csound-6.10.0/000077500000000000000000000000001321653344700131015ustar00rootroot00000000000000csound-6.10.0/.editorconfig000066400000000000000000000003071321653344700155560ustar00rootroot00000000000000root = true [*] insert_final_newline = true trim_trailing_whitespace = true end_of_line = lf indent_style = space indent_size = 4 #[*.{py,h,hh,hpp,c,cc,cpp}] #indent_style = space #indent_size = 4 csound-6.10.0/.gitignore000066400000000000000000000054011321653344700150710ustar00rootroot00000000000000# Intermediate object files *.o *.os *.so # Opcode libraries /lib*.* /tclcsound.* /csladspa.* # Final library /libcsound* # SCons cache and log /.scon* /config.log # Bison & Flex output /Engine/csound_orclex.c /Engine/csound_orcparse.[hc] /Engine/csound_orcparse.output /Engine/csound_prelex.c # gettext output files are all placed in subdirs /po/*/ # Output executables atsa atsa.exe cs cs.exe csb64enc csb64enc.exe csbeats csbeats.exe csound csound.exe cstclsh cstclsh.exe cswish cswish.exe cvanal cvanal.exe dnoise dnoise.exe envext envext.exe extract extract.exe extractor extractor.exe het_export het_export.exe het_import het_import.exe hetro hetro.exe lpanal lpanal.exe lpc_export lpc_export.exe lpc_import lpc_import.exe mkdb mkdb.exe makecsd makecsd.exe mixer mixer.exe pv_export pv_export.exe pv_import pv_import.exe pvanal pvanal.exe pvlook pvlook.exe scale scale.exe scot scot.exe scsort scsort.exe sdif2ad sdif2ad.exe sndinfo sndinfo.exe srconv srconv.exe winsound winsound.exe # PD external /csoundapi*.* # C++ lib /libcsnd* # Python wrappers csnd.py csnd.pyc _csnd.so # CsoundAC /libCsoundAC* CsoundAC.py csladspa.so # SWIG Wrappers *_wrap.cc *_wrap.h interfaces/*.java csnd.jar *.class #Loris anf Perry's stuff Opcodes/Loris/* loris.py Opcodes/stk/*/ # Vim swap files *.swp ## backups *~ ## Others TAGS po/old_* *.wav ##Release_Notes/* .DS_Store /CsoundLib64* examples/java/CSDPlayer.jar examples/java/CsoundEditor.jar ## Build scripts build buildD ## Installer Resources installer/macosx/DmgResources installer/macosx/201* ## Generated Doxygen doc/html doc/doxygen #Generated files if running in-source CMake build cmake_install.cmake CMakeFiles/ Makefile cmake_install.cmake /cmake_uninstall.cmake CTestTestfile.cmake /CMakeCache.txt /interfaces/*wrap.cxx .dylib /csound_orclex.c /csound_orcparse.c /csound_orcparse.h /csound_orcparse.output /csound_prelex.c /frontends/beats.tab.c /frontends/beats.tab.h /frontends/beatslex.yy.c /tests/c/*Test *.swo results.txt *.pyc Custom.cmake Engine/.csound_orc.l.swn Engine/.csound_orc.y.swn *.swm android/CSDPlayer/assets/samples/README android/CSDPlayer/assets/samples/hrtf-44100-left.dat android/CSDPlayer/assets/samples/hrtf-44100-right.dat android/CSDPlayer/assets/samples/hrtf-48000-left.dat android/CSDPlayer/assets/samples/hrtf-48000-right.dat android/CSDPlayer/assets/samples/hrtf-96000-left.dat android/CSDPlayer/assets/samples/hrtf-96000-right.dat android/CSDPlayer/assets/samples/sf_GMbank.sf2 nacl/csound_orclex.c nacl/csound_orcparse.c nacl/csound_orcparse.h nacl/csound_prelex.c nacl/pnacl # Xcode xcshareddata/ *.xcuserstate *.xccheckout project.xcworkspace/ xcuserdata/ emscripten/examples/javascripts/CsoundObj.js emscripten/examples/javascripts/libcsound.js *.bz2 tests/soak/CheckSums tests/soak/Output Opcodes/stk/ csound-6.10.0/.travis.yml000066400000000000000000000036161321653344700152200ustar00rootroot00000000000000language: cpp compiler: - gcc # - clang sudo: false dist: trusty env: global: - secure: "pOICMBtfwljj450Vht1D2/XvtUm07edkbiUI0+PCnfuwiwBFJyqY919whZu+CrplQvkVS+RzvxT3wpgkVccflo0uvNJ7NwfKksRqrUKwTp59nGIwjUsnDjI3YkxOQyxIdIPsSm3bUxXVy/Jge0v6vzvbbPXKxyAxKsupnUBYOwM=" - OMP_NUM_THREADS=4 - VERBOSE=1 before_script: - mkdir -p build script: - "[ ${COVERITY_SCAN_BRANCH} == 1 ] || (cd $TRAVIS_BUILD_DIR/build && cmake .. -DBUILD_STATIC_LIBRARY=ON -DBUILD_TESTS=ON && make && make test && make regression && make csdtests)" ### addons: coverity_scan: project: name: "csound/csound" description: "A user-programmable and user-extensible sound processing language and software synthesizer" notification_email: CSOUND-DEV@listserv.heanet.ie build_command_prepend: "mkdir -p $TRAVIS_BUILD_DIR/build && cd $TRAVIS_BUILD_DIR/build && cmake .." build_command: "make -C $TRAVIS_BUILD_DIR/build" branch_pattern: coverity_scan apt: packages: - cmake - libsndfile1-dev - libasound2-dev - libjack-dev - portaudio19-dev - libportmidi-dev - libpulse-dev - swig - liblua5.1-0-dev - python-dev - puredata-dev - default-jdk - libfltk1.1-dev - libfluidsynth-dev - liblo-dev - fluid - ladspa-sdk - libpng-dev - dssi-dev - libstk0-dev - libgmm++-dev - bison - flex - libportsmf-dev - libeigen3-dev - libcunit1-dev - python-tk notifications: email: recipients: - CSOUND-DEV@listserv.heanet.ie csound-6.10.0/AUTHORS000066400000000000000000000034351321653344700141560ustar00rootroot00000000000000Csound is the product of many people. Csound was originally developed by Barry L. Vercoe of the Music and Cognition Group at the Media Laboratory, M.I.T., Cambridge, MA, USA with partial support from the System Development Foundation and from the National Science Foundation Grant #IRI-8704665. Most of the Csound code has been modified, developed, documented and extended by an independent group of programmers, composers, and scientists. These contributors include David Akbari Nicola Bernardini Mike Berry Fabio Bertolotti Stefan Bilbao David Boothe Richard Boulanger Oeyvind Brandtsegg Eli Breder Phil Burk Andrés Cabrera Brian Carty Michael Casey Corbin Champion Amar Chaudhary Michael Clark Nick Collins Kevin Conder Perry Cook Sean Costello Erik de Castro Lopo Alan deLespinasse Oscar Pablo Di Liscia Richard Dobson Mark Dolson Rasmus Ekman Dan Ellis Tom Erbe Georg Essl John ffitch Kelly Fitz Richard Furse Bill Gardner Matt Gerassimoff Matt Gilliard Michael Gogins Jens Groh Samuel Groner Keith Henderson Torgeir Strand Henriksen Matt Ingalls Thom Johansen Richard Karpen Sami Khoury Anthony Kozar Clemens Ladisch Paul Lansky Victor Lazzarini Allan Lee David McIntyre Dave Madole Gabriel Maldonado Cesare Marilungo Max Mathews Makoto Matsumoto Hans Mikelson Pete Moss Peter Neubäcker Takuji Nishimura Peter Nix Alex Norman Juan Pampin Dave Philips Maurizio Umberto Puxeddu Davide Rocchesso Jean Piché Ville Pulkki John Ramsdell Marc Resibois Sigurd Saue Simon Schampijer Rob Shaw Paris Smaragdis Erik Spjut Dmitriy Startsev Greg Sullivan Tom Sullivan Istvan Varga Bill Verplank Jezar Wakefield (?) Rory Walsh Robin Whittle Christopher Wilson Trevor Wishart Matt Wright Steven Yi There may be others whose names have been inadvertantly omitted. If so, many apologies. Please report any missing names. csound-6.10.0/BUILD.md000066400000000000000000000510721321653344700142670ustar00rootroot00000000000000Csound Build Instructions ========================= Build instructions for building Csound from the source packages for the following operating systems - [Debian/Ubuntu Linux](#debian) - [Mac OS X using Homebrew](#OSXHomebrew) - [General Instructions for Linux without Root access](#generalLinux) - [Raspberry PI standard OS](#raspian) - [Fedora 18](#fedora) - [Windows 32/64 bit using MYSYS (recommended)](#msys2) - [Windows (Mingw32)](#mingw32) - [Windows Visual Studio](#msvs) - [Android](#android) Instructions for RPI compiled by Dominic Melville contact via dcamelville at gmail.com for amendments and updates Debian/Ubuntu -------------- The following instructions will explain how to configure, compile, and install Csound 6 on Debian and Ubuntu systems. ### Requirements You will need root access, primarily to allow installation of dependencies required for building Csound, as well as for installing into /usr/local. ### Building Csound 6 The following instructions are written for those getting a copy of the source code from Git. You will need to adjust the steps accordingly when using the source tarball from the files section. The first thing to do is make sure you have all of the required dependencies for building Csound. In a terminal, do the following: 1. Edit, as root, `/etc/apt/sources.list` and ensure that each line beginning with `deb` has another line below it that is identical except that `deb` is replaced with `deb-src`. Then run `sudo apt-get update`. 1. `sudo apt-get build-dep csound` 2. `sudo apt-get install cmake` 3. `sudo apt-get install git ` The following numbered steps are to be done in a terminal for building and installing Csound: 1. `cd ~ ` 2. `mkdir csound` 3. `cd csound` 4. `git clone https://github.com/csound/csound.git csound` 5. `mkdir cs6make ` 6. `cd cs6make ` 7. `cmake ../csound` 8. `make -j6 ` 9. `sudo make install ` 10. `sudo ldconfig ` At this point, Csound 6 should now be compiled and installed into the /usr/local set of folders. Mac OS X using Homebrew ----------------------- ### Introduction Homebrew is a package manager for OSX. It is able to download, build, and install applications, including their dependencies. The following sections will describe what you will need to do to use Homebrew to install Csound 6. Note: At this time, this method of installing Csound is currently being tested. It is considered beta, and users should be aware that there may be some issues that will be required to be worked through. ### Requirements - Xcode - Xcode Command-Line Tools - Homebrew - [http://www.brew.sh][2] [2]: Installing Homebrew You will first need to have a working Homebrew setup. This requires installing Xcode and the Xcode Command-Line tools. More information on installing Homebrew is available on the Homebrew website as well as their wiki. In particular, you will need to be mindful to enable user read/write for three directories: "/usr/local", "/Library/Python/2.7/site-packages", and "/Library/Java/Extensions". These need to be writable by the user as Csound will need to install packages into each of those folders. Running the following commands at a Terminal prompt should allow you to do this: `sudo chmod +a 'user:YOUR_NAME_HERE allow add_subdirectory,add_file,delete_child,directory_inherit' /Library/Python/2.7/site-packages ` `sudo chmod +a 'user:YOUR_NAME_HERE allow add_subdirectory,add_file,delete_child,directory_inherit' /Library/Java/Extensions ` where YOUR_NAME_HERE refers to your system username. ### Adding the Csound Tap Homebrew has a central repository, but it also allows for adding "taps", which are additional repositories. A Csound tap has been setup at https://github.com/kunstmusik/homebrew-csound. You can tap into it by using the following command: `brew tap kunstmusik/csound` ### Installing Csound Once Homebrew is setup and the csound tap has been tapped, run the following command at the commandline to install Csound: `brew install --HEAD csound ` ### Known Issues There is currently a warning issued when Csound installs: `Warning: Could not fix CsoundLib64.framework/Versions/6.0/CsoundLib64 in /usr/local/Cellar/csound/HEAD/bin/srconv ` `Warning: Could not fix CsoundLib64.framework/Versions/6.0/CsoundLib64 in /usr/local/Cellar/csound/HEAD/bin/sndinfo ` `Warning: Could not fix CsoundLib64.framework/Versions/6.0/CsoundLib64 in /usr/local/Cellar/csound/HEAD/bin/scsort ` `Warning: Could not fix CsoundLib64.framework/Versions/6.0/CsoundLib64 in /usr/local/Cellar/csound/HEAD/bin/scope ` .... This is due to how the CsoundLib64.framework is installed into ~/Library/Frameworks and bypasses Homebrew's installation path for Frameworks. This is a known issue and will be looked into. General Linux without Root access --------------------------------- These are generic instructions to build on any Linux system with no root access. These instructions require a full development system (compilers, flex, bison, cmake). For RT audio you need to make sure you have the alsa headers / lib installed. ### 1) set up your local directory This creates three directories in your HOME directory and adds your local lib directory to dynamic library path. Note that this last step needs to be performed every time you open a new terminal, otherwise the installed Csound will not find its dynamic library dependencies. If you add that line to your HOME/.profile script, it will be run automatically when you start a new terminal. $ $ - `cd ` - `mkdir include ` - `mkdir lib ` - `mkdir bin ` - `mkdir src` - `export LD_LIBRARY_PATH=$HOME/lib:LD_LIBRARY_PATH ` (this last command can be added to your $HOME/.profile file for convenience) ### 2) get and install libsndfile Libsndfile is the only required dependency for a basic Csound build. Ubuntu users: it appears the libsndfile binaries come as default in your installation, so this step might not be required. However, there is no harm in doing it. - `cd src ` - `wget http://www.mega-nerd.com/libsndfile/files/libsndfile-1.0.25.tar.gz ` - `tar xf libsndfile-1.0.25.tar.gz` - `cd libsndfile-1.0.25 ` - `./configure --prefix=$HOME` - `make install ` ### 3) get Csound (latest from git) The latest Csound sources are kept in the develop branch. For the latest released sources, you do not need to change branches. - `cd ..` - `git clone https://github.com/csound/csound.git csound ` - `cd csound` - `git checkout develop` - `mv Custom.cmake.ex Custom.cmake ` ### 4) set the include path for the build Cmake needs to find your locally-installed headers in HOME/bin. You can add custom commands to Cmake by using a Custom.cmake file, which Cmake will read if it exists. Open or create the Custom.cmake file in the top level Csound sources directory and add the following line: `include_directories("ENV{HOME}/include") ` ### 5) build and install Csound The recommended method is to create a separate build directory and run cmake there. - `mkdir build` - `cd build ` - `cmake -DCMAKE_INSTALL_PREFIX=$HOME ..` - `make install ` ### Notes This builds a basic system. If you add dependencies to your HOME directories, then you can run make again to build them. The csound command-line frontend will be installed in $HOME/bin, the libraries in $HOME/lib and the include files in $HOME/include. The plugin dir is in $HOME/lib/csound/plugins64-6.0. ### Dependencies List If the dependency you are adding uses ./configure, you can use the same parameters to it as explained in step 2. If it uses cmake, you can use the same parameters as in step 5. After adding dependencies to your $HOME directories, you can run cmake again to re-build Csound. Check the printed output to see if the added dependency has switched on the build of the desired component. #### OSC opcodes liblo - http://liblo.sourceforge.net/ NB: the build for version 0.28 seems to be broken. #### Fluid opcodes Fluidsynth - http://sourceforge.net/apps/trac/fluidsynth/ NB: cmake might need to be coerced into finding the fluidsynth headers once it is built. For that, you can use the following cmake command (see step 5): cmake -DCMAKE_INSTALL_PREFIX=$HOME -DFLUIDSYNTH_H=$HOME/include .. #### Widget opcodes FLTK - http://www.fltk.org/index.php NB: make sure you configure the FLTK build with --enable-shared, otherwise there could be problems linking to libfltk on 64bit linux. #### Faust opcodes libfaust - use faust2 branch of Faust git sources: $ git clone git://git.code.sf.net/p/faudiostream/code faust $ cd faust $ git checkout faust2 NB: libfaust also requires LLVM 3.0, 3.1, 3.2, 3.3 or 3.4 - http://llvm.org/ LLVM can be built with CMake (as in step 5 above). To build faust, use the following make command (replacing LLVM_32 for LLVM_3* depending on the version you are using, if it is not 3.2) $ make LLVM_VERSION=LLVM_32 LLVM_CONFIG=llvm-config LLVM_CLANG=g++ CXX=g++ ARCHFLAGS=-fPIC To install it, you should run $make PREFIX=$HOME To switch the faust opcodes build on and coerce cmake into finding the faust library use: cmake -DCMAKE_INSTALL_PREFIX=$HOME -DBUILD_FAUST_OPCODES=1 -DFAUST_LIBRARY=$HOME/lib/faust/libfaust.a .. NB: Ubuntu users should be aware that LLVM 3.4 and 3.5 packages seem broken. It is probably recommended to build LLVM by oneself. Otherwise, LLVM 3.3 package is enough for building csound 6.05 with Faust opcodes assuming that - LLVMConfig.cmake is correctly spelled in /usr/share/llvm-3.3/cmake (otherwise create a symbolic link with that name : ln -s /usr/share/llvm-3.3/cmake/LLVM-Config.cmake /usr/share/llvm-3.3/cmake/LLVMConfig.cmake) - llvm-config is correctly spelled in /usr/bin - faust2 is built with LLVM 3.3 - cmake version > 2.8.7 (version 3.3.0 builds easily for instance) Then some additional environment variables may have to be set during the configuration step: cmake -DLLVM_DIR=/usr/share/llvm-3.3/cmake -DCMAKE_MODULE_LINKER_FLAGS="-L/usr/lib/llvm-3.3/lib" -DBUILD_FAUST_OPCODES=1 -DFAUST_LIBRARY=pathTo/libfaust.a ../csound-develop/ #### Portaudio module portaudio - http://www.portaudio.com/ #### Portmidi module portmidi - http://portmedia.sourceforge.net/portmidi/ #### JACK module Jack connection kit - http://jackaudio.org/ #### Python bindings swig - http://www.swig.org/ Python headers / library - http://www.python.org #### Java bindings swig - http://www.swig.org/ Java SDK - http://www.oracle.com/technetwork/java/javase/downloads/index.html Raspberry Pi Standard Distro ----------------------------- ### (Raspian Wheezy) Preliminary step: `sudo apt-get build-dep csound ` If you get the following error: `E: You must put some 'source' URIs in your sources.list ` then add the following line to /etc/apt/sources.list: `deb-src http://mirrordirector.raspbian.org/raspbian/ wheezy main contrib non-free rpi ` (This can be done with nano) After adding that to the sources.list, you should run `sudo apt-get update ` and retry the `sudo apt-get build-dep csound` command. 1. `cd ~ ` 2. `mkdir csound` 3. `cd csound` 4. `git clone https://github.com/csound/csound.git csound` 5. `mkdir cs6make` 6. `cd cs6make` 7. `cmake ../csound -DBUILD_CSOUND_AC=OFF -DCMAKE_BUILD_TYPE="Release"` (this will not build CsoundAC, that gives errors) 8. `make -j6` 9. `sudo make install` 10. `sudo ldconfig ` If you want to use the csnd6 Python library, add the following line to .bashrc: `export PYTHONPATH=/usr/local/lib` Enabling the Python Bindings requires swig and python-dev packages to be installed with `sudo apt-get install swig python-dev` ### NEON support for PFFFT lib From 6.07, Csound includes a choice of FFT libraries. One of these is PFFFT, which can avail of NEON vector operations on arm, where these exist. This can lead to a compilation error if the correct options are not set. If a build error occurs in the compilation of pffft.c, two options exist. 1. Try to add the correct flags for NEON compilation. This can be made by editing the top-level file Custom.cmake.ex, and saving it as Custom.cmake. In that file, the line set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -W -Wall -mtune=core2") should be changed to set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfloat-abi=hard -mfpu=neon") 2. If step 1 fails, there might be no NEON support for your arm chip, in which case, you need to change the line above to set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPFFFT_SIMD_DISABLE") in order to disable the vectorial code and use standard C scalar operations. Fedora 18 --------- ### Introduction This shows how to download the source code from Sourceforge, and build Csound 6 from sources. ### Requirements For some steps, you'll need root access. You may need to install additional packages - the example shows installing a number of additional packages, but the exact requirements depend on your system. You'll need to make sure Cmake, flex, bison, and libsndfile are installed. If you're logged in as a non-root user, you can execute root commands using su -c. So here's how to make sure the basic required packages for building are installed: `su -c "yum install cmake libsndfile libsndfile-devel flex bison" ` You'll be prompted for your root password. ### Downloading Download the latest Csound 6 sources from [https://sourceforge.net/projects/csound/files/csound6/ ][3] [3]: At the time this was written, the downloaded file was Csound6.00.1.tar.gz ### Compiling First uncompress and untar the source code: `gunzip Csound6.00.1.tar.gz ` `tar xf Csound6.00.1.tar.gz ` Change into the source directory `cd Csound6.00.1` In the source directory what gets compiled is controlled by the file CMakeLists.txt. By default lots of stuff will get built, as long as you have the required dependencies installed. The following commands will add most required packages (but note that lua interfaces and faust opcodes may still not work): `su - ` `yum install ladspa ladspa-devel ` `yum install fluidsynth fluidsynth-devel ` `yum install boost boost-devel java-devel ` `yum install jack-audio-connection-kit-devel ` `yum install fltk fltk-devel ` `yum install swig swig-devel ` `yum install pulseaudio-libs-devel ` `yum install portaudio portmidi portaudio-devel portmidi-devel ` `yum install fltk-fluid ` `yum install stk stk-devel ` `yum install python-libs ` `yum install python-devel ` `yum install liblo liblo-devel ` `yum install lua lua-devel ` `yum install eigen3-devel eigen3 ` `yum install gmm-devel ` `yum install wiiuse wiiuse-devel ` `yum install bluez-libs-devel ` yum install llvm-devel `yum install faust faust-tools` `exit ` The building process takes two steps 1. use cmake to create a Makefile 2. use make to build Csound 6 To create the Makefile: `cmake ./ ` At this point you may see messages saying that something can't be built - in that case use your skill and judgement to work out which packages are missing. For instance if you get a message saying fltk cannot be built, you could install the fltk-devel package. If you install a new package, you'll need to run cmake again: `rm CMakeCache.txt ` `cmake ./ ` When you're happy, run make `make ` This builds the csound library. ### Installing By default, Csound 6 will install in /usr/local, so you'll need root permissions: `su -c "make install" ` Finally you need to make sure the library can be found by the linker `su - ` `cd /etc/ld.so.conf.d ` `touch csound6.conf ` `gedit csound6.conf ` In the editor, add one line `/usr/local/lib ` and close the file. Finally update the linker search path `ldconfig ` and log out of root `exit ` Testing As a basic test, just try typing csound at a command prompt, and you should get the help message. Windows 32/64 Bit (msys2) --------------- Csound for Windows can now be built using MSYS2. This is the recommeneded way to build Csound for Windows. Please follow the instruction posted [here](https://github.com/csound/csound/tree/develop/mingw64). Windows 32 Bit (mingw32) --------------- A basic working knowledge of the Windows command prompt is assumed. Further instructions for Windows can be found in their own document at the following link [Csound Windows Build Doc][1] [1]: ### Steps (Vanilla build) 1. Download and install MSYS (http://downloads.sourceforge.net/mingw/MSYS-1.0.11.exe) 2. Download and install MinGW (http://sourceforge.net/projects/mingwbuilds). -When installing choose architecture i686, or x32. 3. Download and install Git(http://git-scm.com/download/win) 4. Download and install libsndfile (32bit) (http://www.mega-nerd.com/libsndfile/) 5. Download and install cmake (http://www.cmake.org/download/) Open the Windows command prompt and cd to a folder you wish to create your Csound repository in. Then run: `git clone https://github.com/csound/csound.git` `cd csound` `mkdir build` `cd build` Then run cmake-gui from the command line: `cmake-gui` To the right of 'Where is the source code:' in cmake-gui browse for the Csound source directory. Underneath it, at the "Where to build the binaries" select the newly created build directory. Now type sndfile into the search field and you should see a few cmake entries concerned with libsndfile. Browse for the correct include folder and library file; libsndfile-1.dll. With this done hit configure. At this point you may be greeted with a cmake-gui dialogue asking which generator to use. Select the "MinGW Makefiles" generator. If the configuration command fails you may need to set the CMAKE_C_COMPILER and CMAKE_CXX_COMPILER entries. Simply click the add entry button and add two new FILEPATH entries, CMAKE_C_COMPILER should point towards your installed gcc.exe, and CMAKE_CXX_COMPILER should point towards g++.exe. These files are found in your MinGW/bin directory. Go back to the command prompt and from your build directory run: `mingw32-make` If everything went Ok, you will now have binaries for most vanilla build of Csound possible. Keep reading if you wish to extend this basic build. ### Steps (adding realtime audio and MIDI) 1. Download portaudio (http://portaudio.com/). 2. Open MSYS shell and cd to portaudio directory. Then run 3. './configure' 4. 'make' If you wish to build with support for ASIO run the following command, replacing the path to your ASIO SDK with your own. './configure --with-host_os=mingw --with-winapi=asio [--with-asiodir=/usr/local/asiosdk2]' 'make' If make has any problems, you can try adding the following directories to your ASIOSDK folders: ASIOSDK2.3\host\pc\.libs C:\SDKs\ASIOSDK2.3\host\.libs ASIOSDK2.3\common\.libs 5. Download and portmidi (http://portmedia.sourceforge.net.), Open command prompt and cd to portmidi directory 6. `mkdir build` 7. `cd build` 8. `cmake ../ -G "Mingw Makefiles"` 9. `mingw32-make` 9. Open up cmake once more and make sure the Csound cmake configuration is open. Then search for entries with portaudio and portmidi in them. Browse for the correct include directories for each, and select the libportaudio-2.dll, and libportmidi.dll libraries. Then run configure and generate. 10. Open the command prompt and cd to the Csound build directory. Then run `mingw32-make` Download and install cmake Run cmake from the csound dir and configure Csound to build using MinGW Makefiles. For this minimal you'll need to disable quite a few features. Run generate. cd to csound build directory and run mingw32-make Windows Visual Studio -------------- Instructions can be found [here](https://github.com/csound/csound/blob/develop/msvc). Android -------------- Requirements 1. SWIG (www.swig.org) 2. libsndfile sources for android (https://bitbucket.org/kunstmusik/libsndfile-android.git) 3. boost (www.boost.org) 4. Android NDK ### Steps 1. Download, build and install SWIG (or install from your distro package system) 2. Clone the libsndfile sources for android repo,e.g.: $ cd $HOME $ mkdir android $ cd android $ git clone https://bitbucket.org/kunstmusik/libsndfile-android.git 3. Set the ANDROID_NDK_MODULE variable to point to the top directory where the libsndfile sources are located,e.g. $ export ANDROID_NDK_MODULE=$HOME/android 4. Download boost and install (headers only) in your include path (e.g. /usr/local/include). There is no need to build the library. 5. Download the Android NDK and place it somewhere (e.g. $HOME), set the ANDROID_NDK_ROOT to point to it $ export ANDROID_NDK_ROOT=$HOME 5. Get Csound, and go to the ./android/CsoundAndroid directory, run $ sh build.sh The Java files and NDK libraries will be under CsoundAndroid. csound-6.10.0/BUILDING_FOR_ANDROID000066400000000000000000000036301321653344700160710ustar00rootroot00000000000000BUILDING FOR ANDROID Csound 6 now builds and runs on Android ABI 9 or later for the ARM-v7 architecture (hard floating point). The build is complex but perhaps not as complex as one might think. Most of the code is C or C++, only some of the code is Java, so mostly the Android Native Development Kit (NDK) must be used, as well of course as the Android Software Development Toolkit (SDK) for Java. To save build time, third-party dependencies are pre-built and installed as part of the Android toolchain. This includes for example the fluidsynth shared library and LuaJIT. The third-party source code must go into a directory pointed to by NDK_MODULE_PATH. NOTE: this MUST be on the same hard disk as the Csound sources. Otherwise your regular Csound build environment can be used after setting the appropriate NDK environment variables. Do not use the 'build.sh' helpers, use $NDK/ndk-build to build and install the shared libraries (modules), the environment variables will do the job of 'build.sh'. There is one exception to this... The following variables must be set (this is an example from my environment): echo "Configure for Android/ARM, armeabi-v7a (ARMv7 VFP), Android 4.0+ (ICS)..." export SDK=/d/Android/adt-bundle-windows-x86-20130514/sdk export NDK=/d/Android/android-ndk-r8e export ANDROID_NDK_ROOT=$NDK export NDK_MODULE_PATH=/c/ndk-modules export PATH=${PATH}:$NDK_MODULE_PATH export CSOUND_SRC_ROOT=/c/Users/new/csound-csound6-git # First Android with decent audio. export NDKABI=9 export NDKVER=$NDK/toolchains/arm-linux-androideabi-4.7 export NDKP=$NDKVER/prebuilt/windows/bin/arm-linux-androideabi- export NDKF="--sysroot $NDK/platforms/android-$NDKABI/arch-arm" export NDKARCH="-march=armv7-a -mfloat-abi=softfp -Wl,--fix-cortex-a8" Obviously all of these variables must be consistent for all components of Csound for Android. Download xxx from SourceForge. Unzip each archive into xxx. csound-6.10.0/Bela/000077500000000000000000000000001321653344700137445ustar00rootroot00000000000000csound-6.10.0/Bela/CsoundBela.cpp000066400000000000000000000043311321653344700164700ustar00rootroot00000000000000#include #include #include #define BLOCKS 8 struct csData{ Csound *csound; CsoundPerformanceThread *thread; void *cbuff; int blocksize; int count; int read; MYFLT *buffer; MYFLT scal; }; csData* gCsData; void cback(void *p){ csData* pp = (csData *) p; if(pp->thread->GetStatus() == 0) csoundWriteCircularBuffer(csound, pp->cbuff, (void *) csoundGetSpout(csound), pp->blocksize); } bool setup(BelaContext *context, void *userData) { gCsData = new csData; Csound *csound = new Csound(); csound->Compile("trapped.csd","-+rtaudio=null", "--realtime"); gCsData->blocksize = csound->GetNchnls()*csound->GetKsmps(); gCsData->cbuff = csoundCreateCircularBuffer(csound->GetCsound(), gCsData->blocksize*BLOCKS, sizeof(MYFLT)); gCsData->thread = new CsoundPerformanceThread(csound->GetCsound()); gCsData->thread->SetProcessCallback(cback,gCsData); gCsData->csound = csound; gCsData->count = 0; gCsData->read = 0; gCsData->scal = userData->csound->Get0dBFS(); gCsData->buffer = new MYFLT[gCsData->blocksize]; gCsData->thread->Play(); //userData = data; return true; } void render(BelaContext *context, void *Data) { int n,i,j,blocksize,read; csData *userData = gCsData; MYFLT *buffer = userData->buffer; MYFLT scal = userData->scal; j = userData->count; read = userData->read; blocksize = userData->blocksize; for(n = 0; n < context->audioFrames; n++){ for(i = 0; i < context->audioOutChannels; i++){ if(j >= read) { read = csoundReadCircularBuffer(NULL, userData->cbuff, buffer, blocksize); j = 0; } if(read > 0) audioWrite(context,n,i,(float)buffer[j++]/scal); } } userData->count = j; userData->read = read; } void cleanup(BelaContext *context, void *Data) { csData *userData = gCsData; gCsData->thread->Stop(); gCsData->thread->Join(); csoundDestroyCircularBuffer(gCsData->csound->GetCsound(), gCsData->cbuff); delete userData->csound; delete userData->thread; delete[] userData->buffer; delete userData; } csound-6.10.0/CMakeLists.txt000066400000000000000000001157571321653344700156610ustar00rootroot00000000000000cmake_minimum_required(VERSION 2.8.12) project(Csound) ENABLE_TESTING() if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") set(CMAKE_COMPILER_IS_CLANG 1) endif() message(STATUS "${CMAKE_HOME_DIRECTORY}") if(NOT MSVC AND NOT WASM) set(CMAKE_CXX_FLAGS_RELEASE "-O3 ") set(CMAKE_C_FLAGS_RELEASE "-O3 ") endif() # Project definitions set(APIVERSION "6.0") # Relative install paths set(EXECUTABLE_INSTALL_DIR "bin") set(LOCALE_INSTALL_DIR "share/locale") set(HEADER_INSTALL_DIR "include/csound") set(CS_FRAMEWORK_DEST "~/Library/Frameworks") include(TestBigEndian) include(CheckFunctionExists) include(CheckIncludeFile) include(CheckIncludeFileCXX) include(CheckLibraryExists) include(CMakeParseArguments) include(CheckCCompilerFlag) include(CheckCXXCompilerFlag) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") # Utility to munge with items in a list. # macro(LIST_REPLACE LIST INDEX NEWVALUE) list(INSERT ${LIST} ${INDEX} ${NEWVALUE}) MATH(EXPR __INDEX "${INDEX} + 1") list (REMOVE_AT ${LIST} ${__INDEX}) endmacro(LIST_REPLACE) # Utility function to make executables. All plugin targets should use this as it # sets up output directory set in top-level CmakeLists.txt # and adds an appropriate install target # # name - name of executable to produce # srcs - list of src files # libs - list of library files to link to # output_name (OPTIONAL) - overide the name of the generated executable # function(make_executable name srcs libs) add_executable(${name} ${srcs}) target_link_libraries (${name} ${libs}) set_target_properties(${name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${BUILD_BIN_DIR}) if(${ARGC} EQUAL 4) set_target_properties(${name} PROPERTIES OUTPUT_NAME ${ARGV3}) endif() install(TARGETS ${name} RUNTIME DESTINATION "${EXECUTABLE_INSTALL_DIR}" ) endfunction(make_executable) # Utility function to make a utility executable # # name - name of executable to produce # srcs - list of src files function(make_utility name srcs) make_executable(${name} "${srcs}" "${CSOUNDLIB}") add_dependencies(${name} ${CSOUNDLIB}) if(LINUX) target_link_libraries(${name} m) endif() endfunction() # Checks if dependencies for an enabled target are fulfilled. # If FAIL_MISSING is true and the dependencies are not fulfilled, # it will abort the cmake run. # If FAIL_MISSING is false, it will set the option to OFF. # If the target is not enabled, it will do nothing. # example: check_deps(BUILD_NEW_PARSER FLEX_EXECUTABLE BISON_EXECUTABLE) function(check_deps option) if(${option}) set(i 1) while( ${i} LESS ${ARGC} ) set(dep ${ARGV${i}}) if(NOT ${dep}) if(FAIL_MISSING) message(FATAL_ERROR "${option} is enabled, but ${dep}=\"${${dep}}\"") else() message(STATUS "${dep}=\"${${dep}}\", so disabling ${option}") set(${option} OFF PARENT_SCOPE) # Set it in the local scope too set(${option} OFF) endif() endif() math(EXPR i "${i}+1") endwhile() endif() if(${option}) message(STATUS "${option} is enabled.") else() message(STATUS "${option} is disabled.") endif() endfunction(check_deps) ### COMPILER OPTIMIZATION FLAGS option(USE_COMPILER_OPTIMIZATIONS "Use the default Csound compiler optimization flags" ON) if(USE_COMPILER_OPTIMIZATIONS) include(cmake/CompilerOptimizations.cmake) endif() if(APPLE) set(OSX_VERSION " ") endif() ## USER OPTIONS ## # Optional targets, they should all default to ON (check_deps will disable them if not possible to build) option(USE_DOUBLE "Set to use double-precision floating point for audio samples." ON) option(BUILD_UTILITIES "Build stand-alone executables for utilities that can also be used with -U" ON) option(NEW_PARSER_DEBUG "Enable tracing of new parser" OFF) option(BUILD_MULTI_CORE "Enable building for multicore system (requires BUILD_NEW_PARSER)" ON) option(FAIL_MISSING "Fail when a required external dependency is not present (useful for packagers)" OFF) option(USE_GETTEXT "Use the Gettext internationalization library" ON) option(BUILD_STATIC_LIBRARY "Also build a static version of the csound library" OFF) option(USE_LRINT "Use lrint/lrintf for converting floating point values to integers." ON) option(USE_CURL "Use CURL library" ON) option(BUILD_RELEASE "Build for release" ON) option(BUILD_INSTALLER "Build installer" OFF) option(BUILD_TESTS "Build tests" ON) option(USE_GIT_COMMIT "Show the git commit in version information" ON) option(REQUIRE_PTHREADS "For non-Windows systems, set whether Csound will use threads or not" ON) # Include this after the install path definitions so we can override them here. # Also after function definitions so we can use them there # Also after user options so that the default values don't overwrite the custom files values find_file(CUSTOM_CMAKE "Custom.cmake" HINTS ${CMAKE_HOME_DIRECTORY}) if(CUSTOM_CMAKE) message(STATUS "Including Custom.cmake file: ${CUSTOM_CMAKE}") include(${CUSTOM_CMAKE}) else() message(STATUS "Not using Custom.cmake file.") endif() option(USE_LIB64 "Set to on to set installation directory for libraries to lib64" OFF) if(USE_LIB64) set(LIBRARY_INSTALL_DIR "lib64") add_definitions("-DLIB64") else() set(LIBRARY_INSTALL_DIR "lib") endif() message(STATUS "LIBRARY INSTALL DIR: ${LIBRARY_INSTALL_DIR}") if(USE_DOUBLE) message(STATUS "Building with 64-bit floats") set(PLUGIN_INSTALL_DIR "${LIBRARY_INSTALL_DIR}/csound/plugins64-${APIVERSION}") else() message(STATUS "Building with 32-bit floats") set(PLUGIN_INSTALL_DIR "${LIBRARY_INSTALL_DIR}/csound/plugins-${APIVERSION}") endif() execute_process ( COMMAND python -c "import site, sys; sys.stdout.write(site.getusersitepackages())" OUTPUT_VARIABLE PYTHON_USER_SITE_PACKAGES ) SET(PYTHON_MODULE_INSTALL_DIR ${PYTHON_USER_SITE_PACKAGES} CACHE PATH "Python module install dir") set(JAVA_MODULE_INSTALL_DIR ${LIBRARY_INSTALL_DIR} CACHE PATH "Java module install dir") set(LUA_MODULE_INSTALL_DIR ${LIBRARY_INSTALL_DIR} CACHE PATH "Lua module install dir") # VL this is breaking CUDA compilation. It's not necessary #if(APPLE) # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -stdlib=libc++") #endif() if(WIN32 AND NOT MSVC) if(EXISTS "C:/MinGW/include") include_directories(C:/MinGW/include) else() MESSAGE(STATUS "MinGW include dir not found.") endif() set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--add-stdcall-alias") endif() if(MSVC) include_directories(${PROJECT_SOURCE_DIR}/msvc/include) list(APPEND CMAKE_REQUIRED_INCLUDES "${PROJECT_SOURCE_DIR}/msvc/include;${PROJECT_SOURCE_DIR}/msvc/deps/include") endif() if(WIN32) set(CMAKE_SHARED_LIBRARY_PREFIX "") set(CMAKE_SHARED_MODULE_PREFIX "") if(NOT MSVC) set(CSOUND_WINDOWS_LIBRARIES msvcrt advapi32 comctl32 comdlg32 glu32 kernel32 odbc32 odbccp32 ole32 oleaut32 shell32 user32 uuid winmm winspool ws2_32 wsock32 advapi32 comctl32 comdlg32 glu32 msvcrt kernel32 odbc32 odbccp32 ole32 oleaut32 shell32 user32 uuid winmm winspool ws2_32 wsock32) else() if(MSVC_VERSION LESS 1900) set(CSOUND_WINDOWS_LIBRARIES msvcrt advapi32 comctl32 comdlg32 glu32 kernel32 odbc32 odbccp32 ole32 oleaut32 shell32 user32 uuid winmm winspool ws2_32 wsock32 advapi32 comctl32 comdlg32 glu32 msvcrt kernel32 odbc32 odbccp32 ole32 oleaut32 shell32 user32 uuid winmm winspool ws2_32 wsock32) else() set(CSOUND_WINDOWS_LIBRARIES ucrt vcruntime advapi32 comctl32 comdlg32 glu32 kernel32 mincore odbc32 odbccp32 ole32 oleaut32 shell32 user32 uuid winmm winspool ws2_32 wsock32 advapi32 comctl32 comdlg32 glu32 kernel32 odbc32 odbccp32 ole32 oleaut32 shell32 user32 uuid winmm winspool ws2_32 wsock32) endif() endif() if(MSVC) # Experimented with flags but did not make change performance results #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Oi /fp:fast /arch:AVX2") #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Oi /fp:fast /arch:AVX2") #set(CompilerFlags # CMAKE_CXX_FLAGS # CMAKE_CXX_FLAGS_DEBUG # CMAKE_CXX_FLAGS_RELEASE # CMAKE_C_FLAGS # CMAKE_C_FLAGS_DEBUG # CMAKE_C_FLAGS_RELEASE # ) #foreach(CompilerFlag ${CompilerFlags}) # string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}") #endforeach() else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mstackrealign -static-libgcc -static") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mstackrealign -static-libstdc++ -static-libgcc -static") set_target_properties(${CSOUNDLIB} PROPERTIES LINK_FLAGS "-static-libstdc++ -static-libgcc -static") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libstdc++ -static-libgcc -static") endif() endif(WIN32) if(APPLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") set_target_properties(${CSOUNDLIB} PROPERTIES CXX_COMPILE_FLAGS "-std=c++11") endif() if(CMAKE_SYSTEM_NAME MATCHES "Linux") set(LINUX YES) else() set(LINUX NO) endif() set(BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}) check_c_compiler_flag(-fvisibility=hidden HAS_VISIBILITY_HIDDEN) check_cxx_compiler_flag(-fvisibility=hidden HAS_CXX_VISIBILITY_HIDDEN) if (HAS_VISIBILITY_HIDDEN) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden") endif() if (HAS_CXX_VISIBILITY_HIDDEN) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") endif() check_c_compiler_flag(-std=gnu99 HAS_GNU99) if (HAS_GNU99) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99") endif() if (HAS_CXX_VISIBILITY_HIDDEN) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") endif() if(APPLE) if(IOS) message(STATUS "Building for iOS.") else() message(STATUS "Building for OSX") if(BUILD_INSTALLER) set(CS_FRAMEWORK_DEST "${CMAKE_INSTALL_PREFIX}") endif() set(DEFAULT_OSX_SYSROOT /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/) if(NOT CMAKE_OSX_SYSROOT AND EXISTS ${DEFAULT_OSX_SYSROOT}) set(CMAKE_OSX_SYSROOT ${DEFAULT_OSX_SYSROOT}) endif() if(CMAKE_OSX_SYSROOT AND NOT CMAKE_OSX_SYSROOT MATCHES ".*OSX10.6.*") set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7) message(STATUS "OSX: Setting Deployment Target to 10.7") endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DHAVE_VECLIB") if(NOT VECLIB_PATH) set(VECLIB_PATH "/System/Library/Frameworks/") endif() endif() endif() if(USE_DOUBLE) if(APPLE) set(CSOUNDLIB "CsoundLib64") set(PLUGIN_INSTALL_DIR "${CS_FRAMEWORK_DEST}/${CSOUNDLIB}.framework/Versions/${APIVERSION}/Resources/Opcodes64") else() set(CSOUNDLIB "csound64") endif() else() if(APPLE) set(CSOUNDLIB "CsoundLib") set(PLUGIN_INSTALL_DIR "${CS_FRAMEWORK_DEST}/${CSOUNDLIB}.framework/Versions/${APIVERSION}/Resources/Opcodes") else() set(CSOUNDLIB "csound") endif() endif() if(APPLE) if(BUILD_INSTALLER) set(CS_FRAMEWORK_FULL_PATH "/Library/Frameworks/${CSOUNDLIB}.framework/Versions/${APIVERSION}/Resources/Opcodes64") else() get_filename_component(JAVA_MODULE_INSTALL_DIR "~/Library/Java/Extensions" ABSOLUTE) get_filename_component(CS_FRAMEWORK_FULL_PATH ${PLUGIN_INSTALL_DIR} ABSOLUTE) endif() add_definitions("-DCS_DEFAULT_PLUGINDIR=\"${CS_FRAMEWORK_FULL_PATH}\"") endif() if(BUILD_RELEASE) add_definitions("-D_CSOUND_RELEASE_") if(LINUX) set(DEFAULT_OPCODEDIR "${CMAKE_INSTALL_PREFIX}/${PLUGIN_INSTALL_DIR}") add_definitions("-DCS_DEFAULT_PLUGINDIR=\"${DEFAULT_OPCODEDIR}\"") endif() else() add_definitions("-DBETA") endif() if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) add_definitions("-Wno-format") endif() #if(USE_DOUBLE) # set(BUILD_PLUGINS_DIR ${BUILD_DIR}/plugins64) #else() # set(BUILD_PLUGINS_DIR ${BUILD_DIR}/plugins) #endif() set(BUILD_PLUGINS_DIR ${BUILD_DIR}) set(BUILD_BIN_DIR ${BUILD_DIR}) set(BUILD_LIB_DIR ${BUILD_DIR}) #if(APPLE AND NOT ${CMAKE_GENERATOR} STREQUAL "Xcode") # set(BUILD_PLUGINS_DIR ${BUILD_DIR}/${CSOUNDLIB}.framework/Versions/${APIVERSION}/Resources/Opcodes) #endif() message(STATUS "BUILD_BIN_DIR set to ${BUILD_BIN_DIR}.") message(STATUS "BUILD_LIB_DIR set to ${BUILD_LIB_DIR}.") message(STATUS "BUILD_PLUGINS_DIR set to ${BUILD_PLUGINS_DIR}.") # OS specific checks TEST_BIG_ENDIAN(BIG_ENDIAN) ## CONFIGURATION ## SET(BUILD_SHARED_LIBS ON) ## HEADER/LIBRARY/OTHER CHECKS ## # First, required stuff if (MSVC) find_library(LIBSNDFILE_LIBRARY NAMES sndfile libsndfile-1 libsndfile) else() find_library(LIBSNDFILE_LIBRARY sndfile libsndfile-1) endif() if(NOT LIBSNDFILE_LIBRARY) message(FATAL_ERROR "Csound requires the sndfile library") endif() find_package(CURL) set(FLTK_SKIP_OPENGL true) find_package(FLTK ) #if (FLTK_FOUND AND MSVC) # # If "SHARED" variants of FLTK libraries exist, use them. # find_library(FLTK_SHARED_VARIANT "fltk_SHARED") # message(STATUS "FLTK_SHARED_VARIANT:" ${FLTK_SHARED_VARIANT}) # if(FLTK_SHARED_VARIANT) # message(STATUS "Using 'SHARED' variants of FLTK libraries.") # LIST_REPLACE(FLTK_LIBRARIES 0 "fltk_SHARED") # LIST_REPLACE(FLTK_LIBRARIES 1 "fltk_forms_SHARED") # LIST_REPLACE(FLTK_LIBRARIES 2 "fltk_images_SHARED") # endif() #endif() find_package(Java) find_package(JNI) find_package(LIBLO) find_package(LUAJIT) find_package(MUSICXML) find_package(PORTSMF) find_package(PythonLibs 2.7) if(NOT STK_LOCAL) find_package(STK) endif() find_package(SWIG) find_package(VSTSDK2X) # TODO should this work for MSVC also? if(WIN32) find_library(FLAC_LIB NAMES FLAC flac) find_library(OGG_LIB ogg) find_library(SPEEX_LIB speex) find_library(VORBIS_LIB vorbis) find_library(VORBISENC_LIB vorbisenc) set(LIBSNDFILE_SUPPORT_LIBS ${VORBIS_LIB} ${VORBISENC_LIB} ${FLAC_LIB} ${OGG_LIB}) if(SPEEX_LIB) list(APPEND LIBSNDFILE_SUPPORT_LIBS ${SPEEX_LIB} ) endif() #message(STATUS "${LIBSNDFILE_SUPPORT_LIBS}") endif() find_path(SNDFILE_H_PATH sndfile.h) if(SNDFILE_H_PATH) include_directories(${SNDFILE_H_PATH}) else() message(FATAL_ERROR "Could not find sndfile.h") endif() if(NOT MSVC AND REQUIRE_PTHREADS) # Use ladder of if's to support older CMake versions (i.e., travis) find_library(PTHREAD_LIBRARY winpthread-1) if(NOT PTHREAD_LIBRARY) find_library(PTHREAD_LIBRARY pthread) endif() if(NOT PTHREAD_LIBRARY) find_library(PTHREAD_LIBRARY pthreadGC2) endif() if(NOT PTHREAD_LIBRARY) message(STATUS "Csound requires the pthread library") endif() #FIXME this variable is for required include directories, possible bug set(CMAKE_REQUIRED_INCLUDES pthread.h) set(CMAKE_REQUIRED_LIBRARIES pthread) endif() # Now, non required library searches # option(USE_ATOMIC_BUILTIN "Use Atomic Builtins if supported" ON) if(USE_ATOMIC_BUILTIN) include(cmake/CheckAtomic.cmake) if(HAVE_ATOMIC_BUILTIN) message(STATUS "Using atomic builtins.") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DHAVE_ATOMIC_BUILTIN") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_ATOMIC_BUILTIN") else() message(STATUS "Not using atomic builtins - not found") endif() else() message(STATUS "Not using atomic builtins - user disabled") endif() find_library(VORBISFILE_LIBRARY vorbisfile) check_include_file(libintl.h LIBINTL_HEADER) find_path(EIGEN3_INCLUDE_PATH eigen3/Eigen/Dense) find_package(GMM) find_library(LIBINTL_LIBRARY intl) find_package(Gettext) check_library_exists(m lrint "" HAVE_LRINT) set(HEADERS_TO_CHECK unistd.h io.h fcntl.h stdint.h sys/time.h sys/types.h termios.h values.h winsock.h sys/socket.h dirent.h ) foreach(header ${HEADERS_TO_CHECK}) # Convert to uppercase and replace [./] with _ string(TOUPPER ${header} tmp) string(REGEX REPLACE [./] "_" upper_header ${tmp}) check_include_file(${header} HAVE_${upper_header}) endforeach() check_deps(USE_LRINT HAVE_LRINT) if(USE_LRINT) add_definitions("-DUSE_LRINT") endif() ## Check existence of CURL if(USE_CURL) find_package(CURL) if(CURL_FOUND) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DHAVE_CURL") else() message(STATUS "Not using CURL for urls - not found.") endif() else() message(STATUS "Not using CURL for urls - disabled.") endif() # Flex/Bison for the new parser find_package(FLEX) find_package(BISON) if(NOT FLEX_EXECUTABLE) message(FATAL_ERROR "Csound requires the flex executable") endif() if(NOT BISON_EXECUTABLE) message(FATAL_ERROR "Csound requires the bison executable") endif() ## MAIN TARGETS ## set(libcsound_CFLAGS -D__BUILDING_LIBCSOUND) include_directories(./H) include_directories(./include) include_directories(./Engine) #adding this for files that #include SDIF/sdif* include_directories(./) #checking pthread functions if(REQUIRE_PTHREADS AND PTHREAD_LIBRARY) #list(APPEND libcsound_CFLAGS -DHAVE_PTHREAD) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DHAVE_PTHREAD") check_function_exists(pthread_spin_lock PTHREAD_SPIN_LOCK_EXISTS) check_function_exists(pthread_barrier_init PTHREAD_BARRIER_INIT_EXISTS) if(PTHREAD_SPIN_LOCK_EXISTS) list(APPEND libcsound_CFLAGS -DHAVE_PTHREAD_SPIN_LOCK) endif() if(PTHREAD_BARRIER_INIT_EXISTS) list(APPEND libcsound_CFLAGS -DHAVE_PTHREAD_BARRIER_INIT) endif() endif() #if(WIN32) include_directories(${LIBSNDFILE_INCLUDE_DIRECTORY}) #endif(WIN32) # get the git hash and pass it to csound SET(git_hash_values "none") if(USE_GIT_COMMIT) find_package(Git) message(STATUS "GIT: ${GIT_EXECUTABLE}") if(GIT_FOUND) execute_process(COMMAND ${GIT_EXECUTABLE} "rev-parse" "HEAD" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE git_hash_value) if (git_hash_value) string(STRIP ${git_hash_value} git_hash_values) message(STATUS "HASH: ${git_hash_values}") endif() endif() endif() set_source_files_properties(Top/csound.c PROPERTIES COMPILE_FLAGS -DGIT_HASH_VALUE=${git_hash_values}) # The csound library set(libcsound_SRCS Top/csound.c Engine/auxfd.c Engine/cfgvar.c Engine/corfiles.c Engine/entry1.c Engine/envvar.c Engine/extract.c Engine/fgens.c Engine/insert.c Engine/linevent.c Engine/memalloc.c Engine/memfiles.c Engine/musmon.c Engine/namedins.c Engine/rdscor.c Engine/scsort.c Engine/scxtract.c Engine/sort.c Engine/sread.c Engine/swritestr.c Engine/twarp.c Engine/csound_type_system.c Engine/csound_standard_types.c Engine/csound_data_structures.c Engine/pools.c InOut/libsnd.c InOut/libsnd_u.c InOut/midifile.c InOut/midirecv.c InOut/midisend.c InOut/winascii.c InOut/windin.c InOut/window.c InOut/winEPS.c InOut/circularbuffer.c OOps/aops.c OOps/bus.c OOps/cmath.c OOps/diskin2.c OOps/disprep.c OOps/dumpf.c OOps/fftlib.c OOps/pffft.c OOps/goto_ops.c OOps/midiinterop.c OOps/midiops.c OOps/midiout.c OOps/mxfft.c OOps/oscils.c OOps/pstream.c OOps/pvfileio.c OOps/pvsanal.c OOps/random.c OOps/remote.c OOps/schedule.c OOps/sndinfUG.c OOps/str_ops.c OOps/ugens1.c OOps/ugens2.c OOps/ugens3.c OOps/ugens4.c OOps/ugens5.c OOps/ugens6.c OOps/ugtabs.c OOps/ugrw1.c OOps/vdelay.c OOps/compile_ops.c Opcodes/babo.c Opcodes/bilbar.c Opcodes/compress.c Opcodes/eqfil.c Opcodes/Vosim.c Opcodes/squinewave.c Opcodes/pinker.c Opcodes/pitch.c Opcodes/pitch0.c Opcodes/spectra.c Opcodes/ambicode1.c Opcodes/sfont.c Opcodes/grain4.c Opcodes/hrtferX.c Opcodes/loscilx.c Opcodes/minmax.c Opcodes/pan2.c Opcodes/arrays.c Opcodes/phisem.c Opcodes/hrtfopcodes.c Opcodes/vbap.c Opcodes/vbap1.c Opcodes/vbap_n.c Opcodes/vbap_zak.c Opcodes/vaops.c Opcodes/ugakbari.c Opcodes/harmon.c Opcodes/pitchtrack.c Opcodes/partikkel.c Opcodes/shape.c Opcodes/tabsum.c Opcodes/crossfm.c Opcodes/pvlock.c Opcodes/fareyseq.c Opcodes/modmatrix.c Opcodes/scoreline.c Opcodes/modal4.c Opcodes/physutil.c Opcodes/physmod.c Opcodes/mandolin.c Opcodes/singwave.c Opcodes/fm4op.c Opcodes/moog1.c Opcodes/shaker.c Opcodes/bowedbar.c Opcodes/gab/tabmorph.c Opcodes/gab/hvs.c Opcodes/gab/sliderTable.c Opcodes/gab/newgabopc.c Opcodes/ftest.c Opcodes/hrtfearly.c Opcodes/hrtfreverb.c Opcodes/cpumeter.c Opcodes/gendy.c Opcodes/tl/sc_noise.c Opcodes/afilters.c Opcodes/wpfilters.c Top/argdecode.c Top/csdebug.c Top/cscore_internal.c Top/cscorfns.c Top/csmodule.c Top/getstring.c Top/main.c Top/new_opts.c Top/one_file.c Top/opcode.c Top/threads.c Top/utility.c Top/threadsafe.c Top/server.c) if(WIN32 AND NOT MSVC) set_source_files_properties(Opcodes/sfont.c PROPERTIES COMPILE_FLAGS -mno-ms-bitfields) endif() set(stdopcod_SRCS Opcodes/ambicode.c Opcodes/bbcut.c Opcodes/biquad.c Opcodes/butter.c Opcodes/clfilt.c Opcodes/cross2.c Opcodes/dam.c Opcodes/dcblockr.c Opcodes/filter.c Opcodes/flanger.c Opcodes/follow.c Opcodes/fout.c Opcodes/freeverb.c Opcodes/ftconv.c Opcodes/ftgen.c Opcodes/gab/gab.c Opcodes/gab/vectorial.c Opcodes/grain.c Opcodes/locsig.c Opcodes/lowpassr.c Opcodes/metro.c Opcodes/midiops2.c Opcodes/midiops3.c Opcodes/newfils.c Opcodes/nlfilt.c Opcodes/oscbnk.c Opcodes/pluck.c Opcodes/paulstretch.c Opcodes/repluck.c Opcodes/reverbsc.c Opcodes/seqtime.c Opcodes/sndloop.c Opcodes/sndwarp.c Opcodes/space.c Opcodes/spat3d.c Opcodes/syncgrain.c Opcodes/ugens7.c Opcodes/ugens9.c Opcodes/ugensa.c Opcodes/uggab.c Opcodes/ugmoss.c Opcodes/ugnorman.c Opcodes/ugsc.c Opcodes/wave-terrain.c Opcodes/stdopcod.c Opcodes/socksend.c Opcodes/sockrecv.c) set(cs_pvs_ops_SRCS Opcodes/ifd.c Opcodes/partials.c Opcodes/psynth.c Opcodes/pvsbasic.c Opcodes/pvscent.c Opcodes/pvsdemix.c Opcodes/pvs_ops.c Opcodes/pvsband.c Opcodes/pvsbuffer.c Opcodes/pvsgendy.c) set(oldpvoc_SRCS Opcodes/dsputil.c Opcodes/pvadd.c Opcodes/pvinterp.c Opcodes/pvocext.c Opcodes/pvread.c Opcodes/ugens8.c Opcodes/vpvoc.c Opcodes/pvoc.c) set(mp3in_SRCS Opcodes/mp3in.c InOut/libmpadec/layer1.c InOut/libmpadec/layer2.c InOut/libmpadec/layer3.c InOut/libmpadec/synth.c InOut/libmpadec/tables.c InOut/libmpadec/mpadec.c InOut/libmpadec/mp3dec.c) list(APPEND libcsound_SRCS ${stdopcod_SRCS} ${cs_pvs_ops_SRCS} ${oldpvoc_SRCS} ${mp3in_SRCS}) if(INIT_STATIC_MODULES) set(static_modules_SRCS Top/init_static_modules.c Opcodes/ampmidid.cpp Opcodes/doppler.cpp Opcodes/tl/fractalnoise.cpp Opcodes/ftsamplebank.cpp Opcodes/mixer.cpp Opcodes/signalflowgraph.cpp) set_source_files_properties(${static_modules_SRCS} PROPERTIES COMPILE_FLAGS -DINIT_STATIC_MODULES) list(APPEND libcsound_SRCS ${static_modules_SRCS}) endif() # Handling New Parser set(YACC_SRC ${CMAKE_CURRENT_SOURCE_DIR}/Engine/csound_orc.y) set(YACC_OUT ${CMAKE_CURRENT_BINARY_DIR}/csound_orcparse.c) set(YACC_OUTH ${CMAKE_CURRENT_BINARY_DIR}/csound_orcparse.h) set(LEX_SRC ${CMAKE_CURRENT_SOURCE_DIR}/Engine/csound_orc.lex) set(LEX_OUT ${CMAKE_CURRENT_BINARY_DIR}/csound_orclex.c) set(PRELEX_SRC ${CMAKE_CURRENT_SOURCE_DIR}/Engine/csound_pre.lex) set(PRELEX_OUT ${CMAKE_CURRENT_BINARY_DIR}/csound_prelex.c) add_custom_command( OUTPUT ${LEX_OUT} DEPENDS ${LEX_SRC} COMMAND ${FLEX_EXECUTABLE} ARGS -B -t ${LEX_SRC} > ${LEX_OUT} ) add_custom_command( DEPENDS ${PRELEX_SRC} COMMAND ${FLEX_EXECUTABLE} ARGS -B ${PRELEX_SRC} > ${PRELEX_OUT} OUTPUT ${PRELEX_OUT} ) add_custom_command( OUTPUT ${YACC_OUT} ${YACC_OUTH} DEPENDS ${YACC_SRC} ${LEX_OUT} COMMAND ${BISON_EXECUTABLE} ARGS -pcsound_orc -d --report=itemset -o ${YACC_OUT} ${YACC_SRC} ) list(APPEND libcsound_SRCS ${LEX_OUT} ${YACC_OUT} ${PRELEX_OUT} Engine/csound_orc_semantics.c Engine/csound_orc_expressions.c Engine/csound_orc_optimize.c Engine/csound_orc_compile.c Engine/new_orc_parser.c Engine/symbtab.c) set_source_files_properties(${YACC_OUT} GENERATED) set_source_files_properties(${YACC_OUTH} GENERATED) set_source_files_properties(${LEX_OUT} GENERATED) set_source_files_properties(${PRELEX_OUT} GENERATED) if(MSVC) set_source_files_properties(${LEX_OUT} PROPERTIES COMPILE_FLAGS -DYY_NO_UNISTD_H) set_source_files_properties(${PRELEX_OUT} PROPERTIES COMPILE_FLAGS -DYY_NO_UNISTD_H) endif() # Handling New Score Parser ##list(APPEND libcsound_CFLAGS -DSCORE_PARSER) #set(YACC_SCOSRC ${CMAKE_CURRENT_SOURCE_DIR}/Engine/csound_sco.y) #set(YACC_SCOOUT ${CMAKE_CURRENT_BINARY_DIR}/csound_scoparse.c) #set(YACC_SCOOUTH ${CMAKE_CURRENT_BINARY_DIR}/csound_scoparse.h) #set(LEX_SCOSRC ${CMAKE_CURRENT_SOURCE_DIR}/Engine/csound_sco.lex) #set(LEX_SCOOUT ${CMAKE_CURRENT_BINARY_DIR}/csound_scolex.c) set(PRELEX_SCOSRC ${CMAKE_CURRENT_SOURCE_DIR}/Engine/csound_prs.lex) set(PRELEX_SCOOUT ${CMAKE_CURRENT_BINARY_DIR}/csound_prslex.c) ##message("${CMAKE_CURRENT_BINARY_DIR}/csound_prslex.c") ##message("${CMAKE_CURRENT_BINARY_DIR}/csound_scolex.c") ##message("${CMAKE_CURRENT_BINARY_DIR}/csound_scoparse.c") #add_custom_command( # OUTPUT ${LEX_SCOOUT} # DEPENDS ${LEX_SCOSRC} # COMMAND ${FLEX_EXECUTABLE} ARGS -B -t ${LEX_SCOSRC} > ${LEX_SCOOUT} # ) add_custom_command( OUTPUT ${PRELEX_SCOOUT} DEPENDS ${PRELEX_SCOSRC} COMMAND ${FLEX_EXECUTABLE} ARGS -B -t -d ${PRELEX_SCOSRC} > ${PRELEX_SCOOUT} ) #add_custom_command( # OUTPUT ${YACC_SCOOUT} ${YACC_SCOOUTH} # DEPENDS ${YACC_SCOSRC} ${LEX_SCOOUT} # COMMAND ${BISON_EXECUTABLE} # ARGS -pcsound_sco -t -d --report=itemset -o ${YACC_SCOOUT} ${YACC_SCOSRC} # ) list(APPEND libcsound_SRCS ${PRELEX_SCOOUT}) #${LEX_SCOOUT} ${YACC_SCOOUT} ${PRELEX_SCOOUT}) #set_source_files_properties(${YACC_SCOOUT} GENERATED) #set_source_files_properties(${LEX_SCOOUT} GENERATED) set_source_files_properties(${PRELEX_SCOOUT} GENERATED) if(MSVC) set_source_files_properties(${PRELEX_SCOOUT} PROPERTIES COMPILE_FLAGS -DYY_NO_UNISTD_H) endif() include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_BINARY_DIR}/include) if(NEW_PARSER_DEBUG) message(STATUS "Building with new parser debugging.") list(APPEND libcsound_CFLAGS -DPARSER_DEBUG=1) else() message(STATUS "Not building with new parser debugging.") endif() if(BUILD_MULTI_CORE) message(STATUS "Building with multicore support.") list(APPEND libcsound_SRCS Engine/cs_new_dispatch.c Engine/cs_par_base.c Engine/cs_par_orc_semantic_analysis.c Engine/cs_par_dispatch.c) list(APPEND libcsound_CFLAGS -DPARCS) else() message(STATUS "Not building with multicore support.") endif() set(CSOUNDLIB_STATIC "${CSOUNDLIB}-static") # ADDING HERE TO GRAB LIST OF HEADERS IN CASE OF BUILDING OSX FRAMEWORK add_subdirectory(include) if(APPLE) string(REGEX REPLACE "([^;]+)(;|$)" "include/\\1\\2" csheaders "${csheaders}") file(GLOB H_headers "${CMAKE_CURRENT_SOURCE_DIR}/H/*.h") set(libcsound_SRCS "${libcsound_SRCS};${csheaders};${H_headers};${CMAKE_CURRENT_BINARY_DIR}/include/float-version.h") endif() add_library(${CSOUNDLIB} SHARED ${libcsound_SRCS}) set_target_properties(${CSOUNDLIB} PROPERTIES SOVERSION ${APIVERSION}) if(APPLE) set_target_properties(${CSOUNDLIB} PROPERTIES FRAMEWORK YES) set_target_properties(${CSOUNDLIB} PROPERTIES FRAMEWORK_VERSION "${APIVERSION}") set_target_properties(${CSOUNDLIB} PROPERTIES PUBLIC_HEADER "${csheaders};${CMAKE_CURRENT_BINARY_DIR}/include/float-version.h") endif() # This copies libsndfile into the framework and sets the install names # of CsoundLib to refer to it. #if(APPLE AND NOT ${CMAKE_GENERATOR} STREQUAL "Xcode") #get_filename_component(source ${LIBSNDFILE_LIBRARY} REALPATH) #get_filename_component(depname ${source} NAME) #set(CSOUNDLIB_DIR ${BUILD_DIR}/${CSOUNDLIB}.framework/Versions/${APIVERSION}) #if(NOT EXISTS ${CSOUNDLIB_DIR}/Resources/libs/${depname}) # add_custom_command( # TARGET ${CSOUNDLIB} # POST_BUILD # COMMAND mkdir # ARGS -p ${CSOUNDLIB_DIR}/Resources/libs # COMMAND cp # ARGS ${source} ${CSOUNDLIB_DIR}/Resources/libs/${depname} # COMMAND ${CMAKE_INSTALL_NAME_TOOL} # ARGS -id ${depname} ${CSOUNDLIB_DIR}/Resources/libs/${depname} #) #endif() #add_custom_command( # TARGET ${CSOUNDLIB} # POST_BUILD # COMMAND ${CMAKE_INSTALL_NAME_TOOL} # ARGS -change ${source} @loader_path/Resources/libs/${depname} ${CSOUNDLIB_DIR}/${CSOUNDLIB} #) #endif() # Utility function to make plugins. All plugin targets should use this as it # sets up output directory set in top-level CmakeLists.txt # and adds the appropriate install target # # libname - name of library to produce # srcs - list of src files (must be quoted if a list) # extralibs (OPTIONAL) - extra libraries to link the plugin to # # NB - this was moved here as it needs some VARS defined above # for setting up the framework function(make_plugin libname srcs) if(APPLE) add_library(${libname} SHARED ${srcs}) else() add_library(${libname} MODULE ${srcs}) endif() set(i 2) while( ${i} LESS ${ARGC} ) if(NOT MSVC OR NOT("${ARGV${i}}" MATCHES "m")) target_link_libraries(${libname} ${ARGV${i}}) endif() math(EXPR i "${i}+1") endwhile() set_target_properties(${libname} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${BUILD_PLUGINS_DIR} LIBRARY_OUTPUT_DIRECTORY ${BUILD_PLUGINS_DIR} ARCHIVE_OUTPUT_DIRECTORY ${BUILD_PLUGINS_DIR}) install(TARGETS ${libname} LIBRARY DESTINATION "${PLUGIN_INSTALL_DIR}" ) endfunction(make_plugin) # this copies the dependencies of plugins into framework # and fixes the lib name references function(add_dependency_to_framework pluginlib dependency) #if(APPLE AND NOT ${CMAKE_GENERATOR} STREQUAL "Xcode") #get_filename_component(source ${dependency} REALPATH) #get_filename_component(depname ${source} NAME) # #set(RESOURCE_DIR ${BUILD_DIR}/${CSOUNDLIB}.framework/Versions/${APIVERSION}/Resources) #if(NOT EXISTS ${RESOURCE_DIR}/libs/${depname}) #add_custom_command( #TARGET ${pluginlib} #COMMAND mkdir #ARGS -p ${RESOURCE_DIR}/libs #COMMAND cp #ARGS -f ${source} ${RESOURCE_DIR}/libs/${depname} #COMMAND ${CMAKE_INSTALL_NAME_TOOL} #ARGS -id ${depname} ${RESOURCE_DIR}/libs/${depname} #) #endif() #add_custom_command( #TARGET ${pluginlib} #POST_BUILD #COMMAND ${CMAKE_INSTALL_NAME_TOOL} #ARGS -change ${source} @loader_path/../libs/${depname} ${BUILD_PLUGINS_DIR}/lib${pluginlib}.dylib #) #endif() endfunction(add_dependency_to_framework) # Add the install target if(WIN32) install(TARGETS ${CSOUNDLIB} RUNTIME DESTINATION "${EXECUTABLE_INSTALL_DIR}" ARCHIVE DESTINATION "${LIBRARY_INSTALL_DIR}" FRAMEWORK DESTINATION "${CS_FRAMEWORK_DEST}") else() install(TARGETS ${CSOUNDLIB} LIBRARY DESTINATION "${LIBRARY_INSTALL_DIR}" ARCHIVE DESTINATION "${LIBRARY_INSTALL_DIR}" FRAMEWORK DESTINATION "${CS_FRAMEWORK_DEST}") endif() if(EMSCRIPTEN) include_directories(emscripten/deps/libsndfile-1.0.25/src/) endif() set(libcsound_LIBS ${LIBSNDFILE_LIBRARY}) if(REQUIRE_PTHREADS AND PTHREAD_LIBRARY) list(APPEND libcsound_LIBS ${PTHREAD_LIBRARY}) endif() if(WIN32) list(APPEND libcsound_LIBS "${CSOUND_WINDOWS_LIBRARIES}") list(APPEND libcsound_LIBS "${LIBSNDFILE_SUPPORT_LIBS}") else() endif() if(CURL_FOUND) list(APPEND libcsound_LIBS ${CURL_LIBRARIES}) if(WIN32 AND NOT MSVC) # not quite working yet with msys2/mingw64 #list(APPEND libcsound_CFLAGS -DCURL_STATICLIB -DLIBSSH_STATIC) #list(APPEND libcsound_LIBS crypto ssh2 ssl ws2_32 rtmp) #find_library(GNUTLS_LIB gnutls) #list(APPEND libcsound_LIBS ${GNUTLS_LIB}) endif() endif() # Linux does not have a separate libintl, it is part of libc set(LIBINTL_AVAIL (LIBINTL_LIBRARY OR LINUX)) check_deps(USE_GETTEXT LIBINTL_HEADER LIBINTL_AVAIL GETTEXT_MSGFMT_EXECUTABLE) if(USE_GETTEXT) message(STATUS "Using GNU gettext.") if(NOT LINUX) list(APPEND libcsound_LIBS ${LIBINTL_LIBRARY}) endif() list(APPEND libcsound_CFLAGS -DGNU_GETTEXT) if(NOT DEFINED CSOUND_TEXTDOMAIN AND BUILD_RELEASE AND (LINUX)) file(TO_NATIVE_PATH "${CMAKE_INSTALL_PREFIX}/${LOCALE_INSTALL_DIR}" CSOUND_TEXTDOMAIN) endif() if(CSOUND_TEXTDOMAIN) message(STATUS "Setting textdomain to ${CSOUND_TEXTDOMAIN}.") set_source_files_properties(Top/getstring.c PROPERTIES COMPILE_FLAGS -DCSOUND_TEXTDOMAIN=\\\"${CSOUND_TEXTDOMAIN}\\\") else() message(STATUS "Not setting textdomain.") endif() else() message(STATUS "Not using localization.") endif() if(LINUX) message(STATUS "Building on Linux.") add_definitions(-DLINUX -DPIPES -DNO_FLTK_THREADS -D_GNU_SOURCE -DHAVE_SOCKETS) list(APPEND libcsound_LIBS m dl) find_library(LIBRT_LIBRARY rt) if(LIBRT_LIBRARY) list(APPEND libcsound_LIBS ${LIBRT_LIBRARY}) message(STATUS " ADDING LIBRT LIBRARY: ${LIBRT_LIBRARY}.") endif() endif() if(APPLE AND NOT IOS) message(STATUS "Building on OSX") add_definitions(-DMACOSX -DPIPES -DNO_FLTK_THREADS -DHAVE_SOCKETS) find_library(ACCELERATE_LIBRARY Accelerate) find_path(VECLIB_PATH "Accelerate/Accelerate.h") include_directories(${VECLIB_PATH}) list(APPEND libcsound_LIBS m dl ${ACCELERATE_LIBRARY}) endif() if(WIN32) add_definitions(-DWIN32) endif() check_function_exists(strlcat HAVE_STRLCAT) if(HAVE_STRLCAT) add_definitions(-DHAVE_STRLCAT) endif() # Locale-aware reading and printing check_function_exists(strtok_r HAVE_STRTOK_R) check_function_exists(strtod_l HAVE_STRTOD_L) check_function_exists(sprintf_l HAVE_SPRINTF_L) if(HAVE_STRTOK_R) add_definitions(-DHAVE_STRTOK_R) endif() if(HAVE_STRTOD_L) add_definitions(-DHAVE_STRTOD_L) endif() if(HAVE_SPRINTF_L) add_definitions(-DHAVE_SPRINTF_L) endif() # Same for Windows check_function_exists(_strtok_r HAVE__STRTOK_R) check_function_exists(_strtod_l HAVE__STRTOD_L) check_function_exists(_sprintf_l HAVE__SPRINTF_L) if(HAVE__STRTOK_R) add_definitions(-DHAVE__STRTOK_R) endif() if(HAVE__STRTOD_L) add_definitions(-DHAVE__STRTOD_L) endif() if(HAVE__SPRINTF_L) add_definitions(-DHAVE__SPRINTF_L) endif() # Pass flags according to system capabilities if(HAVE_WINSOCK_H OR HAVE_SYS_SOCKETS_H) list(APPEND libcsound_CFLAGS -DHAVE_SOCKETS) endif() if(HAVE_DIRENT_H) list(APPEND libcsound_CFLAGS -DHAVE_DIRENT_H) endif() if(HAVE_FCNTL_H) list(APPEND libcsound_CFLAGS -DHAVE_FCNTL_H) endif() if(HAVE_UNISTD_H) list(APPEND libcsound_CFLAGS -DHAVE_UNISTD_H) endif() if(HAVE_STDINT_H) list(APPEND libcsound_CFLAGS -DHAVE_STDINT_H) endif() if(HAVE_SYS_TIME_H) list(APPEND libcsound_CFLAGS -DHAVE_SYS_TIME_H) endif() if(HAVE_SYS_TYPES_H) list(APPEND libcsound_CFLAGS -DHAVE_SYS_TYPES_H) endif() if(HAVE_TERMIOS_H) list(APPEND libcsound_CFLAGS -DHAVE_TERMIOS_H) endif() if(HAVE_VALUES_H) list(APPEND libcsound_CFLAGS -DHAVE_VALUES_H) endif() #if(CMAKE_C_COMPILER MATCHES "gcc") # list(APPEND libcsound_CFLAGS -fno-strict-aliasing) #endif() if(BIG_ENDIAN) list(APPEND libcsound_CFLAGS -DWORDS_BIGENDIAN) endif() target_compile_options(${CSOUNDLIB} PRIVATE ${libcsound_CFLAGS}) target_link_libraries(${CSOUNDLIB} PRIVATE ${libcsound_LIBS}) set_target_properties(${CSOUNDLIB} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${BUILD_BIN_DIR} LIBRARY_OUTPUT_DIRECTORY ${BUILD_LIB_DIR} ARCHIVE_OUTPUT_DIRECTORY ${BUILD_LIB_DIR}) if(BUILD_STATIC_LIBRARY) add_library(${CSOUNDLIB_STATIC} STATIC ${libcsound_SRCS}) SET_TARGET_PROPERTIES(${CSOUNDLIB_STATIC} PROPERTIES OUTPUT_NAME ${CSOUNDLIB}) SET_TARGET_PROPERTIES(${CSOUNDLIB_STATIC} PROPERTIES PREFIX "lib") target_compile_options(${CSOUNDLIB_STATIC} PRIVATE ${libcsound_CFLAGS}) target_link_libraries(${CSOUNDLIB_STATIC} ${libcsound_LIBS}) set_target_properties(${CSOUNDLIB_STATIC} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${BUILD_BIN_DIR} LIBRARY_OUTPUT_DIRECTORY ${BUILD_LIB_DIR} ARCHIVE_OUTPUT_DIRECTORY ${BUILD_LIB_DIR}) # Add the install target install(TARGETS ${CSOUNDLIB_STATIC} LIBRARY DESTINATION "${LIBRARY_INSTALL_DIR}" ARCHIVE DESTINATION "${LIBRARY_INSTALL_DIR}") endif() # VL -- this seems to be a duplicate instruction # and it's breaking the build. See lines 1088-95 #install(TARGETS ${CSOUNDLIB} # LIBRARY DESTINATION "${LIBRARY_INSTALL_DIR}" # ARCHIVE DESTINATION "${LIBRARY_INSTALL_DIR}") ## option(BUILD_CATALOG "Build the opcode/library catalog" OFF) ## check_deps(BUILD_CATALOG) ## if(BUILD_CATALOG) ## make_executable(mkdb "mkdb" "dl") ## set_target_properties(mkdb PROPERTIES LINKER_LANGUAGE C) ## endif() add_subdirectory(Opcodes) add_subdirectory(InOut) add_subdirectory(interfaces) add_subdirectory(frontends) add_subdirectory(util) add_subdirectory(util1) add_subdirectory(SDIF) add_subdirectory(po) add_subdirectory(tests/c) add_subdirectory(tests/commandline) add_subdirectory(tests/regression) add_subdirectory(tests/soak) # uninstall target configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) # target etags/tags if(UNIX) add_custom_target(tags COMMAND etags `find ${CMAKE_CURRENT_SOURCE_DIR} -name \\*.cc -or -name \\*.hh -or -name \\*.cpp -or -name \\*.h -or -name \\*.c | grep -v " " `) add_custom_target(etags DEPENDS tags) endif() # build a CPack driven installer package #include (InstallRequiredSystemLibraries) set (CPACK_PACKAGE_NAME "csound") set (CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING") set (CPACK_PACKAGE_VERSION "6.0.0") set (CPACK_PACKAGE_VERSION_MAJOR "6") set (CPACK_PACKAGE_VERSION_MINOR "0") set (CPACK_PACKAGE_VERSION_PATCH "0") include (CPack) # Documentation find_package(Doxygen) if(DOXYGEN_FOUND) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.doxygen ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) add_custom_target(doc ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) else() message(STATUS "Not building documentation") endif(DOXYGEN_FOUND) csound-6.10.0/COPYING000066400000000000000000000634761321653344700141540ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! csound-6.10.0/ChangeLog000066400000000000000000013567461321653344700147010ustar00rootroot000000000000002012-02-09 john ffitch * Opcodes/ugsc.c (hilbertset): Remove unnecessary arrays 2012-02-06 john ffitch * H/version.h: VERSION 5.16.1 2011-11-30 john ffitch * Opcodes/pitch.c (impulse): If next is negative time, make it absolute value 2011-10-28 john ffitch * Opcodes/socksend.c (send_send, send_sendS): Added optional format message as INT16_LE and remove MTFU check 2011-10-14 John ff * Opcodes/tabvars.c (ftab2tab): (tab2ftab): New opcodes 2011-10-12 John ff * VERSION 5.14 2011-06-21 john ffitch * Opcodes/wiimote.c (wii_data_init): Return value missing (wii_data_inits): Ditto 2011-05-25 John ff * Engine/fgens.c (nextval): Ensure c moves on if not a number 2011-05-19 john ffitch * OOps/cmath.c (exprndiset, kexprndi, aexprndi): New code for exprandi opcode; also cauchyi 2011-05-05 john ffitch * SConstruct (optionsFilename): Try to check that the custom.py exists 2011-04-10 john ffitch * OOps/aops.c (is_NaN, is_NaNa): New function (is_inf, is_infa): New function 2011-03-17 john ffitch * Engine/csound_orc_expressions.c (csound_orc_expand_expressions): Generate kgoto rather than goto. Not totally sure this is right yet 2011-02-09 john ffitch * util1/csd_util/makecsd.c (main): new options for MIDI files and score processing; licence control as well * util1/csd_util/base64.c (encode_file): Added extra arg to select tags 2011-01-20 john ffitch * Opcodes/mp3in.c (mp3len): New code * SConstruct: Add building of fareyseq/fareygen which got lost 2011-01-17 john ffitch * H/version.h: VERSION 5.13 2011-01-13 john ffitch * OOps/ugens2.c (ko1set): ensure that the increment cannot be zero 2011-01-10 john ffitch * Engine/fgens.c (gen49): Use csound->FileOpen2 rather than open to get searching (gen49): buffer used was in wrong units (chars v shorts) 2010-12-28 john ffitch * Engine/symbtab.c (add_token): remove message if Opcode/Function confusion 2010-12-18 john ffitch * Opcodes/gab/tabmorph.c (atabmorphia): Fixed editing error that would have caused opcode to scribble over memory 2010-12-17 John ff * Opcodes/gab/vectorial.c: Lots of optimisations and corrections 2010-12-10 john ffitch * Opcodes/gab/gab.c (isChanged_set): Initialise p->old_inargs 2010-12-05 john ffitch * H/aops.h (struct INCH): Rewritten * OOps/aops.c (inch_opcode): Rewritten * Engine/entry1.c: Allow multiple args in inch * Engine/csound_orc.l (do_at): New code to support @ and @@ operators 2010-11-28 john ffitch * Engine/symbtab.c: Added cent as function 2010-11-27 john ffitch * OOps/ugens3.c (adsyn): check that ktogo is never zero 2010-11-16 John ff * Top/main.c (csoundCompile): and call macro inits * Engine/csound_orc.l: Add standard macro initialisation code to lexer 2010-11-12 John ff * Engine/csound_orc_semantics.c (handle_polymorphic_opcode): Calculating c before switch can lead to following a null pointer. Moved calculation to where it is needed. 2010-11-05 John ff * OOps/ugens4.c (riset, rndset, rhset): Use Warning rather than Message 2010-11-04 John ff * Opcodes/pvsbasic.c (MAXOUTS): Extend upto 16 outputs (localops): Use F format in pvstanal 2010-10-12 john ffitch * Engine/csound_orc.y: Allow labels in exprlists 2010-10-08 John ff * OOps/cmath.c (ipow, apow): If normalisation is zero make it 1; Needed in new parser as optional arg not handled * csound_orc.l: Many changes in macros and stack of inputs 2010-09-23 john ffitch * Opcodes/fout.c (sprints): Attempt to fix %%->% problem 2010-09-18 john ffitch * Engine/csound_orc_expressions.c (create_expression): Unary minus should use i rate if it can 2010-09-17 john ffitch * SConstruct: * Top/csound.c: Make new parser default 2010-09-02 Michael Gogins * Corrected signature of fluidAllOut opcode, and fencepost error in that opcode. * Fixed order of processing in CsoundVST audio output callbacks. 2010-09-02 Michael Gogins * Migrated Windows compiler to MinGW GCC 4.4.0 from Qt for all third party and Csound executables. This compiler generates dw2 exception handling code. * Fixed up examples to execute in their own directories. * Changed csoundSetMessageCallback to reset the callback to csoundDefaultMessageCallback if the user sets the callback to null, in order to prevent segment faults. 2010-09-01 john ffitch * Opcodes/gab/gab.c (adsynt2): Phase not handled correctly 2010-08-31 john ffitch * Engine/csound_orc_expressions.c: Many changes to make if_then etc work 2010-08-28 Michael Gogins * Replaced csound-build.tex with How_to_Build_Csound_on_Windows.doc, in Microsoft Word format, which should be more accessible to users. * Changed multi-threading in the head branch to use OpenMP instead of PThreads, for greater clarity and maintainability. 2010-08-26 john ffitch * Engine/csound_orc_expressions.c (create_cond_expression): New code to deal with (a?b:c) variant (is_expression_node): Added S_Q to expression operators (create_expression): Call create_cond_expression 2010-08-25 John ff * Engine/insert.c (insert): In pset case no not zero excess opcodes 2010-08-10 Michael Gogins * Engine/typetabl.h: Supplied missing type mask for 'J' type code, i.e. k-rate scalar defaulting to -1, used in "STK" opcodes and others. * Opcodes/stk/STKOpcodes.cpp: Changed threading from 5 to 3, changed MIDI controller number and value parameters to 'J' type. * Updated environment, build, and installer scripts for new Windows version built on new Core i7, Windows 7 computer. 2010-08-09 john ffitch * InOut/libsnd.c (sfopenin): Correct warning message * Top/csound.c ("C"): Default value of inchnls is now -1 * Engine/otran.c (oload): Set inchnls to nchnls if not explicit 2010-08-03 john ffitch * Engine/csound_orc.y (ifac): Typo -- used S_MOD rather than S_DIV 2010-08-01 john ffitch * Top/csound.c (csoundAddSpinSample): Needs to use nchnls_i 2010-07-31 john ffitch * Engine/csound_orc_semantics.c (handle_optional_args): * Engine/rdorch.c (getoptxt): Added J arg type 2010-07-28 John ff * Opcodes/urandom.c (urand_run, urand_init, urand_deinit): New code (LINUX ONLY) 2010-07-27 john ffitch * Top/csmodule.c (csoundCheckOpcodeDeny): Complete function vis CS_OMIT_LIBS environment 2010-07-26 john ffitch * Top/csmodule.c (csoundCheckOpcodeDeny): New function (INCOMPLETE) (csoundLoadModules): Check to see if library denied 2010-07-20 john ffitch * Engine/sort.c (ordering): Fixed stupidity of using int where MYFLT was needed * Opcodes/grain.c (ags): Added check that kglen is strictly positive 2010-07-19 john ffitch * Engine/sort.c (ordering): take account of negative p3 2010-07-14 john ffitch * Opcodes/mp3in.c (mp3in): Deal with case of end of data 2010-07-13 john ffitch * Engine/fgens.c (gen23): Typo in check for extra numbers removed 2010-07-08 john ffitch * OOps/sndinfUG.c (filevalid): * Engine/entry1.c: * H/entry1.h: Added filevalid opcode * H/sndinfUG.h (struct): Added FILEVALID structure 2010-07-04 john ffitch * Engine/musmon.c (process_midi_event): * Engine/insert.c (insert, MIDIinsert, insert_event): * Engine/auxfd.c (auxchprint): Print name of instrument if available (fdchprint): ditto 2010-07-03 john ffitch * Engine/sort.c (ordering): Rewrote to make clearer and complete * H/sort.h (srtblk): Changed order of fields to avoid overwrite * Engine/extract.c: Added lineo field to dummy events 2010-06-28 john ffitch * Opcodes/pitch0.c (maxalloc, cpuperc, instcount) Allow named instruments 2010-06-24 john ffitch * Engine/sort.c (ordering): Added ordering on line number if all else fails * H/csoundCore.h (EVTBLK): Added array of chars for strings 2010-05-26 john ffitch * Opcodes/ftgen.c (ftgen): Need to deal with fp[5] in named gen case 2010-05-23 john ffitch * Engine/fgens.c (hfgens): Check was against GENMAX rather than csound->genmax * Opcodes/ftgen.c (ftgen): Allow for named GENs * Top/csound.c (csoundGetNamedGens): New API function * Opcodes/fareyseq.c (tableshuffle): New code for two opcodes 2010-05-16 john ffitch * Opcodes/pitch.c (medfiltset): (medfilt): New code 2010-05-10 john ffitch * Opcodes/fareygen.c: * Opcodes/fareyseq.c: New code * SConstruct: Added farey sequence GEN and opcodes 2010-05-09 john ffitch * install.py: Added atsa to binaries 2010-05-03 john ffitch * OOps/ugens6.c (delay1): use memmove rather than a loop 2010-04-25 john ffitch * Opcodes/uggab.c (lineto): Some changes -- seems better * OOps/ugens3.c (adsyn): Sorted out confusion over int32 and MYFLT * OOps/ugens5.c (atonex): Fix bug; it was repeating the filter to the input rather than cascading (resonx): (tonex): Same error as atonex * Opcodes/gab/gab.c (adsynt2_set): Brought into line with adsynt_set, and revised (adsynt2_set): Initialisation of amp and frequency table was totally wrong 2010-04-10 john ffitch * Engine/fgens.c (gen41): Added check for positive probability 2010-04-05 john ffitch * Opcodes/sndwarp.c (sndwarp): The attempt to give only one warning message was wrong. Think OK now?? 2010-03-24 john ffitch * Top/main.c (csoundCompile): Removed spurious BETA check 2010-03-23 jpff * Engine/sread.c (sget1): Remove repeats free 2010-03-22 john ffitch * Engine/fgens.c (gen28): Typo -- freed x rather than y 2010-03-16 john ffitch * Engine/sort.c: Code replaced with smoothsort code 2010-03-13 john ffitch * Engine/smoothsort.c (sort): Deal with case of no e event 2010-03-12 jpff * SConstruct: Added smoothSort option to control building * Engine/smoothsort.c: New drop-in replacement for sort.c using a fancier sort algorithm 2010-02-28 john ffitch * OOps/ugrw1.c (sprints): A format with a % but no arg would cause a crash 2010-02-25 john ffitch * Opcodes/gab/gab.c: Added range checks to the fast table opcodes 2010-02-21 john ffitch * OOps/aops.c (aassign): Correct typo in arguments * Engine/rdorch.c (splitline): Rework \ inside strings 2010-02-15 jpff * Engine/typetabl.h (]): Need to add p to I case * Engine/rdorch.c (rdorchfile): Do not increment lincnt in line continuation mode 2010-02-13 john ffitch * OOps/aops.c (minit): Ensure a,b=b,a works 2010-02-12 john ffitch * OOps/aops.c (minit, mainit): new code for multiple init * Engine/entry1.c: Changed init to multiple version 2010-01-24 john ffitch * Engine/sread.c (init_smacros): Define INF macro in scores as well (getscochar): Read 'z' as infinity * Engine/rdorch.c (init_math_constants_macros): Added INF macro for infinity in orchestra 2010-01-17 john ffitch * VERSION 5.12 a2010-01-16 john ffitch * Engine/otran.c (oload): Need to check the first 6 variables, up from 5 due to input channel code 2010-01-11 john ffitch * Engine/fgens.c (gen28, gen31, gen32, gen33, gen34): Used malloc/free for local memory * InOut/widgets.cpp (fl_callbackExecButton): Freed memory allocated in Windows case 2010-01-08 mantaraya36 * Engine/insert.c: Allow turning off non-indefinite instruments from negative score events. By John ffitch. 2010-01-08 john ffitch * Engine/musmon.c (musmon): Corrected csound->inchnls to csound->nchnls * Engine/csound_orc.y (param): Alter precedence of ? operator 2010-01-06 jpff * Opcodes/fout.c (fprintf_set): Set line buffering 2010-01-02 john ffitch * Opcodes/uggab.c (loopxseg): Fixed bug on shape 2009-12-28 john ffitch * Engine/linevent.c (sensLine): * Engine/musmon.c (insert_score_event_at_sample): Allow too few arguments in f -x case 2009-12-27 john ffitch * Opcodes/uggab.c (loopxseg): New code for loopxseg opcode 2009-12-26 john ffitch * Opcodes/uggab.c (nterpol_init): Check to stop division by zero 2009-12-25 john ffitch for Francois Pinot * Opcodes/crossfm.h: * Opcodes/crossfm.c: New code 2009-12-23 john ffitch * Opcodes/sfont.c: Set pitches on module creation rather than on every load. 2009-12-22 john ffitch * Opcodes/sfont.c (SfLoad): Added check to see if too many sound fonts are loaded. * Opcodes/pitch.c (trnsetr, trnset): Check argument count is 1mod3 2009-12-20 john ffitch * Engine/csound_orc_semantics.c (handle_optional_args): If there are no arguments yet we still need to add optionals 2009-12-13 john ffitch * Opcodes/nlfilt.c (pinit): New code to implement passign opcode 2009-12-11 john ffitch * Engine/rdorch.c (splitline): Allow \" in strings * Top/one_file.c (readOptions): Reset linecount after reading .csoundrc 2009-11-29 john ffitch * Opcodes/cross2.c (getmag): If magnitude is zero do not scale! 2009-11-28 john ffitch * Opcodes/pitch.c (clockon, clockoff): Reading the clock should be incremental. (correcting bug introduced by Istvan) 2009-11-24 jpff * Engine/musmon.c (gettempo): Fixed stupid error 2009-11-09 john ffitch * Opcodes/pan2.c (pan2run): Fixed editing error in type 3 (thanks to Sigurd Saue) 2009-11-03 john ffitch * Opcodes/p5glove.c (p5glove_find): Use thread to read the USB glove. 2009-10-16 jpff * Opcodes/pvsbasic.c (pvsshiftset): Change MYFLT to float in memset 2009-10-02 jpff * Opcodes/pitch.c (trnsetr, ktrnsegr, trnsegr): New code * Opcodes/spectra.c: declare transegr 2009-09-22 jpff * H/version.h: VERSION 5.11.1 * Opcodes/bilbar.c (bar_run): Fix typo in right end type 1 (bar_run): Loop needs to be one more for right end 2009-09-14 jpff * Engine/fgens.c (gen32): And allow extended here as well, via aux function 2009-09-10 jpff * Engine/fgens.c (gen52, gen51): Added extended arg support 2009-08-27 jpff * H/csoundCore.h (PMAX): Reduced by 2 (EVTBLK): Added c.extra field to EVTBLK * Engine/fgens.c: LOTS of changes to allow extension of arguments uses. * Engine/sread.c (ifa): removed limit of PMAX arguments to events * Engine/rdscor.c (rdscor): Allow reading of more than PMAX fields * Engine/fgens.c (gen23): Total rewrite 2009-08-19 jpff * Engine/fgens.c (hfgens): Correct error string to 1, 23 or 28 for deferred size. 2009-08-12 jpff * Engine/fgens.c (hfgens): Do not extend table of ftables unnecessarily; it used to always extend even if spare slots existed. 2009-08-10 jpff * Opcodes/tabsum.c (tabsum): Fixed silly error that made it all wrong. 2009-07-25 Michael Gogins * The Windows installer now provides the user with options for core, custom, or complete installation. Custom options include independent installation of C/C++, Lua, Python, Java, and Lisp interfaces; independent installation of csnd and CsoundAC; and independent installation of front ends and various other options. 2009-07-21 * OOps/cmath.c (seedrand): if positive would still seed from time 2009-07-20 jpff * OOps/ugrw1.c (printsset): Set string[0] to null as otherwise sprints does wrong thing on empty string 2009-07-18 Michael Gogins * SConstruct now builds completely independent shared libraries for Python, Lua, and Java wrappers. * Reorganized examples directory to put all examples for C, C++, Python, Lua, Java, and Lisp wrappers in separate subdirectories. Opcode demos also go into a separate subdirectory. The root examples directory should now contain only complete pieces or tutorial pieces. 2009-07-05 jpff * Opcodes/spectra.c (mute opcode): Should be type T to accept string or number. * SConstruct (cf): Check that libintl.h exists in the GETTEXT version 2009-06-10 jpff * Engine/csound_orc.l: Corrected continuation line pattern 2009-06-05 jpff * Engine/csound_orc.y (ident): Added unary + * H/version.h: Marked as 5.10.90 and 5.11rc1 2009-06-04 jpff * Engine/csound_orc_expressions.c (create_goto_token) (get_boolean_arg, create_boolean_expression) (create_synthetic_ident, csound_orc_expand_expressions): Create and use Boolean variables with either k or i type as required 2009-05-05 jpff * Engine/csound_orc.l: Deal with \+NL 2009-05-01 jpff * Engine/csound_orc.y (if, ifthen, elsif): Removed requirement for brackets round condition. 2009-04-30 jpff * Engine/csound_orc.y: Remove two globals to the CSOUND structure and start numbered instruments. 2009-04-29 Victor Lazzarini * InOut/FL_graph.cpp: fixed the redrawing of graphs so that only selected ones get redrawn. 2009-04-28 jpff * H/csoundCore.h ("C"): Declare * Top/csound.c ("C"): Initialise floatsize * Engine/musmon.c (musmon): Set csound->floatsize 2009-04-27 Victor Lazzarini * Opcodes/pvsbasic.c: added rounding bin code to pvsscale * Opcodes/ftgen.c: added NP2 support for ftload and ftsave * Engine/fgen.c: moved a PerfError to a Warning when tables are resized to enable ftload to resize deferred-allocation tables. * OOps/ugens5.c: experimental LPC read opcode * H/ugens.h: as above * Engine/oentry1.c: as above 2009-04-24 Anthony Kozar * SConstruct: Define WORDS_BIGENDIAN for hrtfnew opcodes when appropriate. * H/prototyp.h: * H/csoundCore.h: * Top/csound.c: * Engine/memfiles.c: New API function pointer ldmemfile2withCB() which is a version of ldmemfile() allowing a callback to be set and called exactly once to process the MEMFIL buffer after it is loaded. * H/version.h: Increased API version to 2.1. * Engine/memfiles.c (Load_File_): * Opcodes/hrtfopcodes.c: Moved byteswapping code for HRTF opcodes to hrtfnew module utilizing ldmemfile2withCB(). * H/csound.h: Removed file type CSFTYPE_FLOATS_BINARY_SW 2009-04-19 jpff * Opcodes/p5glove.c: New code to controlP5 Glove directly * Engine/csound_orc_semantics.c (handle_polymorphic_opcode): Added polymorphic type 0xfffd 2009-04-17 jpff * Engine/memfiles.c (Load_File_): Add option for byteswap from LITTLE- to BIG-ENDIAN if necessary (CSFTYPE_FLOATS_BINARY_SW) * H/csound.h: New file type CSFTYPE_FLOATS_BINARY_SW 2009-04-08 Michael Gogins * Opcodes/mixer.cpp: Added MixerSetLevel_i, an init-time only version of MixerSetLevel, so that it is possible to set the levels of mixer sends in the orchestra header. 2009-03-30 jpff * OOps/diskin.c (diskin_read_buffer): Typo corrected 2009-03-24 Michael Gogins * frontends/CsoundAC/Score.cpp: * interfaces/CsoundFile.cpp: Implemented importation of MusicXML v2 files into the CsoundAC Score class and the csnd CsoundFile class, using the Grame MusicXML library. 2009-03-22 jpff * OOps/oscils.c (tablexkt): Line adding to ar removed as wrong 2009-03-18 Anthony Kozar * SConstruct: * Opcodes/syncgrain.c: Added config test for values.h. * frontends/cscore/cscoremain.c: * frontends/cscore/cscoremain_MacOS9.c: * util1/scot/scot_main.c: Changed Scot and Cscore to take an optional second commandline argument specifying the output file. 2009-03-16 jpff * InOut/rtalsa.c (set_device_params): Change to snd_pcm_hw_params_set_rate_near rather than exact samplerate from "Pete G." 2009-03-15 jpff * Top/one_file.c (createExScore): Added new facility to have score generated by external code (read_unified_file): and call it 2009-03-14 jpff * util/lpc_export.c (lpc_export): Fix from Martin Rocamora on line 83 * util/lpcx_main.c (main): Fix from Martin Rocamora on line 82 2009-03-04 jpff * Opcodes/wiimote.c: New code (still experimental) to use wiimote in Csound (Linux only at present) 2009-03-01 jpff * Opcodes/mp3in.c: New code to read MP3 files (still experimental) 2009-02-28 Anthony Kozar * H/ugens5.h: * OOps/ugens5.c (lprdset, lpread): Fixed bad assumptions in doubles build when skipping over the LPC file header. 2009-02-23 jpff * Engine/fgens.c (gen49): New gen to read MP3 files using mpadec library 2009-02-07 jpff * Engine/rdorch.c (rdorchfile): * Engine/sread.c (sget1): Mane mname grow rather than being fixed size 2009-02-06 jpff * H/csoundCore.h ("C"): Added GetChannelLock to API * OOps/bus.c (csoundGetChannelLock): New function, deployed as well all over this file * H/csound.h ("C"): Added csoundGetChannelLock 2008-12-19 jpff * H/version.h: VERSION 5.10.1 2008-12-18 jpff * Opcodes/pitch.c (hsboscset): Bug whereby two internal variables may be unititialised fixed. 2008-12-17 Anthony Kozar * SConstruct: Add libintl on OS X when useGettext=1. Commented out -fno-rtti option on OS X. Revised Python detection logic so that it works on multiple versions of OS X. 2008-12-15 jpff * H/version.h (CS_APIVERSION): Upped version to 2/0 * H/csoundCore.h: Cleaned up unused fields in struct CSOUND_ and added some expansions. Tidied timing counters as well. Involved a number of small changes elsewhere 2008-12-04 mantaraya36 * Opcodes/pmidi.c : Added option to listen on all MIDI ports using 'a' instead of a device number. 2008-12-04 jpff * Opcodes/midiops3.c (islider32bit14): I think it should have 32 as arg to ISLIDER14 2008-12-02 jpff * Engine/insert.c: * Engine/linevent.c: * Engine/musmon.c: * Engine/otran.c: * H/csoundCore.h: * H/prototyp.h: * InOut/libsnd.c: * InOut/midisend.c: * OOps/schedule.c: * OOps/ugrw1.c: * Opcodes/OSC.c: * Top/csound.c: Change curTime to integer and work in samples rather than seconds. Same for beatTime 2008-11-30 jpff * Engine/fgens.c (csoundFTAlloc): Make size change with active instruments a PerfError 2008-11-21 jpff * Opcodes/filter.c (izfilter): Loop went 1 too many for coeffs->dcoeffs 2008-11-01 jpff * Opcodes/pitch.c (pitchamdf): Arrange that if peri is zero not to return NaN or Inf values. Suggests some algorithmic error (pitchamdfset): Initialise rmsmedian buffer -- it was undefined. No idea how it ever could work. 2008-10-31 jpff * Engine/otran.c (otran): Experimentally set locale to C numeric before parsing orchestra. 2008-10-27 jpff * OOps/aops.c (outo): Channel 6 was wrong, (outh): also here. 2008-10-18 jpff * InOut/rtwinmm.c (open_device): Dither only if requested. * H/csoundCore.h ("C"): Move dither to visible. * InOut/rtpa.c (set_device_params): Dither only if requested. (paBlockingReadWriteOpen): Ditto. * InOut/rtalsa.c (set_format): Dither only if requested. (MYFLT_to_short_no_dither): New function. 2008-10-09 Victor Lazzarini * Engine/fgens.c: added an optional parameter for GEN20 (type 6, Gaussian), to set the variance (default = 1.0). 2008-09-29 jpff * OOps/diskin.c (diskin_read_buffer): mea culpa; zeros written to wrong place. 2008-09-13 Michael Gogins * H/csound.h: Added Doxygen "mainpage" introductory section at top of file; switched to HTML format for API documentation (replacing LaTeX/PDF format). 2008-09-17 jpff * RELEASE VERSION 5.09 2008-09-13 Michael Gogins * frontends/CsoundAC/Score.cpp: Implemented importation of MusicXML v2 files into the CsoundAC Score class, using the Grame MusicXML library. 2008-09-13 Michael Gogins * custom-mingw.py: Updated for more recent third party packages. * frontends/fltk_gui/CsoundGUIMain.cpp: Score editor works properly now. * examples: Updated CsoundAC.csd and CsoundAC-midi.csd, removed some obsolete precursors of them, added Drone.py Tk GUI example. * csound-build.tex: Detailed instructions for building the Windows installers. * Top/csound.c, H/csoundCore.h: Corrected spinlocks for thread-safe access to spin and spout buffers, added to dummy slots of the CSOUND structure to preserve backwards API compatibility. 2008-09-10 jpff * Opcodes/scoreline.c (localops): Wrong structure named in entry -- probably benign * H/version.h (CS_PACKAGE_STRING): VERSION 5.09 2008-09-09 Anthony Kozar * H/csound.h (csoundSpinLock, csoundSpinUnLock): Removed attempt at printing warnings when spinlocks are not implemented. * Opcodes/sfont.c (SfPlayMono): More declaration before code fixes. * Opcodes/shape.c (PDHalfX): Fixed unitialized variable. * Engine/rdorch.c (skiporccomment): * Opcodes/Vosim.c (vosimset): Added missing return values. 2008-09-08 Anthony Kozar * Top/threads.c (csoundRunCommand, csoundSleep): Consolidated dummy versions to avoid multiple definitions. 2008-09-08 jpff * Top/csound.c ("C"): Do not load pthreads in mac_clasic * Top/threads.c (csoundRunCommand, csoundSleep): Added mac_classic dummy versions * OOps/aops.c (outs): Declarations before code in C 2008-09-02 jpff * H/ugrw1.h: * OOps/ugrw1.c (printkset, printk, printksset, printks): Check that opcode is initialised 2008-08-31 jpff * H/version.h: 5.08.99 2008-08-14 jpff * Engine/csound_orc.l: Added #include and macros (currently without arguments) 2008-08-12 jpff * Opcodes/uggab.c (poscaa, poscka): Ensure frequency is not overwritten if variable is shared 2008-07-26 jpff * Engine/rdorch.c (skiporccomment): Correct stupid error in multiple * characters 2008-07-23 jpff * Engine/fgens.c (gen23): Allow scientific notation (as was in csound4!) 2008-07-05 jpff * Opcodes/ambicode1.c: Added new file with Furse/Wiggins decoders 2008-06-30 Steven Yi * Engine/musmon.c: reverted sensevents to set EVTBLK to outside of while loop; caused bug where using event opcode with "e" would cause a segfault and hang csound 2008-06-26 jpff * SConstruct: Allow selectable version if TCL and TK (needed for OpenSuSE11.0) 2008-06-12 jpff * Engine/memalloc.c (mfree): (mrealloc): Improvements to coding 2008-05-28 Michael Gogins * Top/threads.c: For the Csound threading API, on the Windows platform, I removed the native Windows threading implementation and replaced it with the POSIX threads implementation already used for Linux and OS X. This is to facilitate development of multi-threading in Csound, and to simplify the maintenance of Csound. 2008-05-28 jpff * Opcodes/ugens7.c (harmon): Make constant totally 64bit safe * Opcodes/vbap.c: Change argument types to akOO from akoo etc 2008-05-18 Michael Gogins * Opcodes/chua/ChuaOscillator.cpp: Csound opcode implementation of Chua's Oscillator, a nonlinear dynamical system capable of many kinds of periodic and chaotic behavior, including multiple simultaneous attractors. See the reference manual entry for "chuap" for documentation. See examples/chuap.csd and examples/chuas_oscillator/ChuasOscillatorApp.py for sample Csound usage. * Opcodes/linear_algebra.cpp: Csound i-rate and k-rate opcodes for much standard linear algebra over real and complex vectors and matrices: elementwise arithmetic, norms, transpose and conjugate, inner products, matrix inverse, LU decomposition, QR decomposition, and QR-based eigenvalue decomposition. Includes copying vectors to and from a-rate signals, function tables, and f-signals. See the source code for preliminary documentation and tests/test24.csd for sample Csound usage. 2008-05-17 jpff * util/lpanal.c: Removed static variables to a structure 2008-05-08 jpff * util/envext.c: * util/het_export.c: * util/het_import.c: * util/heti_main.c: * util/lpc_export.c: * util/lpc_import.c: * util/lpci_main.c: * util/lpcx_main.c: * util/mixer.c: * util/pv_export.c: * util/pv_import.c: * util/scale.c: * util/srconv.c: * util/xtrct.c: * util1/sortex/smain.c: * util1/sortex/xmain.c: Corrected licence to LGPL 2008-05-06 jpff * Engine/rdorch.c (skiporccomment): New function to handle /* .. */ (rdorchfile): Call it * Engine/sread.c (sget1): Do not expand macros in /* .. */ context 2008-04-30 jpff * H/sysdep.h: Introduce macros for MYFLT versions of functions * OOps/aops.c: Use macro for exp/expf etc all over 2008-04-28 jpff * OOps/ugens4.c (buzz): Restructured for speed (gbuzz): Ditto 2008-04-24 jpff * Top/argdecode.c (argdecode): OLPC now have dummy R,N and H options 2008-04-15 jpff * OOps/diskin.c (sndo1set): Deprecate soundout in favour of fout 2008-03-23 jpff * Top/argdecode.c (decode_long): Change incorrect %n to %d (shades of BCPL) 2008-03-18 jpff * Opcodes/Vosim.c: New file and opcode 2008-02-27 jpff * Opcodes/vbap.c (localops): Changed vbap* to gave a k-rate last required arg. 2008-03-16 jpff * H/version.h: 5.08.2 2008-03-08 Anthony Kozar * H/prototyp.h: * Top/argdecode.c: * Top/main.c: * Top/one_file.c (readOptions, read_unified_file): readOptions() only prints "missing " message when reading from CSD file. 2008-03-02 Michael Gogins * SConstruct, csoundd.nsi: Many changes to enable building and installing Csound built with MSVC 2008 or MinGW 4.2.1 * CsoundAC: Build as static library to try to work around problem with MSVC corrupting data in C++ classes exported but based on non-exported STL classes. * API Reference: Updated to reflect recent changes. 2008-02-23 Michael Gogins * InOut/widgets.cpp: Fixed a major bug in which the Csound memory manager (C style) was allocating and deallocating a C++ structure (WIDGETS_GLOBALS). If new is not called for WIDGETS_GLOBALS, the constructors of its std::vector collections are not called. Then in the widget csoundDestroyModule function, invalid vectors are iterated, causing an access violation. Fixed by using standard C++ new and delete for the structure to ensure proper creation of its vector members. This is OK because by calling csoundModuleInit and csoundModuleDestroy, Csound is permitting the module to manage its own memory. The code accessed FLTK flags as a value when the flags had not been initialized as a global variable. This caused an access violation in csoundModuleDestroy. The code has been changed to get the flags as a pointer, and only dereference the pointer if it is not null. * Opcodes/vst4cs/src/vst4cs.cpp: Cleaned up csoundModuleDestroy code for Windows MSVC build, which was causing an access violation. 2008-02-22 Michael Gogins * SConstruct: Many changes to enable all features of Csound to build with Microsoft Visual C++ 2008 (MSVC). Also changes to enable build with MinGW 3.4.5/MSys 1.0.11/SCons 0.97. * custom-mingw.py, custom-msvc.py: Rationalized locations of third-party libraries in network mounted "U:/" drive root directory. * Frontends/CsoundAC/Counterpoint.cpp: Many changes to enable MSVC compilation. * CsoundVST: Renamed CsoundVST.exe to CsoundVstShell.exe to enable MSVC build. Exported new RunCsoundVST function to enable CsoundVstShell to run with MSVC build. * Engine/sread.c (nested_repeat, do_repeat, sread, etc.): Renamed struct in_stack_s to avoid debugging conflict with rdorch.c. Fixed some endless loops caused by the 'm' and 'n' statements. Prevented 'm' and 'n' statements from eating next line. Fixed line counts when using 'm' and 'n'. nested_repeat() does not need to change event opcode to 's'. Fixed 'r' repeats to work with optional p1 of 's' and 'e' statements. '{' statement should not reset clock_base, warp_factor, or prvp2. 2008-02-01 Anthony Kozar * H/version.h (CS_APISUBVER): Increased to 6 for Csound 5.08. * Top/getstring.c: Added stub for csoundSetLanguage(). 2008-01-31 Anthony Kozar * H/csound.h (CSOUND_FILETYPES): Added CSFTYPE_IMAGE_PNG. * Opcodes/imageOpcodes.c (__doOpenImage, __doSaveImage): Use FileOpen2() and FileClose() instead of fopen() and fclose(). Other minor fixes. 2008-01-30 jpff * retagged 5.08b 2008-01-29 veplaini * Opcodes/hrtfopcodes.c: New HRTF opcodes by Brian Carty * Opcodes/syncgrain.c: fixed bug in period counter preventing accurate tuning of grain frequency * SConstruct: added token NOGETTEXT to useGettext=0 option 2008-01-29 jpff * H/dumpf.h: Commented out the interpolation argument as not implemented. 2008-01-29 Anthony Kozar * Top/one_file.c (readOptions, checkVersion, etc.): Fixed version checks; prevented crashes in readOptions(), and improved error reporting for CSD. 2008-01-27 Anthony Kozar * Top/one_file.c (read_unified_file, checkLicence): Added as an acceptable alternate spelling of . 2008-01-27 jpff * version 5.08Beta * installer/linux/installer.fl: * installer/linux/new_install.cxx: Added support for installing locales 2008-01-22 Anthony Kozar * Top/argdecode.c (decode_long): Added --csd-line-nums= option. 2008-01-21 Anthony Kozar * Engine/sread.c (scorerr, sreaderr, getscochar, sread, getpfld, etc.): Major changes to score error reporting; now accurately reports the line numbers for the chain of inputs for most errors. Many error messages were changed to avoid redundancy and for clarity. 2008-01-20 Anthony Kozar * H/csoundCore.h (CSOUND): * Top/csound.c: * Top/main.c (csoundCompile): Save the original CSD file name. * Engine/sread.c (scorerr, sget1): Fixed backtrace of score includes in scorerr() and a possible crash when a #include file is not found. 2008-01-19 Anthony Kozar * H/csoundCore.h (CSOUND): * Top/csound.c: * Top/one_file.c (read_unified_file, etc.): * Engine/rdorch.c (synterr): Count lines while reading a CSD and save the offsets of the orchestra and score; add offset to line numbers reported with errors in the orchestra. (Score yet to be done). 2008-01-13 jpff * Opcodes/pan2.c (pan2): Corrected so it agrees with documentation 2008-01-06 jpff * H/version.h (CS_PATCHLEVEL): If subversion goes up,patchlevelneeds to be reset. 2007-12-27 jpff * Opcodes/imageOpcodes.h: * Opcodes/imageOpcodes.c: New code 2007-12-25 jpff * po/french.po: * po/american.po: Translations * po/csound.po: New; gettext template * Top/getstring.c (init_getstring): Alternative version for GNU gettext version * InOut/widgets.cpp: Correct double negatives in error messages 2007-12-17 * H/csoundCore.h (CSOUND): added fields delayederrormessages and printerrormessagesflag and reduced number of dummies * Top/csmodule.c (csoundLoadExternal): Store messages about non-modules * Top/csound.c (csoundPreCompile): Print delayed messages at end if any and in API version * Top/main.c (csoundCompile): If delayed messages print after arg decode 2007-12-15 jpff * Opcodes/pvsband.c (pvsbrej): New opcode for band reject 2007-12-14 Anthony Kozar * Opcodes/shape.c: Added unipolar option to pdclip, pdhalf, and pdhalfy, making it the default. 2007-12-11 Anthony Kozar * Engine/sread.c (ifa, getpfld): New "no-carry" operator (!) for score language that prevents implicit carrying of p-fields in i-statements. (eg. i 2 1 1 4.0 ! will only have 4 p-fields regardless of whether previous i2 statements had more). 2007-12-11 jpff * H/version.h (CS_PATCHLEVEL): 3 * Opcodes/pvsband.c: New code * Opcodes/pvs_ops.c (csoundModuleInit): Initialise pvsband 2007-12-06 Anthony Kozar * SConstruct: * Opcodes/shape.c: New opcodes powershape, polynomial, chebyshevpoly, pdclip, pdhalf, pdhalfy, and syncphasor. 2007-12-03 Anthony Kozar * Engine/sread.c (sread, flushlin, getpfld): Improved line counts for error reporting (still much to do though). Fixed some potential buffer overflows. Fixed {} repeat opcodes and improved their parameter reading (similarly to previous changes for 'r' statement). Now flushing rest of line after finding an illegal character in getpfld(). 2007-11-30 jpff * Opcodes/pvsbasic.c (pvsscale): Improved algorithm for SDFT case so no ampltitude variation 2007-11-29 Anthony Kozar * Top/argdecode.c (argdecode, decode_long): * Top/main.c (csoundCompile): * Top/csound.c (const cenviron_): * Engine/otran.c (otran): * H/csoundCore.h (struct OPARMS): Added --check-syntax-only commandline flag (exclusive with --i-only). otran() and csoundCompile() return early when just checking syntax. --i-only sets --nosound same as -I Added initial value for numThreads to OPARMS. * Top/one_file.c (read_unified_file): CSD read should fail when no tag found so that performance is aborted. * Ops/str_ops.c (getcfg_opcode): Added mac_classic case for host OS name. 2007-11-21 Anthony Kozar * Opcodes/sfont.c: Corrected code for C89 (all declarations at top). 2007-11-07 Felipe Sateler * H/csound.h,frontends/csladspa/csladspa.cpp,interfaces/CsoundFile.hpp, interfaces/filebuilding.h * SConstruct (CheckGcc4): Added stuff to limit visibility of symbols 2007-10-01 jpff * VERSION 5.07 2007-09-30 jpff * OOps/goto_ops.c (turnoff2): Patch from Jonathan Murphy in mode4 case * OOps/pstream.c (pvscross): SDFT support 2007-09-29 jpff * OOps/ugens1.c (xsgset2, xsgset): Allow negative amd zero length segments 2007-10-03 Michael Gogins * Updated Windows installers to current versions: libsndfile, PortAudio, Fluidsynth, Synthesis Toolkit in C++. * Restored Synthesis Toolkit in C++ Csound opcode wrappers for native STK C++ code, as STK now has BSD-type license. * Convenience wrappers in high-level CsoundAC.Composition class for Csound.Score.arrange(), csnd.CppSound.setOrchestra(), and csnd.CppSound.setScoreHeader(), for more intuitive use of CsoundAC with Csound. * Updated Csound API documentation to reflect splitup between CsoundAC and CsoundVST. 2007-09-28 jpff * Opcodes/pan2.c: New code * Opcodes/pvsbasic.c (pvsoscprocess): Added SDFT support 2007-09-21 jpff * Opcodes/pvsbasic.c: Added tests all over to warn if the same f-signal is used as in and out in the same opcode 2007-09-20 jpff * Opcodes/pvsbasic.c (pvsblurset, pvsblur): Added SDFT support 2007-09-19 jpff * Opcodes/pvsbasic.c (pvsfilterset, pvsfilter): Added SDFT support 2007-09-18 jpff * Opcodes/pvsbasic.c (pvsmix): Added SDFT support 2007-09-17 jpff * Opcodes/pvsbasic.c (pvsmoothprocess): Added SDFT support; also a-rate parameters is wanted 2007-09-09 jpff * Made SDFT dependent of SDFT macro and adjust SConstruct to set it * Opcodes/pvsbasic.c (pvsshift, pvsscale): Added SDFT support 2007-09-08 jpff * Opcodes/pvsbasic.h (_pvsfreez): Remove unused lastfreq 2007-08-28 Steven Yi * InOut/rtwinmm.c: midi_in_close had incorrect check causing device not to be closed properly 2007-09-06 jpff * Opcodes/pvsdemix.c (pvsdemix_init): Added (under BETA) support for streamed SDFT. * Opcodes/pvsbasic.h (_pvsfreez): Added field in SDFT case * Opcodes/pvsbuffer.c (pvsbufreadset, pvsbufferset): Added (under BETA) support for streamed SDFT. * Opcodes/pvscent.c (pvscentset, pvscent, pvsscent) (pvspitch_init): Added (under BETA) support for streamed SDFT. Includes a-rate opcode for pvscent * Opcodes/pvsbasic.c (pvsinit, pvsfwriteset, pvsdiskinset) (pvsfreezeset, pvssfreezeprocess, pvsfreezeprocess, pvsoscset) (pvsbinprocess, pvsbinprocessa, pvsmoothset, pvsmixset, pvsmix) (pvsfilterset, pvsscaleset, pvsshiftset, pvsshift, pvsblurset) (pvstencilset, pvstencil): Added (under BETA) support for streamed SDFT. Includes a-rate opcode for pvsbinprocess * OOps/pvsanal.c (pvssanalset, pvsanalset, pvssanal, pvsanal) (pvsynthset, pvssynth, pvsynth): Added (under BETA) support for streamed SDFT * H/pstream.h: Added (under BETA) support for streamed SDFT. Changes to PVSDAT and PVSANAL 2007-08-31 Anthony Kozar * OOps/aops.c: * Engine/entry1.c: * H/entry1.h: Added new value conversion functions to convert from Midi note number to Csound's three pitch formats (cpsmidinn, pchmidinn, and octmidinn). 2007-08-28 Steven Yi * Opcodes/fluidOpcodes/fluidOpcodes.c: modified fluidEngine opcode to take optional number of channels (range 16-256, default to 256) and polyphony (range 16-4096, default to 4096) to use. 2007-08-21 Steven Yi * Opcodes/fluidOpcodes/fluidOpcodes.c: added new fluidSetInterpMethod opcode that wraps fluidSynth's fluid_set_interp_method API method; allows user to choose interpolation method from 0 (none), 1 (Linear), 4 (4th order, default), and 7 (7th order, highest quality) on a per channel basis 2007-08-21 * Opcodes/sfont.c: removed all global static variables 2007-08-16 * SConstruct: Separate Word64 (for PIC) and Lib64 for library name 2007-08-14 * SConstruct: Use .Program rather than .Command in cseditor 2007-07-24 Michael Gogins * Folded all NSIS windows installer scripts into one script, csoundd.nsi. See the top of this script for command-line options to build float sample or double sample versions of Csound, or to omit or include non-free software components. The script automatically detects Python, and can install Python if it is not available; if Python is not available, copies Python features of Csound to a backup directory. * Renamed some example .csd files for greater clarity. * Improved GUI for CsoundVST. * Updated the Csound reference manual for the new installer script, CsoundAC, and changes in CsoundVST. 2007-07-28 jpff * Engine/musmon.c (tempset): Cannot set tempo if beatmode not in force 2007-07-24 Michael Gogins * Removed CsoundVST, vst4cs, and stk.dll (the C++ version of the STK opcodes) from the default Windows installers, in order to bring the Windows installers into line with SourceForge licensing guidelines. * Moved the "Silence" algorithmic composition classes out of the CsoundVST shared library and into a new shared library, Python extension module, and CVS directory, CsoundAC (for "Csound algorithmic composition"). * Created new NSIS installer scripts that do include CsoundVST, vst4cs, and the STK opcodes as a convenience for those who will build these components from source code. * Speeded up the CsoundAC.Voicelead, CsoundAC.VoiceleadingNode, and CsoundAC.Score class methods that work with chord voicings by using a new algorithm to iterate through all voicings of a chord in a specified by range by adding octaves to the lowest and most compact voicing, instead of building a set of all voicings in memory (which would get much too large for complex chords). 2007-07-13 * util/atsa.c (init_sound): Check to see if no partials (ie silence) and stop 2007-07-12 * Opcodes/ugnorman.c: Added scaling by 0dbfs and some code tidying 2007-07-06 * InOut/rtwinmm.c (csoundModuleCreate): Quieten startup message in line with other modules * Opcodes/ugnorman.c (atsaddnzset): Complain about a negative number of bands 2007-07-05 Michael Gogins * Opcodes/vst4cs: Fixed a bug in the vstnote opcode whereby NOTE OFF messages were scheduled, but not always dispatched. NOTE OFF messages are now both scheduled and dispatched. 2007-07-05 jpff * Opcodes/ambicode.c: Used P type for gains in bformenc. Added negative setup to give "controlled opposites" rather than spherical harmonics. Tidied code to make kbeta explicit in encoding. Other code reworking. * Engine/entry1.c: * Engine/rdorch.c (getoptxt): * Engine/csound_orc_semantics.c (handle_polymorphic_opcode): Added P as k-rate defaulting to 1 2007-06-30 jpff * OOps/goto_ops.c (turnoff2): ip->nxtact can be overwritten in mode 0 so need to remember the value before calling deact 2007-06-24 jpff * OOps/ugens2.c (koscl3): The amplitude was being ignored. Multiply by *p->xamp to fix 2007-06-08 jpff * Opcodes/ugsc.h: * Opcodes/ugsc.c: Make filters work in doubles internally 2007-06-04 jpff * VERSION 5.06 * interfaces/cs_glue.h: Removed as it was empty * Opcodes/grain4.c (grainsetv4): Supress messages if no warnings * H/soundio.h (SF2TYPE): Masked off top nibble with SF_FORMAT_TYPEMASK 2007-06-03 Anthony Kozar * Top/cscorfns.c (cscoreRESET & cscoreFileOpen): Fixed deallocation of SPACE blocks. Clarified some error messages. Searches in INCDIR now when opening extra score files and calls csoundNotifyFileOpened(). 2007-06-02 Anthony Kozar * util/dnoise.c: * util/hetro.c: * util/sndinfo.c: * util/srconv.c: Added calls to csound->NotifyFileOpened() as needed. * Opcodes/fout.c (fout_open_file): Changed FileOpen() to FileOpen2(), but the result is not ideal yet because we cannot always know the correct file type for files opened with the fiopen opcode. * H/csoundCore.h: * H/csound.h: Added sftype2csfiletype() function pointer to CSOUND. * Opcodes/py/pythonopcodes.c (exec_file_in_given_context): * Opcodes/py/pyx-gen.py: * Opcodes/py/pyx.auto.c: Replaced fopen() call with FileOpen2() in exec_file_in_given_context(), adding a CSOUND* to the function arguments, and updating the pyexec* opcode routines to pass it. * InOut/virtual_keyboard/KeyboardMapping.cpp: * Top/main.c (csoundCompile): Call csoundNotifyFileOpened() if a dummy score file is created. * InOut/libsnd.c (sfopenin & sfopenout): Call csoundNotifyFileOpened() for the primary input and output soundfiles. 2007-06-01 jpff * OOps/diskin2.c (diskin2_init): * OOps/diskin.c (newsndinset): Supress warning messages when no warnings requested * Top/csound.c (kperf): Restore other way of running chain. Unsafe in presence of delete but needed in turnoff 2007-06-01 Anthony Kozar * Engine/envvar.c (csoundFileOpenWithType): When opening a sound file for reading, replace CSFTYPE_UNKNOWN_AUDIO with actual file type. * InOut/libsnd_u.c (sftype2csfiletype): Ignore endian bits of format. * OOps/sndinfUG.c (getsndinfo): Fixed a small bug in yesterday's changes and worked around opening of PVOC files being reported twice. 2007-05-31 Anthony Kozar * H/csoundCore.h: * H/csound.h: Moved CSOUND_FILETYPES enum to csound.h for host and plugin access. Added more file type constants. * InOut/libsnd_u.c: * OOps/diskin.c * util/mixer.c: * util/scale.c: * util/xtrct.c: type2csfiletype() now does more audio formats and uses sample-encoding information to distinguish between AIFF and AIFC. * H/csound.h: * H/csoundCore.h: * H/prototyp.h: * Engine/memfiles.c: * Top/csound.c: * OOps/ugens3.c: * OOps/ugens5.c: * Opcodes/hrtferX.c: * Opcodes/scansynx.c: * Opcodes/ugens9.c: * Opcodes/ugnorman.c: * util/het_export.c: New API function pointer ldmemfile2() to replace ldmemfile(). Takes an additional parameter for the type of file being opened. Updated all calls to ldmemfile() to use ldmemfile2() instead. New API function pointer NotifyFileOpened() that calls the FileOpenCallback when set. * InOut/winEPS.c: * Opcodes/ftgen.c: * Opcodes/sfont.c: Replaced fopen() calls with FileOpen2(). * Top/main.c: * Top/one_file.c * Engine/musmon.c: * Engine/rdorch.c: * OOps/sndinfUG.c: * Opcodes/Loris/lorisgens5.C: * Opcodes/fluidOpcodes/fluidOpcodes.c: Added calls to csoundNotifyFileOpened() after uses of fopen() within Csound. Added csound->NotifyFileOpened() to fluidLoad and lorisread. lorisread now looks in SADIR for input files. Tracks whether orc and sco files are temporary files. * Top/cscore_internal.c: * Top/csound.c: * H/prototyp.h: Rename internal cscore function to cscore_() to avoid linker warnings for duplicate symbol with standalone cscore programs. 2007-05-30 jpff * Top/argdecode.c (decode_long): Correct string length count in --m-warnings and a few others 2007-05-27 jpff * OOps/aops.c (MOD): Changed to non-integer values can be returned -- reverting to pre Feb2007 version but better code 2007-05-17 Andrés Cabrera * InOut/widgets.cpp, InOut/widgets.h: Added FlslidBnk2, FlvslidBnk, FlvslidBnk2, by Gabriel Maldonado 2007-05-14 Andrés Cabrera * InOut/widgets.cpp, InOut/widgets.h, Opcodes/gab/hvs.c, Opcodes/gab/newgabopc.c, Opcodes/gab/sliderTable.c, Opcodes/gab/tabmorph.c: Added new opcodes from CsoundAV by Gabriel Maldonado: hvs1, hvs2, hvs3, vphaseseg, inrg, outrg, lposcila, lposcilsa, lposcilsa2, tabmorph, tabmorpha, tabmorphak, tabmorphi, trandom, vtable1k, slider8table, slider16table, slider32table, slider64table, slider8tablef, slider16tablef, slider32tablef, slider64tablef, sliderKawai and an a-rate version of ctrl7. * Opcodes/gab/vectorial.c,Opcodes/gab/vectorial.c: Added new optional isize argument to vrandh and vrandi for more similarity with randh and randi 2007-05-02 Michael Gogins * ScoreGen.dll can now act as a MIDI effect as well as a VST plugin that can send MIDI events to the host. I.e., ScoreGen can act as a Python-programmable score generator in VST hosts. As a MIDI effect, ScoreGen can "freeze" generated events into a MIDI part for manual editing or notation, using Cubase's "Free MIDI Modifiers" command. * A number of serious bugs were fixed in ScoreGen's VST event processing. It will now properly play generated scores. 2007-05-07 jpff * Opcodes/pitch.c (pitchset): Do not change parameters! * Opcodes/partikkel.h: * Opcodes/partikkel.c: Remove failed attempt at aliasing-prevention that might result in segfaults or hangs when using kdist. Small optimisations. Some cosmetic stuff. 2007-05-04 * util/het_export.c (het_export): Improved error checks as suggest in bug report 2007-05-02 Michael Gogins * Updated the csnd and CsoundVST Python extension modules to be compatible with Python version 2.5. * Split all SWIG-generated Python stub code off into shared libraries _csnd.pyd and _CsoundVST.pyd. * All remaining code from the old _csnd.dll and _CsoundVST.dll is now in csnd.dll and CsoundVST.dll. * Many classes and functions in CsoundVST are now exported so that they can dynamically link with _CsoundVST.pyd. * "Glue" code for message buffers, etc. has been moved into the csound.h and csound.c files. 2007-04-29 Anthony Kozar * Engine/envvar.c, Engine/fgens.c, Engine/memfiles.c, * Engine/new_orc_parser.c, Engine/rdorch.c, Engine/sread.c, H/csound.h, * H/csoundCore.h, H/envvar.h, H/prototyp.h, H/soundio.h, InOut/libsnd_u.c, * InOut/midifile.c, InOut/midisend.c, OOps/diskin.c, OOps/diskin2.c, * OOps/dumpf.c, OOps/pvfileio.c, OOps/sndinfUG.c, Top/argdecode.c, * Top/csound.c, Top/main.c, Top/one_file.c, util/atsa.c, util/cvanal.c, * util/hetro.c, util/lpanal.c, util/mixer.c, util/pvanal.c, util/scale.c, * util/xtrct.c: New API function pointer FileOpen2() to replace FileOpen(). Takes additional parameters for the type of file being opened and whether it is a temp file. This information (along with filename, etc.) is passed to a new host callback that can be set with csoundSetFileOpenCallback(). Updated most uses of FileOpen() to use FileOpen2() instead. 2007-04-28 Anthony Kozar * Opcodes/ampmidid.cpp: #include "OpcodeBase.hpp", not . * Top/csound.c (kperfThread): * Top/main.c: * Opcodes/gab/vectorial.c (vrand*): Move declarations before other code and kperfThread() should return unsigned long instead of int. 2007-04-22 Michael Gogins * Corrected the logic in the CsoundVST ImageToScore class. * Added support for PNG and JPEG formats to the ImageToScore class. 2007-04-19 jpff * Opcodes/partikkel.h: * Opcodes/partikkel.c: New code from Oeyvind 2007-03-24 jpff * H/version.h (CS_APISUBVER): Increase * Top/csound.c: * Top/argdecode.c: * H/csoundCore.h: Rearrange code on sr/kr override 2007-03-19 Andrés Cabrera * Fixed vrandh and vrandi scaling problems and added optional idstoffset, iseed and ioffset arguments 2007-03-12 Andrés Cabrera * Added preliminary support for vst4cs on linux 2007-03-12 jpff * Opcodes/system_call.c (localops): system was not called at k-rate 2007-03-11 Andrés Cabrera * Added Plastic look for FLslider, FlslidBnk, FLbutton and FLbutBnk 2007-03-07 jpff * VERSION 5.05 2007-03-04 Steven Yi * Engine/sread.c: Applied patch from John McCullough from SourceForge bug 1666632 "Heap Overflow in Marker Parsing" 2007-02-18 Steven Yi * Opcodes/dam.{c.h}: Moved initialization code of power buffer to performance time function as it depends on krate var (kthreshold) 2007-02-17 jpff * OOps/aops.c (MOD): Attempt to fix bad code in MOD 2007-02-14 jpff * Top/cscore.c: Top/cscormai.c: Removed old code 2007-02-13 Anthony Kozar * Top/cscorfns.c: cscoreCopyEvent() was writing past the end of the EVENT struct. Also added new static atEOF to fix an infinite loop caused by a change in the behavior of rdscor(). * Top/cscormai.c: * Top/cscore.c: Moved to frontends/cscore/ * examples/cscore/: Added a number of examples of using Cscore. * util1/cscore/: Removing this directory as it is obsolete. 2007-02-13 jpff * Opcodes/fm4op.h (TwoPole): Not used 2007-02-02 jpff * Opcodes/pitch.c (trnset): Fixed bug in allocation 2007-01-26 jpff * Opcodes/gab/vectorial.c (vexpv_i): Aparent typo used uninitialied variable 2007-01-25 jpff * Opcodes/butter.c: Optimisations and accuracy improvements. Also deleted butter.h and incorporated into source 2007-01-16 Steven Yi * InOut/widgets.cpp (csoundModuleDestroy): wrapped deinit code with a check to see if widgetGlobals is not NULL (was causing segfault when running "csound" or "csound --help") 2007-01-15 Steven Yi * Manually merged in work from New Parser branch; to compile, must enable in build using buildNewParser=1; to use at runtime, use --new-parser flag; notes added to To-fix-and-do file; added tests directory for use with testing new parser (python scripts) 2007-01-15 jpff * Opcodes/wave-terrain.c (wtinit): No need to copy tables * Opcodes/scansyn.c (scsnu_initw): Initialise x2 and x3 as in scansynx 2007-01-07 Anthony Kozar * OOps/remote.c (remoteport): Stub version for platforms without sockets. * SConstruct: Use sys.byteorder to set flags for sfonts and STK opcodes. 2007-01-07 Steven Yi * Engine/envvar.c (csoundGetDirectoryForPath): added call to csoundConvertPathname at top of function to fix bug on Windows where path's with forward slashes were causing segfaults (Recommended by Anthony Kozar on Dev list) 2007-01-07 jpff * Engine/entry1.c: Allow printf and printf_i not have zero arguments after trigger (reverted as causes other problems) * Opcodes/system_call.c: new code 2006-12-02 Michael Gogins * Completed implementation of algorithmic composition helper classes for voice-leading and chord progression in CsoundVST: Voicelead, VoiceleadingNode, Conversions, and Score. These implement orthogonal arithmetical operations for changing interval structure ('prime chord' or P), chord transposition ('transposition' or T), and voicing or inversion within a range ('voicing' or V), as well as arithmetic upon pitch-class set numerals ('Mason number' or M). These operations can be used both to generate scores, and to filter existing scores. 2006-12-23 jpff * InOut/widgets.cpp (save_snap): fl_ask() is depricated so replace by fl_choice() 2006-12-14 jpff * Opcodes/pitch0.c (pfun): Commented out printing 2006-12-02 Michael Gogins * Added CppSound::getInstrumentNames() to return a map of instrument numbers to names for a loaded Csound orchestra. * Added ampmidid opcodes, which map MIDI velocity variable to peak amplitude using the method of Dannenberg (ICMC 2006), according to a user-specified dynamic range in dB. 2006-11-28 Steven Yi * InOut/virtual_keyboard: Modified FLvkeybd to take in width and height, make keyboard resizable 2006-11-26 Steven Yi * InOut/virtual_keyboard: Added FLvkeybd opcode to embed virtual keyboard into FLTK Widget panel; only one allowed per project; useful for demo versions of MIDI orchestras 2006-11-25 Steven Yi * InOut/widgets.cpp: Added FLcloseButton and FLexecButton opcodes; closeButton closes the window panel it is a member of, while execButton runs a command given to it 2006-11-16 jpff * OOps/diskin.c: (and many others) * OOps/remote.c: Use InitError correctly 2006-11-15 Steven Yi * InOut/virtual_keyboard: Added 10 MIDI Sliders to virtual keyboard 2006-11-13 jpff * OOps/remote.c (remoteport): New opcode to set remote port * install.py: Added cseditor to package system 2006-11-09 jpff * VERSION 5.04 2006-10-29 Simon Schampijer * OOps/remote.c: Added the patch from Dan Williams which: 1) Fixes detection of the IP address by correctly converting the uint32 to a string format using inet_ntoa() on Linux. There was something wrong with the manual conversion code that was there which caused only the last octet to be recognized, which meant the remote plugin was mismatching the IP addresses and playing everything locally. I have no idea why it worked before, but my patch is clearly correct (to me at least!) 2) fixes up error handling on plugin init; If the machine runs out of memory while starting the remote plugin, it should return an error in callox() so that CSound is alerted to the error as well. Furthermore, if detection of the local IP address fails for any reason, the plugin should fail to initialize. 2006-10-27 David Akbari * frontends/cseditor/*: * SConstruct: Added build options and targets for basic Csound syntax highlighting text editor that uses FLTK. 2006-10-27 Anthony Kozar * H/sysdep.h: #define for inline with Metrowerks CodeWarrior compiler. * OOps/remote.c: Removed troublesome inline declarations. 2006-10-27 Steven Yi * InOut/virtual_keyboard/*: * SConstruct: Added new FLTK virtual keyboard MIDI driver; enable use by using "-+rtmidi=virtual -M0"; sends MIDI notes in the same way as any real MIDI device; useful for testing and in situations without MIDI gear; still needs a little work 2006-10-26 Anthony Kozar * SConstruct: Check for socket-related headers and define HAVE_SOCKETS if they are found. * Top/main.c: * Engine/musmon.c: * H/remote.h: * OOps/remote.c: #ifdefed remove events based on HAVE_SOCKETS. Created stub functions for when they are not available. Expanded musmon.c interface to remote.c so that no internal knowledge of remote globals is necessary. Remote opcodes still exist on non-socket builds but print a warning message that remove events are not available. 2006-10-26 Anthony Kozar * Top/main.c: * Engine/namedins.c: * Engine/envvar.c: Couple more fixes for concatenating paths. 2006-10-25 jpff * OOps/midiops.c (pgmin): Added optional channel parameter to restrict watch 2006-10-25 Steven Yi * H/csoundCore.h (OPARMS): * Top/argdecode(decode_long): * Top/main.c (csoundCompile): added command line flags --no-default-paths and --default-paths to disable and reenable using path(s) of CSD/ORC/SCO as part of search paths 2006-10-24 Steven Yi * Top/main.c (csoundCompile): changed CSD/ORC/SCO directory to append instead of prepending search paths 2006-10-24 Anthony Kozar * Top/main.c: * Engine/rdorch.c: * Engine/envvar.c: * H/envvar.h: Many changes & improvements to file searching. - New internal interface for X-platform path manipulation. - CSD/ORC/SCO directory prepended to environment variables instead of appended (so that they are searched later). - Relative paths beginning with "./" or "../" now work when specifying filenames in ORC and SCO. - Many bug fixes to MacOS 9 path manipultion. 2006-10-23 jpff * OOps/midiops.c (pgmin): Make program changes in range 1-128 rather than 0-127 * OOps/remote.c (insremot): Need to check csound->remoteGlobals before access 2006-10-22 jpff * OOps/midiops.c: Added pgmchn opcode * Engine/entry1.c: Midiin was not being initialised; also added pgmchn opcode 2006-10-21 jpff * Opcodes/harmon.c: New code from Barry Vercoe 2006-10-19 Steven Yi * Top/main.c (csoundCompile): now adds directory of CSD, or ORC and SCO to INCDIR, SADIR, SSDIR, and MFDIR; SCO path's are currently added before ORC path * Engine/envvar.c (csoundGetDirectoryForPath): New function added to find absolute path given a path as string 2006-10-19 jpff * frontends/winsound/main.cxx (cs_compile_run): If orchname starts with / or \\ change directory to location 2006-10-19 Anthony Kozar * H/cscore.h: Fixed Cscore includes. * Top/csmodule.c: Now searches for & auto-loads plugins on MacOS 9. 2006-10-18 Steven Yi * Engine/musmon.c (process_rt_event): Fixed to check if remoteGlobals is initialized when processing MIDI events 2006-10-17 * util/pv_import.c (pv_import): Chancge exits to returns and replaced printing to stderr by calls to csound->Message 2006-10-16 Anthony Kozar * H/csound.h: * H/cscore.h: * H/cvgvar.h: Added Mac pragmas to export PUBLIC functions. * util/pv_import.c: Fixed check for failure to open output file. 2006-10-12 Michael Gogins * Added Voicelead class to the Silence system in CsoundVST. It finds the closest voice-leadings first by smoothness, then by parsimony, optionally avoiding parallel fifths, between two sets of pitches. * Added methods to the Score class in the Silence system for identifying the prime chord, transposition of prime chord, and voicing index for segments of scores; setting the same properties in segments of scores; and voice-leading between segments of scores. 2006-10-12 jpff * OOps/remote.c: * H/remote.h: New code for remote performance (OLPC) * Engine/entry1.c: Add opcodes insremot, midremot, insglobal and midglobal * Engine/musmon.c: New code for this * H/csoundCore.h: New fields for remote * InOut/midirecv.c: minor chjange for remote 2006-10-12 Steven Yi * Top/one_file.c (readOptions): fixed parsing of quoted strings 2006-09-24 jpff * Engine/musmon.c (print_maxamp): Allow coloured numbers in raw context as well as dB 2006-09-21 Steven Yi * Opcodes/biquad.c (mode): added mode opcode, a translation of François Blanc's mode UDO to C 2006-09-20 jpff * Opcodes/sfont.c (SfLoad): Allow string or number and strset code for file 2006-09-18 Steven Yi * Opcodes/flanger.c (wguide2set): fixed wguide2, code was looking at wrong arguments for xincod values, also check for comparison between the two xincod's was incorrect 2006-09-16 Michael Gogins * Added plugin SDK to Windows installers. 2006-09-15 jpff * util/lpcx_main.c: * util/lpci_main.c: * util/heti_main.c: Simpler versions that do not depend on all of csound for stand-alone versions 2006-09-12 jpff * Engine/sread.c (sread): isdigit is faster than strchr * Engine/insert.c (xinset): strings as arguments (xoutset): Ditto * Engine/otran.c (parse_opcode_args): Tracking strings as UDO arguments 2006-09-12 Steven Yi * Renamed Opcodes/avarops.c to Opcodes/vaops.c, renamed avar_get and avar_set opcodes to vaget and vaset (as requested on Csound list) 2006-09-09 Michael Gogins * Removed Loris from Windows installers as new versions do not run on Windows, and ATS opcodes are similar. * Upgraded LuaJIT to version 1.1.0 for Windows installer. * Upgraded libsndfile to version 1.0.17 for Windows installer. * Added information on Csound syntax coloring for SciTE to tutorial. * Added high-resolution versions of trapped.csd and xanadu.csd. 2006-09-08 Steven Yi * Engine/rdorch.c (rdorchfile, init_math_constants_macros): added math constants found in math.h as a default set of macros (M_PI is $M_PI, etc.) 2006-09-04 Steven Yi * Opcodes/avarops.c: added avar_get and avar_set opcodes to read from and write values to a-rate variables at k-rate 2006-08-28 jpff * Opcodes/newfils.c (moogladder_process): Minor optimisation (loop invariant) 2006-08-25 jpff * Engine/insert.c (delete_instr): Allowed named instruments as well 2006-08-23 veplaini * frontends/tclcsound/commands.c, tclcsound.h: added pvs bus channel interface to tclcsound. Not tested yet. Manual pages for all new opcodes have also been added. 2006-08-23 jpff * Opcodes/biquad.c (tbvcf): Use doubles inside filter * util/atsa.c: All over removed compiler warnings -- mainly missing casts and inappropriate use of floor 2006-08-23 veplaini * csoundCore.h, csound.h, bus.h, bus.c, csound.c, entry1.c : pvs bus now called pvsin/pvsout. * csound.hpp: added a user-friendly interface to pvsin/out * disprep.*, entry1.c: added pvsdisp opcode * pvsbasic.*: added pvsbin, pvsosc and pvsfwrite opcodes * pvscent.c: added pvspitch opcode by Alan OCinneide Manual pages to follow 2006-08-22 jpff * Opcodes/biquad.c (moogvcf, rezzy): Minor optimisations 2006-08-21 jpff * util/lpanal.c (polyzero): Replace pow(..,2.0) by direct calculation twice * SConstruct (stdutilSources): Added build of pv_import/export utilities * Engine/insert.c: Include delete in non-Beta version * util/pvi_main.c, util/pvx_main.c: New code 2006-08-20 veplaini * csoundCore.h, csound.h, bus.h, bus.c, csound.c, entry1.c : added fsig to chani/chano bus interface (now called pvsin/pvsout). * csoundCore.h: commented out redefinition of printf to eliminate warnings (on OLPC build) 2006-08-17 jpff * Top/csmodule.c (csoundLoadExternal): Even if not BETA display the reason that a module failed to load rather than -1 2006-08-15 jpff * Version 5.03 released 2006-08-11 Andres Cabrera * opcodes/Gab/vectorial.c: Added kverbose optional argument and other bug fixes. 2006-08-07 Andres Cabrera * opcodes/Gab/vectorial.c: Added optional arguments isrcoffset and idstoffset to most vectorial opcodes. * opcodes/Gab/vectorial.c: Added i-rate versions of most vectorial opcodes. 2006-07-30 jpff * util/cvanal.c (cvanal): Added termination message 2006-07-27 jpff * Opcodes/biquad.c (moogvcfset): Corrected mind error (divide and divide). Thanks to IV 2006-07-26 jpff * Opcodes/biquad.c (moogvcfset, moogvcf): Allow for scaling to 0dbfs and improve accuracy of filter by using doubles. (rezzyset, rezzy, bqrezset, bqrez): Use doubles in filter 2006-07-21 Michael Gogins * Added new long options for routing MIDI note on message key and velocity numbers to specified pfields: --midi-key=, --midi-key-cps=, --midi-key-oct=, --midi-key-pch=, --midi-velocity=, --midi-velocity-amp=. * Added tutorial LaTeX file tutorial/tutorial.tex. 2006-07-19 Victor Lazzarini * Opcodes/sndloop.c: added flooper2 opcode * Opcodes/syncgrain.*: added syncloop opcode Manual pages also added to cvs * frontends/tclcsound/commands.c: removed -d flag, added csPlayAll command, fixed csCompilelist bug. 2006-07-18 jpff * frontends/csound/sched.c (set_rt_priority): Comment out the check to see if running as root. Will fail later perhaps if cannot set priority. 2006-07-16 jpff * Top/one_file.c (readOptions): Remove trailing spaces in input 2006-07-12 jpff * Opcodes/nlfilt.c (pcount, pvalue): New opodes after IV suggestion * Opcodes/pitch.c (pitchset): Moved some filter coeffieients to double 2006-07-08 jpff * H/csoundCore.h: Removed unused macros and typedefs * Opcodes/physmod.c (make_DLineA): * Opcodes/physutil.c (make_DLineL): No need to zero allocated array * Opcodes/vst4cs/src/vst4cs.cpp: **EXPERIMENTAL** try to make programs 1-16 * Opcodes/osc-sock.c (osc_send_set, oscInitUDP): Use memset rather than deprecated bzero 2006-07-07 Istvan Varga * Engine/entry1.c: corrected opcode data size for inh and ino * Opcodes/bilbar.c (play_pp): use fabs() instead of abs() * Opcodes/biquad.c (nestedapset): do not assume sizeof(MYFLT) == sizeof(long) 2006-06-30 jpff * OOps/midiops.c: * OOps/ugrw1.c: * Opcodes/oscbnk.c: * Opcodes/physmod.c: * Opcodes/uggab.c: * Opcodes/wave-terrain.c: Similar changes to previous 2006-06-30 Istvan Varga * Opcodes/vbap_*.c (vbap_*): Replace 1/ksmps by the precomputed value 2006-06-28 jpff * Opcodes/vst4cs/src/: Many changes bringing code closer to Istvan's fork 2006-06-27 jpff * OOps/cmath.c (exprand): (biexprand): Restored safety checks for negative argument 2006-06-26 jpff * util/pv_import.c: Inverse of pv_export * util/pv_export.c: Code to convert .pvx file to comma-separated text, as a utility 2006-06-23 Istvan Varga * Opcodes/loscilx.c: experimental new opcodes: loscilx, sndload 2006-06-23 jpff * OOps/disprep.c (tempest): If we are in a mask situation retain previous best estimate of tempo 2006-06-18 Istvan Varga * OOps/sndinfUG.c: filelen, filenchnls, filesr opcodes: allow for getting parameters of convolve and PVOC files unless the "enable raw files" flag is zero 2006-06-17 Istvan Varga * OOps/ugens2.c: allow inconsistent table index and output type in table read opcodes if ksmps is 1, but print a warning message 2006-06-16 Istvan Varga * Engine/rdorch.c: experimental implementation of nested #ifdef/#ifndef and #else 2006-06-15 jpff * util/hetro.c (init_het): skip was not initialised 2006-06-15 Istvan Varga * Engine/rdorch.c: added #ifndef * InOut/libsnd_u.c: more quietening of messages 2006-06-14 Istvan Varga * Made messages less verbose in soundin, diskin, diskin2, and sfpassign. * Engine/otran.c: fixed (hopefully) incorrect offset calculation of string variables 2006-06-13 Istvan Varga * New API functions: csoundSetCallback(), csoundRemoveCallback() * OOps/bus.c: sensekey opcode: use new callback interface * H/version.h: updated API version to 1.02 * InOut/widgets.cpp: experimental implementation of sensekey using FLTK (activated with a new optional argument to FLpanel; only one window can receive keyboard events) 2006-06-12 jpff * InOut/midifile.c (csoundMIDIFileOpen): Added MFDIR 2006-06-11 Istvan Varga * Updated version to 5.03.0 beta. * Opcodes/midiops2.c: new opcode: ipgm midipgm [ichn] 2006-06-10 * Csound 5.02.1 release 2006-06-10 Istvan Varga * Engine/sread.c: fixed parsing of score expressions * OOps/aops.c: fixed memory access errors and string channels with numeric channel ID in invalue and outvalue * frontends/winsound/main.cxx, frontends/CsoundVST/CsoundVST.cpp: minor fixes * frontends/fltk_gui/CsoundPerformance.cpp: fixed bug related to display callbacks 2006-06-09 Istvan Varga * OOps/bus.c: Added new optional output argument to sensekey opcode. * Engine/rdorch.c: Made excess number of output arguments a syntax error, rather than silently ignoring them. 2006-06-04 Michael Gogins * Changed the MIDI interoperability opcodes (OOps/midiinterop.c) midinoteoncps, midinoteonoct, midinoteonpch to leave key and velocity unchanged for score-driven performance. 2006-06-04 * Csound 5.02 release 2006-06-04 Istvan Varga * Engine/otran.c: work around constndx() not being compiled correctly 2006-06-03 Istvan Varga * Engine/fgens.c, InOut/libsnd_u.c, OOps/diskin.c, OOps/diskin2.c: GEN01, diskin, diskin2, soundin: with an iformat value of -1, reject headerless files, rather than assuming the same format as the one specified on the command line GEN01: added format codes 7 (8 bit unsigned), 8 (24 bit), and 9 (doubles) * Engine/entry1.c, H/sndinfUG.h, OOps/sndinfUG.c: filelen, filenchnls, filesr: added optional i-time argument that defaults to 1, and if zero, will make the opcodes return zero on headerless files rather than some possibly incorrect defaults * Opcodes/fout.c: fixed bug in fini opcode (negative numbers were read incorrectly) * Engine/sread.c, Engine/swrite.c, Engine/twarp.c: fixes to reading numbers in [] score expressions fixed 's' and 'e' score opcodes with time parameter 2006-06-02 Istvan Varga * New string opcodes: Sdst strsub Ssrc[, istart[, iend]] Sdst strsubk Ssrc, kstart, kend ichr strchar Sstr[, ipos] kchr strchark Sstr[, kpos] ilen strlen Sstr klen strlenk Sstr Sdst strupper Ssrc Sdst strupperk Ssrc Sdst strlower Ssrc Sdst strlowerk Ssrc Sval getcfg iopt ipos strindex Sstr1, Sstr2 kpos strindexk Sstr1, Sstr2 ipos strrindex Sstr1, Sstr2 kpos strrindexk Sstr1, Sstr2 * Engine/express.c, Engine/otran.c: fixed parsing of numbers in exponential notation also some parser fixes related to 0dbfs 2006-06-01 Istvan Varga * Added callback interface to the software bus with named channels, using new opcodes chnrecv and chnsend. The callback function can be set with csoundSetChannelIOCallback(). 2006-05-31 jpff * util/sndinfo.c: Added option to print looping information etc. 2006-05-31 Istvan Varga * InOut/widgets.cpp: FLbutton type 1 callback now sets the output to "ion" 2006-05-30 Istvan Varga * Opcodes/fout.c: new opcode: ficlose 2006-05-30 ma++ ingalls * aops.c, aops.h, csound.h: invalue/outvalue updates as per Istvan's comments * csound.c: changed "early return" comments to debug only * hetro.c: added pollevents inside processing loop * lpanal.c: added warning message with -g flag * sockrecv.c: took out usleep() declaration - was causing compile error 2006-05-28 ma++ ingalls * frontends/CsoundX: added to cvs * aops.c, entry1.c, entry1.h, csound.h: added hack to invalue/outvalue to support strings 2006-05-27 Istvan Varga * Added ATS analysis utility. 2006-05-26 ma++ ingalls * frontends/CsoundVST/AEffect.h: commented out 2 PRAGMAS causing compile error on mac * Opcodes/vst4cs/vsthost.c: added plug-in loading for MACH-O mac. commented out #includes that caused compile error on mac * Opcodes/vst4cs/vsthost.h: commented out #includes that caused compile error on mac * Opcodes/vst4cs/fxbank.h: commented out #includes that caused compile error on mac * OOps/aops.c: added i-rate support to invalue/outvalue 2006-05-24 Istvan Varga * InOut/rtalsa.c: changed default device from "default" to "plughw" * InOut/rtjack.c: list available device names for -i adc or -o dac if an invalid device is specified 2006-05-23 Istvan Varga * Opcodes/ugnorman.c: fixed "not initialised" bug in ATSbufread 2006-05-22 Istvan Varga * OOps/midiops.c: massign(): interpret channel number <= 0 as all channels * H/csoundCore.h, Top/csound.c: added new function GetCurrentThreadID() to CSOUND structure 2006-05-21 Michael Gogins * New API function: csoundGetCurrentThreadId() 2006-05-20 Istvan Varga * Opcodes/stackops.c: added new stack opcodes (stack, push, pop, push_f, pop_f); also moved monitor opcode here. * Reworked user defined opcodes to allow for up to 256 input/output arguments. * Opcodes/bilbar.c: removed use of C++ style comments. 2006-05-16 jpff * Engine/entry1.c: Change args of xin to match OPCODENUMOUTS 2006-05-15 Anthony Kozar * Top/cscormai.c: Fixed #includes. * interfaces/CsoundFile.cpp: isspace() is in and supposed to be in std namespace * H/csoundCore.h: Increased OPCODENUMOUTS to 64 as requested. 2006-05-15 Istvan Varga * Opcodes/monitor.c: added new opcode: monitor 2006-05-14 jpff * util/pvlook.c (pvlook): Rewritten for .pvx format 2006-05-13 jpff * util/pvanal.c: Added -B # argument to give a beta to the Kaiser window; still defaults to 6.8 2006-05-12 Istvan Varga * frontends/csound/csound_main.c: overwrite old log files, rather than appending messages 2006-05-08 Istvan Varga * New API functions: csoundCreateMutex, csoundLockMutex, csoundLockMutexNoWait, csoundUnlockMutex, csoundDestroyMutex, csoundRunCommand 2006-05-04 Istvan Varga * InOut/rtalsa.c: added new "devfile" MIDI driver that uses device files in /dev, based on code from Csound 4.23 mididevice.c 2006-05-03 Istvan Varga * InOut/FL_graph.cpp, InOut/widgets.cpp: * InOut/winFLTK.c, InOut/winFLTK.h: added more FLTK flags (see winFLTK.h) 2006-05-02 Istvan Varga * InOut/widgets.cpp, InOut/winFLTK.c, InOut/winFLTK.h: disable threads by default if graphs are used * OOps/sndinfUG.c: filepeak opcode now uses PEAK chunks with libsndfile >= 1.0.16 2006-04-30 Istvan Varga * Attempt to fix thread locks on MacOS X. * util/srconv.c: fixed output amplitude when downsampling allow utility to be stopped by yield callback * install.py, installer/misc/mkpackage.py: install TclCsound command documentation 2006-04-29 Istvan Varga * Made it possible to control the behavior of the FLTK plugin from the host application. This can be done with the following code between calling csoundPreCompile() and csoundCompile(): CSOUND *csound; ... csoundCreateGlobalVariable(csound, "FLTK_Flags", sizeof(int)); *((int*) csoundQueryGlobalVariable(csound, "FLTK_Flags")) = flags; where 'flags' can be the sum of any of the following values: 1: disable widget opcodes 2: disable FLTK graphs 4: disable the use of a separate thread for widget opcodes 8: disable the use of Fl::lock() and Fl::unlock() 16: disable the use of Fl::awake() additionally, after calling csoundCompile(), the same variable can be checked to find out if graphs or widget opcodes are used: 32: FLrun opcode was called 64: callbacks for FLTK graphs are set * Top/main.c: fixed crash on registering opcodes from the host application * frontends/fltk_gui: new GUI frontend that uses the Csound 5 API and FLTK 2006-04-19 Michael Gogins * Updated Lua to version 5.1 (current version), changed lua_example.lua to use Class:method calls. 2006-04-17 John ffitch * Opcodes/bilbar.c: Added prepared piano string model * H/entry1.h: * Engine/entry1.c: Added remove opcode. Probably should be an API function rather than opcode * Engine/insert.c (delete_instr): New code to delete non-active instruments. Still needs to be checked as it may leave structures dangling. 2006-04-15 Istvan Varga * Engine/namedins.c, Engine/otran.c: optimizations in orchestra parser * interfaces/lua_interface.i: wrap cs_glue.hpp and csPerfThread.hpp 2006-04-09 Istvan Varga * Engine/envvar.c: csoundFileOpen(): check for files with .sd2 extension, and use sf_open() in this case if sf_open_fd() fails * InOut/FL_graph.cpp: wait for the window to be closed by the user at end of performance * InOut/libsnd.c: fixes in enabling peak chunks and dithering * InOut/libsnd_u.c: type2string(): added SD2 to file types * InOut/rtpa.c: print warning if the buffer size (-b) is not an integer multiple of ksmps in full-duplex mode * InOut/window.c: moved deferred loading of widgets plugin from main.c to make graphs work in utilities * Opcodes/compress.c: made rms levels relative to 0dBFS in distort opcode * H/csoundCore.h, Top/csound.c: added dispinit() function pointer to CSOUND structure, for use by utilities * H/version.h: updated API version to 1.01 to reflect change to CSOUND structure * util/pvanal.c: implemented graph displays (limited to 30 frames at this time) * util/sndinfo.c: clear SF_INFO structure before calling sf_open() 2006-04-08 Istvan Varga * OOps/sndinfUG.c: restored filepeak opcode 2006-04-07 Istvan Varga * H/version.h: updated version number to 5.02.0 to reflect addition of new opcodes * Opcodes/compress.c: fixed a few minor errors 2006-04-04 Michael Gogins * Changed FluidSynth opcodes slightly, with fluidEngine iChorusOn, iReverbOn pfields, defaulting to "on"; this can reduce noise in low frequencies in SoundFont rendering. * Updated Windows FluidSynth opcodes to use latest FluidSynth sources. 2006-03-28 jpff * Opcodes/compress.c: New code for distort and compress/expander from Barry Vercoe 2006-03-25 Istvan Varga * Engine/entry1.c, H/aops.h, H/entry1.h, OOps/bus.c, opcodes.dir, Opcodes/pitch.c, Opcodes/pitch.h, Opcodes/spectra.c, Top/csound.c: fixes in sensekey opcode 2006-03-22 Michael Gogins * Added ScoreGeneratorVST, a VST plugin for generating scores in VST hosts using Python. * Updated Windows installer for new targets, including Winsound. 2006-03-22 Istvan Varga * interfaces/cs_glue.cpp: * interfaces/cs_glue.hpp: - added new classes to wrap MIDI I/O: CsoundMidiInputStream sends MIDI input messages CsoundMidiOutputStream polls MIDI output messages - added MIDI I/O callbacks to CsoundCallbackWrapper - made it possible to use the message buffer in multiple threads, to allow for redirecting the message output of a CsoundPerformanceThread 2006-03-21 Istvan Varga * SConstruct, Makefile-win32: renamed Csound library to csound{32,64}.dll.5.1 on Windows * SConstruct: attempts to fix install target (still needs a lot of work) * Engine/namedins.c, OOps/bus.c: fixed a-rate channel allocation in user defined opcode with local ksmps * Engine/linevent.c: various minor fixes and code improvements 2006-03-16 Istvan Varga * Updated version number to 5.01.1 beta. * Opcodes/sftype.h: check for MacOS 9 or PowerPC, and define WORDS_BIGENDIAN on those platforms. 2006-03-13 Anthony Kozar * Top/main.c: Made TYP_AIFF the default for MacOS 9. * Engine/entry1.c: Removed duplicate OENTRYs. 2006-03-12 jpff * Opcodes/bilbar.c (bar_run): Corrected boundary condition 2006-03-11 Istvan Varga * Engine/express.c: fixes in extending tokenstring buffer 2006-03-10 Anthony Kozar * Opcodes/minmax.c: * SConstruct: Added new 'minmax' plugin library with opcodes for finding minimum and maximum values among several signals. 2006-03-10 Michael Gogins * CSD style command lines in CsoundVST are now translated to orc/sco style before performance in order to save having to edit the command line after loading some CSD files. 2006-03-08 Istvan Varga * Made it possible to load opcode plugins only when the opcode is actually used. 2006-03-07 jpff * Engine/otran.c: Removed DTYPE and lclnxtdcnt as not used 2006-02-25 Michael Gogins * Updated SConstruct, custom.py, and Windows installer to build and install PortMidi. 2006-02-24 Istvan Varga * InOut/rtjack.c: Use thread locks instead of calling usleep() in a loop to implement blocking I/O; the -+jack_sleep_time option is now deprecated and ignored. Allow non power of two values for -B. Setting -b to the same value as the JACK buffer size is no longer required. * Engine/insert.c: * Engine/musmon.c: Alternate fix to problems on very short (less than 1/2 control period) notes; the previous fix introduced a new bug that resulted in early termination of the score in some cases. * H/version.h: * installer/misc/csound.spec.in: Updated version number from 5.00.1 to 5.01.0 to reflect the addition of new opcodes. 2006-02-24 Victor Lazzarini * Opcodes/psynth.c new track processing opcodes (also added manual pages): trscale, trshift, trsplit, trmix, trfilter, trcross, trhighest, trlowest, binit. 2006-02-15 Istvan Varga * InOut/widgets.h: moved file from H/ * InOut/widgets.cpp: bug fixes in FLsetVal and FLsetVal_i allow buttons and button banks in FLsetVal fixed handle output of FLbutBank (not sure if this is safe) implemented cursor size parameter for FLknob 2006-02-13 Istvan Varga * OOps/ugrw1.c: fixed bugs in i-rate ZAK opcodes 2006-02-09 Istvan Varga * Engine/rdorch.c: splitline(): made checking for invalid characters stricter fixed labels before else/endif allow bitwise NOT operator in UTF-8 format 2006-02-06 Istvan Varga * Engine/entry1.c: cogoto requires an i-rate conditional * Engine/musmon.c: fixed hang on very short note before end of score or section * Engine/rdorch.c: added hacks to fix the problem of the else branch of an if/then/else always being executed at i-time. Fixed crash on 'then' or 'goto' in variable names in conditional expression for if/elseif (still does not work if there are no parentheses around the conditional expression). 2006-02-03 Istvan Varga * Engine/rdorch.c: fixed crash on extra ) in expressions * Engine/rdorch.c: fixed crash on missing whitespace between if/elseif and ( this needs more testing 2006-01-25 Istvan Varga Anthony Kozar * Opcodes/mixer.cpp: "OpcodeBase.hpp", not * Opcodes/py/pythonopcodes.c: Added support for MacOS 9 Python quirks. * H/sysdep.h: MacOS 9 changes so that Python stuff will compile. 2006-01-11 Istvan Varga * fixed temporary file bug on Windows (do not try to remove extension) * new opcodes: chnmix asig, Schn (mixes to audio output channel) chnclear Schn (clears audio output channel at perf time) * allow dot in channel names (but not as first character) 2006-01-04 Michael Gogins * Updated Windows installer script to be compatible with Istvan Varga's zip file layout; also includes vst4cs, csoundapi~, FluidSynth opcodes, CsoundVST, tclcsound, Loris opcodes, STK C++ opcodes. Also includes manual and API reference. Now uses Python 2.4. 2006-01-04 Istvan Varga * changed default output file type to AIFF on MacOS X * added support for writing MIDI output to a file (--midioutfile=FNAME); not really useful, so may be removed later * various fixes related to creating temporary files 2006-01-03 Istvan Varga * added new optional argument to massign (defaults to 1), which, if zero, skips resetting of MIDI controllers * fixed bugs in pan opcode * added support for named instruments to turnon opcode 2005-12-28 jpff * Engine/fgens.c (gen01raw): Restore looping stuff, which requires libsndfile 1.0.13pre3 or later, so protected by BETA still 2005-12-19 John ffitch * SConstruct (else): Added -fPIC again for 64bit machines (else): Fix path for python for 64bit machines * Opcodes/fluidOpcodes/fluidOpcodes.cpp (fluidLoadIopadr): Cast to int to avoid error (csoundModuleDestroy): Ditto 2005-11-12 Michael Gogins * Removed csoundThrowMessage APIs as redundant with csoundMessage, and not used. * Removed strdup and boost from all but CsoundVST. * Fixes in interfaces and frontends/CsoundVST so that CsoundVST works again. 2005-11-03 Istvan Varga * Changed csoundInitialize() to return a positive value if it was already called earlier. 2005-11-01 Istvan Varga * Removed support for Cygwin. * Fixes in Python opcodes. Also implemented a temporary hack in Top/csmodule.c to fix importing modules from Python opcodes on Linux. * installer/linux/csound.spec.in: * installer/linux/makespec.sh: * installer/linux/mkpackage.py: preliminary tools for creating Linux packages 2005-10-31 Michael Gogins * Moved external language interfaces from frontends/CsoundVST into interfaces directory. * Created interfaces for Python, Java, Lua (all "csnd" module). Wraps H/csound.h, H/cfgvar.h, H/csound.hpp, interfaces/CsoundFile.hpp, interfaces/CppSound.hpp. * Moved CLisp interface to interfaces directory. Wraps H/csound.h (csound.lisp) and interfaces/filebuilding.h (filebuilding.lisp). * Modified CsoundVST to work with "csnd" Python module. * Removed Java interface from CsoundVST. * The Java interface in csnd.jar has a rudimentary GUI front end: run with "java -jar csnd.jar". * Other interfaces have test scripts in interfaces directory. 2005-10-25 John ff * SConstruct: Make building interfaces optional 2005-10-05 Victor Lazzarini * Added Tcl/TK frontends (cstclsh and cswish) 2005-10-15 Michael Gogins * Fixed SConstruct to build CsoundVST using Csound as a shared library. * Added csound.lisp FFI for CLisp (experimental). 2005-10-15 Anthony Kozar * Top/csmodule.c: Implemented csoundOpenLibrary, csoundCloseLibrary, and csoundGetLibrarySymbol for platform (mac_classic). 2005-10-13 John ff * InOut/OSCrecv.c: Many changes to allow listening on multiple ports. Uses same patterns though. 2005-10-12 Anthony Kozar * Top/cscorfns.c: cscoreGetEvent(): Check for file closed to avoid loop. csoundInitializeCscore(): Set next->op = '\0'. * Top/one_file.c: createOrchestra(), createScore(): Make messages debug only. * Opcodes/gab/vectorial.c: Fixed small bugs in checking table size. 2005-10-11 Anthony Kozar * H/cscore.h, Top/cscorfns.c, Top/cscore_internal.c: Renamed all Cscore functions that are to be exported in the "Cscore API". Made all of these take a CSOUND* argument if they did not yet. Added some glue for cscoreListPlay() (not done yet though). * H/csound.h, H/prototyp.h, Engine/musmon.c: Added new API function csoundInitializeCscore() to replace internal cscorinit() call. It sets up the input/output files for Cscore and allows a host to function in "standalone Cscore" mode. * Top/cscormai.c: Transformed this main() stub for standalone Cscore processing into a client of the API. (Still needs more work!) 2005-10-09 John ff * Opcodes/psynth.c (psynth2_init, psynth_init): Added cast to unsigned to avoid compiler warnings. Also change && to || as I think that is more likely correct. 2005-10-07 Anthony Kozar * H/csound.h, H/csoundCore.h, Top/csound.c, Engine/musmon.c: Added new API function csoundSetCscoreCallback() for using an external cscore routine. * SDIF/sdif-mem.h: Changed #include "H/sdif.h" to "sdif.h". 2005-10-02 Istvan Varga * restored Tcl/Tk control opcodes * xyin fixes 2005-09-30 Istvan Varga * new API functions for random numbers: csoundRand31(), csoundSeedRandMT(), csoundRandMT() * removed all uses of rand(), csoundRandMT() is used instead in the "x-class" random opcodes and GEN21, and csoundRand31() in all other opcodes that previously used rand() * attempts to get xyin working 2005-09-25 Istvan Varga * frontends/CsoundVST/CppSound.cpp, frontends/CsoundVST/CppSound.hpp: * frontends/CsoundVST/CsoundVST.cpp: * flcsound/synthesizer.cpp: * H/csoundCore.h, H/csound.h, Top/csound.c: removed the following API functions: csoundSetFLTKThreadLocking() (FLTK moved out of libcsound) csoundGetFLTKThreadLocking() (FLTK moved out of libcsound) csoundGetProgress() (was unimplemented) csoundGetProfile() (was unimplemented) csoundGetCpuUsage() (was unimplemented) * InOut/FL_graph.cpp, InOut/widgets.cpp, InOut/winFLTK.c: * InOut/window.c, Makefile-win32, SConstruct: moved FLTK display code from libcsound to the widgets plugin 2005-09-22 Istvan Varga * frontends/csound/csound_main.c: allow logging to file (-O NAME or --logfile=NAME) * frontends/csound/sched.c: --sched can be used in the format --sched=P,C,T now, where the parameters are: P: priority (-20 to -1: nice, 0: normal, 1 to 99: SCHED_RR) C: maximum allowed CPU usage (1 to 99 percents) T: time interval to check CPU usage (1 to 60 seconds) 2005-09-18 Istvan Varga * Engine/namedins.c, H/csound.h: more complete implementation of bus interface (may still need some changes) * Engine/entry2.c, H/str_ops.h, OOps/str_ops.c: new opcodes 2005-09-17 Istvan Varga * Engine/namedins.c: started to implement bus with named channels; this is not complete yet * Engine/oload.c, Engine/otran.c, Top/csound.c: moved some parts of oload.c to otran.c while others to csound.c removed oload.c * H/csound.h, H/csoundCore.h: new API functions, and variables in CSOUND structure * Engine/otran.c, Top/csmodule.c, Top/csound.c, Top/utility.c: improved warning message for undefined OPCODEDIR/OPCODEDIR64 * Top/csound.c, Top/one_file.c: new command line flag (-+ignore_csopts) to disable the use of options specified in a CSD file one_file.c: minor fixes in parsing CSD files 2005-09-01 Michael Gogins * Added CsoundVST.Soundfile wrapper class for Python access to libsndfile. 2005-09-01 Istvan Varga * Top/csmodule.c: revised code for loading plugin libraries new function: csoundModuleInfo() can be used in plugin libraries to allow for checking API version and MYFLT type * Top/dl_opcodes.c: merged into csmodule.c; removed file * Engine/oload.c, H/csoundCore.h, OOps/ugens3.c, OOps/ugens5.c: removed static variables from ugens3.c and ugens5.c * Top/csound.c: removed adsyn/lpc RESET routines that are no longer needed * Opcodes/hrtferX, Opcodes/natben.c, Top/natben.c, SConstruct: removed unused endianness conversion code * SConstruct: fixed bug that broke building libcsound as a shared library 2005-08-30 Istvan Varga * Opcodes/ugnorman.c: renamed opcodes from ats* to ATS* to avoid namespace pollution 2005-08-28 Istvan Varga * Opcodes/ugnorman.c, Opcodes/ugnorman.h: new opcodes 2005-08-22 Istvan Varga * Engine/musmon.c, H/csound.h, InOut/libsnd.c, Top/csound.c: new API function: csoundSetHostImplementedAudioIO() allows the host application to implement sound I/O with direct access to the spin/spout buffers (or, with a non-zero buffer size parameter and using csoundPerformBuffer(), the input/output buffers), ignoring any -i, -o, -b, and -B options * H/csound.h, H/csoundCore.h, Top/threads.c: added return value to csoundWaitThreadLock(); non-zero if the function returns on timeout instead of the lock being notified 2005-08-20 Istvan Varga * Engine/oload.c, H/csound.h, H/csoundCore.h, Top/threads.c: new API function: csoundWaitThreadLockNoTimeout() similar to csoundWaitThreadLock(), but with infinite timeout, allowing for a possibly more efficient implementation * Top/threads.c: csoundWaitThreadLock(): implemented timeout for Linux * H/csoundCore.h, H/envvar.h, SConstruct: removed envvar.h from installation 2005-08-19 Istvan Varga * Engine/namedins.c, Engine/otran.c, Engine/rdorch.c: * Opcodes/fout.c, Opcodes/oscbnk.c: removed unneeded/redundant RESET code * H/csound.h, H/csoundCore.h, Top/threads.c: * InOut/rtpa.c, InOut/widgets.cpp, InOut/OSCrecv.c, Opcodes/OSC.c: attempts to clean up thread interface * H/prototyp.h: moved declaration of csoundYield() here from csound.h * examples/fl_controller/fl_controller.cpp: fixed a few minor errors 2005-08-18 Istvan Varga * Engine/namedins.c: * Top/csound.c: * Top/main.c: changes to allow host applications to register opcodes with csoundAppendOpcode(); should be called between csoundPreCompile() and csoundCompile() * Engine/oload.c: * H/csound.h: * H/csoundCore.h: removed csoundLoadExternal() and csoundLoadExternals() from public interface * H/opcode.h: removed file * Top/opcode.c: implemented csoundNewOpcodeList() and csoundDisposeOpcodeList() currently, the opcodes can only be listed after loading an orchestra with csoundCompile() 2005-08-12 Istvan Varga * renamed struct ENVIRON_ to struct CSOUND_, and ENVIRON to CSOUND * replaced uses of void* Csound instance pointers with CSOUND* * changes to header files to clean up the API; more need to be done * attempts to fix CsoundVST build - still not quite right 2005-08-03 Steven Yi * Engine/Entry1.c, Engine/fgens.c, H/ftgen.h: New ftfree opcode, takes in table number and free time arg, if zero frees at opcode init time, otherwise at opcode deinit time 2005-08-01 Istvan Varga * Minor fixes in DSSI opcodes (still have problems) * Engine/rdorch.c, Engine/entry1.c, Opcodes/uggab.c: minor parser changes, including the addition of a new code (fffb) for selecting opcode name based on the first input argument (i-, k-, and a-rate, but not constant) * Engine/insert.c: fixes related to re-initialisation of user defined opcodes * Engine/Entry2.c, H/str_ops.h, OOps/str_ops.c: new opcodes: printf, printf_i * Engine/Entry2.c, H/insert.h, OOps/goto_ops.c: new opcodes: loop_l, loop_le, loop_g, loop_ge 2005-07-31 John ff * SConstruct (opts): Added buildDSSI option 2005-07-23 John ff * Opcodes/bowedbar.c (bowedbarset): ADSR not initialised correctly. Still has over hash attack. Also adjust gain. 2005-07-17 Istvan Varga * Engine/rdorch.c: fixed crash on missing endin * Engine/rdorch.c, Engine/sread.c: fixed error message on $ without macro name * H/diskin.h, OOps/diskin.c: fixed soundout crash on Win32 with doubles 2005-07-15 Istvan Varga * removed use of cs.h; replaced with csoundCore.h * util1/sortex/smain.c, util1/sortex/xmain.c: fixed compiler warnings * OOps/diskin2.c: minor fixes in soundin and diskin2 * Engine/entry1.c: added soundouts; diskin extended to 24 channels * H/diskin.h, OOps/diskin.h: replaced diskin with new implementation based on diskin2 (should fix many problems, and allows up to 24 channels instead of the original limit of 4) fixed bug in soundout that resulted in not writing the last buffer to disk implemented soundouts opcode (stereo soundout) * Engine/fgens.c: fixed memory error in GEN20 * Engine/rdorch.c: minor fix in parsing of comments 2005-07-13 Istvan Varga * InOut/midirecv.c: reset controllers 7-11 to 0 in raw controller mode 2005-06-25 Victor Lazzarini * Added Opcodes/partials.c and Opcodes/psynth.c, streaming spectral partial track analysis/synthesis opcodes. 2005-06-23 Victor Lazzarini * Improvements/Fixes to rtcoreaudio.c, addition of non-interleaved audio support * Added Opcodes/ifd.c, Instantaneous Frequency Distribution spectral streaming opcode. 2005-06-23 John ffitch * Engine/sread.c (sread): Do not attempt to read a name in r if at end of line 2005-06-21 John ffitch * Opcodes/biquad.c (biquada, biquad, biquadset): * OOps/ugens5.c (porset, port, tonset, tone, tonsetx, tonex, atone, atonex, rsnset, reson, rsnsetx, resonx, areson): Work in doubles internally 2005-06-20 John ffitch * InOut/OSCrecv.c (OSC_listdeinit): Fixed a typo 2005-06-15 John ff * InOut/OSCrecv.c: New file for OSC listening 2005-06-15 John ffitch * SConstruct: Fixed TAGS so it looks at C files as well 2005-06-13 Victor Lazzarini * Top/dl_opcodes.c: commented out old code that was causing conflict on OSX 10.4 2005-06-09 Victor Lazzarini * InOut/rtcoreaudio.c : further improvements to coreaudio RT IO 2005-06-03 Istvan Varga * Engine/oload.c: * H/csoundCore.h: added (some) PVOC related functions to API * OOps/pvfileio.c: extensively revised code (needs testing): use ANSI C functions for file I/O, removed dependencies on sizeof(long)==4 and endianness, removed limit on number of files * util/pvanal.c: allow the use of PVOC-EX format again (still no displays though) 2005-06-03 Victor Lazzarini * OOps/pvfileio.c: removed statics and added csound* to functions; changed all relevant function calls elsewhere in the code to match the new prototypes 2005-06-01 Victor Lazzarini * Opcodes/pvsbasic.c pvsbasic.h added opcode pvsinit for fsig initialisation 2005-05-31 Istvan Varga * Engine/otran.c: allow global f-signals code changes for faster name lookup in global/local pools * Engine/rdorch.c: store line numbers in variables of type 'int' rather than 'short' TODO: clean up file reading (correct handling of EOL characters, use csoundFileOpen(), do not depend on being able to call ungetc() multiple times) probaly the same needs to be done in sread.c as well * H/oload.h: removed many unused typedefs and macros * OOps/fftlib.c: fixed crash on 64 bit platforms minor code changes 2005-05-30 Istvan Varga * New API functions: csoundAppendOpcodes(): appends a list of opcodes (OENTRY*) csoundRegisterResetCallback(): adds a function to be called by csoundReset() * Top/dl_opcodes.c: unload plugin opcodes (called from csoundReset()) * Top/dl_opcodes.c, Top/main.c: use API functions for adding opcodes, rather than changing opcodlst directly 2005-05-30 Michael Gogins * CsoundVST now supports multiple instantiation of VST plugins; it is not completely stable yet. * The Mixer opcodes now support multiple instantiation of Csound. * OpcodeBase.hpp now works with the new OENTRY structure. The OpcodeBase class now automatically registers a deinit callback, which by default does nothing. * The C++ STK opcodes now use RegisterDeinitCallback and the csoundModule* initialization and deinitialization routines. 2005-05-27 Steven Yi * Opcodes/fluidOpcodes/fluidOpcodes.cpp: modified fluidNote to use RegisterDeinitCallback, removed krate function call 2005-05-27 Istvan Varga * Added new API functions: csoundListUtilities(): returns alphabetically sorted list of registered utilities csoundSetUtilitiyDescription(): sets description text for an utility csoundGetUtilitiyDescription(): returns description text of an utility csoundRegisterDeinitCallback(): registers a function to be called at note deactivation csoundLoadSoundFIle(): loads an entire sound file into memory (similar to ldmemfile()) * Removed OENTRY.dopadr, and all related code, as it is not really needed now (can use csoundModuleDestroy and RegisterDeinitCallback instead). 2005-05-25 Istvan Varga * Engine/insert.c: fixed bug in ihold opcode * Engine/rdorch.c: attempts at fixing else and endif bugs * Added new macros (MYFLT2LONG and MYFLT2LRND) for converting floating point values to integers. 2005-05-24 Victor Lazzarini * changes to rtcoreaudio.c to enable channel independence 2005-05-23 Victor Lazzarini * late entry to the log: added InOut/rtcoreaudio.c * late entry to the log: added Opcodes/sndloop.c (sndloop, flooper, pvsarp, pvsvoc) * late entry to the log: fixed globals in rtpa.c * late entry to the log: added full-duplex support to the portaudio module (rtpa.c pa_blocking.c), aimed primarily at coreaudio 2005-05-23 Steven Yi * Engine/rdorch.c (splitline): Ported over ithen check from Csound4 source, added ithen to IFLABEL struct accordingly 2005-05-17 John ffitch * Engine/swrite.c (swrite): Charge to expand "s #" and "e #" to "f0 #\ns" 2005-05-16 Anthony Kozar * Top/argdecode.c: * Top/csound.c: * Top/main.c: * Engine/filopen.c: * Engine/insert.c: * Engine/linevent.c: * Engine/musmon.c: Converted mills_macintosh to mac_classic or MAC as appropriate or removed code if dependent on Mills globals. 2005-05-15 Anthony Kozar * Top/getstring.c: #include "cs.h", not * Top/threads.c: Added stubs for csound*ThreadLock functions. * Engine/envvar.c: Fixes for MacOS pathnames (more may be needed). 2005-05-15 John ffitch * Top/main.c: Prototype for mytmpnam 2005-05-14 John ffitch * Top/argdecode.c (decode_long): Allow definition of macros * Engine/sread.c (init_smacros): * Engine/rdorch.c (init_omacros): New functions to define macros 2005-05-11 John ffitch * Opcodes/ugmoss.c (valpass): Added cache of p->maxlpt to avoid overwriting arguments 2005-05-08 Michael Gogins * Added examples/Orbifold.py, an interactive display of the 3-dimensional orbifold of all close voice-leadings between 3-tone chords (based on the work of Professor Dmitri Tymoczko of Princeton). Also demonstrates controlling Csound from Python for real-time performance, and the use of 3-dimensional graphics for constructing graphical user interfaces. 2005-05-07 Istvan Varga * Opcodes/biquad.c: * Opcodes/biquad.h: added new optional argument to distort1 opcode (defaults to zero), to select amplitude scaling mode (0: default, compatible with original version; 1: relative to 0dBFS, same as mode 0 if 0dbfs is 32768; 2: unscaled) code changes to improve performance of some opcodes: biquad, vco, pareq, and distort1 improved vco opcode for more accurate output * Engine/rdorch.c: * OOps/aops.c: '=.a' opcode is automatically replaced with 'upsamp' if input is not a-rate, the actual a-rate version has been simplified, and '=' is removed by the parser if the output argument is the same as the input * OOps/ugens6.c: deltapx/deltapxw revised for speed 2005-05-06 Istvan Varga * H/msg_attr.h: * Top/csound.c: new message attributes: CSOUNDMSG_WARNING, CSOUNDMSG_FG_UNDERLINE * Engine/entry2.c: * H/ugens6.h: * OOps/ugens6.c: added new optional argument to delayr and all deltap opcodes, to allow delay taps to read from any of the nested delayr/delayw pairs, not just the last (from Csound 4.23.4.1) 2005-05-05 Istvan Varga * Engine/entry1.c: * Engine/express.c: added k() function for converting i-rate values to k-rate 2005-05-01 Istvan Varga * H/csound.h: * Top/threads.c: new functions: csoundLock(), csoundUnLock() * Top/argdecode.c: added ENVIRON* argument to usage() and dieu() * Top/csound.c: * Top/main.c: - maintain a global list of allocated Csound instances, delete all on exit or fatal signal - new interface function: csoundInitialize(), for global initialisation of Csound library; if not done yet, the first call of csoundCreate() will also call csoundInitialize() - moved signal handler from main.c to csound.c (still not quite right, should really be done by host application) - removed some unused/useless static variables 2005-04-30 Istvan Varga * removed global variable O - use csound->oparms instead * Top/csound.c: - dynamically allocate and destroy Csound instances, rather than using cenviron. Some old code still uses cenviron (and is thus now broken), and should be revised. - made calls to deprecated functions csoundPrintf() (#defined as printf()) and err_printf() fatal errors. 2005-04-29 Istvan Varga * removed all static variables from Engine/sread.c 2005-04-30 Michael Gogins * Disabled GUI options for Python mode and for auto-play when in VST plugin mode, to prevent side effects. * Improved version of CsoundVST.csd orchestra for VST plugin use, using the Csound mixer and some effects. * Updated CsoundVST for removal of various static variables in Csound. 2005-04-24 John ffitch * Top/one_file.c (read_unified_file): Added licence top level field 2005-04-23 John ffitch * SConstruct (guiProgramEnvironment): Need dl and pthreads even without FLTK 2005-04-14 Michael Gogins * Added (very) basic Java GUI front end for Csound. It is the main class in CsoundVST.jar. To be extended. The purpose of this work is to embed Csound5 in Kandid, an interactive graphics program for evolving pictures, and adapt Kandid for evolving pieces. 2005-04-18 Istvan Varga * Top/utility.c, H/cs_util.h: new files for dynamically loading utilities * cvanal.c, dnoise.c, hetro.c, lpanal.c, pvanal.c, pvlook.c, sndinfo.c: moved from Top/ to util/ utilities converted to plugin libraries (not done yet for hetro, lpanal, and pvlook; also pvanal is limited to old format for now) * H/pvoc.h, OOps/pvoc.c: moved functions only used by pvanal to pvanal.c * H/prototyp.h: removed prototypes for utilities * Engine/oload.c, H/csoundCore.h, Top/argdecode.c: ENVIRON: API functions for adding and running utilities changed command line parser for new utility API 2005-04-16 John ffitch * InOut/libsnd.c (sfopenin): Changed in and out channel mismatch to a warning. Trest with care! 2005-04-14 Michael Gogins * Changed CsoundVST to print log messages to stderr (used to be stdout) by default. * Added option to CsoundVST to automatically open the output soundfile for editing or listening at end of performance. * Upgraded Windows installer to set OPCODEDIR, RAWWAVE_PATH, PYTHONPATH, and PATH environment variables (uninstall does not work for PYTHONPATH). 2005-04-12 John ffitch * Opcodes/wave-terrain.c (wtPerf): Improved phase accumulation problem 2005-04-10 Michael Gogins * Updated the STK opcodes to take from 0 to 4 optional krate controller-value pairs. 2005-04-10 John ff * OOps/ugens2.c (itabl3): Missing return 2005-04-09 Michael Gogins * Added "STKName" (e.g. "STKBowed") opcodes for all Perry Cook's Synthesis Toolkit in C++ (STK) 4.2.0 instruments in his "demo" program, using Cook's original C++ code with minimal wrapping (about 25 opcodes, varying in quality from mediocre to very good). To build the opcodes, copy the STK sources into the csound5/Opcodes/stk directory, as instructed in SConstruct. All opcodes have the same signature: asignal STKName ifrequency iloudness {kcontroller kvalue} The RAWWAVE_PATH environment variable must be set to point to the directory containing the "rawwaves" samples. 2005-04-09 John ffitch * InOut/libsnd.c (sndinset): * H/soundio.h: * InOut/libsnd_u.c (sndgetset): Fix skipinit for soundin 2005-04-06 Istvan Varga * Engine/fgens.c: use csound->Message() instead of printf() added ENVIRON* pointer and variable arg list to fterror() replaced use of deprecated FFT functions with csound->RealFFT() limited line length to 80 characters * Engine/oload.c: * H/cs.h: * H/csoundCore.h: removed deprecated functions from ENVIRON: err_printf, IsPowerOfTwo, FFT2torlpacked, FFT2realpacked, cxmult, csoundPrintf * H/fft.h, H/ugens9.h, OOps/disprep.c, OOps/dsputil.c, OOps/fft.c: * OOps/pvinterp.c, OOps/pvread.c, OOps/ugens8.c, OOps/ugens9.c: * OOps/vpvoc.c, Opcodes/oscbnk.c, SConstruct, Top/cvanal.c: * Top/pvanal.c: removed deprecated FFT functions; use fftlib.c interface instead * H/prototyp.h: declare err_printf and csoundPrintf here (deprecated functions) * InOut/widgets.cpp: use csound->Message() instead of csound->Printf() * Top/csound.c: deprecated functions: err_printf, csoundPrintf * Top/main.c: do not call fftRESET() (this function was removed) err_printf moved to Top/csound.c 2005-04-05 Istvan Varga * Engine/sread.c: * H/sort.h: attempts to fix bugs in reading large score files * Engine/namedins.c, Engine/oload.c, H/csdl.h, H/cs.h, H/csoundCore.h: * H/namedins.h, H/OpcodeBase.hpp, H/prototyp.h, H/sftype.h, H/ugrw1.h: * OOps/ugens9.c, OOps/ugrw1.c, Opcodes/babo.h, Opcodes/biquad.h: * Opcodes/brass.h, Opcodes/dam.h: * Opcodes/fluidOpcodes/fluidOpcodes.cpp, Opcodes/Loris/lorisgens5.h: * Opcodes/pitch0.c, Opcodes/py/csoundmodule.c, Opcodes/spat3d.h: * Opcodes/vst4cs/src/vst4cs.h, Opcodes/vst4cs/src/vsthost.h: * Opcodes/wave-terrain.h: minor header changes removed some macros * H/csoundCore.h: * OOps/aops.c: fixed crash in cpsoct() and similar functions on out of range arg 2005-04-03 Steven Yi * SConstruct: added arch and cpu commandline options to fine tune gcc3opt flags for -march and -mcpu 2005-04-03 Istvan Varga * removed macro definitions for ksmps, esr, ekr, and some others; use csound->Message() instead of printf() and err_printf(); (large number of changes in many files) * Engine/namedins.c: * Engine/express.c: removed static and global variables 2005-03-31 Istvan Varga * Engine/entry1.c: * OOps/aops.c: added a-rate int() and frac(), and round(), floor(), and ceil() * Engine/express.c: * Engine/rdorch.c: * Top/main.c: * H/prototyp.h: added << and >> operators, fixed order of precedence express(), expRESET(): use ENVIRON *csound pointer use less obvious label names for if...then * Engine/oload.c: * H/csoundCore.h: * Top/csound.c: moved static invalue/outvalue function pointers to ENVIRON * Opcodes/ugmoss.c: implemented << and >> shift operators fixed bitwise OR at k- and a-rate 2005-03-31 John ffitch * Engine/express.c: Removed statics to environment structure 2005-03-30 Istvan Varga * Engine/oload.c: * Engine/twarp.c: * H/csoundCore.h: * InOut/libsnd_u.c: * OOps/fftlib.c: * OOps/fout.c: * OOps/sdif.c: * Top/csound.c: minor fixes; removed a few more static variables * Engine/express.c: * Engine/rdorch.c: * Opcodes/ugmoss.c: fixed binary operators * OOps/ugrw1.c: fixed printk2 opcode 2005-03-30 John ff * Engine/swrite.c: Remove statics from swrite.c * Engine/oload.c: * Engine/twarp.c: Removed statics from file twarp.c 2005-03-29 Istvan Varga * more API changes (affecting a large number of files) * Opcodes/newfils.c: fixed statevar bug 2005-03-28 Istvan Varga * Engine/auxfd.c, Engine/fgens.c, Engine/insert.c, Engine/oload.c: * H/csdl.h, H/csoundCore.h, H/prototyp.h, InOut/pa_blocking.c: * InOut/rtpa_new.c, InOut/widgets.cpp, OOps/aops.c, OOps/diskin2.c: * OOps/disprep.c, OOps/midiops.c, OOps/pstream.c, OOps/pvadd.c: * OOps/pvinterp.c, OOps/pvread.c, OOps/pvsanal.c, OOps/schedule.c: * OOps/ugens1.c, OOps/ugens2.c, OOps/ugens3.c, OOps/ugens4.c: * OOps/ugens5.c, OOps/ugens6.c, OOps/ugens8.c, OOps/ugens9.c: * OOps/ugrw1.c, OOps/vbap_eight.c, OOps/vbap_four.c: * OOps/vbap_sixteen.c, OOps/vbap_zak.c, OOps/vdelay.c, OOps/vpvoc.c: * Opcodes/babo.c, Opcodes/bbcut.c, Opcodes/biquad.c: * Opcodes/bowedbar.c, Opcodes/cross2.c, Opcodes/filter.c: * Opcodes/flanger.c, Opcodes/fm4op.c, Opcodes/freeverb.c: * Opcodes/ftconv.c, Opcodes/gab/gab.c, Opcodes/gab/vectorial.c: * Opcodes/grain4.c, Opcodes/grain.c, Opcodes/locsig.c: * Opcodes/mandolin.c, Opcodes/metro.c, Opcodes/midiops2.c: * Opcodes/midiops3.c, Opcodes/modal4.c, Opcodes/moog1.c: * Opcodes/nlfilt.c, Opcodes/oscbnk.c, Opcodes/physmod.c: * Opcodes/physutil.c, Opcodes/pitch.c, Opcodes/pluck.c: * Opcodes/pvsbasic.c, Opcodes/pvsdemix.c, Opcodes/repluck.c: * Opcodes/reverbsc.c, Opcodes/scansyn.c, Opcodes/scansynx.c: * Opcodes/seqtime.c, Opcodes/sfont.c, Opcodes/singwave.c: * Opcodes/sndwarp.c, Opcodes/space.c, Opcodes/spat3d.c: * Opcodes/spectra.c, Opcodes/syncgrain.c, Opcodes/ugens7.c: * Opcodes/ugensa.c, Opcodes/uggab.c, Opcodes/ugmoss.c, Opcodes/ugsc.c: * Opcodes/vdelayk.c, Opcodes/wave-terrain.c, Top/csound.c: API changes * OOps/diskin2.c: minor optimization in init routine * Opcodes/ugens6.c: * util2/mixer/extract.c: removed unused files 2005-03-27 Istvan Varga * SConstruct: * InOut/libsnd.c: * InOut/rtpa_new.c: new PortAudio plugin (enabled by useOldPortAudioPlugin=0) * Engine/entry2.c: * Engine/insert.c: * H/insert.h: new opcode: turnoff2 (can turn off other instruments) 2005-03-25 Istvan Varga * InOut/midirecv.c: * Engine/express.c: * Engine/fgens.c: fixed compiler warnings * OOps/diskin.c: * Engine/entry1.c: use diskin2 functions to emulate diskin * Opcodes/hrtferX.c, Top/dnoise.c, Top/cvanal.c, Opcodes/oscbnk.c: * Engine/fgens.c, OOps/ugens9.c, H/ugens8.h, H/pvinterp.h: * H/vpvoc.h, H/disprep.h, Top/pvanal.c, OOps/ugens8.c: * OOps/vpvoc.c, OOps/pvinterp.c, OOps/disprep.c, Engine/oload.c: * H/csdl.h, H/fft.h, OOps/fft.c, H/csoundCore.h: removed redundant (and often slow) FFT code * Top/dnoise.c: fixed sound file output * InOut/libsnd.c: print message correctly when closing output file * H/diskin.h: * OOps/dnfft.c: removed files 2005-03-23 Istvan Varga * OOps/ugens2.c: * Opcodes/biquad.c: * Opcodes/lowpassr.c: * Top/one_file.c: minor fixes 2005-03-22 Istvan Varga * H/diskin2.h: * OOps/diskin2.c: various minor code changes * Top/one_file.c: fixed CsFileB tag * util1/csd_util/base64.c: * util1/csd_util/cs.c: * util1/csd_util/csb64enc.c: * util1/csd_util/makecsd.c: new utilities 2005-03-21 Istvan Varga * Engine/entry1.c: * H/diskin2.h: * OOps/diskin2.c: new opcode * InOut/libsnd_u.c: * OOps/sndinfUG.c: bug fixes in opening sound files * OOps/diskin.c: fixed (partly) clicks in multichannel input; still some bugs * H/soundio.h: fixed soundin crash (was actually caused by unused SOUNDIN.kfrqratio) 2005-03-21 John ffitch * Engine/sread.c (MARGIN): Increase to 600, but needs to be rethought 2005-03-18 Istvan Varga * Engine/oload.c: * H/csoundCore.h: * H/fftlib.h: * OOps/fftlib.c: minor code changes related to FFT functions * Opcodes/ftconv.c: removed use of direct convolution due to patent issues * H/csdl.h: removed some unused macros (fewer is better) * Engine/fgens.c: minor GEN52 fix 2005-03-15 Michael Gogins * The Loris opcodes now work. * Removed pyrun.dll and -lswigpy from SConstruct, as SWIG 1.3.24 (current stable version) does not use it. * The Java wrappers are now built as a jar containing the CsoundVST package. * Added option to not build Java wrappers; as a result, CsoundVST builds on Linux again. * Removed documentation from the Windows installer. 2005-03-15 John ffitch * H/soundio.h (SOUNDIN): * InOut/libsnd.c (sndinset): * OOps/diskin.c (newsndinset): * H/diskin.h (SOUNDINEW): Added skipinit argument to diskin and soundin 2005-03-14 John ffitch * Opcodes/modal4.c (marimbaset): Make zero valid probability for multiple strikes 2005-03-14 Istvan Varga * SConstruct: * Engine/oload.c: * H/csound.h: * H/csoundCore.h: * H/fftlib.h: * OOps/fftlib.c: added new FFT code (faster than functions in fft.c) new API functions: csoundComplexFFT(), csoundInverseComplexFFT(), csoundRealFFT(), csoundInverseRealFFT(), csoundRSpectProd() TODO: make allocation of tables safe with reentrant operation and multiple instances (currently uses statics which is ugly) * Opcodes/ftconv.c: use new FFT functions; opcode is faster now 2005-03-13 Istvan Varga * SConstruct: * Opcodes/ftconv.c: new opcode (zero delay multichannel convolve, reads IR from ftable) not fully tested yet * Engine/fgens.c: added GEN52: creates interleaved multichannel table from other tables * Opcodes/spat3d.c: fixed spat3dt slowdown at end of table made it possible to run spat3dt from the orchestra header (instr 0) 2005-03-13 John ffitch * SConstruct (opts): make installation optional 2005-03-13 Istvan Varga * Engine/fgens.c: * H/ftgen.h: added GEN51 * Opcodes/reverbsc.c: minor code improvements 2005-03-13 John ffitch * Opcodes/ftest.c (gentune): Added Gabriel's gen to the loadable gens under the name gentune 2005-03-12 Istvan Varga * SConstruct: * Opcodes/screverb.c: new opcode (Sean Costello's waveguide reverb) 2005-03-11 Istvan Varga * InOut/widgets.cpp: * Top/csound.c: * Top/pvanal.c: fixed calls of csoundYield() with NULL pointer * Engine/entry1.c: fixed rtclock opcode (should be 0xffff, not 0xfffd) 2005-03-10 Istvan Varga * Engine/entry2.c: run miditempo opcode both at init and performance time * Engine/musmon.c: check for extra MIDI note-offs also when sustaining * Opcodes/freeverb.c: attempts to correct high frequency attenuation for sample rate * Top/argdecode.c: load external modules before printing opcode list 2005-03-09 Istvan Varga * Engine/insert.c: * OOps/schedule.c: fixes in schedule opcodes * SConstruct: removed checks for some unused headers * H/sysdep.h: set DIRSEP to '\\' on Windows * Engine/envvar.c: try_file_open(): do not test for directory on Windows (breaks WINE) * H/csdl.h: removed macro definiton for AppendOpcode * InOut/libsnd.c: * OOps/diskin.c: fixed soundin and diskin amplitude * Opcodes/freeverb.c: new opcode 2005-03-08 Istvan Varga * Engine/insert.c: MIDIinsert(): allow muting instrument by 'q' score opcode * Engine/linevent.c: fixes in RTclose(); do not use atexit() to call this function allow use of 'q' score opcode * Engine/musmon.c: cleanup(): call RTclose() to close line input (-L) * InOut/libsnd.c: do not close line input here; this is done by RTclose() * Top/argdecode.c: allow use of -L stdin on Windows (mills_macintosh still disabled) * Top/csound.c: csoundScoreEvent(): add p2 to current time, not section start time 2005-03-08 Istvan Varga * Engine/entry2.c: added "event_i" opcode (same as "event" but runs at i-time) * Engine/fgens.c, Engine/memalloc.c, Engine/memfiles.c: * Engine/musmon.c, H/prototyp.h: * OOps/pstream.c, OOps/pvadd.c, OOps/pvread.c: * OOps/ugens3.c, OOps/ugens5.c, OOps/ugens8.c, OOps/ugens9.c: * OOps/vpvoc.c, Opcodes/hrtferX.c, Opcodes/scansynx.c: major changes to memfile functions added ENVIRON* argument to allow for multiple instances prototypes in prototyp.h rather than all around in various .c files * Engine/linevent.c: rewritten event opcode to use insert_score_event() added eventOpcodeI() (i-time version of eventOpcode()) * Engine/musmon.c: removed unused #includes and declarations improvements and fixes in sensevents() and insert_score_event() * Engine/oload.c: * H/csoundCore.h: ENVIRON: cosmetic change: moved mrealloc pointer to after mcalloc ldmemfile prototype changed, and also renamed to ldmemfile_ added MEMFIL* pointers memfiles and rwd_memfiles changed SSTRCOD to less trivial value * examples/trapped.csd: * examples/trappedrt.csd: fixed bug in instr 13 that caused various stability problems * H/csdl.h, Opcodes/clfilt.c, Opcodes/follow.c: * Opcodes/hrtferX.c, Opcodes/modal4.c, Opcodes/sndwarp.c: removed "oparm" macro (there are still way too many macros) * H/csoundCore.h: * H/csound.h: * Top/csound.c: return type of csoundScoreEvent() changed to int (zero on success) * H/foo.h: removed file: was unused * H/linevent.h: new file: defines LINEVENT (why was it in schedule.h ?) * H/schedule.h: * OOps/schedule.c: removed sensOrcEvent(); this is now a simple macro in musmon.c * InOut/libsnd.c: print message correctly * Opcodes/py/csoundmodule.c: use insert_score_event(), but file is unused anyway (remove ?) * Opcodes/ugens9.c: removed file: was unused (and redundant as well, also found in OOps) * util2/exports/het_export.c: call csoundCreate() and csoundPreCompile() - needed to fix crash added &cenviron to ldmemfile() call 2005-03-07 Michael Gogins * Added CsoundVST, Loris, and the Csound API headers and libraries to the install target in SConstruct. * Added the Csound manual and the API documentation to the Windows installer. * Updated Loris with v1.2 sources from Loris CVS. Note: lorismorph doesn't work and is awaiting fixes from Kelly Fitz. Other loris opcodes may be broken as well. However, the Loris Python extension module built here does seem to work. 2005-03-07 Istvan Varga * Engine/entry2.c: removed event_set; no longer needed * Engine/insert.c: made deact and schedofftim static xturnoff: always remove instance from schedofftim chain minor fixes * Engine/linevent.c: removed event_set; no longer needed eventOpcode: rewritten to use new insert_score_event() function newevent: removed this function * Engine/musmon.c: new function: insert_score_event made it sure that -B is always greater than and is an integer multiple of -b if real time audio is used various fixes, removed unused prototypes, etc. * Engine/oload.c: * H/csoundCore.h: replaced EVTNODE OrcTrigEvts_ with EVTNODE *OrcTrigEvts in ENVIRON set initial value of dbfs_to_float to 1/DFLT_DBFS * frontends/CsoundVST/CppSound.cpp: removed unused declarations * H/csdl.h: * H/cs.h: removed macro definitons for OrcTrigEvts * H/csoundCore.h: * Opcodes/oscbnk.c: removed EVTBLK.offtim (was not used anywhere) changed EVTNODE for use with insert_score_event and related code * H/oload.h: removed TRNON * H/prototyp.h: removed prototypes for undefined functions newevent and csoundDefaultMidiOpen added int insert_score_event(ENVIRON*, EVTBLK*, double, int); * H/schedule.h: * OOps/schedule.c: added ENVIRON* argument to sensOrcEvent() * InOut/midirecv.c: * OOps/schedule.c: removed unused function prototypes * InOut/widgets.cpp: rewritten ButtonSched to use insert_score_event cleanup() prototype was wrong * OOps/schedule.c: * Top/csound.c: changes for using insert_score_event() to schedule events 2005-03-06 Istvan Varga * Engine/insert.c: * Engine/musmon.c: * InOut/midirecv.c: started to rework event processing code (sensevents() and other functions); still a long way to go, and bugs may heve been introduced * Engine/oload.c: cenviron_: removed sensType, added evt_poll_cnt and evt_poll_maxcnt * csound/csound_main.c: do not call csoundYield() in main loop, kperf() will call it frequently enough; improves performance * H/cs.h: * H/csdl.h: removed macro definitions for sensType * H/csoundCore.h: changes in INSDS, sensEvents_t, and ENVIRON for new event processing code removed MCHNBLK.ksusptr[] and ENVIRON.sensType_ * H/prototyp.h: added prototypes for xturnoff() and xturnoff_now() * InOut/midifile.c: changed miditempo opcode to print score tempo when MIDI file is not available * OOps/schedule.c: minor cosmetic changes (removed old commented out code etc.) * Top/csound.c: * Top/main.c: removed frsturnon * Top/opcode.c: minor fix: print opcodes like oscil.kk correctly 2005-03-03 Istvan Varga * Engine/envvar.c: * H/envvar.h: added SNAPDIR to environment variable list (used by widget opcodes) new API functions: csoundFindInputFile() and csoundFindOutputFile() * Engine/filopen.c: sssfinit(), openin(), openout(), fopenin(): rewritten to use new file search interface isfullpath(), catpath(): removed functions * Engine/memfiles.c: * Engine/rdorch.c: * InOut/widgets.cpp: * InOut/winEPS.c: * OOps/diskin.c: * OOps/pvfileio.c: * OOps/sndinfUG.c: * Opcodes/sfont.c: use new file search functions defined in Engine/envvar.c * Engine/oload.c: * H/csdl.h: * H/cs.h: * H/csoundCore.h: * H/prototyp.h: * Opcodes/fluidOpcodes/fluidOpcodes.cpp: new API functions: csoundFindInputFile() and csoundFindOutputFile() removed isfullpath(), catpath(), sadirpath, sfdirpath, and ssdirpath * OOps/pvfileio.c: use mmalloc() instead of malloc() * Top/argdecode.c: * Top/main.c: * Top/one_file.c: removed unused 'envoutyp' argument from argdecode() and decode_long() * Top/main.c: check SFOUTYP after reading all options, but only if no file type option was specified 2005-03-02 Michael Gogins * Added rule for SConstruct to build Java wrappers for CsoundVST if jni.h is present. 2005-03-02 Istvan Varga * anal/adsyn/het_main.c: * anal/convol/cvl_main.c: * anal/lpc/lpc_main.c: * anal/pvoc/pvc_main.c: * util1/cscore/cscore_main.c: * util1/sortex/smain.c: * util1/sortex/xmain.c: * util2/dnoise.dir/dnoise_main.c: * util2/dnoise.dir/srconv.c: * util2/envext/envext.c: * util2/exports/lpc_import.c: * util2/exports/pv_export.c: * util2/mixer/mixer.c: * util2/mixer/xtrct.c: * util2/pvlook.dir/pvl_main.c: * util2/scale.dir/scale.c: removed ustub library, attempts to fix standalone utilities * Engine/envvar.c: * H/envvar.h: new files for dealing with environment variables * Engine/filopen.c: * Engine/rdorch.c: * InOut/winEPS.c: * InOut/winFLTK.c: * InOut/winX11.c: * Opcodes/fluidOpcodes/fluidOpcodes.cpp: * Top/csmodule.c: * Top/csound.c: * Top/dl_opcodes.c: * Top/dnoise.c: * Top/main.c: * Top/one_file.c: use new environment variable functions * Engine/musmon.c: * frontends/csound/csound_main.c: print benchmark information in cleanup() instead of main() * Engine/oload.c: * H/csoundCore.h: ENVIRON: removed (*SetEnv)(), added envVarDB added csound instance pointer to (*GetEnv)() * H/csdl.h: define macro for GetEnv, but not for SetEnv * H/csound.h: * Top/csound.c: removed csoundGetEnv() and csoundSetEnv() (now in envvar.c) * H/ustub.h: * Top/ustub.c: * util2/mixer/extract.c: removed files * SConstruct: allow building dynamic Csound library (static is still the default) ustub library is no longer built * Top/argdecode.c: new command line option: --env (sets/appends to environment variable) removed empty function argdecodeRESET() * H/soundio.h: added prototypes for type2sf() and sf2type() * OOps/sndinfUG.c: fixes in filelen, filenchnls, and filesr (filepeak is still broken) * Top/csound.c: removed use of CSRTAUDIO environment variable * sndinfo/sndinfo_main.c: fixed crash 2005-03-01 Michael Gogins * Updated CsoundVST code to use Istvan Varga's MIDI driver system, so that CsoundVST works again as a VST plugin, at least in "Csound classic" mode. 2005-03-01 Istvan Varga * Opcodes/gab/gab.c: fixes in Maldonado opcodes * Top/dl_opcodes.c: fixed -v crash * Engine/memalloc.c: print function names correctly * Engine/entry2.c: allow opcode names like FLpanel_end, FLgroup_end, etc. * InOut/midirecv.c: restored original algorithm for assignment of default instr numbers * InOut/libsnd_u.c: * OOps/pvxanal.c: * OOps/ugens8.c: * Top/pvanal.c: bug fixes in sound I/O, pvanal, and pvoc 2005-02-28 Istvan Varga * cleanup.sh: new script to remove files generated during compilation * OOps/fout.c: * Opcodes/fluidOpcodes/fluidOpcodes.cpp: * Opcodes/OSC-Kit/OSC-priority-queue.c: * Opcodes/OSC-Kit/OSC-timetag.c: * util2/mixer/xtrct.c: fixed compiler warnings * American.xmg: * English.xmg: * csound.pdf: * csound.xmg: removed files from repository 2005-02-27 Steven Yi * frontends/CsoundVST/CppSound.hpp: changed #include of cs.h to csoundCore.h 2005-02-27 Michael Gogins * Changed fluid* opcodes: removed Gogins version, merged option to print presets to fluidLoad and added fluidControl opcode from Gogins version, added new fluidAllOut opcode to collect all audio from all Fluidsynth engines in a performance. * Removed Opcodes/fluid directory (Opcodes/fluidOpcodes now implements all features formerly found there). * Updated H/OpcodeBase.hpp to work properly with new SUBR signature. * Updated examples/Koch.py to use fluidOpcodes. 2005-02-27 Istvan Varga * Engine/entry2.c: * H/midiops.h: * OOps/midiops.c: added optional i-time parameter (defaults to 0) to pgmassign, selects MIDI channel (zero means all channels) * Engine/musmon.c: fixed terminating on end of MIDI file (-T flag) * H/csoundCore.h: moved pgm2ins[] from MGLOBAL to MCHNBLK to allow setting per channel other changes in MCHNBLK and MGLOBAL * H/midiops.h: * InOut/midirecv.c: do not use MIDI controllers (<128) for storing Csound internal data Roland NRPNS (VIB_RATE etc.) moved to controllers 128-135 removed MOD_VOLUME removed BENDSENS (replaced with MYFLT MCHNBLK.pbensens) removed DATENABL (replaced with int MCHNBLK.datenabl) * InOut/midifile.c: reduced memory usage of event list do not print any text meta events when message level is zero allow muting tracks with -+mute_tracks option (for example, -+mute_tracks=0010001 will mute the third and seventh tracks; tempo events are still used even if a track is muted) * InOut/midirecv.c: allow setting program change to instrument routing per channel implemented "raw" controller mode (-+raw_controller_mode=yes), which means all control changes are simply stored without handling e.g. RPNs or sustain pedal changes in a special way do not "pollute" controller space with Csound internal data cleaned up code * OOps/midiops.c: cpsmidib and similar opcodes now use bend range RPN information cleaned up code * Top/csound.c: do not initialise pgm2ins[] here (now done by m_chn_init_all()) new command line option: -+mute_tracks=STRING new command line option: -+raw_controller_mode=BOOLEAN 2005-02-26 Istvan Varga * InOut/libsnd_u.c: fixed bug in sndgetset(): sfinfo structure was uninitialised * InOut/midirecv.c: fixed bug in reading MIDI device and file at the same time 2005-02-25 Istvan Varga * Engine/entry2.c: added miditempo opcode (returns current tempo of MIDI file at control rate) * Engine/insert.c: allow muting MIDI channels (massign to 0) in MIDIinsert() * Engine/musmon.c: initialise all MIDI channels before oload() merged MIDI device and file input code (removed sensFMidi) made use of MCHNBLK.insno and MCHNBLK.pgmno more consistent * H/csoundCore.h: * Top/csound.c: increased MIDI input buffer size changes in MGLOBAL for new MIDI file code * H/midifile.h: * InOut/midifile.c: new implementation for reading MIDI files (supports multiple tracks) miditempo opcode * InOut/midirecv.c: changes for using new MIDI file input removed sensFMidi (both device and file input is done by sensMidi) removed FMidiOpen, vlendatum, Fnxtdeltim, fsexdata, and Rnxtdeltim made use of MCHNBLK.insno and MCHNBLK.pgmno more consistent m_chinsno: allow massign to <= 0 (mutes channel) m_chn_init_all: new function m_getchnl: no longer need to check if channel exists * InOut/midisend.c: * InOut/pmidi.c: allow sending simple system messages (clock etc.) * OOps/midiops.c: allow massign to <= 0 (mutes channel) * SConstruct: compile InOut/midifile.c 2005-02-24 Istvan Varga * Engine/oload.c: * H/csdl.h: * H/cs.h: * H/csoundCore.h: removed unused or redundant variables (dbfs_to_short, short_to_dbfs, float_to_dbfs, dbfs_to_long, long_to_dbfs) * H/soundio.h: removed some unused macros and typedefs moved #defines of sf_read_MYFLT and sf_write_MYFLT here set buffer size defaults more usable for real time audio * InOut/libsnd.c: moved #defines of sf_read_MYFLT and sf_write_MYFLT to soundio.h replaced uses of redundant variable float_to_dbfs with e0dbfs * InOut/libsnd_u.c: * OOps/diskin.c: moved #defines of sf_read_MYFLT and sf_write_MYFLT to soundio.h bug fixes (hopefully) in opening and reading sound files removed unused or redundant variables (dbfs_to_short etc.) soundout opcode fixes (clip non-float formats, do not scale) minor cosmetic changes (line length etc.) * OOps/fout.c: moved #defines of sf_read_MYFLT and sf_write_MYFLT to soundio.h * OOps/ugens2.c: * OOps/ugrw1.c: minor tweaks in tabli() made use of FLOOR() macro with negative integer argument safer * Top/cvanal.c: always scale input (actually to revert dbfs scaling done in getsndin(); FFT always expects data in the range 0 to 1) minor cosmetic changes (line length etc.) 2005-02-24 John ffitch * OOps/ugens2.c: Added FLOOR macro to speed up floor throughout and other speedups * OOps/ugrw1.c: Added FLOOR macro to speed up floor Changed a couple of longs to ints as there is no need for values beyond 2 2005-02-23 John ffitch * OOps/ugens2.c (tabli): Unwrap the two case so tests outside loop 2005-02-23 Istvan Varga * InOut/midisend.c: * OOps/midiout.c: Fixed 2 byte messages (program change and channel pressure). 2005-02-22 Istvan Varga * Engine/musmon.c: * Engine/oload.c: * H/csdl.h: * H/cs.h: * H/csoundCore.h: * H/csound.h: * H/midiops2.h: * H/midiops.h: * H/prototyp.h: * InOut/midirecv.c: * InOut/midisend.c: * InOut/pmidi.c: * OOps/midiops.c: * OOps/midiout.c: * Opcodes/midiops2.c: * SConstruct: * Top/argdecode.c: * Top/csound.c: * Top/main.c: MIDI changes: added support for real time MIDI modules (there is only one currently, pmidi.c); implemented both MIDI in and out using PortMIDI in pmidi.c; removed many static variables from MIDI code * InOut/libsnd.c: clip integer format sound files, fixed sfcloseout() * InOut/widgets.cpp: fixed ButtonSched() crash * OOps/diskin.c: fixed soundout opcode * SConstruct: made useJack=1 and useALSA=1 the default again * H/sysdep.h: added integer types 2005-02-22 John ff * SConstruct: Added Word64 as an option. This could be done automatically but one needs to select 64 or 32 bit on a 64 bit machine. 2005-02-20 Istvan Varga * Top/argdecode.c: * Top/main.c: allow orc/sco names in CSD (may be broken), but not in .csoundrc * InOut/mididevice.c: * InOut/midirecv.c: moved files here from OOps * InOut/fmidi.c: removed file, all platform independent MIDI code is in midirecv.c now * InOut/mididevice.c: * InOut/midirecv.c: * InOut/pmidi.c: started to clean up MIDI code; still a long way to go file input and PortMIDI work, but mididevice.c is currently a stub * Engine/oload.c: reset rtaudio function pointers in oloadRESET() * H/csoundCore.h: removed PortMIDI specific function prototypes * H/midiops.h: define MBUFSIZ here * OOps/midiops.c: added function prototypes (should be in midiops.h too ?) * Top/csound.c: removed PortMIDI specific function definitions 2005-02-20 Michael Gogins * Added '--help' to short usage list. * Permit .orc and .sco filenames in .csd files. * Added Sequence node in CsoundVST: child nodes of a Sequence node follow each other in strict temporal order, in the same order that the child nodes were added to the Sequence; the duration of each node is the total duration of all notes that it produces. 2005-02-19 Istvan Varga * Engine/musmon.c: fixed orcompact bug (takes a Csound instance pointer) * Engine/oload.c: * H/csoundCore.h: * H/csdl.h: * H/cs.h: removed variables from ENVIRON (midi_out and oplibs) * frontends/csound/csound_main.c: check for the case when csoundCompile() aborts but there is no error (--help or -U utilname) * H/csdl.h: define Str() for plugin libraries * H/csoundCore.h: define return value for longjmp() to report success: CSOUND_EXITJMP_SUCCESS OPARMS.Midioutname on all platforms, not only BeOS * OOps/midisend.c: Linux midiout writes to device file in non-blocking mode instead of using OSS /dev/sequencer * Top/argdecode.c: replaced redundant definitions of short option list with a single one exit (longjmp) with success after --help, -z, and utility call (-U) various changes to make argdecode safe to call multiple times accumulate rather than overwrite --opcode-lib list minor fixes, removed static variable, etc. * Top/csmodule.c: search OPCODEDIR64 first if MYFLT=double * Top/csound.c: on systems other than WIN32 and mills_macintosh, print messages to stderr instead of stdout so that -o stdout does not get corrupted * Top/cvanal.c: removed exit() call return value is zero on success, -1 on error (other utilities may need similar changes) * Top/dl_opcodes.c: search OPCODEDIR64 first if MYFLT=double load redundant (specified multiple times) opcode libraries only once fixes in opcode library loading * Top/main.c: return value from setjmp() on failure (forced to negative sign) replaced some uses of '&cenviron' with 'csound' removed useless format option warning/errors run a second pass of argdecode after reading a CSD so that options will be overridden correctly moved some code from argdecode here to make multiple calls to argdecode safe call MidiClose() earlier * Engine/oload.c: fixed memory leak (overwrite of ENVIRON.memalloc_db by oloadRESET()) 2005-02-18 Istvan Varga * Engine/auxfd.c, Engine/express.c, Engine/fgens.c, Engine/insert.c: * Engine/linevent.c, Engine/memalloc.c, Engine/memfiles.c: * Engine/musmon.c, Engine/namedins.c, Engine/oload.c, Engine/otran.c: * Engine/rdorch.c, Engine/rdscor.c, Engine/sread.c, Engine/twarp.c: * H/csoundCore.h, H/prototyp.h: * InOut/fmidi.c, InOut/libsnd.c, InOut/libsnd_u.c, InOut/pa_blocking.c: * InOut/pmidi.c, InOut/widgets.cpp, InOut/winX11.c, InOut/winascii.c: * OOps/aops.c, OOps/disprep.c, OOps/fft.c, OOps/fout.c: * OOps/lptrkfns.c, OOps/midiops.c, OOps/midirecv.c, OOps/mxfft.c: * OOps/pstream.c, OOps/pvadd.c, OOps/pvinterp.c, OOps/pvoc.c: * OOps/pvread.c, OOps/pvsanal.c, OOps/schedule.c, OOps/sndinfUG.c: * OOps/ugens1.c, OOps/ugens3.c, OOps/ugens4.c, OOps/ugens5.c: * OOps/ugens6.c, OOps/ugens8.c, OOps/ugens9.c, OOps/ugrw1.c: * OOps/vbap_eight.c, OOps/vbap_four.c, OOps/vbap_sixteen.c: * OOps/vbap_zak.c, OOps/vdelay.c, OOps/vpvoc.c: * Opcodes/babo.c, Opcodes/bbcut.c, Opcodes/biquad.c: * Opcodes/bowedbar.c, Opcodes/cross2.c, Opcodes/filter.c: * Opcodes/flanger.c, Opcodes/grain.c, Opcodes/locsig.c: * Opcodes/nlfilt.c, Opcodes/oscbnk.c, Opcodes/physmod.c: * Opcodes/physutil.c, Opcodes/pitch.c, Opcodes/pluck.c: * Opcodes/pvsbasic.c, Opcodes/pvsdemix.c, Opcodes/repluck.c: * Opcodes/scansyn.c, Opcodes/scansynx.c, Opcodes/sndwarp.c: * Opcodes/space.c, Opcodes/spat3d.c, Opcodes/spectra.c: * Opcodes/syncgrain.c, Opcodes/ugens6.c, Opcodes/ugens7.c: * Opcodes/ugens9.c, Opcodes/ugensa.c, Opcodes/uggab.c: * Opcodes/ugmoss.c, Opcodes/ugsc.c, Opcodes/vdelayk.c: * Opcodes/wave-terrain.c, Opcodes/gab/gab.c, Opcodes/gab/vectorial.c: * Opcodes/py/csoundmodule.c: * Top/argdecode.c, Top/cscorfns.c, Top/csound.c, Top/cvanal.c: * Top/dl_opcodes.c, Top/dnoise.c, Top/hetro.c, Top/lpanal.c: * Top/main.c, Top/one_file.c, Top/opcode.c, Top/threads.c: * util2/dnoise.dir/srconv.c, util2/envext/envext.c: * util2/exports/pv_export.c, util2/mixer/extract.c: * util2/mixer/mixer.c, util2/mixer/xtrct.c, util2/scale.dir/scale.c: added Csound instance pointer to mmalloc(), mcalloc(), mrealloc(), mfree(), memRESET(), auxalloc(), and auxchfree() nbytes argument of mmalloc(), mcalloc(), and mrealloc() was changed from long to size_t * Top/main.c: read .csoundrc both from HOME directory and from current directory 2005-02-17 Istvan Varga * Top/csound.c: the CSRTAUDIO environment variable can be used to set default for -+rtaudio * Engine/cfgvar.h: * Engine/cfgvar.c: added documentation for interface functions * Top/main.c: fixed opening .csoundrc * H/csoundCore.h: * Top/argdecode.c: removed unused O.Volume and -V option * Top/argdecode.c: * Top/main.c: * Top/one_file.c: fixes in parsing string options such as file names 2005-02-16 Istvan Varga * InOut/libsnd.c: print correct audio block sizes audrecv/rtrecord returns the number of bytes read * InOut/rtjack.c: do not connect to JACK server if real time audio is not used * InOut/rtpa.c: audrecv/rtrecord returns the number of bytes read * Opcodes/deps: removed unused file * Opcodes/oscbnk.c: * Opcodes/oscbnk.h: added new opcodes from 4.24.1 (denorm, delayk, vdel_k, and rbjeq) a-rate rnd31 was made faster improved seeding from time removed all static variables (hopefully did not break anything...) * Top/argdecode.c: fixed output to raw sound files (set O.filetyp = TYP_RAW) * Top/csound.c: print newline at end of various "early return" error messages more error checking in dummy rtaudio functions; allow -+rtaudio=null audrecv/rtrecord returns the number of bytes read fixed return value in csoundAppendOpcode (should be zero on success) 2005-02-13 John ffitch * Opcodes/uggab.c (lpshold, loopseg, loopseg_set): Changed to agree with csoundAV 2005-02-11 John ffitch * Opcodes/pvsdemix.[ch]: New files from Victor Lazzarini * SConstruct: Added pvsdemic 2005-02-10 Istvan Varga * frontends/csound/csound_main.c * Top/argdecode.c: Improved --sched option, now accepts a priority value (--sched=N). Priority settings in the range 1 to 99 request the use of SCHED_RR, zero is SCHED_OTHER (not real-time but still locks memory), and -20 to -1 for setting nice level. * Opcodes/gab/vectorial.c: Fixed sequence point warnings. 2005-02-10 Istvan Varga * InOut/rtjack: Implemented JACK real time audio plugin (experimental). * InOut/libsnd.c: Do not call audrecv() after opening sound input in sfopenin(). * Engine/musmon.c: Print correct maxamp info in cleanup(), even if performance is terminated (e.g. by ^C) rather than finished normally. * SConstruct: Added new options noDebug (do not add -g and -gstabs to CCFLAGS), gcc3opt (add optimisation flags for gcc 3.3.x and later), and useGprof (compile and link with -pg). All are disabled by default. Changes to allow compilng JACK plugin. * Top/main.c: Terminate (call longjmp()) if initialisation of modules has failed for some reason. * Top/csound.c: playopen_dummy() and recopen_dummy() now fail if --sched is used, to avoid locking up the machine. Expanded tabs to spaces. * Engine/oload.c: * H/csoundCore.h: * InOut/libsnd.c: * Top/argdecode.c: * Top/csound.c: Use csoundGlobalVariable and csoundConfigurationVariable system for new sound file ID tag options added by Michael Gogins, rather than changing OPARMS, oload.c, argdecode.c, etc. The options are now: -+id_title -+id_copyright -+id_software -+id_artist -+id_comment -+id_date argdecode.c: expanded tabs to spaces 2005-02-09 Michael Gogins * Add long options to set ID tags in output soundfile: --id-title=TITLE Title tag in output soundfile (no spaces) --id-copyright=COPY Copyright tag in output soundfile (no spaces) --id-software=SOFTWARE Software tag in output soundfile (no spaces) --id-artist=ARTIST Artist tag in output soundfile (no spaces) --id-comment=COMMENT Comment tag in output soundfile (no spaces) --id-date=DATE Date tag in output soundfile (no spaces) 2005-02-07 Istvan Varga * Engine/insert.c: Fixed uses of INSDS.xtratim where it was assumed to be short. * Engine/musmon.c: Use ENVIRON.sensEvents_state instead of csoundGlobalVariables, to reduce CPU usage of sensevents(). * Engine/oload.c: * H/csoundCore.h: Added GetRtRecordUserData(), GetRtPlayUserData(), sensEvents_state, rtRecord_userdata, and rtPlay_userdata to ENVIRON. In csoundCore.h: new structure type sensEvents_t. * H/csound.h: * Top/csound.c: New functions void **csoundGetRtRecordUserData(void *csound) and void **csoundGetRtPlayUserData(void *csound). * InOut/rtalsa.c: Use user data pointers instead of csoundGlobalVariables to store device instance data; reduces CPU usage. 2005-02-06 Istvan Varga * Engine/sread.c: Fixed memory corruption bugs that were caused by mixed use of mmalloc and realloc. * Top/main.c: Fixed bug in setting cenviron.exitjmp_. * frontends/csound/csound_main.c: Better checking for real time audio in set_rt_priority(). * Engine/memalloc.c: Rewritten functions mmalloc, mrealloc, etc. 2005-02-05 Istvan Varga * Engine/insert.c: Reworked kperf() so that it always performs one k-period, and does not check for real-time events (that is now done by sensevents()). beatexpire() and timexpire() take double argument instead of MYFLT. * Engine/musmon.c: Call orcompact() in cleanup(). Set real-time audio buffer sizes to more usable defaults. Replaced sensevents() with new version that always senses events for one k-period, and also handles real-time events; this new implementation of sensevents is also not as prone to drop notes as the original, but may still need some tweaking. playevents now simply calls sensevents() and kperf() in a loop, to eliminate redundant code. Misc. changes related to new kperf/sensevents. * H/csound.h: * Top/csound.c: * Top/main.c: Fixes to re-entrancy bugs reported by Michael Gogins. New API function: int csoundPreCompile(void *csound), is optionally called before csoundCompile * H/prototyp.h: * InOut/FL_graph.cpp: Changed kperf prototype to 'void kperf(ENVIRON *csound)'. Global variable 'kcnt' has been removed. * InOut/rtpa.c: Fixed bug in module selection (incorrect use of strcmp). 2005-02-03 Istvan Varga * SConstruct: Fixed (hopefully) the PortMIDI compile error. * Engine/musmon.c: Made it sure that cleanup() is done only once, no matter how many times it is called; fixed closing sound I/O (still not sure if it is correct); remove temporary files in cleanup(). * H/prototyp.h: * Top/main.c: * Top/one_file.c: add_tmpfile() and remove_tmpfiles() now take a void *csound pointer to remove the temporary files of a particular Csound instance. Also removed the static global variable 'toremove'. In main.c, cleanup() is called instead of rtclose to close sound output (cleanup is more useful as it will also close files, remove temporaries, etc.). * InOut/libsnd.c: * InOut/pa_blocking.c: * InOut/rtalsa.c: * InOut/rtpa.c: Incrementing ENVIRON.nrecs_ is now done in libsnd.c, and not in the plugins. Closing line input was also moved to libsnd.c. Fixed memory access problem in rtalsa.c (allocated space was too small in some cases) that caused crashes and odd errors. Attempts were made to make the closing of sound I/O more reliable; this is still not perfect in the case of PortAudio, but ALSA is better now. 2005-02-02 Istvan Varga * Top/main.c: * frontends/csound/csound_main.c: Moved set_rt_priority() and calling of init_getstring() from main.c to csound_main.c. Various changes to use new interfaces. * H/csmodule.h: * Top/csmodule.c: New plugin interface to be used by non-opcode libraries (e.g. real time audio). * H/csoundCore.h: Added new API functions to ENVIRON. * H/csound.h: * H/csoundCore.h: * Top/csound.c: * H/pa_blocking.h: * InOut/libsnd.c: * InOut/pa_blocking.c: * InOut/rtalsa.c: * InOut/rtpa.c: * SConstruct: Code related to real time audio has been revised to allow for loadable modules and multiple instances. * H/cfgvar.h: * Engine/cfgvar.c: New files that implement an interface that allows dynamic creation of options. * Engine/oload.c: Added new function pointers to cenviron_. * Engine/namedins.c: Made the table non-static so that it can be accessed from other files (also renamed it to use a less trivial name). Fixed bug in csoundDestroyGlobalVariable(). * Engine/insert.c: * Engine/musmon.c: * Engine/otran.c: Changes to use new plugin based audio I/O interface. Some functions now take void *csound as the first argument. These include spinrecv(), spoutran(), nzerotran(), spoutsf(), and other related functions. * H/new_opts.h: * Top/new_opts.c: New files for parsing options dynamically created by functions in cfgvar.c. * H/prototyp.h: * Top/argdecode.c: * Top/one_file.c: The functions argdecode(), readOptions(), and read_unified_file() now take 'void *csound' as the first argument. In argdecode.c: use functions from Top/new_opts.c. * H/ustub.h: * Top/ustub.c: Removed old unused prototypes. * install.sh: Install script for Linux. 2005-02-01 John ffitch * frontends/csound/csound_main.c (main): Corrected incorrect C 2005-01-29 Istvan Varga * SConstruct: * InOut/rtalsa.c: added ALSA real-time audio; disabled by default, as it is currently quite limited (no device selection, only float samples are supported). 2005-01-29 Istvan Varga * H/csound.h, H/csoundCore.h: * Engine/namedins.c, Engine/oload.c, Top/csound.c: new function: csoundQueryGlobalVariableNoCheck() functions moved from csound.c to namedins.c * OOps/aops.c: use csoundQueryGlobalVariableNoCheck() 2005-01-28 Istvan Varga * H/csoundCore.h, Engine/oload.c: added void **namedGlobals, int namedGlobalsCurrLimit, and int namedGlobalsMaxLimit to ENVIRON * Top/main.c, frontends/csound/csound_main.c: print compile times (real and CPU) if bit 7 of O.msglevel is set * H/csound.h, Top/csound.c: implemented functions for creating named global "variables" * OOps/aops.c: rtclock opcode uses new timer functions * Top/main.c: print_benchmark_info(): new function (activated by O.msglevel & 128) call csoundDeleteAllGlobalVariables() on RESET create global timer struct that counts from Csound instance start-up; use these calls to get the current real/CPU time in seconds (return value is double): timers_get_real_time(csoundQueryGlobalVariable(csound, "csRtClock")) timers_get_CPU_time(csoundQueryGlobalVariable(csound, "csRtClock")) 2005-01-27 Istvan Varga * Engine/express.c, Engine/oload.c, Engine/rdorch.c, H/csoundCore.h: * Top/argdecode.c: implemented --expression-opt 2005-01-27 Istvan Varga * Engine/entry1.c: * Engine/entry2.c: * Engine/express.c: * Engine/otran.c: * Engine/rdorch.c: use '.' instead of '_' in internal opcode names (e.g. osc.kk instead of osc_kk); this allows the use of the underscore character in real opcode names. Many files in Opcodes/ were also changed. * strings/makedb.c: * strings/all_strings, strings/english-strings, strings/french-strings: * H/text.h: * Top/getstring.c: new implementation for localized messages. Uses Str("...") instead of Str(X_nnnn,"..."). This also needed replacement of Str() in a large number of files. * Engine/oload.c, Engine/otran.c, H/csoundCore.h: use 'int' type for variable indexes instead of 'short'; needs some testing * Engine/oload.c, Top/main.c, Top/one_file.c: removed API function prototypes, use csound.h instead * Top/csound.c, H/csound.h, Engine/oload.c, Engine/otran.c: incorporated some changes from the 'unofficial' 4.24.1 version, including timer functions, better checking of sr/kr/ksmps, and some fixes * Engine/memalloc.c: removed references to free_strings() * H/csdl.h: use csoundLocalizeString() instead of getstring() * InOut/widgets.cpp: include instead of , and use stringstream instead of strstream * Opcodes/midiops3.c: fixed undefined order of operations * SConstruct: added /usr/X11R6/include to include paths on Linux 2005-01-25 Steven Yi * frontends/csound/csound_main.c: set stdout to not buffer if csound output not going to terminal 2005-01-25 John ffitch * InOut/widgets.cpp (FL_run): Need to pass argument to threads in Linux/Mach cases 2005-01-22 Michael Gogins * Added csoundSetFLTKThreadLocking and csoundGetFLTKThreadLocking calls to the Csound API. This controls whether or not the FLTK widget thread calls Fl::lock and Fl::unlock (the default), or not. Programs with their own performance thread or FLTK thread may wish to disable Csound's FLTK thread locking. 2005-01-20 Michael Gogins * Created a working NSIS installer for Windows -- does not install source code. 2005-01-18 John ffitch * Opcodes/newfils.c: New code * Opcodes/syncgrain.c: New code * InOut/widgets.cpp (fl_joystick): Change to way up of joystick 005-01-16 John ffitch * InOut/pa_blocking.c (paBlockingWriteStreamCallback): Fixed incorrect declaration 2005-01-12 Michael Gogins * Call Pa_Terminate after Pa_AbortStream calls in rtclose_. This helps with restarting Csound and CsoundVST. 22005-01-06 John ffitch * All over added first arg to opcodes of the ENVIRON structure 2004-12-23 John ffitch * InOut/pmidi.c (GetMIDIData): Read to wrong place! 2004-12-20 John ffitch * OOps/mididevice.c: * Top/main.c (signal_handler, csoundCompile): * InOut/widgets.cpp (SNAPSHOT): * H/sysdep.h: * H/csoundCore.h: Added code to allow MSVC compilation 2004-12-19 Michael Gogins * Added Java wrapper for the Csound API via CppSound. CsoundVST and Python support do not currently work, but it is now possible to run Csound natively from Java. This is designed mostly for using Csound in Mathematica through J/Link. 2004-12-19 John ff * InOut/pmidi.c (sensMidi): major rehack for PortMIDI structure. Not verified yet. 2004-12-18 John ffitch * Engine/fgens.c (hfgens): Ensure gensub array is initialised 2004-12-14 John ffitch * SConstruct: All over use strings for options rather than numbers. Seems to work but take care! 2004-12-12 Michael Gogins * Updated to FLTK 1.1.6, libsndfile 1.1.11, CVS PortAudio, CVS Loris for Windows pre-built binaries. * Added Loris API documentation to Csound reference manual. 2004-12-10 John ffitch * InOut/libsnd.c: and code * OOps/sndinfUG.c (getsndinfo): Removed unused called to readheader 2004-12-03 Michael Gogins * Tried to remove most remaining compiler warnings: mostly returning int from main, sscanf for %lf with USE_DOUBLE, type casting, etc. 2004-12-02 John ffitch * SConstruct (else): Added PortMIDI build option to aid experimentation. 2004-11-30 John ffitch * Top/main.c (signal_handler): Move message to after check for alarm 2004-11-25 Michael Gogins * Initial implementation of CounterpointNode -- generates species 1, 2, or 3 counterpoint for cantus firmi selected from notes generated by child nodes. Based on code from Bill Schottstaedt's species counterpoint generator (thanks, Bill!). * Optimized the build for boost::ublas matrix code in CsoundVST Node classes. 2004-11-28 John ffitch * OOps/pvfileio.c (write_pvocdata, pvoc_readfmt): Use a union rather than dubious casts. 2004-11-23 John ffitch * OOps/midirecv.c (m_chanmsg): Removed initial values for volume/balance/pan/expressions/bend/mastvol 2004-11-16 John ffitch * OOps/ugens2.c (itable, itabli, itabl3): Need to check OK rather than assume true=OK * Engine/fgens.c: All over removed statics into the environment or into arguments. Make ftfind etc take extra argument. Should assist with reentrance. 2004-11-14 John ffitch * util2/exports/het_import.c (main): Open output as binary stream * Top/main.c (mainRESET): ftRESET takes environment argument * Engine/fgens.c: Move many statics into a single static. Adjust args to gens to reflect this -- statics almost unnecessary 2004-11-11 Michael Gogins * Changed the Python interface to CsoundVST to allow Python programmers to derive new classes in Python from CsoundVST.Node, and these new classes will function as C++ Node * objects in the CsoundVST C++ internals. This enables Python-derived Nodes to function just like regular C++ Nodes in music graphs. 2004-11-11 John ffitch * Engine/fgens.c: Removed static variables ftp and nargs and used arguments instead. Simplifications all over 2004-11-10 John ffitch * H/csdl.h (FLINKAGE): defined * Top/dl_opcodes.c: Allow definitions of fgens * H/csoundCore.h: Added NGFENS structure 2004-11-09 John ffitch * Engine/fgens.c (fgens): Started named fgens (fterror): Allow named gens in error messages (allocgen): New function to allocate new names 2004-10-24 Michael Gogins * Fixes to rtpa.c and pa_callback.c for duplex audio, and libsnd_u.c forsoundfile input, by Victor Lazzarini. * CsoundVST changes directory to that of loaded files. 2004-11-07 John ffitch * H/ftgen.h (GENMAX): set to 43 (really part is fgens below) 2004-11-06 John ffitch * Engine/musmon.c (sensevents): Need to reset nxtim and nxtbt at end of section (not needed in playevents model) 2004-11-05 John ffitch * Opcodes/pvsbasic.c: New file and opcodes * Engine/fgens.c: Added gen43 2004-11-02 John Fitch * Top/threads.c: OSX threads like Linux * InOut/rtpa.c: Use callback stuff for OSX 2004-10-24 Michael Gogins * Renamed libsndfile.dll.0.0.19. * Updated documentation to provide improved directions for extending Csound with builtin or plugin opcodes. * Fixed badly formatted tables in documentation. * Improved API documentation with simple examples. 2004-10-26 John ffitch * OOps/ugrw1.c: Simplified some of the error reporting * H/ugrw1.h (zkwm): and remove value from domix 2004-10-25 John ffitch * OOps/ugens6.c (cmbset): Round rather than truncate 2004-10-24 Michael Gogins * Updated build system for gcc 3.4.2 (candidate), changed some flags to avoid DLL relocation errors on Windows that caused problems with restarting CsoundVST, and with debugging. * First draft of complete Csound 5 manual with Kevin Conder documentation included. There are as yet many errors with tables and graphics, but all (or almost all) of the text appears to be good. 2004-10-21 John ffitch * OOps/ugens6.c (delset, delrset): Round not truncate (deltap): Round not truncate 2004-10-20 John ffitch * OOps/ugens6.c (delrset): NULL list of delays for safety, 2004-09-12 Michael Gogins * Added csound::Score::getCsoundScore method in CsoundVST for easier use of algorithmic composition classes in other Csound-based systems. * Updated csound.pdf with API documentation. * Restored real-time audio code to more functional version. 2004-10-16 John ffitch * Opcodes/sfont.c (Sfplist, filter_string): Removed static array to local in caller 2004-10-07 Steven Yi * Top/dl_opcodes.c (csoundOpenLibrary): Fixed to work with cygwin * Top/thread.s : Fixed to work with cygwin 2004-09-17 John ffitch * util2/exports/pv_export.c (main): Free malloced space 2004-09-12 Michael Gogins * Restored PortAudio to ASIO only, re-ordered 'notify' and 'wait' for better logic and performance. * Improved PortAudio stop/restart by returning PaAbort from callbacks. * Moved Windows DLLs to csound5 root directory. * Added SIGINT to Windows signals handled. * Improved order of directives and comments in custom.py. * Updated csound.pdf to reflect the above. 2004-09-11 Steven Yi * SConstruct: Changed to use prefix directory from command line argument, defaults to /usr/local * SConstruct: Changed install-opcodes to install to "prefix + /lib/csound/opcodes" 2004-09-11 Steven Yi * SConstruct: Added install, install-executables, and install-opcodes targets 2004-09-08 John ffitch * SConstruct (ustub): Added bus.c * Opcodes/bus.c: New code for IO bus * Engine/oload.c: Initialise below * H/csoundCore.h (ENVIRON_): Added busik_, busia_, busok_, busia_ * H/csdl.h (busik, busia, busok, busia): Added macros 2004-08-22 John ffitch * Opcodes/biquad.h: * Opcodes/biquad.c (vcoset, bqrezset, pareqset, tbvcfset): Skip initialisation option 2004-08-21 John ffitch * Opcodes/biquad.c (moogvcfset, rezzyset): Added iskip to avoid initialisation * Opcodes/biquad.h: Added iskip options to moogvcf abd rezzy 2004-08-18 John ffitch * Engine/fgens.c (gen20): Corrected sinc window 2004-08-12 Michael Gogins * Re-arranged sections in csound.pdf to be more helpful for beginners. * Updated csound.pdf to reflect availability of ASIO on Windows. 2004-08-10 Michael Gogins * Implemented threads and mutexes in the Csound API for Windows and Linux, in Top/threads.c. * Implemented low-latency PortAudio with a blocking wrapper that uses mutexes for asynchronus ASIO on MinGW/Windows, in InOut/pa_blocking.c and H/pa_blocking.h. * Fixed Top/threads.c so it compiles on Linux. 2004-08-05 Michael Gogins * Rewrote fluid opcode to break it up into fluidload, fluidcontrol, and fluidout. Added documentation html file. 2004-07-31 Michael Gogins * Removed many warnings, especially by using %lf in sscanf for USE_DOUBLE and re-ordering ctor lists. * Added section to build Loris from sources if present. * SWIG-generated .py files now generated in root directory. 2004-07-25 Michael Gogins * Added csoundTableLength, csoundTableGet, csoundTableSet to API. * Added pyinit opcode. 2004-07-24 Michael Gogins * Python opcodes: imported Maurizio Umberto Puxeddu's Python opcodes for Csound 4 from Gabriel Maldonado's CsoundAV sources, updated for Csound 5 with opcode error status return values. Currently these opcodes only work in CsoundVST, but I may add a pyinit opcode to make them work in command-line csound. 2004-07-23 Michael Gogins * Loris: added sources (for Csound 5 opcode ONLY) and prebuilt binaries (for MinGW/Windows with USE_DOUBLE ONLY) for _loris.dll, which is both a plugin Csound 5 opcode and a Python extension module. * Modified dl_opcodes.c to print debugging info off the -v option, and made the messages clearer. 2004-07-21 Michael Gogins * vst4cs: implemented sample-accurate timing for NOTE ON and NOTE OFF. Renamed opcodes for greater intelligiblity. 2004-07-19 Michael Gogins * Andres Cabrera suggested a global vst audio output opcode, so I added vstplugg to do that. I changed the documentation to reflect it. 2004-07-18 Steven Yi * Engine/oload.c (oload): Moved call to sssfinit to above init0 as recommended by Matt Ingalls, instr 0 opcodes that use fopenin() now function correctly 2004-07-18 John ffitch * OOps/vpvoc.c (vpvset): Ditto * OOps/ugens8.c (pvset): Ditto * OOps/midiops.c (pgmassign): Ditto * OOps/aops.c (invalset,outvalset ): Allow score strings 2004-07-17 Michael Gogins * Andres Cabrera added bank loading to vst4cs. I added plugin editor dialogs and program setting, also refined log message levels and made VST opcode diagnostic messages more informative. 2004-07-17 John ffitch * OOps/dumpf.c (krdset): Allow strings from score and in kdmpset (4 cases each) * OOps/ugens9.c (pconvset): New code (pconvolve): New code 2004-07-13 John Fitch * InOut/widgets.cpp: Various changes to make __MACH__ machines be line Linux. (save_snap): Use fl_ask 2004-07-11 Michael Gogins * Added vst4cs plugin opcode by Andres Cabrera for hosting VST plugins in Csound. Made a number of bug fixes and changes. More changes coming. This is alpha code. Currently building only on mingw. 2004-07-09 John ffitch * Engine/musmon.c (playevents): matt's suggestion to avoid missing events due to rounding. * OOps/ugrw1.c (itablew): Wrong result returned and elsewhere * Engine/otran.c (otran): Move initialisation of pool to start of otran so strings work! (constndx): from here 2004-07-05 Anthony Kozar * Top/argdecode.c (argdecode): don't keep tmp files on Mac * Engine/sread.c (ifa): Rest of ^+ bug fix from csound module. 2004-07-04 John ffitch * strings/all_strings: Added string 226 2004-07-04 Anthony Kozar * Engine/sread.c (ifa): fixed bugs and improved error reporting in ^+ and ^- code. 2004-06-27 Michael Gogins * Fixed (and simplified) real-time audio input. 2004-06-25 Michael Gogins * The CsoundVST Python module now prints Csound messages to Python sys.stdout when running in IDLE. 2004-06-25 Anthony Kozar * These are all changes to allow compilation on MacOS 9 * Top/csound.c: In declaration of csoundExternalMidiRead(), made mbuf unsigned char* to match other calls. * OOps/diskin.c: (newsndinset) changed if (sinfd > 0) to if (sinfd != NULL). * Top/dl_opcodes.c: added #else case for platforms without shared libraries. * InOut/libsnd.c: added #include "MacTransport.h" for Mac builds. * Top/main.c: commented out conditional exclusion of err_printf() for Mac. * OOps/sdif-mem.c: * SDIF/sdif-mem.c: * H/sdif-mem.h: * SDIF/sdif-mem.h: * OOps/sdif.c: * SDIF/sdif.c: changed #include to #include "H/sdif-mem.h" and to "H/sdif.h". * H/sftype.h: #defined PACKED for mac_classic * H/sysdep.h: undefined mills_macintosh (now defined in Prefix.h) and temporarily undefined RTAUDIO for Mac build until PortAudio working. 2004-06-15 John ffitch * OOps/aops.c (outo): Skipped +6 case! 2004-06-12 John ffitch * OOps/ugens2.c (ftkrchk): * OOps/ugrw1.c: Results of some opcodes were reporting errors incorrectly 2004-06-07 Michael Gogins * Changed the CsoundVST module to create a global csound instance of CsoundVST.CppSound that will work both in CsoundVST and in the standalone Python interpreter. 2004-06-02 Michael Gogins * CsoundVST now opens the Python or csd file given on the command line. 2004-05-31 John ffitch * OOps/midirecv.c: declare csoundIsExternalMidiEnabled, csoundExternalMidiDeviceOpen, csoundExternalMidiDeviceClose and OpenMIDIDevice external * Engine/auxfd.c (fdchclose): fd should have been curchp->fd * InOut/libsnd_u.c (SAsndgetset): Return a SNDFILE* rather than an int 2004-05-27 John ffitch * InOut/widgets.cpp (fl_setWidgetValue_set, fl_setWidgetValue): New code stolen from CsoundAV and changed to Csound5 format * Engine/entry2.c: Change entry for FLsetVal * InOut/widgets.cpp: SNAPSHOT::get returns error state (get_snap): and used 2004-05-16 Michael Gogins * Amended SConstruct to keep a list of all dependencies to make sure that zipfiles get built at the very end. * Updated csound.pdf with information about -odac:xxx on ALSA. 2004-05-20 John ffitch * InOut/rtpa.c (playopen_): Decode dac:xxx rather than environment variable * InOut/libsnd.c (sfopenin, sfopenout): Decode dac:xxx style device * H/csoundCore.h (ENVIRON_): type in instance was wrong (missing *) * H/csoundCore.h (ENVIRON_): * H/cs.h (rtin_devs, rtout_devs): * H/csdl.h (rtin_devs, rtout_devs): * Engine/oload.c: Added rtin_devs and rtout_devs for device names rather than just numbers 2004-05-19 John ffitch * Engine/entry1.c: Added "tablew" as a 0xfffe opcode * SConstruct (customSHLINKFLAGS): Darwin seems to need -dynamic * Top/dl_opcodes.c (dlsymIntern): SLOOKUPSYMBOLINIMAGE_OPTION_BIND -> NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 2004-05-18 John ffitch * Opcodes/vdelayk.c (partial_maximum): Added maxk opcode 2004-05-17 John * SConstruct: Use -Wl,-Bdynamic as it is linker option * strings/makedb.c (main): Correct format in printf twice for longs * Top/main.c (install_signal_handler): Restore signal handling 2004-05-17 John ffitch * InOut/rtpa.c (playopen_): Allow selection of ALSA device via environment variable * Engine/entry1.c: Restored tablekt and tableikt 2004-05-16 Michael Gogins * frontends/CsoundVST/CsoundVstFltk.cpp: fixed problem with linefeeds in message lines. 2004-05-12 John ffitch * SConstruct: Set makeDynamic=1 for linux 2004-05-09 Michael Gogins * Added high-level "C" API for CsoundVST (frontends/CsoundVST/csoundvst_api.h and .c). * Fixed random number generator bug in CsoundVST::StrangeAttractor. 2004-05-07 Michael Gogins * Fixed some bugs in rtpa.c to enable lower-latency real-time audio. 2004-05-05 Michael Gogins * Fixed Fl_graph.cpp and widgets.cpp event handling with thread protection. FLTK widgets work now (at least on Windows). 2004-05-05 John ffitch * strings/all_strings: * strings/english-strings: Heavily revised * Top/pvanal.c (pvanal): 1781->1771 * Engine/oload.c (oload): 1711->1704 as overuse * OOps/pvfileio.c (pvoc_readfmt): Minor typo in string (pvoc_readheader): 1555 instead of 1635 (pvoc_putframes): 1527 instead of 1657 * OOps/pvxanal.c (pvxanal): Minor typo in string * Opcodes/scansynx.c Many string renumering for uniqueness * OOps/fout.c (outfile_set): 1463->1451 as overuse * Opcodes/uggab.c (rsnsety): 1453->1453 as overuse * Top/dnoise.c (dnoise): 1198->1199 as overuse (dnoise): Minor type in string * OOps/diskin.c (newsndinset): Minor string correction * OOps/ugrw1.c (printksset): 1136->1135 as overuse * Top/dnoise.c (dnoise): Changed 1052 to 1016 as overuse * Opcodes/ugmoss.c (vcombset): Unified string 668 * OOps/cmath.c (seedrand): String 458 made same as other uses * Top/argdecode.c (longusage): Typo in 425 * Opcodes/uggab.c (kDiscreteUserRand, aDiscreteUserRand) (kContinuousUserRand, aContinuousUserRand): Inconsidtent use of String 315 * Opcodes/ugsc.c (phaser2set): String 243 double used -- changed to 245 * OOps/mididevice.c (OpenMIDIDevice): Typo in string 210 * Top/argdecode.c (decode_long): String 95 was repeated; changed to 97 which was free * OOps/pvread.c (pvreadset, pvocex_loadfile): * OOps/pvinterp.c (pvbufreadset, pvinterpset, pvcrossset): * OOps/pvadd.c (pvaddset): * OOps/pstream.c (pvx_loadfile): String 63 * Top/dnoise.c (dnoise): String 61 * OOps/diskin.c (sngetset): Typing error in string 58 * Engine/insert.c (insert_event): Format string had naked % 2004-05-04 Michael Gogins * Added more Fl::lock and ::unlock calls to CsoundVstFltk.cpp, to protect against Xlib: unexpected async operation errors. CsoundVST now actually works on Linux. 2004-05-03 Michael Gogins * Fixed midiinterop opcodes that were broken when moved to csound5. 2004-05-01 Michael Gogins * Added a new csoundPerformKsmpsAbsolute API function for calling kperf without a score. * Restored external MIDI interface callbacks to working order. Renamed the Open and Close callbacks to DeviceOpen and DeviceClose to clarify their actual function. * Many fixes in CsoundVST to get it working for Csound 5. 2004-04-29 Michael Gogins * Made inbuf and outbuf MYFLT * throughout the sources. * Moved "extern" function and data declarations from csound.c to prototyp.h as much as possible, in order to prevent inconsistencies from spreading. 2004-04-27 John ffitch * Engine/oload.c: Initialise file_opened_ * H/csoundCore.h (ENVIRON_): Added file_opened_ to environment 2004-04-26 Michael Gogins * Added scoreRESET to enable multiple renderings with one Csound API instance. 2004-04-08 John ffitch * InOut/widgets.cpp (fl_knob): Added retuirn to initerror call (fl_button): 2004-04-06 John ffitch * InOut/FL_graph.cpp (draw): Initialise win_h 2004-04-05 John ffitch * H/csound.h: rtplay__ needs to have void* argument * OOps/midirecv.c (csoundDefaultMidiOpen): Needs void* argument * Top/csound.c: mainRESET needs an argument * Engine/linevent.c (newevent): needs csound argument 2004-03-14 John ffitch * OOps/fout.c (infile_act): renamed from infile to avoid name clash with linsndfile support 2004-03-11 John ffitch * InOut/libsnd.c (sfopenout): Added test.au as a default name 2004-03-03 John ffitch * Engine/scxtract.c (scxtract): Added call to sread_init() as suggested by Anthony Kozar 2004-02-29 Steven Yi * InOut/rtpa.c: modifed code to use PortAudio device 1 by default if none given. Messages are now given to user if defaulting to device 1 or what device user has selected. * Top/main.c: changed strcmp to strncmp when looking for dac or devaudio to allow use of --sched when using on linux and selecting PortAudio devices (i.e. dac1, devaudio3) 2004-02-28 Steven Yi * Engine/entry2.c: Added reverbx_set and reverbx back in as well as opcode entries for nreverb/reverb2 2004-02-28 John D. Ramsdell * Makefile.am: Removed _SOURCES vars from conditionals and made plugins libs begin with "lib" so that this automake file works with older version of automake. * configure.ac: Removed AC_PROG_RANLIB and added $srcdir to include so that VPATH works. 2004-02-25 Michael Gogins Modified sources to #ifdef for HAVE_LIBSNDFILE as defined by configure.ac, not _SNDFILE_. Removed jpff_glue.c as its function is now performed by csound.c. Deleted load_opcodes.c after merging it with dl_opcodes.c. 2004-02-22 Michael Gogins New configure.ac, which is a modified version of John Ramsdell's configure.ac. Thanks to John for providing a framework, implementing the required tests, and enabling me to understand the online documentation. All new Makefile.am, which puts all source configuration in one file for all targets. Renamed some "main.c" files to prevent naming conflicts caused by having a single Makefile.am. Moved some opcodes from Opcodes back to OOps due to tangled dependencies. Plugin opcodes are loaded from the directory pointed to by the OPCODEDIR environment variable. The --shared-lib flag is still effective. Enabled PortAudio in Csound 5 together with libsndfile, and changed PortAudio support from v18 to v19. Renamed libanal.a to libustub.a and moved as much code as possible from analysis and utility program "main" files to ustub.c. 2004-02-20 John ffitch * Opcodes/grain.c (ags): Use memcpy rather than a loop to copy back 2004-01-29 John ffitch * Engine/insert.c (ingoto): Check that we are in i-rate case 2004-01-13 John ffitch * Opcodes/sfont.c: casts in many debug statements * Opcodes/mandolin.c (mandolin, mandolinset): Use ENVIRON* argument to Delayline functions 2004-01-01 John ffitch * Opcodes/pluck.c (filter3Set): Need to initialise ->x1 and ->x2 to zero * Opcodes/flanger.c (wguide2, wguide1): Avoid frequencies below 5Hz 2003-11-30 Steven Yi * Engine/insert.c (orcompact): Added calls to deinitialize i-time opcodes 2003-11-29 Steven Yi * H/cs.h: all thing except compability macros moved out to csoundCore.h * H/csoundCore.h: contains everything except compability macros * Top/csound.c: edited to use ENVIRON, #include csoundCore.h instead of cs.h (macros were getting in the way of compiling), still needs to be reconciled with main.c::csoundCompile before being usable 2003-11-25 John ffitch * OOps/vbap_zak.c (vbap_zak_moving_init): Fix zastart/zkstart * Opcodes/bowedbar.c (make_DLineN): Envionment as argument * Opcodes/scansynx.c (listget): Added environment as argument and in calls * H/csdl.h (perferror): Point via p->h.insdshead->csound-> and name changes * H/cs.h (GLOBALS_): Added _ to names in many places * Top/dl_opcodes.c (csoundLoadExternals): resetter function needs environment as argument * Top/jpff_glue.c (csoundReset): Added argument of environment 2003-11-22 John ffitch * Opcodes/grain.c (ags): Check gcount against 1 rather than 0.1 2003-11-07 John D. Ramsdell * Top/getstring.c (init_getstring): The default location for the csound.xmg file is passed in by defining XMGDIR to be a directory string. 2003-11-05 John * util2/sndinfo/main.c (main): * util2/dnoise.dir/srconv.c (main): * util2/dnoise.dir/dnoise.c (main): Initialise e0dbfs in main as it is now in O structure 2003-11-05 John ffitch * Opcodes/ugens6.c: reverb was not declared in opcode table 2003-11-04 John D. Ramsdell * configure.in: Added AM_INIT_AUTOMAKE, AM_PROG_CC_STDC, and code that adds -Wall when using GCC. 2003-11-02 John D. Ramsdell * AUTHORS, INSTALL, NEWS: Added empty files to be filled in when we comply with the GNU Coding Standards. 2003-11-1 Steven Y. Yi * rdorch.c: fixed printf statement in synterr() to use %c instead of %f 2003-10-29 John D. Ramsdell * csound.spec.in: Added an RPM spec for Csound. 2003-10-16 John ffitch * H/csdl.h (getstring): * Engine/oload.c: and initialise * H/cs.h (GLOBALS_): Added auxalloc and getstring 2003-10-14 John ffitch * Top/main.c (mainRESET): Cannot call rtclose if no rtaudio 2003-10-13 John D. Ramsdell * uggab.c (anterpol): Made loop expression unambiguous. * ugens4.c: Int constants changed to unsigned long, as they do not fit as ints. 2003-07-24 John ffitch * widgets.cpp (fl_slider_bank): Remove extern decl of zkstart/zklast * H/csdl.h: * H/cs.h: * Engine/oload.c: * Opcodes/ugrw1.c: Moved zkstart/zklast to gloal structure 2003-06-18 John ffitch * H/ugens6.h: Added revlpsum and revlpsiz fields * Opcodes/ugens6.c (rvbset): Make reverbinit called internally to reverb to avoiud static array. 2003-06-16 John ffitch * dl_opcodes.c (csoundLoadExternals): Added support for RESET function in modules. 2003-06-04 John ffitch * wave.c (wavWriteHdr): peakdata.chunkDataSize needs lenlong call 2003-05-20 John ffitch * biquad.c (bqrez): Make mode positive integer 2003-05-12 John ffitch * Added Copyright/LGPL to all files 2003-05-06 John ffitch * entry2.c: schedwhen should have arguments kSkkm (first two were inverted) 2003-04-13 John ffitch * vpvoc.c (vpvset): Fixed typo of <- instead of <= 2003-03-12 John * diskin.h (struct): inbuf array needs to be longest of SNDINEWBUFSIZ and SNDINEWBUFSIZ_24 2003-03-08 John ffitch * modal4.c (agogobel): Need to set amp/freq in performance part as well as init (vibraphn): Amplitude of vibraophone needs setting at perf time. (marimba): ditto * marimba.h: vibraphn.h: Added first field * fgens.c (hfgens): In allocating table numbers do not overwrite any existing table 2003-03-04 John ffitch * one_file.c (readOptions): Ignore white space before tags (createScore, createOrchestra, createMIDI, createMIDI2) (createSample, createFile, read_unified_file): 2003-02-27 John ffitch * pstream.c (adsyn_frame): The memset should be 64bit 2003-02-19 John ffitch * version.h (VERSION): 4.23f02 * sread.c (getpfld): Reconstruct extending of curmem, especially so as to correct the frstbp chain pointers 2003-02-16 John * version.h (VERSION): 4.23f01 * sread.c (sread_init): new function to separate include files from sections (sread): Removed resetting of str and the unwinding after section ends * scsort.c (scsort): Call sread-init 2003-02-02 John * cs.h: Changed types of xtratim to int and of relesing and actflg to char 2003-01-27 John ffitch * dcblockr.c (dcblockrset): Check that filter is stable 2002-12-21 John * VERSION 4.23 * biquad.c (bqrez): Replaced to do other cases 2002-12-18 John ffitch * widgets.cpp: Windows needs strstrea rather than strstream 2002-12-16 John ffitch * entry1.c: Added fprints fprintks and prints opcodes * aops.c: * entry2.c: removed "ink" and "outk" * biquad.c (vco): Changed parameter range of pw to 0-1 * midiops2.h (MIDIINBUFMAX): Upped buffer size, and simplified code * insert.c (subinstrset): Code moved so "too many p-fields" initerror call does not result in a crash or other errors. 2002-12-15 John ffitch * otran.c (otran): Fencepost error in nulling extension of instrtxtp array 2002-12-07 John * winsound.rc: Added dither box to Extras (seems to have got lost somewhere) * ugens1.c (adsrset1): Need to test <=0 for length rather than zero (fixes madsr) 2002-12-04 John ffitch * musmon.c (gettempo): Result should be 60/betsiz rather than betsiz 2002-12-03 John ffitch * fgens.c (ftgen): Allow negative fcodes in string case (1,23,28) * insert.c (insert_event): insert here * schedule.c: Removed insert_event * midiops2.c (midiin): Replaced (initc7,initc14,initc21): Check that channel exists * namedins.c (strsav_create, strsav_string, strsav_destroy): New code * linevent.c (sensLine): Check that there is a Linefd (event_set): revised to fix some bugs, including crashes that occur when real-time audio, or schedule opcodes are used 2002-11-30 John * biquad.c (bqrezset, bqrez): New filter 2002-11-24 John ffitch * insert.c (deact): revised (beatexpire, timexpire): use revised deact (subinstrset, subinstr, xinset, xoutset) rewritten * insert.h: structure OPCOD_IOBUFS * cs.h: New structure INSTRNAME (Istvan) * rtlinux.c: replaced dspfd with dspfd_in and dspfd_out in various places. This might allow full-duplex operation on some cards (Istvan) * cs.h (rtin_dev, rtout_dev): define * oload.c: Initialise rtin_dev and rtout_dev 2002-11-21 John ffitch * oscbnk.c (vco2init): replaced to fix bugs in setting default parameters * express.c: Use printf rather than putstrg * otran.c: Removed putstrg from here as not used * mididevice.c: new code from Istvan for real-time MIDI input under Win32 * rtalsa.c: New code from Istvan 2002-11-16 John * util2/mixer/xtrct.c (ExtractSound): removed incorrect declaration of samples which stopped extraction except from start (main): Called init-getstring 2002-11-14 John ffitch * modal4.c (agogobelset1): * midiout.c (kvar_out_on_set1): removed deprecated code * argdecode.c (usage): Corrected typo in message 425 2002-11-13 John ffitch * flanger.c (wguide2set): Should have checked arg1 and looked at arg2 * vdelay.c: * ugsc.c: * ugmoss.c: * ugens7.c: * ugens4.c: * ugens3.c: * sndwarp.c: * pitch.c: * oscils.c: * oscbnk.c * grain.c: * flanger.c: * biquad.c: Use macros all over * cs.h (XINARG1, XINARG2, XINARG3, XINARG4): New macros to look at x flags for first 4 arguments (so we can straighten this out) 2002-11-06 John * jpff_glue.c: Only declare/use playopen_ etc if RTAUDIO is defined 2002-11-04 John ffitch * sdif2adsyn.c (main): Minor changes to variables and initialisation 2002-11-02 John ffitch * soundin.c (soundin): Code changed system address, so need a local array for r. 2002-10-30 John ffitch * lowpassr.c (lowprx): Use k field, fixing bug (lowpr_setx): Initialise k and also okr/okf which were not (lowpr, lowpr_set): Same * lowpassr.h: Added k as field to LOWPRX and LOWPR * fgens.c (gen08): Minor fixes to stop compiler warnings (gen01raw): return after error (gen18): ditto * midirecv.c (m_chanmsg): Deal with case when msb=1 and lsb is not known 2002-10-28 John * fgens.c (gen01raw, gen01): Same * oscbnk.c (oscbnk_flen_setup): Moved function so will compile on 68000 * sfont.c (SfPlay_set, SfPlayMono_set, SfInstrPlay_set) (SfInstrPlayMono_set): use ioffset and other minor changes * sfont.h: * entry1.c: Added additional option arg to sfont opcodes * sfont.c (SfPlay_set): Changes from Steven Yi to bring in line with SfPlayMono 2002-10-28 John ffitch * fgens.c (ftRESET): fence post error in freeing flist * cwin.cpp (cwin_exit): Call csoundReset * main.c (mainRESET): Changed order of resets * memalloc.c (all_free): Reset apsize as well 2002-10-20 John * control.c (readvalues): removed \n from the read from the Tcl/Tk process 2002-10-15 John ffitch * VERSION 4.22 * soundio.c (floatran_noscl): New code (floatrecv_noscl): ditto (iotranset): Use it (iotranset): twice 2002-10-14 John ffitch * uggab.c (resony): Use the local buffer so as not to overwrite (rsnsety): Initialise buffer * uggab.h: Added buffer field to RESONY 2002-10-14 John ffitch * ugens5.c (areson): Ensure areson can use same answer variable as input 2002-10-13 John * swrite.c (swrite): * sort.c (sort): * sread.c (sread, getop): * musmon.c (playevents): Add q score event * entry2.c: Added mute opcode * pitch.c (mute_inst): New function * pitch.h: Added MUTE structure * otran.c (tranRESET): Free instrumentName structure * cs.h: Added muted field to INSTRTXT which is a short and aids padding! (GLOBALS_): Added instrumentName to globals 2002-10-12 John * insert.c (insert): Added code to pad parameters with zero if too few provided. 2002-10-09 John * uggab.c (posckk, poscaa, poscka, poscak): replace poscil * entry1.c: Added poscil as _kk, _ka, _ak, _aa opcode * fgens.c (fgens): Allow non power-of-two table sizes (negative lenth) (gen10): use rem rather than mask so allows non-power-of-two * memalloc.c (all_free): call rlsmemfiles * diskin.c (newsndinset): Set length right at beginnin (sreadinew): Add WAV to list of types with known header info 2002-10-08 John ffitch * wave.c (wavReWriteHdr): * soundio.c (sfopenout): * sndinfo.c (sndinfo): * diskin.c (newsndinset, soundinew): * aiff.c (is_aiff_formtype): * aifc.c (aifcReWriteHdr): Changed non-ANSI tell to call to lseek for completeness (aifcReadHeader): Ditto (is_aifc_formtype): Ditto (aifcReWriteHdr): Use SEEK_SET instead of 0 which could be wrong * FL_graph.cpp: and the rest of the winFLTK support. May merge later. * winFLTK.c: New code to replace winX11.c using FLTK rather than raw X 2002-10-07 John ffitch * memalloc.c (all_free): and here * memfiles.c (rlsmemfiles): Add nulling of memfiles for reentrance * oscbnk.c: many changes in vco2 (and related) code (Istvan) * oscbnk.h: similarly to oscbnk.c, all vco2 stuff was replaced by new version * entry2.c: replaced entry for "vco2init" 2002-10-06 John * soundin.c (sndinset): Patch from RWD to reopen input; still looks wrong 2002-10-03 John * rtcoreaudio.c: * mw_menu.c: * midirecv.c: * cscore_main.c: Improved deprecated declarations 2002-09-28 John * insert.h: Added 8 to args in XOUT (Istvan) * fgens.c (ftRESET): call vco2_tables_destroy() * oscbnk.c: added vco2 and related opcodes (Istvan) * oscbnk.h: New structures for vco2 (Istvan) * diskin.c (newsndinset): Fix related to skip time going beyond file end * ugmoss.c (vcomb): Changes from Pete Moss (valpass): Ditto 2002-09-26 John * butter.c (butter_filter): Deal with underflow on pentiums which gets seriously lost (RWD's idea) 2002-09-25 John * uggab.c (loopseg): Wrap segments (lpshold): Ditto and other fixes 2002-09-22 Istvan Varga * linevent.c: Added global_kcounter instead of kcounter 2002-09-21 John ffitch * cs.h (GLOBALS_): Added global forms of ksmps etc * oload.c: Added initialisation * insert.h: New typedef INSTRNAME, OPCOD_IOBUFS, UOPCODE, XIN, XOUT, SETKSMPS * jpff_glue.c (csoundMessageS): New function like csoundMessageV but to stdout * main.c (install_signal_handler): Leave SIGALRM alone if FLTK in use (dribble_printf): Make it dribble, and use csoundMessageS to use stdout 2002-09-21 Istvan Varga * cs.h (OPCODE, ENDOP): Added these and renumber * disprep.c (printv): print (int) p1 instead of insno (works better with user defined opcodes) * entry2.c: Added oscilikt, osciliktp and oscilikts * jpff_glue.c (MakeXYin): Arguments should be MYFLT * oscbnk.h: Added OSCKT and OSCKTP structures * oscbnk.c: various optimisations in oscbnk, grain2, and grain3 minor bug fix in oscbnk new opcodes oscilikt, oscilikts, and osciliktp bug fix in error checking code of all oscilikt opcodes 2002-09-20 John ffitch * soundin.c (soundin): Generalise to <24 channels * soundio.h: Change r1 to r[0] etc in SOUNDIN 2002-09-18 John ffitch * fgens.c (ftRESET): Free table space as well * rdorch.c (splitline): Generation of temporary labels was wrong in then/else 2002-09-17 John ffitch * musmon.c (cleanup): Only close scfp if not already closed * express.c (express): Need to treat a(k) as a special case as well as i(k) 2002-09-16 John ffitch * cwin.cpp (CArg::OnOrchestra): Promote use of unified files 2002-09-08 John * express.c (express): Silly error of && replaced by || in precedence of | and # * ugmoss.c: Rounded conversions in and/or/xor/not 2002-08-30 John * cwin.cpp (Run): Set O and cglob from O_ and cglob_ * soundio.c: recopen and playopen changed to use float rather than MYFLT (sfopenin): Cast sr to (float) in call of recopen (sfopenout): and in recplay 2002-08-25 John * soundin.c (soundin): Use an array for outputs rather than case statement. Generalises but possibly slower 2002-08-24 John * pvsanal.c (pvsynthset): Check size of buffers as well as existence (pvsanalset): Ditto 2002-08-21 John ffitch * VERSION 4.21 * cmath.c (ipow): Added normalisation and check for NaN (kpow): Check (apow): Check more complex here 2002-08-20 John ffitch * fgens.c: Code for ftload, ftloadk, ftsave and ftsavek * entry2.c: Added ftload and ftsave 2002-07-21 John * aops.c: added ink, outk, invalue, and outvalue opcodes * rdorch.c: added 'z' output type 2002-07-18 John * Incorporated the API code which meant minor changes in ustub.h, winX11.c, oload.c, one_file.c, cs.h, cwindow.h, rt*.c, and other places. main.c in all anal directory modified. 2002-07-18 John ffitch * rdorch.c: * otran.c: * insert.c (ingoto, kngoto, subinstrset,subinstr): New code from matt * insert.h (SUBINSR): new structure * soundio.c (longtran): fixed RWD bug that could result in overflows in some cases with positive out of range samples) * cs.h: removed definitions of "dv32768" variable that is no longer needed * cvanal.c (takeFFT): * hrtferX.c (hrtferxk): * grain4.c (grand, grainsetv4): bug in random code with incorrect scaling * oload.c (oload): removed code related to dv32768 * pvanal.c (takeFFTs): * ugens3.c (adsyn): use dbfs_to_float instead of dv32768 * ugens4.c: removed declaration of short_to_dbfs as it is not needed(Istvan) (plukset, krand, arand, rhset, randh, riset, randi): fixed a large number of RWD bugs, all related to 0dbfs scaling of 16 bit random numbers (completely wrong); replaced all occurrences of dv32768 with DV32768, and removed all DBFS code 2002-07-14 John * midiops.c (mctlset, maftset): fixed bugs in initialisation code (Istvan) 2002-07-13 John * soundin.c (dbfs_init): printing to stderr so as not to confuse -o stdout 2002-07-12 John * musmon.c: Printing of amplitudes done with new function print_maxamp including colour printing.. (Istvan) * ugens2.c (tabli): Fixed bug in no-wrap case (tabl3): Ditto * ugensa.c (newpulse, fogset): Ditto * ugens7.c (newpulse): Newpulse only if not iskip (fofset0): Skip lots of initialisation if iskip * ugensa.h (struct): * ugens7.h: Added iskip argument to FOFS and FOGS * pvoc.c: * midisend.c: * main.c (set_rt_priority): * dpwelib.h: FreeBSD case * aops.c (rtclock): Include in Linux case * LINUXaudio.c (setsndparms): FreeBSD code 2002-07-10 John * oload.c (oload): Fencepost error in when to enlarge strsets vector * anal/convol/makef: * anal/convol/main.c: New files * anal/makef (cvl): Include compilation of cvanal stand-alone 2002-07-09 John * soundio.c (audwrt4): #ifdef'ed out as not used 2002-07-04 John ffitch * sread.c (sget1): Make failure to include an include file into a hard error using scorerr * rdorch.c (rdorchfile, rdorchfile): Allow {{ }} long strings (splitline): * sread.c (getscochar): Trap $ without a name (thanks to Maurizio) * ugens5.c: Make lprdadr flexible rather than 20 long (lpcRESET, lprdset, lpslotset, lpitpset): 2002-07-03 John * ugens6.c (a_k_set): New function 2002-07-02 John * dl_opcodes.c (csoundLoadAllOpcodes): Early exit if no libraries to load 2002-06-29 John * util2/envext/envext.c (main): * util2/mixer/extract.c (main): * util2/mixer/xtrct.c (main): * util2/mixer/mixer.c (main): * util2/scale.dir/scale.c (main): * util2/dnoise.dir/dnoise.c (main): * util2/dnoise.dir/srconv.c (main): Initialise dbfs stuff 2002-06-28 John * windin.c (xyinset): * wave-terrain.c (scanhinit, scantinit): * ugsc.c (resonzset): * ugrw2.c (krsnset): Return after initerror * ugrw1.c (zir): initerror->warning * uggab.c (rsnsety): * ugens5.c (rsnset, rsnsetx): * ugens1.c (evxset): * spectra.c (spdspset, spfilset): * schedule.c (lfoset): * scansynx.c (scsnux_init, scsnux_init, scsnsx_init): * scansyn.c (scsnu_init, scsns_init): * pitch.c (pinkset): * midiops.c (cpstmid, chctlset): * midiops2.c (midic7set): Return after initerror * follow.c (flwset): initerror replaced by warning as it can carry on here * disprep.c (fftset): Return after initerror 2002-06-27 John * dumpf.c (kdmpset, kdmp2set, kdmp3set, kdmp4set, krdset) (krd2set, krd3set, krd4set): Return after initerror 2002-06-24 John * entry1.c: Changes arguments of vco to "xxikppovo" 2002-06-22 John * ustub.h (perferror): Added dummy definition * vpvoc.c (ktableseg, ktablexseg, voscili): * vdelay.c (vdelay, vdelay3, vdelayxw, vdelayxs, vdelayxws) (vdelayxq, vdelayxwq): * ugmoss.c (vcomb, valpass): * uggab.c (vibrato, vibr): * ugens9.c (convolve): * ugens8.c (pvoc): * ugens7.c (fof): * ugens6.c (delay, delayr, delayw, deltap, deltapi, deltapn) (deltap3, deltapx, deltapxw, comb, alpass, reverb, pan): * ugens4.c (buzz, gbuzz, pluck): * ugens3.c (foscil, foscili, adsyn): * ugens2.c (ktable, tablefn, ktabli, ktabl3, tabli, tabl3, kosc1) (kosc1i, osciln, koscil, osckk, oscka, oscak, oscaa, koscli) (osckki, osckai, oscaki, oscaai, koscl3, osckk3, oscka3, oscak3) (oscaa3): * spectra.c (noctdft, specdisp, specptrk, specsum, specaddm) (specdiff, specscal, spechist, specfilt): * spat3s.c (spat3d, spat3di): * spat3d.c (spat3d, spat3di): * space.c (space, spdist): * soundin.c (soundin): * sndwarp.c (sndwarp, sndwarpst): * pvinterp.c (pvbufread, pvinterp, pvcross): * pvadd.c (pvadd): * pitch.c (pitch, adsynt, hsboscil, pitchamdf, kphsorbnk) (phsorbnk, Fosckk, Foscak, Foscka, Foscaa, trnseg): * oscils.c (tablexkt): * oscbnk.c (oscbnk, grain2, grain3, rnd31k, rnd31a): * nlfilt.c (nlfilt): * hrtferX.c (hrtferxk): * grain.c (ags): * grain4.c (graingenv4): * disprep.c (kdsplay, kdspfft, tempest): * biquad.c (vco): initerror->perferror (nestedap): Ditto 2002-06-20 John ffitch * ugens1.c (linseg, kxpseg, expseg, knvlpx, envlpx): Should use perferror rather than initerror, and return 2002-06-17 John * Removed tabs and trailing spaces throughout (again) 2002-06-15 John * csdl.h: New file to be used in dynamic libraries * dl_opcodes.c (csoundLoadAllOpcodes): New code for Linux to load dynamic libraries. * main.c (create_opcodlst): Call csoundLoadAllOpcodes in any case * argdecode.c (decode_long): make static, and add opcode-lib= option 2002-06-13 * scansynx.c (scsnsmapx): New code 2002-06-10 John * oload.c: Initialisation of tran_0dbfs was in wrong place * window.c: Initialise exitFn to NULL (dispexit): More checking -- to deal with case when no exitFn * one_file.c (deleteOrch): make global * main.c (remove_plname): make global (was static) (remove_scnam): ditto * entry2.c: Initialisation method for linevent 2002-06-01 John * VERSION 4.20 * midiops.c (pchmidib): Same for pitchbend_value expansion * linevent.c (RTLineset): Local copy of Linepine to avoid OSX compiler bug * rdscor.c (flushline): Get local copy of scfp as mac OSX compiler has a bug in getc/macro expansion (scanflt): Ditto (dumpline): Ditto (rdscor): Ditto * wave.c (write_wavpeak): different scale if 0DBFS * vpvoc.c (vpvset): different scale if 0DBFS * ugens8.c (pvset): different scale if 0DBFS * ugens4.c: (arand, krandh, randh, krandi, randi): different scale if 0DBFS * ugens3.c (adsyn, adsyn): different scale if 0DBFS * soundio.c: (shortran, longtran, floatran, int24ptran, shortrecv, longrecv) (floatrecv): different scale if 0DBFS * soundin.c: (getsndin, soundin): different scale if 0DBFS * rdorch.c (argtyp, argtyp): different scale if 0DBFS * pvxanal.c (chan_split): different scale if 0DBFS * pvinterp.c (pvinterpset, pvcrossset): different scale if 0DBFS * pvanal.c (pvanal): different scale if 0DBFS * pstream.c (pvx_loadfile): different scale if 0DBFS * pitch.c: different scale if 0DBFS * otran.c (tranRESET, otran, plgndx): different scale if 0DBFS * oload.c: (oloadRESET, oload): different scale if 0DBFS * main.c: (MAIN): different scale if 0DBFS * lpanal.c (lpanal): different scale if 0DBFS * hrtferX.c (hrtferxk): different scale if 0DBFS * hetro.c (hetro, writesdif): different scale if 0DBFS * grain4.c (grainsetv4, grand): different scale if 0DBFS * diskin.c: (sreadinew, sndwrt1, sndwrtu) (sndwrt2rev, sndwrt2, sndwrt3, sndwrt3rev, sndwrt4rev, sndwrt4): different scale if 0DBFS * cvanal.c (takeFFT): different scale if 0DBFS * aops.c (dbfsamp): different scale if 0DBFS (ampdbfs, aampdbfs): * aiff.c (write_aiffpeak): scale peak chunk * physutil.h: dbfs_to_float * cs.h: Declare e0dbfs, dbfs_to_float tran_0dbfs in cglob 2002-05-30 John * linevent.c: Changes from matt * opcode.h: new file * opcode.c: Internal reorganisation from matt * entry2.c: New opcodes midinoteoff, midinoteonkey, midinoteoncps, midinoteonoct, midinoteonpch, midipolyaftertouch, midicontrolchange, midiprogramchange, midichannelaftertouch, midipitchbend, mididefault * midiinterop.c: * midiinterop.h: New code, from Michael Gogins with some changes 2002-05-21 John * midirecv.c (m_chanmsg): reset aftertouch (m_chanmsg): Use mapping array (FMidiOpen): Additional check for null channel * midiops.c (midichn, pgmassign): New code * entry2.c: new opcodes midichn, pgmassign, scantable, scanhammer * wave-terrain.c (scanhinit): New code (scantinit, scantPerf): Also new code 2002-05-21 John ffitch * filopen.c (catpath): use characters rather than strings * pvfileio.c (pvoc_openfile): added search of SADIR if not a full path and not in current directory 2002-05-17 John ffitch * oscils.c (tablexkt): Function corrected in cubic interpolation case, and strings updated * midirecv.c (m_chinsno): Missing argument in printf added (FMidiOpen): Allow Format 1 with single track 2002-05-15 John ffitch * clfilt.c: New version with more cases 2002-05-05 John * physmod.c (clarinset): p->v_time should be initialised (clarinset): amp is not know at init time so do it all on first cycle 2002-04-30 John * entry2.c: Added clfilt opcode * fft.c (fftRESET): New function to clear lroot * disprep.c (disprepRESET): New function to clear fftcoefs 2002-04-28 John * entry2.c: Added xscanmap opcode * scansynx.h (struct PSCSNMAPX): New struct * scansynx.c (scsnmapx_init, scsnmapx): New code for xscanmap (scsnux_hammer): Add XALL and correct code 2002-04-27 John * argdecode.c (argdecodeRESET): New function to reset static stdinassgn * main.c (mainRESET): Added argdecodeRESET * fgens.c (gen30): Replaced with new version from Istvan 2002-04-21 John * sndinfUG.c (filepeak): Ensure channel is properly rounded * pvfileio.c (pvoc_getframes): Add setting of rc to nframes in bytereverse case * midiout.c (release_set): No need to check MIDIoutDone * main.c (MAIN): Check for null scorename or empty string * dnoise.c (dnoise): various changes to mill_macintosh stuff * argdecode.c: Message 1704 was wrong in source * aifc.c: * aiff.h: Change name of ApplicationSpecificChunk to AIFFAppSpecificChunk (avoiding mac problems 2002-04-17 John ffitch * otran.c (insprep): Assignment to ngotos was unnecessary 2002-04-04 John * diskin.c (sndwrtf): 32/64 float problem fixed (Istvan) (sndwrtfrev): Ditto 2002-04-01 John * pitch.c (Fosckk, Foscak, Foscka, Foscaa): New experimental code for oscil without power-of-two 2002-03-31 John * everywhere: glob -> cglob as it clashes on MacOSX 2002-03-29 John * sread.c (sget1): Must not call flushlin after #include 2002-03-28 John * VERSION 4.19 * midirecv.c (m_chanmsg): Removed code relating to non-functioning sysex 2002-03-26 John * soundin.c (getsndin): Various incorrect MYFLT changed to float (getsndin): twice 2002-03-24 John * biquad.c (vcoset): Changes from Hans (vco): * vbap_sixteen.c (vbap_SIXTEEN): removed references to p->counter as never given a value * vbap_four.c (vbap_FOUR_moving): Correct typo 2002-03-23 John * oscbnk.c (grain2): Whole function replaced (istvan) 2002-03-19 John * fgens.c (gen33,gen34): New gens 2002-03-18 John * entry2.c: Make second argument of vcomb and valpass an x-rate * fgens.c: Interpolation in gen18 * ugmoss.c: Revised code from pete moss 2002-03-13 John * entry2.c: Added terrain opcode * wave-terrain.h: * wave-terrain.c: New file 2002-03-12 John * midiops2.c (midic7): * insert.c (turnoff): rename curip to lcurip to avoid macro problems * cmath.c: holdrand moved to glob structure * ugens3.c: All over loscal -> LOSCAL * cs.h (LOSCAL): Defined as a constant 2002-03-11 John * argdecode.c (longusage): New function (decode_long): Complete all options 2002-03-10 John * pitch.c (isense): Now works in unix case * vbap_zak.c (vbap_zak_moving, vbap_zak): Off by one? (vbap_zak_init): Initialisation of gains vectors was wrong * vbap_eight.c (vbap_EIGHT_init): Change malloc to auxalloc, and adjust structure. Also use 'natural' output addresses (vbap_EIGHT_moving_init): Ditto * Ditto for vbap_four and vbap_sixteen 2002-03-09 John * cs.h: Define GLOBALS (onept, log10d20): made macros * main.c: Deploy a globals structure 2002-02-26 John ffitch * rdorch.c (getoptxt): Another fix in z,y,Z type arguments which affected event opcode (matt) * musmon.c (musmon): Correct editing error in ~MacClassic case 2002-02-21 John ffitch * sfont.c (fill_SfPointers): Add a skip for unknown chunks 2002-02-19 John * argdecode.c (argdecode): Changed -- to -O and started to add --long options 2002-02-17 John * sread.c (getscochar, sread): Adjust str if inputs changes * argdecode.c (argdecode): ignore --sched option * main.c (set_rt_priority): New code for Linux scheduling (Istvan) 2002-02-16 John * rdorch.c (getoptxt): Allow name translation on answerless opcodes * musmon.c (musmon): * main.c (MAIN): Added BETA message if appropriate * rdorch.c (getoptxt): Allow more x-rate arguments (why not?) * soundio.c (sfopenout): Typo in->out in PIPE code, and added modification of AIFC type to IRCAM 2002-02-15 John * fgens.c (gen12): Change name from gen22 at Gabriel's request * ugens4.c (pluck): Wrong error message (X_1478->X_1480) * sfheader.c (readheader): Clear the hdr structure before use * cwin.cpp (cwin_exit): Call _exit rather than exit * musmon.c (musmon): Change to setting of O.inbufsamps, now from O.oMaxLag 2002-02-14 John * VERSION 4.18 * cwin.cpp (OnMIDI): Added dialog and new class to deal with MIDI Not yet complete * ugmoss.c (dconv): i was not initialised * rdorch.c (splitline): C-comment fails if */ is at beginning of a line 2002-02-13 John * rtwin32.c: Fixes from RWD to separate in and out devices * rdorch.c (rdorchfile): * sread.c (sread): Changes so nesting of #include is unlimited 2002-02-12 John * pvdlg.cpp (DoDataExchange): Remove incorrect frame-size test * ugens4.c (riset): Typo (p->rand<1) should be (p->rand<<1) (riset): Also an else missing (riset): Rewrite clock/old initialisation 2002-01-31 * sfont.c (ChangeByteOrder): reverse bytes in MACOSX, and a number of bugs fixed in this one function * entry2.c: Added oscils, lphasor, tablexkt opcodes * oscils.c, oscils.h: new files 2002-01-30 * oscbnk.c: small changes all over * oscbnk.h: Some fields removed * spat3d.c (spat3d_init_wall): Revisions from Istvan (spat3d_wall_perf): and many others * spat3d.h: New fields 2002-01-26 * cs.h (PMAX): Increased to 1000, which will waste some space..... * oload.h (GVBAS): Redefine as VBAS + PMAX as in comment * fgens.c (FTPMAX): Increased to 150 * insert.c (orcompact): Call doadr if exixts * cscrorfns.c, express.c, fgens.c, insert.c, main.c, memalloc.c, musmon.c, oload.c, otran.c, rdorch.c, soundin.c, ugens3.c, ugens5.c, ugrw1.c: Made RESET code into mainstream * sfont.c (SoundFontLoad): Arcane bug fix in threaded activity * window.c (dispkill): Protect against no kill fn * getstring.c (init_getstring): SSOUND fix * argdecode.c (usage): In reentrant case do not die * musmon.c (musmon): External MIDI again Make kcnt externally visible * midirecv.c (csoundDefaultMidiOpen): New code for SSOUND (sensMidi): Allow user-defined MIDI input in SSOUND * memalloc.c (mfree): Check is all is NULL first (Michael) * main.c: Main main into MAIN and define macros for it to simplify going around * filopen.c (die): IN SSOUND case throw message * fgens.c (ftRESET): Revised for SSOUND (Michael) (gen22): Renamed from gen18 as that was misleading! * cscorfns.c (cscoreRESET): Fixes from Michael Gogins * cs.h: Added deinit field to OPDS and OENTRY 2002-01-22 * filopen.c: undef tell macro before using on mac * sndinfUG.c (filelen): Use aydsize field of p (getsndinfo): and set this field (getsndinfo): New code to look at -i file on command line * sndinfUG.h (struct): Added audsize to structures * sysdep.h (SYS5): Define in macintosh case * soundio.c (iotranset): Added check for rtplay in AE_FLOAT case * main.c (main): mill_macintosh -> mac_classic * linevent.c (RTLineset): mac_classic case needs setvbuf call (RTclose): similar * cs.h (POLL_EVENTS): Corrected mac optional stuff 2002-01-20 * sread.c (operate): Added bitwise operations (getscochar): Added bit operations to [], possibly wrong precedence? * gets.r: Added new strings and corrections * rdorch.c (getoptxt): Decoding or y z and Z arguments changed (intyperr): Additional argument for expected type 2002-01-13 * ugmoss.c (not_k, not_a): New code * fgens.c (hfgens): (fgens): Remove message about increasing number of tables * scansynx.c (scsnux_init): Add range check 2002-01-11 * ugens6.c (cmbset): Initialise p->coef to zero 2002-01-08 * entry2.c: Added opcode vcomb, valpass and ftmorf * ugmoss.h: New structures for new code * ugmoss.c (dconv): Code revised and optimised (Pete) (and_kk, and_kk, and_aa, and_ak, and_ka, or_kk, or_aa, or_ak) (or_ka, xor_kk, xor_aa, xor_ak, xor_ka): New functions for bit arithmetic (vcombset, vcomb, valpass, ftmorfset, ftmorf): New code * fgens.c (gen18): New GEN from Pete Moss 2002-01-06 * VERSION 4.17 * fgens.c (ftRESET): clear ftevt as well (ftgen): Allow gens 23 and 28 in ftgen opcode with strings * util2/mixer/extract.c (main): * util2/mixer/xtrct.c (main): * util2/mixer/mixer.c (main): * sysdep.h: * dpwelib.h: * pvoc.c: * pvanal.c (pvanal): * musmon.c (musmon): * main.c (main): * lpanal.c: * linevent.c: * filopen.c (isfullpath): * dsputil.c: * midirecv.c: Removed ZPC options 2002-01-05 * rdorch.c (getoptxt): Gabriel's (?) typo corrected * aops.c (ftchnls): added code for same * entry1.c: added opcode ftchnls 2002-01-01 * aops.c (cpsoctinit): * fgens.c (gen11): * physmod.c (BowTabl_lookup): * ugens7.c (newpulse): * ugensa.c (newpulse): * ugsc.c (phaser2): Use intpow function * ugens4.c (buzz): Minor optimisation (gbuzz): also minor optimisations (gbuzz): Use version of pow for integers, as should be faster 2001-12-31 * insert.c (infoff): Revised code from Gabriel for delaying off event during release * fgens.c (gen32): New gen (Istvan) 2001-12-27 * schedule.c (ktriginstr): From re to make initialisation in score order 2001-12-25 * scansyn.c: pinterp was plain wrong 2001-12-22 * entry2.c: Added k-rate active opcode * scansyn.c (scsnu_init): Space was wrong size in PHASE_INTERP != 3 case. * entry2.c: Added event opcode (is it needed?) * linevent.c (eventOpcode): New code from matt * musmon.c (playevents): Revised code from rasmus 2001-12-21 * musmon.c (playevents): Fixed another memory leak (re) (playevents): and reorganisation (sensevents): Same fixes 2001-12-19 * entry1.c: parsing of tablew was wrong in that it failed to check k- and a-rate versions. Same for tablewkt * main.c: Include * scansyn.c (listadd): The list of instances was not used properly. 2001-12-16 * spat3d.c (spat3di): Check for depth should be against maxdep not mindep * otran.c (otran): Reworked default sr/kr/ksmps code * oload.c: Initialise esr etc from trans_sr etc so defaults work 2001-12-14 * pvanal.c (pvanal): * lpanal.c (lpanal): * hetro.c (filedump, writesdif): * fout.c (outfile_set, koutfile_set, fiopen, kinfile_set) (i_infile): * sfont.c (SoundFontLoad): Removed code which changed access options for sfont files and others as it seems totally wrong to me. 2001-12-12 * musmon.c (sensevents): Free memory in schedule case (playevents): Ditto 2001-12-11 * sfont.c (SoundFontLoad): In access stuff after looking in SSDIR and SFDIR the check should be on pathnam. Still not sure why it does this! 2001-12-09 * VERSION 4.16 2001-12-08 * main.c (signal_to_string): Not for OSX 2001-12-07 * fgens.c (besseli): #define out * pvxanal.c (besseli): use this version 2001-12-06 * musmon.c (fillbuffer): Fix to allow scheduled events (matt) 2001-12-05 * fgens.c (besseli): Do all calculation in doubles as the MYFLTs were a delusion. * pvxanal.c (pvxanal): Check for all versions of .pvx wrt case * ugens1.c (klnseg): Rewrite to avoid rounding error, but at a cost 2001-12-04 * cwin.cpp (cwin_args): Remove zapping of O.outformat * ugens8.c: corrected reading of pvocex files for multiple notes (RWD) * soundio.c: Added floating noscasler and better checking 2001-12-01 * sread.c (sread): Added x to score language * ugens1.c (xdsrset): Make last segment very long * pvlook.c (pvlook): Added calls to POLL_EVENTS * vpvoc.c (vpvoc): initerror should be perferror * ugrw1.c (zkr): Call warning rather than perferror * uggab.c (trig): * ugensa.c (fog): * ugens7.c (fof): return needed after perferror * ugens5.c (lpread): initerror should be perferror (lpinterpol): initerror should be perferror (lpread): return needed after perferror * singwave.c (make_Modulatr, make_SingWave): Returns after perferror and also make make_Modulatr return a 1 if it failed * ugens4.c (pluck): * ugens1.c (knvlpx): * pitch.c (macset): * physmod.c (clarinset, fluteset, bowedset, brassset): * modal4.c (make_Modal4, marimbaset, vibraphnset, agogobelset): * mandolin.c (mandolinset): return needed after perferror * fm4op.c (make_FM4Op, FM4Op_loadWaves, tubebellset, rhodeset) (wurleyset, heavymetset, b3set, FMVoiceset, percfluteset): Returns after perferror and also make FM4Op_loadWaves return a 1 if it failed. * aops.c (cpstun_i, cpstun, inz): return needed after perferror * ugens1.c (adsrset1): Change test for empty segment to <= 0 from < 2001-11-21 * winEPS.c: Minor fix for Irix6.5 * musmon.c: Reorganisation from matt to allow external calling 2001-11-20 * soundio.c: Arg to open should not have b option 2001-11-19 * fgens.c: New gens 30 and 31 (Istvan) * soundin.c (sndgetset): Count was off-by-one in skipping * cvanal.c (takeFFT): Do not normalise raw or IRCAM formats 2001-11-18 * oscbnk.c (grain2set): New code (grain2, grain3set, grain3, rnd31set, rnd31i, rnd31k): New code (Istvan) * ugens6.c (deltap3): As below * vdelay.c (vdelay3): Optimisations from Istvan * *ALL OVER* introduce mac_classic and mills_macintosh macros * winEPS.c (PS_MakeGraph): Deal file file directory separator * soundio.c (sfopenout): Simplify last case * rtmacintosh.c (rtclose): Remove code marked HACK * pvoc.c: Use sysdep.h rather than special code * pvfileio.c: change write(files[ofd]->fd,(const char*)&... to write(files[ofd]->fd,(char*)&.... to compile on Mac * getstring.c (getstring): More cautious test for strings 2001-11-16 John ffitch * ugsc.c (svf): if provided Q is too small force to 1 (svf): Optimise code 2001-11-14 John ffitch * soundio.c (sfopenout): Added IRCAM format to 3:2000 case 2001-11-11 * sfont.c (SoundFontLoad): Extensive rewrite so it looks in multiple directories. * filopen.c: make ssdirpath and sfdirpath external 2001-11-10 John ffitch * biquad.c (moogvcf): check max is acceptable; if zero make 1 2001-11-07 * ugrw1.c (zakRESET): New function (Gabriel) * main.c (mainRESET): Added zakRESET * sfont.c: Corrected various constants * ugsc.c (resonr): Improved speed by using immediate variables rather than indirect. (resonz): ditto 2001-11-04 * sread.c (sread): Remove call to extend_nxp after label again as it was wrong. Allow salcblk to do this safely 2001-10-29 * biquad.c (rezzy): Protect filter if rez is zero * sread.c (getpfld): if ( = ) should have been if ( == ) (getpfld): twice 2001-10-22 * sread.c (sget1): Apparent off-by-one error in macro args fixed (expand_nxp): Should be mcalloc rather than mmalloc (salcinit): Ditto 2001-10-20 * sfont.c (SoundFontLoad): Improved error message when failing to open 2001-10-13 * pvfileio.c (pvoc_updateheader): Change variable pos to signed 2001-10-07 * cwin.cpp: Added BUTTON_DAC and supporting functions * oscbnk.h (OSCBNK_PHS2INT): Revised definition to improve phase calc (Ivan) 2001-10-06 * fgens.c: Extend fgen table to 42 (gen24, gen40, gen41, gen42): New code * uggab.c (ikRangeRand, aRangeRand, randomi_set, krandomi) (randomi, randomh_set, krandomh, randomh, random3_set, random3) (random3a): New Code * entry2.c: Added opcode cuserrnd and function urd * uggab.c (ikDiscreteUserRand, aDiscreteUserRand) (ikContinuousUserRand, aContinuousUserRand): New code 2001-10-01 * uggab.c (jitters_set, jitter_set, jitter2_set): Added initialisation of p->phs * pvread.c (pvreadset): * ugens8.c (pvset): Added additional checks (RWD) 2001-09-29 * VERSION 4.15 * getstring.c (getstring): Added a second argument to be the default string (init_getstring): Allow null db * aops.c (cpstun_i, cpstun): New functions * oscbnk.h: * oscbnk.c: New code * entry2.c: Added oscbnk * spat3d.c (spat3d): Corrected mindep to maxdep (Istvan) * uggab.c (jitter2_set, jitter2, jitter_set, jitter, jitters_set) (jitters, jittersa): New code from Gabriel * uggab.h: Added JITTER, JITTER2 and JITTERS * cmath.c (seedrand): Added holdrand to remember last random number (for vibrato) * entry2.c: Added vibrato and vibr; jitter, jitter2, jspline * uggab.c (vibrato_set, vibrato, vibr_set, vibr): New code from Gabriel * uggab.h: Added VIBRATO and VIBR 2001-09-02 * schedule.c (triginset): Added code from re to enable proper i-time operation (ktriginstr): and enable deferred-action instrument turnoff 2001-08-31 John ffitch * biquad.c (biquada): New code * entry1.c: Added biquada opcode 2001-08-26 * cwin.rc: Correct layout * ugens1.c (adsrset1): Clear out space if not skipping init * musmon.c (gettempo): New function * midiops.h (struct GTEMPO): * entry2.c: Add tempoval opcode 2001-08-25 * pvanal.c (pvanal): Allow .pvx, .Pvx etc * soundio.c (int24ptran): Need to output 0/1/2 or 1/2/3 depending on endianness * argdecode.c: Add declaration of readOptions * vdelay.c (reverbx_set): The division by esr was not assigned * entry1.c: Entry for soundin had 4 too few m's 2001-08-20 * pvxanal.c (pvxanal): Add total_sampsread * main.c (main): Call init_pvsys to be sure 2001-08-19 * VERSION 4.13 (yes i know should have been 4.14) * uggab.c (lpshold, loopseg, loopseg_set): New code * mxfft.c: * pvxanal.c: * pvsanal.c: * pstream.c * pvfileio.c: New code * memalloc.c: changes to avoid potential memory leaks * memfiles.c (find_memfile): New function (add_memfil): new function * sndinfUG.c (filelen): Handle pvoxex files (filepeak): Handle peak-chunks in all formats (anal_filelen): New function * ugens8.h: Added fields frInc and chans to PVOC structure * ugens8.c: Support for pvocex (pvset): Ditto (pvoc): Concern about memory leak (pvx_loadfile): New function * pvread.c (pvocex_loadfile): New function Support for pvocex files (pvreadset): Ditto * pvanal.c: Added pvstream stuff * entry2.c: Added opcodes =_f, pvsanal, pvsynth, pvsadsyn, pvscross, pvsfread, pvsmaska, pvsftw, pvsftr, pvsinfo * rdorch.c (argtyp): Allow f type, and simplify code (getoptxt): Ditto (intyperr): Ditto * otran.c: Added pvstreaming; include pstream.h, new variables lclpcnt and lclnxtpcnt (otran): Initialise lblnxtpcnt (otran): set in ip structure (insprep): Initialise lplnxtcpcnt (lclnamset): Recognise f variables (lcloffndx): ditto * cs.h: filename array larger in MEMFIL new field lblpcnt in INSTRTXT 2001-08-17 * soundio.c: * midirecv.c: * linevent.c: Added MACOSX case 2001-08-14 * entry1.c: Added deltapx and deltapxw opcodes * ugens6.h: Structures for deltap * ugens6.c (tapxset, deltapx, deltapxw): New functions * vdelay.c: patches from Istvan * entry2.c: Added spat3d. spat3di and spat3dt * spat3d.h: * spat3d.c: New code 2001-08-13 * bbcut.h: * bbcut.c: New code * entry2.c: Added bbcut opcodes 2001-08-08 J P Fitch * midirecv.c (sensMidi): Stupid typing error lost MIDI on Mac (Thanks to matt pointing this out) 2001-08-01 * oload.c (oload): Changed test for integer overflow to unsigned short * express.c: * otran.c: Removed (commented out) various messages about extending pools etc 2001-07-14 John ffitch * ugens4.h: New field in GBUZZ to remember last * ugens4.c (gbuzz): Remember last value to get sign of small denom case right (gbzset): Initial last to +1 2001-07-01 * makedb.c: * getstring.c: * Makefile: Changed extension from .txt to .xmg to avoid confusions 2001-06-18 * soundin.c (sndgetset): (sndinset): Use the field * soundio.h: Added a datapos field to SOUNDIN * lowpassr.h: Added data for recalculation avoidance * lowpassr.c (lowpr): Recalculate coefficients only if there has been a change (lowprx): Ditto 2001-06-14 * wave.c: * soundio.h: * soundio.c: * soundin.c (getstrformat, getsizformat, bytrev3, sndgetset) * sndinfUG.c (filelen, getsndinfo): * sfheader.c (readheader): 24bit support * diskin.c (sngetset, newsndinset, soundinew, sndwrt3) (sndwrt3rev, sndwrtfrev, sndo1set, sndo1set): 24bit support and bug fixes * cwin.cpp (class CArg, OnInitDialog): * cvanal.c (takeFFT): * argdecode.c (argdecode): * aiff.c (aiffReadHeader): Added 24bit support (write_aiffpeak): Ditto 2001-06-06 J P Fitch * fout.c (infile_set): Bug fix from Gabriel 2001-05-26 * ugens8.c (pvset): Remember value of mfp which seemed to be missing 2001-05-24 * soundin.c: Add n-channel support message, and change t0 input from upto 24 channels. * soundio.h: Changes to SOUNDIN structure to match * english-strings: new string 1556 2001-05-20 * vpvoc.c (vpvset): * ugens9.c (cvset): * ugens5.c (lprdset): * ugens3.c (adset): * soundin.c (sndgetset): * sndinfUG.c (getsndinfo): * pvread.c (pvreadset): * pvinterp.c (pvbufreadset, pvinterpset): * pvadd.c (pvaddset): * diskin.c (newsndinset, sndo1set): * OSC-sock.c (osc_send_set): * ugens8.c (pvset): Fence post. Need to check <= to use strset. 2001-05-18 * fgens.c (gen01raw): No need to check p->channel greater than ALLCHNLS with new value of that variable * cs.h (ALLCHNLS): redefined as 0x7fff which is maximum positive 2001-05-15 * dnoise.c: Merge back macintosh changes * babo.c (bround): changed name to avoid macintosh problems 2001-05-12 * perf.c (InitSioux): Make title string a Pascal string 2001-05-09 * pvanal.c (pvanal): Added -H option to control window type (Hamming/hanning) (takeFFTs): Use window type from variable WindowType 2001-05-05 * VERSION 4.13 * dnoise on macintosh fixed etc * argdecode.c (argdecode): Added -@ option to read command line from a file, using readOptions from csd format 2001-05-04 * linevent.c (sensLine): read may have got more than one line. Fix due to Timo Thomas 2001-05-03 * memfiles.c (LoadFile): Remove unused argument foo (ldmemfile): and in call * pvoc.c (PVReadFile): Remove function as seems unused 2001-05-01 * soundio.c (sfopenout): Added /dev/dsp as a synonym for dac on GNU/Linux 2001-04-18 * vdelay.c (vdelay): Ensure delay line is 1 longer for safety 2001-04-14 * pitch.h (struct PFUN): and structure * pitch.c (pfun): New function * entry2.c: Added p() function 2001-04-08 * insert.c: Declaration of opcodlst was wrong; make OENTRY* * vdelay.c (reverbx_set): Rewrote memory allocation to avoid nested auxch as that does not work (reverbx): and change usage in here 2001-04-07 * vdelay.c (reverbx_set): Increase size of auxalloc call as it was too small. 2001-04-03 * one_file.c (readOptions): Move the argv++ to after the tracing; and then remove totally as it is wrong 2001-03-25 * VERSION 4.12 * hetro.c (hetro): Need %lf in case 'M' as it is double (thanks to Jim Croson) 2001-03-20 J P Fitch * vdelay.c (vdelayxw,vdelayxws,vdelayxwq): Modifications from Ivan 2001-03-18 * rtwin32.c (recopen): Typing error (OUT instead of IN) corrected (thanks to Bobby McNulty Junior) 2001-03-06 * vdelay.c: Added opcodes * entry1.c: Added opcodes vdelayxwq, vdelayxws, vdelayxw, vdelayxq, vdelayxs and vdelayx * soundio.h: * sfheader.h: Ircam format should be float (not MYFLT) 2001-03-04 * uggab.c (mirror): A return added in xlow >= xhigh case 2001-02-28 * midiops.c (imidiaft, maftset, midiaft): New code for polyaft opcode * entry1.c: Added polyaft opcode * ugmoss.c: New file * ugmoss.h: New file * entry2.c: Added dconv opcode 2001-02-24 * pitch.c (maca): Ensure that it can be used with overlapping answer and argument variable (mac): Ditto * sread.c (expand_nxp): New function to expand space, and called from a number of places some new. * vdelay.c (reverbx_set): Correct level problem in reverb2 * uggab.c (sum): Ensure that it can be used with overlapping answer and argument variable (product): Ditto 2001-02-21 John ffitch * rdorch.c (rdorchfile): * sread.c (sget1): Allow escaped # in macro body 2001-02-18 * swrite.c: Allow sign after exponential (thanks to Paul Isaacson) 2001-02-17 * ugens6.c (delay): Allow input signal to be the same as output signal (log001): Make a #define constant rather than a variable 2001-02-14 * vdelay.c (reverbx): Copy the input into the temp buffer for the combs so input and output variables can be the same. 2001-02-13 * main.c (signal_to_string): Renamed sig2str as signal_to_string to avoid possible name clashes 2001-02-13 * one_file.c: Define L_tmpnam in Windows case as was too small. Also put the extensions back 2001-02-07 * one_file.c: Changed calls to tmpnam so they do not add the .orc or other extension as that seems to kill Windows2K 2001-02-06 * one_file.c (blank_buffer): Failed to increment i!! Thanks Gabriel. 2001-02-04 * VERSION 4.11 * pitch.h (struct): New field noinsert * pitch.c (waveset): Correct case when pointers meet 2001-02-03 * main.c (main): and use it * one_file.c (read_unified_file): Change argument to be char ** 2001-01-31 * pitch.c (wavesetset): Make length test for <=1 incase of MIDI use 2001-01-27 * util2/dnoise.dir/dnoise.c (main): Some messages corrected 2001-01-26 * one_file.c (read_unified_file): remove strcpy as there was no guarantee of sufficient space 2001-01-21 * lpanal.c (gauss): Removed false code based on assumption of pivot. 2001-01-20 * entry2.c: Added barriage opcode * pitch.c (wavesetset): New function (waveset): New function and opcode 2001-01-12 John ffitch * aifc.c (aifcReadHeader): General confusions fixed I hope (thanks RWD and Jim Crosson) * cwin.cpp (DisplayText): New function for flashtext 2001-01-11 John ffitch * soundio.c (sfopenin, sfopenout): "devaudio" has 8 characters not 7! * entry1.c: rtclock_i should not have had an argument but ftlen_i should 2001-01-06 * nsliders.tk (settext): New code to display text boxes (deltext): and to delete them * control.c (textflash): New function to display text windows * control.h (struct): New TXTWIN structure 2001-01-05 * VERSION 4.10 * soundio.c (sfopenout): Allow devaudio# and dac# as realtime players. 2001-01-02 * physmod.c: Comment out DLineA_clear as not used * hrtferX.c (hrtferxk): Make crossfade unused as it created clicks * express.c (copystring): New function -- like strdup but uses mmalloc (express): use copystring rather than fixed size arguments 2000-12-31 * util2/mixer/mixer.c (main): make default output have .wav or .aif tag as in main system 2000-12-30 * util2/dnoise.dir/: new utility to remove noise from samples * entry1.c: Added tbvcf opcode * biquad.c (tbvcfset, tbvcf): New code from Hans 2000-12-29 * entry2.c: Change name of opcode to "sensekey" * entry1.c: Change vco to have optional arguments * rdorch.c (splitline): A little more cautious in /* ... */ comments wrt newlines. (splitline): and fix some unclear bug by rewriting 2000-12-23 * entry2.c: Added keyhit as an opcode * entry1.c: rtclock opcode as _i and _k * aops.c (rtclock): Support for reading rt-clock * ugens4.c (rndset): Allow seed from clock is >1 (rhset, riset): Ditto * entry2.c: Entry for sense was wrong (needs 2 rather than 3 as no init) 2000-12-20 * entry1.c: Added additional optional argument to comb and alpass * ugens6.c (cmbset): Allow delay in samples for comb and alpass * ugens6.h (COMB): Add insmps optional argument to COMB 2000-12-18 * vbap_zak.c (vbap_zak_control, vbap_zak_moving_control): * vbap_sixteen.c (vbap_SIXTEEN_control) (vbap_SIXTEEN_moving_control): * vbap_eight.c (vbap_EIGHT_control, vbap_EIGHT_moving_control): * vbap_four.c (vbap_FOUR_control, vbap_FOUR_moving_control): It was possible for these to overwrite; loop now starts at 1 * sfheader.c (writeheader): * midirecv.c: * linevent.c (RTLineset): Minor preprocessing error * cs.h: Set _macintosh when necessary 2000-12-17 * entry2.c: New opcode lpf18 * pitch.h (struct LPF18): * pitch.c (lpf18set, lpf18db): New code for LPF with 18dB falloff. 2000-12-15 * swrite.c: Replaced fltout by fprintf -- still not sure about this! * pitch.c (ksense): Added use of _kbhit and _getch for Windows/DOS * pvdlg.cpp (DoDataExchange): Two cases were plain wrong! 2000-12-14 * lpanal.c: Some general code tidying 2000-12-11 * many files: standardise on _macintosh flag 2000-12-08 * argdecode.c (argdecode): Set utility title in mac * soundio.c (audwrt4): Skip code for now (audwrtrev4): Ditto * soundin.c (getsndin): from matt -- only set gain if positive 2000-12-08 J P Fitch * aops.c (dbfsamp): (ampdbfs): (aampdbfs): New code for full scale dB 2000-12-08 * argdecode.c (argdecode): Added call to create_opcodlst to ensure opcode list is made. * main.c (create_opcodlst): Cannot be static as needed elsewhere, like opcodes 2000-12-07 * sfont.c (fill_SfPointers): Added check for sfont format, and new X_1555 2000-12-06 * entry2.c: Added varicol opcode * pitch.c (varicolset): (varicol): New code for variable coloured noise. * pitch.h (struct): New structure for variable coloured noise 2000-12-05 * Cwin.cpp (OnSliders): Display sliders 1 rather than zero 2000-12-03 * VERSION 4.09: released * pluck.c: * wavegde.c: Rewrite significant parts; in particular remove general filter for 3 point FIR which is all that is used 2000-11-27 * aiff.c (aiffReadHeader): Str X_65 had arguments in wrong order in printf 2000-11-26 * pluck.c (pluckExcite): Move pickup point from here (pluckGetSamps): To here 2000-11-25 * wavegde.c (error): String 259 was wrong * pluck.c (pluckPluck): Change spurious floating point constants to FL() or integer. 2000-11-24 * uggab.c (lposc_set): Change from Gabriel/Rasmus * ugens3.c (loscil3): Added check for exact end of loop (loscil): (loscil): (loscil3): on advice from Hedman 2000-11-21 * fgens.c: Declare gen16 and add to table (gen16): New function 2000-11-19 * sftype.h: * sf.h: Corrected MSVC pack command * pitch.h: NSEG and TRANSEG structures * pitch.c (trnset, trnseg, ktrnseg): New code for transeg opcode * entry2.c: transeg opcode 2000-11-18 * ugens1.c (xsgset): Fixed potential bug in xsgset with reusing vector * sf.h: Added pack(1) for macintosh 2000-11-12 * sfont.c (filter_string): new function to remove unprintable characters which kill xterms etc 2000-11-06 * sfheader.c (readheader): Inadvertent change of AUDIO_ENCODING_FLOAT to AUDIO_ENCODING_MYFLT (writeheader): and again 2000-10-25 * entry2.c: setctrl allowed string argument * nsliders.tk: New function, setlab * control.c (ocontrol): Added case 4 to set label to slider 2000-10-16 * one_file.c (checkVersion): New function to allow version checking in .csd files (read_unified_file): And call it 2000-10-14 * ugens4.c (BIPOLAR): New constant (krand): (arand): (krandh): (randh): (krandi): (randi): Make 31-bit PRNG give bipolar results. * entry2.c: Added babo opcode * babo.c: * babo.h: New code [Note special copyright terms] from Nicola * ustub.h: Add peakchunks * oload.c (instance): * otran.c (insprep): * oload.h (LABELIM): Changed MINSHORT to MIN_SHORT to avoid silly problems 2000-10-11 * aiff.c (aiffWriteHdr): (aiffReWriteHdr): * wave.c (wavWriteHdr): Do not write PEAK if not wanted (wavReWriteHdr): Ditto * argdecode.c (argdecode): Case K for peak chunks * main.c (main): Add peakchunk variable 2000-10-08 * BeAudio.c: * Makefile.be: * argdecode.c: * cs.h: * main.c: * midirecv.c: * midisend.c: * rtBe.c: * sysdep.h: * vbap.c: * winBe.c: BeOS patches from Jens Kilian 2000-10-01 * one_file.c (readOptions): Added // and /* */ comments * rtlinux.c: Changed some floats to MYFLT (thanks to Nicola Bernardini) 2000-09-30 * vdelay.c: Simplified constants for cc_time and ca_time; comment out the original nreverb code * entry2.c: Made reverbx the nreverb code as it is a strict superset 2000-09-27 * vdelay.c (reverbx_set): (reverbx): New code, replacing vreverb code. * entry2.c: Added reverbx from re (replacing vreverb) 2000-09-25 J P Fitch * wave.c (wavReWriteHdr): One case of MYFLOAT should have been float (Nicola B.) 2000-09-24 * entry2.c: Added vreverb opcode * vdelay.c (vreverb_set): New code (vreverb): New code * vdelay.h (VREV): new struct * pitch.c (ksense): New code to read keyboard input * main.c (create_opcodlst): New function to create entry table from bits. (main): and use it * rdorch.c: Changed opcodlst to * from [] * oload.c: * otran.c: * opcode.c: * schedule.c * oload.c: Add declarations of opcodlst and oplstend as really here * entry1.c: * entry2.c: Replace entry.c 2000-09-22 * pitch.c (ksense): Added CWIN version of keysensing 2000-09-21 John Fitch * VERSION 4.08 * musmon.c (musmon): * main.c (main): Change banner to indicate 64bit version 2000-09-19 John Fitch * CSliders.cpp: New code for buttons and checks * CSliders.h: Ditto * Cwin.cpp: and the same * control.c (check_set): (check): (button_set): (button): Added for Windows 2000-09-17 * dumpf.c (nkread): Reading needs to take account of MYFLT * entry.c: Added button and checkbox opcodes * control.c (check_set): (check): (button_set): (button): New functions; also reorganise code for starting and reading * nsliders.tk: Added title. and pack -after for sliders. Should allow placement of buttons * pitch.c (impulse,impulse_set): Code for mpulse opcode 2000-09-16 * entry.c: Added impulse opcode (mpulse) 2000-08-27 John ffitch * phisem.c (bambooset): Shake_damp needs to be set; maybe on others as well? (wuterset): Ditto (sleighset): Ditto (guiroset): Ditto (tambourset): Ditto 2000-08-18 * Rename window.h to cwindow.h to avoid Windows problem. Change in many files including makefiles * ALL: FLOAT -> MYFLT to avoid problems with Windows * hetro.c: * soundio.c: * pitch.c: * aifc.c: * aiff.c: * aops.c: * argdecode.c: * biquad.c: * bowedbar.c: * butter.c: * cmath.c: * cross2.c: * cs.h: * cscorfns.c: * cvanal.c: * dam.c: * dcblockr.c: * diskin.c: * disprep.c: * dsputil.c: * dsputil.h: * dumpf.c: * extract.c: * fft.c: * fgens.c: * flanger.c: * fm4op.c: * follow.c: * fout.c: * grain.c: * grain4.c: * hrtferX.c: * insert.c: * interpol.c: * linevent.c: * locsig.c: * lowpassr.c: * lpanal.c: * lptrkfns.c: * mandolin.c: * midiops.c: * midiops2.c: * midiops3.c: * midiout.c: * midirecv.c: * modal4.c: * moog1.c: * moog1.h: * musmon.c: * musmon.c: * nlfilt.c: * oload.c: * otran.c: * phisem.c: * physmod.c: * physutil.h: * pluck.c: * ptrigtbl.h: * pvadd.c: * pvanal.c: * pvinterp.c: * pvocext.c: * pvread.c: * rdscor.c: * repluck.c: * revsets.h: * scansyn.c: * schedule.c: * sfont.c: * shaker.c: * singwave.c: * sndinfo.c: * sndwarp.c: * soundin.c: * soundio.h: * space.c: * spectra.c: * sread.c: * sysdep.h: * twarp.c: * ugens1.c: * ugens2.c: * ugens3.c: * ugens4.c: * ugens5.c: * ugens6.c: * ugens7.c: * ugens8.c: * ugens9.c: * ugensa.c: * uggab.c: * ugrw1.c: * ugrw2.c: * ugsc.c: * vbap.c: * vbap.h: * vbap_eight.c: * vbap_four.c: * vbap_sixteen.c: * vbap_zak.c: * vdelay.c: * vpvoc.c: * wavegde.c: * winEPS.c: * wincwin.c: * windin.c: * window.c: Deal with floating constants and in a few places corrected confusions between float and FLOAT ***** SPELL-CHECKED TO HERE ***** 2000-08-17 * soundio.c: flinbufp and floutbufp shoudl be float (not FLOAT) * pitch.c (GardnerPink_init): Variable float -> FLOAT * fout.c (infile_float): Sort out confusion between float and FLOAT * ugens1.h (struct EXPSEG2): float -> FLOAT 2000-08-15 * anal/adsyn/makef (OBJS): Include sdif code * sdif-mem.c: * sdif.c: * sdif.h: * sdif-mem.h: New file (SDIF again) * text.h (X_MAXNUM): Increase to 1551 * Hetro.c: added SDIF stuff 2000-08-14 * midisend.c: Added FreeBSD code for soundcard * argdecode.c (usage): Error message number changed for dithering to 1537. 2000-08-13 * entry.c: Add optinal argument to guiro -- a bug fix * sread.c (sget1): Typing error ommits c== in c=='_', twice 2000-08-07 * VERSION 4.07 * midiops.c (mctlset): Change default value to lo setting 2000-08-06 * entry.c: Added opcodes cabasa, "crunch", "sekere", "sandpaper", "stix", "guiro", "tambourine", "bamboo", "waterdrip", "sleighbells" * phisem.c: * phisem.h: New files for phisem instruments from STK 3.1 2000-08-05 * vbap.c (choose_ls_triplets): Move array connections to malloced space as rather too big for some architectures. * vdelay.c (nreverb): Set time to 0.001 instead of zero which gives inf values. Also test for <=0 rather than just negative. Also change error message 356 (reverb2_play): Ditto 2000-08-02 * main.c (install_signal_handler): Added support for OS/2 2000-07-30 * soundin.c (sreadin): Added WAV to code for AIFF/AIFC 2000-07-25 * swrite.c (fpnum): Allow E and e format in numbers 2000-07-22 * bowedbar.c: File file from STK3.1 * bowedbar.h: File file from STK3.1 * entry.c: Added wgbowedbar opcode 2000-07-17 * modal4.c (vibraphnset): Strike position was not set at all (agogobelset): Strike position now used, and modified gains * fm4op.c: All over changed ADSR parameters to STK3.1 values 2000-07-16 * physutil.c (ADSR_setAllTimes): New function to keep in step with STK3.1 * modal4.c (agogobelset): Change filter gains to value in STK3.1 (marimbaset): Ditto 2000-07-14 * aiff.c (aiffReadHeader): Added missing argument to message 2000-07-13 * filopen.c (sssfinit): Editing error corrected ## -> # * physmod.c (bowedset): Instantiated teh length/2 code as in later STK 2000-07-02 John Fitch * pvlook.c: Added code to log output from Windows * pvlookdlg.cpp: Added dialog info for output 2000-07-01 John Fitch * pvdlg.cpp (DoDataExchange): Check for illegal hopsize was backwards 2000-07-01 * sread.c (getscochar): * rdorch.c (rdorchfile): Patch (in part) from Istvan Varga for _ in macro names more safely 2000-06-26 * entry.c: Added clip opcode * one_file.c (createSample): New function to read base64 encoded samples (read_base64): New function to allow multiple use (deleteSamp): Delete samples created (read_unified_file): Added option and (createFile): Create file locally if safe from Base64 2000-06-23 * util1/sortex/xmain.c (fopen_path): * util1/sortex/smain.c (fopen_path): $s should be %s twice 2000-06-19 * rdorch.c (rdorchfile): * sread.c (sget1): Allow _ as a part of a macro name * one_file.c (createMIDI2): Added Base64 encoded MIDI files (read_unified_file): and direct to it 2000-05-28 * VERSION 4.06 * entry.c: Added trigseq and seqtime opcodes 2000-05-26 * pitch.c: Added pinkish code. * pitch.h (struct): Added PINKISH structure * entry.c: Added pinkish opcode (re) 2000-05-25 * entry.c: Added opcodes sfplay3, sfplay3m, sfinstr3, sfinstr3m * sfont.c etc: many changes. Lots of ANSI corrections and layout 2000-05-14 * entry.c: control and setctrl for Tcl/Tk and renamed for CWin * sliders.tk: New file (needs serch paths?) * control.c: Added Tcl/Tk version of sliders 2000-05-13 * getstring.c (init_getstring): Removed unnecessary new name variable, as also wrong! 2000-05-10 * aops.c (inall): Change to read a single numbered channel only 2000-05-09 * vbap.h: Added zak opcoes, increased channels to 64 * vbap_zak.c: New file * entry.c: Added vbap_zak opcodes 2000-05-08 * schedule.c: Change to triggering on negative triggers etc * midirecv.c: (MidiOpen): (MidiOpen): Added OS2 support * main.c (main): Added OS2 support 2000-05-07 * soundio.c (audwrite_norm): (audwrite): Make Heartbeat==3 use title bar in CWIN case * fgens.c (gen23): Use fopenin rather than fopen (gen28): Ditto * filopen.c (fopenin): Like openin, but also looks in INCDIR * vpvoc.c: Check that there is a segment table * aops.c (outz): New opcode to link XAK to output (inz): and input to zak * cs.h (MAXCHNLS): Change max number of channels to larger number 256 * aops.c (inn): New function for below (in16): (in32): (inall): New opcodes for larger numbers of channels * entry.c: Added opcodes inx, in32 and inc 2000-05-02 * makefile (CSRCH): Added vbap.c vbap_four.c vbap_eight.c vbap_sixteen.c * vbap.c: * vbap_four.c: * vbap_eight.c: * vbap_sixteen.c: * vbap.h: New files for VBAP opcodes * entry.c: Added vbap opcodes 2000-04-26 * entry.c: Change madsr to call madsrset as below * ugens1.c (adsrset1): Only set xtra time if in MIDI context. Rename function from adsrset (adsrset): New function to use above (madsrset): Ditto 2000-04-23 * rdorch.c (getoptxt): Decode out->outx/outX * aops.c (outn): new function to handle multi-channel outouts (outx): (outX): Use for 16 and 32 (outch): New code to write to numbered channel (outall): Write all channels of any number * aops.h: New structures OUTX and OUTCH * entry.c: New opcodes outx, out32 and outch 2000-04-22 * sread.c (getpfld): Check for curmem overflow in the loops (yeak!) 2000-04-21 * sftype.h: * sf.h: Added PACKED and pack() attributes 2000-04-16 * entry.c: Added additional argument to scans * scansyn.c (scsns_init): Made oscil_interp a selectable variable, defaulting to 4 (scsns_play): And at play time * scansyn.h (struct): Added variables to select interpolation scheme 2000-04-10 John Fitch * VERSION 4.05 released * fout.c (outfile_int_head): (close_files): * soundio.c (sfcloseout): (audwrite_norm): (audwrite): * wave.c (write_wavpeak): (wavReWriteHdr): * aifc.c (aifcReWriteHdr): * aiff.c (aiffReWriteHdr): Added verbose argument to control peak message 2000-04-04 * winX11.c (DrawGraph): Patch to deal with large graphs (David Ogborn) 2000-04-04 J P Fitch * fgens.c (gen23): Corrected deferred case 2000-04-03 * fgens.c: patched from David Ogborn 2000-04-03 J P Fitch * diskin.c (sreadinew): More peak stuff (sngetset): Ditto 2000-04-03 * util1/sortex/xmain.c (dies): Define this function * util1/sortex/smain.c (dies): Define this function 2000-04-02 * musmon.c (playevents): remove calls to write peak chunk as done elsewhere * soundio.c (audwrite_norm): Added normalisation stuff for WAVE floats (audwrtrev4): Same here (audwrt4): Abd fir none bytereversing version (sfopenout): FLOATS and LONGS now similar Call non-reversing fixups correctly 2000-03-31 * soundin.c: Changes all over to take account of gain stuff * sndinfo.c (sndinfo): Small change in case no data * sread.c (sread): Check can open file * one_file.c (read_unified_file): Check file was opned OK (createScore): Ditto * wave.c (wavWriteHdr): many changes to set correct variable-header length etc (RWD) (wavReWriteHdr): Ditto * aiff.c (aiffWriteHdr): Incorporate Peak chunk fully (aiffReWriteHdr): ditto (aiffReadHeader): ditto (aiffReadHeader): ditto (write_aiffpeak): Correct code (all RWD) * aifc.c: Extensive incorporation of Peak chuncks and other such (RWD) 2000-03-26 John ffitch * entry.c: Added opcodes scsnu,scsns, sfload, sfpreset, sfplay, sfplaym, sfplist, sfilist, sfpassign, sfinstrm, sfinstr * sf.h, sftype.h sfenum.h: * sfont.c: New files 2000-03-26 John * midiops3.c: * midiops3.h: Change char to unsigned char throughout 2000-03-25 John * scansyn.[ch]: New file implementing scanned synthesis * rdorch.c (lblfound): realloc forgot to multiply by sizeof(LBLREQ) (lblrequest): Did not extend in this case. * main.c (main): Added general signal handler to call exit so can do temporary clean-up 2000-03-22 John * musmon.c (musmon): Remove extraneous fclose(scfp) 2000-03-21 John ffitch * soundio.c (bytetran): Add optional dithering of output * main.c: Added declaration of dither_output * argdecode.c: Added -Z option, and new string 1485 2000-03-17 John ffitch * VERSION 4.04 (Linux only: no notes) * ugens5.c (atone): output could destroy input before it was used. (atonex): Ditto 2000-02-22 John ffitch * otran.c (otran): Calculation of tran_kr was wrong 2000-02-20 John ffitch * VERSION 4.03 * ugens4.c (krand): Added support for a base value (arand): (krandh): (randh): (krandi): (randi): * aiff.c (aiffReadHeader): If no loop in sample, pretend loops whole sample (experimental at present) * sfheader.c: Move definition of maxpos etc to this file * sndinfo.c: Change size of arrays to MAXCHNLS 2000-02-15 John ffitch * soundio.h: New structures for peaks * wave.c (write_wavpeak): * aiff.c (write_aiffpeak): New function * musmon.c (playevents): Call functions to write peak chunk * grain.c (agsset): Clear buffer if reusing 2000-02-13 John ffitch * wave.c (wavReadHeader): Started support for WAV loops * wave.h: Added smpl and SampleLoop structures * schedule.c (lfoa): Calculation of inc was wrong 2000-02-12 John ffitch * ugens3.c (losset): Default base freq to middle C if missing * entry.c: follow2 opcode * follow.c (envset): (envext): New code * follow.h (struct ENV): New structure 2000-02-07 John Fitch * one_file.c (mytmpnam): New function in WIN32 case * cs.h: Use mytmpnam of WIN32 systems 2000-02-06 John Fitch * util2/scale.dir/scale.c (main): Added code for M and P options (FindAndReportMax): Make return a value of maximum 2000-02-04 J P Fitch * util2/pvlook/pvl_main.c: Add #include for 2000-02-03 John ffitch * pvanal.c (pvanal): Set trfil to stdout in code rather than in initialisation. * midirecv.c (FMidiOpen): Set mfp to stdin in the open code rather than in initialisation. * getstring.c (init_getstring): #endif was one wrong line which broke CSTRINGS mechanism 2000-01-29 John ffitch * VERSION 4.02 * sread.c (ifa): Need tp set prvp2 in . and + cases, as well a ^ 2000-01-13 John ffitch * diskin.c, insert.c, memfiles.c, midirecv.c, pvanal.c * rtaudio.c, rtdirectX.c, rtwin32.c, wincwin.c, window.c, winwat.c Change IGNORE to IGN to please Windows 2000-01-07 John ffitch * musmon.c (musmon): Close the scfp file (sorted score) so it can be deleted. 2000-01-06 John ffitch * insert.c (kperf): Removed check for interaction in instr loop 2000-01-05 John ffitch * rtwin32.c: Change type of indev to HWAVEIN as it should have been * schedule.c (queue_event): Added cast to float for insno * cwin.cpp (OnHScroll): Incorrect & changed to && (AfterSizeChange): Ditto * cs.h (POLL_EVENTS): Error in cwin case? * ugrw1.c (tablew): Incorrect & changed to && (ktablew): Ditto 1999-12-05 John ffitch * fgens.c (gen23): Allow for negative numbers in reading, and initilaise p in open case. * insert.c (kperf): On Windows and Mac/BeOs silences were too long, possibly upto 127 cycles too long. 1999-11-27 John ffitch * midiops3.c: Throughout slider code ensure min++ is obeyed after the assignment (undefined in ANSI C) 1999-11-23 * Cwin.cpp (cwin_exit): Use special code rather than AwaitInput, using wait_for_char variable (cwin_exit): Ditto (OnChar): Set wait_for_char every time 1999-11-21 John ffitch * VERSION 4.01 * uggab.c (resony): Read flag field for log or linear separation * uggab.h: New field in RESONY structure * entry.c: Change in arguments to resony * schedule.c (queue_event): New function to schedule score events into future (schedule): Call insert_event or queue_event depending on when; note midi will only work on now events (kschedule): Same fix. 1999-11-20 John Fitch * wincwin.c (DrawGraph): Add call to cwin_paint back * cwin.cpp (cwin_show): If picture in ontop do not redraw 1999-11-20 John ffitch * all_strings, english-strings: Make version number print in x.xx format (237) * space.c (space): Use local variables rather than p->ch1 etc (RK) 1999-11-18 John ffitch * pvinterp.c (pvbufreadset): * pvread.c (pvreadset): Change test to less than 128 for small frame size (RK) 1999-11-18 John Fitch * argdecode.c (usage): Added message for -t0 and also error string 425 1999-11-07 John ffitch * VERSION 4.00 -- Version for CD-ROM * midirecv.c: Added AMIGA loading of * musmon.c (musmon): Only complain about no score if also no line events. * main.c (main): In normal use use a temporary for scorename and playscore; if -t0 use score.srt * argdecode.c (argdecode): usurp -t0 to mean keep tempraries 1999-11-02 John ffitch * flanger.c (wguide2): Separate a- and k- rate cases, for speed against mixing (wguide1): Ditto * english-strings: Added error message 424 1999-10-31 John ffitch * VERSION 3.591 * shaker.c (shakerset): Do not crash is number of beans is zero * fgens.c (gen21): Ensure a scale of zero is make 1 if argument is missing * midirecv.c (MidiOpen): Misplaced #endif moved () 1999-10-25 John ffitch * otran.c (insprep): Remove reassignment to nlabels, so it will act as a maximum. 1999-10-24 John ffitch * rdorch.c (skiporchar): New function to skip to end of line, string or file * fgens.c (besseli): Make besseli a double->double function (gen20): rewrite kaiser case for effeciency and accuracy * cmath.h: Make besseli a double->double function * ugens6.c (delwset): Remove nulling of last_delayr (delrset): Check for first-delayr rather than last-delatr (Groh) 1999-10-16 John ffitch * one_file.c (createScore): (createOrchestra): Use fputs rather than fprintf as should not interpret formats 1999-10-11 John ffitch * VERSION 3.59 * one_file.c (deleteScore): no longer static (same for sconame) * main.c (main): If no score given generate f0 86400 score, and arrange to delete at end 1999-10-10 John ffitch * main.c (main): Rearrange order of code to allow MIDI initialisation * one_file.c (my_fgets): New function to deal with PC/Unix/Mac files equally. * entry.c: Added ktableseg for tutorials * midiop2.c: * midiops3.h: Separate SLIDER* structs and code * entry.c: Correct structs for sliders 1999-10-09 John ffitch * otran.c (constndx): Initial poolcount set to 1 for SSTRCOD * vpvoc.c (vpvset): If a table is given use it rather than remembered table[x]seg * vpvoc.h (struct): New field in VPVOC structure for optional argument to set table from f ops * one_file.c (createMIDI): Skip to newline after reading a MIDI file (read_unified_file): Set O.FMidiin if a MIDI file was given 1999-10-05 John ffitch * linevent.c: If event is e no not complain about number of args * insert.c (MIDIinsert): Deal with pset in MIDI case (MIDIinsert): No error if psetdata set * one_file.c (read_unified_file): Only change Midi file if read (createMIDI): set flag * ugens1.h: Extra field xtra in LINSEG and EXPSEG * ugens1.c (mxdsrset): Added additional argument to length of release (lsgset): Set xtra to -1 (adsrset): Deal with additional release (lsgrset): Set to -1 (klnsegr): (linsegr): (xsgrset): (expsegr): (kxpsegr): More of same change 1999-10-02 John ffitch * biquad.c: * entry.c: removed "nlalp" pending clarification of IPR 1999-09-26 John ffitch * ugens5.c (tonset): Initialise constants more carefully (tonsetx): The same (tone): The same (tonex): The same (atone): The same (atonex): The same * ugens1.c (klnseg): Rewritten to be same as linseg wrt new segments 1999-09-25 John ffitch * nlfilt.c (nlfilt): Protect L field * cross2.c (Xsynthset): Stop changing ovlp and take new field (Xsynth): Use new field * windin.c (xyinset): Protect a number of fields * grain.c (ags): Stop p->kglen being overwritten * vdelay.c (nreverb): Ensure p->hdif and p->time are not overwritten * repluck.c (wgpsetin): Ensure p->plk is not changed * otran.c (constndx): Removed attempt to have unique constants as it breaks otherthings, not understood 1999-09-22 John ffitch * ugsc.c (phaser1set): Fix array limitations (phaser2set): Similar 1999-09-22 John ffitch * entry.c: Added phaser1, phaser2 and lowpass2 * ugsc.c (phaser1): (phaser2): (lp2): New code 1999-09-12 John ffitch * entry.c: Adjust args to wguide1/wguid2 * aops.c (powoftwoa): New function (logbasetwoa): New function 1999-09-09 John ffitch * express.c (express): Added a^p case whicg was missing * entry.c: removed opcodes from entry as well * ugrw1.c: remove deprecated instime[sk] * dumpf.c: Remove depricated names 1999-09-08 John ffitch * biquad.c (nlalp): (nlalp_set): New functions * biquad.h (struct NLALP): New structure * entry.c: Added nlalp 1999-09-07 John ffitch * musmon.c (musmon): Change commented-out test to O.Linein 1999-09-05 John ffitch * schedule.c: New code for schedkwhen * musmon.c (playevents): * insert.c (kperf): Look for orcevents as well * cs.h: Added OrcEvts field to OPARMS * entry.c: Add schedkwhen * ugens2.c (kphsor): Make phs a double, and consequent changes (phsor): phase and incr double, and consequents * ugens2.h: Make curphs double rather than FLOAT * uggab.c (posc): (kposc): (posc3): (kposc3): Allow negative freq * cwin.cpp (cwin_args): Set FMidiin when teh profile has one * ugens4.c (pluck): Error check for kcps exceeding sample rate * fgens.c (fgens): Typing error == instead of = 1999-08-30 John ffitch * otran.c (constndx): Sharing constants leads to problems so make each one unique 1999-08-29 John ffitch * pitch.c (pitch): Slight code shifting (re) * pitch.c (phsorbnk): New code for new opcode 1999-08-27 John ffitch * VERSION 3.58 * entry.c: New opcode pitchamdf * pitch.c (pitchamdfset): (medianvalue): (pitchamdf): New functions 1999-08-25 John ffitch * midiops.h: Removed MIDIVAL and MIDISCL as they are really MIDIKMB * midiops.c (midibset): Initialise prvbend as it was random (pitchbend_value): reinstate null check * entry.c: New opcodes adsynt and hsboscil * pitch.c (adsyntset): (adsynt): (hsboscset): (hsboscil): New functions * pitch.h (struct ADSYNT, HSBOSC): New structs 1999-08-23 John ffitch * repluck.c (streson): Change sign of output sample * one_file.c (eat_to_eol): New function to handle comments in <> context. (readOptions): Alow empty lines * sread.c (ifa): in case3 with warpin check for i or f opcodes 1999-08-20 John ffitch * ugensa.c (fogset): * ugens7.c (fofset0): Only allocate space if phs is positive; may allow legato * dumpf.c (krdset): (krd2set): (krd3set): (krd4set): openout shoudl have been openin * midisend.c: Define __RPCASYNC_H__ for VC++ v6 (Michael Gogins) * sread.c (sget1): * rdorch.c (rdorchfile): Deal with spaces in macro definitions (re) * one_file.c (read_unified_file): Close unf file before return 1999-08-05 John ffitch * wincwin.c (MakeXYin): (ReadXYin): Rewritten to use whole screen 1999-08-04 John ffitch * sread.c (sget1): * rdorch.c (rdorchfile): Make number of arguments flexible in macros 1999-08-02 John ffitch * VERSION 3.57 * pitch.c (cpuperc): New function to set cpu load (maxalloc): Ditto (prealloc): Ditto * cs.h: Added cpuload field to INSTRTXT 1999-08-02 J P Fitch * argdecode.c (argdecode): variable outformch made static (argdecode): Make it a warning rather than an error to have two values * main.c (main): [rasmus ekman] the default sampel size was set before the .csd decode. Now moved to after 1999-08-01 John Fitch * physmod.c (DLineA_tick): Test for wrapround was wrong 1999-08-01 John Fitch * vdelay.h: Added nreverb header to this fiel and remove nreverb.h * modal4.c (marimbaset): multiple strikes controlled by optional arguments * entry.c: marimba gains two optional arguments * modal4.c (marimbaset): Triple strike could not happen; fixed. Also made messages look at message level 1999-07-31 John ffitch * argdecode.c (argdecode): Make utility decode table driven, and add pvlook * util2/pvlook/pvl_main.c: New file to call pvlook * pvlook.c: New file (from Richard Karpen) changed to utility 1999-07-30 John ffitch * ugens6.c (delrset): (delwset): (tapset): Added FIFO * ugens6.h: Added delay FIFO to DELAYR 1999-07-29 John Fitch * diskin.c: Reconstructed after matt * insert.c: Reworked all POLLEVENTS stuff after matt * sndinfUG.c: New file for interrogation of snd files * entry.c: Added filelen, filenchnls, filesr and filepeak opcodes * musmon.c (playevents): Simplification of calls to POLLEVENTS * fout.c: mark non ANSI stuff as not on macintosh * one_file.c (macgetstring): Renamed function from getstring * argdecode.c (argdecode): -P option for Macintosh 1999-07-26 John Fitch * aops.c (init_powers): (init_logs): (powoftwo_set): (logbasetwo_set): (powoftwo): (logbasetwo): New functions for fast 2^ and log_2 * sread.c (sget1): Change test to >MARGS rather than >=MARGS * cscormai.c (main): Call init_getstring * natben.c: New file (for cscormai.c really, but could be used elsewhere) 1999-07-26 John ffitch * fgens.c (gen23): Added deferred allocation by counting first (fgens): Admit gen23 for deferred (hfgens): Ditto * ugens1.c (xsgset2): New function (expseg2): New function * entry.c: Added expsega 1999-07-25 John Fitch * rdorch.c (getoptxt): DIVZ case was confused with peak case; changed tag to 0xfffc * entry.c: Ditto * insert.c (beatexpire): Count deallocation (timexpire): Ditto 1999-07-25 John ffitch * entry: Added active opcode * pitch.c (instcount): New function to recover active count * insert.c (insert,MIDIinsert): Count new activation (deact): and uncount * cs.h: Added active filed to INSTRTXT * ugens4.c (buzz): (gbuzz): Take absolute value on khd and suppress warning 1999-07-20 John Fitch * rtwin32.c: Reworking by RWD after NT experience 1999-07-20 J P Fitch * pitch.c (clockset): Got clocks wrong in setup -- all mapped to clock 0 1999-07-19 John ffitch * RELEASED VERSION 3.56 * one_file.c (blank_buffer): new function to allow blank lines in gap * fout.c: New file * fout.h: New file 1999-07-18 John Fitch * winX11.c (ExitGraph): Ignore any errors 1999-07-18 John ffitch * sread.c (getscochar): Allowed @ in arithmetic part, and @@ for guard. Gives next power of 2 up, between 1 and 0x40000000 Also corrected ~ case 1999-07-10 John ffitch * uggab.c (fold): New function (after Gabriel, but optimised) (fold_set): * entry.c: Added resony, fold opcodes * uggab.c (rsnsety): (resony): New functions (after Gabriel to remove restriction) * uggab.h (struct): New structures for resony and fold 1999-07-08 John ffitch * insert.c (insert): Added psetdata handling on insert 1999-06-27 * Cwin.cpp (class CSenv): Dialog to set SSDIR etc (CArg): Remember last env in registry, and reset in non-null * winsound.rc: New Dialog for setting environment 1999-06-26 * getstring.c (init_getstring): Ensure name is remembered in Winsound * Cwin.cpp (OnEditOrch): Change to NOWAIT spawn of editor (OnEditScore): Ditto (cwin_exit): Interrupt playing if character typed 1999-06-26 John Fitch * follow.c (follow): Read off end of input; change to post increment 1999-06-20 John ffitch * VERSION 3.55 released * util1/scot/main.c (main): * util2/mixer/extract.c (main): * util2/mixer/mixer.c (main): * lpanal.c (lpanal): * sndinfo.c: * pvanal.c: Accept -j * getstring.c (init_getstring): Look for environment variable CSSTRNGS as well * argdecode.c (argdecode): Skip -j option * main.c (main): init_getstring needs arguments * getstring.c (init_getstring): Check for a -j command line parameter to change strings database. Messy! 1999-06-15 J P Fitch * cwin.cpp (OnExtras): Set Beatmode as well as Cmdtempo when needed 1999-06-05 John ffitch * aops.c: editting error, LIB1 rather than LIBA in asin to log10 (thanks Nicola) 1999-06-04 John Fitch * getstring.c (init_getstring): Change error string 1999-05-30 John ffitch * mandolin.c (mandolin): Rescale sound to get amplitude correct (infoTick): allDone was not initialised * mandolin.c (mandolinset): Added 50Hz as lowest frequency for Mandolin 1999-05-29 John Fitch * rdorch.c (getoptxt): Allow Z as an argument type for a list strating with a kvar, and alternating with avar 1999-05-29 John ffitch * ugens3.c (loscil3): There was no multiply by the amplitude. 1999-05-28 John ffitch * cwin.cpp (cwin_args): Do not add .wav/.aif if dac/devaudio 1999-05-27 John Fitch * text.h: New message * pitch.c (mac, macset): Added new opcode * ugsc.h: * ugsc.c: New files * entry.c: Added opcodes svfilter, hilbert, resonr, resonz. mac 1999-05-24 John Fitch * ugens4.c (buzz): Report knh <=0 once once per note (gbuzz): Same * ugens4.h: New field reported in BUZZ/GBUZZ to suppress excess messages 1999-05-20 J P Fitch * ugens1.c (linseg): (linsegr): (klnsegr): (kxpsegr): (expsegr): (klnseg): Test for out of count was wrong -- replaced by <= 1999-05-17 J P Fitch * VERSION 3.54 released * getstring.c: New file * cs.h: #include text.h * makedb.c: New file to build strings database 1999-05-10 John ffitch * ALL FILES nearly: Added STR macro to strings in preparation for localisation. Later changed to Str 'cos of Irix4 * text.h: new file for localisation. 1999-04-27 John Fitch * uggab.c (product): New code * entry.c: New opcode product 1999-04-27 J P Fitch * entry.c: Rename nsamp to nsamp_i so it can be used! 1999-04-18 John ffitch * main.c (main): Check for .csd and .CSD as DOS messes endings 1999-04-17 John ffitch * biquad.c (biquad): Optimise by using local variables more (pareq): The same (rezzy): The same (moogvcf): Same 1999-04-10 John ffitch * fgens.c (fgens): Added 0.5 to avoid rounding problems * musmon.c (playevents): * linevent.c: Accept e event 1999-04-09 John ffitch * entry.c: Added sum opcode * uggab.c (sum): Added new function * biquad.c (pareq): Changes /2 to *0.5, and stopped recalculation of sqrt 1999-04-06 John ffitch * rdorch.c (getoptxt): Gabriel changes for y and z argument types 1999-04-05 John ffitch * fm4op.c (FM4Op_loadWaves): Initialise w_time array to zero 1999-04-02 John ffitch * cwin.cpp (cwin_args): Add .wav or .aif if no . in name * soundio.c (sfopenout): Default name to test.wav test.aif or test depending on filetyp * rdorch.c (rdorchfile): Check for argument being too long * argdecode.c (argdecode): Section brackets neded in case 'o' due to #ifdef badly used. 1999-04-01 John ffitch * pvread.c (pvreadset): Correct error mesage to say PVREAD rather than PVOC 1999-03-31 John ffitch * biquad.c (vco): * vpvoc.c (voscili): * ugens7.c: * ugens4.c: * ugens3.c: * pvadd.c (pvadd): * spectra.c: * grain.c (ags): * disprep.c (tempeset): * ugensa.c: * ugens2.c: PMASK -> PHMASK for clarity, avoiding Solaris problem and consistency with Barry's sources. 1999-03-25 John ffitch * soundio.c (sfopenout): Piped output must be raw or IRCAM format. Force AIFF and WAv to IRCAM 1999-03-23 John ffitch * cmath.c (irate randoms): All improved coding to minor effect 1999-03-21 John ffitch * VERSION 3.53 * sread.c (getscochar): Accept ~ to indicate a random number * entry.c: Added pitch opcode * pitch.h: * pitch.c: New file * physmod.c (flute): Code improvements to save reading variables inside nsmps loop. 1999-03-20 John ffitch * sysdep.h (tell): Define tell is SYS5 case as it seems to be rare 1999-03-19 J P Fitch * entry.c: use 0xffd for peak opcode * rdorch.c (getoptxt): Use code 0xffd for discrimination on first argument (and not answer) 1999-03-19 John ffitch * soundin.c (soundin): * diskin.c (soundinew): only do code after filend in ngoto is strictly positive 1999-03-14 John Fitch * midiops.c (cpsmidi): Remove pitchbend stuff from cpsmidi * entry.c: Size field in aftouch was wrong 1999-03-11 J P Fitch * sread.c (stof): NeXT fix confusing ramps 1999-03-11 John Fitch * physmod.c (clarinset): (fluteset): (bowedset): (brassset): Assume 50Hz lowest freq if not given 1999-03-10 John Fitch * physmod.c (fluteset): Assume intital amplitude is maximum to avoid a problem with zero. Do not understand this yet, but something to do with ADSR AttackRate. 1999-03-09 John ffitch * entry.c: opcode envlpxr had wrong structure, so could have crashed 1999-03-05 John Fitch * mandolin.c (mandolinset): Allow for skipping initialisation, and add error check. * shaker.h: File not transferred to PC leading to crashes 1999-02-21 John ffitch * entry.c: Change names ondur/ondur2 to the more natural noteondur/noteondur2 Also chanctrl base opcode was missing * aops.c (ftlen): Change to call ftnp2find so any deferred table is loaded before giving teh length. 1999-02-20 John Fitch * ustub.h: Added declaration of currevent * vdelay.c (vdelay3): Setting of v0 could be wrong (possibly?) * pvadd.c (pvaddset): * pvinterp.c (pvcrossset): (pvbufreadset): (pvinterpset): * ugens9.c (cvset): * ugens5.c (lprdset): * ugens3.c (adset): * soundin.c (sndgetset): * diskin.c (newsndinset): Added support for string arguments in score (GAB) * rtnext.c: New file * Makefile: * diskin.c: * entry.c: * linevent.c: * midirecv.c: * sfheader.c: * soundin.c: * soundio.c: * soundio.h: * sread.c: * ugens2.c: Added NeXT code 1999-02-18 J P Fitch * entry.c: The ftsr opcode got lost * biquad.c (nestedapset): New code (nestedap): New code (lorenzset): New code (lorenz): New code * biquad.h: Added NESTEDAP and LORENZ struct 1999-02-14 John ffitch VERSION 3.52 * dumpf.c: Added readk code * dumpf.h: Added KREAD structures * entry.c: Added readk, readk2, readk3 and readk4 * ugens6.c (deltap): Safer test for tap point (deltapi): Ditto (deltapn): Ditto (deltap3): Ditto * swrite.c (pfout): (expramp): Allow () as alternatives to {} * sread.c (operate): Added % and ^ to arithmetic operations (getscochar): Ditto * uggab.h: Add structs for poscil and lposcil * uggab.c: Add code for poscil and lposcil and cubic forms * entry.c: Added poscil and lposcil, poscil3 and lposcil3 * follow.c (follow): Make it follow max abs value rather than max and min separately. Recode for speed as well. (flwset): Recoding for speed later 1999-02-13 John Fitch * sread.c (getscochar): Typing error strlen(b+1)=>strlen(b)+1 1999-02-13 John ffitch * ugens5.c (rsnsetx): Test for new buffer was wrong (tonsetx): Ditto 1999-02-12 John ffitch * ugrw1.c: Deprecated itable* opcodes * modal4.c: Added deprecated message to agogobel * entry.c: Changed all iout* to outi*, kout* to outk* ion/ioff -> noteon/noteoff. midic#/imidi# unified ctrl#/ictrl# unified itable* -> tablei* with deprecated version with message 1999-02-11 John ffitch * entry.c: Changes islider# to slider#_i, similar for slider# and dummy entry. ilimit removed for limit_i etc, itableleng itimes/k 1999-02-09 John ffitch * ugens5.c (tonsetx): Only create buffer of states if initialising and buffer not present. Should remove some clicks. (rsnsetx): Same change 1999-02-08 J P Fitch * aiff.c (aiffReadHeader): Recognise Name, Author, Copyright and Annotation chunks 1999-02-07 John Fitch * oload.h: LABELIM needs to reference nlabels rather than NLABELS * otran.c (insprep): Ensure that goto list is long enough, not just expanded -- probably not necessary * rdorch.c (rdorchfile): Need to extend srclin array as well as linadr array when run out of lines. 1999-02-06 John ffitch * entry.c: Change distort1 to appoo at HM's suggestion 1999-02-05 John ffitch * aiff.c (aiffReadHeader): Skip unknown chunks * biquad.c (biquadset): If reinit field is not zero skip initialisation * entry.c: Added optional extra arg to biquad to control reinit 1999-01-31 John ffitch * VERSION 3.511 * rtaudio.c: split into platform specific bits, and Makefile changed for this. * midiops.c (pitchbend_value): Remove subtraction (and comment) as now handled in midirecv.c * entry.c: all 3 midip_k opcodes shoudl have thread of 3 * distort1 should have thread of 4 not 5 * physmod.c (fluteset): Length of deay line set wrong if optional last argument omitted 1999-01-27 J P Fitch * ugens1.c (adsrset): Length incorrectly set in MIDI subcase. * diskin.c (newsndinset): Function replaced from matt 1999-01-26 John ffitch * sndwarp.c (sndwarp): New line from RK to handle rounding oddity (sndwarpst): Ditto 1999-01-26 J P Fitch * rdorch.c (fopen_path): Correct typing error of $s instead of %s 1999-01-26 J P Fitch * biquad.c * butter.c * cmath.c * dsputil.c * dsputil.h * filter.c * locsig.c * lpanal.c * modal4.c * oload.c * pvinterp.c * space.c * spectra.c * ugens8.c * vpvoc.c * wavegde.c * ugens3.c * fgens.c * prototype.h: Removed variable pi and twopi and used macros instead. In places improved code (ie use TWOPI rather than 2.0*pi) and in spectra.c corrected constants 1999-01-25 John ffitch * express.c (express): Deal with ^ when second argument is c k or i 1999-01-24 John Fitch * VERSION 3.51 * rdorch.c (rdorchfile): Change treatment of \ line continuations 1999-01-24 John Fitch * main.c (main): If argdecode returns zero then exit as all done 1999-01-24 John ffitch * one_file.c (readOptions): Lines starting ; or # treated as comments. Also options starting ; or # end line * follow.c (follow): Improved coding, removing divison etc 1999-01-23 John ffitch * entry.c: Added xadsr and mxadsr opcodes * ugens1.c (adsrset): Added release stuff for MIDI case (xdsrset): New function (mxdsrset): New function 1999-01-23 John ffitch * one_file.c: Changed some printing to _DEBUG only * main.c (main): Check for empty score string as well as null in .csd case * ugens1.c (adsrset): Calculation of length remaining corrected * cwin.cpp (OnOrchestra): Look for .csd files as well 1999-01-22 J P Fitch * one_file.c (readOptions): Check for \r as well as \n as terminator 1999-01-19 John ffitch * sread.c (sget1): Allow /* */comments in scores * rdorch.c (splitline): Correct /* */ comments * ugens2.c (koscl3): Bug in reading table fixed 1999-01-17 John Fitch * argdeccode.c: Take account of AE_24INT in part * soundio.h: Added AE_24INT * cmath.c (ipow, apow, kpow): * cmath.h: (POW) rename pow filed to powerOf to avoid Mac problem * physmod.c (bowed): All code for setting frequency and betaratio was wrong; re-writen. 1999-01-16 John ffitch * entry.c: Added envlpxr opcode which was missing 1999-01-15 John ffitch * physmod.c (bowed): Set slope field as was missing 1999-01-13 J P Fitch * VERSION 3.50 * otran.c (otran): Zeroing instrument table started in wrong place (insprep): Reset ngotos and nlabels at start of function 1999-01-12 John ffitch * vdelay.c (deltapn): Added deltapn 1999-01-10 John ffitch * biquad.c and biquad.h: Added pareq opcode * ugens6.c (deltap3): New function * ugens2.c: Cubic interpolating versions of foscl, loscil and table * entry.c: Change parameter of foscil(i) to xkxxkio * ugens3.h (FOSC): Added new fields for below * ugens3.c (foscili): (foscil): Make more parameters a-rate possibly * entry.c: Added p parameter to moodvcf * biquad.h (MOOGVCF): and max field * biquad.c (moogvcf): Added max scaling 1999-01-04 John Fitch * entry.c: slider (MIDI) opcodes added * midiops3.h: * midiops3.c: New files * entry.c: Added Gabriel Maldonado's slider opcodes 1999-01-04 John Fitch * ugens2.c (koscl3): (osckk3): (oscka3): (oscak3): (oscaa3): New code for oscilators with cubic interpolation * entry.c: Added oscil3 family of opcodes 1998-12-29 John Fitch * ugens1.c (adsrset): Adjust ADSR for sustain too short etc 1998-12-25 John ffitch * aops.c: Added mod?? functions * entry.c: Added mod?? opcodes * express.c (express): Added % operator as mod, somewhat odd as a float. * entry.c: octmidib had flag wrong (editing error I suspect) * midiops.c (icpsmidib_i): (octmidib_i): (pchmidib_i): New functions * entry.c: *midib in i context needs new functions so it is initialised * cs.h: Remove posbend field as not used now. * midirecv.c (m_chanmsg): Remove posbend field (m_chinsno): Send pchbend field * midiops.c (pitchbend_value): Use pchbend field rather than posbend 1998-12-20 John Fitch * version.h; VERSION 3.494 * main.c (main): Decode .csoundrc file * argdecode.c: New file with argdecode funcion * main.c (main): Call argdecode rather than in line * one_file.c (readOptions): Implement reading of options, calling argdecode * schedule.c (lfok): Phase calculation for sine was wromg (schedule): Added code to kill stragglers on reinit (schedwatch): Clear list when done (kschedule): Ditto 1998-12-19 John Fitch * schedule.c (kschedule): Argument count in call to insert_event was wrong by one 1998-12-12 John Fitch * entry.c: New opcode streson * repluck.c (stresonset,streson): New functions * repluck.h: New structure STRES 1998-12-01 John ffitch * rdorch.c (lexerr): Variable mm had incorrect initialisation (re) 1998-11-24 John ffitch * physmod.c (bowedset): Set 'unknown state' values to -1 as the value of zero could be found in the product. 1998-11-21 John ffitch * ugens4.c (arand): Correct a typing error which gave noise in short rand vresion. 1998-11-20 John Fitch * aiff.c, cvanal.c, filopen.c, hetro.c, insert.c, linevent.c: * lpanal.c, main.c, memalloc.c, memfiles.c, midirecv.c, midisend.c: * musmon.c, mw_menu.c, one_file.c, otran.c, pvanal.c, pvoc.c: * rdorch.c, rtaudio.c, sfheader.c, sndinfo.c, soundio.c, wave.c: * windin.c, dpwelib.h, scot.h, sysdep.h, cs.h: Changed __MWERKS__ for macintosh so as not to confuse the BeOS port 1998-11-18 John ffitch * PVDLG.CPP (DoDataExchange): Confusion over hopsize and frame ince sorted out * Cwin.cpp (OnExtras): Move saving of profile into tested area so m_midiselector is valid (rasmus ekman) 1998-11-16 John ffitch * express.c (express): Start to add ^ to expressions for pow 1998-11-14 John Fitch * VERSION 4.392 * aiff.c (aiffReadHeader): Make message understand n-channels * wave.c (wavReadHeader): Added line giving file name as helps sndinfo. Also extended to multi-channel * rdorch.c (getorchar): Ignore ^Z from a file so as not to upset MS-DOS files * ugens4.c: Incorporate new 31bit rand into old opcodes with selector * ugens4.h (struct): Added new field to RAND RANDI and RANDH to select which PRNG 1998-11-14 John ffitch * rdorch.c (getoptxt): Use linopnum to check size as flag rather than many calls to strcmp (getoptxt): Change wrong out[sqho] to a warning and patch * entry.c: Added dummy pow (I had forgotten) * rdorch.c (getoptxt): Added pow to list of translation opcodes 1998-11-09 John Fitch * entry.c: Added opcodes rand2, rand2h and rand2i * ugens4.c: New set of random operators based on 31 bit Park Miller PRNG using Linus Schrage's method for a better version 1998-11-09 John ffitch * midirecv.c: Many changes in LINUX code 1998-11-08 John ffitch * rdorch.c (getoptxt): Added filter2, and fixed bug in intrpol (should be ntrpol). * dumpf.c (old_kdmpset, old_kdmp2set, old_kdmp3set, old_kdmp4set): New functions for kdmpset etc with warning * entry.c: New opcode midion (same as kon), and rename kon2 as midion2. Added dump for kdump etc. kfilter2 and filter2 as filter2_z * midiout.c (kvar_out_on_set1): New function, same as kvar_out_on_set except prints message asking to use midion. 1998-11-07 John ffitch * midiout.h (struct): Many new structures * midiops2.h (MIDIIN): New struct * oload.h: New type PCTL_INIT * entry.c: Added opcodes pctrlinit and dpctrlinit (GAB) midiin, midiout kon2 nrpn cpstmid * oload.c (instance): Channel searching (GAB?) (ctlinit): New function * midisend.c: Changes to LINUX code * midiout.c (iout_on): (iout_off): (iout_on_dur_set): (moscil): (kvar_out_on): (out_controller): (out_aftertouch): (out_poly_aftertouch): (out_progchange): (out_controller14): (out_pitch_bend): Channel has 1 subtracted (GAB) * midiout.c (xtratim): Extend only more required * midiops.c (aftouch): (imidictl): (midictl): (pchmidib): (octmidib): (cpsmidi): (icpsmidib): (kcpsmidib): (ipchbend): (kpchbend): Use MIDI_VALUE or pitchbend_value * midiops.c (massign): Additional code to check instr exists * midiops.c (MIDI_VALUE): (pitchbend_value): Added new macros to check null case 1998-11-03 John ffitch * vdelay.c (vdelay): At last someone [Ed Hall] has sorted out this confused comparison (vdelay): and again * ugens6.c (comb): Alpha exponential problem [Ed Hall] * sread.c (salcblk): * otran.c (otran): Alpha alighment again [Ed Hall] * opcode.c (list_opcodes): Deal with setting n in a beter and portable way [Ed Hall] * oload.c (oload): On alpha need to ensure alignment [Ed Hall] * insert.c (showallocs): On Alpha print in %p format [Ed Hall] * soundio.c (audwrite_norm): * linevent.c: * aiff.c: Added LINUX to non-options (was MAC only) [Ed Hall)] 1998-11-02 John ffitch * ugens1.c (adsrset): segsrem set one too high I think. 1998-11-01 John ffitch * hetro.c (TWOPI): Correct constant from 6.28308530 to 6.28318530 1998-10-29 John ffitch * linevent.c: * soundio.c: * rtaudio.c: pipe etc renaming for LINUX as well as SGI 1998-10-25 John ffitch * schedule.h: * schedule.c: New files 1998-10-25 John ffitch * insert.c: Make tieflag visible for schedule (showallocs): Make visible externally 1998-10-22 John ffitch * entry.c: Added schedule and schedwhen 1998-10-20 John ffitch * version.h: VERSION 3.49 1998-10-20 John ffitch * entry.c: Added envlpr opcode * ugens1.c (evrset): (knvlpxr): (envlpxr): New functions * ugens1.h (struct ENVLPR): Replaced definition as was not used anyway 1998-10-19 John Fitch * entry.c: ntrpol incorrectly specified **************** Send to Matt and Dave ********************** 1998-10-18 John ffitch * entry.c: Added madsr opcode, uses linsegr and adsr code 1998-10-18 John ffitch * sread.c (getpfld): Allow {} and ~ characters in scores (ifa): ^ refers to previous event of any instrument; needs new variable which is set to -1 and reinitialialed at sections etc * swrite.c (pfout): Added {} as calls to expramp and ~ to randramp (expramp): New function (randramp): New function 1998-10-17 John ffitch * entry.c: Added opcodes biquad, moogvcf and rezzy * biquad.c: * biquad.h: New files * musmon.c (musmon): Change name CsMidiOpen to MacMidiOpen * midisend.c: Support for MAC * midirecv.c: MAC declaration of MacSensMidi (m_chanmsg): Now global (m_chn_init): Now global (sensMidi): Code for MAC * main.c (main): Minor changes for MWERKS (dribble_printf): New MAC version * aifc.c (aifcReadHeader): Changes for Matt 1998-10-13 John ffitch * version.h: VERSION 3.49 1998-10-11 John ffitch * entry.c: New opcode adsr * ugens1.c (adsrset): Added adsr opcode to link to linseg 1998-10-11 John ffitch * swrite.c (swrite): Avoid extra space at end of score components 1998-10-11 John ffitch * cs.h: Mke size field in OENTRY a short again!! * swrite.c (swrite): REemoved some extra code in Unix sources * Pvread.h (struct PVREAD): Make fftBuf of type AUXCH * Pvread.c (pvreadset): Fill in fftBuf as a dynamic structure with auxmalloc (pvread): And in its single place of use 1998-10-07 John ffitch * ugens8.h (PVFRAMSIZE): Increased to 8196 and consequent changes * cs.h: Make size field in OENTRY an int 1998-10-06 John ffitch * fgens.c (gen23): New table generator * entry.c: Added wguide1 and wguide2 * aiff.h (Float32Name): Change at Matt's suggestion * main.c (main): Call fflush in case 'V' * soundin.c (sndgetset): Remember curr_func_sr in gen struct * fgens.c (gen01raw): Added memory of curr_func_sr 1998-10-05 John ffitch * aops.c (ftsr): Put ftsr back! * entry.c: rename to ntrpol 1998-09-19 * entry.c: Added intrpol_X opcodes and trig * uggab.c: * uggab.h: New files * rdorch.c (getoptxt): Translate mirror and wrap in _i context 1998-09-16 * ugens5.c (tonsetx): New function after Maldonado (tonex): Ditto (atonex): Ditto (rsnsetx): Ditto (resonx): Ditto * entry.c: Added opcodes tonex atonex resonx * ugens5.h: Added TONEX and RESONX structures 1998-08-25 John ffitch * musmon.c (musmon): Load orchestra before opening MIDI file 1998-08-24 John ffitch * entry.c: Entry for specptrk not in agreement with manual specdisp shudl have last argument optional 1998-08-23 John ffitch * oload.c (oload): NULL out new part of strsets when extending 1998-08-22 John ffitch * ugens4.c (rhset): Correctiosn to older version (buzz): Change the error on knh<=0 to warning and assume 1 1998-08-21 John ffitch * spectra.h: * spectra:c Added spectrum opcode * rdorch.c: Allow w op s,.. opcodes * fgens.c (GENUL): Added this function to stand for unknown gens * entry.c: Add spectrum opcode 1998-08-20 John ffitch * entry.c: Rename kport -> portk etc * wincwin.c: Remove tracing * sread.c (sget1): Another attempt at the interaction between \ and comments * entry.c: ktableseg and ktablexseg renamed as tableseg and tablexseg * midirecv.c (MidiOpen): Ensure m_chnbp array is NULLed and re-layout * soundio.c: * soundin.c: * sndinfo.c: * main.c: * diskin.c: * aifc.c: Change string AIFC to AIFF-C for consistency * midirecv.c (m_chanmsg): Add PROGRAM_TYPE case as was missing * opcode.c: In full case try to maintain better layout * lowpassr.c: Various adjustments * opcode.c: Change to 3 columns 1998-08-19 John ffitch * sread.c (sread): Correct typing error od 1.1 to 1.0 (ifa): Only warp p3 in i case 1998-08-18 John ffitch * ugens5.c (reson): Save value of asig at end (areson): ditto 1998-08-15 John ffitch * vpvoc.c (vpvset): * ugens9.c (cvset): * ugens8.c (pvset): * ugens5.c (lprdset): * ugens3.c (adset): * pvread.c (pvreadset): * pvinterp.c (pvbufreadset): * pvadd.c (pvaddset): * diskin.c (newsndinset): Allow strset in opening * oload.h (STRSMAX): Reduce this to 8 as it grows * oload.c (oload): Make strsmax a variable and expand table as required 1998-08-07 John ffitch * lowpassr.h * lowpassr.c: New code * entry.c: Added opcodes lowres, lowresx and vlowres * oload.c (instance): Deal with strset and pset specially * otran.c: Make ngotos visible * soundin.c (sndgetset): Treat strsets in opening a file * soundio.c (sfopenout): Treat output null as /dev/null * sfheader.c (rewriteheader): Support for /dev/null selection * cwin.cpp (set_up_argv): Allocate 1 longer to argv as it was bust 1998-08-06 John ffitch * otran.c: Make nlabel visible externally * oload.c (oload): Try copying string in STRSET (instance): Make nlabels into an extern and allocate lopds dynamically. * otran.c (otran): Deal with strset specially 1998-08-05 John ffitch * musmon.c (beep): On CWIN use system function Beep 1998-08-04 John ffitch * midirecv.c (m_chinsno): Check diasslowed instr 0 * sread.c (getscochar): * rdorch.c (getorchar): Map '\r' to '\n' * midirecv.c (m_chanmsg): Chsange O.SusPThresh to non zero * cs.h: Remove O.SusPThresh field * cwin.cpp (class CSextras): Remove m_pedal and all references 1998-08-03 John ffitch * rdorch.c (LENMAX): Reduce LENMAX to 100 as rather too generous 1998-08-02 John ffitch * RELEASE VERSION 3.484 1998-08-01 John ffitch * sread.c (sread): Introduce warp_factor for local time warping -- multiple scales etc. Defaults to 1.0, reset at section. Uses v * rdorch.c (lexerr): * sread.c (scorerr): Initialise mm * soundio.c: Changes to reporting in sfopenin/out * aifc.c (aifcWriteHdr): Argument order in memcpy wrong 1998-07-31 John ffitch * rdorch.c (splitline): Use realloc rather than alloc and copy for extending groups (twice) 1998-07-29 John ffitch * entry.c: Change addxx to add_xx etc * express.c (express): Another place where ki should be i_k Also change tags to _xx * flanger.c (flanger): Fix a JPff error in flanger 1998-07-28 John ffitch * entry.c: Last argument to flanger shoudl be v (optional 0.5 default) * sread.c (sget1): Use fopen_path function * rdorch.c (fopen_path): New function to use pathnames in include -- and elsewhere perhaps (rdorchfile): Use function 1998-07-26 John ffitch * sread.c (scorerr): New function for score errors in macros etc (getscochar): Give it an argument to say if we are expanding $ and [ 1998-07-25 John ffitch * lpanal.c (alpol): Removed reclaration of arrays a and x from alpol as it was inside the loop! * cwin.cpp (cwin_ensure_screen): Make it into a int function for new POLL_EVENTS() * aifc.c: New File * aiff.c (is_aiff_formtype): New function * aiff.h: AIFC-32 float support (MWERK only??) * windin.c (xyin): MWERKS version * wave.c (wavResetFrameSize): New fn for MWERKS * soundio.c: * sfheader.c: * sndinfo.c: MWERKS and AIFC support * rtaudio.c: MWEKS support all over * main.c: MWERKS suport and changes for AIFC * wavegde.c: * sysdep.h: * pvinterp.c: * pvanal.c: * otran.c (insprep): * musmon.c: * midirecv.c: * memfiles.c: * memalloc.c (memdie): * lpanal.c (lpanal): * linevent.c: * insert.c (kperf): * hetro.c (hetro): Added MWERK support * fgens.c: fmax renamed maxfnum 'cos of MWERKS name conflict * ftgen.h (MAXFNUM): Chane of name from fmax * filopen.c: * DPWELIB.H: MWERKS support * cvanal.c (cvanal): Add MWEKS to SYMANTEC if defined * cs.h (POLL_EVENTS): Make -i in cases when not used * butter.c: Added MWERKS support 1998-07-24 John ffitch * opcode.c (list_opcodes): Comparison stops at _ by copying strings * sread.c (sget1): heck #include file opened * rdorch.c: Use linepos rather than the broken atbol (rdorchfile): Check that #include file can be opened 1998-07-23 John ffitch * rdorch.c: * sread.c: Allow digits in macro names in both definition and use, by isdigit when not first chararcter 1998-07-22 John ffitch * soundin.c (sndgetset): Bug fix from Matt 1998-07-21 John ffitch * rdorch.c (getoptxt): Translate to divz_..; and for oscil(i_.. * entry.c: Put _ in divz opcodes and oscil(i) 1998-07-20 John ffitch * entry.c: Make gauss etc using the translate flag * rdorch.c (getoptxt): Us a flag of 0xffff to indicate ned for name translation. Move various midi ops to this syste 1998-07-19 John ffitch * main.c: Removed all references to Scot * fgens.c: Changed GEN01 to GEN1 in error messages etc. (gen20): Replaced large declared arrays with mmalloc'ed space which extends. * physmod.c (JetTabl_lookup): Remove fictious JetTable class, as it did not use the provious value. (flute): Change arguements to JetTabl_looup * flute.h: Added lastJet field Remove JetTabl field as not used * physmod.c (flute): Reorganise flute, setting of frequency when changed only etc. Sounds better. (fluteset): Minor initialisations of lastFreq and lastJet. 1998-07-18 John ffitch * physmod.c (DLineA_setDelay): Check that it is initialised; also fix serious typo in initialisation skip. * otran.c (otran): I had missed changing string "r=" to "=_r" Also check string has second char of _ rather than first of r * sread.c: New variable (flushing) to indicate when not to deal with [] things in scores (getscochar): Use it (flushlin): And set it 1998-07-17 John ffitch * physmod.c: For all physical models in theis file, if lowestfreq is negative, skip initialisation. (clarinet, flute, bowed, brass) 1998-07-13 John ffitch * flanger.h: * flanger.c: New file * entry.c: Added flanger entry * fgens.c (fgens): It cleared new part of table one too soon (hfgens): Ditto twice [Thanks Matt] 1998-07-11 John ffitch * otran.c (otran): It checked against MAXINSNO rather than maxinsno and so wiped out all instrs over 200! * fgens.c (gen01raw): Check against ALLCHNS-1 rather than 4 for channel count. (gen04): Suspected editing error as it went off end of the array. Moved an assignment outside loop. Should check old code. * winsound.rc: Change OK button to Render * ugens4.c (rhset): If seed provided is greated that 1 use it directly rather than scaling. * entry.c: Many function renames from axxx -> xxx_a etc * express.c (express): Make functions have _k at end rather than k at start. Fixes name polution problems. 1998-07-10 John ffitch * sfheader.h: Remove readopensf macro as not used anywhere! 1998-06-27 * otran.c (otran): Mistype of MAXINSNO instead of maxinsno 1998-06-25 John ffitch * entry.c: Removed voscili * vpvoc.c: 1998-06-24 John ffitch * entry.c: Removed extra argument in shaker opcode 1998-06-24 J P Fitch * shaker.h: Removed numtimes from structure as not used. 1998-06-23 J P Fitch * version.h: VERSION 3.483 * entry.c: Arguments for aftouch were wrong; made 2 optional * otran.c (otran): Allow STRSET in header blk 1998-06-15 J P Fitch * diskin.c (newsndinset): Bug fix from Matt * soundin.c (sndgetset): Bug fix from Matt 1998-06-02 * version.h: VERSION 3.482 1998-05-29 * Fgens.c (ftresdisp): Only call display if not already displayed displayed new variable. Many tables were getting displayed twice. May be better ways to do this though (fgens): Initialised this variable 1998-05-20 John ffitch * linevent.c (sensLine): If n negative Linend was wrongly set 1998-05-17 * rdorch.c (rdorchfile): Make stray # into a warning rather than error (getorchar): Remember when at start of line (rdorchfile): Only check # when at beginning of line 1998-05-15 John ffitch * sread.c (sread): Correct 'b' case of character in score which is unwanted. * wincwin.c (DrawGraph): Remove call to cwin_paint which was causing each graph to nbe drawn twice 1998-05-14 John ffitch * Cwin.cpp (cwin_args): Set o.outbufsamps from oMaxLag from profile. (OnExtras): Set value to half m_buffer. * pvdlg.cpp (Cpvdlg): Editing errors had left LPC in the initialisations * ugens5.c (tone): (atone): (areson): Coding improvements * soundio.c: Remove incorrect sol support (actually elsewhere) * rtaudio.c: Added solaris support from Sweden * winX11.c: Added casrs to (Window) in various unnecssary places * solarisAudio.h: * solarisAudio.c: New files * cs.h (VARGMAX): Increase to 801 as I cannot see how to make dynmaic yet. 1998-05-11 John ffitch * sread.c (getop): Include 'c' as valid score opcode 1998-05-09 John ffitch * FLUTE.H: lastamp field defined * sread.c (sread): Introduce 'c' as score option to reset a clock base, declare variable, and add top2 fields 1998-05-08 John ffitch * PHYSMOD.C (flute): Reset maxPressure aas a result of k-rate amp 1998-05-02 * rdorch.c: Changes to record names of files and macros and line numbers; new function lexerr to decode all this. 1998-04-28 John ffitch * main.c (main): Allow SET SFOUTYP=IRCAM, and -J option to set it. * soundio.h (TYP_IRCAM): Define new constant 1998-04-27 J P Fitch * otran.c (otran): Need to NULL realloced proportion of instrtxtp array. 1998-04-22 J P Fitch * version.h: Version 3.481 * dcblockr.h: * dcblockr.c: New file * entry.c: Added dcblock opcode 1998-04-21 John ffitch * cross2.c (Xsynthset): The treatment of the base of the buffer would lead to problems with second use or memory recovery. Do not change base. 1998-04-16 J P Fitch * rtaudio.c (rtclose): Use *pcurp2 * musmon.c: Make new variable pcurp2 for WIN32 case. * ugensa.c (newpulse): Extra line setting ovp->formphs added at suggestion of rasmus.ekman 1998-04-15 John ffitch * VERSION 3.48 Tue Apr 14 12:41:54 1998 * oload.c: Remove second declaration of gbloffbas as reduntant. 1998-04-12 John ffitch * util1/sortex/xmain.c (synterr): Added definition * util1/sortex/smain.c (synterr): Added definition of synterr * shaker.h: New field, freq, for below. * shaker.c (shaker): Take acount of frequency argument by calling the filter. * soundio.c (audwrite_norm): Heartbeat formats 1 (as before), 2 (string if .s) and 3 (time in output). (audwrite): The same * main.c (main): Accept a digit after -H for various styles of reporting 1998-04-12 John Fitch * space.h: * locsig.h: * locsig.c: * space.c: New files * entry.c: Added new opcodes for location/space * fgens.c: Added gen28 to tables (fgens): Defer allocation for gen28 as well (hfgens): Same 1998-04-10 * linevent.c (RTLineset): Allow pipes as input to -L * entry.c: Added printk2 opcode * ugrw1.c (printk2set): (printk2): New functions for new opcode * ugrw1.h (struct): PRINTK2 added * linevent.c (RTLineset): Set no buffering if no fcntl function case * rtaudio.c (rtplay): Coding changes to stop re-evaluations [Windows version] Many changes to record for Windows and closing 1998-04-08 * ugensa.c (newpulse): Change to *fund!=0 case [Ekman] * ugens7.c (fof): Treat fractions of grain properly in fof2 case [Ekman] * entry.c: asin, acos and atan renamed sininv, cosinv and taninv Also rename atan2 as taninv2 1998-04-05 John ffitch * entry.c: Aded atan2 operations * aops.c: Added atan2 operations 1998-04-05 * sread.c (getscochar): Add /* */ comments in scores * rdorch.c (copy_arglist): New function to copy argument definition from fixed buffer to new space (getoptxt): Use fixed nxtarglist and copy (getoptxt): Optional arguments are special case * diskin.c (newsndinset): Round error fix from Matt. 1998-04-04 * rdorch.c (rdorchfile): Moved allocation of ARGSPACE to place where orchestra size is known. (rdorchfile): Extend ortext area as needed. 1998-04-03 * rdorch.c (getoptxt): Try to extend ARGSPACE array with realloc * cwin.cpp (OnMouseMove): Remember mouse position on movement * wincwin.c (MakeXYin): Implement (ReadXYin): Implement 1998-04-02 * sread.c: Many changes to add macros and repeats 1998-03-27 * pvadd.c: New file * pvadd.h: New file * entry.c: Add pvadd opcode 1998-03-26 J P Fitch * filopen.c (WR_OPTS): Correct order so Microsoft format is seen before WIN32 (which is really Watcom I guess) 1998-03-24 * rdorch.c (splitline): Added support for C-style comments 1998-03-23 * rdorch.c: Major changes to add macro facility, #include also 1998-03-16 * midirecv.c (m_chanmsg): Change insalloc to instrtxtp->instance * oload.c: Remove declaration of insalloc * insert.c (insdealloc): Removed reference to insalloc array as never initialised. Use instance field of instrtxtp instead 1998-03-15 * physmod.c (bowed): DlineL_setDelat was not set if no vibrato 1998-03-14 * physutil.c (DLineL_setDelay): Add check for delay too big * physmod.c (fluteset): Remove calls to OnePole and DCBlock clear * physutil.c (DCBlock_clear): remove (OnePole_clear): Remove * physutil.h: Remove lastOutput from OnePole and DCBlock * AIFF.C (aiffReadHeader): SEEK_CUR -> SEEK_SET (aiffReadHeader): twice 1998-03-13 * FILOPEN.C: Add WR_OPTS case for MSVC 1998-03-06 * Cwin.cpp (OnExtras): Set O.FMidiin when a midi file is specified (OnMidifile): Add *.mf midi files to types recognised 1998-03-04 J P Fitch * physmod.c (clarinset): (fluteset): (bowedset): (brassset): Cannot be sure frequency given, so reorganise initialisation of frequency, including moving code to the performance function 1998-03-01 * cwin.cpp (cwin_exit): Use cwin_full_program_name for repeat use rather than plain winsound; hence does not have to be in search path * otran.c (otran): and use argument * rdorch.c (getoptxt): Give function an argument for reinit 1998-02-27 * lptrkfns.c (TWOPI): Replace variables by #defines * cross2.c (getmag): max was not intitalised so could have random results. * vdelay.c (multitap_set): max was not intitalised so could have random results. 1998-02-25 * physmod.c (bowed): When checking to see if betaRatio has changed one needs to incorporate frequency. Made lastbeta field into product of beta and freq (bowedset) Consequence of above 1998-02-22 * soundio.c (sfopenin): Added | syntax in -i files (sfopenout): and -o files (sfclosein): Deal with pipes in closing (sfcloseout): and the other kind 1998-02-21 John Fitch * soundin.c (sreadin): Denormalise floating WAV files * rtaudio.c (getWaveOutDevices): New Function (getWaveOutName): New Function (playopen): Allow menu selection if device * midisend.c (openMIDIout): Replace NULL be 0 twice for ignored arguments (openMIDIout): Firest argument to sscanf missing! * dpwelib.h: Add _MSC_VER as well as SYS5 for strchr etc * soundio.c (audwrite_norm): New function for normalised floats (sfopenout): And arrange to call it * hetro.c (hetro): * sndinfo.c (sndinfo): exit onlt for non-CWIN * lpanal.c (lpanal): Use return in CWIN rather than exit (lpanal): Again * pvanal.c (pvanal): Use exit if in CWIN variant * ugens3.c: Moved declaration of isintab to top * wave.c: Many changes for completing floating samples * memalloc.c (memreset): Correct typing error 1998-02-17 J P Fitch * entry.c: Added nreverb opcode, and make reverb2 the same * nreverb.h: New file * vdelay.c (nreverb): New function (nreverb_set): New function (reverb2_play): (reverb2_set): Removed (well #defined out) 1998-02-05 John Fitch * rdorch.c (getoptxt): Add 'h' case 1998-02-01 John Fitch * VERSION.H: 3.473 * shaker.c (shaker): Change type of shake to float * shaker.h: Removed shake_times as not used. Also change some longs to int. 1998-01-19 John Fitch * VERSION.H: 3.47 * hetro.c: Make hmax a short so gets written correctly. 1998-01-07 John Fitch * fm4op.c (hammondB3): Only reset frequencies if there is a modulation, and do it inside main loop 1998-01-06 John Fitch * aops.c: Added tan, asin, acos, sinh, cosh, tanh, log10 support * entry.c: Added functions tan, asin, acos, sinh, cosh, tanh, log10 1998-01-02 John Fitch * entry.c: Added entries for tablekt and tableikt having found them in ugens2.c 1997-12-31 John Fitch * mandolin.c (mandolin): Arrange frequency is at k rate (mandolinset): If no lowest frequency need to multiply by 0.9 -- minimum suggested detune. * mandolin.c: NEW FILE * physutil.c (ADSR_setReleaseRate): (ADSR_setDecayRate): (ADSR_setAttackRate): Correction by NORM_RATE was missing. * fm4op.c (FM4Alg4_tick): Corrected mistaken use of wave[0] 4 times. * shaker.h: * singwave.h: * moog1.h: * fm4op.h: * shaker.c: * singwave.c: * moog1.c: * fm40op.c: NEW FILE 1997-12-28 John Fitch * fgens.c (fgens): Apparent 'hole' at 300 tables. Fix this? * filter.c (FPMAX): Change name from FMAX as that is used elsewhere 1997-12-26 John Fitch * ugensa.h: Make riphs field unsigned as Watcom gave false negative anser! * ugens2.c (kosc1): Will not compile with Symantec PowerC so remove optimisations (koscil): Ditto 1997-12-24 John Fitch * sread.c (getpfld): Allow E and e in numbers 1997-12-23 J P Fitch * entry.c: Added atan in three forms * aops.c: Added atan function. 1997-12-20 John Fitch * wincwin.c (MakeGraph): Remove caption and call to cwin_show (DrawGraph): Added call to cwin_show * cwin.cpp (class CGrapicsWindow): Add methods for Next and Prev Added vectors to remember old graphs (Clear): Copy old picture to the vectors if not already saved. (Next): Next function to cycle through graphs (Prev): And previous graph Altered menus etc to fit, and calls from main window 1997-12-19 John Fitch * rtaudio.c (playopen): Select win_dev in WIN32 if in range, else zero. Declare win_dev. * soundio.c (sfopenin): Accept devaudio# and adc# as valid RT audio in WIN32 situation. 1997-12-17 John Fitch * vibraphn.h: * marimba.h: * modal4.h: * modal4.c: New File, for marimba, vibraphone and agogobel 1997-12-15 John Fitch * fgens.c (gen01raw): Added check that length actually exceeded 1997-12-10 John Fitch * util2/exports/het_import.c (main): And again * util2/exports/het_export.c (main): Deal with header Sat Dec 06 16:44:29 1997 John Fitch * ugens3.c (adsyn): Get pointer to partials (adset): Read header and allocate space via aux * ugens3.h (ADSYN): Make ptlptrs into an aux structure * hetro.c (filedump): Write a header of number of partials 1997-11-24 John Fitch * sread.c (sget1): Deal with \ escapes 1997-11-23 John Fitch * soundin.c (sndgetset): Prepare for AIFC (newsndinset): Ditto (sndo1set): Ditto * soundio.c (sfcloseout): Add TYP_AIFC in preparation (sfopenin): Ditto (sfopenout): Ditto (sfopenout): Ditto * aiff.h: Added CommChunk3 definition * soundio.h (TYP_AIFC): Define new constant * cs.h: Added maxamps field to AIFFDAT structure 1997-11-20 J P Fitch * wave.c (wavReadHeader): Allow floats in input of WAV (wavWriteHdr): Allow floats in writing headers. * main.c (main): Allow WAV format floats 1997-11-18 John Fitch * fgens.c: Increased number of gens to 27; added gen25 and gen27. 1997-11-15 John Fitch * entry.c: Added opcode wgclar, wgflute, wgbow, wgbrass, marimba, vibes, agogobel, shaker, fmbell, fmrhode, fmwurlie, fmmetal, fmb3, fmvoice, fmpercfl * clarinet.h: * flute.h: * bowed.h: * brass.h: * physmod.c: * physutil.h: * physutil.c: New File * rdorch.c: Make lblreq into a dynamic object (rdorchfile): Alloc space to lblreq and initialise lblmax (lblrequest): Rewrite to use arrary access (lblfound): Rewrite to allow gro (lblchk): And again 1997-11-09 John Fitch * sread.c (ifa): Allow ^n in second field of score (getpfld): Admit ^ in scores 1997-11-01 John Fitch * makefile: * Makefile: * cross2.c: * all_files: Rename cross.c as cross2.c for consistency 1997-10-30 John Fitch * midisend.c: Further revision on LINUX version In SGI case ensure only one call to write (for 2 or 3 bytes) for each MIDI output call. * main.c: Added LINUX-specific forward declarations (main): -Q option in LINUX 1997-10-28 John Fitch * midisend.c: Various LINUX changes * ugens1.c (xsgrset): Setting of relestim was missing 1997-10-27 John Fitch * midiops2.c (TRUE): Protect definition in case already exists 1997-10-26 John Fitch * midisend.c: Added LINUX code * ugens1.c (lsgset): Allocation of segment space only checked for NULL and not being long enough (the common bug!) -- by inspection (lsgset): Wrote off end of SEG list. * SGIplay.c (play_on): Argument format to ANSI (play_set): Ditto ... and other functions * midiops2.c (initc7): Added void type (initc14): Ditto (initc21): Ditto * vpvoc.c (vpvset): Declaration of ldmemfil corrected * pvread.c (pvreadset): Declaration of ldmemfil corrected * pvinterp.c (pvbufreadset): Many %d -> %ld * scxtract.c (scxtract): Make functiomn type explicit * pvanal.c (takeFFTs): Correct format %d -> %ld * ugens7.c: Forward declaration of newpulse made ANSI * ugens4.c: Forward declarations of rand15 and rand16 made ANSI * ugens2.c (ptblchk): Added void type * ugens1.c (lsgset): Remopve variable d as not used * midirecv.c (m_chanmsg): Unwrapped ambiguous code * insert.c (MIDIinsert): Removed m_chnbp as not used * express.c (express): Added cast to char* * otran.c (constndx): Added cast to float* in case of C++ compiler * ugrw1.c (itablew): Declaration on ktablew (tableng): %f in format should be %p, or argument dereferenced (itableng): Ditto (tablegpw): Ditto (printksset): Remove false \c and \p cases (zawm): Unwrapped undefined code * fgens.c: Argument type in declaration of gen01raw * entry.c: Use sndwarpgetset * sndwarp.c (sndwarpset): Remove sndwarpset as not used * repluck.c (wgpsetin): Correct no-pluck case, and some code reorganisation to save space flapping 1997-10-15 John Fitch * aops.c (cps2pch): Corrected a rounding error in table case. (cpsxpch): Ditto 1997-10-12 John Fitch * ugens4.h: * ugens4.c: * ugens3.h: * ugens3.c: * entry.c: Remove doscil and poscil 1997-10-10 J P Fitch * aops.h (struct XENH): Correct argument order to fit documentation * cross.c (Xsynthset): Need to check that previous buffer is big enough (same bug as was in grain) (Xsynth): Re-construct due to JPff errors (Xsynth): Wrapping of n was at odd place?? 1997-09-30 John Fitch * ugens2.c (itblchk): Replace NULL by 0 for types Wed Sep 24 15:10:38 1997 J P ffitch * midirecv.c: Prototype for midNotesOff * musmon.c: Need a prototype for xturnon * zroots.c, laguer.c, nrutil.c: Removed, Code moved into filter.c Tue Sep 16 07:54:37 1997 John ffitch * wavegde.c pluck.c filter.c zroots.c complex.c laguer.c nrutil.c: New files for plucked string and filter opcodes * cmath.c (seedrand): If seed of the random number is given as zero, seed from clock. * entry.c: Added new opcodes wgpluck, filter2, kfilter2, and zfilter2 * repluck.c: * repluck.h (struct): Rename WGPLUCK to WGPLUCK2 * entry.c: Renamed wgpluk to wgpluck2, and renamed structure * midirecv.c (m_chinsno): Remove test for maxinsno as there is no such thing really! * ugens2.c (ftkrchk): Moved return to end so all routes return a value. * rdorch.c (rdorchfile): Revise as MACRO now claimed by ADI Thu Sep 11 16:31:41 1997 John ffitch * cwin.cpp (OnGShow): Remove code related to backtrace as irrelevent (OnStop): Added stop and continue menu items as also as ^S-^Q These changes allow scrolling etc Wed Sep 10 11:49:53 1997 John ffitch * ugrw1.c (ftkrchkw): This function did not return any value in one case. Make it return 1 * otran.c (otran): Make sure ksmps is integer * ugrw1.c (timesr): (timesr): (instimes): (printkset): (printk): (printk): (printksset): (printks): Changed 1/ekr to onedkr to save division (zkset): Change value 0 for a float* to NULL as that is what is meant (zakinit): Do this twice more, (and for declarations) (zaset): Also for zastart Mon Sep 08 20:12:58 1997 John ffitch * ugens3.c: Prototype for turnoff * hrtferX.c: Removed function round as not used Fri Sep 05 11:44:30 1997 John ffitch * ugrw1.c (peakk): Changed abs to fabs which is clearly what is needed. Use of abs changes to int and then back. (Whittle code) (peaka): Ditto Thu Sep 04 11:54:26 1997 John ffitch * ugrw1.c (printksset): Tidyup string decode to make it compatable with C wrt \ character. Still needs work. * otran.c (otran): Allocate instrtxtp dynamically and allow to grow with mrealloc. Removes restricton on largest instrument number. * musmon.c (playevents): * midirecv.c (m_chinsno): (m_chn_init): * oload.c (oload): New variable maxinsno replaces constant Wed Sep 03 10:55:46 1997 John ffitch * fgens.c (hfgens): If automatic numbering, it did not always allocate space in table * rdorch.c (getoptxt): Count 'm' in defaults section to remove error in ftgen * insert.c (MIDIinsert): Remove aging and overlap stuff * cs.h: Removed olap and age fields in INSDS * midiops.c: Removed midiolap and midiage * entry,c: Removed octdown and noctdft opcodes, also midiolap and midiage * spectra.c: Removed code for octdown as it is ADI proprietry Fri Aug 29 15:25:59 1997 John ffitch * util2/mixer/mixer.c (main): * cwin.cpp (class CArg): * wave.c (wavReadHeader): * soundio.c (iotranset): * soundin.c (sndo1set etc): * main.c (main): * LINUXaudio.c (setsndparms): * soundio.h (AE_UNCH): Renamed from AE_BYTE to AE_UNCH Thu Aug 28 12:27:48 1997 John ffitch * rtaudio.c (playopen): New variable ntmp as multiple use of ndev was causing problems. * dpwelib.h: * dsputil.c: Removed nested comments * repluck.c: New file * entry.c: Added wgpluck and repluck opcodes Wed Aug 27 14:35:52 1997 John ffitch * ugens5.c: Reorder code so RESET might work Declare DumpPoles instead of DumpPolesF, and comment out call! Tue Aug 26 11:35:48 1997 John ffitch * cross.c: Incorporated fhtfun.c into cross.c * fhtfun.c: REMOVE file * UTIL2/scale.dir/scale.c: Declarations of functions * midiops2.c: New file * entry.c: Added midicontroller message stuff * midiops2.h: New file * grain4.c (graingenv4): Code tidy on *xx++ type code (envv4): Change way of commenting out to #ifdef never 1997-08-20 John Fitch * midisend.c (send_midi_message): (note_on): (note_off): (control_change): (after_touch): (program_change): (pitch_bend): (poly_after_touch): Wrote WIN32 code for these as calls to midiOutShortMsg (openMIDIout): Open device 0 only for now * midioops.h (MD_CHANPRESS, etc): MIDI opcodes * midiout.c: Added calls to openMIDIout in each initialisation function. May seem expensive but is minimal disturbance. 1997-08-18 John Fitch * SENT TO DAVE * midisend.c: Totally new file 1997-08-17 John Fitch * pvanal.c (pvanal): * lpanal.c (lpanal): * cvanal.c (cvanal): * hetro.c (filedump): Ensure analysis file is read-write. Some systems seem to get this wrong * rtaudio.c (playopen): If more than 1 possible output in WIN32 then allow user to choise which. Also added some more checking (rtplay): Remove called to waveOutUnprepareHeader and waveOutPrepareHeader as they seem unnecessary (according to GAB) (rtclose): Change strategy for wrap-up * midiout.h: New file (Gabriel M) * midiout.c: New file (Gabriel M) * entry.c: Added MIDI output opcodes 1997-08-11 John Fitch * rdorch.c: Added type 'h' to argument type -- needed in MIDI 1997-08-06 John Fitch * ugens1.h: Define struct EXXPSEG * ugens1.c (xsgrset): Rewrite function 1997-08-05 John Fitch * otran.c: Remove txtcpy in favour of memcpy, and define macro 1997-08-01 John Fitch * dam.h: New file * dam.c: New file * makefile (dam.u): Added dam target * entry.c: Added dam opcode 1997-07-13 John Fitch * cross.c: New File * fhtfun.c: New File (support for cross) * ugens2.c (oscnset): New function (osciln): New function (for osciln opcode) * ugens2.h: New structure OSCILN * entry.c: Declarations for cross2 opcode Also osciln opcode * soundio.h (IOBUFSAMPS): Larger default buffers for Windows95 1997-07-07 John Fitch * ugens1.h: New fields in EXPSEG * entry.c: Added expsegr * ugens1.c (xsgrset): (kxpsegr): (expsegr): New functions * ugens3.h: New structure DOSC * oload.c (instance): Set chanel if MIDI * insert.c (insert): Add check for MIDI instruments from score 1997-07-05 John Fitch * ugens3.c (dosset, doscil): New functions * entry.c: Added doscil opcode * soundin.c (sndwrt1): (sndwrtu): (sndwrt2rev): (sndwrt2): (sndwrt4rev): (sndwrt4): (sndwrtf): New functions * soundio.h: New structs SNDCOM, SNDOUT and SNDOUTS * soundin.c (sndo1set): New function (soundout): New function (sndo2set): (soundouts): New but null functions * soundio.h (SNDOUTSMPS): New constant * midiops.c (ipchbend): New function (kbndset): New function (kpchbend): New function * entry.c: Added ipchbend and kpchbend, modify pchbend Added soundout. Also soundouts but I think it is a failure Sun Jun 22 11:54:43 1997 John Fitch * midirecv.c: Many changes and new functions for revised MIDI code * cs.h: New struct DPARM, DKLST and DPEXCL * ugens1.c (klnseg): Rewrite (lsgset): Rewrite (linseg): Rewrite * ugens1.h: Defien SEG type/struct * oload.c (oload): Define dvensmps * ugens1.h: Add new fields to LINSEG for releases * rdorch.c (rdorchfile): Added MACRo support Tue Jun 17 15:48:29 1997 John Fitch * entry.c: Added linsegr opcode Mon Jun 16 21:50:39 1997 John Fitch * rdorch.c (rdorchfile): Treat \ ... \n as ignorable Fri Jun 13 21:34:01 1997 John Fitch * entry.c: Added turnon opcode Tue Jun 10 09:02:58 1997 John Fitch * midiops.c (ichanctl): (chctlset): (chanctl): New functions * midiops.h: Added CHANCTL structure * entry.c: Added chanctrl opcodes Mon Jun 9 21:43:27 1997 John Fitch * entry.c: Added extra optional argument to [ik]midictrl * midiops.c (mctlset): Added scaling * midiops.h: Changed MIDICTL to lo and hi from sc and base * midiops.c (imidictl): (midictl): Added scaling * midiops.h: Added MIDIMAP structure * entry.c: Added optonal arguments to veloc * midiops.c (veloc): Added scaling to veloc Removed f128 in favour of a constant Sat Jun 7 20:06:53 1997 John Fitch * entry.c: Added ftlptim opcode * ugens4.c (posset): New function (poscil): New function * ugens4.h: POSC structure * entry.c: Added rnd and birnd in i and k formats Added poscil * aops.c (rnd1): (birnd1): New functions for direct use in orchestras Fri Jun 6 09:20:31 1997 John Fitch * cs.h: Added posbend field to MCHNBLK Thu Jun 5 21:48:00 1997 John Fitch * cs.h: Added mdepends field to INSTRTXT Wed Jun 4 11:46:03 1997 John Fitch * aiff.c (aiffReadHeader): initialised markersp to NULL Tue May 27 08:17:57 1997 John Fitch * cs.h: Added #defines for VSET etc * oload.h (struct): Lots of new structures for Vprogs and the like * midiops.h: Added MASSIGN and CTLINIT structures Sun May 25 17:22:09 1997 John Fitch * ftgen.h: New file * entry.c: Entry for ftgen opcode * fgens.c (hfgens): New code (ftgen): New code; together for ftgen opcode Sat May 24 18:36:41 1997 John Fitch * cs.h: Added fno to FUNC Tue May 20 10:29:02 1997 John Fitch * ugens7.c (harmset): New function (BV) (harmon): Ditto * entry.c: Entry for harmon * ugens7.h (struct): Added HARMON struct Mon May 19 21:51:31 1997 John Fitch * ugensa.c (newpulse): Changes abs to fabs as that is clearly what is needed. Mon May 19 12:20:51 1997 John Fitch * winX11.c: Added include of Mon May 19 08:50:44 1997 John Fitch * rdscor.c (scanflt): treat comments when reading a number Sat May 17 17:31:47 1997 John Fitch * cscormai.c (scfopen): Move this function from rdscor.c as only used in stand-alone cscore * rdscor.c: Delete scfopen function Fri May 16 10:01:41 1997 John Fitch * memalloc.c (memdie): Made function void type * ugens5.c: Added int type to currentLPCSlot, and moved to top of file * midirecv.c: Added int type to sexcnt * winX11.c: Added int type for winstance Sat May 10 23:44:12 1997 John Fitch * ugrw1.c: Change name of times function to timesr to avoid problems with Mac * entry.c: Change name of times function to timesr to avoid problems with Mac Wed May 7 21:04:55 1997 John Fitch * butter.c (butter_filter): Changed declaration on n to long for consistency. Sun May 4 08:58:44 1997 John Fitch * version.h: NEW VERSION 3.46 * fgens.c (fgens): Expand the number of tables available dynamically. Declare fmax etc (gen04): (ftfind): (ftfindp): (ftnp2find): FMAX->fmax * rtaudio.c (RTwavclose): New function to close on early exit (playopen): Minor revisions to Win95, including CWIN->_WIN32 (rtplay): Change _WIN32 way of playing buffers (rtclose): Change _WIN32 close down * prototyp.h: Add argument to getoptxt if RESET * soundin.c (soundinreset): New function protected by RESET (sndinset): Reset file position if already open (soundin): Check initialisation (soundinew): Check initialisation * sndwarp.c (sndwarp): (sndwarpst): Check initialisation * rdorch.c (orchreset): New function protected by RESET (getoptxt): Added argument if RESET and use it for reseting * memalloc.c (memreset): New function protected by RESET * fgens.c (ftreset): New function protected by RESET; code tidying * cscorfns.c (cscorereset): New function protected by RESET Also some code shuffling Sat May 3 19:38:45 1997 John Fitch * spectra.c (koctdown): (octdown): (noctdft): (spdspset): (specdisp): (specptrk): (specsum): (specaddm): (spdifset): (specdiff): (spsclset): (specscal): (sphstset): (spechist): (spfilset): (specfilt): Check initialisations * musmon.c (musreset): New function protected by RESET * disprep.c (kdsplay): (kdspfft): (dspfft): (tempest): Check initialisation * otran.c (tranreset): New function protected by RESET * oload.c (oloadreset): New function protected by RESET * ugens3.c (foscil): (foscili): (adsyn): Check initialisations * ugens4.c (buzz): (gbuzz): (pluck): Check initialisation * ugens5.c (lpcreset): New function protected by RESET (lpinterpol): (lpread): Check initialisation * wave.c (wavReadHeader): Set hdrsize to include non-data chunks * grain4.c (graingenv4): Check initialisation * ugens9.c (convolve): Check initialisation * insert.c (insertreset): New function, protected by RESET (insert): Only print new alloc message if messages 2 set (initerror): Check there is an ids (perferror): and a pds * grain.c (ags): Check initialisation (ags): Check for zero density * express.c (expreset): New function, protected by RESET macro * hrtferX.c (hrtferxk): Check initialisation * ugens2.c (ktable): (table): (ktabli): (tabli): (kosc1): (kosc1i): (koscil): (osckk): (oscka): (oscak): (oscaa): (koscli): (osckki): (osckai): (oscaki): (oscaai): Check initialisation * ugens7.c (fof): Check initialisation * ugens6.c (delay): (delayr): (delayw): (deltap): (deltapi): (comb): (alpass): (reverb): (pan): Check initialisation * ugens8.c (pvoc): Check initialisation * sread.c (pcopy): Another place where fabs is needs in case of negative p3 in score. * nlfilt.c (nlfilt): Check initialisation * ugens1.c: Remove register declarations (klnseg): (linseg): (kxpseg): (expseg): (knvlpx): (envlpx): Check for initialisations * vdelay.c (vdelay): (multitap_play): (reverb2_play): Check for initialisation * pvinterp.c (pvbufread): (pvinterp): (pvcross): Check they are initialised * vpvoc.c (ktableseg):(ktablexseg): (voscili): (vpvoc): Check they are initialised * winX11.c (myXprintLines): ANSIfied function * pvoc.c: * dsputil.c: Removed FLOATARG as it is a mistaken idea * pvoc.h: * dsputil.h: Removed non ANSI stuff, and the horrid FLOATARG * aoscilx.c (aoscilxplay): Check opcode is initialised * follow.c (flwset): Check that length given is not zero (RWD suggestion but moved to init function) Sun Apr 27 13:06:00 1997 John Fitch * cscormai.c (main): Added dribble initialisation (dribble_printf): New function (err_printf): New function * Makefile, makefile: Added new files * all_files: Added new files * ugensa.h: New file * ugensa.c: New file for FOG * entry.c: Add opcode fog Sun Mar 23 18:08:01 1997 John Fitch * otran.c (otran): Revise check for consistent sr/kr=ksmps (otran): Check for finishing inside an instrument Fri Mar 21 21:21:22 1997 John Fitch * entry.c: Added diskin opcode * soundin.c: New code for diskin opcode (Matt Ingalls) * diskin.h: New file * cs.h (DFLT_SR): Change to 44100 (DFLT_KR): Change to 4410 (DFLT_KSMPS): Remains 10 (!) * ugens2.c: Changes to table stuff (Whittle) Thu Mar 20 22:17:00 1997 John Fitch * entry.c: Put Whittle opcodes back * fgens.c (ftfindp): New function (Whittle) Wed Mar 19 13:25:43 1997 John Fitch * otran.c (otran): Set initial tran_{sr,kr,ksmps} to -1 and correct in otran. Sun Mar 16 12:26:50 1997 John Fitch * ugens8.c (pvoc): Simplify initialisation when specwp greater than zero. (Richard Karpen) Sat Mar 8 15:30:34 1997 John Fitch * hrtferX.c: Declaration of bytrevhost * main.c: Added #include for isdigit Fri Mar 7 13:16:37 1997 John Fitch * main.c (err_printf): Same error as before -- code in wrong order. No idea how it got undone. * rtaudio.c (playopen): Comment out line about BitsPerSample on advice Fri Mar 7 09:54:31 1997 John Fitch * opcode.c (list_opcodes): Use mmalloc/mfree rather than malloc/free (list_opcodes): Reorganize argument to mmalloc as well Thu Mar 6 21:43:31 1997 John Fitch * entry.c: Added entry for soundin2 * soundin.c (soundin2): New function, implements soundin2 (sndinset): Initialisation for soundin2 added * soundio.h: Added new fields to SOUNDIN structure for soundin2 Wed Mar 5 10:59:32 1997 John Fitch * hrtferX.c (hrtferxkSet): Reverse bytes after reading HRTFcompact if necessary (as shown by byrevhost) * Makefile (CSRCS): CSRC7 was missing from CSRCS! * makefile (CSRCS): CSRC7 was missing from CSRCS! Tue Mar 4 14:24:47 1997 John Fitch * opcode.c (list_opcodes): The malloc did not get enough memory -- needed multiplication by the sizeof thingy Tue Feb 25 10:33:22 1997 John Fitch * aops.c: Removed register declarations * wave.c: Removed various register declarations * swrite.c (fltout): Reinstated multiplication by precmult for LINUX only. This is still wrong way to do it! Tue Feb 18 08:57:08 1997 John Fitch * sread.c: Remove register declarations throughout (stof): Replace body by call to strtod for simplicity and shorter code. (Experimental I guess) Sun Feb 16 15:49:57 1997 John Fitch * sread.c (ifa): Take absoulte value of previous p3 when reading a score, in order to deal with portamento etc Fri Feb 14 21:49:51 1997 John Fitch * midirecv.c (m_chanmsg): Further midi chages to controllers from Mike Berry Thu Feb 13 21:01:42 1997 John Fitch * midiops.h: sc and base fields in MIDICTRL and irange field in MIDIVAL * midiops.c (midibset): New function from Mike Berry (cpsmidib): Allow scaled pitchbend (octmidib): Ditto (pchmidib): Ditto (mctlset): Deal with controller 0 * rdorch.c (getoptxt): Add code from Mile Berry to fix bug that prevented an opcode with only optional arguments from properly loading defaults * entry.c: Declared midisetb Added optional argument to ipchmidib, ioctmidib, icpsmidib, kpchmidib, koctmidib, kcpsmidib, imidictrl, kmidictrl. Needed initialisation for some Fri Feb 7 08:15:28 1997 John Fitch * ugens7.c (fof): In penultimate line removed * in *ar++ as it does not do anything, and I think it is spurious. Also remove register declarayions all over Wed Feb 5 17:53:54 1997 John Fitch * ugens7.c (newpulse): Corrected code (JPff mistake) Mon Feb 3 09:48:32 1997 John Fitch * version.h (SUBVER): CHANGE VERSION NUMBER TO 3.45 * swrite.c (fltout): Remove precmult as it does nothing and increase precision by one digit * sndwarp.c (sndwarpstgetset): New code from Richard Karpen (sndwarpstset): Ditto (sndwarpst): Ditto * fgens.c (ftfindp): Remove Whittle code Sun Feb 2 12:22:01 1997 John Fitch * util2/mixer/mixer.c (main): Moved line assigning to O.filetyp to before AIFF/WAV sanity checks (MixSound): Second argument to audtran was size when shoudl have been length Sat Feb 1 16:43:33 1997 John Fitch * swrite.c (fltout): Work in doubles internally (RK), but then replaced by fprintf anyway?? * ugens2.c: Remove Whittle code * ugens2.h: Remove Whittle code * main.c (main): Add -z0 and -z1 * Remove ugrw* from makefiles * entry.c: Remove Whittle opcodes Tue Jan 28 07:54:58 1997 John Fitch * entry.c: Add fof2 opcode * ugens7.c (fofset0): Rename fofset and add argument to distinguish fof and fof2 initialisation ; also set fmtmod field in fof call only (fofset): Call fofset0 with true (fofset2): Call fofset0 with false (fof): fof and fof2 cases differ at start of loop (newpulse): Deal with fof2 case at end * ugens7.h: Add glissbas and sampct fields to OVRLAP and foftype field to FOFS * opcode.c: New file * prototyp.h: Added declaration of list_opcodes * main.c (main): Add -z option to list opcodes Sun Jan 26 14:02:06 1997 John Fitch * cmath.c (auniform): Add new function for completeness (ikuniform): Ditto * ugens2.c: Changes to table stuff (Whittle) * ugens2.h: Added pfn field to TABLE for Whittle * ugrw1.c: New file (Whittle) * ugrw2.c: New file (Whittle) * prototyp.h: Added declaration of ftfindp * fgens.c (ftfindp): New function (Whittle) * ugens2.c: Remove register declarations Fri Jan 24 18:52:01 1997 John Fitch * cmath.c: Removed register declarations throughout; also some improved layout of comments Mon Jan 20 08:48:56 1997 John Fitch * lpanal.c (lpanal): Return after exit for compiler (lpanal): Only declare polyReal and polyImag if used * linevent.c (sensLine): Comment out unused variables * ieee80.c: Remove nested comment * hetro.c (hetro): Add a return after exit to keep compilers quiet * fft.c: Remove nested comments in 3 places, and a print statement * aiff.c (aiffReadHeader): Comment out unused vaiables * main.c (main): By use of %n arrange that a numeric argument can be follwed directly by another argument. Wed Jan 15 20:39:12 1997 John Fitch * window.c (DummyRFn): Made it return zero rather than 1 as there does not seem to be an error here. Thanks Marc! Sat Jan 11 16:53:59 1997 John Fitch * vdelay.h: Added istod field to VDEL struct * entry.c: Add optional istod argument to vdelay * vdelay.c (vdelset): Skip initialisation if istod set * ugens6.c: Removed register declarations * vdelay.h (struct): Added istor field to STVB * vdelay.c (reverb2_set): Skip initialisation if istor set and have buffers. * entry.c: Added optional istor argument to reverb2 * butter.c (bbutset): (butset): Skip initialisation if istor non-zero * butter.h (struct): Added istor filed to BFIL and BBFIL * entry.c: Added optional extra argument to all butterworth filters Tue Jan 7 10:32:09 1997 John Fitch * version.h (SUBVER): CHANGE VERSION NUMBER TO 3.44 in Windows * winsound.rc: Added postscript and Oldformat fields to DIALOG_1 and DIALOG_LPC respectively. Some reshuffling to make it fit * cwin.cpp (class CArg): Added m_postscript member (class CArg): and afx command (CArg): Set m_postscript from profile (OnInitDialog): Set initial value of Postscript (cwin_args): Set O.postscript after dialog * lpcdlg.cpp (class Clpcdlg): Added oldf to constructor, and m_oldf to the members. (class Clpcdlg): New afx OnOldFormat (Clpcdlg): Use oldf in constructor (lpanal_dialog): Oldf stuff Mon Jan 6 10:25:31 1997 John Fitch * version.h (SUBVER): CHANGE VERSION NUMBER TO 3.44 * aops.c (cpsxpch): Added table form of cpsxpch and cps2pch * lpanal.c (lpanal): Various fixes after new code. Sun Jan 5 23:17:19 1997 John Fitch * ugens5.c (lpslotset): New function (lpitpset): New function (lpinterpol): New function : other changes throughout * ugens5.h: New field in LPREAD * (struct): New structures * lpc.h (LP_MAGIC2): New definition * lpanal.c: Incorporated Marc Reseibois' alternative format. Many changes all over Sat Jan 4 19:25:23 1997 John Fitch * oload.c: Added postscript filed to initialisation of O structure * main.c (main): Remove O initialisation as in wrong place Fri Jan 3 14:39:30 1997 John Fitch * Files sent to Mills College Thu Jan 2 17:29:17 1997 John Fitch * main.c: Make scorename a global for winEPS Add initialisation of O fields * winEPS.c: New file for Encapsulated PostScript output * cs.h: Added postscript field * window.c (display): (dispexit): (dispset): Call Postscript stuff * main.c (main): Added -G option fopr Postscript printing * hrtferX.c: New code for 3D sound * entry.c: Added hrtfer opcode Mon Dec 30 16:13:40 1996 John Fitch * entry.c: Added opcodes "sndwarp", "ktableseg", "ktablexseg", "voscili", "vpvoc", "pvread", "pvcross", "pvbufread", "pvinterp" * pvinterp.c: * pvread.c: * vpvoc.c: * sndwarp.c: New files added, from Richard Karpen, with some optimisations. Sun Dec 29 13:15:57 1996 John Fitch * aops.c (cps2pch): New function for ET tuning (cpsxpch): Remove attempt at optional arguments * entry.c: Added cps2pch for ET tunings * linevent.c: (sensLine): Use strtod to read floating argument rather than use longs. Untested! Fri Dec 27 14:42:53 1996 John Fitch * util2/exports/het_export.c (err_printf): Define it (dribble_printf): Define it * util2/exports/pv_export.c (err_printf): Define it (mfree): Define it Fri Dec 20 17:45:34 1996 John Fitch * rtaudio.c (rtclose): Modify close down for arbitrary buffers * ugens3.c (adset): Change length of filnam to MAXNAME * ugens5.c: Change length of lpfilnam to MAXNAME * ugens9.c (cvset): Change length of cvfilnam to MAXNAME * ugens8.c: Change length of pvfilnam to MAXNAME * cs.h (MAXNAME): Defined here * filopen.c (isfullpath): In PC case (and Atari) check for a: type names as well as / (MAXNAME): removed from this file Mon Dec 02 15:23:53 1996 * AOPS.c (cpsxpch): New function of equal temprament not 12/octave * AOPS.h (XENH): Structure for tuning Fri Nov 27 14:49:00 1996 John Fitch * rdscor.c (rdscor): Added comments after 'e' Tue Nov 26 16:40:26 1996 * cwin.cpp: Added NONSTOP feature and a button to control it Mon Nov 04 15:38:40 1996 John Fitch * FILOPEN.C (openin): If the file does not exist but SFDIR does it fails to notice a non-existent file. Remove an else! Mon Oct 28 10:13:55 1996 John Fitch * RDORCH.C (synterr): Remove register declarations; so new layout Thu Oct 24 15:36:34 1996 * VDELAY.c (vdelset): Only zero buffer if not new (multitap_set): Ditto (multitap_play): Remove division for assignment Mon Oct 21 21:08:52 1996 * version.h: (SUBVER): CHANGE VERSION NUMBER TO 3.43 * rtaudio.c (playopen): Fixed allocation of buffer in CWIN case (rtplay): Use quadruple bufering correctly Thu Oct 17 18:44:10 1996 John Fitch * VDELAY.c (multitap_set): Fixed the regular bug in allocation of buffer. Thu Oct 17 17:34:15 1996 * butter.c: New variable pidsr, set in both setters and used for pi/esr Thu Oct 17 16:26:20 1996 John Fitch * CMATH.c: Many code tidying operation -- all minor Wed Oct 09 16:27:49 1996 John Fitch * rtaudio.c (playopen): Allocate each buffer with its own GlobalAlloc/GlobalLock Tue Oct 08 16:10:24 1996 John Fitch * LPCDLG.CPP (class Clpcdlg): Added graphics selection -- most of code was there but not visible! Tue Oct 08 15:29:09 1996 John Fitch * CWIN.CPP (OnOrchestra): Change title of dialog window and hide read-only button (OnScore): Change title of dialog window and hide read-only button (OnSoundfile): Change title of dialog window Mon Sep 30 14:06:52 1996 * grain4.c (graingenv4): Took array access out of loop with direct increments and similar use of local names Fri Sep 13 10:45:09 1996 John Fitch * vdelay.c (vdelset): Bracket expression to get binding right (vdelset): Check size of buffer as well as existence (cf grain) (vdelay): Ensure max delay is at least 1 (vdelset): Clear at least one slot Thu Aug 15 05:36:11 1996 John Fitch * version.h (SUBVER): CHANGE VERSION NUMBER TO 3.42 * memalloc.c (mcalloc): If calls for 0 bytes do not give an error * memalloc.c (memdie): Add argument to print size of failure (mfree): Use 0 argument for free (mrealloc): In CWIN set negative (mrealloc): Add argument in general case (mmalloc): Add argument in general case (mcalloc): Add argument in general case Mon Jul 22 08:49:44 1996 John Fitch * fgens.c (gen21): Argument for Weibull ignore p6 so shuffle them down. (gen21): Check for at least 1 argument first, and treat the other two specials in the switch; saves code and very little cost. * cmath.c (exprand): I think algorithm was wrong in assuming lambda always 1. Allowed range and lambda (biexprand): Code had lambda as always 1; make parameter 1/lambda (pcauchrand): Code was plain wrong * fgens.c (gen21): Add range to exponential distribution as well as spread. * cmath.h: Change prototype * cmath.c (unifrand): Add argument so as to give a range. Sat Jul 20 18:55:39 1996 John Fitch * cmath.c (cauchrand): Limit answers to [-1,1]. Despite theory of 99.9% I get some outside. (pcauchrand): The same range limiting. * fgens.c (gen21): For type 7 and 8 (Cauchy) it asked for an additional argument, and ignored the usual one. As it was undocumented fixed to one argument Tue Jul 16 09:29:48 1996 John Fitch * cwin.cpp (OnInitDialog): Format buttons started at _8 rather than _U8. * version.h (SUBVER): CHANGE VERSION NUMBER TO 3.41 * rtaudio.c (rtplay): Triple buffering system (playopen): Create 3 buffers from one GlobalAlloc call (rtclose): Flush buffers before Reset. [All CWIN case] Mon Jul 15 11:31:02 1996 John Fitch * rtaudio.c (rtplay): Remove the memcpy and cycle buffers. Get WHDR_DONE correct and other simplifications. Sun Jul 14 12:35:14 1996 John Fitch * rtaudio.c: Added draft Windows Multimedia support (playopen): Ditto (rtplay): Ditto (rtclose): Ditto Tue Jul 9 21:25:27 1996 John Fitch * util2/mixer/xtrct.c: Change name of variable time to stime cos the Irix6.2 system complains. Fri Jul 5 20:51:58 1996 John Fitch * all_files: SGIplay.c was missing Sun Jun 16 20:58:01 1996 John Fitch * soundio.c (sfcloseout): Make datasize into unsigned long (especially for 68K) Wed Jun 12 08:09:35 1996 John Fitch * wave.c (wavReadHeader): Add cast to (void*) 'cos Mac compiler complained * Transferred files to MAC Mon Jun 10 08:59:57 1996 John Fitch * version.h (SUBVER): CHANGE VERSION NUMBER TO 3.40 * wincwin.c: Include and add variaous ignoring of arguments. (DrawGraph): Add cwin_paint() call * util2/exports/lpc_export.c: * util2/exports/het_import.c: Include which had been missed * ugens9.c: * ugens8.c: Move inclusion of earlier to avoid an arcane VC problem * filopen.c: Add _WIN32 to definitions of RD_OPTS and WR_OPTS (openin): After open the test should be >=0 * fgens.c (gen20): Remove register storage class from array as upsets VC and does no good anyway * pvanal.c (pvanal): * lpanal.c (lpanal): * hetro.c (hetro): * cvanal.c (cvanal): * fgens.c (gen01raw): Check on negative return from sndgetset as consequence of previous change * soundin.c (sndgetset): Change function to return -1 on failure instead of 0 as that does not rely on zero being in use for stdin (SAsndgetset): Also return -1 on failure Sun Jun 9 16:31:48 1996 John Fitch * sysdep.h: Add _WIN32 support * pvoc.c: Add _WIN32 support * main.c (main): Add _WIN32 (main): and again for SYS5 * scot.c (efindword): Change type to void * scot.h: Change type of efindword to void * dsputil.c (hypot): Define hypot as _hypot for Visual C++ * vdelay.c (reverb2_play): Change return type to void * midirecv.c (MidiOpen): Add _WIN32 to SYMANTEC Add _WIN32 to list of o/s which to not load ioctl.h (MidiOpen): Add _WIN32 to non SYS5 list (MidiOpen): Add _WIN32 to systems without ioctl * wave.c (wavReWriteHdr): Value check on result of lseek was wrong. (wavReadHeader): Add code to skip odd chunks in reading a header * dpwelib.h: Add _WIN32 to systems which include * linevent.c (RTclose): Add _WIN32 to list of systems which do not know about fcntl (RTLineset): Ditto * dumpf.c (kdmpset): Change test on openout to <0 (kdmp2set): Ditto (kdmp3set): Ditto (kdmp4set): Ditto Sat Jun 8 16:11:56 1996 John Fitch * cmath.c (gaussrand): Change floating value for n to an integer Mon Jun 3 08:35:11 1996 John Fitch * lpanal.c (lpanal): Allocate coef and cc dynamically * hetdlg.cpp (DoDataExchange): Remove limit of 50 in number of harmonics * hetro.c (hetro): Allocate MAGS and FREQS dynamically (hetro): Allow more than HMAX harmonics (filedump): Allocate mags and freqs dynamically Sun Jun 2 12:53:06 1996 John Fitch * cwin.cpp (cwin_almost_ensure_screen): (cwin_ensure_screen): (cwin_poll_window_manager): (CMainWindow): Change GetSystemTime -> GetLocalTime * memalloc.c (mfree): New function (all_free): Do not free NULL pointers * prototyp.h: Declare mfree * wguide.c (wgpset): * sread.c (sfree): * sndinfo.c (sndinfo): * rdorch.c (rdorchfile): (splitline): * pvoc.c (PVFree): * otran.c (otran): (insprep): * oload.c (oload): * memfiles.c (rlsmemfiles): * insert.c (orcompact): * hetro.c (hetro): (filedump): * fgens.c (fgens): (gn1314): (ftalloc): * cscorfns.c (filclose): * auxfd.c (auxalloc): (auxchfree): * aiff.c (aiffReadHeader): change free -> mfree Thu May 2 21:37:23 1996 John Fitch * version.h (SUBVER): CHANGE VERSION NUMBER TO 3.39 * butter.c (ROOT2): Define ROOTS as a macro rather than recalculate it for each k-rate * memalloc.c: CWIN only -- allow a flexible number of allocs by reallocing the array. Thu Apr 18 11:00:11 1996 John Fitch * grain.c (ags): Optimisations in many places to save recalculation and memory fetches. Moves some stuff out of inner loop. * grain.h (struct): Changed type of PGRA.pr to float Thu Mar 28 08:35:43 1996 John Fitch * version.h (SUBVER): CHANGE VERSION NUMBER TO 3.38 * main.c (main): Add date of compilation to banner * musmon.c (musmon): Add date of compilation to banner * musmon.c (musmon): Removed test for !O.RTevents as it seems to stop score tables being read in MIDI case. Thu Mar 21 09:29:42 1996 John Fitch * main.c (main): Add LATTICE to SYNANTEC to avoid a setlinebuf * midirecv.c: Add LATTICE to options with PC stuff * linevent.c (RTLineset): Add LATTICE to options when do not use fcntl etc Tue Mar 5 23:13:51 1996 John Fitch * sread.c (copylin): Change EOF to EOL in structure. Mends bug about bad characters. Sat Feb 24 14:56:31 1996 John Fitch * otran.c (putop): Correct typing error of \t instead of \n Sun Feb 18 11:37:15 1996 John Fitch * version.h (SUBVER): CHANGE VERSION NUMBER TO 3.37 * rdscor.c (scanflt): Use fscanf rather than read floats character at a time. Not sure that this is necessarily a good thing. * hetro.c (hetro): Added a check that -hn has n>=1 (David Whelan) Sat Feb 17 11:53:57 1996 John Fitch * musmon.c (musmon): Close dribble file at end * auxfd.c (fdchprint): * express.c (putoklist) (putokens): * midirecv.c (sensFMidi): * musmon.c: * otran.c: * rdorch.c: * rdscor.c (dumpline): * winascii.c (DrawAscii): use putc to dribble file as well * version.h: NEW FILE to carry version numbers only * cs.h: include version.h * swrite.c: * sort.c: * pvoc.c: * ieee80.c: Include cs.h to declare dribble stuff * util2/scale.dir/scale.c: * util2/mixer/xtrct.c: * util2/mixer/mixer.c: Added -- option and change all printf/stderr printing to new style * cs.h: Add extern declaration of dribble * lpanal.c (lpanal): * pvanal.c (pvanal): * hetro.c (hetro): Added -- option to log Fri Feb 16 07:37:55 1996 John Fitch * util2/sndinfo/main.c (main): ANSIfy and add dribble stuff * util2/mixer/xtrct.c: * util2/envext/envext.c: * util1/sortex/smain.c: * util1/sortex/xmain.c: * anal/pvoc/main.c: * anal/lpc/main.c: * anal/adsyn/main.c: Added functions dribble_printf and err_printf Thu Feb 15 10:13:40 1996 John Fitch * DECaudio.c * DECplay.c * blaster.c * cvanal.c * hetro.c * ieee80.c * linevent.c * lpanal.c * main.c * memalloc.c * midirecv.c * musmon.c * otran.c * pvanal.c * pvoc.c * rdorch.c * rtaudio.c * sfheader.c * sort.c * spectra.c * sread.c * swrite.c * twarp.c * wave.c * winSGI.c * winbor.c * winfg.c * winwat.c: fprintf(stderr,...) -> err_printf(...) * main.c (dribble_printf): New function to write to stdout and dribble. (err_printf): dito for stderr. * cs.h: Macro printf to dribble_printf and declare it. * main.c (endif): Make -- option for a log/dribble file. Declare dribble variable. Mon Feb 12 08:53:29 1996 John Fitch * musmon.c (musmon): Added guard to opening O.playscore as at least Linux barfs (thabks to Richard Furse). Thu Feb 1 09:41:00 1996 John Fitch * lpanal.c (gauss): Change all *(b+..) of b[...] for clarity (alpol): Calcular error at end more simply -- less arithmetic but some danger of overflow (but I think not) Mon Jan 29 09:51:34 1996 John Fitch * lpanal.c (lpanal, alpol): Allocate array x once in lpanal rather than on every call of alpol. (gauss): Similar for aold Sun Jan 28 15:50:00 1996 John Fitch * lpanal.c (alpol): Optimise a pow(..., 2.0) to a product * mw_menu.c (dlgUtilLpAnal): Set mark in box for Verbose and Graphics boxs (dlgUtilPvAnal): The same. (dlgFileOpen): Allow direct editing of orc and sco file names. Also requires change in Csound.rsrc (dlgUtilLpAnal): Added a Debug option and corrected verbose to give -v1 Mon Jan 22 08:53:45 1996 John Fitch * Csound.rsrc: (Mac only) added titles to dialogs and fixed mini-typo in dialog linking Sun Jan 21 20:15:40 1996 John Fitch * musmon.c (musmon): Remove call to RTclose as atexit does it * linevent.c (RTLineset): Use atexit to arrange call to RTclose Sun Jan 14 21:25:06 1996 John Fitch * sysdep.h: * soundio.c: * pvoc.c: * otran.c: * mw_menu.c: * midirecv.c: * memfiles.c: * main.c: * linevent.c: * filopen.c: * dpwelib.h: * cs.h: Changed THINK_C to SYMANTEC as need to modify their library as bug in I/O. Sun Jan 7 14:49:44 1996 John Fitch * Change type of cscore to void for consistency Thu Jan 4 08:15:53 1996 John Fitch * grain4.c (graingenv4): Changed a 1.0* to a float for speed * cs.h (SUBVER): CHANGE VERSION NUMBER TO 3.36 * grain.c (agsset): Added a size check in the decision to get a new buffer. Wed Jan 3 07:46:39 1996 John Fitch * winX11.c (ExitGraph): Added a check to the CSNOSTOP environment variable to avoid the final wait for click. Mon Jan 1 18:56:08 1996 John Fitch * main.c (endif): Need an exit(0) after call to cvanal Thu Dec 28 16:55:27 1995 John Fitch * util2/mixer/mixer.c (MixSound): In output buffer step by number of channels * util2/mixer/mixer.c: Added prototypes and includes Wed Dec 27 21:16:29 1995 John Fitch * util2/mixer/mixer.c (InitScaleTable): Deal with same x values in table in different way. * util2/mixer/mixer.c (MixSound): Add code to handle stereo etc inputs correctly, with additional field in structure. Mon Dec 25 14:38:20 1995 John Fitch * util2/mixer/mixer.c (main): Added AE_BYTE format (bytetran): New function Fri Dec 22 10:14:06 1995 John Fitch * grain4.c (grainsetv4): Various spelling corrections and minor optimisations. Also changes exit(1) to initerror calls and return. Tue Dec 19 09:34:52 1995 John Fitch * cs.h: Upped VERSION to 3.35 * grain4.c: NEW FILE for granular synthesis * entry.c: Added buthp, butlp, butbp, butbr as synonyms for butterXX, and convle and an abbreviation for convolve. Added grain4 operator * cs.h: Added a next field in MEMFIL to relax memfiles.c * memfiles.c (rlsmemfiles): Adjust to delete from the revised structure (ldmemfile): Follow list of MEMFILs while looking for file Sat Dec 16 14:35:22 1995 John Fitch * mw_menu.c: Added utilities dialogs, and other stuff. * pvanal.c (takeFFTs): Added POLL_EVENTS at end of loop * lpanal.c (lpanal): Added call to POLL_EVENTS at end of loop for Mac and PC. * winsound.ico, dream.ico: Changed to have screen background Sun Dec 3 09:35:05 1995 John Fitch * soundio.c (audwrite): For macintosh make heartbeat use the metronome cursor. * rdscor.c (rdscor): Close score file at EOF. Sat Dec 2 18:04:03 1995 John Fitch * main.c (main): Correct the check for WAV+format and AIFF+format Tue Nov 21 07:22:20 1995 John Fitch * soundio.h: (solaris) include * soundio.c: (solaris) define audiofd variable (sfopenout): (solaris) write header specially * sfheader.c: Solaris support, include (readheader): No need for ininfop, and do rewind (solaris) (writeheader): Solaris has different checks for devaudio when opening. * rtaudio.c: Add solaris support * rdorch.c: Include for solaris * midirecv.c: Add Solaris support * makefile: Added Solaris2.4 library stuff Mon Oct 30 07:16:41 1995 John Fitch * cwin.h: Remove referrences to Greek. Sun Oct 29 10:27:53 1995 John Fitch * winsound.rc: Modified Dialog_1 for unsigned 8bit and reshape Made file names wider, and reposition on screen * cs.h (SUBVER): Increased to 34 * wave.c (wavWriteHdr): Set len0 filed to databytes+36 as suggested by Mohr (wavReWriteHdr): Set len0 to 8 bytes less than end -- seems odd (wavReadHeader): Force BYTE format * soundio.c (iotranset): Set up BYTE format, twice (bytetran): New function for unsigned 8-bit samples (bzerotran): New function ditto (byterecv): New function ditto * soundin.c (getstrformat): Add AE_BYTE format (getsizformat): formatsiz longer for new format, and test against AE_LAST (sndgetset): Add AE_BYTE (getsndin): BYTE format again, in all and select channel forms (soundin): BYTE format * rtaudio.c: Includes and defines for LINUX (recopen): Open for LINUX (playopen): Open and set volume for LINUX (rtrecord): Get LINUX bytes (rtplay): Write LINUX bytes (rtclose): and LINUX close * midirecv.c: Add #defines for LINUX * makefile: Comment on options for LINUX * soundio.h (AE_BYTE): Defined for unsigned 8bit (AE_LAST): Defined for checking purposes * main.c (main): Added -8 option for unsigned 8bit samples. (main): In WAV format must be -8 or -s format (main): Add -V for volume option (LINUX only) (usage): and extend message tp reflect all this * cs.h: Added Volume field to OPARMS structure for LINUX only Mon Oct 23 09:53:37 1995 John Fitch * cs.h (SUBVER): Up subversion number to 33 * cwin.cpp (cwin_args): Set play_on_exit to false unless it is a WAV format. (CDialog): Add OnPlay method * dialogs.h: Add check box for play on exit * winsound.rc: Add Check box for play_on_exit Sun Oct 22 21:31:06 1995 John Fitch * cwin.cpp (cwin_exit): Added code to play sound file on exit and a flag set. No link to set flag yet. Tue Oct 17 22:37:08 1995 John Fitch * main.c (main): Add printing of Version number at start; may revise this. Mon Oct 16 21:07:23 1995 John Fitch * pvdlg.cpp (Cpvdlg::Cpvdlg): Initialise input and output from registry (pvanal_dialog): Write file names back to registry * lpcdlg.cpp (Clpcdlg::Clpcdlg): Initialise input and output from registry (lpanal_dialog): Write file names back to registry * hetdlg.cpp (Chetdlg::Chetdlg): Initialise input and output from registry (hetro_dialog): Write file names back to registry * cvdlg.cpp (Ccvdlg::Ccvdlg): Initialise input and output from registry (cvanal_dialog): Write file names back to registry Mon Oct 16 06:06:57 1995 John Fitch * cwin.cpp: Remove declaration of CTheApp class * cwin.h: Move delaration of CTheApp class to C++ section and get external reference to theApp * cwin.cpp: Generally remove Symbol fonts and Greek (CArg::CArg): Initialise from the registry (cwin_args): Write values back to registry (CArg): Declare csound_section (CArg::OnExtras): Initialize and save in registry (CArg::OnInitDialog): Initialise butons as in registry (CSextras::DoDataExchange): Use DDX to initialise check boxes rather than methods * wave.c (wavWriteHdr): Improved comments Sun Oct 1 16:43:18 1995 John Fitch * WINDOWS Version: Now can distribute cwin.cpp and associated files Sun Sep 24 09:44:59 1995 John Fitch * DOS VERSION: Renames cspent.* to csound.* and change the project accordingly. Wed Sep 20 21:33:40 1995 John Fitch * oload.c (oload): In test for inconsistent sr/kr!=ksmps add extra printing to look for possible MAC bug. Sat Aug 12 15:38:36 1995 John Fitch * memfiles.c (RD_OPTS): Extra cases for DOSGCC, LATTICE and the rest (LoadFile): IGNORE foo argument, and use RD_OPTS as arg to open Sun Jul 30 10:20:57 1995 John Fitch * oload.c (oload): Mac specific STasks -> POLL_EVENTS * winascii.c (MakeAscii): Add second (unused) argument so agrees with design (DrawAscii): POLL_EVENTS in the loop (not mac only STasks) * rdorch.c: For SUN computers need to define SEEK_SET etc as their compiler is not true ANSI (splitline): Mac specific STasks -> POLL_EVENTS * scsort.c: include cs.h for POLL_EVENTS (scsort): Now a void function, and Mac specific STasks -> POLL_EVENTS * otran.c (insprep): Remove unused variable newlabs (insprep): Remove unused variable newlarg (insprep): Mac only STasks -> POLL_EVENTS (constndx): Remove old (commented out) code to read numbers as the scanf version seems more secure. * insert.c (kperf): Layout (kperf): Changed Mac specific STasks to POLL_EVENTS for generality (rireturn): Explicit IGNORE of argument to keep compiler quiet (reinit): Add explicit cast to keep type system sweet * cs.h: Include : __ZTC__ -> __ZPC__ and WATCOMC support : LATTICE C support incorporated from Atari : Declare structures only if in C (not C++) Declare POLL_EVENTS as STasks in Mac, nothing in C, and leave in WINDOWS; for CWIN need to macro fprintf and printf to window-writing versions Sat Jul 29 15:22:05 1995 John Fitch * soundio.h: ANSI only prototypes * filopen.c: Declare soundfile_pointer if on MetroWerks compiler (sssfinit): Add __MWERKS__ to THINK_C (isfullpath): Add __MWERKS__ to THINK_C (catpath): Add __MWERKS__ to THINK_C (unquote): Add __MWERKS__ to THINK_C : Definition of RD_OPTS and WR_OPTS for MetroWerks Define O_BINARY if not done already and use in teh RD/WR OPTS (openout): Not defined for MWERKS, and totally new version, and define tell * soundio.c (audwrite): POLL_EVENTS after heartbeat (sfopenout): For Mac direct output is in AE_SHORT format (sfopenout): Add Mac Headers and Creator (Mac only!) (chartran): Add cast to long as appropriate * sfheader.c (readheader): MetroWerks support (for powerPc) (readheader): Remove unused variable n (readheader): Tidy up #if...#elif... structure (readheader): Do a SEEK to end before closing file to get size, rather than use calculated value, and better general case (writeheader): Add casts in call to write (writeheader): Support fotr Mac file type moved elsewhere Sat Jul 15 15:11:47 1995 John Fitch * pvanal.c: ANSI prototypes only __ZTC__ -> __ZPC__ so Mac compiles (pvanal): Now an int valued function, and calls dialog in WINDOWS case (pvanal): Added -V and -v options for tracing, and print PV data if verbose is set (quit): Change usage message for -v and -V (takeFFTs): IGNORE outputPVH argument (takeFFTs): Do not print simple messages is verbose is set (takeFFTs): but print it later in detail (PrintBuf): Print trace to the trace file * pvoc.c: __ZTC__ -> __ZPC__ * ustub.h: __ZTC__ -> __ZPC__ * musmon.c (musmon): __ZTC__ -> __ZPC__ (musmon): Added calls to POLL_EVENTS all over the place (musmon): If LINEin in use call RTClose as part of clean up (playevents): Call POLL_EVENTS in the loop * lpanal.c: __ZTC__ -> __ZPC__ (lpanal): Now a int valued function, returning non zero for success (lpanal): Remove unused variable nsamps (lpanal): Call dialog system for WINDOWS (lpanal): __ZTC__ -> __ZPC__ (lpanal): Remove unused variable fp2 * linevent.c: Declare stdmode to save old mode of tty (RTLineset): __ZTC__ -> __ZPC__ (RTLineset): Remember old tty mode in stdmode (UNIX only) (RTclose): If output was to tty restore the mode in UNIX cases [Last two fix bug about disapprearing Xterms] (sensLine): ANSI header * sysdep.h: __ZTC__ -> __ZPC__ * dsputil.c: Change __ZTC__ to __ZPC_ and add support for WATCOMC (Rect2Polar): Remove unused variable pha (MakeHalfWin): Removed unused variable a,b and i * dpwelib.h: Change __ZTC__ to __ZPC__ as it interferes with Macintosh compiler * midirecv.c: __ZTC__ -> __ZPC__ (MidiOpen): IGNORE arg if not SGI (m_timcod_QF): IGNORE arguments (m_song_pos): IGNORE arguments (m_song_sel): IGNORE arguments * main.c: __ZTC__ -> __ZPC__ : for Windows declare dialog functions, and rename main to cwin_main (main): add POLL_EVENTS and for Windows call cwin_atexit to free space; call dialog system (main): WATCOM C support (dialog_arguments): WINDOWS only call dialog for arguments Tue Jun 11 11:30:15 1995 John Fitch * memalloc.c (all_free): WINDOWS only function to return all space controlled by at_exit; record up to 1024 blocks (mcalloc): Record space (WINDOWS only) (mmalloc): Record space (WINDOWS only) (mrealloc): Record space (WINDOWS only) Sun Jul 9 16:51:13 1995 John Fitch * hetro.c (hetro): Make it a int function rather than void, and add dialog support for Windows (hetro): POLL_EVENTS() added, and also some debugging code Thu Jun 8 08:49:11 1995 John Fitch * ugens9.c: Correct prototype for writeFromCircBuf * ugens3.c (losset): Proper ANSI prototype for ftnp2find * wave.c (wavReadHeader): IGNORE fname argument * winwat.c (my_term): IGNORE argument (MakeGraph): IGNORE arguments (DrawGraph): Remove unused variables ma,mi and c (DrawGraph): and nx and ny (KillGraph): IGNORE argument (MakeXYin): IGNORE arguments (ReadXYin): IGNORE argument * winfg.c (MakeGraph): Add some debugging as it sometimes get screen wrong * disprep.c (tempeset): Comment out unused variables coef and log001 (tempest): Remove unused xscale variable * ugens8.c: Remove unused variables fzero and fone (pvset): Remove unused variables cp and pvp (pvoc): Remove unused variables nsmps and samp * vdelay.c (ESR): Extra brackets (reverb2_play): Remove unused variable temp, and shorten some warnings (for 286!) Sun Jun 4 13:40:29 1995 John Fitch * scot.c: ANSIfied all declarations * scot.h: and the same * prototyp.h: Change hetro, lpanal, pvanal and cvanal into returning int so the dialogs can indicate success; declare macro IGNORE for general use, and for CWIN declare all_free function * ieee80.c (myUlongToDouble): Layout (myDoubleToUlong): Layout * window.c: ANSI prototypes (DummyFn2): IGNORE arguments (DummyFn1): IGNORE arguments (RdXYDummy): IGNORE arguments (dispinit): The functions assigned are now differentiated as their type differ (dispkill): ANSI format (display): ANSI format * fft.c (FFT2torlpacked): Removed unused variable mm (FFT2realpacked): Removed unused variable mm (FFT2rawpacked): Removed unused variable i Sat Jun 3 17:29:39 1995 John Fitch * express.c (express): Remove unused variable p Sun May 14 18:15:18 1995 John Fitch * dumpf.c (nkdump): Increase precision of output from %4.2 to %6.4 in two places Sat May 13 10:19:24 1995 John Fitch * aiff.c: various debugging statements added, all commented out. Thu Apr 27 15:47:36 1995 John Fitch * sndinfo.c (sndinfo): Add POLL_EVENTS at the start of the function (not sure it is necessary?) * cvanal.c (cvanal): Added support for cvanal_dialog in Windows (quit): Return 1 rather than zero in exit. (takeFFT): Added call to POLL_EVENTS() twice (cvanal): Return 1 as value (true) * blaster.c: In dmaChannel structure use shorts instead of ints (SB_DMA2): Remove macro for DMA2 as now table driven (sb_wait): Count down check so to avoid a hang (sbplay): Mask Channel down to 2 bits (not necessary but clean) Sun Feb 26 1995 John Fitch * winSGI.c (Graphable): ANSI void added (drawAxes): and again * window.h: ANSI format prototypes only * winX11.c: ANSI prototypes only (myXwinWait): ANSI declaration (myXwait): ANSI declaration (myXWaitForExpose): ANSI declaration (Graphable): ANSI declaration (MakeWindow): ANSI declaration (MakeGraph): ANSI declaration (MakeXYin): ANSI declaration (DrawGraph): ANSI declaration (ReadXYin): ANSI declaration (KillWin): ANSI declaration (KillGraph): ANSI declaration (KillXYin): ANSI declaration (ExitGraph): ANSI declarationoa csound-6.10.0/Custom.cmake.ex000066400000000000000000000015621321653344700157740ustar00rootroot00000000000000# CUSTOM PROPERTIES TO SET # GLOBAL #set(CMAKE_BUILD_TYPE "Debug") set(CMAKE_VERBOSE_MAKEFILE ON) set(BUILD_STATIC_LIBRARY ON) set(TCL_VERSION 8.5) set(PYTHON_INCLUDE_DIRS "/usr/include/python2.7") ##set(BUILD_CSOUND_AC OFF) ##set(BUILD_CSOUND_AC_PYTHON_INTERFACE OFF) ##set(BUILD_CSOUND_AC_LUA_INTERFACE OFF) #### NOTE the processor type needs setting set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -W -Wall -mtune=core2") ## also to test multicore #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -W -Wno-missing-field-initializers -Wno-unused-parameter -mtune=core2 -DJPFF") if(WIN32) list(APPEND CMAKE_SYSTEM_INCLUDE_PATH "c:/work/libsndfile-1_0_17") list(APPEND CMAKE_SYSTEM_LIBRARY_PATH "c:/work/libsndfile-1_0_17") list(APPEND CMAKE_SYSTEM_LIBRARY_PATH "c:/Python25/libs") list(APPEND CMAKE_SYSTEM_INCLUDE_PATH "c:/Python25/include") endif() csound-6.10.0/Engine/000077500000000000000000000000001321653344700143065ustar00rootroot00000000000000csound-6.10.0/Engine/README.md000066400000000000000000000037731321653344700155770ustar00rootroot00000000000000Engine: files for internal engine operation ================================ * auxfd.c: auxiliar resources management for opcodes * cfgvar.c: configuration variable functions * corfiles.c: core file processing for csound programs and scores * cs_new_dispatch.c: parallel csound task dependency management and dispatching * cs_par_base.c: parallel csound functions * cs_par_dispatch.c: parallel csound locks * cs_par_orc_semantic_analysis.c: parallel csound semantics * csound_data_structures.c: useful data structures (lists, cons cells, hash tables etc) * csound_orc.lex: csound language lexer * csound_orc.y: csound language parser * csound_orc_compile.c: csound compiler * csound_orc_expressions.c: expression translation, argument lists, etc * csound_orc_optimize.c: expression optimisation * csound_orc_semantics.c: csound code semantic analysis * csound_pre.lex: csound language preprocessor lexer * csound_prs.lex: score preprocessor lexer * csound_sco.lex: score lexer * csound_sco.y: score parser * csound_standard_types.c : csound language internal types * csound_type_system.c : type system functions * entry1.c: opcode database * envvar.c: environment variable and file opening functions * extract.c: score extraction * fgens.c: function table generators * insert.c: opcode instantiation and insertion, user-defined opcode functions * linevent.c: realtime event processing * memalloc.c: memory resources management * memfiles.c: functions for memory files * musmon.c: performance control and event scheduling * namedins.c: functions for named instrument system * new_orc_parser.c: csound language parser control * parse_param.h: macro parameters orchestra parsing structures and prototypes * score_param.h: macro parameters score parsing structures and prototypes * scsort.c: score sorting * scxtract.c: score extraction * sort.c: sorting functions * sread.c: score reading functions. * swritestr.c: score corefile writing. * symbtab.c: compiler symbol table, user-defined opcode parameter setting. * twarp.c: score time warping. csound-6.10.0/Engine/auxfd.c000066400000000000000000000162451321653344700155710ustar00rootroot00000000000000/* auxfd.c: Copyright (C) 1991 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* AUXFD.C */ static CS_NOINLINE void auxchprint(CSOUND *, INSDS *); static CS_NOINLINE void fdchprint(CSOUND *, INSDS *); /* allocate an auxds, or expand an old one */ /* call only from init (xxxset) modules */ void csoundAuxAlloc(CSOUND *csound, size_t nbytes, AUXCH *auxchp) { if (auxchp->auxp != NULL) { /* if allocd with same size, just clear to zero */ if (nbytes == (size_t)auxchp->size) { memset(auxchp->auxp, 0, nbytes); return; } else { void *tmp = auxchp->auxp; /* if size change only, free the old space and re-allocate */ auxchp->auxp = NULL; csound->Free(csound, tmp); } } else { /* else link in new auxch blk */ auxchp->nxtchp = csound->curip->auxchp; csound->curip->auxchp = auxchp; } /* now alloc the space and update the internal data */ auxchp->size = nbytes; auxchp->auxp = csound->Calloc(csound, nbytes); auxchp->endp = (char*)auxchp->auxp + nbytes; if (UNLIKELY(csound->oparms->odebug)) auxchprint(csound, csound->curip); } static uintptr_t alloc_thread(void *p) { AUXASYNC *pp = (AUXASYNC *) p; CSOUND *csound = pp->csound; AUXCH newm; char *ptr; if (pp->auxchp->auxp == NULL) { /* Allocate new memory */ newm.size = pp->nbytes; newm.auxp = csound->Calloc(csound, pp->nbytes); newm.endp = (char*) newm.auxp + pp->nbytes; ptr = (char *) newm.auxp; newm = *(pp->notify(csound, pp->userData, &newm)); /* check that the returned pointer is not NULL and that is not the memory we have just allocated in case the old memory was never swapped back. */ if (newm.auxp != NULL && newm.auxp != ptr) csound->Free(csound, newm.auxp); } else { csoundAuxAlloc(csound,pp->nbytes,pp->auxchp); pp->notify(csound, pp->userData, pp->auxchp); } return 0; } /* Allocate an auxds asynchronously and pass the newly allocated memory via a callback, where it can be swapped if necessary. */ int csoundAuxAllocAsync(CSOUND *csound, size_t nbytes, AUXCH *auxchp, AUXASYNC *as, aux_cb cb, void *userData) { as->csound = csound; as->nbytes = nbytes; as->auxchp = auxchp; as->notify = cb; as->userData = userData; if (UNLIKELY(csoundCreateThread(alloc_thread, as) == NULL)) return CSOUND_ERROR; else return CSOUND_SUCCESS; } /* put fdchp into chain of fd's for this instr */ /* call only from init (xxxset) modules */ void fdrecord(CSOUND *csound, FDCH *fdchp) { fdchp->nxtchp = csound->curip->fdchp; csound->curip->fdchp = fdchp; if (UNLIKELY(csound->oparms->odebug)) fdchprint(csound, csound->curip); } /* close a file and remove from fd chain */ /* call only from inits, after fdrecord */ void fdclose(CSOUND *csound, FDCH *fdchp) { FDCH *prvchp = NULL, *nxtchp; nxtchp = csound->curip->fdchp; /* from current insds, */ while (LIKELY(nxtchp != NULL)) { /* chain through fdlocs */ if (UNLIKELY(nxtchp == fdchp)) { /* till find this one */ void *fd = fdchp->fd; if (LIKELY(fd)) { fdchp->fd = NULL; /* then delete the fd */ csoundFileClose(csound, fd); /* close the file & */ } if (prvchp) prvchp->nxtchp = fdchp->nxtchp; /* unlnk from fdchain */ else csound->curip->fdchp = fdchp->nxtchp; if (UNLIKELY(csound->oparms->odebug)) fdchprint(csound, csound->curip); return; } prvchp = nxtchp; nxtchp = nxtchp->nxtchp; } fdchprint(csound, csound->curip); csound->Die(csound, Str("fdclose: no record of fd %p"), fdchp->fd); } /* release all xds in instr auxp chain */ /* called by insert at orcompact */ void auxchfree(CSOUND *csound, INSDS *ip) { if (UNLIKELY(csound->oparms->odebug)) auxchprint(csound, ip); while (LIKELY(ip->auxchp != NULL)) { /* for all auxp's in chain: */ void *auxp = (void*) ip->auxchp->auxp; AUXCH *nxt = ip->auxchp->nxtchp; memset((void*) ip->auxchp, 0, sizeof(AUXCH)); /* delete the pntr */ csound->Free(csound, auxp); /* & free the space */ ip->auxchp = nxt; } if (UNLIKELY(csound->oparms->odebug)) auxchprint(csound, ip); } /* close all files in instr fd chain */ /* called by insert on deact & expire */ /* (also musmon on s-code, & fgens for gen01) */ void fdchclose(CSOUND *csound, INSDS *ip) { if (UNLIKELY(csound->oparms->odebug)) fdchprint(csound, ip); /* for all fd's in chain: */ for ( ; ip->fdchp != NULL; ip->fdchp = ip->fdchp->nxtchp) { void *fd = ip->fdchp->fd; if (LIKELY(fd)) { ip->fdchp->fd = NULL; /* delete the fd */ csoundFileClose(csound, fd); /* & close the file */ } } if (UNLIKELY(csound->oparms->odebug)) fdchprint(csound, ip); } /* print the xp chain for this insds blk */ static CS_NOINLINE void auxchprint(CSOUND *csound, INSDS *ip) { AUXCH *curchp; char *name = csound->engineState.instrtxtp[ip->insno]->insname; if (name) csoundMessage(csound, Str("auxlist for instr %s [%d] (%p):\n"), name, ip->insno, ip); else csoundMessage(csound, Str("auxlist for instr %d (%p):\n"), ip->insno, ip); /* chain through auxlocs */ for (curchp = ip->auxchp; curchp != NULL; curchp = curchp->nxtchp) csoundMessage(csound, Str("\tauxch at %p: size %zu, auxp %p, endp %p\n"), curchp, curchp->size, curchp->auxp, curchp->endp); } /* print the fd chain for this insds blk */ static CS_NOINLINE void fdchprint(CSOUND *csound, INSDS *ip) { FDCH *curchp; char *name = csound->engineState.instrtxtp[ip->insno]->insname; if (name) csoundMessage(csound, Str("fdlist for instr %s [%d] (%p):"), name, ip->insno, ip); else csoundMessage(csound, Str("fdlist for instr %d (%p):"), ip->insno, ip); /* chain through fdlocs */ for (curchp = ip->fdchp; curchp != NULL; curchp = curchp->nxtchp) csoundMessage(csound, Str(" fd %p in %p"), curchp->fd, curchp); csoundMessage(csound, "\n"); } csound-6.10.0/Engine/cfgvar.c000066400000000000000000000464321321653344700157330ustar00rootroot00000000000000/* cfgvar.c: Copyright (C) 2005 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include "csoundCore.h" #include "cfgvar.h" #include "namedins.h" /* the global database */ /* list of error messages */ static const char *errmsg_list[] = { Str_noop("(no error)"), Str_noop("invalid variable name"), Str_noop("invalid variable type"), Str_noop("invalid flags specified"), Str_noop("NULL pointer argument"), Str_noop("the specified value is too high"), Str_noop("the specified value is too low"), Str_noop("the specified value is not an integer power of two"), Str_noop("invalid boolean value; must be 0 or 1"), Str_noop("memory allocation failed"), Str_noop("string exceeds maximum allowed length"), Str_noop("(unknown error)") }; /* check if the specified name, and type and flags values are valid */ static int check_name(const char *name) { int i, c; if (UNLIKELY(name == NULL)) return CSOUNDCFG_INVALID_NAME; if (UNLIKELY(name[0] == '\0')) return CSOUNDCFG_INVALID_NAME; i = -1; while (name[++i] != '\0') { c = (int) ((unsigned char) name[i]); if (UNLIKELY((c & 0x80) || !(c == '_' || isalpha(c) || isdigit(c)))) return CSOUNDCFG_INVALID_NAME; } return CSOUNDCFG_SUCCESS; } static int check_type(int type) { switch (type) { case CSOUNDCFG_INTEGER: case CSOUNDCFG_BOOLEAN: case CSOUNDCFG_FLOAT: case CSOUNDCFG_DOUBLE: case CSOUNDCFG_MYFLT: case CSOUNDCFG_STRING: break; default: return CSOUNDCFG_INVALID_TYPE; } return CSOUNDCFG_SUCCESS; } static int check_flags(int flags) { if (UNLIKELY((flags & (~(CSOUNDCFG_POWOFTWO))) != 0)) return CSOUNDCFG_INVALID_FLAG; return CSOUNDCFG_SUCCESS; } /** * Allocate configuration variable structure with the specified parameters: * name: name of the variable (may contain letters, digits, and _) * p: pointer to variable * type: type of variable, determines how 'p' is interpreted * CSOUNDCFG_INTEGER: int* * CSOUNDCFG_BOOLEAN: int* (value may be 0 or 1) * CSOUNDCFG_FLOAT: float* * CSOUNDCFG_DOUBLE: double* * CSOUNDCFG_MYFLT: MYFLT* * CSOUNDCFG_STRING: char* (should have enough space) * flags: bitwise OR of flag values, currently only CSOUNDCFG_POWOFTWO * is available, which requests CSOUNDCFG_INTEGER values to be * power of two * min: for CSOUNDCFG_INTEGER, CSOUNDCFG_FLOAT, CSOUNDCFG_DOUBLE, and * CSOUNDCFG_MYFLT, a pointer to a variable of the type selected * by 'type' that specifies the minimum allowed value. * If 'min' is NULL, there is no minimum value. * max: similar to 'min', except it sets the maximum allowed value. * For CSOUNDCFG_STRING, it is a pointer to an int variable * that defines the maximum length of the string (including the * null character at the end) in bytes. This value is limited * to the range 8 to 16384, and if max is NULL, it defaults to 256. * shortDesc: a short description of the variable (may be NULL or an empty * string if a description is not available) * longDesc: a long description of the variable (may be NULL or an empty * string if a description is not available) * A pointer to the newly allocated structure is stored in (*ptr). * Return value is CSOUNDCFG_SUCCESS, or one of the error codes. */ static int cfg_alloc_structure(CSOUND* csound, csCfgVariable_t **ptr, const char *name, void *p, int type, int flags, void *min, void *max, const char *shortDesc, const char *longDesc) { int structBytes = 0, nameBytes, sdBytes, ldBytes, totBytes; void *pp; unsigned char *sdp = NULL, *ldp = NULL; (*ptr) = (csCfgVariable_t*) NULL; /* check for valid parameters */ if (UNLIKELY(p == NULL)) return CSOUNDCFG_NULL_POINTER; if (UNLIKELY(check_name(name) != CSOUNDCFG_SUCCESS)) return CSOUNDCFG_INVALID_NAME; if (UNLIKELY(check_type(type) != CSOUNDCFG_SUCCESS)) return CSOUNDCFG_INVALID_TYPE; if (UNLIKELY(check_flags(flags) != CSOUNDCFG_SUCCESS)) return CSOUNDCFG_INVALID_FLAG; /* calculate the number of bytes to allocate */ structBytes = ((int) sizeof(csCfgVariable_t) + 15) & (~15); nameBytes = (((int) strlen(name) + 1) + 15) & (~15); if (shortDesc != NULL) sdBytes = (shortDesc[0] == '\0' ? 0 : (int) strlen(shortDesc) + 1); else sdBytes = 0; sdBytes = (sdBytes + 15) & (~15); if (longDesc != NULL) ldBytes = (longDesc[0] == '\0' ? 0 : (int) strlen(longDesc) + 1); else ldBytes = 0; ldBytes = (ldBytes + 15) & (~15); totBytes = structBytes + nameBytes + sdBytes + ldBytes; /* allocate memory */ pp = (void*) csound->Calloc(csound, (size_t) totBytes); if (UNLIKELY(pp == NULL)) return CSOUNDCFG_MEMORY; //memset(pp, 0, (size_t) totBytes); (*ptr) = (csCfgVariable_t*) pp; /* copy name and descriptions */ strcpy(((char*) pp + (int) structBytes), name); if (sdBytes > 0) { sdp = (unsigned char*) pp + (int) (structBytes + nameBytes); strcpy((char*) sdp, shortDesc); } else sdp = NULL; if (ldBytes > 0) { ldp = (unsigned char*) pp + (int) (structBytes + nameBytes + sdBytes); strcpy((char*) ldp, longDesc); } else ldp = NULL; /* set up structure */ (*ptr)->h.nxt = (csCfgVariable_t*) NULL; (*ptr)->h.name = (unsigned char*) pp + (int) structBytes; (*ptr)->h.p = p; (*ptr)->h.type = type; (*ptr)->h.flags = flags; (*ptr)->h.shortDesc = sdp; (*ptr)->h.longDesc = ldp; /* depending on type */ switch (type) { case CSOUNDCFG_INTEGER: /* integer */ (*ptr)->i.min = (min == NULL ? -0x7FFFFFFF : *((int*) min)); (*ptr)->i.max = (max == NULL ? 0x7FFFFFFF : *((int*) max)); break; case CSOUNDCFG_BOOLEAN: /* boolean */ (*ptr)->b.flags &= (~(CSOUNDCFG_POWOFTWO)); break; case CSOUNDCFG_FLOAT: /* float */ (*ptr)->f.flags &= (~(CSOUNDCFG_POWOFTWO)); (*ptr)->f.min = (min == NULL ? -1.0e30f : *((float*) min)); (*ptr)->f.max = (max == NULL ? 1.0e30f : *((float*) max)); break; case CSOUNDCFG_DOUBLE: /* double */ (*ptr)->d.flags &= (~(CSOUNDCFG_POWOFTWO)); (*ptr)->d.min = (min == NULL ? -1.0e30 : *((double*) min)); (*ptr)->d.max = (max == NULL ? 1.0e30 : *((double*) max)); break; case CSOUNDCFG_MYFLT: /* MYFLT */ (*ptr)->m.flags &= (~(CSOUNDCFG_POWOFTWO)); (*ptr)->m.min = (min == NULL ? (MYFLT) -1.0e30 : *((MYFLT*) min)); (*ptr)->m.max = (max == NULL ? (MYFLT) 1.0e30 : *((MYFLT*) max)); break; case CSOUNDCFG_STRING: /* string */ (*ptr)->s.flags &= (~(CSOUNDCFG_POWOFTWO)); if (max != NULL) { (*ptr)->s.maxlen = *((int*) max); if ((*ptr)->s.maxlen < 8) (*ptr)->s.maxlen = 8; if ((*ptr)->s.maxlen > 16384) (*ptr)->s.maxlen = 16384; } else (*ptr)->s.maxlen = 256; /* default maximum string length */ break; } /* done */ return CSOUNDCFG_SUCCESS; } /** * This function is similar to csoundCreateGlobalConfigurationVariable(), * except it creates a configuration variable specific to Csound instance * 'csound', and is suitable for calling from the Csound library * (in csoundPreCompile()) or plugins (in csoundModuleCreate()). * The other parameters and return value are the same as in the case of * csoundCreateGlobalConfigurationVariable(). */ PUBLIC int csoundCreateConfigurationVariable(CSOUND *csound, const char *name, void *p, int type, int flags, void *min, void *max, const char *shortDesc, const char *longDesc) { csCfgVariable_t *pp; int retval; /* check if name is already in use */ if (UNLIKELY(csoundQueryConfigurationVariable(csound, name) != NULL)) return CSOUNDCFG_INVALID_NAME; /* if database is not allocated yet, create an empty one */ if (csound->cfgVariableDB == NULL) { csound->cfgVariableDB = cs_hash_table_create(csound); if (UNLIKELY(csound->cfgVariableDB == NULL)) return CSOUNDCFG_MEMORY; } /* allocate structure */ retval = cfg_alloc_structure(csound, &pp, name, p, type, flags, min, max, shortDesc, longDesc); if (UNLIKELY(retval != CSOUNDCFG_SUCCESS)) return retval; /* link into database */ cs_hash_table_put(csound, csound->cfgVariableDB, (char*)name, pp); /* report success */ return CSOUNDCFG_SUCCESS; } /* set configuration variable to value (with error checking) */ static int set_cfgvariable_value(csCfgVariable_t *pp, void *value) { double dVal; MYFLT mVal; float fVal; int iVal; /* set value depending on type */ if (UNLIKELY(value == NULL)) return CSOUNDCFG_NULL_POINTER; switch (pp->h.type) { case CSOUNDCFG_INTEGER: iVal = *((int*) value); if (UNLIKELY(iVal < pp->i.min)) return CSOUNDCFG_TOO_LOW; if (UNLIKELY(iVal > pp->i.max)) return CSOUNDCFG_TOO_HIGH; if (pp->i.flags & CSOUNDCFG_POWOFTWO) if (UNLIKELY(iVal < 1 || (iVal & (iVal - 1)) != 0)) return CSOUNDCFG_NOT_POWOFTWO; *(pp->i.p) = iVal; break; case CSOUNDCFG_BOOLEAN: iVal = *((int*) value); if (UNLIKELY(iVal & (~1))) return CSOUNDCFG_INVALID_BOOLEAN; *(pp->b.p) = iVal; break; case CSOUNDCFG_FLOAT: fVal = *((float*) value); if (UNLIKELY(fVal < pp->f.min)) return CSOUNDCFG_TOO_LOW; if (UNLIKELY(fVal > pp->f.max)) return CSOUNDCFG_TOO_HIGH; *(pp->f.p) = fVal; break; case CSOUNDCFG_DOUBLE: dVal = *((double*) value); if (UNLIKELY(dVal < pp->d.min)) return CSOUNDCFG_TOO_LOW; if (UNLIKELY(dVal > pp->d.max)) return CSOUNDCFG_TOO_HIGH; *(pp->d.p) = dVal; break; case CSOUNDCFG_MYFLT: mVal = *((MYFLT*) value); if (UNLIKELY(mVal < pp->m.min)) return CSOUNDCFG_TOO_LOW; if (UNLIKELY(mVal > pp->m.max)) return CSOUNDCFG_TOO_HIGH; *(pp->m.p) = mVal; break; case CSOUNDCFG_STRING: if (UNLIKELY((int) strlen((char*) value) >= (pp->s.maxlen - 1))) return CSOUNDCFG_STRING_LENGTH; strcpy((char*) (pp->s.p), (char*) value); break; default: return CSOUNDCFG_INVALID_TYPE; } return CSOUNDCFG_SUCCESS; } /** * Set the value of a configuration variable of Csound instance 'csound'. * The 'name' and 'value' parameters, and return value are the same as * in the case of csoundSetGlobalConfigurationVariable(). */ PUBLIC int csoundSetConfigurationVariable(CSOUND *csound, const char *name, void *value) { csCfgVariable_t *pp; /* get pointer to variable */ pp = csoundQueryConfigurationVariable(csound, name); if (UNLIKELY(pp == NULL)) return CSOUNDCFG_INVALID_NAME; /* not found */ return (set_cfgvariable_value(pp, value)); } /* parse string value for configuration variable */ static int parse_cfg_variable(csCfgVariable_t *pp, const char *value) { double dVal; MYFLT mVal; float fVal; int iVal; if (UNLIKELY(value == NULL)) return CSOUNDCFG_NULL_POINTER; switch (pp->h.type) { case CSOUNDCFG_INTEGER: iVal = (int) atoi(value); return set_cfgvariable_value(pp, (void*) (&iVal)); case CSOUNDCFG_BOOLEAN: if (strcmp(value, "0") == 0 || strcmp(value, "no") == 0 || strcmp(value, "No") == 0 || strcmp(value, "NO") == 0 || strcmp(value, "off") == 0 || strcmp(value, "Off") == 0 || strcmp(value, "OFF") == 0 || strcmp(value, "false") == 0 || strcmp(value, "False") == 0 || strcmp(value, "FALSE") == 0) *(pp->b.p) = 0; else if (strcmp(value, "1") == 0 || strcmp(value, "yes") == 0 || strcmp(value, "Yes") == 0 || strcmp(value, "YES") == 0 || strcmp(value, "on") == 0 || strcmp(value, "On") == 0 || strcmp(value, "ON") == 0 || strcmp(value, "true") == 0 || strcmp(value, "True") == 0 || strcmp(value, "TRUE") == 0) *(pp->b.p) = 1; else return CSOUNDCFG_INVALID_BOOLEAN; return CSOUNDCFG_SUCCESS; case CSOUNDCFG_FLOAT: fVal = (float) atof(value); return set_cfgvariable_value(pp, (void*) (&fVal)); case CSOUNDCFG_DOUBLE: dVal = (double) atof(value); return set_cfgvariable_value(pp, (void*) (&dVal)); case CSOUNDCFG_MYFLT: mVal = (MYFLT) atof(value); return set_cfgvariable_value(pp, (void*) (&mVal)); case CSOUNDCFG_STRING: return set_cfgvariable_value(pp, (void*) value); } return CSOUNDCFG_INVALID_TYPE; } /** * Set the value of a configuration variable of Csound instance 'csound', * by parsing a string. * The 'name' and 'value' parameters, and return value are the same as * in the case of csoundParseGlobalConfigurationVariable(). */ PUBLIC int csoundParseConfigurationVariable(CSOUND *csound, const char *name, const char *value) { csCfgVariable_t *pp; /* get pointer to variable */ pp = csoundQueryConfigurationVariable(csound, name); if (UNLIKELY(pp == NULL)) return CSOUNDCFG_INVALID_NAME; /* not found */ return (parse_cfg_variable(pp, value)); } /** * Return pointer to the configuration variable of Csound instace 'csound' * with the specified name. * The return value may be NULL if the variable is not found in the database. */ PUBLIC csCfgVariable_t *csoundQueryConfigurationVariable(CSOUND *csound, const char *name) { if (csound->cfgVariableDB == NULL) { return NULL; } return (csCfgVariable_t*) cs_hash_table_get(csound, csound->cfgVariableDB, (char*)name); } /* compare function for qsort() */ static int compare_func(const void *p1, const void *p2) { return (int) strcmp((char*) ((*((csCfgVariable_t**) p1))->h.name), (char*) ((*((csCfgVariable_t**) p2))->h.name)); } /* create alphabetically sorted list of all entries in 'db' */ static csCfgVariable_t **list_db_entries(CSOUND* csound, CS_HASH_TABLE *db) { csCfgVariable_t **lst; size_t cnt; CONS_CELL* values; values = cs_hash_table_values(csound, db); cnt = cs_cons_length(values); /* allocate memory for list */ lst = (csCfgVariable_t**) csound->Malloc(csound, sizeof(csCfgVariable_t*) * (cnt + (size_t) 1)); if (UNLIKELY(lst == NULL)) return (csCfgVariable_t**) NULL; /* not enough memory */ /* create list */ if (cnt) { cnt = 0; while (values != NULL) { lst[cnt++] = (csCfgVariable_t*)values->value; values = values->next; } qsort((void*) lst, cnt, sizeof(csCfgVariable_t*), compare_func); } lst[cnt] = (csCfgVariable_t*) NULL; /* return pointer to list */ return lst; } /** * Create an alphabetically sorted list of all configuration variables * of Csound instance 'csound'. * Returns a pointer to a NULL terminated array of configuration variable * pointers, or NULL on error. * The caller is responsible for freeing the returned list with * csoundDeleteCfgVarList(), however, the variable pointers in the list * should not be freed. */ PUBLIC csCfgVariable_t **csoundListConfigurationVariables(CSOUND *csound) { return (list_db_entries(csound, csound->cfgVariableDB)); } /** * Release a configuration variable list previously returned * by csoundListGlobalConfigurationVariables() or * csoundListConfigurationVariables(). */ PUBLIC void csoundDeleteCfgVarList(CSOUND* csound, csCfgVariable_t **lst) { if (lst != NULL) csound->Free(csound, lst); } /* remove a configuration variable from 'db' */ static int remove_entry_from_db(CSOUND* csound, CS_HASH_TABLE *db, const char *name) { csCfgVariable_t *pp = cs_hash_table_get(csound, db, (char*)name); if (UNLIKELY(pp == NULL)) return CSOUNDCFG_INVALID_NAME; csound->Free(csound, pp); cs_hash_table_remove(csound, db, (char*)name); return CSOUNDCFG_SUCCESS; } /** * Remove the configuration variable of Csound instance 'csound' with the * specified name from the database. Plugins need not call this, as all * configuration variables are automatically deleted by csoundReset(). * Return value is CSOUNDCFG_SUCCESS in case of success, or * CSOUNDCFG_INVALID_NAME if the variable was not found. */ PUBLIC int csoundDeleteConfigurationVariable(CSOUND *csound, const char *name) { return remove_entry_from_db(csound, csound->cfgVariableDB, name); } static int destroy_entire_db(CSOUND *csound, CS_HASH_TABLE *db) { CONS_CELL *head, *current; if (db == NULL) return CSOUNDCFG_SUCCESS; head = current = cs_hash_table_values(csound, db); while (current != NULL) { if (current->value != NULL) { csound->Free(csound, current->value); } current = current->next; } cs_cons_free(csound, head); cs_hash_table_free(csound, db); return CSOUNDCFG_SUCCESS; } /** * Remove all configuration variables of Csound instance 'csound' * and free database. This function is called by csoundReset(). * Return value is CSOUNDCFG_SUCCESS in case of success. */ int csoundDeleteAllConfigurationVariables(CSOUND *csound) { int retval; retval = destroy_entire_db(csound, csound->cfgVariableDB); csound->cfgVariableDB = NULL; return retval; } /** * Returns pointer to an error string constant for the specified * CSOUNDCFG error code. The string is not translated. */ PUBLIC const char *csoundCfgErrorCodeToString(int errcode) { if (errcode > 0 || errcode < CSOUNDCFG_LASTERROR) return errmsg_list[1 - CSOUNDCFG_LASTERROR]; /* unknown */ else return errmsg_list[(-errcode)]; } csound-6.10.0/Engine/corfiles.c000066400000000000000000000244551321653344700162720ustar00rootroot00000000000000/* corfiles.c: Copyright (C) 2011 John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* CORFILES.C */ #include #include #include #include extern int csoundFileClose(CSOUND*, void*); CORFIL *copy_url_corefile(CSOUND *, const char *, int); CORFIL *corfile_create_w(CSOUND *csound) { CORFIL *ans = (CORFIL*) csound->Malloc(csound, sizeof(CORFIL)); ans->body = (char*)csound->Calloc(csound,100); ans->len = 100; ans->p = 0; return ans; } CORFIL *corfile_create_r(CSOUND *csound, const char *text) { //char *strdup(const char *); CORFIL *ans = (CORFIL*) csound->Malloc(csound, sizeof(CORFIL)); ans->body = cs_strdup(csound, (char*)text); ans->len = strlen(text)+1; ans->p = 0; return ans; } void corfile_putc(CSOUND *csound, int c, CORFIL *f) { char *new; f->body[f->p++] = c; if (UNLIKELY(f->p >= f->len)) { new = (char*) csound->ReAlloc(csound, f->body, f->len+=100); if (UNLIKELY(new==NULL)) { fprintf(stderr, Str("Out of Memory\n")); exit(7); } f->body = new; } f->body[f->p] = '\0'; } void corfile_puts(CSOUND *csound, const char *s, CORFIL *f) { const char *c; int n; /* skip and count the NUL chars to the end */ for (n=0; f->p > 0 && f->body[f->p-1] == '\0'; n++, f->p--); /* append the string */ for (c = s; *c != '\0'; c++) { char *new; f->body[f->p++] = *c; if (UNLIKELY(f->p >= f->len)) { new = (char*) csound->ReAlloc(csound, f->body, f->len+=100); if (UNLIKELY(new==NULL)) { fprintf(stderr, Str("Out of Memory\n")); exit(7); } f->body = new; } } if (n > 0) { /* put the extra NULL chars to the end */ while (--n >= 0) { char *new; f->body[f->p++] = '\0'; if (UNLIKELY(f->p >= f->len)) { new = (char*) csound->ReAlloc(csound, f->body, f->len+=100); if (UNLIKELY(new==NULL)) { fprintf(stderr, Str("Out of Memory\n")); exit(7); } f->body = new; } } } f->body[f->p] = '\0'; } void corfile_flush(CSOUND *csound, CORFIL *f) { char *new; f->len = strlen(f->body)+1; new = (char*)csound->ReAlloc(csound, f->body, f->len); if (UNLIKELY(new==NULL)) { fprintf(stderr, Str("Out of Memory\n")); exit(7); } f->body = new; f->p = 0; } #undef corfile_length int corfile_length(CORFIL *f) { return strlen(f->body); } void corfile_rm(CSOUND *csound, CORFIL **ff) { CORFIL *f = *ff; if (LIKELY(f!=NULL)) { csound->Free(csound, f->body); csound->Free(csound, f); *ff = NULL; } } int corfile_getc(CORFIL *f) { int c = f->body[f->p]; if (UNLIKELY(c=='\0')) return EOF; f->p++; return c; } char *corfile_fgets(char *buff, int len, CORFIL *f) { int i; char *p = &(f->body[f->p]), *q; if (UNLIKELY(*p == '\0')) return NULL; q = strchr(p, '\n'); i = (q-p); if (UNLIKELY(i>=len)) i = len-1; memcpy(buff, p, i); f->p += i; return buff; } #undef corfile_ungetc void corfile_ungetc(CORFIL *f) { --f->p; } MYFLT corfile_get_flt(CORFIL *f) { int n = f->p; MYFLT ans; while (!isspace(f->body[++f->p])); ans = (MYFLT) atof(&f->body[n]); return ans; } #undef corfile_rewind void corfile_rewind(CORFIL *f) { f->p = 0; } #undef corfile_reset void corfile_reset(CORFIL *f) { f->p = 0; f->body[0] = '\0'; } #undef corfile_tell int corfile_tell(CORFIL *f) { return f->p; } #undef corfile_set void corfile_set(CORFIL *f, int n) { f->p = n; } void corfile_seek(CORFIL *f, int n, int dir) { if (dir == SEEK_SET) f->p = n; else if (dir == SEEK_CUR) f->p += n; else if (dir == SEEK_END) f->p = strlen(f->body)-n; if (UNLIKELY(f->p > strlen(f->body))) { printf("INTERNAL ERROR: Corfile seek out of range\n"); exit(1); } } #undef corfile_body char *corfile_body(CORFIL *f) { return f->body; } #undef corfile_current char *corfile_current(CORFIL *f) { return f->body+f->p; } /* *** THIS NEEDS TO TAKE ACCOUNT OF SEARCH PATH *** */ void *fopen_path(CSOUND *csound, FILE **fp, const char *name, const char *basename, char *env, int fromScore); CORFIL *copy_to_corefile(CSOUND *csound, const char *fname, const char *env, int fromScore) { CORFIL *mm; FILE *ff; void *fd; int n; char buffer[1024]; if (UNLIKELY(fname==NULL)) { csound->ErrorMsg(csound, Str("Null file name in copy_to_corefile")); csound->LongJmp(csound, 1); } #ifdef HAVE_CURL if (strstr(fname,"://")) { return copy_url_corefile(csound, fname, fromScore); } #endif fd = fopen_path(csound, &ff, (char *)fname, NULL, (char *)env, fromScore); if (UNLIKELY(ff==NULL)) return NULL; mm = corfile_create_w(csound); memset(buffer, '\0', 1024); while ((n = fread(buffer, 1, 1023, ff))) { /* Need to lose \r characters here */ /* while ((s = strchr(buffer, '\r'))) { */ /* int k = n - (s-buffer); */ /* memmove(s, s+1, k); */ /* n--; */ /* } */ corfile_puts(csound, buffer, mm); memset(buffer, '\0', 1024); } //#ifdef SCORE_PARSER if (fromScore) { corfile_puts(csound, "\n#exit\n", mm); } //#endif corfile_putc(csound, '\0', mm); /* For use in bison/flex */ corfile_putc(csound, '\0', mm); /* For use in bison/flex */ if (fromScore) corfile_flush(csound, mm); csoundFileClose(csound, fd); return mm; } void corfile_preputs(CSOUND *csound, const char *s, CORFIL *f) { char *body = f->body; f->body = (char*)csound->Malloc(csound, f->len=(strlen(body)+strlen(s)+1)); f->p = f->len-1; strcpy(f->body, s); strcat(f->body, body); csound->Free(csound, body); } #ifdef HAVE_CURL #include struct MemoryStruct { char *memory; size_t size; CSOUND* cs; }; static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) { size_t realsize = size * nmemb; struct MemoryStruct *mem = (struct MemoryStruct *)userp; CSOUND *csound = mem->cs; mem->memory = csound->ReAlloc(csound, mem->memory, mem->size + realsize + 1); if (UNLIKELY(mem->memory == NULL)) { /* out of memory! */ printf(Str("not enough memory (realloc returned NULL)\n")); return 0; } memcpy(&(mem->memory[mem->size]), contents, realsize); mem->size += realsize; mem->memory[mem->size] = 0; return realsize; } CORFIL *copy_url_corefile(CSOUND *csound, const char *url, int fromScore) { int n; CURL *curl = curl_easy_init(); CORFIL *mm = corfile_create_w(csound); struct MemoryStruct chunk; chunk.memory = csound->Malloc(csound, 1); /* will grown */ chunk.size = 0; /* no data at this point */ chunk.cs = csound; curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0"); n = curl_easy_perform(curl); if (UNLIKELY(n != CURLE_OK)) { csound->Die(csound, Str("curl_easy_perform() failed: %s\n"), curl_easy_strerror(n)); /* return NULL ? */ } curl_easy_cleanup(curl); corfile_puts(csound, chunk.memory, mm); corfile_putc(csound, '\0', mm); /* For use in bison/flex */ corfile_putc(csound, '\0', mm); /* For use in bison/flex */ if (fromScore) corfile_flush(csound, mm); csound->Free(csound, chunk.memory); curl_global_cleanup(); return mm; } #endif #if 0 int main(void) { CURL *curl_handle; CURLcode res; struct MemoryStruct chunk; /* will grown as needed by the realloc above */ chunk.memory = csound->Malloc(csound, 1); chunk.size = 0; /* no data at this point */ curl_global_init(CURL_GLOBAL_ALL); /* init the curl session */ curl_handle = curl_easy_init(); /* specify URL to get */ curl_easy_setopt(curl_handle, CURLOPT_URL, "http://www.example.com/"); /* send all data to this function */ curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); /* we pass our 'chunk' struct to the callback function */ curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk); /* some servers don't like requests that are made without a user-agent field, so we provide one */ curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); /* get it! */ res = curl_easy_perform(curl_handle); /* check for errors */ if (res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } else { /* * Now, our chunk.memory points to a memory block that is chunk.size * bytes big and contains the remote file. * * Do something nice with it! */ printf("%lu bytes retrieved\n", (long)chunk.size); } /* cleanup curl stuff */ curl_easy_cleanup(curl_handle); if (chunk.memory) free(chunk.memory); /* we're done with libcurl, so clean it up */ curl_global_cleanup(); return 0; } #endif typedef struct dir { char *name; CORFIL *corfile; struct dir *next; } CORDIR; void add_corfile(CSOUND* csound, CORFIL *smpf, char *filename) { CORDIR *entry = csound->Malloc(csound, sizeof(CORDIR)); entry->name = cs_strdup(csound, filename); entry->corfile = smpf; entry->next = (CORDIR *)csound->directory; csound->directory = entry; } csound-6.10.0/Engine/cs_new_dispatch.c000066400000000000000000000675551321653344700176310ustar00rootroot00000000000000/* ** cs_new_dispatch.c ** ** Copyright (C) Martin Brain (mjb@cs.bath.ac.uk) 04/08/12 ** Realisation in code for Csound John ffitch Feb 2013 ** This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ** Fast system for managing task dependencies and dispatching to threads. ** ** Has a DAG of tasks and has to assign them to worker threads while respecting ** dependency order. ** ** OPT marks code relevant to particular optimisations (listed below the code). ** INV marks invariants ** NOTE marks notes */ #include #include #include #include "csoundCore.h" #include "cs_par_base.h" #include "cs_par_orc_semantics.h" #if defined(_MSC_VER) /* For InterlockedCompareExchange */ #include #endif /* Used as an error value */ //typedef int taskID; #define INVALID (-1) #define WAIT (-2) /* Each task has a status */ //enum state { WAITING = 3, /* Dependencies have not been finished */ // AVAILABLE = 2, /* Dependencies met, ready to be run */ // INPROGRESS = 1, /* Has been started */ // DONE = 0 }; /* Has been completed */ /* Sets of prerequiste tasks for each task */ //typedef struct _watchList { // taskID id; // struct _watchList *next; //} watchList; /* Array of states of each task -- need to move to CSOUND structure */ //static enum state *task_status = NULL; /* OPT : Structure lay out */ //static watchList **task_watch = NULL; //static INSDS **task_map = NULL; /* INV : Read by multiple threads, updated by only one */ /* Thus use atomic read and write */ //static char ** task_dep; /* OPT : Structure lay out */ //static watchList * wlmm; #define INIT_SIZE (100) //static int task_max_size; static void dag_print_state(CSOUND *csound) { int i; watchList *w; printf("*** %d tasks\n", csound->dag_num_active); for (i=0; idag_num_active; i++) { printf("%d(%d): ", i, csound->dag_task_map[i]->insno); switch (csound->dag_task_status[i].s) { case DONE: printf("status=DONE (watchList "); w = csound->dag_task_watch[i]; while (w) { printf("%d ", w->id); w=w->next; } printf(")\n"); break; case INPROGRESS: printf("status=INPROGRESS (watchList "); w = csound->dag_task_watch[i]; while (w) { printf("%d ", w->id); w=w->next; } printf(")\n"); break; case AVAILABLE: printf("status=AVAILABLE (watchList "); w = csound->dag_task_watch[i]; while (w) { printf("%d ", w->id); w=w->next; } printf(")\n"); break; case WAITING: { char *tt = csound->dag_task_dep[i]; int j; printf("status=WAITING for tasks ["); for (j=0; jdag_task_max_size; csound->dag_task_status = csound->Calloc(csound, sizeof(stateWithPadding)*max); csound->dag_task_watch = csound->Calloc(csound, sizeof(watchList*)*max); csound->dag_task_map = csound->Calloc(csound, sizeof(INSDS*)*max); csound->dag_task_dep = (char **)csound->Calloc(csound, sizeof(char*)*max); csound->dag_wlmm = (watchList *)csound->Calloc(csound, sizeof(watchList)*max); } static void recreate_dag(CSOUND *csound) { /* Allocate the main task status and watchlists */ int max = csound->dag_task_max_size; csound->dag_task_status = csound->ReAlloc(csound, (stateWithPadding *)csound->dag_task_status, sizeof(stateWithPadding)*max); csound->dag_task_watch = csound->ReAlloc(csound, (struct watchList *)csound->dag_task_watch, sizeof(watchList*)*max); csound->dag_task_map = csound->ReAlloc(csound, (INSDS *)csound->dag_task_map, sizeof(INSDS*)*max); csound->dag_task_dep = (char **)csound->ReAlloc(csound, csound->dag_task_dep, sizeof(char*)*max); csound->dag_wlmm = (watchList *)csound->ReAlloc(csound, csound->dag_wlmm, sizeof(watchList)*max); } static INSTR_SEMANTICS *dag_get_info(CSOUND* csound, int insno) { INSTR_SEMANTICS *current_instr = csp_orc_sa_instr_get_by_num(csound, insno); if (current_instr == NULL) { current_instr = csp_orc_sa_instr_get_by_name(csound, csound->engineState.instrtxtp[insno]->insname); if (UNLIKELY(current_instr == NULL)) csound->Die(csound, Str("Failed to find semantic information" " for instrument '%i'"), insno); } return current_instr; } static int dag_intersect(CSOUND *csound, struct set_t *current, struct set_t *later, int cnt) { struct set_t *ans; int res = 0; struct set_element_t *ele; csp_set_intersection(csound, current, later, &ans); res = ans->count; ele = ans->head; while (ele != NULL) { struct set_element_t *next = ele->next; csound->Free(csound, ele); ele = next; res++; } csound->Free(csound, ans); return res; } void dag_build(CSOUND *csound, INSDS *chain) { INSDS *save = chain; INSDS **task_map; int i; //printf("DAG BUILD***************************************\n"); csound->dag_num_active = 0; while (chain != NULL) { csound->dag_num_active++; chain = chain->nxtact; } if (csound->dag_num_active>csound->dag_task_max_size) { //printf("**************need to extend task vector\n"); csound->dag_task_max_size = csound->dag_num_active+INIT_SIZE; recreate_dag(csound); } if (csound->dag_task_status == NULL) create_dag(csound); /* Should move elsewhere */ else { memset((void*)csound->dag_task_watch, '\0', sizeof(watchList*)*csound->dag_task_max_size); for (i=0; idag_task_max_size; i++) { if (csound->dag_task_dep[i]) { csound->dag_task_dep[i]= NULL; } csound->dag_wlmm[i].id = INVALID; } } task_map = csound->dag_task_map; for (i=0; idag_num_active; i++) { csound->dag_task_status[i].s = AVAILABLE; csound->dag_wlmm[i].id=i; } csound->dag_changed = 0; if (UNLIKELY(csound->oparms->odebug)) printf("dag_num_active = %d\n", csound->dag_num_active); i = 0; chain = save; while (chain != NULL) { /* for each instance check against later */ int j = i+1; /* count of instance */ if (UNLIKELY(csound->oparms->odebug)) printf("\nWho depends on %d (instr %d)?\n", i, chain->insno); INSDS *next = chain->nxtact; INSTR_SEMANTICS *current_instr = dag_get_info(csound, chain->insno); //csp_set_print(csound, current_instr->read); //csp_set_print(csound, current_instr->write); while (next) { INSTR_SEMANTICS *later_instr = dag_get_info(csound, next->insno); int cnt = 0; if (UNLIKELY(csound->oparms->odebug)) printf("%d ", j); //csp_set_print(csound, later_instr->read); //csp_set_print(csound, later_instr->write); //csp_set_print(csound, later_instr->read_write); if (dag_intersect(csound, current_instr->write, later_instr->read, cnt++) || dag_intersect(csound, current_instr->read_write, later_instr->read, cnt++) || dag_intersect(csound, current_instr->read, later_instr->write, cnt++) || dag_intersect(csound, current_instr->write, later_instr->write, cnt++) || dag_intersect(csound, current_instr->read_write, later_instr->write, cnt++) || dag_intersect(csound, current_instr->read, later_instr->read_write, cnt++) || dag_intersect(csound, current_instr->write, later_instr->read_write, cnt++)) { char *tt = csound->dag_task_dep[j]; if (tt==NULL) { /* get dep vector if missing and set watch first time */ tt = csound->dag_task_dep[j] = (char*)csound->Calloc(csound, sizeof(char)*(j+1)); csound->dag_task_status[j].s = WAITING; csound->dag_wlmm[j].next = csound->dag_task_watch[i]; csound->dag_wlmm[j].id = j; csound->dag_task_watch[i] = &(csound->dag_wlmm[j]); //printf("set watch %d to %d\n", j, i); } tt[i] = 1; //printf("-yes "); } j++; next = next->nxtact; } task_map[i] = chain; i++; chain = chain->nxtact; } if (UNLIKELY(csound->oparms->odebug)) dag_print_state(csound); } void dag_reinit(CSOUND *csound) { int i; int max = csound->dag_task_max_size; volatile stateWithPadding *task_status = csound->dag_task_status; watchList * volatile *task_watch = csound->dag_task_watch; watchList *wlmm = csound->dag_wlmm; if (UNLIKELY(csound->oparms->odebug)) printf("DAG REINIT************************\n"); for (i=csound->dag_num_active; idag_num_active; i++) { int j; task_status[i].s = AVAILABLE; task_watch[i] = NULL; if (csound->dag_task_dep[i]==NULL) continue; for (j=0; jdag_task_dep[i][j]) { task_status[i].s = WAITING; wlmm[i].id = i; wlmm[i].next = task_watch[j]; task_watch[j] = &wlmm[i]; break; } } //dag_print_state(csound); } //#define ATOMIC_READ(x) __sync_fetch_and_or(&(x), 0) //#define ATOMIC_WRITE(x,v) __sync_fetch_and_and(&(x), v) #define ATOMIC_READ(x) x #define ATOMIC_WRITE(x,v) x = v; #if defined(_MSC_VER) #define ATOMIC_CAS(x,current,new) \ (current == InterlockedCompareExchange(x, new, current)) #else #define ATOMIC_CAS(x,current,new) __sync_bool_compare_and_swap(x,current,new) #endif #if defined(_MSC_VER) #define ATOMIC_CAS_PTR(x,current,new) \ (current == InterlockedCompareExchangePointer(x, new, current)) #else #define ATOMIC_CAS_PTR(x,current,new) __sync_bool_compare_and_swap(x,current,new) #endif taskID dag_get_task(CSOUND *csound, int index, int numThreads, taskID next_task) { int i; int count_waiting = 0; int active = csound->dag_num_active; int start = (index * active) / numThreads; volatile stateWithPadding *task_status = csound->dag_task_status; enum state current_task_status; if (next_task != INVALID) { // Have forwarded one task from the previous one // assert(ATOMIC_READ(task_status[next_task].s) == WAITING); ATOMIC_WRITE(task_status[next_task].s,INPROGRESS); return next_task; } //printf("**GetTask from %d\n", csound->dag_num_active); i = start; do { current_task_status = ATOMIC_READ(task_status[i].s); switch (current_task_status) { case AVAILABLE : // Need to CAS as the value may have changed if (ATOMIC_CAS(&(task_status[i].s), AVAILABLE, INPROGRESS)) { return (taskID)i; } break; case WAITING : // printf("**%d waiting\n", i); ++count_waiting; break; case INPROGRESS : // print(f"**%d active\n", i); break; case DONE : //printf("**%d done\n", i); break; default : // Enum corrupted! //assert(0); break; } // Increment modulo active i = (i+1 == active) ? 0 : i + 1; } while (i != start); //dag_print_state(csound); if (count_waiting == 0) return (taskID)INVALID; //printf("taskstodo=%d)\n", morework); return (taskID)WAIT; } /* This static is OK as not written */ static const watchList DoNotRead = { INVALID, NULL}; inline static int moveWatch(CSOUND *csound, watchList * volatile *w, watchList *t) { watchList *local=*w; t->next = NULL; //printf("moveWatch\n"); do { //dag_print_state(csound); local = ATOMIC_READ(*w); if (local==&DoNotRead) { //printf("local is DoNotRead\n"); return 0;//was no & earlier } else t->next = local; } while (!ATOMIC_CAS_PTR(w,local,t)); //dag_print_state(csound); //printf("moveWatch done\n"); return 1; } taskID dag_end_task(CSOUND *csound, taskID i) { watchList *to_notify, *next; int canQueue; int j, k; watchList * volatile *task_watch = csound->dag_task_watch; enum state current_task_status; int wait_on_current_tasks; taskID next_task = INVALID; ATOMIC_WRITE(csound->dag_task_status[i].s, DONE); /* as DONE is zero */ // A write barrier /might/ be useful here to avoid the case // of the list being DoNotRead but the status being something // other than done. At the time of writing this wouldn't give // a correctness issue, plus the semantics of GCC's CAS apparently // imply a write barrier, so it should be OK. { /* ATOMIC_SWAP */ do { to_notify = ATOMIC_READ(task_watch[i]); } while (!ATOMIC_CAS_PTR(&task_watch[i],to_notify,(watchList *) &DoNotRead)); } //to_notify = ATOMIC_SWAP(task_watch[i], &DoNotRead); //printf("Ending task %d\n", i); next = to_notify; while (to_notify) { /* walk the list of watchers */ next = to_notify->next; j = to_notify->id; //printf("%d notifying task %d it finished\n", i, j); canQueue = 1; wait_on_current_tasks = 0; for (k=0; kdag_task_dep[j][k]==0) continue; current_task_status = ATOMIC_READ(csound->dag_task_status[k].s); //printf("investigating task %d (%d)\n", k, current_task_status); if (current_task_status == WAITING) { // Prefer watching blocked tasks //printf("found task %d to watch %d status %d\n", // k, j, csound->dag_task_status[k].s); if (moveWatch(csound, &task_watch[k], to_notify)) { //printf("task %d now watches %d\n", j, k); canQueue = 0; wait_on_current_tasks = 0; break; } else { /* assert csound->dag_task_status[j].s == DONE and we are in race */ //printf("Racing status %d %d %d %d\n", // csound->dag_task_status[j].s, i, j, k); } } else if (current_task_status == AVAILABLE || current_task_status == INPROGRESS) { wait_on_current_tasks = 1; } //else { printf("not %d\n", k); } } // Try the same thing again but this time waiting on active or available task if (wait_on_current_tasks == 1) { for (k=0; kdag_task_dep[j][k]==0) continue; current_task_status = ATOMIC_READ(csound->dag_task_status[k].s); //printf("investigating task %d (%d)\n", k, current_task_status); if (current_task_status != DONE) { // Prefer watching blocked tasks //printf("found task %d to watch %d status %d\n", // k, j, csound->dag_task_status[k].s); if (moveWatch(csound, &task_watch[k], to_notify)) { //printf("task %d now watches %d\n", j, k); canQueue = 0; break; } else { /* assert csound->dag_task_status[j].s == DONE and we are in race */ //printf("Racing status %d %d %d %d\n", // csound->dag_task_status[j].s, i, j, k); } } //else { printf("not %d\n", k); } } } if (canQueue) { /* could use monitor here */ if (next_task == INVALID) { next_task = j; // Forward directly to the thread to save re-dispatch } else { ATOMIC_WRITE(csound->dag_task_status[j].s, AVAILABLE); } } to_notify = next; } //dag_print_state(csound); return next_task; } /* INV : Acyclic */ /* INV : Each entry is read by a single thread, * no writes (but see OPT : Watch ordering) */ /* Thus no protection needed */ /* INV : Watches for different tasks are disjoint */ /* INV : Multiple threads can add to a watch list but only one will remove * These are the only interactions */ /* Thus the use of CAS / atomic operations */ /* Used to mark lists that should not be added to, see NOTE : Race condition */ #if 0 watchList nullList; watchList *doNotAdd = &nullList; watchList endwatch = { NULL, NULL }; /* Lists of tasks that depend on the given task */ watchList ** watch; /* OPT : Structure lay out */ watchListMemoryManagement *wlmm; /* OPT : Structure lay out */ /* INV : wlmm[X].s.id == X; */ /* OPT : Data structure redundancy */ /* INV : status[X] == WAITING => wlmm[X].used */ /* INV : wlmm[X].s is in watch[Y] => wlmm[X].used */ /* Watch list helper functions */ void initialiseWatch (watchList **w, taskID id) { wlmm[id].used = TRUE; wlmm[id].s.id = id; wlmm[id].s.tail = *w; *w = &(wlmm[id].s); } inline watchList * getWatches(taskID id) { return __sync_lock_test_and_set (&(watch[id]), doNotAdd); } int moveWatch (watchList **w, watchList *t) { watchList *local; t->tail = NULL; do { local = atomicRead(*w); if (local == doNotAdd) { return 0; } else { t->tail = local; } } while (!atomicCAS(*w,local,t)); /* OPT : Delay loop */ return 1; } void appendToWL (taskID id, watchList *l) { watchList *w; do { w = watch[id]; l->tail = w; w = __sync_val_compare_and_swap(&(watch[id]),w,l); } while (!(w == l)); } inline void deleteWatch (watchList *t) { wlmm[t->id].used = FALSE; } typedef struct monitor { pthread_mutex_t l = PTHREAD_MUTEX_INITIALIZER; unsigned int threadsWaiting = 0; /* Shadows the length of workAvailable wait queue */ queue q; /* OPT : Dispatch order */ pthread_cond_t workAvailable = PTHREAD_COND_INITIALIZER; pthread_cond_t done = PTHREAD_COND_INITIALIZER; } monitor; /* OPT : Lock-free */ /* INV : q.size() + dispatched <= ID */ /* INV : foreach(id,q.contents()) { status[id] = AVAILABLE; } */ /* INV : threadsWaiting <= THREADS */ monitor dispatch; void addWork(monitor *dispatch, taskID id) { pthread_mutex_lock(&dispatch->l); status[id] = AVAILABLE; dispatch->q.push(id); if (threadsWaiting >= 1) { pthread_cond_signal(&dispatch->c); } pthread_mutex_unlock(&dispatch->l); return; } taskID getWork(monitor *dispatch) { taskID returnValue; pthread_mutex_lock(&dispatch->l); while (q.empty()) { ++dispatch->threadsWaiting; if (dispatch->threadsWaiting == THREADS) { /* Will the last person out please turn off the lights! */ pthread_cond_signal(&dispatch->done); } pthread_cond_wait(&dispatch->l,&dispatch->workAvailable); --dispatch->threadsWaiting; /* NOTE : A while loop is needed as waking from this requires * reacquiring the mutex and in the mean time someone * might have got it first and removed the work. */ } returnValue = q.pop(); pthread_mutex_unlock(&dispatch->l); return returnValue; } void waitForWorkToBeCompleted (monitor *dispatch) { /* Requires * INV : threadsWaiting == THREADS <=> \forall id \in ID . status[id] == DONE */ pthread_mutex_lock(&dispatch->l); if (dispatch->threadsWaiting < THREADS) { pthread_cond_wait(&dispatch->l,&dispatch->done); } /* This assertion is more difficult to prove than it might first appear */ assert(dispatch->threadsWaiting == THREADS); pthread_mutex_unlock(&dispatch->l); return; } void mainThread (State *s) { /* Set up the DAG */ if (s->firstRun || s->updateNeeded) { dep = buildDAG(s); /* OPT : Dispatch order */ /* Other : Update anything that is indexed by task * (i.e. all arrays given length ID) */ } /* Reset the data structure */ foreach (id in ID) { watch[id] = NULL; } /* Initialise the dispatch queue */ foreach (id in ID) { /* OPT : Dispatch order */ if (dep[id] == EMPTYSET) { atomicWrite(status[id] = AVAILABLE); addWork(*dispatch,id); } else { atomicWrite(status[id] = WAITING); initialiseWatch(&watch[choose(dep[id])], id); /* OPT : Watch ordering */ } } /* INV : Data structure access invariants start here */ /* INV : Status only decrease from now */ /* INV : Watch list for id contains a subset of the things that depend on id */ /* INV : Each id appears in at most one watch list */ /* INV : doNotAdd only appears at the head of a watch list */ /* INV : if (watch[id] == doNotAdd) then { status[id] == DONE; } */ waitForWorkToBeCompleted(*dispatch); return; } void workerThread (State *s) { taskID work; watchList *tasksToNotify, next; bool canQueue; do { task = getWork(dispatch); /* Do stuff */ atomicWrite(status[work] = INPROGRESS); doStuff(work); atomicWrite(status[work] = DONE); /* NOTE : Race condition */ tasksToNotify = getWatches(work); while (tasksToNotify != NULL) { next = tasksToNotify->tail; canQueue = TRUE; foreach (dep in dep[tasksToNotify->id]) { /* OPT : Watch ordering */ if (atomicRead(status[dep]) != DONE) { /* NOTE : Race condition */ if (moveWatch(watch[dep],tasksToNotify)) { canQueue = FALSE; break; } else { /* Have hit the race condition, try the next option */ assert(atomicRead(status[dep]) == DONE); } } } if (canQueue) { /* OPT : Save one work item */ addWork(*dispatch,tasksToNotify->id); deleteWatch(tasksToNotify); } tasksToNotify = next; } } while (1); /* NOTE : some kind of control for thread exit needed */ return; } /* OPT : Structure lay out * * All data structures that are 1. modified by one or more thread and * 2. accessed by multiple threads, should be aligned to cache lines and * padded so that there is only one instance per cache line. This will reduce * false memory contention between objects that just happen to share a cache * line. Blocking to 64 bytes will probably be sufficient and if people really * care about performance that much they can tune to their particular * architecture. */ /* OPT : Watch ordering * * Moving a watch is relatively cheap (in the uncontended case) but * it would be best to avoid moving watches where possible. The ideal * situation would be for every task to watch the last pre-requisite. * There are two places in the code that affect the watch ordering; * the initial assignment and the movement when a watch is triggered. * Prefering WAITING tasks (in the later) and lower priority tasks * (if combined with the dispatch order optimisation below) are probably * good choices. One mechanism would be to reorder the set (or array) of * dependencies to store this information. When looking for a (new) watch, * tasks are sorted with increasing status first and then the first one picked. * Keeping the list sorted (or at least split between WAITING and others) with * each update should (if the dispatch order is fixed / slowly adapting) result * in the best things to watch moving to the front and thus adaptively give * the best possible tasks to watch. The interaction with a disaptch order * heuristic would need to be considered. Note that only one thread will * look at any given element of dep[] so they can be re-ordered without * needing locking. */ /* OPT : Structure lay out * * Some of the fields are not strictly needed and are just there to make * the algorithm cleaner and more intelligible. The id fields of the watch * lists are not really needed as there is one per task and their position * within the watchListMemoryManager array allows the task to be infered. * Likewise the used flag in the memory manager is primarily for book-keeping * and checking / assertions and could be omitted. */ /* OPT : Delay loop * * In theory it is probably polite to put a slowly increasing delay in * after a failed compare and swap to reduce pressure on the memory * subsystem in the highly contended case. As multiple threads adding * to a task's watch list simultaneously is probably a rare event, the * delay loop is probably unnecessary. */ /* OPT : Dispatch order * * The order in which tasks are dispatched affects the amount of * parallelisation possible. Picking the exact scheduling order, even * if the duration of the tasks is known is probably NP-Hard (see * bin-packing*) so heuristics are probably the way to go. The proporition * of tasks which depend on a given task is probably a reasonable primary * score, with tie-breaks going to longer tasks. This can either be * applied to just the initial tasks (either in ordering the nodes in the DAG) * or in the order in which they are traversed. Alternatively by * sorting the queue / using a heap / other priority queuing structure * it might be possible to do this dynamically. The best solution would * probably be adaptive with a task having its priority incremented * each time another worker thread blocks on a shortage of work, with these * increments also propagated 'upwards' in the DAG. * * *. Which means that a solver could be used to give the best possible * schedule / the maximum parallelisation. This could be useful for * optimisation. */ /* OPT : Lock-free * * A lock free dispatch mechanism is probably possible as threads can * scan the status array for things listed as AVAILABLE and then atomicCAS * to INPROGRESS to claim them. But this starts to involve busy-waits or * direct access to futexes and is probably not worth it. */ /* OPT : Save one work item * * Rather than adding all watching tasks who have their dependencies met to * the dispatch queue, saving one (perhaps the best, see OPT : Dispatch order) * means the thread does not have to wait. In the case of a purely linear DAG * this should be roughly as fast as the single threaded version. */ /* NOTE : Race condition * * There is a subtle race condition: * * Thread 1 Thread 2 * -------- -------- * atomicRead(status[dep]) != DONE * atomicWrite(status[work] = DONE); * tasksToNotify = getWatches(work); * moveWatch(watch[dep],tasksToNotify); * * The key cause is that the status and the watch list cannot be updated * simultaneously. However as getWatches removes all watches and moves or * removes them, it is sufficient to have a doNotAdd watchList node to detect * this race condition and resolve it by having moveWatch() fail. */ void newdag_alloc(CSOUND *csound, int numtasks) { doNotAdd = &endwatch; ?? watch = (watchList **)csound->Calloc(csound, sizeof(watchList *)*numtasks); wlmm = (watchListMemoryManagement *) csound->Calloc(csound, sizeof(watchListMemoryManagement)*numtasks); } #endif csound-6.10.0/Engine/cs_par_base.c000066400000000000000000000404751321653344700167250ustar00rootroot00000000000000/* cs_par_base.c: Copyright (C) 2009: Chris Wilson and John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include "csoundCore.h" #include "cs_par_base.h" int csp_thread_index_get(CSOUND *csound) { void *threadId = csound->GetCurrentThreadID(); int index = 0; THREADINFO *current = csound->multiThreadedThreadInfo; if (UNLIKELY(current == NULL)) { return -1; } while (current != NULL) { // PTHREAD: this should be a class in threads.c to abstract this away #if defined(HAVE_PTHREAD) && !defined(WIN32) if (pthread_equal(*(pthread_t *)threadId, *(pthread_t *)current->threadId)) { #else // FIXME not entirely sure what this should be... //if ((DWORD)csoundGetCurrentThreadId () == (DWORD)threadId) /*if ((DWORD)current->threadId == (DWORD)threadId) {*/ if (current->threadId == threadId) { #endif free(threadId); return index; } index++; current = current->next; } return -1; } /* **** An implementation of Barriers for MAC that lacks them **** */ #if defined(__MACH__) || defined(ANDROID) || defined(NACL) /*#define BARRIER_SERIAL_THREAD (-1) typedef struct { pthread_mutex_t mut; pthread_cond_t cond; unsigned int count, max, iteration; } barrier_t; */ extern int barrier_init(barrier_t *b, void *,unsigned int max); extern int barrier_destroy(barrier_t *b); extern int barrier_wait(barrier_t *b); #ifndef PTHREAD_BARRIER_SERIAL_THREAD /*#define pthread_barrier_t barrier_t */ #define PTHREAD_BARRIER_SERIAL_THREAD BARRIER_SERIAL_THREAD #define pthread_barrier_init(barrier, attr, count) \ barrier_init(barrier,NULL,count) #define pthread_barrier_destroy barrier_destroy #define pthread_barrier_wait barrier_wait #endif int barrier_init(barrier_t *b, void *dump, unsigned int max) { if (UNLIKELY(max == 0)) return EINVAL; if (UNLIKELY(pthread_mutex_init(&b->mut, NULL))) { return -1; } if (UNLIKELY(pthread_cond_init(&b->cond, NULL))) { int err = errno; pthread_mutex_destroy(&b->mut); errno = err; return -1; } b->count = 0; b->iteration = 0; b->max = max; return 0; } int barrier_destroy(barrier_t *b) { if (UNLIKELY(b->count > 0)) return EBUSY; pthread_cond_destroy(&b->cond); pthread_mutex_destroy(&b->mut); return 0; } /* when barrier is passed, all threads except one return 0 */ int barrier_wait(barrier_t *b) { int ret; unsigned int it; pthread_mutex_lock(&b->mut); b->count++; it = b->iteration; if (b->count >= b->max) { b->count = 0; b->iteration++; pthread_cond_broadcast(&b->cond); ret = BARRIER_SERIAL_THREAD; } else { while (it == b->iteration) pthread_cond_wait(&b->cond, &b->mut); ret = 0; } pthread_mutex_unlock(&b->mut); return ret; } #endif /*********************************************************************** * parallel primitives */ void csp_barrier_alloc(CSOUND *csound, void **barrier, int thread_count) { if (UNLIKELY(barrier == NULL)) csound->Die(csound, Str("Invalid NULL Parameter barrier")); if (UNLIKELY(thread_count < 1)) csound->Die(csound, Str("Invalid Parameter thread_count must be > 0")); *barrier = csound->CreateBarrier(thread_count); if (UNLIKELY(*barrier == NULL)) { csound->Die(csound, Str("Failed to allocate barrier")); } } void csp_barrier_dealloc(CSOUND *csound, void **barrier) { if (UNLIKELY(barrier == NULL || *barrier == NULL)) csound->Die(csound, Str("Invalid NULL Parameter barrier")); csound->DestroyBarrier(*barrier); } /*********************************************************************** * set data structure */ /* static prototypes */ static int set_element_delloc(CSOUND *csound, struct set_element_t **set_element); static int set_element_alloc(CSOUND *csound, struct set_element_t **set_element, char *data); static int set_is_set(CSOUND *csound, struct set_t *set); #if 0 static int set_element_is_set_element(CSOUND *csound, struct set_element_t *set_element); #endif int csp_set_alloc(CSOUND *csound, struct set_t **set, set_element_data_eq *ele_eq_func, set_element_data_print *ele_print_func) { struct set_t *p; if (UNLIKELY(set == NULL)) csound->Die(csound, Str("Invalid NULL Parameter set")); *set = p = csound->Malloc(csound, sizeof(struct set_t)); if (UNLIKELY(p == NULL)) { csound->Die(csound, Str("Failed to allocate set")); } memset(p, 0, sizeof(struct set_t)); strncpy(p->hdr, SET_HDR, HDR_LEN); p->ele_eq_func = ele_eq_func; p->ele_print_func = ele_print_func; p->cache = NULL; //printf("csp_set_alloc: %p\n", p); return CSOUND_SUCCESS; } int csp_set_dealloc(CSOUND *csound, struct set_t **set) { struct set_element_t *ele; struct set_t *p = *set; if (UNLIKELY(set == NULL || *set == NULL)) csound->Die(csound, Str("Invalid NULL Parameter set")); if (UNLIKELY(!set_is_set(csound, *set))) csound->Die(csound, Str("Invalid Parameter set not a set")); if (p->cache != NULL) csound->Free(csound, p->cache); ele = p->head; while (ele != NULL) { struct set_element_t *next = ele->next; set_element_delloc(csound, &ele); ele = next; } //printf("csp_set_dealloc: %p\n", p); csound->Free(csound, p); *set = NULL; return CSOUND_SUCCESS; } static int set_element_alloc(CSOUND *csound, struct set_element_t **set_element, char *data) { if (UNLIKELY(set_element == NULL || data == NULL)) csound->Die(csound, Str("Invalid NULL Parameter data")); *set_element = csound->Malloc(csound, sizeof(struct set_element_t)); if (UNLIKELY(*set_element == NULL)) { csound->Die(csound, Str("Failed to allocate set element")); } memset(*set_element, 0, sizeof(struct set_element_t)); strncpy((*set_element)->hdr, SET_ELEMENT_HDR, HDR_LEN); (*set_element)->data = cs_strdup(csound, data); return CSOUND_SUCCESS; } static int set_element_delloc(CSOUND *csound, struct set_element_t **set_element) { if (UNLIKELY(set_element == NULL || *set_element == NULL)) csound->Die(csound, Str("Invalid NULL Parameter set_element")); csound->Free(csound, *set_element); *set_element = NULL; return CSOUND_SUCCESS; } static int set_is_set(CSOUND *csound, struct set_t *set) { char buf[4]; if (set == NULL) return 0; strncpy(buf, (char *)set, HDR_LEN); buf[3] = 0; return strcmp(buf, SET_HDR) == 0; } #if 0 static int set_element_is_set_element(CSOUND *csound, struct set_element_t *set_element) { char buf[4]; if (set_element == NULL) return 0; strncpy(buf, (char *)set_element, HDR_LEN); buf[3] = 0; return strcmp(buf, SET_ELEMENT_HDR) == 0; } #endif int csp_set_alloc_string(CSOUND *csound, struct set_t **set) { return csp_set_alloc(csound, set, csp_set_element_string_eq, csp_set_element_string_print); } int csp_set_element_string_eq(struct set_element_t *ele1, struct set_element_t *ele2) { return strcmp((char *)ele1->data, (char *)ele2->data) == 0; } #if 0 int csp_set_element_ptr_eq(struct set_element_t *ele1, struct set_element_t *ele2) { return (ele1->data == ele2->data); } #endif void csp_set_element_string_print(CSOUND *csound, struct set_element_t *ele) { csound->Message(csound, "%s", (char *)ele->data); } void csp_set_element_ptr_print(CSOUND *csound, struct set_element_t *ele) { csound->Message(csound, "%p", ele->data); } static int set_update_cache(CSOUND *csound, struct set_t *set) { if (set->cache != NULL) { csound->Free(csound, set->cache); set->cache = NULL; } if (set->count > 0) { struct set_element_t *ele; int ctr = 0; set->cache = csound->Malloc(csound, sizeof(struct set_element_t *) * set->count); ele = set->head; while (ele != NULL) { set->cache[ctr] = ele; ctr++; ele = ele->next; } } return CSOUND_SUCCESS; } /* * if out_set_element is not NULL and the element corresponding to * data is not found it will not be changed */ static int set_element_get(CSOUND *csound, struct set_t *set, char *data, struct set_element_t **out_set_element) { #ifdef SET_DEBUG if (UNLIKELY(set == NULL)) csound->Die(csound, Str("Invalid NULL Parameter set")); if (UNLIKELY(data == NULL)) csound->Die(csound, Str("Invalid NULL Parameter data")); if (UNLIKELY(out_set_element == NULL)) csound->Die(csound, Str("Invalid NULL Parameter out_set_element")); #endif { struct set_element_t *ele = set->head; struct set_element_t data_ele = { SET_ELEMENT_HDR, data, 0 }; while (ele != NULL) { if (set->ele_eq_func(ele, &data_ele)) { *out_set_element = ele; break; } ele = ele->next; } } return CSOUND_SUCCESS; } int csp_set_add(CSOUND *csound, struct set_t *set, void *data) { struct set_element_t *ele = NULL; #ifdef SET_DEBUG if (UNLIKELY(set == NULL)) csound->Die(csound, "Invalid NULL Parameter set"); if (UNLIKELY(data == NULL)) csound->Die(csound, "Invalid NULL Parameter data"); #endif if (csp_set_exists(csound, set, data)) { return CSOUND_SUCCESS; } set_element_alloc(csound, &ele, data); if (set->head == NULL) { set->head = ele; set->tail = ele; } else { set->tail->next = ele; set->tail = ele; } set->count++; set_update_cache(csound, set); return CSOUND_SUCCESS; } int csp_set_remove(CSOUND *csound, struct set_t *set, void *data) { #ifdef SET_DEBUG if (UNLIKELY(set == NULL)) csound->Die(csound, "Invalid NULL Parameter set"); if (UNLIKELY(data == NULL)) csound->Die(csound, "Invalid NULL Parameter data"); #endif { struct set_element_t *ele = set->head, *prev = NULL; struct set_element_t data_ele = { SET_ELEMENT_HDR, data, 0 }; while (ele != NULL) { if (set->ele_eq_func(ele, &data_ele)) { if (ele == set->head && ele == set->tail) { set->head = NULL; set->tail = NULL; } else if (ele == set->head) { set->head = ele->next; } else { prev->next = ele->next; } set_element_delloc(csound, &ele); set->count--; break; } prev = ele; ele = ele->next; } } set_update_cache(csound, set); return CSOUND_SUCCESS; } int csp_set_exists(CSOUND *csound, struct set_t *set, void *data) { struct set_element_t *ele = NULL; #ifdef SET_DEBUG if (UNLIKELY(set == NULL)) csound->Die(csound, "Invalid NULL Parameter set"); if (UNLIKELY(data == NULL)) csound->Die(csound, "Invalid NULL Parameter data"); #endif set_element_get(csound, set, data, &ele); return (ele == NULL ? 0 : 1); } int csp_set_print(CSOUND *csound, struct set_t *set) { struct set_element_t *ele; #ifdef SET_DEBUG if (UNLIKELY(set == NULL)) csound->Die(csound, "Invalid NULL Parameter set"); if (UNLIKELY(!set_is_set(csound, set))) csound->Die(csound, "Invalid Parameter set not a set"); #endif ele = set->head; csound->Message(csound, "{ "); while (ele != NULL) { set->ele_print_func(csound, ele); if (ele->next != NULL) csound->Message(csound, ", "); ele = ele->next; } csound->Message(csound, " }\n"); return CSOUND_SUCCESS; } inline int csp_set_count(struct set_t *set) { #ifdef SET_DEBUG if (UNLIKELY(set == NULL)) csound->Die(csound, "Invalid NULL Parameter set"); if (UNLIKELY(!set_is_set(csound, set))) csound->Die(csound, "Invalid Parameter set not a set"); #endif return set->count; } /* 0 indexed */ // FIXME inlining breaks linkage for MSVC /*inline*/ int csp_set_get_num(struct set_t *set, int num, void **data) { #ifdef SET_DEBUG if (UNLIKELY(set == NULL)) csound->Die(csound, "Invalid NULL Parameter set"); if (UNLIKELY(!set_is_set(csound, set))) csound->Die(csound, "Invalid Parameter set not a set"); if (UNLIKELY(um >= set->count)) csound->Die(csound, "Invalid Parameter num is out of bounds"); if (UNLIKELY(data == NULL)) csound->Die(csound, "Invalid NULL Parameter data"); #endif *data = set->cache[num]->data; /* if (set->cache != NULL) { } else { int ctr = 0; struct set_element_t *ele = set->head; while (ctr < num && ele != NULL) { ctr++; ele = ele->next; } if (ctr == num && ele != NULL) { *data = ele->data; } } */ return CSOUND_SUCCESS; } int csp_set_union(CSOUND *csound, struct set_t *first, struct set_t *second, struct set_t **result) { int ctr = 0; int first_len; int second_len; #ifdef SET_DEBUG if (UNLIKELY(first == NULL)) csound->Die(csound, "Invalid NULL Parameter first"); if (UNLIKELY(!set_is_set(csound, first))) csound->Die(csound, "Invalid Parameter set not a first"); if (UNLIKELY(second == NULL)) csound->Die(csound, "Invalid NULL Parameter second"); if (UNLIKELY(!set_is_set(csound, second))) csound->Die(csound, "Invalid Parameter set not a second"); if (UNLIKELY(result == NULL)) csound->Die(csound, "Invalid NULL Parameter result"); if (UNLIKELY(first->ele_eq_func != second->ele_eq_func)) csound->Die(csound, "Invalid sets for comparison (different equality)"); #endif csp_set_alloc(csound, result, first->ele_eq_func, first->ele_print_func); first_len = csp_set_count(first); second_len = csp_set_count(second); while (ctr < first_len) { void *data = NULL; csp_set_get_num(first, ctr, &data); csp_set_add(csound, *result, data); ctr++; } ctr = 0; while (ctr < second_len) { void *data = NULL; csp_set_get_num(second, ctr, &data); csp_set_add(csound, *result, data); ctr++; } return CSOUND_SUCCESS; } int csp_set_intersection(CSOUND *csound, struct set_t *first, struct set_t *second, struct set_t **result) { int ctr = 0; int first_len; #ifdef SET_DEBUG if (UNLIKELY(first == NULL)) csound->Die(csound, "Invalid NULL Parameter first"); if (UNLIKELY(!set_is_set(csound, first))) csound->Die(csound, "Invalid Parameter set not a first"); if (UNLIKELY(second == NULL)) csound->Die(csound, "Invalid NULL Parameter second"); if (UNLIKELY(!set_is_set(csound, second))) csound->Die(csound, "Invalid Parameter set not a second"); if (UNLIKELY(result == NULL)) csound->Die(csound, "Invalid NULL Parameter result"); if (UNLIKELY(first->ele_eq_func != second->ele_eq_func)) csound->Die(csound, "Invalid sets for comparison (different equality)"); #endif csp_set_alloc(csound, result, first->ele_eq_func, first->ele_print_func); first_len = csp_set_count(first); while (ctr < first_len) { void *data = NULL; csp_set_get_num(first, ctr, &data); if (csp_set_exists(csound, second, data)) { csp_set_add(csound, *result, data); } ctr++; } return CSOUND_SUCCESS; } csound-6.10.0/Engine/cs_par_dispatch.c000066400000000000000000000226131321653344700176040ustar00rootroot00000000000000/* cs_par_dispatch.c: Copyright (C) 2009: Chris Wilson and John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include "csoundCore.h" #include "csound_orc.h" #include "cs_par_base.h" #include "cs_par_orc_semantics.h" //#include "cs_par_dispatch.h" #include "cs_par_ops.h" #include "cs_par_structs.h" /*********************************************************************** * external prototypes not in headers */ extern ORCTOKEN *lookup_token(CSOUND *csound, char *); extern void print_tree(CSOUND *, char *, TREE *); /*********************************************************************** * Global Var Lock Inserts */ /* global variables lock support */ struct global_var_lock_t { char hdr[HDR_LEN]; char *name; int index; LOCK_TYPE lock; struct global_var_lock_t *next; }; static inline void csp_locks_lock(CSOUND * csound, int global_index) { if (UNLIKELY(global_index >= csound->global_var_lock_count)) { csound->Die(csound, Str("Poorly specified global lock index: %i [max: %i]\n"), global_index, csound->global_var_lock_count); } /* TRACE_2("Locking: %i [%p %s]\n", global_index, */ /* csound->global_var_lock_cache[global_index], */ /* csound->global_var_lock_cache[global_index]->name); */ TAKE_LOCK(&(csound->global_var_lock_cache[global_index]->lock)); } static inline void csp_locks_unlock(CSOUND * csound, int global_index) { if (UNLIKELY(global_index >= csound->global_var_lock_count)) { csound->Die(csound, Str("Poorly specified global lock index: %i [max: %i]\n"), global_index, csound->global_var_lock_count); } RELS_LOCK(&(csound->global_var_lock_cache[global_index]->lock)); /* TRACE_2("UnLocking: %i [%p %s]\n", */ /* global_index, csound->global_var_lock_cache[global_index], */ /* csound->global_var_lock_cache[global_index]->name); */ } #if 0 static struct global_var_lock_t *global_var_lock_alloc(CSOUND *csound, char *name, int index) { if (UNLIKELY(name == NULL)) csound->Die(csound, Str("Invalid NULL parameter name for a global variable\n")); struct global_var_lock_t *ret = csound->Malloc(csound, sizeof(struct global_var_lock_t)); memset(ret, 0, sizeof(struct global_var_lock_t)); INIT_LOCK(ret->lock); strncpy(ret->hdr, GLOBAL_VAR_LOCK_HDR, HDR_LEN); ret->name = name; ret->index = index; csound->global_var_lock_count++; return ret; } static struct global_var_lock_t *global_var_lock_find(CSOUND *csound, char *name) { if (UNLIKELY(name == NULL)) csound->Die(csound, Str("Invalid NULL parameter name for a global variable\n")); if (csound->global_var_lock_root == NULL) { csound->global_var_lock_root = global_var_lock_alloc(csound, name, 0); return csound->global_var_lock_root; } else { struct global_var_lock_t *current = csound->global_var_lock_root, *previous = NULL; int ctr = 0; while (current != NULL) { if (strcmp(current->name, name) == 0) { break; } previous = current; current = current->next; ctr++; } if (current == NULL) { previous->next = global_var_lock_alloc(csound, name, ctr); return previous->next; } else { return current; } } } static TREE *csp_locks_insert(CSOUND *csound, TREE *root) { csound->Message(csound, Str("Inserting Parallelism Constructs into AST\n")); TREE *anchor = NULL; TREE *current = root; TREE *previous = NULL; INSTR_SEMANTICS *instr = NULL; while (current != NULL) { switch(current->type) { case INSTR_TOKEN: if (current->left->type == T_INSTLIST) { instr = csp_orc_sa_instr_get_by_name(csound, current->left->left->value->lexeme); } else { instr = csp_orc_sa_instr_get_by_name(csound, current->left->value->lexeme); } if (instr->read_write->count > 0 && instr->read->count == 0 && instr->write->count == 0) { csound->Message(csound, Str("Instr %d needs locks"), instr->insno); //print_tree(csound, "before locks", root); current->right = csp_locks_insert(csound, current->right); //print_tree(csound, "after locks", root); } break; case UDO_TOKEN: case IF_TOKEN: break; case '=': { struct set_t *left = csp_orc_sa_globals_find(csound, current->left); struct set_t *right = csp_orc_sa_globals_find(csound, current->right); struct set_t *new = NULL; csp_set_union(csound, left, right, &new); /* add locks if this is a read-write global variable * that is same global read and written in this operation */ if (left->count == 1 && right->count == 1 && new->count == 1) { char *global_var = NULL; struct global_var_lock_t *gvar; char buf[8]; ORCTOKEN *lock_tok, *unlock_tok, *var_tok, *var0_tok;; TREE *lock_leaf, *unlock_leaf; csp_set_get_num(new, 0, (void **)&global_var); gvar = global_var_lock_find(csound, global_var); lock_tok = lookup_token(csound, "##globallock"); unlock_tok = lookup_token(csound, "##globalunlock"); snprintf(buf, 8, "%i", gvar->index); var_tok = make_int(csound, buf); var0_tok = make_int(csound, buf); lock_leaf = make_leaf(csound, current->line, current->locn, T_OPCODE, lock_tok); lock_leaf->right = make_leaf(csound, current->line, current->locn, INTEGER_TOKEN, var_tok); unlock_leaf = make_leaf(csound, current->line, current->locn, T_OPCODE, unlock_tok); unlock_leaf->right = make_leaf(csound, current->line, current->locn, INTEGER_TOKEN, var0_tok); if (previous == NULL) { //TREE *old_current = lock_leaf; lock_leaf->next = current; unlock_leaf->next = current->next; current->next = unlock_leaf; current = unlock_leaf; //print_tree(csound, "changed to\n", lock_leaf); } else { previous->next = lock_leaf; lock_leaf->next = current; unlock_leaf->next = current->next; current->next = unlock_leaf; current = unlock_leaf; //print_tree(csound, "changed-1 to\n", lock_leaf); } } csp_set_dealloc(csound, &new); csp_set_dealloc(csound, &left); csp_set_dealloc(csound, &right); } default: break; } if (anchor == NULL) { anchor = current; } previous = current; current = current->next; } csound->Message(csound, Str("[End Inserting Parallelism Constructs into AST]\n")); return anchor; } #endif void csp_locks_cache_build(CSOUND *csound) { int ctr = 0; struct global_var_lock_t *glob; if (UNLIKELY(csound->global_var_lock_count < 1)) { return; } csound->global_var_lock_cache = csound->Malloc(csound, sizeof(struct global_var_lock_t *) * csound->global_var_lock_count); glob = csound->global_var_lock_root; while (glob != NULL && ctr < csound->global_var_lock_count) { csound->global_var_lock_cache[ctr] = glob; glob = glob->next; ctr++; } /* csound->Message(csound, "Global Locks Cache\n"); ctr = 0; while (ctr < csound->global_var_lock_count) { csound->Message(csound, "[%i] %s\n", csound->global_var_lock_cache[ctr]->index, csound->global_var_lock_cache[ctr]->name); ctr++; } */ } /* The opcodes that implement local global locks */ int globallock(CSOUND *csound, GLOBAL_LOCK_UNLOCK *p) { /* csound->Message(csound, "Locking: %i\n", (int)*p->gvar_ix); */ csp_locks_lock(csound, (int)*p->gvar_ix); return OK; } int globalunlock(CSOUND *csound, GLOBAL_LOCK_UNLOCK *p) { /* csound->Message(csound, "UnLocking: %i\n", (int)*p->gvar_ix); */ csp_locks_unlock(csound, (int)*p->gvar_ix); return OK; } csound-6.10.0/Engine/cs_par_orc_semantic_analysis.c000066400000000000000000000335671321653344700223700ustar00rootroot00000000000000/* cs_par_orc_semantic_analysis.c: Copyright (C) 2009: Chris Wilson and John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include "csoundCore.h" #include "csound_orc.h" #include "tok.h" #include "cs_par_base.h" #include "cs_par_orc_semantics.h" #include "interlocks.h" OENTRY* find_opcode(CSOUND *, char *); /*********************************************************************** * static function prototypes */ /* static int csp_thread_index_get(CSOUND *csound); */ static INSTR_SEMANTICS *instr_semantics_alloc(CSOUND *csound, char *name); /*********************************************************************** * helper functions */ static INSTR_SEMANTICS *instr_semantics_alloc(CSOUND *csound, char *name) { INSTR_SEMANTICS *instr = csound->Malloc(csound, sizeof(INSTR_SEMANTICS)); memset(instr, 0, sizeof(INSTR_SEMANTICS)); strncpy(instr->hdr, INSTR_SEMANTICS_HDR, HDR_LEN); instr->name = name; instr->insno = -1; /* always check for greater than 0 in optimisation so this is a good default */ csp_set_alloc_string(csound, &(instr->read_write)); csp_set_alloc_string(csound, &(instr->write)); csp_set_alloc_string(csound, &(instr->read)); return instr; } /*********************************************************************** * parse time support */ //static INSTR_SEMANTICS *curr; //static INSTR_SEMANTICS *root; /* void csp_orc_sa_cleanup(CSOUND *csound) */ /* { */ /* INSTR_SEMANTICS *current = csound-> instRoot, *h = NULL; */ /* csp_orc_sa_print_list(csound); */ /* while (current != NULL) { */ /* csp_set_dealloc(csound, &(current->read)); */ /* csp_set_dealloc(csound, &(current->write)); */ /* csp_set_dealloc(csound, &(current->read_write)); */ /* h = current; */ /* current = current->next; */ /* csound->Free(csound, h); */ /* } */ /* current = csound->instCurr; */ /* while (current != NULL) { */ /* csp_set_dealloc(csound, &(current->read)); */ /* csp_set_dealloc(csound, &(current->write)); */ /* csp_set_dealloc(csound, &(current->read_write)); */ /* h = current; */ /* current = current->next; */ /* csound->Free(csound, h); */ /* } */ /* csound->instCurr = NULL; */ /* csound->instRoot = NULL; */ /* } */ static void sanitise_set(CSOUND *csound, struct set_t* p) { struct set_element_t *ele = p->head; while (ele != NULL) { ele->data = cs_strdup(csound, (char*)ele->data); ele = ele->next; } } void sanitize(CSOUND*csound) { INSTR_SEMANTICS *p = csound->instRoot; while (p) { if (p->sanitized==0) { sanitise_set(csound, p->read); sanitise_set(csound, p->write); sanitise_set(csound, p->read_write); p->sanitized = 1; } p = p->next; } } void csp_orc_sa_print_list(CSOUND *csound) { csound->Message(csound, "Semantic Analysis\n"); INSTR_SEMANTICS *current = csound->instRoot; while (current != NULL) { csound->Message(csound, "(%p)Instr: %s\n", current, current->name); csound->Message(csound, " read(%p): ", current->read); csp_set_print(csound, current->read); csound->Message(csound, " write:(%p) ", current->write); csp_set_print(csound, current->write); csound->Message(csound, " read_write(%p): ", current->read_write); csp_set_print(csound, current->read_write); current = current->next; } csound->Message(csound, "Semantic Analysis Ends\n"); } void csp_orc_sa_global_read_write_add_list(CSOUND *csound, struct set_t *write, struct set_t *read) { if (UNLIKELY(csound->instCurr == NULL)) { csound->DebugMsg(csound, "Add global read, write lists without any instruments\n"); } else if (UNLIKELY(write == NULL || read == NULL)) { csound->Die(csound, Str("Invalid NULL parameter set to add to global read, " "write lists\n")); } else { csp_orc_sa_global_write_add_list(csound, write); csp_orc_sa_global_read_add_list(csound, read); } } void csp_orc_sa_global_read_write_add_list1(CSOUND *csound, struct set_t *write, struct set_t *read) { if (UNLIKELY(csound->instCurr == NULL)) { csound->DebugMsg(csound, "Add global read, write lists without any instruments\n"); } else if (UNLIKELY(write == NULL || read == NULL)) { csound->Die(csound, Str("Invalid NULL parameter set to add to global read, " "write lists\n")); } else { struct set_t *new = NULL; csp_set_union(csound, write, read, &new); //printf("Line: %d of cs_par_orc_semantics(%p)\n", __LINE__, *new); if (write->count == 1 && read->count == 1 && new->count == 1) { /* this is a read_write list thing */ struct set_t *new_read_write = NULL; csp_set_union(csound, csound->instCurr->read_write, new, &new_read_write); //printf("Line: %d of cs_par_orc_semantics(%p)\n", // __LINE__, *new_read_write); csp_set_dealloc(csound, &csound->instCurr->read_write); csound->instCurr->read_write = new_read_write; } else { csp_orc_sa_global_write_add_list(csound, write); csp_orc_sa_global_read_add_list(csound, read); } csp_set_dealloc(csound, &new); } } void csp_orc_sa_global_write_add_list(CSOUND *csound, struct set_t *set) { if (UNLIKELY(csound->instCurr == NULL)) { csound->Message(csound, Str("Add a global write_list without any instruments\n")); } else if (UNLIKELY(set == NULL)) { csound->Die(csound, Str("Invalid NULL parameter set to add to a " "global write_list\n")); } else { struct set_t *new = NULL; csp_set_union(csound, csound->instCurr->write, set, &new); csp_set_dealloc(csound, &csound->instCurr->write); csp_set_dealloc(csound, &set); csound->instCurr->write = new; } } void csp_orc_sa_global_read_add_list(CSOUND *csound, struct set_t *set) { if (csound->instCurr == NULL) { if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "add a global read_list without any instruments\n"); } else if (UNLIKELY(set == NULL)) { csound->Die(csound, Str("Invalid NULL parameter set to add to a " "global read_list\n")); } else { struct set_t *new = NULL; csp_set_union(csound, csound->instCurr->read, set, &new); csp_set_dealloc(csound, &csound->instCurr->read); csp_set_dealloc(csound, &set); csound->instCurr->read = new; } } void csp_orc_sa_interlocksf(CSOUND *csound, int code) { if (code&0xfff8) { /* zak etc */ struct set_t *rr = NULL; struct set_t *ww = NULL; csp_set_alloc_string(csound, &ww); csp_set_alloc_string(csound, &rr); if (code&ZR) csp_set_add(csound, rr, "##zak"); if (code&ZW) csp_set_add(csound, ww, "##zak"); if (code&TR) csp_set_add(csound, rr, "##tab"); if (code&TW) csp_set_add(csound, ww, "##tab"); if (code&_CR) csp_set_add(csound, rr, "##chn"); if (code&_CW) csp_set_add(csound, ww, "##chn"); if (code&WR) csp_set_add(csound, ww, "##wri"); csp_orc_sa_global_read_write_add_list(csound, ww, rr); if (UNLIKELY(code&_QQ)) csound->Message(csound, Str("opcode deprecated")); } } void csp_orc_sa_interlocks(CSOUND *csound, ORCTOKEN *opcode) { char *name = opcode->lexeme; OENTRY *ep = find_opcode(csound, name); csp_orc_sa_interlocksf(csound, ep->flags); } //static int inInstr = 0; void csp_orc_sa_instr_add(CSOUND *csound, char *name) { name = cs_strdup(csound, name); // JPff: leaks: necessary?? Think it is correct //printf("csp_orc_sa_instr_add name=%s\n", name); csound->inInstr = 1; if (csound->instRoot == NULL) { //printf("instRoot id NULL\n"); csound->instRoot = instr_semantics_alloc(csound, name); csound->instCurr = csound->instRoot; } else if (csound->instCurr == NULL) { INSTR_SEMANTICS *prev = csound->instRoot; //printf("instCurr NULL\n"); csound->instCurr = prev->next; while (csound->instCurr != NULL) { prev = csound->instCurr; csound->instCurr = csound->instCurr->next; } prev->next = instr_semantics_alloc(csound, name); csound->instCurr = prev->next; } else { //printf("othercase\n"); csound->instCurr->next = instr_semantics_alloc(csound, name); csound->instCurr = csound->instCurr->next; } // csound->instCurr->insno = named_instr_find(name); } /* New code to deal with lists of integer instruments -- JPff */ void csp_orc_sa_instr_add_tree(CSOUND *csound, TREE *x) { while (x) { if (x->type == INTEGER_TOKEN) { csp_orc_sa_instr_add(csound, x->value->lexeme); return; } if (x->type == T_IDENT) { csp_orc_sa_instr_add(csound, x->value->lexeme); return; } if (UNLIKELY(x->type != T_INSTLIST)) { csound->DebugMsg(csound,"type %d not T_INSTLIST\n", x->type); csound->Die(csound, Str("Not a proper list of ints")); } csp_orc_sa_instr_add(csound, x->left->value->lexeme); x = x->right; } } struct set_t *csp_orc_sa_globals_find(CSOUND *csound, TREE *node) { struct set_t *left=NULL, *right; struct set_t *current_set = NULL; if (node == NULL) { struct set_t *set = NULL; csp_set_alloc_string(csound, &set); return set; } left = csp_orc_sa_globals_find(csound, node->left); right = csp_orc_sa_globals_find(csound, node->right); csp_set_union(csound, left, right, ¤t_set); //printf("Line: %d of cs_par_orc_semantics(%p)\n", __LINE__, current_set); csp_set_dealloc(csound, &left); csp_set_dealloc(csound, &right); if ((node->type == T_IDENT || node->type == LABEL_TOKEN) && node->value->lexeme[0] == 'g') { csp_set_add(csound, current_set, /*strdup*/(node->value->lexeme)); } if (node->next != NULL) { struct set_t *prev_set = current_set; struct set_t *next = csp_orc_sa_globals_find(csound, node->next); csp_set_union(csound, prev_set, next, ¤t_set); //printf("Line: %d of cs_par_orc_semantics(%p)\n", __LINE__, current_set); csp_set_dealloc(csound, &prev_set); csp_set_dealloc(csound, &next); } return current_set; } INSTR_SEMANTICS *csp_orc_sa_instr_get_by_name(CSOUND *csound, char *instr_name) { INSTR_SEMANTICS *current_instr = csound->instRoot; while (current_instr != NULL) { if (strcmp(current_instr->name, instr_name) == 0) { return current_instr; } current_instr = current_instr->next; } return NULL; } INSTR_SEMANTICS *csp_orc_sa_instr_get_by_num(CSOUND *csound, int16 insno) { #define BUF_LENGTH 8 INSTR_SEMANTICS *current_instr = csound->instRoot; char buf[BUF_LENGTH]; while (current_instr != NULL) { if (current_instr->insno != -1 && current_instr->insno == insno) { return current_instr; } current_instr = current_instr->next; } snprintf(buf, BUF_LENGTH, "%i", insno); current_instr = csp_orc_sa_instr_get_by_name(csound, buf); if (current_instr != NULL) { current_instr->insno = insno; } return current_instr; } /* ANALYZE TREE */ void csp_orc_analyze_tree(CSOUND* csound, TREE* root) { if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "Performing csp analysis\n"); TREE *current = root; TREE *temp; while (current != NULL) { switch (current->type) { case INSTR_TOKEN: if (PARSER_DEBUG) csound->Message(csound, "Instrument found\n"); temp = current->left; // FIXME - need to figure out why csp_orc_sa_instr_add is // called by itself in csound_orc.y csp_orc_sa_instr_add_tree(csound, temp); csp_orc_analyze_tree(csound, current->right); csp_orc_sa_instr_finalize(csound); break; case UDO_TOKEN: if (PARSER_DEBUG) csound->Message(csound, "UDO found\n"); csp_orc_analyze_tree(csound, current->right); break; case IF_TOKEN: case UNTIL_TOKEN: break; case LABEL_TOKEN: break; default: if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "Statement: %s\n", current->value->lexeme); if (current->left != NULL) { csp_orc_sa_global_read_write_add_list(csound, csp_orc_sa_globals_find(csound, current->left), csp_orc_sa_globals_find(csound, current->right)); } else { csp_orc_sa_global_read_add_list(csound, csp_orc_sa_globals_find(csound, current->right)); } break; } current = current->next; } if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "[End csp analysis]\n"); } csound-6.10.0/Engine/csound_data_structures.c000066400000000000000000000210751321653344700212460ustar00rootroot00000000000000/* csound_data_structures.c: Copyright (C) 2013 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "csound_data_structures.h" #ifdef __cplusplus extern "C" { #endif /* FUNCTIONS FOR CONS_CELL */ PUBLIC CONS_CELL* cs_cons(CSOUND* csound, void* val, CONS_CELL* cons) { CONS_CELL* cell = csound->Malloc(csound, sizeof(CONS_CELL)); cell->value = val; cell->next = cons; return cell; } PUBLIC CONS_CELL* cs_cons_append(CONS_CELL* cons1, CONS_CELL* cons2) { if (cons1 == NULL) return cons2; if (cons2 == NULL) return cons1; CONS_CELL* c = cons1; while (c->next != NULL) c = c->next; c->next = cons2; return cons1; } PUBLIC int cs_cons_length(CONS_CELL* head) { CONS_CELL* current = head; int count = 0; while (current != NULL) { count++; current = current->next; } return count; } PUBLIC void cs_cons_free(CSOUND* csound, CONS_CELL* head) { CONS_CELL *current, *next; if (head == NULL) return; current = head; while (current != NULL) { next = current->next; csound->Free(csound, current); current = next; } } PUBLIC void cs_cons_free_complete(CSOUND* csound, CONS_CELL* head) { CONS_CELL *current, *next; if (head == NULL) return; current = head; while (current != NULL) { next = current->next; csound->Free(csound, current->value); csound->Free(csound, current); current = next; } } /* FUNCTION FOR HASH SET */ PUBLIC CS_HASH_TABLE* cs_hash_table_create(CSOUND* csound) { return (CS_HASH_TABLE*) csound->Calloc(csound, sizeof(CS_HASH_TABLE)); } static unsigned int cs_name_hash(char *s) { unsigned int h = 0; while (*s != '\0') { h = (h<<4) ^ *s++; } return (h%HASH_SIZE); } PUBLIC void* cs_hash_table_get(CSOUND* csound, CS_HASH_TABLE* hashTable, char* key) { IGN(csound); unsigned int index; CS_HASH_TABLE_ITEM* item; if (key == NULL) { return NULL; } index = cs_name_hash(key); item = hashTable->buckets[index]; while (item != NULL) { if (strcmp(key, item->key) == 0) { return item->value; } item = item->next; } return NULL; } PUBLIC char* cs_hash_table_get_key(CSOUND* csound, CS_HASH_TABLE* hashTable, char* key) { unsigned int index; CS_HASH_TABLE_ITEM* item; IGN(csound); if (key == NULL) { return NULL; } index = cs_name_hash(key); item = hashTable->buckets[index]; while (item != NULL) { if (strcmp(key, item->key) == 0) { return item->key; } item = item->next; } return NULL; } char* cs_hash_table_put_no_key_copy(CSOUND* csound, CS_HASH_TABLE* hashTable, char* key, void* value) { if (key == NULL) { return NULL; } unsigned int index = cs_name_hash(key); CS_HASH_TABLE_ITEM* item = hashTable->buckets[index]; if (item == NULL) { CS_HASH_TABLE_ITEM* newItem = csound->Malloc(csound, sizeof(CS_HASH_TABLE_ITEM)); newItem->key = key; newItem->value = value; newItem->next = NULL; hashTable->buckets[index] = newItem; return newItem->key; } else { while (item != NULL) { if (strcmp(key, item->key) == 0) { item->value = value; return item->key; } else if (item->next == NULL) { CS_HASH_TABLE_ITEM* newItem = csound->Malloc(csound, sizeof(CS_HASH_TABLE_ITEM)); newItem->key = key; newItem->value = value; newItem->next = NULL; item->next = newItem; return newItem->key; } item = item->next; } } return NULL; } PUBLIC void cs_hash_table_put(CSOUND* csound, CS_HASH_TABLE* hashTable, char* key, void* value) { cs_hash_table_put_no_key_copy(csound, hashTable, cs_strdup(csound, key), value); } PUBLIC char* cs_hash_table_put_key(CSOUND* csound, CS_HASH_TABLE* hashTable, char* key) { return cs_hash_table_put_no_key_copy(csound, hashTable, cs_strdup(csound, key), NULL); } PUBLIC void cs_hash_table_remove(CSOUND* csound, CS_HASH_TABLE* hashTable, char* key) { CS_HASH_TABLE_ITEM *previous, *item; unsigned int index; if (key == NULL) { return; } index = cs_name_hash(key); previous = NULL; item = hashTable->buckets[index]; while (item != NULL) { if (strcmp(key, item->key) == 0) { if (previous == NULL) { hashTable->buckets[index] = item->next; } else { previous->next = item->next; } csound->Free(csound, item); return; } previous = item; item = item->next; } } PUBLIC CONS_CELL* cs_hash_table_keys(CSOUND* csound, CS_HASH_TABLE* hashTable) { CONS_CELL* head = NULL; int i = 0; for (i = 0; i < HASH_SIZE; i++) { CS_HASH_TABLE_ITEM* item = hashTable->buckets[i]; while (item != NULL) { head = cs_cons(csound, item->key, head); item = item->next; } } return head; } PUBLIC CONS_CELL* cs_hash_table_values(CSOUND* csound, CS_HASH_TABLE* hashTable) { CONS_CELL* head = NULL; int i = 0; for (i = 0; i < HASH_SIZE; i++) { CS_HASH_TABLE_ITEM* item = hashTable->buckets[i]; while (item != NULL) { head = cs_cons(csound, item->value, head); item = item->next; } } return head; } PUBLIC void cs_hash_table_merge(CSOUND* csound, CS_HASH_TABLE* target, CS_HASH_TABLE* source) { // TODO - check if this is the best strategy for merging int i = 0; for (i = 0; i < HASH_SIZE; i++) { CS_HASH_TABLE_ITEM* item = source->buckets[i]; while (item != NULL) { CS_HASH_TABLE_ITEM* next = item->next; char* new_key = cs_hash_table_put_no_key_copy(csound, target, item->key, item->value); if (new_key != item->key) { csound->Free(csound, item->key); } csound->Free(csound, item); item = next; } source->buckets[i] = NULL; } } PUBLIC void cs_hash_table_free(CSOUND* csound, CS_HASH_TABLE* hashTable) { int i; for (i = 0; i < HASH_SIZE; i++) { CS_HASH_TABLE_ITEM* item = hashTable->buckets[i]; while(item != NULL) { CS_HASH_TABLE_ITEM* next = item->next; csound->Free(csound, item->key); csound->Free(csound, item); item = next; } } csound->Free(csound, hashTable); } PUBLIC void cs_hash_table_mfree_complete(CSOUND* csound, CS_HASH_TABLE* hashTable) { int i; for (i = 0; i < HASH_SIZE; i++) { CS_HASH_TABLE_ITEM* item = hashTable->buckets[i]; while(item != NULL) { CS_HASH_TABLE_ITEM* next = item->next; csound->Free(csound, item->key); csound->Free(csound, item->value); csound->Free(csound, item); item = next; } } csound->Free(csound, hashTable); } PUBLIC void cs_hash_table_free_complete(CSOUND* csound, CS_HASH_TABLE* hashTable) { int i; for (i = 0; i < HASH_SIZE; i++) { CS_HASH_TABLE_ITEM* item = hashTable->buckets[i]; while(item != NULL) { CS_HASH_TABLE_ITEM* next = item->next; csound->Free(csound, item->key); /* NOTE: This needs to be free, not csound->Free. To use mfree on keys, use cs_hash_table_mfree_complete TODO: Check if this is even necessary anymore... */ free(item->value); csound->Free(csound, item); item = next; } } csound->Free(csound, hashTable); } #ifdef __cplusplus extern "C" { #endif csound-6.10.0/Engine/csound_orc.lex000066400000000000000000000644341321653344700171710ustar00rootroot00000000000000%{ /* csound_orc.l: Copyright (C) 2006 John ffitch, Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include "csoundCore.h" #define YYSTYPE TREE* #define YYLTYPE ORCTOKEN* #define YY_DECL int yylex (YYLTYPE *lvalp, CSOUND *csound, yyscan_t yyscanner) #include "csound_orc.h" #include "corfile.h" YYSTYPE *yylval_param; YYLTYPE *yylloc_param; ORCTOKEN *make_string(CSOUND *, char *); extern ORCTOKEN *lookup_token(CSOUND *, char *, void *); extern void *fopen_path(CSOUND *, FILE **, char *, char *, char *, int); ORCTOKEN *new_token(CSOUND *csound, int type); ORCTOKEN *make_int(CSOUND *, char *); ORCTOKEN *make_num(CSOUND *, char *); ORCTOKEN *make_token(CSOUND *, char *s); ORCTOKEN *make_label(CSOUND *, char *s); #define udoflag csound->parserUdoflag #define namedInstrFlag csound->parserNamedInstrFlag #include "parse_param.h" #define YY_EXTRA_TYPE PARSE_PARM * #define PARM yyget_extra(yyscanner) /* #define YY_INPUT(buf,result,max_size) {\ */ /* result = get_next_char(buf, max_size, yyg); \ */ /* if ( UNLIKELY( result <= 0 )) \ */ /* result = YY_NULL; \ */ /* } */ #define YY_USER_INIT struct yyguts_t; ORCTOKEN *do_at(CSOUND *, int, struct yyguts_t*); int get_next_char(char *, int, struct yyguts_t*); %} %option reentrant %option bison-bridge %option bison-locations %option prefix="csound_orc" %option outfile="Engine/csound_orclex.c" %option stdout %option 8bit LABEL ^[ \t]*[a-zA-Z0-9_][a-zA-Z0-9_]*:([ \t\n]+|$) /* VL: added extra checks for after the colon */ IDENT [a-zA-Z_][a-zA-Z0-9_]* IDENTB [a-zA-Z_][a-zA-Z0-9_]*\([ \t]*("\n")? XIDENT 0|[aijkftKOJVPopS\[\]]+ INTGR [0-9]+ NUMBER [0-9]+\.?[0-9]*([eE][-+]?[0-9]+)?|\.[0-9]+([eE][-+]?[0-9]+)?|0[xX][0-9a-fA-F]+ WHITE [ \t]+ OPTWHITE [ \t]* CONT \\[ \t]*(;.*)?\n XSTR "{{" EXSTR "}}" LINE ^[ \t]*"#line" SLINE "#sline " FILE ^[ \t]*"#source" FNAME [a-zA-Z0-9/:.+-_]+ %x line %x sline %x src %x xstr %x udodef %x udoarg %% "\r" { } /* EATUP THIS PART OF WINDOWS NEWLINE */ {CONT} { csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); } "\n" { csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return NEWLINE; } "("{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return '('; } ")" { return ')'; } "["{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return '['; } "]" { return ']'; } "+"{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return '+'; } "-"{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return '-'; } "*"{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return '*'; } "/"{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return '/'; } "%"{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return '%'; } "\^"{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return '^'; } "?"{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return '?'; } ":" { return ':'; } ","{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return ','; } "!"{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return '!'; } "->" { return S_ELIPSIS; } "!="{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return S_NEQ; } "&&"{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return S_AND; } "||"{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return S_OR; } "<<"{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return S_BITSHIFT_LEFT; } ">>"{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return S_BITSHIFT_RIGHT; } "<"{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return S_LT; } "<="{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return S_LE; } "=="{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return S_EQ; } "+="{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return S_ADDIN; } "-="{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return S_SUBIN; } "*="{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return S_MULIN; } "/="{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return S_DIVIN; } "="{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); *lvalp = make_token(csound, "="); (*lvalp)->type = '='; return '='; } ">"{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return S_GT; } ">="{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return S_GE; } "|"{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return '|'; } "&"{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return '&'; } "#"{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return '#'; } \xC2?\xAC{OPTWHITE}"\n"? { //printf("convert to ~\n"); if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return '~'; } "~"{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return '~'; } "@@"{OPTWHITE}{INTGR} { *lvalp = do_at(csound, 1, yyg); return INTEGER_TOKEN; } "@"{OPTWHITE}{INTGR} { *lvalp = do_at(csound, 0, yyg); return INTEGER_TOKEN; } "@i" { return T_MAPI; } "@k" { return T_MAPK; } "if" { *lvalp = make_token(csound, yytext); (*lvalp)->type = IF_TOKEN; return IF_TOKEN; } "if("{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); *lvalp = make_token(csound, yytext); unput('('); (*lvalp)->type = IF_TOKEN; return IF_TOKEN; } "then" { *lvalp = make_token(csound, yytext); (*lvalp)->type = THEN_TOKEN; return THEN_TOKEN; } "ithen" { *lvalp = make_token(csound, yytext); (*lvalp)->type = ITHEN_TOKEN; return ITHEN_TOKEN; } "kthen" { *lvalp = make_token(csound, yytext); (*lvalp)->type = KTHEN_TOKEN; return KTHEN_TOKEN; } "elseif" { *lvalp = make_token(csound, yytext); (*lvalp)->type = ELSEIF_TOKEN; return ELSEIF_TOKEN; } "elseif("{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); unput('('); *lvalp = make_token(csound, yytext); (*lvalp)->type = ELSEIF_TOKEN; return ELSEIF_TOKEN; } "else" { *lvalp = make_token(csound, yytext); (*lvalp)->type = ELSE_TOKEN; return ELSE_TOKEN; } "endif" { *lvalp = make_token(csound, yytext); (*lvalp)->type = ENDIF_TOKEN; return ENDIF_TOKEN; } "fi" { *lvalp = make_token(csound, yytext); (*lvalp)->type = ENDIF_TOKEN; return ENDIF_TOKEN; } "until" { *lvalp = make_token(csound, yytext); (*lvalp)->type = UNTIL_TOKEN; return UNTIL_TOKEN; } "while" { *lvalp = make_token(csound, yytext); (*lvalp)->type = WHILE_TOKEN; return WHILE_TOKEN; } "do" { *lvalp = make_token(csound, yytext); (*lvalp)->type = DO_TOKEN; return DO_TOKEN; } "od" { *lvalp = make_token(csound, yytext); (*lvalp)->type = OD_TOKEN; return OD_TOKEN; } "enduntil" { *lvalp = make_token(csound, yytext); (*lvalp)->type = OD_TOKEN; return OD_TOKEN; } "goto" { *lvalp = make_token(csound, yytext); (*lvalp)->type = GOTO_TOKEN; return GOTO_TOKEN; }; "igoto" { *lvalp = make_token(csound, yytext); (*lvalp)->type = IGOTO_TOKEN; return IGOTO_TOKEN; }; "kgoto" { *lvalp = make_token(csound, yytext); (*lvalp)->type = KGOTO_TOKEN; return KGOTO_TOKEN; }; "sr" { *lvalp = make_token(csound, yytext); (*lvalp)->type = SRATE_TOKEN; return SRATE_TOKEN; } "kr" { *lvalp = make_token(csound, yytext); (*lvalp)->type = KRATE_TOKEN; return KRATE_TOKEN; } "ksmps" { *lvalp = make_token(csound, yytext); (*lvalp)->type = KSMPS_TOKEN; return KSMPS_TOKEN; } "nchnls" { *lvalp = make_token(csound, yytext); (*lvalp)->type = NCHNLS_TOKEN; return NCHNLS_TOKEN; } "nchnls_i" { *lvalp = make_token(csound, yytext); (*lvalp)->type = NCHNLSI_TOKEN; return NCHNLSI_TOKEN; } "A4" { *lvalp = make_token(csound, yytext); (*lvalp)->type = A4_TOKEN; return A4_TOKEN; } "instr" { namedInstrFlag = 1; return INSTR_TOKEN; } "endin" { *lvalp = make_token(csound, yytext); (*lvalp)->type = ENDIN_TOKEN; return ENDIN_TOKEN; } "opcode" { BEGIN(udodef); return UDOSTART_DEFINITION; } "endop" { *lvalp = new_token(csound, UDOEND_TOKEN); return UDOEND_TOKEN; } {LABEL} { char *pp = yytext; while (*pp==' ' || *pp=='\t') pp++; *lvalp = make_label(csound, pp); return LABEL_TOKEN; } "\{\{" { PARM->xstrbuff = (char *)malloc(128); PARM->xstrptr = 0; PARM->xstrmax = 128; PARM->xstrbuff[PARM->xstrptr++] = '"'; PARM->xstrbuff[PARM->xstrptr] = '\0'; BEGIN(xstr); } "}}" { BEGIN(INITIAL); PARM->xstrbuff[PARM->xstrptr++] = '"'; PARM->xstrbuff[PARM->xstrptr] = '\0'; /* printf("xstrbuff:>>%s<<\n", PARM->xstrbuff); */ *lvalp = make_string(csound, PARM->xstrbuff); free(PARM->xstrbuff); return STRING_TOKEN; } "\n" { /* The next two should be one case but I cannot get that to work */ if (UNLIKELY(PARM->xstrptr+2==PARM->xstrmax)) { PARM->xstrbuff = (char *)realloc(PARM->xstrbuff, PARM->xstrmax+=80); csound->DebugMsg(csound,"Extending xstr buffer\n"); } //csound->DebugMsg(csound,"Adding newline (%.2x)\n", yytext[0]); PARM->xstrbuff[PARM->xstrptr++] = yytext[0]; PARM->xstrbuff[PARM->xstrptr] = '\0'; } "\r" { } . { if (UNLIKELY(PARM->xstrptr+2==PARM->xstrmax)) { PARM->xstrbuff = (char *)realloc(PARM->xstrbuff, PARM->xstrmax+=80); csound->DebugMsg(csound,"Extending xstr buffer\n"); } //csound->DebugMsg(csound,"Adding (%.2x)\n", yytext[0]); PARM->xstrbuff[PARM->xstrptr++] = yytext[0]; PARM->xstrbuff[PARM->xstrptr] = '\0'; } {WHITE} { } {IDENT} { BEGIN(udoarg); *lvalp = lookup_token(csound, yytext, yyscanner); /* csound->Message(csound,"%s -> %d\n", yytext, (*lvalp)->type); */ return (*lvalp)->type; } ","{OPTWHITE}"\n"? { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return ','; } {XIDENT} { BEGIN(udoarg); *lvalp = lookup_token(csound, yytext, yyscanner); /* csound->Message(csound,"%s -> %d\n", yytext, (*lvalp)->type); */ return (*lvalp)->type; } "\n" { BEGIN(INITIAL); csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); return NEWLINE; } \" { /* String decode by c-code not rexp */ int cnt = 80; char *buff = malloc(cnt); int n = 1; int ch; buff[0] = '"'; for (;;) { ch = input(yyscanner); if (ch=='"') { if (n>=cnt-2) buff = realloc(buff, cnt+=20); buff[n++] = ch; buff[n] = '\0'; break; } else if (ch=='\\') { ch = input(yyscanner); switch (ch) { case 'a': case 'b': case 'n': case 'r': case 't': case '\\': if (n>=cnt-2) buff = realloc(buff, cnt+=20); buff[n++] = '\\'; buff[n++]= ch; break; /* VL - 21-1-17 fix for octals in strings */ case '0':case '1':case '2':case '3': case '4':case '5':case '6':case '7': if (n>=cnt-2) buff = realloc(buff, cnt+=20); buff[n++] = '\\'; buff[n++]= ch; break; default: if (n>=cnt-2) buff = realloc(buff, cnt+=20); buff[n++] = ch; break; } } else if (UNLIKELY(ch=='\n')) { if (UNLIKELY(n>=cnt-2)) buff = realloc(buff, cnt+=20); buff[n++] = '"'; buff[n] = '\0'; csound->Message(csound, Str("unterminated string found on line %d >>%s<<\n"), csound_orcget_lineno(yyscanner), buff); break; } else { if (UNLIKELY(n>=cnt-2)) buff = realloc(buff, cnt+=20); buff[n++] = ch; } } *lvalp = make_string(csound, buff); free(buff); return (STRING_TOKEN); } "0dbfs" { *lvalp = make_token(csound, yytext); (*lvalp)->type = ZERODBFS_TOKEN; /* csound->Message(csound,"%d\n", (*lvalp)->type); */ return ZERODBFS_TOKEN; } {IDENTB} { if (UNLIKELY(strchr(yytext, '\n'))) csound_orcset_lineno(1+csound_orcget_lineno(yyscanner), yyscanner); *strrchr(yytext, '(') = '\0'; *lvalp = lookup_token(csound, yytext, yyscanner); return (*lvalp)->type+1; } {IDENT} { *lvalp = lookup_token(csound, yytext, yyscanner); /* csound->Message(csound,"%s -> %d\n", yytext, (*lvalp)->type); */ return (*lvalp)->type; } {INTGR} { if (udoflag == 0) { *lvalp = make_string(csound, yytext); (*lvalp)->type = UDO_ANS_TOKEN; } else if (udoflag == 1) { *lvalp = make_string(csound, yytext); (*lvalp)->type = UDO_ARGS_TOKEN; } else { *lvalp = make_int(csound, yytext); return (INTEGER_TOKEN); } csound->Message(csound,"%d\n", (*lvalp)->type); return ((*lvalp)->type); } {NUMBER} { *lvalp = make_num(csound, yytext); return (NUMBER_TOKEN); } {WHITE} { } {SLINE} { BEGIN(sline); } {INTGR} { csound_orcset_lineno(atoi(yytext), yyscanner); } [ \t]* { BEGIN(INITIAL);} {LINE} { BEGIN(line); } [ \t]* /* eat the whitespace */ {INTGR} { csound_orcset_lineno(atoi(yytext), yyscanner); } "\n" {BEGIN(INITIAL);} {FILE} { BEGIN(src); } [ \t]* /* eat the whitespace */ {FNAME} { PARM->locn = atoll(yytext); } "\n" { BEGIN(INITIAL); } . { { int c = yytext[0]&0xff; printf("Error: character %c(%.2x)\n", c, c); } return ERROR_TOKEN; } <> { yyterminate(); } %% /* unused at the moment static inline int isNameChar(int c, int pos) { c = (int) ((unsigned char) c); return (isalpha(c) || (pos && (c == '_' || isdigit(c)))); } */ ORCTOKEN *new_token(CSOUND *csound, int type) { ORCTOKEN *ans = (ORCTOKEN*)csound->Calloc(csound, sizeof(ORCTOKEN)); ans->type = type; return ans; } ORCTOKEN *make_token(CSOUND *csound, char *s) { ORCTOKEN *ans = new_token(csound, STRING_TOKEN); ans->lexeme = cs_strdup(csound, s); return ans; } ORCTOKEN *make_label(CSOUND *csound, char *s) { ORCTOKEN *ans = new_token(csound, LABEL_TOKEN); int len; char *ps = s; while (*ps != ':') ps++; *(ps+1) = '\0'; len = strlen(s); ans->lexeme = (char*)csound->Calloc(csound, len); strncpy(ans->lexeme, s, len-1); /* Not the trailing colon */ return ans; } ORCTOKEN *make_string(CSOUND *csound, char *s) { ORCTOKEN *ans = new_token(csound, STRING_TOKEN); int len = strlen(s); /* Keep the quote marks */ ans->lexeme = (char*)csound->Calloc(csound, len + 1); strcpy(ans->lexeme, s); //printf(">>%s<<\n", ans->lexeme); return ans; } ORCTOKEN *do_at(CSOUND *csound, int k, struct yyguts_t *yyg) { int n, i = 1; ORCTOKEN *ans; char buf[16]; char *s = yytext; int len; while (*s=='@') s++; n = atoi(s); while (i<=n-k && i< 0x4000000) i <<= 1; ans = new_token(csound, INTEGER_TOKEN); sprintf(buf, "%d", i+k); len = strlen(buf); ans->lexeme = (char*)csound->Calloc(csound, len + 1); strncpy(ans->lexeme, buf, len); ans->value = i; return ans; } ORCTOKEN *make_int(CSOUND *csound, char *s) { int n = atoi(s); ORCTOKEN *ans = new_token(csound, INTEGER_TOKEN); int len = strlen(s); ans->lexeme = (char*)csound->Calloc(csound, len + 1); strncpy(ans->lexeme, s, len); ans->value = n; return ans; } ORCTOKEN *make_num(CSOUND *csound, char *s) { double n = atof(s); ORCTOKEN *ans = new_token(csound, NUMBER_TOKEN); int len = strlen(s); ans->lexeme = (char*)csound->Calloc(csound, len + 1); strncpy(ans->lexeme, s, len); ans->fvalue = n; return ans; } char *csound_orcget_current_pointer(void *yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; return yyg->yy_c_buf_p; } uint64_t csound_orcget_locn(void *yyscanner) { // struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; return PARM->locn; } void csound_orcput_ilocn(void *yyscanner, uint64_t num, uint64_t fil) { // struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; PARM->iline = num; PARM->ilocn = fil; } uint64_t csound_orcget_iline(void *yyscanner) { // struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; return PARM->iline; } uint64_t csound_orcget_ilocn(void *yyscanner) { // struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; return PARM->ilocn; } /* {STRCONSTe} { *lvalp = make_string(csound, yytext); csound->Message(csound, Str("unterminated string found on line %d >>%s<<\n"), csound_orcget_lineno(yyscanner), yytext); return (STRING_TOKEN); } STRCONSTe \"(\.|[^\"])$ STRCONST \"(\\.|[^\"\n])*\" */ csound-6.10.0/Engine/csound_orc.y000066400000000000000000001035631321653344700166460ustar00rootroot00000000000000/* csound_orc.y: Copyright (C) 2006, 2007 John ffitch, Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ %pure-parser %parse-param {PARSE_PARM *parm} %parse-param {void *scanner} %lex-param { CSOUND * csound } %lex-param {yyscan_t *scanner} %token NEWLINE %token S_NEQ %token S_AND %token S_OR %token S_LT %token S_LE %token S_EQ %token S_ADDIN %token S_SUBIN %token S_MULIN %token S_DIVIN %token S_GT %token S_GE %token S_BITSHIFT_LEFT %token S_BITSHIFT_RRIGHT %token LABEL_TOKEN %token IF_TOKEN %token T_OPCODE0 %token T_OPCODE0B %token T_OPCODE %token T_OPCODEB %token UDO_TOKEN %token UDOSTART_DEFINITION %token UDOEND_TOKEN %token UDO_ANS_TOKEN %token UDO_ARGS_TOKEN %token ERROR_TOKEN %token T_FUNCTION %token T_FUNCTIONB %token INSTR_TOKEN %token ENDIN_TOKEN %token GOTO_TOKEN %token KGOTO_TOKEN %token IGOTO_TOKEN %token SRATE_TOKEN %token KRATE_TOKEN %token KSMPS_TOKEN %token NCHNLS_TOKEN %token NCHNLSI_TOKEN %token ZERODBFS_TOKEN %token A4_TOKEN %token STRING_TOKEN %token T_IDENT %token T_IDENTB %token INTEGER_TOKEN %token NUMBER_TOKEN %token THEN_TOKEN %token ITHEN_TOKEN %token KTHEN_TOKEN %token ELSEIF_TOKEN %token ELSE_TOKEN %token ENDIF_TOKEN %token UNTIL_TOKEN %token WHILE_TOKEN %token DO_TOKEN %token OD_TOKEN %token T_INSTLIST %token S_ELIPSIS %token T_ARRAY %token T_ARRAY_IDENT %token T_MAPI %token T_MAPK %start orcfile %left '?' %left S_AND S_OR %nonassoc THEN_TOKEN ITHEN_TOKEN KTHEN_TOKEN ELSE_TOKEN /* IS THIS NECESSARY? */ %left '|' %left '&' %left S_LT S_GT S_LEQ S_GEQ S_EQ S_NEQ %left S_BITSHIFT_LEFT S_BITSHIFT_RIGHT %left '+' '-' %left '*' '/' '%' %left '^' %left '#' %right '~' %right S_UNOT %right S_UMINUS %right S_ATAT %right S_AT %token S_GOTO %token T_HIGHEST %error-verbose %parse-param { CSOUND * csound } %parse-param { TREE ** astTree } /* NOTE: Perhaps should use %union feature of bison */ %{ /* #define YYSTYPE ORCTOKEN* */ /* JPff thinks that line must be wrong and is trying this! */ #define YYSTYPE TREE* #ifndef NULL #define NULL 0L #endif #include "csoundCore.h" #include #include #include "namedins.h" #include "csound_orc.h" #include "parse_param.h" #ifndef __EMSCRIPTEN__ #include "cs_par_base.h" #include "cs_par_orc_semantics.h" #else #define csp_orc_sa_instr_add(a,b) #define csp_orc_sa_instr_add_tree(a,b) #define csp_orc_sa_instr_finalize(a) #define csp_orc_sa_global_read_write_add_list(a,b,c) #define csp_orc_sa_globals_find(a,b) #define csp_orc_sa_global_read_write_add_list1(a,b,c) #define csp_orc_sa_interlocks(a, b) #define csp_orc_sa_global_read_add_list(a,b) #endif #define udoflag csound->parserUdoflag #define namedInstrFlag csound->parserNamedInstrFlag extern TREE* appendToTree(CSOUND * csound, TREE *first, TREE *newlast); extern int csound_orclex(TREE**, CSOUND *, void *); extern void print_tree(CSOUND *, char *msg, TREE *); extern TREE* constant_fold(CSOUND *, TREE *); extern void csound_orcerror(PARSE_PARM *, void *, CSOUND *, TREE**, const char*); extern int add_udo_definition(CSOUND*, char *, char *, char *); extern ORCTOKEN *lookup_token(CSOUND*,char*,void*); #define LINE csound_orcget_lineno(scanner) #define LOCN csound_orcget_locn(scanner) extern uint64_t csound_orcget_locn(void *); extern int csound_orcget_lineno(void *); extern ORCTOKEN *make_string(CSOUND *, char *); %} %% orcfile : rootstatement { csound->synterrcnt = csound_orcnerrs; if (UNLIKELY(csound->oparms->odebug)) print_tree(csound, "ALL", $1); $1 = constant_fold(csound, $1); if (UNLIKELY(csound->oparms->odebug)) print_tree(csound, "Folded", $1); if ($1 != NULL) *astTree = ((TREE *)$1); } ; rootstatement : rootstatement topstatement { $$ = appendToTree(csound, $1, $2); } | rootstatement instrdecl { $$ = appendToTree(csound, $1, $2); } | rootstatement udodecl { $$ = appendToTree(csound, $1, $2); } | topstatement | instrdecl | udodecl ; instlist : INTEGER_TOKEN ',' instlist { $$ = make_node(csound, LINE, LOCN, T_INSTLIST, make_leaf(csound, LINE,LOCN, INTEGER_TOKEN, (ORCTOKEN *)$1), $3); } | label ',' instlist { csp_orc_sa_instr_add(csound, ((ORCTOKEN *)$1)->lexeme); $$ = make_node(csound,LINE,LOCN, T_INSTLIST, make_leaf(csound, LINE,LOCN, T_IDENT, (ORCTOKEN *)$1), $3); } | '+' label ',' instlist { TREE *ans; ans = make_leaf(csound, LINE,LOCN, T_IDENT, (ORCTOKEN *)$2); ans->rate = (int) '+'; csp_orc_sa_instr_add(csound, ((ORCTOKEN *)$2)->lexeme); $$ = make_node(csound,LINE,LOCN, T_INSTLIST, ans, $4); } | '+' label { TREE *ans; ans = make_leaf(csound, LINE,LOCN, T_IDENT, (ORCTOKEN *)$2); ans->rate = (int) '+'; $$ = ans; } | INTEGER_TOKEN { $$ = make_leaf(csound, LINE,LOCN, INTEGER_TOKEN, (ORCTOKEN *)$1); } | label { $$ = make_leaf(csound, LINE,LOCN, T_IDENT, (ORCTOKEN *)$1); } ; instrdecl : INSTR_TOKEN { namedInstrFlag = 1; csound_orcput_ilocn(scanner, LINE, LOCN); } instlist NEWLINE { namedInstrFlag = 0; csp_orc_sa_instr_add_tree(csound, $3); } statementlist ENDIN_TOKEN NEWLINE { $$ = make_node(csound, csound_orcget_iline(scanner), csound_orcget_ilocn(scanner), INSTR_TOKEN, $3, $6); csp_orc_sa_instr_finalize(csound); } | INSTR_TOKEN NEWLINE error { namedInstrFlag = 0; csound->Message(csound, Str("No number following instr\n")); csp_orc_sa_instr_finalize(csound); $$ = NULL; } ; udoname : T_IDENT { $$ = (TREE *)$1; } | T_OPCODE { $$ = (TREE *)$1; } | T_OPCODE0 { $$ = (TREE *)$1; } udodecl : UDOSTART_DEFINITION { udoflag = -2; } udoname { udoflag = -1; } ',' { udoflag = 0;} UDO_ANS_TOKEN { udoflag = 1; } ',' UDO_ARGS_TOKEN NEWLINE { udoflag = 2; add_udo_definition(csound, ((ORCTOKEN *)$3)->lexeme, ((ORCTOKEN *)$7)->lexeme, ((ORCTOKEN *)$10)->lexeme); } statementlist UDOEND_TOKEN NEWLINE { TREE *udoTop = make_leaf(csound, LINE,LOCN, UDO_TOKEN, (ORCTOKEN *)NULL); TREE *ident = make_leaf(csound, LINE,LOCN, T_IDENT, (ORCTOKEN *)$3); TREE *udoAns = make_leaf(csound, LINE,LOCN, UDO_ANS_TOKEN, (ORCTOKEN *)$7); TREE *udoArgs = make_leaf(csound, LINE,LOCN, UDO_ARGS_TOKEN, (ORCTOKEN *)$10); udoflag = -1; if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "UDO COMPLETE\n"); udoTop->left = ident; ident->left = udoAns; ident->right = udoArgs; udoTop->right = (TREE *)$13; $$ = udoTop; if (UNLIKELY(PARSER_DEBUG)) print_tree(csound, "UDO\n", (TREE *)$$); } ; statementlist : statementlist statement { $$ = appendToTree(csound, (TREE *)$1, (TREE *)$2); } | /* null */ { $$ = NULL; } ; topstatement : rident '=' expr NEWLINE { TREE *ans = make_leaf(csound,LINE,LOCN, '=', (ORCTOKEN *)$2); ans->left = (TREE *)$1; ans->right = (TREE *)$3; $$ = ans; } | statement { $$ = $1; } ; statement : ident '=' expr NEWLINE { //int op = ($1->value->lexeme[0]!='a')?'=':LOCAL_ASSIGN; TREE *ans = make_leaf(csound,LINE,LOCN, '=', (ORCTOKEN *)$2); ans->left = (TREE *)$1; //print_tree(csound, "****assign", ans); ans->right = (TREE *)$3; $$ = ans; if (namedInstrFlag!=2) csp_orc_sa_global_read_write_add_list(csound, csp_orc_sa_globals_find(csound, ans->left), csp_orc_sa_globals_find(csound, ans->right)); } | ident S_ADDIN expr NEWLINE { TREE *ans = make_leaf(csound,LINE,LOCN, '=', make_token(csound, "=")); ORCTOKEN *repeat = make_token(csound, $1->value->lexeme); ans->left = (TREE *)$1; ans->right = make_node(csound,LINE,LOCN, '+', make_leaf(csound,LINE,LOCN, $1->value->type, repeat), (TREE *)$3); //print_tree(csound, "+=", ans); $$ = ans; if (namedInstrFlag!=2) csp_orc_sa_global_read_write_add_list1(csound, csp_orc_sa_globals_find(csound, ans->left), csp_orc_sa_globals_find(csound, ans->right)); } | ident S_SUBIN expr NEWLINE { TREE *ans = make_leaf(csound,LINE,LOCN, '=', make_token(csound, "=")); ORCTOKEN *repeat = make_token(csound, $1->value->lexeme); ans->left = (TREE *)$1; ans->right = make_node(csound,LINE,LOCN, '-', make_leaf(csound,LINE,LOCN, $1->value->type, repeat), (TREE *)$3); //print_tree(csound, "-=", ans); $$ = ans; if (namedInstrFlag!=2) csp_orc_sa_global_read_write_add_list1(csound, csp_orc_sa_globals_find(csound, ans->left), csp_orc_sa_globals_find(csound, ans->right)); } | ident S_MULIN expr NEWLINE { TREE *ans = make_leaf(csound,LINE,LOCN, '=', make_token(csound, "=")); ORCTOKEN *repeat = make_token(csound, $1->value->lexeme); ans->left = (TREE *)$1; ans->right = make_node(csound,LINE,LOCN, '*', make_leaf(csound,LINE,LOCN, $1->value->type, repeat), (TREE *)$3); //print_tree(csound, "-=", ans); $$ = ans; if (namedInstrFlag!=2) csp_orc_sa_global_read_write_add_list(csound, csp_orc_sa_globals_find(csound, ans->left), csp_orc_sa_globals_find(csound, ans->right)); } | ident S_DIVIN expr NEWLINE { TREE *ans = make_leaf(csound,LINE,LOCN, '=', make_token(csound, "=")); ORCTOKEN *repeat = make_token(csound, $1->value->lexeme); ans->left = (TREE *)$1; ans->right = make_node(csound,LINE,LOCN, '/', make_leaf(csound,LINE,LOCN, $1->value->type, repeat), (TREE *)$3); //print_tree(csound, "-=", ans); $$ = ans; if (namedInstrFlag!=2) csp_orc_sa_global_read_write_add_list(csound, csp_orc_sa_globals_find(csound, ans->left), csp_orc_sa_globals_find(csound, ans->right)); } | arrayexpr '=' expr NEWLINE { TREE *ans = make_leaf(csound,LINE,LOCN, '=', (ORCTOKEN *)$2); ans->left = (TREE *)$1; ans->right = (TREE *)$3; $$ = ans; } | arrayident '=' expr NEWLINE { TREE *ans = make_leaf(csound,LINE,LOCN, '=', (ORCTOKEN *)$2); ans->left = (TREE *)$1; ans->right = (TREE *)$3; $$ = ans; } | ans opcode exprlist NEWLINE { $2->left = $1; $2->right = $3; $2->value->optype = NULL; $$ = $2; if (namedInstrFlag!=2) { csp_orc_sa_global_read_write_add_list(csound, csp_orc_sa_globals_find(csound, $2->left), csp_orc_sa_globals_find(csound, $2->right)); csp_orc_sa_interlocks(csound, $2->value); } query_deprecated_opcode(csound, $2->value); } | opcode0 exprlist NEWLINE { ((TREE *)$1)->left = NULL; ((TREE *)$1)->right = (TREE *)$2; $1->value->optype = NULL; $$ = $1; if (namedInstrFlag!=2) { csp_orc_sa_global_read_add_list(csound, csp_orc_sa_globals_find(csound, $1->right)); csp_orc_sa_interlocks(csound, $1->value); } query_deprecated_opcode(csound, $1->value); } | opcode0b exprlist ')' NEWLINE { /* VL: to allow general func ops with no answers */ ((TREE *)$1)->left = NULL; ((TREE *)$1)->right = (TREE *)$2; $1->value->optype = NULL; $$ = $1; if (namedInstrFlag!=2) { csp_orc_sa_global_read_add_list(csound, csp_orc_sa_globals_find(csound, $1->right)); csp_orc_sa_interlocks(csound, $1->value); } query_deprecated_opcode(csound, $1->value); } | LABEL_TOKEN { //printf("label %s\n", ((ORCTOKEN *)$1)->lexeme); $$ = make_leaf(csound,LINE,LOCN, LABEL_TOKEN, (ORCTOKEN *)$1); } | goto label NEWLINE { $1->left = NULL; $1->right = make_leaf(csound, LINE,LOCN, LABEL_TOKEN, (ORCTOKEN *)$2); $$ = $1; } | IF_TOKEN bexpr goto label NEWLINE { $3->left = NULL; $3->right = make_leaf(csound, LINE,LOCN, LABEL_TOKEN, (ORCTOKEN *)$4); $$ = make_node(csound,LINE,LOCN, IF_TOKEN, $2, $3); } | ifthen | UNTIL_TOKEN bexpr DO_TOKEN statementlist OD_TOKEN { if ($2) { $$ = make_leaf(csound,$2->line,$2->locn, UNTIL_TOKEN, (ORCTOKEN *)$1); $$->left = $2; $$->right = $4; } else $$ = NULL; } | WHILE_TOKEN bexpr DO_TOKEN statementlist OD_TOKEN { if ($2) { $$ = make_leaf(csound,$2->line,$2->locn, WHILE_TOKEN, (ORCTOKEN *)$1); $$->left = $2; $$->right = $4; } else $$ = NULL; } | NEWLINE { $$ = NULL; } ; ans : ident { $$ = $1; } | arrayident { $$ = $1; } | arrayexpr { $$ = $1; } | T_IDENT error { csound->Message(csound, "Unexpected untyped word %s when expecting a variable\n", ((ORCTOKEN*)$1)->lexeme); $$ = NULL; } | ans ',' ident { $$ = appendToTree(csound, $1, $3); } | ans ',' T_IDENT error { csound->Message(csound, "Unexpected untyped word %s when expecting a variable\n", ((ORCTOKEN*)$3)->lexeme); $$ = appendToTree(csound, $1, NULL); } | ans ',' arrayident { $$ = appendToTree(csound, $1, $3); } | ans ',' arrayexpr { $$ = appendToTree(csound, $1, $3); } ; arrayexpr : arrayexpr '[' iexp ']' { appendToTree(csound, $1->right, $3); $$ = $1; } | ident '[' iexp ']' { char* arrayName = $1->value->lexeme; $$ = make_node(csound, LINE, LOCN, T_ARRAY, make_leaf(csound, LINE, LOCN, T_IDENT, make_token(csound, arrayName)), $3); } ; ifthen : IF_TOKEN bexpr then NEWLINE statementlist ENDIF_TOKEN NEWLINE { if ($2) $$ = make_node(csound,$2->line, $2->locn, IF_TOKEN, $2, $3); else $$ = NULL; $3->right = $5; //print_tree(csound, "if-endif", $$); } | IF_TOKEN bexpr then NEWLINE statementlist ELSE_TOKEN statementlist ENDIF_TOKEN NEWLINE { $3->right = $5; if ($5 != NULL) $3->next = make_node(csound,$5->line, $5->locn, ELSE_TOKEN, NULL, $7); else $3->next = make_node(csound,1+($3->line),$3->locn, ELSE_TOKEN, NULL, $7); $$ = make_node(csound,$2->line, $2->locn, IF_TOKEN, $2, $3); //print_tree(csound, "if-else", $$); } | IF_TOKEN bexpr then NEWLINE statementlist elseiflist ENDIF_TOKEN NEWLINE { if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "IF-ELSEIF FOUND!\n"); $3->right = $5; $3->next = $6; $$ = make_node(csound, $2->line, $2->locn, IF_TOKEN, $2, $3); //print_tree(csound, "if-elseif\n", $$); } | IF_TOKEN bexpr then NEWLINE statementlist elseiflist ELSE_TOKEN statementlist ENDIF_TOKEN NEWLINE { TREE * tempLastNode; $3->right = $5; $3->next = $6; $$ = make_node(csound, $2->line, $2->locn, IF_TOKEN, $2, $3); tempLastNode = $$; while (tempLastNode->right!=NULL && tempLastNode->right->next!=NULL) { tempLastNode = tempLastNode->right->next; } if ($8) tempLastNode->right->next = make_node(csound, $8->line,$8->locn, ELSE_TOKEN, NULL, $8); else tempLastNode->right->next = make_node(csound, LINE,LOCN, ELSE_TOKEN, NULL, $8); //print_tree(csound, "IF TREE", $$); } ; elseiflist : elseiflist elseif { TREE * tempLastNode = $1; while (tempLastNode->right!=NULL && tempLastNode->right->next!=NULL) { tempLastNode = tempLastNode->right->next; } tempLastNode->right->next = $2; $$ = $1; } | elseif { $$ = $1; } ; elseif : ELSEIF_TOKEN bexpr then NEWLINE statementlist { if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "ELSEIF FOUND!\n"); $3->right = $5; $$ = make_node(csound,$2->line,$2->locn, ELSEIF_TOKEN, $2, $3); //print_tree(csound, "ELSEIF", $$); } ; then : THEN_TOKEN { $$ = make_leaf(csound,LINE,LOCN, THEN_TOKEN, (ORCTOKEN *)$1); } | KTHEN_TOKEN { $$ = make_leaf(csound,LINE,LOCN, KTHEN_TOKEN, (ORCTOKEN *)$1); } | ITHEN_TOKEN { $$ = make_leaf(csound,LINE,LOCN, ITHEN_TOKEN, (ORCTOKEN *)$1); } ; goto : GOTO_TOKEN { $$ = make_leaf(csound,LINE,LOCN, GOTO_TOKEN, (ORCTOKEN *)$1); } | KGOTO_TOKEN { $$ = make_leaf(csound,LINE,LOCN, KGOTO_TOKEN, (ORCTOKEN *)$1); } | IGOTO_TOKEN { $$ = make_leaf(csound,LINE,LOCN, IGOTO_TOKEN, (ORCTOKEN *)$1); } ; /* Allow all words as a label */ label : T_OPCODE { $$ = (TREE *)$1; } | T_OPCODE0 { $$ = (TREE *)$1; } | T_FUNCTION { $$ = (TREE *)$1; } | T_IDENT { $$ = (TREE *)$1; } | IF_TOKEN { $$ = (TREE *)$1; } | THEN_TOKEN { $$ = (TREE *)$1; } | ITHEN_TOKEN { $$ = (TREE *)$1; } | KTHEN_TOKEN { $$ = (TREE *)$1; } | ELSEIF_TOKEN { $$ = (TREE *)$1; } | ENDIF_TOKEN { $$ = (TREE *)$1; } | UNTIL_TOKEN { $$ = (TREE *)$1; } | DO_TOKEN { $$ = (TREE *)$1; } | OD_TOKEN { $$ = (TREE *)$1; } | INTEGER_TOKEN { $$ = (TREE *)$1; } | ENDIN_TOKEN { $$ = (TREE *)$1; } ; exprlist : exprlist ',' expr { /* $$ = make_node(',', $1, $3); */ $$ = appendToTree(csound, $1, $3); } | exprlist ',' label { /* $$ = make_node(',', $1, $3); */ $$ = appendToTree(csound, $1, make_leaf(csound, LINE,LOCN, LABEL_TOKEN, (ORCTOKEN *)$3)); } | exprlist ',' error { $$ = NULL; } | expr { $$ = $1; } | bexpr { $$ = $1; } | T_IDENT { $$ = make_leaf(csound, LINE,LOCN, LABEL_TOKEN, (ORCTOKEN *)$1); } | T_OPCODE { $$ = make_leaf(csound, LINE,LOCN, LABEL_TOKEN, (ORCTOKEN *)$1); } | T_FUNCTION { $$ = make_leaf(csound, LINE,LOCN, LABEL_TOKEN, (ORCTOKEN *)$1); } | /* null */ { $$ = NULL; } ; bexpr : '(' bexpr ')' { $$ = $2; } | expr S_LE expr { $$ = make_node(csound, LINE,LOCN, S_LE, $1, $3); } | expr S_LE error { $$ = NULL; } | expr S_GE expr { $$ = make_node(csound, LINE,LOCN, S_GE, $1, $3); } | expr S_GE error { $$ = NULL; } | expr S_NEQ expr { $$ = make_node(csound, LINE,LOCN, S_NEQ, $1, $3); } | expr S_NEQ error { $$ = NULL; } | expr S_EQ expr { $$ = make_node(csound, LINE,LOCN, S_EQ, $1, $3); } | expr S_EQ error { $$ = NULL; } | expr '=' expr { $$ = make_node(csound, LINE,LOCN, S_EQ, $1, $3); } | expr '=' error { $$ = NULL; } | expr S_GT expr { $$ = make_node(csound, LINE,LOCN, S_GT, $1, $3); } | expr S_GT error { $$ = NULL; } | expr S_LT expr { $$ = make_node(csound, LINE,LOCN, S_LT, $1, $3); } | expr S_LT error { $$ = NULL; } | bexpr S_AND bexpr { $$ = make_node(csound, LINE,LOCN, S_AND, $1, $3); } | bexpr S_AND error { $$ = NULL; } | bexpr S_OR bexpr { $$ = make_node(csound, LINE,LOCN, S_OR, $1, $3); } | bexpr S_OR error { $$ = NULL; } | '!' bexpr %prec S_UNOT { $$ = make_node(csound, LINE,LOCN, S_UNOT, $2, NULL); } | '!' error { $$ = NULL; } ; expr : bexpr '?' expr ':' expr %prec '?' { $$ = make_node(csound,LINE,LOCN, '?', $1, make_node(csound, LINE,LOCN, ':', $3, $5)); } | bexpr '?' expr ':' error { $$ = NULL; } | bexpr '?' expr error { $$ = NULL; } | bexpr '?' error { $$ = NULL; } | iexp { $$ = $1; } ; iexp : iexp '+' iexp { $$ = make_node(csound, LINE,LOCN, '+', $1, $3); } | iexp '+' error { $$ = NULL; } | iexp '-' iexp { $$ = make_node(csound ,LINE,LOCN, '-', $1, $3); } | iexp '-' error { $$ = NULL; } | '-' iexp %prec S_UMINUS { $$ = make_node(csound,LINE,LOCN, S_UMINUS, NULL, $2); } | '-' error { $$ = NULL; } | '+' iexp %prec S_UMINUS { $$ = $2; } | '+' error { $$ = NULL; } | iterm { $$ = $1; } ; iterm : iexp '*' iexp { $$ = make_node(csound, LINE,LOCN, '*', $1, $3); } | iexp '*' error { $$ = NULL; } | iexp '/' iexp { $$ = make_node(csound, LINE,LOCN, '/', $1, $3); } | iexp '/' error { $$ = NULL; } | iexp '^' iexp { $$ = make_node(csound, LINE,LOCN, '^', $1, $3); } | iexp '^' error { $$ = NULL; } | iexp '%' iexp { $$ = make_node(csound, LINE,LOCN, '%', $1, $3); } | iexp '%' error { $$ = NULL; } | ifac { $$ = $1; } ; ifac : ident { $$ = $1; } | constant { $$ = $1; } | arrayexpr { $$ = $1; } | iexp '|' iexp { $$ = make_node(csound, LINE,LOCN, '|', $1, $3); } | iexp '|' error { $$ = NULL; } | iexp '&' iexp { $$ = make_node(csound, LINE,LOCN, '&', $1, $3); } | iexp '&' error { $$ = NULL; } | iexp '#' iexp { $$ = make_node(csound, LINE,LOCN, '#', $1, $3); } | iexp '#' error { $$ = NULL; } | iexp S_BITSHIFT_LEFT iexp { $$ = make_node(csound, LINE,LOCN, S_BITSHIFT_LEFT, $1, $3); } | iexp S_BITSHIFT_LEFT error { $$ = NULL; } | iexp S_BITSHIFT_RIGHT iexp { $$ = make_node(csound, LINE,LOCN, S_BITSHIFT_RIGHT, $1, $3); } | iexp S_BITSHIFT_RIGHT error { $$ = NULL; } | '~' iexp %prec S_UMINUS { $$ = make_node(csound, LINE,LOCN, '~', NULL, $2);} | '~' error { $$ = NULL; } | '(' expr ')' { $$ = $2; } | '(' expr error { $$ = NULL; } | '(' error { $$ = NULL; } | opcode exprlist ')' { $1->left = NULL; $1->right = $2; $1->type = T_FUNCTION; $$ = $1; } | opcode ':' opcodeb exprlist ')' /* needed because a & k are opcodes */ { $1->left = NULL; $1->right = $4; $1->type = T_FUNCTION; $1->value->optype = $3->value->lexeme; $$ = $1; } | opcodeb exprlist ')' { $1->left = NULL; $1->right = $2; $1->type = T_FUNCTION; $1->value->optype = NULL; $$ = $1; //print_tree(csound, "FUNCTION CALL", $$); } | identb error { $$ = NULL; } | opcodeb error { $$ = NULL; } ; rident : SRATE_TOKEN { $$ = make_leaf(csound, LINE,LOCN, SRATE_TOKEN, (ORCTOKEN *)$1); } | KRATE_TOKEN { $$ = make_leaf(csound, LINE,LOCN, KRATE_TOKEN, (ORCTOKEN *)$1); } | KSMPS_TOKEN { $$ = make_leaf(csound, LINE,LOCN, KSMPS_TOKEN, (ORCTOKEN *)$1); } | NCHNLS_TOKEN { $$ = make_leaf(csound, LINE,LOCN, NCHNLS_TOKEN, (ORCTOKEN *)$1); } | NCHNLSI_TOKEN { $$ = make_leaf(csound, LINE,LOCN, NCHNLSI_TOKEN, (ORCTOKEN *)$1); } | ZERODBFS_TOKEN { $$ = make_leaf(csound, LINE,LOCN, ZERODBFS_TOKEN, (ORCTOKEN *)$1); } | A4_TOKEN { $$ = make_leaf(csound, LINE,LOCN, A4_TOKEN, (ORCTOKEN *)$1); } ; arrayident: arrayident '[' ']' { appendToTree(csound, $1->right, make_leaf(csound, LINE, LOCN, '[', make_token(csound, "["))); $$ = $1; } | ident '[' ']' { $$ = make_leaf(csound, LINE, LOCN, T_ARRAY_IDENT, make_token(csound, $1->value->lexeme)); $$->right = make_leaf(csound, LINE, LOCN, '[', make_token(csound, "[")); }; ident : T_IDENT { $$ = make_leaf(csound, LINE,LOCN, T_IDENT, (ORCTOKEN *)$1); } identb : T_IDENTB { $$ = make_leaf(csound, LINE,LOCN, T_IDENT, (ORCTOKEN *)$1); } constant : INTEGER_TOKEN { $$ = make_leaf(csound, LINE,LOCN, INTEGER_TOKEN, (ORCTOKEN *)$1); } | NUMBER_TOKEN { $$ = make_leaf(csound, LINE,LOCN, NUMBER_TOKEN, (ORCTOKEN *)$1); } | STRING_TOKEN { $$ = make_leaf(csound, LINE,LOCN, STRING_TOKEN, (ORCTOKEN *)$1); } | SRATE_TOKEN { $$ = make_leaf(csound, LINE,LOCN, SRATE_TOKEN, (ORCTOKEN *)$1); } | KRATE_TOKEN { $$ = make_leaf(csound, LINE,LOCN, KRATE_TOKEN, (ORCTOKEN *)$1); } | KSMPS_TOKEN { $$ = make_leaf(csound, LINE,LOCN, KSMPS_TOKEN, (ORCTOKEN *)$1); } | NCHNLS_TOKEN { $$ = make_leaf(csound, LINE,LOCN, NCHNLS_TOKEN, (ORCTOKEN *)$1); } | NCHNLSI_TOKEN { $$ = make_leaf(csound, LINE,LOCN, NCHNLSI_TOKEN, (ORCTOKEN *)$1); } | ZERODBFS_TOKEN { $$ = make_leaf(csound, LINE,LOCN, ZERODBFS_TOKEN, (ORCTOKEN *)$1); } | A4_TOKEN { $$ = make_leaf(csound, LINE,LOCN, A4_TOKEN, (ORCTOKEN *)$1); } ; opcode0 : T_OPCODE0 { if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "opcode0 $1=%p (%s)\n", $1,((ORCTOKEN *)$1)->lexeme ); $$ = make_leaf(csound,LINE,LOCN, T_OPCODE0, (ORCTOKEN *)$1); } ; opcode0b : T_OPCODE0B { if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "opcode0b $1=%p (%s)\n", $1,((ORCTOKEN *)$1)->lexeme ); $$ = make_leaf(csound,LINE,LOCN, T_OPCODE0, (ORCTOKEN *)$1); } ; opcode : T_OPCODE { $$ = make_leaf(csound,LINE,LOCN, T_OPCODE, (ORCTOKEN *)$1); } | T_FUNCTION { $$ = make_leaf(csound,LINE,LOCN, T_OPCODE, (ORCTOKEN *)$1); } ; opcodeb : T_OPCODEB { $$ = make_leaf(csound,LINE,LOCN, T_OPCODE, (ORCTOKEN *)$1); } | T_FUNCTIONB { $$ = make_leaf(csound,LINE,LOCN, T_OPCODE, (ORCTOKEN *)$1); } ; %% #ifdef SOME_FINE_DAY void yyerror(char *s, ...) { va_list ap; va_start(ap, s); if (yylloc.first_line) fprintf(stderr, "%d.%d-%d.%d: error: ", yylloc.first_line, yylloc.first_column, yylloc.last_line, yylloc.last_column); vfprintf(stderr, s, ap); fprintf(stderr, "\n"); } void lyyerror(YYLTYPE t, char *s, ...) { va_list ap; va_start(ap, s); if (t.first_line) fprintf(stderr, "%d.%d-%d.%d: error: ", t.first_line, t.first_column, t.last_line, t.last_column); vfprintf(stderr, s, ap); fprintf(stderr, "\n"); } #endif csound-6.10.0/Engine/csound_orc_compile.c000066400000000000000000002307751321653344700203360ustar00rootroot00000000000000/* csound_orc_compile.c: (Based on otran.c) Copyright (C) 1991, 1997, 2003, 2006, 2012 Barry Vercoe, John ffitch, Steven Yi, Victor Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "parse_param.h" #include "csound_orc.h" #include #include #include #include "oload.h" #include "insert.h" #include "pstream.h" //#include "typetabl.h" #include "csound_standard_types.h" #include "csound_orc_semantics.h" static const char* INSTR_NAME_FIRST = "::^inm_first^::"; static ARG* createArg(CSOUND *csound, INSTRTXT* ip, char *s, ENGINE_STATE *engineState); static void insprep(CSOUND *, INSTRTXT *, ENGINE_STATE *engineState); static void lgbuild(CSOUND *, INSTRTXT *, char *, int inarg, ENGINE_STATE *engineState); int pnum(char *s) ; static void unquote_string(char *, const char *); void print_tree(CSOUND *, char *, TREE *); void close_instrument(CSOUND *csound, ENGINE_STATE *engineState, INSTRTXT * ip); char argtyp2(char *s); void debugPrintCsound(CSOUND* csound); void named_instr_assign_numbers(CSOUND *csound, ENGINE_STATE *engineState); int named_instr_alloc(CSOUND *csound, char *s, INSTRTXT *ip, int32 insno, ENGINE_STATE *engineState, int merge); int check_instr_name(char *s); void free_instr_var_memory(CSOUND*, INSDS*); void mergeState_enqueue(CSOUND *csound, ENGINE_STATE *e, TYPE_TABLE* t, OPDS *ids); extern const char* SYNTHESIZED_ARG; #ifdef FLOAT_COMPARE #undef FLOAT_COMPARE #endif #ifdef USE_DOUBLE #define FLOAT_COMPARE(x,y) (fabs((double) (x) / (double) (y) - 1.0) > 1.0e-12) #else #define FLOAT_COMPARE(x,y) (fabs((double) (x) / (double) (y) - 1.0) > 5.0e-7) #endif /* ------------------------------------------------------------------------ */ char* strsav_string(CSOUND* csound, ENGINE_STATE* engineState, char* key) { char* retVal = cs_hash_table_get_key(csound, csound->engineState.stringPool, key); if (retVal == NULL) { //printf("strsav_string: %s\n", key); retVal = cs_hash_table_put_key(csound, engineState->stringPool, key); } return retVal; } int pnum(char *s) /* check a char string for pnum format */ /* and return the pnum ( >= 0 ) */ { /* else return -1 */ int n; if (*s == 'p' || *s == 'P') if (sscanf(++s, "%d", &n)) return(n); return(-1); } #if 0 static int argCount(ARG* arg) { int retVal = -1; if (arg != NULL) { retVal = 0; while (arg != NULL) { arg = arg->next; retVal++; } } return retVal; } #endif /* get size of string in MYFLT units */ /*static inline int strlen_to_samples(const char *s) { int n = (int) strlen(s); n = (n + (int) sizeof(MYFLT)) / (int) sizeof(MYFLT); return n; } */ /* convert string constant */ void unquote_string(char *dst, const char *src) { int i, j, n = (int) strlen(src) - 1; for (i = 1, j = 0; i < n; i++) { //printf("char - %c\n", src[i]); if (src[i] != '\\') dst[j++] = src[i]; else { //printf("char-- - %c\n", src[i]); switch (src[++i]) { case 'a': dst[j++] = '\a'; break; case 'b': dst[j++] = '\b'; break; case 'f': dst[j++] = '\f'; break; case 'n': dst[j++] = '\n'; break; case 'r': dst[j++] = '\r'; break; case 't': dst[j++] = '\t'; break; case 'v': dst[j++] = '\v'; break; case '"': dst[j++] = '"'; break; case '\\': dst[j++] = '\\'; /*printf("char-- + %c\n", src[i]);*/ break; default: //printf("char-- ++ %c\n", src[i]); if (src[i] >= '0' && src[i] <= '7') { int k = 0, l = (int) src[i] - '0'; while (++k < 3 && src[i + 1] >= '0' && src[i + 1] <= '7') l = (l << 3) | ((int) src[++i] - '0'); dst[j++] = (char) l; } else { dst[j++] = '\\'; i--; } } } } dst[j] = '\0'; } int tree_arg_list_count(TREE * root) { int count = 0; TREE * current = root; while (current != NULL) { current = current->next; count++; } return count; } /** * Returns last OPTXT of OPTXT chain optxt */ static OPTXT * last_optxt(OPTXT *optxt) { OPTXT *current = optxt; while (current->nxtop != NULL) { current = current->nxtop; } return current; } /** * Append OPTXT op2 to end of OPTXT chain op1 */ /* static inline void append_optxt(OPTXT *op1, OPTXT *op2) { last_optxt(op1)->nxtop = op2; } */ /** Counts number of args in argString, taking into account array identifiers */ int argsRequired(char* argString) { int retVal = 0; char* t = argString; if (t != NULL) { while (*t != '\0') { retVal++; t++; while (*t == '[') { t++; if (*t != ']') { // ERROR HERE, unmatched array identifier, perhaps should report... return -1; } t++; } } } return retVal; } /** Splits args in argString into char**, taking into account array identifiers */ char** splitArgs(CSOUND* csound, char* argString) { int argCount = argsRequired(argString); char** args = csound->Malloc(csound, sizeof(char*) * (argCount + 1)); // printf("alloc %p \n", args); char* t = argString; int i = 0; if (t != NULL) { while (*t != '\0' ) { char* part; int dimensions = 0; if (*(t + 1) == '[') { char* start = t; int len = 1; int j; t++; while (*t == '[') { t++; len++; if (UNLIKELY(*t != ']')) { // FIXME: needs more precise error information csound->Message(csound, Str("ERROR: Unmatched bracket found in array" "argument type specification\n")); return NULL; } t++; len++; dimensions++; } part = csound->Malloc(csound, sizeof(char) * (dimensions + 3)); //printf("alloc %p \n", part); part[dimensions + 2] = '\0'; part[dimensions + 1] = ']'; part[dimensions] = *start; for (j = 0; j < dimensions; j++) { part[j] = '['; } } else { part = csound->Malloc(csound, sizeof(char) * 2); //printf("alloc %p \n", part); part[0] = *t; part[1] = '\0'; t++; } args[i] = part; i++; } } args[argCount] = NULL; return args; } OENTRY* find_opcode(CSOUND*, char*); /** * Create an Opcode (OPTXT) from the AST node given for a given engineState */ OPTXT *create_opcode(CSOUND *csound, TREE *root, INSTRTXT *ip, ENGINE_STATE *engineState) { TEXT *tp; TREE *inargs, *outargs; OPTXT *optxt; char *arg; int n;// nreqd; optxt = (OPTXT *) csound->Calloc(csound, (int32)sizeof(OPTXT)); tp = &(optxt->t); OENTRY* labelOpcode; switch(root->type) { case LABEL_TOKEN: labelOpcode = find_opcode(csound, "$label"); /* TODO - Need to verify here or elsewhere that this label is not already defined */ tp->oentry = labelOpcode; tp->opcod = strsav_string(csound, engineState, root->value->lexeme); tp->outlist = (ARGLST *) csound->Malloc(csound, sizeof(ARGLST)); tp->outlist->count = 0; tp->inlist = (ARGLST *) csound->Malloc(csound, sizeof(ARGLST)); tp->inlist->count = 0; ip->mdepends |= labelOpcode->flags; ip->opdstot += labelOpcode->dsblksiz; break; case '=': case GOTO_TOKEN: case IGOTO_TOKEN: case KGOTO_TOKEN: case T_OPCODE: case T_OPCODE0: if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "create_opcode: Found node for opcode %s\n", root->value->lexeme); // FIXME THIS RESULT IS NOT USED -- VL I don't think it's needed //nreqd = tree_arg_list_count(root->left); /* outcount */ /* replace opcode if needed */ /* INITIAL SETUP */ tp->oentry = (OENTRY*)root->markup; tp->opcod = strsav_string(csound, engineState, tp->oentry->opname); tp->linenum = root->line; ip->mdepends |= tp->oentry->flags; ip->opdstot += tp->oentry->dsblksiz; /* BUILD ARG LISTS */ { int incount = tree_arg_list_count(root->right); int outcount = tree_arg_list_count(root->left); int argcount = 0; size_t m = sizeof(ARGLST) + (incount - 1) * sizeof(char*); tp->inlist = (ARGLST*) csound->ReAlloc(csound, tp->inlist, m); tp->inlist->count = incount; m = sizeof(ARGLST) + (outcount - 1) * sizeof(char*); tp->outlist = (ARGLST*) csound->ReAlloc(csound, tp->outlist, m); tp->outlist->count = outcount; tp->inArgCount = 0; for (inargs = root->right; inargs != NULL; inargs = inargs->next) { /* INARGS */ arg = inargs->value->lexeme; //printf("arg: %s \n", arg); tp->inlist->arg[argcount++] = strsav_string(csound, engineState, arg); if ((n = pnum(arg)) >= 0) { if (n > ip->pmax) ip->pmax = n; } /* VL 14/12/11 : calling lgbuild here seems to be problematic for undef arg checks */ else { lgbuild(csound, ip, arg, 1, engineState); } if (inargs->markup != &SYNTHESIZED_ARG) { tp->inArgCount++; } } } /* VERIFY ARG LISTS MATCH OPCODE EXPECTED TYPES */ { OENTRY *ep = tp->oentry; int argcount = 0; for (outargs = root->left; outargs != NULL; outargs = outargs->next) { arg = outargs->value->lexeme; tp->outlist->arg[argcount++] = strsav_string(csound, engineState, arg); } tp->outArgCount = 0; /* OUTARGS */ for (outargs = root->left; outargs != NULL; outargs = outargs->next) { arg = outargs->value->lexeme; if ((n = pnum(arg)) >= 0) { if (n > ip->pmax) ip->pmax = n; } else { csound->DebugMsg(csound, "Arg: %s\n", arg); lgbuild(csound, ip, arg, 0, engineState); } tp->outArgCount++; } if (root->right != NULL) { if (ep->intypes[0] != 'l') { /* intype defined by 1st inarg */ tp->intype = argtyp2( tp->inlist->arg[0]); } else { tp->intype = 'l'; /* (unless label) */ } } if (root->left != NULL) { /* pftype defined by outarg */ tp->pftype = argtyp2( root->left->value->lexeme); } else { /* else by 1st inarg */ tp->pftype = tp->intype; } } break; default: csound->Message(csound, Str("create_opcode: No rule to handle statement of " "type %d\n"), root->type); if (PARSER_DEBUG) print_tree(csound, NULL, root); } return optxt; } /** * Add a global variable and allocate memory * Globals, unlike locals, keep their memory space * in separate blocks, pointed by var->memBlock */ void addGlobalVariable(CSOUND *csound, ENGINE_STATE *engineState, CS_TYPE* type, char *name, void *typeArg) { CS_VARIABLE *var = csoundCreateVariable(csound, csound->typePool, type, name, typeArg); size_t memSize = CS_VAR_TYPE_OFFSET + var->memBlockSize; CS_VAR_MEM *varMem = csound->Malloc(csound, memSize); csoundAddVariable(csound, engineState->varPool, var); varMem->varType = var->varType; var->memBlock = varMem; if (var->initializeVariableMemory != NULL) { var->initializeVariableMemory((void *)csound, var, &varMem->value); } } void* find_or_add_constant(CSOUND* csound, CS_HASH_TABLE* constantsPool, const char* name, MYFLT value) { void* retVal = cs_hash_table_get(csound, constantsPool, (char *) name); if (retVal == NULL) { CS_VAR_MEM *memValue = csound->Calloc(csound, sizeof(CS_VAR_MEM)); memValue->varType = (CS_TYPE*)&CS_VAR_TYPE_C; memValue->value = value; cs_hash_table_put(csound, constantsPool, (char *) name, memValue); retVal = cs_hash_table_get(csound, constantsPool, (char *) name); } return retVal; } /** * NB - instr0 to be created only once, in the first compilation * and stored in csound->instr0 * Create an Instrument (INSTRTXT) from the AST node given for use as * Instrument0. Called from csound_orc_compile. */ INSTRTXT *create_instrument0(CSOUND *csound, TREE *root, ENGINE_STATE *engineState, CS_VAR_POOL* varPool) { INSTRTXT *ip; OPTXT *op; TREE *current; MYFLT sr= FL(-1.0), kr= FL(-1.0), ksmps= FL(-1.0), nchnls= DFLT_NCHNLS, inchnls = FL(0.0), _0dbfs= FL(-1.0); int krdef = 0; //, ksmpsdef = 0, srdef = 0; double A4 = 0.0; CS_TYPE* rType = (CS_TYPE*)&CS_VAR_TYPE_R; addGlobalVariable(csound, engineState, rType, "sr", NULL); addGlobalVariable(csound, engineState, rType, "kr", NULL); addGlobalVariable(csound, engineState, rType, "ksmps", NULL); addGlobalVariable(csound, engineState, rType, "nchnls", NULL); addGlobalVariable(csound, engineState, rType, "nchnls_i", NULL); addGlobalVariable(csound, engineState, rType, "0dbfs", NULL); addGlobalVariable(csound, engineState, rType, "A4", NULL); addGlobalVariable(csound, engineState, rType, "$sr", NULL); addGlobalVariable(csound, engineState, rType, "$kr", NULL); addGlobalVariable(csound, engineState, rType, "$ksmps", NULL); find_or_add_constant(csound, engineState->constantsPool, "0", 0.0); ip = (INSTRTXT *) csound->Calloc(csound, sizeof(INSTRTXT)); ip->varPool = varPool; op = (OPTXT *)ip; current = root; /* initialize */ ip->mdepends = 0; ip->opdstot = 0; ip->nocheckpcnt = 0; ip->pmax = 3L; /* start chain */ ip->t.oentry = find_opcode(csound, "instr"); /* to hold global assigns */ ip->t.opcod = strsav_string(csound, engineState, "instr"); /* The following differs from otran and needs review. otran keeps a * nulllist to point to for empty lists, while this is creating a new list * regardless */ ip->t.outlist = (ARGLST *) csound->Malloc(csound, sizeof(ARGLST)); ip->t.outlist->count = 0; ip->t.inlist = (ARGLST *) csound->Malloc(csound, sizeof(ARGLST)); ip->t.inlist->count = 1; ip->t.inlist->arg[0] = strsav_string(csound, engineState, "0"); while (current != NULL) { unsigned int uval; if (current->type != INSTR_TOKEN && current->type != UDO_TOKEN) { OENTRY* oentry = (OENTRY*)current->markup; if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "In INSTR 0: %s\n", current->value->lexeme); if (current->type == '=' && strcmp(oentry->opname, "=.r") == 0) { //FIXME - perhaps should add check as it was in //constndx? Not sure if necessary due to assumption //that tree will be verified MYFLT val = (MYFLT) cs_strtod(current->right->value->lexeme, NULL); // systems constants get set here and are not // compiled into i-time code find_or_add_constant(csound, csound->engineState.constantsPool, (const char*) current->right->value->lexeme, val); /* modify otran defaults*/ /* removed assignments to csound->tran_* */ if (current->left->type == SRATE_TOKEN) { sr = val; //srdef = 1; } else if (current->left->type == KRATE_TOKEN) { kr = val; krdef = 1; } else if (current->left->type == KSMPS_TOKEN) { uval = (val<=0 ? 1u : (unsigned int)val); ksmps = uval; //ksmpsdef = 1; } else if (current->left->type == NCHNLS_TOKEN) { uval = (val<=0 ? 1u : (unsigned int)val); nchnls = uval; } else if (current->left->type == NCHNLSI_TOKEN) { uval = (val<=0 ? 1u : (unsigned int)val); inchnls = uval; } else if (current->left->type == ZERODBFS_TOKEN) { _0dbfs = val; } else if (current->left->type == A4_TOKEN) { A4 = val; } } else { op->nxtop = create_opcode(csound, current, ip, engineState); op = last_optxt(op); } } current = current->next; } /* Deal with defaults and consistency */ if (ksmps == FL(-1.0)) { if (sr == FL(-1.0)) sr = DFLT_SR; if (kr == FL(-1.0)) kr = DFLT_KR; ksmps = (MYFLT) ((int) (sr/kr + FL(0.5))); kr = sr/ksmps; /* VL - avoid inconsistency */ } else if (kr == FL(-1.0)) { if (sr == FL(-1.0)) sr = DFLT_SR; kr = sr/ksmps; } else if (sr == FL(-1.0)) { sr = kr*ksmps; } /* That deals with missing values, however we do need ksmps to be integer */ { CSOUND *p = (CSOUND*) csound; char err_msg[128]; CS_SPRINTF(err_msg, "sr = %.7g, kr = %.7g, ksmps = %.7g\nerror:", sr, kr, ksmps); if (UNLIKELY(sr <= FL(0.0))) synterr(p, Str("%s invalid sample rate"), err_msg); if (UNLIKELY(kr <= FL(0.0))) synterr(p, Str("%s invalid control rate"), err_msg); if (UNLIKELY(ksmps <= FL(0.0))) synterr(p, Str("%s invalid number of samples"), err_msg); else if (UNLIKELY(ksmps < FL(0.75) || FLOAT_COMPARE(ksmps, MYFLT2LRND(ksmps)))) synterr(p, Str("%s invalid ksmps value"), err_msg); else if (UNLIKELY(FLOAT_COMPARE(sr,(double)kr *ksmps))) synterr(p, Str("%s inconsistent sr, kr, ksmps\n"), err_msg); else if (UNLIKELY(ksmps > sr)) synterr(p, Str("%s inconsistent sr, kr, ksmps \n"), err_msg); } csound->ksmps = ksmps; csound->nchnls = nchnls; if (inchnls==0) csound->inchnls = nchnls; else csound->inchnls = inchnls; csound->esr = sr; csound->ekr = kr; if (_0dbfs < 0) csound->e0dbfs = DFLT_DBFS; else csound->e0dbfs = _0dbfs; if (A4 == 0) csound->A4 = 440.0; else { extern void csound_aops_init_tables(CSOUND *); csound->A4 = A4; csound_aops_init_tables(csound); } if (UNLIKELY(csound->e0dbfs <= FL(0.0))) { csound->Warning(csound, Str("bad value for 0dbfs: must be positive. " "Setting default value.")); csound->e0dbfs = DFLT_DBFS; } OPARMS *O = csound->oparms; if (O->nchnls_override > 0) csound->nchnls = csound->inchnls = O->nchnls_override; if (O->nchnls_i_override > 0) csound->inchnls = O->nchnls_i_override; if (O->e0dbfs_override > 0) csound->e0dbfs = O->e0dbfs_override; if (UNLIKELY(O->odebug)) csound->Message(csound, "esr = %7.1f, ekr = %7.1f, ksmps = %d, nchnls = %d " "0dbfs = %.1f\n", csound->esr, csound->ekr, csound->ksmps, csound->nchnls, csound->e0dbfs); if (O->sr_override || O->kr_override || O->ksmps_override) { /* if command-line overrides, apply now */ MYFLT ensmps; if (!O->ksmps_override) { csound->esr = (MYFLT) (O->sr_override ? O->sr_override : csound->esr); if (krdef) { csound->ekr = (MYFLT) (O->kr_override ? O->kr_override : csound->ekr); csound->ksmps = (int) ((ensmps = ((MYFLT) csound->esr / (MYFLT) csound->ekr)) + FL(0.5)); } else { csound->ekr = csound->esr / csound->ksmps; ensmps = csound->ksmps; } } else { csound->ksmps = (ensmps = O->ksmps_override); if (O->sr_override) { csound->ekr = O->sr_override / csound->ksmps; csound->esr = O->sr_override; } else if (O->kr_override) { csound->esr = O->kr_override * csound->ksmps; csound->ekr = O->kr_override; } else { csound->ekr = csound->esr / csound->ksmps; } } /* chk consistency one more time */ { char s[256]; CS_SPRINTF(s, Str("sr = %.7g, kr = %.7g, ksmps = %.7g\nerror:"), csound->esr, csound->ekr, ensmps); if (UNLIKELY(csound->ksmps < 1 || FLOAT_COMPARE(ensmps, csound->ksmps))) csoundDie(csound, Str("%s invalid ksmps value"), s); if (UNLIKELY(csound->esr <= FL(0.0))) csoundDie(csound, Str("%s invalid sample rate"), s); if (UNLIKELY(csound->ekr <= FL(0.0))) csoundDie(csound, Str("%s invalid control rate"), s); if (UNLIKELY(FLOAT_COMPARE(csound->esr, (double) csound->ekr * ensmps))) csoundDie(csound, Str("%s inconsistent sr, kr, ksmps"), s); } csound->Message(csound, Str("sample rate overrides: " "esr = %7.4f, ekr = %7.4f, ksmps = %d\n"), csound->esr, csound->ekr, csound->ksmps); } csound->tpidsr = TWOPI_F / csound->esr; /* now set internal */ csound->mtpdsr = -(csound->tpidsr); /* consts */ csound->pidsr = PI_F / csound->esr; csound->mpidsr = -(csound->pidsr); csound->onedksmps = FL(1.0) / (MYFLT) csound->ksmps; csound->sicvt = FMAXLEN / csound->esr; csound->kicvt = FMAXLEN / csound->ekr; csound->onedsr = FL(1.0) / csound->esr; csound->onedkr = FL(1.0) / csound->ekr; csound->global_kcounter = csound->kcounter; if (csound->ksmps != DFLT_KSMPS) { reallocateVarPoolMemory(csound, engineState->varPool); //csound->Message(csound, "recalculate varpool\n"); } close_instrument(csound, engineState, ip); return ip; } /** This global instrument replaces instr 0 in subsequent compilations. It does not allow the setting of system parameters such as ksmps etc, but it allows i-time code to be compiled and run. **/ INSTRTXT *create_global_instrument(CSOUND *csound, TREE *root, ENGINE_STATE *engineState, CS_VAR_POOL* varPool) { INSTRTXT *ip; OPTXT *op; TREE *current; //csound->inZero = 1; find_or_add_constant(csound, engineState->constantsPool, "0", 0); ip = (INSTRTXT *) csound->Calloc(csound, sizeof(INSTRTXT)); ip->varPool = varPool; op = (OPTXT *)ip; current = root; /* initialize */ ip->mdepends = 0; ip->opdstot = 0; ip->pmax = 3L; /* start chain */ ip->t.oentry = find_opcode(csound, "instr"); /* to hold global assigns */ ip->t.opcod = strsav_string(csound, engineState, "instr"); /* The following differs from otran and needs review. otran keeps a * nulllist to point to for empty lists, while this is creating a new list * regardless */ ip->t.outlist = (ARGLST *) csound->Malloc(csound, sizeof(ARGLST)); ip->t.outlist->count = 0; ip->t.inlist = (ARGLST *) csound->Malloc(csound, sizeof(ARGLST)); ip->t.inlist->count = 1; ip->t.inlist->arg[0] = strsav_string(csound, engineState, "0"); while (current != NULL) { if (current->type != INSTR_TOKEN && current->type != UDO_TOKEN) { OENTRY* oentry = (OENTRY*)current->markup; if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "In INSTR GLOBAL: %s\n", current->value->lexeme); if (UNLIKELY(current->type == '=' && strcmp(oentry->opname, "=.r") == 0)) csound->Warning(csound, Str("system constants can only be set once\n")); else { op->nxtop = create_opcode(csound, current, ip, engineState); op = last_optxt(op); } } current = current->next; } close_instrument(csound, engineState, ip); //csound->inZero = 0; return ip; } int tree_contains_fn_p(CSOUND *csound, TREE* t) { //print_tree(csound, "\ntree_contains_fn_p", t); while (t!=NULL) { if (t->type == T_OPCODE && strcmp(t->value->lexeme, "p")==0) return 1; if (t->left && tree_contains_fn_p(csound, t->left)) return 1; if (t->right && tree_contains_fn_p(csound, t->right)) return 1; t = t->next; } return 0; } /** * Create an Instrument (INSTRTXT) from the AST node given. Called from * csound_orc_compile. */ INSTRTXT *create_instrument(CSOUND *csound, TREE *root, ENGINE_STATE *engineState) { INSTRTXT *ip; OPTXT *op; char *c; TREE *statements, *current; ip = (INSTRTXT *) csound->Calloc(csound, sizeof(INSTRTXT)); ip->varPool = (CS_VAR_POOL*)root->markup; op = (OPTXT *)ip; statements = root->right; ip->mdepends = 0; ip->opdstot = 0; ip->nocheckpcnt = tree_contains_fn_p(csound, root->right); ip->pmax = 3L; /* Initialize */ ip->t.oentry = find_opcode(csound, "instr"); /* to hold global assigns */ ip->t.opcod = strsav_string(csound, engineState, "instr"); /* The following differs from otran and needs review. otran keeps a * nulllist to point to for empty lists, while this is creating a new list * regardless */ ip->t.outlist = (ARGLST *) csound->Malloc(csound, sizeof(ARGLST)); ip->t.outlist->count = 0; ip->t.inlist = (ARGLST *) csound->Malloc(csound, sizeof(ARGLST)); ip->t.inlist->count = 1; /* create local ksmps variable */ CS_TYPE* rType = (CS_TYPE*)&CS_VAR_TYPE_R; CS_VARIABLE *var = csoundCreateVariable(csound, csound->typePool, rType, "ksmps", NULL); csoundAddVariable(csound, ip->varPool, var); /* same for kr */ var = csoundCreateVariable(csound, csound->typePool, rType, "kr", NULL); csoundAddVariable(csound, ip->varPool, var); /* Maybe should do this assignment at end when instr is setup? * Note: look into how "instr 4,5,6,8" is handled, i.e. if copies * are made or if they are all set to point to the same INSTRTXT * * Note2: For now am not checking if root->left is a list (i.e. checking * root->left->next is NULL or not to indicate list) */ if (root->left->type == INTEGER_TOKEN) { /* numbered instrument */ int32 instrNum = (int32)root->left->value->value; /* Not used! */ c = csound->Malloc(csound, 10); /* arbritrarily chosen number of digits */ snprintf(c, 10, "%ld", (long)instrNum); if (PARSER_DEBUG) csound->Message(csound, Str("create_instrument: instr num %d\n"), instrNum); ip->t.inlist->arg[0] = strsav_string(csound, engineState, c); csound->Free(csound, c); } else if (root->left->type == T_IDENT && !(root->left->left != NULL && root->left->left->type == UDO_ANS_TOKEN)) { /* named instrument */ int32 insno_priority = -1L; c = root->left->value->lexeme; if (PARSER_DEBUG) csound->Message(csound, "create_instrument: instr name %s\n", c); if (UNLIKELY(root->left->rate == (int) '+')) { insno_priority--; } ip->insname = csound->Malloc(csound, strlen(c) + 1); strcpy(ip->insname, c); } current = statements; while (current != NULL) { OPTXT * optxt = create_opcode(csound, current, ip, engineState); op->nxtop = optxt; op = last_optxt(op); current = current->next; } close_instrument(csound, engineState, ip); return ip; } void close_instrument(CSOUND *csound, ENGINE_STATE* engineState, INSTRTXT * ip) { OPTXT * bp, *current; int n; bp = (OPTXT *) csound->Calloc(csound, (int32)sizeof(OPTXT)); bp->t.oentry = find_opcode(csound, "endin"); /* send an endin to */ bp->t.opcod = strsav_string(csound, engineState, "endin"); /* term instr 0 blk */ bp->t.outlist = bp->t.inlist = NULL; bp->nxtop = NULL; /* terminate the optxt chain */ current = (OPTXT *)ip; while (current->nxtop != NULL) { current = current->nxtop; } current->nxtop = bp; ip->pextrab = ((n = ip->pmax - 3L) > 0 ? (int) n * sizeof(MYFLT) : 0); ip->pextrab = ((int) ip->pextrab + 7) & (~7); ip->muted = 1; } void deleteVarPoolMemory(void* csound, CS_VAR_POOL* pool); /** This function deletes an inactive instrument which has been replaced */ void free_instrtxt(CSOUND *csound, INSTRTXT *instrtxt) { INSTRTXT *ip = instrtxt; INSDS *active = ip->instance; while (active != NULL) { /* remove instance memory */ INSDS *nxt = active->nxtinstance; if (active->fdchp != NULL) fdchclose(csound, active); if (active->auxchp != NULL) auxchfree(csound, active); free_instr_var_memory(csound, active); if (active->opcod_iobufs != NULL) csound->Free(csound, active->opcod_iobufs); csound->Free(csound, active); active = nxt; } OPTXT *t = ip->nxtop; while (t) { OPTXT *s = t->nxtop; TEXT *ttp = &t->t; //printf("%s \n", ttp->opcod); ARG* current = ttp->outArgs; while (current != NULL) { ARG *tmp = current; //printf("delete %p \n", tmp); current = current->next; csound->Free(csound, tmp); } csound->Free(csound, t->t.outlist); current = ttp->inArgs; while (current != NULL) { ARG *tmp = current; //printf("delete %p \n", tmp); current = current->next; csound->Free(csound, tmp); } csound->Free(csound, t->t.inlist); csound->Free(csound, t); t = s; } csound->Free(csound, ip->t.outlist); csound->Free(csound, ip->t.inlist); CS_VARIABLE *var = ip->varPool->head; while (var != NULL) { CS_VARIABLE *tmp = var; var = var->next; csound->Free(csound, tmp->varName); } csoundFreeVarPool(csound, ip->varPool); csound->Free(csound, ip); if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, Str("-- deleted instr from deadpool \n")); } /** * This function has two purposes: * 1) check deadpool for active instances, and * if none is active, send it to be deleted * 2) add a dead instr to deadpool (because it still has active instances) */ void add_to_deadpool(CSOUND *csound, INSTRTXT *instrtxt) { /* check current items in deadpool to see if they need deleting */ int i; for (i=0; i < csound->dead_instr_no; i++) { if (csound->dead_instr_pool[i] != NULL) { INSDS *active = csound->dead_instr_pool[i]->instance; while (active != NULL) { if (active->actflg) { // add_to_deadpool(csound,csound->dead_instr_pool[i]); break; } active = active->nxtinstance; } /* no active instances */ if (active == NULL) { if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, Str(" -- free instr def %p %p \n"), csound->dead_instr_pool[i]->instance, csound->dead_instr_pool[i]); free_instrtxt(csound, csound->dead_instr_pool[i]); csound->dead_instr_pool[i] = NULL; } } } /* add latest instr to deadpool */ /* check for free slots */ for (i=0; i < csound->dead_instr_no; i++) { if (csound->dead_instr_pool[i] == NULL) { csound->dead_instr_pool[i] = instrtxt; if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, Str(" -- added to deadpool slot %d \n"), i); return; } } /* no free slots, expand pool */ csound->dead_instr_pool = (INSTRTXT**) csound->ReAlloc(csound, csound->dead_instr_pool, ++csound->dead_instr_no * sizeof(INSTRTXT*)); csound->dead_instr_pool[csound->dead_instr_no-1] = instrtxt; if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, Str(" -- added to deadpool slot %d \n"), csound->dead_instr_no-1); } /** allocate entry for named instrument ip with name s instrument number is set to insno If named instr exists, it is replaced. */ int named_instr_alloc(CSOUND *csound, char *s, INSTRTXT *ip, int32 insno, ENGINE_STATE *engineState, int merge) { INSTRNAME *inm, *inm2, *inm_head; int ret = 1; if (UNLIKELY(!engineState->instrumentNames)) engineState->instrumentNames = cs_hash_table_create(csound); /* now check if instrument is already defined */ inm = cs_hash_table_get(csound, engineState->instrumentNames, s); if (inm != NULL) { int i; ret = 0; if (!merge) return ret; inm->ip->isNew = 1; /* redefinition does not raise an error now, just a warning */ if (UNLIKELY(csound->oparms->odebug)) csound->Warning(csound, Str("instr %d redefined, replacing previous definition"), inm->instno); /* here we should move the old instrument definition into a deadpool which will be checked for active instances and freed when there are no further ones */ for (i=0; i < engineState->maxinsno; i++) { /* check for duplicate numbers and do nothing */ if (i != inm->instno && engineState->instrtxtp[i] == engineState->instrtxtp[inm->instno]) goto cont; } INSDS *active = engineState->instrtxtp[inm->instno]->instance; while (active != NULL) { if (active->actflg) { /* FIXME: */ /* this seems to be wiping memory that is still being used */ // add_to_deadpool(csound, engineState->instrtxtp[inm->instno]); /* this marks the instrument number ready for replacement */ engineState->instrtxtp[inm->instno] = NULL; break; } active = active->nxtinstance; } /* no active instances */ if (active == NULL) { if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, Str("no active instances \n")); free_instrtxt(csound, engineState->instrtxtp[inm->instno]); engineState->instrtxtp[inm->instno] = NULL; } inm->ip->instance = inm->ip->act_instance = inm->ip->lst_instance = NULL; } cont: /* allocate entry, */ inm = (INSTRNAME*) csound->Calloc(csound, sizeof(INSTRNAME)); inm2 = (INSTRNAME*) csound->Calloc(csound, sizeof(INSTRNAME)); /* and store parameters */ inm->name = cs_strdup(csound, s); inm->ip = ip; inm2->instno = insno; inm2->name = (char*) inm; /* hack */ //printf("insno %d \n", insno); /* link into chain */ cs_hash_table_put(csound, engineState->instrumentNames, s, inm); inm_head = cs_hash_table_get(csound, engineState->instrumentNames, (char*)INSTR_NAME_FIRST); /* temporary chain for use by named_instr_assign_numbers() */ if (inm_head == NULL) { cs_hash_table_put(csound, engineState->instrumentNames, (char*)INSTR_NAME_FIRST, inm2); } else { while (inm_head->next != NULL) { inm_head = inm_head->next; } inm_head->next = inm2; } if (UNLIKELY(csound->oparms->odebug) && engineState == &csound->engineState) csound->Message(csound, "named instr name = \"%s\", txtp = %p,\n", s, (void*) ip); return ret; } /** assign instrument numbers to all named instruments */ void named_instr_assign_numbers(CSOUND *csound, ENGINE_STATE *engineState) { INSTRNAME *inm, *inm2, *inm_first; int num = 0, insno_priority = 0; if (!engineState->instrumentNames) return; /* no named instruments */ inm_first = cs_hash_table_get(csound, engineState->instrumentNames, (char*)INSTR_NAME_FIRST); while (--insno_priority > -3) { if (insno_priority == -2) { num = engineState->maxinsno; /* find last used instr number */ while (!engineState->instrtxtp[num] && --num); } for (inm = inm_first; inm; inm = inm->next) { if ((int) inm->instno != insno_priority) continue; /* the following is based on code by Matt J. Ingalls */ /* find an unused number and use it */ while (++num <= engineState->maxinsno && engineState->instrtxtp[num]); /* we may need to expand the instrument array */ if (num > engineState->maxinsno) { int m = engineState->maxinsno; engineState->maxinsno += MAXINSNO; /* Expand */ engineState->instrtxtp = (INSTRTXT**) csound->ReAlloc(csound, engineState->instrtxtp, (1 + engineState->maxinsno) * sizeof(INSTRTXT*)); /* Array expected to be nulled so.... */ while (++m <= engineState->maxinsno) engineState->instrtxtp[m] = NULL; } /* hack: "name" actually points to the corresponding INSTRNAME */ inm2 = (INSTRNAME*) (inm->name); /* entry in the table */ //printf("instno %d \n", num); inm2->instno = (int32) num; engineState->instrtxtp[num] = inm2->ip; if (UNLIKELY(csound->oparms->msglevel && engineState == &csound->engineState)) csound->Message(csound, Str("instr %s uses instrument number %d\n"), inm2->name, num); } } /* clear temporary chains */ inm = inm_first; while (inm) { INSTRNAME *nxtinm = inm->next; csound->Free(csound, inm); inm = nxtinm; } cs_hash_table_remove(csound, engineState->instrumentNames, (char*)INSTR_NAME_FIRST); } /** Insert INSTRTXT into an engineState list of INSTRTXT's, checking to see if number is greater than number of pointers currently allocated and if so expand pool of instruments */ void insert_instrtxt(CSOUND *csound, INSTRTXT *instrtxt, int32 instrNum, ENGINE_STATE *engineState, int merge) { int i; if (UNLIKELY(instrNum >= engineState->maxinsno)) { int old_maxinsno = engineState->maxinsno; /* expand */ while (instrNum >= engineState->maxinsno) { engineState->maxinsno += MAXINSNO; } engineState->instrtxtp = (INSTRTXT**)csound->ReAlloc(csound, engineState->instrtxtp, (1 + engineState->maxinsno) * sizeof(INSTRTXT*)); /* Array expected to be nulled so.... */ for (i = old_maxinsno + 1; i <= engineState->maxinsno; i++) { engineState->instrtxtp[i] = NULL; } } if (UNLIKELY(engineState->instrtxtp[instrNum] != NULL)) { instrtxt->isNew = 1; /* redefinition does not raise an error now, just a warning */ /* unless we are not merging */ if (!merge) synterr(csound, Str("instr %d redefined\n"), instrNum); if (UNLIKELY(instrNum && csound->oparms->odebug)) csound->Warning(csound, Str("instr %d redefined, replacing previous definition"), instrNum); /* inherit active & maxalloc flags */ instrtxt->active = engineState->instrtxtp[instrNum]->active; instrtxt->maxalloc = engineState->instrtxtp[instrNum]->maxalloc; /* here we should move the old instrument definition into a deadpool which will be checked for active instances and freed when there are no further ones */ for (i=0; i < engineState->maxinsno; i++) { /* check for duplicate numbers and do nothing */ if (i != instrNum && engineState->instrtxtp[i] == engineState->instrtxtp[instrNum]) goto end; } INSDS *active = engineState->instrtxtp[instrNum]->instance; while (active != NULL && instrNum != 0) { if (active->actflg) { add_to_deadpool(csound, engineState->instrtxtp[instrNum]); break; } active = active->nxtinstance; } /* no active instances */ /* instr0 is freed elsewhere */ if (active == NULL && instrNum != 0) { if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, Str("no active instances of instr %d \n"), instrNum); free_instrtxt(csound, engineState->instrtxtp[instrNum]); } /* err++; continue; */ } end: instrtxt->instance = instrtxt->act_instance = instrtxt->lst_instance = NULL; engineState->instrtxtp[instrNum] = instrtxt; } void insert_opcodes(CSOUND *csound, OPCODINFO *opcodeInfo, ENGINE_STATE *engineState) { if (opcodeInfo) { int num = engineState->maxinsno; /* store after any other instruments */ OPCODINFO *inm = opcodeInfo; while (inm) { /* we may need to expand the instrument array */ if (UNLIKELY(++num > engineState->maxopcno)) { int i; i = (engineState->maxopcno > 0 ? engineState->maxopcno : engineState->maxinsno); engineState->maxopcno = i + MAXINSNO; engineState->instrtxtp = (INSTRTXT**) csound->ReAlloc(csound, engineState->instrtxtp, (1 + engineState->maxopcno) * sizeof(INSTRTXT*)); /* Array expected to be nulled so.... */ while (++i <= engineState->maxopcno) engineState->instrtxtp[i] = NULL; } inm->instno = num; //csound->Message(csound, Str("UDO INSTR NUM: %d\n"), num); engineState->instrtxtp[num] = inm->ip; inm = inm->prv; } } } OPCODINFO *find_opcode_info(CSOUND *csound, char *opname, char* outargs, char* inargs) { OPCODINFO *opinfo = csound->opcodeInfo; if (UNLIKELY(opinfo == NULL)) { csound->Message(csound, Str("!!! csound->opcodeInfo is NULL !!!\n")); return NULL; } while (opinfo != NULL) { if (UNLIKELY(strcmp(opinfo->name, opname) == 0 && strcmp(opinfo->intypes, inargs) == 0 && strcmp(opinfo->outtypes, outargs) == 0)) { return opinfo; } opinfo = opinfo->prv; /* Move on: JPff suggestion */ } return NULL; } /** Merge a new engineState into csound->engineState 1) Add to stringPool, constantsPool and varPool (globals) 2) Add to opinfo and UDOs 3) Call insert_instrtxt() on csound->engineState for each new instrument 4) Call insprep() and recalculateVarPoolMemory() for each new instrument 5) patch up nxtinstxt order */ int engineState_merge(CSOUND *csound, ENGINE_STATE *engineState) { int i, end = engineState->maxinsno; ENGINE_STATE *current_state = &csound->engineState; INSTRTXT *current, *old_instr0; int count = 0; //cs_hash_table_merge(csound, // current_state->stringPool, engineState->stringPool); cs_hash_table_merge(csound, current_state->constantsPool, engineState->constantsPool); /* for (count = 0; count < engineState->constantsPool->count; count++) { if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, Str(" merging constants %d) %f\n"), count, engineState->constantsPool->values[count].value); myflt_pool_find_or_add(csound, current_state->constantsPool, engineState->constantsPool->values[count].value); }*/ CS_VARIABLE* gVar = engineState->varPool->head; while (gVar != NULL) { CS_VARIABLE* var; if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, Str(" merging %p %d) %s:%s\n"), gVar, count, gVar->varName, gVar->varType->varTypeName); var = csoundFindVariableWithName(csound, current_state->varPool, gVar->varName); if (var == NULL) { ARRAY_VAR_INIT varInit; varInit.dimensions = gVar->dimensions; varInit.type = gVar->subType; var = csoundCreateVariable(csound, csound->typePool, gVar->varType, gVar->varName, &varInit); csoundAddVariable(csound, current_state->varPool, var); /* memory has already been allocated, so we just point to it */ /* when disposing of the engineState global vars, we do not delete the memBlock */ var->memBlock = gVar->memBlock; if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, Str(" adding %p %d) %s:%s\n"), var, count, gVar->varName, gVar->varType->varTypeName); gVar = gVar->next; } else { // if variable exists // free variable mem block // printf("free %p \n", gVar->memBlock); // the CS_VARIABLE itself will be freed on engine_free() csound->Free(csound, gVar->memBlock); csound->Free(csound, gVar->varName); gVar = gVar->next; } } /* merge opcodinfo */ /* VL probably not the right place, since instr list might grow insert_opcodes(csound, csound->opcodeInfo, current_state); */ old_instr0 = current_state->instrtxtp[0]; insert_instrtxt(csound,engineState->instrtxtp[0],0,current_state,1); for (i=1; i < end; i++) { current = engineState->instrtxtp[i]; if (current != NULL) { if (current->insname == NULL) { if (csound->oparms->odebug) csound->Message(csound, Str("merging instr %d \n"), i); /* a first attempt at this merge is to make it use insert_instrtxt again */ /* insert instrument in current engine */ insert_instrtxt(csound,current,i,current_state,1); } else { if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, Str("merging instr %s \n"), current->insname); /* allocate a named_instr string in the current engine */ named_instr_alloc(csound,current->insname,current,-1L,current_state,1); } } } /* merges all named instruments */ //printf("assign numbers; %p\n", current_state); named_instr_assign_numbers(csound,current_state);\ /* VL MOVED here after all instruments are merged so that we get the correct number */ insert_opcodes(csound, csound->opcodeInfo, current_state); /* this needs to be called in a separate loop in case of multiple instr numbers, so insprep() is called only once */ current = (&(engineState->instxtanchor));//->nxtinstxt; while ((current = current->nxtinstxt) != NULL) { if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, "insprep %p \n", current); insprep(csound, current, current_state);/* run insprep() to connect ARGS */ recalculateVarPoolMemory(csound, current->varPool); /* recalculate var pool */ } /* now we need to patch up instr order */ end = current_state->maxinsno; end = end < current_state->maxopcno ? current_state->maxopcno : end; for (i=0; i < end; i++) { int j; current = current_state->instrtxtp[i]; if (current != NULL) { if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, "instr %d:%p \n", i, current); current->nxtinstxt = NULL; j = i; while (++j < end-1) { if (current_state->instrtxtp[j] != NULL) { current->nxtinstxt = current_state->instrtxtp[j]; break; } } } } (&(current_state->instxtanchor))->nxtinstxt = csound->instr0; /* now free old instr 0 */ free_instrtxt(csound, old_instr0); return 0; } int engineState_free(CSOUND *csound, ENGINE_STATE *engineState) { csound->Free(csound, engineState->instrumentNames); cs_hash_table_free(csound, engineState->constantsPool); //cs_hash_table_free(csound, engineState->stringPool); csoundFreeVarPool(csound, engineState->varPool); csound->Free(csound, engineState->instrtxtp); csound->Free(csound, engineState); return 0; } void free_typetable(CSOUND *csound, TYPE_TABLE *typeTable) { cs_cons_free_complete(csound, typeTable->labelList); csound->Free(csound, typeTable); } static char *node2string(int type) { /* Add new nodes here as necessary -- JPff */ switch (type) { /* case LABEL_TOKEN: */ /* return "label"; */ default: return "??"; } } /** Merge and Dispose of engine state and type table, and run global i-time code */ void merge_state(CSOUND *csound, ENGINE_STATE *engineState, TYPE_TABLE* typetable, OPDS *ids) { if (csound->init_pass_threadlock) csoundLockMutex(csound->init_pass_threadlock); engineState_merge(csound, engineState); engineState_free(csound, engineState); free_typetable(csound, typetable); /* run global i-time code */ init0(csound); csound->ids = ids; if (csound->init_pass_threadlock) csoundUnlockMutex(csound->init_pass_threadlock); } /** * Compile the given TREE node into structs In the the first compilation run, it: 1) Uses the empty csound->engineState 2) Creates instrument 0 3) Creates other instruments and UDOs 4) Runs insprep() and recalculateVarpool() for each instrument In any subsequent compilation run, it: 1) Creates a new engineState 2) instrument 0 is treated as a global i-time instrument, header constants are ignored. 3) Creates other instruments 4) Calls engineState_merge() and engineState_free() async determines asynchronous operation of the merge stage. VL 20-12-12 * ASSUMES: TREE has been validated prior to compilation * * */ int csoundCompileTreeInternal(CSOUND *csound, TREE *root, int async) { INSTRTXT *instrtxt = NULL; INSTRTXT *ip = NULL; INSTRTXT *prvinstxt; OPTXT *bp; char *opname; TREE * current = root; ENGINE_STATE *engineState; CS_VARIABLE* var; TYPE_TABLE* typeTable = (TYPE_TABLE*)current->markup; current = current->next; if (csound->instr0 == NULL) { engineState = &csound->engineState; engineState->varPool = typeTable->globalPool; csound->instr0 = create_instrument0(csound, current, engineState, typeTable->instr0LocalPool); cs_hash_table_put_key(csound, engineState->stringPool, "\"\""); prvinstxt = &(engineState->instxtanchor); engineState->instrtxtp = (INSTRTXT **) csound->Calloc(csound, (1 + engineState->maxinsno) * sizeof(INSTRTXT*)); prvinstxt = prvinstxt->nxtinstxt = csound->instr0; insert_instrtxt(csound, csound->instr0, 0, engineState,0); } else { engineState = (ENGINE_STATE *) csound->Calloc(csound, sizeof(ENGINE_STATE)); engineState->stringPool = csound->engineState.stringPool; //cs_hash_table_create(csound); engineState->constantsPool = cs_hash_table_create(csound); engineState->varPool = typeTable->globalPool; prvinstxt = &(engineState->instxtanchor); engineState->instrtxtp = (INSTRTXT **) csound->Calloc(csound, (1 + engineState->maxinsno) * sizeof(INSTRTXT*)); /* VL: allowing global code to be evaluated in subsequent compilations */ csound->instr0 = create_global_instrument(csound, current, engineState, typeTable->instr0LocalPool); insert_instrtxt(csound, csound->instr0, 0, engineState,1); prvinstxt = prvinstxt->nxtinstxt = csound->instr0; //engineState->maxinsno = 1; } // allocate memory for global vars // if this variable already exists, // memory will be freed on merge. var = typeTable->globalPool->head; while (var != NULL) { size_t memSize = CS_VAR_TYPE_OFFSET + var->memBlockSize; CS_VAR_MEM* varMem = (CS_VAR_MEM*) csound->Calloc(csound, memSize); //printf("alloc %p -- %s\n", varMem, var->varName); varMem->varType = var->varType; var->memBlock = varMem; if (var->initializeVariableMemory != NULL) { var->initializeVariableMemory((void *)csound, var, &varMem->value); } else memset(&varMem->value , 0, var->memBlockSize); var = var->next; } while (current != NULL) { switch (current->type) { case '=': /* csound->Message(csound, "Assignment found\n"); */ break; case INSTR_TOKEN: //print_tree(csound, "Instrument found\n", current); instrtxt = create_instrument(csound, current,engineState); prvinstxt = prvinstxt->nxtinstxt = instrtxt; /* Handle Inserting into CSOUND here by checking ids (name or * numbered) and using new insert_instrtxt? */ /* Temporarily using the following code */ if (current->left->type == INTEGER_TOKEN) { /* numbered instrument, eg.: instr 1 */ int32 instrNum = (int32)current->left->value->value; insert_instrtxt(csound, instrtxt, instrNum, engineState,0); } else if (current->left->type == T_IDENT) { /* named instrument, eg.: instr Hello */ int32 insno_priority = -1L; char *c; c = current->left->value->lexeme; if (UNLIKELY(current->left->rate == (int) '+')) { insno_priority--; } if (UNLIKELY(!check_instr_name(c))) { synterr(csound, Str("invalid name for instrument")); } named_instr_alloc(csound,c,instrtxt, insno_priority, engineState,0); /* VL 10.10.14: check for redefinition */ //if (UNLIKELY(!named_instr_alloc(csound, c, // instrtxt, insno_priority, // engineState, 0))) { //synterr(csound, Str("instr %s redefined\n"), c); //} instrtxt->insname = csound->Malloc(csound, strlen(c) + 1); strcpy(instrtxt->insname, c); } else if (current->left->type == T_INSTLIST) { /* list of instr names, eg: instr Hello, 1, 2 */ TREE *p = current->left; while (p) { if (PARSER_DEBUG) print_tree(csound, "Top of loop\n", p); if (p->left) { if (p->left->type == INTEGER_TOKEN) { insert_instrtxt(csound, instrtxt, p->left->value->value, engineState,0); } else if (p->left->type == T_IDENT) { int32 insno_priority = -1L; char *c; c = p->left->value->lexeme; if (UNLIKELY(p->left->rate == (int) '+')) { insno_priority--; } if (UNLIKELY(!check_instr_name(c))) { synterr(csound, Str("invalid name for instrument")); } if (UNLIKELY(!named_instr_alloc(csound, c, instrtxt, insno_priority, engineState,0))) { synterr(csound, Str("instr %s redefined"), c); } instrtxt->insname = csound->Malloc(csound, strlen(c) + 1); strcpy(instrtxt->insname, c); } } else { if (p->type == INTEGER_TOKEN) { insert_instrtxt(csound, instrtxt, p->value->value, engineState,0); } else if (p->type == T_IDENT) { int32 insno_priority = -1L; char *c; c = p->value->lexeme; if (UNLIKELY(p->rate == (int) '+')) { insno_priority--; } if (UNLIKELY(!check_instr_name(c))) { synterr(csound, Str("invalid name for instrument")); } if (UNLIKELY(!named_instr_alloc(csound, c, instrtxt, insno_priority, engineState,0))) { synterr(csound, Str("instr %s redefined"), c); } instrtxt->insname = csound->Malloc(csound, strlen(c) + 1); strcpy(instrtxt->insname, c); } break; } p = p->right; } } break; case UDO_TOKEN: /* csound->Message(csound, "UDO found\n"); */ instrtxt = create_instrument(csound, current, engineState); prvinstxt = prvinstxt->nxtinstxt = instrtxt; opname = current->left->value->lexeme; OPCODINFO *opinfo = find_opcode_info(csound, opname, current->left->left->value->lexeme, current->left->right->value->lexeme); if (UNLIKELY(opinfo == NULL)) { csound->Message(csound, Str("ERROR: Could not find OPCODINFO for opname: %s\n"), opname); } else { opinfo->ip = instrtxt; instrtxt->insname = cs_strdup(csound, opname); instrtxt->opcode_info = opinfo; } /* Handle Inserting into CSOUND here by checking id's (name or * numbered) and using new insert_instrtxt? */ break; case T_OPCODE: case T_OPCODE0: case LABEL: case LABEL_TOKEN: break; default: csound->Message(csound, Str("Unknown TREE node of type %d (%s) found in root.\n"), current->type, node2string(current->type)); if (PARSER_DEBUG) print_tree(csound, NULL, current); } current = current->next; } if (UNLIKELY(csound->synterrcnt)) { print_opcodedir_warning(csound); csound->Warning(csound, Str("%d syntax errors in orchestra. " "compilation invalid\n"), csound->synterrcnt); free_typetable(csound, typeTable); return CSOUND_ERROR; } /* now add the instruments with names, assigning them fake instr numbers */ named_instr_assign_numbers(csound,engineState); if (engineState != &csound->engineState) { OPDS *ids = csound->ids; /* any compilation other than the first one */ /* merge ENGINE_STATE */ /* lock to ensure thread-safety */ if (!async) { csoundLockMutex(csound->API_lock); merge_state(csound, engineState, typeTable, ids); csoundUnlockMutex(csound->API_lock); } else mergeState_enqueue(csound, engineState, typeTable, ids); } else { /* first compilation */ insert_opcodes(csound, csound->opcodeInfo, engineState); ip = engineState->instxtanchor.nxtinstxt; bp = (OPTXT *) ip; while (bp != (OPTXT *) NULL && (bp = bp->nxtop) != NULL) { /* chk instr 0 for illegal perfs */ int thread; OENTRY* oentry = bp->t.oentry; if (strcmp(oentry->opname, "endin") == 0) break; if (strcmp(oentry->opname, "$label") == 0) continue; if (PARSER_DEBUG) csound->DebugMsg(csound, "Instr 0 check on opcode=%s\n", bp->t.opcod); if (UNLIKELY((thread = oentry->thread) & 06 || (!thread && bp->t.pftype != 'b'))) { csound->DebugMsg(csound, "***opcode=%s thread=%d pftype=%c\n", bp->t.opcod, thread, bp->t.pftype); /* synterr(csound, Str("perf-pass statements illegal in header blk (%s)\n"), oentry->opname);*/ csound->Warning(csound, Str("%s: perf-time code in global space, ignored"), oentry->opname); } } ip = &(engineState->instxtanchor); while ((ip = ip->nxtinstxt) != NULL) { /* add all other entries */ insprep(csound, ip, engineState); /* as combined offsets */ recalculateVarPoolMemory(csound, ip->varPool); } CS_VARIABLE *var; var = csoundFindVariableWithName(csound, engineState->varPool, "sr"); var->memBlock->value = csound->esr; var = csoundFindVariableWithName(csound, engineState->varPool, "kr"); var->memBlock->value = csound->ekr; var = csoundFindVariableWithName(csound, engineState->varPool, "ksmps"); var->memBlock->value = csound->ksmps; var = csoundFindVariableWithName(csound, engineState->varPool, "nchnls"); var->memBlock->value = csound->nchnls; if (csound->inchnls<0) csound->inchnls = csound->nchnls; var = csoundFindVariableWithName(csound, engineState->varPool, "nchnls_i"); var->memBlock->value = csound->inchnls; var = csoundFindVariableWithName(csound, engineState->varPool, "0dbfs"); var->memBlock->value = csound->e0dbfs; var = csoundFindVariableWithName(csound, engineState->varPool, "A4"); var->memBlock->value = csound->A4; } return CSOUND_SUCCESS; } #ifdef EMSCRIPTEN void sanitize(CSOUND *csound) {} #else extern void sanitize(CSOUND *csound); #endif /** Parse and compile an orchestra given on an string (OPTIONAL) if str is NULL the string is taken from the internal corfile containing the initial orchestra file passed to Csound. Also evaluates any global space code. async determines asynchronous operation of the merge stage. */ int csoundCompileOrcInternal(CSOUND *csound, const char *str, int async) { TREE *root; int retVal=1; volatile jmp_buf tmpExitJmp; memcpy((void*) &tmpExitJmp, (void*) &csound->exitjmp, sizeof(jmp_buf)); if ((retVal=setjmp(csound->exitjmp))) { memcpy((void*) &csound->exitjmp, (void*) &tmpExitJmp, sizeof(jmp_buf)); return retVal; } //retVal = 1; root = csoundParseOrc(csound, str); if (LIKELY(root != NULL)) { retVal = csoundCompileTreeInternal(csound, root, async); // Sanitise semantic sets here sanitize(csound); csoundDeleteTree(csound, root); } else { // csoundDeleteTree(csound, root); memcpy((void*) &csound->exitjmp, (void*) &tmpExitJmp, sizeof(jmp_buf)); return CSOUND_ERROR; } if (UNLIKELY(csound->oparms->odebug)) debugPrintCsound(csound); memcpy((void*) &csound->exitjmp, (void*) &tmpExitJmp, sizeof(jmp_buf)); return retVal; } /* prep an instr template for efficient allocs */ /* repl arg refs by offset ndx to lcl/gbl space */ static void insprep(CSOUND *csound, INSTRTXT *tp, ENGINE_STATE *engineState) { OPARMS *O = csound->oparms; OPTXT *optxt; OENTRY *ep; char **argp; int n, inreqd; char** argStringParts; ARGLST *outlist, *inlist; OENTRY* pset = find_opcode(csound, "pset"); optxt = (OPTXT *)tp; while ((optxt = optxt->nxtop) != NULL) { /* for each op in instr */ TEXT *ttp = &optxt->t; ep = ttp->oentry; if (strcmp(ep->opname, "endin") == 0 /* (until ENDIN) */ || strcmp(ep->opname, "endop") == 0) break; if (strcmp(ep->opname, "$label") == 0) { continue; } if (UNLIKELY(O->odebug)) csound->Message(csound, "%s args:", ep->opname); if ((outlist = ttp->outlist) == NULL || !outlist->count) ttp->outArgs = NULL; else { n = outlist->count; argp = outlist->arg; /* get outarg indices */ while (n--) { ARG* arg = createArg(csound, tp, *argp++, engineState); if (ttp->outArgs == NULL) { ttp->outArgs = arg; } else { ARG* current = ttp->outArgs; while (current->next != NULL) { current = current->next; } current->next = arg; arg->next = NULL; } } } if ((inlist = ttp->inlist) == NULL || !inlist->count) ttp->inArgs = NULL; else { inreqd = argsRequired(ep->intypes); argStringParts = splitArgs(csound, ep->intypes); argp = inlist->arg; /* get inarg indices */ for (n=0; n < inlist->count; n++, argp++) { ARG* arg = NULL; if (n < inreqd && *argStringParts[n] == 'l') { arg = csound->Calloc(csound, sizeof(ARG)); arg->type = ARG_LABEL; arg->argPtr = csound->Malloc(csound, strlen(*argp) + 1); strcpy(arg->argPtr, *argp); if (UNLIKELY(O->odebug)) csound->Message(csound, "\t%s:", *argp); /* if arg is label, */ } else { char *s = *argp; arg = createArg(csound, tp, s, engineState); } if (ttp->inArgs == NULL) { ttp->inArgs = arg; //printf("yinarg %p -- opcode %s \n", arg, ttp->opcod); } else { ARG* current = ttp->inArgs; //printf("xinarg %p %p -- opcode %s \n", current, arg, ttp->opcod); while (current->next != NULL) { //printf("inarg %p %p -- opcode %s \n", current, arg, ttp->opcod); current = current->next; } current->next = arg; arg->next = NULL; } } if (ttp->oentry == pset) { MYFLT* fp1; int n; ARG* inArgs = ttp->inArgs; //CS_VARIABLE* var; if (tp->insname) csound->Message(csound, "PSET: isname=\"%s\", pmax=%d\n", tp->insname, tp->pmax); else csound->Message(csound, "PSET: isno=??, pmax=%d\n", tp->pmax); if (UNLIKELY((n = ttp->inArgCount) != tp->pmax)) { //csound->Warning(csound, Str("i%d pset args != pmax"), (int) insno); csound->Warning(csound, Str("i[fixme] pset args != pmax")); if (n < tp->pmax) n = tp->pmax; /* cf pset, pmax */ } tp->psetdata = (MYFLT*) csound->Calloc(csound, n * sizeof(MYFLT)); for (n = 0, fp1 = tp->psetdata; n < (int)ttp->inArgCount; n++, inArgs = inArgs->next) { switch (inArgs->type) { case ARG_CONSTANT: *fp1++ = ((CS_VAR_MEM*)inArgs->argPtr)->value; break; // case ARG_LOCAL: // *fp1++ = 44.0; // break; // // case ARG_GLOBAL: // var = (CS_VARIABLE*)inArgs->argPtr; // *fp1++ = *((MYFLT*)var->memBlock); // break; /* FIXME - to note, because this is done during compile time, pset does not work with local and global variables as they have not been initialized yet. Csound5 also did not work with local/global variables. In the future, use the test in tests/commandline/contrib/test_pset.csd for testing. */ default: *fp1++ = 0.0; break; } // csound->Message(csound, "..%f..", *(fp1-1)); } csound->Message(csound, "\n"); } //printf("delete %p \n", argStringParts); for (n=0; argStringParts[n] != NULL; n++) { //printf("delete %p \n", argStringParts[n]); csound->Free(csound, argStringParts[n]); } csound->Free(csound, argStringParts); } if (UNLIKELY(O->odebug)) csound->Message(csound, "\n"); } } /* build pool of floating const values */ /* build lcl/gbl list of ds names, offsets */ /* (no need to save the returned values) */ static void lgbuild(CSOUND *csound, INSTRTXT* ip, char *s, int inarg, ENGINE_STATE *engineState) { char c; char* temp; c = *s; /* must trap 0dbfs as name starts with a digit! */ if ((c >= '1' && c <= '9') || c == '.' || c == '-' || c == '+' || (c == '0' && strcmp(s, "0dbfs") != 0)) { if (cs_hash_table_get(csound, csound->engineState.constantsPool, s) == NULL) { find_or_add_constant(csound, engineState->constantsPool, s, cs_strtod(s, NULL)); } } else if (c == '"') { temp = csound->Calloc(csound, strlen(s) + 1); //csound->Message(csound, "%c \n", s[1]); unquote_string(temp, s); cs_hash_table_put_key(csound, engineState->stringPool, temp); csound->Free(csound, temp); } } /* get storage ndx of const, pnum, lcl or gbl */ /* argument const/gbl indexes are positiv+1, */ /* pnum/lcl negativ-1 called only after */ /* poolcount & lclpmax are finalised */ static ARG* createArg(CSOUND *csound, INSTRTXT* ip, char *s, ENGINE_STATE *engineState) { char c; char* temp; int n; c = *s; ARG* arg = csound->Calloc(csound, sizeof(ARG)); if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, "\t%s", s); /* if arg is label, */ /* must trap 0dbfs as name starts with a digit! */ if ((c >= '1' && c <= '9') || c == '.' || c == '-' || c == '+' || (c == '0' && strcmp(s, "0dbfs") != 0)) { arg->type = ARG_CONSTANT; //printf("create constant %p: %c \n", arg, c); if ((arg->argPtr = cs_hash_table_get(csound, csound->engineState.constantsPool, s)) != NULL) { arg->argPtr = find_or_add_constant(csound, engineState->constantsPool, s, cs_strtod(s, NULL)); } } else if (c == '"') { size_t memSize = CS_VAR_TYPE_OFFSET + sizeof(STRINGDAT); CS_VAR_MEM* varMem = csound->Calloc(csound, memSize); STRINGDAT *str = (STRINGDAT*)&varMem->value; //printf("create string %p: %s \n", arg, str->data); varMem->varType = (CS_TYPE*)&CS_VAR_TYPE_S; arg->type = ARG_STRING; temp = csound->Calloc(csound, strlen(s) + 1); unquote_string(temp, s); str->data = cs_hash_table_get_key(csound, csound->engineState.stringPool, temp); str->size = strlen(temp) + 1; csound->Free(csound, temp); arg->argPtr = str; if (str->data == NULL) { str->data = cs_hash_table_put_key(csound, engineState->stringPool, temp); } } else if ((n = pnum(s)) >= 0) { arg->type = ARG_PFIELD; arg->index = n; } /* trap local ksmps and kr */ else if ((strcmp(s, "ksmps") == 0 && csoundFindVariableWithName(csound, ip->varPool, s)) || (strcmp(s, "kr") == 0 && csoundFindVariableWithName(csound, ip->varPool, s))) { arg->type = ARG_LOCAL; arg->argPtr = csoundFindVariableWithName(csound, ip->varPool, s); } else if (c == 'g' || (c == '#' && *(s+1) == 'g') || csoundFindVariableWithName(csound, csound->engineState.varPool, s) != NULL) { // FIXME - figure out why string pool searched with gexist //|| string_pool_indexof(csound->engineState.stringPool, s) > 0) { arg->type = ARG_GLOBAL; arg->argPtr = csoundFindVariableWithName(csound, engineState->varPool, s); //printf("create global %p: %s \n", arg->argPtr, s); } else { arg->type = ARG_LOCAL; arg->argPtr = csoundFindVariableWithName(csound, ip->varPool, s); //printf("create local %p: %s \n", arg, s); if (arg->argPtr == NULL) { csound->Message(csound, Str("Missing local arg: %s\n"), s); } } /* csound->Message(csound, " [%s -> %d (%x)]\n", s, indx, indx); */ return arg; } char argtyp2(char *s) { /* find arg type: d, w, a, k, i, c, p, r, S, B, b, t */ char c = *s; /* also set lgprevdef if !c && !p && !S */ /* trap this before parsing for a number! */ /* two situations: defined at header level: 0dbfs = 1.0 * and returned as a value: idb = 0dbfs */ if ((c >= '1' && c <= '9') || c == '.' || c == '-' || c == '+' || (c == '0' && strcmp(s, "0dbfs") != 0)) return('c'); /* const */ if (pnum(s) >= 0) return('p'); /* pnum */ if (c == '"') return('S'); /* quoted String */ if (strcmp(s,"sr") == 0 || strcmp(s,"kr") == 0 || strcmp(s,"0dbfs") == 0 || strcmp(s,"nchnls_i") == 0 || strcmp(s,"ksmps") == 0 || strcmp(s,"nchnls") == 0) return('r'); /* rsvd */ if (c == 'w') /* N.B. w NOT YET #TYPE OR GLOBAL */ return(c); if (c == '#') c = *(++s); if (c == 'g') c = *(++s); if (c == '[') { while (c == '[') { c = *(++s); } } if (c == 't') { /* Support legacy t-vars by mapping to k subtypes */ return 'k'; } if (strchr("akiBbfSt", c) != NULL) return(c); else return('?'); } /* For diagnostics map file name or macro name to an index */ uint8_t file_to_int(CSOUND *csound, const char *name) { //extern char *strdup(const char *); uint8_t n = 0; char **filedir = csound->filedir; while (n<255 && filedir[n] && n<255) { /* Do we have it already? */ if (strcmp(filedir[n], name)==0) return n; /* yes */ n++; /* look again */ } // Not there so add // ensure long enough? if (UNLIKELY(n==255)) { filedir[n] = cs_strdup(csound, Str("**unrecorded**")); } else { filedir[n] = cs_strdup(csound, (char *) name); filedir[n+1] = NULL; } return n; } void debugPrintCsound(CSOUND* csound) { INSTRTXT *current; CONS_CELL* val = cs_hash_table_keys(csound, csound->engineState.stringPool); CONS_CELL* const_val = cs_hash_table_values(csound, csound->engineState.constantsPool); int count = 0; csound->Message(csound, "Compile State:\n"); csound->Message(csound, "String Pool:\n"); while (val != NULL) { csound->Message(csound, " %d) %s\n", count++, (char *)val->value); val = val->next; } csound->Message(csound, "Constants Pool:\n"); while (const_val != NULL) { CS_VAR_MEM* mem = (CS_VAR_MEM*)const_val->value; csound->Message(csound, " %d) %f\n", count++, mem->value); const_val = const_val->next; } csound->Message(csound, "Global Variables:\n"); CS_VARIABLE* gVar = csound->engineState.varPool->head; count = 0; while (gVar != NULL) { csound->Message(csound, " %d) %s:%s\n", count++, gVar->varName, gVar->varType->varTypeName); gVar = gVar->next; } /* bad practice to declare variables in middle of block */ current = &(csound->engineState.instxtanchor); current = current->nxtinstxt; count = 0; while (current != NULL) { csound->Message(csound, "Instrument %d %p %p\n", count, current, current->nxtinstxt); csound->Message(csound, "Variables\n"); if (current->varPool != NULL) { CS_VARIABLE* var = current->varPool->head; int index = 0; while (var != NULL) { if (var->varType == &CS_VAR_TYPE_ARRAY) { csound->Message(csound, " %d) %s:[%s]\n", index++, var->varName, var->subType->varTypeName); } else { csound->Message(csound, " %d) %s:%s\n", index++, var->varName, var->varType->varTypeName); } var = var->next; } } count++; current = current->nxtinstxt; } } #include "interlocks.h" void query_deprecated_opcode(CSOUND *csound, ORCTOKEN *o) { char *name = o->lexeme; OENTRY *ep = find_opcode(csound, name); if (UNLIKELY(ep->flags&_QQ)) csound->Warning(csound, Str("Opcode \"%s\" is deprecated\n"), name); } csound-6.10.0/Engine/csound_orc_expressions.c000066400000000000000000001274271321653344700212670ustar00rootroot00000000000000 /* csound_orc_expressions.c: Copyright (C) 2006 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "csound_orc.h" #include "csound_orc_expressions.h" #include "csound_type_system.h" #include "csound_orc_semantics.h" extern char argtyp2(char *); extern void print_tree(CSOUND *, char *, TREE *); extern void handle_optional_args(CSOUND *, TREE *); extern ORCTOKEN *make_token(CSOUND *, char *); extern ORCTOKEN *make_label(CSOUND *, char *); extern OENTRIES* find_opcode2(CSOUND *, char*); extern char* resolve_opcode_get_outarg(CSOUND* , OENTRIES* , char*); extern TREE* appendToTree(CSOUND * csound, TREE *first, TREE *newlast); extern char* get_arg_string_from_tree(CSOUND* csound, TREE* tree, TYPE_TABLE* typeTable); extern void add_arg(CSOUND* csound, char* varName, TYPE_TABLE* typeTable); extern void add_array_arg(CSOUND* csound, char* varName, int dimensions, TYPE_TABLE* typeTable); extern char* get_array_sub_type(CSOUND* csound, char*); extern char* convert_external_to_internal(CSOUND* csound, char* arg); static TREE *create_boolean_expression(CSOUND*, TREE*, int, int, TYPE_TABLE*); static TREE *create_expression(CSOUND *, TREE *, int, int, TYPE_TABLE*); char *check_annotated_type(CSOUND* csound, OENTRIES* entries, char* outArgTypes); static int genlabs = 300; TREE* tree_tail(TREE* node) { TREE* t = node; if (t == NULL) { return NULL; } while (t->next != NULL) { t = t->next; } return t; } char *create_out_arg(CSOUND *csound, char* outype, int argCount, TYPE_TABLE* typeTable) { char* s = (char *)csound->Malloc(csound, 16); switch(*outype) { case 'a': snprintf(s, 16, "#a%d", argCount); break; case 'K': case 'k': snprintf(s, 16, "#k%d", argCount); break; case 'B': snprintf(s, 16, "#B%d", argCount); break; case 'b': snprintf(s, 16, "#b%d", argCount); break; case 'f': snprintf(s, 16, "#f%d", argCount); break; case 't': snprintf(s, 16, "#k%d", argCount); break; case 'S': snprintf(s, 16, "#S%d", argCount); break; case '[': snprintf(s, 16, "#%c%d[]", outype[1], argCount); break; default: snprintf(s, 16, "#i%d", argCount); break; } if (*outype == '[') { add_array_arg(csound, s, 1, typeTable); } else { add_arg(csound, s, typeTable); } return s; } /** * Handles expression opcode type, appending to passed in opname * returns outarg type */ char * get_boolean_arg(CSOUND *csound, TYPE_TABLE* typeTable, int type) { char* s = (char *)csound->Malloc(csound, 8); snprintf(s, 8, "#%c%d", type?'B':'b', typeTable->localPool->synthArgCount++); return s; } static TREE *create_empty_token(CSOUND *csound) { TREE *ans; ans = (TREE*)csound->Malloc(csound, sizeof(TREE)); if (UNLIKELY(ans==NULL)) { /* fprintf(stderr, "Out of memory\n"); */ exit(1); } ans->type = -1; ans->left = NULL; ans->right = NULL; ans->next = NULL; ans->len = 0; ans->rate = -1; ans->line = 0; ans->locn = 0; ans->value = NULL; ans->markup = NULL; return ans; } static TREE *create_minus_token(CSOUND *csound) { TREE *ans; ans = (TREE*)csound->Malloc(csound, sizeof(TREE)); if (UNLIKELY(ans==NULL)) { /* fprintf(stderr, "Out of memory\n"); */ exit(1); } ans->type = INTEGER_TOKEN; ans->left = NULL; ans->right = NULL; ans->next = NULL; ans->len = 0; ans->rate = -1; ans->markup = NULL; ans->value = make_int(csound, "-1"); return ans; } static TREE * create_opcode_token(CSOUND *csound, char* op) { TREE *ans = create_empty_token(csound); ans->type = T_OPCODE; ans->value = make_token(csound, op); ans->value->type = T_OPCODE; return ans; } static TREE * create_ans_token(CSOUND *csound, char* var) { TREE *ans = create_empty_token(csound); ans->type = T_IDENT; ans->value = make_token(csound, var); ans->value->type = ans->type; return ans; } static TREE * create_goto_token(CSOUND *csound, char * booleanVar, TREE * gotoNode, int type) { /* TREE *ans = create_empty_token(csound); */ char* op = (char *)csound->Malloc(csound, 8); /* Unchecked */ TREE *opTree, *bVar; switch(gotoNode->type) { case KGOTO_TOKEN: strncpy(op, "ckgoto", 8); break; case IGOTO_TOKEN: strncpy(op, "cigoto", 8); break; case ITHEN_TOKEN: icase: strncpy(op, "cingoto", 8); break; case THEN_TOKEN: if (csound->inZero) goto icase; /* fall through */ case KTHEN_TOKEN: strncpy(op, "cngoto", 8); break; default: switch (type) { case 1: strncpy(op, "ckgoto", 8); break; case 0x8001: strncpy(op, "cnkgoto", 8); break; case 0: strncpy(op, "cggoto", 8); break; case 0x8000: strncpy(op,csound->inZero?"cingoto":"cngoto", 8); break; default: printf("Whooops %d\n", type); } } opTree = create_opcode_token(csound, op); bVar = create_empty_token(csound); bVar->type = T_IDENT; //(type ? T_IDENT_B : T_IDENT_b); bVar->value = make_token(csound, booleanVar); bVar->value->type = bVar->type; opTree->left = NULL; opTree->right = bVar; opTree->right->next = gotoNode->right; csound->Free(csound, op); return opTree; } /* THIS PROBABLY NEEDS TO CHANGE TO RETURN DIFFERENT GOTO TYPES LIKE IGOTO, ETC */ static TREE *create_simple_goto_token(CSOUND *csound, TREE *label, int type) { char* op = (char *)csound->Calloc(csound, 6); TREE * opTree; char *gt[3] = {"kgoto", "igoto", "goto"}; if (csound->inZero && type==2) type = 1; strncpy(op, gt[type],6); /* kgoto, igoto, goto ?? */ opTree = create_opcode_token(csound, op); opTree->left = NULL; opTree->right = label; csound->Free(csound, op); return opTree; } /* Returns true if passed in TREE node is a numerical expression */ int is_expression_node(TREE *node) { if (node == NULL) { return 0; } switch(node->type) { case '+': case '-': case '*': case '/': case '%': case '^': case T_FUNCTION: case S_UMINUS: case '|': case '&': case S_BITSHIFT_RIGHT: case S_BITSHIFT_LEFT: case '#': case '~': case '?': case T_ARRAY: return 1; } return 0; } /* Returns if passed in TREE node is a boolean expression */ int is_boolean_expression_node(TREE *node) { if (node == NULL) { return 0; } switch(node->type) { case S_EQ: case S_NEQ: case S_GE: case S_LE: case S_GT: case S_LT: case S_AND: case S_OR: case S_UNOT: return 1; } return 0; } static TREE *create_cond_expression(CSOUND *csound, TREE *root, int line, int locn, TYPE_TABLE* typeTable) { char *arg1, *arg2, *ans, *outarg = NULL; char* outype; TREE *anchor = create_boolean_expression(csound, root->left, line, locn, typeTable); TREE *last; TREE * opTree; TREE *b; TREE *c = root->right->left, *d = root->right->right; last = anchor; char condInTypes[64]; while (last->next != NULL) { last = last->next; } b= create_ans_token(csound, last->left->value->lexeme); if (is_expression_node(c)) { last->next = create_expression(csound, c, line, locn, typeTable); /* TODO - Free memory of old left node freetree */ last = last->next; while (last->next != NULL) { last = last->next; } c = create_ans_token(csound, last->left->value->lexeme); } if (is_expression_node(d)) { last->next = create_expression(csound, d, line, locn, typeTable); /* TODO - Free memory of old left node freetree */ last = last->next; while (last->next != NULL) { last = last->next; } d = create_ans_token(csound, last->left->value->lexeme); } arg1 = get_arg_type2(csound, c, typeTable); arg2 = get_arg_type2(csound, d, typeTable); ans = get_arg_type2(csound, b, typeTable); snprintf(condInTypes, 64, "%s%s%s", ans, arg1, arg2); OENTRIES* entries = find_opcode2(csound, ":cond"); outype = resolve_opcode_get_outarg(csound, entries, condInTypes); if (outype == NULL) { csound->Free(csound, entries); return NULL; } outarg = create_out_arg(csound, outype, typeTable->localPool->synthArgCount++, typeTable); opTree = create_opcode_token(csound, cs_strdup(csound, ":cond")); opTree->left = create_ans_token(csound, outarg); opTree->right = b; opTree->right->next = c; opTree->right->next->next = d; /* should recycle memory for root->right */ //csound->Free(csound, root->right); root->right = NULL; last->next = opTree; // print_tree(csound, "Answer:\n", anchor); csound->Free(csound, entries); return anchor; } static char* create_out_arg_for_expression(CSOUND* csound, char* op, TREE* left, TREE* right, TYPE_TABLE* typeTable) { char* outType; OENTRIES* opentries = find_opcode2(csound, op); char* leftArgType = get_arg_string_from_tree(csound, left, typeTable); char* rightArgType = get_arg_string_from_tree(csound, right, typeTable); char* argString = csound->Calloc(csound, 80); strncpy(argString, leftArgType, 80); strlcat(argString, rightArgType, 80); outType = resolve_opcode_get_outarg(csound, opentries, argString); csound->Free(csound, argString); csound->Free(csound, leftArgType); csound->Free(csound, rightArgType); csound->Free(csound, opentries); if (outType == NULL) return NULL; outType = convert_external_to_internal(csound, outType); return create_out_arg(csound, outType, typeTable->localPool->synthArgCount++, typeTable); } /** * Create a chain of Opcode (OPTXT) text from the AST node given. Called from * create_opcode when an expression node has been found as an argument */ static TREE *create_expression(CSOUND *csound, TREE *root, int line, int locn, TYPE_TABLE* typeTable) { char op[80], *outarg = NULL; TREE *anchor = NULL, *last; TREE * opTree, *current, *newArgList; OENTRIES* opentries; /* HANDLE SUB EXPRESSIONS */ if (root->type=='?') return create_cond_expression(csound, root, line, locn, typeTable); memset(op, 0, 80); current = root->left; newArgList = NULL; while (current != NULL) { if (is_expression_node(current)) { TREE* newArg; anchor = appendToTree(csound, anchor, create_expression(csound, current, line, locn, typeTable)); last = tree_tail(anchor); newArg = create_ans_token(csound, last->left->value->lexeme); newArgList = appendToTree(csound, newArgList, newArg); current = current->next; } else { TREE* temp; newArgList = appendToTree(csound, newArgList, current); temp = current->next; current->next = NULL; current = temp; } } root->left = newArgList; current = root->right; newArgList = NULL; while (current != NULL) { if (is_expression_node(current)) { TREE* newArg; anchor = appendToTree(csound, anchor, create_expression(csound, current, line, locn, typeTable)); last = tree_tail(anchor); newArg = create_ans_token(csound, last->left->value->lexeme); newArgList = appendToTree(csound, newArgList, newArg); current = current->next; } else { TREE* temp; newArgList = appendToTree(csound, newArgList, current); temp = current->next; current->next = NULL; current = temp; } } root->right = newArgList; switch(root->type) { case '+': strncpy(op, "##add", 80); outarg = create_out_arg_for_expression(csound, op, root->left, root->right, typeTable); break; case '-': strncpy(op, "##sub", 80); outarg = create_out_arg_for_expression(csound, op, root->left, root->right, typeTable); break; case '*': strncpy(op, "##mul", 80); outarg = create_out_arg_for_expression(csound, op, root->left, root->right, typeTable); break; case '%': strncpy(op, "##mod", 80); outarg = create_out_arg_for_expression(csound, op, root->left, root->right, typeTable); break; case '/': strncpy(op, "##div", 80); outarg = create_out_arg_for_expression(csound, op, root->left, root->right, typeTable); break; case '^': strncpy(op, "##pow", 80); outarg = create_out_arg_for_expression(csound, op, root->left, root->right, typeTable); break; case T_FUNCTION: { char *outtype, *outtype_internal; int len = strlen(root->value->lexeme); strncpy(op, root->value->lexeme, len); if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "Found OP: %s\n", op); opentries = find_opcode2(csound, root->value->lexeme); if (UNLIKELY(opentries->count == 0)) { csound->Warning(csound, Str("error: function %s not found, " "line %d \n"), root->value->lexeme, line); outtype = "i"; } else { char* inArgTypes = get_arg_string_from_tree(csound, root->right, typeTable); if (root->value->optype != NULL) outtype = check_annotated_type(csound, opentries, root->value->optype); /* if there are type annotations */ else outtype = resolve_opcode_get_outarg(csound, opentries, inArgTypes); csound->Free(csound, inArgTypes); } csound->Free(csound, opentries); if (UNLIKELY(outtype == NULL)) { csound->Warning(csound, Str("error: opcode %s with output type %s not found, " "line %d"), root->value->lexeme, root->value->optype, line); outtype = "i"; } outtype_internal = convert_external_to_internal(csound, outtype); outarg = create_out_arg(csound, outtype_internal, typeTable->localPool->synthArgCount++, typeTable); } break; case S_UMINUS: if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "HANDLING UNARY MINUS!"); root->left = create_minus_token(csound); // arg1 = 'i'; strncpy(op, "##mul", 80); outarg = create_out_arg_for_expression(csound, op, root->left, root->right, typeTable); break; case '|': strncpy(op, "##or", 80); outarg = create_out_arg_for_expression(csound, op, root->left, root->right, typeTable); break; case '&': strncpy(op, "##and", 80); outarg = create_out_arg_for_expression(csound, op, root->left, root->right, typeTable); break; case S_BITSHIFT_RIGHT: strncpy(op, "##shr", 80); outarg = create_out_arg_for_expression(csound, op, root->left, root->right, typeTable); break; case S_BITSHIFT_LEFT: strncpy(op, "##shl", 80); outarg = create_out_arg_for_expression(csound, op, root->left, root->right, typeTable); break; case '#': strncpy(op, "##xor", 80); outarg = create_out_arg_for_expression(csound, op, root->left, root->right, typeTable); break; case '~': { strncpy(op, "##not", 80); opentries = find_opcode2(csound, op); char* rightArgType = get_arg_string_from_tree(csound, root->right, typeTable); if (rightArgType == NULL) { return NULL; } char* outype = resolve_opcode_get_outarg(csound, opentries, rightArgType); csound->Free(csound, rightArgType); csound->Free(csound, opentries); if (outype == NULL) { return NULL; } outarg = create_out_arg(csound, outype, typeTable->localPool->synthArgCount++, typeTable); } break; case T_ARRAY: strncpy(op, "##array_get", 80); char* leftArgType = get_arg_string_from_tree(csound, root->left, typeTable); //FIXME: this is sort of hackish as it's checking and arg // string; should use a function to get the CS_TYPE of the var // instead if (strlen(leftArgType) > 1 && leftArgType[1] == '[') { outarg = create_out_arg(csound, get_array_sub_type(csound, root->left->value->lexeme), typeTable->localPool->synthArgCount++, typeTable); } else { opentries = find_opcode2(csound, op); char* rightArgType = get_arg_string_from_tree(csound, root->right, typeTable); leftArgType =csound->ReAlloc(csound, leftArgType, strlen(leftArgType) + strlen(rightArgType) + 1); char* argString = strcat(leftArgType, rightArgType); char* outype = resolve_opcode_get_outarg(csound, opentries, argString); csound->Free(csound, rightArgType); csound->Free(csound, leftArgType); csound->Free(csound, opentries); if (outype == NULL) { return NULL; } outarg = create_out_arg(csound, outype, typeTable->localPool->synthArgCount++, typeTable); } break; /* it should not get here, but if it does, return NULL */ default: return NULL; } opTree = create_opcode_token(csound, op); if (root->value) opTree->value->optype = root->value->optype; if (root->left != NULL) { opTree->right = root->left; opTree->right->next = root->right; opTree->left = create_ans_token(csound, outarg); opTree->line = line; opTree->locn = locn; //print_tree(csound, "making expression", opTree); } else { opTree->right = root->right; opTree->left = create_ans_token(csound, outarg); opTree->line = line; opTree->locn = locn; } if (anchor == NULL) { anchor = opTree; } else { last = anchor; while (last->next != NULL) { last = last->next; } last->next = opTree; } csound->Free(csound, outarg); return anchor; } /** * Create a chain of Opcode (OPTXT) text from the AST node given. Called from * create_opcode when an expression node has been found as an argument */ static TREE *create_boolean_expression(CSOUND *csound, TREE *root, int line, int locn, TYPE_TABLE* typeTable) { char *op, *outarg; TREE *anchor = NULL, *last; TREE * opTree; if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "Creating boolean expression\n"); /* HANDLE SUB EXPRESSIONS */ if (is_boolean_expression_node(root->left)) { anchor = create_boolean_expression(csound, root->left, line, locn, typeTable); last = anchor; while (last->next != NULL) { last = last->next; } /* TODO - Free memory of old left node freetree */ root->left = create_ans_token(csound, last->left->value->lexeme); } else if (is_expression_node(root->left)) { anchor = create_expression(csound, root->left, line, locn, typeTable); /* TODO - Free memory of old left node freetree */ last = anchor; while (last->next != NULL) { last = last->next; } root->left = create_ans_token(csound, last->left->value->lexeme); } if (is_boolean_expression_node(root->right)) { TREE * newRight = create_boolean_expression(csound, root->right, line, locn, typeTable); if (anchor == NULL) { anchor = newRight; } else { last = anchor; while (last->next != NULL) { last = last->next; } last->next = newRight; } last = newRight; while (last->next != NULL) { last = last->next; } /* TODO - Free memory of old right node freetree */ root->right = create_ans_token(csound, last->left->value->lexeme); } else if (is_expression_node(root->right)) { TREE * newRight = create_expression(csound, root->right, line, locn, typeTable); if (anchor == NULL) { anchor = newRight; } else { last = anchor; while (last->next != NULL) { last = last->next; } last->next = newRight; } last = newRight; while (last->next != NULL) { last = last->next; } /* TODO - Free memory of old right node freetree */ root->right = create_ans_token(csound, last->left->value->lexeme); root->line = line; root->locn = locn; } op = csound->Calloc(csound, 80); switch(root->type) { case S_UNOT: strncpy(op, "!", 80); break; case S_EQ: strncpy(op, "==", 80); break; case S_NEQ: strncpy(op, "!=", 80); break; case S_GE: strncpy(op, ">=", 80); break; case S_LE: strncpy(op, "<=", 80); break; case S_GT: strncpy(op, ">", 80); break; case S_LT: strncpy(op, "<", 80); break; case S_AND: strncpy(op, "&&", 80); break; case S_OR: strncpy(op, "||", 80); break; } if (UNLIKELY(PARSER_DEBUG)) { if (root->type == S_UNOT) csound->Message(csound, "Operator Found: %s (%c)\n", op, argtyp2( root->left->value->lexeme)); else csound->Message(csound, "Operator Found: %s (%c %c)\n", op, argtyp2( root->left->value->lexeme), argtyp2( root->right->value->lexeme)); } if (root->type == S_UNOT) { outarg = get_boolean_arg(csound, typeTable, argtyp2( root->left->value->lexeme) =='k' || argtyp2( root->left->value->lexeme) =='B'); } else outarg = get_boolean_arg(csound, typeTable, argtyp2( root->left->value->lexeme) =='k' || argtyp2( root->right->value->lexeme)=='k' || argtyp2( root->left->value->lexeme) =='B' || argtyp2( root->right->value->lexeme)=='B'); add_arg(csound, outarg, typeTable); opTree = create_opcode_token(csound, op); opTree->right = root->left; opTree->right->next = root->right; opTree->left = create_ans_token(csound, outarg); if (anchor == NULL) { anchor = opTree; } else { last = anchor; while (last->next != NULL) { last = last->next; } last->next = opTree; } csound->Free(csound, outarg); csound->Free(csound, op); return anchor; } static TREE *create_synthetic_ident(CSOUND *csound, int32 count) { char *label = (char *)csound->Calloc(csound, 20); ORCTOKEN *token; snprintf(label,20, "__synthetic_%ld", (long)count); if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "Creating Synthetic T_IDENT: %s\n", label); token = make_token(csound, label); token->type = T_IDENT; csound->Free(csound, label); return make_leaf(csound, -1, 0, T_IDENT, token); } static TREE *create_synthetic_label(CSOUND *csound, int32 count) { char *label = (char *)csound->Calloc(csound, 20); ORCTOKEN *token; snprintf(label, 20, "__synthetic_%ld:", (long)count); if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "Creating Synthetic label: %s\n", label); token = make_label(csound, label); csound->Free(csound, label); return make_leaf(csound, -1, 0, LABEL_TOKEN, token); } void handle_negative_number(CSOUND* csound, TREE* root) { if (root->type == S_UMINUS && (root->right->type == INTEGER_TOKEN || root->right->type == NUMBER_TOKEN)) { int len = strlen(root->right->value->lexeme); char* negativeNumber = csound->Malloc(csound, len + 3); negativeNumber[0] = '-'; strcpy(negativeNumber + 1, root->right->value->lexeme); negativeNumber[len + 2] = '\0'; root->type = root->right->type; root->value = root->right->type == INTEGER_TOKEN ? make_int(csound, negativeNumber) : make_num(csound, negativeNumber); root->value->lexeme = negativeNumber; } } static void collapse_last_assigment(CSOUND* csound, TREE* anchor, TYPE_TABLE* typeTable) { TREE *a, *b, *temp; temp = anchor; if (temp == NULL || temp->next == NULL) { return; } while (temp->next != NULL) { a = temp; b = temp->next; temp = temp->next; } if (b == NULL || a->left == NULL || b->left == NULL || b->right == NULL) { return; } char *tmp1 = get_arg_type2(csound, b->left, typeTable); char *tmp2 = get_arg_type2(csound, b->right, typeTable); if ((b->type == '=') && !strcmp(a->left->value->lexeme, b->right->value->lexeme) && tmp1 == tmp2) { a->left = b->left; a->next = NULL; csound->Free(csound, b); } csound->Free(csound, tmp1); csound->Free(csound, tmp2); } /* returns the head of a list of TREE* nodes, expanding all RHS expressions into statements prior to the original statement line, and LHS expressions (array sets) after the original statement line */ TREE* expand_statement(CSOUND* csound, TREE* current, TYPE_TABLE* typeTable) { /* This is WRONG in optional argsq */ TREE* anchor = NULL; TREE* originalNext = current->next; TREE* previousArg = NULL; TREE* currentArg = current->right; current->next = NULL; if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "Found Statement.\n"); while (currentArg != NULL) { TREE* last; TREE *nextArg; TREE *newArgTree; TREE *expressionNodes; int is_bool = 0; handle_negative_number(csound, currentArg); if (is_expression_node(currentArg) || (is_bool = is_boolean_expression_node(currentArg))) { char * newArg; if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "Found Expression.\n"); if (is_bool == 0) { expressionNodes = create_expression(csound, currentArg, currentArg->line, currentArg->locn, typeTable); // free discarded node } else { expressionNodes = create_boolean_expression(csound, currentArg, currentArg->line, currentArg->locn, typeTable); } nextArg = currentArg->next; csound->Free(csound, currentArg); /* Set as anchor if necessary */ anchor = appendToTree(csound, anchor, expressionNodes); /* reconnect into chain */ last = tree_tail(expressionNodes); newArg = last->left->value->lexeme; if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "New Arg: %s\n", newArg); /* handle arg replacement of currentArg here */ /* **** was a bug as currentArg could be freed above **** */ //nextArg = currentArg->next; newArgTree = create_ans_token(csound, newArg); if (previousArg == NULL) { current->right = newArgTree; } else { previousArg->next = newArgTree; } newArgTree->next = nextArg; currentArg = newArgTree; /* TODO - Delete the expression nodes here */ } previousArg = currentArg; currentArg = currentArg->next; } anchor = appendToTree(csound, anchor, current); // handle LHS expressions (i.e. array-set's) previousArg = NULL; currentArg = current->left; int init = 0; if (strcmp("init", current->value->lexeme)==0) { //print_tree(csound, "init",current); init = 1; } while (currentArg != NULL) { TREE* temp; if (currentArg->type == T_ARRAY) { char *outType; char* leftArgType = get_arg_string_from_tree(csound, currentArg->left, typeTable); //FIXME: this is sort of hackish as it's checking and arg // string; should use a function to get the CS_TYPE of the // var instead if (strlen(leftArgType) > 1 && leftArgType[1] == '[') { outType = get_array_sub_type(csound, currentArg->left->value->lexeme); if (init) outType = "i"; } else { // FIXME - this is hardcoded to "k" for now. The problem // here is that this body of code is essentially looking // for what type to use for the synthesized in-type. I // think the solution is to use the types from the opcode // that this LHS array_set is being used with, but this is // not implemented. // OENTRIES* opentries = find_opcode2(csound, "##array_set"); // // char* rightArgType = get_arg_string_from_tree(csound, // currentArg->right, // typeTable); // // char* argString = strcat(leftArgType, rightArgType); // argString = strcat(argString, "k"); // FIXME - this is hardcoding a k input for what would be the in arg type // // outType = resolve_opcode_get_outarg(csound, opentries, // argString); outType = init ? "i":"k"; // free(argString); // if (outType == NULL) { // return NULL; // } } temp = create_ans_token(csound, create_out_arg(csound, outType, typeTable->localPool->synthArgCount++, typeTable)); if (previousArg == NULL) { current->left = temp; } else { previousArg->next = temp; } temp->next = currentArg->next; TREE* arraySet = create_opcode_token(csound, (init ? "##array_init": "##array_set")); arraySet->right = currentArg->left; arraySet->right->next = make_leaf(csound, temp->line, temp->locn, T_IDENT, make_token(csound, temp->value->lexeme)); arraySet->right->next->next = currentArg->right; // TODO - check if this handles expressions anchor = appendToTree(csound, anchor, arraySet); //print_tree(csound, "anchor", anchor); currentArg = temp; csound->Free(csound, leftArgType); } previousArg = currentArg; currentArg = currentArg->next; } handle_optional_args(csound, current); collapse_last_assigment(csound, anchor, typeTable); appendToTree(csound, anchor, originalNext); return anchor; } /* Flattens one level of if-blocks, sub-if-blocks should get flattened when the expander goes through statements */ TREE* expand_if_statement(CSOUND* csound, TREE* current, TYPE_TABLE* typeTable) { TREE* anchor = NULL; TREE* expressionNodes = NULL; TREE* left = current->left; TREE* right = current->right; TREE* last; TREE* gotoToken; if (right->type == IGOTO_TOKEN || right->type == KGOTO_TOKEN || right->type == GOTO_TOKEN) { if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "Found if-goto\n"); expressionNodes = create_boolean_expression(csound, left, right->line, right->locn, typeTable); anchor = appendToTree(csound, anchor, expressionNodes); /* reconnect into chain */ last = tree_tail(expressionNodes); gotoToken = create_goto_token(csound, last->left->value->lexeme, right, last->left->type == 'k' || right->type =='k'); last->next = gotoToken; gotoToken->next = current->next; } else if (LIKELY(right->type == THEN_TOKEN || right->type == ITHEN_TOKEN || right->type == KTHEN_TOKEN)) { int endLabelCounter = -1; TREE *tempLeft; TREE *tempRight; TREE* last; TREE *ifBlockCurrent = current; if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "Found if-then\n"); if (right->next != NULL) { endLabelCounter = genlabs++; } while (ifBlockCurrent != NULL) { tempLeft = ifBlockCurrent->left; tempRight = ifBlockCurrent->right; if (ifBlockCurrent->type == ELSE_TOKEN) { appendToTree(csound, anchor, tempRight); break; } expressionNodes = create_boolean_expression(csound, tempLeft, tempLeft->line, tempLeft->locn, typeTable); anchor = appendToTree(csound, anchor, expressionNodes); last = tree_tail(expressionNodes); /* reconnect into chain */ { TREE *statements, *label, *labelEnd, *gotoToken; int gotoType; statements = tempRight->right; label = create_synthetic_ident(csound, genlabs); labelEnd = create_synthetic_label(csound, genlabs++); tempRight->right = label; typeTable->labelList = cs_cons(csound, cs_strdup(csound, labelEnd->value->lexeme), typeTable->labelList); //printf("allocate label %s\n", typeTable->labelList->value ); gotoType = // checking for #B... var name (last->left->value->lexeme[1] == 'B'); gotoToken = create_goto_token(csound, last->left->value->lexeme, tempRight, gotoType); gotoToken->next = statements; anchor = appendToTree(csound, anchor, gotoToken); /* relinking */ last = tree_tail(last); if (endLabelCounter > 0) { TREE *endLabel = create_synthetic_ident(csound, endLabelCounter); int type = (gotoType == 1) ? 0 : 2; /* csound->DebugMsg(csound, "%s(%d): type = %d %d\n", */ /* __FILE__, __LINE__, type, gotoType); */ TREE *gotoEndLabelToken = create_simple_goto_token(csound, endLabel, type); if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "Creating simple goto token\n"); appendToTree(csound, last, gotoEndLabelToken); gotoEndLabelToken->next = labelEnd; } else { appendToTree(csound, last, labelEnd); } ifBlockCurrent = tempRight->next; } } if (endLabelCounter > 0) { TREE *endLabel = create_synthetic_label(csound, endLabelCounter); anchor = appendToTree(csound, anchor, endLabel); typeTable->labelList = cs_cons(csound, cs_strdup(csound, endLabel->value->lexeme), typeTable->labelList); //printf("allocate label %s\n", typeTable->labelList->value ); } anchor = appendToTree(csound, anchor, current->next); } else { csound->Message(csound, Str("ERROR: Neither if-goto or if-then found on line %d!!!"), right->line); } return anchor; } /* 1. create top label to loop back to 2. do boolean expression 3. do goto token that checks boolean and goes to end label 4. insert statements 5. add goto token that goes to top label 6. end label */ TREE* expand_until_statement(CSOUND* csound, TREE* current, TYPE_TABLE* typeTable, int dowhile) { TREE* anchor = NULL; TREE* expressionNodes = NULL; TREE* gotoToken; int32 topLabelCounter = genlabs++; int32 endLabelCounter = genlabs++; TREE* tempRight = current->right; TREE* last = NULL; TREE* labelEnd; int gotoType; anchor = create_synthetic_label(csound, topLabelCounter); typeTable->labelList = cs_cons(csound, cs_strdup(csound, anchor->value->lexeme), typeTable->labelList); expressionNodes = create_boolean_expression(csound, current->left, current->line, current->locn, typeTable); anchor = appendToTree(csound, anchor, expressionNodes); last = tree_tail(anchor); labelEnd = create_synthetic_label(csound, endLabelCounter); typeTable->labelList = cs_cons(csound, cs_strdup(csound, labelEnd->value->lexeme), typeTable->labelList); gotoType = last->left->value->lexeme[1] == 'B'; // checking for #B... var name //printf("gottype = %d ; dowhile = %d\n", gotoType, dowhile); gotoToken = create_goto_token(csound, last->left->value->lexeme, labelEnd, gotoType+0x8000*dowhile); gotoToken->next = tempRight; gotoToken->right->next = labelEnd; last = appendToTree(csound, last, gotoToken); last = tree_tail(last); labelEnd = create_synthetic_label(csound, endLabelCounter); TREE *topLabel = create_synthetic_ident(csound, topLabelCounter); TREE *gotoTopLabelToken = create_simple_goto_token(csound, topLabel, (gotoType==1 ? 0 : 1)); appendToTree(csound, last, gotoTopLabelToken); gotoTopLabelToken->next = labelEnd; labelEnd->next = current->next; return anchor; } int is_statement_expansion_required(TREE* root) { TREE* current = root->right; while (current != NULL) { if (is_boolean_expression_node(current) || is_expression_node(current)) { return 1; } current = current->next; } current = root->left; while (current != NULL) { if (current->type == T_ARRAY) { return 1; } current = current->next; } return 0; } /* Expands expression nodes into opcode calls * * * for if-goto, expands to: * 1. Expression nodes - all of the expressions that lead to the boolean var * 2. goto node - a conditional goto to evals the boolean var and goes to a * label * * for if-then-elseif-else, expands to: * 1. for each conditional, converts to a set of: * -expression nodes * -conditional not-goto that goes to block end label if condition does * not pass (negative version of conditional is used to conditional skip * contents of block) * -statements (body of within conditional block) * -goto complete block end (this signifies that at the end of these * statements, skip all other elseif or else branches and go to very end) * -block end label * 2. for else statements found, do no conditional and just link in statements * * */ //TREE *csound_orc_expand_expressions(CSOUND * csound, TREE *root) //{ // // int32 labelCounter = 300L; // // TREE *anchor = NULL; // TREE * expressionNodes = NULL; // // TREE *current = root; // TREE *previous = NULL; // // if (UNLIKELY(PARSER_DEBUG)) // csound->Message(csound, "[Begin Expanding Expressions in AST]\n"); // // while (current != NULL) { // switch(current->type) { // case INSTR_TOKEN: // if (UNLIKELY(PARSER_DEBUG)) // csound->Message(csound, "Instrument found\n"); // current->right = csound_orc_expand_expressions(csound, current->right); // //print_tree(csound, "AFTER", current); // break; // // case UDO_TOKEN: // if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "UDO found\n"); // current->right = csound_orc_expand_expressions(csound, current->right); // break; // // case IF_TOKEN: // if (UNLIKELY(PARSER_DEBUG)) // csound->Message(csound, "Found IF statement\n"); // // current = expand_if_statement(csound, current); // // if (previous != NULL) { // previous->next = current; // } // // continue; // case UNTIL_TOKEN: // if (UNLIKELY(PARSER_DEBUG)) // csound->Message(csound, "Found UNTIL statement\n"); // // current = expand_until_statement(csound, current); // // if (previous != NULL) { // previous->next = current; // } // // continue; // // case LABEL_TOKEN: // break; // // default: // //maincase: // if (is_statement_expansion_required(current)) { // current = expand_statement(csound, current); // // if (previous != NULL) { // previous->next = current; // } // continue; // } else { // handle_optional_args(csound, current); // } // } // // if (anchor == NULL) { // anchor = current; // } // previous = current; // current = current->next; // } // // if (UNLIKELY(PARSER_DEBUG)) // csound->Message(csound, "[End Expanding Expressions in AST]\n"); // // return anchor; //} csound-6.10.0/Engine/csound_orc_optimize.c000066400000000000000000000211061321653344700205300ustar00rootroot00000000000000 /* csound_orc_optimize.c: Copyright (C) 2006 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "csound_orc.h" static TREE * create_fun_token(CSOUND *csound, TREE *right, char *fname) { TREE *ans; ans = (TREE*)csound->Malloc(csound, sizeof(TREE)); if (UNLIKELY(ans == NULL)) exit(1); ans->type = T_FUNCTION; ans->value = make_token(csound, fname); ans->value->type = T_FUNCTION; ans->left = NULL; ans->right = right; ans->next = NULL; ans->len = 0; ans->markup = NULL; ans->rate = -1; return ans; } static TREE * optimize_ifun(CSOUND *csound, TREE *root) { /* print_tree(csound, "optimize_ifun: before", root); */ switch(root->right->type) { case INTEGER_TOKEN: case NUMBER_TOKEN: /* i(num) -> num */ // FIXME - reinstate optimization after implementing get_type(varname) // case T_IDENT_I: /* i(ivar) -> ivar */ // case T_IDENT_GI: /* i(givar) -> givar */ // case T_IDENT_P: /* i(pN) -> pN */ root = root->right; break; // case T_IDENT_K: /* i(kvar) -> i(kvar) */ // case T_IDENT_GK: /* i(gkvar) -> i(gkvar) */ // break; case T_FUNCTION: /* i(fn(x)) -> fn(i(x)) */ { TREE *funTree = root->right; funTree->right = create_fun_token(csound, funTree->right, "i"); root = funTree; } break; default: /* i(A op B) -> i(A) op i(B) */ if (root->right->left != NULL) root->right->left = create_fun_token(csound, root->right->left, "i"); if (root->right->right != NULL) root->right->right = create_fun_token(csound, root->right->right, "i"); root->right->next = root->next; root = root->right; break; } /* print_tree(csound, "optimize_ifun: after", root); */ return root; } /** Verifies and optimise; constant fold and opcodes and args are correct*/ /* The wrong place to fold constants so done in parser -- JPff */ static TREE * verify_tree1(CSOUND *csound, TREE *root) { TREE *last; //print_tree(csound, "Verify", root); if (root->right && root->right->type != T_INSTLIST) { if (root->type == T_OPCODE || root->type == T_OPCODE0) { last = root->right; while (last->next) { /* we optimize the i() functions in the opcode */ if (last->next->type == T_FUNCTION && (strcmp(last->next->value->lexeme, "i") == 0)) { TREE *temp = optimize_ifun(csound, last->next); temp->next = last->next->next; last->next = temp; } last = last->next; } } if (root->right->type == T_FUNCTION && (strcmp(root->right->value->lexeme, "i") == 0)) { /* i() function */ root->right = optimize_ifun(csound, root->right); } last = root->right; while (last->next) { last->next = verify_tree1(csound, last->next); last = last->next; } root->right = verify_tree1(csound, root->right); if (root->left) { if (root->left->type == T_FUNCTION && (strcmp(root->left->value->lexeme, "i") == 0)) { /* i() function */ root->left = optimize_ifun(csound, root->left); } root->left= verify_tree1(csound, root->left); } } return root; } TREE* constant_fold(CSOUND *csound, TREE* root) { extern MYFLT MOD(MYFLT, MYFLT); TREE* current = root; while (current) { switch (current->type) { case '+': case '-': case '*': case '/': case '^': case '%': case '|': case '&': case '#': case S_BITSHIFT_LEFT: case S_BITSHIFT_RIGHT: current->left = constant_fold(csound, current->left); current->right = constant_fold(csound, current->right); //print_tree(csound, "Folding case??\n", current); if ((current->left->type == INTEGER_TOKEN || current->left->type == NUMBER_TOKEN) && (current->right->type == INTEGER_TOKEN || current->right->type == NUMBER_TOKEN)) { MYFLT lval, rval; char buf[64]; lval = (current->left->type == INTEGER_TOKEN ? (double)current->left->value->value : current->left->value->fvalue); rval = (current->right->type == INTEGER_TOKEN ? (double)current->right->value->value : current->right->value->fvalue); //printf("lval = %g rval = %g\n", lval, rval); switch (current->type) { case '+': lval = lval + rval; break; case '-': lval = lval - rval; break; case '*': lval = lval * rval; break; case '/': lval = lval / rval; break; case '^': lval = POWER(lval,rval); break; case '%': lval = MOD(lval,rval); break; case '|': lval = (MYFLT)(((int)lval)|((int)rval)); break; case '&': lval = (MYFLT)(((int)lval)&((int)rval)); break; case '#': lval = (MYFLT)(((int)lval)^((int)rval)); break; case S_BITSHIFT_LEFT: lval = (MYFLT)(((int)lval)<<((int)rval)); break; case S_BITSHIFT_RIGHT: lval = (MYFLT)(((int)lval)>>((int)rval)); break; } //printf("ans = %g\n", lval); current->value = current->left->value; current->type = NUMBER_TOKEN; current->value->fvalue = lval; snprintf(buf, 60, "%.20g", lval); csound->Free(csound, current->value->lexeme); current->value->lexeme = cs_strdup(csound, buf); csound->Free(csound, current->left); csound->Free(csound, current->right->value); csound->Free(csound, current->right); current->right = current->left = NULL; } break; case S_UMINUS: case '~': //print_tree(csound, "Folding case?\n", current); current->right = constant_fold(csound, current->right); //print_tree(csound, "Folding case??\n", current); if (current->right->type == INTEGER_TOKEN || current->right->type == NUMBER_TOKEN) { MYFLT lval; char buf[64]; lval = (current->right->type == INTEGER_TOKEN ? (double)current->right->value->value : current->right->value->fvalue); switch (current->type) { case S_UMINUS: lval = -lval; break; case '~': lval = (MYFLT)(~(int)lval); break; } current->value = current->right->value; current->type = NUMBER_TOKEN; current->value->fvalue = lval; snprintf(buf, 60, "%.20g", lval); csound->Free(csound, current->value->lexeme); current->value->lexeme = cs_strdup(csound, buf); csound->Free(csound, current->right); current->right = NULL; } break; default: current->left = constant_fold(csound, current->left); current->right = constant_fold(csound, current->right); } current = current->next; } return root; } /* Optimizes tree (expressions, etc.) */ TREE * csound_orc_optimize(CSOUND *csound, TREE *root) { TREE *original=root, *last = NULL; while (root) { TREE *xx = verify_tree1(csound, root); if (xx != root) { xx->next = root->next; if (last) last->next = xx; else original = xx; } last = root; root = root->next; } return original; } csound-6.10.0/Engine/csound_orc_semantics.c000066400000000000000000002250251321653344700206640ustar00rootroot00000000000000/* csound_orc_semantics.c: Copyright (C) 2006 John ffitch, Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include //#include #include "csoundCore.h" #include "csound_orc.h" #include "namedins.h" #include "parse_param.h" #include "csound_type_system.h" #include "csound_standard_types.h" #include "csound_orc_expressions.h" #include "csound_orc_semantics.h" extern char *csound_orcget_text ( void *scanner ); static int is_label(char* ident, CONS_CELL* labelList); extern uint64_t csound_orcget_locn(void *); extern char argtyp2(char*); extern int tree_arg_list_count(TREE *); void print_tree(CSOUND *, char *, TREE *); /* from csound_orc_compile.c */ extern int argsRequired(char* arrayName); extern char** splitArgs(CSOUND* csound, char* argString); extern int pnum(char*); OENTRIES* find_opcode2(CSOUND*, char*); char* resolve_opcode_get_outarg(CSOUND* csound, OENTRIES* entries, char* inArgTypes); int check_out_args(CSOUND* csound, char* outArgsFound, char* opOutArgs); char* get_arg_string_from_tree(CSOUND* csound, TREE* tree, TYPE_TABLE* typeTable); char* convert_internal_to_external(CSOUND* csound, char* arg); char* convert_external_to_internal(CSOUND* csound, char* arg); void do_baktrace(CSOUND *csound, uint64_t files); const char* SYNTHESIZED_ARG = "_synthesized"; char* cs_strdup(CSOUND* csound, char* str) { size_t len; char* retVal; if (str == NULL) return NULL; len = strlen(str); retVal = csound->Malloc(csound, len + 1); if (len > 0) { strncpy(retVal, str, len); } retVal[len] = '\0'; return retVal; } char* cs_strndup(CSOUND* csound, char* str, size_t size) { size_t len; char* retVal; if (str == NULL || size == 0) return NULL; len = strlen(str); if (size > len) { // catches if str is empty string return cs_strdup(csound, str); } retVal = csound->Malloc(csound, size + 1); memcpy(retVal, str, size); retVal[size] = '\0'; return retVal; } char* get_expression_opcode_type(CSOUND* csound, TREE* tree) { switch(tree->type) { case '+': return "##add"; case '-': return "##sub"; case '*': return "##mul"; case '%': return "##mod"; case '/': return "##div"; case '^': return "##pow"; case S_UMINUS: return "##mul"; case '|': return "##or"; case '&': return "##and"; case S_BITSHIFT_RIGHT: return "##shr"; case S_BITSHIFT_LEFT: return "##shl"; case '#': return "##xor"; case '~': return "##not"; case T_ARRAY: return "##array_get"; } csound->Warning(csound, Str("Unknown function type found: %d [%c]\n"), tree->type, tree->type); return NULL; } char* get_boolean_expression_opcode_type(CSOUND* csound, TREE* tree) { switch(tree->type) { case S_EQ: return "=="; case S_NEQ: return "!="; case S_GE: return ">="; case S_LE: return "<="; case S_GT: return ">"; case S_LT: return "<"; case S_AND: return "&&"; case S_OR: return "||"; case S_UNOT: return "!"; } csound->Warning(csound, Str("Unknown boolean expression type found: %d\n"), tree->type); return NULL; } //FIXME - current just returns subtype but assumes single char type name, // should check for long type names, as well as check dimensions and remove one char* get_array_sub_type(CSOUND* csound, char* arrayName) { char temp[2]; char *t = arrayName; if (*t == '#') t++; if (*t == 'g') t++; if (*t == 't') { /* Support legacy t-vars by mapping to k subtypes */ return cs_strdup(csound, "k"); } while (*t == '[') { t++; } temp[0] = *t; temp[1] = 0; return cs_strdup(csound, temp); } char* create_array_arg_type(CSOUND* csound, CS_VARIABLE* arrayVar) { int i, len = arrayVar->dimensions + 3; char* retVal = csound->Malloc(csound, len); retVal[len - 1] = '\0'; retVal[len - 2] = ']'; retVal[len - 3] = *arrayVar->subType->varTypeName; for (i = len - 4; i >= 0; i--) { retVal[i] = '['; } return retVal; } /* this checks if the annotated type exists */ char *check_annotated_type(CSOUND* csound, OENTRIES* entries, char* outArgTypes) { int i; for (i = 0; i < entries->count; i++) { OENTRY* temp = entries->entries[i]; if (check_out_args(csound, outArgTypes, temp->outypes)) return outArgTypes; } return NULL; } static int isirate(/*CSOUND *csound,*/ TREE *t) { /* check that argument is an i-rate constant or variable */ //print_tree(csound, "isirate", t); if (t->type == INTEGER_TOKEN) { //printf("integer case\n"); return 1; } else if (t->type == T_IDENT) { //printf("identifier case\n"); if (t->value->lexeme[0] != 'p' && t->value->lexeme[0] != 'i' && (t->value->lexeme[0] != 'g' || t->value->lexeme[1] != 'i')) return 0; return 1; } else if (t->type == T_ARRAY) { //printf("array case\n"); if (isirate(/*csound, */t->right)==0) return 0; t = t->next; while (t) { //printf("t=%p t->type=%d\n", t, t->type); if (isirate(/*csound,*/ t)==0) return 0; t = t->next; } return 1; } else return 0; } /* This function gets arg type with checking type table */ char* get_arg_type2(CSOUND* csound, TREE* tree, TYPE_TABLE* typeTable) { char* s; char* t; //CS_TYPE* type; CS_VARIABLE* var; if (is_expression_node(tree)) { TREE* nodeToCheck = tree; if (tree->type == T_ARRAY) { char* leftArgType = get_arg_type2(csound, tree->left, typeTable); //FIXME - should use CS_TYPE and not interrogate string if (leftArgType[0] == '[') { return get_array_sub_type(csound, tree->left->value->lexeme); } else { char* rightArgType = get_arg_string_from_tree(csound, tree->right, typeTable); leftArgType = csound->ReAlloc(csound, leftArgType, strlen(leftArgType) + strlen(rightArgType) + 1); char* argString = strcat(leftArgType, rightArgType); OENTRIES* opentries = find_opcode2(csound, "##array_get"); char* outype = resolve_opcode_get_outarg(csound, opentries, argString); csound->Free(csound, opentries); if (UNLIKELY(outype == NULL)) { synterr(csound, Str("unable to find array operator for " "types %s line %d\n"), argString, tree->line); do_baktrace(csound, tree->locn); return NULL; } csound->Free(csound, leftArgType); csound->Free(csound, rightArgType); return cs_strdup(csound, outype); } } if (tree->type == '?') { char* arg1, *arg2, *ans, *out; char condInTypes[64]; ans = get_arg_type2(csound, tree->left, typeTable); if (UNLIKELY(ans == NULL || (*ans != 'b' && *ans != 'B'))) { synterr(csound, Str("non-boolean expression found for ternary operator," " line %d\n"), tree->line); do_baktrace(csound, tree->locn); return NULL; } arg1 = get_arg_type2(csound, tree->right->left, typeTable); arg2 = get_arg_type2(csound, tree->right->right, typeTable); snprintf(condInTypes, 64, "%s%s%s", ans, arg1, arg2); OENTRIES* opentries = find_opcode2(csound, ":cond"); out = resolve_opcode_get_outarg(csound, opentries, condInTypes); csound->Free(csound, opentries); if (UNLIKELY(out == NULL)) { synterr(csound, Str("unable to find ternary operator for " "types '%s ? %s : %s' line %d\n"), ans, arg1, arg2, tree->line); do_baktrace(csound, tree->locn); return NULL; } csound->Free(csound, arg1); csound->Free(csound, arg2); csound->Free(csound, ans); return cs_strdup(csound, out); } // Deal with odd case of i(expressions) if (tree->type == T_FUNCTION && !strcmp(tree->value->lexeme, "i")) { //print_tree(csound, "i()", tree); if (tree->right->type == T_ARRAY && tree->right->left->type == T_IDENT && isirate(/*csound,*/ tree->right->right)) { //printf("OK array case\n"); } else if (UNLIKELY(tree->right->type != LABEL_TOKEN)) synterr(csound, Str("Use of i() with expression not permitted on line %d\n"), tree->line); } if (tree->type == T_FUNCTION) { char* argTypeRight = get_arg_string_from_tree(csound, tree->right, typeTable); char* opname = tree->value->lexeme; OENTRIES* entries = find_opcode2(csound, opname); char * out; if (tree->value->optype != NULL) /* if there is type annotation */ out = check_annotated_type(csound, entries, tree->value->optype); else out = resolve_opcode_get_outarg(csound, entries, argTypeRight); if (UNLIKELY(out == 0)) { synterr(csound, Str("error: opcode '%s' for expression with arg " "types %s not found, line %d\n"), opname, argTypeRight, tree->line); do_baktrace(csound, tree->locn); return NULL; } csound->Free(csound, argTypeRight); csound->Free(csound, entries); return cs_strdup(csound, out); } char* argTypeRight = get_arg_type2(csound, nodeToCheck->right, typeTable); if (nodeToCheck->left != NULL) { char* argTypeLeft = get_arg_type2(csound, nodeToCheck->left, typeTable); char* opname = get_expression_opcode_type(csound, nodeToCheck); int len1, len2; char* inArgTypes; char* out; if (UNLIKELY(argTypeLeft == NULL || argTypeRight == NULL)) { synterr(csound, Str("Unable to verify arg types for expression '%s'\n" "Line %d\n"), opname, tree->line); do_baktrace(csound, tree->locn); return NULL; } OENTRIES* entries = find_opcode2(csound, opname); argTypeLeft = convert_internal_to_external(csound, argTypeLeft); argTypeRight = convert_internal_to_external(csound, argTypeRight); len1 = strlen(argTypeLeft); len2 = strlen(argTypeRight); inArgTypes = csound->Malloc(csound, len1 + len2 + 1); strncpy(inArgTypes, argTypeLeft, len1); strncpy(inArgTypes + len1, argTypeRight, len2); inArgTypes[len1 + len2] = '\0'; out = resolve_opcode_get_outarg(csound, entries, inArgTypes); csound->Free(csound, entries); if (UNLIKELY(out == NULL)) { synterr(csound, Str("error: opcode '%s' for expression with arg " "types %s not found, line %d \n"), opname, inArgTypes, tree->line); do_baktrace(csound, tree->locn); csound->Free(csound, inArgTypes); return NULL; } csound->Free(csound, argTypeLeft); csound->Free(csound, argTypeRight); csound->Free(csound, inArgTypes); return cs_strdup(csound, out); } else { return argTypeRight; } } if (is_boolean_expression_node(tree)) { if (tree->type == S_UNOT) { return get_arg_type2(csound, tree->left, typeTable); } else { char* argTypeLeft = get_arg_type2(csound, tree->left, typeTable); char* argTypeRight = get_arg_type2(csound, tree->right, typeTable); char* opname = get_boolean_expression_opcode_type(csound, tree); int len1, len2; char* inArgTypes; char* out; OENTRIES* entries; if (UNLIKELY(argTypeLeft == NULL || argTypeRight == NULL)) { synterr(csound, Str("Unable to verify arg types for boolean expression '%s'\n" "Line %d\n"), opname, tree->line); do_baktrace(csound, tree->locn); return NULL; } entries = find_opcode2(csound, opname); len1 = strlen(argTypeLeft); len2 = strlen(argTypeRight); inArgTypes = csound->Malloc(csound, len1 + len2 + 1); strncpy(inArgTypes, argTypeLeft, len1); strncpy(inArgTypes + len1, argTypeRight, len2); inArgTypes[len1 + len2] = '\0'; out = resolve_opcode_get_outarg(csound, entries, inArgTypes); csound->Free(csound, entries); if (UNLIKELY(out == NULL)) { synterr(csound, Str("error: boolean expression '%s' with arg " "types %s not found, line %d \n"), opname, inArgTypes, tree->line); do_baktrace(csound, tree->locn); csound->Free(csound, inArgTypes); return NULL; } csound->Free(csound, argTypeLeft); csound->Free(csound, argTypeRight); csound->Free(csound, inArgTypes); return cs_strdup(csound, out); } } switch(tree->type) { case NUMBER_TOKEN: case INTEGER_TOKEN: return cs_strdup(csound, "c"); /* const */ case STRING_TOKEN: return cs_strdup(csound, "S"); /* quoted String */ case SRATE_TOKEN: case KRATE_TOKEN: case KSMPS_TOKEN: case A4_TOKEN: case ZERODBFS_TOKEN: case NCHNLS_TOKEN: case NCHNLSI_TOKEN: return cs_strdup(csound, "r"); /* rsvd */ case LABEL_TOKEN: //FIXME: Need to review why label token is used so much in parser, //for now treat as T_IDENT case T_ARRAY_IDENT: case T_IDENT: s = tree->value->lexeme; if (is_label(s, typeTable->labelList)) { return cs_strdup(csound, "l"); } if (*s == 't') { /* Support legacy t-vars by mapping to k-array */ return cs_strdup(csound, "[k]"); } if ((*s >= '1' && *s <= '9') || *s == '.' || *s == '-' || *s == '+' || (*s == '0' && strcmp(s, "0dbfs") != 0)) return cs_strdup(csound, "c"); /* const */ if (*s == '"') return cs_strdup(csound, "S"); if (pnum(s) >= 0) return cs_strdup(csound, "p"); /* pnum */ if (*s == '#') s++; /* VL: 16/01/2014 in a second compilation, the typeTable->globalPool is incorrect and will not contain the correct addresses of global variables, which are stored correctly in the engineState.varPool. Ideally we should remove typeTable->globalPool and only use the varPool in the engineState */ if (*s == 'g') { var = csoundFindVariableWithName(csound, csound->engineState.varPool, tree->value->lexeme); if (var == NULL) var = csoundFindVariableWithName(csound, typeTable->globalPool, tree->value->lexeme); //printf("var: %p %s\n", var, var->varName); } else var = csoundFindVariableWithName(csound, typeTable->localPool, tree->value->lexeme); if (UNLIKELY(var == NULL)) { synterr(csound, Str("Variable '%s' used before defined\n" "Line %d\n"), tree->value->lexeme, tree->line); do_baktrace(csound, tree->locn); return NULL; } if (var->varType == &CS_VAR_TYPE_ARRAY) { return create_array_arg_type(csound, var); } else { return cs_strdup(csound, var->varType->varTypeName); } case T_ARRAY: s = tree->value->lexeme; if (*s == '#') s++; if (*s == 'g') s++; if (*s == 't') { /* Support legacy t-vars by mapping to k-array */ return cs_strdup(csound, "[k]"); } t = s; int len = 1; while (*t == '[') { t++; len++; } char* retVal = csound->Malloc(csound, (len + 2) * sizeof(char)); memcpy(retVal, s, len); retVal[len] = ']'; retVal[len + 1] = '\0'; return retVal; default: csoundWarning(csound, Str("Unknown arg type: %d\n"), tree->type); print_tree(csound, "Arg Tree\n", tree); return NULL; } } char* get_opcode_short_name(CSOUND* csound, char* opname) { char* dot = strchr(opname, '.'); if (dot != NULL) { int opLen = dot - opname; return cs_strndup(csound, opname, opLen); } return opname; } /* find opcode with the specified name in opcode list */ /* returns index to opcodlst[], or zero if the opcode cannot be found */ OENTRY* find_opcode(CSOUND *csound, char *opname) { char *shortName; CONS_CELL* head; OENTRY* retVal; if (opname[0] == '\0' || isdigit(opname[0])) return 0; shortName = get_opcode_short_name(csound, opname); head = cs_hash_table_get(csound, csound->opcodes, shortName); retVal = (head != NULL) ? head->value : NULL; if (shortName != opname) csound->Free(csound, shortName); return retVal; } static OENTRIES* get_entries(CSOUND* csound, int count) { OENTRIES* x = csound->Calloc(csound, sizeof(OENTRIES*)+sizeof(OENTRY*)*count); x->count = count; return x; } /* Finds OENTRIES that match the given opcode name. May return multiple * OENTRY*'s for each entry in a polyMorphic opcode. */ OENTRIES* find_opcode2(CSOUND* csound, char* opname) { int i = 0; char *shortName; CONS_CELL *head; OENTRIES* retVal; if (UNLIKELY(opname == NULL)) { return NULL; } shortName = get_opcode_short_name(csound, opname); head = cs_hash_table_get(csound, csound->opcodes, shortName); retVal = get_entries(csound, cs_cons_length(head)); while (head != NULL) { retVal->entries[i++] = head->value; head = head->next; } if (shortName != opname) { csound->Free(csound, shortName); } return retVal; } inline static int is_in_optional_arg(char arg) { return (strchr("opqvjhOJVP?", arg) != NULL); } inline static int is_in_var_arg(char arg) { return (strchr("mMNnWyzZ*", arg) != NULL); } int check_array_arg(char* found, char* required) { char* f = found; char* r = required; while (*r == '[') r++; if (*r == '.' || *r == '?' || *r == '*') { return 1; } while (*f == '[') f++; return (*f == *r); } int check_in_arg(char* found, char* required) { char* t; int i; if (UNLIKELY(found == NULL || required == NULL)) { return 0; } if (strcmp(found, required) == 0) { return 1; } if (*required == '.' || *required == '?' || *required == '*') { return 1; } if (*found == '[' || *required == '[') { if (*found != *required) { return 0; } return check_array_arg(found, required); } t = (char*)POLY_IN_TYPES[0]; for (i = 0; t != NULL; i += 2) { if (strcmp(required, t) == 0) { return (strchr(POLY_IN_TYPES[i + 1], *found) != NULL); } t = (char*)POLY_IN_TYPES[i + 2]; } if (is_in_optional_arg(*required)) { t = (char*)OPTIONAL_IN_TYPES[0]; for (i = 0; t != NULL; i += 2) { if (strcmp(required, t) == 0) { return (strchr(OPTIONAL_IN_TYPES[i + 1], *found) != NULL); } t = (char*)OPTIONAL_IN_TYPES[i + 2]; } } if (!is_in_var_arg(*required)) { return 0; } t = (char*)VAR_ARG_IN_TYPES[0]; for (i = 0; t != NULL; i += 2) { if (strcmp(required, t) == 0) { return (strchr(VAR_ARG_IN_TYPES[i + 1], *found) != NULL); } t = (char*)VAR_ARG_IN_TYPES[i + 2]; } return 0; } int check_in_args(CSOUND* csound, char* inArgsFound, char* opInArgs) { if ((inArgsFound == NULL || strlen(inArgsFound) == 0) && (opInArgs == NULL || strlen(opInArgs) == 0)) { return 1; } if (UNLIKELY(opInArgs == NULL)) { return 0; } { int argsFoundCount = argsRequired(inArgsFound); int argsRequiredCount = argsRequired(opInArgs); char** argsRequired = splitArgs(csound, opInArgs); char** argsFound; int i; int argTypeIndex = 0; char* varArg = NULL; int returnVal = 1; if (argsRequired == NULL) { return 0; } if ((argsFoundCount > argsRequiredCount) && !(is_in_var_arg(*argsRequired[argsRequiredCount - 1]))) { csound->Free(csound, argsRequired); return 0; } argsFound = splitArgs(csound, inArgsFound); if (argsFoundCount == 0) { if (is_in_var_arg(*argsRequired[0])) { varArg = argsRequired[0]; } } else { for (i = 0; i < argsFoundCount; i++) { char* argFound = argsFound[i]; if (varArg != NULL) { if (!check_in_arg(argFound, varArg)) { returnVal = 0; break; } } else { char* argRequired = argsRequired[argTypeIndex++]; if (!check_in_arg(argFound, argRequired)) { returnVal = 0; break; } if (is_in_var_arg(*argRequired)) { varArg = argRequired; } } } } if (returnVal && varArg == NULL) { while (argTypeIndex < argsRequiredCount) { char c = *argsRequired[argTypeIndex++]; if (!is_in_optional_arg(c) && !is_in_var_arg(c)) { returnVal = 0; break; } } } //printf("delete %p \n", argsFound); int n; for (n=0; argsFound[n] != NULL; n++) { // printf("delete %p \n", argsFound[n]); csound->Free(csound, argsFound[n]); } csound->Free(csound, argsFound); //printf("delete %p \n", argsRequired); for (n=0; argsRequired[n] != NULL; n++) { //printf("delete %p \n", argsRequired[n]); csound->Free(csound, argsRequired[n]); } csound->Free(csound, argsRequired); return returnVal; } } inline static int is_out_var_arg(char arg) { return (strchr("mzIXNF*", arg) != NULL); } int check_out_arg(char* found, char* required) { char* t; int i; if (UNLIKELY(found == NULL || required == NULL)) { return 0; } // constants not allowed in out args if (strcmp(found, "c") == 0) { return 0; } if (*required == '.' || *required == '?' || *required == '*') { return 1; } if (*found == '[' || *required == '[') { if (*found != *required) { return 0; } return check_array_arg(found, required); } if (strcmp(found, required) == 0) { return 1; } t = (char*)POLY_OUT_TYPES[0]; for (i = 0; t != NULL; i += 2) { if (strcmp(required, t) == 0) { return (strchr(POLY_OUT_TYPES[i + 1], *found) != NULL); } t = (char*)POLY_OUT_TYPES[i + 2]; } if (!is_out_var_arg(*required)) { return 0; } t = (char*)VAR_ARG_OUT_TYPES[0]; for (i = 0; t != NULL; i += 2) { if (strcmp(required, t) == 0) { return (strchr(VAR_ARG_OUT_TYPES[i + 1], *found) != NULL); } t = (char*)VAR_ARG_OUT_TYPES[i + 2]; } return 0; } int check_out_args(CSOUND* csound, char* outArgsFound, char* opOutArgs) { if ((outArgsFound == NULL || strlen(outArgsFound) == 0) && (opOutArgs == NULL || strlen(opOutArgs) == 0)) { return 1; } { int argsFoundCount = argsRequired(outArgsFound); int argsRequiredCount = argsRequired(opOutArgs); char** argsRequired = splitArgs(csound, opOutArgs); char** argsFound; int i; int argTypeIndex = 0; char* varArg = NULL; int returnVal = 1; if ((argsFoundCount > argsRequiredCount) && !(is_out_var_arg(*argsRequired[argsRequiredCount - 1]))) { csound->Free(csound, argsRequired); return 0; } argsFound = splitArgs(csound, outArgsFound); for (i = 0; i < argsFoundCount; i++) { char* argFound = argsFound[i]; if (varArg != NULL) { if (!check_out_arg(argFound, varArg)) { returnVal = 0; break; } } else { char* argRequired = argsRequired[argTypeIndex++]; if (!check_out_arg(argFound, argRequired)) { returnVal = 0; break; } if (is_out_var_arg(*argRequired)) { varArg = argRequired; } } } if (returnVal && varArg == NULL) { if (argTypeIndex < argsRequiredCount) { char* argRequired = argsRequired[argTypeIndex]; returnVal = is_out_var_arg(*argRequired); } else { returnVal = 1; } } //printf("delete %p \n", argsFound); int n; for (n=0; argsFound[n] != NULL; n++) { // printf("delete %p \n", argsFound[n]); csound->Free(csound, argsFound[n]); } csound->Free(csound, argsFound); //printf("delete %p \n", argsRequired); for (n=0; argsRequired[n] != NULL; n++) { //printf("delete %p \n", argsRequired[n]); csound->Free(csound, argsRequired[n]); } csound->Free(csound, argsRequired); return returnVal; } } /* Given an OENTRIES list, resolve to a single OENTRY* based on the * found in- and out- argtypes. Returns NULL if opcode could not be * resolved. If more than one entry matches, mechanism assumes there * are multiple opcode entries with same types and last one should * override previous definitions. */ OENTRY* resolve_opcode(CSOUND* csound, OENTRIES* entries, char* outArgTypes, char* inArgTypes) { // OENTRY* retVal = NULL; int i; for (i = 0; i < entries->count; i++) { OENTRY* temp = entries->entries[i]; // if (temp->intypes == NULL && temp->outypes == NULL) { // if (outArgTypes == NULL && inArgTypes == NULL) { // // } // continue; // } if (check_in_args(csound, inArgTypes, temp->intypes) && check_out_args(csound, outArgTypes, temp->outypes)) { // if (retVal != NULL) { // return NULL; // } // retVal = temp; return temp; } } return NULL; // return retVal; } OENTRY* resolve_opcode_exact(CSOUND* csound, OENTRIES* entries, char* outArgTypes, char* inArgTypes) { int i; for (i = 0; i < entries->count; i++) { OENTRY* temp = entries->entries[i]; if (temp->intypes != NULL && !strcmp(inArgTypes, temp->intypes) && temp->outypes != NULL && !strcmp(outArgTypes, temp->outypes)) { return temp; } } return NULL; } /* used when creating T_FUNCTION's */ char* resolve_opcode_get_outarg(CSOUND* csound, OENTRIES* entries, char* inArgTypes) { int i; for (i = 0; i < entries->count; i++) { OENTRY* temp = entries->entries[i]; if (temp->intypes == NULL && temp->outypes == NULL) { continue; } if (check_in_args(csound, inArgTypes, temp->intypes)) { // FIXME this is only returning the first match, we need to check // if there are multiple matches and if so, return NULL to signify // ambiguity return temp->outypes; } } return NULL; } //PUBLIC int resolve_opcode_num(CSOUND* csound, OENTRIES* entries, // char* outArgTypes, char* inArgTypes) { // // int i; //// int retVal = -1; // // for (i = 0; i < entries->count; i++) { // OENTRY* temp = entries->entries[i]; // if (temp->intypes == NULL && temp->outypes == NULL) { // continue; // } // if (check_in_args(csound, inArgTypes, temp->intypes) && // check_out_args(csound, outArgTypes, temp->outypes)) { //// if (retVal >= 0) { //// return 0; //// } //// retVal = entries->opnum[i]; // return entries->opnum[i]; // } // // } // //// return (retVal < 0) ? 0 : retVal; // return 0; //} /* Converts internal array specifier from [[a] to a[][]. Used by get_arg_string_from_tree to create an arg string that is compatible with the ones found in OENTRY's. splitArgs converts back to internal representation. */ char* convert_internal_to_external(CSOUND* csound, char* arg) { int i, dimensions; char* retVal; if (arg == NULL || *arg != '[') { return arg; } dimensions = 0; while (*arg == '[') { arg++; dimensions++; } retVal = csound->Malloc(csound, sizeof(char) * ((dimensions * 2) + 2)); retVal[0] = *arg; for (i = 0; i < dimensions * 2; i += 2) { retVal[i + 1] = '['; retVal[i + 2] = ']'; } retVal[dimensions * 2 + 1] = '\0'; //csound->Free(csound, arg); return retVal; } /* ASSUMES VALID ARRAY SPECIFIER! */ char* convert_external_to_internal(CSOUND* csound, char* arg) { int i, dimensions; char* retVal; if (arg == NULL || *(arg + 1) != '[') { return arg; } dimensions = (strlen(arg) - 1) / 2; retVal = csound->Malloc(csound, sizeof(char) * (dimensions + 3)); retVal[dimensions + 2] = '\0'; retVal[dimensions + 1] = ']'; retVal[dimensions] = *arg; for (i = 0; i < dimensions; i++) { retVal[i] = '['; } //csound->Free(csound, arg); return retVal; } char* get_arg_string_from_tree(CSOUND* csound, TREE* tree, TYPE_TABLE* typeTable) { int len = tree_arg_list_count(tree); int i; if (len == 0) { return NULL; } char** argTypes = csound->Malloc(csound, len * sizeof(char*)); char* argString = NULL; TREE* current = tree; int index = 0; int argsLen = 0; while (current != NULL) { char* argType = get_arg_type2(csound, current, typeTable); //FIXME - fix if argType is NULL and remove the below hack if (argType == NULL) { argsLen += 1; argTypes[index++] = cs_strdup(csound, "@"); } else { argType = convert_internal_to_external(csound, argType); argsLen += strlen(argType); argTypes[index++] = argType; } current = current->next; } argString = csound->Malloc(csound, (argsLen + 1) * sizeof(char)); char* temp = argString; for (i = 0; i < len; i++) { int size = strlen(argTypes[i]); memcpy(temp, argTypes[i], size); temp += size; csound->Free(csound, argTypes[i]); } argString[argsLen] = '\0'; csound->Free(csound, argTypes); return argString; } OENTRY* find_opcode_new(CSOUND* csound, char* opname, char* outArgsFound, char* inArgsFound) { // csound->Message(csound, "Searching for opcode: %s | %s | %s\n", // outArgsFound, opname, inArgsFound); OENTRIES* opcodes = find_opcode2(csound, opname); if (opcodes->count == 0) { return NULL; } OENTRY* retVal = resolve_opcode(csound, opcodes, outArgsFound, inArgsFound); csound->Free(csound, opcodes); return retVal; } OENTRY* find_opcode_exact(CSOUND* csound, char* opname, char* outArgsFound, char* inArgsFound) { OENTRIES* opcodes = find_opcode2(csound, opname); if (opcodes->count == 0) { return NULL; } OENTRY* retVal = resolve_opcode_exact(csound, opcodes, outArgsFound, inArgsFound); csound->Free(csound, opcodes); return retVal; } //FIXME - this needs to be updated to take into account array names // that could clash with non-array names, i.e. kVar and kVar[] int check_args_exist(CSOUND* csound, TREE* tree, TYPE_TABLE* typeTable) { CS_VARIABLE *var = 0; TREE* current; char* argType; char* varName; CS_VAR_POOL* pool; if (tree == NULL) { return 1; } current = tree; while (current != NULL) { if (is_expression_node(tree) || is_boolean_expression_node(tree)) { if (!(check_args_exist(csound, tree->left, typeTable) && check_args_exist(csound, tree->right, typeTable))) { return 0; } } else { switch (current->type) { case LABEL_TOKEN: case T_IDENT: varName = current->value->lexeme; if (is_label(varName, typeTable->labelList)) { break; } argType = get_arg_type2(csound, current, typeTable); if (UNLIKELY(argType==NULL)) { synterr(csound, Str("Variable type for %s could not be determined.\n"), varName); do_baktrace(csound, tree->locn); return 0; } //FIXME - this feels like a hack if (*argType == 'c' || *argType == 'r' || *argType == 'p') { csound->Free(csound, argType); break; } csound->Free(csound, argType); pool = (*varName == 'g') ? typeTable->globalPool : typeTable->localPool; var = csoundFindVariableWithName(csound, pool, varName); if (UNLIKELY(var == NULL)) { /* VL: 13-06-13 if it is not found, we still check the global (merged) pool */ if (*varName == 'g') var = csoundFindVariableWithName(csound, csound->engineState.varPool, varName); if (UNLIKELY(var == NULL)) { synterr(csound, Str("Variable '%s' used before defined\nline %d"), varName, tree->line); do_baktrace(csound, tree->locn); return 0; } } break; case T_ARRAY: varName = current->left->value->lexeme; pool = (*varName == 'g') ? typeTable->globalPool : typeTable->localPool; if (UNLIKELY(csoundFindVariableWithName(csound, pool, varName) == NULL)) { CS_VARIABLE *var = 0; /* VL: 13-06-13 if it is not found, we still check the global (merged) pool */ if (var == NULL && *varName == 'g') var = csoundFindVariableWithName(csound, csound->engineState.varPool, varName); if (UNLIKELY(var == NULL)) { synterr(csound, Str("Variable '%s' used before defined\nLine %d\n"), varName, current->left->line); do_baktrace(csound, current->left->locn); return 0; } } break; default: //synterr(csound, "Unknown arg type: %s\n", current->value->lexeme); //printf("\t->FOUND OTHER: %s %d\n", current->value->lexeme, // current->type); break; } } current = current->next; } return 1; } void add_arg(CSOUND* csound, char* varName, TYPE_TABLE* typeTable) { CS_TYPE* type; CS_VARIABLE* var; char *t; CS_VAR_POOL* pool; char argLetter[2]; ARRAY_VAR_INIT varInit; void* typeArg = NULL; t = varName; if (*t == '#') t++; pool = (*t == 'g') ? typeTable->globalPool : typeTable->localPool; var = csoundFindVariableWithName(csound, pool, varName); if (var == NULL) { t = varName; argLetter[1] = 0; if (*t == '#') t++; if (*t == 'g') t++; if (*t == '[' || *t == 't') { /* Support legacy t-vars */ int dimensions = 1; CS_TYPE* varType; char* b = t + 1; while (*b == '[') { b++; dimensions++; } argLetter[0] = (*b == 't') ? 'k' : *b; /* Support legacy t-vars */ varType = csoundGetTypeWithVarTypeName(csound->typePool, argLetter); varInit.dimensions = dimensions; varInit.type = varType; typeArg = &varInit; } argLetter[0] = (*t == 't') ? '[' : *t; /* Support legacy t-vars */ type = csoundGetTypeForVarName(csound->typePool, argLetter); var = csoundCreateVariable(csound, csound->typePool, type, varName, typeArg); csoundAddVariable(csound, pool, var); } else { //TODO - implement reference count increment } } void add_array_arg(CSOUND* csound, char* varName, int dimensions, TYPE_TABLE* typeTable) { CS_VARIABLE* var; char *t; CS_VAR_POOL* pool; char argLetter[2]; ARRAY_VAR_INIT varInit; void* typeArg = NULL; pool = (*varName == 'g') ? typeTable->globalPool : typeTable->localPool; var = csoundFindVariableWithName(csound, pool, varName); if (var == NULL) { CS_TYPE* varType; t = varName; argLetter[1] = 0; if (*t == '#') t++; if (*t == 'g') t++; argLetter[0] = (*t == 't') ? 'k' : *t; /* Support legacy t-vars */ varType = csoundGetTypeWithVarTypeName(csound->typePool, argLetter); varInit.dimensions = dimensions; varInit.type = varType; typeArg = &varInit; var = csoundCreateVariable(csound, csound->typePool, (CS_TYPE*) &CS_VAR_TYPE_ARRAY, varName, typeArg); csoundAddVariable(csound, pool, var); } else { //TODO - implement reference count increment } } /* return 1 on succcess, 0 on failure */ int add_args(CSOUND* csound, TREE* tree, TYPE_TABLE* typeTable) { TREE* current; char* varName; if (tree == NULL) { return 1; } current = tree; while (current != NULL) { switch (current->type) { case T_ARRAY_IDENT: varName = current->value->lexeme; add_array_arg(csound, varName, tree_arg_list_count(current->right), typeTable); break; case LABEL_TOKEN: case T_IDENT: varName = current->value->lexeme; if (UNLIKELY(*varName == 't')) { /* Support legacy t-vars */ add_array_arg(csound, varName, 1, typeTable); } else { add_arg(csound, varName, typeTable); } break; case T_ARRAY: varName = current->left->value->lexeme; // FIXME - this needs to work for array and a-names add_arg(csound, varName, typeTable); break; default: //synterr(csound, "Unknown arg type: %s\n", current->value->lexeme); //printf("\t->FOUND OTHER: %s %d\n", // current->value->lexeme, current->type); break; } current = current->next; } return 1; } /* * Verifies: * -number of args correct * -types of arg correct * -expressions are valid and types correct */ int verify_opcode(CSOUND* csound, TREE* root, TYPE_TABLE* typeTable) { TREE* left = root->left; TREE* right = root->right; char* leftArgString; char* rightArgString; char* opcodeName; if (root->value == NULL) return 0; if (!check_args_exist(csound, root->right, typeTable)) { return 0; } add_args(csound, root->left, typeTable); opcodeName = root->value->lexeme; //printf("%p %p (%s) \n", root, root->value, opcodeName); leftArgString = get_arg_string_from_tree(csound, left, typeTable); rightArgString = get_arg_string_from_tree(csound, right, typeTable); if (!strcmp(opcodeName, "xin")) { int nreqd = tree_arg_list_count(root->right); if (nreqd > OPCODENUMOUTS_LOW) { opcodeName = (nreqd > OPCODENUMOUTS_HIGH) ? "##xin256" : "##xin64"; } } OENTRIES* entries = find_opcode2(csound, opcodeName); if (UNLIKELY(entries == NULL || entries->count == 0)) { synterr(csound, Str("Unable to find opcode with name: %s\n"), root->value->lexeme); if (entries != NULL) { csound->Free(csound, entries); } return 0; } OENTRY* oentry; if (root->value->optype == NULL) oentry = resolve_opcode(csound, entries, leftArgString, rightArgString); /* if there is type annotation, try to resolve it */ else oentry = resolve_opcode(csound, entries, root->value->optype, rightArgString); if (UNLIKELY(oentry == NULL)) { synterr(csound, Str("Unable to find opcode entry for \'%s\' " "with matching argument types:\n"), opcodeName); csoundMessage(csound, Str("Found: %s %s %s\n"), leftArgString, root->value->lexeme, rightArgString); csoundMessage(csound, Str("Line: %d\n"), root->line); do_baktrace(csound, root->locn); csound->Free(csound, leftArgString); csound->Free(csound, rightArgString); csound->Free(csound, entries); return 0; } else { if (csound->oparms->sampleAccurate && (strcmp(oentry->opname, "=.a")==0) && left->value->lexeme[0]=='a') { /* Deal with sample accurate assigns */ int i = 0; while (strcmp(entries->entries[i]->opname, "=.l")) { printf("not %d %s\n",i, entries->entries[i]->opname); i++; } oentry = entries->entries[i]; } root->markup = oentry; } csound->Free(csound, leftArgString); csound->Free(csound, rightArgString); csound->Free(csound, entries); return 1; } /* Walks tree and finds all label: definitions */ CONS_CELL* get_label_list(CSOUND* csound, TREE* root) { CONS_CELL* head = NULL, *ret = NULL; TREE* current = root; char* labelText; while (current != NULL) { switch(current->type) { case LABEL_TOKEN: labelText = current->value->lexeme; head = cs_cons(csound, cs_strdup(csound, labelText), head); break; case IF_TOKEN: case ELSEIF_TOKEN: if (current->right->type == THEN_TOKEN || current->right->type == KTHEN_TOKEN || current->right->type == ITHEN_TOKEN) { ret = get_label_list(csound, current->right->right); head = cs_cons_append(head, ret); ret = get_label_list(csound, current->right->next); head = cs_cons_append(head, ret); } break; case ELSE_TOKEN: case UNTIL_TOKEN: case WHILE_TOKEN: ret = get_label_list(csound, current->right); head = cs_cons_append(head, ret); break; default: break; } current = current->next; } return head; } static int is_label(char* ident, CONS_CELL* labelList) { CONS_CELL* current; if (labelList == NULL) return 0; current = labelList; while (current != NULL) { if (strcmp((char*)current->value, ident) == 0) { return 1; } current = current->next; } return 0; } int verify_if_statement(CSOUND* csound, TREE* root, TYPE_TABLE* typeTable) { char* outArg; TREE* right = root->right; if (right->type == IGOTO_TOKEN || right->type == KGOTO_TOKEN || right->type == GOTO_TOKEN) { if (!check_args_exist(csound, root->left, typeTable)) { return 0; } outArg = get_arg_type2(csound, root->left, typeTable); return (outArg != NULL && (*outArg == 'b' || *outArg == 'B')); } else if (right->type == THEN_TOKEN || right->type == ITHEN_TOKEN || right->type == KTHEN_TOKEN) { //TREE *tempLeft; //TREE *tempRight; TREE* current = root; while (current != NULL) { //tempLeft = current->left; //tempRight = current->right; if (current->type == ELSE_TOKEN) { break; } if (!check_args_exist(csound, current->left, typeTable)) { return 0; } outArg = get_arg_type2(csound, current->left, typeTable); if (outArg == NULL || (*outArg != 'b' && *outArg != 'B')) { csound->Free(csound, outArg); return 0; } csound->Free(csound, outArg); current = (current->right == NULL) ? NULL : current->right->next; } } return 1; } int verify_until_statement(CSOUND* csound, TREE* root, TYPE_TABLE* typeTable) { char* outArg; if (!check_args_exist(csound, root->left, typeTable)) { return 0; }; outArg = get_arg_type2(csound, root->left, typeTable); if (UNLIKELY(outArg == NULL || (*outArg != 'b' && *outArg != 'B'))) { synterr(csound, Str("expression for until/while statement not a boolean " "expression, line %d\n"), root->line); do_baktrace(csound, root->locn); return 0; } return 1; } /** Verifies if xin and xout statements are correct for UDO needs to check: xin/xout number of args matches UDO input/output arg specifications xin/xout statements exist if UDO in and out args are not 0 */ int verify_xin_xout(CSOUND *csound, TREE *udoTree, TYPE_TABLE *typeTable) { if (udoTree->right == NULL) { return 1; } TREE* outArgsTree = udoTree->left->left; TREE* inArgsTree = udoTree->left->right; TREE* current = udoTree->right; TREE* xinArgs = NULL; TREE* xoutArgs = NULL; char* inArgs = inArgsTree->value->lexeme; char* outArgs = outArgsTree->value->lexeme; unsigned int i; for (i = 0; i < strlen(inArgs);i++) { if (inArgs[i] == 'K') { inArgs[i] = 'k'; } } for (i = 0; i < strlen(outArgs);i++) { if (outArgs[i] == 'K') { outArgs[i] = 'k'; } } while (current != NULL) { if (current->value != NULL) { if (strcmp("xin", current->value->lexeme) == 0) { if (UNLIKELY(xinArgs != NULL)) { synterr(csound, Str("Multiple xin statements found. " "Only one is allowed.")); return 0; } xinArgs = current->left; } if (strcmp("xout", current->value->lexeme) == 0) { if (UNLIKELY(xoutArgs != NULL)) { synterr(csound, Str("Multiple xout statements found. " "Only one is allowed.")); return 0; } xoutArgs = current->right; } } current = current->next; } char* inArgsFound = get_arg_string_from_tree(csound, xinArgs, typeTable); char* outArgsFound = get_arg_string_from_tree(csound, xoutArgs, typeTable); if (!check_in_args(csound, inArgsFound, inArgs)) { if (UNLIKELY(!(strcmp("0", inArgs) == 0 && xinArgs == NULL))) { synterr(csound, Str("invalid xin statement for UDO: defined '%s', found '%s'\n"), inArgs, inArgsFound); return 0; } } if (!check_in_args(csound, outArgsFound, outArgs)) { if (UNLIKELY(!(strcmp("0", outArgs) == 0 && xoutArgs == NULL))) { synterr(csound, Str("invalid xout statement for UDO: defined '%s', found '%s'\n"), outArgs, outArgsFound); return 0; } } return 1; } TREE* verify_tree(CSOUND * csound, TREE *root, TYPE_TABLE* typeTable) { TREE *anchor = NULL; TREE *current = root; TREE *previous = NULL; TREE* newRight; CONS_CELL* parentLabelList = typeTable->labelList; typeTable->labelList = get_label_list(csound, root); //if (root->value) //printf("###verify %p %p (%s) \n", root, root->value, root->value->lexeme); if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "Verifying AST\n"); while (current != NULL) { switch(current->type) { case INSTR_TOKEN: csound->inZero = 0; if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "Instrument found\n"); typeTable->localPool = csoundCreateVarPool(csound); current->markup = typeTable->localPool; if (current->right) { newRight = verify_tree(csound, current->right, typeTable); if (newRight == NULL) { cs_cons_free(csound, typeTable->labelList); typeTable->labelList = parentLabelList; return NULL; } current->right = newRight; newRight = NULL; } typeTable->localPool = typeTable->instr0LocalPool; break; case UDO_TOKEN: csound->inZero = 0; if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "UDO found\n"); typeTable->localPool = csoundCreateVarPool(csound); current->markup = typeTable->localPool; if (current->right != NULL) { newRight = verify_tree(csound, current->right, typeTable); if (newRight == NULL) { cs_cons_free(csound, typeTable->labelList); typeTable->labelList = parentLabelList; return NULL; } current->right = newRight; if (!verify_xin_xout(csound, current, typeTable)) { return 0; } newRight = NULL; } typeTable->localPool = typeTable->instr0LocalPool; break; case IF_TOKEN: if (!verify_if_statement(csound, current, typeTable)) { return 0; } current = expand_if_statement(csound, current, typeTable); if (previous != NULL) { previous->next = current; } continue; case UNTIL_TOKEN: case WHILE_TOKEN: if (!verify_until_statement(csound, current, typeTable)) { return 0; } current = expand_until_statement(csound, current, typeTable, current->type==WHILE_TOKEN); if (previous != NULL) { previous->next = current; } continue; case LABEL_TOKEN: break; case '+': case '-': case '*': case '/': //printf("Folding case?\n"); current->left = verify_tree(csound, current->left, typeTable); current->right = verify_tree(csound, current->right, typeTable); if ((current->left->type == INTEGER_TOKEN || current->left->type == NUMBER_TOKEN) && (current->right->type == INTEGER_TOKEN || current->right->type == NUMBER_TOKEN)) { MYFLT lval, rval; lval = (current->left->type == INTEGER_TOKEN ? (double)current->left->value->value : current->left->value->fvalue); rval = (current->right->type == INTEGER_TOKEN ? (double)current->right->value->value : current->right->value->fvalue); switch (current->type) { case '+': lval = lval + rval; break; case '-': lval = lval - rval; break; case '*': lval = lval * rval; break; case '/': lval = lval / rval; break; } current->type = NUMBER_TOKEN; current->value->fvalue = lval; csound->Free(csound, current->left); csound->Free(csound, current->right); } break; case ENDIN_TOKEN: case UDOEND_TOKEN: csound->inZero = 1; /* fall through */ default: if (!verify_opcode(csound, current, typeTable)) { return 0; } //print_tree(csound, "verify_tree", current); if (is_statement_expansion_required(current)) { current = expand_statement(csound, current, typeTable); if (previous != NULL) { previous->next = current; } continue; } else { handle_optional_args(csound, current); } } if (anchor == NULL) { anchor = current; } previous = current; current = current->next; } if (PARSER_DEBUG) csound->Message(csound, "[End Verifying AST]\n"); cs_cons_free(csound, typeTable->labelList); typeTable->labelList = parentLabelList; return anchor; } /* BISON PARSER FUNCTION */ int csound_orcwrap(void* dummy) { #ifdef DEBUG printf("\n === END OF INPUT ===\n"); #endif return (1); } /* UTILITY FUNCTIONS */ extern int csound_orcget_lineno(void*); extern char *csound_orcget_current_pointer(void *); /* BISON PARSER FUNCTION */ void csound_orcerror(PARSE_PARM *pp, void *yyscanner, CSOUND *csound, TREE **astTree, const char *str) { char ch; char *p = csound_orcget_current_pointer(yyscanner)-1; int line = csound_orcget_lineno(yyscanner); uint64_t files = csound_orcget_locn(yyscanner); if (UNLIKELY(*p=='\0' || *p=='\n')) line--; //printf("LINE: %d\n", line); csound->Message(csound, Str("\nerror: %s (token \"%s\")"), str, csound_orcget_text(yyscanner)); do_baktrace(csound, files); csound->Message(csound, Str(" line %d:\n>>>"), line); while ((ch=*--p) != '\n' && ch != '\0'); do { ch = *++p; if (UNLIKELY(ch == '\n')) break; // Now get rid of any continuations if (ch=='#' && strncmp(p,"sline ",6)) { p+=7; while (isdigit(*p)) p++; } else csound->Message(csound, "%c", ch); } while (ch != '\n' && ch != '\0'); csound->Message(csound, " <<<\n"); } void do_baktrace(CSOUND *csound, uint64_t files) { while (files) { unsigned int ff = files&0xff; files = files >>8; csound->Message(csound, Str(" from file %s (%d)\n"), csound->filedir[ff], ff); } } /** * Appends TREE * node to TREE * node using ->next field in struct; walks * down list to append at end; checks for NULL's and returns * appropriate nodes */ TREE* appendToTree(CSOUND * csound, TREE *first, TREE *newlast) { TREE *current; if (first == NULL) { return newlast; } if (newlast == NULL) { return first; } /* HACK - Checks to see if first node is uninitialized (sort of) * This occurs for rules like in topstatement where the left hand * topstatement the first time around is not initialized to anything * useful; the number 400 is arbitrary, chosen as it seemed to be a * value higher than all the type numbers that were being printed out */ if (first->type > 400 || first-> type < 0) { return newlast; } current = first; while (current->next != NULL) { current = current->next; } current->next = newlast; return first; } /* USED BY PARSER TO ASSEMBLE TREE NODES */ TREE* make_node(CSOUND *csound, int line, int locn, int type, TREE* left, TREE* right) { TREE *ans; ans = (TREE*)csound->Malloc(csound, sizeof(TREE)); if (UNLIKELY(ans==NULL)) { /* fprintf(stderr, "Out of memory\n"); */ exit(1); } ans->type = type; ans->left = left; ans->right = right; ans->value = NULL; /* New code -- JPff */ ans->next = NULL; ans->len = 2; ans->rate = -1; ans->line = line; ans->locn = locn; ans->markup = NULL; //printf("make node %p %p %p\n", ans, ans->left, ans->right); //csound->DebugMsg(csound, "%s(%d) line = %d\n", __FILE__, __LINE__, line); return ans; } TREE* make_leaf(CSOUND *csound, int line, int locn, int type, ORCTOKEN *v) { TREE *ans; ans = (TREE*)csound->Calloc(csound, sizeof(TREE)); if (UNLIKELY(ans==NULL)) { /* fprintf(stderr, "Out of memory\n"); */ exit(1); } ans->type = type; ans->left = NULL; ans->right = NULL; ans->next = NULL; ans->len = 0; ans->rate = -1; ans->value = v; ans->line = line; ans->locn = locn; ans->markup = NULL; //if (ans->value) // printf("make leaf %p %p (%s) \n", ans, ans->value, ans->value->lexeme); csound->DebugMsg(csound, "csound_orc_semantics(%d) line = %d\n", __LINE__, line); return ans; } static void delete_tree(CSOUND *csound, TREE *l) { while (1) { TREE *old = l; if (UNLIKELY(l==NULL)) { return; } //else printf("l = %p\n", l); if (l->value) { if (l->value->lexeme) { //printf("Free %p %p (%s)\n", l, l->value, l->value->lexeme); csound->Free(csound, l->value->lexeme); //l->value->lexeme = NULL; } //printf("Free val %p\n", l->value); csound->Free(csound, l->value); //l->value = NULL; } // printf("left %p right %p \n", l->left, l->right); delete_tree(csound, l->left); //l->left = NULL; delete_tree(csound, l->right); //l->right = NULL; l = l->next; //printf("Free old %p next: %p\n", old, l); csound->Free(csound, old); } } PUBLIC void csoundDeleteTree(CSOUND *csound, TREE *tree) { //printf("Tree %p\n", tree); delete_tree(csound, tree); } /* DEBUGGING FUNCTIONS */ void print_tree_i(CSOUND *csound, TREE *l, int n) { int i; if (UNLIKELY(l==NULL)) { return; } for (i=0; iMessage(csound, " "); } csound->Message(csound, "TYPE: %d ", l->type); switch (l->type) { case ',': case '?': case ':': case '!': case '+': case '-': case '*': case '/': case '%': case '^': case '(': case ')': case '=': csound->Message(csound,"%c:(%d:%s)\n", l->type, l->line, csound->filedir[(l->locn)&0xff]); break; case NEWLINE: csound->Message(csound,"NEWLINE:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case S_NEQ: csound->Message(csound,"S_NEQ:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case S_AND: csound->Message(csound,"S_AND:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case S_OR: csound->Message(csound,"S_OR:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case S_LT: csound->Message(csound,"S_LT:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case S_LE: csound->Message(csound,"S_LE:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case S_EQ: csound->Message(csound,"S_EQ:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case S_UNOT: csound->Message(csound,"S_UNOT:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case S_GT: csound->Message(csound,"S_GT:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case S_GE: csound->Message(csound,"S_GE:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case LABEL_TOKEN: csound->Message(csound,"LABEL_TOKEN: %s\n", l->value->lexeme); break; case IF_TOKEN: csound->Message(csound,"IF_TOKEN:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case THEN_TOKEN: csound->Message(csound,"THEN_TOKEN:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case ITHEN_TOKEN: csound->Message(csound,"ITHEN_TOKEN:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case KTHEN_TOKEN: csound->Message(csound,"KTHEN_TOKEN:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case ELSEIF_TOKEN: csound->Message(csound,"ELSEIF_TOKEN:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case ELSE_TOKEN: csound->Message(csound,"ELSE_TOKEN:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case UNTIL_TOKEN: csound->Message(csound,"UNTIL_TOKEN:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case WHILE_TOKEN: csound->Message(csound,"WHILE_TOKEN:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case DO_TOKEN: csound->Message(csound,"DO_TOKEN:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case OD_TOKEN: csound->Message(csound,"OD_TOKEN:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case GOTO_TOKEN: csound->Message(csound,"GOTO_TOKEN:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case IGOTO_TOKEN: csound->Message(csound,"IGOTO_TOKEN:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case KGOTO_TOKEN: csound->Message(csound,"KGOTO_TOKEN:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case SRATE_TOKEN: csound->Message(csound,"SRATE_TOKEN:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case KRATE_TOKEN: csound->Message(csound,"KRATE_TOKEN:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case ZERODBFS_TOKEN: csound->Message(csound,"ZERODFFS_TOKEN:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case A4_TOKEN: csound->Message(csound,"A4_TOKEN:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case KSMPS_TOKEN: csound->Message(csound,"KSMPS_TOKEN:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case NCHNLS_TOKEN: csound->Message(csound,"NCHNLS_TOKEN:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case NCHNLSI_TOKEN: csound->Message(csound,"NCHNLSI_TOKEN:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case INSTR_TOKEN: csound->Message(csound,"INSTR_TOKEN:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case STRING_TOKEN: csound->Message(csound,"STRING_TOKEN: %s\n", l->value->lexeme); break; case T_IDENT: csound->Message(csound,"T_IDENT: %s\n", l->value->lexeme); break; case INTEGER_TOKEN: csound->Message(csound,"INTEGER_TOKEN: %d\n", l->value->value); break; case NUMBER_TOKEN: csound->Message(csound,"NUMBER_TOKEN: %f\n", l->value->fvalue); break; case S_ANDTHEN: csound->Message(csound,"S_ANDTHEN:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case S_APPLY: csound->Message(csound,"S_APPLY:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case T_OPCODE0: csound->Message(csound,"T_OPCODE0: %s\n", l->value->lexeme); break; case T_OPCODE: csound->Message(csound,"T_OPCODE: %s\n", l->value->lexeme); break; case T_FUNCTION: csound->Message(csound,"T_FUNCTION: %s\n", l->value->lexeme); break; case S_UMINUS: csound->Message(csound,"S_UMINUS:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case T_INSTLIST: csound->Message(csound,"T_INSTLIST:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; case '[': csound->Message(csound,"[:(%d:%s)\n", l->line, csound->filedir[(l->locn)&0xff]); break; default: csound->Message(csound,"unknown:%d(%d:%s)\n", l->type, l->line, csound->filedir[(l->locn)&0xff]); } print_tree_i(csound, l->left,n+1); print_tree_i(csound, l->right,n+1); if (l->next != NULL) { print_tree_i(csound, l->next, n); } } enum {TREE_NONE, TREE_LEFT, TREE_RIGHT, TREE_NEXT}; static void print_tree_xml(CSOUND *csound, TREE *l, int n, int which) { int i; char *child[4] = {"", "left", "right", "next"}; if (l==NULL) { return; } for (i=0; iMessage(csound, " "); } csound->Message(csound, "value, l->type); switch (l->type) { case ',': case '?': case ':': case '!': case '+': case '-': case '*': case '/': case '%': case '^': case '(': case ')': case '=': case '|': case '&': case '#': case '~': csound->Message(csound,"name=\"%c\"", l->type); break; case NEWLINE: csound->Message(csound,"name=\"NEWLINE\""); break; case S_NEQ: csound->Message(csound,"name=\"S_NEQ\""); break; case S_AND: csound->Message(csound,"name=\"S_AND\""); break; case S_OR: csound->Message(csound,"name=\"S_OR\""); break; case S_LT: csound->Message(csound,"name=\"S_LT\""); break; case S_LE: csound->Message(csound,"name=\"S_LE\""); break; case S_EQ: csound->Message(csound,"name=\"S_EQ\""); break; case S_UNOT: csound->Message(csound,"name=\"S_UNOT\""); break; case S_GT: csound->Message(csound,"name=\"S_GT\""); break; case S_GE: csound->Message(csound,"name=\"S_GE\""); break; case S_BITSHIFT_RIGHT: csound->Message(csound,"name=\"S_BITSHIFT_RIGHT\""); break; case S_BITSHIFT_LEFT: csound->Message(csound,"name=\"S_BITSHIFT_LEFT\""); break; case LABEL_TOKEN: csound->Message(csound,"name=\"LABEL_TOKEN\" label=\"%s\"", l->value->lexeme); break; case IF_TOKEN: csound->Message(csound,"name=\"IF_TOKEN\""); break; case THEN_TOKEN: csound->Message(csound,"name=\"THEN_TOKEN\""); break; case ITHEN_TOKEN: csound->Message(csound,"name=\"ITHEN_TOKEN\""); break; case KTHEN_TOKEN: csound->Message(csound,"name=\"KTHEN_TOKEN\""); break; case ELSEIF_TOKEN: csound->Message(csound,"name=\"ELSEIF_TOKEN\""); break; case ELSE_TOKEN: csound->Message(csound,"name=\"ELSE_TOKEN\""); break; case UNTIL_TOKEN: csound->Message(csound,"name=\"UNTIL_TOKEN\""); break; case WHILE_TOKEN: csound->Message(csound,"name=\"WHILE_TOKEN\""); break; case DO_TOKEN: csound->Message(csound,"name=\"DO_TOKEN\""); break; case OD_TOKEN: csound->Message(csound,"name=\"OD_TOKEN\""); break; case GOTO_TOKEN: csound->Message(csound,"name=\"GOTO_TOKEN\""); break; case IGOTO_TOKEN: csound->Message(csound,"name=\"IGOTO_TOKEN\""); break; case KGOTO_TOKEN: csound->Message(csound,"name=\"KGOTO_TOKEN\""); break; case SRATE_TOKEN: csound->Message(csound,"name=\"SRATE_TOKEN\""); break; case KRATE_TOKEN: csound->Message(csound,"name=\"KRATE_TOKEN\""); break; case ZERODBFS_TOKEN: csound->Message(csound,"name=\"ZERODBFS_TOKEN\""); break; case A4_TOKEN: csound->Message(csound,"name=\"A4_TOKEN\""); break; case KSMPS_TOKEN: csound->Message(csound,"name=\"KSMPS_TOKEN\""); break; case NCHNLS_TOKEN: csound->Message(csound,"name=\"NCHNLS_TOKEN\""); break; case NCHNLSI_TOKEN: csound->Message(csound,"name=\"NCHNLSI_TOKEN\""); break; case INSTR_TOKEN: csound->Message(csound,"name=\"INSTR_TOKEN\""); break; case STRING_TOKEN: csound->Message(csound,"name=\"T_STRCONST\" str=\"%s\"", l->value->lexeme); break; case T_IDENT: csound->Message(csound,"name=\"T_IDENT\" varname=\"%s\"", l->value->lexeme); break; case T_ARRAY: csound->Message(csound,"name=\"T_ARRAY\""); break; case T_ARRAY_IDENT: csound->Message(csound,"name=\"T_ARRAY_IDENT\" varname=\"%s\"", l->value->lexeme); break; case INTEGER_TOKEN: csound->Message(csound,"name=\"INTEGER_TOKEN\" value=\"%d\"", l->value->value); break; case NUMBER_TOKEN: csound->Message(csound,"name=\"NUMBER_TOKEN\" value=\"%f\"", l->value->fvalue); break; case S_ANDTHEN: csound->Message(csound,"name=\"S_ANDTHEN\""); break; case S_APPLY: csound->Message(csound,"name=\"S_APPLY\""); break; case T_OPCODE0: csound->Message(csound,"name=\"T_OPCODE0\" opname0=\"%s\"", l->value->lexeme); break; case T_OPCODE: csound->Message(csound,"name=\"T_OPCODE\" opname=\"%s\"", l->value->lexeme); break; case T_FUNCTION: csound->Message(csound,"name=\"T_FUNCTION\" fname=\"%s\"", l->value->lexeme); break; case S_UMINUS: csound->Message(csound,"name=\"S_UMINUS\""); break; case T_INSTLIST: csound->Message(csound,"name=\"T_INSTLIST\""); break; case UDO_TOKEN: csound->Message(csound,"name=\"UDO_TOKEN\""); break; case UDO_ANS_TOKEN: csound->Message(csound,"name=\"UDO_ANS_TOKEN\" signature=\"%s\"", l->value->lexeme); break; case UDO_ARGS_TOKEN: csound->Message(csound,"name=\"UDO_ARGS_TOKEN\" signature=\"%s\"", l->value->lexeme); break; case S_ELIPSIS: csound->Message(csound,"name=\"S_ELIPSIS\""); break; // case T_MAPI: // csound->Message(csound,"name=\"T_MAPI\""); break; // case T_MAPK: // csound->Message(csound,"name=\"T_MAPK\""); break; // case T_TADD: // csound->Message(csound,"name=\"T_TADD\""); break; // case T_SUB: // csound->Message(csound,"name=\"T_SUB\""); break; // case S_TUMINUS: // csound->Message(csound,"name=\"S_TUMINUS\""); break; // case T_TMUL: // csound->Message(csound,"name=\"T_TMUL\""); break; // case T_TDIV: // csound->Message(csound,"name=\"T_TDIV\""); break; // case T_TREM: // csound->Message(csound,"name=\"T_TREM\""); break; default: csound->Message(csound,"name=\"unknown\"(%d)", l->type); } csound->Message(csound, " loc=\"%d:%s\">\n", l->line, csound->filedir[(l->locn)&0xff]); print_tree_xml(csound, l->left,n+1, TREE_LEFT); print_tree_xml(csound, l->right,n+1, TREE_RIGHT); for (i=0; iMessage(csound, " "); } csound->Message(csound, "\n", child[which]); if (l->next != NULL) { print_tree_xml(csound, l->next, n, TREE_NEXT); } } void print_tree(CSOUND * csound, char* msg, TREE *l) { if (msg) csound->Message(csound, "%s", msg); else csound->Message(csound, "Printing Tree\n"); csound->Message(csound, "\n"); print_tree_xml(csound, l, 0, TREE_NONE); csound->Message(csound, "\n"); } void handle_optional_args(CSOUND *csound, TREE *l) { if (l == NULL || l->type == LABEL_TOKEN) return; { OENTRY *ep = (OENTRY*)l->markup; int nreqd = 0; int incnt = tree_arg_list_count(l->right); TREE * temp; char** inArgParts = NULL; if (UNLIKELY(ep==NULL)) { /* **** FIXME **** */ printf("THIS SHOULD NOT HAPPEN -- ep NULL csound_orc-semantics(%d)\n", __LINE__); } if (ep->intypes != NULL) { nreqd = argsRequired(ep->intypes); inArgParts = splitArgs(csound, ep->intypes); } if (UNLIKELY(PARSER_DEBUG)) { csound->Message(csound, "Handling Optional Args for opcode %s, %d, %d", ep->opname, incnt, nreqd); csound->Message(csound, "ep->intypes = >%s<\n", ep->intypes); } if (incnt < nreqd) { /* or set defaults: */ do { switch (*inArgParts[incnt]) { case 'O': /* Will this work? Doubtful code.... */ case 'o': temp = make_leaf(csound, l->line, l->locn, INTEGER_TOKEN, make_int(csound, "0")); temp->markup = &SYNTHESIZED_ARG; if (l->right==NULL) l->right = temp; else appendToTree(csound, l->right, temp); break; case 'P': case 'p': temp = make_leaf(csound, l->line, l->locn, INTEGER_TOKEN, make_int(csound, "1")); temp->markup = &SYNTHESIZED_ARG; if (l->right==NULL) l->right = temp; else appendToTree(csound, l->right, temp); break; case 'q': temp = make_leaf(csound, l->line, l->locn, INTEGER_TOKEN, make_int(csound, "10")); temp->markup = &SYNTHESIZED_ARG; if (l->right==NULL) l->right = temp; else appendToTree(csound, l->right, temp); break; case 'V': case 'v': temp = make_leaf(csound, l->line, l->locn, NUMBER_TOKEN, make_num(csound, ".5")); temp->markup = &SYNTHESIZED_ARG; if (l->right==NULL) l->right = temp; else appendToTree(csound, l->right, temp); break; case 'h': temp = make_leaf(csound, l->line, l->locn, INTEGER_TOKEN, make_int(csound, "127")); temp->markup = &SYNTHESIZED_ARG; if (l->right==NULL) l->right = temp; else appendToTree(csound, l->right, temp); break; case 'J': case 'j': temp = make_leaf(csound, l->line, l->locn, INTEGER_TOKEN, make_int(csound, "-1")); temp->markup = &SYNTHESIZED_ARG; if (l->right==NULL) l->right = temp; else appendToTree(csound, l->right, temp); break; case 'M': case 'N': case 'm': case 'W': nreqd--; break; default: synterr(csound, Str("insufficient required arguments for opcode %s" " on line %d:\n"), ep->opname, l->line); do_baktrace(csound, l->locn); } incnt++; } while (incnt < nreqd); } // printf("delete %p \n", inArgParts); if (inArgParts != NULL) { int n; for (n=0; inArgParts[n] != NULL; n++) { //printf("delete %p \n", inArgParts[n]); csound->Free(csound, inArgParts[n]); } csound->Free(csound, inArgParts); } } } char tree_argtyp(CSOUND *csound, TREE *tree) { if (tree->type == INTEGER_TOKEN || tree->type == NUMBER_TOKEN) { return 'i'; } return argtyp2( tree->value->lexeme); } csound-6.10.0/Engine/csound_pre.lex000066400000000000000000001533611321653344700171720ustar00rootroot00000000000000%{ /* csound_pre.l: Copyright (C) 2011 John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MAc 02111-1307 USA */ #include #include #include #include #include "csoundCore.h" #include "corfile.h" #define YY_DECL int yylex (CSOUND *csound, yyscan_t yyscanner) static void comment(yyscan_t); static void do_comment(yyscan_t); static void do_include(CSOUND *, int, yyscan_t); static void do_macro_arg(CSOUND *, char *, yyscan_t); static void do_macro(CSOUND *, char *, yyscan_t); static void do_umacro(CSOUND *, char *, yyscan_t); static void do_ifdef(CSOUND *, char *, yyscan_t); static void do_ifdef_skip_code(CSOUND *, yyscan_t); static void do_function(CSOUND*, char *, CORFIL*); //static void print_csound_predata(CSOUND *,char *,yyscan_t); static void csound_pre_line(CSOUND *, CORFIL*, yyscan_t); static void delete_macros(CSOUND*, yyscan_t); #include "parse_param.h" #define YY_EXTRA_TYPE PRE_PARM * #define PARM yyget_extra(yyscanner) #define YY_USER_INIT {csound_pre_scan_string(csound->orchstr->body, yyscanner); \ csound_preset_lineno(csound->orcLineOffset, yyscanner); \ yyg->yy_flex_debug_r=1; PARM->macro_stack_size = 0; \ PARM->alt_stack = NULL; PARM->macro_stack_ptr = 0; \ } static MACRO *find_definition(MACRO *, char *); %} %option reentrant %option noyywrap %option prefix="csound_pre" %option outfile="Engine/csound_prelex.c" %option stdout NEWLINE (\n|\r\n?) STSTR \" ESCAPE \\. XSTR \{\{([^}]|\}[^}])*\}\} IDENT [a-zA-Z_][a-zA-Z0-9_]* MACRONAME "$"`?[a-zA-Z_][a-zA-Z0-9_`]* MACRONAMED "$"`?[a-zA-Z_][a-zA-Z0-9_`]*\. MACRONAMEA "$"`?[a-zA-Z_][a-zA-Z0-9_`]*\( MACRONAMEDA "$"`?[a-zA-Z_][a-zA-Z0-9_`]*\.\( MACROB [a-zA-Z_][a-zA-Z0-9_]*\( MACRO [a-zA-Z_][a-zA-Z0-9_]* STCOM \/\* INCLUDE "#include" DEFINE #[ \t]*define UNDEF "#undef" IFDEF #ifn?def ELSE #else[ \t]*(;.*)?$ END #end(if)?[ \t]*(;.*)?(\n|\r\n?) CONT \\[ \t]*(;.*)?(\n|\r\n?) RESET "###\n" INT "int"[ \t]*\( FRAC "frac"[ \t]*\( ROUND "round"[ \t]*\( FLOOR "floor"[ \t]*\( CEIL "ceil"[ \t]*\( RND "rnd"[ \t]*\( BIRND "birnd"[ \t]*\( ABS "abs"[ \t]*\( EXP "exp"[ \t]*\( LOG "log"[ \t]*\( SQRT "sqrt"[ \t]*\( SIN "sin"[ \t]*\( COS "cos"[ \t]*\( TAN "tan"[ \t]*\( SININV "sininv"[ \t]*\( COSINV "cosinv"[ \t]*\( TANINV "taninv"[ \t]*\( LOG10 "log10"[ \t]*\( LOG2 "log2"[ \t]*\( SINH "sinh"[ \t]*\( COSH "cosh"[ \t]*\( TANH "tanh"[ \t]*\( AMPDB "ampdb"[ \t]*\( AMPDBFS "ampdbfs"[ \t]*\( DBAMP "dbamp"[ \t]*\( DBFSAMP "dbfsamp"[ \t]*\( FTCPS "ftcps"[ \t]*\( FTLEN "ftlen"[ \t]*\( FTSR "ftsr"[ \t]*\( FTLPTIM "ftlptim"[ \t]*\( FTCHNLS "ftchnls"[ \t]*\( I "i"[ \t]*\( K "k"[ \t]*\( CPSOCT "cpsoct"[ \t]*\( OCTPCH "octpch"[ \t]*\( CPSPCH "cpspch"[ \t]*\( PCHOCT "pchoct"[ \t]*\( OCTCPS "octcps"[ \t]*\( NSAMP "nsamp"[ \t]*\( POWOFTWO "powoftwo"[ \t]*\( LOGBTWO "logbtwo"[ \t]*\( A "a"[ \t]*\( TB0 "tb0"[ \t]*\( TB1 "tb1"[ \t]*\( TB2 "tb2"[ \t]*\( TB3 "tb3"[ \t]*\( TB4 "tb4"[ \t]*\( TB5 "tb5"[ \t]*\( TB6 "tb6"[ \t]*\( TB7 "tb7"[ \t]*\( TB8 "tb8"[ \t]*\( TB9 "tb9"[ \t]*\( TB10 "tb10"[ \t]*\( TB11 "tb11"[ \t]*\( TB12 "tb12"[ \t]*\( TB13 "tb13"[ \t]*\( TB14 "tb14"[ \t]*\( TB15 "tb15"[ \t]*\( URD "urd"[ \t]*\( NOT "not"[ \t]*\( CENT "cent"[ \t]*\( OCTAVE "octave"[ \t]*\( SEMITONE "semitone"[ \t]*\( CPSMIDIN "cpsmidinn"[ \t]*\( OCTMIDIN "octmidinn"[ \t]*\( PCHMIDIN "pchmidinn"[ \t]*\( DB "db"[ \t]*\( P "p"[ \t]*\( QINF "qinf"[ \t]*\( QNAN "qnan"[ \t]*\( %X incl %x macro %x umacro %x ifdef %% {RESET} { csound_preset_lineno(csound->orcLineOffset, yyscanner); csound->Free(csound, PARM->alt_stack); } {CONT} { char bb[80]; csound_preset_lineno(1+csound_preget_lineno(yyscanner), yyscanner); if (PARM->isString==0) { sprintf(bb, "#sline %d ", csound_preget_lineno(yyscanner)); corfile_puts(csound, bb, csound->expanded_orc); } } {NEWLINE} { corfile_putc(csound, '\n', csound->expanded_orc); csound_preset_lineno(1+csound_preget_lineno(yyscanner), yyscanner); csound_pre_line(csound, csound->expanded_orc, yyscanner); } "//" { if (PARM->isString != 1) { comment(yyscanner); corfile_putc(csound, '\n', csound->expanded_orc); csound_pre_line(csound, csound->expanded_orc, yyscanner); } else { corfile_puts(csound, yytext, csound->expanded_orc); } } ";" { if (PARM->isString != 1) { comment(yyscanner); corfile_putc(csound, '\n', csound->expanded_orc); csound_pre_line(csound, csound->expanded_orc, yyscanner); } else { corfile_puts(csound, yytext, csound->expanded_orc); } //corfile_putline(csound_preget_lineno(yyscanner), // csound->expanded_orc); } {STCOM} { if (PARM->isString != 1) do_comment(yyscanner); else corfile_puts(csound, yytext, csound->expanded_orc); } {ESCAPE} { corfile_puts(csound, yytext, csound->expanded_orc); } {STSTR} { corfile_putc(csound, '"', csound->expanded_orc); PARM->isString = !PARM->isString; } {XSTR} { char c, *str = yytext; if (PARM->isString == 1) yyless(2); while ((c = *str++) != '\0') { switch(c) { case '\r': if (*str == '\n') continue; case '\n': csound_preset_lineno(1+csound_preget_lineno(yyscanner), yyscanner); break; default: break; } } corfile_puts(csound, yytext, csound->expanded_orc); } {MACRONAME}|{MACRONAMED} { MACRO *mm = PARM->macros; //printf("macro name >>%s<<\n", yytext); mm = find_definition(mm, yytext+1); if (UNLIKELY(mm == NULL)) { csound->Message(csound,Str("Undefined macro: '%s'"), yytext); //csound->LongJmp(csound, 1); corfile_puts(csound, "$error", csound->expanded_orc); } else { /* Need to read from macro definition */ if (UNLIKELY(PARM->macro_stack_ptr >= PARM->macro_stack_size )) { PARM->alt_stack = (MACRON*) csound->ReAlloc(csound, PARM->alt_stack, sizeof(MACRON)* (PARM->macro_stack_size+=10)); if (UNLIKELY(PARM->alt_stack == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } } PARM->alt_stack[PARM->macro_stack_ptr].n = 0; PARM->alt_stack[PARM->macro_stack_ptr].line = csound_preget_lineno(yyscanner); PARM->alt_stack[PARM->macro_stack_ptr++].s = NULL; yypush_buffer_state(YY_CURRENT_BUFFER, yyscanner); csound_preset_lineno(1, yyscanner); if (UNLIKELY(PARM->depth>1022)) { csound->Message(csound, Str("macros/include nested too deep: ")); csound->LongJmp(csound, 1); } PARM->lstack[++PARM->depth] = (strchr(mm->body,'\n') ?file_to_int(csound, yytext) : 63); yy_scan_string(mm->body, yyscanner); /* csound->DebugMsg(csound,"%p\n", YY_CURRENT_BUFFER); */ } } {MACRONAMEA}|{MACRONAMEDA} { MACRO *mm = PARM->macros; int err = 0; char *mname; int c, i, j, cnt=0; //csound->DebugMsg(csound,"Macro with arguments call %s\n", // yytext); yytext[yyleng-1] = '\0'; mm = find_definition(PARM->macros, yytext+1); if (UNLIKELY(mm == NULL)) { csound->Message(csound,Str("Undefined macro: '%s'"), yytext); corfile_puts(csound, "$error", csound->expanded_orc); } else { mname = yytext; /* Need to read from macro definition */ csound->DebugMsg(csound,"Looking for %d args\n", mm->acnt); for (j = 0; j < mm->acnt; j++) { char term = (j == mm->acnt - 1 ? ')' : '\''); /* Compatability */ char trm1 = (j == mm->acnt - 1 ? ')' : '#'); MACRO *nn = (MACRO*) csound->Malloc(csound, sizeof(MACRO)); int size = 100; if (UNLIKELY(nn == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } nn->name = csound->Malloc(csound, strlen(mm->arg[j]) + 1); if (UNLIKELY(nn->name == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } csound->DebugMsg(csound,"Arg %d: %s\n", j+1, mm->arg[j]); strcpy(nn->name, mm->arg[j]); csound->Message(csound, "defining argument %s ", nn->name); i = 0; nn->body = (char*) csound->Malloc(csound, 100); if (UNLIKELY(nn->body == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } while (1) { c = input(yyscanner); if (cnt==0 && ( c==term || c==trm1)) break; if (UNLIKELY(cnt==0 && c == ')')) { csound->Message(csound, Str("Too few arguments to macro\n")); corfile_puts(csound, "$error", csound->expanded_orc); err = 1; break; } if (c=='(') cnt++; if (c==')') cnt--; if (c == '\\') { int newc = input(yyscanner); if (newc == ')') nn->body[i++] = c; c = newc; } if (UNLIKELY(i > 98)) { csound->Message(csound, Str("Missing argument " "terminator\n%.98s"), nn->body); corfile_puts(csound, "$error", csound->expanded_orc); err = 1; break; } nn->body[i++] = c; if (UNLIKELY(i >= size)) { nn->body = csound->ReAlloc(csound, nn->body, size += 100); if (UNLIKELY(nn->body == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } } } nn->body[i] = '\0'; csound->Message(csound, "as...#%s#\n", nn->body); nn->acnt = 0; /* No arguments for arguments */ nn->next = PARM->macros; PARM->macros = nn; } if (!err) { //csound->DebugMsg(csound,"New body: ...#%s#\n", mm->body); if (UNLIKELY(PARM->macro_stack_ptr >= PARM->macro_stack_size )) { PARM->alt_stack = (MACRON*) csound->ReAlloc(csound, PARM->alt_stack, sizeof(MACRON)* (PARM->macro_stack_size+=10)); if (UNLIKELY(PARM->alt_stack == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } /* csound->DebugMsg(csound, */ /* "macro_stack extends alt_stack to %d long\n", */ /* PARM->macro_stack_size); */ } PARM->alt_stack[PARM->macro_stack_ptr].n = PARM->macros->acnt; PARM->alt_stack[PARM->macro_stack_ptr].line = csound_preget_lineno(yyscanner); PARM->alt_stack[PARM->macro_stack_ptr++].s = PARM->macros; PARM->alt_stack[PARM->macro_stack_ptr].n = 0; PARM->alt_stack[PARM->macro_stack_ptr].line = csound_preget_lineno(yyscanner); /* printf("stacked line = %llu at %d\n", */ /* csound_preget_lineno(yyscanner), */ /* PARM->macro_stack_ptr-1); */ PARM->alt_stack[PARM->macro_stack_ptr].s = NULL; //csound->DebugMsg(csound,"Push %p macro stack\n", // PARM->macros); yypush_buffer_state(YY_CURRENT_BUFFER, yyscanner); csound_preset_lineno(1, yyscanner); if (UNLIKELY(PARM->depth>1022)) { csound->Message(csound, Str("macros/include nested too deep: ")); corfile_puts(csound, "$error", csound->expanded_orc); err = 1; } } if (!err) { PARM->lstack[++PARM->depth] = (strchr(mm->body,'\n') ?file_to_int(csound, mname) : 63); yy_scan_string(mm->body, yyscanner); } } } {INCLUDE} { if (PARM->isString != 1) BEGIN(incl); else corfile_puts(csound, yytext, csound->expanded_orc); } [ \t]* /* eat the whitespace */ . { /* got the include file name */ do_include(csound, yytext[0], yyscanner); BEGIN(INITIAL); } #exit { corfile_putc(csound, '\0', csound->expanded_orc); corfile_putc(csound, '\0', csound->expanded_orc); delete_macros(csound, yyscanner); return 0;} <> { MACRO *x, *y=NULL; int n; /* csound->DebugMsg(csound,"*********Leaving buffer %p\n", */ /* YY_CURRENT_BUFFER); */ yypop_buffer_state(yyscanner); PARM->depth--; if (UNLIKELY(PARM->depth > 1024)) csound->Die(csound, Str("unexpected EOF!")); PARM->llocn = PARM->locn; PARM->locn = make_location(PARM); /* csound->DebugMsg(csound,"%s(%d): loc=%Ld; lastloc=%Ld\n", */ /* __FILE__, __LINE__, */ /* PARM->llocn, PARM->locn); */ if ( !YY_CURRENT_BUFFER ) yyterminate(); csound->DebugMsg(csound,"End of input; popping to %p\n", YY_CURRENT_BUFFER); csound_pre_line(csound, csound->expanded_orc, yyscanner); n = PARM->alt_stack[--PARM->macro_stack_ptr].n; /* printf("lineno on stack is %llu\n", */ /* PARM->alt_stack[PARM->macro_stack_ptr].line); */ csound->DebugMsg(csound,"n=%d\n", n); if (n!=0) { /* We need to delete n macros starting with y */ y = PARM->alt_stack[PARM->macro_stack_ptr].s; x = PARM->macros; if (x==y) { while (n>0) { mfree(csound, y->name); x=y->next; mfree(csound, y); y=x; n--; } PARM->macros = x; } else { MACRO *nxt = y->next; while (x->next != y) x = x->next; while (n>0) { nxt = y->next; mfree(csound, y->name); mfree(csound, y); y=nxt; n--; } x->next = nxt; } y->next = x; } csound_preset_lineno(PARM->alt_stack[PARM->macro_stack_ptr].line, yyscanner); csound->DebugMsg(csound, "csound_pe(%d): line now %d at %d\n", __LINE__, csound_preget_lineno(yyscanner), PARM->macro_stack_ptr); csound->DebugMsg(csound, "End of input segment: macro pop %p -> %p\n", y, PARM->macros); csound_preset_lineno(PARM->alt_stack[PARM->macro_stack_ptr].line, yyscanner); //print_csound_predata(csound,"Before pre_line", yyscanner); csound_pre_line(csound, csound->orchstr, yyscanner); //print_csound_predata(csound,"After pre_line", yyscanner); } {DEFINE} { if (PARM->isString != 1) BEGIN(macro); else corfile_puts(csound, yytext, csound->expanded_orc); } [ \t]* /* eat the whitespace */ {MACROB} { yytext[yyleng-1] = '\0'; csound->DebugMsg(csound,"Define macro with args %s\n", yytext); /* print_csound_predata(csound, "Before do_macro_arg", yyscanner); */ do_macro_arg(csound, yytext, yyscanner); //print_csound_predata(csound,"After do_macro_arg", yyscanner); BEGIN(INITIAL); } {MACRO} { csound->DebugMsg(csound,"Define macro %s\n", yytext); /* print_csound_predata(csound,"Before do_macro", yyscanner); */ do_macro(csound, yytext, yyscanner); //print_csound_predata(csound,"After do_macro", yyscanner); BEGIN(INITIAL); } . { csound->Message(csound, Str("Unexpected character %c(%.2x) line %d\n"), yytext[0], yytext[0], csound_preget_lineno(yyscanner)); csound->LongJmp(csound, 1); } {UNDEF} { if (PARM->isString != 1) BEGIN(umacro); else corfile_puts(csound, yytext, csound->expanded_orc); } [ \t]* /* eat the whitespace */ {MACRO} { csound->DebugMsg(csound,"Undefine macro %s\n", yytext); do_umacro(csound, yytext, yyscanner); BEGIN(INITIAL); } {IFDEF} { if (PARM->isString != 1) { PARM->isIfndef = (yytext[3] == 'n'); /* #ifdef or #ifndef */ csound_preset_lineno(1+csound_preget_lineno(yyscanner), yyscanner); corfile_putc(csound, '\n', csound->expanded_orc); csound_pre_line(csound, csound->expanded_orc, yyscanner); BEGIN(ifdef); } else { corfile_puts(csound, yytext, csound->expanded_orc); } } [ \t]* /* eat the whitespace */ {IDENT} { do_ifdef(csound, yytext, yyscanner); BEGIN(INITIAL); } {ELSE} { if (PARM->isString != 1) { if (PARM->ifdefStack == NULL) { csound->Message(csound, Str("#else without #if\n")); csound->LongJmp(csound, 1); } else if (PARM->ifdefStack->isElse) { csound->Message(csound, Str("#else after #else\n")); csound->LongJmp(csound, 1); } PARM->ifdefStack->isElse = 1; csound_preset_lineno(1+csound_preget_lineno(yyscanner), yyscanner); corfile_putc(csound, '\n', csound->expanded_orc); csound_pre_line(csound, csound->expanded_orc, yyscanner); do_ifdef_skip_code(csound, yyscanner); } else { corfile_puts(csound, yytext, csound->expanded_orc); } } {END} { if (PARM->isString != 1) { IFDEFSTACK *pp = PARM->ifdefStack; if (UNLIKELY(pp == NULL)) { csound->Message(csound, Str("Unmatched #end\n")); csound->LongJmp(csound, 1); } PARM->ifdefStack = pp->prv; csound_preset_lineno(1+csound_preget_lineno(yyscanner), yyscanner); corfile_putc(csound, '\n', csound->expanded_orc); csound_pre_line(csound, csound->expanded_orc, yyscanner); mfree(csound, pp); } else { corfile_puts(csound, yytext, csound->expanded_orc); } } {IDENT} { corfile_puts(csound, yytext,csound->expanded_orc); } {INT} { do_function(csound, yytext,csound->expanded_orc); } {FRAC} { do_function(csound, yytext,csound->expanded_orc); } {ROUND} { do_function(csound, yytext,csound->expanded_orc); } {FLOOR} { do_function(csound, yytext,csound->expanded_orc); } {CEIL} { do_function(csound, yytext,csound->expanded_orc); } {RND} { do_function(csound, yytext,csound->expanded_orc); } {BIRND} { do_function(csound, yytext,csound->expanded_orc); } {ABS} { do_function(csound, yytext,csound->expanded_orc); } {EXP} { do_function(csound, yytext,csound->expanded_orc); } {LOG} { do_function(csound, yytext,csound->expanded_orc); } {SQRT} { do_function(csound, yytext,csound->expanded_orc); } {SIN} { do_function(csound, yytext,csound->expanded_orc); } {COS} { do_function(csound, yytext,csound->expanded_orc); } {TAN} { do_function(csound, yytext,csound->expanded_orc); } {SININV} { do_function(csound, yytext,csound->expanded_orc); } {COSINV} { do_function(csound, yytext,csound->expanded_orc); } {TANINV} { do_function(csound, yytext,csound->expanded_orc); } {LOG10} { do_function(csound, yytext,csound->expanded_orc); } {LOG2} { do_function(csound, yytext,csound->expanded_orc); } {SINH} { do_function(csound, yytext,csound->expanded_orc); } {COSH} { do_function(csound, yytext,csound->expanded_orc); } {TANH} { do_function(csound, yytext,csound->expanded_orc); } {AMPDB} { do_function(csound, yytext,csound->expanded_orc); } {AMPDBFS} { do_function(csound, yytext,csound->expanded_orc); } {DBAMP} { do_function(csound, yytext,csound->expanded_orc); } {DBFSAMP} { do_function(csound, yytext,csound->expanded_orc); } {FTCPS} { do_function(csound, yytext,csound->expanded_orc); } {FTLEN} { do_function(csound, yytext,csound->expanded_orc); } {FTSR} { do_function(csound, yytext,csound->expanded_orc); } {FTLPTIM} { do_function(csound, yytext,csound->expanded_orc); } {FTCHNLS} { do_function(csound, yytext,csound->expanded_orc); } {I} { do_function(csound, yytext,csound->expanded_orc); } {K} { do_function(csound, yytext,csound->expanded_orc); } {CPSOCT} { do_function(csound, yytext,csound->expanded_orc); } {OCTPCH} { do_function(csound, yytext,csound->expanded_orc); } {CPSPCH} { do_function(csound, yytext,csound->expanded_orc); } {PCHOCT} { do_function(csound, yytext,csound->expanded_orc); } {OCTCPS} { do_function(csound, yytext,csound->expanded_orc); } {NSAMP} { do_function(csound, yytext,csound->expanded_orc); } {POWOFTWO} { do_function(csound, yytext,csound->expanded_orc); } {LOGBTWO} { do_function(csound, yytext,csound->expanded_orc); } {A} { do_function(csound, yytext,csound->expanded_orc); } {TB0} { do_function(csound, yytext,csound->expanded_orc); } {TB1} { do_function(csound, yytext,csound->expanded_orc); } {TB2} { do_function(csound, yytext,csound->expanded_orc); } {TB3} { do_function(csound, yytext,csound->expanded_orc); } {TB4} { do_function(csound, yytext,csound->expanded_orc); } {TB5} { do_function(csound, yytext,csound->expanded_orc); } {TB6} { do_function(csound, yytext,csound->expanded_orc); } {TB7} { do_function(csound, yytext,csound->expanded_orc); } {TB8} { do_function(csound, yytext,csound->expanded_orc); } {TB9} { do_function(csound, yytext,csound->expanded_orc); } {TB10} { do_function(csound, yytext,csound->expanded_orc); } {TB11} { do_function(csound, yytext,csound->expanded_orc); } {TB12} { do_function(csound, yytext,csound->expanded_orc); } {TB13} { do_function(csound, yytext,csound->expanded_orc); } {TB14} { do_function(csound, yytext,csound->expanded_orc); } {TB15} { do_function(csound, yytext,csound->expanded_orc); } {URD} { do_function(csound, yytext,csound->expanded_orc); } {NOT} { do_function(csound, yytext,csound->expanded_orc); } {CENT} { do_function(csound, yytext,csound->expanded_orc); } {OCTAVE} { do_function(csound, yytext,csound->expanded_orc); } {SEMITONE} { do_function(csound, yytext,csound->expanded_orc); } {CPSMIDIN} { do_function(csound, yytext,csound->expanded_orc); } {OCTMIDIN} { do_function(csound, yytext,csound->expanded_orc); } {PCHMIDIN} { do_function(csound, yytext,csound->expanded_orc); } {DB} { do_function(csound, yytext,csound->expanded_orc); } {P} { do_function(csound, yytext,csound->expanded_orc); } {QINF} { do_function(csound, yytext,csound->expanded_orc); } {QNAN} { do_function(csound, yytext,csound->expanded_orc); } . { corfile_putc(csound, yytext[0], csound->expanded_orc); } %% void comment(yyscan_t yyscanner) /* Skip until nextline */ { char c; struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; while ((c = input(yyscanner)) != '\n' && c != '\r') { /* skip */ if (UNLIKELY((int)c == EOF)) { YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; return; } } if (c == '\r' && (c = input(yyscanner)) != '\n') { if (LIKELY((int)c != EOF)) unput(c); else YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } csound_preset_lineno(1+csound_preget_lineno(yyscanner),yyscanner); } void do_comment(yyscan_t yyscanner) /* Skip until * and / chars */ { int c; struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; TOP: c = input(yyscanner); switch (c) { NL: case '\n': csound_preset_lineno(1+csound_preget_lineno(yyscanner),yyscanner); goto TOP; case '*': AST: c = input(yyscanner); switch (c) { case '*': goto AST; case '\n': goto NL; case '/': return; case EOF: goto ERR; default: goto TOP; } case EOF: ERR: YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; return; default: goto TOP; } } #ifndef WIN32 int isDir(char *path) { struct stat statbuf; if (stat(path, &statbuf) != 0) return 0; return S_ISDIR(statbuf.st_mode); } #else int isDir(char *path) { return 0;} #endif void do_include(CSOUND *csound, int term, yyscan_t yyscanner) { char buffer[100]; int p=0; int c; CORFIL *cf; struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; while ((c=input(yyscanner))!=term) { if (c=='\n' || c==EOF) { csound->Warning(csound, Str("Ill formed #include ignored")); return; } buffer[p] = c; p++; } buffer[p] = '\0'; while ((c=input(yyscanner))!='\n'); if (UNLIKELY(PARM->depth++>=1024)) { csound->Die(csound, Str("Includes nested too deeply")); } csound_preset_lineno(1+csound_preget_lineno(yyscanner), yyscanner); csound->DebugMsg(csound,"line %d at end of #include line\n", csound_preget_lineno(yyscanner)); { uint8_t n = file_to_int(csound, buffer); char bb[128]; PARM->lstack[PARM->depth] = n; sprintf(bb, "#source %llu\n", PARM->locn = make_location(PARM)); PARM->llocn = PARM->locn; corfile_puts(csound, bb, csound->expanded_orc); } csound->DebugMsg(csound,"reading included file \"%s\"\n", buffer); if (UNLIKELY(isDir(buffer))) csound->Warning(csound, Str("%s is a directory; not including"), buffer); cf = copy_to_corefile(csound, buffer, "INCDIR", 0); if (UNLIKELY(cf == NULL)) csound->Die(csound, Str("Cannot open #include'd file %s\n"), buffer); if (UNLIKELY(PARM->macro_stack_ptr >= PARM->macro_stack_size )) { PARM->alt_stack = (MACRON*) csound->ReAlloc(csound, PARM->alt_stack, sizeof(MACRON)*(PARM->macro_stack_size+=10)); if (UNLIKELY(PARM->alt_stack == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } /* csound->DebugMsg(csound, "alt_stack now %d long, \n", */ /* PARM->macro_stack_size); */ } csound->DebugMsg(csound,"cso_pre(%d): stacking line %d at %d\n", __LINE__, csound_preget_lineno(yyscanner),PARM->macro_stack_ptr); PARM->alt_stack[PARM->macro_stack_ptr].n = 0; PARM->alt_stack[PARM->macro_stack_ptr].line = csound_preget_lineno(yyscanner); PARM->alt_stack[PARM->macro_stack_ptr++].s = NULL; csound_prepush_buffer_state(YY_CURRENT_BUFFER, yyscanner); csound_pre_scan_string(cf->body, yyscanner); corfile_rm(csound, &cf); csound->DebugMsg(csound,"Set line number to 1\n"); csound_preset_lineno(1, yyscanner); } static inline int isNameChar(int c, int pos) { c = (int) ((unsigned char) c); return (isalpha(c) || (pos && (c == '_' || isdigit(c)))); } static void do_macro_arg(CSOUND *csound, char *name0, yyscan_t yyscanner) { MACRO *mm = (MACRO*) csound->Malloc(csound, sizeof(MACRO)); int arg = 0, i, c; int size = 100; int mlen = 40; char *q = name0; char *mname = malloc(mlen); if (UNLIKELY(mm == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } mm->margs = MARGS; /* Initial size */ mm->name = (char*)csound->Malloc(csound, strlen(name0) + 1); if (UNLIKELY(mm->name == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } strcpy(mm->name, name0); do { i = 0; q = name0; mname[i++] = '`'; while ((c = *q++)) { mname[i++] = c; if (UNLIKELY(i==mlen)) mname = (char *)realloc(mname, mlen+=40); if (UNLIKELY(mname == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } } mname[i++] = '`'; if (UNLIKELY(i==mlen)) { mname = (char *)realloc(mname, mlen+=40); if (UNLIKELY(mname == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } } mname[i++] = '`'; if (UNLIKELY(i==mlen)) { mname = (char *)realloc(mname, mlen+=40); if (UNLIKELY(mname == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } } while (isspace((c = input(yyscanner)))); while (isNameChar(c, i)) { mname[i++] = c; if (UNLIKELY(i==mlen)) { mname = (char *)realloc(mname, mlen+=40); if (UNLIKELY(mname == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } } c = input(yyscanner); } mname[i] = '\0'; mm->arg[arg] = csound->Malloc(csound, i + 1); if (UNLIKELY(mm->arg[arg] == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } strcpy(mm->arg[arg++], mname); if (UNLIKELY(arg >= mm->margs)) { mm = (MACRO*) csound->ReAlloc(csound, mm, sizeof(MACRO) + mm->margs * sizeof(char*)); if (UNLIKELY(mm == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } mm->margs += MARGS; } while (isspace(c)) c = input(yyscanner); } while (c == '\'' || c == '#'); if (UNLIKELY(c != ')')) { csound->Message(csound, Str("macro error\n")); } free(mname); c = input(yyscanner); while (c!='#') { if (UNLIKELY(c==EOF)) csound->Die(csound, Str("define macro runaway\n")); else if (c==';') { while ((c=input(yyscanner))!= '\n') if (UNLIKELY(c==EOF)) { csound->Die(csound, Str("define macro runaway\n")); } } else if (c=='/') { if ((c=input(yyscanner))=='/') { while ((c=input(yyscanner))!= '\n') if (UNLIKELY(c==EOF)) csound->Die(csound, Str("define macro runaway\n")); } else if (c=='*') { while ((c=input(yyscanner))!='*') { again: if (UNLIKELY(c==EOF)) csound->Die(csound, Str("define macro runaway\n")); } if ((c=input(yyscanner))!='/') goto again; } } else if (UNLIKELY(!isspace(c))) csound->Die(csound, Str("define macro unexpected character %c(0x%.2x) awaiting #\n"), c, c); c = input(yyscanner); /* skip to start of body */ } mm->acnt = arg; i = 0; mm->body = (char*) csound->Malloc(csound, 100); if (UNLIKELY(mm->body == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } while ((c = input(yyscanner)) != '#') { /* read body */ if (UNLIKELY(c == EOF)) csound->Die(csound, Str("define macro with args: unexpected EOF")); if (c=='$') { /* munge macro name? */ int n = strlen(name0)+4; if (UNLIKELY(i+n >= size)) { mm->body = csound->ReAlloc(csound, mm->body, size += 100); if (UNLIKELY(mm->body == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } } mm->body[i] = '$'; mm->body[i+1] = '`'; strcpy(&mm->body[i+2], name0); mm->body[i + n - 2] = '`'; mm->body[i + n - 1] = '`'; i+=n; continue; } mm->body[i++] = c=='\r'?'\n':c; if (UNLIKELY(i >= size)) { mm->body = csound->ReAlloc(csound, mm->body, size += 100); if (UNLIKELY(mm->body == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } } if (c == '\\') { /* allow escaped # */ mm->body[i++] = c = input(yyscanner); if (UNLIKELY(i >= size)) { mm->body = csound->ReAlloc(csound, mm->body, size += 100); if (UNLIKELY(mm->body == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } } } if (UNLIKELY(c == '\n' || c == '\r')) { csound_preset_lineno(1+csound_preget_lineno(yyscanner),yyscanner); corfile_putc(csound, '\n', csound->expanded_orc); csound_pre_line(csound, csound->expanded_orc, yyscanner); } } mm->body[i] = '\0'; mm->next = PARM->macros; PARM->macros = mm; } static void do_macro(CSOUND *csound, char *name0, yyscan_t yyscanner) { MACRO *mm = (MACRO*) csound->Malloc(csound, sizeof(MACRO)); int i, c; int size = 100; if (UNLIKELY(mm == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } mm->margs = MARGS; /* Initial size */ csound->DebugMsg(csound,"Macro definition for %s\n", name0); mm->name = (char*)csound->Malloc(csound, strlen(name0) + 1); if (UNLIKELY(mm->name == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } strcpy(mm->name, name0); mm->acnt = 0; i = 0; while ((c = input(yyscanner)) != '#') { if (UNLIKELY(c==EOF)) csound->Die(csound, Str("define macro runaway\n")); else if (c==';') { while ((c=input(yyscanner))!= '\n') if (UNLIKELY(c==EOF)) { csound->Die(csound, Str("define macro runaway\n")); } } else if (c=='/') { if ((c=input(yyscanner))=='/') { while ((c=input(yyscanner))!= '\n') if (UNLIKELY(c==EOF)) csound->Die(csound, Str("define macro runaway\n")); } else if (c=='*') { while ((c=input(yyscanner))!='*') { again: if (UNLIKELY(c==EOF)) csound->Die(csound, Str("define macro runaway\n")); } if ((c=input(yyscanner))!='/') goto again; } } else if (UNLIKELY(!isspace(c))) csound->Die(csound, Str("define macro unexpected character %c(0x%.2x)" " awaiting #\n"), c, c); } mm->body = (char*) csound->Malloc(csound, 100); if (UNLIKELY(mm->body == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } while ((c = input(yyscanner)) != '#') { if (UNLIKELY(c == EOF || c==0)) csound->Die(csound, Str("define macro: unexpected EOF")); mm->body[i++] = c=='\r'?'\n':c; if (UNLIKELY(i >= size)) { mm->body = csound->ReAlloc(csound, mm->body, size += 100); if (UNLIKELY(mm->body == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } } if (c == '\\') { /* allow escaped # */ mm->body[i++] = c = input(yyscanner); if (UNLIKELY(i >= size)) { mm->body = csound->ReAlloc(csound, mm->body, size += 100); if (UNLIKELY(mm->body == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } } } if (UNLIKELY(c == '\n' || c == '\r')) { csound_preset_lineno(1+csound_preget_lineno(yyscanner),yyscanner); corfile_putc(csound, '\n', csound->expanded_orc); csound_pre_line(csound, csound->expanded_orc, yyscanner); } } mm->body[i] = '\0'; csound->DebugMsg(csound,"Body #%s#\n", mm->body); mm->next = PARM->macros; PARM->macros = mm; } static void do_umacro(CSOUND *csound, char *name0, yyscan_t yyscanner) { int i,c; if (UNLIKELY(csound->oparms->msglevel)) csound->Message(csound,Str("macro %s undefined\n"), name0); csound->DebugMsg(csound, "macro %s undefined\n", name0); if (strcmp(name0, PARM->macros->name)==0) { MACRO *mm=PARM->macros->next; mfree(csound, PARM->macros->name); mfree(csound, PARM->macros->body); for (i=0; imacros->acnt; i++) mfree(csound, PARM->macros->arg[i]); mfree(csound, PARM->macros); PARM->macros = mm; } else { MACRO *mm = PARM->macros; MACRO *nn = mm->next; while (strcmp(name0, nn->name) != 0) { mm = nn; nn = nn->next; if (UNLIKELY(nn == NULL)) { csound->Message(csound, Str("Undefining undefined macro")); csound->LongJmp(csound, 1); } } mfree(csound, nn->name); mfree(csound, nn->body); for (i=0; iacnt; i++) mfree(csound, nn->arg[i]); mm->next = nn->next; mfree(csound, nn); } while ((c=input(yyscanner)) != '\n' && c != EOF && c != '\r'); /* ignore rest of line */ csound_preset_lineno(1+csound_preget_lineno(yyscanner),yyscanner); } static void do_ifdef(CSOUND *csound, char *name0, yyscan_t yyscanner) { int c; MACRO *mm; IFDEFSTACK *pp; pp = (IFDEFSTACK*) csound->Calloc(csound, sizeof(IFDEFSTACK)); if (UNLIKELY(pp == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } pp->prv = PARM->ifdefStack; pp->isDef = PARM->isIfndef; for (mm = PARM->macros; mm != NULL; mm = mm->next) { if (strcmp(name0, mm->name) == 0) { pp->isDef ^= (unsigned char) 1; break; } } PARM->ifdefStack = pp; pp->isSkip = pp->isDef ^ (unsigned char) 1; if (pp->isSkip) do_ifdef_skip_code(csound, yyscanner); else while ((c = input(yyscanner)) != '\n' && c != '\r' && c != EOF); } static void do_ifdef_skip_code(CSOUND *csound, yyscan_t yyscanner) { int i, c, nested_ifdef = 0; char buf[8]; IFDEFSTACK *pp; /* buf = (char*)malloc(8*sizeof(char)); */ /* if (UNLIKELY(buf == NULL)) { */ /* csound->Message(csound, Str("Memory exhausted")); */ /* csound->LongJmp(csound, 1); */ /* } */ pp = PARM->ifdefStack; c = input(yyscanner); for (;;) { while (c!='\n' && c!= '\r') { if (UNLIKELY(c == EOF)) { csound->Message(csound, Str("Unmatched #if%sdef\n"), PARM->isIfndef ? "n" : ""); csound->LongJmp(csound, 1); } c = input(yyscanner); } csound_preset_lineno(1+csound_preget_lineno(yyscanner), yyscanner); corfile_putc(csound, '\n', csound->expanded_orc); csound_pre_line(csound, csound->expanded_orc, yyscanner); while (isblank(c = input(yyscanner))); /* eat the whitespace */ if (c == '#') { for (i=0; islower(c = input(yyscanner)) && i < 7; i++) buf[i] = c; buf[i] = '\0'; if (strcmp("end", buf) == 0 || strcmp("endif", buf) == 0) { if (nested_ifdef-- == 0) { PARM->ifdefStack = pp->prv; mfree(csound, pp); break; } } else if (strcmp("ifdef", buf) == 0 || strcmp("ifndef", buf) == 0) { nested_ifdef++; } else if (strcmp("else", buf) == 0 && nested_ifdef == 0) { if (UNLIKELY(pp->isElse)) { csound->Message(csound, Str("#else after #else\n")); csound->LongJmp(csound, 1); } pp->isElse = 1; break; } } } while (c != '\n' && c != EOF && c != '\r') c = input(yyscanner); } static void delete_macros(CSOUND *csound, yyscan_t yyscanner) { MACRO * qq = PARM->macros; if (qq) { MACRO *mm = qq; while (mm) { csound->Free(csound, mm->body); csound->Free(csound, mm->name); qq = mm->next; csound->Free(csound, mm); mm = qq; } } } static void add_math_const_macro(CSOUND *csound, PRE_PARM* qq, char * name, char *body) { MACRO *mm; mm = (MACRO*) csound->Calloc(csound, sizeof(MACRO)); mm->name = (char*) csound->Calloc(csound, strlen(name) + 3); sprintf(mm->name, "M_%s", name); mm->next = qq->macros; qq->macros = mm; mm->margs = MARGS; /* Initial size */ mm->acnt = 0; mm->body = (char*) csound->Calloc(csound, strlen(body) + 1); mm->body = strcpy(mm->body, body); } /** * Add math constants from math.h as orc PARM->macros */ void cs_init_math_constants_macros(CSOUND *csound, PRE_PARM* qq) { qq->macros = NULL; add_math_const_macro(csound, qq, "E", "2.71828182845904523536"); add_math_const_macro(csound, qq, "LOG2E", "1.44269504088896340736"); add_math_const_macro(csound, qq, "LOG10E","0.43429448190325182765"); add_math_const_macro(csound, qq, "LN2", "0.69314718055994530942"); add_math_const_macro(csound, qq, "LN10", "2.30258509299404568402"); add_math_const_macro(csound, qq, "PI", "3.14159265358979323846"); add_math_const_macro(csound, qq, "PI_2", "1.57079632679489661923"); add_math_const_macro(csound, qq, "PI_4", "0.78539816339744830962"); add_math_const_macro(csound, qq, "1_PI", "0.31830988618379067154"); add_math_const_macro(csound, qq, "2_PI", "0.63661977236758134308"); add_math_const_macro(csound, qq,"2_SQRTPI", "1.12837916709551257390"); add_math_const_macro(csound, qq, "SQRT2", "1.41421356237309504880"); add_math_const_macro(csound, qq,"SQRT1_2","0.70710678118654752440"); add_math_const_macro(csound, qq, "INF", "800000000000.0");/* ~25367 years */ } void cs_init_omacros(CSOUND *csound, PRE_PARM *qq, NAMES *nn) { while (nn) { char *s = nn->mac; char *p = strchr(s, '='); char *mname; MACRO *mm; if (p == NULL) p = s + strlen(s); if (csound->oparms->msglevel & 7) csound->Message(csound, Str("Macro definition for %*s\n"), (int) (p - s), s); s = strchr(s, ':') + 1; /* skip arg bit */ if (UNLIKELY(s == NULL || s >= p)) { csound->Die(csound, Str("Invalid macro name for --omacro")); } mname = (char*) csound->Malloc(csound, (p - s) + 1); if (UNLIKELY(mname == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } strncpy(mname, s, p - s); mname[p - s] = '\0'; /* check if macro is already defined */ for (mm = qq->macros; mm != NULL; mm = mm->next) { if (strcmp(mm->name, mname) == 0) break; } if (mm == NULL) { mm = (MACRO*) csound->Calloc(csound, sizeof(MACRO)); if (UNLIKELY(mm == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } mm->name = mname; mm->next = qq->macros; qq->macros = mm; } else mfree(csound, mname); mm->margs = MARGS; /* Initial size */ mm->acnt = 0; if (*p != '\0') p++; mm->body = (char*) csound->Malloc(csound, strlen(p) + 1); if (UNLIKELY(mm->body == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } strcpy(mm->body, p); nn = nn->next; } } /* int csound_prewrap(void *yyscanner) */ /* { */ /* return 1; */ /* } */ void csound_pre_line(CSOUND *csound, CORFIL* cf, void *yyscanner) { int n = csound_preget_lineno(yyscanner); //printf("line number %d\n", n); /* This assumes that the initial line was not written with this system */ if (cf->p>0 && cf->body[cf->p-1]=='\n') { uint64_t locn = PARM->locn; uint64_t llocn = PARM->llocn; if (UNLIKELY(locn != llocn)) { char bb[80]; sprintf(bb, "#source %llu\n", locn); corfile_puts(csound, bb, cf); } PARM->llocn = locn; if (UNLIKELY(n!=PARM->line+1)) { char bb[80]; sprintf(bb, "#line %d\n", n); corfile_puts(csound, bb, cf); } } PARM->line = n; } void do_function(CSOUND *csound, char *text, CORFIL *cf) { char *p = text; //printf("do_function on >>%s<<\n", text); while (*p != '\0') { if (!isspace(*p)) corfile_putc(csound, *p, cf); p++; } return; } static MACRO *find_definition(MACRO *mmo, char *s) { MACRO *mm = mmo; if (s[strlen(s)-1]=='.') s[strlen(s)-1]='\0'; else if (s[strlen(s)-2]=='.' && s[strlen(s)-1]=='(') { s[strlen(s)-2] = '('; s[strlen(s)-1] = '\0'; } // printf("****Looking for %s strlen=%d\n", s, strlen(s), s[strlen(s)-1]); while (mm != NULL) { /* Find the definition */ //printf("looking at %p(%s) body #%s#\n", mm, mm->name, mm->body); if (!(strcmp(s, mm->name))) break; mm = mm->next; } if (mm == NULL) { mm = mmo; s++; /* skip _ */ looking: while (*s++!='`') { if (*s=='\0') return NULL; } if (*s++!='`') { s--; goto looking; } //printf("now try looking for %s\n", s); while (mm != NULL) { /* Find the definition */ //printf("looking at %p(%s) body #%s#\n", mm, mm->name, mm->body); if (!(strcmp(s, mm->name))) break; mm = mm->next; } } //if (mm) printf("found body #%s#\n****\n", mm->body); return mm; } #if 0 static void print_csound_predata(CSOUND *csound, char *mesg, void *yyscanner) { struct yyguts_t *yyg =(struct yyguts_t*)yyscanner; csound->DebugMsg(csound,"********* %s extra data ************", mesg); csound->DebugMsg(csound,"yyscanner = %p", yyscanner); csound->DebugMsg(csound,"yyextra_r = %p, yyin_r = %p, yyout_r = %p," " yy_buffer_stack_top = %d", yyg->yyextra_r, yyg->yyin_r,yyg->yyout_r, yyg->yy_buffer_stack_top); csound->DebugMsg(csound,"yy_buffer_stack_max = %d1, yy_buffer_stack = %p, " "yy_hold_char = %d '%c'", yyg->yy_buffer_stack_max, yyg->yy_buffer_stack, yyg->yy_hold_char, yyg->yy_hold_char); csound->DebugMsg(csound,"yy_n_chars = %d, yyleng_r = %d, yy_c_buf_p = %p %c", yyg->yy_n_chars, yyg->yyleng_r, yyg->yy_c_buf_p, *yyg->yy_c_buf_p); csound->DebugMsg(csound,"yy_init = %d, yy_start = %d, " "yy_did_buffer_switch_on_eof = %d", yyg->yy_init, yyg->yy_start, yyg->yy_did_buffer_switch_on_eof); csound->DebugMsg(csound,"yy_start_stack_ptr = %d," " yy_start_stack_depth = %d, yy_start_stack = %p", yyg->yy_start_stack_ptr, yyg->yy_start_stack_depth, yyg->yy_start_stack); csound->DebugMsg(csound,"yy_last_accepting_state = %d, " "yy_last_accepting_cpos = %p %c", yyg->yy_last_accepting_state, yyg->yy_last_accepting_cpos, *yyg->yy_last_accepting_cpos); csound->DebugMsg(csound,"yylineno_r = %d, yy_flex_debug_r = %d, " "yytext_r = %p \"%s\", yy_more_flag = %d, yy_more_len = %d", yyg->yylineno_r, yyg->yy_flex_debug_r, yyg->yytext_r, yyg->yytext_r, yyg->yy_more_flag, yyg->yy_more_len); { PRE_PARM* pp = yyg->yyextra_r; printf("macros = %p, isIfndef = %d, isString = %d, line - %d loc = %d\n", pp->macros, pp->isIfndef, pp->isString, pp->line, pp->locn); printf ("llocn = %d dept=%d\n", pp->llocn, pp->depth); } csound->DebugMsg(csound,"*********\n"); } #endif csound-6.10.0/Engine/csound_prs.lex000066400000000000000000001640141321653344700172050ustar00rootroot00000000000000%{ /* csound_prs.lex: Copyright (C) 2011, 2016 John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include "csoundCore.h" #include "corfile.h" #define YY_DECL int yylex (CSOUND *csound, yyscan_t yyscanner) static void comment(yyscan_t); static void do_comment(yyscan_t); static void do_include(CSOUND *, int, yyscan_t); extern int isDir(char *); static void do_macro_arg(CSOUND *, char *, yyscan_t); static void do_macro(CSOUND *, char *, yyscan_t); static void do_umacro(CSOUND *, char *, yyscan_t); static void do_ifdef(CSOUND *, char *, yyscan_t); static void do_ifdef_skip_code(CSOUND *, yyscan_t); //static void print_csound_prsdata(CSOUND *,char *,yyscan_t); static void csound_prs_line(CORFIL*, yyscan_t); static void delete_macros(CSOUND*, yyscan_t); #define MACDEBUG 1 static inline int isNameChar(int cc, int pos) { unsigned char c = ((unsigned char) cc); return (isalpha(c) || (pos && (c == '_' || isdigit(c)))); } #include "score_param.h" #define YY_EXTRA_TYPE PRS_PARM * #define PARM yyget_extra(yyscanner) #define YY_USER_INIT {csound_prs_scan_string(csound->scorestr->body, yyscanner); \ csound_prsset_lineno(csound->scoLineOffset, yyscanner); \ /*yyg->yy_flex_debug_r=1;*/ PARM->macro_stack_size = 0; \ PARM->alt_stack = NULL; PARM->macro_stack_ptr = 0; \ PARM->cf = csound->expanded_sco; \ } static MACRO *find_definition(MACRO *, char *); %} %option reentrant %option noyywrap %option prefix="csound_prs" %option outfile="Engine/csound_prslex.c" %option stdout NEWLINE (\n|\r\n?) STSTR \" ESCAPE \\. IDENT [a-zA-Z_][a-zA-Z0-9_]* MACRONAME "$"`?[a-zA-Z_][a-zA-Z0-9_`]* MACRONAMED "$"`?[a-zA-Z_][a-zA-Z0-9_`]*\. MACRONAMEA "$"`?[a-zA-Z_][a-zA-Z0-9_`]*\( MACRONAMEDA "$"`?[a-zA-Z_][a-zA-Z0-9_`]*\.\( MACROB [a-zA-Z_][a-zA-Z0-9_]*\( MACRO [a-zA-Z_][a-zA-Z0-9_]* NUMBER [0-9]+\.?[0-9]*([eE][-+]?[0-9]+)?|\.[0-9]+([eE][-+]?[0-9]+)?|0[xX][0-9a-fA-F]+ STCOM \/\* INCLUDE "#include" DEFINE #[ \t]*define UNDEF "#undef" IFDEF #ifn?def ELSE #else[ \t]*(;.*)?$ END #end(if)?[ \t]*(;.*)?(\n|\r\n?) LOOP #loop EXIT #exit CONT \\[ \t]*(;.*)?(\n|\r\n?) SEND ^[ \t]*[es] ROP ^[ \t]*r NM [nm] %X incl %x macro %x umacro %x ifdef %x lname %% {CONT} { #ifdef SCORE_PARSER char bb[80]; #endif csound_prsset_lineno(1+csound_prsget_lineno(yyscanner), yyscanner); #ifdef SCORE_PARSER if (PARM->isString==0) { sprintf(bb, "#sline %d ", csound_prsget_lineno(yyscanner)); corfile_puts(csound, bb, PARM->cf); } #endif } {NEWLINE} { corfile_putc(csound, '\n', PARM->cf); csound_prsset_lineno(1+csound_prsget_lineno(yyscanner), yyscanner); csound_prs_line(PARM->cf, yyscanner); } "//" { if (PARM->isString != 1) { comment(yyscanner); corfile_putc(csound, '\n', PARM->cf); csound_prs_line(PARM->cf, yyscanner); } else { corfile_puts(csound, yytext, PARM->cf); } } ";" { if (PARM->isString != 1) { comment(yyscanner); corfile_putc(csound, '\n', PARM->cf); csound_prs_line(PARM->cf, yyscanner); } else { corfile_puts(csound, yytext, PARM->cf); } //corfile_putline(csound_prsget_lineno(yyscanner), // PARM->cf); } {STCOM} { if (PARM->isString != 1) do_comment(yyscanner); else corfile_puts(csound, yytext, PARM->cf); } {ESCAPE} { corfile_puts(csound, yytext, PARM->cf); } {STSTR} { corfile_putc(csound, '"', PARM->cf); PARM->isString = !PARM->isString; } {MACRONAME}|{MACRONAMED} { MACRO *mm = PARM->macros; mm = find_definition(mm, yytext+1); if (UNLIKELY(mm == NULL)) { csound->Message(csound,Str("Undefined macro: '%s'"), yytext); //csound->LongJmp(csound, 1); corfile_puts(csound, "$error", PARM->cf); } else { /* Need to read from macro definition */ if (mm->acnt<0) { /* Macro inhibitted */ corfile_puts(csound, yytext, PARM->cf); } else { if (UNLIKELY(PARM->macro_stack_ptr>= PARM->macro_stack_size)) { PARM->alt_stack = (MACRON*) csound->ReAlloc(csound, PARM->alt_stack, sizeof(MACRON)*(PARM->macro_stack_size+=10)); if (UNLIKELY(PARM->alt_stack == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } /* csound->DebugMsg(csound, "alt_stack now %d long\n", */ /* PARM->macro_stack_size); */ } PARM->alt_stack[PARM->macro_stack_ptr].n = 0; PARM->alt_stack[PARM->macro_stack_ptr].line = csound_prsget_lineno(yyscanner); PARM->alt_stack[PARM->macro_stack_ptr++].s = NULL; yypush_buffer_state(YY_CURRENT_BUFFER, yyscanner); csound_prsset_lineno(1, yyscanner); if (UNLIKELY(PARM->depth>1022)) { csound->Message(csound, Str("macros/include nested too deep: ")); csound->LongJmp(csound, 1); } PARM->lstack[++PARM->depth] = (strchr(mm->body,'\n') ?file_to_int(csound, yytext) : 63); yy_scan_string(mm->body, yyscanner); /* csound->DebugMsg(csound,"%p\n", YY_CURRENT_BUFFER); */ } } } {MACRONAMEA}|{MACRONAMEDA} { MACRO *mm = PARM->macros; int err =0; char *mname; int c, i, j, cnt=0; //csound->DebugMsg(csound,"Macro with arguments call %s\n", // yytext); yytext[yyleng-1] = '\0'; mm = find_definition(PARM->macros, yytext+1); if (UNLIKELY(mm == NULL)) { csound->Message(csound,Str("Undefined macro: '%s'"), yytext); corfile_puts(csound, "$error", PARM->cf); //csound->LongJmp(csound, 1); } else { mname = yytext; /* Need to read from macro definition */ //csound->DebugMsg(csound,"Looking for %d args\n", mm->acnt); for (j = 0; j < mm->acnt; j++) { char term = (j == mm->acnt - 1 ? ')' : '\''); /* Compatability */ char trm1 = (j == mm->acnt - 1 ? ')' : '#'); MACRO *nn = (MACRO*) csound->Malloc(csound, sizeof(MACRO)); //int size = 100; if (UNLIKELY(nn == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } nn->name = csound->Malloc(csound, strlen(mm->arg[j]) + 1); if (UNLIKELY(nn->name == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } //csound->DebugMsg(csound,"Arg %d: %s\n", j+1, mm->arg[j]); strcpy(nn->name, mm->arg[j]); csound->Message(csound, "defining argument %s ", nn->name); i = 0; nn->body = (char*) csound->Malloc(csound, 100); if (UNLIKELY(nn->body == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } while (1) { c = input(yyscanner); if (cnt==0 && ( c==term || c==trm1)) break; if (UNLIKELY(cnt==0 && c == ')')) { csound->Message(csound, Str("Too few arguments to macro\n")); corfile_puts(csound, "$error", PARM->cf); err = 1; break; } if (c=='(') cnt++; if (c==')') cnt--; if (c == '\\') { int newc = input(yyscanner); if (newc != ')') nn ->body[i++] = c; c = newc; } if (UNLIKELY(i > 98)) { csound->Message(csound, Str("Missing argument terminator\n%.98s"), nn->body); corfile_puts(csound, "$error", PARM->cf); err = 1; break; } nn->body[i++] = c; /* if (UNLIKELY(i >= size)) { */ /* nn->body = csound->ReAlloc(csound, nn->body, */ /* size += 100); */ /* if (UNLIKELY(nn->body == NULL)) { */ /* csound->Message(csound, Str("Memory exhausted")); */ /* csound->LongJmp(csound, 1); */ /* } */ /* } */ } nn->body[i] = '\0'; csound->Message(csound, "as...#%s#\n", nn->body); nn->acnt = 0; /* No arguments for arguments */ nn->next = PARM->macros; PARM->macros = nn; } if (!err) { //csound->DebugMsg(csound,"New body: ...#%s#\n", mm->body); if (UNLIKELY(PARM->macro_stack_ptr >= PARM->macro_stack_size )) { PARM->alt_stack = (MACRON*) csound->ReAlloc(csound, PARM->alt_stack, sizeof(MACRON)*(PARM->macro_stack_size+=10)); if (UNLIKELY(PARM->alt_stack == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } /* csound->DebugMsg(csound, */ /* "macro_stack extends alt_stack to %d long\n", */ /* PARM->macro_stack_size); */ } PARM->alt_stack[PARM->macro_stack_ptr].n = PARM->macros->acnt; PARM->alt_stack[PARM->macro_stack_ptr].line = csound_prsget_lineno(yyscanner); PARM->alt_stack[PARM->macro_stack_ptr++].s = PARM->macros; PARM->alt_stack[PARM->macro_stack_ptr].n = 0; PARM->alt_stack[PARM->macro_stack_ptr].line = csound_prsget_lineno(yyscanner); /* printf("stacked line = %llu at %d\n", */ /* csound_prsget_lineno(yyscanner), */ /* PARM->macro_stack_ptr-1); */ PARM->alt_stack[PARM->macro_stack_ptr].s = NULL; //csound->DebugMsg(csound,"Push %p macro stack\n", // PARM->macros); yypush_buffer_state(YY_CURRENT_BUFFER, yyscanner); csound_prsset_lineno(1, yyscanner); if (UNLIKELY(PARM->depth>1022)) { csound->Message(csound, Str("macros/include nested too deep: ")); //csound->LongJmp(csound, 1); corfile_puts(csound, "$error", PARM->cf); err = 1; } } if (!err) { PARM->lstack[++PARM->depth] = (strchr(mm->body,'\n') ?file_to_int(csound, mname) : 63); yy_scan_string(mm->body, yyscanner); } } } {INCLUDE} { if (PARM->isString != 1) BEGIN(incl); else corfile_puts(csound, yytext, PARM->cf); } [ \t]* /* eat the whitespace */ . { /* got the include file name */ do_include(csound, yytext[0], yyscanner); BEGIN(INITIAL); } {EXIT} { //printf("exit found: >>>%s<<<\n", PARM->cf->body); corfile_putc(csound, '\0', PARM->cf); corfile_putc(csound, '\0', PARM->cf); delete_macros(csound, yyscanner); return 0; } <> { MACRO *x, *y=NULL; int n; csound->DebugMsg(csound,"*********Leaving buffer %p\n", YY_CURRENT_BUFFER); yypop_buffer_state(yyscanner); PARM->depth--; if (UNLIKELY(PARM->depth > 1024)) { //csound->Die(csound, Str("unexpected EOF!!")); csound->Message(csound, Str("unexpected EOF!!\n")); csound->LongJmp(csound, 1); } PARM->llocn = PARM->locn; PARM->locn = make_location(PARM); csound->DebugMsg(csound,"csound-prs(%d): loc=%u; lastloc=%u\n", __LINE__, PARM->llocn, PARM->locn); if ( !YY_CURRENT_BUFFER ) yyterminate(); csound->DebugMsg(csound,"End of input; popping to %p\n", YY_CURRENT_BUFFER); csound_prs_line(PARM->cf, yyscanner); n = PARM->alt_stack[--PARM->macro_stack_ptr].n; /* printf("lineno on stack is %llu\n", */ /* PARM->alt_stack[PARM->macro_stack_ptr].line); */ csound->DebugMsg(csound,"n=%d\n", n); if (n!=0) { /* We need to delete n macros starting with y */ y = PARM->alt_stack[PARM->macro_stack_ptr].s; x = PARM->macros; if (x==y) { while (n>0) { mfree(csound, y->name); x=y->next; mfree(csound, y); y=x; n--; } PARM->macros = x; } else { MACRO *nxt = y->next; while (x->next != y) x = x->next; while (n>0) { nxt = y->next; mfree(csound, y->name); mfree(csound, y); y=nxt; n--; } x->next = nxt; } y->next = x; } csound_prsset_lineno(PARM->alt_stack[PARM->macro_stack_ptr].line, yyscanner); csound->DebugMsg(csound, "csound_prs(%d): line now %d at %d\n", __LINE__, csound_prsget_lineno(yyscanner), PARM->macro_stack_ptr); csound->DebugMsg(csound, "End of input segment: macro pop %p -> %p\n", y, PARM->macros); csound_prsset_lineno(PARM->alt_stack[PARM->macro_stack_ptr].line, yyscanner); //print_csound_prsdata(csound,"Before prs_line", yyscanner); csound_prs_line(PARM->cf, yyscanner); //print_csound_prsdata(csound,"After prs_line", yyscanner); } {DEFINE} { if (PARM->isString != 1) BEGIN(macro); else corfile_puts(csound, yytext, PARM->cf); } [ \t]* /* eat the whitespace */ {MACROB} { yytext[yyleng-1] = '\0'; csound->DebugMsg(csound,"Define macro with args %s\n", yytext); /* print_csound_prsdata(csound, "Before do_macro_arg", yyscanner); */ do_macro_arg(csound, yytext, yyscanner); //print_csound_prsdata(csound,"After do_macro_arg", yyscanner); BEGIN(INITIAL); } {MACRO} { csound->DebugMsg(csound,"Define macro %s\n", yytext); /* print_csound_prsdata(csound,"Before do_macro", yyscanner); */ do_macro(csound, yytext, yyscanner); //print_csound_prsdata(csound,"After do_macro", yyscanner); BEGIN(INITIAL); } . { csound->Message(csound, Str("Unexpected character %c(%.2x) line %d\n"), yytext[0], yytext[0], csound_prsget_lineno(yyscanner)); csound->LongJmp(csound, 1); } {UNDEF} { if (PARM->isString != 1) BEGIN(umacro); else corfile_puts(csound, yytext, PARM->cf); } [ \t]* /* eat the whitespace */ {MACRO} { csound->DebugMsg(csound,"Undefine macro %s\n", yytext); do_umacro(csound, yytext, yyscanner); BEGIN(INITIAL); } {IFDEF} { if (PARM->isString != 1) { PARM->isIfndef = (yytext[3] == 'n'); /* #ifdef or #ifndef */ csound_prsset_lineno(1+csound_prsget_lineno(yyscanner), yyscanner); corfile_putc(csound, '\n', PARM->cf); csound_prs_line(PARM->cf, yyscanner); BEGIN(ifdef); } else { corfile_puts(csound, yytext, PARM->cf); } } [ \t]* /* eat the whitespace */ {IDENT} { do_ifdef(csound, yytext, yyscanner); BEGIN(INITIAL); } {ELSE} { if (PARM->isString != 1) { if (UNLIKELY(PARM->ifdefStack == NULL)) { csound->Message(csound, Str("#else without #if\n")); csound->LongJmp(csound, 1); } else if (UNLIKELY(PARM->ifdefStack->isElse)) { csound->Message(csound, Str("#else after #else\n")); csound->LongJmp(csound, 1); } PARM->ifdefStack->isElse = 1; csound_prsset_lineno(1+csound_prsget_lineno(yyscanner), yyscanner); corfile_putc(csound, '\n', PARM->cf); csound_prs_line(PARM->cf, yyscanner); do_ifdef_skip_code(csound, yyscanner); } else { corfile_puts(csound, yytext, PARM->cf); } } {END} { if (PARM->isString != 1) { IFDEFSTACK *pp = PARM->ifdefStack; if (UNLIKELY(pp == NULL)) { csound->Message(csound, Str("Unmatched #end\n")); csound->LongJmp(csound, 1); } PARM->ifdefStack = pp->prv; csound_prsset_lineno(1+csound_prsget_lineno(yyscanner), yyscanner); corfile_putc(csound, '\n', PARM->cf); csound_prs_line(PARM->cf, yyscanner); mfree(csound, pp); } else { corfile_puts(csound, yytext, PARM->cf); } } {NM} { corfile_putc(csound, yytext[0], PARM->cf); if (!PARM->isString) BEGIN(lname); } [ \t]* /* eat the whitespace */ {IDENT} { corfile_putc(csound, ' ', PARM->cf); corfile_puts(csound, yytext, PARM->cf); BEGIN(INITIAL); } "{" { int c, i; PARM->repeat_index++; if (UNLIKELY(PARM->repeat_index >= RPTDEPTH)) csound->Die(csound, Str("Loops are nested too deeply")); PARM->repeat_mm_n[PARM->repeat_index] = (MACRO*)csound->Malloc(csound, sizeof(MACRO)); if (UNLIKELY(PARM->repeat_mm_n[PARM->repeat_index] == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } PARM->repeat_cnt_n[PARM->repeat_index] = 0; do { c = input(yyscanner); } while (isblank(c)); if (c=='$') { // macro to yield count char buf[256]; int i=0; MACRO* mm; //printf("*** macro count\n"); while (!isblank(c=input(yyscanner)) && c!='.') { buf[i++] = c; } if (c=='.') c = input(yyscanner); buf[i] = '\0'; //printf("*** lookup macro %s\n", buf); if ((mm = find_definition(PARM->macros, buf))==NULL) { csound->Message(csound,Str("Undefined macro: '%s'"), yytext); //csound->LongJmp(csound, 1); corfile_puts(csound, "$error", PARM->cf); PARM->repeat_cnt_n[PARM->repeat_index] = 0; } else PARM->repeat_cnt_n[PARM->repeat_index] = atoi(mm->body); } else { while (isdigit(c)) { PARM->repeat_cnt_n[PARM->repeat_index] = 10 * PARM->repeat_cnt_n[PARM->repeat_index] + c - '0'; c = input(yyscanner); } } if (UNLIKELY(PARM->repeat_cnt_n[PARM->repeat_index] <= 0 || !isspace(c))) csound->Die(csound, Str("{: invalid repeat count")); if (PARM->repeat_index > 1) { char st[41]; int j; for (j = 0; j < PARM->repeat_index; j++) { st[j] = ' '; st[j+1] = '\0'; } if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, Str("%s Nested LOOP=%d Level:%d\n"), st, PARM->repeat_cnt_n[PARM->repeat_index], PARM->repeat_index); } else { if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, Str("External LOOP=%d Level:%d\n"), PARM->repeat_cnt_n[PARM->repeat_index], PARM->repeat_index); } while (isblank(c)) { c = input(yyscanner); } for (i = 0; isNameChar(c, i) && i < (NAMELEN-1); i++) { PARM->repeat_name_n[PARM->repeat_index][i] = c; c = input(yyscanner); } PARM->repeat_name_n[PARM->repeat_index][i] = '\0'; unput(c); /* Define macro for counter */ PARM->repeat_mm_n[PARM->repeat_index]->name = csound->Malloc(csound, strlen(PARM->repeat_name_n[PARM->repeat_index])+1); if (UNLIKELY(PARM->repeat_mm_n[PARM->repeat_index]->name==NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } strcpy(PARM->repeat_mm_n[PARM->repeat_index]->name, PARM->repeat_name_n[PARM->repeat_index]); PARM->repeat_mm_n[PARM->repeat_index]->acnt = -1; PARM->repeat_mm_n[PARM->repeat_index]->body = csound->Calloc(csound, 16); // ensure nulls PARM->repeat_mm_n[PARM->repeat_index]->body[0] = '0'; PARM->repeat_indx[PARM->repeat_index] = 0; csound->DebugMsg(csound,"csound_prs(%d): repeat %s zero %p\n", __LINE__, PARM->repeat_name_n[PARM->repeat_index], PARM->repeat_mm_n[PARM->repeat_index]->body); PARM->repeat_mm_n[PARM->repeat_index]->next = PARM->macros; PARM->macros = PARM->repeat_mm_n[PARM->repeat_index]; while (input(yyscanner)!='\n') {} PARM->cf_stack[PARM->repeat_index] = PARM->cf; PARM->cf = corfile_create_w(csound); } "}" { int temp; CORFIL *bdy = PARM->cf; if (UNLIKELY((temp=PARM->repeat_cnt_n[PARM->repeat_index])==0)) { csound->Message(csound, Str("unmatched } in score\n")); csound->LongJmp(csound, 1); } corfile_puts(csound, "#loop", PARM->cf); corfile_putc(csound, '\0', PARM->cf); corfile_putc(csound, '\0', PARM->cf); PARM->cf = PARM->cf_stack[PARM->repeat_index]; //printf("****Repeat body\n>>>%s<<<\n", bdy->body); PARM->repeat_mm_n[PARM->repeat_index]->acnt = 0; /* uninhibit */ if (UNLIKELY(PARM->macro_stack_ptr >= PARM->macro_stack_size )) { PARM->alt_stack = (MACRON*)csound->ReAlloc(csound, PARM->alt_stack, sizeof(MACRON)*(PARM->macro_stack_size+=10)); if (UNLIKELY(PARM->alt_stack == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } } csound->DebugMsg(csound,"csound_ps(%d): stacking line %d at %d\n", __LINE__, csound_prsget_lineno(yyscanner),PARM->macro_stack_ptr); PARM->alt_stack[PARM->macro_stack_ptr].n = 0; PARM->alt_stack[PARM->macro_stack_ptr].line = csound_prsget_lineno(yyscanner); PARM->alt_stack[PARM->macro_stack_ptr++].s = NULL; PARM->depth++; csound_prspush_buffer_state(YY_CURRENT_BUFFER, yyscanner); csound_prs_scan_string(bdy->body, yyscanner); PARM->cf_stack[PARM->repeat_index] = bdy; } {LOOP} { //printf("#loop found\n"); yypop_buffer_state(yyscanner); PARM->depth--; PARM->llocn = PARM->locn; PARM->locn = make_location(PARM); /* printf("Loop structures: count = %d, name = %s, indx = %d\n", */ /* PARM->repeat_cnt_n[PARM->repeat_index], */ /* PARM->repeat_name_n[PARM->repeat_index], */ /* PARM->repeat_indx[PARM->repeat_index]); */ if (++PARM->repeat_indx[PARM->repeat_index] != PARM->repeat_cnt_n[PARM->repeat_index]) { snprintf(PARM->repeat_mm_n[PARM->repeat_index]->body, 16, "%d", PARM->repeat_indx[PARM->repeat_index]); //printf(">>%s<<\n", PARM->cf_stack[PARM->repeat_index]->body); PARM->depth++; csound_prspush_buffer_state(YY_CURRENT_BUFFER, yyscanner); csound_prs_scan_string(PARM->cf_stack[PARM->repeat_index]->body, yyscanner); } else { //printf("*** end loop\n"); //printf(">>%s<<\n", PARM->cf->body); corfile_rm(csound, &PARM->cf_stack[PARM->repeat_index]); PARM->repeat_index--; } } {ROP} { if (PARM->isString) corfile_puts(csound, yytext, PARM->cf); else { int c, i; char buff[120]; corfile_putc(csound, 's', PARM->cf); corfile_putc(csound, '\n', PARM->cf); //printf("r detected\n"); if (UNLIKELY(PARM->in_repeat_sect)) csound->Die(csound, Str("Section loops cannot be nested")); PARM->repeat_sect_cnt = 0; PARM->in_repeat_sect = 1; /* Mark as recording */ do { c = input(yyscanner); } while (isblank(c)); while (isdigit(c)) { PARM->repeat_sect_cnt = 10 * PARM->repeat_sect_cnt + c - '0'; c = input(yyscanner); } if (UNLIKELY(PARM->repeat_sect_cnt <= 0 || !isspace(c))) { csound->Message(csound, Str("r: invalid repeat count")); csound->LongJmp(csound, 1); } if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, Str("r LOOP=%d\n"), PARM->repeat_sect_cnt); while (isblank(c)) { c = input(yyscanner); } if (!isalpha(c)) { //no macro //printf("No macro\n"); PARM->repeat_sect_mm =NULL; } else { for (i = 0; isNameChar(c, i) && i < (NAMELEN-1); i++) { buff[i] = c; c = input(yyscanner); } PARM->repeat_sect_mm = (MACRO*)csound->Malloc(csound, sizeof(MACRO)); if (UNLIKELY(PARM->repeat_sect_mm== NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } buff[i] = '\0'; printf("macro name %s\n", buff); /* Define macro for counter */ PARM->repeat_sect_mm->name = cs_strdup(csound, buff); PARM->repeat_sect_mm->acnt = -1; /* inhibit */ PARM->repeat_sect_mm->body = csound->Calloc(csound, 16); PARM->repeat_sect_mm->body[0] = '0'; //csound->DebugMsg(csound,"repeat %s zero %s\n", // buff, PARM->repeat_sect_mm->body); PARM->repeat_sect_mm->next = PARM->macros; /* add to chain */ PARM->macros = PARM->repeat_sect_mm; } unput(c); PARM->repeat_sect_line = PARM->line; PARM->repeat_sect_index = 0; while (input(yyscanner)!='\n') {} PARM->repeat_sect_cf = PARM->cf; PARM->cf = corfile_create_w(csound); } } {SEND} { if (!PARM->isString) { int op = yytext[strlen(yytext)-1]; //printf("section end %d %c\n%s\n", // PARM->in_repeat_sect, op, PARM->cf->body); if (PARM->in_repeat_sect==1) { corfile_putc(csound, 's', PARM->cf); while (1) { int c = input(yyscanner); if (c=='\n') break; if (!isspace(c)&&!isdigit(c)) { unput(c); break;} corfile_putc(csound, c, PARM->cf); } corfile_putc(csound, '\n', PARM->cf); unput(op); PARM->in_repeat_sect=2; //printf("****Repeat body\n>>>%s<<<\n", PARM->cf->body); if (PARM->repeat_sect_mm) PARM->repeat_sect_mm->acnt = 0; /* uninhibit */ csound_prspush_buffer_state(YY_CURRENT_BUFFER, yyscanner); csound_prs_scan_string(PARM->cf->body, yyscanner); { CORFIL *tmp = PARM->cf; PARM->cf = PARM->repeat_sect_cf; PARM->repeat_sect_cf = tmp; } PARM->line = PARM->repeat_sect_line; } else if (PARM->in_repeat_sect==2) { corfile_putc(csound, 's', PARM->cf); while (1) { int c = input(yyscanner); if (c=='\n') break; corfile_putc(csound, c, PARM->cf); } corfile_putc(csound, '\n', PARM->cf); yypop_buffer_state(yyscanner); PARM->llocn = PARM->locn; PARM->locn = make_location(PARM); //printf("repeat section %d %d\n", // PARM->repeat_sect_index,PARM->repeat_sect_cnt); PARM->repeat_sect_index++; if (PARM->repeat_sect_indexrepeat_sect_cnt) { if (PARM->repeat_sect_mm) { snprintf(PARM->repeat_sect_mm->body, 16, "%d", PARM->repeat_sect_index); //printf("%s now %s\n", // PARM->repeat_sect_mm->name,PARM->repeat_sect_mm->body); } csound_prspush_buffer_state(YY_CURRENT_BUFFER, yyscanner); csound_prs_scan_string(PARM->repeat_sect_cf->body, yyscanner); PARM->line = PARM->repeat_sect_line; } else { /* corfile_putc(csound, op, PARM->cf); */ /* corfile_putc(csound, '\n', PARM->cf); */ //printf("end of loop\n"); PARM->in_repeat_sect=0; corfile_rm(csound, &PARM->repeat_sect_cf); //csound->Free(csound, PARM->repeat_sect_mm->body); //PARM->repeat_sect_mm->body = NULL; } } else { corfile_putc(csound, op, PARM->cf); /* while (1) { */ /* int c = input(yyscanner); */ /* printf("**copy %.2x(%c)\n", c, c); */ /* corfile_putc(csound, c, PARM->cf); */ /* if (c=='\n') break; */ /* if (c=='\0') break; */ /* } */ } } else corfile_puts(csound, yytext, PARM->cf); } . { corfile_putc(csound, yytext[0], PARM->cf); } %% static void comment(yyscan_t yyscanner) /* Skip until nextline */ { char c; struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; while ((c = input(yyscanner)) != '\n' && c != '\r') { /* skip */ if (UNLIKELY((int)c == EOF)) { YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; return; } } if (c == '\r' && (c = input(yyscanner)) != '\n') { if (LIKELY((int)c != EOF)) unput(c); else YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } csound_prsset_lineno(1+csound_prsget_lineno(yyscanner),yyscanner); } static void do_comment(yyscan_t yyscanner) /* Skip until * and / chars */ { int c; struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; TOP: c = input(yyscanner); switch (c) { NL: case '\n': csound_prsset_lineno(1+csound_prsget_lineno(yyscanner),yyscanner); goto TOP; case '*': AST: c = input(yyscanner); switch (c) { case '*': goto AST; case '\n': goto NL; case '/': return; case EOF: goto ERR; default: goto TOP; } case EOF: ERR: YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; return; default: goto TOP; } } static void do_include(CSOUND *csound, int term, yyscan_t yyscanner) { char buffer[100]; int p=0; int c; CORFIL *cf; struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; while ((c=input(yyscanner))!=term) { if (c=='\n' || c==EOF) { csound->Warning(csound, Str("Ill formed #include ignored")); return; } buffer[p] = c; p++; } buffer[p] = '\0'; while ((c=input(yyscanner))!='\n'); if (UNLIKELY(PARM->depth++>=1024)) { csound->Die(csound, Str("Includes nested too deeply")); } csound_prsset_lineno(1+csound_prsget_lineno(yyscanner), yyscanner); csound->DebugMsg(csound,"line %d at end of #include line\n", csound_prsget_lineno(yyscanner)); { uint8_t n = file_to_int(csound, buffer); //char bb[128]; PARM->lstack[PARM->depth] = n; //sprintf(bb, "#source %llu\n", PARM->locn = make_location(PARM)); PARM->llocn = PARM->locn; #ifdef SCORE_PARSER //corfile_puts(csound, bb, PARM->cf); #endif } csound->DebugMsg(csound,"reading included file \"%s\"\n", buffer); if (UNLIKELY(isDir(buffer))) csound->Warning(csound, Str("%s is a directory; not including"), buffer); cf = copy_to_corefile(csound, buffer, "INCDIR", 0); if (UNLIKELY(cf == NULL)) csound->Die(csound, Str("Cannot open #include'd file %s\n"), buffer); if (UNLIKELY(PARM->macro_stack_ptr >= PARM->macro_stack_size )) { PARM->alt_stack = (MACRON*) csound->ReAlloc(csound, PARM->alt_stack, sizeof(MACRON)*(PARM->macro_stack_size+=10)); if (UNLIKELY(PARM->alt_stack == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } /* csound->DebugMsg(csound, "alt_stack now %d long, \n", */ /* PARM->macro_stack_size); */ } csound->DebugMsg(csound,"csound_prs(%d): stacking line %d at %d\n", __LINE__, csound_prsget_lineno(yyscanner),PARM->macro_stack_ptr); PARM->alt_stack[PARM->macro_stack_ptr].n = 0; PARM->alt_stack[PARM->macro_stack_ptr].line = csound_prsget_lineno(yyscanner); PARM->alt_stack[PARM->macro_stack_ptr++].s = NULL; csound_prspush_buffer_state(YY_CURRENT_BUFFER, yyscanner); csound_prs_scan_string(cf->body, yyscanner); corfile_rm(csound, &cf); csound->DebugMsg(csound,"Set line number to 1\n"); csound_prsset_lineno(1, yyscanner); } static void do_macro_arg(CSOUND *csound, char *name0, yyscan_t yyscanner) { MACRO *mm = (MACRO*) csound->Malloc(csound, sizeof(MACRO)); int arg = 0, i, c; int size = 100; int mlen = 40; char *q = name0; char *mname = malloc(mlen); if (UNLIKELY(mm == NULL||mname == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } mm->margs = MARGS; /* Initial size */ mm->name = (char*)csound->Malloc(csound, strlen(name0) + 1); if (UNLIKELY(mm->name == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } strcpy(mm->name, name0); do { i = 0; q = name0; mname[i++] = '`'; while ((c = *q++)) { mname[i++] = c; if (UNLIKELY(i==mlen)) mname = (char *)realloc(mname, mlen+=40); if (UNLIKELY(mname == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } } mname[i++] = '`'; if (UNLIKELY(i==mlen)) { mname = (char *)realloc(mname, mlen+=40); if (UNLIKELY(mname == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } } mname[i++] = '`'; if (UNLIKELY(i==mlen)) { mname = (char *)realloc(mname, mlen+=40); if (UNLIKELY(mname == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } } while (isspace((c = input(yyscanner)))); while (isNameChar(c, i)) { mname[i++] = c; if (UNLIKELY(i==mlen)) { mname = (char *)realloc(mname, mlen+=40); if (UNLIKELY(mname == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } } c = input(yyscanner); } mname[i] = '\0'; mm->arg[arg] = csound->Malloc(csound, i + 1); if (UNLIKELY(mm->arg[arg] == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } strcpy(mm->arg[arg++], mname); if (UNLIKELY(arg >= mm->margs)) { mm = (MACRO*) csound->ReAlloc(csound, mm, sizeof(MACRO) + mm->margs * sizeof(char*)); if (UNLIKELY(mm == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } mm->margs += MARGS; } while (isspace(c)) c = input(yyscanner); } while (c == '\'' || c == '#'); if (UNLIKELY(c != ')')) { csound->Message(csound, Str("macro error\n")); } free(mname); c = input(yyscanner); while (c!='#') { if (UNLIKELY(c==EOF)) csound->Die(csound, Str("define macro runaway\n")); else if (c==';') { while ((c=input(yyscanner))!= '\n') if (UNLIKELY(c==EOF)) { csound->Die(csound, Str("define macro runaway\n")); } } else if (c=='/') { if ((c=input(yyscanner))=='/') { while ((c=input(yyscanner))!= '\n') if (UNLIKELY(c==EOF)) csound->Die(csound, Str("define macro runaway\n")); } else if (c=='*') { while ((c=input(yyscanner))!='*') { again: if (UNLIKELY(c==EOF)) csound->Die(csound, Str("define macro runaway\n")); } if ((c=input(yyscanner))!='/') goto again; } } else if (UNLIKELY(!isspace(c))) csound->Die(csound, Str("define macro unexpected character %c(0x%.2x) awaiting #\n"), c, c); c = input(yyscanner); /* skip to start of body */ } mm->acnt = arg; i = 0; mm->body = (char*) csound->Malloc(csound, 100); if (UNLIKELY(mm->body == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } while ((c = input(yyscanner)) != '#') { /* read body */ if (UNLIKELY(c == EOF)) csound->Die(csound, Str("define macro with args: unexpected EOF")); if (c=='$') { /* munge macro name? */ int n = strlen(name0)+4; if (UNLIKELY(i+n >= size)) { mm->body = csound->ReAlloc(csound, mm->body, size += 100); if (UNLIKELY(mm->body == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } } mm->body[i] = '$'; mm->body[i+1] = '`'; strcpy(&mm->body[i+2], name0); mm->body[i + n - 2] = '`'; mm->body[i + n - 1] = '`'; i+=n; continue; } mm->body[i++] = c=='\r'?'\n':c; if (UNLIKELY(i >= size)) { mm->body = csound->ReAlloc(csound, mm->body, size += 100); if (UNLIKELY(mm->body == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } } if (c == '\\') { /* allow escaped # */ mm->body[i++] = c = input(yyscanner); if (UNLIKELY(i >= size)) { mm->body = csound->ReAlloc(csound, mm->body, size += 100); if (UNLIKELY(mm->body == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } } } if (UNLIKELY(c == '\n' || c == '\r')) { csound_prsset_lineno(1+csound_prsget_lineno(yyscanner),yyscanner); corfile_putc(csound, '\n', PARM->cf); csound_prs_line(PARM->cf, yyscanner); } } mm->body[i] = '\0'; mm->next = PARM->macros; PARM->macros = mm; } static void do_macro(CSOUND *csound, char *name0, yyscan_t yyscanner) { MACRO *mm = (MACRO*) csound->Malloc(csound, sizeof(MACRO)); int i, c; int size = 100; if (UNLIKELY(mm == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } mm->margs = MARGS; /* Initial size */ csound->DebugMsg(csound,"Macro definition for %s\n", name0); mm->name = (char*)csound->Malloc(csound, strlen(name0) + 1); if (UNLIKELY(mm->name == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } strcpy(mm->name, name0); mm->acnt = 0; i = 0; while ((c = input(yyscanner)) != '#') { if (UNLIKELY(c==EOF)) csound->Die(csound, Str("define macro runaway\n")); else if (c==';') { while ((c=input(yyscanner))!= '\n') if (UNLIKELY(c==EOF)) { csound->Die(csound, Str("define macro runaway\n")); } } else if (c=='/') { if ((c=input(yyscanner))=='/') { while ((c=input(yyscanner))!= '\n') if (UNLIKELY(c==EOF)) csound->Die(csound, Str("define macro runaway\n")); } else if (c=='*') { while ((c=input(yyscanner))!='*') { again: if (UNLIKELY(c==EOF)) csound->Die(csound, Str("define macro runaway\n")); } if ((c=input(yyscanner))!='/') goto again; } } else if (UNLIKELY(!isspace(c))) csound->Die(csound, Str("define macro unexpected character %c(0x%.2x)" "awaiting #\n"), c, c); } mm->body = (char*) csound->Malloc(csound, 100); if (UNLIKELY(mm->body == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } while ((c = input(yyscanner)) != '#') { if (UNLIKELY(c == EOF || c==0)) csound->Die(csound, Str("define macro: unexpected EOF")); mm->body[i++] = c=='\r'?'\n':c; if (UNLIKELY(i >= size)) { mm->body = csound->ReAlloc(csound, mm->body, size += 100); if (UNLIKELY(mm->body == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } } if (c == '\\') { /* allow escaped # */ mm->body[i++] = c = input(yyscanner); if (UNLIKELY(i >= size)) { mm->body = csound->ReAlloc(csound, mm->body, size += 100); if (UNLIKELY(mm->body == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } } } if (UNLIKELY(c == '\n' || c == '\r')) { csound_prsset_lineno(1+csound_prsget_lineno(yyscanner),yyscanner); corfile_putc(csound, '\n', PARM->cf); csound_prs_line(PARM->cf, yyscanner); } } mm->body[i] = '\0'; csound->DebugMsg(csound,"Body #%s#\n", mm->body); mm->next = PARM->macros; PARM->macros = mm; } static void do_umacro(CSOUND *csound, char *name0, yyscan_t yyscanner) { int i,c; if (UNLIKELY(csound->oparms->msglevel)) csound->Message(csound,Str("macro %s undefined\n"), name0); csound->DebugMsg(csound, "macro %s undefined\n", name0); if (strcmp(name0, PARM->macros->name)==0) { MACRO *mm=PARM->macros->next; mfree(csound, PARM->macros->name); mfree(csound, PARM->macros->body); for (i=0; imacros->acnt; i++) mfree(csound, PARM->macros->arg[i]); mfree(csound, PARM->macros); PARM->macros = mm; } else { MACRO *mm = PARM->macros; MACRO *nn = mm->next; while (strcmp(name0, nn->name) != 0) { mm = nn; nn = nn->next; if (UNLIKELY(nn == NULL)) { csound->Message(csound, Str("Undefining undefined macro")); csound->LongJmp(csound, 1); } } mfree(csound, nn->name); mfree(csound, nn->body); for (i=0; iacnt; i++) mfree(csound, nn->arg[i]); mm->next = nn->next; mfree(csound, nn); } while ((c=input(yyscanner)) != '\n' && c != EOF && c != '\r'); /* ignore rest of line */ csound_prsset_lineno(1+csound_prsget_lineno(yyscanner),yyscanner); } static void do_ifdef(CSOUND *csound, char *name0, yyscan_t yyscanner) { int c; MACRO *mm; IFDEFSTACK *pp; pp = (IFDEFSTACK*) csound->Calloc(csound, sizeof(IFDEFSTACK)); if (UNLIKELY(pp == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } pp->prv = PARM->ifdefStack; pp->isDef = PARM->isIfndef; for (mm = PARM->macros; mm != NULL; mm = mm->next) { if (strcmp(name0, mm->name) == 0) { pp->isDef ^= (unsigned char) 1; break; } } PARM->ifdefStack = pp; pp->isSkip = pp->isDef ^ (unsigned char) 1; if (pp->isSkip) do_ifdef_skip_code(csound, yyscanner); else while ((c = input(yyscanner)) != '\n' && c != '\r' && c != EOF); } static void do_ifdef_skip_code(CSOUND *csound, yyscan_t yyscanner) { int i, c, nested_ifdef = 0; char buf[8]; IFDEFSTACK *pp; /* buf = (char*)malloc(8*sizeof(char)); */ /* if (UNLIKELY(buf == NULL)) { */ /* csound->Message(csound, Str("Memory exhausted")); */ /* csound->LongJmp(csound, 1); */ /* } */ pp = PARM->ifdefStack; c = input(yyscanner); for (;;) { while (c!='\n' && c!= '\r') { if (UNLIKELY(c == EOF)) { csound->Message(csound, Str("Unmatched #if%sdef\n"), PARM->isIfndef ? "n" : ""); csound->LongJmp(csound, 1); } c = input(yyscanner); } csound_prsset_lineno(1+csound_prsget_lineno(yyscanner), yyscanner); corfile_putc(csound, '\n', PARM->cf); csound_prs_line(PARM->cf, yyscanner); while (isblank(c = input(yyscanner))); /* eat the whitespace */ if (c == '#') { for (i=0; islower(c = input(yyscanner)) && i < 7; i++) buf[i] = c; buf[i] = '\0'; if (strcmp("end", buf) == 0 || strcmp("endif", buf) == 0) { if (nested_ifdef-- == 0) { PARM->ifdefStack = pp->prv; mfree(csound, pp); break; } } else if (strcmp("ifdef", buf) == 0 || strcmp("ifndef", buf) == 0) { nested_ifdef++; } else if (strcmp("else", buf) == 0 && nested_ifdef == 0) { if (UNLIKELY(pp->isElse)) { csound->Message(csound, Str("#else after #else\n")); csound->LongJmp(csound, 1); } pp->isElse = 1; break; } } } //free(buf); while (c != '\n' && c != EOF && c != '\r') c = input(yyscanner); } static void delete_macros(CSOUND *csound, yyscan_t yyscanner) { MACRO * qq = PARM->macros; if (qq) { MACRO *mm = qq; while (mm) { csound->Free(csound, mm->body); csound->Free(csound, mm->name); qq = mm->next; csound->Free(csound, mm); mm = qq; } } } void cs_init_smacros(CSOUND *csound, PRS_PARM *qq, NAMES *nn) { while (nn) { char *s = nn->mac; char *p = strchr(s, '='); char *mname; MACRO *mm; if (p == NULL) p = s + strlen(s); if (UNLIKELY(csound->oparms->msglevel & 7)) csound->Message(csound, Str("Macro definition for %*s\n"), (int) (p - s), s); s = strchr(s, ':') + 1; /* skip arg bit */ if (UNLIKELY(s == NULL || s >= p)) { csound->Die(csound, Str("Invalid macro name for --smacro")); } mname = (char*) csound->Malloc(csound, (p - s) + 1); if (UNLIKELY(mname == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } strncpy(mname, s, p - s); mname[p - s] = '\0'; /* check if macro is already defined */ for (mm = qq->macros; mm != NULL; mm = mm->next) { if (strcmp(mm->name, mname) == 0) break; } if (mm == NULL) { mm = (MACRO*) csound->Calloc(csound, sizeof(MACRO)); if (UNLIKELY(mm == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } mm->name = mname; mm->next = qq->macros; qq->macros = mm; } else mfree(csound, mname); mm->margs = MARGS; /* Initial size */ mm->acnt = 0; if (*p != '\0') p++; mm->body = (char*) csound->Malloc(csound, strlen(p) + 1); if (UNLIKELY(mm->body == NULL)) { csound->Message(csound, Str("Memory exhausted")); csound->LongJmp(csound, 1); } strcpy(mm->body, p); nn = nn->next; } } static void csound_prs_line(CORFIL* cf, void *yyscanner) { int n = csound_prsget_lineno(yyscanner); //printf("line number %d\n", n); /* This assumes that the initial line was not written with this system */ if (cf->p>0 && cf->body[cf->p-1]=='\n') { uint64_t locn = PARM->locn; #if 0 uint64_t llocn = PARM->llocn; if (locn != llocn) { //char bb[80]; //sprintf(bb, "#source %llu\n", locn); //corfile_puts(bb, cf); } #endif PARM->llocn = locn; #ifdef SCORE_PARSER //if (n!=PARM->line+1) { //char bb[80]; //sprintf(bb, "#line %d\n", n); //printf("#line %d\n", n); //corfile_puts(bb, cf); //} #endif } PARM->line = n; } static MACRO *find_definition(MACRO *mmo, char *s) { MACRO *mm = mmo; if (s[strlen(s)-1]=='.') s[strlen(s)-1]='\0'; else if (s[strlen(s)-2]=='.' && s[strlen(s)-1]=='(') { s[strlen(s)-2] = '('; s[strlen(s)-1] = '\0'; } //printf("****Looking for %s\n", s); while (mm != NULL) { /* Find the definition */ //printf("looking at %p(%s) body #%s#\n", mm, mm->name, mm->body); if (!(strcmp(s, mm->name))) break; mm = mm->next; } if (mm == NULL) { mm = mmo; s++; /* skip _ */ looking: while (*s++!='`') { if (*s=='\0') return NULL; } if (*s++!='`') { s--; goto looking; } //printf("now try looking for %s\n", s); while (mm != NULL) { /* Find the definition */ //printf("looking at %p(%s) body #%s#\n", mm, mm->name, mm->body); if (!(strcmp(s, mm->name))) break; mm = mm->next; } } //if (mm) printf("found body #%s#%c\n****\n", mm->body, mm->acnt?'X':' '); return mm; } #if 0 static void print_csound_prsdata(CSOUND *csound, char *mesg, void *yyscanner) { struct yyguts_t *yyg =(struct yyguts_t*)yyscanner; csound->DebugMsg(csound,"********* %s extra data ************", mesg); csound->DebugMsg(csound,"yyscanner = %p", yyscanner); csound->DebugMsg(csound,"yyextra_r = %p, yyin_r = %p, yyout_r = %p," " yy_buffer_stack_top = %d", yyg->yyextra_r, yyg->yyin_r,yyg->yyout_r, yyg->yy_buffer_stack_top); csound->DebugMsg(csound,"yy_buffer_stack_max = %d1, yy_buffer_stack = %p, " "yy_hold_char = %d '%c'", yyg->yy_buffer_stack_max, yyg->yy_buffer_stack, yyg->yy_hold_char, yyg->yy_hold_char); csound->DebugMsg(csound,"yy_n_chars = %d, yyleng_r = %d, yy_c_buf_p = %p %c", yyg->yy_n_chars, yyg->yyleng_r, yyg->yy_c_buf_p, *yyg->yy_c_buf_p); csound->DebugMsg(csound,"yy_init = %d, yy_start = %d, " "yy_did_buffer_switch_on_eof = %d", yyg->yy_init, yyg->yy_start, yyg->yy_did_buffer_switch_on_eof); csound->DebugMsg(csound,"yy_start_stack_ptr = %d," " yy_start_stack_depth = %d, yy_start_stack = %p", yyg->yy_start_stack_ptr, yyg->yy_start_stack_depth, yyg->yy_start_stack); csound->DebugMsg(csound,"yy_last_accepting_state = %d, " "yy_last_accepting_cpos = %p %c", yyg->yy_last_accepting_state, yyg->yy_last_accepting_cpos, *yyg->yy_last_accepting_cpos); csound->DebugMsg(csound,"yylineno_r = %d, yy_flex_debug_r = %d, " "yytext_r = %p \"%s\", yy_more_flag = %d, yy_more_len = %d", yyg->yylineno_r, yyg->yy_flex_debug_r, yyg->yytext_r, yyg->yytext_r, yyg->yy_more_flag, yyg->yy_more_len); { PRS_PARM* pp = yyg->yyextra_r; printf("macros = %p, isIfndef = %d, isString = %d, line - %d loc = %d\n", pp->macros, pp->isIfndef, pp->isString, pp->line, pp->locn); printf ("llocn = %d dept=%d\n", pp->llocn, pp->depth); } csound->DebugMsg(csound,"*********\n"); } #endif csound-6.10.0/Engine/csound_sco.lex000066400000000000000000000150031321653344700171560ustar00rootroot00000000000000%{ /* csound_sco.lex: Copyright (C) 2013 March John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include "csoundCore.h" #include "score_param.h" #include "csound_scoparse.h" #define YYSTYPE MYFLT #define YYLTYPE SCOTOKEN #define YY_DECL int yylex (YYLTYPE *lvalp, CSOUND *csound, yyscan_t yyscanner) #include "corfile.h" YYLTYPE *yylval_param; YYLTYPE *yylloc_param; static SCOTOKEN *make_string(CSOUND *, char *); static SCOTOKEN *make_int(CSOUND *, int); static SCOTOKEN *make_num(CSOUND *, double); extern void *fopen_path(CSOUND *, FILE **, char *, char *, char *, int); #define YY_EXTRA_TYPE SCORE_PARM * #define PARM yyget_extra(yyscanner) #define YY_USER_INIT struct yyguts_t; static SCOTOKEN *do_at(CSOUND *, int, struct yyguts_t*); %} %option reentrant %option bison-bridge %option bison-locations %option prefix="csound_sco" %option outfile="Engine/csound_scolex.c" %option stdout STRCONST \"(\\.|[^\"])*\" STRCONSTe \"(\\.|[^\"])*$ INTGR -?[0-9]+ NUMBER -?[0-9]+\.?[0-9]*([eE][-+]?[0-9]+)?|\.[0-9]+([eE][-+]?[0-9]+)?|0[xX][0-9a-fA-F]+ WHITE [ \t]+ OPTWHITE [ \t]* CONT \\[ \t]*(;.*)?\n LINE "#line" FILE "#source" EXIT "#exit" FNAME [a-zA-Z0-9/:.+-_]+ NPX "np^"${INTGR} PPX "pp^"${INTGR} CNPX "NP^"${INTGR} CPPX "PP^"${INTGR} %x line %x src %% "\r" { } /* EATUP THIS PART OF WINDOWS NEWLINE */ {CONT} { csound_scoset_lineno(1+csound_scoget_lineno(yyscanner), yyscanner); } "\n" { int n = csound_scoget_lineno(yyscanner)+1; csound_scoset_lineno(n, yyscanner); return NEWLINE; } ${NPX} { return T_NP; } ${PPX} { return T_PP; } ${CNPX} { return T_CNP; } ${CPPX} { return T_CPP; } "a" { return yytext[0];} "b" { return yytext[0];} "e" { return yytext[0];} "f" { return yytext[0];} "i" { return yytext[0];} "m" { return yytext[0];} "n" { return yytext[0];} "q" { return yytext[0];} "r" { return yytext[0];} "s" { return yytext[0];} "t" { return yytext[0];} "v" { return yytext[0];} "w" { return yytext[0];} "x" { return yytext[0];} "y" { return yytext[0];} "z" { return yytext[0];} "(" { return '('; } ")" { return ')'; } "[" { return '['; } "]" { return ']'; } "{" { return '}'; } "}" { return '}'; } "+" { return '+'; } "-" { return '-'; } "*" { return '*'; } "/" { return '/'; } "%" { return '%'; } "\^" { return '^'; } "!" { return '!'; } ">" { return '>'; } "<" { return '<'; } "|" { return '|'; } "&" { return '&'; } "#" { return '#'; } "~" { return '~'; } "." { return '.'; } "@@"{OPTWHITE}{INTGR} { lvalp = do_at(csound, 1, yyg); return INTEGER_TOKEN; } "@"{OPTWHITE}{INTGR} { lvalp = do_at(csound, 0, yyg); return INTEGER_TOKEN; } {STRCONST} { lvalp = make_string(csound, yytext); return (STRING_TOKEN); } {STRCONSTe} { lvalp = make_string(csound, yytext); csound->Message(csound, Str("unterminated string found on line %d >>%s<<\n"), csound_scoget_lineno(yyscanner), yytext); return (STRING_TOKEN); } {INTGR} { lvalp = make_int(csound, atoi(yytext)); return (INTEGER_TOKEN); } {NUMBER} { lvalp = make_num(csound, atof(yytext)); return (NUMBER_TOKEN); } {WHITE} { } {LINE} { BEGIN(line); } [ \t]* /* eat the whitespace */ {INTGR} { csound_scoset_lineno(atoi(yytext), yyscanner); printf("set line to %d (%s)\n", csound_scoget_lineno(yyscanner), yytext); } "\n" {BEGIN(INITIAL);} {FILE} { BEGIN(src); } [ \t]* /* eat the whitespace */ {FNAME} { PARM->locn = atoi(yytext); } "\n" { BEGIN(INITIAL); } {EXIT} { yyterminate(); } <> { yyterminate(); } . { fprintf(stderr, "unknown character %c(%.2x)\n", yytext[0], yytext[0]); } %% static SCOTOKEN *make_string(CSOUND *csound, char *s) { SCOTOKEN *ans = (SCOTOKEN*)mcalloc(csound, sizeof(SCOTOKEN)); ans->type = STRING_TOKEN; ans->strbuff = strdup(s); return ans; } static SCOTOKEN *make_int(CSOUND *csound, int i) { SCOTOKEN *ans = (SCOTOKEN*)mcalloc(csound, sizeof(SCOTOKEN)); ans->type = INTEGER_TOKEN; ans->ival = i; return ans; } static SCOTOKEN *make_num(CSOUND *csound, double f) { SCOTOKEN *ans = (SCOTOKEN*)mcalloc(csound, sizeof(SCOTOKEN)); ans->type = NUMBER_TOKEN; ans->fval = (MYFLT)f; return ans; } static SCOTOKEN *do_at(CSOUND *csound, int k, struct yyguts_t *yyg) { SCOTOKEN *ans = (SCOTOKEN*)mcalloc(csound, sizeof(SCOTOKEN)); int n, i = 1; char *s = yytext; while (*s=='@') s++; n = atoi(s); while (i<=n-k && i< 0x4000000) i <<= 1; ans->type = INTEGER_TOKEN; ans->ival = i; return ans; } char *csound_scoget_current_pointer(void *yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; return yyg->yy_c_buf_p; } int csound_scoget_locn(void *yyscanner) { // struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; return PARM->locn; } csound-6.10.0/Engine/csound_sco.y000066400000000000000000000202171321653344700166410ustar00rootroot00000000000000/* csound_sco.y: Copyright (C) 2013 John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ %{ #ifndef NULL #define NULL 0L #endif #include "csoundCore.h" #include #include #include #include #include "score_param.h" extern void csound_scoerror(SCORE_PARM *, void *, CSOUND *, ScoreTree *, const char*); extern int csound_scolex(ScoreTree**, CSOUND *, void *); #define LINE csound_scoget_lineno(scanner) #define LOCN csound_scoget_locn(scanner) extern int csound_scoget_locn(void *); extern int csound_scoget_lineno(void *); static ScoreTree* makesco(CSOUND *csound, int op, ListItem* car, ScoreTree* cdr, int, int); static ScoreTree* makesco1(CSOUND *csound, ScoreTree* car, ScoreTree* cdr); static ListItem* makelist(CSOUND *csound, double car, ListItem* cdr); %} %pure_parser %parse-param {SCORE_PARM *parm} %parse-param {void *scanner} %lex-param { CSOUND * csound } %lex-param {yyscan_t *scanner} %union { int oper; double val; ScoreTree *t; ListItem *l; } %type opcode %type arg exp term fac constant %type scoline scolines statement %type arglist %token NEWLINE %token T_ERROR %token STRING_TOKEN %token INTEGER_TOKEN %token NUMBER_TOKEN %start scofile %left S_AND S_OR %left '|' %left '&' %left S_LT S_GT S_LEQ S_GEQ S_EQ S_NEQ %left S_BITSHIFT_LEFT S_BITSHIFT_RIGHT %left '+' '-' %left '*' '/' '%' %left '^' %left '#' %right '~' %right S_UNOT %right S_UMINUS %token T_HIGHEST %pure-parser %error-verbose %token T_NP %token T_PP %token T_CNP %token T_CPP %pure_parser /* %error-verbose */ %parse-param { CSOUND * csound } %parse-param { ScoreTree * scoTree } %% scofile : scolines { printf("result %p\n", $1); *scoTree = *$1;} ; scoline : statement { $$ = $1; } | '{' scolines '}' NEWLINE { $$ = $2; } ; scolines : scoline scolines { $$ = makesco1(csound, $1, $2); } | { $$ = NULL; } ; statement : opcode arglist NEWLINE { printf("op=%c\n", $1); $$ = makesco(csound, $1, NULL, NULL, LINE,LOCN); } ; opcode : 'i' { $$ = 'i'; } | 'f' { $$ = 'f'; } | 'a' { $$ = 'a'; } | 'e' { $$ = 'e'; } | 's' { $$ = 's'; } | 't' { $$ = 't'; } ; arglist : arg arglist { $$ = makelist(csound, $1, $2);} | { $$ = NULL; } ; arg : NUMBER_TOKEN { $$ = parm->fval;} | INTEGER_TOKEN { $$ = (MYFLT)parm->ival;} | STRING_TOKEN {} | '[' exp ']' { $$ = $2; } | T_NP { $$ = nan("1"); } | T_PP { $$ = nan("2"); } | T_CNP { $$ = nan("3"); } | T_CPP { $$ = nan("4"); } ; exp : exp '+' exp { $$ = $1 + $3; } | exp '+' error | exp '-' exp { $$ = $1 - $3; } | exp '-' error | '-' exp %prec S_UMINUS { $$ = - $2; } | '-' error { } | '+' exp %prec S_UMINUS { $$ = $2; } | '+' error { } | term { $$ = $1; } ; term : exp '*' exp { $$ = $1 * $3; } | exp '*' error | exp '/' exp { $$ = $1 / $3; } | exp '/' error | exp '^' exp { $$ = pow($1, $3); } | exp '^' error | exp '%' exp { $$ = (double)((int)$1 % (int)$3); } | exp '%' error | fac { $$ = $1; } ; fac : constant { $$ = $1; } | exp '|' exp { $$ = (int)$1 | (int)$3; } | exp '|' error | exp '&' exp { $$ = (int)$1 & (int)$3; } | exp '&' error | exp '#' exp { $$ = (int)$1 ^ (int)$3; } | exp '#' error | exp S_BITSHIFT_LEFT exp { $$ = (int)$1 << (int)$3; } | exp S_BITSHIFT_LEFT error | exp S_BITSHIFT_RIGHT exp { $$ = (int)$1 >> (int)$3; } | exp S_BITSHIFT_RIGHT error | '~' exp %prec S_UMINUS { $$ = ~(int)$2; } | '~' error { $$ = 0; } | '(' exp ')' { $$ = $2; } | '(' exp error { $$ = 0; } | '(' error { $$ = 0; } ; constant : NUMBER_TOKEN { $$ = parm->fval; } | INTEGER_TOKEN { $$ = (MYFLT)parm->ival; } ; %% #ifdef SOME_FINE_DAY void yyerror(char *s, ...) { va_list ap; va_start(ap, s); if(yylloc.first_line) fprintf(stderr, "%d.%d-%d.%d: error: ", yylloc.first_line, yylloc.first_column, yylloc.last_line, yylloc.last_column); vfprintf(stderr, s, ap); fprintf(stderr, "\n"); } void lyyerror(YYLTYPE t, char *s, ...) { va_list ap; va_start(ap, s); if(t.first_line) fprintf(stderr, "%d.%d-%d.%d: error: ", t.first_line, t.first_column, t.last_line, t.last_column); vfprintf(stderr, s, ap); fprintf(stderr, "\n"); } #endif extern void do_baktrace(CSOUND *csound, uint64_t files); extern char *csound_scoget_text ( void *scanner ); extern char *csound_scoget_current_pointer(void *yyscanner); void csound_scoerror(SCORE_PARM *parm, void *yyscanner, CSOUND *cs, ScoreTree *t, const char* str) { char ch; char *p = csound_scoget_current_pointer(yyscanner)-1; int line = csound_scoget_lineno(yyscanner); uint64_t files = csound_scoget_locn(yyscanner); if (*p=='\0') line--; cs->Message(cs, Str("\nerror: %s (token \"%s\")"), str, csound_scoget_text(yyscanner)); do_baktrace(cs, files); cs->Message(cs, Str(" line %d:\n>>>"), line); while ((ch=*--p) != '\n' && ch != '\0'); do { ch = *++p; if (ch == '\n') break; cs->Message(cs, "%c", ch); } while (ch != '\n' && ch != '\0'); cs->Message(cs, " <<<\n"); } int csound_scowrap() { #ifdef DEBUG printf("\n === END OF INPUT ===\n"); #endif return (1); } static ScoreTree* makesco(CSOUND *csound, int op, ListItem* car, ScoreTree* cdr, int line, int locn) { ScoreTree* a = (ScoreTree*)csound->Malloc(csound, sizeof(ScoreTree)); a->op = op; a->args = car; a->next = cdr; a->line = line; a->locn = locn; return a; } static ScoreTree* makesco1(CSOUND *csound, ScoreTree* car, ScoreTree* cdr) { car->next = cdr; return car; } static ListItem* makelist(CSOUND *csound, double car, ListItem* cdr) { ListItem* a = (ListItem*)csound->Malloc(csound, sizeof(ListItem)); a->val = car; a->args = cdr; return a; } #if 0 int yylex(void) { int c; while ((c=getchar())==' '); if (isdigit(c)) { int n = c-'0'; while (isdigit(c=getchar())) { n = 10*n+c-'0'; } ungetc(c, stdin); return NUMBER_TOKEN; } return c=='\n' ? NEWLINE : c; } extern int csound_scodebug; int main(void) { csound_scodebug = 1; yyparse(); return 0; } #endif csound-6.10.0/Engine/csound_standard_types.c000066400000000000000000000313411321653344700210530ustar00rootroot00000000000000/* csound_standard_types.c: Copyright (C) 2012,2013 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "csound_standard_types.h" #include "pstream.h" #include /* MEMORY COPYING FUNCTIONS */ void myflt_copy_value(void* csound, void* dest, void* src) { IGN(csound); MYFLT* f1 = (MYFLT*)dest; MYFLT* f2 = (MYFLT*)src; *f1 = *f2; } void asig_copy_value(void* csound, void* dest, void* src) { IGN(csound); memcpy(dest, src, sizeof(MYFLT) * ((CSOUND*)csound)->ksmps); } void wsig_copy_value(void* csound, void* dest, void* src) { IGN(csound); memcpy(dest, src, sizeof(SPECDAT)); //TODO - check if this needs to copy SPECDAT's DOWNDAT member and AUXCH } void fsig_copy_value(void* csound, void* dest, void* src) { PVSDAT *fsigout = (PVSDAT*) dest; PVSDAT *fsigin = (PVSDAT*) src; int N = fsigin->N; memcpy(dest, src, sizeof(PVSDAT) - sizeof(AUXCH)); if(fsigout->frame.auxp == NULL || fsigout->frame.size < (N + 2) * sizeof(float)) ((CSOUND *)csound)->AuxAlloc(csound, (N + 2) * sizeof(float), &fsigout->frame); memcpy(fsigout->frame.auxp, fsigin->frame.auxp, (N + 2) * sizeof(float)); } void string_copy_value(void* csound, void* dest, void* src) { STRINGDAT* sDest = (STRINGDAT*)dest; STRINGDAT* sSrc = (STRINGDAT*)src; CSOUND* cs = (CSOUND*)csound; if (UNLIKELY(src == NULL)) return; if (UNLIKELY(dest == NULL)) return; if (sSrc->size > sDest->size) { if (sDest->data != NULL) { cs->Free(cs, sDest->data); } sDest->data = cs_strdup(csound, sSrc->data); sDest->size = strlen(sDest->data)+1; } else { if (sDest->data == NULL) { sDest->data = cs_strdup(csound, sSrc->data); sDest->size = strlen(sDest->data)+1; } else {//breaks here //fprintf(stderr, "\n in:src %p size=%d >>>%s<<data=%p\n", // sSrc->data, sSrc->size, sSrc->data, sDest->size, sDest->data); //memcpy(sDest->data, sSrc->data, sDest->size); //memset(sDest->data,0,sDest->size); strncpy(sDest->data, sSrc->data, sDest->size-1); //cs->Free(cs, sDest->data); sDest->data = cs_strdup(csound, sSrc->data); //sDest->size = strlen(sDest->data)+1; } } //sDest->size = sSrc->size; //fprintf(stderr, "out:srcsize=%d >>>%s<<data=%p\n", // sSrc->size, sSrc->data, sDest->size, sDest->data); } static size_t array_get_num_members(ARRAYDAT* aSrc) { int i, retVal = 0; if (aSrc->dimensions <= 0) { return retVal; } retVal = aSrc->sizes[0]; for (i = 1; i < aSrc->dimensions; i++) { retVal *= aSrc->sizes[i]; } return (size_t)retVal; } void array_copy_value(void* csound, void* dest, void* src) { ARRAYDAT* aDest = (ARRAYDAT*)dest; ARRAYDAT* aSrc = (ARRAYDAT*)src; CSOUND* cs = (CSOUND*)csound; size_t j; int memMyfltSize; size_t arrayNumMembers; arrayNumMembers = array_get_num_members(aSrc); memMyfltSize = aSrc->arrayMemberSize / sizeof(MYFLT); if(aDest->data == NULL || aSrc->arrayMemberSize != aDest->arrayMemberSize || aSrc->dimensions != aDest->dimensions || aSrc->arrayType != aDest->arrayType || arrayNumMembers != array_get_num_members(aDest)) { aDest->arrayMemberSize = aSrc->arrayMemberSize; aDest->dimensions = aSrc->dimensions; if(aDest->sizes != NULL) { cs->Free(cs, aDest->sizes); } aDest->sizes = cs->Malloc(cs, sizeof(int) * aSrc->dimensions); memcpy(aDest->sizes, aSrc->sizes, sizeof(int) * aSrc->dimensions); aDest->arrayType = aSrc->arrayType; if(aDest->data != NULL) { cs->Free(cs, aDest->data); } aDest->data = cs->Calloc(cs, aSrc->arrayMemberSize * arrayNumMembers); } for (j = 0; j < arrayNumMembers; j++) { int index = j * memMyfltSize; aDest->arrayType->copyValue(csound, aDest->data + index, aSrc->data + index); } } /* MEM SIZE UPDATING FUNCTIONS */ void updateAsigMemBlock(void* csound, CS_VARIABLE* var) { CSOUND* cs = (CSOUND*)csound; int ksmps = cs->ksmps; var->memBlockSize = CS_FLOAT_ALIGN(ksmps * sizeof (MYFLT)); } void varInitMemory(void *csound, CS_VARIABLE* var, MYFLT* memblock) { IGN(csound); memset(memblock, 0, var->memBlockSize); } void arrayInitMemory(void *csound, CS_VARIABLE* var, MYFLT* memblock) { IGN(csound); ARRAYDAT* dat = (ARRAYDAT*)memblock; dat->arrayType = var->subType; } void varInitMemoryString(void *csound, CS_VARIABLE* var, MYFLT* memblock) { IGN(var); STRINGDAT *str = (STRINGDAT *)memblock; CSOUND* cs = (CSOUND*)csound; str->data = (char *) cs->Calloc(csound, 8); str->size = 8; //printf("initialised %s %p %s %d\n", var->varName, str, str->data, str->size); } void varInitMemoryFsig(void *csound, CS_VARIABLE* var, MYFLT* memblock) { IGN(var); PVSDAT *fsig = (PVSDAT *)memblock; IGN(csound); memset(fsig, 0, sizeof(PVSDAT)); /* VL: clear memory for now */ } /* CREATE VAR FUNCTIONS */ CS_VARIABLE* createAsig(void* cs, void* p) { int ksmps; CSOUND* csound = (CSOUND*)cs; IGN(p); //FIXME - this needs to take into account local ksmps, once //context work is complete // if (instr != NULL) { // OPDS* p = (OPDS*)instr; // ksmps = CS_KSMPS; // } else { ksmps = csound->ksmps; // } CS_VARIABLE* var = csound->Calloc(csound, sizeof (CS_VARIABLE)); var->memBlockSize = CS_FLOAT_ALIGN(ksmps * sizeof (MYFLT)); var->updateMemBlockSize = &updateAsigMemBlock; var->initializeVariableMemory = &varInitMemory; return var; } CS_VARIABLE* createMyflt(void* cs, void* p) { CSOUND* csound = (CSOUND*)cs; CS_VARIABLE* var = csound->Calloc(csound, sizeof (CS_VARIABLE)); IGN(p); var->memBlockSize = CS_FLOAT_ALIGN(sizeof (MYFLT)); var->initializeVariableMemory = &varInitMemory; return var; } CS_VARIABLE* createBool(void* cs, void* p) { CSOUND* csound = (CSOUND*)cs; CS_VARIABLE* var = csound->Calloc(csound, sizeof (CS_VARIABLE)); IGN(p); var->memBlockSize = CS_FLOAT_ALIGN(sizeof (MYFLT)); var->initializeVariableMemory = &varInitMemory; return var; } CS_VARIABLE* createWsig(void* cs, void* p) { CSOUND* csound = (CSOUND*)cs; CS_VARIABLE* var = csound->Calloc(csound, sizeof (CS_VARIABLE)); IGN(p); var->memBlockSize = CS_FLOAT_ALIGN(sizeof(SPECDAT)); var->initializeVariableMemory = &varInitMemory; return var; } CS_VARIABLE* createFsig(void* cs, void* p) { CSOUND* csound = (CSOUND*)cs; CS_VARIABLE* var = csound->Calloc(csound, sizeof (CS_VARIABLE)); IGN(p); var->memBlockSize = CS_FLOAT_ALIGN(sizeof(PVSDAT)); var->initializeVariableMemory = &varInitMemoryFsig; return var; } CS_VARIABLE* createString(void* cs, void* p) { CSOUND* csound = (CSOUND*)cs; CS_VARIABLE* var = csound->Calloc(csound, sizeof (CS_VARIABLE)); IGN(p); var->memBlockSize = CS_FLOAT_ALIGN(sizeof(STRINGDAT)); var->initializeVariableMemory = &varInitMemoryString; return var; } CS_VARIABLE* createArray(void* csnd, void* p) { CSOUND* csound = (CSOUND*)csnd; ARRAY_VAR_INIT* state = (ARRAY_VAR_INIT*)p; CS_VARIABLE* var = csound->Calloc(csound, sizeof (CS_VARIABLE)); var->memBlockSize = CS_FLOAT_ALIGN(sizeof(ARRAYDAT)); var->initializeVariableMemory = &arrayInitMemory; if (state) { // NB: this function is being called with p=NULL CS_TYPE* type = state->type; var->subType = type; var->dimensions = state->dimensions; } return var; } /* FREE VAR MEM FUNCTIONS */ void string_free_var_mem(void* csnd, void* p ) { CSOUND* csound = (CSOUND*)csnd; STRINGDAT* dat = (STRINGDAT*)p; if(dat->data != NULL) { csound->Free(csound, dat->data); } } void array_free_var_mem(void* csnd, void* p) { CSOUND* csound = (CSOUND*)csnd; ARRAYDAT* dat = (ARRAYDAT*)p; if(dat->data != NULL) { CS_TYPE* arrayType = dat->arrayType; if (arrayType->freeVariableMemory != NULL) { MYFLT* mem = dat->data; size_t memMyfltSize = dat->arrayMemberSize / sizeof(MYFLT); int i, size = dat->sizes[0]; for (i = 1; i < dat->dimensions; i++) { size *= dat->sizes[i]; } //size = MYFLT2LRND(size); // size is not a float but int for (i = 0; i < size; i++) { arrayType->freeVariableMemory(csound, mem+ (i * memMyfltSize)); } } csound->Free(csound, dat->data); } if (dat->sizes != NULL) { csound->Free(csound, dat->sizes); } } /* STANDARD TYPE DEFINITIONS */ const CS_TYPE CS_VAR_TYPE_A = { "a", "audio rate vector", CS_ARG_TYPE_BOTH, createAsig, asig_copy_value, NULL, NULL }; const CS_TYPE CS_VAR_TYPE_K = { "k", "control rate var", CS_ARG_TYPE_BOTH, createMyflt, myflt_copy_value, NULL, NULL }; const CS_TYPE CS_VAR_TYPE_I = { "i", "init time var", CS_ARG_TYPE_BOTH, createMyflt, myflt_copy_value, NULL, NULL }; const CS_TYPE CS_VAR_TYPE_S = { "S", "String var", CS_ARG_TYPE_BOTH, createString, string_copy_value, NULL, string_free_var_mem }; const CS_TYPE CS_VAR_TYPE_P = { "p", "p-field", CS_ARG_TYPE_BOTH, createMyflt, myflt_copy_value, NULL, NULL }; const CS_TYPE CS_VAR_TYPE_R = { "r", "reserved symbol", CS_ARG_TYPE_BOTH, createMyflt, myflt_copy_value, NULL, NULL }; const CS_TYPE CS_VAR_TYPE_C = { "c", "constant", CS_ARG_TYPE_IN, createMyflt, myflt_copy_value, NULL, NULL }; const CS_TYPE CS_VAR_TYPE_W = { "w", "spectral", CS_ARG_TYPE_BOTH, createWsig, wsig_copy_value, NULL, NULL }; const CS_TYPE CS_VAR_TYPE_F = { "f", "f-sig", CS_ARG_TYPE_BOTH, createFsig, fsig_copy_value, NULL, NULL }; const CS_TYPE CS_VAR_TYPE_B = { "B", "boolean", CS_ARG_TYPE_BOTH, createBool, myflt_copy_value, NULL, NULL }; const CS_TYPE CS_VAR_TYPE_b = { "b", "boolean", CS_ARG_TYPE_BOTH, createBool, myflt_copy_value, NULL, NULL }; const CS_TYPE CS_VAR_TYPE_ARRAY = { "[", "array", CS_ARG_TYPE_BOTH, createArray, array_copy_value, NULL, array_free_var_mem }; void csoundAddStandardTypes(CSOUND* csound, TYPE_POOL* pool) { csoundAddVariableType(csound, pool, (CS_TYPE*)&CS_VAR_TYPE_A); csoundAddVariableType(csound, pool, (CS_TYPE*)&CS_VAR_TYPE_K); csoundAddVariableType(csound, pool, (CS_TYPE*)&CS_VAR_TYPE_I); csoundAddVariableType(csound, pool, (CS_TYPE*)&CS_VAR_TYPE_S); csoundAddVariableType(csound, pool, (CS_TYPE*)&CS_VAR_TYPE_P); csoundAddVariableType(csound, pool, (CS_TYPE*)&CS_VAR_TYPE_R); csoundAddVariableType(csound, pool, (CS_TYPE*)&CS_VAR_TYPE_C); csoundAddVariableType(csound, pool, (CS_TYPE*)&CS_VAR_TYPE_W); csoundAddVariableType(csound, pool, (CS_TYPE*)&CS_VAR_TYPE_F); csoundAddVariableType(csound, pool, (CS_TYPE*)&CS_VAR_TYPE_B); csoundAddVariableType(csound, pool, (CS_TYPE*)&CS_VAR_TYPE_b); csoundAddVariableType(csound, pool, (CS_TYPE*)&CS_VAR_TYPE_ARRAY); } /* Type maps for poly, optional, and var arg types * format is in pairs of specified type and types it can resolve into, * termintated by a NULL */ const char* POLY_IN_TYPES[] = { "x", "kacpri", "T", "Sicpr", "U", "Sikcpr", "i", "cpri", "k", "cprki", "B", "Bb", NULL}; const char* OPTIONAL_IN_TYPES[] = { "o", "icpr", "p", "icpr", "q", "icpr", "v", "icpr", "j", "icpr", "h", "icpr", "O", "kicpr", "J", "kicpr", "V", "kicpr", "P", "kicpr", NULL }; const char* VAR_ARG_IN_TYPES[] = { "m", "icrp", "M", "icrpka", "N", "icrpkaS", "n", "icrp", /* this one requires odd number of args... */ "W", "S", "y", "a", "z", "kicrp", "Z", "kaicrp", NULL /* this one needs to be ka alternatating... */ }; const char* POLY_OUT_TYPES[] = { "s", "ka", "i", "pi", NULL }; const char* VAR_ARG_OUT_TYPES[] = { "m", "a", "z", "k", "I", "Sip", /* had comment of (not implemented yet) in entry1.c */ "X", "akip", "N", "akipS", "F", "f", NULL }; csound-6.10.0/Engine/csound_type_system.c000066400000000000000000000216161321653344700204200ustar00rootroot00000000000000/* csound_type_system.c: Copyright (C) 2012,2013 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csound_type_system.h" #include #include #include "csoundCore.h" int csTypeExistsWithSameName(TYPE_POOL* pool, CS_TYPE* typeInstance) { CS_TYPE_ITEM* current = pool->head; while (current != NULL) { /* printf("Search if type [%s] == [%s]", current->varTypeName, typeInstance->varTypeName); */ if (strcmp(current->cstype->varTypeName, typeInstance->varTypeName) == 0) { return 1; } current = current->next; } return 0; } CS_TYPE* csoundGetTypeWithVarTypeName(TYPE_POOL* pool, char* typeName) { CS_TYPE_ITEM* current = pool->head; while (current != NULL) { if (strcmp(typeName, current->cstype->varTypeName) == 0) { return current->cstype; } current = current->next; } return NULL; } CS_TYPE* csoundGetTypeForVarName(TYPE_POOL* pool, char* varName) { CS_TYPE_ITEM* current = pool->head; char temp[2]; temp[0] = varName[0]; temp[1] = 0; while (current != NULL) { if (strcmp(temp, current->cstype->varTypeName) == 0) { return current->cstype; } current = current->next; } return NULL; } int csoundAddVariableType(CSOUND* csound, TYPE_POOL* pool, CS_TYPE* typeInstance) { CS_TYPE_ITEM* item; if (csTypeExistsWithSameName(pool, typeInstance)) { return 0; } item = (CS_TYPE_ITEM*)csound->Calloc(csound, sizeof(CS_TYPE_ITEM)); item->cstype = typeInstance; if (pool->head == NULL) { pool->head = item; } else { CS_TYPE_ITEM* current = pool->head; while (current->next) { current = current->next; } current->next = item; item->next = NULL; } /* printf("Adding type with type name: %s\n", typeInstance->varTypeName); */ return 1; } /* VAR POOL FUNCTIONS */ CS_VAR_POOL* csoundCreateVarPool(CSOUND* csound) { CS_VAR_POOL* varPool = csound->Calloc(csound, sizeof(CS_VAR_POOL)); varPool->table = cs_hash_table_create(csound); return varPool; } void csoundFreeVarPool(CSOUND* csound, CS_VAR_POOL* pool) { if(pool->table) cs_hash_table_mfree_complete(csound, pool->table); csound->Free(csound, pool); } char* getVarSimpleName(CSOUND* csound, const char* varName) { char* retVal; if (varName[0] != '[') { retVal = (char*)csound->Calloc(csound, sizeof(char) * (strlen(varName) + 1)); strcpy(retVal, varName); } else { int start = 0; int typeEnd = 0; int len = strlen(varName); int newFirstLen, newSecondLen, newTotalLen; char* t = (char*) varName; char* t2; while(*t == '[') { t++; start++; } typeEnd = start; t2 = t; while(*t2 != ']' && *t2 != (char)0) { t2++; typeEnd++; } t2++; typeEnd++; newFirstLen = (typeEnd - start - 1); newSecondLen = (len - typeEnd); newTotalLen = newFirstLen + newSecondLen; retVal = (char*)csound->Calloc(csound, sizeof(char) * (newTotalLen + 1)); strncpy(retVal, t, newFirstLen); strncpy(retVal + newFirstLen, t2, newSecondLen); } return retVal; } CS_VARIABLE* csoundCreateVariable(void* csound, TYPE_POOL* pool, CS_TYPE* type, char* name, void* typeArg) { CS_TYPE_ITEM* current = pool->head; if (LIKELY(type != NULL)) while (current != NULL) { if (strcmp(type->varTypeName, current->cstype->varTypeName) == 0) { CS_VARIABLE* var = current->cstype->createVariable(csound, typeArg); var->varType = type; var->varName = cs_strdup(csound, name); return var; } current = current->next; } else ((CSOUND *)csound)->ErrorMsg(csound, Str("cannot create variable %s: NULL type"), name); return NULL; } CS_VARIABLE* csoundFindVariableWithName(CSOUND* csound, CS_VAR_POOL* pool, const char* name) { CS_VARIABLE* returnValue = cs_hash_table_get(csound, pool->table, (char*)name); if (returnValue == NULL && pool->parent != NULL) { returnValue = csoundFindVariableWithName(csound, pool->parent, name); } return returnValue; } CS_VARIABLE* csoundGetVariable(CS_VAR_POOL* pool, int index) { CS_VARIABLE* current = pool->head; int i; for(i = 0; i < index || current != NULL; i++) { /* THIS WAS WRONG!! && or || meant foR , ?? */ current = current->next; } return current; } //int csoundGetVariableIndex(CS_VAR_POOL* pool, CS_VARIABLE* var) { // CS_VARIABLE* current = pool->head; // int index = 0; // // if (current == NULL) { // return -1; // } // // for (index = 0; current != NULL; index++) { // if (current == var) { // return index; // } // } // return -1; //} int csoundAddVariable(CSOUND* csound, CS_VAR_POOL* pool, CS_VARIABLE* var) { if(var != NULL) { if(pool->head == NULL) { pool->head = var; pool->tail = var; } else { pool->tail->next = var; pool->tail = var; } cs_hash_table_put(csound, pool->table, var->varName, var); // may need to revise this; var pools are accessed as MYFLT*, // so need to ensure all memory is aligned to sizeof(MYFLT) var->memBlockIndex = (pool->poolSize / sizeof(MYFLT)) + ((pool->varCount + 1) * (CS_FLOAT_ALIGN(CS_VAR_TYPE_OFFSET) / sizeof(MYFLT))); pool->poolSize += var->memBlockSize; pool->varCount += 1; return 0; } else return -1; } void recalculateVarPoolMemory(void* csound, CS_VAR_POOL* pool) { CS_VARIABLE* current = pool->head; int varCount = 1; pool->poolSize = 0; while (current != NULL) { /* VL 26-12-12: had to revert these lines to avoid memory crashes with higher ksmps */ if(current->updateMemBlockSize != NULL) { current->updateMemBlockSize(csound, current); } current->memBlockIndex = (pool->poolSize / sizeof(MYFLT)) + (varCount * CS_FLOAT_ALIGN(CS_VAR_TYPE_OFFSET) / sizeof(MYFLT)); pool->poolSize += current->memBlockSize; current = current->next; varCount++; } } void reallocateVarPoolMemory(void* csound, CS_VAR_POOL* pool) { CS_VARIABLE* current = pool->head; CS_VAR_MEM* varMem = NULL; size_t memSize; pool->poolSize = 0; while (current != NULL) { varMem = current->memBlock; memSize = current->memBlockSize; if(current->updateMemBlockSize != NULL) { current->updateMemBlockSize(csound, current); } // VL 14-3-2015 only realloc if we need to if(memSize < (size_t)current->memBlockSize) { memSize = CS_VAR_TYPE_OFFSET + current->memBlockSize; varMem = (CS_VAR_MEM *)((CSOUND *)csound)->ReAlloc(csound,varMem, memSize); current->memBlock = varMem; } pool->poolSize += current->memBlockSize; current = current->next; } } void deleteVarPoolMemory(void* csnd, CS_VAR_POOL* pool) { CS_VARIABLE* current = pool->head, *tmp; CSOUND *csound = (CSOUND *)csnd; CS_TYPE* type; while (current != NULL) { tmp = current; type = current->subType; if (type->freeVariableMemory != NULL) { type->freeVariableMemory(csound, current->memBlock); } csound->Free(csound, current->memBlock); current = current->next; csound->Free(csound, tmp); } } void initializeVarPool(void *csound, MYFLT* memBlock, CS_VAR_POOL* pool) { CS_VARIABLE* current = pool->head; int varNum = 1; while (current != NULL) { if (current->initializeVariableMemory != NULL) { current->initializeVariableMemory(csound, current, memBlock + current->memBlockIndex); } varNum++; current = current->next; } } void debug_print_varpool(CSOUND* csound, CS_VAR_POOL* pool) { CS_VARIABLE* gVar = pool->head; int count = 0; while(gVar != NULL) { csound->Message(csound, " %d) %s:%s\n", count++, gVar->varName, gVar->varType->varTypeName); gVar = gVar->next; } } csound-6.10.0/Engine/entry1.c000066400000000000000000002352561321653344700157110ustar00rootroot00000000000000/* entry1.c: Copyright (C) 1991 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "entry1.h" /* ENTRY1.C */ #include "interlocks.h" /* thread vals, where isub=1, ksub=2, asub=4: 0 = 1 OR 2 (B out only) 1 = 1 2 = 2 3 = 1 AND 2 4 = 4 5 = 1 AND 4 7 = 1 AND (2 OR 4) */ /* inarg types include the following: i irate scalar k krate scalar a arate vector f frequency variable w spectral variable x krate scalar or arate vector S String T String or i-rate U String or i/k-rate B Boolean k-rate b Boolean i-rate; internally generated as required l Label . required arg of any-type and codes ? optional arg of any-type m begins an indef list of iargs (any count) M begins an indef list of args (any count/rate i,k,a) N begins an indef list of args (any count/rate i,k,a,S) o optional i-rate, defaulting to 0 p " " 1 q " " 10 v " " .5 j " " -1 h " " 127 O optional k-rate, defaulting to 0 J " " -1 V " " .5 P " " 1 W begins indef list of Strings (any count) y begins indef list of aargs (any count) z begins indef list of kargs (any count) Z begins alternating kakaka...list (any count) */ /* outarg types include: i, k, a, S as above * multiple out args of any-type m multiple out aargs z multiple out kargs I multiple out irate (not implemented yet) s deprecated (use a or k as required) X multiple args (a, k, or i-rate) IV - Sep 1 2002 N multiple args (a, k, i, or S-rate) F multiple args (f-rate)# */ OENTRY opcodlst_1[] = { /* opcode dspace flags thread outarg inargs isub ksub asub */ { "", 0, 0, 0, "", "", NULL, NULL, NULL, NULL }, { "instr", 0, 0, 0, "", "", NULL, NULL, NULL, NULL }, { "endin", 0, 0, 0, "", "", NULL, NULL, NULL, NULL }, /* IV - Sep 8 2002 */ { "opcode", 0, 0, 0, "", "", NULL, NULL, NULL, NULL }, { "endop", 0, 0, 0, "", "", NULL, NULL, NULL, NULL }, { "$label", S(LBLBLK), 0,0, "", "", NULL, NULL, NULL, NULL }, { "pset", S(PVSET), 0,0, "", "m", NULL, NULL, NULL, NULL }, /* IV - Sep 8 2002 - added entries for user defined opcodes, xin, xout */ /* and setksmps */ { "##userOpcode", S(UOPCODE),0, 7, "", "", useropcdset, useropcd, useropcd, NULL }, /* IV - Sep 10 2002: removed perf time routines of xin and xout */ { "xin", S(XIN_MAX),0, 1, "****************", "", xinset, NULL, NULL, NULL }, /* { "xin.64", S(XIN_HIGH),0, 1, "****************************************************************", "", xinset, NULL, NULL }, { "##xin256", S(XIN_MAX),0, 1, "****************************************************************" "****************************************************************" "****************************************************************" "****************************************************************", "", xinset, NULL, NULL },*/ { "xout", S(XOUT_MAX),0, 1, "", "*", xoutset, NULL, NULL, NULL }, { "setksmps", S(SETKSMPS),0, 1, "", "i", setksmpsset, NULL, NULL }, { "ctrlinit",S(CTLINIT),0,1, "", "im", ctrlinit, NULL, NULL, NULL}, { "massign",S(MASSIGN), 0,1, "", "iip",massign_p, NULL, NULL, NULL}, { "massign.iS",S(MASSIGNS), 0,1, "", "iSp",massign_S, NULL, NULL, NULL}, { "turnon", S(TURNON), 0,1, "", "io", turnon, NULL, NULL, NULL}, { "turnon.S", S(TURNON), 0,1, "", "So", turnon_S, NULL, NULL, NULL}, { "remoteport", S(REMOTEPORT), 0,1, "", "i", remoteport, NULL, NULL, NULL}, { "insremot",S(INSREMOT),0,1, "", "SSm",insremot, NULL, NULL, NULL}, { "midremot",S(MIDREMOT),0,1, "", "SSm",midremot, NULL, NULL, NULL}, { "insglobal",S(INSGLOBAL),0,1, "", "Sm", insglobal, NULL, NULL, NULL}, { "midglobal",S(MIDGLOBAL),0,1, "", "Sm", midglobal, NULL, NULL, NULL}, { "ihold", S(LINK),0, 1, "", "", ihold, NULL, NULL, NULL }, { "turnoff",S(LINK),0, 2, "", "", NULL, turnoff, NULL, NULL }, { "=.S", S(STRCPY_OP),0, 1, "S", "S", (SUBR) strcpy_opcode_S, NULL, (SUBR) NULL, NULL }, { "=.T", S(STRGET_OP),0, 1, "S", "i", (SUBR) strcpy_opcode_p, (SUBR) NULL, (SUBR) NULL, NULL }, { "=.r", S(ASSIGN),0, 1, "r", "i", rassign, NULL, NULL, NULL }, { "=.i", S(ASSIGNM),0, 1, "IIIIIIIIIIIIIIIIIIIIIIII", "m", minit, NULL, NULL, NULL }, { "=.k", S(ASSIGNM),0, 2, "zzzzzzzzzzzzzzzzzzzzzzzz", "z", NULL, minit, NULL, NULL }, { "=.a", S(ASSIGN),0, 4, "a", "a", NULL, NULL, gaassign, NULL }, { "=.l", S(ASSIGN),0, 4, "a", "a", NULL, NULL, laassign, NULL }, { "=.up", S(UPSAMP),0, 4, "a", "k", NULL, NULL, (SUBR)upsamp, NULL }, { "=.down", S(DOWNSAMP),0, 3, "k", "ao", (SUBR)downset,(SUBR)downsamp }, // { "=.t", S(ASSIGNT),0, 2, "t", "kk", NULL, tassign, NULL }, { "init.S", S(STRCPY_OP),0, 1, "S", "S", (SUBR) strcpy_opcode_S }, { "init.Si", S(STRCPY_OP),0, 1, "S", "i", (SUBR) strcpy_opcode_p }, { "init.i", S(ASSIGNM),0, 1, "IIIIIIIIIIIIIIIIIIIIIIII", "m", minit }, { "init.k", S(ASSIGNM),0, 1, "zzzzzzzzzzzzzzzzzzzzzzzz", "m", minit }, { "init.a", S(ASSIGNM),0, 1, "mmmmmmmmmmmmmmmmmmmmmmmm", "m", mainit }, { ">", S(RELAT),0, 0, "b", "ii", gt, gt }, { ">.0", S(RELAT),0, 0, "B", "kk", gt, gt }, { ">=", S(RELAT),0, 0, "b", "ii", ge, ge }, { ">=.0", S(RELAT),0, 0, "B", "kk", ge, ge }, { "<", S(RELAT),0, 0, "b", "ii", lt, lt }, { "<.0", S(RELAT),0, 0, "B", "kk", lt, lt }, { "<=", S(RELAT),0, 0, "b", "ii", le, le }, { "<=.0", S(RELAT),0, 0, "B", "kk", le, le }, { "==", S(RELAT),0, 0, "b", "ii", eq, eq }, { "==.0", S(RELAT),0, 0, "B", "kk", eq, eq }, { "!=", S(RELAT),0, 0, "b", "ii", ne, ne }, { "!=.0", S(RELAT),0, 0, "B", "kk", ne, ne }, { "!", S(LOGCL),0, 0, "b", "b", b_not, b_not }, { "!.0", S(LOGCL),0, 0, "B", "B", b_not, b_not }, { "&&", S(LOGCL),0, 0, "b", "bb", and, and }, { "&&.0", S(LOGCL),0, 0, "B", "BB", and, and }, { "||", S(LOGCL),0, 0, "b", "bb", or, or }, { "||.0", S(LOGCL),0, 0, "B", "BB", or, or }, { ":cond.i", S(CONVAL),0, 1, "i", "bii", conval }, { ":cond.k", S(CONVAL),0, 2, "k", "Bkk", NULL, conval }, { ":cond.a", S(CONVAL),0, 4, "a", "Bxx", NULL, NULL, aconval }, { ":cond.s", S(CONVAL),0, 3, "S", "bSS", conval, NULL }, { ":cond.S", S(CONVAL),0, 3, "S", "BSS", conval, conval }, { "##add.ii", S(AOP),0, 1, "i", "ii", addkk }, { "##sub.ii", S(AOP),0, 1, "i", "ii", subkk }, { "##mul.ii", S(AOP),0, 1, "i", "ii", mulkk }, { "##div.ii", S(AOP),0, 1, "i", "ii", divkk }, { "##mod.ii", S(AOP),0, 1, "i", "ii", modkk }, { "##add.kk", S(AOP),0, 2, "k", "kk", NULL, addkk }, { "##sub.kk", S(AOP),0, 2, "k", "kk", NULL, subkk }, { "##mul.kk", S(AOP),0, 2, "k", "kk", NULL, mulkk }, { "##div.kk", S(AOP),0, 2, "k", "kk", NULL, divkk }, { "##mod.kk", S(AOP),0, 2, "k", "kk", NULL, modkk }, { "##add.ka", S(AOP),0, 4, "a", "ka", NULL, NULL, addka }, { "##sub.ka", S(AOP),0, 4, "a", "ka", NULL, NULL, subka }, { "##mul.ka", S(AOP),0, 4, "a", "ka", NULL, NULL, mulka }, { "##div.ka", S(AOP),0, 4, "a", "ka", NULL, NULL, divka }, { "##mod.ka", S(AOP),0, 4, "a", "ka", NULL, NULL, modka }, { "##add.ak", S(AOP),0, 4, "a", "ak", NULL, NULL, addak }, { "##sub.ak", S(AOP),0, 4, "a", "ak", NULL, NULL, subak }, { "##mul.ak", S(AOP),0, 4, "a", "ak", NULL, NULL, mulak }, { "##div.ak", S(AOP),0, 4, "a", "ak", NULL, NULL, divak }, { "##mod.ak", S(AOP),0, 4, "a", "ak", NULL, NULL, modak }, { "##add.aa", S(AOP),0, 4, "a", "aa", NULL, NULL, addaa }, { "##sub.aa", S(AOP),0, 4, "a", "aa", NULL, NULL, subaa }, { "##mul.aa", S(AOP),0, 4, "a", "aa", NULL, NULL, mulaa }, { "##div.aa", S(AOP),0, 4, "a", "aa", NULL, NULL, divaa }, { "##mod.aa", S(AOP),0, 4, "a", "aa", NULL, NULL, modaa }, { "divz", 0xfffc }, { "divz.ii", S(DIVZ),0, 1, "i", "iii", divzkk, NULL, NULL }, { "divz.kk", S(DIVZ),0, 2, "k", "kkk", NULL, divzkk, NULL }, { "divz.ak", S(DIVZ),0, 4, "a", "akk", NULL, NULL, divzak }, { "divz.ka", S(DIVZ),0, 4, "a", "kak", NULL, NULL, divzka }, { "divz.aa", S(DIVZ),0, 4, "a", "aak", NULL, NULL, divzaa }, { "int.i", S(EVAL),0, 1, "i", "i", int1 }, { "frac.i", S(EVAL),0, 1, "i", "i", frac1 }, { "round.i",S(EVAL),0, 1, "i", "i", int1_round }, { "floor.i",S(EVAL),0, 1, "i", "i", int1_floor }, { "ceil.i", S(EVAL),0, 1, "i", "i", int1_ceil }, { "rnd.i", S(EVAL),0, 1, "i", "i", rnd1 }, { "birnd.i",S(EVAL),0, 1, "i", "i", birnd1 }, { "abs.i", S(EVAL),0, 1, "i", "i", abs1 }, { "exp.i", S(EVAL),0, 1, "i", "i", exp01 }, { "log.i", S(EVAL),0, 1, "i", "i", log01 }, { "sqrt.i", S(EVAL),0, 1, "i", "i", sqrt1 }, { "sin.i", S(EVAL),0, 1, "i", "i", sin1 }, { "cos.i", S(EVAL),0, 1, "i", "i", cos1 }, { "tan.i", S(EVAL),0, 1, "i", "i", tan1 }, { "qinf.i", S(EVAL),0, 1, "i", "i", is_inf }, { "qnan.i", S(EVAL),0, 1, "i", "i", is_NaN }, { "sininv.i", S(EVAL),0, 1, "i", "i", asin1 }, { "cosinv.i", S(EVAL),0, 1, "i", "i", acos1 }, { "taninv.i", S(EVAL),0, 1, "i", "i", atan1 }, { "taninv2.i",S(AOP),0, 1, "i", "ii", atan21 }, { "log10.i",S(EVAL),0, 1, "i", "i", log101 }, { "log2.i", S(EVAL),0, 1, "i", "i", log21 }, { "sinh.i", S(EVAL),0, 1, "i", "i", sinh1 }, { "cosh.i", S(EVAL),0, 1, "i", "i", cosh1 }, { "tanh.i", S(EVAL),0, 1, "i", "i", tanh1 }, { "int.k", S(EVAL),0, 2, "k", "k", NULL, int1 }, { "frac.k", S(EVAL),0, 2, "k", "k", NULL, frac1 }, { "round.k",S(EVAL),0, 2, "k", "k", NULL, int1_round }, { "floor.k",S(EVAL),0, 2, "k", "k", NULL, int1_floor }, { "ceil.k", S(EVAL),0, 2, "k", "k", NULL, int1_ceil }, { "rnd.k", S(EVAL),0, 2, "k", "k", NULL, rnd1 }, { "birnd.k",S(EVAL),0, 2, "k", "k", NULL, birnd1 }, { "abs.k", S(EVAL),0, 2, "k", "k", NULL, abs1 }, { "exp.k", S(EVAL),0, 2, "k", "k", NULL, exp01 }, { "log.k", S(EVAL),0, 2, "k", "k", NULL, log01 }, { "sqrt.k", S(EVAL),0, 2, "k", "k", NULL, sqrt1 }, { "sin.k", S(EVAL),0, 2, "k", "k", NULL, sin1 }, { "cos.k", S(EVAL),0, 2, "k", "k", NULL, cos1 }, { "tan.k", S(EVAL),0, 2, "k", "k", NULL, tan1 }, { "qinf.k", S(EVAL),0, 2, "k", "k", NULL, is_inf }, { "qnan.k", S(EVAL),0, 2, "k", "k", NULL, is_NaN }, { "sininv.k", S(EVAL),0, 2, "k", "k", NULL, asin1 }, { "cosinv.k", S(EVAL),0, 2, "k", "k", NULL, acos1 }, { "taninv.k", S(EVAL),0, 2, "k", "k", NULL, atan1 }, { "taninv2.k",S(AOP),0, 2, "k", "kk", NULL, atan21 }, { "sinh.k", S(EVAL),0, 2, "k", "k", NULL, sinh1 }, { "cosh.k", S(EVAL),0, 2, "k", "k", NULL, cosh1 }, { "tanh.k", S(EVAL),0, 2, "k", "k", NULL, tanh1 }, { "log10.k",S(EVAL),0, 2, "k", "k", NULL, log101 }, { "log2.k", S(EVAL),0, 2, "k", "k", NULL, log21 }, { "int.a", S(EVAL),0, 4, "a", "a", NULL, NULL, int1a }, { "frac.a", S(EVAL),0, 4, "a", "a", NULL, NULL, frac1a }, { "round.a",S(EVAL),0, 4, "a", "a", NULL, NULL, int1a_round }, { "floor.a",S(EVAL),0, 4, "a", "a", NULL, NULL, int1a_floor }, { "ceil.a", S(EVAL),0, 4, "a", "a", NULL, NULL, int1a_ceil }, { "abs.a", S(EVAL),0, 4, "a", "a", NULL, NULL, absa }, { "exp.a", S(EVAL),0, 4, "a", "a", NULL, NULL, expa }, { "log.a", S(EVAL),0, 4, "a", "a", NULL, NULL, loga }, { "sqrt.a", S(EVAL),0, 4, "a", "a", NULL, NULL, sqrta }, { "sin.a", S(EVAL),0, 4, "a", "a", NULL, NULL, sina }, { "cos.a", S(EVAL),0, 4, "a", "a", NULL, NULL, cosa }, { "tan.a", S(EVAL),0, 4, "a", "a", NULL, NULL, tana }, { "qinf.a", S(EVAL),0, 4, "a", "a", NULL, NULL, is_infa }, { "qnan.a", S(EVAL),0, 4, "a", "a", NULL, NULL, is_NaNa }, { "sininv.a", S(EVAL),0, 4, "a", "a", NULL, NULL, asina }, { "cosinv.a", S(EVAL),0, 4, "a", "a", NULL, NULL, acosa }, { "taninv.a", S(EVAL),0, 4, "a", "a", NULL, NULL, atana }, { "taninv2.a",S(AOP),0, 4, "a", "aa", NULL, NULL, atan2aa }, { "sinh.a", S(EVAL),0, 4, "a", "a", NULL, NULL, sinha }, { "cosh.a", S(EVAL),0, 4, "a", "a", NULL, NULL, cosha }, { "tanh.a", S(EVAL),0, 4, "a", "a", NULL, NULL, tanha }, { "log10.a",S(EVAL),0, 4, "a", "a", NULL, NULL, log10a }, { "log2.a", S(EVAL),0, 4, "a", "a", NULL, NULL, log2a }, { "ampdb.a",S(EVAL),0, 4, "a", "a", NULL, NULL, aampdb }, { "ampdb.i",S(EVAL),0, 1, "i", "i", ampdb }, { "ampdb.k",S(EVAL),0, 2, "k", "k", NULL, ampdb }, { "ampdbfs.a",S(EVAL),0, 4, "a", "a", NULL, NULL, aampdbfs }, { "ampdbfs.i",S(EVAL),0, 1, "i", "i", ampdbfs }, { "ampdbfs.k",S(EVAL),0, 2, "k", "k", NULL, ampdbfs }, { "dbamp.i",S(EVAL),0, 1, "i", "i", dbamp }, { "dbamp.k",S(EVAL),0, 2, "k", "k", NULL, dbamp }, { "dbfsamp.i",S(EVAL),0, 1, "i", "i", dbfsamp }, { "dbfsamp.k",S(EVAL),0, 2, "k", "k", NULL, dbfsamp }, { "rtclock.i",S(EVAL),0, 1, "i", "", rtclock }, { "rtclock.k",S(EVAL),0, 2, "k", "", NULL, rtclock }, { "ftlen.i",S(EVAL),0, 1, "i", "i", ftlen }, { "ftsr.i",S(EVAL),0, 1, "i", "i", ftsr }, { "ftlptim.i",S(EVAL),0, 1, "i", "i", ftlptim }, { "ftchnls.i",S(EVAL),0, 1, "i", "i", ftchnls }, { "ftcps.i",S(EVAL),0, 1, "i", "i", ftcps }, { "i.i", S(ASSIGN),0, 1, "i", "i", assign }, { "i.k", S(ASSIGN),0, 1, "i", "k", assign }, { "k.i", S(ASSIGN),0, 1, "k", "i", assign }, { "k.a", S(DOWNSAMP),0, 3, "k", "ao", (SUBR)downset,(SUBR)downsamp }, { "cpsoct.i",S(EVAL),0, 1, "i", "i", cpsoct }, { "octpch.i",S(EVAL),0, 1, "i", "i", octpch }, { "cpspch.i",S(EVAL),0, 1, "i", "i", cpspch }, { "pchoct.i",S(EVAL),0, 1, "i", "i", pchoct }, { "octcps.i",S(EVAL),0, 1, "i", "i", octcps }, { "cpsoct.k",S(EVAL),0, 2, "k", "k", NULL, cpsoct }, { "octpch.k",S(EVAL),0, 2, "k", "k", NULL, octpch }, { "cpspch.k",S(EVAL),0, 2, "k", "k", NULL, cpspch }, { "pchoct.k",S(EVAL),0, 2, "k", "k", NULL, pchoct }, { "octcps.k",S(EVAL),0, 2, "k", "k", NULL, octcps }, { "cpsoct.a",S(EVAL),0, 4, "a", "a", NULL, NULL, acpsoct }, { "cpsmidinn.i",S(EVAL),0,1, "i", "i", cpsmidinn }, { "octmidinn.i",S(EVAL),0,1, "i", "i", octmidinn }, { "pchmidinn.i",S(EVAL),0,1, "i", "i", pchmidinn }, { "cpsmidinn.k",S(EVAL),0,2, "k", "k", NULL, cpsmidinn }, { "octmidinn.k",S(EVAL),0,2, "k", "k", NULL, octmidinn }, { "pchmidinn.k",S(EVAL),0,2, "k", "k", NULL, pchmidinn }, { "notnum", S(MIDIKMB),0, 1, "i", "", notnum }, { "veloc", S(MIDIMAP),0, 1, "i", "oh", veloc }, { "pchmidi",S(MIDIKMB),0, 1, "i", "", pchmidi }, { "octmidi",S(MIDIKMB),0, 1, "i", "", octmidi }, { "cpsmidi",S(MIDIKMB),0, 1, "i", "", cpsmidi }, { "pchmidib.i",S(MIDIKMB),0,1, "i", "o", pchmidib_i }, { "octmidib.i",S(MIDIKMB),0,1, "i", "o", octmidib_i }, { "cpsmidib.i",S(MIDIKMB),0,1, "i", "o", icpsmidib_i }, { "pchmidib.k",S(MIDIKMB),0,3, "k", "o", midibset, pchmidib }, { "octmidib.k",S(MIDIKMB),0,3, "k", "o", midibset, octmidib }, { "cpsmidib.k",S(MIDIKMB),0,3, "k", "o", midibset, icpsmidib }, { "ampmidi",S(MIDIAMP),0, 1, "i", "io", ampmidi }, { "aftouch",S(MIDIKMAP),0, 3, "k", "oh", aftset, aftouch }, { "pchbend.i",S(MIDIMAP),0,0x21, "i", "jp", ipchbend }, { "pchbend.k",S(MIDIKMAP),0,0x23, "k", "jp", kbndset,kpchbend }, { "midictrl.i",S(MIDICTL),0,1, "i", "ioh", imidictl }, { "midictrl.k",S(MIDICTL),0,3, "k", "ioh", mctlset, midictl }, { "polyaft.i",S(MIDICTL),0,1, "i", "ioh", imidiaft }, { "polyaft.k",S(MIDICTL),0,3, "k", "ioh", maftset, midiaft }, { "chanctrl.i",S(CHANCTL),0,1, "i", "iioh", ichanctl }, { "chanctrl.k",S(CHANCTL),0,3, "k", "iioh", chctlset,chanctl }, { "line", S(LINE),0, 3, "k", "iii", linset, kline, NULL }, { "line.a", S(LINE),0, 5, "a", "iii", linset, NULL, aline }, { "expon", S(EXPON),0, 3, "k", "iii", expset, kexpon, NULL }, { "expon.a", S(EXPON),0, 5, "a", "iii", expset, NULL, expon }, { "cosseg", S(COSSEG),0, 3, "k", "iim", csgset, kosseg, NULL }, { "cosseg.a", S(COSSEG),0, 5, "a", "iim", csgset, NULL, cosseg }, { "cossegb", S(COSSEG),0, 3, "k", "iim", csgset_bkpt, kosseg, NULL }, { "cossegb.a", S(COSSEG),0, 5, "a", "iim", csgset_bkpt, NULL, cosseg }, { "cossegr", S(COSSEG),0, 3, "k", "iim", csgrset, kcssegr, NULL }, { "cossegr.a", S(COSSEG),0, 5, "a", "iim", csgrset, NULL, cossegr }, { "linseg", S(LINSEG),0, 3, "k", "iim", lsgset, klnseg, NULL }, { "linseg.a", S(LINSEG),0, 5, "a", "iim", lsgset, NULL, linseg }, { "linsegb", S(LINSEG),0, 3, "k", "iim", lsgset_bkpt, klnseg, NULL }, { "linsegb.a", S(LINSEG),0, 5, "a", "iim", lsgset_bkpt, NULL, linseg }, { "linsegr",S(LINSEG),0, 3, "k", "iim", lsgrset,klnsegr,NULL }, { "linsegr.a",S(LINSEG),0, 5, "a", "iim", lsgrset,NULL,linsegr }, { "expseg", S(EXXPSEG),0, 3, "k", "iim", xsgset, kxpseg, NULL }, { "expseg.a", S(EXXPSEG),0, 5, "a", "iim", xsgset, NULL, expseg }, { "expsegb", S(EXXPSEG),0, 3, "k", "iim", xsgset_bkpt, kxpseg, NULL }, { "expsegb.a", S(EXXPSEG),0, 5, "a", "iim", xsgset_bkpt, NULL, expseg }, { "expsega",S(EXPSEG2),0, 5, "a", "iim", xsgset2, NULL, expseg2 }, { "expsegba",S(EXPSEG2),0, 5, "a", "iim", xsgset2b, NULL, expseg2 }, { "expsegr",S(EXPSEG),0, 3, "k", "iim", xsgrset,kxpsegr,NULL }, { "expsegr.a",S(EXPSEG),0, 5, "a", "iim", xsgrset,NULL,expsegr }, { "linen", S(LINEN),0, 3, "k", "kiii", lnnset, klinen, NULL }, { "linen.a", S(LINEN),0, 5, "a", "aiii", alnnset, NULL, linen }, { "linen.x", S(LINEN),0, 5, "a", "kiii", alnnset, NULL, linen }, { "linenr", S(LINENR),0, 3, "k", "kiii", lnrset, klinenr,NULL }, { "linenr.a", S(LINENR),0, 5, "a", "aiii", alnrset, NULL,linenr }, { "linenr.x", S(LINENR),0, 5, "a", "kiii", alnrset, NULL,linenr }, { "envlpx", S(ENVLPX), TR, 3, "k","kiiiiiio", evxset, knvlpx, NULL }, { "envlpxr", S(ENVLPR),TR, 3, "k","kiiiiioo", evrset, knvlpxr, NULL }, { "envlpx.a", S(ENVLPX), TR, 5, "a","aiiiiiio", aevxset, NULL,envlpx }, { "envlpxr.a", S(ENVLPR),TR, 5, "a","aiiiiioo", aevrset, NULL,envlpxr }, { "envlpx.x", S(ENVLPX), TR, 5, "a","kiiiiiio", aevxset, NULL,envlpx }, { "envlpxr.x", S(ENVLPR),TR, 5, "a","kiiiiioo", aevrset, NULL,envlpxr }, { "phasor", S(PHSOR),0, 5, "a", "xo", phsset, NULL, phsor }, { "phasor.k", S(PHSOR),0, 3, "k", "ko", phsset, kphsor, NULL }, { "ephasor", S(EPHSOR), 0, 5, "aa", "xko", ephsset, NULL, ephsor }, { "signum.i", S(ASSIGN), 0, 1, "i", "i", signum, NULL, NULL }, { "signum.k", S(ASSIGN), 0, 3, "k", "k", signum, signum, NULL }, { "signum.a", S(ASSIGN), 0, 4, "a", "a", NULL, NULL, asignum }, /* { "table", 0xffff, TR }, */ /* { "tablei", 0xffff, TR }, */ /* { "table3", 0xffff, TR }, */ { "table.i", S(TABL),0, 1, "i", "iiooo",(SUBR)tabler_init }, { "table.k", S(TABL),0, 3, "k", "xiooo",(SUBR)tabl_setup, (SUBR)tabler_kontrol }, { "table.a", S(TABL),0, 5, "a", "xiooo",(SUBR)tabl_setup, NULL, (SUBR)tabler_audio }, { "tablei.i", S(TABL),0, 1, "i", "iiooo",(SUBR)tableir_init }, { "tablei.k", S(TABL),0, 3, "k", "xiooo",(SUBR)tabl_setup, (SUBR)tableir_kontrol }, { "tablei.a", S(TABL),0, 5, "a", "xiooo",(SUBR)tabl_setup, NULL, (SUBR)tableir_audio }, { "table3.i", S(TABL),0, 1, "i", "iiooo",(SUBR)table3r_init }, { "table3.k", S(TABL),0, 3, "k", "xiooo",(SUBR)tabl_setup, (SUBR)table3r_kontrol }, { "table3.a", S(TABL),0, 5, "a", "xiooo",(SUBR)tabl_setup, NULL, (SUBR)table3r_audio }, /* { "ptable", 0xffff, TR }, */ /* { "ptablei", 0xffff, TR }, */ /* { "ptable3", 0xffff, TR }, */ { "ptable.i", S(TABLE),0, 1, "i", "iiooo",(SUBR)tabler_init }, { "ptable.k", S(TABLE),0, 3, "k", "xiooo",(SUBR)tabl_setup, (SUBR)tabler_kontrol }, { "ptable.a", S(TABLE),0, 5, "a", "xiooo",(SUBR)tabl_setup, NULL, (SUBR)tabler_audio }, { "ptablei.i", S(TABLE),0, 1, "i", "iiooo",(SUBR)tableir_init }, { "ptablei.k", S(TABLE),0, 3, "k", "xiooo",(SUBR)tabl_setup, (SUBR)tableir_kontrol }, { "ptablei.a", S(TABLE),0, 5, "a", "xiooo",(SUBR)tabl_setup, NULL, (SUBR)tableir_audio }, { "ptable3.i", S(TABLE),0, 1, "i", "iiooo",(SUBR)table3r_init }, { "ptable3.k", S(TABLE),0, 3, "k", "xiooo",(SUBR)tabl_setup, (SUBR)table3r_kontrol }, { "ptable3.a", S(TABLE),0, 5, "a", "xiooo",(SUBR)tabl_setup, NULL, (SUBR)table3r_audio }, { "oscil1", S(OSCIL1), TR, 3, "k", "ikij", ko1set, kosc1 }, { "oscil1i",S(OSCIL1), TR, 3, "k", "ikij", ko1set, kosc1i }, { "osciln", S(OSCILN), TR, 5, "a", "kiii", oscnset,NULL, osciln }, { "oscil.a",S(OSC),0, 5, "a", "kkjo", oscset, NULL, osckk }, { "oscil.kk",S(OSC),0, 7, "s", "kkjo", oscset, koscil, osckk }, { "oscil.ka",S(OSC),0, 5, "a", "kajo", oscset, NULL, oscka }, { "oscil.ak",S(OSC),0, 5, "a", "akjo", oscset, NULL, oscak }, { "oscil.aa",S(OSC),0, 5, "a", "aajo", oscset, NULL, oscaa }, { "oscil.kkA",S(OSC),0, 7, "a", "kki[]o", oscsetA, koscil, osckk }, { "oscil.kaA",S(OSC),0, 5, "a", "kai[]o", oscsetA, NULL, oscka }, { "oscil.akA",S(OSC),0, 5, "a", "aki[]o", oscsetA, NULL, oscak }, { "oscil.aaA",S(OSC),0, 5, "a", "aai[]o", oscsetA, NULL,oscaa }, /* Change these to { "oscil.kk", S(POSC),0, 7, "s", "kkjo", posc_set, kposc, posckk }, { "oscil.ka", S(POSC),0, 5, "a", "kajo", posc_set, NULL, poscka }, { "oscil.ak", S(POSC),0, 5, "a", "akjo", posc_set, NULL, poscak }, { "oscil.aa", S(POSC),0, 5, "a", "aajo", posc_set, NULL, poscaa }, { "oscil3.kk", S(POSC),0, 7, "s", "kkjo", posc_set, kposc3, posc3 }, */ { "oscili.a",S(OSC),0, 5, "a", "kkjo", oscset, NULL, osckki }, { "oscili.kk",S(OSC),0, 3, "k", "kkjo", oscset, koscli, NULL }, { "oscili.ka",S(OSC),0, 5, "a", "kajo", oscset, NULL, osckai }, { "oscili.ak",S(OSC),0, 5, "a", "akjo", oscset, NULL, oscaki }, { "oscili.aa",S(OSC),0, 5, "a", "aajo", oscset, NULL, oscaai }, { "oscili.aA",S(OSC),0, 5, "a", "kki[]o", oscsetA, NULL, osckki }, { "oscili.kkA",S(OSC),0, 3, "k", "kki[]o", oscsetA, koscli, NULL }, { "oscili.kaA",S(OSC),0, 5, "a", "kai[]o", oscsetA, NULL, osckai }, { "oscili.akA",S(OSC),0, 5, "a", "aki[]o", oscsetA, NULL, oscaki }, { "oscili.aaA",S(OSC),0, 5, "a", "aai[]o", oscsetA, NULL, oscaai }, { "oscil3.a",S(OSC),0, 5, "a", "kkjo", oscset, NULL, osckk3 }, { "oscil3.kk",S(OSC),0, 3, "k", "kkjo", oscset, koscl3, NULL }, { "oscil3.ka",S(OSC),0, 5, "a", "kajo", oscset, NULL, oscka3 }, { "oscil3.ak",S(OSC),0, 5, "a", "akjo", oscset, NULL, oscak3 }, { "oscil3.aa",S(OSC),0, 5, "a", "aajo", oscset, NULL, oscaa3 }, { "oscil3.aA",S(OSC),0, 5, "a", "kki[]o", oscsetA, NULL, osckk3 }, { "oscil3.kkA",S(OSC),0, 3, "k", "kki[]o", oscsetA, koscl3, NULL }, { "oscil3.kaA",S(OSC),0, 5, "a", "kai[]o", oscsetA, NULL, oscka3 }, { "oscil3.akA",S(OSC),0, 5, "a", "aki[]o", oscsetA, NULL, oscak3 }, { "oscil3.aaA",S(OSC),0, 5, "a", "aai[]o", oscsetA, NULL, oscaa3 }, /* end change */ { "foscil", S(FOSC),TR, 5, "a", "xkxxkjo",foscset,NULL, foscil }, { "foscili",S(FOSC),TR, 5, "a", "xkxxkjo",foscset,NULL, foscili }, { "loscil", S(LOSC),TR, 5, "mm","xkjojoojoo",losset,NULL, loscil }, { "loscil3", S(LOSC),TR, 5, "mm","xkjojoojoo",losset,NULL, loscil3 }, { "adsyn", S(ADSYN),0, 5, "a", "kkkSo", adset_S, NULL, adsyn }, { "adsyn.i", S(ADSYN),0, 5, "a", "kkkio", adset, NULL, adsyn }, { "buzz", S(BUZZ),TR, 5, "a", "xxkio", bzzset, NULL, buzz }, { "gbuzz", S(GBUZZ),TR, 5, "a", "xxkkkio",gbzset, NULL, gbuzz }, { "pluck", S(PLUCK), TR, 5, "a", "kkiiioo",plukset,NULL, pluck }, { "rand", S(RAND),0, 5, "a", "xvoo", rndset, NULL, arand }, { "rand.k", S(RAND),0, 3, "k", "xvoo", rndset, krand, NULL }, { "randh", S(RANDH),0, 5, "a", "xxvoo", rhset, NULL, randh }, { "randh.k", S(RANDH),0, 3, "k", "xxvoo", rhset, krandh, NULL }, { "randi", S(RANDI),0, 5, "a", "xxvoo", riset, NULL, randi }, { "randi.k", S(RANDI),0, 3, "k", "xxvoo", riset, krandi, NULL }, { "port", S(PORT),0, 3, "k", "kio", porset, port }, { "tone.k", S(TONE),0, 5, "a", "ako", tonset, NULL, tone }, { "tonex.k",S(TONEX),0, 5, "a", "akoo", tonsetx, NULL, tonex }, { "atone.k", S(TONE),0, 5, "a", "ako", tonset, NULL, atone }, { "atonex.k", S(TONEX),0, 5, "a", "akoo", tonsetx, NULL, atonex }, { "reson", S(RESON), 0, 5, "a", "axxoo", rsnset, NULL, reson }, { "resonx", S(RESONX),0, 5, "a", "axxooo", rsnsetx, NULL, resonx }, { "areson.kk", S(RESON),0,5, "a", "akkoo",rsnset, NULL, areson }, { "lpread", S(LPREAD),0, 3, "kkkk", "kSoo", lprdset_S,lpread }, { "lpread.i", S(LPREAD),0, 3, "kkkk", "kioo", lprdset,lpread }, { "lpform", S(LPFORM),0, 3, "kk", "k", lpformantset,lpformant }, { "lpreson",S(LPRESON),0, 5, "a", "a", lprsnset,NULL, lpreson }, { "lpfreson",S(LPFRESON),0,5, "a", "ak", lpfrsnset,NULL, lpfreson}, { "lpslot" , S(LPSLOT),0, 1, "", "i", lpslotset, NULL, NULL }, { "lpinterp", S(LPINTERPOL),0, 3, "", "iik", lpitpset, lpinterpol, NULL}, { "rms", S(RMS),0, 3, "k", "aqo", rmsset, rms }, { "gain", S(GAIN),0, 5, "a", "akqo", gainset,NULL, gain }, { "balance",S(BALANCE),0, 5, "a", "aaqo", balnset,NULL, balance }, { "pan", S(PAN),0, 5, "aaaa", "akkioo",(SUBR)panset,NULL, (SUBR)pan }, { "soundin",S(DISKIN2),0,5,"mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm","Soooo", sndinset_S, NULL, soundin }, { "soundin.i",S(DISKIN2),0,5,"mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm","ioooo", sndinset, NULL, soundin }, { "soundout",S(SNDOUT), _QQ, 5, "", "aSo", sndoutset_S, NULL, soundout }, { "soundout.i",S(SNDOUT), _QQ, 5, "", "aio", sndoutset, NULL, soundout }, { "soundouts",S(SNDOUTS),_QQ, 5, "", "aaSo", sndoutset_S, NULL, soundouts }, { "soundouts.i",S(SNDOUTS),_QQ, 5, "", "aaio", sndoutset, NULL, soundouts }, { "in.a", S(INM),0, 4, "a", "", NULL, NULL, in }, { "in.s", S(INM),0, 4, "aa", "", NULL, NULL, ins }, { "in.A", S(INM),0, 4, "a[]", "", NULL, NULL, inarray }, { "ins", S(INS),0, 4, "aa", "", NULL, NULL, ins }, { "inq", S(INQ),0, 4, "aaaa", "", NULL, NULL, inq }, { "out.a", S(OUTX),0, 5, "", "y", ochn, NULL, outall }, { "out.A", S(OUTARRAY),0, 4, "", "a[]", NULL, NULL, outarr }, { "outs", S(OUTX),0, 5, "", "y", ochn, NULL, outall }, { "outq", S(OUTX),0, 5, "", "y", ochn, NULL, outall }, { "outh", S(OUTX),0, 5, "", "y", ochn, NULL, outall }, { "outo", S(OUTX),0, 5, "", "y", ochn, NULL, outall }, { "outx", S(OUTX),0, 5, "", "y", ochn, NULL, outall }, { "out32", S(OUTX),0, 5, "", "y", ochn, NULL, outall }, { "outs1", S(OUTM),0, 4, "", "a", NULL, NULL, outs1 }, { "outs2", S(OUTM),0, 5, "", "a", och2, NULL, outs2 }, { "outq1", S(OUTM),0, 4, "", "a", NULL, NULL, outs1 }, { "outq2", S(OUTM),0, 5, "", "a", och2, NULL, outs2 }, { "outq3", S(OUTM),0, 5, "", "a", och3, NULL, outq3 }, { "outq4", S(OUTM),0, 5, "", "a", och4, NULL, outq4 }, { "igoto", S(GOTO),0, 1, "", "l", igoto }, { "kgoto", S(GOTO),0, 2, "", "l", NULL, kgoto }, { "goto", S(GOTO),0, 3, "", "l", igoto, kgoto }, { "cigoto", S(CGOTO),0, 1, "", "Bl", icgoto }, { "ckgoto", S(CGOTO),0, 2, "", "Bl", NULL, kcgoto }, { "cggoto.0", S(CGOTO),0, 3, "", "Bl", icgoto, kcgoto }, { "timout", S(TIMOUT),0, 3, "", "iil", timset, timout }, { "reinit", S(GOTO),0, 2, "", "l", NULL, reinit }, { "rigoto", S(GOTO),0, 1, "", "l", rigoto }, { "rireturn",S(LINK),0, 1, "", "", rireturn }, { "tigoto", S(GOTO),0, 1, "", "l", tigoto }, { "tival", S(EVAL),0, 1, "i", "", tival }, { "print", S(PRINTV),WR, 1, "", "m", printv }, { "display",S(DSPLAY),0, 7, "", "xioo", dspset, kdsplay,dsplay }, { "pvsdisp",S(FSIGDISP),0, 3, "", "foo", fdspset, fdsplay,NULL }, { "dispfft",S(DSPFFT),0, 7, "", "xiiooooo",fftset,kdspfft,dspfft }, { "dumpk", S(KDUMP),0, 3, "", "kSii", kdmpset_S,kdump }, { "dumpk2", S(KDUMP2),0, 3, "", "kkSii",kdmp2set_S,kdump2 }, { "dumpk3", S(KDUMP3),0, 3, "", "kkkSii",kdmp3set_S,kdump3 }, { "dumpk4", S(KDUMP4),0, 3, "", "kkkkSii",kdmp4set_S,kdump4 }, { "dumpk.i", S(KDUMP),0, 3, "", "kiii", kdmpset_p,kdump }, { "dumpk2.i", S(KDUMP2),0, 3, "", "kkiii",kdmp2set_p,kdump2 }, { "dumpk3.i", S(KDUMP3),0, 3, "", "kkkiii",kdmp3set_p,kdump3 }, { "dumpk4.i", S(KDUMP4),0, 3, "", "kkkkiii",kdmp4set_p,kdump4 }, { "readk", S(KREAD),0, 3, "k", "Sii", krdset_S, kread }, { "readk2", S(KREAD2),0, 3, "kk", "Sii", krd2set_S, kread2 }, { "readk3", S(KREAD3),0, 3, "kkk", "Sii", krd3set_S, kread3 }, { "readk4", S(KREAD4),0, 3, "kkkk", "Sii", krd4set_S, kread4 }, { "readk.i", S(KREAD),0, 3, "k", "iii", krdset_p, kread }, { "readk2.i", S(KREAD2),0, 3, "kk", "iii", krd2set_p, kread2 }, { "readk3.i", S(KREAD3),0, 3, "kkk", "iii", krd3set_p, kread3 }, { "readk4.i", S(KREAD4),0, 3, "kkkk", "iii", krd4set_p, kread4 }, { "readks", S(KREADS),0, 3, "S", "Si", krdsset_S, kreads }, { "readks.i", S(KREADS),0, 3, "S", "ii", krdsset_p, kreads }, { "xyin", S(XYIN), _QQ, 1, "kk", "iiiiioo",xyinset,NULL }, { "tempest", S(TEMPEST),0, 5, "k","kiiiiiiiiiop",tempeset,NULL,tempest}, { "tempo", S(TEMPO),0, 3, "", "ki", tempset,tempo }, { "pow.i", S(POW),0, 1, "i", "iip", ipow, NULL, NULL }, { "pow.k", S(POW),0, 2, "k", "kkp", NULL, ipow, NULL }, { "pow.a", S(POW),0, 4, "a", "akp", NULL, NULL, apow }, { "##pow.i", S(POW),0, 1, "i", "iip", ipow, NULL, NULL }, { "##pow.k", S(POW),0, 2, "k", "kkp", NULL, ipow, NULL }, { "##pow.a", S(POW),0, 4, "a", "akp", NULL, NULL, apow }, { "oscilx", S(OSCILN), TR, 5, "a", "kiii", oscnset,NULL, osciln }, { "linrand.i",S(PRAND),0, 1, "i", "k", iklinear, NULL, NULL }, { "linrand.k",S(PRAND),0, 2, "k", "k", NULL, iklinear, NULL }, { "linrand.a",S(PRAND),0, 4, "a", "k", NULL, NULL, alinear }, { "trirand.i",S(PRAND),0, 1, "i", "k", iktrian, NULL, NULL }, { "trirand.k",S(PRAND),0, 2, "k", "k", NULL, iktrian, NULL }, { "trirand.a",S(PRAND),0, 4, "a", "k", NULL, NULL, atrian }, { "exprand.i",S(PRAND),0, 1, "i", "k", ikexp, NULL, NULL }, { "exprand.k",S(PRAND),0, 2, "k", "k", NULL, ikexp, NULL }, { "exprand.a",S(PRAND),0, 4, "a", "k", NULL, NULL, aexp }, { "bexprnd.i",S(PRAND),0, 1, "i", "k", ikbiexp, NULL, NULL }, { "bexprnd.k",S(PRAND),0, 2, "k", "k", NULL, ikbiexp, NULL }, { "bexprnd.a",S(PRAND),0, 4, "a", "k", NULL, NULL, abiexp }, { "cauchy.i", S(PRAND),0, 1, "i", "k", ikcauchy, NULL, NULL }, { "cauchy.k", S(PRAND),0, 2, "k", "k", NULL, ikcauchy, NULL }, { "cauchy.a", S(PRAND),0, 4, "a", "k", NULL, NULL, acauchy }, { "pcauchy.i",S(PRAND),0, 1, "i", "k", ikpcauchy, NULL,NULL }, { "pcauchy.k",S(PRAND),0, 2, "k", "k", NULL, ikpcauchy,NULL }, { "pcauchy.a",S(PRAND),0, 4, "a", "k", NULL, NULL, apcauchy}, { "poisson.i",S(PRAND),0, 1, "i", "k", ikpoiss, NULL, NULL }, { "poisson.k",S(PRAND),0, 2, "k", "k", NULL, ikpoiss, NULL }, { "poisson.a",S(PRAND),0, 4, "a", "k", NULL, NULL, apoiss }, { "gauss.i" , S(PRAND),0, 1, "i", "k", ikgaus, NULL, NULL }, { "gauss.k" , S(PRAND),0, 2, "k", "k", NULL, ikgaus, NULL }, { "gauss.a" , S(PRAND),0, 4, "a", "k", NULL, NULL, agaus }, { "weibull.i",S(PRAND),0, 1, "i", "kk", ikweib, NULL, NULL }, { "weibull.k",S(PRAND),0, 2, "k", "kk", NULL, ikweib, NULL }, { "weibull.a",S(PRAND),0, 4, "a", "kk", NULL, NULL, aweib }, { "betarand.i",S(PRAND),0,1, "i", "kkk", ikbeta, NULL, NULL }, { "betarand.k",S(PRAND),0,2, "k", "kkk", NULL, ikbeta,NULL }, { "betarand.a",S(PRAND),0,4, "a", "kkk", NULL, NULL, abeta }, { "seed", S(PRAND),0, 1, "", "i", seedrand, NULL, NULL }, { "getseed.i",S(GETSEED),0, 1, "i", "", getseed, NULL, NULL }, { "getseed.k",S(GETSEED),0, 3, "k", "", getseed, getseed, NULL }, { "unirand.i",S(PRAND),0, 1, "i", "k", ikuniform, NULL, NULL }, { "unirand.k",S(PRAND),0, 2, "k", "k", NULL, ikuniform, NULL}, { "unirand.a",S(PRAND),0, 4, "a", "k", NULL, NULL, auniform }, { "diskin",S(DISKIN2_ARRAY),0, 5, "a[]", "SPooooooo", (SUBR) diskin_init_array_S, (SUBR) NULL, (SUBR) diskin2_perf_array }, { "diskin2",S(DISKIN2_ARRAY),0, 5, "a[]", "SPooooooo", (SUBR) diskin2_init_array_S, (SUBR) NULL, (SUBR) diskin2_perf_array }, { "diskin.i",S(DISKIN2_ARRAY),0, 5, "a[]", "iPooooooo", (SUBR) diskin_init_array_I, (SUBR) NULL, (SUBR) diskin2_perf_array }, { "diskin2.i",S(DISKIN2_ARRAY),0, 5, "a[]", "iPooooooo", (SUBR) diskin2_init_array_I, (SUBR) NULL, (SUBR) diskin2_perf_array }, { "diskin",S(DISKIN2),0, 5, "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", "SPooooooo", (SUBR) diskin_init_S, (SUBR) NULL, (SUBR) diskin2_perf }, { "diskin2",S(DISKIN2),0, 5, "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", "SPooooooo", (SUBR) diskin2_init_S, (SUBR) NULL, (SUBR) diskin2_perf }, { "diskin.i",S(DISKIN2),0, 5, "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", "iPooooooo", (SUBR) diskin_init, (SUBR) NULL, (SUBR) diskin2_perf }, { "diskin2.i",S(DISKIN2),0, 5, "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", "iPooooooo", (SUBR) diskin2_init, (SUBR) NULL, (SUBR) diskin2_perf }, { "noteon", S(OUT_ON),0, 1, "", "iii", iout_on, NULL, NULL }, { "noteoff", S(OUT_ON),0, 1, "", "iii", iout_off, NULL, NULL }, { "noteondur",S(OUT_ON_DUR),0,3, "", "iiii", iout_on_dur_set,iout_on_dur,NULL}, { "noteondur2",S(OUT_ON_DUR),0,3, "", "iiii", iout_on_dur_set,iout_on_dur2,NULL}, { "moscil",S(MOSCIL),0, 3, "", "kkkkk",moscil_set, moscil, NULL}, { "midion",S(KOUT_ON),0, 3, "", "kkk", kvar_out_on_set,kvar_out_on,NULL}, { "outic",S(OUT_CONTR),0, 1, "", "iiiii", out_controller, NULL, NULL}, { "outkc",S(OUT_CONTR),0, 2, "", "kkkkk", NULL, out_controller, NULL}, { "outic14",S(OUT_CONTR14),0,1, "", "iiiiii",out_controller14, NULL,NULL}, { "outkc14",S(OUT_CONTR14),0,2, "", "kkkkkk",NULL, out_controller14, NULL}, { "outipb",S(OUT_PB),0, 1, "", "iiii", out_pitch_bend, NULL , NULL}, { "outkpb",S(OUT_PB),0, 2, "", "kkkk", NULL, out_pitch_bend, NULL}, { "outiat",S(OUT_ATOUCH),0,1, "", "iiii", out_aftertouch, NULL , NULL}, { "outkat",S(OUT_ATOUCH),0,2, "", "kkkk", NULL, out_aftertouch, NULL}, { "outipc",S(OUT_PCHG),0, 1, "", "iiii", out_progchange, NULL , NULL}, { "outkpc",S(OUT_PCHG),0, 2, "", "kkkk", NULL, out_progchange, NULL}, { "outipat",S(OUT_POLYATOUCH),0,1,"", "iiiii", out_poly_aftertouch, NULL,NULL}, { "outkpat",S(OUT_POLYATOUCH),0,2,"", "kkkkk", NULL, out_poly_aftertouch,NULL}, { "release",S(REL),0, 3, "k", "", release_set, release, NULL }, { "xtratim",S(XTRADUR),0, 1, "", "i", xtratim, NULL, NULL }, { "mclock", S(MCLOCK),0, 3, "", "i", mclock_set, mclock, NULL }, { "mrtmsg", S(XTRADUR),0, 1, "", "i", mrtmsg, NULL, NULL }, { "midiout",S(MIDIOUT),0, 2, "", "kkkk", NULL, midiout, NULL }, { "midiout_i",S(MIDIOUT), 0, 1, "", "iiii", midiout, NULL, NULL }, { "midion2", S(KON2),0, 3, "", "kkkk", kon2_set, kon2, NULL }, { "nrpn", S(NRPN),0, 2, "", "kkk", NULL, nrpn ,NULL }, { "mdelay", S(MDELAY),0, 3, "", "kkkkk",mdelay_set, mdelay, NULL }, { "nsamp.i", S(EVAL),0, 1, "i", "i", numsamp }, { "powoftwo.i",S(EVAL),0, 1, "i", "i", powoftwo }, { "powoftwo.k",S(EVAL),0, 2, "k", "k", NULL, powoftwo }, { "powoftwo.a",S(EVAL),0, 4, "a", "a", NULL, NULL, powoftwoa }, { "logbtwo.i",S(EVAL),0, 1, "i", "i", ilogbasetwo }, { "logbtwo.k",S(EVAL),0, 3, "k", "k", logbasetwo_set, logbasetwo }, { "logbtwo.a",S(EVAL),0, 5, "a", "a", logbasetwo_set, NULL, logbasetwoa }, { "filelen", S(SNDINFO),0, 1, "i", "Sp", filelen_S, NULL, NULL }, { "filenchnls", S(SNDINFO),0, 1, "i", "Sp", filenchnls_S, NULL, NULL }, { "filesr", S(SNDINFO),0, 1, "i", "Sp", filesr_S, NULL, NULL }, { "filebit", S(SNDINFO),0, 1, "i", "Sp", filebit_S, NULL, NULL }, { "filepeak", S(SNDINFOPEAK),0, 1, "i", "So", filepeak_S, NULL, NULL }, { "filevalid", S(FILEVALID),0, 1, "i", "S", filevalid_S, NULL, NULL }, { "filelen.i", S(SNDINFO),0, 1, "i", "ip", filelen, NULL, NULL }, { "filenchnls.i", S(SNDINFO),0, 1, "i", "ip", filenchnls, NULL, NULL }, { "filesr.i", S(SNDINFO),0, 1, "i", "ip", filesr, NULL, NULL }, { "filebit.i", S(SNDINFO),0, 1, "i", "ip", filebit, NULL, NULL }, { "filepeak.i", S(SNDINFOPEAK),0, 1, "i", "io", filepeak, NULL, NULL }, { "filevalid.i", S(FILEVALID),0, 1, "i", "i", filevalid, NULL, NULL }, /* { "nlalp", S(NLALP),0, 5, "a", "akkoo", nlalp_set, NULL, nlalp }, */ { "ptableiw", S(TABLEW),TW, 1, "", "iiiooo", (SUBR)tablew_init, NULL, NULL}, { "ptablew.kk", S(TABLEW),0, 3, "", "kkiooo",(SUBR)tabl_setup, (SUBR)tablew_kontrol, NULL }, { "ptablew.aa", S(TABLEW),0, 5, "", "aaiooo",(SUBR)tabl_setup, NULL, (SUBR)tablew_audio }, { "tableiw", S(TABL),TW, 1, "", "iiiooo", (SUBR)tablew_init, NULL, NULL}, { "tablew", S(TABL),TW, 1, "", "iiiooo", (SUBR)tablew_init, NULL, NULL}, { "tablew.kk", S(TABL),TW, 3, "", "kkiooo",(SUBR)tabl_setup, (SUBR)tablew_kontrol, NULL }, { "tablew.aa", S(TABL),TW, 5, "", "aaiooo",(SUBR)tabl_setup, NULL, (SUBR)tablew_audio }, { "tablewkt.kk", S(TABL),TW,3, "", "kkkooo", (SUBR)tablkt_setup,(SUBR)tablewkt_kontrol,NULL}, { "tablewkt.aa", S(TABL),TW,5, "", "aakooo", (SUBR)tablkt_setup,NULL,(SUBR)tablewkt_audio}, { "tableng.i", S(TLEN),TR,1, "i", "i", (SUBR)table_length, NULL, NULL}, { "tableng.k", S(TLEN),TR,2, "k", "k", NULL, (SUBR)table_length, NULL}, { "tableigpw",S(TGP), TB, 1, "", "i", (SUBR)table_gpw, NULL, NULL}, { "tablegpw", S(TGP), TB,2, "", "k", NULL, (SUBR)table_gpw, NULL}, { "tableimix",S(TABLMIX),TB, 1, "", "iiiiiiiii", (SUBR)table_mix, NULL, NULL}, { "tablemix", S(TABLMIX),TB, 2, "", "kkkkkkkkk", NULL, (SUBR)table_mix, NULL}, { "tableicopy",S(TGP),TB, 1, "", "ii", (SUBR)table_copy, NULL, NULL}, { "tablecopy", S(TGP),TB, 2, "", "kk", NULL, (SUBR)table_copy, NULL}, { "tablera", S(TABLRA),TR, 5, "a", "kkk", (SUBR)table_ra_set, NULL, (SUBR)table_ra}, { "tablewa", S(TABLWA),TW, 5, "k", "kakp", (SUBR)table_wa_set, NULL, (SUBR)table_wa}, { "tablekt", S(TABL),TR, 3, "k", "xkooo", (SUBR)tablkt_setup, (SUBR)tablerkt_kontrol, NULL }, { "tablekt.a", S(TABL),TR, 5, "a", "xkooo", (SUBR)tablkt_setup, NULL, (SUBR)tablerkt_audio }, { "tableikt", S(TABL),TR, 3, "k", "xkooo", (SUBR)tablkt_setup, (SUBR)tableirkt_kontrol, NULL }, { "tableikt.a", S(TABL),TR, 5, "a", "xkooo", (SUBR)tablkt_setup, NULL, (SUBR)tableirkt_audio }, { "table3kt", S(TABL),TR, 3, "k", "xkooo", (SUBR)tablkt_setup, (SUBR)table3rkt_kontrol, NULL }, { "table3kt.a", S(TABL),TR, 5, "a", "xkooo", (SUBR)tablkt_setup, NULL, (SUBR)table3rkt_audio }, { "zakinit", S(ZAKINIT), ZB, 1, "", "ii", (SUBR)zakinit, NULL, NULL }, { "zir", S(ZKR),ZR, 1, "i", "i", (SUBR)zir, NULL, NULL }, { "zkr", S(ZKR),ZR, 3, "k", "k", (SUBR)zkset, (SUBR)zkr, NULL}, { "ziw", S(ZKW),ZW, 1, "", "ii", (SUBR)ziw, NULL, NULL }, { "zkw", S(ZKW), ZW, 3, "", "kk", (SUBR)zkset, (SUBR)zkw, NULL}, { "ziwm", S(ZKWM), ZB, 1, "", "iip", (SUBR)ziwm, NULL, NULL }, { "zkwm", S(ZKWM), ZB, 3, "", "kkp", (SUBR)zkset, (SUBR)zkwm, NULL}, { "zkmod", S(ZKMOD), ZB, 2, "k", "kk", NULL, (SUBR)zkmod, NULL }, { "zkcl", S(ZKCL), ZW, 3, "", "kk", (SUBR)zkset, (SUBR)zkcl, NULL }, { "zar", S(ZAR),ZR, 5, "a", "k", (SUBR)zaset, NULL, (SUBR)zar }, { "zarg", S(ZARG), ZB, 5, "a", "kk", (SUBR)zaset, NULL, (SUBR)zarg }, { "zaw", S(ZAW), ZW, 5, "", "ak", (SUBR)zaset, NULL, (SUBR)zaw }, { "zawm", S(ZAWM), ZB, 5, "", "akp", (SUBR)zaset, NULL, (SUBR)zawm }, { "zamod", S(ZAMOD), ZB, 4, "a", "ak", NULL, NULL, (SUBR)zamod}, { "zacl", S(ZACL), ZW, 5, "", "kk", (SUBR)zaset, NULL, (SUBR)zacl}, { "inz", S(IOZ), ZW, 4, "", "k", (SUBR)zaset, NULL, (SUBR)inz }, { "outz", S(IOZ),ZR, 4, "", "k", (SUBR)zaset, NULL, (SUBR)outz }, { "timek.i", S(RDTIME),0, 1, "i", "", (SUBR)timek, NULL, NULL }, { "times.i", S(RDTIME),0, 1, "i", "", (SUBR)timesr, NULL, NULL }, { "timek.k", S(RDTIME),0, 2, "k", "", NULL, (SUBR)timek, NULL }, { "times.k", S(RDTIME),0, 2, "k", "", NULL, (SUBR)timesr,NULL }, { "timeinstk", S(RDTIME),0, 3, "k", "", (SUBR)instimset, (SUBR)instimek, NULL }, { "timeinsts", S(RDTIME),0, 3, "k", "", (SUBR)instimset, (SUBR)instimes, NULL }, { "peak.k", S(PEAK),0, 2, "k", "k", NULL, (SUBR)peakk, NULL }, { "peak.a", S(PEAK),0, 4, "k", "a", NULL, NULL, (SUBR)peaka }, { "printk", S(PRINTK),WR, 3,"", "iko", (SUBR)printkset, (SUBR)printk, NULL }, { "printks",S(PRINTKS),WR, 3, "", "SiM", (SUBR)printksset_S,(SUBR)printks, NULL }, { "printks2", sizeof(PRINTK3),0, 3, "", "Sk", (SUBR)printk3set, (SUBR)printk3 }, { "printks.i",S(PRINTKS),WR, 3, "", "iiM", (SUBR)printksset,(SUBR)printks, NULL }, { "prints",S(PRINTS),0, 1, "", "SM", (SUBR)printsset_S, NULL, NULL }, { "prints.i",S(PRINTS),0, 1, "", "iM", (SUBR)printsset, NULL, NULL }, { "printk2", S(PRINTK2), WR, 3, "", "ko", (SUBR)printk2set, (SUBR)printk2, NULL }, { "portk", S(KPORT),0, 3, "k", "kko", (SUBR)kporset, (SUBR)kport, NULL }, { "tonek", S(KTONE),0, 3, "k", "kko", (SUBR)ktonset, (SUBR)ktone, NULL }, { "atonek", S(KTONE),0, 3, "k", "kko", (SUBR)ktonset, (SUBR)katone, NULL}, { "resonk", S(KRESON),0, 3, "k", "kkkpo",(SUBR)krsnset, (SUBR)kreson, NULL}, { "aresonk",S(KRESON),0, 3, "k", "kkkpo",(SUBR)krsnset, (SUBR)kareson, NULL}, { "limit.i", S(LIMIT),0, 1, "i", "iii", (SUBR)klimit, NULL, NULL }, { "limit.k", S(LIMIT),0, 2, "k", "kkk", NULL, (SUBR)klimit, NULL }, { "limit.a", S(LIMIT),0, 4, "a", "akk", NULL, NULL, (SUBR)limit }, { "prealloc", S(AOP),0, 1, "", "iio", (SUBR)prealloc, NULL, NULL }, { "prealloc", S(AOP),0, 1, "", "Sio", (SUBR)prealloc_S, NULL, NULL }, /* opcode dspace thread outarg inargs isub ksub asub */ { "inh", S(INH),0, 4, "aaaaaa","", NULL, NULL, inh }, { "ino", S(INO),0, 4, "aaaaaaaa","", NULL, NULL, ino }, { "inx", S(INALL),0, 4, "aaaaaaaaaaaaaaaa","", NULL, NULL, in16 }, { "in32", S(INALL),0, 4, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "", NULL, NULL, in32 }, { "inch", S(INCH1),0, 5, "a", "k", inch1_set, NULL, (SUBR) inch_opcode1 }, { "inch.m", S(INCH),0, 5, "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", "z", inch_set, NULL, inch_opcode }, { "_in", S(INALL),0, 5, "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", "", inch_set, NULL, inall_opcode }, /* Note that there is code in rdorch.c that assumes that opcodes starting with the characters out followed by a s, q, h, o or x are in this group ***BEWARE*** CODE REMOVED 2011-Dec-14 */ { "outch", S(OUTCH),0, 4, "", "Z", NULL, NULL, outch }, { "outc", S(OUTX),0, 4, "", "y", ochn, NULL, outall }, { "cpsxpch", S(XENH),TR, 1, "i", "iiii", cpsxpch, NULL, NULL }, { "cps2pch", S(XENH),TR, 1, "i", "ii", cps2pch, NULL, NULL }, { "cpstun", S(CPSTUN), TR, 2, "k", "kkk", NULL, cpstun }, { "cpstuni",S(CPSTUNI), TR, 1, "i", "ii", cpstun_i, }, { "cpstmid", S(CPSTABLE),0, 1, "i", "i", (SUBR)cpstmid }, { "adsr", S(LINSEG),0, 3, "k", "iiiio",adsrset,klnseg, NULL }, { "adsr.a", S(LINSEG),0, 5, "a", "iiiio",adsrset,NULL, linseg }, { "madsr", S(LINSEG),0, 3, "k", "iiiioj", madsrset,klnsegr,NULL }, { "madsr.a", S(LINSEG),0, 5, "s", "iiiioj", madsrset,NULL, linsegr }, { "xadsr", S(EXXPSEG),0, 3, "k", "iiiio", xdsrset, kxpseg, NULL }, { "xadsr.a", S(EXXPSEG),0, 5, "a", "iiiio", xdsrset, NULL, expseg }, { "mxadsr", S(EXPSEG),0, 3, "k", "iiiioj", mxdsrset, kxpsegr, NULL}, { "mxadsr.a", S(EXPSEG),0, 5, "a", "iiiioj", mxdsrset, NULL, expsegr}, { "schedule", S(SCHED),0, 1, "", "iiim", schedule, NULL, NULL }, { "schedule.N", S(SCHED),0, 1, "", "iiiN", schedule_N, NULL, NULL }, { "schedule.S", S(SCHED),0, 1, "", "Siim", schedule_S, NULL, NULL }, { "schedule.SN", S(SCHED),0, 1, "", "SiiN", schedule_SN, NULL, NULL }, { "schedwhen", S(WSCHED),0,3, "", "kkkkm",ifschedule, kschedule, NULL }, { "schedwhen", S(WSCHED),0,3, "", "kSkkm",ifschedule, kschedule, NULL }, { "schedkwhen", S(TRIGINSTR),0, 3,"", "kkkkkz",triginset, ktriginstr, NULL }, { "schedkwhen.S", S(TRIGINSTR),0, 3,"", "kkkSkz", triginset_S, ktriginstr_S, NULL }, { "schedkwhennamed", S(TRIGINSTR),0, 3,"", "kkkkkz",triginset, ktriginstr, NULL }, { "schedkwhennamed.S", S(TRIGINSTR),0, 3,"", "kkkSkz",triginset_S, ktriginstr_S, NULL }, { "trigseq", S(TRIGSEQ),0, 3, "", "kkkkkz", trigseq_set, trigseq, NULL }, { "event", S(LINEVENT),0, 2, "", "Skz", NULL, eventOpcode, NULL }, { "event_i", S(LINEVENT),0,1, "", "Sim", eventOpcodeI, NULL, NULL }, { "event.S", S(LINEVENT),0, 2, "", "SSz", NULL, eventOpcode_S, NULL }, { "event_i.S", S(LINEVENT),0,1, "", "SSm", eventOpcodeI_S, NULL, NULL }, { "nstance", S(LINEVENT2),0,2, "k", "kkz", NULL, instanceOpcode, NULL }, { "nstance.i", S(LINEVENT2),0,1, "i", "iiim", instanceOpcode, NULL, NULL }, { "nstance.kS", S(LINEVENT2),0, 2, "k", "SSz", NULL, instanceOpcode_S, NULL }, { "nstance.S", S(LINEVENT2),0, 1, "i", "Siim", instanceOpcode_S, NULL, NULL}, { "turnoff.i", S(KILLOP),0,1, "", "i", kill_instance, NULL, NULL }, { "turnoff.k", S(KILLOP),0,2, "", "k", NULL, kill_instance, NULL}, { "lfo", S(LFO),0, 3, "k", "kko", lfoset, lfok, NULL }, { "lfo.a", S(LFO),0, 5, "a", "kko", lfoset, NULL, lfoa }, { "oscils", S(OSCILS),0, 5, "a", "iiio", (SUBR)oscils_set, NULL, (SUBR)oscils }, { "lphasor", S(LPHASOR),0,5, "a", "xooooooo" , (SUBR)lphasor_set, NULL, (SUBR)lphasor }, { "tablexkt", S(TABLEXKT),TR, 5, "a", "xkkiooo", (SUBR)tablexkt_set, NULL, (SUBR)tablexkt }, { "reverb2", S(NREV2),0, 5, "a", "akkoojoj", (SUBR)reverbx_set,NULL,(SUBR)reverbx }, { "nreverb", S(NREV2),0, 5, "a", "akkoojoj", (SUBR)reverbx_set,NULL,(SUBR) reverbx }, { "=.f", S(FASSIGN),0, 3, "f", "f", (SUBR)fassign_set, (SUBR)fassign }, { "init.f", S(FASSIGN),0, 1, "f", "f", (SUBR)fassign_set, NULL, NULL }, { "pvsanal", S(PVSANAL), 0, 5, "f", "aiiiioo", pvsanalset, NULL, pvsanal }, { "pvsynth", S(PVSYNTH),0, 5, "a", "fo", pvsynthset, NULL, pvsynth }, { "pvsadsyn", S(PVADS),0, 7, "a", "fikopo", pvadsynset, pvadsyn, pvadsyn}, { "pvscross", S(PVSCROSS),0,3, "f", "ffkk", pvscrosset, pvscross, NULL }, { "pvsfread", S(PVSFREAD),0,3, "f", "kSo", pvsfreadset_S, pvsfread, NULL}, { "pvsfread.i", S(PVSFREAD),0,3, "f", "kio", pvsfreadset, pvsfread, NULL}, { "pvsmaska", S(PVSMASKA),0,3, "f", "fik", pvsmaskaset, pvsmaska, NULL }, { "pvsftw", S(PVSFTW), TW, 3, "k", "fio", pvsftwset, pvsftw, NULL }, { "pvsftr", S(PVSFTR),TR, 3, "", "fio", pvsftrset, pvsftr, NULL }, { "pvsinfo", S(PVSINFO),0, 1, "iiii","f", pvsinfo, NULL, NULL }, { "octave", 0xffff }, { "semitone", 0xffff }, { "cent", 0xffff }, { "octave.i", S(EVAL),0, 1, "i", "i", powoftwo }, { "octave.k", S(EVAL),0, 2, "k", "k", NULL, powoftwo }, { "octave.a", S(EVAL),0, 4, "a", "a", NULL, NULL, powoftwoa }, { "semitone.i",S(EVAL),0, 1, "i", "i", semitone }, { "semitone.k",S(EVAL),0, 2, "k", "k", NULL, semitone }, { "semitone.a",S(EVAL),0, 4, "a", "a", NULL, NULL, asemitone }, { "cent.i", S(EVAL),0, 1, "i", "i", cent }, { "cent.k", S(EVAL),0, 2, "k", "k", NULL, cent }, { "cent.a", S(EVAL),0, 4, "a", "a", NULL, NULL, acent }, { "db", 0xffff }, { "db.i", S(EVAL),0, 1, "i", "i", db }, { "db.k", S(EVAL),0, 2, "k", "k", NULL, db }, { "db.a", S(EVAL),0, 4, "a", "a", NULL, NULL, dba }, { "midichn", S(MIDICHN),0, 1, "i", "", midichn, NULL, NULL }, { "pgmassign",S(PGMASSIGN),0, 1, "", "iio", pgmassign, NULL, NULL }, { "pgmassign.S",S(PGMASSIGN),0, 1, "", "iSo", pgmassign_S, NULL, NULL }, { "midiin", S(MIDIIN),0, 3, "kkkk", "", midiin_set, midiin, NULL }, { "pgmchn", S(PGMIN),0, 3, "kk", "o", pgmin_set, pgmin, NULL }, { "ctlchn", S(CTLIN),0, 3, "kkk", "oo", ctlin_set, ctlin, NULL }, { "miditempo", S(MIDITEMPO),0, 3, "k", "", (SUBR) midiTempoOpcode, (SUBR) midiTempoOpcode, NULL }, { "midifilestatus", S(MIDITEMPO),0, 2, "k", "", NULL, (SUBR) midiFileStatus, NULL }, { "midinoteoff", S(MIDINOTEON),0,3,"", "xx", midinoteoff, midinoteoff, }, { "midinoteonkey", S(MIDINOTEON),0,3, "", "xx", midinoteonkey, midinoteonkey }, { "midinoteoncps", S(MIDINOTEON),0, 3, "", "xx", midinoteoncps,midinoteoncps }, { "midinoteonoct", S(MIDINOTEON),0, 3, "", "xx", midinoteonoct,midinoteonoct }, { "midinoteonpch", S(MIDINOTEON),0, 3, "", "xx", midinoteonpch, midinoteonpch }, { "midipolyaftertouch", S(MIDIPOLYAFTERTOUCH),0, 3, "", "xxoh", midipolyaftertouch, midipolyaftertouch}, { "midicontrolchange", S(MIDICONTROLCHANGE),0, 3, "", "xxoh",midicontrolchange, midicontrolchange }, { "midiprogramchange", S(MIDIPROGRAMCHANGE),0, 3, "", "x", midiprogramchange, midiprogramchange }, { "midichannelaftertouch", S(MIDICHANNELAFTERTOUCH),0, 3, "", "xoh",midichannelaftertouch, midichannelaftertouch }, { "midipitchbend", S(MIDIPITCHBEND),0,3, "", "xoh", midipitchbend, midipitchbend }, { "mididefault", S(MIDIDEFAULT),0, 3, "", "xx", mididefault, mididefault }, { "invalue", 0xFFFF, _CR, 0, NULL, NULL, (SUBR) NULL, (SUBR) NULL }, { "invalue.k", S(INVAL),0, 3, "k", "i", (SUBR) invalset,(SUBR) kinval, NULL }, { "invalue.i", S(INVAL),0, 1, "i", "i", (SUBR) invalsetgo, NULL, NULL }, { "invalue.kS", S(INVAL),0, 3, "k", "S", (SUBR) invalset_S,(SUBR) kinval, NULL }, { "invalue.iS", S(INVAL),0, 1, "i", "S", (SUBR) invalsetSgo, NULL, NULL }, { "invalue.S", S(INVAL),0, 3, "S", "i", (SUBR) invalset_string, (SUBR) kinvalS, NULL }, { "invalue.SS", S(INVAL),0, 3, "S", "S", (SUBR) invalset_string_S, (SUBR) kinvalS, NULL }, { "outvalue", S(OUTVAL), _CW, 3, "", "ik", (SUBR) outvalset, (SUBR) koutval, NULL}, { "outvalue.i", S(OUTVAL), _CW, 1, "", "ii", (SUBR) outvalsetgo, NULL, NULL}, { "outvalue.k", S(OUTVAL), _CW, 3, "", "Sk", (SUBR) outvalset_S, (SUBR) koutval, NULL}, { "outvalue.Si", S(OUTVAL), _CW, 1, "", "Si", (SUBR) outvalsetSgo, NULL, NULL}, { "outvalue.S", S(OUTVAL), _CW, 3, "", "iS", (SUBR) outvalset_string, (SUBR) koutvalS, NULL}, { "outvalue.SS", S(OUTVAL), _CW, 3, "", "SS", (SUBR) outvalset_string_S, (SUBR) koutvalS, NULL}, /* IV - Oct 20 2002 */ { "subinstr", S(SUBINST),0, 5, "mmmmmmmm", "SN", subinstrset_S, NULL, subinstr }, { "subinstrinit", S(SUBINST),0, 1, "", "SN", subinstrset_S, NULL, NULL }, { "subinstr.i", S(SUBINST),0, 5, "mmmmmmmm", "iN", subinstrset, NULL, subinstr }, { "subinstrinit.i", S(SUBINST),0, 1, "", "iN", subinstrset, NULL, NULL }, { "nstrnum", S(NSTRNUM),0, 1, "i", "S", nstrnumset_S, NULL, NULL }, { "nstrnum.i", S(NSTRNUM),0, 1, "i", "i", nstrnumset, NULL, NULL }, { "turnoff2", 0xFFFB, _CW, 0, NULL, NULL, NULL, NULL, NULL }, { "turnoff2.S",S(TURNOFF2),0,2, "", "Skk", NULL, turnoff2S, NULL }, { "turnoff2.c",S(TURNOFF2),0,2, "", "ikk", NULL, turnoff2k, NULL }, { "turnoff2.k",S(TURNOFF2),0,2, "", "kkk", NULL, turnoff2k, NULL }, { "turnoff2.i",S(TURNOFF2),0,2, "", "ikk", NULL, turnoff2k, NULL }, { "turnoff2.r",S(TURNOFF2),0,2, "", "ikk", NULL, turnoff2k, NULL }, { "cngoto", S(CGOTO),0, 3, "", "Bl", ingoto, kngoto, NULL }, { "cnkgoto", S(CGOTO),0, 2, "", "Bl", NULL, kngoto, NULL }, { "cingoto", S(CGOTO),0, 1, "", "Bl", ingoto, NULL, NULL }, { "tempoval", S(GTEMPO),0, 2, "k", "", NULL, (SUBR)gettempo, NULL }, { "downsamp",S(DOWNSAMP),0,3, "k", "ao", (SUBR)downset,(SUBR)downsamp }, { "upsamp", S(UPSAMP),0, 4, "a", "k", NULL, NULL, (SUBR)upsamp }, /* IV - Sep 5 2002 */ { "interp", S(INTERP),0, 5, "a", "kooo", (SUBR)interpset,NULL, (SUBR)interp }, { "a.k", S(INTERP),0, 5, "a", "k", (SUBR)a_k_set,NULL, (SUBR)interp }, { "integ", S(INDIFF), 0, 5, "a", "xo", (SUBR)indfset,NULL,(SUBR)integrate}, { "integ.k", S(INDIFF), 0, 3, "k", "xo", (SUBR)indfset,(SUBR)kntegrate, NULL}, { "diff", S(INDIFF),0, 5, "a", "xo", (SUBR)indfset,NULL, (SUBR)diff }, { "diff.k", S(INDIFF),0, 3, "k", "xo", (SUBR)indfset,(SUBR)kdiff, NULL }, { "samphold",S(SAMPHOLD),0,5, "a", "xxoo", (SUBR)samphset,NULL,(SUBR)samphold }, { "samphold.k",S(SAMPHOLD),0,3, "k", "xxoo", (SUBR)samphset,(SUBR)ksmphold,NULL }, { "delay", S(DELAY),0, 5, "a", "aio", (SUBR)delset, NULL, (SUBR)delay }, { "delayr", S(DELAYR),0, 5, "aX","io", (SUBR)delrset,NULL, (SUBR)delayr }, { "delayw", S(DELAYW),0, 5, "", "a", (SUBR)delwset,NULL, (SUBR)delayw }, { "delay1", S(DELAY1),0, 5, "a", "ao", (SUBR)del1set,NULL, (SUBR)delay1 }, { "deltap", S(DELTAP),0, 5, "a", "ko", (SUBR)tapset, NULL, (SUBR)deltap }, { "deltapi",S(DELTAP),0, 5, "a", "xo", (SUBR)tapset, NULL, (SUBR)deltapi }, { "deltapn",S(DELTAP),0, 5, "a", "xo", (SUBR)tapset, NULL, (SUBR)deltapn }, { "deltap3",S(DELTAP),0, 5, "a", "xo", (SUBR)tapset, NULL, (SUBR)deltap3 }, { "reverb", S(REVERB),0, 5, "a", "ako", (SUBR)rvbset, NULL, (SUBR)reverb }, { "vdelay", S(VDEL),0, 5, "a", "axio", (SUBR)vdelset, NULL, (SUBR)vdelay }, { "vdelay3", S(VDEL),0, 5, "a", "axio", (SUBR)vdelset, NULL, (SUBR)vdelay3 }, { "vdelayxwq",S(VDELXQ),0,5, "aaaa", "aaaaaiio", (SUBR)vdelxqset, NULL, (SUBR)vdelayxwq}, { "vdelayxws",S(VDELXS),0,5, "aa", "aaaiio", (SUBR)vdelxsset, NULL, (SUBR)vdelayxws }, { "vdelayxw", S(VDELX),0, 5, "a", "aaiio", (SUBR)vdelxset, NULL, (SUBR)vdelayxw}, { "vdelayxq", S(VDELXQ),0,5, "aaaa", "aaaaaiio", (SUBR)vdelxqset, NULL, (SUBR)vdelayxq}, { "vdelayxs", S(VDELXS),0,5, "aa", "aaaiio", (SUBR)vdelxsset, NULL, (SUBR)vdelayxs}, { "vdelayx", S(VDELX),0, 5, "a", "aaiio", (SUBR)vdelxset, NULL, (SUBR)vdelayx}, { "deltapx", S(DELTAPX),0,5, "a", "aio", (SUBR)tapxset, NULL, (SUBR)deltapx }, { "deltapxw", S(DELTAPX),0,5, "", "aaio", (SUBR)tapxset, NULL, (SUBR)deltapxw }, { "multitap", S(MDEL),0, 5, "a", "am", (SUBR)multitap_set,NULL,(SUBR)multitap_play}, { "comb", S(COMB),0, 5, "a", "akioo", (SUBR)cmbset,NULL, (SUBR)comb }, { "combinv",S(COMB),0, 5, "a", "akioo", (SUBR)cmbset,NULL, (SUBR)invcomb }, { "alpass", S(COMB),0, 5, "a", "axioo", (SUBR)cmbset,NULL, (SUBR)alpass }, { "strset", S(STRSET_OP),0, 1, "", "iS", (SUBR) strset_init, (SUBR) NULL, (SUBR) NULL }, { "strget", S(STRGET_OP),0, 1, "S", "i", (SUBR) strget_init, (SUBR) NULL, (SUBR) NULL }, { "S", S(STRGET_OP),0, 1, "S", "i", (SUBR) s_opcode, (SUBR) NULL, (SUBR) NULL }, { "S", S(STRGET_OP),0, 3, "S", "k", (SUBR) s_opcode,(SUBR) s_opcode_k, (SUBR) NULL }, { "strcpy", S(STRCPY_OP),0, 1, "S", "S", (SUBR) strcpy_opcode_S, (SUBR) NULL, (SUBR) NULL }, { "strcpy", S(STRGET_OP),0, 1, "S", "i", (SUBR) strcpy_opcode_p, (SUBR) NULL, (SUBR) NULL }, { "strcpyk", S(STRCPY_OP),0, 3, "S", "S", (SUBR) strcpy_opcode_S, (SUBR) strcpy_opcode_S, (SUBR) NULL }, { "strcpyk.k", S(STRGET_OP),0, 3, "S", "k", (SUBR) strcpy_opcode_p, (SUBR) strcpy_opcode_p, (SUBR) NULL }, { "strcat", S(STRCAT_OP),0, 1, "S", "SS", (SUBR) strcat_opcode, (SUBR) NULL, (SUBR) NULL }, { "strcatk", S(STRCAT_OP),0, 3, "S", "SS", (SUBR) strcat_opcode, (SUBR) strcat_opcode, (SUBR) NULL }, { "strcmp", S(STRCMP_OP),0, 1, "i", "SS", (SUBR) strcmp_opcode, (SUBR) NULL, (SUBR) NULL }, { "strcmpk", S(STRCAT_OP),0, 3, "k", "SS", (SUBR) strcmp_opcode, (SUBR) strcmp_opcode, (SUBR) NULL }, { "sprintf", S(SPRINTF_OP),0, 1, "S", "STN", (SUBR) sprintf_opcode, (SUBR) NULL, (SUBR) NULL }, { "sprintfk", S(SPRINTF_OP),WR, 3, "S", "SUN", (SUBR) sprintf_opcode, (SUBR) sprintf_opcode, (SUBR) NULL }, { "printf_i", S(PRINTF_OP),0, 1, "", "SiTN", (SUBR) printf_opcode_init, (SUBR) NULL, (SUBR) NULL }, { "printf", S(PRINTF_OP),WR, 3, "", "SkUN", (SUBR) printf_opcode_set, (SUBR) printf_opcode_perf, (SUBR) NULL }, { "puts", S(PUTS_OP),WR, 3, "", "Sko", (SUBR) puts_opcode_init, (SUBR) puts_opcode_perf, (SUBR) NULL }, { "strtod", S(STRSET_OP),0, 1, "i", "S", (SUBR) strtod_opcode_S, (SUBR) NULL, (SUBR) NULL }, { "strtod", S(STRTOD_OP),0, 1, "i", "i", (SUBR) strtod_opcode_p, (SUBR) NULL, (SUBR) NULL }, { "strtodk", S(STRSET_OP),0, 3, "k", "S", (SUBR) strtod_opcode_S, (SUBR) strtod_opcode_S, (SUBR) NULL }, { "strtol", S(STRSET_OP),0, 1, "i", "S", (SUBR) strtol_opcode_S, (SUBR) NULL, (SUBR) NULL }, { "strtol", S(STRTOD_OP),0, 1, "i", "i", (SUBR) strtol_opcode_p, (SUBR) NULL, (SUBR) NULL }, { "strtolk", S(STRSET_OP),0, 3, "k", "S", (SUBR) strtol_opcode_S, (SUBR) strtol_opcode_S, (SUBR) NULL }, { "strsub", S(STRSUB_OP),0, 1, "S", "Soj", (SUBR) strsub_opcode, (SUBR) NULL, (SUBR) NULL }, { "strsubk", S(STRSUB_OP),0, 3, "S", "Skk", (SUBR) strsub_opcode, (SUBR) strsub_opcode, (SUBR) NULL }, { "strchar", S(STRCHAR_OP),0, 1, "i", "So", (SUBR) strchar_opcode, (SUBR) NULL, (SUBR) NULL }, { "strchark", S(STRCHAR_OP),0, 3, "k", "SO", (SUBR) strchar_opcode, (SUBR) strchar_opcode, (SUBR) NULL }, { "strlen", S(STRLEN_OP),0, 1, "i", "S", (SUBR) strlen_opcode, (SUBR) NULL, (SUBR) NULL }, { "strlenk", S(STRLEN_OP),0, 3, "k", "S", (SUBR) strlen_opcode, (SUBR) strlen_opcode, (SUBR) NULL }, { "strupper", S(STRUPPER_OP),0, 1, "S", "S", (SUBR) strupper_opcode, (SUBR) NULL, (SUBR) NULL }, { "strupperk", S(STRUPPER_OP),0, 3, "S", "S", (SUBR) strupper_opcode, (SUBR) strupper_opcode, (SUBR) NULL }, { "strlower", S(STRUPPER_OP),0, 1, "S", "S", (SUBR) strlower_opcode, (SUBR) NULL, (SUBR) NULL }, { "strlowerk", S(STRUPPER_OP),0, 3, "S", "S", (SUBR) strlower_opcode, (SUBR) strlower_opcode, (SUBR) NULL }, { "getcfg", S(GETCFG_OP),0, 1, "S", "i", (SUBR) getcfg_opcode, (SUBR) NULL, (SUBR) NULL }, { "strindex", S(STRINDEX_OP),0, 1, "i", "SS", (SUBR) strindex_opcode, (SUBR) NULL, (SUBR) NULL }, { "strindexk", S(STRINDEX_OP),0, 3, "k", "SS", (SUBR) strindex_opcode, (SUBR) strindex_opcode, (SUBR) NULL }, { "strrindex", S(STRINDEX_OP),0, 1, "i", "SS", (SUBR) strrindex_opcode, (SUBR) NULL, (SUBR) NULL }, { "strrindexk", S(STRINDEX_OP),0, 3, "k", "SS", (SUBR) strrindex_opcode, (SUBR) strrindex_opcode, (SUBR) NULL }, { "print_type", S(PRINT_TYPE_OP),0, 1, "", ".", (SUBR) print_type_opcode, (SUBR) NULL, (SUBR) NULL }, #ifdef HAVE_CURL { "strfromurl", S(STRCPY_OP), 0, 1, "S", "S", (SUBR) str_from_url }, #endif { "changed.S", S(STRINDEX_OP),0, 3, "k", "S", (SUBR) str_changed, (SUBR) str_changed_k, (SUBR) NULL }, { "loop_lt", 0xfffb }, { "loop_le", 0xfffb }, { "loop_gt", 0xfffb }, { "loop_ge", 0xfffb }, { "loop_lt.i", S(LOOP_OPS),0, 1, "", "iiil", (SUBR) loop_l_i, NULL, NULL }, { "loop_le.i", S(LOOP_OPS),0, 1, "", "iiil", (SUBR) loop_le_i, NULL, NULL }, { "loop_gt.i", S(LOOP_OPS),0, 1, "", "iiil", (SUBR) loop_g_i, NULL, NULL }, { "loop_ge.i", S(LOOP_OPS),0, 1, "", "iiil", (SUBR) loop_ge_i, NULL, NULL }, { "loop_lt.k", S(LOOP_OPS),0, 2, "", "kkkl", NULL, (SUBR) loop_l_p, NULL }, { "loop_le.k", S(LOOP_OPS),0, 2, "", "kkkl", NULL, (SUBR) loop_le_p, NULL }, { "loop_gt.k", S(LOOP_OPS),0, 2, "", "kkkl", NULL, (SUBR) loop_g_p, NULL }, { "loop_ge.k", S(LOOP_OPS),0, 2, "", "kkkl", NULL, (SUBR) loop_ge_p, NULL }, { "chnget", 0xFFFF, _CR }, { "chnget.i", S(CHNGET),0, 1, "i", "S", (SUBR) chnget_opcode_init_i, (SUBR) NULL, (SUBR) NULL }, { "chnget.k", S(CHNGET),0, 3, "k", "S", (SUBR) chnget_opcode_init_k, (SUBR) notinit_opcode_stub, (SUBR) NULL }, { "chnget.a", S(CHNGET),0, 5, "a", "S", (SUBR) chnget_opcode_init_a, (SUBR) NULL, (SUBR) notinit_opcode_stub }, { "chnget.S", S(CHNGET),0, 3, "S", "S", (SUBR) chnget_opcode_init_S, (SUBR) chnget_opcode_perf_S, (SUBR) NULL}, { "chngetks", S(CHNGET),0, 2, "S", "S", (SUBR) NULL, (SUBR) chnget_opcode_perf_S, (SUBR) NULL}, { "chnset", 0xFFFB, _CW }, { "chnset.i", S(CHNGET),_CW, 1, "", "iS", (SUBR) chnset_opcode_init_i, (SUBR) NULL, (SUBR) NULL }, // { "chnset.r", S(CHNGET),0, 1, "", "iS", // (SUBR) chnset_opcode_init_i, (SUBR) NULL, (SUBR) NULL }, // { "chnset.c", S(CHNGET),0, 1, "", "iS", // (SUBR) chnset_opcode_init_i, (SUBR) NULL, (SUBR) NULL }, { "chnset.k", S(CHNGET),_CW, 3, "", "kS", (SUBR) chnset_opcode_init_k, (SUBR) notinit_opcode_stub, (SUBR) NULL }, { "chnset.a", S(CHNGET),_CW, 5, "", "aS", (SUBR) chnset_opcode_init_a, (SUBR) NULL, (SUBR) notinit_opcode_stub }, { "chnset.S", S(CHNGET),_CW, 3, "", "SS", (SUBR) chnset_opcode_init_S, (SUBR) chnset_opcode_perf_S, (SUBR) NULL }, { "chnsetks", S(CHNGET),_CW, 2, "", "SS", (SUBR) NULL, (SUBR) chnset_opcode_perf_S, (SUBR) NULL }, { "chnmix", S(CHNGET), _CB, 5, "", "aS", (SUBR) chnmix_opcode_init, (SUBR) NULL, (SUBR) notinit_opcode_stub }, { "chnclear", S(CHNCLEAR), _CW, 5, "", "S", (SUBR) chnclear_opcode_init, (SUBR) NULL, (SUBR) notinit_opcode_stub }, { "chn_k", S(CHN_OPCODE_K), _CW, 1, "", "SiooooooooN", (SUBR) chn_k_opcode_init, (SUBR) NULL, (SUBR) NULL }, { "chn_a", S(CHN_OPCODE), _CW, 1, "", "Si", (SUBR) chn_a_opcode_init, (SUBR) NULL, (SUBR) NULL }, { "chn_S", S(CHN_OPCODE), _CW, 1, "", "Si", (SUBR) chn_S_opcode_init, (SUBR) NULL, (SUBR) NULL }, { "chnexport", 0xFFFF, 0, 0, NULL, NULL, (SUBR) NULL, (SUBR) NULL }, { "chnexport.i", S(CHNEXPORT_OPCODE),0, 1, "i", "Sioooo", (SUBR) chnexport_opcode_init, (SUBR) NULL, (SUBR) NULL }, { "chnexport.k", S(CHNEXPORT_OPCODE),0, 1, "k", "Sioooo", (SUBR) chnexport_opcode_init, (SUBR) NULL, (SUBR) NULL }, { "chnexport.a", S(CHNEXPORT_OPCODE),0, 1, "a", "Si", (SUBR) chnexport_opcode_init, (SUBR) NULL, (SUBR) NULL }, { "chnexport.S", S(CHNEXPORT_OPCODE),0, 1, "S", "Si", (SUBR) chnexport_opcode_init, (SUBR) NULL, (SUBR) NULL }, { "chnparams", S(CHNPARAMS_OPCODE),_CR, 1, "iiiiii", "S", (SUBR) chnparams_opcode_init, (SUBR) NULL, (SUBR) NULL }, /* these opcodes have never been fully implemented { "chnrecv", S(CHNSEND), _CR, 3, "", "So", (SUBR) chnrecv_opcode_init, (SUBR) notinit_opcode_stub, (SUBR) NULL }, { "chnsend", S(CHNSEND),0, 3, "", "So", (SUBR) chnsend_opcode_init, (SUBR) notinit_opcode_stub, (SUBR) NULL }, */ { "chano", 0xFFFD, _CW, 0, NULL, NULL, (SUBR) NULL, (SUBR) NULL }, { "chano.k", S(ASSIGN),0, 2, "", "kk", (SUBR) NULL, (SUBR) chano_opcode_perf_k, (SUBR) NULL }, { "chano.a", S(ASSIGN),0, 4, "", "ak", (SUBR) NULL, (SUBR) NULL, (SUBR) chano_opcode_perf_a }, { "pvsout", S(FCHAN),0, 3, "", "fk", (SUBR) pvsout_init, (SUBR) pvsout_perf, (SUBR) NULL }, { "chani", 0xFFFF, _CR, 0, NULL, NULL, (SUBR) NULL, (SUBR) NULL }, { "chani.k", S(ASSIGN),0, 2, "k", "k", (SUBR) NULL, (SUBR) chani_opcode_perf_k, (SUBR) NULL }, { "chani.a", S(ASSIGN),0, 4, "a", "k", (SUBR) NULL, (SUBR) NULL, (SUBR) chani_opcode_perf_a }, { "pvsin", S(FCHAN),0, 3, "f", "kooopo", (SUBR) pvsin_init, (SUBR) pvsin_perf, (SUBR) NULL }, { "sense", S(KSENSE),0, 2, "kz", "", (SUBR) NULL, (SUBR) sensekey_perf, (SUBR) NULL }, { "sensekey", S(KSENSE),0, 2, "kz", "", (SUBR) NULL, (SUBR) sensekey_perf, (SUBR) NULL }, { "remove", S(DELETEIN),0, 1, "", "T", (SUBR) delete_instr, (SUBR) NULL, (SUBR) NULL }, { "##globallock", S(GLOBAL_LOCK_UNLOCK),0, 3, "", "i", globallock, globallock, NULL}, { "##globalunlock", S(GLOBAL_LOCK_UNLOCK),0, 3, "", "i", globalunlock, globalunlock, NULL}, { "##error",S(ERRFN),0, 1, "i", "i", error_fn, NULL, NULL }, { "exprandi.i",S(PRANDI),0, 1, "i", "kxx", iexprndi, NULL, NULL }, { "exprandi.k",S(PRANDI),0, 3, "k", "kxx", exprndiset, kexprndi, NULL }, { "exprandi.a",S(PRANDI),0, 4, "a", "kxx", exprndiset, NULL, aexprndi }, { "cauchyi.i", S(PRANDI),0, 1, "i", "kxx", icauchyi, NULL, NULL }, { "cauchyi.k", S(PRANDI),0, 3, "k", "kxx", cauchyiset, kcauchyi, NULL }, { "cauchyi.a", S(PRANDI),0, 4, "a", "kxx", cauchyiset, NULL, acauchyi }, { "gaussi.i", S(PRANDI),0, 1, "i", "kxx", igaussi, NULL, NULL }, { "gaussi.k", S(PRANDI),0, 3, "k", "kxx", gaussiset, kgaussi, NULL }, { "gaussi.a", S(PRANDI),0, 4, "a", "kxx", gaussiset, NULL, agaussi }, { "ftresizei", S(RESIZE), TB, 1, "i", "ii", (SUBR) resize_table, NULL, NULL }, { "ftresize", S(RESIZE), TB, 2, "k", "kk", NULL, (SUBR) resize_table, NULL }, { "compileorc", S(COMPILE), 0, 1, "i", "S", (SUBR) compile_orc_i, NULL, NULL }, { "compilecsd", S(COMPILE), 0, 1, "i", "S", (SUBR) compile_csd_i, NULL, NULL }, { "compilestr", S(COMPILE), 0, 1, "i", "S", (SUBR) compile_str_i, NULL, NULL }, { "evalstr", S(COMPILE), 0, 1, "i", "S", (SUBR) eval_str_i, NULL, NULL }, { "evalstr", S(COMPILE), 0, 2, "k", "Sk", NULL, (SUBR) eval_str_k, NULL }, { "readscore", S(COMPILE), 0, 1, "i", "S", (SUBR) read_score_i, NULL, NULL }, { "return", S(RETVAL), 0, 1, "", "i", (SUBR) retval_i, NULL, NULL }, /* ----------------------------------------------------------------------- */ { "monitor", sizeof(MONITOR_OPCODE), 0, 3, "mmmmmmmmmmmmmmmmmmmmmmmm", "", (SUBR) monitor_opcode_init, (SUBR) notinit_opcode_stub, (SUBR) NULL }, { "outrg", S(OUTRANGE), 0,5, "", "ky", (SUBR)outRange_i, (SUBR)NULL, (SUBR)outRange}, { "nchnls_hw", S(ASSIGN), 0,1, "ii", "", (SUBR)hw_channels}, { "midiarp", S(MIDIARP),0, 3, "kk", "kO", midiarp_set, midiarp, NULL }, /* terminate list */ { NULL, 0, 0, 0, NULL, NULL, (SUBR) NULL, (SUBR) NULL, (SUBR) NULL } }; csound-6.10.0/Engine/envvar.c000066400000000000000000001363401321653344700157620ustar00rootroot00000000000000/* envvar.c: Copyright (C) 2005 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "soundio.h" #include "envvar.h" #include #include #if defined(MSVC) #include #endif #include "namedins.h" /* list of environment variables used by Csound */ static const char *envVar_list[] = { "CSNOSTOP", "CSOUNDRC", "CSSTRNGS", "CS_LANG", "HOME", "INCDIR", "OPCODE6DIR", "OPCODE6DIR64", "RAWWAVE_PATH", "SADIR", "SFDIR", "SFOUTYP", "SNAPDIR", "SSDIR", "MFDIR", NULL }; typedef struct CSFILE_ { struct CSFILE_ *nxt; struct CSFILE_ *prv; int type; int fd; FILE *f; SNDFILE *sf; void *cb; int async_flag; int items; int pos; MYFLT *buf; int bufsize; char fullName[1]; } CSFILE; #if defined(MSVC) #define RD_OPTS _O_RDONLY | _O_BINARY #define WR_OPTS _O_TRUNC | _O_CREAT | _O_WRONLY | _O_BINARY,_S_IWRITE #elif defined(WIN32) #define RD_OPTS O_RDONLY | O_BINARY #define WR_OPTS O_TRUNC | O_CREAT | O_WRONLY | O_BINARY, 0644 #elif defined DOSGCC #define RD_OPTS O_RDONLY | O_BINARY, 0 #define WR_OPTS O_TRUNC | O_CREAT | O_WRONLY | O_BINARY, 0644 #else #ifndef O_BINARY # define O_BINARY (0) #endif #define RD_OPTS O_RDONLY | O_BINARY, 0 #define WR_OPTS O_TRUNC | O_CREAT | O_WRONLY | O_BINARY, 0644 #endif typedef struct searchPathCacheEntry_s { char *name; struct searchPathCacheEntry_s *nxt; char *lst[1]; } searchPathCacheEntry_t; typedef struct nameChain_s { struct nameChain_s *nxt; char s[1]; } nameChain_t; /* Space for 16 global environment variables, */ /* 32 bytes for name and 480 bytes for value. */ /* Only written by csoundSetGlobalEnv(). */ static char globalEnvVars[8192] = { (char) 0 }; #define globalEnvVarName(x) ((char*) &(globalEnvVars[(int) (x) << 9])) #define globalEnvVarValue(x) ((char*) &(globalEnvVars[((int) (x) << 9) + 32])) static int is_valid_envvar_name(const char *name) { char *s; if (UNLIKELY(name == NULL || name[0] == '\0')) return 0; s = (char*) &(name[0]); if (UNLIKELY(!(isalpha(*s) || *s == '_'))) return 0; while (*(++s) != '\0') { if (UNLIKELY(!(isalpha(*s) || isdigit(*s) || *s == '_'))) return 0; } return 1; } /** * Get pointer to value of environment variable 'name'. * Return value is NULL if the variable is not set. */ PUBLIC const char *csoundGetEnv(CSOUND *csound, const char *name) { if (csound == NULL) { int i; if (name == NULL || name[0] == '\0') return (const char*) NULL; for (i = 0; i < 16; i++) { if (strcmp(globalEnvVarName(i), name) == 0) return (const char*) globalEnvVarValue(i); } return (const char*) getenv(name); } if (csound->envVarDB == NULL) return NULL; return (const char*) cs_hash_table_get(csound, csound->envVarDB, (char*)name); } /** * Set the global value of environment variable 'name' to 'value', * or delete variable if 'value' is NULL. * It is not safe to call this function while any Csound instances * are active. * Returns zero on success. */ PUBLIC int csoundSetGlobalEnv(const char *name, const char *value) { int i; if (UNLIKELY(name == NULL || name[0] == '\0' || (int) strlen(name) >= 32)) return -1; /* invalid name */ for (i = 0; i < 16; i++) { if ((value != NULL && globalEnvVarName(i)[0] == '\0') || strcmp(name, globalEnvVarName(i)) == 0) break; } if (UNLIKELY(i >= 16)) /* not found / no free slot */ return -1; if (value == NULL) { globalEnvVarName(i)[0] = '\0'; /* delete existing variable */ return 0; } if (UNLIKELY(strlen(value) >= 480)) return -1; /* string value is too long */ strcpy(globalEnvVarName(i), name); strcpy(globalEnvVarValue(i), value); return 0; } /** * Set environment variable 'name' to 'value'. * Returns CSOUND_SUCCESS on success, and CSOUND_ERROR or CSOUND_MEMORY * if the environment variable could not be set for some reason. */ int csoundSetEnv(CSOUND *csound, const char *name, const char *value) { searchPathCacheEntry_t *ep, *nxt; char *oldValue; /* check for valid parameters */ if (UNLIKELY(csound == NULL || !is_valid_envvar_name(name))) return CSOUND_ERROR; /* invalidate search path cache */ ep = (searchPathCacheEntry_t*) csound->searchPathCache; while (ep != NULL) { nxt = ep->nxt; csound->Free(csound, ep); ep = nxt; } csound->searchPathCache = NULL; oldValue = cs_hash_table_get(csound, csound->envVarDB, (char*)name); if (oldValue != NULL) { csound->Free(csound, oldValue); } cs_hash_table_put(csound, csound->envVarDB, (char*)name, cs_strdup(csound, (char*)value)); /* print debugging info if requested */ if (UNLIKELY(csound->oparms->odebug)) { csoundMessage(csound, Str("Environment variable '%s' has been set to "), name); if (value == NULL) csoundMessage(csound, "NULL\n"); else csoundMessage(csound, "'%s'\n", value); } /* report success */ return CSOUND_SUCCESS; } /** * Append 'value' to environment variable 'name', using ENVSEP as * separator character. * Returns CSOUND_SUCCESS on success, and CSOUND_ERROR or CSOUND_MEMORY * if the environment variable could not be set for some reason. */ int csoundAppendEnv(CSOUND *csound, const char *name, const char *value) { const char *oldval; char *newval; int retval; /* check for valid parameters */ if (UNLIKELY(csound == NULL || !is_valid_envvar_name(name))) return CSOUND_ERROR; /* get original value of variable */ oldval = csoundGetEnv(csound, name); if (oldval == NULL) return csoundSetEnv(csound, name, value); if (value == NULL || value[0] == '\0') return CSOUND_SUCCESS; /* allocate new value (+ 2 bytes for ENVSEP and null character) */ newval = (char*) csound->Malloc(csound, (size_t) strlen(oldval) + (size_t) strlen(value) + (size_t) 2); /* append to old value */ strcpy(newval, oldval); /* These are safe as space calculated above */ // printf("%d: newval = %s\n", __LINE__, newval); // should be a better way newval[strlen(oldval)]= ENVSEP; newval[strlen(oldval)+1]= '\0'; // printf("%d: newval = %s\n", __LINE__, newval); strcat(newval, value); // printf("%d: newval = %s\n", __LINE__, newval); /* set variable */ retval = csoundSetEnv(csound, name, newval); csound->Free(csound, newval); /* return with error code */ return retval; } /** * Prepend 'value' to environment variable 'name', using ENVSEP as * separator character. * Returns CSOUND_SUCCESS on success, and CSOUND_ERROR or CSOUND_MEMORY * if the environment variable could not be set for some reason. */ int csoundPrependEnv(CSOUND *csound, const char *name, const char *value) { const char *oldval; char *newval; int retval; /* check for valid parameters */ if (UNLIKELY(csound == NULL || !is_valid_envvar_name(name))) return CSOUND_ERROR; /* get original value of variable */ oldval = csoundGetEnv(csound, name); if (oldval == NULL) return csoundSetEnv(csound, name, value); if (value == NULL || value[0] == '\0') return CSOUND_SUCCESS; /* allocate new value (+ 2 bytes for ';' and null character) */ newval = (char*) csound->Malloc(csound, (size_t) strlen(oldval) + (size_t) strlen(value) + (size_t) 2); /* prepend to old value */ strcpy(newval, value); // printf("%d: newval = %s\n", __LINE__, newval); newval[strlen(value)]= ENVSEP; newval[strlen(value)+1]= '\0'; // printf("%d: newval = %s\n", __LINE__, newval); strcat(newval, oldval); // printf("%d: newval = %s\n", __LINE__, newval); /* set variable */ retval = csoundSetEnv(csound, name, newval); csound->Free(csound, newval); /* return with error code */ return retval; } /** * Initialise environment variable database, and copy system * environment variables. * Returns CSOUND_SUCCESS on success, and CSOUND_ERROR or * CSOUND_MEMORY in case of an error. */ int csoundInitEnv(CSOUND *csound) { int i, retval; /* check if already initialised */ if (csound->envVarDB != NULL) return CSOUND_SUCCESS; /* allocate table */ csound->envVarDB = cs_hash_table_create(csound); /* copy standard Csound environment variables */ for (i = 0; envVar_list[i] != NULL; i++) { const char *name = envVar_list[i]; const char *value = getenv(name); if (value != NULL) { retval = csoundSetEnv(csound, name, value); if (retval != CSOUND_SUCCESS) return retval; } } /* copy any global defaults set with csoundSetGlobalEnv() */ for (i = 0; i < 16; i++) { if (globalEnvVarName(i)[0] != '\0') { retval = csoundSetEnv(csound, globalEnvVarName(i), globalEnvVarValue(i)); if (retval != CSOUND_SUCCESS) return retval; } } /* done */ return CSOUND_SUCCESS; } /** * Parse 's' as an assignment to environment variable, in the format * "NAME=VALUE" for replacing the previous value, or "NAME+=VALUE" * for appending. * Returns CSOUND_SUCCESS on success, and CSOUND_ERROR or * CSOUND_MEMORY in case of an error. */ int csoundParseEnv(CSOUND *csound, const char *s) { char *name, *value, msg[256]; int append_mode, retval; /* copy string constant */ name = (char*) csound->Malloc(csound, (size_t) strlen(s) + (size_t) 1); strcpy(name, s); /* check assignment format */ value = strchr(name, '='); append_mode = 0; if (UNLIKELY(value == NULL || value == name)) { strncpy(msg, Str(" *** invalid format for --env\n"), 255); retval = CSOUND_ERROR; goto err_return; } *(value++) = '\0'; if (*(value - 2) == '+') { append_mode = 1; *(value - 2) = '\0'; } if (UNLIKELY(!is_valid_envvar_name(name))) { strncpy(msg, Str(" *** invalid environment variable name\n"), 255); retval = CSOUND_ERROR; goto err_return; } /* set variable */ if (!append_mode) retval = csoundSetEnv(csound, name, value); else retval = csoundAppendEnv(csound, name, value); if (UNLIKELY(retval == CSOUND_MEMORY)) strncpy(msg, Str(" *** memory allocation failure\n"), 255); else strncpy(msg, Str(" *** error setting environment variable\n"), 255); err_return: if (UNLIKELY(retval != CSOUND_SUCCESS)) csoundMessage(csound, "%s", msg); csound->Free(csound, name); return retval; } char **csoundGetSearchPathFromEnv(CSOUND *csound, const char *envList) { searchPathCacheEntry_t *p; nameChain_t *env_lst = NULL, *path_lst = NULL, *tmp, *prv, *nxt; char *s; int i, j, k, len, pathCnt = 0, totLen = 0; /* check if the specified environment variable list was already parsed */ p = (searchPathCacheEntry_t*) csound->searchPathCache; while (p != NULL) { if (sCmp(p->name, envList) == 0) return (&(p->lst[0])); p = p->nxt; } /* not found, need to create new entry */ len = (int) strlen(envList); /* split environment variable list to tokens */ for (i = j = 0; i <= len; i++) { if (envList[i] == ';' || envList[i] == ':' || envList[i] == '\0') { if (i > j) { tmp = (nameChain_t*)csound->Malloc(csound, sizeof(nameChain_t) + (i-j)); for (k = 0; j < i; j++, k++) tmp->s[k] = envList[j]; tmp->s[k] = '\0'; tmp->nxt = NULL; if (env_lst != NULL) { /* search for duplicate entry */ prv = nxt = env_lst; do { if (sCmp(env_lst->s, tmp->s) == 0) break; prv = nxt; } while ((nxt = prv->nxt) != NULL); if (nxt == NULL) prv->nxt = tmp; else csound->Free(csound, tmp); /* and remove if there is any */ } else env_lst = tmp; } j = i + 1; } } /* expand environment variables to path list */ while (env_lst != NULL) { nxt = env_lst->nxt; s = (char*) csoundGetEnv(csound, env_lst->s); csound->Free(csound, env_lst); env_lst = nxt; if (s != NULL && s[0] != '\0') len = (int) strlen(s); else len = -1; // **** THIS CODE DOES NOT CHECK FOR WINDOWS STYLE C:\foo **** for (i = j = 0; i <= len; i++) { if (i==0 && isalpha(s[i]) && s[i+1]==':') i++; else if (s[i] == ';' || s[i] == ':' || s[i] == '\0') { if (i > j) { tmp = (nameChain_t*) csound->Malloc(csound, sizeof(nameChain_t) + (i - j) + 1); /* copy with converting pathname delimiters */ /* FIXME: should call csoundConvertPathname instead */ for (k = 0; j < i; j++, k++) tmp->s[k] = (s[j] == '/' || s[j] == '\\' ? DIRSEP : s[j]); while (tmp->s[--k] == DIRSEP); tmp->s[++k] = DIRSEP; tmp->s[++k] = '\0'; tmp->nxt = path_lst; path_lst = tmp; /* search for duplicate entry */ for (prv = tmp; (tmp = tmp->nxt) != NULL; prv = tmp) if (sCmp(path_lst->s, tmp->s) == 0) break; if (tmp != NULL) { /* and remove if there is any */ prv->nxt = tmp->nxt; csound->Free(csound, tmp); } else { /* calculate storage requirement */ pathCnt++; totLen += (k + 1); } } j = i + 1; if (i+2<=len && s[i+2]==':' && isalpha(s[i+1])) i+=2; } } } totLen += ((int) strlen(envList) + 1); /* create path cache entry */ p = (searchPathCacheEntry_t*) csound->Malloc(csound, sizeof(searchPathCacheEntry_t) + sizeof(char*) * pathCnt + sizeof(char) * totLen); s = (char*) &(p->lst[pathCnt + 1]); p->name = s; strcpy(p->name, envList); s += ((int) strlen(envList) + 1); p->nxt = (searchPathCacheEntry_t*) csound->searchPathCache; if (UNLIKELY(csound->oparms->odebug)) csound->DebugMsg(csound, Str("Creating search path cache for '%s':"), p->name); for (i = 0; (i < pathCnt) && (path_lst != NULL); i++) { p->lst[i] = s; strcpy(s, path_lst->s); s += ((int) strlen(path_lst->s) + 1); nxt = path_lst->nxt; csound->Free(csound, path_lst); path_lst = nxt; if (UNLIKELY(csound->oparms->odebug)) csound->DebugMsg(csound, "%5d: \"%s\"", (i + 1), p->lst[i]); } p->lst[i] = NULL; /* link into database */ csound->searchPathCache = (void*) p; /* return with pathname list */ return (&(p->lst[0])); } /** Check if file name is valid, and copy with converting pathname delimiters */ char *csoundConvertPathname(CSOUND *csound, const char *filename) { char *name; int i = 0; /* FIXMEs: need to convert ':' from Mac pathnames (but be careful of not messing up Windows drive names!); need to be careful of relative paths containing "./", "../", or multiple colons "::"; need to collapse multiple slashes "//" or "\\\\" ?? */ if (filename == NULL || filename[0] == '\0') return NULL; name = (char*) csound->Malloc(csound, (size_t) strlen(filename) + (size_t) 1); do { if (filename[i] != '/' && filename[i] != '\\') name[i] = filename[i]; else name[i] = DIRSEP; } while (filename[i++] != '\0'); if (name[i - 2] == DIRSEP #ifdef WIN32 || (isalpha(name[0]) && name[1] == ':' && name[2] == '\0') #endif ) { csound->Free(csound, name); return NULL; } return name; } /** Check if name is a full pathname for the platform we are running on. */ int csoundIsNameFullpath(const char *name) { #ifdef WIN32 if (isalpha(name[0]) && name[1] == ':') return 1; #endif if (name[0] == DIRSEP) /* || (name[0] == '.' && (name[1] == DIRSEP || (name[1] == '.' && name[2] == DIRSEP)))) */ return 1; return 0; } /** Check if name is a relative pathname for this platform. Bare * filenames with no path information are not counted. */ int csoundIsNameRelativePath(const char *name) { if (name[0] != DIRSEP && strchr(name, DIRSEP) != NULL) return 1; return 0; } /** Check if name is a "leaf" (bare) filename for this platform. */ int csoundIsNameJustFilename(const char *name) { if (strchr(name, DIRSEP) != NULL) return 0; #ifdef WIN32 if (name[2] == ':') return 0; #endif return 1; } /** Properly concatenates the full or relative pathname in path1 with * the relative pathname or filename in path2 according to the rules * for the platform we are running on. path1 is assumed to be * a directory whether it ends with DIRSEP or not. Relative paths must * conform to the conventions for the current platform (begin with ':' * on MacOS 9 and not begin with DIRSEP on others). */ char* csoundConcatenatePaths(CSOUND* csound, const char *path1, const char *path2) { char *result; const char *start2; char separator[2]; int len1 = strlen(path1); int len2 = strlen(path2); /* cannot join two full pathnames -- so just return path2 ? */ if (csoundIsNameFullpath(path2)) { result = (char*) csound->Malloc(csound, (size_t)len2+1); strcpy(result, path2); return result; } start2 = path2; /* ignore "./" at the beginning */ if (path2[0] == '.' && path2[1] == DIRSEP) start2 = path2 + 2; result = (char*) csound->Malloc(csound, (size_t)len1+(size_t)len2+2); strcpy(result, path1); /* check for final DIRSEP in path1 */ if (path1[len1-1] != DIRSEP) { separator[0] = DIRSEP; separator[1] = '\0'; strcat(result, separator); } strcat(result, start2); return result; } /** Converts a pathname to native format and returns just the part of * the path that specifies the directory. Does not return the final * DIRSEP. Returns an empty string if no path components occur before * the filename. Returns NULL if unable to carry out the operation * for some reason. */ char *csoundSplitDirectoryFromPath(CSOUND* csound, const char * path) { char *convPath; char *lastIndex; char *partialPath; int len; if ((convPath = csoundConvertPathname(csound, path)) == NULL) return NULL; lastIndex = strrchr(convPath, DIRSEP); if (lastIndex == NULL) { /* no DIRSEP before filename */ #ifdef WIN32 /* e.g. C:filename */ if (isalpha(convPath[0]) && convPath[1] == ':') { partialPath = (char*) csound->Malloc(csound, (size_t) 3); partialPath[0] = convPath[0]; partialPath[1] = convPath[1]; partialPath[2] = '\0'; csound->Free(csound, convPath); return partialPath; } #endif partialPath = (char*) csound->Malloc(csound, (size_t) 1); partialPath[0] = '\0'; } else { len = lastIndex - convPath; partialPath = (char*) csound->Malloc(csound, len+1); strncpy(partialPath, convPath, len); partialPath[len] = '\0'; } csound->Free(csound, convPath); return partialPath; } /** Return just the final component of a full path */ char *csoundSplitFilenameFromPath(CSOUND* csound, const char * path) { char *convPath; char *lastIndex; char *filename; int len; if ((convPath = csoundConvertPathname(csound, path)) == NULL) return NULL; lastIndex = strrchr(convPath, DIRSEP); len = strlen(lastIndex); filename = (char*) csound->Malloc(csound, len+1); strcpy(filename, lastIndex+1); csound->Free(csound, convPath); return filename; } /* given a file name as string, return full path of directory of file; * Note: does not check if file exists */ char *csoundGetDirectoryForPath(CSOUND* csound, const char * path) { char *partialPath, *tempPath, *lastIndex; char *retval; char *cwd; int len; if (path == NULL) return NULL; tempPath = csoundConvertPathname(csound, path); if (tempPath == NULL) return NULL; lastIndex = strrchr(tempPath, DIRSEP); if (tempPath && csoundIsNameFullpath(tempPath)) { /* check if root directory */ if (lastIndex == tempPath) { partialPath = (char *)csound->Malloc(csound, 2); partialPath[0] = DIRSEP; partialPath[1] = '\0'; csound->Free(csound, tempPath); return partialPath; } # ifdef WIN32 /* check if root directory of Windows drive */ if ((lastIndex - tempPath) == 2 && tempPath[1] == ':') { partialPath = (char *)csound->Malloc(csound, 4); partialPath[0] = tempPath[0]; partialPath[1] = tempPath[1]; partialPath[2] = tempPath[2]; partialPath[3] = '\0'; csound->Free(csound, tempPath); return partialPath; } # endif len = (lastIndex - tempPath); partialPath = (char *)csound->Calloc(csound, len + 1); strncpy(partialPath, tempPath, len); csound->Free(csound, tempPath); return partialPath; } /* do we need to worry about ~/ on *nix systems ? */ /* we have a relative path or just a filename */ len = 32; cwd = csound->Malloc(csound, len); again: if (UNLIKELY(getcwd(cwd, len)==NULL)) { // Should check ERANGE==errno //csoundDie(csound, Str("Current directory path name too long\n")); len =len+len; cwd = csound->ReAlloc(csound, cwd, len); if (UNLIKELY(len>1024*1024)) csoundDie(csound, Str("Current directory path name too long\n")); goto again; } if (lastIndex == NULL) { return cwd; } len = (lastIndex - tempPath); /* could be 0 on OS 9 */ partialPath = (char *)csound->Calloc(csound, len + 1); strncpy(partialPath, tempPath, len); retval = csoundConcatenatePaths(csound, cwd, partialPath); csound->Free(csound, cwd); csound->Free(csound, partialPath); csound->Free(csound, tempPath); return retval; } static FILE *csoundFindFile_Std(CSOUND *csound, char **fullName, const char *filename, const char *mode, const char *envList) { FILE *f; char *name, *name2, **searchPath; *fullName = NULL; if ((name = csoundConvertPathname(csound, filename)) == NULL) return (FILE*) NULL; if (mode[0] != 'w') { /* read: try the specified name first */ f = fopen(name, mode); if (f != NULL) { *fullName = name; return f; } /* if full path, and not found: */ if (csoundIsNameFullpath(name)) { csound->Free(csound, name); return (FILE*) NULL; } } else if (csoundIsNameFullpath(name)) { /* if write and full path: */ f = fopen(name, mode); if (f != NULL) *fullName = name; else csound->Free(csound, name); return f; } /* search paths defined by environment variable list */ if (envList != NULL && envList[0] != '\0' && (searchPath = csoundGetSearchPathFromEnv((CSOUND*) csound, envList)) != NULL) { //len = (int) strlen(name) + 1; while (*searchPath != NULL) { name2 = csoundConcatenatePaths(csound, *searchPath, name); f = fopen(name2, mode); if (f != NULL) { csound->Free(csound, name); *fullName = name2; return f; } csound->Free(csound, name2); searchPath++; } } /* if write mode, try current directory last */ if (mode[0] == 'w') { f = fopen(name, mode); if (f != NULL) { *fullName = name; return f; } } /* not found */ csound->Free(csound, name); return (FILE*) NULL; } static int csoundFindFile_Fd(CSOUND *csound, char **fullName, const char *filename, int write_mode, const char *envList) { char *name, *name2, **searchPath; int fd; *fullName = NULL; if ((name = csoundConvertPathname(csound, filename)) == NULL) return -1; if (!write_mode) { /* read: try the specified name first */ fd = open(name, RD_OPTS); if (fd >= 0) { *fullName = name; return fd; } /* if full path, and not found: */ if (csoundIsNameFullpath(name)) { csound->Free(csound, name); return -1; } } else if (csoundIsNameFullpath(name)) { /* if write and full path: */ fd = open(name, WR_OPTS); if (fd >= 0) *fullName = name; else csound->Free(csound, name); return fd; } /* search paths defined by environment variable list */ if (envList != NULL && envList[0] != '\0' && (searchPath = csoundGetSearchPathFromEnv((CSOUND*) csound, envList)) != NULL) { //len = (int) strlen(name) + 1; while (*searchPath != NULL) { name2 = csoundConcatenatePaths(csound, *searchPath, name); if (!write_mode) fd = open(name2, RD_OPTS); else fd = open(name2, WR_OPTS); if (fd >= 0) { csound->Free(csound, name); *fullName = name2; return fd; } csound->Free(csound, name2); searchPath++; } } /* if write mode, try current directory last */ if (write_mode) { fd = open(name, WR_OPTS); if (fd >= 0) { *fullName = name; return fd; } } /* not found */ csound->Free(csound, name); return -1; } /** * Search for input file 'filename'. * If the file name specifies full path (it begins with '.', the pathname * delimiter character, or a drive letter and ':' on Windows), that exact * file name is tried without searching. * Otherwise, the file is searched relative to the current directory first, * and if it is still not found, a pathname list that is created the * following way is searched: * 1. if envList is NULL or empty, no directories are searched * 2. envList is parsed as a ';' or ':' separated list of environment * variable names, and all environment variables are expanded and * expected to contain a ';' or ':' separated list of directory names * 2. all directories in the resulting pathname list are searched, starting * from the last and towards the first one, and the directory where the * file is found first will be used * The function returns a pointer to the full name of the file if it is * found, and NULL if the file could not be found in any of the search paths, * or an error has occured. The caller is responsible for freeing the memory * pointed to by the return value, by calling csound->Free(). */ char *csoundFindInputFile(CSOUND *csound, const char *filename, const char *envList) { char *name_found; int fd; if (csound == NULL) return NULL; fd = csoundFindFile_Fd(csound, &name_found, filename, 0, envList); if (fd >= 0) close(fd); return name_found; } /** * Search for a location to write file 'filename'. * If the file name specifies full path (it begins with '.', the pathname * delimiter character, or a drive letter and ':' on Windows), that exact * file name is tried without searching. * Otherwise, a pathname list that is created the following way is searched: * 1. if envList is NULL or empty, no directories are searched * 2. envList is parsed as a ';' separated list of environment variable * names, and all environment variables are expanded and expected to * contain a ';' separated list of directory names * 2. all directories in the resulting pathname list are searched, starting * from the last and towards the first one, and the directory that is * found first where the file can be written to will be used * Finally, if the file cannot be written to any of the directories in the * search paths, writing relative to the current directory is tried. * The function returns a pointer to the full name of the file if a location * suitable for writing the file is found, and NULL if the file cannot not be * written anywhere in the search paths, or an error has occured. * The caller is responsible for freeing the memory pointed to by the return * value, by calling csound->Free(). */ char *csoundFindOutputFile(CSOUND *csound, const char *filename, const char *envList) { char *name_found; int fd; if (csound == NULL) return NULL; fd = csoundFindFile_Fd(csound, &name_found, filename, 1, envList); if (fd >= 0) { close(fd); if (remove(name_found)<0) csound->DebugMsg(csound, Str("Remove failed\n")); } return name_found; } /** * Open a file and return handle. * * CSOUND *csound: * Csound instance pointer * void *fd: * pointer a variable of type int, FILE*, or SNDFILE*, depending on 'type', * for storing handle to be passed to file read/write functions * int type: * file type, one of the following: * CSFILE_FD_R: read file using low level interface (open()) * CSFILE_FD_W: write file using low level interface (open()) * CSFILE_STD: use ANSI C interface (fopen()) * CSFILE_SND_R: read sound file * CSFILE_SND_W: write sound file * const char *name: * file name * void *param: * parameters, depending on type: * CSFILE_FD_R: unused (should be NULL) * CSFILE_FD_W: unused (should be NULL) * CSFILE_STD: mode parameter (of type char*) to be passed to fopen() * CSFILE_SND_R: SF_INFO* parameter for sf_open(), with defaults for * raw file; the actual format paramaters of the opened * file will be stored in this structure * CSFILE_SND_W: SF_INFO* parameter for sf_open(), output file format * const char *env: * list of environment variables for search path (see csoundFindInputFile() * for details); if NULL, the specified name is used as it is, without any * conversion or search. * int csFileType: * A value from the enumeration CSOUND_FILETYPES (see soundCore.h) * int isTemporary: * 1 if this file will be deleted when Csound is finished. * Otherwise, 0. * return value: * opaque handle to the opened file, for use with csoundGetFileName() or * csoundFileClose(), or storing in FDCH.fd. * On failure, NULL is returned. */ void *csoundFileOpenWithType(CSOUND *csound, void *fd, int type, const char *name, void *param, const char *env, int csFileType, int isTemporary) { CSFILE *p = NULL; char *fullName = NULL; FILE *tmp_f = NULL; SF_INFO sfinfo; int tmp_fd = -1, nbytes = (int) sizeof(CSFILE); /* check file type */ if (UNLIKELY((unsigned int) (type - 1) >= (unsigned int) CSFILE_SND_W)) { csoundErrorMsg(csound, Str("internal error: csoundFileOpen(): " "invalid type: %d"), type); return NULL; } /* get full name and open file */ if (env == NULL) { #if defined(WIN32) /* To handle Widows errors in file name characters. */ size_t sz = 2 * MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0); wchar_t *wfname = alloca(sz); wchar_t *wmode = 0; MultiByteToWideChar(CP_UTF8, 0, name, -1, wfname, sz); sz = 2 * MultiByteToWideChar(CP_UTF8, 0, param, -1, NULL, 0); wmode = alloca(sz); MultiByteToWideChar(CP_UTF8, 0, param, -1, wmode, sz); if (type == CSFILE_STD) { tmp_f = _wfopen(wfname, wmode); if (UNLIKELY(tmp_f == NULL)) { /* csoundErrorMsg(csound, Str("csound->FileOpen2(\"%s\") failed: %s."), */ /* name, strerror(errno)); */ goto err_return; } fullName = (char*) name; } #else if (type == CSFILE_STD) { fullName = (char*) name; tmp_f = fopen(fullName, (char*) param); if (UNLIKELY(tmp_f == NULL)) { /* csoundErrorMsg(csound, Str("csound->FileOpen2(\"%s\") failed: %s."), */ /* name, strerror(errno)); */ goto err_return; } } #endif else { fullName = (char*) name; if (type == CSFILE_SND_R || type == CSFILE_FD_R) tmp_fd = open(fullName, RD_OPTS); else tmp_fd = open(fullName, WR_OPTS); if (tmp_fd < 0) goto err_return; } } else { if (type == CSFILE_STD) { tmp_f = csoundFindFile_Std(csound, &fullName, name, (char*) param, env); if (UNLIKELY(tmp_f == NULL)) goto err_return; } else { if (type == CSFILE_SND_R || type == CSFILE_FD_R) tmp_fd = csoundFindFile_Fd(csound, &fullName, name, 0, env); else tmp_fd = csoundFindFile_Fd(csound, &fullName, name, 1, env); if (UNLIKELY(tmp_fd < 0)) goto err_return; } } nbytes += (int) strlen(fullName); /* allocate file structure */ p = (CSFILE*) csound->Malloc(csound, (size_t) nbytes); if (UNLIKELY(p == NULL)) goto err_return; p->nxt = (CSFILE*) csound->open_files; p->prv = (CSFILE*) NULL; p->type = type; p->fd = tmp_fd; p->f = tmp_f; p->sf = (SNDFILE*) NULL; strcpy(&(p->fullName[0]), fullName); if (env != NULL) { csound->Free(csound, fullName); env = NULL; } /* if sound file, re-open file descriptor with libsndfile */ switch (type) { case CSFILE_STD: /* stdio */ *((FILE**) fd) = tmp_f; break; case CSFILE_SND_R: /* sound file read */ memset(&sfinfo, 0, sizeof(SF_INFO)); p->sf = sf_open_fd(tmp_fd, SFM_READ, &sfinfo, 0); if (p->sf == (SNDFILE*) NULL) { int extPos; /* open failed: */ extPos = (nbytes - (int) sizeof(CSFILE)) - 4; /* check for .sd2 file first */ if (extPos > 0 && p->fullName[extPos] == (char) '.' && (p->fullName[extPos + 1] | (char) 0x20) == (char) 's' && (p->fullName[extPos + 2] | (char) 0x20) == (char) 'd' && p->fullName[extPos + 3] == (char) '2') { memset(&sfinfo, 0, sizeof(SF_INFO)); p->sf = sf_open(&(p->fullName[0]), SFM_READ, &sfinfo); if (p->sf != (SNDFILE*) NULL) { /* if successfully opened as .sd2, */ /* the integer file descriptor is no longer needed */ close(tmp_fd); p->fd = tmp_fd = -1; sf_command(p->sf, SFC_SET_VBR_ENCODING_QUALITY, &csound->oparms->quality, sizeof(double)); goto doneSFOpen; } } /* maybe raw file ? rewind and try again */ if (lseek(tmp_fd, (off_t) 0, SEEK_SET) == (off_t) 0) p->sf = sf_open_fd(tmp_fd, SFM_READ, (SF_INFO*) param, 0); if (UNLIKELY(p->sf == (SNDFILE*) NULL)) goto err_return; } else { doneSFOpen: memcpy((SF_INFO*) param, &sfinfo, sizeof(SF_INFO)); } *((SNDFILE**) fd) = p->sf; break; case CSFILE_SND_W: /* sound file write */ p->sf = sf_open_fd(tmp_fd, SFM_WRITE, (SF_INFO*) param, 0); if (UNLIKELY(p->sf == (SNDFILE*) NULL)) goto err_return; sf_command(p->sf, SFC_SET_CLIPPING, NULL, SF_TRUE); sf_command(p->sf, SFC_SET_VBR_ENCODING_QUALITY, &csound->oparms->quality, sizeof(double)); *((SNDFILE**) fd) = p->sf; break; default: /* low level I/O */ *((int*) fd) = tmp_fd; } /* link into chain of open files */ if (csound->open_files != NULL) ((CSFILE*) csound->open_files)->prv = p; csound->open_files = (void*) p; /* notify the host if it asked */ if (csound->FileOpenCallback_ != NULL) { int writing = (type == CSFILE_SND_W || type == CSFILE_FD_W || (type == CSFILE_STD && ((char*)param)[0] == 'w')); if (csFileType == CSFTYPE_UNKNOWN_AUDIO && type == CSFILE_SND_R) csFileType = sftype2csfiletype(((SF_INFO*)param)->format); csound->FileOpenCallback_(csound, p->fullName, csFileType, writing, isTemporary); } /* return with opaque file handle */ p->cb = NULL; p->async_flag = 0; p->buf = NULL; p->bufsize = 0; return (void*) p; err_return: /* clean up on error */ if (p != NULL) csound->Free(csound, p); if (fullName != NULL && env != NULL) csound->Free(csound, fullName); if (tmp_fd >= 0) close(tmp_fd); else if (tmp_f != NULL) fclose(tmp_f); if (type > CSFILE_STD) *((SNDFILE**) fd) = (SNDFILE*) NULL; else if (type == CSFILE_STD) *((FILE**) fd) = (FILE*) NULL; else *((int*) fd) = -1; return NULL; } /** * Allocate a file handle for an existing file already opened with open(), * fopen(), or sf_open(), for later use with csoundFileClose() or * csoundGetFileName(), or storing in an FDCH structure. * Files registered this way (or opened with csoundFileOpen()) are also * automatically closed by csoundReset(). * Parameters and return value are similar to csoundFileOpen(), except * fullName is the name that will be returned by a later call to * csoundGetFileName(). */ void *csoundCreateFileHandle(CSOUND *csound, void *fd, int type, const char *fullName) { CSFILE *p = NULL; int nbytes = (int) sizeof(CSFILE); /* name should not be empty */ if (fullName == NULL || fullName[0] == '\0') return NULL; nbytes += (int) strlen(fullName); /* allocate file structure */ p = (CSFILE*) csound->Malloc(csound, (size_t) nbytes); if (p == NULL) return NULL; p->nxt = (CSFILE*) csound->open_files; p->prv = (CSFILE*) NULL; p->type = type; p->fd = -1; p->f = (FILE*) NULL; p->sf = (SNDFILE*) NULL; p->cb = NULL; strcpy(&(p->fullName[0]), fullName); /* open file */ switch (type) { case CSFILE_FD_R: case CSFILE_FD_W: p->fd = *((int*) fd); break; case CSFILE_STD: p->f = *((FILE**) fd); break; case CSFILE_SND_R: case CSFILE_SND_W: p->sf = *((SNDFILE**) fd); break; default: csoundErrorMsg(csound, Str("internal error: csoundCreateFileHandle(): " "invalid type: %d"), type); csound->Free(csound, p); return NULL; } /* link into chain of open files */ if (csound->open_files != NULL) ((CSFILE*) csound->open_files)->prv = p; csound->open_files = (void*) p; /* return with opaque file handle */ p->cb = NULL; return (void*) p; } /** * Get the full name of a file previously opened with csoundFileOpen(). */ char *csoundGetFileName(void *fd) { return &(((CSFILE*) fd)->fullName[0]); } /** * Close a file previously opened with csoundFileOpen(). */ int csoundFileClose(CSOUND *csound, void *fd) { CSFILE *p = (CSFILE*) fd; int retval = -1; if (p->async_flag == ASYNC_GLOBAL) { csound->WaitThreadLockNoTimeout(csound->file_io_threadlock); /* close file */ switch (p->type) { case CSFILE_FD_R: case CSFILE_FD_W: retval = close(p->fd); break; case CSFILE_STD: retval = fclose(p->f); break; case CSFILE_SND_R: case CSFILE_SND_W: if (p->sf) retval = sf_close(p->sf); p->sf = NULL; if (p->fd >= 0) retval |= close(p->fd); break; } /* unlink from chain of open files */ if (p->prv == NULL) csound->open_files = (void*) p->nxt; else p->prv->nxt = p->nxt; if (p->nxt != NULL) p->nxt->prv = p->prv; if (p->buf != NULL) csound->Free(csound, p->buf); p->bufsize = 0; csound->DestroyCircularBuffer(csound, p->cb); csound->NotifyThreadLock(csound->file_io_threadlock); } else { /* close file */ switch (p->type) { case CSFILE_FD_R: case CSFILE_FD_W: retval = close(p->fd); break; case CSFILE_STD: retval = fclose(p->f); break; case CSFILE_SND_R: case CSFILE_SND_W: retval = sf_close(p->sf); if (p->fd >= 0) retval |= close(p->fd); break; } /* unlink from chain of open files */ if (p->prv == NULL) csound->open_files = (void*) p->nxt; else p->prv->nxt = p->nxt; if (p->nxt != NULL) p->nxt->prv = p->prv; } /* free allocated memory */ csound->Free(csound, fd); /* return with error value */ return retval; } /* Close all open files; called by csoundReset(). */ void close_all_files(CSOUND *csound) { while (csound->open_files != NULL) csoundFileClose(csound, csound->open_files); if (csound->file_io_start) { #ifndef __EMSCRIPTEN__ csound->JoinThread(csound->file_io_thread); #endif if (csound->file_io_threadlock != NULL) csound->DestroyThreadLock(csound->file_io_threadlock); } } /* The fromScore parameter should be 1 if opening a score include file, 0 if opening an orchestra include file */ void *fopen_path(CSOUND *csound, FILE **fp, char *name, char *basename, char *env, int fromScore) { void *fd; int csftype = (fromScore ? CSFTYPE_SCO_INCLUDE : CSFTYPE_ORC_INCLUDE); /* First try to open name given */ fd = csound->FileOpen2(csound, fp, CSFILE_STD, name, "r", NULL, csftype, 0); if (fd != NULL) return fd; /* if that fails try in base directory */ if (basename != NULL) { char *dir, *name_full; if ((dir = csoundSplitDirectoryFromPath(csound, basename)) != NULL) { name_full = csoundConcatenatePaths(csound, dir, name); fd = csound->FileOpen2(csound, fp, CSFILE_STD, name_full, "r", NULL, csftype, 0); csound->Free(csound, dir); csound->Free(csound, name_full); if (fd != NULL) return fd; } } /* or use env argument */ fd = csound->FileOpen2(csound, fp, CSFILE_STD, name, "r", env, csftype, 0); return fd; } void *file_iothread(void *p); void *csoundFileOpenWithType_Async(CSOUND *csound, void *fd, int type, const char *name, void *param, const char *env, int csFileType, int buffsize, int isTemporary) { #ifndef __EMSCRIPTEN__ CSFILE *p; if ((p = (CSFILE *) csoundFileOpenWithType(csound,fd,type,name,param,env, csFileType,isTemporary)) == NULL) return NULL; if (csound->file_io_start == 0) { csound->file_io_start = 1; csound->file_io_threadlock = csound->CreateThreadLock(); csound->NotifyThreadLock(csound->file_io_threadlock); csound->file_io_thread = csound->CreateThread((uintptr_t (*)(void *))file_iothread, (void *) csound); } csound->WaitThreadLockNoTimeout(csound->file_io_threadlock); p->async_flag = ASYNC_GLOBAL; p->cb = csound->CreateCircularBuffer(csound, buffsize*4, sizeof(MYFLT)); p->items = 0; p->pos = 0; p->bufsize = buffsize; p->buf = (MYFLT *) csound->Calloc(csound, sizeof(MYFLT)*buffsize); csound->NotifyThreadLock(csound->file_io_threadlock); if (p->cb == NULL || p->buf == NULL) { /* close file immediately */ csoundFileClose(csound, (void *) p); return NULL; } return (void *) p; #else return NULL; #endif } unsigned int csoundReadAsync(CSOUND *csound, void *handle, MYFLT *buf, int items) { CSFILE *p = handle; if (p != NULL && p->cb != NULL) return csound->ReadCircularBuffer(csound, p->cb, buf, items); else return 0; } unsigned int csoundWriteAsync(CSOUND *csound, void *handle, MYFLT *buf, int items) { CSFILE *p = handle; if (p != NULL && p->cb != NULL) return csound->WriteCircularBuffer(csound, p->cb, buf, items); else return 0; } int csoundFSeekAsync(CSOUND *csound, void *handle, int pos, int whence){ CSFILE *p = handle; int ret = 0; csound->WaitThreadLockNoTimeout(csound->file_io_threadlock); switch (p->type) { case CSFILE_FD_R: break; case CSFILE_FD_W: break; case CSFILE_STD: break; case CSFILE_SND_R: case CSFILE_SND_W: ret = sf_seek(p->sf,pos,whence); //csoundMessage(csound, "seek set %d \n", pos); csound->FlushCircularBuffer(csound, p->cb); p->items = 0; break; } csound->NotifyThreadLock(csound->file_io_threadlock); return ret; } static int read_files(CSOUND *csound){ CSFILE *current = (CSFILE *) csound->open_files; if (current == NULL) return 0; while (current) { if (current->async_flag == ASYNC_GLOBAL) { int m = current->pos, l, n = current->items; int items = current->bufsize; MYFLT *buf = current->buf; switch (current->type) { case CSFILE_FD_R: break; case CSFILE_FD_W: break; case CSFILE_STD: break; case CSFILE_SND_R: if (n == 0) { n = sf_read_MYFLT(current->sf, buf, items); m = 0; } l = csound->WriteCircularBuffer(csound,current->cb,&buf[m],n); m += l; n -= l; current->items = n; current->pos = m; break; case CSFILE_SND_W: items = csound->ReadCircularBuffer(csound, current->cb, buf, items); if (items == 0) { csoundSleep(10); break;} sf_write_MYFLT(current->sf, buf, items); break; } } current = current->nxt; } return 1; } void *file_iothread(void *p){ int res = 1; CSOUND *csound = p; int wakeup = (int) (1000*csound->ksmps/csound->esr); _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); if (wakeup == 0) wakeup = 1; while (res){ csoundSleep(wakeup); csound->WaitThreadLockNoTimeout(csound->file_io_threadlock); res = read_files(csound); csound->NotifyThreadLock(csound->file_io_threadlock); } csound->file_io_start = 0; return NULL; } csound-6.10.0/Engine/extract.c000066400000000000000000000211741321653344700161310ustar00rootroot00000000000000/* extract.c: Copyright (C) 1991 Barry Vercoe This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "sysdep.h" /* EXTRACT.C */ #include "extract.h" extern int realtset(CSOUND *, SRTBLK *); extern MYFLT realt(CSOUND *, MYFLT); static void include(EXTRACT_STATICS*, SRTBLK *); //#define STA(x) (extractStatics->x) static const SRTBLK a0 = { NULL, NULL, 0, 3, FL(0.0), FL(0.0), FL(0.0), FL(0.0), FL(0.0), 0, SP, "a 0 0 0\n" }; static const SRTBLK f0 = { NULL, NULL, 0, 2, FL(0.0), FL(0.0), FL(0.0), FL(0.0), FL(0.0), 0, SP, "f 0 0\n" }; static const SRTBLK e = { NULL, NULL, 0, 0, FL(0.0), FL(0.0), FL(0.0), FL(0.0), FL(0.0), 0, SP, "e\n" }; static void alloc_globals(EXTRACT_STATICS* extractStatics) { memcpy(&extractStatics->a0, &a0, sizeof(SRTBLK)); memcpy(&extractStatics->f0, &f0, sizeof(SRTBLK)); memcpy(&extractStatics->e, &e, sizeof(SRTBLK)); } void readxfil(CSOUND *csound, EXTRACT_STATICS* extractStatics, FILE *xfp) /* read the extract control file */ { int flag, all; char s[128]; alloc_globals(extractStatics); all = 1; flag = 'i'; /* default -i flag supplied */ extractStatics->onsect = 1; extractStatics->onbeat = FL(0.0); /* other default vals */ extractStatics->offsect = 999; extractStatics->offbeat = FL(0.0); // while (fscanf(xfp, s) != EOF) { // while (fscanf(xfp, "%.81s", s) != EOF) { while (fscanf(xfp, "%100s", s) > 0) { // while (fgets(s, 82, xfp) > 0) { char *c = s; int i; //printf("string: %s\n", s); switch (*c) { case 'i': all = 0; // intended no break here case 'f': case 't': flag = *c++; break; default: switch (flag) { case 'i': sscanf(s, "%d", &i); //printf("i: %d\n", i); if (LIKELY(i>=0 && i < INSMAX)) extractStatics->inslst[i] = 1; else csound->Message(csound, Str("instrument number out of range")); all = 0; break; case 'f': //printf("f: %s\n", s); #if defined(USE_DOUBLE) CS_SSCANF(s, "%d:%lf", &extractStatics->onsect, &extractStatics->onbeat); #else CS_SSCANF(s, "%d:%f", &extractStatics->onsect, &extractStatics->onbeat); #endif break; case 't': //printf("t: %s\n"); extractStatics->offsect = extractStatics->onsect; /* default offsect */ #if defined(USE_DOUBLE) CS_SSCANF(s, "%d:%lf", &extractStatics->offsect,&extractStatics->offbeat); #else CS_SSCANF(s, "%d:%f", &extractStatics->offsect, &extractStatics->offbeat); #endif } } } //printf("extract read\n"); if (all) { char *ip; for (ip = &extractStatics->inslst[0]; ip < &extractStatics->inslst[INSMAX]; *ip++ = 1); } extractStatics->ontime = extractStatics->a0.newp3 = extractStatics->a0.p3val = extractStatics->onbeat; extractStatics->offtime = extractStatics->f0.newp2 = extractStatics->f0.p2val = extractStatics->offbeat; } void extract(CSOUND *csound, EXTRACT_STATICS* extractStatics) /* extract instr events within the time period */ { SRTBLK *bp; MYFLT turnoff, anticip; int warped; alloc_globals(extractStatics); if ((bp = csound->frstbp) == NULL) /* if null file */ return; if (++extractStatics->sectno > extractStatics->offsect) { /* or later section, */ csound->frstbp = NULL; return; /* return */ } extractStatics->frstout = extractStatics->prvout = NULL; if (extractStatics->sectno < extractStatics->onsect) { /* for sects preceding, */ do { switch (bp->text[0]) { case 'f': /* include f's at time 0 */ bp->p2val = bp->newp2 = FL(1.0); /* time 1 for now!! */ include(extractStatics, bp); break; case 'w': case 's': case 'e': include(extractStatics, bp); /* incl w,s,e verbatim */ break; case 't': case 'i': case 'a': break; /* but skip all t,i,a */ } } while ((bp = bp->nxtblk) != NULL); } else { /* for sections in timespan: */ do { switch(bp->text[0]) { case 'w': warped = realtset(csound, bp); if (extractStatics->sectno == extractStatics->onsect && warped) extractStatics->ontime = extractStatics->a0.newp3 = realt(csound, extractStatics->onbeat); if (extractStatics->sectno == extractStatics->offsect && warped) extractStatics->offtime = extractStatics->f0.newp2 = realt(csound, extractStatics->offbeat); include(extractStatics, bp); break; case 't': include(extractStatics, bp); break; case 'f': casef: if (extractStatics->sectno == extractStatics->onsect && bp->newp2 < extractStatics->ontime) bp->newp2 = extractStatics->ontime; else if (extractStatics->sectno == extractStatics->offsect && bp->newp2 > extractStatics->offtime) break; if (extractStatics->sectno == extractStatics->onsect && !extractStatics->a0done) { if (extractStatics->onbeat > 0) include(extractStatics, &extractStatics->a0); extractStatics->a0done++; } include(extractStatics, bp); break; case 'i': if (!extractStatics->inslst[bp->insno]) /* skip insnos not required */ break; if (bp->newp3 < 0) /* treat indef dur like f */ goto casef; case 'a':turnoff = bp->newp2 + bp->newp3; /* i and a: */ if (extractStatics->sectno == extractStatics->onsect) { if (turnoff < extractStatics->ontime) break; if ((anticip = extractStatics->ontime - bp->newp2) > 0) { if ((bp->newp3 -= anticip) < FL(0.001)) break; bp->p3val -= extractStatics->onbeat - bp->p2val; bp->newp2 = extractStatics->ontime; bp->p2val = extractStatics->onbeat; } } if (extractStatics->sectno == extractStatics->offsect) { if (bp->newp2 >= extractStatics->offtime) break; if (turnoff > extractStatics->offtime) { bp->newp3 = extractStatics->offtime - bp->newp2; bp->p3val = extractStatics->offbeat - bp->p2val; } } if (extractStatics->sectno == extractStatics->onsect && !extractStatics->a0done) { if (extractStatics->onbeat > 0) include(extractStatics, &extractStatics->a0); extractStatics->a0done++; } include(extractStatics, bp); break; case 's': case 'e': if (extractStatics->sectno == extractStatics->offsect) { include(extractStatics, &extractStatics->f0); include(extractStatics, &extractStatics->e); } else include(extractStatics, bp); break; } } while ((bp = bp->nxtblk) != NULL); } csound->frstbp = extractStatics->frstout; if (extractStatics->prvout != NULL) extractStatics->prvout->nxtblk = NULL; } /* wire a srtblk into the outlist */ static void include(EXTRACT_STATICS* extractStatics, SRTBLK *bp) { if (extractStatics->frstout == NULL) /* first one is special */ extractStatics->frstout = bp; else extractStatics->prvout->nxtblk = bp; /* others just add onto list */ bp->prvblk = extractStatics->prvout; /* maintain the backptr */ extractStatics->prvout = bp; /* and get ready for next */ } csound-6.10.0/Engine/fgens.c000066400000000000000000003367601321653344700155730ustar00rootroot00000000000000/* fgens.c: Copyright (C) 1991, 1994, 1995, 1998, 2000, 2004 Barry Vercoe, John ffitch, Paris Smaragdis, Gabriel Maldonado, Richard Karpen, Greg Sullivan, Pete Moss, Istvan Varga, Victor Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* FGENS.C */ #include #include "soundio.h" #include "cwindow.h" #include "cmath.h" #include "fgens.h" #include "pstream.h" #include "pvfileio.h" #include /* #undef ISSTRCOD */ int isstrcod(MYFLT xx) { #ifdef USE_DOUBLE union { double d; int32_t i[2]; } z; z.d = xx; return ((z.i[1]&0x7ff00000)==0x7ff00000); #else union { float f; int32_t i; } z; z.f = xx; return ((z.i&0x7f800000) == 0x7f800000); #endif } extern double besseli(double); static int gen01raw(FGDATA *, FUNC *); static int gen01(FGDATA *, FUNC *), gen02(FGDATA *, FUNC *); static int gen03(FGDATA *, FUNC *), gen04(FGDATA *, FUNC *); static int gen05(FGDATA *, FUNC *), gen06(FGDATA *, FUNC *); static int gen07(FGDATA *, FUNC *), gen08(FGDATA *, FUNC *); static int gen09(FGDATA *, FUNC *), gen10(FGDATA *, FUNC *); static int gen11(FGDATA *, FUNC *), gen12(FGDATA *, FUNC *); static int gen13(FGDATA *, FUNC *), gen14(FGDATA *, FUNC *); static int gen15(FGDATA *, FUNC *), gen17(FGDATA *, FUNC *); static int gen18(FGDATA *, FUNC *), gen19(FGDATA *, FUNC *); static int gen20(FGDATA *, FUNC *), gen21(FGDATA *, FUNC *); static int gen23(FGDATA *, FUNC *), gen24(FGDATA *, FUNC *); static int gen16(FGDATA *, FUNC *), gen25(FGDATA *, FUNC *); static int gen27(FGDATA *, FUNC *), gen28(FGDATA *, FUNC *); static int gen30(FGDATA *, FUNC *), gen31(FGDATA *, FUNC *); static int gen32(FGDATA *, FUNC *), gen33(FGDATA *, FUNC *); static int gen34(FGDATA *, FUNC *), gen40(FGDATA *, FUNC *); static int gen41(FGDATA *, FUNC *), gen42(FGDATA *, FUNC *); static int gen43(FGDATA *, FUNC *); static int gn1314(FGDATA *, FUNC *, MYFLT, MYFLT); static int gen51(FGDATA *, FUNC *), gen52(FGDATA *, FUNC *); static int gen53(FGDATA *, FUNC *); static int GENUL(FGDATA *, FUNC *); #ifndef NACL static int gen49(FGDATA *, FUNC *); #endif static const GEN or_sub[GENMAX + 1] = { GENUL, gen01, gen02, gen03, gen04, gen05, gen06, gen07, gen08, gen09, gen10, gen11, gen12, gen13, gen14, gen15, gen16, gen17, gen18, gen19, gen20, gen21, GENUL, gen23, gen24, gen25, GENUL, gen27, gen28, GENUL, gen30, gen31, gen32, gen33, gen34, GENUL, GENUL, GENUL, GENUL, GENUL, gen40, gen41, gen42, gen43, GENUL, GENUL, GENUL, GENUL, GENUL, #ifndef NACL gen49, #else GENUL, #endif GENUL, gen51, gen52, gen53, GENUL, GENUL, GENUL, GENUL, GENUL, GENUL, GENUL }; typedef struct namedgen { char *name; int genum; struct namedgen *next; } NAMEDGEN; #define tpd360 (FL(0.0174532925199433)) #define FTAB_SEARCH_BASE (100) CS_NOINLINE int fterror(const FGDATA *, const char *, ...); static CS_NOINLINE void ftresdisp(const FGDATA *, FUNC *); static CS_NOINLINE FUNC *ftalloc(const FGDATA *); static int GENUL(FGDATA *ff, FUNC *ftp) { (void) ftp; return fterror(ff, Str("unknown GEN number")); } static inline unsigned int isPowerOfTwo (unsigned int x) { return (x > 0) && !(x & (x - 1)) ? 1 : 0; } /** * Create ftable using evtblk data, and store pointer to new table in *ftpp. * If mode is zero, a zero table number is ignored, otherwise a new table * number is automatically assigned. * Returns zero on success. */ int hfgens(CSOUND *csound, FUNC **ftpp, const EVTBLK *evtblkp, int mode) { int32 genum, ltest; int lobits, msg_enabled, i; FUNC *ftp; FGDATA ff; int nonpowof2_flag=0; /* gab: fixed for non-powoftwo function tables*/ *ftpp = NULL; if (UNLIKELY(csound->gensub == NULL)) { csound->gensub = (GEN*) csound->Malloc(csound, sizeof(GEN) * (GENMAX + 1)); memcpy(csound->gensub, or_sub, sizeof(GEN) * (GENMAX + 1)); csound->genmax = GENMAX + 1; } msg_enabled = csound->oparms->msglevel & 7; ff.csound = csound; memcpy((char*) &(ff.e), (char*) evtblkp, (size_t) ((char*) &(evtblkp->p[2]) - (char*) evtblkp)); ff.fno = (int) MYFLT2LRND(ff.e.p[1]); if (!ff.fno) { if (!mode) return 0; /* fno = 0: return, */ ff.fno = FTAB_SEARCH_BASE; do { /* or automatic number */ ++ff.fno; } while (ff.fno <= csound->maxfnum && csound->flist[ff.fno] != NULL); ff.e.p[1] = (MYFLT) (ff.fno); } else if (ff.fno < 0) { /* fno < 0: remove */ ff.fno = -(ff.fno); if (UNLIKELY(ff.fno > csound->maxfnum || (ftp = csound->flist[ff.fno]) == NULL)) { return fterror(&ff, Str("ftable does not exist")); } csound->flist[ff.fno] = NULL; csound->Free(csound, (void*) ftp); if (UNLIKELY(msg_enabled)) csoundMessage(csound, Str("ftable %d now deleted\n"), ff.fno); return 0; } if (UNLIKELY(ff.fno > csound->maxfnum)) { /* extend list if necessary */ FUNC **nn; int size; for (size = csound->maxfnum; size < ff.fno; size += MAXFNUM) ; nn = (FUNC**) csound->ReAlloc(csound, csound->flist, (size + 1) * sizeof(FUNC*)); csound->flist = nn; for (i = csound->maxfnum + 1; i <= size; i++) csound->flist[i] = NULL; /* Clear new section */ csound->maxfnum = size; } if (UNLIKELY(ff.e.pcnt <= 4)) { /* chk minimum arg count */ return fterror(&ff, Str("insufficient gen arguments")); } if (UNLIKELY(ff.e.pcnt>PMAX)) { //#ifdef BETA csound->DebugMsg(csound, "T%d/%d(%d): x=%p memcpy from %p to %p length %zu\n", (int)evtblkp->p[1], (int)evtblkp->p[4], ff.e.pcnt, evtblkp->c.extra, &(ff.e.p[2]), &(evtblkp->p[2]), sizeof(MYFLT) * PMAX); //#endif memcpy(&(ff.e.p[2]), &(evtblkp->p[2]), sizeof(MYFLT) * (PMAX-2)); ff.e.c.extra = (MYFLT*)csound->Malloc(csound,sizeof(MYFLT) * (evtblkp->c.extra[0]+1)); memcpy(ff.e.c.extra, evtblkp->c.extra, sizeof(MYFLT) * (evtblkp->c.extra[0]+1)); } else memcpy(&(ff.e.p[2]), &(evtblkp->p[2]), sizeof(MYFLT) * ((int) ff.e.pcnt - 1)); if (isstrcod(ff.e.p[4])) { /* A named gen given so search the list of extra gens */ NAMEDGEN *n = (NAMEDGEN*) csound->namedgen; while (n) { if (strcmp(n->name, ff.e.strarg) == 0) { /* Look up by name */ ff.e.p[4] = genum = n->genum; break; } n = n->next; /* and round again */ } if (UNLIKELY(n == NULL)) { return fterror(&ff, Str("Named gen \"%s\" not defined"), ff.e.strarg); } } else { genum = (int32) MYFLT2LRND(ff.e.p[4]); if (genum < 0) genum = -genum; if (UNLIKELY(!genum || genum > csound->genmax)) { /* & legal gen number x*/ return fterror(&ff, Str("illegal gen number")); } } ff.flen = (int32) MYFLT2LRND(ff.e.p[3]); if (!ff.flen) { /* defer alloc to gen01|gen23|gen28 */ ff.guardreq = 1; if (UNLIKELY(genum != 1 && genum != 23 && genum != 28 && genum != 49)) { return fterror(&ff, Str("deferred size for GENs 1, 23, 28 or 49 only")); } if (UNLIKELY(msg_enabled)) csoundMessage(csound, Str("ftable %d:\n"), ff.fno); i = (*csound->gensub[genum])(&ff, NULL); ftp = csound->flist[ff.fno]; if (i != 0) { csound->flist[ff.fno] = NULL; csound->Free(csound, ftp); return -1; } *ftpp = ftp; return 0; } /* if user flen given */ if (ff.flen < 0L || !isPowerOfTwo(ff.flen&~1)) { /* gab for non-pow-of-two-length */ ff.guardreq = 1; if (ff.flen<0) ff.flen = -(ff.flen); /* gab: fixed */ if (!(ff.flen & (ff.flen - 1L)) || ff.flen > MAXLEN) goto powOfTwoLen; lobits = 0; /* Hope this is not needed! */ nonpowof2_flag = 1; /* gab: fixed for non-powoftwo function tables*/ } else { ff.guardreq = ff.flen & 01; /* set guard request flg */ ff.flen &= -2L; /* flen now w/o guardpt */ powOfTwoLen: if (UNLIKELY(ff.flen <= 0L || ff.flen > MAXLEN)) { return fterror(&ff, Str("illegal table length")); } for (ltest = ff.flen, lobits = 0; (ltest & MAXLEN) == 0L; lobits++, ltest <<= 1) ; if (UNLIKELY(ltest != MAXLEN)) { /* flen is not power-of-2 */ // return fterror(&ff, Str("illegal table length")); //csound->Warning(csound, Str("table %d size not power of two"), ff.fno); lobits = 0; nonpowof2_flag = 1; ff.guardreq = 1; } } ftp = ftalloc(&ff); /* alloc ftable space now */ ftp->lenmask = ((ff.flen & (ff.flen - 1L)) ? 0L : (ff.flen - 1L)); /* init hdr w powof2 data */ ftp->lobits = lobits; i = (1 << lobits); ftp->lomask = (int32) (i - 1); ftp->lodiv = FL(1.0) / (MYFLT) i; /* & other useful vals */ ftp->nchanls = 1; /* presume mono for now */ ftp->flenfrms = ff.flen; if (nonpowof2_flag) ftp->lenmask = 0xFFFFFFFF; /* gab: fixed for non-powoftwo function tables */ if (UNLIKELY(msg_enabled)) csoundMessage(csound, Str("ftable %d:\n"), ff.fno); if ((*csound->gensub[genum])(&ff, ftp) != 0) { csound->flist[ff.fno] = NULL; csound->Free(csound, ftp); return -1; } /* VL 11.01.05 for deferred GEN01, it's called in gen01raw */ ftresdisp(&ff, ftp); /* rescale and display */ *ftpp = ftp; /* keep original arguments, from GEN number */ ftp->argcnt = ff.e.pcnt - 3; { /* Note this does not handle extended args -- JPff */ int size=ftp->argcnt; if (UNLIKELY(size>PMAX-4)) size=PMAX-4; /* printf("size = %d -> %d ftp->args = %p\n", */ /* size, sizeof(MYFLT)*size, ftp->args); */ memcpy(ftp->args, &(ff.e.p[4]), sizeof(MYFLT)*size); /* is this right? */ /*for (k=0; k < size; k++) csound->Message(csound, "%f \n", ftp->args[k]);*/ } return 0; } /** * Allocates space for 'tableNum' with a length (not including the guard * point) of 'len' samples. The table data is not cleared to zero. * Return value is zero on success. */ int csoundFTAlloc(CSOUND *csound, int tableNum, int len) { int i, size; FUNC **nn, *ftp; if (UNLIKELY(tableNum <= 0 || len <= 0 || len > (int) MAXLEN)) return -1; if (UNLIKELY(tableNum > csound->maxfnum)) { /* extend list if necessary */ for (size = csound->maxfnum; size < tableNum; size += MAXFNUM) ; nn = (FUNC**) csound->ReAlloc(csound, csound->flist, (size + 1) * sizeof(FUNC*)); csound->flist = nn; for (i = csound->maxfnum + 1; i <= size; i++) csound->flist[i] = NULL; /* Clear new section */ csound->maxfnum = size; } /* allocate space for table */ size = (int) (len * (int) sizeof(MYFLT)); ftp = csound->flist[tableNum]; if (ftp == NULL) { csound->flist[tableNum] = (FUNC*) csound->Malloc(csound, sizeof(FUNC)); csound->flist[tableNum]->ftable = (MYFLT*)csound->Malloc(csound, sizeof(MYFLT)*(len+1)); } else if (len != (int) ftp->flen) { if (UNLIKELY(csound->actanchor.nxtact != NULL)) { /* & chk for danger */ /* return */ /* VL: changed this into a Warning */ csound->Warning(csound, Str("ftable %d relocating due to size change" "\n currently active instruments " "may find this disturbing"), tableNum); } csound->flist[tableNum] = NULL; csound->Free(csound, ftp); csound->flist[tableNum] = (FUNC*) csound->Malloc(csound, (size_t) size); } /* initialise table header */ ftp = csound->flist[tableNum]; //memset((void*) ftp, 0, (size_t) ((char*) &(ftp->ftable) - (char*) ftp)); ftp->flen = (int32) len; if (!(len & (len - 1))) { /* for power of two length: */ ftp->lenmask = (int32) (len - 1); for (i = len, ftp->lobits = 0L; i < (int) MAXLEN; ftp->lobits++, i <<= 1) ; i = (int) MAXLEN / len; ftp->lomask = (int32) (i - 1); ftp->lodiv = FL(1.0) / (MYFLT) i; } ftp->flenfrms = (int32) len; ftp->nchanls = 1L; ftp->fno = (int32) tableNum; return 0; } /** * Deletes a function table. * Return value is zero on success. */ int csoundFTDelete(CSOUND *csound, int tableNum) { FUNC *ftp; if (UNLIKELY((unsigned int) (tableNum - 1) >= (unsigned int) csound->maxfnum)) return -1; ftp = csound->flist[tableNum]; if (UNLIKELY(ftp == NULL)) return -1; csound->flist[tableNum] = NULL; csound->Free(csound, ftp); return 0; } /* read ftable values directly from p-args */ static int gen02(FGDATA *ff, FUNC *ftp) { MYFLT *fp = ftp->ftable, *pp = &(ff->e.p[5]); int nvals = ff->e.pcnt - 4; int nsw = 1; CSOUND *csound = ff->csound; if (UNLIKELY(ff->e.pcnt>=PMAX)) csound->Warning(csound, Str("using extended arguments\n")); if (nvals >= (int) ff->flen) nvals = (int) ff->flen + 1; /* for all vals up to flen+1 */ while (nvals--) { *fp++ = *pp++; /* copy into ftable */ if (UNLIKELY(nsw && pp>&ff->e.p[PMAX])) { #ifdef BETA csound->DebugMsg(csound, "Switch to extra args\n"); #endif nsw = 0; /* only switch once */ pp = &(ff->e.c.extra[1]); } } return OK; } static int gen03(FGDATA *ff, FUNC *ftp) { int ncoefs, nargs = ff->e.pcnt - 4; MYFLT xintvl, xscale; int xloc, nlocs; MYFLT *fp = ftp->ftable, x, sum, *coefp, *coef0, *coeflim; if (UNLIKELY((ncoefs = nargs - 2) <= 0)) { return fterror(ff, Str("no coefs present")); } coef0 = &ff->e.p[7]; coeflim = coef0 + ncoefs; if (UNLIKELY((xintvl = ff->e.p[6] - ff->e.p[5]) <= 0)) { return fterror(ff, Str("illegal x interval")); } xscale = xintvl / (MYFLT)ff->flen; xloc = (int) (ff->e.p[5] / xscale); /* initial xloc */ nlocs = (int) ff->flen + 1; do { /* for each loc: */ x = xloc++ * xscale; coefp = coeflim; sum = *--coefp; /* init sum to coef(n) */ while (coefp > coef0) { sum *= x; /* & accum by Horner's rule */ sum += *--coefp; } *fp++ = sum; } while (--nlocs); return OK; } static int gen04(FGDATA *ff, FUNC *ftp) { CSOUND *csound = ff->csound; MYFLT *valp, *rvalp, *fp = ftp->ftable; int n, r; FUNC *srcftp; MYFLT val, max, maxinv; int srcno, srcpts, ptratio; if (UNLIKELY(ff->e.pcnt < 6)) { return fterror(ff, Str("insufficient arguments")); } if (UNLIKELY((srcno = (int)ff->e.p[5]) <= 0 || srcno > csound->maxfnum || (srcftp = csound->flist[srcno]) == NULL)) { return fterror(ff, Str("unknown srctable number")); } if (!ff->e.p[6]) { srcpts = srcftp->flen; valp = srcftp->ftable; rvalp = NULL; } else { srcpts = srcftp->flen >>1; valp = &srcftp->ftable[srcpts]; rvalp = valp - 1; } if (UNLIKELY((ptratio = srcpts / ff->flen) < 1)) { return fterror(ff, Str("table size too large")); } if ((val = *valp++)) { if (val < FL(0.0)) val = -val; max = val; maxinv = FL(1.0) / max; } else { max = FL(0.0); maxinv = FL(1.0); } *fp++ = maxinv; for (n = ff->flen; n--; ) { for (r = ptratio; r--; ) { if ((val = *valp++)) { if (val < FL(0.0)) val = -val; if (val > max) { max = val; maxinv = FL(1.0) / max; } } if (rvalp != NULL && (val = *rvalp--)) { if (val < 0.) val = -val; if (val > max) { max = val; maxinv = FL(1.0) / max; } } } *fp++ = maxinv; } ff->guardreq = 1; /* disable new guard point */ ff->e.p[4] = -FL(4.0); /* and rescaling */ return OK; } static int gen05(FGDATA *ff, FUNC *ftp) { int nsegs, seglen; MYFLT *valp, *fp, *finp; MYFLT amp1, mult; int nsw = 1; CSOUND *csound = ff->csound; if (UNLIKELY(ff->e.pcnt>=PMAX)) csound->Warning(csound, Str("using extended arguments\n")); if ((nsegs = (ff->e.pcnt-5) >> 1) <= 0) /* nsegs = nargs-1 /2 */ return OK; valp = &ff->e.p[5]; fp = ftp->ftable; finp = fp + ff->flen; if (UNLIKELY(*valp == 0)) goto gn5er2; do { amp1 = *valp++; if (UNLIKELY(nsw && valp>&ff->e.p[PMAX])) { valp = &(ff->e.c.extra[1]); nsw = 0; } if (!(seglen = (int)*valp++)) { if (UNLIKELY(nsw && valp>&ff->e.p[PMAX])) { valp = &(ff->e.c.extra[1]); nsw = 0; } continue; } if (UNLIKELY(nsw && valp>&ff->e.p[PMAX])) { valp = &(ff->e.c.extra[1]); nsw = 0; } if (UNLIKELY(seglen < 0)) goto gn5er1; if (UNLIKELY((mult = *valp/amp1) <= 0)) goto gn5er2; mult = POWER(mult, FL(1.0)/seglen); while (seglen--) { *fp++ = amp1; amp1 *= mult; if (fp > finp) return OK; } } while (--nsegs); if (fp == finp) /* if 2**n pnts, add guardpt */ *fp = amp1; return OK; gn5er1: return fterror(ff, Str("gen call has negative segment size:")); gn5er2: return fterror(ff, Str("illegal input vals for gen call, beginning:")); } static int gen07(FGDATA *ff, FUNC *ftp) { int nsegs, seglen; MYFLT *valp, *fp, *finp; MYFLT amp1, incr; if ((nsegs = (ff->e.pcnt-5) >> 1) <= 0) /* nsegs = nargs-1 /2 */ return OK; valp = &ff->e.p[5]; fp = ftp->ftable; finp = fp + ff->flen; do { amp1 = *valp++; if (!(seglen = (int)*valp++)) continue; if (UNLIKELY(seglen < 0)) goto gn7err; incr = (*valp - amp1) / seglen; while (seglen--) { *fp++ = amp1; amp1 += incr; if (fp > finp) return OK; } } while (--nsegs); if (fp == finp) /* if 2**n pnts, add guardpt */ *fp = amp1; return OK; gn7err: return fterror(ff, Str("gen call has negative segment size:")); } static int gen06(FGDATA *ff, FUNC *ftp) { MYFLT *segp, *extremp, *inflexp, *segptsp, *fp, *finp; MYFLT y, diff2; int pntno, pntinc, nsegs, npts; int nsw = 1; CSOUND *csound = ff->csound; if (UNLIKELY(ff->e.pcnt>=PMAX)) csound->Warning(csound, Str("using extended arguments\n")); if (UNLIKELY((nsegs = ((ff->e.pcnt - 5) >> 1)) < 1)) { return fterror(ff, Str("insufficient arguments")); } fp = ftp->ftable; finp = fp + ff->flen; pntinc = 1; for (segp = &ff->e.p[3], segptsp = &ff->e.p[4]; nsegs > 0; nsegs--) { segp += 1; if (UNLIKELY(nsw && segp>&ff->e.p[PMAX])) { segp = &(ff->e.c.extra[1]); nsw = 0; } segp += 1; if (UNLIKELY(nsw && segp>&ff->e.p[PMAX])) { segp = &(ff->e.c.extra[1]); nsw = 0; } segptsp = segp + 1; if (UNLIKELY(nsw && segptsp>&ff->e.p[PMAX])) { segptsp = &(ff->e.c.extra[1]); } if (UNLIKELY((npts = (int)*segptsp) < 0)) { return fterror(ff, Str("negative segsiz")); } if (pntinc > 0) { pntno = 0; inflexp = segp + 1; if (UNLIKELY(nsw && inflexp>&ff->e.p[PMAX])) { inflexp = &(ff->e.c.extra[1]); } inflexp++; if (UNLIKELY(nsw && inflexp>&ff->e.p[PMAX])) { inflexp = &(ff->e.c.extra[1]); } extremp = segp; } else { pntno = npts; inflexp = segp; extremp = segp + 1; if (UNLIKELY(nsw && extremp>&ff->e.p[PMAX])) { extremp = &(ff->e.c.extra[1]); } extremp++; if (UNLIKELY(nsw && extremp>&ff->e.p[PMAX])) { extremp = &(ff->e.c.extra[1]); } } diff2 = (*inflexp - *extremp) * FL(0.5); for ( ; npts > 0 && fp < finp; pntno += pntinc, npts--) { y = (MYFLT)pntno / *segptsp; *fp++ = (FL(3.0)-y) * y * y * diff2 + *extremp; } pntinc = -pntinc; } segp += 1; if (UNLIKELY(nsw && segp>&ff->e.p[PMAX])) { segp = &(ff->e.c.extra[1]); nsw = 0; } segp += 1; if (UNLIKELY(nsw && segp>&ff->e.p[PMAX])) { segp = &(ff->e.c.extra[1]); nsw = 0; } *fp = *(segp); /* write last target point */ return OK; } static int gen08(FGDATA *ff, FUNC *ftp) { MYFLT R, x, c3, c2, c1, c0, *fp, *fplim, *valp; MYFLT f2 = FL(0.0), f1, f0, df1, df0, dx01, dx12 = FL(0.0), curx; MYFLT slope, resd1, resd0; int nsegs, npts; CSOUND *csound = ff->csound; int nsw = 1; if (UNLIKELY(ff->e.pcnt>=PMAX)) csound->Warning(csound, Str("using extended arguments\n")); if (UNLIKELY((nsegs = (ff->e.pcnt - 5) >> 1) <= 0)) { return fterror(ff, Str("insufficient arguments")); } valp = &ff->e.p[5]; fp = ftp->ftable; fplim = fp + ff->flen; f0 = *valp++; /* 1st 3 params give vals at x0, x1 */ if (UNLIKELY((dx01 = *valp++) <= FL(0.0))) { /* and dist between*/ return fterror(ff, Str("illegal x interval")); } f1 = *valp++; curx = df0 = FL(0.0); /* init x to origin; slope at x0 = 0 */ do { /* for each spline segmnt (x0 to x1) */ if (nsegs > 1) { /* if another seg to follow */ MYFLT dx02; if (UNLIKELY((dx12 = *valp++) <= FL(0.0))) { /* read its distance */ return fterror(ff, Str("illegal x interval")); } f2 = *valp++; /* and the value at x2 */ if (UNLIKELY(UNLIKELY(nsw && valp>&ff->e.p[PMAX]))) { #ifdef BETA csound->DebugMsg(csound, "Switch to extra args\n"); #endif nsw = 0; /* only switch once */ valp = &(ff->e.c.extra[1]); } dx02 = dx01 + dx12; df1 = ( f2*dx01*dx01 + f1*(dx12-dx01)*dx02 - f0*dx12*dx12 ) / (dx01*dx02*dx12); } /* df1 is slope of parabola at x1 */ else df1 = FL(0.0); if ((npts = (int) (dx01 - curx)) > fplim - fp) npts = fplim - fp; if (npts > 0) { /* for non-trivial segment: */ slope = (f1 - f0) / dx01; /* get slope x0 to x1 */ resd0 = df0 - slope; /* then residual slope */ resd1 = df1 - slope; /* at x0 and x1 */ c3 = (resd0 + resd1) / (dx01*dx01); c2 = - (resd1 + FL(2.0)*resd0) / dx01; c1 = df0; /* and calc cubic coefs */ c0 = f0; for (x = curx; npts>0; --npts, x += FL(1.0)) { R = c3; R *= x; R += c2; /* f(x) = ((c3 x + c2) x + c1) x + c0 */ R *= x; R += c1; R *= x; R += c0; *fp++ = R; /* store n pts for this seg */ } curx = x; } curx -= dx01; /* back up x by length last segment */ dx01 = dx12; /* relocate to the next segment */ f0 = f1; /* by assuming its parameters */ f1 = f2; df0 = df1; } while (--nsegs && fpflen; CSOUND *csound = ff->csound; int nsw = 1; if (UNLIKELY(ff->e.pcnt>=PMAX)) csound->Warning(csound, Str("using extended arguments\n")); if ((hcnt = (ff->e.pcnt - 4) / 3) <= 0) /* hcnt = nargs / 3 */ return OK; valp = &ff->e.p[5]; finp = &ftp->ftable[ff->flen]; do { inc = *(valp++) * tpdlen; if (UNLIKELY(nsw && valp>&ff->e.p[PMAX])) { #ifdef BETA csound->DebugMsg(csound, "Switch to extra args\n"); #endif nsw = 0; /* only switch once */ valp = &(ff->e.c.extra[1]); } amp = *(valp++); if (UNLIKELY(nsw && valp>&ff->e.p[PMAX])) { #ifdef BETA csound->DebugMsg(csound, "Switch to extra args\n"); #endif nsw = 0; /* only switch once */ valp = &(ff->e.c.extra[1]); } phs = *(valp++) * tpd360; if (UNLIKELY(nsw && valp>&ff->e.p[PMAX])) { #ifdef BETA csound->DebugMsg(csound, "Switch to extra args\n"); #endif nsw = 0; /* only switch once */ valp = &(ff->e.c.extra[1]); } for (fp = ftp->ftable; fp <= finp; fp++) { *fp += (MYFLT) (sin(phs) * amp); if (UNLIKELY((phs += inc) >= TWOPI)) phs -= TWOPI; } } while (--hcnt); return OK; } static int gen10(FGDATA *ff, FUNC *ftp) { int32 phs, hcnt; MYFLT amp, *fp, *finp; int32 flen = ff->flen; double tpdlen = TWOPI / (double) flen; CSOUND *csound = ff->csound; if (UNLIKELY(ff->e.pcnt>=PMAX)) csound->Warning(csound, Str("using extended arguments\n")); hcnt = ff->e.pcnt - 4; /* hcnt is nargs */ finp = &ftp->ftable[flen]; do { MYFLT *valp = (hcnt+4>=PMAX ? &ff->e.c.extra[hcnt+5-PMAX] : &ff->e.p[hcnt + 4]); if ((amp = *valp) != FL(0.0)) /* for non-0 amps, */ for (phs = 0, fp = ftp->ftable; fp <= finp; fp++) { *fp += (MYFLT) sin(phs * tpdlen) * amp; /* accum sin pts */ phs += hcnt; /* phsinc is hno */ phs %= flen; } } while (--hcnt); return OK; } static int gen11(FGDATA *ff, FUNC *ftp) { MYFLT *fp, *finp; int32 phs; double x; MYFLT denom, r, scale; int n, k; int nargs = ff->e.pcnt - 4; if (UNLIKELY((n = (int) ff->e.p[5]) < 1)) { return fterror(ff, Str("nh partials < 1")); } k = 1; r = FL(1.0); if (ff->e.pcnt > 5) k = (int) ff->e.p[6]; if (nargs > 2) r = ff->e.p[7]; fp = ftp->ftable; finp = fp + ff->flen; if (ff->e.pcnt == 5 || (k == 1 && r == FL(1.0))) { /* simple "buzz" case */ int tnp1; MYFLT pdlen; tnp1 = (n << 1) + 1; scale = FL(0.5) / n; pdlen = PI_F / (MYFLT) ff->flen; for (phs = 0; fp <= finp; phs++) { x = phs * pdlen; if (!(denom = (MYFLT) sin(x))) *fp++ = FL(1.0); else *fp++ = ((MYFLT) sin(tnp1 * x) / denom - FL(1.0)) * scale; } } else { /* complex "gbuzz" case */ double tpdlen = TWOPI / (double) ff->flen; MYFLT numer, twor, rsqp1, rtn, rtnp1, absr; int km1, kpn, kpnm1; km1 = k - 1; kpn = k + n; kpnm1 = kpn - 1; twor = r * FL(2.0); rsqp1 = r * r + FL(1.0); rtn = intpow(r, (int32) n); rtnp1 = rtn * r; if ((absr = FABS(r)) > FL(0.999) && absr < FL(1.001)) scale = FL(1.0) / n; else scale = (FL(1.0) - absr) / (FL(1.0) - FABS(rtn)); for (phs = 0; fp <= finp; phs++) { x = (double) phs * tpdlen; numer = (MYFLT)cos(x*k) - r * (MYFLT)cos(x*km1) - rtn*(MYFLT)cos(x*kpn) + rtnp1 * (MYFLT)cos(x*kpnm1); if ((denom = rsqp1 - twor * (MYFLT) cos(x)) > FL(0.0001) || denom < -FL(0.0001)) *fp++ = numer / denom * scale; else *fp++ = FL(1.0); } } return OK; } static int gen12(FGDATA *ff, FUNC *ftp) { static const double coefs[] = { 3.5156229, 3.0899424, 1.2067492, 0.2659732, 0.0360768, 0.0045813 }; const double *coefp, *cplim = coefs + 6; double sum, tsquare, evenpowr; int n; MYFLT *fp; double xscale; xscale = (double) ff->e.p[5] / ff->flen / 3.75; for (n = 0, fp = ftp->ftable; n <= ff->flen; n++) { tsquare = (double) n * xscale; tsquare *= tsquare; for (sum = evenpowr = 1.0, coefp = coefs; coefp < cplim; coefp++) { evenpowr *= tsquare; sum += *coefp * evenpowr; } *fp++ = (MYFLT) log(sum); } return OK; } static int gen13(FGDATA *ff, FUNC *ftp) { return gn1314(ff, ftp, FL(2.0), FL(0.5)); } static int gen14(FGDATA *ff, FUNC *ftp) { return gn1314(ff, ftp, FL(1.0), FL(1.0)); } static int gn1314(FGDATA *ff, FUNC *ftp, MYFLT mxval, MYFLT mxscal) { CSOUND *csound = ff->csound; int32 nh, nn; MYFLT *mp, *mspace, *hp, *oddhp; MYFLT xamp, xintvl, scalfac, sum, prvm; int nsw = 1; if (UNLIKELY(ff->e.pcnt>=PMAX)) csound->Warning(csound, Str("using extended arguments\n")); if (UNLIKELY((nh = ff->e.pcnt - 6) <= 0)) { return fterror(ff, Str("insufficient arguments")); } if (UNLIKELY((xintvl = ff->e.p[5]) <= 0)) { return fterror(ff, Str("illegal xint value")); } if (UNLIKELY((xamp = ff->e.p[6]) <= 0)) { return fterror(ff, Str("illegal xamp value")); } ff->e.p[5] = -xintvl; ff->e.p[6] = xintvl; nn = nh * sizeof(MYFLT) / 2; /* alloc spc for terms 3,5,7,..*/ mp = mspace = (MYFLT *) csound->Calloc(csound, nn); /* of 1st row of matrix, and */ for (nn = (nh + 1) >>1; --nn; ) /* form array of non-0 terms */ *mp++ = mxval = -mxval; /* -val, val, -val, val ... */ scalfac = 2 / xamp; hp = &ff->e.p[7]; /* beginning with given h0, */ do { mp = mspace; oddhp = hp; sum = *oddhp++; /* sum = diag(=1) * this h */ if (UNLIKELY(nsw && oddhp>&ff->e.p[PMAX])) { #ifdef BETA csound->DebugMsg(csound, "Switch to extra args\n"); #endif nsw = 0; /* only switch once */ oddhp = &(ff->e.c.extra[1]); } for (nn = (nh+1) >>1; --nn; ) { int nnsw = nsw; oddhp++; /* + odd terms * h+2,h+4,.. */ if (UNLIKELY(nnsw && oddhp>&ff->e.p[PMAX])) { #ifdef BETA csound->DebugMsg(csound, "Switch to extra args\n"); #endif nnsw = 0; /* only switch once */ oddhp = &(ff->e.c.extra[1]); } sum += *mp++ * *oddhp++; if (UNLIKELY(nnsw && oddhp>&ff->e.p[PMAX])) { #ifdef BETA csound->DebugMsg(csound, "Switch to extra args\n"); #endif nnsw = 0; /* only switch once */ oddhp = &(ff->e.c.extra[1]); } } *hp++ = sum * mxscal; /* repl this h w. coef (sum) */ if (UNLIKELY(nsw && hp>&ff->e.p[PMAX])) { #ifdef BETA csound->DebugMsg(csound, "Switch to extra args\n"); #endif nsw = 0; /* only switch once */ hp = &(ff->e.c.extra[1]); } mp = mspace; prvm = FL(1.0); for (nn = nh>>1; --nn > 0; mp++) /* calc nxt row matrix terms */ *mp = prvm = *mp - prvm; mxscal *= scalfac; } while (--nh); /* loop til all h's replaced */ csound->Free(csound,mspace); return gen03(ff, ftp); /* then call gen03 to write */ } static int gen15(FGDATA *ff, FUNC *ftp) { MYFLT xint, xamp, *hsin, h, angle; MYFLT *fp, *cosp, *sinp; int n, nh; void *lp13; int nargs = ff->e.pcnt - 4; CSOUND *csound = ff->csound; int nsw = 1; if (UNLIKELY(ff->e.pcnt>=PMAX)) csound->Warning(csound, Str("using extended arguments\n")); if (UNLIKELY(nargs & 01)) { return fterror(ff, Str("uneven number of args")); } hsin = (MYFLT*)csound->Malloc(csound,sizeof(MYFLT)*((1+ff->e.pcnt)/2)); nh = (nargs - 2) >>1; fp = &ff->e.p[5]; /* save p5, p6 */ xint = *fp++; xamp = *fp++; for (n = nh, cosp = fp, sinp = hsin; n > 0; n--) { h = *fp++; /* rpl h,angle pairs */ if (UNLIKELY(nsw && fp>&ff->e.p[PMAX])) { #ifdef BETA csound->DebugMsg(csound, "Switch to extra args\n"); #endif nsw = 0; /* only switch once */ fp = &(ff->e.c.extra[1]); } angle = (MYFLT) (*fp++ * tpd360); *cosp++ = h * COS(angle); /* with h cos angle */ *sinp++ = h * SIN(angle); /* and save the sine */ } nargs -= nh; ff->e.pcnt = (int16)(nargs + 4); /* added by F. Pinot 16-01-2012 */ if (UNLIKELY(gen13(ff, ftp) != OK)) { /* call gen13 */ csound->Free(csound,hsin); return NOTOK; } lp13 = (void*) ftp; ff->fno++; /* alloc eq. space for fno+1 */ ftp = ftalloc(ff); /* & copy header */ memcpy((void*) ftp, lp13, (size_t) sizeof(FUNC)-sizeof(MYFLT*)); ftp->fno = (int32) ff->fno; fp = &ff->e.p[5]; nsw = 1; *fp++ = xint; /* restore p5, p6, */ *fp++ = xamp; for (n = nh-1, sinp = hsin+1; n > 0; n--) { /* then skip h0*sin */ *fp++ = *sinp++; /* & copy rem hn*sin */ if (UNLIKELY(nsw && fp>&ff->e.p[PMAX])) { #ifdef BETA csound->DebugMsg(csound, "Switch to extra args\n"); #endif nsw = 0; /* only switch once */ fp = &(ff->e.c.extra[1]); } } nargs--; ff->e.pcnt = (int16)(nargs + 4); /* added by F. Pinot 16-01-2012 */ csound->Free(csound,hsin); n = gen14(ff, ftp); /* now draw ftable */ ftresdisp(ff, ftp); /* added by F. Pinot 16-01-2012 */ ff->fno--; /* F. Pinot, the first function table */ /* is scaled and displayed by hfgens */ return n; } static int gen16(FGDATA *ff, FUNC *ftp) { MYFLT *fp, *valp, val; int nargs = ff->e.pcnt - 4; int nseg = nargs / 3; fp = ftp->ftable; valp = &ff->e.p[5]; *fp++ = val = *valp++; while (nseg-- > 0) { MYFLT dur = *valp++; MYFLT alpha = *valp++; MYFLT nxtval = *valp++; int32 cnt = (int32) (dur + FL(0.5)); if (alpha == FL(0.0)) { MYFLT c1 = (nxtval-val)/dur; while (cnt-- > 0) { *fp++ = val = val + c1; } } else { MYFLT c1 = (nxtval - val)/(FL(1.0) - EXP(alpha)); MYFLT x; alpha /= dur; x = alpha; while (cnt-->0) { *fp++ = val + c1 * (FL(1.0) - EXP(x)); x += alpha; } val = *(fp-1); } } return OK; } static int gen17(FGDATA *ff, FUNC *ftp) { int nsegs, ndx, nxtndx; MYFLT *valp, *fp, *finp; MYFLT val; int nargs = ff->e.pcnt - 4; CSOUND *csound = ff->csound; int nsw = 1; if (UNLIKELY(ff->e.pcnt>=PMAX)) csound->Warning(csound, Str("using extended arguments\n")); if ((nsegs = nargs >> 1) <= 0) /* nsegs = nargs /2 */ goto gn17err; valp = &ff->e.p[5]; fp = ftp->ftable; finp = fp + ff->flen; if (UNLIKELY((ndx = (int)*valp++) != 0)) goto gn17err; while (--nsegs) { val = *valp++; if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1])) nsw =0, valp = &(ff->e.c.extra[1]); if (UNLIKELY((nxtndx = (int)*valp++) <= ndx)) goto gn17err; if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1])) nsw =0, valp = &(ff->e.c.extra[1]); do { *fp++ = val; if (fp > finp) return OK; } while (++ndx < nxtndx); } val = *valp; while (fp <= finp) /* include 2**n + 1 guardpt */ *fp++ = val; return OK; gn17err: return fterror(ff, Str("gen call has illegal x-ordinate values:")); } /* by pete moss (petemoss@petemoss.org), jan 2002 */ static int gen18(FGDATA *ff, FUNC *ftp) { CSOUND *csound = ff->csound; int cnt, start, finish, fnlen, j; MYFLT *pp = &ff->e.p[5], fn, amp, *fp, *fp18 = ftp->ftable, range, f; double i; FUNC *fnp; int nargs = ff->e.pcnt - 4; int nsw = 1; if (UNLIKELY(ff->e.pcnt>=PMAX)) csound->Warning(csound, Str("using extended arguments\n")); if (UNLIKELY((cnt = nargs >> 2) <= 0)) { return fterror(ff, Str("wrong number of args")); } while (cnt--) { fn=*pp++; if (UNLIKELY(nsw && pp>=&ff->e.p[PMAX-1])) nsw =0, pp = &(ff->e.c.extra[1]); amp=*pp++; if (UNLIKELY(nsw && pp>=&ff->e.p[PMAX-1])) nsw =0, pp = &(ff->e.c.extra[1]); start=(int)*pp++; if (UNLIKELY(nsw && pp>=&ff->e.p[PMAX-1])) nsw =0, pp = &(ff->e.c.extra[1]); finish=(int)*pp++; if (UNLIKELY(nsw && pp>=&ff->e.p[PMAX-1])) nsw =0, pp = &(ff->e.c.extra[1]); if (UNLIKELY((start>ff->flen) || (finish>=ff->flen))) { /* make sure start and finish < flen */ return fterror(ff, Str("a range given exceeds table length")); } if (LIKELY((fnp=csoundFTFind(csound,&fn))!=NULL)) { /* make sure fn exists */ fp = fnp->ftable, fnlen = fnp->flen-1; /* and set it up */ } else { return fterror(ff, Str("an input function does not exist")); } range = (MYFLT) (finish - start), j = start; while (j <= finish) { /* write the table */ unsigned int ii; f = (MYFLT)modf((fnlen*(j - start)/range), &i); ii = (unsigned int)i; //printf("***ii=%d f=%g\n", ii, f); if (ii==fnp->flen) fp18[j++] += amp * fp[ii]; else fp18[j++] += amp * ((f * (fp[ii+1] - fp[ii])) + fp[ii]); } } return OK; } static int gen19(FGDATA *ff, FUNC *ftp) { int hcnt; MYFLT *valp, *fp, *finp; double phs, inc, amp, dc, tpdlen = TWOPI / (double) ff->flen; int nargs = ff->e.pcnt - 4; CSOUND *csound = ff->csound; int nsw = 1; if (UNLIKELY(ff->e.pcnt>=PMAX)) csound->Warning(csound, Str("using extended arguments\n")); if ((hcnt = nargs / 4) <= 0) /* hcnt = nargs / 4 */ return OK; valp = &ff->e.p[5]; finp = &ftp->ftable[ff->flen]; do { inc = *(valp++) * tpdlen; if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1])) nsw =0, valp = &(ff->e.c.extra[1]); amp = *(valp++); if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1])) nsw =0, valp = &(ff->e.c.extra[1]); phs = *(valp++) * tpd360; if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1])) nsw =0, valp = &(ff->e.c.extra[1]); dc = *(valp++); if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1])) nsw =0, valp = &(ff->e.c.extra[1]); for (fp = ftp->ftable; fp <= finp; fp++) { *fp += (MYFLT) (sin(phs) * amp + dc); /* dc after str scale */ if ((phs += inc) >= TWOPI) phs -= TWOPI; } } while (--hcnt); return OK; } /* GEN20 and GEN21 by Paris Smaragdis 1994 B.C.M. Csound development team */ static int gen20(FGDATA *ff, FUNC *ftp) { MYFLT cf[4], *ft; double arg, x, xarg, beta = 0.0,varian = 1.0; int i, nargs = ff->e.pcnt - 4; ft = ftp->ftable; xarg = 1.0; if (ff->e.p[4] < FL(0.0)) { xarg = ff->e.p[6]; if ( nargs < 2 ) xarg = 1.0; } if (nargs > 2) { beta = (double) ff->e.p[7]; varian = (double) ff->e.p[7]; } switch ((int) ff->e.p[5]) { case 1: /* Hamming */ cf[0] = FL(0.54); cf[1] = FL(0.46); cf[2] = cf[3] = FL(0.0); break; case 2: /* Hanning */ cf[0] = cf[1] = FL(0.5); cf[2] = cf[3] = FL(0.0); break; case 3: /* Bartlett */ arg = 2.0/ff->flen; for (i = 0, x = 0.0 ; i < ((int) ff->flen >> 1) ; i++, x++) ft[i] = (MYFLT) (x * arg * xarg); for ( ; i < (int) ff->flen ; i++, x++) ft[i] = (MYFLT) ((2.0 - x * arg) * xarg); return OK; case 4: /* Blackman */ cf[0] = FL(0.42); cf[1] = FL(0.5); cf[2] = FL(0.08); cf[3] = FL(0.0); break; case 5: /* Blackman-Harris */ cf[0] = FL(0.35878); cf[1] = FL(0.48829); cf[2] = FL(0.14128); cf[3] = FL(0.01168); break; case 6: /* Gaussian */ arg = 12.0 / ff->flen; for (i = 0, x = -6.0 ; i < ((int) ff->flen >> 1) ; i++, x += arg) ft[i] = (MYFLT)(xarg * (pow(2.718281828459,-(x*x)/(2.0*varian*varian)))); for (x = 0.0 ; i <= (int) ff->flen ; i++, x += arg) ft[i] = (MYFLT)(xarg * (pow(2.718281828459,-(x*x)/(2.0*varian*varian)))); return OK; case 7: /* Kaiser */ { double flen2 = 4.0 / ((double) ff->flen * (double) ff->flen); double besbeta = 1.0 / besseli(beta); x = (double) ff->flen * (-0.5) + 1.0; ft[0] = ft[ff->flen] = (MYFLT) (xarg * besbeta); for (i = 1 ; i < (int) ff->flen ; i++, x += 1.0) ft[i] = (MYFLT) (xarg * besseli(beta * sqrt(1.0 - x * x * flen2)) * besbeta); return OK; } case 8: /* Rectangular */ for (i = 0; i <= (int) ff->flen ; i++) ft[i] = FL(1.0); return OK; case 9: /* Sinc */ arg = TWOPI / ff->flen; for (i = 0, x = -PI ; i < ((int) ff->flen >> 1) ; i++, x += arg) ft[i] = (MYFLT) (xarg * sin(x) / x); ft[i++] = (MYFLT) xarg; for (x = arg ; i <= (int) ff->flen ; i++, x += arg) ft[i] = (MYFLT) (xarg * sin(x) / x); return OK; default: return fterror(ff, Str("No such window type!")); } arg = TWOPI / ff->flen; for (i = 0, x = 0.0 ; i <= (int) ff->flen ; i++, x += arg) ft[i] = (MYFLT) (xarg * (cf[0] - cf[1]*cos(x) + cf[2]*cos(2.0 * x) - cf[3]*cos(3.0 * x))); return OK; } static int gen21(FGDATA *ff, FUNC *ftp) { int retval = gen21_rand(ff, ftp); switch (retval) { case 0: break; case -1: return fterror(ff, Str("Wrong number of input arguments")); case -2: return fterror(ff, Str("unknown distribution")); default: return NOTOK; } return OK; } static MYFLT nextval(FILE *f) { /* Read the next charcater; suppress multiple space and comments to a single space */ int c; top: c = getc(f); top1: if (UNLIKELY(feof(f))) return NAN; /* Hope value is ignored */ if (isdigit(c) || c=='e' || c=='E' || c=='+' || c=='-' || c=='.') { double d; /* A number starts */ char buff[128]; int j = 0; do { /* Fill buffer */ buff[j++] = c; c = getc(f); } while (isdigit(c) || c=='e' || c=='E' || c=='+' || c=='-' || c=='.'); buff[j]='\0'; d = atof(buff); if (c==';' || c=='#') { /* If exended with comment clear it now */ while ((c = getc(f)) != '\n'); } return (MYFLT)d; } while (isspace(c) || c == ',') c = getc(f); /* Whitespace */ if (c==';' || c=='#' || c=='<') { /* Comment and tag*/ while ((c = getc(f)) != '\n'); } if (isdigit(c) || c=='e' || c=='E' || c=='+' || c=='-' || c=='.') goto top1; goto top; } static int gen23(FGDATA *ff, FUNC *ftp) /* ASCII file table read Gab 17-feb-98*/ /* Modified after Paris Smaragdis by JPff */ { /* And further hacked 2009 by JPff */ CSOUND *csound = ff->csound; MYFLT *fp; FILE *infile; void *fd; int j; MYFLT tmp; fd = csound->FileOpen2(csound, &infile, CSFILE_STD, ff->e.strarg, "r", "SFDIR;SSDIR;INCDIR", CSFTYPE_FLOATS_TEXT, 0); if (UNLIKELY(fd == NULL)) { return fterror(ff, Str("error opening ASCII file")); } if (ftp == NULL) { /* Start counting elements */ ff->flen = 0; do { ff->flen++; nextval(infile); } while (!feof(infile)); ff->flen--; // overshoots by 1 csoundMessage(csound, Str("%ld elements in %s\n"), (long) ff->flen, ff->e.strarg); rewind(infile); /* Allocate memory and read them in now */ /* ff->flen = ff->flen + 2; ??? */ ftp = ftalloc(ff); ftp->lenmask = 0xFFFFFFFF; /* avoid the error in csoundFTFind */ } fp = ftp->ftable; j = 0; while (!feof(infile) && j < ff->flen) fp[j++] = nextval(infile); tmp = nextval(infile); // overshot value if (UNLIKELY(!feof(infile))) csound->Warning(csound, Str("Number(s) after table full in GEN23, starting %f"), tmp); csound->FileClose(csound, fd); // if (def) { MYFLT *tab = ftp->ftable; tab[ff->flen] = tab[0]; /* guard point */ //ftp->flen -= 1; /* exclude guard point */ ftresdisp(ff, ftp); /* VL: 11.01.05 for deferred alloc tables */ } return OK; } static int gen24(FGDATA *ff, FUNC *ftp) { CSOUND *csound = ff->csound; MYFLT *fp = ftp->ftable, *fp_source; FUNC *srcftp; int srcno, srcpts, j; MYFLT max, min, new_max, new_min, source_amp, target_amp, amp_ratio; int nargs = ff->e.pcnt - 4; if (UNLIKELY(nargs < 3)) { return fterror(ff, Str("insufficient arguments")); } if (UNLIKELY((srcno = (int) ff->e.p[5]) <= 0 || srcno > csound->maxfnum || (srcftp = csound->flist[srcno]) == NULL)) { return fterror(ff, Str("unknown srctable number")); } fp_source = srcftp->ftable; new_min = ff->e.p[6]; new_max = ff->e.p[7]; srcpts = srcftp->flen; if (UNLIKELY(srcpts!= ff->flen)) { return fterror(ff, Str("table size must be the same of source table")); } max = min = fp_source[0]; for (j = 0; j < srcpts; j++) { if (fp_source[j] > max ) max = fp_source[j]; if (fp_source[j] < min ) min = fp_source[j]; } source_amp = max - min; target_amp = new_max - new_min; amp_ratio = target_amp/source_amp; for (j = 0; j < srcpts; j++) { fp[j] = (fp_source[j]-min) * amp_ratio + new_min; } fp[j] = fp[j-1]; return OK; } static int gen25(FGDATA *ff, FUNC *ftp) { int nsegs, seglen; MYFLT *valp, *fp, *finp; MYFLT x1, x2, y1, y2, mult; int nargs = ff->e.pcnt - 4; CSOUND *csound = ff->csound; int nsw = 1; if (UNLIKELY(ff->e.pcnt>=PMAX)) csound->Warning(csound, Str("using extended arguments\n")); if ((nsegs = ((nargs / 2) - 1)) <= 0) return OK; valp = &ff->e.p[5]; fp = ftp->ftable; finp = fp + ff->flen; do { x1 = *valp++; if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1])) nsw =0, valp = &(ff->e.c.extra[1]); y1 = *valp++; if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1])) nsw =0, valp = &(ff->e.c.extra[1]); x2 = *valp++; if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1])) nsw =0, valp = &(ff->e.c.extra[1]); if (LIKELY(nsegs > 1)) { y2 = *valp++; if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1])) nsw =0, valp = &(ff->e.c.extra[1]); } else y2 = *valp; if (UNLIKELY(x2 < x1)) goto gn25err; if (UNLIKELY(x1 > ff->flen || x2 > ff->flen)) goto gn25err2; seglen = (int)(x2-x1); if (UNLIKELY(y1 <= 0 || y2 <= 0)) goto gn25err3; mult = y2/y1; mult = POWER(mult, FL(1.0)/seglen); while (seglen--) { *fp++ = y1; y1 *= mult; if (fp > finp) return OK; } valp -= 2; } while (--nsegs); if (fp == finp) /* if 2**n pnts, add guardpt */ *fp = y1; return OK; gn25err: return fterror(ff, Str("x coordinates must all be in increasing order:")); gn25err2: return fterror(ff, Str("x coordinate greater than function size:")); gn25err3: return fterror(ff, Str("illegal input val (y <= 0) for gen call, beginning:")); } static int gen27(FGDATA *ff, FUNC *ftp) { int nsegs; MYFLT *valp, *fp, *finp; MYFLT x1, x2, y1, y2, yy, seglen, incr; int nargs = ff->e.pcnt - 4; CSOUND *csound = ff->csound; int nsw = 1; if (UNLIKELY(ff->e.pcnt>=PMAX)) csound->Warning(csound, Str("using extended arguments\n")); if ((nsegs = ((nargs / 2) - 1)) <= 0) return OK; valp = &ff->e.p[5]; fp = ftp->ftable; finp = fp + ff->flen; //printf("valp=%p end=%p extra=%p\n", // valp, &ff->e.p[PMAX-1], &(ff->e.c.extra[1])); x2 = *valp++; y2 = *valp++; do { x1 = x2; y1 = y2; x2 = *valp++; if (UNLIKELY(nsw && valp>&ff->e.p[PMAX-1])) { //printf("extend: valp=%p extra=%p\n", valp, &(ff->e.c.extra[1])); nsw =0, valp = &(ff->e.c.extra[1]); //printf("extendx2: valp=%p\n", valp); } //if (nsw==0) printf("extend: valp=%p\n", valp); if (LIKELY(nsegs > 1)) { y2 = *valp++; if (UNLIKELY(nsw && valp>&ff->e.p[PMAX-1])) { //printf("extendy2: valp=%p extra=%p\n", valp, &(ff->e.c.extra[1])); nsw =0, valp = &(ff->e.c.extra[1]); //printf("extend: valp=%p\n", valp); } } else { y2 = *valp; //printf("end of list: valp = %p x1,y1,x2,y2 = %f,%f,%f,%f\n", // valp, x1, y1, x2, y2); } if (UNLIKELY(x2 < x1)) goto gn27err; if (UNLIKELY(x1 > ff->flen || x2 > ff->flen)) goto gn27err2; seglen = x2-x1; incr = (y2 - y1) / seglen; yy = y1; while (seglen--) { *fp++ = yy; yy += incr; if (fp > finp) return OK; } } while (--nsegs); if (fp == finp) /* if 2**n pnts, add guardpt */ *fp = y1; return OK; gn27err: printf("nsegs=%d x1,y1 = %f,%f x2,y2 = %f,%f\n", nsegs, x1, y1, x2, y2); return fterror(ff, Str("x coordinates must all be in increasing order:")); gn27err2: return fterror(ff, Str("x coordinate greater than function size:")); } /* read X Y values directly from ascii file */ static int gen28(FGDATA *ff, FUNC *ftp) { CSOUND *csound = ff->csound; MYFLT *fp = ftp->ftable, *finp; int seglen, resolution = 100; FILE *filp; void *fd; int i=0, j=0; MYFLT *x, *y, *z; int arraysize = 1000; MYFLT x1, y1, z1, x2, y2, z2, incrx, incry; if (UNLIKELY(ff->flen)) return fterror(ff, Str("GEN28 requires zero table length")); fd = csound->FileOpen2(csound, &filp, CSFILE_STD, ff->e.strarg, "r", "SFDIR;SSDIR;INCDIR", CSFTYPE_FLOATS_TEXT, 0); if (UNLIKELY(fd == NULL)) goto gen28err1; x = (MYFLT*)csound->Malloc(csound,arraysize*sizeof(MYFLT)); y = (MYFLT*)csound->Malloc(csound,arraysize*sizeof(MYFLT)); z = (MYFLT*)csound->Malloc(csound,arraysize*sizeof(MYFLT)); #if defined(USE_DOUBLE) while (fscanf( filp, "%lf%lf%lf", &z[i], &x[i], &y[i])!= EOF) #else while (fscanf( filp, "%f%f%f", &z[i], &x[i], &y[i])!= EOF) #endif { i++; if (UNLIKELY(i>=arraysize)) { MYFLT* newx, *newy, *newz; arraysize += 1000; newx = (MYFLT*)realloc(x, arraysize*sizeof(MYFLT)); newy = (MYFLT*)realloc(y, arraysize*sizeof(MYFLT)); newz = (MYFLT*)realloc(z, arraysize*sizeof(MYFLT)); if (UNLIKELY(!newx || !newy || !newz)) { fprintf(stderr, Str("Out of Memory\n")); exit(7); } x = newx; y = newy; z = newz; } } --i; ff->flen = (int32) (z[i] * resolution * 2); ff->flen = ff->flen + 2; /* ??? */ ftp = ftalloc(ff); fp = ftp->ftable; finp = fp + ff->flen; do { x1 = x[j]; y1 = y[j]; x2 = x[j+1]; y2 = y[j+1]; z1 = z[j]; z2 = z[j+1]; if (UNLIKELY(z2 < z1)) goto gen28err2; seglen = (int)((z2-z1) * resolution); incrx = (x2 - x1) / (MYFLT)seglen; incry = (y2 - y1) / (MYFLT)seglen; while (seglen--) { *fp++ = x1; x1 += incrx; *fp++ = y1; y1 += incry; } j++; } while (--i); do { *fp++ = x[j]; *fp++ = y[j+1]; } while (fp < finp); csound->Free(csound,x); csound->Free(csound,y); csound->Free(csound,z); csound->FileClose(csound, fd); return OK; gen28err1: return fterror(ff, Str("could not open space file")); gen28err2: csound->Free(csound,x); csound->Free(csound,y); csound->Free(csound,z); return fterror(ff, Str("Time values must be in increasing order")); } /* gen30: extract a range of harmonic partials from source table */ static int gen30(FGDATA *ff, FUNC *ftp) { CSOUND *csound = ff->csound; MYFLT *x, *f1, *f2; int l1, l2, minh = 0, maxh = 0, i; MYFLT xsr, minfrac, maxfrac; int nargs = ff->e.pcnt - 4; if (UNLIKELY(nargs < 3)) { return fterror(ff, Str("insufficient gen arguments")); } xsr = FL(1.0); if ((nargs > 3) && (ff->e.p[8] > FL(0.0))) xsr = csound->esr / ff->e.p[8]; l2 = csoundGetTable(csound, &f2, (int) ff->e.p[5]); if (UNLIKELY(l2 < 0)) { return fterror(ff, Str("GEN30: source ftable not found")); } f1 = ftp->ftable; l1 = (int) ftp->flen; minfrac = ff->e.p[6]; /* lowest harmonic partial number */ maxfrac = ff->e.p[7] * xsr; /* highest harmonic partial number */ i = (l1 < l2 ? l1 : l2) >> 1; /* sr/2 limit */ /* limit to 0 - sr/2 range */ if ((maxfrac < FL(0.0)) || (minfrac > (MYFLT) i)) return OK; if (maxfrac > (MYFLT) i) maxfrac = (MYFLT) i; if (minfrac < FL(0.0)) minfrac = FL(0.0); if ((nargs > 4) && (ff->e.p[9] != FL(0.0))) { minh = (int) minfrac; /* "interpolation" mode */ minfrac -= (MYFLT) minh; minfrac = FL(1.0) - minfrac; maxh = (int) maxfrac; maxfrac -= (MYFLT) (maxh++); if (maxh > i) { maxh = i; maxfrac = FL(1.0); } } else { minh = (int) ((double) minfrac + (i < 10000 ? 0.99 : 0.9)); maxh = (int) ((double) maxfrac + (i < 10000 ? 0.01 : 0.1)); minfrac = maxfrac = FL(1.0); } if (minh > maxh) return OK; i = (l1 > l2 ? l1 : l2) + 2; x = (MYFLT*) csound->Malloc(csound,sizeof(MYFLT) * i); /* read src table with amplitude scale */ xsr = csound->GetInverseRealFFTScale(csound, l1) * (MYFLT) l1 / (MYFLT) l2; for (i = 0; i < l2; i++) x[i] = xsr * f2[i]; /* filter */ csound->RealFFT(csound, x, l2); x[l2] = x[1]; x[1] = x[l2 + 1] = FL(0.0); for (i = 0; i < (minh << 1); i++) x[i] = FL(0.0); x[i++] *= minfrac; x[i] *= minfrac; i = maxh << 1; x[i++] *= maxfrac; x[i++] *= maxfrac; for ( ; i < (l1 + 2); i++) x[i] = FL(0.0); x[1] = x[l1]; x[l1] = x[l1 + 1] = FL(0.0); csound->InverseRealFFT(csound, x, l1); /* write dest. table */ /* memcpy(f1, x, l1*sizeof(MYFLT)); */ for (i = 0; i < l1; i++) f1[i] = x[i]; f1[l1] = f1[0]; /* write guard point */ csound->Free(csound,x); return OK; } /* gen31: transpose, phase shift, and mix source table */ static int gen31(FGDATA *ff, FUNC *ftp) { CSOUND *csound = ff->csound; MYFLT *x, *y, *f1, *f2; MYFLT a, p; double d_re, d_im, p_re, p_im, ptmp; int i, j, k, n, l1, l2; int nargs = ff->e.pcnt - 4; MYFLT *valp = &ff->e.p[6]; int nsw = 1; if (UNLIKELY(ff->e.pcnt>=PMAX)) csound->Warning(csound, Str("using extended arguments\n")); if (UNLIKELY(nargs < 4)) { return fterror(ff, Str("insufficient gen arguments")); } l2 = csoundGetTable(csound, &f2, (int) ff->e.p[5]); if (UNLIKELY(l2 < 0)) { return fterror(ff, Str("GEN31: source ftable not found")); } f1 = ftp->ftable; l1 = (int) ftp->flen; x = (MYFLT*) csound->Calloc(csound, (l2 + 2)*sizeof(MYFLT)); y = (MYFLT*) csound->Calloc(csound, l1 + 2*sizeof(MYFLT)); /* read and analyze src table, apply amplitude scale */ a = csound->GetInverseRealFFTScale(csound, l1) * (MYFLT) l1 / (MYFLT) l2; for (i = 0; i < l2; i++) x[i] = a * f2[i]; csound->RealFFT(csound, x, l2); x[l2] = x[1]; x[1] = x[l2 + 1] = FL(0.0); for (j = 6; j < (nargs + 3); j+=3) { n = (int) (FL(0.5) + *valp++); if (n < 1) n = 1; /* frequency */ if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1])) nsw =0, valp = &(ff->e.c.extra[1]); a = *valp++; /* amplitude */ if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1])) nsw =0, valp = &(ff->e.c.extra[1]); p = *valp++; /* phase */ if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1])) nsw =0, valp = &(ff->e.c.extra[1]); //p -= (MYFLT) ((int) p); { MYFLT dummy = FL(0.0); p = MODF(p, &dummy); } if (UNLIKELY(p < FL(0.0))) p += FL(1.0); p *= TWOPI_F; d_re = cos((double) p); d_im = sin((double) p); p_re = 1.0; p_im = 0.0; /* init. phase */ for (i = k = 0; (i <= l1 && k <= l2); i += (n << 1), k += 2) { /* mix to table */ y[i + 0] += a * (x[k + 0] * (MYFLT) p_re - x[k + 1] * (MYFLT) p_im); y[i + 1] += a * (x[k + 1] * (MYFLT) p_re + x[k + 0] * (MYFLT) p_im); /* update phase */ ptmp = p_re * d_re - p_im * d_im; p_im = p_im * d_re + p_re * d_im; p_re = ptmp; } } /* write dest. table */ y[1] = y[l1]; y[l1] = y[l1 + 1] = FL(0.0); csound->InverseRealFFT(csound, y, l1); /* memcpy(f1, y, l1*sizeof(MYFLT)); */ for (i = 0; i < l1; i++) f1[i] = y[i]; f1[l1] = f1[0]; /* write guard point */ csound->Free(csound,x); csound->Free(csound,y); return OK; } /* gen32: transpose, phase shift, and mix source tables */ static inline MYFLT paccess(FGDATA *ff, int i) { if (LIKELY(ie.p[i]; else return ff->e.c.extra[i-PMAX+1]; } static int gen32(FGDATA *ff, FUNC *ftp) { CSOUND *csound = ff->csound; MYFLT *x, *y, *f1, *f2; MYFLT a, p; double d_re, d_im, p_re, p_im, ptmp; int i, j, k, n, l1, l2, ntabl, *pnum, ft; int nargs = ff->e.pcnt - 4; if (UNLIKELY(ff->e.pcnt>=PMAX)) { csound->Warning(csound, Str("using extended arguments\n")); } if (UNLIKELY(nargs < 4)) { return fterror(ff, Str("insufficient gen arguments")); } ntabl = nargs >> 2; /* number of waves to mix */ pnum = (int*) csound->Malloc(csound,sizeof(int) * ntabl); for (i = 0; i < ntabl; i++) pnum[i] = (i << 2) + 5; /* p-field numbers */ do { i = k = 0; /* sort by table number */ while (i < (ntabl - 1)) { if (paccess(ff,pnum[i]) > paccess(ff,pnum[i + 1])) { j = pnum[i]; pnum[i] = pnum[i + 1]; pnum[i + 1] = j; k = 1; } i++; } } while (k); f1 = ftp->ftable; l1 = (int) ftp->flen; memset(f1, 0, l1*sizeof(MYFLT)); /* for (i = 0; i <= l1; i++) */ /* f1[i] = FL(0.0); */ x = y = NULL; ft = 0x7FFFFFFF; /* last table number */ j = -1; /* current wave number */ while (++j < ntabl) { p = paccess(ff,pnum[j]); /* table number */ i = (int) MYFLT2LRND(p); l2 = csoundGetTable(csound, &f2, abs(i)); if (UNLIKELY(l2 < 0)) { fterror(ff, Str("GEN32: source ftable %d not found"), abs(i)); if (x != NULL) csound->Free(csound,x); if (y != NULL) csound->Free(csound,y); csound->Free(csound,pnum); return NOTOK; } if (i < 0) { /* use linear interpolation */ ft = i; p_re = (double) paccess(ff,pnum[j] + 3); /* start phase */ p_re -= (double) ((int) p_re); if (p_re < 0.0) p_re++; p_re *= (double) l2; d_re = (double) paccess(ff,pnum[j] + 1); /* frequency */ d_re *= (double) l2 / (double) l1; a = paccess(ff,pnum[j] + 2); /* amplitude */ for (i = 0; i <= l1; i++) { k = (int) p_re; p = (MYFLT) (p_re - (double) k); if (k >= l2) k -= l2; f1[i] += f2[k++] * a * (FL(1.0) - p); f1[i] += f2[k] * a * p; p_re += d_re; while (p_re < 0.0) p_re += (double) l2; while (p_re >= (double) l2) p_re -= (double) l2; } } else { /* use FFT */ if (i != ft) { ft = i; /* new table */ if (y == NULL) y = (MYFLT*) csound->Calloc(csound,(l1 + 2)*sizeof (MYFLT)); if (x != NULL) csound->Free(csound,x); x = (MYFLT*) csound->Calloc(csound,(l2 + 2)*sizeof (MYFLT)); /* read and analyze src table */ for (i = 0; i < l2; i++) x[i] = f2[i]; csound->RealFFT(csound, x, l2); x[l2] = x[1]; x[1] = x[l2 + 1] = FL(0.0); } n = (int) (FL(0.5) + paccess(ff,pnum[j] + 1)); /* frequency */ if (n < 1) n = 1; a = paccess(ff,pnum[j] + 2) * (MYFLT) l1 / (MYFLT) l2; /* amplitude */ a *= csound->GetInverseRealFFTScale(csound, (int) l1); p = paccess(ff,pnum[j] + 3); /* phase */ p -= (MYFLT) ((int) p); if (p < FL(0.0)) p += FL(1.0); p *= TWOPI_F; d_re = cos ((double) p); d_im = sin ((double) p); p_re = 1.0; p_im = 0.0; /* init. phase */ if (y != NULL) for (i = k = 0; (i <= l1 && k <= l2); i += (n << 1), k += 2) { /* mix to table */ y[i + 0] += a * (x[k + 0] * (MYFLT) p_re - x[k + 1] * (MYFLT) p_im); y[i + 1] += a * (x[k + 1] * (MYFLT) p_re + x[k + 0] * (MYFLT) p_im); /* update phase */ ptmp = p_re * d_re - p_im * d_im; p_im = p_im * d_re + p_re * d_im; p_re = ptmp; } } } /* write dest. table */ if (y != NULL) { y[1] = y[l1]; y[l1] = y[l1 + 1] = FL(0.0); csound->InverseRealFFT(csound, y, l1); for (i = 0; i < l1; i++) f1[i] += y[i]; f1[l1] += y[0]; /* write guard point */ csound->Free(csound,x); /* free tmp memory */ csound->Free(csound,y); } csound->Free(csound,pnum); return OK; } /* GEN33 by Istvan Varga */ static int gen33(FGDATA *ff, FUNC *ftp) { CSOUND *csound = ff->csound; MYFLT fmode, *ft, *srcft, scl, amp, phs; MYFLT *x; int nh, flen, srclen, i, pnum, maxp; int nargs = ff->e.pcnt - 4; if (UNLIKELY(nargs < 3)) { return fterror(ff, Str("insufficient gen arguments")); } if (nargs > 3) /* check optional argument */ fmode = ff->e.p[8]; else fmode = FL(0.0); /* table length and data */ ft = ftp->ftable; flen = (int) ftp->flen; /* source table */ srclen = csoundGetTable(csound, &srcft, (int) ff->e.p[5]); if (UNLIKELY(srclen < 0)) { return fterror(ff, Str("GEN33: source ftable not found")); } /* number of partials */ nh = (int) (ff->e.p[6] + FL(0.5)); if (UNLIKELY(nh > (srclen / 3))) nh = srclen / 3; if (UNLIKELY(nh < 0)) nh = 0; /* amplitude scale */ scl = FL(0.5) * (MYFLT) flen * ff->e.p[7]; scl *= csound->GetInverseRealFFTScale(csound, flen); /* frequency mode */ if (fmode < FL(0.0)) { fmode = (MYFLT) flen / (csound->esr * -fmode); /* frequency in Hz */ } else if (fmode > FL(0.0)) { fmode = (MYFLT) flen / fmode; /* ref. sample rate */ } else { fmode = FL(1.0); /* partial number */ } /* allocate memory for tmp data */ x = (MYFLT*) csound->Calloc(csound,(flen + 2)*sizeof(MYFLT)); maxp = flen >> 1; /* max. partial number */ i = nh; while (i--) { /* amplitude */ amp = scl * *(srcft++); /* partial number */ pnum = (int) MYFLT2LRND(fmode * *srcft); srcft++; if (UNLIKELY(pnum < (-maxp) || pnum > maxp)) { srcft++; continue; /* skip partial with too high frequency */ } /* initial phase */ phs = TWOPI_F * *(srcft++); if (UNLIKELY(pnum < 0)) { phs = PI_F - phs; pnum = -pnum; /* negative frequency */ } /* mix to FFT data */ x[pnum << 1] += amp * SIN(phs); x[(pnum << 1) + 1] -= amp * COS(phs); } csound->InverseRealFFT(csound, x, flen); /* iFFT */ memcpy(ft, x, flen*sizeof(MYFLT)); /* for (i = 0; i < flen; i++) /\* copy to output table *\/ */ /* ft[i] = x[i]; */ ft[flen] = x[0]; /* write guard point */ /* free tmp memory */ csound->Free(csound,x); return OK; } /* GEN34 by Istvan Varga */ static int gen34(FGDATA *ff, FUNC *ftp) { CSOUND *csound = ff->csound; MYFLT fmode, *ft, *srcft, scl; double y0, y1, x, c, v, *xn, *cn, *vn, *tmp, amp, frq, phs; int32 nh, flen, srclen, i, j, k, l, bs; FUNC *src; int nargs = ff->e.pcnt - 4; if (UNLIKELY(nargs < 3)) { return fterror(ff, Str("insufficient gen arguments")); } if (nargs > 3) /* check optional argument */ fmode = ff->e.p[8]; else fmode = FL(0.0); /* table length and data */ ft = ftp->ftable; flen = (int32) ftp->flen; /* source table */ if (UNLIKELY((src = csoundFTnp2Find(csound, &(ff->e.p[5]))) == NULL)) return NOTOK; srcft = src->ftable; srclen = (int32) src->flen; /* number of partials */ nh = (int32) (ff->e.p[6] + FL(0.5)); if (UNLIKELY(nh > (srclen / 3L))) nh = srclen / 3L; if (UNLIKELY(nh < 0L)) nh = 0L; /* amplitude scale */ scl = ff->e.p[7]; /* frequency mode */ if (fmode < FL(0.0)) { fmode = TWOPI_F / (csound->esr * -fmode); /* frequency in Hz */ } else if (fmode > FL(0.0)) { fmode = TWOPI_F / fmode; /* ref. sample rate */ } else { fmode = TWOPI_F / (MYFLT) flen; /* partial number */ } /* use blocks of 256 samples (2048 bytes) for speed */ bs = 256L; /* allocate memory for tmp data */ tmp = (double*) csound->Malloc(csound, sizeof(double) * bs); xn = (double*) csound->Malloc(csound, sizeof(double) * (nh + 1L)); cn = (double*) csound->Malloc(csound, sizeof(double) * (nh + 1L)); vn = (double*) csound->Malloc(csound, sizeof(double) * (nh + 1L)); /* initialise oscillators */ i = -1L; while (++i < nh) { amp = (double) scl * (double) *(srcft++); /* amplitude */ frq = (double) fmode * (double) *(srcft++); /* frequency */ if (UNLIKELY(fabs (frq) > PI)) { xn[i] = cn[i] = vn[i] = 0.0; srcft++; continue; /* skip partial with too high frequency */ } phs = TWOPI * (double) *(srcft++); /* phase */ /* calculate coeffs for fast sine oscillator */ y0 = sin(phs); /* sample 0 */ y1 = sin(phs + frq); /* sample 1 */ xn[i] = y0; cn[i] = 2.0 * cos(frq) - 2.0; vn[i] = y1 - cn[i] * y0 - y0; /* amp. scale */ xn[i] *= amp; vn[i] *= amp; } /* render output */ j = flen + 1L; /* include guard point */ do { k = (j > bs ? bs : j); /* block size */ /* clear buffer */ memset(tmp, 0, k*sizeof(double)); /* for (i = 0L; i < k; i++) tmp[i] = 0.0; */ /* fast sine oscillator */ i = -1L; while (++i < nh) { x = xn[i]; c = cn[i]; v = vn[i]; l = k; do { *(tmp++) += x; v += c * x; x += v; } while (--l); tmp -= k; /* restore pointer */ xn[i] = x; vn[i] = v; /* save oscillator state */ } /* write to output table */ for (i = 0L; i < k; i++) *(ft++) = (MYFLT) tmp[i]; j -= k; } while (j); /* free tmp buffers */ csound->Free(csound,tmp); csound->Free(csound,xn); csound->Free(csound,cn); csound->Free(csound,vn); return OK; } static int gen40(FGDATA *ff, FUNC *ftp) /*gab d5*/ { CSOUND *csound = ff->csound; MYFLT *fp = ftp->ftable, *fp_source, *fp_temp; FUNC *srcftp; int srcno, srcpts, j, k; MYFLT last_value = FL(0.0), lenratio; if (UNLIKELY((srcno = (int) ff->e.p[5]) <= 0 || srcno > csound->maxfnum || (srcftp = csound->flist[srcno]) == NULL)) { return fterror(ff, Str("unknown source table number")); } fp_source = srcftp->ftable; srcpts = srcftp->flen; fp_temp = (MYFLT *) csound->Calloc(csound,srcpts*sizeof(MYFLT)); for (j = 0; j < srcpts; j++) { last_value += fp_source[j]; fp_temp[j] = last_value; } lenratio = (ff->flen-1)/last_value; for (j = 0; j < ff->flen; j++) { k=0; while ( k++ < srcpts && fp_temp[k] * lenratio < j) ; k--; fp[j] = (MYFLT) k; } fp[j] = fp[j-1]; csound->Free(csound,fp_temp); return OK; } static int gen41(FGDATA *ff, FUNC *ftp) /*gab d5*/ { MYFLT *fp = ftp->ftable, *pp = &ff->e.p[5]; int i, j, k, width; MYFLT tot_prob = FL(0.0); int nargs = ff->e.pcnt - 4; for (j=0; j < nargs; j+=2) { if (UNLIKELY(pp[j+1]<0)) return fterror(ff, Str("Gen41: negative probability not allowed")); tot_prob += pp[j+1]; } //printf("total prob = %g\n", tot_prob); for (i=0, j=0; j< nargs; j+=2) { width = (int) ((pp[j+1]/tot_prob) * ff->flen +.5); for ( k=0; k < width; k++,i++) { fp[i] = pp[j]; } } //printf("GEN41: i=%d le=%d\n", i, ff->flen); if (UNLIKELY(i<=ff->flen)) fp[i] = pp[j-1]; /* conditional is attempt to stop error */ return OK; } static int gen42(FGDATA *ff, FUNC *ftp) /*gab d5*/ { MYFLT *fp = ftp->ftable, inc; int j, k, width; MYFLT tot_prob = FL(0.0); int nargs = ff->e.pcnt - 4; CSOUND *csound = ff->csound; int nsw = 1; MYFLT *valp = &ff->e.p[5]; if (UNLIKELY(ff->e.pcnt>=PMAX)) csound->Warning(csound, Str("using extended arguments\n")); for (j=0; j < nargs; j+=3) { if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1])) nsw =0, valp = &(ff->e.c.extra[1]); valp++; if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1])) nsw =0, valp = &(ff->e.c.extra[1]); valp++; if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1])) nsw =0, valp = &(ff->e.c.extra[1]); tot_prob += *valp++; } nsw = 1; valp = &ff->e.p[5]; for (j=0; j< nargs; j+=3) { MYFLT p1, p2, p3; p1 = *valp++; if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1])) nsw =0, valp = &(ff->e.c.extra[1]); p2 = *valp++; if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1])) nsw =0, valp = &(ff->e.c.extra[1]); p3 = *valp++; if (UNLIKELY(nsw && valp>=&ff->e.p[PMAX-1])) nsw =0, valp = &(ff->e.c.extra[1]); width = (int) ((p3/tot_prob) * ff->flen +FL(0.5)); inc = (p2-p1) / (MYFLT) (width-1); for ( k=0; k < width; k++) { *fp++ = p1+(inc*k); } } *fp = *(fp-1); return OK; } CS_NOINLINE int fterror(const FGDATA *ff, const char *s, ...) { CSOUND *csound = ff->csound; char buf[64]; va_list args; snprintf(buf, 64, Str("ftable %d: "), ff->fno); va_start(args, s); csound->ErrMsgV(csound, buf, s, args); va_end(args); csoundMessage(csound, "f%3.0f %8.2f %8.2f ", ff->e.p[1], ff->e.p2orig, ff->e.p3orig); if (isstrcod(ff->e.p[4])) csoundMessage(csound,"%s", ff->e.strarg); else csoundMessage(csound, "%8.2f", ff->e.p[4]); if (isstrcod(ff->e.p[5])) csoundMessage(csound, " \"%s\" ...\n", ff->e.strarg); else csoundMessage(csound, "%8.2f ...\n", ff->e.p[5]); return -1; } /* set guardpt, rescale the function, and display it */ static CS_NOINLINE void ftresdisp(const FGDATA *ff, FUNC *ftp) { CSOUND *csound = ff->csound; MYFLT *fp, *finp = &ftp->ftable[ff->flen]; MYFLT abs, maxval; WINDAT dwindow; char strmsg[64]; if (!ff->guardreq) /* if no guardpt yet, do it */ ftp->ftable[ff->flen] = ftp->ftable[0]; if (ff->e.p[4] > FL(0.0)) { /* if genum positve, rescale */ for (fp=ftp->ftable, maxval = FL(0.0); fp<=finp; ) { if ((abs = *fp++) < FL(0.0)) abs = -abs; if (abs > maxval) maxval = abs; } if (maxval != FL(0.0) && maxval != FL(1.0)) for (fp=ftp->ftable; fp<=finp; fp++) *fp /= maxval; } if (!csound->oparms->displays) return; memset(&dwindow, 0, sizeof(WINDAT)); snprintf(strmsg, 64, Str("ftable %d:"), (int) ff->fno); dispset(csound, &dwindow, ftp->ftable, (int32) (ff->flen), strmsg, 0, "ftable"); display(csound, &dwindow); } static void generate_sine_tab(CSOUND *csound) { /* Assume power of 2 length */ int flen = csound->sinelength; FUNC *ftp = (FUNC*) csound->Calloc(csound, sizeof(FUNC)); ftp->ftable = (MYFLT*) csound->Calloc(csound, sizeof(MYFLT)*(flen+1)); double tpdlen = TWOPI / (double) flen; MYFLT *ftable = ftp->ftable; unsigned int i; int ltest, lobits; for (ltest = flen, lobits = 0; (ltest & MAXLEN) == 0L; lobits++, ltest <<= 1) ; ftp->lobits = lobits; i = (1 << lobits); ftp->lomask = (int32) (i - 1); ftp->lodiv = FL(1.0) / (MYFLT) i; /* & other useful vals */ ftp->flen = ftp->flenfrms = flen; ftp->fno = -1; ftp->lenmask = flen - 1; ftp->nchanls = 1; for (i = 1; iflen; i++) ftable[i] = (MYFLT) sin(i*tpdlen); ftable[0] = ftable[ftp->flen] = FL(0.0); csound->sinetable = ftp; return; } /* alloc ftable space for fno (or replace one) */ /* set ftp to point to that structure */ static CS_NOINLINE FUNC *ftalloc(const FGDATA *ff) { CSOUND *csound = ff->csound; FUNC *ftp = csound->flist[ff->fno]; if (UNLIKELY(ftp != NULL)) { csound->Warning(csound, Str("replacing previous ftable %d"), ff->fno); if (ff->flen != (int32)ftp->flen) { /* if redraw & diff len, */ csound->Free(csound, ftp->ftable); csound->Free(csound, (void*) ftp); /* release old space */ csound->flist[ff->fno] = ftp = NULL; if (UNLIKELY(csound->actanchor.nxtact != NULL)) { /* & chk for danger */ csound->Warning(csound, Str("ftable %d relocating due to size change" "\n currently active instruments " "may find this disturbing"), ff->fno); } } else { /* else clear it to zero */ MYFLT *tmp = ftp->ftable; memset((void*) ftp->ftable, 0, sizeof(MYFLT)*(ff->flen+1)); memset((void*) ftp, 0, sizeof(FUNC)); ftp->ftable = tmp; /* restore table pointer */ } } if (ftp == NULL) { /* alloc space as reqd */ csound->flist[ff->fno] = ftp = (FUNC*) csound->Calloc(csound, sizeof(FUNC)); ftp->ftable = (MYFLT*) csound->Calloc(csound, (1+ff->flen) * sizeof(MYFLT)); } ftp->fno = (int32) ff->fno; ftp->flen = ff->flen; return ftp; } /* find the ptr to an existing ftable structure */ /* called by oscils, etc at init time */ FUNC *csoundFTFind(CSOUND *csound, MYFLT *argp) { FUNC *ftp; int fno; fno = MYFLT2LONG(*argp); if (UNLIKELY(fno == -1)) { if (UNLIKELY(csound->sinetable==NULL)) generate_sine_tab(csound); return csound->sinetable; } if (UNLIKELY(fno <= 0 || fno > csound->maxfnum || (ftp = csound->flist[fno]) == NULL)) { csoundInitError(csound, Str("Invalid ftable no. %f"), *argp); return NULL; } else if (UNLIKELY(ftp->lenmask == -1)) { csoundInitError(csound, Str("illegal table length")); return NULL; } else if (UNLIKELY(!ftp->lenmask)) { csoundInitError(csound, Str("deferred-size ftable %f illegal here"), *argp); return NULL; } return ftp; } /* find the ptr to an existing ftable structure */ /* called by oscils, etc at init time */ /* does not throw an error when a non-pow of two size table is found */ FUNC *csoundFTFind2(CSOUND *csound, MYFLT *argp) { FUNC *ftp; int fno; fno = MYFLT2LONG(*argp); if (UNLIKELY(fno == -1)) { if (UNLIKELY(csound->sinetable==NULL)) generate_sine_tab(csound); return csound->sinetable; } if (UNLIKELY(fno <= 0 || fno > csound->maxfnum || (ftp = csound->flist[fno]) == NULL)) { return NULL; } else if (UNLIKELY(ftp->lenmask == -1)) { return NULL; } else if (UNLIKELY(!ftp->lenmask)) { return NULL; } return ftp; } static FUNC *gen01_defer_load(CSOUND *csound, int fno); PUBLIC int csoundGetTable(CSOUND *csound, MYFLT **tablePtr, int tableNum) { FUNC *ftp; if (UNLIKELY((unsigned int) (tableNum - 1) >= (unsigned int) csound->maxfnum)) goto err_return; ftp = csound->flist[tableNum]; if (UNLIKELY(ftp == NULL)) goto err_return; if (!ftp->flen) { ftp = gen01_defer_load(csound, tableNum); if (UNLIKELY(ftp == NULL)) goto err_return; } *tablePtr = ftp->ftable; return (int) ftp->flen; err_return: *tablePtr = (MYFLT*) NULL; return -1; } PUBLIC int csoundGetTableArgs(CSOUND *csound, MYFLT **argsPtr, int tableNum) { FUNC *ftp; if (UNLIKELY((unsigned int) (tableNum - 1) >= (unsigned int) csound->maxfnum)) goto err_return; ftp = csound->flist[tableNum]; if (UNLIKELY(ftp == NULL)) goto err_return; *argsPtr = ftp->args; return (int) ftp->argcnt; err_return: *argsPtr = (MYFLT*) NULL; return -1; } /************************************** * csoundFTFindP() * * New function to find a function table at performance time. Based * on csoundFTFind() which is intended to run at init time only. * * This function can be called from other modules - such as ugrw1.c. * * It returns a pointer to a FUNC data structure which contains all * the details of the desired table. 0 is returned if it cannot be * found. * * This does not handle deferred function table loads (gen01). * * Maybe this could be achieved, but some exploration would be * required to see that this is feasible at performance time. */ FUNC *csoundFTFindP(CSOUND *csound, MYFLT *argp) { FUNC *ftp; int fno; /* Check limits, and then index directly into the flist[] which * contains pointers to FUNC data structures for each table. */ fno = MYFLT2LONG(*argp); if (UNLIKELY(fno == -1)) { if (UNLIKELY(csound->sinetable==NULL)) generate_sine_tab(csound); return csound->sinetable; } if (UNLIKELY(fno <= 0 || fno > csound->maxfnum || (ftp = csound->flist[fno]) == NULL)) { csound->ErrorMsg(csound, Str("Invalid ftable no. %f"), *argp); return NULL; } else if (UNLIKELY(!ftp->lenmask)) { /* Now check that the table has a length > 0. This should only * occur for tables which have not been loaded yet. */ csound->ErrorMsg(csound, Str("Deferred-size ftable %f load " "not available at perf time."), *argp); return NULL; } return ftp; } /* find ptr to a deferred-size ftable structure */ /* called by loscil at init time, and ftlen */ FUNC *csoundFTnp2Find(CSOUND *csound, MYFLT *argp) { FUNC *ftp; int fno = MYFLT2LONG(*argp); if (UNLIKELY(fno == -1)) { if (UNLIKELY(csound->sinetable==NULL)) generate_sine_tab(csound); return csound->sinetable; } if (UNLIKELY(fno <= 0 || fno > csound->maxfnum || (ftp = csound->flist[fno]) == NULL)) { csound->ErrorMsg(csound, Str("Invalid ftable no. %f"), *argp); return NULL; } if (ftp->flen == 0) { if (LIKELY(csound->oparms->gen01defer)) ftp = gen01_defer_load(csound, fno); else { csound->ErrorMsg(csound, Str("Invalid ftable no. %f"), *argp); return NULL; } if (UNLIKELY(ftp == NULL)) csound->inerrcnt++; } return ftp; } /* read ftable values from a sound file */ /* stops reading when table is full */ static int gen01(FGDATA *ff, FUNC *ftp) { if (UNLIKELY(ff->e.pcnt < 8)) { return fterror(ff, Str("insufficient arguments")); } if (ff->csound->oparms->gen01defer) { /* We're deferring the soundfile load until performance time, so allocate the function table descriptor, save the arguments, and get out */ ftp = ftalloc(ff); ftp->gen01args.gen01 = ff->e.p[4]; ftp->gen01args.ifilno = ff->e.p[5]; ftp->gen01args.iskptim = ff->e.p[6]; ftp->gen01args.iformat = ff->e.p[7]; ftp->gen01args.channel = ff->e.p[8]; strncpy(ftp->gen01args.strarg, ff->e.strarg, SSTRSIZ-1); return OK; } return gen01raw(ff, ftp); } static void needsiz(CSOUND *csound, FGDATA *ff, int32 maxend) { int32 nxtpow; maxend -= 1; nxtpow = 2; while (maxend >>= 1) nxtpow <<= 1; csoundMessage(csound, Str("non-deferred ftable %d needs size %d\n"), (int) ff->fno, nxtpow); } static const int gen01_format_table[11] = { 0, 0, AE_CHAR, AE_ALAW, AE_ULAW, AE_SHORT, AE_LONG, AE_FLOAT, AE_UNCH, AE_24INT, AE_DOUBLE }; /* read ftable values from a sound file */ /* stops reading when table is full */ static int gen01raw(FGDATA *ff, FUNC *ftp) { CSOUND *csound = ff->csound; SOUNDIN *p; SOUNDIN tmpspace; SNDFILE *fd; int truncmsg = 0; int32 inlocs = 0; int def = 0, table_length = ff->flen + 1; p = &tmpspace; memset(p, 0, sizeof(SOUNDIN)); { int32 filno = (int32) MYFLT2LRND(ff->e.p[5]); int fmt = (int) MYFLT2LRND(ff->e.p[7]); /* union { */ /* MYFLT d; */ /* int32_t i[2]; */ /* } xx; */ /* xx.d = ff->e.p[5]; */ /* printf("****line %d: ff->e.p[5] %f %.8x %.8x\n", __LINE__, */ /* ff->e.p[5], xx.i[1], xx.i[0]); */ /* printf("****line %d: isstrcod=%d %d file %s\n", __LINE__, */ /* isstrcod(ff->e.p[5]), isnan(ff->e.p[5]), ff->e.strarg); */ if (isstrcod(ff->e.p[5])) { /* printf("****line %d\n" , __LINE__); */ if (ff->e.strarg[0] == '"') { int len = (int) strlen(ff->e.strarg) - 2; /* printf("****line %d\n" , __LINE__); */ strncpy(p->sfname, ff->e.strarg + 1, 512); if (len >= 0 && p->sfname[len] == '"') p->sfname[len] = '\0'; } else { /* printf("****line %d\n" , __LINE__); */ strncpy(p->sfname, ff->e.strarg, 512); } } else if (filno >= 0 && filno <= csound->strsmax && csound->strsets && csound->strsets[filno]) { /* printf("****line %d\n" , __LINE__); */ strncpy(p->sfname, csound->strsets[filno], 512); } else { /* printf("****line %d\n" , __LINE__); */ snprintf(p->sfname, 512, "soundin.%d", filno); /* soundin.filno */ } /* printf("****line %d: sfname=%s\n" , __LINE__, p->sfname); */ if (!fmt) p->format = csound->oparms->outformat; else { if (UNLIKELY(fmt < -1 || fmt > 9)) return fterror(ff, Str("invalid sample format: %d"), fmt); p->format = gen01_format_table[fmt + 1]; } } p->skiptime = ff->e.p[6]; p->channel = (int) MYFLT2LRND(ff->e.p[8]); p->do_floatscaling = 0; if (UNLIKELY(p->channel < 0 /* || p->channel > ALLCHNLS-1 */)) { return fterror(ff, Str("channel %d illegal"), (int) p->channel); } if (p->channel == 0) /* snd is chan 1,2,..8 or all */ p->channel = ALLCHNLS; p->analonly = 0; if (UNLIKELY(ff->flen == 0 && (csound->oparms->msglevel & 7))) { csoundMessage(csound, Str("deferred alloc for %s\n"), p->sfname); } if (UNLIKELY((fd = sndgetset(csound, p))==NULL)) { /* sndinset to open the file */ return fterror(ff, Str("Failed to open file %s"), p->sfname); } if (ff->flen == 0) { /* deferred ftalloc requestd: */ if (UNLIKELY((ff->flen = p->framesrem + 1) <= 0)) { /* get minsize from soundin */ return fterror(ff, Str("deferred size, but filesize unknown")); } if (UNLIKELY(csound->oparms->msglevel & 7)) csoundMessage(csound, Str(" defer length %d\n"), ff->flen - 1); if (p->channel == ALLCHNLS) ff->flen *= p->nchanls; ff->guardreq = 1; /* presum this includes guard */ /*ff->flen -= 1;*/ /* VL: this was causing tables to exclude last point */ ftp = ftalloc(ff); /* alloc now, and */ ftp->lenmask = 0L; /* mark hdr partly filled */ /*if (p->channel==ALLCHNLS) ftp->nchanls = p->nchanls; else ftp->nchanls = 1; ftp->flenfrms = ff->flen / p->nchanls; */ /* ?????????? */ def = 1; ff->flen -= 1; table_length = ff->flen; } if (p->channel==ALLCHNLS) { //ff->flen *= p->nchanls; ftp->nchanls = p->nchanls; } else ftp->nchanls = 1; ftp->flenfrms = ff->flen / p->nchanls; /* ?????????? */ ftp->gen01args.sample_rate = (MYFLT) p->sr; ftp->cvtbas = LOFACT * p->sr * csound->onedsr; { SF_INSTRUMENT lpd; int ans = sf_command(fd, SFC_GET_INSTRUMENT, &lpd, sizeof(SF_INSTRUMENT)); if (ans) { double natcps; #ifdef BETA if ((csound->oparms_.msglevel & 7) == 7) { csoundMessage(csound, "Base Note : %u\tDetune : %u\n" "Low Note : %u\tHigh Note : %u\n" "Low Vel. : %u\tHigh Vel. : %u\n" "Gain : %d\tCount : %d\n" "mode : %d\n" "start : %d\tend : %d\tcount :%d\n" "mode : %d\n" "start : %d\tend : %d\tcount :%d\n\n", lpd.basenote, 0U, lpd.key_lo, lpd.key_hi, lpd.velocity_lo, lpd.velocity_hi, lpd.gain, lpd.loop_count, lpd.loops[0].mode, lpd.loops[0].start, lpd.loops[0].end, lpd.loops[0].count, lpd.loops[1].mode, lpd.loops[1].start, lpd.loops[1].end, lpd.loops[1].count); } #endif natcps = pow(2.0, ((double) ((int) lpd.basenote - 69) + (double) lpd.detune * 0.01) / 12.0) * csound->A4; /* As far as I can tell this gainfac value is never used! */ //gainfac = exp((double) lpd.gain * LOG10D20); /* if (lpd.basenote == 0) lpd.basenote = ftp->cvtbas; */ ftp->cpscvt = ftp->cvtbas / natcps; ftp->loopmode1 = (lpd.loops[0].mode == SF_LOOP_NONE ? 0 : lpd.loops[0].mode == SF_LOOP_FORWARD ? 1 : 2); ftp->loopmode2 = (lpd.loops[1].mode == SF_LOOP_NONE ? 0 : lpd.loops[1].mode == SF_LOOP_FORWARD ? 1 : 2); ftp->begin1 = lpd.loops[0].start; ftp->begin2 = lpd.loops[1].start; if (ftp->loopmode1) /* Greg Sullivan */ ftp->end1 = lpd.loops[0].end; else ftp->end1 = ftp->flenfrms; /* Greg Sullivan */ ftp->end2 = lpd.loops[1].end; if (UNLIKELY(ftp->end1 > ff->flen || ftp->end2 > ff->flen)) { int32 maxend; csound->Warning(csound, Str("GEN1: input file truncated by ftable size")); if ((maxend = ftp->end1) < ftp->end2) maxend = ftp->end2; csoundMessage(csound, Str("\tlooping endpoint %d exceeds ftsize %d\n"), maxend, ff->flen); needsiz(csound, ff, maxend); truncmsg = 1; } } else { ftp->cpscvt = FL(0.0); /* else no looping possible */ ftp->loopmode1 = 0; ftp->loopmode2 = 0; ftp->end1 = ftp->flenfrms; /* Greg Sullivan */ } } /* read sound with opt gain */ if (UNLIKELY((inlocs=getsndin(csound, fd, ftp->ftable, table_length, p)) < 0)) { return fterror(ff, Str("GEN1 read error")); } if (UNLIKELY(p->audrem > 0 && !truncmsg && p->framesrem > ff->flen)) { /* Reduce msg */ csound->Warning(csound, Str("GEN1: file truncated by ftable size")); csound->Warning(csound, Str("\taudio samps %d exceeds ftsize %d"), (int32) p->framesrem, (int32) ff->flen); needsiz(csound, ff, p->framesrem); /* ???????????? */ } ftp->soundend = inlocs / ftp->nchanls; /* record end of sound samps */ csound->FileClose(csound, p->fd); if (def) { MYFLT *tab = ftp->ftable; ftresdisp(ff, ftp); /* VL: 11.01.05 for deferred alloc tables */ tab[ff->flen] = tab[0]; /* guard point */ ftp->flen -= 1; /* exclude guard point */ } /* save arguments */ ftp->argcnt = ff->e.pcnt - 3; { /* Note this does not handle extened args -- JPff */ int size=ftp->argcnt; //if (size>=PMAX) size=PMAX; // Coverity 96615 says this overflows memcpy(ftp->args, &(ff->e.p[4]), sizeof(MYFLT)*size); /* for (k=0; k < size; k++) csound->Message(csound, "%f \n", ftp->args[k]);*/ } return OK; } /* GEN 43 (c) Victor Lazzarini, 2004 */ typedef struct _pvstabledat { int32 fftsize; int32 overlap; int32 winsize; int wintype; int chans; int32 format; int32 blockalign; uint32 frames; } PVSTABLEDAT; static int gen43(FGDATA *ff, FUNC *ftp) { CSOUND *csound = ff->csound; MYFLT *fp = ftp->ftable; MYFLT *filno; int nvals = ff->e.pcnt - 4; MYFLT *channel; char filename[MAXNAME]; PVOCEX_MEMFILE pp; PVSTABLEDAT p; uint32 framesize, blockalign, bins; uint32 frames, i, j; float *framep, *startp; double accum = 0.0; if (UNLIKELY(nvals != 2)) { return fterror(ff, Str("wrong number of ftable arguments")); } filno = &ff->e.p[5]; if (isstrcod(ff->e.p[5])) strncpy(filename, (char *)(&ff->e.strarg[0]), MAXNAME-1); else csound->strarg2name(csound, filename, filno, "pvoc.", 0); if (UNLIKELY(PVOCEX_LoadFile(csound, filename, &pp) != 0)) return fterror(ff, Str("Failed to load PVOC-EX file")); //csoundDie(csound, Str("Failed to load PVOC-EX file")); p.fftsize = pp.fftsize; p.overlap = pp.overlap; p.winsize = pp.winsize; p.wintype = pp.wintype; p.chans = pp.chans; p.format = pp.format; p.frames = pp.nframes; channel = &ff->e.p[6]; if (UNLIKELY(*channel > p.chans)) return fterror(ff, Str("illegal channel number")); framesize = p.fftsize+1; bins = framesize/2; frames = p.frames; if (*channel > 0) { startp = (float *) pp.data + (p.fftsize + 2) * ((int) *channel - 1); blockalign = (p.fftsize+2) * p.chans; /* only read one channel */ } else { startp = (float *) pp.data; blockalign = (p.fftsize+2); /* read all channels */ } framep = startp; if (UNLIKELY(bins > (uint32) (ftp->flen+1))) { return fterror(ff, Str("ftable size too small")); } for (i=0; icsound; MYFLT *fp = ftp == NULL ? NULL: ftp->ftable; mp3dec_t mpa = NULL; mpadec_config_t config = { MPADEC_CONFIG_FULL_QUALITY, MPADEC_CONFIG_AUTO, MPADEC_CONFIG_16BIT, MPADEC_CONFIG_LITTLE_ENDIAN, MPADEC_CONFIG_REPLAYGAIN_NONE, TRUE, TRUE, TRUE, 0.0 }; int skip = 0, chan = 0, r, fd; int p = 0; char sfname[1024]; mpadec_info_t mpainfo; uint32_t bufsize, bufused = 0; uint8_t *buffer; int size = 0x1000; int flen, nchanls, def = 0; if (UNLIKELY(ff->e.pcnt < 7)) { return fterror(ff, Str("insufficient arguments")); } /* memset(&mpainfo, 0, sizeof(mpadec_info_t)); */ /* Is this necessary? */ { int32 filno = (int32) MYFLT2LRND(ff->e.p[5]); if (isstrcod(ff->e.p[5])) { if (ff->e.strarg[0] == '"') { int len = (int) strlen(ff->e.strarg) - 2; strncpy(sfname, ff->e.strarg + 1, 1023); if (len >= 0 && sfname[len] == '"') sfname[len] = '\0'; } else strncpy(sfname, ff->e.strarg, 1023); } else if ((filno= (int32) MYFLT2LRND(ff->e.p[5])) >= 0 && filno <= csound->strsmax && csound->strsets && csound->strsets[filno]) strncpy(sfname, csound->strsets[filno], 1023); else snprintf(sfname, 1024, "soundin.%d", filno); /* soundin.filno */ } chan = (int) MYFLT2LRND(ff->e.p[7]); if (UNLIKELY(chan < 0)) { return fterror(ff, Str("channel %d illegal"), (int) chan); } switch (chan) { case 0: config.mode = MPADEC_CONFIG_AUTO; break; case 1: config.mode = MPADEC_CONFIG_MONO; break; case 2: config.mode = MPADEC_CONFIG_STEREO; break; case 3: config.mode = MPADEC_CONFIG_CHANNEL1; break; case 4: config.mode = MPADEC_CONFIG_CHANNEL2; break; } mpa = mp3dec_init(); if (UNLIKELY(!mpa)) { return fterror(ff, Str("Not enough memory\n")); } if (UNLIKELY((r = mp3dec_configure(mpa, &config)) != MP3DEC_RETCODE_OK)) { mp3dec_uninit(mpa); return fterror(ff, mp3dec_error(r)); } (void)csound->FileOpen2(csound, &fd, CSFILE_FD_R, sfname, NULL, "SFDIR;SSDIR", CSFTYPE_UNKNOWN_AUDIO, 0); // fd = open(sfname, O_RDONLY); /* search paths */ if (UNLIKELY(fd < 0)) { mp3dec_uninit(mpa); fterror(ff, "sfname"); } if (UNLIKELY((r = mp3dec_init_file(mpa, fd, 0, FALSE)) != MP3DEC_RETCODE_OK)) { mp3dec_uninit(mpa); return fterror(ff, mp3dec_error(r)); } if (UNLIKELY((r = mp3dec_get_info(mpa, &mpainfo, MPADEC_INFO_STREAM)) != MP3DEC_RETCODE_OK)) { mp3dec_uninit(mpa); return fterror(ff, mp3dec_error(r)); } /* maxsize = mpainfo.decoded_sample_size */ /* *mpainfo.decoded_frame_samples */ /* *mpainfo.frames; */ { char temp[80]; if (mpainfo.frequency < 16000) strcpy(temp, "MPEG-2.5 "); else if (mpainfo.frequency < 32000) strcpy(temp, "MPEG-2 "); else strcpy(temp, "MPEG-1 "); if (mpainfo.layer == 1) strcat(temp, "Layer I"); else if (mpainfo.layer == 2) strcat(temp, "Layer II"); else strcat(temp, "Layer III"); csound->DebugMsg(csound, "Input: %s, %s, %d kbps, %d Hz (%d:%02d)\n", temp, ((mpainfo.channels > 1) ? "stereo" : "mono"), mpainfo.bitrate, mpainfo.frequency, mpainfo.duration/60, mpainfo.duration%60); } buffer = (uint8_t *)csound->Malloc(csound,size); bufsize = size/mpainfo.decoded_sample_size; skip = (int)(ff->e.p[6] * mpainfo.frequency); while (skip > 0) { uint32_t xx = skip; if ((uint32_t)xx > bufsize) xx = bufsize; // printf("gen49: skipping xx\n", xx); skip -=xx; mp3dec_decode(mpa, buffer, mpainfo.decoded_sample_size*xx, &bufused); } //bufsize *= mpainfo.decoded_sample_size; r = mp3dec_decode(mpa, buffer, size, &bufused); nchanls = (chan == 2 && mpainfo.channels == 2 ? 2 : 1); if (ff->flen == 0) { /* deferred ftalloc */ int fsize, frames; frames = mpainfo.frames * mpainfo.decoded_frame_samples; fsize = frames * nchanls; if (UNLIKELY((ff->flen = fsize) <= 0)) return fterror(ff, Str("deferred size, but filesize unknown")); if (UNLIKELY(ff->flen > MAXLEN)) return fterror(ff, Str("illegal table length")); if (UNLIKELY(csound->oparms->msglevel & 7)) csoundMessage(csound, Str(" defer length %d\n"), ff->flen); ftp = ftalloc(ff); ftp->lenmask = 0L; ftp->flenfrms = frames; ftp->nchanls = nchanls; fp = ftp->ftable; def = 1; } ftp->gen01args.sample_rate = mpainfo.frequency; ftp->cvtbas = LOFACT * mpainfo.frequency * csound->onedsr; flen = ftp->flen; //printf("gen49: flen=%d size=%d bufsize=%d\n", flen, size, bufsize); while ((r == MP3DEC_RETCODE_OK) && bufused) { unsigned int i; short *bb = (short*)buffer; //printf("gen49: p=%d bufused=%d\n", p, bufused); for (i=0; i=flen)) { csound->Free(csound,buffer); //printf("gen49: i=%d p=%d exit as at end of table\n", i, p); return ((mp3dec_uninit(mpa) == MP3DEC_RETCODE_OK) ? OK : NOTOK); } fp[p] = ((MYFLT)bb[i]/(MYFLT)0x7fff) * csound->e0dbfs; //printf("%d: %f %d\n", p, fp[p], bb[i]); p++; } if (i <= 0) break; //printf("gen49: new buffer\n"); r = mp3dec_decode(mpa, buffer, size, &bufused); } csound->Free(csound, buffer); r |= mp3dec_uninit(mpa); if (def) ftresdisp(ff, ftp); return ((r == MP3DEC_RETCODE_OK) ? OK : NOTOK); } static int gen49(FGDATA *ff, FUNC *ftp) { if (UNLIKELY(ff->e.pcnt < 7)) { return fterror(ff, Str("insufficient arguments")); } if (ff->csound->oparms->gen01defer) { /* We're deferring the soundfile load until performance time, so allocate the function table descriptor, save the arguments, and get out */ ftp = ftalloc(ff); ftp->gen01args.gen01 = ff->e.p[4]; ftp->gen01args.ifilno = ff->e.p[5]; ftp->gen01args.iskptim = ff->e.p[6]; ftp->gen01args.iformat = ff->e.p[7]; ftp->gen01args.channel = ff->e.p[8]; strncpy(ftp->gen01args.strarg, ff->e.strarg, SSTRSIZ-1); return OK; } return gen49raw(ff, ftp); } #endif static int gen51(FGDATA *ff, FUNC *ftp) /* Gab 1/3/2005 */ { int j, notenum, grade, numgrades, basekeymidi, nvals; MYFLT basefreq, factor, interval; MYFLT *fp = ftp->ftable, *pp; CSOUND *csound = ff->csound; if (UNLIKELY(ff->e.pcnt>=PMAX)) { csound->Warning(csound, Str("using extended arguments\n")); } nvals = ff->flen; pp = &(ff->e.p[5]); numgrades = (int) *pp++; interval = *pp++; basefreq = *pp++; basekeymidi = (int) *pp++; if (UNLIKELY((ff->e.pcnt - 8) < numgrades)) { /* gab fixed */ return fterror(ff, Str("GEN51: invalid number of p-fields (too few grades)")); } for (j = 0; j < nvals; j++) { MYFLT x; notenum = j; if (notenum < basekeymidi) { notenum = basekeymidi - notenum; grade = (numgrades - (notenum % numgrades)) % numgrades; factor = -((MYFLT) ((int) ((notenum + numgrades - 1) / numgrades))); } else { notenum = notenum - basekeymidi; grade = notenum % numgrades; factor = (MYFLT) ((int) (notenum / numgrades)); } factor = POWER(interval, factor); if (LIKELY(gradee.c.extra[grade-PMAX+11]; fp[j] = x * factor * basefreq; } return OK; } static int gen52(FGDATA *ff, FUNC *ftp) { CSOUND *csound = ff->csound; MYFLT *src, *dst; FUNC *f; int nchn, len, len2, i, j, k, n; int nargs = (int) ff->e.pcnt - 4; if (UNLIKELY(ff->e.pcnt>=PMAX)) { csound->Warning(csound, Str("using extended arguments\n")); } if (UNLIKELY(nargs < 4)) { return fterror(ff, Str("insufficient gen arguments")); } nchn = MYFLT2LRND(ff->e.p[5]); if (UNLIKELY(((nchn * 3) + 1) != nargs)) { return fterror(ff, Str("number of channels " "inconsistent with number of args")); } len = ((int) ftp->flen / nchn) * nchn; dst = ftp->ftable; memset(dst, 0, ftp->flen*sizeof(MYFLT)); /* for (i = len; i <= (int) ftp->flen; i++) */ /* dst[i] = FL(0.0); */ for (n = 0; n < nchn; n++) { MYFLT *pp; if (LIKELY((n * 3) + 6e.p[(n * 3) + 6]); else pp = &(ff->e.c.extra[(n * 3) + 6-PMAX]); f = csoundFTFind(csound, pp); if (UNLIKELY(f == NULL)) return NOTOK; len2 = (int) f->flen; src = f->ftable; i = n; if (LIKELY((n * 3) + 7e.p[(n * 3) + 7]); else j = MYFLT2LRND(ff->e.c.extra[(n * 3) + 7-PMAX]); if (LIKELY((n * 3) + 8e.p[(n * 3) + 8]); else k = MYFLT2LRND(ff->e.c.extra[(n * 3) + 8-PMAX]); while (i < len) { if (j >= 0 && j < len2) dst[i] = src[j]; else dst[i] = FL(0.0); i += nchn; j += k; } } return OK; } static void gen53_apply_window(MYFLT *buf, MYFLT *w, int npts, int wpts, int minphase) { int64_t ph, ph_inc; int i, j; MYFLT pfrac; for (i = 1, j = 0; i < npts; i <<= 1, j++) ; if (!minphase) { ph = (int64_t) 0; ph_inc = ((int64_t) wpts << 32) >> j; } else { ph = (int64_t) wpts << 31; ph_inc = ((int64_t) wpts << 31) >> j; } for (i = 0; i <= npts; i++) { j = (int) (ph >> 32); pfrac = (MYFLT) ((int) (((uint32_t) ph) >> 1)); if (j >= wpts) { buf[i] *= w[wpts]; } else { pfrac *= (FL(0.5) / (MYFLT) 0x40000000); buf[i] *= (w[j] + ((w[j + 1] - w[j]) * pfrac)); } ph += ph_inc; } } static void gen53_freq_response_to_ir(CSOUND *csound, MYFLT *obuf, MYFLT *ibuf, MYFLT *wbuf, int npts, int wpts, int mode) { MYFLT *buf1, *buf2; double tmp; MYFLT scaleFac; int i, j, npts2 = (npts << 1); scaleFac = csound->GetInverseRealFFTScale(csound, npts); /* ---- linear phase impulse response ---- */ i = j = 0; do { obuf[i++] = (FABS(ibuf[j])) * scaleFac; j++; obuf[i++] = FL(0.0); obuf[i++] = -(FABS(ibuf[j]) * scaleFac); j++; obuf[i++] = FL(0.0); } while (i < npts); obuf[1] = ibuf[j] * scaleFac; csound->InverseRealFFT(csound, obuf, npts); obuf[npts] = FL(0.0); /* clear guard point */ if (wbuf != NULL && !(mode & 4)) /* apply window if requested */ gen53_apply_window(obuf, wbuf, npts, wpts, 0); if (!(mode & 1)) { csound->Message(csound, "linear-phase output \n"); return; } /* ---- minimum phase impulse response ---- */ scaleFac = csound->GetInverseRealFFTScale(csound, npts2); buf1 = (MYFLT*) csound->Malloc(csound, sizeof(MYFLT) * (size_t) npts2); buf2 = (MYFLT*) csound->Malloc(csound, sizeof(MYFLT) * (size_t) npts2); /* upsample magnitude response by a factor of 2, */ /* and store result in obuf[0]...obuf[npts] */ for (j = 0; j < (npts >> 1); j++) buf1[j] = FL(0.0); for (i = 0; i < npts; i++, j++) buf1[j] = obuf[i]; for ( ; j < npts2; j++) buf1[j] = FL(0.0); csound->RealFFT(csound, buf1, npts2); for (i = j = 0; i < npts; i++, j += 2) { tmp = (double) buf1[j]; tmp = sqrt(tmp * tmp + 1.0e-20); obuf[i] = (MYFLT) tmp; } tmp = (double) buf1[1]; tmp = sqrt(tmp * tmp + 1.0e-20); obuf[i] = (MYFLT) tmp; /* calculate logarithm of magnitude response, */ for (i = 0; i <= npts; i++) { buf1[i] = LOG(obuf[i]); } for (j = i - 2; i < npts2; i++, j--) /* need full spectrum, */ buf1[i] = buf1[j]; /* not just the lower half */ csound->RealFFT(csound, buf1, npts2); /* and convolve with 1/tan(x) impulse response */ buf2[0] = FL(0.0); buf2[1] = FL(0.0); for (i = 2; i < npts2; i += 2) { buf2[i] = FL(0.0); buf2[i + 1] = (MYFLT) (npts2 - i) / (MYFLT) npts2; } csound->RealFFTMult(csound, buf1, buf1, buf2, npts2, scaleFac); /* store unwrapped phase response in buf1 */ csound->InverseRealFFT(csound, buf1, npts2); /* convert from magnitude/phase format to real/imaginary */ for (i = 2; i < npts2; i += 2) { double ph; ph = (double) buf1[i >> 1] / TWOPI; ph = TWOPI * modf(ph, &tmp); ph = (ph < 0.0 ? ph + PI : ph - PI); tmp = -((double) scaleFac * (double) obuf[i >> 1]); buf2[i] = (MYFLT) (tmp * cos(ph)); buf2[i + 1] = (MYFLT) (tmp * sin(ph)); } buf2[0] = scaleFac * obuf[0]; buf2[1] = scaleFac * obuf[npts]; /* perform inverse FFT to get impulse response */ csound->InverseRealFFT(csound, buf2, npts2); /* copy output, truncating to table length + guard point */ for (i = 0; i <= npts; i++) obuf[i] = buf2[i]; csound->Free(csound, buf2); csound->Free(csound, buf1); csound->Message(csound, "minimum-phase output\n"); if (wbuf != NULL && !(mode & 8)) /* apply window if requested */ gen53_apply_window(obuf, wbuf, npts, wpts, 1); } static int gen53(FGDATA *ff, FUNC *ftp) { CSOUND *csound = ff->csound; MYFLT *srcftp, *dstftp, *winftp = NULL; int nargs = ff->e.pcnt - 4; int mode = 0, srcftno, winftno = 0, srcflen, dstflen, winflen = 0; if (UNLIKELY(nargs < 1 || nargs > 3)) { return fterror(ff, Str("GEN53: invalid number of gen arguments")); } srcftno = (int) MYFLT2LRND(ff->e.p[5]); if (nargs > 1) mode = (int) MYFLT2LRND(ff->e.p[6]); if (nargs > 2) winftno = (int) MYFLT2LRND(ff->e.p[7]); dstftp = ftp->ftable; dstflen = (int) ftp->flen; if (UNLIKELY(dstflen < 8 || (dstflen & (dstflen - 1)))) { return fterror(ff, Str("GEN53: invalid table length")); } srcflen = csoundGetTable(csound, &srcftp, srcftno); if (UNLIKELY(srcflen < 0)) { return fterror(ff, Str("GEN53: invalid source table number")); } if (UNLIKELY(mode & (~15))) { return fterror(ff, Str("GEN53: mode must be in the range 0 to 15")); } if (UNLIKELY((!(mode & 2) && srcflen != (dstflen >> 1)) || ((mode & 2) && srcflen != dstflen))) { return fterror(ff, Str("GEN53: invalid source table length:")); } if (winftno) { winflen = csoundGetTable(csound, &winftp, winftno); if (UNLIKELY(winflen <= 0 || (winflen & (winflen - 1)))) { return fterror(ff, Str("GEN53: invalid window table")); } } if (mode & 2) { /* if input data is impulse response: */ MYFLT *tmpft; int i, j; tmpft = (MYFLT*) csound->Calloc(csound, sizeof(MYFLT) * (size_t) ((dstflen >> 1) + 1)); memcpy(dstftp, srcftp, sizeof(MYFLT) * (size_t) dstflen); csound->RealFFT(csound, dstftp, dstflen); tmpft[0] = dstftp[0]; for (i = 2, j = 1; i < dstflen; i += 2, j++) tmpft[j] = SQRT(((dstftp[i] * dstftp[i]) + (dstftp[i + 1] * dstftp[i + 1]))); tmpft[j] = dstftp[1]; csound->Message(csound,Str("GEN 53: impulse response input, ")); gen53_freq_response_to_ir(csound, dstftp, tmpft, winftp, dstflen, winflen, mode); csound->Free(csound, tmpft); } else { /* input is frequency response: */ csound->Message(csound, Str("GEN 53: frequency response input, ")); gen53_freq_response_to_ir(csound, dstftp, srcftp, winftp, dstflen, winflen, mode); } return OK; } int allocgen(CSOUND *csound, char *s, GEN fn) { NAMEDGEN *n = (NAMEDGEN*) csound->namedgen; while (n != NULL) { if (strcmp(s, n->name) == 0) return n->genum; n = n->next; } /* Need to allocate */ n = (NAMEDGEN*) csound->Malloc(csound, sizeof(NAMEDGEN)); n->genum = csound->genmax++; n->next = (NAMEDGEN*) csound->namedgen; n->name = csound->Malloc(csound, strlen(s) + 1); strcpy(n->name, s); csound->namedgen = (void*) n; if (LIKELY(csound->gensub == NULL)) { csound->gensub = (GEN*) csound->Malloc(csound, csound->genmax * sizeof(GEN)); memcpy(csound->gensub, or_sub, sizeof(or_sub)); } else csound->gensub = (GEN*) csound->ReAlloc(csound, csound->gensub, csound->genmax * sizeof(GEN)); csound->gensub[csound->genmax-1] = fn; return csound->genmax-1; } int csoundIsNamedGEN(CSOUND *csound, int num) { NAMEDGEN *n = (NAMEDGEN*) csound->namedgen; while (n != NULL) { if (n->genum == abs(num)) return strlen(n->name); n = n->next; } return 0; } /* ODDITY: does not stop when num found but continues to end; aso not used! */ void csoundGetNamedGEN(CSOUND *csound, int num, char *name, int len) { NAMEDGEN *n = (NAMEDGEN*) csound->namedgen; while (n != NULL) { if (n->genum == abs(num)) { strncpy(name,n->name,len); return; } n = n->next; } } #include "resize.h" static int warned = 0; /* Thread Safe */ int resize_table(CSOUND *csound, RESIZE *p) { unsigned int fsize = (unsigned int) MYFLT2LRND(*p->nsize); int fno = (int) MYFLT2LRND(*p->fn); FUNC *ftp; if (UNLIKELY(warned==0)) { printf("WARNING: EXPERIMENTAL CODE\n"); warned = 1; } if (UNLIKELY((ftp = csound->FTFind(csound, p->fn)) == NULL)) return NOTOK; if (ftp->flenftable = (MYFLT *) csound->ReAlloc(csound, ftp->ftable, sizeof(MYFLT)*(fsize+1)); ftp->flen = fsize+1; csound->flist[fno] = ftp; return OK; } static CS_NOINLINE FUNC *gen01_defer_load(CSOUND *csound, int fno) { FGDATA ff; char *strarg; FUNC *ftp = csound->flist[fno]; /* The soundfile hasn't been loaded yet, so call GEN01 */ strarg = csound->Malloc(csound, strlen(ftp->gen01args.strarg)+1); strcpy(strarg, ftp->gen01args.strarg); memset(&ff, 0, sizeof(FGDATA)); ff.csound = csound; ff.fno = fno; ff.e.strarg = strarg; ff.e.opcod = 'f'; ff.e.pcnt = 8; ff.e.p[1] = (MYFLT) fno; ff.e.p[4] = ftp->gen01args.gen01; ff.e.p[5] = ftp->gen01args.ifilno; ff.e.p[6] = ftp->gen01args.iskptim; ff.e.p[7] = ftp->gen01args.iformat; ff.e.p[8] = ftp->gen01args.channel; if (UNLIKELY(gen01raw(&ff, ftp) != 0)) { csoundErrorMsg(csound, Str("Deferred load of '%s' failed"), strarg); return NULL; } return csound->flist[fno]; } csound-6.10.0/Engine/insert.c000066400000000000000000002573341321653344700157740ustar00rootroot00000000000000/* insert.c: Copyright (C) 1991, 1997, 1999, 2002, 2005 Barry Vercoe, Istvan Varga, John ffitch, Gabriel Maldonado, matt ingalls This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* INSERT.C */ #include "oload.h" #include "insert.h" /* for goto's */ #include "aops.h" /* for cond's */ #include "midiops.h" #include "namedins.h" /* IV - Oct 31 2002 */ #include "pstream.h" #include "interlocks.h" #include "csound_type_system.h" #include "csound_standard_types.h" static void showallocs(CSOUND *); static void deact(CSOUND *, INSDS *); static void schedofftim(CSOUND *, INSDS *); void beatexpire(CSOUND *, double); void timexpire(CSOUND *, double); static void instance(CSOUND *, int); extern int argsRequired(char* argString); int init0(CSOUND *csound) { INSTRTXT *tp = csound->engineState.instrtxtp[0]; INSDS *ip; instance(csound, 0); /* allocate instr 0 */ csound->curip = ip = tp->act_instance; tp->act_instance = ip->nxtact; csound->ids = (OPDS*) ip; tp->active++; ip->actflg++; ip->ksmps = csound->ksmps; ip->ekr = csound->ekr; ip->kcounter = csound->kcounter; ip->onedksmps = csound->onedksmps; ip->onedkr = csound->onedkr; ip->kicvt = csound->kicvt; csound->inerrcnt = 0; while ((csound->ids = csound->ids->nxti) != NULL) { (*csound->ids->iopadr)(csound, csound->ids); /* run all i-code */ } return csound->inerrcnt; /* return errcnt */ } static void putop(CSOUND *csound, TEXT *tp) { int n, nn; if ((n = tp->outlist->count) != 0) { nn = 0; while (n--) csound->Message(csound, "%s\t", tp->outlist->arg[nn++]); } else csound->Message(csound, "\t"); csound->Message(csound, "%s\t", tp->opcod); if ((n = tp->inlist->count) != 0) { nn = 0; while (n--) csound->Message(csound, "%s\t", tp->inlist->arg[nn++]); } csound->Message(csound, "\n"); } static void set_xtratim(CSOUND *csound, INSDS *ip) { if (UNLIKELY(ip->relesing)) return; ip->offtim = (csound->icurTime + ip->ksmps * (double) ip->xtratim)/csound->esr; ip->offbet = csound->curBeat + (csound->curBeat_inc * (double) ip->xtratim); ip->relesing = 1; csound->engineState.instrtxtp[ip->insno]->pending_release++; } /* insert an instr copy into active list */ /* then run an init pass */ int insert(CSOUND *csound, int insno, EVTBLK *newevtp) { INSTRTXT *tp; INSDS *ip, *prvp, *nxtp; OPARMS *O = csound->oparms; CS_VAR_MEM *pfields = NULL; /* *** was uninitialised *** */ int tie=0, i; if (UNLIKELY(csound->advanceCnt)) return 0; if (UNLIKELY(O->odebug)) { char *name = csound->engineState.instrtxtp[insno]->insname; if (UNLIKELY(name)) csound->Message(csound, Str("activating instr %s at %lld\n"), name, csound->icurTime); else csound->Message(csound, Str("activating instr %d at %lld\n"), insno, csound->icurTime); } csound->inerrcnt = 0; tp = csound->engineState.instrtxtp[insno]; if (UNLIKELY(tp->muted == 0)) { char *name = csound->engineState.instrtxtp[insno]->insname; if (UNLIKELY(name)) csound->Warning(csound, Str("Instrument %s muted\n"), name); else csound->Warning(csound, Str("Instrument %d muted\n"), insno); return 0; } /* if (UNLIKELY(tp->mdepends & MO)) { */ /* char *name = csound->engineState.instrtxtp[insno]->insname; */ /* if (UNLIKELY(name)) */ /* csound->Message(csound, Str("instr %s expects midi event data, " */ /* "cannot run from score\n"), name); */ /* else */ /* csound->Message(csound, Str("instr %d expects midi event data, " */ /* "cannot run from score\n"), insno); */ /* return(1); */ /* } */ if (tp->cpuload > FL(0.0)) { csound->cpu_power_busy += tp->cpuload; /* if there is no more cpu processing time*/ if (UNLIKELY(csound->cpu_power_busy > FL(100.0))) { csound->cpu_power_busy -= tp->cpuload; csoundWarning(csound, Str("cannot allocate last note because " "it exceeds 100%% of cpu time")); return(0); } } if (UNLIKELY(tp->maxalloc > 0 && tp->active >= tp->maxalloc)) { csoundWarning(csound, Str("cannot allocate last note because it exceeds " "instr maxalloc")); return(0); } /* if find this insno, active, with indef (tie) & matching p1 */ for (ip = tp->instance; ip != NULL; ip = ip->nxtinstance) { if (ip->actflg && ip->offtim < 0.0 && ip->p1.value == newevtp->p[1]) { csound->tieflag++; ip->tieflag = 1; tie = 1; goto init; /* continue that event */ } } /* alloc new dspace if needed */ if (tp->act_instance == NULL || tp->isNew) { if (UNLIKELY(O->msglevel & RNGEMSG)) { char *name = csound->engineState.instrtxtp[insno]->insname; if (UNLIKELY(name)) csound->Message(csound, Str("new alloc for instr %s:\n"), name); else csound->Message(csound, Str("new alloc for instr %d:\n"), insno); } instance(csound, insno); tp->isNew=0; } /* pop from free instance chain */ if (UNLIKELY(csound->oparms->odebug)) csoundMessage(csound, "insert(): tp->act_instance = %p \n", tp->act_instance); ip = tp->act_instance; tp->act_instance = ip->nxtact; ip->insno = (int16) insno; ip->ksmps = csound->ksmps; ip->ekr = csound->ekr; ip->kcounter = csound->kcounter; ip->onedksmps = csound->onedksmps; ip->onedkr = csound->onedkr; ip->kicvt = csound->kicvt; ip->pds = NULL; /* Add an active instrument */ tp->active++; tp->instcnt++; csound->dag_changed++; /* Need to remake DAG */ //printf("**** dag changed by insert\n"); nxtp = &(csound->actanchor); /* now splice into activ lst */ while ((prvp = nxtp) && (nxtp = prvp->nxtact) != NULL) { if (nxtp->insno > insno || (nxtp->insno == insno && nxtp->p1.value > newevtp->p[1])) { nxtp->prvact = ip; break; } } ip->nxtact = nxtp; ip->prvact = prvp; prvp->nxtact = ip; ip->actflg++; /* and mark the instr active */ { int n; MYFLT *flp, *fep; init: pfields = (CS_VAR_MEM*)&ip->p0; if (tp->psetdata) { int i; CS_VAR_MEM* pfields = (CS_VAR_MEM*) &ip->p0; MYFLT *pdat = tp->psetdata + 2; int32 nn = tp->pmax - 2; /* put cur vals in pflds */ for (i = 0; i < nn; i++) { CS_VAR_MEM* pfield = (pfields + i + 3); pfield->value = *(pdat + i); } } n = tp->pmax; if (UNLIKELY((tp->nocheckpcnt == 0) && n != newevtp->pcnt && !tp->psetdata)) { char *name = csound->engineState.instrtxtp[insno]->insname; if (UNLIKELY(name)) csoundWarning(csound, Str("instr %s uses %d p-fields but is given %d"), name, n, newevtp->pcnt); else csoundWarning(csound, Str("instr %d uses %d p-fields but is given %d"), insno, n, newevtp->pcnt); } if (newevtp->p3orig >= FL(0.0)) ip->offbet = csound->beatOffs + (double) newevtp->p2orig + (double) newevtp->p3orig; else ip->offbet = -1.0; flp = &ip->p1.value; fep = &newevtp->p[0]; if (UNLIKELY(O->odebug)) csound->Message(csound, "psave beg at %p\n", (void*) flp); if (n > newevtp->pcnt) n = newevtp->pcnt; /* IV - Oct 20 2002 */ for (i = 1; i < n + 1; i++) { CS_VAR_MEM* pfield = pfields + i; pfield->varType = (CS_TYPE*)&CS_VAR_TYPE_P; pfield->value = fep[i]; } if (n < tp->pmax && tp->psetdata==NULL) { for (i = 0; i < tp->pmax - n; i++) { CS_VAR_MEM* pfield = pfields + i + n + 1; pfield->varType = (CS_TYPE*)&CS_VAR_TYPE_P; pfield->value = 0; } } if (UNLIKELY(O->odebug)) csound->Message(csound, " ending at %p\n", (void*) flp); } #ifdef HAVE_ATOMIC_BUILTIN __sync_lock_test_and_set((int*)&ip->init_done,1); #else ip->init_done = 1; #endif if (O->Beatmode) ip->p2.value = (MYFLT) (csound->icurTime/csound->esr - csound->timeOffs); ip->offtim = (double) ip->p3.value; /* & duplicate p3 for now */ ip->m_chnbp = (MCHNBLK*) NULL; ip->xtratim = 0; ip->relesing = 0; ip->m_sust = 0; ip->nxtolap = NULL; ip->opcod_iobufs = NULL; ip->strarg = newevtp->strarg; /* copy strarg so it does not get lost */ #ifdef HAVE_ATOMIC_BUILTIN __sync_lock_test_and_set((int*)&ip->init_done,0); #else ip->init_done = 0; #endif if (csound->realtime_audio_flag == 0) { csound->curip = ip; csound->ids = (OPDS *)ip; /* do init pass for this instr */ while ((csound->ids = csound->ids->nxti) != NULL) { if (UNLIKELY(O->odebug)) csound->Message(csound, "init %s:\n", csound->ids->optext->t.oentry->opname); (*csound->ids->iopadr)(csound, csound->ids); } ip->init_done = 1; ip->tieflag = 0; ip->reinitflag = 0; csound->tieflag = csound->reinitflag = 0; } if (UNLIKELY(csound->inerrcnt || ip->p3.value == FL(0.0))) { xturnoff_now(csound, ip); return csound->inerrcnt; } /* new code for sample-accurate timing, not for tied notes */ if (O->sampleAccurate && !tie) { int64_t start_time_samps, start_time_kcycles; double duration_samps; while (ip->init_done != 1) { // FIXME maybe just pass everything through csoundSleep? #if defined(MACOSX) || defined(LINUX) || defined(HAIKU) usleep (1); #else csoundSleep (1); #endif } start_time_samps = (int64_t) (ip->p2.value * csound->esr); duration_samps = ip->p3.value * csound->esr; start_time_kcycles = start_time_samps/csound->ksmps; ip->ksmps_offset = start_time_samps - start_time_kcycles*csound->ksmps; //printf("ksmps offset = %d \n", ip->ksmps_offset); /* with no p3 or xtratim values, can't set the sample accur duration */ if (ip->p3.value > 0 && ip->xtratim == 0) ip->no_end = csound->ksmps - ((int)duration_samps+ip->ksmps_offset)%csound->ksmps; /* the ksmps_no_end field is initially 0, set to no_end in the last perf cycle */ else ip->no_end = 0; ip->ksmps_no_end = 0; /* if (ip->no_end) { */ /* // printf(">>>> %d\n",((int)duration_samps+ip->ksmps_offset)); */ /* printf(">>>> no_end=%d (%ld,%d,%f,%d)\n", */ /* ip->no_end, (long)duration_kcycles, csound->ksmps, */ /* duration_samps, ip->ksmps_offset); */ /* //printf(" > p2=%f p3=%f\n", ip->p2, ip->p3); */ /* } */ } else { /* ksmps_offset = */ ip->ksmps_offset = 0; ip->ksmps_no_end = 0; ip->no_end = 0; } #ifdef BETA if (UNLIKELY(O->odebug)) csound->Message(csound, "In insert: %d %lf %lf\n", __LINE__, ip->p3.value, ip->offtim); /* *********** */ #endif if (ip->p3.value > FL(0.0) && ip->offtim > 0.0) { /* if still finite time, */ double p2 = (double) ip->p2.value + csound->timeOffs; ip->offtim = p2 + (double) ip->p3.value; //csound->Message(csound, "%lf\n", ip->offtim); /* csound->Message(csound, "ip->offtim = %lf -> ", ip->offtim); */ if (O->sampleAccurate && !tie && ip->p3.value > 0 && ip->xtratim == 0) /* ceil for sample-accurate ending */ ip->offtim = CEIL(ip->offtim*csound->ekr) / csound->ekr; else /* normal : round */ ip->offtim = FLOOR(ip->offtim * csound->ekr +0.5)/csound->ekr; //csound->Message(csound, "%lf\n", ip->offtim); if (O->Beatmode) { p2 = ((p2*csound->esr - csound->icurTime) / csound->ibeatTime) + csound->curBeat; ip->offbet = p2 + ((double) ip->p3.value*csound->esr / csound->ibeatTime); } #ifdef BETA if (UNLIKELY(O->odebug)) csound->Message(csound, "Calling schedofftim line %d; offtime= %lf (%lf)\n", __LINE__, ip->offtim, ip->offtim*csound->ekr); #endif schedofftim(csound, ip); /* put in turnoff list */ } else { ip->offbet = -1.0; ip->offtim = -1.0; /* else mark indef */ } if (UNLIKELY(O->odebug)) { char *name = csound->engineState.instrtxtp[insno]->insname; if (UNLIKELY(name)) csound->Message(csound, Str("instr %s now active:\n"), name); else csound->Message(csound, Str("instr %d now active:\n"), insno); showallocs(csound); } if (newevtp->pinstance != NULL) { *((MYFLT *)newevtp->pinstance) = (MYFLT) ((long) ip); } return 0; } /* insert a MIDI instr copy into active list */ /* then run an init pass */ int MIDIinsert(CSOUND *csound, int insno, MCHNBLK *chn, MEVENT *mep) { INSTRTXT *tp; INSDS *ip, **ipp, *prvp, *nxtp; OPARMS *O = csound->oparms; CS_VAR_MEM *pfields; EVTBLK *evt; int pmax = 0; if (UNLIKELY(csound->advanceCnt)) return 0; if (UNLIKELY(insno <= 0 || csound->engineState.instrtxtp[insno]->muted == 0)) return 0; /* muted */ tp = csound->engineState.instrtxtp[insno]; if (tp->cpuload > FL(0.0)) { csound->cpu_power_busy += tp->cpuload; if (UNLIKELY(csound->cpu_power_busy > FL(100.0))) { /* if there is no more cpu time */ csound->cpu_power_busy -= tp->cpuload; csoundWarning(csound, Str("cannot allocate last note because " "it exceeds 100%% of cpu time")); return(0); } } if (UNLIKELY(tp->maxalloc > 0 && tp->active >= tp->maxalloc)) { csoundWarning(csound, Str("cannot allocate last note because it exceeds " "instr maxalloc")); return(0); } tp->active++; tp->instcnt++; csound->dag_changed++; /* Need to remake DAG */ if (UNLIKELY(O->odebug)) { char *name = csound->engineState.instrtxtp[insno]->insname; if (UNLIKELY(name)) csound->Message(csound, Str("MIDI activating instr %s\n"), name); else csound->Message(csound, Str("MIDI activating instr %d\n"), insno); } csound->inerrcnt = 0; ipp = &chn->kinsptr[mep->dat1]; /* key insptr ptr */ /* alloc new dspace if needed */ if (tp->act_instance == NULL || tp->isNew) { if (UNLIKELY(O->msglevel & RNGEMSG)) { char *name = csound->engineState.instrtxtp[insno]->insname; if (UNLIKELY(name)) csound->Message(csound, Str("new MIDI alloc for instr %s:\n"), name); else csound->Message(csound, Str("new MIDI alloc for instr %d:\n"), insno); } instance(csound, insno); tp->isNew = 0; } /* pop from free instance chain */ /* **** COVERITY: note that call to instance fills in structure to **** which tp points. This is a false positive **** */ ip = tp->act_instance; tp->act_instance = ip->nxtact; ip->insno = (int16) insno; if (UNLIKELY(O->odebug)) csound->Message(csound, "Now %d active instr %d\n", tp->active, insno); if (UNLIKELY((prvp = *ipp) != NULL)) { /* if key currently activ */ csoundWarning(csound, Str("MIDI note overlaps with key %d on same channel"), (int) mep->dat1); while (prvp->nxtolap != NULL) /* append to overlap list */ prvp = prvp->nxtolap; prvp->nxtolap = ip; } else *ipp = ip; /* of overlapping notes, the one that was turned on first will be */ /* turned off first as well */ ip->nxtolap = NULL; nxtp = &(csound->actanchor); /* now splice into activ lst */ while ((prvp = nxtp) && (nxtp = prvp->nxtact) != NULL) { if (nxtp->insno > insno) { nxtp->prvact = ip; break; } } ip->nxtact = nxtp; ip->prvact = prvp; prvp->nxtact = ip; ip->actflg++; /* and mark the instr active */ ip->m_chnbp = chn; /* rec address of chnl ctrl blk */ ip->m_pitch = (unsigned char) mep->dat1; /* rec MIDI data */ ip->m_veloc = (unsigned char) mep->dat2; ip->xtratim = 0; ip->m_sust = 0; ip->relesing = 0; ip->offbet = -1.0; ip->offtim = -1.0; /* set indef duration */ ip->opcod_iobufs = NULL; /* IV - Sep 8 2002: */ ip->p1.value = (MYFLT) insno; /* set these required p-fields */ ip->p2.value = (MYFLT) (csound->icurTime/csound->esr - csound->timeOffs); ip->p3.value = FL(-1.0); ip->ksmps = csound->ksmps; ip->ekr = csound->ekr; ip->kcounter = csound->kcounter; ip->onedksmps = csound->onedksmps; ip->onedkr = csound->onedkr; ip->kicvt = csound->kicvt; ip->pds = NULL; pfields = (CS_VAR_MEM*)&ip->p0; if (tp->psetdata != NULL) { int i; MYFLT *pdat = tp->psetdata + 2; int32 nn = tp->pmax - 2; /* put cur vals in pflds */ for (i = 0; i < nn; i++) { CS_VAR_MEM* pfield = (pfields + i + 3); pfield->value = *(pdat + i); } pmax = tp->pmax; } /* MIDI channel message note on routing overrides pset: */ if (O->midiKey) { int pfield_index = O->midiKey; CS_VAR_MEM* pfield = (pfields + pfield_index); MYFLT value = (MYFLT) ip->m_pitch; pfield->value = value; if (UNLIKELY(O->msglevel & WARNMSG)) { csound->Message(csound, " midiKey: pfield: %3d value: %3d\n", pfield_index, (int) pfield->value); } if (pmax < pfield_index) pmax = pfield_index; } else if (O->midiKeyCps) { int pfield_index = O->midiKeyCps; CS_VAR_MEM* pfield = (pfields + pfield_index); MYFLT value = (MYFLT) ip->m_pitch; value = value / FL(12.0) + FL(3.0); value = value * OCTRES; value = (MYFLT) CPSOCTL((int32) value); pfield->value = value; if (UNLIKELY(O->msglevel & WARNMSG)) { csound->Message(csound, " midiKeyCps: pfield: %3d value: %3d\n", pfield_index, (int) pfield->value); } if (pmax < pfield_index) pmax = pfield_index; } else if (O->midiKeyOct) { int pfield_index = O->midiKeyOct; CS_VAR_MEM* pfield = (pfields + pfield_index); MYFLT value = (MYFLT) ip->m_pitch; value = value / FL(12.0) + FL(3.0); pfield->value = value; if (UNLIKELY(O->msglevel & WARNMSG)) { csound->Message(csound, " midiKeyOct: pfield: %3d value: %3d\n", pfield_index, (int) pfield->value); } if (pmax < pfield_index) pmax = pfield_index; } else if (O->midiKeyPch) { int pfield_index = O->midiKeyPch; CS_VAR_MEM* pfield = (pfields + pfield_index); MYFLT value = (MYFLT) ip->m_pitch; double octave = 0; double fraction = 0.0; value = value / FL(12.0) + FL(3.0); fraction = modf(value, &octave); fraction *= 0.12; value = octave + fraction; pfield->value = value; if (UNLIKELY(O->msglevel & WARNMSG)) { csound->Message(csound, " midiKeyPch: pfield: %3d value: %3d\n", pfield_index, (int) pfield->value); } if (pmax < pfield_index) pmax = pfield_index; } if (O->midiVelocity) { int pfield_index = O->midiVelocity; CS_VAR_MEM* pfield = (pfields + pfield_index); MYFLT value = (MYFLT) ip->m_veloc; pfield->value = value; if (UNLIKELY(O->msglevel & WARNMSG)) { csound->Message(csound, " midiVelocity: pfield: %3d value: %3d\n", pfield_index, (int) pfield->value); } if (pmax < pfield_index) pmax = pfield_index; } else if (O->midiVelocityAmp) { int pfield_index = O->midiVelocityAmp; CS_VAR_MEM* pfield = (pfields + pfield_index); MYFLT value = (MYFLT) ip->m_veloc; value = value * value / FL(16239.0); value = value * csound->e0dbfs; pfield->value = value; if (UNLIKELY(O->msglevel & WARNMSG)) { csound->Message(csound, " midiVelocityAmp: pfield: %3d value: %3d\n", pfield_index, (int)pfield->value); } if (pmax < pfield_index) pmax = pfield_index; } if (pmax > 0) { int i; if (csound->currevent == NULL) { evt = (EVTBLK *) csound->Calloc(csound, sizeof(EVTBLK)); csound->currevent = evt; } else evt = csound->currevent; evt->pcnt = pmax+1; for (i =0; i < evt->pcnt; i++) { evt->p[i] = pfields[i].value; } } #ifdef HAVE_ATOMIC_BUILTIN __sync_lock_test_and_set((int*)&ip->init_done,0); #else ip->init_done = 0; #endif csound->curip = ip; if (csound->realtime_audio_flag == 0) { csound->ids = (OPDS *)ip; /* do init pass for this instr */ while ((csound->ids = csound->ids->nxti) != NULL) { if (UNLIKELY(O->odebug)) csound->Message(csound, "init %s:\n", csound->ids->optext->t.oentry->opname); (*csound->ids->iopadr)(csound, csound->ids); } ip->init_done = 1; ip->tieflag = ip->reinitflag = 0; csound->tieflag = csound->reinitflag = 0; } if (UNLIKELY(csound->inerrcnt)) { xturnoff_now(csound, ip); return csound->inerrcnt; } if (UNLIKELY(O->odebug)) { char *name = csound->engineState.instrtxtp[insno]->insname; if (UNLIKELY(name)) csound->Message(csound, Str("instr %s now active:\n"), name); else csound->Message(csound, Str("instr %d now active:\n"), insno); showallocs(csound); } return 0; } static void showallocs(CSOUND *csound) /* debugging aid */ { INSTRTXT *txtp; INSDS *p; csound->Message(csound, "insno\tinstanc\tnxtinst\tprvinst\tnxtact\t" "prvact\tnxtoff\tactflg\tofftim\n"); for (txtp = &(csound->engineState.instxtanchor); txtp != NULL; txtp = txtp->nxtinstxt) if ((p = txtp->instance) != NULL) { /* * On Alpha, we print pointers as pointers. heh 981101 * and now on all platforms (JPff) */ do { csound->Message(csound, "%d\t%p\t%p\t%p\t%p\t%p\t%p\t%d\t%3.1f\n", (int) p->insno, (void*) p, (void*) p->nxtinstance, (void*) p->prvinstance, (void*) p->nxtact, (void*) p->prvact, (void*) p->nxtoff, p->actflg, p->offtim); } while ((p = p->nxtinstance) != NULL); } } static void schedofftim(CSOUND *csound, INSDS *ip) { /* put an active instr into offtime list */ INSDS *prvp, *nxtp; /* called by insert() & midioff + xtratim */ if ((nxtp = csound->frstoff) == NULL || nxtp->offtim > ip->offtim) { /* set into */ csound->frstoff = ip; /* firstoff chain */ ip->nxtoff = nxtp; /* IV - Feb 24 2006: check if this note already needs to be turned off */ /* the following comparisons must match those in sensevents() */ #ifdef BETA if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound,"schedofftim: %lf %lf %f\n", ip->offtim, csound->icurTime/csound->esr, csound->curTime_inc); #endif if (csound->oparms_.Beatmode) { double tval = csound->curBeat + (0.505 * csound->curBeat_inc); if (ip->offbet <= tval) beatexpire(csound, tval); } else { double tval = (csound->icurTime + (0.505 * csound->ksmps))/csound->esr; if (ip->offtim <= tval) timexpire(csound, tval); } #ifdef BETA if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound,"schedofftim: %lf %lf %lf\n", ip->offtim, (csound->icurTime + (0.505 * csound->ksmps))/csound->esr, csound->ekr*((csound->icurTime + (0.505 * csound->ksmps))/csound->esr)); #endif } else { while ((prvp = nxtp) && (nxtp = nxtp->nxtoff) != NULL && ip->offtim >= nxtp->offtim); prvp->nxtoff = ip; ip->nxtoff = nxtp; } } /* csound.c */ extern int csoundDeinitialiseOpcodes(CSOUND *csound, INSDS *ip); int useropcd(CSOUND *, UOPCODE*); static void deact(CSOUND *csound, INSDS *ip) { /* unlink single instr from activ chain */ INSDS *nxtp; /* and mark it inactive */ /* close any files in fd chain */ if (ip->nxtd != NULL) csoundDeinitialiseOpcodes(csound, ip); /* remove an active instrument */ csound->engineState.instrtxtp[ip->insno]->active--; if (ip->xtratim > 0) csound->engineState.instrtxtp[ip->insno]->pending_release--; csound->cpu_power_busy -= csound->engineState.instrtxtp[ip->insno]->cpuload; /* IV - Sep 8 2002: free subinstr instances */ /* that would otherwise result in a memory leak */ if (ip->opcod_deact) { UOPCODE *p = (UOPCODE*) ip->opcod_deact; /* IV - Oct 26 2002 */ deact(csound, p->ip); /* deactivate */ p->ip = NULL; /* IV - Oct 26 2002: set perf routine to "not initialised" */ p->h.opadr = (SUBR) useropcd; ip->opcod_deact = NULL; } if (ip->subins_deact) { deact(csound, ((SUBINST*) ip->subins_deact)->ip); /* IV - Oct 24 2002 */ ((SUBINST*) ip->subins_deact)->ip = NULL; ip->subins_deact = NULL; } if (UNLIKELY(csound->oparms->odebug)) { char *name = csound->engineState.instrtxtp[ip->insno]->insname; if (UNLIKELY(name)) csound->Message(csound, Str("removed instance of instr %s\n"), name); else csound->Message(csound, Str("removed instance of instr %d\n"), ip->insno); } /* IV - Oct 24 2002: ip->prvact may be NULL, so need to check */ if (ip->prvact && (nxtp = ip->prvact->nxtact = ip->nxtact) != NULL) nxtp->prvact = ip->prvact; ip->actflg = 0; /* link into free instance chain */ /* This also destroys ip->nxtact causing loops */ if (csound->engineState.instrtxtp[ip->insno] == ip->instr){ ip->nxtact = csound->engineState.instrtxtp[ip->insno]->act_instance; csound->engineState.instrtxtp[ip->insno]->act_instance = ip; } if (ip->fdchp != NULL) fdchclose(csound, ip); csound->dag_changed++; //printf("**** dag changed by deact\n"); } int kill_instance(CSOUND *csound, KILLOP *p) { if (LIKELY(*p->inst)) xturnoff(csound, (INSDS *) ((long)*p->inst)); else csound->Warning(csound, Str("instance not valid \n")); return OK; } /* Turn off a particular insalloc, also remove from list of active */ /* MIDI notes. Allows for releasing if ip->xtratim > 0. */ void xturnoff(CSOUND *csound, INSDS *ip) /* turnoff a particular insalloc */ { /* called by inexclus on ctrl 111 */ MCHNBLK *chn; if (UNLIKELY(ip->relesing)) return; /* already releasing: nothing to do */ chn = ip->m_chnbp; if (chn != NULL) { /* if this was a MIDI note */ INSDS *prvip; prvip = chn->kinsptr[ip->m_pitch]; /* remov from activ lst */ if (ip->m_sust && chn->ksuscnt) chn->ksuscnt--; ip->m_sust = 0; /* force turnoff even if sustaining */ if (prvip != NULL) { if (prvip == ip) chn->kinsptr[ip->m_pitch] = ip->nxtolap; else { while (prvip != NULL && prvip->nxtolap != ip) prvip = prvip->nxtolap; if (prvip != NULL) prvip->nxtolap = ip->nxtolap; } } } /* remove from schedoff chain first if finite duration */ if (csound->frstoff != NULL && ip->offtim >= 0.0) { INSDS *prvip; prvip = csound->frstoff; if (prvip == ip) csound->frstoff = ip->nxtoff; else { while (prvip != NULL && prvip->nxtoff != ip) prvip = prvip->nxtoff; if (prvip != NULL) prvip->nxtoff = ip->nxtoff; } } /* if extra time needed: schedoff at new time */ if (ip->xtratim > 0) { set_xtratim(csound, ip); #ifdef BETA if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, "Calling schedofftim line %d\n", __LINE__); #endif schedofftim(csound, ip); } else { /* no extra time needed: deactivate immediately */ deact(csound, ip); csound->dag_changed++; /* Need to remake DAG */ //printf("**** dag changed by xturnoff\n"); } } /* Turn off instrument instance immediately, without releasing. */ /* Removes alloc from list of active MIDI notes. */ void xturnoff_now(CSOUND *csound, INSDS *ip) { ip->xtratim = 0; ip->relesing = 0; xturnoff(csound, ip); } extern void free_instrtxt(CSOUND *csound, INSTRTXT *instrtxt); void free_instr_var_memory(CSOUND* csound, INSDS* ip) { INSTRTXT* instrDef = ip->instr; CS_VAR_POOL* pool = instrDef->varPool; CS_VARIABLE* current = pool->head; while (current != NULL) { CS_TYPE* varType = current->varType; if (varType->freeVariableMemory != NULL) { varType->freeVariableMemory(csound, ip->lclbas + current->memBlockIndex); } current = current->next; } } void orcompact(CSOUND *csound) /* free all inactive instr spaces */ { INSTRTXT *txtp; INSDS *ip, *nxtip, *prvip, **prvnxtloc; int cnt = 0; for (txtp = &(csound->engineState.instxtanchor); txtp != NULL; txtp = txtp->nxtinstxt) { // csound->Message(csound, "txp=%p \n", txtp); if ((ip = txtp->instance) != NULL) { /* if instance exists */ prvip = NULL; prvnxtloc = &txtp->instance; do { if (!ip->actflg) { // csound->Message(csound, "ip=%p \n", ip); cnt++; if (ip->opcod_iobufs && ip->insno > csound->engineState.maxinsno) csound->Free(csound, ip->opcod_iobufs); /* IV - Nov 10 2002 */ if (ip->fdchp != NULL) fdchclose(csound, ip); if (ip->auxchp != NULL) auxchfree(csound, ip); free_instr_var_memory(csound, ip); if ((nxtip = ip->nxtinstance) != NULL) nxtip->prvinstance = prvip; *prvnxtloc = nxtip; csound->Free(csound, (char *)ip); } else { prvip = ip; prvnxtloc = &ip->nxtinstance; } } while ((ip = *prvnxtloc) != NULL); } /* IV - Oct 31 2002 */ if (!txtp->instance) txtp->lst_instance = NULL; /* find last alloc */ else { ip = txtp->instance; while (ip->nxtinstance) ip = ip->nxtinstance; txtp->lst_instance = ip; } txtp->act_instance = NULL; /* no free instances */ } /* check current items in deadpool to see if they need deleting */ { int i; for (i=0; i < csound->dead_instr_no; i++) { if (csound->dead_instr_pool[i] != NULL) { INSDS *active = csound->dead_instr_pool[i]->instance; while (active != NULL) { if (active->actflg) { // add_to_deadpool(csound,csound->dead_instr_pool[i]); break; } active = active->nxtinstance; } /* no active instances */ if (active == NULL) { free_instrtxt(csound, csound->dead_instr_pool[i]); csound->dead_instr_pool[i] = NULL; } } } } if (UNLIKELY(cnt)) csound->Message(csound, Str("inactive allocs returned to freespace\n")); } void infoff(CSOUND *csound, MYFLT p1) /* turn off an indef copy of instr p1 */ { /* called by musmon */ INSDS *ip; int insno; insno = (int) p1; if (LIKELY((ip = (csound->engineState.instrtxtp[insno])->instance) != NULL)) { do { if (ip->insno == insno /* if find the insno */ && ip->actflg /* active */ && ip->offtim < 0.0 /* but indef, VL: currently this condition cannot be removed, as it breaks turning off extratime instances */ && ip->p1.value == p1) { if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, "turning off inf copy of instr %d\n", insno); xturnoff(csound, ip); return; /* turn it off */ } } while ((ip = ip->nxtinstance) != NULL); } csound->Message(csound, Str("could not find playing instr %f\n"), p1); } int csoundInitError(CSOUND *csound, const char *s, ...) { va_list args; INSDS *ip; char buf[512]; /* RWD: need this! */ if (UNLIKELY(csound->ids == NULL)) { va_start(args, s); csoundErrMsgV(csound, Str("\nINIT ERROR: "), s, args); va_end(args); csound->LongJmp(csound, 1); } /* IV - Oct 16 2002: check for subinstr and user opcode */ ip = csound->ids->insdshead; if (ip->opcod_iobufs) { OPCODINFO *op = ((OPCOD_IOBUFS*) ip->opcod_iobufs)->opcode_info; /* find top level instrument instance */ do { ip = ((OPCOD_IOBUFS*) ip->opcod_iobufs)->parent_ip; } while (ip->opcod_iobufs); if (op) snprintf(buf, 512, Str("INIT ERROR in instr %d (opcode %s): "), ip->insno, op->name); else snprintf(buf, 512, Str("INIT ERROR in instr %d (subinstr %d): "), ip->insno, csound->ids->insdshead->insno); } else snprintf(buf, 512, Str("INIT ERROR in instr %d: "), ip->insno); va_start(args, s); csoundErrMsgV(csound, buf, s, args); va_end(args); putop(csound, &(csound->ids->optext->t)); return ++(csound->inerrcnt); } int csoundPerfError(CSOUND *csound, INSDS *ip, const char *s, ...) { va_list args; char buf[512]; if (ip->opcod_iobufs) { OPCODINFO *op = ((OPCOD_IOBUFS*) ip->opcod_iobufs)->opcode_info; /* find top level instrument instance */ do { ip = ((OPCOD_IOBUFS*) ip->opcod_iobufs)->parent_ip; } while (ip->opcod_iobufs); if (op) snprintf(buf, 512, Str("PERF ERROR in instr %d (opcode %s): "), ip->insno, op->name); else snprintf(buf, 512, Str("PERF ERROR in instr %d (subinstr %d): "), ip->insno, ip->insno); } else snprintf(buf, 512, Str("PERF ERROR in instr %d: "), ip->insno); va_start(args, s); csoundErrMsgV(csound, buf, s, args); va_end(args); if (ip->pds) putop(csound, &(ip->pds->optext->t)); csoundMessage(csound, Str(" note aborted\n")); csound->perferrcnt++; xturnoff_now((CSOUND*) csound, ip); /* rm ins fr actlist */ return csound->perferrcnt; /* contin from there */ } int subinstrset_(CSOUND *csound, SUBINST *p, int instno) { OPDS *saved_ids = csound->ids; INSDS *saved_curip = csound->curip; CS_VAR_MEM *pfield; int n, init_op, inarg_ofs; INSDS *pip = p->h.insdshead; init_op = (p->h.opadr == NULL ? 1 : 0); inarg_ofs = (init_op ? 0 : SUBINSTNUMOUTS); if (UNLIKELY(instno < 0)) return NOTOK; /* IV - Oct 9 2002: need this check */ if (UNLIKELY(!init_op && p->OUTOCOUNT > csound->nchnls)) { return csoundInitError(csound, Str("subinstr: number of output " "args greater than nchnls")); } /* IV - Oct 9 2002: copied this code from useropcdset() to fix some bugs */ if (!(pip->reinitflag | pip->tieflag)) { /* get instance */ if (csound->engineState.instrtxtp[instno]->act_instance == NULL) instance(csound, instno); p->ip = csound->engineState.instrtxtp[instno]->act_instance; csound->engineState.instrtxtp[instno]->act_instance = p->ip->nxtact; p->ip->insno = (int16) instno; p->ip->actflg++; /* and mark the instr active */ csound->engineState.instrtxtp[instno]->active++; csound->engineState.instrtxtp[instno]->instcnt++; p->ip->p1.value = (MYFLT) instno; /* VL 21-10-16: iobufs are not used here and are causing trouble elsewhere. Commenting it out */ /* p->ip->opcod_iobufs = (void*) &p->buf; */ /* link into deact chain */ p->ip->subins_deact = saved_curip->subins_deact; p->ip->opcod_deact = NULL; saved_curip->subins_deact = (void*) p; p->parent_ip = p->buf.parent_ip = saved_curip; } /* set the local ksmps values */ // if (local_ksmps != CS_KSMPS) { // /* this is the case when p->ip->ksmps != p->h.insdshead->ksmps */ // p->ip->ksmps = local_ksmps; // ksmps_scale = CS_KSMPS / local_ksmps; // lcurip->onedksmps = FL(1.0) / (MYFLT) local_ksmps; // lcurip->ekr = csound->esr / (MYFLT) local_ksmps; // lcurip->onedkr = FL(1.0) / lcurip->ekr; // lcurip->kicvt = (MYFLT) FMAXLEN /lcurip->ekr; // lcurip->kcounter *= ksmps_scale; // } else { p->ip->ksmps = CS_KSMPS; p->ip->kcounter = CS_KCNT; p->ip->ekr = CS_EKR; p->ip->onedkr = CS_ONEDKR; p->ip->onedksmps = CS_ONEDKSMPS; p->ip->kicvt = CS_KICVT; // } /* copy parameters from this instrument into our subinstrument */ p->ip->xtratim = saved_curip->xtratim; p->ip->m_sust = 0; p->ip->relesing = saved_curip->relesing; p->ip->offbet = saved_curip->offbet; p->ip->offtim = saved_curip->offtim; p->ip->nxtolap = NULL; p->ip->p2 = saved_curip->p2; p->ip->p3 = saved_curip->p3; p->ip->ksmps = CS_KSMPS; /* IV - Oct 31 2002 */ p->ip->m_chnbp = saved_curip->m_chnbp; p->ip->m_pitch = saved_curip->m_pitch; p->ip->m_veloc = saved_curip->m_veloc; p->ip->ksmps_offset = saved_curip->ksmps_offset; p->ip->ksmps_no_end = saved_curip->ksmps_no_end; p->ip->tieflag = saved_curip->tieflag; p->ip->reinitflag = saved_curip->reinitflag; /* copy remainder of pfields */ pfield = (CS_VAR_MEM*)&p->ip->p3; /* by default all inputs are i-rate mapped to p-fields */ if (UNLIKELY(p->INOCOUNT > (unsigned int)(csound->engineState.instrtxtp[instno]->pmax + 1))) return csoundInitError(csound, Str("subinstr: too many p-fields")); union { MYFLT d; int32 i; } ch; int str_cnt = 0, len = 0; char *argstr; for (n = 1; (unsigned int) n < p->INOCOUNT; n++){ if (IS_STR_ARG(p->ar[inarg_ofs + n])) { ch.d = SSTRCOD; ch.i = str_cnt & 0xffff; (pfield + n)->value = ch.d; argstr = ((STRINGDAT *)p->ar[inarg_ofs + n])->data; if (str_cnt == 0) p->ip->strarg = csound->Calloc(csound, strlen(argstr)+1); else p->ip->strarg = csound->ReAlloc(csound, p->ip->strarg, len+strlen(argstr)+1); strcpy(p->ip->strarg + len, argstr); len += strlen(argstr)+1; str_cnt++; } else (pfield + n)->value = *p->ar[inarg_ofs + n]; } /* allocate memory for a temporary store of spout buffers */ if (!init_op && !(pip->reinitflag | pip->tieflag)) csoundAuxAlloc(csound, (int32) csound->nspout * sizeof(MYFLT), &p->saved_spout); /* do init pass for this instr */ csound->curip = p->ip; csound->ids = (OPDS *)p->ip; p->ip->init_done = 0; while ((csound->ids = csound->ids->nxti) != NULL) { (*csound->ids->iopadr)(csound, csound->ids); } p->ip->init_done = 1; /* copy length related parameters back to caller instr */ saved_curip->xtratim = csound->curip->xtratim; saved_curip->relesing = csound->curip->relesing; saved_curip->offbet = csound->curip->offbet; saved_curip->offtim = csound->curip->offtim; saved_curip->p3 = csound->curip->p3; /* restore globals */ csound->ids = saved_ids; csound->curip = saved_curip; return OK; } int subinstrset_S(CSOUND *csound, SUBINST *p){ int instno, init_op, inarg_ofs; /* check if we are using subinstrinit or subinstr */ init_op = (p->h.opadr == NULL ? 1 : 0); inarg_ofs = (init_op ? 0 : SUBINSTNUMOUTS); instno = strarg2insno(csound, ((STRINGDAT *)p->ar[inarg_ofs])->data, 1); return subinstrset_(csound,p,instno); } int subinstrset(CSOUND *csound, SUBINST *p){ int instno, init_op, inarg_ofs; /* check if we are using subinstrinit or subinstr */ init_op = (p->h.opadr == NULL ? 1 : 0); inarg_ofs = (init_op ? 0 : SUBINSTNUMOUTS); instno = (int) *(p->ar[inarg_ofs]); return subinstrset_(csound,p,instno); } /* IV - Sep 8 2002: new functions for user defined opcodes (based */ /* on Matt J. Ingalls' subinstruments, but mostly rewritten) */ /* UDOs now use the local ksmps stored in lcurip->ksmps all the other dependent parameters are calculated in relation to this. lcurip->ksmps is set to the caller ksmps (CS_KSMPS), unless a new local ksmps is used, in which case it is set to that value. If local ksmps differs from CS_KSMPS, we set useropcd1() to deal with the perf-time code. Otherwise useropcd2() is used. For recursive calls when the local ksmps is set to differ from the calling instrument ksmps, the top-level call will use useropcd1(), whereas all the other recursive calls will use useropdc2(), since their local ksmps will be the same as the caller. Also in case of a local ksmps that differs from the caller, the local kcounter value, obtained from the caller is scaled to denote the correct kcount in terms of local kcycles. */ int useropcd1(CSOUND *, UOPCODE*), useropcd2(CSOUND *, UOPCODE*); int useropcdset(CSOUND *csound, UOPCODE *p) { OPDS *saved_ids = csound->ids; INSDS *parent_ip = csound->curip, *lcurip; INSTRTXT *tp; unsigned int instno; unsigned int pcnt; unsigned int i, n; OPCODINFO *inm; OPCOD_IOBUFS *buf = NULL; MYFLT ksmps_scale; unsigned int local_ksmps; /* default ksmps */ local_ksmps = CS_KSMPS; ksmps_scale = 1; /* look up the 'fake' instr number, and opcode name */ inm = (OPCODINFO*) p->h.optext->t.oentry->useropinfo; instno = inm->instno; tp = csound->engineState.instrtxtp[instno]; if (tp == NULL) return csound->InitError(csound, "Can't find instr %d (UDO %s)\n", instno, inm->name); /* set local ksmps if defined by user */ n = p->OUTOCOUNT + p->INCOUNT - 1; if (*(p->ar[n]) != FL(0.0)) { i = (unsigned int) *(p->ar[n]); if (UNLIKELY(i < 1 || i > csound->ksmps || ((CS_KSMPS / i) * i) != CS_KSMPS)) { return csoundInitError(csound, Str("%s: invalid local ksmps value: %d"), inm->name, i); } local_ksmps = i; } if (!p->ip) { /* search for already allocated, but not active instance */ /* if none was found, allocate a new instance */ if (!tp->act_instance) instance(csound, instno); /* **** COVERITY: note that call to instance fills in structure to **** which tp points. This is a false positive **** */ lcurip = tp->act_instance; /* use free intance, and */ tp->act_instance = lcurip->nxtact; /* remove from chain */ lcurip->actflg++; /* and mark the instr active */ tp->active++; tp->instcnt++; /* link into deact chain */ lcurip->opcod_deact = parent_ip->opcod_deact; lcurip->subins_deact = NULL; parent_ip->opcod_deact = (void*) p; p->ip = lcurip; /* IV - Nov 10 2002: set up pointers to I/O buffers */ buf = p->buf = (OPCOD_IOBUFS*) lcurip->opcod_iobufs; buf->opcode_info = inm; /* initialise perf time address lists */ buf->iobufp_ptrs[0] = buf->iobufp_ptrs[1] = NULL; buf->iobufp_ptrs[2] = buf->iobufp_ptrs[3] = NULL; buf->iobufp_ptrs[4] = buf->iobufp_ptrs[5] = NULL; buf->iobufp_ptrs[6] = buf->iobufp_ptrs[7] = NULL; buf->iobufp_ptrs[8] = buf->iobufp_ptrs[9] = NULL; buf->iobufp_ptrs[10] = buf->iobufp_ptrs[11] = NULL; /* store parameters of input and output channels, and parent ip */ buf->uopcode_struct = (void*) p; buf->parent_ip = p->parent_ip = parent_ip; } /* copy parameters from the caller instrument into our subinstrument */ lcurip = p->ip; /* set the local ksmps values */ if (local_ksmps != CS_KSMPS) { /* this is the case when p->ip->ksmps != p->h.insdshead->ksmps */ lcurip->ksmps = local_ksmps; ksmps_scale = CS_KSMPS / local_ksmps; lcurip->onedksmps = FL(1.0) / (MYFLT) local_ksmps; lcurip->ekr = csound->esr / (MYFLT) local_ksmps; lcurip->onedkr = FL(1.0) / lcurip->ekr; lcurip->kicvt = (MYFLT) FMAXLEN /lcurip->ekr; lcurip->kcounter *= ksmps_scale; } else { lcurip->ksmps = CS_KSMPS; lcurip->kcounter = CS_KCNT; lcurip->ekr = CS_EKR; lcurip->onedkr = CS_ONEDKR; lcurip->onedksmps = CS_ONEDKSMPS; lcurip->kicvt = CS_KICVT; } /* VL 13-12-13 */ /* this sets ksmps and kr local variables */ /* create local ksmps variable and init with ksmps */ if (lcurip->lclbas != NULL) { CS_VARIABLE *var = csoundFindVariableWithName(csound, lcurip->instr->varPool, "ksmps"); *((MYFLT *)(var->memBlockIndex + lcurip->lclbas)) = lcurip->ksmps; /* same for kr */ var = csoundFindVariableWithName(csound, lcurip->instr->varPool, "kr"); *((MYFLT *)(var->memBlockIndex + lcurip->lclbas)) = lcurip->ekr; } lcurip->m_chnbp = parent_ip->m_chnbp; /* MIDI parameters */ lcurip->m_pitch = parent_ip->m_pitch; lcurip->m_veloc = parent_ip->m_veloc; lcurip->xtratim = parent_ip->xtratim * ksmps_scale; lcurip->m_sust = 0; lcurip->relesing = parent_ip->relesing; lcurip->offbet = parent_ip->offbet; lcurip->offtim = parent_ip->offtim; lcurip->nxtolap = NULL; lcurip->ksmps_offset = parent_ip->ksmps_offset; lcurip->ksmps_no_end = parent_ip->ksmps_no_end; lcurip->tieflag = parent_ip->tieflag; lcurip->reinitflag = parent_ip->reinitflag; /* copy all p-fields, including p1 (will this work ?) */ if (tp->pmax > 3) { /* requested number of p-fields */ n = tp->pmax; pcnt = 0; while (pcnt < n) { if ((i = csound->engineState.instrtxtp[parent_ip->insno]->pmax) > pcnt) { if (i > n) i = n; /* copy next block of p-fields */ memcpy(&(lcurip->p1) + pcnt, &(parent_ip->p1) + pcnt, (size_t) ((i - pcnt) * sizeof(CS_VAR_MEM))); pcnt = i; } /* top level instr reached */ if (parent_ip->opcod_iobufs == NULL) break; parent_ip = ((OPCOD_IOBUFS*) parent_ip->opcod_iobufs)->parent_ip; } } else memcpy(&(lcurip->p1), &(parent_ip->p1), 3 * sizeof(CS_VAR_MEM)); /* do init pass for this instr */ p->ip->init_done = 0; csound->curip = lcurip; csound->ids = (OPDS *) (lcurip->nxti); while (csound->ids != NULL) { (*csound->ids->iopadr)(csound, csound->ids); csound->ids = csound->ids->nxti; } p->ip->init_done = 1; /* copy length related parameters back to caller instr */ parent_ip->relesing = lcurip->relesing; parent_ip->offbet = lcurip->offbet; parent_ip->offtim = lcurip->offtim; parent_ip->p3 = lcurip->p3; local_ksmps = lcurip->ksmps; /* restore globals */ csound->ids = saved_ids; csound->curip = parent_ip; /* select perf routine and scale xtratim accordingly */ if (local_ksmps != CS_KSMPS) { ksmps_scale = CS_KSMPS / local_ksmps; parent_ip->xtratim = lcurip->xtratim / ksmps_scale; p->h.opadr = (SUBR) useropcd1; } else { parent_ip->xtratim = lcurip->xtratim; p->h.opadr = (SUBR) useropcd2; } if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, "EXTRATIM=> cur(%p): %d, parent(%p): %d\n", lcurip, lcurip->xtratim, parent_ip, parent_ip->xtratim); return OK; } /* IV - Sep 17 2002: dummy user opcode function for not initialised case */ int useropcd(CSOUND *csound, UOPCODE *p) { if (UNLIKELY(p->h.nxtp)) return csoundPerfError(csound, p->h.insdshead, Str("%s: not initialised"), p->h.optext->t.opcod); else return OK; } /* IV - Sep 1 2002: new opcodes: xin, xout */ int xinset(CSOUND *csound, XIN *p) { OPCOD_IOBUFS *buf; OPCODINFO *inm; MYFLT **bufs, **tmp; int i; CS_VARIABLE* current; (void) csound; buf = (OPCOD_IOBUFS*) p->h.insdshead->opcod_iobufs; inm = buf->opcode_info; bufs = ((UOPCODE*) buf->uopcode_struct)->ar + inm->outchns; tmp = buf->iobufp_ptrs; // this is used to record the UDO's internal vars // for copying at perf-time current = inm->in_arg_pool->head; for (i = 0; i < inm->inchns; i++) { void* in = (void*)bufs[i]; void* out = (void*)p->args[i]; tmp[i + inm->outchns] = out; current->varType->copyValue(csound, out, in); current = current->next; } return OK; } int xoutset(CSOUND *csound, XOUT *p) { OPCOD_IOBUFS *buf; OPCODINFO *inm; MYFLT **bufs, **tmp; CS_VARIABLE* current; int i; (void) csound; buf = (OPCOD_IOBUFS*) p->h.insdshead->opcod_iobufs; inm = buf->opcode_info; bufs = ((UOPCODE*) buf->uopcode_struct)->ar; tmp = buf->iobufp_ptrs; // this is used to record the UDO's internal vars // for copying at perf-time current = inm->out_arg_pool->head; for (i = 0; i < inm->outchns; i++) { void* in = (void*)p->args[i]; void* out = (void*)bufs[i]; tmp[i] = in; current->varType->copyValue(csound, out, in); current = current->next; } return OK; } /* IV - Sep 8 2002: new opcode: setksmps */ /* This opcode sets the local ksmps for an instrument it can be used on any instrument with the implementation of a mechanism to perform at local ksmps (in kperf etc) */ //#include "typetabl.h" #include "csound_standard_types.h" int setksmpsset(CSOUND *csound, SETKSMPS *p) { unsigned int l_ksmps, n; l_ksmps = (unsigned int) *(p->i_ksmps); if (!l_ksmps) return OK; /* zero: do not change */ if (UNLIKELY(l_ksmps < 1 || l_ksmps > CS_KSMPS || ((CS_KSMPS / l_ksmps) * l_ksmps != CS_KSMPS))) { return csoundInitError(csound, Str("setksmps: invalid ksmps value: %d, original: %d"), l_ksmps, CS_KSMPS); } n = CS_KSMPS / l_ksmps; p->h.insdshead->xtratim *= n; CS_KSMPS = l_ksmps; CS_ONEDKSMPS = FL(1.0) / (MYFLT) CS_KSMPS; CS_EKR = csound->esr / (MYFLT) CS_KSMPS; CS_ONEDKR = FL(1.0) / CS_EKR; CS_KICVT = (MYFLT) FMAXLEN / CS_EKR; CS_KCNT *= n; /* VL 13-12-13 */ /* this sets ksmps and kr local variables */ /* lookup local ksmps variable and init with ksmps */ INSTRTXT *ip = p->h.insdshead->instr; CS_VARIABLE *var = csoundFindVariableWithName(csound, ip->varPool, "ksmps"); MYFLT *varmem = p->h.insdshead->lclbas + var->memBlockIndex; *varmem = CS_KSMPS; /* same for kr */ var = csoundFindVariableWithName(csound, ip->varPool, "kr"); varmem = p->h.insdshead->lclbas + var->memBlockIndex; *varmem = CS_EKR; return OK; } /* IV - Oct 16 2002: nstrnum opcode (returns the instrument number of a */ /* named instrument) */ int nstrnumset(CSOUND *csound, NSTRNUM *p) { /* IV - Oct 31 2002 */ *(p->i_insno) = (MYFLT) strarg2insno(csound, p->iname, 0); return (*(p->i_insno) > FL(0.0) ? OK : NOTOK); } int nstrnumset_S(CSOUND *csound, NSTRNUM *p) { /* IV - Oct 31 2002 */ *(p->i_insno) = (MYFLT) strarg2insno(csound, ((STRINGDAT *)p->iname)->data, 1); return (*(p->i_insno) > FL(0.0) ? OK : NOTOK); } /* unlink expired notes from activ chain */ /* and mark them inactive */ /* close any files in each fdchain */ /* IV - Feb 05 2005: changed to double */ void beatexpire(CSOUND *csound, double beat) { INSDS *ip; strt: if ((ip = csound->frstoff) != NULL && ip->offbet <= beat) { do { if (!ip->relesing && ip->xtratim) { /* IV - Nov 30 2002: */ /* allow extra time for finite length (p3 > 0) score notes */ set_xtratim(csound, ip); /* enter release stage */ csound->frstoff = ip->nxtoff; /* update turnoff list */ #ifdef BETA if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, "Calling schedofftim line %d\n", __LINE__); #endif schedofftim(csound, ip); goto strt; /* and start again */ } else deact(csound, ip); /* IV - Sep 5 2002: use deact() as it also */ } /* deactivates subinstrument instances */ while ((ip = ip->nxtoff) != NULL && ip->offbet <= beat); csound->frstoff = ip; if (UNLIKELY(csound->oparms->odebug)) { csound->Message(csound, "deactivated all notes to beat %7.3f\n", beat); csound->Message(csound, "frstoff = %p\n", (void*) csound->frstoff); } } } /* unlink expired notes from activ chain */ /* and mark them inactive */ /* close any files in each fdchain */ /* IV - Feb 05 2005: changed to double */ void timexpire(CSOUND *csound, double time) { INSDS *ip; strt: if ((ip = csound->frstoff) != NULL && ip->offtim <= time) { do { if (!ip->relesing && ip->xtratim) { /* IV - Nov 30 2002: */ /* allow extra time for finite length (p3 > 0) score notes */ set_xtratim(csound, ip); /* enter release stage */ csound->frstoff = ip->nxtoff; /* update turnoff list */ #ifdef BETA if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, "Calling schedofftim line %d\n", __LINE__); #endif schedofftim(csound, ip); goto strt; /* and start again */ } else deact(csound, ip); /* IV - Sep 5 2002: use deact() as it also */ } /* deactivates subinstrument instances */ while ((ip = ip->nxtoff) != NULL && ip->offtim <= time); csound->frstoff = ip; if (UNLIKELY(csound->oparms->odebug)) { csound->Message(csound, "deactivated all notes to time %7.3f\n", time); csound->Message(csound, "frstoff = %p\n", (void*) csound->frstoff); } } } /** this was rewritten for Csound 6 to allow PARCS and local ksmps instruments */ int subinstr(CSOUND *csound, SUBINST *p) { OPDS *saved_pds = CS_PDS; MYFLT *pbuf; uint32_t frame, chan; unsigned int nsmps = CS_KSMPS; INSDS *ip = p->ip; //printf("%s \n", p->ip->strarg); if (UNLIKELY(p->ip == NULL)) { /* IV - Oct 26 2002 */ return csoundPerfError(csound, p->h.insdshead, Str("subinstr: not initialised")); } /* copy current spout buffer and clear it */ ip->spout = (MYFLT*) p->saved_spout.auxp; memset(ip->spout, 0, csound->nspout*sizeof(MYFLT)); csound->spoutactive = 0; /* update release flag */ ip->relesing = p->parent_ip->relesing; /* IV - Nov 16 2002 */ /* run each opcode */ if (csound->ksmps == ip->ksmps) { if ((CS_PDS = (OPDS *) (ip->nxtp)) != NULL) { CS_PDS->insdshead->pds = NULL; do { (*CS_PDS->opadr)(csound, CS_PDS); if (CS_PDS->insdshead->pds != NULL) { CS_PDS = CS_PDS->insdshead->pds; CS_PDS->insdshead->pds = NULL; } } while ((CS_PDS = CS_PDS->nxtp)); } ip->kcounter++; } else { int i, n = csound->nspout, start = 0; int lksmps = ip->ksmps; int incr = csound->nchnls*lksmps; int offset = ip->ksmps_offset; int early = ip->ksmps_no_end; ip->spin = csound->spin; ip->kcounter = csound->kcounter*csound->ksmps/lksmps; /* we have to deal with sample-accurate code whole CS_KSMPS blocks are offset here, the remainder is left to each opcode to deal with. */ while (offset >= lksmps) { offset -= lksmps; start += csound->nchnls; } ip->ksmps_offset = offset; if (early) { n -= (early*csound->nchnls); ip->ksmps_no_end = early % lksmps; } for (i=start; i < n; i+=incr, ip->spin+=incr, ip->spout+=incr) { if ((CS_PDS = (OPDS *) (ip->nxtp)) != NULL) { CS_PDS->insdshead->pds = NULL; do { (*CS_PDS->opadr)(csound, CS_PDS); if (CS_PDS->insdshead->pds != NULL) { CS_PDS = CS_PDS->insdshead->pds; CS_PDS->insdshead->pds = NULL; } } while ((CS_PDS = CS_PDS->nxtp)); } ip->kcounter++; } ip->spout = (MYFLT*) p->saved_spout.auxp; } /* copy outputs */ for (chan = 0; chan < p->OUTOCOUNT; chan++) { for (pbuf = ip->spout + chan*nsmps, frame = 0; frame < nsmps; frame++) { p->ar[chan][frame] = pbuf[frame]; //printf("%f \n", p->ar[chan][frame]); //pbuf += csound->nchnls; } } CS_PDS = saved_pds; /* check if instrument was deactivated (e.g. by perferror) */ if (!p->ip) { /* loop to last opds */ while (CS_PDS->nxtp) { CS_PDS = CS_PDS->nxtp; } } return OK; } /* IV - Sep 17 2002 -- case 1: local ksmps is used */ int useropcd1(CSOUND *csound, UOPCODE *p) { OPDS *saved_pds = CS_PDS; int g_ksmps, ofs, early, offset, i; OPCODINFO *inm; CS_VARIABLE* current; INSDS *this_instr = p->ip; MYFLT** internal_ptrs = p->buf->iobufp_ptrs; MYFLT** external_ptrs = p->ar; p->ip->relesing = p->parent_ip->relesing; /* IV - Nov 16 2002 */ early = p->h.insdshead->ksmps_no_end; offset = p->h.insdshead->ksmps_offset; p->ip->spin = p->parent_ip->spin; p->ip->spout = p->parent_ip->spout; inm = p->buf->opcode_info; /* global ksmps is the caller instr ksmps minus sample-accurate end */ g_ksmps = CS_KSMPS - early; /* sample-accurate offset */ ofs = offset; /* clear offsets, since with CS_KSMPS=1 they don't apply to opcodes, but to the calling code (ie. this code) */ this_instr->ksmps_offset = 0; this_instr->ksmps_no_end = 0; if (this_instr->ksmps == 1) { /* special case for local kr == sr */ do { /* copy inputs */ current = inm->in_arg_pool->head; for (i = 0; i < inm->inchns; i++) { // this hardcoded type check for non-perf time vars needs to change //to use generic code... // skip a-vars for now, handle uniquely within performance loop if (current->varType != &CS_VAR_TYPE_I && current->varType != &CS_VAR_TYPE_b && current->varType != &CS_VAR_TYPE_A && current->subType != &CS_VAR_TYPE_I && current->subType != &CS_VAR_TYPE_A) { // This one checks if an array has a subtype of 'i' void* in = (void*)external_ptrs[i + inm->outchns]; void* out = (void*)internal_ptrs[i + inm->outchns]; current->varType->copyValue(csound, out, in); } else if (current->varType == &CS_VAR_TYPE_A) { MYFLT* in = (void*)external_ptrs[i + inm->outchns]; MYFLT* out = (void*)internal_ptrs[i + inm->outchns]; *out = *(in + ofs); } else if (current->varType == &CS_VAR_TYPE_ARRAY && current->subType == &CS_VAR_TYPE_A) { ARRAYDAT* src = (ARRAYDAT*)external_ptrs[i + inm->outchns]; ARRAYDAT* target = (ARRAYDAT*)internal_ptrs[i + inm->outchns]; int count = src->sizes[0]; int j; if (src->dimensions > 1) { for (j = 0; j < src->dimensions; j++) { count *= src->sizes[j]; } } for (j = 0; j < count; j++) { int memberOffset = j * (src->arrayMemberSize / sizeof(MYFLT)); MYFLT* in = src->data + memberOffset; MYFLT* out = target->data + memberOffset; *out = *(in + ofs); } } current = current->next; } if ((CS_PDS = (OPDS *) (this_instr->nxtp)) != NULL) { CS_PDS->insdshead->pds = NULL; do { (*CS_PDS->opadr)(csound, CS_PDS); if (CS_PDS->insdshead->pds != NULL && CS_PDS->insdshead->pds->insdshead) { CS_PDS = CS_PDS->insdshead->pds; CS_PDS->insdshead->pds = NULL; } } while ((CS_PDS = CS_PDS->nxtp)); } /* copy a-sig outputs, accounting for offset */ current = inm->out_arg_pool->head; for (i = 0; i < inm->outchns; i++) { if (current->varType == &CS_VAR_TYPE_A) { MYFLT* in = (void*)internal_ptrs[i]; MYFLT* out = (void*)external_ptrs[i]; *(out + ofs) = *in; } else if (current->varType == &CS_VAR_TYPE_ARRAY && current->subType == &CS_VAR_TYPE_A) { ARRAYDAT* src = (ARRAYDAT*)internal_ptrs[i]; ARRAYDAT* target = (ARRAYDAT*)external_ptrs[i]; int count = src->sizes[0]; int j; if (src->dimensions > 1) { for (j = 0; j < src->dimensions; j++) { count *= src->sizes[j]; } } for (j = 0; j < count; j++) { int memberOffset = j * (src->arrayMemberSize / sizeof(MYFLT)); MYFLT* in = src->data + memberOffset; MYFLT* out = target->data + memberOffset; *(out + ofs) = *in; } } current = current->next; } this_instr->kcounter++; this_instr->spout += csound->nchnls; this_instr->spin += csound->nchnls; } while (++ofs < g_ksmps); } else { /* generic case for local kr != sr */ /* we have to deal with sample-accurate code whole CS_KSMPS blocks are offset here, the remainder is left to each opcode to deal with. */ int start = 0; int lksmps = this_instr->ksmps; while (ofs >= lksmps) { ofs -= lksmps; start++; } this_instr->ksmps_offset = ofs; ofs = start; if (UNLIKELY(early)) this_instr->ksmps_no_end = early % lksmps; do { /* copy a-sig inputs, accounting for offset */ size_t asigSize = (this_instr->ksmps * sizeof(MYFLT)); current = inm->in_arg_pool->head; for (i = 0; i < inm->inchns; i++) { // this hardcoded type check for non-perf time vars needs to change //to use generic code... // skip a-vars for now, handle uniquely within performance loop if (current->varType != &CS_VAR_TYPE_I && current->varType != &CS_VAR_TYPE_b && current->varType != &CS_VAR_TYPE_A && current->subType != &CS_VAR_TYPE_I && current->subType != &CS_VAR_TYPE_A) { // This one checks if an array has a subtype of 'i' void* in = (void*)external_ptrs[i + inm->outchns]; void* out = (void*)internal_ptrs[i + inm->outchns]; current->varType->copyValue(csound, out, in); } else if (current->varType == &CS_VAR_TYPE_A) { MYFLT* in = (void*)external_ptrs[i + inm->outchns]; MYFLT* out = (void*)internal_ptrs[i + inm->outchns]; memcpy(out, in + ofs, asigSize); } else if (current->varType == &CS_VAR_TYPE_ARRAY && current->subType == &CS_VAR_TYPE_A) { ARRAYDAT* src = (ARRAYDAT*)external_ptrs[i + inm->outchns]; ARRAYDAT* target = (ARRAYDAT*)internal_ptrs[i + inm->outchns]; int count = src->sizes[0]; int j; if (src->dimensions > 1) { for (j = 0; j < src->dimensions; j++) { count *= src->sizes[j]; } } for (j = 0; j < count; j++) { int memberOffset = j * (src->arrayMemberSize / sizeof(MYFLT)); MYFLT* in = src->data + memberOffset; MYFLT* out = target->data + memberOffset; memcpy(out, in + ofs, asigSize); } } current = current->next; } /* run each opcode */ if ((CS_PDS = (OPDS *) (this_instr->nxtp)) != NULL) { CS_PDS->insdshead->pds = NULL; do { (*CS_PDS->opadr)(csound, CS_PDS); if (CS_PDS->insdshead->pds != NULL && CS_PDS->insdshead->pds->insdshead) { CS_PDS = CS_PDS->insdshead->pds; CS_PDS->insdshead->pds = NULL; } }while ((CS_PDS = CS_PDS->nxtp)); } /* copy a-sig outputs, accounting for offset */ current = inm->out_arg_pool->head; for (i = 0; i < inm->outchns; i++) { if (current->varType == &CS_VAR_TYPE_A) { MYFLT* in = (void*)internal_ptrs[i]; MYFLT* out = (void*)external_ptrs[i]; memcpy(out + ofs, in, asigSize); } else if (current->varType == &CS_VAR_TYPE_ARRAY && current->subType == &CS_VAR_TYPE_A) { ARRAYDAT* src = (ARRAYDAT*)internal_ptrs[i]; ARRAYDAT* target = (ARRAYDAT*)external_ptrs[i]; int count = src->sizes[0]; int j; if (src->dimensions > 1) { for (j = 0; j < src->dimensions; j++) { count *= src->sizes[j]; } } for (j = 0; j < count; j++) { int memberOffset = j * (src->arrayMemberSize / sizeof(MYFLT)); MYFLT* in = src->data + memberOffset; MYFLT* out = target->data + memberOffset; memcpy(out + ofs, in, asigSize); } } current = current->next; } this_instr->spout += csound->nchnls*lksmps; this_instr->spin += csound->nchnls*lksmps; this_instr->kcounter++; } while ((ofs += this_instr->ksmps) < g_ksmps); } /* copy outputs */ current = inm->out_arg_pool->head; for (i = 0; i < inm->outchns; i++) { // this hardcoded type check for non-perf time vars needs to change // to use generic code... if (current->varType != &CS_VAR_TYPE_I && current->varType != &CS_VAR_TYPE_b && current->subType != &CS_VAR_TYPE_I) { void* in = (void*)internal_ptrs[i]; void* out = (void*)external_ptrs[i]; if (current->varType == &CS_VAR_TYPE_A) { /* clear the beginning portion of outputs for sample accurate end */ if (offset) { memset(out, '\0', sizeof(MYFLT) * offset); } /* clear the end portion of outputs for sample accurate end */ if (early) { memset((char*)out + g_ksmps, '\0', sizeof(MYFLT) * early); } } else if (current->varType == &CS_VAR_TYPE_ARRAY && current->subType == &CS_VAR_TYPE_A) { if (offset || early) { ARRAYDAT* outDat = (ARRAYDAT*)out; int count = outDat->sizes[0]; int j; if (outDat->dimensions > 1) { for (j = 0; j < outDat->dimensions; j++) { count *= outDat->sizes[j]; } } if (offset) { for (j = 0; j < count; j++) { int memberOffset = j * (outDat->arrayMemberSize / sizeof(MYFLT)); MYFLT* outMem = outDat->data + memberOffset; memset(outMem, '\0', sizeof(MYFLT) * offset); } } if (early) { for (j = 0; j < count; j++) { int memberOffset = j * (outDat->arrayMemberSize / sizeof(MYFLT)); MYFLT* outMem = outDat->data + memberOffset; memset(outMem + g_ksmps, '\0', sizeof(MYFLT) * early); } } } } else { current->varType->copyValue(csound, out, in); } } current = current->next; } CS_PDS = saved_pds; /* check if instrument was deactivated (e.g. by perferror) */ if (!p->ip) /* loop to last opds */ while (CS_PDS->nxtp) CS_PDS = CS_PDS->nxtp; return OK; } /* IV - Sep 17 2002 -- case 2: simplified routine for no local ksmps */ int useropcd2(CSOUND *csound, UOPCODE *p) { OPDS *saved_pds = CS_PDS; MYFLT **tmp; INSDS *this_instr = p->ip; OPCODINFO *inm; CS_VARIABLE* current; int i; p->ip->spin = p->parent_ip->spin; p->ip->spout = p->parent_ip->spout; if (UNLIKELY(!(CS_PDS = (OPDS*) (p->ip->nxtp)))) goto endop; /* no perf code */ /* IV - Nov 16 2002: update release flag */ p->ip->relesing = p->parent_ip->relesing; tmp = p->buf->iobufp_ptrs; inm = p->buf->opcode_info; MYFLT** internal_ptrs = tmp; MYFLT** external_ptrs = p->ar; /* copy inputs */ current = inm->in_arg_pool->head; for (i = 0; i < inm->inchns; i++) { // this hardcoded type check for non-perf time vars needs to //change to use generic code... if (current->varType != &CS_VAR_TYPE_I && current->varType != &CS_VAR_TYPE_b && current->subType != &CS_VAR_TYPE_I) { if (current->varType == &CS_VAR_TYPE_A && CS_KSMPS == 1) { *internal_ptrs[i + inm->outchns] = *external_ptrs[i + inm->outchns]; } else { void* in = (void*)external_ptrs[i + inm->outchns]; void* out = (void*)internal_ptrs[i + inm->outchns]; current->varType->copyValue(csound, out, in); // memcpy(out, in, p->buf->in_arg_sizes[i]); } } current = current->next; } /* run each opcode */ CS_PDS->insdshead->pds = NULL; do { (*CS_PDS->opadr)(csound, CS_PDS); if (CS_PDS->insdshead->pds != NULL && CS_PDS->insdshead->pds->insdshead) { CS_PDS = CS_PDS->insdshead->pds; CS_PDS->insdshead->pds = NULL; } } while ((CS_PDS = CS_PDS->nxtp)); this_instr->kcounter++; /* copy outputs */ current = inm->out_arg_pool->head; for (i = 0; i < inm->outchns; i++) { // this hardcoded type check for non-perf time vars needs to change to // use generic code... if (current->varType != &CS_VAR_TYPE_I && current->varType != &CS_VAR_TYPE_b && current->subType != &CS_VAR_TYPE_I) { if (current->varType == &CS_VAR_TYPE_A && CS_KSMPS == 1) { *external_ptrs[i] = *internal_ptrs[i]; } else { void* in = (void*)internal_ptrs[i]; void* out = (void*)external_ptrs[i]; // memcpy(out, in, p->buf->out_arg_sizes[i]); current->varType->copyValue(csound, out, in); } } current = current->next; } endop: /* restore globals */ CS_PDS = saved_pds; /* check if instrument was deactivated (e.g. by perferror) */ if (!p->ip) { /* loop to last opds */ while (CS_PDS->nxtp) { CS_PDS = CS_PDS->nxtp; } } return OK; } /* UTILITY FUNCTIONS FOR LABELS */ int findLabelMemOffset(CSOUND* csound, INSTRTXT* ip, char* labelName) { OPTXT* optxt = (OPTXT*) ip; int offset = 0; IGN(csound); while ((optxt = optxt->nxtop) != NULL) { TEXT* t = &optxt->t; if (strcmp(t->oentry->opname, "$label") == 0 && strcmp(t->opcod, labelName) == 0) { break; } offset += t->oentry->dsblksiz; } return offset; } /* create instance of an instr template */ /* allocates and sets up all pntrs */ static void instance(CSOUND *csound, int insno) { INSTRTXT *tp; INSDS *ip; OPTXT *optxt; OPDS *opds, *prvids, *prvpds; const OENTRY *ep; int i, n, pextent, pextra, pextrab; char *nxtopds, *opdslim; MYFLT **argpp, *lclbas; CS_VAR_MEM *lcloffbas; // start of pfields char* opMemStart; OPARMS *O = csound->oparms; int odebug = O->odebug; ARG* arg; int argStringCount; CS_VARIABLE* current; tp = csound->engineState.instrtxtp[insno]; n = 3; if (O->midiKey>n) n = O->midiKey; if (O->midiKeyCps>n) n = O->midiKeyCps; if (O->midiKeyOct>n) n = O->midiKeyOct; if (O->midiKeyPch>n) n = O->midiKeyPch; if (O->midiVelocity>n) n = O->midiVelocity; if (O->midiVelocityAmp>n) n = O->midiVelocityAmp; pextra = n-3; pextrab = ((i = tp->pmax - 3L) > 0 ? (int) i * sizeof(CS_VAR_MEM) : 0); /* alloc new space, */ pextent = sizeof(INSDS) + pextrab + pextra*sizeof(CS_VAR_MEM); ip = (INSDS*) csound->Calloc(csound, (size_t) pextent + tp->varPool->poolSize + (tp->varPool->varCount * CS_FLOAT_ALIGN(CS_VAR_TYPE_OFFSET)) + (tp->varPool->varCount * sizeof(CS_VARIABLE*)) + tp->opdstot); ip->csound = csound; ip->m_chnbp = (MCHNBLK*) NULL; ip->instr = tp; /* IV - Oct 26 2002: replaced with faster version (no search) */ ip->prvinstance = tp->lst_instance; if (tp->lst_instance) tp->lst_instance->nxtinstance = ip; else tp->instance = ip; tp->lst_instance = ip; /* link into free instance chain */ ip->nxtact = tp->act_instance; tp->act_instance = ip; ip->insno = insno; if (UNLIKELY(csound->oparms->odebug)) csoundMessage(csound,"instance(): tp->act_instance = %p \n", tp->act_instance); if (insno > csound->engineState.maxinsno) { // size_t pcnt = (size_t) tp->opcode_info->perf_incnt; // pcnt += (size_t) tp->opcode_info->perf_outcnt; OPCODINFO* info = tp->opcode_info; size_t pcnt = sizeof(OPCOD_IOBUFS) + sizeof(MYFLT*) * (info->inchns + info->outchns); ip->opcod_iobufs = (void*) csound->Malloc(csound, pcnt); } /* gbloffbas = csound->globalVarPool; */ lcloffbas = (CS_VAR_MEM*)&ip->p0; lclbas = (MYFLT*) ((char*) ip + pextent); /* split local space */ initializeVarPool((void *)csound, lclbas, tp->varPool); opMemStart = nxtopds = (char*) lclbas + tp->varPool->poolSize + (tp->varPool->varCount * CS_FLOAT_ALIGN(CS_VAR_TYPE_OFFSET)); opdslim = nxtopds + tp->opdstot; if (UNLIKELY(odebug)) csound->Message(csound, Str("instr %d allocated at %p\n\tlclbas %p, opds %p\n"), insno, ip, lclbas, nxtopds); optxt = (OPTXT*) tp; prvids = prvpds = (OPDS*) ip; // prvids->insdshead = ip; /* initialize vars for CS_TYPE */ for (current = tp->varPool->head; current != NULL; current = current->next) { char* ptr = (char*)(lclbas + current->memBlockIndex); CS_TYPE** typePtr = (CS_TYPE**)(ptr - CS_VAR_TYPE_OFFSET); *typePtr = current->varType; } while ((optxt = optxt->nxtop) != NULL) { /* for each op in instr */ TEXT *ttp = &optxt->t; ep = ttp->oentry; opds = (OPDS*) nxtopds; /* take reqd opds */ nxtopds += ep->dsblksiz; if (UNLIKELY(strcmp(ep->opname, "endin") == 0 /* (until ENDIN) */ || strcmp(ep->opname, "endop") == 0)) /* (or ENDOP) */ break; if (UNLIKELY(strcmp(ep->opname, "pset") == 0)) { ip->p1.value = (MYFLT) insno; continue; } if (UNLIKELY(odebug)) csound->Message(csound, Str("op (%s) allocated at %p\n"), ep->opname, opds); opds->optext = optxt; /* set common headata */ opds->insdshead = ip; if (strcmp(ep->opname, "$label") == 0) { /* LABEL: */ LBLBLK *lblbp = (LBLBLK *) opds; lblbp->prvi = prvids; /* save i/p links */ lblbp->prvp = prvpds; continue; /* for later refs */ } if ((ep->thread & 07) == 0) { /* thread 1 OR 2: */ if (ttp->pftype == 'b') { prvids = prvids->nxti = opds; opds->iopadr = ep->iopadr; } else { prvpds = prvpds->nxtp = opds; opds->opadr = ep->kopadr; } goto args; } if ((ep->thread & 01) != 0) { /* thread 1: */ prvids = prvids->nxti = opds; /* link into ichain */ opds->iopadr = ep->iopadr; /* & set exec adr */ if (UNLIKELY(opds->iopadr == NULL)) csoundDie(csound, Str("null iopadr")); } if ((n = ep->thread & 06) != 0) { /* thread 2 OR 4: */ prvpds = prvpds->nxtp = opds; /* link into pchain */ if (!(n & 04) || ((ttp->pftype == 'k' || ttp->pftype == 'c') && ep->kopadr != NULL)) opds->opadr = ep->kopadr; /* krate or */ else opds->opadr = ep->aopadr; /* arate */ if (UNLIKELY(odebug)) csound->Message(csound, "opadr = %p\n", (void*) opds->opadr); if (UNLIKELY(opds->opadr == NULL)) csoundDie(csound, Str("null opadr")); } args: if (ep->useropinfo == NULL) argpp = (MYFLT **) ((char *) opds + sizeof(OPDS)); else /* user defined opcodes are a special case */ argpp = &(((UOPCODE *) ((char *) opds))->ar[0]); arg = ttp->outArgs; for (n = 0; arg != NULL; n++) { MYFLT *fltp; CS_VARIABLE* var = (CS_VARIABLE*)arg->argPtr; if (arg->type == ARG_GLOBAL) { fltp = &(var->memBlock->value); /* gbloffbas + var->memBlockIndex; */ } else if (arg->type == ARG_LOCAL) { fltp = lclbas + var->memBlockIndex; } else if (arg->type == ARG_PFIELD) { CS_VAR_MEM* pfield = lcloffbas + arg->index; fltp = &(pfield->value); } else { csound->Message(csound, Str("FIXME: Unhandled out-arg type: %d\n"), arg->type); fltp = NULL; } argpp[n] = fltp; arg = arg->next; } for (argStringCount = argsRequired(ep->outypes); n < argStringCount; n++) /* if more outypes, pad */ argpp[n] = NULL; arg = ttp->inArgs; ip->lclbas = lclbas; for (; arg != NULL; n++, arg = arg->next) { CS_VARIABLE* var = (CS_VARIABLE*)(arg->argPtr); if (arg->type == ARG_CONSTANT) { CS_VAR_MEM *varMem = (CS_VAR_MEM*)arg->argPtr; argpp[n] = &varMem->value; } else if (arg->type == ARG_STRING) { argpp[n] = (MYFLT*)(arg->argPtr); } else if (arg->type == ARG_PFIELD) { CS_VAR_MEM* pfield = lcloffbas + arg->index; argpp[n] = &(pfield->value); } else if (arg->type == ARG_GLOBAL) { argpp[n] = &(var->memBlock->value); /*gbloffbas + var->memBlockIndex; */ } else if (arg->type == ARG_LOCAL){ argpp[n] = lclbas + var->memBlockIndex; } else if (arg->type == ARG_LABEL) { argpp[n] = (MYFLT*)(opMemStart + findLabelMemOffset(csound, tp, (char*)arg->argPtr)); } else { csound->Message(csound, Str("FIXME: instance unexpected arg: %d\n"), arg->type); } } } /* VL 13-12-13: point the memory to the local ksmps & kr variables, and initialise them */ CS_VARIABLE* var = csoundFindVariableWithName(csound, ip->instr->varPool, "ksmps"); if (var) { char* temp = (char*)(lclbas + var->memBlockIndex); var->memBlock = (CS_VAR_MEM*)(temp - CS_VAR_TYPE_OFFSET); var->memBlock->value = csound->ksmps; } var = csoundFindVariableWithName(csound, ip->instr->varPool, "kr"); if (var) { char* temp = (char*)(lclbas + var->memBlockIndex); var->memBlock = (CS_VAR_MEM*)(temp - CS_VAR_TYPE_OFFSET); var->memBlock->value = csound->ekr; } if (UNLIKELY(nxtopds > opdslim)) csoundDie(csound, Str("inconsistent opds total")); } int prealloc_(CSOUND *csound, AOP *p, int instname) { int n, a; if (instname) n = (int) strarg2opcno(csound, ((STRINGDAT*)p->r)->data, 1, (*p->b == FL(0.0) ? 0 : 1)); else { if (csound->ISSTRCOD(*p->r)) n = (int) strarg2opcno(csound, get_arg_string(csound,*p->r), 1, (*p->b == FL(0.0) ? 0 : 1)); else n = *p->r; } if (UNLIKELY(n < 1)) return NOTOK; a = (int) *p->a - csound->engineState.instrtxtp[n]->active; for ( ; a > 0; a--) instance(csound, n); return OK; } int prealloc(CSOUND *csound, AOP *p){ return prealloc_(csound,p,0); } int prealloc_S(CSOUND *csound, AOP *p){ return prealloc_(csound,p,1); } int delete_instr(CSOUND *csound, DELETEIN *p) { int n; INSTRTXT *ip; INSDS *active; INSTRTXT *txtp; if (IS_STR_ARG(p->insno)) n = csound->strarg2insno(csound, ((STRINGDAT *)p->insno)->data, 1); else n = (int) (*p->insno + FL(0.5)); if (UNLIKELY(n < 1 || n > csound->engineState.maxinsno || csound->engineState.instrtxtp[n] == NULL)) return OK; /* Instrument does not exist so noop */ ip = csound->engineState.instrtxtp[n]; active = ip->instance; while (active != NULL) { /* Check there are no active instances */ INSDS *nxt = active->nxtinstance; if (UNLIKELY(active->actflg)) { /* Can only remove non-active instruments */ char *name = csound->engineState.instrtxtp[n]->insname; if (name) return csound->InitError(csound, Str("Instrument %s is still active"), name); else return csound->InitError(csound, Str("Instrument %d is still active"), n); } #if 0 if (active->opcod_iobufs && active->insno > csound->engineState.maxinsno) csound->Free(csound, active->opcod_iobufs); /* IV - Nov 10 2002 */ #endif if (active->fdchp != NULL) fdchclose(csound, active); if (active->auxchp != NULL) auxchfree(csound, active); free_instr_var_memory(csound, active); csound->Free(csound, active); active = nxt; } csound->engineState.instrtxtp[n] = NULL; /* Now patch it out */ for (txtp = &(csound->engineState.instxtanchor); txtp != NULL; txtp = txtp->nxtinstxt) if (txtp->nxtinstxt == ip) { OPTXT *t = ip->nxtop; txtp->nxtinstxt = ip->nxtinstxt; while (t) { OPTXT *s = t->nxtop; csound->Free(csound, t); t = s; } csound->Free(csound, ip); return OK; } return NOTOK; } void killInstance_enqueue(CSOUND *csound, MYFLT instr, int insno, INSDS *ip, int mode, int allow_release); void killInstance(CSOUND *csound, MYFLT instr, int insno, INSDS *ip, int mode, int allow_release) { INSDS *ip2 = NULL, *nip; do { /* This loop does not terminate in mode=0 */ nip = ip->nxtact; if (((mode & 8) && ip->offtim >= 0.0) || ((mode & 4) && ip->p1.value != instr) || (allow_release && ip->relesing)) { ip = nip; continue; } if (!(mode & 3)) { if (allow_release) { xturnoff(csound, ip); } else { nip = ip->nxtact; xturnoff_now(csound, ip); } } else { ip2 = ip; if ((mode & 3) == 1) break; } ip = nip; } while (ip != NULL && (int) ip->insno == insno); if (ip2 != NULL) { if (allow_release) { xturnoff(csound, ip2); } else { xturnoff_now(csound, ip2); } } } int csoundKillInstanceInternal(CSOUND *csound, MYFLT instr, char *instrName, int mode, int allow_release, int async) { INSDS *ip; int insno; if (instrName) { insno = named_instr_find(csound, instrName); instr = (MYFLT) insno; } else insno = instr; if (UNLIKELY(insno < 1 || insno > (int) csound->engineState.maxinsno || csound->engineState.instrtxtp[insno] == NULL)) { return CSOUND_ERROR; } if (UNLIKELY(mode < 0 || mode > 15 || (mode & 3) == 3)) { csoundUnlockMutex(csound->API_lock); return CSOUND_ERROR; } ip = &(csound->actanchor); while ((ip = ip->nxtact) != NULL && (int) ip->insno != insno); if (UNLIKELY(ip == NULL)) { return CSOUND_ERROR; } if (async) { csoundLockMutex(csound->API_lock); killInstance(csound, instr, insno, ip, mode, allow_release); csoundUnlockMutex(csound->API_lock); } else killInstance_enqueue(csound, instr, insno, ip, mode, allow_release); return CSOUND_SUCCESS; } /** In realtime mode, this function takes care of the init pass in a separate thread. Any new instances will have their init-pass code executed here. This thread is started by musmon() and killed by csoundCleanup() */ void *init_pass_thread(void *p){ CSOUND *csound = (CSOUND *) p; INSDS *ip; int done; float wakeup = (1000*csound->ksmps/csound->esr); _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); while (csound->init_pass_loop) { #if defined(MACOSX) || defined(LINUX) || defined(HAIKU) usleep(10*wakeup); #else csoundSleep(((int)wakeup > 0) ? wakeup : 1); #endif ip = csound->actanchor.nxtact; /* do init pass for this instr */ csoundLockMutex(csound->init_pass_threadlock); while (ip != NULL){ INSDS *nxt = ip->nxtact; #ifdef HAVE_ATOMIC_BUILTIN done = __sync_fetch_and_add((int *) &ip->init_done, 0); #else done = ip->init_done; #endif if (done == 0) { csound->ids = (OPDS *) (ip->nxti); csound->curip = ip; while (csound->ids != NULL) { if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, "init %s:\n", csound->ids->optext->t.oentry->opname); (*csound->ids->iopadr)(csound, csound->ids); csound->ids = csound->ids->nxti; } ip->tieflag = 0; #ifdef HAVE_ATOMIC_BUILTIN __sync_lock_test_and_set((int*)&ip->init_done,1); #else ip->init_done = 1; #endif if (ip->reinitflag==1) { ip->reinitflag = 0; } } ip = nxt; } csoundUnlockMutex(csound->init_pass_threadlock); } return NULL; } csound-6.10.0/Engine/linevent.c000066400000000000000000000477361321653344700163170ustar00rootroot00000000000000/* linevent.c: Copyright (C) 1991 Barry Vercoe, John ffitch, matt ingalls This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* LINEVENT.C */ #include #ifdef MSVC #include #endif #include "linevent.h" #ifdef PIPES # if defined(SGI) || defined(LINUX) || defined(NeXT) || defined(__MACH__) # define _popen popen # define _pclose pclose # elif defined(__BEOS__) || defined(__MACH__) # include # define _popen popen # define _pclose pclose # else FILE *_popen(const char *, const char *); # endif #endif #define LBUFSIZ1 32768 #define LF '\n' /* typedef struct { */ /* char *Linep, *Linebufend; */ /* FILE *Linecons; */ /* int stdmode; */ /* EVTBLK prve; */ /* char Linebuf[LBUFSIZ]; */ /* } LINEVENT_GLOBALS; */ static void sensLine(CSOUND *csound, void *userData); #define STA(x) (csound->lineventStatics.x) #define MAXSTR 1048576 /* 1MB */ void RTLineset(CSOUND *csound) /* set up Linebuf & ready the input files */ { /* callable once from musmon.c */ OPARMS *O = csound->oparms; /* csound->lineventGlobals = (LINEVENT_GLOBALS*) */ /* csound->Calloc(csound, */ /* sizeof(LINEVENT_GLOBALS)); */ STA(linebufsiz) = LBUFSIZ1; STA(Linebuf) = (char *) csound->Calloc(csound, STA(linebufsiz)); STA(orchestrab) = (char *) csound->Calloc(csound, MAXSTR); STA(orchestra) = STA(orchestrab); STA(prve).opcod = ' '; STA(Linebufend) = STA(Linebuf) + STA(linebufsiz); STA(Linep) = STA(Linebuf); if (strcmp(O->Linename, "stdin") == 0) { #if defined(DOSGCC) || defined(WIN32) setvbuf(stdin, NULL, _IONBF, 0); /* WARNING("-L stdin: system has no fcntl function to get stdin"); */ #else STA(stdmode) = fcntl(csound->Linefd, F_GETFL, 0); if (UNLIKELY(fcntl(csound->Linefd, F_SETFL, STA(stdmode) | O_NDELAY) < 0)) csoundDie(csound, Str("-L stdin fcntl failed")); #endif } #ifdef PIPES else if (UNLIKELY(O->Linename[0] == '|')) { csound->Linepipe = _popen(&(O->Linename[1]), "r"); if (LIKELY(csound->Linepipe != NULL)) { csound->Linefd = fileno(csound->Linepipe); setvbuf(csound->Linepipe, NULL, _IONBF, 0); } else csoundDie(csound, Str("Cannot open %s"), O->Linename); } #endif #define MODE ,0 else if (UNLIKELY((csound->Linefd=open(O->Linename, O_RDONLY|O_NDELAY MODE)) < 0)) csoundDie(csound, Str("Cannot open %s"), O->Linename); if(csound->oparms->odebug) csound->Message(csound, Str("stdmode = %.8x Linefd = %d\n"), STA(stdmode), csound->Linefd); csound->RegisterSenseEventCallback(csound, sensLine, NULL); } #ifdef PIPES int _pclose(FILE*); #endif void RTclose(CSOUND *csound) { if (csound->oparms->Linein == 0) return; csound->oparms->Linein = 0; if(csound->oparms->odebug) csound->Message(csound, Str("stdmode = %.8x Linefd = %d\n"), STA(stdmode), csound->Linefd); #ifdef PIPES if (csound->oparms->Linename[0] == '|') _pclose(csound->Linepipe); else #endif { if (strcmp(csound->oparms->Linename, "stdin") != 0) close(csound->Linefd); #if !defined(DOSGCC) && !defined(WIN32) else if (UNLIKELY(fcntl(csound->Linefd, F_SETFL, STA(stdmode)))) csoundDie(csound, Str("Failed to set file status\n")); #endif } //csound->Free(csound, csound->lineventGlobals); //csound->lineventGlobals = NULL; } /* does string segment contain LF? */ static inline int containsLF(char *cp, char *endp) { while (cp < endp) { if (UNLIKELY(*cp++ == LF)) return 1; } return 0; } static CS_NOINLINE int linevent_alloc(CSOUND *csound, int reallocsize) { volatile jmp_buf tmpExitJmp; int err; unsigned int tmp; if (reallocsize > 0) { /* VL 20-11-17 need to record the STA(Linep) offset in relation to STA(Linebuf) */ tmp = (STA(Linep) - STA(Linebuf)); STA(Linebuf) = (char *) csound->ReAlloc(csound, (void *) STA(Linebuf), reallocsize); STA(linebufsiz) = reallocsize; STA(Linebufend) = STA(Linebuf) + STA(linebufsiz); /* VL 20-11-17 so we can place it in the correct position after reallocation */ STA(Linep) = STA(Linebuf) + tmp; } else if (STA(Linebuf)==NULL) { STA(linebufsiz) = LBUFSIZ1; STA(Linebuf) = (char *) csound->Calloc(csound, STA(linebufsiz)); } if (STA(Linebuf) == NULL) { return 1; } //csound->Message(csound, "1. realloc: %d\n", reallocsize); if (STA(Linep)) return 0; csound->Linefd = -1; memcpy((void*) &tmpExitJmp, (void*) &csound->exitjmp, sizeof(jmp_buf)); if ((err = setjmp(csound->exitjmp)) != 0) { memcpy((void*) &csound->exitjmp, (void*) &tmpExitJmp, sizeof(jmp_buf)); //csound->lineventGlobals = NULL; return -1; } memcpy((void*) &csound->exitjmp, (void*) &tmpExitJmp, sizeof(jmp_buf)); STA(prve).opcod = ' '; STA(Linebufend) = STA(Linebuf) + STA(linebufsiz); STA(Linep) = STA(Linebuf); csound->RegisterSenseEventCallback(csound, sensLine, NULL); return 0; } /* insert text from an external source, to be interpreted as if coming in from stdin/Linefd for -L */ void csoundInputMessageInternal(CSOUND *csound, const char *message) { int32 size = (int32) strlen(message); int n; if ((n=linevent_alloc(csound, 0)) != 0) return; if (!size) return; if (UNLIKELY((STA(Linep) + size) >= STA(Linebufend))) { int extralloc = STA(Linep) + size - STA(Linebufend); csound->Message(csound, "realloc %d\n", extralloc); // csound->Message(csound, "extralloc: %d %d %d\n", // extralloc, size, (int)(STA(Linebufend) - STA(Linep))); // FIXME -- Coverity points out that this test is always false // and n is never used #if 0 if ((n=linevent_alloc(csound, (STA(linebufsiz) + extralloc))) != 0) { csoundErrorMsg(csound, Str("LineBuffer Overflow - " "Input Data has been Lost")); return; } #else n = linevent_alloc(csound, (STA(linebufsiz) + extralloc)); #endif } //csound->Message(csound, "%u = %u\n", (STA(Linep) + size), STA(Linebufend) ); memcpy(STA(Linep), message, size); if (STA(Linep)[size - 1] != (char) '\n') STA(Linep)[size++] = (char) '\n'; STA(Linep) += size; } /* accumlate RT Linein buffer, & place completed events in EVTBLK */ /* does more syntax checking than rdscor, since not preprocessed */ static void sensLine(CSOUND *csound, void *userData) { char *cp, *Linestart, *Linend; int c, cm1, cpp1, n, pcnt, oflag = STA(oflag); IGN(userData); while (1) { if(STA(oflag) > oflag) break; Linend = STA(Linep); if (csound->Linefd >= 0) { n = read(csound->Linefd, Linend, STA(Linebufend) - Linend); Linend += (n > 0 ? n : 0); } if (Linend <= STA(Linebuf)) break; Linestart = STA(Linebuf); cp = Linestart; while (containsLF(Linestart, Linend)) { EVTBLK e; char *sstrp = NULL; int scnt = 0; int strsiz = 0; memset(&e, 0, sizeof(EVTBLK)); e.strarg = NULL; e.scnt = 0; c = *cp; while (isblank(c)) /* skip initial white space */ c = *(++cp); if (c == LF) { /* if null line, bugout */ Linestart = (++cp); continue; } cm1 = *(cp-1); cpp1 = *(cp+1); /* new orchestra input */ if(STA(oflag)) { if(c == '}' && cm1 != '}' && cpp1 != '}') { STA(oflag) = 0; STA(orchestra) = STA(orchestrab); csoundCompileOrc(csound, STA(orchestrab)); csound->Message(csound, "::compiling orchestra::\n"); Linestart = (++cp); continue; } else { char *pc; memcpy(STA(orchestra), Linestart, Linend - Linestart); STA(orchestra) += (Linend - Linestart); *STA(orchestra) = '\0'; STA(oflag)++; if((pc = strrchr(STA(orchestrab), '}')) != NULL) { if(*(pc-1) != '}') { *pc = '\0'; cp = strrchr(Linestart, '}'); } else { Linestart = Linend; } } else { Linestart = Linend; } continue; } } else if(c == '{') { STA(oflag) = 1; csound->Message(csound, "::reading orchestra, use '}' to terminate::\n"); cp++; continue; } switch (c) { /* look for legal opcode */ case 'e': /* Quit realtime */ case 'i': case 'q': case 'f': case 'a': e.opcod = c; break; default: csound->ErrorMsg(csound, Str("unknown opcode %c"), c); goto Lerr; } /* for params that follow: */ pcnt = 0; do { char *newcp; do { /* skip white space */ c = *(++cp); } while (isblank(c)); if (c == LF) break; pcnt++; if (c == '"') { /* if find character string */ if (e.strarg == NULL) e.strarg = csound->Malloc(csound, strsiz=SSTRSIZ); sstrp = e.strarg; n = scnt; while (n-->0) sstrp += strlen(sstrp)+1; n = 0; while ((c = *(++cp)) != '"') { /* VL: allow strings to be multi-line */ // if (UNLIKELY(c == LF)) { // csound->ErrorMsg(csound, Str("unmatched quotes")); // goto Lerr; //} if(c == '\\') { cp++; c = *cp;} sstrp[n++] = c; /* save in private strbuf */ if (UNLIKELY((sstrp-e.strarg)+n >= strsiz-10)) { e.strarg = csound->ReAlloc(csound, e.strarg, strsiz+=SSTRSIZ); sstrp = e.strarg+n; } } sstrp[n] = '\0'; { union { MYFLT d; int32 i; } ch; ch.d = SSTRCOD; ch.i += scnt++; e.p[pcnt] = ch.d; /* set as string with count */ } e.scnt = scnt; //printf("string: %s \n", sstrp); continue; } if (UNLIKELY(!(isdigit(c) || c == '+' || c == '-' || c == '.'))) goto Lerr; if (c == '.' && /* if lone dot, */ (isblank(n = cp[1]) || n == LF)) { if (UNLIKELY(e.opcod != 'i' || STA(prve).opcod != 'i' || pcnt > STA(prve).pcnt)) { csound->ErrorMsg(csound, Str("dot carry has no reference")); goto Lerr; } /* pfld carry */ e.p[pcnt] = STA(prve).p[pcnt]; if (UNLIKELY(csound->ISSTRCOD(e.p[pcnt]))) { csound->ErrorMsg(csound, Str("cannot carry string p-field")); goto Lerr; } continue; } e.p[pcnt] = (MYFLT) cs_strtod(cp, &newcp); cp = newcp - 1; } while (pcnt < PMAX); if (e.opcod =='f' && e.p[1]ErrorMsg(csound, Str("too few pfields (%d)"), pcnt + 1); goto Lerr; } if (UNLIKELY(pcnt > 1 && e.p[2] < FL(0.0))) { csound->ErrorMsg(csound, Str("-L with negative p2 illegal")); goto Lerr; } e.pcnt = pcnt; /* & record pfld count */ if (e.opcod == 'i') { /* do carries for instr data */ memcpy((void*) &STA(prve), (void*) &e, (size_t) ((char*) &(e.p[pcnt + 1]) - (char*) &e)); /* FIXME: how to carry string args ? */ STA(prve).strarg = NULL; } if (UNLIKELY(pcnt >= PMAX && c != LF)) { csound->ErrorMsg(csound, Str("too many pfields")); while (*(++cp) != LF) /* flush any excess data */ ; } Linestart = (++cp); insert_score_event_at_sample(csound, &e, csound->icurTime); continue; Lerr: n = cp - Linestart; /* error position */ while (*cp != LF) cp++; /* go on to LF */ *cp = '\0'; /* & insert NULL */ csound->ErrorMsg(csound, Str("illegal RT scoreline:\n%s\n%*s"), Linestart, n + 1, "^"); /* mark the error */ Linestart = (++cp); } if (Linestart != &(STA(Linebuf)[0])) { int len = (int) (Linend - Linestart); /* move any remaining characters to the beginning of the buffer */ for (n = 0; n < len; n++) STA(Linebuf)[n] = Linestart[n]; n = (int) (Linestart - &(STA(Linebuf)[0])); STA(Linep) -= n; Linend -= n; } if (Linend == STA(Linep)) /* return if no more data is available */ break; STA(Linep) = Linend; /* accum the chars */ } } /* send a lineevent from the orchestra -matt 2001/12/07 */ static const char *errmsg_1 = Str_noop("event: param 1 must be \"a\", \"i\", \"q\", \"f\", \"d\", or \"e\""); static const char *errmsg_2 = Str_noop("event: string name is allowed only for \"i\", \"d\", and \"q\" events"); int eventOpcode_(CSOUND *csound, LINEVENT *p, int insname, char p1) { EVTBLK evt; int i; char opcod; memset(&evt, 0, sizeof(EVTBLK)); if (p1==0) opcod = *((STRINGDAT*) p->args[0])->data; else opcod = p1; if (UNLIKELY((opcod != 'a' && opcod != 'i' && opcod != 'q' && opcod != 'f' && opcod != 'e' && opcod != 'd') /*|| ((STRINGDAT*) p->args[0])->data[1] != '\0'*/)) return csound->PerfError(csound, p->h.insdshead, "%s", Str(errmsg_1)); evt.strarg = NULL; evt.scnt = 0; evt.opcod = opcod; if (p->flag==1) evt.pcnt = p->argno-2; else evt.pcnt = p->INOCOUNT - 1; /* IV - Oct 31 2002: allow string argument */ if (evt.pcnt > 0) { if (insname) { if (UNLIKELY(evt.opcod != 'i' && evt.opcod != 'q' && opcod != 'd')) return csound->PerfError(csound, p->h.insdshead, "%s", Str(errmsg_2)); evt.p[1] = csound->strarg2insno(csound, ((STRINGDAT*) p->args[1])->data, 1); evt.strarg = NULL; evt.scnt = 0; } else { if (csound->ISSTRCOD(*p->args[1])) { evt.p[1] = csound->strarg2insno(csound, get_arg_string(csound, *p->args[1]), 1); } else evt.p[1] = *p->args[1]; evt.strarg = NULL; evt.scnt = 0; } for (i = 2; i <= evt.pcnt; i++) evt.p[i] = *p->args[i]; } if(opcod == 'd') { evt.opcod = 'i'; evt.p[1] *= -1; } if (UNLIKELY(insert_score_event_at_sample(csound, &evt, csound->icurTime) != 0)) return csound->PerfError(csound, p->h.insdshead, Str("event: error creating '%c' event"), opcod); return OK; } int eventOpcode(CSOUND *csound, LINEVENT *p) { return eventOpcode_(csound, p, 0, 0); } int eventOpcode_S(CSOUND *csound, LINEVENT *p) { return eventOpcode_(csound, p, 1, 0); } /* i-time version of event opcode */ int eventOpcodeI_(CSOUND *csound, LINEVENT *p, int insname, char p1) { EVTBLK evt; int i, err = 0; char opcod; memset(&evt, 0, sizeof(EVTBLK)); if (p1==0) opcod = *((STRINGDAT*) p->args[0])->data; else opcod = p1; if (UNLIKELY((opcod != 'a' && opcod != 'i' && opcod != 'q' && opcod != 'f' && opcod != 'e' && opcod != 'd') /*|| ((STRINGDAT*) p->args[0])->data[1] != '\0'*/)) return csound->InitError(csound, "%s", Str(errmsg_1)); evt.strarg = NULL; evt.scnt = 0; evt.opcod = opcod; if (p->flag==1) evt.pcnt = p->argno-1; else evt.pcnt = p->INOCOUNT - 1; /* IV - Oct 31 2002: allow string argument */ if (evt.pcnt > 0) { if (insname) { if (UNLIKELY(evt.opcod != 'i' && evt.opcod != 'q' && opcod != 'd')) return csound->InitError(csound, "%s", Str(errmsg_2)); evt.p[1] = csound->strarg2insno(csound,((STRINGDAT *)p->args[1])->data, 1); evt.strarg = NULL; evt.scnt = 0; for (i = 2; i <= evt.pcnt; i++) evt.p[i] = *p->args[i]; } else { evt.strarg = NULL; evt.scnt = 0; if (csound->ISSTRCOD(*p->args[1])) { evt.p[1] = csound->strarg2insno(csound, get_arg_string(csound, *p->args[1]), 1); } else evt.p[1] = *p->args[1]; for (i = 2; i <= evt.pcnt; i++) evt.p[i] = *p->args[i]; } } if(opcod == 'd') { evt.opcod = 'i'; evt.p[1] *= -1; } if (opcod == 'f' && (int) evt.pcnt >= 2 && evt.p[2] <= FL(0.0)) { FUNC *dummyftp; err = csound->hfgens(csound, &dummyftp, &evt, 0); } else err = insert_score_event_at_sample(csound, &evt, csound->icurTime); if (UNLIKELY(err)) csound->InitError(csound, Str("event_i: error creating '%c' event"), opcod); return (err == 0 ? OK : NOTOK); } int eventOpcodeI(CSOUND *csound, LINEVENT *p) { return eventOpcodeI_(csound, p, 0, 0); } int eventOpcodeI_S(CSOUND *csound, LINEVENT *p) { return eventOpcodeI_(csound, p, 1, 0); } int instanceOpcode_(CSOUND *csound, LINEVENT2 *p, int insname) { EVTBLK evt; int i; evt.strarg = NULL; evt.scnt = 0; evt.opcod = 'i'; evt.pcnt = p->INOCOUNT; /* pass in the memory to hold the instance after insertion */ evt.pinstance = (void *) p->inst; /* IV - Oct 31 2002: allow string argument */ if (evt.pcnt > 0) { if (insname) { evt.p[1] = csound->strarg2insno(csound, ((STRINGDAT*) p->args[0])->data, 1); evt.strarg = NULL; evt.scnt = 0; } else { if (csound->ISSTRCOD(*p->args[0])) { evt.p[1] = csound->strarg2insno(csound, get_arg_string(csound, *p->args[0]), 1); } else evt.p[1] = *p->args[0]; evt.strarg = NULL; evt.scnt = 0; } for (i = 2; i <= evt.pcnt; i++) evt.p[i] = *p->args[i-1]; } if (insert_score_event_at_sample(csound, &evt, csound->icurTime) != 0) return csound->PerfError(csound, p->h.insdshead, Str("instance: error creating event")); return OK; } int instanceOpcode(CSOUND *csound, LINEVENT2 *p) { return instanceOpcode_(csound, p, 0); } int instanceOpcode_S(CSOUND *csound, LINEVENT2 *p) { return instanceOpcode_(csound, p, 1); } csound-6.10.0/Engine/memalloc.c000066400000000000000000000170521321653344700162500ustar00rootroot00000000000000/* memalloc.c: Copyright (C) 1991 Barry Vercoe, John ffitch, Richard Dobson, (C) 2005 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* MEMALLOC.C */ /* This code wraps malloc etc with maintaining a list of allocated memory so it can be freed on a reset. It would not be necessary with a zoned allocator. */ #if defined(BETA) && !defined(MEMDEBUG) #define MEMDEBUG 1 #endif #define MEMALLOC_MAGIC 0x6D426C6B /* The memory list must be controlled by mutex */ #define CSOUND_MEM_SPINLOCK csoundSpinLock(&csound->memlock); #define CSOUND_MEM_SPINUNLOCK csoundSpinUnLock(&csound->memlock); typedef struct memAllocBlock_s { #ifdef MEMDEBUG int magic; /* 0x6D426C6B ("mBlk") */ void *ptr; /* pointer to allocated area */ #endif struct memAllocBlock_s *prv; /* previous structure in chain */ struct memAllocBlock_s *nxt; /* next structure in chain */ } memAllocBlock_t; #define HDR_SIZE (((int) sizeof(memAllocBlock_t) + 7) & (~7)) #define ALLOC_BYTES(n) ((size_t) HDR_SIZE + (size_t) (n)) #define DATA_PTR(p) ((void*) ((unsigned char*) (p) + (int) HDR_SIZE)) #define HDR_PTR(p) ((memAllocBlock_t*) ((unsigned char*) (p) - (int) HDR_SIZE)) #define MEMALLOC_DB (csound->memalloc_db) static void memdie(CSOUND *csound, size_t nbytes) { csound->ErrorMsg(csound, Str("memory allocate failure for %zu"), nbytes); csound->LongJmp(csound, CSOUND_MEMORY); } void *mmalloc(CSOUND *csound, size_t size) { void *p; #ifdef MEMDEBUG if (UNLIKELY(size == (size_t) 0)) { csound->DebugMsg(csound, " *** internal error: mmalloc() called with zero nbytes\n"); return NULL; } #endif /* allocate memory */ if (UNLIKELY((p = malloc(ALLOC_BYTES(size))) == NULL)) { memdie(csound, size); /* does a long jump */ } /* link into chain */ #ifdef MEMDEBUG ((memAllocBlock_t*) p)->magic = MEMALLOC_MAGIC; ((memAllocBlock_t*) p)->ptr = DATA_PTR(p); #endif CSOUND_MEM_SPINLOCK ((memAllocBlock_t*) p)->prv = (memAllocBlock_t*) NULL; ((memAllocBlock_t*) p)->nxt = (memAllocBlock_t*) MEMALLOC_DB; if (MEMALLOC_DB != NULL) ((memAllocBlock_t*) MEMALLOC_DB)->prv = (memAllocBlock_t*) p; MEMALLOC_DB = (void*) p; CSOUND_MEM_SPINUNLOCK /* return with data pointer */ return DATA_PTR(p); } void *mmallocDebug(CSOUND *csound, size_t size, char *file, int line) { void *ans = mmalloc(csound,size); printf("Alloc %p (%zu) %s:%d\n", ans, size, file, line); return ans; } void *mcalloc(CSOUND *csound, size_t size) { void *p; #ifdef MEMDEBUG if (UNLIKELY(size == (size_t) 0)) { csound->DebugMsg(csound, " *** internal error: csound->Calloc() called with zero nbytes\n"); return NULL; } #endif /* allocate memory */ if (UNLIKELY((p = calloc(ALLOC_BYTES(size), (size_t) 1)) == NULL)) { memdie(csound, size); /* does longjump */ } /* link into chain */ #ifdef MEMDEBUG ((memAllocBlock_t*) p)->magic = MEMALLOC_MAGIC; ((memAllocBlock_t*) p)->ptr = DATA_PTR(p); #endif CSOUND_MEM_SPINLOCK ((memAllocBlock_t*) p)->prv = (memAllocBlock_t*) NULL; ((memAllocBlock_t*) p)->nxt = (memAllocBlock_t*) MEMALLOC_DB; if (MEMALLOC_DB != NULL) ((memAllocBlock_t*) MEMALLOC_DB)->prv = (memAllocBlock_t*) p; MEMALLOC_DB = (void*) p; CSOUND_MEM_SPINUNLOCK /* return with data pointer */ return DATA_PTR(p); } void *mcallocDebug(CSOUND *csound, size_t size, char *file, int line) { void *ans = mcalloc(csound,size); printf("Alloc %p (%zu) %s:%d\n", ans, size, file, line); return ans; } void mfree(CSOUND *csound, void *p) { memAllocBlock_t *pp; if (UNLIKELY(p == NULL)) return; pp = HDR_PTR(p); #ifdef MEMDEBUG if (UNLIKELY(pp->magic != MEMALLOC_MAGIC || pp->ptr != p)) { csound->Warning(csound, "csound->Free() called with invalid " "pointer (%p) %x %p %x", p, pp->magic, pp->ptr, MEMALLOC_MAGIC); /* exit() is ugly, but this is a fatal error that can only occur */ /* as a result of a bug */ /* exit(-1); */ /*VL 28-12-12 - returning from here instead of exit() */ return; } pp->magic = 0; #endif CSOUND_MEM_SPINLOCK /* unlink from chain */ { memAllocBlock_t *prv = pp->prv, *nxt = pp->nxt; if (nxt != NULL) nxt->prv = prv; if (prv != NULL) prv->nxt = nxt; else MEMALLOC_DB = (void*)nxt; } //csound->Message(csound, "free\n"); /* free memory */ free((void*) pp); CSOUND_MEM_SPINUNLOCK } void mfreeDebug(CSOUND *csound, void *ans, char *file, int line) { printf("Free %p %s:%d\n", ans, file, line); mfree(csound,ans); } void *mrealloc(CSOUND *csound, void *oldp, size_t size) { memAllocBlock_t *pp; void *p; if (UNLIKELY(oldp == NULL)) return mmalloc(csound, size); if (UNLIKELY(size == (size_t) 0)) { mfree(csound, oldp); return NULL; } pp = HDR_PTR(oldp); #ifdef MEMDEBUG if (UNLIKELY(pp->magic != MEMALLOC_MAGIC || pp->ptr != oldp)) { csound->DebugMsg(csound, " *** internal error: mrealloc() called with invalid " "pointer (%p)\n", oldp); /* exit() is ugly, but this is a fatal error that can only occur */ /* as a result of a bug */ exit(-1); } /* mark old header as invalid */ pp->magic = 0; pp->ptr = NULL; #endif /* allocate memory */ p = realloc((void*) pp, ALLOC_BYTES(size)); if (UNLIKELY(p == NULL)) { #ifdef MEMDEBUG CSOUND_MEM_SPINLOCK /* alloc failed, restore original header */ pp->magic = MEMALLOC_MAGIC; pp->ptr = oldp; CSOUND_MEM_SPINUNLOCK #endif memdie(csound, size); return NULL; } CSOUND_MEM_SPINLOCK /* create new header and update chain pointers */ pp = (memAllocBlock_t*) p; #ifdef MEMDEBUG pp->magic = MEMALLOC_MAGIC; pp->ptr = DATA_PTR(pp); #endif { memAllocBlock_t *prv = pp->prv, *nxt = pp->nxt; if (nxt != NULL) nxt->prv = pp; if (prv != NULL) prv->nxt = pp; else MEMALLOC_DB = (void*) pp; } CSOUND_MEM_SPINUNLOCK /* return with data pointer */ return DATA_PTR(pp); } void *mreallocDebug(CSOUND *csound, void *oldp, size_t size, char *file, int line) { void *p = mrealloc(csound, oldp, size); printf("Realloc %p->%p (%zu) %s:%d\n", oldp, p, size, file, line); return p; } void memRESET(CSOUND *csound) { memAllocBlock_t *pp, *nxtp; pp = (memAllocBlock_t*) MEMALLOC_DB; MEMALLOC_DB = NULL; while (pp != NULL) { nxtp = pp->nxt; #ifdef MEMDEBUG pp->magic = 0; #endif free((void*) pp); pp = nxtp; } } csound-6.10.0/Engine/memfiles.c000066400000000000000000000600161321653344700162560ustar00rootroot00000000000000/* memfiles.c: Copyright (C) 1991, 2001 Barry Vercoe, John ffitch, Richard Dobson (C) 2005 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* MEMFILES.C */ #include "soundio.h" #include "pvfileio.h" #include "convolve.h" #include "lpc.h" #include "pstream.h" #include "namedins.h" #include #include static int Load_Het_File_(CSOUND *csound, const char *filnam, char **allocp, int32 *len) { FILE *f; int length = 1024; int i = 0; int cc; int16 x; char *all; char buffer[16]; //void *dummy = 0; f = fopen(filnam, "r"); if (f==NULL) { csound->Warning(csound, Str("failed to open file %s\n"), filnam); return NOTOK; } csoundNotifyFileOpened(csound, filnam, CSFTYPE_HETRO, 0, 0); all = (char *)csound->Malloc(csound, (size_t) length); if (6!=fread(buffer, 1, 6, f)) { /* Skip HETRO */ csound->Warning(csound, Str("failed to read file %s\n"), filnam); fclose(f); return NOTOK; } //for (i=0; i<6; i++) getc(f); /* Skip HETRO */ /*dummy =*/ (void)fgets(buffer, 10, f); /* number of partials */ x = atoi(buffer); memcpy(&all[0], &x, sizeof(int16)); /* Read data until end, pack as int16 */ for (i=sizeof(int16);;i+=sizeof(int16)) { int p = 0; while ((cc=getc(f))!=',' && cc!='\n' && p<15) { if (cc == EOF) { goto out; } buffer[p++] = cc; } buffer[p]='\0'; /* Expand as necessary */ if (UNLIKELY(i>=length-4)) all = csound->ReAlloc(csound, all, length+=1024); x = atoi(buffer); memcpy(&all[i], &x, sizeof(int16)); } out: fclose(f); /* and close it */ *len = i; all = csound->ReAlloc(csound, all, i); *allocp = all; return 0; /* return 0 for OK */ } static MYFLT read_ieee(FILE* f, int *end) { char buff[120]; double x; char *p = fgets(buff, 120, f); if (p==NULL || feof(f)) { *end = 1; return FL(0.0); } x = cs_strtod(buff, NULL); return (MYFLT)x; /* union { */ /* double d; */ /* struct {int j,k;} n; */ /* int64_t i; */ /* } x; */ /* int sign=1, ex; */ /* int64_t man; */ /* int64_t bit = 1; */ /* char buff[32]; */ /* char *p; */ /* bit <<= 62; */ /* p = fgets(buff, 32, f); */ /* printf("... %s", buff); */ /* if (p==NULL || feof(f)) { */ /* printf("ending\n"); */ /* *end = 1; */ /* return FL(0.0); */ /* } */ /* if (strstr(p, "0x0p+0")) { */ /* return FL(0.0); */ /* } */ /* if (buff[0]=='-') sign=-1; */ /* p = strchr(buff, '.')+1; */ /* sscanf(p, "%lxp%d", &man, &ex); */ /* x.i = man; */ /* if (man!=(int64_t)0) x.i |= bit; */ /* x.d = ldexp(x.d, ex-1); */ /* if (sign<0) x.d =-x.d; */ /* return (MYFLT)x.d; */ } static int Load_CV_File_(CSOUND *csound, const char *filnam, char **allocp, int32 *len) { FILE *f; int length = 4096; unsigned int i = 0; int j = 0; MYFLT x; char *all; CVSTRUCT cvh = {0,0,0,0,0.0,0,0,0,0,{0}}; char buff[120]; char *p; //void *dummy = 0; f = fopen(filnam, "r"); csoundNotifyFileOpened(csound, filnam, CSFTYPE_CVANAL, 0, 0); all = (char *)csound->Malloc(csound, (size_t) length); /* dummy =*/ (void)fgets(buff, 120, f); /* Skip CVANAL */ cvh.magic = CVMAGIC; p = fgets(buff, 120, f); if (UNLIKELY(p==NULL)) { fclose(f); return csoundInitError(csound, Str("Ill-formed CV file\n")); } cvh.headBsize = strtol(p, &p, 10); cvh.dataBsize = strtol(p, &p, 10); cvh.dataFormat = strtol(p, &p, 10); cvh.samplingRate = (MYFLT)cs_strtod(p, &p); cvh.src_chnls = strtol(p, &p, 10); cvh.channel = strtol(p, &p, 10); cvh.Hlen = strtol(p, &p, 10); cvh.Format = strtol(p, &p, 10); /* fscanf(f, "%d %d %d %g %d %d %d %d\n", */ /* &cvh.headBsize, &cvh.dataBsize, &cvh.dataFormat, */ /* &cvh.samplingRate, &cvh.src_chnls, &cvh.channel, */ /* &cvh.Hlen, &cvh.Format); */ cvh.headBsize = sizeof(int32)*8 + sizeof(MYFLT); memcpy(&all[0], &cvh, sizeof(CVSTRUCT)); /* Read data until end, pack as MYFLTs */ for (i=sizeof(CVSTRUCT);;i+=sizeof(MYFLT)) { /* Expand as necessary */ if (UNLIKELY(i>=length-sizeof(MYFLT)-4)) { //printf("expanding from %p[%d] to\n", all, length); all = csound->ReAlloc(csound, all, length+=4096); //printf("i=%d %p[%d]\n", i, all, length); } x = read_ieee(f, &j); if (j) break; memcpy(&all[i], &x, sizeof(MYFLT)); } fclose(f); /* and close it */ //printf("length=%d i=%d\n", length, i); *len = i; all = csound->ReAlloc(csound, all, i); *allocp = all; return 0; /* return 0 for OK */ } static int Load_LP_File_(CSOUND *csound, const char *filnam, char **allocp, int32 *len) { FILE *f; int length = 4096; unsigned int i = 0; int j = 0; MYFLT x; char *all, *p; LPHEADER lph = {0,0,0,0,0.0,0.0,0.0,{0}}; char buff[120]; //void *dummy = 0; f = fopen(filnam, "r"); csoundNotifyFileOpened(csound, filnam, CSFTYPE_LPC, 0, 0); all = (char *)csound->Malloc(csound, (size_t) length); for (i=0; i<6; i++) fgetc(f); /* Skip LPANAL */ if (UNLIKELY(4!=fscanf(f, "%d %d %d %d\n", &lph.headersize, &lph.lpmagic, &lph.npoles, &lph.nvals))) { fclose(f); return csound->InitError(csound, Str("Ill-formed LPC file\n")); } /* dummy = */ (void)fgets(buff, 120, f); lph.framrate = (MYFLT)cs_strtod(buff, &p); lph.srate = (MYFLT)cs_strtod(p, &p); lph.duration = (MYFLT)cs_strtod(p, &p); /* lph.text[0] = (char)strtol(p, &p, 0); */ /* lph.text[1] = (char)strtol(p, &p, 0); */ /* lph.text[2] = (char)strtol(p, &p, 0); */ /* lph.text[3] = (char)strtol(p, &p, 0); */ /* printf("LPHeader %d %d %d %d\n%f %f %f\n", */ /* lph.headersize, lph.lpmagic, lph.npoles, lph.nvals, */ /* lph.framrate, lph.srate, lph.duration); */ /* fscanf(f, "%f %f %f %.2x %.2x %.2x %.2x\n", */ /* &lph.framrate, &lph.srate, &lph.duration, */ /* &lph.text[0], &lph.text[1], &lph.text[2], &lph.text[3]); */ // This needs surgery if in/out different MYFLT sizes *** FIX ME *** lph.headersize = sizeof(int32)*4+sizeof(MYFLT)*3; memcpy(&all[0], &lph, lph.headersize); /* Read data until end, pack as MYFLTs */ for (i=lph.headersize;;i+=sizeof(MYFLT)) { /* Expand as necessary */ if (UNLIKELY(i>=length-sizeof(MYFLT)-8)) { //printf("expanding from %p[%d] to\n", all, length); all = csound->ReAlloc(csound, all, length+=4096); //printf("i=%d %p[%d]\n", i, all, length); } x = read_ieee(f, &j); if (j) break; memcpy(&all[i], &x, sizeof(MYFLT)); } fclose(f); /* and close it */ printf("length=%d i=%u\n", length, i); *len = i; all = csound->ReAlloc(csound, all, i); *allocp = all; return 0; /* return 0 for OK */ } static int Load_File_(CSOUND *csound, const char *filnam, char **allocp, int32 *len, int csFileType) { FILE *f; //void *dummy = 0; *allocp = NULL; f = fopen(filnam, "rb"); if (UNLIKELY(f == NULL)) /* if cannot open the file */ return 1; /* return 1 */ if (csFileType==CSFTYPE_HETRO) { char buff[8]; /* dummy = */ (void)fgets(buff, 6, f); if (strcmp(buff, "HETRO")==0) { fclose(f); return Load_Het_File_(csound, filnam, allocp, len); } } else if (csFileType==CSFTYPE_CVANAL) { char buff[8]; /* dummy = */ (void)fgets(buff, 7, f); if (strcmp(buff, "CVANAL")==0) { fclose(f); return Load_CV_File_(csound, filnam, allocp, len); } } else if (csFileType==CSFTYPE_LPC) { char buff[8]; /* dummy = */ (void)fgets(buff, 7, f); if (strcmp(buff, "LPANAL")==0) { fclose(f); return Load_LP_File_(csound, filnam, allocp, len); } } /* notify the host if it asked */ csoundNotifyFileOpened(csound, filnam, csFileType, 0, 0); fseek(f, 0L, SEEK_END); /* then get its length */ *len = (int32) ftell(f); fseek(f, 0L, SEEK_SET); if (UNLIKELY(*len < 1L)) goto err_return; *allocp = csound->Malloc(csound, (size_t) (*len)); /* alloc as reqd */ if (UNLIKELY(fread(*allocp, (size_t) 1, /* read file in */ (size_t) (*len), f) != (size_t) (*len))) goto err_return; fclose(f); /* and close it */ return 0; /* return 0 for OK */ err_return: if (*allocp != NULL) { csound->Free(csound, *allocp); *allocp = NULL; } fclose(f); return 1; } /* Backwards-compatible wrapper for ldmemfile2(). Please use ldmemfile2() or ldmemfile2withCB() in all new code instead. MEMFIL *ldmemfile(CSOUND *csound, const char *filnam) { return ldmemfile2withCB(csound, filnam, CSFTYPE_UNKNOWN, NULL); } */ /* Takes an additional parameter specifying the type of the file being opened. The type constants are defined in the enumeration CSOUND_FILETYPES. Use ldmemfile2() to load file without additional processing. MEMFIL *ldmemfile2(CSOUND *csound, const char *filnam, int csFileType) { return ldmemfile2withCB(csound, filnam, csFileType, NULL); } */ /* This version of ldmemfile2 allows you to specify a callback procedure to process the file's data after it is loaded. This method ensures that your procedure is only called once even if the file is "loaded" multiple times by several opcodes. callback can be NULL. Callback signature: int myfunc(CSOUND* csound, MEMFIL* mfp) Callback return value: OK (0) or NOTOK (-1) */ MEMFIL *ldmemfile2withCB(CSOUND *csound, const char *filnam, int csFileType, int (*callback)(CSOUND*, MEMFIL*)) { /* read an entire file into memory and log it */ MEMFIL *mfp, *last = NULL; /* share the file with all subsequent requests*/ char *allocp; /* if not fullpath, look in current directory,*/ int32 len; /* then SADIR (if defined). */ char *pathnam; /* Used by adsyn, pvoc, and lpread */ mfp = csound->memfiles; while (mfp != NULL) { /* Checking chain */ if (strcmp(mfp->filename, filnam) == 0) /* if match */ return mfp; /* we have it */ last = mfp; mfp = mfp->next; } /* Add new file description */ mfp = (MEMFIL*) csound->Calloc(csound, sizeof(MEMFIL)); if (last != NULL) last->next = mfp; else csound->memfiles = mfp; mfp->next = NULL; strncpy(mfp->filename, filnam, 255); pathnam = csoundFindInputFile(csound, filnam, "SADIR"); if (UNLIKELY(pathnam == NULL)) { csoundMessage(csound, Str("cannot load %s\n"), filnam); delete_memfile(csound, filnam); return NULL; } if (UNLIKELY(Load_File_(csound, pathnam, &allocp, &len, csFileType) != 0)) { /* loadfile */ csoundMessage(csound, Str("cannot load %s, or SADIR undefined\n"), pathnam); csound->Free(csound, pathnam); delete_memfile(csound, filnam); return NULL; } /* init the struct */ mfp->beginp = allocp; mfp->endp = allocp + len; mfp->length = len; if (callback != NULL) { if (callback(csound, mfp) != OK) { csoundMessage(csound, Str("error processing file %s\n"), filnam); csound->Free(csound, pathnam); delete_memfile(csound, filnam); return NULL; } } csoundMessage(csound, Str("file %s (%ld bytes) loaded into memory\n"), pathnam, (long) len); csound->Free(csound, pathnam); return mfp; /* rtn new slotadr */ } /* clear the memfile array, & free all allocated space */ void rlsmemfiles(CSOUND *csound) { MEMFIL *mfp = csound->memfiles, *nxt; while (mfp != NULL) { nxt = mfp->next; csound->Free(csound, mfp->beginp); /* free the space */ csound->Free(csound, mfp); mfp = nxt; } csound->memfiles = NULL; } int delete_memfile(CSOUND *csound, const char *filnam) { MEMFIL *mfp, *prv; prv = NULL; mfp = csound->memfiles; while (mfp != NULL) { if (strcmp(mfp->filename, filnam) == 0) break; prv = mfp; mfp = mfp->next; } if (mfp == NULL) return -1; if (prv == NULL) csound->memfiles = mfp->next; else prv->next = mfp->next; csound->Free(csound, mfp->beginp); csound->Free(csound, mfp); return 0; } /* ------------------------------------------------------------------------ */ /* despite basic parity in analysis and synthesis, we still have to rescale the amplitudes by 32768 to fit Csound's notion of 0dBFS. Note we do NOT try to rescale to match the old .pv format. */ /* custom version of ldmemfile(); enables pvfileio funcs to apply byte-reversal if needed. NB: filename size in MEMFIL struct was only 64; now 256... */ /* RWD NB PVOCEX format always 32bit, so no MYFLTs here! */ static int pvx_err_msg(CSOUND *csound, const char *fmt, ...) { va_list args; va_start(args, fmt); csound->ErrMsgV(csound, Str("PVOCEX_LoadFile(): error:\n "), fmt, args); va_end(args); return -1; } int PVOCEX_LoadFile(CSOUND *csound, const char *fname, PVOCEX_MEMFILE *p) { PVOCDATA pvdata; WAVEFORMATEX fmt; PVOCEX_MEMFILE *pp; int i, j, rc = 0, pvx_id, hdr_size, name_size; int32 mem_wanted; int32 totalframes, framelen; float *pFrame; if (UNLIKELY(fname == NULL || fname[0] == '\0')) { memset(p, 0, sizeof(PVOCEX_MEMFILE)); return pvx_err_msg(csound, Str("Empty or NULL file name")); } /* is this file already loaded ? */ pp = csound->pvx_memfiles; while (pp != NULL && strcmp(pp->filename, fname) != 0) pp = pp->nxt; if (pp != NULL) { memcpy(p, pp, sizeof(PVOCEX_MEMFILE)); return 0; } hdr_size = ((int) sizeof(PVOCEX_MEMFILE) + 7) & (~7); name_size = ((int) strlen(fname) + 8) & (~7); memset(p, 0, sizeof(PVOCEX_MEMFILE)); memset(&pvdata, 0, sizeof(PVOCDATA)); memset(&fmt, 0, sizeof(WAVEFORMATEX)); pvx_id = csound->PVOC_OpenFile(csound, fname, &pvdata, &fmt); if (UNLIKELY(pvx_id < 0)) { return pvx_err_msg(csound, Str("unable to open pvocex file %s: %s"), fname, csound->PVOC_ErrorString(csound)); } framelen = 2 * pvdata.nAnalysisBins; /* also, accept only 32bit floats for now */ if (UNLIKELY(pvdata.wWordFormat != PVOC_IEEE_FLOAT)) { return pvx_err_msg(csound, Str("pvoc-ex file %s is not 32bit floats"), fname); } /* FOR NOW, accept only PVOC_AMP_FREQ: later, we can convert */ /* NB Csound knows no other: frameFormat is not read anywhere! */ if (UNLIKELY(pvdata.wAnalFormat != PVOC_AMP_FREQ)) { return pvx_err_msg(csound, Str("pvoc-ex file %s not in AMP_FREQ format"), fname); } /* ignore the window spec until we can use it! */ totalframes = csound->PVOC_FrameCount(csound, pvx_id); if (UNLIKELY(totalframes <= 0)) { return pvx_err_msg(csound, Str("pvoc-ex file %s is empty!"), fname); } mem_wanted = totalframes * 2 * pvdata.nAnalysisBins * sizeof(float); /* try for the big block first! */ pp = (PVOCEX_MEMFILE*) csound->Malloc(csound, (size_t) (hdr_size + name_size) + (size_t) mem_wanted); memset((void*) pp, 0, (size_t) (hdr_size + name_size)); pp->filename = (char*) ((uintptr_t) pp + (uintptr_t) hdr_size); pp->nxt = csound->pvx_memfiles; pp->data = (float*) ((uintptr_t) pp + (uintptr_t) (hdr_size + name_size)); strcpy(pp->filename, fname); /* despite using pvocex infile, and pvocex-style resynth, we ~still~ have to rescale to Csound's internal range! This is because all pvocex calculations assume +-1 floatsam i/o. It seems preferable to do this here, rather than force the user to do so. Csound might change one day... */ for (pFrame = pp->data, i = 0; i < totalframes; i++) { rc = csound->PVOC_GetFrames(csound, pvx_id, pFrame, 1); if (UNLIKELY(rc != 1)) break; /* read error, but may still have something to use */ /* scale amps to Csound range, to fit fsig */ for (j = 0; j < framelen; j += 2) { pFrame[j] *= (float) csound->e0dbfs; } pFrame += framelen; } csound->PVOC_CloseFile(csound, pvx_id); if (UNLIKELY(rc < 0)) { csound->Free(csound, pp); return pvx_err_msg(csound, Str("error reading pvoc-ex file %s"), fname); } if (UNLIKELY(i < totalframes)) { csound->Free(csound, pp); return pvx_err_msg(csound, Str("error reading pvoc-ex file %s " "after %d frames"), fname, i); } pp->srate = (MYFLT) fmt.nSamplesPerSec; if (UNLIKELY(pp->srate != csound->esr)) { /* & chk the data */ csound->Warning(csound, Str("%s's srate = %8.0f, orch's srate = %8.0f"), fname, pp->srate, csound->esr); } pp->nframes = (uint32) totalframes; pp->format = PVS_AMP_FREQ; pp->fftsize = 2 * (pvdata.nAnalysisBins - 1); pp->overlap = pvdata.dwOverlap; pp->winsize = pvdata.dwWinlen; pp->chans = fmt.nChannels; switch ((pv_wtype) pvdata.wWindowType) { case PVOC_HAMMING: pp->wintype = PVS_WIN_HAMMING; break; case PVOC_HANN: pp->wintype = PVS_WIN_HANN; break; case PVOC_KAISER: pp->wintype = PVS_WIN_KAISER; break; default: /* deal with all other possibilities later! */ pp->wintype = PVS_WIN_HAMMING; break; } /* link into PVOC-EX memfile chain */ csound->pvx_memfiles = pp; csound->Message(csound, Str("file %s (%d bytes) loaded into memory\n"), fname, (int32) mem_wanted); memcpy(p, pp, sizeof(PVOCEX_MEMFILE)); return 0; } /* ------------------------------------------------------------------------ */ /** * Load an entire sound file into memory. * 'fileName' is the file name (searched in the current directory first, * then search path defined by SSDIR, then SFDIR), and sfinfo (optional, * may be NULL) stores the default parameters for opening a raw file. * On success, a pointer to an SNDMEMFILE structure (see csoundCore.h) is * returned, and sound file parameters are stored in sfinfo (assuming that * it is not NULL). * Multiple calls of csoundLoadSoundFile() with the same file name will * share the same SNDMEMFILE structure, and the file is loaded only once * from disk. * The return value is NULL if an error occurs (the contents of sfinfo may * be undefined in this case). */ SNDMEMFILE *csoundLoadSoundFile(CSOUND *csound, const char *fileName, void *sfi) { SF_INFO *sfinfo = sfi; SNDFILE *sf; void *fd; SNDMEMFILE *p = NULL; SF_INFO tmp; if (UNLIKELY(fileName == NULL || fileName[0] == '\0')) return NULL; /* check if file is already loaded */ if (csound->sndmemfiles != NULL) { p = cs_hash_table_get(csound, csound->sndmemfiles, (char*)fileName); } else { csound->sndmemfiles = cs_hash_table_create(csound); } if (p != NULL) { /* if file was loaded earlier: */ if (sfinfo != NULL) { memset(sfinfo, 0, sizeof(SF_INFO)); sfinfo->frames = (sf_count_t) p->nFrames; sfinfo->samplerate = ((int) p->sampleRate + 0.5); sfinfo->channels = p->nChannels; sfinfo->format = FORMAT2SF(p->sampleFormat) | TYPE2SF(p->fileType); } return p; } /* open file */ if (sfinfo == NULL) { memset(&tmp, 0, sizeof(SF_INFO)); sfinfo = &tmp; } fd = csound->FileOpen2(csound, &sf, CSFILE_SND_R, fileName, sfinfo, "SFDIR;SSDIR", CSFTYPE_UNKNOWN_AUDIO, 0); if (UNLIKELY(fd == NULL)) { csound->ErrorMsg(csound, Str("csoundLoadSoundFile(): failed to open '%s'"), fileName); return NULL; } p = (SNDMEMFILE*) csound->Malloc(csound, sizeof(SNDMEMFILE) + (size_t) sfinfo->frames * sizeof(float)); /* set parameters */ p->name = (char*) csound->Malloc(csound, strlen(fileName) + 1); strcpy(p->name, fileName); p->fullName = (char*) csound->Malloc(csound, strlen(csound->GetFileName(fd)) + 1); strcpy(p->fullName, csound->GetFileName(fd)); p->sampleRate = (double) sfinfo->samplerate; p->nFrames = (size_t) sfinfo->frames; p->nChannels = sfinfo->channels; p->sampleFormat = SF2FORMAT(sfinfo->format); p->fileType = SF2TYPE(sfinfo->format); /* set defaults for sampler information */ p->loopMode = 0; p->startOffs = 0.0; p->loopStart = 0.0; p->loopEnd = 0.0; p->baseFreq = 1.0; p->scaleFac = 1.0; { SF_INSTRUMENT lpd; if (sf_command(sf, SFC_GET_INSTRUMENT, &lpd, sizeof(SF_INSTRUMENT)) != 0) { if (lpd.loop_count > 0 && lpd.loops[0].mode != SF_LOOP_NONE) { /* set loop mode and loop points */ p->loopMode = (lpd.loops[0].mode == SF_LOOP_FORWARD ? 2 : (lpd.loops[0].mode == SF_LOOP_BACKWARD ? 3 : 4)); p->loopStart = (double) lpd.loops[0].start; p->loopEnd = (double) lpd.loops[0].end; } else { /* loop mode: off */ p->loopMode = 1; } p->baseFreq = pow(2.0, (double) (((int) lpd.basenote - 69) * 100 + (int) lpd.detune) / 1200.0) * csound->A4; p->scaleFac = pow(10.0, (double) lpd.gain * 0.05); } } if (UNLIKELY((size_t) sf_readf_float(sf, &(p->data[0]), (sf_count_t) p->nFrames) != p->nFrames)) { csound->FileClose(csound, fd); csound->Free(csound, p->name); csound->Free(csound, p->fullName); csound->Free(csound, p); csound->ErrorMsg(csound, Str("csoundLoadSoundFile(): error reading '%s'"), fileName); return NULL; } p->data[p->nFrames] = 0.0f; csound->FileClose(csound, fd); csound->Message(csound, Str("File '%s' (sr = %d Hz, %d channel(s), %lld " "sample frames) loaded into memory\n"), p->fullName, (int) sfinfo->samplerate, (int) sfinfo->channels, sfinfo->frames); /* link into database */ cs_hash_table_put(csound, csound->sndmemfiles, (char*)fileName, p); /* return with pointer to file structure */ return p; } csound-6.10.0/Engine/musmon.c000066400000000000000000001465311321653344700160020ustar00rootroot00000000000000/* musmon.c: Copyright (C) 1991,2002 Barry Vercoe, John ffitch, Istvan Varga, rasmus ekman This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* MUSMON.C */ #include "midiops.h" #include "soundio.h" #include "namedins.h" #include "oload.h" #include "remote.h" #include #include "corfile.h" #include "csdebug.h" #define SEGAMPS AMPLMSG #define SORMSG RNGEMSG extern int MIDIinsert(CSOUND *, int, MCHNBLK*, MEVENT*); extern int insert(CSOUND *, int, EVTBLK*); extern void MidiOpen(CSOUND *); extern void m_chn_init_all(CSOUND *); //extern char * scsortstr(CSOUND *, CORFIL *); extern void infoff(CSOUND*, MYFLT), orcompact(CSOUND*); extern void beatexpire(CSOUND *, double), timexpire(CSOUND *, double); extern void sfopenin(CSOUND *), sfopenout(CSOUND*), sfnopenout(CSOUND*); extern void iotranset(CSOUND *), sfclosein(CSOUND*), sfcloseout(CSOUND*); extern void MidiClose(CSOUND *); extern void RTclose(CSOUND *); extern void remote_Cleanup(CSOUND *); extern char **csoundGetSearchPathFromEnv(CSOUND *, const char *); /* extern void initialize_instrument0(CSOUND *); */ typedef struct evt_cb_func { void (*func)(CSOUND *, void *); void *userData; struct evt_cb_func *nxt; } EVT_CB_FUNC; #define STA(x) (csound->musmonStatics.x) /* IV - Jan 28 2005 */ void print_benchmark_info(CSOUND *csound, const char *s) { double rt, ct; if ((csound->oparms->msglevel & TIMEMSG) == 0 || csound->csRtClock == NULL) return; rt = csoundGetRealTime(csound->csRtClock); ct = csoundGetCPUTime(csound->csRtClock); csound->Message(csound, Str("Elapsed time at %s: real: %.3fs, CPU: %.3fs\n"), (char*) s, rt, ct); } static void settempo(CSOUND *csound, double tempo) { if (tempo <= 0.0) return; if (csound->oparms->Beatmode==1) csound->ibeatTime = (int64_t)(csound->esr*60.0 / tempo); csound->curBeat_inc = tempo / (60.0 * (double) csound->ekr); } int gettempo(CSOUND *csound, GTEMPO *p) { if (LIKELY(csound->oparms->Beatmode)) { *p->ans = FL(60.0) * csound->esr / (MYFLT)csound->ibeatTime; } else *p->ans = FL(60.0); return OK; } int tempset(CSOUND *csound, TEMPO *p) { double tempo; if (UNLIKELY((tempo = (double)*p->istartempo) <= FL(0.0))) { return csound->InitError(csound, Str("illegal istartempo value")); } if (UNLIKELY(csound->oparms->Beatmode==0)) return csound->InitError(csound, Str("Beat mode not in force")); settempo(csound, tempo); p->prvtempo = (MYFLT)tempo; return OK; } int tempo(CSOUND *csound, TEMPO *p) { if (*p->ktempo != p->prvtempo) { settempo(csound, (double)*p->ktempo); p->prvtempo = *p->ktempo; } return OK; } static void print_maxamp(CSOUND *csound, MYFLT x) { int attr = 0; if (!(csound->oparms->msglevel & 0x60)) { /* 0x00: raw amplitudes */ if (csound->oparms->msglevel & 0x100) { MYFLT y = x / csound->e0dbfs; /* relative level */ if (UNLIKELY(y >= FL(1.0))) /* >= 0 dB: red */ attr = CSOUNDMSG_FG_BOLD | CSOUNDMSG_FG_RED; else if (csound->oparms->msglevel & 0x200) { if (y >= FL(0.5)) /* -6..0 dB: yellow */ attr = CSOUNDMSG_FG_BOLD | CSOUNDMSG_FG_CYAN; /* was yellow but... */ else if (y >= FL(0.125)) /* -24..-6 dB: green */ attr = CSOUNDMSG_FG_BOLD | CSOUNDMSG_FG_GREEN; else /* -200..-24 dB: blue */ attr = CSOUNDMSG_FG_BOLD | CSOUNDMSG_FG_BLUE; } } if (csound->e0dbfs > FL(3000.0)) csound->MessageS(csound, attr, "%9.1f", x); else if (csound->e0dbfs < FL(3.0)) csound->MessageS(csound, attr, "%9.5f", x); else if (csound->e0dbfs > FL(300.0)) csound->MessageS(csound, attr, "%9.2f", x); else if (csound->e0dbfs > FL(30.0)) csound->MessageS(csound, attr, "%9.3f", x); else csound->MessageS(csound, attr, "%9.4f", x); } else { /* dB values */ MYFLT y = x / csound->e0dbfs; /* relative level */ if (UNLIKELY(y < FL(1.0e-10))) { /* less than -200 dB: print zero */ csound->Message(csound, " 0 "); return; } y = FL(20.0) * (MYFLT) log10((double) y); if (csound->oparms->msglevel & 0x40) { if (UNLIKELY(y >= FL(0.0))) /* >= 0 dB: red */ attr = CSOUNDMSG_FG_BOLD | CSOUNDMSG_FG_RED; else if (csound->oparms->msglevel & 0x20) { if (y >= FL(-6.0)) /* -6..0 dB: yellow */ attr = CSOUNDMSG_FG_BOLD | CSOUNDMSG_FG_YELLOW; else if (y >= FL(-24.0)) /* -24..-6 dB: green */ attr = CSOUNDMSG_FG_BOLD | CSOUNDMSG_FG_GREEN; else /* -200..-24 dB: blue */ attr = CSOUNDMSG_FG_BOLD | CSOUNDMSG_FG_BLUE; } } csound->MessageS(csound, attr, "%+9.2f", y); } } int musmon(CSOUND *csound) { OPARMS *O = csound->oparms; /* VL - 20-10-16 this is already printed in csound.c */ /* #ifdef USE_DOUBLE #ifdef BETA csound->Message(csound, Str("--Csound version %s beta (double samples) %s \n[%s]\n"), CS_PACKAGE_VERSION, CS_PACKAGE_DATE, GIT_HASH_VALUE_ST); #else csound->Message(csound, Str("--Csound version %s (double samples) %s \n[%s]\n"), CS_PACKAGE_VERSION, CS_PACKAGE_DATE, GIT_HASH_VALUE_ST); #endif #else #ifdef BETA csound->Message(csound, Str("--Csound version %s beta (float samples) %s\n[%s]\n"), CS_PACKAGE_VERSION, CS_PACKAGE_DATE, GIT_HASH_VALUE_ST); #else csound->Message(csound, Str("--Csound version %s (float samples) %s\n[%s]\n"), CS_PACKAGE_VERSION, CS_PACKAGE_DATE, GIT_HASH_VALUE_ST); #endif #endif */ /* initialise search path cache */ csoundGetSearchPathFromEnv(csound, "SNAPDIR"); csoundGetSearchPathFromEnv(csound, "SFDIR;SSDIR;INCDIR"); csoundGetSearchPathFromEnv(csound, "SFDIR"); csoundGetSearchPathFromEnv(csound, "SADIR"); csoundGetSearchPathFromEnv(csound, "SFDIR;SSDIR"); m_chn_init_all(csound); /* allocate MIDI channels */ dispinit(csound); /* initialise graphics or character display */ reverbinit(csound); dbfs_init(csound, csound->e0dbfs); csound->nspout = csound->ksmps * csound->nchnls; /* alloc spin & spout */ csound->nspin = csound->ksmps * csound->inchnls; /* JPff: in preparation */ csound->spin = (MYFLT *) csound->Calloc(csound, csound->nspin*sizeof(MYFLT)); csound->spraw = (MYFLT *) csound->Calloc(csound, csound->nspout*sizeof(MYFLT)); csound->spout = (MYFLT *) csound->Calloc(csound, csound->nspout*sizeof(MYFLT)); csound->auxspin = (MYFLT *) csound->Calloc(csound, csound->nspin*sizeof(MYFLT)); /* memset(csound->maxamp, '\0', sizeof(MYFLT)*MAXCHNLS); */ /* memset(csound->smaxamp, '\0', sizeof(MYFLT)*MAXCHNLS); */ /* memset(csound->omaxamp, '\0', sizeof(MYFLT)*MAXCHNLS); */ /* initialise sensevents state */ csound->prvbt = csound->curbt = csound->nxtbt = 0.0; csound->curp2 = csound->nxtim = csound->timeOffs = csound->beatOffs = 0.0; csound->icurTime = 0L; if (O->Beatmode && O->cmdTempo > 0.0) { /* if performing from beats, set the initial tempo */ csound->curBeat_inc = O->cmdTempo / (60.0 * (double) csound->ekr); csound->ibeatTime = (int64_t)(csound->esr*60.0 / O->cmdTempo); } else { csound->curBeat_inc = 1.0 / (double) csound->ekr; csound->ibeatTime = 1; } csound->cyclesRemaining = 0; memset(&(csound->evt), 0, sizeof(EVTBLK)); /* run instr 0 inits */ if (UNLIKELY(init0(csound) != 0)) csoundDie(csound, Str("header init errors")); /* kperf() will not call csoundYield() more than 250 times per second */ csound->evt_poll_cnt = 0; csound->evt_poll_maxcnt = (int)(250.0 /(double) csound->ekr); /* VL this was wrong: kr/250 originally */ /* Enable musmon to handle external MIDI input, if it has been enabled. */ if (O->Midiin || O->FMidiin || O->RMidiin) { O->RTevents = 1; MidiOpen(csound); /* alloc bufs & open files */ } csound->Message(csound, Str("orch now loaded\n")); csound->multichan = (csound->nchnls > 1 ? 1 : 0); STA(segamps) = O->msglevel & SEGAMPS; STA(sormsg) = O->msglevel & SORMSG; if (O->Linein) RTLineset(csound); /* if realtime input expected */ if (csound->enableHostImplementedAudioIO && csound->hostRequestedBufferSize) { int bufsize = (int) csound->hostRequestedBufferSize; int ksmps = (int) csound->ksmps; bufsize = (bufsize + (ksmps >> 1)) / ksmps; bufsize = (bufsize ? bufsize * ksmps : ksmps); O->outbufsamps = O->inbufsamps = bufsize; } else { if (!O->oMaxLag) O->oMaxLag = IODACSAMPS; if (!O->outbufsamps) O->outbufsamps = IOBUFSAMPS; else if (UNLIKELY(O->outbufsamps < 0)) { /* if k-aligned iobufs requested */ /* set from absolute value */ O->outbufsamps *= -(csound->ksmps); csound->Message(csound, Str("k-period aligned audio buffering\n")); if (O->oMaxLag <= O->outbufsamps) O->oMaxLag = O->outbufsamps << 1; } /* else keep the user values */ /* IV - Feb 04 2005: make sure that buffer sizes for real time audio */ /* are usable */ if (check_rtaudio_name(O->infilename, NULL, 0) >= 0 || check_rtaudio_name(O->outfilename, NULL, 1) >= 0) { O->oMaxLag = ((O->oMaxLag + O->outbufsamps - 1) / O->outbufsamps) * O->outbufsamps; if (O->oMaxLag <= O->outbufsamps && O->outbufsamps > 1) O->outbufsamps >>= 1; } O->inbufsamps = O->outbufsamps; } csound->Message(csound, Str("audio buffered in %d sample-frame blocks\n"), (int) O->outbufsamps); O->inbufsamps *= csound->inchnls; /* now adjusted for n channels */ O->outbufsamps *= csound->nchnls; iotranset(csound); /* point recv & tran to audio formatter */ /* open audio file or device for input first, and then for output */ if (!csound->enableHostImplementedAudioIO) { if (O->sfread) sfopenin(csound); if (O->sfwrite && !csound->initonly) sfopenout(csound); else sfnopenout(csound); } if (O->playscore!=NULL) corfile_flush(csound, O->playscore); //csound->scfp if (UNLIKELY(O->usingcscore)) { if (STA(lsect) == NULL) { STA(lsect) = (EVENT*) csound->Malloc(csound, sizeof(EVENT)); STA(lsect)->op = 'l'; } csound->Message(csound, Str("using Cscore processing\n")); /* override stdout in */ if (UNLIKELY(!(csound->oscfp = fopen("cscore.out", "w")))) csoundDie(csound, Str("cannot create cscore.out")); csoundNotifyFileOpened(csound, "cscore.out", CSFTYPE_SCORE_OUT, 1, 0); /* rdscor for cscorefns */ csoundInitializeCscore(csound, csound->scfp, csound->oscfp); /* call cscore, optionally re-enter via lplay() */ csound->cscoreCallback_(csound); fclose(csound->oscfp); csound->oscfp = NULL; if (csound->scfp != NULL) { fclose(csound->scfp); csound->scfp = NULL; } if (STA(lplayed)) return 0; /* read from cscore.out */ if (UNLIKELY(!(csound->scfp = fopen("cscore.out", "r")))) { csoundDie(csound, Str("cannot reopen cscore.out")); } else { CORFIL *inf = corfile_create_w(csound); int c; while ((c=getc(csound->scfp))!=EOF) corfile_putc(csound, c, inf); corfile_rewind(inf); csound->scorestr = inf; corfile_rm(csound, &csound->scstr); } csoundNotifyFileOpened(csound, "cscore.out", CSFTYPE_SCORE_OUT, 0, 0); /* write to cscore.srt */ if (UNLIKELY(!(csound->oscfp = fopen("cscore.srt", "w")))) csoundDie(csound, Str("cannot reopen cscore.srt")); csoundNotifyFileOpened(csound, "cscore.srt", CSFTYPE_SCORE_OUT, 1, 0); csound->Message(csound, Str("sorting cscore.out ..\n")); /* csound->scorestr = copy_to_corefile(csound, "cscore.srt", NULL, 1); */ scsortstr(csound, csound->scorestr); /* call the sorter again */ fclose(csound->scfp); csound->scfp = NULL; fputs(corfile_body(csound->scstr), csound->oscfp); fclose(csound->oscfp); csound->oscfp = NULL; csound->Message(csound, Str("\t... done\n")); csound->Message(csound, Str("playing from cscore.srt\n")); O->usingcscore = 0; } csound->Message(csound, Str("SECTION %d:\n"), ++STA(sectno)); /* apply score offset if non-zero */ if (csound->csoundScoreOffsetSeconds_ > FL(0.0)) csoundSetScoreOffsetSeconds(csound, csound->csoundScoreOffsetSeconds_); #ifndef __EMSCRIPTEN__ if (csound->realtime_audio_flag && csound->init_pass_loop == 0){ extern void *init_pass_thread(void *); csound->init_pass_threadlock = csoundCreateMutex(0); csoundLockMutex(csound->init_pass_threadlock); csound->init_pass_loop = 1; csoundUnlockMutex(csound->init_pass_threadlock); csound->init_pass_thread = csound->CreateThread( (uintptr_t (*)(void*)) init_pass_thread, (void*)csound); } #endif /* since we are running in components, we exit here to playevents later */ return 0; } static void deactivate_all_notes(CSOUND *csound) { INSDS *ip = csound->actanchor.nxtact; while (ip != NULL) { INSDS *nxt = ip->nxtact; xturnoff_now(csound, ip); ip = nxt; } } static void delete_pending_rt_events(CSOUND *csound) { EVTNODE *ep = csound->OrcTrigEvts; while (ep != NULL) { EVTNODE *nxt = ep->nxt; if (ep->evt.strarg != NULL) { csound->Free(csound,ep->evt.strarg); ep->evt.strarg = NULL; } /* push to stack of free event nodes */ ep->nxt = csound->freeEvtNodes; csound->freeEvtNodes = ep; ep = nxt; } csound->OrcTrigEvts = NULL; } static inline void cs_beep(CSOUND *csound) { csound->Message(csound, Str("%c\tbeep!\n"), '\a'); } PUBLIC int csoundCleanup(CSOUND *csound) { void *p; MYFLT *maxp; int32 *rngp; uint32_t n; csoundLockMutex(csound->API_lock); if (csound->QueryGlobalVariable(csound,"::UDPCOM") != NULL) csoundUDPServerClose(csound); while (csound->evtFuncChain != NULL) { p = (void*) csound->evtFuncChain; csound->evtFuncChain = ((EVT_CB_FUNC*) p)->nxt; csound->Free(csound,p); } /* check if we have already cleaned up */ if (!(csound->engineStatus & CS_STATE_CLN)){ csoundUnlockMutex(csound->API_lock); return 0; } /* will not clean up more than once */ csound->engineStatus &= ~(CS_STATE_CLN); deactivate_all_notes(csound); if (csound->engineState.instrtxtp && csound->engineState.instrtxtp[0] && csound->engineState.instrtxtp[0]->instance && csound->engineState.instrtxtp[0]->instance->actflg) xturnoff_now(csound, csound->engineState.instrtxtp[0]->instance); delete_pending_rt_events(csound); #ifndef __EMSCRIPTEN__ if (csound->init_pass_loop == 1) { csoundLockMutex(csound->init_pass_threadlock); csound->init_pass_loop = 0; csoundUnlockMutex(csound->init_pass_threadlock); csound->JoinThread(csound->init_pass_thread); csoundDestroyMutex(csound->init_pass_threadlock); csound->init_pass_threadlock = 0; } #endif while (csound->freeEvtNodes != NULL) { p = (void*) csound->freeEvtNodes; csound->freeEvtNodes = ((EVTNODE*) p)->nxt; csound->Free(csound,p); } orcompact(csound); corfile_rm(csound, &csound->scstr); /* print stats only if musmon was actually run */ /* NOT SURE HOW ************************** */ { csound->Message(csound, Str("end of score.\t\t overall amps:")); corfile_rm(csound, &csound->expanded_sco); for (n = 0; n < csound->nchnls; n++) { if (csound->smaxamp[n] > csound->omaxamp[n]) csound->omaxamp[n] = csound->smaxamp[n]; if (csound->maxamp[n] > csound->omaxamp[n]) csound->omaxamp[n] = csound->maxamp[n]; STA(orngcnt)[n] += (STA(srngcnt)[n] + csound->rngcnt[n]); } for (maxp = csound->omaxamp, n = csound->nchnls; n--; ) print_maxamp(csound, *maxp++); if (csound->oparms->outformat != AE_FLOAT) { csound->Message(csound, Str("\n\t overall samples out of range:")); for (rngp = STA(orngcnt), n = csound->nchnls; n--; ) csound->Message(csound, "%9d", *rngp++); } csound->Message(csound, Str("\n%d errors in performance\n"), csound->perferrcnt); print_benchmark_info(csound, Str("end of performance")); } /* close line input (-L) */ RTclose(csound); /* close MIDI input */ MidiClose(csound); /* IV - Feb 03 2005: do not need to call rtclose from here, */ /* as sfclosein/sfcloseout will do that. */ if (!csound->enableHostImplementedAudioIO) { sfclosein(csound); sfcloseout(csound); if (UNLIKELY(!csound->oparms->sfwrite)) csound->Message(csound, Str("no sound written to disk\n")); } /* close any remote.c sockets */ if (csound->remoteGlobals) remote_Cleanup(csound); if (UNLIKELY(csound->oparms->ringbell)) cs_beep(csound); csoundUnlockMutex(csound->API_lock); return dispexit(csound); /* hold or terminate the display output */ } int lplay(CSOUND *csound, EVLIST *a) /* cscore re-entry into musmon */ { /* if (csound->musmonGlobals == NULL) */ /* csound->musmonGlobals = csound->Calloc(csound, sizeof(MUSMON_GLOBALS)); */ STA(lplayed) = 1; if (!STA(sectno)) csound->Message(csound, Str("SECTION %d:\n"), ++STA(sectno)); STA(ep) = &a->e[1]; /* from 1st evlist member */ STA(epend) = STA(ep) + a->nevents; /* to last */ while (csoundPerform(csound) == 0) /* play list members */ ; /* NB: empoty loop */ return OK; } /* make list to turn on instrs for indef */ /* perf called from i0 for execution in playevents */ int turnon(CSOUND *csound, TURNON *p) { EVTBLK evt; int insno; memset(&evt, 0, sizeof(EVTBLK)); evt.strarg = NULL; evt.scnt = 0; evt.opcod = 'i'; evt.pcnt = 3; if (csound->ISSTRCOD(*p->insno)) { char *ss = get_arg_string(csound,*p->insno); insno = csound->strarg2insno(csound,ss,1); if (insno <= 0L) return NOTOK; } else insno = *p->insno; evt.p[1] = (MYFLT) insno; evt.p[2] = *p->itime; evt.p[3] = FL(-1.0); evt.c.extra = NULL; return insert_score_event_at_sample(csound, &evt, csound->icurTime); } /* make list to turn on instrs for indef */ /* perf called from i0 for execution in playevents */ int turnon_S(CSOUND *csound, TURNON *p) { EVTBLK evt; int insno; memset(&evt, 0, sizeof(EVTBLK)); evt.strarg = NULL; evt.scnt = 0; evt.opcod = 'i'; evt.pcnt = 3; insno = csound->strarg2insno(csound, ((STRINGDAT *)p->insno)->data, 1); if (UNLIKELY(insno <= 0L)) return NOTOK; evt.p[1] = (MYFLT) insno; evt.p[2] = *p->itime; evt.p[3] = FL(-1.0); evt.c.extra = NULL; return insert_score_event_at_sample(csound, &evt, csound->icurTime); } /* Print current amplitude values, and update section amps. */ static void print_amp_values(CSOUND *csound, int score_evt) { CSOUND *p = csound; MYFLT *maxp, *smaxp; uint32 *maxps, *smaxps; int32 *rngp, *srngp; int n; if (UNLIKELY(STA(segamps) || (p->rngflg && STA(sormsg)))) { if (score_evt) p->Message(p, "B%7.3f ..%7.3f T%7.3f TT%7.3f M:", p->prvbt - p->beatOffs, p->curbt - p->beatOffs, p->curp2 - p->timeOffs, p->curp2); else p->Message(p, " rtevent:\t T%7.3f TT%7.3f M:", p->curp2 - p->timeOffs, p->curp2); for (n = p->nchnls, maxp = p->maxamp; n--; ) print_maxamp(p, *maxp++); /* IV - Jul 9 2002 */ p->Message(p, "\n"); if (UNLIKELY(p->rngflg)) { p->Message(p, Str("\t number of samples out of range:")); for (n = p->nchnls, rngp = p->rngcnt; n--; ) p->Message(p, "%9d", *rngp++); p->Message(p, "\n"); } } if (p->rngflg) { p->rngflg = 0; STA(srngflg)++; } for (n = p->nchnls, maxp = p->maxamp - 1, smaxp = p->smaxamp - 1, maxps = p->maxpos - 1, smaxps = p->smaxpos - 1, rngp = p->rngcnt, srngp = STA(srngcnt); n--; ) { ++maxps; ++smaxps; if (*++maxp > *++smaxp) { *smaxp = *maxp; *smaxps = *maxps; } *maxp = FL(0.0); *maxps = 0; *srngp++ += *rngp; *rngp++ = 0; } } /* Update overall amplitudes from section values, */ /* and optionally print message (1: section end, 2: lplay end). */ static void section_amps(CSOUND *csound, int enable_msgs) { CSOUND *p = csound; MYFLT *maxp, *smaxp; uint32 *maxps, *smaxps; int32 *rngp, *srngp; int n; if (enable_msgs) { if (enable_msgs == 1) p->Message(p, Str("end of section %d\t sect peak amps:"), STA(sectno)); else if (enable_msgs == 2) p->Message(p, Str("end of lplay event list\t peak amps:")); for (n = p->nchnls, maxp = p->smaxamp; n--; ) print_maxamp(p, *maxp++); /* IV - Jul 9 2002 */ p->Message(p, "\n"); if (UNLIKELY(STA(srngflg))) { p->Message(p, Str("\t number of samples out of range:")); for (n = p->nchnls, srngp = STA(srngcnt); n--; ) p->Message(p, "%9d", *srngp++); p->Message(p, "\n"); } } STA(srngflg) = 0; for (n = p->nchnls, smaxp = p->smaxamp - 1, maxp = p->omaxamp - 1, smaxps = p->smaxpos - 1, maxps = p->omaxpos - 1, srngp = STA(srngcnt), rngp = STA(orngcnt); n--; ) { ++maxps; ++smaxps; if (UNLIKELY(*++smaxp > *++maxp)) { *maxp = *smaxp; /* keep ovrl maxamps */ *maxps = *smaxps; /* And where */ } *smaxp = FL(0.0); *smaxps = 0; *rngp++ += *srngp; /* and orng counts */ *srngp++ = 0; } } static CS_NOINLINE void printScoreError(CSOUND *p, int rtEvt, const char *fmt, ...) { va_list args; if (rtEvt) p->Message(p, "\t\t T%7.3f", p->curp2 - p->timeOffs); else p->Message(p, "\t B%7.3f", p->curbt - p->beatOffs); va_start(args, fmt); p->ErrMsgV(p, NULL, fmt, args); va_end(args); p->perferrcnt++; } static int process_score_event(CSOUND *csound, EVTBLK *evt, int rtEvt) { EVTBLK *saved_currevent; int insno, rfd, n; saved_currevent = csound->currevent; csound->currevent = evt; switch (evt->opcod) { /* scorevt or Linevt: */ case 'e': /* quit realtime */ case 'l': case 's': while (csound->frstoff != NULL) { INSDS *nxt = csound->frstoff->nxtoff; xturnoff_now(csound, csound->frstoff); csound->frstoff = nxt; } csound->currevent = saved_currevent; return (evt->opcod == 'l' ? 3 : (evt->opcod == 's' ? 1 : 2)); case 'q': if (csound->ISSTRCOD(evt->p[1]) && evt->strarg) { /* IV - Oct 31 2002 */ if (UNLIKELY((insno = (int) named_instr_find(csound, evt->strarg)) == 0)) { printScoreError(csound, rtEvt, Str(" - note deleted. instr %s undefined"), evt->strarg); break; } csound->Message(csound, Str("Setting instrument %s %s\n"), evt->strarg, (evt->p[3] == 0 ? Str("off") : Str("on"))); csound->engineState.instrtxtp[insno]->muted = (int16) evt->p[3]; } else { /* IV - Oct 31 2002 */ insno = abs((int) evt->p[1]); if (UNLIKELY((unsigned int)(insno-1) >= (unsigned int) csound->engineState.maxinsno || csound->engineState.instrtxtp[insno] == NULL)) { printScoreError(csound, rtEvt, Str(" - note deleted. instr %d(%d) undefined"), insno, csound->engineState.maxinsno); break; } csound->Message(csound, Str("Setting instrument %d %s\n"), insno, (evt->p[3] == 0 ? Str("off") : (Str("on")))); csound->engineState.instrtxtp[insno]->muted = (int16) evt->p[3]; } break; case 'i': case 'd': if (csound->ISSTRCOD(evt->p[1]) && evt->strarg) { /* IV - Oct 31 2002 */ if (UNLIKELY((insno = (int) named_instr_find(csound, evt->strarg)) == 0)) { printScoreError(csound, rtEvt, Str(" - note deleted. instr %s undefined"), evt->strarg); break; } if (insno<0) { evt->p[1] = insno; insno = -insno; } else if (evt->opcod=='d') evt->p[1]=-insno; if ((rfd = getRemoteInsRfd(csound, insno))) { /* RM: if this note labeled as remote */ if (rfd == GLOBAL_REMOT) insGlobevt(csound, evt); /* RM: do a global send and allow local */ else { insSendevt(csound, evt, rfd);/* RM: or send to single remote Csound */ break; /* RM: and quit */ } } evt->p[1] = (MYFLT) insno; if (csound->oparms->Beatmode && !rtEvt && evt->p3orig > FL(0.0)) evt->p[3] = evt->p3orig * (MYFLT) csound->ibeatTime/csound->esr; /* else alloc, init, activate */ if (UNLIKELY((n = insert(csound, insno, evt)))) { printScoreError(csound, rtEvt, Str(" - note deleted. i%d (%s) had %d init errors"), insno, evt->strarg, n); } } else { /* IV - Oct 31 2002 */ insno = abs((int) evt->p[1]); if (UNLIKELY((unsigned int)(insno-1) >= (unsigned int)csound->engineState.maxinsno || csound->engineState.instrtxtp[insno] == NULL)) { printScoreError(csound, rtEvt, Str(" - note deleted. instr %d(%d) undefined"), insno, csound->engineState.maxinsno); break; } if ((rfd = getRemoteInsRfd(csound, insno))) { /* RM: if this note labeled as remote */ if (rfd == GLOBAL_REMOT) insGlobevt(csound, evt); /* RM: do a global send and allow local */ else { insSendevt(csound, evt, rfd);/* RM: or send to single remote Csound */ break; /* RM: and quit */ } } if (evt->p[1] < FL(0.0)) /* if p1 neg, */ infoff(csound, -evt->p[1]); /* turnoff any infin cpy */ else { if (csound->oparms->Beatmode && !rtEvt && evt->p3orig > FL(0.0)) evt->p[3] = evt->p3orig * (MYFLT) csound->ibeatTime/csound->esr; if (UNLIKELY((n = insert(csound, insno, evt)))) { /* else alloc, init, activate */ printScoreError(csound, rtEvt, Str(" - note deleted. i%d had %d init errors"), insno, n); } } } break; case 'f': /* f event: */ { FUNC *dummyftp; csound->hfgens(csound, &dummyftp, evt, 0); /* construct locally */ if (getRemoteInsRfdCount(csound)) insGlobevt(csound, evt); /* RM: & optionally send to all remotes */ } break; case 'a': { int64_t kCnt; kCnt = (int64_t) ((double) csound->ekr * (double) evt->p[3] + 0.5); if (kCnt > csound->advanceCnt) { csound->advanceCnt = kCnt; csound->Message(csound, Str("time advanced %5.3f beats by score request\n"), evt->p3orig); } } break; } csound->currevent = saved_currevent; return 0; } /* RM: this now broken out for access from process_rt_event & sensevents -- bv */ static void process_midi_event(CSOUND *csound, MEVENT *mep, MCHNBLK *chn) { int n, insno = chn->insno; if (mep->type == NOTEON_TYPE && mep->dat2) { /* midi note ON: */ if (UNLIKELY((n = MIDIinsert(csound, insno, chn, mep)))) { /* alloc,init,activ */ csound->Message(csound, Str("\t\t T%7.3f - note deleted. "), csound->curp2); { char *name = csound->engineState.instrtxtp[insno]->insname; if (name) csound->Message(csound, Str("instr %s had %d init errors\n"), name, n); else csound->Message(csound, Str("instr %d had %d init errors\n"), insno, n); } csound->perferrcnt++; } } else { /* else midi note OFF: */ INSDS *ip = chn->kinsptr[mep->dat1]; if (ip == NULL) /* if already off, done */ csound->Mxtroffs++; else if (chn->sustaining) { /* if sustain pedal on */ while (ip != NULL && ip->m_sust) ip = ip->nxtolap; if (ip != NULL) { ip->m_sust = 1; /* let the note ring */ chn->ksuscnt++; } else csound->Mxtroffs++; } else xturnoff(csound, ip); /* else some kind of off */ } } static int process_rt_event(CSOUND *csound, int sensType) { EVTBLK *evt; int retval, insno, rfd; retval = 0; if (csound->curp2 * csound->esr < (double)csound->icurTime) { csound->curp2 = (double)csound->icurTime/csound->esr; print_amp_values(csound, 0); } if (sensType == 4) { /* RM: Realtime orc event */ EVTNODE *e = csound->OrcTrigEvts; /* RM: Events are sorted on insertion, so just check the first */ evt = &(e->evt); insno = MYFLT2LONG(evt->p[1]); if ((rfd = getRemoteInsRfd(csound, insno))) { if (rfd == GLOBAL_REMOT) insGlobevt(csound, evt); /* RM: do a global send and allow local */ else insSendevt(csound, evt, rfd); /* RM: or send to single remote Csound */ return 0; } /* pop from the list */ csound->OrcTrigEvts = e->nxt; retval = process_score_event(csound, evt, 1); if (evt->strarg != NULL) { csound->Free(csound, evt->strarg); evt->strarg = NULL; } /* push back to free alloc stack so it can be reused later */ e->nxt = csound->freeEvtNodes; csound->freeEvtNodes = e; } else if (sensType == 2) { /* Midievent: */ MEVENT *mep; MCHNBLK *chn; /* realtime or Midifile */ mep = csound->midiGlobals->Midevtblk; chn = csound->m_chnbp[mep->chan]; if ((rfd = getRemoteChnRfd(csound, mep->chan+1))) { /* RM: USE CHAN + 1 */ if (rfd == GLOBAL_REMOT) MIDIGlobevt(csound, mep); else MIDIsendevt(csound, mep, rfd); return 0; } else /* RM: this part is broken out -- bv */ process_midi_event(csound, mep, chn); } return retval; } #define RNDINT64(x) ((int64_t) ((double) (x) + ((double) (x) < 0.0 ? -0.5 : 0.5))) extern int sensMidi(CSOUND *); /* sense events for one k-period */ /* return value is one of the following: */ /* 0: continue performance */ /* 1: terminate (e.g. end of MIDI file) */ /* 2: normal end of score */ int sensevents(CSOUND *csound) { EVTBLK *e; OPARMS *O = csound->oparms; int retval, sensType; int conn, *sinp; csdebug_data_t *data = (csdebug_data_t *) csound->csdebug_data; if (UNLIKELY(data && data->status == CSDEBUG_STATUS_STOPPED)) { return 0; /* don't process events if we're in debug mode and stopped */ } if (UNLIKELY(csound->MTrkend && O->termifend)) { /* end of MIDI file: */ deactivate_all_notes(csound); csound->Message(csound, Str("terminating.\n")); return 1; /* abort with perf incomplete */ } /* if turnoffs pending, remove any expired instrs */ if (UNLIKELY(csound->frstoff != NULL)) { double tval; /* the following comparisons must match those in schedofftim() */ if (O->Beatmode) { tval = csound->curBeat + (0.505 * csound->curBeat_inc); if (csound->frstoff->offbet <= tval) beatexpire(csound, tval); } else { tval = ((double)csound->icurTime + csound->ksmps * 0.505)/csound->esr; if (csound->frstoff->offtim <= tval) timexpire(csound, tval); } } e = &(csound->evt); if (--(csound->cyclesRemaining) <= 0) { /* if done performing score segment: */ if (!csound->cyclesRemaining) { csound->prvbt = csound->curbt; /* update beats and times */ csound->curbt = csound->nxtbt; csound->curp2 = csound->nxtim; print_amp_values(csound, 1); /* print amplitudes for this segment */ } else /* this should only happen at */ csound->cyclesRemaining = 0; /* beginning of performance */ } retest: while (csound->cyclesRemaining <= 0) { /* read each score event: */ if (e->opcod != '\0') { /* if there is a pending score event, handle it now */ switch (e->opcod) { case 'e': /* end of score, */ case 'l': /* lplay list, */ case 's': /* or section: */ if (csound->frstoff != NULL) { /* if still have notes with finite length, wait until all are turned off */ csound->nxtim = csound->frstoff->offtim; csound->nxtbt = csound->frstoff->offbet; break; } /* end of: 1: section, 2: score, 3: lplay list */ retval = (e->opcod == 'l' ? 3 : (e->opcod == 's' ? 1 : 2)); goto scode; default: /* q, i, f, a: */ process_score_event(csound, e, 0);/* handle event now */ e->opcod = '\0'; /* and get next one */ continue; } } else { /* else read next score event */ if (UNLIKELY(O->usingcscore)) { /* get next lplay event */ /* FIXME: this may be non-portable */ if (STA(ep) < STA(epend)) /* nxt event */ memcpy((void*) e, (void*) &((*STA(ep)++)->strarg), sizeof(EVTBLK)); else /* else lcode */ memcpy((void*) e, (void*) &(STA(lsect)->strarg), sizeof(EVTBLK)); } else if (!(rdscor(csound, e))) /* or rd nxt evt from scstr */ e->opcod = 'e'; csound->currevent = e; switch (e->opcod) { case 'w': if (!O->Beatmode) /* Not beatmode: read 'w' */ settempo(csound, (double)e->p2orig); /* to init the tempo */ continue; /* for this section */ case 'q': case 'i': case 'd': case 'f': case 'a': csound->nxtim = (double) e->p[2] + csound->timeOffs; csound->nxtbt = (double) e->p2orig + csound->beatOffs; if (e->opcod=='i'||e->opcod=='d') if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, "new event: %16.13lf %16.13lf\n", csound->nxtim, csound->nxtbt); break; case 'e': case 'l': case 's': continue; default: csound->Message(csound, Str("error in score. illegal opcode %c (ASCII %d)\n"), e->opcod, e->opcod); csound->perferrcnt++; continue; } } /* calculate the number of k-periods remaining until next event */ if (!O->sampleAccurate) { if (O->Beatmode) csound->cyclesRemaining = RNDINT64((csound->nxtbt - csound->curBeat) / csound->curBeat_inc); else { csound->cyclesRemaining = RNDINT64((csound->nxtim*csound->esr - csound->icurTime)/csound->ksmps); csound->nxtim = (csound->cyclesRemaining*csound->ksmps+csound->icurTime)/csound->esr; } } else { /* VL 30-11-2012 new code for sample-accurate timing needs to truncate cyclesRemaining */ if (O->Beatmode) csound->cyclesRemaining = (int64_t) ((csound->nxtbt - csound->curBeat) / csound->curBeat_inc); else { csound->cyclesRemaining = (int64_t) FLOOR((csound->nxtim*csound->esr - csound->icurTime+csound->onedsr*0.5) / csound->ksmps); csound->nxtim = (csound->cyclesRemaining*csound->ksmps+csound->icurTime)/csound->esr; } } } /* handle any real time events now: */ /* FIXME: the initialisation pass of real time */ /* events is not sorted by instrument number */ /* (although it never was sorted anyway...) */ if (UNLIKELY(O->RTevents || getRemoteSocksIn(csound))) { int nrecvd; /* run all registered callback functions */ if (csound->evtFuncChain != NULL && !csound->advanceCnt) { EVT_CB_FUNC *fp = (EVT_CB_FUNC*) csound->evtFuncChain; do { fp->func(csound, fp->userData); fp = fp->nxt; } while (fp != NULL); } /* check for pending real time events */ while (csound->OrcTrigEvts != NULL && csound->OrcTrigEvts->start_kcnt <= (uint32) csound->global_kcounter) { if ((retval = process_rt_event(csound, 4)) != 0) goto scode; } /* RM */ if ((sinp = getRemoteSocksIn(csound))) { while ((conn = *sinp++)) { while ((nrecvd = SVrecv(csound, conn, (void*)&(csound->SVrecvbuf), sizeof(REMOT_BUF) )) > 0) { int lentot = 0; do { REMOT_BUF *bp = (REMOT_BUF*)((char*)(&(csound->SVrecvbuf))+lentot); if (bp->type == SCOR_EVT) { EVTBLK *evt = (EVTBLK*)bp->data; evt->p[2] = (double)csound->icurTime/csound->esr; if ((retval = process_score_event(csound, evt, 1)) != 0) { e->opcod = evt->opcod; /* pass any s, e, or l */ goto scode; } } else if (bp->type == MIDI_EVT) { MEVENT *mep = (MEVENT *)bp->data; MCHNBLK *chn = csound->m_chnbp[mep->chan]; process_midi_event(csound, mep, chn); } else if (bp->type == MIDI_MSG) { MEVENT *mep = (MEVENT *)bp->data; if (UNLIKELY(mep->type == 0xFF && mep->dat1 == 0x2F)) { csound->MTrkend = 1; /* catch a Trkend */ csound->Message(csound, "SERVER%c: ", remoteID(csound)); csound->Message(csound, "caught a Trkend\n"); /*csoundCleanup(csound); exit(0);*/ return 2; /* end of performance */ } else m_chanmsg(csound, mep); /* or a chan msg */ } lentot+=bp->len; } while (lentot < nrecvd); } } } /* MIDI note messages */ if (O->Midiin || O->FMidiin) while ((sensType = sensMidi(csound)) != 0) if ((retval = process_rt_event(csound, sensType)) != 0) goto scode; } /* no score event at this time, return to continue performance */ return 0; scode: /* end of section (retval == 1), score (retval == 2), */ /* or lplay list (retval == 3) */ if (getRemoteInsRfdCount(csound)) insGlobevt(csound, e);/* RM: send s,e, or l to any remotes */ e->opcod = '\0'; if (retval == 3) { section_amps(csound, 2); return 1; } /* for s, or e after s */ if (retval == 1 || (retval == 2 && STA(sectno) > 1)) { delete_pending_rt_events(csound); if (O->Beatmode) csound->curbt = csound->curBeat; csound->curp2 = csound->nxtim = csound->timeOffs = csound->icurTime/csound->esr; csound->prvbt = csound->nxtbt = csound->beatOffs = csound->curbt; section_amps(csound, 1); } else{ section_amps(csound, 0); } if (retval == 1) { /* if s code, */ orcompact(csound); /* rtn inactiv spc */ if (csound->actanchor.nxtact == NULL) /* if no indef ins */ rlsmemfiles(csound); /* purge memfiles */ csound->Message(csound, Str("SECTION %d:\n"), ++STA(sectno)); goto retest; /* & back for more */ } return 2; /* done with entire score */ } static inline uint64_t time2kcnt(CSOUND *csound, double tval) { if (tval > 0.0) { tval *= (double) csound->ekr; #ifdef HAVE_C99 return (uint64_t) llrint(tval); #else return (uint64_t) (tval + 0.5); #endif } return 0UL; } /* Schedule new score event to be played. 'time_ofs' is the amount of */ /* time in seconds to add to evt->p[2] to get the actual start time */ /* of the event (measured from the beginning of performance, and not */ /* section) in seconds. */ /* Required parameters in 'evt': */ /* char *strarg string argument of event (NULL if none) */ /* char opcod event opcode (a, e, f, i, l, q, s) */ /* int16 pcnt number of p-fields (>=3 for q, i, a; >=4 for f) */ /* MYFLT p[] array of p-fields, p[1]..p[pcnt] should be set */ /* p2orig and p3orig are calculated from p[2] and p[3]. */ /* The contents of 'evt', including the string argument, need not be */ /* preserved after calling this function, as a copy of the event is */ /* made. */ /* Return value is zero on success. */ int insert_score_event_at_sample(CSOUND *csound, EVTBLK *evt, int64_t time_ofs) { double start_time; EVTNODE *e, *prv; CSOUND *st = csound; MYFLT *p; uint32 start_kcnt; int i, retval; retval = -1; /* make a copy of the event... */ if (csound->freeEvtNodes != NULL) { /* pop alloc from stack */ e = csound->freeEvtNodes; /* if available */ csound->freeEvtNodes = e->nxt; } else { e = (EVTNODE*) csound->Calloc(csound, sizeof(EVTNODE)); /* or alloc new one */ if (UNLIKELY(e == NULL)) return CSOUND_MEMORY; } if (evt->strarg != NULL) { /* copy string argument if present */ /* NEED TO COPY WHOLE STRING STRUCTURE */ int n = evt->scnt; char *p = evt->strarg; while (n--) { p += strlen(p)+1; }; e->evt.strarg = (char*) csound->Malloc(csound, (size_t) (p-evt->strarg)+1); if (UNLIKELY(e->evt.strarg == NULL)) { csound->Free(csound, e); return CSOUND_MEMORY; } memcpy(e->evt.strarg, evt->strarg, p-evt->strarg+1 ); e->evt.scnt = evt->scnt; } e->evt.pinstance = evt->pinstance; e->evt.opcod = evt->opcod; e->evt.pcnt = evt->pcnt; p = &(e->evt.p[0]); i = 0; while (++i <= evt->pcnt) /* copy p-field list */ p[i] = evt->p[i]; /* ...and use the copy from now on */ evt = &(e->evt); /* check for required p-fields */ switch (evt->opcod) { case 'f': if (UNLIKELY((evt->pcnt < 4) && (p[1]>0))) goto pfld_err; goto cont; case 'i': case 'q': case 'a': if (UNLIKELY(evt->pcnt < 3)) goto pfld_err; /* fall through */ case 'd': cont: /* calculate actual start time in seconds and k-periods */ start_time = (double) p[2] + (double)time_ofs/csound->esr; start_kcnt = time2kcnt(csound, start_time); /* correct p2 value for section offset */ p[2] = (MYFLT) (start_time - st->timeOffs); if (p[2] < FL(0.0)) p[2] = FL(0.0); /* start beat: this is possibly wrong */ evt->p2orig = (MYFLT) (((start_time - st->icurTime/st->esr) / st->ibeatTime) + (st->curBeat - st->beatOffs)); if (evt->p2orig < FL(0.0)) evt->p2orig = FL(0.0); evt->p3orig = p[3]; break; default: start_kcnt = 0UL; /* compiler only */ } switch (evt->opcod) { case 'i': /* note event */ case 'd': /* calculate the length in beats */ if (evt->p3orig > FL(0.0)) evt->p3orig = (MYFLT) ((double) evt->p3orig / st->ibeatTime); /* fall through */ case 'q': /* mute instrument */ /* check for a valid instrument number or name */ if (evt->opcod=='d') { if (evt->strarg != NULL && csound->ISSTRCOD(p[1])) { i = (int) named_instr_find(csound, evt->strarg); //printf("d opcode %s -> %d\n", evt->strarg, i); p[1] = -i; } else { i = (int) fabs((double) p[1]); p[1] = -i; } } else if (evt->strarg != NULL && csound->ISSTRCOD(p[1])) { i = (int) named_instr_find(csound, evt->strarg); if (i<0) {p[1]=i; i= -i;} } else i = (int) fabs((double) p[1]); if (UNLIKELY((unsigned int) (i - 1) >= (unsigned int) csound->engineState.maxinsno || csound->engineState.instrtxtp[i] == NULL)) { csoundMessage(csound, Str("insert_score_event(): invalid instrument " "number or name %d\n" ), i); goto err_return; } break; case 'a': /* advance score time */ /* calculate the length in beats */ evt->p3orig = (MYFLT) ((double) evt->p3orig *csound->esr/ st->ibeatTime); /* fall through */ case 'f': /* function table */ break; case 'e': /* end of score, */ case 'l': /* lplay list, */ case 's': /* section: */ start_time = (double)time_ofs/csound->esr; if (evt->pcnt >= 2) start_time += (double) p[2]; evt->pcnt = 0; start_kcnt = time2kcnt(csound, start_time); break; default: csoundMessage(csound, Str("insert_score_event(): unknown opcode: %c\n"), evt->opcod); goto err_return; } /* queue new event */ e->start_kcnt = start_kcnt; prv = csound->OrcTrigEvts; /* if list is empty, or at beginning of list: */ if (prv == NULL || start_kcnt < prv->start_kcnt) { e->nxt = prv; csound->OrcTrigEvts = e; } else { /* otherwise sort by time */ while (prv->nxt != NULL && start_kcnt >= prv->nxt->start_kcnt) prv = prv->nxt; e->nxt = prv->nxt; prv->nxt = e; } /* Make sure sensevents() looks for RT events */ csound->oparms->RTevents = 1; return 0; pfld_err: csoundMessage(csound, Str("insert_score_event(): insufficient p-fields\n")); err_return: /* clean up */ if (e->evt.strarg != NULL) csound->Free(csound, e->evt.strarg); e->evt.strarg = NULL; e->nxt = csound->freeEvtNodes; csound->freeEvtNodes = e; return retval; } int insert_score_event(CSOUND *csound, EVTBLK *evt, double time_ofs) { return insert_score_event_at_sample(csound, evt, time_ofs*csound->esr); } /* called by csoundRewindScore() to reset performance to time zero */ void musmon_rewind_score(CSOUND *csound) { /* deactivate all currently playing notes */ deactivate_all_notes(csound); /* flush any pending real time events */ delete_pending_rt_events(csound); if (csound->global_kcounter != 0L) { /* reset score time */ csound->global_kcounter = csound->kcounter = 0L; csound->nxtbt = csound->curbt = csound->prvbt = 0.0; csound->nxtim = csound->curp2 = 0.0; csound->beatOffs = csound->timeOffs = 0.0; csound->curBeat = 0.0; csound->icurTime = 0L; csound->cyclesRemaining = 0; csound->evt.strarg = NULL; csound->evt.scnt = 0; csound->evt.opcod = '\0'; /* reset tempo */ if (csound->oparms->Beatmode) settempo(csound, csound->oparms->cmdTempo); else settempo(csound, 60.0); /* update section/overall amplitudes, reset to section 1 */ section_amps(csound, 1); STA(sectno) = 1; csound->Message(csound, Str("SECTION %d:\n"), STA(sectno)); } /* apply score offset if non-zero */ csound->advanceCnt = 0; if (csound->csoundScoreOffsetSeconds_ > FL(0.0)) csoundSetScoreOffsetSeconds(csound, csound->csoundScoreOffsetSeconds_); if (csound->scstr) corfile_rewind(csound->scstr); else csound->Warning(csound, Str("cannot rewind score: no score in memory \n")); } /** * Register a function to be called once in every control period * by sensevents(). Any number of functions may be registered, * and will be called in the order of registration. * The callback function takes two arguments: the Csound instance * pointer, and the userData pointer as passed to this function. * Returns zero on success. */ PUBLIC int csoundRegisterSenseEventCallback(CSOUND *csound, void (*func)(CSOUND *, void *), void *userData) { EVT_CB_FUNC *fp = (EVT_CB_FUNC*) csound->evtFuncChain; if (fp == NULL) { fp = (EVT_CB_FUNC*) csound->Calloc(csound, sizeof(EVT_CB_FUNC)); csound->evtFuncChain = (void*) fp; } else { while (fp->nxt != NULL) fp = fp->nxt; fp->nxt = (EVT_CB_FUNC*) csound->Calloc(csound, sizeof(EVT_CB_FUNC)); fp = fp->nxt; } if (UNLIKELY(fp == NULL)) return CSOUND_MEMORY; fp->func = func; fp->userData = userData; fp->nxt = NULL; csound->oparms->RTevents = 1; return 0; } csound-6.10.0/Engine/namedins.c000066400000000000000000000262131321653344700162540ustar00rootroot00000000000000/* namedins.c: Copyright (C) 2002, 2005, 2006 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "namedins.h" #include "csound_orc_semantics.h" #include /* check if the string s is a valid instrument or opcode name */ /* return value is zero if the string is not a valid name */ int check_instr_name(char *s) { char *c = s; if (UNLIKELY(!*c)) return 0; /* empty */ if (UNLIKELY(!isalpha(*c) && *c != '_')) return 0; /* chk if 1st char is valid */ while (*++c) if (UNLIKELY(!isalnum(*c) && *c != '_')) return 0; return 1; /* no errors */ } /* find the instrument number for the specified name */ /* return value is zero if none was found */ int32 named_instr_find(CSOUND *csound, char *s) { INSTRNAME *inm; int ss = (*s=='-'?1:0); if (!csound->engineState.instrumentNames) return 0L; /* no named instruments defined */ /* now find instrument */ inm = cs_hash_table_get(csound, csound->engineState.instrumentNames, s+ss); return (inm == NULL) ? 0L : (ss ? -inm->instno : inm->instno); } /* convert opcode string argument to instrument number */ /* return value is -1 if the instrument cannot be found */ /* (in such cases, csoundInitError() is also called) */ int32 strarg2insno(CSOUND *csound, void *p, int is_string) { int32 insno; if (is_string) { if (UNLIKELY((insno = named_instr_find(csound, (char*) p)) <= 0)) { csound->Warning(csound, Str("instr %s not found"), (char*) p); return -1; } } else { /* numbered instrument */ insno = (int32) *((MYFLT*) p); if (UNLIKELY(insno < 1 || insno > csound->engineState.maxinsno || !csound->engineState.instrtxtp[insno])) { csound->Warning(csound, Str("Cannot Find Instrument %d"), (int) insno); return -1; } } return insno; } /* same as strarg2insno, but runs at perf time, */ /* and does not support numbered instruments */ /* (used by opcodes like event or schedkwhen) */ int32 strarg2insno_p(CSOUND *csound, char *s) { int32 insno; if (UNLIKELY(!(insno = named_instr_find(csound, s)))) { csound->ErrorMsg(csound, Str("instr %s not found"), s); return -1; } return insno; } /* convert opcode string argument to instrument number */ /* (also allows user defined opcode names); if the integer */ /* argument is non-zero, only opcode names are searched */ /* return value is -1 if the instrument cannot be found */ /* (in such cases, csoundInitError() is also called) */ int32 strarg2opcno(CSOUND *csound, void *p, int is_string, int force_opcode) { int32 insno = 0; if (!force_opcode) { /* try instruments first, if enabled */ if (is_string) { insno = named_instr_find(csound, (char*) p); } else { /* numbered instrument */ insno = (int32) *((MYFLT*) p); if (UNLIKELY(insno < 1 || insno > csound->engineState.maxinsno || !csound->engineState.instrtxtp[insno])) { csound->InitError(csound, Str("Cannot Find Instrument %d"), (int) insno); return -1; } } } if (!insno && is_string) { /* if no instrument was found, */ OPCODINFO *inm = csound->opcodeInfo; /* search for user opcode */ while (inm && sCmp(inm->name, (char*) p)) inm = inm->prv; if (inm) insno = (int32) inm->instno; } if (UNLIKELY(insno < 1)) { csound->InitError(csound, Str("cannot find the specified instrument or opcode")); insno = -1; } return insno; } /* create file name from opcode argument (string or MYFLT) */ /* CSOUND *csound: */ /* pointer to Csound instance */ /* char *s: */ /* output buffer, should have enough space; if NULL, the */ /* required amount of memory is allocated and returned */ /* void *p: */ /* opcode argument, is interpreted as char* or MYFLT*, */ /* depending on the 'is_string' parameter */ /* const char *baseName: */ /* name prefix to be used if the 'p' argument is MYFLT, */ /* and it is neither SSTRCOD, nor a valid index to strset */ /* space. */ /* For example, if "soundin." is passed as baseName, file */ /* names in the format "soundin.%d" will be generated. */ /* baseName may be an empty string, but should not be NULL */ /* int is_string: */ /* if non-zero, 'p' is interpreted as a char* pointer and */ /* is used as the file name. Otherwise, it is expected to */ /* point to a MYFLT value, and the following are tried: */ /* 1. if the value is SSTRCOD, the string argument of */ /* the current score event is used (string p-field) */ /* 2. if the value, rounded to the nearest integer, is a */ /* valid index to strset space, the strset string is */ /* used */ /* 3. the file name is generated using baseName and the */ /* value rounded to the nearest integer, as described */ /* above */ /* return value: */ /* pointer to the output string; if 's' is not NULL, it is */ /* always the same as 's', otherwise it is allocated with */ /* csound->Malloc() and the caller is responsible for */ /* freeing the allocated memory with csound->Free() or */ /* csound->Free() */ char *strarg2name(CSOUND *csound, char *s, void *p, const char *baseName, int is_string) { if (is_string) { /* opcode string argument */ if (s == NULL) s = csound->Malloc(csound, strlen((char*) p) + 1); strcpy(s, (char*) p); } else if (csound->ISSTRCOD(*((MYFLT*) p))) { /* p-field string, unquote and copy */ char *s2 = get_arg_string(csound, *((MYFLT*)p)); int i = 0; //printf("strarg2name: %g %s\n", *((MYFLT*)p), s2); if (s == NULL) s = csound->Malloc(csound, strlen(s2) + 1); if (*s2 == '"') s2++; while (*s2 != '"' && *s2 != '\0') s[i++] = *(s2++); s[i] = '\0'; } else { int i = (int) ((double) *((MYFLT*) p) + (*((MYFLT*) p) >= FL(0.0) ? 0.5 : -0.5)); if (i >= 0 && i <= (int) csound->strsmax && csound->strsets != NULL && csound->strsets[i] != NULL) { if (s == NULL) s = csound->Malloc(csound, strlen(csound->strsets[i]) + 1); strcpy(s, csound->strsets[i]); } else { int n; if (s == NULL) { /* allocate +20 characters, assuming sizeof(int) <= 8 */ s = csound->Malloc(csound, n = strlen(baseName) + 21); snprintf(s, n, "%s%d", baseName, i); } else sprintf(s, "%s%d", baseName, i); /* dubious */ } } return s; } /* ----------------------------------------------------------------------- */ /* the following functions are for efficient management of the opcode list */ /* -------- IV - Jan 29 2005 -------- */ /** * Allocate nbytes bytes of memory that can be accessed later by calling * csoundQueryGlobalVariable() with the specified name; the space is * cleared to zero. * Returns CSOUND_SUCCESS on success, CSOUND_ERROR in case of invalid * parameters (zero nbytes, invalid or already used name), or * CSOUND_MEMORY if there is not enough memory. */ PUBLIC int csoundCreateGlobalVariable(CSOUND *csound, const char *name, size_t nbytes) { void* p; /* create new empty database if it does not exist yet */ if (UNLIKELY(csound->namedGlobals == NULL)) { csound->namedGlobals = cs_hash_table_create(csound); if (UNLIKELY(csound->namedGlobals == NULL)) return CSOUND_MEMORY; } /* check for valid parameters */ if (UNLIKELY(name == NULL)) return CSOUND_ERROR; if (UNLIKELY(name[0] == '\0')) return CSOUND_ERROR; if (UNLIKELY(nbytes < (size_t) 1 || nbytes >= (size_t) 0x7F000000L)) return CSOUND_ERROR; if (cs_hash_table_get(csound, csound->namedGlobals, (char*)name) != NULL) return CSOUND_ERROR; p = csound->Calloc(csound, nbytes); if (UNLIKELY(p == NULL)) return CSOUND_MEMORY; cs_hash_table_put(csound, csound->namedGlobals, (char*)name, p); return CSOUND_SUCCESS; } /** * Get pointer to space allocated with the name "name". * Returns NULL if the specified name is not defined. */ PUBLIC void *csoundQueryGlobalVariable(CSOUND *csound, const char *name) { /* check if there is an actual database to search */ if (csound->namedGlobals == NULL) return NULL; /* check for a valid name */ if (UNLIKELY(name == NULL)) return NULL; if (UNLIKELY(name[0] == '\0')) return NULL; return cs_hash_table_get(csound, csound->namedGlobals, (char*) name); } /** * This function is the same as csoundQueryGlobalVariable(), except the * variable is assumed to exist and no error checking is done. * Faster, but may crash or return an invalid pointer if 'name' is * not defined. */ PUBLIC void *csoundQueryGlobalVariableNoCheck(CSOUND *csound, const char *name) { return cs_hash_table_get(csound, csound->namedGlobals, (char*) name); } /** * Free memory allocated for "name" and remove "name" from the database. * Return value is CSOUND_SUCCESS on success, or CSOUND_ERROR if the name is * not defined. */ PUBLIC int csoundDestroyGlobalVariable(CSOUND *csound, const char *name) { void *p = cs_hash_table_get(csound, csound->namedGlobals, (char*)name); if (UNLIKELY(p == NULL)) return CSOUND_ERROR; csound->Free(csound, p); cs_hash_table_remove(csound, csound->namedGlobals, (char*) name); return CSOUND_SUCCESS; } /** * Free entire global variable database. This function is for internal use * only (e.g. by RESET routines). */ void csoundDeleteAllGlobalVariables(CSOUND *csound) { if (csound == NULL || csound->namedGlobals == NULL) return; cs_hash_table_mfree_complete(csound, csound->namedGlobals); csound->namedGlobals = NULL; } csound-6.10.0/Engine/new_orc_parser.c000066400000000000000000000264571321653344700175000ustar00rootroot00000000000000/* new_orc_parser.c: Copyright (C) 2006 Steven Yi Modifications 2009 by Christopher Wilson for multicore This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "csound_orc.h" #include "corfile.h" #if defined(HAVE_DIRENT_H) # include # if 0 && defined(__MACH__) typedef void* DIR; DIR opendir(const char *); struct dirent *readdir(DIR*); int closedir(DIR*); # endif #endif #if defined(WIN32) && !defined(__CYGWIN__) # include # include #endif extern void csound_orcrestart(FILE*, void *); extern int csound_orcdebug; extern void print_csound_predata(void *); extern int csound_prelex_init(void *); extern void csound_preset_extra(void *, void *); extern int csound_prelex(CSOUND*, void*); extern int csound_prelex_destroy(void *); extern void csound_orc_scan_buffer (const char *, size_t, void*); extern int csound_orcparse(PARSE_PARM *, void *, CSOUND*, TREE**); extern int csound_orclex_init(void *); extern void csound_orcset_extra(void *, void *); extern void csound_orcset_lineno(int, void*); extern int csound_orclex_destroy(void *); extern void init_symbtab(CSOUND*); extern void print_tree(CSOUND *, char *, TREE *); extern TREE* verify_tree(CSOUND *, TREE *, TYPE_TABLE*); extern TREE *csound_orc_expand_expressions(CSOUND *, TREE *); extern TREE* csound_orc_optimize(CSOUND *, TREE *); //extern void csp_orc_analyze_tree(CSOUND* csound, TREE* root); extern void csp_orc_sa_print_list(CSOUND*); #if 0 static void csound_print_preextra(CSOUND *csound, PRE_PARM *x) { csound->DebugMsg(csound,"********* Extra Pre Data %p *********\n", x); csound->DebugMsg(csound,"macros = %p, macro_stack_ptr = %u, ifdefStack=%p,\n" "isIfndef=%d\n, line=%d\n", x->macros, x->macro_stack_ptr, x->ifdefStack, x->isIfndef, x->line); csound->DebugMsg(csound,"******************\n"); } #endif uint64_t make_location(PRE_PARM *qq) { int d = qq->depth; uint64_t loc = 0; int n = (d>8?d-7:0); for (; n<=d; n++) { loc = (loc<<8)+(qq->lstack[n]); } return loc; } // Code to add #includes of UDOs static void add_include_udo_dir(CSOUND *csound, CORFIL *xx) { #if defined(HAVE_DIRENT_H) char *dir = getenv("CS_UDO_DIR"); char buff[1024]; if (dir) { DIR *udo = opendir(dir); printf(Str("** found CS_UDO_DIR=%s\n"), dir); if (udo) { struct dirent *f; //printf("**and it opens\n"); strcpy(buff, "#line 0\n"); while ((f = readdir(udo)) != NULL) { char *fname = &(f->d_name[0]); int n = (int)strlen(fname); //printf("** name=%s n=%d\n", fname, n); if (n>4 && (strcmp(&fname[n-4], ".udo")==0)) { strlcat(buff, "#include \"", 1024); strlcat(buff, dir, 1024); strlcat(buff, "/", 1024); strlcat(buff, fname, 1024); strlcat(buff, "\"\n", 1024); if (strlen(buff)>768) { corfile_preputs(csound, buff, xx); buff[0] ='\0'; } } } closedir(udo); strlcat(buff, "###\n", 1024); corfile_preputs(csound, buff, xx); } } //printf("Giving\n%s", corfile_body(xx)); #endif } TREE *csoundParseOrc(CSOUND *csound, const char *str) { int err; OPARMS *O = csound->oparms; csound->parserNamedInstrFlag = 2; { PRE_PARM qq; /* Preprocess */ memset(&qq, 0, sizeof(PRE_PARM)); //csp_orc_sa_print_list(csound); csound_prelex_init(&qq.yyscanner); csound_preset_extra(&qq, qq.yyscanner); qq.line = csound->orcLineOffset; csound->expanded_orc = corfile_create_w(csound); file_to_int(csound, "**unknown**"); if (str==NULL) { char bb[80]; if (UNLIKELY(csound->orchstr==NULL && !csound->oparms->daemon)) csound->Die(csound, Str("parser: failed to open input file %s\n"), csound->orchname); else if (csound->orchstr==NULL && csound->oparms->daemon) return NULL; add_include_udo_dir(csound, csound->orchstr); if (csound->orchname==NULL || csound->orchname[0]=='\0') csound->orchname = csound->csdname; /* We know this is the start so stack is empty so far */ snprintf(bb, 80, "#source %d\n", qq.lstack[0] = file_to_int(csound, csound->orchname)); corfile_puts(csound, bb, csound->expanded_orc); snprintf(bb, 80, "#line %d\n", csound->orcLineOffset); corfile_puts(csound, bb, csound->expanded_orc); } else { char bb[80]; if (csound->orchstr == NULL || corfile_body(csound->orchstr) == NULL) csound->orchstr = corfile_create_w(csound); else corfile_reset(csound->orchstr); snprintf(bb, 80, "#line %d\n", csound->orcLineOffset); corfile_puts(csound, bb, csound->orchstr); corfile_puts(csound, str, csound->orchstr); corfile_puts(csound, "\n#exit\n", csound->orchstr); corfile_putc(csound, '\0', csound->orchstr); corfile_putc(csound, '\0', csound->orchstr); } csound->DebugMsg(csound, "Calling preprocess on >>%s<<\n", corfile_body(csound->orchstr)); //csound->DebugMsg(csound,"FILE: %s \n", csound->orchstr->body); // csound_print_preextra(&qq); cs_init_math_constants_macros(csound, &qq); cs_init_omacros(csound, &qq, csound->omacros); // csound_print_preextra(&qq); csound_prelex(csound, qq.yyscanner); if (UNLIKELY(qq.ifdefStack != NULL)) { csound->Message(csound, Str("Unmatched #ifdef\n")); csound->LongJmp(csound, 1); } csound_prelex_destroy(qq.yyscanner); csound->DebugMsg(csound, "yielding >>%s<<\n", corfile_body(csound->expanded_orc)); corfile_rm(csound, &csound->orchstr); } { /* VL 15.3.2015 allocating memory here will cause unwanted growth. We just pass a pointer, which will be allocated by make leaf */ TREE* astTree = NULL; TREE* newRoot; PARSE_PARM pp; TYPE_TABLE* typeTable = NULL; /* Parse */ memset(&pp, '\0', sizeof(PARSE_PARM)); init_symbtab(csound); csound_orcdebug = O->odebug; csound_orclex_init(&pp.yyscanner); csound_orcset_extra(&pp, pp.yyscanner); csound_orc_scan_buffer(corfile_body(csound->expanded_orc), corfile_tell(csound->expanded_orc), pp.yyscanner); //csound_orcset_lineno(csound->orcLineOffset, pp.yyscanner); //printf("%p \n", astTree); err = csound_orcparse(&pp, pp.yyscanner, csound, &astTree); //printf("%p \n", astTree); //print_tree(csound, "AST - AFTER csound_orcparse()\n", astTree); //csp_orc_sa_cleanup(csound); corfile_rm(csound, &csound->expanded_orc); if (UNLIKELY(csound->oparms->odebug)) csp_orc_sa_print_list(csound); if (UNLIKELY(csound->synterrcnt)) err = 3; if (LIKELY(err == 0)) { if (csound->oparms->odebug) csound->Message(csound, Str("Parsing successful!\n")); } else { if (err == 1){ csound->Message(csound, Str("Parsing failed due to invalid input!\n")); } else if (err == 2){ csound->Message(csound, Str("Parsing failed due to memory exhaustion!\n")); } else if (err == 3){ csound->Message(csound, Str("Parsing failed due to %d syntax error%s!\n"), csound->synterrcnt, csound->synterrcnt==1?"":"s"); } goto ending; } if (UNLIKELY(PARSER_DEBUG)) { print_tree(csound, "AST - INITIAL\n", astTree); } typeTable = csound->Malloc(csound, sizeof(TYPE_TABLE)); typeTable->udos = NULL; typeTable->globalPool = csoundCreateVarPool(csound); typeTable->instr0LocalPool = csoundCreateVarPool(csound); typeTable->localPool = typeTable->instr0LocalPool; typeTable->labelList = NULL; astTree = verify_tree(csound, astTree, typeTable); // csound->Free(csound, typeTable->instr0LocalPool); // csound->Free(csound, typeTable->globalPool); // csound->Free(csound, typeTable); //print_tree(csound, "AST - FOLDED\n", astTree); //FIXME - synterrcnt should not be global if (UNLIKELY(astTree == NULL || csound->synterrcnt)) { err = 3; if (astTree) csound->Message(csound, Str("Parsing failed due to %d semantic error%s!\n"), csound->synterrcnt, csound->synterrcnt==1?"":"s"); else if (csound->synterrcnt) csound->Message(csound, Str("Parsing failed due to syntax errors\n")); else csound->Message(csound, Str("Parsing failed due to no input!\n")); goto ending; } err = 0; //csp_orc_analyze_tree(csound, astTree); // astTree = csound_orc_expand_expressions(csound, astTree); // if (UNLIKELY(PARSER_DEBUG)) { print_tree(csound, "AST - AFTER VERIFICATION/EXPANSION\n", astTree); } ending: csound_orclex_destroy(pp.yyscanner); if (UNLIKELY(err)) { csound->ErrorMsg(csound, Str("Stopping on parser failure")); csoundDeleteTree(csound, astTree); if (typeTable != NULL) { csoundFreeVarPool(csound, typeTable->globalPool); if (typeTable->instr0LocalPool != NULL) { csoundFreeVarPool(csound, typeTable->instr0LocalPool); } if (typeTable->localPool != typeTable->instr0LocalPool) { csoundFreeVarPool(csound, typeTable->localPool); } csound->Free(csound, typeTable); } return NULL; } astTree = csound_orc_optimize(csound, astTree); //print_tree(csound, "AST after optmize", astTree); // small hack: use an extra node as head of tree list to hold the // typeTable, to be used during compilation newRoot = make_leaf(csound, 0, 0, 0, NULL); newRoot->markup = typeTable; newRoot->next = astTree; /* if (str!=NULL){ */ /* if (typeTable != NULL) { */ /* csoundFreeVarPool(csound, typeTable->globalPool); */ /* if (typeTable->instr0LocalPool != NULL) { */ /* csoundFreeVarPool(csound, typeTable->instr0LocalPool); */ /* } */ /* if (typeTable->localPool != typeTable->instr0LocalPool) { */ /* csoundFreeVarPool(csound, typeTable->localPool); */ /* } */ /* csound->Free(csound, typeTable); */ /* } */ /* } */ return newRoot; } } csound-6.10.0/Engine/parse_param.h000066400000000000000000000057621321653344700167630ustar00rootroot00000000000000/* parse-param.h: Copyright (C) 2012 John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __PARSE_PARAM_H #define __PARSE_PARAM_H #define MARGS (3) #define MAX_INCLUDE_DEPTH 100 struct MACRO; typedef struct MACRON { int n; unsigned int line; struct MACRO *s; } MACRON; typedef struct MACRO { /* To store active macros */ char *name; /* Use is by name */ int acnt; /* Count of arguments */ char *body; /* The text of the macro */ struct MACRO *next; /* Chain of active macros */ int margs; /* amount of space for args */ char *arg[MARGS]; /* With these arguments */ } MACRO; typedef struct IFDEFSTACK_ { struct IFDEFSTACK_ *prv; unsigned char isDef; /* non-zero if #ifdef is true, or #ifndef */ /* is false */ unsigned char isElse; /* non-zero between #else and #endif */ unsigned char isSkip; /* sum of: 1: skipping code due to this */ /* #ifdef, 2: skipping due to parent */ } IFDEFSTACK; typedef struct pre_parm_s { void *yyscanner; MACRO *macros; MACRON *alt_stack; //[MAX_INCLUDE_DEPTH]; unsigned int macro_stack_ptr; unsigned int macro_stack_size; IFDEFSTACK *ifdefStack; unsigned char isIfndef; unsigned char isString; uint16_t line; uint64_t locn; uint64_t llocn; uint16_t depth; uint16_t lstack[1024]; } PRE_PARM; typedef struct parse_parm_s { void *yyscanner; uint64_t locn; char *xstrbuff; int xstrptr,xstrmax; uint64_t iline; /* Line number for start of instrument */ uint64_t ilocn; /* and location */ } PARSE_PARM; void cs_init_math_constants_macros(CSOUND*, PRE_PARM*); void cs_init_omacros(CSOUND*, PRE_PARM*, NAMES*); uint64_t make_location(PRE_PARM *); extern uint8_t file_to_int(CSOUND*, const char*); extern void csound_orcput_ilocn(void *, uint64_t, uint64_t); extern uint64_t csound_orcget_iline(void *); extern uint64_t csound_orcget_ilocn(void *); #endif csound-6.10.0/Engine/pools.c000066400000000000000000000045161321653344700156140ustar00rootroot00000000000000/* pools.c: Copyright (C) 2012 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "pools.h" #include "csound_standard_types.h" /* MYFLT POOL */ MYFLT_POOL* myflt_pool_create(CSOUND* csound) { MYFLT_POOL* pool = csound->Malloc(csound, sizeof(MYFLT_POOL)); pool->count = 0; pool->max = POOL_SIZE; pool->values = csound->Calloc(csound, sizeof(CS_VAR_MEM) * POOL_SIZE); return pool; } void myflt_pool_free(CSOUND *csound, MYFLT_POOL *pool){ if (pool != NULL) { csound->Free(csound, pool->values); csound->Free(csound, pool); } } int myflt_pool_indexof(MYFLT_POOL* pool, MYFLT value) { int retVal = -1; int i; for (i = 0; i < pool->count; i++) { if (pool->values[i].value == value) { retVal = i; break; } } return retVal; } int myflt_pool_find_or_add(CSOUND* csound, MYFLT_POOL* pool, MYFLT value) { int index = myflt_pool_indexof(pool, value); if (index == -1) { if (UNLIKELY(pool->count > 0 && pool->count % POOL_SIZE == 0)) { pool->max += POOL_SIZE; pool->values = csound->ReAlloc(csound, pool->values, pool->max * sizeof (CS_VAR_MEM)); } index = pool->count; pool->values[index].varType = (CS_TYPE*)&CS_VAR_TYPE_C; pool->values[index].value = value; pool->count++; } return index; } int myflt_pool_find_or_addc(CSOUND* csound, MYFLT_POOL* pool, char* s) { MYFLT val = (MYFLT) cs_strtod(s, NULL); return myflt_pool_find_or_add(csound, pool, val); } csound-6.10.0/Engine/rdscor.c000066400000000000000000000237651321653344700157630ustar00rootroot00000000000000/* rdscor.c: Copyright (C) 2011 John ffitch (after Barry Vercoe) This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* RDSCORSTR.C */ #include "corfile.h" #include "insert.h" char* get_arg_string(CSOUND *csound, MYFLT p) { int32 n; char *ss; INSDS* ip = csound->ids->insdshead; while (ip->opcod_iobufs != NULL) { ip = ((OPCOD_IOBUFS*)ip->opcod_iobufs)->parent_ip; } ss = ip->strarg; /* look at this instr's strarg */ { union { MYFLT d; int32 i; } ch; ch.d = p; n = ch.i&0xffff; while (n-- > 0) { ss += strlen(ss)+1; } } return ss; } static void dumpline(CSOUND *); static void flushline(CSOUND *csound) /* flush scorefile to next newline */ { int c; while ((c = corfile_getc(csound->scstr)) != '\0' && c != '\n') ; } static int scanflt(CSOUND *csound, MYFLT *pfld) { /* read a MYFLT from scorefile; return 1 if OK, else 0 */ int c; while ((c = corfile_getc(csound->scstr)) == ' ' || c == '\t') /* skip leading white space */ ; if (UNLIKELY(c == ';')) { /* Comments terminate line */ flushline(csound); return 0; } if (c == '"') { /* if find a quoted string */ char *sstrp; int n = csound->scnt; if ((sstrp = csound->sstrbuf) == NULL) sstrp = csound->sstrbuf = csound->Malloc(csound, csound->strsiz=SSTRSIZ); while (n--!=0) sstrp += strlen(sstrp)+1; n = sstrp-csound->sstrbuf; while ((c = corfile_getc(csound->scstr)) != '"') { //if (c=='\\') c = corfile_getc(csound->scstr); *sstrp++ = c; n++; if (n > csound->strsiz-10) { csound->sstrbuf = csound->ReAlloc(csound, csound->sstrbuf, csound->strsiz+=SSTRSIZ); sstrp = csound->sstrbuf+n; } } *sstrp++ = '\0'; { union { MYFLT d; int32 i; } ch; ch.d = SSTRCOD; ch.i += csound->scnt++; *pfld = ch.d; /* set as string with count */ } csound->sstrlen = sstrp - csound->sstrbuf; /* & overall length */ //printf("csound->sstrlen = %d\n", csound->sstrlen); return(1); } if (UNLIKELY(!((c>='0' && c<='9') || c=='+' || c=='-' || c=='.'))) { corfile_ungetc(csound->scstr); csound->Message(csound, Str("ERROR: illegal character %c(%.2x) in scoreline: "), c, c); dumpline(csound); return(0); } corfile_ungetc(csound->scstr); { MYFLT ans = corfile_get_flt(csound->scstr); *pfld = ans; //printf("%s(%d):%lf %lf\n", __FILE__, __LINE__, ans, *pfld); } return(1); } static void dumpline(CSOUND *csound) /* print the line while flushing it */ { int c; while ((c = corfile_getc(csound->scstr)) != '\0' && c != '\n') { csound->Message(csound, "%c", c); } csound->Message(csound, Str("\n\tremainder of line flushed\n")); } int rdscor(CSOUND *csound, EVTBLK *e) /* read next score-line from scorefile */ /* & maintain section warped status */ { /* presumes good format if warped */ MYFLT *pp, *plim; int c; e->pinstance = NULL; if (csound->scstr == NULL || csound->scstr->body[0] == '\0') { /* if no concurrent scorefile */ e->opcod = 'f'; /* return an 'f 0 3600' */ e->p[1] = FL(0.0); e->p[2] = FL(INF); e->p2orig = FL(INF); e->pcnt = 2; return(1); } /* else read the real score */ while ((c = corfile_getc(csound->scstr)) != '\0') { csound->scnt = 0; switch (c) { case ' ': case '\t': case '\n': continue; /* skip leading white space */ case ';': flushline(csound); continue; case 's': case 't': case 'y': csound->warped = 0; goto unwarped; case 'w': csound->warped = 1; /* w statement is itself unwarped */ unwarped: e->opcod = c; /* UNWARPED scorefile: */ pp = &e->p[0]; plim = &e->p[PMAX]; /* caution, irregular format */ while (1) { while ((c = corfile_getc(csound->scstr))==' ' || c=='\t'); /* eat whitespace */ if (c == ';') { flushline(csound); break; } /* comments? skip */ if (c == '\n' || c == '\0') break; /* newline? done */ corfile_ungetc(csound->scstr); /* pfld: back up */ if (!scanflt(csound, ++pp)) break; /* & read value */ if (UNLIKELY(pp >= plim)) { csound->Message(csound, Str("ERROR: too many pfields: ")); dumpline(csound); break; } } e->p2orig = e->p[2]; /* now go count the pfields */ e->p3orig = e->p[3]; e->c.extra = NULL; goto setp; case 'e': e->opcod = c; e->pcnt = 0; return(1); case EOF: /* necessary for cscoreGetEvent */ return(0); default: /* WARPED scorefile: */ if (!csound->warped) goto unwarped; e->opcod = c; /* opcod */ csound->Free(csound, e->c.extra); e->c.extra = NULL; pp = &e->p[0]; plim = &e->p[PMAX]; if (corfile_getc(csound->scstr) != '\n' && scanflt(csound, ++pp)) /* p1 */ if (corfile_getc(csound->scstr) != '\n' && scanflt(csound, &e->p2orig)) /* p2 orig */ if (corfile_getc(csound->scstr) != '\n' && scanflt(csound, ++pp)) /* p2 warp */ if (corfile_getc(csound->scstr) != '\n' && scanflt(csound, &e->p3orig)) /* p3 */ if (corfile_getc(csound->scstr) != '\n' && scanflt(csound, ++pp)) /* p3 warp */ while (corfile_getc(csound->scstr) != '\n' && scanflt(csound, ++pp)) /* p4.... */ if (pp >= plim) { MYFLT *new; MYFLT *q; int c=1; csound->DebugMsg(csound, "Extra p-fields (%d %d %d %d)\n", (int)e->p[1],(int)e->p[2], (int)e->p[3],(int)e->p[4]); new = (MYFLT*) csound->Malloc(csound, sizeof(MYFLT)*PMAX); if (UNLIKELY(new==NULL)) { fprintf(stderr, Str("Out of Memory\n")); exit(7); } e->c.extra = new; e->c.extra[0] = PMAX-2; e->c.extra[1] = *pp; q = &e->c.extra[1]; while ((corfile_getc(csound->scstr) != '\n') && (scanflt(csound, &q[c++]))) { if (c+1 >= (int) e->c.extra[0]) { int size = (int)e->c.extra[0]+PMAX; /* printf("last values(%p): %f %f %f\n", */ /* q, q[c-3], q[c-2], q[c-1]); */ csound->DebugMsg(csound, "and more extra p-fields [%d](%d)%d\n", c, (int) e->c.extra[0], (int)sizeof(MYFLT)* ((int)e->c.extra[0]+PMAX)); new = (MYFLT *) csound->ReAlloc(csound, e->c.extra, sizeof(MYFLT)*size); if (new==NULL) { fprintf(stderr, "Out of Memory\n"); exit(7); } new[0] = size; e->c.extra = new; q = &new[1]; /* printf("%p(%d) values: %f %f %f\n", (int)new[0], */ /* q, q[c-3], q[c-2], q[c-1]); */ } } e->c.extra[0] = c; /* flushline(csound); */ goto setp; } setp: if (!csound->csoundIsScorePending_ && e->opcod == 'i') { /* FIXME: should pause and not mute */ csound->sstrlen = 0; e->opcod = 'f'; e->p[1] = FL(0.0); e->pcnt = 2; e->scnt = 0; return 1; } e->pcnt = pp - &e->p[0]; /* count the pfields */ if (UNLIKELY(e->pcnt>=PMAX)) e->pcnt += e->c.extra[0]; /* and overflow fields */ if (csound->sstrlen) { /* if string arg present, save it */ e->strarg = csound->sstrbuf; csound->sstrbuf = NULL; e->scnt = csound->scnt; csound->sstrlen = 0; } else { e->strarg = NULL; e->scnt = 0; } /* is this necessary?? */ return 1; } } corfile_rm(csound, &(csound->scstr)); return 0; } csound-6.10.0/Engine/scope.c000066400000000000000000000050731321653344700155700ustar00rootroot00000000000000#include "csoundCore.h" #include "corfile.h" #include "score_param.h" extern uint8_t file_to_int(CSOUND*, const char*); int scope(CSOUND *csound) { extern void print_csound_prsdata(void *); extern int csound_prslex_init(void *); extern void csound_prsset_extra(void *, void *); extern int csound_prslex(CSOUND*, void*); extern int csound_prslex_destroy(void *); extern void csound_sco_scan_buffer (const char *, size_t, void*); extern int csound_scoparse(SCORE_PARM *, void *, CSOUND*, ScoreTree*); extern void csound_scolex_init(void *); extern void csound_scoset_extra(void *, void *); extern void csound_scoset_lineno(int, void*); extern void csound_scolex_destroy(void *); #if 0 { PRS_PARM qq; char buff[1024]; /* Pre-process */ memset(&qq, '\0', sizeof(PRS_PARM)); csound_prslex_init(&qq.yyscanner); csound_prsset_extra(&qq, qq.yyscanner); //printf("depth = %d\n", qq.depth); csound->expanded_sco = corfile_create_w(); printf("Input:\n%s<<<\n", corfile_body(csound->sreadStatics.str->cf)); snprintf(buff, 1024, "#source %d\n", qq.lstack[0] = file_to_int(csound, csound->scorename? csound->scorename:"**unknown**")); corfile_puts(buff, csound->expanded_sco); snprintf(buff, 1024, "#line %d\n", csound->scoLineOffset); corfile_puts(buff, csound->expanded_sco); qq.line = 1; csound_prslex(csound, qq.yyscanner); csound->Message(csound, "yielding >>%s<<\n", corfile_body(csound->expanded_sco)); csound_prslex_destroy(qq.yyscanner); corfile_rm(&csound->scorestr); } { ScoreTree* scoTree = (ScoreTree *)csound->Calloc(csound, sizeof(ScoreTree)); SCORE_PARM pp; extern int csound_scodebug; int err; /* Parse */ memset(&pp, '\0', sizeof(SCORE_PARM)); csound_scolex_init(&pp.yyscanner); csound_scoset_extra(&pp, pp.yyscanner); csound_sco_scan_buffer(corfile_body(csound->expanded_sco), corfile_tell(csound->expanded_sco), pp.yyscanner); csound_scodebug = 0; err = csound_scoparse(&pp, pp.yyscanner, csound, scoTree); corfile_rm(&csound->expanded_sco); if (LIKELY(err == 0)) csound->Message(csound, "Parsing successful!\n"); { ScoreTree* s = scoTree; while (s) { printf("(%d,%s): opode = %c\n", s->line, csound->filedir[s->locn&0xff], s->op); s = s->next; } } } #endif return 0; } csound-6.10.0/Engine/score_param.h000066400000000000000000000057401321653344700167600ustar00rootroot00000000000000#ifndef __SCORE_PARAM_H #define __SCORE_PARAM_H typedef struct ListItem { double val; struct ListItem *args; } ListItem; typedef struct ScoreTree { int op; ListItem *args; struct ScoreTree *next; int line; int locn; } ScoreTree; #define MARGS (3) #define MAX_INCLUDE_DEPTH 100 struct MACRO; typedef struct MACRON { int n; unsigned int line; struct MACRO *s; } MACRON; typedef struct MACRO { /* To store active macros */ char *name; /* Use is by name */ int acnt; /* Count of arguments */ char *body; /* The text of the macro */ struct MACRO *next; /* Chain of active macros */ int margs; /* amount of space for args */ char *arg[MARGS]; /* With these arguments */ } MACRO; typedef struct IFDEFSTACK_ { struct IFDEFSTACK_ *prv; unsigned char isDef; /* non-zero if #ifdef is true, or #ifndef */ /* is false */ unsigned char isElse; /* non-zero between #else and #endif */ unsigned char isSkip; /* sum of: 1: skipping code due to this */ /* #ifdef, 2: skipping due to parent */ } IFDEFSTACK; typedef struct prs_parm_s { void *yyscanner; CORFIL *cf; MACRO *macros; MACRON *alt_stack; //[MAX_INCLUDE_DEPTH]; unsigned int macro_stack_ptr; unsigned int macro_stack_size; IFDEFSTACK *ifdefStack; unsigned char isIfndef; unsigned char isString; uint16_t line; uint32_t locn; uint32_t llocn; uint16_t depth; uint16_t lstack[1024]; /* Variable for nested repeat loops */ #define NAMELEN 40 /* array size of repeat macro names */ #define RPTDEPTH 40 /* size of repeat_n arrays (39 loop levels) */ char repeat_name_n[RPTDEPTH][NAMELEN]; int repeat_cnt_n[RPTDEPTH]; int repeat_indx[RPTDEPTH]; CORFIL *cf_stack[RPTDEPTH]; int repeat_inc_n /* = 1 */; MACRO *repeat_mm_n[RPTDEPTH]; int repeat_index; /* Variables for section repeat */ int in_repeat_sect; int repeat_sect_cnt; int repeat_sect_index; int repeat_sect_line; CORFIL *repeat_sect_cf; MACRO *repeat_sect_mm; } PRS_PARM; typedef struct scotoken_s { int type; int ival; MYFLT fval; char *strbuff; } SCOTOKEN; typedef struct score_parm_s { void *yyscanner; int locn; MACRO *macros; char *xstrbuff; int xstrptr,xstrmax; int ival; MYFLT fval; SCOTOKEN *arglist; } SCORE_PARM; uint64_t make_location(PRS_PARM *); extern uint8_t file_to_int(CSOUND*, const char*); #endif csound-6.10.0/Engine/scsort.c000066400000000000000000000043421321653344700157720ustar00rootroot00000000000000/* scsort.c: Copyright (C) 1991 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* SCSORT.C */ #include "corfile.h" extern void sort(CSOUND*); extern void twarp(CSOUND*); extern void swritestr(CSOUND*, CORFIL *sco, int first); extern void sfree(CSOUND *csound); //extern void sread_init(CSOUND *csound); extern int sread(CSOUND *csound); /* called from smain.c or some other main */ /* reads,sorts,timewarps each score sect in turn */ extern void sread_initstr(CSOUND *, CORFIL *sco); char *scsortstr(CSOUND *csound, CORFIL *scin) { int n; int m = 0, first = 0; CORFIL *sco; csound->scoreout = NULL; if (csound->scstr == NULL && (csound->engineStatus & CS_STATE_COMP) == 0) { first = 1; sco = csound->scstr = corfile_create_w(csound); } else sco = corfile_create_w(csound); csound->sectcnt = 0; sread_initstr(csound, scin); while ((n = sread(csound)) > 0) { sort(csound); twarp(csound); swritestr(csound, sco, first); //printf("sorted: >>>%s<<<\n", sco->body); m++; } if (first) { if (m==0) corfile_puts(csound, "f0 800000000000.0\ne\n", sco); /* ~25367 years */ else corfile_puts(csound, "e\n", sco); } corfile_flush(csound, sco); sfree(csound); if (first) { return sco->body; } else { char *str = cs_strdup(csound,sco->body); corfile_rm(csound, &(sco)); return str; } } csound-6.10.0/Engine/scxtract.c000066400000000000000000000043221321653344700163060ustar00rootroot00000000000000/* scxtract.c: Copyright (C) 1991 Barry Vercoe; 2012 John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* SCXTRACT.C */ #include "corfile.h" #include "extract.h" extern void sfree(CSOUND *csound); extern int sread(CSOUND *csound); //extern void sread_init(CSOUND *csound); extern void swritestr(CSOUND *csound, CORFIL *sco, int first); /* called from xmain.c or some other main */ /* extracts events from each score sect */ /* according to the controlling xfile */ extern void sread_initstr(CSOUND *, CORFIL *sco); int scxtract(CSOUND *csound, CORFIL *scin, FILE *xfile) { int n; EXTRACT_STATICS* extractStatics = csound->Calloc(csound, sizeof(EXTRACT_STATICS)); corfile_seek(scin, 0, SEEK_END); corfile_puts(csound, "\n#exit\n", scin); corfile_rewind(scin); csound->scoreout = NULL; csound->scorestr = scin; csound->scstr = corfile_create_w(csound); csound->sectcnt = 0; readxfil(csound, extractStatics, xfile); sread_initstr(csound, scin); while ((n = sread(csound)) > 0) { /* allout(); */ /* textout(); */ extract(csound, extractStatics); swritestr(csound, csound->scstr, 1); } //printf("***extracted: >>%s<<\n", csound->scstr->body); corfile_flush(csound, csound->scstr); sfree(csound); /* return all memory used */ csound->Free(csound, extractStatics); return 0; } csound-6.10.0/Engine/sort.c000066400000000000000000000172011321653344700154420ustar00rootroot00000000000000/* sort.c: Copyright (C) 2010 John ffitch with some code from Barry Vercoe This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* the smoothsort is from the Web http://en.wikibooks.org/wiki/Algorithm_Implementation/Sorting/Smoothsort recovered march 2010 Adapted from Delphi implementation of Dijkstra's algorithm. */ #include "csoundCore.h" /* SORT.C */ /* inline int ordering(SRTBLK *a, SRTBLK *b) */ /* { */ /* char cb = b->text[0], ca = a->text[0]; */ /* MYFLT diff; */ /* int prdiff, indiff; */ /* int ans; */ /* ans = !(ca != 'w' */ /* && (cb == 'w' || */ /* (ca != 't' && */ /* (cb == 't' || */ /* ((diff = b->newp2 - a->newp2) < 0 || */ /* (!diff && */ /* ((prdiff = b->preced - a->preced) < 0 || */ /* (!prdiff && cb == 'i' && */ /* ((indiff = b->insno - a->insno) < 0 || */ /* (!indiff && b->newp3 < a->newp3) ) */ /* )))))) || */ /* (b->lineno < a->lineno) )); */ /* /\* fprintf(stderr, "(%p,%p)[%c,%c] -> %d\n", a, b, ca, cb, ans); *\/ */ /* return ans; */ /* } */ #if !defined(TRUE) #define TRUE (1) #endif #if !defined(FALSE) #define FALSE (0) #endif static inline int ordering(SRTBLK *a, SRTBLK *b) { char cb = b->text[0], ca = a->text[0]; MYFLT tmp; int itmp; /* printf("SORT: ca=%c, cb=%c\n", ca, cb); */ if (ca=='w') return TRUE; if (cb=='w') return FALSE; if (cb=='t') return FALSE; tmp = b->newp2 - a->newp2; if (tmp < 0) return FALSE; if (tmp > 0) return TRUE; itmp = b->preced - a->preced; if (itmp < 0) return FALSE; if (itmp > 0) return TRUE; if ((cb == 'i') && (ca=='i')) { /* printf("SORT: ain=%f, bin=%f\n", a->insno, b->insno); */ tmp = b->insno - a->insno; if (tmp < 0) return FALSE; if (tmp > 0) return TRUE; /* printf("SORT: ap3=%f, bp3=%f\n", a->newp3, b->newp3); */ /* tmp = fabs(b->newp3) - fabs(a->newp3); */ tmp = b->newp3 - a->newp3; if (tmp < 0) return FALSE; if (tmp > 0) return TRUE; } /* printf("(%p,%p)[%c,%c]{%d,%d} -> %d\n", */ /* a, b, ca, cb, a->lineno, b->lineno, b->lineno > a->lineno); */ return (b->lineno > a->lineno); } #define UP(IA,IB) {temp=IA; IA+=(IB)+1; IB=temp;} #define DOWN(IA,IB) {temp=IB; IB=(IA)-(IB)-1; IA=temp;} /* These need to be encapsulated */ #define q (data[0]) #define r (data[1]) #define p (data[2]) #define b (data[3]) #define c (data[4]) #define r1 (data[5]) #define b1 (data[6]) #define c1 (data[7]) inline static void sift(SRTBLK *A[], int data[]) { int r0, r2, temp; SRTBLK * T; r0 = r1; T = A[r0]; while (b1 >= 3) { r2 = r1-b1+c1; if (! ordering(A[r1-1],A[r2])) { r2 = r1-1; DOWN(b1,c1) } if (ordering(A[r2],T)) b1 = 1; else { A[r1] = A[r2]; r1 = r2; DOWN(b1,c1) } } if (UNLIKELY(r1 != r0)) A[r1] = T; } inline static void trinkle(SRTBLK *A[], int data[]) { int p1,r2,r3, r0, temp; SRTBLK * T; p1 = p; b1 = b; c1 = c; r0 = r1; T = A[r0]; while (p1 > 0) { while ((p1 & 1)==0) { p1 >>= 1; UP(b1,c1) } r3 = r1-b1; if ((p1==1) || ordering(A[r3], T)) p1 = 0; else { p1--; if (b1==1) { A[r1] = A[r3]; r1 = r3; } else if (b1 >= 3) { r2 = r1-b1+c1; if (! ordering(A[r1-1],A[r2])) { r2 = r1-1; DOWN(b1,c1) p1 <<= 1; } if (ordering(A[r2],A[r3])) { A[r1] = A[r3]; r1 = r3; } else { A[r1] = A[r2]; r1 = r2; DOWN(b1,c1) p1 = 0; } } } } if (r0-r1) A[r1] = T; sift(A, data); } inline static void semitrinkle(SRTBLK *A[], int data[]) { SRTBLK * T; r1 = r-c; if (! ordering(A[r1],A[r])) { T = A[r]; A[r] = A[r1]; A[r1] = T; trinkle(A, data); } } static void smoothsort(SRTBLK *A[], const int N) { int temp; int data[] = {/*q*/ 1, /*r*/ 0, /*p*/ 1, /*b*/ 1, /*c*/ 1, 0,0,0}; /* building tree */ while (q < N) { r1 = r; if ((p & 7)==3) { b1 = b; c1 = c; sift(A, data); p = (p+1) >> 2; UP(b,c) UP(b,c) } else if ((p & 3)==1) { if (q + c < N) { b1 = b; c1 = c; sift(A, data); } else trinkle(A, data); DOWN(b,c); p <<= 1; while (b > 1) { DOWN(b,c) p <<= 1; } p++; } q++; r++; } r1 = r; trinkle(A, data); /* building sorted array */ while (q > 1) { q--; if (b==1) { r--; p--; while ((p & 1)==0) { p >>= 1; UP(b,c) } } else if (b >= 3) { p--; r = r-b+c; if (p > 0) semitrinkle(A, data); DOWN(b,c) p = (p << 1) + 1; r = r+c; semitrinkle(A, data); DOWN(b,c) p = (p << 1) + 1; } /* element q processed */ } /* element 0 processed */ } void sort(CSOUND *csound) { SRTBLK *bp; SRTBLK **A; int i, n = 0; if (UNLIKELY((bp = csound->frstbp) == NULL)) return; do { n++; /* Need to count to alloc the array */ switch (bp->text[0]) { case 'd': case 'i': if (bp->insno < 0) bp->preced = 'b'; else bp->preced = 'd'; break; case 'f': bp->preced = 'c'; break; case 'a': bp->preced = 'e'; break; case 'e': // bp->newp2 ; case 'q': case 'w': case 't': case 's': bp->preced = 'a'; break; case 'x': n--; break; case -1: case 'y': break; default: csound->Message(csound, Str("sort: illegal opcode %c(%.2x)\n"), bp->text[0], bp->text[0]); break; } } while ((bp = bp->nxtblk) != NULL); if (n>1) { /* Get a temporary array and populate it */ A = ((SRTBLK**) csound->Malloc(csound, n*sizeof(SRTBLK*))); bp = csound->frstbp; for (i=0; inxtblk) { A[i] = bp; if (bp->text[0]=='x') i--; /* try to ignore x opcode */ } if (LIKELY(A[n-1]->text[0]=='e' || A[n-1]->text[0]=='s')) smoothsort(A, n-1); else smoothsort(A, n); /* Relink list in order; first and last different */ csound->frstbp = bp = A[0]; bp->prvblk = NULL; bp->nxtblk = A[1]; for (i=1; iprvblk = A[i-1]; bp->nxtblk = A[i+1]; } if (n>1) bp = A[n-1]; bp->nxtblk = NULL; bp->prvblk = A[n-2]; /* and return temporary space */ csound->Free(csound, A); } } csound-6.10.0/Engine/sread.c000066400000000000000000002345031321653344700155570ustar00rootroot00000000000000/* sread.c: Copyright (C) 1991, 1997 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* SREAD.C */ #include /* for fabs() */ #include #include "namedins.h" /* IV - Oct 31 2002 */ #include "corfile.h" #include "Engine/score_param.h" #define MEMSIZ 16384 /* size of memory requests from system */ #define MARGIN 4096 /* minimum remaining before new request */ #define NAMELEN 40 /* array size of repeat macro names */ #define RPTDEPTH 40 /* size of repeat_n arrays (39 loop levels) */ //#define MACDEBUG (1) static void print_input_backtrace(CSOUND *csound, int needLFs, void (*msgfunc)(CSOUND*, const char*, ...)); static void copylin(CSOUND *), copypflds(CSOUND *); static void ifa(CSOUND *), setprv(CSOUND *); static void carryerror(CSOUND *), pcopy(CSOUND *, int, int, SRTBLK*); static void salcinit(CSOUND *); static void salcblk(CSOUND *), flushlin(CSOUND *); static int getop(CSOUND *), getpfld(CSOUND *); MYFLT stof(CSOUND *, char *); extern void *fopen_path(CSOUND *, FILE **, char *, char *, char *, int); extern int csound_prslex_init(void *); extern void csound_prsset_extra(void *, void *); extern int csound_prslex(CSOUND*, void*); extern int csound_prslex_destroy(void *); extern void cs_init_smacros(CSOUND*, PRS_PARM*, NAMES*); #define STA(x) (csound->sreadStatics.x) static intptr_t expand_nxp(CSOUND *csound) { char *oldp; SRTBLK *p; intptr_t offs; size_t nbytes; if (UNLIKELY(STA(nxp) >= (STA(memend) + MARGIN))) { csound->Die(csound, Str("sread: text space overrun, increase MARGIN")); return 0; /* not reached */ } /* calculate the number of bytes to allocate */ nbytes = (size_t) (STA(memend) - STA(curmem)); nbytes = nbytes + (nbytes >> 3) + (size_t) (MEMSIZ - 1); nbytes &= ~((size_t) (MEMSIZ - 1)); /* extend allocated memory */ oldp = STA(curmem); STA(curmem) = (char*) csound->ReAlloc(csound, STA(curmem), nbytes + (size_t) MARGIN); STA(memend) = (char*) STA(curmem) + (int32) nbytes; /* did the pointer change ? */ if (STA(curmem) == oldp) return (intptr_t) 0; /* no, nothing to do */ /* correct all pointers for the change */ offs = (intptr_t) ((uintptr_t) STA(curmem) - (uintptr_t) oldp); if (STA(bp) != NULL) STA(bp) = (SRTBLK*) ((uintptr_t) STA(bp) + (intptr_t) offs); if (STA(prvibp) != NULL) STA(prvibp) = (SRTBLK*) ((uintptr_t) STA(prvibp) + (intptr_t) offs); if (STA(sp) != NULL) STA(sp) = (char*) ((uintptr_t) STA(sp) + (intptr_t) offs); if (STA(nxp) != NULL) STA(nxp) = (char*) ((uintptr_t) STA(nxp) + (intptr_t) offs); if (csound->frstbp == NULL) return offs; p = csound->frstbp; csound->frstbp = p = (SRTBLK*) ((uintptr_t) p + (intptr_t) offs); do { if (p->prvblk != NULL) p->prvblk = (SRTBLK*) ((uintptr_t) p->prvblk + (intptr_t) offs); if (p->nxtblk != NULL) p->nxtblk = (SRTBLK*) ((uintptr_t) p->nxtblk + (intptr_t) offs); p = p->nxtblk; } while (p != NULL); /* return pointer change in bytes */ return offs; } /* sreaderr() - for non-fatal "warnings" */ static void sreaderr(CSOUND *csound, const char *s, ...) { va_list args; csoundMessage(csound, Str("sread: ")); va_start(args, s); csoundMessageV(csound, 0, s, args); va_end(args); csoundMessage(csound, "\n"); print_input_backtrace(csound, 1, csoundMessage); return; } /* scorerr() - for fatal errors in score parsing */ static void scorerr(CSOUND *csound, const char *s, ...) { va_list args; va_start(args, s); csound->ErrMsgV(csound, Str("score error: "), s, args); va_end(args); print_input_backtrace(csound, 0, csoundErrorMsg); csound->LongJmp(csound, 1); } static void print_input_backtrace(CSOUND *csound, int needLFs, void (*msgfunc)(CSOUND*, const char*, ...)) { IN_STACK *curr = STA(str); char *m, *lf = (needLFs ? "\n" : ""); int lastinput = 0; int lastsource = 2; /* 2=current file, 1=macro, 0=#include */ msgfunc(csound, Str(" section %d: at position %d%s"), csound->sectcnt, STA(linepos), lf); do { if (curr == STA(inputs)) lastinput = 1; if (UNLIKELY(!curr->mac || !curr->mac->name)){ csound->Warning(csound, Str("Internal error in print_input_backtrace()")); return; } switch(lastsource) { case 0: m = Str(" included from line %d of macro %s%s"); break; case 1: m = Str(" called from line %d of macro %s%s"); break; //default: case 2: m = Str(" in line %d of macro %s%s"); break; } msgfunc(csound, m, (lastsource == 0 ? curr->line - 1 : curr->line), curr->mac->name, lf); /* #include is one line before */ if (lastinput && csound->oparms->useCsdLineCounts && csound->csdname) { /* print name & line # of CSD instead of temp sco */ msgfunc(csound, m, (lastsource == 0 ? csound->scoLineOffset + curr->line - 1 : csound->scoLineOffset + curr->line), csound->csdname, lf); } /* else { */ /* msgfunc(csound, m, (lastsource == 0 ? curr->line - 1 : curr->line), */ /* corfile_tell(curr->cf), lf); /\* #include is one line before *\/ */ /* } */ } while (!lastsource); curr--; return; } static MYFLT operate(CSOUND *csound, MYFLT a, MYFLT b, char c) { MYFLT ans; extern MYFLT MOD(MYFLT,MYFLT); switch (c) { case '+': ans = a + b; break; case '-': ans = a - b; break; case '*': ans = a * b; break; case '/': ans = a / b; break; case '%': ans = MOD(a, b); break; case '^': ans = POWER(a, b); break; case '&': ans = (MYFLT) (MYFLT2LRND(a) & MYFLT2LRND(b)); break; case '|': ans = (MYFLT) (MYFLT2LRND(a) | MYFLT2LRND(b)); break; case '#': ans = (MYFLT) (MYFLT2LRND(a) ^ MYFLT2LRND(b)); break; default: csoundDie(csound, Str("Internal error op=%c"), c); ans = FL(0.0); /* compiler only */ } return ans; } static int undefine_score_macro(CSOUND *csound, const char *name) { S_MACRO *mm, *nn; int i; if (strcmp(name, STA(macros)->name) == 0) { mm = STA(macros)->next; if (strcmp(STA(macros)->name, "[") != 0) corfile_rm(csound, &(STA(macros)->body)); csound->Free(csound, STA(macros)->name); #ifdef MACDEBUG csound->DebugMsg(csound,"%s(%d): corfile is %p\n", __FILE__, __LINE__, STA(macros)->body); #endif for (i = 0; i < STA(macros)->acnt; i++) csound->Free(csound, STA(macros)->arg[i]); csound->Free(csound, STA(macros)); STA(macros) = mm; } else { mm = STA(macros); nn = mm->next; while (strcmp(name, nn->name) != 0) { mm = nn; nn = nn->next; if (UNLIKELY(nn == NULL)) { scorerr(csound, Str("Undefining undefined macro")); return -1; } } csound->Free(csound, nn->name); corfile_rm(csound, &nn->body); for (i = 0; i < nn->acnt; i++) csound->Free(csound, nn->arg[i]); mm->next = nn->next; csound->Free(csound, nn); } return 0; } static inline int isNameChar(int c, int pos) { //c = (int) ((unsigned char) c); if (UNLIKELY(c<0)) return 0; return (isalpha(c) || (pos && (c == '_' || isdigit(c)))); } /* Functions to read/unread chracters from * a stack of file and macro inputs */ static inline void ungetscochar(CSOUND *csound, int c) { corfile_ungetc(csound->expanded_sco); csound->expanded_sco->body[csound->expanded_sco->p] = (char)c; } static int getscochar(CSOUND *csound, int expand) { /* Read a score character, expanding macros if flag set */ int c; IGN(expand); #ifdef never /* top: */ /* c = corfile_getc(STA(str)->cf); */ /* if (c == EOF) { */ /* if (STA(str) == &STA(inputs)[0]) { */ /* corfile_putc('\n', STA(str)->cf); /\* to ensure repeated EOF *\/ */ /* return EOF; */ /* } */ /* if (STA(str)->mac == 0) { */ /* corfile_rm(&(STA(str)->cf)); /\* No longer needed *\/ */ /* } */ /* else { */ /* corfile_rewind(STA(str)->cf); */ /* } */ /* STA(pop) += STA(str)->args; */ /* STA(str)--; STA(input_cnt)--; */ /* goto top; */ /* } */ /* #ifdef MACDEBUG */ /* csound->DebugMsg(csound,"%s(%d): character = %c(%.2d)\n", */ /* __FILE__, __LINE__, c, c); */ /* #endif */ /* if (c == '\r') { /\* can only occur in files, and not in macros *\/ */ /* if ((c = corfile_getc(STA(str)->cf)) != '\n') { */ /* if (c == EOF) */ /* goto top; */ /* corfile_ungetc(STA(str)->cf); */ /* } */ /* c = '\n'; */ /* } */ /* if (c == '\n') { */ /* STA(str)->line++; STA(linepos) = -1; */ /* } */ /* else STA(linepos)++; */ /* if (STA(ingappop) && STA(pop)) { */ /* do { */ /* if (STA(macros) != NULL) { */ /* #ifdef MACDEBUG */ /* csound->Message(csound,"popping %s\n", STA(macros)->name); */ /* #endif */ /* undefine_score_macro(csound, STA(macros)->name); */ /* } */ /* STA(pop)--; */ /* } while (STA(pop)); */ /* } */ /* if (c == '$' && expand) { */ /* char name[100]; */ /* unsigned int i = 0; */ /* int j; */ /* S_MACRO *mm, *mm_save = NULL; */ /* STA(ingappop) = 0; */ /* while (isNameChar((c = getscochar(csound, 1)), (int) i)) { */ /* name[i++] = c; name[i] = '\0'; */ /* mm = STA(macros); */ /* while (mm != NULL) { /\* Find the definition *\/ */ /* if (!(strcmp(name, mm->name))) { */ /* mm_save = mm; /\* found a match, save it *\/ */ /* break; */ /* } */ /* mm = mm->next; */ /* } */ /* } */ /* mm = mm_save; */ /* if (UNLIKELY(mm == NULL)) { */ /* if (!i) */ /* scorerr(csound, Str("Macro expansion symbol ($) without macro name")); */ /* else */ /* scorerr(csound, Str("Undefined macro: '%s'"), name); */ /* } */ /* if (strlen(mm->name) != i) { */ /* int cnt = (int) i - (int) strlen(mm->name); */ /* csound->Warning(csound, Str("$%s matches macro name $%s"), */ /* name, mm->name); */ /* do { */ /* ungetscochar(csound, c); */ /* c = name[--i]; */ /* } while (cnt--); */ /* } */ /* else if (c != '.') */ /* ungetscochar(csound, c); */ /* #ifdef MACDEBUG */ /* csound->Message(csound, "Found macro %s required %d arguments\n", */ /* mm->name, mm->acnt); */ /* #endif */ /* /\* Should bind arguments here *\/ */ /* /\* How do I recognise entities?? *\/ */ /* if (mm->acnt) { */ /* if (UNLIKELY((c=getscochar(csound, 1)) != '(')) */ /* scorerr(csound, Str("Syntax error in macro call")); */ /* for (j = 0; j < mm->acnt; j++) { */ /* char term = (j == mm->acnt - 1 ? ')' : '\''); */ /* char trm1 = (j == mm->acnt - 1 ? ')' : '#'); */ /* S_MACRO* nn = (S_MACRO*) csound->Malloc(csound, sizeof(S_MACRO)); */ /* nn->name = csound->Malloc(csound, strlen(mm->arg[j])+1); */ /* strcpy(nn->name, mm->arg[j]); */ /* #ifdef MACDEBUG */ /* csound->Message(csound,"defining argument %s ", nn->name); */ /* #endif */ /* nn->body = corfile_create_w(); */ /* #ifdef MACDEBUG */ /* csound->DebugMsg(csound,"%s(%d): creating\n", */ /* __FILE__, __LINE__, nn->body); */ /* #endif */ /* while ((c = getscochar(csound, 1))!= term && c != trm1) { */ /* if (UNLIKELY(c==EOF)) */ /* scorerr(csound, Str("Syntax error in macro call")); */ /* corfile_putc(c, nn->body); */ /* } */ /* corfile_rewind(nn->body); */ /* #ifdef MACDEBUG */ /* csound->Message(csound,"as...#%s#\n", corfile_body(nn->body)); */ /* #endif */ /* nn->acnt = 0; /\* No arguments for arguments *\/ */ /* nn->next = STA(macros); */ /* STA(macros) = nn; */ /* } */ /* } */ /* STA(input_cnt)++; */ /* if (UNLIKELY(STA(input_cnt)>=STA(input_size))) { */ /* int old = STA(str)-STA(inputs); */ /* STA(input_size) += 20; */ /* STA(inputs) = csound->ReAlloc(csound, STA(inputs), STA(input_size) */ /* * sizeof(IN_STACK)); */ /* STA(str) = &STA(inputs)[old]; /\* In case it moves *\/ */ /* } */ /* STA(str)++; */ /* STA(str)->cf = mm->body; STA(str)->args = mm->acnt; */ /* STA(str)->is_marked_repeat = 0; */ /* STA(str)->mac = mm; STA(str)->line = 1; */ /* #ifdef MACDEBUG */ /* csound->Message(csound, */ /* "Macro %s definded as >>%s<<\n", */ /* mm->name, corfile_body(mm->body)); */ /* #endif */ /* STA(ingappop) = 1; */ /* goto top; */ /* } */ /* /\* End of macro expander *\/ */ /* if (expand && c == '[') { /\* Evaluable section *\/ */ /* char stack[30]; */ /* MYFLT vv[30]; */ /* char *op = stack - 1; */ /* MYFLT *pv = vv - 1; */ /* char buffer[100]; */ /* int i; */ /* int type = 0; // 1 -> expecting binary operator,')', or ']'; else 0 */ /* *++op = '['; */ /* c = getscochar(csound, 1); */ /* do { */ /* switch (c) { */ /* case '0': case '1': case '2': case '3': case '4': */ /* case '5': case '6': case '7': case '8': case '9': */ /* case '.': */ /* if (UNLIKELY(type)) { */ /* scorerr(csound, Str("illegal placement of number in [] " */ /* "expression")); */ /* } */ /* parseNumber: */ /* i = 0; */ /* do { */ /* buffer[i++] = c; */ /* c = getscochar(csound, 1); */ /* } while (isdigit(c) || c == '.'); */ /* if (c == 'e' || c == 'E') { */ /* buffer[i++] = c; */ /* c = getscochar(csound, 1); */ /* if (c == '+' || c == '-') { */ /* buffer[i++] = c; */ /* c = getscochar(csound, 1); */ /* } */ /* while (isdigit(c)) { */ /* buffer[i++] = c; */ /* c = getscochar(csound, 1); */ /* } */ /* } */ /* buffer[i] = '\0'; */ /* *++pv = stof(csound, buffer); */ /* type = 1; */ /* break; */ /* case '~': */ /* if (UNLIKELY(type)) { */ /* scorerr(csound, Str("illegal placement of operator ~ in [] " */ /* "expression")); */ /* } */ /* *++pv = (MYFLT) (csound->Rand31(&(csound->randSeed1)) - 1) */ /* / FL(2147483645); */ /* type = 1; */ /* c = getscochar(csound, 1); */ /* break; */ /* case '@': */ /* if (UNLIKELY(type)) { */ /* scorerr(csound, Str("illegal placement of operator @ or @@ in" */ /* " [] expression")); */ /* } */ /* { */ /* int n = 0; */ /* int k = 0; /\* 0 or 1 depending on guard bit *\/ */ /* c = getscochar(csound, 1); */ /* if (c=='@') { k = 1; c = getscochar(csound, 1);} */ /* while (isdigit(c)) { */ /* n = 10*n + c - '0'; */ /* c = getscochar(csound, 1); */ /* } */ /* i = 1; */ /* while (i<=n-k && i< 0x4000000) i <<= 1; */ /* *++pv = (MYFLT)(i+k); */ /* type = 1; */ /* } */ /* break; */ /* case '+': case '-': */ /* if (!type) */ /* goto parseNumber; */ /* if (*op != '[' && *op != '(') { */ /* MYFLT v = operate(csound, *(pv-1), *pv, *op); */ /* op--; pv--; */ /* *pv = v; */ /* } */ /* type = 0; */ /* *++op = c; c = getscochar(csound, 1); break; */ /* case '*': */ /* case '/': */ /* case '%': */ /* if (UNLIKELY(!type)) { */ /* scorerr(csound, Str("illegal placement of operator %c in [] " */ /* "expression"), c); */ /* } */ /* if (*op == '*' || *op == '/' || *op == '%') { */ /* MYFLT v = operate(csound, *(pv-1), *pv, *op); */ /* op--; pv--; */ /* *pv = v; */ /* } */ /* type = 0; */ /* *++op = c; c = getscochar(csound, 1); break; */ /* case '&': */ /* case '|': */ /* case '#': */ /* if (UNLIKELY(!type)) { */ /* scorerr(csound, Str("illegal placement of operator %c in [] " */ /* "expression"), c); */ /* } */ /* if (*op == '|' || *op == '&' || *op == '#') { */ /* MYFLT v = operate(csound, *(pv-1), *pv, *op); */ /* op--; pv--; */ /* *pv = v; */ /* } */ /* type = 0; */ /* *++op = c; c = getscochar(csound, 1); break; */ /* case '(': */ /* if (UNLIKELY(type)) { */ /* scorerr(csound, Str("illegal placement of '(' in [] expression")); */ /* } */ /* type = 0; */ /* *++op = c; c = getscochar(csound, 1); break; */ /* case ')': */ /* if (UNLIKELY(!type)) { */ /* scorerr(csound, Str("missing operand before ')' in [] expression")); */ /* } */ /* while (*op != '(') { */ /* MYFLT v = operate(csound, *(pv-1), *pv, *op); */ /* op--; pv--; */ /* *pv = v; */ /* } */ /* type = 1; */ /* op--; c = getscochar(csound, 1); break; */ /* case '^': */ /* type = 0; */ /* *++op = c; c = getscochar(csound, 1); break; */ /* case ']': */ /* if (UNLIKELY(!type)) { */ /* scorerr(csound, */ /* Str("missing operand before closing bracket in []")); */ /* } */ /* while (*op != '[') { */ /* MYFLT v = operate(csound, *(pv-1), *pv, *op); */ /* op--; pv--; */ /* *pv = v; */ /* } */ /* c = '$'; */ /* break; */ /* case '$': */ /* break; */ /* case ' ': /\* Ignore spaces *\/ */ /* c = getscochar(csound, 1); */ /* continue; */ /* default: */ /* scorerr(csound, Str("illegal character %c(%.2x) in [] expression"), */ /* c, c); */ /* } */ /* } while (c != '$'); */ /* /\* Make string macro or value *\/ */ /* CS_SPRINTF(buffer, "%f", *pv); */ /* { */ /* S_MACRO *nn = (S_MACRO*) csound->Malloc(csound, sizeof(S_MACRO)); */ /* nn->name = csound->Malloc(csound, 2); */ /* strcpy(nn->name, "["); */ /* nn->body = corfile_create_r(buffer); */ /* #ifdef MACDEBUG */ /* csound->DebugMsg(csound,"%s(%d): creating arg %p\n", */ /* __FILE__, __LINE__, nn->body); */ /* #endif */ /* nn->acnt = 0; /\* No arguments for arguments *\/ */ /* nn->next = STA(macros); */ /* STA(macros) = nn; */ /* STA(input_cnt)++; */ /* if (UNLIKELY(STA(input_cnt)>=STA(input_size))) { */ /* int old = STA(str)-STA(inputs); */ /* STA(input_size) += 20; */ /* STA(inputs) = csound->ReAlloc(csound, STA(inputs), STA(input_size) */ /* * sizeof(IN_STACK)); */ /* STA(str) = &STA(inputs)[old]; /\* In case it moves *\/ */ /* } */ /* STA(str)++; */ /* STA(str)->cf = nn->body; STA(str)->args = 0; */ /* STA(str)->is_marked_repeat = 0; */ /* STA(str)->mac = NULL; STA(str)->line = 1; */ /* #ifdef MACDEBUG */ /* csound->Message(csound,"[] defined as >>%s<<\n", */ /* corfile_body(nn->body)); */ /* #endif */ /* STA(ingappop) = 1; */ /* goto top; */ /* } */ /* } */ /* return c; */ #else /* Read a score character, expanding macros expanded */ c = corfile_getc(csound->expanded_sco); if (c == EOF) { if (STA(str) == &STA(inputs)[0]) { //corfile_putc('\n', STA(str)->cf); /* to ensure repeated EOF */ return EOF; } } #ifdef MACDEBUG csound->DebugMsg(csound,"%s(%d): character = %c(%.2d)\n", __FILE__, __LINE__, c, c); #endif if (c == '\n') { STA(str)->line++; STA(linepos) = -1; } else STA(linepos)++; return c; #endif } /* #ifdef never */ /* static int nested_repeat(CSOUND *csound) /\* gab A9*\/ */ /* { */ /* STA(repeat_cnt_n)[STA(repeat_index)]--; */ /* if (STA(repeat_cnt_n)[STA(repeat_index)] == 0) { /\* Expired *\/ */ /* if (STA(repeat_index) > 1) { */ /* char c[41]; */ /* int j; */ /* memset(c, '\0', 41); */ /* for (j = 0; joparms->odebug/\*csound->oparms->msglevel & TIMEMSG*\/) */ /* csound->Message(csound,Str("%s Nested LOOP terminated, level:%d\n"), */ /* c,STA(repeat_index)); */ /* } */ /* else { */ /* if (csound->oparms->odebug/\*csound->oparms->msglevel & TIMEMSG*\/) */ /* csound->Message(csound,Str("External LOOP terminated, level:%d\n"), */ /* STA(repeat_index)); */ /* } */ /* undefine_score_macro(csound, STA(repeat_name_n)[STA(repeat_index)]); */ /* STA(repeat_index)--; */ /* } */ /* else { */ /* int i; */ /* corfile_set(STA(str)->cf,STA(repeat_point_n)[STA(repeat_index)]); */ /* sscanf(corfile_current(STA(repeat_mm_n)[STA(repeat_index)]->body), */ /* "%d", &i); */ /* #ifdef MACDEBUG */ /* csound->DebugMsg(csound,"%s(%d) reset point to %d\n", __FILE__, __LINE__, */ /* STA(repeat_point_n)[STA(repeat_index)], i); */ /* csound->DebugMsg(csound,"%s(%d) corefile: %s %d %d\n", __FILE__, __LINE__, */ /* STA(repeat_mm_n)[STA(repeat_index)]->body->body, */ /* STA(repeat_mm_n)[STA(repeat_index)]->body->p, */ /* STA(repeat_mm_n)[STA(repeat_index)]->body->len); */ /* #endif */ /* i = i + STA(repeat_inc_n); */ /* { */ /* char buffer[128]; */ /* memset(buffer, '\0', 128); */ /* snprintf(buffer, 128, "%d", i); */ /* #ifdef MACDEBUG */ /* csound->DebugMsg(csound,"%s(%d) new i = %s\n", */ /* __FILE__, __LINE__, buffer); */ /* #endif */ /* corfile_reset(STA(repeat_mm_n)[STA(repeat_index)]->body); */ /* corfile_puts(buffer, STA(repeat_mm_n)[STA(repeat_index)]->body); */ /* corfile_rewind(STA(repeat_mm_n)[STA(repeat_index)]->body); */ /* #ifdef MACDEBUG */ /* csound->DebugMsg(csound,"%s(%d) corefile: %s %d %d\n", */ /* __FILE__, __LINE__, */ /* STA(repeat_mm_n)[STA(repeat_index)]->body->body, */ /* STA(repeat_mm_n)[STA(repeat_index)]->body->p, */ /* STA(repeat_mm_n)[STA(repeat_index)]->body->len); */ /* #endif */ /* } */ /* if (STA(repeat_index) > 1) { */ /* char c[41]; */ /* int j; */ /* memset(c, '\0', 41); */ /* for (j = 0; joparms->odebug/\*csound->oparms->msglevel & TIMEMSG*\/) */ /* csound->Message(csound,Str("%s Nested LOOP section (%d) Level:%d\n"), */ /* c, i, STA(repeat_index)); */ /* } */ /* else { */ /* if (csound->oparms->odebug/\*csound->oparms->msglevel & TIMEMSG*\/) */ /* csound->Message(csound,Str(" External LOOP section (%d) Level:%d\n"), */ /* i, STA(repeat_index)); */ /* } */ /* return 1; */ /* } */ /* return 0; */ /* } */ /* #endif */ /* static int do_repeat(CSOUND *csound) */ /* { /\* At end of section repeat if necessary *\/ */ /* STA(repeat_cnt)--; */ /* if (STA(repeat_cnt) == 0) { /\* Expired *\/ */ /* /\* Delete macro (assuming there is any) *\/ */ /* if (csound->oparms->msglevel & TIMEMSG) */ /* csound->Message(csound, Str("Loop terminated\n")); */ /* if (STA(repeat_name)[0] != '\0') */ /* undefine_score_macro(csound, STA(repeat_name)); */ /* STA(repeat_name)[0] = '\0'; */ /* } */ /* else { */ /* int i, n; */ /* corfile_set(csound->expanded_sco, STA(repeat_point)); */ /* if (STA(repeat_name)[0] != '\0') { */ /* sscanf(corfile_current(STA(repeat_mm)->body), "%d%n", &i, &n); */ /* i = i + STA(repeat_inc); */ /* corfile_seek(STA(repeat_mm)->body, n, SEEK_CUR); */ /* { */ /* char buffer[128]; */ /* snprintf(buffer, 128, "%d", i); */ /* corfile_reset(STA(repeat_mm)->body); */ /* corfile_puts(buffer, STA(repeat_mm)->body); */ /* corfile_rewind(STA(repeat_mm)->body); */ /* } */ /* if (csound->oparms->msglevel & TIMEMSG) */ /* csound->Message(csound, Str("Repeat section (%d)\n"), i); */ /* } */ /* else */ /* csound->Message(csound, Str("Repeat section\n")); */ /* /\* replace 'e' or 'r' with 's' and end section *\/ */ /* STA(bp)->text[0] = 's'; */ /* STA(clock_base) = FL(0.0); */ /* STA(warp_factor) = FL(1.0); */ /* STA(prvp2) = -FL(1.0); */ /* return 1; */ /* } */ /* return 0; */ /* } */ #if 0 static void init_smacros(CSOUND *csound, NAMES *nn) { S_MACRO *mm; while (nn) { char *s = nn->mac; char *p = strchr(s, '='); char *mname; if (p == NULL) p = s + strlen(s); //if (csound->oparms->msglevel & 7) //sound->Message(csound, Str("Macro definition for %*s\n"), p - s, s); s = strchr(s, ':') + 1; /* skip arg bit */ if (UNLIKELY(s == NULL || s >= p)) csound->Die(csound, Str("Invalid macro name for --smacro")); mname = (char*) csound->Malloc(csound, (p - s) + 1); strncpy(mname, s, p - s); mname[p - s] = '\0'; /* check if macro is already defined */ for (mm = STA(macros); mm != NULL; mm = mm->next) { if (strcmp(mm->name, mname) == 0) break; } if (mm == NULL) { mm = (S_MACRO*) csound->Calloc(csound, sizeof(S_MACRO)); mm->name = mname; mm->next = STA(macros); STA(macros) = mm; } else csound->Free(csound, mname); mm->margs = MARGS; /* Initial size */ mm->acnt = 0; if (*p != '\0') p++; mm->body = corfile_create_r(p); #ifdef MACDEBUG csound->DebugMsg(csound,"%s(%d): init %s %p\n", __FILE__, __LINE__, mm->name, mm->body); #endif nn = nn->next; } mm = (S_MACRO*) csound->Calloc(csound, sizeof(S_MACRO)); mm->name = (char*)csound->Malloc(csound,4); strcpy(mm->name, "INF"); mm->body = corfile_create_r("800000000000.0"); #ifdef MACDEBUG csound->DebugMsg(csound,"%s(%d): INF %p\n", __FILE__, __LINE__, mm->body); #endif mm->next = STA(macros); STA(macros) = mm; } #endif /* #if never */ /* void sread_init(CSOUND *csound) */ /* { */ /* /\* sread_alloc_globals(csound); *\/ */ /* STA(inputs) = (IN_STACK*) csound->Malloc(csound, 20 * sizeof(IN_STACK)); */ /* STA(input_size) = 20; */ /* STA(input_cnt) = 0; */ /* STA(str) = STA(inputs); */ /* STA(str)->cf = csound->scstr; */ /* STA(str)->is_marked_repeat = 0; */ /* STA(str)->line = 1; STA(str)->mac = NULL; */ /* init_smacros(csound, csound->smacros); */ /* } */ /* #endif */ void sread_initstr(CSOUND *csound, CORFIL *sco) { /* sread_alloc_globals(csound); */ IGN(sco); STA(inputs) = (IN_STACK*) csound->Malloc(csound, 20 * sizeof(IN_STACK)); STA(input_size) = 20; STA(input_cnt) = 0; STA(str) = STA(inputs); STA(str)->is_marked_repeat = 0; STA(str)->line = 1; STA(str)->mac = NULL; //init_smacros(csound, csound->smacros); { PRS_PARM qq; memset(&qq, '\0', sizeof(PRS_PARM)); csound_prslex_init(&qq.yyscanner); cs_init_smacros(csound, &qq, csound->smacros); csound_prsset_extra(&qq, qq.yyscanner); csound->expanded_sco = corfile_create_w(csound); /* printf("Input:\n%s<<<\n", */ /* corfile_body(csound->sreadStatics.str->cf)); */ csound_prslex(csound, qq.yyscanner); csound->DebugMsg(csound, "yielding >>%s<<\n", corfile_body(csound->expanded_sco)); csound_prslex_destroy(qq.yyscanner); corfile_rm(csound, &csound->scorestr); corfile_rewind(csound->expanded_sco); } } int sread(CSOUND *csound) /* called from main, reads from SCOREIN */ { /* each score statement gets a sortblock */ int rtncod; /* return code to calling program: */ /* 1 = section read */ /* 0 = end of file */ /* sread_alloc_globals(csound); */ STA(bp) = STA(prvibp) = csound->frstbp = NULL; STA(nxp) = NULL; STA(warpin) = 0; STA(lincnt) = 1; csound->sectcnt++; rtncod = 0; salcinit(csound); /* init the mem space for this section */ #ifdef never if (csound->score_parser) { extern int scope(CSOUND*); printf("**********************************************************\n"); printf("*******************EXPERIMENTAL CODE**********************\n"); printf("**********************************************************\n"); scope(csound); exit(0); } #endif while ((STA(op) = getop(csound)) != EOF) { /* read next op from scorefile */ rtncod = 1; salcblk(csound); /* build a line structure; init bp,nxp */ again: switch (STA(op)) { /* and dispatch on opcodes */ case 'y': { char *p = &(STA(bp)->text[1]); char q; //char *old_nxp = STA(nxp)-2; //printf("text=%s<<\n", STA(bp)->text); /* Measurement shows isdigit and 3 cases is about 30% */ /* faster than use of strchr (measured on Suse9.3) */ /* if (strchr("+-.0123456789", *p) != NULL) { */ while ((q=getscochar(csound,1))!='\n') *p++ = q; *p = '\0'; //printf("text=%s<<\n", STA(bp)->text); p = &(STA(bp)->text[1]); while (isblank(q=*p)) p++; if (isdigit(q) || q=='+' || q=='-' || q=='.') { double tt; char *tmp = p; tt = cs_strtod(p, &tmp); //printf("tt=%lf q=%c\n", tt, q); csound->randSeed1 = (int)tt; printf("seed from score %d\n", csound->randSeed1); } else { uint32_t tmp = (uint32_t) csound->GetRandomSeedFromTime(); while (tmp >= (uint32_t) 0x7FFFFFFE) tmp -= (uint32_t) 0x7FFFFFFE; csound->randSeed1 = tmp+1; printf("seed from clock %d\n", csound->randSeed1); } //printf("cleaning up\n"); break; //q = STA(op) = getop(csound); //printf("next op = %c(%.2x)\n", q, q); //goto again; } case 'i': case 'd': case 'f': case 'a': case 'q': ifa(csound); break; case 'w': STA(warpin)++; copypflds(csound); break; case 't': copypflds(csound); break; case 'b': /* Set a clock base */ { char *old_nxp = STA(nxp)-2; getpfld(csound); STA(clock_base) = stof(csound, STA(sp)); if (csound->oparms->msglevel & TIMEMSG) csound->Message(csound,Str("Clockbase = %f\n"), STA(clock_base)); flushlin(csound); STA(op) = getop(csound); STA(nxp) = old_nxp; *STA(nxp)++ = STA(op); /* Undo this line */ STA(nxp)++; goto again; } case 'C': /* toggle carry */ { char *old_nxp = STA(nxp)-2; getpfld(csound); STA(nocarry) = stof(csound, STA(sp))==0.0?1:0; //printf("nocarry = %d\n", STA(nocarry)); flushlin(csound); STA(op) = getop(csound); STA(nxp) = old_nxp; *STA(nxp)++ = STA(op); /* Undo this line */ STA(nxp)++; goto again; } case 's': case 'e': /* check for optional p1 before doing repeats */ copylin(csound); { char *p = &(STA(bp)->text[1]); char q; while (isblank(*p)) p++; /* Measurement shows isdigit and 3 cases is about 30% */ /* faster than use of strchr (measured on Suse9.3) */ /* if (strchr("+-.0123456789", *p) != NULL) { */ q = *p; if (isdigit(q) || q=='+' || q=='-' || q=='.') { double tt; char *tmp = p; tt = cs_strtod(p, &tmp); if (tmp != p && (*tmp == '\0' || isspace(*tmp))) { STA(bp)->pcnt = 1; STA(bp)->p1val = STA(bp)->p2val = STA(bp)->newp2 = (MYFLT) tt; } } else STA(bp)->p1val = STA(bp)->p2val = STA(bp)->newp2 = FL(0.0); } /* If we are in a repeat of a marked section ('n' statement), we must pop those inputs before doing an 'r' repeat. */ if (STA(str)->is_marked_repeat) { //printf("end of n; return to %d\n", STA(str)->oposit); corfile_set(csound->expanded_sco, STA(str)->oposit); STA(str)--; return rtncod; } /* while (STA(str)->is_marked_repeat && STA(input_cnt) > 0) { */ /* /\* close all marked repeat inputs *\/ */ /* //corfile_rm(&(STA(str)->cf)); */ /* STA(str)--; STA(input_cnt)--; */ /* } */ /* if (STA(repeat_cnt) != 0) { */ /* if (do_repeat(csound)) */ /* return rtncod; */ /* } */ if (STA(op) != 'e') { STA(clock_base) = FL(0.0); STA(warp_factor) = FL(1.0); STA(prvp2) = -FL(1.0); } return rtncod; /* #ifdef never */ /* case '}': */ /* { */ /* int temp; */ /* char *old_nxp = STA(nxp)-2; */ /* if ((temp=STA(repeat_cnt_n)[STA(repeat_index)])!=0) */ /* nested_repeat(csound); */ /* STA(op) = getop(csound); */ /* STA(nxp) = old_nxp; */ /* *STA(nxp)++ = STA(op); */ /* STA(nxp)++; */ /* goto again; */ /* } */ /* case '{': */ /* { */ /* char *old_nxp = STA(nxp)-2; */ /* int c, i; */ /* STA(repeat_index)++; */ /* if (UNLIKELY(STA(repeat_index) >= RPTDEPTH)) */ /* scorerr(csound, Str("Loops are nested too deeply")); */ /* STA(repeat_mm_n)[STA(repeat_index)] = */ /* (S_MACRO*)csound->Malloc(csound, sizeof(S_MACRO)); */ /* STA(repeat_cnt_n)[STA(repeat_index)] = 0; */ /* do { */ /* c = getscochar(csound, 1); */ /* } while(isblank(c)); */ /* while (isdigit(c)) { */ /* STA(repeat_cnt_n)[STA(repeat_index)] = */ /* 10 * STA(repeat_cnt_n)[STA(repeat_index)] + c - '0'; */ /* c = getscochar(csound, 1); */ /* } */ /* if (UNLIKELY(STA(repeat_cnt_n)[STA(repeat_index)] <= 0 */ /* || !isspace(c))) // != ' ' && c != '\t' && c != '\n'))) */ /* scorerr(csound, Str("{: invalid repeat count")); */ /* if (STA(repeat_index) > 1) { */ /* char st[41]; */ /* int j; */ /* for (j = 0; j < STA(repeat_index); j++) { */ /* st[j] = ' '; */ /* st[j+1] = '\0'; */ /* } */ /* if (csound->oparms->odebug/\*csound->oparms->msglevel & TIMEMSG*\/) */ /* csound->Message(csound, Str("%s Nested LOOP=%d Level:%d\n"), */ /* st, STA(repeat_cnt_n)[STA(repeat_index)], */ /* STA(repeat_index)); */ /* } */ /* else { */ /* if (csound->oparms->odebug/\*csound->oparms->msglevel & TIMEMSG*\/) */ /* csound->Message(csound, Str("External LOOP=%d Level:%d\n"), */ /* STA(repeat_cnt_n)[STA(repeat_index)], */ /* STA(repeat_index)); */ /* } */ /* while (isblank(c)) { */ /* c = getscochar(csound, 1); */ /* } */ /* for (i = 0; isNameChar(c, i) && i < (NAMELEN-1); i++) { */ /* STA(repeat_name_n)[STA(repeat_index)][i] = c; */ /* c = getscochar(csound, 1); */ /* } */ /* STA(repeat_name_n)[STA(repeat_index)][i] = '\0'; */ /* ungetscochar(csound, c); */ /* /\* Define macro for counter *\/ */ /* STA(repeat_mm_n)[STA(repeat_index)]->name = */ /* csound->Malloc(csound, */ /* strlen(STA(repeat_name_n)[STA(repeat_index)])+1); */ /* strcpy(STA(repeat_mm_n)[STA(repeat_index)]->name, */ /* STA(repeat_name_n)[STA(repeat_index)]); */ /* STA(repeat_mm_n)[STA(repeat_index)]->acnt = 0; */ /* STA(repeat_mm_n)[STA(repeat_index)]->body = corfile_create_r("0"); */ /* #ifdef MACDEBUG */ /* csound->DebugMsg(csound,"%s(%d): repeat %s zero %p\n", */ /* __FILE__, __LINE__, */ /* STA(repeat_name_n)[STA(repeat_index)], */ /* STA(repeat_mm_n)[STA(repeat_index)]->body); */ /* #endif */ /* STA(repeat_mm_n)[STA(repeat_index)]->next = STA(macros); */ /* STA(macros) = STA(repeat_mm_n)[STA(repeat_index)]; */ /* flushlin(csound); /\* Ignore rest of line *\/ */ /* STA(repeat_point_n)[STA(repeat_index)] = */ /* corfile_tell(STA(str)->cf); */ /* /\* { does not start a new section - akozar *\/ */ /* /\* STA(clock_base) = FL(0.0); */ /* STA(warp_factor) = FL(1.0); */ /* STA(prvp2) = -FL(1.0); *\/ */ /* STA(op) = getop(csound); */ /* STA(nxp) = old_nxp; */ /* *STA(nxp)++ = STA(op); */ /* STA(nxp)++; */ /* goto again; */ /* } */ /* #endif */ /* case 'r': /\* For now treat as s *\/ */ /* /\* First deal with previous section *\/ */ /* /\* If we are in a repeat of a marked section ('n' statement), */ /* we must pop those inputs before doing an 'r' repeat. *\/ */ /* if (STA(str)->is_marked_repeat) { */ /* while (STA(str)->is_marked_repeat && STA(input_cnt) > 0) { */ /* /\* close all marked repeat inputs *\/ */ /* //corfile_rm(&(STA(str)->cf)); */ /* STA(str)--; STA(input_cnt)--; */ /* } */ /* /\* last time thru an 'r', cleanup up 'r' before finishing 'n' *\/ */ /* if (STA(repeat_cnt) == 1) do_repeat(csound); */ /* if (STA(repeat_cnt) == 0) { */ /* /\* replace with 's' and end section if no previous 'r' */ /* or just finished an 'r' loop *\/ */ /* STA(bp)->text[0] = 's'; */ /* STA(clock_base) = FL(0.0); */ /* STA(warp_factor) = FL(1.0); */ /* STA(prvp2) = -FL(1.0); */ /* return rtncod; */ /* } */ /* } */ /* if (STA(repeat_cnt) != 0) { */ /* if (do_repeat(csound)) */ /* return rtncod; */ /* } */ /* /\* Then remember this state *\/ */ /* *(STA(nxp)-2) = 's'; *STA(nxp)++ = LF; */ /* if (STA(nxp) >= STA(memend)) /\* if this memblk exhausted *\/ */ /* expand_nxp(csound); */ /* { */ /* int c, i; */ /* STA(repeat_cnt) = 0; */ /* do { */ /* c = getscochar(csound, 1); */ /* } while (isblank(c)); */ /* while (isdigit(c)) { */ /* STA(repeat_cnt) = 10 * STA(repeat_cnt) + c - '0'; */ /* c = getscochar(csound, 1); */ /* } */ /* if (UNLIKELY(STA(repeat_cnt) <= 0 || !isspace(c))) */ /* //(c != ' ' && c != '\t' && c != '\n') */ /* scorerr(csound, Str("r: invalid repeat count")); */ /* if (csound->oparms->msglevel & TIMEMSG) */ /* csound->Message(csound, Str("Repeats=%d\n"), STA(repeat_cnt)); */ /* while (isblank(c)) { */ /* c = getscochar(csound, 1); */ /* } */ /* for (i = 0; isNameChar(c, i) && i < (NAMELEN-1); i++) { */ /* STA(repeat_name)[i] = c; */ /* c = getscochar(csound, 1); */ /* } */ /* STA(repeat_name)[i] = '\0'; */ /* ungetscochar(csound, c); */ /* flushlin(csound); /\* Ignore rest of line *\/ */ /* if (i) { */ /* /\* Only if there is a name: define macro for counter *\/ */ /* STA(repeat_mm) = (S_MACRO*) csound->Malloc(csound, sizeof(S_MACRO)); */ /* STA(repeat_mm)->name = csound->Malloc(csound, */ /* strlen(STA(repeat_name)) + 1); */ /* strcpy(STA(repeat_mm)->name, STA(repeat_name)); */ /* STA(repeat_mm)->acnt = 0; */ /* STA(repeat_mm)->body = corfile_create_r("1"); */ /* #ifdef MACDEBUG */ /* csound->DebugMsg(csound,"%s(%d): 1 %p\n", */ /* __FILE__, __LINE__,STA(repeat_mm)->body); */ /* #endif */ /* STA(repeat_mm)->next = STA(macros); */ /* STA(macros) = STA(repeat_mm); */ /* } */ /* STA(repeat_point) = corfile_tell(csound->expanded_sco); */ /* } */ /* STA(clock_base) = FL(0.0); */ /* STA(warp_factor) = FL(1.0); */ /* STA(prvp2) = -FL(1.0); */ /* return rtncod; */ case 'm': /* Remember this place */ { char *old_nxp = STA(nxp)-2; char buff[200]; int c; int i = 0, j; while (isblank(c = getscochar(csound, 1))); while (isNameChar(c, i)) { buff[i++] = c; c = getscochar(csound, 1); } buff[i] = '\0'; if (c != EOF && c != '\n') flushlin(csound); if (csound->oparms->msglevel & TIMEMSG) csound->Message(csound,Str("m Named section >>>%s<<<\n"), buff); //printf("*** last_name = %d\n", STA(last_name)); for (j=0; j=STA(last_name)) { j = ++STA(last_name); STA(names)[j].name =cs_strdup(csound, buff); } STA(names)[j].posit = corfile_tell(csound->expanded_sco); //printf("posit=%d\n", STA(names)[j].posit); STA(names)[j].line = STA(str)->line; //printf("line-%d\n",STA(names)[j].line); if (csound->oparms->msglevel & TIMEMSG) csound->Message(csound,Str("%d: %s position %d\n"), j, STA(names)[j].name, STA(names)[j].posit); STA(op) = getop(csound); STA(nxp) = old_nxp; *STA(nxp)++ = STA(op); /* Undo this line */ STA(nxp)++; goto again; /* suggested this loses a line?? */ } case 'n': { char *old_nxp = STA(nxp)-2; char buff[200]; int c; int i = 0; while (isblank(c = getscochar(csound, 1))); while (isNameChar(c, i)) { buff[i++] = c; c = getscochar(csound, 1); } buff[i] = '\0'; printf("n Named section %s\n", buff); if (c != '\n' && c != EOF) flushlin(csound); //printf("last_name %d\n", STA(last_name)); for (i = 0; i<=STA(last_name); i++) { //printf("n: %s %s(%d)\n", buff, STA(names)[i].name, i); if (strcmp(buff, STA(names)[i].name)==0) break; } //printf("i=%d\n", i); if (UNLIKELY(i > STA(last_name))) sreaderr(csound, Str("Name %s not found"), buff); else { //csound->Message(csound, Str("%d: %s (%ld)\n"), // i, buff, STA(names)[i].posit); STA(input_cnt)++; if (STA(input_cnt)>=STA(input_size)) { int old = STA(str)-STA(inputs); STA(input_size) += 20; STA(inputs) = csound->ReAlloc(csound, STA(inputs), STA(input_size) * sizeof(IN_STACK)); STA(str) = &STA(inputs)[old]; /* In case it moves */ } STA(str)++; STA(str)->is_marked_repeat = 1; STA(str)->line = STA(names)[i].line; STA(str)->oposit = corfile_tell(csound->expanded_sco); corfile_set(csound->expanded_sco, STA(names)[i].posit); //printf("posit was %d moved to %d\n", // STA(str)->oposit, STA(names)[i].posit); } STA(op) = getop(csound); STA(nxp) = old_nxp; *STA(nxp)++ = STA(op); /* Undo this line */ STA(nxp)++; goto again; } case 'v': /* Suggestion of Bryan Bales */ { /* Set local variability of time */ char *old_nxp = STA(nxp)-2; getpfld(csound); STA(warp_factor) = stof(csound, STA(sp)); if (csound->oparms->msglevel & TIMEMSG) csound->Message(csound, Str("Warp_factor = %f\n"), STA(warp_factor)); flushlin(csound); STA(op) = getop(csound); STA(nxp) = old_nxp; *STA(nxp)++ = STA(op); /* Undo this line */ STA(nxp)++; goto again; } case 'x': /* Skip section */ //printf("***skipping section\n"); flushlin(csound); while (1) { switch (STA(op) = getop(csound)) { case 's': case 'r': case 'm': case 'e': //printf("***skip ending with %c\n", STA(op)); salcblk(csound); /* place op, blank into text */ goto again; case EOF: goto ending; default: //printf("***ignoring %c\n", STA(op)); flushlin(csound); } } break; case -1: break; default: csound->Message(csound, Str("sread is confused on legal opcodes %c(%.2x)\n"), STA(op), STA(op)); break; } } ending: if (STA(repeat_cnt) > 0) { STA(op) = 'e'; salcblk(csound); /* if (do_repeat(csound)) */ /* return rtncod; */ *STA(nxp)++ = LF; } if (!rtncod) { /* Ending so clear macros */ while (STA(macros) != NULL) { undefine_score_macro(csound, STA(macros)->name); } } return rtncod; } static void copylin(CSOUND *csound) /* copy source line to srtblk */ { int c; STA(nxp)--; if (STA(nxp) >= STA(memend)) /* if this memblk exhausted */ expand_nxp(csound); do { c = getscochar(csound, 1); *STA(nxp)++ = c; } while (c != LF && c != EOF); if (c == EOF) *(STA(nxp)-1) = '\n'; /* Avoid EOF characters */ STA(lincnt)++; STA(linpos) = 0; } static void copypflds(CSOUND *csound) { STA(bp)->pcnt = 0; while (getpfld(csound)) /* copy each pfield, */ STA(bp)->pcnt++; /* count them, */ *(STA(nxp)-1) = LF; /* terminate with newline */ } static void ifa(CSOUND *csound) { SRTBLK *prvbp; int n, nocarry = 0; STA(bp)->pcnt = 0; while (getpfld(csound)) { /* while there's another pfield, */ nocarry = 0; ++STA(bp)->pcnt; /* if (UNLIKELY(++STA(bp)->pcnt == PMAX)) { */ /* sreaderr(csound, Str("instr pcount exceeds PMAX")); */ /* csound->Message(csound, Str(" remainder of line flushed\n")); */ /* flushlin(csound); */ /* continue; */ /* } */ if (*STA(sp) == '^' && STA(op) == 'i' && STA(bp)->pcnt == 2) { int foundplus = 0; if (*(STA(sp)+1)=='+') { STA(sp)++; foundplus = 1; } if (UNLIKELY(STA(prvp2)<0)) { sreaderr(csound,Str("No previous event for ^")); STA(prvp2) = STA(bp)->p2val = STA(warp_factor) * stof(csound, STA(sp)+1); } else if (UNLIKELY(isspace(*(STA(sp)+1)))) { /* stof() assumes no leading whitespace -- 070204, akozar */ sreaderr(csound, Str("illegal space following %s, zero substituted"), (foundplus ? "^+" : "^")); STA(prvp2) = STA(bp)->p2val = STA(prvp2); } else STA(prvp2) = STA(bp)->p2val = STA(prvp2) + STA(warp_factor) * stof(csound, STA(sp) + 1); } else if (STA(nxp)-STA(sp) == 2 && (*STA(sp) == '.' || *STA(sp) == '+')) { if (STA(op) == 'i' && (*STA(sp) == '.' || STA(bp)->pcnt == 2) && ((STA(bp)->pcnt >= 2 && (prvbp = STA(prvibp)) != NULL && STA(bp)->pcnt <= prvbp->pcnt) || (STA(bp)->pcnt == 1 && (prvbp = STA(bp)->prvblk) != NULL && prvbp->text[0] == 'i'))) { if (*STA(sp) == '.') { STA(nxp) = STA(sp); pcopy(csound, (int) STA(bp)->pcnt, 1, prvbp); if (STA(bp)->pcnt >= 2) STA(prvp2) = STA(bp)->p2val; } else /* need the fabs() in case of neg p3 */ STA(prvp2) = STA(bp)->p2val = prvbp->p2val + FABS(prvbp->p3val); } else carryerror(csound); } else if (*STA(sp) == '!') { int getmore = 0; if (UNLIKELY(STA(op) != 'i')) { *(STA(nxp)-1) = '\0'; getmore = 1; sreaderr(csound, Str("ignoring '%s' in '%c' event"), STA(sp), STA(op)); } else if (UNLIKELY(STA(bp)->pcnt < 4)) { sreaderr(csound, Str("! invalid in p1, p2, or p3")); csound->Message(csound, Str(" remainder of line flushed\n")); flushlin(csound); } else if (UNLIKELY(STA(nxp)-STA(sp) != 2)) { sreaderr(csound, Str("illegal character after !: '%c'"), *(STA(sp)+1)); csound->Message(csound, Str(" remainder of line flushed\n")); flushlin(csound); } else { nocarry = 1; /* only set when no syntax errors */ flushlin(csound); } /* but always delete the pfield beginning with '!' */ STA(nxp) = STA(sp); STA(bp)->pcnt--; if (getmore) continue; /* not the best, but not easy to delete event */ /* since ifa() doesn't return anything */ else break; } else switch (STA(bp)->pcnt) { /* watch for p1,p2,p3, */ case 1: /* & MYFLT, setinsno..*/ if ((STA(op) == 'i' || STA(op) == 'd' || STA(op) == 'q') && *STA(sp) == '"') { /* csound->DebugMsg(csound,"***Entering second dubious code scnt=%d\n", csound->scnt0); */ STA(bp)->p1val = SSTRCOD; /* allow string name */ } else { STA(bp)->p1val = stof(csound, STA(sp)); } if (STA(op) == 'i' || STA(op) == 'd') setprv(csound); else STA(prvibp) = NULL; break; case 2: STA(prvp2) = STA(bp)->p2val = STA(warp_factor)*stof(csound, STA(sp)) + STA(clock_base); break; case 3: if (STA(op) == 'i') STA(bp)->p3val = STA(warp_factor) * stof(csound, STA(sp)); else STA(bp)->p3val = stof(csound, STA(sp)); break; default:break; } switch (STA(bp)->pcnt) { /* newp2, newp3: */ case 2: if (STA(warpin)) { /* for warpin, */ getpfld(csound); /* newp2 follows */ STA(bp)->newp2 = STA(warp_factor) * stof(csound, STA(sp)) + STA(clock_base); STA(nxp) = STA(sp); /* (skip text) */ } else STA(bp)->newp2 = STA(bp)->p2val; /* else use p2val */ break; case 3: if (STA(warpin) && (STA(op) == 'i' || STA(op) == 'f')) { getpfld(csound); /* same for newp3 */ STA(bp)->newp3 = STA(warp_factor) * stof(csound, STA(sp)); STA(nxp) = STA(sp); } else STA(bp)->newp3 = STA(bp)->p3val; break; } } if (STA(nocarry) && (STA(bp)->pcnt<3) && STA(op) == 'i' && ((prvbp = STA(prvibp)) != NULL || (!STA(bp)->pcnt && (prvbp = STA(bp)->prvblk) != NULL && prvbp->text[0] == 'i'))){ /* carry p1-p3 */ int pcnt = STA(bp)->pcnt; n = 3-pcnt; pcopy(csound, pcnt + 1, n, prvbp); STA(bp)->pcnt = 3; } if (STA(op) == 'i' && !nocarry && /* then carry any rem pflds */ !STA(nocarry) && ((prvbp = STA(prvibp)) != NULL || (!STA(bp)->pcnt && (prvbp = STA(bp)->prvblk) != NULL && prvbp->text[0] == 'i')) && (n = prvbp->pcnt - STA(bp)->pcnt) > 0) { //printf("carrying p-fields\n"); pcopy(csound, (int) STA(bp)->pcnt + 1, n, prvbp); STA(bp)->pcnt += n; } *(STA(nxp)-1) = LF; /* terminate this stmnt with newline */ } static void setprv(CSOUND *csound) /* set insno = (int) p1val */ { /* prvibp = prv note, same insno */ SRTBLK *p = STA(bp); int16 n; if (csound->ISSTRCOD(STA(bp)->p1val) && *STA(sp) == '"') { /* IV - Oct 31 2002 */ int sign = 0; char name[MAXNAME], *c, *s = STA(sp); /* unquote instrument name */ c = name; while (*++s != '"') *c++ = *s; *c = '\0'; if (*name=='-') { sign = 1; printf("negative name %s\n", name); } /* find corresponding insno */ if (UNLIKELY(!(n = (int16) named_instr_find(csound, name+sign)))) { csound->Message(csound, Str("WARNING: instr %s not found, " "assuming insno = -1\n"), name); n = -1; } if (sign) n = -n; } else n = (int16) STA(bp)->p1val; /* set current insno */ STA(bp)->insno = n; while ((p = p->prvblk) != NULL) if (p->insno == n) { STA(prvibp) = p; /* find prev same */ return; } STA(prvibp) = NULL; /* if there is one */ } static void carryerror(CSOUND *csound) /* print offending text line */ { /* (partial) */ char *p; csound->Message(csound, Str("sread: illegal use of carry, " " 0 substituted\n")); *(STA(nxp) - 3) = SP; p = STA(bp)->text; while (p <= STA(nxp) - 2) csound->Message(csound, "%c", *p++); csound->Message(csound, "<=\n"); print_input_backtrace(csound, 1, csoundMessage); *(STA(nxp) - 2) = '0'; } static void pcopy(CSOUND *csound, int pfno, int ncopy, SRTBLK *prvbp) /* cpy pfields from prev note of this instr */ /* begin at pfno, copy 'ncopy' fields */ /* uses *nxp++; sp untouched */ { char *p, *pp, c; int n; pp = prvbp->text; /* in text of prev note, */ n = pfno; while (n--) while (*pp++ != SP) /* locate starting pfld */ ; n = ncopy; p = STA(nxp); while (n--) { /* and copy n pflds */ if (*pp != '"') while ((*p++ = c = *pp++) != SP && c != LF) ; else { *p++ = *pp++; while ((*p++ = *pp++) != '"') ; *p++ = *pp++; } switch (pfno) { case 1: STA(bp)->p1val = prvbp->p1val; /* with p1-p3 vals */ setprv(csound); break; case 2: if (*(p-2) == '+') /* (interpr . of +) */ STA(prvp2) = STA(bp)->p2val = prvbp->p2val + FABS(prvbp->p3val); else STA(prvp2) = STA(bp)->p2val = prvbp->p2val; STA(bp)->newp2 = STA(bp)->p2val; break; case 3: STA(bp)->newp3 = STA(bp)->p3val = prvbp->p3val; break; default: break; } STA(bp)->lineno = prvbp->lineno; pfno++; } STA(nxp) = p; /* adjust globl nxp pntr */ } static void salcinit(CSOUND *csound) { /* init the sorter mem space for a new section */ if (STA(curmem) == NULL) { /* alloc 1st memblk if nec; init *nxp to this */ STA(curmem) = (char*) csound->Calloc(csound, (size_t) (MEMSIZ + MARGIN)); STA(memend) = (char*) STA(curmem) + MEMSIZ; } STA(nxp) = (char*) STA(curmem); } static void salcblk(CSOUND *csound) { /* alloc a srtblk from current mem space: */ SRTBLK *prvbp; /* align following *nxp, set new bp, nxp */ /* set srtblk lnks, put op+blank in text */ if (STA(nxp) >= STA(memend)) /* if this memblk exhausted */ expand_nxp(csound); /* now allocate a srtblk from this space: */ prvbp = STA(bp); STA(bp) = (SRTBLK*) (((uintptr_t) STA(nxp) + (uintptr_t)7) & ~((uintptr_t)7)); if (csound->frstbp == NULL) csound->frstbp = STA(bp); if (prvbp != NULL) prvbp->nxtblk = STA(bp); /* link with prev srtblk */ STA(bp)->nxtblk = NULL; STA(bp)->prvblk = prvbp; STA(bp)->insno = 0; STA(bp)->pcnt = 0; STA(bp)->lineno = STA(lincnt); STA(nxp) = &(STA(bp)->text[0]); *STA(nxp)++ = STA(op); /* place op, blank into text */ *STA(nxp)++ = SP; *STA(nxp) = '\0'; } void sfree(CSOUND *csound) /* free all sorter allocated space */ { /* called at completion of sort */ /* sread_alloc_globals(csound); */ if (STA(curmem) != NULL) { csound->Free(csound, STA(curmem)); STA(curmem) = NULL; } while (STA(str) != &STA(inputs)[0]) { //corfile_rm(&(STA(str)->cf)); STA(str)--; } corfile_rm(csound, &(csound->scorestr)); } static void flushlin(CSOUND *csound) { /* flush input to end-of-line; inc lincnt */ int c; while ((c = getscochar(csound, 0)) != LF && c != EOF) ; STA(linpos) = 0; STA(lincnt)++; } /* unused at the moment static inline int check_preproc_name(CSOUND *csound, const char *name) { int i; char c; for (i = 1; name[i] != '\0'; i++) { c = (char) getscochar(csound, 1); if (c != name[i]) return 0; } return 1; } */ static int sget1(CSOUND *csound) /* get first non-white, non-comment char */ { int c; srch: while (isblank(c = getscochar(csound, 1)) || c == LF) if (c == LF) { STA(lincnt)++; STA(linpos) = 0; } if (c == ';' || c == 'c') { flushlin(csound); goto srch; } #ifdef never /* if (c == '\\') { /\* Deal with continuations and specials *\/ */ /* again: */ /* c = getscochar(csound, 1); */ /* if (c==';') { */ /* while ((c=getscochar(csound, 1)!='\n') && c!=EOF); */ /* goto srch; */ /* } */ /* if (isblank(c)) goto again; */ /* if (c!='\n' && c!=EOF) { */ /* csound->Message(csound, Str("Improper \\")); */ /* while (c!='\n' && c!=EOF) c = getscochar(csound, 1); */ /* } */ /* goto srch; */ /* } */ /* if (c == '/') { /\* Could be a C-comment *\/ */ /* c = getscochar(csound, 1); */ /* if (c != '*') { */ /* ungetscochar(csound, c); */ /* c = '/'; */ /* } */ /* else { /\* It is a comment *\/ */ /* top: /\* ignore comment chars *\/ */ /* c = getscochar(csound, 0); */ /* switch (c) { */ /* case '*': */ /* stars: /\* is next char / ? *\/ */ /* c = getscochar(csound, 0); */ /* switch (c) { */ /* case '*': goto stars; */ /* default: goto top; */ /* case '/': goto srch; */ /* case EOF: return EOF; */ /* } */ /* case EOF: return EOF; */ /* default: goto top; */ /* } */ /* } */ /* } */ /* if (c == '#') { */ /* int mlen = 40; */ /* char *mname = csound->Malloc(csound, 40); /\* Start Macro definition *\/ */ /* int i = 0; */ /* while (isspace((c = getscochar(csound, 1)))); */ /* if (c == 'd') { */ /* int arg = 0; */ /* S_MACRO *mm = (S_MACRO*) csound->Malloc(csound, sizeof(S_MACRO)); */ /* mm->margs = MARGS; */ /* if (UNLIKELY(!check_preproc_name(csound, "define"))) { */ /* csound->Message(csound, Str("Not #define")); */ /* csound->Free(csound, mm); */ /* csound->Free(csound, mname); */ /* flushlin(csound); */ /* goto srch; */ /* } */ /* while (isspace((c = getscochar(csound, 1)))); */ /* while (isNameChar(c, i)) { */ /* char *new; */ /* mname[i++] = c; */ /* if (i==mlen) { */ /* new = (char *) csound->ReAlloc(csound, mname, mlen+=40); */ /* if (new==NULL) { */ /* fprintf(stderr, "Out of Memory\n"); */ /* exit(7); */ /* } */ /* mname = new; */ /* } */ /* c = getscochar(csound, 1); */ /* } */ /* mname[i] = '\0'; */ /* if (csound->oparms->msglevel & TIMEMSG) */ /* csound->Message(csound, Str("Macro definition for %s\n"), mname); */ /* mm->name = csound->Malloc(csound, i + 1); */ /* strcpy(mm->name, mname); */ /* if (c == '(') { /\* arguments *\/ */ /* do { */ /* while (isspace((c = getscochar(csound, 1)))); */ /* i = 0; */ /* while (isNameChar(c, i)) { */ /* char *new; */ /* mname[i++] = c; */ /* if (i==mlen) { */ /* new = (char *)csound->ReAlloc(csound, mname, mlen+=40); */ /* if (new==NULL) { */ /* fprintf(stderr, "Out of Memory\n"); */ /* exit(7); */ /* } */ /* mname = new; */ /* } */ /* c = getscochar(csound, 1); */ /* } */ /* mname[i] = '\0'; */ /* mm->arg[arg] = csound->Malloc(csound, i+1); */ /* strcpy(mm->arg[arg++], mname); */ /* if (arg>=mm->margs) { */ /* mm = (S_MACRO*)csound->ReAlloc(csound, mm, */ /* sizeof(S_MACRO)+mm->margs*sizeof(char*)); */ /* mm->margs += MARGS; */ /* } */ /* while (isspace(c)) c = getscochar(csound, 1); */ /* } while (c=='\'' || c=='#'); */ /* if (UNLIKELY(c!=')')) { */ /* csound->Message(csound, Str("macro error\n")); */ /* flushlin(csound); */ /* csound->Free(csound, mname); */ /* goto srch; */ /* } */ /* } */ /* mm->acnt = arg; */ /* while ((c = getscochar(csound, 1)) != '#') { /\* Skip to next # *\/ */ /* if (UNLIKELY(c==EOF)) */ /* scorerr(csound, Str("Syntax error in macro definition")); */ /* } */ /* mm->body = corfile_create_w(); */ /* #ifdef MACDEBUG */ /* csound->DebugMsg(csound,"%s(%d): macro %s %p\n", */ /* __FILE__, __LINE__, mname, mm->body); */ /* #endif */ /* while ((c = getscochar(csound, 0)) != '#') { // Do not expand here!! */ /* if (UNLIKELY(c==EOF)) */ /* scorerr(csound, Str("Syntax error in macro definition")); */ /* corfile_putc(c, mm->body); */ /* if (c=='\\') { */ /* corfile_putc(getscochar(csound, 0), mm->body); // Allow escaped # */ /* } */ /* if (c=='\n') STA(lincnt)++; */ /* } */ /* corfile_rewind(mm->body); */ /* mm->next = STA(macros); */ /* STA(macros) = mm; */ /* #ifdef MACDEBUG */ /* csound->Message(csound, Str("Macro %s with %d arguments defined\n"), */ /* mm->name, mm->acnt); */ /* csound->Message(csound, "with body %s\n", corfile_body(mm->body)); */ /* #endif */ /* c = ' '; */ /* flushlin(csound); */ /* csound->Free(csound, mname); */ /* goto srch; */ /* } */ /* else if (c == 'i') { */ /* int delim; */ /* if (UNLIKELY(!check_preproc_name(csound, "include"))) { */ /* csound->Message(csound, Str("Not #include")); */ /* flushlin(csound); */ /* csound->Free(csound, mname); */ /* goto srch; */ /* } */ /* while (isspace((c = getscochar(csound, 1)))); */ /* delim = c; */ /* i = 0; */ /* while ((c=getscochar(csound, 1))!=delim) { */ /* char *new; */ /* mname[i++] = c; */ /* if (i==mlen) { */ /* new = (char *)realloc(mname, mlen+=40); */ /* if (new==NULL) { */ /* fprintf(stderr, "Out of Memory\n"); */ /* exit(7); */ /* } */ /* mname = new; */ /* } */ /* } */ /* mname[i]='\0'; */ /* while ((c=getscochar(csound, 1))!='\n'); */ /* STA(input_cnt)++; */ /* if (STA(input_cnt)>=STA(input_size)) { */ /* int old = STA(str)-STA(inputs); */ /* STA(input_size) += 20; */ /* STA(inputs) = csound->ReAlloc(csound, STA(inputs), STA(input_size) */ /* * sizeof(IN_STACK)); */ /* STA(str) = &STA(inputs)[old]; /\* In case it moves *\/ */ /* } */ /* STA(str)++; */ /* STA(str)->is_marked_repeat = 0; */ /* #ifdef HAVE_CURL */ /* if (strstr(mname, "://")) */ /* STA(str)->cf = copy_url_corefile(csound, mname, 1); */ /* else */ /* #endif */ /* STA(str)->cf = copy_to_corefile(csound, mname, "INCDIR", 1); */ /* if (STA(str)->cf == NULL) { */ /* STA(str)--; */ /* STA(str)->line--; /\* include was one line earlier *\/ */ /* STA(linepos) = 0; */ /* scorerr(csound, Str("Cannot open #include'd file %s"), mname); */ /* } */ /* else { */ /* STA(str)->line = 1; */ /* csound->Free(csound, mname); */ /* goto srch; */ /* } */ /* } */ /* else if (c == 'u') { */ /* if (UNLIKELY(!check_preproc_name(csound, "undef"))) { */ /* csound->Message(csound, Str("Not #undef")); */ /* flushlin(csound); */ /* csound->Free(csound, mname); */ /* goto srch; */ /* } */ /* while (isspace((c = getscochar(csound, 1)))); */ /* while (isNameChar(c, i)) { */ /* char *new; */ /* mname[i++] = c; */ /* if (i==mlen) { */ /* new = (char *)realloc(mname, mlen+=40); */ /* if (new==NULL) { */ /* fprintf(stderr, "Out of Memory\n"); */ /* exit(7); */ /* } */ /* mname = new; */ /* } */ /* c = getscochar(csound, 1); */ /* } */ /* mname[i] = '\0'; */ /* if (csound->oparms->msglevel & TIMEMSG) */ /* csound->Message(csound, Str("macro %s undefined\n"), mname); */ /* undefine_score_macro(csound, mname); */ /* while (c != '\n' && c != EOF) */ /* c = getscochar(csound, 1); /\* ignore rest of line *\/ */ /* } */ /* #ifdef never */ /* else if (c=='e') { */ /* if (UNLIKELY(!check_preproc_name(csound, "exit"))) { */ /* csound->Message(csound, "Not #exit"); */ /* flushlin(csound); */ /* csound->Free(csound, mname); */ /* goto srch; */ /* } */ /* while (c != '\n' && c != EOF) */ /* c = getscochar(csound, 1); /\* ignore rest of line *\/ */ /* } */ /* #endif */ /* else { */ /* sreaderr(csound, Str("unknown # option")); */ /* flushlin(csound); */ /* } */ /* csound->Free(csound, mname); */ /* goto srch; */ /* } */ #endif return c; } static int getop(CSOUND *csound) /* get next legal opcode */ { int c; nextc: c = sget1(csound); /* get first active char */ switch (c) { /* and check legality */ case 'a': /* Advance time */ case 'b': /* Reset base clock */ case 'd': /* De-note */ case 'C': /* toggle carry flag */ case 'e': /* End of all */ case 'f': /* f-table */ case 'i': /* Instrument */ case 'm': /* Mark this point */ case 'n': /* Duplicate from named position */ case 'q': /* quiet instrument ie mute */ case 'r': /* Repeated section */ case 's': /* Section */ case 't': /* time warp */ case 'v': /* Local warping */ case 'w': case 'x': case 'y': /* Set random seed */ case '{': /* Section brackets */ case '}': case EOF: break; /* if ok, go with it */ default: /* else complain */ sreaderr(csound, Str("illegal opcode %c"), c); csound->Message(csound,Str(" remainder of line flushed\n")); flushlin(csound); goto nextc; } STA(linpos)++; return(c); } static MYFLT read_expression(CSOUND *csound) { char stack[30]; MYFLT vv[30]; char *op = stack - 1; MYFLT *pv = vv - 1; char buffer[100]; int i, c; int type = 0; /* 1 -> expecting binary operator,')', or ']'; else 0 */ *++op = '['; c = getscochar(csound, 1); do { //printf("read_expression: c=%c\n", c); switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '.': if (UNLIKELY(type)) { scorerr(csound, Str("illegal placement of number in [] " "expression")); } parseNumber: i = 0; do { buffer[i++] = c; c = getscochar(csound, 1); } while (isdigit(c) || c == '.'); if (c == 'e' || c == 'E') { buffer[i++] = c; c = getscochar(csound, 1); if (c == '+' || c == '-') { buffer[i++] = c; c = getscochar(csound, 1); } while (isdigit(c)) { buffer[i++] = c; c = getscochar(csound, 1); } } buffer[i] = '\0'; *++pv = stof(csound, buffer); type = 1; break; case '~': if (UNLIKELY(type)) { scorerr(csound, Str("illegal placement of operator ~ in [] " "expression")); } *++pv = (MYFLT) (csound->Rand31(&(csound->randSeed1)) - 1) / FL(2147483645); type = 1; c = getscochar(csound, 1); break; case '@': if (UNLIKELY(type)) { scorerr(csound, Str("illegal placement of operator @ or @@ in" " [] expression")); } { int n = 0; int k = 0; /* 0 or 1 depending on guard bit */ c = getscochar(csound, 1); if (c=='@') { k = 1; c = getscochar(csound, 1);} while (isdigit(c)) { n = 10*n + c - '0'; c = getscochar(csound, 1); } i = 1; while (i<=n-k && i< 0x4000000) i <<= 1; *++pv = (MYFLT)(i+k); type = 1; } break; case '+': case '-': if (!type) goto parseNumber; if (*op != '[' && *op != '(') { MYFLT v = operate(csound, *(pv-1), *pv, *op); op--; pv--; *pv = v; } type = 0; *++op = c; c = getscochar(csound, 1); break; case '*': case '/': case '%': if (UNLIKELY(!type)) { scorerr(csound, Str("illegal placement of operator %c in [] " "expression"), c); } if (*op == '*' || *op == '/' || *op == '%') { MYFLT v = operate(csound, *(pv-1), *pv, *op); op--; pv--; *pv = v; } type = 0; *++op = c; c = getscochar(csound, 1); break; case '&': case '|': case '#': if (UNLIKELY(!type)) { scorerr(csound, Str("illegal placement of operator %c in [] " "expression"), c); } if (*op == '|' || *op == '&' || *op == '#') { MYFLT v = operate(csound, *(pv-1), *pv, *op); op--; pv--; *pv = v; } type = 0; *++op = c; c = getscochar(csound, 1); break; case '(': if (UNLIKELY(type)) { scorerr(csound, Str("illegal placement of '(' in [] expression")); } type = 0; *++op = c; c = getscochar(csound, 1); break; case ')': if (UNLIKELY(!type)) { scorerr(csound, Str("missing operand before ')' in [] expression")); } while (*op != '(') { MYFLT v = operate(csound, *(pv-1), *pv, *op); op--; pv--; *pv = v; } type = 1; op--; c = getscochar(csound, 1); break; case '^': type = 0; *++op = c; c = getscochar(csound, 1); break; case '[': if (UNLIKELY(type)) { scorerr(csound, Str("illegal placement of '[' in [] expression")); } type = 1; { //int i; MYFLT x; //for (i=0;i<=pv-vv;i++) printf(" %lf ", vv[i]); //printf("| %d\n", pv-vv); x = read_expression(csound); *++pv = x; //printf("recursion gives %lf (%lf)\n", x,*(pv-1)); //for (i=0;i()\"~!", c) == NULL) { */ if (!isdigit(c) && c!='.' && c!='+' && c!='-' && c!='^' && c!='n' && c!='p' && c!='<' && c!='>' && c!='(' && c!=')' && c!='"' && c!='~' && c!='!' && c!='z') { ungetscochar(csound, c); /* then no more pfields */ if (UNLIKELY(STA(linpos))) { sreaderr(csound, Str("unexpected char %c"), c); csound->Message(csound, Str(" remainder of line flushed\n")); flushlin(csound); } return(0); /* so return */ } p = STA(sp) = STA(nxp); /* else start copying to text */ *p++ = c; STA(linpos)++; if (c == '"') { /* if have quoted string, */ /* IV - Oct 31 2002: allow string instr name for i and q events */ if (UNLIKELY(STA(bp)->pcnt < 3 && !((STA(op) == 'i' || STA(op) == 'd' || STA(op) == 'q') && !STA(bp)->pcnt))) { sreaderr(csound, Str("illegally placed string")); csound->Message(csound, Str(" remainder of line flushed\n")); flushlin(csound); return(0); } while ((c = getscochar(csound, 1)) != '"') { if (UNLIKELY(c == LF || c == EOF)) { sreaderr(csound, Str("unmatched quote")); return(0); } *p++ = c; /* copy to matched quote */ /* **** CHECK **** */ if (p >= STA(memend)) p = (char*) ((uintptr_t) p + expand_nxp(csound)); /* **** END CHECK **** */ } *p++ = c; goto blank; } while (1) { c = getscochar(csound, 1); /* else while legal chars, continue to bld string */ /* if (strchr("0123456789.+-eEnp<>()~", c) != NULL) { */ if (isdigit(c) || c=='.' || c=='+' || c=='-' || c=='e' || c=='E' || c=='n' || c=='p' || c=='<' || c=='>' || c=='(' || c==')' || c=='~' || c=='z') { *p++ = c; /* **** CHECK **** */ if (p >= STA(memend)) p = (char*) ((uintptr_t) p + expand_nxp(csound)); /* **** END CHECK **** */ } else { /* any illegal is delimiter */ ungetscochar(csound, c); break; } } blank: *p++ = SP; STA(nxp) = p; /* add blank */ return(1); /* and report ok */ } MYFLT stof(CSOUND *csound, char s[]) /* convert string to MYFLT */ /* (assumes no white space at beginning */ { /* but a blank or nl at end) */ char *p; MYFLT x = (MYFLT) cs_strtod(s, &p); if (*p=='z') return FL(800000000000.0); /* 25367 years */ if (UNLIKELY(s == p || !(*p == '\0' || isspace(*p)))) { csound->Message(csound, Str("sread: illegal number format: ")); p = s; while (!(*p == '\0' || isspace(*p))) { csound->Message(csound, "%c", *p); *p++ = '0'; } csound->Message(csound,Str(" zero substituted.\n")); print_input_backtrace(csound, 1, csoundMessage); return FL(0.0); } return x; } csound-6.10.0/Engine/swritestr.c000066400000000000000000000421341321653344700165240ustar00rootroot00000000000000/* swritestr.c: Copyright (C) 2011 John ffitch (after Barry Vercoe) This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* SWRITESTR.C */ #include #include #include #include "corfile.h" static SRTBLK *nxtins(SRTBLK *), *prvins(SRTBLK *); static char *pfout(CSOUND *,SRTBLK *, char *, int, int, CORFIL *sco); static char *nextp(CSOUND *,SRTBLK *, char *, int, int, CORFIL *sco); static char *prevp(CSOUND *,SRTBLK *, char *, int, int, CORFIL *sco); static char *ramp(CSOUND *,SRTBLK *, char *, int, int, CORFIL *sco); static char *expramp(CSOUND *,SRTBLK *, char *, int, int,CORFIL *sco); static char *randramp(CSOUND *,SRTBLK *, char *, int, int, CORFIL *sco); static char *pfStr(CSOUND *,char *, int, int, CORFIL *sco); static char *fpnum(CSOUND *,char *, int, int, CORFIL *sco); static void fltout(CSOUND *csound, MYFLT n, CORFIL *sco) { char *c, buffer[1024]; #ifdef USE_DOUBLE CS_SPRINTF(buffer, "%.17lg", n); #else CS_SPRINTF(buffer, "%.9g", n); #endif /* corfile_puts(buffer, sco); */ for (c = buffer; *c != '\0'; c++) corfile_putc(csound, *c, sco); } /* The 'first' parameter was added so that the copies of p2 and p3 are made only in scores loaded before the first compilation before performance starts; in this case swritestr() is called with first = 0; In the case of scores passed in after Csound is running, events are scheduled as RT events through the linevent mechanism (linevent.c) and in that scenario, cannot contain duplicate p2 and p3 values. In this case, swritestr() is called with first = 1; VL - new in Csound 6. */ void swritestr(CSOUND *csound, CORFIL *sco, int first) { SRTBLK *bp; char *p, c, isntAfunc; int lincnt, pcnt=0; if (UNLIKELY((bp = csound->frstbp) == NULL)) return; lincnt = 0; if ((c = bp->text[0]) != 'w' && c != 's' && c != 'e') { /* if no warp stmnt but real data, */ /* create warp-format indicator */ if (first) corfile_puts(csound, "w 0 60\n", sco); lincnt++; } nxtlin: lincnt++; /* now for each line: */ p = bp->text; c = *p++; isntAfunc = 1; switch (c) { case 'z': printf("skip z\n"); //corfile_putc('\n', sco); break; case 'f': isntAfunc = 0; /* fall through */ case 'q': case 'i': case 'd': case 'a': corfile_putc(csound, c, sco); corfile_putc(csound, *p++, sco); while ((c = *p++) != SP && c != LF) corfile_putc(csound, c, sco); /* put p1 */ corfile_putc(csound, c, sco); if (c == LF) break; fltout(csound, bp->p2val, sco); /* put p2val, */ corfile_putc(csound, SP, sco); if (first) fltout(csound, bp->newp2, sco); /* newp2, */ while ((c = *p++) != SP && c != LF) ; corfile_putc(csound, c, sco); /* and delim */ if (c == LF) break; if (isntAfunc) { fltout(csound, bp->p3val, sco); /* put p3val, */ corfile_putc(csound, SP, sco); if (first) fltout(csound, bp->newp3, sco); /* newp3, */ while ((c = *p++) != SP && c != LF) ; } else { /*make sure p3s (table length) are ints */ char temp[256]; snprintf(temp,256,"%d ",(int32)bp->p3val); /* put p3val */ fpnum(csound,temp, lincnt, pcnt, sco); corfile_putc(csound, SP, sco); if (first) { snprintf(temp,256,"%d ",(int32)bp->newp3); /* put newp3 */ fpnum(csound,temp, lincnt, pcnt, sco); } while ((c = *p++) != SP && c != LF) ; } pcnt = 3; while (c != LF) { pcnt++; corfile_putc(csound, SP, sco); p = pfout(csound,bp,p,lincnt,pcnt, sco); /* now put each pfield */ c = *p++; } corfile_putc(csound, '\n', sco); break; case 's': case 'e': if (bp->pcnt > 0) { char buffer[80]; CS_SPRINTF(buffer, "f 0 %f %f\n", bp->p2val, bp->newp2); corfile_puts(csound, buffer, sco); } corfile_putc(csound, c, sco); corfile_putc(csound, LF, sco); break; case 'w': case 't': corfile_putc(csound, c, sco); while ((c = *p++) != LF) /* put entire line */ corfile_putc(csound, c, sco); corfile_putc(csound, LF, sco); break; case 'x': case 'y': case -1: break; default: csound->Message(csound, Str("swrite: unexpected opcode %c, section %d line %d\n"), c, csound->sectcnt, lincnt); break; } if ((bp = bp->nxtblk) != NULL) goto nxtlin; } static char *pfout(CSOUND *csound, SRTBLK *bp, char *p, int lincnt, int pcnt, CORFIL *sco) { switch (*p) { case 'n': p = nextp(csound, bp,p, lincnt, pcnt, sco); break; case 'p': p = prevp(csound, bp,p, lincnt, pcnt, sco); break; case '<': case '>': p = ramp(csound, bp,p, lincnt, pcnt, sco); break; case '(': case ')': p = expramp(csound, bp, p, lincnt, pcnt, sco); break; case '~': p = randramp(csound, bp, p, lincnt, pcnt, sco); break; case '"': p = pfStr(csound, p, lincnt, pcnt, sco); break; default: p = fpnum(csound, p, lincnt, pcnt, sco); break; } return(p); } static SRTBLK *nxtins(SRTBLK *bp) /* find nxt note with same p1 */ { MYFLT p1; p1 = bp->p1val; while ((bp = bp->nxtblk) != NULL && (bp->p1val != p1 || bp->text[0] != 'i')) ; return(bp); } static SRTBLK *prvins(SRTBLK *bp) /* find prv note with same p1 */ { MYFLT p1; p1 = bp->p1val; while ((bp = bp->prvblk) != NULL && (bp->p1val != p1 || bp->text[0] != 'i')) ; return(bp); } static char *nextp(CSOUND *csound, SRTBLK *bp, char *p, int lincnt, int pcnt, CORFIL *sco) { char *q; int n; q = p; p++; /* 1st char */ if (UNLIKELY(*p++ != 'p')) /* 2nd char */ goto error; n = 999; if (isdigit(*p)) n = *p++ - '0'; if (isdigit(*p)) /* n is np subscript no */ n = 10*n + (*p++ - '0'); if (UNLIKELY(*p != SP && *p != LF)) goto error; if (LIKELY((bp = nxtins(bp)) != NULL /* for nxtins, same p1 */ && n <= bp->pcnt)) { q = bp->text; while (n--) while (*q++ != SP) /* go find the pfield */ ; pfout(csound,bp,q,lincnt,pcnt,sco); /* and put it out */ } else { error: csound->Message(csound,Str("swrite: output, sect%d line%d p%d makes" " illegal reference to "), csound->sectcnt,lincnt,pcnt); while (q < p) csound->Message(csound,"%c", *q++); while (*p != SP && *p != LF) csound->Message(csound,"%c", *p++); csound->Message(csound,Str(" Zero substituted\n")); corfile_putc(csound, '0', sco); } return(p); } static char *prevp(CSOUND *csound, SRTBLK *bp, char *p, int lincnt, int pcnt, CORFIL *sco) { char *q; int n; q = p; p++; /* 1st char */ if (UNLIKELY(*p++ != 'p')) /* 2nd char */ goto error; n = 999; if (isdigit(*p)) n = *p++ - '0'; if (isdigit(*p)) /* n is np subscript no */ n = 10*n + (*p++ - '0'); if (UNLIKELY(*p != SP && *p != LF)) goto error; if (LIKELY((bp = prvins(bp)) != NULL /* for prvins, same p1, */ && n <= bp->pcnt)) { q = bp->text; while (n--) while (*q++ != SP) /* go find the pfield */ ; pfout(csound,bp,q,lincnt,pcnt, sco); /* and put it out */ } else { error: csound->Message(csound, Str("swrite: output, sect%d line%d p%d makes illegal reference to "), csound->sectcnt,lincnt,pcnt); while (q < p) csound->Message(csound,"%c", *q++); while (*p != SP && *p != LF) csound->Message(csound,"%c", *p++); csound->Message(csound,Str(" Zero substituted\n")); corfile_putc(csound, '0', sco); } return(p); } static char *ramp(CSOUND *csound, SRTBLK *bp, char *p, int lincnt, int pcnt, CORFIL *sco) /* NB np's may reference a ramp but ramps must terminate in valid nums */ { char *q; char *psav; SRTBLK *prvbp, *nxtbp; MYFLT pval, qval, rval, p2span; extern MYFLT stof(CSOUND *, char *); int pnum, n; psav = ++p; if (UNLIKELY(*psav != SP && *psav != LF)) goto error1; pnum = 0; q = bp->text; while (q < p) if (*q++ == SP) pnum++; prvbp = bp; backup: if (LIKELY((prvbp = prvins(prvbp)) != NULL)) { p = prvbp->text; n = pnum; while (n--) while (*p++ != SP) ; if (*p == '>' || *p == '<') goto backup; } else goto error2; nxtbp = bp; forwrd: if (LIKELY((nxtbp = nxtins(nxtbp)) != NULL)) { q = nxtbp->text; n = pnum; while (n--) while (*q++ != SP) ; if (*q == '>' || *q == '<') goto forwrd; } else goto error2; pval = stof(csound, p); /* the error msgs generated by stof */ qval = stof(csound, q); /* are misleading */ if (UNLIKELY((p2span = nxtbp->newp2 - prvbp->newp2) <= 0)) goto error2; rval = (qval - pval) * (bp->newp2 - prvbp->newp2) / p2span + pval; fltout(csound, rval, sco); return(psav); error1: csound->Message(csound, Str("swrite: output, sect%d line%d p%d has illegal ramp symbol\n"), csound->sectcnt,lincnt,pcnt); goto put0; error2: csound->Message(csound, Str("swrite: output, sect%d line%d p%d ramp " "has illegal forward or backward ref\n"), csound->sectcnt, lincnt, pcnt); put0: corfile_putc(csound, '0', sco); return(psav); } static char *expramp(CSOUND *csound, SRTBLK *bp, char *p, int lincnt, int pcnt, CORFIL *sco) /* NB np's may reference a ramp but ramps must terminate in valid nums */ { char *q; char *psav; SRTBLK *prvbp, *nxtbp; MYFLT pval, qval, rval; double p2span; extern MYFLT stof(CSOUND *, char *); int pnum, n; psav = ++p; if (UNLIKELY(*psav != SP && *psav != LF)) goto error1; pnum = 0; q = bp->text; while (q < p) if (*q++ == SP) pnum++; prvbp = bp; backup: if (LIKELY((prvbp = prvins(prvbp)) != NULL)) { p = prvbp->text; n = pnum; while (n--) while (*p++ != SP) ; if (*p == '}' || *p == '{' || *p == '(' || *p == ')') goto backup; } else goto error2; nxtbp = bp; forwrd: if (LIKELY((nxtbp = nxtins(nxtbp)) != NULL)) { q = nxtbp->text; n = pnum; while (n--) while (*q++ != SP) ; if (*q == '}' || *q == '{' || *q == '(' || *q == ')') goto forwrd; } else goto error2; pval = stof(csound, p); /* the error msgs generated by stof */ qval = stof(csound, q); /* are misleading */ p2span = (double)(nxtbp->newp2 - prvbp->newp2); /* printf("pval=%f qval=%f span = %f\n", pval, qval, p2span); */ rval = pval * (MYFLT)pow((double)(qval/pval), (double)(bp->newp2 - prvbp->newp2) / p2span); /* printf("rval=%f bp->newp2=%f prvbp->newp2-%f\n", rval, bp->newp2, prvbp->newp2); */ fltout(csound, rval, sco); return(psav); error1: csound->Message(csound,Str("swrite: output, sect%d line%d p%d has illegal" " expramp symbol\n"), csound->sectcnt,lincnt,pcnt); goto put0; error2: csound->Message(csound, Str("swrite: output, sect%d line%d p%d expramp " "has illegal forward or backward ref\n"), csound->sectcnt, lincnt, pcnt); put0: corfile_putc(csound, '0', sco); return(psav); } static char *randramp(CSOUND *csound, SRTBLK *bp, char *p, int lincnt, int pcnt, CORFIL *sco) /* NB np's may reference a ramp but ramps must terminate in valid nums */ { char *q; char *psav; SRTBLK *prvbp, *nxtbp; MYFLT pval, qval, rval; extern MYFLT stof(CSOUND *, char *); int pnum, n; psav = ++p; if (UNLIKELY(*psav != SP && *psav != LF)) goto error1; pnum = 0; q = bp->text; while (q < p) if (*q++ == SP) pnum++; prvbp = bp; backup: if (LIKELY((prvbp = prvins(prvbp)) != NULL)) { p = prvbp->text; n = pnum; while (n--) while (*p++ != SP) ; if (UNLIKELY(*p == '~')) goto backup; } else goto error2; nxtbp = bp; forwrd: if (LIKELY((nxtbp = nxtins(nxtbp)) != NULL)) { q = nxtbp->text; n = pnum; while (n--) while (*q++ != SP) ; if (*q == '~') goto forwrd; } else goto error2; pval = stof(csound, p); /* the error msgs generated by stof */ qval = stof(csound, q); /* are misleading */ rval = (MYFLT) (((double) (csound->Rand31(&(csound->randSeed1)) - 1) / 2147483645.0) * ((double) qval - (double) pval) + (double) pval); fltout(csound, rval, sco); return(psav); error1: csound->Message(csound,Str("swrite: output, sect%d line%d p%d has illegal" " expramp symbol\n"), csound->sectcnt,lincnt,pcnt); goto put0; error2: csound->Message(csound,Str("swrite: output, sect%d line%d p%d expramp has" " illegal forward or backward ref\n"), csound->sectcnt,lincnt,pcnt); put0: corfile_putc(csound, '0', sco); return(psav); } static char *pfStr(CSOUND *csound, char *p, int lincnt, int pcnt, CORFIL *sco) { /* moves quoted ascii string to SCOREOUT file */ char *q = p; /* with no internal format chk */ corfile_putc(csound, *p++, sco); while (*p != '"') corfile_putc(csound, *p++, sco); corfile_putc(csound, *p++, sco); if (UNLIKELY(*p != SP && *p != LF)) { csound->Message(csound, Str("swrite: output, sect%d line%d p%d " "has illegally terminated string "), csound->sectcnt, lincnt, pcnt); while (q < p) csound->Message(csound,"%c", *q++); while (*p != SP && *p != LF) csound->Message(csound,"%c", *p++); csound->Message(csound,"\n"); } return(p); } static char *fpnum(CSOUND *csound, char *p, int lincnt, int pcnt, CORFIL *sco) /* moves ascii string */ /* to SCOREOUT file with fpnum format chk */ { char *q; int dcnt; q = p; if (*p == '+') p++; if (*p == '-') corfile_putc(csound, *p++, sco); dcnt = 0; while (isdigit(*p)) { // printf("*p=%c\n", *p); corfile_putc(csound, *p++, sco); dcnt++; } // printf("%d:output: %s<<\n", __LINE__, sco); if (*p == '.') corfile_putc(csound, *p++, sco); while (isdigit(*p)) { corfile_putc(csound, *p++, sco); dcnt++; } // printf("%d:output: %s<<\n", __LINE__, sco); if (*p == 'E' || *p == 'e') { /* Allow exponential notation */ corfile_putc(csound, *p++, sco); dcnt++; if (*p == '+' || *p == '-') { corfile_putc(csound, *p++, sco); dcnt++; } while (isdigit(*p)) { corfile_putc(csound, *p++, sco); dcnt++; } } // printf("%d:output: %s<<\n", __LINE__, sco); if (UNLIKELY((*p != SP && *p != LF) || !dcnt)) { csound->Message(csound,Str("swrite: output, sect%d line%d p%d has " "illegal number "), csound->sectcnt,lincnt,pcnt); while (q < p) csound->Message(csound,"%c", *q++); while (*p != SP && *p != LF) csound->Message(csound,"%c", *p++); csound->Message(csound,Str(" String truncated\n")); if (!dcnt) corfile_putc(csound, '0', sco); } return(p); } csound-6.10.0/Engine/symbtab.c000066400000000000000000000427161321653344700161250ustar00rootroot00000000000000/* symbtab.c: Copyright (C) 2006 John ffitch, Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include "csoundCore.h" #include "tok.h" #include "csound_orc.h" #include "insert.h" #include "namedins.h" #include "interlocks.h" #include "csound_orc_semantics.h" #include "csound_standard_types.h" #ifndef PARSER_DEBUG #define PARSER_DEBUG (0) #endif // FIXME - this is global... // VL moved to csound struct //CS_HASH_TABLE* symbtab; #define udoflag csound->parserUdoflag #define namedInstrFlag csound->parserNamedInstrFlag ORCTOKEN *add_token(CSOUND *csound, char *s, int type); //static ORCTOKEN *add_token_p(CSOUND *csound, char *s, int type, int val); extern int csound_orcget_lineno(void*); /* from csound_orc_compile.c */ extern char** splitArgs(CSOUND* csound, char* argString); int get_opcode_type(OENTRY *ep) { int retVal = 0; if (ep->outypes == NULL || strlen(ep->outypes) == 0) { retVal = T_OPCODE0; } else { retVal = T_OPCODE; } return retVal; } void init_symbtab(CSOUND *csound) { OENTRY *ep; CONS_CELL *top, *head, *items; char *shortName; if (csound->symbtab == NULL) { /* VL 27 02 2015 -- if symbtab exists, do not create it again to avoid memory consumption. */ //printf("init symbtab\n"); csound->symbtab = cs_hash_table_create(csound); /* Now we need to populate with basic words */ /* Add token types for opcodes to symbtab. If a polymorphic opcode * definition is found (dsblksiz >= 0xfffb), look for implementations * of that opcode to correctly mark the type of opcode it is (T_OPCODE, * T_OPCODE0, or T_OPCODE00) */ top = head = cs_hash_table_values(csound, csound->opcodes); while (head != NULL) { items = head->value; while (items != NULL) { ep = items->value; if (ep->dsblksiz < 0xfffb) { shortName = get_opcode_short_name(csound, ep->opname); add_token(csound, shortName, get_opcode_type(ep)); if (shortName != ep->opname) { csound->Free(csound, shortName); } } items = items->next; } head = head->next; } csound->Free(csound, top); } } ORCTOKEN *add_token(CSOUND *csound, char *s, int type) { //printf("Hash value for %s: %i\n", s, h); ORCTOKEN *a = cs_hash_table_get(csound, csound->symbtab, s); ORCTOKEN *ans; if (a!=NULL) { if (type == a->type) return a; if (UNLIKELY((type!=T_FUNCTION || a->type!=T_OPCODE))) csound->Warning(csound, Str("Type confusion for %s (%d,%d), replacing\n"), s, type, a->type); a->type = type; return a; } ans = new_token(csound, T_IDENT); ans->lexeme = (char*)csound->Malloc(csound, 1+strlen(s)); strcpy(ans->lexeme, s); ans->type = type; cs_hash_table_put(csound, csound->symbtab, s, ans); return ans; } /* static ORCTOKEN *add_token_p(CSOUND *csound, char *s, int type, int val) */ /* { */ /* ORCTOKEN *ans = add_token(csound, s, type); */ /* ans->value = val; */ /* return ans; */ /* } */ int isUDOArgList(char *s) { int len = strlen(s) - 1; while (len >= 0) { if (UNLIKELY(strchr("aijkftKOJVPopS[]0", s[len]) == NULL)) { /* printf("Invalid char '%c' in '%s'", *p, s); */ return 0; } len--; } return 1; } int isUDOAnsList(char *s) { int len = strlen(s) - 1; while (len >= 0) { if (UNLIKELY(strchr("aikftSK[]0", s[len]) == NULL)) { return 0; } len--; } return 1; } ORCTOKEN *lookup_token(CSOUND *csound, char *s, void *yyscanner) { int type = T_IDENT; ORCTOKEN *a; ORCTOKEN *ans; if (UNLIKELY(PARSER_DEBUG)) csound->Message(csound, "Looking up token for: %s\n", s); if (udoflag == 0) { if (isUDOAnsList(s)) { ans = new_token(csound, UDO_ANS_TOKEN); ans->lexeme = (char*)csound->Malloc(csound, 1+strlen(s)); strcpy(ans->lexeme, s); return ans; } } if (udoflag == 1) { if (UNLIKELY(csound->oparms->odebug)) printf("Found UDO Arg List\n"); if (isUDOArgList(s)) { ans = new_token(csound, UDO_ARGS_TOKEN); ans->lexeme = (char*)csound->Malloc(csound, 1+strlen(s)); strcpy(ans->lexeme, s); return ans; } } a = cs_hash_table_get(csound, csound->symbtab, s); if (a != NULL) { ans = (ORCTOKEN*)csound->Malloc(csound, sizeof(ORCTOKEN)); memcpy(ans, a, sizeof(ORCTOKEN)); ans->next = NULL; ans->lexeme = (char *)csound->Malloc(csound, strlen(a->lexeme) + 1); strcpy(ans->lexeme, a->lexeme); return ans; } ans = new_token(csound, T_IDENT); ans->lexeme = (char*)csound->Malloc(csound, 1+strlen(s)); strcpy(ans->lexeme, s); if (udoflag == -2 || namedInstrFlag == 1) { return ans; } ans->type = type; return ans; } //static int is_optional_udo_in_arg(char* argtype) { // return strchr("jOPVop", *argtype) != NULL; //} static char map_udo_in_arg_type(char in) { if (strchr("ijop", in) != NULL) { return 'i'; } else if (strchr("kKOJPV", in) != NULL) { return 'k'; } return in; } static char map_udo_out_arg_type(char in) { if (in == 'K') { return 'k'; } return in; } static void map_args(char* args) { while (*args != '\0') { *args = map_udo_out_arg_type(*args); args++; } } /** * This function takes in the arguments from useropinfo in OENTRY and parses them, filling the OENTRY input and output types and creating the argument lists for xinset/xouset in insert.c argument pointerlists, stored in useropinfo->in_ndx_list and useropinfo->out_ndx_list. The argument lists are terminated by a -1 and are set in the following order: i-var args (i-time vars) S-var args (strings) i-arrays a-vars k-vars f-sigs arrays (a,k,f) This order is fixed and followed up in xinset/xoutset and useropcd1, useropcd2. Original code - IV Oct 12 2002 modified by VL for Csound 6 */ static int parse_opcode_args(CSOUND *csound, OENTRY *opc) { OPCODINFO *inm = (OPCODINFO*) opc->useropinfo; char** in_args; char** out_args; char intypes[256]; char typeSpecifier[2]; char tempName[20]; int i = 0, err = 0; int n=0; ARRAY_VAR_INIT varInit; typeSpecifier[1] = '\0'; // The following handles adding of extra 'o' type for optional // ksmps arg for all UDO's if (*inm->intypes == '0') { intypes[0] = 'o'; intypes[1] = '\0'; } else { snprintf(intypes, 256, "%so", inm->intypes); } in_args = splitArgs(csound, intypes); out_args = splitArgs(csound, inm->outtypes); if (UNLIKELY(in_args == NULL)) { synterr(csound, Str("invalid input argument types found for opcode %s: %s\n"), inm->name, intypes); err++; } if (UNLIKELY(out_args == NULL)) { synterr(csound, Str("invalid output argument types found for opcode %s: %s\n"), inm->name, inm->outtypes); err++; } if (UNLIKELY(err > 0)) goto early_exit; if (*in_args[0] != '0') { while (in_args[i] != NULL) { char* in_arg = in_args[i]; snprintf(tempName, 20, "in%d", i); if (*in_arg == '[') { int dimensions = 0; while (*in_arg == '[') { dimensions += 1; in_arg += 1; } typeSpecifier[0] = *in_arg; // printf("Dimensions: %d SubArgType: %s\n", dimensions, typeSpecifier); CS_TYPE* type = csoundGetTypeWithVarTypeName(csound->typePool, typeSpecifier); if (UNLIKELY(type == NULL)) { synterr(csound, Str("invalid input type for opcode %s \n"), in_arg); err++; continue; } varInit.dimensions = dimensions; varInit.type = type; CS_VARIABLE* var = csoundCreateVariable(csound, csound->typePool, (CS_TYPE*)&CS_VAR_TYPE_ARRAY, tempName, &varInit); var->dimensions = dimensions; csoundAddVariable(csound, inm->in_arg_pool, var); } else { char c = map_udo_in_arg_type(*in_arg); // printf("found arg type %s -> %c\n", in_arg, c); typeSpecifier[0] = c; CS_TYPE* type = csoundGetTypeWithVarTypeName(csound->typePool, typeSpecifier); if (UNLIKELY(type == NULL)) { synterr(csound, Str("invalid input type for opcode %s \n"), in_arg); err++; continue; } CS_VARIABLE* var = csoundCreateVariable(csound, csound->typePool, type, tempName, NULL); csoundAddVariable(csound, inm->in_arg_pool, var); } i++; } } // inm->inchns = i + 1; /* Add one for optional local ksmps */ inm->inchns = i - 1; i = 0; if (*out_args[0] != '0') { while(out_args[i] != NULL) { char* out_arg = out_args[i]; snprintf(tempName, 20, "out%d", i); if (*out_arg == '[') { int dimensions = 0; while (*out_arg == '[') { dimensions += 1; out_arg += 1; } typeSpecifier[0] = *out_arg; //printf("Dimensions: %d SubArgType: %s\n", dimensions, typeSpecifier); CS_TYPE* type = csoundGetTypeWithVarTypeName(csound->typePool, typeSpecifier); if (UNLIKELY(type == NULL)) { synterr(csound, Str("invalid output type for opcode %s"), out_arg); err++; continue; } varInit.dimensions = dimensions; varInit.type = type; CS_VARIABLE* var = csoundCreateVariable(csound, csound->typePool, (CS_TYPE*)&CS_VAR_TYPE_ARRAY, tempName, &varInit); var->dimensions = dimensions; csoundAddVariable(csound, inm->out_arg_pool, var); } else { char c = map_udo_out_arg_type(*out_arg); // printf("found arg type %s -> %c\n", out_arg, c); typeSpecifier[0] = c; CS_TYPE* type = csoundGetTypeWithVarTypeName(csound->typePool, typeSpecifier); if (UNLIKELY(type == NULL)) { synterr(csound, Str("invalid output type for opcode %s"), out_arg); err++; continue; } CS_VARIABLE* var = csoundCreateVariable(csound, csound->typePool, type, tempName, NULL); csoundAddVariable(csound, inm->out_arg_pool, var); } i++; } } inm->outchns = i; opc->dsblksiz = (uint16) (sizeof(UOPCODE) + sizeof(MYFLT*) * (inm->inchns + inm->outchns)); opc->dsblksiz = ((opc->dsblksiz + (uint16) 15) & (~((uint16) 15))); /* align (needed ?) */ opc->intypes = cs_strdup(csound, intypes); opc->outypes = cs_strdup(csound, (inm->outtypes[0] == '0') ? "" : inm->outtypes); map_args(opc->intypes); map_args(opc->outypes); // /* count the number of arguments, and check types */ // default: // synterr(csound, Str("invalid input type for opcode %s"), inm->name); // err++; i--; // } // i++; types++; // if (UNLIKELY(i > OPCODENUMOUTS_MAX)) { // synterr(csound, Str("too many input args for opcode %s"), inm->name); // csound->LongJmp(csound, 1); // } // } // default: // synterr(csound, Str("invalid output type for opcode %s"), inm->name); // err++; i--; // } // i++; types++; // } // early_exit: if(in_args != NULL) { while(in_args[n] != NULL) { // printf("delete %p \n", argsFound[n]); csound->Free(csound, in_args[n]); n++; } csound->Free(csound, in_args); } if (out_args != NULL) { n = 0; while(out_args[n] != NULL) { // printf("delete %p \n", argsFound[n]); csound->Free(csound, out_args[n]); n++; } csound->Free(csound, out_args); } return err; } OENTRY* csound_find_internal_oentry(CSOUND* csound, OENTRY* oentry) { CONS_CELL *items; char *shortName; OENTRY *ep, *retVal = NULL; if (oentry == NULL) { return NULL; } shortName = get_opcode_short_name(csound, oentry->opname); items = cs_hash_table_get(csound, csound->opcodes, shortName); while (items != NULL) { ep = items->value; if (oentry->iopadr == ep->iopadr && oentry->kopadr == ep->kopadr && oentry->aopadr == ep->aopadr && strcmp(oentry->opname, ep->opname) == 0 && strcmp(oentry->outypes, ep->outypes) == 0 && strcmp(oentry->intypes, ep->intypes) == 0) { retVal = ep; break; } items = items->next; } if (shortName != oentry->opname) { csound->Free(csound, shortName); } return retVal; } /** Adds a UDO definition as an T_OPCODE or T_OPCODE0 type to the symbol table * used at parse time. An OENTRY is also added at this time so that at * verification time the opcode can be looked up to get its signature. */ int add_udo_definition(CSOUND *csound, char *opname, char *outtypes, char *intypes) { OENTRY tmpEntry, *opc, *newopc; OPCODINFO *inm; int len; if (UNLIKELY(!check_instr_name(opname))) { synterr(csound, Str("invalid name for opcode")); return -1; } len = strlen(intypes); if (len == 1 && *intypes == '0') { opc = find_opcode_exact(csound, opname, outtypes, "o"); } else { char* adjusted_intypes = csound->Malloc(csound, sizeof(char) * (len + 2)); sprintf(adjusted_intypes, "%so", intypes); opc = find_opcode_exact(csound, opname, outtypes, adjusted_intypes); csound->Free(csound, adjusted_intypes); } /* check if opcode is already defined */ if (UNLIKELY(opc != NULL)) { /* IV - Oct 31 2002: redefine old opcode if possible */ if (UNLIKELY( !strcmp(opname, "instr") || !strcmp(opname, "endin") || !strcmp(opname, "opcode") || !strcmp(opname, "endop") || !strcmp(opname, "$label") || !strcmp(opname, "pset") || !strcmp(opname, "xin") || !strcmp(opname, "xout") || !strcmp(opname, "subinstr"))) { synterr(csound, Str("cannot redefine %s"), opname); return -2; } csound->Message(csound, Str("WARNING: redefined opcode: %s\n"), opname); } /* IV - Oct 31 2002 */ /* store the name in a linked list (note: must use csound->Calloc) */ inm = (OPCODINFO *) csound->Calloc(csound, sizeof(OPCODINFO)); inm->name = cs_strdup(csound, opname); inm->intypes = intypes; inm->outtypes = outtypes; inm->in_arg_pool = csoundCreateVarPool(csound); inm->out_arg_pool = csoundCreateVarPool(csound); inm->prv = csound->opcodeInfo; csound->opcodeInfo = inm; if (opc != NULL) { opc->useropinfo = inm; newopc = opc; } else { /* IV - Oct 31 2002: */ /* create a fake opcode so we can call it as such */ opc = find_opcode(csound, "##userOpcode"); memcpy(&tmpEntry, opc, sizeof(OENTRY)); tmpEntry.opname = cs_strdup(csound, opname); csound->AppendOpcodes(csound, &tmpEntry, 1); newopc = csound_find_internal_oentry(csound, &tmpEntry); newopc->useropinfo = (void*) inm; /* ptr to opcode parameters */ /* check in/out types and copy to the opcode's */ /* IV - Sep 8 2002: opcodes have an optional arg for ksmps */ newopc->outypes = csound->Malloc(csound, strlen(outtypes) + 1 + strlen(intypes) + 2); newopc->intypes = &(newopc->outypes[strlen(outtypes) + 1]); if (strcmp(outtypes, "0")==0) { add_token(csound, opname, T_OPCODE0); } else { add_token(csound, opname, T_OPCODE); } } if (UNLIKELY(parse_opcode_args(csound, newopc) != 0)) return -3; return 0; } void synterr(CSOUND *csound, const char *s, ...) { va_list args; csound->MessageS(csound, CSOUNDMSG_ERROR, Str("error: ")); va_start(args, s); csound->MessageV(csound, CSOUNDMSG_ERROR, s, args); va_end(args); /* FIXME - Removed temporarily for debugging * This function may not be necessary at all in the end if some of this is * done in the parser */ csound->synterrcnt++; } csound-6.10.0/Engine/twarp.c000066400000000000000000000161541321653344700156160ustar00rootroot00000000000000/* twarp.c: Copyright (C) 1991 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* TWARP.C */ /* #define TSEGMAX (PMAX/2) */ /* #define TSEGMAX (100) */ #define TSEGMAX (20) typedef struct { MYFLT betbas; MYFLT durslp; MYFLT durbas; MYFLT timbas; } TSEG; int realtset(CSOUND *, SRTBLK *); MYFLT realt(CSOUND *, MYFLT); void twarp(CSOUND *csound) /* time-warp a score section acc to T-statement */ { SRTBLK *bp; MYFLT absp3; MYFLT endtime; int negp3; if (UNLIKELY((bp = csound->frstbp) == NULL)) /* if null file, */ return; while (bp->text[0] != 't') /* or cannot find a t, */ if (UNLIKELY((bp = bp->nxtblk) == NULL)) return; /* we are done */ bp->text[0] = 'w'; /* else mark the t used */ if (!realtset(csound, bp)) /* and init the t-array */ return; /* (done if t0 60 or err) */ bp = csound->frstbp; negp3 = 0; do { switch (bp->text[0]) { /* else warp all timvals */ case 'i': absp3 = bp->newp3; if (UNLIKELY(absp3 < 0)) { absp3 = -absp3; negp3++; } endtime = bp->newp2 + absp3; bp->newp2 = realt(csound, bp->newp2); bp->newp3 = realt(csound, endtime) - bp->newp2; if (negp3) { bp->newp3 = -bp->newp3; negp3--; } break; case 'a': endtime = bp->newp2 + bp->newp3; bp->newp2 = realt(csound, bp->newp2); bp->newp3 = realt(csound, endtime) - bp->newp2; break; case 'f': case 'q': bp->newp2 = realt(csound, bp->newp2); break; case 't': case 'w': break; case 's': case 'e': if (bp->pcnt > 0) bp->newp2 = realt(csound, bp->p2val); break; default: csound->Message(csound, Str("twarp: illegal opcode\n")); break; } } while ((bp = bp->nxtblk) != NULL); } int realtset(CSOUND *csound, SRTBLK *bp) { char *p; char c; MYFLT tempo, betspan, durbas, avgdur, stof(CSOUND *, char *); TSEG *tp, *prvtp; if (csound->tseg == NULL) { /* if no space yet, alloc */ csound->tseg = csound->Malloc(csound, (int32)TSEGMAX * sizeof(TSEG)); csound->tplim = (TSEG*) csound->tseg + TSEGMAX-1; csound->tseglen = TSEGMAX; } tp = (TSEG*) (csound->tpsave = csound->tseg); if (UNLIKELY(bp->pcnt < 2)) goto error1; p = bp->text; /* first go to p1 */ p += 2; if (UNLIKELY((tp->betbas = stof(csound, p)) != 0)) /* betbas1 must be zero */ goto error1; while ((c = *p++) != SP) {} if (UNLIKELY((tempo = stof(csound, p)) <= 0)) /* durbas = 60/tempo */ goto error2; if (bp->pcnt == 2 && tempo == FL(60.0)) /* just t0 60 means done */ return(0); tp->durbas = FL(60.0)/tempo; tp->timbas = FL(0.0); /* timbas1 = 0 */ while ((c = *p++) != SP && c != LF) {} while (c != LF) { /* for each time-tempo pair: */ prvtp = tp; if (UNLIKELY(++tp > (TSEG*) csound->tplim)) { /* extend */ TSEG* oldtseg = csound->tseg; /* printf("<tplim, csound->tpsave, tp, prvtp, csound->tseglen); */ /* printf("tseg extend %p->", oldtseg); */ csound->tseglen += TSEGMAX; csound->tseg = (TSEG*)csound->ReAlloc(csound, oldtseg, csound->tseglen*sizeof(TSEG)); if (csound->tseg != oldtseg) { /* printf(" MOVED "); */ tp += ((TSEG*)csound->tseg - oldtseg); prvtp = tp-1; csound->tplim = ((char*)csound->tseg) + csound->tseglen-1; csound->tpsave = csound->tseg; } /* printf("%p\n", csound->tseg); */ /* printf("tplim, tpsave, tp, prvtp, size = %p, %p, %p, %p, %d>>\n", */ /* csound->tplim, csound->tpsave, tp, prvtp, csound->tseglen); */ //goto error3; } tp->betbas = stof(csound, p); /* betbas = time */ while ((c = *p++) != SP && c != LF) {} if (UNLIKELY(c == LF)) goto error1; if (UNLIKELY((tempo = stof(csound, p)) <= 0)) /* get tempo */ goto error2; if ((betspan = tp->betbas - prvtp->betbas) <= 0) { if (UNLIKELY(betspan < 0)) /* if time = lastime */ goto error1; tp--; /* overwrit prvdurbas*/ tp->durbas = FL(60.0)/tempo; /* with 60/tempo */ goto align; /* and reloop */ } tp->durbas = durbas = FL(60.0)/tempo; /* else this durbas */ avgdur = (durbas + prvtp->durbas)*FL(0.5); tp->timbas = avgdur*betspan + prvtp->timbas; /* set timbas*/ prvtp->durslp = (avgdur - prvtp->durbas)/betspan;/* prvdurslp*/ align: while ((c = *p++) != SP && c != LF) {} } tp->durslp = FL(0.0); /* clear last durslp */ if (UNLIKELY(++tp > (TSEG*) csound->tplim)) { /* extend */ TSEG* oldtseg = csound->tseg; /* printf("tplim, tpsave, tp, size = %p, %p, %p, %d\n", */ /* csound->tplim, csound->tpsave, tp, csound->tseglen); */ /* printf("tseg extend %p->", oldtseg); */ csound->tseglen += TSEGMAX; csound->tseg = (TSEG*)csound->ReAlloc(csound, oldtseg, csound->tseglen*sizeof(TSEG)); tp += ((TSEG*)csound->tseg - oldtseg); csound->tplim = ((char*)csound->tseg) + csound->tseglen-1; csound->tpsave = csound->tseg; } tp->betbas = FL(9223372036854775807.0); /* and cap with large betval */ return(1); error1: csound->Message(csound,Str("twarp: t has extra or disordered beat value\n")); return(0); error2: csound->Message(csound,Str("twarp: t has non-positive tempo\n")); return(0); } MYFLT realt(CSOUND *csound, MYFLT srctim) { TSEG *tp; MYFLT diff; tp = (TSEG*) csound->tpsave; while (srctim >= (tp+1)->betbas) tp++; while ((diff = srctim - tp->betbas) < FL(0.0)) tp--; csound->tpsave = tp; return ((tp->durslp * diff + tp->durbas) * diff + tp->timbas); } csound-6.10.0/H/000077500000000000000000000000001321653344700132705ustar00rootroot00000000000000csound-6.10.0/H/aops.h000066400000000000000000000075411321653344700144120ustar00rootroot00000000000000/* aops.h: Copyright (C) 1991 Barry Vercoe, John ffitch, Gabriel Maldonado This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* AOPS.H */ #define CSOUND_SPIN_SPINLOCK csoundSpinLock(&csound->spinlock); #define CSOUND_SPIN_SPINUNLOCK csoundSpinUnLock(&csound->spinlock); #define CSOUND_SPOUT_SPINLOCK csoundSpinLock(&csound->spoutlock); #define CSOUND_SPOUT_SPINUNLOCK csoundSpinUnLock(&csound->spoutlock); typedef struct { OPDS h; MYFLT *r, *a; } ASSIGN; #define ASSIGNM_MAX (24) typedef struct { OPDS h; MYFLT *r[ASSIGNM_MAX], *a[ASSIGNM_MAX]; } ASSIGNM; typedef struct { OPDS h; TABDAT *a; MYFLT *size, *value; } INITT; typedef struct { OPDS h; TABDAT *tab; MYFLT *ind; MYFLT *val; } ASSIGNT; typedef struct { OPDS h; MYFLT *ans; TABDAT *tab; MYFLT *ind; } TABREF; typedef struct { OPDS h; int *rbool; MYFLT *a, *b; } RELAT; typedef struct { OPDS h; int *rbool, *ibool, *jbool; } LOGCL; typedef struct { OPDS h; MYFLT *r; int *cond; MYFLT *a, *b; } CONVAL; typedef struct { OPDS h; MYFLT *r, *a, *b; } AOP; typedef struct { OPDS h; MYFLT *r, *a, *b, *def; } DIVZ; typedef struct { OPDS h; MYFLT *r, *a; } EVAL; typedef struct { OPDS h; MYFLT *ar; } INM; typedef struct { OPDS h; ARRAYDAT *tabout; } INA; typedef struct { OPDS h; MYFLT *ar1, *ar2; } INS; typedef struct { OPDS h; MYFLT *ar1, *ar2, *ar3, *ar4; } INQ; typedef struct { OPDS h; MYFLT *ar1, *ar2, *ar3, *ar4, *ar5, *ar6; } INH; typedef struct { OPDS h; MYFLT *ar1, *ar2, *ar3, *ar4, *ar5, *ar6, *ar7, *ar8; } INO; typedef struct { OPDS h; MYFLT *ar[40]; /* array size should be consistent with entry2.c */ } INALL; typedef struct { OPDS h; MYFLT *ar[40]; MYFLT *ch[VARGMAX]; int init; } INCH; typedef struct { OPDS h; MYFLT *ar; MYFLT *ch; int init; } INCH1; typedef struct { OPDS h; MYFLT *asig[VARGMAX]; } OUTX; typedef struct { OPDS h; ARRAYDAT *tabin; } OUTARRAY; typedef struct { OPDS h; MYFLT *asig; } OUTM; typedef struct { OPDS h; MYFLT *args[VARGMAX]; } OUTCH; typedef struct { OPDS h; MYFLT *r, *pc, *et, *cy, *ref; } XENH; typedef struct { OPDS h; MYFLT *r, *ktrig, *kinput, *tablenum; MYFLT old_r; } CPSTUN; typedef struct { OPDS h; MYFLT *r, *input, *tablenum; } CPSTUNI; typedef struct { OPDS h; MYFLT *res, *arg; } ERRFN; typedef struct MONITOR_OPCODE_ { OPDS h; MYFLT *ar[24]; } MONITOR_OPCODE; typedef struct { OPDS h; MYFLT *kstartChan, *argums[VARGMAX]; int narg; } OUTRANGE; int monitor_opcode_perf(CSOUND *csound, MONITOR_OPCODE *p); int monitor_opcode_init(CSOUND *csound, MONITOR_OPCODE *p); int outRange_i(CSOUND *csound, OUTRANGE *p); int outRange(CSOUND *csound, OUTRANGE *p); int hw_channels(CSOUND *csound, ASSIGN *p); csound-6.10.0/H/bus.h000066400000000000000000000123411321653344700142330ustar00rootroot00000000000000/* bus.h: Copyright (C) 2004 John ffitch (C) 2005, 2006 Istvan Varga (C) 2006 Victor Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* BUS.H */ #ifndef CSOUND_BUS_H #define CSOUND_BUS_H #include "pstream.h" #include "csound_standard_types.h" #define MAX_CHAN_NAME 1024 #ifdef __cplusplus extern "C" { #endif typedef struct { OPDS h; MYFLT *r, *a; } CHNVAL; typedef struct { OPDS h; PVSDAT *r; MYFLT *a,*N, *overlap, *winsize, *wintype, *format; PVSDAT init; } FCHAN; typedef struct { OPDS h; MYFLT *ans; MYFLT *keyDown; int evtbuf; } KSENSE; typedef struct channelEntry_s { struct channelEntry_s *nxt; controlChannelHints_t hints; MYFLT *data; #ifndef MACOSX #if defined(HAVE_PTHREAD_SPIN_LOCK) pthread_spinlock_t *lock; pthread_spinlock_t theLock; #else int lock; #endif #else int lock; /* Multi-thread protection */ #endif int type; int datasize; /* size of allocated chn data */ char name[1]; } CHNENTRY; typedef struct { OPDS h; MYFLT *arg; STRINGDAT *iname; MYFLT *fp; int *lock; int pos; char chname[MAX_CHAN_NAME+1]; } CHNGET; typedef struct { OPDS h; STRINGDAT *iname; MYFLT *fp; int *lock; } CHNCLEAR; typedef struct { OPDS h; STRINGDAT *iname; MYFLT *imode; MYFLT *itype; MYFLT *idflt; MYFLT *imin; MYFLT *imax; MYFLT *ix; MYFLT *iy; MYFLT *iwidth; MYFLT *iheight; STRINGDAT *Sattributes; int *lock; } CHN_OPCODE_K; typedef struct { OPDS h; STRINGDAT *iname; MYFLT *imode; int *lock; } CHN_OPCODE; typedef struct { OPDS h; MYFLT *arg; STRINGDAT *iname; MYFLT *imode; MYFLT *itype; MYFLT *idflt; MYFLT *imin; MYFLT *imax; } CHNEXPORT_OPCODE; typedef struct { OPDS h; MYFLT *itype; MYFLT *imode; MYFLT *ictltype; MYFLT *idflt; MYFLT *imin; MYFLT *imax; STRINGDAT *iname; } CHNPARAMS_OPCODE; typedef struct { OPDS h; MYFLT *value, *valID; AUXCH channelName; const CS_TYPE *channelType; void *channelptr; } INVAL; typedef struct { OPDS h; MYFLT *valID, *value; AUXCH channelName; const CS_TYPE *channelType; void *channelptr; } OUTVAL; int chano_opcode_perf_k(CSOUND *, CHNVAL *); int chano_opcode_perf_a(CSOUND *, CHNVAL *); int chani_opcode_perf_k(CSOUND *, CHNVAL *); int chani_opcode_perf_a(CSOUND *, CHNVAL *); int pvsin_init(CSOUND *, FCHAN *); int pvsin_perf(CSOUND *, FCHAN *); int pvsout_init(CSOUND *, FCHAN *); int pvsout_perf(CSOUND *, FCHAN *); int sensekey_perf(CSOUND *, KSENSE *); int notinit_opcode_stub(CSOUND *, void *); int chnget_opcode_init_i(CSOUND *, CHNGET *); int chnget_opcode_init_k(CSOUND *, CHNGET *); int chnget_opcode_init_a(CSOUND *, CHNGET *); int chnget_opcode_init_S(CSOUND *, CHNGET *); int chnget_opcode_perf_S(CSOUND *, CHNGET *); int chnset_opcode_init_i(CSOUND *, CHNGET *); int chnset_opcode_init_k(CSOUND *, CHNGET *); int chnset_opcode_init_a(CSOUND *, CHNGET *); int chnset_opcode_init_S(CSOUND *, CHNGET *); int chnset_opcode_perf_S(CSOUND *, CHNGET *); int chnmix_opcode_init(CSOUND *, CHNGET *); int chnclear_opcode_init(CSOUND *, CHNCLEAR *); int chn_k_opcode_init(CSOUND *, CHN_OPCODE_K *); int chn_a_opcode_init(CSOUND *, CHN_OPCODE *); int chn_S_opcode_init(CSOUND *, CHN_OPCODE *); int chnexport_opcode_init(CSOUND *, CHNEXPORT_OPCODE *); int chnparams_opcode_init(CSOUND *, CHNPARAMS_OPCODE *); int kinval(CSOUND *csound, INVAL *p); int kinvalS(CSOUND *csound, INVAL *p); int invalset(CSOUND *csound, INVAL *p); int invalset_string(CSOUND *csound, INVAL *p); int invalset_string_S(CSOUND *csound, INVAL *p); int invalset_S(CSOUND *csound, INVAL *p); int invalsetgo(CSOUND *csound, INVAL *p); int invalsetSgo(CSOUND *csound, INVAL *p); int koutval(CSOUND *csound, OUTVAL *p); int koutvalS(CSOUND *csound, OUTVAL *p); int outvalset(CSOUND *csound, OUTVAL *p); int outvalset_string(CSOUND *csound, OUTVAL *p); int outvalset_string_S(CSOUND *csound, OUTVAL *p); int outvalset_S(CSOUND *csound, OUTVAL *p); int outvalsetgo(CSOUND *csound, OUTVAL *p); int outvalsetSgo(CSOUND *csound, OUTVAL *p); #ifdef __cplusplus } #endif #endif /* CSOUND_BUS_H */ csound-6.10.0/H/cmath.h000066400000000000000000000027111321653344700145360ustar00rootroot00000000000000/* cmath.h: Copyright (C) 1994 Paris Smaragdis, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ double besseli(double); /* returns 0 on success, -1 if there are insufficient arguments, */ /* and -2 in the case of an unknown distribution */ int gen21_rand(FGDATA *ff, FUNC *ftp); typedef struct { OPDS h; MYFLT *sr, *in, *powerOf, *norm; } POW; typedef struct { OPDS h; MYFLT *out, *arg1, *arg2, *arg3; } PRAND; typedef struct { OPDS h; MYFLT *ar, *arg1, *xamp, *xcps; MYFLT *iseed; MYFLT dfdmax, num1, num2; int32 phs; int ampcod, cpscod; } PRANDI; typedef struct { OPDS h; MYFLT *ans; } GETSEED; csound-6.10.0/H/compile_ops.h000066400000000000000000000025441321653344700157570ustar00rootroot00000000000000/* compile_ops.h: Copyright (C) 2013 by Victor Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include typedef struct _compile { OPDS h; MYFLT *res; MYFLT *str; MYFLT *ktrig; }COMPILE; typedef struct _retval { OPDS h; MYFLT *ret; } RETVAL; int compile_orc_i(CSOUND *csound, COMPILE *c); int compile_str_i(CSOUND *csound, COMPILE *c); int compile_csd_i(CSOUND *csound, COMPILE *c); int read_score_i(CSOUND *csound, COMPILE *c); int eval_str_i(CSOUND *csound, COMPILE *p); int eval_str_k(CSOUND *csound, COMPILE *p); int retval_i(CSOUND *csound, RETVAL *p); int eval_str_k(CSOUND *csound, COMPILE *p); csound-6.10.0/H/convolve.h000066400000000000000000000050031321653344700152720ustar00rootroot00000000000000/* convolve.h: Copyright (C) 1996 Greg Sullivan This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _CONVOLVE_H_ #define _CONVOLVE_H_ #define CONVOLVE_VERSION_STRING "CONVOLVE VERSION: V1.1\n" #ifndef NULL #define NULL 0L #endif /* !NULL */ #define CVMAGIC 666 /* Evil, eh? */ #define CVDFLTBYTS 4 typedef struct cvstruct { int32 magic; /* magic number to identify */ int32 headBsize; /* byte offset from start to data */ int32 dataBsize; /* total number of bytes of data */ int32 dataFormat; /* (int) format specifier */ MYFLT samplingRate; /* of original sample */ int32 src_chnls; /* no. of channels in source */ int32 channel; /* requested channel(s) */ int32 Hlen; /* length of impulse reponse */ int32 Format; /* (int) how words are org'd in frm */ char info[CVDFLTBYTS]; /* extendable byte area */ } CVSTRUCT; /* Error codes returned by CONVOLVE file functions */ #define CVE_OK 0 /* no error*/ #define CVE_NOPEN -1 /* couldn't open file */ #define CVE_NCV -2 /* not a CONVOLVE file */ #define CVE_MALLOC -3 /* couldn't allocate memory */ #define CVE_RDERR -4 /* read error */ #define CVE_WRERR -5 /* write error */ #define CV_UNK_LEN -1L /* flag if dataBsize unknown in hdr */ /* values for dataFormat field */ #define CVMYFLT (4+32) /* 32 bit float data */ /* values for frameFormat field */ #define CVRECT 1 /* real, imag pairs */ /********************************/ /* exported function prototypes */ /********************************/ #endif /* !_CONVOLVE_H_ */ csound-6.10.0/H/corfile.h000066400000000000000000000041001321653344700150570ustar00rootroot00000000000000/* corfiles.h: Copyright (C) 2011 John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __corfil #define __corfil CORFIL *corfile_create_w(CSOUND*); CORFIL *corfile_create_r(CSOUND*,const char *text); void corfile_putc(CSOUND*,int c, CORFIL *f); void corfile_puts(CSOUND*,const char *s, CORFIL *f); void corfile_flush(CSOUND*,CORFIL *f); void corfile_rm(CSOUND*,CORFIL **ff); int corfile_getc(CORFIL *f); void corfile_ungetc(CORFIL *f); char *corfile_fgets(char *b, int len, CORFIL *f); #define corfile_ungetc(f) (--f->p) MYFLT corfile_get_flt(CORFIL *f); void corfile_reset(CORFIL *f); #define corfile_reset(f) (f->body[f->p=0]='\0') void corfile_rewind(CORFIL *f); #define corfile_rewind(f) (f->p=0) int corfile_tell(CORFIL *f); #define corfile_tell(f) (f->p) char *corfile_body(CORFIL *f); #define corfile_body(f) (f->body) char *corfile_current(CORFIL *f); #define corfile_current(f) (f->body+f->p) CORFIL *copy_to_corefile(CSOUND *, const char *, const char *, int); CORFIL *copy_url_corefile(CSOUND *, const char *, int); int corfile_length(CORFIL *f); #define corfile_length(f) (strlen(f->body)) void corfile_set(CORFIL *f, int n); #define corfile_set(f,n) (f->p = n) void corfile_seek(CORFIL *f, int n, int dir); void corfile_preputs(CSOUND *csound, const char *s, CORFIL *f); void add_corfile(CSOUND* csound, CORFIL *smpf, char *filename); #endif csound-6.10.0/H/csGblMtx.h000066400000000000000000000043741321653344700151740ustar00rootroot00000000000000/* csGblMtx.h: Copyright (C) 2005 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef CSOUND_CSGBLMTX_H #ifdef HAVE_PTHREAD #include #ifdef __cplusplus extern "C" { #endif static pthread_mutex_t csound_global_lock_ = PTHREAD_MUTEX_INITIALIZER; void csoundLock() { pthread_mutex_lock(&csound_global_lock_); } void csoundUnLock() { pthread_mutex_unlock(&csound_global_lock_); } #ifdef __cplusplus } #endif #elif defined(_WIN32) || defined (__WIN32__) #define _WIN32_WINNT 0x0600 #include #ifdef __cplusplus extern "C" { #endif static INIT_ONCE g_InitOnce = INIT_ONCE_STATIC_INIT; static CRITICAL_SECTION* csound_global_lock; static BOOL CALLBACK InitHandleFunction ( PINIT_ONCE InitOnce, PVOID Parameter, PVOID *lpContext) { CRITICAL_SECTION* cs = (CRITICAL_SECTION*) malloc(sizeof(CRITICAL_SECTION)); InitializeCriticalSection(cs); *lpContext = cs; return 1; } void csoundLock() { BOOL status; CRITICAL_SECTION* cs; status = InitOnceExecuteOnce(&g_InitOnce, InitHandleFunction, NULL, &cs); if (status) { EnterCriticalSection(cs); } } void csoundUnLock() { BOOL status; CRITICAL_SECTION* cs; status = InitOnceExecuteOnce(&g_InitOnce, InitHandleFunction, NULL, &cs); if (status) { LeaveCriticalSection(cs); } } #ifdef __cplusplus } #endif #else /* END WIN32 */ #ifdef __cplusplus extern "C" { #endif void csoundLock() { } void csoundUnLock() { } #ifdef __cplusplus } #endif #endif #endif /* CSOUND_CSGBLMTX_H */ csound-6.10.0/H/cs_jack.h000066400000000000000000000070011321653344700150340ustar00rootroot00000000000000/* .h: Copyright (C) 2008 by Cesare Marilungo This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define MAX_NAME_LEN 32 /* for client and port name */ typedef struct RtJackBuffer_ { #ifdef LINUX pthread_mutex_t csndLock; /* signaled by process callback */ pthread_mutex_t jackLock; /* signaled by audio thread */ #else void *csndLock; /* signaled by process callback */ void *jackLock; /* signaled by audio thread */ #endif jack_default_audio_sample_t **inBufs; /* 'nChannels' capture buffers */ jack_default_audio_sample_t **outBufs; /* 'nChannels' playback buffers */ } RtJackBuffer; typedef struct RtJackGlobals_ { CSOUND *csound; /* Csound instance pointer */ int jackState; /* 0: OK, 1: sr changed, 2: quit */ char clientName[MAX_NAME_LEN + 1]; /* client name */ char inputPortName[MAX_NAME_LEN + 1]; /* input port name prefix */ char outputPortName[MAX_NAME_LEN + 1]; /* output port name prefix */ int sleepTime; /* sleep time in us (deprecated) */ char *inDevName; /* device name for -i adc */ char *outDevName; /* device name for -o dac */ int sampleRate; /* sample rate in Hz */ int nChannels; /* number of channels */ int nChannels_i; /* number of in channels */ int bufSize; /* buffer size in sample frames */ int nBuffers; /* number of buffers (>= 2) */ int inputEnabled; /* non-zero if capture (adc) is on */ int outputEnabled; /* non-zero if playback (dac) is on */ int csndBufCnt; /* current buffer in Csound thread */ int csndBufPos; /* buffer position in Csound thread */ int jackBufCnt; /* current buffer in JACK callback */ int jackBufPos; /* buffer position in JACK callback */ jack_client_t *client; /* JACK client pointer */ jack_port_t **inPorts; /* 'nChannels' ports for capture */ jack_default_audio_sample_t **inPortBufs; jack_port_t **outPorts; /* 'nChannels' ports for playback */ jack_default_audio_sample_t **outPortBufs; RtJackBuffer **bufs; /* 'nBuffers' I/O buffers */ int xrunFlag; /* non-zero if an xrun has occured */ jack_client_t *listclient; int outDevNum, inDevNum; /* select devs by number */ } RtJackGlobals; csound-6.10.0/H/cs_par_base.h000066400000000000000000000163321321653344700157070ustar00rootroot00000000000000/* cs_par_base.h: Copyright (C) 2011, 2017 John ffitch and Stephen Kyne This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __CS_PAR_BASE_H__ #define __CS_PAR_BASE_H__ // Semaphone.h only exists when using pthreads, doesn't apply to Windows #ifndef WIN32 #include #endif /* #define TAKE_LOCK(x) pthread_spin_lock(x) #define RELS_LOCK(x) pthread_spin_unlock(x) #define LOCK_TYPE pthread_spinlock_t #define INIT_LOCK(x) pthread_spin_init(&(x), PTHREAD_PROCESS_PRIVATE)*/ /* #define TAKE_LOCK(x) pthread_mutex_lock(x) */ /* #define RELS_LOCK(x) pthread_mutex_unlock(x) */ /* #define LOCK_TYPE pthread_mutex_t */ /* #define INIT_LOCK(x) pthread_mutex_init(&(x), NULL) */ #if !defined(HAVE_PTHREAD_SPIN_LOCK) // Windows environment should use native threads # if WIN32 #define TAKE_LOCK(x) csoundLockMutex(x) #define RELS_LOCK(x) csoundUnlockMutex(x) #define LOCK_TYPE LPCRITICAL_SECTION // PTHREAD: FIXME no init function? unless createMutex should be used // but has a different function signature #define INIT_LOCK(x) csoundCreateMutex(0) # else /* VL: 18.05.2011 enabled this to allow OSX build */ #define TAKE_LOCK(x) pthread_mutex_lock(x) #define RELS_LOCK(x) pthread_mutex_unlock(x) #define LOCK_TYPE pthread_mutex_t #define INIT_LOCK(x) pthread_mutex_init(&(x), NULL) # endif #else #define TAKE_LOCK(x) pthread_spin_lock(x) #define RELS_LOCK(x) pthread_spin_unlock(x) #define LOCK_TYPE pthread_spinlock_t #define INIT_LOCK(x) pthread_spin_init(&(x), PTHREAD_PROCESS_PRIVATE) #endif #define DYNAMIC_2_SERIALIZE_PAR /* #define TIMING */ /* #define SPINLOCK_BARRIER */ /* #define SPINLOCK_2_BARRIER */ #define HASH_CACHE /* #define HYBRID_HASH_CACHE */ /* #define LINEAR_CACHE */ /* #define CACLULATE_WEIGHTS_BUILD */ #define LOOKUP_WEIGHTS #define KPERF_SYM 0x31 #define BARRIER_1_WAIT_SYM 0x32 #define BARRIER_2_WAIT_SYM 0x33 /* return thread index of caller */ int csp_thread_index_get(CSOUND *csound); /* structure headers */ #define HDR_LEN 4 //#define INSTR_WEIGHT_INFO_HDR "IWI" #define INSTR_SEMANTICS_HDR "SEM" #define SET_ELEMENT_HDR "STE" #define SET_HDR "SET" //#define DAG_2_HDR "DG2" //#define DAG_NODE_2_HDR "DN2" //#define SEMAPHORE_HDR "SPS" #define GLOBAL_VAR_LOCK_HDR "GVL" //#define SERIALIZED_DAG_HDR "SDG" /* * set structures * * set maintains insertion order of elements * implemented as a singly linked list */ struct set_element_t { char hdr[4]; void *data; struct set_element_t *next; }; struct set_t { char hdr[4]; struct set_element_t *head; struct set_element_t *tail; int count; int (*ele_eq_func)(struct set_element_t *, struct set_element_t *); void (*ele_print_func)(CSOUND *, struct set_element_t *); struct set_element_t **cache; }; /* function pointer types for set member equality */ typedef int (set_element_data_eq)(struct set_element_t *, struct set_element_t *); int csp_set_element_string_eq(struct set_element_t *ele1, struct set_element_t *ele2); int csp_set_element_ptr_eq(struct set_element_t *ele1, struct set_element_t *ele2); /* function pointer types for set member printing */ typedef void (set_element_data_print)(CSOUND *, struct set_element_t *); void csp_set_element_string_print(CSOUND *csound, struct set_element_t *ele); void csp_set_element_ptr_print(CSOUND *csound, struct set_element_t *ele); /* allocating sets with specification of element equality and printing functions */ int csp_set_alloc(CSOUND *csound, struct set_t **set, set_element_data_eq *ele_eq_func, set_element_data_print *ele_print_func); int csp_set_dealloc(CSOUND *csound, struct set_t **set); /* shortcut to get a set of strings uses string element equality and printing functions */ int csp_set_alloc_string(CSOUND *csound, struct set_t **set); /* functions to manipulate set, return CSOUND_SUCCESS if successful */ int csp_set_add(CSOUND *csound, struct set_t *set, void *data); int csp_set_remove(CSOUND *csound, struct set_t *set, void *data); /* check element existance returns 1 if data exists */ int csp_set_exists(CSOUND *csound, struct set_t *set, void *data); int csp_set_print(CSOUND *csound, struct set_t *set); /* get a count and access members */ int csp_set_count(struct set_t *set); int csp_set_get_num(struct set_t *set, int num, void **data); /* * set union and intersection * allocates a new set in result * union/intersect first and second putting into result */ int csp_set_union(CSOUND *csound, struct set_t *first, struct set_t *second, struct set_t **result); int csp_set_intersection(CSOUND *csound, struct set_t *first, struct set_t *second, struct set_t **result); /* spinlock */ /* semaphore */ /* struct semaphore_spin_t { */ /* char hdr[HDR_LEN]; */ /* int thread_count; */ /* int max_threads; */ /* int arrived; */ /* int held; */ /* int spinlock; */ /* int count; */ /* int lock; */ /* int *key; */ /* int locks[]; */ /* }; */ // Kludge to allow us to pass in HANDLE objects to be used as semaphore whilst // supporting the traditional pthread way for non Windows platforms // FIXME, does this even work? API's take ** versions of sem_t #ifdef WIN32 typedef HANDLE sem_t; #endif /* create a semaphore with a maximum number of threads * initially 1 thread is allowed in */ void csp_semaphore_alloc(CSOUND *csound, sem_t **sem, int max_threads); void csp_semaphore_dealloc(CSOUND *csound, sem_t **sem); /* wait at the semaphore. if the number allowed in is greater than the * number arrived calling thread continues * otherwise thread blocks until semaphore is grown */ void csp_semaphore_wait(CSOUND *csound, sem_t *sem); /* increase the number of threads allowed in by 1 */ void csp_semaphore_grow(CSOUND *csound, sem_t *sem); /* reduce the number of threads allowed in and the arrive count by 1 * call this when calling thread is finished with the semaphore. */ void csp_semaphore_release(CSOUND *csound, sem_t *sem); /* call when all threads are done with the resource the semaphore is protecting. * releases all blocked threads. */ void csp_semaphore_release_end(CSOUND *csound, sem_t *sem); /* print semaphore info */ void csp_semaphore_release_print(CSOUND *csound, sem_t *sem); #endif /* end of include guard: __CS_PAR_BASE_H__ */ csound-6.10.0/H/cs_par_dispatch.h000066400000000000000000000026721321653344700165760ustar00rootroot00000000000000/* cs_par_dispatch.h: Copyright (C) 2011 by John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __CS_PAR_DISPATCH_H__ #define __CS_PAR_DISPATCH_H__ /* * locks must first be inserted and then the cache built * following this globals can be locked and unlocked with * the appropriate functions */ /* add global locks into AST root */ static TREE *csp_locks_insert(CSOUND * csound, TREE *root); /* build the cache of global locks */ void csp_locks_cache_build(CSOUND *csound); /* lock global with index */ void csp_locks_lock(CSOUND * csound, int global_index); /* unlock global with index */ void csp_locks_unlock(CSOUND * csound, int global_index); #endif /* end of include guard: __CS_PAR_DISPATCH_H__ */ csound-6.10.0/H/cs_par_ops.h000066400000000000000000000017631321653344700156000ustar00rootroot00000000000000/* cs_par_ops.h: Copyright (C) 2010 Chris Wilson and John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* CS_PAR_OPS.H */ typedef struct { OPDS h; MYFLT *gvar_ix; } GLOBAL_LOCK_UNLOCK; csound-6.10.0/H/cs_par_orc_semantics.h000066400000000000000000000071761321653344700176340ustar00rootroot00000000000000/* cs_par_orc_sematics.h: Copyright (C) 2011 by John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __CSOUND_ORC_SEMANTIC_ANALYSIS_H__ #define __CSOUND_ORC_SEMANTIC_ANALYSIS_H__ /* * This module maintains a list of instruments that have been parsed * When parsing an instrument: * csp_orc_sa_instr_add * called first to setup instrument (when parsed the instrument name/number) * csp_orc_sa_global_read_write_add_list * called to add globals to that instruments dependency lists * csp_orc_sa_instr_finalize * called when finished parsing that instrument * * csp_orc_sa_instr_get_by_name or by_num * called to fetch an instrument later */ /* maintain information about insturments defined */ typedef struct instr_semantics_t { char hdr[HDR_LEN]; char *name; int32 insno; int32 sanitized; struct set_t *read; struct set_t *write; struct set_t *read_write; uint32_t weight; struct instr_semantics_t *next; } INSTR_SEMANTICS; void csp_orc_sa_cleanup(CSOUND *csound); void csp_orc_sa_print_list(CSOUND *csound); /* maintain state about the current instrument we are parsing */ /* add a new instrument */ void csp_orc_sa_instr_add(CSOUND *csound, char *name); void csp_orc_sa_instr_add_tree(CSOUND *csound, TREE *x); /* finish the current instrument */ #define csp_orc_sa_instr_finalize(csound) \ { csound->instCurr = NULL; csound->inInstr = 0; } /* add the globals read and written to the current instrument; second case * if write and read contain the same global and size of both is 1 then * that global is added to the read-write list of the current instrument */ void csp_orc_sa_global_read_write_add_list(CSOUND *csound, struct set_t *write, struct set_t *read); void csp_orc_sa_global_read_write_add_list1(CSOUND *csound, struct set_t *write, struct set_t *read); /* add to the read and write lists of the current instrument */ void csp_orc_sa_global_write_add_list(CSOUND *csound, struct set_t *list); void csp_orc_sa_global_read_add_list(CSOUND *csound, struct set_t *list); /* find all the globals contained in the sub-tree node */ struct set_t *csp_orc_sa_globals_find(CSOUND *csound, TREE *node); /* find an instrument from the instruments parsed */ struct instr_semantics_t *csp_orc_sa_instr_get_by_name(CSOUND *csound, char *instr_name); struct instr_semantics_t *csp_orc_sa_instr_get_by_num(CSOUND *csound, int16 insno); /* interlocks */ void csp_orc_sa_interlocks(CSOUND *, ORCTOKEN *); void csp_orc_sa_interlocksf(CSOUND *, int); void csp_orc_analyze_tree(CSOUND *, TREE*); #endif /* end of include guard: __CSOUND_ORC_SEMANTIC_ANALYSIS_H__ */ csound-6.10.0/H/csmodule.h000066400000000000000000000133651321653344700152640ustar00rootroot00000000000000/* csmodule.h: Copyright (C) 2005 Istvan Varga based on dl_opcodes.c, Copyright (C) 2002 John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef CSOUND_CSMODULE_H #define CSOUND_CSMODULE_H /****************************************************************************** * NEW PLUGIN INTERFACE * * ==================== * * * * Plugin libraries are loaded from the directory defined by the environment * * variable OPCODE6DIR (or the current directory if OPCODE6DIR is unset) by * * csoundPreCompile() while initialising a Csound instance, and are unloaded * * at the end of performance by csoundReset(). * * A library may export any of the following five interface functions, * * however, the presence of csoundModuleCreate() is required for identifying * * the file as a Csound plugin module. * * * * int csoundModuleCreate(CSOUND *csound) (required) * * -------------------------------------- * * * * Pre-initialisation function, called by csoundPreCompile(). * * * * int csoundModuleInit(CSOUND *csound) (optional) * * ------------------------------------ * * * * Called by Csound instances before orchestra translation. One possible use * * of csoundModuleInit() is adding new opcodes with csoundAppendOpcode(). * * * * int csoundModuleDestroy(CSOUND *csound) (optional) * * --------------------------------------- * * * * Destructor function for Csound instance 'csound', called at the end of * * performance, after closing audio output. * * * * const char *csoundModuleErrorCodeToString(int errcode) (optional) * * ------------------------------------------------------ * * * * Converts error codes returned by any of the initialisation or destructor * * functions to a string message. * * * * int csoundModuleInfo(void) (optional) * * -------------------------- * * * * Returns information that can be used to determine if the plugin was built * * for a compatible version of libcsound. The return value may be the sum of * * any of the following two values: * * * * ((CS_APIVERSION << 16) + (CS_APISUBVER << 8)) API version * * (int) sizeof(MYFLT) MYFLT type * * * ******************************************************************************/ #ifdef __cplusplus extern "C" { #endif /* ------------------------ INTERNAL API FUNCTIONS ------------------------ */ /** * Load plugin libraries for Csound instance 'csound', and call * pre-initialisation functions. * Return value is CSOUND_SUCCESS if there was no error, CSOUND_ERROR if * some modules could not be loaded or initialised, and CSOUND_MEMORY * if a memory allocation failure has occured. */ int csoundLoadModules(CSOUND *csound); /** * Call initialisation functions of all loaded modules that have a * csoundModuleInit symbol, for Csound instance 'csound'. * Return value is CSOUND_SUCCESS if there was no error, and CSOUND_ERROR if * some modules could not be initialised. */ int csoundInitModules(CSOUND *csound); /** * Call destructor functions of all loaded modules that have a * csoundModuleDestroy symbol, for Csound instance 'csound'. * Return value is CSOUND_SUCCESS if there was no error, and * CSOUND_ERROR if some modules could not be de-initialised. */ int csoundDestroyModules(CSOUND *csound); /** * Initialise opcodes not in entry1.c */ int csoundInitSaticModules(CSOUND *csound); #ifdef __cplusplus } #endif #endif /* CSOUND_CSMODULE_H */ csound-6.10.0/H/csound_orc.h000066400000000000000000000043061321653344700156020ustar00rootroot00000000000000/* csound_orc.h: Copyright (C) 2007, 2017 by Stee Yi ad John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __CSOUND_ORC_H #define __CSOUND_ORC_H #define YYDEBUG 1 #include "parse_param.h" #include "tok.h" #include "csound_orcparse.h" #include "csoundCore.h" enum { S_ANDTHEN = T_HIGHEST+1, S_APPLY, }; typedef struct type_table { OENTRY* udos; CS_VAR_POOL* globalPool; CS_VAR_POOL* instr0LocalPool; CS_VAR_POOL* localPool; CONS_CELL* labelList; } TYPE_TABLE; #ifndef PARSER_DEBUG #define PARSER_DEBUG (0) #endif TREE* make_node(CSOUND *, int, int, int, TREE*, TREE*); TREE* make_leaf(CSOUND *, int, int, int, ORCTOKEN*); ORCTOKEN* make_int(CSOUND *,char *); ORCTOKEN* make_num(CSOUND *,char *); ORCTOKEN *make_token(CSOUND *csound, char *s); /*void instr0(CSOUND *, ORCTOKEN*, TREE*, TREE*);*/ /* extern TREE* statement_list; */ /* double get_num(TREE*); */ /*int get_int(TREE*);*/ /*TREE* check_opcode(TREE*, TREE*, TREE*);*/ /*TREE* check_opcode0(TREE*, TREE*);*/ /*void start_instr(int);*/ /* extern double sr, kr; extern int ksmps, nchnls; */ void query_deprecated_opcode(CSOUND *, ORCTOKEN *); // holds matching oentries from opcodeList // has space for 16 matches and next pointer in case more are found // (unlikely though) typedef struct oentries { int count; /* Number of etries in table */ //char *opname; //int prvnum; OENTRY* entries[0]; /* Entended by count entries */ } OENTRIES; #endif csound-6.10.0/H/csound_orc_expressions.h000066400000000000000000000027221321653344700202440ustar00rootroot00000000000000/* csound_orc_expressions.h: Copyright (C) 2013 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef CSOUND_ORC_EXPRESSION_H #define CSOUND_ORC_EXPRESSION_H 1 #include "csound_orc.h" CONS_CELL* cs_cons(CSOUND* csound, void* val, CONS_CELL* cons); CONS_CELL* cs_cons_append(CONS_CELL* cons1, CONS_CELL* cons2); int is_expression_node(TREE *node); int is_boolean_expression_node(TREE *node); int is_statement_expansion_required(TREE* root); void handle_optional_args(CSOUND *csound, TREE *l); TREE* expand_if_statement(CSOUND* csound, TREE* current, TYPE_TABLE* typeTable); TREE* expand_until_statement(CSOUND* csound, TREE* current, TYPE_TABLE* typeTable, int); TREE* expand_statement(CSOUND* csound, TREE* current, TYPE_TABLE* typeTable); #endif csound-6.10.0/H/csound_orc_semantics.h000066400000000000000000000026051321653344700176500ustar00rootroot00000000000000/* csound_orc_sematics.h: Copyright (C) 2013 by Steve Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef CSOUND_ORC_SEMANTICS_H #define CSOUND_ORC_SEMANTICS_H #include "csoundCore.h" #include "csound_orc.h" /** Gets short version of opcode name, trimming off anything after '.'. If opname has no '.' in name, simply returns the opname pointer. If the name is truncated, caller is responsible for calling mfree on returned value. Caller should compare the returned value with the passed in opname to see if it is different and thus requires mfree'ing. */ #include "find_opcode.h" char* get_arg_type2(CSOUND* csound, TREE* tree, TYPE_TABLE* typeTable); #endif csound-6.10.0/H/diskin2.h000066400000000000000000000111551321653344700150070ustar00rootroot00000000000000/* diskin2.h: Copyright (C) 2005 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef CSOUND_DISKIN2_H #define CSOUND_DISKIN2_H #include #define DISKIN2_MAXCHN 40 /* for consistency with soundin */ #define POS_FRAC_SHIFT 28 /* allows pitch accuracy of 2^-28 */ #define POS_FRAC_SCALE 0x10000000 #define POS_FRAC_MASK 0x0FFFFFFF typedef struct { OPDS h; MYFLT *aOut[DISKIN2_MAXCHN]; MYFLT *iFileCode; MYFLT *kTranspose; MYFLT *iSkipTime; MYFLT *iWrapMode; MYFLT *iSampleFormat; MYFLT *iWinSize; MYFLT *iBufSize; MYFLT *iSkipInit; MYFLT *forceSync; /* ------------------------------------- */ MYFLT WinSize; MYFLT BufSize; MYFLT SkipInit; MYFLT fforceSync; int initDone; int nChannels; int bufSize; /* in sample frames, power of two */ int wrapMode; int32 fileLength; /* in sample frames */ int32 bufStartPos; int64_t pos_frac; /* type should be defined in sysdep.h */ int64_t pos_frac_inc; int32 prvBufStartPos; int32 winSize; MYFLT *buf; MYFLT *prvBuf; MYFLT prv_kTranspose; MYFLT winFact; double warpScale; SNDFILE *sf; FDCH fdch; AUXCH auxData; /* for dynamically allocated buffers */ AUXCH auxData2; MYFLT *aOut_buf; MYFLT aOut_bufsize; void *cb; int async; } DISKIN2; typedef struct { OPDS h; ARRAYDAT *aOut; MYFLT *iFileCode; MYFLT *kTranspose; MYFLT *iSkipTime; MYFLT *iWrapMode; MYFLT *iSampleFormat; MYFLT *iWinSize; MYFLT *iBufSize; MYFLT *iSkipInit; MYFLT *forceSync; /* ------------------------------------- */ MYFLT WinSize; MYFLT BufSize; MYFLT SkipInit; MYFLT fforceSync; int initDone; int nChannels; int bufSize; /* in sample frames, power of two */ int wrapMode; int32 fileLength; /* in sample frames */ int32 bufStartPos; int64_t pos_frac; /* type should be defined in sysdep.h */ int64_t pos_frac_inc; int32 prvBufStartPos; int32 winSize; MYFLT *buf; MYFLT *prvBuf; MYFLT prv_kTranspose; MYFLT winFact; double warpScale; SNDFILE *sf; FDCH fdch; AUXCH auxData; /* for dynamically allocated buffers */ AUXCH auxData2; MYFLT *aOut_buf; MYFLT aOut_bufsize; void *cb; int async; } DISKIN2_ARRAY; int diskin2_init(CSOUND *csound, DISKIN2 *p); int diskin2_init_S(CSOUND *csound, DISKIN2 *p); int diskin2_perf(CSOUND *csound, DISKIN2 *p); int diskin2_init_array_I(CSOUND *csound, DISKIN2_ARRAY *p); int diskin2_init_array_S(CSOUND *csound, DISKIN2_ARRAY *p); int diskin_init_array_I(CSOUND *csound, DISKIN2_ARRAY *p); int diskin_init_array_S(CSOUND *csound, DISKIN2_ARRAY *p); int diskin2_perf_array(CSOUND *csound, DISKIN2_ARRAY *p); typedef struct { OPDS h; MYFLT *aOut[DISKIN2_MAXCHN]; MYFLT *iFileCode, *iSkipTime, *iSampleFormat, *iSkipInit, *iBufSize; int nChannels; int bufSize; /* in sample frames (power of two) */ int_least64_t fileLength; /* in sample frames */ int_least64_t bufStartPos; int_least64_t read_pos; /* current sample frame being read */ MYFLT *buf; SNDFILE *sf; MYFLT scaleFac; FDCH fdch; AUXCH auxData; /* for dynamically allocated buffers */ } SOUNDIN_; #define SNDOUTSMPS (1024) typedef struct { SNDFILE *sf; void *fd; MYFLT *outbufp, *bufend; MYFLT outbuf[SNDOUTSMPS]; } SNDCOM; typedef struct { OPDS h; MYFLT *asig, *ifilcod, *iformat; SNDCOM c; } SNDOUT; typedef struct { OPDS h; MYFLT *asig1, *asig2, *ifilcod, *iformat; SNDCOM c; } SNDOUTS; #endif /* CSOUND_DISKIN2_H */ csound-6.10.0/H/disprep.h000066400000000000000000000046411321653344700151140ustar00rootroot00000000000000/* disprep.h: Copyright (C) 1991 Barry Vercoe This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* DISPREP.H */ #include "pstream.h" typedef struct { OPDS h; MYFLT *iargs[VARGMAX]; } PRINTV; typedef struct { OPDS h; MYFLT *signal, *iprd, *inprds, *iwtflg; int32 npts, nprds, bufpts, totpts, pntcnt; WINDAT dwindow; MYFLT *nxtp, *begp, *endp; AUXCH auxch; } DSPLAY; typedef struct { OPDS h; PVSDAT *fin; MYFLT *points, *flag; int size; WINDAT dwindow; AUXCH fdata; uint32 lastframe; } FSIGDISP; #define WINDMAX 16384 #define WINDMIN 16 typedef struct { OPDS h; MYFLT *signal, *iprd, *inpts, *ihann, *idbout, *iwtflg, *imin, *imax; MYFLT *sampbuf, *bufp, *endp, overN; int32 windsize, overlap, ncoefs; int hanning, dbout; int npts, start; WINDAT dwindow; AUXCH auxch; AUXCH smpbuf; } DSPFFT; typedef struct { OPDS h; MYFLT *kout,*kin,*iprd,*imindur,*imemdur,*ihp,*ithresh,*ihtim,*ixfdbak; MYFLT *istartempo,*ifn,*idisprd,*itweek; int countdown, timcount, npts, minlam, maxlam; MYFLT *hbeg, *hcur, *hend; MYFLT *xbeg, *xcur, *xend; MYFLT *stmemp, *linexp, *ftable, *xscale, *lmults; int16 *lambdas; MYFLT *stmemnow, ncross, coef0, coef1, yt1, thresh; MYFLT fwdcoef, fwdmask, xfdbak, avglam, tempscal, tempo, tweek; int dcntdown, dtimcnt; WINDAT dwindow; AUXCH auxch; } TEMPEST; csound-6.10.0/H/dumpf.h000066400000000000000000000056071321653344700145640ustar00rootroot00000000000000/* dumpf.h: Copyright (C) 1991 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* DUMPF.H */ typedef struct { OPDS h; MYFLT *ksig, *ifilcod, *iformat, *iprd; int format; int32 countdown, timcount; FILE *f; FDCH fdch; } KDUMP; typedef struct { OPDS h; MYFLT *ksig1, *ksig2, *ifilcod, *iformat, *iprd; int format; int32 countdown, timcount; FILE *f; FDCH fdch; } KDUMP2; typedef struct { OPDS h; MYFLT *ksig1, *ksig2, *ksig3, *ifilcod, *iformat, *iprd; int format; int32 countdown, timcount; FILE *f; FDCH fdch; } KDUMP3; typedef struct { OPDS h; MYFLT *ksig1, *ksig2, *ksig3, *ksig4, *ifilcod, *iformat, *iprd; int format; int32 countdown, timcount; FILE *f; FDCH fdch; } KDUMP4; typedef struct { OPDS h; MYFLT *k1, *ifilcod, *iformat, *iprd; /* MYFLT *interp; */ int format; int32 countdown, timcount; MYFLT k[4]; FILE *f; FDCH fdch; } KREAD; typedef struct { OPDS h; MYFLT *k1, *k2, *ifilcod, *iformat, *iprd; /* MYFLT *interp; */ int format; int32 countdown, timcount; MYFLT k[4]; FILE *f; FDCH fdch; } KREAD2; typedef struct { OPDS h; MYFLT *k1, *k2, *k3, *ifilcod, *iformat, *iprd; /* MYFLT *interp; */ int format; int32 countdown, timcount; MYFLT k[4]; FILE *f; FDCH fdch; } KREAD3; typedef struct { OPDS h; MYFLT *k1, *k2, *k3, *k4, *ifilcod, *iformat, *iprd; /* MYFLT *interp; */ int format; int32 countdown, timcount; MYFLT k[4]; FILE *f; FDCH fdch; } KREAD4; typedef struct { OPDS h; STRINGDAT *str; MYFLT *ifilcod, *iprd; int32 countdown, timcount; char *lasts; FILE *f; FDCH fdch; } KREADS; csound-6.10.0/H/entry1.h000066400000000000000000000575161321653344700147010ustar00rootroot00000000000000/* entry1.h: Copyright (C) 1991 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* ENTRY1.H */ #include "insert.h" #include "aops.h" #include "midiops.h" #include "ugens1.h" #include "ugens2.h" #include "ugens3.h" #include "ugens4.h" #include "ugens5.h" #include "ugens6.h" #include "cwindow.h" #include "windin.h" #include "disprep.h" #include "soundio.h" #include "dumpf.h" #include "cmath.h" #include "diskin2.h" #include "oload.h" #include "midiout.h" #include "sndinfUG.h" #include "ugrw1.h" #include "schedule.h" #include "vdelay.h" #include "pstream.h" #include "oscils.h" #include "midifile.h" #include "midiinterop.h" #include "linevent.h" #include "str_ops.h" #include "bus.h" #include "pstream.h" #include "remote.h" #include "resize.h" #include "cs_par_ops.h" #include "ugtabs.h" #include "compile_ops.h" #define S(x) sizeof(x) int ihold(CSOUND *, void *), turnoff(CSOUND *, void *); int gaassign(CSOUND *, void *), rassign(CSOUND *, void *); int aassign(CSOUND *, void *), laassign(CSOUND *, void *); int assign(CSOUND *, void *); int init(CSOUND *, void *), ainit(CSOUND *, void *); int minit(CSOUND *, void *), mainit(CSOUND *, void *); /* int tinit(CSOUND *, void *), tassign(CSOUND *, void *); */ /* int tabref_check(CSOUND *, void *), tabref(CSOUND *, void *); */ int gt(CSOUND *, void *), ge(CSOUND *, void *); int lt(CSOUND *, void *), le(CSOUND *, void *); int eq(CSOUND *, void *), ne(CSOUND *, void *); int and(CSOUND *, void *), or(CSOUND *, void *); int b_not(CSOUND *, void*); int conval(CSOUND *, void *), aconval(CSOUND *, void *); int addkk(CSOUND *, void *), subkk(CSOUND *, void *); int mulkk(CSOUND *, void *), divkk(CSOUND *, void *); int modkk(CSOUND *, void *); int addka(CSOUND *, void *), subka(CSOUND *, void *); int mulka(CSOUND *, void *), divka(CSOUND *, void *); int modka(CSOUND *, void *); int addak(CSOUND *, void *), subak(CSOUND *, void *); int mulak(CSOUND *, void *), divak(CSOUND *, void *); int modak(CSOUND *, void *); int addaa(CSOUND *, void *), subaa(CSOUND *, void *); int mulaa(CSOUND *, void *), divaa(CSOUND *, void *); int modaa(CSOUND *, void *); int divzkk(CSOUND *, void *), divzka(CSOUND *, void *); int divzak(CSOUND *, void *), divzaa(CSOUND *, void *); int int1(CSOUND *, void *), int1a(CSOUND *, void *); int frac1(CSOUND *, void *), frac1a(CSOUND *, void *); int int1_round(CSOUND *, void *), int1a_round(CSOUND *, void *); int int1_floor(CSOUND *, void *), int1a_floor(CSOUND *, void *); int int1_ceil(CSOUND *, void *), int1a_ceil(CSOUND *, void *); int rnd1(CSOUND *, void *), birnd1(CSOUND *, void *); int abs1(CSOUND *, void *), exp01(CSOUND *, void *); int log01(CSOUND *, void *), sqrt1(CSOUND *, void *); int sin1(CSOUND *, void *), cos1(CSOUND *, void *); int is_NaN(CSOUND *, void *), is_NaNa(CSOUND *, void *); int is_inf(CSOUND *, void *), is_infa(CSOUND *, void *); int tan1(CSOUND *, void *), asin1(CSOUND *, void *); int acos1(CSOUND *, void *), atan1(CSOUND *, void *); int sinh1(CSOUND *, void *), cosh1(CSOUND *, void *); int tanh1(CSOUND *, void *), log101(CSOUND *, void *), log21(CSOUND *, void *); int atan21(CSOUND *, void *), atan2aa(CSOUND *, void *); int absa(CSOUND *, void *), expa(CSOUND *, void *); int loga(CSOUND *, void *), sqrta(CSOUND *, void *); int sina(CSOUND *, void *), cosa(CSOUND *, void *); int tana(CSOUND *, void *), asina(CSOUND *, void *); int acosa(CSOUND *, void *), atana(CSOUND *, void *); int sinha(CSOUND *, void *), cosha(CSOUND *, void *); int tanha(CSOUND *, void *), log10a(CSOUND *, void *), log2a(CSOUND *, void *); int dbamp(CSOUND *, void *), ampdb(CSOUND *, void *); int aampdb(CSOUND *, void *), dbfsamp(CSOUND *, void *); int ampdbfs(CSOUND *, void *), aampdbfs(CSOUND *, void *); int ftlen(CSOUND *, void *), ftlptim(CSOUND *, void *); int ftchnls(CSOUND *, void *), ftcps(CSOUND *, void *); int signum(CSOUND *, void *), asignum(CSOUND *, void *); int rtclock(CSOUND *, void *); int cpsoct(CSOUND *, void *), octpch(CSOUND *, void *); int cpspch(CSOUND *, void *), pchoct(CSOUND *, void *); int octcps(CSOUND *, void *), acpsoct(CSOUND *, void *); int cpsmidinn(CSOUND *, void *), octmidinn(CSOUND *, void *); int pchmidinn(CSOUND *, void *);int massign_S(CSOUND *, void *); int massign_p(CSOUND *, void *), ctrlinit(CSOUND *, void *); int notnum(CSOUND *, void *), veloc(CSOUND *, void *); int pchmidi(CSOUND *, void *), pchmidib(CSOUND *, void *); int octmidi(CSOUND *, void *), octmidib(CSOUND *, void *); int pchmidib_i(CSOUND *, void *), octmidib_i(CSOUND *, void *); int icpsmidib_i(CSOUND *, void *), cpsmidi(CSOUND *, void *); int icpsmidib(CSOUND *, void *), kcpsmidib(CSOUND *, void *); int kmbset(CSOUND *, void *), midibset(CSOUND *, void *); int ipchmidib(CSOUND *, void *), ioctmidib(CSOUND *, void *); int kpchmidib(CSOUND *, void *), koctmidib(CSOUND *, void *); int msclset(CSOUND *, void *), ampmidi(CSOUND *, void *); int aftset(CSOUND *, void *), aftouch(CSOUND *, void *); int chpress(CSOUND *, void *), ipchbend(CSOUND *, void *); int kbndset(CSOUND *, void *), kpchbend(CSOUND *, void *); int imidictl(CSOUND *, void *), mctlset(CSOUND *, void *); int midictl(CSOUND *, void *), imidiaft(CSOUND *, void *); int maftset(CSOUND *, void *), midiaft(CSOUND *, void *); int midiout(CSOUND *, void *), turnon(CSOUND *, void *); int turnon_S(CSOUND *, void *); int kmapset(CSOUND *, void *), polyaft(CSOUND *, void *); int ichanctl(CSOUND *, void *), chctlset(CSOUND *, void *); int chanctl(CSOUND *, void *), linset(CSOUND *, void *); int kline(CSOUND *, void *), aline(CSOUND *, void *); int expset(CSOUND *, void *), kexpon(CSOUND *, void *); int expon(CSOUND *, void *), lsgset(CSOUND *, void *); int klnseg(CSOUND *, void *), linseg(CSOUND *, void *); int csgset(CSOUND *, void *), kosseg(CSOUND *, void *); int csgset_bkpt(CSOUND *, void *), cosseg(CSOUND *, void *); int csgrset(CSOUND *, void *); int kcssegr(CSOUND *, void *), cossegr(CSOUND *, void *); int madsrset(CSOUND *, void *), adsrset(CSOUND *, void *); int xdsrset(CSOUND *, void *), mxdsrset(CSOUND *, void *); int expseg2(CSOUND *, void *), xsgset(CSOUND *, void *); int kxpseg(CSOUND *, void *), expseg(CSOUND *, void *); int xsgset2(CSOUND *, void *), lsgrset(CSOUND *, void *); int klnsegr(CSOUND *, void *), linsegr(CSOUND *, void *); int xsgrset(CSOUND *, void *), kxpsegr(CSOUND *, void *); int expsegr(CSOUND *, void *), lnnset(CSOUND *, void *); int klinen(CSOUND *, void *), linen(CSOUND *, void *); int lnrset(CSOUND *, void *), klinenr(CSOUND *, void *); int linenr(CSOUND *, void *), evxset(CSOUND *, void *); int knvlpx(CSOUND *, void *), envlpx(CSOUND *, void *); int evrset(CSOUND *, void *), knvlpxr(CSOUND *, void *); int envlpxr(CSOUND *, void *), phsset(CSOUND *, void *); int ephsset(CSOUND *, void *), ephsor(CSOUND *, void *); int kphsor(CSOUND *, void *), phsor(CSOUND *, void *); int ko1set(CSOUND *, void *); int kosc1(CSOUND *, void *), kosc1i(CSOUND *, void *); int oscnset(CSOUND *, void *), osciln(CSOUND *, void *); int oscset(CSOUND *, void *), koscil(CSOUND *, void *); int oscsetA(CSOUND *, void *); int osckk(CSOUND *, void *), oscka(CSOUND *, void *); int oscak(CSOUND *, void *), oscaa(CSOUND *, void *); int koscli(CSOUND *, void *), osckki(CSOUND *, void *); int osckai(CSOUND *, void *), oscaki(CSOUND *, void *); int oscaai(CSOUND *, void *), foscset(CSOUND *, void *); int foscil(CSOUND *, void *), foscili(CSOUND *, void *); int losset(CSOUND *, void *), loscil(CSOUND *, void *); int loscil3(CSOUND *, void *), koscl3(CSOUND *, void *); int osckk3(CSOUND *, void *), oscka3(CSOUND *, void *); int oscak3(CSOUND *, void *), oscaa3(CSOUND *, void *); int adset(CSOUND *, void *), adsyn(CSOUND *, void *); int bzzset(CSOUND *, void *), buzz(CSOUND *, void *); int gbzset(CSOUND *, void *), gbuzz(CSOUND *, void *); int plukset(CSOUND *, void *), pluck(CSOUND *, void *); int rndset(CSOUND *, void *), krand(CSOUND *, void *); int arand(CSOUND *, void *), rhset(CSOUND *, void *); int krandh(CSOUND *, void *), randh(CSOUND *, void *); int riset(CSOUND *, void *), krandi(CSOUND *, void *); int randi(CSOUND *, void *), rndset2(CSOUND *, void *); int krand2(CSOUND *, void *), arand2(CSOUND *, void *); int rhset2(CSOUND *, void *), krandh2(CSOUND *, void *); int randh2(CSOUND *, void *), riset2(CSOUND *, void *); int krandi2(CSOUND *, void *), randi2(CSOUND *, void *); int porset(CSOUND *, void *), port(CSOUND *, void *); int tonset(CSOUND *, void *), tone(CSOUND *, void *); int atone(CSOUND *, void *), rsnset(CSOUND *, void *); int reson(CSOUND *, void *), areson(CSOUND *, void *); int resonx(CSOUND *, void *), aresonx(CSOUND *, void *); int rsnsetx(CSOUND *, void *), tonex(CSOUND *, void *); int atonex(CSOUND *, void *), tonsetx(CSOUND *, void *); int lprdset(CSOUND *, void *), lpread(CSOUND *, void *); int lpformantset(CSOUND *, void *), lpformant(CSOUND *, void*); int lprsnset(CSOUND *, void *), lpreson(CSOUND *, void *); int lpfrsnset(CSOUND *, void *), lpfreson(CSOUND *, void *); int lpslotset(CSOUND *, void *), lpitpset(CSOUND *, void *); int lpinterpol(CSOUND *, void *); int rmsset(CSOUND *, void *), rms(CSOUND *, void *); int gainset(CSOUND *, void *), gain(CSOUND *, void *); int sndinset(CSOUND *, void *), sndinset_S(CSOUND *, void *), soundin(CSOUND *, void *); int sndoutset(CSOUND *, void *), sndoutset_S(CSOUND *, void *), soundout(CSOUND *, void *); int soundouts(CSOUND *, void *), inarray(CSOUND *, void *); int in(CSOUND *, void *), ins(CSOUND *, void *); int inq(CSOUND *, void *), inh(CSOUND *, void *); int ino(CSOUND *, void *), in16(CSOUND *, void *); int in32(CSOUND *, void *), outarr(CSOUND *, void *); int inch_opcode(CSOUND *, void *), inall_opcode(CSOUND *, void *); int inch_set(CSOUND*, void*), outmultiple(CSOUND *, void *); /* int out(CSOUND *, void *), outs(CSOUND *, void *); */ int outs1(CSOUND *, void *), outs2(CSOUND *, void *); int och2(CSOUND *, void *), och3(CSOUND *, void *); int och4(CSOUND *, void *), ochn(CSOUND *, void *); int outq1(CSOUND *, void *), outq2(CSOUND *, void *); int outq3(CSOUND *, void *), outq4(CSOUND *, void *); /* int outh(CSOUND *, void *), outo(CSOUND *, void *); */ /* int outx(CSOUND *, void *), outX(CSOUND *, void *); */ int outch(CSOUND *, void *), outall(CSOUND *, void *); int igoto(CSOUND *, void *), kgoto(CSOUND *, void *); int icgoto(CSOUND *, void *), kcgoto(CSOUND *, void *); int timset(CSOUND *, void *), timout(CSOUND *, void *); int reinit(CSOUND *, void *), rigoto(CSOUND *, void *); int rireturn(CSOUND *, void *), tigoto(CSOUND *, void *); int tival(CSOUND *, void *), printv(CSOUND *, void *); int dspset(CSOUND *, void *), kdsplay(CSOUND *, void *); int fdspset(CSOUND *, void *), fdsplay(CSOUND *, void *); int dsplay(CSOUND *, void *), fftset(CSOUND *, void *); int kdspfft(CSOUND *, void *), dspfft(CSOUND *, void *); int xyinset(CSOUND *, void *); int tempeset(CSOUND *, void *), tempest(CSOUND *, void *); int tempset(CSOUND *, void *), tempo(CSOUND *, void *); int old_kdmpset(CSOUND *, void *), old_kdmp2set(CSOUND *, void *); int old_kdmp3set(CSOUND *, void *), old_kdmp4set(CSOUND *, void *); int kdmpset_p(CSOUND *, void *), kdmp2set_p(CSOUND *, void *); int kdmp3set_p(CSOUND *, void *), kdmp4set_p(CSOUND *, void *); int kdmpset_S(CSOUND *, void *), kdmp2set_S(CSOUND *, void *); int kdmp3set_S(CSOUND *, void *), kdmp4set_S(CSOUND *, void *); int kdump(CSOUND *, void *), kdump2(CSOUND *, void *); int kdump3(CSOUND *, void *), kdump4(CSOUND *, void *); int krdset_S(CSOUND *, void *), krd2set_S(CSOUND *, void *); int krd3set_S(CSOUND *, void *), krd4set_S(CSOUND *, void *); int krdset_p(CSOUND *, void *), krd2set_p(CSOUND *, void *); int krd3set_p(CSOUND *, void *), krd4set_p(CSOUND *, void *); int kread(CSOUND *, void *), kread2(CSOUND *, void *); int kread3(CSOUND *, void *), kread4(CSOUND *, void *); int krdsset_S(CSOUND *, void *),krdsset_p(CSOUND *, void *), kreads(CSOUND *, void *); int ipow(CSOUND *, void *), apow(CSOUND *, void *); int alinear(CSOUND *, void *), iklinear(CSOUND *, void *); int atrian(CSOUND *, void *), iktrian(CSOUND *, void *); int aexp(CSOUND *, void *), ikexp(CSOUND *, void *); int abiexp(CSOUND *, void *), ikbiexp(CSOUND *, void *); int agaus(CSOUND *, void *), ikgaus(CSOUND *, void *); int acauchy(CSOUND *, void *), ikcauchy(CSOUND *, void *); int apcauchy(CSOUND *, void *), ikpcauchy(CSOUND *, void *); int abeta(CSOUND *, void *), ikbeta(CSOUND *, void *); int aweib(CSOUND *, void *), ikweib(CSOUND *, void *); int apoiss(CSOUND *, void *), ikpoiss(CSOUND *, void *); int seedrand(CSOUND *, void *), getseed(CSOUND *, void *); int auniform(CSOUND *, void *), ikuniform(CSOUND *, void *); int newsndinset(CSOUND *, void *), soundinew(CSOUND *, void *); int iout_on(CSOUND *, void *), iout_off(CSOUND *, void *); int out_controller(CSOUND *, void *), iout_on_dur_set(CSOUND *, void *); int iout_on_dur(CSOUND *, void *), iout_on_dur2(CSOUND *, void *); int moscil_set(CSOUND *, void *), moscil(CSOUND *, void *); int kvar_out_on_set(CSOUND *, void *), kvar_out_on_set1(CSOUND *, void *); int kvar_out_on(CSOUND *, void *), out_controller14(CSOUND *, void *); int out_pitch_bend(CSOUND *, void *), out_aftertouch(CSOUND *, void *); int out_poly_aftertouch(CSOUND*, void*), out_progchange(CSOUND*, void*); int release_set(CSOUND *, void *), release(CSOUND *, void *); int xtratim(CSOUND *, void *); int mclock_set(CSOUND *, void *), mclock(CSOUND *, void *); int mrtmsg(CSOUND *, void *); int cabasaset(CSOUND *, void *), cabasa(CSOUND *, void *); int sekereset(CSOUND *, void *), sandset(CSOUND *, void *); int stixset(CSOUND *, void *), crunchset(CSOUND *, void *); int guiroset(CSOUND *, void *), guiro(CSOUND *, void *); int sekere(CSOUND *, void *); int tambourset(CSOUND *, void *), tambourine(CSOUND *, void *); int bambooset(CSOUND *, void *), bamboo(CSOUND *, void *); int wuterset(CSOUND *, void *), wuter(CSOUND *, void *); int sleighset(CSOUND *, void *), sleighbells(CSOUND *, void *); int trig_set(CSOUND *, void *), trig(CSOUND *, void *); int numsamp(CSOUND *, void *), ftsr(CSOUND *, void *); int kon2_set(CSOUND *, void *), kon2(CSOUND *, void *); int nrpn(CSOUND *, void *); int mdelay(CSOUND *, void *), mdelay_set(CSOUND *, void *); int sum(CSOUND *, void *), product(CSOUND *, void *); int macset(CSOUND *, void *); int mac(CSOUND *, void *), maca(CSOUND *, void *); int nestedapset(CSOUND *, void *), nestedap(CSOUND *, void *); int lorenzset(CSOUND *, void *), lorenz(CSOUND *, void *); int filelen(CSOUND *, void *), filenchnls(CSOUND *, void *); int filesr(CSOUND *, void *), filepeak(CSOUND *, void *); int filevalid(CSOUND *, void *); int filelen_S(CSOUND *, void *), filenchnls_S(CSOUND *, void *); int filesr_S(CSOUND *, void *), filepeak_S(CSOUND *, void *); int filevalid_S(CSOUND *, void *); int ilogbasetwo(CSOUND *, void *), logbasetwo_set(CSOUND *, void *); int powoftwo(CSOUND *, void *), powoftwoa(CSOUND *, void *); int logbasetwo(CSOUND *, void *), logbasetwoa(CSOUND *, void *); int lp2_set(CSOUND *, void *), lp2(CSOUND *, void *); int phaser2set(CSOUND *, void *), phaser2(CSOUND *, void *); int phaser1set(CSOUND *, void *), phaser1(CSOUND *, void *); int balnset(CSOUND *, void *), balance(CSOUND *, void *); int prealloc(CSOUND *, void *); int prealloc_S(CSOUND *, void *), active_alloc(CSOUND*, void*); int cpsxpch(CSOUND *, void *), cps2pch(CSOUND *, void *); int cpstmid(CSOUND *, void *); int cpstun(CSOUND *, void *), cpstun_i(CSOUND *, void *); int wgpsetin(CSOUND *, void *); int wgpset(CSOUND *, void *), wgpluck(CSOUND *, void *); int clarinset(CSOUND *, void *), clarin(CSOUND *, void *); int fluteset(CSOUND *, void *), flute(CSOUND *, void *); int bowedset(CSOUND *, void *), bowed(CSOUND *, void *); int brassset(CSOUND *, void *), brass(CSOUND *, void *); int schedule(CSOUND *, void *), schedule_S(CSOUND *, void *); int schedule_N(CSOUND *, void *), schedule_SN(CSOUND *, void *); int ifschedule(CSOUND *, void *), kschedule(CSOUND *, void *); int triginset(CSOUND *, void *), ktriginstr(CSOUND *, void *); int triginset_S(CSOUND *, void *), ktriginstr_S(CSOUND *, void *); int trigseq_set(CSOUND *, void *), trigseq(CSOUND *, void *); int eventOpcode(CSOUND *, void *), eventOpcodeI(CSOUND *, void *); int eventOpcode_S(CSOUND *, void *), eventOpcodeI_S(CSOUND *, void *); int instanceOpcode(CSOUND *, void *), instanceOpcode_S(CSOUND *, void *); int kill_instance(CSOUND *csound, void *p); int lfoset(CSOUND *, void *); int lfok(CSOUND *, void *), lfoa(CSOUND *, void *); int mute_inst(CSOUND *, void *); int pvsanalset(CSOUND *, void *), pvsanal(CSOUND *, void *); int pvsynthset(CSOUND *, void *), pvsynth(CSOUND *, void *); int pvadsynset(CSOUND *, void *), pvadsyn(CSOUND *, void *); int pvscrosset(CSOUND *, void *), pvscross(CSOUND *, void *); int pvsfreadset(CSOUND *, void *), pvsfread(CSOUND *, void *); int pvsmaskaset(CSOUND *, void *), pvsmaska(CSOUND *, void *); int pvsftwset(CSOUND *, void *), pvsftw(CSOUND *, void *); int pvsftrset(CSOUND *, void *), pvsftr(CSOUND *, void *); int pvsinfo(CSOUND *, void *); int gettempo(CSOUND *, void *), fassign(CSOUND *, void *); int loopseg_set(CSOUND *, void *); int loopseg(CSOUND *, void *), lpshold(CSOUND *, void *); int lineto_set(CSOUND *, void *), lineto(CSOUND *, void *); int tlineto_set(CSOUND *, void *), tlineto(CSOUND *, void *); int vibrato_set(CSOUND *, void *), vibrato(CSOUND *, void *); int vibr_set(CSOUND *, void *), vibr(CSOUND *, void *); int randomi_set(CSOUND *, void *); int krandomi(CSOUND *, void *), randomi(CSOUND *, void *); int randomh_set(CSOUND *, void *); int krandomh(CSOUND *, void *), randomh(CSOUND *, void *); int random3_set(CSOUND *, void *); int random3(CSOUND *, void *), random3a(CSOUND *, void *); int db(CSOUND *, void *), dba(CSOUND *, void *); int semitone(CSOUND *, void *), asemitone(CSOUND *, void *); int cent(CSOUND *, void *), acent(CSOUND *, void *); int midichn(CSOUND *, void *), pgmassign(CSOUND *, void *), pgmassign_S(CSOUND *, void *); int midiin_set(CSOUND *, void *), midiin(CSOUND *, void *); int pgmin_set(CSOUND *, void *), pgmin(CSOUND *, void *); int ctlin_set(CSOUND *, void *), ctlin(CSOUND *, void *); int midinoteoff(CSOUND *, void *), midinoteonkey(CSOUND *, void *); int midinoteoncps(CSOUND *, void *), midinoteonoct(CSOUND *, void *); int midinoteonpch(CSOUND *, void *), midipolyaftertouch(CSOUND *, void *); int midicontrolchange(CSOUND *, void *); int midiprogramchange(CSOUND *, void *); int midichannelaftertouch(CSOUND *, void *); int midipitchbend(CSOUND *, void *); int mididefault(CSOUND *, void *); int subinstrset_S(CSOUND *, void *); int subinstrset(CSOUND *, void *), subinstr(CSOUND *, void *); int useropcdset(CSOUND *, void *), useropcd(CSOUND *, void *); int setksmpsset(CSOUND *, void *); int xinset(CSOUND *, void *), xoutset(CSOUND *, void *); int ingoto(CSOUND *, void *), kngoto(CSOUND *, void *); int iingoto(CSOUND *, void *), kingoto(CSOUND *, void *); int nstrnumset(CSOUND *, void *), turnoff2k(CSOUND *, void *); int nstrnumset_S(CSOUND *, void *); int turnoff2S(CSOUND *, void *) ; int loop_l_i(CSOUND *, void *), loop_le_i(CSOUND *, void *); int loop_g_i(CSOUND *, void *), loop_ge_i(CSOUND *, void *); int loop_l_p(CSOUND *, void *), loop_le_p(CSOUND *, void *); int loop_g_p(CSOUND *, void *), loop_ge_p(CSOUND *, void *); int delete_instr(CSOUND *, void *); int insremot(CSOUND *, void *), insglobal(CSOUND *, void *); int midremot(CSOUND *, void *), midglobal(CSOUND *, void *); int remoteport(CSOUND *, void *); int globallock(CSOUND *, void *); int globalunlock(CSOUND *, void *); int filebit(CSOUND *, void *); int filebit_S(CSOUND *, void *); int iexprndi(CSOUND *, void *), exprndiset(CSOUND *, void *); int kexprndi(CSOUND *, void *), aexprndi(CSOUND *, void *); int icauchyi(CSOUND *, void *), cauchyiset(CSOUND *, void *); int kcauchyi(CSOUND *, void *), acauchyi(CSOUND *, void *); int igaussi(CSOUND *, void *), gaussiset(CSOUND *, void *); int kgaussi(CSOUND *, void *), agaussi(CSOUND *, void *); int lsgset_bkpt(CSOUND *csound, void *p); int xsgset_bkpt(CSOUND *csound, void *p); int xsgset_bkpt(CSOUND *csound, void *p), xsgset2b(CSOUND *, void *); int resize_table(CSOUND *csound, void *p); int error_fn(CSOUND *csound, void *p); int fassign_set(CSOUND *csound, FASSIGN *p); int tabler_init(CSOUND *csound, TABL *p); int tabl_setup(CSOUND *csound, TABL *p); int tabler_kontrol(CSOUND *csound, TABL *p); int tabler_audio(CSOUND *csound, TABL *p); int tableir_init(CSOUND *csound, TABL *p); int tableir_audio(CSOUND *csound, TABL *p); int tableir_kontrol(CSOUND *csound, TABL *p); int tableir_audio(CSOUND *csound, TABL *p); int table3r_init(CSOUND *csound, TABL *p); int table3r_kontrol(CSOUND *csound, TABL *p); int table3r_audio(CSOUND *csound, TABL *p); int tablerkt_kontrol(CSOUND *csound, TABL *p); int tablerkt_audio(CSOUND *csound, TABL *p); int tableirkt_kontrol(CSOUND *csound, TABL *p); int tableirkt_audio(CSOUND *csound, TABL *p); int table3rkt_kontrol(CSOUND *csound, TABL *p); int table3rkt_audio(CSOUND *csound, TABL *p); int tablew_init(CSOUND *csound, TABL *p); int tablew_kontrol(CSOUND *csound, TABL *p); int tablew_audio(CSOUND *csound, TABL *p); int tablewkt_kontrol(CSOUND *csound, TABL *p); int tablewkt_audio(CSOUND *csound, TABL *p); int table_length(CSOUND *csound, TLEN *p); int table_gpw(CSOUND *csound, TGP *p); int table_copy(CSOUND *csound, TGP *p); int table_mix(CSOUND *csound, TABLMIX *p); int table_ra_set(CSOUND *csound, TABLRA *p); int table_ra(CSOUND *csound, TABLRA *p); int table_wa_set(CSOUND *csound, TABLWA *p); int table_wa(CSOUND *csound, TABLWA *p); int tablkt_setup(CSOUND *csound, TABL *p); int diskin_init(CSOUND *csound, DISKIN2 *p); int diskin_init_S(CSOUND *csound, DISKIN2 *p); int inch1_set(CSOUND *csound, void *p); int inch_opcode1(CSOUND *csound, void *p); int adset_S(CSOUND *csound, void *p); int lprdset_S(CSOUND *csound, void *p); int pvsfreadset_S(CSOUND *csound, void *p); int alnnset(CSOUND *csound, void *p); int alnrset(CSOUND *csound, void *p); int aevxset(CSOUND *csound, void *p); int aevrset(CSOUND *csound, void *p); int midiarp_set(CSOUND *, void *); int midiarp(CSOUND *, void *); csound-6.10.0/H/envvar.h000066400000000000000000000246231321653344700147510ustar00rootroot00000000000000/* envvar.h: Copyright (C) 2005 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef CSOUND_ENVVAR_H #define CSOUND_ENVVAR_H #if !defined(__BUILDING_LIBCSOUND) # error "Csound plugins and host applications should not include envvar.h" #endif #ifdef __cplusplus extern "C" { #endif /** * Set environment variable 'name' to 'value'. * Returns CSOUND_SUCCESS on success, and CSOUND_ERROR or CSOUND_MEMORY * if the environment variable could not be set for some reason. */ int csoundSetEnv(CSOUND *csound, const char *name, const char *value); /** * Append 'value' to environment variable 'name', using ';' as * separator character. * Returns CSOUND_SUCCESS on success, and CSOUND_ERROR or CSOUND_MEMORY * if the environment variable could not be set for some reason. */ int csoundAppendEnv(CSOUND *csound, const char *name, const char *value); /** * Prepend 'value' to environment variable 'name', using ';' as * separator character. * Returns CSOUND_SUCCESS on success, and CSOUND_ERROR or CSOUND_MEMORY * if the environment variable could not be set for some reason. */ int csoundPrependEnv(CSOUND *csound, const char *name, const char *value); /** * Initialise environment variable database, and copy system * environment variables. * Returns CSOUND_SUCCESS on success, and CSOUND_ERROR or * CSOUND_MEMORY in case of an error. */ int csoundInitEnv(CSOUND *csound); /** * Parse 's' as an assignment to environment variable, in the format * "NAME=VALUE" for replacing the previous value, or "NAME+=VALUE" * for appending. * Returns CSOUND_SUCCESS on success, and CSOUND_ERROR or * CSOUND_MEMORY in case of an error. */ int csoundParseEnv(CSOUND *csound, const char *s); /** Check if file name is valid, and copy with converting pathname delimiters */ char *csoundConvertPathname(CSOUND *csound, const char *filename); /** Check if name is a full pathname for the platform we are running on. */ int csoundIsNameFullpath(const char *name); /** Check if name is a relative pathname for this platform. Bare * filenames with no path information are not counted. */ int csoundIsNameRelativePath(const char *name); /** Check if name is a "leaf" (bare) filename for this platform. */ int csoundIsNameJustFilename(const char *name); /** Properly concatenates the full or relative pathname in path1 with * the relative pathname or filename in path2 according to the rules * for the platform we are running on. path1 is assumed to be * a directory whether it ends with DIRSEP or not. Relative paths must * conform to the conventions for the current platform (begin with ':' * on MacOS 9 and not begin with DIRSEP on others). */ char* csoundConcatenatePaths(CSOUND* csound, const char *path1, const char *path2); /** Converts a pathname to native format and returns just the part of * the path that specifies the directory. Does not return the final * DIRSEP. Returns an empty string if no path components occur before * the filename. Returns NULL if unable to carry out the operation * for some reason. */ char *csoundSplitDirectoryFromPath(CSOUND* csound, const char * path); /** Return just the final component of a full path */ char *csoundSplitFilenameFromPath(CSOUND* csound, const char * path); /** * Search for input file 'filename'. * If the file name specifies full path (it begins with '.', the pathname * delimiter character, or a drive letter and ':' on Windows), that exact * file name is tried without searching. * Otherwise, the file is searched relative to the current directory first, * and if it is still not found, a pathname list that is created the * following way is searched: * 1. if envList is NULL or empty, no directories are searched * 2. envList is parsed as a ';' separated list of environment variable * names, and all environment variables are expanded and expected to * contain a ';' separated list of directory names * 2. all directories in the resulting pathname list are searched, starting * from the last and towards the first one, and the directory where the * file is found first will be used * The function returns a pointer to the full name of the file if it is * found, and NULL if the file could not be found in any of the search paths, * or an error has occured. The caller is responsible for freeing the memory * pointed to by the return value, by calling mfree(). */ char *csoundFindInputFile(CSOUND *csound, const char *filename, const char *envList); /** * Search for a location to write file 'filename'. * If the file name specifies full path (it begins with '.', the pathname * delimiter character, or a drive letter and ':' on Windows), that exact * file name is tried without searching. * Otherwise, a pathname list that is created the following way is searched: * 1. if envList is NULL or empty, no directories are searched * 2. envList is parsed as a ';' separated list of environment variable * names, and all environment variables are expanded and expected to * contain a ';' separated list of directory names * 2. all directories in the resulting pathname list are searched, starting * from the last and towards the first one, and the directory that is * found first where the file can be written to will be used * Finally, if the file cannot be written to any of the directories in the * search paths, writing relative to the current directory is tried. * The function returns a pointer to the full name of the file if a location * suitable for writing the file is found, and NULL if the file cannot not be * written anywhere in the search paths, or an error has occured. * The caller is responsible for freeing the memory pointed to by the return * value, by calling mfree(). */ char *csoundFindOutputFile(CSOUND *csound, const char *filename, const char *envList); /** * Open a file and return handle. * * CSOUND *csound: * Csound instance pointer * void *fd: * pointer a variable of type int, FILE*, or SNDFILE*, depending on 'type', * for storing handle to be passed to file read/write functions * int type: * file type, one of the following: * CSFILE_FD_R: read file using low level interface (open()) * CSFILE_FD_W: write file using low level interface (open()) * CSFILE_STD: use ANSI C interface (fopen()) * CSFILE_SND_R: read sound file * CSFILE_SND_W: write sound file * const char *name: * file name * void *param: * parameters, depending on type: * CSFILE_FD_R: unused (should be NULL) * CSFILE_FD_W: unused (should be NULL) * CSFILE_STD: mode parameter (of type char*) to be passed to fopen() * CSFILE_SND_R: SF_INFO* parameter for sf_open(), with defaults for * raw file; the actual format paramaters of the opened * file will be stored in this structure * CSFILE_SND_W: SF_INFO* parameter for sf_open(), output file format * const char *env: * list of environment variables for search path (see csoundFindInputFile() * for details); if NULL, the specified name is used as it is, without any * conversion or search. * int csFileType: * A value from the enumeration CSOUND_FILETYPES (see CsoundCore.h) * int isTemporary: * 1 if this file will be deleted when Csound is finished. * Otherwise, 0. * return value: * opaque handle to the opened file, for use with csoundGetFileName() or * csoundFileClose(), or storing in FDCH.fd. * On failure, NULL is returned. */ void *csoundFileOpenWithType(CSOUND *csound, void *fd, int type, const char *name, void *param, const char *env, int csFileType, int isTemporary); /** * Allocate a file handle for an existing file already opened with open(), * fopen(), or sf_open(), for later use with csoundFileClose() or * csoundGetFileName(), or storing in an FDCH structure. * Files registered this way are also * automatically closed by csoundReset(). * Parameters and return value are similar to csoundFileOpenithType(), except * fullName is the name that will be returned by a later call to * csoundGetFileName(). */ void *csoundCreateFileHandle(CSOUND *, void *fd, int type, const char *fullName); /** * Get the full name of a file previously opened with csoundFileOpen(). */ char *csoundGetFileName(void *fd); /** * Close a file previously opened with csoundFileOpen(). */ int csoundFileClose(CSOUND *, void *fd); /** Given a file name as string, return full path of directory of file; * Note: does not check if file exists */ char *csoundGetDirectoryForPath(CSOUND* csound, const char * path); void *csoundFileOpenWithType_Async(CSOUND *csound, void *fd, int type, const char *name, void *param, const char *env, int csFileType, int buffsize, int isTemporary); unsigned int csoundReadAsync(CSOUND *csound, void *handle, MYFLT *buf, int items); unsigned int csoundWriteAsync(CSOUND *csound, void *handle, MYFLT *buf, int items); int csoundFSeekAsync(CSOUND *csound, void *handle, int pos, int whence); #ifdef __cplusplus } #endif #endif /* CSOUND_ENVVAR_H */ csound-6.10.0/H/extract.h000066400000000000000000000030571321653344700151200ustar00rootroot00000000000000/* extract.h: Copyright (C) 2013 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef EXTRACT_H #define EXTRACT_H #define INSMAX 4096 typedef struct extractStatics__ { char inslst[INSMAX]; /* values set by readxfil */ int sectno, a0done; int onsect, offsect; /* " " " */ MYFLT onbeat, offbeat; /* " " " */ MYFLT ontime, offtime; /* set by readxfil, mod by w-stmnt */ SRTBLK *frstout, *prvout; /* links for building new outlist */ SRTBLK a0; SRTBLK f0; SRTBLK e; } EXTRACT_STATICS; /* read the extract control file */ void readxfil(CSOUND *csound, EXTRACT_STATICS* extractStatics, FILE *xfp); /* extract instr events within the time period */ void extract(CSOUND *csound, EXTRACT_STATICS* extractStatics); #endif csound-6.10.0/H/fftlib.h000066400000000000000000000124701321653344700147130ustar00rootroot00000000000000/* fftlib.h: Copyright (C) 2005 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef CSOUND_FFTLIB_H #define CSOUND_FFTLIB_H #if !defined(__BUILDING_LIBCSOUND) # error "Csound plugins and host applications should not include fftlib.h" #endif #ifdef __cplusplus extern "C" { #endif /** * Returns the amplitude scale that should be applied to the result of * an inverse complex FFT with a length of 'FFTsize' samples. */ MYFLT csoundGetInverseComplexFFTScale(CSOUND *csound, int FFTsize); /** * Returns the amplitude scale that should be applied to the result of * an inverse real FFT with a length of 'FFTsize' samples. */ MYFLT csoundGetInverseRealFFTScale(CSOUND *csound, int FFTsize); /** * Compute in-place complex FFT * FFTsize: FFT length in samples * buf: array of FFTsize*2 MYFLT values, * in interleaved real/imaginary format */ void csoundComplexFFT(CSOUND *csound, MYFLT *buf, int FFTsize); /** * Compute in-place inverse complex FFT * FFTsize: FFT length in samples * buf: array of FFTsize*2 MYFLT values, * in interleaved real/imaginary format * Output should be scaled by the return value of * csoundGetInverseComplexFFTScale(csound, FFTsize). */ void csoundInverseComplexFFT(CSOUND *csound, MYFLT *buf, int FFTsize); /** * Compute in-place real FFT * FFTsize: FFT length in samples * buf: array of FFTsize MYFLT values; output is in interleaved * real/imaginary format, except for buf[1] which is the real * part for the Nyquist frequency */ void csoundRealFFT(CSOUND *csound, MYFLT *buf, int FFTsize); /** * Compute in-place inverse real FFT * FFTsize: FFT length in samples * buf: array of FFTsize MYFLT values; input is expected to be in * interleaved real/imaginary format, except for buf[1] which * is the real part for the Nyquist frequency * Output should be scaled by the return value of * csoundGetInverseRealFFTScale(csound, FFTsize). */ void csoundInverseRealFFT(CSOUND *csound, MYFLT *buf, int FFTsize); /** * Multiply two arrays (buf1 and buf2) of complex data in the format * returned by csoundRealFFT(), and leave the result in outbuf, which * may be the same as either buf1 or buf2. * An amplitude scale of 'scaleFac' is also applied. * The arrays should contain 'FFTsize' MYFLT values. */ void csoundRealFFTMult(CSOUND *csound, MYFLT *outbuf, MYFLT *buf1, MYFLT *buf2, int FFTsize, MYFLT scaleFac); /** * Compute in-place real FFT, allowing non power of two FFT sizes. * * buf: array of FFTsize + 2 MYFLT values; output is in interleaved * real/imaginary format (note: the real part of the Nyquist * frequency is stored in buf[FFTsize], and not in buf[1]). * FFTsize: FFT length in samples; not required to be an integer power of two, * but should be even and not have too many factors. */ void csoundRealFFTnp2(CSOUND *csound, MYFLT *buf, int FFTsize); /** * Compute in-place inverse real FFT, allowing non power of two FFT sizes. * The output does not need to be scaled. * * buf: array of FFTsize + 2 MYFLT values, in interleaved real/imaginary * format (note: the real part of the Nyquist frequency is stored * in buf[FFTsize], and not in buf[1]). * FFTsize: FFT length in samples; not required to be an integer power of two, * but should be even and not have too many factors. */ void csoundInverseRealFFTnp2(CSOUND *csound, MYFLT *buf, int FFTsize); /** * New Real FFT interface * Creates a setup for a series of FFT operations. * * FFTsize: FFT length in samples; not required to be an integer power of two, * but should be even and not have too many factors. * d: direction (FFT_FWD or FFT_INV). Scaling by 1/FFTsize is done on * the inverse direction (as with the other RealFFT functions above). * * returns: a pointer to the FFT setup. */ void *csoundRealFFT2Setup(CSOUND *csound, int FFTsize, int d); /** * New Real FFT interface * Compute in-place real FFT. * * buf: array of FFTsize + 2 MYFLT values, in interleaved real/imaginary * format (note: the real part of the Nyquist frequency is stored * in buf[FFTsize], and not in buf[1]). * setup: an FFT setup created with csoundRealFFT2Setup() */ void csoundRealFFT2(CSOUND *csound, void *setup, MYFLT *sig); #ifdef __cplusplus } #endif #endif /* CSOUND_FFTLIB_H */ csound-6.10.0/H/fgens.h000066400000000000000000000032301321653344700145410ustar00rootroot00000000000000/* fgens.h: Copyright (C) 1991 Barry Vercoe This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* FGENS.H */ #ifndef CSOUND_FGENS_H #define CSOUND_FGENS_H #define MAXFNUM 100 #define GENMAX 60 /** * Create ftable using evtblk data, and store pointer to new table in *ftpp. * If mode is zero, a zero table number is ignored, otherwise a new table * number is automatically assigned. * Returns zero on success. */ int hfgens(CSOUND *csound, FUNC **ftpp, const EVTBLK *evtblkp, int mode); /** * Allocates space for 'tableNum' with a length (not including the guard * point) of 'len' samples. The table data is not cleared to zero. * Return value is zero on success. */ int csoundFTAlloc(CSOUND *csound, int tableNum, int len); /** * Deletes a function table. * Return value is zero on success. */ int csoundFTDelete(CSOUND *csound, int tableNum); #endif /* CSOUND_FGENS_H */ csound-6.10.0/H/find_opcode.h000066400000000000000000000023551321653344700157170ustar00rootroot00000000000000/* find_opcode.h: Copyright (C) 2016 by John ffitc This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ char* get_opcode_short_name(CSOUND* csound, char* opname); PUBLIC OENTRY* find_opcode_new(CSOUND* csound, char* opname, char* outArgsFound, char* inArgsFound); PUBLIC OENTRY* find_opcode_exact(CSOUND* csound, char* opname, char* outArgsFound, char* inArgsFound); /* find OENTRY with the specified name in opcode list */ OENTRY* find_opcode(CSOUND *, char *); csound-6.10.0/H/insert.h000066400000000000000000000063501321653344700147510ustar00rootroot00000000000000/* insert.h: Copyright (C) 1991, 2002 Barry Vercoe, Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ typedef struct { /* INSERT.H */ OPDS h; LBLBLK *lblblk; } GOTO; typedef struct { OPDS h; int *cond; LBLBLK *lblblk; } CGOTO; typedef struct { OPDS h; MYFLT *ndxvar, *incr, *limit; LBLBLK *l; } LOOP_OPS; typedef struct { OPDS h; MYFLT *idel, *idur; LBLBLK *lblblk; int32 cnt1, cnt2; } TIMOUT; typedef struct { OPDS h; } LINK; typedef struct { OPDS h; MYFLT *inst; } KILLOP; /* the number of optional outputs defined in entry.c */ #define SUBINSTNUMOUTS 8 typedef struct { OPCODINFO *opcode_info; void *uopcode_struct; INSDS *parent_ip; MYFLT *iobufp_ptrs[12]; /* expandable IV - Oct 26 2002 */ /* was 8 */ } OPCOD_IOBUFS; typedef struct { /* IV - Oct 16 2002 */ OPDS h; MYFLT *ar[VARGMAX]; INSDS *ip, *parent_ip; AUXCH saved_spout; OPCOD_IOBUFS buf; } SUBINST; typedef struct { /* IV - Sep 8 2002: new structure: UOPCODE */ OPDS h; INSDS *ip, *parent_ip; OPCOD_IOBUFS *buf; /*unsigned int l_ksmps; int ksmps_scale; MYFLT l_ekr, l_onedkr, l_onedksmps, l_kicvt; int mode;*/ /* special case: the argument list is stored at the end of the */ /* opcode data structure */ MYFLT *ar[1]; } UOPCODE; /* IV - Sep 8 2002: added opcodes: xin, xout, and setksmps */ typedef struct { OPDS h; MYFLT *args[1]; } XIN; typedef struct { OPDS h; MYFLT *args[OPCODENUMOUTS_LOW]; } XIN_LOW; typedef struct { OPDS h; MYFLT *args[OPCODENUMOUTS_HIGH]; } XIN_HIGH; typedef struct { OPDS h; MYFLT *args[OPCODENUMOUTS_MAX]; } XIN_MAX; typedef struct { OPDS h; MYFLT *args[1]; } XOUT; typedef struct { OPDS h; MYFLT *args[OPCODENUMOUTS_LOW]; } XOUT_LOW; typedef struct { OPDS h; MYFLT *args[OPCODENUMOUTS_HIGH]; } XOUT_HIGH; typedef struct { OPDS h; MYFLT *args[OPCODENUMOUTS_MAX]; } XOUT_MAX; typedef struct { OPDS h; MYFLT *i_ksmps; } SETKSMPS; typedef struct { /* IV - Oct 20 2002 */ OPDS h; MYFLT *i_insno, *iname; } NSTRNUM; typedef struct { OPDS h; MYFLT *kInsNo, *kFlags, *kRelease; } TURNOFF2; typedef struct { OPDS h; MYFLT *insno; } DELETEIN; csound-6.10.0/H/linevent.h000066400000000000000000000025711321653344700152720ustar00rootroot00000000000000/* linevent.h: Copyright (C) 2001 matt ingalls This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef CSOUND_LINEVENT_H #define CSOUND_LINEVENT_H /*****************************************************************/ /* linevent */ /* Dec 2001 by matt ingalls */ /*****************************************************************/ typedef struct { OPDS h; MYFLT *args[VARGMAX]; int argno; int flag; } LINEVENT; typedef struct { OPDS h; MYFLT *inst; MYFLT *args[VARGMAX]; int argno; } LINEVENT2; #endif /* CSOUND_LINEVENT_H */ csound-6.10.0/H/lpc.h000066400000000000000000000025161321653344700142230ustar00rootroot00000000000000/* lpc.h: Copyright (C) 1992 Barry Vercoe This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* LPC.H */ #define LP_MAGIC 999 #define LP_MAGIC2 2399 /* pole file type */ #define LPBUFSIZ 4096 /* in lpanal */ #define MAXWINDIN 1000 /* was for 10ms hops at 50 KC */ #define MAXPOLES 5000 #define NDATA 4 /* number of data values stored with frame */ typedef struct { uint32_t headersize, lpmagic, npoles, nvals; MYFLT framrate, srate, duration; char text[4]; } LPHEADER; csound-6.10.0/H/midifile.h000066400000000000000000000031561321653344700152300ustar00rootroot00000000000000/* midifile.h: Copyright (C) 2005 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef CSOUND_MIDIFILE_H #define CSOUND_MIDIFILE_H #ifdef __cplusplus extern "C" { #endif /* open MIDI file, read all tracks, and create event list */ int csoundMIDIFileOpen(CSOUND *csound, const char *name); /* read MIDI file event data at performace time */ int csoundMIDIFileRead(CSOUND *csound, unsigned char *buf, int nBytes); /* destroy MIDI file event list */ int csoundMIDIFileClose(CSOUND *csound); /* ------------------------------------------------------------------------ */ typedef struct { OPDS h; MYFLT *kResult; } MIDITEMPO; /* miditempo opcode: returns the current tempo of MIDI file */ extern int midiTempoOpcode(CSOUND *csound, MIDITEMPO *p); extern int midiFileStatus(CSOUND *csound, MIDITEMPO *p); #ifdef __cplusplus } #endif #endif /* CSOUND_MIDIFILE_H */ csound-6.10.0/H/midiinterop.h000066400000000000000000000142411321653344700157660ustar00rootroot00000000000000/* midiinterop.h: Copyright (C) 2002 Michael Gogins This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef MIDIINTEROP_H #define MIDIINTEROP_H #include "csoundCore.h" /* MIDI INTEROPERABILITY OPCODES midinoteoff xkey, xvelocity midinoteonkey xkey, xvelocity midinoteoncps xcps, xvelocity midinoteonoct xoct, xvelocity midinoteonpch xpch, xvelocity midipolyaftertouch xpolyaftertouch, xcontrollervalue [, olow, hhigh] midicontrolchange, xcontroller, xcontrollervalue [, olow, hhigh] midiprogramchange xprogram midichannelaftertouch xchannelaftertouch [, olow, hhigh] midipitchbend xpitchbend [, olow, hhigh] mididefault xdefault, xvalue Description These opcodes are designed to simplify writing instruments that can be used interchangeably for either score or MIDI input, and to make it easier to adapt instruments originally written for score input to work with MIDI input. In general, it should be possible to write instrument definitions that work identically with both scores and MIDI, including both MIDI files and real-time MIDI input, without using any conditional statements, and that take full advantage of MIDI voice messages. Note that correlating Csound instruments with MIDI channel numbers is done using the massign opcode for real-time performance. For file-driven performance, instrument numbers default to MIDI channel number + 1, but the defaults are overridden by any MIDI program change messages in the file. Initialization xkey - returns MIDI key during MIDI activation, remains unchanged otherwise kcps - returns MIDI key translated to cycles per second during MIDI activation, remains unchanged otherwise xoct - returns MIDI key translated to linear octaves during MIDI activation, remains unchanged otherwise xpch - returns MIDI key translated to octave.pch during MIDI activation, remains unchanged otherwise xvelocity - returns MIDI velocity during MIDI activation, remains unchanged otherwise xpolyaftertouch - returns MIDI polyphonic aftertouch during MIDI activation, remains unchanged otherwise xcontroller - specifies a MIDI controller number xcontrollervalue - returns the value of the MIDI controller during MIDI activation, remains unchanged otherwise xprogram - returns the MIDI program change value during MIDI activation, remains unchanged otherwise xchannelaftertouch - returns the MIDI channel aftertouch during MIDI activation, remains unchanged otherwise xpitchbend - returns the MIDI pitch bend during MIDI activation, remains unchanged otherwise xdefault - specifies a default value that will be used during MIDI activation xvalue - overwritten by xdefault during MIDI activation, remains unchanged otherwise olow - optional low value after rescaling, defaults to 0. hhigh - optional high value after rescaling, defaults to 127. Performance for the first 10 opcodes, if the instrument was activated by MIDI input, the opcode overwrites the value of the "x" input variable(s) with the corresponding value from MIDI input. If the instrument was NOT activated by MIDI input, the value of the "x" input variable(s) remains unchanged. This enables score pfields to receive MIDI input data during MIDI activation, and score values otherwise. For the mididefault opcode, if the instrument was activated by MIDI input, the opcode will overwrite the value of xvalue with the value of xdefault. If the instrument was NOT activated by MIDI input, xvalue will remain unchanged. This enables score pfields to receive a default value during MIDI activation, and score values otherwise. To adapt an ordinary Csound instrument designed for score activation for score/MIDI interoperability: 1. Change all linen, linseg, and expseg opcodes to linenr, linsegr, and expsegr, respectively. This will not materially change score-driven performance. 2. Add the following lines at the beginning of the instrument definition: mididefault 60, p3 ; Ensures that a MIDI-activated instrument will have a positive p3 field. midinoteoncps p4, p5 ; Puts MIDI key translated to cycles per second into p4, and MIDI velocity into p5 Obviously, midinoteoncps could be changed to midinoteonoct or any of the other options, and the choice of pfields is arbitrary. Author: Michael Gogins gogins@pipeline.com */ typedef struct MIDINOTEON_ { OPDS h; MYFLT *xkey; MYFLT *xvelocity; } MIDINOTEON; typedef struct MIDIPOLYAFTERTOUCH_ { OPDS h; MYFLT *xpolyaftertouch; MYFLT *xcontroller; MYFLT *olow; MYFLT *hhigh; } MIDIPOLYAFTERTOUCH; typedef struct MIDICONTROLCHANGE_ { OPDS h; MYFLT *xcontroller; MYFLT *xcontrollervalue; MYFLT *olow; MYFLT *hhigh; } MIDICONTROLCHANGE; typedef struct MIDIPROGRAMCHANGE_ { OPDS h; MYFLT *xprogram; } MIDIPROGRAMCHANGE; typedef struct MIDICHANNELAFTERTOUCH_ { OPDS h; MYFLT *xchannelaftertouch; MYFLT *olow; MYFLT *hhigh; } MIDICHANNELAFTERTOUCH; typedef struct MIDIPITCHBEND_ { OPDS h; MYFLT *xpitchbend; MYFLT *olow; MYFLT *hhigh; } MIDIPITCHBEND; typedef struct MIDIDEFAULT_ { OPDS h; MYFLT *xdefault; MYFLT *xvalue; } MIDIDEFAULT; #endif csound-6.10.0/H/midioops.h000066400000000000000000000024241321653344700152660ustar00rootroot00000000000000/* midioops.h: Copyright (C) 1997 John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* midioops.h */ /* John ffitch -- August 1997 */ /* ********************************************************************** * Defines etc for the basic MIDI output codes * **********************************************************************/ #define MD_NOTEOFF (0x80) #define MD_NOTEON (0x90) #define MD_POLYAFTER (0xa0) #define MD_CNTRLCHG (0xb0) #define MD_PGMCHG (0xc0) #define MD_CHANPRESS (0xd0) #define MD_PTCHBENDCHG (0xe0) csound-6.10.0/H/midiops.h000066400000000000000000000074041321653344700151120ustar00rootroot00000000000000/* midiops.h: Copyright (C) 1995 Barry Vercoe, Gabriel maldonado, Istvan Varga, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* MIDIOPS.H */ #ifndef MIDIOPS_H #define MIDIOPS_H #define NOTEOFF_TYPE 0x80 #define NOTEON_TYPE 0x90 #define POLYAFT_TYPE 0xA0 #define CONTROL_TYPE 0xB0 #define PROGRAM_TYPE 0xC0 #define AFTOUCH_TYPE 0xD0 #define PCHBEND_TYPE 0xE0 #define SYSTEM_TYPE 0xF0 #define DATENTRY 6 #define VOLUME 7 #define SUSTAIN_SW 64 #define NRPNLSB 98 #define NRPNMSB 99 #define RPNLSB 100 #define RPNMSB 101 #define VIB_RATE 128 /* ROLAND EXTENDED CTRLS */ #define VIB_DEPTH 129 /* in unused ctl_val spc */ #define VIB_DELAY 130 #define TVF_CUTOFF 131 #define TVF_RESON 132 #define TVA_RIS 133 #define TVA_DEC 134 #define TVA_RLS 135 typedef struct { OPDS h; MYFLT *chnl; STRINGDAT *insno; MYFLT *iresetctls; } MASSIGNS; typedef struct { OPDS h; MYFLT *chnl; MYFLT *insno; MYFLT *iresetctls; } MASSIGN; typedef struct { OPDS h; MYFLT *chnl, *ctrls[64]; } CTLINIT; typedef struct { OPDS h; MYFLT *r, *imax, *ifn; } MIDIAMP; typedef struct { OPDS h; MYFLT *r, *ictlno, *ilo, *ihi; int32 ctlno; MYFLT scale, lo; } MIDICTL; typedef struct { OPDS h; MYFLT *r, *ichano, *ictlno, *ilo, *ihi; int32 chano, ctlno; MYFLT scale, lo; } CHANCTL; typedef struct { OPDS h; MYFLT *r, *iscal; MYFLT scale, prvbend, prvout; } MIDIKMB; typedef struct { OPDS h; MYFLT *r, *ilo, *ihi; } MIDIMAP; typedef struct { OPDS h; MYFLT *r, *ilo, *ihi; MYFLT scale, lo; } MIDIKMAP; typedef struct { OPDS h; MYFLT *olap; } MIDIOLAP; typedef struct { OPDS h; MYFLT *r; } MIDIAGE; typedef struct { OPDS h; MYFLT *r, *tablenum; /* *numgrades, *interval, *basefreq, *basekeymidi; */ } CPSTABLE; typedef struct { OPDS h; MYFLT *ans; } GTEMPO; typedef struct { OPDS h; MYFLT *ichn; } MIDICHN; typedef struct { OPDS h; MYFLT *ipgm, *inst, *ichn; } PGMASSIGN; typedef struct { OPDS h; MYFLT *status, *chan, *data1, *data2; int local_buf_index; /* IV - Nov 30 2002 */ } MIDIIN; typedef struct { OPDS h; MYFLT *pgm, *chn, *ochan; int local_buf_index; /* IV - Nov 30 2002 */ int watch; } PGMIN; typedef struct { OPDS h; MYFLT *data, *numb, *chn, *ochan, *onum; int local_buf_index; /* IV - Nov 30 2002 */ int watch1, watch2; } CTLIN; typedef struct { OPDS h; MYFLT *noteOut, *counter; MYFLT *arpRate, *arpMode; int metroTick; double curphs; int flag; int status, chan, data1, data2, noteCnt, noteIndex, maxNumNotes, direction; int notes[10]; int sortedNotes[10]; int local_buf_index; } MIDIARP; #endif csound-6.10.0/H/midiout.h000066400000000000000000000071361321653344700151220ustar00rootroot00000000000000/* midiout.h: Copyright (C) 1997 Gabriel Maldonado, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /****************************************/ /** midiout UGs by Gabriel Maldonado **/ /****************************************/ typedef int BOOL; #ifndef TRUE # define TRUE (1) #endif #ifndef FALSE # define FALSE (0) #endif typedef struct { OPDS h; MYFLT *r; } REL; typedef struct { OPDS h; MYFLT *extradur; } XTRADUR; typedef struct { OPDS h; MYFLT *freq; MYFLT period, clock_tics; int beginning_flag; } MCLOCK; typedef struct { OPDS h; MYFLT *message; } MRT; typedef struct { OPDS h; MYFLT *ichn,*inum,*ivel; } OUT_ON; typedef struct { OPDS h; MYFLT *ichn,*inum,*ivel,*idur; MYFLT istart_time; int chn, num, vel; BOOL fl_expired, fl_extra_dur; } OUT_ON_DUR; typedef struct { OPDS h; MYFLT *kchn,*knum,*kvel,*kdur,*kpause; MYFLT istart_time; int last_chn, last_num, last_vel; MYFLT last_dur, last_pause; BOOL fl_note_expired, fl_first_note, fl_end_note; } MOSCIL; typedef struct { OPDS h; MYFLT *kchn,*knum,*kvel; int last_chn, last_num, last_vel; BOOL fl_note_expired, fl_first_note; } KOUT_ON; typedef struct { OPDS h; MYFLT *chn,*num, *value, *min, *max; int last_value, lastchn, lastctrl; } OUT_CONTR; typedef struct { OPDS h; MYFLT *chn, *msb_num, *lsb_num, *value, *min, *max; int last_value, lastchn, lastctrl; } OUT_CONTR14; typedef struct { OPDS h; MYFLT *chn, *value, *min, *max; int last_value, lastchn; } OUT_PB; typedef struct { OPDS h; MYFLT *chn, *value, *min, *max; int last_value, lastchn; } OUT_ATOUCH; typedef struct { OPDS h; MYFLT *chn, *prog_num, *min, *max; int last_prog_num, lastchn; } OUT_PCHG; typedef struct { OPDS h; MYFLT *chn, *num, *value, *min, *max; int last_value, lastchn, lastctrl; } OUT_POLYATOUCH; typedef struct { OPDS h; MYFLT *kchn,*knum,*kvel,*ktrig; int last_chn, last_num, last_vel; BOOL fl_note_expired/*, fl_first_note*/; } KON2; typedef struct { OPDS h; MYFLT *in_type, *in_chan, *in_dat1, *in_dat2; } MIDIOUT; typedef struct { OPDS h; MYFLT *chan, *parm_num, *parm_value; int old_chan, old_parm, old_value; } NRPN; typedef struct { unsigned char status; unsigned char dat1; unsigned char dat2; MYFLT delay; } DELTAB; #define DELTAB_LENGTH 1000 typedef struct { OPDS h; MYFLT *in_status, *in_chan, *in_dat1, *in_dat2, *kdelay; unsigned char status[DELTAB_LENGTH]; unsigned char chan[DELTAB_LENGTH]; unsigned char dat1[DELTAB_LENGTH]; unsigned char dat2[DELTAB_LENGTH]; MYFLT time[DELTAB_LENGTH]; unsigned int write_index, read_index; } MDELAY; csound-6.10.0/H/mp3dec.h000066400000000000000000000036031321653344700146160ustar00rootroot00000000000000/* * mpadec - MPEG audio decoder * Copyright (C) 2002-2004 Dmitriy Startsev (dstartsev@rambler.ru) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* $Id$ */ #ifndef __MP3DEC_H #define __MP3DEC_H #include #include "mpadec.h" #define MP3DEC_RETCODE_OK 0 #define MP3DEC_RETCODE_INVALID_HANDLE 1 #define MP3DEC_RETCODE_BAD_STATE 2 #define MP3DEC_RETCODE_INVALID_PARAMETERS 3 #define MP3DEC_RETCODE_NOT_MPEG_STREAM 4 #define MP3DEC_RETCODE_SEEK_FAILED 5 #define MP3DEC_RETCODE_UNKNOWN 6 #define MP3DEC_SEEK_BYTES 0 #define MP3DEC_SEEK_SAMPLES 1 #define MP3DEC_SEEK_SECONDS 2 typedef void *mp3dec_t; #ifdef __cplusplus extern "C" { #endif mp3dec_t mp3dec_init(void); int mp3dec_init_file(mp3dec_t mp3dec, int fd, int64_t length, int nogap); int mp3dec_uninit(mp3dec_t mp3dec); int mp3dec_reset(mp3dec_t mp3dec); int mp3dec_configure(mp3dec_t mp3dec, mpadec_config_t *cfg); int mp3dec_get_info(mp3dec_t mp3dec, void *info, int info_type); int mp3dec_decode(mp3dec_t mp3dec, uint8_t *buf, uint32_t bufsize, uint32_t *used); int mp3dec_seek(mp3dec_t mp3dec, int64_t pos, int units); char *mp3dec_error(int code); #ifdef __cplusplus } #endif #endif csound-6.10.0/H/mp3dec_internal.h000066400000000000000000000027021321653344700165110ustar00rootroot00000000000000/* * mpadec - MPEG audio decoder * Copyright (C) 2002-2004 Dmitriy Startsev (dstartsev@rambler.ru) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* $Id: mp3dec_internal.h,v 1.2 2004/08/02 09:38:09 metal_man Exp $ */ #ifndef __MP3DEC_INTERNAL_H #define __MP3DEC_INTERNAL_H #include "mp3dec.h" #define MP3DEC_FLAG_INITIALIZED 1 #define MP3DEC_FLAG_SEEKABLE 2 struct mp3dec_t { uint32_t size; mpadec_t mpadec; int32_t fd; uint32_t flags; int64_t stream_offset; int64_t stream_size; int64_t stream_position; mpadec_info_t mpainfo; mp3tag_info_t taginfo; uint32_t in_buffer_offset; uint32_t in_buffer_used; uint32_t out_buffer_offset; uint32_t out_buffer_used; uint8_t in_buffer[0x10000]; uint8_t out_buffer[8*1152]; }; #endif csound-6.10.0/H/mpadec.h000066400000000000000000000074251321653344700147020ustar00rootroot00000000000000/* * mpadec - MPEG audio decoder * Copyright (C) 2002-2004 Dmitriy Startsev (dstartsev@rambler.ru) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* $Id$ */ #ifndef __MPADEC_H #define __MPADEC_H #undef FALSE #undef TRUE #define FALSE 0 #define TRUE 1 #define MPADEC_VERSION 0x0900 #define MPADEC_RETCODE_OK 0 #define MPADEC_RETCODE_INVALID_HANDLE 1 #define MPADEC_RETCODE_NOT_ENOUGH_MEMORY 2 #define MPADEC_RETCODE_BAD_STATE 3 #define MPADEC_RETCODE_INVALID_PARAMETERS 4 #define MPADEC_RETCODE_NEED_MORE_DATA 5 #define MPADEC_RETCODE_BUFFER_TOO_SMALL 6 #define MPADEC_RETCODE_NO_SYNC 7 #define MPADEC_RETCODE_UNKNOWN 8 #define MPADEC_CONFIG_FULL_QUALITY 0 #define MPADEC_CONFIG_HALF_QUALITY 1 #define MPADEC_CONFIG_AUTO 0 #define MPADEC_CONFIG_MONO 1 #define MPADEC_CONFIG_STEREO 2 #define MPADEC_CONFIG_CHANNEL1 3 #define MPADEC_CONFIG_CHANNEL2 4 #define MPADEC_CONFIG_16BIT 0 #define MPADEC_CONFIG_24BIT 1 #define MPADEC_CONFIG_32BIT 2 #define MPADEC_CONFIG_FLOAT 3 #define MPADEC_CONFIG_LITTLE_ENDIAN 0 #define MPADEC_CONFIG_BIG_ENDIAN 1 #define MPADEC_CONFIG_REPLAYGAIN_NONE 0 #define MPADEC_CONFIG_REPLAYGAIN_RADIO 1 #define MPADEC_CONFIG_REPLAYGAIN_AUDIOPHILE 2 #define MPADEC_CONFIG_REPLAYGAIN_CUSTOM 3 #define MPADEC_INFO_STREAM 0 #define MPADEC_INFO_TAG 1 #define MPADEC_INFO_CONFIG 2 typedef struct { uint8_t quality; uint8_t mode; uint8_t format; uint8_t endian; uint8_t replaygain; uint8_t skip; uint8_t crc; uint8_t dblsync; float gain; } mpadec_config_t; typedef struct { int32_t layer; int32_t channels; int32_t frequency; int32_t bitrate; uint8_t mode; uint8_t copyright; uint8_t original; uint8_t emphasis; int32_t frames; int32_t frame_size; int32_t frame_samples; int32_t decoded_channels; int32_t decoded_frequency; int32_t decoded_sample_size; int32_t decoded_frame_samples; int32_t duration; } mpadec_info_t; typedef struct { uint32_t flags; uint32_t frames; uint32_t bytes; uint8_t toc[100]; int32_t replay_gain[2]; int32_t enc_delay; int32_t enc_padding; } mp3tag_info_t; typedef void *mpadec_t; typedef void *mpadec2_t; #ifdef __cplusplus extern "C" { #endif mpadec_t mpadec_init(void); int mpadec_uninit(mpadec_t mpadec); int mpadec_reset(mpadec_t mpadec); int mpadec_configure(mpadec_t mpadec, mpadec_config_t *cfg); int mpadec_get_info(mpadec_t mpadec, void *info, int info_type); int mpadec_decode(mpadec_t mpadec, uint8_t *srcbuf, uint32_t srcsize, uint8_t *dstbuf, uint32_t dstsize, uint32_t *srcused, uint32_t *dstused); char *mpadec_error(int code); mpadec2_t mpadec2_init(void); int mpadec2_uninit(mpadec2_t mpadec); int mpadec2_reset(mpadec2_t mpadec); int mpadec2_configure(mpadec2_t mpadec, mpadec_config_t *cfg); int mpadec2_get_info(mpadec2_t mpadec, void *info, int info_type); int mpadec2_decode(mpadec2_t mpadec, uint8_t *srcbuf, uint32_t srcsize, uint8_t *dstbuf, uint32_t dstsize, uint32_t *dstused); #define mpadec2_error(x) mpadec_error(x) #ifdef __cplusplus } #endif #endif csound-6.10.0/H/mpadec_internal.h000066400000000000000000000120611321653344700165660ustar00rootroot00000000000000/* * mpadec - MPEG audio decoder * Copyright (C) 2002-2004 Dmitriy Startsev (dstartsev@rambler.ru) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* $Id: mpadec_internal.h,v 1.1.1.1 2004/07/27 02:57:55 metal_man Exp $ */ #ifndef __MPADEC_INTERNAL_H #define __MPADEC_INTERNAL_H #include "csoundCore.h" #include "mpadec.h" #define MPADEC_STATE_UNDEFINED 0 #define MPADEC_STATE_START 1 #define MPADEC_STATE_DECODE 2 #define MPG_MD_STEREO 0 #define MPG_MD_JOINT_STEREO 1 #define MPG_MD_DUAL_CHANNEL 2 #define MPG_MD_MONO 3 #define SBLIMIT 32 #define SSLIMIT 18 #define SCALE_BLOCK 12 typedef struct { MYFLT decwin[512 + 32]; MYFLT muls[27][64]; MYFLT gainpow2[256 + 122]; MYFLT ispow[8207]; MYFLT win[2][4][36]; MYFLT *istabs[3][2][2]; MYFLT tan1_1[16]; MYFLT tan2_1[16]; MYFLT tan1_2[16]; MYFLT tan2_2[16]; MYFLT pow1_1[2][16]; MYFLT pow2_1[2][16]; MYFLT pow1_2[2][16]; MYFLT pow2_2[2][16]; int32_t long_limit[9][23]; int32_t short_limit[9][14]; int32_t n_slen2[512]; int32_t i_slen2[256]; int32_t mapbuf0[9][152]; int32_t mapbuf1[9][156]; int32_t mapbuf2[9][44]; int32_t *map[9][3]; int32_t *mapend[9][3]; uint8_t *mp2tables[10]; uint8_t grp3tab[32*3]; uint8_t grp5tab[128*3]; uint8_t grp9tab[1024*3]; } mpadec_tables_t; typedef struct { uint16_t bits; int16_t d; } alloc_table_t; typedef struct { uint32_t linbits; int16_t *table; } newhuff_t; typedef struct { int16_t long_idx[23]; int16_t long_diff[22]; int16_t short_idx[14]; int16_t short_diff[13]; } bandinfo_t; typedef struct { uint8_t layer; uint8_t mode; uint8_t channels; uint8_t decoded_channels; uint8_t LSF; uint8_t MPEG25; uint8_t CRC; uint8_t extension; uint8_t mode_ext; uint8_t copyright; uint8_t original; uint8_t emphasis; uint8_t jsbound; uint8_t sblimit; uint8_t downsample; uint8_t downsample_sblimit; uint16_t crc; uint16_t rsvd; uint32_t padding; uint32_t bitrate_index; uint32_t frequency_index; uint32_t bitrate; uint32_t frequency; uint32_t frame_size; uint32_t frame_samples; uint32_t decoded_frequency; uint32_t decoded_samples; uint32_t decoded_size; alloc_table_t *alloc_table; } frameinfo_t; typedef struct { int32_t scfsi; uint32_t part2_3_length; uint32_t big_values; uint32_t scalefac_compress; uint8_t block_type; uint8_t mixed_block_flag; uint8_t preflag; uint8_t scalefac_scale; uint32_t table_select[3]; uint32_t subblock_gain[3]; uint32_t maxband[3]; uint32_t maxbandl; uint32_t maxb; uint32_t region1start; uint32_t region2start; uint32_t count1table_select; MYFLT *full_gain[3]; MYFLT *pow2gain; } grinfo_t; typedef struct { uint32_t main_data_begin; uint32_t private_bits; struct { grinfo_t gr[2]; } ch[2]; } sideinfo_t; struct mpadec_t { uint32_t size; uint32_t state; uint8_t *next_byte; uint32_t bytes_left; uint32_t bit_buffer; uint8_t bits_left; uint8_t error; uint8_t free_format; uint8_t pad1; uint32_t sample_size; uint32_t prev_frame_size; uint32_t header; uint32_t hsize; uint32_t ssize; uint32_t dsize; uint16_t crc; uint16_t pad2; uint32_t skip_samples; uint32_t padding_samples; uint32_t padding_start; uint32_t decoded_frames; uint32_t decoded_samples; mp3tag_info_t tag_info; uint32_t synth_size; MYFLT replay_gain; void (*synth_func)(void *mpadec, MYFLT block[SBLIMIT], int channel, uint8_t *buffer); uint32_t reservoir_size; uint8_t reservoir[2048]; frameinfo_t frame; sideinfo_t sideinfo; mpadec_config_t config; mpadec_tables_t tables; uint32_t synth_bufoffs; uint8_t hybrid_block[4]; MYFLT hybrid_in[2][SBLIMIT+1][SSLIMIT]; MYFLT hybrid_out[2][SSLIMIT+1][SBLIMIT]; MYFLT hybrid_buffers[2][2][SBLIMIT*SSLIMIT+SBLIMIT+SSLIMIT]; MYFLT synth_buffers[2][2][0x110]; }; struct mpabuffer_t { uint32_t size; uint32_t offset; uint32_t used; uint8_t *buffer; struct mpabuffer_t *next; }; struct mpadec2_t { uint32_t size; mpadec_t mpadec; struct mpabuffer_t *buffers; uint32_t in_buffer_offset; uint32_t in_buffer_used; uint32_t out_buffer_offset; uint32_t out_buffer_used; uint8_t in_buffer[0x10000]; uint8_t out_buffer[8*1152]; }; #define GETBITS(n) ((mpa->bits_left >= \ (uint8_t)(n)) ? ((mpa->bit_buffer >> (mpa->bits_left -= (uint8_t)(n))) \ & bitmask[n]) : getbits(mpa, n)) #endif csound-6.10.0/H/namedins.h000066400000000000000000000112201321653344700152330ustar00rootroot00000000000000/* namedins.h: Copyright (C) 2002 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* namedins.h -- written by Istvan Varga, Oct 2002 */ #ifndef CSOUND_NAMEDINS_H #define CSOUND_NAMEDINS_H #include "csoundCore.h" /* for INSTRTXT */ #ifdef __cplusplus extern "C" { #endif /* check if the string s is a valid instrument or opcode name */ /* return value is zero if the string is not a valid name */ int check_instr_name(char *); /* find the instrument number for the specified name */ /* return value is zero if none was found */ int32 named_instr_find(CSOUND *, char *); /* convert opcode string argument to instrument number */ /* return value is -1 if the instrument cannot be found */ /* (in such cases, csoundInitError() is also called) */ int32 strarg2insno(CSOUND *, void *, int); /* same as strarg2insno, but runs at perf time, */ /* and does not support numbered instruments */ /* (used by opcodes like event or schedkwhen) */ int32 strarg2insno_p(CSOUND *, char *); /* convert opcode string argument to instrument number */ /* (also allows user defined opcode names); if the integer */ /* argument is non-zero, only opcode names are searched */ /* return value is -1 if the instrument cannot be found */ /* (in such cases, csoundInitError() is also called) */ int32 strarg2opcno(CSOUND *, void *, int, int); /* create file name from opcode argument (string or MYFLT) */ /* CSOUND *csound: */ /* pointer to Csound instance */ /* char *s: */ /* output buffer, should have enough space; if NULL, the */ /* required amount of memory is allocated and returned */ /* void *p: */ /* opcode argument, is interpreted as char* or MYFLT*, */ /* depending on the 'is_string' parameter */ /* const char *baseName: */ /* name prefix to be used if the 'p' argument is MYFLT, */ /* and it is neither SSTRCOD, nor a valid index to strset */ /* space. */ /* For example, if "soundin." is passed as baseName, file */ /* names in the format "soundin.%d" will be generated. */ /* baseName may be an empty string, but should not be NULL */ /* int is_string: */ /* if non-zero, 'p' is interpreted as a char* pointer and */ /* is used as the file name. Otherwise, it is expected to */ /* point to a MYFLT value, and the following are tried: */ /* 1. if the value is SSTRCOD, the string argument of */ /* the current score event is used (string p-field) */ /* 2. if the value, rounded to the nearest integer, is a */ /* valid index to strset space, the strset string is */ /* used */ /* 3. the file name is generated using baseName and the */ /* value rounded to the nearest integer, as described */ /* above */ /* return value: */ /* pointer to the output string; if 's' is not NULL, it is */ /* always the same as 's', otherwise it is allocated with */ /* mmalloc() and the caller is responsible for freeing the */ /* allocated memory with mfree() or csound->Free() */ char *strarg2name(CSOUND *, char *, void *, const char *, int); /* ----------------------------------------------------------------------- */ static inline int sCmp(const char *x, const char *y) { int i = 0; while (x[i] == y[i] && x[i] != (char) 0) i++; return (x[i] != y[i]); } /* ----------------------------------------------------------------------- */ #ifdef __cplusplus } #endif #endif /* CSOUND_NAMEDINS_H */ csound-6.10.0/H/new_opts.h000066400000000000000000000034641321653344700153060ustar00rootroot00000000000000/* new_opts.h: Copyright (C) 2005 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef CSOUND_NEW_OPTS_H #define CSOUND_NEW_OPTS_H #ifdef __cplusplus extern "C" { #endif /** * Assignment to configuration variables from the command line can be done * with '-+NAME=VALUE'. Boolean variables can be set to true with any of * '-+NAME', '-+NAME=1', '-+NAME=yes', '-+NAME=on', and '-+NAME=true', * while setting to false is possible with any of '-+no-NAME', '-+NAME=0', * '-+NAME=no', '-+NAME=off', and '-+NAME=false'. */ /* ------------------------ INTERNAL API FUNCTIONS ------------------------ */ /* list command line usage of all registered configuration variables */ void dump_cfg_variables(CSOUND *csound); /* Parse 's' as an assignment to a configuration variable in the format */ /* '-+NAME=VALUE'. In the case of boolean variables, the format may also */ /* be '-+NAME' for true, and '-+no-NAME' for false. */ /* Return value is zero on success. */ int parse_option_as_cfgvar(CSOUND *csound, const char *s); #ifdef __cplusplus } #endif #endif /* CSOUND_NEW_OPTS_H */ csound-6.10.0/H/oload.h000066400000000000000000000027121321653344700145410ustar00rootroot00000000000000/* oload.h: Copyright (C) 1991 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef CSOUND_OLOAD_H #define CSOUND_OLOAD_H #define NCONSTS 256 /* gbl */ /* OLOAD.H */ //#define NLABELS 5 /* lcl */ //#define NGOTOS 40 #define LABELOFS (-0x40000000) #define LABELIM (-0x38000000) #define STR_OFS (0x78000000) /* string constant index base */ typedef struct { char *lbltxt; int *ndxp; } LBLARG; typedef struct { int lblno; MYFLT **argpp; } LARGNO; typedef struct { MYFLT *sets[PMAX]; } PVSET; typedef struct { OPDS h; MYFLT *insno, *itime; } TURNON; #endif /* CSOUND_OLOAD_H */ csound-6.10.0/H/oscils.h000066400000000000000000000044741321653344700147460ustar00rootroot00000000000000/* oscils.h: Copyright (C) 2002 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* ------ oscils, lphasor, and tablexkt by Istvan Varga (Jan 5 2002) ------ */ #ifndef CSOUND_OSCILS_H #define CSOUND_OSCILS_H /* oscils opcode struct */ typedef struct { OPDS h; MYFLT *ar, *iamp, *icps, *iphs, *iflg; /* opcode args */ /* internal variables */ int use_double; double xd, cd, vd; MYFLT x, c, v; } OSCILS; /* lphasor opcode struct */ typedef struct { OPDS h; MYFLT *ar, *xtrns, *ilps, *ilpe; /* opcode */ MYFLT *imode, *istrt, *istor; /* args */ /* internal variables */ int loop_mode; double phs, lps, lpe; int dir; /* playback direction (0: backward, 1: forward) */ } LPHASOR; /* tablexkt opcode struct */ typedef struct { OPDS h; MYFLT *ar, *xndx, *kfn, *kwarp, *iwsize; /* opcode */ MYFLT *ixmode, *ixoff, *iwrap; /* args */ /* internal variables */ int raw_ndx, ndx_scl, wrap_ndx, wsize; MYFLT win_fact; /* double wsized2_d, pidwsize_d; */ /* for oscils_hann.c */ } TABLEXKT; /* these functions are exported to entry*.c */ #ifndef CSOUND_OSCILS_C extern int oscils_set (CSOUND *, void*); extern int oscils (CSOUND *, void*); extern int lphasor_set (CSOUND *, void*); extern int lphasor (CSOUND *, void*); extern int tablexkt_set (CSOUND *, void*); extern int tablexkt (CSOUND *, void*); #endif #endif /* CSOUND_OSCILS_H */ csound-6.10.0/H/pffft.h000066400000000000000000000153641321653344700145570ustar00rootroot00000000000000/* Copyright (c) 2013 Julien Pommier ( pommier@modartt.com ) Based on original fortran 77 code from FFTPACKv4 from NETLIB, authored by Dr Paul Swarztrauber of NCAR, in 1985. As confirmed by the NCAR fftpack software curators, the following FFTPACKv5 license applies to FFTPACKv4 sources. My changes are released under the same terms. FFTPACK license: http://www.cisl.ucar.edu/css/software/fftpack5/ftpk.html Copyright (c) 2004 the University Corporation for Atmospheric Research ("UCAR"). All rights reserved. Developed by NCAR's Computational and Information Systems Laboratory, UCAR, www.cisl.ucar.edu. Redistribution and use of the Software in source and binary forms, with or without modification, is permitted provided that the following conditions are met: - Neither the names of NCAR's Computational and Information Systems Laboratory, the University Corporation for Atmospheric Research, nor the names of its sponsors or contributors may be used to endorse or promote products derived from this Software without specific prior written permission. - Redistributions of source code must retain the above copyright notices, this list of conditions, and the disclaimer below. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the disclaimer below in the documentation and/or other materials provided with the distribution. THIS 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 CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 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 WITH THE SOFTWARE. */ /* PFFFT : a Pretty Fast FFT. This is basically an adaptation of the single precision fftpack (v4) as found on netlib taking advantage of SIMD instruction found on cpus such as intel x86 (SSE1), powerpc (Altivec), and arm (NEON). For architectures where no SIMD instruction is available, the code falls back to a scalar version. Restrictions: - 1D transforms only, with 32-bit single precision. - supports only transforms for inputs of length N of the form N=(2^a)*(3^b)*(5^c), a >= 5, b >=0, c >= 0 (32, 48, 64, 96, 128, 144, 160, etc are all acceptable lengths). Performance is best for 128<=N<=8192. - all (float*) pointers in the functions below are expected to have an "simd-compatible" alignment, that is 16 bytes on x86 and powerpc CPUs. You can allocate such buffers with the functions pffft_aligned_malloc / pffft_aligned_free (or with stuff like posix_memalign..) */ #ifndef PFFFT_H #define PFFFT_H #include // for size_t #ifdef __cplusplus extern "C" { #endif /* opaque struct holding internal stuff (precomputed twiddle factors) this struct can be shared by many threads as it contains only read-only data. */ typedef struct PFFFT_Setup PFFFT_Setup; /* direction of the transform */ typedef enum { PFFFT_FORWARD, PFFFT_BACKWARD } pffft_direction_t; /* type of transform */ typedef enum { PFFFT_REAL, PFFFT_COMPLEX } pffft_transform_t; /* prepare for performing transforms of size N -- the returned PFFFT_Setup structure is read-only so it can safely be shared by multiple concurrent threads. */ PFFFT_Setup *pffft_new_setup(int N, pffft_transform_t transform); void pffft_destroy_setup(PFFFT_Setup *); /* Perform a Fourier transform , The z-domain data is stored in the most efficient order for transforming it back, or using it for convolution. If you need to have its content sorted in the "usual" way, that is as an array of interleaved complex numbers, either use pffft_transform_ordered , or call pffft_zreorder after the forward fft, and before the backward fft. Transforms are not scaled: PFFFT_BACKWARD(PFFFT_FORWARD(x)) = N*x. Typically you will want to scale the backward transform by 1/N. The 'work' pointer should point to an area of N (2*N for complex fft) floats, properly aligned. If 'work' is NULL, then stack will be used instead (this is probably the best strategy for small FFTs, say for N < 16384). input and output may alias. */ void pffft_transform(PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction); /* Similar to pffft_transform, but makes sure that the output is ordered as expected (interleaved complex numbers). This is similar to calling pffft_transform and then pffft_zreorder. input and output may alias. */ void pffft_transform_ordered(PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction); /* call pffft_zreorder(.., PFFFT_FORWARD) after pffft_transform(..., PFFFT_FORWARD) if you want to have the frequency components in the correct "canonical" order, as interleaved complex numbers. (for real transforms, both 0-frequency and half frequency components, which are real, are assembled in the first entry as F(0)+i*F(n/2+1). Note that the original fftpack did place F(n/2+1) at the end of the arrays). input and output should not alias. */ void pffft_zreorder(PFFFT_Setup *setup, const float *input, float *output, pffft_direction_t direction); /* Perform a multiplication of the frequency components of dft_a and dft_b and accumulate them into dft_ab. The arrays should have been obtained with pffft_transform(.., PFFFT_FORWARD) and should *not* have been reordered with pffft_zreorder (otherwise just perform the operation yourself as the dft coefs are stored as interleaved complex numbers). the operation performed is: dft_ab += (dft_a * fdt_b)*scaling The dft_a, dft_b and dft_ab pointers may alias. */ void pffft_zconvolve_accumulate(PFFFT_Setup *setup, const float *dft_a, const float *dft_b, float *dft_ab, float scaling); /* the float buffers must have the correct alignment (16-byte boundary on intel and powerpc). This function may be used to obtain such correctly aligned buffers. */ void *pffft_aligned_malloc(size_t nb_bytes); void pffft_aligned_free(void *); /* return 4 or 1 whether support SSE/Altivec instructions was enable when building pffft.c */ int pffft_simd_size(void); #ifdef __cplusplus } #endif #endif // PFFFT_H csound-6.10.0/H/prototyp.h000066400000000000000000000246751321653344700153570ustar00rootroot00000000000000/* prototyp.h: Copyright (C) 1991-2005 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* PROTOTYP.H */ #if defined(__BUILDING_LIBCSOUND) && !defined(_CSOUND_PROTO_H) #define _CSOUND_PROTO_H #include #include #ifdef __cplusplus extern "C" { #endif void cscore_(CSOUND *); void *mmalloc(CSOUND *, size_t); void *mcalloc(CSOUND *, size_t); void *mrealloc(CSOUND *, void *, size_t); void mfree(CSOUND *, void *); void *mmallocDebug(CSOUND *, size_t, char*, int); void *mcallocDebug(CSOUND *, size_t, char*, int); void *mreallocDebug(CSOUND *, void *, size_t, char*, int); void mfreeDebug(CSOUND *, void *, char*, int); char *cs_strdup(CSOUND*, char*); char *cs_strndup(CSOUND*, char*, size_t); void csoundAuxAlloc(CSOUND *, size_t, AUXCH *), auxchfree(CSOUND *, INSDS *); int csoundAuxAllocAsync(CSOUND *, size_t , AUXCH *, AUXASYNC *, aux_cb , void *); void fdrecord(CSOUND *, FDCH *), fdclose(CSOUND *, FDCH *); void fdchclose(CSOUND *, INSDS *); CS_PRINTF2 void synterr(CSOUND *, const char *, ...); CS_NORETURN CS_PRINTF2 void csoundDie(CSOUND *, const char *, ...); CS_PRINTF2 int csoundInitError(CSOUND *, const char *, ...); CS_PRINTF3 int csoundPerfError(CSOUND *, INSDS *ip, const char *, ...); CS_PRINTF2 void csoundWarning(CSOUND *, const char *, ...); CS_PRINTF2 void csoundDebugMsg(CSOUND *, const char *, ...); CS_PRINTF2 void csoundErrorMsg(CSOUND *, const char *, ...); void csoundErrMsgV(CSOUND *, const char *, const char *, va_list); CS_NORETURN void csoundLongJmp(CSOUND *, int retval); TEXT *getoptxt(CSOUND *, int *); void reverbinit(CSOUND *); void dispinit(CSOUND *); int init0(CSOUND *); void scsort(CSOUND *, FILE *, FILE *); char *scsortstr(CSOUND *, CORFIL *); int scxtract(CSOUND *, CORFIL *, FILE *); int rdscor(CSOUND *, EVTBLK *); int musmon(CSOUND *); void RTLineset(CSOUND *); FUNC *csoundFTFind(CSOUND *, MYFLT *); FUNC *csoundFTFindP(CSOUND *, MYFLT *); FUNC *csoundFTnp2Find(CSOUND *, MYFLT *); MYFLT intpow(MYFLT, int32); void list_opcodes(CSOUND *, int); char *getstrformat(int format); int sfsampsize(int sf_format); char *type2string(int type); int type2csfiletype(int type, int encoding); int sftype2csfiletype(int type); void rewriteheader(void *ofd); #if 0 int readOptions_file(CSOUND *, FILE *, int); #else int readOptions(CSOUND *, CORFIL *, int); #endif PUBLIC int argdecode(CSOUND *, int, const char **); void remove_tmpfiles(CSOUND *); void add_tmpfile(CSOUND *, char *); void xturnoff(CSOUND *, INSDS *); void xturnoff_now(CSOUND *, INSDS *); int insert_score_event(CSOUND *, EVTBLK *, double); //MEMFIL *ldmemfile(CSOUND *, const char *); //MEMFIL *ldmemfile2(CSOUND *, const char *, int); MEMFIL *ldmemfile2withCB(CSOUND *csound, const char *filnam, int csFileType, int (*callback)(CSOUND*, MEMFIL*)); void rlsmemfiles(CSOUND *); int delete_memfile(CSOUND *, const char *); char *csoundTmpFileName(CSOUND *, const char *); void *SAsndgetset(CSOUND *, char *, void *, MYFLT *, MYFLT *, MYFLT *, int); int getsndin(CSOUND *, void *, MYFLT *, int, void *); void *sndgetset(CSOUND *, void *); void dbfs_init(CSOUND *, MYFLT dbfs); int csoundLoadExternals(CSOUND *); SNDMEMFILE *csoundLoadSoundFile(CSOUND *, const char *name, void *sfinfo); int PVOCEX_LoadFile(CSOUND *, const char *fname, PVOCEX_MEMFILE *p); void print_opcodedir_warning(CSOUND *); int check_rtaudio_name(char *fName, char **devName, int isOutput); int csoundLoadOpcodeDB(CSOUND *, const char *); void csoundDestroyOpcodeDB(CSOUND *); int csoundCheckOpcodePluginFile(CSOUND *, const char *); //int csoundLoadAllPluginOpcodes(CSOUND *); int csoundLoadAndInitModule(CSOUND *, const char *); void csoundNotifyFileOpened(CSOUND *, const char *, int, int, int); int insert_score_event_at_sample(CSOUND *, EVTBLK *, int64_t); char *get_arg_string(CSOUND *, MYFLT); /** * Register a function to be called at note deactivation. * Should be called from the initialisation routine of an opcode. * 'p' is a pointer to the OPDS structure of the opcode, and 'func' * is the function to be called, with the same arguments and return * value as in the case of opcode init/perf functions. * The functions are called in reverse order of registration. * Returns zero on success. */ int csoundRegisterDeinitCallback(CSOUND *, void *p, int (*func)(CSOUND *, void *)); /** * Register a function to be called by csoundReset(), in reverse order * of registration, before unloading external modules. The function takes * the Csound instance pointer as the first argument, and the pointer * passed here as 'userData' as the second, and is expected to return zero * on success. * The return value of csoundRegisterResetCallback() is zero on success. */ int csoundRegisterResetCallback(CSOUND *, void *userData, int (*func)(CSOUND *, void *)); /** * Returns the name of the opcode of which the data structure * is pointed to by 'p'. */ char *csoundGetOpcodeName(void *p); /** * Returns the number of input arguments for opcode 'p'. */ int csoundGetInputArgCnt(void *p); /** Returns the CS_TYPE for an opcode's arg pointer */ CS_TYPE* csoundGetTypeForArg(void* argPtr); /** * Returns a binary value of which bit 0 is set if the first input * argument is a string, bit 1 is set if the second input argument is * a string, and so on. * Only the first 31 arguments are guaranteed to be reported correctly. */ unsigned long csoundGetInputArgSMask(void *p); /** * Returns the name of input argument 'n' (counting from 0) for opcode 'p'. */ char *csoundGetInputArgName(void *p, int n); /** * Returns the number of output arguments for opcode 'p'. */ int csoundGetOutputArgCnt(void *p); /** * Returns a binary value of which bit 0 is set if the first output * argument is a string, bit 1 is set if the second output argument is * a string, and so on. * Only the first 31 arguments are guaranteed to be reported correctly. */ unsigned long csoundGetOutputArgSMask(void *p); /** * Returns the name of output argument 'n' (counting from 0) for opcode 'p'. */ char *csoundGetOutputArgName(void *p, int n); /** * Set release time in control periods (1 / csound->ekr second units) * for opcode 'p' to 'n'. If the current release time is longer than * the specified value, it is not changed. * Returns the new release time. */ int csoundSetReleaseLength(void *p, int n); /** * Set release time in seconds for opcode 'p' to 'n'. * If the current release time is longer than the specified value, * it is not changed. * Returns the new release time in seconds. */ MYFLT csoundSetReleaseLengthSeconds(void *p, MYFLT n); /** * Returns MIDI channel number (0 to 15) for the instrument instance * that called opcode 'p'. * In the case of score notes, -1 is returned. */ int csoundGetMidiChannelNumber(void *p); /** * Returns a pointer to the MIDI channel structure for the instrument * instance that called opcode 'p'. * In the case of score notes, NULL is returned. */ MCHNBLK *csoundGetMidiChannel(void *p); /** * Returns MIDI note number (in the range 0 to 127) for opcode 'p'. * If the opcode was not called from a MIDI activated instrument * instance, the return value is undefined. */ int csoundGetMidiNoteNumber(void *p); /** * Returns MIDI velocity (in the range 0 to 127) for opcode 'p'. * If the opcode was not called from a MIDI activated instrument * instance, the return value is undefined. */ int csoundGetMidiVelocity(void *p); /** * Returns non-zero if the current note (owning opcode 'p') is releasing. */ int csoundGetReleaseFlag(void *p); /** * Returns the note-off time in seconds (measured from the beginning of * performance) of the current instrument instance, from which opcode 'p' * was called. The return value may be negative if the note has indefinite * duration. */ double csoundGetOffTime(void *p); /** * Returns the array of p-fields passed to the instrument instance * that owns opcode 'p', starting from p0. Only p1, p2, and p3 are * guaranteed to be available. p2 is measured in seconds from the * beginning of the current section. */ MYFLT *csoundGetPFields(void *p); /** * Returns the instrument number (p1) for opcode 'p'. */ int csoundGetInstrumentNumber(void *p); /** * Returns pointer to a string constant storing an error massage * for error code 'errcode'. */ const char *csoundExternalMidiErrorString(CSOUND *, int errcode); /** * Appends a list of opcodes implemented by external software to Csound's * internal opcode list. The list should either be terminated with an entry * that has a NULL opname, or the number of entries (> 0) should be specified * in 'n'. * Returns zero on success. */ int csoundAppendOpcodes(CSOUND *, const OENTRY *opcodeList, int n); /** * Check system events, yielding cpu time for coopertative multitasking, etc. */ int csoundYield(CSOUND *); /** * Register utility with the specified name. * Returns zero on success. */ int csoundAddUtility(CSOUND *, const char *name, int (*UtilFunc)(CSOUND *, int, char **)); /** * Set description text for the specified utility. * Returns zero on success. */ int csoundSetUtilityDescription(CSOUND *, const char *utilName, const char *utilDesc); /** * Remove all configuration variables of Csound instance 'csound', * and free database. This function is called by csoundReset(). * Return value is CSOUNDCFG_SUCCESS in case of success. */ int csoundDeleteAllConfigurationVariables(CSOUND *); #ifdef __cplusplus } #endif #endif /* __BUILDING_LIBCSOUND && !_CSOUND_PROTO_H */ csound-6.10.0/H/remote.h000066400000000000000000000112401321653344700147320ustar00rootroot00000000000000/* remote.h: Copyright (C) 2006 by Barry Vercoe This file is not yet part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef CSOUND_REMOTE_H #define CSOUND_REMOTE_H #ifdef HAVE_SOCKETS #if defined(WIN32) && !defined(__CYGWIN__) #include #ifndef SHUT_RDWR #define SHUT_RD 0x00 #define SHUT_WR 0x01 #define SHUT_RDWR 0x02 #endif #else #include #ifdef __HAIKU__ #include #endif #include #include #ifdef MACOSX #include #endif #ifdef LINUX #include #endif #include #ifdef HAVE_UNISTD_H # include #endif #endif #endif /* HAVE_SOCKETS */ #include #include #ifdef HAVE_SYS_TYPES_H # include #endif #include #include void m_chanmsg(CSOUND *csound, MEVENT *mep); /* called from midirecv & musmon */ char remoteID(CSOUND *csound); #define REMOT_PORT 40002 #define SCOR_EVT 1 #define MIDI_EVT 2 #define MIDI_MSG 3 #define MAXSEND (sizeof(EVTBLK) + 2*sizeof(int)) #define GLOBAL_REMOT -99 typedef struct { /* Remote Communication buffer */ int len; /* lentot = len + type + data used */ int type; char data[MAXSEND]; } REMOT_BUF; #ifdef HAVE_SOCKETS typedef struct { char *adr; int rfd; } SOCK; typedef struct { SOCK *socksout; /* = NULL; */ int *socksin; /* = NULL; */ int *insrfd_list; /* = NULL; */ int *chnrfd_list; /* = NULL; */ int insrfd_count; /* = 0; */ int chnrfd_count; /* = 0; */ int *insrfd; /* = NULL; */ int *chnrfd; /* = NULL; */ char *ipadrs; /* = NULL; */ struct sockaddr_in to_addr; struct sockaddr_in local_addr; REMOT_BUF CLsendbuf; /* rt evt output Communications buffer */ int remote_port; /* = 40002 default */ } REMOTE_GLOBALS; #endif /* HAVE_SOCKETS */ typedef struct { /* structs for INSTR 0 opcodes */ OPDS h; MYFLT *port; } REMOTEPORT; typedef struct { /* structs for INSTR 0 opcodes */ OPDS h; STRINGDAT *str1, *str2; MYFLT *insno[64]; } INSREMOT; typedef struct { /* structs for INSTR 0 opcodes */ OPDS h; STRINGDAT *str1; MYFLT *insno[64]; } INSGLOBAL; typedef struct { OPDS h; STRINGDAT *str1, *str2; MYFLT *chnum[16]; } MIDREMOT; typedef struct { /* structs for INSTR 0 opcodes */ OPDS h; STRINGDAT *str1; MYFLT *chnum[16]; } MIDGLOBAL; int CLsend(CSOUND *csound, int conn, void *data, int length); int SVrecv(CSOUND *csound, int conn, void *data, int length); /* musmon: divert a score insno event to a remote machine */ int insSendevt(CSOUND *p, EVTBLK *evt, int rfd); /* musmon: send an event (funcs, reverbs) to all active remote machines */ int insGlobevt(CSOUND *p, EVTBLK *evt); /* musmon: divert a MIDI channel event to a remote machine */ int MIDIsendevt(CSOUND *p, MEVENT *evt, int rfd); /* musmon: send a MIDI channel event (ctrlrs, reverbs) to all active remote machines */ int MIDIGlobevt(CSOUND *p, MEVENT *evt); /* midirecv: divert a MIDI channel message to a remote machine */ int MIDIsend_msg(CSOUND *p, MEVENT *evt, int rfd); /* midirecv: send a MIDI channel message (ctrlrs, reverbs) to all active remote machines */ int MIDIGlob_msg(CSOUND *p, MEVENT *evt); /* musmon: returns the active input sockets # */ int* getRemoteSocksIn(CSOUND *csound); /* musmon: determine whether an instrument accepts remove events */ int getRemoteInsRfd(CSOUND *csound, int insno); /* musmon: determine how many instruments accept remove events */ int getRemoteInsRfdCount(CSOUND *csound); /* musmon: determine whether MIDI channel accepts remove events */ int getRemoteChnRfd(CSOUND *csound, int chan); #endif /* CSOUND_REMOTE_H */ csound-6.10.0/H/resize.h000066400000000000000000000017701321653344700147470ustar00rootroot00000000000000/* resize.h: Copyright (C) 2011 by Jon ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ typedef struct { OPDS h; MYFLT *size; /* Ansser */ MYFLT *fn; /* which table */ MYFLT *nsize; /* new size */ } RESIZE; csound-6.10.0/H/schedule.h000066400000000000000000000050631321653344700152410ustar00rootroot00000000000000/* schedule.h: Copyright (C) 1999, 2002 rasmus ekman, Istvan Varga, John ffitch, Gabriel Maldonado, matt ingalls This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ typedef struct { OPDS h; MYFLT *which, *when, *dur; MYFLT *argums[VARGMAX-3]; int midi; INSDS *kicked; } SCHED; typedef struct { OPDS h; MYFLT *trigger; MYFLT *which, *when, *dur; MYFLT *argums[VARGMAX-3]; int todo; MYFLT abs_when; int midi; INSDS *kicked; } WSCHED; typedef struct { OPDS h; MYFLT *res; MYFLT *kamp, *xcps, *type; AUXCH auxd; MYFLT *sine; int lasttype; int32 phs; } LFO; /*****************************************************************/ /* triginstr - Start instrument events at k-rate from orchestra. */ /* August 1999 by rasmus ekman. */ /*****************************************************************/ typedef struct { OPDS h; MYFLT *trigger, *mintime, *maxinst; MYFLT *args[PMAX+1]; MYFLT prvmintim; int32 timrem, prvktim, kadjust; } TRIGINSTR; /*****************************************************************/ /* trigseq, seqtime - */ /* May 2000 by Gabriel Maldonado */ /*****************************************************************/ typedef struct { OPDS h; MYFLT *ktrig, *kstart, *kloop, *initndx, *kfn, *outargs[VARGMAX]; int32 ndx; int nargs, done; int32 pfn; MYFLT *table; } TRIGSEQ; typedef struct { OPDS h; MYFLT *ktrig, *unit_time, *kstart, *kloop, *initndx, *kfn; int32 ndx; int done; double start, newtime; int32 pfn; MYFLT *table; } SEQTIM; csound-6.10.0/H/sndinfUG.h000066400000000000000000000020531321653344700151560ustar00rootroot00000000000000/* sndinfUG.h: Copyright (C) 1999 matt ingalls This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ typedef struct { OPDS h; MYFLT *r1, *ifilno, *irawfiles; } SNDINFO; typedef struct { OPDS h; MYFLT *r1, *ifilno, *channel; } SNDINFOPEAK; typedef struct { OPDS h; MYFLT *r1, *ifilno; } FILEVALID; csound-6.10.0/H/sort.h000066400000000000000000000024431321653344700144330ustar00rootroot00000000000000/* sort.h: Copyright (C) 1991 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include /* SORT.H */ #ifndef MYFLT #include "sysdep.h" #endif #define SP ' ' #define LF '\n' typedef struct srtblk { struct srtblk *nxtblk; struct srtblk *prvblk; int16 insno; int16 pcnt; MYFLT p1val; MYFLT p2val; MYFLT p3val; MYFLT newp2; MYFLT newp3; int16 lineno; char preced; char text[9]; } SRTBLK; csound-6.10.0/H/str_ops.h000066400000000000000000000102601321653344700151310ustar00rootroot00000000000000/* str_ops.h: Copyright (C) 2005, 2006 Istvan Varga (C) 2005 Matt J. Ingalls, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef CSOUND_STR_OPS_H #define CSOUND_STR_OPS_H #ifdef __cplusplus extern "C" { #endif typedef struct { OPDS h; MYFLT *indx; STRINGDAT *str; } STRSET_OP; typedef struct { OPDS h; MYFLT *r; STRINGDAT *str; char *mem; } STRCHGD; typedef struct { OPDS h; MYFLT *indx; MYFLT *str; } STRTOD_OP; typedef struct { OPDS h; STRINGDAT *r; MYFLT *indx; } STRGET_OP; typedef struct { OPDS h; STRINGDAT *r; STRINGDAT *str; } STRCPY_OP; typedef struct { OPDS h; STRINGDAT *r; STRINGDAT *str1; STRINGDAT *str2; } STRCAT_OP; typedef struct { OPDS h; MYFLT *r; STRINGDAT *str1; STRINGDAT *str2; } STRCMP_OP; typedef struct { OPDS h; STRINGDAT *r; STRINGDAT *sfmt; MYFLT *args[64]; } SPRINTF_OP; typedef struct { OPDS h; STRINGDAT *sfmt; MYFLT *ktrig; MYFLT *args[64]; MYFLT prv_ktrig; } PRINTF_OP; typedef struct { OPDS h; STRINGDAT *str; MYFLT *ktrig; MYFLT *no_newline; MYFLT prv_ktrig; int noNewLine; } PUTS_OP; typedef struct { OPDS h; STRINGDAT *Sdst; STRINGDAT *Ssrc; MYFLT *istart; MYFLT *iend; } STRSUB_OP; typedef struct { OPDS h; MYFLT *ichr; STRINGDAT *Ssrc; MYFLT *ipos; } STRCHAR_OP; typedef struct { OPDS h; MYFLT *ilen; STRINGDAT *Ssrc; } STRLEN_OP; typedef struct { OPDS h; STRINGDAT *Sdst; STRINGDAT *Ssrc; } STRUPPER_OP; typedef struct { OPDS h; STRINGDAT *Sdst; MYFLT *iopt; } GETCFG_OP; typedef struct { OPDS h; MYFLT *ipos; STRINGDAT *Ssrc1; STRINGDAT *Ssrc2; } STRINDEX_OP; typedef struct { OPDS h; MYFLT *inVar; } PRINT_TYPE_OP; #ifndef CSOUND_STR_OPS_C int strset_init(CSOUND *, void *); int strget_init(CSOUND *, void *); int strcpy_opcode_p(CSOUND *, void *); int strcpy_opcode_S(CSOUND *, void *); int strassign_opcode_S(CSOUND *, void *); int strassign_opcode_Sk(CSOUND *, void *); int strcat_opcode(CSOUND *, void *); int strcmp_opcode(CSOUND *, void *); int sprintf_opcode(CSOUND *, void *); int printf_opcode_init(CSOUND *, void *); int printf_opcode_set(CSOUND *, void *); int printf_opcode_perf(CSOUND *, void *); int puts_opcode_init(CSOUND *, void *); int puts_opcode_perf(CSOUND *, void *); int strtod_opcode_p(CSOUND *, void *); int strtod_opcode_S(CSOUND *, void *); int strtol_opcode_p(CSOUND *, void *); int strtol_opcode_S(CSOUND *, void *); int strsub_opcode(CSOUND *, void *); int strchar_opcode(CSOUND *, void *); int strlen_opcode(CSOUND *, void *); int strupper_opcode(CSOUND *, void *); int strlower_opcode(CSOUND *, void *); int getcfg_opcode(CSOUND *, void *); int strindex_opcode(CSOUND *, void *); int strrindex_opcode(CSOUND *, void *); int str_changed(CSOUND *csound, STRCHGD *p); int str_changed_k(CSOUND *csound, STRCHGD *p); int str_from_url(CSOUND *csound, STRCPY_OP *p); int print_type_opcode(CSOUND*, void*); int s_opcode(CSOUND *csound, void *p); int s_opcode_k(CSOUND *csound, void *p); #endif /* CSOUND_STR_OPS_C */ #ifdef __cplusplus } #endif #endif /* CSOUND_STR_OPS_H */ csound-6.10.0/H/tok.h000066400000000000000000000017321321653344700142410ustar00rootroot00000000000000/* tok.h: Copyright (C) 2007 by Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __TOK_H #define __TOK_H #include "csoundCore.h" /* typedef int (*SUBR)(void *, void *); */ extern ORCTOKEN *new_token(CSOUND *, int); #endif csound-6.10.0/H/ugens1.h000066400000000000000000000064261321653344700146530ustar00rootroot00000000000000/* ugens1.h: Copyright (C) 1991 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* UGENS1.H */ typedef struct { OPDS h; MYFLT *xr, *ia, *idur, *ib; double val, incr, kincr; } LINE; typedef struct { OPDS h; MYFLT *xr, *ia, *idur, *ib; double val, mlt, kmlt; } EXPON; typedef struct { int32 cnt, acnt; MYFLT val, mlt, amlt; } XSEG; typedef struct { int32 cnt, acnt; double nxtpt; } SEG; typedef struct { OPDS h; MYFLT *rslt, *argums[VARGMAX]; SEG *cursegp; int32 nsegs; int32 segsrem, curcnt; double curval, curinc, curainc; AUXCH auxch; int32 xtra; } LINSEG; typedef struct { OPDS h; MYFLT *rslt, *argums[VARGMAX]; SEG *cursegp; int32 nsegs; int32 segsrem, curcnt; double y1, y2, x, inc, val; AUXCH auxch; int32 xtra; } COSSEG; typedef struct { OPDS h; MYFLT *rslt, *argums[VARGMAX]; SEG *cursegp; int32 segsrem, curcnt; double curval, curmlt, curamlt; int32 nsegs; AUXCH auxch; int32 xtra; } EXPSEG; typedef struct { OPDS h; MYFLT *rslt, *argums[VARGMAX]; XSEG *cursegp; int32 segsrem, curcnt; double curval, curmlt, curamlt; int32 nsegs; AUXCH auxch; } EXXPSEG; typedef struct { OPDS h; MYFLT *rslt, *sig, *iris, *idur, *idec; double lin1, inc1, val, lin2, inc2; int32 cnt1, cnt2; } LINEN; typedef struct { OPDS h; MYFLT *rslt, *sig, *iris, *idec, *iatdec; double lin1, inc1, val, val2, mlt2; int32 cnt1; } LINENR; typedef struct { OPDS h; MYFLT *rslt, *xamp, *irise, *idur, *idec, *ifn, *iatss; MYFLT *iatdec, *ixmod; int32 phs, ki, cnt1; double val, mlt1, mlt2, asym; FUNC *ftp; } ENVLPX; typedef struct { OPDS h; MYFLT *rslt, *xamp, *irise, *idec, *ifn, *iatss, *iatdec; MYFLT *ixmod, *irind; int32 phs, ki, rlsing, rlscnt, rindep; double val, mlt1, mlt2, asym, atdec; FUNC *ftp; } ENVLPR; typedef struct { OPDS h; MYFLT *rslt, *argums[VARGMAX]; XSEG *cursegp; int32 nsegs; AUXCH auxch; } EXPSEG2; /*gab-A1*/ csound-6.10.0/H/ugens2.h000066400000000000000000000035461321653344700146540ustar00rootroot00000000000000/* ugens2.h: Copyright (C) 1991 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* UGENS2.H */ typedef struct { OPDS h; MYFLT *sr, *xcps, *iphs; double curphs; } PHSOR; typedef struct { OPDS h; MYFLT *sr,*aphs, *xcps, *kR, *iphs; double curphs; double b; } EPHSOR; typedef struct { OPDS h; MYFLT *rslt, *xndx, *xfn, *ixmode, *ixoff, *iwrap; MYFLT offset; int32 pfn; int32 xbmul; int wrap; FUNC *ftp; } TABLE; typedef struct { OPDS h; MYFLT *rslt, *idel, *kamp, *idur, *ifn; int32 kinc, phs; int32 dcnt; FUNC *ftp; } OSCIL1; typedef struct { OPDS h; MYFLT *rslt, *kamp, *ifrq, *ifn, *itimes; MYFLT index, inc, maxndx; int32 ntimes; FUNC *ftp; } OSCILN; typedef struct { OPDS h; MYFLT *sr, *xamp, *xcps, *ifn, *iphs; int32 lphs; FUNC *ftp; FUNC FF; } OSC; csound-6.10.0/H/ugens3.h000066400000000000000000000037151321653344700146530ustar00rootroot00000000000000/* ugens3.h: Copyright (C) 1991 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* UGENS3.H */ typedef struct { OPDS h; MYFLT *rslt, *xamp, *kcps, *xcar, *xmod, *kndx, *ifn, *iphs; int32 mphs, cphs; int16 ampcod, carcod, modcod; FUNC *ftp; } FOSC; typedef struct { OPDS h; MYFLT *ar1,*ar2,*xamp,*kcps,*ifn,*ibas,*imod1,*ibeg1,*iend1, *imod2,*ibeg2,*iend2; MYFLT cpscvt; MYFLT lphs; int16 mod1, mod2; MYFLT beg1, beg2; MYFLT end1, end2; int16 seg1, curmod, looping, stereo; FUNC *ftp; } LOSC; typedef struct { int16 tim; int16 val; } DUPLE; typedef struct ptlptr { struct ptlptr *nxtp; DUPLE *ap; DUPLE *fp; int16 amp,frq; int32 phs; } PTLPTR; #define MAXPTLS 50 /* must agree with hetro.c */ typedef struct { OPDS h; MYFLT *rslt, *kamod, *kfmod, *ksmod, *ifilcod, *dum; MEMFIL *mfp; int32 mksecs; AUXCH aux; /* PTLPTR ptlptrs[MAXPTLS + 1]; make dynamic */ } ADSYN; csound-6.10.0/H/ugens4.h000066400000000000000000000043241321653344700146510ustar00rootroot00000000000000/* ugens4.h: Copyright (C) 1991 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* UGENS4.H */ typedef struct { OPDS h; MYFLT *ar, *xamp, *xcps, *knh, *ifn, *iphs; int16 ampcod, cpscod; int32 lphs; FUNC *ftp; int reported; } BUZZ; typedef struct { OPDS h; MYFLT *ar, *xamp, *xcps, *kn, *kk, *kr, *ifn, *iphs; int16 ampcod, cpscod, prvn; MYFLT prvr, twor, rsqp1, rtn, rtnp1, rsumr; int32 lphs; FUNC *ftp; int reported; MYFLT last; } GBUZZ; typedef struct { OPDS h; MYFLT *ar, *kamp, *kcps, *icps, *ifn, *imeth, *ipar1, *ipar2; MYFLT sicps, param1, param2; int16 thresh1, thresh2, method; int32 phs256, npts, maxpts; AUXCH auxch; } PLUCK; typedef struct { OPDS h; MYFLT *ar, *xamp, *iseed, *sel, *base; int rand; int16 ampcod; int16 new; } RAND; typedef struct { OPDS h; MYFLT *ar, *xamp, *xcps, *iseed, *sel, *base; int16 ampcod, cpscod, new; int rand; long phs; MYFLT num1; } RANDH; typedef struct { OPDS h; MYFLT *ar, *xamp, *xcps, *iseed, *sel, *base; int16 ampcod, cpscod, new; int rand; long phs; MYFLT num1, num2, dfdmax; } RANDI; csound-6.10.0/H/ugens5.h000066400000000000000000000076121321653344700146550ustar00rootroot00000000000000/* ugens5.h: Copyright (C) 1991 Barry Vercoe, John ffitch, Gabriel Maldonado This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "lpc.h" /* UGENS5.H */ typedef struct { OPDS h; MYFLT *kr, *ksig, *ihtim, *isig; double c1, c2, yt1; MYFLT ihtim_old; } PORT; typedef struct { OPDS h; MYFLT *ar, *asig, *khp, *istor; double c1, c2, yt1, prvhp; } TONE; typedef struct { OPDS h; MYFLT *ar, *asig, *kcf, *kbw, *iscl, *istor; int scale; double c1, c2, c3, yt1, yt2, cosf, prvcf, prvbw; int asigf, asigw; } RESON; typedef struct { OPDS h; MYFLT *ar, *asig, *khp, *ord, *istor; double c1, c2, *yt1, prvhp; int loop; AUXCH aux; } TONEX; typedef struct { OPDS h; MYFLT *ar, *asig, *kcf, *kbw, *ord, *iscl, *istor; int scale, loop; double c1, c2, c3, *yt1, *yt2, cosf, prvcf, prvbw; AUXCH aux; } RESONX; typedef struct { OPDS h; MYFLT *krmr, *krmo, *kerr, *kcps, *ktimpt, *ifilcod, *inpoles, *ifrmrate; int32 headlen, npoles, nvals, lastfram16, lastmsg; MYFLT *kcoefs, framrat16; int storePoles ; MEMFIL *mfp; AUXCH aux; } LPREAD; typedef struct { OPDS h; MYFLT *ar, *asig; MYFLT *circbuf, *circjp, *jp2lim; LPREAD *lpread; AUXCH aux; } LPRESON; typedef struct { OPDS h; MYFLT *kcf,*kbw, *kfor; LPREAD *lpread; AUXCH aux; } LPFORM; typedef struct { OPDS h; MYFLT *ar, *asig, *kfrqratio; MYFLT *past, prvratio, d, prvout; LPREAD *lpread; AUXCH aux; } LPFRESON; typedef struct { OPDS h; MYFLT *kr, *asig, *ihp, *istor; double c1, c2, prvq; } RMS; typedef struct { OPDS h; MYFLT *ar, *asig, *krms, *ihp, *istor; double c1, c2, prvq, prva; } GAIN; typedef struct { OPDS h; MYFLT *ar, *asig, *csig, *ihp, *istor; double c1, c2, prvq, prvr, prva; } BALANCE; typedef struct { OPDS h; MYFLT *islotnum ; /* Assume sizeof(int)== sizeof(MYFLT) */ } LPSLOT ; typedef struct { OPDS h; MYFLT *islot1 ; MYFLT *islot2 ; /* Assume sizeof(pointer)== sizeof(MYFLT) */ MYFLT *kmix ; MYFLT *fpad[5]; /* Pad for kcoef correctly put (Mighty dangerous) */ int32 lpad,npoles ; LPREAD *lp1,*lp2 ; int32 lastmsg; MYFLT *kcoefs/*[MAXPOLES*2]*/, framrat16; int storePoles ; AUXCH aux; } LPINTERPOL ; typedef struct { OPDS h; MYFLT *ans, *sig, *min, *max; } LIMIT; typedef PORT KPORT; typedef TONE KTONE; typedef RESON KRESON; int kporset(CSOUND*,PORT *p); int kport(CSOUND*,PORT *p); int ktonset(CSOUND*,TONE *p); int ktone(CSOUND*,TONE *p); int katone(CSOUND*,TONE *p); int krsnset(CSOUND*,RESON *p); int kreson(CSOUND*,RESON *p); int kareson(CSOUND*,RESON *p); int klimit(CSOUND*,LIMIT *p); int limit(CSOUND*,LIMIT *p); csound-6.10.0/H/ugens6.h000066400000000000000000000106061321653344700146530ustar00rootroot00000000000000/* ugens6.h: Copyright (C) 1991-2000 Barry Vercoe, John ffitch, Jens Groh, Hans Mikelson, Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* UGENS6.H */ typedef struct { OPDS h; MYFLT *kr, *asig, *ilen; unsigned int len; } DOWNSAMP; typedef struct { OPDS h; MYFLT *ar, *ksig; } UPSAMP; typedef struct { OPDS h; MYFLT *rslt, *xsig, *istor; MYFLT prev; } INDIFF; typedef struct { OPDS h; /* JPff Nov 2015 */ MYFLT *rslt, *xsig, *istor, *imode, *istart; /* IV - Sep 5 2002 */ int init_k; MYFLT prev; } INTERP; typedef struct { OPDS h; MYFLT *xr, *xsig, *xgate, *ival, *istor; MYFLT state; int audiogate; } SAMPHOLD; typedef struct { OPDS h; MYFLT *ar, *asig, *idlt, *istor; MYFLT *curp; int32 npts; AUXCH auxch; } DELAY; typedef struct DELAYR { OPDS h; MYFLT *ar, *indx, *idlt, *istor; MYFLT *curp; uint32_t npts; AUXCH auxch; struct DELAYR *next_delayr; /* fifo for delayr pointers by Jens Groh */ } DELAYR; typedef struct { OPDS h; MYFLT *ar, *xdlt, *indx; DELAYR *delayr; } DELTAP; typedef struct { OPDS h; MYFLT *ar, *adlt, *iwsize, *indx; int wsize; double d2x; DELAYR *delayr; } DELTAPX; typedef struct { OPDS h; MYFLT *asig; DELAYR *delayr; } DELAYW; typedef struct { OPDS h; MYFLT *ar, *asig, *istor; MYFLT sav1; } DELAY1; typedef struct { OPDS h; MYFLT *ar, *asig, *krvt, *ilpt, *istor, *insmps; MYFLT coef, prvt, *pntr; AUXCH auxch; } COMB; typedef struct { OPDS h; MYFLT *ar, *asig, *krvt, *istor; MYFLT c1, c2, c3, c4, c5, c6, prvt; MYFLT *p1, *p2, *p3, *p4, *p5, *p6; MYFLT *adr1, *adr2, *adr3, *adr4, *adr5, *adr6; AUXCH auxch; int32 revlpsum; AUXCH revlpsiz; } REVERB; typedef struct { OPDS h; MYFLT *r1, *r2, *r3, *r4, *asig, *kx, *ky, *ifn, *imode, *ioffset; MYFLT xmul, xoff; FUNC *ftp; } PAN; int downset(CSOUND *, DOWNSAMP *p); int downsamp(CSOUND *, DOWNSAMP *p); int upsamp(CSOUND *, UPSAMP *p); int a_k_set(CSOUND *, INTERP *p); int interpset(CSOUND *, INTERP *p); int interp(CSOUND *, INTERP *p); int indfset(CSOUND *, INDIFF *p); int kntegrate(CSOUND *, INDIFF *p); int integrate(CSOUND *, INDIFF *p); int kdiff(CSOUND *, INDIFF *p); int diff(CSOUND *, INDIFF *p); int samphset(CSOUND *, SAMPHOLD *p); int ksmphold(CSOUND *, SAMPHOLD *p); int samphold(CSOUND *, SAMPHOLD *p); int delset(CSOUND *, DELAY *p); int delrset(CSOUND *, DELAYR *p); int delwset(CSOUND *, DELAYW *p); int tapset(CSOUND *, DELTAP *p); int delay(CSOUND *, DELAY *p); int delayr(CSOUND *, DELAYR *p); int delayw(CSOUND *, DELAYW *p); int deltap(CSOUND *, DELTAP *p); int deltapi(CSOUND *, DELTAP *p); int deltapn(CSOUND *, DELTAP *p); int deltap3(CSOUND *, DELTAP *p); int tapxset(CSOUND *, DELTAPX *p); int deltapx(CSOUND *, DELTAPX *p); int deltapxw(CSOUND *, DELTAPX *p); int del1set(CSOUND *, DELAY1 *p); int delay1(CSOUND *, DELAY1 *p); int cmbset(CSOUND *, COMB *p); int comb(CSOUND *, COMB *p); int invcomb(CSOUND *, COMB *p); int alpass(CSOUND *, COMB *p); void reverbinit(CSOUND *); int rvbset(CSOUND *, REVERB *p); int reverb(CSOUND *, REVERB *p); int panset(CSOUND *, PAN *p); int pan(CSOUND *, PAN *p); csound-6.10.0/H/ugens7.h000066400000000000000000000051571321653344700146610ustar00rootroot00000000000000/* ugens7.h: Copyright (C) 1995 Michael Clarke, based on ideas from CHANT (IRCAM) 1996 Barry Vercoe This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* UGENS7.H */ #define PFRAC1(x) ((MYFLT)((x) & ftp1->lomask) * ftp1->lodiv) typedef struct ovrlap { struct ovrlap *nxtact, *nxtfree; int32 timrem, dectim, formphs, forminc, risphs, risinc, decphs, decinc; MYFLT curamp, expamp; MYFLT glissbas;/* Gliss factor to add to forminc (ifna index incr) */ int32 sampct; /* Sample count since grain started */ } OVRLAP; typedef struct { OPDS h; MYFLT *ar, *xamp, *xfund, *xform, *koct, *kband, *kris, *kdur, *kdec; MYFLT *iolaps, *ifna, *ifnb, *itotdur, *iphs, *ifmode, *iskip; /* kgliss and ifmode are same field */ OVRLAP basovrlap; int32 durtogo, fundphs, fofcount, prvsmps; MYFLT prvband, expamp, preamp; int16 foftype; /* Distinguish fof and fof2 */ int16 xincod, ampcod, fundcod, formcod, fmtmod; AUXCH auxch; FUNC *ftp1, *ftp2; } FOFS; typedef struct { OPDS h; MYFLT *ar, *asig, *kest, *kvar, *kfrq1, *kfrq2; MYFLT *icpsmode, *ilowest, *iptrkprd; int32 nbufsmps, n2bufsmps, phase1, phase2, period, autoktim, autokcnt; int32 mindist, maxdist, max2dist, lomaxdist, cpsmode; MYFLT c1, c2, prvq, prvest, prvar, minfrq, estprd, lsicvt; MYFLT *bufp, *midp, *inp1, *inp2; MYFLT *bufq, *midq, *inq1, *inq2, *autobuf; MYFLT *puls1, *puls2, *puls3, lin1, lin2, lin3; MYFLT inc1, inc2, inc11, inc12, inc21, inc22, inc31, inc32; int32 cnt1, cnt2, cnt3, pnt1, pnt2, pnt3; int32 pnt11, pnt12, pnt13, pnt21, pnt22, pnt23, pnt31, pnt32, pnt33; AUXCH auxch; } HARMON; csound-6.10.0/H/ugrw1.h000066400000000000000000000333041321653344700145110ustar00rootroot00000000000000/* ugrw1.h: Copyright (C) 1997 Robin Whittle This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* UGRW1.H */ /* These files are based on Robin Whittle's * ugrw1.c of 27 August 1996 * and ugrw1.h of 7 January 1995 * * In February 1997, John Fitch reformatted the comments and * cleaned up some code in printksset() - which was working fine * but was inelegantly coded. * * * Copyright notice - Robin Whittle 25 February 1997 * * Documentation files, and the original .c and .h files, with more * spaced out comments, are available from http://www.firstpr.com.au * * The code in both ugrw1 and ugrw2 is copyright Robin Whittle. * Permission is granted to use this in whole or in part for any * purpose, provided this copyright notice remains intact and * any alterations to the source code, including comments, are * clearly indicated as such. */ #include "csoundCore.h" /* * Unit generators by Robin Whittle 6 January 1996 * Header file containing data structures for UGRW1.C. */ /* TABLEW data structure used by all the tablew subroutines. */ typedef struct { OPDS h; MYFLT *xsig; /* Input value to write to table. */ MYFLT *xndx; /* Index into the table where want to write */ MYFLT *xfn; /* Number of table we are writing to. */ MYFLT *ixmode; /* Index mode (optional parm). * 0 --> Use raw xfn and ixoff. * 1 --> Use these with a range of 0 to 1 for * the entire range of the table. */ MYFLT *ixoff; /* Offset (opt). Fixed value to add to ndx*/ MYFLT *iwgmode; /* Wrap and guard point mode (optional) * 0 --> Limit indx to between 0 table len * 1 --> Index wraps around modulo len * 2 --> Write with 0.5 step offset, and * write both 0 and guard with the * same data. */ /* Internal variable for previous state of xfn. */ int32 pfn; /* Internal variable for what to multiply * the ndx and ixoff by. Set to 1 or table * length by tblwset() depending on ixmode. */ int32 xbmul; /* Internal variable for iwrap and igmode. */ int iwgm; /* Internal variable for offset. */ MYFLT offset; /* Pointer to data structure used to access * function table. tblwset() writes this, based * on the value of xfn. */ FUNC *ftp; } TABLEW; /* TABLENG data structure used by function tableng to return the * length of the table. */ typedef struct { OPDS h; MYFLT *kout; /* Output pointer */ MYFLT *xfn; /* Points to the number of the table. */ } TABLENG; /* TABLEGPW data structure used by function tablegpw to write the * guard point of a specified table. (No output arguments) */ typedef struct { OPDS h; MYFLT *xfn; /* Points to number of table. */ } TABLEGPW; /* TABLEMIX data structure used by function tablemix. */ typedef struct { OPDS h; MYFLT *dft, *doff, *len, *s1ft, *s1off, *s1g, *s2ft, *s2off, *s2g; /* Storage to remember what the table numbers were from a previous k cycle, and to store pointers to their FUNC data structures. */ int pdft; /* Previous destination */ int ps1ft, ps2ft; /* source function table numbers. */ FUNC *funcd, *funcs1, *funcs2; } TABLEMIX; /* TABLECOPY data structure used by function tablecopy. */ typedef struct { OPDS h; MYFLT *dft; /* Destination function table number. */ MYFLT *sft; /* Source function table number */ /* Storage to remember what the table numbers were from a previous k cycle, and to store pointers to their FUNC data structures. */ int pdft; /* Previous destination */ int psft; /* source function table numbers. */ FUNC *funcd, *funcs; } TABLECOPY; /* TABLERA data structure used by tablera subroutine. */ typedef struct { OPDS h; MYFLT *adest; /* A rate destination */ MYFLT *kfn; /* Number of table read */ MYFLT *kstart; /* Index mode within table */ MYFLT *koff; /* Offset to add to table index */ /* Internal variable for previous state of xfn. */ int32 pfn; /* Pointer to function table data structure */ FUNC *ftp; } TABLERA; /* TABLEWA data structure used by tablewa subroutine. */ typedef struct { OPDS h; MYFLT *kstart; /* Index mode within table we start reading. * Note this is also an input argument. First * we read it to determine where we should start * writing the a rate samples. When we have * finished we write to it the number of the * next location which should be written. */ MYFLT *kfn; /* Number of table we are reading from. */ MYFLT *asig; /* a rate input signal. */ MYFLT *koff; /* Offset to add to table index. */ int32 pfn; /* Pointer to function table. */ FUNC *ftp; } TABLEWA; /*****************************************************************************/ /* Data structures for the zak family of ugens for patching data at i, * k or a rates. * See also four global variables declared in the C code. */ /* ZAKINIT data structure for zakinit(). */ typedef struct { OPDS h; MYFLT *isizea; /* Number of a locations, each an array of * ksmps long, to to reserve for a rate * patching */ MYFLT *isizek; /* Number of locations for i or k rate * variables */ } ZAKINIT; /* ZKR data structure for zir() and zkr(). */ typedef struct { OPDS h; MYFLT *rslt; /* Where to write the value read from zk */ MYFLT *ndx; /* Location in zk space to read */ } ZKR; /* ZKW data structure for ziw() and zkw(). */ typedef struct { OPDS h; MYFLT *sig; /* Value to write */ MYFLT *ndx; /* Locations to read */ } ZKW; /* ZKWM data structure for ziwm() and zkwm(). */ typedef struct { OPDS h; MYFLT *sig; /* Value to write */ MYFLT *ndx; /* Locations to read */ MYFLT *mix; /* 0 for write directly; !0 for mix - add in */ } ZKWM; /* ZKMOD data structure for zkmod(). */ typedef struct { OPDS h; MYFLT *rslt; /* Points to where to write output */ MYFLT *sig; /* Value to modulate */ MYFLT *zkmod; /* Which zk variable to use to modulate sig */ } ZKMOD; /* ZKCL data structure for zkcl(). */ typedef struct { OPDS h; MYFLT *first; /* First variable to clear */ MYFLT *last; /* Final variable to clear */ } ZKCL; /* ZAR data structure for zar(). */ typedef struct { OPDS h; MYFLT *rslt; /* Where to write the value */ MYFLT *ndx; /* Location in za space to read */ } ZAR; /* ZARG data structure for zarg(). */ typedef struct { OPDS h; MYFLT *rslt; /* Where to write the zk location */ MYFLT *ndx; /* Location in za space to read */ MYFLT *kgain; /* Gain to be given to signal read */ } ZARG; /* ZAW data structure for zaw(). */ typedef struct { OPDS h; MYFLT *sig, *ndx; } ZAW; /* ZAWM data structure for zawm(). */ typedef struct { OPDS h; MYFLT *sig; MYFLT *ndx, *mix; /* Locations to read; 0 for write directly, or addd in */ } ZAWM; /* ZAWOD data structure for zamod(). */ typedef struct { OPDS h; MYFLT *rslt; MYFLT *sig, *zamod; /* Value to modulate; Which za variable to use */ } ZAMOD; /* ZACL data structure for zacl(). */ typedef struct { OPDS h; MYFLT *first, *last; } ZACL; /*****************************************************************************/ /* RDTIME data structure for timek(), times(), instimset(), instimek() and instimes(). */ typedef struct { OPDS h; MYFLT *rslt; int32 instartk; } RDTIME; /*****************************************************************************/ /* PRINTK data structure for printk() and printkset(). */ typedef struct { OPDS h; MYFLT *ptime; /* How much time to leave between each print*/ MYFLT *val; /* Value to print */ MYFLT *space; /* Spaces to insert before printing */ MYFLT initime, ctime; /* Time when initialised; initialised */ int32 pspace; /* How many spaces to print */ int32 cysofar; /* Number of print cycles so far */ int initialised; /* Non zero for initialised */ } PRINTK; /* PRINTKS data structure for printks() and printksset() */ typedef struct { OPDS h; MYFLT *ifilcod; /* File name */ MYFLT *ptime; /* How much time to leave between each print */ MYFLT *kvals[VARGMAX];/* values to print */ MYFLT initime, ctime; /* Time when initialised; Cycle time */ int32 cysofar; /* Number of print cycles so far from 0 */ int initialised; char txtstring[8192]; /* Place to store the string printed */ char* old; } PRINTKS; /* an i-rate-only prints */ typedef struct { OPDS h; MYFLT *ifilcod; /* File name */ MYFLT *kvals[VARGMAX];/* values to print */ } PRINTS; /*****************************************************************************/ /* PEAK data structure for peakk() and peaka(). */ typedef struct { OPDS h; MYFLT *kpeakout; /* Pointer to k or a rate input variable. */ MYFLT *xsigin; /* Pointer to k rate input variable which, * if set to no zero, causes the ugen to * clear the accumulator. */ } PEAK; typedef struct { OPDS h; MYFLT *val, *space; MYFLT oldvalue; int pspace; } PRINTK2; typedef struct { OPDS h; MYFLT *iformat; MYFLT *val; MYFLT oldvalue; char *sarg; } PRINTK3; typedef struct { OPDS h; MYFLT *ndx; } IOZ; int instimek(CSOUND*,RDTIME *p); int instimes(CSOUND*,RDTIME *p); int instimset(CSOUND*,RDTIME *p); int inz(CSOUND*,IOZ *p); //int itablecopy(CSOUND*,TABLECOPY *p); //int itablegpw(CSOUND*,TABLEGPW *p); //int itablemix(CSOUND*,TABLEMIX *p); //int itableng(CSOUND*,TABLENG *p); //int itablew(CSOUND*,TABLEW *p); //int ktablew(CSOUND*,TABLEW *p); //int ktablewkt(CSOUND*,TABLEW *p); int outz(CSOUND*,IOZ *p); int peaka(CSOUND*,PEAK *p); int peakk(CSOUND*,PEAK *p); int printk(CSOUND*,PRINTK *p); int printk2(CSOUND*,PRINTK2 *p); int printk2set(CSOUND*,PRINTK2 *p); int printks(CSOUND*,PRINTKS *p); int printkset(CSOUND*,PRINTK *p); int printksset(CSOUND*,PRINTKS *p); int printksset_S(CSOUND*,PRINTKS *p); int printsset(CSOUND*,PRINTS *p); int printsset_S(CSOUND*,PRINTS *p); int printk3(CSOUND*,PRINTK3 *p); int printk3set(CSOUND*,PRINTK3 *p); //int tablecopy(CSOUND*,TABLECOPY *p); //int tablecopyset(CSOUND*,TABLECOPY *p); //int tablegpw(CSOUND*,TABLEGPW *p); //int tablemix(CSOUND*,TABLEMIX *p); //int tablemixset(CSOUND*,TABLEMIX *p); //int tableng(CSOUND*,TABLENG *p); //int tablera(CSOUND*,TABLERA *p); //int tableraset(CSOUND*,TABLERA *p); //int tablew(CSOUND*,TABLEW *p); //int tablewa(CSOUND*,TABLEWA *p); //int tablewaset(CSOUND*,TABLEWA *p); //int tablewkt(CSOUND*,TABLEW *p); //int tblsetw(CSOUND*,TABLEW *p); //int tblsetwkt(CSOUND*,TABLEW *p); int timek(CSOUND*,RDTIME *p); int timesr(CSOUND*,RDTIME *p); int zacl(CSOUND*,ZACL *p); int zakinit(CSOUND*,ZAKINIT *p); int zamod(CSOUND*,ZAMOD *p); int zar(CSOUND*,ZAR *p); int zarg(CSOUND*,ZARG *p); int zaset(CSOUND*,ZAR *p); int zaw(CSOUND*,ZAW *p); int zawm(CSOUND*,ZAWM *p); int zir(CSOUND*,ZKR *p); int ziw(CSOUND*,ZKW *p); int ziwm(CSOUND*,ZKWM *p); int zkcl(CSOUND*,ZKCL *p); int zkmod(CSOUND*,ZKMOD *p); int zkr(CSOUND*,ZKR *p); int zkset(CSOUND*,ZKR *p); int zkw(CSOUND*,ZKW *p); int zkwm(CSOUND*,ZKWM *p); csound-6.10.0/H/ugtabs.h000066400000000000000000000026671321653344700147410ustar00rootroot00000000000000/* ugtabs.h: new implementation of table readers and writers Copyright (C) 2013 V Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ typedef struct _tabl { OPDS h; MYFLT *sig, *ndx, *ftable, *mode, *offset, *wrap; MYFLT mul; int32 np2; int32 len; int iwrap; FUNC *ftp; } TABL; typedef struct _tlen { OPDS h; MYFLT *ans, *ftable; } TLEN; typedef struct _tgp { OPDS h; MYFLT *ftable, *ftsrc; } TGP; typedef struct _tablmix { OPDS h; MYFLT *tab, *off, *len, *tab1, *off1, *g1, *tab2, *off2, *g2; } TABLMIX; typedef struct _tablra { OPDS h; MYFLT *sig,*ftable,*strt,*off; } TABLRA; typedef struct _tablwa { OPDS h; MYFLT *strt,*ftable,*sig,*off,*skipinit; MYFLT pos; } TABLWA; csound-6.10.0/H/vdelay.h000066400000000000000000000105231321653344700147260ustar00rootroot00000000000000/* vdelay.h: Copyright (C) 1994 Paris Smaragdis, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* vdelay, multitap, reverb2 coded by Paris Smaragdis */ /* Berklee College of Music Csound development team */ /* Copyright (c) December 1994. All rights reserved */ typedef struct { OPDS h; MYFLT *sr, *ain, *adel, *imaxd, *istod; uint32 maxd; AUXCH aux; int32 left; } VDEL; typedef struct { OPDS h; MYFLT *sr1, *sr2, *sr3, *sr4; MYFLT *ain1, *ain2, *ain3, *ain4, *adel, *imaxd, *iquality, *istod; AUXCH aux1, aux2, aux3, aux4; uint32 maxd; int interp_size; int32 left; } VDELXQ; typedef struct { OPDS h; MYFLT *sr1, *sr2, *ain1, *ain2, *adel, *imaxd, *iquality, *istod; AUXCH aux1, aux2; uint32 maxd; int interp_size; int32 left; } VDELXS; typedef struct { OPDS h; MYFLT *sr1, *ain1, *adel, *imaxd, *iquality, *istod; AUXCH aux1; uint32 maxd; int interp_size; int32 left; } VDELX; typedef struct { OPDS h; MYFLT *sr, *ain, *ndel[VARGMAX]; AUXCH aux; int32 left, max; } MDEL; #if 0 #define Combs 6 #define Alpas 5 typedef struct { OPDS h; MYFLT *out, *in, *time, *hdif, *istor; MYFLT *cbuf_cur[Combs], *abuf_cur[Alpas]; MYFLT c_time[Combs], c_gain[Combs], a_time[Alpas], a_gain[Alpas]; MYFLT z[Combs], g[Combs]; AUXCH temp; AUXCH caux[Combs], aaux[Alpas]; MYFLT prev_time, prev_hdif; } STVB; /* nreverb coded by Paris Smaragdis 1994 and Richard Karpen 1998 */ typedef struct { OPDS h; MYFLT *out, *in, *time, *hdif, *istor; MYFLT *cbuf_cur[Combs], *abuf_cur[Alpas]; MYFLT c_time[Combs], c_gain[Combs], a_time[Alpas], a_gain[Alpas]; MYFLT z[Combs], g[Combs]; AUXCH temp; AUXCH caux[Combs], aaux[Alpas]; MYFLT prev_time, prev_hdif; } NREV; #endif /* * Based on nreverb coded by Paris Smaragdis 1994 and Richard Karpen 1998. * Changes made to allow user-defined comb and alpas constant in a ftable. * Sept 2000, by rasmus ekman. * Memory allocation fixed April 2001 by JPff */ typedef struct { OPDS h; MYFLT *out, *in, *time, *hdif, *istor; MYFLT *inumCombs, *ifnCombs, *inumAlpas, *ifnAlpas; /* Used to be [Combs]- and [Alpas]-sized arrays */ int numCombs, numAlpas; MYFLT **cbuf_cur, **abuf_cur; MYFLT **pcbuf_cur, **pabuf_cur; MYFLT *c_time, *c_gain, *a_time, *a_gain; const MYFLT *c_orggains, *a_orggains; MYFLT *z, *g; /* [Combs] */ AUXCH temp; AUXCH caux, aaux; AUXCH caux2, aaux2; /* Used to hold space for all dynamized arrays */ MYFLT prev_time, prev_hdif; } NREV2; int vdelset(CSOUND *, VDEL *p); int vdelay(CSOUND *, VDEL *p); int vdelay3(CSOUND *, VDEL *p); int vdelxset(CSOUND *, VDELX *p); int vdelxsset(CSOUND *, VDELXS *p); int vdelxqset(CSOUND *, VDELXQ *p); int vdelayx(CSOUND *, VDELX *p); int vdelayxw(CSOUND *, VDELX *p); int vdelayxs(CSOUND *, VDELXS *p); int vdelayxws(CSOUND *, VDELXS *p); int vdelayxq(CSOUND *, VDELXQ *p); int vdelayxwq(CSOUND *, VDELXQ *p); int multitap_set(CSOUND *, MDEL *p); int multitap_play(CSOUND *, MDEL *p); #if 0 int nreverb_set(CSOUND *, NREV *p); int nreverb(CSOUND *, NREV *p); #endif int reverbx_set(CSOUND *, NREV2 *p); int reverbx(CSOUND *, NREV2 *p); csound-6.10.0/H/winEPS.h000066400000000000000000000023311321653344700146050ustar00rootroot00000000000000/* winEPS.h: write Postscript graphs Copyright (C) 1995 Fabio P. Bertolotti This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* */ /* Functions to write PS code */ /* */ /* Open PS file & write header */ void PS_MakeGraph(CSOUND *csound, WINDAT *wdptr, const char *name); /* Make one plot per page */ void PS_DrawGraph(CSOUND *csound, WINDAT *wdptr); int PS_ExitGraph(CSOUND *csound); /* Write PS trailer */ csound-6.10.0/H/windin.h000066400000000000000000000022101321653344700147240ustar00rootroot00000000000000/* windin.h: Copyright (C) 1991 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* WINDIN.H */ typedef struct { OPDS h; MYFLT *kxrslt, *kyrslt; MYFLT *iprd, *ixmin, *ixmax, *iymin, *iymax, *ixinit, *iyinit; int countdown, timcount; XYINDAT w; /* window specific data structure */ } XYIN; csound-6.10.0/How_to_Build_Csound_and_CsoundQt_on_Windows.doc000066400000000000000000003330001321653344700243300ustar00rootroot00000000000000ࡱ; 3 !"#$%&'()*+,-./01256789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~Root Entry   FMicrosoft Word-Dokument MSWordDocWord.Document.89qOh+'0 px Michael Gogins138@KS@@|E@0)e [llNormal$a$1$*$7$5$3$A$3B*OJ QJ CJmH sH KHPJnHtH^JaJ_H9~~ Heading 1'@& & F & F$a$1$$2OJQJCJ mH sH 5KHnHtH^JaJ _H9\ Heading 2'@& & F & F$a$1$$8OJQJCJmH sH 65KHnHtH^JaJ_H9]\~~ Heading 3'@& & F & F$a$1$$2OJQJCJmH sH 5KHnHtH^JaJ_H9\ Heading 4'@& & F & F$a$1$$8OJQJCJmH sH 65KHnHtH^JaJ_H9]\"" WW8Num1z0"" WW8Num1z1"" WW8Num1z2"!" WW8Num1z3"1" WW8Num1z4"A" WW8Num1z5"Q" WW8Num1z6"a" WW8Num1z7"q" WW8Num1z8:: WW8Num2z0OJQJCJPJ^JaJ.. WW8Num2z1 OJQJ^J:: WW8Num3z0OJQJCJPJ^JaJ.. WW8Num3z1 OJQJ^J66 WW8Num4z0OJQJCJ^JaJ.. WW8Num4z1 OJQJ^J"" WW8Num5z0"" WW8Num5z1"" WW8Num5z2"" WW8Num5z3"!" WW8Num5z4"1" WW8Num5z5"A" WW8Num5z6"Q" WW8Num5z7"a" WW8Num5z8.q. WW8Num2z4 OJQJ^J.. WW8Num3z4 OJQJ^JBBAbsatz-StandardschriftartHHWW-Absatz-StandardschriftartJJWW-Absatz-Standardschriftart1LLWW-Absatz-Standardschriftart11NNWW-Absatz-Standardschriftart111PP WW-Absatz-Standardschriftart1111RR!WW-Absatz-Standardschriftart11111TT"WW-Absatz-Standardschriftart111111VV#WW-Absatz-Standardschriftart1111111X!X$WW-Absatz-Standardschriftart11111111Z1Z%WW-Absatz-Standardschriftart111111111\A\&WW-Absatz-Standardschriftart1111111111^Q^'WW-Absatz-Standardschriftart11111111111`a`(WW-Absatz-Standardschriftart111111111111bqb)WW-Absatz-Standardschriftart1111111111111dd*WW-Absatz-Standardschriftart11111111111111ff+WW-Absatz-Standardschriftart111111111111111hh,WW-Absatz-Standardschriftart1111111111111111jj-WW-Absatz-Standardschriftart11111111111111111ll.WW-Absatz-Standardschriftart111111111111111111nn/WW-Absatz-Standardschriftart1111111111111111111pp0WW-Absatz-Standardschriftart11111111111111111111rr1WW-Absatz-Standardschriftart111111111111111111111tt2WW-Absatz-Standardschriftart1111111111111111111111vv3WW-Absatz-Standardschriftart11111111111111111111111x!x4WW-Absatz-Standardschriftart111111111111111111111111z1z5WW-Absatz-Standardschriftart1111111111111111111111111|A|6WW-Absatz-Standardschriftart11111111111111111111111111~Q~7WW-Absatz-Standardschriftart111111111111111111111111111a8WW-Absatz-Standardschriftart1111111111111111111111111111q9WW-Absatz-Standardschriftart11111111111111111111111111111:WW-Absatz-Standardschriftart111111111111111111111111111111;WW-Absatz-Standardschriftart1111111111111111111111111111111<WW-Absatz-Standardschriftart11111111111111111111111111111111=WW-Absatz-Standardschriftart111111111111111111111111111111111>WW-Absatz-Standardschriftart1111111111111111111111111111111111?WW-Absatz-Standardschriftart11111111111111111111111111111111111@WW-Absatz-Standardschriftart111111111111111111111111111111111111AWW-Absatz-Standardschriftart1111111111111111111111111111111111111BWW-Absatz-Standardschriftart11111111111111111111111111111111111111CWW-Absatz-Standardschriftart111111111111111111111111111111111111111!DWW-Absatz-Standardschriftart11111111111111111111111111111111111111111EWW-Absatz-Standardschriftart111111111111111111111111111111111111111112A2Numbering SymbolsJUQJ Internet Link B* phmHsH>*nHtH_H:a: Source TextOJQJCJPJ^J.q.BulletsOJQJPJ^JZVZVisited Internet Link B* phmHsH>*nHtH_HffHeadingY$a$1$$0OJQJCJmH sH KHPJnHtH^JaJ_H9dBd Text BodyZ$a$1$s,OJ QJ CJmH sH KHnHtH^JaJ_H9Z/ZList[$a$1$s,OJ QJ CJmH sH KHnHtH^JaJ_H9h"hCaption\$a$1$xx $2OJ QJ CJmH sH 6KHnHtH^JaJ_H9]VVIndex]$a$1$ $,OJ QJ CJmH sH KHnHtH^JaJ_H9ZZCode^$a$1$,OJQJCJmH sH KHnHtH^JaJ_H9``Text_$a$1$xx2OJ QJ CJ$mH sH 6KHnHtH^JaJ_H9]j6jList 2`$a$1$^]`x,OJ QJ CJmH sH KHnHtH^JaJ_H9xxPreformatted Texta$a$1$0OJQJCJmH sH KHPJnHtH^JaJ_H9<"< Quotationsb^7]7`2>2Titlec$a$CJ85aJ8\:J:Subtitled$a$<xCJ$aJ$xDd!80&>E@Udofxldf:^}~,|3<;Ujj|Ɗ>$`UnknownUnknown Author_Bre_:BxRF1CDwy? !""##M$$*%%R&\''')7*h*+++,,,///2Q22d333X5557728=9h99U:v::b;;;~<<<l???B7BXBCCCEEEgEGGHHH*IIJ>JJ3K\K[MMMOO0Ps```Ehbhhi+jPjQjjjst"txXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX^`P^@`^`0^``^`^`^`^``^0`0^`OJQJCJ^JaJ ^8`8OJQJ^J% ^`OJQJ^J%^`OJQJCJ^JaJ ^p`pOJQJ^J% ^ ` OJQJ^J%^@ `@ OJQJCJ^JaJ ^ ` OJQJ^J% ^`OJQJ^J%^`OJQJCJ^JaJ ^8`8OJQJ^J% ^`OJQJ^J%^`OJQJCJ^JaJ ^p`pOJQJ^J% ^ ` OJQJ^J%^@ `@ OJQJCJ^JaJ ^ ` OJQJ^J% ^`OJQJ^J%^`OJQJCJ^JaJ ^8`8OJQJ^J% ^`OJQJ^J%^`OJQJCJ^JaJ ^p`pOJQJ^J% ^ ` OJQJ^J%^@ `@ OJQJCJ^JaJ ^ ` OJQJ^J% ^`OJQJ^J%^`.^8`8.^`.^`.^p`p.^ ` .^@ `@ .^ ` .^`.WW8Num2WW8Num3WW8Num4WW8Num5xxPGTimes New Roman5Symbol3&ArialiLiberation SerifTimes New Roman?4Courier New?&Courier New?4Courier New?4Courier NewGTimes New RomanE4Lucida Console/$F27?5Courier New/$F26GTimes New Roman5Mangal3$Arial5Symbol_ OpenSymbolArial Unicode MS_ OpenSymbolArial Unicode MS5Symbol74NSimSun_ OpenSymbolArial Unicode MS5SimSunBhބ;'_jWW_jWW' 0 05DyK yK http://download.qt.io/official_releases/qt/5.5/5.5.1/qt-opensource-windows-x86-mingw492-5.5.1.exeDyK yK `http://developer.android.com/develop/index.htmlDyK yK http://sourceforge.net/projects/boost/files/boost/1.59.0/boost_1_59_0.7z/downloadDyK yK ,http://www.cmake.org/DyK yK <http://cunit.sourceforge.net/DyK yK Phttp://www.zlatkovic.com/libxml.en.htmlDyK yK ~http://www.oasis-open.org/docbook/xml/4.5/docbook-xml-4.5.zipD-DyK yK http://sourceforge.net/project/downloading.php?group_id=21935&filename=docbook-xsl-1.76.1.zipDyK yK 2http://www.graphviz.org/DyK yK Jhttp://www.stack.nl/~dimitri/doxygenDyK yK Jhttp://www.stack.nl/~dimitri/doxygen-DyK yK http://sourceforge.net/p/csound/csound6-git/ci/29e5d7338d30a86dae4f2eed20f31d38dd73caff/tree/DyK yK @http://git-scm.com/download/winDyK yK Lhttp://www.gtk.org/download/index.phpDyK yK http://www.oracle.com/technetwork/java/javase/downloads/index.html DyK yK https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspxDyK yK http://sourceforge.net/projects/mingwbuilds/files/external-binary-packages/msys%2B7za%2Bwget%2Bsvn%2Bgit%2Bmercurial%2Bcvs-rev13.7z/downloadDyK yK phttp://www.python.org/ftp/python/2.7.3/python-2.7.3.msiDyK  yK Nhttp://www.qt.io/download-open-source/ section-2DyK yK ,http://www.scons.org/DyK yK Dhttp://www.swig.org/download.htmlDyK yK .https://cefbuilds.com/DyK yK jhttp://eigen.tuxfamily.org/index.php?title=Main_PageDyK yK ^http://www.fltk.org/software.php?VERSION=1.3.3DyK yK Xhttp://sourceforge.net/projects/fluidsynth/DyK yK vhttp://download.gna.org/getfem/html/homepage/download.htmlDyK yK :https://www.tug.org/texlive/DyK yK &http://luajit.org/DyK yK Jhttp://www.mega-nerd.com/libsndfile/DyK yK Jhttp://code.google.com/p/libmusicxmlDyK yK Nhttp://www.portaudio.com/usingsvn.htmlDyK yK Dhttp://portmedia.sourceforge.net/DyK yK Dhttp://portmedia.sourceforge.net/DyK yK Dhttp://portmedia.sourceforge.net/DyK yK lhttp://sourceforge.net/projects/libpng/?source=navbarDyK yK Vhttps://www.sourceware.org/pthreads-win32/DyK yK Vhttp://www.mega-nerd.com/SRC/download.htmlDyK yK Rhttps://ccrma.stanford.edu/software/stk/DyK yK |http://www.steinberg.net/en/company/3rd_party_developer.htmlIDyK yK |http://msdn.microsoft.com/en-us/windows/desktop/hh852363.aspxDyK yK Vhttp://sourceforge.net/projects/qutecsoundDyK Ffrontends/nwjs"frontends/nwjsDyK yK Jhttp://www.jrsoftware.org/isinfo.phpDyK yK Lhttp://nsis.sourceforge.net/Main_PageDyK yK >http://www.michael-gogins.com/ ՜.+,D՜.+,\M 0`Caolan80 2Dx}rrr* s/ .R/m5b^/ 4$.h /HR/ How to Build Csound 6 and CsoundQt on Windows Michael Gogins michael.gogins@gmail.com 12 November 2015 Introduction This document provides up to date instructions for building Csound and associated programs that go into the Windows installer for Csound on Windows. This document should be updated in reasonable detail with each release of Csound for Windows, and pushed to Git head. Csound uses Cmake for building, and uses an Inno Setup Compiler scripta similar installer but does not set any environment variables. There is also the option to make a Windows release by making the install target, and then zip up the entire install directory tree in file named according to the pattern csound-version-minorversion-win32.zip. to create the Windows installer, which attempts to bundle together with Csound all generally useful plugin opcodes, language interfaces, and the CsoundQt and NW.js front ends. Downloads, installations, and tasks are listed more or less in the order they should be performed. In the following, Updated means that the tool or component was updated to the latest good version at that date; Checked means that the tool or component was checked at that date but did not need to be updated as it was still at the latest good version; and Downloaded means that the tool or component was downloaded at that date but for some reason not built or installed.\ Please note, Cabbage is no longer included in the Windows installer at the request of its author, due to library incompatibility problems. Filesystem The conceit of these instructions is that Csound is built in a standard Linux environment (which is simulated using MSys), using the standard GNU compiler (which is MinGW). To assist us in this delusion: Toolchain binaries must go in the system path: either /usr/bin or /usr/local/bin for binaries that are designed for MinGW or MSys, or the usual Program Files directories for regular Windows programs. It doesn't really matter where the tool executables actually go, as long as they are in the system PATH environment variable. So they can go where their Windows installers by default puts them. Third party software that we simply install can go /usr/opt or else where their Windows installers by default puts them. For third party software that we build, we install sources into /usr/local/src. If there is an install target, we make the install targets which should, normally, end up in the more or less standard /usr/local/bin, /usr/local/lib, and /usr/local/include. If there is no install target, we leave the third party software where it was built. Note: /usr/local in this document is relative to the MSys directory and would actually be something like C:\msys\local. Code Generation Csound for Windows is built for the 32 bit CPU architecture (this will soon be changed to 64 bit CPU architecture!). Code is built optimized for release but also including debugging information. Code generation for all builds must be for release versions of all runtime libraries and all third party libraries. Not only all components of Csound and CsoundAC, but also all third-party libraries that Csound links with dynamically  including FLTK, PortAudio, and FluidSynth  must be built with code generated for propagating exceptions across image boundaries (dwarf2), and using the Posix threading model. However, CsoundQt is an exception, and is built with the Qt SDK for Microsoft C++, assuming Microsoft Visual Studio has been installed. That is because it includes the Chromium Embedded Framework which is best used as a prebuilt library, itself built with MSVC. In general, at least the following compiler options should be used for building all Csound related code: For Cmake, set build type to RelWithDebInfo. C Options -g -O2 -march=nocona -DNDEBUG -I/usr/local/include C++ Options -g -O2 -std=gnu++11 -march=nocona -DNDEBUG -I/usr/local/include Prefix If the build tool permits configuration an installation prefix, set it to /usr/local. Toolchain MinGW Compiler with Qt SDK Updated 16 October 2015. All C++ binaries that are packaged with Csound must be built with the same C++ ABI. In practice, this means building everything with the same compiler. The following will give you a functional build of the 32-bit MinGW C++ compiler plus a prebuilt version of the complete Qt SDK version 5.5.1:  HYPERLINK "http://download.qt.io/official_releases/qt/5.5/5.5.1/qt-opensource-windows-x86-mingw492-5.5.1.exe"http://download.qt.io/official_releases/qt/5.5/5.5.1/qt-opensource-windows-x86-mingw492-5.5.1.exe. Android Studio Updated 14 October 2015. Csound for Android and its dependencies must be built using Google's Android Studio, Android SDK, and Android Native Development Kit. All of these components may be installed by downloading Android Studio and using it to install the other components. Download Android Studio from  HYPERLINK "http://developer.android.com/develop/index.html"http://developer.android.com/develop/index.html. Update all the components required for your Android target, including the NDK and system image, as well as the Android support library. Boost Updated 17 October 2015. Parts of boost are required by CsoundAC. Install boost source code from  HYPERLINK "http://sourceforge.net/projects/boost/files/boost/1.59.0/boost_1_59_0.7z/download"http://sourceforge.net/projects/boost/files/boost/1.59.0/boost_1_59_0.7z/download. In a Windows command shell (NOT the MSys shell), change to the boost source directory, ensure that MinGW's gcc is in the PATH, and build boost: bootstrap.bat gcc b2.exe toolset=gcc In your build environment, set an environment variable BOOST_ROOT that points to the Boost directory. Then, test that Cmake can find boost with: cmake --find-package -DNAME=Boost -DCOMPILER_ID=GNU -DLANGUAGE=CXX -DMODE=EXIST If that works, then Cmake should be able to find boost when configuring for Csound. CMake Updated 16 October 2015. Csound itself is built using CMake. Install CMake from  HYPERLINK "http://www.cmake.org/"http://www.cmake.org/. You should export some environment variables to help Cmake find things in the MSys shell: export BOOST_ROOT=/d/msys/local/src/boost_1_55_0 export CMAKE_INCLUDE_PATH=/d/meys/local/include export CMAKE_LIBRARY_PATH-/d/msys/local/lib CUnit Updated 23 October 2015. CUnit is used to run unit tests for Csound. Install CUnit source code from  HYPERLINK "http://cunit.sourceforge.net/"http://cunit.sourceforge.net/ in /usr/local/src. Configure with ./bootstrap. Make with make. Install with make install. DocBook Updated 26 July 2013. DocBook is used to generate the Csound Reference Manual from XML source files. Install the current Windows build of xsltproc and libxml2 from  HYPERLINK "http://www.zlatkovic.com/libxml.en.html"http://www.zlatkovic.com/libxml.en.html into /usr/local. Install the current  HYPERLINK "http://www.oasis-open.org/docbook/xml/4.5/docbook-xml-4.5.zipD"http://www.oasis-open.org/docbook/xml/4.5/docbook-xml-4.5.zip DocBook XML DTDs. Copy this tree to one directory above the Csound manual directory. Install the current DocBook XSL stylesheets from  HYPERLINK "http://sourceforge.net/project/downloading.php?group_id=21935&filename=docbook-xsl-1.76.1.zip"http://sourceforge.net/project/downloading.php?group_id=21935&filename=docbook-xsl-1.76.1.zip into /usr/local/opt. Dot Updated 18 October 2015. Install ATT Graphviz from  HYPERLINK "http://www.graphviz.org/"http://www.graphviz.org Doxygen Updated 17 October 2015. Doxygen is used to generate the Csound API and CsoundAC API documentation from comments in the source code. Install the current version of Doxygen from  HYPERLINK "http://www.stack.nl/~dimitri/doxygen"http://www.stack.nl/~dimitri/doxyge HYPERLINK "http://www.stack.nl/~dimitri/doxygen"n. Git Updated 20 October 2016. Csound 6 source code is maintained in a Git repository at  HYPERLINK "http://sourceforge.net/p/csound/csound6-git/ci/29e5d7338d30a86dae4f2eed20f31d38dd73caff/tree/"http://sourceforge.net/p/csound/csound6-git/ci/29e5d7338d30a86dae4f2eed20f31d38dd73caff/tree/. Install Git from  HYPERLINK "http://git-scm.com/download/win"http://git-scm.com/download/win. GTK Updated 26 July 2013. Fluidsynth and perhaps some other third party packages require some GTK and GNU libraries not supplied with Msys. Download the all-in-one GTK+ stack from  HYPERLINK "http://www.gtk.org/download/index.php"http://www.gtk.org/download/index.php. Unzip it somewhere. Select all directories (bin, include, and the rest) and copy them into /msys/local. Java SDK Updated 8 April 2015. The Java SDK is used for generating Java bindings to the Csound API and CsoundAC. Some examples of Java programs using Csound also require the SDK. Java is also used to build Csound apps for iOS and Android. Install the Java SE SDK from  HYPERLINK "http://www.oracle.com/technetwork/java/javase/downloads/index.html"http://www.oracle.com/technetwork/java/javase/downloads/index.html. Microsoft Visual Studio Community Edition Updated 15 October 2015. CsoundQt must be built with the Microsoft C++ compiler, included in Visual Studio Community edition, which can be downloaded for free from  HYPERLINK "https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx"https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx. MSys Checked 17 October 2015. In addition to the compiler, building Csound and its dependencies requires some other tools. Install MSys from  HYPERLINK "http://sourceforge.net/projects/mingwbuilds/files/external-binary-packages/msys%2B7za%2Bwget%2Bsvn%2Bgit%2Bmercurial%2Bcvs-rev13.7z/download"http://sourceforge.net/projects/mingwbuilds/files/external-binary-packages/msys%2B7za%2Bwget%2Bsvn%2Bgit%2Bmercurial%2Bcvs-rev13.7z/download. This includes bison, flex, autotools and some other goodies. Edit the MSys etc/fstab file to map the MinGW directory to /mingw. Python Updated 16 October 2015. The Csound API has a Python interface, and some Csound examples use Python. Install Python 2.7.9 from  HYPERLINK "http://www.python.org/ftp/python/2.7.3/python-2.7.3.msi"http://www.python.org/. Please note, later versions of Python 2.7 do not work because of a bug in version detection. Create a MinGW import library for Python in the Python libs directory by running: gendef c:/Windows/system32/python27.dll dlltool --input-def python27.def --dllname python27 --output-lib libpython27.a Please note, this must be done every time the version of Python or the version of the MinGW compiler changes. Qt SDK for Microsoft C++ Updated 17 October 2015. The 32 bit Qt SDK for use with the Microsoft compiler can be obtained from an online installer downloaded from  HYPERLINK "http://www.qt.io/download-open-source/" \l "section-2"http://www.qt.io/download-open-source/#section-2. SCons Updated 17 October 2015. SCons (Software Construction) is a build system that is particularly easy to use. It is used here to make custom builds of some third-party software that lacks a Windows build system, or has a Windows build system that lacks features Csound needs.. Install SCons for Windows from  HYPERLINK "http://www.scons.org/"http://www.scons.org/. SWIG Updated 16 October 2015. SWIG is used for automatically generating the bindings to the Csound API and to CsoundAC for the Python, Java, and Lua programming languages. Install SwigWin from  HYPERLINK "http://www.swig.org/download.html"http://www.swig.org/download.html. Third Party Packages The most recent versions of all tools and third-party packages that are in general use should be used for Csound. Sometimes this is packaged as a released version, sometimes it is packaged as a beta version, sometimes it is always built from sources. If in doubt, search the World Wide Web or check mailing lists for the software. If the library does not come pre-built for Windows or with a functional build system for MSys/MinGW, create a CMake file for the library. Chromium Embedded Framework Updated 25 October 2015. CEF is embedded in CsoundQt to support Web pages integrated with Csound pieces. Download the prebuilt libraries and headers from  HYPERLINK "https://cefbuilds.com/"https://cefbuilds.com/, choosing the most recent non-development branch. Build the C++ wrapper library and examples for CEF using Cmake according to the instructions in CmakeLists.txt using Microsoft Visual Studio for 32 bit CPU architecture (x86), release version. You must use the same version of Visual C++ that was used to build the Qt SDK, and you must rebuild the wrapper library with the /MD compiler option instead of the default /MT. Eigen Updated 15 October 2015. Eigen is a C++ library for matrix arithmetic and linear algebra, used by CsoundAC. Install Eigen source code from  HYPERLINK "http://eigen.tuxfamily.org/index.php?title=Main_Page"http://eigen.tuxfamily.org/index.php?title=Main_Page in /usr/local/include. This is a header file-only library and does not need to be built or installed. FLTK Updated 16 October 2015. FLTK is used by the FLTK widgets opcodes. Install the latest FLTK 1.3 source code from  HYPERLINK "http://www.fltk.org/software.php?VERSION=1.3.3"http://www.fltk.org/software.php?VERSION=1.3.3 into /usr/local/src. Configure with cmake-gui cmake, setting CMAKE_INSTALL_PREFIX to D:/msys/local. Set CMAKE_BUILD_TYPE to RelWithDebInfo. Add -march=nocona to CFLAGS. Make with make. Install with make install. Fluidsynth Updated 17 October 2015. FluidSynth is used by the fluid opcodes to provide an all-in-one sampled synthesis solution for Csound. Install FluidSynth source code from  HYPERLINK "http://sourceforge.net/projects/fluidsynth/"http://sourceforge.net/projects/fluidsynth/ in /usr/local/src. Csound does not require any of FluidSynth's internal audio or soundfile drivers. Configure with ./configure --disable-portaudio-support. Make with make CFLAGS=-DDEFAULT_SOUNDFONT='\"c:/soundfonts/default.sf2\"'. Install with make install. gmm++ Updated 16 October 2015. The linear algebra opcodes use gmm++ to implement efficient matrix arithmetic and some matrix decompositions. Yes, Csound can do eigenvalue decompositions! Download the gmm++ standalone source code from  HYPERLINK "http://download.gna.org/getfem/html/homepage/download.html"http://download.gna.org/getfem/html/homepage/download.html. This is a header file only library. Install the gmm-5.n/include/gmm directory into /usr/local/include. LaTeX Checked 18 October 2015. LaTeX is used for typesetting the Csound and Csound AC tutorials that are included in the Windows release. Install TeX Live from  HYPERLINK "https://www.tug.org/texlive/"https://www.tug.org/texlive/ LuaJIT Updated 23 October 2015. The Csound API has a Lua interface, and the Lua opcodes require LuaJIT in particular, which is bundled with the Csound Windows distribution. Install LuaJIT source code from  HYPERLINK "http://luajit.org/"http://luajit.org/ in /usr/src. Build LuaJIT with make. Install with make install. libsndfile Checked 15 October 2015. This is required by Csound for reading and writing soundfiles. It is a pre-built library. Install libsndfile from  HYPERLINK "http://www.mega-nerd.com/libsndfile/"http://www.mega-nerd.com/libsndfile/ in /usr/opt. MusicXML Updated 23 October 2015. MusicXML is used by the CppSound class in the Csound API to import MusicXML files. Install the MusicXML source code in /usr/local with git clone  HYPERLINK "http://code.google.com/p/libmusicxml"http://code.google.com/p/libmusicxml. Configure with cmake-gui cmake, setting CMAKE_INSTALL_PREFIX to D:/msys64/mingw64. Set CMAKE_BUILD_TYPE to RelWithDebInfo. Add -march=nocona to CFLAGS. Make with make in the cmake directory. Install with make install in the cmake directory. OpenSoundControl Updated 23 October 2015. Csound uses the OpenSoundControl protocol in the OSC opcodes for low-latency network communications to and from Csound. Update liblo tag 0.26 from the tarball at (not SVN!). First, configure with ./configure  prefix=/msys/local --enable-static --disable-shared. Make with make. Install with make install. PortAudio Updated 19 October 2015. Install PortAudio source code from  HYPERLINK "http://www.portaudio.com/usingsvn.html"http://www.portaudio.com/usingsvn.html into /usr/local/src. Copy the dsound.h file from the STK src/include directory into the MinGW include directory. Execute autoreconf -if to regenerate all the autotools files. Configure with ./configure - with-winapi=wmme,directx,asio - with-asiodir=/usr/local/src/asiosdk2  with-gnu-ld=yes  enable-static  disable-shared. Make with make. This makes static libraries, but not a regular dynamic link library. Install with make install. PortMidi Updated 24 October 2014. Csound can use the PortMidi library for MIDI input and output. Install the PortMedia source code from  HYPERLINK "http://portmedia.sourceforge.net/"http://portmedia.sourceforge.net. Configure with cmake-gui. Make with make. There is no install target for make, set locations in Csound's Cmake build. Run the test programs to ensure that the build works. PortSMF Updated 24 October 2015. PortSMF is used by CsoundAC for importing and exporting standard MIDI files (format 1). Install the PortMedia source code from  HYPERLINK "http://portmedia.sourceforge.net/"http://portmedia.sourceforge.net. Configure with ./configure. Make with make. Install with make install. It is still possible to unset xxx. In that case, the PortSMF source code has been incorporated into the Csound 6 Git repository. From time to time, replace the Csound 6 sources with current PortSMF sources from  HYPERLINK "http://portmedia.sourceforge.net/"http://portmedia.sourceforge.net/. Pure Data Checked 23 October 2015. Install Pure Data source code using Git from git://pure-data.git.sourceforge.net/gitroot/pure-data/pure-data into usr/local/src. PNG and LIBZ Updated 23 October 2015. The LIBZ compression library is used by PNG. To enable Cmake to find the library, it is necessary to build it from sources and install it. Follow the instructions in the source directory. The PNG library is used by the image opcodes. To enable Cmake to find PNG, it is necessary to build it from sources and install it. Install the latest release sources from  HYPERLINK "http://sourceforge.net/projects/libpng/?source=navbar"http://sourceforge.net/projects/libpng/?source=navbar in /usr/local/src. Configure with ./configure. Build with make. Install with make install. Pthreads Updated 23 October 2015. Download the Pthreads for Windows variant from  HYPERLINK "https://www.sourceware.org/pthreads-win32/"https://www.sourceware.org/pthreads-win32/, install it in /usr/opt, and configure it in Csound's Cmake build. Secret Rabbit Code Updated 23 October 2015. Csound can use this for sample rate conversions. Download from  HYPERLINK "http://www.mega-nerd.com/SRC/download.html"http://www.mega-nerd.com/SRC/download.html and copy to /usr/local/src. Configure with ./configure. Make with make. Install with make install. Synthesis Toolkit in C++ (STK) Updated 23 October 2015. Install the STK source code from  HYPERLINK "https://ccrma.stanford.edu/software/stk/"https://ccrma.stanford.edu/software/stk/ in /usr/local/src. Configure with ./configure RAWWAVE_PATH=. --enable-static  -disable-shared Make with make (not mingw32-make). Install with make install. Steinberg Proprietary SDKs Updated 16 November 2014. Steinberg's VST SDK is used by CsoundVST and the vst4cs opcodes, the VSTModuleArchitectureSDK is used for the ScoreGenerator VST plugin that is part of CsoundAC, and the ASIO SDK is used by the PortAudio library that Csound uses for real-time audio input and output. Install the VST SDK 2.4 from  HYPERLINK "http://www.steinberg.net/en/company/3rd_party_developer.htmlI"http://www.steinberg.net/en/company/3rd_party_developer.html in /usr/local/src/Steinberg. Install the ASIO SDK version 2.3 in /usr/local/src/asiosdk2 Please note, these SDKs are proprietary software and you must agree to Steinberg's license terms for use. Windows SDK The Windows SDK for Windows 8 contains header files and libraries that used to belong to the DirectX SDK, and that are used by some third-party dependencies of Csound, such as PortAudio, which we have to build. Install the Windows SDK from  HYPERLINK "http://msdn.microsoft.com/en-us/windows/desktop/hh852363.aspx"http://msdn.microsoft.com/en-us/windows/desktop/hh852363.aspx. Currently, this does not include Visual Studio, but that is OK. Building Csound 6 Create and/or update a shell script to set up all environment variables and paths for building Csound and for running Csound from and in the build environment. This is an example of such a script (6env): #!/bin/sh echo "Configure for development..." export PATH=${PATH}:/c/Program_Files_x86/SciTE export PATH=${PATH}:/c/Program_Files_x86/Git/bin export PATH=${PATH}:/c/mingw32-4.7.2/msys/1.0/local/bin export PATH=${PATH}:/c/Program_Files_x86/swigwin-2.0.10 export PATH=${PATH}:/c/Python27 echo "Configure for Android/ARM, armeabi-v7a (ARMv7 VFP), Android 2.3.3+///" export SDK=/d/Android/adt-bundle-windows-x86-20130514/sdk export NDK=/d/Android/android-ndk-r8e export ANDROID_NDK_ROOT=$NDK export CSOUND_HOME=/c/Users/new/csound-csound6-git export NDK_MODULE_PATH=${CSOUND_HOME}/android/pluginlibs export PATH=${PATH}:$NDK_MODULE_PATH export NDKABI=9 export NDKVER=$NDK/toolchains/arm-linux-androideabi-4.7 export NDKP=$NDKVER/prebuilt/windows/bin/arm-linux-androideabi- export NDKF="--sysroot $NDK/platforms/android-$NDKABI/arch-arm" export NDKARCH="-march=armv7-a -mfloat-abi=softfp -Wl,--fix-cortex-a8" echo "Configure shared libraries and programs needed to run Csound..." export PATH=${PATH}:/c/mingw32-4.7.2/msys/1.0/opt/Mega-Nerd/libsndfile/bin export PATH=${PATH}:/c/mingw32-4.7.2/msys/1.0/local/src/portaudio export PATH=${PATH}:/c/mingw32-4.7.2/msys/1.0/local/src/portmidi export PATH=${PATH}:/c/mingw32-4.7.2/msys/1.0/local/src/fluidsynth/src/.libs export PATH=${PATH}:/c/mingw32-4.7.2/msys/1.0/local/src/libmusicxml-3.00-src/cmake export PATH=${PATH}:/c/mingw32-4.7.2/msys/1.0/local/src/luajit-2.0/src export PATH=${PATH}:/c/Program_Files/Modartt/Pianoteq\ 4 export PATH=${PATH}:/c/Program_Files/BWF_MetaEdit_CLI_Windows_x64 export PATH=${PATH}:/c/Program_Files_x86/sox-14-4-1 export PATH=${PATH}:/c/Program_Files_x86/Audacity export PATH=${PATH}:/c/Program_Files_x86/Lame\ For\ Audacity export PATH=/c/Users/new/csound-csound6-git:${PATH} echo "Configure environment variables needed to run Csound..." export OPCODE6DIR64=/c/Users/new/csound-csound6-git export RAWWAVE_PATH=/c/mingw32-4.7.2/msys/1.0/local/src/stk-4.4.4/rawwaves export PYTHONPATH=/c/Users/new/csound-csound6-git echo "Configure environment variables needed to run LuaJIT with ufo libraries..." export LUA_PATH="./?.lua;../?.lua;D:/ufo/?.lua;D:/ufo/ffi/?.lua;D:/ufo/bin/Windows/x86/?.lua;" export LUA_CPATH="D:/ufo/?;D:/ufo/bin/?;" export PATH=${PATH}:/d/ufo/bin echo In the Msys shell, change to the Csound root directory and execute source 6env to actually create your Csound environment. Update the Csound source code by executing git pull. Execute cmake-gui . & to configure your Cmake build system for your environment. When using CMake, generate MSys makefiles, not MinGW makefiles. Pay attention to CMake's error messages. It may be that a variable for an include path or library is missing from the initial state of the cache. Go ahead and add the variable called for by the error message. Configure for double-precision samples. At this time, there is a serious problem with the Java interface on Windows: the SWIG generated C++ file interfaces/java_interfaceJAVA_wrap.cxx defines long long long, a type that is not supported by MinGW and which breaks the build. Here is the workaround: At about line 33 of C:\Program_Files_x86\swigwin-3.0.n\Lib\java\javahead.swg, comment out the line typedef long long __int64: /* Fix for jlong on some versions of gcc on Windows */ #if defined(__GNUC__) && !defined(__INTEL_COMPILER) //typedef long long __int64; #endif Change to examples/java and execute make to build the Java example jars. Building the Csound Reference Manual Build the examples for the manual using a command line such as python csd2docbook.py -a. Build the manual itself using a command line such as mingw32-make html-dist XSL_BASE_PATH=/d/msys/local/opt/docbook-xsl-1.76.1. Build the API reference by executing cd doc; doxygen Doxyfile; doxygen Doxyfile-CsoundAC. Building CsoundQt In the Csound build environment, obtain the CsoundQt source from SourceForge at  HYPERLINK "http://sourceforge.net/projects/qutecsound"http://sourceforge.net/projects/qutecsound using git: git clone git://git.code.sf.net/p/qutecsound/code qutecsound-code In the CsoundQt source directory create a config.user.pri file containing paths to third party packages customized for your Csound build environment, such as: CSOUND_INTERFACES_INCLUDE_DIR = C:\\Users\\new\\csound-csound6-git\\interfaces DEFAULT_CSOUND_API_INCLUDE_DIRS = C:\\Users\\new\\csound-csound6-git\\include C:\\Users\\new\\csound-csound6-git\\interfaces DEFAULT_CSOUND_LIBRARY_DIRS = "C:\\Users\new\\csound-csound6-git" DEFAULT_LIBSNDFILE_INCLUDE_DIRS = "C:\\mingw32-4.7.2\\msys\\1.0\\opt\\Mega-Nerd\\libsndfile\\include" DEFAULT_LIBSNDFILE_LIBRARY_DIRS = "C:\\mingw32-4.7.2\\msys\\1.0\\opt\\Mega-Nerd\\libsndfile\\bin" build32: DEFAULT_CSOUND_LIBS = csound32.dll build64: DEFAULT_CSOUND_LIBS = csound64.dll LIBSNDFILE_LIB = libsndfile-1.dll DEFAULT_PYTHON_INCLUDE_DIRS = "C:\\Python27\\include" DEFAULT_PYTHONQT_SRC_DIRS = "$$(PROGRAMFILES)\\PythonQt" Because it now is built with the Chromium Embedded Framework, CsoundQt must be compiled using Microsoft Visual C++, the same version as used to build CEF, for 32 bit CPU architecture. Therefore, you must first create a Visual C++ import library for Csound with something like this in the Visual C++ command shell: @echo CREATING MICROSOFT IMPORT LIBRARY FOR CSOUND64.DLL dumpbin /exports %CSOUND_HOME%\csound64.dll > exports.txt @echo LIBRARY CSOUND64 >> %CSOUND_HOME%\csound64.def @echo EXPORTS >> %CSOUND_HOME%\csound64.def FOR /F "skip=19 tokens=4" %%l in (exports.txt) do @echo %%l >> %CSOUND_HOME%\csound64.def lib /def:%CSOUND_HOME%\csound64.def /out:%CSOUND_HOME%\csound64.lib /machine:x86 Then run QtCreator, load the qcs project, run qmake, and build the project. It will not run unless all required DLLs are present in the build directory, and in the proper directory layout too, along with the CEF runtime. Build csound.node See the README.md in  HYPERLINK "frontends/nwjs"C:\Users\mike\csound-csound6-git\frontends\nwjs. Run Tests After building all targets, change to the root of the build directory and run make test, continuing through crashes and exceptions. Then run make csdtests., also continuing through crashes and exceptions. If too many tests fail, you probably need to fix something. Building the Installer Build the installer using Inno Setup Compiler NSIS from  HYPERLINK "http://www.jrsoftware.org/isinfo.php"http://www.jrsoftware.org/isinfo.php HYPERLINK "http://nsis.sourceforge.net/Main_Page"nsis.sourceforge.net/Main_Page with the NONFREE (VST) stuff. The deployment of CsoundQt takes special care. The Qt libraries load some DLLs through dynamic linking and other DLLs as plugin modules. There are no helpful error messages or logs. Either the Qt plugins load, or they don't and the application crashes. It seems the only way to get it straight is: Use the Dependency Walker utility to identify the dynamically linked Qt DLLs and put them into the Csound bin directory. Use the Process Explorer utility to identify the Qt plugins that CsoundQt loads when it is running. These go into specific subdirectories of the Csound bin directory as follows. Having too many Qt libraries apparently is as bad as not having the required ones. Currently the list of Qt libraries is: mkg@sorabji /c/Program_Files_x86/csound6/bin $ ls -ll Qt*.dll platforms plugins/* -rwxr-xr-x 1 mkg Administrators 9527492 Jul 25 23:22 Qt5Core.dll -rwxr-xr-x 1 mkg Administrators 9678079 Jul 25 23:26 Qt5Gui.dll -rwxr-xr-x 1 mkg Administrators 783361 Jul 25 23:32 Qt5PrintSupport.dll -rwxr-xr-x 1 mkg Administrators 12456443 Jul 25 23:31 Qt5Widgets.dll -rwxr-xr-x 1 mkg Administrators 611324 Jul 25 23:23 Qt5Xml.dll platforms: total 2354 -rwxr-xr-x 1 mkg Administrators 2409481 Aug 2 19:27 qwindows.dll plugins/accessible: total 605 -rwxr-xr-x 1 mkg Administrators 618749 Aug 2 19:27 qtaccessiblewidgets.dll plugins/imageformats: total 2450 -rwxr-xr-x 1 mkg Administrators 131180 Aug 2 19:27 qgif.dll -rwxr-xr-x 1 mkg Administrators 135293 Aug 2 19:27 qico.dll -rwxr-xr-x 1 mkg Administrators 409066 Aug 2 19:27 qjpeg.dll -rwxr-xr-x 1 mkg Administrators 628497 Aug 2 19:27 qmng.dll -rwxr-xr-x 1 mkg Administrators 132618 Aug 2 19:27 qsvg.dll -rwxr-xr-x 1 mkg Administrators 197247 Aug 2 19:27 qsvgicon.dll -rwxr-xr-x 1 mkg Administrators 128440 Aug 2 19:27 qtga.dll -rwxr-xr-x 1 mkg Administrators 618469 Aug 2 19:27 qtiff.dll -rwxr-xr-x 1 mkg Administrators 123177 Aug 2 19:27 qwbmp.dll plugins/printsupport: total 102 -rwxr-xr-x 1 mkg Administrators 103642 Jul 25 23:34 windowsprintersupport.dll Build the installer again, this time without the NONFREE stuff. Perform functional tests below. Update this document to reflect any changes in procedure or dependencies. Upload the free software installer to SourceForge and update the release package. Upload the NONFREE installer to  HYPERLINK "http://www.michael-gogins.com/"http://www.michael-gogins.com/. Building for Android Install Android Studio. Use its SDK Manager to upgrade to recent tools and libraries, including the support libraries. Currently Csound for Android runs on Android 5 but it no longer runs on Android 4. The log reports that missing srand causes the .so's to fail to load. This appears to be a bug in Android Studio choosing the wrong libraries to install in the apk file. In the MSys shell, change to the csound/android directory. Execute ./build-all-mkg.sh clean. Execute ./build-all-mkg. Run Android Studio and load the csound/android/CsoundForAndroid/CsoundForAndroid project. You may need to monkey with the .idea files as they may need to be told which modules are really modules. Invalidate the caches and reload. Sync with gradle. Connect your Android 5 or higher device to your computer with a USB cable. Run the Csound for Android app from Android Studio. To Do Android Update Android app's built-in user guide (done). Upload. Update FLOSS manual's Android section. CsoundQt Try to get HTML to display immediately upon loading the piece (done). Try passing JavaScript callbacks into CsoundQt. Installer Build installer. Test. Upload.  &FJLjlx    " * , D F L N ^ ` l   Z  d   48:BDPRVXbdпCJ65aJ]\!CJ^JaJOJQJcHdhj;CJaJcHdhj;CJaJHhj;CJPJ^JaJCJaJ ^JOJQJPJ^JGdhjln~  $&248:H*.0 <@\h:DH\(J>@DFPCJ65aJ]\ ^JOJQJ 65]\CJPJ^JaJOJQJCJ6aJ]CJPJ^JaJCJaJH &(68HJNPVXfhz|     " $ , . 4 6 L N ` b j l x z !!!CJPJ^JaJCJaJCJ65aJ]\CJ65PJ^JaJ]\U!!!! !"!*!,!4!6!H!J!P!R!h!j!~!!!!!!"R"$$(%D%F%Z%%%X&&'^''))***++++++.. ......080¯“0JUCJPJ^JaJj5UCJPJ^JaJ0JUCJPJ^JaJjUUCJ65PJ^JaJ]\CJPJ^JaJOJQJ ^JOJQJCJ65aJ]\CJaJCJPJ^JaJ98000111.202X3z334$44f56N66677727479J9996:8:::t:v:~::::::;(;:;h;<<<<<<@=B=N=b===&>jeUCJaJ ^JOJQJjUjUCJ65PJ^JaJ]\ ^JOJQJB0JV:;B*phCJ@65fHq ^JaJOJQJ0JUjUU7&>(>*>>>> ? ???,?.?:?D@DDDDDDDDDD2EEEjUjUjBUCJ65PJ^JaJ]\ ^JOJQJjUPJ^JCJ^JaJOJQJCJPJ^JaJCJaJ0JUUj&U>E|F~FF:GNNNOOPPP2Q4Q8QBQvQTRVRSSSTT"U@Uۻۻj UCJPJ^JaJ0JUCJPJ^JaJj UCJPJ^JaJj U ^JOJQJj9 UCJ65PJ^JaJ]\j U0JUUj[ U9@URUUUUUUVVBWDWFWrWtWvWXXX(YYZ[[[l\n\p\\\\\]F_H________BaDaaaaaabbddٱCJmH sH aJCJaJCJ65aJ]\jUj9U0JUCJPJ^JaJjbU0JV ^JOJQJ0JUjUUCJ65PJ^JaJ]\CJPJ^JaJCJPJ^JaJOJQJ3ddddddddddde"e$e&e(eeHeJeVeXe^etevexeeeeeeeeee*f2g4gzg|g~gggjjjjk8klllll mmm:mmnnn@oBoDooojU ^JOJQJj*UCJ65PJ^JaJ]\ ^JOJQJ0JUjUU 65]\CJmH sH aJCJmH sH PJ^JaJBoooopp p pHpPpjpvpppppppppqq4qLqdqqrr"s$s&s|s~ssshttttLuluuuuu\w^wwwwdxfxҿjU 65]\ ^JOJQJ0JUjUUCJ65PJ^JaJ]\CJ^JaJOJQJ%:;B*ph@65^JOJQJ:;B*ph@65%:;B*ph@65^JOJQJ ^JOJQJ ^JOJQJ3fxxxy6yDyxyzz|zzzz { {{N{|||||}}},}V}^}|}}}}~~(*,tv~Ȁ܀`bdЁ*2T`0JU^JOJQJjU ^JOJQJjU 65]\j/U0JUjUUCJ65PJ^JaJ]\ ^JOJQJ>Ȃ҂ނJbr|p 0H^؆چ@BDЇP^08 >Ћ֋l·آCJPJ^JaJCJaJ):;B* ph.46CJ@65^JOJQJ0JUj<UUB*phCJ^J OJ QJ 65]\ ^JOJQJ:;B*ph@65%:;B*ph@65^JOJQJ7lnpԌ"0HP̍΍ҍԍNDNP*BJh*,ΒВ0JUjeU ^JOJQJjUCJPJ^JaJ 65]\PJ^JOJQJPJ^JOJQJPJ^J ^JOJQJ0JUCJPJ^JaJ0JUCJPJ ^J aJUjU;*,46>@VXbltv6h:<—ė.08TXxΘ,TVv4$&(|~֜ *DdjU ^JOJQJ0JUjU ^JOJQJ0JU^JOJQJjUU ^JOJQJ 0JUPJ ^J PJ^J 65]\CdfhĞ<|Ÿ0dLNPȣʣԣPl~RLN`bʼj5 U0JUB*>*PJ ^J 0JUB*>*PJ ^JOJQJ0JUB*>*^JOJQJ 0JUB*>* 0JUPJ ^J jHUPJ^J 65]\6^J]OJQJ ^JOJQJ ^JOJQJ0JUUjU7нV $&.046@T\bdn8hlvx~hjvx~ ^JOJQJPJ^JOJQJCJ 6aJ ]CJ aJ PJ^JCJPJ ^JaJOJQJCJPJ^JaJCJaJPJ ^JOJQJEDVXZ$&Xr~TVXf}r0JUCJPJ^JaJj"UCJPJ^JaJcHdhj;CJPJ^JaJHhj;CJPJ^JaJCJaJOJ QJ j!U ^JOJQJ0JUj"!UUCJ aJ CJPJ ^J aJ%CJPJ ^JaJOJQJHhj;CJPJ ^JaJOJQJ,f HJV\^lnxz$(Ndpt"&L`&<0&"r~ʸŭŭŨʟCJPJ ^J aJCJaJCJ^JaJOJQJCJPJ ^JaJOJQJCJaJCJPJ^JaJ!0JUCJPJ ^J aJcHdhj;jd#UU!0JUCJPJ^JaJHhj;>$&2@BJL\^bdrtz| *,24@BHJXZxzDFBLdj&D: ^JOJQJ0JUj!$UUPJ^JCJPJ ^JaJOJQJCJaJCJPJ^JaJP:D^ ^JOJQJ\z   2<,Z Z & F^]`Z & FZ & FZZZZZZZZ & F & F$a$ & F$a$ & F$a$  & F$a$,L"$$H%\%%%Z&h&'('`'++/0062V3X3|3aaZZZZZZ & FZZ & FZZZZZ & F|33p44h5666:777R88 999::,;<;ZZZZ^^^^ZZZ & FZZZZ-ad$a$$dN%dO&dP'dQ<;<f=R?vA~AfBvBCDEBGHH IJ KbLLHNN:QDQ$UUUZZZZZZZZZZZZZ & FZZZZUV4XXX*YYZZ\\___aabbdeefhijZZZZZZZ & FZZZZZ & FZaaaZZZjkk@mmmnnopqPqfqhrstPuuuvlx:yFy{{j|ZZZZZZZZZZZZZZZZZZ & Fj|2}b}}}~0؄DL`vƊZZZZZZZZZZZZZZZZZ & FZZZƊ .N֒8jZZZZZZZZZZZZZZZZZZZZ & FZޚFƟ2|Tl Z & FZZZZZZZZZZZZZZZZ & FZbī4B|T..^^^^^^^^^^^^^^^^^^^^^^^^LNh**z\^ܸ޸Fܹ@B^^^^^^^^^^^^^^^^^^^^^^^^8BD:*pl FNZ^ZZZ & FZ^^]`^^]`^^]`^^]`ZZZZZ^^^^,&v:.0j,<`*>Z & FZ^^^^^^Z^^^^^^^^^^^^>R&Pfrt$^^]`^^]`^^]`^^]`^^]`^^]`^^]`^^]`^^]`^^]`^^]`Z & FZZ & FZ$&Nb(>2($^^]`^^]`^^]`^^]`^^]`^^]`^^]`^^]`^^]`^^]`^^]`^^]`^^]`^^]`^^]`t4lJtbZF6ZZZZZZZZZ & FZZZZZ^^]`^^]`^^]`^^]`^^]`4@P""DP`Z & FZ & F & FZ 0/ =!n"n#n$n2P1h0p3P(20Root Entry FCompObjjOle 1Table7Data  $SummaryInformation(DWordDocument42DDocumentSummaryInformation8 tcsound-6.10.0/INSTALLING000066400000000000000000000006651321653344700144770ustar00rootroot00000000000000INSTALLING CSOUND 6 To install prebuilt binaries for Linux on Intel, Windows, and OS X, obtain the appropriate archive or installer from the Files page at http://sourceforge.net/projects/csound. To build from sources using the Csound GIT repository at Github or using a source archive, follow the instructions in the BUILD.md file. NOTE: For Windows, follow the instructions in "How_to_Build_Csound_on_Windows.doc" in Csound 6 GIT. csound-6.10.0/InOut/000077500000000000000000000000001321653344700141375ustar00rootroot00000000000000csound-6.10.0/InOut/CMakeLists.txt000066400000000000000000000225731321653344700167100ustar00rootroot00000000000000# REAL TIME AUDIO AND MIDI message(STATUS "") message(STATUS "## REALTIME AUDIO AND MIDI ##") option(USE_PULSEAUDIO "Build the PulseAudio I/O module" ON) option(USE_PORTAUDIO "Build the PortAudio I/O module" ON) option(USE_PORTMIDI "Build the PortMIDI I/O module" ON) option(USE_IPMIDI "Build the IPMIDI I/O module" ON) option(USE_JACK "Build the jack I/O module and opcodes" ON) option(USE_ALSA "Build the ALSA I/O module" ON) # option(USE_COREAUDIO "Build the CoreAudio I/O module" ON) option(USE_COREMIDI "Build the CoreMIDI I/O Module" ON) option(USE_AUDIOUNIT "Build the CoreAudio AudioUnit I/O module (requires CoreAudio)" ON) option(USE_FLTK "Use FLTK for graphs and widget opcodes" ON) option(BUILD_VIRTUAL_KEYBOARD "Build Virtual MIDI keyboard" ON) option(NEED_PORTTIME "porttime library separate from portmidi" ON) set(CMAKE_REQUIRED_INCLUDES /usr/local/include) # FIND LIBRARIES AND HEADERS if(USE_ALSA) find_library(ALSA_LIBRARY asound) check_include_file(alsa/asoundlib.h ALSA_HEADER) endif() if(USE_PORTAUDIO) find_path(PORTAUDIO_INCLUDE_PATH portaudio.h) find_library(PORTAUDIO_LIBRARY NAMES portaudio portaudio_x64) if(PORTAUDIO_INCLUDE_PATH AND PORTAUDIO_LIBRARY) try_run(PORTAUDIO_V19 PORTAUDIO_TEST_COMPILED ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/portaudio_test.c CMAKE_FLAGS -DLINK_LIBRARIES:STRING=${PORTAUDIO_LIBRARY} COMPILE_DEFINITIONS "-I${PORTAUDIO_INCLUDE_PATH}" COMPILE_OUTPUT_VARIABLE OUTPUT) if(NOT PORTAUDIO_TEST_COMPILED AND NOT WIN32) set(PORTAUDIO_V19 false) endif() else() set(PORTAUDIO_V19 false) endif() endif() if(USE_PORTMIDI) find_path(PORTMIDI_INCLUDE_PATH portmidi.h) find_library(PORTMIDI_LIBRARY portmidi) if(NOT WIN32) if(NEED_PORTTIME) find_library(PORTTIME_LIBRARY porttime) endif() endif() endif() if(USE_JACK) find_library(JACK_LIBRARY jack) find_library(JACKDMP_LIBRARY jackdmp) check_include_file(jack/jack.h JACK_HEADER) endif() if(USE_PULSEAUDIO) find_library(PULSEAUDIO_LIBRARY pulse) find_library(PULSESIMPLE_LIBRARY pulse-simple) check_include_file(pulse/simple.h PULSEAUDIO_HEADER) endif() # if(USE_COREAUDIO) # find_path(COREAUDIO_INCLUDE_PATH CoreAudio.h) # find_library(COREAUDIO_LIBRARY CoreAudio) # endif() if(USE_COREMIDI) find_path(COREMIDI_INCLUDE_PATH CoreMidi.h) find_library(COREMIDI_LIBRARY CoreMidi) find_library(COREFOUNDATION_LIBRARY CoreFoundation) endif() if(USE_AUDIOUNIT) find_path(AUDIOUNIT_INCLUDE_PATH AudioUnit.h) find_library(AUDIOUNIT_LIBRARY AudioUnit) find_library(COREFOUNDATION_LIBRARY CoreFoundation) find_path(COREAUDIO_INCLUDE_PATH CoreAudio.h) find_library(COREAUDIO_LIBRARY CoreAudio) endif() # BUILD TARGETS # check_deps(USE_COREAUDIO APPLE COREAUDIO_INCLUDE_PATH COREAUDIO_LIBRARY) # if(USE_COREAUDIO) # make_plugin(rtcoreaudio rtcoreaudio.c) # target_include_directories(rtcoreaudio PRIVATE ${COREAUDIO_INCLUDE_PATH}) # target_link_libraries(rtcoreaudio ${COREAUDIO_LIBRARY}) # endif() check_deps(USE_COREMIDI APPLE COREMIDI_INCLUDE_PATH COREMIDI_LIBRARY COREFOUNDATION_LIBRARY) if(USE_COREMIDI) make_plugin(cmidi cmidi.c) target_include_directories(cmidi PRIVATE ${COREMIDI_INCLUDE_PATH}) target_link_libraries(cmidi ${COREMIDI_LIBRARY} ${COREFOUNDATION_LIBRARY}) endif() check_deps(USE_AUDIOUNIT APPLE COREAUDIO_INCLUDE_PATH COREAUDIO_LIBRARY AUDIOUNIT_INCLUDE_PATH AUDIOUNIT_LIBRARY COREFOUNDATION_LIBRARY) if(USE_AUDIOUNIT) make_plugin(rtauhal rtauhal.c) target_include_directories(rtauhal PRIVATE ${AUDIOUNIT_INCLUDE_PATH}) target_link_libraries(rtauhal ${AUDIOUNIT_LIBRARY} ${COREFOUNDATION_LIBRARY} ${COREAUDIO_LIBRARY}) endif() check_deps(USE_ALSA ALSA_HEADER ALSA_LIBRARY PTHREAD_LIBRARY) if(USE_ALSA) set(rtalsa_LIBS ${ALSA_LIBRARY} ${PTHREAD_LIBRARY} m) make_plugin(rtalsa rtalsa.c ${rtalsa_LIBS}) endif() if(WIN32) message(STATUS "Building Windows MME plugin(rtwinmm).") if(MSVC) make_plugin(rtwinmm rtwinmm.c) target_link_libraries(rtwinmm winmm.lib) target_link_libraries(rtwinmm gdi32) target_link_libraries(rtwinmm kernel32) else() set(rtwinmm_LIBS winmm gdi32 kernel32) # should probably do checks for these libs make_plugin(rtwinmm rtwinmm.c "${rtwinmm_LIBS}") endif() endif() check_deps(USE_PULSEAUDIO PULSEAUDIO_HEADER PULSEAUDIO_LIBRARY PULSESIMPLE_LIBRARY) if(USE_PULSEAUDIO) make_plugin(rtpulse rtpulse.c ${PULSEAUDIO_LIBRARY} ${PULSESIMPLE_LIBRARY}) endif() if(WIN32) check_deps(USE_PORTAUDIO PORTAUDIO_INCLUDE_PATH PORTAUDIO_LIBRARY) else() check_deps(USE_PORTAUDIO PORTAUDIO_INCLUDE_PATH PORTAUDIO_LIBRARY PORTAUDIO_TEST_COMPILED) endif() if(USE_PORTAUDIO AND PORTAUDIO_V19 MATCHES 1) message(STATUS "Building rtpa module.") make_plugin(rtpa rtpa.c) target_include_directories(rtpa PRIVATE ${PORTAUDIO_INCLUDE_PATH}) if(BUILD_STATIC_LIBRARY) if(WIN32) set_source_files_properties(rtpa.c PROPERTIES LANGUAGE CXX) target_link_libraries(rtpa winmm dsound setupapi ${PORTAUDIO_LIBRARY} ${CSOUND_WINDOWS_LIBRARIES}) else() target_link_libraries(rtpa ${PORTAUDIO_LIBRARY}) endif() else() if(MSVC) set_source_files_properties(rtpa.c PROPERTIES LANGUAGE CXX) target_link_libraries(rtpa winmm dsound setupapi ${PORTAUDIO_LIBRARY} ${CSOUND_WINDOWS_LIBRARIES}) else() target_link_libraries(rtpa ${PORTAUDIO_LIBRARY}) endif() endif() else() message(STATUS "Not building Portaudio Driver...") message(STATUS "Portaudio v19 Found: ${PORTAUDIO_V19}.") endif() if(APPLE) check_deps(USE_PORTMIDI PORTMIDI_INCLUDE_PATH PORTMIDI_LIBRARY) elseif(WIN32) if(MSVC) check_deps(USE_PORTMIDI PORTMIDI_INCLUDE_PATH PORTMIDI_LIBRARY) else() if(NEED_PORTTIME) check_deps(USE_PORTMIDI PORTMIDI_INCLUDE_PATH PORTTIME_INCLUDE_PATH PORTMIDI_LIBRARY) else() check_deps(USE_PORTMIDI PORTMIDI_INCLUDE_PATH PORTMIDI_LIBRARY) endif() endif() elseif(NEED_PORTTIME) check_deps(USE_PORTMIDI PORTMIDI_INCLUDE_PATH PORTMIDI_LIBRARY PORTTIME_LIBRARY) else() check_deps(USE_PORTMIDI PORTMIDI_INCLUDE_PATH PORTMIDI_LIBRARY) endif() if(USE_PORTMIDI) make_plugin(pmidi pmidi.c) target_include_directories(pmidi PRIVATE ${PORTMIDI_INCLUDE_PATH}) target_link_libraries(pmidi ${PORTMIDI_LIBRARY}) if(LINUX) if(NEED_PORTTIME) target_include_directories(pmidi PRIVATE ${PORTTIME_INCLUDE_PATH}) target_link_libraries(pmidi ${PORTTIME_LIBRARY}) endif() elseif(WIN32) if(NEED_PORTTIME) target_include_directories(pmidi PRIVATE ${PORTTIME_INCLUDE_PATH}) endif() target_link_libraries(pmidi ${CSOUND_WINDOWS_LIBRARIES}) elseif(LINUX AND ALSA_LIBRARY) target_link_libraries(pmidi ${ALSA_LIBRARY}) endif() add_dependency_to_framework(pmidi ${PORTMIDI_LIBRARY}) endif() #check_deps(USE_IPMIDI PORTMIDI_HEADER PORTMIDI_LIBRARY) if(USE_IPMIDI) if(WIN32) set(ipmidi_LIBS ws2_32) endif() make_plugin(ipmidi ipmidi.c "${ipmidi_LIBS}") endif() check_deps(USE_JACK JACK_HEADER JACK_LIBRARY) if(USE_JACK) set(rtjack_LIBS "") if(LINUX) list(APPEND rtjack_LIBS ${JACK_LIBRARY} ${PTHREAD_LIBRARY}) elseif(WIN32) list(APPEND rtjack_LIBS ${JACKDMP_LIBRARY} ${PTHREAD_LIBRARY}) else() list(APPEND rtjack_LIBS ${JACK_LIBRARY} ${PTHREAD_LIBRARY}) endif() make_plugin(rtjack rtjack.c "${rtjack_LIBS}") endif() check_deps(USE_FLTK FLTK_FOUND) if(USE_FLTK) set(widgets_SRCS FL_graph.cpp winFLTK.c widgets.cpp) make_plugin(widgets "${widgets_SRCS}" "${FLTK_LIBRARIES}") if(NOT MSVC) target_link_libraries(widgets ${FLTK_BASE_LIBRARY}) target_link_libraries(widgets ${FLTK_FORMS_LIBRARY}) target_link_libraries(widgets ${FLTK_IMAGES_LIBRARY}) else() target_link_libraries(widgets ${FLTK_LIBRARIES}) endif() target_include_directories(widgets PRIVATE ${FLTK_INCLUDE_DIR}) #add_dependency_to_framework(widgets ${FLTK_BASE_LIBRARY}) #add_dependency_to_framework(widgets ${FLTK_FORMS_LIBRARY}) #add_dependency_to_framework(widgets ${FLTK_IMAGES_LIBRARY}) endif() check_deps(BUILD_VIRTUAL_KEYBOARD FLTK_FOUND) if(BUILD_VIRTUAL_KEYBOARD) set(virtual_SRCS virtual_keyboard/FLTKKeyboard.cpp virtual_keyboard/FLTKKeyboardWindow.cpp virtual_keyboard/FLTKKeyboardWidget.cpp virtual_keyboard/virtual_keyboard.cpp virtual_keyboard/Bank.cpp virtual_keyboard/KeyboardMapping.cpp virtual_keyboard/Program.cpp virtual_keyboard/SliderBank.cpp virtual_keyboard/SliderData.cpp) make_plugin(virtual "${virtual_SRCS}" "${FLTK_LIBRARIES}") if (NOT MSVC) target_link_libraries(virtual ${FLTK_BASE_LIBRARY}) target_link_libraries(virtual ${FLTK_FORMS_LIBRARY}) target_link_libraries(virtual ${FLTK_IMAGES_LIBRARY}) else() target_link_libraries(virtual ${FLTK_LIBRARIES}) endif() #add_dependency_to_framework(virtual ${FLTK_BASE_LIBRARY}) #add_dependency_to_framework(virtual ${FLTK_FORMS_LIBRARY}) #add_dependency_to_framework(virtual ${FLTK_IMAGES_LIBRARY}) target_include_directories(virtual PRIVATE ".") target_include_directories(virtual PRIVATE ${FLTK_INCLUDE_DIR}) endif() message(STATUS "") csound-6.10.0/InOut/FL_graph.cpp000066400000000000000000000363111321653344700163310ustar00rootroot00000000000000 /* FL_graph.cpp: code for drawing graphs using FLTK library Copyright (C) 2003 John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #ifdef _MSC_VER #include #endif #include "csdl.h" #include "cwindow.h" #include "winFLTK.h" #define NUMOFWINDOWS (30) #define XINIT 10 /* set default window location */ #define YINIT 50 #define WIDTH 450 /* start off small - user resizes */ #define HEIGHT 150 #define BDR 5 #define BORDERW 10 /* inset from L & R edge */ #define TXHGHT 14 /* baseline offset for text */ #define MAXLSEGS 4096 /* X can only deal with so many linesegs .. */ class graph_box : public Fl_Window { void draw(); public: int curr; int last; CSOUND *csound; graph_box(void *cs, int x, int y, int w, int h, const char *l = 0) : Fl_Window(x, y, w, h, l) { curr = last = -1; csound = (CSOUND*)cs; } //void add_graph(WINDAT *wdptr); }; typedef struct { Fl_Choice *choice; Fl_Button *end; Fl_Menu_Item *menu; graph_box *graph; int graph_created; Fl_Window *form; } FLGRAPH_GLOBALS; #define ST(x) ((flgraphGlobals)->x) /*void printouts(CSOUND *csound){ csound->Message(csound, "menu object: %p\n", ST(menu)); csound->Message(csound, "form object: %p\n", ST(form)); csound->Message(csound, "graph object: %p\n", ST(graph)); csound->Message(csound, "choice object: %p\n", ST(choice)); csound->Message(csound, "globals %p\n", csound->flgraphGlobals); }*/ void flgraph_init(CSOUND *csound) { FLGRAPH_GLOBALS *flgraphGlobals = (FLGRAPH_GLOBALS *) csound->QueryGlobalVariable(csound, "FLGRAPH_GLOBALS"); if (flgraphGlobals==NULL) { csound->CreateGlobalVariable(csound, "FLGRAPH_GLOBALS", sizeof(FLGRAPH_GLOBALS)); flgraphGlobals = (FLGRAPH_GLOBALS *) csound->QueryGlobalVariable(csound, "FLGRAPH_GLOBALS"); //csound->flgraphGlobals = //(FLGRAPH_GLOBALS*) csound->Malloc(csound,sizeof(FLGRAPH_GLOBALS)); } ST(form) = (Fl_Window *) 0; ST(choice) = (Fl_Choice *) 0; ST(end) = (Fl_Button *) 0; ST(graph) = (graph_box *) 0; ST(menu) = (Fl_Menu_Item *) 0; ST(graph_created) = 0; /*ST(menu) = (Fl_Menu_Item*) csound->Calloc(csound, sizeof(Fl_Menu_Item)*(1+NUMOFWINDOWS));*/ /* VL: moved menu object to be built at each new compilation */ } /* static graph_box *graph = (graph_box *) 0; */ void graph_box::draw() { FLGRAPH_GLOBALS *flgraphGlobals = (FLGRAPH_GLOBALS *) csound->QueryGlobalVariable(csound, "FLGRAPH_GLOBALS"); Fl_Window::draw(); fl_color(0, 0, 0); fl_line_style(FL_SOLID); fl_rect(0, 0, w(), h()); if (curr >= 0) { WINDAT *win = (WINDAT*) ST(menu)[curr].user_data_; if (!win) return; MYFLT *fdata = win->fdata; long npts = win->npts; char *msg = win->caption; short win_x, win_y, win_h; /* window rect */ short gra_x, gra_y, gra_w, gra_h; /* graph rect is inset */ short y_axis; int lsegs, pts_pls; int pol; char string[80]; pol = win->polarity; win_x = 0; win_y = 0; /* window pixels addressed relative */ win_h = h(); /* set new width and height so we leave a 20% border around the plot */ gra_w = w() - 2*BORDERW; gra_h = h(); gra_x = win_x + BORDERW; gra_y = win_y; /* figure height of Y axis - top, middle or bottom */ if (pol == (short)BIPOL) y_axis = gra_y + (gra_h/2); else if (pol == (short)NEGPOL) y_axis = gra_y; else /* POSPOL */ y_axis = gra_y + gra_h; if (npts < MAXLSEGS) { lsegs = npts; /* one lineseg per datum */ pts_pls = 1; } else { pts_pls = npts/MAXLSEGS; if (npts%MAXLSEGS) pts_pls++; lsegs = npts/pts_pls; } fl_begin_line(); { /* take scale factors out of for-loop for faster run-time */ MYFLT x_scale = gra_w / (MYFLT) (lsegs - 1); MYFLT y_scale = gra_h / win->oabsmax; /* unipolar default */ MYFLT f, ma, mi, *fdptr = fdata; int c, i = 0, j = lsegs; if (pol == (short) BIPOL) y_scale /= 2.0; /* max data scales to h/2 */ /* put x-y pairs into a point list for XDraw */ while (j--) { int x = gra_x + (short) ((MYFLT) i++ * x_scale); int y; if (pts_pls == 1) f = *fdptr++; else { ma = mi = *fdptr++; for (c = 1; c < pts_pls; ++c) if ((f = *fdptr++) > ma) ma = f; else if ( f 0) f = ma; else if (ma > -mi) f = ma; else f = mi; } y = y_axis - (short) (f * y_scale); fl_vertex(x, y); } } fl_end_line(); /* now draw axes: y-axis is always on the left edge, x-axis height is determined by the case we're in */ fl_line(gra_x, y_axis, (gra_x + gra_w), y_axis); fl_line(gra_x, y_axis, (gra_x + gra_w), y_axis); fl_line(gra_x, gra_y, gra_x, (gra_y + gra_h)); if (win->danflag) { /* flag to add dotted divider */ fl_line_style(FL_DOT); fl_line(win_x+w()/2, win_y, win_x+w()/2, win_y+win_h); } if (pol != NEGPOL) sprintf(string, "%s %ld points, max %5.3f", msg, npts, win->oabsmax); else sprintf(string, "%s %ld points, max %5.3f", msg, npts, win->max); ST(form)->label(string); } fl_line_style(FL_SOLID); } void add_graph(CSOUND *csound, WINDAT *wdptr) { FLGRAPH_GLOBALS *flgraphGlobals = (FLGRAPH_GLOBALS *) csound->QueryGlobalVariable(csound, "FLGRAPH_GLOBALS"); WINDAT *n = (WINDAT*) malloc(sizeof(WINDAT)); int m; WINDAT *old; int replacing = 0; memcpy(n, wdptr, sizeof(WINDAT)); n->fdata = (MYFLT*) malloc(n->npts * sizeof(MYFLT)); memcpy(n->fdata, wdptr->fdata, n->npts * sizeof(MYFLT)); for (m = 0; m < NUMOFWINDOWS; m++) { // If text the same use slot if (ST(menu) != NULL) { if (ST(menu)[m].text != NULL && strlen(wdptr->caption) == 0){ if(strcmp(wdptr->caption, ST(menu)[m].text) == 0) { replacing = 1; goto replace; } } } } // Use a new slot, cycling round ST(graph)->last++; m = ST(graph)->last; if (m >= NUMOFWINDOWS) m = ST(graph)->last = 0; replace: old = (WINDAT*)ST(menu)[m].user_data_; if (old) { free((void*) old->fdata); free((void*) old); } ST(menu)[m].user_data_ = n; if (replacing == 0) { if (ST(menu)[m].text != NULL) free((void*) ST(menu)[m].text); ST(menu)[m].text = (const char*) malloc(strlen(n->caption) + 1); strcpy((char*) ST(menu)[m].text, n->caption); } // ST(graph)->curr = m; // ST(choice)->value(m); ST(graph)->curr = ST(choice)->value(); /* VL: 29.04.09 fix */ ST(graph)->redraw(); } void do_redraw(Fl_Widget *, void *cs) { CSOUND *csound = (CSOUND*)cs; FLGRAPH_GLOBALS *flgraphGlobals = (FLGRAPH_GLOBALS *) csound->QueryGlobalVariable(csound, "FLGRAPH_GLOBALS"); ST(graph)->curr = ST(choice)->value(); ST(graph)->redraw(); } void makeWindow(CSOUND *csound, char *name) { FLGRAPH_GLOBALS *flgraphGlobals = (FLGRAPH_GLOBALS *) csound->QueryGlobalVariable(csound, "FLGRAPH_GLOBALS"); if (ST(form)) return; ST(form) = new Fl_Window(WIDTH, HEIGHT, name); ST(menu) = new Fl_Menu_Item[1+NUMOFWINDOWS]; memset(ST(menu), 0, sizeof(Fl_Menu_Item)*(1+NUMOFWINDOWS)); ST(choice) = new Fl_Choice(140, 0, 140, 20, "Choose Graph"); ST(choice)->menu(ST(menu)); ST(choice)->value(0); ST(choice)->callback((Fl_Callback*) do_redraw, (void*)csound); ST(graph) = new graph_box(csound, BDR, 30 + BDR, WIDTH - 2 * BDR, HEIGHT - 30 - 2 * BDR); ST(graph)->end(); ST(end) = new Fl_Button(WIDTH - 40, 0, 35, 20, "Quit"); ST(end)->hide(); ST(form)->resizable(ST(graph)); ST(form)->end(); ST(graph_created) = 1; } void graphs_reset(CSOUND * csound){ //if (csound->flgraphGlobals != NULL) // csound->Free(csound, csound->flgraphGlobals); } extern "C" { void DrawGraph_FLTK(CSOUND *csound, WINDAT *wdptr) { add_graph(csound, wdptr); csound->CheckEvents(csound); } uintptr_t MakeWindow_FLTK(CSOUND *csound, char *name) { FLGRAPH_GLOBALS *flgraphGlobals = (FLGRAPH_GLOBALS *) csound->QueryGlobalVariable(csound, "FLGRAPH_GLOBALS"); if (ST(form) == NULL) { makeWindow(csound, name); ST(form)->show(); } return (uintptr_t) ST(form); } int CsoundYield_FLTK(CSOUND *csound){ #ifndef NO_FLTK_THREADS /* nothing to do, unless no widget thread is running */ if (csound->QueryGlobalVariable(csound, "_widgets_globals") != NULL) return 1; #endif Fl_wait_locked(csound, 0.0); return 1; } void kill_graph(CSOUND *csound, uintptr_t m) { FLGRAPH_GLOBALS *flgraphGlobals = (FLGRAPH_GLOBALS *) csound->QueryGlobalVariable(csound, "FLGRAPH_GLOBALS"); for (int i = 0; i < NUMOFWINDOWS; i++) { WINDAT *n = (WINDAT*) ST(menu)[i].user_data_; if (n != NULL && ((uintptr_t) n == m ||n->windid == m)) { free(n->fdata); free(n); free((void*) ST(menu)[i].text); ST(menu)[i].user_data_ = (void*) 0; ST(menu)[i].text = (char*) 0; return; } } } int ExitGraph_FLTK(CSOUND *csound) { FLGRAPH_GLOBALS *flgraphGlobals = (FLGRAPH_GLOBALS *) csound->QueryGlobalVariable(csound, "FLGRAPH_GLOBALS"); if (flgraphGlobals == 0) { return OK; } if (ST(form) && ST(graph_created) == 1) { if (ST(form)->shown() && !(getFLTKFlags(csound) & 256)) { const char *env = csound->GetEnv(csound, "CSNOSTOP"); if (env == NULL || strcmp(env, "yes") != 0) { ST(end)->show(); // print click-Exit message in most recently active window while (ST(end)->value() == 0 && ST(form)->shown()) { Fl_wait_locked(csound, 0.03); } } } delete ST(form); ST(form) = (Fl_Window *) 0; Fl_wait_locked(csound, 0.0); ST(choice) = (Fl_Choice *) 0; ST(graph) = (graph_box *) 0; ST(end) = (Fl_Button *) 0; ST(graph_created) = 0; for (int i = 0; i < NUMOFWINDOWS; i++) { WINDAT *n = (WINDAT*) ST(menu)[i].user_data_; if (n) kill_graph(csound, (uintptr_t) ((void*) n)); } if (ST(menu)){ delete[] ST(menu); ST(menu) = (Fl_Menu_Item *) 0; } } return 0; } #define GUTTERH 20 /* space for text at top & bottom */ #define BORDERW 10 /* inset from L & R edge */ void MakeXYin_FLTK(CSOUND *csound, XYINDAT *w, MYFLT x, MYFLT y) { if (w->windid == (uintptr_t) 0) { Fl_Window *xyin = new Fl_Window(WIDTH, WIDTH, "XY input"); short win_x, win_y; short gra_x, gra_y, gra_w, gra_h; win_x = 0; win_y = 0; /* window pixels addressed relative */ Fl_lock(csound); xyin->show(); Fl_wait(csound, 0.0); Fl_unlock(csound); /* set new width and height so we leave a 20% border around the plot */ gra_w = xyin->w() - 2*BORDERW; gra_h = xyin->h() - 2*GUTTERH; gra_x = win_x + BORDERW; gra_y = win_y + GUTTERH; w->m_x = gra_x + (int) (x * (MYFLT) gra_w); w->m_y = gra_y + (int) (y * (MYFLT) gra_h); w->down = 0; Fl_lock(csound); Fl_wait(csound, 0.0); xyin->make_current(); fl_color(0, 0, 0); fl_line_style(FL_DOT); fl_line(gra_x, w->m_y, (gra_x + gra_w), w->m_y); fl_line(w->m_x, gra_y, w->m_x, (gra_y + gra_h)); Fl_unlock(csound); w->windid = (uintptr_t) xyin; } } void ReadXYin_FLTK(CSOUND *csound, XYINDAT *wdptr) { short win_x, win_y; short gra_x, gra_y, gra_w, gra_h; short m_x, m_y; Fl_Window *xwin = (Fl_Window*) wdptr->windid; Fl_lock(csound); Fl_wait(csound, 0.0); m_x = Fl::event_x(); m_y = Fl::event_y(); wdptr->down = (short) (Fl::event_button1() ? 1 : 0); Fl_unlock(csound); if (!wdptr->down) return; win_x = 0; win_y = 0; /* window pixels addressed relative */ /* set new width and height so we leave a 20% border around the plot */ gra_w = xwin->w() - 2*BORDERW; gra_h = xwin->h() - 2*GUTTERH; gra_x = win_x + BORDERW; gra_y = win_y + GUTTERH; /* clip mouse position */ if (m_x < gra_x) m_x = gra_x; else if (m_x > gra_x+gra_w) m_x = gra_x+gra_w; if (m_y < gra_y) m_y = gra_y; else if (m_y > gra_y+gra_h) m_y = gra_y+gra_h; if (m_x != wdptr->m_x || m_y != wdptr->m_y) { /* only redo if changed */ Fl_lock(csound); xwin->make_current(); /* undraw old crosshairs */ fl_color(FL_BACKGROUND_COLOR); fl_line_style(FL_SOLID); fl_line(gra_x, wdptr->m_y, (gra_x + gra_w), wdptr->m_y); fl_line(wdptr->m_x, gra_y, wdptr->m_x, (gra_y + gra_h)); // Draw new fl_color(0, 0, 0); fl_line_style(FL_SOLID); fl_line(gra_x, m_y, (gra_x + gra_w), m_y); fl_line(m_x, gra_y, m_x, (gra_y + gra_h)); Fl_unlock(csound); wdptr->m_x = m_x; wdptr->m_y = m_y; wdptr->x = ((MYFLT) m_x - gra_x) / (MYFLT) gra_w; wdptr->y = ((MYFLT) m_y - gra_y) / (MYFLT) gra_h; } } void KillXYin_FLTK(CSOUND *csound, XYINDAT *wdptr) { delete ((Fl_Window*) wdptr->windid); wdptr->windid = (uintptr_t) 0; } } csound-6.10.0/InOut/circularbuffer.c000066400000000000000000000123601321653344700173030ustar00rootroot00000000000000/* circularbuffer.c: Copyright (C) 2012 Victor Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include typedef struct _circular_buffer { char *buffer; int wp; int rp; int numelem; int elemsize; /* in number of bytes */ } circular_buffer; void *csoundCreateCircularBuffer(CSOUND *csound, int numelem, int elemsize){ circular_buffer *p; if ((p = (circular_buffer *) csound->Malloc(csound, sizeof(circular_buffer))) == NULL) { return NULL; } p->numelem = numelem; p->wp = p->rp = 0; p->elemsize = elemsize; if ((p->buffer = (char *) csound->Malloc(csound, numelem*elemsize)) == NULL) { return NULL; } memset(p->buffer, 0, numelem*elemsize); return (void *)p; } static int checkspace(circular_buffer *p, int writeCheck){ int wp = p->wp, rp = p->rp, numelem = p->numelem; if(writeCheck){ if (wp > rp) return rp - wp + numelem - 1; else if (wp < rp) return rp - wp - 1; else return numelem - 1; } else { if (wp > rp) return wp - rp; else if (wp < rp) return wp - rp + numelem; else return 0; } } int csoundReadCircularBuffer(CSOUND *csound, void *p, void *out, int items) { IGN(csound); if (p == NULL) return 0; { int remaining; int itemsread, numelem = ((circular_buffer *)p)->numelem; int elemsize = ((circular_buffer *)p)->elemsize; int i=0, rp = ((circular_buffer *)p)->rp; char *buffer = ((circular_buffer *)p)->buffer; if ((remaining = checkspace(p, 0)) == 0) { return 0; } itemsread = items > remaining ? remaining : items; for (i=0; i < itemsread; i++){ memcpy((char *) out + (i * elemsize), &(buffer[elemsize * rp++]), elemsize); if (rp == numelem) { rp = 0; } } #if defined(MSVC) InterlockedExchange(&((circular_buffer *)p)->rp, rp); #elif defined(HAVE_ATOMIC_BUILTIN) __sync_lock_test_and_set(&((circular_buffer *)p)->rp,rp); #else ((circular_buffer *)p)->rp = rp; #endif return itemsread; } } int csoundPeekCircularBuffer(CSOUND *csound, void *p, void *out, int items) { IGN(csound); if (p == NULL) return 0; int remaining; int itemsread, numelem = ((circular_buffer *)p)->numelem; int elemsize = ((circular_buffer *)p)->elemsize; int i=0, rp = ((circular_buffer *)p)->rp; char *buffer = ((circular_buffer *)p)->buffer; if ((remaining = checkspace(p, 0)) == 0) { return 0; } itemsread = items > remaining ? remaining : items; for(i=0; i < itemsread; i++){ memcpy((char *) out + (i * elemsize), &(buffer[elemsize * rp++]), elemsize); if (rp == numelem) { rp = 0; } } return itemsread; } void csoundFlushCircularBuffer(CSOUND *csound, void *p) { IGN(csound); if (p == NULL) return; int remaining; int itemsread, numelem = ((circular_buffer *)p)->numelem; int i=0, rp = ((circular_buffer *)p)->rp; //MYFLT *buffer = ((circular_buffer *)p)->buffer; if ((remaining = checkspace(p, 0)) == 0) { return; } itemsread = numelem > remaining ? remaining: numelem; for (i=0; i < itemsread; i++){ rp++; if(rp == numelem) rp = 0; } #if defined(MSVC) InterlockedExchange(&((circular_buffer *)p)->rp, rp); #elif defined(HAVE_ATOMIC_BUILTIN) __sync_lock_test_and_set(&((circular_buffer *)p)->rp,rp); #else ((circular_buffer *)p)->rp = rp; #endif } int csoundWriteCircularBuffer(CSOUND *csound, void *p, const void *in, int items) { IGN(csound); if (p == NULL) return 0; int remaining; int itemswrite, numelem = ((circular_buffer *)p)->numelem; int elemsize = ((circular_buffer *)p)->elemsize; int i=0, wp = ((circular_buffer *)p)->wp; char *buffer = ((circular_buffer *)p)->buffer; if ((remaining = checkspace(p, 1)) == 0) { return 0; } itemswrite = items > remaining ? remaining : items; for(i=0; i < itemswrite; i++){ memcpy(&(buffer[elemsize * wp++]), ((char *) in) + (i * elemsize), elemsize); if(wp == numelem) wp = 0; } #if defined(MSVC) InterlockedExchange(&((circular_buffer *)p)->wp, wp); #elif defined(HAVE_ATOMIC_BUILTIN) __sync_lock_test_and_set(&((circular_buffer *)p)->wp,wp); #else ((circular_buffer *)p)->wp = wp; #endif return itemswrite; } void csoundDestroyCircularBuffer(CSOUND *csound, void *p){ if(p == NULL) return; csound->Free(csound, ((circular_buffer *)p)->buffer); csound->Free(csound, p); } csound-6.10.0/InOut/cmidi.c000066400000000000000000000217761321653344700154050ustar00rootroot00000000000000/* cmidi.c: Copyright (C) 2011 V Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Realtime MIDI using coremidi */ #include #include #include #include "csdl.h" /* CMIDI.C */ #include "midiops.h" /* MIDI message queue size */ #define DSIZE 4096 /* MIDI data struct */ typedef struct { Byte status; Byte data1; Byte data2; Byte flag; } MIDIdata; /* user data for MIDI callbacks */ typedef struct _cdata { MIDIdata *mdata; int p; int q; MIDIClientRef mclient; } cdata; /* coremidi callback, called when MIDI data is available */ void ReadProc(const MIDIPacketList *pktlist, void *refcon, void *srcConnRefCon) { cdata *data = (cdata *)refcon; MIDIdata *mdata = data->mdata; int *p = &data->p; UInt32 i, j; MIDIPacket *packet = &((MIDIPacketList *)pktlist)->packet[0]; Byte *curpack; for (i = 0; i < pktlist->numPackets; i++) { for (j=0; j < packet->length; j+=3) { curpack = packet->data+j; memcpy(&mdata[*p], curpack, 3); mdata[*p].flag = 1; (*p)++; if (*p == DSIZE) *p = 0; } packet = MIDIPacketNext(packet); } } static int listDevices(CSOUND *csound, CS_MIDIDEVICE *list, int isOutput) { int k, endpoints; MIDIEndpointRef endpoint; CFStringRef name = NULL; CFStringEncoding defaultEncoding = CFStringGetSystemEncoding(); char tmp[64]; char *drv = (char*) (csound->QueryGlobalVariable(csound, "_RTMIDI")); if (isOutput) return 0; endpoints = MIDIGetNumberOfSources(); if (list == NULL) return endpoints; for(k=0; k < endpoints; k++) { endpoint = MIDIGetSource(k); MIDIObjectGetStringProperty(endpoint, kMIDIPropertyName, &name); const char *sn = CFStringGetCStringPtr(name, defaultEncoding); if(sn != NULL) strncpy(list[k].device_name, sn, 63); snprintf(tmp, 64, "%d", k); strncpy(list[k].device_id, tmp, 63); list[k].isOutput = isOutput; strcpy(list[k].interface_name, ""); strncpy(list[k].midi_module, drv, 63); } if (name) CFRelease(name); return endpoints; } /* csound MIDI input open callback, sets the device for input */ static int MidiInDeviceOpen(CSOUND *csound, void **userData, const char *dev) { int k, endpoints; CFStringRef name = NULL, cname = NULL, pname = NULL; CFStringEncoding defaultEncoding = CFStringGetSystemEncoding(); MIDIClientRef mclient = (MIDIClientRef) 0; MIDIPortRef mport = (MIDIPortRef) 0; MIDIEndpointRef endpoint; MIDIdata *mdata = (MIDIdata *) csound->Malloc(csound, DSIZE*sizeof(MIDIdata)); OSStatus ret; cdata *refcon = (cdata *) csound->Malloc(csound, sizeof(cdata)); memset(mdata, 0, sizeof(MIDIdata)*DSIZE); refcon->mdata = mdata; refcon->p = 0; refcon->q = 0; /* MIDI client */ cname = CFStringCreateWithCString(NULL, "my client", defaultEncoding); ret = MIDIClientCreate(cname, NULL, NULL, &mclient); if (!ret){ /* MIDI input port */ pname = CFStringCreateWithCString(NULL, "inport", defaultEncoding); ret = MIDIInputPortCreate(mclient, pname, ReadProc, refcon, &mport); if (!ret){ /* sources, we connect to all available input sources */ endpoints = MIDIGetNumberOfSources(); csound->Message(csound, Str("%d MIDI sources in system \n"), endpoints); if (!strcmp(dev,"all")) { csound->Message(csound, Str("receiving from all sources \n")); for(k=0; k < endpoints; k++){ endpoint = MIDIGetSource(k); long srcRefCon = (long) endpoint; MIDIPortConnectSource(mport, endpoint, (void *) srcRefCon); MIDIObjectGetStringProperty(endpoint, kMIDIPropertyName, &name); csound->Message(csound, Str("connecting midi device %d: %s \n"), k, CFStringGetCStringPtr(name, defaultEncoding)); } } else{ k = atoi(dev); if (k < endpoints){ endpoint = MIDIGetSource(k); long srcRefCon = (long) endpoint; MIDIPortConnectSource(mport, endpoint, (void *) srcRefCon); MIDIObjectGetStringProperty(endpoint, kMIDIPropertyName, &name); csound->Message(csound, Str("connecting midi device %d: %s \n"), k, CFStringGetCStringPtr(name, defaultEncoding)); } else csound->Message(csound, Str("MIDI device number %d is out-of-range, " "not connected \n"), k); } } } refcon->mclient = mclient; *userData = (void*) refcon; if (name) CFRelease(name); if (pname) CFRelease(pname); if (cname) CFRelease(cname); /* report success */ return 0; } static int MidiOutDeviceOpen(CSOUND *csound, void **userData, const char *dev) { /*stub for the moment */ csound->Message(csound, Str("output not implemented yet in CoreMIDI \n")); return 0; } /* used to distinguish between 1 and 2-byte messages */ static const int datbyts[8] = { 2, 2, 2, 2, 1, 1, 2, 0 }; /* csound MIDI read callback, called every k-cycle */ static int MidiDataRead(CSOUND *csound, void *userData, unsigned char *mbuf, int nbytes) { cdata *data = (cdata *)userData; MIDIdata *mdata = data->mdata; int *q = &data->q, st, d1, d2, n = 0; /* check if there is new data in circular queue */ while (mdata[*q].flag) { st = (int) mdata[*q].status; d1 = (int) mdata[*q].data1; d2 = (int) mdata[*q].data2; if (st < 0x80) goto next; if (st >= 0xF0 && !(st == 0xF8 || st == 0xFA || st == 0xFB || st == 0xFC || st == 0xFF)) goto next; nbytes -= (datbyts[(st - 0x80) >> 4] + 1); if (nbytes < 0) break; /* write to csound midi buffer */ n += (datbyts[(st - 0x80) >> 4] + 1); switch (datbyts[(st - 0x80) >> 4]) { case 0: *mbuf++ = (unsigned char) st; break; case 1: *mbuf++ = (unsigned char) st; *mbuf++ = (unsigned char) d1; break; case 2: *mbuf++ = (unsigned char) st; *mbuf++ = (unsigned char) d1; *mbuf++ = (unsigned char) d2; break; } /* mark as read */ next: mdata[*q].flag = 0; (*q)++; if (*q==DSIZE) *q = 0; } /* return the number of bytes read */ return n; } /* csound close device callback */ static int MidiInDeviceClose(CSOUND *csound, void *userData) { cdata * data = (cdata *)userData; if (data != NULL) { MIDIClientDispose(data->mclient); csound->Free(csound, data->mdata); csound->Free(csound, data); } return 0; } static int MidiDataWrite(CSOUND *csound, void *userData, const unsigned char *mbuf, int nbytes) { /* stub at the moment */ /* */ return nbytes; } static int MidiOutDeviceClose(CSOUND *csound, void *userData) { /* stub at the mement */ return 0; } /* module interface functions */ PUBLIC int csoundModuleCreate(CSOUND *csound) { /* nothing to do, report success */ //csound->Message(csound, Str("CoreMIDI real time MIDI plugin for Csound\n")); return 0; } PUBLIC int csoundModuleInit(CSOUND *csound) { char *drv; csound->module_list_add(csound, "coremidi", "midi"); drv = (char*) (csound->QueryGlobalVariable(csound, "_RTMIDI")); if (drv == NULL) return 0; if (!(strcmp(drv, "coremidi") == 0 || strcmp(drv, "CoreMidi") == 0 || strcmp(drv, "CoreMIDI") == 0 || strcmp(drv, "cm") == 0)) return 0; csound->Message(csound, Str("rtmidi: CoreMIDI module enabled\n")); csound->SetExternalMidiInOpenCallback(csound, MidiInDeviceOpen); csound->SetExternalMidiReadCallback(csound, MidiDataRead); csound->SetExternalMidiInCloseCallback(csound, MidiInDeviceClose); csound->SetExternalMidiOutOpenCallback(csound, MidiOutDeviceOpen); csound->SetExternalMidiWriteCallback(csound, MidiDataWrite); csound->SetExternalMidiOutCloseCallback(csound, MidiOutDeviceClose); csound->SetMIDIDeviceListCallback(csound,listDevices); return 0; } PUBLIC int csoundModuleInfo(void) { /* does not depend on MYFLT type */ return ((CS_APIVERSION << 16) + (CS_APISUBVER << 8)); } csound-6.10.0/InOut/ipmidi.c000066400000000000000000000117721321653344700155660ustar00rootroot00000000000000/* ipmidi.c: Copyright (C) 2012 Henri Manson This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Realtime MIDI using ipmidi library */ #include #ifdef WIN32 #include #include #else #include #include #include #include #include #endif #include #include "csdl.h" /* IPMIDI.C */ #include "midiops.h" #include "oload.h" static int OpenMidiInDevice_(CSOUND *csound, void **userData, const char *dev) { static int sock; int status; struct sockaddr_in saddr; struct ip_mreq mreq; #ifdef WIN32 WSADATA wsaData; if (WSAStartup (MAKEWORD(2, 2), &wsaData) != 0) { fprintf(stderr, Str("WSAStartup failed!\n")); return -1; } #endif printf("OpenMidiInDevice_: %s\n", dev); // set content of struct saddr and imreq to zero memset(&saddr, 0, sizeof(struct sockaddr_in)); // open a UDP socket sock = socket(PF_INET, SOCK_DGRAM, 0); if ( sock < 0 ) { perror(Str("Error creating socket")); return -1; } saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl(INADDR_ANY); saddr.sin_port = htons(21928); status = bind(sock, (struct sockaddr *) &saddr, sizeof(struct sockaddr_in)); if ( status < 0 ) { #ifdef WIN32 char *buff = strerror(errno); printf("WSAGetLastError() = %d\n", WSAGetLastError()); #else char buff[128]; (void)strerror_r(errno, buff, 128); #endif csound->ErrorMsg(csound, Str("Error binding socket to interface: %s"), buff); //perror("Error binding socket to interface"); return -1; } mreq.imr_multiaddr.s_addr = inet_addr("225.0.0.37"); mreq.imr_interface.s_addr = htonl(INADDR_ANY); status = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); if ( status < 0 ) { #ifdef WIN32 char *buff = strerror(errno); csound->ErrorMsg(csound, "WSAGetLastError() = %d\n", WSAGetLastError()); return -1; #else char buff[128]; (void)strerror_r(errno, buff, 128); csound->ErrorMsg(csound, Str("Error adding membership to interface: %s"), buff); return NOTOK; //perror("Error binding socket to interface"); #endif } *userData = (void*) &sock; /* report success */ return 0; } static int ReadMidiData_(CSOUND *csound, void *userData, unsigned char *mbuf, int nbytes) { int n; int sock = *((int *) userData); fd_set rset; struct timeval timeout; int rc; n = 0; FD_ZERO(&rset); FD_SET(sock, &rset); timeout.tv_sec = 0; timeout.tv_usec = 0; rc = select(sock + 1, &rset, NULL, NULL, &timeout); if (rc > 0) { #ifdef WIN32 n = recv(sock, mbuf, nbytes, 0); #else n = read(sock, mbuf, nbytes); #endif printf("ReadMidiData__ n = %d\n", n); } /* return the number of bytes read */ return n; } static int CloseMidiInDevice_(CSOUND *csound, void *userData) { int sock = *((int *) userData); //printf("CloseMidiInDevice_\n"); close(sock); #ifdef WIN32 WSACleanup(); #endif return 0; } /* module interface functions */ PUBLIC int csoundModuleCreate(CSOUND *csound) { OPARMS oparms; csound->GetOParms(csound, &oparms); /* nothing to do, report success */ if (oparms.msglevel & 0x400) csound->Message(csound, Str("ipMIDI real time MIDI plugin for Csound\n")); return 0; } PUBLIC int csoundModuleInit(CSOUND *csound) { char *drv; OPARMS oparms; csound->GetOParms(csound, &oparms); drv = (char*) (csound->QueryGlobalVariable(csound, "_RTMIDI")); if (drv == NULL) return 0; if (strcmp(drv, "ipmidi") != 0) return 0; if (oparms.msglevel & 0x400) csound->Message(csound, Str("ipmidi: ipMIDI module enabled\n")); csound->SetExternalMidiInOpenCallback(csound, OpenMidiInDevice_); csound->SetExternalMidiReadCallback(csound, ReadMidiData_); csound->SetExternalMidiInCloseCallback(csound, CloseMidiInDevice_); return 0; } PUBLIC int csoundModuleInfo(void) { /* does not depend on MYFLT type */ return ((CS_APIVERSION << 16) + (CS_APISUBVER << 8)); } csound-6.10.0/InOut/libmpadec/000077500000000000000000000000001321653344700160575ustar00rootroot00000000000000csound-6.10.0/InOut/libmpadec/layer1.c000066400000000000000000000131111321653344700174150ustar00rootroot00000000000000/* * mpadec - MPEG audio decoder * Copyright (C) 2002-2004 Dmitriy Startsev (dstartsev@rambler.ru) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* $Id: layer1.c,v 1.1.1.1 2004/07/27 02:57:18 metal_man Exp $ */ #include "mpadec_internal.h" extern const uint32_t bitmask[17]; extern alloc_table_t *alloc_tables[5]; extern unsigned getbits(mpadec_t mpadec, int n); extern uint16_t update_crc(uint16_t init, uint8_t *buf, int length); static void I_decode_bitalloc(mpadec_t mpadec, uint8_t *bit_alloc, uint8_t *scalefac) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; uint8_t *ba = bit_alloc, *scf = scalefac; uint32_t crclen = mpa->bytes_left; if (mpa->frame.channels > 1) { unsigned i, jsbound = mpa->frame.jsbound; for (i = jsbound; i; i--) { *ba++ = (uint8_t)GETBITS(4); *ba++ = (uint8_t)GETBITS(4); } for (i = (SBLIMIT - jsbound); i; i--) *ba++ = (uint8_t)GETBITS(4); if (mpa->config.crc && mpa->frame.CRC) { crclen -= mpa->bytes_left; mpa->crc = update_crc(mpa->crc, mpa->next_byte - crclen, ((crclen << 3) - mpa->bits_left)); if (mpa->crc != mpa->frame.crc) mpa->error = TRUE; } ba = bit_alloc; for (i = jsbound; i; i--) { if (*ba++) *scf++ = (uint8_t)GETBITS(6); if (*ba++) *scf++ = (uint8_t)GETBITS(6); } for (i = (SBLIMIT - jsbound); i; i--) { if (*ba++) { *scf++ = (uint8_t)GETBITS(6); *scf++ = (uint8_t)GETBITS(6); } } } else { register unsigned i; for (i = SBLIMIT; i; i--) *ba++ = (uint8_t)GETBITS(4); if (mpa->config.crc && mpa->frame.CRC) { crclen -= mpa->bytes_left; mpa->crc = update_crc(mpa->crc, mpa->next_byte - crclen, ((crclen << 3) - mpa->bits_left)); if (mpa->crc != mpa->frame.crc) mpa->error = TRUE; } ba = bit_alloc; for (i = SBLIMIT; i; i--) if (*ba++) *scf++ = (uint8_t)GETBITS(6); } } static void I_decode_samples(mpadec_t mpadec, uint8_t *bit_alloc, uint8_t *scalefac, MYFLT fraction[2][SBLIMIT]) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; uint8_t *ba = bit_alloc, *scf = scalefac; unsigned i, n; if (mpa->frame.channels > 1) { unsigned jsbound = mpa->frame.jsbound; MYFLT *f0 = fraction[0], *f1 = fraction[1]; for (i = jsbound; i; i--) { if ((n = *ba++) != 0) *f0++ = (((-1)<tables.muls[n + 1][*scf++]; else *f0++ = 0.0; if ((n = *ba++) != 0) *f1++ = (((-1)<tables.muls[n + 1][*scf++]; else *f1++ = 0.0; } for (i = (SBLIMIT - jsbound); i; i--) { if ((n = *ba++) != 0) { register MYFLT tmp = (((-1) << n) + GETBITS(n + 1) + 1); *f0++ = tmp*mpa->tables.muls[n + 1][*scf++]; *f1++ = tmp*mpa->tables.muls[n + 1][*scf++]; } else *f0++ = *f1++ = 0.0; } for (i = (SBLIMIT - mpa->frame.downsample_sblimit); i; i--) *--f0 = *--f1 = 0.0; } else { MYFLT *f0 = fraction[0]; for (i = SBLIMIT; i; i--) { if ((n = *ba++) != 0) *f0++ = (((-1)<tables.muls[n + 1][*scf++]; else *f0++ = 0.0; } for (i = (SBLIMIT - mpa->frame.downsample_sblimit); i; i--) *--f0 = 0.0; } } void decode_layer1(mpadec_t mpadec, uint8_t *buffer) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; int i, j, single; MYFLT fraction[2][SBLIMIT]; uint8_t bit_alloc[2*SBLIMIT]; uint8_t scalefac[2*SBLIMIT]; mpa->error = FALSE; mpa->bits_left = 0; mpa->frame.jsbound = (uint8_t)((mpa->frame.mode == MPG_MD_JOINT_STEREO) ? ((mpa->frame.mode_ext + 1) << 2) : SBLIMIT); if (mpa->frame.channels > 1) switch (mpa->config.mode) { case MPADEC_CONFIG_MONO: single = 0; break; case MPADEC_CONFIG_CHANNEL1: single = 1; break; case MPADEC_CONFIG_CHANNEL2: single = 2; break; default: single = -1; break; } else single = 1; I_decode_bitalloc(mpa, bit_alloc, scalefac); for (i = 0; i < SCALE_BLOCK; i++) { I_decode_samples(mpa, bit_alloc, scalefac, fraction); if (!single) for (j = 0; j < SBLIMIT; j++) fraction[0][j] = 0.5*(fraction[0][j] + fraction[1][j]); if (single < 0) { mpa->synth_func(mpa, fraction[0], 0, buffer); mpa->synth_func(mpa, fraction[1], 1, buffer); } else if (!single) { mpa->synth_func(mpa, fraction[0], 0, buffer); } else { mpa->synth_func(mpa, fraction[single - 1], 0, buffer); } buffer += mpa->synth_size; } { register unsigned n = mpa->bits_left >> 3; mpa->next_byte -= n; mpa->bytes_left += n; mpa->reservoir_size = 0; } } csound-6.10.0/InOut/libmpadec/layer2.c000066400000000000000000000216571321653344700174340ustar00rootroot00000000000000/* * mpadec - MPEG audio decoder * Copyright (C) 2002-2004 Dmitriy Startsev (dstartsev@rambler.ru) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* $Id: layer2.c,v 1.2 2009/03/01 15:27:05 jpff Exp $ */ #include "mpadec_internal.h" extern const uint32_t bitmask[17]; extern alloc_table_t *alloc_tables[5]; extern unsigned getbits(mpadec_t mpadec, int n); extern uint16_t update_crc(uint16_t init, uint8_t *buf, int length); static void II_decode_bitalloc(mpadec_t mpadec, uint8_t *bit_alloc, uint8_t *scalefac) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; alloc_table_t *alloc = mpa->frame.alloc_table; uint8_t *scfsi, *ba = bit_alloc, *scf = scalefac; unsigned i, step, sblimit2, sblimit = mpa->frame.sblimit; uint32_t crclen = mpa->bytes_left; uint8_t scfsi_buf[2*SBLIMIT]; if (mpa->frame.channels > 1) { unsigned jsbound = mpa->frame.jsbound; sblimit2 = sblimit << 1; for (i = jsbound; i; i--, alloc += (1 << step)) { step = alloc->bits; *ba++ = (uint8_t)GETBITS(step); *ba++ = (uint8_t)GETBITS(step); } for (i = sblimit - jsbound; i; i--, alloc += (1 << step)) { step = alloc->bits; ba[0] = (uint8_t)GETBITS(step); ba[1] = ba[0]; ba += 2; } ba = bit_alloc; scfsi = scfsi_buf; for (i = sblimit2; i; i--) if (*ba++) *scfsi++ = (uint8_t)GETBITS(2); } else { sblimit2 = sblimit; for (i = sblimit; i; i--, alloc += (1 << step)) { step = alloc->bits; *ba++ = (uint8_t)GETBITS(step); } ba = bit_alloc; scfsi = scfsi_buf; for (i = sblimit; i; i--) if (*ba++) *scfsi++ = (uint8_t)GETBITS(2); } if (mpa->config.crc && mpa->frame.CRC) { crclen -= mpa->bytes_left; mpa->crc = update_crc(mpa->crc, mpa->next_byte - crclen, ((crclen << 3) - mpa->bits_left)); if (mpa->crc != mpa->frame.crc) mpa->error = TRUE; } ba = bit_alloc; scfsi = scfsi_buf; for (i = sblimit2; i; i--) { if (*ba++) { switch (*scfsi++) { case 0: scf[0] = (uint8_t)GETBITS(6); scf[1] = (uint8_t)GETBITS(6); scf[2] = (uint8_t)GETBITS(6); break; case 1: scf[0] = (uint8_t)GETBITS(6); scf[1] = scf[0]; scf[2] = (uint8_t)GETBITS(6); break; case 2: scf[0] = (uint8_t)GETBITS(6); scf[1] = scf[2] = scf[0]; break; default: scf[0] = (uint8_t)GETBITS(6); scf[1] = (uint8_t)GETBITS(6); scf[2] = scf[1]; break; } scf += 3; } } } static void II_decode_samples(mpadec_t mpadec, uint8_t *bit_alloc, uint8_t *scalefac, MYFLT fraction[2][4][SBLIMIT], int x1) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; alloc_table_t *alloc = mpa->frame.alloc_table, *alloc2; uint8_t *ba = bit_alloc, *scf = scalefac; unsigned i, j, k, step, sblimit = mpa->frame.sblimit; unsigned jsbound = mpa->frame.jsbound; for (i = 0; i < jsbound; i++, alloc += (1 << step)) { step = alloc->bits; for (j = 0; j < (unsigned)mpa->frame.channels; j++) { unsigned b = *ba++; int d; if (b) { alloc2 = alloc + b; k = alloc2->bits; d = alloc2->d; if (d < 0) { register MYFLT cm = mpa->tables.muls[k][scf[x1]]; fraction[j][0][i] = ((MYFLT)((int)GETBITS(k) + d))*cm; fraction[j][1][i] = ((MYFLT)((int)GETBITS(k) + d))*cm; fraction[j][2][i] = ((MYFLT)((int)GETBITS(k) + d))*cm; } else { unsigned idx = GETBITS(k), m = scf[x1]; uint8_t *tab = (mpa->tables.mp2tables[d] + 3*idx); fraction[j][0][i] = mpa->tables.muls[*tab++][m]; fraction[j][1][i] = mpa->tables.muls[*tab++][m]; fraction[j][2][i] = mpa->tables.muls[*tab][m]; } scf += 3; } else fraction[j][0][i] = fraction[j][1][i] = fraction[j][2][i] = 0.0; } } for (i = jsbound; i < sblimit; i++, alloc += (1 << step)) { unsigned b = ba[1]; int d; step = alloc->bits; ba += 2; if (b) { alloc2 = alloc + b; k = alloc2->bits; d = alloc2->d; if (d < 0) { register MYFLT cm = mpa->tables.muls[k][scf[x1 + 3]]; fraction[1][0][i] = fraction[0][0][i] = ((MYFLT)((int)GETBITS(k) + d))*cm; fraction[1][1][i] = fraction[0][1][i] = ((MYFLT)((int)GETBITS(k) + d))*cm; fraction[1][2][i] = fraction[0][2][i] = ((MYFLT)((int)GETBITS(k) + d))*cm; cm = mpa->tables.muls[k][scf[x1]]; fraction[0][0][i] *= cm; fraction[0][1][i] *= cm; fraction[0][2][i] *= cm; } else { unsigned idx = GETBITS(k), m1 = scf[x1], m2 = scf[x1 + 3]; uint8_t *tab = (mpa->tables.mp2tables[d] + 3*idx); fraction[0][0][i] = mpa->tables.muls[*tab][m1]; fraction[1][0][i] = mpa->tables.muls[*tab++][m2]; fraction[0][1][i] = mpa->tables.muls[*tab][m1]; fraction[1][1][i] = mpa->tables.muls[*tab++][m2]; fraction[0][2][i] = mpa->tables.muls[*tab][m1]; fraction[1][2][i] = mpa->tables.muls[*tab][m2]; } scf += 6; } else fraction[0][0][i] = fraction[0][1][i] = fraction[0][2][i] = fraction[1][0][i] = fraction[1][1][i] = fraction[1][2][i] = 0.0; } if (sblimit > (unsigned)mpa->frame.downsample_sblimit) sblimit = mpa->frame.downsample_sblimit; for (i = sblimit; i < SBLIMIT; i++) for (j = 0; j < (unsigned)mpa->frame.channels; j++) fraction[j][0][i] = fraction[j][1][i] = fraction[j][2][i] = 0.0; } void decode_layer2(mpadec_t mpadec, uint8_t *buffer) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; int i, j, table, single; MYFLT fraction[2][4][SBLIMIT]; uint8_t bit_alloc[2*SBLIMIT]; uint8_t scalefac[3*2*SBLIMIT]; static uint8_t sblimits[5] = { 27 , 30 , 8, 12 , 30 }; static uint8_t translate[3][2][16] = { { { 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 1, 1, 1, 1, 1, 0 }, { 0, 2, 2, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 } }, { { 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, { { 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 1, 1, 1, 1, 1, 0 }, { 0, 3, 3, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 } } }; mpa->error = FALSE; mpa->bits_left = 0; if (mpa->frame.LSF) table = 4; else table = translate[mpa->frame.frequency_index] [2 - mpa->frame.channels][mpa->frame.bitrate_index]; mpa->frame.alloc_table = alloc_tables[table]; mpa->frame.sblimit = sblimits[table]; mpa->frame.jsbound = (uint8_t)((mpa->frame.mode == MPG_MD_JOINT_STEREO) ? ((mpa->frame.mode_ext + 1) << 2) : mpa->frame.sblimit); if (mpa->frame.channels > 1) switch (mpa->config.mode) { case MPADEC_CONFIG_MONO: single = 0; break; case MPADEC_CONFIG_CHANNEL1: single = 1; break; case MPADEC_CONFIG_CHANNEL2: single = 2; break; default: single = -1; break; } else single = 1; II_decode_bitalloc(mpa, bit_alloc, scalefac); for (i = 0; i < SCALE_BLOCK; i++) { II_decode_samples(mpa, bit_alloc, scalefac, fraction, i >> 2); if (!single) for (j = 0; j < 3; j++) { register int k; for (k = 0; k < SBLIMIT; k++) fraction[0][j][k] = 0.5*(fraction[0][j][k] + fraction[1][j][k]); } if (single < 0) { for (j = 0; j < 3; j++, buffer += mpa->synth_size) { mpa->synth_func(mpa, fraction[0][j], 0, buffer); mpa->synth_func(mpa, fraction[1][j], 1, buffer); } } else if (!single) { for (j = 0; j < 3; j++, buffer += mpa->synth_size) { mpa->synth_func(mpa, fraction[0][j], 0, buffer); } } else { for (j = 0; j < 3; j++, buffer += mpa->synth_size) { mpa->synth_func(mpa, fraction[single - 1][j], 0, buffer); } } } { register unsigned n = mpa->bits_left >> 3; mpa->next_byte -= n; mpa->bytes_left += n; mpa->reservoir_size = 0; } } csound-6.10.0/InOut/libmpadec/layer3.c000066400000000000000000001064061321653344700174310ustar00rootroot00000000000000 /* * mpadec - MPEG audio decoder * Copyright (C) 2002-2004 Dmitriy Startsev (dstartsev@rambler.ru) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* $Id: layer3.c,v 1.3 2009/03/01 15:27:05 jpff Exp $ */ #include "mpadec_internal.h" extern const uint32_t bitmask[17]; extern bandinfo_t band_info[]; extern newhuff_t hufft[], hufftc[]; extern const MYFLT newcos[8]; extern const MYFLT tfcos36[9]; extern const MYFLT tfcos12[3]; extern const MYFLT cs[8]; extern const MYFLT ca[8]; extern uint32_t getbits(mpadec_t mpadec, unsigned n); extern uint16_t update_crc(uint16_t init, uint8_t *buf, int length); static int decode_layer3_sideinfo(mpadec_t mpadec) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; int ch, gr, ms_stereo, powdiff, databits = 0; static const uint8_t tabs[2][5] = { { 2, 9, 5, 3, 4 }, { 1, 8, 1, 2, 9 } }; const uint8_t *tab = tabs[mpa->frame.LSF]; ms_stereo = ((mpa->frame.mode == MPG_MD_JOINT_STEREO) && (mpa->frame.mode_ext & 2)); powdiff = ((mpa->frame.channels > 1) && (mpa->config.mode == MPADEC_CONFIG_MONO)) ? 4 : 0; mpa->sideinfo.main_data_begin = GETBITS(tab[1]); if (mpa->frame.channels == 1) mpa->sideinfo.private_bits = GETBITS(tab[2]); else mpa->sideinfo.private_bits = GETBITS(tab[3]); if (!mpa->frame.LSF) { for (ch = 0; ch < mpa->frame.channels; ch++) { mpa->sideinfo.ch[ch].gr[0].scfsi = -1; mpa->sideinfo.ch[ch].gr[1].scfsi = GETBITS(4); } } for (gr = 0; gr < tab[0]; gr++) { for (ch = 0; ch < mpa->frame.channels; ch++) { register grinfo_t *grinfo = &mpa->sideinfo.ch[ch].gr[gr]; grinfo->part2_3_length = GETBITS(12); grinfo->big_values = GETBITS(9); databits += grinfo->part2_3_length; if (grinfo->big_values > 288) grinfo->big_values = 288; grinfo->pow2gain = mpa->tables.gainpow2 + 256 - GETBITS(8) + powdiff; if (ms_stereo) grinfo->pow2gain += 2; grinfo->scalefac_compress = GETBITS(tab[4]); if (GETBITS(1)) { grinfo->block_type = (uint8_t)GETBITS(2); grinfo->mixed_block_flag = (uint8_t)GETBITS(1); grinfo->table_select[0] = GETBITS(5); grinfo->table_select[1] = GETBITS(5); grinfo->table_select[2] = 0; grinfo->full_gain[0] = grinfo->pow2gain + (GETBITS(3) << 3); grinfo->full_gain[1] = grinfo->pow2gain + (GETBITS(3) << 3); grinfo->full_gain[2] = grinfo->pow2gain + (GETBITS(3) << 3); if (!grinfo->block_type) { mpa->error = TRUE; return 0; } else mpa->error = FALSE; if (mpa->frame.LSF) { if (grinfo->block_type == 2) { if (grinfo->mixed_block_flag) { if (mpa->frame.frequency_index == 8) grinfo->region1start = 48; else grinfo->region1start = 48 >> 1; } else { if (mpa->frame.frequency_index == 8) grinfo->region1start = 36; else grinfo->region1start = 36 >> 1; } } else { if (mpa->frame.frequency_index == 8) grinfo->region1start = 54; else grinfo->region1start = 54 >> 1; } } else grinfo->region1start = 36 >> 1; grinfo->region2start = 576 >> 1; } else { grinfo->block_type = 0; grinfo->mixed_block_flag = 0; grinfo->table_select[0] = GETBITS(5); grinfo->table_select[1] = GETBITS(5); grinfo->table_select[2] = GETBITS(5); { register int tmp = GETBITS(4); grinfo->region1start = band_info[mpa->frame.frequency_index].long_idx[tmp + 1] >> 1; tmp += GETBITS(3); grinfo->region2start = band_info[mpa->frame.frequency_index].long_idx[tmp + 2] >> 1; } } if (!mpa->frame.LSF) grinfo->preflag = (uint8_t)GETBITS(1); grinfo->scalefac_scale = (uint8_t)GETBITS(1); grinfo->count1table_select = (uint8_t)GETBITS(1); } } databits -= 8*mpa->sideinfo.main_data_begin; return databits; } static int III_get_scale_factors(mpadec_t mpadec, grinfo_t *gr_info, int32_t *scf) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; register grinfo_t *grinfo = gr_info; int numbits = 0; static uint8_t slen[2][16] = { {0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4}, {0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3} }; static uint8_t stab[3][6][4] = { { { 6, 5, 5,5 } , { 6, 5, 7,3 } , { 11,10,0,0} , { 7, 7, 7,0 } , { 6, 6, 6,3 } , { 8, 8,5,0} } , { { 9, 9, 9,9 } , { 9, 9,12,6 } , { 18,18,0,0} , {12,12,12,0 } , {12, 9, 9,6 } , { 15,12,9,0} } , { { 6, 9, 9,9 } , { 6, 9,12,6 } , { 15,18,0,0} , { 6,15,12,0 } , { 6,12, 9,6 } , { 6,18,9,0} } }; if (!mpa->frame.LSF) { int i, num0 = slen[0][grinfo->scalefac_compress], num1 = slen[1][grinfo->scalefac_compress]; if (grinfo->block_type == 2) { i = 18; numbits = 18*(num0 + num1); if (grinfo->mixed_block_flag) { i--; numbits -= num0; } for (; i; i--) *scf++ = GETBITS(num0); for (i = 18; i; i--) *scf++ = GETBITS(num1); scf[0] = scf[1] = scf[2] = 0; } else { if (grinfo->scfsi < 0) { for (i = 11; i; i--) *scf++ = GETBITS(num0); for (i = 10; i; i--) *scf++ = GETBITS(num1); numbits = 10*(num0 + num1) + num0; *scf = 0; } else { numbits = 0; if (!(grinfo->scfsi & 8)) { for (i = 6; i; i--) *scf++ = GETBITS(num0); numbits += 6*num0; } else scf += 6; if (!(grinfo->scfsi & 4)) { for (i = 5; i; i--) *scf++ = GETBITS(num0); numbits += 5*num0; } else scf += 5; if (!(grinfo->scfsi & 2)) { for (i = 5; i; i--) *scf++ = GETBITS(num1); numbits += 5*num1; } else scf += 5; if (!(grinfo->scfsi & 1)) { for (i = 5; i; i--) *scf++ = GETBITS(num1); numbits += 5*num1; } else scf += 5; *scf = 0; } } } else { int i, j, n = 0; unsigned s_len; uint8_t *pnt; if ((mpa->frame.mode == MPG_MD_JOINT_STEREO) && (mpa->frame.mode_ext & 1)) { s_len = mpa->tables.i_slen2[grinfo->scalefac_compress >> 1]; } else s_len = mpa->tables.n_slen2[grinfo->scalefac_compress]; grinfo->preflag = (uint8_t)((s_len >> 15) & 1); if (grinfo->block_type == 2) n = grinfo->mixed_block_flag ? 2 : 1; pnt = stab[n][(s_len >> 12) & 7]; for (i = 0; i < 4; i++) { int num = s_len & 7; s_len >>= 3; if (num) { for (j = 0; j < (int)pnt[i]; j++) *scf++ = GETBITS(num); numbits += pnt[i]*num; } else for (j = 0; j < (int)pnt[i]; j++) *scf++ = 0; } for (i = (n << 1) + 1; i; i--) *scf++ = 0; } return numbits; } static int III_decode_samples(mpadec_t mpadec, grinfo_t *gr_info, MYFLT xr[SBLIMIT][SSLIMIT], int32_t *scf, int part2bits) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; register grinfo_t *grinfo = gr_info; int shift = 1 + grinfo->scalefac_scale, l[3], l3; int part2remain = grinfo->part2_3_length - part2bits; MYFLT *xrptr = (MYFLT *)xr; int32_t *me; static uint8_t pretab1[22] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3, 2, 0 }; static uint8_t pretab2[22] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; l3 = ((576 >> 1) - grinfo->big_values) >> 1; if (grinfo->big_values <= grinfo->region1start) { l[0] = grinfo->big_values; l[1] = l[2] = 0; } else { l[0] = grinfo->region1start; if (grinfo->big_values <= grinfo->region2start) { l[1] = grinfo->big_values - l[0]; l[2] = 0; } else { l[1] = grinfo->region2start - l[0]; l[2] = grinfo->big_values - grinfo->region2start; } } if (grinfo->block_type == 2) { int32_t i, max[4], step = 0, lwin = 0, cb = 0; register MYFLT v = 0.0; register int32_t *m, mc; if (grinfo->mixed_block_flag) { max[3] = -1; max[0] = max[1] = max[2] = 2; m = mpa->tables.map[mpa->frame.frequency_index][0]; me = mpa->tables.mapend[mpa->frame.frequency_index][0]; } else { max[0] = max[1] = max[2] = max[3] = -1; m = mpa->tables.map[mpa->frame.frequency_index][1]; me = mpa->tables.mapend[mpa->frame.frequency_index][1]; } mc = 0; for (i = 0; i < 2; i++) { int lp = l[i]; newhuff_t *h = hufft + grinfo->table_select[i]; for (; lp; lp--, mc--) { register int x, y; if (!mc) { mc = *m++; xrptr = ((MYFLT *)xr) + (*m++); lwin = *m++; cb = *m++; if (lwin == 3) { v = grinfo->pow2gain[(*scf++) << shift]; step = 1; } else { v = grinfo->full_gain[lwin][(*scf++) << shift]; step = 3; } } { register int16_t *val = h->table; while ((y = *val++) < 0) { if (GETBITS(1)) val -= y; part2remain--; } x = y >> 4; y &= 0x0F; } if ((x == 15) && h->linbits) { max[lwin] = cb; part2remain -= h->linbits + 1; x += GETBITS(h->linbits); if (GETBITS(1)) *xrptr = -mpa->tables.ispow[x]*v; else *xrptr = mpa->tables.ispow[x]*v; } else if (x) { max[lwin] = cb; if (GETBITS(1)) *xrptr = -mpa->tables.ispow[x]*v; else *xrptr = mpa->tables.ispow[x]*v; part2remain--; } else *xrptr = 0.0; xrptr += step; if ((y == 15) && h->linbits) { max[lwin] = cb; part2remain -= h->linbits + 1; y += GETBITS(h->linbits); if (GETBITS(1)) *xrptr = -mpa->tables.ispow[y]*v; else *xrptr = mpa->tables.ispow[y]*v; } else if (y) { max[lwin] = cb; if (GETBITS(1)) *xrptr = -mpa->tables.ispow[y]*v; else *xrptr = mpa->tables.ispow[y]*v; part2remain--; } else *xrptr = 0.0; xrptr += step; } } for (; l3 && (part2remain > 0); l3--) { newhuff_t *h = hufftc + grinfo->count1table_select; register int16_t *val = h->table, a; while ((a = *val++) < 0) { part2remain--; if (part2remain < 0) { part2remain++; a = 0; break; } if (GETBITS(1)) val -= a; } for (i = 0; i < 4; i++) { if (!(i & 1)) { if (!mc) { mc = *m++; xrptr = ((MYFLT *)xr) + (*m++); lwin = *m++; cb = *m++; if (lwin == 3) { v = grinfo->pow2gain[(*scf++) << shift]; step = 1; } else { v = grinfo->full_gain[lwin][(*scf++) << shift]; step = 3; } } mc--; } if (a & (8 >> i)) { max[lwin] = cb; part2remain--; if (part2remain < 0) { part2remain++; break; } if (GETBITS(1)) *xrptr = -v; else *xrptr = v; } else *xrptr = 0.0; xrptr += step; } } if (lwin < 3) { while (1) { for (; mc > 0; mc--) { xrptr[0] = xrptr[3] = 0.0; xrptr += 6; } if (m >= me) break; mc = *m++; xrptr = ((MYFLT *)xr) + (*m++); if ((*m++) == 0) break; m++; } } grinfo->maxband[0] = max[0] + 1; grinfo->maxband[1] = max[1] + 1; grinfo->maxband[2] = max[2] + 1; grinfo->maxbandl = max[3] + 1; { int rmax = max[0] > max[1] ? max[0] : max[1]; rmax = (rmax > max[2] ? rmax : max[2]) + 1; grinfo->maxb = rmax ? mpa->tables.short_limit[mpa->frame.frequency_index][rmax] : mpa->tables.long_limit[mpa->frame.frequency_index][max[3] + 1]; } } else { uint8_t *pretab = grinfo->preflag ? pretab1 : pretab2; int32_t i, max = -1, cb = 0, mc = 0; int32_t *m = mpa->tables.map[mpa->frame.frequency_index][2]; register MYFLT v = 0.0; for (i = 0; i < 3; i++) { int lp = l[i]; newhuff_t *h = hufft + grinfo->table_select[i]; for (; lp; lp--, mc--) { register int x, y; if (!mc) { mc = *m++; cb = *m++; if (cb == 21) v = 0.0; else v = grinfo->pow2gain[((*scf++) + (*pretab++)) << shift]; } { register int16_t *val = h->table; while ((y = *val++) < 0) { if (GETBITS(1)) val -= y; part2remain--; } x = y >> 4; y &= 0x0F; } if ((x == 15) && h->linbits) { max = cb; part2remain -= h->linbits + 1; x += GETBITS(h->linbits); if (GETBITS(1)) *xrptr++ = -mpa->tables.ispow[x]*v; else *xrptr++ = mpa->tables.ispow[x]*v; } else if (x) { max = cb; if (GETBITS(1)) *xrptr++ = -mpa->tables.ispow[x]*v; else *xrptr++ = mpa->tables.ispow[x]*v; part2remain--; } else *xrptr++ = 0.0; if ((y == 15) && h->linbits) { max = cb; part2remain -= h->linbits + 1; y += GETBITS(h->linbits); if (GETBITS(1)) *xrptr++ = -mpa->tables.ispow[y]*v; else *xrptr++ = mpa->tables.ispow[y]*v; } else if (y) { max = cb; if (GETBITS(1)) *xrptr++ = -mpa->tables.ispow[y]*v; else *xrptr++ = mpa->tables.ispow[y]*v; part2remain--; } else *xrptr++ = 0.0; } } for (; l3 && (part2remain > 0); l3--) { newhuff_t *h = hufftc + grinfo->count1table_select; register int16_t *val = h->table, a; while ((a = *val++) < 0) { part2remain--; if (part2remain < 0) { part2remain++; a = 0; break; } if (GETBITS(1)) val -= a; } for (i = 0; i < 4; i++) { if (!(i & 1)) { if (!mc) { mc = *m++; cb = *m++; v = grinfo->pow2gain[((*scf++) + (*pretab++)) << shift]; } mc--; } if (a & (8 >> i)) { max = cb; part2remain--; if (part2remain < 0) { part2remain++; break; } if (GETBITS(1)) *xrptr++ = -v; else *xrptr++ = v; } else *xrptr++ = 0.0; } } grinfo->maxbandl = max + 1; grinfo->maxb = mpa->tables.long_limit[mpa->frame.frequency_index][max + 1]; } while (xrptr < &xr[SBLIMIT][0]) *xrptr++ = 0.0; while (part2remain > 0) { register unsigned tmp, i = (part2remain > 16) ? 16 : part2remain; tmp = GETBITS(i); part2remain -= i; i = tmp; } mpa->error = (uint8_t)((part2remain < 0) ? TRUE : FALSE); return mpa->error; } static void III_i_stereo(mpadec_t mpadec, grinfo_t *gr_info, MYFLT xrbuf[2][SBLIMIT][SSLIMIT], int32_t *scalefac) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; register grinfo_t *grinfo = gr_info; MYFLT (*xr)[SBLIMIT*SSLIMIT] = (MYFLT (*)[SBLIMIT*SSLIMIT])xrbuf; bandinfo_t *bi = &band_info[mpa->frame.frequency_index]; int tab = mpa->frame.LSF + (grinfo->scalefac_compress & mpa->frame.LSF); int ms_stereo = ((mpa->frame.mode == MPG_MD_JOINT_STEREO) && (mpa->frame.mode_ext & 2)) ? TRUE : FALSE; const MYFLT *tab1, *tab2; tab1 = mpa->tables.istabs[tab][ms_stereo][0]; tab2 = mpa->tables.istabs[tab][ms_stereo][1]; if (grinfo->block_type == 2) { int lwin, do_l = grinfo->mixed_block_flag; for (lwin = 0; lwin < 3; lwin++) { int32_t is_p, sb, idx, sfb = grinfo->maxband[lwin]; if (sfb > 3) do_l = FALSE; for (; sfb < 12; sfb++) { is_p = scalefac[3*sfb + lwin - grinfo->mixed_block_flag]; if (is_p != 7) { MYFLT t1 = tab1[is_p], t2 = tab2[is_p]; sb = bi->short_diff[sfb]; idx = bi->short_idx[sfb] + lwin; for (; sb; sb--, idx += 3) { register MYFLT v = xr[0][idx]; xr[0][idx] = v*t1; xr[1][idx] = v*t2; } } } is_p = scalefac[3*11 + lwin - grinfo->mixed_block_flag]; sb = bi->short_diff[12]; idx = bi->short_idx[12] + lwin; if (is_p != 7) { MYFLT t1 = tab1[is_p], t2 = tab2[is_p]; for (; sb; sb--, idx += 3) { register MYFLT v = xr[0][idx]; xr[0][idx] = v*t1; xr[1][idx] = v*t2; } } } if (do_l) { int sfb = grinfo->maxbandl; int idx = bi->long_idx[sfb]; for (; sfb < 8; sfb++) { int sb = bi->long_diff[sfb]; int is_p = scalefac[sfb]; if (is_p != 7) { MYFLT t1 = tab1[is_p], t2 = tab2[is_p]; for (; sb; sb--, idx++) { register MYFLT v = xr[0][idx]; xr[0][idx] = v*t1; xr[1][idx] = v*t2; } } else idx += sb; } } } else { int sfb = grinfo->maxbandl; int is_p, idx = bi->long_idx[sfb]; for (; sfb < 21; sfb++) { int sb = bi->long_diff[sfb]; is_p = scalefac[sfb]; if (is_p != 7) { MYFLT t1 = tab1[is_p], t2 = tab2[is_p]; for (; sb; sb--, idx++) { register MYFLT v = xr[0][idx]; xr[0][idx] = v*t1; xr[1][idx] = v*t2; } } else idx += sb; } is_p = scalefac[20]; if (is_p != 7) { int sb = bi->long_diff[21]; MYFLT t1 = tab1[is_p], t2 = tab2[is_p]; for (; sb; sb--, idx++) { register MYFLT v = xr[0][idx]; xr[0][idx] = v*t1; xr[1][idx] = v*t2; } } } } static void III_antialias(grinfo_t *gr_info, MYFLT xr[SBLIMIT][SSLIMIT]) { register grinfo_t *grinfo = gr_info; int sblim; if (grinfo->block_type == 2) { if (!grinfo->mixed_block_flag) return; sblim = 1; } else sblim = grinfo->maxb - 1; { int sb; MYFLT *xr1 = (MYFLT *)xr[1]; for (sb = sblim; sb; sb--, xr1 += 10) { int ss; MYFLT *xr2 = xr1; for (ss = 0; ss < 8; ss++) { register MYFLT bu = *--xr2, bd = *xr1; *xr2 = bu*cs[ss] - bd*ca[ss]; *xr1++ = bd*cs[ss] + bu*ca[ss]; } } } } static void dct36(register MYFLT *in, register MYFLT *out1, register MYFLT *out2, register MYFLT *w, register MYFLT *ts) { MYFLT tmp[18]; { in[17] += in[16]; in[16] += in[15]; in[15] += in[14]; in[14] += in[13]; in[13] += in[12]; in[12] += in[11]; in[11] += in[10]; in[10] += in[9]; in[9] += in[8]; in[8] += in[7]; in[7] += in[6]; in[6] += in[5]; in[5] += in[4]; in[4] += in[3]; in[3] += in[2]; in[2] += in[1]; in[1] += in[0]; in[17] += in[15]; in[15] += in[13]; in[13] += in[11]; in[11] += in[9]; in[9] += in[7]; in[7] += in[5]; in[5] += in[3]; in[3] += in[1]; { MYFLT t3; { MYFLT t0, t1, t2; t0 = newcos[7]*(in[8] + in[16] - in[4]); t1 = newcos[7]*in[12]; t3 = in[0]; t2 = t3 - t1 - t1; tmp[1] = tmp[7] = t2 - t0; tmp[4] = t2 + t0 + t0; t3 += t1; t2 = newcos[6]*(in[10] + in[14] - in[2]); tmp[1] -= t2; tmp[7] += t2; } { MYFLT t0, t1, t2; t0 = newcos[0]*(in[4] + in[8]); t1 = newcos[1]*(in[8] - in[16]); t2 = newcos[2]*(in[4] + in[16]); tmp[2] = tmp[6] = t3 - t0 - t2; tmp[0] = tmp[8] = t3 + t0 + t1; tmp[3] = tmp[5] = t3 - t1 + t2; } } { MYFLT t1, t2, t3; t1 = newcos[3]*(in[2] + in[10]); t2 = newcos[4]*(in[10] - in[14]); t3 = newcos[6]*in[6]; { MYFLT t0 = t1 + t2 + t3; tmp[0] += t0; tmp[8] -= t0; } t2 -= t3; t1 -= t3; t3 = newcos[5]*(in[2] + in[14]); t1 += t3; tmp[3] += t1; tmp[5] -= t1; t2 -= t3; tmp[2] += t2; tmp[6] -= t2; } { MYFLT t0, t1, t2, t3, t4, t5, t6, t7; t1 = newcos[7]*in[13]; t2 = newcos[7]*(in[9] + in[17] - in[5]); t3 = in[1] + t1; t4 = in[1] - t1 - t1; t5 = t4 - t2; t0 = newcos[0]*(in[5] + in[9]); t1 = newcos[1]*(in[9] - in[17]); tmp[13] = (t4 + t2 + t2)*tfcos36[17 - 13]; t2 = newcos[2]*(in[5] + in[17]); t6 = t3 - t0 - t2; t0 += t3 + t1; t3 += t2 - t1; t2 = newcos[3]*(in[3] + in[11]); t4 = newcos[4]*(in[11] - in[15]); t7 = newcos[6]*in[7]; t1 = t2 + t4 + t7; tmp[17] = (t0 + t1)*tfcos36[17 - 17]; tmp[9] = (t0 - t1)*tfcos36[17 - 9]; t1 = newcos[5]*(in[3] + in[15]); t2 += t1 - t7; tmp[14] = (t3 + t2)*tfcos36[17 - 14]; t0 = newcos[6]*(in[11] + in[15] - in[3]); tmp[12] = (t3 - t2)*tfcos36[17 - 12]; t4 -= t1 + t7; tmp[16] = (t5 - t0)*tfcos36[17 - 16]; tmp[10] = (t5 + t0)*tfcos36[17 - 10]; tmp[15] = (t6 + t4)*tfcos36[17 - 15]; tmp[11] = (t6 - t4)*tfcos36[17 - 11]; } } #define DCT36_MACRO(v) { \ register MYFLT tmpval = tmp[(v)] + tmp[17 - (v)]; \ out2[9 + (v)] = tmpval*w[27 + (v)]; \ out2[8 - (v)] = tmpval*w[26 - (v)]; \ tmpval = tmp[(v)] - tmp[17 - (v)]; \ ts[SBLIMIT*(8 - (v))] = out1[8 - (v)] + tmpval*w[8 - (v)]; \ ts[SBLIMIT*(9 + (v))] = out1[9 + (v)] + tmpval*w[9 + (v)]; \ } { DCT36_MACRO(0); DCT36_MACRO(1); DCT36_MACRO(2); DCT36_MACRO(3); DCT36_MACRO(4); DCT36_MACRO(5); DCT36_MACRO(6); DCT36_MACRO(7); DCT36_MACRO(8); } #undef DCT36_MACRO } static void dct12(register MYFLT *in, register MYFLT *out1, register MYFLT *out2, register MYFLT *w, register MYFLT *ts) { #define DCT12_PART1 in5 = in[5*3]; \ in5 += (in4 = in[4*3]); \ in4 += (in3 = in[3*3]); \ in3 += (in2 = in[2*3]); \ in2 += (in1 = in[1*3]); \ in1 += (in0 = in[0*3]); \ in5 += in3; in3 += in1; \ in2 *= newcos[6]; \ in3 *= newcos[6]; #define DCT12_PART2 in0 += in4*newcos[7]; \ in4 = in0 + in2; \ in0 -= in2; \ in1 += in5*newcos[7]; \ in5 = (in1 + in3)*tfcos12[0]; \ in1 = (in1 - in3)*tfcos12[2]; \ in3 = in4 + in5; \ in4 -= in5; \ in2 = in0 + in1; \ in0 -= in1; { MYFLT in0, in1, in2, in3, in4, in5; ts[0*SBLIMIT] = out1[0]; ts[1*SBLIMIT] = out1[1]; ts[2*SBLIMIT] = out1[2]; ts[3*SBLIMIT] = out1[3]; ts[4*SBLIMIT] = out1[4]; ts[5*SBLIMIT] = out1[5]; DCT12_PART1 { register MYFLT tmp0, tmp1 = in0 - in4; { register MYFLT tmp2 = (in1 - in5)*tfcos12[1]; tmp0 = tmp1 + tmp2; tmp1 -= tmp2; } ts[(17 - 1)*SBLIMIT] = out1[17 - 1] + tmp0*w[11 - 1]; ts[(12 + 1)*SBLIMIT] = out1[12 + 1] + tmp0*w[6 + 1]; ts[(6 + 1)*SBLIMIT] = out1[6 + 1] + tmp1*w[1]; ts[(11 - 1)*SBLIMIT] = out1[11 - 1] + tmp1*w[5 - 1]; } DCT12_PART2 ts[(17 - 0)*SBLIMIT] = out1[17 - 0] + in2*w[11 - 0]; ts[(12 + 0)*SBLIMIT] = out1[12 + 0] + in2*w[6 + 0]; ts[(12 + 2)*SBLIMIT] = out1[12 + 2] + in3*w[6 + 2]; ts[(17 - 2)*SBLIMIT] = out1[17 - 2] + in3*w[11 - 2]; ts[(6 + 0)*SBLIMIT] = out1[6 + 0] + in0*w[0]; ts[(11 - 0)*SBLIMIT] = out1[11 - 0] + in0*w[5 - 0]; ts[(6 + 2)*SBLIMIT] = out1[6 + 2] + in4*w[2]; ts[(11 - 2)*SBLIMIT] = out1[11 - 2] + in4*w[5 - 2]; } in++; { MYFLT in0, in1, in2, in3, in4, in5; DCT12_PART1 { register MYFLT tmp0, tmp1 = in0 - in4; { register MYFLT tmp2 = (in1 - in5)*tfcos12[1]; tmp0 = tmp1 + tmp2; tmp1 -= tmp2; } out2[5 - 1] = tmp0*w[11 - 1]; out2[0 + 1] = tmp0*w[6 + 1]; ts[(12 + 1)*SBLIMIT] += tmp1*w[0 + 1]; ts[(17 - 1)*SBLIMIT] += tmp1*w[5 - 1]; } DCT12_PART2 out2[5 - 0] = in2*w[11 - 0]; out2[0 + 0] = in2*w[6 + 0]; out2[0 + 2] = in3*w[6 + 2]; out2[5 - 2] = in3*w[11 - 2]; ts[(12 + 0)*SBLIMIT] += in0*w[0]; ts[(17 - 0)*SBLIMIT] += in0*w[5 - 0]; ts[(12 + 2)*SBLIMIT] += in4*w[2]; ts[(17 - 2)*SBLIMIT] += in4*w[5 - 2]; } in++; { MYFLT in0, in1, in2, in3, in4, in5; out2[12] = out2[13] = out2[14] = out2[15] = out2[16] = out2[17] = 0.0; DCT12_PART1 { register MYFLT tmp0, tmp1 = in0 - in4; { register MYFLT tmp2 = (in1 - in5)*tfcos12[1]; tmp0 = tmp1 + tmp2; tmp1 -= tmp2; } out2[11 - 1] = tmp0*w[11 - 1]; out2[6 + 1] = tmp0*w[6 + 1]; out2[0 + 1] += tmp1*w[1]; out2[5 - 1] += tmp1*w[5 - 1]; } DCT12_PART2 out2[11 - 0] = in2*w[11 - 0]; out2[6 + 0] = in2*w[6 + 0]; out2[6 + 2] = in3*w[6 + 2]; out2[11 - 2] = in3*w[11 - 2]; out2[0 + 0] += in0*w[0]; out2[5 - 0] += in0*w[5 - 0]; out2[0 + 2] += in4*w[2]; out2[5 - 2] += in4*w[5 - 2]; } #undef DCT12_PART1 #undef DCT12_PART2 } static void III_hybrid(mpadec_t mpadec, grinfo_t *gr_info, MYFLT fs_in[SBLIMIT][SSLIMIT], MYFLT ts_out[SSLIMIT][SBLIMIT], int channel) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; register grinfo_t *grinfo = gr_info; MYFLT *tsptr = (MYFLT *)ts_out; MYFLT *out1, *out2; unsigned bt = grinfo->block_type, sb = 0; { register unsigned b = mpa->hybrid_block[channel]; out1 = mpa->hybrid_buffers[b][channel]; b ^= 1; out2 = mpa->hybrid_buffers[b][channel]; mpa->hybrid_block[channel] = (uint8_t)b; } if (grinfo->mixed_block_flag) { sb = 2; dct36(fs_in[0], out1, out2, mpa->tables.win[0][0], tsptr); dct36(fs_in[1], out1 + SSLIMIT, out2 + SSLIMIT, mpa->tables.win[1][0], tsptr + 1); out1 += 36; out2 += 36; tsptr += 2; } if (bt == 2) { for (; sb < grinfo->maxb; sb += 2, out1 += 36, out2 += 36, tsptr += 2) { dct12(fs_in[sb], out1, out2, mpa->tables.win[0][2], tsptr); dct12(fs_in[sb + 1], out1 + SSLIMIT, out2 + SSLIMIT, mpa->tables.win[1][2], tsptr + 1); } } else { for (; sb < grinfo->maxb; sb += 2, out1 += 36, out2 += 36, tsptr += 2) { dct36(fs_in[sb], out1, out2, mpa->tables.win[0][bt], tsptr); dct36(fs_in[sb + 1], out1 + SSLIMIT, out2 + SSLIMIT, mpa->tables.win[1][bt], tsptr + 1); } } for (; sb < SBLIMIT; sb++, tsptr++) { register int i; for (i = 0; i < SSLIMIT; i++) { tsptr[i*SBLIMIT] = *out1++; *out2++ = 0.0; } } } void decode_layer3(mpadec_t mpadec, uint8_t *buffer) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; uint8_t *saved_next_byte = mpa->next_byte; uint32_t saved_bytes_left = mpa->bytes_left; int32_t dbits, scalefacs[2][39]; int ch, gr, ss, i_stereo, ms_stereo, single, channels, granules = mpa->frame.LSF ? 1 : 2; mpa->error = FALSE; mpa->bits_left = 0; if (mpa->config.crc && mpa->frame.CRC) { mpa->crc = update_crc(mpa->crc, mpa->next_byte, mpa->ssize << 3); if (mpa->crc != mpa->frame.crc) mpa->error = TRUE; } dbits = decode_layer3_sideinfo(mpa); mpa->dsize = (((dbits < 0) ? 0 : dbits) + 7) >> 3; mpa->next_byte = saved_next_byte + mpa->ssize; mpa->bytes_left = saved_bytes_left - mpa->ssize; mpa->bits_left = 0; saved_next_byte = NULL; saved_bytes_left = mpa->bytes_left; if (mpa->error) mpa->sideinfo.main_data_begin = mpa->reservoir_size + 1; if (mpa->sideinfo.main_data_begin) { if (mpa->sideinfo.main_data_begin <= mpa->reservoir_size) { uint8_t *ptr = mpa->reservoir + mpa->reservoir_size; uint32_t tmp = mpa->frame.frame_size - mpa->hsize - mpa->ssize; if (tmp > (sizeof(mpa->reservoir) - mpa->reservoir_size)) tmp = sizeof(mpa->reservoir) - mpa->reservoir_size; saved_next_byte = mpa->next_byte; memcpy(ptr, mpa->next_byte, tmp); mpa->next_byte = ptr - mpa->sideinfo.main_data_begin; mpa->bytes_left = mpa->sideinfo.main_data_begin + tmp; } else { uint32_t tmp = mpa->frame.frame_size - mpa->hsize - mpa->ssize; if (tmp > 512) { mpa->next_byte += tmp - 512; mpa->bytes_left -= tmp - 512; tmp = 512; } if ((mpa->reservoir_size) && (mpa->reservoir_size > 512)) { memmove(mpa->reservoir, mpa->reservoir + mpa->reservoir_size - 512, 512); mpa->reservoir_size = 512; } memcpy(mpa->reservoir + mpa->reservoir_size, mpa->next_byte, tmp); mpa->reservoir_size += tmp; mpa->next_byte += tmp; mpa->bytes_left -= tmp; memset(buffer, 0, mpa->frame.decoded_size); mpa->error = TRUE; return; } } if (mpa->frame.mode == MPG_MD_JOINT_STEREO) { i_stereo = mpa->frame.mode_ext & 1; ms_stereo = (mpa->frame.mode_ext & 2) >> 1; } else i_stereo = ms_stereo = 0; if (mpa->frame.channels > 1) switch (mpa->config.mode) { case MPADEC_CONFIG_MONO: single = 0; break; case MPADEC_CONFIG_CHANNEL1: single = 1; break; case MPADEC_CONFIG_CHANNEL2: single = 2; break; default: single = -1; break; } else single = 1; channels = (single < 0) ? 2 : 1; for (gr = 0; gr < granules; gr++) { grinfo_t *grinfo = &mpa->sideinfo.ch[0].gr[gr]; int32_t part2bits = III_get_scale_factors(mpa, grinfo, scalefacs[0]); if (III_decode_samples(mpa, grinfo, mpa->hybrid_in[0], scalefacs[0], part2bits)) { unsigned size = mpa->frame.decoded_size; if (!mpa->frame.LSF && gr) size >>= 1; memset(buffer, 0, size); mpa->error = TRUE; goto done; } if (mpa->frame.channels > 1) { grinfo = &mpa->sideinfo.ch[1].gr[gr]; part2bits = III_get_scale_factors(mpa, grinfo, scalefacs[1]); if (III_decode_samples(mpa, grinfo, mpa->hybrid_in[1], scalefacs[1], part2bits)) { unsigned size = mpa->frame.decoded_size; if (!mpa->frame.LSF && gr) size >>= 1; memset(buffer, 0, size); mpa->error = TRUE; goto done; } if (ms_stereo) { MYFLT *in0 = (MYFLT *)(mpa->hybrid_in[0]), *in1 = (MYFLT *)(mpa->hybrid_in[1]); unsigned i, maxb = mpa->sideinfo.ch[0].gr[gr].maxb; if (mpa->sideinfo.ch[1].gr[gr].maxb > maxb) maxb = mpa->sideinfo.ch[1].gr[gr].maxb; for (i = 0; i < SSLIMIT*maxb; i++) { register MYFLT tmp0 = in0[i]; register MYFLT tmp1 = in1[i]; in0[i] = tmp0 + tmp1; in1[i] = tmp0 - tmp1; } } if (i_stereo) III_i_stereo(mpa, grinfo, mpa->hybrid_in, scalefacs[1]); if (i_stereo || ms_stereo || !single) { if (grinfo->maxb > mpa->sideinfo.ch[0].gr[gr].maxb) mpa->sideinfo.ch[0].gr[gr].maxb = grinfo->maxb; else grinfo->maxb = mpa->sideinfo.ch[0].gr[gr].maxb; } if (!single) { register unsigned i; MYFLT *in0 = (MYFLT *)(mpa->hybrid_in[0]), *in1 = (MYFLT *)(mpa->hybrid_in[1]); for (i = 0; i < SSLIMIT*grinfo->maxb; i++, in0++) *in0 = (*in0 + *in1++); } else if (single == 2) { register unsigned i; MYFLT *in0 = (MYFLT *)(mpa->hybrid_in[0]), *in1 = (MYFLT *)(mpa->hybrid_in[1]); for (i = 0; i < SSLIMIT*grinfo->maxb; i++, in0++) *in0 = *in1++; } } for (ch = 0; ch < channels; ch++) { grinfo = &mpa->sideinfo.ch[ch].gr[gr]; III_antialias(grinfo, mpa->hybrid_in[ch]); III_hybrid(mpa, grinfo, mpa->hybrid_in[ch], mpa->hybrid_out[ch], ch); } if (single < 0) { for (ss = 0; ss < SSLIMIT; ss++, buffer += mpa->synth_size) { mpa->synth_func(mpa, mpa->hybrid_out[0][ss], 0, buffer); mpa->synth_func(mpa, mpa->hybrid_out[1][ss], 1, buffer); } } else { for (ss = 0; ss < SSLIMIT; ss++, buffer += mpa->synth_size) { mpa->synth_func(mpa, mpa->hybrid_out[0][ss], 0, buffer); } } } done: { register unsigned n = mpa->bits_left >> 3; mpa->next_byte -= n; mpa->bytes_left += n; if (saved_next_byte) { uint32_t tmp = mpa->frame.frame_size - mpa->hsize - mpa->ssize; if (mpa->bytes_left) { if (mpa->bytes_left > 512) { mpa->next_byte += mpa->bytes_left - 512; mpa->bytes_left = 512; } memmove(mpa->reservoir, mpa->next_byte, mpa->bytes_left); mpa->reservoir_size = mpa->bytes_left; } else mpa->reservoir_size = 0; mpa->next_byte = saved_next_byte + tmp; mpa->bytes_left = saved_bytes_left - tmp; } else { uint32_t tmp = mpa->frame.frame_size - mpa->hsize - mpa->ssize; mpa->reservoir_size = 0; if (tmp > (saved_bytes_left - mpa->bytes_left)) { tmp -= saved_bytes_left - mpa->bytes_left; if (tmp > 512) { mpa->next_byte += tmp - 512; mpa->bytes_left -= tmp - 512; tmp = 512; } memcpy(mpa->reservoir, mpa->next_byte, tmp); mpa->reservoir_size = tmp; mpa->next_byte += tmp; mpa->bytes_left -= tmp; } } } } csound-6.10.0/InOut/libmpadec/mp3dec.c000066400000000000000000000355541321653344700174120ustar00rootroot00000000000000/* * mpadec - MPEG audio decoder * Copyright (C) 2002-2004 Dmitriy Startsev (dstartsev@rambler.ru) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* $Id: mp3dec.c,v 1.6 2009/03/01 15:27:05 jpff Exp $ */ #include "csoundCore.h" #include "mp3dec_internal.h" mp3dec_t mp3dec_init(void) { register struct mp3dec_t *mp3 = (struct mp3dec_t *)malloc(sizeof(struct mp3dec_t)); if (!mp3) return NULL; memset(mp3, 0, sizeof(struct mp3dec_t)); mp3->size = sizeof(struct mp3dec_t); mp3->fd = -1; mp3->mpadec = mpadec_init(); if (!mp3->mpadec) { free(mp3); return NULL; } return mp3; } int mp3dec_init_file(mp3dec_t mp3dec, int fd, int64_t length, int nogap) { register struct mp3dec_t *mp3 = (struct mp3dec_t *)mp3dec; int64_t tmp; int r; if (!mp3 || (mp3->size != sizeof(struct mp3dec_t)) || !mp3->mpadec) return MP3DEC_RETCODE_INVALID_HANDLE; if (fd < 0) { mp3dec_reset(mp3); return MP3DEC_RETCODE_INVALID_PARAMETERS; } if (mp3->flags & MP3DEC_FLAG_INITIALIZED) close(mp3->fd); mp3->fd = fd; mp3->flags = MP3DEC_FLAG_SEEKABLE; mp3->stream_offset = mp3->stream_size = mp3->stream_position = 0; mp3->in_buffer_offset = mp3->in_buffer_used = 0; mp3->out_buffer_offset = mp3->out_buffer_used = 0; tmp = lseek(fd, 0, SEEK_CUR); if (tmp >= 0) mp3->stream_offset = tmp; else mp3->flags &= ~MP3DEC_FLAG_SEEKABLE; if (mp3->flags & MP3DEC_FLAG_SEEKABLE) { tmp = lseek(fd, 0, SEEK_END); if (tmp >= 0) { mp3->stream_size = tmp; tmp = lseek(fd, mp3->stream_offset, SEEK_SET); if (tmp<0) fprintf(stderr, "seek failure im mp3\n"); } else mp3->flags &= ~MP3DEC_FLAG_SEEKABLE; } if (mp3->stream_size > mp3->stream_offset) { mp3->stream_size -= mp3->stream_offset; if (length && (length < mp3->stream_size)) mp3->stream_size = length; } else mp3->stream_size = length; // check for ID3 tag if (lseek(fd, 0, SEEK_SET)==0) { char hdr[10]; if (read(fd, &hdr, 10)!= 10) return MP3DEC_RETCODE_NOT_MPEG_STREAM; if (hdr[0] == 'I' && hdr[1] == 'D' && hdr[2] == '3') { /* A*2^21+B*2^14+C*2^7+D=A*2097152+B*16384+C*128+D*/ mp3->stream_offset = hdr[6]*2097152+hdr[7]*16384+hdr[8]*128+hdr[9] + 10; // fprintf(stderr, "==== found ID3 tag, skipping %lld bytes ==== \n", // mp3->stream_offset); } (void) lseek(fd, mp3->stream_offset, SEEK_SET); } r = read(fd, mp3->in_buffer, 4); if (r < 4) { mp3dec_reset(mp3); return ((r < 0) ? MP3DEC_RETCODE_INVALID_PARAMETERS : MP3DEC_RETCODE_NOT_MPEG_STREAM); } else mp3->in_buffer_used = r; if (mp3->flags & MP3DEC_FLAG_SEEKABLE) tmp = lseek(fd, mp3->stream_offset, SEEK_SET); else tmp = -1; if (tmp < 0) { int32_t n = sizeof(mp3->in_buffer) - mp3->in_buffer_used; mp3->flags &= ~MP3DEC_FLAG_SEEKABLE; if (mp3->stream_size && (n > (mp3->stream_size - mp3->in_buffer_used))) n = (int32_t)(mp3->stream_size - mp3->in_buffer_used); n = read(fd, mp3->in_buffer + mp3->in_buffer_used, n); if (n < 0) n = 0; mp3->in_buffer_used += n; mp3->stream_position = mp3->in_buffer_used; } else { int32_t n = sizeof(mp3->in_buffer); if (mp3->stream_size && (n > mp3->stream_size)) n = (int32_t)mp3->stream_size; n = read(fd, mp3->in_buffer, n); if (n < 0) n = 0; mp3->stream_position = mp3->in_buffer_used = n; } if (mp3->in_buffer_used < 4) { mp3dec_reset(mp3); return MP3DEC_RETCODE_NOT_MPEG_STREAM; } if (nogap) { mpadec_decode(mp3->mpadec, mp3->in_buffer, mp3->in_buffer_used, mp3->out_buffer, sizeof(mp3->out_buffer), &mp3->in_buffer_offset, &mp3->out_buffer_used); mp3->in_buffer_used -= mp3->in_buffer_offset; if (!mp3->out_buffer_used) { mpadec_reset(mp3->mpadec); mp3->in_buffer_used += mp3->in_buffer_offset; mp3->in_buffer_offset = 0; } } else mpadec_reset(mp3->mpadec); if (!mp3->out_buffer_used) { r = mpadec_decode(mp3->mpadec, mp3->in_buffer, mp3->in_buffer_used, NULL, 0, &mp3->in_buffer_offset, NULL); mp3->in_buffer_used -= mp3->in_buffer_offset; if (r != MPADEC_RETCODE_OK) { // this is a fix for ID3 tag at the start of a file while(r == 7) { /* NO SYNC, read more data */ int32_t n = sizeof(mp3->in_buffer); if (mp3->stream_size && (n > mp3->stream_size)) n = (int32_t)mp3->stream_size; n = read(fd, mp3->in_buffer, n); if (n <= 0){ n = 0; break; } /* EOF */ mp3->stream_position = mp3->in_buffer_used = n; r = mpadec_decode(mp3->mpadec, mp3->in_buffer, mp3->in_buffer_used, NULL, 0, &mp3->in_buffer_offset, NULL); mp3->in_buffer_used -= mp3->in_buffer_offset; } if (r != MPADEC_RETCODE_OK) { mp3dec_reset(mp3); return MP3DEC_RETCODE_NOT_MPEG_STREAM; } } } if ((mpadec_get_info(mp3->mpadec, &mp3->mpainfo, MPADEC_INFO_STREAM) != MPADEC_RETCODE_OK) || (mpadec_get_info(mp3->mpadec, &mp3->taginfo, MPADEC_INFO_TAG) != MPADEC_RETCODE_OK)) { mp3dec_reset(mp3); return MP3DEC_RETCODE_NOT_MPEG_STREAM; } if (mp3->taginfo.flags & 2) if (!mp3->stream_size || (mp3->stream_size > mp3->taginfo.bytes)) mp3->stream_size = mp3->taginfo.bytes; if (mp3->taginfo.flags & 1) { mp3->mpainfo.frames = mp3->taginfo.frames; if (mp3->mpainfo.frames && mp3->mpainfo.frame_samples) { mp3->mpainfo.bitrate = (int32_t) ((MYFLT)(((MYFLT)mp3->stream_size*(MYFLT)mp3->mpainfo.frequency + 0.5)/ ((MYFLT)125.0*mp3->mpainfo.frame_samples*mp3->mpainfo.frames))); } } else if (mp3->mpainfo.bitrate && mp3->mpainfo.frame_samples) { mp3->mpainfo.frames = (int32_t) ((MYFLT)(((MYFLT)mp3->stream_size*(MYFLT)mp3->mpainfo.frequency + 0.5)/ ((MYFLT)125.0*mp3->mpainfo.frame_samples*mp3->mpainfo.bitrate))); } mp3->mpainfo.duration = (mp3->mpainfo.frames*mp3->mpainfo.frame_samples + (mp3->mpainfo.frequency >> 1))/mp3->mpainfo.frequency; mp3->flags |= MP3DEC_FLAG_INITIALIZED; return MP3DEC_RETCODE_OK; } int mp3dec_uninit(mp3dec_t mp3dec) { register struct mp3dec_t *mp3 = (struct mp3dec_t *)mp3dec; if (!mp3 || (mp3->size != sizeof(struct mp3dec_t)) || !mp3->mpadec) return MP3DEC_RETCODE_INVALID_HANDLE; if (mp3->flags & MP3DEC_FLAG_INITIALIZED) close(mp3->fd); mp3->fd = -1; mp3->flags = 0; mpadec_uninit(mp3->mpadec); mp3->size = 0; free(mp3); return MP3DEC_RETCODE_OK; } int mp3dec_reset(mp3dec_t mp3dec) { register struct mp3dec_t *mp3 = (struct mp3dec_t *)mp3dec; if (!mp3 || (mp3->size != sizeof(struct mp3dec_t)) || !mp3->mpadec) return MP3DEC_RETCODE_INVALID_HANDLE; if (mp3->flags & MP3DEC_FLAG_INITIALIZED) close(mp3->fd); mp3->fd = -1; mp3->flags = 0; mpadec_reset(mp3->mpadec); mp3->stream_offset = mp3->stream_size = mp3->stream_position = 0; mp3->in_buffer_offset = mp3->in_buffer_used = 0; mp3->out_buffer_offset = mp3->out_buffer_used = 0; memset(&mp3->mpainfo, 0, sizeof(mp3->mpainfo)); memset(&mp3->taginfo, 0, sizeof(mp3->taginfo)); return MP3DEC_RETCODE_OK; } int mp3dec_configure(mp3dec_t mp3dec, mpadec_config_t *cfg) { register struct mp3dec_t *mp3 = (struct mp3dec_t *)mp3dec; if (!mp3 || (mp3->size != sizeof(struct mp3dec_t)) || !mp3->mpadec) return MP3DEC_RETCODE_INVALID_HANDLE; mp3->out_buffer_offset = mp3->out_buffer_used = 0; if (mpadec_configure(mp3->mpadec, cfg) != MPADEC_RETCODE_OK) return MP3DEC_RETCODE_INVALID_PARAMETERS; return MP3DEC_RETCODE_OK; } int mp3dec_get_info(mp3dec_t mp3dec, void *info, int info_type) { register struct mp3dec_t *mp3 = (struct mp3dec_t *)mp3dec; if (!mp3 || (mp3->size != sizeof(struct mp3dec_t)) || !mp3->mpadec) return MP3DEC_RETCODE_INVALID_HANDLE; if (!info) return MP3DEC_RETCODE_INVALID_PARAMETERS; if (mp3->flags & MP3DEC_FLAG_INITIALIZED) { switch (info_type) { case MPADEC_INFO_STREAM: memcpy(info, &mp3->mpainfo, sizeof(mp3->mpainfo)); break; case MPADEC_INFO_TAG: memcpy(info, &mp3->taginfo, sizeof(mp3->taginfo)); break; case MPADEC_INFO_CONFIG: default: if (mpadec_get_info(mp3->mpadec, info, info_type) != MPADEC_RETCODE_OK) return MP3DEC_RETCODE_INVALID_PARAMETERS; } } else return MP3DEC_RETCODE_BAD_STATE; return MP3DEC_RETCODE_OK; } int mp3dec_decode(mp3dec_t mp3dec, uint8_t *buf, uint32_t bufsize, uint32_t *used) { register struct mp3dec_t *mp3 = (struct mp3dec_t *)mp3dec; uint32_t n, src_used, dst_used; int r; if (used) *used = 0; if (!mp3 || (mp3->size != sizeof(struct mp3dec_t)) || !mp3->mpadec) return MP3DEC_RETCODE_INVALID_HANDLE; if (!(mp3->flags & MP3DEC_FLAG_INITIALIZED)) return MP3DEC_RETCODE_BAD_STATE; if (!buf) return MP3DEC_RETCODE_INVALID_PARAMETERS; while (bufsize) { if (mp3->out_buffer_used) { n = (bufsize < mp3->out_buffer_used) ? bufsize : mp3->out_buffer_used; memcpy(buf, mp3->out_buffer + mp3->out_buffer_offset, n); mp3->out_buffer_offset += n; mp3->out_buffer_used -= n; buf += n; bufsize -= n; if (used) *used += n; } if (!bufsize) break; if (mp3->in_buffer_used > 4) { r = mpadec_decode(mp3->mpadec, mp3->in_buffer + mp3->in_buffer_offset, mp3->in_buffer_used, buf, bufsize, &src_used, &dst_used); mp3->in_buffer_offset += src_used; mp3->in_buffer_used -= src_used; buf += dst_used; bufsize -= dst_used; if (used) *used += dst_used; if (!bufsize) break; if (r == MPADEC_RETCODE_BUFFER_TOO_SMALL) { mp3->out_buffer_offset = mp3->out_buffer_used = 0; mpadec_decode(mp3->mpadec, mp3->in_buffer + mp3->in_buffer_offset, mp3->in_buffer_used, mp3->out_buffer, sizeof(mp3->out_buffer), &src_used, &mp3->out_buffer_used); mp3->in_buffer_offset += src_used; mp3->in_buffer_used -= src_used; continue; } } if (mp3->in_buffer_used && mp3->in_buffer_offset) memmove(mp3->in_buffer, mp3->in_buffer + mp3->in_buffer_offset, mp3->in_buffer_used); mp3->in_buffer_offset = 0; n = sizeof(mp3->in_buffer) - mp3->in_buffer_used; if (mp3->stream_size && (n > (mp3->stream_size - mp3->stream_position))) n = (int32_t)(mp3->stream_size - mp3->stream_position); if (n) r = read(mp3->fd, mp3->in_buffer + mp3->in_buffer_used, n); else r = 0; if (r < 0) r = 0; mp3->in_buffer_used += r; mp3->stream_position += r; if (mp3->stream_position > mp3->stream_size) mp3->stream_position = mp3->stream_size; if (!r) break; } return MP3DEC_RETCODE_OK; } int mp3dec_seek(mp3dec_t mp3dec, int64_t pos, int units) { register struct mp3dec_t *mp3 = (struct mp3dec_t *)mp3dec; int64_t newpos; if (!mp3 || (mp3->size != sizeof(struct mp3dec_t)) || !mp3->mpadec) return MP3DEC_RETCODE_INVALID_HANDLE; if (!(mp3->flags & MP3DEC_FLAG_INITIALIZED)) return MP3DEC_RETCODE_BAD_STATE; if (!(mp3->flags & MP3DEC_FLAG_SEEKABLE)) return MP3DEC_RETCODE_SEEK_FAILED; if (units == MP3DEC_SEEK_BYTES) { newpos = (pos < mp3->stream_size) ? pos : mp3->stream_size; newpos = lseek(mp3->fd, mp3->stream_offset + newpos, SEEK_SET); if (newpos < 0) return MP3DEC_RETCODE_SEEK_FAILED; mp3->stream_position = newpos - mp3->stream_offset; mp3->in_buffer_offset = mp3->in_buffer_used = 0; mp3->out_buffer_offset = mp3->out_buffer_used = 0; } else if (units == MP3DEC_SEEK_SAMPLES) { MYFLT fsize = (MYFLT)(125.0*mp3->mpainfo.bitrate*mp3->mpainfo.decoded_frame_samples)/ (MYFLT)mp3->mpainfo.decoded_frequency; newpos = (int64_t) ((MYFLT)pos*fsize/(MYFLT)mp3->mpainfo.decoded_frame_samples); //printf("seek pos: %d %d\n", newpos, pos); if (newpos > mp3->stream_size) newpos = mp3->stream_size; pos = (pos%mp3->mpainfo.decoded_frame_samples)* mp3->mpainfo.decoded_sample_size; newpos = lseek(mp3->fd, mp3->stream_offset + newpos, SEEK_SET); if (newpos < 0) return MP3DEC_RETCODE_SEEK_FAILED; mp3->stream_position = newpos - mp3->stream_offset; mp3->in_buffer_offset = mp3->in_buffer_used = 0; mp3->out_buffer_offset = mp3->out_buffer_used = 0; { uint8_t temp[8*1152]; mp3dec_decode(mp3, temp, (uint32_t)pos, NULL); } } else if (units == MP3DEC_SEEK_SECONDS) { if (pos > mp3->mpainfo.duration) pos = mp3->mpainfo.duration; if (mp3->taginfo.flags & 4) { int32_t n = (int32_t)((100*pos + (mp3->mpainfo.duration >> 1))/ mp3->mpainfo.duration); if (n > 99) newpos = mp3->stream_size; else newpos = (mp3->taginfo.toc[n]*mp3->stream_size)/255; } else newpos = (pos*mp3->stream_size + (mp3->mpainfo.duration >> 1))/ mp3->mpainfo.duration; if (newpos > mp3->stream_size) newpos = mp3->stream_size; newpos = lseek(mp3->fd, mp3->stream_offset + newpos, SEEK_SET); if (newpos < 0) return MP3DEC_RETCODE_SEEK_FAILED; mp3->stream_position = newpos - mp3->stream_offset; mp3->in_buffer_offset = mp3->in_buffer_used = 0; mp3->out_buffer_offset = mp3->out_buffer_used = 0; } else return MP3DEC_RETCODE_INVALID_PARAMETERS; return MP3DEC_RETCODE_OK; } char *mp3dec_error(int code) { static char *mp3_errors[] = { "No error", "Invalid handle", "Bad decoder state", "Invalid parameters", "Not an MPEG audio stream", "Seek failed", "Unknown error" }; if (code > MP3DEC_RETCODE_UNKNOWN) code = MP3DEC_RETCODE_UNKNOWN; return mp3_errors[code]; } csound-6.10.0/InOut/libmpadec/mp3dec_internal.h000066400000000000000000000027351321653344700213060ustar00rootroot00000000000000/* * mpadec - MPEG audio decoder * Copyright (C) 2002-2004 Dmitriy Startsev (dstartsev@rambler.ru) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* $Id: mp3dec_internal.h,v 1.2 2004/08/02 09:38:09 metal_man Exp $ */ #ifndef __MP3DEC_INTERNAL_H #define __MP3DEC_INTERNAL_H #include "mpadec_config.h" #include "mp3dec.h" #define MP3DEC_FLAG_INITIALIZED 1 #define MP3DEC_FLAG_SEEKABLE 2 struct mp3dec_t { uint32_t size; mpadec_t mpadec; int32_t fd; uint32_t flags; int64_t stream_offset; int64_t stream_size; int64_t stream_position; mpadec_info_t mpainfo; mp3tag_info_t taginfo; uint32_t in_buffer_offset; uint32_t in_buffer_used; uint32_t out_buffer_offset; uint32_t out_buffer_used; uint8_t in_buffer[0x10000]; uint8_t out_buffer[8*1152]; }; #endif csound-6.10.0/InOut/libmpadec/mpadec.c000066400000000000000000001032621321653344700174600ustar00rootroot00000000000000/* * mpadec - MPEG audio decoder * Copyright (C) 2002-2004 Dmitriy Startsev (dstartsev@rambler.ru) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* $Id: mpadec.c,v 1.3 2009/03/01 15:27:05 jpff Exp $ */ #include #include "csoundCore.h" #include "mpadec_internal.h" extern const uint16_t crc_table[256]; extern void *synth_table[2][2][4][4]; const uint32_t bitmask[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; const int32_t frequency_table[9] = { 44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000 }; const int16_t bitrate_table[2][3][16] = { { { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 560 }, { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448 }, { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 } }, { { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 320 }, { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 192 }, { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 192 } } }; extern void init_tables(mpadec_t mpadec, MYFLT scale, int32_t sblimit); extern void decode_layer1(mpadec_t mpadec, uint8_t *buffer); extern void decode_layer2(mpadec_t mpadec, uint8_t *buffer); extern void decode_layer3(mpadec_t mpadec, uint8_t *buffer); uint32_t getbits(mpadec_t mpadec, unsigned n) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; while ((mpa->bits_left <= 24) && mpa->bytes_left) { mpa->bit_buffer = (mpa->bit_buffer << 8) | *mpa->next_byte++; mpa->bits_left += (uint8_t)8; mpa->bytes_left--; } while (mpa->bits_left <= 24) { mpa->bit_buffer = (mpa->bit_buffer << 8); mpa->bits_left += (uint8_t)8; } mpa->bits_left -= (uint8_t)n; return (mpa->bit_buffer >> mpa->bits_left) & bitmask[n]; } uint16_t update_crc(uint16_t init, uint8_t *buf, int length) { register uint32_t crc = (uint32_t)init, tmp; register int l = length; register uint8_t *b = buf; for (; l >= 8; l -= 8) crc = (crc << 8) ^ crc_table[((crc >> 8) ^ (*b++)) & 0xFF]; tmp = (uint32_t)(*b) << 8; while (l--) { tmp <<= 1; crc <<= 1; if ((crc ^ tmp) & 0x10000) crc ^= 0x8005; } return (uint16_t)crc; } static uint32_t detect_frame_size(mpadec_t mpadec) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; register uint8_t *buf = mpa->next_byte; uint32_t i = mpa->bytes_left, hdr = 0; if (i < (mpa->frame.frame_size + 4)) return 0; buf += mpa->frame.frame_size; i -= mpa->frame.frame_size; while (i >= 4) { register uint32_t tmp = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3]; if (((tmp & 0xFFE00000) == 0xFFE00000) && (tmp & (3 << 17)) && ((tmp & (3 << 10)) != (3 << 10))) { if ((mpa->frame.layer == (uint8_t)(4 - ((tmp >> 17) & 3))) && (mpa->frame.frequency_index == (((tmp >> 10) & 3) + 3*(mpa->frame.LSF + mpa->frame.MPEG25))) && (mpa->frame.channels == ((((tmp >> 6) & 3) == MPG_MD_MONO) ? 1 : 2))) { if (mpa->config.dblsync) { uint32_t fs = mpa->bytes_left - i - mpa->frame.padding + ((tmp>>9) & 1); if (i >= (fs + 4)) { buf += fs; tmp = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; buf -= fs; if (((tmp & 0xFFE00000) == 0xFFE00000) && (tmp & (3 << 17)) && ((tmp & (3 << 10)) != (3 << 10))) { if ((mpa->frame.layer == (uint8_t)(4 - ((tmp >> 17) & 3))) && (mpa->frame.frequency_index == (((tmp>>10)&3) + 3*(mpa->frame.LSF + mpa->frame.MPEG25))) && (mpa->frame.channels == ((((tmp>>6)&3) == MPG_MD_MONO)?1:2))) { hdr = tmp; break; } } } else return 0; } else { hdr = tmp; break; } } } buf++; i--; } return (hdr ? (mpa->bytes_left - i) : 0); } static int decode_header(mpadec_t mpadec, uint32_t header) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; unsigned int layer, bridx, fridx; layer = 4 - ((header >> 17) & 3); bridx = ((header >> 12) & 0x0F); fridx = ((header >> 10) & 3); if ((fridx == 3) || (layer == 4) || ((layer != 3) && !bridx)) return FALSE; if (header & (1 << 20)) { mpa->frame.LSF = (uint8_t)((header & (1 << 19)) ? FALSE : TRUE); mpa->frame.MPEG25 = FALSE; } else mpa->frame.LSF = mpa->frame.MPEG25 = TRUE; mpa->frame.layer = (uint8_t)layer; mpa->frame.bitrate_index = bridx; mpa->frame.bitrate = bitrate_table[mpa->frame.LSF][layer - 1][bridx]; mpa->frame.frequency_index = (fridx += 3*(mpa->frame.LSF + mpa->frame.MPEG25)); mpa->frame.frequency = frequency_table[fridx]; mpa->frame.decoded_frequency = mpa->frame.frequency >> mpa->config.quality; mpa->frame.CRC = (uint8_t)(((header >> 16) & 1) ^ 1); mpa->frame.padding = ((header >> 9) & 1); mpa->frame.extension = (uint8_t)((header >> 8) & 1); mpa->frame.mode = (uint8_t)((header >> 6) & 3); mpa->frame.mode_ext = (uint8_t)((header >> 4) & 3); mpa->frame.copyright = (uint8_t)((header >> 3) & 1); mpa->frame.original = (uint8_t)((header >> 2) & 1); mpa->frame.emphasis = (uint8_t)(header & 3); mpa->frame.channels = (uint8_t)((mpa->frame.mode == MPG_MD_MONO) ? 1 : 2); switch (mpa->config.mode) { case MPADEC_CONFIG_CHANNEL1: case MPADEC_CONFIG_CHANNEL2: case MPADEC_CONFIG_MONO: mpa->frame.decoded_channels = 1; break; case MPADEC_CONFIG_STEREO: mpa->frame.decoded_channels = 2; break; default: mpa->frame.decoded_channels = mpa->frame.channels; } mpa->free_format = FALSE; switch (mpa->frame.layer) { case 1: mpa->frame.frame_samples = 384; mpa->frame.frame_size = (12000*mpa->frame.bitrate/mpa->frame.frequency + mpa->frame.padding) << 2; mpa->ssize = 0; break; case 2: mpa->frame.frame_samples = 1152; mpa->frame.frame_size = 144000*mpa->frame.bitrate/mpa->frame.frequency + mpa->frame.padding; mpa->ssize = 0; break; case 3: mpa->frame.frame_samples = 1152 >> mpa->frame.LSF; if (mpa->frame.LSF) mpa->ssize = (mpa->frame.channels > 1) ? 17 : 9; else mpa->ssize = (mpa->frame.channels > 1) ? 32 : 17; if (mpa->frame.bitrate_index) { mpa->frame.frame_size = 144000*mpa->frame.bitrate/(mpa->frame.frequency << mpa->frame.LSF) + mpa->frame.padding; mpa->prev_frame_size = 0; } else { register uint32_t div = 125*mpa->frame.frame_samples; if (!mpa->prev_frame_size) { mpa->frame.frame_size = (mpa->frame.CRC ? 6 : 4) + mpa->ssize + mpa->frame.padding; mpa->prev_frame_size = detect_frame_size(mpa); if (mpa->prev_frame_size) mpa->prev_frame_size -= mpa->frame.padding; } mpa->frame.frame_size = mpa->prev_frame_size + mpa->frame.padding; mpa->frame.bitrate = (mpa->frame.frame_size*mpa->frame.frequency + (div >> 1))/div; mpa->free_format = TRUE; } break; } mpa->frame.decoded_samples = mpa->frame.frame_samples >> mpa->config.quality; mpa->frame.downsample = FALSE; mpa->frame.downsample_sblimit = SBLIMIT; mpa->frame.decoded_size = mpa->frame.decoded_samples*mpa->frame.decoded_channels; switch (mpa->config.format) { case MPADEC_CONFIG_24BIT: mpa->frame.decoded_size *= 3; break; case MPADEC_CONFIG_32BIT: case MPADEC_CONFIG_FLOAT: mpa->frame.decoded_size <<= 2; break; default: mpa->frame.decoded_size <<= 1; break; } mpa->hsize = mpa->frame.CRC ? 6 : 4; if (mpa->frame.frame_size < (mpa->hsize + mpa->ssize)) mpa->frame.frame_size = mpa->hsize + mpa->ssize; mpa->dsize = mpa->frame.frame_size - (mpa->hsize + mpa->ssize); return TRUE; } static uint32_t sync_buffer(mpadec_t mpadec) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; register uint8_t *buf = mpa->next_byte; uint32_t retval = 0, i = mpa->bytes_left; if (mpa->state == MPADEC_STATE_START) { buf += 128; i -= 128; while (i >= 4) { register uint32_t tmp = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3]; if (((tmp & 0xFFE00000) == 0xFFE00000) && (tmp & (3<<17)) && ((tmp & (3<<10)) != (3<<10))) { if (mpa->config.dblsync) { if (decode_header(mpa, tmp)) { if ((i < (mpa->frame.frame_size + 4)) || (mpa->free_format && !mpa->prev_frame_size)) { break; } else { register uint32_t tmp2 = (buf[mpa->frame.frame_size]<<24) | (buf[mpa->frame.frame_size + 1]<<16) | (buf[mpa->frame.frame_size + 2]<<8) | buf[mpa->frame.frame_size + 3]; if (((tmp2 & 0xFFE00000) == 0xFFE00000) && (tmp2 & (3<<17)) && ((tmp2 & (3<<10)) != (3<<10))) { if ((mpa->frame.layer == (uint8_t)(4 - ((tmp2 >> 17) & 3))) && (mpa->frame.frequency_index == (((tmp2>>10)&3) + 3*(mpa->frame.LSF + mpa->frame.MPEG25))) && (mpa->frame.channels == ((((tmp2>>6)&3)==MPG_MD_MONO)?1:2))) { retval = tmp; break; } } } } } else { retval = tmp; break; } } buf++; i--; } } else { while (i >= 4) { register uint32_t tmp = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3]; if (((tmp & 0xFFE00000) == 0xFFE00000) && (tmp & (3<<17)) && ((tmp & (3<<10)) != (3<<10))) { if ((mpa->frame.layer == (uint8_t)(4 - ((tmp >> 17) & 3))) && (mpa->frame.frequency_index == (((tmp >> 10) & 3) + 3*(mpa->frame.LSF + mpa->frame.MPEG25))) && (mpa->frame.channels == ((((tmp>>6)&3) == MPG_MD_MONO) ? 1 : 2))) { retval = tmp; break; } } buf++; i--; } } if (i < mpa->bytes_left) { i = mpa->bytes_left - i; mpa->next_byte = buf;; mpa->bytes_left -= i; if (i >= 512) { mpa->reservoir_size = 0; i = 512; } memcpy(mpa->reservoir + mpa->reservoir_size, mpa->next_byte - i, i); mpa->reservoir_size += i; } return retval; } static int first_frame(mpadec_t mpadec) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; int i, skip = FALSE; uint32_t framesize; MYFLT scale; if (mpa->frame.channels > 1) i = ((mpa->config.mode == MPADEC_CONFIG_STEREO) || (mpa->config.mode == MPADEC_CONFIG_AUTO)) ? 3 : 2; else i = (mpa->config.mode == MPADEC_CONFIG_STEREO) ? 1 : 0; mpa->synth_func = synth_table[mpa->config.quality][mpa->config.endian][mpa->config.format][i]; mpa->sample_size = mpa->frame.decoded_channels; switch (mpa->config.format) { case MPADEC_CONFIG_24BIT: mpa->sample_size *= 3; scale = 0x800000; break; case MPADEC_CONFIG_32BIT: mpa->sample_size <<= 2; scale = 0x80000000; break; case MPADEC_CONFIG_FLOAT: mpa->sample_size <<= 2; scale = 1; break; default: mpa->sample_size <<= 1; scale = 0x8000; break; } mpa->synth_size = (mpa->sample_size<<5) >> mpa->config.quality; if (mpa->config.replaygain != MPADEC_CONFIG_REPLAYGAIN_CUSTOM) { mpa->config.gain = 0.0; mpa->replay_gain = 1.0; } mpa->skip_samples = 0; mpa->padding_samples = 0; mpa->decoded_frames = 0; mpa->decoded_samples = 0; memset(&mpa->tag_info, 0, sizeof(mpa->tag_info)); framesize = (mpa->frame.frame_size < mpa->bytes_left) ? mpa->frame.frame_size : mpa->bytes_left; if ((mpa->frame.layer == 3) && (framesize >= (mpa->ssize + 124))) { register uint8_t *buf = mpa->next_byte + 4 + mpa->ssize; if (((buf[0] == 'X') && (buf[1] == 'i') && (buf[2] == 'n') && (buf[3] == 'g')) || ((buf[0] == 'I') && (buf[1] == 'n') && (buf[2] == 'f') && (buf[3] == 'o'))) { skip = TRUE; mpa->next_byte += framesize; mpa->bytes_left -= framesize; buf += 4; mpa->tag_info.flags = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3]; buf += 4; if (mpa->tag_info.flags & 1) { mpa->tag_info.frames = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3]; buf += 4; }; if (mpa->tag_info.flags & 2) { mpa->tag_info.bytes = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3]; buf += 4; }; if (mpa->tag_info.flags & 4) { memcpy(mpa->tag_info.toc, buf, 100); buf += 100; }; if (mpa->tag_info.flags & 8) buf += 4; mpa->tag_info.flags &= 7; if (framesize >= mpa->ssize + 160) { buf += 15; mpa->tag_info.replay_gain[0] = ((buf[0]<<8) | buf[1]) & 0x1FF; if (buf[0] & 2) mpa->tag_info.replay_gain[0] = -mpa->tag_info.replay_gain[0]; buf += 2; mpa->tag_info.replay_gain[1] = ((buf[0]<<8) | buf[1]) & 0x1FF; if (buf[0] & 2) mpa->tag_info.replay_gain[1] = -mpa->tag_info.replay_gain[1]; buf += 4; mpa->tag_info.enc_delay = (buf[0]<<4) | ((buf[1] >> 4) & 0x0F); mpa->tag_info.enc_padding = ((buf[1] & 0x0F)<<8) | buf[2]; if (((mpa->tag_info.enc_delay < 0) || (mpa->tag_info.enc_delay > 3000)) || ((mpa->tag_info.enc_padding < 0) || (mpa->tag_info.enc_padding > 3000))) { mpa->tag_info.replay_gain[0] = mpa->tag_info.replay_gain[1] = 0; mpa->tag_info.enc_delay = 0; mpa->tag_info.enc_padding = 0; } else { if (mpa->config.replaygain == MPADEC_CONFIG_REPLAYGAIN_RADIO) { mpa->config.gain = ((MYFLT)mpa->tag_info.replay_gain[0])/10.0; } else if (mpa->config.replaygain == MPADEC_CONFIG_REPLAYGAIN_AUDIOPHILE) { mpa->config.gain = ((MYFLT)mpa->tag_info.replay_gain[1])/10.0; } } mpa->skip_samples = mpa->tag_info.enc_delay; mpa->padding_samples = mpa->tag_info.enc_padding; } } } mpa->replay_gain = pow(10.0, mpa->config.gain/20.0); if (mpa->config.replaygain != MPADEC_CONFIG_REPLAYGAIN_NONE) scale *= mpa->replay_gain; init_tables(mpa, scale, SBLIMIT >> mpa->config.quality); if (mpa->frame.layer == 3) { mpa->skip_samples += 529; if ((mpa->tag_info.flags & 1) && (mpa->padding_samples > 529)) mpa->padding_samples -= 529; else mpa->padding_samples = 0; } else { mpa->skip_samples += 241; mpa->padding_samples = 0; } mpa->padding_start = mpa->tag_info.frames*mpa->frame.frame_samples; if (mpa->padding_start > mpa->padding_samples) mpa->padding_start -= mpa->padding_samples; else mpa->padding_start = 0; mpa->state = MPADEC_STATE_DECODE; return skip; } mpadec_t mpadec_init(void) { register struct mpadec_t *mpa = (struct mpadec_t *)malloc(sizeof(struct mpadec_t)); union { uint8_t t8[2]; uint16_t t16; } ch; if (!mpa) return NULL; memset(mpa, 0, sizeof(struct mpadec_t)); mpa->size = sizeof(struct mpadec_t); ch.t16 = 1; //*((int16_t *)temp) = 1; mpa->config.quality = MPADEC_CONFIG_FULL_QUALITY; mpa->config.mode = MPADEC_CONFIG_AUTO; mpa->config.format = MPADEC_CONFIG_16BIT; mpa->config.endian = (uint8_t)(ch.t8[0] ? MPADEC_CONFIG_LITTLE_ENDIAN : MPADEC_CONFIG_BIG_ENDIAN); mpa->config.replaygain = MPADEC_CONFIG_REPLAYGAIN_NONE; mpa->config.skip = TRUE; mpa->config.crc = TRUE; mpa->config.dblsync = TRUE; mpa->config.gain = 0.0; mpa->replay_gain = 1.0; init_tables(mpa, 0x8000, SBLIMIT); mpa->synth_bufoffs = 1; mpa->state = MPADEC_STATE_START; return mpa; } int mpadec_uninit(mpadec_t mpadec) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; if (mpa && (mpa->size == sizeof(struct mpadec_t))) { mpa->size = mpa->state = 0; free(mpa); return MPADEC_RETCODE_OK; } else return MPADEC_RETCODE_INVALID_HANDLE; } int mpadec_reset(mpadec_t mpadec) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; if (mpa && (mpa->size == sizeof(struct mpadec_t))) { memset(mpa->hybrid_in, 0, sizeof(mpa->hybrid_in)); memset(mpa->hybrid_out, 0, sizeof(mpa->hybrid_out)); memset(mpa->hybrid_buffers, 0, sizeof(mpa->hybrid_buffers)); memset(mpa->synth_buffers, 0, sizeof(mpa->synth_buffers)); mpa->hybrid_block[0] = mpa->hybrid_block[1] = 0; mpa->synth_bufoffs = 1; memset(&mpa->tag_info, 0, sizeof(mpa->tag_info)); if (mpa->config.replaygain != MPADEC_CONFIG_REPLAYGAIN_CUSTOM) mpa->config.gain = 0.0; mpa->prev_frame_size = 0; mpa->free_format = FALSE; mpa->error = FALSE; mpa->reservoir_size = 0; mpa->replay_gain = 1.0; mpa->skip_samples = 0; mpa->padding_samples = 0; mpa->decoded_frames = 0; mpa->decoded_samples = 0; mpa->state = MPADEC_STATE_START; return MPADEC_RETCODE_OK; } else return MPADEC_RETCODE_INVALID_HANDLE; } int mpadec_configure(mpadec_t mpadec, mpadec_config_t *cfg) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; int32_t i, sblimit; MYFLT scale; if (mpa && (mpa->size == sizeof(struct mpadec_t))) { if (!cfg) return MPADEC_RETCODE_INVALID_PARAMETERS; if ((cfg->quality > MPADEC_CONFIG_HALF_QUALITY) || (cfg->mode > MPADEC_CONFIG_CHANNEL2) || (cfg->format > MPADEC_CONFIG_FLOAT) || (cfg->endian > MPADEC_CONFIG_BIG_ENDIAN) || (cfg->replaygain > MPADEC_CONFIG_REPLAYGAIN_CUSTOM)) return MPADEC_RETCODE_INVALID_PARAMETERS; mpa->config.quality = cfg->quality; mpa->config.mode = cfg->mode; mpa->config.format = cfg->format; mpa->config.endian = cfg->endian; mpa->config.replaygain = cfg->replaygain; mpa->config.skip = (uint8_t)(cfg->skip ? TRUE : FALSE); mpa->config.crc = (uint8_t)(cfg->crc ? TRUE : FALSE); mpa->config.dblsync = (uint8_t)(cfg->dblsync ? TRUE : FALSE); if (mpa->config.replaygain == MPADEC_CONFIG_REPLAYGAIN_CUSTOM) { mpa->config.gain = cfg->gain; } else { mpa->config.gain = 0.0; if (mpa->tag_info.flags) { if (mpa->config.replaygain == MPADEC_CONFIG_REPLAYGAIN_RADIO) { mpa->config.gain = ((MYFLT)mpa->tag_info.replay_gain[0])/10.0; } else if (mpa->config.replaygain == MPADEC_CONFIG_REPLAYGAIN_AUDIOPHILE) { mpa->config.gain = ((MYFLT)mpa->tag_info.replay_gain[1])/10.0; } } } mpa->replay_gain = pow(10.0, mpa->config.gain/20.0); switch (mpa->config.format) { case MPADEC_CONFIG_24BIT: scale = 0x800000; break; case MPADEC_CONFIG_32BIT: scale = 0x80000000; break; case MPADEC_CONFIG_FLOAT: scale = 1; break; default: scale = 0x8000; break; } sblimit = SBLIMIT >> mpa->config.quality; if (mpa->config.replaygain != MPADEC_CONFIG_REPLAYGAIN_NONE) scale *= mpa->replay_gain; init_tables(mpa, scale, sblimit); if ((mpa->state > MPADEC_STATE_START) && mpa->header) { decode_header(mpa, mpa->header); if (mpa->frame.channels < 2) i = (mpa->config.mode == MPADEC_CONFIG_STEREO) ? 1 : 0; else i = ((mpa->config.mode == MPADEC_CONFIG_STEREO) || (mpa->config.mode == MPADEC_CONFIG_AUTO)) ? 3 : 2; mpa->synth_func = synth_table[mpa->config.quality][mpa->config.endian] [mpa->config.format][i]; mpa->sample_size = mpa->frame.decoded_channels; switch (mpa->config.format) { case MPADEC_CONFIG_24BIT: mpa->sample_size *= 3; break; case MPADEC_CONFIG_32BIT: case MPADEC_CONFIG_FLOAT: mpa->sample_size <<= 2; break; default: mpa->sample_size <<= 1; break; } mpa->synth_size = (mpa->sample_size<<5) >> mpa->config.quality; } else mpa->state = MPADEC_STATE_START; return MPADEC_RETCODE_OK; } else return MPADEC_RETCODE_INVALID_HANDLE; } int mpadec_get_info(mpadec_t mpadec, void *info, int info_type) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; if (!mpa || (mpa->size != sizeof(struct mpadec_t))) return MPADEC_RETCODE_INVALID_HANDLE; if (!info) return MPADEC_RETCODE_INVALID_PARAMETERS; if (info_type == MPADEC_INFO_CONFIG) { register mpadec_config_t *cfg = (mpadec_config_t *)info; cfg->quality = mpa->config.quality; cfg->mode = mpa->config.mode; cfg->format = mpa->config.format; cfg->endian = mpa->config.endian; cfg->replaygain = mpa->config.replaygain; cfg->skip = mpa->config.skip; cfg->crc = mpa->config.crc; cfg->dblsync = mpa->config.dblsync; cfg->gain = mpa->config.gain; } else if (info_type == MPADEC_INFO_TAG) { register mp3tag_info_t *tag = (mp3tag_info_t *)info; if (mpa->state < MPADEC_STATE_DECODE) { memset(tag, 0, sizeof(mp3tag_info_t)); return MPADEC_RETCODE_BAD_STATE; } else memcpy(tag, &mpa->tag_info, sizeof(mpa->tag_info)); } else if (info_type == MPADEC_INFO_STREAM) { register mpadec_info_t *inf = (mpadec_info_t *)info; if (mpa->state < MPADEC_STATE_DECODE) { memset(inf, 0, sizeof(mpadec_info_t)); return MPADEC_RETCODE_BAD_STATE; } else { inf->layer = mpa->frame.layer; inf->channels = mpa->frame.channels; inf->frequency = mpa->frame.frequency; inf->bitrate = mpa->frame.bitrate; inf->mode = mpa->frame.mode; inf->copyright = mpa->frame.copyright; inf->original = mpa->frame.original; inf->emphasis = mpa->frame.emphasis; inf->decoded_channels = mpa->frame.decoded_channels; inf->decoded_frequency = mpa->frame.decoded_frequency; inf->decoded_sample_size = mpa->sample_size; inf->frame_size = mpa->frame.frame_size; inf->frame_samples = mpa->frame.frame_samples; inf->decoded_frame_samples = mpa->frame.decoded_samples; if (mpa->tag_info.flags & 1) { inf->frames = mpa->tag_info.frames; inf->duration = (mpa->tag_info.frames*mpa->frame.frame_samples + (mpa->frame.frequency >> 1))/mpa->frame.frequency; } else { inf->frames = 0; inf->duration = 0; } } } else return MPADEC_RETCODE_INVALID_PARAMETERS; return MPADEC_RETCODE_OK; } int mpadec_decode(mpadec_t mpadec, uint8_t *srcbuf, uint32_t srcsize, uint8_t *dstbuf, uint32_t dstsize, uint32_t *srcused, uint32_t *dstused) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; int retcode = MPADEC_RETCODE_OK; uint32_t decoded_size = 0; if (srcused) *srcused = 0; if (dstused) *dstused = 0; if (!dstbuf) dstsize = 0; if (!mpa || (mpa->size != sizeof(struct mpadec_t))) return MPADEC_RETCODE_INVALID_HANDLE; if (mpa->state < MPADEC_STATE_START) return MPADEC_RETCODE_BAD_STATE; if (!srcbuf || ((mpa->state > MPADEC_STATE_START) && !dstbuf )) return MPADEC_RETCODE_INVALID_PARAMETERS; mpa->next_byte = srcbuf; mpa->bytes_left = srcsize; while (mpa->bytes_left >= 4) { mpa->error = FALSE; mpa->bits_left = 0; mpa->header = sync_buffer(mpa); if (!mpa->header) { if (!decoded_size) retcode = MPADEC_RETCODE_NO_SYNC; break; } decode_header(mpa, mpa->header); if ((mpa->bytes_left < mpa->frame.frame_size) || (mpa->free_format && !mpa->prev_frame_size)) { retcode = MPADEC_RETCODE_NEED_MORE_DATA; break; } if (mpa->state == MPADEC_STATE_START) { if (first_frame(mpa)) continue; } else if ((mpa->frame.layer == 3) && (mpa->frame.frame_size >= (mpa->ssize + 12))) { register uint8_t *buf = mpa->next_byte + 4 + mpa->ssize; if (((buf[0] == 'X') && (buf[1] == 'i') && (buf[2] == 'n') && (buf[3] == 'g')) || ((buf[0] == 'I') && (buf[1] == 'n') && (buf[2] == 'f') && (buf[3] == 'o'))) { mpa->next_byte += mpa->frame.frame_size; mpa->bytes_left -= mpa->frame.frame_size; continue; } } if (dstsize < mpa->frame.decoded_size) { retcode = MPADEC_RETCODE_BUFFER_TOO_SMALL; break; } if (mpa->config.crc && mpa->frame.CRC) { mpa->frame.crc = (uint16_t)((mpa->next_byte[4]<<8) | mpa->next_byte[5]); mpa->crc = update_crc(0xFFFF, mpa->next_byte + 2, 16); } mpa->next_byte += mpa->hsize; mpa->bytes_left -= mpa->hsize; /* ??Check dstbuf non NULL?? */ if (dstbuf == NULL) return MPADEC_RETCODE_UNKNOWN; switch (mpa->frame.layer) { case 1: decode_layer1(mpa, dstbuf); break; case 2: decode_layer2(mpa, dstbuf); break; case 3: decode_layer3(mpa, dstbuf); break; } if (mpa->config.crc && mpa->error) memset(dstbuf, 0, mpa->frame.decoded_size); dstbuf += mpa->frame.decoded_size; dstsize -= mpa->frame.decoded_size; decoded_size += mpa->frame.decoded_size; mpa->decoded_samples += mpa->frame.frame_samples; mpa->decoded_frames++; if (mpa->config.skip) { if (mpa->skip_samples) { if (mpa->skip_samples >= mpa->frame.frame_samples) { dstbuf -= mpa->frame.decoded_size; dstsize += mpa->frame.decoded_size; decoded_size -= mpa->frame.decoded_size; mpa->skip_samples -= mpa->frame.frame_samples; } else { uint32_t tmp = mpa->frame.frame_samples - mpa->skip_samples; tmp = mpa->sample_size*(tmp >> mpa->config.quality); memmove(dstbuf - mpa->frame.decoded_size, dstbuf - tmp, tmp); dstbuf -= mpa->frame.decoded_size - tmp; dstsize += mpa->frame.decoded_size - tmp; decoded_size -= mpa->frame.decoded_size - tmp; mpa->skip_samples = 0; } } else if ((mpa->padding_samples) && (mpa->decoded_samples > mpa->padding_start)) { uint32_t tmp = mpa->decoded_samples - mpa->padding_start; if (tmp > mpa->padding_samples) tmp = mpa->padding_samples; mpa->padding_start += tmp; mpa->padding_samples -= tmp; tmp = mpa->sample_size*(tmp >> mpa->config.quality); dstbuf -= tmp; dstsize += tmp; decoded_size -= tmp; } } } if (srcused) *srcused = srcsize - mpa->bytes_left; if (dstused) *dstused = decoded_size; if ((retcode == MPADEC_RETCODE_OK) && mpa->bytes_left) retcode = MPADEC_RETCODE_NEED_MORE_DATA; if (!dstbuf && (retcode == MPADEC_RETCODE_BUFFER_TOO_SMALL)) retcode = MPADEC_RETCODE_OK; return retcode; } char *mpadec_error(int code) { static char *mpa_errors[] = { "No error", "Invalid handle", "Not enough memory", "Bad decoder state", "Invalid parameters", "Need more data", "Output buffer too small", "Unable to synchronize", "Unknown error" }; if (code > MPADEC_RETCODE_UNKNOWN) code = MPADEC_RETCODE_UNKNOWN; return mpa_errors[code]; } mpadec2_t mpadec2_init(void) { register struct mpadec2_t *mpa = (struct mpadec2_t *)malloc(sizeof(struct mpadec2_t)); if (!mpa) return NULL; mpa->size = sizeof(struct mpadec2_t); mpa->buffers = NULL; mpa->in_buffer_offset = mpa->in_buffer_used = 0; mpa->out_buffer_offset = mpa->out_buffer_used = 0; mpa->mpadec = mpadec_init(); if (!mpa->mpadec) { free(mpa); return NULL; } return mpa; } int mpadec2_uninit(mpadec2_t mpadec) { register struct mpadec2_t *mpa = (struct mpadec2_t *)mpadec; if (mpa && (mpa->size == sizeof(struct mpadec2_t))) { struct mpabuffer_t *buf = mpa->buffers, *tmp; while (buf) { tmp = buf; buf = buf->next; free(tmp); } mpadec_uninit(mpa->mpadec); free(mpa); return MPADEC_RETCODE_OK; } else return MPADEC_RETCODE_INVALID_HANDLE; } int mpadec2_reset(mpadec2_t mpadec) { register struct mpadec2_t *mpa = (struct mpadec2_t *)mpadec; if (mpa && (mpa->size == sizeof(struct mpadec2_t))) { struct mpabuffer_t *buf = mpa->buffers, *tmp; while (buf) { tmp = buf; buf = buf->next; free(tmp); } mpa->buffers = NULL; mpa->in_buffer_offset = mpa->in_buffer_used = 0; mpa->out_buffer_offset = mpa->out_buffer_used = 0; mpadec_reset(mpa->mpadec); return MPADEC_RETCODE_OK; } else return MPADEC_RETCODE_INVALID_HANDLE; } int mpadec2_configure(mpadec2_t mpadec, mpadec_config_t *cfg) { register struct mpadec2_t *mpa = (struct mpadec2_t *)mpadec; if (!mpa || (mpa->size != sizeof(struct mpadec2_t))) return MPADEC_RETCODE_INVALID_HANDLE; mpa->out_buffer_offset = mpa->out_buffer_used = 0; return (mpadec_configure(mpa->mpadec, cfg)); } int mpadec2_get_info(mpadec2_t mpadec, void *info, int info_type) { register struct mpadec2_t *mpa = (struct mpadec2_t *)mpadec; if (!mpa || (mpa->size != sizeof(struct mpadec2_t))) return MPADEC_RETCODE_INVALID_HANDLE; return (mpadec_get_info(mpa->mpadec, info, info_type)); } int mpadec2_decode(mpadec2_t mpadec, uint8_t *srcbuf, uint32_t srcsize, uint8_t *dstbuf, uint32_t dstsize, uint32_t *dstused) { register struct mpadec2_t *mpa = (struct mpadec2_t *)mpadec; uint32_t n, src_used, dst_used; int r; if (dstused) *dstused = 0; if (!mpa || (mpa->size != sizeof(struct mpadec2_t))) return MPADEC_RETCODE_INVALID_HANDLE; if (((struct mpadec_t *)mpa->mpadec)->state < MPADEC_STATE_START) return MPADEC_RETCODE_BAD_STATE; if (srcbuf && srcsize) { struct mpabuffer_t *last = mpa->buffers, *buf; if (last) { while (last->next) last = last->next; if ((last->offset + last->used) < last->size) { n = last->size - (last->offset + last->used); if (n > srcsize) n = srcsize; memcpy(last->buffer + last->offset + last->used, srcbuf, n); last->used += n; srcbuf += n; srcsize -= n; } } if (srcsize) { n = (srcsize > 4096) ? srcsize : 4096; buf = (struct mpabuffer_t *)malloc(n + sizeof(struct mpabuffer_t)); if (buf) { buf->size = n; buf->offset = buf->used = 0; buf->buffer = (uint8_t *)buf + sizeof(struct mpabuffer_t); buf->next = NULL; memcpy(buf->buffer, srcbuf, srcsize); buf->used = srcsize; if (last) last->next = buf; else mpa->buffers = buf; } else return MPADEC_RETCODE_NOT_ENOUGH_MEMORY; } } if (!dstbuf || !dstsize) return MPADEC_RETCODE_OK; while (dstsize) { struct mpabuffer_t *buf = mpa->buffers; if (mpa->out_buffer_used) { n = (dstsize < mpa->out_buffer_used) ? dstsize : mpa->out_buffer_used; memcpy(dstbuf, mpa->out_buffer + mpa->out_buffer_offset, n); mpa->out_buffer_offset += n; mpa->out_buffer_used -= n; dstbuf += n; dstsize -= n; if (dstused) *dstused += n; } if (!dstsize) break; if (mpa->in_buffer_used && mpa->in_buffer_offset) memmove(mpa->in_buffer, mpa->in_buffer + mpa->in_buffer_offset, mpa->in_buffer_used); mpa->in_buffer_offset = 0; while (buf && (mpa->in_buffer_used < sizeof(mpa->in_buffer))) { if (buf->used) { n = sizeof(mpa->in_buffer) - mpa->in_buffer_used; if (n > buf->used) n = buf->used; memcpy(mpa->in_buffer + mpa->in_buffer_offset + mpa->in_buffer_used, buf->buffer + buf->offset, n); buf->offset += n; buf->used -= n; mpa->in_buffer_used += n; } if (!buf->used) { struct mpabuffer_t *tmp = buf; buf = buf->next; free(tmp); } } mpa->buffers = buf; r = mpadec_decode(mpa->mpadec, mpa->in_buffer + mpa->in_buffer_offset, mpa->in_buffer_used, dstbuf, dstsize, &src_used, &dst_used); mpa->in_buffer_offset += src_used; mpa->in_buffer_used -= src_used; dstbuf += dst_used; dstsize -= dst_used; if (dstused) *dstused += dst_used; if (r == MPADEC_RETCODE_BUFFER_TOO_SMALL) { mpa->out_buffer_offset = mpa->out_buffer_used = 0; mpadec_decode(mpa->mpadec, mpa->in_buffer + mpa->in_buffer_offset, mpa->in_buffer_used, mpa->out_buffer, sizeof(mpa->out_buffer), &src_used, &mpa->out_buffer_used); mpa->in_buffer_offset += src_used; mpa->in_buffer_used -= src_used; if (!mpa->out_buffer_used) break; } else if (!mpa->buffers) break; } return MPADEC_RETCODE_OK; } csound-6.10.0/InOut/libmpadec/mpadec_config.h000066400000000000000000000030361321653344700210100ustar00rootroot00000000000000 /* Hardware architecture */ //#define ARCH_ALPHA //#define ARCH_PPC //#define ARCH_SPARC #define ARCH_X86 //#define ARCH_AMD64 //#define ARCH_IA64 #ifdef WIN32 #define HAVE_IO_H #define HAVE_CONIO_H #undef OSS #else #define HAVE_INTTYPES_H #endif #define FLOAT MYFLT #include "sysdep.h" /*#ifdef HAVE_INTTYPES_H #include #else typedef signed char int8_t; typedef unsigned char uint8_t; typedef signed short int16_t; typedef unsigned short uint16_t; #if defined(__BORLANDC__) || defined(_MSC_VER) typedef signed __int64 int64_t; typedef unsigned __int64 uint64_t; #elif defined(__GNUC__) typedef signed long long int64_t; typedef unsigned long long uint64_t; #endif #if defined(ARCH_AMD64) || defined(ARCH_IA64) || defined(ARCH_ALPHA) typedef signed int int32_t; typedef unsigned int uint32_t; typedef int64_t intptr_t; typedef uint64_t uintptr_t; #else typedef signed long int32_t; typedef unsigned long uint32_t; typedef int32_t intptr_t; typedef uint32_t uintptr_t; #endif #endif */ #undef PACKED #ifdef __GNUC__ #define PACKED __attribute__((packed)) #else #define PACKED #endif #include #include #include #include #include #include #ifdef HAVE_IO_H #include #endif #undef FALSE #undef TRUE #define FALSE 0 #define TRUE 1 #ifndef O_BINARY #define O_BINARY 0 #endif #ifdef WIN32 #define strcasecmp stricmp #endif #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #ifndef M_SQRT2 #define M_SQRT2 1.41421356237309504880 #endif csound-6.10.0/InOut/libmpadec/mpadec_internal.h000066400000000000000000000120641321653344700213600ustar00rootroot00000000000000/* * mpadec - MPEG audio decoder * Copyright (C) 2002-2004 Dmitriy Startsev (dstartsev@rambler.ru) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* $Id: mpadec_internal.h,v 1.1.1.1 2004/07/27 02:57:55 metal_man Exp $ */ #ifndef __MPADEC_INTERNAL_H #define __MPADEC_INTERNAL_H #include "mpadec_config.h" #include "mpadec.h" #define MPADEC_STATE_UNDEFINED 0 #define MPADEC_STATE_START 1 #define MPADEC_STATE_DECODE 2 #define MPG_MD_STEREO 0 #define MPG_MD_JOINT_STEREO 1 #define MPG_MD_DUAL_CHANNEL 2 #define MPG_MD_MONO 3 #define SBLIMIT 32 #define SSLIMIT 18 #define SCALE_BLOCK 12 typedef struct { FLOAT decwin[512 + 32]; FLOAT muls[27][64]; FLOAT gainpow2[256 + 122]; FLOAT ispow[8207]; FLOAT win[2][4][36]; FLOAT *istabs[3][2][2]; FLOAT tan1_1[16]; FLOAT tan2_1[16]; FLOAT tan1_2[16]; FLOAT tan2_2[16]; FLOAT pow1_1[2][16]; FLOAT pow2_1[2][16]; FLOAT pow1_2[2][16]; FLOAT pow2_2[2][16]; int32_t long_limit[9][23]; int32_t short_limit[9][14]; int32_t n_slen2[512]; int32_t i_slen2[256]; int32_t mapbuf0[9][152]; int32_t mapbuf1[9][156]; int32_t mapbuf2[9][44]; int32_t *map[9][3]; int32_t *mapend[9][3]; uint8_t *mp2tables[10]; uint8_t grp3tab[32*3]; uint8_t grp5tab[128*3]; uint8_t grp9tab[1024*3]; } mpadec_tables_t; typedef struct { uint16_t bits; int16_t d; } alloc_table_t; typedef struct { uint32_t linbits; int16_t *table; } newhuff_t; typedef struct { int16_t long_idx[23]; int16_t long_diff[22]; int16_t short_idx[14]; int16_t short_diff[13]; } bandinfo_t; typedef struct { uint8_t layer; uint8_t mode; uint8_t channels; uint8_t decoded_channels; uint8_t LSF; uint8_t MPEG25; uint8_t CRC; uint8_t extension; uint8_t mode_ext; uint8_t copyright; uint8_t original; uint8_t emphasis; uint8_t jsbound; uint8_t sblimit; uint8_t downsample; uint8_t downsample_sblimit; uint16_t crc; uint16_t rsvd; uint32_t padding; uint32_t bitrate_index; uint32_t frequency_index; uint32_t bitrate; uint32_t frequency; uint32_t frame_size; uint32_t frame_samples; uint32_t decoded_frequency; uint32_t decoded_samples; uint32_t decoded_size; alloc_table_t *alloc_table; } frameinfo_t; typedef struct { int32_t scfsi; uint32_t part2_3_length; uint32_t big_values; uint32_t scalefac_compress; uint8_t block_type; uint8_t mixed_block_flag; uint8_t preflag; uint8_t scalefac_scale; uint32_t table_select[3]; uint32_t subblock_gain[3]; uint32_t maxband[3]; uint32_t maxbandl; uint32_t maxb; uint32_t region1start; uint32_t region2start; uint32_t count1table_select; FLOAT *full_gain[3]; FLOAT *pow2gain; } grinfo_t; typedef struct { uint32_t main_data_begin; uint32_t private_bits; struct { grinfo_t gr[2]; } ch[2]; } sideinfo_t; struct mpadec_t { uint32_t size; uint32_t state; uint8_t *next_byte; uint32_t bytes_left; uint32_t bit_buffer; uint8_t bits_left; uint8_t error; uint8_t free_format; uint8_t pad1; uint32_t sample_size; uint32_t prev_frame_size; uint32_t header; uint32_t hsize; uint32_t ssize; uint32_t dsize; uint16_t crc; uint16_t pad2; uint32_t skip_samples; uint32_t padding_samples; uint32_t padding_start; uint32_t decoded_frames; uint32_t decoded_samples; mp3tag_info_t tag_info; uint32_t synth_size; FLOAT replay_gain; void (*synth_func)(void *mpadec, FLOAT block[SBLIMIT], int channel, uint8_t *buffer); uint32_t reservoir_size; uint8_t reservoir[2048]; frameinfo_t frame; sideinfo_t sideinfo; mpadec_config_t config; mpadec_tables_t tables; uint32_t synth_bufoffs; uint8_t hybrid_block[4]; FLOAT hybrid_in[2][SBLIMIT][SSLIMIT]; FLOAT hybrid_out[2][SSLIMIT][SBLIMIT]; FLOAT hybrid_buffers[2][2][SBLIMIT*SSLIMIT]; FLOAT synth_buffers[2][2][0x110]; }; struct mpabuffer_t { uint32_t size; uint32_t offset; uint32_t used; uint8_t *buffer; struct mpabuffer_t *next; }; struct mpadec2_t { uint32_t size; mpadec_t mpadec; struct mpabuffer_t *buffers; uint32_t in_buffer_offset; uint32_t in_buffer_used; uint32_t out_buffer_offset; uint32_t out_buffer_used; uint8_t in_buffer[0x10000]; uint8_t out_buffer[8*1152]; }; #define GETBITS(n) ((mpa->bits_left >= (uint8_t)(n)) \ ? ((mpa->bit_buffer >> (mpa->bits_left -= \ (uint8_t)(n))) & bitmask[n]) : getbits(mpa, n)) #endif csound-6.10.0/InOut/libmpadec/synth.c000066400000000000000000001316431321653344700174000ustar00rootroot00000000000000/* * mpadec - MPEG audio decoder * Copyright (C) 2002-2004 Dmitriy Startsev (dstartsev@rambler.ru) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* $Id: synth.c,v 1.3 2004/08/03 05:22:22 metal_man Exp $ */ #include "mpadec_internal.h" #define ROUND(x) (floor((x) + 0.5)) #define LROUND(x) ((int32_t)(ROUND(x))) #define LLROUND(x) ((int64_t)(ROUND(x))) static const MYFLT costab[32] = { 0.50060299823519630134550410676638, 0.50547095989754365998444458560696, 0.51544730992262454697495130564925, 0.53104259108978417447573393235719, 0.55310389603444452782938083813705, 0.58293496820613387367383070125262, 0.62250412303566481615725615676281, 0.67480834145500574602596871104104, 0.74453627100229844977698119197295, 0.83934964541552703873926374662543, 0.97256823786196069369768941405256, 1.16943993343288495515577028404220, 1.48416461631416627724332693742810, 2.05778100995341155085655447971040, 3.40760841846871878570119133345910, 10.1900081235480568112121092010360, 0.50241928618815570551167011928012, 0.52249861493968888062857531905669, 0.56694403481635770368053791515488, 0.64682178335999012954836011165200, 0.78815462345125022473398248719742, 1.06067768599034747134045174723310, 1.72244709823833392781591536415660, 5.10114861868916385810624549234540, 0.50979557910415916894193980398784, 0.60134488693504528054372182390922, 0.89997622313641570463850954094189, 2.56291544774150617879608629617770, 0.54119610014619698439972320536639, 1.30656296487637652785664317342720, 0.70710678118654752440084436210485, 0.0 }; static void dct64(MYFLT *outptr0, MYFLT *outptr1, MYFLT *samples) { MYFLT tmp1[32], tmp2[32]; { MYFLT *in = samples; tmp1[0] = in[0] + in[31]; tmp1[1] = in[1] + in[30]; tmp1[31] = (in[0] - in[31])*costab[0]; tmp1[30] = (in[1] - in[30])*costab[1]; tmp1[2] = in[2] + in[29]; tmp1[3] = in[3] + in[28]; tmp1[29] = (in[2] - in[29])*costab[2]; tmp1[28] = (in[3] - in[28])*costab[3]; tmp1[4] = in[4] + in[27]; tmp1[5] = in[5] + in[26]; tmp1[27] = (in[4] - in[27])*costab[4]; tmp1[26] = (in[5] - in[26])*costab[5]; tmp1[6] = in[6] + in[25]; tmp1[7] = in[7] + in[24]; tmp1[25] = (in[6] - in[25])*costab[6]; tmp1[24] = (in[7] - in[24])*costab[7]; tmp1[8] = in[8] + in[23]; tmp1[9] = in[9] + in[22]; tmp1[23] = (in[8] - in[23])*costab[8]; tmp1[22] = (in[9] - in[22])*costab[9]; tmp1[10] = in[10] + in[21]; tmp1[11] = in[11] + in[20]; tmp1[21] = (in[10] - in[21])*costab[10]; tmp1[20] = (in[11] - in[20])*costab[11]; tmp1[12] = in[12] + in[19]; tmp1[13] = in[13] + in[18]; tmp1[19] = (in[12] - in[19])*costab[12]; tmp1[18] = (in[13] - in[18])*costab[13]; tmp1[14] = in[14] + in[17]; tmp1[15] = in[15] + in[16]; tmp1[17] = (in[14] - in[17])*costab[14]; tmp1[16] = (in[15] - in[16])*costab[15]; } { tmp2[0] = tmp1[0] + tmp1[15]; tmp2[1] = tmp1[1] + tmp1[14]; tmp2[15] = (tmp1[0] - tmp1[15])*costab[16 + 0]; tmp2[14] = (tmp1[1] - tmp1[14])*costab[16 + 1]; tmp2[2] = tmp1[2] + tmp1[13]; tmp2[3] = tmp1[3] + tmp1[12]; tmp2[13] = (tmp1[2] - tmp1[13])*costab[16 + 2]; tmp2[12] = (tmp1[3] - tmp1[12])*costab[16 + 3]; tmp2[4] = tmp1[4] + tmp1[11]; tmp2[5] = tmp1[5] + tmp1[10]; tmp2[11] = (tmp1[4] - tmp1[11])*costab[16 + 4]; tmp2[10] = (tmp1[5] - tmp1[10])*costab[16 + 5]; tmp2[6] = tmp1[6] + tmp1[9]; tmp2[7] = tmp1[7] + tmp1[8]; tmp2[9] = (tmp1[6] - tmp1[9])*costab[16 + 6]; tmp2[8] = (tmp1[7] - tmp1[8])*costab[16 + 7]; tmp2[16] = tmp1[16] + tmp1[31]; tmp2[17] = tmp1[17] + tmp1[30]; tmp2[31] = (tmp1[31] - tmp1[16])*costab[16 + 0]; tmp2[30] = (tmp1[30] - tmp1[17])*costab[16 + 1]; tmp2[18] = tmp1[18] + tmp1[29]; tmp2[19] = tmp1[19] + tmp1[28]; tmp2[29] = (tmp1[29] - tmp1[18])*costab[16 + 2]; tmp2[28] = (tmp1[28] - tmp1[19])*costab[16 + 3]; tmp2[20] = tmp1[20] + tmp1[27]; tmp2[21] = tmp1[21] + tmp1[26]; tmp2[27] = (tmp1[27] - tmp1[20])*costab[16 + 4]; tmp2[26] = (tmp1[26] - tmp1[21])*costab[16 + 5]; tmp2[22] = tmp1[22] + tmp1[25]; tmp2[23] = tmp1[23] + tmp1[24]; tmp2[25] = (tmp1[25] - tmp1[22])*costab[16 + 6]; tmp2[24] = (tmp1[24] - tmp1[23])*costab[16 + 7]; } { tmp1[0] = tmp2[0] + tmp2[7]; tmp1[7] = (tmp2[0] - tmp2[7])*costab[16 + 8 + 0]; tmp1[1] = tmp2[1] + tmp2[6]; tmp1[6] = (tmp2[1] - tmp2[6])*costab[16 + 8 + 1]; tmp1[2] = tmp2[2] + tmp2[5]; tmp1[5] = (tmp2[2] - tmp2[5])*costab[16 + 8 + 2]; tmp1[3] = tmp2[3] + tmp2[4]; tmp1[4] = (tmp2[3] - tmp2[4])*costab[16 + 8 + 3]; tmp1[8] = tmp2[8] + tmp2[15]; tmp1[15] = (tmp2[15] - tmp2[8])*costab[16 + 8 + 0]; tmp1[9] = tmp2[9] + tmp2[14]; tmp1[14] = (tmp2[14] - tmp2[9])*costab[16 + 8 + 1]; tmp1[10] = tmp2[10] + tmp2[13]; tmp1[13] = (tmp2[13] - tmp2[10])*costab[16 + 8 + 2]; tmp1[11] = tmp2[11] + tmp2[12]; tmp1[12] = (tmp2[12] - tmp2[11])*costab[16 + 8 + 3]; tmp1[16] = tmp2[16] + tmp2[23]; tmp1[23] = (tmp2[16] - tmp2[23])*costab[16 + 8 + 0]; tmp1[17] = tmp2[17] + tmp2[22]; tmp1[22] = (tmp2[17] - tmp2[22])*costab[16 + 8 + 1]; tmp1[18] = tmp2[18] + tmp2[21]; tmp1[21] = (tmp2[18] - tmp2[21])*costab[16 + 8 + 2]; tmp1[19] = tmp2[19] + tmp2[20]; tmp1[20] = (tmp2[19] - tmp2[20])*costab[16 + 8 + 3]; tmp1[24] = tmp2[24] + tmp2[31]; tmp1[31] = (tmp2[31] - tmp2[24])*costab[16 + 8 + 0]; tmp1[25] = tmp2[25] + tmp2[30]; tmp1[30] = (tmp2[30] - tmp2[25])*costab[16 + 8 + 1]; tmp1[26] = tmp2[26] + tmp2[29]; tmp1[29] = (tmp2[29] - tmp2[26])*costab[16 + 8 + 2]; tmp1[27] = tmp2[27] + tmp2[28]; tmp1[28] = (tmp2[28] - tmp2[27])*costab[16 + 8 + 3]; } { tmp2[0] = tmp1[0] + tmp1[3]; tmp2[3] = (tmp1[0] - tmp1[3])*costab[16 + 8 + 4 + 0]; tmp2[1] = tmp1[1] + tmp1[2]; tmp2[2] = (tmp1[1] - tmp1[2])*costab[16 + 8 + 4 + 1]; tmp2[4] = tmp1[4] + tmp1[7]; tmp2[7] = (tmp1[7] - tmp1[4])*costab[16 + 8 + 4 + 0]; tmp2[5] = tmp1[5] + tmp1[6]; tmp2[6] = (tmp1[6] - tmp1[5])*costab[16 + 8 + 4 + 1]; tmp2[8] = tmp1[8] + tmp1[11]; tmp2[11] = (tmp1[8] - tmp1[11])*costab[16 + 8 + 4 + 0]; tmp2[9] = tmp1[9] + tmp1[10]; tmp2[10] = (tmp1[9] - tmp1[10])*costab[16 + 8 + 4 + 1]; tmp2[12] = tmp1[12] + tmp1[15]; tmp2[15] = (tmp1[15] - tmp1[12])*costab[16 + 8 + 4 + 0]; tmp2[13] = tmp1[13] + tmp1[14]; tmp2[14] = (tmp1[14] - tmp1[13])*costab[16 + 8 + 4 + 1]; tmp2[16] = tmp1[16] + tmp1[19]; tmp2[19] = (tmp1[16] - tmp1[19])*costab[16 + 8 + 4 + 0]; tmp2[17] = tmp1[17] + tmp1[18]; tmp2[18] = (tmp1[17] - tmp1[18])*costab[16 + 8 + 4 + 1]; tmp2[20] = tmp1[20] + tmp1[23]; tmp2[23] = (tmp1[23] - tmp1[20])*costab[16 + 8 + 4 + 0]; tmp2[21] = tmp1[21] + tmp1[22]; tmp2[22] = (tmp1[22] - tmp1[21])*costab[16 + 8 + 4 + 1]; tmp2[24] = tmp1[24] + tmp1[27]; tmp2[27] = (tmp1[24] - tmp1[27])*costab[16 + 8 + 4 + 0]; tmp2[25] = tmp1[25] + tmp1[26]; tmp2[26] = (tmp1[25] - tmp1[26])*costab[16 + 8 + 4 + 1]; tmp2[28] = tmp1[28] + tmp1[31]; tmp2[31] = (tmp1[31] - tmp1[28])*costab[16 + 8 + 4 + 0]; tmp2[29] = tmp1[29] + tmp1[30]; tmp2[30] = (tmp1[30] - tmp1[29])*costab[16 + 8 + 4 + 1]; } { tmp1[0] = tmp2[0] + tmp2[1]; tmp1[1] = (tmp2[0] - tmp2[1])*costab[16 + 8 + 4 + 2]; tmp1[2] = tmp2[2] + tmp2[3]; tmp1[3] = (tmp2[3] - tmp2[2])*costab[16 + 8 + 4 + 2]; tmp1[2] += tmp1[3]; tmp1[4] = tmp2[4] + tmp2[5]; tmp1[5] = (tmp2[4] - tmp2[5])*costab[16 + 8 + 4 + 2]; tmp1[6] = tmp2[6] + tmp2[7]; tmp1[7] = (tmp2[7] - tmp2[6])*costab[16 + 8 + 4 + 2]; tmp1[6] += tmp1[7]; tmp1[4] += tmp1[6]; tmp1[6] += tmp1[5]; tmp1[5] += tmp1[7]; tmp1[8] = tmp2[8] + tmp2[9]; tmp1[9] = (tmp2[8] - tmp2[9])*costab[16 + 8 + 4 + 2]; tmp1[10] = tmp2[10] + tmp2[11]; tmp1[11] = (tmp2[11] - tmp2[10])*costab[16 + 8 + 4 + 2]; tmp1[10] += tmp1[11]; tmp1[12] = tmp2[12] + tmp2[13]; tmp1[13] = (tmp2[12] - tmp2[13])*costab[16 + 8 + 4 + 2]; tmp1[14] = tmp2[14] + tmp2[15]; tmp1[15] = (tmp2[15] - tmp2[14])*costab[16 + 8 + 4 + 2]; tmp1[14] += tmp1[15]; tmp1[12] += tmp1[14]; tmp1[14] += tmp1[13]; tmp1[13] += tmp1[15]; tmp1[16] = tmp2[16] + tmp2[17]; tmp1[17] = (tmp2[16] - tmp2[17])*costab[16 + 8 + 4 + 2]; tmp1[18] = tmp2[18] + tmp2[19]; tmp1[19] = (tmp2[19] - tmp2[18])*costab[16 + 8 + 4 + 2]; tmp1[18] += tmp1[19]; tmp1[20] = tmp2[20] + tmp2[21]; tmp1[21] = (tmp2[20] - tmp2[21])*costab[16 + 8 + 4 + 2]; tmp1[22] = tmp2[22] + tmp2[23]; tmp1[23] = (tmp2[23] - tmp2[22])*costab[16 + 8 + 4 + 2]; tmp1[22] += tmp1[23]; tmp1[20] += tmp1[22]; tmp1[22] += tmp1[21]; tmp1[21] += tmp1[23]; tmp1[24] = tmp2[24] + tmp2[25]; tmp1[25] = (tmp2[24] - tmp2[25])*costab[16 + 8 + 4 + 2]; tmp1[26] = tmp2[26] + tmp2[27]; tmp1[27] = (tmp2[27] - tmp2[26])*costab[16 + 8 + 4 + 2]; tmp1[26] += tmp1[27]; tmp1[28] = tmp2[28] + tmp2[29]; tmp1[29] = (tmp2[28] - tmp2[29])*costab[16 + 8 + 4 + 2]; tmp1[30] = tmp2[30] + tmp2[31]; tmp1[31] = (tmp2[31] - tmp2[30])*costab[16 + 8 + 4 + 2]; tmp1[30] += tmp1[31]; tmp1[28] += tmp1[30]; tmp1[30] += tmp1[29]; tmp1[29] += tmp1[31]; } { MYFLT tmp, *out0 = outptr0, *out1 = outptr1; out0[16*16] = tmp1[0]; out0[12*16] = tmp1[4]; out0[8*16] = tmp1[2]; out0[4*16] = tmp1[6]; out0[0*16] = tmp1[1]; out1[0*16] = tmp1[1]; out1[4*16] = tmp1[5]; out1[8*16] = tmp1[3]; out1[12*16] = tmp1[7]; out0[14*16] = tmp1[8] + tmp1[12]; out0[10*16] = tmp1[12] + tmp1[10]; out0[6*16] = tmp1[10] + tmp1[14]; out0[2*16] = tmp1[14] + tmp1[9]; out1[2*16] = tmp1[9] + tmp1[13]; out1[6*16] = tmp1[13] + tmp1[11]; out1[10*16] = tmp1[11] + tmp1[15]; out1[14*16] = tmp1[15]; tmp = tmp1[24] + tmp1[28]; out0[15*16] = tmp + tmp1[16]; out0[13*16] = tmp + tmp1[20]; tmp = tmp1[28] + tmp1[26]; out0[11*16] = tmp + tmp1[20]; out0[9*16] = tmp + tmp1[18]; tmp = tmp1[26] + tmp1[30]; out0[7*16] = tmp + tmp1[18]; out0[5*16] = tmp + tmp1[22]; tmp = tmp1[30] + tmp1[25]; out0[3*16] = tmp + tmp1[22]; out0[1*16] = tmp + tmp1[17]; tmp = tmp1[25] + tmp1[29]; out1[1*16] = tmp + tmp1[17]; out1[3*16] = tmp + tmp1[21]; tmp = tmp1[29] + tmp1[27]; out1[5*16] = tmp + tmp1[21]; out1[7*16] = tmp + tmp1[19]; tmp = tmp1[27] + tmp1[31]; out1[9*16] = tmp + tmp1[19]; out1[11*16] = tmp + tmp1[23]; out1[13*16] = tmp1[23] + tmp1[31]; out1[15*16] = tmp1[31]; } } static void synth_full(mpadec_t mpadec, MYFLT *bandptr, int channel, MYFLT *buffer) { struct mpadec_t *mpa = (struct mpadec_t *)mpadec; unsigned bo; MYFLT *b0, (*buf)[0x110]; if (!channel) { mpa->synth_bufoffs--; mpa->synth_bufoffs &= 0x0F; buf = mpa->synth_buffers[0]; } else buf = mpa->synth_buffers[1]; if (mpa->synth_bufoffs & 1) { b0 = buf[0]; bo = mpa->synth_bufoffs; dct64(buf[1] + ((mpa->synth_bufoffs + 1) & 0x0F), buf[0] + mpa->synth_bufoffs, bandptr); } else { b0 = buf[1]; bo = mpa->synth_bufoffs + 1; dct64(buf[0] + mpa->synth_bufoffs, buf[1] + (mpa->synth_bufoffs + 1), bandptr); } { int i; MYFLT *out = buffer; MYFLT *win = mpa->tables.decwin + (16 - bo); for (i = 16; i; i--, win += 32, b0 += 16) { MYFLT sum = win[0]*b0[0]; sum -= win[1]*b0[1]; sum += win[2]*b0[2]; sum -= win[3]*b0[3]; sum += win[4]*b0[4]; sum -= win[5]*b0[5]; sum += win[6]*b0[6]; sum -= win[7]*b0[7]; sum += win[8]*b0[8]; sum -= win[9]*b0[9]; sum += win[10]*b0[10]; sum -= win[11]*b0[11]; sum += win[12]*b0[12]; sum -= win[13]*b0[13]; sum += win[14]*b0[14]; sum -= win[15]*b0[15]; *out++ = sum; } { MYFLT sum = win[0]*b0[0]; sum += win[2]*b0[2]; sum += win[4]*b0[4]; sum += win[6]*b0[6]; sum += win[8]*b0[8]; sum += win[10]*b0[10]; sum += win[12]*b0[12]; sum += win[14]*b0[14]; *out++ = sum; win -= 32; b0 -= 16; } win += (bo << 1); for (i = 15; i; i--, win -= 32, b0 -= 16) { MYFLT sum = -win[-1]*b0[0]; sum -= win[-2]*b0[1]; sum -= win[-3]*b0[2]; sum -= win[-4]*b0[3]; sum -= win[-5]*b0[4]; sum -= win[-6]*b0[5]; sum -= win[-7]*b0[6]; sum -= win[-8]*b0[7]; sum -= win[-9]*b0[8]; sum -= win[-10]*b0[9]; sum -= win[-11]*b0[10]; sum -= win[-12]*b0[11]; sum -= win[-13]*b0[12]; sum -= win[-14]*b0[13]; sum -= win[-15]*b0[14]; sum -= win[-0]*b0[15]; *out++ = sum; } } } static void synth_half(mpadec_t mpadec, MYFLT *bandptr, int channel, MYFLT *buffer) { struct mpadec_t *mpa = (struct mpadec_t *)mpadec; unsigned bo; MYFLT *b0, (*buf)[0x110]; if (!channel) { mpa->synth_bufoffs--; mpa->synth_bufoffs &= 0x0F; buf = mpa->synth_buffers[0]; } else buf = mpa->synth_buffers[1]; if (mpa->synth_bufoffs & 1) { b0 = buf[0]; bo = mpa->synth_bufoffs; dct64(buf[1] + ((mpa->synth_bufoffs + 1) & 0x0F), buf[0] + mpa->synth_bufoffs, bandptr); } else { b0 = buf[1]; bo = mpa->synth_bufoffs + 1; dct64(buf[0] + mpa->synth_bufoffs, buf[1] + (mpa->synth_bufoffs + 1), bandptr); } { int i; MYFLT *out = buffer; MYFLT *win = mpa->tables.decwin + (16 - bo); for (i = 8; i; i--, win += 64, b0 += 32) { MYFLT sum = win[0]*b0[0]; sum -= win[1]*b0[1]; sum += win[2]*b0[2]; sum -= win[3]*b0[3]; sum += win[4]*b0[4]; sum -= win[5]*b0[5]; sum += win[6]*b0[6]; sum -= win[7]*b0[7]; sum += win[8]*b0[8]; sum -= win[9]*b0[9]; sum += win[10]*b0[10]; sum -= win[11]*b0[11]; sum += win[12]*b0[12]; sum -= win[13]*b0[13]; sum += win[14]*b0[14]; sum -= win[15]*b0[15]; *out++ = sum; } { MYFLT sum = win[0]*b0[0]; sum += win[2]*b0[2]; sum += win[4]*b0[4]; sum += win[6]*b0[6]; sum += win[8]*b0[8]; sum += win[10]*b0[10]; sum += win[12]*b0[12]; sum += win[14]*b0[14]; *out++ = sum; win -= 64; b0 -= 32; } win += (bo << 1); for (i = 7; i; i--, win -= 64, b0 -= 32) { MYFLT sum = -win[-1]*b0[0]; sum -= win[-2]*b0[1]; sum -= win[-3]*b0[2]; sum -= win[-4]*b0[3]; sum -= win[-5]*b0[4]; sum -= win[-6]*b0[5]; sum -= win[-7]*b0[6]; sum -= win[-8]*b0[7]; sum -= win[-9]*b0[8]; sum -= win[-10]*b0[9]; sum -= win[-11]*b0[10]; sum -= win[-12]*b0[11]; sum -= win[-13]*b0[12]; sum -= win[-14]*b0[13]; sum -= win[-15]*b0[14]; sum -= win[-0]*b0[15]; *out++ = sum; } } } /* Full quality */ /* 16 bit, little-endian */ static void synth_full16lmm(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; int16_t *out = (int16_t *)buffer; MYFLT buf[SBLIMIT]; synth_full(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT; i++, out++) { int32_t tmp = LROUND(buf[i]); if (tmp > 32767) tmp = 32767; else if (tmp < -32768) tmp = -32768; ((uint8_t *)out)[0] = (uint8_t)tmp; ((int8_t *)out)[1] = (int8_t)(tmp >> 8); } } #define synth_full16lsm synth_full16lmm static void synth_full16lms(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; int16_t *out = (int16_t *)buffer; MYFLT buf[SBLIMIT]; synth_full(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT; i++, out += 2) { int32_t tmp = LROUND(buf[i]); if (tmp > 32767) tmp = 32767; else if (tmp < -32768) tmp = -32768; ((uint8_t *)out)[0] = ((uint8_t *)out)[2] = (uint8_t)tmp; ((int8_t *)out)[1] = ((int8_t *)out)[3] = (int8_t)(tmp >> 8); } } static void synth_full16lss(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; int16_t *out = (int16_t *)buffer; MYFLT buf[SBLIMIT]; synth_full(mpadec, bandptr, channel, buf); if (channel) out++; for (i = 0; i < SBLIMIT; i++, out += 2) { int32_t tmp = LROUND(buf[i]); if (tmp > 32767) tmp = 32767; else if (tmp < -32768) tmp = -32768; ((uint8_t *)out)[0] = (uint8_t)tmp; ((int8_t *)out)[1] = (int8_t)(tmp >> 8); } } /* 16 bit, big-endian */ static void synth_full16bmm(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; int16_t *out = (int16_t *)buffer; MYFLT buf[SBLIMIT]; synth_full(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT; i++, out++) { int32_t tmp = LROUND(buf[i]); if (tmp > 32767) tmp = 32767; else if (tmp < -32768) tmp = -32768; ((uint8_t *)out)[1] = (uint8_t)tmp; ((int8_t *)out)[0] = (int8_t)(tmp >> 8); } } #define synth_full16bsm synth_full16bmm static void synth_full16bms(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; int16_t *out = (int16_t *)buffer; MYFLT buf[SBLIMIT]; synth_full(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT; i++, out += 2) { int32_t tmp = LROUND(buf[i]); if (tmp > 32767) tmp = 32767; else if (tmp < -32768) tmp = -32768; ((uint8_t *)out)[1] = ((uint8_t *)out)[3] = (uint8_t)tmp; ((int8_t *)out)[0] = ((int8_t *)out)[2] = (int8_t)(tmp >> 8); } } static void synth_full16bss(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; int16_t *out = (int16_t *)buffer; MYFLT buf[SBLIMIT]; synth_full(mpadec, bandptr, channel, buf); if (channel) out++; for (i = 0; i < SBLIMIT; i++, out += 2) { int32_t tmp = LROUND(buf[i]); if (tmp > 32767) tmp = 32767; else if (tmp < -32768) tmp = -32768; ((uint8_t *)out)[1] = (uint8_t)tmp; ((int8_t *)out)[0] = (int8_t)(tmp >> 8); } } /* 24 bit, little-endian */ static void synth_full24lmm(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; uint8_t *out = (uint8_t *)buffer; MYFLT buf[SBLIMIT]; synth_full(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT; i++, out += 3) { int32_t tmp = LROUND(buf[i]); if (tmp > 0x7FFFFF) tmp = 0x7FFFFF; else if (tmp < -0x800000) tmp = -0x800000; ((uint8_t *)out)[0] = (uint8_t)tmp; ((uint8_t *)out)[1] = (uint8_t)(tmp >> 8); ((int8_t *)out)[2] = (int8_t)(tmp >> 16); } } #define synth_full24lsm synth_full24lmm static void synth_full24lms(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; uint8_t *out = (uint8_t *)buffer; MYFLT buf[SBLIMIT]; synth_full(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT; i++, out += 6) { int32_t tmp = LROUND(buf[i]); if (tmp > 0x7FFFFF) tmp = 0x7FFFFF; else if (tmp < -0x800000) tmp = -0x800000; ((uint8_t *)out)[0] = ((uint8_t *)out)[3] = (uint8_t)tmp; ((uint8_t *)out)[1] = ((uint8_t *)out)[4] = (uint8_t)(tmp >> 8); ((int8_t *)out)[2] = ((int8_t *)out)[5] = (int8_t)(tmp >> 16); } } static void synth_full24lss(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; uint8_t *out = (uint8_t *)buffer; MYFLT buf[SBLIMIT]; synth_full(mpadec, bandptr, channel, buf); if (channel) out += 3; for (i = 0; i < SBLIMIT; i++, out += 6) { int32_t tmp = LROUND(buf[i]); if (tmp > 0x7FFFFF) tmp = 0x7FFFFF; else if (tmp < -0x800000) tmp = -0x800000; ((uint8_t *)out)[0] = (uint8_t)tmp; ((uint8_t *)out)[1] = (uint8_t)(tmp >> 8); ((int8_t *)out)[2] = (int8_t)(tmp >> 16); } } /* 24 bit, big-endian */ static void synth_full24bmm(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; uint8_t *out = (uint8_t *)buffer; MYFLT buf[SBLIMIT]; synth_full(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT; i++, out += 3) { int32_t tmp = LROUND(buf[i]); if (tmp > 0x7FFFFF) tmp = 0x7FFFFF; else if (tmp < -0x800000) tmp = -0x800000; ((uint8_t *)out)[2] = (uint8_t)tmp; ((uint8_t *)out)[1] = (uint8_t)(tmp >> 8); ((int8_t *)out)[0] = (int8_t)(tmp >> 16); } } #define synth_full24bsm synth_full24bmm static void synth_full24bms(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; uint8_t *out = (uint8_t *)buffer; MYFLT buf[SBLIMIT]; synth_full(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT; i++, out += 6) { int32_t tmp = LROUND(buf[i]); if (tmp > 0x7FFFFF) tmp = 0x7FFFFF; else if (tmp < -0x800000) tmp = -0x800000; ((uint8_t *)out)[2] = ((uint8_t *)out)[5] = (uint8_t)tmp; ((uint8_t *)out)[1] = ((uint8_t *)out)[4] = (uint8_t)(tmp >> 8); ((int8_t *)out)[0] = ((int8_t *)out)[3] = (int8_t)(tmp >> 16); } } static void synth_full24bss(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; uint8_t *out = (uint8_t *)buffer; MYFLT buf[SBLIMIT]; synth_full(mpadec, bandptr, channel, buf); if (channel) out += 3; for (i = 0; i < SBLIMIT; i++, out += 6) { int32_t tmp = LROUND(buf[i]); if (tmp > 0x7FFFFF) tmp = 0x7FFFFF; else if (tmp < -0x800000) tmp = -0x800000; ((uint8_t *)out)[2] = (uint8_t)tmp; ((uint8_t *)out)[1] = (uint8_t)(tmp >> 8); ((int8_t *)out)[0] = (int8_t)(tmp >> 16); } } /* 32 bit , little-endian */ static void synth_full32lmm(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; int32_t *out = (int32_t *)buffer; MYFLT buf[SBLIMIT]; synth_full(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT; i++, out++) { int64_t tmp = LLROUND(buf[i]); if (tmp > 0x7FFFFFFF) tmp = 0x7FFFFFFF; else if (tmp < (-0x7FFFFFFF - 1)) tmp = (-0x7FFFFFFF - 1); ((uint8_t *)out)[0] = (uint8_t)tmp; ((uint8_t *)out)[1] = (uint8_t)(tmp >> 8); ((uint8_t *)out)[2] = (uint8_t)(tmp >> 16); ((int8_t *)out)[3] = (int8_t)(tmp >> 24); } } #define synth_full32lsm synth_full32lmm static void synth_full32lms(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; int32_t *out = (int32_t *)buffer; MYFLT buf[SBLIMIT]; synth_full(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT; i++, out += 2) { int64_t tmp = LLROUND(buf[i]); if (tmp > 0x7FFFFFFF) tmp = 0x7FFFFFFF; else if (tmp < (-0x7FFFFFFF - 1)) tmp = (-0x7FFFFFFF - 1); ((uint8_t *)out)[0] = ((uint8_t *)out)[4] = (uint8_t)tmp; ((uint8_t *)out)[1] = ((uint8_t *)out)[5] = (uint8_t)(tmp >> 8); ((uint8_t *)out)[2] = ((uint8_t *)out)[6] = (uint8_t)(tmp >> 16); ((int8_t *)out)[3] = ((int8_t *)out)[7] = (int8_t)(tmp >> 24); } } static void synth_full32lss(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; int32_t *out = (int32_t *)buffer; MYFLT buf[SBLIMIT]; synth_full(mpadec, bandptr, channel, buf); if (channel) out++; for (i = 0; i < SBLIMIT; i++, out += 2) { int64_t tmp = LLROUND(buf[i]); if (tmp > 0x7FFFFFFF) tmp = 0x7FFFFFFF; else if (tmp < (-0x7FFFFFFF - 1)) tmp = (-0x7FFFFFFF - 1); ((uint8_t *)out)[0] = (uint8_t)tmp; ((uint8_t *)out)[1] = (uint8_t)(tmp >> 8); ((uint8_t *)out)[2] = (uint8_t)(tmp >> 16); ((int8_t *)out)[3] = (int8_t)(tmp >> 24); } } /* 32 bit, big-endian */ static void synth_full32bmm(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; int32_t *out = (int32_t *)buffer; MYFLT buf[SBLIMIT]; synth_full(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT; i++, out++) { int64_t tmp = LLROUND(buf[i]); if (tmp > 0x7FFFFFFF) tmp = 0x7FFFFFFF; else if (tmp < (-0x7FFFFFFF - 1)) tmp = (-0x7FFFFFFF - 1); ((uint8_t *)out)[3] = (uint8_t)tmp; ((uint8_t *)out)[2] = (uint8_t)(tmp >> 8); ((uint8_t *)out)[1] = (uint8_t)(tmp >> 16); ((int8_t *)out)[0] = (int8_t)(tmp >> 24); } } #define synth_full32bsm synth_full32bmm static void synth_full32bms(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; int32_t *out = (int32_t *)buffer; MYFLT buf[SBLIMIT]; synth_full(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT; i++, out += 2) { int64_t tmp = LLROUND(buf[i]); if (tmp > 0x7FFFFFFF) tmp = 0x7FFFFFFF; else if (tmp < (-0x7FFFFFFF - 1)) tmp = (-0x7FFFFFFF - 1); ((uint8_t *)out)[3] = ((uint8_t *)out)[7] = (uint8_t)tmp; ((uint8_t *)out)[2] = ((uint8_t *)out)[6] = (uint8_t)(tmp >> 8); ((uint8_t *)out)[1] = ((uint8_t *)out)[5] = (uint8_t)(tmp >> 16); ((int8_t *)out)[0] = ((int8_t *)out)[4] = (int8_t)(tmp >> 24); } } static void synth_full32bss(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; int32_t *out = (int32_t *)buffer; MYFLT buf[SBLIMIT]; synth_full(mpadec, bandptr, channel, buf); if (channel) out++; for (i = 0; i < SBLIMIT; i++, out += 2) { int64_t tmp = LLROUND(buf[i]); if (tmp > 0x7FFFFFFF) tmp = 0x7FFFFFFF; else if (tmp < (-0x7FFFFFFF - 1)) tmp = (-0x7FFFFFFF - 1); ((uint8_t *)out)[3] = (uint8_t)tmp; ((uint8_t *)out)[2] = (uint8_t)(tmp >> 8); ((uint8_t *)out)[1] = (uint8_t)(tmp >> 16); ((int8_t *)out)[0] = (int8_t)(tmp >> 24); } } /* 32 bit floating-point, little-endian */ static void synth_full32flmm(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; float *out = (float *)buffer; MYFLT buf[SBLIMIT]; synth_full(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT; i++, out++) { union tmp__ { int32_t i; float f; } tmp; tmp.f = (float)buf[i]; ((uint8_t *)out)[0] = (uint8_t)tmp.i; ((uint8_t *)out)[1] = (uint8_t)(tmp.i >> 8); ((uint8_t *)out)[2] = (uint8_t)(tmp.i >> 16); ((int8_t *)out)[3] = (int8_t)(tmp.i >> 24); } } #define synth_full32flsm synth_full32flmm static void synth_full32flms(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; float *out = (float *)buffer; MYFLT buf[SBLIMIT]; synth_full(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT; i++, out += 2) { union tmp__ { int32_t i; float f; } tmp; tmp.f = (float)buf[i]; ((uint8_t *)out)[0] = ((uint8_t *)out)[4] = (uint8_t)tmp.i; ((uint8_t *)out)[1] = ((uint8_t *)out)[5] = (uint8_t)(tmp.i >> 8); ((uint8_t *)out)[2] = ((uint8_t *)out)[6] = (uint8_t)(tmp.i >> 16); ((int8_t *)out)[3] = ((int8_t *)out)[7] = (int8_t)(tmp.i >> 24); } } static void synth_full32flss(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; float *out = (float *)buffer; MYFLT buf[SBLIMIT]; synth_full(mpadec, bandptr, channel, buf); if (channel) out++; for (i = 0; i < SBLIMIT; i++, out += 2) { union tmp__ { int32_t i; float f; } tmp; tmp.f = (float)buf[i]; ((uint8_t *)out)[0] = (uint8_t)tmp.i; ((uint8_t *)out)[1] = (uint8_t)(tmp.i >> 8); ((uint8_t *)out)[2] = (uint8_t)(tmp.i >> 16); ((int8_t *)out)[3] = (int8_t)(tmp.i >> 24); } } /* 32 bit floating-point, big-endian */ static void synth_full32fbmm(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; float *out = (float *)buffer; MYFLT buf[SBLIMIT]; synth_full(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT; i++, out++) { union tmp__ { int32_t i; float f; } tmp; tmp.f = (float)buf[i]; ((uint8_t *)out)[3] = (uint8_t)tmp.i; ((uint8_t *)out)[2] = (uint8_t)(tmp.i >> 8); ((uint8_t *)out)[1] = (uint8_t)(tmp.i >> 16); ((int8_t *)out)[0] = (int8_t)(tmp.i >> 24); } } #define synth_full32fbsm synth_full32fbmm static void synth_full32fbms(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; float *out = (float *)buffer; MYFLT buf[SBLIMIT]; synth_full(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT; i++, out += 2) { union tmp__ { int32_t i; float f; } tmp; tmp.f = (float)buf[i]; ((uint8_t *)out)[3] = ((uint8_t *)out)[7] = (uint8_t)tmp.i; ((uint8_t *)out)[2] = ((uint8_t *)out)[6] = (uint8_t)(tmp.i >> 8); ((uint8_t *)out)[1] = ((uint8_t *)out)[5] = (uint8_t)(tmp.i >> 16); ((int8_t *)out)[0] = ((int8_t *)out)[4] = (int8_t)(tmp.i >> 24); } } static void synth_full32fbss(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; float *out = (float *)buffer; MYFLT buf[SBLIMIT]; synth_full(mpadec, bandptr, channel, buf); if (channel) out++; for (i = 0; i < SBLIMIT; i++, out += 2) { union tmp__ { int32_t i; float f; } tmp; tmp.f = (float)buf[i]; ((uint8_t *)out)[3] = (uint8_t)tmp.i; ((uint8_t *)out)[2] = (uint8_t)(tmp.i >> 8); ((uint8_t *)out)[1] = (uint8_t)(tmp.i >> 16); ((int8_t *)out)[0] = (int8_t)(tmp.i >> 24); } } /* Half quality */ /* 16 bit, little-endian */ static void synth_half16lmm(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; int16_t *out = (int16_t *)buffer; MYFLT buf[SBLIMIT/2]; synth_half(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT/2; i++, out++) { int32_t tmp = LROUND(buf[i]); if (tmp > 32767) tmp = 32767; else if (tmp < -32768) tmp = -32768; ((uint8_t *)out)[0] = (uint8_t)tmp; ((int8_t *)out)[1] = (int8_t)(tmp >> 8); } } #define synth_half16lsm synth_half16lmm static void synth_half16lms(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; int16_t *out = (int16_t *)buffer; MYFLT buf[SBLIMIT/2]; synth_half(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT/2; i++, out += 2) { int32_t tmp = LROUND(buf[i]); if (tmp > 32767) tmp = 32767; else if (tmp < -32768) tmp = -32768; ((uint8_t *)out)[0] = ((uint8_t *)out)[2] = (uint8_t)tmp; ((int8_t *)out)[1] = ((int8_t *)out)[3] = (int8_t)(tmp >> 8); } } static void synth_half16lss(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; int16_t *out = (int16_t *)buffer; MYFLT buf[SBLIMIT/2]; synth_half(mpadec, bandptr, channel, buf); if (channel) out++; for (i = 0; i < SBLIMIT/2; i++, out += 2) { int32_t tmp = LROUND(buf[i]); if (tmp > 32767) tmp = 32767; else if (tmp < -32768) tmp = -32768; ((uint8_t *)out)[0] = (uint8_t)tmp; ((int8_t *)out)[1] = (int8_t)(tmp >> 8); } } /* 16 bit, big-endian */ static void synth_half16bmm(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; int16_t *out = (int16_t *)buffer; MYFLT buf[SBLIMIT/2]; synth_half(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT/2; i++, out++) { int32_t tmp = LROUND(buf[i]); if (tmp > 32767) tmp = 32767; else if (tmp < -32768) tmp = -32768; ((uint8_t *)out)[1] = (uint8_t)tmp; ((int8_t *)out)[0] = (int8_t)(tmp >> 8); } } #define synth_half16bsm synth_half16bmm static void synth_half16bms(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; int16_t *out = (int16_t *)buffer; MYFLT buf[SBLIMIT/2]; synth_half(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT/2; i++, out += 2) { int32_t tmp = LROUND(buf[i]); if (tmp > 32767) tmp = 32767; else if (tmp < -32768) tmp = -32768; ((uint8_t *)out)[1] = ((uint8_t *)out)[3] = (uint8_t)tmp; ((int8_t *)out)[0] = ((int8_t *)out)[2] = (int8_t)(tmp >> 8); } } static void synth_half16bss(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; int16_t *out = (int16_t *)buffer; MYFLT buf[SBLIMIT/2]; synth_half(mpadec, bandptr, channel, buf); if (channel) out++; for (i = 0; i < SBLIMIT/2; i++, out += 2) { int32_t tmp = LROUND(buf[i]); if (tmp > 32767) tmp = 32767; else if (tmp < -32768) tmp = -32768; ((uint8_t *)out)[1] = (uint8_t)tmp; ((int8_t *)out)[0] = (int8_t)(tmp >> 8); } } /* 24 bit, little-endian */ static void synth_half24lmm(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; uint8_t *out = (uint8_t *)buffer; MYFLT buf[SBLIMIT/2]; synth_half(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT/2; i++, out += 3) { int32_t tmp = LROUND(buf[i]); if (tmp > 0x7FFFFF) tmp = 0x7FFFFF; else if (tmp < -0x800000) tmp = -0x800000; ((uint8_t *)out)[0] = (uint8_t)tmp; ((uint8_t *)out)[1] = (uint8_t)(tmp >> 8); ((int8_t *)out)[2] = (int8_t)(tmp >> 16); } } #define synth_half24lsm synth_half24lmm static void synth_half24lms(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; uint8_t *out = (uint8_t *)buffer; MYFLT buf[SBLIMIT/2]; synth_half(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT/2; i++, out += 6) { int32_t tmp = LROUND(buf[i]); if (tmp > 0x7FFFFF) tmp = 0x7FFFFF; else if (tmp < -0x800000) tmp = -0x800000; ((uint8_t *)out)[0] = ((uint8_t *)out)[3] = (uint8_t)tmp; ((uint8_t *)out)[1] = ((uint8_t *)out)[4] = (uint8_t)(tmp >> 8); ((int8_t *)out)[2] = ((int8_t *)out)[5] = (int8_t)(tmp >> 16); } } static void synth_half24lss(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; uint8_t *out = (uint8_t *)buffer; MYFLT buf[SBLIMIT/2]; synth_half(mpadec, bandptr, channel, buf); if (channel) out += 3; for (i = 0; i < SBLIMIT/2; i++, out += 6) { int32_t tmp = LROUND(buf[i]); if (tmp > 0x7FFFFF) tmp = 0x7FFFFF; else if (tmp < -0x800000) tmp = -0x800000; ((uint8_t *)out)[0] = (uint8_t)tmp; ((uint8_t *)out)[1] = (uint8_t)(tmp >> 8); ((int8_t *)out)[2] = (int8_t)(tmp >> 16); } } /* 24 bit, big-endian */ static void synth_half24bmm(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; uint8_t *out = (uint8_t *)buffer; MYFLT buf[SBLIMIT/2]; synth_half(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT/2; i++, out += 3) { int32_t tmp = LROUND(buf[i]); if (tmp > 0x7FFFFF) tmp = 0x7FFFFF; else if (tmp < -0x800000) tmp = -0x800000; ((uint8_t *)out)[2] = (uint8_t)tmp; ((uint8_t *)out)[1] = (uint8_t)(tmp >> 8); ((int8_t *)out)[0] = (int8_t)(tmp >> 16); } } #define synth_half24bsm synth_half24bmm static void synth_half24bms(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; uint8_t *out = (uint8_t *)buffer; MYFLT buf[SBLIMIT/2]; synth_half(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT/2; i++, out += 6) { int32_t tmp = LROUND(buf[i]); if (tmp > 0x7FFFFF) tmp = 0x7FFFFF; else if (tmp < -0x800000) tmp = -0x800000; ((uint8_t *)out)[2] = ((uint8_t *)out)[5] = (uint8_t)tmp; ((uint8_t *)out)[1] = ((uint8_t *)out)[4] = (uint8_t)(tmp >> 8); ((int8_t *)out)[0] = ((int8_t *)out)[3] = (int8_t)(tmp >> 16); } } static void synth_half24bss(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; uint8_t *out = (uint8_t *)buffer; MYFLT buf[SBLIMIT/2]; synth_half(mpadec, bandptr, channel, buf); if (channel) out += 3; for (i = 0; i < SBLIMIT/2; i++, out += 6) { int32_t tmp = LROUND(buf[i]); if (tmp > 0x7FFFFF) tmp = 0x7FFFFF; else if (tmp < -0x800000) tmp = -0x800000; ((uint8_t *)out)[2] = (uint8_t)tmp; ((uint8_t *)out)[1] = (uint8_t)(tmp >> 8); ((int8_t *)out)[0] = (int8_t)(tmp >> 16); } } /* 32 bit, little-endian */ static void synth_half32lmm(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; int32_t *out = (int32_t *)buffer; MYFLT buf[SBLIMIT/2]; synth_half(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT/2; i++, out++) { int64_t tmp = LLROUND(buf[i]); if (tmp > 0x7FFFFFFF) tmp = 0x7FFFFFFF; else if (tmp < (-0x7FFFFFFF - 1)) tmp = (-0x7FFFFFFF - 1); ((uint8_t *)out)[0] = (uint8_t)tmp; ((uint8_t *)out)[1] = (uint8_t)(tmp >> 8); ((uint8_t *)out)[2] = (uint8_t)(tmp >> 16); ((int8_t *)out)[3] = (int8_t)(tmp >> 24); } } #define synth_half32lsm synth_half32lmm static void synth_half32lms(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; int32_t *out = (int32_t *)buffer; MYFLT buf[SBLIMIT/2]; synth_half(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT/2; i++, out += 2) { int64_t tmp = LLROUND(buf[i]); if (tmp > 0x7FFFFFFF) tmp = 0x7FFFFFFF; else if (tmp < (-0x7FFFFFFF - 1)) tmp = (-0x7FFFFFFF - 1); ((uint8_t *)out)[0] = ((uint8_t *)out)[4] = (uint8_t)tmp; ((uint8_t *)out)[1] = ((uint8_t *)out)[5] = (uint8_t)(tmp >> 8); ((uint8_t *)out)[2] = ((uint8_t *)out)[6] = (uint8_t)(tmp >> 16); ((int8_t *)out)[3] = ((int8_t *)out)[7] = (int8_t)(tmp >> 24); } } static void synth_half32lss(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; int32_t *out = (int32_t *)buffer; MYFLT buf[SBLIMIT/2]; synth_half(mpadec, bandptr, channel, buf); if (channel) out++; for (i = 0; i < SBLIMIT/2; i++, out += 2) { int64_t tmp = LLROUND(buf[i]); if (tmp > 0x7FFFFFFF) tmp = 0x7FFFFFFF; else if (tmp < (-0x7FFFFFFF - 1)) tmp = (-0x7FFFFFFF - 1); ((uint8_t *)out)[0] = (uint8_t)tmp; ((uint8_t *)out)[1] = (uint8_t)(tmp >> 8); ((uint8_t *)out)[2] = (uint8_t)(tmp >> 16); ((int8_t *)out)[3] = (int8_t)(tmp >> 24); } } /* 32 bit, big-endian */ static void synth_half32bmm(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; int32_t *out = (int32_t *)buffer; MYFLT buf[SBLIMIT/2]; synth_half(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT/2; i++, out++) { int64_t tmp = LLROUND(buf[i]); if (tmp > 0x7FFFFFFF) tmp = 0x7FFFFFFF; else if (tmp < (-0x7FFFFFFF - 1)) tmp = (-0x7FFFFFFF - 1); ((uint8_t *)out)[3] = (uint8_t)tmp; ((uint8_t *)out)[2] = (uint8_t)(tmp >> 8); ((uint8_t *)out)[1] = (uint8_t)(tmp >> 16); ((int8_t *)out)[0] = (int8_t)(tmp >> 24); } } #define synth_half32bsm synth_half32bmm static void synth_half32bms(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; int32_t *out = (int32_t *)buffer; MYFLT buf[SBLIMIT/2]; synth_half(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT/2; i++, out += 2) { int64_t tmp = LLROUND(buf[i]); if (tmp > 0x7FFFFFFF) tmp = 0x7FFFFFFF; else if (tmp < (-0x7FFFFFFF - 1)) tmp = (-0x7FFFFFFF - 1); ((uint8_t *)out)[3] = ((uint8_t *)out)[7] = (uint8_t)tmp; ((uint8_t *)out)[2] = ((uint8_t *)out)[6] = (uint8_t)(tmp >> 8); ((uint8_t *)out)[1] = ((uint8_t *)out)[5] = (uint8_t)(tmp >> 16); ((int8_t *)out)[0] = ((int8_t *)out)[4] = (int8_t)(tmp >> 24); } } static void synth_half32bss(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; int32_t *out = (int32_t *)buffer; MYFLT buf[SBLIMIT/2]; synth_half(mpadec, bandptr, channel, buf); if (channel) out++; for (i = 0; i < SBLIMIT/2; i++, out += 2) { int64_t tmp = LLROUND(buf[i]); if (tmp > 0x7FFFFFFF) tmp = 0x7FFFFFFF; else if (tmp < (-0x7FFFFFFF - 1)) tmp = (-0x7FFFFFFF - 1); ((uint8_t *)out)[3] = (uint8_t)tmp; ((uint8_t *)out)[2] = (uint8_t)(tmp >> 8); ((uint8_t *)out)[1] = (uint8_t)(tmp >> 16); ((int8_t *)out)[0] = (int8_t)(tmp >> 24); } } /* 32 bit floating-point, little-endian */ static void synth_half32flmm(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; float *out = (float *)buffer; MYFLT buf[SBLIMIT/2]; synth_half(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT/2; i++, out++) { union tmp__ { int32_t i; float f; } tmp; tmp.f = (float)buf[i]; ((uint8_t *)out)[0] = (uint8_t)tmp.i; ((uint8_t *)out)[1] = (uint8_t)(tmp.i >> 8); ((uint8_t *)out)[2] = (uint8_t)(tmp.i >> 16); ((int8_t *)out)[3] = (int8_t)(tmp.i >> 24); } } #define synth_half32flsm synth_half32flmm static void synth_half32flms(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; float *out = (float *)buffer; MYFLT buf[SBLIMIT/2]; synth_half(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT/2; i++, out += 2) { union tmp__ { int32_t i; float f; } tmp; tmp.f = (float)buf[i]; ((uint8_t *)out)[0] = ((uint8_t *)out)[4] = (uint8_t)tmp.i; ((uint8_t *)out)[1] = ((uint8_t *)out)[5] = (uint8_t)(tmp.i >> 8); ((uint8_t *)out)[2] = ((uint8_t *)out)[6] = (uint8_t)(tmp.i >> 16); ((int8_t *)out)[3] = ((int8_t *)out)[7] = (int8_t)(tmp.i >> 24); } } static void synth_half32flss(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; float *out = (float *)buffer; MYFLT buf[SBLIMIT/2]; synth_half(mpadec, bandptr, channel, buf); if (channel) out++; for (i = 0; i < SBLIMIT/2; i++, out += 2) { union tmp__ { int32_t i; float f; } tmp; tmp.f = (float)buf[i]; ((uint8_t *)out)[0] = (uint8_t)tmp.i; ((uint8_t *)out)[1] = (uint8_t)(tmp.i >> 8); ((uint8_t *)out)[2] = (uint8_t)(tmp.i >> 16); ((int8_t *)out)[3] = (int8_t)(tmp.i >> 24); } } /* 32 bit floating-point, big-endian */ static void synth_half32fbmm(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; float *out = (float *)buffer; MYFLT buf[SBLIMIT/2]; synth_half(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT/2; i++, out++) { union tmp__ { int32_t i; float f; } tmp; tmp.f = (float)buf[i]; ((uint8_t *)out)[3] = (uint8_t)tmp.i; ((uint8_t *)out)[2] = (uint8_t)(tmp.i >> 8); ((uint8_t *)out)[1] = (uint8_t)(tmp.i >> 16); ((int8_t *)out)[0] = (int8_t)(tmp.i >> 24); } } #define synth_half32fbsm synth_half32fbmm static void synth_half32fbms(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; float *out = (float *)buffer; MYFLT buf[SBLIMIT/2]; synth_half(mpadec, bandptr, channel, buf); for (i = 0; i < SBLIMIT/2; i++, out += 2) { union tmp__ { int32_t i; float f; } tmp; tmp.f = (float)buf[i]; ((uint8_t *)out)[3] = ((uint8_t *)out)[7] = (uint8_t)tmp.i; ((uint8_t *)out)[2] = ((uint8_t *)out)[6] = (uint8_t)(tmp.i >> 8); ((uint8_t *)out)[1] = ((uint8_t *)out)[5] = (uint8_t)(tmp.i >> 16); ((int8_t *)out)[0] = ((int8_t *)out)[4] = (int8_t)(tmp.i >> 24); } } static void synth_half32fbss(mpadec_t mpadec, MYFLT *bandptr, int channel, uint8_t *buffer) { int i; float *out = (float *)buffer; MYFLT buf[SBLIMIT/2]; synth_half(mpadec, bandptr, channel, buf); if (channel) out++; for (i = 0; i < SBLIMIT/2; i++, out += 2) { union tmp__ { int32 i; float f; } tmp; tmp.f = (float)buf[i]; ((uint8_t *)out)[3] = (uint8_t)tmp.i; ((uint8_t *)out)[2] = (uint8_t)(tmp.i >> 8); ((uint8_t *)out)[1] = (uint8_t)(tmp.i >> 16); ((int8_t *)out)[0] = (int8_t)(tmp.i >> 24); } } void *synth_table[2][2][4][4] = { { { { synth_full16lmm, synth_full16lms, synth_full16lsm, synth_full16lss }, { synth_full24lmm, synth_full24lms, synth_full24lsm, synth_full24lss }, { synth_full32lmm, synth_full32lms, synth_full32lsm, synth_full32lss }, { synth_full32flmm, synth_full32flms, synth_full32flsm, synth_full32flss } }, { { synth_full16bmm, synth_full16bms, synth_full16bsm, synth_full16bss }, { synth_full24bmm, synth_full24bms, synth_full24bsm, synth_full24bss }, { synth_full32bmm, synth_full32bms, synth_full32bsm, synth_full32bss }, { synth_full32fbmm, synth_full32fbms, synth_full32fbsm, synth_full32fbss } } }, { { { synth_half16lmm, synth_half16lms, synth_half16lsm, synth_half16lss }, { synth_half24lmm, synth_half24lms, synth_half24lsm, synth_half24lss }, { synth_half32lmm, synth_half32lms, synth_half32lsm, synth_half32lss }, { synth_half32flmm, synth_half32flms, synth_half32flsm, synth_half32flss } }, { { synth_half16bmm, synth_half16bms, synth_half16bsm, synth_half16bss }, { synth_half24bmm, synth_half24bms, synth_half24bsm, synth_half24bss }, { synth_half32bmm, synth_half32bms, synth_half32bsm, synth_half32bss }, { synth_half32fbmm, synth_half32fbms, synth_half32fbsm, synth_half32fbss } } } }; csound-6.10.0/InOut/libmpadec/tables.c000066400000000000000000001312421321653344700175000ustar00rootroot00000000000000/* * mpadec - MPEG audio decoder * Copyright (C) 2002-2004 Dmitriy Startsev (dstartsev@rambler.ru) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* $Id: tables.c,v 1.1.1.1 2004/07/27 02:58:48 metal_man Exp $ */ #include #include "csoundCore.h" #include "mpadec_internal.h" const uint16_t crc_table[256] = { 0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011, 0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022, 0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072, 0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041, 0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2, 0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1, 0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1, 0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082, 0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192, 0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1, 0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1, 0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2, 0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151, 0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162, 0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132, 0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101, 0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312, 0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321, 0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371, 0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342, 0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1, 0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2, 0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2, 0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381, 0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291, 0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2, 0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2, 0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1, 0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252, 0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261, 0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231, 0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202 }; const MYFLT newcos[8] = { 0.93969262078590838405410927732473, -0.17364817766693034885171662676931, -0.76604444311897803520239265055542, 0.98480775301220805936674302458952, -0.34202014332566873304409961468226, -0.64278760968653932632264340990726, 0.86602540378443864676372317075294, 0.5 }; const MYFLT tfcos36[9] = { 0.50190991877167369479228784572231, 0.51763809020504152469779767524810, 0.55168895948124587824344735167135, 0.61038729438072803416729403213053, 0.70710678118654752440084436210485, 0.87172339781054900991884170836219, 1.18310079157624925896683916310440, 1.93185165257813657349948639945780, 5.73685662283492756457461251791420 }; const MYFLT tfcos12[3] = { 0.5176380902050415246977976752481, 0.70710678118654752440084436210485, 1.9318516525781365734994863994578 }; const MYFLT cs[8] = { 0.85749292571254418689325777610964, 0.88174199731770518177557399759066, 0.94962864910273289204833276115398, 0.98331459249179014599030200066392, 0.99551781606758576429088040422867, 0.99916055817814750452934664352117, 0.99989919524444704626703489425565, 0.99999315507028023572010150517204 }; const MYFLT ca[8] = { -0.5144957554275265121359546656657900, -0.4717319685649722722499320887110000, -0.3133774542039018543759498111808100, -0.1819131996109811770082058701228300, -0.0945741925264206476076336384017240, -0.0409655828853040476857032123843680, -0.0141985685724711480569918954984300, -0.0036999746737600368721643755691366 }; bandinfo_t band_info[9] = { /* MPEG 1.0 */ { { 0, 4, 8, 12, 16, 20, 24, 30, 36, 44, 52, 62, 74, 90, 110, 134, 162, 196, 238, 288, 342, 418, 576 }, { 4, 4, 4, 4, 4, 4, 6, 6, 8, 8, 10, 12, 16, 20, 24, 28, 34, 42, 50, 54, 76, 158 }, { 0, 4*3, 8*3, 12*3, 16*3, 22*3, 30*3, 40*3, 52*3, 66*3, 84*3, 106*3, 136*3, 192*3 }, { 4, 4, 4, 4, 6, 8, 10, 12, 14, 18, 22, 30, 56 } }, { { 0, 4, 8, 12, 16, 20, 24, 30, 36, 42, 50, 60, 72, 88, 106, 128, 156, 190, 230, 276, 330, 384, 576 }, { 4, 4, 4, 4, 4, 4, 6, 6, 6, 8, 10, 12, 16, 18, 22, 28, 34, 40, 46, 54, 54, 192 }, { 0, 4*3, 8*3, 12*3, 16*3, 22*3, 28*3, 38*3, 50*3, 64*3, 80*3, 100*3, 126*3, 192*3 }, { 4, 4, 4, 4, 6, 6, 10, 12, 14, 16, 20, 26, 66 } }, { { 0, 4, 8, 12, 16, 20, 24, 30, 36, 44, 54, 66, 82, 102, 126, 156, 194, 240, 296, 364, 448, 550, 576 }, { 4, 4, 4, 4, 4, 4, 6, 6, 8, 10, 12, 16, 20, 24, 30, 38, 46, 56, 68, 84, 102, 26 }, { 0, 4*3, 8*3, 12*3, 16*3, 22*3, 30*3, 42*3, 58*3, 78*3, 104*3, 138*3, 180*3, 192*3 }, { 4, 4, 4, 4, 6, 8, 12, 16, 20, 26, 34, 42, 12 } }, /* MPEG 2.0 */ { { 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522, 576 }, { 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, 20, 24, 28, 32, 38, 46, 52, 60, 68, 58, 54 }, { 0, 4*3, 8*3, 12*3, 18*3, 24*3, 32*3, 42*3, 56*3, 74*3, 100*3, 132*3, 174*3, 192*3 }, { 4, 4, 4, 6, 6, 8, 10, 14, 18, 26, 32, 42, 18 } }, { { 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 114, 136, 162, 194, 232, 278, 330, 394, 464, 540, 576 }, { 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, 18, 22, 26, 32, 38, 46, 52, 64, 70, 76, 36 }, { 0, 4*3, 8*3, 12*3, 18*3, 26*3, 36*3, 48*3, 62*3, 80*3, 104*3, 136*3, 180*3, 192*3 }, { 4, 4, 4, 6, 8, 10, 12, 14, 18, 24, 32, 44, 12 } }, { { 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522, 576 }, { 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, 20, 24, 28, 32, 38, 46, 52, 60, 68, 58, 54 }, { 0, 4*3, 8*3, 12*3, 18*3, 26*3, 36*3, 48*3, 62*3, 80*3, 104*3, 134*3, 174*3, 192*3 }, { 4, 4, 4, 6, 8, 10, 12, 14, 18, 24, 30, 40, 18 } }, /* MPEG 2.5 */ { { 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522, 576 }, { 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, 20, 24, 28, 32, 38, 46, 52, 60, 68, 58, 54 }, { 0, 12, 24, 36, 54, 78, 108, 144, 186, 240, 312, 402, 522, 576 }, { 4, 4, 4, 6, 8, 10, 12, 14, 18, 24, 30, 40, 18 } }, { { 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522, 576 }, { 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, 20, 24, 28, 32, 38, 46, 52, 60, 68, 58, 54 }, { 0, 12, 24, 36, 54, 78, 108, 144, 186, 240, 312, 402, 522, 576 }, { 4, 4, 4, 6, 8, 10, 12, 14, 18, 24, 30, 40, 18 } }, { { 0, 12, 24, 36, 48, 60, 72, 88, 108, 132, 160, 192, 232, 280, 336, 400, 476, 566, 568, 570, 572, 574, 576 }, { 12, 12, 12, 12, 12, 12, 16, 20, 24, 28, 32, 40, 48, 56, 64, 76, 90, 2, 2, 2, 2, 2 }, { 0, 24, 48, 72, 108, 156, 216, 288, 372, 480, 486, 492, 498, 576 }, { 8, 8, 8, 12, 16, 20, 24, 28, 36, 2, 2, 2, 26 } }, }; static alloc_table_t alloc_0[] = { {4,0}, {5,3}, {3,-3}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {14,-8191}, {15,-16383}, {16,-32767}, {4,0}, {5,3}, {3,-3}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {14,-8191}, {15,-16383}, {16,-32767}, {4,0}, {5,3}, {3,-3}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {14,-8191}, {15,-16383}, {16,-32767}, {4,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {16,-32767}, {4,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {16,-32767}, {4,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {16,-32767}, {4,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {16,-32767}, {4,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {16,-32767}, {4,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {16,-32767}, {4,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {16,-32767}, {4,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {16,-32767}, {3,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {16,-32767}, {3,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {16,-32767}, {3,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {16,-32767}, {3,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {16,-32767}, {3,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {16,-32767}, {3,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {16,-32767}, {3,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {16,-32767}, {3,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {16,-32767}, {3,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {16,-32767}, {3,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {16,-32767}, {3,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {16,-32767}, {3,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {16,-32767}, {2,0}, {5,3}, {7,5}, {16,-32767}, {2,0}, {5,3}, {7,5}, {16,-32767}, {2,0}, {5,3}, {7,5}, {16,-32767}, {2,0}, {5,3}, {7,5}, {16,-32767} }; static alloc_table_t alloc_1[] = { {4,0}, {5,3}, {3,-3}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {14,-8191}, {15,-16383}, {16,-32767}, {4,0}, {5,3}, {3,-3}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {14,-8191}, {15,-16383}, {16,-32767}, {4,0}, {5,3}, {3,-3}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {14,-8191}, {15,-16383}, {16,-32767}, {4,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {16,-32767}, {4,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {16,-32767}, {4,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {16,-32767}, {4,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {16,-32767}, {4,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {16,-32767}, {4,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {16,-32767}, {4,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {16,-32767}, {4,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {16,-32767}, {3,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {16,-32767}, {3,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {16,-32767}, {3,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {16,-32767}, {3,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {16,-32767}, {3,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {16,-32767}, {3,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {16,-32767}, {3,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {16,-32767}, {3,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {16,-32767}, {3,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {16,-32767}, {3,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {16,-32767}, {3,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {16,-32767}, {3,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {16,-32767}, {2,0}, {5,3}, {7,5}, {16,-32767}, {2,0}, {5,3}, {7,5}, {16,-32767}, {2,0}, {5,3}, {7,5}, {16,-32767}, {2,0}, {5,3}, {7,5}, {16,-32767}, {2,0}, {5,3}, {7,5}, {16,-32767}, {2,0}, {5,3}, {7,5}, {16,-32767}, {2,0}, {5,3}, {7,5}, {16,-32767} }; static alloc_table_t alloc_2[] = { {4,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {14,-8191}, {15,-16383}, {4,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {14,-8191}, {15,-16383}, {3,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {3,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {3,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {3,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {3,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {3,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63} }; static alloc_table_t alloc_3[] = { {4,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {14,-8191}, {15,-16383}, {4,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {14,-8191}, {15,-16383}, {3,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {3,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {3,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {3,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {3,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {3,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {3,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {3,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {3,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {3,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63} }; static alloc_table_t alloc_4[] = { {4,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {14,-8191}, {4,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {14,-8191}, {4,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {14,-8191}, {4,0}, {5,3}, {7,5}, {3,-3}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {8,-127}, {9,-255}, {10,-511}, {11,-1023}, {12,-2047}, {13,-4095}, {14,-8191}, {3,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {3,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {3,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {3,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {3,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {3,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {3,0}, {5,3}, {7,5}, {10,9}, {4,-7}, {5,-15}, {6,-31}, {7,-63}, {2,0}, {5,3}, {7,5}, {10,9}, {2,0}, {5,3}, {7,5}, {10,9}, {2,0}, {5,3}, {7,5}, {10,9}, {2,0}, {5,3}, {7,5}, {10,9}, {2,0}, {5,3}, {7,5}, {10,9}, {2,0}, {5,3}, {7,5}, {10,9}, {2,0}, {5,3}, {7,5}, {10,9}, {2,0}, {5,3}, {7,5}, {10,9}, {2,0}, {5,3}, {7,5}, {10,9}, {2,0}, {5,3}, {7,5}, {10,9}, {2,0}, {5,3}, {7,5}, {10,9}, {2,0}, {5,3}, {7,5}, {10,9}, {2,0}, {5,3}, {7,5}, {10,9}, {2,0}, {5,3}, {7,5}, {10,9}, {2,0}, {5,3}, {7,5}, {10,9}, {2,0}, {5,3}, {7,5}, {10,9}, {2,0}, {5,3}, {7,5}, {10,9}, {2,0}, {5,3}, {7,5}, {10,9}, {2,0}, {5,3}, {7,5}, {10,9} }; alloc_table_t *alloc_tables[5] = { alloc_0, alloc_1, alloc_2, alloc_3, alloc_4 }; static int16_t tab0[] = { 0 }; static int16_t tab1[] = { -5, -3, -1, 17, 1, 16, 0 }; static int16_t tab2[] = { -15, -11, -9, -5, -3, -1, 34, 2, 18, -1, 33, 32, 17, -1, 1, 16, 0 }; static int16_t tab3[] = { -13, -11, -9, -5, -3, -1, 34, 2, 18, -1, 33, 32, 16, 17, -1, 1, 0 }; static int16_t tab5[] = { -29, -25, -23, -15, -7, -5, -3, -1, 51, 35, 50, 49, -3, -1, 19, 3, -1, 48, 34, -3, -1, 18, 33, -1, 2, 32, 17, -1, 1, 16, 0 }; static int16_t tab6[] = { -25, -19, -13, -9, -5, -3, -1, 51, 3, 35, -1, 50, 48, -1, 19, 49, -3, -1, 34, 2, 18, -3, -1, 33, 32, 1, -1, 17, -1, 16, 0 }; static int16_t tab7[] = { -69, -65, -57, -39, -29, -17, -11, -7, -3, -1, 85, 69, -1, 84, 83, -1, 53, 68, -3, -1, 37, 82, 21, -5, -1, 81, -1, 5, 52, -1, 80, -1, 67, 51, -5, -3, -1, 36, 66, 20, -1, 65, 64, -11, -7, -3, -1, 4, 35, -1, 50, 3, -1, 19, 49, -3, -1, 48, 34, 18, -5, -1, 33, -1, 2, 32, 17, -1, 1, 16, 0 }; static int16_t tab8[] = { -65, -63, -59, -45, -31, -19, -13, -7, -5, -3, -1, 85, 84, 69, 83, -3, -1, 53, 68, 37, -3, -1, 82, 5, 21, -5, -1, 81, -1, 52, 67, -3, -1, 80, 51, 36, -5, -3, -1, 66, 20, 65, -3, -1, 4, 64, -1, 35, 50, -9, -7, -3, -1, 19, 49, -1, 3, 48, 34, -1, 2, 32, -1, 18, 33, 17, -3, -1, 1, 16, 0 }; static int16_t tab9[] = { -63, -53, -41, -29, -19, -11, -5, -3, -1, 85, 69, 53, -1, 83, -1, 84, 5, -3, -1, 68, 37, -1, 82, 21, -3, -1, 81, 52, -1, 67, -1, 80, 4, -7, -3, -1, 36, 66, -1, 51, 64, -1, 20, 65, -5, -3, -1, 35, 50, 19, -1, 49, -1, 3, 48, -5, -3, -1, 34, 2, 18, -1, 33, 32, -3, -1, 17, 1, -1, 16, 0 }; static int16_t tab10[] = { -125, -121, -111, -83, -55, -35, -21, -13, -7, -3, -1, 119, 103, -1, 118, 87, -3, -1, 117, 102, 71, -3, -1, 116, 86, -1, 101, 55, -9, -3, -1, 115, 70, -3, -1, 85, 84, 99, -1, 39, 114, -11, -5, -3, -1, 100, 7, 112, -1, 98, -1, 69, 53, -5, -1, 6, -1, 83, 68, 23, -17, -5, -1, 113, -1, 54, 38, -5, -3, -1, 37, 82, 21, -1, 81, -1, 52, 67, -3, -1, 22, 97, -1, 96, -1, 5, 80, -19, -11, -7, -3, -1, 36, 66, -1, 51, 4, -1, 20, 65, -3, -1, 64, 35, -1, 50, 3, -3, -1, 19, 49, -1, 48, 34, -7, -3, -1, 18, 33, -1, 2, 32, 17, -1, 1, 16, 0 }; static int16_t tab11[] = { -121, -113, -89, -59, -43, -27, -17, -7, -3, -1, 119, 103, -1, 118, 117, -3, -1, 102, 71, -1, 116, -1, 87, 85, -5, -3, -1, 86, 101, 55, -1, 115, 70, -9, -7, -3, -1, 69, 84, -1, 53, 83, 39, -1, 114, -1, 100, 7, -5, -1, 113, -1, 23, 112, -3, -1, 54, 99, -1, 96, -1, 68, 37, -13, -7, -5, -3, -1, 82, 5, 21, 98, -3, -1, 38, 6, 22, -5, -1, 97, -1, 81, 52, -5, -1, 80, -1, 67, 51, -1, 36, 66, -15, -11, -7, -3, -1, 20, 65, -1, 4, 64, -1, 35, 50, -1, 19, 49, -5, -3, -1, 3, 48, 34, 33, -5, -1, 18, -1, 2, 32, 17, -3, -1, 1, 16, 0 }; static int16_t tab12[] = { -115, -99, -73, -45, -27, -17, -9, -5, -3, -1, 119, 103, 118, -1, 87, 117, -3, -1, 102, 71, -1, 116, 101, -3, -1, 86, 55, -3, -1, 115, 85, 39, -7, -3, -1, 114, 70, -1, 100, 23, -5, -1, 113, -1, 7, 112, -1, 54, 99, -13, -9, -3, -1, 69, 84, -1, 68, -1, 6, 5, -1, 38, 98, -5, -1, 97, -1, 22, 96, -3, -1, 53, 83, -1, 37, 82, -17, -7, -3, -1, 21, 81, -1, 52, 67, -5, -3, -1, 80, 4, 36, -1, 66, 20, -3, -1, 51, 65, -1, 35, 50, -11, -7, -5, -3, -1, 64, 3, 48, 19, -1, 49, 34, -1, 18, 33, -7, -5, -3, -1, 2, 32, 0, 17, -1, 1, 16 }; static int16_t tab13[] = { -509, -503, -475, -405, -333, -265, -205, -153, -115, -83, -53, -35, -21, -13, -9, -7, -5, -3, -1, 254, 252, 253, 237, 255, -1, 239, 223, -3, -1, 238, 207, -1, 222, 191, -9, -3, -1, 251, 206, -1, 220, -1, 175, 233, -1, 236, 221, -9, -5, -3, -1, 250, 205, 190, -1, 235, 159, -3, -1, 249, 234, -1, 189, 219, -17, -9, -3, -1, 143, 248, -1, 204, -1, 174, 158, -5, -1, 142, -1, 127, 126, 247, -5, -1, 218, -1, 173, 188, -3, -1, 203, 246, 111, -15, -7, -3, -1, 232, 95, -1, 157, 217, -3, -1, 245, 231, -1, 172, 187, -9, -3, -1, 79, 244, -3, -1, 202, 230, 243, -1, 63, -1, 141, 216, -21, -9, -3, -1, 47, 242, -3, -1, 110, 156, 15, -5, -3, -1, 201, 94, 171, -3, -1, 125, 215, 78, -11, -5, -3, -1, 200, 214, 62, -1, 185, -1, 155, 170, -1, 31, 241, -23, -13, -5, -1, 240, -1, 186, 229, -3, -1, 228, 140, -1, 109, 227, -5, -1, 226, -1, 46, 14, -1, 30, 225, -15, -7, -3, -1, 224, 93, -1, 213, 124, -3, -1, 199, 77, -1, 139, 184, -7, -3, -1, 212, 154, -1, 169, 108, -1, 198, 61, -37, -21, -9, -5, -3, -1, 211, 123, 45, -1, 210, 29, -5, -1, 183, -1, 92, 197, -3, -1, 153, 122, 195, -7, -5, -3, -1, 167, 151, 75, 209, -3, -1, 13, 208, -1, 138, 168, -11, -7, -3, -1, 76, 196, -1, 107, 182, -1, 60, 44, -3, -1, 194, 91, -3, -1, 181, 137, 28, -43, -23, -11, -5, -1, 193, -1, 152, 12, -1, 192, -1, 180, 106, -5, -3, -1, 166, 121, 59, -1, 179, -1, 136, 90, -11, -5, -1, 43, -1, 165, 105, -1, 164, -1, 120, 135, -5, -1, 148, -1, 119, 118, 178, -11, -3, -1, 27, 177, -3, -1, 11, 176, -1, 150, 74, -7, -3, -1, 58, 163, -1, 89, 149, -1, 42, 162, -47, -23, -9, -3, -1, 26, 161, -3, -1, 10, 104, 160, -5, -3, -1, 134, 73, 147, -3, -1, 57, 88, -1, 133, 103, -9, -3, -1, 41, 146, -3, -1, 87, 117, 56, -5, -1, 131, -1, 102, 71, -3, -1, 116, 86, -1, 101, 115, -11, -3, -1, 25, 145, -3, -1, 9, 144, -1, 72, 132, -7, -5, -1, 114, -1, 70, 100, 40, -1, 130, 24, -41, -27, -11, -5, -3, -1, 55, 39, 23, -1, 113, -1, 85, 7, -7, -3, -1, 112, 54, -1, 99, 69, -3, -1, 84, 38, -1, 98, 53, -5, -1, 129, -1, 8, 128, -3, -1, 22, 97, -1, 6, 96, -13, -9, -5, -3, -1, 83, 68, 37, -1, 82, 5, -1, 21, 81, -7, -3, -1, 52, 67, -1, 80, 36, -3, -1, 66, 51, 20, -19, -11, -5, -1, 65, -1, 4, 64, -3, -1, 35, 50, 19, -3, -1, 49, 3, -1, 48, 34, -3, -1, 18, 33, -1, 2, 32, -3, -1, 17, 1, 16, 0 }; static int16_t tab15[] = { -495, -445, -355, -263, -183, -115, -77, -43, -27, -13, -7, -3, -1, 255, 239, -1, 254, 223, -1, 238, -1, 253, 207, -7, -3, -1, 252, 222, -1, 237, 191, -1, 251, -1, 206, 236, -7, -3, -1, 221, 175, -1, 250, 190, -3, -1, 235, 205, -1, 220, 159, -15, -7, -3, -1, 249, 234, -1, 189, 219, -3, -1, 143, 248, -1, 204, 158, -7, -3, -1, 233, 127, -1, 247, 173, -3, -1, 218, 188, -1, 111, -1, 174, 15, -19, -11, -3, -1, 203, 246, -3, -1, 142, 232, -1, 95, 157, -3, -1, 245, 126, -1, 231, 172, -9, -3, -1, 202, 187, -3, -1, 217, 141, 79, -3, -1, 244, 63, -1, 243, 216, -33, -17, -9, -3, -1, 230, 47, -1, 242, -1, 110, 240, -3, -1, 31, 241, -1, 156, 201, -7, -3, -1, 94, 171, -1, 186, 229, -3, -1, 125, 215, -1, 78, 228, -15, -7, -3, -1, 140, 200, -1, 62, 109, -3, -1, 214, 227, -1, 155, 185, -7, -3, -1, 46, 170, -1, 226, 30, -5, -1, 225, -1, 14, 224, -1, 93, 213, -45, -25, -13, -7, -3, -1, 124, 199, -1, 77, 139, -1, 212, -1, 184, 154, -7, -3, -1, 169, 108, -1, 198, 61, -1, 211, 210, -9, -5, -3, -1, 45, 13, 29, -1, 123, 183, -5, -1, 209, -1, 92, 208, -1, 197, 138, -17, -7, -3, -1, 168, 76, -1, 196, 107, -5, -1, 182, -1, 153, 12, -1, 60, 195, -9, -3, -1, 122, 167, -1, 166, -1, 192, 11, -1, 194, -1, 44, 91, -55, -29, -15, -7, -3, -1, 181, 28, -1, 137, 152, -3, -1, 193, 75, -1, 180, 106, -5, -3, -1, 59, 121, 179, -3, -1, 151, 136, -1, 43, 90, -11, -5, -1, 178, -1, 165, 27, -1, 177, -1, 176, 105, -7, -3, -1, 150, 74, -1, 164, 120, -3, -1, 135, 58, 163, -17, -7, -3, -1, 89, 149, -1, 42, 162, -3, -1, 26, 161, -3, -1, 10, 160, 104, -7, -3, -1, 134, 73, -1, 148, 57, -5, -1, 147, -1, 119, 9, -1, 88, 133, -53, -29, -13, -7, -3, -1, 41, 103, -1, 118, 146, -1, 145, -1, 25, 144, -7, -3, -1, 72, 132, -1, 87, 117, -3, -1, 56, 131, -1, 102, 71, -7, -3, -1, 40, 130, -1, 24, 129, -7, -3, -1, 116, 8, -1, 128, 86, -3, -1, 101, 55, -1, 115, 70, -17, -7, -3, -1, 39, 114, -1, 100, 23, -3, -1, 85, 113, -3, -1, 7, 112, 54, -7, -3, -1, 99, 69, -1, 84, 38, -3, -1, 98, 22, -3, -1, 6, 96, 53, -33, -19, -9, -5, -1, 97, -1, 83, 68, -1, 37, 82, -3, -1, 21, 81, -3, -1, 5, 80, 52, -7, -3, -1, 67, 36, -1, 66, 51, -1, 65, -1, 20, 4, -9, -3, -1, 35, 50, -3, -1, 64, 3, 19, -3, -1, 49, 48, 34, -9, -7, -3, -1, 18, 33, -1, 2, 32, 17, -3, -1, 1, 16, 0 }; static int16_t tab16[] = { -509, -503, -461, -323, -103, -37, -27, -15, -7, -3, -1, 239, 254, -1, 223, 253, -3, -1, 207, 252, -1, 191, 251, -5, -1, 175, -1, 250, 159, -3, -1, 249, 248, 143, -7, -3, -1, 127, 247, -1, 111, 246, 255, -9, -5, -3, -1, 95, 245, 79, -1, 244, 243, -53, -1, 240, -1, 63, -29, -19, -13, -7, -5, -1, 206, -1, 236, 221, 222, -1, 233, -1, 234, 217, -1, 238, -1, 237, 235, -3, -1, 190, 205, -3, -1, 220, 219, 174, -11, -5, -1, 204, -1, 173, 218, -3, -1, 126, 172, 202, -5, -3, -1, 201, 125, 94, 189, 242, -93, -5, -3, -1, 47, 15, 31, -1, 241, -49, -25, -13, -5, -1, 158, -1, 188, 203, -3, -1, 142, 232, -1, 157, 231, -7, -3, -1, 187, 141, -1, 216, 110, -1, 230, 156, -13, -7, -3, -1, 171, 186, -1, 229, 215, -1, 78, -1, 228, 140, -3, -1, 200, 62, -1, 109, -1, 214, 155, -19, -11, -5, -3, -1, 185, 170, 225, -1, 212, -1, 184, 169, -5, -1, 123, -1, 183, 208, 227, -7, -3, -1, 14, 224, -1, 93, 213, -3, -1, 124, 199, -1, 77, 139, -75, -45, -27, -13, -7, -3, -1, 154, 108, -1, 198, 61, -3, -1, 92, 197, 13, -7, -3, -1, 138, 168, -1, 153, 76, -3, -1, 182, 122, 60, -11, -5, -3, -1, 91, 137, 28, -1, 192, -1, 152, 121, -1, 226, -1, 46, 30, -15, -7, -3, -1, 211, 45, -1, 210, 209, -5, -1, 59, -1, 151, 136, 29, -7, -3, -1, 196, 107, -1, 195, 167, -1, 44, -1, 194, 181, -23, -13, -7, -3, -1, 193, 12, -1, 75, 180, -3, -1, 106, 166, 179, -5, -3, -1, 90, 165, 43, -1, 178, 27, -13, -5, -1, 177, -1, 11, 176, -3, -1, 105, 150, -1, 74, 164, -5, -3, -1, 120, 135, 163, -3, -1, 58, 89, 42, -97, -57, -33, -19, -11, -5, -3, -1, 149, 104, 161, -3, -1, 134, 119, 148, -5, -3, -1, 73, 87, 103, 162, -5, -1, 26, -1, 10, 160, -3, -1, 57, 147, -1, 88, 133, -9, -3, -1, 41, 146, -3, -1, 118, 9, 25, -5, -1, 145, -1, 144, 72, -3, -1, 132, 117, -1, 56, 131, -21, -11, -5, -3, -1, 102, 40, 130, -3, -1, 71, 116, 24, -3, -1, 129, 128, -3, -1, 8, 86, 55, -9, -5, -1, 115, -1, 101, 70, -1, 39, 114, -5, -3, -1, 100, 85, 7, 23, -23, -13, -5, -1, 113, -1, 112, 54, -3, -1, 99, 69, -1, 84, 38, -3, -1, 98, 22, -1, 97, -1, 6, 96, -9, -5, -1, 83, -1, 53, 68, -1, 37, 82, -1, 81, -1, 21, 5, -33, -23, -13, -7, -3, -1, 52, 67, -1, 80, 36, -3, -1, 66, 51, 20, -5, -1, 65, -1, 4, 64, -1, 35, 50, -3, -1, 19, 49, -3, -1, 3, 48, 34, -3, -1, 18, 33, -1, 2, 32, -3, -1, 17, 1, 16, 0 }; static int16_t tab24[] = { -451, -117, -43, -25, -15, -7, -3, -1, 239, 254, -1, 223, 253, -3, -1, 207, 252, -1, 191, 251, -5, -1, 250, -1, 175, 159, -1, 249, 248, -9, -5, -3, -1, 143, 127, 247, -1, 111, 246, -3, -1, 95, 245, -1, 79, 244, -71, -7, -3, -1, 63, 243, -1, 47, 242, -5, -1, 241, -1, 31, 240, -25, -9, -1, 15, -3, -1, 238, 222, -1, 237, 206, -7, -3, -1, 236, 221, -1, 190, 235, -3, -1, 205, 220, -1, 174, 234, -15, -7, -3, -1, 189, 219, -1, 204, 158, -3, -1, 233, 173, -1, 218, 188, -7, -3, -1, 203, 142, -1, 232, 157, -3, -1, 217, 126, -1, 231, 172, 255, -235, -143, -77, -45, -25, -15, -7, -3, -1, 202, 187, -1, 141, 216, -5, -3, -1, 14, 224, 13, 230, -5, -3, -1, 110, 156, 201, -1, 94, 186, -9, -5, -1, 229, -1, 171, 125, -1, 215, 228, -3, -1, 140, 200, -3, -1, 78, 46, 62, -15, -7, -3, -1, 109, 214, -1, 227, 155, -3, -1, 185, 170, -1, 226, 30, -7, -3, -1, 225, 93, -1, 213, 124, -3, -1, 199, 77, -1, 139, 184, -31, -15, -7, -3, -1, 212, 154, -1, 169, 108, -3, -1, 198, 61, -1, 211, 45, -7, -3, -1, 210, 29, -1, 123, 183, -3, -1, 209, 92, -1, 197, 138, -17, -7, -3, -1, 168, 153, -1, 76, 196, -3, -1, 107, 182, -3, -1, 208, 12, 60, -7, -3, -1, 195, 122, -1, 167, 44, -3, -1, 194, 91, -1, 181, 28, -57, -35, -19, -7, -3, -1, 137, 152, -1, 193, 75, -5, -3, -1, 192, 11, 59, -3, -1, 176, 10, 26, -5, -1, 180, -1, 106, 166, -3, -1, 121, 151, -3, -1, 160, 9, 144, -9, -3, -1, 179, 136, -3, -1, 43, 90, 178, -7, -3, -1, 165, 27, -1, 177, 105, -1, 150, 164, -17, -9, -5, -3, -1, 74, 120, 135, -1, 58, 163, -3, -1, 89, 149, -1, 42, 162, -7, -3, -1, 161, 104, -1, 134, 119, -3, -1, 73, 148, -1, 57, 147, -63, -31, -15, -7, -3, -1, 88, 133, -1, 41, 103, -3, -1, 118, 146, -1, 25, 145, -7, -3, -1, 72, 132, -1, 87, 117, -3, -1, 56, 131, -1, 102, 40, -17, -7, -3, -1, 130, 24, -1, 71, 116, -5, -1, 129, -1, 8, 128, -1, 86, 101, -7, -5, -1, 23, -1, 7, 112, 115, -3, -1, 55, 39, 114, -15, -7, -3, -1, 70, 100, -1, 85, 113, -3, -1, 54, 99, -1, 69, 84, -7, -3, -1, 38, 98, -1, 22, 97, -5, -3, -1, 6, 96, 53, -1, 83, 68, -51, -37, -23, -15, -9, -3, -1, 37, 82, -1, 21, -1, 5, 80, -1, 81, -1, 52, 67, -3, -1, 36, 66, -1, 51, 20, -9, -5, -1, 65, -1, 4, 64, -1, 35, 50, -1, 19, 49, -7, -5, -3, -1, 3, 48, 34, 18, -1, 33, -1, 2, 32, -3, -1, 17, 1, -1, 16, 0 }; static int16_t tab_c0[] = { -29, -21, -13, -7, -3, -1, 11, 15, -1, 13, 14, -3, -1, 7, 5, 9, -3, -1, 6, 3, -1, 10, 12, -3, -1, 2, 1, -1, 4, 8, 0 }; static int16_t tab_c1[] = { -15, -7, -3, -1, 15, 14, -1, 13, 12, -3, -1, 11, 10, -1, 9, 8, -7, -3, -1, 7, 6, -1, 5, 4, -3, -1, 3, 2, -1, 1, 0 }; newhuff_t hufft[] = { { 0, tab0 }, { 0, tab1 }, { 0, tab2 }, { 0, tab3 }, { 0, tab0 }, { 0, tab5 }, { 0, tab6 }, { 0, tab7 }, { 0, tab8 }, { 0, tab9 }, { 0, tab10 }, { 0, tab11 }, { 0, tab12 }, { 0, tab13 }, { 0, tab0 }, { 0, tab15 }, { 1, tab16 }, { 2, tab16 }, { 3, tab16 }, { 4, tab16 }, { 6, tab16 }, { 8, tab16 }, { 10, tab16 }, { 13, tab16 }, { 4, tab24 }, { 5, tab24 }, { 6, tab24 }, { 7, tab24 }, { 8, tab24 }, { 9, tab24 }, { 11, tab24 }, { 13, tab24 } }; newhuff_t hufftc[] = { { 0, tab_c0 }, { 0, tab_c1 } }; static int32_t intwinbase[] = { 0, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -3, -3, -4, -4, -5, -5, -6, -7, -7, -8, -9, -10, -11, -13, -14, -16, -17, -19, -21, -24, -26, -29, -31, -35, -38, -41, -45, -49, -53, -58, -63, -68, -73, -79, -85, -91, -97, -104, -111, -117, -125, -132, -139, -147, -154, -161, -169, -176, -183, -190, -196, -202, -208, -213, -218, -222, -225, -227, -228, -228, -227, -224, -221, -215, -208, -200, -189, -177, -163, -146, -127, -106, -83, -57, -29, 2, 36, 72, 111, 153, 197, 244, 294, 347, 401, 459, 519, 581, 645, 711, 779, 848, 919, 991, 1064, 1137, 1210, 1283, 1356, 1428, 1498, 1567, 1634, 1698, 1759, 1817, 1870, 1919, 1962, 2001, 2032, 2057, 2075, 2085, 2087, 2080, 2063, 2037, 2000, 1952, 1893, 1822, 1739, 1644, 1535, 1414, 1280, 1131, 970, 794, 605, 402, 185, -45, -288, -545, -814, -1095, -1388, -1692, -2006, -2330, -2663, -3004, -3351, -3705, -4063, -4425, -4788, -5153, -5517, -5879, -6237, -6589, -6935, -7271, -7597, -7910, -8209, -8491, -8755, -8998, -9219, -9416, -9585, -9727, -9838, -9916, -9959, -9966, -9935, -9863, -9750, -9592, -9389, -9139, -8840, -8492, -8092, -7640, -7134, -6574, -5959, -5288, -4561, -3776, -2935, -2037, -1082, -70, 998, 2122, 3300, 4533, 5818, 7154, 8540, 9975, 11455, 12980, 14548, 16155, 17799, 19478, 21189, 22929, 24694, 26482, 28289, 30112, 31947, 33791, 35640, 37489, 39336, 41176, 43006, 44821, 46617, 48390, 50137, 51853, 53534, 55178, 56778, 58333, 59838, 61289, 62684, 64019, 65290, 66494, 67629, 68692, 69679, 70590, 71420, 72169, 72835, 73415, 73908, 74313, 74630, 74856, 74992, 75038 }; static void make_synth_window(mpadec_t mpadec, MYFLT scale) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; register int i, j, k; scale = -scale; for (i = 0, j = 0, k = 0; i < 256; i++, j++, k += 32) { if (k < (512 + 16)) mpa->tables.decwin[k] = mpa->tables.decwin[k + 16] = ((MYFLT)intwinbase[j]/65536.0)*scale; if ((i & 31) == 31) k -= 1023; if ((i & 63) == 63) scale = -scale; } for (; i < 512; i++, j--, k += 32) { if (k < (512 + 16)) mpa->tables.decwin[k] = mpa->tables.decwin[k + 16] = ((MYFLT)intwinbase[j]/65536.0)*scale; if ((i & 31) == 31) k -= 1023; if ((i & 63) == 63) scale = -scale; } } static void init_limits(mpadec_t mpadec, int32_t sblimit) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; register int i, j; for (i = 0; i < 9; i++) { for (j = 0; j < 23; j++) { mpa->tables.long_limit[i][j] = (band_info[i].long_idx[j] + 7)/SSLIMIT + 1; if (mpa->tables.long_limit[i][j] > sblimit) mpa->tables.long_limit[i][j] = sblimit; } for (j = 0; j < 14; j++) { mpa->tables.short_limit[i][j] = (band_info[i].short_idx[j] - 1)/SSLIMIT + 1; if (mpa->tables.short_limit[i][j] > sblimit) mpa->tables.short_limit[i][j] = sblimit; } } } static void init_layer2(mpadec_t mpadec) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; int i, j, k; uint8_t *tab; static MYFLT mulmul[27] = { 0.0, -2.0/3.0, 2.0/3.0, 2.0/7.0, 2.0/15.0, 2.0/31.0, 2.0/63.0, 2.0/127.0, 2.0/255.0, 2.0/511.0, 2.0/1023.0, 2.0/2047.0, 2.0/4095.0, 2.0/8191.0, 2.0/16383.0, 2.0/32767.0, 2.0/65535.0, -4.0/5.0, -2.0/5.0, 2.0/5.0, 4.0/5.0, -8.0/9.0, -4.0/9.0, -2.0/9.0, 2.0/9.0, 4.0/9.0, 8.0/9.0 }; static uint8_t base[3][9] = { { 1, 0, 2, }, { 17, 18, 0, 19, 20, }, { 21, 1, 22, 23, 0, 24, 25, 2, 26 } }; tab = mpa->tables.grp3tab; for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) for (k = 0; k < 3; k++, tab += 3) { tab[0] = base[0][k]; tab[1] = base[0][j]; tab[2] = base[0][i]; } tab = mpa->tables.grp5tab; for (i = 0; i < 5; i++) for (j = 0; j < 5; j++) for (k = 0; k < 5; k++, tab += 3) { tab[0] = base[1][k]; tab[1] = base[1][j]; tab[2] = base[1][i]; } tab = mpa->tables.grp9tab; for (i = 0; i < 9; i++) for (j = 0; j < 9; j++) for (k = 0; k < 9; k++, tab += 3) { tab[0] = base[2][k]; tab[1] = base[2][j]; tab[2] = base[2][i]; } mpa->tables.mp2tables[0] = mpa->tables.mp2tables[1] = mpa->tables.mp2tables[2] = NULL; mpa->tables.mp2tables[3] = mpa->tables.grp3tab; mpa->tables.mp2tables[4] = NULL; mpa->tables.mp2tables[5] = mpa->tables.grp5tab; mpa->tables.mp2tables[6] = mpa->tables.mp2tables[7] = mpa->tables.mp2tables[8] = NULL; mpa->tables.mp2tables[9] = mpa->tables.grp9tab; for (i = 0; i < 27; i++) { for (j = 0, k = 3; j < 63; j++, k--) mpa->tables.muls[i][j] = mulmul[i]*pow(2.0, (MYFLT)k/3.0); mpa->tables.muls[i][63] = 0.0; } } static void init_layer3(mpadec_t mpadec) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; int i, j, k, l; for (i = -256; i < 122; i++) mpa->tables.gainpow2[i + 256] = pow(2.0, -0.25*(i + 210)); for (i = 0; i < 8207; i++) mpa->tables.ispow[i] = pow(i, 4.0/3.0); for (i = 0; i < 18; i++) { mpa->tables.win[0][0][i] = mpa->tables.win[0][1][i] = 0.5*sin((2*i + 1)*M_PI/72.0)/cos((2*i + 19)*M_PI/72.0); mpa->tables.win[0][0][i + 18] = mpa->tables.win[0][3][i + 18] = 0.5*sin((2*(i + 18) + 1)*M_PI/72.0)/cos((2*(i + 18) + 19)*M_PI/72.0); } for (i = 0; i < 6; i++) { mpa->tables.win[0][1][i + 18] = 0.5/cos((2*(i + 18) + 19)*M_PI/72.0); mpa->tables.win[0][3][i + 12] = 0.5/cos((2*(i + 12) + 19)*M_PI/72.0); mpa->tables.win[0][1][i + 24] = 0.5*sin((2*i + 13)*M_PI/24.0)/cos((2*(i + 24) + 19)*M_PI/72.0); mpa->tables.win[0][1][i + 30] = mpa->tables.win[0][3][i] = 0.0; mpa->tables.win[0][3][i + 6] = 0.5*sin((2*i + 1)*M_PI/24.0)/cos((2*(i + 6) + 19)*M_PI/72.0); } for (i = 0; i < 12; i++) { mpa->tables.win[0][2][i] = 0.5*sin((2*i + 1)*M_PI/24.0)/cos((2*i + 7)*M_PI/24.0); } for (i = 0; i < 4; i++) { int len = (i == 2) ? 12 : 36; for (j = 0; j < len; j += 2) { mpa->tables.win[1][i][j] = mpa->tables.win[0][i][j]; mpa->tables.win[1][i][j + 1] = -mpa->tables.win[0][i][j + 1]; } } for (i = 0; i < 16; i++) { MYFLT tmp = tan(i*M_PI/12.0); mpa->tables.tan1_1[i] = tmp/(1.0 + tmp); mpa->tables.tan2_1[i] = 1.0/(1.0 + tmp); mpa->tables.tan1_2[i] = M_SQRT2*tmp/(1.0 + tmp); mpa->tables.tan2_2[i] = M_SQRT2/(1.0 + tmp); for (j = 0; j < 2; j++) { MYFLT base = pow(2.0, -0.25*(j + 1)); MYFLT p1 = 1.0, p2 = 1.0; if (i > 0) { if (i & 1) p1 = pow(base, 0.5*(i + 1)); else p2 = pow(base, 0.5*i); } mpa->tables.pow1_1[j][i] = p1; mpa->tables.pow2_1[j][i] = p2; mpa->tables.pow1_2[j][i] = M_SQRT2*p1; mpa->tables.pow2_2[j][i] = M_SQRT2*p2; } } mpa->tables.istabs[0][0][0] = mpa->tables.tan1_1; mpa->tables.istabs[0][0][1] = mpa->tables.tan2_1; mpa->tables.istabs[0][1][0] = mpa->tables.tan1_2; mpa->tables.istabs[0][1][1] = mpa->tables.tan2_2; mpa->tables.istabs[1][0][0] = mpa->tables.pow1_1[0]; mpa->tables.istabs[1][0][1] = mpa->tables.pow2_1[0]; mpa->tables.istabs[1][1][0] = mpa->tables.pow1_2[0]; mpa->tables.istabs[1][1][1] = mpa->tables.pow2_2[0]; mpa->tables.istabs[2][0][0] = mpa->tables.pow1_1[1]; mpa->tables.istabs[2][0][1] = mpa->tables.pow2_1[1]; mpa->tables.istabs[2][1][0] = mpa->tables.pow1_2[1]; mpa->tables.istabs[2][1][1] = mpa->tables.pow2_2[1]; for (i = 0; i < 9; i++) { bandinfo_t *bi = &band_info[i]; int32_t *mp, cb, lwin; int16_t *bdf; mp = mpa->tables.map[i][0] = mpa->tables.mapbuf0[i]; bdf = bi->long_diff; for (cb = 0, j = 0; cb < 8; cb++, j += *bdf++, mp += 4) { mp[0] = (*bdf) >> 1; mp[1] = j; mp[2] = 3; mp[3] = cb; } bdf = bi->short_diff + 3; for (cb = 3; cb < 13; cb++) { int l = (*bdf++) >> 1; for (lwin = 0; lwin < 3; lwin++, mp += 4) { mp[0] = l; mp[1] = j + lwin; mp[2] = lwin; mp[3] = cb; } j += 6*l; } mpa->tables.mapend[i][0] = mp; mp = mpa->tables.map[i][1] = mpa->tables.mapbuf1[i]; bdf = bi->short_diff; for (cb = 0, j = 0; cb < 13; cb++) { int l = (*bdf++) >> 1; for (lwin = 0; lwin < 3; lwin++, mp += 4) { mp[0] = l; mp[1] = j + lwin; mp[2] = lwin; mp[3] = cb; } j += 6*l; } mpa->tables.mapend[i][1] = mp; mp = mpa->tables.map[i][2] = mpa->tables.mapbuf2[i]; bdf = bi->long_diff; for (cb = 0; cb < 22; cb++, mp += 2) { mp[0] = (*bdf++) >> 1; mp[1] = cb; } mpa->tables.mapend[i][2] = mp; } for (i = 0; i < 5; i++) { for (j = 0; j < 6; j++) { for (k = 0; k < 6; k++) { register int n = k + 6*j + 36*i; mpa->tables.i_slen2[n] = i | (j << 3) | (k << 6) | (3 << 12); } } } for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { for (k = 0; k < 4; k++) { register int n = k + 4*j + 16*i; mpa->tables.i_slen2[n + 180] = i | (j << 3) | (k << 6) | (4 << 12); } } } for (i = 0; i < 4; i++) { for (j = 0; j < 3; j++) { register int n = j + 3*i; mpa->tables.i_slen2[n + 244] = i | (j << 3) | (5 << 12); mpa->tables.n_slen2[n + 500] = i | (j << 3) | (2 << 12) | (1 << 15); } } for (i = 0; i < 5; i++) { for (j = 0; j < 5; j++) { for (k = 0; k < 4; k++) { for (l = 0; l < 4; l++) { register int n = l + 4*k + 16*j + 80*i; mpa->tables.n_slen2[n] = i | (j << 3) | (k << 6) | (l << 9); } } } } for (i = 0; i < 5; i++) { for (j = 0; j < 5; j++) { for (k = 0; k < 4; k++) { register int n = k + 4*j + 20*i; mpa->tables.n_slen2[n + 400] = i | (j << 3) | (k << 6) | (1 << 12); } } } } void init_tables(mpadec_t mpadec, MYFLT scale, int32_t sblimit) { register struct mpadec_t *mpa = (struct mpadec_t *)mpadec; if (mpa->state < MPADEC_STATE_START) { init_layer2(mpa); init_layer3(mpa); } init_limits(mpa, sblimit); make_synth_window(mpa, scale); } csound-6.10.0/InOut/libsnd.c000066400000000000000000001052321321653344700155610ustar00rootroot00000000000000/* sndlib.c: Copyright (C) 2004 John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* SNDLIB.C */ #include "soundio.h" #include #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef PIPES # if defined(SGI) || defined(LINUX) || defined(__BEOS__) || defined(NeXT) || \ defined(__MACH__) # define _popen popen # define _pclose pclose # endif extern FILE * _popen(const char *, const char *); extern int _pclose(FILE *); #endif static void sndwrterr(CSOUND *, int, int); static void sndfilein_noscale(CSOUND *csound); #define STA(x) (csound->libsndStatics.x) static inline void alloc_globals(CSOUND *csound) { csound->libsndStatics.nframes = (uint32)1; } /* The interface requires 2 functions: spoutran to transfer nspout items to buffer audtran to actually write the data spoutran is called with nchnls*ksamps items and this need to be buffered until outbufsiz items have been accumulated. It will call audtran to flush when this happens. */ static void spoutsf(CSOUND *csound) { uint32_t chn = 0; int n; int spoutrem = csound->nspout; MYFLT *sp = csound->spout; MYFLT absamp = FL(0.0); uint32 nframes = csound->libsndStatics.nframes; nchk: /* if nspout remaining > buf rem, prepare to send in parts */ if ((n = spoutrem) > (int) csound->libsndStatics.outbufrem) { n = (int) csound->libsndStatics.outbufrem; } spoutrem -= n; csound->libsndStatics.outbufrem -= n; do { absamp = *sp++; if (csound->libsndStatics.osfopen) { *csound->libsndStatics.outbufp++ = (absamp * csound->dbfs_to_float); } if (absamp < FL(0.0)) { absamp = -absamp; } if (absamp > csound->maxamp[chn]) { /* maxamp this seg */ csound->maxamp[chn] = absamp; csound->maxpos[chn] = nframes; } if (absamp > csound->e0dbfs) { /* out of range? */ csound->rngcnt[chn]++; /* report it */ csound->rngflg = 1; } if (csound->multichan) { if (++chn >= csound->nchnls) { chn = 0; nframes++; } } else { nframes++; } } while (--n); if (!csound->libsndStatics.outbufrem) { if (csound->libsndStatics.osfopen) { csound->nrecs++; csound->audtran(csound, csound->libsndStatics.outbuf, csound->libsndStatics.outbufsiz); /* Flush buffer */ csound->libsndStatics.outbufp = (MYFLT*) csound->libsndStatics.outbuf; } csound->libsndStatics.outbufrem = csound->oparms_.outbufsamps; if (spoutrem) { goto nchk; } } csound->libsndStatics.nframes = nframes; } /* special version of spoutsf for "raw" floating point files */ static void spoutsf_noscale(CSOUND *csound) { uint32_t chn = 0; int n, spoutrem = csound->nspout; MYFLT *sp = csound->spout; MYFLT absamp = FL(0.0); uint32 nframes = csound->libsndStatics.nframes; nchk: /* if nspout remaining > buf rem, prepare to send in parts */ if ((n = spoutrem) > (int) csound->libsndStatics.outbufrem) n = (int)csound->libsndStatics.outbufrem; spoutrem -= n; csound->libsndStatics.outbufrem -= n; do { absamp = *sp++; if (csound->libsndStatics.osfopen) *csound->libsndStatics.outbufp++ = absamp; if (absamp < FL(0.0)) absamp = -absamp; if (absamp > csound->maxamp[chn]) { /* maxamp this seg */ csound->maxamp[chn] = absamp; csound->maxpos[chn] = nframes; } if (++chn >= csound->nchnls) chn = 0, nframes++; } while (--n); if (!csound->libsndStatics.outbufrem) { if (csound->libsndStatics.osfopen) { csound->nrecs++; csound->audtran(csound, csound->libsndStatics.outbuf, csound->libsndStatics.outbufsiz); /* Flush buffer */ csound->libsndStatics.outbufp = (MYFLT*) csound->libsndStatics.outbuf; } csound->libsndStatics.outbufrem = csound->oparms_.outbufsamps; if (spoutrem) goto nchk; } csound->libsndStatics.nframes = nframes; } /* diskfile write option for audtran's */ /* assigned during sfopenout() */ static void writesf(CSOUND *csound, const MYFLT *outbuf, int nbytes) { OPARMS *O = csound->oparms; int n; if (UNLIKELY(STA(outfile) == NULL)) return; n = (int) sf_write_MYFLT(STA(outfile), (MYFLT*) outbuf, nbytes / sizeof(MYFLT)) * (int) sizeof(MYFLT); if (UNLIKELY(n < nbytes)) sndwrterr(csound, n, nbytes); if (UNLIKELY(O->rewrt_hdr)) rewriteheader((void *)STA(outfile)); switch (O->heartbeat) { case 1: csound->MessageS(csound, CSOUNDMSG_REALTIME, "%c\010", "|/-\\"[csound->nrecs & 3]); break; case 2: csound->MessageS(csound, CSOUNDMSG_REALTIME, "."); break; case 3: { char s[512]; CS_SPRINTF(s, "%ld(%.3f)%n", (long) csound->nrecs, csound->icurTime/csound->esr, &n); if (n > 0) { memset(&(s[n]), '\b', n); s[n + n] = '\0'; csound->MessageS(csound, CSOUNDMSG_REALTIME, "%s", s); } } break; case 4: csound->MessageS(csound, CSOUNDMSG_REALTIME, "%s", "\a"); break; } } static void writesf_dither_16(CSOUND *csound, const MYFLT *outbuf, int nbytes) { OPARMS *O = csound->oparms; int n; int m = nbytes / sizeof(MYFLT); MYFLT *buf = (MYFLT*) outbuf; int dith; if (UNLIKELY(STA(outfile) == NULL)) return; dith = STA(dither); for (n=0; n>1; /* triangular distribution */ result = (MYFLT) (rnd - 0x8000) / ((MYFLT) 0x10000); result /= ((MYFLT) 0x7fff); buf[n] += result; } STA(dither) = dith; n = (int) sf_write_MYFLT(STA(outfile), (MYFLT*) outbuf, nbytes / sizeof(MYFLT)) * (int) sizeof(MYFLT); if (UNLIKELY(n < nbytes)) sndwrterr(csound, n, nbytes); if (UNLIKELY(O->rewrt_hdr)) rewriteheader(STA(outfile)); switch (O->heartbeat) { case 1: csound->MessageS(csound, CSOUNDMSG_REALTIME, "%c\010", "|/-\\"[csound->nrecs & 3]); break; case 2: csound->MessageS(csound, CSOUNDMSG_REALTIME, "."); break; case 3: { char s[512]; CS_SPRINTF(s, "%ld(%.3f)%n", (long) csound->nrecs, csound->icurTime/csound->esr, &n); if (n > 0) { memset(&(s[n]), '\b', n); s[n + n] = '\0'; csound->MessageS(csound, CSOUNDMSG_REALTIME, "%s", s); } } break; case 4: csound->MessageS(csound, CSOUNDMSG_REALTIME, "\a"); break; } } static void writesf_dither_8(CSOUND *csound, const MYFLT *outbuf, int nbytes) { OPARMS *O = csound->oparms; int n; int m = nbytes / sizeof(MYFLT); MYFLT *buf = (MYFLT*) outbuf; int dith; if (UNLIKELY(STA(outfile) == NULL)) return; dith = STA(dither); for (n=0; n>1; /* triangular distribution */ result = (MYFLT) (rnd - 0x8000) / ((MYFLT) 0x10000); result /= ((MYFLT) 0x7f); buf[n] += result; } STA(dither) = dith; n = (int) sf_write_MYFLT(STA(outfile), (MYFLT*) outbuf, nbytes / sizeof(MYFLT)) * (int) sizeof(MYFLT); if (UNLIKELY(n < nbytes)) sndwrterr(csound, n, nbytes); if (UNLIKELY(O->rewrt_hdr)) rewriteheader(STA(outfile)); switch (O->heartbeat) { case 1: csound->MessageS(csound, CSOUNDMSG_REALTIME, "%c\010", "|/-\\"[csound->nrecs & 3]); break; case 2: csound->MessageS(csound, CSOUNDMSG_REALTIME, "."); break; case 3: { char s[512]; CS_SPRINTF(s, "%ld(%.3f)%n", (long) csound->nrecs, csound->icurTime/csound->esr, &n); if (n > 0) { memset(&(s[n]), '\b', n); s[n + n] = '\0'; csound->MessageS(csound, CSOUNDMSG_REALTIME, "%s", s); } } break; case 4: csound->MessageS(csound, CSOUNDMSG_REALTIME, "\a"); break; } } static void writesf_dither_u16(CSOUND *csound, const MYFLT *outbuf, int nbytes) { OPARMS *O = csound->oparms; int n; int m = nbytes / sizeof(MYFLT); MYFLT *buf = (MYFLT*) outbuf; int dith; if (UNLIKELY(STA(outfile) == NULL)) return; dith = STA(dither); for (n=0; nrewrt_hdr)) rewriteheader(STA(outfile)); switch (O->heartbeat) { case 1: csound->MessageS(csound, CSOUNDMSG_REALTIME, "%c\010", "|/-\\"[csound->nrecs & 3]); break; case 2: csound->MessageS(csound, CSOUNDMSG_REALTIME, "."); break; case 3: { char s[512]; CS_SPRINTF(s, "%ld(%.3f)%n", (long) csound->nrecs, csound->icurTime/csound->esr, &n); if (n > 0) { memset(&(s[n]), '\b', n); s[n + n] = '\0'; csound->MessageS(csound, CSOUNDMSG_REALTIME, "%s", s); } } break; case 4: csound->MessageS(csound, CSOUNDMSG_REALTIME, "%s", "\a"); break; } } static void writesf_dither_u8(CSOUND *csound, const MYFLT *outbuf, int nbytes) { OPARMS *O = csound->oparms; int n; int m = nbytes / sizeof(MYFLT); MYFLT *buf = (MYFLT*) outbuf; int dith; if (UNLIKELY(STA(outfile) == NULL)) return; dith = STA(dither); for (n=0; nrewrt_hdr)) rewriteheader(STA(outfile)); switch (O->heartbeat) { case 1: csound->MessageS(csound, CSOUNDMSG_REALTIME, "%c\010", "|/-\\"[csound->nrecs & 3]); break; case 2: csound->MessageS(csound, CSOUNDMSG_REALTIME, "."); break; case 3: { char s[512]; CS_SPRINTF(s, "%ld(%.3f)%n", (long) csound->nrecs, csound->icurTime/csound->esr, &n); if (n > 0) { memset(&(s[n]), '\b', n); s[n + n] = '\0'; csound->MessageS(csound, CSOUNDMSG_REALTIME, "%s", s); } } break; case 4: csound->MessageS(csound, CSOUNDMSG_REALTIME, "\a"); break; } } static int readsf(CSOUND *csound, MYFLT *inbuf, int inbufsize) { int i, n; (void) csound; n = inbufsize / (int) sizeof(MYFLT); i = (int) sf_read_MYFLT(STA(infile), inbuf, n); if (UNLIKELY(i < 0)) return inbufsize; memset(&inbuf[i], 0, (n-i)*sizeof(MYFLT)); return inbufsize; } /* Checks if the specified file name is a real-time audio device. */ /* Returns the device number (defaults to 1024) if it is, and -1 otherwise. */ /* If a device name is specified, and 'devName' is not NULL, a pointer to it */ /* is stored in *devName. */ /* Called from musmon, str_ops and here */ int check_rtaudio_name(char *fName, char **devName, int isOutput) { char *s; if (devName != NULL) *devName = (char*) NULL; if (fName == NULL) return -1; s = fName; if ((isOutput && strncmp(fName, "dac", 3) == 0) || (!isOutput && strncmp(fName, "adc", 3) == 0)) s += 3; else if (strncmp(fName, "devaudio", 8) == 0) s += 8; else return -1; if (*s == (char) '\0') return 1024; if (*s == (char) ':') { if (devName != NULL) { *devName = &(s[1]); } return 1024; } else { int devNum = 0; while (*s >= (char) '0' && *s <= (char) '9') { devNum = devNum * 10 + ((int) *s - (int) '0'); if (devNum >= 1024) break; if (*(++s) == (char) '\0') return devNum; } } return -1; } void sfopenin(CSOUND *csound) /* init for continuous soundin */ { OPARMS *O = csound->oparms; char *sfname, *fullName; SF_INFO sfinfo; int fileType = (int) TYP_RAW; int isfd = 0; /* stdin */ alloc_globals(csound); STA(inbufrem) = (uint32) 0; /* start with empty buffer */ sfname = O->infilename; if (UNLIKELY(sfname == NULL || sfname[0] == '\0')) csound->Die(csound, Str("error: no input file name")); if (strcmp(sfname, "stdin") == 0) { STA(pipdevin) = 1; } #ifdef PIPES else if (sfname[0] == '|') { STA(pin) = _popen(sfname + 1, "r"); isfd = fileno(STA(pin)); STA(pipdevin) = 1; } #endif else { csRtAudioParams parm; /* check for real time audio input, and get device name/number */ parm.devNum = check_rtaudio_name(sfname, &(parm.devName), 0); if (parm.devNum >= 0) { /* set device parameters */ parm.bufSamp_SW = (unsigned int) O->inbufsamps / (unsigned int) csound->inchnls; parm.bufSamp_HW = O->oMaxLag; parm.nChannels = csound->inchnls; parm.sampleFormat = O->informat; parm.sampleRate = (float) csound->esr; /* open devaudio for input */ if (UNLIKELY(csound->recopen_callback(csound, &parm) != 0)) csoundDie(csound, Str("Failed to initialise real time audio input")); /* & redirect audio gets */ csound->audrecv = csound->rtrecord_callback; STA(pipdevin) = 2; /* no backward seeks ! */ goto inset; /* no header processing */ } } /* open file */ memset(&sfinfo, 0, sizeof(SF_INFO)); if (STA(pipdevin)) { STA(infile) = sf_open_fd(isfd, SFM_READ, &sfinfo, 0); if (UNLIKELY(STA(infile) == NULL)) { /* open failed: possibly raw file, but cannot seek back to try again */ const char *sfError = sf_strerror(NULL); csoundDie(csound, Str("isfinit: cannot open %s -- %s"), sfname, sfError); } } else { fullName = csoundFindInputFile(csound, sfname, "SFDIR;SSDIR"); if (UNLIKELY(fullName == NULL)) /* if not found */ csoundDie(csound, Str("isfinit: cannot open %s"), sfname); STA(infile) = sf_open(fullName, SFM_READ, &sfinfo); if (STA(infile) == NULL) { /* open failed: maybe raw file ? */ memset(&sfinfo, 0, sizeof(SF_INFO)); sfinfo.samplerate = (int) (csound->esr + FL(0.5)); sfinfo.channels = csound->nchnls; /* FIXME: assumes input sample format is same as output */ sfinfo.format = TYPE2SF(TYP_RAW) | FORMAT2SF(O->outformat); STA(infile) = sf_open(fullName, SFM_READ, &sfinfo); /* try again */ } if (UNLIKELY(STA(infile) == NULL)) { const char *sfError = sf_strerror(NULL); csoundDie(csound, Str("isfinit: cannot open %s -- %s"), fullName, sfError); } /* only notify the host if we opened a real file, not stdin or a pipe */ csoundNotifyFileOpened(csound, fullName, sftype2csfiletype(sfinfo.format), 0, 0); sfname = fullName; } /* chk the hdr codes */ if (sfinfo.samplerate != (int) (csound->esr + FL(0.5))) { csound->Warning(csound, Str("audio_in %s has sr = %d, orch sr = %d"), sfname, (int) sfinfo.samplerate, (int) (csound->esr + FL(0.5))); } if (sfinfo.channels != csound->inchnls) { csound->Warning(csound, Str("audio_in %s has %d chnls, orch %d chnls_i"), sfname, (int) sfinfo.channels, csound->inchnls); } /* Do we care about the format? Can assume float?? */ O->informat = SF2FORMAT(sfinfo.format); fileType = (int) SF2TYPE(sfinfo.format); csound->audrecv = readsf; /* will use standard audio gets */ if ((O->informat == AE_FLOAT || O->informat == AE_DOUBLE) && !(fileType == TYP_WAV || fileType == TYP_AIFF || fileType == TYP_W64)) { /* do not scale "raw" floating point files */ csound->spinrecv = sndfilein_noscale; } inset: /* calc inbufsize reqd */ STA(inbufsiz) = (unsigned) (O->inbufsamps * sizeof(MYFLT)); STA(inbuf) = (MYFLT*) csound->Calloc(csound, STA(inbufsiz)); /* alloc inbuf space */ if (STA(pipdevout) == 2) csound->Message(csound, Str("reading %d sample blks of %lu-bit floats from %s \n"), O->inbufsamps * O->sfsampsize, sizeof(MYFLT)*8, sfname); else { csound->Message(csound, Str("reading %d-byte blks of %s from %s (%s)\n"), O->inbufsamps * (int) sfsampsize(FORMAT2SF(O->informat)), getstrformat(O->informat), sfname, type2string(fileType)); } STA(isfopen) = 1; } static char* copyrightcode(int n) { char* a[] = { "All Rights Reserved\n", "Creative Commons Attribution-NonCommercial-NoDerivatives\nCC BY-NC-ND\n)", "Creative Commons Attribution-NonCommercial-ShareAlike\nCC BY-NC-SA\n", "Creative Commons Attribution-NonCommercial\nCC BY-NC\n", "Creative Commons Attribution-NoDerivatives\nCC BY-ND\n", "Creative Commons Attribution-ShareAlike\nCC BY-SA\n", "Creative Commons Attribution\nCC BY\n", "Licenced under BSD\n" }; if (n>=8) n = 0; return a[n]; } void sfopenout(CSOUND *csound) /* init for sound out */ { /* (not called if nosound) */ OPARMS *O = csound->oparms; char *s, *fName, *fullName; SF_INFO sfinfo; int osfd = 1; /* stdout */ alloc_globals(csound); if (O->outfilename == NULL) { switch (O->filetyp) { case TYP_WAV: case TYP_W64: case TYP_WAVEX: case TYP_RF64: O->outfilename = "test.wav"; break; case TYP_AIFF: O->outfilename = "test.aif"; break; case TYP_AU: O->outfilename = "test.au"; break; case TYP_PAF: O->outfilename = "test.paf"; break; case TYP_SVX: O->outfilename = "test.svx"; break; case TYP_NIST: O->outfilename = "test.sph"; break; case TYP_VOC: O->outfilename = "test.voc"; break; /* case TYP_IRCAM: */ /* O->outfilename = ""; */ /* break; */ /* case TYP_MAT4: */ /* O->outfilename = ""; */ /* break; */ /* case TYP_MAT5: */ /* O->outfilename = ""; */ /* break; */ /* case TYP_PVF: */ /* O->outfilename = ""; */ /* break; */ case TYP_XI: O->outfilename = "test.xi"; break; /* case TYP_HTK: */ /* O->outfilename = ""; */ /* break; */ /* case TYP_SDS: */ /* O->outfilename = "test.sds"; */ /* break; */ case TYP_AVR: O->outfilename = "test.avr"; break; case TYP_SD2: O->outfilename = "test.sd2"; break; case TYP_FLAC: O->outfilename = "test.flac"; break; case TYP_CAF: O->outfilename = "test.caf"; break; case TYP_OGG: O->outfilename = "test.ogg"; break; /* case TYP_MPC2K: */ /* O->outfilename = ""; */ /* break; */ default: O->outfilename = "test"; break; } } STA(sfoutname) = fName = O->outfilename; if (strcmp(fName, "stdout") == 0) { STA(pipdevout) = 1; } #ifdef PIPES else if (fName[0] == '|') { STA(pout) = _popen(fName+1, "w"); osfd = fileno(STA(pout)); STA(pipdevout) = 1; if (O->filetyp == TYP_AIFF || O->filetyp == TYP_WAV) { char fmt_name[6]; if (O->sfsampsize == 8) { strcpy(fmt_name, "AU"); O->filetyp = TYP_AU; } else { strcpy(fmt_name, "IRCAM"); O->filetyp = TYP_IRCAM; } csound->Message(csound, Str("Output file type changed to %s " "for use in pipe\n"), fmt_name); } } #endif else { csRtAudioParams parm; /* check for real time audio output, and get device name/number */ parm.devNum = check_rtaudio_name(fName, &(parm.devName), 1); if (parm.devNum >= 0) { /* set device parameters */ parm.bufSamp_SW = (unsigned int) O->outbufsamps / csound->nchnls; parm.bufSamp_HW = O->oMaxLag; parm.nChannels = csound->nchnls; parm.sampleFormat = O->outformat; parm.sampleRate = (float) csound->esr; csound->spoutran = spoutsf; /* open devaudio for output */ if (UNLIKELY(csound->playopen_callback(csound, &parm) != 0)) csoundDie(csound, Str("Failed to initialise real time audio output")); /* & redirect audio puts */ csound->audtran = csound->rtplay_callback; STA(outbufrem) = parm.bufSamp_SW * parm.nChannels; STA(pipdevout) = 2; /* no backward seeks ! */ if (O->realtime == 1) /* set realtime priority mode */ csound->realtime_audio_flag = 1; goto outset; /* no header needed */ } else if (strcmp(fName, "null") == 0) { STA(outfile) = NULL; if (csound->dither_output && csound->oparms->outformat!=AE_FLOAT && csound->oparms->outformat!=AE_DOUBLE) { if (csound->oparms->outformat==AE_SHORT) if (csound->dither_output==1) csound->audtran = writesf_dither_16; else csound->audtran = writesf_dither_u16; else if (csound->oparms->outformat==AE_CHAR) if (csound->dither_output==1) csound->audtran = writesf_dither_8; else csound->audtran = writesf_dither_u8; else csound->audtran = writesf; } else csound->audtran = writesf; goto outset; } } /* set format parameters */ memset(&sfinfo, 0, sizeof(SF_INFO)); //sfinfo.frames = 0; sfinfo.samplerate = (int) (csound->esr + FL(0.5)); sfinfo.channels = csound->nchnls; sfinfo.format = TYPE2SF(O->filetyp) | FORMAT2SF(O->outformat); /* open file */ if (STA(pipdevout)) { STA(outfile) = sf_open_fd(osfd, SFM_WRITE, &sfinfo, 0); sf_command(STA(outfile), SFC_SET_VBR_ENCODING_QUALITY, &O->quality, sizeof(double)); #ifdef PIPES if (STA(outfile) == NULL) { char fmt_name[6]; if (O->sfsampsize == 8) { if (UNLIKELY(O->filetyp == TYP_AU)) csoundDie(csound, Str("sfinit: cannot open fd %d\n%s"), osfd, sf_strerror(NULL)); strcpy(fmt_name, "AU"); O->filetyp = TYP_AU; } else { if (UNLIKELY(O->filetyp == TYP_IRCAM)) csoundDie(csound, Str("sfinit: cannot open fd %d\n%s"), osfd, sf_strerror(NULL)); strcpy(fmt_name, "IRCAM"); O->filetyp = TYP_IRCAM; } csound->Message(csound, Str("Output file type changed to %s " "for use in pipe\n"), fmt_name); sfinfo.format = TYPE2SF(O->filetyp) | FORMAT2SF(O->outformat); STA(outfile) = sf_open_fd(osfd, SFM_WRITE, &sfinfo, 0); sf_command(STA(outfile), SFC_SET_VBR_ENCODING_QUALITY, &O->quality, sizeof(double)); } #endif if (UNLIKELY(STA(outfile) == NULL)) csoundDie(csound, Str("sfinit: cannot open fd %d\n%s"), osfd, sf_strerror(NULL)); } else { fullName = csoundFindOutputFile(csound, fName, "SFDIR"); if (UNLIKELY(fullName == NULL)) csoundDie(csound, Str("sfinit: cannot open %s"), fName); STA(sfoutname) = fullName; STA(outfile) = sf_open(fullName, SFM_WRITE, &sfinfo); if (UNLIKELY(STA(outfile) == NULL)) csoundDie(csound, Str("sfinit: cannot open %s\n%s"), fullName, sf_strerror (NULL)); sf_command(STA(outfile), SFC_SET_VBR_ENCODING_QUALITY, &O->quality, sizeof(double)); /* only notify the host if we opened a real file, not stdout or a pipe */ csoundNotifyFileOpened(csound, fullName, type2csfiletype(O->filetyp, O->outformat), 1, 0); } /* IV - Feb 22 2005: clip integer formats */ if (O->outformat != AE_FLOAT && O->outformat != AE_DOUBLE) sf_command(STA(outfile), SFC_SET_CLIPPING, NULL, SF_TRUE); sf_command(STA(outfile), SFC_SET_ADD_PEAK_CHUNK, NULL, (csound->peakchunks ? SF_TRUE : SF_FALSE)); #ifdef SOME_FINE_DAY if (csound->dither_output) { /* This may not be written yet!! */ SF_DITHER_INFO ditherInfo; memset(&ditherInfo, 0, sizeof(SF_DITHER_INFO)); ditherInfo.type = SFD_TRIANGULAR_PDF | SFD_DEFAULT_LEVEL; ditherInfo.level = 1.0; ditherInfo.name = (char*) NULL; sf_command(STA(outfile), SFC_SET_DITHER_ON_WRITE, &ditherInfo, sizeof(SF_DITHER_INFO)); } #endif if (!(O->outformat == AE_FLOAT || O->outformat == AE_DOUBLE) || (O->filetyp == TYP_WAV || O->filetyp == TYP_AIFF || O->filetyp == TYP_W64)) csound->spoutran = spoutsf; /* accumulate output */ else csound->spoutran = spoutsf_noscale; if (csound->dither_output && csound->oparms->outformat!=AE_FLOAT && csound->oparms->outformat!=AE_DOUBLE) { if (csound->oparms->outformat==AE_SHORT) csound->audtran = writesf_dither_16; else if (csound->oparms->outformat==AE_CHAR) csound->audtran = writesf_dither_8; else csound->audtran = writesf; } else csound->audtran = writesf; /* Write any tags. */ if ((s = csound->SF_id_title) != NULL && *s != '\0') sf_set_string(STA(outfile), SF_STR_TITLE, s); if ((s = csound->SF_csd_licence) == NULL || *s == '\0') s = csound->SF_id_copyright; if (s != NULL && *s != '\0') sf_set_string(STA(outfile), SF_STR_COPYRIGHT, s); else if (csound->SF_id_scopyright>=0) { char buff[256]; time_t tt = time(NULL); strftime(buff, 256, "Copyright %Y: ", gmtime(&tt)); strncat(buff,copyrightcode(csound->SF_id_scopyright), 255); buff[255] = '\0'; sf_set_string(STA(outfile), SF_STR_COPYRIGHT, buff); } if ((s = csound->SF_id_software) != NULL && *s != '\0') sf_set_string(STA(outfile), SF_STR_SOFTWARE, s); if ((s = csound->SF_id_artist) != NULL && *s != '\0') sf_set_string(STA(outfile), SF_STR_ARTIST, s); if ((s = csound->SF_id_comment) != NULL && *s != '\0') sf_set_string(STA(outfile), SF_STR_COMMENT, s); if ((s = csound->SF_id_date) != NULL && *s != '\0') sf_set_string(STA(outfile), SF_STR_DATE, s); /* file is now open */ STA(osfopen) = 1; outset: O->sfsampsize = (int) sfsampsize(FORMAT2SF(O->outformat)); /* calc outbuf size & alloc bufspace */ STA(outbufsiz) = O->outbufsamps * sizeof(MYFLT); STA(outbufp) = STA(outbuf) = csound->Malloc(csound, STA(outbufsiz)); if (STA(pipdevout) == 2) csound->Message(csound, Str("writing %d sample blks of %lu-bit floats to %s \n"), O->outbufsamps, sizeof(MYFLT)*8, STA(sfoutname)); else { csound->Message(csound, Str("writing %d-byte blks of %s to %s"), O->outbufsamps * O->sfsampsize, getstrformat(O->outformat), STA(sfoutname)); if (O->sfheader == 0) csound->Message(csound, Str(" (raw)\n")); else csound->Message(csound, " (%s)\n", type2string(O->filetyp)); } STA(osfopen) = 1; STA(outbufrem) = O->outbufsamps; } void sfclosein(CSOUND *csound) { alloc_globals(csound); if (!STA(isfopen)) return; if (STA(pipdevin) == 2 && (!STA(osfopen) || STA(pipdevout) != 2)) { /* close only if not open for output too */ csound->rtclose_callback(csound); } else if (STA(pipdevin) != 2) { if (STA(infile) != NULL) sf_close(STA(infile)); #ifdef PIPES if (STA(pin) != NULL) { _pclose(STA(pin)); STA(pin) = NULL; } #endif STA(infile) = NULL; } STA(isfopen) = 0; } void sfcloseout(CSOUND *csound) { OPARMS *O = csound->oparms; int nb; alloc_globals(csound); if (!STA(osfopen)) return; if ((nb = (O->outbufsamps - STA(outbufrem)) * sizeof(MYFLT)) > 0) { /* flush outbuffer */ csound->nrecs++; csound->audtran(csound, STA(outbuf), nb); } if (STA(pipdevout) == 2 && (!STA(isfopen) || STA(pipdevin) != 2)) { /* close only if not open for input too */ csound->rtclose_callback(csound); } if (STA(pipdevout) == 2) goto report; if (STA(outfile) != NULL) { if (!STA(pipdevout) && O->outformat != AE_VORBIS) sf_command(STA(outfile), SFC_UPDATE_HEADER_NOW, NULL, 0); sf_close(STA(outfile)); STA(outfile) = NULL; } #ifdef PIPES if (STA(pout) != NULL) { _pclose(STA(pout)); STA(pout) = NULL; } #endif report: if (STA(pipdevout) == 2) { csound->Message(csound, Str("%d %d sample blks of %lu-bit floats written to %s\n"), csound->nrecs, O->outbufsamps, sizeof(MYFLT)*8, STA(sfoutname)); } else { csound->Message(csound, Str("%d %d sample blks of %s written to %s"), O->outbufsamps, O->outbufsamps * O->sfsampsize, getstrformat(O->outformat), STA(sfoutname)); if (O->sfheader == 0) csound->Message(csound, Str(" (raw)\n")); else csound->Message(csound, " (%s)\n", type2string(O->filetyp)); } STA(osfopen) = 0; } /* report soundfile write(osfd) error */ /* called after chk of write() bytecnt */ static void sndwrterr(CSOUND *csound, int nret, int nput) { csound->ErrorMsg(csound, Str("soundfile write returned bytecount of %d, not %d"), nret, nput); csound->ErrorMsg(csound, Str("(disk may be full...\n closing the file ...)")); STA(outbufrem) = csound->oparms->outbufsamps; /* consider buf is flushed */ sfcloseout(csound); /* & try to close the file */ csound->Die(csound, Str("\t... closed\n")); } void sfnopenout(CSOUND *csound) { alloc_globals(csound); csound->Message(csound, Str("not writing to sound disk\n")); /* init counter, though not writing */ STA(outbufrem) = csound->oparms->outbufsamps; } static inline void sndfilein_(CSOUND *csound, MYFLT scaleFac) { OPARMS *O = csound->oparms; int i, n, nsmps, bufpos; nsmps = csound->nspin; bufpos = (int) O->inbufsamps - (int) STA(inbufrem); for (i = 0; iinbufsamps - (int) STA(inbufrem)) * (int) sizeof(MYFLT); n = csound->audrecv(csound, STA(inbuf) + (int) STA(inbufrem), n); STA(inbufrem) += (unsigned int) (n / (int) sizeof(MYFLT)); } while ((int) STA(inbufrem) < (int) O->inbufsamps); bufpos = 0; } csound->spin[i] = STA(inbuf)[bufpos++] * scaleFac; STA(inbufrem)--; } } static void sndfilein(CSOUND *csound) { sndfilein_(csound, csound->e0dbfs); } /* special version of sndfilein for "raw" floating point files */ static void sndfilein_noscale(CSOUND *csound) { sndfilein_(csound, FL(1.0)); } static int audrecv_dummy(CSOUND *csound, MYFLT *buf, int nbytes) { (void) csound; (void) buf; return nbytes; } static void audtran_dummy(CSOUND *csound, const MYFLT *buf, int nbytes) { (void) csound; (void) buf; (void) nbytes; } /* direct recv & tran calls to the right audio formatter */ /* & init its audio_io bufptr */ void iotranset(CSOUND *csound) { OPARMS *O; csound->spinrecv = sndfilein; csound->spoutran = spoutsf; if (!csound->enableHostImplementedAudioIO) return; alloc_globals(csound); O = csound->oparms; csound->audrecv = audrecv_dummy; csound->audtran = audtran_dummy; STA(inbufrem) = (unsigned int) O->inbufsamps; STA(outbufrem) = (unsigned int) O->outbufsamps; if (!csound->hostRequestedBufferSize) { O->sfread = 0; O->sfwrite = 0; STA(osfopen) = 0; return; } STA(inbufsiz) = (unsigned int) (O->inbufsamps * (int) sizeof(MYFLT)); STA(inbuf) = (MYFLT*) csound->Calloc(csound, STA(inbufsiz)); STA(outbufsiz) = (unsigned int) (O->outbufsamps * (int) sizeof(MYFLT)); STA(outbuf) = (MYFLT*) csound->Calloc(csound, STA(outbufsiz)); STA(outbufp) = STA(outbuf); O->sfread = 1; O->sfwrite = 1; STA(osfopen) = 1; } PUBLIC MYFLT *csoundGetInputBuffer(CSOUND *csound) { return STA(inbuf); } PUBLIC MYFLT *csoundGetOutputBuffer(CSOUND *csound) { return STA(outbuf); } csound-6.10.0/InOut/libsnd_u.c000066400000000000000000000357761321653344700161240ustar00rootroot00000000000000/* libsnd_u.c: This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "soundio.h" #include void rewriteheader(void *ofd) { if (LIKELY(ofd != NULL)) sf_command((SNDFILE *)ofd, SFC_UPDATE_HEADER_NOW, NULL, 0); } /* Stand-Alone sndgetset() */ /* used by SoundAnal progs */ /* Returns NULL on failure */ void *SAsndgetset(CSOUND *csound, char *infilnam, void *ap_, MYFLT *abeg_time, MYFLT *ainput_dur, MYFLT *asr, int channel) { SOUNDIN **ap = (SOUNDIN**) ap_; SOUNDIN *p; SNDFILE *infile = NULL; csound->esr = FL(0.0); /* set esr 0. with no orchestra */ *ap = p = (SOUNDIN*) csound->Calloc(csound, sizeof(SOUNDIN)); strncpy(p->sfname, infilnam, 511); p->sfname[511] = '\0'; if (UNLIKELY(channel < 1 && channel != ALLCHNLS)) { csound->Message(csound, Str("channel request %d illegal\n"), channel); csound->Free(csound, p); *ap = NULL; return NULL; } p->channel = channel; p->analonly = 1; p->sr = (int) (*asr + FL(0.5)); p->skiptime = *abeg_time; if ((infile = sndgetset(csound, p)) == NULL) /* open sndfil, do skiptime */ return(NULL); if (UNLIKELY(p->framesrem < (int64_t) 0)) { csound->Warning(csound, Str("undetermined file length, " "will attempt requested duration")); } else { if (*ainput_dur <= FL(0.0)) { /* 0 durtim, use to EOF */ p->getframes = p->framesrem; *ainput_dur = (MYFLT) ((double) p->getframes / (double) p->sr); } /* else chk that input dur is within filetime rem */ else { p->getframes = (int64_t) ((double) p->sr * (double) *ainput_dur + 0.5); if (UNLIKELY(p->getframes > p->framesrem)) { p->getframes = p->framesrem; csound->Warning(csound, Str("full requested duration not available")); } } csound->Message(csound, Str("analysing %ld sample frames (%3.1f secs)"), (long) p->getframes, *ainput_dur); if (*abeg_time != FL(0.0)) csound->Message(csound, Str(" from timepoint %3.1f\n"), *abeg_time); else csound->Message(csound, "\n"); } return (void*) infile; } /* special handling of sound input to accomodate reads thru pipes & net * where nbytes rcvd can be < n requested * * extra arg passed for filetyp testing on POST-HEADER reads of audio samples */ static int sreadin(CSOUND *csound, SNDFILE *infd, MYFLT *inbuf, int nsamples, SOUNDIN *p) { /* return the number of samples read */ int n, ntot = 0; do { n = sf_read_MYFLT(infd, inbuf + ntot, nsamples - ntot); if (UNLIKELY(n < 0)) csound->Die(csound, Str("soundfile read error")); } while (n > 0 && (ntot += n) < nsamples); if (p->audrem > (int64_t) 0) { if ((int64_t) ntot > p->audrem) /* chk haven't exceeded */ ntot = (int) p->audrem; /* limit of audio data */ p->audrem -= (int64_t) ntot; return ntot; } return 0; } /* core of soundinset */ /* called from sndinset, SAsndgetset, & gen01 */ /* Return NULL on failure */ void *sndgetset(CSOUND *csound, void *p_) { SOUNDIN *p = (SOUNDIN*) p_; int n; int framesinbuf, skipframes; char *sfname; SF_INFO sfinfo; sfname = &(p->sfname[0]); /* IV - Feb 26 2005: should initialise sfinfo structure */ memset(&sfinfo, 0, sizeof(SF_INFO)); sfinfo.format = (p->format ? /* store default sample format, */ ((int) FORMAT2SF(p->format) | SF_FORMAT_RAW) : 0); sfinfo.channels = 1; /* number of channels, */ if (p->analonly) /* and sample rate */ sfinfo.samplerate = (int) p->sr; else sfinfo.samplerate = (int) ((double) csound->esr + 0.5); if (sfinfo.samplerate < 1) sfinfo.samplerate = (int) ((double) DFLT_SR + 0.5); /* open with full dir paths */ p->fd = csound->FileOpen2(csound, &(p->sinfd), CSFILE_SND_R, sfname, &sfinfo, "SFDIR;SSDIR", CSFTYPE_UNKNOWN_AUDIO, 0); if (UNLIKELY(p->fd == NULL)) { csound->ErrorMsg(csound, Str("soundin cannot open %s"), sfname); goto err_return; } /* & record fullpath filnam */ sfname = csound->GetFileName(p->fd); /* copy type from headata */ p->format = SF2FORMAT(sfinfo.format); p->sampframsiz = (int) sfsampsize(sfinfo.format) * (int) sfinfo.channels; p->nchanls = sfinfo.channels; framesinbuf = (int) SNDINBUFSIZ / (int) p->nchanls; p->bufsmps = framesinbuf * p->nchanls; p->endfile = 0; p->filetyp = SF2TYPE(sfinfo.format); if (p->analonly) { /* anal: if sr param val */ if (p->sr != 0 && p->sr != sfinfo.samplerate) { /* use it */ csound->Warning(csound, Str("-s %d overriding soundfile sr %d"), (int) p->sr, (int) sfinfo.samplerate); sfinfo.samplerate = p->sr; } } else if (UNLIKELY(sfinfo.samplerate != (int) ((double) csound->esr + 0.5))) { csound->Warning(csound, /* non-anal: cmp w. esr */ "%s sr = %d, orch sr = %7.1f", sfname, (int) sfinfo.samplerate, csound->esr); } if (UNLIKELY(p->channel != ALLCHNLS && p->channel > sfinfo.channels)) { csound->ErrorMsg(csound, Str("error: req chan %d, file %s has only %d"), (int) p->channel, sfname, (int) sfinfo.channels); goto err_return; } p->sr = (int) sfinfo.samplerate; if (csound->oparms_.msglevel & 3) { csound->Message(csound, Str("audio sr = %d, "), (int) p->sr); switch (p->nchanls) { case 1: csound->Message(csound, Str("monaural")); break; case 2: csound->Message(csound, Str("stereo")); break; case 4: csound->Message(csound, Str("quad")); break; case 6: csound->Message(csound, Str("hex")); break; case 8: csound->Message(csound, Str("oct")); break; default: csound->Message(csound, Str("%d-channels"), (int) p->nchanls); } if (p->nchanls > 1) { if (p->channel == ALLCHNLS) csound->Message(csound, Str(", reading %s channels"), (p->nchanls == 2 ? Str("both") : Str("all"))); else csound->Message(csound, Str(", reading channel %d"), (int) p->channel); } csound->Message(csound, Str("\nopening %s infile %s\n"), type2string(p->filetyp), sfname); } p->audrem = (int64_t) sfinfo.frames * (int64_t) sfinfo.channels; p->framesrem = (int64_t) sfinfo.frames; /* find frames rem */ skipframes = (int) ((double) p->skiptime * (double) p->sr + (p->skiptime >= FL(0.0) ? 0.5 : -0.5)); if (skipframes < 0) { n = -skipframes; if (UNLIKELY(n > framesinbuf)) { csound->ErrorMsg(csound, Str("soundin: invalid skip time")); goto err_return; } n *= (int) sfinfo.channels; p->inbufp = &(p->inbuf[0]); p->bufend = p->inbufp; do { *(p->bufend++) = FL(0.0); } while (--n); } else if (skipframes < framesinbuf) { /* if sound within 1st buf */ n = sreadin(csound, p->sinfd, p->inbuf, p->bufsmps, p); p->bufend = &(p->inbuf[0]) + n; p->inbufp = &(p->inbuf[0]) + (skipframes * (int) sfinfo.channels); if (p->inbufp >= p->bufend) { p->inbufp = p->bufend; p->audrem = (int64_t) 0; p->endfile = 1; } } else if ((int64_t) skipframes >= p->framesrem) { n = framesinbuf * (int) sfinfo.channels; p->inbufp = &(p->inbuf[0]); p->bufend = p->inbufp; do { *(p->bufend++) = FL(0.0); } while (--n); p->audrem = (int64_t) 0; p->endfile = 1; } else { /* for greater skiptime: */ /* else seek to bndry */ if (UNLIKELY(sf_seek(p->sinfd, (sf_count_t) skipframes, SEEK_SET) < 0)) { csound->ErrorMsg(csound, Str("soundin seek error")); goto err_return; } /* now rd fulbuf */ if ((n = sreadin(csound, p->sinfd, p->inbuf, p->bufsmps, p)) == 0) p->endfile = 1; p->inbufp = p->inbuf; p->bufend = p->inbuf + n; } if (p->framesrem != (int64_t) -1) p->framesrem -= (int64_t) skipframes; /* sampleframes to EOF */ return p->sinfd; /* return the active fd */ err_return: if (p->fd != NULL) csound->FileClose(csound, p->fd); p->sinfd = NULL; p->fd = NULL; return NULL; } /* a simplified soundin */ int getsndin(CSOUND *csound, void *fd_, MYFLT *fp, int nlocs, void *p_) { SNDFILE *fd = (SNDFILE*) fd_; SOUNDIN *p = (SOUNDIN*) p_; int i = 0, n; MYFLT scalefac; if (p->format == AE_FLOAT || p->format == AE_DOUBLE) { if (p->filetyp == TYP_WAV || p->filetyp == TYP_AIFF || p->filetyp == TYP_W64) scalefac = csound->e0dbfs; else scalefac = FL(1.0); if (p->do_floatscaling) scalefac *= p->fscalefac; } else scalefac = csound->e0dbfs; if (p->nchanls == 1 || p->channel == ALLCHNLS) { /* MONO or ALLCHNLS */ for ( ; i < nlocs; i++) { if (p->inbufp >= p->bufend) { if ((n = sreadin(csound, fd, p->inbuf, p->bufsmps, p)) <= 0) break; p->inbufp = p->inbuf; p->bufend = p->inbuf + n; } fp[i] = *p->inbufp++ * scalefac; } } else { /* MULTI-CHANNEL, SELECT ONE */ int chcnt; for ( ; i < nlocs; i++) { if (p->inbufp >= p->bufend) { if ((n = sreadin(csound, fd, p->inbuf, p->bufsmps, p)) <= 0) break; p->inbufp = p->inbuf; p->bufend = p->inbuf + n; } chcnt = 0; do { if (++chcnt == p->channel) fp[i] = *p->inbufp * scalefac; p->inbufp++; } while (chcnt < p->nchanls); } } n = i; memset(&(fp[i]), 0, (nlocs-i)*sizeof(MYFLT)); /* if incomplete PAD */ /* for ( ; i < nlocs; i++) /\* if incomplete *\/ */ /* fp[i] = FL(0.0); /\* pad with 0's *\/ */ return n; } void dbfs_init(CSOUND *csound, MYFLT dbfs) { csound->dbfs_to_float = FL(1.0) / dbfs; csound->e0dbfs = dbfs; /* probably want this message written just before note messages start... */ csound->Message(csound, Str("0dBFS level = %.1f\n"), dbfs); } char *type2string(int x) { switch (x) { case TYP_WAV: return "WAV"; case TYP_AIFF: return "AIFF"; case TYP_AU: return "AU"; case TYP_RAW: return "RAW"; case TYP_PAF: return "PAF"; case TYP_SVX: return "SVX"; case TYP_NIST: return "NIST"; case TYP_VOC: return "VOC"; case TYP_IRCAM: return "IRCAM"; case TYP_W64: return "W64"; case TYP_MAT4: return "MAT4"; case TYP_MAT5: return "MAT5"; case TYP_PVF: return "PVF"; case TYP_XI: return "XI"; case TYP_HTK: return "HTK"; case TYP_SDS: return "SDS"; case TYP_SD2: return "SD2"; case TYP_FLAC: return "FLAC"; case TYP_CAF: return "CAF"; case TYP_WVE: return "WVE"; case TYP_OGG: return "OGG"; case TYP_MPC2K: return "MPC2K"; case TYP_RF64: return "RF64"; default: return Str("unknown"); } } int sfsampsize(int type) { switch (type & SF_FORMAT_SUBMASK) { case SF_FORMAT_PCM_16: return 2; /* Signed 16 bit data */ case SF_FORMAT_PCM_32: return 4; /* Signed 32 bit data */ case SF_FORMAT_FLOAT: return 4; /* 32 bit float data */ case SF_FORMAT_PCM_24: return 3; /* Signed 24 bit data */ case SF_FORMAT_DOUBLE: return 8; /* 64 bit float data */ } return 1; } char *getstrformat(int format) /* used here, and in sfheader.c */ { switch (format) { case AE_UNCH: return Str("unsigned bytes"); /* J. Mohr 1995 Oct 17 */ case AE_CHAR: return Str("signed chars"); case AE_ALAW: return Str("alaw bytes"); case AE_ULAW: return Str("ulaw bytes"); case AE_SHORT: return Str("shorts"); case AE_LONG: return Str("longs"); case AE_FLOAT: return Str("floats"); case AE_DOUBLE: return Str("double floats"); case AE_24INT: return Str("24bit ints"); /* RWD 5:2001 */ case AE_VORBIS: return Str("vorbis encoding"); } return Str("unknown"); } /* type should be one of Csound's TYP_XXX macros, encoding should be one of its AE_XXX macros. */ int type2csfiletype(int type, int encoding) { switch (type) { case TYP_RAW: return CSFTYPE_RAW_AUDIO; case TYP_IRCAM: return CSFTYPE_IRCAM; case TYP_AIFF: switch (encoding) { case AE_CHAR: case AE_SHORT: case AE_24INT: case AE_LONG: return CSFTYPE_AIFF; default: return CSFTYPE_AIFC; } case TYP_WAV: return CSFTYPE_WAVE; case TYP_AU: return CSFTYPE_AU; case TYP_W64: return CSFTYPE_W64; case TYP_WAVEX: return CSFTYPE_WAVEX; case TYP_AVR: return CSFTYPE_AVR; case TYP_HTK: return CSFTYPE_HTK; case TYP_MAT4: return CSFTYPE_MAT4; case TYP_MAT5: return CSFTYPE_MAT5; case TYP_NIST: return CSFTYPE_NIST; case TYP_PAF: return CSFTYPE_PAF; case TYP_PVF: return CSFTYPE_PVF; case TYP_SVX: return CSFTYPE_SVX; case TYP_VOC: return CSFTYPE_VOC; case TYP_XI: return CSFTYPE_XI; case TYP_SDS: return CSFTYPE_SDS; case TYP_SD2: return CSFTYPE_SD2; case TYP_FLAC: return CSFTYPE_FLAC; case TYP_CAF: return CSFTYPE_CAF; case TYP_WVE: return CSFTYPE_WVE; case TYP_OGG: return CSFTYPE_OGG; case TYP_MPC2K: return CSFTYPE_MPC2K; case TYP_RF64: return CSFTYPE_RF64; default: return CSFTYPE_UNKNOWN_AUDIO; } } /* type should be one of libsndfile's format values. */ int sftype2csfiletype(int type) { /* mask out the endian-ness bits */ int typemod = type & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK); return type2csfiletype(SF2TYPE(typemod), SF2FORMAT(typemod)); } csound-6.10.0/InOut/midifile.c000066400000000000000000000670021321653344700160720ustar00rootroot00000000000000/* midifile.c: Copyright (C) 2005 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "midifile.h" #include static const char *midiFile_ID = "MThd"; static const char *midiTrack_ID = "MTrk"; /* default tempo in beats per minute */ static const double default_tempo = 120.0; typedef struct tempoEvent_s { unsigned long kcnt; /* time (in ticks while reading */ /* MIDI file, will be converted */ /* to kperiods once file is read) */ double tempoVal; /* tempo value in beats per minute */ } tempoEvent_t; typedef struct midiEvent_s { unsigned long kcnt; /* time (in ticks while reading */ /* MIDI file, will be converted */ /* to kperiods once file is read) */ #if 0 unsigned char *data; /* pointer to sysex or meta event */ /* data (currently not used) */ #endif unsigned char st; /* status byte (0x80-0xFF) */ unsigned char d1; /* data byte 1 (0x00-0x7F) */ unsigned char d2; /* data byte 2 (0x00-0x7F) */ } midiEvent_t; typedef struct midiFile_s { /* static file data, not changed at performance */ double timeCode; /* > 0: ticks per beat */ /* < 0: ticks per second */ unsigned long totalKcnt; /* total duration of file */ /* (in ticks while reading file, */ /* converted to kperiods) */ int nEvents; /* number of events */ int maxEvents; /* event array size */ int nTempo; /* number of tempo changes */ int maxTempo; /* tempo change array size */ midiEvent_t *eventList; /* array of MIDI events */ tempoEvent_t *tempoList; /* array of tempo changes */ /* performance time state variables */ double currentTempo; /* current tempo in BPM */ int eventListIndex; /* index of next MIDI event in list */ int tempoListIndex; /* index of next tempo change */ } midiFile_t; #define MIDIFILE (csound->midiGlobals->midiFileData) #define MF(x) (((midiFile_t*) MIDIFILE)->x) static int getCh(CSOUND *csound, FILE *f, int *bytesLeft) { int c; if (f == NULL) return -1; c = getc(f); if (UNLIKELY(c == EOF)) { csound->Message(csound, Str(" *** unexpected end of MIDI file\n")); return -1; } if (bytesLeft != NULL) { if (UNLIKELY(--(*bytesLeft) < 0)) { csound->Message(csound, Str(" *** unexpected end of MIDI track\n")); return -1; } } return (c & 0xFF); } static int getVLenData(CSOUND *csound, FILE *f, int *bytesLeft) { int c, n, cnt; n = cnt = 0; do { if (UNLIKELY(++cnt > 4)) { csound->Message(csound, Str(" *** invalid dynamic length data in MIDI file\n")); return -1; } c = getCh(csound, f, bytesLeft); if (c < 0) return -1; n = (n << 7) | (c & 0x7F); } while (c & 0x80); return n; } /* return the number of bytes to read for status byte 'c' */ /* return value is 0, 1, 2, or -1 in the case of an unknown */ /* or special message */ static int msgDataBytes(int c) { switch (c & 0xF0) { case 0x80: /* note off */ case 0x90: /* note on */ case 0xA0: /* polyphonic pressure */ case 0xB0: /* control change */ case 0xE0: /* pitch bend */ return 2; case 0xC0: /* program change */ case 0xD0: /* channel pressure */ return 1; case 0xF0: switch (c) { case 0xF2: /* song position */ return 2; case 0xF1: /* MTC quarter frame */ case 0xF3: /* song select */ return 1; case 0xF0: /* system exclusive */ case 0xF7: /* escape sequence */ case 0xFF: /* meta event */ case 0xF4: /* unknown */ case 0xF5: /* unknown */ case 0xF9: /* unknown */ case 0xFD: /* unknown */ return -1; default: /* tune request, real time system messages */ return 0; } } /* anything else is unknown */ return -1; } static int alloc_event(CSOUND *csound, unsigned long kcnt, unsigned char *data, int st, int d1, int d2) { midiEvent_t *tmp; IGN(data); /* expand array if necessary */ if (MF(nEvents) >= MF(maxEvents)) { MF(maxEvents) += (MF(maxEvents) >> 3); MF(maxEvents) = (MF(maxEvents) + 64) & (~63); tmp = (midiEvent_t*) csound->ReAlloc(csound, MF(eventList), sizeof(midiEvent_t) * MF(maxEvents)); MF(eventList) = tmp; tmp = &(MF(eventList)[MF(nEvents)]); memset(tmp, 0, sizeof(midiEvent_t) * (MF(maxEvents) - MF(nEvents))); } /* store new event */ tmp = &(MF(eventList)[MF(nEvents)]); MF(nEvents)++; tmp->kcnt = kcnt; /* tmp->data = data; */ /* not used yet */ tmp->st = (unsigned char) st; tmp->d1 = (unsigned char) d1; tmp->d2 = (unsigned char) d2; /* done */ return 0; } static int alloc_tempo(CSOUND *csound, unsigned long kcnt, double tempoVal) { tempoEvent_t *tmp; /* expand array if necessary */ if (MF(nTempo) >= MF(maxTempo)) { MF(maxTempo) += (MF(maxTempo) >> 3); MF(maxTempo) = (MF(maxTempo) + 64) & (~63); tmp = (tempoEvent_t*) csound->ReAlloc(csound, MF(tempoList), sizeof(tempoEvent_t) * MF(maxTempo)); MF(tempoList) = tmp; tmp = &(MF(tempoList)[MF(nTempo)]); memset(tmp, 0, sizeof(tempoEvent_t) * (MF(maxTempo) - MF(nTempo))); } /* store new event */ tmp = &(MF(tempoList)[MF(nTempo)]); MF(nTempo)++; tmp->kcnt = kcnt; tmp->tempoVal = tempoVal; /* done */ return 0; } static int readEvent(CSOUND *csound, FILE *f, int *tlen, unsigned long tickCnt, int st, int *saved_st); static int checkRealTimeEvent(CSOUND *csound, FILE *f, int *tlen, unsigned long tickCnt, int st, int *saved_st) { if (st & 0x80) { if (UNLIKELY(st < 0xF8 || st > 0xFE)) { csound->Message(csound, Str(" *** unexpected event 0x%02X\n"), (unsigned int) st); return -1; } /* handle real time message (return code -2) */ if (readEvent(csound, f, tlen, tickCnt, st, saved_st) != 0) return -1; return -2; } return st; } static int readEvent(CSOUND *csound, FILE *f, int *tlen, unsigned long tickCnt, int st, int *saved_st) { int i, c, d, cnt, dataBytes[2]; cnt = dataBytes[0] = dataBytes[1] = 0; if (st < 0x80) { /* repeat previous status byte */ dataBytes[cnt++] = st; st = *saved_st; if (UNLIKELY(st < 0x80)) { csound->Message(csound, Str(" *** invalid MIDI file data\n")); return -1; } } c = msgDataBytes(st); if (c >= 0) { if (c > 0) { /* save status byte for repeat */ *saved_st = st; } while (cnt < c) { /* read data byte(s) */ d = getCh(csound, f, tlen); if (d < 0 || *tlen < 0) return -1; d = checkRealTimeEvent(csound, f, tlen, tickCnt, d, saved_st); if (d == -2) /* read real time event: continue with reading data */ continue; if (d < 0) return -1; dataBytes[cnt++] = d; } return alloc_event(csound, tickCnt, NULL, st, dataBytes[0], dataBytes[1]); } /* message is of unknown or special type */ if (st == 0xF0) { /* system exclusive */ i = getVLenData(csound, f, tlen); if (i < 0 || *tlen < 0) return -1; /* read message */ while (--i >= 0) { d = getCh(csound, f, tlen); if (d < 0 || *tlen < 0) return -1; if (d == 0xF7) { /* EOX */ if (LIKELY(!i)) return 0; /* should be at end of message */ csound->Message(csound, Str(" *** unexpected end of system " "exclusive message\n")); return -1; } d = checkRealTimeEvent(csound, f, tlen, tickCnt, d, saved_st); if (d == -2) /* if read real time event, */ i++; /* continue with reading message bytes */ else if (UNLIKELY(d < 0)) return -1; /* error */ } /* zero length or EOX not found */ csound->Message(csound, Str(" *** invalid system exclusive " "message in MIDI file\n")); return -1; } else if (st == 0xF7) { /* escape sequence: skip message */ i = getVLenData(csound, f, tlen); /* message length */ if (i < 0 || *tlen < 0) return -1; while (--i >= 0) { c = getCh(csound, f, tlen); if (c < 0 || *tlen < 0) return -1; } return 0; } else if (st == 0xFF) { /* meta event */ st = getCh(csound, f, tlen); /* message type */ if (st < 0 || *tlen < 0) return -1; i = getVLenData(csound, f, tlen); /* message length */ if (i < 0 || *tlen < 0) return -1; if (i > 0 && ((st >= 1 && st <= 5 && (csound->oparms->msglevel & 7) == 7) || (st == 3 && csound->oparms->msglevel != 0))) { /* print non-empty text meta events, depending on message level */ switch (st) { case 0x01: csound->Message(csound, Str(" Message: ")); break; case 0x02: csound->Message(csound, Str(" Copyright info: ")); break; case 0x03: csound->Message(csound, Str(" Track name: ")); break; case 0x04: csound->Message(csound, Str(" Instrument name: ")); break; case 0x05: csound->Message(csound, Str(" Song lyric: ")); break; } while (--i >= 0) { c = getCh(csound, f, tlen); if (c < 0 || *tlen < 0) return -1; csound->Message(csound, "%c", c); } csound->Message(csound, "\n"); return 0; } switch (st) { case 0x51: /* tempo change */ d = 0; while (--i >= 0) { c = getCh(csound, f, tlen); if (c < 0 || *tlen < 0) return -1; d = (d << 8) | c; } if (UNLIKELY(d < 1)) { csound->Message(csound, Str(" *** invalid tempo\n")); return -1; } return alloc_tempo(csound, tickCnt, (60000000.0 / (double) d)); case 0x2F: /* end of track */ if (UNLIKELY(i)) { csound->Message(csound, Str(" *** invalid end of track event\n")); return -1; } if (UNLIKELY(*tlen > 0)) { csound->Message(csound, Str(" *** trailing garbage at end of " "MIDI track\n")); return -1; } /* update file length info */ if (tickCnt > MF(totalKcnt)) MF(totalKcnt) = tickCnt; return 0; default: /* skip any other meta event */ while (--i >= 0) { c = getCh(csound, f, tlen); if (c < 0 || *tlen < 0) return -1; } return 0; } } csound->Message(csound, Str(" *** unknown MIDI message: 0x%02X\n"), (unsigned int) st); return -1; } static int readTrack(CSOUND *csound, FILE *f) { unsigned int tickCnt; int i, c, tlen, st, saved_st; /* check for track header */ for (i = 0; i < 4; i++) { c = getCh(csound, f, NULL); if (c < 0) return -1; if (UNLIKELY(c != (int) midiTrack_ID[i])) { csound->Message(csound, Str(" *** invalid MIDI track header\n")); return -1; } } /* read track length */ tlen = 0; for (i = 0; i < 4; i++) { c = getCh(csound, f, NULL); if (c < 0) return -1; tlen = (tlen << 8) | c; } /* read track data */ tickCnt = 0UL; saved_st = -1; while (tlen > 0) { /* get delta time */ c = getVLenData(csound, f, &tlen); if (c < 0 || tlen < 0) return -1; tickCnt += (unsigned long) c; /* get status byte */ st = getCh(csound, f, &tlen); if (st < 0 || tlen < 0) return -1; /* process event */ if (readEvent(csound, f, &tlen, tickCnt, st, &saved_st) != 0) return -1; } /* successfully read track */ return 0; } /** * Sorts an array of midiEvent_t structures using merge sort algorithm * so that the order of events at the same time is preserved. * 'p' is the array to be sorted, and 'cnt' is the number of elements * (should be > 1). 'tmp' is temporary space of the same length as 'p'. */ static CS_NOINLINE void midiEvent_sort(midiEvent_t *p, midiEvent_t *tmp, size_t cnt) { size_t p1, p2, dstp; size_t n = cnt >> 1; if (n > (size_t) 1) midiEvent_sort(p, tmp, n); if (cnt > (size_t) 2) midiEvent_sort(&(p[n]), tmp, cnt - n); dstp = (size_t) 0; p1 = (size_t) 0; p2 = n; do { size_t srcp; if (p2 >= cnt || (p1 < n && p[p1].kcnt <= p[p2].kcnt)) srcp = p1++; else srcp = p2++; tmp[dstp] = p[srcp]; } while (++dstp < cnt); /* copy result back to original array */ memcpy(p, tmp, cnt * sizeof(midiEvent_t)); } /** * Sorts an array of tempoEvent_t structures using merge sort algorithm * so that the order of events at the same time is preserved. * 'p' is the array to be sorted, and 'cnt' is the number of elements * (should be > 1). 'tmp' is temporary space of the same length as 'p'. */ static CS_NOINLINE void tempoEvent_sort(tempoEvent_t *p, tempoEvent_t *tmp, size_t cnt) { size_t p1, p2, dstp; size_t n = cnt >> 1; if (n > (size_t) 1) tempoEvent_sort(p, tmp, n); if (cnt > (size_t) 2) tempoEvent_sort(&(p[n]), tmp, cnt - n); dstp = (size_t) 0; p1 = (size_t) 0; p2 = n; do { size_t srcp; if (p2 >= cnt || (p1 < n && p[p1].kcnt <= p[p2].kcnt)) srcp = p1++; else srcp = p2++; tmp[dstp] = p[srcp]; } while (++dstp < cnt); /* copy result back to original array */ memcpy(p, tmp, cnt * sizeof(tempoEvent_t)); } /* sort event lists by time and convert tick times to Csound k-periods */ static void sortEventLists(CSOUND *csound) { double timeVal, tempoVal; unsigned long prvTicks, curTicks, tickEvent, tickTempo; int i, j; /* sort events by time in ascending order */ if (MF(nEvents) > 1 || MF(nTempo) > 1) { void *tmp; size_t nbytes; nbytes = (size_t) MF(nEvents) * sizeof(midiEvent_t); if (((size_t) MF(nTempo) * sizeof(tempoEvent_t)) > nbytes) nbytes = (size_t) MF(nTempo) * sizeof(tempoEvent_t); tmp = csound->Malloc(csound, nbytes); if (MF(nEvents) > 1) midiEvent_sort(MF(eventList), (midiEvent_t *) tmp, (size_t) MF(nEvents)); if (MF(nTempo) > 1) tempoEvent_sort(MF(tempoList), (tempoEvent_t *) tmp, (size_t) MF(nTempo)); csound->Free(csound, tmp); } if (MF(timeCode) > 0.0) { /* tick values are in fractions of a beat */ timeVal = 0.0; tempoVal = default_tempo; prvTicks = curTicks = 0UL; /* k-periods per tick */ tempoVal = (double) csound->ekr / (tempoVal * MF(timeCode) / 60.0); i = j = 0; while (i < MF(nEvents) || j < MF(nTempo)) { prvTicks = curTicks; tickEvent = tickTempo = 0UL; tickEvent--; tickTempo--; /* will be max value for unsigned long */ if (i < MF(nEvents)) tickEvent = MF(eventList)[i].kcnt; if (j < MF(nTempo)) tickTempo = MF(tempoList)[j].kcnt; if (tickEvent < tickTempo) { curTicks = tickEvent; timeVal += ((double) ((long) (curTicks - prvTicks)) * tempoVal); MF(eventList)[i++].kcnt = (unsigned long) (timeVal + 0.5); } else { curTicks = tickTempo; timeVal += ((double) ((long) (curTicks - prvTicks)) * tempoVal); tempoVal = MF(tempoList)[j].tempoVal; /* new tempo */ /* k-periods per tick */ tempoVal = (double) csound->ekr / (tempoVal * MF(timeCode) / 60.0); MF(tempoList)[j++].kcnt = (unsigned long) (timeVal + 0.5); } } /* calculate total file length in k-periods */ timeVal += ((double) ((long) (MF(totalKcnt) - curTicks)) * tempoVal); MF(totalKcnt) = (unsigned long) (timeVal + 0.5); } else { /* simple case: time based tick values */ tempoVal = -(MF(timeCode)); /* k-periods per tick */ tempoVal = (double) csound->ekr / tempoVal; i = -1; while (++i < MF(nEvents)) { curTicks = MF(eventList)[i].kcnt; timeVal = (double) curTicks * tempoVal; curTicks = (unsigned long) (timeVal + 0.5); MF(eventList)[i].kcnt = curTicks; } i = -1; while (++i < MF(nTempo)) { curTicks = MF(tempoList)[i].kcnt; timeVal = (double) curTicks * tempoVal; curTicks = (unsigned long) (timeVal + 0.5); MF(tempoList)[i].kcnt = curTicks; } /* calculate total file length in k-periods */ MF(totalKcnt) = (unsigned long) ((double) MF(totalKcnt) * tempoVal + 0.5); } } /* ------------------------------------------------------------------------ */ /* open MIDI file, read all tracks, and create event list */ int csoundMIDIFileOpen(CSOUND *csound, const char *name) { FILE *f = NULL; void *fd = NULL; char *m; int i, c, hdrLen, fileFormat, nTracks, timeCode, saved_nEvents; int mute_track; if (MIDIFILE != NULL) return 0; /* already opened */ /* open file */ if (UNLIKELY(name == NULL || name[0] == '\0')) return -1; //if (*name==3) name++; /* Because of ETX added bt readOptions */ if (strcmp(name, "stdin") == 0) f = stdin; else { fd = csound->FileOpen2(csound, &f, CSFILE_STD, name, "rb", "SFDIR;SSDIR;MFDIR", CSFTYPE_STD_MIDI, 0); if (UNLIKELY(fd == NULL)) { csound->ErrorMsg(csound, Str(" *** error opening MIDI file '%s': %s"), name, strerror(errno)); return -1; } } csound->Message(csound, Str("Reading MIDI file '%s'...\n"), name); /* check header */ for (i = 0; i < 4; i++) { c = getCh(csound, f, NULL); if (UNLIKELY(c < 0)) goto err_return; if (UNLIKELY(c != (int) midiFile_ID[i])) { csound->Message(csound, Str(" *** invalid MIDI file header\n")); goto err_return; } } /* header length: must be 6 bytes */ hdrLen = 0; for (i = 0; i < 4; i++) { c = getCh(csound, f, NULL); if (UNLIKELY(c < 0)) goto err_return; hdrLen = (hdrLen << 8) | c; } if (UNLIKELY(hdrLen != 6)) { csound->Message(csound, Str(" *** invalid MIDI file header\n")); goto err_return; } /* file format (only 0 and 1 are supported) */ fileFormat = 0; for (i = 0; i < 2; i++) { c = getCh(csound, f, NULL); if (UNLIKELY(c < 0)) goto err_return; fileFormat = (fileFormat << 8) | c; } if (UNLIKELY(fileFormat != 0 && fileFormat != 1)) { csound->Message(csound, Str(" *** MIDI file format %d is not supported\n"), fileFormat); goto err_return; } /* number of tracks */ nTracks = 0; for (i = 0; i < 2; i++) { c = getCh(csound, f, NULL); if (UNLIKELY(c < 0)) goto err_return; nTracks = (nTracks << 8) | c; } if (UNLIKELY(nTracks < 1)) { csound->Message(csound, Str(" *** invalid number of tracks\n")); goto err_return; } if (UNLIKELY(nTracks > 1 && !fileFormat)) { csound->Message(csound, Str("WARNING: format 0 MIDI file with " "multiple tracks\n")); } /* time code */ timeCode = 0; for (i = 0; i < 2; i++) { c = getCh(csound, f, NULL); if (UNLIKELY(c < 0)) goto err_return; timeCode = (timeCode << 8) | c; } /* allocate structure */ MIDIFILE = (void*) csound->Calloc(csound, sizeof(midiFile_t)); /* calculate ticks per second or beat based on time code */ if (UNLIKELY(timeCode < 1 || (timeCode >= 0x8000 && (timeCode & 0xFF) == 0))) { csound->Message(csound, Str(" *** invalid time code: %d\n"), timeCode); goto err_return; } if (timeCode < 0x8000) MF(timeCode) = (double) timeCode; else { switch (timeCode & 0xFF00) { case 0xE800: case 0xE700: case 0xE200: MF(timeCode) = (double) ((timeCode >> 8) - 256); break; case 0xE300: MF(timeCode) = -29.97; break; default: csound->Message(csound, Str(" *** invalid time code: %d\n"), timeCode); goto err_return; } MF(timeCode) *= (double) (timeCode & 0xFF); } /* initialise structure data */ MF(totalKcnt) = csound->global_kcounter; MF(nEvents) = 0; MF(maxEvents) = 0; MF(nTempo) = 0; MF(maxTempo) = 0; MF(eventList) = (midiEvent_t*) NULL; MF(tempoList) = (tempoEvent_t*) NULL; MF(currentTempo) = default_tempo; MF(eventListIndex) = 0; MF(tempoListIndex) = 0; /* read all tracks */ m = &(csound->midiGlobals->muteTrackList[0]); for (i = 0; i < nTracks; i++) { saved_nEvents = MF(nEvents); mute_track = 0; if (*m != '\0') { /* is this track muted ? */ if (*m == '1') mute_track = 1; else if (UNLIKELY(*m != '0')) { csound->Message(csound, Str(" *** invalid mute track list format\n")); goto err_return; } m++; } if (!mute_track) csound->Message(csound, Str(" Track %2d\n"), i); else csound->Message(csound, Str(" Track %2d is muted\n"), i); if (readTrack(csound, f) != 0) goto err_return; if (mute_track) /* if track is muted, discard any */ MF(nEvents) = saved_nEvents; /* non-tempo events read */ } if (fd != NULL) csound->FileClose(csound, fd); /* prepare event and tempo list for reading */ sortEventLists(csound); /* successfully read MIDI file */ csound->Message(csound, Str("done.\n")); return 0; /* in case of error: clean up and report error */ err_return: if (fd != NULL) csound->FileClose(csound, fd); csoundMIDIFileClose(csound); return -1; } /* read MIDI file event data at performace time */ int csoundMIDIFileRead(CSOUND *csound, unsigned char *buf, int nBytes) { midiFile_t *mf; int i, j, n, nRead; mf = (midiFile_t*) MIDIFILE; if (mf == NULL) return 0; i = mf->eventListIndex; j = mf->tempoListIndex; if (i >= mf->nEvents && j >= mf->nTempo) { /* there are no more events, */ if ((unsigned long) csound->global_kcounter >= mf->totalKcnt && !(csound->MTrkend)) { /* and end of file is reached: */ csound->Message(csound, Str("end of midi track in '%s'\n"), csound->oparms->FMidiname); csound->Message(csound, Str("%d forced decays, %d extra noteoffs\n"), csound->Mforcdecs, csound->Mxtroffs); csound->MTrkend = 1; csoundMIDIFileClose(csound); csound->oparms->FMidiin = 0; if (csound->oparms->ringbell && !(csound->oparms->termifend)) csound->Message(csound, "\a"); } return 0; } /* otherwise read any events with time less than or equal to */ /* current orchestra time */ while (j < mf->nTempo && (unsigned long) csound->global_kcounter >= mf->tempoList[j].kcnt) { /* tempo change */ mf->currentTempo = mf->tempoList[j++].tempoVal; } mf->tempoListIndex = j; nRead = 0; while (i < mf->nEvents && (unsigned long) csound->global_kcounter >= mf->eventList[i].kcnt) { n = msgDataBytes((int) mf->eventList[i].st) + 1; if (n < 1) { i++; continue; /* unknown or system event: skip */ } nBytes -= n; if (UNLIKELY(nBytes < 0)) { csound->Message(csound, Str(" *** buffer overflow while reading " "MIDI file events\n")); break; /* return with whatever has been read so far */ } nRead += n; *buf++ = mf->eventList[i].st; if (n > 1) *buf++ = mf->eventList[i].d1; if (n > 2) *buf++ = mf->eventList[i].d2; i++; } mf->eventListIndex = i; /* return the number of bytes read */ return nRead; } /* destroy MIDI file event list */ int csoundMIDIFileClose(CSOUND *csound) { /* nothing to do: memRESET() will free any allocated memory */ MIDIFILE = (void*) NULL; return 0; } /* midirecv.c, resets MIDI controllers on a channel */ extern void midi_ctl_reset(CSOUND *csound, int16 chan); /* called by csoundRewindScore() to reset performance to time zero */ void midifile_rewind_score(CSOUND *csound) { int i; OPARMS *O = csound->oparms; if (MIDIFILE != NULL) { /* reset event index and tempo */ MF(currentTempo) = default_tempo; MF(eventListIndex) = 0; MF(tempoListIndex) = 0; csound->MTrkend = csound->Mxtroffs = csound->Mforcdecs = 0; /* reset controllers on all channels */ for (i = 0; i < MAXCHAN; i++) midi_ctl_reset(csound, (int16) i); } else if (LIKELY(O->FMidiname != NULL)) { csound->MTrkend = 0; if (UNLIKELY(csoundMIDIFileOpen(csound, O->FMidiname) != 0)) csound->Die(csound, Str("Failed to load MIDI file.")); O->FMidiin = 1; } else csound->Warning(csound, Str("Cannot rewind MIDI score\n")); } /* ------------------------------------------------------------------------ */ /* miditempo opcode: returns the current tempo of MIDI file or score */ int midiTempoOpcode(CSOUND *csound, MIDITEMPO *p) { if (MIDIFILE == NULL) *(p->kResult) = FL(60.0) *csound->esr / (MYFLT)(csound->ibeatTime); else *(p->kResult) = (MYFLT) MF(currentTempo); return OK; } int midiFileStatus(CSOUND *csound, MIDITEMPO *p){ *p->kResult = csound->oparms->FMidiin; return OK; } csound-6.10.0/InOut/midirecv.c000066400000000000000000000541431321653344700161140ustar00rootroot00000000000000/* midirecv.c: Copyright (C) 1995 Barry Vercoe, John ffitch (C) 2005 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Real time MIDI callback functions: ---------------------------------- int (*MidiInOpenCallback)(CSOUND *csound, void **userData, const char *devName); Open MIDI input device 'devName', and store stream specific data pointer in *userData. Return value is zero on success, and a non-zero error code if an error occured. int (*MidiReadCallback)(CSOUND *csound, void *userData, unsigned char *buf, int nbytes); Read at most 'nbytes' bytes of MIDI data from input stream 'userData', and store in 'buf'. Returns the actual number of bytes read, which may be zero if there were no events, and negative in case of an error. Note: incomplete messages (such as a note on status without the data bytes) should not be returned. int (*MidiInCloseCallback)(CSOUND *csound, void *userData); Close MIDI input device associated with 'userData'. Return value is zero on success, and a non-zero error code on failure. int (*MidiOutOpenCallback)(CSOUND *csound, void **userData, const char *devName); Open MIDI output device 'devName', and store stream specific data pointer in *userData. Return value is zero on success, and a non-zero error code if an error occured. int (*MidiWriteCallback)(CSOUND *csound, void *userData, const unsigned char *buf, int nbytes); Write 'nbytes' bytes of MIDI data to output stream 'userData' from 'buf' (the buffer will not contain incomplete messages). Returns the actual number of bytes written, or a negative error code. int (*MidiOutCloseCallback)(CSOUND *csound, void *userData); Close MIDI output device associated with '*userData'. Return value is zero on success, and a non-zero error code on failure. const char *(*MidiErrorStringCallback)(int errcode); Returns pointer to a string constant storing an error massage for error code 'errcode'. Setting function pointers: -------------------------- void csoundSetExternalMidiInOpenCallback(CSOUND *csound, int (*func)(CSOUND *, void **, const char *)); void csoundSetExternalMidiReadCallback(CSOUND *csound, int (*func)(CSOUND *, void *, unsigned char *, int)); void csoundSetExternalMidiInCloseCallback(CSOUND *csound, int (*func)(CSOUND *, void *)); void csoundSetExternalMidiOutOpenCallback(CSOUND *csound, int (*func)(CSOUND *, void **, const char *)); void csoundSetExternalMidiWriteCallback(CSOUND *csound, int (*func)(CSOUND *, void *, const unsigned char *, int)); void csoundSetExternalMidiOutCloseCallback(CSOUND *csound, int (*func)(CSOUND *, void *)); void csoundSetExternalMidiErrorStringCallback(CSOUND *csound, const char *(*func)(int)); */ #include "csoundCore.h" #include "midiops.h" #include "midifile.h" #define MGLOB(x) (csound->midiGlobals->x) static void midNotesOff(CSOUND *); static const MYFLT dsctl_map[12] = { FL(1.0), FL(0.0), FL(1.0), FL(0.0), FL(1.0), FL(0.0), FL(1.0), FL(0.0), FL(1.0), FL(0.0), FL(1.0), FL(0.0) }; static const int16 datbyts[8] = { 2, 2, 2, 2, 1, 1, 2, 0 }; /* open a Midi event stream for reading, alloc bufs */ /* callable once from main.c */ void MidiOpen(CSOUND *csound) { MGLOBAL *p = csound->midiGlobals; OPARMS *O = csound->oparms; int err; /* First set up buffers. */ p->Midevtblk = (MEVENT*) csound->Calloc(csound, sizeof(MEVENT)); p->sexp = 0; /* Then open device... */ if (O->Midiin) { if (p->MidiInOpenCallback == NULL) csound->Die(csound, Str(" *** no callback for opening MIDI input")); if (p->MidiReadCallback == NULL) csound->Die(csound, Str(" *** no callback for reading MIDI data")); err = p->MidiInOpenCallback(csound, &(p->midiInUserData), O->Midiname); if (err != 0) { csound->Die(csound, Str(" *** error opening MIDI in device: %d (%s)"), err, csoundExternalMidiErrorString(csound, err)); } } /* and file. */ if (O->FMidiin && O->FMidiname != NULL) { if (csoundMIDIFileOpen(csound, O->FMidiname) != 0) csound->Die(csound, Str("Failed to load MIDI file.")); } } /* turn off all notes in chnl sust array */ /* called by SUSTAIN_SW_off only if count non-zero */ static void sustsoff(CSOUND *csound, MCHNBLK *chn) { INSDS *ip; int nn; if (chn->ksuscnt <= 0) { chn->ksuscnt = 0; return; } for (nn = 0; nn < 128; nn++) { ip = chn->kinsptr[nn]; while (ip != NULL) { if (ip->m_sust) xturnoff(csound, ip); ip = ip->nxtolap; } } if (chn->ksuscnt) csound->Message(csound, Str("sustain count still %d\n"), chn->ksuscnt); chn->ksuscnt = 0; } /* reset all controllers for this channel */ void midi_ctl_reset(CSOUND *csound, int16 chan) { MCHNBLK *chn; int i; chn = csound->m_chnbp[chan]; for (i = 1; i <= 135; i++) /* from ctlr 1 to ctlr 128 */ chn->ctl_val[i] = FL(0.0); /* reset all ctlrs to 0 */ /* exceptions: */ if (!MGLOB(rawControllerMode)) { chn->ctl_val[7] = FL(127.0); /* volume */ chn->ctl_val[8] = FL(64.0); /* balance */ chn->ctl_val[10] = FL(64.0); /* pan */ chn->ctl_val[11] = FL(127.0); /* expression */ } else chn->ctl_val[0] = FL(0.0); chn->pbensens = FL(2.0); /* pitch bend range */ chn->datenabl = 0; /* reset aftertouch to max value - added by Istvan Varga, May 2002 */ chn->aftouch = csound->aftouch; for (i = 0; i < 128; i++) chn->polyaft[i] = csound->aftouch; /* controller 64 has just been set to zero: terminate any held notes */ if (chn->ksuscnt && !MGLOB(rawControllerMode)) sustsoff(csound, chn); chn->sustaining = 0; /* reset pitch bend */ chn->pchbend = FL(0.0); } /* execute non-note channel voice and channel mode commands */ void m_chanmsg(CSOUND *csound, MEVENT *mep) { MCHNBLK *chn = csound->m_chnbp[mep->chan]; int16 n; MYFLT *fp; switch (mep->type) { case PROGRAM_TYPE: /* PROGRAM CHANGE */ chn->pgmno = mep->dat1; if (chn->insno <= 0) /* ignore if channel is muted */ break; n = (int16) chn->pgm2ins[mep->dat1]; /* program change -> INSTR */ if (n > 0 && n <= csound->engineState.maxinsno && /* if corresp instr exists */ csound->engineState.instrtxtp[n] != NULL) { /* assign as insno */ chn->insno = n; /* else ignore prog. change */ csound->Message(csound, Str("midi channel %d now using instr %d\n"), mep->chan + 1, chn->insno); } break; case POLYAFT_TYPE: chn->polyaft[mep->dat1] = mep->dat2; /* Polyphon per-Key Press */ break; case CONTROL_TYPE: /* CONTROL CHANGE MESSAGES: */ n = mep->dat1; if (MGLOB(rawControllerMode)) { /* "raw" mode: */ chn->ctl_val[n] = (MYFLT) mep->dat2; /* only store value */ break; } if (n >= 111) /* if special, redirect */ goto special; if (n == NRPNMSB || n == RPNMSB) { chn->dpmsb = mep->dat2; } else if (n == NRPNLSB || n == RPNLSB) { chn->dplsb = mep->dat2; if (chn->dplsb == 127 && chn->dpmsb == 127) chn->datenabl = 0; else chn->datenabl = 1; } else if (n == DATENTRY && chn->datenabl) { int msb = chn->dpmsb; int lsb = chn->dplsb; MYFLT fval; if (msb == 0 && lsb == 0) { chn->pbensens = (MYFLT) mep->dat2; } else if (msb == 1) { /* GS system PART PARAMS */ int ctl; switch(lsb) { case 8: ctl = VIB_RATE; break; case 9: ctl = VIB_DEPTH; break; case 10: ctl = VIB_DELAY; break; case 32: ctl = TVF_CUTOFF; break; case 33: ctl = TVF_RESON; break; case 99: ctl = TVA_RIS; break; case 100:ctl = TVA_DEC; break; case 102:ctl = TVA_RLS; break; default: csound->Message(csound, Str("unknown NPRN lsb %d\n"), lsb); goto err; } fval = (MYFLT) (mep->dat2 - 64); chn->ctl_val[ctl] = fval; /* then store */ } else { if (msb < 24 || msb == 25 || msb == 27 || msb > 31 || lsb < 25 || lsb > 87) csound->Message(csound, Str("unknown drum param nos, msb %d lsb %d\n"), (int) msb, (int) lsb); else { static const int drtab[8] = {0,0,1,1,2,3,4,5}; int parnum = drtab[msb - 24]; if (parnum == 0) fval = (MYFLT) (mep->dat2 - 64); else fval = mep->dat2; // if (dsctl_map != NULL) { always true fp = (MYFLT*) &(dsctl_map[parnum*2]); if (*fp != FL(0.0)) { MYFLT xx = (fval * *fp++); fval = xx + *fp; /* optionally map */ } csound->Message(csound, Str("CHAN %d DRUMKEY %d not in keylst, " "PARAM %d NOT UPDATED\n"), (int) mep->chan + 1, (int) lsb, (int) msb); } } } else chn->ctl_val[n] = (MYFLT) mep->dat2; /* record data as MYFLT */ err: if (n == SUSTAIN_SW) { /* if sustainP changed */ if (mep->dat2 > 0) chn->sustaining = 1; else if (chn->sustaining) { /* & going off */ chn->sustaining = 0; sustsoff(csound, chn); /* reles any notes */ } } break; special: if (n < 121) { /* for ctrlr 111, 112, ... chk inexclus lists */ if ((csound->oparms->msglevel & 7) == 7) csound->Message(csound, Str("ctrl %d has no exclus list\n"), (int) n); break; } /* 121 == RESET ALL CONTROLLERS */ if (n == 121) { /* CHANNEL MODE MESSAGES: */ midi_ctl_reset(csound, mep->chan); } else if (n == 122) { /* absorb lcl ctrl data */ /* int lcl_ctrl = mep->dat2; ?? */ /* 0:off, 127:on */ } else if (n == 123) midNotesOff(csound); /* allchnl AllNotesOff */ else if (n == 126) { /* MONO mode */ if (chn->monobas == NULL) { MONPCH *mnew, *mend; chn->monobas = (MONPCH *)csound->Calloc(csound, (long)sizeof(MONPCH) * 8); mnew = chn->monobas; mend = mnew + 8; do { mnew->pch = -1; } while (++mnew < mend); } chn->mono = 1; } else if (n == 127) { /* POLY mode */ if (chn->monobas != NULL) { csound->Free(csound, (char *)chn->monobas); chn->monobas = NULL; } chn->mono = 0; } else csound->Message(csound, Str("chnl mode msg %d not implemented\n"), n); break; case AFTOUCH_TYPE: chn->aftouch = mep->dat1; /* chanl (all-key) Press */ break; case PCHBEND_TYPE: chn->pchbend = (MYFLT)(((mep->dat2 - 64) << 7) + mep->dat1)/FL(8192.0); break; case SYSTEM_TYPE: /* sys_common 1-3 only: chan contains which */ switch(mep->chan) { case 1: case 2: case 3: break; default: csound->Die(csound, Str("unrecognised sys_common type %d"), mep->chan); } break; default: csound->Die(csound, Str("unrecognised message type %d"), mep->type); } } /* initialise all MIDI channels; called by musmon before oload() */ void m_chn_init_all(CSOUND *csound) { /* alloc a midi control blk for a midi chnl */ MCHNBLK *chn; /* & assign corr instr n+1, else a default */ int defaultinsno, n; int16 chan; defaultinsno = 0; while (csound->engineState.instrtxtp && ++defaultinsno <= (int) csound->engineState.maxinsno && csound->engineState.instrtxtp[defaultinsno] == NULL); if (defaultinsno > (int) csound->engineState.maxinsno) defaultinsno = 0; /* no instruments */ for (chan = (int16) 0; chan < (int16) 16; chan++) { /* alloc a midi control blk for midi channel */ /* & assign default instrument number */ csound->m_chnbp[chan] = chn = (MCHNBLK*) csound->Calloc(csound, sizeof(MCHNBLK)); n = (int) chan + 1; /* if corresponding instrument exists, assign as insno, */ if (csound->engineState.instrtxtp && n <= (int) csound->engineState.maxinsno && csound->engineState.instrtxtp[n] != NULL) chn->insno = (int16) n; else if (defaultinsno > 0) chn->insno = (int16) defaultinsno; else chn->insno = (int16) -1; /* else mute channel */ /* reset all controllers */ chn->pgmno = -1; midi_ctl_reset(csound, chan); for (n = 0; n < 128; n++) chn->pgm2ins[n] = (int16) (n + 1); if (csound->oparms->Midiin || csound->oparms->FMidiin) { if (chn->insno > 0) csound->Message(csound, Str("midi channel %d using instr %d\n"), chan + 1, chn->insno); else csound->Message(csound, Str("midi channel %d is muted\n"), chan + 1); } } } /* assign an insno to a chnl */ /* =massign: called from i0 */ int m_chinsno(CSOUND *csound, int chan, int insno, int reset_ctls) { MCHNBLK *chn; MEVENT mev; if (chan < 0 || chan > 15) return csound->InitError(csound, Str("illegal channel number")); chn = csound->m_chnbp[chan]; if (insno <= 0) { chn->insno = -1; csound->Message(csound, Str("MIDI channel %d muted\n"), chan + 1); } else { if (insno > csound->engineState.maxinsno || csound->engineState.instrtxtp[insno] == NULL) { csound->Message(csound, Str("Insno = %d\n"), insno); return csound->InitError(csound, Str("unknown instr")); } chn->insno = (int16) insno; csound->Message(csound, Str("chnl %d using instr %d\n"), chan + 1, chn->insno); /* check for program change: will override massign if enabled */ if (chn->pgmno >= 0) { mev.type = PROGRAM_TYPE; mev.chan = (int16) chan; mev.dat1 = chn->pgmno; mev.dat2 = 0; m_chanmsg(csound, &mev); } } if (reset_ctls) midi_ctl_reset(csound, (int16) chan); return OK; } static void AllNotesOff(CSOUND *csound, MCHNBLK *chn) { INSDS *ip; int nn; for (nn = 0; nn < 128; nn++) { ip = chn->kinsptr[nn]; while (ip != NULL) { /* xturnoff_now(csound, ip); */ xturnoff(csound, ip); /* allow release - is this correct ? */ ip = ip->nxtolap; } } } /* turn off ALL curr midi notes, ALL chnls */ /* called by musmon, ctrl 123 & sensMidi */ static void midNotesOff(CSOUND *csound) { int chan = 0; do { AllNotesOff(csound, csound->m_chnbp[chan]); } while (++chan < MAXCHAN); } /* sense a MIDI event, collect the data & dispatch */ /* called from sensevents(), returns 2 if MIDI on/off */ int sensMidi(CSOUND *csound) { MGLOBAL *p = csound->midiGlobals; MEVENT *mep = p->Midevtblk; OPARMS *O = csound->oparms; int n; int16 c, type; nxtchr: if (p->bufp >= p->endatp) { p->bufp = &(p->mbuf[0]); p->endatp = p->bufp; if (O->Midiin && !csound->advanceCnt) { /* read MIDI device */ n = p->MidiReadCallback(csound, p->midiInUserData, p->bufp, MBUFSIZ); if (n < 0) csoundErrorMsg(csound, Str(" *** error reading MIDI device: %d (%s)"), n, csoundExternalMidiErrorString(csound, n)); else p->endatp += (int) n; } if (O->FMidiin) { /* read MIDI file */ n = csoundMIDIFileRead(csound, p->endatp, MBUFSIZ - (int) (p->endatp - p->bufp)); if (n > 0) p->endatp += (int) n; } if (p->endatp <= p->bufp) return 0; /* no events were received */ } if ((c = *(p->bufp++)) & 0x80) { /* STATUS byte: */ type = c & 0xF0; if (type == SYSTEM_TYPE) { int16 lo3 = (c & 0x07); if (c & 0x08) /* sys_realtime: */ switch (lo3) { /* dispatch now */ case 0: /* m_clktim++; */ /* timing clock */ case 2: /* start */ case 3: /* continue */ case 4: /* stop */ case 6: /* active sensing */ case 7: /* system reset */ goto nxtchr; default: csound->Message(csound, Str("undefined sys-realtime msg %x\n"), c); goto nxtchr; } else { /* sys_non-realtime status: */ p->sexp = 0; /* implies sys_exclus end */ switch (lo3) { /* dispatch on lo3: */ case 7: goto nxtchr; /* EOX: already done */ case 0: p->sexp = 1; /* sys_ex begin: */ goto nxtchr; /* goto copy data */ /* sys_common: need some data, so build evt */ case 1: /* MTC quarter frame */ case 3: p->datreq = 1; /* song select */ break; case 2: p->datreq = 2; /* song position */ break; case 6: /* tune request */ goto nxtchr; default: csound->Message(csound, Str("undefined sys_common msg %x\n"), c); p->datreq = 32767; /* waste any data following */ p->datcnt = 0; goto nxtchr; } } mep->type = type; /* begin sys_com event */ mep->chan = lo3; /* holding code in chan */ p->datcnt = 0; goto nxtchr; } else { /* other status types: */ int16 chan; p->sexp = 0; /* also implies sys_exclus end */ chan = c & 0xF; mep->type = type; /* & begin new event */ mep->chan = chan; p->datreq = datbyts[(type>>4) & 0x7]; p->datcnt = 0; goto nxtchr; } } if (p->sexp != 0) { /* NON-STATUS byte: */ goto nxtchr; } if (p->datcnt == 0) mep->dat1 = c; /* else normal data */ else mep->dat2 = c; if (++p->datcnt < p->datreq) /* if msg incomplete */ goto nxtchr; /* get next char */ /* Enter the input event into a buffer used by 'midiin'. */ if (mep->type != SYSTEM_TYPE) { unsigned char *pMessage = &(p->MIDIINbuffer2[p->MIDIINbufIndex++].bData[0]); p->MIDIINbufIndex &= MIDIINBUFMSK; *pMessage++ = mep->type | mep->chan; *pMessage++ = (unsigned char) mep->dat1; *pMessage = (p->datreq < 2 ? (unsigned char) 0 : mep->dat2); } p->datcnt = 0; /* else allow a repeat */ /* NB: this allows repeat in syscom 1,2,3 too */ if (mep->type > NOTEON_TYPE) { /* if control or syscom */ m_chanmsg(csound, mep); /* handle from here */ goto nxtchr; /* & go look for more */ } return 2; /* else it's note_on/off */ } extern void csoundCloseMidiOutFile(CSOUND *); void MidiClose(CSOUND *csound) { MGLOBAL *p = csound->midiGlobals; int retval; if (p==NULL) { printf("No MIDI\n"); return; } if (p->MidiInCloseCallback != NULL) { retval = p->MidiInCloseCallback(csound, p->midiInUserData); if (retval != 0) csoundErrorMsg(csound, Str("Error closing MIDI in device: %d (%s)"), retval, csoundExternalMidiErrorString(csound, retval)); } p->midiInUserData = NULL; if (p->MIDIoutDONE && p->MidiOutCloseCallback != NULL) { retval = p->MidiOutCloseCallback(csound, p->midiOutUserData); if (retval != 0) csoundErrorMsg(csound, Str("Error closing MIDI out device: %d (%s)"), retval, csoundExternalMidiErrorString(csound, retval)); } p->MIDIoutDONE = 0; p->midiOutUserData = NULL; if (p->midiFileData != NULL) { csoundMIDIFileClose(csound); p->midiFileData = NULL; } if (p->midiOutFileData != NULL) { csoundCloseMidiOutFile(csound); p->midiOutFileData = NULL; } } csound-6.10.0/InOut/midisend.c000066400000000000000000000172751321653344700161130ustar00rootroot00000000000000/* midisend.c: Copyright (C) 1997 Dave Philips (C) 2005 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* MIDISEND.C */ #include "midioops.h" typedef struct midiOutFile_s { FILE *f; void *fd; unsigned int prv_tick; size_t nBytes; unsigned char prv_status; } midiOutFile_t; static const unsigned char midiMsgBytes[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 0, 1 }; /* header for type 0 (1 track) MIDI file with 1/3 ms time resolution */ static const unsigned char midiOutFile_header[25] = { 0x4D, 0x54, 0x68, 0x64, /* "MThd" */ 0x00, 0x00, 0x00, 0x06, /* header length */ 0x00, 0x00, /* file type */ 0x00, 0x01, /* number of tracks */ 0x19, 0x78, /* tick time (1/25 sec / 120), */ /*VL this was 0xE7, which was wrong, changed to 0x19 0x78 */ 0x4D, 0x54, 0x72, 0x6B, /* "MTrk" */ 0x00, 0x00, 0x00, 0x00, /* track length (updated later) */ /* -------------------------------------------------------- */ 0xFF, 0x2F, 0x00 /* end of track */ }; /* write a single event to MIDI out file */ static CS_NOINLINE void csoundWriteMidiOutFile(CSOUND *csound, const unsigned char *evt, int nbytes) { unsigned char buf[8]; double s; midiOutFile_t *p = (midiOutFile_t *) csound->midiGlobals->midiOutFileData; unsigned int t, prv; int ndx = 0; if (nbytes < 2) return; s = csound->icurTime/csound->esr; /* this check (for perf time run?) used the global pds, which has now been removed. My impression is that it is sufficient to check for csound->ids, but this might need attention if MIDI file output has problems */ if (csound->ids == NULL) s -= csound->ksmps/csound->esr; s *= 13040.; /* VL NOV 11: this was 3000.0, which was wrong; 13040.0 was arrived at by experimentation */ #ifdef HAVE_C99 t = (unsigned int) lrint(s); #else t = (unsigned int) ((int) (s + 0.5)); #endif t = ((int) t >= 0L ? t : 0UL); prv = p->prv_tick; p->prv_tick = t; t -= prv; if (t > 0x0000007FUL) { if (t > 0x00003FFFUL) { if (t > 0x001FFFFFUL) { buf[ndx++] = ((unsigned char) (t >> 21) & (unsigned char) 0x7F) | (unsigned char) 0x80; } buf[ndx++] = ((unsigned char) (t >> 14) & (unsigned char) 0x7F) | (unsigned char) 0x80; } buf[ndx++] = ((unsigned char) (t >> 7) & (unsigned char) 0x7F) | (unsigned char) 0x80; } buf[ndx++] = (unsigned char) t & (unsigned char) 0x7F; { unsigned char st = *evt; if (st != p->prv_status) { buf[ndx++] = st; p->prv_status = st; } } buf[ndx++] = evt[1]; if (nbytes > 2) buf[ndx++] = evt[2]; p->nBytes += (size_t) ndx; fwrite(&(buf[0]), (size_t) 1, (size_t) ndx, p->f); } void send_midi_message(CSOUND *csound, int status, int data1, int data2) { MGLOBAL *p = csound->midiGlobals; unsigned char buf[4]; unsigned char nbytes; buf[0] = (unsigned char) status; nbytes = midiMsgBytes[(unsigned char) status >> 3]; buf[1] = (unsigned char) data1; buf[2] = (unsigned char) data2; if (!nbytes) return; if (csound->oparms_.Midioutname != NULL) p->MidiWriteCallback(csound, p->midiOutUserData, &(buf[0]), (int) nbytes); if (p->midiOutFileData != NULL) csoundWriteMidiOutFile(csound, &(buf[0]), (int) nbytes); } void note_on(CSOUND *csound, int chan, int num, int vel) { send_midi_message(csound, (chan & 0x0F) | MD_NOTEON, num, vel); } void note_off(CSOUND *csound, int chan, int num, int vel) { send_midi_message(csound, (chan & 0x0F) | MD_NOTEOFF, num, vel); } void control_change(CSOUND *csound, int chan, int num, int value) { send_midi_message(csound, (chan & 0x0F) | MD_CNTRLCHG, num, value); } void after_touch(CSOUND *csound, int chan, int value) { send_midi_message(csound, (chan & 0x0F) | MD_CHANPRESS, value, 0); } void program_change(CSOUND *csound, int chan, int num) { send_midi_message(csound, (chan & 0x0F) | MD_PGMCHG, num, 0); } void pitch_bend(CSOUND *csound, int chan, int lsb, int msb) { send_midi_message(csound, (chan & 0x0F) | MD_PTCHBENDCHG, lsb, msb); } void poly_after_touch(CSOUND *csound, int chan, int note_num, int value) { send_midi_message(csound, (chan & 0x0F) | MD_POLYAFTER, note_num, value); } void openMIDIout(CSOUND *csound) { MGLOBAL *p = csound->midiGlobals; midiOutFile_t *fp; OPARMS *O = &(csound->oparms_); int retval; /* open MIDI out device */ if (O->Midioutname != NULL && !p->MIDIoutDONE) { if (UNLIKELY(p->MidiOutOpenCallback == NULL)) csoundDie(csound, Str(" *** no callback for opening MIDI output")); if (UNLIKELY(p->MidiWriteCallback == NULL)) csoundDie(csound, Str(" *** no callback for writing MIDI data")); p->MIDIoutDONE = 1; retval = p->MidiOutOpenCallback(csound, &(p->midiOutUserData), O->Midioutname); if (UNLIKELY(retval != 0)) { csoundDie(csound, Str(" *** error opening MIDI out device: %d (%s)"), retval, csoundExternalMidiErrorString(csound, retval)); } } /* open MIDI out file */ if (O->FMidioutname == NULL || p->midiOutFileData != NULL) return; fp = (midiOutFile_t *) csound->Calloc(csound, sizeof(midiOutFile_t)); fp->fd = csound->FileOpen2(csound, &(fp->f), CSFILE_STD, O->FMidioutname, "wb", NULL, CSFTYPE_STD_MIDI, 0); if (UNLIKELY(fp->fd == NULL)) { csoundDie(csound, Str(" *** error opening MIDI out file '%s'"), O->FMidioutname); } p->midiOutFileData = (void *) fp; /* write header */ if (UNLIKELY(fwrite(&(midiOutFile_header[0]), (size_t)1, (size_t)22, fp->f) != 22)) { csound->Die(csound, Str("Short write in MIDI\n")); } } void csoundCloseMidiOutFile(CSOUND *csound) { midiOutFile_t *p = (midiOutFile_t *) csound->midiGlobals->midiOutFileData; /* write end of track meta-event */ csoundWriteMidiOutFile(csound, &(midiOutFile_header[22]), 3); /* update header for track length */ if (fseek(p->f, 18L, SEEK_SET)<0) csound->Message(csound, Str("error closing MIDI output file\n")); fputc((int)(p->nBytes >> 24) & 0xFF, p->f); fputc((int)(p->nBytes >> 16) & 0xFF, p->f); fputc((int)(p->nBytes >> 8) & 0xFF, p->f); fputc((int)(p->nBytes) & 0xFF, p->f); /* close file and clean up */ csound->midiGlobals->midiOutFileData = NULL; csound->FileClose(csound, p->fd); csound->Free(csound, p); } csound-6.10.0/InOut/pmidi.c000066400000000000000000000406011321653344700154060ustar00rootroot00000000000000/* pmidi.c: Copyright (C) 2004 John ffitch after Barry Vercoe (C) 2005 Istvan Varga (C) 2008 Andres Cabrera This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Realtime MIDI using Portmidi library */ #include "csdl.h" /* PMIDI.C */ #include "csGblMtx.h" #include "midiops.h" #include #include /* Stub for compiling this file with MinGW and linking with portmidi.lib built witn MSVC AND with Windows libraries from MinGW (missing __wassert). */ #if defined(WIN32) && !defined(MSVC) void _wassert(wchar_t *condition) { } #endif typedef struct _pmall_data { PortMidiStream *midistream; struct _pmall_data *next; } pmall_data; static const int datbyts[8] = { 2, 2, 2, 2, 1, 1, 2, 0 }; static int portMidiErrMsg(CSOUND *csound, const char *msg, ...) { va_list args; va_start(args, msg); csound->ErrMsgV(csound, " *** PortMIDI: ", msg, args); va_end(args); return -1; } static int portMidi_getDeviceCount(int output) { int i, cnt1, cnt2; PmDeviceInfo *info; cnt1 = (int)Pm_CountDevices(); if (UNLIKELY(cnt1 < 1)) return cnt1; /* no devices */ cnt2 = 0; for (i = 0; i < cnt1; i++) { info = (PmDeviceInfo*)Pm_GetDeviceInfo((PmDeviceID) i); if (output && info->output) cnt2++; else if (!output && info->input) cnt2++; } return cnt2; } static int portMidi_getRealDeviceID(int dev, int output) { int i, j, cnt; PmDeviceInfo *info; cnt = (int)Pm_CountDevices(); i = j = -1; while (++i < cnt) { info = (PmDeviceInfo*)Pm_GetDeviceInfo((PmDeviceID) i); if ((output && !(info->output)) || (!output && !(info->input))) continue; if (++j == dev) return i; } return -1; } static int portMidi_getPackedDeviceID(int dev, int output) { int i, j, cnt; PmDeviceInfo *info; cnt = (int)Pm_CountDevices(); i = j = -1; while (++i < cnt) { info = (PmDeviceInfo*)Pm_GetDeviceInfo((PmDeviceID) i); if ((output && info->output) || (!output && info->input)) j++; if (i == dev) return j; } return -1; } static PmDeviceInfo *portMidi_getDeviceInfo(int dev, int output) { int i; i = portMidi_getRealDeviceID(dev, output); if (UNLIKELY(i < 0)) return NULL; return ((PmDeviceInfo*)Pm_GetDeviceInfo((PmDeviceID) i)); } /* reference count for PortMidi initialisation */ static unsigned long portmidi_init_cnt = 0UL; static int stop_portmidi(CSOUND *csound, void *userData) { (void) csound; (void) userData; #if !defined(WIN32) csoundLock(); #endif if (portmidi_init_cnt) { if (--portmidi_init_cnt == 0UL) { Pm_Terminate(); Pt_Stop(); } } #if !defined(WIN32) csoundUnLock(); #endif return 0; } static int start_portmidi(CSOUND *csound) { const char *errMsg = NULL; #if !defined(WIN32) csoundLock(); #endif if (!portmidi_init_cnt) { if (UNLIKELY(Pm_Initialize() != pmNoError)) errMsg = Str(" *** error initialising PortMIDI"); else if (UNLIKELY(Pt_Start(1, NULL, NULL) != ptNoError)) errMsg = Str(" *** error initialising PortTime"); } if (errMsg == NULL) portmidi_init_cnt++; #if !defined(WIN32) csoundUnLock(); #endif if (UNLIKELY(errMsg != NULL)) { csound->ErrorMsg(csound, "%s", Str(errMsg)); return -1; } //#if !defined(WIN32) //csound_global_mutex_unlock(); //#endif return csound->RegisterResetCallback(csound, NULL, stop_portmidi); } static int listDevices(CSOUND *csound, CS_MIDIDEVICE *list, int isOutput){ int i, cnt; PmDeviceInfo *info; char tmp[64]; char *drv = (char*) (csound->QueryGlobalVariable(csound, "_RTMIDI")); if (UNLIKELY(start_portmidi(csound) != 0)) return 0; cnt = portMidi_getDeviceCount(isOutput); if (list == NULL) return cnt; for (i = 0; i < cnt; i++) { info = portMidi_getDeviceInfo(i, isOutput); if (info->name != NULL) strncpy(list[i].device_name, info->name, 63); snprintf(tmp, 64, "%d", i); strncpy(list[i].device_id, tmp, 63); list[i].isOutput = isOutput; if (info->interf != NULL) strncpy(list[i].interface_name, info->interf, 63); else strcpy(list[i].interface_name, ""); strncpy(list[i].midi_module, drv, 63); } return cnt; } static void portMidi_listDevices(CSOUND *csound, int output) { int i,n = listDevices(csound, NULL, output); CS_MIDIDEVICE *devs = (CS_MIDIDEVICE *) csound->Malloc(csound, n*sizeof(CS_MIDIDEVICE)); listDevices(csound, devs, output); for(i=0; i < n; i++) csound->Message(csound, "%s: %s (%s)\n", devs[i].device_id, devs[i].device_name, devs[i].midi_module); csound->Free(csound, devs); } static int OpenMidiInDevice_(CSOUND *csound, void **userData, const char *dev) { int cntdev, devnum, opendevs, i; PmEvent buffer; PmError retval; PmDeviceInfo *info; // PortMidiStream *midistream; pmall_data *data = NULL; pmall_data *next = NULL; if (UNLIKELY(start_portmidi(csound) != 0)) return -1; /* check if there are any devices available */ cntdev = portMidi_getDeviceCount(0); portMidi_listDevices(csound, 0); /* look up device in list */ if (dev == NULL || dev[0] == '\0') devnum = portMidi_getPackedDeviceID((int)Pm_GetDefaultInputDeviceID(), 0); else if (UNLIKELY((dev[0] < '0' || dev[0] > '9') && dev[0] != 'a')) { portMidiErrMsg(csound, Str("error: must specify a device number (>=0) or" " 'a' for all, not a name")); return -1; } else if (dev[0] != 'a') { devnum = (int)atoi(dev); if (UNLIKELY(devnum < 0 || devnum >= cntdev)) { portMidiErrMsg(csound, Str("error: device number is out of range")); return -1; } } else { // allow to proceed if 'a' is given even if there are no MIDI devices devnum = -1; } if (UNLIKELY(cntdev < 1 && (dev==NULL || dev[0] != 'a'))) { return portMidiErrMsg(csound, Str("no input devices are available")); } opendevs = 0; for (i = 0; i < cntdev; i++) { if (devnum == i || devnum == -1) { if (opendevs == 0) { data = (pmall_data *) csound->Malloc(csound, sizeof(pmall_data)); next = data; data->next = NULL; opendevs++; } else { next->next = (pmall_data *) csound->Malloc(csound, sizeof(pmall_data)); next = next->next; next->next = NULL; opendevs++; } info = portMidi_getDeviceInfo(i, 0); if (info->interf != NULL) csound->Message(csound, Str("PortMIDI: Activated input device %d: '%s' (%s)\n"), i, info->name, info->interf); else csound->Message(csound, Str("PortMIDI: Activated input device %d: '%s'\n"), i, info->name); retval = Pm_OpenInput(&next->midistream, (PmDeviceID) portMidi_getRealDeviceID(i, 0), NULL, 512L, (PmTimeProcPtr) NULL, NULL); if (UNLIKELY(retval != pmNoError)) { // Prevent leaking memory from "data" if (data) { next = data->next; csound->Free(csound, data); } return portMidiErrMsg(csound, Str("error opening input device %d: %s"), i, Pm_GetErrorText(retval)); } /* only interested in channel messages (note on, control change, etc.) */ /* GAB: fixed for portmidi v.23Aug06 */ Pm_SetFilter(next->midistream, (PM_FILT_ACTIVE | PM_FILT_SYSEX)); /* empty the buffer after setting filter */ while (Pm_Poll(next->midistream) == TRUE) { Pm_Read(next->midistream, &buffer, 1); } } } *userData = (void*) data; /* report success */ return 0; } static int OpenMidiOutDevice_(CSOUND *csound, void **userData, const char *dev) { int cntdev, devnum; PmError retval; PmDeviceInfo *info; PortMidiStream *midistream; if (UNLIKELY(start_portmidi(csound) != 0)) return -1; /* check if there are any devices available */ cntdev = portMidi_getDeviceCount(1); if (UNLIKELY(cntdev < 1)) { return portMidiErrMsg(csound, Str("no output devices are available")); } /* look up device in list */ portMidi_listDevices(csound, 1); if (dev == NULL || dev[0] == '\0') devnum = portMidi_getPackedDeviceID((int)Pm_GetDefaultOutputDeviceID(), 1); else if (UNLIKELY(dev[0] < '0' || dev[0] > '9')) { portMidiErrMsg(csound, Str("error: must specify a device number (>=0), " "not a name")); return -1; } else devnum = (int)atoi(dev); if (UNLIKELY(devnum < 0 || devnum >= cntdev)) { portMidiErrMsg(csound, Str("error: device number is out of range")); return -1; } info = portMidi_getDeviceInfo(devnum, 1); if (info->interf != NULL) csound->Message(csound, Str("PortMIDI: selected output device %d: '%s' (%s)\n"), devnum, info->name, info->interf); else csound->Message(csound, Str("PortMIDI: selected output device %d: '%s'\n"), devnum, info->name); retval = Pm_OpenOutput(&midistream, (PmDeviceID) portMidi_getRealDeviceID(devnum, 1), NULL, 512L, (PmTimeProcPtr) NULL, NULL, 0L); if (UNLIKELY(retval != pmNoError)) { return portMidiErrMsg(csound, Str("error opening output device %d: %s"), devnum, Pm_GetErrorText(retval)); } *userData = (void*) midistream; /* report success */ return 0; } static int ReadMidiData_(CSOUND *csound, void *userData, unsigned char *mbuf, int nbytes) { int n, retval, st, d1, d2; PmEvent mev; pmall_data *data; /* * Reads from MIDI input device linked list. */ n = 0; data = (pmall_data *)userData; while (data) { retval = Pm_Poll(data->midistream); if (retval != FALSE) { if (UNLIKELY(retval < 0)) return portMidiErrMsg(csound, Str("error polling input device")); while ((retval = Pm_Read(data->midistream, &mev, 1L)) > 0) { st = (int)Pm_MessageStatus(mev.message); d1 = (int)Pm_MessageData1(mev.message); d2 = (int)Pm_MessageData2(mev.message); /* unknown message or sysex data: ignore */ if (UNLIKELY(st < 0x80)) continue; /* ignore most system messages */ if (UNLIKELY(st >= 0xF0 && !(st == 0xF8 || st == 0xFA || st == 0xFB || st == 0xFC || st == 0xFF))) continue; nbytes -= (datbyts[(st - 0x80) >> 4] + 1); if (UNLIKELY(nbytes < 0)) { portMidiErrMsg(csound, Str("buffer overflow in MIDI input")); break; } /* channel messages */ n += (datbyts[(st - 0x80) >> 4] + 1); switch (datbyts[(st - 0x80) >> 4]) { case 0: *mbuf++ = (unsigned char) st; break; case 1: *mbuf++ = (unsigned char) st; *mbuf++ = (unsigned char) d1; break; case 2: *mbuf++ = (unsigned char) st; *mbuf++ = (unsigned char) d1; *mbuf++ = (unsigned char) d2; break; } } if (UNLIKELY(retval < 0)) { portMidiErrMsg(csound, Str("read error %d"), retval); if (n < 1) n = -1; } } data = data->next; } /* return the number of bytes read */ return n; } static int WriteMidiData_(CSOUND *csound, void *userData, const unsigned char *mbuf, int nbytes) { int n, st; PmEvent mev; PortMidiStream *midistream; /* * Writes to user-defined MIDI output. */ midistream = (PortMidiStream*) userData; if (UNLIKELY(nbytes < 1)) return 0; n = 0; do { //int time = csound->GetCurrentTimeSamples(csound)/csound->GetSr(csound); //printf("jitter: %d \n", // Pt_Time(NULL) - (int)(1000*time/csound->GetSr(csound))); st = (int)*(mbuf++); if (UNLIKELY(st < 0x80)) { portMidiErrMsg(csound, Str("invalid MIDI out data")); break; } if (UNLIKELY(st >= 0xF0 && st < 0xF8)) { portMidiErrMsg(csound, Str("MIDI out: system message 0x%02X is not supported"), (unsigned int) st); break; } nbytes -= (datbyts[(st - 0x80) >> 4] + 1); if (UNLIKELY(nbytes < 0)) { portMidiErrMsg(csound, Str("MIDI out: truncated message")); break; } mev.message = (PmMessage) 0; mev.timestamp = (PmTimestamp) 0; mev.message |= (PmMessage) Pm_Message(st, 0, 0); if (datbyts[(st - 0x80) >> 4] > 0) mev.message |= (PmMessage) Pm_Message(0, (int)*(mbuf++), 0); if (datbyts[(st - 0x80) >> 4] > 1) mev.message |= (PmMessage) Pm_Message(0, 0, (int)*(mbuf++)); if (UNLIKELY(Pm_Write(midistream, &mev, 1L) != pmNoError)) portMidiErrMsg(csound, Str("MIDI out: error writing message")); else { n += (datbyts[(st - 0x80) >> 4] + 1); } } while (nbytes > 0); /* return the number of bytes written */ return n; } static int CloseMidiInDevice_(CSOUND *csound, void *userData) { PmError retval; pmall_data* data = (pmall_data*) userData; while (data) { retval = Pm_Close(data->midistream); if (UNLIKELY(retval != pmNoError)) { return portMidiErrMsg(csound, Str("error closing input device")); } pmall_data* olddata; olddata = data; data = data->next; csound->Free(csound, olddata); } return 0; } static int CloseMidiOutDevice_(CSOUND *csound, void *userData) { PmError retval; if (userData != NULL) { retval = Pm_Close((PortMidiStream*) userData); if (UNLIKELY(retval != pmNoError)) { return portMidiErrMsg(csound, Str("error closing output device")); } } return 0; } /* module interface functions */ PUBLIC int csoundModuleCreate(CSOUND *csound) { /* nothing to do, report success */ // csound->Message(csound, Str("PortMIDI real time MIDI plugin for Csound\n")); return 0; } PUBLIC int csoundModuleInit(CSOUND *csound) { char *drv; csound->module_list_add(csound, "portmidi", "midi"); drv = (char*) (csound->QueryGlobalVariable(csound, "_RTMIDI")); if (drv == NULL) return 0; if (!(strcmp(drv, "portmidi") == 0 || strcmp(drv, "PortMidi") == 0 || strcmp(drv, "PortMIDI") == 0 || strcmp(drv, "pm") == 0)) return 0; csound->Message(csound, Str("rtmidi: PortMIDI module enabled\n")); csound->SetExternalMidiInOpenCallback(csound, OpenMidiInDevice_); csound->SetExternalMidiReadCallback(csound, ReadMidiData_); csound->SetExternalMidiInCloseCallback(csound, CloseMidiInDevice_); csound->SetExternalMidiOutOpenCallback(csound, OpenMidiOutDevice_); csound->SetExternalMidiWriteCallback(csound, WriteMidiData_); csound->SetExternalMidiOutCloseCallback(csound, CloseMidiOutDevice_); csound->SetMIDIDeviceListCallback(csound,listDevices); return 0; } PUBLIC int csoundModuleDestroy(CSOUND *csound) { return 0; } PUBLIC int csoundModuleInfo(void) { /* does not depend on MYFLT type */ return ((CS_APIVERSION << 16) + (CS_APISUBVER << 8)); } csound-6.10.0/InOut/rtalsa.c000066400000000000000000001735511321653344700156050ustar00rootroot00000000000000/* rtalsa.c: Copyright (C) 2005 Istvan Varga (C) 2009 Andrés Cabrera, Clemens Ladisch (C) 2012 Tito Latini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _ISOC99_SOURCE #define _ISOC99_SOURCE 1 #endif #ifndef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 200112L #endif #ifndef _DEFAULT_SOURCE #define _DEFAULT_SOURCE 1 #endif /* _BSD_SOURCE definition can be dropped once support for glibc < 2.19 is dropped */ #ifndef _BSD_SOURCE #define _BSD_SOURCE 1 #endif #include "csdl.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "soundio.h" typedef struct devparams_ { snd_pcm_t *handle; /* handle */ void *buf; /* sample conversion buffer */ char *device; /* device name */ int format; /* sample format */ int sampleSize; /* MYFLT sample frame size in bytes */ uint32_t srate; /* sample rate in Hz */ int nchns; /* number of channels */ int buffer_smps; /* buffer length in samples */ int period_smps; /* period time in samples */ /* playback sample conversion function */ void (*playconv)(int, MYFLT *, void *, int *); /* record sample conversion function */ void (*rec_conv)(int, void *, MYFLT *); int seed; /* random seed for dithering */ } DEVPARAMS; #ifdef BUF_SIZE #undef BUF_SIZE #endif #define BUF_SIZE 4096 typedef struct alsaMidiInputDevice_ { unsigned char buf[BUF_SIZE]; snd_rawmidi_t *dev; int bufpos, nbytes, datreq; unsigned char prvStatus, dat1, dat2; struct alsaMidiInputDevice_ *next; } alsaMidiInputDevice; typedef struct midiDevFile_ { unsigned char buf[BUF_SIZE]; int fd; int bufpos, nbytes, datreq; unsigned char prvStatus, dat1, dat2; } midiDevFile; typedef struct alsaseqMidi_ { snd_seq_t *seq; snd_midi_event_t *mev; snd_seq_event_t sev; snd_seq_client_info_t *cinfo; snd_seq_port_info_t *pinfo; } alsaseqMidi; static const unsigned char dataBytes[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 2, 0 }; int set_scheduler_priority(CSOUND *csound, int priority) { struct sched_param p; memset(&p, 0, sizeof(struct sched_param)); if (UNLIKELY(priority < -20 || priority > sched_get_priority_max(SCHED_RR))) { csound->Message(csound, Str("--scheduler: invalid priority value; " "the allowed range is:")); csound->Message(csound,Str(" -20 to -1: set nice level")); csound->Message(csound,Str(" 0: normal scheduling, " "but lock memory")); csound->Message(csound,Str(" 1 to %d: SCHED_RR with the specified " "priority (DANGEROUS)"), sched_get_priority_max(SCHED_RR)); return -1; } /* set scheduling policy and priority */ if (priority > 0) { p.sched_priority = priority; if (UNLIKELY(sched_setscheduler(0, SCHED_RR, &p) != 0)) { csound->Message(csound, Str("csound: cannot set scheduling policy to SCHED_RR")); } else csound->Message(csound, Str("csound: setting scheduling policy to SCHED_RR\n")); } else { /* nice requested */ if (UNLIKELY(setpriority(PRIO_PROCESS, 0, priority) != 0)) { csound->Message(csound, Str("csound: cannot set nice level to %d"), priority); } } return 0; } /* sample conversion routines for playback */ static void MYFLT_to_short(int nSmps, MYFLT *inBuf, int16_t *outBuf, int *seed) { MYFLT tmp_f; int tmp_i; int n; for (n=0; n>1) - 0x8000) * (FL(1.0) / (MYFLT) 0x10000); tmp_f += inBuf[n] * (MYFLT) 0x8000; #ifndef USE_DOUBLE tmp_i = (int) lrintf(tmp_f); #else tmp_i = (int) lrint(tmp_f); #endif if (tmp_i < -0x8000) tmp_i = -0x8000; if (tmp_i > 0x7FFF) tmp_i = 0x7FFF; outBuf[n] = (int16_t) tmp_i; } } static void MYFLT_to_short_u(int nSmps, MYFLT *inBuf, int16_t *outBuf, int *seed) { MYFLT tmp_f; int tmp_i; int n; for (n=0; n 0x7FFF) tmp_i = 0x7FFF; outBuf[n] = (int16_t) tmp_i; } } static void MYFLT_to_short_no_dither(int nSmps, MYFLT *inBuf, int16_t *outBuf, int *seed) { MYFLT tmp_f; int tmp_i; int n; for (n=0; n 0x7FFF) tmp_i = 0x7FFF; outBuf[n] = (int16_t) tmp_i; } } static void MYFLT_to_long(int nSmps, MYFLT *inBuf, int32_t *outBuf, int *seed) { MYFLT tmp_f; int64_t tmp_i; (void) seed; int n; for (n=0; n (int64_t) 0x7FFFFFFF) tmp_i = (int64_t) 0x7FFFFFFF; outBuf[n] = (int32_t) tmp_i; } } static void MYFLT_to_float(int nSmps, MYFLT *inBuf, float *outBuf, int *seed) { (void) seed; int n; for (n=0; nQueryGlobalVariable(csound, "_DAC_CHANNELS_"); if (dachans == NULL) { if (csound->CreateGlobalVariable(csound, "_DAC_CHANNELS_", sizeof(int)) != 0) return; dachans = (int *) csound->QueryGlobalVariable(csound, "_DAC_CHANNELS_"); *dachans = chans; } } static void ADC_channels(CSOUND *csound, int chans){ int *dachans = (int *) csound->QueryGlobalVariable(csound, "_ADC_CHANNELS_"); if (dachans == NULL) { if (csound->CreateGlobalVariable(csound, "_ADC_CHANNELS_", sizeof(int)) != 0) return; dachans = (int *) csound->QueryGlobalVariable(csound, "_ADC_CHANNELS_"); *dachans = chans; } } /* set up audio device */ #define MSGLEN (512) static int set_device_params(CSOUND *csound, DEVPARAMS *dev, int play) { snd_pcm_hw_params_t *hw_params; snd_pcm_sw_params_t *sw_params; snd_pcm_format_t alsaFmt; int err, n, alloc_smps; CSOUND *p = csound; char *devName, msg[MSGLEN]; dev->buf = NULL; snd_pcm_hw_params_alloca(&hw_params); snd_pcm_sw_params_alloca(&sw_params); /* open the device */ if (dev->device == NULL || dev->device[0] == '\0') devName = "default"; else devName = dev->device; err = snd_pcm_open(&(dev->handle), devName, (play ? SND_PCM_STREAM_PLAYBACK : SND_PCM_STREAM_CAPTURE), 0); if (UNLIKELY(err < 0)) { if (play) p->ErrorMsg(p, Str(" *** Cannot open device '%s' for audio output: %s"), devName, snd_strerror(err)); else p->ErrorMsg(p, Str(" *** Cannot open device '%s' for audio input: %s"), devName, snd_strerror(err)); return -1; } /* allocate hardware and software parameters */ if (UNLIKELY(snd_pcm_hw_params_any(dev->handle, hw_params) < 0)) { strncpy(msg, Str("No real-time audio configurations found"), MSGLEN); goto err_return_msg; } /*=======================*/ unsigned int hwchns; if (UNLIKELY(snd_pcm_hw_params_get_channels_max(hw_params, &hwchns) < 0)) { strncpy(msg, Str("Could not retrieve max number of channels"), MSGLEN); goto err_return_msg; } if(play) { DAC_channels(csound,hwchns); } else ADC_channels(csound,hwchns); /*=========================*/ /* now set the various hardware parameters: */ /* access method, */ if (UNLIKELY(snd_pcm_hw_params_set_access(dev->handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0)) { strncpy(msg, Str("Error setting access type for soundcard"), MSGLEN); goto err_return_msg; } /* sample format, */ alsaFmt = SND_PCM_FORMAT_UNKNOWN; dev->sampleSize = (int) sizeof(MYFLT) * dev->nchns; { void (*fp)(void) = NULL; alsaFmt = set_format(&fp, dev->format, play, csound->GetDitherMode(csound)); if (play) dev->playconv = (void (*)(int, MYFLT*, void*, int*)) fp; else dev->rec_conv = (void (*)(int, void*, MYFLT*)) fp; } if (UNLIKELY(alsaFmt == SND_PCM_FORMAT_UNKNOWN)) { strncpy(msg, Str("Unknown sample format.\n *** Only 16-bit and 32-bit " "integers, and 32-bit floats are supported."), MSGLEN); goto err_return_msg; } if (UNLIKELY(snd_pcm_hw_params_set_format(dev->handle, hw_params, alsaFmt)<0)) { strncpy(msg, Str("Unable to set requested sample format on soundcard"),MSGLEN); goto err_return_msg; } /* number of channels, */ if (UNLIKELY(snd_pcm_hw_params_set_channels(dev->handle, hw_params, (unsigned int) dev->nchns) < 0)) { strncpy(msg, Str("Unable to set number of channels on soundcard"), MSGLEN); goto err_return_msg; } /* sample rate, (patched for sound cards that object to fixed rate) */ { unsigned int target = dev->srate; if (UNLIKELY(snd_pcm_hw_params_set_rate_near(dev->handle, hw_params, (unsigned int *) &dev->srate, 0) < 0)) { strncpy(msg, Str("Unable to set sample rate on soundcard"), MSGLEN); goto err_return_msg; } if (dev->srate!=target) p->MessageS(p, CSOUNDMSG_WARNING, Str(" *** rate set to %d\n"), dev->srate); } /* buffer size, */ if (dev->buffer_smps == 0) dev->buffer_smps = 1024; else if (dev->buffer_smps < 16) dev->buffer_smps = 16; { snd_pcm_uframes_t nn = (snd_pcm_uframes_t) dev->buffer_smps; err = snd_pcm_hw_params_set_buffer_size_near(dev->handle, hw_params, &nn); if (err < 0 || (int) nn != dev->buffer_smps) { if (UNLIKELY(err >= 0)) { p->Message(p, Str("ALSA: -B %d not allowed on this device; " "using %d instead\n"), dev->buffer_smps, (int) nn); dev->buffer_smps=nn; } } } /* and period size */ alloc_smps = dev->period_smps; if (dev->period_smps == 0) dev->period_smps = 256; else if (dev->period_smps < 8) dev->period_smps = 8; else if (dev->period_smps > (dev->buffer_smps >> 1)) dev->period_smps = (dev->buffer_smps >> 1); if (alloc_smps < dev->period_smps) /* make sure that enough memory */ alloc_smps = dev->period_smps; /* is allocated for the buffer */ { snd_pcm_uframes_t nn = (snd_pcm_uframes_t) dev->period_smps; int dir = 0; err = snd_pcm_hw_params_set_period_size_near(dev->handle, hw_params, &nn, &dir); if (err < 0 || (int) nn != dev->period_smps) { if (UNLIKELY(err >= 0)) { p->Message(p, Str("ALSA: -b %d not allowed on this device; " "using %d instead\n"), dev->period_smps, (int) nn); dev->period_smps=nn; } } } /* set up device according to the above parameters */ if (UNLIKELY(snd_pcm_hw_params(dev->handle, hw_params) < 0)) { strncpy(msg, Str("Error setting hardware parameters for real-time audio"), MSGLEN); goto err_return_msg; } /* print settings */ if (p->GetMessageLevel(p) != 0) p->Message(p, Str("ALSA %s: total buffer size: %d, period size: %d \n"), (play ? "output" : "input"), dev->buffer_smps, dev->period_smps /*, dev->srate*/); /* now set software parameters */ n = (play ? dev->buffer_smps : 1); if (UNLIKELY(snd_pcm_sw_params_current(dev->handle, sw_params) < 0 || snd_pcm_sw_params_set_start_threshold(dev->handle, sw_params, (snd_pcm_uframes_t) n) < 0 || snd_pcm_sw_params_set_avail_min(dev->handle, sw_params, dev->period_smps) < 0 || /* snd_pcm_sw_params_set_xfer_align(dev->handle, sw_params, 1) < 0 || */ snd_pcm_sw_params(dev->handle, sw_params) < 0)) { strncpy(msg, Str("Error setting software parameters for real-time audio"),MSGLEN); goto err_return_msg; } /* allocate memory for sample conversion buffer */ n = (dev->format == AE_SHORT ? 2 : 4) * dev->nchns * alloc_smps; dev->buf = (void*) csound->Malloc(csound, (size_t) n); if (UNLIKELY(dev->buf == NULL)) { strncpy(msg, Str("Memory allocation failure"),MSGLEN); goto err_return_msg; } memset(dev->buf, 0, (size_t) n); /* device successfully opened */ return 0; err_return_msg: p->MessageS(p, CSOUNDMSG_ERROR, " *** %s\n", msg); snd_pcm_close(dev->handle); return -1; } static void list_devices(CSOUND *csound) { FILE * f = fopen("/proc/asound/pcm", "r"); /*file presents this format: 02-00: Analog PCM : Mona : playback 6 : capture 4*/ char *line, *line_; line = (char *) csound->Calloc (csound, 128* sizeof(char)); line_ = (char *) csound->Calloc (csound, 128* sizeof(char)); char card_[] = " "; char num_[] = " "; char *temp; if (f) { char *th; while (fgets(line, 128, f)) { /* Read one line*/ strcpy(line_, line); temp = strtok_r (line, "-", &th); strncpy (card_, temp, 2); temp = strtok_r (NULL, ":", &th); strncpy (num_, temp, 2); int card = atoi (card_); int num = atoi (num_); temp = strchr (line_, ':'); if (temp) temp = temp + 2; /* name contains spaces at the beginning and the end. And line return at the end*/ csound->Message(csound, " \"hw:%i,%i\" - %s",card, num, temp ); } fclose(f); } csound->Free(csound, line); csound->Free(csound, line_); } int listDevices(CSOUND *csound, CS_AUDIODEVICE *list, int isOutput){ FILE * f = fopen("/proc/asound/pcm", "r"); /*file presents this format: 02-00: Analog PCM : Mona : playback 6 : capture 4*/ char line[128], line_[128]; char card_[] = " "; char num_[] = " "; char *temp; char tmp[64]; int n =0; memset(line, '\0', 128); memset(line_, '\0', 128); if (f) { char *th; while (fgets(line, 128, f)) { /* Read one line*/ strcpy(line_, line); temp = strtok_r (line, "-", &th); if (temp==NULL) { fclose(f); return 0; } strncpy (card_, temp, 2); temp = strtok_r (NULL, ":", &th); if (temp==NULL) { fclose(f); return 0; } strncpy (num_, temp, 2); int card = atoi (card_); int num = atoi (num_); temp = strchr (line_, ':'); if (temp) { temp = temp + 2; } else { fclose(f); return 0; } if (list != NULL) { /* for some reason, there appears to be a memory problem if we try to copy more than 10 chars, even though list[n].device_name is 64 chars long */ strncpy(list[n].device_name, temp, 10); list[n].device_name[10] = '\0'; snprintf(tmp, 64, "%shw:%i,%i", isOutput ? "dac:" : "adc:", card, num); strncpy(list[n].device_id, tmp, 16); list[n].max_nchnls = -1; list[n].isOutput = isOutput; } n++; } fclose(f); } return n; } static int open_device(CSOUND *csound, const csRtAudioParams *parm, int play) { DEVPARAMS *dev; void **userDataPtr; int retval; userDataPtr = (play ? (void**) csound->GetRtPlayUserData(csound) : (void**) csound->GetRtRecordUserData(csound)); /* check if the device is already opened */ if (*userDataPtr != NULL) return 0; if (UNLIKELY(parm->devNum != 1024)) { csound->ErrorMsg(csound, Str(" *** ALSA: must specify a device name, " "not a number (e.g. -odac:hw:0,0)")); list_devices(csound); return -1; } /* allocate structure */ dev = (DEVPARAMS*) csound->Malloc(csound, sizeof(DEVPARAMS)); if (UNLIKELY(dev == NULL)) { csound->ErrorMsg(csound, Str(" *** ALSA: %s: memory allocation failure"), (play ? "playopen" : "recopen")); return -1; } *userDataPtr = (void*) dev; memset(dev, 0, sizeof(DEVPARAMS)); /* set up parameters */ dev->handle = (snd_pcm_t*) NULL; dev->buf = NULL; dev->device = parm->devName; dev->format = parm->sampleFormat; dev->sampleSize = 1; dev->srate = (int) (parm->sampleRate + 0.5f); dev->nchns = parm->nChannels; dev->buffer_smps = parm->bufSamp_HW; dev->period_smps = parm->bufSamp_SW; dev->playconv = (void (*)(int, MYFLT*, void*, int*)) NULL; dev->rec_conv = (void (*)(int, void*, MYFLT*)) NULL; dev->seed = 1; /* open device */ retval = set_device_params(csound, dev, play); if (retval != 0) { csound->Free(csound,dev); *userDataPtr = NULL; } return retval; } /* open for audio input */ static int recopen_(CSOUND *csound, const csRtAudioParams *parm) { return open_device(csound, parm, 0); } /* open for audio output */ static int playopen_(CSOUND *csound, const csRtAudioParams *parm) { return open_device(csound, parm, 1); } /* get samples from ADC */ #ifdef warning #undef warning #endif #define warning(x) { \ if (UNLIKELY(csound->GetMessageLevel(csound) & 4)) \ csound->Warning(csound, Str(x)); \ } static int rtrecord_(CSOUND *csound, MYFLT *inbuf, int nbytes) { DEVPARAMS *dev; int n, m, err; dev = (DEVPARAMS*) *(csound->GetRtRecordUserData(csound)); if (dev->handle == NULL) { /* no device, return zero samples */ memset(inbuf, 0, (size_t) nbytes); return nbytes; } /* calculate the number of samples to record */ n = nbytes / dev->sampleSize; m = 0; while (n) { err = (int) snd_pcm_readi(dev->handle, dev->buf, (snd_pcm_uframes_t) n); if (err >= 0) { n -= err; m += err; continue; } /* handle I/O errors */ if (UNLIKELY(err == -EPIPE)) { /* buffer underrun */ warning(Str("Buffer overrun in real-time audio input")); /* complain */ if (snd_pcm_prepare(dev->handle) >= 0) continue; } else if (err == -ESTRPIPE) { /* suspend */ warning(Str("Real-time audio input suspended")); while (snd_pcm_resume(dev->handle) == -EAGAIN) sleep(1); if (snd_pcm_prepare(dev->handle) >= 0) continue; } /* could not recover from error */ csound->ErrorMsg(csound, Str("Error reading data from audio input device")); snd_pcm_close(dev->handle); dev->handle = NULL; break; } /* convert samples to MYFLT */ dev->rec_conv(m * dev->nchns, dev->buf, inbuf); return (m * dev->sampleSize); } /* put samples to DAC */ static void rtplay_(CSOUND *csound, const MYFLT *outbuf, int nbytes) { DEVPARAMS *dev; int n, err; dev = (DEVPARAMS*) *(csound->GetRtPlayUserData(csound)); if (dev->handle == NULL) return; /* calculate the number of samples to play */ n = nbytes / dev->sampleSize; /* convert samples from MYFLT */ dev->playconv(n * dev->nchns, (MYFLT*) outbuf, dev->buf, &(dev->seed)); while (n) { err = (int) snd_pcm_writei(dev->handle, dev->buf, (snd_pcm_uframes_t) n); if (err >= 0) { n -= err; continue; } /* handle I/O errors */ if (err == -EPIPE) { /* buffer underrun */ warning(Str("Buffer underrun in real-time audio output")); /* complain */ if (snd_pcm_prepare(dev->handle) >= 0) continue; } else if (err == -ESTRPIPE) { /* suspend */ warning(Str("Real-time audio output suspended")); while (snd_pcm_resume(dev->handle) == -EAGAIN) sleep(1); if (snd_pcm_prepare(dev->handle) >= 0) continue; } /* could not recover from error */ csound->ErrorMsg(csound, Str("Error writing data to audio output device")); snd_pcm_close(dev->handle); dev->handle = NULL; break; } } /* close the I/O device entirely */ /* called only when both complete */ static void rtclose_(CSOUND *csound) { DEVPARAMS *dev; dev = (DEVPARAMS*) (*(csound->GetRtRecordUserData(csound))); if (dev != NULL) { *(csound->GetRtRecordUserData(csound)) = NULL; if (dev->handle != NULL) snd_pcm_close(dev->handle); if (dev->buf != NULL) csound->Free(csound, dev->buf); csound->Free(csound,dev); } dev = (DEVPARAMS*) (*(csound->GetRtPlayUserData(csound))); if (dev != NULL) { *(csound->GetRtPlayUserData(csound)) = NULL; if (dev->handle != NULL) snd_pcm_close(dev->handle); if (dev->buf != NULL) csound->Free(csound, dev->buf); csound->Free(csound,dev); } } static alsaMidiInputDevice* open_midi_device(CSOUND *csound, const char *s) { int err; alsaMidiInputDevice *dev; dev = (alsaMidiInputDevice*) csound->Malloc(csound, sizeof(alsaMidiInputDevice)); if (UNLIKELY(dev == NULL)) { csound->ErrorMsg(csound, Str("ALSA MIDI: memory allocation failure")); return dev; } memset(dev, 0, sizeof(alsaMidiInputDevice)); err = snd_rawmidi_open(&(dev->dev), NULL, s, SND_RAWMIDI_NONBLOCK); if (UNLIKELY(err != 0)) { csound->ErrorMsg(csound, Str("ALSA: error opening MIDI input device: '%s'"), s); csound->Free(csound,dev); return NULL; } csound->Message(csound, Str("ALSA: opened MIDI input device '%s'\n"), s); return dev; } // This is the function which contains code from amidi static int midi_in_open(CSOUND *csound, void **userData, const char *devName) { alsaMidiInputDevice *dev = NULL, *newdev, *olddev; //const char *s = "hw:0,0"; int card; int device; snd_ctl_t *ctl; char* name; int numdevs = 0; name = (char *) csound->Calloc(csound, 32* sizeof(char)); (*userData) = NULL; olddev = NULL; if (UNLIKELY(devName==NULL)) { csound->Message(csound, Str("ALSA midi: no string\n")); exit(1); /* what should happen here???????? */ } else if (devName[0] == 'a') { csound->Message(csound, Str("ALSA midi: Using all devices.\n")); card = -1; if (snd_card_next(&card) >= 0 && card >= 0) { do { snprintf(name, 32, "hw:%d", card); if (snd_ctl_open(&ctl, name, 0) >= 0) { device = -1; for (;;) { if (snd_ctl_rawmidi_next_device(ctl, &device) < 0) { break; } if (device < 0) { break; } snprintf(name, 32, "hw:%d,%d", card, device); newdev = open_midi_device(csound, name); if (LIKELY(newdev != NULL)) { /* Device opened successfully */ numdevs++; if (olddev != NULL) { olddev->next = newdev; } else { /* First Device */ dev = newdev; } olddev = newdev; newdev = NULL; } else { /* Device couldn't be opened */ csound->Message(csound, Str("ALSA midi: Error opening device: %s\n"), name); } } } if (snd_card_next(&card) < 0) break; } while (card >= 0); snd_ctl_close(ctl); } } else if (devName[0] != '\0') { dev = open_midi_device(csound, devName); if (dev == NULL) { csound->Free(csound, name); return -1; } numdevs = 1; } csound->Free(csound, name); if (UNLIKELY(numdevs == 0)) { csound->ErrorMsg(csound, Str("ALSA midi: No devices found.\n")); *userData = NULL; } else { *userData = (void*) dev; } return 0; } static int midi_in_read(CSOUND *csound, void *userData, unsigned char *buf, int nbytes) { alsaMidiInputDevice *dev = (alsaMidiInputDevice*) userData; int bufpos = 0; unsigned char c; if (!dev) { /* No devices */ /* fprintf(stderr, "No devices!"); */ return 0; } /* (void) csound; */ dev->bufpos = 0; while (dev && dev->dev) { while ((nbytes - bufpos) >= 3) { if (dev->bufpos >= dev->nbytes) { /* read from device */ int n = (int) snd_rawmidi_read(dev->dev, &(dev->buf[0]), BUF_SIZE); dev->bufpos = 0; if (n <= 0) { /* until there is no more data left */ dev->nbytes = 0; break; } dev->nbytes = n; } c = dev->buf[dev->bufpos++]; if (c >= (unsigned char) 0xF8) { /* real time message */ buf[bufpos++] = c; continue; } if (c == (unsigned char) 0xF7) /* end of system exclusive */ c = dev->prvStatus; if (c < (unsigned char) 0x80) { /* data byte */ if (dev->datreq <= 0) continue; if (dev->datreq == (int) dataBytes[(int) dev->prvStatus >> 4]) dev->dat1 = c; else dev->dat2 = c; if (--(dev->datreq) != 0) continue; dev->datreq = dataBytes[(int) dev->prvStatus >> 4]; buf[bufpos] = dev->prvStatus; buf[bufpos + 1] = dev->dat1; buf[bufpos + 2] = dev->dat2; bufpos += (dev->datreq + 1); continue; } else if (c < (unsigned char) 0xF0) { /* channel message */ dev->prvStatus = c; dev->datreq = dataBytes[(int) c >> 4]; continue; } if (c < (unsigned char) 0xF4) /* ignore system messages */ dev->datreq = -1; } dev = dev->next; } return bufpos; } static int midi_in_close(CSOUND *csound, void *userData) { int ret = 0, retval = 0; alsaMidiInputDevice *olddev, *dev = NULL; (void) csound; dev = (alsaMidiInputDevice*) userData; while (dev != NULL) { if (dev->dev) { ret = snd_rawmidi_close(dev->dev); } olddev = dev; dev = dev->next; csound->Free(csound,olddev); if (retval != -1) retval = ret; } return retval; } static int midi_out_open(CSOUND *csound, void **userData, const char *devName) { snd_rawmidi_t *dev = NULL; const char *s = "hw:0,0"; int err; (*userData) = NULL; if (devName != NULL && devName[0] != '\0') s = devName; err = snd_rawmidi_open(NULL, &dev, s, SND_RAWMIDI_NONBLOCK); if (err != 0) { csound->ErrorMsg(csound, Str("ALSA: error opening MIDI output device '%s'"),s); return 0; } csound->Message(csound, Str("ALSA: opened MIDI output device '%s'\n"), s); (*userData) = (void*) dev; return 0; } static int midi_out_write(CSOUND *csound, void *userData, const unsigned char *buf, int nbytes) { (void) csound; snd_rawmidi_write((snd_rawmidi_t*) userData, buf, (size_t) nbytes); /* snd_rawmidi_drain((snd_rawmidi_t*) userData); */ return nbytes; } static int midi_out_close(CSOUND *csound, void *userData) { int retval = 0; (void) csound; if (userData != NULL) { snd_rawmidi_drain((snd_rawmidi_t*) userData); retval = snd_rawmidi_close((snd_rawmidi_t*) userData); } return retval; } /* The following functions include code from Csound 4.23 (mididevice.c), */ /* written by John ffitch, David Ratajczak, and others. */ static int midi_in_open_file(CSOUND *csound, void **userData, const char *devName) { midiDevFile *dev; const char *s = "stdin"; (*userData) = NULL; dev = (midiDevFile*) csound->Calloc(csound, sizeof(midiDevFile)); if (devName != NULL && devName[0] != '\0') s = devName; if (strcmp(s, "stdin") == 0) { if (fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) | O_NDELAY) < 0) { csound->ErrorMsg(csound, Str("-M stdin fcntl failed")); return -1; } dev->fd = 0; } else { /* open MIDI device, & set nodelay on reads */ if ((dev->fd = open(s, O_RDONLY | O_NDELAY, 0)) < 0) { csound->ErrorMsg(csound, Str("cannot open %s"), s); return -1; } } if (isatty(dev->fd)) { struct termios tty; memset(&tty, 0, sizeof(struct termios)); if (tcgetattr(dev->fd, &tty) < 0) { if (dev->fd > 2) close(dev->fd); csound->ErrorMsg(csound, Str("MIDI receive: cannot get termios info.")); return -1; } cfmakeraw(&tty); if (cfsetispeed(&tty, EXTB) < 0) { if (dev->fd > 2) close(dev->fd); csound->ErrorMsg(csound, Str("MIDI receive: cannot set input baud rate.")); return -1; } if (tcsetattr(dev->fd, TCSANOW, &tty) < 0) { if (dev->fd > 2) close(dev->fd); csound->ErrorMsg(csound, Str("MIDI receive: cannot set termios.")); return -1; } } csound->Message(csound, Str("Opened MIDI input device file '%s'\n"), s); (*userData) = (void*) dev; return 0; } static int midi_in_read_file(CSOUND *csound, void *userData, unsigned char *buf, int nbytes) { midiDevFile *dev = (midiDevFile*) userData; int bufpos = 0; unsigned char c; while ((nbytes - bufpos) >= 3) { if (dev->bufpos >= dev->nbytes) { /* read from device */ /* For select() call, from David Ratajczak */ fd_set rfds; struct timeval tv; int n; dev->bufpos = 0; dev->nbytes = 0; /******** NEW STUFF **********/ /* from David Ratajczak */ /* Use select() to make truly */ /* non-blocking call to midi */ /******************************/ /* Watch rtfd to see when it has input. */ FD_ZERO(&rfds); FD_SET(dev->fd, &rfds); /* return immediately */ tv.tv_sec = 0; tv.tv_usec = 0; n = select(dev->fd + 1, &rfds, NULL, NULL, &tv); /* Don't rely on the value of tv now! */ if (n) { if (n < 0) csound->ErrorMsg(csound, Str("sensMIDI: retval errno %d"), errno); else n = read(dev->fd, &(dev->buf[0]), BUF_SIZE); } if (n > 0) dev->nbytes = n; else break; /* until there is no more data left */ } c = dev->buf[dev->bufpos++]; if (c >= (unsigned char) 0xF8) { /* real time message */ buf[bufpos++] = c; continue; } if (c == (unsigned char) 0xF7) /* end of system exclusive */ c = dev->prvStatus; if (c < (unsigned char) 0x80) { /* data byte */ if (dev->datreq <= 0) continue; if (dev->datreq == (int) dataBytes[(int) dev->prvStatus >> 4]) dev->dat1 = c; else dev->dat2 = c; if (--(dev->datreq) != 0) continue; dev->datreq = dataBytes[(int) dev->prvStatus >> 4]; buf[bufpos] = dev->prvStatus; buf[bufpos + 1] = dev->dat1; buf[bufpos + 2] = dev->dat2; bufpos += (dev->datreq + 1); continue; } else if (c < (unsigned char) 0xF0) { /* channel message */ dev->prvStatus = c; dev->datreq = dataBytes[(int) c >> 4]; continue; } if (c < (unsigned char) 0xF4) /* ignore system messages */ dev->datreq = -1; } return bufpos; } static int midi_in_close_file(CSOUND *csound, void *userData) { int retval = 0; if (userData != NULL) { int fd = ((midiDevFile*) userData)->fd; if (fd > 2) retval = close(fd); csound->Free(csound, userData); } return retval; } static int midi_out_open_file(CSOUND *csound, void **userData, const char *devName) { int fd = 1; /* stdout */ (*userData) = NULL; if (devName != NULL && devName[0] != '\0' && strcmp(devName, "stdout") != 0) { fd = open(devName, O_WRONLY); if (fd < 0) { csound->ErrorMsg(csound, Str("Error opening MIDI output device file '%s'"), devName); return -1; } csound->Message(csound, Str("Opened MIDI output device file '%s'\n"), devName); } (*userData) = (void*) ((uintptr_t) fd); return 0; } static int midi_out_write_file(CSOUND *csound, void *userData, const unsigned char *buf, int nbytes) { int retval; (void) csound; retval = (int) write((int) ((uintptr_t) userData), buf, (size_t) nbytes); return retval; } static int midi_out_close_file(CSOUND *csound, void *userData) { int retval = 0; (void) csound; if (userData != NULL) { int fd = (int) ((uintptr_t) userData); if (fd > 2) retval = close(fd); } return retval; } /* ALSA MIDI Sequencer added by Tito Latini (2012) */ #define ALSASEQ_SYSEX_BUFFER_SIZE (1024) static int alsaseq_get_client_id(CSOUND *csound, alsaseqMidi *amidi, unsigned int capability, const char *name) { snd_seq_client_info_t *client_info = amidi->cinfo; snd_seq_port_info_t *port_info = amidi->pinfo; snd_seq_client_info_set_client(client_info, -1); while (snd_seq_query_next_client(amidi->seq, client_info) >= 0) { int client_id; if ((client_id = snd_seq_client_info_get_client(client_info)) < 0) break; snd_seq_port_info_set_client(port_info, client_id); snd_seq_port_info_set_port(port_info, -1); if (snd_seq_query_next_port(amidi->seq, port_info) < 0) break; if (snd_seq_port_info_get_capability(port_info) & capability) { char *client_name; client_name = (char*) snd_seq_client_info_get_name(client_info); if (strcmp(name, client_name) == 0) return client_id; } } return -1; } /* * my_strchr is a destructive version of strchr that removes the * escape characters '\' from the string s. If escape_all is zero, * '\' is removed only when it is the escape char for c. */ static char *my_strchr(const char *s, int c, int escape_all) { int refill, success = 0, escape = 0, changed = 0; char *old = (char*)s; for (refill = 1; *s != '\0'; s++) { if (*s == c) { if (escape) { escape = 0; refill = 1; } else { success = 1; break; } } else if (*s == '\\' || *s == 0x18) { /* * CAN char used to mark the escape character during the parsing * of CsOptions. It is useful only in parse_option_as_cfgvar. */ escape ^= 1; if (escape_all || *(s+1) == c) { refill = !escape; changed = 1; } } else if (escape) { escape = 0; refill = 1; } if (refill) { /* ETX char used to mark the limits of a string */ if (*s != 3 && *s != '\n') *old++ = (*s == 0x18 ? '\\' : *s); else changed = 1; } } if (changed) *old = '\0'; return (success ? (char*)s : NULL); } /* Searching for port number after ':' at the end of the string */ static int get_port_from_string(CSOUND *csound, char *str) { int port = 0; char *end, *tmp, *c = str; while (1) { c = my_strchr(c, ':', 1); if (c == NULL) break; tmp = c+1; port = strtol(tmp, &end, 10); if (*end == '\0') { *c = '\0'; break; } else { /* Not found, continue the search */ port = 0; c = tmp; } } return port; } static int alsaseq_connect(CSOUND *csound, alsaseqMidi *amidi, unsigned int capability, const char *addr_str) { snd_seq_addr_t addr; char *s, *client_spec, direction_str[5]; int (*amidi_connect)(snd_seq_t*, int, int, int); if (capability == SND_SEQ_PORT_CAP_READ) { strcpy(direction_str, "from"); amidi_connect = snd_seq_connect_from; } else { strcpy(direction_str, "to"); amidi_connect = snd_seq_connect_to; } snd_seq_client_info_alloca(&amidi->cinfo); snd_seq_port_info_alloca(&amidi->pinfo); client_spec = s = (char*) addr_str; while (s != NULL) { int err; if ((s = my_strchr(client_spec, ',', 0)) != NULL) *s = '\0'; if (*client_spec <= '9' && *client_spec >= '0') { /* client_id[:port] */ err = snd_seq_parse_address(amidi->seq, &addr, client_spec); if (err >= 0) { err = amidi_connect(amidi->seq, 0, addr.client, addr.port); if (err < 0) { csound->ErrorMsg(csound, Str("ALSASEQ: connection failed %s %s (%s)"), direction_str, client_spec, snd_strerror(err)); } else { csound->Message(csound, Str("ALSASEQ: connected %s %d:%d\n"), direction_str, addr.client, addr.port); } } } else { /* client_name[:port] */ int client, port; port = get_port_from_string(csound, client_spec); client = alsaseq_get_client_id(csound, amidi, capability, client_spec); if (client >= 0) { err = amidi_connect(amidi->seq, 0, client, port); if (err < 0) { csound->ErrorMsg(csound, Str("ALSASEQ: connection failed %s %s, port %d (%s)"), direction_str, client_spec, port, snd_strerror(err)); } else { csound->Message(csound, Str("ALSASEQ: connected %s %d:%d\n"), direction_str, client, port); } } else { csound->ErrorMsg(csound, Str("ALSASEQ: connection failed %s %s, port %d (%s)"), direction_str, client_spec, port, snd_strerror(client)); } } if (s != NULL) client_spec = s+1; } return OK; } static int alsaseq_in_open(CSOUND *csound, void **userData, const char *devName) { int err, client_id, port_id; alsaseqMidi *amidi; csCfgVariable_t *cfg; char *client_name; *userData = NULL; amidi = (alsaseqMidi*) csound->Malloc(csound, sizeof(alsaseqMidi)); if (UNLIKELY(amidi == NULL)) { csound->ErrorMsg(csound, Str("ALSASEQ input: memory allocation failure")); return -1; } memset(amidi, 0, sizeof(alsaseqMidi)); err = snd_seq_open(&(amidi->seq), "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); if (UNLIKELY(err < 0)) { csound->ErrorMsg(csound, Str("ALSASEQ: error opening sequencer (%s)"), snd_strerror(err)); csound->Free(csound,amidi); return -1; } csound->Message(csound, Str("ALSASEQ: opened MIDI input sequencer\n")); cfg = csound->QueryConfigurationVariable(csound, "alsaseq_client"); client_name = cfg->s.p; err = snd_seq_set_client_name(amidi->seq, client_name); if (UNLIKELY(err < 0)) { csound->ErrorMsg(csound, Str("ALSASEQ: cannot set client name '%s' (%s)"), client_name, snd_strerror(err)); snd_seq_close(amidi->seq); csound->Free(csound,amidi); return -1; } err = snd_seq_create_simple_port(amidi->seq, client_name, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION); if (UNLIKELY(err < 0)) { csound->ErrorMsg(csound, Str("ALSASEQ: cannot create input port (%s)"), snd_strerror(err)); snd_seq_close(amidi->seq); csound->Free(csound,amidi); return -1; } client_id = snd_seq_client_id(amidi->seq); port_id = err; csound->Message(csound, Str("ALSASEQ: created input port '%s' %d:%d\n"), client_name, client_id, port_id); err = snd_midi_event_new(ALSASEQ_SYSEX_BUFFER_SIZE, &amidi->mev); if (UNLIKELY(err < 0)) { csound->ErrorMsg(csound, Str("ALSASEQ: cannot create midi event (%s)"), snd_strerror(err)); snd_seq_close(amidi->seq); csound->Free(csound,amidi); return -1; } snd_midi_event_init(amidi->mev); alsaseq_connect(csound, amidi, SND_SEQ_PORT_CAP_READ, devName); *userData = (void*) amidi; return OK; } static int alsaseq_in_read(CSOUND *csound, void *userData, unsigned char *buf, int nbytes) { int err; alsaseqMidi *amidi = (alsaseqMidi*) userData; snd_seq_event_t *ev; IGN(csound); err = snd_seq_event_input(amidi->seq, &ev); if (err <= 0) return 0; else err = snd_midi_event_decode(amidi->mev, buf, nbytes, ev); return (err==-ENOENT) ? 0 : err; } static int alsaseq_in_close(CSOUND *csound, void *userData) { alsaseqMidi *amidi = (alsaseqMidi*) userData; IGN(csound); if (amidi != NULL) { snd_midi_event_free(amidi->mev); snd_seq_close(amidi->seq); csound->Free(csound,amidi); } return OK; } static int alsaseq_out_open(CSOUND *csound, void **userData, const char *devName) { int err, client_id, port_id; alsaseqMidi *amidi; csCfgVariable_t *cfg; char *client_name; *userData = NULL; amidi = (alsaseqMidi*) csound->Malloc(csound, sizeof(alsaseqMidi)); if (UNLIKELY(amidi == NULL)) { csound->ErrorMsg(csound, Str("ALSASEQ output: memory allocation failure")); return -1; } memset(amidi, 0, sizeof(alsaseqMidi)); err = snd_seq_open(&(amidi->seq), "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); if (UNLIKELY(err < 0)) { csound->ErrorMsg(csound, Str("ALSASEQ: error opening sequencer (%s)"), snd_strerror(err)); csound->Free(csound, amidi); return -1; } csound->Message(csound, Str("ALSASEQ: opened MIDI output sequencer\n")); cfg = csound->QueryConfigurationVariable(csound, "alsaseq_client"); client_name = cfg->s.p; err = snd_seq_set_client_name(amidi->seq, client_name); if (UNLIKELY(err < 0)) { csound->ErrorMsg(csound, Str("ALSASEQ: cannot set client name '%s' (%s)"), client_name, snd_strerror(err)); snd_seq_close(amidi->seq); csound->Free(csound, amidi); return -1; } err = snd_seq_create_simple_port(amidi->seq, client_name, SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ, SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION); if (UNLIKELY(err < 0)) { csound->ErrorMsg(csound, Str("ALSASEQ: cannot create output port (%s)"), snd_strerror(err)); snd_seq_close(amidi->seq); csound->Free(csound,amidi); return -1; } client_id = snd_seq_client_id(amidi->seq); port_id = err; csound->Message(csound, Str("ALSASEQ: created output port '%s' %d:%d\n"), client_name, client_id, port_id); err = snd_midi_event_new(ALSASEQ_SYSEX_BUFFER_SIZE, &amidi->mev); if (UNLIKELY(err < 0)) { csound->ErrorMsg(csound, Str("ALSASEQ: cannot create midi event (%s)"), snd_strerror(err)); snd_seq_close(amidi->seq); csound->Free(csound,amidi); return -1; } snd_midi_event_init(amidi->mev); snd_seq_ev_clear(&amidi->sev); snd_seq_ev_set_source(&amidi->sev, port_id); snd_seq_ev_set_subs(&amidi->sev); snd_seq_ev_set_direct(&amidi->sev); alsaseq_connect(csound, amidi, SND_SEQ_PORT_CAP_WRITE, devName); *userData = (void*) amidi; return OK; } static int alsaseq_out_write(CSOUND *csound, void *userData, const unsigned char *buf, int nbytes) { alsaseqMidi *amidi = (alsaseqMidi*) userData; IGN(csound); if (nbytes == 0) return 0; snd_midi_event_reset_encode(amidi->mev); nbytes = snd_midi_event_encode(amidi->mev, buf, nbytes, &amidi->sev); snd_seq_event_output(amidi->seq, &amidi->sev); snd_seq_drain_output(amidi->seq); return nbytes; } static int alsaseq_out_close(CSOUND *csound, void *userData) { alsaseqMidi *amidi = (alsaseqMidi*) userData; IGN(csound); if (amidi != NULL) { snd_seq_drain_output(amidi->seq); snd_midi_event_free(amidi->mev); snd_seq_close(amidi->seq); csound->Free(csound,amidi); } return OK; } /* module interface functions */ PUBLIC int csoundModuleCreate(CSOUND *csound) { int minsched, maxsched, *priority, maxlen; char *alsaseq_client; csound->CreateGlobalVariable(csound, "::priority", sizeof(int)); priority = (int *) (csound->QueryGlobalVariable(csound, "::priority")); if (priority == NULL) csound->Message(csound, Str("warning... could not create global var\n")); minsched = -20; maxsched = (int) sched_get_priority_max(SCHED_RR); csound->CreateConfigurationVariable(csound, "rtscheduler", priority, CSOUNDCFG_INTEGER, 0, &minsched, &maxsched, Str("RT scheduler priority, alsa module"), NULL); maxlen = 64; alsaseq_client = (char*) csound->Calloc(csound, maxlen*sizeof(char)); strcpy(alsaseq_client, "Csound"); csound->CreateConfigurationVariable(csound, "alsaseq_client", (void*) alsaseq_client, CSOUNDCFG_STRING, 0, NULL, &maxlen, Str("ALSASEQ client name (default: Csound)"), NULL); /* nothing to do, report success */ { OPARMS oparms; csound->GetOParms(csound, &oparms); if (oparms.msglevel & 0x400) csound->Message(csound, Str("ALSA real-time audio and MIDI module " "for Csound by Istvan Varga\n")); } return 0; } int listRawMidi(CSOUND *csound, CS_MIDIDEVICE *list, int isOutput) { int count = 0; int card, err; card = -1; if ((err = snd_card_next(&card)) < 0) { csound->ErrorMsg(csound, Str("cannot determine card number: %s"), snd_strerror(err)); return 0; } if (card < 0) { csound->ErrorMsg(csound,Str("no sound card found")); return 0; } do { snd_ctl_t *ctl; char name[32]; int device; int err; snprintf(name, 32, "hw:%d", card); if ((err = snd_ctl_open(&ctl, name, 0)) < 0) { csound->ErrorMsg(csound, Str("cannot open control for card %d: %s"), card, snd_strerror(err)); return 0; } device = -1; for (;;) { if ((err = snd_ctl_rawmidi_next_device(ctl, &device)) < 0) { csound->ErrorMsg(csound, Str("cannot determine device number: %s"), snd_strerror(err)); break; } if (device < 0) break; snd_rawmidi_info_t *info; const char *name; const char *sub_name; int subs, subs_in, subs_out; int sub; int err; snd_rawmidi_info_alloca(&info); snd_rawmidi_info_set_device(info, device); snd_rawmidi_info_set_stream(info, SND_RAWMIDI_STREAM_INPUT); err = snd_ctl_rawmidi_info(ctl, info); if (err >= 0) subs_in = snd_rawmidi_info_get_subdevices_count(info); else subs_in = 0; snd_rawmidi_info_set_stream(info, SND_RAWMIDI_STREAM_OUTPUT); err = snd_ctl_rawmidi_info(ctl, info); if (err >= 0) subs_out = snd_rawmidi_info_get_subdevices_count(info); else subs_out = 0; subs = subs_in > subs_out ? subs_in : subs_out; if (!subs) return 0; for (sub = 0; sub < subs; ++sub) { snd_rawmidi_info_set_stream(info, sub < subs_in ? SND_RAWMIDI_STREAM_INPUT : SND_RAWMIDI_STREAM_OUTPUT); snd_rawmidi_info_set_subdevice(info, sub); err = snd_ctl_rawmidi_info(ctl, info); if (err < 0) { csound->Warning(csound, Str("cannot get rawmidi information %d:%d:%d: %s\n"), card, device, sub, snd_strerror(err)); return 0; } name = snd_rawmidi_info_get_name(info); sub_name = snd_rawmidi_info_get_subdevice_name(info); if (sub == 0 && sub_name[0] == '\0') { if (sub < subs_in && !isOutput) { if (list) { char devid[32]; strncpy(list[count].device_name, name, 31); snprintf(devid, 32, "hw:%d,%d", card, device); strncpy(list[count].device_id, devid, 63); strncpy(list[count].interface_name, devid, 31); strncpy(list[count].midi_module, "alsaraw", 8); list[count].isOutput = isOutput; } count++; } if (sub < subs_out && isOutput) { if (list) { char devid[64]; strncpy(list[count].device_name, name, 63); snprintf(devid, 64, "hw:%d,%d", card, device); strncpy(list[count].device_id, devid, 63); strncpy(list[count].interface_name, devid, 31); strncpy(list[count].midi_module, "alsaraw", 8); list[count].isOutput = isOutput; } count++; } break; } else { if (sub < subs_in && !isOutput) { if (list) { char devid[64]; strncpy(list[count].device_name, sub_name, 63); snprintf(devid, 64, "hw:%d,%d,%d", card, device,sub); strncpy(list[count].device_id, devid, 63); strncpy(list[count].midi_module, "alsaraw", 8); list[count].isOutput = isOutput; } count++; } if (sub < subs_out && isOutput) { if (list) { char devid[64]; strncpy(list[count].device_name, sub_name, 63); snprintf(devid, 64, "hw:%d,%d,%d", card, device,sub); strncpy(list[count].device_id, devid, 63); strncpy(list[count].midi_module, "alsaraw", 8); list[count].isOutput = isOutput; } count++; } } } } snd_ctl_close(ctl); if ((err = snd_card_next(&card)) < 0) { csound->Warning(csound, Str("cannot determine card number: %s"), snd_strerror(err)); break; } } while (card >= 0); return count; } #define LIST_INPUT 1 #define LIST_OUTPUT 2 #define perm_ok(pinfo,bits) \ ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits)) static int check_permission(snd_seq_port_info_t *pinfo, int perm) { if (perm) { if (perm & LIST_INPUT) { if (perm_ok(pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ)) goto __ok; } if (perm & LIST_OUTPUT) { if (perm_ok(pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) goto __ok; } return 0; } __ok: if (snd_seq_port_info_get_capability(pinfo) & SND_SEQ_PORT_CAP_NO_EXPORT) return 0; return 1; } int listAlsaSeq(CSOUND *csound, CS_MIDIDEVICE *list, int isOutput) { snd_seq_client_info_t *cinfo; snd_seq_port_info_t *pinfo; int numdevs = 0, count = 0; snd_seq_t *seq; IGN(csound); if (snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, 0) < 0) { fprintf(stderr, Str("can't open sequencer\n")); return 1; } snd_seq_client_info_alloca(&cinfo); snd_seq_port_info_alloca(&pinfo); snd_seq_client_info_set_client(cinfo, -1); while (snd_seq_query_next_client(seq, cinfo) >= 0) { /* reset query info */ snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo)); snd_seq_port_info_set_port(pinfo, -1); count = 0; while (snd_seq_query_next_port(seq, pinfo) >= 0) { if (check_permission(pinfo, isOutput? LIST_OUTPUT : LIST_INPUT)) { if (list) { strncpy(list[numdevs].midi_module, "alsaseq", 15); strncpy(list[numdevs].device_name, snd_seq_port_info_get_name(pinfo), 63); strncpy(list[numdevs].interface_name, snd_seq_client_info_get_name(cinfo), 63); snprintf(list[numdevs].device_id, 64, "hw:%d,%d", snd_seq_client_info_get_client(cinfo), snd_seq_port_info_get_port(pinfo)); } numdevs++; count++; } } } return numdevs; } static int listDevicesM(CSOUND *csound, CS_MIDIDEVICE *list, int isOutput){ int count = 0; char *s; s = (char*) csound->QueryGlobalVariable(csound, "_RTMIDI"); if (strncmp(s, "alsaraw", 8) == 0) { /* ALSA Raw MIDI */ count = listRawMidi(csound, list, isOutput); } else if (strncmp(s, "alsaseq", 8) == 0) {/* ALSA Sequencer */ count = listAlsaSeq(csound, list, isOutput); } else if (strncmp(s, "devfile", 8) == 0) { } else { csound->ErrorMsg(csound, Str("rtalsa: Wrong callback.")); } return count; } PUBLIC int csoundModuleInit(CSOUND *csound) { char *s; int i; char buf[9]; OPARMS oparms; csound->GetOParms(csound, &oparms); csound->module_list_add(csound, "alsa", "audio"); csound->module_list_add(csound, "alsaraw", "midi"); csound->module_list_add(csound, "alsaseq", "midi"); csound->module_list_add(csound, "devfile", "midi"); csCfgVariable_t *cfg; int priority; if ((cfg=csound->QueryConfigurationVariable(csound, "rtscheduler")) != NULL) { priority = *(cfg->i.p); if (priority != 0) set_scheduler_priority(csound, priority); csound->DeleteConfigurationVariable(csound, "rtscheduler"); csound->DestroyGlobalVariable(csound, "::priority"); } s = (char*) csound->QueryGlobalVariable(csound, "_RTAUDIO"); i = 0; if (s != NULL) { while (*s != (char) 0 && i < 8) buf[i++] = *(s++) | (char) 0x20; } buf[i] = (char) 0; if (strcmp(&(buf[0]), "alsa") == 0) { csound->Message(csound, Str("rtaudio: ALSA module enabled\n")); csound->SetPlayopenCallback(csound, playopen_); csound->SetRecopenCallback(csound, recopen_); csound->SetRtplayCallback(csound, rtplay_); csound->SetRtrecordCallback(csound, rtrecord_); csound->SetRtcloseCallback(csound, rtclose_); csound->SetAudioDeviceListCallback(csound, listDevices); } s = (char*) csound->QueryGlobalVariable(csound, "_RTMIDI"); i = 0; if (s != NULL) { while (*s != (char) 0 && i < 8) buf[i++] = *(s++) | (char) 0x20; } buf[i] = (char) 0; if (strcmp(&(buf[0]), "alsaraw") == 0 || strcmp(&(buf[0]), "alsa") == 0) { csound->Message(csound, Str("rtmidi: ALSA Raw MIDI module enabled\n")); csound->SetExternalMidiInOpenCallback(csound, midi_in_open); csound->SetExternalMidiReadCallback(csound, midi_in_read); csound->SetExternalMidiInCloseCallback(csound, midi_in_close); csound->SetExternalMidiOutOpenCallback(csound, midi_out_open); csound->SetExternalMidiWriteCallback(csound, midi_out_write); csound->SetExternalMidiOutCloseCallback(csound, midi_out_close); csound->SetMIDIDeviceListCallback(csound,listDevicesM); } else if (strcmp(&(buf[0]), "alsaseq") == 0) { if (oparms.msglevel & 0x400) csound->Message(csound, Str("rtmidi: ALSASEQ module enabled\n")); csound->SetExternalMidiInOpenCallback(csound, alsaseq_in_open); csound->SetExternalMidiReadCallback(csound, alsaseq_in_read); csound->SetExternalMidiInCloseCallback(csound, alsaseq_in_close); csound->SetExternalMidiOutOpenCallback(csound, alsaseq_out_open); csound->SetExternalMidiWriteCallback(csound, alsaseq_out_write); csound->SetExternalMidiOutCloseCallback(csound, alsaseq_out_close); csound->SetMIDIDeviceListCallback(csound,listDevicesM); } else if (strcmp(&(buf[0]), "devfile") == 0) { csound->Message(csound, Str("rtmidi: devfile module enabled\n")); csound->SetExternalMidiInOpenCallback(csound, midi_in_open_file); csound->SetExternalMidiReadCallback(csound, midi_in_read_file); csound->SetExternalMidiInCloseCallback(csound, midi_in_close_file); csound->SetExternalMidiOutOpenCallback(csound, midi_out_open_file); csound->SetExternalMidiWriteCallback(csound, midi_out_write_file); csound->SetExternalMidiOutCloseCallback(csound, midi_out_close_file); csound->SetMIDIDeviceListCallback(csound,listDevicesM); } return 0; } PUBLIC int csoundModuleDestroy(CSOUND *csound) { csCfgVariable_t *cfg; cfg = csound->QueryConfigurationVariable(csound, "alsaseq_client"); if (cfg != NULL && cfg->s.p != NULL) csound->Free(csound, cfg->s.p); return OK; } PUBLIC int csoundModuleInfo(void) { return ((CS_APIVERSION << 16) + (CS_APISUBVER << 8) + (int) sizeof(MYFLT)); } csound-6.10.0/InOut/rtauhal.c000066400000000000000000000713611321653344700157530ustar00rootroot00000000000000/* rtauhal.c: Copyright (C) 2011 Victor Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include "csdl.h" #include "soundio.h" #if !defined(MAC_OS_X_VERSION_10_6) /* the API was changed for 10.6, these make it backwards compatible */ typedef ComponentInstance AudioComponentInstance; typedef Component AudioComponent; typedef ComponentDescription AudioComponentDescription; #define AudioComponentFindNext FindNextComponent #define AudioComponentInstanceNew OpenAComponent #define AudioComponentInstanceDispose CloseComponent typedef float AudioUnitSampleType; #endif typedef struct { char name[128]; int outchannels; int inchannels; int indevnum; int outdevnum; } Device_Info; typedef struct csdata_ { AudioDeviceID dev; AudioStreamBasicDescription format; int inBufSamples; int outBufSamples; int currentInputIndex; int currentOutputIndex; MYFLT *inputBuffer; MYFLT *outputBuffer; csRtAudioParams *inParm; csRtAudioParams *outParm; int onchnls, inchnls; AudioComponentInstance outunit; AudioComponentInstance inunit; CSOUND *csound; AudioBufferList *inputdata; int disp; AudioDeviceID defdevin; AudioDeviceID defdevout; int devnos; int devin; int devout; void *incb; void *outcb; } csdata; OSStatus Csound_Input(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData); OSStatus Csound_Render(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 dump, UInt32 inNumberFrames, AudioBufferList *ioData); static void DAC_channels(CSOUND *csound, int chans){ int *dachans = (int *) csound->QueryGlobalVariable(csound, "_DAC_CHANNELS_"); if (dachans == NULL) { if (csound->CreateGlobalVariable(csound, "_DAC_CHANNELS_", sizeof(int)) != 0) return; dachans = (int *) csound->QueryGlobalVariable(csound, "_DAC_CHANNELS_"); *dachans = chans; } } static void ADC_channels(CSOUND *csound, int chans){ int *dachans = (int *) csound->QueryGlobalVariable(csound, "_ADC_CHANNELS_"); if (dachans == NULL) { if (csound->CreateGlobalVariable(csound, "_ADC_CHANNELS_", sizeof(int)) != 0) return; dachans = (int *) csound->QueryGlobalVariable(csound, "_ADC_CHANNELS_"); *dachans = chans; } } int AuHAL_open(CSOUND *csound, const csRtAudioParams * parm, csdata *cdata, int isInput) { UInt32 psize, devnum, devnos; AudioDeviceID dev; AudioDeviceID *sysdevs; AudioStreamBasicDescription format; int i; Device_Info *devinfo; UInt32 bufframes, nchnls; int devouts = 0, devins = 0; double srate; UInt32 enableIO, maxFPS; AudioComponent HALOutput; AudioComponentInstance *aunit; AudioComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0}; AudioObjectPropertyAddress prop = { kAudioObjectPropertyName, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; CFStringRef devName; CFStringEncoding defaultEncoding = CFStringGetSystemEncoding(); prop.mSelector = (isInput ? kAudioHardwarePropertyDefaultInputDevice : kAudioHardwarePropertyDefaultOutputDevice); psize = sizeof(AudioDeviceID); AudioObjectGetPropertyData(kAudioObjectSystemObject, &prop, 0, NULL, &psize, &dev); if(isInput) cdata->defdevin = dev; else cdata->defdevout = dev; prop.mSelector = kAudioHardwarePropertyDevices; AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &prop, 0, NULL, &psize); devnos = psize / sizeof(AudioDeviceID); sysdevs = (AudioDeviceID *) csound->Malloc(csound,psize); devinfo = (Device_Info *) csound->Malloc(csound,devnos*sizeof(Device_Info)); AudioObjectGetPropertyData(kAudioObjectSystemObject, &prop, 0, NULL, &psize, sysdevs); cdata->devnos = devnos; for (i = 0; (unsigned int) i < devnos; i++) { AudioBufferList *b; int devchannels, k, n; int numlists; psize = sizeof(CFStringRef); prop.mScope = kAudioObjectPropertyScopeGlobal; prop.mSelector = kAudioObjectPropertyName; AudioObjectGetPropertyData(sysdevs[i], &prop, 0, NULL, &psize, &devName); if(CFStringGetCStringPtr(devName, defaultEncoding)) strncpy(devinfo[i].name, CFStringGetCStringPtr(devName, defaultEncoding), 127); else strncpy(devinfo[i].name, "unnamed device", 127); CFRelease(devName); devchannels = 0; prop.mScope = kAudioDevicePropertyScopeInput; prop.mSelector = kAudioDevicePropertyStreamConfiguration; AudioObjectGetPropertyDataSize(sysdevs[i], &prop, 0, NULL, &psize); b = (AudioBufferList *) csound->Malloc(csound,psize); numlists = psize / sizeof(AudioBufferList); AudioObjectGetPropertyData(sysdevs[i], &prop, 0, NULL, &psize, b); for(n=0; n < numlists; n++){ for(k=0; (unsigned int) k < b[n].mNumberBuffers; k++) devchannels += b[n].mBuffers[k].mNumberChannels; } devinfo[i].inchannels = devchannels; if(devchannels) { devins++; devinfo[i].indevnum = devins; } else devinfo[i].indevnum = -1; csound->Free(csound,b); devchannels = 0; prop.mScope = kAudioDevicePropertyScopeOutput; AudioObjectGetPropertyDataSize(sysdevs[i], &prop, 0, NULL, &psize); b = (AudioBufferList *) csound->Malloc(csound,psize); numlists = psize /sizeof(AudioBufferList); AudioObjectGetPropertyData(sysdevs[i], &prop, 0, NULL, &psize, b); for(n=0; n < numlists; n++){ for(k=0; (unsigned int) k < b[n].mNumberBuffers; k++) devchannels += b[n].mBuffers[k].mNumberChannels; } devinfo[i].outchannels = devchannels; if(devchannels) { devouts++; devinfo[i].outdevnum = devouts; } else devinfo[i].outdevnum = -1; csound->Free(csound,b); } if(cdata->disp) csound->Message(csound, "==========================================================\n"); if (isInput) csound->Message(csound, Str("AuHAL Module: found %d input device(s):\n"), devins); else csound->Message(csound, Str("AuHAL Module: found %d output device(s):\n"), devouts); for (i = 0; (unsigned int) i < devnos; i++) { if (isInput) { if(devinfo[i].inchannels) { csound->Message(csound, Str("%d: %s (%d channels) \n"), devinfo[i].indevnum, devinfo[i].name, devinfo[i].inchannels); } } else { if(devinfo[i].outchannels) csound->Message(csound, Str("%d: %s (%d channels) \n"), devinfo[i].outdevnum, devinfo[i].name, devinfo[i].outchannels); } } if (parm->devName != NULL) devnum = atoi(parm->devName); else devnum = parm->devNum; if (devnum > 0 && devnum < 1024) { int CoreAudioDev = -1; prop.mSelector = kAudioHardwarePropertyDevices; if (isInput) { for(i=0; (unsigned int) i < devnos; i++) { if((unsigned int) devinfo[i].indevnum == devnum) CoreAudioDev = i; } if (LIKELY(CoreAudioDev >= 0)) { prop.mSelector = kAudioHardwarePropertyDefaultInputDevice; dev = sysdevs[CoreAudioDev]; AudioObjectSetPropertyData(kAudioObjectSystemObject, &prop, 0, NULL, sizeof(AudioDeviceID), &dev); } else csound->Warning(csound, Str("requested device %d out of range"), devnum); } else { prop.mSelector = kAudioHardwarePropertyDefaultOutputDevice; for(i=0;(unsigned int) i < devnos; i++) { if((unsigned int) devinfo[i].outdevnum == devnum) CoreAudioDev = i; } if (LIKELY(CoreAudioDev >= 0)) { dev = sysdevs[CoreAudioDev]; AudioObjectSetPropertyData(kAudioObjectSystemObject, &prop, 0, NULL, sizeof(AudioDeviceID), &dev); } else csound->Warning(csound, Str("requested device %d (%s) out of range"), devnum, devinfo[CoreAudioDev].name); } } for(i=0; (unsigned int) i < devnos; i++) if(sysdevs[i] == dev){ if(isInput) ADC_channels(csound, devinfo[i].inchannels); else DAC_channels(csound, devinfo[i].outchannels); } csound->Free(csound,sysdevs); csound->Free(csound,devinfo); psize = sizeof(CFStringRef); prop.mSelector = kAudioObjectPropertyName; AudioObjectGetPropertyData(dev, &prop, 0, NULL, &psize, &devName); if(isInput) csound->Message(csound, Str("selected input device: %s \n"), CFStringGetCStringPtr(devName, defaultEncoding)); else csound->Message(csound, Str("selected output device: %s \n"), CFStringGetCStringPtr(devName, defaultEncoding)); CFRelease(devName); srate = csound->GetSr(csound); if(!isInput){ nchnls =cdata->onchnls = parm->nChannels; bufframes = csound->GetOutputBufferSize(csound)/nchnls; } else { nchnls = cdata->inchnls = parm->nChannels; bufframes = csound->GetInputBufferSize(csound)/nchnls; } /* although the SR is set in the stream properties, we also need to set the device to match */ double sr; prop.mSelector = kAudioDevicePropertyNominalSampleRate; if(!isInput){ AudioObjectGetPropertyData(dev, &prop, 0, NULL, &psize, &sr); csound->system_sr(csound, sr); } psize = sizeof(double); AudioObjectSetPropertyData(dev, &prop, 0, NULL, psize, &srate); AudioObjectGetPropertyData(dev, &prop, 0, NULL, &psize, &sr); if(UNLIKELY(sr != srate)) { csound->Warning(csound, Str("Attempted to set device SR, tried %.1f, got %.1f \n"), srate, sr); } HALOutput = AudioComponentFindNext(NULL, &cd); if (isInput) { AudioComponentInstanceNew(HALOutput, &(cdata->inunit)); enableIO = 1; AudioUnitSetProperty(cdata->inunit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO)); enableIO = 0; AudioUnitSetProperty(cdata->inunit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO)); psize = sizeof(AudioDeviceID); /* for input, select device AFTER enabling IO */ AudioUnitSetProperty(cdata->inunit,kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, isInput, &dev, psize); aunit = &(cdata->inunit); } else { AudioComponentInstanceNew(HALOutput, &(cdata->outunit)); psize = sizeof(AudioDeviceID); /* for output, select device BEFORE enabling IO */ AudioUnitSetProperty(cdata->outunit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, isInput, &dev, psize); enableIO = 1; AudioUnitSetProperty(cdata->outunit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO)); enableIO = 0; AudioUnitSetProperty(cdata->outunit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO)); aunit = &(cdata->outunit); } /* now set the buffer size */ psize = sizeof(AudioDeviceID); AudioUnitGetProperty(*aunit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, isInput, &dev, &psize); prop.mSelector = kAudioDevicePropertyBufferFrameSize; psize = 4; AudioObjectSetPropertyData(dev, &prop, 0, NULL, psize, &bufframes); psize = sizeof(maxFPS); AudioUnitGetProperty(*aunit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, isInput, &maxFPS, &psize); AudioUnitSetProperty(*aunit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, isInput, &bufframes, sizeof(UInt32)); /* set the stream properties */ psize = sizeof(AudioStreamBasicDescription); AudioUnitGetProperty(*aunit, kAudioUnitProperty_StreamFormat, (isInput ? kAudioUnitScope_Output : kAudioUnitScope_Input), isInput, &format, &psize); format.mSampleRate = srate; format.mFormatID = kAudioFormatLinearPCM; format.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked | kLinearPCMFormatFlagIsNonInterleaved; format.mBytesPerPacket = sizeof(Float32); format.mFramesPerPacket = 1; format.mBytesPerFrame = sizeof(Float32); format.mChannelsPerFrame = nchnls; format.mBitsPerChannel = sizeof(Float32)*8; AudioUnitSetProperty(*aunit, kAudioUnitProperty_StreamFormat, (isInput ? kAudioUnitScope_Output : kAudioUnitScope_Input), isInput, &format, sizeof(AudioStreamBasicDescription)); /* set the callbacks and open the device */ if(!isInput) { AURenderCallbackStruct output; output.inputProc = Csound_Render; output.inputProcRefCon = cdata; AudioUnitSetProperty(*aunit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, isInput, &output, sizeof(output)); AudioUnitInitialize(*aunit); AudioOutputUnitStart(*aunit); csound->Message(csound, Str("***** AuHAL module: output device open with %d " "buffer frames\n"), bufframes); cdata->disp = 0; } else { AURenderCallbackStruct input; AudioBufferList *CAInputData = (AudioBufferList*)csound->Malloc(csound,sizeof(UInt32) + cdata->inchnls * sizeof(AudioBuffer)); CAInputData->mNumberBuffers = cdata->inchnls; for (i = 0; i < cdata->inchnls; i++) { CAInputData->mBuffers[i].mNumberChannels = 1; CAInputData->mBuffers[i].mDataByteSize = bufframes * sizeof(Float32); CAInputData->mBuffers[i].mData = csound->Calloc(csound,bufframes* sizeof(Float32)); } cdata->inputdata = CAInputData; input.inputProc = Csound_Input; input.inputProcRefCon = cdata; AudioUnitSetProperty(*aunit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Input, isInput, &input, sizeof(input)); AudioUnitInitialize(*aunit); AudioOutputUnitStart(*aunit); csound->Message(csound, "***** AuHAL module: input device open with %d buffer frames\n", bufframes); } if(!cdata->disp) csound->Message(csound, "==========================================================\n"); cdata->disp = 0; return 0; } int listDevices(CSOUND *csound, CS_AUDIODEVICE *list, int isOutput){ UInt32 psize, devnos; AudioDeviceID *sysdevs; Device_Info *devinfo; int i; int devouts = 0, devins = 0; AudioObjectPropertyAddress prop = { kAudioObjectPropertyName, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; CFStringRef devName; CFStringEncoding defaultEncoding = CFStringGetSystemEncoding(); prop.mSelector = kAudioHardwarePropertyDevices; AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &prop, 0, NULL, &psize); devnos = psize / sizeof(AudioDeviceID); sysdevs = (AudioDeviceID *) csound->Malloc(csound,psize); devinfo = (Device_Info *) csound->Malloc(csound,devnos*sizeof*devinfo); AudioObjectGetPropertyData(kAudioObjectSystemObject, &prop, 0, NULL, &psize, sysdevs); for (i = 0; (unsigned int) i < devnos; i++) { AudioBufferList *b; int devchannels, k, n; int numlists; psize = sizeof(CFStringRef); prop.mScope = kAudioObjectPropertyScopeGlobal; prop.mSelector = kAudioObjectPropertyName; AudioObjectGetPropertyData(sysdevs[i], &prop, 0, NULL, &psize, &devName); memset(devinfo[i].name,0,128); if(CFStringGetCStringPtr(devName, defaultEncoding) != NULL) strncpy(devinfo[i].name, CFStringGetCStringPtr(devName, defaultEncoding),127); CFRelease(devName); devchannels = 0; prop.mScope = kAudioDevicePropertyScopeInput; prop.mSelector = kAudioDevicePropertyStreamConfiguration; AudioObjectGetPropertyDataSize(sysdevs[i], &prop, 0, NULL, &psize); b = (AudioBufferList *) csound->Malloc(csound,psize); numlists = psize / sizeof(AudioBufferList); AudioObjectGetPropertyData(sysdevs[i], &prop, 0, NULL, &psize, b); for(n=0; n < numlists; n++){ for(k=0; (unsigned int) k < b[n].mNumberBuffers; k++) devchannels += b[n].mBuffers[k].mNumberChannels; } devinfo[i].inchannels = devchannels; if(devchannels) { devins++; devinfo[i].indevnum = devins; } else devinfo[i].indevnum = -1; csound->Free(csound,b); devchannels = 0; prop.mScope = kAudioDevicePropertyScopeOutput; AudioObjectGetPropertyDataSize(sysdevs[i], &prop, 0, NULL, &psize); b = (AudioBufferList *) csound->Malloc(csound,psize); numlists = psize /sizeof(AudioBufferList); AudioObjectGetPropertyData(sysdevs[i], &prop, 0, NULL, &psize, b); for(n=0; n < numlists; n++){ for(k=0; (unsigned int) k < b[n].mNumberBuffers; k++) devchannels += b[n].mBuffers[k].mNumberChannels; } devinfo[i].outchannels = devchannels; if(devchannels) { devouts++; devinfo[i].outdevnum = devouts; } else devinfo[i].outdevnum = -1; csound->Free(csound,b); } if(list==NULL){ return (isOutput ? devouts : devins); } else { char tmp[64], *s; int n=0, i; if ((s = (char*) csound->QueryGlobalVariable(csound, "_RTAUDIO")) == NULL) return 0; if(!isOutput){ for(i=0; (unsigned int) i < devnos; i++) { if(devinfo[i].inchannels) { strncpy(list[n].device_name, devinfo[i].name, 63); snprintf(tmp, 64, "adc%d", devinfo[i].indevnum); strncpy(list[n].device_id, tmp, 63); strncpy(list[n].rt_module, s, 63); list[n].max_nchnls = devinfo[i].inchannels; list[n].isOutput = 0; n++; } } return n; } else { for(i=0;(unsigned int) i < devnos; i++){ if(devinfo[i].outchannels) { strncpy(list[n].device_name, devinfo[i].name, 63); snprintf(tmp, 64, "dac%d", devinfo[i].outdevnum); strncpy(list[n].device_id, tmp, 63); strncpy(list[n].rt_module, s, 63); list[n].max_nchnls = devinfo[i].outchannels; list[n].isOutput = 1; n++; } } return n; } } } /* open for audio input */ static int recopen_(CSOUND *csound, const csRtAudioParams * parm) { csdata *cdata; void **recordata = csound->GetRtRecordUserData(csound); if (*(csound->GetRtRecordUserData(csound)) != NULL) return 0; /* allocate structure */ if(*(csound->GetRtPlayUserData(csound) )!= NULL) cdata = (csdata *) *(csound->GetRtPlayUserData(csound)); else { cdata = (csdata *) csound->Calloc(csound, sizeof(csdata)); cdata->disp = 1; } cdata->inunit = NULL; *recordata = (void *) cdata; cdata->inParm = (csRtAudioParams *) parm; cdata->csound = cdata->csound; cdata->inputBuffer = (MYFLT *) csound->Calloc(csound, csound->GetInputBufferSize(csound)* sizeof(MYFLT)); cdata->incb = csound->CreateCircularBuffer(csound, parm->bufSamp_HW*parm->nChannels, sizeof(MYFLT)); int ret = AuHAL_open(csound, parm, cdata, 1); return ret; } /* open for audio output */ static int playopen_(CSOUND *csound, const csRtAudioParams * parm) { csdata *cdata; void **playdata = csound->GetRtPlayUserData(csound); if(*(csound->GetRtRecordUserData(csound)) != NULL) cdata = (csdata *) *(csound->GetRtRecordUserData(csound)); else { cdata = (csdata *) csound->Calloc(csound, sizeof(csdata)); cdata->disp = 1; } cdata->outunit = NULL; *playdata = (void *) cdata; cdata->outParm = (csRtAudioParams *) parm; cdata->csound = csound; cdata->outputBuffer = (MYFLT *) csound->Calloc(csound, csound->GetOutputBufferSize(csound)* sizeof(MYFLT)); memset(cdata->outputBuffer, 0, csound->GetOutputBufferSize(csound)*sizeof(MYFLT)); cdata->outcb = csound->CreateCircularBuffer(csound, parm->bufSamp_HW*parm->nChannels, sizeof(MYFLT)); return AuHAL_open(csound, parm,cdata,0); } OSStatus Csound_Input(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { csdata *cdata = (csdata *) inRefCon; CSOUND *csound = cdata->csound; int inchnls = cdata->inchnls; MYFLT *inputBuffer = cdata->inputBuffer; int j,k; Float32 *buffer; int n = inNumberFrames*inchnls; int l; IGN(ioData); AudioUnitRender(cdata->inunit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, cdata->inputdata); for (k = 0; k < inchnls; k++){ buffer = (Float32 *) cdata->inputdata->mBuffers[k].mData; for(j=0; (unsigned int) j < inNumberFrames; j++){ inputBuffer[j*inchnls+k] = buffer[j]; } } l = csound->WriteCircularBuffer(csound, cdata->incb,inputBuffer,n); return 0; } #define MICROS 1000000 static int rtrecord_(CSOUND *csound, MYFLT *inbuff_, int nbytes) { csdata *cdata; int n = nbytes/sizeof(MYFLT); int m = 0, l, w = n; MYFLT sr = csound->GetSr(csound); cdata = (csdata *) *(csound->GetRtRecordUserData(csound)); do{ l = csound->ReadCircularBuffer(csound,cdata->incb,&inbuff_[m],n); m += l; n -= l; if(n) usleep(MICROS*w/sr); } while(n); return nbytes; } OSStatus Csound_Render(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { csdata *cdata = (csdata *) inRefCon; CSOUND *csound = cdata->csound; int onchnls = cdata->onchnls; MYFLT *outputBuffer = cdata->outputBuffer; int j,k; Float32 *buffer; int n = inNumberFrames*onchnls; IGN(ioActionFlags); IGN(inTimeStamp); IGN(inBusNumber); n = csound->ReadCircularBuffer(csound,cdata->outcb,outputBuffer,n); for (k = 0; k < onchnls; k++) { buffer = (Float32 *) ioData->mBuffers[k].mData; for(j=0; (unsigned int) j < inNumberFrames; j++){ buffer[j] = (Float32) outputBuffer[j*onchnls+k] ; outputBuffer[j*onchnls+k] = FL(0.0); } } return 0; } static void rtplay_(CSOUND *csound, const MYFLT *outbuff_, int nbytes) { csdata *cdata; int n = nbytes/sizeof(MYFLT); int m = 0, l, w = n; MYFLT sr = csound->GetSr(csound); cdata = (csdata *) *(csound->GetRtPlayUserData(csound)); do { l = csound->WriteCircularBuffer(csound, cdata->outcb,&outbuff_[m],n); m += l; n -= l; if(n) usleep(MICROS*w/sr); } while(n); } /* close the I/O device entirely */ /* called only when both complete */ static void rtclose_(CSOUND *csound) { csdata *cdata; cdata = (csdata *) *(csound->GetRtRecordUserData(csound)); if(cdata == NULL) cdata = (csdata *) *(csound->GetRtPlayUserData(csound)); if (cdata != NULL) { usleep(1000*csound->GetOutputBufferSize(csound)/ (csound->GetSr(csound)*csound->GetNchnls(csound))); if(cdata->inunit != NULL){ AudioOutputUnitStop(cdata->inunit); AudioUnitUninitialize(cdata->inunit); AudioComponentInstanceDispose(cdata->inunit); } if(cdata->outunit != NULL){ AudioOutputUnitStop(cdata->outunit); AudioUnitUninitialize(cdata->outunit); AudioComponentInstanceDispose(cdata->outunit); } if (cdata->outputBuffer != NULL) { csound->Free(csound,cdata->outputBuffer); cdata->outputBuffer = NULL; } if (cdata->inputBuffer != NULL) { csound->Free(csound,cdata->inputBuffer); cdata->inputBuffer = NULL; } *(csound->GetRtRecordUserData(csound)) = NULL; *(csound->GetRtPlayUserData(csound)) = NULL; if(cdata->inputdata) { int i; for (i = 0; i < cdata->inchnls; i++) csound->Free(csound,cdata->inputdata->mBuffers[i].mData); csound->Free(csound,cdata->inputdata); } if(cdata->defdevin) { AudioObjectPropertyAddress prop = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; UInt32 psize = sizeof(AudioDeviceID); AudioObjectSetPropertyData(kAudioObjectSystemObject, &prop, 0, NULL, psize, &cdata->defdevin); } if(cdata->defdevout) { AudioObjectPropertyAddress prop = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; UInt32 psize = sizeof(AudioDeviceID); AudioObjectSetPropertyData(kAudioObjectSystemObject, &prop, 0, NULL, psize, &cdata->defdevout); } csound->DestroyCircularBuffer(csound, cdata->incb); csound->DestroyCircularBuffer(csound, cdata->outcb); csound->Free(csound,cdata); csound->Message(csound, Str("AuHAL module: device closed\n")); } } int csoundModuleInit(CSOUND *csound) { char *drv; csound->module_list_add(csound, "auhal", "audio"); drv = (char *) csound->QueryGlobalVariable(csound, "_RTAUDIO"); if (drv == NULL) return 0; if (!(strcmp(drv, "auhal") == 0 || strcmp(drv, "AuHal") == 0 || strcmp(drv, "AUHAL") == 0 || strcmp(drv, "coreaudio") == 0 || strcmp(drv, "CoreAudio") == 0 || strcmp(drv, "COREAUDIO") == 0)) return 0; //if (csound->oparms->msglevel & 0x400) csound->Message(csound, Str("rtaudio: coreaaudio-AuHAL module enabled\n")); csound->SetPlayopenCallback(csound, playopen_); csound->SetRecopenCallback(csound, recopen_); csound->SetRtplayCallback(csound, rtplay_); csound->SetRtrecordCallback(csound, rtrecord_); csound->SetRtcloseCallback(csound, rtclose_); csound->SetAudioDeviceListCallback(csound, listDevices); return 0; } int csoundModuleCreate(CSOUND *csound) { IGN(csound); return 0; } csound-6.10.0/InOut/rtjack.c000066400000000000000000001470001321653344700155630ustar00rootroot00000000000000/* rtjack.c: Copyright (C) 2005, 2006 Istvan Varga 2016 Victor Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include /* no #ifdef, should always have these on systems where JACK is available */ #include #include #ifdef LINUX #include #endif #include "csdl.h" #include "soundio.h" #ifdef LINUX #include #endif #include "cs_jack.h" static int listDevices(CSOUND *csound, CS_AUDIODEVICE *list, int isOutput); #ifdef LINUX static inline int rtJack_CreateLock(CSOUND *csound, pthread_mutex_t *p) { (void) csound; return (pthread_mutex_init(p, (pthread_mutexattr_t*) NULL)); } static inline void rtJack_Lock(CSOUND *csound, pthread_mutex_t *p) { (void) csound; pthread_mutex_lock(p); } static inline int rtJack_LockTimeout(CSOUND *csound, pthread_mutex_t *p, size_t milliseconds) { struct timeval tv; struct timespec ts; register size_t n, s; register int retval = pthread_mutex_trylock(p); if (!retval) return retval; if (!milliseconds) return retval; gettimeofday(&tv, NULL); s = milliseconds / (size_t) 1000; n = milliseconds - (s * (size_t) 1000); s += (size_t) tv.tv_sec; n = (size_t) (((int) n * 1000 + (int) tv.tv_usec) * 1000); ts.tv_nsec = (long) (n < (size_t) 1000000000 ? n : n - 1000000000); ts.tv_sec = (time_t) (n < (size_t) 1000000000 ? s : s + 1); return pthread_mutex_timedlock(p, &ts); } static inline int rtJack_TryLock(CSOUND *csound, pthread_mutex_t *p) { (void) csound; return (pthread_mutex_trylock(p)); } static inline void rtJack_Unlock(CSOUND *csound, pthread_mutex_t *p) { (void) csound; pthread_mutex_unlock(p); } static inline void rtJack_DestroyLock(CSOUND *csound, pthread_mutex_t *p) { (void) csound; pthread_mutex_unlock(p); pthread_mutex_destroy(p); } #else /* LINUX */ static inline int rtJack_CreateLock(CSOUND *csound, void **p) { *p = csound->CreateThreadLock(); return (*p != NULL ? 0 : -1); } static inline void rtJack_Lock(CSOUND *csound, void **p) { csound->WaitThreadLockNoTimeout(*p); } static inline int rtJack_LockTimeout(CSOUND *csound, void **p, size_t timeout) { return csound->WaitThreadLock(*p, timeout); } static inline int rtJack_TryLock(CSOUND *csound, void **p) { return (csound->WaitThreadLock(*p, (size_t) 0)); } static inline void rtJack_Unlock(CSOUND *csound, void **p) { csound->NotifyThreadLock(*p); } static inline void rtJack_DestroyLock(CSOUND *csound, void **p) { csound->NotifyThreadLock(*p); csound->DestroyThreadLock(*p); *p = NULL; } #endif /* !LINUX */ /* print error message, close connection, and terminate performance */ static CS_NORETURN void rtJack_Error(CSOUND *, int errCode, const char *msg); static int processCallback(jack_nframes_t nframes, void *arg); /* callback functions */ static int sampleRateCallback(jack_nframes_t nframes, void *arg) { RtJackGlobals *p = (RtJackGlobals*) arg; if (p->sampleRate != (int) nframes) p->jackState = 1; return 0; } static int bufferSizeCallback(jack_nframes_t nframes, void *arg) { RtJackGlobals *p = (RtJackGlobals*) arg; (void) nframes; /* invalidate output port buffer pointer cache */ if (p->outPortBufs != NULL) p->outPortBufs[0] = (jack_default_audio_sample_t*) NULL; return 0; } #ifdef LINUX static void freeWheelCallback(int starting, void *arg) { RtJackGlobals *p; CSOUND *csound; p = (RtJackGlobals*) arg; csound = p->csound; if (starting) { if (UNLIKELY(sched_getscheduler(0) != SCHED_OTHER)) { struct sched_param sp; csound->Message(csound, Str(" *** WARNING: " "disabling --sched in freewheel mode\n")); memset(&sp, 0, sizeof(struct sched_param)); sp.sched_priority = 0; sched_setscheduler(0, SCHED_OTHER, &sp); } } } #endif static int xrunCallback(void *arg) { RtJackGlobals *p = (RtJackGlobals*) arg; p->xrunFlag = 1; return 0; } static void shutDownCallback(void *arg) { RtJackGlobals *p = (RtJackGlobals*) arg; p->jackState = 2; if (p->bufs != NULL) { int i; for (i = 0; i < p->nBuffers; i++) { if (p->bufs[i] != NULL && (p->bufs[i]->inBufs != NULL || p->bufs[i]->outBufs != NULL)) rtJack_Unlock(p->csound, &(p->bufs[i]->csndLock)); } } } static inline size_t rtJack_AlignData(size_t ofs) { return ((ofs + (size_t) 15) & (~((size_t) 15))); } /* allocate ring buffers */ static void rtJack_AllocateBuffers(RtJackGlobals *p) { CSOUND *csound = p->csound; void *ptr; size_t i, j, m, nBytes, nBytesPerBuf, ofs1, ofs2, ofs3; m = (size_t) ((p->inputEnabled ? 1 : 0) + (p->outputEnabled ? 1 : 0)); if (!m) return; /* calculate the number of bytes to allocate */ ofs1 = rtJack_AlignData(sizeof(RtJackBuffer*) * (size_t) p->nBuffers); ofs2 = rtJack_AlignData(sizeof(RtJackBuffer)); ofs3 = rtJack_AlignData(sizeof(jack_default_audio_sample_t*) * (size_t) p->nChannels * m); nBytesPerBuf = ofs2 + ofs3; nBytesPerBuf += rtJack_AlignData(sizeof(jack_default_audio_sample_t) * (size_t) p->nChannels * (size_t) p->bufSize * m); nBytes = ofs1 + (nBytesPerBuf * (size_t) p->nBuffers); /* allocate memory */ ptr = (RtJackBuffer**) csound->Malloc(csound, nBytes); if (UNLIKELY(ptr == NULL)) rtJack_Error(csound, CSOUND_MEMORY, Str("memory allocation failure")); p->bufs = (RtJackBuffer**) ptr; memset((void*) ptr, 0, nBytes); /* set pointer to each buffer */ ptr = (void*) ((char*) ptr + (long) ofs1); for (i = (size_t) 0; i < (size_t) p->nBuffers; i++) { p->bufs[i] = ptr; ptr = (void*) ((char*) ptr + (long) nBytesPerBuf); } for (i = (size_t) 0; i < (size_t) p->nBuffers; i++) { /* create lock for signaling when the process callback is done */ /* with the buffer */ if (UNLIKELY(rtJack_CreateLock(csound, &(p->bufs[i]->csndLock)) != 0)) rtJack_Error(csound, CSOUND_MEMORY, Str("memory allocation failure")); /* create lock for signaling when the Csound thread is done */ /* with the buffer */ if (UNLIKELY(rtJack_CreateLock(csound, &(p->bufs[i]->jackLock)) != 0)) { rtJack_DestroyLock(csound, &(p->bufs[i]->csndLock)); rtJack_Error(csound, CSOUND_MEMORY, Str("memory allocation failure")); } ptr = (void*) p->bufs[i]; ptr = (void*) ((char*) ptr + (long) ofs2); /* set pointers to input/output buffers */ if (p->inputEnabled) { p->bufs[i]->inBufs = (jack_default_audio_sample_t**) ptr; ptr = (void*) &(p->bufs[i]->inBufs[p->nChannels]); } if (p->outputEnabled) p->bufs[i]->outBufs = (jack_default_audio_sample_t**) ptr; ptr = (void*) p->bufs[i]; ptr = (void*) ((char*) ptr + (long) (ofs2 + ofs3)); for (j = (size_t) 0; j < (size_t) p->nChannels; j++) { if (p->inputEnabled) { p->bufs[i]->inBufs[j] = (jack_default_audio_sample_t*) ptr; ptr = (void*) &(p->bufs[i]->inBufs[j][p->bufSize]); } if (p->outputEnabled) { p->bufs[i]->outBufs[j] = (jack_default_audio_sample_t*) ptr; ptr = (void*) &(p->bufs[i]->outBufs[j][p->bufSize]); } } } } static void listPorts(CSOUND *csound, int isOutput){ int i,n = listDevices(csound,NULL,isOutput); CS_AUDIODEVICE *devs = (CS_AUDIODEVICE *) csound->Malloc(csound, n*sizeof(CS_AUDIODEVICE)); listDevices(csound,devs,isOutput); csound->Message(csound, "Jack %s ports:\n", isOutput ? "output" : "input"); for(i=0; i < n; i++) csound->Message(csound, " %d: %s (dac:%s)\n", i, devs[i].device_id, devs[i].device_name); csound->Free(csound,devs); } /* register JACK ports */ static void rtJack_RegisterPorts(RtJackGlobals *p) { char portName[MAX_NAME_LEN + 4]; unsigned long flags = 0UL; int i; CSOUND *csound = p->csound; if (!(p->inputEnabled && p->outputEnabled)) flags = (unsigned long) JackPortIsTerminal; if (p->inputEnabled) { /* register input ports */ for (i = 0; i < p->nChannels_i; i++) { snprintf(portName, MAX_NAME_LEN + 4, "%s%d", p->inputPortName, i + 1); p->inPorts[i] = jack_port_register(p->client, &(portName[0]), JACK_DEFAULT_AUDIO_TYPE, flags | JackPortIsInput, 0UL); if (UNLIKELY(p->inPorts[i] == NULL)) rtJack_Error(csound, -1, Str("error registering input ports")); } } if (p->outputEnabled) { /* register output ports */ for (i = 0; i < p->nChannels; i++) { snprintf(portName, MAX_NAME_LEN + 4, "%s%d", p->outputPortName, i + 1); p->outPorts[i] = jack_port_register(p->client, &(portName[0]), JACK_DEFAULT_AUDIO_TYPE, flags | JackPortIsOutput, 0UL); if (UNLIKELY(p->outPorts[i] == NULL)) rtJack_Error(csound, -1, Str("error registering output ports")); } } } /* connect to JACK server, set up ports and ring buffers, */ /* activate client, and connect ports if requested */ static void openJackStreams(RtJackGlobals *p) { char buf[256]; int i, j, k; CSOUND *csound = p->csound; /* connect to JACK server */ p->client = jack_client_open(&(p->clientName[0]), JackNoStartServer, NULL); if (UNLIKELY(p->client == NULL)) rtJack_Error(csound, -1, Str("could not connect to JACK server")); csound->system_sr(csound, jack_get_sample_rate(p->client)); csound->Message(csound, "system sr: %f\n", csound->system_sr(csound,0)); /* check consistency of parameters */ if (UNLIKELY(p->nChannels < 1 || p->nChannels > 255)) rtJack_Error(csound, -1, Str("invalid number of channels")); if (p->inputEnabled) { if (UNLIKELY(p->nChannels_i < 1 || p->nChannels > 255)) rtJack_Error(csound, -1, Str("invalid number of input channels")); } if (UNLIKELY(p->sampleRate < 1000 || p->sampleRate > 768000)) rtJack_Error(csound, -1, Str("invalid sample rate")); if (UNLIKELY(p->sampleRate != (int) jack_get_sample_rate(p->client))) { snprintf(&(buf[0]), 256, Str("sample rate %d does not match " "JACK sample rate %d"), p->sampleRate, (int) jack_get_sample_rate(p->client)); rtJack_Error(p->csound, -1, &(buf[0])); } if (UNLIKELY(p->bufSize < 8 || p->bufSize > 32768)) rtJack_Error(csound, -1, Str("invalid period size (-b)")); if (p->nBuffers < 2) p->nBuffers = 2; if (UNLIKELY((unsigned int) (p->nBuffers * p->bufSize) > (unsigned int) 65536)) rtJack_Error(csound, -1, Str("invalid buffer size (-B)")); if (UNLIKELY(((p->nBuffers - 1) * p->bufSize) < (int) jack_get_buffer_size(p->client))) rtJack_Error(csound, -1, Str("buffer size (-B) is too small")); /* register ports */ rtJack_RegisterPorts(p); /* allocate ring buffers if not done yet */ if (p->bufs == NULL) rtJack_AllocateBuffers(p); /* initialise ring buffers */ p->csndBufCnt = 0; p->csndBufPos = 0; p->jackBufCnt = 0; p->jackBufPos = 0; for (i = 0; i < p->nBuffers; i++) { rtJack_TryLock(p->csound, &(p->bufs[i]->csndLock)); rtJack_Unlock(p->csound, &(p->bufs[i]->jackLock)); if (p->inputEnabled) { for (j = 0; j < p->nChannels_i; j++) { for (k = 0; k < p->bufSize; k++) p->bufs[i]->inBufs[j][k] = (jack_default_audio_sample_t) 0; } } if (p->outputEnabled) { for (j = 0; j < p->nChannels; j++) { for (k = 0; k < p->bufSize; k++) p->bufs[i]->outBufs[j][k] = (jack_default_audio_sample_t) 0; } } } /* output port buffer pointer cache is invalid initially */ if (p->outputEnabled) p->outPortBufs[0] = (jack_default_audio_sample_t*) NULL; /* register callback functions */ if (UNLIKELY(jack_set_sample_rate_callback(p->client, sampleRateCallback, (void*) p) != 0)) rtJack_Error(csound, -1, Str("error setting sample rate callback")); if (UNLIKELY(jack_set_buffer_size_callback(p->client, bufferSizeCallback, (void*) p) != 0)) rtJack_Error(csound, -1, Str("error setting buffer size callback")); #ifdef LINUX if (UNLIKELY(jack_set_freewheel_callback(p->client, freeWheelCallback, (void*) p) != 0)) rtJack_Error(csound, -1, Str("error setting freewheel callback")); #endif if (UNLIKELY(jack_set_xrun_callback(p->client, xrunCallback, (void*) p) != 0)) rtJack_Error(csound, -1, Str("error setting xrun callback")); jack_on_shutdown(p->client, shutDownCallback, (void*) p); if (UNLIKELY(jack_set_process_callback(p->client, processCallback, (void*) p) != 0)) rtJack_Error(csound, -1, Str("error setting process callback")); /* activate client */ if (UNLIKELY(jack_activate(p->client) != 0)) rtJack_Error(csound, -1, Str("error activating JACK client")); /* connect ports if requested */ if (p->inputEnabled) { listPorts(csound,0); if (p->inDevNum >= 0){ int num = p->inDevNum; unsigned long portFlags = JackPortIsOutput; char **portNames = (char**) jack_get_ports(p->client, (char*) NULL, JACK_DEFAULT_AUDIO_TYPE, portFlags); for (i = 0; i < p->nChannels_i; i++) { if (portNames[num+i] != NULL){ csound->Message(csound, Str("connecting channel %d to %s \n"), i,portNames[num+i]); if (jack_connect(p->client, portNames[num+i], jack_port_name(p->inPorts[i])) != 0) { csound->Warning(csound, Str("failed autoconnecting input channel %d \n" "(needs manual connection)"), i+1); } } else csound->Warning(csound, Str("jack port %d not valid \n" "failed autoconnecting input channel %d \n" "(needs manual connection)"), num+i, i+1); } jack_free(portNames); } else { if (strcmp(p->outDevName, "null") && p->inDevName != NULL){ char dev[128], *dev_final, *sp; strncpy(dev, p->inDevName, 128); dev[127]='\0'; dev_final = dev; sp = strchr(dev_final, '\0'); if (!isalpha(dev_final[0])) dev_final++; for (i = 0; i < p->nChannels; i++) { snprintf(sp, 128-(dev-sp), "%d", i + 1); csound->Message(csound, Str("connecting channel %d to %s \n"), i, dev_final); if (UNLIKELY(jack_connect(p->client, dev_final, jack_port_name(p->inPorts[i])) != 0)) { csound->Warning(csound, Str("not autoconnecting input channel %d \n" "(needs manual connection)"), i+1); } } *sp = (char) 0; } csound->Message(csound, Str("put port not connected\n")); } } if (p->outputEnabled) { listPorts(csound,1); if (p->outDevNum >= 0) { int num = p->outDevNum; unsigned long portFlags = JackPortIsInput; char **portNames = (char**) jack_get_ports(p->client, (char*) NULL, JACK_DEFAULT_AUDIO_TYPE, portFlags); for (i = 0; i < p->nChannels; i++) { if (portNames[num+i] != NULL) { csound->Message(csound, Str("connecting channel %d to %s \n"), i,portNames[num+i]); if (jack_connect(p->client, jack_port_name(p->outPorts[i]), portNames[num+i]) != 0) { csound->Warning(csound, Str("failed autoconnecting output channel %d \n" "(needs manual connection)"), i+1); } } else csound->Warning(csound, Str("jack port %d not valid \n" "failed autoconnecting output channel %d \n" "(needs manual connection)"), num+i, i+1); } jack_free(portNames); } else { if (p->outDevName != NULL && strcmp(p->outDevName, "null")){ char dev[128], *dev_final, *sp; strncpy(dev, p->outDevName, 128); dev[127]='\0'; dev_final = dev; sp = strchr(dev_final, '\0'); if (!isalpha(dev_final[0])) dev_final++; for (i = 0; i < p->nChannels; i++) { snprintf(sp, 128-(dev-sp), "%d", i + 1); csound->Message(csound, Str("connecting channel %d to %s \n"), i, dev_final); if (UNLIKELY(jack_connect(p->client, jack_port_name(p->outPorts[i]), dev_final) != 0)) { csound->Warning(csound, Str("failed to autoconnect output channel " "%d \n(needs manual connection)"), i+1); } } *sp = (char) 0; } else csound->Message(csound, Str("output port not connected\n")); } } /* stream is now active */ p->jackState = 0; } /* Make a copy of the device name specified for -i adc or -o dac, */ /* allocating extra space for a channel number suffix. */ /* Also set up other device parameters, and check consistency. */ static void rtJack_CopyDevParams(RtJackGlobals *p, const csRtAudioParams *parm, int isOutput) { CSOUND *csound; char *s; size_t nBytes; csound = p->csound; if (parm->devNum != 1024) { if (isOutput){ p->outDevNum = parm->devNum; p->outDevName = NULL; } else { p->inDevNum = parm->devNum; p->inDevName = NULL; } } else { if (parm->devName != NULL && parm->devName[0] != (char) 0) { /* NOTE: this assumes max. 999 channels (the current limit is 255) */ nBytes = strlen(parm->devName) + 4; s = (char*) csound->Malloc(csound, nBytes+1); if (UNLIKELY(s == NULL)) rtJack_Error(csound, CSOUND_MEMORY, Str("memory allocation failure")); strcpy(s, parm->devName); if (isOutput){ p->outDevNum = -1; p->outDevName = s; } else { p->inDevName = s; p->inDevNum = -1; } } if (isOutput && p->inputEnabled) { /* full duplex audio I/O: check consistency of parameters */ if (UNLIKELY(/*p->nChannels != parm->nChannels ||*/ (unsigned int)p->bufSize != parm->bufSamp_SW)) rtJack_Error(csound, -1, Str("input and output parameters are not consistent")); if (UNLIKELY((unsigned int)((parm->bufSamp_SW / csound->GetKsmps(csound)) * csound->GetKsmps(csound)) != parm->bufSamp_SW)) rtJack_Error(csound, -1, Str("period size (-b) must be an integer " "multiple of ksmps")); } } p->sampleRate = (int) parm->sampleRate; if (UNLIKELY((float) p->sampleRate != parm->sampleRate)) rtJack_Error(csound, -1, Str("sample rate must be an integer")); if (isOutput) p->nChannels = parm->nChannels; else p->nChannels_i = parm->nChannels; p->bufSize = parm->bufSamp_SW; p->nBuffers = (parm->bufSamp_HW + parm->bufSamp_SW - 1) / parm->bufSamp_SW; } /* open for audio input */ static int recopen_(CSOUND *csound, const csRtAudioParams *parm) { RtJackGlobals *p; p = (RtJackGlobals*) csound->QueryGlobalVariable(csound, "_rtjackGlobals"); if (p == NULL) return -1; *(csound->GetRtRecordUserData(csound)) = (void*) p; rtJack_CopyDevParams(p, parm, 0); p->inputEnabled = 1; /* allocate pointers to input ports */ p->inPorts = (jack_port_t**) csound->Calloc(csound, (size_t) p->nChannels_i* sizeof(jack_port_t*)); if (UNLIKELY(p->inPorts == NULL)) rtJack_Error(p->csound, CSOUND_MEMORY, Str("memory allocation failure")); /* allocate pointers to input port buffers */ p->inPortBufs = (jack_default_audio_sample_t**) csound->Calloc(csound, (size_t)p->nChannels_i * sizeof(jack_default_audio_sample_t*)); if (UNLIKELY(p->inPortBufs == NULL)) rtJack_Error(p->csound, CSOUND_MEMORY, Str("memory allocation failure")); return 0; } /* open for audio output */ static int playopen_(CSOUND *csound, const csRtAudioParams *parm) { RtJackGlobals *p; p = (RtJackGlobals*) csound->QueryGlobalVariable(csound, "_rtjackGlobals"); if (p == NULL) return -1; *(csound->GetRtPlayUserData(csound)) = (void*) p; rtJack_CopyDevParams(p, parm, 1); p->outputEnabled = 1; /* allocate pointers to output ports */ p->outPorts = (jack_port_t**) csound->Calloc(csound, (size_t) p->nChannels* sizeof(jack_port_t*)); if (UNLIKELY(p->outPorts == NULL)) rtJack_Error(p->csound, CSOUND_MEMORY, Str("memory allocation failure")); /* allocate pointers to output port buffers */ p->outPortBufs = (jack_default_audio_sample_t**) csound->Calloc(csound, (size_t) p->nChannels* sizeof(jack_default_audio_sample_t*)); if (UNLIKELY(p->outPortBufs == NULL)) rtJack_Error(p->csound, CSOUND_MEMORY, Str("memory allocation failure")); /* activate client to start playback */ openJackStreams(p); return 0; } /* the process callback is called by the JACK client thread, */ /* and copies data to the input and from the output ring buffers */ static int processCallback(jack_nframes_t nframes, void *arg) { RtJackGlobals *p; int i, j, k, l; p = (RtJackGlobals*) arg; /* get pointers to port buffers */ if (p->inputEnabled) { for (i = 0; i < p->nChannels_i; i++) p->inPortBufs[i] = (jack_default_audio_sample_t*) jack_port_get_buffer(p->inPorts[i], nframes); } if (p->outputEnabled && p->outPortBufs[0] == NULL) { for (i = 0; i < p->nChannels; i++) p->outPortBufs[i] = (jack_default_audio_sample_t*) jack_port_get_buffer(p->outPorts[i], nframes); } i = 0; do { /* if starting new buffer: */ if (p->jackBufPos == 0) { /* check for xrun: */ if (rtJack_TryLock(p->csound, &(p->bufs[p->jackBufCnt]->jackLock)) != 0) { p->xrunFlag = 1; /* yes, discard input and fill output with zero samples */ if (p->outputEnabled) { for (j = 0; j < p->nChannels; j++) for (k = i; k < (int) nframes; k++) p->outPortBufs[j][k] = (jack_default_audio_sample_t) 0; return 0; } } } /* copy audio data on each channel */ k = (int) nframes - i; l = p->bufSize - p->jackBufPos; l = (l < k ? l : k); /* number of frames to copy */ if (p->inputEnabled) { for (j = 0; j < p->nChannels_i; j++) { jack_default_audio_sample_t *srcp, *dstp; srcp = &(p->inPortBufs[j][i]); dstp = &(p->bufs[p->jackBufCnt]->inBufs[j][p->jackBufPos]); for (k = 0; k < l; k++) dstp[k] = srcp[k]; } } if (p->outputEnabled) { for (j = 0; j < p->nChannels; j++) { jack_default_audio_sample_t *srcp, *dstp; srcp = &(p->bufs[p->jackBufCnt]->outBufs[j][p->jackBufPos]); dstp = &(p->outPortBufs[j][i]); for (k = 0; k < l; k++) dstp[k] = srcp[k]; } } p->jackBufPos += l; i += l; /* if done with a buffer, notify Csound thread and advance to next one */ if (p->jackBufPos >= p->bufSize) { p->jackBufPos = 0; rtJack_Unlock(p->csound, &(p->bufs[p->jackBufCnt]->csndLock)); if (++(p->jackBufCnt) >= p->nBuffers) p->jackBufCnt = 0; } } while (i < (int) nframes); return 0; } static CS_NOINLINE CS_NORETURN void rtJack_Abort(CSOUND *csound, int err) { switch (err) { case 1: rtJack_Error(csound, -1, Str("JACK sample rate changed")); break; default: rtJack_Error(csound, -1, Str("no connection to JACK server")); } } static CS_NOINLINE void rtJack_Restart(RtJackGlobals *p) { CSOUND *csound = p->csound; csound->ErrorMsg(csound, Str(" *** rtjack: connection to JACK " "server was lost, reconnecting...")); p->jackState = -1; jack_client_close(p->client); openJackStreams(p); } /* get samples from ADC */ static int rtrecord_(CSOUND *csound, MYFLT *inbuf_, int bytes_) { RtJackGlobals *p; int i, j, k, nframes, bufpos, bufcnt; p = (RtJackGlobals*) *(csound->GetRtPlayUserData(csound)); if (UNLIKELY(p==NULL)) rtJack_Abort(csound, 0); if (p->jackState != 0) { if (p->jackState < 0) openJackStreams(p); /* open audio input */ else if (p->jackState == 2) rtJack_Restart(p); else rtJack_Abort(csound, p->jackState); } nframes = bytes_ / (p->nChannels_i * (int) sizeof(MYFLT)); bufpos = p->csndBufPos; bufcnt = p->csndBufCnt; for (i = j = 0; i < nframes; i++) { if (bufpos == 0) { /* wait until there is enough data in ring buffer */ /* VL 28.03.15 -- timeout after wait for 10 buffer lengths */ int ret = rtJack_LockTimeout(csound, &(p->bufs[bufcnt]->csndLock), 10000*(nframes/csound->GetSr(csound))); if (ret) { memset(inbuf_, 0, bytes_); OPARMS oparms; csound->GetOParms(csound, &oparms); if (UNLIKELY(oparms.msglevel & 4)) csound->Warning(csound, Str("rtjack: input audio timeout")); return bytes_; } } /* copy audio data */ for (k = 0; k < p->nChannels_i; k++) inbuf_[j++] = (MYFLT) p->bufs[bufcnt]->inBufs[k][i]; if (++bufpos >= p->bufSize) { bufpos = 0; /* notify JACK callback that this buffer has been consumed */ if (!p->outputEnabled) rtJack_Unlock(csound, &(p->bufs[bufcnt]->jackLock)); /* advance to next buffer */ if (++bufcnt >= p->nBuffers) bufcnt = 0; } } if (!p->outputEnabled) { p->csndBufPos = bufpos; p->csndBufCnt = bufcnt; } if (p->xrunFlag) { p->xrunFlag = 0; OPARMS oparms; csound->GetOParms(csound, &oparms); if (UNLIKELY(oparms.msglevel & 4)) csound->Warning(csound, Str("rtjack: xrun in real time audio")); } return bytes_; } /* put samples to DAC */ static void rtplay_(CSOUND *csound, const MYFLT *outbuf_, int bytes_) { RtJackGlobals *p; int i, j, k, nframes; p = (RtJackGlobals*) *(csound->GetRtPlayUserData(csound)); if (p == NULL) return; if (p->jackState != 0) { if (p->jackState == 2) rtJack_Restart(p); else rtJack_Abort(csound, p->jackState); return; } nframes = bytes_ / (p->nChannels * (int) sizeof(MYFLT)); for (i = j = 0; i < nframes; i++) { if (p->csndBufPos == 0) { /* wait until there is enough free space in ring buffer */ if (!p->inputEnabled) /* **** COVERITY: claims this is a double lock **** */ rtJack_Lock(csound, &(p->bufs[p->csndBufCnt]->csndLock)); } /* copy audio data */ for (k = 0; k < p->nChannels; k++) p->bufs[p->csndBufCnt]->outBufs[k][i] = (jack_default_audio_sample_t) outbuf_[j++]; if (++(p->csndBufPos) >= p->bufSize) { p->csndBufPos = 0; /* notify JACK callback that this buffer is now filled */ rtJack_Unlock(csound, &(p->bufs[p->csndBufCnt]->jackLock)); /* advance to next buffer */ if (++(p->csndBufCnt) >= p->nBuffers) p->csndBufCnt = 0; } } if (p->xrunFlag) { p->xrunFlag = 0; csound->Warning(csound, Str("rtjack: xrun in real time audio")); } } /* release ring buffers */ static void rtJack_DeleteBuffers(RtJackGlobals *p) { RtJackBuffer **bufs; size_t i; if (p->bufs == (RtJackBuffer**) NULL) return; bufs = p->bufs; p->bufs = (RtJackBuffer**) NULL; for (i = (size_t) 0; i < (size_t) p->nBuffers; i++) { if (bufs[i]->inBufs == (jack_default_audio_sample_t**) NULL && bufs[i]->outBufs == (jack_default_audio_sample_t**) NULL) continue; rtJack_DestroyLock(p->csound, &(bufs[i]->csndLock)); rtJack_DestroyLock(p->csound, &(bufs[i]->jackLock)); } p->csound->Free(p->csound,(void*) bufs); } /* close the I/O device entirely */ /* called only when both complete */ static CS_NOINLINE void rtclose_(CSOUND *csound) { RtJackGlobals p; RtJackGlobals *pp; int i; pp = (RtJackGlobals*) csound->QueryGlobalVariable(csound, "_rtjackGlobals"); if (pp == NULL) return; *(csound->GetRtPlayUserData(csound)) = NULL; *(csound->GetRtRecordUserData(csound)) = NULL; memcpy(&p, pp, sizeof(RtJackGlobals)); /* free globals */ if (p.client != (jack_client_t*) NULL) { /* deactivate client */ //if (p.jackState != 2) { //if (p.jackState == 0) // csound->Sleep((size_t) // ((int) ((double) (p.bufSize * p.nBuffers) // * 1000.0 / (double) p.sampleRate + 0.999))); jack_deactivate(p.client); //} csound->Sleep((size_t) 50); /* unregister and free all ports */ if (p.inPorts != NULL) { for (i = 0; i < p.nChannels_i; i++) { if (p.inPorts[i] != NULL && p.jackState != 2) jack_port_unregister(p.client, p.inPorts[i]); } } if (p.outPorts != NULL) { for (i = 0; i < p.nChannels; i++) { if (p.outPorts[i] != NULL && p.jackState != 2) jack_port_unregister(p.client, p.outPorts[i]); } } /* close connection */ if (p.jackState != 2) { jack_client_close(p.client); } } /* free copy of input and output device name */ if (p.inDevName != NULL) csound->Free(csound,p.inDevName); if (p.outDevName != NULL) csound->Free(csound,p.outDevName); /* free ports and port buffer pointers */ if (p.inPorts != NULL) csound->Free(csound,p.inPorts); if (p.inPortBufs != NULL) csound->Free(csound,p.inPortBufs); if (p.outPorts != NULL) csound->Free(csound,p.outPorts); if (p.outPortBufs != NULL) csound->Free(csound,p.outPortBufs); /* free ring buffers */ rtJack_DeleteBuffers(&p); csound->DestroyGlobalVariable(csound, "_rtjackGlobals"); } /* print error message, close connection, and terminate performance */ static CS_NORETURN void rtJack_Error(CSOUND *csound, int errCode, const char *msg) { csound->ErrorMsg(csound, " *** rtjack: %s", msg); rtclose_(csound); csound->LongJmp(csound, errCode); } int listDevices(CSOUND *csound, CS_AUDIODEVICE *list, int isOutput){ char **portNames = (char**) NULL, port[64]; unsigned long portFlags; int i, n, cnt=0; jack_client_t *jackClient; RtJackGlobals* p = (RtJackGlobals*) csound->QueryGlobalVariableNoCheck(csound, "_rtjackGlobals"); if (p->listclient == NULL) p->listclient = jack_client_open("list", JackNoStartServer, NULL); jackClient = p->listclient; if (jackClient == NULL) return 0; portFlags = (isOutput ? (unsigned long) JackPortIsInput : (unsigned long) JackPortIsOutput); portNames = (char**) jack_get_ports(jackClient, (char*) NULL, JACK_DEFAULT_AUDIO_TYPE, portFlags); if (portNames == NULL) { jack_client_close(jackClient); p->listclient = NULL; return 0; } memset(port, '\0', 64); for(i=0; portNames[i] != NULL; i++, cnt++) { n = (int) strlen(portNames[i]); strncpy(port, portNames[i], n); port[n] = '\0'; if (list != NULL) { strncpy(list[cnt].device_name, port, 63); snprintf(list[cnt].device_id, 63, "%s%d", isOutput ? "dac" : "adc", cnt); list[cnt].max_nchnls = 1; list[cnt].isOutput = isOutput; } } jack_free(portNames); jack_client_close(jackClient); p->listclient = NULL; return cnt; } typedef struct RtJackMIDIGlobals_ { char clientName[MAX_NAME_LEN]; char inputPortName[MAX_NAME_LEN]; char outputPortName[MAX_NAME_LEN]; } RtJackMIDIGlobals; /* module interface functions */ PUBLIC int csoundModuleCreate(CSOUND *csound) { RtJackGlobals *p; int i, j; OPARMS oparms; csound->GetOParms(csound, &oparms); /* allocate and initialise globals */ if (UNLIKELY(oparms.msglevel & 0x400)) csound->Message(csound, Str("JACK real-time audio module for Csound\n")); if (UNLIKELY(csound->CreateGlobalVariable(csound, "_rtjackGlobals", sizeof(RtJackGlobals)) != 0)) { csound->ErrorMsg(csound, Str(" *** rtjack: error allocating globals")); return -1; } p = (RtJackGlobals*) csound->QueryGlobalVariableNoCheck(csound, "_rtjackGlobals"); p->csound = csound; p->jackState = -1; strcpy(&(p->clientName[0]), "csound6"); strcpy(&(p->inputPortName[0]), "input"); strcpy(&(p->outputPortName[0]), "output"); p->sleepTime = 1000; /* this is not actually used */ p->inDevName = (char*) NULL; p->outDevName = (char*) NULL; p->client = (jack_client_t*) NULL; p->inPorts = (jack_port_t**) NULL; p->inPortBufs = (jack_default_audio_sample_t**) NULL; p->outPorts = (jack_port_t**) NULL; p->outPortBufs = (jack_default_audio_sample_t**) NULL; p->bufs = (RtJackBuffer**) NULL; /* register options: */ /* client name */ i = jack_client_name_size(); if (i > (MAX_NAME_LEN + 1)) i = (MAX_NAME_LEN + 1); csound->CreateConfigurationVariable(csound, "jack_client", (void*) &(p->clientName[0]), CSOUNDCFG_STRING, 0, NULL, &i, Str("JACK client name (default: csound6)"), NULL); /* input port name */ i = jack_port_name_size() - 3; if (i > (MAX_NAME_LEN + 1)) i = (MAX_NAME_LEN + 1); csound->CreateConfigurationVariable(csound, "jack_inportname", (void*) &(p->inputPortName[0]), CSOUNDCFG_STRING, 0, NULL, &i, Str("JACK input port name prefix " "(default: input)"), NULL); /* output port name */ i = jack_port_name_size() - 3; if (i > (MAX_NAME_LEN + 1)) i = (MAX_NAME_LEN + 1); csound->CreateConfigurationVariable(csound, "jack_outportname", (void*) &(p->outputPortName[0]), CSOUNDCFG_STRING, 0, NULL, &i, Str("JACK output port name prefix" " (default: output)"), NULL); /* sleep time */ i = 250; j = 25000; /* min/max value */ csound->CreateConfigurationVariable(csound, "jack_sleep_time", (void*) &(p->sleepTime), CSOUNDCFG_INTEGER, 0, &i, &j, Str("Deprecated"), NULL); /* done */ p->listclient = NULL; RtJackMIDIGlobals *pm; if (oparms.msglevel & 0x400) csound->Message(csound, Str("JACK MIDI module for Csound\n")); if (csound->CreateGlobalVariable(csound, "_rtjackMIDIGlobals", sizeof(RtJackMIDIGlobals)) != 0) { csound->ErrorMsg(csound, Str(" *** rtjack MIDI: error allocating globals")); return -1; } pm = (RtJackMIDIGlobals*) csound->QueryGlobalVariableNoCheck(csound, "_rtjackMIDIGlobals"); strcpy(&(pm->clientName[0]), "csound6-midi"); strcpy(&(pm->inputPortName[0]), "port"); strcpy(&(pm->outputPortName[0]), "port"); /* client name */ i = jack_client_name_size(); if (i > (MAX_NAME_LEN + 1)) i = (MAX_NAME_LEN + 1); csound->CreateConfigurationVariable(csound, "jack_midi_client", (void*) &(pm->clientName[0]), CSOUNDCFG_STRING, 0, NULL, &i, Str("JACK MIDI client name prefix" " (default: csound6-midi)"), NULL); /* input port name */ i = jack_port_name_size() - 3; if (i > (MAX_NAME_LEN + 1)) i = (MAX_NAME_LEN + 1); csound->CreateConfigurationVariable(csound, "jack_midi_inportname", (void*) &(pm->inputPortName[0]), CSOUNDCFG_STRING, 0, NULL, &i, Str("JACK MIDI input port name" "(default: port)"), NULL); /* output port name */ i = jack_port_name_size() - 3; if (i > (MAX_NAME_LEN + 1)) i = (MAX_NAME_LEN + 1); csound->CreateConfigurationVariable(csound, "jack_midi_outportname", (void*) &(pm->outputPortName[0]), CSOUNDCFG_STRING, 0, NULL, &i, Str("JACK MIDI output port name" " (default: port)"), NULL); return 0; } #define JACK_MIDI_BUFFSIZE 1024 typedef struct jackMidiDevice_ { jack_client_t *client; jack_port_t *port; CSOUND *csound; void *cb; } jackMidiDevice; int MidiInProcessCallback(jack_nframes_t nframes, void *userData){ jack_midi_event_t event; jackMidiDevice *dev = (jackMidiDevice *) userData; CSOUND *csound = dev->csound; int n = 0; while(jack_midi_event_get(&event, jack_port_get_buffer(dev->port,nframes), n++) == 0) { if (UNLIKELY(csound->WriteCircularBuffer(csound,dev->cb, event.buffer,event.size) != (int) event.size)){ csound->Warning(csound, Str("Jack MIDI module: buffer overflow")); return 1; } } return 0; } static int midi_in_open(CSOUND *csound, void **userData, const char *devName){ jack_client_t *jack_client; jack_port_t *jack_port; jackMidiDevice *dev; RtJackMIDIGlobals *pm; char clientName[MAX_NAME_LEN+3]; pm = (RtJackMIDIGlobals*) csound->QueryGlobalVariableNoCheck(csound, "_rtjackMIDIGlobals"); sprintf(clientName, "%s_in", pm->clientName); if (UNLIKELY((jack_client = jack_client_open(clientName, 0, NULL)) == NULL)){ *userData = NULL; csound->ErrorMsg(csound, Str("Jack MIDI module: failed to create client for input")); return NOTOK; } if (UNLIKELY((jack_port = jack_port_register(jack_client,pm->inputPortName, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput|JackPortIsTerminal, 0)) == NULL)){ jack_client_close(jack_client); *userData = NULL; csound->ErrorMsg(csound, Str("Jack MIDI module: failed to register input port")); return NOTOK; } dev = (jackMidiDevice *) csound->Calloc(csound,sizeof(jackMidiDevice)); dev->client = jack_client; dev->port = jack_port; dev->csound = csound; dev->cb = csound->CreateCircularBuffer(csound, JACK_MIDI_BUFFSIZE, sizeof(char)); if (UNLIKELY(jack_set_process_callback(jack_client, MidiInProcessCallback, (void*) dev) != 0)){ jack_client_close(jack_client); csound->DestroyCircularBuffer(csound, dev->cb); csound->Free(csound, dev); csound->ErrorMsg(csound, Str("Jack MIDI module: failed to set input" " process callback")); return NOTOK; } if (UNLIKELY(jack_activate(jack_client) != 0)){ jack_client_close(jack_client); csound->DestroyCircularBuffer(csound, dev->cb); csound->Free(csound, dev); *userData = NULL; csound->ErrorMsg(csound, Str("Jack MIDI module: failed to activate input")); return NOTOK; } if (strcmp(devName,"0")){ if (UNLIKELY(jack_connect(jack_client,devName, jack_port_name(dev->port)) != 0)){ csound->Warning(csound, Str("Jack MIDI module: failed to connect to: %s"), devName); } } *userData = (void *) dev; return OK; } static int midi_in_read(CSOUND *csound, void *userData, unsigned char *buf, int nbytes) { jackMidiDevice *dev = (jackMidiDevice *) userData; return csound->ReadCircularBuffer(csound,dev->cb,buf,nbytes); } static int midi_in_close(CSOUND *csound, void *userData){ jackMidiDevice *dev = (jackMidiDevice *) userData; if(dev != NULL) { jack_port_disconnect(dev->client, dev->port); jack_client_close(dev->client); csound->DestroyCircularBuffer(csound, dev->cb); csound->Free(csound, dev); } return OK; } int MidiOutProcessCallback(jack_nframes_t nframes, void *userData){ jackMidiDevice *dev = (jackMidiDevice *) userData; CSOUND *csound = dev->csound; jack_midi_data_t buf[JACK_MIDI_BUFFSIZE]; int n; jack_midi_clear_buffer(jack_port_get_buffer(dev->port,nframes)); while((n = csound->ReadCircularBuffer(csound,dev->cb, buf, JACK_MIDI_BUFFSIZE)) != 0) { if(UNLIKELY(jack_midi_event_write(jack_port_get_buffer(dev->port,nframes), 0, buf,n) != 0)){ csound->Warning(csound, Str("Jack MIDI module: out buffer overflow")); return 1; } } return 0; } static int midi_out_open(CSOUND *csound, void **userData, const char *devName) { jack_client_t *jack_client; jack_port_t *jack_port; jackMidiDevice *dev; RtJackMIDIGlobals *pm; char clientName[MAX_NAME_LEN+4]; pm = (RtJackMIDIGlobals*) csound->QueryGlobalVariableNoCheck(csound, "_rtjackMIDIGlobals"); sprintf(clientName, "%s_out", pm->clientName); if(UNLIKELY((jack_client = jack_client_open(clientName, 0, NULL)) == NULL)){ *userData = NULL; csound->ErrorMsg(csound, Str("Jack MIDI module: failed to create client for output")); return NOTOK; } if(UNLIKELY((jack_port = jack_port_register(jack_client,pm->outputPortName, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0)) == NULL)){ jack_client_close(jack_client); *userData = NULL; csound->ErrorMsg(csound, Str("Jack MIDI module: failed to register output port")); return NOTOK; } dev = (jackMidiDevice *) csound->Calloc(csound,sizeof(jackMidiDevice)); dev->client = jack_client; dev->port = jack_port; dev->csound = csound; dev->cb = csound->CreateCircularBuffer(csound, JACK_MIDI_BUFFSIZE, sizeof(char)); if(UNLIKELY(jack_set_process_callback(jack_client, MidiOutProcessCallback, (void*) dev) != 0)){ jack_client_close(jack_client); csound->DestroyCircularBuffer(csound, dev->cb); csound->Free(csound, dev); csound->ErrorMsg(csound, Str("Jack MIDI module: failed to set input" " process callback")); return NOTOK; } if(UNLIKELY(jack_activate(jack_client) != 0)){ jack_client_close(jack_client); csound->DestroyCircularBuffer(csound, dev->cb); csound->Free(csound, dev); *userData = NULL; csound->ErrorMsg(csound, Str("Jack MIDI module: failed to activate output")); return NOTOK; } if(strcmp(devName,"0")){ if(UNLIKELY(jack_connect(jack_client, jack_port_name(dev->port),devName) != 0)){ csound->Warning(csound, Str("Jack MIDI out module: failed to connect to: %s"), devName); } } *userData = (void *) dev; return OK; } static int midi_out_write(CSOUND *csound, void *userData, const unsigned char *buf, int nbytes) { jackMidiDevice *dev = (jackMidiDevice *) userData; return csound->WriteCircularBuffer(csound,dev->cb,buf,nbytes); return OK; } static int midi_out_close(CSOUND *csound, void *userData){ jackMidiDevice *dev = (jackMidiDevice *) userData; if(dev != NULL) { jack_port_disconnect(dev->client, dev->port); jack_client_close(dev->client); csound->DestroyCircularBuffer(csound, dev->cb); csound->Free(csound, dev); } return OK; } static int listDevicesM(CSOUND *csound, CS_MIDIDEVICE *list, int isOutput){ char **portNames = (char**) NULL, port[64]; unsigned long portFlags; int i, n, cnt=0; jack_client_t *jackClient; RtJackGlobals* p = (RtJackGlobals*) csound->QueryGlobalVariableNoCheck(csound, "_rtjackGlobals"); char *drv = (char*) (csound->QueryGlobalVariable(csound, "_RTMIDI")); if(p->listclient == NULL) p->listclient = jack_client_open("list", JackNoStartServer, NULL); jackClient = p->listclient; if(jackClient == NULL) return 0; portFlags = (isOutput ? (unsigned long) JackPortIsInput : (unsigned long) JackPortIsOutput); portNames = (char**) jack_get_ports(jackClient, (char*) NULL, JACK_DEFAULT_MIDI_TYPE, portFlags); if(portNames == NULL) { jack_client_close(jackClient); p->listclient = NULL; return 0; } memset(port, '\0', 64); for(i=0; portNames[i] != NULL; i++, cnt++) { n = (int) strlen(portNames[i]); strncpy(port, portNames[i], n); port[n] = '\0'; if (list != NULL) { strncpy(list[cnt].device_name, port, 63); snprintf(list[cnt].device_id, 63, "%d", cnt); list[cnt].isOutput = isOutput; strcpy(list[i].interface_name, ""); strncpy(list[i].midi_module, drv, 63); } } jack_free(portNames); jack_client_close(jackClient); p->listclient = NULL; return cnt; return 0; } /* static int listDevices(CSOUND *csound, CS_MIDIDEVICE *list, int isOutput){ int i, cnt; PmDeviceInfo *info; char tmp[64]; char *drv = (char*) (csound->QueryGlobalVariable(csound, "_RTMIDI")); if (UNLIKELY(start_portmidi(csound) != 0)) return 0; cnt = portMidi_getDeviceCount(isOutput); if (list == NULL) return cnt; for (i = 0; i < cnt; i++) { info = portMidi_getDeviceInfo(i, isOutput); if(info->name != NULL) strncpy(list[i].device_name, info->name, 63); snprintf(tmp, 64, "%d", i); strncpy(list[i].device_id, tmp, 63); list[i].isOutput = isOutput; if (info->interf != NULL) strncpy(list[i].interface_name, info->interf, 63); else strcpy(list[i].interface_name, ""); strncpy(list[i].midi_module, drv, 63); } return cnt; } */ PUBLIC int csoundModuleDestroy(CSOUND *csound) { RtJackGlobals* p = (RtJackGlobals*) csound->QueryGlobalVariableNoCheck(csound, "_rtjackGlobals"); if(p && p->listclient) { jack_client_close(p->listclient); p->listclient = NULL; } return OK; } PUBLIC int csoundModuleInit(CSOUND *csound) { char *drv; csound->module_list_add(csound,"jack", "audio"); drv = (char*) csound->QueryGlobalVariable(csound, "_RTAUDIO"); if (drv == NULL) return 0; if (!(strcmp(drv, "jack") == 0 || strcmp(drv, "Jack") == 0 || strcmp(drv, "JACK") == 0)) return 0; csound->Message(csound, Str("rtaudio: JACK module enabled\n")); { /* register Csound interface functions */ csound->SetPlayopenCallback(csound, playopen_); csound->SetRecopenCallback(csound, recopen_); csound->SetRtplayCallback(csound, rtplay_); csound->SetRtrecordCallback(csound, rtrecord_); csound->SetRtcloseCallback(csound, rtclose_); csound->SetAudioDeviceListCallback(csound, listDevices); } drv = (char*) csound->QueryGlobalVariable(csound, "_RTMIDI"); if (drv == NULL) return 0; if (!(strcmp(drv, "jack") == 0 || strcmp(drv, "Jack") == 0 || strcmp(drv, "JACK") == 0)) return 0; csound->Message(csound, Str("rtmidi: JACK module enabled\n")); { csound->SetExternalMidiInOpenCallback(csound, midi_in_open); csound->SetExternalMidiReadCallback(csound, midi_in_read); csound->SetExternalMidiInCloseCallback(csound, midi_in_close); csound->SetExternalMidiOutOpenCallback(csound, midi_out_open); csound->SetExternalMidiWriteCallback(csound, midi_out_write); csound->SetExternalMidiOutCloseCallback(csound, midi_out_close); csound->SetMIDIDeviceListCallback(csound,listDevicesM); } return 0; } PUBLIC int csoundModuleInfo(void) { return ((CS_APIVERSION << 16) + (CS_APISUBVER << 8) + (int) sizeof(MYFLT)); } csound-6.10.0/InOut/rtpa.c000066400000000000000000000724451321653344700152650ustar00rootroot00000000000000/* rtpa.c: Copyright (C) 2004, 2005 John ffitch, Istvan Varga, Michael Gogins, Victor Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* RTPA.C for PortAudio */ #include "csdl.h" #if !defined(WIN32) #include "soundio.h" #endif #include #define NO_FULLDUPLEX_PA_LOCK 0 typedef struct PaAlsaStreamInfo { unsigned long size; PaHostApiTypeId hostApiType; unsigned long version; const char *deviceString; } PaAlsaStreamInfo; typedef struct devparams_ { PaStream *handle; /* stream handle */ float *buf; /* sample conversion buffer */ int nchns; /* number of channels */ } DEVPARAMS; typedef struct PA_BLOCKING_STREAM_ { CSOUND *csound; PaStream *paStream; int mode; /* 1: rec, 2: play, 3: full-duplex */ int noPaLock; int inBufSamples; int outBufSamples; int currentInputIndex; int currentOutputIndex; float *inputBuffer; float *outputBuffer; void *paLock; /* thread lock for stream callback */ void *clientLock; /* thread lock for rtplay/rtrecord */ csRtAudioParams inParm; csRtAudioParams outParm; PaStreamParameters inputPaParameters; PaStreamParameters outputPaParameters; #ifdef WIN32 int paused; /* VL: to allow for smooth pausing */ #endif int paLockTimeout; int complete; } PA_BLOCKING_STREAM; static int pa_PrintErrMsg(CSOUND *csound, const char *fmt, ...) { va_list args; va_start(args, fmt); csound->ErrMsgV(csound, Str(" *** PortAudio: error: "), fmt, args); va_end(args); return -1; } static int initPortAudio(CSOUND *csound) { char *s; int err; /* initialise PortAudio */ if (!csound->QueryGlobalVariable(csound, "::PortAudio::NeedsTerminate")) { if (csound->CreateGlobalVariable(csound, "::PortAudio::NeedsTerminate", 1) != 0) return -1; err = (int) Pa_Initialize(); if (UNLIKELY(err != (int) paNoError)) { return pa_PrintErrMsg(csound, "%d: %s", err, Pa_GetErrorText((PaError) err)); } /* print PortAudio version */ if ((s = (char*) Pa_GetVersionText()) != NULL) csound->Message(csound, "%s\n", s); } return 0; } /* list available input or output devices; returns the number of devices */ int listDevices(CSOUND *csound, CS_AUDIODEVICE *list, int isOutput){ PaDeviceInfo *dev_info; PaHostApiInfo *api_info; int i, j, ndev; char tmp[256], *s; if (initPortAudio(csound) != 0) return 0; if ((s = (char*) csound->QueryGlobalVariable(csound, "_RTAUDIO")) == NULL) return 0; ndev = (int) Pa_GetDeviceCount(); for (i = j = 0; i < ndev; i++) { dev_info = (PaDeviceInfo*) Pa_GetDeviceInfo((PaDeviceIndex) i); if ((isOutput && dev_info->maxOutputChannels > 0) || (!isOutput && dev_info->maxInputChannels > 0)) j++; } if (!j) return 0; if(list!=NULL) { for (i = j = 0; i < ndev; i++) { dev_info = (PaDeviceInfo*) Pa_GetDeviceInfo((PaDeviceIndex) i); api_info = (PaHostApiInfo*) Pa_GetHostApiInfo(dev_info->hostApi); if ((isOutput && dev_info->maxOutputChannels > 0) || (!isOutput && dev_info->maxInputChannels > 0)) { //strncpy(list[j].device_name, dev_info->name, 63); snprintf(list[j].device_name, 63, "%s [%s]", dev_info->name, api_info->name); if (isOutput) { snprintf(tmp, 256, "dac%d", j); } else { snprintf(tmp, 256, "adc%d", j); } strncpy(list[j].device_id, tmp, 63); strncpy(list[j].rt_module, s, 63); list[j].max_nchnls = isOutput ? dev_info->maxOutputChannels : dev_info->maxInputChannels; list[j].isOutput = isOutput; j++; } } } return j; } static int listPortAudioDevices_blocking(CSOUND *csound, int print_list, int play) { int i,n = listDevices(csound, NULL, play); CS_AUDIODEVICE *devs = (CS_AUDIODEVICE *) csound->Malloc(csound, n*sizeof(CS_AUDIODEVICE)); listDevices(csound, devs, play); for(i=0; i < n; i++) csound->Message(csound, " %3d: %s (%s)\n", i, devs[i].device_id, devs[i].device_name); csound->Free(csound, devs); return n; } static void DAC_channels(CSOUND *csound, int chans){ int *dachans = (int *) csound->QueryGlobalVariable(csound, "_DAC_CHANNELS_"); if (dachans == NULL) { if (csound->CreateGlobalVariable(csound, "_DAC_CHANNELS_", sizeof(int)) != 0) return; dachans = (int *) csound->QueryGlobalVariable(csound, "_DAC_CHANNELS_"); *dachans = chans; } } static void ADC_channels(CSOUND *csound, int chans){ int *dachans = (int *) csound->QueryGlobalVariable(csound, "_ADC_CHANNELS_"); if (dachans == NULL) { if (csound->CreateGlobalVariable(csound, "_ADC_CHANNELS_", sizeof(int)) != 0) return; dachans = (int *) csound->QueryGlobalVariable(csound, "_ADC_CHANNELS_"); *dachans = chans; } } /* select PortAudio device; returns the actual device number */ static int selectPortAudioDevice(CSOUND *csound, int devNum, int play) { PaDeviceInfo *dev_info; int i, j, maxNum; maxNum = listPortAudioDevices_blocking(csound, 1, play) - 1; if (maxNum < 0) return -1; if (devNum == 1024) { if (play) devNum = (int) Pa_GetDefaultOutputDevice(); else devNum = (int) Pa_GetDefaultInputDevice(); } else { if (devNum < 0 || devNum > maxNum) { /* listPortAudioDevices_blocking(csound, 1, play); */ pa_PrintErrMsg(csound, Str("%s device number %d is out of range"), (play ? Str("output") : Str("input")), devNum); return -1; } for (i = j = 0; j <= maxNum; i++) { dev_info = (PaDeviceInfo*) Pa_GetDeviceInfo((PaDeviceIndex) i); if ((play && dev_info->maxOutputChannels > 0) || (!play && dev_info->maxInputChannels > 0)) { if (j == devNum) break; j++; } } devNum = i; } dev_info = (PaDeviceInfo*) Pa_GetDeviceInfo((PaDeviceIndex) devNum); if (dev_info) { csound->Message(csound, Str("PortAudio: selected %s device '%s'\n"), (play ? Str("output") : Str("input")), dev_info->name); if(play) { csound->system_sr(csound, (MYFLT) dev_info->defaultSampleRate); DAC_channels(csound, dev_info->maxOutputChannels); } else ADC_channels(csound, dev_info->maxInputChannels); } else csound->Message(csound, Str("PortAudio: failed to obtain device info.\n")); return devNum; } static int pa_SetStreamParameters(CSOUND *csound, PaStreamParameters *sp, csRtAudioParams *parm, int is_playback) { int dev; memset(sp, 0, sizeof(PaStreamParameters)); if (UNLIKELY(parm->devName != NULL && parm->devName[0] != '\0')) { return pa_PrintErrMsg(csound, Str("Must specify a device number, not a name")); } dev = selectPortAudioDevice(csound, parm->devNum, is_playback); if (dev < 0) return -1; sp->device = (PaDeviceIndex) dev; sp->channelCount = (parm->nChannels < 2 ? 2 : parm->nChannels); sp->sampleFormat = (PaSampleFormat) paFloat32; sp->suggestedLatency = (PaTime) ((double) parm->bufSamp_HW / (double) parm->sampleRate); sp->hostApiSpecificStreamInfo = NULL; return 0; } static void rtclose_(CSOUND *csound); static int paBlockingReadWriteStreamCallback(const void *, void *, unsigned long, const PaStreamCallbackTimeInfo *, PaStreamCallbackFlags, void *); static int paBlockingReadWriteOpen(CSOUND *csound) { PA_BLOCKING_STREAM *pabs; PaStream *stream = NULL; PaError err; pabs = (PA_BLOCKING_STREAM*) csound->QueryGlobalVariable(csound, "_rtpaGlobals"); if (pabs == NULL) return -1; if (UNLIKELY(initPortAudio(csound) != 0)) goto err_return; if (UNLIKELY((int) Pa_GetDeviceCount() <= 0)) { pa_PrintErrMsg(csound, Str("No sound device is available")); goto err_return; } if (UNLIKELY(pabs->mode & 1)) { if (pa_SetStreamParameters(csound, &(pabs->inputPaParameters), &(pabs->inParm), 0) != 0) goto err_return; pabs->inBufSamples = pabs->inParm.bufSamp_SW * (int) pabs->inputPaParameters.channelCount; pabs->inputBuffer = (float*) csound->Calloc(csound, (size_t) pabs->inBufSamples* sizeof(float)); if (UNLIKELY(pabs->inputBuffer == NULL)) { pa_PrintErrMsg(csound, Str("Memory allocation failure")); goto err_return; } } if (pabs->mode & 2) { if (UNLIKELY(pa_SetStreamParameters(csound, &(pabs->outputPaParameters), &(pabs->outParm), 1) != 0)) goto err_return; pabs->outBufSamples = pabs->outParm.bufSamp_SW * (int) pabs->outputPaParameters.channelCount; pabs->outputBuffer = (float*) csound->Calloc(csound, (size_t) pabs->outBufSamples* sizeof(float)); if (UNLIKELY(pabs->outputBuffer == NULL)) { pa_PrintErrMsg(csound, Str("Memory allocation failure")); goto err_return; } } if ((pabs->mode & 3) == 3) { if (UNLIKELY(pabs->inParm.bufSamp_SW != pabs->outParm.bufSamp_SW)) { pa_PrintErrMsg(csound, Str("Inconsistent full-duplex buffer sizes")); goto err_return; } if (UNLIKELY(pabs->inParm.sampleRate != pabs->outParm.sampleRate)) { pa_PrintErrMsg(csound, Str("Inconsistent full-duplex sample rates")); goto err_return; } if (UNLIKELY(((pabs->inParm.bufSamp_SW / csound->GetKsmps(csound)) * csound->GetKsmps(csound)) != pabs->inParm.bufSamp_SW)) csound->MessageS(csound, CSOUNDMSG_WARNING, Str("WARNING: buffer size should be an integer " "multiple of ksmps in full-duplex mode\n")); #if NO_FULLDUPLEX_PA_LOCK pabs->noPaLock = 1; #endif } pabs->paLock = csound->CreateThreadLock(); if (UNLIKELY(pabs->paLock == NULL)) goto err_return; pabs->clientLock = csound->CreateThreadLock(); if (UNLIKELY(pabs->clientLock == NULL)) goto err_return; #if NO_FULLDUPLEX_PA_LOCK if (!pabs->noPaLock) #endif csound->WaitThreadLock(pabs->paLock, (size_t) 500); csound->WaitThreadLock(pabs->clientLock, (size_t) 500); pabs->paLockTimeout = (int) (1.33 * (pabs->outputPaParameters.suggestedLatency >= pabs->inputPaParameters.suggestedLatency ? pabs->outputPaParameters.suggestedLatency : pabs->inputPaParameters.suggestedLatency)); if (pabs->paLockTimeout < 25) pabs->paLockTimeout = 25; else if (pabs->paLockTimeout > 1000) pabs->paLockTimeout = 1000; err = Pa_OpenStream(&stream, (pabs->mode & 1 ? &(pabs->inputPaParameters) : (PaStreamParameters*) NULL), (pabs->mode & 2 ? &(pabs->outputPaParameters) : (PaStreamParameters*) NULL), (double) (pabs->mode & 2 ? pabs->outParm.sampleRate : pabs->inParm.sampleRate), (unsigned long) (pabs->mode & 2 ? pabs->outParm.bufSamp_SW : pabs->inParm.bufSamp_SW), (csound->GetDitherMode(csound) ? (PaStreamFlags) paNoFlag : (PaStreamFlags) paDitherOff), paBlockingReadWriteStreamCallback, (void*) pabs); if (UNLIKELY(err != paNoError)) { pa_PrintErrMsg(csound, "%d: %s", (int) err, Pa_GetErrorText(err)); goto err_return; } err = Pa_StartStream(stream); if (UNLIKELY(err != paNoError)) { Pa_CloseStream(stream); pa_PrintErrMsg(csound, "%d: %s", (int) err, Pa_GetErrorText(err)); goto err_return; } pabs->paStream = stream; return 0; /* clean up and report error */ err_return: rtclose_(csound); return -1; } static CS_NOINLINE void paClearOutputBuffer(PA_BLOCKING_STREAM *pabs, float *buf) { int nsmps = pabs->outBufSamples; memset(buf,0, nsmps*sizeof(float)); /* int i = 0; */ /* do { */ /* buf[i] = 0.0f; */ /* } while (++i < nsmps); */ } static int paBlockingReadWriteStreamCallback(const void *input, void *output, unsigned long frameCount, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData) { int err; PA_BLOCKING_STREAM *pabs = (PA_BLOCKING_STREAM*) userData; CSOUND *csound = pabs->csound; float *paInput = (float*) input; float *paOutput = (float*) output; if (pabs->complete == 1) { return paComplete; } #ifdef WIN32 if (pabs->paStream == NULL || pabs->paused ) { if (pabs->mode & 2) paClearOutputBuffer(pabs, paOutput); return paContinue; } #endif #if NO_FULLDUPLEX_PA_LOCK err = 0; if (!pabs->noPaLock) #endif /*#ifndef __MACH__*/ /*# ifdef WIN32 */ err = csound->WaitThreadLock(pabs->paLock, (size_t) pabs->paLockTimeout); /*# else err = csound->WaitThreadLock(pabs->paLock, (size_t) 500); # endif #else csound->WaitThreadLock(pabs->paLock, (size_t) 500); err = 0; #endif*/ if (pabs->mode & 1) { int n = pabs->inBufSamples; int i = 0; do { pabs->inputBuffer[i] = paInput[i]; } while (++i < n); } if (pabs->mode & 2) { if (!err) { int n = pabs->outBufSamples; int i = 0; do { paOutput[i] = pabs->outputBuffer[i]; } while (++i < n); } else { #ifdef WIN32 pabs->paused = err; #endif paClearOutputBuffer(pabs, paOutput); } } paClearOutputBuffer(pabs, pabs->outputBuffer); csound->NotifyThreadLock(pabs->clientLock); return paContinue; } /* get samples from ADC */ static int rtrecord_(CSOUND *csound, MYFLT *buffer, int nbytes) { PA_BLOCKING_STREAM *pabs; int i = 0, samples = nbytes / (int) sizeof(MYFLT); pabs = (PA_BLOCKING_STREAM*) *(csound->GetRtRecordUserData(csound)); if (pabs == NULL) { memset(buffer, 0, nbytes); return nbytes; } if (pabs->paStream == NULL) { if (UNLIKELY(paBlockingReadWriteOpen(csound) != 0)) csound->Die(csound, Str("Failed to initialise real time audio input")); } do { buffer[i] = (MYFLT) pabs->inputBuffer[pabs->currentInputIndex++]; if (pabs->inParm.nChannels == 1) pabs->currentInputIndex++; if (pabs->currentInputIndex >= pabs->inBufSamples) { if (pabs->mode == 1) { #if NO_FULLDUPLEX_PA_LOCK if (!pabs->noPaLock) #endif csound->NotifyThreadLock(pabs->paLock); csound->WaitThreadLock(pabs->clientLock, (size_t) 500); } pabs->currentInputIndex = 0; } } while (++i < samples); return nbytes; } /* put samples to DAC */ static void rtplay_(CSOUND *csound, const MYFLT *buffer, int nbytes) { PA_BLOCKING_STREAM *pabs; int i = 0, samples = nbytes / (int) sizeof(MYFLT); pabs = (PA_BLOCKING_STREAM*) *(csound->GetRtPlayUserData(csound)); if (pabs == NULL) return; #ifdef WIN32 pabs->paused = 0; #endif do { pabs->outputBuffer[pabs->currentOutputIndex++] = (float) buffer[i]; if (pabs->outParm.nChannels == 1) pabs->outputBuffer[pabs->currentOutputIndex++] = (float) buffer[i]; if (pabs->currentOutputIndex >= pabs->outBufSamples) { #if NO_FULLDUPLEX_PA_LOCK if (!pabs->noPaLock) #endif csound->NotifyThreadLock(pabs->paLock); csound->WaitThreadLock(pabs->clientLock, (size_t) 500); pabs->currentOutputIndex = 0; } } while (++i < samples); } /* open for audio input */ static int recopen_(CSOUND *csound, const csRtAudioParams *parm) { CSOUND *p = csound; PA_BLOCKING_STREAM *pabs; pabs = (PA_BLOCKING_STREAM*) p->QueryGlobalVariable(p, "_rtpaGlobals"); if (pabs == NULL) { if (p->CreateGlobalVariable(p, "_rtpaGlobals", sizeof(PA_BLOCKING_STREAM)) != 0) return -1; pabs = (PA_BLOCKING_STREAM*) p->QueryGlobalVariable(p, "_rtpaGlobals"); pabs->csound = p; } pabs->mode |= 1; memcpy(&(pabs->inParm), parm, sizeof(csRtAudioParams)); *(p->GetRtRecordUserData(p)) = (void*) pabs; pabs->complete = 0; return 0; } /* open for audio output */ static int playopen_(CSOUND *csound, const csRtAudioParams *parm) { CSOUND *p = csound; PA_BLOCKING_STREAM *pabs; pabs = (PA_BLOCKING_STREAM*) p->QueryGlobalVariable(p, "_rtpaGlobals"); if (pabs == NULL) { if (p->CreateGlobalVariable(p, "_rtpaGlobals", sizeof(PA_BLOCKING_STREAM)) != 0) return -1; pabs = (PA_BLOCKING_STREAM*) p->QueryGlobalVariable(p, "_rtpaGlobals"); pabs->csound = p; } pabs->mode |= 2; memcpy(&(pabs->outParm), parm, sizeof(csRtAudioParams)); *(p->GetRtPlayUserData(p)) = (void*) pabs; pabs->complete = 0; return (paBlockingReadWriteOpen(p)); } /* close the I/O device entirely */ static void rtclose_(CSOUND *csound) { PA_BLOCKING_STREAM *pabs; pabs = (PA_BLOCKING_STREAM*) csound->QueryGlobalVariable(csound, "_rtpaGlobals"); csound->Message(csound, Str("closing device\n")); if (pabs == NULL) return; pabs->complete = 1; if (pabs->paStream != NULL) { PaStream *stream = pabs->paStream; unsigned int i; for (i = 0; i < 4u; i++) { #if NO_FULLDUPLEX_PA_LOCK if (!pabs->noPaLock) #endif csound->NotifyThreadLock(pabs->paLock); csound->NotifyThreadLock(pabs->clientLock); //Pa_Sleep(80); } Pa_StopStream(stream); Pa_CloseStream(stream); //Pa_Sleep(80); } if (pabs->clientLock != NULL) { csound->NotifyThreadLock(pabs->clientLock); csound->DestroyThreadLock(pabs->clientLock); pabs->clientLock = NULL; } if (pabs->paLock != NULL) { csound->NotifyThreadLock(pabs->paLock); csound->DestroyThreadLock(pabs->paLock); pabs->paLock = NULL; } if (pabs->outputBuffer != NULL) { csound->Free(csound,pabs->outputBuffer); pabs->outputBuffer = NULL; } if (pabs->inputBuffer != NULL) { csound->Free(csound,pabs->inputBuffer); pabs->inputBuffer = NULL; } pabs->paStream = NULL; *(csound->GetRtRecordUserData(csound)) = NULL; *(csound->GetRtPlayUserData(csound)) = NULL; csound->DestroyGlobalVariable(csound, "_rtpaGlobals"); } /* set up audio device */ static int set_device_params(CSOUND *csound, DEVPARAMS *dev, const csRtAudioParams *parm, int play) { PaStreamParameters streamParams; CSOUND *p = csound; int err; /* set parameters */ memset(dev, 0, sizeof(DEVPARAMS)); memset(&streamParams, 0, sizeof(PaStreamParameters)); streamParams.hostApiSpecificStreamInfo = NULL; if (UNLIKELY(parm->devName != NULL && parm->devName[0] != '\0')) { #if !defined(LINUX) listPortAudioDevices_blocking(p, 1, play); pa_PrintErrMsg(p, Str("Must specify a device number, not a name")); return -1; #else PaAlsaStreamInfo info; p->Message(p, Str("PortAudio: using ALSA device '%s'\n"), parm->devName); memset(&info, 0, sizeof(PaAlsaStreamInfo)); info.deviceString = parm->devName; info.hostApiType = paALSA; info.version = 1; info.size = sizeof(info); streamParams.device = paUseHostApiSpecificDeviceSpecification; streamParams.hostApiSpecificStreamInfo = &info; #endif } else { int devNum = selectPortAudioDevice(p, parm->devNum, play); if (devNum < 0) return -1; streamParams.device = (PaDeviceIndex) devNum; } streamParams.channelCount = parm->nChannels; streamParams.sampleFormat = paFloat32; streamParams.suggestedLatency = (PaTime) ((double) parm->bufSamp_HW / (double) parm->sampleRate); /* open stream */ if (play) { err = (int) Pa_OpenStream(&(dev->handle), NULL, &streamParams, (double) parm->sampleRate, (unsigned long) parm->bufSamp_SW, (csound->GetDitherMode(csound) ? paNoFlag:paDitherOff), NULL, NULL); } else { err = (int) Pa_OpenStream(&(dev->handle), &streamParams, NULL, (double) parm->sampleRate, (unsigned long) parm->bufSamp_SW, paNoFlag, NULL, NULL); } if (UNLIKELY(err != (int) paNoError)) { pa_PrintErrMsg(p, "%d: %s", err, Pa_GetErrorText((PaError) err)); return -1; } /* set up device parameters */ dev->nchns = parm->nChannels; dev->buf = (float*) p->Calloc(p, (size_t) (parm->bufSamp_SW * parm->nChannels * (int) sizeof(float))); return 0; } /* open for audio input */ static int recopen_blocking(CSOUND *csound, const csRtAudioParams *parm) { DEVPARAMS *dev; int retval; if (initPortAudio(csound) != 0) return -1; /* check if the device is already opened */ if (*(csound->GetRtRecordUserData(csound)) != NULL) return 0; /* allocate structure */ dev = (DEVPARAMS*) csound->Calloc(csound, sizeof(DEVPARAMS)); *(csound->GetRtRecordUserData(csound)) = (void*) dev; /* set up parameters and open stream */ retval = set_device_params(csound, dev, parm, 0); if (retval != 0) { csound->Free(csound, dev); *(csound->GetRtRecordUserData(csound)) = NULL; } else Pa_StartStream(dev->handle); return retval; } /* open for audio output */ static int playopen_blocking(CSOUND *csound, const csRtAudioParams *parm) { DEVPARAMS *dev; int retval; if (initPortAudio(csound) != 0) return -1; /* check if the device is already opened */ if (*(csound->GetRtPlayUserData(csound)) != NULL) return 0; /* allocate structure */ dev = (DEVPARAMS*) csound->Calloc(csound, sizeof(DEVPARAMS)); *(csound->GetRtPlayUserData(csound)) = (void*) dev; /* set up parameters and open stream */ retval = set_device_params(csound, dev, parm, 1); if (retval != 0) { csound->Free(csound, dev); *(csound->GetRtPlayUserData(csound)) = NULL; } else Pa_StartStream(dev->handle); return retval; } /* get samples from ADC */ static int rtrecord_blocking(CSOUND *csound, MYFLT *inbuf, int nbytes) { DEVPARAMS *dev; int i, n, err; dev = (DEVPARAMS*) (*(csound->GetRtRecordUserData(csound))); /* calculate the number of samples to record */ n = nbytes / (dev->nchns * (int) sizeof(MYFLT)); err = (int) Pa_ReadStream(dev->handle, dev->buf, (unsigned long) n); if (UNLIKELY(err != (int) paNoError && (csound->GetMessageLevel(csound) & 4))) csound->Warning(csound, Str("Buffer overrun in real-time audio input")); /* convert samples to MYFLT */ for (i = 0; i < (n * dev->nchns); i++) inbuf[i] = (MYFLT) dev->buf[i]; return nbytes; } /* put samples to DAC */ static void rtplay_blocking(CSOUND *csound, const MYFLT *outbuf, int nbytes) { DEVPARAMS *dev; int i, n, err; dev = (DEVPARAMS*) (*(csound->GetRtPlayUserData(csound))); /* calculate the number of samples to play */ n = nbytes / (dev->nchns * (int) sizeof(MYFLT)); /* convert samples from MYFLT */ for (i = 0; i < (n * dev->nchns); i++) dev->buf[i] = (float) outbuf[i]; err = (int) Pa_WriteStream(dev->handle, dev->buf, (unsigned long) n); if (UNLIKELY(err != (int) paNoError && (csound->GetMessageLevel(csound) & 4))) csound->Warning(csound, Str("Buffer underrun in real-time audio output")); } /* close the I/O device entirely */ /* called only when both complete */ static void rtclose_blocking(CSOUND *csound) { DEVPARAMS *dev; csound->Message(csound, Str("closing device\n")); dev = (DEVPARAMS*) (*(csound->GetRtRecordUserData(csound))); if (dev != NULL) { *(csound->GetRtRecordUserData(csound)) = NULL; if (dev->handle != NULL) { Pa_StopStream(dev->handle); Pa_CloseStream(dev->handle); } if (dev->buf != NULL) csound->Free(csound, dev->buf); csound->Free(csound, dev); } dev = (DEVPARAMS*) (*(csound->GetRtPlayUserData(csound))); if (dev != NULL) { *(csound->GetRtPlayUserData(csound)) = NULL; if (dev->handle != NULL) { Pa_StopStream(dev->handle); Pa_CloseStream(dev->handle); } if (dev->buf != NULL) csound->Free(csound, dev->buf); csound->Free(csound, dev); } } /* module interface functions */ PUBLIC int csoundModuleCreate(CSOUND *csound) { /* nothing to do, report success */ //csound->Message(csound, // Str("PortAudio real-time audio module for Csound\n")); return 0; } PUBLIC int csoundModuleInit(CSOUND *csound) { char *s, drv[12]; int i; csound->module_list_add(csound, "pa_bl", "audio"); csound->module_list_add(csound, "pa_cb", "audio"); if ((s = (char*) csound->QueryGlobalVariable(csound, "_RTAUDIO")) == NULL) return 0; for (i = 0; s[i] != '\0' && i < 11; i++) drv[i] = s[i] & (char) 0xDF; drv[i] = '\0'; if (!(strcmp(drv, "PORTAUDIO") == 0 || strcmp(drv, "PA") == 0 || strcmp(drv, "PA_BL") == 0 || strcmp(drv, "PA_CB") == 0)) return 0; csound->Message(csound, Str("rtaudio: PortAudio module enabled ... \n")); /* set function pointers */ #ifdef LINUX if (strcmp(drv, "PA_CB") != 0) #else if (strcmp(drv, "PA_BL") == 0) #endif { csound->Message(csound, Str("using blocking interface\n")); csound->SetPlayopenCallback(csound, playopen_blocking); csound->SetRecopenCallback(csound, recopen_blocking); csound->SetRtplayCallback(csound, rtplay_blocking); csound->SetRtrecordCallback(csound, rtrecord_blocking); csound->SetRtcloseCallback(csound, rtclose_blocking); csound->SetAudioDeviceListCallback(csound, listDevices); } else { csound->Message(csound, Str("using callback interface\n")); csound->SetPlayopenCallback(csound, playopen_); csound->SetRecopenCallback(csound, recopen_); csound->SetRtplayCallback(csound, rtplay_); csound->SetRtrecordCallback(csound, rtrecord_); csound->SetRtcloseCallback(csound, rtclose_); csound->SetAudioDeviceListCallback(csound, listDevices); } csound->module_list_add(csound, s, "audio"); return 0; } PUBLIC int csoundModuleDestroy(CSOUND *csound) { if (csound->QueryGlobalVariable(csound, "::PortAudio::NeedsTerminate")) { csound->DestroyGlobalVariable(csound, "::PortAudio::NeedsTerminate"); return ((int) Pa_Terminate() == (int) paNoError ? 0 : -1); } return 0; } PUBLIC int csoundModuleInfo(void) { return ((CS_APIVERSION << 16) + (CS_APISUBVER << 8) + (int) sizeof(MYFLT)); } csound-6.10.0/InOut/rtpa.cpp000066400000000000000000000024771321653344700156230ustar00rootroot00000000000000/* rtpa.cpp: Copyright (C) 2004, 2005 John ffitch, Istvan Varga, Michael Gogins, Victor Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* RTPA.C for PortAudio */ /* The rtpa module links with PortAudio which, in turn, contains C++ code. * In order for Csound built with MinGW to handle exceptions thrown from * this C++ code in the PortAudio library, it is necessary to compile and link * rtpa itself as C++ code. */ #ifdef __cplusplus extern "C" { #endif #include "rtpa.c" #ifdef __cplusplus }; #endif csound-6.10.0/InOut/rtpulse.c000066400000000000000000000214271321653344700160070ustar00rootroot00000000000000/* rtpulse.c: Copyright (C) 2008 Victor Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include typedef struct _pulse_params { pa_simple *ps; pa_sample_spec spec; float *buf; } pulse_params; typedef struct _pulse_globals { char server[64]; char oname[32]; char iname[32]; } pulse_globals; PUBLIC int csoundModuleCreate(CSOUND *csound) { pulse_globals *p; int siz = 64; OPARMS oparms; csound->GetOParms(csound, &oparms); if (oparms.msglevel & 0x400) csound->Message(csound, Str("PulseAudio client RT IO module for Csound" "by Victor Lazzarini\n")); if (UNLIKELY(csound->CreateGlobalVariable(csound, "_pulse_globals", sizeof(pulse_globals)) != 0)) { csound->ErrorMsg(csound, Str(" *** rtpulse: error allocating globals")); return -1; } p = (pulse_globals*) csound->QueryGlobalVariableNoCheck(csound, "_pulse_globals"); strcpy(&(p->server[0]), "default"); csound->CreateConfigurationVariable( csound,"server", (void*) &(p->server[0]), CSOUNDCFG_STRING, 0, NULL, &siz, "PulseAudio server name (default: default server)", NULL); strcpy(&(p->oname[0]), "csound-out"); siz = 32; csound->CreateConfigurationVariable( csound,"output_stream", (void*) &(p->oname[0]), CSOUNDCFG_STRING, 0, NULL, &siz, "PulseAudio output stream name (default: csound-out)", NULL); strcpy(&(p->iname[0]), "csound-in"); csound->CreateConfigurationVariable( csound,"input_stream", (void*) &(p->iname[0]), CSOUNDCFG_STRING, 0, NULL, &siz, "PulseAudio input stream name (default: csound-in)", NULL); return 0; } PUBLIC int csoundModuleInfo(void) { return ((CS_APIVERSION << 16) + (CS_APISUBVER << 8) + (int) sizeof(MYFLT)); } static int pulse_playopen(CSOUND *csound, const csRtAudioParams *parm) { pulse_params *pulse; pulse_globals *pg; const char *server; /* pa_buffer_attr attr */ int pulserror; pulse = (pulse_params *) csound->Malloc(csound, sizeof(pulse_params)); *(csound->GetRtPlayUserData(csound)) = (void *) pulse; pulse->spec.rate = csound->GetSr(csound); pulse->spec.channels = csound->GetNchnls(csound); pulse->spec.format = PA_SAMPLE_FLOAT32; pulse->buf = (float *) csound->Malloc(csound, sizeof(float)*parm->bufSamp_SW*pulse->spec.channels); /* attr.maxlength = parm->bufSamp_HW; attr.prebuf = parm->bufSamp_SW; attr.tlength = parm->bufSamp_SW; attr.minreq = parm->bufSamp_SW; attr.fragsize = parm->bufSamp_SW; */ pg = (pulse_globals*) csound->QueryGlobalVariableNoCheck(csound, "_pulse_globals"); if (!strcmp(pg->server,"default")){ server = NULL; csound->Message(csound, Str("PulseAudio output server: default\n")); } else { server = pg->server; csound->Message(csound, Str("PulseAudio output server %s\n"), server); } pulse->ps = pa_simple_new (server, "csound", PA_STREAM_PLAYBACK, parm->devName, &(pg->oname[0]), &(pulse->spec), NULL, /*&attrib*/ NULL, &pulserror ) ; if (LIKELY(pulse->ps)){ csound->Message(csound, Str("pulseaudio output open\n")); return 0; } else { csound->ErrorMsg(csound,Str("Pulse audio module error: %s\n"), pa_strerror(pulserror)); return -1; } } static void pulse_play(CSOUND *csound, const MYFLT *outbuf, int nbytes){ int i, bufsiz, pulserror; float *buf; pulse_params *pulse = (pulse_params*) *(csound->GetRtPlayUserData(csound)); //MYFLT norm = csound->e0dbfs; bufsiz = nbytes/sizeof(MYFLT); buf = pulse->buf; for (i=0;ips, buf, bufsiz*sizeof(float), &pulserror) < 0)) csound->ErrorMsg(csound,Str("Pulse audio module error: %s\n"), pa_strerror(pulserror)); } static void pulse_close(CSOUND *csound) { int error; pulse_params *pulse = (pulse_params*) *(csound->GetRtPlayUserData(csound)); if (pulse != NULL){ pa_simple_drain(pulse->ps, &error); pa_simple_free(pulse->ps); csound->Free(csound,pulse->buf); } pulse = (pulse_params*) *(csound->GetRtRecordUserData(csound)) ; if (pulse != NULL){ pa_simple_free(pulse->ps); csound->Free(csound,pulse->buf); } csound->DestroyGlobalVariable(csound, "pulse_globals"); } static int pulse_recopen(CSOUND *csound, const csRtAudioParams *parm) { pulse_params *pulse; pulse_globals *pg; const char *server; /*pa_buffer_attr attr;*/ int pulserror; pulse = (pulse_params *) csound->Malloc(csound, sizeof(pulse_params)); *(csound->GetRtRecordUserData(csound)) = (void *) pulse; pulse->spec.rate = csound->GetSr(csound); pulse->spec.channels = csound->GetNchnls_i(csound); pulse->spec.format = PA_SAMPLE_FLOAT32; pulse->buf = (float *) csound->Malloc(csound, sizeof(float)*parm->bufSamp_SW*pulse->spec.channels); /* attr.maxlength = parm->bufSamp_HW; attr.prebuf = 0; attr.tlength = parm->bufSamp_SW; attr.minreq = parm->bufSamp_SW; attr.fragsize = parm->bufSamp_SW; */ pg = (pulse_globals*) csound->QueryGlobalVariableNoCheck(csound, "_pulse_globals"); if (!strcmp(pg->server,"default")){ server = NULL; csound->Message(csound, Str("PulseAudio input server: default\n")); } else { server = pg->server; csound->Message(csound, Str("PulseAudio input server %s\n"), server); } pulse->ps = pa_simple_new (server, "csound", PA_STREAM_RECORD, parm->devName, &(pg->iname[0]), &(pulse->spec), NULL, /*&attr*/ NULL, &pulserror ); if (LIKELY(pulse->ps)) return 0; else { csound->ErrorMsg(csound,Str("Pulse audio module error: %s\n"), pa_strerror(pulserror)); return -1; } } static int pulse_record(CSOUND *csound, MYFLT *inbuf, int nbytes) { int i, bufsiz,pulserror; float *buf; pulse_params *pulse = (pulse_params*) *(csound->GetRtRecordUserData(csound)) ; //MYFLT norm = csound->e0dbfs; bufsiz = nbytes/sizeof(MYFLT); buf = pulse->buf; if (UNLIKELY(pa_simple_read(pulse->ps, buf, bufsiz*sizeof(float), &pulserror) < 0)) { csound->ErrorMsg(csound,Str("Pulse audio module error: %s\n"), pa_strerror(pulserror)); return -1; } else { for (i=0;imodule_list_add(csound, "pulse", "audio"); s = (char*) csound->QueryGlobalVariable(csound, "_RTAUDIO"); i = 0; if (s != NULL) { while (*s != (char) 0 && i < 8) buf[i++] = *(s++) | (char) 0x20; } buf[i] = (char) 0; if (strcmp(&(buf[0]), "pulse") == 0) { csound->Message(csound, Str("rtaudio: pulseaudio module enabled\n")); csound->SetPlayopenCallback(csound, pulse_playopen); csound->SetRecopenCallback(csound, pulse_recopen); csound->SetRtplayCallback(csound, pulse_play); csound->SetRtrecordCallback(csound, pulse_record); csound->SetRtcloseCallback(csound, pulse_close); } return 0; } csound-6.10.0/InOut/rtwinmm.c000066400000000000000000000645551321653344700160170ustar00rootroot00000000000000/* rtwinmm.c: Copyright (C) 2005 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "csdl.h" #include "soundio.h" #ifdef MAXBUFFERS #undef MAXBUFFERS #endif #define MAXBUFFERS 256 typedef struct rtWinMMDevice_ { HWAVEIN inDev; HWAVEOUT outDev; int cur_buf; int nBuffers; int seed; /* random seed for dithering */ int enable_buf_timer; /* playback sample conversion function */ void (*playconv)(int, MYFLT*, void*, int*); /* record sample conversion function */ void (*rec_conv)(int, void*, MYFLT*); int64_t prv_time; float timeConv, bufTime; WAVEHDR buffers[MAXBUFFERS]; } rtWinMMDevice; typedef struct rtWinMMGlobals_ { rtWinMMDevice *inDev; rtWinMMDevice *outDev; int enable_buf_timer; } rtWinMMGlobals; #define MBUFSIZE 1024 typedef struct rtmidi_mme_globals_ { HMIDIIN inDev; int inBufWritePos; int inBufReadPos; DWORD inBuf[MBUFSIZE]; CRITICAL_SECTION threadLock; } RTMIDI_MME_GLOBALS; static const unsigned char msg_bytes[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 0, 1 }; static inline int64_t large_integer_to_int64(LARGE_INTEGER *p) { return ((int64_t) p->LowPart + ((int64_t) p->HighPart << 32)); } static int err_msg(CSOUND *csound, const char *fmt, ...) { va_list args; va_start(args, fmt); csound->ErrMsgV(csound, Str("winmm: error: "), fmt, args); va_end(args); return -1; } static int allocate_buffers(CSOUND *csound, rtWinMMDevice *dev, const csRtAudioParams *parm, int is_playback) { HGLOBAL ptr; int i, err = 0, bufFrames, bufSamples, bufBytes; bufFrames = parm->bufSamp_SW; bufSamples = bufFrames * parm->nChannels; bufBytes = bufSamples * (parm->sampleFormat == AE_SHORT ? 2 : 4); dev->nBuffers = parm->bufSamp_HW / parm->bufSamp_SW; if (dev->nBuffers < 2) dev->nBuffers = 2; if (dev->enable_buf_timer) dev->nBuffers *= 2; if (UNLIKELY(dev->nBuffers > MAXBUFFERS)) { dev->nBuffers = 0; return err_msg(csound, Str("too many buffers")); } for (i = 0; i < dev->nBuffers; i++) { ptr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, (SIZE_T) bufBytes); if (UNLIKELY(ptr == (HGLOBAL) NULL)) { dev->nBuffers = i; return err_msg(csound, Str("memory allocation failure")); } dev->buffers[i].lpData = (LPSTR) GlobalLock(ptr); memset((void*) dev->buffers[i].lpData, 0, (size_t) bufBytes); dev->buffers[i].dwBufferLength = (DWORD) bufBytes; if (is_playback) err = (int) waveOutPrepareHeader(dev->outDev, (LPWAVEHDR) &(dev->buffers[i]), sizeof(WAVEHDR)); else err = (int) waveInPrepareHeader(dev->inDev, (LPWAVEHDR) &(dev->buffers[i]), sizeof(WAVEHDR)); if (UNLIKELY(err != MMSYSERR_NOERROR)) return err_msg(csound, Str("failed to prepare buffers")); dev->buffers[i].dwFlags |= WHDR_DONE; } return 0; } static int set_format_params(CSOUND *csound, WAVEFORMATEX *wfx, const csRtAudioParams *parm) { int sampsize = 4, framsize; memset(wfx, 0, sizeof(WAVEFORMATEX)); switch (parm->sampleFormat) { case AE_SHORT: sampsize = 2; break; case AE_LONG: case AE_FLOAT: break; default: return err_msg(csound, Str("invalid sample format: " "must be -s, -l, or -f")); } framsize = sampsize * parm->nChannels; wfx->wFormatTag = (WORD) (parm->sampleFormat == AE_FLOAT ? 3 : 1); wfx->nChannels = (WORD) parm->nChannels; wfx->nSamplesPerSec = (DWORD) ((double) parm->sampleRate + 0.5); wfx->nAvgBytesPerSec = (DWORD) ((int) wfx->nSamplesPerSec * framsize); wfx->nBlockAlign = (DWORD) framsize; wfx->wBitsPerSample = (DWORD) (sampsize << 3); return 0; } /* sample conversion routines for playback */ static void MYFLT_to_short(int nSmps, MYFLT *inBuf, int16_t *outBuf, int *seed) { MYFLT tmp_f; int tmp_i; int n; for (n=0; n>1) - 0x8000) * (FL(1.0) / (MYFLT) 0x10000); tmp_f += inBuf[n] * (MYFLT) 0x8000; tmp_i = (int) MYFLT2LRND(tmp_f); if (tmp_i < -0x8000) tmp_i = -0x8000; if (tmp_i > 0x7FFF) tmp_i = 0x7FFF; outBuf[n] = (int16_t) tmp_i; } } static void MYFLT_to_short_u(int nSmps, MYFLT *inBuf, int16_t *outBuf, int *seed) { MYFLT tmp_f; int tmp_i; int n; for (n=0; n 0x7FFF) tmp_i = 0x7FFF; outBuf[n] = (int16_t) tmp_i; } } static void MYFLT_to_short_no_dither(int nSmps, MYFLT *inBuf, int16_t *outBuf, int *seed) { MYFLT tmp_f; int tmp_i; int n; for (n=0; n 0x7FFF) tmp_i = 0x7FFF; outBuf[n] = (int16_t) tmp_i; } } static void MYFLT_to_long(int nSmps, MYFLT *inBuf, int32_t *outBuf, int *seed) { MYFLT tmp_f; int64_t tmp_i; (void) seed; int n; for (n=0; n (int64_t) 0x7FFFFFFF) tmp_i = (int64_t) 0x7FFFFFFF; outBuf[n] = (int32_t) tmp_i; } } static void MYFLT_to_float(int nSmps, MYFLT *inBuf, float *outBuf, int *seed) { (void) seed; int n; for (n=0; ndevName != NULL)) return err_msg(csound, Str("Must specify a device number, not a name")); if (set_format_params(csound, &wfx, parm) != 0) return -1; devNum = (parm->devNum == 1024 ? 0 : parm->devNum); if (parm->sampleFormat != AE_FLOAT && ((int) GetVersion() & 0xFF) >= 0x05) openFlags |= WAVE_FORMAT_DIRECT; if (is_playback) { WAVEOUTCAPSA caps; ndev = (int) waveOutGetNumDevs(); csound->Message(csound, Str("The available output devices are:\n")); for (i = 0; i < ndev; i++) { waveOutGetDevCapsA((unsigned int) i, (LPWAVEOUTCAPSA) &caps, sizeof(WAVEOUTCAPSA)); csound->Message(csound, Str("%3d: %s\n"), i, (char*) caps.szPname); } if (UNLIKELY(ndev < 1)) return err_msg(csound, Str("No output device is available")); if (UNLIKELY(devNum < 0 || devNum >= ndev)) { return err_msg(csound, Str("Device number is out of range")); } waveOutGetDevCapsA((unsigned int) devNum, (LPWAVEOUTCAPSA) &caps, sizeof(WAVEOUTCAPSA)); csound->Message(csound, Str("winmm: opening output device %d (%s)\n"), devNum, (char*) caps.szPname); } else { WAVEINCAPSA caps; ndev = (int) waveInGetNumDevs(); csound->Message(csound, Str("The available input devices are:\n")); for (i = 0; i < ndev; i++) { waveInGetDevCapsA((unsigned int) i, (LPWAVEINCAPSA) &caps, sizeof(WAVEINCAPSA)); csound->Message(csound, Str("%3d: %s\n"), i, (char*) caps.szPname); } if (UNLIKELY(ndev < 1)) return err_msg(csound, Str("no input device is available")); if (UNLIKELY(devNum < 0 || devNum >= ndev)) { return err_msg(csound, Str("device number is out of range")); } waveInGetDevCapsA((unsigned int) devNum, (LPWAVEINCAPSA) &caps, sizeof(WAVEINCAPSA)); csound->Message(csound, Str("winmm: opening input device %d (%s)\n"), devNum, (char*) caps.szPname); } p = (rtWinMMGlobals*) csound->QueryGlobalVariable(csound, "_rtwinmm_globals"); dev = (rtWinMMDevice*) csound->Malloc(csound, sizeof(rtWinMMDevice)); if (UNLIKELY(dev == NULL)) return err_msg(csound, Str("memory allocation failure")); memset(dev, 0, sizeof(rtWinMMDevice)); conv_idx = (parm->sampleFormat == AE_SHORT ? 0 : (parm->sampleFormat == AE_LONG ? 1 : 2)); if (is_playback) { p->outDev = dev; *(csound->GetRtPlayUserData(csound)) = (void*) dev; dev->enable_buf_timer = p->enable_buf_timer; if (UNLIKELY(waveOutOpen((LPHWAVEOUT) &(dev->outDev), (unsigned int) devNum, (LPWAVEFORMATEX) &wfx, 0, 0, openFlags) != MMSYSERR_NOERROR)) { dev->outDev = (HWAVEOUT) 0; return err_msg(csound, Str("failed to open device")); } switch (conv_idx) { case 0: if (csound->GetDitherMode(csound)==1) dev->playconv = (void (*)(int, MYFLT*, void*, int*)) MYFLT_to_short; else if (csound->GetDitherMode(csound)==2) dev->playconv = (void (*)(int, MYFLT*, void*, int*)) MYFLT_to_short_u; else dev->playconv = (void (*)(int, MYFLT*, void*, int*)) MYFLT_to_short_no_dither; break; case 1: dev->playconv = (void (*)(int, MYFLT*, void*, int*)) MYFLT_to_long; break; case 2: dev->playconv = (void (*)(int, MYFLT*, void*, int*)) MYFLT_to_float; break; } } else { p->inDev = dev; *(csound->GetRtRecordUserData(csound)) = (void*) dev; /* disable playback timer in full-duplex mode */ dev->enable_buf_timer = p->enable_buf_timer = 0; if (UNLIKELY(waveInOpen((LPHWAVEIN) &(dev->inDev), (unsigned int) devNum, (LPWAVEFORMATEX) &wfx, 0, 0, openFlags) != MMSYSERR_NOERROR)) { dev->inDev = (HWAVEIN) 0; return err_msg(csound, Str("failed to open device")); } switch (conv_idx) { case 0: dev->rec_conv = (void (*)(int, void*, MYFLT*)) short_to_MYFLT; break; case 1: dev->rec_conv = (void (*)(int, void*, MYFLT*)) long_to_MYFLT; break; case 2: dev->rec_conv = (void (*)(int, void*, MYFLT*)) float_to_MYFLT; break; } } if (UNLIKELY(allocate_buffers(csound, dev, parm, is_playback) != 0)) return -1; if (!is_playback) waveInStart(dev->inDev); QueryPerformanceFrequency(&pp); dev->timeConv = 1000.0f / (float) large_integer_to_int64(&pp); dev->bufTime = 1000.0f * (float) parm->bufSamp_SW / parm->sampleRate; QueryPerformanceCounter(&pp); dev->prv_time = large_integer_to_int64(&pp); return 0; } /* open for audio input */ static int recopen_(CSOUND *csound, const csRtAudioParams *parm) { return open_device(csound, parm, 0); } /* open for audio output */ static int playopen_(CSOUND *csound, const csRtAudioParams *parm) { return open_device(csound, parm, 1); } /* get samples from ADC */ static int rtrecord_(CSOUND *csound, MYFLT *inBuf, int nbytes) { rtWinMMDevice *dev = (rtWinMMDevice*) *(csound->GetRtRecordUserData(csound)); WAVEHDR *buf = &(dev->buffers[dev->cur_buf]); volatile DWORD *dwFlags = &(buf->dwFlags); dev->rec_conv(nbytes / (int) sizeof(MYFLT), (void*) buf->lpData, inBuf); while (!(*dwFlags & WHDR_DONE)) Sleep(1); waveInAddBuffer(dev->inDev, (LPWAVEHDR) buf, sizeof(WAVEHDR)); if (++(dev->cur_buf) >= dev->nBuffers) dev->cur_buf = 0; return nbytes; } /* put samples to DAC */ /* N.B. This routine serves as a THROTTLE in Csound Realtime Performance, */ /* delaying the actual writes and return until the hardware output buffer */ /* passes a sample-specific THRESHOLD. If the I/O BLOCKING functionality */ /* is implemented ACCURATELY by the vendor-supplied audio-library write, */ /* that is sufficient. Otherwise, requires some kind of IOCTL from here. */ /* This functionality is IMPORTANT when other realtime I/O is occurring, */ /* such as when external MIDI data is being collected from a serial port. */ /* Since Csound polls for MIDI input at the software synthesis K-rate */ /* (the resolution of all software-synthesized events), the user can */ /* eliminate MIDI jitter by requesting that both be made synchronous with */ /* the above audio I/O blocks, i.e. by setting -b to some 1 or 2 K-prds. */ static void rtplay_(CSOUND *csound, const MYFLT *outBuf, int nbytes) { rtWinMMDevice *dev = (rtWinMMDevice*) *(csound->GetRtPlayUserData(csound)); WAVEHDR *buf = &(dev->buffers[dev->cur_buf]); volatile DWORD *dwFlags = &(buf->dwFlags); LARGE_INTEGER pp; int64_t curTime; float timeDiff, timeWait; int i, nbufs; while (!(*dwFlags & WHDR_DONE)) Sleep(1); dev->playconv(nbytes / (int) sizeof(MYFLT), (MYFLT*) outBuf, (void*) buf->lpData, &(dev->seed)); waveOutWrite(dev->outDev, (LPWAVEHDR) buf, sizeof(WAVEHDR)); if (++(dev->cur_buf) >= dev->nBuffers) dev->cur_buf = 0; if (!dev->enable_buf_timer) return; QueryPerformanceCounter(&pp); curTime = large_integer_to_int64(&pp); timeDiff = (float) (curTime - dev->prv_time) * dev->timeConv; dev->prv_time = curTime; for (i = nbufs = 0; i < dev->nBuffers; i++) { if (!(dev->buffers[i].dwFlags & WHDR_DONE)) nbufs++; } if (nbufs <= 1) return; timeWait = dev->bufTime; timeWait *= (((float) nbufs / (float) dev->nBuffers) * 0.25f + 0.875f); timeWait -= timeDiff; i = MYFLT2LRND(timeWait); if (i > 0) Sleep((DWORD) i); } static void rtclose_(CSOUND *csound) { rtWinMMGlobals *pp; rtWinMMDevice *inDev, *outDev; int i; *(csound->GetRtPlayUserData(csound)) = NULL; *(csound->GetRtRecordUserData(csound)) = NULL; pp = (rtWinMMGlobals*) csound->QueryGlobalVariable(csound, "_rtwinmm_globals"); if (pp == NULL) return; inDev = pp->inDev; outDev = pp->outDev; csound->DestroyGlobalVariable(csound, "_rtwinmm_globals"); if (inDev != NULL) { waveInStop(inDev->inDev); waveInReset(inDev->inDev); for (i = 0; i < inDev->nBuffers; i++) { waveInUnprepareHeader(inDev->inDev, (LPWAVEHDR) &(inDev->buffers[i]), sizeof(WAVEHDR)); GlobalUnlock((HGLOBAL) inDev->buffers[i].lpData); GlobalFree((HGLOBAL) inDev->buffers[i].lpData); } waveInClose(inDev->inDev); csound->Free(csound,inDev); } if (outDev != NULL) { volatile DWORD *dwFlags = &(outDev->buffers[outDev->cur_buf].dwFlags); while (!(*dwFlags & WHDR_DONE)) Sleep(1); waveOutReset(outDev->outDev); for (i = 0; i < outDev->nBuffers; i++) { waveOutUnprepareHeader(outDev->outDev, (LPWAVEHDR) &(outDev->buffers[i]), sizeof(WAVEHDR)); GlobalUnlock((HGLOBAL) outDev->buffers[i].lpData); GlobalFree((HGLOBAL) outDev->buffers[i].lpData); } waveOutClose(outDev->outDev); csound->Free(csound,outDev); } } static void CALLBACK midi_in_handler(HMIDIIN hmin, UINT wMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) { RTMIDI_MME_GLOBALS *p = (RTMIDI_MME_GLOBALS*) dwInstance; int new_pos; (void) hmin; (void) dwParam2; if (wMsg != MIM_DATA) /* ignore non-data messages */ return; EnterCriticalSection(&(p->threadLock)); new_pos = (p->inBufWritePos + 1) & (MBUFSIZE - 1); if (new_pos != p->inBufReadPos) { p->inBuf[p->inBufWritePos] = dwParam1; p->inBufWritePos = new_pos; } LeaveCriticalSection(&(p->threadLock)); } static int midi_in_open(CSOUND *csound, void **userData, const char *devName) { int i, ndev, devnum = 0; RTMIDI_MME_GLOBALS *p; MIDIINCAPS caps; *userData = NULL; ndev = (int) midiInGetNumDevs(); if (UNLIKELY(ndev < 1)) { csound->ErrorMsg(csound, Str("rtmidi: no input devices are available")); return -1; } if (devName != NULL && devName[0] != '\0' && strcmp(devName, "default") != 0) { if (UNLIKELY(devName[0] < '0' || devName[0] > '9')) { csound->ErrorMsg(csound, Str("rtmidi: must specify a device number, " "not a name")); return -1; } devnum = (int) atoi(devName); } csound->Message(csound, Str("The available MIDI input devices are:\n")); for (i = 0; i < ndev; i++) { midiInGetDevCaps((unsigned int) i, &caps, sizeof(MIDIINCAPS)); csound->Message(csound, "%3d: %s\n", i, &(caps.szPname[0])); } if (UNLIKELY(devnum < 0 || devnum >= ndev)) { csound->ErrorMsg(csound, Str("rtmidi: input device number is out of range")); return -1; } p = (RTMIDI_MME_GLOBALS*) csound->Calloc(csound, (size_t) sizeof(RTMIDI_MME_GLOBALS)); if (UNLIKELY(p == NULL)) { csound->ErrorMsg(csound, Str("rtmidi: memory allocation failure")); return -1; } InitializeCriticalSection(&(p->threadLock)); *userData = (void*) p; midiInGetDevCaps((unsigned int) devnum, &caps, sizeof(MIDIINCAPS)); csound->Message(csound, Str("Opening MIDI input device %d (%s)\n"), devnum, &(caps.szPname[0])); if (UNLIKELY(midiInOpen(&(p->inDev), (unsigned int) devnum, (DWORD) midi_in_handler, (DWORD) p, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)) { p->inDev = (HMIDIIN) 0; csound->ErrorMsg(csound, Str("rtmidi: could not open input device")); return -1; } midiInStart(p->inDev); return 0; } static int midi_in_read(CSOUND *csound, void *userData, unsigned char *buf, int nbytes) { RTMIDI_MME_GLOBALS *p = (RTMIDI_MME_GLOBALS*) userData; unsigned int tmp; unsigned char s, d1, d2, len; int nread = 0; (void) csound; EnterCriticalSection(&(p->threadLock)); while (p->inBufReadPos != p->inBufWritePos) { tmp = (unsigned int) p->inBuf[p->inBufReadPos++]; p->inBufReadPos &= (MBUFSIZE - 1); s = (unsigned char) tmp; tmp >>= 8; d1 = (unsigned char) tmp; tmp >>= 8; d2 = (unsigned char) tmp; len = msg_bytes[(int) s >> 3]; if (nread + len > nbytes) break; if (len) { buf[nread++] = s; if (--len) { buf[nread++] = d1; if (--len) buf[nread++] = d2; } } } LeaveCriticalSection(&(p->threadLock)); return nread; } static int midi_in_close(CSOUND *csound, void *userData) { RTMIDI_MME_GLOBALS *p = (RTMIDI_MME_GLOBALS*) userData; (void) csound; if (p == NULL) return 0; if (p->inDev != (HMIDIIN) 0) { midiInStop(p->inDev); midiInReset(p->inDev); midiInClose(p->inDev); } DeleteCriticalSection(&(p->threadLock)); csound->Free(csound,p); return 0; } static int midi_out_open(CSOUND *csound, void **userData, const char *devName) { int i, ndev, devnum = 0; MIDIOUTCAPS caps; HMIDIOUT outDev = (HMIDIOUT) 0; *userData = NULL; ndev = (int) midiOutGetNumDevs(); if (UNLIKELY(ndev < 1)) { csound->ErrorMsg(csound, Str("rtmidi: no output devices are available")); return -1; } if (devName != NULL && devName[0] != '\0' && strcmp(devName, "default") != 0) { if (UNLIKELY(devName[0] < '0' || devName[0] > '9')) { csound->ErrorMsg(csound, Str("rtmidi: must specify a device number, " "not a name")); return -1; } devnum = (int) atoi(devName); } csound->Message(csound, Str("The available MIDI output devices are:\n")); for (i = 0; i < ndev; i++) { midiOutGetDevCaps((unsigned int) i, &caps, sizeof(MIDIOUTCAPS)); csound->Message(csound, "%3d: %s\n", i, &(caps.szPname[0])); } if (UNLIKELY(devnum < 0 || devnum >= ndev)) { csound->ErrorMsg(csound, Str("rtmidi: output device number is out of range")); return -1; } midiOutGetDevCaps((unsigned int) devnum, &caps, sizeof(MIDIOUTCAPS)); csound->Message(csound, Str("Opening MIDI output device %d (%s)\n"), devnum, &(caps.szPname[0])); if (UNLIKELY(midiOutOpen(&outDev, (unsigned int) devnum, (DWORD) 0, (DWORD) 0, CALLBACK_NULL) != MMSYSERR_NOERROR)) { csound->ErrorMsg(csound, Str("rtmidi: could not open output device")); return -1; } *userData = (void*) outDev; return 0; } static int midi_out_write(CSOUND *csound, void *userData, const unsigned char *buf, int nbytes) { HMIDIOUT outDev = (HMIDIOUT) userData; unsigned int tmp; unsigned char s, len; int pos = 0; (void) csound; while (pos < nbytes) { s = buf[pos++]; len = msg_bytes[(int) s >> 3]; if (!len) continue; tmp = (unsigned int) s; if (--len) { if (pos >= nbytes) break; tmp |= ((unsigned int) buf[pos++] << 8); if (--len) { if (pos >= nbytes) break; tmp |= ((unsigned int) buf[pos++] << 16); } } midiOutShortMsg(outDev, (DWORD) tmp); } return pos; } static int midi_out_close(CSOUND *csound, void *userData) { (void) csound; if (userData != NULL) { HMIDIOUT outDev = (HMIDIOUT) userData; midiOutReset(outDev); midiOutClose(outDev); } return 0; } /* module interface functions */ PUBLIC int csoundModuleCreate(CSOUND *csound) { rtWinMMGlobals *pp; OPARMS oparms; csound->GetOParms(csound, &oparms); if (UNLIKELY(oparms.msglevel & 0x400)) csound->Message(csound, Str("Windows MME real time audio and MIDI module " "for Csound by Istvan Varga\n")); if (UNLIKELY(csound->CreateGlobalVariable(csound, "_rtwinmm_globals", sizeof(rtWinMMGlobals)) != 0)) return err_msg(csound, Str("could not allocate global structure")); pp = (rtWinMMGlobals*) csound->QueryGlobalVariable(csound, "_rtwinmm_globals"); pp->inDev = NULL; pp->outDev = NULL; pp->enable_buf_timer = 1; return (csound->CreateConfigurationVariable( csound, "mme_playback_timer", &(pp->enable_buf_timer), CSOUNDCFG_BOOLEAN, 0, NULL, NULL, "Attempt to reduce timing jitter " "in MME sound output (default: on)", NULL)); } static CS_NOINLINE int check_name(const char *s) { if (s != NULL) { char buf[8]; int i = 0; do { buf[i] = s[i] | (char) 0x20; i++; } while (i < 7 && s[i] != '\0'); buf[i] = '\0'; if (strcmp(buf, "winmm") == 0 || strcmp(buf, "mme") == 0) return 1; } return 0; } PUBLIC int csoundModuleInit(CSOUND *csound) { if (check_name((char*) csound->QueryGlobalVariable(csound, "_RTAUDIO"))) { csound->Message(csound, Str("rtaudio: WinMM module enabled\n")); csound->SetPlayopenCallback(csound, playopen_); csound->SetRecopenCallback(csound, recopen_); csound->SetRtplayCallback(csound, rtplay_); csound->SetRtrecordCallback(csound, rtrecord_); csound->SetRtcloseCallback(csound, rtclose_); } if (check_name((char*) csound->QueryGlobalVariable(csound, "_RTMIDI"))) { csound->Message(csound, Str("rtmidi: WinMM module enabled\n")); csound->SetExternalMidiInOpenCallback(csound, midi_in_open); csound->SetExternalMidiReadCallback(csound, midi_in_read); csound->SetExternalMidiInCloseCallback(csound, midi_in_close); csound->SetExternalMidiOutOpenCallback(csound, midi_out_open); csound->SetExternalMidiWriteCallback(csound, midi_out_write); csound->SetExternalMidiOutCloseCallback(csound, midi_out_close); } return 0; } PUBLIC int csoundModuleInfo(void) { return ((CS_APIVERSION << 16) + (CS_APISUBVER << 8) + (int) sizeof(MYFLT)); } csound-6.10.0/InOut/virtual_keyboard/000077500000000000000000000000001321653344700175055ustar00rootroot00000000000000csound-6.10.0/InOut/virtual_keyboard/Bank.cpp000066400000000000000000000110121321653344700210570ustar00rootroot00000000000000/* Bank.cpp: Copyright (C) 2006 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "Bank.hpp" static char* gm[] = { (char *)"Acoustic Grand", (char *)"Bright Acoustic", (char *)"Electric Grand", (char *)"Honky-Tonk", (char *)"Electric Piano 1", (char *)"Electric Piano 2", (char *)"Harpsichord", (char *)"Clavinet", (char *)"Celesta", (char *)"Glockenspiel", (char *)"Music Box", (char *)"Vibraphone", (char *)"Marimba", (char *)"Xylophone", (char *)"Tubular Bells", (char *)"Dulcimer", (char *)"Drawbar Organ", (char *)"Percussive Organ", (char *)"Rock Organ", (char *)"Church Organ", (char *)"Reed Organ", (char *)"Accoridan", (char *)"Harmonica", (char *)"Tango Accordian", (char *)"Nylon String Guitar", (char *)"Steel String Guitar", (char *)"Electric Jazz Guitar", (char *)"Electric Clean Guitar", (char *)"Electric Muted Guitar", (char *)"Overdriven Guitar", (char *)"Distortion Guitar", (char *)"Guitar Harmonics", (char *)"Acoustic Bass", (char *)"Electric Bass(finger)", (char *)"Electric Bass(pick)", (char *)"Fretless Bass", (char *)"Slap Bass 1", (char *)"Slap Bass 2", (char *)"Synth Bass 1", (char *)"Synth Bass 2", (char *)"Violin", (char *)"Viola", (char *)"Cello", (char *)"Contrabass", (char *)"Tremolo Strings", (char *)"Pizzicato Strings", (char *)"Orchestral Strings", (char *)"Timpani", (char *)"String Ensemble 1", (char *)"String Ensemble 2", (char *)"SynthStrings 1", (char *)"SynthStrings 2", (char *)"Choir Aahs", (char *)"Voice Oohs", (char *)"Synth Voice", (char *)"Orchestra Hit", (char *)"Trumpet", (char *)"Trombone", (char *)"Tuba", (char *)"Muted Trumpet", (char *)"French Horn", (char *)"Brass Section", (char *)"SynthBrass 1", (char *)"SynthBrass 2", (char *)"Soprano Sax", (char *)"Alto Sax", (char *)"Tenor Sax", (char *)"Baritone Sax", (char *)"Oboe", (char *)"English Horn", (char *)"Bassoon", (char *)"Clarinet", (char *)"Piccolo", (char *)"Flute", (char *)"Recorder", (char *)"Pan Flute", (char *)"Blown Bottle", (char *)"Skakuhachi", (char *)"Whistle", (char *)"Ocarina", (char *)"Lead 1 (square)", (char *)"Lead 2 (sawtooth)", (char *)"Lead 3 (calliope)", (char *)"Lead 4 (chiff)", (char *)"Lead 5 (charang)", (char *)"Lead 6 (voice)", (char *)"Lead 7 (fifths)", (char *)"Lead 8 (bass+lead)", (char *)"Pad 1 (new age)", (char *)"Pad 2 (warm)", (char *)"Pad 3 (polysynth)", (char *)"Pad 4 (choir)", (char *)"Pad 5 (bowed)", (char *)"Pad 6 (metallic)", (char *)"Pad 7 (halo)", (char *)"Pad 8 (sweep)", (char *)"FX 1 (rain)", (char *)"FX 2 (soundtrack)", (char *)"FX 3 (crystal)", (char *)"FX 4 (atmosphere)", (char *)"FX 5 (brightness)", (char *)"FX 6 (goblins)", (char *)"FX 7 (echoes)", (char *)"FX 8 (sci-fi)", (char *)"Sitar", (char *)"Banjo", (char *)"Shamisen", (char *)"Koto", (char *)"Kalimba", (char *)"Bagpipe", (char *)"Fiddle", (char *)"Shanai", (char *)"Tinkle Bell", (char *)"Agogo", (char *)"Steel Drums", (char *)"Woodblock", (char *)"Taiko Drum", (char *)"Melodic Tom", (char *)"Synth Drum", (char *)"Reverse Cymbal", (char *)"Guitar Fret Noise", (char *)"Breath Noise", (char *)"Seashore", (char *)"Bird Tweet", (char *)"Telephone Ring", (char *)"Helicopter", (char *)"Applause", (char *)"Gunshot" }; Bank::Bank(CSOUND *csound, char* bankName) : bankNum(0) { this->name = bankName; currentProgram = 0; previousProgram = -1; } Bank::~Bank() { while( !programs.empty() ) { programs.erase( programs.begin() ); } } void Bank::initializeGM() { for(int i = 0; i < 128; i++) { Program temp(i, gm[i]); this->programs.push_back(temp); } } csound-6.10.0/InOut/virtual_keyboard/Bank.hpp000066400000000000000000000023161321653344700210730ustar00rootroot00000000000000/* Bank.hpp: Copyright (C) 2006 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef BANK_HPP_ #define BANK_HPP_ #include #include "csdl.h" #include "Program.hpp" using namespace std; class Bank { public: Bank(CSOUND *csound, char *bankName); virtual ~Bank(); char *name; int bankNum; vector programs; int previousProgram; int currentProgram; void initializeGM(); }; #endif /*BANK_HPP_*/ csound-6.10.0/InOut/virtual_keyboard/FLTKKeyboard.cpp000066400000000000000000000264401321653344700224400ustar00rootroot00000000000000/* FLTKKeyboard.cpp: Copyright (C) 2006 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include "FLTKKeyboard.hpp" FLTKKeyboard::FLTKKeyboard(CSOUND *csound, SliderBank *sliderBank, int X, int Y, int W, int H, const char *L) : Fl_Widget(X, Y, W, H, L) { this->csound = csound; this->sliderBank = sliderBank; this->mutex = csound->Create_Mutex(0); FLTKKeyboard *o = this; o->box(FL_FLAT_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NO_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->user_data((void*)(this)); o->align(FL_ALIGN_TOP); o->when(FL_WHEN_RELEASE); for(int i = 0; i < 88; i++) { keyStates[i] = 0; changedKeyStates[i] = 0; } lastMidiKey = -1; whiteKeys[0] = 0; whiteKeys[1] = 2; whiteKeys[2] = 4; whiteKeys[3] = 5; whiteKeys[4] = 7; whiteKeys[5] = 9; whiteKeys[6] = 11; octave = 5; aNotesOff = 0; } FLTKKeyboard::~FLTKKeyboard() { if (mutex) { csound->DestroyMutex(mutex); mutex = (void*) 0; } } void FLTKKeyboard::lock() { if(mutex) { csound->LockMutex(mutex); } } void FLTKKeyboard::unlock() { if(mutex) { csound->UnlockMutex(mutex); } } void FLTKKeyboard::allNotesOff() { this->lock(); for(int i = 0; i < 88; i++) { this->keyStates[i] = -1; } this->lastMidiKey = -1; this->aNotesOff = 1; this->unlock(); this->redraw(); } int FLTKKeyboard::getMidiValForWhiteKey(int whiteKeyNum) { if(whiteKeyNum < 2) { return whiteKeyNum * 2; } int adjusted = whiteKeyNum - 2; int oct = adjusted / 7; int key = adjusted % 7; return 3 + (oct * 12) + whiteKeys[key]; } int FLTKKeyboard::getMIDIKey(int xVal, int yVal) { int x = xVal - this->x(); int y = yVal - this->y(); if(x > this->w()) { return 87; } if(x < 0) { return 0; } int whiteKeyHeight = this->h(); int blackKeyHeight = (int)(whiteKeyHeight * .625); float whiteKeyWidth = this->w() / 52.0; float blackKeyWidth = whiteKeyWidth * .8333333; float leftKeyBound = blackKeyWidth / 2.0; float rightKeyBound = whiteKeyWidth - leftKeyBound; // 52 white keys int whiteKey = (int)(x / whiteKeyWidth); float extra = x - (whiteKey * whiteKeyWidth); if(whiteKey < 2) { if(whiteKey == 0) { if(y > blackKeyHeight + this->y()) { return whiteKey; } else { if(extra > rightKeyBound) { return whiteKey + 1; } return whiteKey; } } else { if(y > blackKeyHeight) { return getMidiValForWhiteKey(whiteKey); } else { if(extra < leftKeyBound) { return getMidiValForWhiteKey(whiteKey) - 1; } return getMidiValForWhiteKey(whiteKey); } } } int adjustedKey = (whiteKey - 2) % 7; if(adjustedKey == 0 || adjustedKey == 3) { if(y > blackKeyHeight) { return getMidiValForWhiteKey(whiteKey); } else { if(extra > rightKeyBound) { return getMidiValForWhiteKey(whiteKey) + 1; } return getMidiValForWhiteKey(whiteKey); } } else if(adjustedKey == 2 || adjustedKey == 6) { if(y > blackKeyHeight) { return getMidiValForWhiteKey(whiteKey); } else { if(extra < leftKeyBound) { return getMidiValForWhiteKey(whiteKey) - 1; } return getMidiValForWhiteKey(whiteKey); } } if(y > blackKeyHeight) { return getMidiValForWhiteKey(whiteKey); } if(extra < leftKeyBound) { return getMidiValForWhiteKey(whiteKey) - 1; } if(extra > rightKeyBound) { return getMidiValForWhiteKey(whiteKey) + 1; } return getMidiValForWhiteKey(whiteKey); } void FLTKKeyboard::handleControl(int key) { int index; switch(key) { case '1': index = 0; break; case '2': index = 1; break; case '3': index = 2; break; case '4': index = 3; break; case '5': index = 4; break; case '6': index = 5; break; case '7': index = 6; break; case '8': index = 7; break; case '9': index = 8; break; case '0': index = 9; break; default: return; } if(Fl::event_shift()) { sliderBank->incrementSlider(index, -1); } else { sliderBank->incrementSlider(index, 1); } return; } void FLTKKeyboard::handleKey(int key, int value) { int index = -1; switch(key) { case 'z': index = 0; break; case 's': index = 1; break; case 'x': index = 2; break; case 'd': index = 3; break; case 'c': index = 4; break; case 'v': index = 5; break; case 'g': index = 6; break; case 'b': index = 7; break; case 'h': index = 8; break; case 'n': index = 9; break; case 'j': index = 10; break; case 'm': index = 11; break; case 'q': index = 12; break; case '2': index = 13; break; case 'w': index = 14; break; case '3': index = 15; break; case 'e': index = 16; break; case 'r': index = 17; break; case '5': index = 18; break; case 't': index = 19; break; case '6': index = 20; break; case 'y': index = 21; break; case '7': index = 22; break; case 'u': index = 23; break; case 'i': index = 24; break; case '9': index = 25; break; case 'o': index = 26; break; case '0': index = 27; break; case 'p': index = 28; break; default: return; } if(Fl::event_shift()) { index += 29; } // This cannot happen // if(index < 0) { // return; //} index = ((octave * 12) + index) - 21; if(index < 0 || index > 87) { return; } lock(); if(keyStates[index] != value) { keyStates[index] = value; } unlock(); } int FLTKKeyboard::handle(int event) { int key; switch(event) { case FL_PUSH: if(Fl::event_button2() || Fl::event_button3()) { return 1; } key = getMIDIKey(Fl::event_x(), Fl::event_y()); this->lock(); lastMidiKey = key; keyStates[key] = 1; this->unlock(); Fl::focus(this); this->redraw(); return 1; case FL_DRAG: if(Fl::event_button2() || Fl::event_button3()) { return 1; } key = getMIDIKey(Fl::event_x(), Fl::event_y()); if(key != lastMidiKey) { this->lock(); keyStates[lastMidiKey] = -1; if(keyStates[key] != 1) { keyStates[key] = 1; } lastMidiKey = key; this->unlock(); this->redraw(); } return 1; case FL_RELEASE: if(Fl::event_button1()) { return 1; } key = getMIDIKey(Fl::event_x(), Fl::event_y()); this->lock(); keyStates[key] = 0; if(lastMidiKey >= -1) { keyStates[lastMidiKey] = -1; } lastMidiKey = -1; this->unlock(); this->redraw(); return 1; case FL_MOVE: if(lastMidiKey >= 0) { this->lock(); keyStates[lastMidiKey] = 0; lastMidiKey = -1; this->unlock(); } return 1; case FL_KEYDOWN: //csound->Message(csound, "Key Down: Code: %d\n", Fl::event_key()); if(Fl::event_ctrl() && sliderBank != NULL) { handleControl(Fl::event_key()); } else { handleKey(Fl::event_key(), 1); } Fl::focus(this); this->redraw(); return 1; case FL_KEYUP: if(Fl::focus() == this) { //csound->Message(csound, "Key Up: Code: %d\n", Fl::event_key()); handleKey(Fl::event_key(), -1); this->redraw(); return 1; } default: return Fl_Widget::handle(event); } } int FLTKKeyboard::isWhiteKey(int key) { if(key < 3) { return !(key % 2); } int adjustedKey = (key - 3) % 12; switch(adjustedKey) { case 0: case 2: case 4: case 5: case 7: case 9: case 11: return 1; } return 0; } void FLTKKeyboard::draw() { int i; int whiteKeyHeight = this->h(); int blackKeyHeight = (int)(whiteKeyHeight * .625); float whiteKeyWidth = this->w() / 52.0; int blackKeyWidth = (int)(whiteKeyWidth * .8333333); int blackKeyOffset = blackKeyWidth / 2; float runningX = (float)this->x(); int yval = this->y(); fl_draw_box(box(), this->x(), this->y(), this->w(), this->h(), FL_WHITE); fl_rect(this->x(), this->y(), this->w(),this->h(), FL_BLACK); int lineHeight = this->y() + whiteKeyHeight - 1; // Draw White Keys for(i = 0; i < 88; i++) { if(isWhiteKey(i)) { int newX = int(runningX + 0.5); if(keyStates[i] == 1) { int newW = (int(runningX + whiteKeyWidth + 0.5) - newX); fl_draw_box(box(), newX, yval, newW, whiteKeyHeight - 1, FL_BLUE); } runningX += whiteKeyWidth; fl_color(FL_BLACK); fl_line(newX, this->y(), newX, lineHeight); } } runningX = (float)this->x(); // Draw Black Keys for(i = 0; i < 88; i++) { if(isWhiteKey(i)) { runningX += whiteKeyWidth; } else { if(keyStates[i] == 1) { fl_draw_box(box(), (int)(runningX - blackKeyOffset), yval, blackKeyWidth, blackKeyHeight, FL_BLUE); } else { fl_draw_box(box(), (int)(runningX - blackKeyOffset), yval, blackKeyWidth, blackKeyHeight, FL_BLACK); } fl_rect((int)(runningX - blackKeyOffset), yval, blackKeyWidth, blackKeyHeight, FL_BLACK); } } } csound-6.10.0/InOut/virtual_keyboard/FLTKKeyboard.hpp000066400000000000000000000031631321653344700224420ustar00rootroot00000000000000/* FLTKKeyboard.hpp: Copyright (C) 2006 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FLTKKEYBOARD_HPP_ #define FLTKKEYBOARD_HPP_ #include #include #include "csdl.h" #include "SliderBank.hpp" class FLTKKeyboard : public Fl_Widget { public: FLTKKeyboard(CSOUND *csound, SliderBank *sliderBank, int X, int Y, int W, int H, const char *L); ~FLTKKeyboard(); int handle(int event); void draw(); int keyStates[88]; int changedKeyStates[88]; int whiteKeys[7]; void lock(); void unlock(); void allNotesOff(); int aNotesOff; int octave; private: int getMIDIKey(int x, int y); int lastMidiKey; int isWhiteKey(int key); int getMidiValForWhiteKey(int whiteKeyNum); void handleKey(int key, int value); void handleControl(int key); CSOUND *csound; void * mutex; SliderBank *sliderBank; }; #endif /*FLTKKEYBOARD_HPP_*/ csound-6.10.0/InOut/virtual_keyboard/FLTKKeyboardWidget.cpp000066400000000000000000000130261321653344700236000ustar00rootroot00000000000000/* FLTKKeyboardWidget.hpp: Copyright (C) 2006 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "FLTKKeyboardWidget.hpp" static void allNotesOff(Fl_Widget *widget, void * v) { FLTKKeyboardWidget *win = (FLTKKeyboardWidget *)v; win->keyboard->allNotesOff(); } static void channelChange(Fl_Widget *widget, void * v) { Fl_Spinner *spinner = (Fl_Spinner *)widget; FLTKKeyboardWidget *win = (FLTKKeyboardWidget *)v; win->lock(); int channel = (int)spinner->value() - 1; win->keyboardMapping->setCurrentChannel(channel); win->bankChoice->value(win->keyboardMapping->getCurrentBank()); win->setProgramNames(); win->unlock(); } static void bankChange(Fl_Widget *widget, void * v) { Fl_Choice *choice = (Fl_Choice *)widget; FLTKKeyboardWidget *win = (FLTKKeyboardWidget *)v; win->lock(); win->keyboardMapping->setCurrentBank((int)choice->value()); win->setProgramNames(); win->unlock(); } static void programChange(Fl_Widget *widget, void * v) { Fl_Choice *choice = (Fl_Choice *)widget; FLTKKeyboardWidget *win = (FLTKKeyboardWidget *)v; win->lock(); win->keyboardMapping->setCurrentProgram((int)choice->value()); win->unlock(); } static void octaveChange(Fl_Widget *widget, void * v) { Fl_Choice *choice = (Fl_Choice *)widget; FLTKKeyboardWidget *win = (FLTKKeyboardWidget *)v; win->lock(); win->keyboard->octave = (int)choice->value() + 1; win->unlock(); } FLTKKeyboardWidget::FLTKKeyboardWidget(CSOUND *csound, const char *deviceMap, int X, int Y, int w, int h) : Fl_Group(X, Y, w, h) { char octave[2]; octave[1] = 0; this->csound = csound; this->mutex = csound->Create_Mutex(0); this->keyboardMapping = new KeyboardMapping(csound, deviceMap); this->begin(); int baseX = this->x(); int baseY = this->y(); int row1 = baseY; int row2 = row1 + 20; int row3 = row2 + 20; int x1 = (int)(baseX + ((60 / 754.0) * w)); int x2 = (int)(baseX + ((180 / 754.0) * w)); int x3 = (int)(baseX + ((420 / 754.0) * w)); int x4 = (int)(baseX + ((670 / 754.0) * w)); int w1 = (int)((80 / 754.0) * w); int w2 = (int)((180 / 754.0) * w); int w3 = (int)((200 / 754.0) * w); int w4 = (int)((80 / 754.0) * w); //624, 120 this->channelSpinner = new Fl_Spinner(x1, row1, w1, 20, "Channel"); channelSpinner->maximum(16); channelSpinner->minimum(1); this->channelSpinner->callback((Fl_Callback*) channelChange, this); this->bankChoice = new Fl_Choice(x2, row1, w2, 20, "Bank"); this->programChoice = new Fl_Choice(x3, row1, w3, 20, "Program"); this->octaveChoice = new Fl_Choice(x4, row1, w4, 20, "Octave"); bankChoice->clear(); for(unsigned int i = 0; i < keyboardMapping->banks.size(); i++) { bankChoice->add(keyboardMapping->banks[i]->name); } bankChoice->value(0); setProgramNames(); octaveChoice->clear(); for(unsigned int i = 1; i < 8; i++) { octave[0] = i + 48; octaveChoice->add(octave); } octaveChoice->value(4); this->bankChoice->callback((Fl_Callback*)bankChange, this); this->programChoice->callback((Fl_Callback*)programChange, this); this->octaveChoice->callback((Fl_Callback*)octaveChange, this); this->allNotesOffButton = new Fl_Button(baseX, row2, w, 20, "All Notes Off"); this->allNotesOffButton->callback((Fl_Callback*) allNotesOff, this); this->keyboard = new FLTKKeyboard(csound, NULL, baseX, row3, w, h - 40, "Keyboard"); this->end(); } FLTKKeyboardWidget::~FLTKKeyboardWidget() { if (mutex) { csound->DestroyMutex(mutex); mutex = (void*) 0; } delete keyboardMapping; } void FLTKKeyboardWidget::setProgramNames() { Bank* bank = keyboardMapping->banks[keyboardMapping->getCurrentBank()]; programChoice->clear(); for( vector::iterator iter = bank->programs.begin(); iter != bank->programs.end(); iter++ ) { programChoice->add((*iter).name); } programChoice->value(bank->currentProgram); } int FLTKKeyboardWidget::handle(int event) { switch(event) { case FL_KEYDOWN: return this->keyboard->handle(event); case FL_KEYUP: return this->keyboard->handle(event); // case FL_DEACTIVATE: // this->keyboard->allNotesOff(); // csound->Message(csound, "Deactivate\n"); // return 1; default: // this->csound->Message(this->csound, "Keyboard event: %d\n", event); return Fl_Group::handle(event); } } void FLTKKeyboardWidget::lock() { if(mutex) { csound->LockMutex(mutex); } } void FLTKKeyboardWidget::unlock() { if(mutex) { csound->UnlockMutex(mutex); } } csound-6.10.0/InOut/virtual_keyboard/FLTKKeyboardWidget.hpp000066400000000000000000000033311321653344700236030ustar00rootroot00000000000000/* FLTKKeyboardWidget.hpp: Copyright (C) 2006 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FLTKKEYBOARDWIDGET_HPP_ #define FLTKKEYBOARDWIDGET_HPP_ #include #include #include #include #include #include "FLTKKeyboard.hpp" #include "KeyboardMapping.hpp" #include "csdl.h" class FLTKKeyboardWidget : public Fl_Group { public: FLTKKeyboardWidget(CSOUND * csound, const char *deviceMap, int x, int y, int w, int h); ~FLTKKeyboardWidget(); FLTKKeyboard *keyboard; Fl_Button *allNotesOffButton; Fl_Spinner *channelSpinner; Fl_Choice *bankChoice; Fl_Choice *programChoice; Fl_Choice *octaveChoice; KeyboardMapping *keyboardMapping; int handle(int event); void lock(); void unlock(); void setSelectedBank(); void setProgramNames(); private: CSOUND* csound; void * mutex; }; #endif /*FLTKKEYBOARDWIDGET_HPP_*/ csound-6.10.0/InOut/virtual_keyboard/FLTKKeyboardWindow.cpp000066400000000000000000000124121321653344700236220ustar00rootroot00000000000000/* FLTKKeyboardWindow.hpp: Copyright (C) 2006 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "FLTKKeyboardWindow.hpp" static void allNotesOff(Fl_Widget *widget, void * v) { FLTKKeyboardWindow *win = (FLTKKeyboardWindow *)v; win->keyboard->allNotesOff(); } static void channelChange(Fl_Widget *widget, void * v) { Fl_Spinner *spinner = (Fl_Spinner *)widget; FLTKKeyboardWindow *win = (FLTKKeyboardWindow *)v; win->lock(); int channel = (int)spinner->value() - 1; win->keyboardMapping->setCurrentChannel(channel); win->bankChoice->value(win->keyboardMapping->getCurrentBank()); win->setProgramNames(); win->sliderBank->setChannel(channel); win->unlock(); } static void bankChange(Fl_Widget *widget, void * v) { Fl_Choice *choice = (Fl_Choice *)widget; FLTKKeyboardWindow *win = (FLTKKeyboardWindow *)v; win->lock(); win->keyboardMapping->setCurrentBank((int)choice->value()); win->setProgramNames(); win->unlock(); } static void programChange(Fl_Widget *widget, void * v) { Fl_Choice *choice = (Fl_Choice *)widget; FLTKKeyboardWindow *win = (FLTKKeyboardWindow *)v; win->lock(); win->keyboardMapping->setCurrentProgram((int)choice->value()); win->unlock(); } static void octaveChange(Fl_Widget *widget, void * v) { Fl_Choice *choice = (Fl_Choice *)widget; FLTKKeyboardWindow *win = (FLTKKeyboardWindow *)v; win->lock(); win->keyboard->octave = (int)choice->value() + 1; win->unlock(); } FLTKKeyboardWindow::FLTKKeyboardWindow(CSOUND *csound, const char *deviceMap, int W, int H, const char *L = 0) : Fl_Double_Window(W, H, L) { char octave[2]; octave[1] = 0; this->csound = csound; this->mutex = csound->Create_Mutex(0); this->keyboardMapping = new KeyboardMapping(csound, deviceMap); this->begin(); int row1 = 0; int row2 = row1 + 150; int row3 = row2 + 20; int row4 = row3 + 20; this->sliderBank = new SliderBank(csound, 0, row1, W, 150); this->channelSpinner = new Fl_Spinner(60, row2, 80, 20, "Channel"); channelSpinner->maximum(16); channelSpinner->minimum(1); this->channelSpinner->callback((Fl_Callback*) channelChange, this); this->bankChoice = new Fl_Choice(180, row2, 180, 20, "Bank"); this->programChoice = new Fl_Choice(420, row2, 200, 20, "Program"); this->octaveChoice = new Fl_Choice(670, row2, 80, 20, "Octave"); bankChoice->clear(); for(unsigned int i = 0; i < keyboardMapping->banks.size(); i++) { bankChoice->add(keyboardMapping->banks[i]->name); } bankChoice->value(0); setProgramNames(); octaveChoice->clear(); for(unsigned int i = 1; i < 8; i++) { octave[0] = i + 48; octaveChoice->add(octave); } octaveChoice->value(4); this->bankChoice->callback((Fl_Callback*)bankChange, this); this->programChoice->callback((Fl_Callback*)programChange, this); this->octaveChoice->callback((Fl_Callback*)octaveChange, this); this->allNotesOffButton = new Fl_Button(0, row3, W, 20, "All Notes Off"); this->allNotesOffButton->callback((Fl_Callback*) allNotesOff, this); this->keyboard = new FLTKKeyboard(csound, this->sliderBank, 0, row4, W, 80, "Keyboard"); this->end(); } FLTKKeyboardWindow::~FLTKKeyboardWindow() { if (mutex) { csound->DestroyMutex(mutex); mutex = (void*) 0; } delete keyboardMapping; } void FLTKKeyboardWindow::setProgramNames() { Bank* bank = keyboardMapping->banks[keyboardMapping->getCurrentBank()]; programChoice->clear(); for( vector::iterator iter = bank->programs.begin(); iter != bank->programs.end(); iter++ ) { programChoice->add((*iter).name); } programChoice->value(bank->currentProgram); } int FLTKKeyboardWindow::handle(int event) { //this->csound->Message(this->csound, "Keyboard event: %d\n", event); switch(event) { case FL_KEYDOWN: return this->keyboard->handle(event); case FL_KEYUP: return this->keyboard->handle(event); // case FL_DEACTIVATE: // this->keyboard->allNotesOff(); // csound->Message(csound, "Deactivate\n"); // return 1; default: return Fl_Double_Window::handle(event); } } void FLTKKeyboardWindow::lock() { if(mutex) { csound->LockMutex(mutex); } } void FLTKKeyboardWindow::unlock() { if(mutex) { csound->UnlockMutex(mutex); } } csound-6.10.0/InOut/virtual_keyboard/FLTKKeyboardWindow.hpp000066400000000000000000000034371321653344700236360ustar00rootroot00000000000000/* FLTKKeyboardWindow.hpp: Copyright (C) 2006 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FLTKKEYBOARDWINDOW_HPP_ #define FLTKKEYBOARDWINDOW_HPP_ #include #include #include #include #include #include "FLTKKeyboard.hpp" #include "KeyboardMapping.hpp" #include "SliderBank.hpp" #include "csdl.h" class FLTKKeyboardWindow : public Fl_Double_Window { public: FLTKKeyboardWindow(CSOUND * csound, const char *deviceMap, int w, int h, const char* t); ~FLTKKeyboardWindow(); FLTKKeyboard *keyboard; Fl_Button *allNotesOffButton; Fl_Spinner *channelSpinner; Fl_Choice *bankChoice; Fl_Choice *programChoice; Fl_Choice *octaveChoice; KeyboardMapping *keyboardMapping; SliderBank *sliderBank; int handle(int event); void lock(); void unlock(); void setSelectedBank(); void setProgramNames(); private: CSOUND* csound; void * mutex; }; #endif /*FLTKKEYBOARDWINDOW_HPP_*/ csound-6.10.0/InOut/virtual_keyboard/KeyboardMapping.cpp000066400000000000000000000127551321653344700232770ustar00rootroot00000000000000/* KeyboardMapping.cpp: Copyright (C) 2006 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "KeyboardMapping.hpp" #include #include #define LINELENGTH (300) static char *my_fgets(char *s, int n, FILE *stream) { char *a = s; if (n <= 1) return NULL; /* best of a bad deal */ do { int ch = getc(stream); if (ch == EOF) { /* error or EOF */ if (s == a) return NULL; /* no chars -> leave */ if (ferror(stream)) a = NULL; break; /* add NULL even if ferror(), spec says 'indeterminate' */ } if (ch == '\n' || ch == '\r') { /* end of line ? */ *(s++) = '\n'; /* convert */ if (ch == '\r') { ch = getc(stream); if (ch != '\n') /* Mac format */ ungetc(ch, stream); } break; } *(s++) = ch; } while (--n > 1); *s = '\0'; return a; } KeyboardMapping::KeyboardMapping(CSOUND *csound, const char *mapFileName) { FILE *mapFile; char *mapf = strdup(mapFileName); void *fd = csound->FileOpen2(csound, &mapFile, CSFILE_STD, mapf, (void *)"r", "INCDIR", CSFTYPE_OTHER_TEXT, 0); if (fd == NULL) { initializeDefaults(csound); } else { initializeMap(csound, mapFile); csound->FileClose(csound, fd); } currentChannel = 0; previousChannel = 0; for(int i = 0; i < 16; i++) { currentBank[i] = 0; previousBank[i] = -1; } previousProgram = -1; } KeyboardMapping::~KeyboardMapping() { for(unsigned int i = 0; i < banks.size(); i++) { delete banks[i]; } } void KeyboardMapping::initializeMap(CSOUND * csound, FILE *file) { char buff[LINELENGTH]; char *p; /* 0 = general search * 1 = bank found but error in bank def, ignore all until next bank */ int state = 0; Bank *bank = NULL; while (my_fgets(buff, LINELENGTH, file)!=NULL) { p = buff; while (*p == ' ' || *p == '\t') p++; if(*p == '#') { // line comment continue; } if(*p == '[') { p++; // cleanup current bank if(bank != NULL) { if(bank->programs.size() == 0) { bank->initializeGM(); } } char *q = strstr(p, "="); char *z = strstr(p, "]"); if(q == NULL || z == NULL) { state = 1; continue; } *q = '\0'; *z = '\0'; int bankNum = atoi(p) - 1; char *name = (char *)csound->Calloc(csound, strlen(q +1) + 1); memcpy(name, q + 1, strlen(q + 1) + 1); if(bankNum >= 0 && bankNum < 16384) { bank = new Bank(csound, name); bank->bankNum = bankNum; banks.push_back(bank); //bank->initializeGM(); state = 0; } else { state = 1; } } else { if(state == 1 || bank == NULL) { continue; } char *q = strstr(p, "="); if(q == NULL) { continue; } *q = '\0'; int programNum = atoi(p) - 1; char *name = (char *)csound->Calloc(csound, strlen(q +1) + 1); memcpy(name, q + 1, strlen(q + 1) + 1); if(programNum >= 0 && programNum < 128) { Program program(programNum, name); bank->programs.push_back(program); } } } } void KeyboardMapping::initializeDefaults(CSOUND *csound) { for(int i = 0; i < 128; i++) { char * name = (char *)csound->Calloc(csound, 9); sprintf(name, "Bank %d", i + 1); Bank *temp = new Bank(csound, name); temp->initializeGM(); banks.push_back(temp); } } int KeyboardMapping::getCurrentChannel() { return currentChannel; } int KeyboardMapping::getCurrentBank() { return currentBank[currentChannel]; } int KeyboardMapping::getPreviousBank() { return previousBank[currentChannel]; } int KeyboardMapping::getCurrentProgram() { return banks[getCurrentBank()]->currentProgram; } int KeyboardMapping::getPreviousProgram() { return banks[getCurrentBank()]->previousProgram; } void KeyboardMapping::setCurrentChannel(int index) { currentChannel = index; } void KeyboardMapping::setCurrentBank(int index) { currentBank[currentChannel] = index; } void KeyboardMapping::setPreviousBank(int index) { previousBank[currentChannel] = index; } void KeyboardMapping::setCurrentProgram(int index) { banks[currentBank[currentChannel]]->currentProgram = index; } void KeyboardMapping::setPreviousProgram(int index) { banks[currentBank[currentChannel]]->previousProgram = index; } int KeyboardMapping::getCurrentBankMIDINumber() { return banks[getCurrentBank()]->bankNum; } csound-6.10.0/InOut/virtual_keyboard/KeyboardMapping.hpp000066400000000000000000000035151321653344700232760ustar00rootroot00000000000000/* KeyboardMapping.hpp: Copyright (C) 2006 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef KEYBOARDMAPPING_HPP_ #define KEYBOARDMAPPING_HPP_ #include "csdl.h" #include "Bank.hpp" #include #include #include using namespace std; class KeyboardMapping { public: KeyboardMapping(CSOUND *csound, const char *mapFileName); ~KeyboardMapping(); vector banks; int getCurrentChannel(); int getCurrentBank(); int getPreviousBank(); int getCurrentProgram(); int getPreviousProgram(); void setCurrentChannel(int index); void setCurrentBank(int index); void setPreviousBank(int index); void setCurrentProgram(int index); void setPreviousProgram(int index); int getCurrentBankMIDINumber(); int previousChannel; int previousProgram; private: void initializeDefaults(CSOUND *); void initializeMap(CSOUND *, FILE *); int currentChannel; int previousBank[16]; int currentBank[16]; }; #endif /*KEYBOARDMAPPING_HPP_*/ csound-6.10.0/InOut/virtual_keyboard/Program.cpp000066400000000000000000000017041321653344700216220ustar00rootroot00000000000000/* Program.cpp: Copyright (C) 2006 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "Program.hpp" Program::Program(int num, char *programName) { this->programNum = num; this->name = programName; } csound-6.10.0/InOut/virtual_keyboard/Program.hpp000066400000000000000000000017501321653344700216300ustar00rootroot00000000000000/* Program.hpp: Copyright (C) 2006 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef PROGRAM_HPP_ #define PROGRAM_HPP_ class Program { public: Program(int num, char * programName); int programNum; char * name; }; #endif /*PROGRAM_HPP_*/ csound-6.10.0/InOut/virtual_keyboard/SliderBank.cpp000066400000000000000000000073641321653344700222410ustar00rootroot00000000000000/* SliderBank.cpp: Copyright (C) 2006 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "SliderBank.hpp" #include #include int WheelSlider::handle(int event) { int res = Fl_Value_Slider::handle(event); if (event == FL_MOUSEWHEEL) { int dy = Fl::event_dy(); value(clamp(round(increment(value(), -dy)))); return 1; } return res; } static void spinnerCallback(Fl_Widget *widget, void *v) { Fl_Spinner *spinner = (Fl_Spinner *)widget; SliderBank *sliderBank = (SliderBank *)v; for(int i = 0; i < 10; i++) { if(sliderBank->spinners[i] == spinner) { sliderBank->lock(); SliderData* data = sliderBank->getSliderData(); data->controllerNumber[i] = (int)spinner->value(); sliderBank->unlock(); } } } static void sliderCallback(Fl_Widget *widget, void *v) { Fl_Slider *slider = (Fl_Slider *)widget; SliderBank *sliderBank = (SliderBank *)v; for(int i = 0; i < 10; i++) { if(sliderBank->sliders[i] == slider) { sliderBank->lock(); SliderData* data = sliderBank->getSliderData(); data->controllerValue[i] = (int)slider->value(); sliderBank->unlock(); } } } SliderBank::SliderBank(CSOUND *csound, int X, int Y, int W, int H) : Fl_Group(X, Y, W, H) { this->csound = csound; this->mutex = csound->Create_Mutex(0); this->channel = 0; this->begin(); for(int i = 0; i < 10; i++) { int x, y; if(i < 5) { x = 10; y = 10 + (i * 25); } else { x = 382; y = 10 + ((i - 5) * 25); } Fl_Spinner *spinner = new Fl_Spinner(x, y, 60, 20); spinners[i] = spinner; spinner->maximum(127); spinner->minimum(0); spinner->step(1); spinner->value(i + 1); spinner->callback((Fl_Callback*)spinnerCallback, this); WheelSlider *slider = new WheelSlider(x + 70, y, 292, 20); sliders[i] = slider; slider->type(FL_HOR_SLIDER); slider->maximum(127); slider->minimum(0); slider->step(1); slider->value(0); slider->callback((Fl_Callback*)sliderCallback, this); } this->end(); } SliderBank::~SliderBank() { if (mutex) { csound->DestroyMutex(mutex); mutex = (void*) 0; } } void SliderBank::setChannel(int channel) { this->channel = channel; SliderData data = sliderData[channel]; lock(); for(int i = 0; i < 10; i++) { spinners[i]->value(data.controllerNumber[i]); sliders[i]->value(data.controllerValue[i]); } unlock(); } SliderData * SliderBank::getSliderData() { return &sliderData[channel]; } void SliderBank::incrementSlider(int index, int n) { Fl_Slider* slider = sliders[index]; slider->value(slider->clamp(slider->round(slider->increment(slider->value(), n)))); } void SliderBank::lock() { if(mutex) { csound->LockMutex(mutex); } } void SliderBank::unlock() { if(mutex) { csound->UnlockMutex(mutex); } } csound-6.10.0/InOut/virtual_keyboard/SliderBank.hpp000066400000000000000000000032171321653344700222370ustar00rootroot00000000000000/* SliderBank.hpp: Copyright (C) 2006 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef SLIDERBANK_HPP_ #define SLIDERBANK_HPP_ #include #include #include #include #include "csdl.h" #include "SliderData.hpp" class WheelSlider: public Fl_Value_Slider { int handle(int); public: WheelSlider(int x, int y, int w, int h, const char *l=0) : Fl_Value_Slider (x,y,w,h,l) {} }; class SliderBank : public Fl_Group { public: SliderBank(CSOUND *csound, int X, int Y, int W, int H); virtual ~SliderBank(); CSOUND *csound; void * mutex; void setChannel(int channel); SliderData *getSliderData(); void incrementSlider(int index, int n); void lock(); void unlock(); WheelSlider* sliders[10]; Fl_Spinner* spinners[10]; private: int channel; SliderData sliderData[16]; }; #endif /*SLIDERBANK_HPP_*/ csound-6.10.0/InOut/virtual_keyboard/SliderData.cpp000066400000000000000000000021241321653344700222240ustar00rootroot00000000000000/* SliderData.hpp: Copyright (C) 2006 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "SliderData.hpp" SliderData::SliderData() { for(int i = 0; i < 10; i++) { controllerNumber[i] = (i + 1); previousControllerNumber[i] = -1; controllerValue[i] = 0; previousControllerValue[i] = -1; } } SliderData::~SliderData() { } csound-6.10.0/InOut/virtual_keyboard/SliderData.hpp000066400000000000000000000021421321653344700222310ustar00rootroot00000000000000/* SliderData.hpp: Copyright (C) 2006 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef SLIDERDATA_HPP_ #define SLIDERDATA_HPP_ class SliderData { public: SliderData(); virtual ~SliderData(); int controllerNumber[10]; int previousControllerNumber[10]; int controllerValue[10]; int previousControllerValue[10]; }; #endif /*SLIDERDATA_HPP_*/ csound-6.10.0/InOut/virtual_keyboard/keyboard.map000066400000000000000000000023031321653344700220020ustar00rootroot00000000000000# Custom Keyboard Map for Virtual Keyboard # Steven Yi # # USAGE # # When using the Virtual Keyboard, you can supply a filename for a mapping # of banks and programs via the -M flag, for example: # # csound -+rtmidi=virtual -Mkeyboard.map my_project.csd # # INFORMATION ON THE FORMAT # # -lines that start with '#' are comments # -lines that have [] start new bank definitions, # the contents are bankNum=bankName, with bankNum=[1,16384] # -lines following bank statements are program definitions # in the format programNum=programName, with programNum=[1,128] # -bankNumbers and programNumbers are defined in this file # starting with 1, but are converted to midi values (starting # with 0) when read # # NOTES # # -if an invalid bank definition is found, all program # defintions that follow will be ignored until a new # valid bank definition is found # -if a valid bank is defined by no valid programs found # for that bank, it will default to General MIDI program # definitions # -if an invalid program definition is found, it will be # ignored [1=My Bank] 1=My Test Patch 1 2=My Test Patch 2 30=My Test Patch 30 [2=My Bank2] 1=My Test Patch 1(bank2) 2=My Test Patch 2(bank2) 30=My Test Patch 30(bank3) csound-6.10.0/InOut/virtual_keyboard/virtual_keyboard.cpp000066400000000000000000000311471321653344700235650ustar00rootroot00000000000000/* virtual_keyboard.cpp: Copyright (C) 2006 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csdl.h" #include "midiops.h" #include "winFLTK.h" #include "FLTKKeyboardWindow.hpp" #include "FLTKKeyboardWidget.hpp" #include "KeyboardMapping.hpp" #include "SliderData.hpp" #include static std::map keyboardWidgets; static FLTKKeyboardWindow *createWindow(CSOUND *csound, const char *dev) { return new FLTKKeyboardWindow(csound, dev, 754, 270, "Csound Virtual Keyboard"); } static FLTKKeyboardWidget *createWidget(CSOUND *csound, const char *dev, int w, int h, int x, int y) { return new FLTKKeyboardWidget(csound, dev, x, y, w, h); } static void deleteWindow(CSOUND *csound, FLTKKeyboardWindow * keyWin) { if(keyWin == NULL) { return; } Fl_lock(csound); keyWin->hide(); delete keyWin; Fl_awake(csound); Fl_wait(csound, 0.0); Fl_unlock(csound); } extern "C" { typedef struct { OPDS h; STRINGDAT *mapFileName; MYFLT *iwidth, *iheight, *ix, *iy; } FLVKEYBD; static int OpenMidiInDevice_(CSOUND *csound, void **userData, const char *dev) { if(keyboardWidgets.find(csound) != keyboardWidgets.end()) { return 0; } FLTKKeyboardWindow *keyboard = createWindow(csound, dev); *userData = (void *)keyboard; Fl_lock(csound); keyboard->show(); Fl_wait(csound, 0.0); Fl_unlock(csound); /* report success */ return 0; } static int OpenMidiOutDevice_(CSOUND *csound, void **userData, const char *dev) { /* report success */ return 0; } static int ReadMidiWindow(CSOUND *csound, FLTKKeyboardWindow *keyWin, unsigned char *mbuf, int nbytes) { int i; Fl_lock(csound); Fl_awake(csound); Fl_wait(csound, 0.0); Fl_unlock(csound); if(!keyWin->visible()) { return 0; } int count = 0; keyWin->lock(); KeyboardMapping* keyboardMapping = keyWin->keyboardMapping; int channel = keyboardMapping->getCurrentChannel(); if(keyboardMapping->getCurrentBank() != keyboardMapping->getPreviousBank()) { int bankNum = keyboardMapping->getCurrentBankMIDINumber(); unsigned char msb = (unsigned char)(bankNum >> 7) & (unsigned char)0x7F; unsigned char lsb = (unsigned char)bankNum & (unsigned char)0x7F; *mbuf++ = (unsigned char)(0xB0 + channel); // MSB *mbuf++ = (unsigned char)0; *mbuf++ = msb; *mbuf++ = (unsigned char)(0xB0 + channel); // LSB *mbuf++ = (unsigned char)32; *mbuf++ = lsb; *mbuf++ = (unsigned char)(0xC0 + channel); // Program Change *mbuf++ = (unsigned char)keyboardMapping->getCurrentProgram(); count += 8; keyboardMapping->setPreviousBank(keyboardMapping->getCurrentBank()); keyboardMapping->setPreviousProgram(keyboardMapping->getCurrentProgram()); } else if(keyboardMapping->getCurrentProgram() != keyboardMapping->getPreviousProgram()) { *mbuf++ = (unsigned char)(0xC0 + channel); // Program Change *mbuf++ = (unsigned char)keyboardMapping->getCurrentProgram(); count += 2; keyboardMapping->setPreviousProgram(keyboardMapping->getCurrentProgram()); } keyWin->sliderBank->lock(); SliderData *sliderData = keyWin->sliderBank->getSliderData(); for(i = 0; i < 10; i++) { if(sliderData->controllerNumber[i] != sliderData->previousControllerNumber[i]) { *mbuf++ = (unsigned char)(0xB0 + channel); *mbuf++ = (unsigned char)sliderData->controllerNumber[i]; *mbuf++ = (unsigned char)sliderData->controllerValue[i]; count += 3; sliderData->previousControllerNumber[i] = sliderData->controllerNumber[i]; sliderData->previousControllerValue[i] = sliderData->controllerValue[i]; } else if(sliderData->controllerValue[i] != sliderData->previousControllerValue[i]) { *mbuf++ = (unsigned char)(0xB0 + channel); *mbuf++ = (unsigned char)sliderData->controllerNumber[i]; *mbuf++ = (unsigned char)sliderData->controllerValue[i]; count += 3; sliderData->previousControllerValue[i] = sliderData->controllerValue[i]; } } keyWin->sliderBank->unlock(); keyWin->unlock(); keyWin->keyboard->lock(); int *changedKeyStates = keyWin->keyboard->changedKeyStates; int *keyStates = keyWin->keyboard->keyStates; for(i = 0; i < 88; i++) { if(keyStates[i] == -1) { *mbuf++ = (unsigned char)0x90 + channel; *mbuf++ = (unsigned char)i + 21; *mbuf++ = (unsigned char)0; count += 3; keyStates[i] = 0; } else if(changedKeyStates[i] != keyStates[i]) { if(keyStates[i] == 1) { *mbuf++ = (unsigned char)0x90 + channel; *mbuf++ = (unsigned char)i + 21; *mbuf++ = (unsigned char)127; count += 3; } else { *mbuf++ = (unsigned char)0x90 + channel; *mbuf++ = (unsigned char)i + 21; *mbuf++ = (unsigned char)0; count += 3; } } changedKeyStates[i] = keyStates[i]; } if(keyWin->keyboard->aNotesOff == 1) { keyWin->keyboard->aNotesOff = 0; *mbuf++ = (unsigned char)0xB0; *mbuf++ = (unsigned char)123; *mbuf++ = (unsigned char)0; count += 3; } keyWin->keyboard->unlock(); return count; } static int ReadMidiWidget(CSOUND *csound, FLTKKeyboardWidget *widget, unsigned char *mbuf, int nbytes) { int i; if(!widget->visible()) { return 0; } int count = 0; widget->lock(); KeyboardMapping* keyboardMapping = widget->keyboardMapping; int channel = keyboardMapping->getCurrentChannel(); if(keyboardMapping->getCurrentBank() != keyboardMapping->getPreviousBank()) { int bankNum = keyboardMapping->getCurrentBankMIDINumber(); unsigned char msb = (unsigned char)(bankNum >> 7) & (unsigned char)0x7F; unsigned char lsb = (unsigned char)bankNum & (unsigned char)0x7F; *mbuf++ = (unsigned char)(0xB0 + channel); // MSB *mbuf++ = (unsigned char)0; *mbuf++ = msb; *mbuf++ = (unsigned char)(0xB0 + channel); // LSB *mbuf++ = (unsigned char)32; *mbuf++ = lsb; *mbuf++ = (unsigned char)(0xC0 + channel); // Program Change *mbuf++ = (unsigned char)keyboardMapping->getCurrentProgram(); count += 8; keyboardMapping->setPreviousBank(keyboardMapping->getCurrentBank()); keyboardMapping->setPreviousProgram(keyboardMapping->getCurrentProgram()); } else if(keyboardMapping->getCurrentProgram() != keyboardMapping->getPreviousProgram()) { *mbuf++ = (unsigned char)(0xC0 + channel); // Program Change *mbuf++ = (unsigned char)keyboardMapping->getCurrentProgram(); count += 2; keyboardMapping->setPreviousProgram(keyboardMapping->getCurrentProgram()); } widget->unlock(); widget->keyboard->lock(); int *changedKeyStates = widget->keyboard->changedKeyStates; int *keyStates = widget->keyboard->keyStates; for(i = 0; i < 88; i++) { if(keyStates[i] == -1) { *mbuf++ = (unsigned char)0x90 + channel; *mbuf++ = (unsigned char)i + 21; *mbuf++ = (unsigned char)0; count += 3; keyStates[i] = 0; } else if(changedKeyStates[i] != keyStates[i]) { if(keyStates[i] == 1) { *mbuf++ = (unsigned char)0x90 + channel; *mbuf++ = (unsigned char)i + 21; *mbuf++ = (unsigned char)127; count += 3; } else { *mbuf++ = (unsigned char)0x90 + channel; *mbuf++ = (unsigned char)i + 21; *mbuf++ = (unsigned char)0; count += 3; } } changedKeyStates[i] = keyStates[i]; } if(widget->keyboard->aNotesOff == 1) { widget->keyboard->aNotesOff = 0; *mbuf++ = (unsigned char)0xB0; *mbuf++ = (unsigned char)123; *mbuf++ = (unsigned char)0; count += 3; } widget->keyboard->unlock(); return count; } static int ReadMidiData_(CSOUND *csound, void *userData, unsigned char *mbuf, int nbytes) { if(keyboardWidgets.find(csound) == keyboardWidgets.end()) { return ReadMidiWindow(csound, (FLTKKeyboardWindow *)userData, mbuf, nbytes); } return ReadMidiWidget(csound, keyboardWidgets[csound], mbuf, nbytes); } static int WriteMidiData_(CSOUND *csound, void *userData, const unsigned char *mbuf, int nbytes) { /* return the number of bytes written */ return 0; } static int CloseMidiInDevice_(CSOUND *csound, void *userData) { deleteWindow(csound, (FLTKKeyboardWindow *)userData); return 0; } static int CloseMidiOutDevice_(CSOUND *csound, void *userData) { return 0; } /* FLvkeybd Opcode */ static int fl_vkeybd(CSOUND *csound, FLVKEYBD *p) { if(keyboardWidgets.find(csound) != keyboardWidgets.end()) { csound->ErrorMsg(csound, "FLvkeybd may only be used once in a project.\n"); return -1; } char *mapFileName = new char[MAXNAME]; strncpy(mapFileName, p->mapFileName->data, MAXNAME-1); FLTKKeyboardWidget *widget = createWidget(csound, mapFileName, (int)*p->iwidth, (int)*p->iheight, (int)*p->ix, (int)*p->iy); keyboardWidgets[csound] = widget; delete[] mapFileName; return OK; } #define S(x) sizeof(x) const OENTRY widgetOpcodes_[] = { { (char*)"FLvkeybd", S(FLVKEYBD), 0, 1, (char*)"", (char*)"Siiii", (SUBR) fl_vkeybd, (SUBR) NULL, (SUBR) NULL }, { NULL, 0, 0, 0, NULL, NULL, (SUBR) NULL, (SUBR) NULL,(SUBR) NULL } }; /* module interface functions */ PUBLIC int csoundModuleCreate(CSOUND *csound) { /* nothing to do, report success */ //csound->Message(csound, "virtual_keyboard real time MIDI plugin for Csound\n"); return 0; } PUBLIC int csoundModuleInit(CSOUND *csound) { char *drv; const OENTRY *ep = &(widgetOpcodes_[0]); if (csound->QueryGlobalVariable(csound, "FLTK_Flags") == (void*) 0) { if (csound->CreateGlobalVariable(csound, "FLTK_Flags", sizeof(int)) != 0) csound->Die(csound, "%s", Str("virtual_keyboard.cpp: error allocating FLTK flags")); } for ( ; ep->opname != NULL; ep++) { if (csound->AppendOpcode(csound, ep->opname, (int)ep->dsblksiz, (int)ep->flags, (int)ep->thread, ep->outypes, ep->intypes, ep->iopadr, ep->kopadr, ep->aopadr) != 0) { csound->ErrorMsg(csound, Str("Error registering opcode '%s'"), ep->opname); return -1; } } drv = (char*) (csound->QueryGlobalVariable(csound, "_RTMIDI")); if (drv == NULL) return 0; if (!(strcmp(drv, "virtual") == 0)) return 0; csound->Message(csound, "rtmidi: virtual_keyboard module enabled\n"); csound->SetExternalMidiInOpenCallback(csound, OpenMidiInDevice_); csound->SetExternalMidiReadCallback(csound, ReadMidiData_); csound->SetExternalMidiInCloseCallback(csound, CloseMidiInDevice_); csound->SetExternalMidiOutOpenCallback(csound, OpenMidiOutDevice_); csound->SetExternalMidiWriteCallback(csound, WriteMidiData_); csound->SetExternalMidiOutCloseCallback(csound, CloseMidiOutDevice_); return 0; } PUBLIC int csoundModuleInfo(void) { /* does not depend on MYFLT type */ return ((CS_APIVERSION << 16) + (CS_APISUBVER << 8)); } } // END EXTERN C csound-6.10.0/InOut/widgets.cpp000066400000000000000000006470601321653344700163260ustar00rootroot00000000000000/* widgets.cpp: Copyright (C) 2002 Gabriel Maldonado This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #if defined(WIN32) # include #endif #ifndef _MSC_VER # include #endif #if !defined(_MSC_VER) #include #endif #include #include "widglobals.h" #include Fl_Font FONT_TABLE[] = { FL_HELVETICA, FL_HELVETICA, FL_HELVETICA_BOLD, FL_HELVETICA_ITALIC, FL_HELVETICA_BOLD_ITALIC, FL_COURIER, FL_COURIER_BOLD, FL_COURIER_ITALIC, FL_COURIER_BOLD_ITALIC, FL_TIMES, FL_TIMES_BOLD, FL_TIMES_ITALIC, FL_TIMES_BOLD_ITALIC, FL_SYMBOL, FL_SCREEN, FL_SCREEN_BOLD, FL_ZAPF_DINGBATS }; Fl_Align ALIGN_TABLE[] = { FL_ALIGN_BOTTOM, FL_ALIGN_CENTER, FL_ALIGN_TOP, FL_ALIGN_BOTTOM, FL_ALIGN_LEFT, FL_ALIGN_RIGHT, FL_ALIGN_TOP_LEFT, FL_ALIGN_TOP_RIGHT, FL_ALIGN_BOTTOM_LEFT, FL_ALIGN_BOTTOM_RIGHT }; Fl_Boxtype BOX_TABLE[] = { FL_FLAT_BOX, FL_FLAT_BOX, FL_UP_BOX, FL_DOWN_BOX, FL_THIN_UP_BOX, FL_THIN_DOWN_BOX, FL_ENGRAVED_BOX, FL_EMBOSSED_BOX, FL_BORDER_BOX, _FL_SHADOW_BOX, _FL_ROUNDED_BOX, _FL_RSHADOW_BOX, _FL_RFLAT_BOX, _FL_ROUND_UP_BOX, _FL_ROUND_DOWN_BOX, _FL_DIAMOND_UP_BOX, _FL_DIAMOND_DOWN_BOX,_FL_OVAL_BOX, _FL_OSHADOW_BOX, _FL_OFLAT_BOX}; void widget_init(CSOUND *csound) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *) csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); if (widgetGlobals == NULL) { csound->CreateGlobalVariable(csound, "WIDGET_GLOBALS", sizeof(WIDGET_GLOBALS)); widgetGlobals = (WIDGET_GLOBALS *) csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); //csound->widgetGlobals = new WIDGET_GLOBALS; //csound->Calloc(csound, sizeof(WIDGET_GLOBALS)); // widgetGlobals->indrag = 0; // widgetGlobals->sldrag = 0; // widgetGlobals->stack_count) = 0; widgetGlobals->FLcontrol_iheight = 15; widgetGlobals->FLroller_iheight = 18; widgetGlobals->FLcontrol_iwidth = 400; widgetGlobals->FLroller_iwidth = 150; widgetGlobals->FLvalue_iwidth = 100; widgetGlobals->FLcolor = -1; widgetGlobals->FLcolor2 = -1; // below was commented out, why? VL 24-04-08 widgetGlobals->FLtext_size = 0; widgetGlobals->FLtext_color = -1; widgetGlobals->FLtext_font = -1; // below was commented out, why? VL 24-04-08 widgetGlobals->FLtext_align = 0; widgetGlobals->FL_ix = 10; widgetGlobals->FL_iy = 10; widgetGlobals->currentSnapGroup = 0; widgetGlobals->last_KEY=0; widgetGlobals->isKeyDown=0; } } extern void graphs_reset(CSOUND *csound); int widget_reset(CSOUND *csound, void *pp) { (void) pp; WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); if (widgetGlobals != NULL) { widgetGlobals->AddrStack.~vector(); widgetGlobals->allocatedStrings.~vector(); widgetGlobals->fl_windows.~vector(); csound->DestroyGlobalVariable(csound, "WIDGET_GLOBALS"); } graphs_reset(csound); return OK; } #ifndef NO_FLTK_THREADS extern "C" { /* called by sensevents() once in every control period */ static void evt_callback(CSOUND *csound, widgetsGlobals_t *p) { /* flush any pending real time events */ if (UNLIKELY(p->eventQueue != NULL)) { csound->LockMutex(p->mutex_); while (p->eventQueue != NULL) { rtEvt_t *ep = p->eventQueue; p->eventQueue = ep->nxt; ep->evt.pinstance = NULL; csound->UnlockMutex(p->mutex_); csound->insert_score_event_at_sample(csound, &(ep->evt), csound->GetCurrentTimeSamples(csound)); free(ep); csound->LockMutex(p->mutex_); } csound->UnlockMutex(p->mutex_); } /* if all windows have been closed, terminate performance */ if (UNLIKELY(p->exit_now)) { EVTBLK e; memset(&e, 0, sizeof(EVTBLK)); e.opcod = 'e'; csound->insert_score_event_at_sample(csound, &e, csound->GetCurrentTimeSamples(csound)); } } } // extern "C" #endif // NO_FLTK_THREADS // ---- IV - Aug 23 2002 ---- included file: Fl_linux_stubs.cpp /* * this is a file used in the linux distribution to be able to use * the DirectCsound 5.1 widget code by Gabriel Maldonado on linux * systems. * * This code has been written by Nicola Bernardini (nicb@centrotemporeale.it) * mostly based on ideas by Dave Phillips (dlphip@bright.net) */ extern "C" { void ButtonSched(CSOUND *csound, MYFLT *args[], int numargs) { /* based on code by rasmus */ #ifndef NO_FLTK_THREADS widgetsGlobals_t *p; /* this is still not fully thread safe... */ /* hope that no global variable is created just while this fn is called */ p = (widgetsGlobals_t*) csound->QueryGlobalVariable(csound, "_widgets_globals"); if (p != NULL) { rtEvt_t *evt; int i; /* Create the new event */ evt = (rtEvt_t*) malloc(sizeof(rtEvt_t)); evt->nxt = NULL; evt->evt.pinstance = NULL; evt->evt.strarg = NULL; evt->evt.scnt = 0; evt->evt.opcod = (char) *args[0]; if (evt->evt.opcod == '\0') evt->evt.opcod = 'i'; evt->evt.pcnt = numargs - 1; evt->evt.p[1] = evt->evt.p[2] = evt->evt.p[3] = MYFLT(0.0); for (i = 1; i < numargs; i++) evt->evt.p[i] = *args[i]; if (evt->evt.p[2] < MYFLT(0.0)) evt->evt.p[2] = MYFLT(0.0); /* queue event for insertion by main Csound thread */ csound->LockMutex(p->mutex_); if (p->eventQueue == NULL) p->eventQueue = evt; else { rtEvt_t *ep = p->eventQueue; while (ep->nxt != NULL) ep = ep->nxt; ep->nxt = evt; } csound->UnlockMutex(p->mutex_); } else #endif // NO_FLTK_THREADS { EVTBLK e; int i; /* Create the new event */ e.strarg = NULL; e.scnt = 0; e.opcod = (char) *args[0]; if (e.opcod == '\0') e.opcod = 'i'; e.pcnt = numargs - 1; e.p[1] = e.p[2] = e.p[3] = MYFLT(0.0); for (i = 1; i < numargs; i++) e.p[i] = *args[i]; if (e.p[2] < MYFLT(0.0)) e.p[2] = MYFLT(0.0); e.pinstance = NULL; csound->insert_score_event_at_sample(csound, &e, csound->GetCurrentTimeSamples(csound)); } } } // ---- IV - Aug 23 2002 ---- included file: Fl_Knob.cxx // generated by Fast Light User Interface Designer (fluid) version 2.00 Fl_Knob::Fl_Knob(CSOUND *cs, int xx,int yy,int ww,int hh,const char *l) : Fl_Valuator(xx,yy,ww,hh,l) { csound = cs; a1 = 35; a2 = 325; _type = DOTLIN; _percent = 0.3f; _scaleticks = 10; } Fl_Knob::~Fl_Knob(void) { } void Fl_Knob::draw(void) { int ox,oy,ww,hh,side; unsigned char rr,gg,bb; ox = x(); oy = y(); ww = w(); hh = h(); draw_label(); fl_clip(ox,oy,ww,hh); if (ww > hh) { side = hh; ox = ox + (ww - side) / 2; } else { side = ww; oy = oy + (hh - side) / 2; } side = w() > h () ? hh:ww; int dam = damage(); if (dam & FL_DAMAGE_ALL) { int col = parent()->color(); fl_color(col); fl_rectf(ox,oy,side,side); Fl::get_color((Fl_Color)col,rr,gg,bb); shadow(-60,rr,gg,bb); fl_pie(ox+9,oy+9,side-12,side-12,0,360); draw_scale(ox,oy,side); col = color(); Fl::get_color((Fl_Color)col,rr,gg,bb); shadow(15,rr,gg,bb); fl_pie(ox+6,oy+6,side-12,side-12,40,80); shadow(30,rr,gg,bb); fl_pie(ox+6,oy+6,side-12,side-12,80,220); shadow(-15,rr,gg,bb); fl_pie(ox+6,oy+6,side-12,side-12,220,260); shadow(-30,rr,gg,bb); fl_pie(ox+6,oy+6,side-12,side-12,260,400); fl_color(FL_BLACK); fl_arc(ox+6,oy+6,side-11,side-11,0,360); fl_color(col); fl_pie(ox+10,oy+10,side-20,side-20,0,360); } else { fl_color(color()); fl_pie(ox+10,oy+10,side-20,side-20,0,360); } Fl::get_color((Fl_Color)color(),rr,gg,bb); shadow(10,rr,gg,bb); fl_pie(ox+10,oy+10,side-20,side-20,110,150); fl_pie(ox+10,oy+10,side-20,side-20,290,330); shadow(17,rr,gg,bb); fl_pie(ox+10,oy+10,side-20,side-20,120,140); fl_pie(ox+10,oy+10,side-20,side-20,300,320); shadow(25,rr,gg,bb); fl_pie(ox+10,oy+10,side-20,side-20,127,133); fl_pie(ox+10,oy+10,side-20,side-20,307,313); draw_cursor(ox,oy,side); fl_pop_clip(); } int Fl_Knob::handle(int event) { int ox,oy,ww,hh; ox = x() + 10; oy = y() + 10; ww = w() - 20; hh = h() - 20; switch (event) { case FL_PUSH: handle_push(); return 1; // CHECKME ***JPff added this; is that right?*** case FL_DRAG: { int mx = Fl::event_x()-ox-ww/2; int my = Fl::event_y()-oy-hh/2; if (!mx && !my) return 1; double angle = 270-atan2((float)-my, (float)mx)*180.0/PI; double oldangle = (a2-a1)*(value()-minimum())/(maximum()-minimum()) + a1; while (angle < oldangle-180) angle += 360.0; while (angle > oldangle+180) angle -= 360.0; double val; if ((a1= a1)) { val = minimum(); } else if ((a1= a2) : (angle <= a2)) { val = maximum(); } else { val = minimum() + (maximum()-minimum())*(angle-a1)/(a2-a1); } handle_drag(clamp(round(val))); } return 1; case FL_RELEASE: handle_release(); return 1; default: return 0; } return 0; } void Fl_Knob::type(int ty) { _type = ty; } void Fl_Knob::shadow(const int offs,const uchar r,uchar g,uchar b) { int rr,gg,bb; rr = r + offs; rr = rr > 255 ? 255 : rr; rr = rr < 0 ? 0:rr; gg = g + offs; gg = gg > 255 ? 255 : gg; gg = gg < 0 ? 0 :gg ; bb = b + offs; bb = bb > 255 ? 255 : bb; bb = bb < 0 ? 0 : bb; fl_color((uchar)rr,(uchar)gg,(uchar)bb); } void Fl_Knob::draw_scale(const int ox,const int oy,const int side) { float x1,y1,x2,y2,rds,cx,cy,ca,sa; rds = side * 0.5f; cx = ox + side * 0.5f; cy = oy + side * 0.5f; if (!(_type & DOTLOG_3)) { if (_scaleticks == 0) return; double a_step = (10.0*PI/6.0) / _scaleticks; double a_orig = -(PI/3.0); for (int a = 0; a <= _scaleticks; a++) { double na = a_orig + a * a_step; ca = cos(na); sa = sin(na); x1 = cx + rds * ca; y1 = cy - rds * sa; x2 = cx + (rds-6) * ca; y2 = cy - (rds-6) * sa; fl_color(FL_BLACK); fl_line((int)x1,(int)y1,(int)x2,(int)y2); fl_color(FL_WHITE); if (sa*ca >=0) fl_line((int)x1+1,(int)y1+1,(int)x2+1,(int)y2+1); else fl_line((int)x1+1,(int)y1-1,(int)x2+1,(int)y2-1); } } else { int nb_dec = (_type & DOTLOG_3); for (int k = 0; k < nb_dec; k++) { double a_step = (10.0*PI/6.0) / nb_dec; double a_orig = -(PI/3.0) + k * a_step; for (int a = (k) ? 2:1; a <= 10; ) { double na = a_orig + log10((double)a) * a_step; ca = cos(na); sa = sin(na); x1 = cx - rds * ca; y1 = cy - rds * sa; x2 = cx - (rds-6) * ca; y2 = cy - (rds-6) * sa; fl_color(FL_BLACK); fl_line((int)x1,(int)y1,(int)x2,(int)y2); fl_color(FL_WHITE); if (sa*ca <0) fl_line((int)x1+1,(int)y1+1,(int)x2+1,(int)y2+1); else fl_line((int)x1+1,(int)y1-1,(int)x2+1,(int)y2-1); if ((a == 1) || (nb_dec == 1)) a += 1; else a += 2; } } } } void Fl_Knob::draw_cursor(const int ox,const int oy,const int side) { float rds,cur,cx,cy; double angle; rds = (side - 20.0f) * 0.5f; cur = _percent * rds * 0.5f; cx = ox + side * 0.5f; cy = oy + side * 0.5f; angle = (a2-a1)*(value()-minimum())/(maximum()-minimum()) + a1; fl_push_matrix(); fl_scale(1,1); fl_translate(cx,cy); fl_rotate(-angle); fl_translate(0,rds-cur-2.0f); if (_type 1.0f) _percent = 1.0f; if (visible()) damage(FL_DAMAGE_CHILD); } void Fl_Knob::scaleticks(const int tck) { _scaleticks = tck; if (_scaleticks < 0) _scaleticks = 0; if (_scaleticks > 31) _scaleticks = 31; if (visible()) damage(FL_DAMAGE_ALL); } // ---- IV - Aug 23 2002 ---- included file: Fl_Spin.cpp void Fl_Spin::draw() { int sxx = x(), syy = y(), sww = w(), shh = h(); Fl_Boxtype box1 = (Fl_Boxtype)(box()); int border_size=Fl::box_dx(box()); WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); if (damage()&~FL_DAMAGE_CHILD) clear_damage(FL_DAMAGE_ALL); if (!box1) box1 = (Fl_Boxtype)(box()&-2); if ((widgetGlobals->indrag || mouseobj) && deltadir!=0) { if (deltadir>0) { draw_box(fl_down(box1),sxx,syy,sww,shh/2,color()); draw_box(box1,sxx,syy+shh/2,sww,shh/2,color()); } else { draw_box(box1,sxx,syy,sww,shh/2,color()); draw_box(fl_down(box1),sxx,syy+shh/2,sww,shh/2,color()); } } else { draw_box(box1,sxx,syy,sww,shh/2,color()); draw_box(box1,sxx,syy+shh/2,sww,shh/2,color()); } sxx+=border_size; syy+=border_size; sww-=border_size*2; shh-=border_size*2; if (active_r()) { fl_color(selection_color()); } else { fl_color(selection_color() | 8); } int w1 = (sww-1)|1; // use odd sizes only int X = sxx+w1/2; int W = w1/3; int h1 = shh/2-border_size-2; int Y= syy; fl_polygon(X, Y, X+W,Y+h1 , X-W, Y+h1); Y=syy+shh/2+border_size+1+h1; fl_polygon(X, Y, X-W, Y-h1, X+W, Y-h1); clear_damage(); } void Fl_Spin::repeat_callback(void* v) { Fl_Spin* b = (Fl_Spin*)v; if (b->mouseobj) { Fl::add_timeout(0.1, repeat_callback, b); b->increment_cb(); } } void Fl_Spin::increment_cb(void) { if (!mouseobj) return; delta += deltadir; double v; switch (drag) { case 3: v = increment(value(), deltadir*100); break; case 2: v = increment(value(), deltadir*10); break; default:v = increment(value(), deltadir); break; } v = round(v); handle_drag(soft()?softclamp(v):clamp(v)); } int Fl_Spin::handle(int event) { double v; int olddelta; int mx = Fl::event_x(); int my = Fl::event_y(); int sxx = x(), syy = y(), sww = w(), shh = h(); WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); switch (event) { case FL_PUSH: // if (!step()) goto DEFAULT; iy = my; ix = mx; drag = Fl::event_button(); handle_push(); widgetGlobals->indrag=1; mouseobj=1; Fl::add_timeout(0.5, repeat_callback, this); delta=0; if (Fl::event_inside(sxx,syy,sww,shh/2)) { deltadir=1; } else if (Fl::event_inside(sxx,syy+shh/2,sww,shh/2)) { deltadir=-1; } else { deltadir=0; } increment_cb(); redraw(); return 1; case FL_DRAG: if (mouseobj) { mouseobj=0; Fl::remove_timeout(repeat_callback, this); } // if (!step()) goto DEFAULT; olddelta=delta; delta = - (Fl::event_y()-iy); if ((delta>5) || (delta<-5)) { deltadir=((olddelta-delta)>0)?-1:(((olddelta-delta)<0)?1:0); } else { deltadir=0; delta = olddelta; } switch (drag) { case 3: v = increment(value(), deltadir*100); break; case 2: v = increment(value(), deltadir*10); break; default:v = increment(value(), deltadir); break; } v = round(v); handle_drag(soft()?softclamp(v):clamp(v)); widgetGlobals->indrag=1; return 1; case FL_RELEASE: if (mouseobj) { Fl::remove_timeout(repeat_callback, this); } // if (!step()) goto DEFAULT; widgetGlobals->indrag=0; delta=0; deltadir=0; mouseobj=0; handle_release(); redraw(); return 1; default: widgetGlobals->indrag=0; return Fl_Valuator::handle(event); } } Fl_Spin::~Fl_Spin(void) { Fl::remove_timeout(repeat_callback, this); } Fl_Spin::Fl_Spin(CSOUND *cs, int x, int y, int w, int h, const char* l) : Fl_Valuator(x,y,w,h,l) { csound = cs; WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); soft_ = 0; align(FL_ALIGN_LEFT); ix=x; iy=y; drag=0; widgetGlobals->indrag=0; mouseobj = 0; deltadir=0; delta=0; indrag=0; } // ---- IV - Aug 23 2002 ---- included file: Fl_Value_Input_Spin.cpp void Fl_Value_Input_Spin::input_cb(Fl_Widget*, void* v) { Fl_Value_Input_Spin& t = *(Fl_Value_Input_Spin*)v; CSOUND *csound = t.csound; WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); double nv; if (t.step()>=1.0) nv = strtol(t.input.value(), 0, 0); else nv = csound->strtod((char*)t.input.value(), 0); widgetGlobals->hack_o_rama1 = 1; t.handle_push(); t.handle_drag(nv); t.handle_release(); widgetGlobals->hack_o_rama1 = 0; } void Fl_Value_Input_Spin::draw(void) { int sxx = x(), syy = y(), sww = w(), shh = h(); sxx += sww - buttonssize(); sww = buttonssize(); Fl_Boxtype box1 = (Fl_Boxtype)(box()&-2); int border_size=Fl::box_dx(box()); WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); if (damage()&~FL_DAMAGE_CHILD) input.clear_damage(FL_DAMAGE_ALL); input.box(box()); input.color(FL_WHITE, selection_color()); input.redraw(); input.clear_damage(); sxx+=border_size; syy+=border_size; sww-=border_size*2; shh-=border_size*2; if (!box1) box1 = (Fl_Boxtype)(box()&-2); if ((widgetGlobals->indrag || mouseobj) && deltadir!=0) { if (deltadir>0) { draw_box(fl_down(box1),sxx,syy,sww,shh/2,color()); draw_box(box1,sxx,syy+shh/2,sww,shh/2,color()); } else { draw_box(box1,sxx,syy,sww,shh/2,color()); draw_box(fl_down(box1),sxx,syy+shh/2,sww,shh/2,color()); } } else { draw_box(box1,sxx,syy,sww,shh/2,color()); draw_box(box1,sxx,syy+shh/2,sww,shh/2,color()); } sxx+=border_size; syy+=border_size; sww-=border_size*2; shh-=border_size*2; if (active_r()) { fl_color(labelcolor()); } else { fl_color(labelcolor() | 8); } int w1 = (sww-1)|1; // use odd sizes only int X = sxx+w1/2; int W = w1/3; int h1 = shh/2-border_size-2; int Y= syy; fl_polygon(X, Y, X+W,Y+h1 , X-W, Y+h1); Y=syy+shh/2+border_size+1+h1; fl_polygon(X, Y, X-W, Y-h1, X+W, Y-h1); clear_damage(); } void Fl_Value_Input_Spin::resize(int X, int Y, int W, int H) { input.resize(X,Y,W,H); Fl_Valuator::resize(X,Y,W,H); } void Fl_Value_Input_Spin::value_damage(void) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); if (widgetGlobals->hack_o_rama1) return; char buf[128]; format(buf); input.value(buf); input.mark(input.position()); // turn off selection highlight } void Fl_Value_Input_Spin::repeat_callback(void* v) { Fl_Value_Input_Spin* b = (Fl_Value_Input_Spin*)v; if (b->mouseobj) { Fl::add_timeout(.1, repeat_callback, b); b->increment_cb(); } } void Fl_Value_Input_Spin::increment_cb(void) { if (!mouseobj) return; delta+=deltadir; double v; switch (drag) { case 3: v = increment(value(), deltadir*100); break; case 2: v = increment(value(), deltadir*10); break; default:v = increment(value(), deltadir); break; } v = round(v); handle_drag(soft()?softclamp(v):clamp(v)); } int Fl_Value_Input_Spin::handle(int event) { double v; int olddelta; int mx = Fl::event_x(); int my = Fl::event_y(); int sxx = x(), syy = y(), sww = w(), shh = h(); sxx += sww - buttonssize(); sww = buttonssize(); WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); if (!widgetGlobals->indrag && ( !widgetGlobals->sldrag || !((mx>=sxx && mx<=(sxx+sww)) && (my>=syy && my<=(syy+shh)))) ) { widgetGlobals->indrag=0; switch(event) { case FL_PUSH: case FL_DRAG: widgetGlobals->sldrag=1; break; case FL_FOCUS: input.take_focus(); break; case FL_UNFOCUS: redraw(); break; default: widgetGlobals->sldrag=0; } input.type(step()>=1.0 ? FL_INT_INPUT : FL_FLOAT_INPUT); return input.handle(event); } switch (event) { case FL_PUSH: // if (!step()) goto DEFAULT; iy = my; ix = mx; drag = Fl::event_button(); handle_push(); widgetGlobals->indrag=1; mouseobj=1; Fl::add_timeout(.5, repeat_callback, this); delta=0; if (Fl::event_inside(sxx,syy,sww,shh/2)) { deltadir=1; } else if (Fl::event_inside(sxx,syy+shh/2,sww,shh/2)) { deltadir=-1; } else { deltadir=0; } increment_cb(); redraw(); return 1; case FL_DRAG: if (mouseobj) { mouseobj=0; Fl::remove_timeout(repeat_callback, this); } // if (!step()) goto DEFAULT; olddelta=delta; delta = - (Fl::event_y()-iy); if ((delta>5) || (delta<-5) ) { deltadir=((olddelta-delta)>0)?-1:(((olddelta-delta)<0)?1:0); } else { deltadir=0; delta = olddelta; } switch (drag) { case 3: v = increment(value(), deltadir*100); break; case 2: v = increment(value(), deltadir*10); break; default:v = increment(value(), deltadir); break; } v = round(v); handle_drag(soft()?softclamp(v):clamp(v)); widgetGlobals->indrag=1; return 1; case FL_RELEASE: if (mouseobj) { Fl::remove_timeout(repeat_callback, this); } // if (!step()) goto DEFAULT; widgetGlobals->indrag=0; delta=0; deltadir=0; mouseobj=0; handle_release(); redraw(); return 1; case FL_FOCUS: widgetGlobals->indrag=0; return input.take_focus(); default: widgetGlobals->indrag=0; input.type(step()>=1.0 ? FL_INT_INPUT : FL_FLOAT_INPUT); return 1; } } Fl_Value_Input_Spin::~Fl_Value_Input_Spin(void) { Fl::remove_timeout(repeat_callback, this); } Fl_Value_Input_Spin::Fl_Value_Input_Spin(CSOUND * cs, int x, int y, int w, int h, const char* l) : Fl_Valuator(x,y,w,h,l), input(x, y, w, h, 0) { csound = cs; WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); soft_ = 0; // if (input.parent()) // defeat automatic-add // ((Fl_Group*)input.parent())->remove(input); // input.parent(this); // kludge! this->parent()->add(input); input.callback(input_cb, this); input.when(FL_WHEN_CHANGED); selection_color(input.selection_color()); align(FL_ALIGN_LEFT); box(input.box()); value_damage(); buttonssize(15); ix = x; iy = y; drag = 0; widgetGlobals->indrag = 0; widgetGlobals->sldrag = 0; mouseobj = 0; deltadir = 0; delta = 0; } // ---- IV - Aug 23 2002 ---- included file: Fl_Value_Slider_Input.cpp void Fl_Value_Slider_Input::input_cb(Fl_Widget*, void* v) { Fl_Value_Slider_Input& t = *(Fl_Value_Slider_Input*)v; CSOUND *csound = t.csound; WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); double nv; if (t.step()>=1.0) nv = strtol(t.input.value(), 0, 0); else nv = csound->strtod((char*)t.input.value(), 0); widgetGlobals->hack_o_rama2 = 1; t.handle_push(); t.handle_drag(nv); t.handle_release(); widgetGlobals->hack_o_rama2 = 0; } void Fl_Value_Slider_Input::draw(void) { int sxx = x(), syy = y(), sww = w(), shh = h(); //int bww = w(); int X = x(), Y = y(), W = w(), H = h(); int border_size=Fl::box_dx(box()); if (horizontal()) { //bww = textboxsize(); sxx += textboxsize(); sww -= textboxsize(); input.resize(X,Y,W-sww,shh); } else { fl_font(input.textfont(), input.textsize()); syy += fl_height()+(border_size+1)*2; shh -= fl_height()+(border_size+1)*2; input.resize(X,Y,W,H-shh); } if (damage()&~FL_DAMAGE_CHILD) input.clear_damage(FL_DAMAGE_ALL); input.box(box()); input.color(FL_WHITE, selection_color()); input.redraw(); input.resize(X,Y,W,H); input.clear_damage(); // if (horizontal()) input.draw(); clear_damage(); draw_box(box(),sxx,syy,sww,shh,color()); sxx+=border_size; syy+=border_size; sww-=border_size*2; shh-=border_size*2; if (border_size<2) { sxx++; syy++; sww--; shh--; } Fl_Slider::draw(sxx,syy,sww,shh); } void Fl_Value_Slider_Input::resize(int X, int Y, int W, int H) { input.resize(X,Y,W,H); Fl_Value_Slider::resize(X,Y,W,H); } void Fl_Value_Slider_Input::value_damage() { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); if (widgetGlobals->hack_o_rama2) return; char buf[128]; format(buf); input.value(buf); input.mark(input.position()); // turn off selection highlight } int Fl_Value_Slider_Input::handle(int event) { int mx = Fl::event_x(); int my = Fl::event_y(); int sxx = x(), syy = y(), sww = w(), shh = h(); int border_size=Fl::box_dx(box()); WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); if (horizontal()) { sxx += textboxsize(); sww -= textboxsize(); } else { fl_font(input.textfont(), input.textsize()); syy += fl_height()+(border_size+1)*2; shh -= fl_height()+(border_size+1)*2; } if ( !widgetGlobals->indrag && ( !widgetGlobals->sldrag || !((mx>=sxx && mx<=(sxx+sww)) && (my>=syy && my<=(syy+shh)))) ) { widgetGlobals->indrag=0; switch(event) { case FL_PUSH: case FL_DRAG: widgetGlobals->sldrag=1; break; case FL_FOCUS: input.take_focus(); break; case FL_UNFOCUS: redraw(); break; default: widgetGlobals->sldrag=0; } input.type(step()>=1.0 ? FL_INT_INPUT : FL_FLOAT_INPUT); return input.handle(event); } switch (event) { case FL_PUSH: widgetGlobals->ix = mx; widgetGlobals->drag = Fl::event_button(); widgetGlobals->indrag=1; return Fl_Slider::handle(event,sxx,syy,sww,shh); case FL_DRAG: widgetGlobals->indrag=1; return Fl_Slider::handle(event,sxx,syy,sww,shh); case FL_RELEASE: // if (!step()) goto DEFAULT; if (value() != previous_value() || !Fl::event_is_click()) handle_release(); else { input.handle(FL_PUSH); input.handle(FL_RELEASE); } widgetGlobals->indrag=0; return 1; case FL_FOCUS: widgetGlobals->indrag=0; input.take_focus(); return Fl_Slider::handle(event,sxx,syy,sww,shh); default: widgetGlobals->indrag=0; input.type(step()>=1.0 ? FL_INT_INPUT : FL_FLOAT_INPUT); input.handle(event); return Fl_Slider::handle(event,sxx,syy,sww,shh); } } Fl_Value_Slider_Input::Fl_Value_Slider_Input(CSOUND *cs, int x, int y, int w, int h, const char* l) : Fl_Value_Slider(x,y,w,h,l),input(x, y, w, h, 0) { csound = cs; soft_ = 0; // if (input.parent()) // defeat automatic-add // ((Fl_Group*)input.parent())->remove(input); // input.parent(this); // kludge! // input.callback(input_cb, this); parent()->add(input); // input.when(FL_WHEN_CHANGED | FL_WHEN_ENTER_KEY); input.when(FL_WHEN_CHANGED ); selection_color(input.selection_color()); input.align(FL_ALIGN_LEFT); align(FL_ALIGN_LEFT); textboxsize(35); value_damage(); } // ---- IV - Aug 23 2002 ---- end of included files static char *GetString(CSOUND *csound, MYFLT *pname, int is_string); //--------------- static void set_butbank_value(Fl_Group *o, MYFLT value) { int childr = o->children(); Fl_Button *b; int ival = (int) value, j, label; if (ival < 0 || ival >= childr || (MYFLT) ival != value) return; for (j = 0; j < childr; j++) { b = (Fl_Button *) o->child(j); label = atoi(b->label()); if (label == ival) { b->value(1); b->do_callback(); } else b->value(0); } } inline void FLlock() { //gab Fl::lock(); } inline void FLunlock() { //gab Fl::unlock(); Fl::awake((void*) 0); } SNAPSHOT::SNAPSHOT (vector& valuators, int snapGroup) { // the constructor captures current values of all widgets // by copying all current values from "valuators" vector (AddrSetValue) // to the "fields" vector is_empty = 1; FLlock(); //<================= int i,k; int vsize = valuators.size(); for (i = 0, k = 0; i < vsize && k < vsize; i++, k++) { while (valuators[k].group != snapGroup ) { k++; if (UNLIKELY(k >=vsize)) goto err; } ADDR_SET_VALUE& v = valuators[k]; CSOUND *csound = (CSOUND*) (((OPDS *) (v.opcode))->insdshead->csound); string opcode_name, widg_name; fields.resize(i+1); if ((int) fields.size() < i+1) fields.resize(i+1); VALUATOR_FIELD* fld = &(fields[i]); float val, min, max; opcode_name = fld->opcode_name = ((OPDS *) (v.opcode))->optext->t.opcod; if (UNLIKELY(opcode_name.c_str() == NULL)) { csound->InitError(csound, Str("Invalid snapshot. Perhaps you modified " "orchestra widget code after you saved " "the snapshot bank.")); goto err; } else if (opcode_name == "FLslider") { FLSLIDER *p = (FLSLIDER *) (v.opcode); fld->widg_name = p->name->data; fld->exp = (int) *p->iexp; min = fld->min = *p->imin; max = fld->max = *p->imax; switch (fld->exp) { case LIN_: case EXP_: val = *p->kout; if (min < max) { if (val < min) val=min; else if(val>max) val=max; } else { if (val < max) val=max; else if(val>min) val=min; } break; default: val = ((Fl_Valuator *)v.WidgAddress)->value(); } fld->value = val; } else if (opcode_name == "FLslidBnk" || opcode_name == "FLvslidBnk") { FLSLIDERBANK *p = (FLSLIDERBANK *) (v.opcode); fld->widg_name = ((STRINGDAT *)p->names)->data; int numsliders = (int) *p->inumsliders; fld->sldbnk = p->slider_data; // fld->sldbnkValues = new MYFLT[numsliders]; // widgetGlobals->allocatedStrings.push_back((char *) fld->sldbnkValues); fld->exp = numsliders; // EXCEPTIONAL CASE! fld->exp contains the number // of sliders and not the exponential flag for (int j =0; j < numsliders; j++) { switch (fld->sldbnk[j].exp) { case LIN_: case EXP_: val = *fld->sldbnk[j].out; min = fld->sldbnk[j].min; max = fld->sldbnk[j].max; if (min < max) { if (val < min) val=min; else if(val>max) val=max; } else { if (val < max) val=max; else if(val>min) val=min; } break; default: val = ((Fl_Valuator *) ((Fl_Group*)v.WidgAddress)-> child(j))->value(); } fld->set_sldbnk(j, val); } } else if (opcode_name == "FLslidBnk2" || opcode_name == "FLvslidBnk2") { FLSLIDERBANK2 *p = (FLSLIDERBANK2 *) (v.opcode); fld->widg_name = ((STRINGDAT *)p->names)->data; int numsliders = (int) *p->inumsliders; fld->sldbnk = p->slider_data; // EXCEPTIONAL CASE! fld->exp contains the number of sliders // and not the exponential flag fld->exp = numsliders; for (int j =0; j < numsliders; j++) { switch (fld->sldbnk[j].exp) { case LIN_: case EXP_: val = *fld->sldbnk[j].out; min = fld->sldbnk[j].min; max = fld->sldbnk[j].max; if (min < max) { if (val < min) val=min; else if(val>max) val=max; } else { if (val < max) val=max; else if(val>min) val=min; } break; default: val = ((Fl_Valuator *) ((Fl_Group*) v.WidgAddress)->child(j))->value(); } fld->set_sldbnk(j, val); } } else if (opcode_name == "FLknob") { FLKNOB *p = (FLKNOB *) (v.opcode); fld->widg_name = p->name->data; fld->exp = (int) *p->iexp; min = fld->min = *p->imin; max = fld->max = *p->imax; switch (fld->exp) { case LIN_: case EXP_: val = *p->kout; if (min < max) { if (val < min) val=min; else if(val>max) val=max; } else { if (val < max) val=max; else if(val>min) val=min; } break; default: val = ((Fl_Valuator *)v.WidgAddress)->value(); } fld->value = val; } else if (opcode_name == "FLroller") { FLROLLER *p = (FLROLLER *) (v.opcode); fld->widg_name = p->name->data; fld->exp = (int) *p->iexp; min = fld->min = *p->imin; max = fld->max = *p->imax; switch (fld->exp) { case LIN_: case EXP_: val = *p->kout; if (min < max) { if (val < min) val=min; else if(val>max) val=max; } else { if (val < max) val=max; else if(val>min) val=min; } break; default: val = ((Fl_Valuator *)v.WidgAddress)->value(); } fld->value = val; } else if (opcode_name == "FLtext") { FLTEXT *p = (FLTEXT *) (v.opcode); fld->widg_name = p->name->data; val = *p->kout; min = fld->min = *p->imin; max = fld->max = *p->imax; if (min < max) { if (val < min) val=min; else if(val>max) val=max; } else { if (val < max) val=max; else if(val>min) val=min; } fld->value = val; fld->exp = LIN_; } else if (opcode_name == "FLjoy") { FLJOYSTICK *p = (FLJOYSTICK *) (v.opcode); fld->widg_name = p->name->data; fld->exp = (int) *p->iexpx; min = fld->min = *p->iminx; max = fld->max = *p->imaxx; switch (fld->exp) { case LIN_: case EXP_: val = *p->koutx; if (min < max) { if (val < min) val=min; else if(val>max) val=max; } else { if (val < max) val=max; else if(val>min) val=min; } break; default: val = ((Fl_Positioner *)v.WidgAddress)->xvalue(); } fld->value = val; fld->exp2 = (int) *p->iexpy; min = fld->min2 = *p->iminy; max = fld->max2 = *p->imaxy; switch (fld->exp2) { case LIN_: case EXP_: val = *p->kouty; if (min < max) { if (val < min) val=min; else if(val>max) val=max; } else { if (val < max) val=max; else if(val>min) val=min; } break; default: val = ((Fl_Positioner *)v.WidgAddress)->yvalue(); } fld->value2 =val; } else if (opcode_name == "FLbutton") { FLBUTTON *p = (FLBUTTON *) (v.opcode); fld->widg_name = p->name->data; fld->value = *p->kout; fld->min = 0; fld->max = 1; fld->exp = LIN_; } else if (opcode_name == "FLbutBank") { FLBUTTONBANK *p = (FLBUTTONBANK *) (v.opcode); fld->widg_name = Str("No name for FLbutbank"); //fld->widg_name = GetString(csound, p->name, p->XSTRCODE); fld->value = *p->kout; fld->min = 0; fld->max = 1; fld->exp = LIN_; } else if (opcode_name == "FLcount") { FLCOUNTER *p = (FLCOUNTER *) (v.opcode); fld->widg_name = p->name->data; val = *p->kout; min = *p->imin; max =*p->imax; if (min != max) { if (val < min) val=min; else if (val>max) val=max; } fld->value = val; fld->min = *p->imin; fld->max = *p->imax; fld->exp = LIN_; } else if (opcode_name == "FLvalue") { FLVALUE *p = (FLVALUE *) (v.opcode); fld->widg_name = p->name->data; } else if (opcode_name == "FLbox") { FL_BOX *p = (FL_BOX *) (v.opcode); fld->widg_name = p->itext->data; } } err: FLunlock(); //<================= } int SNAPSHOT::get(vector& valuators, int snapGroup) { if (UNLIKELY(is_empty == 1)) { /* FIXME: should have CSOUND* pointer here */ /* return csound->InitError(csound, Str("empty snapshot")); */ return -1; } FLlock(); //<================= int j,k; int siz =valuators.size(); for (j = 0, k = 0; j< siz && k < siz; j++, k++) { // int grp = valuators[k].group; //Not used while (valuators[k].group != snapGroup) { k++; if (k >= (int) valuators.size()) goto end_func; } Fl_Widget* o = (Fl_Widget*) (valuators[k].WidgAddress); void *opcode = valuators[k].opcode; //CSOUND *csound = (CSOUND*) (((OPDS*) opcode)->insdshead->csound); //Not used VALUATOR_FIELD* fld = &fields[j]; string opcode_name = fld->opcode_name; MYFLT val = fld->value, valtab = fld->value, min=fld->min, max=fld->max, range,base; if (min < max) { if (val < min) val = min; else if (val >max) val = max; } else { if (val < max) val=max; else if(val>min) val=min; } if (opcode_name == "FLjoy") { switch(fld->exp) { case LIN_: ((Fl_Positioner*) o)->xvalue(val); break; case EXP_: range = fld->max - fld->min; #if defined(sun) base = ::pow(fld->max / (double)fld->min, 1.0/(double)range); #else base = ::pow(fld->max / fld->min, 1.0/(double)range); #endif ((Fl_Positioner*) o)->xvalue(log(val/fld->min) / log(base)) ; break; default: ((Fl_Positioner*) o)->xvalue(valtab); break; } val = fld->value2; min = fld->min2; max = fld->max2; // if (val < min) val = min; // else if (val >max) val = max; switch(fld->exp2) { case LIN_: ((Fl_Positioner*) o)->yvalue(val); break; case EXP_: range = fld->max2 - fld->min2; #if defined(sun) base = ::pow(fld->max2 / (double)fld->min2, 1.0/(double)range); #else base = ::pow(fld->max2 / fld->min2, 1.0/(double)range); #endif ((Fl_Positioner*) o)->yvalue(log(val/fld->min2) / log(base)) ; break; default: ((Fl_Positioner*) o)->yvalue(valtab); break; } o->do_callback(o, opcode); } else if (opcode_name == "FLbutton") { FLBUTTON *p = (FLBUTTON*) (opcode); // don't allow to retreive its value if >= 10 or between 21 and 29 if ((*p->itype < 10) || (*p->itype < 30 && *p->itype > 20)) { if(fld->value >= *p->ioff - 0.0001 && fld->value <= *p->ioff + 0.0001) // to avoid eventual math rounding ((Fl_Button*) o)->value(0); else if (fld->value >= *p->ion - 0.0001 && fld->value <= *p->ion + 0.0001) // to avoid eventual math rounding ((Fl_Button*) o)->value(1); else ((Fl_Button*) o)->value((int)fld->value); o->do_callback(o, opcode); } } else if (opcode_name == "FLbutBank") { FLBUTTONBANK *p = (FLBUTTONBANK*) (opcode); if (*p->itype < 10 || (*p->itype < 30 && *p->itype > 20)) { // don't allow to retreive its value if >= 10 //((Fl_Group*) o)->value(fld->value); set_butbank_value((Fl_Group*) o, fld->value); //o->do_callback(o, opcode); *p->kout=fld->value; if (*p->args[0] >= 0) ButtonSched(p->h.insdshead->csound, p->args, p->INOCOUNT-7); } } else if (opcode_name == "FLcount") { FLCOUNTER *p = (FLCOUNTER*) (opcode); if (*p->itype < 10 || (*p->itype < 30 && *p->itype > 20)) { // don't allow to retreive its value if >= 10 ((Fl_Counter*) o)->value(fld->value); o->do_callback(o, opcode); } } else if (opcode_name == "FLslidBnk" || opcode_name == "FLvslidBnk") { FLSLIDERBANK *p = (FLSLIDERBANK*) (opcode); int numsliders = (int) *p->inumsliders; Fl_Group * grup = (Fl_Group *) o; for (int j =0; j < numsliders; j++) { MYFLT val = fld->get_sldbnk(j); switch (p->slider_data[j].exp) { case LIN_: ((Fl_Valuator *) grup->child(j))->value(val); break; case EXP_: range = p->slider_data[j].max - p->slider_data[j].min; #if defined(sun) base = ::pow(p->slider_data[j].max / (double)p->slider_data[j].min, 1.0/(double)range); #else base = ::pow(p->slider_data[j].max / p->slider_data[j].min, 1.0/(double)range); #endif ((Fl_Valuator*) grup->child(j))-> value(log(val/p->slider_data[j].min) / log(base)) ; break; default:// TABLE the value must be in the 0 to 1 range... val = (val - fld->min ) / (fld->max - fld->min); ((Fl_Valuator *) grup->child(j))->value(val); break; } grup->child(j)->do_callback( grup->child(j), (void *) &(p->slider_data[j])); } } else if (opcode_name == "FLslidBnk2" || opcode_name == "FLvslidBnk2") { FLSLIDERBANK2 *p = (FLSLIDERBANK2*) (opcode); int numsliders = (int) *p->inumsliders; Fl_Group * grup = (Fl_Group *) o; for (int j =0; j < numsliders; j++) { MYFLT val = fld->get_sldbnk(j); switch (p->slider_data[j].exp) { case LIN_: ((Fl_Valuator *) grup->child(j))->value(val); break; case EXP_: range = p->slider_data[j].max - p->slider_data[j].min; base = pow(p->slider_data[j].max / p->slider_data[j].min, 1/range); ((Fl_Valuator*) grup->child(j))->value(log(val/p->slider_data[j].min) / log(base)) ; break; default:// TABLE the value must be in the 0 to 1 range... val = (val - fld->min ) / (fld->max - fld->min); ((Fl_Valuator *) grup->child(j))->value(val); break; } grup->child(j)->do_callback( grup->child(j), (void *) &(p->slider_data[j])); } } else { switch(fld->exp) { case LIN_: if (opcode_name == "FLbox" || opcode_name == "FLvalue" ) continue; else if (opcode_name == "FLtext" && *((FLTEXT *)opcode)->itype == 1) { ((Fl_Valuator*) o)->value(val); continue; } ((Fl_Valuator*) o)->value(val); break; case EXP_: range = fld->max - fld->min; #if defined(sun) base = ::pow(fld->max / (double)fld->min, 1.0/(double)range); #else base = ::pow(fld->max / fld->min, 1.0/(double)range); #endif ((Fl_Valuator*) o)->value(log(val/fld->min) / log(base)) ; break; default: // TABLE the value must be in the 0 to 1 range... ((Fl_Valuator*) o)->value(valtab); break; } o->do_callback(o, opcode); } } end_func: FLunlock(); //<================= return OK; } extern "C" { static int set_snap(CSOUND *csound, FLSETSNAP *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); SNAPSHOT snap(widgetGlobals->AddrSetValue, (int) *p->group ); int numfields = snap.fields.size(); int index = (int) *p->index; int group = (int) *p->group; SNAPVEC snapvec_init; SNAPSHOT snap_init; snap_init.fields.resize(1,VALUATOR_FIELD()); snapvec_init.resize(1,snap_init); if (group+1 > (int) widgetGlobals->snapshots.size()) widgetGlobals->snapshots.resize(group+1, snapvec_init); // *p->inum_snap = widgetGlobals->snapshots.size(); *p->inum_val = numfields; // number of snapshots if (*p->ifn >= 1) { // if the table number is valid FUNC *ftp; // store the snapshot into the table if (LIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) != NULL)) { MYFLT *table = ftp->ftable; for (int j = 0; j < numfields; j++) { table[index*numfields+j] = snap.fields[j].value; } } else return csound->InitError(csound, Str("FLsetsnap: invalid table")); } else { // else store it into snapshot bank if ((int) widgetGlobals->snapshots[group].size() < index+1) widgetGlobals->snapshots[group].resize(index+1); csound->Message(csound, Str("setsnap saving\n")); widgetGlobals->snapshots[group][index]=snap; *p->inum_snap = widgetGlobals->snapshots[group].size(); } return OK; } static int get_snap(CSOUND *csound, FLGETSNAP *p) { int index = (int) *p->index; int group = (int) *p->group; SNAPVEC snapvec_init; SNAPSHOT snap_init; WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); snap_init.fields.resize(1,VALUATOR_FIELD()); snapvec_init.resize(1,snap_init); if (group+1 > (int) widgetGlobals->snapshots.size()) widgetGlobals->snapshots.resize(group+1, snapvec_init); if (!widgetGlobals->snapshots[group].empty()) { if (index >= (int) widgetGlobals->snapshots[group].size()) index = widgetGlobals->snapshots[group].size()-1; else if (index < 0) index=0; if (widgetGlobals->snapshots[group][index].get(widgetGlobals->AddrSetValue, (int) *p->group)!=OK) return NOTOK; } *p->inum_el = widgetGlobals->snapshots[group].size(); return OK; } static int save_snap(CSOUND *csound, FLSAVESNAPS *p) { char s[MAXNAME], *s2; string filename; #ifdef WIN32 int id = MessageBox(NULL, Str("Saving could overwrite the old file.\n" "Are you sure to save ?"), Str("Warning"), MB_SYSTEMMODAL | MB_ICONWARNING | MB_OKCANCEL); if (id != IDOK) return OK; #else # if !defined(NO_FLTK_THREADS) if (!((getFLTKFlags(csound) & 260) ^ 4)) # endif { int n; Fl_lock(csound); n = fl_choice("%s", Str("Saving could overwrite the old file.\n" "Are you sure you want to save ?"), Str("No"), Str("Yes"), (const char*)""); // used to be NULL Fl_unlock(csound); if (!n) return OK; } #endif csound->strarg2name(csound, s, p->filename->data, "snap.", 1); s2 = csound->FindOutputFile(csound, s, "SNAPDIR"); if (UNLIKELY(s2 == NULL)) return csound->InitError(csound, Str("FLsavesnap: cannot open file")); strncpy(s, s2, MAXNAME-1); csound->Free(csound, s2); filename = s; fstream file(filename.c_str(), ios::out); int group = (int) *p->group; WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); for (int j =0; j < (int) widgetGlobals->snapshots[group].size(); j++) { file << "----------- "<< j << " -----------\n"; int siz = widgetGlobals->snapshots[group][j].fields.size(); for ( int k = 0; k < siz; k++) { VALUATOR_FIELD& f = widgetGlobals->snapshots[group][j].fields[k]; // if (f.group != group) continue; if (f.opcode_name == "FLjoy") { file <QueryGlobalVariable(csound, "WIDGET_GLOBALS"); csound->strarg2name(csound, s, p->filename->data, "snap.", 1); s2 = csound->FindInputFile(csound, s, "SNAPDIR"); if (UNLIKELY(s2 == NULL)) return csound->InitError(csound, Str("FLloadsnap: cannot open file")); strncpy(s, s2, MAXNAME-1); csound->Free(csound, s2); filename = s; fstream file(filename.c_str(), ios::in); int group = (int) *p->group; int j=0,k=-1,q=0; SNAPVEC snapvec_init; SNAPSHOT snap_init; snap_init.fields.resize(1,VALUATOR_FIELD()); snapvec_init.resize(1,snap_init); if (group+1 > (int) widgetGlobals->snapshots.size()) widgetGlobals->snapshots.resize(group+1, snapvec_init); while (!(file.eof())) { char buf[MAXNAME]; file.getline(buf,MAXNAME-1); stringstream sbuf; sbuf << buf; string opc, opc_orig; getline(sbuf, opc, ' '); const char *ss = opc.c_str(); if (*ss == '-') { // if it is a separation line k++; j=0; q=0; if ((int) widgetGlobals->snapshots[group].size() < k+1) widgetGlobals->snapshots[group].resize(k+1); } else if (*ss != '\0' && *ss != ' ' && *ss != '\n'){ //ignore blank lines ADDR_SET_VALUE* v = &(widgetGlobals->AddrSetValue[q]); while (widgetGlobals->AddrSetValue[q].group != group) { q++; if (q >= (int) widgetGlobals->AddrSetValue.size()) continue; v = &(widgetGlobals->AddrSetValue[q]); } if (k<0) return NOTOK; if ((int) widgetGlobals->snapshots[group][k].fields.size() < j+1) widgetGlobals->snapshots[group][k].fields.resize(j+1); widgetGlobals->snapshots[group][k].is_empty = 0; VALUATOR_FIELD& fld = widgetGlobals->snapshots[group][k].fields[j]; opc_orig = ((OPDS *) (v->opcode))->optext->t.opcod; if (UNLIKELY(!(opc_orig == opc))) { //return csound->InitError(csound, csound->Message(csound, Str("unmatched widget, probably due to a " "modified orchestra. Modifying an " "orchestra makes it incompatible with " "old snapshot files")); } else if (opc == "FLjoy") { fld.opcode_name = opc; string s; getline(sbuf,s, ' '); fld.value = atof(s.c_str()); getline(sbuf,s, ' '); fld.value2 = atof(s.c_str()); getline(sbuf,s, ' '); fld.min = atof(s.c_str()); getline(sbuf,s, ' '); fld.max = atof(s.c_str()); getline(sbuf,s, ' '); fld.min2 = atof(s.c_str()); getline(sbuf,s, ' '); fld.max2 = atof(s.c_str()); getline(sbuf,s, ' '); fld.exp = atoi(s.c_str()); getline(sbuf,s, ' '); fld.exp2 = atoi(s.c_str()); getline(sbuf,s, '\"'); getline(sbuf,s, '\"'); fld.widg_name = s; } else if (opc == "FLslidBnk" || opc == "FLvslidBnk" || opc == "FLslidBnk2" || opc == "FLvslidBnk2" ) { fld.opcode_name = opc; string s; getline(sbuf,s, ' '); // EXCEPTIONAL CASE! fld.exp contains the number of sliders // and not the exponential flag fld.exp = atoi(s.c_str()); // fld.sldbnkValues = new MYFLT[fld.exp]; // fld.insert_sldbnk(fld.exp); // allocatedStrings.push_back((char *) fld.sldbnkValues); // widgetGlobals->allocatedStrings.push_back((char *) fld.sldbnkValues); for (int kk =0; kk < fld.exp; kk++) { getline(sbuf,s, ' '); // fld.sldbnkValues[kk] = atof(s.c_str()); fld.set_sldbnk(kk,atof(s.c_str())); } getline(sbuf,s, '\"'); getline(sbuf,s, '\"'); fld.widg_name = s; } else { fld.opcode_name = opc; string s; getline(sbuf,s, ' '); fld.value = atof(s.c_str()); getline(sbuf,s, ' '); fld.min = atof(s.c_str()); getline(sbuf,s, ' '); fld.max = atof(s.c_str()); getline(sbuf,s, ' '); fld.exp = atoi(s.c_str()); getline(sbuf,s, '\"'); getline(sbuf,s, '\"'); fld.widg_name = s; } j++; q++; } } file.close(); return OK; } static int fltkKeyboardCallback(void *, void *, unsigned int); } // extern "C" // ----------- static char *GetString(CSOUND *csound, MYFLT *pname, int is_string) { char *Name = new char[MAXNAME]; WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); widgetGlobals->allocatedStrings.push_back(Name); return csound->strarg2name(csound, Name, pname, "", is_string); } class CsoundFLTKKeyboardBuffer { private: CSOUND *csound; WIDGET_GLOBALS *widgetGlobals; void *mutex_; char kbdTextBuf[64]; int kbdEvtBuf[64]; int kbdTextBufRPos; int kbdTextBufWPos; int kbdEvtBufRPos; int kbdEvtBufWPos; std::map keyboardState; void lockMutex() { if (mutex_) csound->LockMutex(mutex_); } void unlockMutex() { if (mutex_) csound->UnlockMutex(mutex_); } public: CsoundFLTKKeyboardBuffer(CSOUND *csound) { this->csound = csound; widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); mutex_ = csound->Create_Mutex(0); kbdTextBufRPos = 0; kbdTextBufWPos = 0; kbdEvtBufRPos = 0; kbdEvtBufWPos = 0; } ~CsoundFLTKKeyboardBuffer() { if (mutex_) { csound->DestroyMutex(mutex_); mutex_ = (void*) 0; } } CSOUND *GetCsound() { return csound; } void writeFLEvent(int evt) { const char *s; int keyCode; keyCode = (int) Fl::event_key() & (int) 0xFFFF; if (keyCode) { lockMutex(); if (evt == FL_KEYDOWN) { s = Fl::event_text(); while (*s != (char) 0) { kbdTextBuf[kbdTextBufWPos] = *(s++); kbdTextBufWPos = (kbdTextBufWPos + 1) & 63; } if (keyboardState[keyCode] == (unsigned char) 0) { keyboardState[keyCode] = (unsigned char) 1; kbdEvtBuf[kbdEvtBufWPos] = keyCode; kbdEvtBufWPos = (kbdEvtBufWPos + 1) & 63; } } else if (keyboardState[keyCode] != (unsigned char) 0) { keyboardState[keyCode] = (unsigned char) 0; kbdEvtBuf[kbdEvtBufWPos] = keyCode | (int) 0x10000; kbdEvtBufWPos = (kbdEvtBufWPos + 1) & 63; } unlockMutex(); } } int getKeyboardText() { int retval = 0; lockMutex(); if (kbdTextBufRPos != kbdTextBufWPos) { retval = (int) ((unsigned char) kbdTextBuf[kbdTextBufRPos]); kbdTextBufRPos = (kbdTextBufRPos + 1) & 63; } unlockMutex(); return retval; } int getKeyboardEvent() { int retval = 0; lockMutex(); if (kbdEvtBufRPos != kbdEvtBufWPos) { retval = kbdEvtBuf[kbdEvtBufRPos]; kbdEvtBufRPos = (kbdEvtBufRPos + 1) & 63; } unlockMutex(); return retval; } }; class CsoundFLWindow : public Fl_Double_Window { public: CSOUND *csound_; //gab WIDGET_GLOBALS *widgetGlobals; CsoundFLTKKeyboardBuffer fltkKeyboardBuffer; CsoundFLWindow(CSOUND *csound, int w, int h, const char *title = 0) : Fl_Double_Window(w, h, title), csound_(csound), fltkKeyboardBuffer(csound)//gab { widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); csound->Set_KeyCallback(csound, fltkKeyboardCallback, (void*) this, CSOUND_CALLBACK_KBD_EVENT | CSOUND_CALLBACK_KBD_TEXT); } CsoundFLWindow(CSOUND *csound, int x, int y, int w, int h, const char *title = 0) : Fl_Double_Window(x, y, w, h, title), csound_(csound), fltkKeyboardBuffer(csound)//gab { widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); csound->Set_KeyCallback(csound, fltkKeyboardCallback, (void*) this, CSOUND_CALLBACK_KBD_EVENT | CSOUND_CALLBACK_KBD_TEXT); } virtual ~CsoundFLWindow() { CSOUND *csound = fltkKeyboardBuffer.GetCsound(); csound->Remove_KeyCallback(csound, fltkKeyboardCallback); } virtual int handle(int evt) { switch (evt) { case FL_FOCUS: Fl::focus(this); case FL_UNFOCUS: return 1; case FL_KEYDOWN: widgetGlobals->last_KEY = Fl::event_key(); //gab widgetGlobals->isKeyDown = true; //gab break; case FL_KEYUP: widgetGlobals->last_KEY = Fl::event_key(); //gab widgetGlobals->isKeyDown = false; //gab if (Fl::focus() == this) fltkKeyboardBuffer.writeFLEvent(evt); break; } return Fl_Window::handle(evt); } }; extern "C" { static int fltkKeyboardCallback(void *userData, void *p, unsigned int type) { switch (type) { case CSOUND_CALLBACK_KBD_EVENT: *((int*) p) = ((CsoundFLWindow*) userData)->fltkKeyboardBuffer.getKeyboardEvent(); break; case CSOUND_CALLBACK_KBD_TEXT: *((int*) p) = ((CsoundFLWindow*) userData)->fltkKeyboardBuffer.getKeyboardText(); break; default: return 1; } return 0; } PUBLIC int csoundModuleDestroy(CSOUND *csound) { int j; WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); #ifndef NO_FLTK_THREADS int *fltkflags = getFLTKFlagsPtr(csound); if (fltkflags) { if ((*fltkflags & 260) ^ 4) { widgetsGlobals_t *p = (widgetsGlobals_t*) csound->QueryGlobalVariable(csound, "_widgets_globals"); if (p) { if (!(*fltkflags & 256)) { /* if window(s) still open: */ if (!p->exit_now) { /* notify GUI thread... */ p->end_of_perf = -1; Fl_lock(csound); Fl_awake(csound); Fl_unlock(csound); /* ...and wait for it to close */ csound->JoinThread(p->threadHandle); p->threadHandle = NULL; } } /* clean up */ csound->LockMutex(p->mutex_); while (p->eventQueue != NULL) { rtEvt_t *nxt = p->eventQueue->nxt; free(p->eventQueue); p->eventQueue = nxt; } csound->UnlockMutex(p->mutex_); csound->DestroyMutex(p->mutex_); csound->DestroyGlobalVariable(csound, "_widgets_globals"); } } } #endif // NO_FLTK_THREADS if(widgetGlobals != NULL) { for (j = widgetGlobals->allocatedStrings.size() - 1; j >= 0; j--) { delete[] widgetGlobals->allocatedStrings[j]; widgetGlobals->allocatedStrings.pop_back(); } j = widgetGlobals->fl_windows.size(); if (j > 0) { // destroy all opened panels do { j--; if (widgetGlobals->fl_windows[j].is_subwindow == 0) delete widgetGlobals->fl_windows[j].panel; // VL: this might leak memory, needs checking. widgetGlobals->fl_windows.pop_back(); } while (j); Fl_wait_locked(csound, 0.0); } widgetGlobals->AddrStack.~vector(); widgetGlobals->allocatedStrings.~vector(); widgetGlobals->fl_windows.~vector(); for (size_t si = 0, sn = widgetGlobals->snapshots.size(); si < sn; ++si) { SNAPVEC &svec = widgetGlobals->snapshots[si]; int ss = svec.size(); for (j = 0; j < ss; j++) { svec[j].fields.erase(svec[j].fields.begin(), svec[j].fields.end()); // VL: probably leaks memory, needs checking. svec.resize(svec.size() + 1); } } widgetGlobals->AddrSetValue.clear(); // VL: leaks memory, needs fixing. widgetGlobals->stack_count = 0; widgetGlobals->FLcontrol_iheight = 15; widgetGlobals->FLroller_iheight = 18; widgetGlobals->FLcontrol_iwidth = 400; widgetGlobals->FLroller_iwidth = 150; widgetGlobals->FLvalue_iwidth = 100; widgetGlobals->FLcolor = -1; widgetGlobals->FLcolor2 = -1; widgetGlobals->FLtext_size = 0; widgetGlobals->FLtext_color = -1; widgetGlobals->FLtext_font = -1; widgetGlobals->FLtext_align = 0; widgetGlobals->FL_ix = 10; widgetGlobals->FL_iy = 10; //delete (WIDGET_GLOBALS*)csound->widgetGlobals; csound->DestroyGlobalVariable(csound, "WIDGET_GLOBALS"); //csound->widgetGlobals = NULL; } return 0; } } // extern "C" //----------- #ifndef NO_FLTK_THREADS extern "C" { static uintptr_t fltkRun(void *userdata) { volatile widgetsGlobals_t *p; CSOUND *csound = (CSOUND*) userdata; int j; WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); p = (widgetsGlobals_t*) csound->QueryGlobalVariable(csound, "_widgets_globals"); #ifdef LINUX { struct sched_param sp; // IV - Aug 27 2002: widget thread is always run with normal priority memset(&sp, 0, sizeof(struct sched_param)); pthread_setschedparam(pthread_self(), SCHED_OTHER, &sp); } #endif if (!(p->fltkFlags & 8)) Fl::lock(); for (j = 0; j < (int) widgetGlobals->fl_windows.size(); j++) { widgetGlobals->fl_windows[j].panel->show(); } #ifdef CS_VSTHOST for (size_t k=0; k < widgetGlobals->VSTplugEditors.size(); k++) { int panelNum = widgetGlobals->VSTplugEditors[k]->targetFLpanel; #ifdef WIN32 HWND xid = fl_xid(widgetGlobals->fl_windows[panelNum].panel); widgetGlobals->VSTplugEditors[k]->SetEditWindow(xid); #elif defined (LINUX) || defined(MACOSX) // put some appropriate alternative code here Fl_Window * xid = fl_find(fl_xid(widgetGlobals->fl_windows[panelNum].panel)); widgetGlobals->VSTplugEditors[k]->SetEditWindow(xid); #endif // WIN32 } #endif // CS_VSTHOST if (!(p->fltkFlags & 16)) Fl::awake(); if (!(p->fltkFlags & 8)) Fl::unlock(); do { if (!(p->fltkFlags & 8)) Fl::lock(); Fl::wait(0.02); j = (Fl::first_window() != (Fl_Window*) 0); if (!(p->fltkFlags & 8)) Fl::unlock(); } while (j && !p->end_of_perf); csound->Message(csound, Str("end of widget thread\n")); // IV - Jun 07 2005: exit if all windows are closed p->exit_now = -1; return (uintptr_t) 0; } } // extern "C" #endif // NO_FLTK_THREADS extern "C" { int CsoundYield_FLTK(CSOUND *csound); int FL_run(CSOUND *csound, FLRUN *p) { int *fltkFlags; WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); fltkFlags = getFLTKFlagsPtr(csound); (*fltkFlags) |= 32; #ifndef NO_FLTK_THREADS if (((*fltkFlags) & 260) ^ 4) { widgetsGlobals_t *pp; if (UNLIKELY(csound->QueryGlobalVariable(csound, "_widgets_globals") != NULL)) return csound->InitError(csound, Str("FLrun was already called")); if (UNLIKELY(csound->CreateGlobalVariable(csound, "_widgets_globals", sizeof(widgetsGlobals_t)) != 0)) csound->Die(csound, Str("FL_run: memory allocation failure")); pp = (widgetsGlobals_t*) csound->QueryGlobalVariable(csound, "_widgets_globals"); pp->fltkFlags = *fltkFlags; /* create thread lock */ pp->mutex_ = csound->Create_Mutex(0); /* register callback function to be called by sensevents() */ csound->RegisterSenseEventCallback(csound, (void (*)(CSOUND *, void *)) evt_callback, (void*) pp); if (!((*fltkFlags) & 256)) { pp->threadHandle = csound->CreateThread(fltkRun, (void*) csound); return OK; } } #endif // NO_FLTK_THREADS { int j; Fl_lock(csound); for (j = 0; j < (int) widgetGlobals->fl_windows.size(); j++) { widgetGlobals->fl_windows[j].panel->show(); } Fl_wait(csound, 0.0); Fl_unlock(csound); if (!((*fltkFlags) & 256)) csound->SetInternalYieldCallback(csound, CsoundYield_FLTK); } return OK; } int fl_update(CSOUND *csound, FLRUN *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); Fl_lock(csound); for (int j=0; j< (int) widgetGlobals->AddrSetValue.size()-1; j++) { ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[j]; Fl_Valuator *o = (Fl_Valuator *) v.WidgAddress; o->do_callback(o, v.opcode); } Fl_unlock(csound); return OK; } } // extern "C" //---------------------------------------------- static inline void displ(MYFLT val, MYFLT index, CSOUND *csound) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); if (index >= 0) { // display current value of valuator char valString[MAXNAME]; sprintf(valString, "%.5g", val); ((Fl_Output*) (widgetGlobals->AddrSetValue[(long) index]).WidgAddress)-> value(valString); } } static void fl_callbackButton1(Fl_Button* w, void *a) { FLBUTTON *p = (FLBUTTON *) a; *((FLBUTTON*) a)->kout = *p->ion; if (*p->args[0] >= 0) ButtonSched(p->h.insdshead->csound, p->args, p->INOCOUNT-8); } static void fl_callbackCloseButton(Fl_Button* w, void *a) { Fl_Window *p = (Fl_Window *) a; p->hide(); } static void fl_callbackExecButton(Fl_Button* w, void *a) { FLEXECBUTTON *p = (FLEXECBUTTON *)a; CSOUND *csound = p->csound; char *command = (char *)csound->Malloc(csound, strlen(p->commandString) + 1); #if defined(LINUX) || defined (MACOSX) pid_t pId = vfork(); if (pId == 0) { char *th; char *v[40]; int i = 0; strcpy(command, p->commandString); char *tok = csound->strtok_r(command,(char *) " ", &th); if(tok != NULL) { v[i++] = tok; while((tok = csound->strtok_r(NULL,(char *) " ", &th)) != NULL) { v[i++] = tok; } v[i] = NULL; execvp(v[0], v); } _exit(0); } else if (UNLIKELY(pId < 0)) { p->csound->Message(p->csound, Str("Error: Unable to fork process\n")); } csound->Free(csound, command); #elif defined(WIN32) { #undef strtok_r // undefine from pthread.h on Windows char *th; char *v[40]; int i = 0; strcpy(command, p->commandString); char *tok = csound->strtok_r(command,(char *) " ", &th); if(tok != NULL) { v[i++] = tok; while((tok = csound->strtok_r(NULL,(char *) " ", &th)) != NULL) { v[i++] = tok; } v[i] = NULL; csound->Free(csound, command); // Otherwise will lose space if (UNLIKELY(csound->RunCommand(v, 1)<0)) p->csound->Message(p->csound, Str("Error: Unable to fork process\n")); } } #endif } static void fl_callbackButton(Fl_Button* w, void *a) { FLBUTTON *p = (FLBUTTON *) a; *((FLBUTTON*) a)->kout = (w->value()) ? *p->ion : *p->ioff; if (*p->args[0] >= 0) ButtonSched(p->h.insdshead->csound, p->args, p->INOCOUNT-8); } static void fl_callbackButtonBank(Fl_Button* w, void *a) { FLBUTTONBANK *p = (FLBUTTONBANK *) a; *((FLBUTTONBANK*) a)->kout = (MYFLT) atoi(w->label()); if (*p->args[0] >= 0) ButtonSched(p->h.insdshead->csound, p->args, p->INOCOUNT-7); } static void fl_callbackCounter(Fl_Counter* w, void *a) { FLCOUNTER *p = (FLCOUNTER *) a; *((FLCOUNTER*) a)->kout = w->value(); if (*p->args[0] >= 0) ButtonSched(p->h.insdshead->csound, p->args, p->INOCOUNT-10); } static void fl_callbackLinearSlider(Fl_Valuator* w, void *a) { FLSLIDER *p = ((FLSLIDER*) a); displ(*p->kout = w->value(), *p->idisp, p->h.insdshead->csound); } static void fl_callbackExponentialSlider(Fl_Valuator* w, void *a) { FLSLIDER *p = ((FLSLIDER*) a); #if defined(sun) displ(*p->kout = p->min * ::pow ((double)p->base, w->value()), *p->idisp, p->h.insdshead->csound); #else displ(*p->kout = p->min * ::pow (p->base, w->value()), *p->idisp, p->h.insdshead->csound); #endif } static void fl_callbackInterpTableSlider(Fl_Valuator* w, void *a) { FLSLIDER *p = ((FLSLIDER*) a); MYFLT ndx = w->value() * (p->tablen-1); int index = (int) ndx; MYFLT v1 = p->table[index]; displ(*p->kout = p->min+ ( v1 + (p->table[index+1] - v1) * (ndx - index)) * (*p->imax - p->min), *p->idisp, p->h.insdshead->csound); } static void fl_callbackTableSlider(Fl_Valuator* w, void *a) { FLSLIDER *p = ((FLSLIDER*) a); displ(*p->kout = p->min+ p->table[(long) (w->value() * p->tablen)] * (*p->imax - p->min), *p->idisp, p->h.insdshead->csound); } static void fl_callbackLinearSliderBank(Fl_Valuator* w, void *a) { SLDBK_ELEMENT* p = (SLDBK_ELEMENT*) a; *p->out = w->value(); } static void fl_callbackExponentialSliderBank(Fl_Valuator* w, void *a) { SLDBK_ELEMENT* p = (SLDBK_ELEMENT*) a; #if defined(sun) *p->out = p->min * ::pow ((double)p->base, w->value()); #else *p->out = p->min * ::pow (p->base, w->value()); #endif } static void fl_callbackInterpTableSliderBank(Fl_Valuator* w, void *a) { SLDBK_ELEMENT *p = ((SLDBK_ELEMENT*) a); MYFLT ndx = w->value() * (p->tablen-1); int index = (int) ndx; MYFLT v1 = p->table[index]; *p->out = p->min + ( v1 + (p->table[index+1] - v1) * (ndx - index)) * (p->max - p->min); } static void fl_callbackTableSliderBank(Fl_Valuator* w, void *a) { SLDBK_ELEMENT *p = ((SLDBK_ELEMENT*) a); *p->out = p->min + p->table[(long)(w->value() * p->tablen)] * (p->max - p->min); } static void fl_callbackJoystick(Fl_Widget* w, void *a) { FLJOYSTICK *p = (FLJOYSTICK*) a; Fl_Positioner *j = (Fl_Positioner*) w; MYFLT val; int iexpx = (int) *p->iexpx, iexpy = (int) *p->iexpy; switch (iexpx) { case LIN_: val = j->xvalue(); break; case EXP_: #if defined(sun) val = *p->iminx * ::pow ((double)p->basex, j->xvalue()); #else val = *p->iminx * ::pow (p->basex, j->xvalue()); #endif break; default: if (iexpx > 0) { //interpolated MYFLT ndx = j->xvalue() * (p->tablenx-1); int index = (int) ndx; MYFLT v1 = p->tablex[index]; val = *p->iminx + ( v1 + (p->tablex[index+1] - v1) * (ndx - index)) * (*p->imaxx - *p->iminx); } else // non-interpolated val = *p->iminx+ p->tablex[(long) (j->xvalue() * p->tablenx)] * (*p->imaxx - *p->iminx); } displ(*p->koutx = val,*p->idispx, p->h.insdshead->csound); switch (iexpy) { case LIN_: val = j->yvalue(); break; case EXP_: #if defined(sun) val = *p->iminy * ::pow ((double)p->basey, j->yvalue()); #else val = *p->iminy * ::pow (p->basey, j->yvalue()); #endif break; default: if (iexpy > 0) { //interpolated MYFLT ndx = j->yvalue() * (p->tableny-1); long index = (long) ndx; MYFLT v1 = p->tabley[index]; val = *p->iminy + ( v1 + (p->tabley[index+1] - v1) * (ndx - index)) * (*p->imaxy - *p->iminy); } else { // non-interpolated long index = (long) (j->yvalue()* p->tableny); val = *p->iminy+ p->tabley[index] * (*p->imaxy - *p->iminy); } } displ(*p->kouty = val, *p->idispy, p->h.insdshead->csound); } static void fl_callbackLinearRoller(Fl_Valuator* w, void *a) { FLROLLER *p = ((FLROLLER*) a); displ(*p->kout = w->value(),*p->idisp, p->h.insdshead->csound); } static void fl_callbackExponentialRoller(Fl_Valuator* w, void *a) { FLROLLER *p = ((FLROLLER*) a); #if defined(sun) displ(*p->kout = ((FLROLLER*) a)->min * ::pow ((double)p->base, w->value()), *p->idisp, p->h.insdshead->csound); #else displ(*p->kout = ((FLROLLER*) a)->min * ::pow (p->base, w->value()), *p->idisp, p->h.insdshead->csound); #endif } static void fl_callbackInterpTableRoller(Fl_Valuator* w, void *a) { FLROLLER *p = ((FLROLLER*) a); MYFLT ndx = w->value() * (p->tablen-1); int index = (int) ndx; MYFLT v1 = p->table[index]; displ(*p->kout = p->min+ ( v1 + (p->table[index+1] - v1) * (ndx - index)) * (*p->imax - p->min), *p->idisp, p->h.insdshead->csound); } static void fl_callbackTableRoller(Fl_Valuator* w, void *a) { FLROLLER *p = ((FLROLLER*) a); displ(*p->kout = p->min+ p->table[(long) (w->value() * p->tablen)] * (*p->imax - p->min), *p->idisp, p->h.insdshead->csound); } static void fl_callbackLinearKnob(Fl_Valuator* w, void *a) { FLKNOB *p = ((FLKNOB*) a); displ( *p->kout = w->value(), *p->idisp, p->h.insdshead->csound); } static void fl_callbackExponentialKnob(Fl_Valuator* w, void *a) { FLKNOB *p = ((FLKNOB*) a); #if defined(sun) displ(*p->kout = ((FLKNOB*) a)->min * ::pow ((double)p->base, w->value()), *p->idisp, p->h.insdshead->csound); #else displ(*p->kout = ((FLKNOB*) a)->min * ::pow (p->base, w->value()), *p->idisp, p->h.insdshead->csound); #endif } static void fl_callbackInterpTableKnob(Fl_Valuator* w, void *a) { FLKNOB *p = ((FLKNOB*) a); MYFLT ndx = w->value() * (p->tablen-1); int index = (int) ndx; MYFLT v1 = p->table[index]; displ(*p->kout = p->min+ ( v1 + (p->table[index+1] - v1) * (ndx - index)) * (*p->imax - p->min), *p->idisp, p->h.insdshead->csound); } static void fl_callbackTableKnob(Fl_Valuator* w, void *a) { FLKNOB *p = ((FLKNOB*) a); displ(*p->kout = p->min+ p->table[(long) (w->value() * p->tablen)] * (*p->imax - p->min), *p->idisp, p->h.insdshead->csound); } static void fl_callbackLinearValueInput(Fl_Valuator* w, void *a) { *((FLTEXT*) a)->kout = w->value(); } //----------- static int rand_31_i(CSOUND *csound, int maxVal) { int seed = csound->GetRandSeed(csound,2); double x = (double) (csound->Rand31(&seed) - 1); return (int) (x * (double) (maxVal + 1) / 2147483646.0); } static void widget_attributes(CSOUND *csound, Fl_Widget *o) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); if (widgetGlobals->FLtext_size == -2 ) { widgetGlobals->FLtext_size = -1; widgetGlobals->FLtext_color= -1; widgetGlobals->FLtext_font = -1; widgetGlobals->FLtext_align= -1; widgetGlobals->FLcolor = -1; } if (widgetGlobals->FLtext_size > 0) // if > 0 assign it, else skip, leaving default o->labelsize(widgetGlobals->FLtext_size); switch ((int) widgetGlobals->FLtext_color) { case -2: // random color o->labelcolor(fl_rgb_color(rand_31_i(csound, 255), rand_31_i(csound, 255), rand_31_i(csound, 255))); break; case -1: // if FLtext_color is == -1, color assignment is skipped, // leaving default color break; default: o->labelcolor(widgetGlobals->FLtext_color); break; } if (widgetGlobals->FLtext_font> 0) { Fl_Font font; if (widgetGlobals->FLtext_font<0 || widgetGlobals->FLtext_font>16) font = FL_HELVETICA; else font = FONT_TABLE[widgetGlobals->FLtext_font]; // switch (FLtext_font) { // case 1: font = FL_HELVETICA; break; // case 2: font = FL_HELVETICA_BOLD; break; // case 3: font = FL_HELVETICA_ITALIC; break; // case 4: font = FL_HELVETICA_BOLD_ITALIC; break; // case 5: font = FL_COURIER; break; // case 6: font = FL_COURIER_BOLD; break; // case 7: font = FL_COURIER_ITALIC; break; // case 8: font = FL_COURIER_BOLD_ITALIC; break; // case 9: font = FL_TIMES; break; // case 10: font = FL_TIMES_BOLD; break; // case 11: font = FL_TIMES_ITALIC; break; // case 12: font = FL_TIMES_BOLD_ITALIC; break; // case 13: font = FL_SYMBOL; break; // case 14: font = FL_SCREEN; break; // case 15: font = FL_SCREEN_BOLD; break; // case 16: font = FL_ZAPF_DINGBATS; break; // default: font = FL_HELVETICA; break; // } o->labelfont(font); } if (widgetGlobals->FLtext_align > 0) { Fl_Align type; if (widgetGlobals->FLtext_align<0 || widgetGlobals->FLtext_align>9) type = FL_ALIGN_BOTTOM; else type = ALIGN_TABLE[widgetGlobals->FLtext_align]; // switch (widgetGlobals->FLtext_align) { // case 1: type = FL_ALIGN_CENTER; break; // case 2: type = FL_ALIGN_TOP; break; // case 3: type = FL_ALIGN_BOTTOM; break; // case 4: type = FL_ALIGN_LEFT; break; // case 5: type = FL_ALIGN_RIGHT; break; // case 6: type = FL_ALIGN_TOP_LEFT; break; // case 7: type = FL_ALIGN_TOP_RIGHT; break; // case 8: type = FL_ALIGN_BOTTOM_LEFT; break; // case 9: type = FL_ALIGN_BOTTOM_RIGHT; break; // case -1: // What type is this? // default: type = FL_ALIGN_BOTTOM; break; // } o->align(type); } switch ((int) widgetGlobals->FLcolor) { // random color case -2: o->color(FL_GRAY, fl_rgb_color(rand_31_i(csound, 255), rand_31_i(csound, 255), rand_31_i(csound, 255))); break; case -1: // if FLcolor is == -1, color assignment is skipped, // leaving widget default color break; default: o->color(widgetGlobals->FLcolor, widgetGlobals->FLcolor2); break; } } //----------- extern "C" { // static int FLkeyb(CSOUND *csound, FLKEYB *p) // { // (void) csound; // (void) p; // return OK; // } //----------- void flpanel_cb(Fl_Widget *,void *) { //suppresses the close button } static int StartPanel(CSOUND *csound, FLPANEL *p) { char *panelName; panelName = p->name->data; WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); *(getFLTKFlagsPtr(csound)) |= 32; int x = (int) *p->ix, y = (int) *p->iy; int width = (int) *p->iwidth, height = (int) *p->iheight; if (width < 0) width = 400; // default if (height < 0) height = 300; Fl_Boxtype borderType; int iborder = (int) *p->border; if (iborder<0 || iborder>7) borderType = FL_FLAT_BOX; else borderType = BOX_TABLE[iborder]; // switch( (int) *p->border ) { // case 0: borderType = FL_FLAT_BOX; break; // case 1: borderType = FL_DOWN_BOX; break; // case 2: borderType = FL_UP_BOX; break; // case 3: borderType = FL_ENGRAVED_BOX; break; // case 4: borderType = FL_EMBOSSED_BOX; break; // case 5: borderType = FL_BORDER_BOX; break; // case 6: borderType = FL_THIN_DOWN_BOX; break; // case 7: borderType = FL_THIN_UP_BOX; break; // default: borderType = FL_FLAT_BOX; // } Fl_Window *o; if (*(p->ikbdsense) == MYFLT(0.0)) { if (x < 0) o = new Fl_Window(width, height, panelName); else o = new Fl_Window(x, y, width, height, panelName); } else if (x < 0) o = new CsoundFLWindow(csound, width, height, panelName); else o = new CsoundFLWindow(csound, x, y, width, height, panelName); widget_attributes(csound, o); o->box(borderType); o->resizable(o); if (*p->iclose != 0) o->callback(flpanel_cb); widget_attributes(csound, o); ADDR_STACK adrstk(&p->h, (void *) o, widgetGlobals->stack_count); widgetGlobals->AddrStack.push_back(adrstk); PANELS panel(o, (widgetGlobals->stack_count > 0) ? 1 : 0); widgetGlobals->fl_windows.push_back(panel); widgetGlobals->stack_count++; return OK; } static int EndPanel(CSOUND *csound, FLPANELEND *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); widgetGlobals->stack_count--; ADDR_STACK adrstk = widgetGlobals->AddrStack.back(); if (UNLIKELY(adrstk.h->optext->t.opcod && strcmp( adrstk.h->optext->t.opcod, "FLpanel"))) return csound->InitError(csound, Str("FLpanel_end: invalid stack pointer: " "verify its placement")); if (UNLIKELY(adrstk.count != widgetGlobals->stack_count)) return csound->InitError(csound, Str("FLpanel_end: invalid stack count: " "verify FLpanel/FLpanel_end count and" " placement")); ((Fl_Window*) adrstk.WidgAddress)->end(); widgetGlobals->AddrStack.pop_back(); return OK; } //----------- static int StartScroll(CSOUND *csound, FLSCROLL *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); Fl_Scroll *o = new Fl_Scroll ((int) *p->ix, (int) *p->iy, (int) *p->iwidth, (int) *p->iheight); ADDR_STACK adrstk(&p->h,o,widgetGlobals->stack_count); widgetGlobals->AddrStack.push_back(adrstk); widgetGlobals->stack_count++; return OK; } static int EndScroll(CSOUND *csound, FLSCROLLEND *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); widgetGlobals->stack_count--; ADDR_STACK adrstk = widgetGlobals->AddrStack.back(); if (UNLIKELY(strcmp( adrstk.h->optext->t.opcod, "FLscroll"))) return csound->InitError(csound, Str("FLscroll_end: invalid stack pointer: " "verify its placement")); if (UNLIKELY(adrstk.count != widgetGlobals->stack_count)) return csound->InitError(csound, Str("FLscroll_end: invalid stack count: " "verify FLscroll/FLscroll_end count " "and placement")); ((Fl_Scroll*) adrstk.WidgAddress)->end(); widgetGlobals->AddrStack.pop_back(); return OK; } //----------- static int StartTabs(CSOUND *csound, FLTABS *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); Fl_Tabs *o = new Fl_Tabs ((int) *p->ix, (int) *p->iy, (int) *p->iwidth, (int) *p->iheight); widget_attributes(csound, o); // o->box(FL_PLASTIC_UP_BOX); ADDR_STACK adrstk(&p->h,o,widgetGlobals->stack_count); widgetGlobals->AddrStack.push_back(adrstk); widgetGlobals->stack_count++; return OK; } static int EndTabs(CSOUND *csound, FLTABSEND *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); widgetGlobals->stack_count--; ADDR_STACK adrstk = widgetGlobals->AddrStack.back(); if (UNLIKELY(strcmp( adrstk.h->optext->t.opcod, "FLtabs"))) return csound->InitError(csound, Str("FLscroll_end: invalid stack pointer: " "verify its placement")); if (UNLIKELY(adrstk.count != widgetGlobals->stack_count)) return csound->InitError(csound, Str("FLtabs_end: invalid stack count: " "verify FLtabs/FLtabs_end count and " "placement")); ((Fl_Scroll*) adrstk.WidgAddress)->end(); widgetGlobals->AddrStack.pop_back(); return OK; } //----------- static int StartGroup(CSOUND *csound, FLGROUP *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); char *Name = p->name->data; Fl_Group *o = new Fl_Group ((int) *p->ix, (int) *p->iy, (int) *p->iwidth, (int) *p->iheight,Name); widget_attributes(csound, o); Fl_Boxtype borderType; int iborder = (int)*p->border; if (iborder<0 || iborder>7) borderType = FL_FLAT_BOX; else borderType = BOX_TABLE[iborder]; // switch((int)*p->border ) { // case 0: borderType = FL_FLAT_BOX; break; // case 1: borderType = FL_DOWN_BOX; break; // case 2: borderType = FL_UP_BOX; break; // case 3: borderType = FL_ENGRAVED_BOX; break; // case 4: borderType = FL_EMBOSSED_BOX; break; // case 5: borderType = FL_BORDER_BOX; break; // case 6: borderType = FL_THIN_DOWN_BOX; break; // case 7: borderType = FL_THIN_UP_BOX; break; // default: borderType = FL_FLAT_BOX; // } o->box(borderType); widget_attributes(csound, o); ADDR_STACK adrstk(&p->h,o,widgetGlobals->stack_count); widgetGlobals->AddrStack.push_back(adrstk); widgetGlobals->stack_count++; return OK; } static int EndGroup(CSOUND *csound, FLGROUPEND *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); widgetGlobals->stack_count--; ADDR_STACK adrstk = widgetGlobals->AddrStack.back(); if (UNLIKELY(strcmp( adrstk.h->optext->t.opcod, "FLgroup"))) return csound->InitError(csound, Str("FLgroup_end: invalid stack pointer: " "verify its placement")); if (UNLIKELY(adrstk.count != widgetGlobals->stack_count)) return csound->InitError(csound, Str("FLgroup_end: invalid stack count: " "verify FLgroup/FLgroup_end count and" " placement")); ((Fl_Scroll*) adrstk.WidgAddress)->end(); widgetGlobals->AddrStack.pop_back(); return OK; } //----------- static int StartPack(CSOUND *csound, FLPACK *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); Fl_Pack *o = new Fl_Pack ((int) *p->ix, (int) *p->iy, (int) *p->iwidth, (int) *p->iheight); Fl_Boxtype borderType = FL_FLAT_BOX; int iborder = (int)*p->iborder; // fl_window->resizable(o); if (!((iborder<0 || iborder>7))) borderType = BOX_TABLE[iborder]; o->box(borderType); // JPff added March 2012 o->type((int)*p->itype); o->spacing((int)*p->ispace); ADDR_STACK adrstk(&p->h,o,widgetGlobals->stack_count); widgetGlobals->AddrStack.push_back(adrstk); widgetGlobals->stack_count++; return OK; } static int EndPack(CSOUND *csound, FLSCROLLEND *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); widgetGlobals->stack_count--; ADDR_STACK adrstk = widgetGlobals->AddrStack.back(); if (UNLIKELY(strcmp( adrstk.h->optext->t.opcod, "FLpack"))) return csound->InitError(csound, Str("FLpack_end: invalid stack pointer: " "verify its placement")); if (UNLIKELY(adrstk.count != widgetGlobals->stack_count)) return csound->InitError(csound, Str("FLpack_end: invalid stack count: " "verify FLpack/FLpack_end count and " "placement")); ((Fl_Pack*) adrstk.WidgAddress)->end(); widgetGlobals->AddrStack.pop_back(); return OK; } //----------- static int fl_widget_color(CSOUND *csound, FLWIDGCOL *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); if (*p->red1 < 0) { // reset colors to default widgetGlobals->FLcolor = (int) *p->red1; //when called without arguments widgetGlobals->FLcolor2 =(int) *p->red1; } else { widgetGlobals->FLcolor = fl_rgb_color((int) *p->red1, (int) *p->green1, (int) *p->blue1); widgetGlobals->FLcolor2 = fl_rgb_color((int) *p->red2, (int) *p->green2, (int) *p->blue2); } return OK; } static int fl_widget_color2(CSOUND *csound, FLWIDGCOL2 *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); if (*p->red < 0) { // reset colors to default widgetGlobals->FLcolor2 =(int) *p->red; } else { widgetGlobals->FLcolor2 = fl_rgb_color((int) *p->red, (int) *p->green, (int) *p->blue); } return OK; } static int fl_widget_label(CSOUND *csound, FLWIDGLABEL *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); if (*p->size <= 0) { // reset settings to default widgetGlobals->FLtext_size = 0; //when called without arguments widgetGlobals->FLtext_font = -1; widgetGlobals->FLtext_align = 0; widgetGlobals->FLtext_color = -1; } else { widgetGlobals->FLtext_size = (int) *p->size; if (*p->font > -1) widgetGlobals->FLtext_font = (int) *p->font; if (*p->align > 0) widgetGlobals->FLtext_align = (int) *p->align; if (*p->red > -1 && *p->green > -1 && *p->blue > -1) { widgetGlobals->FLtext_color = fl_rgb_color((int) *p->red, (int) *p->green, (int) *p->blue); } } return OK; } } // extern "C" // ----------- static int fl_getWidgetTypeFromOpcodeName(CSOUND *csound, void *p) { const char *opname = csound->GetOpcodeName(p); if (strcmp(opname, "FLbutton") == 0) return 1; if (strcmp(opname, "FLbutBank") == 0) return 2; if (strcmp(opname, "FLjoy") == 0) return 3; if (strcmp(opname, "FLvalue") == 0) return 4; if (strcmp(opname, "FLbox") != 0) return 0; csound->Warning(csound, Str("System error: value() method called from " "non-valuator object")); return -1; } static void fl_setWidgetValue_(CSOUND *csound, ADDR_SET_VALUE &v, int widgetType, MYFLT val, MYFLT log_base) { Fl_Widget *o = (Fl_Widget *) v.WidgAddress; void *p = v.opcode; bool fltkLockingIsEnabled; if ((!widgetType || widgetType > 2) && (v.exponential == LIN_ || v.exponential == EXP_)) { if (val < v.min) val = v.min; else if (val > v.max) val = v.max; if (v.exponential == EXP_) val = (MYFLT) (log(val / v.min) / log_base); } fltkLockingIsEnabled = ((getFLTKFlags(csound) & 8) == 0); if (fltkLockingIsEnabled) Fl_lock(csound); switch (widgetType) { case 0: // valuator ((Fl_Valuator *) o)->value(val); break; case 1: // FLbutton if (val == *(((FLBUTTON *) v.opcode)->ion)) ((Fl_Button *) o)->value(1); else if (val == *(((FLBUTTON *) v.opcode)->ioff)) ((Fl_Button *) o)->value(0); break; case 2: // FLbutBank set_butbank_value((Fl_Group *) o, val); break; case 3: // FLjoy { static int flag = 0; // FLsetVal always requires two adjacent calls when setting FLjoy if (!flag) { ((Fl_Positioner *) o)->xvalue(val); flag = 1; } else { ((Fl_Positioner *) o)->yvalue(val); flag = 0; } } break; default: // invalid if (fltkLockingIsEnabled) Fl_unlock(csound); return; } o->do_callback(o, p); if (fltkLockingIsEnabled) Fl_unlock(csound); } extern "C" { static int fl_setWidgetValuei(CSOUND *csound, FL_SET_WIDGET_VALUE_I *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); MYFLT log_base = MYFLT(1.0); ADDR_SET_VALUE &v = widgetGlobals->AddrSetValue[(int) *p->ihandle]; int widgetType; widgetType = fl_getWidgetTypeFromOpcodeName(csound, v.opcode); if (UNLIKELY(widgetType == 4)) { csound->InitError(csound, Str("FLvalue cannot be set by FLsetVal.\n")); return NOTOK; } if (widgetType < 0) return OK; if (!widgetType || widgetType > 2) { switch (v.exponential) { case LIN_: // linear break; case EXP_: // exponential #if defined(sun) log_base = (MYFLT) log(::pow(v.max / (double)v.min, 1.0 / (v.max - v.min))); #else log_base = (MYFLT) log(::pow(v.max / v.min, 1.0 / (v.max - v.min))); #endif break; default: csound->Warning(csound, Str("(fl_setWidgetValuei): " "not fully implemented yet; exp=%d"), v.exponential); } } fl_setWidgetValue_(csound, v, widgetType, *(p->ivalue), log_base); return OK; } static int fl_setWidgetValue_set(CSOUND *csound, FL_SET_WIDGET_VALUE *p) { p->handle = (int) *(p->ihandle); WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); MYFLT log_base = MYFLT(1.0); ADDR_SET_VALUE &v = widgetGlobals->AddrSetValue[p->handle]; int widgetType; widgetType = fl_getWidgetTypeFromOpcodeName(csound, v.opcode); if (UNLIKELY(widgetType == 4)) { csound->InitError(csound, Str("FLvalue cannot be set by FLsetVal\n")); return NOTOK; } if (widgetType < 0) return OK; if (!widgetType || widgetType > 2) { switch (v.exponential) { case LIN_: // linear break; case EXP_: // exponential #if defined(sun) log_base = (MYFLT) log(::pow(v.max / (double)v.min, 1.0 / (v.max - v.min))); #else log_base = (MYFLT) log(::pow(v.max / v.min, 1.0 / (v.max - v.min))); #endif break; default: csound->Warning(csound, Str("(fl_setWidgetValue_set): " "not fully implemented yet; exp=%d"), v.exponential); } } p->widgetType = widgetType; p->log_base = log_base; return OK; } static int fl_setWidgetValue(CSOUND *csound, FL_SET_WIDGET_VALUE *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); if (*p->ktrig != MYFLT(0.0)) fl_setWidgetValue_(csound, widgetGlobals->AddrSetValue[p->handle], p->widgetType, *(p->kvalue), p->log_base); return OK; } //----------- //----------- static int fl_setColor1(CSOUND *csound, FL_SET_COLOR *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle]; Fl_Widget *o = (Fl_Widget *) v.WidgAddress; int color = fl_rgb_color((int) *p->red, (int) *p->green, (int) *p->blue); o->color(color); return OK; } static int fl_setColor2(CSOUND *csound, FL_SET_COLOR *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle]; Fl_Widget *o = (Fl_Widget *) v.WidgAddress; int color = fl_rgb_color((int) *p->red, (int) *p->green, (int) *p->blue); o->selection_color(color); return OK; } static int fl_setTextColor(CSOUND *csound, FL_SET_COLOR *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle]; Fl_Widget *o = (Fl_Widget *) v.WidgAddress; int color = fl_rgb_color((int) *p->red, (int) *p->green, (int) *p->blue); o->labelcolor(color); return OK; } static int fl_setTextSize(CSOUND *csound, FL_SET_TEXTSIZE *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle]; Fl_Widget *o = (Fl_Widget *) v.WidgAddress; o->labelsize((uchar) *p->ivalue); return OK; } static int fl_setFont(CSOUND *csound, FL_SET_FONT *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle]; Fl_Widget *o = (Fl_Widget *) v.WidgAddress; Fl_Font font; int ifnt = (int) *p->itype; if (ifnt<0 || ifnt>16) font = FL_HELVETICA; else font = FONT_TABLE[ifnt]; // switch ((int) *p->itype) { // case 1: font = FL_HELVETICA; break; // case 2: font = FL_HELVETICA_BOLD; break; // case 3: font = FL_HELVETICA_ITALIC; break; // case 4: font = FL_HELVETICA_BOLD_ITALIC; break; // case 5: font = FL_COURIER; break; // case 6: font = FL_COURIER_BOLD; break; // case 7: font = FL_COURIER_ITALIC; break; // case 8: font = FL_COURIER_BOLD_ITALIC; break; // case 9: font = FL_TIMES; break; // case 10: font = FL_TIMES_BOLD; break; // case 11: font = FL_TIMES_ITALIC; break; // case 12: font = FL_TIMES_BOLD_ITALIC; break; // case 13: font = FL_SYMBOL; break; // case 14: font = FL_SCREEN; break; // case 15: font = FL_SCREEN_BOLD; break; // case 16: font = FL_ZAPF_DINGBATS; break; // default: font = FL_SCREEN; // } o->labelfont(font); return OK; } static int fl_setTextType(CSOUND *csound, FL_SET_FONT *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle]; Fl_Widget *o = (Fl_Widget *) v.WidgAddress; Fl_Labeltype type; switch ((int) *p->itype) { case 0: type = FL_NORMAL_LABEL; break; case 1: type = FL_NO_LABEL; break; case 2: type = FL_SYMBOL_LABEL; break; case 3: type = FL_SHADOW_LABEL; break; case 4: type = FL_ENGRAVED_LABEL; break; case 5: type = FL_EMBOSSED_LABEL; break; /* case 6: type = _FL_BITMAP_LABEL; break; case 7: type = _FL_PIXMAP_LABEL; break; case 8: type = _FL_IMAGE_LABEL; break; case 9: type = _FL_MULTI_LABEL; break; */ case 10: type = FL_FREE_LABELTYPE; break; default: type = FL_NORMAL_LABEL; } o->labeltype(type); o->window()->redraw(); return OK; } static int fl_box_(CSOUND *csound, FL_BOX *p, char *text) { //char *text = p->itext->data; Fl_Box *o = new Fl_Box((int)*p->ix, (int)*p->iy, (int)*p->iwidth, (int)*p->iheight, text); widget_attributes(csound, o); Fl_Boxtype type; int itype = (int) *p->itype; if (itype<0 || itype>19) type = FL_FLAT_BOX; else type = BOX_TABLE[itype]; // switch ((int) *p->itype) { // case 1: type = FL_FLAT_BOX; break; // case 2: type = FL_UP_BOX; break; // case 3: type = FL_DOWN_BOX; break; // case 4: type = FL_THIN_UP_BOX; break; // case 5: type = FL_THIN_DOWN_BOX; break; // case 6: type = FL_ENGRAVED_BOX; break; // case 7: type = FL_EMBOSSED_BOX; break; // case 8: type = FL_BORDER_BOX; break; // case 9: type = _FL_SHADOW_BOX; break; // case 10: type = _FL_ROUNDED_BOX; break; // case 11: type = _FL_RSHADOW_BOX; break; // case 12: type = _FL_RFLAT_BOX; break; // case 13: type = _FL_ROUND_UP_BOX; break; // case 14: type = _FL_ROUND_DOWN_BOX; break; // case 15: type = _FL_DIAMOND_UP_BOX; break; // case 16: type = _FL_DIAMOND_DOWN_BOX; break; // case 17: type = _FL_OVAL_BOX; break; // case 18: type = _FL_OSHADOW_BOX; break; // case 19: type = _FL_OFLAT_BOX; break; // default: type = FL_FLAT_BOX; // } o->box(type); Fl_Font font; int ifnt = (int) *p->ifont; if (ifnt<0 || ifnt>16) font = FL_HELVETICA; else font = FONT_TABLE[ifnt]; // switch ((int) *p->ifont) { // case 1: font = FL_HELVETICA; break; // case 2: font = FL_HELVETICA_BOLD; break; // case 3: font = FL_HELVETICA_ITALIC; break; // case 4: font = FL_HELVETICA_BOLD_ITALIC; break; // case 5: font = FL_COURIER; break; // case 6: font = FL_COURIER_BOLD; break; // case 7: font = FL_COURIER_ITALIC; break; // case 8: font = FL_COURIER_BOLD_ITALIC; break; // case 9: font = FL_TIMES; break; // case 10: font = FL_TIMES_BOLD; break; // case 11: font = FL_TIMES_ITALIC; break; // case 12: font = FL_TIMES_BOLD_ITALIC; break; // case 13: font = FL_SYMBOL; break; // case 14: font = FL_SCREEN; break; // case 15: font = FL_SCREEN_BOLD; break; // case 16: font = FL_ZAPF_DINGBATS; break; // default: font = FL_HELVETICA; // } o->labelfont(font); o->labelsize((unsigned char)*p->isize); o->align(FL_ALIGN_WRAP); WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(0, 0, 0, (void *)o, (void *)p, widgetGlobals->currentSnapGroup)); *p->ihandle = widgetGlobals->AddrSetValue.size()-1; return OK; } static int fl_box_s(CSOUND *csound, FL_BOX *p) { return fl_box_(csound, p, p->itext->data); } static int fl_box_i(CSOUND *csound, FL_BOX *p) { int i = (int)*((MYFLT*)p->itext); char* text; if (i<0 || i>csound->GetStrsmax(csound)) text = (char *) "???"; else if ((text=csound->GetStrsets(csound,i))==NULL) text = (char *) "???"; return fl_box_(csound, p, text); } static int fl_setText(CSOUND *csound, FL_SET_TEXT *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); char *text = p->itext->data; ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle]; Fl_Widget *o = (Fl_Widget *) v.WidgAddress; o->label(text); return OK; } static int fl_setTexti(CSOUND *csound, FL_SET_TEXTi *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); int i = (int)(*p->ndx); char *text ; ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle]; Fl_Widget *o = (Fl_Widget *) v.WidgAddress; if (i<0 || i>csound->GetStrsmax(csound)) text = (char *) "???"; else if ((text=csound->GetStrsets(csound,i))==NULL) text = (char *) "???"; o->label(text); return OK; } static int fl_setSize(CSOUND *csound, FL_SET_SIZE *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle]; Fl_Widget *o = (Fl_Widget *) v.WidgAddress; o->size((short) *p->iwidth, (short) *p->iheight); return OK; } static int fl_setPosition(CSOUND *csound, FL_SET_POSITION *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle]; Fl_Widget *o = (Fl_Widget *) v.WidgAddress; o->position((short) *p->ix, (short) *p->iy); return OK; } static int fl_hide(CSOUND *csound, FL_WIDHIDE *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); Fl_lock(csound); ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle]; Fl_Widget *o = (Fl_Widget *) v.WidgAddress; o->hide(); Fl_unlock(csound); return OK; } static int fl_show(CSOUND *csound, FL_WIDSHOW *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); Fl_lock(csound); ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle]; Fl_Widget *o = (Fl_Widget *) v.WidgAddress; o->show(); Fl_unlock(csound); return OK; } static int fl_setBox(CSOUND *csound, FL_SETBOX *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle]; Fl_Widget *o = (Fl_Widget *) v.WidgAddress; Fl_Boxtype type; int itype = (int) *p->itype; if (itype<0||itype>19) type = FL_FLAT_BOX; else type = BOX_TABLE[itype]; // switch ((int) *p->itype) { // case 1: type = FL_FLAT_BOX; break; // case 2: type = FL_UP_BOX; break; // case 3: type = FL_DOWN_BOX; break; // case 4: type = FL_THIN_UP_BOX; break; // case 5: type = FL_THIN_DOWN_BOX; break; // case 6: type = FL_ENGRAVED_BOX; break; // case 7: type = FL_EMBOSSED_BOX; break; // case 8: type = FL_BORDER_BOX; break; // case 9: type = FL_SHADOW_BOX; break; // case 10: type = FL_ROUNDED_BOX; break; // case 11: type = FL_RSHADOW_BOX; break; // case 12: type = FL_RFLAT_BOX; break; // case 13: type = FL_ROUND_UP_BOX; break; // case 14: type = FL_ROUND_DOWN_BOX; break; // case 15: type = FL_DIAMOND_UP_BOX; break; // case 16: type = FL_DIAMOND_DOWN_BOX; break; // case 17: type = FL_OVAL_BOX; break; // case 18: type = FL_OSHADOW_BOX; break; // case 19: type = FL_OFLAT_BOX; break; // default: type = FL_FLAT_BOX; // } o->box(type); return OK; } static int fl_align(CSOUND *csound, FL_TALIGN *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle]; Fl_Widget *o = (Fl_Widget *) v.WidgAddress; Fl_Align type; int itype= (int) *p->itype; if (itype<0 || itype>9) type = FL_ALIGN_BOTTOM; else type = ALIGN_TABLE[itype]; // switch ((int) *p->itype) { // case 1: type = FL_ALIGN_CENTER; break; // case 2: type = FL_ALIGN_TOP; break; // case 3: type = FL_ALIGN_BOTTOM; break; // case 4: type = FL_ALIGN_LEFT; break; // case 5: type = FL_ALIGN_RIGHT; break; // case 6: type = FL_ALIGN_TOP_LEFT; break; // case 7: type = FL_ALIGN_TOP_RIGHT; break; // case 8: type = FL_ALIGN_BOTTOM_LEFT; break; // case 9: type = FL_ALIGN_BOTTOM_RIGHT; break; // default: type = FL_ALIGN_BOTTOM; // } o->align(type); return OK; } //----------- //----------- static int fl_value(CSOUND *csound, FLVALUE *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); char *controlName = p->name->data; int ix, iy, iwidth, iheight; if (*p->ix<0) ix = widgetGlobals->FL_ix; else widgetGlobals->FL_ix = ix = (int) *p->ix; if (*p->iy<0) iy = widgetGlobals->FL_iy; else widgetGlobals->FL_iy = iy = (int) *p->iy; if (*p->iwidth<0) iwidth = widgetGlobals->FLvalue_iwidth; else widgetGlobals->FLvalue_iwidth = iwidth = (int) *p->iwidth; if (*p->iheight<0) iheight = widgetGlobals->FLroller_iheight; else widgetGlobals->FLroller_iheight = iheight = (int) *p->iheight; Fl_Output *o = new Fl_Output(ix, iy, iwidth, iheight,controlName); o->align(FL_ALIGN_BOTTOM | FL_ALIGN_WRAP); if (widgetGlobals->FLcolor < 0 ) o->color(FL_GRAY ); else o->color(widgetGlobals->FLcolor, widgetGlobals->FLcolor2); widget_attributes(csound, o); //AddrValue.push_back((void *) o); widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(0, 0, 0, (void *) o, (void *) p, widgetGlobals->currentSnapGroup)); //*p->ihandle = AddrValue.size()-1; *p->ihandle = widgetGlobals->AddrSetValue.size()-1; return OK; } //----------- static int fl_slider(CSOUND *csound, FLSLIDER *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); char *controlName = p->name->data; int ix,iy,iwidth, iheight,itype, iexp; bool plastic = false; if (*p->iy < 0) { iy = widgetGlobals->FL_iy; widgetGlobals->FL_iy += widgetGlobals->FLcontrol_iheight + 5; } else { iy = (int) *p->iy; widgetGlobals->FL_iy = iy + widgetGlobals->FLcontrol_iheight + 5; } if (*p->ix < 0) ix = widgetGlobals->FL_ix; // omitted options: set default else widgetGlobals->FL_ix = ix = (int) *p->ix; if (*p->iwidth < 0) iwidth = widgetGlobals->FLcontrol_iwidth; else widgetGlobals->FLcontrol_iwidth = iwidth = (int) *p->iwidth; if (*p->iheight < 0) iheight = widgetGlobals->FLcontrol_iheight; else widgetGlobals->FLcontrol_iheight = iheight = (int) *p->iheight; if (*p->itype < 1) itype = 1; else itype = (int) *p->itype; //if (*p->iexp == LIN_) iexp = LIN_; //else iexp = (int) *p->iexp; switch((int) *p->iexp) { case -1: iexp = EXP_; break; case 0: iexp = LIN_; break; default: iexp = (int) *p->iexp; } if (itype > 19) { plastic = true; itype = itype - 20; } if (UNLIKELY(itype > 10 && iexp == EXP_)) { csound->Warning(csound, Str("FLslider exponential, using non-labeled slider")); itype -= 10; } Fl_Slider *o; if (itype <= 10) o = new Fl_Slider(ix, iy, iwidth, iheight, controlName); else { o = new Fl_Value_Slider_Input(csound, ix, iy, iwidth, iheight, controlName); itype -=10; //o->labelsize(20); ((Fl_Value_Slider_Input*) o)->textboxsize(50); ((Fl_Value_Slider_Input*) o)->textsize(13); o->align(FL_ALIGN_BOTTOM | FL_ALIGN_WRAP); } switch (itype) { case 1: o->type(FL_HOR_FILL_SLIDER); break; case 2: o->type(FL_VERT_FILL_SLIDER); break; case 3: o->type(FL_HOR_SLIDER); break; case 4: o->type(FL_VERT_SLIDER); break; case 5: o->type(FL_HOR_NICE_SLIDER); o->box(FL_FLAT_BOX); break; case 6: o->type(FL_VERT_NICE_SLIDER); o->box(FL_FLAT_BOX); break; default: return csound->InitError(csound, Str("FLslider: invalid slider type")); } if (plastic) o->box(FL_PLASTIC_DOWN_BOX); widget_attributes(csound, o); MYFLT min = p->min = *p->imin, max = *p->imax, range; switch (iexp) { case LIN_: //linear o->range(min,max); o->callback((Fl_Callback*)fl_callbackLinearSlider,(void *) p); break; case EXP_ : //exponential if (UNLIKELY(min == 0 || max == 0)) return csound->InitError(csound, Str("FLslider: zero is illegal " "in exponential operations")); range = max - min; o->range(0,range); #if defined(sun) p->base = ::pow((max / (double)min), 1.0/(double)range); #else p->base = ::pow((max / min), 1.0/(double)range); #endif o->callback((Fl_Callback*)fl_callbackExponentialSlider,(void *) p); break; default: { FUNC *ftp; MYFLT fnum = abs(iexp); if ((ftp = csound->FTnp2Find(csound, &fnum)) != NULL) { p->table = ftp->ftable; p->tablen = ftp->flen; } else return NOTOK; o->range(0,0.99999999); if (iexp > 0) //interpolated o->callback((Fl_Callback*)fl_callbackInterpTableSlider,(void *) p); else // non-interpolated o->callback((Fl_Callback*)fl_callbackTableSlider,(void *) p); } } widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(iexp, *p->imin, *p->imax, (void *) o, (void*) p)); /*widgetGlobals->currentSnapGroup;*/ *p->ihandle = widgetGlobals->AddrSetValue.size()-1; return OK; } static int fl_slider_bank_(CSOUND *csound, FLSLIDERBANK *p, int istring) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); char s[MAXNAME]; bool plastic = false; if (istring) strncpy(s, ((STRINGDAT*) p->names)->data, MAXNAME-1); else if ((long) *p->names <= csound->GetStrsmax(csound) && csound->GetStrsets(csound,(long) *p->names)) { strncpy(s, csound->GetStrsets(csound,(long) *p->names), MAXNAME-1); } string tempname(s); stringstream sbuf; sbuf << tempname; int width = (int) *p->iwidth; if (width <=0) width = 100; Fl_Group* w = new Fl_Group((int)*p->ix, (int)*p->iy, width, (int)*p->inumsliders*10); FUNC *ftp; MYFLT *minmaxtable = NULL, *typetable = NULL, *outable, *exptable = NULL; MYFLT *zkstart; int zklast = csound->GetZakBounds(csound, &zkstart); if (*p->ioutable < 1) { if (LIKELY(zkstart != NULL && zklast > (long)(*p->inumsliders+*p->ioutablestart_ndx))) outable = zkstart + (long) *p->ioutablestart_ndx; else { return csound->InitError(csound, Str("invalid ZAK space allocation")); } } else { if (LIKELY((ftp = csound->FTnp2Find(csound, p->ioutable)) != NULL)) outable = ftp->ftable + (long) *p->ioutablestart_ndx; else return NOTOK; } if ((int) *p->iminmaxtable > 0) { if (LIKELY((ftp = csound->FTnp2Find(csound, p->iminmaxtable)) != NULL)) minmaxtable = ftp->ftable; else return NOTOK; } if ((int) *p->iexptable > 0) { if (LIKELY((ftp = csound->FTnp2Find(csound, p->iexptable)) != NULL)) exptable = ftp->ftable; else return NOTOK; } if ((int) *p->itypetable > 0) { if (LIKELY((ftp = csound->FTnp2Find(csound, p->itypetable)) != NULL)) typetable = ftp->ftable; else return NOTOK; } for (int j =0; j< *p->inumsliders; j++) { string stemp; if (tempname == " ") { char s[40]; sprintf(s, "%d", j); stemp = s; } else getline(sbuf, stemp, '@'); char *Name = new char[stemp.size()+2]; strcpy(Name,stemp.c_str()); widgetGlobals->allocatedStrings.push_back(Name); int x = (int) *p->ix, y = (int) *p->iy + j*10; Fl_Slider *o; int slider_type; if ((int) *p->itypetable <= 0) { // no slider type table if (*p->itypetable >= -7) // all sliders are of the same type slider_type = -((int) *p->itypetable); else if (*p->itypetable >= -27 && *p->itypetable < -20) { slider_type = -((int) *p->itypetable) - 20; plastic = true; } else // random type slider_type = rand_31_i(csound, 7) | 1; } else slider_type = (int) typetable[j]; if (slider_type > 20) { plastic = true; slider_type -= 20; } if (slider_type < 10) o = new Fl_Slider(x, y, width, 10, Name); else { o = new Fl_Value_Slider_Input(csound, x, y, width, 10, Name); slider_type -=10; ((Fl_Value_Slider_Input*) o)->textboxsize(50); ((Fl_Value_Slider_Input*) o)->textsize(13); } switch((int) slider_type) { //type case 1: o->type(FL_HOR_FILL_SLIDER); break; case 3: o->type(FL_HOR_SLIDER); break; case 5: o->type(FL_HOR_NICE_SLIDER); o->box(FL_FLAT_BOX); break; case 7: o->type(FL_HOR_NICE_SLIDER); o->box(FL_DOWN_BOX); break; default: o->type(FL_HOR_NICE_SLIDER); o->box(FL_FLAT_BOX); break; } if (plastic) o->box(FL_PLASTIC_DOWN_BOX); o->align(FL_ALIGN_LEFT); widget_attributes(csound, o); MYFLT min, max, range; if ((int) *p->iminmaxtable > 0) { min = minmaxtable[j*2]; max = minmaxtable[j*2+1]; } else { min = MYFLT(0.0); max = MYFLT(1.0); } int iexp; p->slider_data[j].min=min; p->slider_data[j].max=max; p->slider_data[j].out=&outable[j]; if ((int) *p->iexptable <=0) // no table, all sliders have the same behaviour iexp = (int) *p->iexptable; else iexp = (int) exptable[j]; switch (iexp) { case -1: iexp = EXP_; break; case 0: iexp = LIN_; break; } MYFLT val = 0; p->slider_data[j].exp = iexp; switch (iexp) { case LIN_: //linear o->range(min,max); o->callback((Fl_Callback*)fl_callbackLinearSliderBank, (void *) &(p->slider_data[j])); val = outable[j]; if (val > max) val = max; else if (val < min) val = min; break; case EXP_ : //exponential if (UNLIKELY(min == 0 || max == 0)) return csound->InitError(csound, Str("FLslidBnk: zero is illegal " "in exponential operations")); range = max - min; o->range(0,range); #if defined(sun) p->slider_data[j].base = ::pow((max / (double)min), 1.0/(double)range); #else p->slider_data[j].base = ::pow((max / min), 1.0/(double)range); #endif o->callback((Fl_Callback*)fl_callbackExponentialSliderBank, (void *) &(p->slider_data[j])); { val = outable[j]; MYFLT range = max-min; #if defined(sun) MYFLT base = ::pow(max / (double)min, 1.0/(double)range); #else MYFLT base = ::pow(max / min, 1.0/(double)range); #endif val = (log(val/min) / log(base)) ; } break; default: { FUNC *ftp; MYFLT fnum = abs(iexp); if ((ftp = csound->FTnp2Find(csound, &fnum)) != NULL) p->slider_data[j].table = ftp->ftable; else return NOTOK; p->slider_data[j].tablen = ftp->flen; o->range(0,0.99999999); if (iexp > 0) //interpolated o->callback((Fl_Callback*)fl_callbackInterpTableSliderBank, (void *) &(p->slider_data[j])); else // non-interpolated o->callback((Fl_Callback*)fl_callbackTableSliderBank, (void *) &(p->slider_data[j])); } } o->value(val); } w->resizable(w); if (*p->iwidth <=0 || *p->iheight <=0) {// default width and height int a,b; w->size( a= w->parent()->w() -50, b= w->parent()->h()); w->position(50, 0); } else { w->size( (int)*p->iwidth, (int)*p->iheight); w->position((int)*p->ix, (int)*p->iy); } w->end(); widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(LIN_, 0, 0, (void *) w, (void *) p, widgetGlobals->currentSnapGroup)); //*p->ihandle = widgetGlobals->AddrSetValue.size()-1; widgetGlobals->last_sldbnk = widgetGlobals->AddrSetValue.size()-1; //gab return OK; } static int fl_slider_bank(CSOUND *csound, FLSLIDERBANK *p){ return fl_slider_bank_(csound,p,0); } static int fl_slider_bank_S(CSOUND *csound, FLSLIDERBANK *p){ return fl_slider_bank_(csound,p,1); } static int fl_joystick(CSOUND *csound, FLJOYSTICK *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); char *Name = p->name->data; int ix,iy,iwidth, iheight, iexpx, iexpy; if (*p->ix < 0) ix = 10; // omitted options: set default else widgetGlobals->FL_ix = ix = (int) *p->ix; if (*p->iy < 0) iy = 10; // omitted options: set default else iy = (int) *p->iy; if (*p->iwidth < 0) iwidth = 130; else iwidth = (int) *p->iwidth; if (*p->iheight < 0) iheight = 130; else iheight = (int) *p->iheight; switch((int) *p->iexpx) { case -1: iexpx = EXP_; break; case 0: iexpx = LIN_; break; default: iexpx = (int) *p->iexpx; } switch((int) *p->iexpy) { case -1: iexpy = EXP_; break; case 0: iexpy = LIN_; break; default: iexpy = (int) *p->iexpy; } /* if (*p->iexpx == LIN_) iexpx = LIN_; else iexpx = (int) *p->iexpx; if (*p->iexpy == LIN_) iexpy = LIN_; else iexpy = (int) *p->iexpy; */ Fl_Positioner *o = new Fl_Positioner(ix, iy, iwidth, iheight, Name); widget_attributes(csound, o); switch (iexpx) { case LIN_: //linear o->xbounds(*p->iminx,*p->imaxx); break; case EXP_: //exponential { if (UNLIKELY(*p->iminx == 0 || *p->imaxx == 0)) return csound->InitError(csound, Str("FLjoy X axe: zero is illegal " "in exponential operations")); MYFLT range = *p->imaxx - *p->iminx; o->xbounds(0,range); #if defined(sun) p->basex = ::pow((*p->imaxx / (double)*p->iminx), 1.0/(double)range); #else p->basex = ::pow((*p->imaxx / *p->iminx), 1.0/(double)range); #endif } break; default: { FUNC *ftp; MYFLT fnum = abs(iexpx); if ((ftp = csound->FTnp2Find(csound, &fnum)) != NULL) { p->tablex = ftp->ftable; p->tablenx = ftp->flen; } else return NOTOK; o->xbounds(0,0.99999999); /* if (iexp > 0) //interpolated o->callback((Fl_Callback*)fl_callbackInterpTableSlider,(void *) p); else // non-interpolated o->callback((Fl_Callback*)fl_callbackTableSlider,(void *) p); */ } } switch (iexpy) { case LIN_: //linear o->ybounds(*p->imaxy,*p->iminy); break; case EXP_ : //exponential { if (UNLIKELY(*p->iminy == 0 || *p->imaxy == 0)) return csound->InitError(csound, Str("FLjoy X axe: zero is illegal " "in exponential operations")); MYFLT range = *p->imaxy - *p->iminy; o->ybounds(range,0); #if defined(sun) p->basey = ::pow((*p->imaxy / (double)*p->iminy), 1.0/(double)range); #else p->basey = ::pow((*p->imaxy / *p->iminy), 1.0/(double)range); #endif } break; default: { FUNC *ftp; MYFLT fnum = abs(iexpy); if (LIKELY((ftp = csound->FTnp2Find(csound, &fnum)) != NULL)) { p->tabley = ftp->ftable; p->tableny = ftp->flen; } else return NOTOK; o->ybounds(0,0.99999999); /* if (iexp > 0) //interpolated o->callback((Fl_Callback*)fl_callbackInterpTableSlider,(void *) p); else // non-interpolated o->callback((Fl_Callback*)fl_callbackTableSlider,(void *) p); */ } } o->align(FL_ALIGN_BOTTOM | FL_ALIGN_WRAP); o->callback((Fl_Callback*)fl_callbackJoystick,(void *) p); widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(iexpx, *p->iminx, *p->imaxx, (void *) o, (void *) p, widgetGlobals->currentSnapGroup)); *p->ihandle1 = widgetGlobals->AddrSetValue.size()-1; ADDR_SET_VALUE *asv = &widgetGlobals->AddrSetValue[(int) *p->ihandle1]; asv->widg_type = FL_JOY; asv->joy = JOY_X; widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(iexpy, *p->iminy, *p->imaxy, (void *) o, (void *) p, widgetGlobals->currentSnapGroup)); *p->ihandle2 = widgetGlobals->AddrSetValue.size()-1; asv = &widgetGlobals->AddrSetValue[(int) *p->ihandle2]; asv->widg_type = FL_JOY; asv->joy = JOY_Y; return OK; } static int fl_knob(CSOUND *csound, FLKNOB *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); char *controlName = p->name->data; int ix, iy, iwidth, itype, iexp; if (*p->iy < 0) iy = widgetGlobals->FL_iy; else widgetGlobals->FL_iy = iy = (int) *p->iy; if (*p->ix < 0) ix = widgetGlobals->FL_ix; else widgetGlobals->FL_ix = ix = (int) *p->ix; if (*p->iwidth < 0) iwidth = widgetGlobals->FLcontrol_iwidth; else widgetGlobals->FLcontrol_iwidth = iwidth = (int) *p->iwidth; if (*p->itype < 1) itype = 1; else itype = (int) *p->itype; /* if (*p->iexp < LIN_) iexp = LIN_; else iexp = (int) *p->iexp; */ switch((int) *p->iexp) { case -1: iexp = EXP_; break; case 0: iexp = LIN_; break; default: iexp = (int) *p->iexp; } Fl_Valuator* o; switch (itype) { case 1: o = new Fl_Knob(csound, ix, iy, iwidth, iwidth, controlName); o->box(FL_NO_BOX); if (*p->icursorsize > MYFLT(0.5)) ((Fl_Knob*) o)->cursor((int) (*p->icursorsize + MYFLT(0.5))); break; case 2: o = new Fl_Dial(ix, iy, iwidth, iwidth, controlName); o->type(FL_FILL_DIAL); o->box(_FL_OSHADOW_BOX); ((Fl_Dial*) o)->angles(20, 340); break; case 3: o = new Fl_Dial(ix, iy, iwidth, iwidth, controlName); o->type(FL_LINE_DIAL); o->box(_FL_OSHADOW_BOX); break; case 4: o = new Fl_Dial(ix, iy, iwidth, iwidth, controlName); o->type(FL_NORMAL_DIAL); o->box(_FL_OSHADOW_BOX); break; default: return csound->InitError(csound, Str("FLknob: invalid knob type")); } widget_attributes(csound, o); o->align(FL_ALIGN_BOTTOM | FL_ALIGN_WRAP); o->range(*p->imin, *p->imax); switch (iexp) { case LIN_: //linear o->range(*p->imin,*p->imax); o->callback((Fl_Callback*)fl_callbackLinearKnob,(void *) p); o->step(0.001); break; case EXP_ : //exponential { MYFLT min = p->min = *p->imin, max = *p->imax; if (UNLIKELY(min == 0 || max == 0)) return csound->InitError(csound, Str("FLknob: zero is illegal " "in exponential operations")); MYFLT range = max - min; o->range(0,range); #if defined(sun) p->base = ::pow((max / (double)min), 1.0/(double)range); #else p->base = ::pow((max / min), 1.0/(double)range); #endif o->callback((Fl_Callback*)fl_callbackExponentialKnob,(void *) p); } break; default: { FUNC *ftp; p->min = *p->imin; MYFLT fnum = abs(iexp); if ((ftp = csound->FTnp2Find(csound, &fnum)) != NULL) { p->table = ftp->ftable; p->tablen = ftp->flen; } else return OK; o->range(0,0.99999999); if (iexp > 0) //interpolated o->callback((Fl_Callback*)fl_callbackInterpTableKnob,(void *) p); else // non-interpolated o->callback((Fl_Callback*)fl_callbackTableKnob,(void *) p); } } widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(iexp, *p->imin, *p->imax, (void *) o, (void *) p)); *p->ihandle = widgetGlobals->AddrSetValue.size()-1; return OK; } static int fl_text(CSOUND *csound, FLTEXT *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); char *controlName = p->name->data; int ix,iy,iwidth,iheight,itype; MYFLT istep; if (*p->iy < 0) iy = widgetGlobals->FL_iy; else widgetGlobals->FL_iy = iy = (int) *p->iy; if (*p->ix < 0) ix = widgetGlobals->FL_ix; else widgetGlobals->FL_ix = ix = (int) *p->ix; if (*p->iwidth < 0) iwidth = widgetGlobals->FLcontrol_iwidth; else widgetGlobals->FLcontrol_iwidth = iwidth = (int) *p->iwidth; if (*p->iheight < 0) iheight = widgetGlobals->FLcontrol_iheight; else widgetGlobals->FLcontrol_iheight = iheight = (int) *p->iheight; if (*p->itype < 1) itype = 1; else itype = (int) *p->itype; if (*p->istep < 0) istep = MYFLT(.1); else istep = *p->istep; Fl_Valuator* o; switch(itype) { case 1: { o = new Fl_Value_Input(ix, iy, iwidth, iheight, controlName); ((Fl_Value_Input *) o)->step(istep); ((Fl_Value_Input *) o)->range(*p->imin,*p->imax); } break; case 2: { o = new Fl_Value_Input_Spin(csound, ix, iy, iwidth, iheight, controlName); ((Fl_Value_Input *) o)->step(istep); ((Fl_Value_Input *) o)->range(*p->imin,*p->imax); } break; case 3: { o = new Fl_Value_Output(ix, iy, iwidth, iheight, controlName); ((Fl_Value_Output *) o)->step(istep); ((Fl_Value_Output *) o)->range(*p->imin,*p->imax); } break; default: return NOTOK; } o->align(FL_ALIGN_BOTTOM | FL_ALIGN_WRAP); widget_attributes(csound, o); o->callback((Fl_Callback*)fl_callbackLinearValueInput,(void *) p); widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(1, *p->imin, *p->imax, (void *) o, (void *) p, widgetGlobals->currentSnapGroup)); *p->ihandle = widgetGlobals->AddrSetValue.size()-1; return OK; } static int fl_button(CSOUND *csound, FLBUTTON *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); char *Name = p->name->data; int type = (int) *p->itype; bool plastic = false; if (type > 19) { type = type - 20; plastic = true; } if (UNLIKELY(type > 9)) { // ignored when getting widgetGlobals->snapshots csound->Warning(csound, Str("FLbutton \"%s\" ignoring snapshot capture retrieve"), Name); type = type - 10; } Fl_Button *w; *p->kout = *p->ioff; // IV - Aug 27 2002 switch (type) { case 1: w = new Fl_Button((int)*p->ix, (int)*p->iy, (int)*p->iwidth, (int)*p->iheight, Name); if (plastic) { w->box(FL_PLASTIC_UP_BOX); w->down_box(FL_PLASTIC_DOWN_BOX); } break; case 2: w = new Fl_Light_Button((int)*p->ix, (int)*p->iy, (int)*p->iwidth, (int)*p->iheight, Name); if (plastic) { w->box(FL_PLASTIC_UP_BOX); // w->down_box(FL_PLASTIC_DOWN_BOX); //Doesn't work } break; case 3: w = new Fl_Check_Button((int)*p->ix, (int)*p->iy, (int)*p->iwidth, (int)*p->iheight, Name); if (plastic) { w->box(FL_PLASTIC_UP_BOX); w->down_box(FL_PLASTIC_DOWN_BOX); } break; case 4: w = new Fl_Round_Button((int)*p->ix, (int)*p->iy, (int)*p->iwidth, (int)*p->iheight, Name); if (plastic) { w->box(FL_PLASTIC_UP_BOX); w->down_box(FL_PLASTIC_DOWN_BOX); } break; default: return csound->InitError(csound, Str("FLbutton: invalid button type")); } Fl_Button *o = w; o->align(FL_ALIGN_WRAP); widget_attributes(csound, o); if (type == 1) o->callback((Fl_Callback*) fl_callbackButton1, (void*) p); else o->callback((Fl_Callback*) fl_callbackButton, (void*) p); widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(0, 0, 0, (void *) o, (void *) p, widgetGlobals->currentSnapGroup)); *p->ihandle = widgetGlobals->AddrSetValue.size() - 1; return OK; } static int fl_close_button(CSOUND *csound, FLCLOSEBUTTON *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); char *Name = p->name->data; Fl_Button *w; w = new Fl_Button((int)*p->ix, (int)*p->iy, (int)*p->iwidth, (int)*p->iheight, Name); Fl_Button *o = w; o->align(FL_ALIGN_WRAP); widget_attributes(csound, o); ADDR_STACK adrstk = widgetGlobals->AddrStack.back(); if (UNLIKELY(strcmp( adrstk.h->optext->t.opcod, "FLpanel"))) return csound->InitError(csound, Str("FLcloseButton: invalid stack" " pointer: verify its placement")); o->callback((Fl_Callback*) fl_callbackCloseButton, (void*) adrstk.WidgAddress); widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(0, 0, 0, (void *) o, (void *) p)); *p->ihandle = widgetGlobals->AddrSetValue.size() - 1; return OK; } static int fl_exec_button(CSOUND *csound, FLEXECBUTTON *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); p->csound = csound; Fl_Button *w; p->commandString = p->command->data; csound->Message(csound, Str("Command Found: %s\n"), p->commandString); w = new Fl_Button((int)*p->ix, (int)*p->iy, (int)*p->iwidth, (int)*p->iheight, Str("About")); Fl_Button *o = w; o->align(FL_ALIGN_WRAP); widget_attributes(csound, o); o->callback((Fl_Callback*) fl_callbackExecButton, (void*) p); widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(0, 0, 0, (void *) o, (void *) p, widgetGlobals->currentSnapGroup)); *p->ihandle = widgetGlobals->AddrSetValue.size() - 1; return OK; } static int fl_button_bank(CSOUND *csound, FLBUTTONBANK *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); char *Name = (char*)"/0"; int type = (int) *p->itype; bool plastic = false; if (type > 20) { plastic = true; type = type - 20; } if (UNLIKELY(type > 9)) { // ignored when getting widgetGlobals->snapshots csound->Warning(csound, Str("FLbutton \"%s\" ignoring snapshot capture retrieve"), Name); type = type - 10; } Fl_Group* o = new Fl_Group((int)*p->ix, (int)*p->iy, (int)*p->inumx * 10, (int)*p->inumy*10); int z = 0; for (int j = 0; j < *p->inumx; j++) { for (int k = 0; k < *p->inumy; k++) { int x = (int) *p->ix + j*10, y = (int) *p->iy + k*10; Fl_Button *w; char *btName = new char[30]; widgetGlobals->allocatedStrings.push_back(btName); sprintf(btName, "%d", z); switch (type) { case 1: w = new Fl_Button(x, y, 10, 10, btName); if (plastic) { w->box(FL_PLASTIC_UP_BOX); w->down_box(FL_PLASTIC_DOWN_BOX); } break; case 2: w = new Fl_Light_Button(x, y, 10, 10, btName); if (plastic) { w->box(FL_PLASTIC_UP_BOX); } break; case 3: w = new Fl_Check_Button(x, y, 10, 10, btName); if (plastic) { w->box(FL_PLASTIC_UP_BOX); w->down_box(FL_PLASTIC_DOWN_BOX); } break; case 4: w = new Fl_Round_Button(x, y, 10, 10, btName); if (plastic) { w->box(FL_PLASTIC_UP_BOX); w->down_box(FL_PLASTIC_DOWN_BOX); } break; default: return csound->InitError(csound, Str("FLbuttonBank: " "invalid button type")); } widget_attributes(csound, w); w->type(FL_RADIO_BUTTON); w->callback((Fl_Callback*) fl_callbackButtonBank, (void *) p); if (!z) w->value(1); z++; } } o->resizable(o); //*p->ix, *p->iy, o->size( (int)*p->iwidth, (int)*p->iheight); o->position((int)*p->ix, (int)*p->iy); o->align(FL_ALIGN_BOTTOM | FL_ALIGN_WRAP); o->end(); widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(0, 0, 0, (void *) o, (void *) p, widgetGlobals->currentSnapGroup)); *p->kout = MYFLT(0.0); *p->ihandle = widgetGlobals->AddrSetValue.size()-1; return OK; } static int fl_counter(CSOUND *csound, FLCOUNTER *p) { char *controlName = p->name->data; // int ix,iy,iwidth,iheight,itype; // MYFLT istep1, istep2; WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); Fl_Counter* o = new Fl_Counter((int)*p->ix, (int)*p->iy, (int)*p->iwidth, (int)*p->iheight, controlName); widget_attributes(csound, o); int type = (int) *p->itype; if (UNLIKELY(type >9 )) { // ignored when getting widgetGlobals->snapshots csound->Warning(csound, Str("FLcount \"%s\" ignoring snapshot capture retrieve"), controlName); type = type-10; } switch(type) { case 1: o->type(FL_NORMAL_COUNTER); break; case 2: o->type(FL_SIMPLE_COUNTER); break; default:o->type(FL_NORMAL_COUNTER); break; } o->step(*p->istep1); o->lstep(*p->istep2); o->align(FL_ALIGN_BOTTOM | FL_ALIGN_WRAP); // range is accepted only if min and max are different if (*p->imin != *p->imax) o->range(*p->imin,*p->imax); //otherwise no-range widget_attributes(csound, o); o->callback((Fl_Callback*)fl_callbackCounter,(void *) p); widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(1, 0, 100000, (void *) o, (void *) p, widgetGlobals->currentSnapGroup)); *p->ihandle = widgetGlobals->AddrSetValue.size()-1; return OK; } static int fl_roller(CSOUND *csound, FLROLLER *p) { char *controlName = p->name->data; int ix,iy,iwidth, iheight,itype, iexp ; double istep; WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); if (*p->iy < 0) { iy = widgetGlobals->FL_iy; widgetGlobals->FL_iy += widgetGlobals->FLroller_iheight + 15; } else { iy = (int) *p->iy; widgetGlobals->FL_iy = iy + widgetGlobals->FLroller_iheight + 15; } // omitted options: set defaults if (*p->ix<0) ix = widgetGlobals->FL_ix; else widgetGlobals->FL_ix = ix = (int) *p->ix; if (*p->iy<0) iy = widgetGlobals->FL_iy; else widgetGlobals->FL_iy = iy = (int) *p->iy; if (*p->iwidth<0) iwidth = widgetGlobals->FLroller_iwidth; else widgetGlobals->FLroller_iwidth = iwidth = (int) *p->iwidth; if (*p->iheight<0) iheight = widgetGlobals->FLroller_iheight; else widgetGlobals->FLroller_iheight = iheight = (int) *p->iheight; if (*p->itype<1) itype = 1; else itype = (int) *p->itype; //if (*p->iexpiexp; switch((int) *p->iexp) { case -1: iexp = EXP_; break; case 0: iexp = LIN_; break; default: iexp = (int) *p->iexp; } if (*p->istep<0) istep = 1; else istep = *p->istep; p->min = *p->imin; Fl_Roller *o; switch (itype) { case 1: o = new Fl_Roller(ix, iy, iwidth, iheight, controlName); o->type(FL_HORIZONTAL); break; case 2: o = new Fl_Roller(ix, iy, iwidth, iheight, controlName); o->type(FL_VERTICAL); break; default: return csound->InitError(csound, Str("FLroller: invalid roller type")); } widget_attributes(csound, o); o->step(istep); switch (iexp) { case LIN_: //linear o->range(*p->imin,*p->imax); o->callback((Fl_Callback*)fl_callbackLinearRoller,(void *) p); break; case EXP_ : //exponential { MYFLT min = p->min, max = *p->imax; if (UNLIKELY(min == 0 || max == 0)) return csound->InitError(csound, Str("FLslider: zero is illegal " "in exponential operations")); MYFLT range = max - min; o->range(0,range); #if defined(sun) p->base = ::pow((max / (double)min), 1.0/(double)range); #else p->base = ::pow((max / min), 1.0/(double)range); #endif o->callback((Fl_Callback*)fl_callbackExponentialRoller,(void *) p); } break; default: { FUNC *ftp; MYFLT fnum = abs(iexp); if ((ftp = csound->FTnp2Find(csound, &fnum)) != NULL) { p->table = ftp->ftable; p->tablen = ftp->flen; } else return NOTOK; o->range(0,0.99999999); if (iexp > 0) //interpolated o->callback((Fl_Callback*)fl_callbackInterpTableRoller,(void *) p); else // non-interpolated o->callback((Fl_Callback*)fl_callbackTableRoller,(void *) p); } } widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(iexp, *p->imin, *p->imax, (void *) o, (void *) p, widgetGlobals->currentSnapGroup)); *p->ihandle = widgetGlobals->AddrSetValue.size()-1; return OK; } static int FLprintkset(CSOUND *csound, FLPRINTK *p) { //WIDGET_GLOBALS *widgetGlobals = //(WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); if (*p->ptime < MYFLT(1.0) / CS_EKR) p->ctime = MYFLT(1.0) / CS_EKR; else p->ctime = *p->ptime; p->initime = (MYFLT) csound->GetKcounter(csound) * (1.0/CS_EKR); p->cysofar = -1; return OK; } static int FLprintk(CSOUND *csound, FLPRINTK *p) { MYFLT timel; long cycles; WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); timel = ((MYFLT) csound->GetKcounter(csound) * (1.0/CS_EKR)) - p->initime; cycles = (long)(timel / p->ctime); if (p->cysofar < cycles) { p->cysofar = cycles; char valString[MAXNAME]; sprintf(valString,"%.5g", *p->val); ((Fl_Output*) (widgetGlobals->AddrSetValue[(long) *p->idisp]).WidgAddress)-> value(valString ); } return OK; } static int FLprintk2set(CSOUND *csound, FLPRINTK2 *p) // IV - Aug 27 2002 { p->oldvalue = MYFLT(-1.12123e35); // hack to force printing first value return OK; } static int FLprintk2(CSOUND *csound, FLPRINTK2 *p) { MYFLT value = *p->val; WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); if (p->oldvalue != value) { char valString[MAXNAME]; sprintf(valString,"%.5g", *p->val); ((Fl_Output*) (widgetGlobals->AddrSetValue[(long) *p->idisp]).WidgAddress)-> value(valString ); p->oldvalue = value; } return OK; } // New opcodes for Csound5.06 by Gabriel Maldonado, ported by Andres Cabrera void skin(CSOUND* csound, Fl_Widget *o, int imgNum, bool isTiled) { // WIDGET_GLOBALS *widgetGlobals = // (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); #ifdef CS_IMAGE extern void* get_image(CSOUND* csound, int imgNum); ImageSTRUCT *bmp = (ImageSTRUCT*) get_image(csound, imgNum); FLlock(); Fl_RGB_Image *img = new Fl_RGB_Image((BYTE*) (bmp->data), bmp->xsize,bmp->ysize,bmp->csize); widgetGlobals->allocatedStrings.push_back((char *) img); if (isTiled) { Fl_Tiled_Image *t_img = new Fl_Tiled_Image(img); o->image(t_img); widgetGlobals->allocatedStrings.push_back((char *) t_img); } else { o->image(img); } o->align(FL_ALIGN_INSIDE); FLunlock(); #endif } class HVS_BOX : public Fl_Box{ int rx,ry,rw,rh; int red, green, blue; // Fl_PNG_Image *img; public: int numLinesX,numLinesY; MYFLT valueX, valueY; HVS_BOX(int numLinesX_, int numLinesY_, int x, int y, int w, int h) : Fl_Box(x,y,w,h) { numLinesX = numLinesX_ - 1; numLinesY = numLinesY_ - 1; valueX = valueY = .5; rx = rw = ry = rh = 0; red = green = blue = 0; // if (filename != NULL) { // img = new Fl_PNG_Image(filename); // this->image(img); // } } void draw() { Fl_Box::draw(); fl_color(selection_color()); MYFLT Xincr = w()/(MYFLT) numLinesX; MYFLT Yincr = h()/(MYFLT) numLinesY; fl_color(FL_RED); for (int j = 1; j < numLinesX; j++) { fl_yxline((int) (j*Xincr+x()), y(), h()+y()); } for (int k = 1; k QueryGlobalVariable(csound, "WIDGET_GLOBALS"); if (UNLIKELY(*p->numlinesX < 2 || *p->numlinesY < 2)) return csound->InitError(csound, Str("FLhvsBox: a square area must be" " delimited by 2 lines at least")); HVS_BOX *o = new HVS_BOX((int) *p->numlinesX,(int) *p->numlinesY, (int) *p->ix,(int) *p->iy, (int) *p->iwidth, (int) *p->iheight); widget_attributes(csound,o); o->box(FL_DOWN_BOX); if (*p->image >= 0) skin(csound, o, (int) *p->image, false); widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(0, 0, 0, (void *) o, (void *) p, widgetGlobals->currentSnapGroup)); *p->ihandle = widgetGlobals->AddrSetValue.size()-1; return OK; } static int fl_setHvsValue_set(CSOUND *csound,FL_SET_HVS_VALUE *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); ADDR_SET_VALUE v = widgetGlobals->AddrSetValue[(int) *p->ihandle]; p->WidgAddress = v.WidgAddress; p->opcode = v.opcode; return OK; } static int fl_setHvsValue(CSOUND *csound,FL_SET_HVS_VALUE *p) { if(*p->kx != p->old_x || *p->ky != p->old_y ) { HVS_BOX *o = (HVS_BOX *) p->WidgAddress; FLlock(); o->setXY(*p->kx, *p->ky); FLunlock(); p->old_x = *p->kx; p->old_y = *p->ky; } return OK; } static int fl_keyin_set(CSOUND *csound,FLKEYIN *p) { FUNC* ftp; if (*p->ifn > 0) { // mapping values p->flag = 1; if (LIKELY((ftp = csound->FTnp2Find(csound,p->ifn)) != NULL)) p->table = ftp->ftable; else { return csound->InitError(csound, Str("FLkeyIn: invalid table number")); } if (UNLIKELY(ftp->flen < 512)) { return csound->InitError(csound, Str("FLkeyIn: table too short!")); } } else p->flag = 0; return OK; } static int fl_keyin(CSOUND *csound,FLKEYIN *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); if (widgetGlobals->last_KEY) { int key; if ( widgetGlobals->last_KEY > 0 && widgetGlobals->last_KEY < 256) key = widgetGlobals->last_KEY; else key = (widgetGlobals->last_KEY & 0xFF) + 256; // function keys if(p->flag) { if(widgetGlobals->isKeyDown) p->table[key] = 1; else p->table[key] = 0; } if (widgetGlobals->isKeyDown) *p->kascii = key; else *p->kascii = -key; widgetGlobals->last_KEY = 0; } return OK; } static int fl_setSnapGroup(CSOUND *csound, FLSETSNAPGROUP *p) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); widgetGlobals->currentSnapGroup = (int) *p->group; return OK; } static int fl_mouse_set(CSOUND *csound,FLMOUSE *p) { p->width= Fl::w(); p->height= Fl::h(); return OK; } static int fl_mouse(CSOUND *csound,FLMOUSE *p) { if (*p->flagRaw == 0) { *p->x = (MYFLT) Fl::event_x_root()/p->width; *p->y = 1.0 - ((MYFLT) Fl::event_y_root()/p->height); } else if (*p->flagRaw == 1) { *p->x = (MYFLT) Fl::event_x_root(); *p->y = (MYFLT) Fl::event_y_root(); } else if (*p->flagRaw == 2) { *p->x = (MYFLT) Fl::event_x(); *p->y = (MYFLT) Fl::event_y(); } // *p->b1 = (MYFLT) (Fl::event_button1() >> 56); // *p->b2 = (MYFLT) (Fl::event_button2() >> 57); // *p->b3 = (MYFLT) (Fl::event_button3() >> 58); *p->b1 = (MYFLT) (Fl::event_button1() >> 24); *p->b2 = (MYFLT) (Fl::event_button2() >> 25); *p->b3 = (MYFLT) (Fl::event_button3() >> 26); return OK; } static int fl_vertical_slider_bank_(CSOUND *csound, FLSLIDERBANK *p, int istring) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); char s[MAXNAME]; bool plastic = false; if (istring) strncpy(s, ((STRINGDAT *)p->names)->data, MAXNAME-1); else if ((long) *p->names <= csound->GetStrsmax(csound) && csound->GetStrsets(csound,(long) *p->names)) { strncpy(s, csound->GetStrsets(csound,(long) *p->names), MAXNAME-1); } string tempname(s); stringstream sbuf; sbuf << tempname; int height = (int) *p->iheight; if (height <=0) height = 100; Fl_Group* w = new Fl_Group((int)*p->ix, (int)*p->iy, (int)*p->inumsliders*10, height); FUNC *ftp; MYFLT *minmaxtable = NULL, *typetable = NULL, *outable, *exptable = NULL; MYFLT *zkstart; int zklast = csound->GetZakBounds(csound, &zkstart); if (*p->ioutable < 1) { if (LIKELY(zkstart != NULL && zklast > (long)(*p->inumsliders+*p->ioutablestart_ndx))) outable = zkstart + (long) *p->ioutablestart_ndx; else { return csound->InitError(csound, Str("invalid ZAK space allocation")); } } else { if (LIKELY((ftp = csound->FTnp2Find(csound, p->ioutable)) != NULL)) outable = ftp->ftable + (long) *p->ioutablestart_ndx; else return NOTOK; } if ((int) *p->iminmaxtable > 0) { if (LIKELY((ftp = csound->FTnp2Find(csound, p->iminmaxtable)) != NULL)) minmaxtable = ftp->ftable; else return NOTOK; } if ((int) *p->iexptable > 0) { if (LIKELY((ftp = csound->FTnp2Find(csound, p->iexptable)) != NULL)) exptable = ftp->ftable; else return NOTOK; } if ((int) *p->itypetable > 0) { if (LIKELY((ftp = csound->FTnp2Find(csound, p->itypetable)) != NULL)) typetable = ftp->ftable; else return NOTOK; } p->elements = (long) *p->inumsliders; for (int j =0; j< p->elements; j++) { string stemp; if (tempname == " ") { char s[40]; sprintf(s, "%d", j); stemp = s; } else getline(sbuf, stemp, '@'); char *Name = new char[stemp.size()+2]; strcpy(Name,stemp.c_str()); widgetGlobals->allocatedStrings.push_back(Name); int x = (int) *p->ix+j*10, y = (int) *p->iy /*+ j*10*/; Fl_Slider *o; int slider_type; if ((int) *p->itypetable <= 0) { // no slider type table if (*p->itypetable >= -7) // all sliders are of the same type slider_type = -((int) *p->itypetable); else if (*p->itypetable >= -27 && *p->itypetable < -20) { slider_type = -((int) *p->itypetable) - 20; plastic = true; } else { // random type slider_type = rand_31_i(csound, 7) | 1; switch(slider_type) { case 0: slider_type = 1; break; case 2: slider_type = 3; break; case 4: slider_type = 5; break; case 6: slider_type = 7; break; default: slider_type = 1; } } } else slider_type = (int) typetable[j]; if (slider_type > 20) { plastic = true; slider_type -= 20; } if (slider_type < 10) o = new Fl_Slider(x, y, 10, height, Name); else { o = new Fl_Value_Slider_Input(csound, x, y, 10, height, Name); slider_type -=10; ((Fl_Value_Slider_Input*) o)->textboxsize(50); ((Fl_Value_Slider_Input*) o)->textsize(13); } switch((int) slider_type) { //type case 1: o->type(FL_VERT_FILL_SLIDER); break; case 3: o->type(FL_VERT_SLIDER); break; case 5: o->type(FL_VERT_NICE_SLIDER); o->box(FL_FLAT_BOX); break; case 7: o->type(FL_VERT_NICE_SLIDER); o->box(FL_DOWN_BOX); break; default: o->type(FL_VERT_NICE_SLIDER); o->box(FL_FLAT_BOX); break; } o->align(FL_ALIGN_BOTTOM); if (plastic) o->box(FL_PLASTIC_DOWN_BOX); widget_attributes(csound, o); MYFLT min, max, range; if ((int) *p->iminmaxtable > 0) { min = minmaxtable[j*2]; max = minmaxtable[j*2+1]; } else { min = MYFLT(0.0); max = MYFLT(1.0); } int iexp; p->slider_data[j].min=min; p->slider_data[j].max=max; p->slider_data[j].out=&outable[j]; if ((int) *p->iexptable <=0) // no table, all sliders have the same behaviour iexp = (int) *p->iexptable; else iexp = (int) exptable[j]; switch (iexp) { case -1: iexp = EXP_; break; case 0: iexp = LIN_; break; } MYFLT val = 0; p->slider_data[j].exp = iexp; switch (iexp) { case LIN_: //linear o->range(min,max); o->callback((Fl_Callback*)fl_callbackLinearSliderBank, (void *) &(p->slider_data[j])); val = outable[j]; if (val > max) val = max; else if (val < min) val = min; break; case EXP_ : //exponential if (UNLIKELY(min == 0 || max == 0)) return csound->InitError(csound, Str("FLvslidBnk: zero is illegal " "in exponential operations")); range = max - min; o->range(range,0); #if defined(sun) p->slider_data[j].base = ::pow((max / (double)min), 1.0/(double)range); #else p->slider_data[j].base = ::pow((max / min), 1.0/(double)range); #endif o->callback((Fl_Callback*)fl_callbackExponentialSliderBank, (void *) &(p->slider_data[j])); { val = outable[j]; MYFLT range = max-min; #if defined(sun) MYFLT base = ::pow(max / (double)min, 1.0/(double)range); #else MYFLT base = ::pow(max / min, 1.0/(double)range); #endif val = (log(val/min) / log(base)) ; } break; default: { FUNC *ftp; MYFLT fnum = abs(iexp); if (LIKELY((ftp = csound->FTnp2Find(csound, &fnum)) != NULL)) p->slider_data[j].table = ftp->ftable; else return NOTOK; p->slider_data[j].tablen = ftp->flen; o->range(.99999999,0); if (iexp > 0) //interpolated o->callback((Fl_Callback*)fl_callbackInterpTableSliderBank, (void *) &(p->slider_data[j])); else // non-interpolated o->callback((Fl_Callback*)fl_callbackTableSliderBank, (void *) &(p->slider_data[j])); } } o->value(val); p->slider_data[j].widget_addr= (void*) o; } w->resizable(w); if (*p->iwidth <=0 || *p->iheight <=0) {// default width and height int a,b; w->size( a= w->parent()->w(), b= w->parent()->h()-50); w->position(0, 0); } else { w->size( (int)*p->iwidth, (int)*p->iheight); w->position((int)*p->ix, (int)*p->iy); } w->end(); widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(LIN_, 0, 0, (void *) w, (void *) p, widgetGlobals->currentSnapGroup)); widgetGlobals->last_sldbnk = widgetGlobals->AddrSetValue.size()-1; //gab return OK; } static int fl_vertical_slider_bank(CSOUND *csound, FLSLIDERBANK *p){ return fl_vertical_slider_bank_(csound,p,0); } static int fl_vertical_slider_bank_S(CSOUND *csound, FLSLIDERBANK *p){ return fl_vertical_slider_bank_(csound,p,1); } static int fl_slider_bank2_(CSOUND *csound, FLSLIDERBANK2 *p, int istring) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); char s[MAXNAME]; bool plastic = false; if (istring) strncpy(s, ((STRINGDAT*) p->names)->data, MAXNAME-1); else if ((long) *p->names <= csound->GetStrsmax(csound) && csound->GetStrsets(csound,(long) *p->names)) { strncpy(s, csound->GetStrsets(csound,(long) *p->names), MAXNAME-1); } string tempname(s); stringstream sbuf; sbuf << tempname; int width = (int) *p->iwidth; if (width <=0) width = 100; Fl_Group* w = new Fl_Group((int)*p->ix, (int)*p->iy, width, (int)*p->inumsliders*10); FUNC *ftp; MYFLT *configtable, *outable; MYFLT *zkstart; int zklast = csound->GetZakBounds(csound, &zkstart); if (*p->ioutable < 1) { if (LIKELY(zkstart != NULL && zklast>(long)(*p->inumsliders + *p->ioutablestart_ndx))) outable = zkstart + (long) *p->ioutablestart_ndx; else { return csound->InitError(csound, Str("invalid ZAK space allocation")); } } else { if ((ftp = csound->FTnp2Find(csound, p->ioutable)) != NULL) outable = ftp->ftable + (long) *p->ioutablestart_ndx; else return NOTOK; } if((ftp = csound->FTnp2Find(csound, p->iconfigtable)) != NULL) configtable = ftp->ftable; else return NOTOK; p->elements = (long) *p->inumsliders; for (int j =0; j< p->elements; j++) { string stemp; if (tempname == " ") { char s[40]; sprintf(s, "%d", j); stemp = s; } else getline(sbuf, stemp, '@'); char *Name = new char[stemp.size()+2]; strcpy(Name,stemp.c_str()); widgetGlobals->allocatedStrings.push_back(Name); int x = (int) *p->ix, y = (int) *p->iy + j*10; Fl_Slider *o; int slider_type = (int) configtable[j*4+3]; int iexp = (int) configtable[j*4+2]; if (slider_type > 19) { plastic = true; slider_type = slider_type - 20; } if (UNLIKELY(slider_type > 10 && iexp == EXP_)) { csound->Warning(csound, Str("FLslider exponential, using non-labeled slider")); slider_type -= 10; } if (slider_type <= 10) o = new Fl_Slider(x, y, width, 10, Name); else { o = new Fl_Value_Slider_Input( csound, x, y, width, 10, Name); slider_type -=10; ((Fl_Value_Slider_Input*) o)->textboxsize(20); ((Fl_Value_Slider_Input*) o)->textsize(13); } switch((int) slider_type) { //type case 1: o->type(FL_HOR_FILL_SLIDER); break; case 3: o->type(FL_HOR_SLIDER); break; case 5: o->type(FL_HOR_NICE_SLIDER); o->box(FL_FLAT_BOX); break; case 7: o->type(FL_HOR_NICE_SLIDER); o->box(FL_DOWN_BOX); break; default: o->type(FL_HOR_NICE_SLIDER); o->box(FL_FLAT_BOX); break; } o->align(FL_ALIGN_LEFT); if (plastic) o->box(FL_PLASTIC_DOWN_BOX); o->step(0.0); widget_attributes(csound, o); MYFLT min, max, range; min = configtable[j*4]; max = configtable[j*4+1]; p->slider_data[j].min=min; p->slider_data[j].max=max; p->slider_data[j].out=&outable[j]; switch (iexp) { case -1: iexp = EXP_; break; case 0: iexp = LIN_; break; } MYFLT val = 0; p->slider_data[j].exp = iexp; switch (iexp) { case LIN_: //linear o->range(min,max); o->callback((Fl_Callback*)fl_callbackLinearSliderBank, (void *) &(p->slider_data[j])); val = outable[j]; if (val > max) val = max; else if (val < min) val = min; break; case EXP_ : //exponential if (UNLIKELY(min == 0 || max == 0)) return csound->InitError(csound, Str("FLsliderBank: zero is illegal " "in exponential operations")); range = max - min; o->range(0,range); #if defined(sun) p->slider_data[j].base = ::pow((max / (double)min), 1.0/(double)range); #else p->slider_data[j].base = ::pow((max / min), 1.0/(double)range); #endif o->callback((Fl_Callback*)fl_callbackExponentialSliderBank, (void *) &(p->slider_data[j])); { val = outable[j]; MYFLT range = max-min; #if defined(sun) MYFLT base = ::pow(max / (double)min, 1.0/(double)range); #else MYFLT base = ::pow(max / min, 1.0/(double)range); #endif val = (log(val/min) / log(base)) ; } break; default: { FUNC *ftp; MYFLT fnum = abs(iexp); if ((ftp = csound->FTnp2Find(csound, &fnum)) != NULL) p->slider_data[j].table = ftp->ftable; else return NOTOK; p->slider_data[j].tablen = ftp->flen; o->range(0,0.99999999); if (iexp > 0) //interpolated o->callback((Fl_Callback*)fl_callbackInterpTableSliderBank, (void *) &(p->slider_data[j])); else // non-interpolated o->callback((Fl_Callback*)fl_callbackTableSliderBank, (void *) &(p->slider_data[j])); } } o->value(val); p->slider_data[j].widget_addr= (void*) o; } w->resizable(w); if (*p->iwidth <=0 || *p->iheight <=0) {// default width and height int a,b; w->size( a= w->parent()->w() -50, b= w->parent()->h()); w->position(50, 0); } else { w->size( (int)*p->iwidth, (int)*p->iheight); w->position((int)*p->ix, (int)*p->iy); } w->end(); widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(LIN_, 0, 0, (void *) w, (void *) p, widgetGlobals->currentSnapGroup)); //*p->ihandle = widgetGlobals->AddrSetValue.size()-1; widgetGlobals->last_sldbnk = widgetGlobals->AddrSetValue.size()-1; //gab return OK; } static int fl_slider_bank2(CSOUND *csound, FLSLIDERBANK2 *p){ return fl_slider_bank2_(csound, p,0); } static int fl_slider_bank2_S(CSOUND *csound, FLSLIDERBANK2 *p){ return fl_slider_bank2_(csound, p,1); } static int fl_vertical_slider_bank2_(CSOUND *csound, FLSLIDERBANK2 *p, int istring) { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); char s[MAXNAME]; bool plastic = false; if (istring) strncpy(s, ((STRINGDAT*) p->names)->data, MAXNAME-1); else if ((long) *p->names <= csound->GetStrsmax(csound) && csound->GetStrsets(csound,(long) *p->names)) { strncpy(s, csound->GetStrsets(csound,(long) *p->names), MAXNAME-1); } string tempname(s); stringstream sbuf; sbuf << tempname; int height = (int) *p->iheight; if (height <=0) height = 100; Fl_Group* w = new Fl_Group((int)*p->ix, (int)*p->iy, (int) *p->inumsliders*10, height); FUNC *ftp; MYFLT *configtable, *outable; MYFLT *zkstart; int zklast = csound->GetZakBounds(csound, &zkstart); if (*p->ioutable < 1) { if (LIKELY(zkstart != NULL && zklast>(long)(*p->inumsliders + *p->ioutablestart_ndx))) outable = zkstart + (long) *p->ioutablestart_ndx; else { return csound->InitError(csound, Str("invalid ZAK space allocation")); } } else { if ((ftp = csound->FTnp2Find(csound, p->ioutable)) != NULL) outable = ftp->ftable + (long) *p->ioutablestart_ndx; else return NOTOK; } if((ftp = csound->FTnp2Find(csound, p->iconfigtable)) != NULL) configtable = ftp->ftable; else return NOTOK; p->elements = (long) *p->inumsliders; for (int j =0; j< p->elements; j++) { string stemp; if (tempname == " ") { char s[40]; sprintf(s, "%d", j); stemp = s; } else getline(sbuf, stemp, '@'); char *Name = new char[stemp.size()+2]; strcpy(Name,stemp.c_str()); widgetGlobals->allocatedStrings.push_back(Name); int x = (int) *p->ix+j*10, y = (int) *p->iy /*+ j*10*/; Fl_Slider *o; int slider_type= (int) configtable[j*4+3]; int iexp = (int) configtable[j*4+2]; if (slider_type > 19) { plastic = true; slider_type -= 20; } if (UNLIKELY(slider_type > 10 && iexp == EXP_)) { csound->Warning(csound, Str("FLslidBnk2: FLslider exponential, " "using non-labeled slider")); slider_type -= 10; } if (slider_type <= 10) o = new Fl_Slider(x, y, 10, height, Name); else { o = new Fl_Value_Slider_Input( csound, x, y, 10, height, Name); slider_type -=10; ((Fl_Value_Slider_Input*) o)->textboxsize(50); ((Fl_Value_Slider_Input*) o)->textsize(13); } switch((int) slider_type) { //type case 1: case 2: o->type(FL_VERT_FILL_SLIDER); break; case 3: case 4: o->type(FL_VERT_SLIDER); break; case 5: case 6: o->type(FL_VERT_NICE_SLIDER); o->box(FL_FLAT_BOX); break; case 7: case 8: o->type(FL_VERT_NICE_SLIDER); o->box(FL_DOWN_BOX); break; default: o->type(FL_VERT_NICE_SLIDER); o->box(FL_FLAT_BOX); break; } o->align(FL_ALIGN_BOTTOM); if (plastic) o->box(FL_PLASTIC_DOWN_BOX); widget_attributes(csound, o); MYFLT min, max, range; min = configtable[j*4]; max = configtable[j*4+1]; p->slider_data[j].min=min; p->slider_data[j].max=max; p->slider_data[j].out=&outable[j]; switch (iexp) { case -1: iexp = EXP_; break; case 0: iexp = LIN_; break; } MYFLT val = 0; p->slider_data[j].exp = iexp; switch (iexp) { case LIN_: //linear o->range(min,max); o->callback((Fl_Callback*)fl_callbackLinearSliderBank, (void *) &(p->slider_data[j])); val = outable[j]; if (val > max) val = max; else if (val < min) val = min; break; case EXP_ : //exponential if (UNLIKELY(min == 0 || max == 0)) return csound->InitError(csound, Str("FLsliderBank: zero is illegal " "in exponential operations")); range = max - min; o->range(range,0); #if defined(sun) p->slider_data[j].base = ::pow((max / (double)min), 1.0/(double)range); #else p->slider_data[j].base = ::pow((max / min), 1.0/(double)range); #endif o->callback((Fl_Callback*)fl_callbackExponentialSliderBank, (void *) &(p->slider_data[j])); { val = outable[j]; MYFLT range = max-min; #if defined(sun) MYFLT base = ::pow(max / (double)min, 1.0/(double)range); #else MYFLT base = ::pow(max / min, 1.0/(double)range); #endif val = (log(val/min) / log(base)) ; } break; default: { FUNC *ftp; MYFLT fnum = abs(iexp); if ((ftp = csound->FTnp2Find(csound, &fnum)) != NULL) p->slider_data[j].table = ftp->ftable; else return NOTOK; p->slider_data[j].tablen = ftp->flen; o->range(.99999999,0); if (iexp > 0) //interpolated o->callback((Fl_Callback*)fl_callbackInterpTableSliderBank, (void *) &(p->slider_data[j])); else // non-interpolated o->callback((Fl_Callback*)fl_callbackTableSliderBank, (void *) &(p->slider_data[j])); } } o->value(val); p->slider_data[j].widget_addr= (void*) o; } w->resizable(w); if (*p->iwidth <=0 || *p->iheight <=0) {// default width and height int a,b; w->size( a= w->parent()->w(), b= w->parent()->h()-50); w->position(0, 0); } else { w->size( (int)*p->iwidth, (int)*p->iheight); w->position((int)*p->ix, (int)*p->iy); } w->end(); widgetGlobals->AddrSetValue.push_back(ADDR_SET_VALUE(LIN_, 0, 0, (void *) w, (void *) p, widgetGlobals->currentSnapGroup)); //*p->ihandle = widgetGlobals->AddrSetValue.size()-1; widgetGlobals->last_sldbnk = widgetGlobals->AddrSetValue.size()-1; //gab return OK; } static int fl_vertical_slider_bank2(CSOUND *csound, FLSLIDERBANK2 *p){ return fl_vertical_slider_bank2_(csound,p,0); } static int fl_vertical_slider_bank2_S(CSOUND *csound, FLSLIDERBANK2 *p){ return fl_vertical_slider_bank2_(csound,p,1); } static int fl_slider_bank_getHandle(CSOUND *csound, FLSLDBNK_GETHANDLE *p) //valid only if called immediately after FLslidBnk { WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); *p->ihandle = widgetGlobals->last_sldbnk; return OK; } static int fl_slider_bank_setVal(CSOUND *csound, FLSLDBNK_SET *p) { FUNC* ftp; MYFLT *table, *outable; int numslid = (int)*p->numSlid; int startInd = (int)*p->startInd; int startSlid = (int)*p->startSlid; WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); if (LIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) != NULL)) table = ftp->ftable; else { return csound->InitError(csound, Str("FLsldBnkSet: invalid table number")); } // *startInd, *startSlid, *numSlid if (UNLIKELY( (int) ftp->flen < startInd + numslid)) { return csound->InitError(csound, Str("FLslidBnkSet: table too short!")); } FLSLIDERBANK *q = (FLSLIDERBANK *)widgetGlobals->AddrSetValue[ (int) *p->ihandle].opcode; if (LIKELY((ftp = csound->FTnp2Find(csound, q->ioutable)) != NULL)) outable = ftp->ftable; else { return csound->InitError(csound, Str("FLsldBnkSet: invalid outable number")); } if (numslid == 0) numslid = (int)(q->elements - *p->startSlid); if (UNLIKELY( q->elements > startSlid + numslid)) { return csound->InitError(csound, Str("FLslidBnkSet: too many sliders to reset!")); } for (int j = startSlid, k = startInd; j< numslid + startSlid; j++, k++) { MYFLT val = 0; // MYFLT base = q->slider_data[j].base; int iexp = q->slider_data[j].exp; MYFLT min = q->slider_data[j].min; MYFLT max = q->slider_data[j].max; switch (iexp) { case LIN_: //linear val = table[k]; if (val > max) val = max; else if (val < min) val = min; break; case EXP_ : //exponential { MYFLT range = max - min; MYFLT base2 = pow(max / min, 1/range); val = (log(table[k]/min) / log(base2)) ; } break; default: return csound->InitError(csound, Str("FLslidBnkSet: " "function mapping not available")); } FLlock(); ((Fl_Slider*) (q->slider_data[j].widget_addr))->value(val); FLunlock(); outable[j] = table[k]; } return OK; } static int fl_slider_bank2_setVal(CSOUND *csound, FLSLDBNK_SET *p) { FUNC* ftp; MYFLT *table, *outable; int numslid = (int)*p->numSlid; int startInd = (int)*p->startInd; int startSlid = (int)*p->startSlid; WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); if (LIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) != NULL)) table = ftp->ftable; else { return csound->InitError(csound, Str("FLsldBnkSet: invalid table number")); } // *startInd, *startSlid, *numSlid if (UNLIKELY((int) ftp->flen < startInd + numslid)) { return csound->InitError(csound, Str("FLslidBnkSet: table too short!")); } FLSLIDERBANK2 *q = (FLSLIDERBANK2 *)widgetGlobals->AddrSetValue[ (int) *p->ihandle].opcode; if (LIKELY((ftp = csound->FTnp2Find(csound, q->ioutable)) != NULL)) outable = ftp->ftable; else { return csound->InitError(csound, Str("FLsldBnkSet: invalid outable number")); } if (numslid == 0) numslid = (int)(q->elements - *p->startSlid); if (UNLIKELY( q->elements > startSlid + numslid)) { return csound->InitError(csound, Str("FLslidBnkSet: too many sliders to reset!")); } for (int j = startSlid, k = startInd; j< numslid + startSlid; j++, k++) { MYFLT val = 0; // MYFLT base = q->slider_data[j].base; int iexp = q->slider_data[j].exp; MYFLT min = q->slider_data[j].min; MYFLT max = q->slider_data[j].max; switch (iexp) { case LIN_: //linear val = table[k]; if (val > max) val = max; else if (val < min) val = min; break; case EXP_ : //exponential { MYFLT range = max - min; MYFLT base2 = pow(max / min, 1/range); val = (log(table[k]/min) / log(base2)); } break; default: // table { // val = table[k]; if (UNLIKELY(val < 0 || val > 1)) { // input range must be 0 to 1 csound->PerfError(csound, p->h.insdshead, Str("FLslidBnk2Setk: value out of range: " "function mapping requires a 0 to 1 " "range for input")); } } //{ // initerror("FLslidBnkSet: function mapping not available"); // return; //} } FLlock(); ((Fl_Slider*) (q->slider_data[j].widget_addr))->value(val); FLunlock(); outable[j] = table[k]; } return OK; } static int fl_slider_bank2_setVal_k_set(CSOUND *csound, FLSLDBNK2_SETK *p) { FUNC* ftp; p->numslid = (int)*p->numSlid; p->startind = (int)*p->startInd; p->startslid = (int)*p->startSlid; WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); if (LIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) != NULL)) p->table = ftp->ftable; else { return csound->InitError(csound, Str("FLsldBnkSetk: invalid table number")); } // *startInd, *startSlid, *numSlid if (UNLIKELY( (int) ftp->flen < p->startind + p->numslid)) { return csound->InitError(csound, Str("FLslidBnkSetk: table too short!")); } p->q = (FLSLIDERBANK2 *) widgetGlobals->AddrSetValue[ (int) *p->ihandle].opcode; if (LIKELY((ftp = csound->FTnp2Find(csound, p->q->ioutable)) != NULL)) p->outable = ftp->ftable; else { return csound->InitError(csound, Str("FLsldBnkSetk: invalid outable number")); } if (p->numslid == 0) p->numslid = p->q->elements - p->startslid; if (UNLIKELY( p->q->elements < p->startslid + p->numslid)) { return csound->InitError(csound, Str("FLslidBnkSetk: too many sliders to reset!")); } return OK; } static int fl_slider_bank2_setVal_k(CSOUND *csound, FLSLDBNK2_SETK *p) { //WIDGET_GLOBALS *widgetGlobals = // (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); if(*p->kflag) { FLSLIDERBANK2 *q = p->q; MYFLT *table=p->table; for (int j = p->startslid, k = p->startind; j< p->numslid + p->startslid; j++, k++) { MYFLT val = 0; // MYFLT base= q->slider_data[j].base; int iexp = q->slider_data[j].exp; MYFLT min = q->slider_data[j].min; MYFLT max = q->slider_data[j].max; switch (iexp) { case LIN_: //linear val = table[k]; if (val > max) val = max; else if (val < min) val = min; break; case EXP_ : //exponential { MYFLT range = max - min; MYFLT base2 = pow(max / min, 1/range); val = (log(table[k]/min) / log(base2)); } break; default: // table { val = table[k]; if (UNLIKELY(val < 0 || val > 1)) { // input range must be 0 to 1 csound->PerfError(csound, p->h.insdshead, Str("FLslidBnk2Setk: value out of range:" " function mapping requires a 0 to 1" " range for input")); } } } if (val != p->oldValues[j]) { FLlock(); ((Fl_Slider*) (q->slider_data[j].widget_addr))->value(val); ((Fl_Slider*) (q->slider_data[j].widget_addr))->do_callback(); FLunlock(); p->oldValues[j] = val; } } } return OK; } static int fl_slider_bank_setVal_k_set(CSOUND *csound, FLSLDBNK_SETK *p) { FUNC* ftp; WIDGET_GLOBALS *widgetGlobals = (WIDGET_GLOBALS *)csound->QueryGlobalVariable(csound, "WIDGET_GLOBALS"); p->numslid = (int)*p->numSlid; p->startind = (int)*p->startInd; p->startslid = (int)*p->startSlid; if (LIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) != NULL)) p->table = ftp->ftable; else { return csound->InitError(csound, Str("FLslidBnkSetk: invalid table number")); } // *startInd, *startSlid, *numSlid if (UNLIKELY( (int) ftp->flen < p->startind + p->numslid)) { return csound->InitError(csound, Str("FLslidBnkSetk: table too short!")); } p->q = (FLSLIDERBANK *) widgetGlobals->AddrSetValue[ (int) *p->ihandle].opcode; if (LIKELY((ftp = csound->FTnp2Find(csound, p->q->ioutable)) != NULL)) p->outable = ftp->ftable; else { return csound->InitError(csound, Str("FLslidBnkSetk: invalid outable number")); } if (p->numslid == 0) p->numslid = p->q->elements - p->startslid; if (UNLIKELY( p->q->elements < p->startslid + p->numslid)) { return csound->InitError(csound, Str("FLslidBnkSetk:" " too many sliders to reset!")); } return OK; } static int fl_slider_bank_setVal_k(CSOUND *csound, FLSLDBNK_SETK *p) { if (*p->kflag) { FLSLIDERBANK *q = p->q; MYFLT *table=p->table; for (int j = p->startslid, k = p->startind; j< p->numslid + p->startslid; j++, k++) { MYFLT val = 0; // MYFLT base= q->slider_data[j].base; //Not used int iexp = q->slider_data[j].exp; MYFLT min = q->slider_data[j].min; MYFLT max = q->slider_data[j].max; switch (iexp) { case LIN_: //linear val = table[k]; if (val > max) val = max; else if (val < min) val = min; break; case EXP_ : //exponential { MYFLT range = max - min; MYFLT base2 = pow(max / min, 1/range); val = (log(table[k]/min) / log(base2)); } break; default: // table { val = table[k]; if (UNLIKELY(val < 0 || val > 1)) { // input range must be 0 to 1 csound->PerfError(csound, p->h.insdshead, Str("FLslidBnk2Setk: value out of range: " "function mapping requires a 0 to 1 range " "for input")); } } } if (val != p->oldValues[j]) { FLlock(); ((Fl_Slider*) (q->slider_data[j].widget_addr))->value(val); ((Fl_Slider*) (q->slider_data[j].widget_addr))->do_callback(); FLunlock(); p->oldValues[j] = val; } } } return OK; } static int FLxyin_set(CSOUND *csound, FLXYIN *p) { *p->koutx = *p->ioutx; //initial values *p->kouty = *p->iouty; p->rangex = *p->ioutx_max - *p->ioutx_min; p->rangey = *p->iouty_max - *p->iouty_min; switch((int) *p->iexpx) { case 0: // LIN p->expx = LIN_; break; case -1: // EXP p->expx = EXP_; if (UNLIKELY(*p->ioutx_min == 0 || *p->ioutx_max==0)) return csound->InitError(csound, Str("FLxyin: none of X limits can be zero in" " exponential mode!")); p->basex = pow((double) (*p->ioutx_max / *p->ioutx_min), (double) (1/p->rangex)); break; default: // TABLE p->expx = (int) *p->iexpx; { FUNC *ftp; MYFLT fnum = abs(p->expx); if ((ftp = csound->FTnp2Find(csound, &fnum)) != NULL) { p->tablex = ftp->ftable; p->tablenx = ftp->flen; } else return NOTOK; } } switch((int) *p->iexpy) { case 0: // LIN p->expy = LIN_; break; case -1: // EXP p->expy = EXP_; if (UNLIKELY(*p->iouty_min == 0 || *p->iouty_max==0)) return csound->InitError(csound, Str("FLxyin: none of Y limits can " "be zero in exponential mode!")); p->basey = pow((double) (*p->iouty_max / *p->iouty_min), (double) (1/p->rangey)); break; default: // TABLE p->expy = (int) *p->iexpy; { FUNC *ftp; MYFLT fnum = abs(p->expy); if ((ftp = csound->FTnp2Find(csound, &fnum)) != NULL) { p->tabley = ftp->ftable; p->tableny = ftp->flen; } else return NOTOK; } } return OK; } static int FLxyin(CSOUND *csound, FLXYIN *p) { int windx_min = (int)*p->iwindx_min, windx_max = (int)*p->iwindx_max; int windy_min = (int)*p->iwindy_min, windy_max = (int)*p->iwindy_max; MYFLT outx_min = *p->ioutx_min, outy_min = *p->iouty_min; MYFLT x=Fl::event_x(); MYFLT y=Fl::event_y(); *p->kinside = 1; if (x< windx_min) { x = windx_min; *p->kinside = 0; } else if (x > windx_max) { x = windx_max; *p->kinside = 0; } if (y< windy_min) { y = windy_min; *p->kinside = 0; } else if (y > windy_max) { y = windy_max; *p->kinside = 0; } MYFLT xx = x - windx_min; xx /= windx_max - windx_min; MYFLT yy = windy_max - y; yy /= windy_max - windy_min; switch (p->expx) { case LIN_: *p->koutx = outx_min + xx * p->rangex; break; case EXP_: *p->koutx = outx_min * pow (p->basex, xx * p->rangex); break; default: // TABLE if (p->expx > 0) { //interpolated MYFLT ndx = xx * (p->tablenx-1); int index = (int) ndx; MYFLT v1 = p->tablex[index]; *p->koutx = outx_min + ( v1 + (p->tablex[index+1] - v1) * (ndx - index)) * p->rangex; } else // non-interpolated *p->koutx = outx_min + p->tablex[(int) (xx*p->tablenx)] * p->rangex; } switch (p->expy) { case LIN_: *p->kouty = outy_min + yy * p->rangey; break; case EXP_: *p->kouty = outy_min * pow (p->basey, yy * p->rangey); break; default: // TABLE if (p->expy > 0) { //interpolated MYFLT ndx = yy * (p->tableny-1); int index = (int) ndx; MYFLT v1 = p->tabley[index]; *p->kouty = outy_min + ( v1 + ( p->tabley[index+1] - v1) * (ndx - index)) * p->rangey; } else // non-interpolated *p->kouty = outy_min + p->tabley[(int) (yy*p->tableny)] * p->rangey; } return OK; } // //FIXME: Should this be defined to 0dbfs? // #define MAXAMPVU 32767 // // //TODO: Implement FLTK meter // void VuMeter(CSOUND *csound); // // static int VuMeter_set(CSOUND *csound, FLTKMETER *p) { // //isVumeterActive = 1; // csoundSetVuMeterCallback(csound, VuMeter); // //OPARMS *O = csound->oparms; // int nchnls = csound->nchnls; // Fl_Window *o; // int iw; // iw = (csound->oparms->sfread) ? 30 : 15; // o = new Fl_Window(0,0, 410,nchnls * iw+35, "Meter"); // Fl_Box *box = new Fl_Box(10,3,260,10,"Outputs"); // box->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); // //else o = new Fl_Panel(x,y,width,height, panelName); // //o->box((Fl_Boxtype) borderType); // o->resizable(o); // o->callback(flpanel_cb); // //o->set_modal(); // widget_attributes(csound,o); // // PANELS panel(o, (widgetGlobals->stack_count>0) ? 1 : 0); // widgetGlobals->fl_windows.push_back(panel); // int j; // // for ( j = 0; j < nchnls; j++) { // string stemp; // char s[10]; // stemp = itoa(j+1,s,10); // char *Name = new char[stemp.size()+2]; // strcpy(Name,stemp.c_str()); // widgetGlobals->allocatedStrings.push_back(Name); // // Fl_Slider *w = new Fl_Slider(20, 18+15*j, 380, 10, Name); // w->align(FL_ALIGN_LEFT); // p->widg_address[j] = (unsigned long) w; // w->type(FL_HOR_FILL_SLIDER); // w->color(FL_BACKGROUND_COLOR,FL_GREEN); // w->box(FL_PLASTIC_DOWN_BOX); // w->range(0,MAXAMPVU); // } // // if (csound->oparms->sfread) { // box = new Fl_Box(10,18 + 15 * nchnls ,260,10,"Inputs"); // box->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); // for ( ; j < nchnls*2; j++) { // string stemp; // char s[10]; // stemp = itoa(j+1- nchnls,s,10); // char *Name = new char[stemp.size()+2]; // strcpy(Name,stemp.c_str()); // widgetGlobals->allocatedStrings.push_back(Name); // Fl_Slider *w = new Fl_Slider(20, 30+15*j , 380, 10, Name); // w->align(FL_ALIGN_LEFT); // p->widg_address[j] = (unsigned long) w; // w->type(FL_HOR_FILL_SLIDER); // w->color(FL_BACKGROUND_COLOR,FL_YELLOW); // w->box(FL_PLASTIC_DOWN_BOX); // w->range(0,MAXAMPVU); // } // } // o->end(); // widgetGlobals->p_vumeter = p; // p->dummycycles = csound->ekr / 16 ; // p->dummycyc = 0; // return OK; // } // // //extern "C" MYFLT *spout,*spin; //GAB // // void VuMeter(CSOUND *csound){ // FLTKMETER *p = widgetGlobals->p_vumeter; // Fl_Slider *w; // int nchnls = csound->nchnls; // int n = (csound->oparms->sfread) ? nchnls * 2 : nchnls; // MYFLT temp[MAXCHNLS]; // int smps = csound->GetKsmps(csound); // MYFLT max[MAXCHNLS]; // MYFLT *spo = csound->spout; // MYFLT *spi = csound->spin; // // static int overfl[MAXCHNLS]; // int i; // for (i=0;i max[i] ) // max[i]= temp[i]; // } // if (csound->oparms->sfread) { // for ( ; i max[i] ) // max[i]= temp[i]; // } // } // //if ((temp= (MYFLT) fabs(*a++)) > max) max = temp; // } while (--smps); // // for (i=0; i p->max[i]) // p->max[i] = (overfl[i] = max[i]>MAXAMPVU) ? MAXAMPVU : max[i]; // } // p->dummycyc++; // if (!(p->dummycyc % p->dummycycles)) { // for (int j=0; jwidg_address[j]; // // FLlock(); // if (overfl[j]) { // w->selection_color(FL_RED); // overfl[j] = 0; // } // else { // if (j < nchnls) w->selection_color(FL_GREEN); // else w->selection_color(FL_YELLOW); // } // w->value( p->max[j]); // w->do_callback(w); // FLunlock(); // } // #ifdef WIN32 // // PostMessage(callback_target,0,0,0); // #endif // for (i=0; imax[i] = 0; // } // } // } // extern "C" #define S(x) sizeof(x) const OENTRY widgetOpcodes_[] = { { (char*)"FLslider", S(FLSLIDER), 0, 1, (char*)"ki", (char*)"Siijjjjjjj", (SUBR) fl_slider, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLslidBnk", S(FLSLIDERBANK), 0, 1, (char*)"", (char*)"Siooooooooo", (SUBR) fl_slider_bank_S, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLslidBnk.i", S(FLSLIDERBANK), 0, 1, (char*)"", (char*)"iiooooooooo", (SUBR) fl_slider_bank, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLknob", S(FLKNOB), 0, 1, (char*)"ki", (char*)"Siijjjjjjo", (SUBR) fl_knob, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLroller", S(FLROLLER), 0, 1, (char*)"ki", (char*)"Siijjjjjjjj", (SUBR) fl_roller, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLtext", S(FLTEXT), 0, 1, (char*)"ki", (char*)"Siijjjjjj", (SUBR) fl_text, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLjoy", S(FLJOYSTICK), 0, 1, (char*)"kkii", (char*)"Siiiijjjjjjjj", (SUBR) fl_joystick, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLcount", S(FLCOUNTER), 0, 1, (char*)"ki", (char*)"Siiiiiiiiiz", (SUBR) fl_counter, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLbutton", S(FLBUTTON), 0, 1, (char*)"ki", (char*)"Siiiiiiiz", (SUBR) fl_button, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLbutBank", S(FLBUTTONBANK), 0, 1, (char*)"ki", (char*)"iiiiiiiz", (SUBR) fl_button_bank, (SUBR) NULL, (SUBR) NULL }, // { (char*)"FLkeyb", S(FLKEYB), 0, 1, (char*)"k", (char*)"z", // (SUBR) FLkeyb, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLcolor", S(FLWIDGCOL), 0, 1, (char*)"", (char*)"jjjjjj", (SUBR) fl_widget_color, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLcolor2", S(FLWIDGCOL2), 0, 1, (char*)"", (char*)"jjj", (SUBR) fl_widget_color2, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLlabel", S(FLWIDGLABEL), 0, 1, (char*)"", (char*)"ojojjj", (SUBR) fl_widget_label, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLsetVal_i", S(FL_SET_WIDGET_VALUE_I), 0, 1, (char*)"", (char*)"ii", (SUBR) fl_setWidgetValuei, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLsetVali", S(FL_SET_WIDGET_VALUE_I), 0, 1, (char*)"", (char*)"ii", (SUBR) fl_setWidgetValuei, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLsetVal", S(FL_SET_WIDGET_VALUE),0, 3, (char*)"", (char*)"kki", (SUBR) fl_setWidgetValue_set, (SUBR) fl_setWidgetValue, (SUBR) NULL }, { (char*)"FLsetColor", S(FL_SET_COLOR), 0, 1, (char*)"", (char*)"iiii", (SUBR) fl_setColor1, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLsetColor2", S(FL_SET_COLOR), 0, 1, (char*)"", (char*)"iiii", (SUBR) fl_setColor2, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLsetTextSize", S(FL_SET_TEXTSIZE), 0, 1, (char*)"", (char*)"ii", (SUBR) fl_setTextSize, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLsetTextColor", S(FL_SET_COLOR), 0, 1, (char*)"", (char*)"iiii", (SUBR) fl_setTextColor, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLsetFont", S(FL_SET_FONT), 0, 1, (char*)"", (char*)"ii", (SUBR) fl_setFont, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLsetTextType", S(FL_SET_FONT), 0, 1, (char*)"", (char*)"ii", (SUBR) fl_setTextType, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLsetText", S(FL_SET_TEXT), 0, 1, (char*)"", (char*)"Si", (SUBR) fl_setText, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLsetText", S(FL_SET_TEXTi), 0, 1, (char*)"", (char*)"ii", (SUBR) fl_setTexti, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLsetSize", S(FL_SET_SIZE), 0, 1, (char*)"", (char*)"iii", (SUBR) fl_setSize, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLsetPosition", S(FL_SET_POSITION), 0, 1, (char*)"", (char*)"iii", (SUBR) fl_setPosition, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLhide", S(FL_WIDHIDE), 0, 1, (char*)"", (char*)"i", (SUBR) fl_hide, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLshow", S(FL_WIDSHOW), 0, 1, (char*)"", (char*)"i", (SUBR) fl_show, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLsetBox", S(FL_SETBOX), 0, 1, (char*)"", (char*)"ii", (SUBR) fl_setBox, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLsetAlign", S(FL_TALIGN), 0, 1, (char*)"", (char*)"ii", (SUBR) fl_align, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLbox", S(FL_BOX), 0, 1, (char*)"i", (char*)"Siiiiiii", (SUBR) fl_box_s, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLbox", S(FL_BOX), 0, 1, (char*)"i", (char*)"iiiiiiii", (SUBR) fl_box_i, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLvalue", S(FLVALUE), 0, 1, (char*)"i", (char*)"Sjjjj", (SUBR) fl_value, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLpanel", S(FLPANEL), 0, 1, (char*)"", (char*)"Sjjjoooo", (SUBR) StartPanel, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLpanelEnd", S(FLPANELEND), 0, 1, (char*)"", (char*)"", (SUBR) EndPanel, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLpanel_end", S(FLPANELEND), 0, 1, (char*)"", (char*)"", (SUBR) EndPanel, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLscroll", S(FLSCROLL), 0, 1, (char*)"", (char*)"iiii", (SUBR) StartScroll, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLscrollEnd", S(FLSCROLLEND), 0, 1, (char*)"", (char*)"", (SUBR) EndScroll, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLscroll_end",S(FLSCROLLEND), 0, 1, (char*)"", (char*)"", (SUBR) EndScroll, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLpack", S(FLPACK), 0, 1, (char*)"", (char*)"iiiiooo", (SUBR) StartPack, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLpackEnd", S(FLPACKEND), 0, 1, (char*)"", (char*)"", (SUBR) EndPack, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLpack_end", S(FLPACKEND), 0, 1, (char*)"", (char*)"", (SUBR) EndPack, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLtabs", S(FLTABS), 0, 1, (char*)"", (char*)"iiii", (SUBR) StartTabs, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLtabsEnd", S(FLTABSEND), 0, 1, (char*)"", (char*)"", (SUBR) EndTabs, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLtabs_end", S(FLTABSEND), 0, 1, (char*)"", (char*)"", (SUBR) EndTabs, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLgroup", S(FLGROUP), 0, 1, (char*)"", (char*)"Siiiij", (SUBR) StartGroup, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLgroupEnd", S(FLGROUPEND), 0, 1, (char*)"", (char*)"", (SUBR) EndGroup, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLgroup_end", S(FLGROUPEND), 0, 1, (char*)"", (char*)"", (SUBR) EndGroup, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLsetsnap", S(FLSETSNAP), 0, 1, (char*)"ii", (char*)"ioo", (SUBR) set_snap, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLsetSnapGroup", S(FLSETSNAPGROUP), 0, 1, (char*)"", (char*)"i", (SUBR)fl_setSnapGroup, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLgetsnap", S(FLGETSNAP), 0, 1, (char*)"i", (char*)"io", (SUBR) get_snap, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLsavesnap", S(FLSAVESNAPS), 0, 1, (char*)"", (char*)"So", (SUBR) save_snap, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLloadsnap", S(FLLOADSNAPS), 0, 1, (char*)"", (char*)"So", (SUBR) load_snap, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLrun", S(FLRUN), 0, 1, (char*)"", (char*)"", (SUBR) FL_run, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLupdate", S(FLRUN), 0, 1, (char*)"", (char*)"", (SUBR) fl_update, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLprintk", S(FLPRINTK), 0, 3, (char*)"", (char*)"iki", (SUBR) FLprintkset, (SUBR) FLprintk, (SUBR) NULL }, { (char*)"FLprintk2", S(FLPRINTK2), 0, 3, (char*)"", (char*)"ki", (SUBR) FLprintk2set, (SUBR) FLprintk2, (SUBR) NULL }, { (char*)"FLcloseButton", S(FLCLOSEBUTTON), 0, 1, (char*)"i", (char*)"Siiii", (SUBR) fl_close_button, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLexecButton", S(FLEXECBUTTON), 0, 1, (char*)"i", (char*)"Siiii", (SUBR) fl_exec_button, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLkeyIn", S(FLKEYIN), 0, 3, (char*)"k", (char*)"o", (SUBR)fl_keyin_set, (SUBR)fl_keyin, (SUBR) NULL }, { (char*)"FLxyin", S(FLXYIN), 0, 3, (char*)"kkk",(char*)"iiiiiiiioooo", (SUBR)FLxyin_set, (SUBR)FLxyin, (SUBR) NULL }, { (char*)"FLmouse", S(FLMOUSE), 0, 3, (char*)"kkkkk",(char*)"o", (SUBR)fl_mouse_set, (SUBR)fl_mouse, (SUBR) NULL }, { (char*)"FLvslidBnk", S(FLSLIDERBANK), 0, 1, (char*)"", (char*)"Siooooooooo", (SUBR)fl_vertical_slider_bank_S, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLvslidBnk.i", S(FLSLIDERBANK), 0, 1, (char*)"", (char*)"iiooooooooo", (SUBR)fl_vertical_slider_bank, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLslidBnk2", S(FLSLIDERBANK2),0, 1, (char*)"", (char*)"Siiiooooo", (SUBR)fl_slider_bank2_S , (SUBR) NULL, (SUBR) NULL }, { (char*)"FLslidBnk2.i", S(FLSLIDERBANK2),0, 1, (char*)"", (char*)"iiiiooooo", (SUBR)fl_slider_bank2 , (SUBR) NULL, (SUBR) NULL }, { (char*)"FLvslidBnk2", S(FLSLIDERBANK2),0, 1, (char*)"", (char*)"Siiiooooo", (SUBR)fl_vertical_slider_bank2_S, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLvslidBnk2.i", S(FLSLIDERBANK2),0, 1, (char*)"", (char*)"iiiiooooo", (SUBR)fl_vertical_slider_bank2, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLslidBnkGetHandle",S(FLSLDBNK_GETHANDLE),0, 1, (char*)"i", (char*)"", (SUBR)fl_slider_bank_getHandle, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLslidBnkSet",S(FLSLDBNK_SET), 0, 1, (char*)"", (char*)"iiooo", (SUBR)fl_slider_bank_setVal, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLslidBnkSetk", S(FLSLDBNK2_SETK), 0, 3, (char*)"", (char*)"kiiooo", (SUBR)fl_slider_bank_setVal_k_set,(SUBR)fl_slider_bank_setVal_k,(SUBR) NULL }, { (char*)"FLslidBnk2Set", S(FLSLDBNK_SET), 0, 1, (char*)"", (char*)"iiooo", (SUBR)fl_slider_bank2_setVal, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLslidBnk2Setk", S(FLSLDBNK2_SETK), 0, 3, (char*)"", (char*)"kiiooo", (SUBR)fl_slider_bank2_setVal_k_set, (SUBR)fl_slider_bank2_setVal_k, (SUBR) NULL }, { (char*)"FLhvsBox", S(FL_HVSBOX), 0, 1, (char*)"i", (char*)"iiiiiio", (SUBR)fl_hvsbox, (SUBR) NULL, (SUBR) NULL }, { (char*)"FLhvsBoxSetValue",S(FL_SET_HVS_VALUE), 0, 3, (char*)"", (char*)"kki", (SUBR)fl_setHvsValue_set, (SUBR)fl_setHvsValue, (SUBR) NULL }, // { (char*)"FLmeter", S(FLTKMETER), 0, 1, (char*)"", (char*)"", // (SUBR)VuMeter_set, (SUBR) NULL, (SUBR) NULL }, { NULL, 0, 0, 0, NULL, NULL, (SUBR) NULL, (SUBR) NULL, (SUBR) NULL } }; csound-6.10.0/InOut/widgets.h000066400000000000000000000360761321653344700157720ustar00rootroot00000000000000/* widgets.h: Copyright (C) 2002 Gabriel Maldonado This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef CSOUND_WIDGETS_H #define CSOUND_WIDGETS_H #ifdef __cplusplus extern "C" { #endif typedef struct { OPDS h; MYFLT *kout, *ihandle; STRINGDAT *name; MYFLT *imin, *imax, *iexp; MYFLT *itype, *idisp, *iwidth, *iheight, *ix, *iy; MYFLT min, base, *table; long tablen; } FLSLIDER; #define MAXSLIDERBANK 128 typedef struct { void *widget_addr; //gab MYFLT min, max, *out; MYFLT base, *table; long tablen; int exp; } SLDBK_ELEMENT; // --------------------------------------------------------------------- typedef struct { OPDS h; MYFLT *names; MYFLT *inumsliders, *ioutable, *iwidth, *iheight; MYFLT *ix, *iy, *itypetable, *iexptable, *ioutablestart_ndx; MYFLT *iminmaxtable; SLDBK_ELEMENT slider_data[MAXSLIDERBANK]; long elements; } FLSLIDERBANK; typedef struct { OPDS h; MYFLT *names; MYFLT *inumsliders, *ioutable, *iconfigtable, *iwidth, *iheight, *ix, *iy, *ioutablestart_ndx; SLDBK_ELEMENT slider_data[MAXSLIDERBANK]; long elements; } FLSLIDERBANK2; //gab // typedef struct { // OPDS h; // MYFLT *kout, *args[PMAX+1]; // } FLKEYB; typedef struct { OPDS h; MYFLT *kvalue, *ihandle; } FLBUTTONCALL; typedef struct { OPDS h; MYFLT *koutx, *kouty, *ihandle1, *ihandle2; STRINGDAT *name; MYFLT *iminx, *imaxx, *iminy, *imaxy; MYFLT *iexpx, *iexpy, *idispx, *idispy, *iwidth, *iheight, *ix, *iy; MYFLT basex, basey, *tablex, *tabley; long tablenx, tableny; } FLJOYSTICK; typedef struct { OPDS h; MYFLT *kout, *ihandle; STRINGDAT *name; MYFLT *imin, *imax, *istep, *iexp; MYFLT *itype, *idisp, *iwidth, *iheight, *ix, *iy; MYFLT min, base, *table; long tablen; } FLROLLER; typedef struct { OPDS h; MYFLT *kout, *ihandle; STRINGDAT *name; MYFLT *imin, *imax, *iexp, *itype; MYFLT *idisp, *iwidth, *ix, *iy, *icursorsize; MYFLT min, base, *table; long tablen; } FLKNOB; typedef struct { OPDS h; MYFLT *kout, *ihandle; STRINGDAT *name; MYFLT *imin, *imax, *istep, *itype; MYFLT *iwidth, *iheight, *ix, *iy; } FLTEXT; // --------------------------------------------------------------------- typedef struct { OPDS h; MYFLT *red1, *green1, *blue1, *red2, *green2, *blue2; } FLWIDGCOL; typedef struct { OPDS h; MYFLT *red, *green, *blue; } FLWIDGCOL2; typedef struct { OPDS h; MYFLT *size, *font, *align, *red, *green, *blue; } FLWIDGLABEL; // --------------------------------------------------------------------- typedef struct { OPDS h; MYFLT *ivalue, *ihandle; } FL_SET_WIDGET_VALUE_I; typedef struct { OPDS h; MYFLT *ktrig, *kvalue, *ihandle; int handle; int widgetType; MYFLT log_base; } FL_SET_WIDGET_VALUE; typedef struct { OPDS h; MYFLT *red, *green, *blue, *ihandle; } FL_SET_COLOR; typedef struct { OPDS h; MYFLT *ivalue, *ihandle; } FL_SET_TEXTSIZE; typedef struct { OPDS h; MYFLT *itype, *ihandle; } FL_SET_FONT; typedef struct { OPDS h; STRINGDAT *itext; MYFLT *ihandle; } FL_SET_TEXT; typedef struct { OPDS h; MYFLT *ndx; MYFLT *ihandle; } FL_SET_TEXTi; typedef struct { OPDS h; MYFLT *itype, *ihandle; } FL_TALIGN; typedef struct { OPDS h; MYFLT *iwidth, *iheight, *ihandle; } FL_SET_SIZE; typedef struct { OPDS h; MYFLT *ix, *iy, *ihandle; } FL_SET_POSITION; typedef struct { OPDS h; MYFLT *ihandle; } FL_WIDHIDE; typedef struct { OPDS h; MYFLT *ihandle; } FL_WIDSHOW; typedef struct { OPDS h; MYFLT *itype, *ihandle; } FL_SETBOX; typedef struct { OPDS h; MYFLT *ihandle; STRINGDAT *itext; MYFLT *itype, *ifont, *isize; MYFLT *iwidth, *iheight, *ix, *iy; } FL_BOX; // --------------------------------------------------------------------- typedef struct { OPDS h; MYFLT *ihandle; STRINGDAT *name; MYFLT *iwidth, *iheight, *ix, *iy; } FLVALUE; typedef struct { OPDS h; } FLRUN; typedef struct { OPDS h; STRINGDAT *name; MYFLT *iwidth, *iheight, *ix, *iy, *border, *ikbdsense, *iclose; } FLPANEL; typedef struct { OPDS h; MYFLT *inum_snap, *inum_val, *index, *ifn, *group; } FLSETSNAP; typedef struct { OPDS h; MYFLT *inum_el, *index, *group; } FLGETSNAP; typedef struct { OPDS h; STRINGDAT *filename; MYFLT *group; } FLSAVESNAPS; typedef struct { OPDS h; STRINGDAT *filename; MYFLT *group; } FLLOADSNAPS; typedef struct { OPDS h; } FLPANELEND; typedef struct { OPDS h; MYFLT *iwidth, *iheight, *ix, *iy; } FLSCROLL; typedef struct { OPDS h; } FLSCROLLEND; typedef struct { OPDS h; MYFLT *iwidth, *iheight, *ix, *iy; } FLTABS; typedef struct { OPDS h; } FLTABSEND; typedef struct { OPDS h; STRINGDAT *name; MYFLT *iwidth, *iheight, *ix, *iy, *border; } FLGROUP; typedef struct { OPDS h; } FLGROUPEND; typedef struct { OPDS h; MYFLT *iwidth, *iheight, *ix, *iy, *itype, *ispace, *iborder; } FLPACK; typedef struct { OPDS h; } FLPACKEND; typedef struct { OPDS h; MYFLT *kout, *ihandle; STRINGDAT *name; MYFLT *ion, *ioff, *itype; MYFLT *iwidth, *iheight, *ix, *iy, *args[PMAX]; } FLBUTTON; typedef struct { OPDS h; MYFLT *kout, *ihandle; /* outs */ MYFLT *itype, *inumx, *inumy, *iwidth, *iheight, *ix, *iy, *args[PMAX]; } FLBUTTONBANK; typedef struct { OPDS h; MYFLT *kout, *ihandle; STRINGDAT *name; MYFLT *imin, *imax, *istep1, *istep2, *itype; MYFLT *iwidth, *iheight, *ix, *iy, *args[PMAX]; } FLCOUNTER; typedef struct { OPDS h; MYFLT *ptime, *val, *idisp; MYFLT initime, ctime; long cysofar; } FLPRINTK; typedef struct { OPDS h; MYFLT *val, *idisp; MYFLT oldvalue; /* int pspace; */ } FLPRINTK2; typedef struct { OPDS h; MYFLT *ihandle; STRINGDAT *name; MYFLT *iwidth, *iheight, *ix, *iy; } FLCLOSEBUTTON; typedef struct { OPDS h; MYFLT *ihandle; STRINGDAT *command; MYFLT *iwidth, *iheight, *ix, *iy; char *commandString; CSOUND *csound; } FLEXECBUTTON; #ifdef __cplusplus } #endif #if defined(CSOUND_WIDGETS_CPP) /* ---- IV - Aug 23 2002 ---- included file: Fl_Ball.H */ class Fl_Ball : public Fl_Valuator { private: CSOUND *csound; int ix, iy, drag; int spinning; int ballstacks, ballslices; float ballsize; float curquat[4]; float lastquat[4]; float mat[4][4]; char soft_; uchar mouseobj; static PUBLIC void repeat_callback(void *); PUBLIC void increment_cb(); PUBLIC void vertex_by_matrix(float &x, float &y, float &z); PUBLIC void transform_ball_vertex(float &x, float &y, float &z); PUBLIC void rotate(float &x, float &y, float &z, float rotx=0.0f, float roty=0.0f, float rotz=0.0f); PUBLIC void draw_solid_ball(float radius, int slices, int stacks); PUBLIC void draw_wire_ball(float radius, int slices, int stacks); public: PUBLIC void draw(); PUBLIC void handle_drag(double v=0.0); PUBLIC void handle_release(); PUBLIC int handle(int); PUBLIC Fl_Ball(CSOUND *cs, int x, int y, int w, int h, const char *l = 0); void soft(char x) {soft_ = x;} char soft() const {return soft_;} float ballscale() const {return ballsize;} void ballscale(float s) { ballsize=s;} void rotateball(float rotx=0.0f, float roty=0.0f, float rotz=0.0f); void getrot(float &rotx, float &roty, float &rotz); void stacks(int s) { ballstacks=s; } int stacks() const { return ballstacks; } void slices(int s) { ballslices=s; } int slices() const { return ballslices; } ~Fl_Ball(); }; /* ---- IV - Aug 23 2002 ---- included file: Fl_Knob.H */ /* generated by Fast Light User Interface Designer (fluid) version 2.00 */ class Fl_Knob : public Fl_Valuator { public: enum Fl_Knobtype { DOTLIN=0, DOTLOG_1, DOTLOG_2, DOTLOG_3, LINELIN, LINELOG_1, LINELOG_2, LINELOG_3 }; private: CSOUND *csound; int _type; float _percent; int _scaleticks; short a1, a2; public: Fl_Knob(CSOUND *cs, int xx, int yy, int ww, int hh, const char *l=0); ~Fl_Knob(); private: void draw(); int handle(int event); public: void type(int ty); private: void shadow(const int offs, const uchar r, uchar g, uchar b); void draw_scale(const int ox, const int oy, const int side); void draw_cursor(const int ox, const int oy, const int side); public: void cursor(const int pc); void scaleticks(const int tck); }; /* ---- IV - Aug 23 2002 ---- included file: Fl_Spin.H */ class Fl_Spin : public Fl_Valuator { private: CSOUND * csound; int ix, iy, drag, indrag; int delta, deltadir; char soft_; uchar mouseobj; static PUBLIC void repeat_callback(void *); PUBLIC void increment_cb(); public: PUBLIC void draw(); PUBLIC int handle(int); PUBLIC Fl_Spin(CSOUND *cs, int x, int y, int w, int h, const char *l = 0); void soft(char x) {soft_ = x;} char soft() const {return soft_;} ~Fl_Spin(); }; /* ---- IV - Aug 23 2002 ---- included file: Fl_Value_Input_Spin.H */ class Fl_Value_Input_Spin : public Fl_Valuator { private: CSOUND * csound; int ix, iy, drag; int delta, deltadir; char soft_; uchar mouseobj; int butsize; static PUBLIC void input_cb(Fl_Widget*, void*); // cause damage() due to value() changing virtual PUBLIC void value_damage(); static PUBLIC void repeat_callback(void *); PUBLIC void increment_cb(); public: Fl_Input input; PUBLIC void draw(); PUBLIC int handle(int); PUBLIC void resize(int, int, int, int); PUBLIC Fl_Value_Input_Spin(CSOUND *csound, int x, int y, int w, int h, const char *l = 0); void soft(char x) {soft_ = x;} char soft() const {return soft_;} Fl_Font textfont() const {return input.textfont();} void textfont(uchar s) { input.textfont(s);} uchar textsize() const {return input.textsize();} void textsize(uchar s) {input.textsize(s);} Fl_Color textcolor() const {return input.textcolor();} void textcolor(uchar n) {input.textcolor(n);} Fl_Color cursor_color() const {return input.cursor_color();} void cursor_color(uchar n) {input.cursor_color(n);} int buttonssize() const {return butsize;} void buttonssize(int s) { butsize=s;} ~Fl_Value_Input_Spin(); }; /* ---- IV - Aug 23 2002 ---- included file: Fl_Value_Slider_Input.H */ class Fl_Value_Slider_Input : public Fl_Value_Slider { private: CSOUND *csound; char soft_; int txtboxsize; static PUBLIC void input_cb(Fl_Widget*, void*); // cause damage() due to value() changing virtual PUBLIC void value_damage(); public: Fl_Input input; PUBLIC void draw(); PUBLIC int handle(int); PUBLIC void resize(int, int, int, int); PUBLIC Fl_Value_Slider_Input(CSOUND * cs, int x, int y, int w, int h, const char *l = 0); void soft(char x) {soft_ = x;} char soft() const {return soft_;} Fl_Font textfont() const {return input.textfont();} void textfont(uchar s) { input.textfont(s);} uchar textsize() const {return input.textsize();} void textsize(uchar s) {input.textsize(s);} Fl_Color textcolor() const {return input.textcolor();} void textcolor(uchar n) {input.textcolor(n);} Fl_Color cursor_color() const {return input.cursor_color();} void cursor_color(uchar n) {input.cursor_color(n);} void textboxsize(int s) { txtboxsize=s;} int textboxsize() const {return txtboxsize;} }; // New widgets for Csound5.06 by Gabriel Maldonado // Ported by Andres Cabrera. This section below comes // from the file newwidgets.h typedef struct { OPDS h; MYFLT *ihandle; } FLSLDBNK_GETHANDLE; //gab typedef struct { OPDS h; MYFLT *ihandle, *ifn, *startInd, *startSlid, *numSlid; //int oldx, oly; } FLSLDBNK_SET; //gab typedef struct { OPDS h; MYFLT *kflag, *ihandle, *ifn, *startInd, *startSlid, *numSlid; MYFLT oldValues[MAXSLIDERBANK]; int numslid, startind, startslid; FLSLIDERBANK2 *q; MYFLT *table, *outable; //int oldx, oly; } FLSLDBNK2_SETK; typedef struct { OPDS h; MYFLT *kflag, *ihandle, *ifn, *startInd, *startSlid, *numSlid; MYFLT oldValues[MAXSLIDERBANK]; int numslid, startind, startslid; FLSLIDERBANK *q; MYFLT *table, *outable; //int oldx, oly; } FLSLDBNK_SETK; typedef struct { OPDS h; MYFLT *koutx, *kouty, *kinside; //outs MYFLT *ioutx_min, *ioutx_max, *iouty_min, *iouty_max, *iwindx_min, *iwindx_max, *iwindy_min, *iwindy_max, *iexpx, *iexpy, *ioutx, *iouty; //ins MYFLT oldx, oldy, *tablex, *tabley; int expx, expy; long tablenx, tableny; double rangex, rangey, basex, basey; //int pspace; } FLXYIN; //gab typedef struct { OPDS h; // MYFLT *ktrig, *kvalue, *ihandle; MYFLT *chan, *cc, *ihandle; int ccVal, oldCCval; MYFLT log_base, min, max, range; void *WidgAddress, *opcode, *addrSetVal; int exp, widg_type; } FL_MIDI_WIDGET_VALUE; typedef struct { OPDS h; MYFLT *kascii,*ifn;//, *ifnMap; MYFLT *table;//, *tableMap; int flag; } FLKEYIN; typedef struct { OPDS h; MYFLT *group; } FLSETSNAPGROUP; typedef struct { OPDS h; MYFLT *x,*y, *b1, *b2, *b3, *flagRaw; MYFLT height,width; } FLMOUSE; typedef struct { OPDS h; MYFLT *ihandle, *numlinesX, *numlinesY, *iwidth, *iheight, *ix, *iy,*image; int width, height; } FL_HVSBOX; typedef struct { OPDS h; MYFLT *kx, *ky, *ihandle; void *WidgAddress, *opcode; MYFLT old_x, old_y; } FL_SET_HVS_VALUE; typedef struct { OPDS h; MYFLT max[MAXCHNLS]; unsigned long widg_address[MAXCHNLS]; int dummycycles, dummycyc; } FLTKMETER; #endif /* CSOUND_WIDGETS_CPP */ #endif /* CSOUND_WIDGETS_H */ csound-6.10.0/InOut/widglobals.h000066400000000000000000000136671321653344700164540ustar00rootroot00000000000000#include #include #include #if defined(WIN32) # include #endif /* defined(WIN32) */ #if defined(LINUX) # include # include # include #endif /* defined(LINUX) */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; /* ** Undefine CS_VSTHOST to build FLTK without VST. */ #ifdef CS_VSTHOST #include "Opcodes/vst4cs/src/vsthost.h" #endif #include "csdl.h" #include "winFLTK.h" #ifdef CS_IMAGE # include "stdpch.h" # include "anydec.h" # include "anybmp.h" # include "imagestruct.h" #endif #define CSOUND_WIDGETS_CPP 1 #include "widgets.h" #define LIN_ (0) #define EXP_ (-1) #undef min #undef max typedef struct rtEvt_s { struct rtEvt_s *nxt; EVTBLK evt; } rtEvt_t; #ifndef NO_FLTK_THREADS typedef struct widgetsGlobals_s { rtEvt_t *eventQueue; void *mutex_; int exit_now; /* set by GUI when all windows are closed */ int end_of_perf; /* set by main thread at end of performance */ void *threadHandle; int fltkFlags; } widgetsGlobals_t; #endif struct ADDR { void *opcode; void *WidgAddress; }; struct ADDR_STACK { /*: ADDR*/ OPDS *h; void *WidgAddress; int count; ADDR_STACK(OPDS *new_h,void *new_address, int new_count) : h(new_h),WidgAddress(new_address), count(new_count) {} ADDR_STACK() { h=NULL; WidgAddress = NULL; count=0; } }; struct VALUATOR_FIELD { MYFLT value, value2; MYFLT min,max, min2,max2; int exp, exp2; string widg_name; string opcode_name; SLDBK_ELEMENT *sldbnk; private: vector sldbnkValues; public: VALUATOR_FIELD() { value = 0; value2 =0; widg_name= ""; opcode_name =""; min = 0; max =1; min2=0; max2=1; exp=LIN_; exp2=LIN_; sldbnk=0; } void set_sldbnk(int ndx, MYFLT val) { if (ndx >= (int)sldbnkValues.size()) { sldbnkValues.resize(ndx+1); } sldbnkValues[ndx]= val; } MYFLT get_sldbnk(int ndx) { return sldbnkValues[ndx]; } // ~VALUATOR_FIELD() { if (sldbnk != 0) delete sldbnk; // if (sldbnkValues !=0) delete sldbnkValues; } }; enum FL_ENUM {FL_WIDG=0, FL_JOY, JOY_X=128, JOY_Y }; //gab struct ADDR_SET_VALUE { /*: ADDR*/ int exponential; MYFLT min,max; void *WidgAddress, *opcode; FL_ENUM widg_type; //gab FL_ENUM joy; //gab int group; // group for snapshot groups ADDR_SET_VALUE(int new_exponential,MYFLT new_min, MYFLT new_max, void *new_WidgAddress, void *new_opcode, int grp = 0) : exponential(new_exponential),min(new_min), max(new_max), WidgAddress(new_WidgAddress),opcode(new_opcode), widg_type(FL_WIDG), joy(FL_JOY), group(grp) {} ADDR_SET_VALUE() { exponential=LIN_; min=0; max=0; WidgAddress=NULL; opcode=NULL; widg_type = FL_WIDG; group = 0; joy = FL_JOY; } }; struct PANELS { Fl_Window *panel; int is_subwindow; PANELS(Fl_Window *new_panel, int flag) : panel(new_panel), is_subwindow(flag) { } PANELS() { panel = NULL; is_subwindow=0; } }; struct SNAPSHOT { int is_empty; vector fields; SNAPSHOT(vector& valuators, int snapGroup = 0); SNAPSHOT() { is_empty = 1; } int get(vector& valuators, int snapGroup = 0); }; typedef vector SNAPVEC; //gab struct WIDGET_GLOBALS { WIDGET_GLOBALS(); ~WIDGET_GLOBALS() { fl_windows.resize(0); AddrStack.resize(0); //addresses of containers AddrSetValue.resize(0); //addresses of valuators for (int i = 0, n = allocatedStrings.size(); i < n; ++i) { delete[] allocatedStrings[i]; } allocatedStrings.resize(0); snapshots.resize(0); } char hack_o_rama1; // IV - Aug 23 2002 char hack_o_rama2; int ix, drag, indrag, sldrag; int stack_count; int FLcontrol_iheight; int FLroller_iheight; int FLcontrol_iwidth; int FLroller_iwidth; int FLvalue_iwidth; int FLcolor; int FLcolor2; int FLtext_size; int FLtext_color; int FLtext_font; int FLtext_align; int currentSnapGroup; // GAB for snapshot groups int last_KEY; // GAB bool isKeyDown; //GAB int FL_ix; int FL_iy; vector fl_windows; // all panels vector AddrStack; //addresses of containers vector AddrSetValue; //addresses of valuators vector allocatedStrings; int last_sldbnk; FL_MIDI_WIDGET_VALUE *midiFLaddress[16][128]; // gab128 cc * 16 midi channels int midiFLold_val[16][128]; //gab vector snapshots; vector::iterator snapshots_iterator; FLTKMETER *p_vumeter; #ifdef CS_IMAGE vector Bm_image; // map of pointers to CAnyBmp objects vector::iterator Bm_image_iterator; // iterator of the map #endif }; csound-6.10.0/InOut/winEPS.c000066400000000000000000000351661321653344700154630ustar00rootroot00000000000000/* winEPS.c: Copyright (C) 1995 Fabio P. Bertolotti This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* WINEPS.C */ #include "cwindow.h" #include /*-------------------------------------- winEPS.c --------------------------- * * Write Csound's graphics in PostScript format into a file for later viewing. * * * Fabio P. Bertolotti, * Dec 1995, * Rosdorf, Germany. * email: fabio@ts.go.dlr.de * * * * The PS output file is located in the same directory as the * sound file, and has the name of the sound file with the * extension ``.eps'' appended. * * On NeXT running Csnd, the sound file has the extension * ``.snd''. In this case, the PS file has the name of the * sound file, with the extension ``.eps'' substituting the * ``.snd'' extension. Such extension replacement also occurs * for output files ending in ``.aiff'', ``.au'' and ``.wav'' * * If sound output is being piped directly to the DAC, then * there is no PS output. * * * Each new graph is plotted on a fresh PostScript page * On each page we print the current date, the name of the * score file, the orchestra file, the maximum and minimum values * and the figure caption, as defined by Csound. * Both the vertical and horizontal axes are labeled (unlike * SGI and X11 window graphs, which have no labels). * * * If you improve this subroutine or the PostScript ``look'' of the * graphs, I would be grateful if you email me the improved version, * at: fabio@ts.go.dlr.de Thanks. * * --------------------------------------------------------------------------*/ #include #include #ifdef __MACH__ /* No idea why these are not declared */ extern struct tm * localtime(const time_t *); extern char * asctime(const struct tm *); #endif /** * Origin and size of PostScript plot */ #define MyPS_XORIG (FL(100.0)) #define MyPS_YORIG (FL(130.0)) #define MyPS_WIDTH (FL(450.0)) #define MyPS_HEIGHT (FL(400.0)) #define MyPS_FONT "/Times-Roman" #define MyPS_FONTSIZE (FL(20.0)) typedef struct winEPS_globals_ { FILE *psFile; void *psfd; /* CSFILE* returned by FileOpen2() */ char ps_date[40]; /* Print time & date on every plot */ int currentPage; /* Current page number */ } winEPS_globals_t; void PS_MakeGraph(CSOUND *csound, WINDAT *wdptr, const char *name) { winEPS_globals_t *pp; char *filenam; char pathnam[1024]; char *t; time_t lt; OPARMS oparms; csound->GetOParms(csound, &oparms); IGN(wdptr); IGN(name); if (csound->winEPS_globals != NULL) return; csound->winEPS_globals = csound->Calloc(csound, sizeof(winEPS_globals_t)); pp = (winEPS_globals_t *) csound->winEPS_globals; filenam = oparms.outfilename; if (filenam == NULL) filenam = "test"; /* O.outfilename not set yet */ /* If sound output is being piped directly to the DAC, then */ /* there is no PS output, (psFileOK remains 0), */ /* otherwise open an encapsulated PostScript output file */ /* with a name related to the sound file's name. */ /* */ /* The PS file is located in the same directory as the */ /* sound file, and has the name of the sound file with the */ /* extension ``.eps'' appended. */ /* */ /** * Remove extension from sound-file and add ".eps" */ strncpy(pathnam, filenam, 1024); pathnam[1023] = '\0'; t = strrchr(pathnam, '.'); if (t != NULL) *t = '\0'; strlcat(pathnam, ".eps", 1024); pp->psfd = csound->FileOpen2(csound, &(pp->psFile), CSFILE_STD, pathnam, "w", "SFDIR", CSFTYPE_POSTSCRIPT, 0); if (UNLIKELY(pp->psfd == NULL)) { csound->Message(csound, Str("** Warning ** PostScript file %s " "cannot be opened\n"), pathnam); csound->winEPS_globals = NULL; csound->Free(csound, (void *)pp); return; } csound->Message(csound, Str("\n PostScript graphs written to file %s\n\n"), pathnam); /** * Get the current time and date */ lt = time(NULL); #ifndef LINUX { struct tm *date_ptr; char *date; date_ptr = localtime(<); date = asctime(date_ptr); t = pp->ps_date; while (*date != '\n') *t++ = *date++; *t = '\0'; } #else /* avoid use of non-reentrant functions */ { struct tm tmp1; memset(&tmp1, 0, sizeof(struct tm)); localtime_r(<, &tmp1); asctime_r(&tmp1, &(pp->ps_date[0])); } #endif /** * Print PostScript file Header * Place every plot on a new page. */ fprintf(pp->psFile, "%s \n", "%!PS-Adobe-2.0"); fprintf(pp->psFile, "%s \n", "%%Creator: Csound"); fprintf(pp->psFile, "%s %s \n", "%%CreationDate:", pp->ps_date); fprintf(pp->psFile, "%s \n", "%%Pages: (atend)"); fprintf(pp->psFile, "%s \n", "%%PageOrder: Ascend"); fprintf(pp->psFile, "%s \n", "%%BoundingBox: 010 010 540 700"); fprintf(pp->psFile, "%s \n", "%%Orientation: Portrait"); fprintf(pp->psFile, "%s \n", "%%EndComments"); fprintf(pp->psFile, "%s \n", " "); } static void setAxisNumbers(MYFLT *min, MYFLT *max, char *cmin, char *cmax) { double bmin, bmax, big; int i; /** * Get most significant digit */ bmin = 0.0000001; if (fabs(*min) > bmin) { while ((int)(fabs(*min) / bmin)) bmin = bmin * 10.0; } bmax = 0.0000001; if (fabs((double)*max) > bmax) { while ((i = (int)(FABS(*max) / bmax))) bmax = bmax * 10.0; } if (fabs(bmin) > fabs(bmax)) big = fabs(bmin); else big = fabs(bmax); /** * Set max and minimm to nearest 2nd sig digit */ if (*max == FL(0.0)) i = 0; else i = (int)((*max / big) * 100.0) + 1; *max = (MYFLT) (i * big * 0.01); if (*min == FL(0.0)) i = 0; else i = (int)((*min / big) * 100.0) - 1; *min = (MYFLT) (i * big * 0.01); if (fabs(*max - *min) < 0.0000001) *max = *min + FL(1.0); /* No zero divide */ /** * Write characters */ CS_SPRINTF(cmin, "%g", *min); CS_SPRINTF(cmax, "%g", *max); } static void PS_drawAxes(winEPS_globals_t *pp, char *cxmin, char *cxmax, char *cymin, char *cymax) { MYFLT xx, yy, dx, dy; MYFLT fnts, swide; int i; /** * Make axes - box */ fprintf(pp->psFile, " \n"); fprintf(pp->psFile, "%% Axes \n"); fprintf(pp->psFile, "1 setlinewidth \n"); fprintf(pp->psFile, "newpath \n"); xx = MyPS_XORIG; yy = MyPS_YORIG; fprintf(pp->psFile, "%f %f moveto \n", xx, yy); xx = MyPS_XORIG + MyPS_WIDTH; fprintf(pp->psFile, "%f %f lineto \n", xx, yy); yy = MyPS_YORIG + MyPS_HEIGHT; fprintf(pp->psFile, "%f %f lineto \n", xx, yy); xx = MyPS_XORIG; fprintf(pp->psFile, "%f %f lineto \n", xx, yy); fprintf(pp->psFile, "closepath stroke \n"); /** * Make tick marks: x-axis */ fprintf(pp->psFile, " \n"); fprintf(pp->psFile, "%% x-tickmarks \n"); fprintf(pp->psFile, "1 setlinewidth \n"); xx = MyPS_XORIG; dx = MyPS_WIDTH / FL(10.0); dy = MyPS_HEIGHT/ FL(10.0); for (i = 0; i <= 10; i++) { yy = MyPS_YORIG; fprintf(pp->psFile, "%f %f moveto \n", xx, yy); yy = MyPS_YORIG + dy/FL(6.0); fprintf(pp->psFile, "%f %f lineto stroke \n", xx, yy); yy = MyPS_YORIG + MyPS_HEIGHT - dy/FL(6.0); fprintf(pp->psFile, "%f %f moveto \n", xx, yy); yy = MyPS_YORIG + MyPS_HEIGHT; fprintf(pp->psFile, "%f %f lineto stroke \n", xx, yy); xx += dx; } /** * Make tick marks: y-axis */ fprintf(pp->psFile, " \n"); fprintf(pp->psFile, "%% y-tickmarks \n"); fprintf(pp->psFile, "1 setlinewidth \n"); yy = MyPS_YORIG; for (i = 0; i <= 10; i++) { xx = MyPS_XORIG; fprintf(pp->psFile, "%f %f moveto \n", xx, yy); xx = MyPS_XORIG + dx/FL(6.0); fprintf(pp->psFile, "%f %f lineto stroke \n", xx, yy); xx = MyPS_XORIG + MyPS_WIDTH - dx / FL(6.0); fprintf(pp->psFile, "%f %f moveto \n", xx, yy); xx = MyPS_XORIG + MyPS_WIDTH; fprintf(pp->psFile, "%f %f lineto stroke \n", xx, yy); yy += dy; } /** * Label the axes's max and min */ fnts = MyPS_FONTSIZE; fprintf(pp->psFile, " \n"); fprintf(pp->psFile, "%s findfont %f scalefont setfont \n", MyPS_FONT, fnts); swide = FL(0.5) * fnts * (MYFLT) strlen(cxmin); xx = MyPS_XORIG - swide * FL(0.5); yy = MyPS_YORIG - fnts * FL(1.8); fprintf(pp->psFile, "%f %f moveto \n", xx, yy); fprintf(pp->psFile, "(%s) show \n", cxmin); swide = FL(0.5) * fnts * (MYFLT) strlen(cxmax); xx = MyPS_XORIG + MyPS_WIDTH - swide * FL(0.2); yy = MyPS_YORIG - fnts * FL(1.8); fprintf(pp->psFile, "%f %f moveto \n", xx, yy); fprintf(pp->psFile, "(%s) show \n", cxmax); swide = FL(0.5) * fnts * strlen(cymin); xx = MyPS_XORIG - fnts * FL(0.5) - swide; yy = MyPS_YORIG - fnts * FL(0.4); fprintf(pp->psFile, "%f %f moveto \n", xx, yy); fprintf(pp->psFile, "(%s) show \n", cymin); swide = FL(0.5) * fnts * (MYFLT) strlen(cymax); xx = MyPS_XORIG - fnts * FL(0.5) - swide; yy = MyPS_YORIG + MyPS_HEIGHT - fnts * FL(0.4); fprintf(pp->psFile, "%f %f moveto \n", xx, yy); fprintf(pp->psFile, "(%s) show \n", cymax); } void PS_DrawGraph(CSOUND *csound, WINDAT *wdptr) { winEPS_globals_t *pp; int iskip = (wdptr->npts < MyPS_WIDTH ? 1 : (int)(wdptr->npts / MyPS_WIDTH)); MYFLT ymin, ymax, xx, yy, dx, dy, fnts; char cxmin[20], cxmax[20], cymin[20], cymax[20]; int i; /** * No action when the output file is not opened */ pp = (winEPS_globals_t *)csound->winEPS_globals; if (pp == NULL) return; /** * draw current page and start a newpage. */ pp->currentPage++; if (pp->currentPage > 1) fprintf(pp->psFile, "showpage \n"); fprintf(pp->psFile, " \n"); fprintf(pp->psFile, "%%%%Page: %d %d \n", pp->currentPage, pp->currentPage); fprintf(pp->psFile, " \n"); /** * Get labels for axis limits, then draw the axis */ //xmin = FL(0.0); /* xmax = FL(1.0) * wdptr->npts; */ snprintf(cxmin, 20, "%d", 0); snprintf(cxmax, 20, "%ld", (long)wdptr->npts); ymin = wdptr->min; ymax = wdptr->max; setAxisNumbers(&ymin, &ymax, cymin, cymax); PS_drawAxes(pp, cxmin, cxmax, cymin, cymax); /** * write the plot caption */ fnts = MyPS_FONTSIZE; fprintf(pp->psFile, " \n"); fprintf(pp->psFile, "%s findfont %f scalefont setfont \n", MyPS_FONT, fnts); xx = MyPS_XORIG; yy = MyPS_YORIG + MyPS_HEIGHT + FL(7.0) * fnts * FL(1.5); fprintf(pp->psFile, "%f %f moveto \n", xx, yy); fprintf(pp->psFile, "(date: %s ) show \n", pp->ps_date); yy = MyPS_YORIG + MyPS_HEIGHT + FL(6.0) * fnts * FL(1.5); fprintf(pp->psFile, "%f %f moveto \n", xx, yy); fprintf(pp->psFile, "(scorefile: %s) show \n", csound->scorename); yy = MyPS_YORIG + MyPS_HEIGHT + FL(5.0) * fnts * FL(1.5); fprintf(pp->psFile, "%f %f moveto \n", xx, yy); fprintf(pp->psFile, "(orch_file: %s) show \n", csound->orchname); yy = MyPS_YORIG + MyPS_HEIGHT + FL(4.0) * fnts * FL(1.5); fprintf(pp->psFile, "%f %f moveto \n", xx, yy); fprintf(pp->psFile, "(maximum : %f) show \n", wdptr->max); yy = MyPS_YORIG + MyPS_HEIGHT + FL(3.0) * fnts * FL(1.5); fprintf(pp->psFile, "%f %f moveto \n", xx, yy); fprintf(pp->psFile, "(minimum : %f) show \n", wdptr->min); if (wdptr->caption[0]) { xx = MyPS_XORIG + MyPS_WIDTH / FL(3.0); yy = MyPS_YORIG + MyPS_HEIGHT + fnts; fprintf(pp->psFile, "%f %f moveto \n0", xx, yy); fprintf(pp->psFile, "(%s) show \n", wdptr->caption); } /** * Draw 0 line if inside box */ dy = MyPS_HEIGHT / (ymax - ymin); if (ymin < 0 && ymax > 0) { fprintf(pp->psFile, " \n"); fprintf(pp->psFile, "%% 0-line \n"); yy = MyPS_YORIG + (0 - ymin) * dy; dx = (FL(1.0) * MyPS_WIDTH) / FL(100.0); for (i = 0; i < 100; i += 3) { xx = MyPS_XORIG + i * dx; fprintf(pp->psFile, "%f %f moveto \n", xx, yy); xx = MyPS_XORIG + (i + 1) * dx; fprintf(pp->psFile, "%f %f lineto stroke \n", xx, yy); } } /** * write the plot data */ fprintf(pp->psFile, " \n"); fprintf(pp->psFile, "%% Plot data \n"); fprintf(pp->psFile, "1 setlinewidth \n"); dx = iskip * MyPS_WIDTH / ((MYFLT) wdptr->npts); xx = MyPS_XORIG; yy = MyPS_YORIG + (wdptr->fdata[0] - ymin) * dy; fprintf(pp->psFile, "newpath %f %f moveto \n", xx, yy); for (i = 1; i < wdptr->npts; i += iskip) { xx += dx; yy = MyPS_YORIG + (wdptr->fdata[i] - ymin) * dy; fprintf(pp->psFile, "%f %f lineto \n", xx, yy); } fprintf(pp->psFile, "stroke \n"); } int PS_ExitGraph(CSOUND *csound) { winEPS_globals_t *pp; /** * No action when the output file is not opened */ pp = (winEPS_globals_t *) csound->winEPS_globals; if (pp != NULL) { fprintf(pp->psFile, " \n"); fprintf(pp->psFile, "showpage \n"); fprintf(pp->psFile, " \n"); fprintf(pp->psFile, "%%%%Trailer \n"); fprintf(pp->psFile, "%%%%Pages: %d \n", pp->currentPage); fprintf(pp->psFile, "%%%%EOF\n"); csound->FileClose(csound, pp->psfd); csound->winEPS_globals = NULL; csound->Free(csound, (void *) pp); } return 0; } csound-6.10.0/InOut/winFLTK.c000066400000000000000000000112141321653344700155600ustar00rootroot00000000000000/* winFLTK.c: graphs using FLTK library Copyright (C) 2002 John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* winFLTK.c */ /* Csound FLTK/X graphs */ /* jpff,06Oct02 */ #include "csdl.h" #include #include "cwindow.h" #ifdef LINUX #include #endif #include "winFLTK.h" static void MakeGraph_FLTK(CSOUND *csound, WINDAT *wdptr, const char *name) { wdptr->windid = MakeWindow_FLTK(csound,(char*)name); } static void KillGraph_FLTK(CSOUND *csound, WINDAT *wdptr) { kill_graph(csound, wdptr->windid); } static int dummyWidgetOpcode(CSOUND *csound, void *p) { const char *opname; opname = csound->GetOpcodeName(p); csound->Die(csound, Str("%s: widget opcodes have been disabled by " "the host application"), opname); return NOTOK; } PUBLIC int csoundModuleCreate(CSOUND *csound) { (void)csound; return 0; } PUBLIC int csoundModuleInit(CSOUND *csound) { const OENTRY *ep = &(widgetOpcodes_[0]); int initFlags = 0; int *fltkFlags; int enableDisplays = 0; OPARMS oparms; csound->GetOParms(csound, &oparms); if (csound->QueryGlobalVariable(csound, "FLTK_Flags") == (void*) 0) { if (UNLIKELY(csound->CreateGlobalVariable(csound, "FLTK_Flags", sizeof(int)) != 0)) csound->Die(csound, "%s", Str("widgets.cpp: error allocating FLTK flags")); initFlags = 1; } fltkFlags = getFLTKFlagsPtr(csound); if (((*fltkFlags) & 2) == 0 && !(oparms.graphsoff || oparms.postscript)) { #ifdef LINUX Display *dpy = XOpenDisplay(NULL); if (dpy != NULL) { XCloseDisplay(dpy); #endif if (csound->SetIsGraphable(csound, 1) == 0) { enableDisplays = 1; (*fltkFlags) |= 64; if (!((*fltkFlags) & 256)) csound->SetInternalYieldCallback(csound, CsoundYield_FLTK); flgraph_init(csound); /* Create space */ csound->SetMakeGraphCallback(csound, MakeGraph_FLTK); csound->SetDrawGraphCallback(csound, DrawGraph_FLTK); csound->SetKillGraphCallback(csound, KillGraph_FLTK); csound->SetExitGraphCallback(csound, ExitGraph_FLTK); /* seemed to crash, but not anymore... */ csound->RegisterResetCallback(csound, NULL, widget_reset); csound->Message(csound, "graph init... \n"); } #ifdef LINUX } #endif } if (initFlags) { #ifndef __MACH__ if (enableDisplays) #endif (*fltkFlags) |= 28; } if (!((*fltkFlags) & 129)) for ( ; ep->opname != NULL; ep++) { if (csound->AppendOpcode(csound, ep->opname, (int)ep->dsblksiz, (int)ep->flags, (int)ep->thread, ep->outypes, ep->intypes, ep->iopadr, ep->kopadr, ep->aopadr) != 0) { csound->ErrorMsg(csound, Str("Error registering opcode '%s'"), ep->opname); return -1; } } else if (!((*fltkFlags) & 128)) { for ( ; ep->opname != NULL; ep++) { if (csound->AppendOpcode( csound, ep->opname, (int)ep->dsblksiz, (int)ep->flags,(int)ep->thread, ep->outypes, ep->intypes, (((int)ep->thread & 1) ? dummyWidgetOpcode : (SUBR) 0), (((int)ep->thread & 2) ? dummyWidgetOpcode : (SUBR) 0), (((int)ep->thread & 4) ? dummyWidgetOpcode : (SUBR) 0)) != 0) { csound->ErrorMsg(csound, Str("Error registering opcode '%s'"), ep->opname); return -1; } } } widget_init(csound); return 0; } PUBLIC int csoundModuleInfo(void) { return ((CS_APIVERSION << 16) + (CS_APISUBVER << 8) + (int)sizeof(MYFLT)); } csound-6.10.0/InOut/winFLTK.h000066400000000000000000000070201321653344700155650ustar00rootroot00000000000000/* winFLTK.h: Copyright (C) 2006 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef CSOUND_WINFLTK_H #define CSOUND_WINFLTK_H #include "csdl.h" #ifdef __cplusplus #include #endif /** * FLTK flags is the sum of any of the following values: * 1 (input): disable widget opcodes by setting up dummy opcodes instead * 2 (input): disable FLTK graphs * 4 (input): disable the use of a separate thread for widget opcodes * 8 (input): disable the use of Fl::lock() and Fl::unlock() * 16 (input): disable the use of Fl::awake() * 32 (output): widget opcodes are used * 64 (output): FLTK graphs are used * 128 (input): disable widget opcodes by not registering any opcodes * 256 (input): disable the use of Fl::wait() (implies no widget thread) */ static inline int getFLTKFlags(CSOUND *csound) { return (*((int*) csound->QueryGlobalVariableNoCheck(csound, "FLTK_Flags"))); } static inline int *getFLTKFlagsPtr(CSOUND *csound) { return ((int*) csound->QueryGlobalVariableNoCheck(csound, "FLTK_Flags")); } #ifdef __cplusplus static inline void Fl_lock(CSOUND *csound) { #ifdef NO_FLTK_THREADS (void) csound; #else if (!(getFLTKFlags(csound) & 8)) { Fl::lock(); } #endif } static inline void Fl_unlock(CSOUND *csound) { #ifdef NO_FLTK_THREADS (void) csound; #else if (!(getFLTKFlags(csound) & 8)) { Fl::unlock(); } #endif } static inline void Fl_awake(CSOUND *csound) { #ifdef NO_FLTK_THREADS (void) csound; #else if (!(getFLTKFlags(csound) & 16)) { Fl::awake(); } #endif } static inline void Fl_wait(CSOUND *csound, double seconds) { if (!(getFLTKFlags(csound) & 256)) Fl::wait(seconds); } static inline void Fl_wait_locked(CSOUND *csound, double seconds) { int fltkFlags; fltkFlags = getFLTKFlags(csound); if (!(fltkFlags & 256)) { #ifndef NO_FLTK_THREADS if (!(fltkFlags & 8)) Fl::lock(); #endif Fl::wait(seconds); #ifndef NO_FLTK_THREADS if (!(fltkFlags & 8)) Fl::unlock(); #endif } } #endif /* __cplusplus */ #ifdef __cplusplus extern "C" { #endif extern int CsoundYield_FLTK(CSOUND *); extern void DrawGraph_FLTK(CSOUND *, WINDAT *); extern int ExitGraph_FLTK(CSOUND *); extern void kill_graph(CSOUND *, uintptr_t); extern void KillXYin_FLTK(CSOUND *, XYINDAT *); extern uintptr_t MakeWindow_FLTK(CSOUND *, char *); extern void MakeXYin_FLTK(CSOUND *, XYINDAT *, MYFLT, MYFLT); extern int myFLwait(void); extern void ReadXYin_FLTK(CSOUND *, XYINDAT *); extern void flgraph_init(CSOUND *csound); extern void widget_init(CSOUND *); extern int widget_reset(CSOUND *, void *); extern const OENTRY widgetOpcodes_[]; #ifdef __cplusplus } /* extern "C" */ #endif #endif /* CSOUND_WINFLTK_H */ csound-6.10.0/InOut/winascii.c000066400000000000000000000062501321653344700161140ustar00rootroot00000000000000/* winascii.c: graphs in ascii text Copyright (C) 1991 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* winascii.c */ #include "cwindow.h" /* teletype csound graphs */ #define HOR 80 #define VER 20 #define YOFF 10 #define YOFF4 40 void MakeAscii(CSOUND *csound, WINDAT *wdptr, const char *n) { IGN(n); IGN(csound); wdptr->windid = ~((uintptr_t) 0); /* just so it's not null */ } void KillAscii(CSOUND *csound, WINDAT *wdptr) { IGN(csound); wdptr->windid = 0; /* just to make out that it's dead */ } /* display an n-pnt float array using simple ascii chars */ static CS_NOINLINE void DrawAscii_(CSOUND *csound, WINDAT *wdptr, char *points) { long npts = wdptr->npts; MYFLT absmax = wdptr->absmax; char *s; MYFLT *fp = wdptr->fdata, *fplim = fp + npts; int n, vscale4, vpos, vmin = VER, vmax = 0, incr; MYFLT scalefactor; scalefactor = YOFF4 / absmax; /* get normalizing */ incr = (npts-1)/HOR + 1; /* & sampling facs */ for (s = points + (YOFF * HOR), n = 0; fp < fplim; n++, fp += incr) { s[n] = '_'; /* now write x-axis */ vscale4 = (int) (*fp * scalefactor + YOFF4); vpos = vscale4 >> 2; /* and sampled pnts (with 1/4 line resolution) */ if ((unsigned int) vpos > (unsigned int) VER) continue; if (vpos < vmin) vmin = vpos; if (vpos > vmax) vmax = vpos; points[vpos * HOR + n] = "_.-'"[vscale4 & 3]; /* into dsplay array */ } for (vpos = vmax; vpos >= vmin; vpos--) { /* for all lines: */ s = points + (vpos * HOR); for (n = (HOR - 1); n >= 0 && s[n] == ' '; n--) ; /* find last char & */ csoundMessage(csound, "%.*s\n", n + 1, s); /* putline to there */ } } void DrawAscii(CSOUND *csound, WINDAT *wdptr) { csoundMessage(csound, Str("%s\t%ld points, scalemax %5.3f\n"), wdptr->caption, (long) wdptr->npts, wdptr->absmax); if (wdptr->absmax) { /* for non-triv fn: */ char points[(VER + 1) * HOR]; /* alloc the 2-Dim array */ memset(&(points[0]), ' ', ((VER + 1) * HOR)); /* blank out all pts */ DrawAscii_(csound, wdptr, &(points[0])); } } csound-6.10.0/InOut/windin.c000066400000000000000000000070771321653344700156060ustar00rootroot00000000000000/* windin.c: Copyright (C) 1991 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* WINDIN.C */ #include "cwindow.h" #include "windin.h" /* real-time input control units */ /* 26aug90 dpwe */ int xyinset(CSOUND *csound, XYIN *p) { // This is not the way to do it; set _QQ in interlocks IGN(p); return csound->InitError(csound, Str("xyin opcode has been deprecated in Csound6.")); } /* static int deinit_func(CSOUND *csound, void *p) */ /* { */ /* csound->csoundKillXYinCallback_(csound, &(((XYIN*) p)->w)); */ /* return OK; */ /* } */ /* int xyinset(CSOUND *csound, XYIN *p) */ /* { */ /* MYFLT x, y; */ /* MYFLT iymax = *p->iymax; */ /* MYFLT iymin = *p->iymin; */ /* MYFLT ixmax = *p->ixmax; */ /* MYFLT ixmin = *p->ixmin; */ /* MYFLT iyinit = *p->iyinit; */ /* MYFLT ixinit = *p->ixinit; */ /* if (UNLIKELY((p->timcount = (int)(CS_EKR * *p->iprd + FL(0.5)))<=0)) { */ /* return csound->InitError(csound, Str("illegal iprd")); */ /* } */ /* if (UNLIKELY(iymin > iymax)) { /\* swap if wrong order *\/ */ /* y = iymin; iymin = iymax; iymax = y; */ /* } */ /* if (UNLIKELY(iyinit < iymin)) */ /* iyinit = iymin; */ /* else if (UNLIKELY(iyinit > iymax)) */ /* iyinit = iymax; */ /* *(p->kyrslt) = iyinit; */ /* y = (*p->iymax != *p->iymin ? (*p->iymax-iyinit)/ (*p->iymax - *p->iymin) */ /* : FL(0.5)); */ /* p->w.y = y; */ /* if (UNLIKELY(ixmin > ixmax)) { /\* swap if wrong order *\/ */ /* x = ixmin; ixmin = ixmax; ixmax = x; */ /* } */ /* if (UNLIKELY(ixinit < ixmin)) */ /* ixinit = ixmin; */ /* else if (UNLIKELY(ixinit > ixmax)) */ /* ixinit = ixmax; */ /* *(p->kxrslt) = ixinit; */ /* x = (*p->ixmax != *p->ixmin ? (ixinit-*p->ixmin) / (*p->ixmax - *p->ixmin) */ /* : FL(0.5)); */ /* p->w.x = x; */ /* csound->csoundMakeXYinCallback_(csound, &p->w, x, y); */ /* csound->RegisterDeinitCallback(csound, (void*) p, deinit_func); */ /* p->countdown = 1; /\* init counter to run xyin on first call *\/ */ /* return OK; */ /* } */ /* int xyin(CSOUND *csound, XYIN *p) */ /* { */ /* if (UNLIKELY(!(--p->countdown))) { /\* at each countdown *\/ */ /* p->countdown = p->timcount; /\* reset counter & *\/ */ /* csound->csoundReadXYinCallback_(csound, &p->w); \* read cursor postn */ /* *(p->kxrslt) = *p->ixmin + p->w.x * (*p->ixmax - *p->ixmin); */ /* *(p->kyrslt) = *p->iymin + (FL(1.0) - p->w.y) * (*p->iymax - *p->iymin); */ /* } */ /* return OK; */ /* } */ csound-6.10.0/InOut/window.c000066400000000000000000000144731321653344700156230ustar00rootroot00000000000000/* window.c: Copyright (C) 1991 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* WINDOW.C */ #include "cwindow.h" /* graph window mgr */ #include "winEPS.h" /* PostSCript routines */ /* dpwe 16may90 */ extern OENTRY* find_opcode_new(CSOUND*, char*, char*, char*); extern void MakeAscii(CSOUND *, WINDAT *, const char *); extern void DrawAscii(CSOUND *, WINDAT *); extern void KillAscii(CSOUND *, WINDAT *); /* somewhere to invoke for no display */ static void DummyFn1(CSOUND *csound, WINDAT *p, const char *s) { IGN(csound); IGN(p); IGN(s); } /* somewhere to invoke for no display */ static void DummyFn2(CSOUND *csound, WINDAT *p) { IGN(csound); IGN(p); } /* somewhere to invoke that returns 1 (!) for dummy exit fn */ /* Used to be 1 but seems silly (MR/JPff) */ static int DummyFn3(CSOUND *csound) { IGN(csound); return 0; } /* initial proportions */ /* called once on initialisation of program to */ /* choose between teletype or bitmap graphics */ void dispinit(CSOUND *csound) { OPARMS O; csound->GetOParms(csound, &O); if (O.displays && !(O.graphsoff || O.postscript)) { if (!csound->isGraphable_) find_opcode_new(csound, "FLrun", NULL, NULL); /* load FLTK for displays */ if (csound->isGraphable_) return; /* provided by window driver: is this session able? */ } if (!O.displays) { csound->Message(csound, Str("displays suppressed\n")); csound->csoundMakeGraphCallback_ = DummyFn1; csound->csoundDrawGraphCallback_ = DummyFn2; csound->csoundKillGraphCallback_ = DummyFn2; } else { if (csound->csoundDrawGraphCallback_ == NULL){ // if callbacks are not set by host csound->Message(csound, Str("graphics %s, ascii substituted\n"), ((O.graphsoff || O.postscript) ? Str("suppressed") : Str("not supported on this terminal"))); csound->csoundMakeGraphCallback_ = MakeAscii; csound->csoundDrawGraphCallback_ = DrawAscii; csound->csoundKillGraphCallback_ = KillAscii; } } csound->csoundExitGraphCallback_ = DummyFn3; } void dispset(CSOUND *csound, /* setup a new window */ WINDAT *wdptr, /* & init the data struct */ MYFLT *fdata, int32 npts, char *caption, int waitflg, char *label) { OPARMS O; char *s = caption; char *t = wdptr->caption; char *tlim = t + CAPSIZE - 1; csound->GetOParms(csound, &O); if (!O.displays) return; /* return if displays disabled */ wdptr->fdata = fdata; /* init remainder of data structure */ wdptr->npts = npts; while (*s != '\0' && t < tlim) *t++ = *s++; /* (copy the caption) */ *t = '\0'; if (!wdptr->windid) { /* if no window defined for this str, create one */ csound->csoundMakeGraphCallback_(csound, wdptr, label); if (O.postscript) PS_MakeGraph(csound, wdptr, label); /* open PS file + write header */ } wdptr->waitflg = waitflg; wdptr->polarity = (int16)NOPOL; wdptr->max = FL(0.0); wdptr->min = FL(0.0); wdptr->absmax = FL(0.0); wdptr->oabsmax = FL(0.0); wdptr->danflag = 0; } int dispexit(CSOUND *csound) { OPARMS O; csound->GetOParms(csound, &O); if (O.postscript) PS_ExitGraph(csound); /* Write trailer to PostScript file */ /* prompt for exit from last active window */ int ret = -1; if (csound->csoundExitGraphCallback_) { ret = csound->csoundExitGraphCallback_(csound); } return ret; } void display(CSOUND *csound, WINDAT *wdptr) /* prepare a MYFLT array, then */ /* call the graphing fn */ { MYFLT *fp, *fplim; MYFLT max, min, absmax, fval; int pol; OPARMS O; csound->GetOParms(csound, &O); if (!O.displays) return; /* displays disabled? return */ fp = wdptr->fdata; fplim = fp + wdptr->npts; for (max = *fp++, min = max; fp < fplim; ) { /* find max & min values */ if ((fval = *fp++) > max) max = fval; else if (fval < min) min = fval; } absmax = (-min > max )? (-min):max; wdptr->max = max; /* record most pos and most */ wdptr->min = min; /* neg this array of data */ wdptr->absmax = absmax; /* record absmax this data */ /* VL: absmax needs to be updated at every display in some cases */ if (wdptr->absflag || absmax > wdptr->oabsmax) wdptr->oabsmax = absmax; /* & absmax over life of win */ pol = wdptr->polarity; /* adjust polarity flg for life of win */ if (pol == (int16)NOPOL) { if (max > FL(0.0) && min < FL(0.0)) pol = (int16)BIPOL; else if (max <= FL(0.0) && min FL(0.0)) pol = (int16)BIPOL; wdptr->polarity = pol; if (O.odebug) csound->Message(csound, " calling draw callback \n"); /* now graph the function */ csound->csoundDrawGraphCallback_(csound, wdptr); /* Write postscript code */ if (O.postscript) PS_DrawGraph(csound, wdptr); } csound-6.10.0/LICENCE.random000066400000000000000000000036021321653344700153460ustar00rootroot00000000000000 A C-program for MT19937, with initialisation improved 2002/1/26. Coded by Takuji Nishimura and Makoto Matsumoto. Before using, initialise the state by using csoundSeedRandMT(). Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, 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 names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 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. Any feedback is very welcome. http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) csound-6.10.0/LICENSE.FLTK000066400000000000000000000647661321653344700146700ustar00rootroot00000000000000 FLTK License December 11, 2001 The FLTK library and included programs are provided under the terms of the GNU Library General Public License (LGPL) with the following exceptions: 1. Modifications to the FLTK configure script, config header file, and makefiles by themselves to support a specific platform do not constitute a modified or derivative work. The authors do request that such modifications be contributed to the FLTK project - send all contributions to "fltk-bugs@fltk.org". 2. Widgets that are subclassed from FLTK widgets do not constitute a derivative work. 3. Static linking of applications and widgets to the FLTK library does not constitute a derivative work and does not require the author to provide source code for the application or widget, use the shared FLTK libraries, or link their applications or widgets against a user-supplied version of FLTK. If you link the application or widget to a modified version of FLTK, then the changes to FLTK must be provided under the terms of the LGPL in sections 1, 2, and 4. 4. You do not have to provide a copy of the FLTK license with programs that are linked to the FLTK library, nor do you have to identify the FLTK license in your program or documentation as required by section 6 of the LGPL. However, programs must still identify their use of FLTK. The following example statement can be included in user documentation to satisfy this requirement: [program/widget] is based in part on the work of the FLTK project (http://www.fltk.org). ----------------------------------------------------------------------- GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! csound-6.10.0/LICENSE.PortAudio000066400000000000000000000026401321653344700160150ustar00rootroot00000000000000/* * PortAudio Portable Real-Time Audio Library * Latest Version at: http://www.portaudio.com/ * * Copyright (c) 1999-2000 Phil Burk and Ross Bencina * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * Any person wishing to distribute modifications to the Software is * requested to send the modifications to the original developer so that * they can be incorporated into the canonical version. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ csound-6.10.0/LICENSE.PortMidi000066400000000000000000000027371321653344700156450ustar00rootroot00000000000000/* * PortMidi Portable Real-Time MIDI Library * Latest version available at: http://www.cs.cmu.edu/~music/portmidi/ * * Copyright (c) 1999-2000 Ross Bencina and Phil Burk * Copyright (c) 2001 Roger B. Dannenberg * * 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. * */ csound-6.10.0/OOps/000077500000000000000000000000001321653344700137615ustar00rootroot00000000000000csound-6.10.0/OOps/aops.c000066400000000000000000001710571321653344700151020ustar00rootroot00000000000000/* aops.c: Copyright (C) 1991 Barry Vercoe, John ffitch, Gabriel Maldonado This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* AOPS.C */ #include "aops.h" #include #include #define POW2TABSIZI 4096 #if ULONG_MAX == 18446744073709551615UL # define POW2MAX (24.0) #else # define POW2MAX (15.0) #endif #define EIPT3 (25.0/3.0) #define LOGTWO (0.69314718055994530942) #define STEPS (32768) #define INTERVAL (4.0) #define ONEdLOG2 FL(1.4426950408889634074) #define MIDINOTE0 (3.00) /* Lowest midi note is 3.00 in oct & pch formats */ /* initialise the tables, called by csoundPreCompile() */ void csound_aops_init_tables(CSOUND *csound) { int i; if (csound->cpsocfrc==NULL) csound->cpsocfrc = (MYFLT *) csound->Malloc(csound, sizeof(MYFLT)*OCTRES); if (csound->powerof2==NULL) csound->powerof2 = (MYFLT *) csound->Malloc(csound, sizeof(MYFLT)*POW2TABSIZI); for (i = 0; i < OCTRES; i++) csound->cpsocfrc[i] = POWER(FL(2.0), (MYFLT)i / OCTRES) * ONEPT; for (i = 0; i < POW2TABSIZI; i++) { csound->powerof2[i] = POWER(FL(2.0), (MYFLT)i * (MYFLT)(1.0/POW2TABSIZI) - FL(POW2MAX)); } } MYFLT csoundPow2(CSOUND *csound, MYFLT a) { int n; if (a > POW2MAX) a = POW2MAX; else if (a < -POW2MAX) a = -POW2MAX; /* 4096 * 15 */ n = (int)MYFLT2LRND(a * FL(POW2TABSIZI)) + POW2MAX*POW2TABSIZI; return ((MYFLT) (1UL << (n >> 12)) * csound->powerof2[n & (POW2TABSIZI-1)]); } /*static inline MYFLT pow2(MYFLT a) { int n = (int)MYFLT2LRND(a * FL(POW2TABSIZI)) + POW2MAX*POW2TABSIZI; return ((MYFLT) (1 << (n >> 12)) * powerof2[n & (POW2TABSIZI-1)]); }*/ int rassign(CSOUND *csound, ASSIGN *p) { /* already assigned by otran */ IGN(csound); IGN(p); return OK; } int assign(CSOUND *csound, ASSIGN *p) { IGN(csound); *p->r = *p->a; return OK; } int aassign(CSOUND *csound, ASSIGN *p, int islocal) { IGN(csound); uint32_t nsmps = CS_KSMPS; if (LIKELY(nsmps!=1)) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nsmps = CS_KSMPS; /* the orchestra parser converts '=' to 'upsamp' if input arg is k-rate, */ /* and skips the opcode if outarg == inarg */ if (UNLIKELY(islocal &&offset)) memset(p->r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; if (islocal) memset(&p->r[nsmps], '\0', early*sizeof(MYFLT)); } memcpy(&p->r[offset], &p->a[offset], (nsmps-offset) * sizeof(MYFLT)); } else *p->r =*p->a; return OK; } int gaassign(CSOUND *csound, ASSIGN *p) { return aassign(csound, p, 0); } int laassign(CSOUND *csound, ASSIGN *p) { return aassign(csound, p, 1); } int ainit(CSOUND *csound, ASSIGN *p) { IGN(csound); uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; MYFLT aa = *p->a; int n, nsmps = CS_KSMPS; if (UNLIKELY(offset)) memset(p->r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) p->r[n] = aa; return OK; } int minit(CSOUND *csound, ASSIGNM *p) { unsigned int nargs = p->INCOUNT; unsigned int i; MYFLT *tmp; if (UNLIKELY(nargs > p->OUTOCOUNT)) return csound->InitError(csound, Str("Cannot be more In arguments than Out in " "init (%d,%d)"),p->OUTOCOUNT, nargs); if (p->OUTOCOUNT==1) { *p->r[0] = *p->a[0]; return OK; } tmp = (MYFLT*)csound->Malloc(csound, sizeof(MYFLT)*p->OUTOCOUNT); for (i=0; ia[i]; for (; iOUTOCOUNT; i++) tmp[i] = *p->a[nargs-1]; for (i=0; iOUTOCOUNT; i++) *p->r[i] = tmp[i]; csound->Free(csound, tmp); return OK; } int mainit(CSOUND *csound, ASSIGNM *p) { unsigned int nargs = p->INCOUNT; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; unsigned int i, n, nsmps = CS_KSMPS; MYFLT aa = FL(0.0); early = nsmps - early; /* Bit at end to ignore */ if (UNLIKELY(nargs > p->OUTOCOUNT)) return csound->InitError(csound, Str("Cannot be more In arguments than Out in " "init (%d,%d)"),p->OUTOCOUNT, nargs); for (i=0; ia[i]; MYFLT *r =p->r[i]; for (n = 0; n < nsmps; n++) r[n] = (n < offset || n > early ? FL(0.0) : aa); } for (; iOUTOCOUNT; i++) { MYFLT *r =p->r[i]; memset(r, '\0', nsmps*sizeof(MYFLT)); for (n = 0; n < nsmps; n++) r[n] = (n < offset || n > early ? FL(0.0) : aa); } return OK; } int signum(CSOUND *csound, ASSIGN *p) { IGN(csound); MYFLT a = *p->a; int ans = (a==FL(0.0) ? 0 : ar = (MYFLT) ans; return OK; } int asignum(CSOUND *csound, ASSIGN *p) { IGN(csound); uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; unsigned int i, nsmps = CS_KSMPS; MYFLT *a = p->a; memset(p->r, '\0', nsmps*sizeof(MYFLT)); early = nsmps-early; for (i=offset; ir[i] = (MYFLT) ans; } return OK; } #define RELATN(OPNAME,OP) \ int OPNAME(CSOUND *csound, RELAT *p) \ { IGN(csound); *p->rbool = (*p->a OP *p->b) ? 1 : 0; \ return OK; } RELATN(gt,>) RELATN(ge,>=) RELATN(lt,<) RELATN(le,<=) RELATN(eq,==) RELATN(ne,!=) int b_not(CSOUND *csound, LOGCL *p) { IGN(csound); *p->rbool = (*p->ibool) ? 0 : 1; return OK; } #define LOGCLX(OPNAME,OP) \ int OPNAME(CSOUND *csound, LOGCL *p) \ { IGN(csound);*p->rbool = (*p->ibool OP *p->jbool) ? 1 : 0; return OK; } LOGCLX(and,&&) LOGCLX(or,||) #define KK(OPNAME,OP) \ int OPNAME(CSOUND *csound, AOP *p) \ { IGN(csound); *p->r = *p->a OP *p->b; return OK; } KK(addkk,+) KK(subkk,-) KK(mulkk,*) //KK(divkk,/) int divkk(CSOUND *csound, AOP *p) { MYFLT div = *p->b; IGN(csound); if (UNLIKELY(div==FL(0.0))) csound->Warning(csound, Str("Division by zero")); *p->r = *p->a / div; return OK; } MYFLT MOD(MYFLT a, MYFLT bb) { if (UNLIKELY(bb==FL(0.0))) return FL(0.0); else { MYFLT b = (bb<0 ? -bb : bb); MYFLT d = FMOD(a, b); while (d>b) d -= b; while (-d>b) d += b; return d; } } int modkk(CSOUND *csound, AOP *p) { IGN(csound); *p->r = MOD(*p->a, *p->b); return OK; } #define KA(OPNAME,OP) \ int OPNAME(CSOUND *csound, AOP *p) { \ uint32_t n, nsmps = CS_KSMPS; \ IGN(csound); \ if (LIKELY(nsmps!=1)) { \ MYFLT *r, a, *b; \ uint32_t offset = p->h.insdshead->ksmps_offset; \ uint32_t early = p->h.insdshead->ksmps_no_end; \ r = p->r; \ a = *p->a; \ b = p->b; \ if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); \ if (UNLIKELY(early)) { \ nsmps -= early; \ memset(&r[nsmps], '\0', early*sizeof(MYFLT)); \ } \ for (n=offset; nr = *p->a OP *p->b; \ return OK; \ } \ } KA(addka,+) KA(subka,-) KA(mulka,*) KA(divka,/) int modka(CSOUND *csound, AOP *p) { IGN(csound); MYFLT *r, a, *b; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; r = p->r; a = *p->a; b = p->b; if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nh.insdshead->ksmps_offset; \ uint32_t early = p->h.insdshead->ksmps_no_end; \ r = p->r; \ a = p->a; \ b = *p->b; \ if (UNLIKELY(offset)) \ memset(r, '\0', offset*sizeof(MYFLT)); \ if (UNLIKELY(early)) { \ nsmps -= early; \ memset(&r[nsmps], '\0', early*sizeof(MYFLT)); \ } \ for (n=offset; nr[0] = p->a[0] OP *p->b; \ return OK; \ } \ } AK(addak,+) AK(subak,-) AK(mulak,*) //AK(divak,/) int divak(CSOUND *csound, AOP *p) { uint32_t n, nsmps = CS_KSMPS; MYFLT b = *p->b; if (LIKELY(nsmps != 1)) { MYFLT *r, *a; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; r = p->r; a = p->a; b = *p->b; if (UNLIKELY(b==FL(0.0))) csound->Warning(csound, Str("Division by zero")); if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); \ } for (n=offset; nWarning(csound, Str("Division by zero")); p->r[0] = p->a[0] / b; return OK; } } int modak(CSOUND *csound, AOP *p) { IGN(csound); MYFLT *r, *a, b; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; r = p->r; a = p->a; b = *p->b; if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nh.insdshead->ksmps_offset; \ uint32_t early = p->h.insdshead->ksmps_no_end; \ r = p->r; \ a = p->a; \ b = p->b; \ if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); \ if (UNLIKELY(early)) { \ nsmps -= early; \ memset(&r[nsmps], '\0', early*sizeof(MYFLT)); \ } \ for (n=offset; nr = *p->a OP *p->b; \ return OK; \ } \ } /* VL experimental code using SSE for operations needs memory alignment - 16 bytes */ #ifdef USE_SSE #include "emmintrin.h" #define AA_VEC(OPNAME,OP) \ int OPNAME(CSOUND *csound, AOP *p){ \ MYFLT *r, *a, *b; \ __m128d va, vb; \ uint32_t n, nsmps = CS_KSMPS, end; \ if (LIKELY(nsmps!=1)) { \ uint32_t offset = p->h.insdshead->ksmps_offset; \ uint32_t early = p->h.insdshead->ksmps_no_end; \ r = p->r; a = p->a; b = p->b; \ if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); \ if (UNLIKELY(early)) { \ nsmps -= early; \ memset(&r[nsmps], '\0', early*sizeof(MYFLT)); \ } \ end = nsmps; \ for (n=offset; nr = *p->a + *p->b;\ return OK; \ } \ } \ AA_VEC(addaa,_mm_add_pd) AA_VEC(subaa,_mm_sub_pd) AA_VEC(mulaa,_mm_mul_pd) AA_VEC(divaa,_mm_div_pd) #else AA(addaa,+) AA(subaa,-) AA(mulaa,*) AA(divaa,/) #endif int modaa(CSOUND *csound, AOP *p) { MYFLT *r, *a, *b; IGN(csound); uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; r = p->r; a = p->a; b = p->b; if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nr = (*p->b != FL(0.0) ? *p->a / *p->b : *p->def); return OK; } int divzka(CSOUND *csound, DIVZ *p) { uint32_t n; IGN(csound); MYFLT *r, a, *b, def; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nsmps = CS_KSMPS; r = p->r; a = *p->a; b = p->b; def = *p->def; if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nh.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nsmps = CS_KSMPS; r = p->r; a = p->a; b = *p->b; def = *p->def; if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } if (UNLIKELY(b==FL(0.0))) { for (n=offset; nh.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nsmps = CS_KSMPS; r = p->r; a = p->a; b = p->b; def = *p->def; if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; ncond) *p->r = *p->a; else *p->r = *p->b; return OK; } int aconval(CSOUND *csound, CONVAL *p) { uint32_t offset = p->h.insdshead->ksmps_offset*sizeof(MYFLT); uint32_t early = p->h.insdshead->ksmps_no_end*sizeof(MYFLT); MYFLT *r, *s; IGN(csound); r = p->r; if (*p->cond) s = p->a; else s = p->b; if (r!=s) { memset(r, '\0', offset); memcpy(&r[offset], &s[offset], CS_KSMPS*sizeof(MYFLT)-offset-early); memset(&r[offset-early], '\0', early); } return OK; } int int1(CSOUND *csound, EVAL *p) /* returns signed whole no. */ { MYFLT intpart; IGN(csound); MODF(*p->a, &intpart); *p->r = intpart; return OK; } int int1a(CSOUND *csound, EVAL *p) /* returns signed whole no. */ { MYFLT intpart, *a=p->a, *r=p->r; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps =CS_KSMPS; IGN(csound); if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { MODF(a[n], &intpart); r[n] = intpart; } return OK; } int frac1(CSOUND *csound, EVAL *p) /* returns positive frac part */ { MYFLT intpart, fracpart; IGN(csound); fracpart = MODF(*p->a, &intpart); *p->r = fracpart; return OK; } int frac1a(CSOUND *csound, EVAL *p) /* returns positive frac part */ { MYFLT intpart, fracpart, *r = p->r, *a = p->a; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps =CS_KSMPS; IGN(csound); if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { fracpart = MODF(a[n], &intpart); r[n] = fracpart; } return OK; } #ifdef MYFLOOR #undef MYFLOOR #endif #define MYFLOOR(x) ((int32)((double)(x) >= 0.0 ? (x) : (x) - 0.99999999)) #ifdef MYCEIL #undef MYCEIL #endif #define MYCEIL(x) ((int32)((double)(x) >= 0.0 ? (x) + 0.99999999 : (x))) int int1_round(CSOUND *csound, EVAL *p) /* round to nearest integer */ { IGN(csound); *p->r = (MYFLT) MYFLT2LRND(*p->a); return OK; } int int1a_round(CSOUND *csound, EVAL *p) /* round to nearest integer */ { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps =CS_KSMPS; MYFLT *r=p->r, *a=p->a; IGN(csound); if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) r[n] = (MYFLT)MYFLT2LRND(a[n]); return OK; } int int1_floor(CSOUND *csound, EVAL *p) /* round down */ { IGN(csound); *p->r = (MYFLT)(MYFLOOR(*p->a)); return OK; } int int1a_floor(CSOUND *csound, EVAL *p) /* round down */ { MYFLT *a=p->a, *r=p->r; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps =CS_KSMPS; IGN(csound); if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) r[n] = (MYFLT)(MYFLOOR(a[n])); return OK; } int int1_ceil(CSOUND *csound, EVAL *p) /* round up */ { IGN(csound); *p->r = (MYFLT)(MYCEIL(*p->a)); return OK; } int int1a_ceil(CSOUND *csound, EVAL *p) /* round up */ { MYFLT *a=p->a, *r=p->r; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps =CS_KSMPS; IGN(csound); if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) r[n] = (MYFLT)(MYCEIL(a[n])); return OK; } #define rndmlt (105.947) int rnd1(CSOUND *csound, EVAL *p) /* returns unipolar rand(x) */ { double intpart; csound->rndfrac = modf(csound->rndfrac * rndmlt, &intpart); *p->r = *p->a * (MYFLT)csound->rndfrac; return OK; } int birnd1(CSOUND *csound, EVAL *p) /* returns bipolar rand(x) */ { double intpart; csound->rndfrac = modf(csound->rndfrac * rndmlt, &intpart); *p->r = *p->a * (FL(2.0) * (MYFLT)csound->rndfrac - FL(1.0)); return OK; } #define LIB1(OPNAME,LIBNAME) int OPNAME(CSOUND *csound, EVAL *p) \ { IGN(csound); *p->r = LIBNAME(*p->a); return OK; } LIB1(abs1,FABS) LIB1(exp01,EXP) LIB1(log01,LOG) LIB1(sqrt1,SQRT) LIB1(sin1,SIN) LIB1(cos1,COS) LIB1(tan1,TAN) LIB1(asin1,ASIN) LIB1(acos1,ACOS) LIB1(atan1,ATAN) LIB1(sinh1,SINH) LIB1(cosh1,COSH) LIB1(tanh1,TANH) LIB1(log101,LOG10) LIB1(log21,LOG2) int atan21(CSOUND *csound, AOP *p) { IGN(csound); *p->r = ATAN2(*p->a, *p->b); return OK; } #define LIBA(OPNAME,LIBNAME) int OPNAME(CSOUND *csound, EVAL *p) { \ IGN(csound); \ uint32_t offset = p->h.insdshead->ksmps_offset; \ uint32_t early = p->h.insdshead->ksmps_no_end; \ uint32_t n, nsmps =CS_KSMPS; \ MYFLT *r, *a; \ r = p->r; \ a = p->a; \ if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); \ if (UNLIKELY(early)) { \ nsmps -= early; \ memset(&r[nsmps], '\0', early*sizeof(MYFLT)); \ } \ for (n = offset; n < nsmps; n++) \ r[n] = LIBNAME(a[n]); \ return OK; \ } LIBA(absa,FABS) LIBA(expa,EXP) LIBA(loga,LOG) LIBA(sqrta,SQRT) LIBA(sina,SIN) LIBA(cosa,COS) LIBA(tana,TAN) LIBA(asina,ASIN) LIBA(acosa,ACOS) LIBA(atana,ATAN) LIBA(sinha,SINH) LIBA(cosha,COSH) LIBA(tanha,TANH) LIBA(log10a,LOG10) LIBA(log2a,LOG2) int atan2aa(CSOUND *csound, AOP *p) { MYFLT *r, *a, *b; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps =CS_KSMPS; IGN(csound); r = p->r; a = p->a; b = p->b; if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) r[n] = ATAN2(a[n], b[n]); return OK; } int dbamp(CSOUND *csound, EVAL *p) { IGN(csound); *p->r = LOG(FABS(*p->a)) / LOG10D20; return OK; } int ampdb(CSOUND *csound, EVAL *p) { IGN(csound); *p->r = EXP(*p->a * LOG10D20); return OK; } int aampdb(CSOUND *csound, EVAL *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps =CS_KSMPS; MYFLT *r = p->r, *a = p->a; IGN(csound); if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) r[n] = EXP(a[n] * LOG10D20); return OK; } int dbfsamp(CSOUND *csound, EVAL *p) { *p->r = LOG(FABS(*p->a) / csound->e0dbfs) / LOG10D20; return OK; } int ampdbfs(CSOUND *csound, EVAL *p) { *p->r = csound->e0dbfs * EXP(*p->a * LOG10D20); return OK; } int aampdbfs(CSOUND *csound, EVAL *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps =CS_KSMPS; MYFLT *r, *a; r = p->r; a = p->a; if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) r[n] = csound->e0dbfs * EXP(a[n] * LOG10D20); return OK; } int ftlen(CSOUND *csound, EVAL *p) { FUNC *ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->a)) == NULL)) { *p->r = -FL(1.0); /* Return something */ return NOTOK; } *p->r = (MYFLT)ftp->flen; return OK; } int ftchnls(CSOUND *csound, EVAL *p) { FUNC *ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->a)) == NULL)) { *p->r = -FL(1.0); /* Return something */ return NOTOK; } *p->r = (MYFLT)ftp->nchanls; return OK; } int ftcps(CSOUND *csound, EVAL *p) { FUNC *ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->a)) == NULL) || ftp->cpscvt == FL(0.0)) { *p->r = -FL(1.0); /* Return something */ return NOTOK; } *p->r = (MYFLT)(ftp->cvtbas/ftp->cpscvt); return OK; } int ftlptim(CSOUND *csound, EVAL *p) { FUNC *ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->a)) == NULL)) return NOTOK; if (LIKELY(ftp->loopmode1)) *p->r = ftp->begin1 * csound->onedsr; else { *p->r = FL(0.0); csound->Warning(csound, Str("non-looping sample")); } return OK; } int numsamp(CSOUND *csound, EVAL *p) /***** nsamp by G.Maldonado ****/ { FUNC *ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->a)) == NULL)) { *p->r = FL(0.0); return NOTOK; } /* if (ftp->soundend) */ *p->r = (MYFLT)ftp->soundend; /* else *p->r = (MYFLT)(ftp->flen + 1); */ return OK; } int ftsr(CSOUND *csound, EVAL *p) /**** ftsr by G.Maldonado ****/ { FUNC *ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->a)) == NULL)) { *p->r = FL(0.0); return NOTOK; } *p->r = ftp->gen01args.sample_rate; return OK; } int rtclock(CSOUND *csound, EVAL *p) { *p->r = (MYFLT)csoundGetRealTime(csound->csRtClock); return OK; } int octpch(CSOUND *csound, EVAL *p) { IGN(csound); double fract, oct; fract = modf((double)*p->a, &oct); fract *= EIPT3; *p->r = (MYFLT)(oct + fract); return OK; } int pchoct(CSOUND *csound, EVAL *p) { IGN(csound); double fract, oct; fract = modf((double)*p->a, &oct); fract *= 0.12; *p->r = (MYFLT)(oct + fract); return OK; } int cpsoct(CSOUND *csound, EVAL *p) { int loct = (int)(*p->a * OCTRES); *p->r = (MYFLT)CPSOCTL(loct); return OK; } int acpsoct(CSOUND *csound, EVAL *p) { MYFLT *r, *a; int loct; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps =CS_KSMPS; a = p->a; r = p->r; if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { loct = (int)(a[n] * OCTRES); r[n] = CPSOCTL(loct); } return OK; } int octcps(CSOUND *csound, EVAL *p) { IGN(csound); *p->r = (LOG(*p->a /(MYFLT)ONEPT) / (MYFLT)LOGTWO); return OK; } int cpspch(CSOUND *csound, EVAL *p) { double fract, oct; int loct; fract = modf((double)*p->a, &oct); fract *= EIPT3; loct = (int)MYFLT2LRND((oct + fract) * OCTRES); *p->r = (MYFLT)CPSOCTL(loct); return OK; } int cpsmidinn(CSOUND *csound, EVAL *p) { IGN(csound); *p->r = pow(FL(2.0), (*p->a - FL(69.0)) / FL(12.0)) * (MYFLT)(csound->A4); return OK; } int octmidinn(CSOUND *csound, EVAL *p) { IGN(csound); /* Convert Midi Note number to 8ve.decimal format */ *p->r = (*p->a / FL(12.0)) + FL(MIDINOTE0); return OK; } int pchmidinn(CSOUND *csound, EVAL *p) { IGN(csound); double fract, oct, octdec; /* Convert Midi Note number to 8ve.decimal format */ octdec = ((double)*p->a / 12.0) + MIDINOTE0; /* then convert to 8ve.pc format */ fract = modf(octdec, &oct); fract *= 0.12; *p->r = (MYFLT)(oct + fract); return OK; } int cpsxpch(CSOUND *csound, XENH *p) { /* This may be too expensive */ double fract; double loct; fract = modf((double)*p->pc, &loct); /* Get octave */ if (*p->et > 0) { fract = pow((double)*p->cy, loct + (100.0*fract)/((double)*p->et)); *p->r = (MYFLT)fract * *p->ref; } else { /* Values in a table */ MYFLT t = - *p->et; FUNC* ftp = csound->FTnp2Find(csound, &t); int32 len; if (UNLIKELY(ftp == NULL)) return csound->PerfError(csound, p->h.insdshead,Str("No tuning table %d"), -((int)*p->et)); len = ftp->flen; while (fract>len) { fract -= len; loct++; } fract += 0.005; *p->r = *p->ref * *(ftp->ftable + (int)(100.0*fract)) * POWER(*p->cy, (MYFLT)loct); } return OK; } int cps2pch(CSOUND *csound, XENH *p) { double fract; double loct; fract = modf((double)*p->pc, &loct); /* Get octave */ if (*p->et > 0) { fract = pow(2.0, loct + (100.0*fract)/((double)*p->et)); *p->r = (MYFLT)(fract * 1.02197503906); /* Refer to base frequency */ } else { MYFLT t = - *p->et; FUNC* ftp = csound->FTnp2Find(csound, &t); int32 len; if (UNLIKELY(ftp == NULL)) return csound->PerfError(csound, p->h.insdshead,Str("No tuning table %d"), -((int)*p->et)); len = ftp->flen; while (fract>len) { fract -= len; loct++; } fract += 0.005; *p->r = (MYFLT)(1.02197503906 * *(ftp->ftable +(int)(100.0*fract)) * pow(2.0, loct)); } /* double ref = 261.62561 / pow(2.0, 8.0); */ return OK; } int cpstun_i(CSOUND *csound, CPSTUNI *p) { FUNC *ftp; MYFLT *func; int notenum = (int)*p->input; int grade; int numgrades; int basekeymidi; MYFLT basefreq, factor, interval; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->tablenum)) == NULL)) goto err1; func = ftp->ftable; numgrades = (int)*func++; interval = *func++; basefreq = *func++; basekeymidi = (int)*func++; if (notenum < basekeymidi) { notenum = basekeymidi - notenum; grade = (numgrades-(notenum % numgrades)) % numgrades; factor = - (MYFLT)(int)((notenum+numgrades-1) / numgrades) ; } else { notenum = notenum - basekeymidi; grade = notenum % numgrades; factor = (MYFLT)(int)(notenum / numgrades); } factor = POWER(interval, factor); *p->r = func[grade] * factor * basefreq; return OK; err1: return csound->PerfError(csound, p->h.insdshead,Str("cpstun: invalid table")); } int cpstun(CSOUND *csound, CPSTUN *p) { if (*p->ktrig) { FUNC *ftp; MYFLT *func; int notenum = (int)*p->kinput; int grade; int numgrades; int basekeymidi; MYFLT basefreq, factor, interval; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->tablenum)) == NULL)) goto err1; func = ftp->ftable; numgrades = (int)*func++; interval = *func++; basefreq = *func++; basekeymidi = (int)*func++; if (notenum < basekeymidi) { notenum = basekeymidi - notenum; grade = (numgrades-(notenum % numgrades)) % numgrades; factor = - (MYFLT)(int)((notenum+numgrades-1) / numgrades) ; } else { notenum = notenum - basekeymidi; grade = notenum % numgrades; factor = (MYFLT)(int)(notenum / numgrades); } factor = POWER(interval, factor); p->old_r = (*p->r = func[grade] * factor * basefreq); } else *p->r = p->old_r; return OK; err1: return csound->PerfError(csound, p->h.insdshead,Str("cpstun: invalid table")); } int logbasetwo_set(CSOUND *csound, EVAL *p) { IGN(p); if (UNLIKELY(csound->logbase2 == NULL)) { double x = (1.0 / INTERVAL); int i; csound->logbase2 = (MYFLT*) csound->Malloc(csound, (STEPS + 1) * sizeof(MYFLT)); for (i = 0; i <= STEPS; i++) { csound->logbase2[i] = ONEdLOG2 * LOG((MYFLT)x); x += ((INTERVAL - 1.0 / INTERVAL) / (double)STEPS); } } return OK; } int powoftwo(CSOUND *csound, EVAL *p) { *p->r = csound->Pow2(csound,*p->a); return OK; } int powoftwoa(CSOUND *csound, EVAL *p) { /* by G.Maldonado, liberalised by JPff */ MYFLT *a=p->a, *r=p->r; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps =CS_KSMPS; if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) r[n] = csound->Pow2(csound,a[n]); return OK; } #define ONEd12 (FL(0.08333333333333333333333)) #define ONEd1200 (FL(0.00083333333333333333333)) int semitone(CSOUND *csound, EVAL *p) { MYFLT a = *p->a*ONEd12; *p->r = csound->Pow2(csound,a); return OK; } int asemitone(CSOUND *csound, EVAL *p) /* JPff */ { MYFLT *r, *a; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps =CS_KSMPS; a = p->a; r = p->r; if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { MYFLT aa = (a[n])*ONEd12; r[n] = csound->Pow2(csound,aa); } return OK; } int cent(CSOUND *csound, EVAL *p) { MYFLT a = *p->a*ONEd1200; *p->r = csound->Pow2(csound,a); return OK; } int acent(CSOUND *csound, EVAL *p) /* JPff */ { MYFLT *r, *a; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps =CS_KSMPS; a = p->a; r = p->r; if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { MYFLT aa = (a[n])*ONEd1200; r[n] = csound->Pow2(csound,aa); } return OK; } #define LOG2_10D20 (FL(0.166096404744368117393515971474)) int db(CSOUND *csound, EVAL *p) { *p->r = csound->Pow2(csound,*p->a*LOG2_10D20); return OK; } int dba(CSOUND *csound, EVAL *p) /* JPff */ { MYFLT *r, *a; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps =CS_KSMPS; a = p->a; r = p->r; if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { MYFLT aa = a[n]; r[n] = csound->Pow2(csound,aa*LOG2_10D20); } return OK; } int logbasetwo(CSOUND *csound, EVAL *p) { int n = (int)((*p->a - (FL(1.0)/INTERVAL)) / (INTERVAL - FL(1.0)/INTERVAL) * STEPS + FL(0.5)); if (n<0 || n>STEPS) *p->r = LOG(*p->a)*ONEdLOG2; else *p->r = csound->logbase2[n]; return OK; } int logbasetwoa(CSOUND *csound, EVAL *p) { /* by G.Maldonado liberalised by JPff */ MYFLT *r, *a; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps =CS_KSMPS; a = p->a; r = p->r; if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { MYFLT aa = a[n]; int n = (int)((aa - (FL(1.0)/INTERVAL)) / (INTERVAL - FL(1.0)/INTERVAL) * STEPS + FL(0.5)); if (n<0 || n>STEPS) r[n] = LOG(aa)*ONEdLOG2; else r[n] = csound->logbase2[n]; } return OK; } int ilogbasetwo(CSOUND *csound, EVAL *p) { logbasetwo_set(csound, p); logbasetwo(csound, p); return OK; } int in(CSOUND *csound, INM *p) { uint32_t offset = p->h.insdshead->ksmps_offset*sizeof(MYFLT); uint32_t early = p->h.insdshead->ksmps_no_end; if (csound->inchnls != 1) return csound->PerfError(csound, p->h.insdshead, "Wrong numnber of input channels\n"); CSOUND_SPIN_SPINLOCK if (UNLIKELY(offset)) memset(p->ar, '\0', offset); memcpy(&p->ar[offset], CS_SPIN, (CS_KSMPS-early) * sizeof(MYFLT)-offset); if (UNLIKELY(early)) memset(&p->ar[CS_KSMPS-early], '\0', early * sizeof(MYFLT)); CSOUND_SPIN_SPINUNLOCK return OK; } int inarray(CSOUND *csound, INA *p) { MYFLT *data = p->tabout->data; uint32_t n = p->tabout->sizes[0]; uint32_t offset = p->h.insdshead->ksmps_offset*sizeof(MYFLT); uint32_t early = p->h.insdshead->ksmps_no_end; MYFLT *sp = CS_SPIN; uint32_t m, nsmps =CS_KSMPS, i; uint32_t ksmps = nsmps; if ((int)n>csound->inchnls) n = csound->inchnls; CSOUND_SPIN_SPINLOCK if (UNLIKELY(offset)) for (i = 0; i < n; i++) memset(&data[i*ksmps], '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; for (i = 0; i < n; i++) memset(&data[nsmps+i*ksmps], '\0', early*sizeof(MYFLT)); } for (m = offset; m < nsmps; m++) { for (i = 0; i < n; i++) data[m+i*ksmps] = *sp++; } CSOUND_SPIN_SPINUNLOCK return OK; } int ins(CSOUND *csound, INS *p) { MYFLT *sp, *ar1, *ar2; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps =CS_KSMPS, k; if(csound->inchnls != 2) return csound->PerfError(csound, p->h.insdshead, "Wrong numnber of input channels\n"); CSOUND_SPIN_SPINLOCK sp = CS_SPIN; ar1 = p->ar1; ar2 = p->ar2; if (UNLIKELY(offset)) { memset(ar1, '\0', offset*sizeof(MYFLT)); memset(ar2, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&p->ar1[nsmps], '\0', early * sizeof(MYFLT)); memset(&p->ar2[nsmps], '\0', early * sizeof(MYFLT)); } for (n=offset, k=0; nar1, *ar2 = p->ar2, *ar3 = p->ar3, *ar4 = p->ar4; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps =CS_KSMPS, k; if(csound->inchnls != 4) return csound->PerfError(csound, p->h.insdshead, "Wrong numnber of input channels\n"); CSOUND_SPIN_SPINLOCK if (UNLIKELY(offset)) { memset(ar1, '\0', offset*sizeof(MYFLT)); memset(ar2, '\0', offset*sizeof(MYFLT)); memset(ar3, '\0', offset*sizeof(MYFLT)); memset(ar4, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&ar1[nsmps], '\0', early * sizeof(MYFLT)); memset(&ar2[nsmps], '\0', early * sizeof(MYFLT)); memset(&ar3[nsmps], '\0', early * sizeof(MYFLT)); memset(&ar4[nsmps], '\0', early * sizeof(MYFLT)); } for (n=offset, k=0; nar1, *ar2 = p->ar2, *ar3 = p->ar3, *ar4 = p->ar4, *ar5 = p->ar5, *ar6 = p->ar6; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps =CS_KSMPS, k; if(csound->inchnls != 6) return csound->PerfError(csound, p->h.insdshead, "Wrong numnber of input channels\n"); CSOUND_SPIN_SPINLOCK if (UNLIKELY(offset)) { memset(ar1, '\0', offset*sizeof(MYFLT)); memset(ar2, '\0', offset*sizeof(MYFLT)); memset(ar3, '\0', offset*sizeof(MYFLT)); memset(ar4, '\0', offset*sizeof(MYFLT)); memset(ar5, '\0', offset*sizeof(MYFLT)); memset(ar6, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&ar1[nsmps], '\0', early * sizeof(MYFLT)); memset(&ar2[nsmps], '\0', early * sizeof(MYFLT)); memset(&ar3[nsmps], '\0', early * sizeof(MYFLT)); memset(&ar4[nsmps], '\0', early * sizeof(MYFLT)); memset(&ar5[nsmps], '\0', early * sizeof(MYFLT)); memset(&ar6[nsmps], '\0', early * sizeof(MYFLT)); } for (n=offset, k=0; nar1, *ar2 = p->ar2, *ar3 = p->ar3, *ar4 = p->ar4, *ar5 = p->ar5, *ar6 = p->ar6, *ar7 = p->ar7, *ar8 = p->ar8; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps =CS_KSMPS, k; if(csound->inchnls != 8) return csound->PerfError(csound, p->h.insdshead, "Wrong numnber of input channels\n"); CSOUND_SPIN_SPINLOCK if (UNLIKELY(offset)) { memset(ar1, '\0', offset*sizeof(MYFLT)); memset(ar2, '\0', offset*sizeof(MYFLT)); memset(ar3, '\0', offset*sizeof(MYFLT)); memset(ar4, '\0', offset*sizeof(MYFLT)); memset(ar5, '\0', offset*sizeof(MYFLT)); memset(ar6, '\0', offset*sizeof(MYFLT)); memset(ar7, '\0', offset*sizeof(MYFLT)); memset(ar8, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&ar1[nsmps], '\0', early * sizeof(MYFLT)); memset(&ar2[nsmps], '\0', early * sizeof(MYFLT)); memset(&ar3[nsmps], '\0', early * sizeof(MYFLT)); memset(&ar4[nsmps], '\0', early * sizeof(MYFLT)); memset(&ar5[nsmps], '\0', early * sizeof(MYFLT)); memset(&ar6[nsmps], '\0', early * sizeof(MYFLT)); memset(&ar7[nsmps], '\0', early * sizeof(MYFLT)); memset(&ar8[nsmps], '\0', early * sizeof(MYFLT)); } for (n=offset, k=0; nar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t m, nsmps =CS_KSMPS, i; if(csound->inchnls != (int) n) return csound->PerfError(csound, p->h.insdshead, "Wrong numnber of input channels\n"); CSOUND_SPIN_SPINLOCK if (UNLIKELY(offset)) for (i = 0; i < n; i++) memset(ara[i], '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; for (i = 0; i < n; i++) memset(ara[i], '\0', early*sizeof(MYFLT)); } for (m = offset; m < nsmps; m++) { for (i = 0; i < n; i++) *ara[i] = *sp++; } CSOUND_SPIN_SPINUNLOCK return OK; } int in16(CSOUND *csound, INALL *p) { return inn(csound, p, 16u); } int in32(CSOUND *csound, INALL *p) { return inn(csound, p, 32u); } int inch1_set(CSOUND *csound, INCH1 *p) { IGN(csound); p->init = 1; return OK; } int inch_opcode1(CSOUND *csound, INCH1 *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS, ch; MYFLT *sp, *ain; ch = ((int)*p->ch + FL(0.5)); if (UNLIKELY(ch > (uint32_t)csound->inchnls)) { if (p->init) csound->Message(csound, Str("Input channel %d too large; ignored"), ch); memset(p->ar, 0, sizeof(MYFLT)*nsmps); p->init = 0; // return OK; } else if (UNLIKELY(ch < 1)) { if (p->init) csound->Message(csound, Str("Input channel %d is invalid; ignored"), ch); memset(p->ar, 0, sizeof(MYFLT)*nsmps); p->init = 0; } else { sp = CS_SPIN + (ch - 1); ain = p->ar; if (UNLIKELY(offset)) memset(ain, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ain[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { ain[n] = *sp; sp += csound->inchnls; } } return OK; } int inch_set(CSOUND *csound, INCH *p) { IGN(csound); p->init = 1; return OK; } int inch_opcode(CSOUND *csound, INCH *p) { /* Rewritten to allow multiple args upto 40 */ uint32_t nc, nChannels = p->INCOUNT; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS, ch; MYFLT *sp, *ain; if (UNLIKELY(nChannels != p->OUTOCOUNT)) return csound->PerfError(csound, p->h.insdshead, Str("Input and output argument count differs in inch")); for (nc=0; ncch[nc] + FL(0.5)); if (UNLIKELY(ch > (uint32_t)csound->inchnls)) { if (p->init) csound->Message(csound, Str("Input channel %d too large; ignored"), ch); memset(p->ar[nc], 0, sizeof(MYFLT)*nsmps); p->init = 0; // return OK; } else if (UNLIKELY(ch < 1)) { if (p->init) csound->Message(csound, Str("Input channel %d is invalid; ignored"), ch); memset(p->ar, 0, sizeof(MYFLT)*nsmps); p->init = 0; } else { sp = CS_SPIN + (ch - 1); ain = p->ar[nc]; if (UNLIKELY(offset)) memset(ain, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ain[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { ain[n] = *sp; sp += csound->inchnls; } } } return OK; } int inall_opcode(CSOUND *csound, INALL *p) { uint32_t n = (int)p->OUTOCOUNT, m; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t i,j = 0, k = 0, nsmps = CS_KSMPS; uint32_t early = nsmps - p->h.insdshead->ksmps_no_end; MYFLT *spin = CS_SPIN; if(csound->inchnls != (int) n) return csound->PerfError(csound, p->h.insdshead, "Wrong numnber of input channels\n"); CSOUND_SPIN_SPINLOCK m = (n < (uint32_t)csound->inchnls ? n : (uint32_t)csound->inchnls); for (j=0; jearly) { for (i=0 ; i < n; i++) p->ar[i][j] = FL(0.0); } else { for (i=0; iar[i][j] = spin[k + i]; } for ( ; i < n; i++) p->ar[i][j] = FL(0.0); k += csound->inchnls; } CSOUND_SPIN_SPINUNLOCK return OK; } int outs1(CSOUND *csound, OUTM *p) { MYFLT *sp= CS_SPOUT /*csound->spraw*/, *ap1= p->asig; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t nsmps =CS_KSMPS, n; uint32_t early = nsmps-p->h.insdshead->ksmps_no_end; CSOUND_SPOUT_SPINLOCK if (!csound->spoutactive) { if (offset) memset(sp, '\0', offset*sizeof(MYFLT)); memcpy(&sp[offset], &ap1[offset], (early-offset)*sizeof(MYFLT)); if (early!=nsmps) memset(&sp[early], '\0', (nsmps-early)*sizeof(MYFLT)); /* for (n=0; nearly) ? FL(0.0) : ap1[n]; */ /* } */ if (csound->nchnls>1) memset(&sp[nsmps], '\0', nsmps*(csound->nchnls-1)*sizeof(MYFLT)); csound->spoutactive = 1; } else { for (n=0; n=offset) sp[n] += ap1[n]; } } CSOUND_SPOUT_SPINUNLOCK return OK; } #define OUTCN(n) if (n>csound->nchnls) return \ csound->InitError(csound, \ Str("Channel greater than nchnls")); \ return OK; int och2(CSOUND *csound, OUTM *p) { IGN(p); OUTCN(2) } int och3(CSOUND *csound, OUTM *p) { IGN(p); OUTCN(3) } int och4(CSOUND *csound, OUTM *p) { IGN(p); OUTCN(4) } int outs2(CSOUND *csound, OUTM *p) { MYFLT *sp = CS_SPOUT /*csound->spraw*/, *ap2 = p->asig; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t nsmps =CS_KSMPS, n; uint32_t early = nsmps-p->h.insdshead->ksmps_no_end; CSOUND_SPOUT_SPINLOCK if (!csound->spoutactive) { memset(sp, '\0', nsmps*sizeof(MYFLT)); sp +=nsmps; if (offset) memset(sp, '\0', offset*sizeof(MYFLT)); memcpy(&sp[offset], &ap2[offset], (early-offset)*sizeof(MYFLT)); if (early!=nsmps) memset(&sp[early], '\0', (nsmps-early)*sizeof(MYFLT)); if (csound->nchnls>2) memset(&sp[nsmps], '\0', (csound->nchnls-2)*sizeof(MYFLT)); csound->spoutactive = 1; } else { sp +=nsmps; for (n=offset; nspraw*/, *ap3 = p->asig; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t nsmps =CS_KSMPS, n; uint32_t early = nsmps-p->h.insdshead->ksmps_no_end; CSOUND_SPOUT_SPINLOCK if (!csound->spoutactive) { memset(sp, '\0', 2*nsmps*sizeof(MYFLT)); sp += 2*nsmps; if (offset) memset(sp, '\0', offset*sizeof(MYFLT)); memcpy(&sp[offset], &ap3[offset], (early-offset)*sizeof(MYFLT)); if (early!=nsmps) memset(&sp[early], '\0', (nsmps-early)*sizeof(MYFLT)); if (csound->nchnls>3) memset(&sp[nsmps], '\0', (csound->nchnls-3)*sizeof(MYFLT)); csound->spoutactive = 1; } else { sp += 2*nsmps; for (n=offset; nspraw*/, *ap4 = p->asig; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t nsmps =CS_KSMPS, n; uint32_t early = nsmps-p->h.insdshead->ksmps_no_end; CSOUND_SPOUT_SPINLOCK if (!csound->spoutactive) { memset(sp, '\0', 3*nsmps*sizeof(MYFLT)); sp += 3*nsmps; if (offset) memset(sp, '\0', offset*sizeof(MYFLT)); memcpy(&sp[offset], &ap4[offset], (early-offset)*sizeof(MYFLT)); if (early!=nsmps) memset(&sp[early], '\0', (nsmps-early)*sizeof(MYFLT)); if (csound->nchnls>4) memset(&sp[nsmps], '\0', (csound->nchnls-4)*sizeof(MYFLT)); csound->spoutactive = 1; } else { sp += 3*nsmps; for (n=offset; nspraw; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; // if (UNLIKELY((offset|early))) { early = nsmps - early; CSOUND_SPOUT_SPINLOCK if (!csound->spoutactive) { memset(spout, '\0', csound->nspout*sizeof(MYFLT)); for (i=0; iasig[i]+offset, (early-offset)*sizeof(MYFLT)); k += nsmps; } csound->spoutactive = 1; } else { for (i=0; iasig[i][j]; } k += nsmps; } } CSOUND_SPOUT_SPINUNLOCK // } /* else { */ /* CSOUND_SPOUT_SPINLOCK */ /* if (!csound->spoutactive) { */ /* for (i=0; iasig[i], nsmps*sizeof(MYFLT)); */ /* k += nsmps; */ /* } */ /* if (csound->nchnls>n+1) { */ /* printf("nchnks, n = %d,%d\n", csound->nchnls, n); */ /* memset(&spout[k], '\0', (nsmps*(csound->nchnls-n))*sizeof(MYFLT)); */ /* } */ /* csound->spoutactive = 1; */ /* } */ /* else { */ /* for (i=0; iasig[i][j]; */ /* } */ /* k += nsmps; */ /* } */ /* } */ /* CSOUND_SPOUT_SPINUNLOCK */ /* } */ return OK; } int ochn(CSOUND *csound, OUTX *p) { uint32_t nch = p->INOCOUNT; if (nch>csound->nchnls) csound->Warning(csound, Str("Excess channels ignored\n")); return OK; } int outall(CSOUND *csound, OUTX *p) /* Output a list of channels */ { uint32_t nch = p->INOCOUNT; return outn(csound, (nch <= csound->nchnls ? nch : csound->nchnls), p); } int outarr(CSOUND *csound, OUTARRAY *p) { uint32_t nsmps =CS_KSMPS, i, j; uint32_t ksmps = nsmps; uint32_t n = p->tabin->sizes[0]; MYFLT *data = p->tabin->data; MYFLT *spout = CS_SPOUT; //csound->spraw; if (csound->oparms->sampleAccurate) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = nsmps-p->h.insdshead->ksmps_no_end; CSOUND_SPOUT_SPINLOCK if (!csound->spoutactive) { memset(spout, '\0', csound->nspout*sizeof(MYFLT)); for (i=0; ispoutactive = 1; } else { /* no need to offset data is already offset in the buffer*/ for (i=0; ispoutactive) { memcpy(spout, data, n*ksmps*sizeof(MYFLT)); if (csound->nchnls!=n) memset(&spout[n*ksmps], '\0', (csound->nchnls-n)*ksmps*sizeof(MYFLT)); csound->spoutactive = 1; } else { for (i=0; ih.insdshead->ksmps_offset; uint32_t nsmps = CS_KSMPS, j, n; uint32_t early = nsmps-p->h.insdshead->ksmps_no_end; uint32_t count = p->INOCOUNT; MYFLT **args = p->args; uint32_t nchnls = csound->nchnls; MYFLT *spout = CS_SPOUT; CSOUND_SPOUT_SPINLOCK for (j = 0; j < count; j += 2) { ch = (int)(*args[j] + FL(0.5)); if (ch < 1) ch = 1; apn = args[j + 1]; if (ch > nchnls) continue; if (!csound->spoutactive) { ch--; memset(spout, '\0', csound->nspout*sizeof(MYFLT)); memcpy(&spout[offset+ch*nsmps], apn, (early-offset)*sizeof(MYFLT)); csound->spoutactive = 1; } else { sp = spout + (ch - 1)*nsmps; for (n=offset; nr = isnan(*p->a); return OK; } /* ********COULD BE IMPROVED******** */ int is_NaNa(CSOUND *csound, ASSIGN *p) { IGN(csound); uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t k, nsmps = CS_KSMPS; uint32_t early = nsmps - p->h.insdshead->ksmps_no_end; MYFLT *a = p->a; *p->r = FL(0.0); for (k=offset; kr += isnan(a[k]); return OK; } int is_inf(CSOUND *csound, ASSIGN *p) { IGN(csound); *p->r = isinf(*p->a); return OK; } /* ********COULD BE IMPROVED******** */ int is_infa(CSOUND *csound, ASSIGN *p) { IGN(csound); uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t k, nsmps = CS_KSMPS; uint32_t early = nsmps-p->h.insdshead->ksmps_no_end; MYFLT *a = p->a; MYFLT ans = FL(0.0); int sign = 1; for (k=offset; kr = ans*sign; return OK; } int error_fn(CSOUND *csound, ERRFN *p) { IGN(p); return csound->InitError(csound, Str("Unknown function called")); } /* ------------------------------------------------------------------------ */ int monitor_opcode_perf(CSOUND *csound, MONITOR_OPCODE *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, j, nsmps = CS_KSMPS, nchnls = csound->GetNchnls(csound); MYFLT *spout = csound->spraw; if (csound->spoutactive) { for (j = 0; jnsmps-early) p->ar[j][i] = FL(0.0); else p->ar[j][i] = spout[i+j*nsmps]; } } } else { for (j = 0; jar[j], '\0', nsmps*sizeof(MYFLT)); } } return OK; } int monitor_opcode_init(CSOUND *csound, MONITOR_OPCODE *p) { if (UNLIKELY(csound->GetOutputArgCnt(p) != (int)csound->GetNchnls(csound))) return csound->InitError(csound, Str("number of arguments != nchnls")); p->h.opadr = (SUBR) monitor_opcode_perf; return OK; } /* -------------------------------------------------------------------- */ int outRange_i(CSOUND *csound, OUTRANGE *p) { IGN(csound); p->narg = p->INOCOUNT-1; return OK; } int outRange(CSOUND *csound, OUTRANGE *p) { int j; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; //int nchnls = csound->GetNchnls(csound); MYFLT *ara[VARGMAX]; int startChan = (int) *p->kstartChan -1; MYFLT *sp = csound->spraw + startChan*nsmps; int narg = p->narg; if (startChan < 0) return csound->PerfError(csound, p->h.insdshead, Str("outrg: channel number cannot be < 1 " "(1 is the first channel)")); for (j = 0; j < narg; j++) ara[j] = p->argums[j]; if (!csound->spoutactive) { memset(csound->spraw, '\0', csound->nspout * sizeof(MYFLT)); /* no need to offset ?? why ?? */ int i; for (i=0; i < narg; i++) { memcpy(sp, ara[i], nsmps*sizeof(MYFLT)); sp += nsmps; } csound->spoutactive = 1; } else { int i; for (i=0; i < narg; i++) { for (n=offset; nQueryGlobalVariable(csound, "_DAC_CHANNELS_"); if (dachans == NULL) { csound->Warning(csound, Str("number of hardware output channels" " not currently available")); } else *p->r = *dachans; dachans = (int *) csound->QueryGlobalVariable(csound, "_ADC_CHANNELS_"); if (dachans == NULL) { csound->Warning(csound, Str("number of hardware input channels" " not currently available")); } else *p->a = *dachans; return OK; } csound-6.10.0/OOps/bus.c000066400000000000000000001467431321653344700147350ustar00rootroot00000000000000/* bus.c: Copyright (C) 2004 John ffitch (C) 2005, 2006 Istvan Varga (c) 2006 Victor Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* BUS.C */ #include "csoundCore.h" #include #include #include #include #ifdef NACL #include #endif #include "bus.h" #include "namedins.h" /* For sensing opcodes */ #if defined(__unix) || defined(__unix__) || defined(__MACH__) # ifdef HAVE_SYS_TIME_H # include # endif # ifdef HAVE_SYS_TYPES_H # include # endif # ifdef HAVE_TERMIOS_H # include # endif #elif defined(WIN32) # include #endif /* ------------------------------------------------------------------------ */ #ifdef HAVE_C99 # ifdef MYFLT2LRND # undef MYFLT2LRND # endif # ifndef USE_DOUBLE # define MYFLT2LRND lrintf # else # define MYFLT2LRND lrint # endif #endif #ifdef USE_DOUBLE # define MYFLT_INT_TYPE int64_t #else # define MYFLT_INT_TYPE int32_t #endif int chani_opcode_perf_k(CSOUND *csound, CHNVAL *p) { int n = (int)MYFLT2LRND(*(p->a)); char chan_name[16]; int err; MYFLT *val; if (UNLIKELY(n < 0)) return csound->PerfError(csound, p->h.insdshead,Str("chani: invalid index")); snprintf(chan_name, 16, "%i", n); err = csoundGetChannelPtr(csound, &val, chan_name, CSOUND_CONTROL_CHANNEL | CSOUND_INPUT_CHANNEL); if (UNLIKELY(err)) return csound->PerfError(csound, p->h.insdshead, Str("chani error %d:" "channel not found or not right type"), err); *(p->r) = *val; return OK; } int chano_opcode_perf_k(CSOUND *csound, CHNVAL *p) { int n = (int)MYFLT2LRND(*(p->a)); char chan_name[16]; int err; MYFLT *val; if (UNLIKELY(n < 0)) return csound->PerfError(csound,p->h.insdshead,Str("chani: invalid index")); snprintf(chan_name, 16, "%i", n); err = csoundGetChannelPtr(csound, &val, chan_name, CSOUND_CONTROL_CHANNEL | CSOUND_INPUT_CHANNEL); if (UNLIKELY(err)) return csound->PerfError(csound, p->h.insdshead, Str("chano error %d:" "channel not found or not right type"), err); *val = *(p->r); return OK; } int chani_opcode_perf_a(CSOUND *csound, CHNVAL *p) { int n = (int)MYFLT2LRND(*(p->a)); uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; char chan_name[16]; int err; MYFLT *val; if (UNLIKELY(n < 0)) return csound->PerfError(csound, p->h.insdshead,Str("chani: invalid index")); snprintf(chan_name, 16, "%i", n); err = csoundGetChannelPtr(csound, &val, chan_name, CSOUND_AUDIO_CHANNEL | CSOUND_INPUT_CHANNEL); if (UNLIKELY(err)) return csound->PerfError(csound, p->h.insdshead, Str("chani error %d:" "channel not found or not right type"), err); if (UNLIKELY(offset)) memset(p->r, '\0', offset * sizeof(MYFLT)); memcpy(&p->r[offset], &val[offset], sizeof(MYFLT) * (CS_KSMPS-offset-early)); if (UNLIKELY(early)) memset(&p->r[CS_KSMPS-early], '\0', early * sizeof(MYFLT)); return OK; } int chano_opcode_perf_a(CSOUND *csound, CHNVAL *p) { int n = (int)MYFLT2LRND(*(p->a)); uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; char chan_name[16]; int err; MYFLT *val; if (UNLIKELY(n < 0)) return csound->PerfError(csound, p->h.insdshead,Str("chani: invalid index")); snprintf(chan_name, 16, "%i", n); err = csoundGetChannelPtr(csound, &val, chan_name, CSOUND_AUDIO_CHANNEL | CSOUND_OUTPUT_CHANNEL); if (UNLIKELY(err)) return csound->PerfError(csound, p->h.insdshead, Str("chano error %d:" "channel not found or not right type"), err); if (UNLIKELY(offset)) memset(&val, '\0', offset * sizeof(MYFLT)); memcpy(&val[offset], &p->r[offset], sizeof(MYFLT) * (CS_KSMPS-offset-early)); if (UNLIKELY(early)) memset(&val[CS_KSMPS-early], '\0', early * sizeof(MYFLT)); return OK; } int pvsin_init(CSOUND *csound, FCHAN *p) { int N; MYFLT *pp; PVSDATEXT *f; int n = (int)MYFLT2LRND(*(p->a)); char name[16]; snprintf(name, 16, "%i", n); if (csoundGetChannelPtr(csound, &pp, name, CSOUND_PVS_CHANNEL | CSOUND_INPUT_CHANNEL) == CSOUND_SUCCESS){ int *lock = csoundGetChannelLock(csound, name); f = (PVSDATEXT *) pp; csoundSpinLock(lock); memcpy(&(p->init), f, sizeof(PVSDAT)-sizeof(AUXCH)); csoundSpinUnLock(lock); } N = p->init.N = (int32)(*p->N ? *p->N : p->init.N); p->init.overlap = (int32) (*p->overlap ? *p->overlap : p->init.overlap); p->init.winsize = (int32) (*p->winsize ? *p->winsize : p->init.winsize); p->init.wintype = (int32)(*p->wintype); p->init.format = (int32)(*p->format); p->init.framecount = 0; memcpy(p->r, &p->init, sizeof(PVSDAT)-sizeof(AUXCH)); if (p->r->frame.auxp == NULL || p->r->frame.size < sizeof(float) * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->r->frame); return OK; } int pvsin_perf(CSOUND *csound, FCHAN *p) { PVSDAT *fout = p->r; int n = (int)MYFLT2LRND(*(p->a)); char chan_name[16]; int err, size, *lock; PVSDATEXT *fin; MYFLT *pp; if (UNLIKELY(n < 0)) return csound->PerfError(csound, p->h.insdshead,Str("pvsin: invalid index")); snprintf(chan_name, 16, "%i", n); err = csoundGetChannelPtr(csound, &pp, chan_name, CSOUND_PVS_CHANNEL | CSOUND_INPUT_CHANNEL); fin = (PVSDATEXT *) pp; if (UNLIKELY(err)) return csound->PerfError(csound, p->h.insdshead, Str("pvsin error %d:" "channel not found or not right type"), err); size = fin->N < fout->N ? fin->N : fout->N; lock = csoundGetChannelLock(csound, chan_name); csoundSpinLock(lock); memcpy(fout, fin, sizeof(PVSDAT)-sizeof(AUXCH)); //printf("fout=%p fout->frame.auxp=%p fin=%p fin->frame=%p\n", // fout, fout->frame.auxp, fin, fin->frame); if(fin->frame != NULL) memcpy(fout->frame.auxp, fin->frame, sizeof(float)*(size+2)); else memset(fout->frame.auxp, 0, sizeof(float)*(size+2)); csoundSpinUnLock(lock); return OK; } int pvsout_init(CSOUND *csound, FCHAN *p) { PVSDAT *fin = p->r; MYFLT *pp; PVSDATEXT *f; int n = (int)MYFLT2LRND(*(p->a)); char name[16]; snprintf(name, 16, "%i", n); if (csoundGetChannelPtr(csound, &pp, name, CSOUND_PVS_CHANNEL | CSOUND_OUTPUT_CHANNEL) == CSOUND_SUCCESS){ int *lock = csoundGetChannelLock(csound, name); f = (PVSDATEXT *) pp; csoundSpinLock(lock); if(f->frame == NULL) { f->frame = csound->Calloc(csound, sizeof(float)*(fin->N+2)); } else if(f->N < fin->N) { f->frame = csound->ReAlloc(csound, f->frame, sizeof(float)*(fin->N+2)); } memcpy(f, fin, sizeof(PVSDAT)-sizeof(AUXCH)); csoundSpinUnLock(lock); } return OK; } int pvsout_perf(CSOUND *csound, FCHAN *p) { PVSDAT *fin = p->r; int n = (int)MYFLT2LRND(*(p->a)); char chan_name[16]; int err, size, *lock; PVSDATEXT *fout; MYFLT *pp; if (UNLIKELY(n < 0)) return csound->PerfError(csound, p->h.insdshead,Str("pvsout: invalid index")); snprintf(chan_name, 16, "%i", n); err = csoundGetChannelPtr(csound, &pp, chan_name, CSOUND_PVS_CHANNEL | CSOUND_OUTPUT_CHANNEL); fout = (PVSDATEXT *) pp; if (UNLIKELY(err)) return csound->PerfError(csound, p->h.insdshead, Str("pvsout error %d:" "channel not found or not right type"), err); lock = csoundGetChannelLock(csound, chan_name); csoundSpinLock(lock); size = fin->N < fout->N ? fin->N : fout->N; memcpy(fout, fin, sizeof(PVSDAT)-sizeof(AUXCH)); if(fout->frame != NULL) memcpy(fout->frame, fin->frame.auxp, sizeof(float)*(size+2)); csoundSpinUnLock(lock); return OK; } /* ======================================================================== */ /* "chn" opcodes and bus interface by Istvan Varga */ static int delete_channel_db(CSOUND *csound, void *p) { CONS_CELL *head, *values; IGN(p); if (csound->chn_db == NULL) { return 0; } head = values = cs_hash_table_values(csound, csound->chn_db); if (head != NULL) { while(values != NULL) { CHNENTRY* entry = values->value; if ((entry->type & CSOUND_CHANNEL_TYPE_MASK) != CSOUND_CONTROL_CHANNEL) { csound->Free(csound, entry->hints.attributes); } /* SY - 2014.07.14 - Don't free entry->data and rely on Csound memory db to free it; fixes issue with RTTI and chnexport of a global var, which maps to the CS_VAR_MEM's memblock, which is not what is allocated; other vars will be freed since they were Calloc'd */ /* csound->Free(csound, entry->data); */ entry->datasize = 0; values = values->next; } cs_cons_free(csound, head); } cs_hash_table_mfree_complete(csound, csound->chn_db); csound->chn_db = NULL; return 0; } static inline CHNENTRY *find_channel(CSOUND *csound, const char *name) { if (csound->chn_db != NULL && name[0]) { return (CHNENTRY*) cs_hash_table_get(csound, csound->chn_db, (char*) name); } return NULL; } void set_channel_data_ptr(CSOUND *csound, const char *name, void *ptr, int newSize) { find_channel(csound, name)->data = (MYFLT *) ptr; find_channel(csound, name)->datasize = newSize; } #define INIT_STRING_CHANNEL_DATASIZE 256 static CS_NOINLINE CHNENTRY *alloc_channel(CSOUND *csound, const char *name, int type) { CHNENTRY *pp; int dsize = 0; switch (type & CSOUND_CHANNEL_TYPE_MASK) { case CSOUND_CONTROL_CHANNEL: dsize = sizeof(MYFLT); break; case CSOUND_AUDIO_CHANNEL: dsize = ((int)sizeof(MYFLT) * csound->ksmps); break; case CSOUND_STRING_CHANNEL: dsize = (sizeof(STRINGDAT)); break; case CSOUND_PVS_CHANNEL: dsize = (sizeof(PVSDATEXT)); break; } pp = (CHNENTRY *) csound->Calloc(csound, (size_t) sizeof(CHNENTRY) + strlen(name) + 1); if (pp == NULL) return (CHNENTRY*) NULL; pp->data = (MYFLT *) csound->Calloc(csound, dsize); if ((type & CSOUND_CHANNEL_TYPE_MASK) == CSOUND_STRING_CHANNEL) { ((STRINGDAT*) pp->data)->size = 128; ((STRINGDAT*) pp->data)->data = csound->Calloc(csound, 128 * sizeof(char)); } #ifndef MACOSX #if defined(HAVE_PTHREAD_SPIN_LOCK) pthread_spin_init(&(pp->theLock), PTHREAD_PROCESS_PRIVATE); pp->lock = &(pp->theLock); #endif #endif pp->datasize = dsize; return (CHNENTRY*) pp; } static CS_NOINLINE int create_new_channel(CSOUND *csound, const char *name, int type) { CHNENTRY *pp; /* check for valid parameters and calculate hash value */ if (UNLIKELY(!(type & 48))) return CSOUND_ERROR; /* create new empty database if not allocated */ if (csound->chn_db == NULL) { csound->chn_db = cs_hash_table_create(csound); if (UNLIKELY(csound->RegisterResetCallback(csound, NULL, delete_channel_db) != 0)) return CSOUND_MEMORY; if (UNLIKELY(csound->chn_db == NULL)) return CSOUND_MEMORY; } /* allocate new entry */ pp = alloc_channel(csound, name, type); if (UNLIKELY(pp == NULL)) return CSOUND_MEMORY; pp->hints.behav = 0; pp->type = type; strcpy(&(pp->name[0]), name); cs_hash_table_put(csound, csound->chn_db, (char*)name, pp); return CSOUND_SUCCESS; } PUBLIC int csoundGetChannelPtr(CSOUND *csound, MYFLT **p, const char *name, int type) { CHNENTRY *pp; *p = (MYFLT*) NULL; if (UNLIKELY(name == NULL)) return CSOUND_ERROR; pp = find_channel(csound, name); if (!pp) { if (create_new_channel(csound, name, type) == CSOUND_SUCCESS) { pp = find_channel(csound, name); } } if (pp != NULL) { if ((pp->type ^ type) & CSOUND_CHANNEL_TYPE_MASK) return pp->type; pp->type |= (type & (CSOUND_INPUT_CHANNEL | CSOUND_OUTPUT_CHANNEL)); *p = pp->data; return CSOUND_SUCCESS; } return CSOUND_ERROR; } PUBLIC int csoundGetChannelDatasize(CSOUND *csound, const char *name){ CHNENTRY *pp; pp = find_channel(csound, name); if (pp == NULL) return 0; else { /* the reason for this is that if chnexport is used with strings, the datasize might become invalid */ if ((pp->type & CSOUND_STRING_CHANNEL) == CSOUND_STRING_CHANNEL) return ((STRINGDAT*)pp->data)->size; return pp->datasize; } } PUBLIC int *csoundGetChannelLock(CSOUND *csound, const char *name) { CHNENTRY *pp; if (UNLIKELY(name == NULL)) return NULL; pp = find_channel(csound, name); if (pp) { #ifndef MACOSX #if defined(HAVE_PTHREAD_SPIN_LOCK) return (int*)pp->lock; #else return &(pp->lock); #endif #else return &(pp->lock); #endif } else return NULL; } static int cmp_func(const void *p1, const void *p2) { return strcmp(((controlChannelInfo_t*) p1)->name, ((controlChannelInfo_t*) p2)->name); } PUBLIC int csoundListChannels(CSOUND *csound, controlChannelInfo_t **lst) { CHNENTRY *pp; size_t n; CONS_CELL* channels; *lst = (controlChannelInfo_t*) NULL; if (csound->chn_db == NULL) return 0; channels = cs_hash_table_values(csound, csound->chn_db); n = cs_cons_length(channels); if (!n) return 0; /* create list, initially in unsorted order */ // csound->Malloc and the caller has to free it. // if not, it will be freed on reset *lst = (controlChannelInfo_t*) csound->Malloc(csound, n * sizeof(controlChannelInfo_t)); if (UNLIKELY(*lst == NULL)) return CSOUND_MEMORY; n = 0; while (channels != NULL) { pp = channels->value; (*lst)[n].name = pp->name; (*lst)[n].type = pp->type; (*lst)[n].hints = pp->hints; channels = channels->next; n++; } /* sort list */ qsort((void*) (*lst), n, sizeof(controlChannelInfo_t), cmp_func); /* return the number of channels */ return (int)n; } PUBLIC void csoundDeleteChannelList(CSOUND *csound, controlChannelInfo_t *lst) { //(void) csound; if (lst != NULL) csound->Free(csound, lst); } PUBLIC int csoundSetControlChannelHints(CSOUND *csound, const char *name, controlChannelHints_t hints) { CHNENTRY *pp; if (UNLIKELY(name == NULL)) return CSOUND_ERROR; pp = find_channel(csound, name); if (UNLIKELY(pp == NULL)) return CSOUND_ERROR; if (UNLIKELY((pp->type & CSOUND_CHANNEL_TYPE_MASK) != CSOUND_CONTROL_CHANNEL)) return CSOUND_ERROR; if (hints.behav == CSOUND_CONTROL_CHANNEL_NO_HINTS) { pp->hints.behav = CSOUND_CONTROL_CHANNEL_NO_HINTS; return 0; } if (hints.behav == CSOUND_CONTROL_CHANNEL_INT) { hints.dflt = (MYFLT) ((int32) MYFLT2LRND(hints.dflt)); hints.min = (MYFLT) ((int32) MYFLT2LRND(hints.min)); hints.max = (MYFLT) ((int32) MYFLT2LRND(hints.max)); } if (UNLIKELY(hints.min > hints.max || hints.dflt < hints.min || hints.dflt > hints.max || (hints.behav == CSOUND_CONTROL_CHANNEL_EXP && ((hints.min * hints.max) <= FL(0.0))))) { return CSOUND_ERROR; } pp->hints = hints; if (hints.attributes) { pp->hints.attributes = (char *) csound->Malloc(csound, (strlen(hints.attributes) + 1)* sizeof(char)); strcpy(pp->hints.attributes, hints.attributes); } return CSOUND_SUCCESS; } /** * Returns special parameters (assuming there are any) of a control channel, * previously set with csoundSetControlChannelHints(). * If the channel exists, is a control channel, and has the special parameters * assigned, then the default, minimum, and maximum value is stored in *dflt, * *min, and *max, respectively, and a positive value that is one of * CSOUND_CONTROL_CHANNEL_INT, CSOUND_CONTROL_CHANNEL_LIN, and * CSOUND_CONTROL_CHANNEL_EXP is returned. * In any other case, *dflt, *min, and *max are not changed, and the return * value is zero if the channel exists, is a control channel, but has no * special parameters set; otherwise, a negative error code is returned. */ PUBLIC int csoundGetControlChannelHints(CSOUND *csound, const char *name, controlChannelHints_t *hints) { CHNENTRY *pp; if (UNLIKELY(name == NULL)) return CSOUND_ERROR; pp = find_channel(csound, name); if (pp == NULL) return CSOUND_ERROR; if ((pp->type & CSOUND_CHANNEL_TYPE_MASK) != CSOUND_CONTROL_CHANNEL) return CSOUND_ERROR; if (pp->hints.behav == 0) return CSOUND_ERROR; *hints = pp->hints; if (pp->hints.attributes) { hints->attributes = (char *) csound->Malloc(csound, strlen(pp->hints.attributes) + 1); strcpy(hints->attributes, pp->hints.attributes); } return 0; } /* ------------------------------------------------------------------------ */ /* perf time stub for printing "not initialised" error message */ int notinit_opcode_stub(CSOUND *csound, void *p) { return csound->PerfError(csound, ((CHNGET *)p)->h.insdshead, Str("%s: not initialised"), csound->GetOpcodeName(p)); } /* print error message on failed channel query */ static CS_NOINLINE void print_chn_err_perf(void *p, int err) { CSOUND *csound = ((OPDS*) p)->insdshead->csound; const char *msg; if (((OPDS*) p)->opadr != (SUBR) NULL) ((OPDS*) p)->opadr = (SUBR) notinit_opcode_stub; if (err == CSOUND_MEMORY) msg = "memory allocation failure"; else if (err < 0) msg = "invalid channel name"; else msg = "channel already exists with incompatible type"; csound->Warning(csound, "%s", Str(msg)); } static CS_NOINLINE int print_chn_err(void *p, int err) { CSOUND *csound = ((OPDS*) p)->insdshead->csound; const char *msg; if (((OPDS*) p)->opadr != (SUBR) NULL) ((OPDS*) p)->opadr = (SUBR) notinit_opcode_stub; if (err == CSOUND_MEMORY) msg = "memory allocation failure"; else if (err < 0) msg = "invalid channel name"; else msg = "channel already exists with incompatible type"; return csound->InitError(csound, "%s", Str(msg)); } /* receive control value from bus at performance time */ static int chnget_opcode_perf_k(CSOUND *csound, CHNGET *p) { if(strncmp(p->chname, p->iname->data, MAX_CHAN_NAME)){ int err = csoundGetChannelPtr(csound, &(p->fp), (char*) p->iname->data, CSOUND_CONTROL_CHANNEL | CSOUND_INPUT_CHANNEL); if(err == 0) { p->lock = csoundGetChannelLock(csound, (char*) p->iname->data); strncpy(p->chname, p->iname->data, MAX_CHAN_NAME); } else print_chn_err_perf(p, err); } #if defined(MSVC) volatile union { MYFLT d; MYFLT_INT_TYPE i; } x; x.i = InterlockedExchangeAdd64((MYFLT_INT_TYPE *) p->fp, 0); *(p->arg) = x.d; #elif defined(HAVE_ATOMIC_BUILTIN) volatile union { MYFLT d; MYFLT_INT_TYPE i; } x; x.i = __sync_fetch_and_add((MYFLT_INT_TYPE *) p->fp, 0); *(p->arg) = x.d; #else *(p->arg) = *(p->fp); #endif return OK; } /* receive audio data from bus at performance time */ static int chnget_opcode_perf_a(CSOUND *csound, CHNGET *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; if(strncmp(p->chname, p->iname->data, MAX_CHAN_NAME)){ int err = csoundGetChannelPtr(csound, &(p->fp), (char*) p->iname->data, CSOUND_AUDIO_CHANNEL | CSOUND_INPUT_CHANNEL); if(err == 0) { p->lock = csoundGetChannelLock(csound, (char*) p->iname->data); strncpy(p->chname, p->iname->data, MAX_CHAN_NAME); } else print_chn_err_perf(p, err); } if(CS_KSMPS == (unsigned int) csound->ksmps) { csoundSpinLock(p->lock); if (UNLIKELY(offset)) memset(p->arg, '\0', offset); memcpy(&p->arg[offset], p->fp, sizeof(MYFLT)*(CS_KSMPS-offset-early)); if (UNLIKELY(early)) memset(&p->arg[CS_KSMPS-early], '\0', sizeof(MYFLT)*early); csoundSpinUnLock(p->lock); } else { csoundSpinLock(p->lock); if (UNLIKELY(offset)) memset(p->arg, '\0', offset); memcpy(&p->arg[offset], &(p->fp[offset+p->pos]), sizeof(MYFLT)*(CS_KSMPS-offset-early)); if (UNLIKELY(early)) memset(&p->arg[CS_KSMPS-early], '\0', sizeof(MYFLT)*early); p->pos+=CS_KSMPS; p->pos %= (csound->ksmps-offset); csoundSpinUnLock(p->lock); } return OK; } /* receive control value from bus at init time */ int chnget_opcode_init_i(CSOUND *csound, CHNGET *p) { int err; err = csoundGetChannelPtr(csound, &(p->fp), p->iname->data, CSOUND_CONTROL_CHANNEL | CSOUND_INPUT_CHANNEL); if (UNLIKELY(err)) return print_chn_err(p, err); #if defined(MSVC) { union { MYFLT d; MYFLT_INT_TYPE i; } x; x.i = InterlockedExchangeAdd64((MYFLT_INT_TYPE *)p->fp, 0); *(p->arg) = x.d; } #elif defined(HAVE_ATOMIC_BUILTIN) { union { MYFLT d; MYFLT_INT_TYPE i; } x; x.i = __sync_fetch_and_add((MYFLT_INT_TYPE *) p->fp, 0); *(p->arg) = x.d; } #else *(p->arg) = *(p->fp); #endif return OK; } /* init routine for chnget opcode (control data) */ int chnget_opcode_init_k(CSOUND *csound, CHNGET *p) { int err; err = csoundGetChannelPtr(csound, &(p->fp), (char*) p->iname->data, CSOUND_CONTROL_CHANNEL | CSOUND_INPUT_CHANNEL); p->lock = csoundGetChannelLock(csound, (char*) p->iname->data); if (LIKELY(!err)) { strncpy(p->chname, p->iname->data, MAX_CHAN_NAME); p->h.opadr = (SUBR) chnget_opcode_perf_k; return OK; } return print_chn_err(p, err); } /* init routine for chnget opcode (audio data) */ int chnget_opcode_init_a(CSOUND *csound, CHNGET *p) { int err; p->pos = 0; err = csoundGetChannelPtr(csound, &(p->fp), (char*) p->iname->data, CSOUND_AUDIO_CHANNEL | CSOUND_INPUT_CHANNEL); p->lock = csoundGetChannelLock(csound, (char*) p->iname->data); if (LIKELY(!err)) { strncpy(p->chname, p->iname->data, MAX_CHAN_NAME); p->h.opadr = (SUBR) chnget_opcode_perf_a; return OK; } return print_chn_err(p, err); } /* receive string value from bus at init time */ int chnget_opcode_init_S(CSOUND *csound, CHNGET *p) { int err; char *s = ((STRINGDAT *) p->arg)->data; err = csoundGetChannelPtr(csound, &(p->fp), (char*) p->iname->data, CSOUND_STRING_CHANNEL | CSOUND_INPUT_CHANNEL); p->lock = csoundGetChannelLock(csound, (char*) p->iname->data); if (UNLIKELY(err)) return print_chn_err(p, err); csoundSpinLock(p->lock); if(((STRINGDAT *) p->fp)->data != NULL) { if(((STRINGDAT *) p->fp)->size > ((STRINGDAT *) p->arg)->size) { if(s != NULL) csound->Free(csound, s); s = cs_strdup(csound,((STRINGDAT *) p->fp)->data); ((STRINGDAT *) p->arg)->data = s; ((STRINGDAT *) p->arg)->size = strlen(s) + 1; } else strcpy(((STRINGDAT *) p->arg)->data, ((STRINGDAT *) p->fp)->data); } csoundSpinUnLock(p->lock); return OK; } int chnget_opcode_perf_S(CSOUND *csound, CHNGET *p) { int err; char *s = ((STRINGDAT *) p->arg)->data; err = csoundGetChannelPtr(csound, &(p->fp), (char*) p->iname->data, CSOUND_STRING_CHANNEL | CSOUND_INPUT_CHANNEL); p->lock = csoundGetChannelLock(csound, (char*) p->iname->data); if (UNLIKELY(err)) return print_chn_err(p, err); if(s != NULL && ((STRINGDAT *) p->fp)->data != NULL && strcmp(s, ((STRINGDAT *) p->fp)->data) == 0) return OK; csoundSpinLock(p->lock); if(((STRINGDAT *) p->fp)->data != NULL){ if(((STRINGDAT *) p->arg)->size <= ((STRINGDAT *) p->fp)->size) { if(s != NULL) csound->Free(csound, s); s = cs_strdup(csound,((STRINGDAT *) p->fp)->data); ((STRINGDAT *) p->arg)->data = s; ((STRINGDAT *) p->arg)->size = strlen(s) + 1; } else strcpy (((STRINGDAT *) p->arg)->data, ((STRINGDAT *) p->fp)->data); } csoundSpinUnLock(p->lock); return OK; } /* send control value to bus at performance time */ static int chnset_opcode_perf_k(CSOUND *csound, CHNGET *p) { if(strncmp(p->chname, p->iname->data, MAX_CHAN_NAME)){ int err = csoundGetChannelPtr(csound, &(p->fp), (char*) p->iname->data, CSOUND_CONTROL_CHANNEL | CSOUND_INPUT_CHANNEL); if(err == 0) { p->lock = csoundGetChannelLock(csound, (char*) p->iname->data); strncpy(p->chname, p->iname->data, MAX_CHAN_NAME); } else print_chn_err_perf(p, err); } #if defined(MSVC) volatile union { MYFLT d; MYFLT_INT_TYPE i; } x; x.d = *(p->arg); InterlockedExchange64((MYFLT_INT_TYPE *) p->fp, x.i); #elif defined(HAVE_ATOMIC_BUILTIN) union { MYFLT d; MYFLT_INT_TYPE i; } x; x.d = *(p->arg); __sync_lock_test_and_set((MYFLT_INT_TYPE *)(p->fp),x.i); #else csoundSpinLock(p->lock); *(p->fp) = *(p->arg); csoundSpinUnLock(p->lock); #endif return OK; } /* send audio data to bus at performance time */ static int chnset_opcode_perf_a(CSOUND *csound, CHNGET *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; if(CS_KSMPS == (unsigned int) csound->ksmps){ /* Need lock for the channel */ csoundSpinLock(p->lock); if (UNLIKELY(offset)) memset(p->fp, '\0', sizeof(MYFLT)*offset); memcpy(&p->fp[offset], &p->arg[offset], sizeof(MYFLT)*(CS_KSMPS-offset-early)); if (UNLIKELY(early)) memset(&p->fp[early], '\0', sizeof(MYFLT)*(CS_KSMPS-early)); csoundSpinUnLock(p->lock); } else { /* Need lock for the channel */ csoundSpinLock(p->lock); if (UNLIKELY(offset)) memset(p->fp, '\0', sizeof(MYFLT)*offset); memcpy(&p->fp[offset+p->pos], &p->arg[offset], sizeof(MYFLT)*(CS_KSMPS-offset-early)); if (UNLIKELY(early)) memset(&p->fp[early], '\0', sizeof(MYFLT)*(CS_KSMPS-early)); p->pos += CS_KSMPS; p->pos %= (csound->ksmps-offset); csoundSpinUnLock(p->lock); } return OK; } /* send audio data to bus at performance time, mixing to previous output */ static int chnmix_opcode_perf(CSOUND *csound, CHNGET *p) { uint32_t n = 0; IGN(csound); uint32_t nsmps = CS_KSMPS; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; if (UNLIKELY(early)) nsmps -= early; /* Need lock for the channel */ csoundSpinLock(p->lock); for (n=offset; nfp[n] += p->arg[n]; } csoundSpinUnLock(p->lock); return OK; } /* clear an audio channel to zero at performance time */ static int chnclear_opcode_perf(CSOUND *csound, CHNCLEAR *p) { /* Need lock for the channel */ IGN(csound); csoundSpinLock(p->lock); memset(p->fp, 0, CS_KSMPS*sizeof(MYFLT)); /* Should this leave start? */ csoundSpinUnLock(p->lock); return OK; } /* send control value to bus at init time */ int chnset_opcode_init_i(CSOUND *csound, CHNGET *p) { int err; err = csoundGetChannelPtr(csound, &(p->fp), (char*) p->iname->data, CSOUND_CONTROL_CHANNEL | CSOUND_OUTPUT_CHANNEL); if (UNLIKELY(err)) return print_chn_err(p, err); #if defined(MSVC) volatile union { MYFLT d; MYFLT_INT_TYPE i; } x; x.d = *(p->arg); InterlockedExchange64((MYFLT_INT_TYPE *) p->fp, x.i); #elif defined(HAVE_ATOMIC_BUILTIN) union { MYFLT d; MYFLT_INT_TYPE i; } x; x.d = *(p->arg); __sync_lock_test_and_set((MYFLT_INT_TYPE *)(p->fp),x.i); #else { int *lock; /* Need lock for the channel */ p->lock = lock = csoundGetChannelLock(csound, (char*) p->iname->data); csoundSpinLock(lock); *(p->fp) = *(p->arg); csoundSpinUnLock(lock); } #endif return OK; } /* init routine for chnset opcode (control data) */ int chnset_opcode_init_k(CSOUND *csound, CHNGET *p) { int err; err = csoundGetChannelPtr(csound, &(p->fp), (char*) p->iname->data, CSOUND_CONTROL_CHANNEL | CSOUND_OUTPUT_CHANNEL); if (LIKELY(!err)) { p->lock = csoundGetChannelLock(csound, (char*) p->iname->data); p->h.opadr = (SUBR) chnset_opcode_perf_k; return OK; } return print_chn_err(p, err); } /* init routine for chnset opcode (audio data) */ int chnset_opcode_init_a(CSOUND *csound, CHNGET *p) { int err; p->pos = 0; err = csoundGetChannelPtr(csound, &(p->fp), (char*) p->iname->data, CSOUND_AUDIO_CHANNEL | CSOUND_OUTPUT_CHANNEL); if (!err) { p->lock = csoundGetChannelLock(csound, (char*) p->iname->data); p->h.opadr = (SUBR) chnset_opcode_perf_a; return OK; } return print_chn_err(p, err); } /* init routine for chnmix opcode */ int chnmix_opcode_init(CSOUND *csound, CHNGET *p) { int err; err = csoundGetChannelPtr(csound, &(p->fp), (char*) p->iname->data, CSOUND_AUDIO_CHANNEL | CSOUND_OUTPUT_CHANNEL); if (LIKELY(!err)) { p->lock = csoundGetChannelLock(csound, (char*) p->iname->data); p->h.opadr = (SUBR) chnmix_opcode_perf; return OK; } return print_chn_err(p, err); } /* init routine for chnclear opcode */ int chnclear_opcode_init(CSOUND *csound, CHNCLEAR *p) { int err; /* NOTE: p->imode is a pointer to the channel data here */ err = csoundGetChannelPtr(csound, &(p->fp), (char*) p->iname->data, CSOUND_AUDIO_CHANNEL | CSOUND_OUTPUT_CHANNEL); if (LIKELY(!err)) { p->lock = csoundGetChannelLock(csound, (char*) p->iname->data); p->h.opadr = (SUBR) chnclear_opcode_perf; return OK; } return print_chn_err(p, err); } /* send string to bus at init time */ int chnset_opcode_init_S(CSOUND *csound, CHNGET *p) { int err; int *lock; char *s = ((STRINGDAT *) p->arg)->data; err = csoundGetChannelPtr(csound, &(p->fp), (char*) p->iname->data, CSOUND_STRING_CHANNEL | CSOUND_OUTPUT_CHANNEL); // size = csoundGetChannelDatasize(csound, p->iname->data); if (UNLIKELY(err)) { return print_chn_err(p, err); } if (s==NULL) return NOTOK; p->lock = lock = csoundGetChannelLock(csound, (char*) p->iname->data); csoundSpinLock(lock); if (strlen(s) >= (unsigned int) ((STRINGDAT *)p->fp)->size) { if (((STRINGDAT *)p->fp)->data != NULL) csound->Free(csound, ((STRINGDAT *)p->fp)->data); ((STRINGDAT *)p->fp)->data = cs_strdup(csound, s); ((STRINGDAT *)p->fp)->size = strlen(s)+1; //set_channel_data_ptr(csound, p->iname->data,p->fp, strlen(s)+1); } else if(((STRINGDAT *)p->fp)->data != NULL) strcpy(((STRINGDAT *)p->fp)->data, s); csoundSpinUnLock(lock); return OK; } int chnset_opcode_perf_S(CSOUND *csound, CHNGET *p) { int err; int *lock; char *s = ((STRINGDAT *) p->arg)->data; if ((err=csoundGetChannelPtr(csound, &(p->fp), (char*) p->iname->data, CSOUND_STRING_CHANNEL | CSOUND_OUTPUT_CHANNEL))) return err; // size = csoundGetChannelDatasize(csound, p->iname->data); if (s==NULL) return NOTOK; if (((STRINGDAT *)p->fp)->data && strcmp(s, ((STRINGDAT *)p->fp)->data) == 0) return OK; p->lock = lock = csoundGetChannelLock(csound, (char*) p->iname->data); csoundSpinLock(lock); if (strlen(s) >= (unsigned int) ((STRINGDAT *)p->fp)->size) { if (((STRINGDAT *)p->fp)->data != NULL) csound->Free(csound, ((STRINGDAT *)p->fp)->data); ((STRINGDAT *)p->fp)->data = cs_strdup(csound, s); ((STRINGDAT *)p->fp)->size = strlen(s)+1; //set_channel_data_ptr(csound, p->iname->data,p->fp, strlen(s)+1); //printf("p: %s: %s \n", p->iname->data, ((STRINGDAT *)p->fp)->data); } else if(((STRINGDAT *)p->fp)->data != NULL) strcpy(((STRINGDAT *)p->fp)->data, s); csoundSpinUnLock(lock); //printf("%s \n", (char *)p->fp); return OK; } /* declare control channel, optionally with special parameters */ int chn_k_opcode_init(CSOUND *csound, CHN_OPCODE_K *p) { MYFLT *dummy; int type, mode, err; controlChannelHints_t hints; hints.attributes = NULL; hints.max = hints.min = hints.dflt = FL(0.0); hints.x = hints.y = hints.height = hints.width = 0; mode = (int)MYFLT2LRND(*(p->imode)); if (UNLIKELY(mode < 1 || mode > 3)) return csound->InitError(csound, Str("invalid mode parameter")); type = CSOUND_CONTROL_CHANNEL; if (mode & 1) type |= CSOUND_INPUT_CHANNEL; if (mode & 2) type |= CSOUND_OUTPUT_CHANNEL; err = csoundGetChannelPtr(csound, &dummy, (char*) p->iname->data, type); if (err) return print_chn_err(p, err); hints.behav = CSOUND_CONTROL_CHANNEL_NO_HINTS; if ((int)MYFLT2LRND(*(p->itype)) == 1) hints.behav = CSOUND_CONTROL_CHANNEL_INT; else if ((int)MYFLT2LRND(*(p->itype)) == 2) hints.behav |= CSOUND_CONTROL_CHANNEL_LIN; else if ((int)MYFLT2LRND(*(p->itype)) == 3) hints.behav |= CSOUND_CONTROL_CHANNEL_EXP; if ((int)MYFLT2LRND(*(p->itype)) != 0) { hints.attributes = 0; if (p->INOCOUNT > 10) { hints.attributes = p->Sattributes->data; } hints.dflt = *(p->idflt); hints.min = *(p->imin); hints.max = *(p->imax); hints.x = *(p->ix); hints.y = *(p->iy); hints.width = *(p->iwidth); hints.height = *(p->iheight); } err = csoundSetControlChannelHints(csound, (char*) p->iname->data, hints); if (LIKELY(!err)) { p->lock = csoundGetChannelLock(csound, (char*) p->iname->data); return OK; } if (err == CSOUND_MEMORY) return print_chn_err(p, err); return csound->InitError(csound, Str("invalid channel parameters")); } /* declare audio channel */ int chn_a_opcode_init(CSOUND *csound, CHN_OPCODE *p) { MYFLT *dummy; int type, mode, err; mode = (int)MYFLT2LRND(*(p->imode)); if (UNLIKELY(mode < 1 || mode > 3)) return csound->InitError(csound, Str("invalid mode parameter")); type = CSOUND_AUDIO_CHANNEL; if (mode & 1) type |= CSOUND_INPUT_CHANNEL; if (mode & 2) type |= CSOUND_OUTPUT_CHANNEL; err = csoundGetChannelPtr(csound, &dummy, (char*) p->iname->data, type); if (UNLIKELY(err)) return print_chn_err(p, err); return OK; } /* declare string channel */ int chn_S_opcode_init(CSOUND *csound, CHN_OPCODE *p) { MYFLT *dummy; int type, mode, err; mode = (int)MYFLT2LRND(*(p->imode)); if (UNLIKELY(mode < 1 || mode > 3)) return csound->InitError(csound, Str("invalid mode parameter")); type = CSOUND_STRING_CHANNEL; if (mode & 1) type |= CSOUND_INPUT_CHANNEL; if (mode & 2) type |= CSOUND_OUTPUT_CHANNEL; err = csoundGetChannelPtr(csound, &dummy, (char*) p->iname->data, type); if (UNLIKELY(err)) return print_chn_err(p, err); p->lock = csoundGetChannelLock(csound, (char*) p->iname->data); return OK; } /* export new channel from global orchestra variable */ int chnexport_opcode_init(CSOUND *csound, CHNEXPORT_OPCODE *p) { MYFLT *dummy; const char *argName; int type = CSOUND_CONTROL_CHANNEL, mode, err; controlChannelHints_t hints; CHNENTRY *chn; /* must have an output argument of type 'gi', 'gk', 'ga', or 'gS' */ if (UNLIKELY(csound->GetOutputArgCnt(p) != 1)) goto arg_err; argName = csound->GetOutputArgName(p, 0); if (UNLIKELY(argName == NULL)) goto arg_err; if (UNLIKELY(argName[0] != 'g')) goto arg_err; switch ((int)argName[1]) { case 'i': case 'k': break; case 'a': type = CSOUND_AUDIO_CHANNEL; break; case 'S': type = CSOUND_STRING_CHANNEL; break; default: goto arg_err; } /* mode (input and/or output) */ mode = (int)MYFLT2LRND(*(p->imode)); if (UNLIKELY(mode < 1 || mode > 3)) return csound->InitError(csound, Str("invalid mode parameter")); if (mode & 1) type |= CSOUND_INPUT_CHANNEL; if (mode & 2) type |= CSOUND_OUTPUT_CHANNEL; /* check if the channel already exists (it should not) */ err = csoundGetChannelPtr(csound, &dummy, (char*) p->iname->data, 0); if (UNLIKELY(err >= 0)) return csound->InitError(csound, Str("channel already exists")); /* now create new channel, using output variable for data storage */ // dummy = p->arg; /* THIS NEEDS A LOCK BUT DOES NOT EXIST YET */ /* lock = csoundGetChannelLock(csound, (char*) p->iname->data); */ /* csoundSpinLock(lock); */ err = create_new_channel(csound, (char*) p->iname->data, type); /* csoundSpinLock(lock); */ if (err) return print_chn_err(p, err); /* Now we need to find the channel entry */ chn = find_channel(csound, (char*) p->iname->data); /* free the allocated memory (we will not use it) */ csound->Free(csound, chn->data); /* point to the arg var */ chn->data = p->arg; /* if control channel, set additional parameters */ if ((type & CSOUND_CHANNEL_TYPE_MASK) != CSOUND_CONTROL_CHANNEL) return OK; type = (int)MYFLT2LRND(*(p->itype)); hints.behav = CSOUND_CONTROL_CHANNEL_LIN; hints.dflt = *(p->idflt); hints.min = *(p->imin); hints.max = *(p->imax); hints.attributes = NULL; err = csoundSetControlChannelHints(csound, (char*) p->iname->data, hints); if (LIKELY(!err)) return OK; if (err == CSOUND_MEMORY) return print_chn_err(p, err); return csound->InitError(csound, Str("invalid channel parameters")); arg_err: return csound->InitError(csound, Str("invalid export variable")); } /* returns all parameters of a channel */ int chnparams_opcode_init(CSOUND *csound, CHNPARAMS_OPCODE *p) { MYFLT *dummy; int err; /* all values default to zero... */ *(p->itype) = FL(0.0); *(p->imode) = FL(0.0); *(p->ictltype) = FL(0.0); *(p->idflt) = FL(0.0); *(p->imin) = FL(0.0); *(p->imax) = FL(0.0); err = csoundGetChannelPtr(csound, &dummy, (char*) p->iname->data, 0); /* ...if channel does not exist */ if (err <= 0) return OK; /* type (control/audio/string) */ *(p->itype) = (MYFLT) (err & 15); /* mode (input and/or output) */ *(p->imode) = (MYFLT) ((err & 48) >> 4); /* check for control channel parameters */ if ((err & 15) == CSOUND_CONTROL_CHANNEL) { controlChannelHints_t hints; err = csoundGetControlChannelHints(csound, (char*) p->iname->data, &hints); if (UNLIKELY(err > 0)) *(p->ictltype) = (MYFLT) err; *(p->ictltype) = hints.behav; *(p->idflt) = hints.dflt; *(p->imin) = hints.min; *(p->imax) = hints.max; } return OK; } /* ********************************************************************** */ /* *************** SENSING ********************************************** */ /* ********************************************************************** */ int sensekey_perf(CSOUND *csound, KSENSE *p) { int keyCode = 0; int retval; retval = csound->doCsoundCallback(csound, &keyCode, (p->keyDown != NULL ? CSOUND_CALLBACK_KBD_EVENT : CSOUND_CALLBACK_KBD_TEXT)); if (retval > 0) { if (!p->evtbuf) { #if defined(__unix) || defined(__unix__) || defined(__MACH__) if (csound->inChar_ < 0) { # if defined(WIN32) setvbuf(stdin, NULL, _IONBF, 0); /* Does not seem to work */ # elif defined(HAVE_TERMIOS_H) struct termios tty; tcgetattr(0, &tty); tty.c_lflag &= (~ICANON); tcsetattr(0, TCSANOW, &tty); # endif } #endif p->evtbuf = -1; } if (csound->inChar_ < 0) { #if defined(__unix) || defined(__unix__) || defined(__MACH__) fd_set rfds; struct timeval tv; /* Watch stdin (fd 0) to see when it has input. */ FD_ZERO(&rfds); FD_SET(0, &rfds); /* No waiting */ tv.tv_sec = 0; tv.tv_usec = 0; retval = select(1, &rfds, NULL, NULL, &tv); if (retval>0) { char ch = '\0'; int n=0; if (UNLIKELY((n=read(0, &ch, 1))<0)) { csound->PerfError(csound, p->h.insdshead, Str("read failure in sensekey\n")); return NOTOK; } //if n==0 then EOF which we treat as empty if(n==0) ch = '\0'; keyCode = (int)((unsigned char) ch); /* FD_ISSET(0, &rfds) will be true. */ } else if (retval<0) perror(Str("sensekey error:")); #else unsigned char ch = (unsigned char) '\0'; # ifdef WIN32 if (_kbhit()) ch = (unsigned char) _getch(); # else ch = (unsigned char) getchar(); # endif keyCode = (int)ch; #endif } else if (csound->inChar_ > 0) { keyCode = csound->inChar_; csound->inChar_ = 0; } if (p->evtbuf != -1) { int tmp = keyCode; keyCode = p->evtbuf; tmp = (keyCode < 0 ? tmp : (-1 - keyCode)); p->evtbuf = (tmp != 0 ? tmp : -1); } else if (p->OUTOCOUNT>1 && p->keyDown != NULL) p->evtbuf = -1 - keyCode; if (keyCode < 0) keyCode = 65535 - keyCode; } else if (retval < 0) { keyCode = 0; } *(p->ans) = (MYFLT) ((keyCode & (int)0xFFFF) ? (keyCode & (int)0xFFFF) : -1); if (p->OUTOCOUNT>1 && p->keyDown != NULL) *(p->keyDown) = (MYFLT) ((keyCode > 0 && keyCode < 65536) ? 1 : 0); return OK; } /* k-rate and string i/o opcodes */ /* invalue and outvalue are used with the csoundAPI */ /* ma++ ingalls matt@sonomatics.com */ int kinval(CSOUND *csound, INVAL *p) { if (csound->InputChannelCallback_) { csound->InputChannelCallback_(csound, (char*) p->channelName.auxp, p->value, p->channelType); } else *(p->value) = FL(0.0); return OK; } int kinvalS(CSOUND *csound, INVAL *p) { if (csound->InputChannelCallback_) { csound->InputChannelCallback_(csound, (char*) p->channelName.auxp, ((STRINGDAT *)p->value)->data, p->channelType); } else { ((STRINGDAT *)p->value)->data[0] = '\0'; } return OK; } int invalset_string_S(CSOUND *csound, INVAL *p) { int err; int type; STRINGDAT *out = (STRINGDAT *) p->value; const char *s = ((STRINGDAT *)p->valID)->data; csound->AuxAlloc(csound, strlen(s) + 1, &p->channelName); strcpy((char*) p->channelName.auxp, s); p->channelType = &CS_VAR_TYPE_S; type = CSOUND_STRING_CHANNEL | CSOUND_INPUT_CHANNEL; err = csoundGetChannelPtr(csound, (MYFLT **) &(p->channelptr), (char*) p->channelName.auxp, type); if (UNLIKELY(err)) return print_chn_err(p, err); if (out->data == NULL || out->size < 256) { if(out->data != NULL) csound->Free(csound, out->data); out->data = csound->Calloc(csound, 256); out->size = 256; } /* grab input now for use during i-pass */ kinvalS(csound, p); if (!csound->InputChannelCallback_) { csound->Warning(csound,Str("InputChannelCallback not set.")); } return OK; } int invalset_S(CSOUND *csound, INVAL *p) { int err; int type; const char *s = ((STRINGDAT *)p->valID)->data; csound->AuxAlloc(csound, strlen(s) + 1, &p->channelName); strcpy((char*) p->channelName.auxp, s); p->channelType = &CS_VAR_TYPE_K; type = CSOUND_CONTROL_CHANNEL | CSOUND_INPUT_CHANNEL; err = csoundGetChannelPtr(csound, (MYFLT **) &(p->channelptr), (char*) p->channelName.auxp, type); if (UNLIKELY(err)) return print_chn_err(p, err); /* grab input now for use during i-pass */ kinval(csound, p); if (!csound->InputChannelCallback_) { csound->Warning(csound,Str("InputChannelCallback not set.")); } return OK; } int invalsetgo(CSOUND *csound, INVAL *p) { int ans = invalset(csound, p); if (ans==OK) ans = kinval(csound, p); return ans; } int invalsetSgo(CSOUND *csound, INVAL *p) { int ans = invalset_S(csound, p); if (ans==OK) ans = kinval(csound, p); return ans; } int invalset_string(CSOUND *csound, INVAL *p) { int err; int type; /* convert numerical channel to string name */ csound->AuxAlloc(csound, 64, &p->channelName); snprintf((char*) p->channelName.auxp, 64, "%d", (int)MYFLT2LRND(*p->valID)); p->channelType = &CS_VAR_TYPE_S; type = CSOUND_STRING_CHANNEL | CSOUND_INPUT_CHANNEL; err = csoundGetChannelPtr(csound, (MYFLT **) &(p->channelptr), (char*) p->channelName.auxp, type); if (UNLIKELY(err)) return print_chn_err(p, err); /* grab input now for use during i-pass */ kinvalS(csound, p); if (!csound->InputChannelCallback_) { csound->Warning(csound,Str("InputChannelCallback not set.")); } return OK; } int invalset(CSOUND *csound, INVAL *p) { int err; int type; /* convert numerical channel to string name */ csound->AuxAlloc(csound, 32, &p->channelName); snprintf((char*) p->channelName.auxp, 32, "%d", (int)MYFLT2LRND(*p->valID)); p->channelType = &CS_VAR_TYPE_K; type = CSOUND_CONTROL_CHANNEL | CSOUND_INPUT_CHANNEL; err = csoundGetChannelPtr(csound, (MYFLT **) &(p->channelptr), (char*) p->channelName.auxp, type); if (UNLIKELY(err)) return print_chn_err(p, err); /* grab input now for use during i-pass */ kinval(csound, p); if (!csound->InputChannelCallback_) { csound->Warning(csound,Str("InputChannelCallback not set.")); } return OK; } int koutvalS(CSOUND *csound, OUTVAL *p) { char *chan = (char*)p->channelName.auxp; if (csound->OutputChannelCallback_) { csound->OutputChannelCallback_(csound, chan, ((STRINGDAT *)p->value)->data, p->channelType); } return OK; } int koutval(CSOUND *csound, OUTVAL *p) { char *chan = (char*)p->channelName.auxp; if (csound->OutputChannelCallback_) { csound->OutputChannelCallback_(csound, chan, p->value, p->channelType); *((MYFLT *) p->channelptr) = *(p->value); } return OK; } int outvalset_string_S(CSOUND *csound, OUTVAL *p) { int type, err; const char *s = ((STRINGDAT *)p->valID)->data; csound->AuxAlloc(csound, strlen(s) + 1, &p->channelName); strcpy((char*) p->channelName.auxp, s); p->channelType = &CS_VAR_TYPE_S; type = CSOUND_STRING_CHANNEL | CSOUND_OUTPUT_CHANNEL; err = csoundGetChannelPtr(csound, (MYFLT **) &(p->channelptr), (char*) p->channelName.auxp, type); if (UNLIKELY(err)) return print_chn_err(p, err); /* send output now for use during i-pass */ koutvalS(csound, p); if (!csound->OutputChannelCallback_) { csound->Warning(csound,Str("OutputChannelCallback not set.")); } return OK; } int outvalset_S(CSOUND *csound, OUTVAL *p) { int type, err; const char *s = ((STRINGDAT *)p->valID)->data; csound->AuxAlloc(csound, strlen(s) + 1, &p->channelName); strcpy((char*) p->channelName.auxp, s); p->channelType = &CS_VAR_TYPE_K; type = CSOUND_CONTROL_CHANNEL | CSOUND_OUTPUT_CHANNEL; err = csoundGetChannelPtr(csound, (MYFLT **) &(p->channelptr), (char*) p->channelName.auxp, type); if (UNLIKELY(err)) return print_chn_err(p, err); /* send output now for use during i-pass */ koutval(csound, p); if (!csound->OutputChannelCallback_) { csound->Warning(csound,Str("OutputChannelCallback not set.")); } return OK; } int outvalset_string(CSOUND *csound, OUTVAL *p) { int type, err; /* convert numerical channel to string name */ if(p->channelName.auxp == NULL) csound->AuxAlloc(csound, 32, &p->channelName); snprintf((char*)p->channelName.auxp, 32, "%d", (int)MYFLT2LRND(*p->valID)); p->channelType = &CS_VAR_TYPE_S; type = CSOUND_STRING_CHANNEL | CSOUND_OUTPUT_CHANNEL; err = csoundGetChannelPtr(csound, (MYFLT **) &(p->channelptr), (char*) p->channelName.auxp, type); if (UNLIKELY(err)) return print_chn_err(p, err); /* send output now for use during i-pass */ koutvalS(csound, p); if (!csound->OutputChannelCallback_) { csound->Warning(csound,Str("OutputChannelCallback not set.")); } return OK; } int outvalset(CSOUND *csound, OUTVAL *p) { int type, err; /* convert numerical channel to string name */ csound->AuxAlloc(csound, 64, &p->channelName); snprintf((char*)p->channelName.auxp, 64, "%d", (int)MYFLT2LRND(*p->valID)); p->channelType = &CS_VAR_TYPE_K; type = CSOUND_CONTROL_CHANNEL | CSOUND_OUTPUT_CHANNEL; err = csoundGetChannelPtr(csound,(MYFLT **) &(p->channelptr), (char*) p->channelName.auxp, type); if (UNLIKELY(err)) return print_chn_err(p, err); /* send output now for use during i-pass */ koutval(csound, p); if (!csound->OutputChannelCallback_) { csound->Warning(csound,Str("OutputChannelCallback not set.")); } return OK; } int outvalsetgo(CSOUND *csound, OUTVAL *p) { int ans = outvalset(csound,p); if (ans==OK) ans = koutval(csound,p); return ans; } int outvalsetSgo(CSOUND *csound, OUTVAL *p) { int ans = outvalset_S(csound,p); if (ans==OK) ans = koutval(csound,p); return ans; } csound-6.10.0/OOps/cmath.c000066400000000000000000000561151321653344700152310ustar00rootroot00000000000000/* cmath.c: Copyright (C) 1994 Paris Smaragdis, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Math functions for Csound coded by Paris Smaragdis 1994 */ /* Berklee College of Music Csound development team */ #include "csoundCore.h" #include "cmath.h" #include int ipow(CSOUND *csound, POW *p) /* Power for i-rate */ { MYFLT in = *p->in; MYFLT powerOf = *p->powerOf; if (UNLIKELY(in == FL(0.0) && powerOf == FL(0.0))) return csound->PerfError(csound, p->h.insdshead, Str("NaN in pow\n")); else if (p->norm!=NULL && *p->norm != FL(0.0)) *p->sr = POWER(in, powerOf) / *p->norm; else *p->sr = POWER(in, powerOf); return OK; } int apow(CSOUND *csound, POW *p) /* Power routine for a-rate */ { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *in = p->in, *out = p->sr; MYFLT powerOf = *p->powerOf; MYFLT norm = (p->norm!=NULL ? *p->norm : FL(1.0)); if (norm==FL(0.0)) norm = FL(1.0); memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } if (UNLIKELY(powerOf == FL(0.0))) { MYFLT yy = FL(1.0) / norm; for (n = offset; n < nsmps; n++) { MYFLT xx = in[n]; if (UNLIKELY(xx == FL(0.0))) { return csound->PerfError(csound, p->h.insdshead,Str("NaN in pow\n")); } else out[n] = yy; } } else { for (n = offset; n < nsmps; n++) out[n] = POWER(in[n], powerOf) / norm; } return OK; } int seedrand(CSOUND *csound, PRAND *p) { uint32_t seedVal = (uint32_t)0; int32 xx = (int32)((double)*p->out + 0.5); if (xx > FL(0.0)) seedVal = (uint32_t)xx; else if (xx==0) { seedVal = (uint32_t)csound->GetRandomSeedFromTime(); csound->Warning(csound, Str("Seeding from current time %u\n"), (unsigned int)seedVal); } else csound->Warning(csound, Str("Seeding with %u\n"), (unsigned int)seedVal); csound->SeedRandMT(&(csound->randState_), NULL, seedVal); csound->holdrand = (int)(seedVal & (uint32_t) 0x7FFFFFFF); while (seedVal >= (uint32_t)0x7FFFFFFE) seedVal -= (uint32_t)0x7FFFFFFE; csound->randSeed1 = ((int)seedVal + 1); return OK; } int getseed(CSOUND *csound, GETSEED *p) { *p->ans = csound->randSeed1; return OK; } /* * * * * * RANDOM NUMBER GENERATORS * * * * * */ #define UInt32toFlt(x) ((double)(x) * (1.0 / 4294967295.03125)) #define unirand(c) ((MYFLT) UInt32toFlt(csoundRandMT(&((c)->randState_)))) static inline MYFLT unifrand(CSOUND *csound, MYFLT range) { return (range * unirand(csound)); } /* linear distribution routine */ static inline MYFLT linrand(CSOUND *csound, MYFLT range) { uint32_t r1, r2; r1 = csoundRandMT(&(csound->randState_)); r2 = csoundRandMT(&(csound->randState_)); return ((MYFLT)UInt32toFlt(r1 < r2 ? r1 : r2) * range); } /* triangle distribution routine */ static inline MYFLT trirand(CSOUND *csound, MYFLT range) { uint64_t r1; r1 = (uint64_t)csoundRandMT(&(csound->randState_)); r1 += (uint64_t)csoundRandMT(&(csound->randState_)); return ((MYFLT) ((double)((int64_t)r1 - (int64_t)0xFFFFFFFFU) * (1.0 / 4294967295.03125)) * range); } /* exponential distribution routine */ static MYFLT exprand(CSOUND *csound, MYFLT lambda) { uint32_t r1; if (UNLIKELY(lambda < FL(0.0))) return (FL(0.0)); /* for safety */ do { r1 = csoundRandMT(&(csound->randState_)); } while (!r1); return -((MYFLT)log(UInt32toFlt(r1)) * lambda); } /* bilateral exponential distribution routine */ static MYFLT biexprand(CSOUND *csound, MYFLT range) { int32_t r1; if (UNLIKELY(range < FL(0.0))) return (FL(0.0)); /* For safety */ while ((r1 = (int32_t)csoundRandMT(&(csound->randState_)))==0); if (r1 < (int32_t)0) { return -(LOG(-(r1) * (FL(1.0) / FL(2147483648.0))) * range); } return (LOG(r1 * (FL(1.0) / FL(2147483648.0))) * range); } /* gaussian distribution routine */ static MYFLT gaussrand(CSOUND *csound, MYFLT s) { int64_t r1 = -((int64_t)0xFFFFFFFFU * 6); int n = 12; double x; do { r1 += (int64_t)csoundRandMT(&(csound->randState_)); } while (--n); x = (double)r1; return (MYFLT)(x * ((double)s * (1.0 / (3.83 * 4294967295.03125)))); } /* cauchy distribution routine */ static MYFLT cauchrand(CSOUND *csound, MYFLT a) { uint32_t r1; MYFLT x; do { r1 = csoundRandMT(&(csound->randState_)); /* Limit range artificially */ } while (r1 > (uint32_t)2143188560U && r1 < (uint32_t)2151778735U); x = TAN((MYFLT)r1 * (PI_F / FL(4294967295.0))) * (FL(1.0) / FL(318.3)); return (x * a); } /* positive cauchy distribution routine */ static MYFLT pcauchrand(CSOUND *csound, MYFLT a) { uint32_t r1; MYFLT x; do { r1 = csoundRandMT(&(csound->randState_)); } while (r1 > (uint32_t)4286377121U); /* Limit range artificially */ x = TAN((MYFLT)r1 * (PI_F * FL(0.5) / FL(4294967295.0))) * (FL(1.0) / FL(318.3)); return (x * a); } /* beta distribution routine */ static MYFLT betarand(CSOUND *csound, MYFLT range, MYFLT a, MYFLT b) { double r1, r2; double aa, bb; if (UNLIKELY(a <= FL(0.0) || b <= FL(0.0))) return FL(0.0); aa = (double)a; bb = (double)b; do { uint32_t tmp; do { tmp = csoundRandMT(&(csound->randState_)); } while (!tmp); r1 = pow(UInt32toFlt(tmp), 1.0 / aa); do { tmp = csoundRandMT(&(csound->randState_)); } while (!tmp); r2 = r1 + pow(UInt32toFlt(tmp), 1.0 / bb); } while (r2 > 1.0); return (((MYFLT)r1 / (MYFLT)r2) * range); } /* weibull distribution routine */ static MYFLT weibrand(CSOUND *csound, MYFLT s, MYFLT t) { uint32_t r1; double r2; if (UNLIKELY(t <= FL(0.0))) return FL(0.0); do { r1 = csoundRandMT(&(csound->randState_)); } while (!r1 || r1 == (uint32_t)0xFFFFFFFFU); r2 = 1.0 - ((double)r1 * (1.0 / 4294967295.0)); return (s * (MYFLT)pow(-(log(r2)), (1.0 / (double)t))); } /* Poisson distribution routine */ static MYFLT poissrand(CSOUND *csound, MYFLT lambda) { MYFLT r1, r2, r3; if (UNLIKELY(lambda < FL(0.0))) return FL(0.0); r1 = unirand(csound); r2 = EXP(-lambda); r3 = FL(0.0); while (r1 >= r2) { r3++; r1 *= unirand(csound); } return (r3); } /* ------------------------------------------------------------------------ */ int auniform(CSOUND *csound, PRAND *p) /* Uniform distribution */ { MYFLT *out = p->out; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; double scale = (double)*p->arg1 * (1.0 / 4294967295.03125); if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nrandState_)) * scale); } return OK; } int ikuniform(CSOUND *csound, PRAND *p) { *p->out = unifrand(csound, *p->arg1); return OK; } int alinear(CSOUND *csound, PRAND *p) /* Linear random functions */ { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *out = p->out; MYFLT arg1 = *p->arg1; memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) out[n] = linrand(csound, arg1); return OK; } int iklinear(CSOUND *csound, PRAND *p) { *p->out = linrand(csound, *p->arg1); return OK; } int atrian(CSOUND *csound, PRAND *p) /* Triangle random functions */ { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *out = p->out; MYFLT arg1 = *p->arg1; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) out[n] = trirand(csound, arg1); return OK; } int iktrian(CSOUND *csound, PRAND *p) { *p->out = trirand(csound, *p->arg1); return OK; } int exprndiset(CSOUND *csound, PRANDI *p) { p->num1 = exprand(csound, *p->arg1); p->num2 = exprand(csound, *p->arg1); p->dfdmax = (p->num2 - p->num1) / FMAXLEN; p->phs = 0; p->ampcod = IS_ASIG_ARG(p->xamp) ? 1 : 0; /* (not used by krandi) */ p->cpscod = IS_ASIG_ARG(p->xcps) ? 1 : 0; return OK; } int kexprndi(CSOUND *csound, PRANDI *p) { /* rslt = (num1 + diff*phs) * amp */ /* IV - Jul 11 2002 */ *p->ar = (p->num1 + (MYFLT)p->phs * p->dfdmax) * *p->xamp; p->phs += (int32)(*p->xcps * CS_KICVT); /* phs += inc */ if (UNLIKELY(p->phs >= MAXLEN)) { /* when phs overflows, */ p->phs &= PHMASK; /* mod the phs */ p->num1 = p->num2; /* & new num vals */ p->num2 = exprand(csound, *p->arg1); p->dfdmax = (p->num2 - p->num1) / FMAXLEN; } return OK; } int iexprndi(CSOUND *csound, PRANDI *p) { exprndiset(csound, p); return kexprndi(csound, p); } int aexprndi(CSOUND *csound, PRANDI *p) { int32 phs = p->phs, inc; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *ar, *ampp, *cpsp; cpsp = p->xcps; ampp = p->xamp; ar = p->ar; inc = (int32)(cpsp[0] * csound->sicvt); if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;nampcod) ar[n] = (p->num1 + (MYFLT)phs * p->dfdmax) * ampp[n]; else ar[n] = (p->num1 + (MYFLT)phs * p->dfdmax) * ampp[0]; phs += inc; /* phs += inc */ if (p->cpscod) inc = (int32)(cpsp[n] * csound->sicvt); /* (nxt inc) */ if (UNLIKELY(phs >= MAXLEN)) { /* when phs o'flows */ phs &= PHMASK; p->num1 = p->num2; p->num2 = exprand(csound, *p->arg1); p->dfdmax = (p->num2 - p->num1) / FMAXLEN; } } p->phs = phs; return OK; } int aexp(CSOUND *csound, PRAND *p) /* Exponential random functions */ { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *out = p->out; MYFLT arg1 = *p->arg1; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) out[n] = exprand(csound, arg1); return OK; } int ikexp(CSOUND *csound, PRAND *p) { *p->out = exprand(csound, *p->arg1); return OK; } int abiexp(CSOUND *csound, PRAND *p) /* Bilateral exponential rand */ { /* functions */ uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *out = p->out; MYFLT arg1 = *p->arg1; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) out[n] = biexprand(csound, arg1); return OK; } int ikbiexp(CSOUND *csound, PRAND *p) { *p->out = biexprand(csound, *p->arg1); return OK; } int agaus(CSOUND *csound, PRAND *p) /* Gaussian random functions */ { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *out = p->out; MYFLT arg1 = *p->arg1; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) out[n] = gaussrand(csound, arg1); return OK; } int ikgaus(CSOUND *csound, PRAND *p) { *p->out = gaussrand(csound, *p->arg1); return OK; } int acauchy(CSOUND *csound, PRAND *p) /* Cauchy random functions */ { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *out = p->out; MYFLT arg1 = *p->arg1; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) out[n] = cauchrand(csound, arg1); return OK; } int gaussiset(CSOUND *csound, PRANDI *p) { p->num1 = gaussrand(csound, *p->arg1); p->num2 = gaussrand(csound, *p->arg1); p->dfdmax = (p->num2 - p->num1) / FMAXLEN; p->phs = 0; p->ampcod = IS_ASIG_ARG(p->xamp) ? 1 : 0; /* (not used by krandi) */ p->cpscod = IS_ASIG_ARG(p->xcps) ? 1 : 0; return OK; } int kgaussi(CSOUND *csound, PRANDI *p) { /* rslt = (num1 + diff*phs) * amp */ /* IV - Jul 11 2002 */ *p->ar = (p->num1 + (MYFLT)p->phs * p->dfdmax) * *p->xamp; p->phs += (int32)(*p->xcps * CS_KICVT); /* phs += inc */ if (UNLIKELY(p->phs >= MAXLEN)) { /* when phs overflows, */ p->phs &= PHMASK; /* mod the phs */ p->num1 = p->num2; /* & new num vals */ p->num2 = gaussrand(csound, *p->arg1); p->dfdmax = (p->num2 - p->num1) / FMAXLEN; } return OK; } int igaussi(CSOUND *csound, PRANDI *p) { gaussiset(csound, p); return kgaussi(csound, p); } int agaussi(CSOUND *csound, PRANDI *p) { int32 phs = p->phs, inc; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *ar, *ampp, *cpsp; cpsp = p->xcps; ampp = p->xamp; ar = p->ar; inc = (int32)(*cpsp * csound->sicvt); if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;nampcod) ar[n] = (p->num1 + (MYFLT)phs * p->dfdmax) * ampp[n]; else ar[n] = (p->num1 + (MYFLT)phs * p->dfdmax) * ampp[0]; phs += inc; /* phs += inc */ if (p->cpscod) inc = (int32)(cpsp[n] * csound->sicvt); /* (nxt inc) */ if (UNLIKELY(phs >= MAXLEN)) { /* when phs o'flows */ phs &= PHMASK; p->num1 = p->num2; p->num2 = gaussrand(csound, *p->arg1); p->dfdmax = (p->num2 - p->num1) / FMAXLEN; } } p->phs = phs; return OK; } int ikcauchy(CSOUND *csound, PRAND *p) { *p->out = cauchrand(csound, *p->arg1); return OK; } int apcauchy(CSOUND *csound, PRAND *p) /* +ve Cauchy random functions */ { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *out = p->out; MYFLT arg1 = *p->arg1; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) out[n] = pcauchrand(csound, arg1); return OK; } int ikpcauchy(CSOUND *csound, PRAND *p) { *p->out = pcauchrand(csound, *p->arg1); return OK; } int cauchyiset(CSOUND *csound, PRANDI *p) { p->num1 = cauchrand(csound, *p->arg1); p->num2 = cauchrand(csound, *p->arg1); p->dfdmax = (p->num2 - p->num1) / FMAXLEN; p->phs = 0; p->ampcod = IS_ASIG_ARG(p->xamp) ? 1 : 0; /* (not used by krandi) */ p->cpscod = IS_ASIG_ARG(p->xcps) ? 1 : 0; return OK; } int kcauchyi(CSOUND *csound, PRANDI *p) { /* rslt = (num1 + diff*phs) * amp */ /* IV - Jul 11 2002 */ *p->ar = (p->num1 + (MYFLT)p->phs * p->dfdmax) * *p->xamp; p->phs += (int32)(*p->xcps * CS_KICVT); /* phs += inc */ if (UNLIKELY(p->phs >= MAXLEN)) { /* when phs overflows, */ p->phs &= PHMASK; /* mod the phs */ p->num1 = p->num2; /* & new num vals */ p->num2 = cauchrand(csound, *p->arg1); p->dfdmax = (p->num2 - p->num1) / FMAXLEN; } return OK; } int icauchyi(CSOUND *csound, PRANDI *p) { cauchyiset(csound, p); return kcauchyi(csound, p); } int acauchyi(CSOUND *csound, PRANDI *p) { int32 phs = p->phs, inc; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *ar, *ampp, *cpsp; cpsp = p->xcps; ampp = p->xamp; ar = p->ar; inc = (int32)(*cpsp * csound->sicvt); if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;nampcod) ar[n] = (p->num1 + (MYFLT)phs * p->dfdmax) * ampp[n]; else ar[n] = (p->num1 + (MYFLT)phs * p->dfdmax) * ampp[0]; phs += inc; /* phs += inc */ if (p->cpscod) inc = (int32)(cpsp[n] * csound->sicvt); /* (nxt inc) */ if (UNLIKELY(phs >= MAXLEN)) { /* when phs o'flows */ phs &= PHMASK; p->num1 = p->num2; p->num2 = cauchrand(csound, *p->arg1); p->dfdmax = (p->num2 - p->num1) / FMAXLEN; } } p->phs = phs; return OK; } int abeta(CSOUND *csound, PRAND *p) /* Beta random functions */ { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *out = p->out; MYFLT arg1 = *p->arg1; MYFLT arg2 = *p->arg2; MYFLT arg3 = *p->arg3; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n = 0; n < nsmps; n++) out[n] = betarand(csound, arg1, arg2, arg3); return OK; } int ikbeta(CSOUND *csound, PRAND *p) { *p->out = betarand(csound, *p->arg1, *p->arg2, *p->arg3); return OK; } int aweib(CSOUND *csound, PRAND *p) /* Weibull randon functions */ { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *out = p->out; MYFLT arg1 = *p->arg1; MYFLT arg2 = *p->arg2; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) out[n] = weibrand(csound, arg1, arg2); return OK; } int ikweib(CSOUND *csound, PRAND *p) { *p->out = weibrand(csound, *p->arg1, *p->arg2); return OK; } int apoiss(CSOUND *csound, PRAND *p) /* Poisson random funcions */ { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *out = p->out; MYFLT arg1 = *p->arg1; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) out[n] = poissrand(csound, arg1); return OK; } int ikpoiss(CSOUND *csound, PRAND *p) { *p->out = poissrand(csound, *p->arg1); return OK; } /* ------------------------------------------------------------------------ */ int gen21_rand(FGDATA *ff, FUNC *ftp) { CSOUND *csound = ff->csound; int32 i, n; MYFLT *ft; MYFLT scale; int nargs = ff->e.pcnt - 4; ft = ftp->ftable; scale = (nargs > 1 ? ff->e.p[6] : FL(1.0)); n = ff->flen; if (ff->guardreq) n++; switch ((int) ff->e.p[5]) { case 1: /* Uniform distribution */ for (i = 0 ; i < n ; i++) ft[i] = unifrand(csound, scale); break; case 2: /* Linear distribution */ for (i = 0 ; i < n ; i++) ft[i] = linrand(csound, scale); break; case 3: /* Triangular about 0.5 */ for (i = 0 ; i < n ; i++) ft[i] = trirand(csound, scale); break; case 4: /* Exponential */ for (i = 0 ; i < n ; i++) ft[i] = exprand(csound, scale); break; case 5: /* Bilateral exponential */ for (i = 0 ; i < n ; i++) ft[i] = biexprand(csound, scale); break; case 6: /* Gaussian distribution */ for (i = 0 ; i < n ; i++) ft[i] = gaussrand(csound, scale); break; case 7: /* Cauchy distribution */ for (i = 0 ; i < n ; i++) ft[i] = cauchrand(csound, scale); break; case 8: /* Positive Cauchy */ for (i = 0 ; i < n ; i++) ft[i] = pcauchrand(csound, scale); break; case 9: /* Beta distribution */ if (UNLIKELY(nargs < 3)) { return -1; } for (i = 0 ; i < n ; i++) ft[i] = betarand(csound, scale, (MYFLT) ff->e.p[7], (MYFLT) ff->e.p[8]); break; case 10: /* Weibull Distribution */ if (UNLIKELY(nargs < 2)) { return -1; } for (i = 0 ; i < n ; i++) ft[i] = weibrand(csound, scale, (MYFLT) ff->e.p[7]); break; case 11: /* Poisson Distribution */ for (i = 0 ; i < n ; i++) ft[i] = poissrand(csound, scale); break; default: return -2; } return OK; } csound-6.10.0/OOps/compile_ops.c000066400000000000000000000056611321653344700164460ustar00rootroot00000000000000/* compile_ops.c: Copyright (c) 2013 Victor Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "compile_ops.h" #include int csoundCompileOrcInternal(CSOUND *csound, const char *str, int async); int csoundReadScoreInternal(CSOUND *csound, const char *str); int compile_orc_i(CSOUND *csound, COMPILE *p){ FILE *fp; size_t size=0; char *orc, c, *name; name = ((STRINGDAT *)p->str)->data; fp = fopen(name, "rb"); if (fp == NULL) { csound->Warning(csound, Str("compileorc: could not open %s\n"), name); *p->res = (MYFLT)(CSOUND_ERROR); return NOTOK; } while(!feof(fp)) size += fread(&c,1,1,fp); if(size==0) { fclose(fp); *p->res = (MYFLT)(CSOUND_ERROR); return csound->InitError(csound, Str("compileorc: could not read %s\n"), name); } orc = (char *) csound->Calloc(csound, size+1); fseek(fp, 0, SEEK_SET); if (UNLIKELY(fread(orc,1,size,fp)!=size)) { fclose(fp); csound->Free(csound,orc); return NOTOK; } *p->res = (MYFLT)(csoundCompileOrcInternal(csound, orc, 0)); fclose(fp); csound->Free(csound,orc); return OK; } int compile_csd_i(CSOUND *csound, COMPILE *p){ *p->res = (MYFLT) csoundCompileCsd(csound, ((STRINGDAT *)p->str)->data); return OK; } int compile_str_i(CSOUND *csound, COMPILE *p){ //void csp_orc_sa_print_list(CSOUND*); //printf("START\n"); *p->res = (MYFLT)(csoundCompileOrcInternal(csound, ((STRINGDAT *)p->str)->data, 0)); //printf("END\n"); //csp_orc_sa_print_list(csound); return OK; } int read_score_i(CSOUND *csound, COMPILE *p){ *p->res = (MYFLT)(csoundReadScoreInternal(csound, ((STRINGDAT *)p->str)->data)); return OK; } int eval_str_i(CSOUND *csound, COMPILE *p){ *p->res = csoundEvalCode(csound, ((STRINGDAT *)p->str)->data); return OK; } int eval_str_k(CSOUND *csound, COMPILE *p){ if (*p->ktrig) *p->res = csoundEvalCode(csound, ((STRINGDAT *)p->str)->data); return OK; } int retval_i(CSOUND *csound, RETVAL *p){ INSDS *ip = p->h.insdshead; ip->retval = *p->ret; return OK; } csound-6.10.0/OOps/diskin2.c000066400000000000000000002360121321653344700154740ustar00rootroot00000000000000/* diskin2.c: Copyright (C) 2005 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "soundio.h" #include "diskin2.h" #include typedef struct DISKIN_INST_ { CSOUND *csound; DISKIN2 *diskin; struct DISKIN_INST_ *nxt; } DISKIN_INST; static CS_NOINLINE void diskin2_read_buffer(CSOUND *csound, DISKIN2 *p, int bufReadPos) { MYFLT *tmp; int32 nsmps; int i; IGN(csound); /* swap buffer pointers */ tmp = p->buf; p->buf = p->prvBuf; p->prvBuf = tmp; /* check if requested data can be found in previously used buffer */ i = (int)((int32) bufReadPos + (p->bufStartPos - p->prvBufStartPos)); if ((unsigned int) i < (unsigned int) p->bufSize) { int32 tmp2; /* yes, only need to swap buffers and return */ tmp2 = p->bufStartPos; p->bufStartPos = p->prvBufStartPos; p->prvBufStartPos = tmp2; return; } /* save buffer position */ p->prvBufStartPos = p->bufStartPos; /* calculate new buffer frame start position */ p->bufStartPos = p->bufStartPos + (int32) bufReadPos; p->bufStartPos &= (~((int32) (p->bufSize - 1))); i = 0; if (p->bufStartPos >= 0L) { /* number of sample frames to read */ nsmps = p->fileLength - p->bufStartPos; if (nsmps > 0L) { /* if there is anything to read: */ if (nsmps > (int32) p->bufSize) nsmps = (int32) p->bufSize; nsmps *= (int32) p->nChannels; sf_seek(p->sf, (sf_count_t) p->bufStartPos, SEEK_SET); /* convert sample count to mono samples and read file */ i = (int)sf_read_MYFLT(p->sf, p->buf, (sf_count_t) nsmps); if (UNLIKELY(i < 0)) /* error ? */ i = 0; /* clear entire buffer to zero */ } } /* fill rest of buffer with zero samples */ memset(&p->buf[i], 0, sizeof(MYFLT)*(p->bufSize * p->nChannels-i)); /* while (i < (p->bufSize * p->nChannels)) */ /* p->buf[i++] = FL(0.0); */ } /* Mix one sample frame from input file at location 'pos' to outputs */ /* of opcode 'p', at sample index 'n' (0 <= n < ksmps), with amplitude */ /* scale 'scl'. */ static inline void diskin2_get_sample(CSOUND *csound, DISKIN2 *p, int32 fPos, int n, MYFLT scl) { int bufPos, i; if (p->wrapMode) { if (UNLIKELY(fPos >= p->fileLength)){ fPos -= p->fileLength; } else if (UNLIKELY(fPos < 0L)){ fPos += p->fileLength; } } bufPos = (int)(fPos - p->bufStartPos); if (UNLIKELY((unsigned int) bufPos >= (unsigned int) p->bufSize)) { /* not in current buffer frame, need to read file */ diskin2_read_buffer(csound, p, bufPos); /* recalculate buffer position */ bufPos = (int)(fPos - p->bufStartPos); } if (p->aOut_buf == NULL){ MYFLT **aOut = p->aOut; /* copy all channels from buffer */ if (p->nChannels == 1) { aOut[0][n] += scl * p->buf[bufPos]; } else if (p->nChannels == 2) { bufPos += bufPos; aOut[0][n] += scl * p->buf[bufPos]; aOut[1][n] += scl * p->buf[bufPos + 1]; } else { bufPos *= p->nChannels; i = 0; /* p->aOut[i++][n] += scl * p->buf[bufPos++]; */ /* p->aOut[i++][n] += scl * p->buf[bufPos++]; */ do { aOut[i++][n] += scl * p->buf[bufPos++]; } while (i < p->nChannels); } } else{ MYFLT *aOut = p->aOut_buf; int chans = p->nChannels; /* copy all channels from buffer */ if (chans == 1) { aOut[n] += scl * p->buf[bufPos]; } else if (chans == 2) { bufPos += bufPos; aOut[n*2] += scl * p->buf[bufPos]; aOut[n*2+1] += scl * p->buf[bufPos+1]; } else { bufPos *= chans;//p->nChannels; i = 0; do { aOut[n*chans+i] += scl * p->buf[bufPos++]; } while (++i < chans); } } } /* ------------- set up fast sine generator ------------- */ /* Input args: */ /* a: amplitude */ /* f: frequency (-PI - PI) */ /* p: initial phase (0 - PI/2) */ /* c: 2.0 * cos(f) - 2.0 */ /* Output args: */ /* *x: first output sample */ /* *v: coefficients for calculating next sample as */ /* shown below: */ /* v = v + c * x */ /* x = x + v */ /* These values are calculated as follows: */ /* x = y[0] */ /* v = y[1] - (c + 1.0) * y[0] */ /* where y[0], and y[1] are the first, and */ /* second sample of the sine wave to be */ /* generated, respectively. */ /* -------- written by Istvan Varga, Jan 28 2002 -------- */ static inline void init_sine_gen(double a, double f, double p, double c, double *x, double *v) { double y0, y1; /* these should be doubles */ y0 = sin(p); y1 = sin(p + f); *x = y0; *v = y1 - (c * y0) - y0; /* amp. scale */ *x *= a; *v *= a; } /* calculate buffer size in sample frames */ static int diskin2_calc_buffer_size(DISKIN2 *p, int n_monoSamps) { int i, nFrames; /* default to 4096 mono samples if zero or negative */ if (n_monoSamps <= 0) n_monoSamps = 4096; /* convert mono samples -> sample frames */ i = n_monoSamps / p->nChannels; /* limit to sane range */ if (i < p->winSize) i = p->winSize; else if (i > 1048576) i = 1048576; /* buffer size must be an integer power of two, so round up */ nFrames = 64; /* will be at least 128 sample frames */ do { nFrames <<= 1; } while (nFrames < i); return nFrames; } static const int diskin2_format_table[11] = { 0, SF_FORMAT_RAW | SF_FORMAT_PCM_16, SF_FORMAT_RAW | SF_FORMAT_PCM_S8, SF_FORMAT_RAW | SF_FORMAT_ALAW, SF_FORMAT_RAW | SF_FORMAT_ULAW, SF_FORMAT_RAW | SF_FORMAT_PCM_16, SF_FORMAT_RAW | SF_FORMAT_PCM_32, SF_FORMAT_RAW | SF_FORMAT_FLOAT, SF_FORMAT_RAW | SF_FORMAT_PCM_U8, SF_FORMAT_RAW | SF_FORMAT_PCM_24, SF_FORMAT_RAW | SF_FORMAT_DOUBLE }; static int diskin2_init_(CSOUND *csound, DISKIN2 *p, int stringname); int diskin2_init(CSOUND *csound, DISKIN2 *p) { p->SkipInit = *p->iSkipInit; p->WinSize = *p->iWinSize; p->BufSize = *p->iBufSize; p->fforceSync = *p->forceSync; return diskin2_init_(csound,p,0); } int diskin2_init_S(CSOUND *csound, DISKIN2 *p) { p->SkipInit = *p->iSkipInit; p->WinSize = *p->iWinSize; p->BufSize = *p->iBufSize; p->fforceSync = *p->forceSync; return diskin2_init_(csound,p,1); } /* VL 11-01-13 diskin_init - calls diskin2_init */ int diskin_init(CSOUND *csound, DISKIN2 *p){ p->SkipInit = *p->iWinSize; p->WinSize = 2; p->BufSize = 0; p->fforceSync = 0; return diskin2_init_(csound,p,0); } int diskin_init_S(CSOUND *csound, DISKIN2 *p){ p->SkipInit = *p->iWinSize; p->WinSize = 2; p->BufSize = 0; p->fforceSync = 0; return diskin2_init_(csound,p,1); } /* * soundin now uses diskin2 VL 24-12-16 */ int sndinset(CSOUND *csound, DISKIN2 *p) { int ret; p->SkipInit = *p->iWrapMode; p->iSampleFormat = p->iSkipTime; p->iSkipTime = p->kTranspose; p->WinSize = 2; p->BufSize = 0; p->fforceSync = 0; ret = diskin2_init_(csound,p,0); return ret; } int sndinset_S(CSOUND *csound, DISKIN2 *p){ int ret; p->SkipInit = *p->iWrapMode; p->iSampleFormat = p->iSkipTime; p->iSkipTime = p->kTranspose; p->WinSize = 2; p->BufSize = 0; p->fforceSync = 0; ret = diskin2_init_(csound,p,1); return ret; } int soundin(CSOUND *csound, DISKIN2 *p){ MYFLT tmp = *p->kTranspose; int ret; *p->kTranspose = 1.; ret = diskin2_perf(csound, p); *p->kTranspose = tmp; return ret; } int diskin2_async_deinit(CSOUND *csound, void *p); static int diskin2_init_(CSOUND *csound, DISKIN2 *p, int stringname) { double pos; char name[1024]; void *fd; SF_INFO sfinfo; int n; /* check number of channels */ p->nChannels = (int)(p->OUTOCOUNT); if (UNLIKELY(p->nChannels < 1 || p->nChannels > DISKIN2_MAXCHN)) { return csound->InitError(csound, Str("diskin2: invalid number of channels")); } /* if already open, close old file first */ if (p->fdch.fd != NULL) { /* skip initialisation if requested */ if (p->SkipInit != FL(0.0)) return OK; fdclose(csound, &(p->fdch)); } /* set default format parameters */ memset(&sfinfo, 0, sizeof(SF_INFO)); sfinfo.samplerate = (int)(csound->esr + FL(0.5)); sfinfo.channels = p->nChannels; /* check for user specified sample format */ n = (int)(*(p->iSampleFormat) + FL(2.5)) - 1; if (UNLIKELY(n < 0 || n > 10)) return csound->InitError(csound, Str("diskin2: unknown sample format")); sfinfo.format = diskin2_format_table[n]; /* open file */ /* FIXME: name can overflow with very long string */ if (stringname==0){ if (csound->ISSTRCOD(*p->iFileCode)) strncpy(name,get_arg_string(csound, *p->iFileCode), 1023); else csound->strarg2name(csound, name, p->iFileCode, "soundin.",0); } else strncpy(name, ((STRINGDAT *)p->iFileCode)->data, 1023); fd = csound->FileOpen2(csound, &(p->sf), CSFILE_SND_R, name, &sfinfo, "SFDIR;SSDIR", CSFTYPE_UNKNOWN_AUDIO, 0); if (UNLIKELY(fd == NULL)) { return csound->InitError(csound, Str("diskin2: %s: failed to open file (%s)"), name, strerror(errno)); } /* record file handle so that it will be closed at note-off */ memset(&(p->fdch), 0, sizeof(FDCH)); p->fdch.fd = fd; fdrecord(csound, &(p->fdch)); /* check number of channels in file (must equal the number of outargs) */ if (UNLIKELY(sfinfo.channels != p->nChannels)) { return csound->InitError(csound, Str("diskin2: number of output args " "inconsistent with number of file channels")); } /* skip initialisation if requested */ if (p->initDone && p->SkipInit != FL(0.0)) return OK; /* interpolation window size: valid settings are 1 (no interpolation), */ /* 2 (linear interpolation), 4 (cubic interpolation), and integer */ /* multiples of 4 in the range 8 to 1024 (sinc interpolation) */ p->winSize = (int)((p->WinSize) + FL(0.5)); if (p->winSize < 1) p->winSize = 4; /* use cubic interpolation by default */ else if (p->winSize > 2) { /* cubic/sinc: round to nearest integer multiple of 4 */ p->winSize = (p->winSize + 2) & (~3L); if ((uint32) p->winSize > 1024UL) p->winSize = 1024; /* constant for window calculation */ p->winFact = (FL(1.0) - POWER(p->winSize * FL(0.85172), -FL(0.89624))) / ((MYFLT)((p->winSize * p->winSize) >> 2)); } /* set file parameters from header info */ p->fileLength = (int32) sfinfo.frames; p->warpScale = 1.0; if ((int)(csound->esr + FL(0.5)) != sfinfo.samplerate) { if (LIKELY(p->winSize != 1)) { /* will automatically convert sample rate if interpolation is enabled */ p->warpScale = (double)sfinfo.samplerate / (double)csound->esr; } else { csound->Warning(csound, Str("diskin2: warning: file sample rate (%d) " "!= orchestra sr (%d)\n"), sfinfo.samplerate, (int)(csound->esr + FL(0.5))); } } /* wrap mode */ p->wrapMode = (*(p->iWrapMode) == FL(0.0) ? 0 : 1); if (UNLIKELY(p->fileLength < 1L)) p->wrapMode = 0; /* initialise read position */ pos = (double)*(p->iSkipTime) * (double)csound->esr * p->warpScale; pos *= (double)POS_FRAC_SCALE; p->pos_frac = (int64_t)(pos >= 0.0 ? (pos + 0.5) : (pos - 0.5)); if (p->wrapMode) { p->pos_frac %= ((int64_t)p->fileLength << POS_FRAC_SHIFT); if (UNLIKELY(p->pos_frac < (int64_t)0)) p->pos_frac += ((int64_t)p->fileLength << POS_FRAC_SHIFT); } p->pos_frac_inc = (int64_t)0; p->prv_kTranspose = FL(0.0); /* allocate and initialise buffers */ p->bufSize = diskin2_calc_buffer_size(p, (int)((p->BufSize) + FL(0.5))); n = 2 * p->bufSize * p->nChannels * (int)sizeof(MYFLT); if (n != (int)p->auxData.size) csound->AuxAlloc(csound, (int32) n, &(p->auxData)); p->bufStartPos = p->prvBufStartPos = -((int32)p->bufSize); n = p->bufSize * p->nChannels; p->buf = (MYFLT*) (p->auxData.auxp); p->prvBuf = (MYFLT*) p->buf + (int)n; memset(p->buf, 0, n*sizeof(MYFLT)); // create circular buffer, on fail set mode to synchronous if (csound->realtime_audio_flag==1 && p->fforceSync==0 && (p->cb = csound->CreateCircularBuffer(csound, p->bufSize*p->nChannels*2, sizeof(MYFLT))) != NULL){ DISKIN_INST **top, *current; int *start; // allocate buffer n = CS_KSMPS*sizeof(MYFLT)*p->nChannels; if (n != (int)p->auxData2.size) csound->AuxAlloc(csound, (int32) n, &(p->auxData2)); p->aOut_buf = (MYFLT *) (p->auxData2.auxp); memset(p->aOut_buf, 0, n); p->aOut_bufsize = CS_KSMPS; #ifndef __EMSCRIPTEN__ if ((top=(DISKIN_INST **)csound->QueryGlobalVariable(csound, "DISKIN_INST")) == NULL){ csound->CreateGlobalVariable(csound, "DISKIN_INST", sizeof(DISKIN_INST *)); top = (DISKIN_INST **) csound->QueryGlobalVariable(csound, "DISKIN_INST"); *top = (DISKIN_INST *) csound->Calloc(csound, sizeof(DISKIN_INST)); csound->CreateGlobalVariable(csound, "DISKIN_PTHREAD", sizeof(void**)); csound->CreateGlobalVariable(csound, "DISKIN_THREAD_START", sizeof(int)); current = *top; } else #endif { current = *top; while(current->nxt != NULL) { /* find next empty slot in chain */ current = current->nxt; } current->nxt = (DISKIN_INST *) csound->Calloc(csound, sizeof(DISKIN_INST)); current = current->nxt; } current->csound = csound; current->diskin = p; current->nxt = NULL; #ifndef __EMSCRIPTEN__ if ( *(start = csound->QueryGlobalVariable(csound, "DISKIN_THREAD_START")) == 0) { uintptr_t diskin_io_thread(void *p); void **thread = csound->QueryGlobalVariable(csound, "DISKIN_PTHREAD"); *thread = csound->CreateThread(diskin_io_thread, *top); *start = 1; } #endif csound->RegisterDeinitCallback(csound, p, diskin2_async_deinit); p->async = 1; /* print file information */ if (UNLIKELY((csound->oparms_.msglevel & 7) == 7)) { csound->Message(csound, Str("diskin2: opened (asynchronously) '%s':\n" " %d Hz, %d channel(s), " "%lld sample frames\n"), csound->GetFileName(fd), sfinfo.samplerate, sfinfo.channels, sfinfo.frames); } } else { p->aOut_buf = NULL; p->aOut_bufsize = 0; p->async = 0; /* print file information */ if (UNLIKELY((csound->oparms_.msglevel & 7) == 7)) { csound->Message(csound, Str("diskin2: opened '%s':\n" " %d Hz, %d channel(s), " "%lld sample frames\n"), csound->GetFileName(fd), sfinfo.samplerate, sfinfo.channels, sfinfo.frames); } } /* done initialisation */ p->initDone = 1; return OK; } int diskin2_async_deinit(CSOUND *csound, void *p){ DISKIN_INST **top, *current, *prv; if ((top = (DISKIN_INST **) csound->QueryGlobalVariable(csound, "DISKIN_INST")) == NULL) return NOTOK; current = *top; prv = NULL; while(current->diskin != (DISKIN2 *)p) { prv = current; current = current->nxt; } if (prv == NULL) *top = current->nxt; else prv->nxt = current->nxt; #ifndef __EMSCRIPTEN__ if (*top == NULL) { int *start; void **pt; start = (int *) csound->QueryGlobalVariable(csound,"DISKIN_THREAD_START"); *start = 0; pt = csound->QueryGlobalVariable(csound,"DISKIN_PTHREAD"); //csound->Message(csound, "dealloc %p %d\n", start, *start); csound->JoinThread(*pt); csound->DestroyGlobalVariable(csound, "DISKIN_PTHREAD"); csound->DestroyGlobalVariable(csound, "DISKIN_THREAD_START"); csound->DestroyGlobalVariable(csound, "DISKIN_INST"); } #endif csound->Free(csound, current); csound->DestroyCircularBuffer(csound, ((DISKIN2 *)p)->cb); return OK; } static inline void diskin2_file_pos_inc(DISKIN2 *p, int32 *ndx) { p->pos_frac += p->pos_frac_inc; *ndx = (int32) (p->pos_frac >> POS_FRAC_SHIFT); if (p->wrapMode) { if (*ndx >= p->fileLength) { *ndx -= p->fileLength; p->pos_frac -= ((int64_t)p->fileLength << POS_FRAC_SHIFT); } else if (*ndx < 0L) { *ndx += p->fileLength; p->pos_frac += ((int64_t)p->fileLength << POS_FRAC_SHIFT); } } } int diskin2_perf_synchronous(CSOUND *csound, DISKIN2 *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; int nsmps = CS_KSMPS; int chn, i, nn; double d, frac_d, x, c, v, pidwarp_d; MYFLT frac, a0, a1, a2, a3, onedwarp, winFact; int32 ndx; int wsized2, warp; if (UNLIKELY(p->fdch.fd == NULL) ) goto file_error; if (!p->initDone && !p->SkipInit){ return csound->PerfError(csound, p->h.insdshead, Str("diskin2: not initialised")); } if (*(p->kTranspose) != p->prv_kTranspose) { double f; p->prv_kTranspose = *(p->kTranspose); f = (double)p->prv_kTranspose * p->warpScale * (double)POS_FRAC_SCALE; #ifdef HAVE_C99 p->pos_frac_inc = (int64_t)llrint(f); #else p->pos_frac_inc = (int64_t)(f + (f < 0.0 ? -0.5 : 0.5)); #endif } /* clear outputs to zero first */ for (chn = 0; chn < p->nChannels; chn++) for (nn = 0; nn < nsmps; nn++) p->aOut[chn][nn] = FL(0.0); /* file read position */ if (UNLIKELY(early)) nsmps -= early; ndx = (int32) (p->pos_frac >> POS_FRAC_SHIFT); switch (p->winSize) { case 1: /* ---- no interpolation ---- */ for (nn = offset; nn < nsmps; nn++) { if (p->pos_frac & ((int64_t)POS_FRAC_SCALE >> 1)) ndx++; /* round to nearest sample */ diskin2_get_sample(csound, p, ndx, nn, FL(1.0)); /* update file position */ diskin2_file_pos_inc(p, &ndx); } break; case 2: /* ---- linear interpolation ---- */ for (nn = offset; nn < nsmps; nn++) { a1 = (MYFLT)((int)(p->pos_frac & (int64_t)POS_FRAC_MASK)) * (FL(1.0) / (MYFLT)POS_FRAC_SCALE); a0 = FL(1.0) - a1; diskin2_get_sample(csound, p, ndx, nn, a0); ndx++; diskin2_get_sample(csound, p, ndx, nn, a1); /* update file position */ diskin2_file_pos_inc(p, &ndx); } break; case 4: /* ---- cubic interpolation ---- */ for (nn = offset; nn < nsmps; nn++) { frac = (MYFLT)((int)(p->pos_frac & (int64_t)POS_FRAC_MASK)) * (FL(1.0) / (MYFLT)POS_FRAC_SCALE); a3 = frac * frac; a3 -= FL(1.0); a3 *= (FL(1.0) / FL(6.0)); a2 = frac; a2 += FL(1.0); a0 = (a2 *= FL(0.5)); a0 -= FL(1.0); a1 = FL(3.0) * a3; a2 -= a1; a0 -= a3; a1 -= frac; a0 *= frac; a1 *= frac; a2 *= frac; a3 *= frac; a1 += FL(1.0); ndx--; /* sample -1 */ diskin2_get_sample(csound, p, ndx, nn, a0); ndx++; /* sample 0 */ diskin2_get_sample(csound, p, ndx, nn, a1); ndx++; /* sample +1 */ diskin2_get_sample(csound, p, ndx, nn, a2); ndx++; /* sample +2 */ diskin2_get_sample(csound, p, ndx, nn, a3); /* update file position */ diskin2_file_pos_inc(p, &ndx); } break; default: /* ---- sinc interpolation ---- */ wsized2 = p->winSize >> 1; nn = POS_FRAC_SCALE + (POS_FRAC_SCALE >> 12); if (p->pos_frac_inc > (int64_t) nn || p->pos_frac_inc < (int64_t) (-nn)) { warp = 1; /* enable warp */ onedwarp = (p->pos_frac_inc >= (int64_t) 0 ? ((MYFLT)nn / (MYFLT)p->pos_frac_inc) : ((MYFLT)(-nn) / (MYFLT)p->pos_frac_inc)); pidwarp_d = PI * (double)onedwarp; c = 2.0 * cos(pidwarp_d) - 2.0; /* correct window for kwarp */ x = v = (double)wsized2; x *= x; x = 1.0 / x; v *= (double)onedwarp; v -= (double)((int)v) + 0.5; v *= 4.0 * v; winFact = (MYFLT)(((double)p->winFact - x) * v + x); } else { warp = 0; onedwarp = FL(0.0); pidwarp_d = c = 0.0; winFact = p->winFact; } for (nn = offset; nn < nsmps; nn++) { frac_d = (double)((int)(p->pos_frac & (int64_t)POS_FRAC_MASK)) * (1.0 / (double)POS_FRAC_SCALE); ndx += (int32)(1 - wsized2); d = (double)(1 - wsized2) - frac_d; if (warp) { /* ---- warp enabled ---- */ init_sine_gen((1.0 / PI), pidwarp_d, (pidwarp_d * d), c, &x, &v); /* samples -(window size / 2 - 1) to -1 */ i = wsized2 - 1; do { a1 = (MYFLT)d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = (MYFLT)x * a1 * a1 / (MYFLT)d; diskin2_get_sample(csound, p, ndx, nn, a1); ndx++; d += 1.0; v += c * x; x += v; } while (--i); /* sample 0 */ /* avoid division by zero */ if (UNLIKELY(frac_d < 0.00003)) { a1 = onedwarp; } else { a1 = (MYFLT)d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = (MYFLT)x * a1 * a1 / (MYFLT)d; } diskin2_get_sample(csound, p, ndx, nn, a1); ndx++; d += 1.0; v += c * x; x += v; /* sample 1 */ /* avoid division by zero */ if (UNLIKELY(frac_d > 0.99997)) { a1 = onedwarp; } else { a1 = (MYFLT)d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = (MYFLT)x * a1 * a1 / (MYFLT)d; } diskin2_get_sample(csound, p, ndx, nn, a1); ndx++; d += 1.0; v += c * x; x += v; /* samples 2 to (window size / 2) */ i = wsized2 - 1; do { a1 = (MYFLT)d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = (MYFLT)x * a1 * a1 / (MYFLT)d; diskin2_get_sample(csound, p, ndx, nn, a1); ndx++; d += 1.0; v += c * x; x += v; } while (--i); } else { /* ---- warp disabled ---- */ /* avoid division by zero */ if (frac_d < 0.00001 || frac_d > 0.99999) { ndx += (int32) (wsized2 - (frac_d < 0.5 ? 1 : 0)); diskin2_get_sample(csound, p, ndx, nn, FL(1.0)); } else { a0 = (MYFLT)(sin(PI * frac_d) / PI); i = wsized2; do { a1 = (MYFLT)d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = a1 * a1 / (MYFLT)d; diskin2_get_sample(csound, p, ndx, nn, a1*a0); d += 1.0; ndx++; a1 = (MYFLT)d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = -(a1 * a1 / (MYFLT)d); diskin2_get_sample(csound, p, ndx, nn, a1*a0); d += 1.0; ndx++; } while (--i); } } /* update file position */ diskin2_file_pos_inc(p, &ndx); } } /* apply 0dBFS scale */ for (chn = 0; chn < p->nChannels; chn++) for (nn = offset; nn < nsmps; nn++) p->aOut[chn][nn] *= csound->e0dbfs; return OK; file_error: csound->ErrorMsg(csound, Str("diskin2: file descriptor closed or invalid\n")); return NOTOK; } int diskin_file_read(CSOUND *csound, DISKIN2 *p) { /* nsmps is bufsize in frames */ int nsmps = p->aOut_bufsize - p->h.insdshead->ksmps_offset; int i, nn; int chn, chans = p->nChannels; double d, frac_d, x, c, v, pidwarp_d; MYFLT frac, a0, a1, a2, a3, onedwarp, winFact; int32 ndx; int wsized2, warp; MYFLT *aOut = (MYFLT *)p->aOut_buf; /* needs to be allocated */ if (UNLIKELY(p->fdch.fd == NULL) ) goto file_error; if (!p->initDone && !p->SkipInit) { return csound->PerfError(csound, p->h.insdshead, Str("diskin2: not initialised")); } if (*(p->kTranspose) != p->prv_kTranspose) { double f; p->prv_kTranspose = *(p->kTranspose); f = (double)p->prv_kTranspose * p->warpScale * (double)POS_FRAC_SCALE; #ifdef HAVE_C99 p->pos_frac_inc = (int64_t)llrint(f); #else p->pos_frac_inc = (int64_t)(f + (f < 0.0 ? -0.5 : 0.5)); #endif } /* clear outputs to zero first */ for (chn = 0; chn < chans; chn++) for (nn = 0; nn < nsmps; nn++) aOut[chn + nn*chans] = FL(0.0); /* file read position */ ndx = (int32) (p->pos_frac >> POS_FRAC_SHIFT); switch (p->winSize) { case 1: /* ---- no interpolation ---- */ for (nn = 0; nn < nsmps; nn++) { if (p->pos_frac & ((int64_t)POS_FRAC_SCALE >> 1)) ndx++; /* round to nearest sample */ diskin2_get_sample(csound, p, ndx, nn, FL(1.0)); /* update file position */ diskin2_file_pos_inc(p, &ndx); } break; case 2: /* ---- linear interpolation ---- */ for (nn = 0; nn < nsmps; nn++) { a1 = (MYFLT)((int)(p->pos_frac & (int64_t)POS_FRAC_MASK)) * (FL(1.0) / (MYFLT)POS_FRAC_SCALE); a0 = FL(1.0) - a1; diskin2_get_sample(csound, p, ndx, nn, a0); ndx++; diskin2_get_sample(csound, p, ndx, nn, a1); /* update file position */ diskin2_file_pos_inc(p, &ndx); } break; case 4: /* ---- cubic interpolation ---- */ for (nn = 0; nn < nsmps; nn++) { frac = (MYFLT)((int)(p->pos_frac & (int64_t)POS_FRAC_MASK)) * (FL(1.0) / (MYFLT)POS_FRAC_SCALE); a3 = frac * frac; a3 -= FL(1.0); a3 *= (FL(1.0) / FL(6.0)); a2 = frac; a2 += FL(1.0); a0 = (a2 *= FL(0.5)); a0 -= FL(1.0); a1 = FL(3.0) * a3; a2 -= a1; a0 -= a3; a1 -= frac; a0 *= frac; a1 *= frac; a2 *= frac; a3 *= frac; a1 += FL(1.0); ndx--; /* sample -1 */ diskin2_get_sample(csound, p, ndx, nn, a0); ndx++; /* sample 0 */ diskin2_get_sample(csound, p, ndx, nn, a1); ndx++; /* sample +1 */ diskin2_get_sample(csound, p, ndx, nn, a2); ndx++; /* sample +2 */ diskin2_get_sample(csound, p, ndx, nn, a3); /* update file position */ diskin2_file_pos_inc(p, &ndx); } break; default: /* ---- sinc interpolation ---- */ wsized2 = p->winSize >> 1; nn = POS_FRAC_SCALE + (POS_FRAC_SCALE >> 12); if (p->pos_frac_inc > (int64_t) nn || p->pos_frac_inc < (int64_t) (-nn)) { warp = 1; /* enable warp */ onedwarp = (p->pos_frac_inc >= (int64_t) 0 ? ((MYFLT)nn / (MYFLT)p->pos_frac_inc) : ((MYFLT)(-nn) / (MYFLT)p->pos_frac_inc)); pidwarp_d = PI * (double)onedwarp; c = 2.0 * cos(pidwarp_d) - 2.0; /* correct window for kwarp */ x = v = (double)wsized2; x *= x; x = 1.0 / x; v *= (double)onedwarp; v -= (double)((int)v) + 0.5; v *= 4.0 * v; winFact = (MYFLT)(((double)p->winFact - x) * v + x); } else { warp = 0; onedwarp = FL(0.0); pidwarp_d = c = 0.0; winFact = p->winFact; } for (nn = 0; nn < nsmps; nn++) { frac_d = (double)((int)(p->pos_frac & (int64_t)POS_FRAC_MASK)) * (1.0 / (double)POS_FRAC_SCALE); ndx += (int32)(1 - wsized2); d = (double)(1 - wsized2) - frac_d; if (warp) { /* ---- warp enabled ---- */ init_sine_gen((1.0 / PI), pidwarp_d, (pidwarp_d * d), c, &x, &v); /* samples -(window size / 2 - 1) to -1 */ i = wsized2 - 1; do { a1 = (MYFLT)d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = (MYFLT)x * a1 * a1 / (MYFLT)d; diskin2_get_sample(csound, p, ndx, nn, a1); ndx++; d += 1.0; v += c * x; x += v; } while (--i); /* sample 0 */ /* avoid division by zero */ if (UNLIKELY(frac_d < 0.00003)) { a1 = onedwarp; } else { a1 = (MYFLT)d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = (MYFLT)x * a1 * a1 / (MYFLT)d; } diskin2_get_sample(csound, p, ndx, nn, a1); ndx++; d += 1.0; v += c * x; x += v; /* sample 1 */ /* avoid division by zero */ if (UNLIKELY(frac_d > 0.99997)) { a1 = onedwarp; } else { a1 = (MYFLT)d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = (MYFLT)x * a1 * a1 / (MYFLT)d; } diskin2_get_sample(csound, p, ndx, nn, a1); ndx++; d += 1.0; v += c * x; x += v; /* samples 2 to (window size / 2) */ i = wsized2 - 1; do { a1 = (MYFLT)d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = (MYFLT)x * a1 * a1 / (MYFLT)d; diskin2_get_sample(csound, p, ndx, nn, a1); ndx++; d += 1.0; v += c * x; x += v; } while (--i); } else { /* ---- warp disabled ---- */ /* avoid division by zero */ if (frac_d < 0.00001 || frac_d > 0.99999) { ndx += (int32) (wsized2 - (frac_d < 0.5 ? 1 : 0)); diskin2_get_sample(csound, p, ndx, nn, FL(1.0)); } else { a0 = (MYFLT)(sin(PI * frac_d) / PI); i = wsized2; do { a1 = (MYFLT)d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = a0 * a1 * a1 / (MYFLT)d; diskin2_get_sample(csound, p, ndx, nn, a1); d += 1.0; ndx++; a1 = (MYFLT)d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = -(a0 * a1 * a1 / (MYFLT)d); diskin2_get_sample(csound, p, ndx, nn, a1); d += 1.0; ndx++; } while (--i); } } /* update file position */ diskin2_file_pos_inc(p, &ndx); } } { /* write to circular buffer */ int lc, mc=0, nc=nsmps*p->nChannels; int *start = csound->QueryGlobalVariable(csound,"DISKIN_THREAD_START"); do{ lc = csound->WriteCircularBuffer(csound, p->cb, &aOut[mc], nc); nc -= lc; mc += lc; } while(nc && *start); } return OK; file_error: csound->ErrorMsg(csound, Str("diskin2: file descriptor closed or invalid\n")); return NOTOK; } int diskin2_perf_asynchronous(CSOUND *csound, DISKIN2 *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, nsmps = CS_KSMPS; MYFLT samp; int chn; void *cb = p->cb; int chans = p->nChannels; if (offset || early) { for (chn = 0; chn < chans; chn++) for (nn = 0; nn < nsmps; nn++) p->aOut[chn][nn] = FL(0.0); if (UNLIKELY(early)) nsmps -= early; } if (UNLIKELY(p->fdch.fd == NULL)) return NOTOK; if (!p->initDone && !p->SkipInit){ return csound->PerfError(csound, p->h.insdshead, Str("diskin2: not initialised")); } for (nn = offset; nn < nsmps; nn++){ for (chn = 0; chn < chans; chn++) { //int i =0; //do { // i = csound->ReadCircularBuffer(csound, cb, &samp, 1); //} while(i==0); p->aOut[chn][nn] = csound->e0dbfs*samp; } } return OK; } uintptr_t diskin_io_thread(void *p){ DISKIN_INST *current = (DISKIN_INST *) p; int wakeup = 1000*current->csound->ksmps/current->csound->esr; int *start = current->csound->QueryGlobalVariable(current->csound,"DISKIN_THREAD_START"); _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); while(*start){ current = (DISKIN_INST *) p; csoundSleep(wakeup > 0 ? wakeup : 1); while(current != NULL){ diskin_file_read(current->csound, current->diskin); current = current->nxt; } } return 0; } int diskin2_perf(CSOUND *csound, DISKIN2 *p) { if (!p->async) return diskin2_perf_synchronous(csound, p); else return diskin2_perf_asynchronous(csound, p); } static int soundout_deinit(CSOUND *csound, void *pp) { char *opname = csound->GetOpcodeName(pp); SNDCOM *q; if (strcmp(opname, "soundouts") == 0) q = &(((SNDOUTS*) pp)->c); else q = &(((SNDOUT*) pp)->c); if (q->fd != NULL) { /* flush buffer */ MYFLT *p0 = (MYFLT*) &(q->outbuf[0]); MYFLT *p1 = (MYFLT*) q->outbufp; if (p1 > p0) { sf_write_MYFLT(q->sf, p0, (sf_count_t) ((MYFLT*) p1 - (MYFLT*) p0)); q->outbufp = (MYFLT*) &(q->outbuf[0]); } /* close file */ csound->FileClose(csound, q->fd); q->sf = (SNDFILE*) NULL; q->fd = NULL; } return OK; } /* RWD:DBFS: NB: thse funcs all supposed to write to a 'raw' file, so what will people want for 0dbfs handling? really need to update opcode with more options. */ /* init routine for instr soundout */ static int sndo1set_(CSOUND *csound, void *pp, int stringname) { char *sfname, *opname, name[1024]; SNDCOM *q; MYFLT *ifilcod, *iformat; int filetyp = TYP_RAW, format = csound->oparms_.outformat, nchns = 1; SF_INFO sfinfo; //SNDOUTS *p = (SNDOUTS*) pp; opname = csound->GetOpcodeName(pp); csound->Warning(csound, Str("%s is deprecated; use fout instead\n"), opname); if (strcmp(opname, "soundouts") == 0 || strcmp(opname, "soundouts.i") == 0) { q = &(((SNDOUTS*) pp)->c); ifilcod = ((SNDOUTS*) pp)->ifilcod; iformat = ((SNDOUTS*) pp)->iformat; nchns++; } else { q = &(((SNDOUT*) pp)->c); ifilcod = ((SNDOUT*) pp)->ifilcod; iformat = ((SNDOUT*) pp)->iformat; } if (q->fd != NULL) /* if file already open, */ return OK; /* return now */ csound->RegisterDeinitCallback(csound, pp, soundout_deinit); if (stringname==0){ if (csound->ISSTRCOD(*ifilcod)) strncpy(name,get_arg_string(csound, *ifilcod), 1023); else csound->strarg2name(csound, name, ifilcod, "soundout.",0); } else strncpy(name, ((STRINGDAT *)ifilcod)->data, 1023); sfname = name; memset(&sfinfo, 0, sizeof(SF_INFO)); //sfinfo.frames = 0; sfinfo.samplerate = (int) (csound->esr + FL(0.5)); sfinfo.channels = nchns; switch ((int) (*iformat + FL(0.5))) { case 1: format = AE_CHAR; break; case 4: format = AE_SHORT; break; case 5: format = AE_LONG; break; case 6: format = AE_FLOAT; case 0: break; default: return csound->InitError(csound, Str("%s: invalid sample format: %d"), opname, (int) (*iformat + FL(0.5))); } sfinfo.format = TYPE2SF(filetyp) | FORMAT2SF(format); if (q->fd == NULL) { return csound->InitError(csound, Str("%s cannot open %s"), opname, sfname); } sfname = csound->GetFileName(q->fd); if (format != AE_FLOAT) sf_command(q->sf, SFC_SET_CLIPPING, NULL, SF_TRUE); else sf_command(q->sf, SFC_SET_CLIPPING, NULL, SF_FALSE); #ifdef USE_DOUBLE sf_command(q->sf, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE); #else sf_command(q->sf, SFC_SET_NORM_FLOAT, NULL, SF_FALSE); #endif csound->Warning(csound, Str("%s: opening RAW outfile %s\n"), opname, sfname); q->outbufp = q->outbuf; /* fix - isro 20-11-96 */ q->bufend = q->outbuf + SNDOUTSMPS; /* fix - isro 20-11-96 */ return OK; } int sndoutset(CSOUND *csound, SNDOUT *p){ return sndo1set_(csound,p,0); } int sndoutset_S(CSOUND *csound, SNDOUT *p){ return sndo1set_(csound,p,1); } int soundout(CSOUND *csound, SNDOUT *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, nsmps = CS_KSMPS; if (UNLIKELY(p->c.sf == NULL)) return csound->PerfError(csound, p->h.insdshead, Str("soundout: not initialised")); if (UNLIKELY(early)) nsmps -= early; for (nn = offset; nn < nsmps; nn++) { if (UNLIKELY(p->c.outbufp >= p->c.bufend)) { sf_write_MYFLT(p->c.sf, p->c.outbuf, p->c.bufend - p->c.outbuf); p->c.outbufp = p->c.outbuf; } *(p->c.outbufp++) = p->asig[nn]; } return OK; } int soundouts(CSOUND *csound, SNDOUTS *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, nsmps = CS_KSMPS; if (UNLIKELY(p->c.sf == NULL)) return csound->PerfError(csound, p->h.insdshead, Str("soundouts: not initialised")); if (UNLIKELY(early)) nsmps -= early; for (nn = offset; nn < nsmps; nn++) { if (UNLIKELY(p->c.outbufp >= p->c.bufend)) { sf_write_MYFLT(p->c.sf, p->c.outbuf, p->c.bufend - p->c.outbuf); p->c.outbufp = p->c.outbuf; } *(p->c.outbufp++) = p->asig1[nn]; *(p->c.outbufp++) = p->asig2[nn]; } return OK; } static CS_NOINLINE void diskin2_read_buffer_array(CSOUND *csound, DISKIN2_ARRAY *p, int bufReadPos) { MYFLT *tmp; int32 nsmps; int i; IGN(csound); /* swap buffer pointers */ tmp = p->buf; p->buf = p->prvBuf; p->prvBuf = tmp; /* check if requested data can be found in previously used buffer */ i = (int)((int32) bufReadPos + (p->bufStartPos - p->prvBufStartPos)); if ((unsigned int) i < (unsigned int) p->bufSize) { int32 tmp2; /* yes, only need to swap buffers and return */ tmp2 = p->bufStartPos; p->bufStartPos = p->prvBufStartPos; p->prvBufStartPos = tmp2; return; } /* save buffer position */ p->prvBufStartPos = p->bufStartPos; /* calculate new buffer frame start position */ p->bufStartPos = p->bufStartPos + (int32) bufReadPos; p->bufStartPos &= (~((int32) (p->bufSize - 1))); i = 0; if (p->bufStartPos >= 0L) { /* number of sample frames to read */ nsmps = p->fileLength - p->bufStartPos; if (nsmps > 0L) { /* if there is anything to read: */ if (nsmps > (int32) p->bufSize) nsmps = (int32) p->bufSize; nsmps *= (int32) p->nChannels; sf_seek(p->sf, (sf_count_t) p->bufStartPos, SEEK_SET); /* convert sample count to mono samples and read file */ i = (int)sf_read_MYFLT(p->sf, p->buf, (sf_count_t) nsmps); if (UNLIKELY(i < 0)) /* error ? */ i = 0; /* clear entire buffer to zero */ } } /* fill rest of buffer with zero samples */ memset(&p->buf[i], 0, sizeof(MYFLT)*(p->bufSize * p->nChannels-i)); /* while (i < (p->bufSize * p->nChannels)) */ /* p->buf[i++] = FL(0.0); */ } static int diskin2_calc_buffer_size_array(DISKIN2_ARRAY *p, int n_monoSamps) { int i, nFrames; /* default to 4096 mono samples if zero or negative */ if (n_monoSamps <= 0) n_monoSamps = 4096; /* convert mono samples -> sample frames */ i = n_monoSamps / p->nChannels; /* limit to sane range */ if (i < p->winSize) i = p->winSize; else if (i > 1048576) i = 1048576; /* buffer size must be an integer power of two, so round up */ nFrames = 64; /* will be at least 128 sample frames */ do { nFrames <<= 1; } while (nFrames < i); return nFrames; } static inline void diskin2_file_pos_inc_array(DISKIN2_ARRAY *p, int32 *ndx) { p->pos_frac += p->pos_frac_inc; *ndx = (int32) (p->pos_frac >> POS_FRAC_SHIFT); if (p->wrapMode) { if (*ndx >= p->fileLength) { *ndx -= p->fileLength; p->pos_frac -= ((int64_t)p->fileLength << POS_FRAC_SHIFT); } else if (*ndx < 0L) { *ndx += p->fileLength; p->pos_frac += ((int64_t)p->fileLength << POS_FRAC_SHIFT); } } } static inline void diskin2_get_sample_array(CSOUND *csound, DISKIN2_ARRAY *p, int32 fPos, int n, MYFLT scl) { int bufPos, i; int ksmps = CS_KSMPS; MYFLT *aOut = (MYFLT *) p->aOut->data; if (p->wrapMode) { if (UNLIKELY(fPos >= p->fileLength)){ fPos -= p->fileLength; } else if (UNLIKELY(fPos < 0L)){ fPos += p->fileLength; } } bufPos = (int)(fPos - p->bufStartPos); if (UNLIKELY((unsigned int) bufPos >= (unsigned int) p->bufSize)) { /* not in current buffer frame, need to read file */ diskin2_read_buffer_array(csound, p, bufPos); /* recalculate buffer position */ bufPos = (int)(fPos - p->bufStartPos); } /* copy all channels from buffer */ if (p->aOut_buf == NULL){ if (p->nChannels == 1) { aOut[n] += scl * p->buf[bufPos]; } else if (p->nChannels == 2) { bufPos += bufPos; aOut[n] += scl * p->buf[bufPos]; aOut[n+ksmps] += scl * p->buf[bufPos + 1]; } else { bufPos *= p->nChannels; i = 0; do { aOut[i*ksmps+n] += scl * p->buf[bufPos++]; } while (++i < p->nChannels); } } else{ MYFLT *aOut = p->aOut_buf; int chans = p->nChannels; /* copy all channels from buffer */ if (chans == 1) { aOut[n] += scl * p->buf[bufPos]; } else if (chans == 2) { bufPos += bufPos; aOut[n*2] += scl * p->buf[bufPos]; aOut[n*2+1] += scl * p->buf[bufPos+1]; } else { bufPos *= chans;//p->nChannels; i = 0; do { aOut[n*chans+i] += scl * p->buf[bufPos++]; } while (++i < chans); } } } int diskin2_async_deinit_array(CSOUND *csound, void *p){ DISKIN_INST **top, *current, *prv; if ((top = (DISKIN_INST **) csound->QueryGlobalVariable(csound, "DISKIN_INST_ARRAY")) == NULL) return NOTOK; current = *top; prv = NULL; while(current->diskin != (DISKIN2 *)p) { prv = current; current = current->nxt; } if (prv == NULL) *top = current->nxt; else prv->nxt = current->nxt; #ifndef __EMSCRIPTEN__ if (*top == NULL) { int *start; void **pt; start = (int *) csound->QueryGlobalVariable(csound, "DISKIN_THREAD_START_ARRAY"); *start = 0; pt = csound->QueryGlobalVariable(csound,"DISKIN_PTHREAD_ARRAY"); //csound->Message(csound, "dealloc %p %d\n", start, *start); csound->JoinThread(*pt); csound->DestroyGlobalVariable(csound, "DISKIN_PTHREAD_ARRAY"); csound->DestroyGlobalVariable(csound, "DISKIN_THREAD_START_ARRAY"); csound->DestroyGlobalVariable(csound, "DISKIN_INST_ARRAY"); } #endif csound->Free(csound, current); csound->DestroyCircularBuffer(csound, ((DISKIN2_ARRAY *)p)->cb); return OK; } int diskin_file_read_array(CSOUND *csound, DISKIN2_ARRAY *p) { /* nsmps is bufsize in frames */ int nsmps = p->aOut_bufsize - p->h.insdshead->ksmps_offset; int i, nn; int chn, chans = p->nChannels; double d, frac_d, x, c, v, pidwarp_d; MYFLT frac, a0, a1, a2, a3, onedwarp, winFact; int32 ndx; int wsized2, warp; MYFLT *aOut = (MYFLT *)p->aOut_buf; /* needs to be allocated */ if (UNLIKELY(p->fdch.fd == NULL) ) goto file_error; if (!p->initDone && !p->SkipInit) { return csound->PerfError(csound, p->h.insdshead, Str("diskin2: not initialised")); } if (*(p->kTranspose) != p->prv_kTranspose) { double f; p->prv_kTranspose = *(p->kTranspose); f = (double)p->prv_kTranspose * p->warpScale * (double)POS_FRAC_SCALE; #ifdef HAVE_C99 p->pos_frac_inc = (int64_t)llrint(f); #else p->pos_frac_inc = (int64_t)(f + (f < 0.0 ? -0.5 : 0.5)); #endif } /* clear outputs to zero first */ for (chn = 0; chn < chans; chn++) for (nn = 0; nn < nsmps; nn++) aOut[chn + nn*chans] = FL(0.0); /* file read position */ ndx = (int32) (p->pos_frac >> POS_FRAC_SHIFT); switch (p->winSize) { case 1: /* ---- no interpolation ---- */ for (nn = 0; nn < nsmps; nn++) { if (p->pos_frac & ((int64_t)POS_FRAC_SCALE >> 1)) ndx++; /* round to nearest sample */ diskin2_get_sample_array(csound, p, ndx, nn, FL(1.0)); /* update file position */ diskin2_file_pos_inc_array(p, &ndx); } break; case 2: /* ---- linear interpolation ---- */ for (nn = 0; nn < nsmps; nn++) { a1 = (MYFLT)((int)(p->pos_frac & (int64_t)POS_FRAC_MASK)) * (FL(1.0) / (MYFLT)POS_FRAC_SCALE); a0 = FL(1.0) - a1; diskin2_get_sample_array(csound, p, ndx, nn, a0); ndx++; diskin2_get_sample_array(csound, p, ndx, nn, a1); /* update file position */ diskin2_file_pos_inc_array(p, &ndx); } break; case 4: /* ---- cubic interpolation ---- */ for (nn = 0; nn < nsmps; nn++) { frac = (MYFLT)((int)(p->pos_frac & (int64_t)POS_FRAC_MASK)) * (FL(1.0) / (MYFLT)POS_FRAC_SCALE); a3 = frac * frac; a3 -= FL(1.0); a3 *= (FL(1.0) / FL(6.0)); a2 = frac; a2 += FL(1.0); a0 = (a2 *= FL(0.5)); a0 -= FL(1.0); a1 = FL(3.0) * a3; a2 -= a1; a0 -= a3; a1 -= frac; a0 *= frac; a1 *= frac; a2 *= frac; a3 *= frac; a1 += FL(1.0); ndx--; /* sample -1 */ diskin2_get_sample_array(csound, p, ndx, nn, a0); ndx++; /* sample 0 */ diskin2_get_sample_array(csound, p, ndx, nn, a1); ndx++; /* sample +1 */ diskin2_get_sample_array(csound, p, ndx, nn, a2); ndx++; /* sample +2 */ diskin2_get_sample_array(csound, p, ndx, nn, a3); /* update file position */ diskin2_file_pos_inc_array(p, &ndx); } break; default: /* ---- sinc interpolation ---- */ wsized2 = p->winSize >> 1; nn = POS_FRAC_SCALE + (POS_FRAC_SCALE >> 12); if (p->pos_frac_inc > (int64_t) nn || p->pos_frac_inc < (int64_t) (-nn)) { warp = 1; /* enable warp */ onedwarp = (p->pos_frac_inc >= (int64_t) 0 ? ((MYFLT)nn / (MYFLT)p->pos_frac_inc) : ((MYFLT)(-nn) / (MYFLT)p->pos_frac_inc)); pidwarp_d = PI * (double)onedwarp; c = 2.0 * cos(pidwarp_d) - 2.0; /* correct window for kwarp */ x = v = (double)wsized2; x *= x; x = 1.0 / x; v *= (double)onedwarp; v -= (double)((int)v) + 0.5; v *= 4.0 * v; winFact = (MYFLT)(((double)p->winFact - x) * v + x); } else { warp = 0; onedwarp = FL(0.0); pidwarp_d = c = 0.0; winFact = p->winFact; } for (nn = 0; nn < nsmps; nn++) { frac_d = (double)((int)(p->pos_frac & (int64_t)POS_FRAC_MASK)) * (1.0 / (double)POS_FRAC_SCALE); ndx += (int32)(1 - wsized2); d = (double)(1 - wsized2) - frac_d; if (warp) { /* ---- warp enabled ---- */ init_sine_gen((1.0 / PI), pidwarp_d, (pidwarp_d * d), c, &x, &v); /* samples -(window size / 2 - 1) to -1 */ i = wsized2 - 1; do { a1 = (MYFLT)d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = (MYFLT)x * a1 * a1 / (MYFLT)d; diskin2_get_sample_array(csound, p, ndx, nn, a1); ndx++; d += 1.0; v += c * x; x += v; } while (--i); /* sample 0 */ /* avoid division by zero */ if (UNLIKELY(frac_d < 0.00003)) { a1 = onedwarp; } else { a1 = (MYFLT)d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = (MYFLT)x * a1 * a1 / (MYFLT)d; } diskin2_get_sample_array(csound, p, ndx, nn, a1); ndx++; d += 1.0; v += c * x; x += v; /* sample 1 */ /* avoid division by zero */ if (UNLIKELY(frac_d > 0.99997)) { a1 = onedwarp; } else { a1 = (MYFLT)d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = (MYFLT)x * a1 * a1 / (MYFLT)d; } diskin2_get_sample_array(csound, p, ndx, nn, a1); ndx++; d += 1.0; v += c * x; x += v; /* samples 2 to (window size / 2) */ i = wsized2 - 1; do { a1 = (MYFLT)d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = (MYFLT)x * a1 * a1 / (MYFLT)d; diskin2_get_sample_array(csound, p, ndx, nn, a1); ndx++; d += 1.0; v += c * x; x += v; } while (--i); } else { /* ---- warp disabled ---- */ /* avoid division by zero */ if (frac_d < 0.00001 || frac_d > 0.99999) { ndx += (int32) (wsized2 - (frac_d < 0.5 ? 1 : 0)); diskin2_get_sample_array(csound, p, ndx, nn, FL(1.0)); } else { a0 = (MYFLT)(sin(PI * frac_d) / PI); i = wsized2; do { a1 = (MYFLT)d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = a0 * a1 * a1 / (MYFLT)d; diskin2_get_sample_array(csound, p, ndx, nn, a1); d += 1.0; ndx++; a1 = (MYFLT)d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = -(a0 * a1 * a1 / (MYFLT)d); diskin2_get_sample_array(csound, p, ndx, nn, a1); d += 1.0; ndx++; } while (--i); } } /* update file position */ diskin2_file_pos_inc_array(p, &ndx); } } { /* write to circular buffer */ int lc, mc=0, nc=nsmps*p->nChannels; int *start = csound->QueryGlobalVariable(csound,"DISKIN_THREAD_START"); do{ lc = csound->WriteCircularBuffer(csound, p->cb, &aOut[mc], nc); nc -= lc; mc += lc; } while(nc && *start); } return OK; file_error: csound->ErrorMsg(csound, Str("diskin2: file descriptor closed or invalid\n")); return NOTOK; } uintptr_t diskin_io_thread_array(void *p){ DISKIN_INST *current = (DISKIN_INST *) p; int wakeup = 1000*current->csound->ksmps/current->csound->esr; int *start = current->csound->QueryGlobalVariable(current->csound, "DISKIN_THREAD_START_ARRAY"); _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); while(*start){ current = (DISKIN_INST *) p; csoundSleep(wakeup > 0 ? wakeup : 1); while(current != NULL){ diskin_file_read_array(current->csound, (DISKIN2_ARRAY *)current->diskin); current = current->nxt; } } return 0; } static int diskin2_init_array(CSOUND *csound, DISKIN2_ARRAY *p, int stringname) { double pos; char name[1024]; void *fd; SF_INFO sfinfo; int n; ARRAYDAT *t = p->aOut; /* if already open, close old file first */ if (p->fdch.fd != NULL) { /* skip initialisation if requested */ if (p->SkipInit != FL(0.0)) return OK; fdclose(csound, &(p->fdch)); } // to handle raw files number of channels if (t->data) p->nChannels = t->sizes[0]; /* set default format parameters */ memset(&sfinfo, 0, sizeof(SF_INFO)); sfinfo.samplerate = (int)(csound->esr + FL(0.5)); sfinfo.channels = p->nChannels; /* check for user specified sample format */ n = (int)(*(p->iSampleFormat) + FL(2.5)) - 1; if (UNLIKELY(n < 0 || n > 10)) return csound->InitError(csound, Str("diskin2: unknown sample format")); sfinfo.format = diskin2_format_table[n]; /* open file */ /* FIXME: name can overflow with very long string */ if (stringname==0){ if (csound->ISSTRCOD(*p->iFileCode)) strncpy(name,get_arg_string(csound, *p->iFileCode), 1023); else csound->strarg2name(csound, name, p->iFileCode, "soundin.",0); } else strncpy(name, ((STRINGDAT *)p->iFileCode)->data, 1023); fd = csound->FileOpen2(csound, &(p->sf), CSFILE_SND_R, name, &sfinfo, "SFDIR;SSDIR", CSFTYPE_UNKNOWN_AUDIO, 0); if (UNLIKELY(fd == NULL)) { return csound->InitError(csound, Str("diskin2: %s: failed to open file"), name); } /* record file handle so that it will be closed at note-off */ memset(&(p->fdch), 0, sizeof(FDCH)); p->fdch.fd = fd; fdrecord(csound, &(p->fdch)); /* get number of channels in file */ p->nChannels = sfinfo.channels; if (UNLIKELY(t->data == NULL) || t->sizes[0] < p->nChannels ) { /* create array */ CS_VARIABLE* var; int memSize; if (t->data) { csound->Free(csound, t->data); csound->Free(csound, t->sizes); } t->dimensions = 1; t->sizes = csound->Calloc(csound, sizeof(int)); t->sizes[0] = p->nChannels; var = t->arrayType->createVariable(csound, NULL); t->arrayMemberSize = var->memBlockSize; memSize = var->memBlockSize*(t->sizes[0]); t->data = csound->Calloc(csound, memSize); } /* else { */ /* /\* check dim 1 to see if it matches channels*\/ */ /* if (t->sizes[0] < p->nChannels) */ /* return csound->InitError(csound, */ /* Str("diskin2: output array too small")); */ /* } */ /* skip initialisation if requested */ if (p->initDone && (p->SkipInit) != FL(0.0)) return OK; /* interpolation window size: valid settings are 1 (no interpolation), */ /* 2 (linear interpolation), 4 (cubic interpolation), and integer */ /* multiples of 4 in the range 8 to 1024 (sinc interpolation) */ p->winSize = (int)((p->WinSize) + FL(0.5)); if (p->winSize < 1) p->winSize = 4; /* use cubic interpolation by default */ else if (p->winSize > 2) { /* cubic/sinc: round to nearest integer multiple of 4 */ p->winSize = (p->winSize + 2) & (~3L); if ((uint32) p->winSize > 1024UL) p->winSize = 1024; /* constant for window calculation */ p->winFact = (FL(1.0) - POWER(p->winSize * FL(0.85172), -FL(0.89624))) / ((MYFLT)((p->winSize * p->winSize) >> 2)); } /* set file parameters from header info */ p->fileLength = (int32) sfinfo.frames; p->warpScale = 1.0; if ((int)(csound->esr + FL(0.5)) != sfinfo.samplerate) { if (LIKELY(p->winSize != 1)) { /* will automatically convert sample rate if interpolation is enabled */ p->warpScale = (double)sfinfo.samplerate / (double)csound->esr; } else { csound->Warning(csound, Str("diskin2: warning: file sample rate (%d) " "!= orchestra sr (%d)\n"), sfinfo.samplerate, (int)(csound->esr + FL(0.5))); } } /* wrap mode */ p->wrapMode = (*(p->iWrapMode) == FL(0.0) ? 0 : 1); if (UNLIKELY(p->fileLength < 1L)) p->wrapMode = 0; /* initialise read position */ pos = (double)*(p->iSkipTime) * (double)csound->esr * p->warpScale; pos *= (double)POS_FRAC_SCALE; p->pos_frac = (int64_t)(pos >= 0.0 ? (pos + 0.5) : (pos - 0.5)); if (p->wrapMode) { p->pos_frac %= ((int64_t)p->fileLength << POS_FRAC_SHIFT); if (UNLIKELY(p->pos_frac < (int64_t)0)) p->pos_frac += ((int64_t)p->fileLength << POS_FRAC_SHIFT); } p->pos_frac_inc = (int64_t)0; p->prv_kTranspose = FL(0.0); /* allocate and initialise buffers */ p->bufSize = diskin2_calc_buffer_size_array(p, (int)((p->BufSize) + FL(0.5))); n = 2 * p->bufSize * p->nChannels * (int)sizeof(MYFLT); if (n != (int)p->auxData.size) csound->AuxAlloc(csound, (int32) n, &(p->auxData)); p->bufStartPos = p->prvBufStartPos = -((int32)p->bufSize); n = p->bufSize * p->nChannels; p->buf = (MYFLT*) (p->auxData.auxp); p->prvBuf = (MYFLT*) p->buf + (int)n; memset(p->buf, 0, n*sizeof(MYFLT)); // create circular buffer, on fail set mode to synchronous if (csound->realtime_audio_flag==1 && p->fforceSync==0 && (p->cb = csound->CreateCircularBuffer(csound, p->bufSize*p->nChannels*2, sizeof(MYFLT))) != NULL){ DISKIN_INST **top, *current; int *start; // allocate buffer n = CS_KSMPS*sizeof(MYFLT)*p->nChannels; if (n != (int)p->auxData2.size) csound->AuxAlloc(csound, (int32) n, &(p->auxData2)); p->aOut_buf = (MYFLT *) (p->auxData2.auxp); memset(p->aOut_buf, 0, n); p->aOut_bufsize = CS_KSMPS; #ifndef __EMSCRIPTEN__ if ((top=(DISKIN_INST **) csound->QueryGlobalVariable(csound, "DISKIN_INST_ARRAY")) == NULL){ csound->CreateGlobalVariable(csound, "DISKIN_INST_ARRAY", sizeof(DISKIN_INST *)); top = (DISKIN_INST **) csound->QueryGlobalVariable(csound, "DISKIN_INST_ARRAY"); *top = (DISKIN_INST *) csound->Calloc(csound, sizeof(DISKIN_INST)); csound->CreateGlobalVariable(csound, "DISKIN_PTHREAD_ARRAY", sizeof(void**)); csound->CreateGlobalVariable(csound, "DISKIN_THREAD_START_ARRAY", sizeof(int)); current = *top; } else #endif { current = *top; while(current->nxt != NULL) { /* find next empty slot in chain */ current = current->nxt; } current->nxt = (DISKIN_INST *) csound->Calloc(csound, sizeof(DISKIN_INST)); current = current->nxt; } current->csound = csound; current->diskin = (DISKIN2 *) p; current->nxt = NULL; #ifndef __EMSCRIPTEN__ if (*(start = csound->QueryGlobalVariable(csound, "DISKIN_THREAD_START_ARRAY")) == 0) { uintptr_t diskin_io_thread_array(void *p); // TOFIX: this variable (thread) is not referenced #if 0 void **thread = csound->QueryGlobalVariable(csound, "DISKIN_PTHREAD_ARRAY"); #endif *start = 1; csound->CreateThread(diskin_io_thread_array, *top); } #endif csound->RegisterDeinitCallback(csound, (DISKIN2 *) p, diskin2_async_deinit_array); p->async = 1; /* print file information */ if (UNLIKELY((csound->oparms_.msglevel & 7) == 7)) { csound->Message(csound, Str("diskin2: opened (asynchronously) '%s':\n" " %d Hz, %d channel(s), " "%lld sample frames\n"), csound->GetFileName(fd), sfinfo.samplerate, sfinfo.channels, sfinfo.frames); } } else { p->aOut_buf = NULL; p->aOut_bufsize = 0; p->async = 0; /* print file information */ if (UNLIKELY((csound->oparms_.msglevel & 7) == 7)) { csound->Message(csound, Str("diskin2: opened '%s':\n" " %d Hz, %d channel(s), " "%lld sample frames\n"), csound->GetFileName(fd), sfinfo.samplerate, sfinfo.channels, sfinfo.frames); } } /* done initialisation */ p->initDone = 1; return OK; } int diskin2_perf_synchronous_array(CSOUND *csound, DISKIN2_ARRAY *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; int nsmps = CS_KSMPS, ksmps = CS_KSMPS; int chn, i, nn; double d, frac_d, x, c, v, pidwarp_d; MYFLT frac, a0, a1, a2, a3, onedwarp, winFact; int32 ndx; int wsized2, warp; MYFLT *aOut = (MYFLT *) p->aOut->data; if (UNLIKELY(p->fdch.fd == NULL) ) goto file_error; if (!p->initDone && !p->SkipInit){ return csound->PerfError(csound, p->h.insdshead, Str("diskin2: not initialised")); } if (*(p->kTranspose) != p->prv_kTranspose) { double f; p->prv_kTranspose = *(p->kTranspose); f = (double)p->prv_kTranspose * p->warpScale * (double)POS_FRAC_SCALE; #ifdef HAVE_C99 p->pos_frac_inc = (int64_t)llrint(f); #else p->pos_frac_inc = (int64_t)(f + (f < 0.0 ? -0.5 : 0.5)); #endif } /* clear outputs to zero first */ for (chn = 0; chn < p->nChannels; chn++) for (nn = 0; nn < nsmps; nn++) aOut[chn*ksmps+nn] = FL(0.0); /* file read position */ if (UNLIKELY(early)) nsmps -= early; ndx = (int32) (p->pos_frac >> POS_FRAC_SHIFT); switch (p->winSize) { case 1: /* ---- no interpolation ---- */ for (nn = offset; nn < nsmps; nn++) { if (p->pos_frac & ((int64_t)POS_FRAC_SCALE >> 1)) ndx++; /* round to nearest sample */ diskin2_get_sample_array(csound, p, ndx, nn, FL(1.0)); /* update file position */ diskin2_file_pos_inc_array(p, &ndx); } break; case 2: /* ---- linear interpolation ---- */ for (nn = offset; nn < nsmps; nn++) { a1 = (MYFLT)((int)(p->pos_frac & (int64_t)POS_FRAC_MASK)) * (FL(1.0) / (MYFLT)POS_FRAC_SCALE); a0 = FL(1.0) - a1; diskin2_get_sample_array(csound, p, ndx, nn, a0); ndx++; diskin2_get_sample_array(csound, p, ndx, nn, a1); /* update file position */ diskin2_file_pos_inc_array(p, &ndx); } break; case 4: /* ---- cubic interpolation ---- */ for (nn = offset; nn < nsmps; nn++) { frac = (MYFLT)((int)(p->pos_frac & (int64_t)POS_FRAC_MASK)) * (FL(1.0) / (MYFLT)POS_FRAC_SCALE); a3 = frac * frac; a3 -= FL(1.0); a3 *= (FL(1.0) / FL(6.0)); a2 = frac; a2 += FL(1.0); a0 = (a2 *= FL(0.5)); a0 -= FL(1.0); a1 = FL(3.0) * a3; a2 -= a1; a0 -= a3; a1 -= frac; a0 *= frac; a1 *= frac; a2 *= frac; a3 *= frac; a1 += FL(1.0); ndx--; /* sample -1 */ diskin2_get_sample_array(csound, p, ndx, nn, a0); ndx++; /* sample 0 */ diskin2_get_sample_array(csound, p, ndx, nn, a1); ndx++; /* sample +1 */ diskin2_get_sample_array(csound, p, ndx, nn, a2); ndx++; /* sample +2 */ diskin2_get_sample_array(csound, p, ndx, nn, a3); /* update file position */ diskin2_file_pos_inc_array(p, &ndx); } break; default: /* ---- sinc interpolation ---- */ wsized2 = p->winSize >> 1; nn = POS_FRAC_SCALE + (POS_FRAC_SCALE >> 12); if (p->pos_frac_inc > (int64_t) nn || p->pos_frac_inc < (int64_t) (-nn)) { warp = 1; /* enable warp */ onedwarp = (p->pos_frac_inc >= (int64_t) 0 ? ((MYFLT)nn / (MYFLT)p->pos_frac_inc) : ((MYFLT)(-nn) / (MYFLT)p->pos_frac_inc)); pidwarp_d = PI * (double)onedwarp; c = 2.0 * cos(pidwarp_d) - 2.0; /* correct window for kwarp */ x = v = (double)wsized2; x *= x; x = 1.0 / x; v *= (double)onedwarp; v -= (double)((int)v) + 0.5; v *= 4.0 * v; winFact = (MYFLT)(((double)p->winFact - x) * v + x); } else { warp = 0; onedwarp = FL(0.0); pidwarp_d = c = 0.0; winFact = p->winFact; } for (nn = offset; nn < nsmps; nn++) { frac_d = (double)((int)(p->pos_frac & (int64_t)POS_FRAC_MASK)) * (1.0 / (double)POS_FRAC_SCALE); ndx += (int32)(1 - wsized2); d = (double)(1 - wsized2) - frac_d; if (warp) { /* ---- warp enabled ---- */ init_sine_gen((1.0 / PI), pidwarp_d, (pidwarp_d * d), c, &x, &v); /* samples -(window size / 2 - 1) to -1 */ i = wsized2 - 1; do { a1 = (MYFLT)d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = (MYFLT)x * a1 * a1 / (MYFLT)d; diskin2_get_sample_array(csound, p, ndx, nn, a1); ndx++; d += 1.0; v += c * x; x += v; } while (--i); /* sample 0 */ /* avoid division by zero */ if (UNLIKELY(frac_d < 0.00003)) { a1 = onedwarp; } else { a1 = (MYFLT)d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = (MYFLT)x * a1 * a1 / (MYFLT)d; } diskin2_get_sample_array(csound, p, ndx, nn, a1); ndx++; d += 1.0; v += c * x; x += v; /* sample 1 */ /* avoid division by zero */ if (UNLIKELY(frac_d > 0.99997)) { a1 = onedwarp; } else { a1 = (MYFLT)d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = (MYFLT)x * a1 * a1 / (MYFLT)d; } diskin2_get_sample_array(csound, p, ndx, nn, a1); ndx++; d += 1.0; v += c * x; x += v; /* samples 2 to (window size / 2) */ i = wsized2 - 1; do { a1 = (MYFLT)d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = (MYFLT)x * a1 * a1 / (MYFLT)d; diskin2_get_sample_array(csound, p, ndx, nn, a1); ndx++; d += 1.0; v += c * x; x += v; } while (--i); } else { /* ---- warp disabled ---- */ /* avoid division by zero */ if (frac_d < 0.00001 || frac_d > 0.99999) { ndx += (int32) (wsized2 - (frac_d < 0.5 ? 1 : 0)); diskin2_get_sample_array(csound, p, ndx, nn, FL(1.0)); } else { a0 = (MYFLT)(sin(PI * frac_d) / PI); i = wsized2; do { a1 = (MYFLT)d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = a0 * a1 * a1 / (MYFLT)d; diskin2_get_sample_array(csound, p, ndx, nn, a1); d += 1.0; ndx++; a1 = (MYFLT)d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = -(a0 * a1 * a1 / (MYFLT)d); diskin2_get_sample_array(csound, p, ndx, nn, a1); d += 1.0; ndx++; } while (--i); } } /* update file position */ diskin2_file_pos_inc_array(p, &ndx); } } /* apply 0dBFS scale */ for (chn = 0; chn < p->nChannels; chn++) for (nn = offset; nn < nsmps; nn++) aOut[chn*ksmps+nn] *= csound->e0dbfs; return OK; file_error: csound->ErrorMsg(csound, Str("diskin2: file descriptor closed or invalid\n")); return NOTOK; } int diskin2_perf_asynchronous_array(CSOUND *csound, DISKIN2_ARRAY *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, nsmps = CS_KSMPS, ksmps = CS_KSMPS; MYFLT samp; int chn; void *cb = p->cb; int chans = p->nChannels; MYFLT *aOut = (MYFLT *) p->aOut->data; if (offset || early) { for (chn = 0; chn < chans; chn++) for (nn = 0; nn < nsmps; nn++) aOut[chn*ksmps+nn] = FL(0.0); if (UNLIKELY(early)) nsmps -= early; } if (UNLIKELY(p->fdch.fd == NULL)) return NOTOK; if (!p->initDone && !p->SkipInit){ return csound->PerfError(csound, p->h.insdshead, Str("diskin2: not initialised")); } for (nn = offset; nn < nsmps; nn++){ for (chn = 0; chn < chans; chn++) { //int i =0; //do { // i = csound->ReadCircularBuffer(csound, cb, &samp, 1); //} while(i==0); aOut[chn*ksmps+nn] = csound->e0dbfs*samp; } } return OK; } int diskin2_init_array_I(CSOUND *csound, DISKIN2_ARRAY *p) { p->SkipInit = *p->iSkipInit; p->WinSize = *p->iWinSize; p->BufSize = *p->iBufSize; p->fforceSync = *p->forceSync; return diskin2_init_array(csound,p,0); } int diskin2_init_array_S(CSOUND *csound, DISKIN2_ARRAY *p) { p->SkipInit = *p->iSkipInit; p->WinSize = *p->iWinSize; p->BufSize = *p->iBufSize; p->fforceSync = *p->forceSync; return diskin2_init_array(csound,p,1); } /* diskin_init_array - calls diskin2_init_array */ int diskin_init_array_I(CSOUND *csound, DISKIN2_ARRAY *p){ p->SkipInit = *p->iWinSize; p->WinSize = 2; p->BufSize = 0; p->fforceSync = 0; return diskin2_init_array(csound,p,0); } int diskin_init_array_S(CSOUND *csound, DISKIN2_ARRAY *p){ p->SkipInit = *p->iWinSize; p->WinSize = 2; p->BufSize = 0; p->fforceSync = 0; return diskin2_init_array(csound,p,1); } int diskin2_perf_array(CSOUND *csound, DISKIN2_ARRAY *p) { if (!p->async) return diskin2_perf_synchronous_array(csound, p); else return diskin2_perf_asynchronous_array(csound, p); } #if 0 // OLD SOUNDIN code VL 24-12-2016 /* -------- soundin opcode: simplified version of diskin2 -------- */ static void soundin_read_buffer(CSOUND *csound, SOUNDIN_ *p, int bufReadPos) { int i = 0; /* calculate new buffer frame start position */ p->bufStartPos = p->bufStartPos + (int_least64_t) bufReadPos; p->bufStartPos &= (~((int_least64_t) (p->bufSize - 1))); if (p->bufStartPos >= (int_least64_t) 0) { int_least64_t lsmps; int nsmps; /* number of sample frames to read */ lsmps = p->fileLength - p->bufStartPos; if (lsmps > (int_least64_t) 0) { /* if there is anything to read: */ nsmps = (lsmps < (int_least64_t) p->bufSize ? (int) lsmps : p->bufSize); /* convert sample count to mono samples and read file */ nsmps *= (int) p->nChannels; if (csound->realtime_audio_flag==0){ sf_seek(p->sf, (sf_count_t) p->bufStartPos, SEEK_SET); i = (int) sf_read_MYFLT(p->sf, p->buf, (sf_count_t) nsmps); } else i = (int) csound->ReadAsync(csound, p->fdch.fd, p->buf, (sf_count_t) nsmps); if (UNLIKELY(i < 0)) /* error ? */ i = 0; /* clear entire buffer to zero */ } } /* fill rest of buffer with zero samples */ for ( ; i < (p->bufSize * p->nChannels); i++) p->buf[i] = FL(0.0); } /* calculate buffer size in sample frames */ static int soundin_calc_buffer_size(SOUNDIN_ *p, int n_monoSamps) { int i, nFrames; /* default to 2048 mono samples if zero or negative */ if (n_monoSamps <= 0) n_monoSamps = 2048; /* convert mono samples -> sample frames */ i = n_monoSamps / p->nChannels; /* limit to sane range */ if (i > 1048576) i = 1048576; /* buffer size must be an integer power of two, so round up */ nFrames = 32; /* will be at least 64 sample frames */ do { nFrames <<= 1; } while (nFrames < i); return nFrames; } static int sndinset_(CSOUND *csound, SOUNDIN_ *p, int stringname) { double pos; char name[1024]; void *fd; SF_INFO sfinfo; int n, fmt, typ; /* check number of channels */ p->nChannels = (int) (p->OUTOCOUNT); if (UNLIKELY(p->nChannels < 1 || p->nChannels > DISKIN2_MAXCHN)) { return csound->InitError(csound, Str("soundin: invalid number of channels")); } p->bufSize = soundin_calc_buffer_size(p, (int) (*(p->iBufSize) + FL(0.5))); /* if already open, close old file first */ if (p->fdch.fd != NULL) { /* skip initialisation if requested */ if (*(p->iSkipInit) != FL(0.0)) return OK; fdclose(csound, &(p->fdch)); } /* set default format parameters */ memset(&sfinfo, 0, sizeof(SF_INFO)); sfinfo.samplerate = (int) (csound->esr + FL(0.5)); sfinfo.channels = p->nChannels; /* check for user specified sample format */ n = (int) (*(p->iSampleFormat) + FL(2.5)) - 1; if (n == 1) { sfinfo.format = SF_FORMAT_RAW | (int) FORMAT2SF(csound->oparms_.outformat); } else { if (UNLIKELY(n < 0 || n > 10)) return csound->InitError(csound, Str("soundin: unknown sample format")); sfinfo.format = diskin2_format_table[n]; } /* open file */ /* FIXME: name can overflow with very long string */ if (stringname==0){ if (csound->ISSTRCOD(*p->iFileCode)) strncpy(name,get_arg_string(csound, *p->iFileCode), 1023); else csound->strarg2name(csound, name, p->iFileCode, "soundin.",0); } else strncpy(name, ((STRINGDAT *)p->iFileCode)->data, 1023); if (csound->realtime_audio_flag==0) fd = csound->FileOpen2(csound, &(p->sf), CSFILE_SND_R, name, &sfinfo, "SFDIR;SSDIR", CSFTYPE_UNKNOWN_AUDIO, 0); else fd = csound->FileOpenAsync(csound, &(p->sf), CSFILE_SND_R, name, &sfinfo, "SFDIR;SSDIR", CSFTYPE_UNKNOWN_AUDIO, p->bufSize*p->nChannels, 0); if (UNLIKELY(fd == NULL)) { return csound->InitError(csound, Str("soundin: %s: failed to open file"), name); } /* record file handle so that it will be closed at note-off */ memset(&(p->fdch), 0, sizeof(FDCH)); p->fdch.fd = fd; fdrecord(csound, &(p->fdch)); /* print file information */ if (UNLIKELY((csound->oparms_.msglevel & 7) == 7)) { csound->Message(csound, Str("soundin: opened '%s':\n" " %d Hz, %d channel(s), " "%ld sample frames\n"), csound->GetFileName(fd), (int) sfinfo.samplerate, (int) sfinfo.channels, (int32) sfinfo.frames); } /* check number of channels in file (must equal the number of outargs) */ if (UNLIKELY(sfinfo.channels != p->nChannels)) { return csound->InitError(csound, Str("soundin: number of output args " "inconsistent with number of file channels")); } /* skip initialisation if requested */ if (p->auxData.auxp != NULL && *(p->iSkipInit) != FL(0.0)) return OK; /* set file parameters from header info */ p->fileLength = (int_least64_t) sfinfo.frames; if ((int) (csound->esr + FL(0.5)) != sfinfo.samplerate) csound->Warning(csound, Str("soundin: file sample rate (%d) " "!= orchestra sr (%d)\n"), sfinfo.samplerate, (int) (csound->esr + FL(0.5))); fmt = sfinfo.format & SF_FORMAT_SUBMASK; typ = sfinfo.format & SF_FORMAT_TYPEMASK; if ((fmt != SF_FORMAT_FLOAT && fmt != SF_FORMAT_DOUBLE) || (typ == SF_FORMAT_WAV || typ == SF_FORMAT_W64 || typ == SF_FORMAT_AIFF)) p->scaleFac = csound->e0dbfs; else p->scaleFac = FL(1.0); /* do not scale "raw" float files */ /* initialise read position */ pos = (double)*(p->iSkipTime) * (double)sfinfo.samplerate; p->read_pos = (int_least64_t)(pos + (pos >= 0.0 ? 0.5 : -0.5)); /* allocate and initialise buffer */ n = p->bufSize * p->nChannels; if (n != (int) p->auxData.size) csound->AuxAlloc(csound, (int32) (n * (int) sizeof(MYFLT)), &(p->auxData)); p->buf = (MYFLT*) (p->auxData.auxp); /* make sure that read position is not in buffer, to force read */ if (p->read_pos < (int_least64_t) 0) p->bufStartPos = (int_least64_t) p->bufSize; else p->bufStartPos = -((int_least64_t) p->bufSize); /* done initialisation */ if (csound->realtime_audio_flag) { csound->FSeekAsync(csound,p->fdch.fd, p->read_pos, SEEK_SET); // csound->Message(csound, "using async code \n"); } return OK; } int sndinset(CSOUND *csound, SOUNDIN_ *p){ return sndinset_(csound,p,0); } int sndinset_S(CSOUND *csound, SOUNDIN_ *p){ return sndinset_(csound,p,1); } int soundin(CSOUND *csound, SOUNDIN_ *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, nsmps=CS_KSMPS, bufPos; int i; if (UNLIKELY(p->fdch.fd == NULL)) { return csound->PerfError(csound, p->h.insdshead, Str("soundin: not initialised")); } if (UNLIKELY(offset)) for (i=0; inChannels; i++) memset(p->aOut[i], '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; for (i=0; inChannels; i++) memset(&(p->aOut[i][nsmps]), '\0', early*sizeof(MYFLT)); } for (nn = offset; nn < nsmps; nn++) { bufPos = (int) (p->read_pos - p->bufStartPos); if ((unsigned int) bufPos >= (unsigned int) p->bufSize) { /* not in current buffer frame, need to read file */ soundin_read_buffer(csound, p, bufPos); /* recalculate buffer position */ bufPos = (int) (p->read_pos - p->bufStartPos); } /* copy all channels from buffer */ if (p->nChannels == 1) { p->aOut[0][nn] = p->scaleFac * (MYFLT) p->buf[bufPos]; } else if (p->nChannels == 2) { bufPos += bufPos; p->aOut[0][nn] = p->scaleFac * p->buf[bufPos]; p->aOut[1][nn] = p->scaleFac * p->buf[bufPos + 1]; } else { bufPos *= p->nChannels; i = 0; do { p->aOut[i++][nn] = p->scaleFac * p->buf[bufPos++]; } while (i < p->nChannels); } p->read_pos++; } return OK; } #endif csound-6.10.0/OOps/disprep.c000066400000000000000000000610321321653344700155750ustar00rootroot00000000000000/* disprep.c: Copyright (C) 1991 Barry Vercoe This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* DISPREP.C */ #include #include "cwindow.h" #include "disprep.h" #ifdef MSVC /* Thanks to Richard Dobson */ # define hypot _hypot #endif int printv(CSOUND *csound, PRINTV *p) { int nargs = p->INOCOUNT; char **txtp = p->h.optext->t.inlist->arg; MYFLT **valp = p->iargs; csound->MessageS(csound, CSOUNDMSG_ORCH, "instr %d:", (int) p->h.insdshead->p1.value); while (nargs--) { csound->MessageS(csound, CSOUNDMSG_ORCH, " %s = %5.3f", *txtp++, **valp++); } csound->MessageS(csound, CSOUNDMSG_ORCH, "\n"); return OK; } int fdspset(CSOUND *csound, FSIGDISP *p){ char strmsg[256]; p->size = p->fin->N/2 + 1; if ((*p->points != (MYFLT) 0) && (p->size > (int) *p->points)) { p->size = *p->points; } if ((p->fdata.auxp == NULL) || (p->fdata.size < (unsigned int) (p->size*sizeof(MYFLT)))) { csound->AuxAlloc(csound, p->size*sizeof(MYFLT), &p->fdata); } snprintf(strmsg, 256, Str("instr %d, pvs-signal %s:"), (int) p->h.insdshead->p1.value, p->h.optext->t.inlist->arg[0]); dispset(csound, &p->dwindow, (MYFLT*) p->fdata.auxp, p->size, strmsg, (int) *p->flag, Str("display")); p->lastframe = 0; return OK; } int fdsplay(CSOUND *csound, FSIGDISP *p) { float *fin = p->fin->frame.auxp; MYFLT *pdata = p->fdata.auxp; int i,k, end = p->size; if (p->lastframe < p->fin->framecount) { for (i=0, k=0; k < end; i+=2,k++) pdata[k] = fin[i]; display(csound, &p->dwindow); p->lastframe = p->fin->framecount; } return OK; } int dspset(CSOUND *csound, DSPLAY *p) { int32 npts, nprds, bufpts, totpts; char *auxp; char strmsg[256]; if (p->h.optext->t.intype == 'k') npts = (int32)(*p->iprd * CS_EKR); else npts = (int32)(*p->iprd * csound->esr); if (UNLIKELY(npts <= 0)) { return csound->InitError(csound, Str("illegal iprd in display")); } if ((nprds = (int32)*p->inprds) <= 1) { nprds = 0; bufpts = npts; totpts = npts; } else { bufpts = npts * nprds; totpts = bufpts * 2; } if ((auxp = p->auxch.auxp) == NULL || totpts != p->totpts) { csound->AuxAlloc(csound, totpts * sizeof(MYFLT), &p->auxch); auxp = p->auxch.auxp; p->begp = (MYFLT *) auxp; p->endp = p->begp + bufpts; p->npts = npts; p->nprds = nprds; p->bufpts = bufpts; p->totpts = totpts; } p->nxtp = (MYFLT *) auxp; p->pntcnt = npts; snprintf(strmsg, 256, Str("instr %d, signal %s:"), (int) p->h.insdshead->p1.value, p->h.optext->t.inlist->arg[0]); dispset(csound, &p->dwindow, (MYFLT*) auxp, bufpts, strmsg, (int) *p->iwtflg, Str("display")); return OK; } int kdsplay(CSOUND *csound, DSPLAY *p) { MYFLT *fp = p->nxtp; if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; /* RWD fix */ if (!p->nprds) { *fp++ = *p->signal; if (fp >= p->endp) { fp = p->begp; display(csound, &p->dwindow); } } else { MYFLT *fp2 = fp + p->bufpts; *fp++ = *p->signal; *fp2 = *p->signal; if (!(--p->pntcnt)) { p->pntcnt = p->npts; if (fp >= p->endp) { fp = p->begp; fp2 = fp + p->bufpts; } p->dwindow.fdata = fp; /* display from fp */ display(csound, &p->dwindow); } } p->nxtp = fp; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("display: not initialised")); } int dsplay(CSOUND *csound, DSPLAY *p) { MYFLT *fp = p->nxtp, *sp = p->signal, *endp = p->endp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; nsmps -= early; if (!p->nprds) { for (n=offset; n= endp) { fp = p->begp; display(csound, &p->dwindow); } } } else { MYFLT *fp2 = fp + p->bufpts; for (n=offset; npntcnt)) { p->pntcnt = p->npts; if (fp >= endp) { fp = p->begp; fp2 = fp + p->bufpts; } p->dwindow.fdata = fp; /* display from fp */ display(csound, &p->dwindow); } } } p->nxtp = fp; return OK; } /* Write window coefs into buffer, don't malloc */ static void FillHalfWin(MYFLT *wBuf, int32 size, MYFLT max, int hannq) /* 1 => hanning window else hamming */ { MYFLT a,b; int32 i; if (hannq) { a = FL(0.50); b = FL(0.50); } else { a = FL(0.54); b = FL(0.46); } if (wBuf!= NULL) { /* NB: size/2 + 1 long - just indep terms */ MYFLT tmp; size /= 2; /* to fix scaling */ tmp = PI_F/(MYFLT)size; /* optimisatuon?? */ for (i=0; i<=size;++i) wBuf[i] = max * (a-b*COS(tmp*(MYFLT)i) ); } return; } static void ApplyHalfWin(MYFLT *buf, MYFLT *win, int32 len) { /* Window only store 1st half, is symmetric */ int32 j; int32 lenOn2 = (len/2); for (j=lenOn2+1; j--; ) *buf++ *= *win++; for (j =len-lenOn2-1, win--; j--; ) *buf++ *= *--win; } int fftset(CSOUND *csound, DSPFFT *p) /* fftset, dspfft -- calc Fast Fourier */ /* Transform of collected samples and */ /* displays coefficients (mag or db) */ { int32 window_size, step_size; int hanning; char strmsg[256]; int32 minbin, maxbin; minbin = *p->imin; maxbin = *p->imax; if(p->smpbuf.auxp == NULL) csound->AuxAlloc(csound, sizeof(MYFLT)*WINDMAX, &(p->smpbuf)); p->sampbuf = (MYFLT *) p->smpbuf.auxp; window_size = (int32)*p->inpts; if (UNLIKELY(window_size > WINDMAX)) { return csound->InitError(csound, Str("too many points requested")); } if (UNLIKELY(window_size < WINDMIN)) { return csound->InitError(csound, Str("too few points requested")); } if (UNLIKELY(window_size < 1L || (window_size & (window_size - 1L)) != 0L)) { return csound->InitError(csound, Str("window size must be power of two")); } if (p->h.optext->t.intype == 'k') step_size = (int32)(*p->iprd * CS_EKR); else step_size = (int32)(*p->iprd * csound->esr); if (UNLIKELY(step_size <= 0)) { return csound->InitError(csound, Str("illegal iprd in ffy display")); } hanning = (int)*p->ihann; p->dbout = (int)*p->idbout; p->overlap = window_size - step_size; if ( (maxbin - minbin) != p->npts || minbin != p->start || window_size != p->windsize || hanning != p->hanning) { /* if windowing has changed: */ int32 auxsiz; MYFLT *hWin; p->windsize = window_size; /* set new parameter values */ p->hanning = hanning; p->bufp = p->sampbuf; p->endp = p->bufp + window_size; p->overN = FL(1.0)/(*p->inpts); p->ncoefs = window_size >>1; auxsiz = (window_size/2 + 1) * sizeof(MYFLT); /* size for half window */ csound->AuxAlloc(csound, (int32)auxsiz, &p->auxch); /* alloc or realloc */ hWin = (MYFLT *) p->auxch.auxp; FillHalfWin(hWin, window_size, FL(1.0), hanning); /* fill with proper values */ if (csound->disprep_fftcoefs == NULL) { /* room for WINDMAX*2 floats (fft size) */ csound->disprep_fftcoefs = (MYFLT*) csound->Malloc(csound, WINDMAX * 2 * sizeof(MYFLT)); } snprintf(strmsg, 256, Str("instr %d, signal %s, fft (%s):"), (int) p->h.insdshead->p1.value, p->h.optext->t.inlist->arg[0], p->dbout ? Str("db") : Str("mag")); if(maxbin == 0) maxbin = p->ncoefs; if(minbin > maxbin) minbin = 0; p->npts = maxbin - minbin; p->start = minbin; dispset(csound, &p->dwindow, csound->disprep_fftcoefs+p->start, p->npts, strmsg, (int) *p->iwtflg, Str("fft")); } return OK; } /* pack re,im,re,im into re,re */ static void PackReals(MYFLT *buffer, int32 size) { MYFLT *b2 = buffer; ++size; while (--size) { *b2++ = *buffer++; ++buffer; } } /* Convert Real & Imaginary spectra into Amplitude & Phase */ static void Rect2Polar(MYFLT *buffer, int32 size, MYFLT scal) { int32 i; MYFLT *real,*imag; MYFLT re,im; MYFLT mag; real = buffer; imag = buffer+1; for (i = 0; i < size; i++) { re = real[i+i]*scal; im = imag[i+i]*scal; real[2L*i] = mag = HYPOT(re,im); if (mag == FL(0.0)) imag[i+i] = FL(0.0); else imag[i+i] = ATAN2(im,re); } } /* packed buffer ie. reals, not complex */ static void Lin2DB(MYFLT *buffer, int32 size) { while (size--) { if(*buffer > 0.0) *buffer = /* FL(20.0)*log10 */ FL(8.68589)*LOG(*buffer); buffer++; } } static void d_fft( /* perform an FFT as reqd below */ CSOUND *csound, MYFLT *sce, /* input array - pure packed real */ MYFLT *dst, /* output array - packed magnitude, only half-length */ int32 size, /* number of points in input */ MYFLT *hWin, /* hanning window lookup table */ int dbq, MYFLT scal) /* flag: 1-> convert output into db */ { memcpy(dst, sce, sizeof(MYFLT) * size); /* copy into scratch buffer */ ApplyHalfWin(dst, hWin, size); csound->RealFFT(csound, dst, (int) size); /* perform the FFT */ dst[size] = dst[1]; dst[1] = dst[size + 1L] = FL(0.0); Rect2Polar(dst, (size >> 1) + 1, scal); PackReals(dst, (size >> 1) + 1); if (dbq) Lin2DB(dst, (size >> 1) + 1); } int kdspfft(CSOUND *csound, DSPFFT *p) { MYFLT *bufp = p->bufp, *endp = p->endp; if(p->dbout) p->dwindow.polarity = NEGPOL; else p->dwindow.polarity = POSPOL; if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; /* RWD fix */ if (bufp < p->sampbuf) /* skip any spare samples */ bufp++; else { /* then start collecting */ *bufp++ = *p->signal; if (bufp >= endp) { /* when full, do fft: */ MYFLT *tp; //MYFLT *tplim; MYFLT *hWin = (MYFLT *) p->auxch.auxp; d_fft(csound, p->sampbuf, csound->disprep_fftcoefs, p->windsize, hWin, p->dbout, p->overN); tp = csound->disprep_fftcoefs; //tplim = tp + p->ncoefs; //do { // *tp *= p->overN; /* scale 1/N */ //} while (++tp < tplim); display(csound, &p->dwindow); /* & display */ if (p->overlap > 0) { bufp = p->sampbuf; tp = endp - p->overlap; do { *bufp++ = *tp++; } while (tp < endp); } else bufp = p->sampbuf + p->overlap; } } p->bufp = bufp; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("dispfft: not initialised")); } int dspfft(CSOUND *csound, DSPFFT *p) { MYFLT *sigp = p->signal, *bufp = p->bufp, *endp = p->endp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if(p->dbout){ p->dwindow.polarity = NEGPOL; p->dwindow.absflag = 1; } else p->dwindow.polarity = POSPOL; if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; nsmps -= early; for (n=offset; nsampbuf) { /* skip any spare samples */ bufp++; sigp++; } else { /* then start collecting */ *bufp++ = *sigp++; if (bufp >= endp) { /* when full, do fft: */ MYFLT *tp; //MYFLT *tplim; MYFLT *hWin = (MYFLT *) p->auxch.auxp; d_fft(csound, p->sampbuf, csound->disprep_fftcoefs, p->windsize, hWin, p->dbout, p->overN); tp = csound->disprep_fftcoefs; //tplim = tp + p->ncoefs; //do { // *tp *= p->overN; /* scale 1/N */ //} while (++tp < tplim); display(csound, &p->dwindow); /* & display */ if (p->overlap > 0) { bufp = p->sampbuf; tp = endp - p->overlap; do { *bufp++ = *tp++; } while(tp < endp); } else bufp = p->sampbuf + p->overlap; } } } p->bufp = bufp; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("dispfft: not initialised")); } #define NTERMS 4 #define NCROSS (NTERMS * (NTERMS-1)) int tempeset(CSOUND *csound, TEMPEST *p) { int npts = 0, nptsm1, minlam = 0, maxlam, lamspan, auxsiz; MYFLT *fltp; FUNC *ftp; MYFLT b, iperiod = *p->iprd; char strmsg[256]; if (UNLIKELY((p->timcount = (int)(CS_EKR * iperiod)) <= 0)) return csound->InitError(csound, Str("illegal iperiod")); if (UNLIKELY((p->dtimcnt = (int)(CS_EKR * *p->idisprd)) < 0)) return csound->InitError(csound, Str("illegal idisprd")); if (UNLIKELY((p->tweek = *p->itweek) <= 0)) return csound->InitError(csound, Str("illegal itweek")); if (iperiod != FL(0.0)) { if (UNLIKELY((minlam = (int)(*p->imindur/iperiod)) <= 0)) return csound->InitError(csound, Str("illegal imindur")); if (UNLIKELY((npts = (int)(*p->imemdur / iperiod)) <= 0)) return csound->InitError(csound, Str("illegal imemdur")); } if (UNLIKELY(*p->ihtim <= FL(0.0))) return csound->InitError(csound, Str("illegal ihtim")); if (UNLIKELY(*p->istartempo <= FL(0.0))) return csound->InitError(csound, Str("illegal startempo")); ftp = csound->FTFind(csound, p->ifn); if (UNLIKELY(ftp != NULL && *ftp->ftable == FL(0.0))) return csound->InitError(csound, Str("ifn table begins with zero")); if (UNLIKELY(ftp==NULL)) return NOTOK; if (npts==0) return NOTOK; nptsm1 = npts - 1; if (npts != p->npts || minlam != p->minlam) { p->npts = npts; p->minlam = minlam; p->maxlam = maxlam = nptsm1/(NTERMS-1); lamspan = maxlam - minlam + 1; /* alloc 8 bufs: 2 circ, 6 lin */ auxsiz = (npts * 5 + lamspan * 3) * sizeof(MYFLT); csound->AuxAlloc(csound, (int32)auxsiz, &p->auxch); fltp = (MYFLT *) p->auxch.auxp; p->hbeg = fltp; fltp += npts; p->hend = fltp; p->xbeg = fltp; fltp += npts; p->xend = fltp; p->stmemp = fltp; fltp += npts; p->linexp = fltp; fltp += npts; p->ftable = fltp; fltp += npts; p->xscale = fltp; fltp += lamspan; p->lmults = fltp; fltp += lamspan; p->lambdas = (int16 *) fltp; p->stmemnow = p->stmemp + nptsm1; } if (p->dtimcnt && !(p->dwindow.windid)) { /* init to display stmem & exp */ snprintf(strmsg, 256, "instr %d tempest:", (int) p->h.insdshead->p1.value); dispset(csound, &p->dwindow, p->stmemp, (int32)npts * 2, strmsg, 0, Str("tempest")); p->dwindow.danflag = 1; /* for mid-scale axis */ } { MYFLT *funp = ftp->ftable; int32 phs = 0; int32 inc = (int32)PHMASK / npts; int32 nn, lobits = ftp->lobits; for (fltp=p->hbeg, nn=npts*4; nn--; ) /* clr 2 circ & 1st 2 lin bufs */ *fltp++ = FL(0.0); for (fltp=p->ftable+npts, nn=npts; nn--; ) { /* now sample the ftable */ *--fltp = *(funp + (phs >> lobits)); /* backwards into tbl buf */ phs += inc; } } { MYFLT *tblp, sumraw, sumsqr; /* calc the CROSS prod scalers */ int32 terms; int32 lambda, maxlam; MYFLT crossprods, RMS, *endtable = p->ftable + nptsm1; /* MYFLT coef, log001 = -6.9078; */ MYFLT *xscale = p->xscale; p->ncross = (MYFLT) NCROSS; for (lambda=p->minlam,maxlam=p->maxlam; lambda <= maxlam; lambda++) { tblp = endtable; sumraw = *tblp; sumsqr = *tblp * *tblp; terms = NTERMS - 1; do { tblp -= lambda; sumraw += *tblp; sumsqr += *tblp * *tblp; } while (--terms); crossprods = sumraw * sumraw - sumsqr; RMS = SQRT(crossprods / p->ncross); /* coef = exp(log001 * lambda / npts); *xscale++ = coef / RMS / (NTERMS - 1); */ *xscale++ = FL(0.05)/ RMS / lambda; } } /* calc input lo-pass filter coefs */ b = FL(2.0) - COS((*p->ihp * 6.28318 * CS_ONEDKR)); p->coef1 = b - SQRT(b * b - FL(1.0)); p->coef0 = FL(1.0) - p->coef1; p->yt1 = FL(0.0); p->fwdcoef = POWER(FL(0.5), p->timcount*CS_ONEDKR/(*p->ihtim)); p->fwdmask = FL(0.0); #ifdef DEBUG csound->Message(csound, Str("kin lopass coef1 %6.4f, fwd mask coef1 %6.4f\n"), p->coef1, p->fwdcoef); #endif p->thresh = *p->ithresh; /* record incoming loudness threshold */ p->xfdbak = *p->ixfdbak; /* & expectation feedback fraction */ p->tempscal = FL(60.0) * CS_EKR / p->timcount; p->avglam = p->tempscal / *p->istartempo; /* init the tempo factors */ p->tempo = FL(0.0); p->hcur = p->hbeg; /* init the circular ptrs */ p->xcur = p->xbeg; p->countdown = p->timcount; /* & prime the countdowns */ p->dcntdown = p->dtimcnt; return OK; } #define NMULTS 5 static const MYFLT lenmults[NMULTS] = { FL(3.0), FL(2.0), FL(1.0), FL(0.5), FL(0.333) }; static const MYFLT lenfracs[NMULTS*2] = { FL(0.30), FL(0.3667), FL(0.45), FL(0.55), FL(0.92), FL(1.08), FL(1.88), FL(2.12), FL(2.85), FL(3.15) }; int tempest(CSOUND *csound, TEMPEST *p) { p->yt1 = p->coef0 * *p->kin + p->coef1 * p->yt1; /* get lo-pass of kinput */ if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; /* RWD fix */ if (!(--p->countdown)) { /* then on countdown: */ MYFLT *memp; MYFLT kin, expect, *xcur = p->xcur; /* xcur from prv pass */ MYFLT lamtot = FL(0.0), weightot = FL(0.0); p->countdown = p->timcount; /* reset the countdown */ expect = *xcur; /* get expected val from prv calc */ *xcur++ = FL(0.0); /* & clear the loc it occupied */ if (xcur >= p->xend) xcur = p->xbeg; /* xcur now points to cur xarray */ p->xcur = xcur; #ifdef DEBUG csound->Message(csound, "**kin -> %f (%f,%f)\n", *p->kin - p->yt1, *p->kin, p->yt1); #endif if ((kin = *p->kin - p->yt1) < FL(0.0)) kin = FL(0.0); { /* ignore input below lopass */ MYFLT *hcur = p->hcur; MYFLT *hend = p->hend; MYFLT *tblp = p->ftable; int32 wrap; *hcur++ = kin + expect * p->xfdbak; /* join insample & expect val */ if (hcur < hend) p->hcur = hcur; /* stor pntr for next insamp */ else p->hcur = p->hbeg; wrap = hcur - p->hbeg; memp = p->stmemp; while (hcur < hend) /* now lineariz & envlp hbuf */ *memp++ = *hcur++ * *tblp++; /* into st_mem buf */ for (hcur=p->hbeg; wrap--; ) *memp++ = *hcur++ * *tblp++; } if (p->yt1 > p->thresh /* if lo-pass of kinput now significant */ && kin > p->fwdmask) { /* & kin > masking due to prev kin */ MYFLT sumraw, sumsqr; int32 lambda, minlam, maxlam; int terms, nn, npts = p->npts; MYFLT mult, crossprods, RMScross, RMStot, unilam, rd; MYFLT *xend = p->xend; /* MYFLT *xscale = p->xscale; */ const MYFLT *mults, *fracs; MYFLT *mulp; int16 minlen, maxlen, *lenp, *endlens; for (memp=p->stmemp,nn=npts,sumsqr=FL(0.0); nn--; memp++) sumsqr += *memp * *memp; RMStot = (MYFLT)sqrt(sumsqr/npts); #ifdef DEBUG csound->Message(csound, "RMStot = %6.1f\n", RMStot); #endif mults = lenmults; /* use the static lentables */ fracs = lenfracs; mulp = p->lmults; lenp = p->lambdas; minlam = p->minlam; maxlam = p->maxlam; nn = NMULTS; do { mult = *mults++; minlen = (int16)(p->avglam * *fracs++); /* & the current avglam */ maxlen = (int16)(p->avglam * *fracs++); if (minlen >= minlam && maxlen <= maxlam) do { *lenp++ = minlen++; /* creat lst of lambda lens */ *mulp++ = mult; /* & their unit multipliers */ } while (minlen <= maxlen); } while (--nn); endlens = lenp; /* now for these lambda lens: */ for (lenp=p->lambdas,mulp=p->lmults; lenp < endlens; ) { lambda = *lenp++; mult = *mulp++; memp = p->stmemnow; sumraw = *memp; sumsqr = *memp * *memp; /* autocorrelate the st_mem buf */ terms = NTERMS - 1; do { memp -= lambda; sumraw += *memp; sumsqr += *memp * *memp; } while (--terms); crossprods = sumraw * sumraw - sumsqr; if (crossprods >= 0) RMScross = SQRT(crossprods / p->ncross); else RMScross = FL(0.0); if (RMScross < FL(1.4) * RMStot) /* if RMScross significant: */ continue; #ifdef DEBUG csound->Message(csound, "RMScross = %6.1f, lambda = %ld\n", RMScross, lambda); #endif /* RMS *= *xscale++; */ unilam = lambda * mult; /* get unit lambda implied */ lamtot += unilam * RMScross; /* & add weighted to total */ weightot += RMScross; RMScross /= FL(5.0); memp = xcur - 1; /* multiply project into expect buf */ for (terms=1; terms < NTERMS; ++terms) { if ((memp += (lambda-terms+1)) >= xend) memp -= npts; for (nn=terms,rd=RMScross/terms; nn--; ) { *memp++ += rd; if (memp >= xend) memp -= npts; } } } } if (weightot) { /* if accumed weights, */ p->avglam = (p->avglam + lamtot/weightot)/FL(2.0); /* update the avglam */ p->avglam /= p->tweek; p->tempo = p->tempscal / p->avglam; /* & cvt to tempo */ #ifdef DEBUG csound->Message(csound, "lamtot %6.2f, weightot %6.2f, " "newavglam %6.2f, tempo %6.2f\n", lamtot, weightot, p->avglam, p->tempo); #endif } else { if (kin < -(p->fwdmask)) { p->tempo = FL(0.0); /* else tempo is 0 */ } } p->fwdmask = p->fwdmask * p->fwdcoef + kin; } if (!(--p->dcntdown)) { /* on display countdown */ MYFLT *linp = p->linexp; MYFLT *xcur = p->xcur; MYFLT *xend = p->xend; int32 wrap = xcur - p->xbeg; while (xcur < xend) /* lineariz the circ xbuf */ *linp++ = *xcur++; /* into linexp buf */ for (xcur=p->xbeg; wrap--; ) *linp++ = *xcur++; display(csound, &p->dwindow); /* display double window */ p->dcntdown = p->dtimcnt; /* & reset the counter */ } /* if (p->tempo != 0.0) */ *p->kout = p->tempo; /* put current tempo */ return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("tempest: not initialised")); } csound-6.10.0/OOps/dumpf.c000066400000000000000000000647741321653344700152620ustar00rootroot00000000000000/* dumpf.c: Copyright (C) 1991 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* DUMPF.C */ #include "dumpf.h" #include static const int dumpf_format_table[9] = { 0, CSFTYPE_INTEGER_BINARY, 0, 0, CSFTYPE_INTEGER_BINARY, CSFTYPE_INTEGER_BINARY, CSFTYPE_FLOATS_BINARY, CSFTYPE_INTEGER_TEXT, CSFTYPE_FLOATS_TEXT, }; int kdmpset_S(CSOUND *csound, KDUMP *p) { /* open in curdir or pathname */ char soundoname[1024]; if (UNLIKELY((p->format = (int)*p->iformat) < 1 || p->format > 8)) { return csound->InitError(csound, Str("unknown format request")); } if (UNLIKELY(p->format == 2 || p->format == 3)) { return csound->InitError(csound, Str("alaw and ulaw not implemented here")); } strncpy(soundoname, ((STRINGDAT *)p->ifilcod)->data, 1023); if (p->fdch.fd != NULL) fdclose(csound, &(p->fdch)); p->fdch.fd = csound->FileOpen2(csound, &(p->f), CSFILE_STD, soundoname, "wb", "", dumpf_format_table[p->format], 0); if (UNLIKELY(p->fdch.fd == NULL)) return csound->InitError(csound, Str("Cannot open %s"), soundoname); fdrecord(csound, &p->fdch); if ((p->timcount = (int32)(*p->iprd * CS_EKR)) <= 0) p->timcount = 1; p->countdown = p->timcount; return OK; } int kdmpset_p(CSOUND *csound, KDUMP *p) { /* open in curdir or pathname */ char soundoname[1024]; if (UNLIKELY((p->format = (int)*p->iformat) < 1 || p->format > 8)) { return csound->InitError(csound, Str("unknown format request")); } if (UNLIKELY(p->format == 2 || p->format == 3)) { return csound->InitError(csound, Str("alaw and ulaw not implemented here")); } if (csound->ISSTRCOD(*p->ifilcod)) strncpy(soundoname, get_arg_string(csound, *p->ifilcod), 1023); else csound->strarg2name(csound, soundoname, p->ifilcod, "dumpk.", 0); if (p->fdch.fd != NULL) fdclose(csound, &(p->fdch)); p->fdch.fd = csound->FileOpen2(csound, &(p->f), CSFILE_STD, soundoname, "wb", "", dumpf_format_table[p->format], 0); if (UNLIKELY(p->fdch.fd == NULL)) return csound->InitError(csound, Str("Cannot open %s"), soundoname); fdrecord(csound, &p->fdch); if ((p->timcount = (int32)(*p->iprd * CS_EKR)) <= 0) p->timcount = 1; p->countdown = p->timcount; return OK; } int kdmp2set_S(CSOUND *csound, KDUMP2 *p) { /* open in curdir or pathname */ char soundoname[1024]; if (UNLIKELY((p->format = (int)*p->iformat) < 1 || p->format > 8)) { return csound->InitError(csound, Str("unknown format request")); } if (UNLIKELY(p->format == 2 || p->format == 3)) { return csound->InitError(csound, Str("alaw and ulaw not implemented here")); } strncpy(soundoname, ((STRINGDAT *)p->ifilcod)->data, 1023); if (p->fdch.fd != NULL) fdclose(csound, &(p->fdch)); p->fdch.fd = csound->FileOpen2(csound, &(p->f), CSFILE_STD, soundoname, "wb", "", dumpf_format_table[p->format], 0); if (UNLIKELY(p->fdch.fd == NULL)) return csound->InitError(csound, Str("Cannot open %s"), soundoname); fdrecord(csound, &p->fdch); if ((p->timcount = (int32)(*p->iprd * CS_EKR)) <= 0) p->timcount = 1; p->countdown = p->timcount; return OK; } int kdmp2set_p(CSOUND *csound, KDUMP2 *p) { /* open in curdir or pathname */ char soundoname[1024]; if (UNLIKELY((p->format = (int)*p->iformat) < 1 || p->format > 8)) { return csound->InitError(csound, Str("unknown format request")); } if (UNLIKELY(p->format == 2 || p->format == 3)) { return csound->InitError(csound, Str("alaw and ulaw not implemented here")); } if (csound->ISSTRCOD(*p->ifilcod)) strncpy(soundoname, get_arg_string(csound, *p->ifilcod), 1023); else csound->strarg2name(csound, soundoname, p->ifilcod, "dumpk.", 0); if (p->fdch.fd != NULL) fdclose(csound, &(p->fdch)); p->fdch.fd = csound->FileOpen2(csound, &(p->f), CSFILE_STD, soundoname, "wb", "", dumpf_format_table[p->format], 0); if (UNLIKELY(p->fdch.fd == NULL)) return csound->InitError(csound, Str("Cannot open %s"), soundoname); fdrecord(csound, &p->fdch); if ((p->timcount = (int32)(*p->iprd * CS_EKR)) <= 0) p->timcount = 1; p->countdown = p->timcount; return OK; } int kdmp3set_S(CSOUND *csound, KDUMP3 *p) { /* open in curdir or pathname */ char soundoname[1024]; if (UNLIKELY((p->format = (int)*p->iformat) < 1 || p->format > 8)) { return csound->InitError(csound, Str("unknown format request")); } if (UNLIKELY(p->format == 2 || p->format == 3)) { return csound->InitError(csound, Str("alaw and ulaw not implemented here")); } strncpy(soundoname, ((STRINGDAT *)p->ifilcod)->data, 1023); if (p->fdch.fd != NULL) fdclose(csound, &(p->fdch)); p->fdch.fd = csound->FileOpen2(csound, &(p->f), CSFILE_STD, soundoname, "wb", "", dumpf_format_table[p->format], 0); if (UNLIKELY(p->fdch.fd == NULL)) return csound->InitError(csound, Str("Cannot open %s"), soundoname); fdrecord(csound, &p->fdch); if ((p->timcount = (int32)(*p->iprd * CS_EKR)) <= 0) p->timcount = 1; p->countdown = p->timcount; return OK; } int kdmp3set_p(CSOUND *csound, KDUMP3 *p) { /* open in curdir or pathname */ char soundoname[1024]; if (UNLIKELY((p->format = (int)*p->iformat) < 1 || p->format > 8)) { return csound->InitError(csound, Str("unknown format request")); } if (UNLIKELY(p->format == 2 || p->format == 3)) { return csound->InitError(csound, Str("alaw and ulaw not implemented here")); } if (csound->ISSTRCOD(*p->ifilcod)) strncpy(soundoname, get_arg_string(csound, *p->ifilcod), 1023); else csound->strarg2name(csound, soundoname, p->ifilcod, "dumpk.", 0); if (p->fdch.fd != NULL) fdclose(csound, &(p->fdch)); p->fdch.fd = csound->FileOpen2(csound, &(p->f), CSFILE_STD, soundoname, "wb", "", dumpf_format_table[p->format], 0); if (UNLIKELY(p->fdch.fd == NULL)) return csound->InitError(csound, Str("Cannot open %s"), soundoname); fdrecord(csound, &p->fdch); if ((p->timcount = (int32)(*p->iprd * CS_EKR)) <= 0) p->timcount = 1; p->countdown = p->timcount; return OK; } int kdmp4set_S(CSOUND *csound, KDUMP4 *p) { /* open in curdir or pathname */ char soundoname[1024]; if (UNLIKELY((p->format = (int)*p->iformat) < 1 || p->format > 8)) { return csound->InitError(csound, Str("unknown format request")); } if (UNLIKELY(p->format == 2 || p->format == 3)) { return csound->InitError(csound, Str("alaw and ulaw not implemented here")); } strncpy(soundoname, ((STRINGDAT *)p->ifilcod)->data, 1023); if (p->fdch.fd != NULL) fdclose(csound, &(p->fdch)); p->fdch.fd = csound->FileOpen2(csound, &(p->f), CSFILE_STD, soundoname, "wb", "", dumpf_format_table[p->format], 0); if (p->fdch.fd == NULL) return csound->InitError(csound, Str("Cannot open %s"), soundoname); fdrecord(csound, &p->fdch); if ((p->timcount = (int32)(*p->iprd * CS_EKR)) <= 0) p->timcount = 1; p->countdown = p->timcount; return OK; } int kdmp4set_p(CSOUND *csound, KDUMP4 *p) { /* open in curdir or pathname */ char soundoname[1024]; if (UNLIKELY((p->format = (int)*p->iformat) < 1 || p->format > 8)) { return csound->InitError(csound, Str("unknown format request")); } if (UNLIKELY(p->format == 2 || p->format == 3)) { return csound->InitError(csound, Str("alaw and ulaw not implemented here")); } if (csound->ISSTRCOD(*p->ifilcod)) strncpy(soundoname, get_arg_string(csound, *p->ifilcod), 1023); else csound->strarg2name(csound, soundoname, p->ifilcod, "dumpk.", 0); if (p->fdch.fd != NULL) fdclose(csound, &(p->fdch)); p->fdch.fd = csound->FileOpen2(csound, &(p->f), CSFILE_STD, soundoname, "wb", "", dumpf_format_table[p->format], 0); if (p->fdch.fd == NULL) return csound->InitError(csound, Str("Cannot open %s"), soundoname); fdrecord(csound, &p->fdch); if ((p->timcount = (int32)(*p->iprd * CS_EKR)) <= 0) p->timcount = 1; p->countdown = p->timcount; return OK; } static void nkdump(CSOUND *csound, MYFLT *kp, FILE *ofd, int format, int nk, void *p) { char buf1[256], outbuf[256]; int len = 0; switch(format) { /* place formatted kvals into outbuf */ case 1: { int8_t *bp = (int8_t*) outbuf; len = nk; while (nk--) *bp++ = (int8_t) *kp++; break; } case 4: { int16_t *bp = (int16_t*) outbuf; len = nk * 2; while (nk--) *bp++ = (int16_t) *kp++; break; } case 5: { int32_t *bp = (int32_t*) outbuf; len = nk * 4; while (nk--) *bp++ = (int32_t) *kp++; break; } case 6: { float *bp = (float*) outbuf; len = nk * sizeof(float); while (nk--) *bp++ = (float) *kp++; break; } case 7: outbuf[0] = '\0'; while (--nk) { snprintf(buf1, 256, "%ld\t", (long) *kp++); strlcat(outbuf, buf1, 256); } snprintf(buf1, 256, "%ld\n", (long) *kp); strlcat(outbuf, buf1, 256); len = strlen(outbuf); break; case 8: *outbuf = '\0'; while (--nk) { CS_SPRINTF(buf1, "%6.4f\t", *kp++); strlcat(outbuf, buf1, 256); } CS_SPRINTF(buf1, "%6.4f\n", *kp); strlcat(outbuf, buf1, 256); len = strlen(outbuf); break; default: csound->PerfError(csound,((KDUMP *)p)->h.insdshead, Str("unknown kdump format")); } if (UNLIKELY(fwrite(outbuf, len, 1, ofd)!=1)) { /* now write the buffer */ csound->PerfError(csound, ((KDUMP *)p)->h.insdshead, Str("write failure in dumpk")); } } int kdump(CSOUND *csound, KDUMP *p) { MYFLT kval[4]; if (--p->countdown <= 0) { p->countdown = p->timcount; kval[0] = *p->ksig; nkdump(csound, kval, p->f, p->format, 1, p); } return OK; } int kdump2(CSOUND *csound, KDUMP2 *p) { MYFLT kval[4]; if (--p->countdown <= 0) { p->countdown = p->timcount; kval[0] = *p->ksig1; kval[1] = *p->ksig2; nkdump(csound, kval, p->f, p->format, 2, p); } return OK; } int kdump3(CSOUND *csound, KDUMP3 *p) { MYFLT kval[4]; if (--p->countdown <= 0) { p->countdown = p->timcount; kval[0] = *p->ksig1; kval[1] = *p->ksig2; kval[2] = *p->ksig3; nkdump(csound, kval, p->f, p->format, 3, p); } return OK; } int kdump4(CSOUND *csound, KDUMP4 *p) { MYFLT kval[4]; if (--p->countdown <= 0) { p->countdown = p->timcount; kval[0] = *p->ksig1; kval[1] = *p->ksig2; kval[2] = *p->ksig3; kval[3] = *p->ksig4; nkdump(csound, kval, p->f, p->format, 4, p); } return OK; } /* ******************************************************************** */ /* ******** READK and friends; new code 1999 Feb 14 by JPff ******** */ /* ******************************************************************** */ int krdset_p(CSOUND *csound, KREAD *p) { /* open in curdir or pathname */ char soundiname[1024]; if (UNLIKELY((p->format = (int)*p->iformat) < 1 || p->format > 8)) { return csound->InitError(csound, Str("unknown format request")); } if (UNLIKELY(p->format == 2 || p->format == 3)) { return csound->InitError(csound, Str("alaw and ulaw not implemented here")); } if (csound->ISSTRCOD(*p->ifilcod)) strncpy(soundiname, get_arg_string(csound, *p->ifilcod), 1023); else csound->strarg2name(csound, soundiname, p->ifilcod, "readk.", 0); if (p->fdch.fd != NULL) fdclose(csound, &(p->fdch)); p->fdch.fd = csound->FileOpen2(csound, &(p->f), CSFILE_STD, soundiname, "rb", "SFDIR;SSDIR", dumpf_format_table[p->format], 0); if (UNLIKELY(p->fdch.fd == NULL)) return csound->InitError(csound, Str("Cannot open %s"), soundiname); fdrecord(csound, &p->fdch); if ((p->timcount = (int32)(*p->iprd * CS_EKR)) <= 0) p->timcount = 1; p->countdown = 0; p->k[0] = p->k[1] = p->k[2] = p->k[3] = FL(0.0); return OK; } int krdset_S(CSOUND *csound, KREAD *p) { /* open in curdir or pathname */ char soundiname[1024]; if (UNLIKELY((p->format = (int)*p->iformat) < 1 || p->format > 8)) { return csound->InitError(csound, Str("unknown format request")); } if (UNLIKELY(p->format == 2 || p->format == 3)) { return csound->InitError(csound, Str("alaw and ulaw not implemented here")); } strncpy(soundiname, ((STRINGDAT *)p->ifilcod)->data, 1023); if (p->fdch.fd != NULL) fdclose(csound, &(p->fdch)); p->fdch.fd = csound->FileOpen2(csound, &(p->f), CSFILE_STD, soundiname, "rb", "SFDIR;SSDIR", dumpf_format_table[p->format], 0); if (UNLIKELY(p->fdch.fd == NULL)) return csound->InitError(csound, Str("Cannot open %s"), soundiname); fdrecord(csound, &p->fdch); if ((p->timcount = (int32)(*p->iprd * CS_EKR)) <= 0) p->timcount = 1; p->countdown = 0; p->k[0] = p->k[1] = p->k[2] = p->k[3] = FL(0.0); return OK; } int krd2set_S(CSOUND *csound, KREAD2 *p) { /* open in curdir or pathname */ char soundiname[1024]; if (UNLIKELY((p->format = (int)*p->iformat) < 1 || p->format > 8)) { return csound->InitError(csound, Str("unknown format request")); } if (UNLIKELY(p->format == 2 || p->format == 3)) { return csound->InitError(csound, Str("alaw and ulaw not implemented here")); } strncpy(soundiname, ((STRINGDAT *)p->ifilcod)->data, 1023); if (p->fdch.fd != NULL) fdclose(csound, &(p->fdch)); p->fdch.fd = csound->FileOpen2(csound, &(p->f), CSFILE_STD, soundiname, "rb", "SFDIR;SSDIR", dumpf_format_table[p->format], 0); if (UNLIKELY(p->fdch.fd == NULL)) return csound->InitError(csound, Str("Cannot open %s"), soundiname); fdrecord(csound, &p->fdch); if ((p->timcount = (int32)(*p->iprd * CS_EKR)) <= 0) p->timcount = 1; p->countdown = 0; p->k[0] = p->k[1] = p->k[2] = p->k[3] = FL(0.0); return OK; } int krd2set_p(CSOUND *csound, KREAD2 *p) { /* open in curdir or pathname */ char soundiname[1024]; if (UNLIKELY((p->format = (int)*p->iformat) < 1 || p->format > 8)) { return csound->InitError(csound, Str("unknown format request")); } if (UNLIKELY(p->format == 2 || p->format == 3)) { return csound->InitError(csound, Str("alaw and ulaw not implemented here")); } if (csound->ISSTRCOD(*p->ifilcod)) strncpy(soundiname, get_arg_string(csound, *p->ifilcod), 1023); else csound->strarg2name(csound, soundiname, p->ifilcod, "readk.", 0); if (p->fdch.fd != NULL) fdclose(csound, &(p->fdch)); p->fdch.fd = csound->FileOpen2(csound, &(p->f), CSFILE_STD, soundiname, "rb", "SFDIR;SSDIR", dumpf_format_table[p->format], 0); if (UNLIKELY(p->fdch.fd == NULL)) return csound->InitError(csound, Str("Cannot open %s"), soundiname); fdrecord(csound, &p->fdch); if ((p->timcount = (int32)(*p->iprd * CS_EKR)) <= 0) p->timcount = 1; p->countdown = 0; p->k[0] = p->k[1] = p->k[2] = p->k[3] = FL(0.0); return OK; } int krd3set_S(CSOUND *csound, KREAD3 *p) { /* open in curdir or pathname */ char soundiname[1024]; if (UNLIKELY((p->format = (int)*p->iformat) < 1 || p->format > 8)) { return csound->InitError(csound, Str("unknown format request")); } if (UNLIKELY(p->format == 2 || p->format == 3)) { return csound->InitError(csound, Str("alaw and ulaw not implemented here")); } strncpy(soundiname, ((STRINGDAT *)p->ifilcod)->data, 1023); if (p->fdch.fd != NULL) fdclose(csound, &(p->fdch)); p->fdch.fd = csound->FileOpen2(csound, &(p->f), CSFILE_STD, soundiname, "rb", "SFDIR;SSDIR", dumpf_format_table[p->format], 0); if (UNLIKELY(p->fdch.fd == NULL)) return csound->InitError(csound, Str("Cannot open %s"), soundiname); fdrecord(csound, &p->fdch); if ((p->timcount = (int32)(*p->iprd * CS_EKR)) <= 0) p->timcount = 1; p->countdown = 0; p->k[0] = p->k[1] = p->k[2] = p->k[3] = FL(0.0); return OK; } int krd3set_p(CSOUND *csound, KREAD3 *p) { /* open in curdir or pathname */ char soundiname[1024]; if (UNLIKELY((p->format = (int)*p->iformat) < 1 || p->format > 8)) { return csound->InitError(csound, Str("unknown format request")); } if (UNLIKELY(p->format == 2 || p->format == 3)) { return csound->InitError(csound, Str("alaw and ulaw not implemented here")); } if (csound->ISSTRCOD(*p->ifilcod)) strncpy(soundiname, get_arg_string(csound, *p->ifilcod), 1023); else csound->strarg2name(csound, soundiname, p->ifilcod, "readk.", 0); if (p->fdch.fd != NULL) fdclose(csound, &(p->fdch)); p->fdch.fd = csound->FileOpen2(csound, &(p->f), CSFILE_STD, soundiname, "rb", "SFDIR;SSDIR", dumpf_format_table[p->format], 0); if (UNLIKELY(p->fdch.fd == NULL)) return csound->InitError(csound, Str("Cannot open %s"), soundiname); fdrecord(csound, &p->fdch); if ((p->timcount = (int32)(*p->iprd * CS_EKR)) <= 0) p->timcount = 1; p->countdown = 0; p->k[0] = p->k[1] = p->k[2] = p->k[3] = FL(0.0); return OK; } int krd4set_S(CSOUND *csound, KREAD4 *p) { /* open in curdir or pathname */ char soundiname[1024]; if (UNLIKELY((p->format = (int)*p->iformat) < 1 || p->format > 8)) { return csound->InitError(csound, Str("unknown format request")); } if (UNLIKELY(p->format == 2 || p->format == 3)) { return csound->InitError(csound, Str("alaw and ulaw not implemented here")); } strncpy(soundiname, ((STRINGDAT *)p->ifilcod)->data, 1023); if (p->fdch.fd != NULL) fdclose(csound, &(p->fdch)); p->fdch.fd = csound->FileOpen2(csound, &(p->f), CSFILE_STD, soundiname, "rb", "SFDIR;SSDIR", dumpf_format_table[p->format], 0); if (UNLIKELY(p->fdch.fd == NULL)) return csound->InitError(csound, Str("Cannot open %s"), soundiname); fdrecord(csound, &p->fdch); if ((p->timcount = (int32)(*p->iprd * CS_EKR)) <= 0) p->timcount = 1; p->countdown = 0; p->k[0] = p->k[1] = p->k[2] = p->k[3] = FL(0.0); return OK; } int krd4set_p(CSOUND *csound, KREAD4 *p) { /* open in curdir or pathname */ char soundiname[1024]; if (UNLIKELY((p->format = (int)*p->iformat) < 1 || p->format > 8)) { return csound->InitError(csound, Str("unknown format request")); } if (UNLIKELY(p->format == 2 || p->format == 3)) { return csound->InitError(csound, Str("alaw and ulaw not implemented here")); } if (csound->ISSTRCOD(*p->ifilcod)) strncpy(soundiname, get_arg_string(csound, *p->ifilcod), 1023); else csound->strarg2name(csound, soundiname, p->ifilcod, "readk.", 0); if (p->fdch.fd != NULL) fdclose(csound, &(p->fdch)); p->fdch.fd = csound->FileOpen2(csound, &(p->f), CSFILE_STD, soundiname, "rb", "SFDIR;SSDIR", dumpf_format_table[p->format], 0); if (UNLIKELY(p->fdch.fd == NULL)) return csound->InitError(csound, Str("Cannot open %s"), soundiname); fdrecord(csound, &p->fdch); if ((p->timcount = (int32)(*p->iprd * CS_EKR)) <= 0) p->timcount = 1; p->countdown = 0; p->k[0] = p->k[1] = p->k[2] = p->k[3] = FL(0.0); return OK; } static void nkread(CSOUND *csound, MYFLT *kp, FILE *ifd, int format, int nk) { int len; char inbuf[256]; switch(format) { /* place formatted kvals into outbuf */ case 1: { int8_t *bp = (int8_t*)inbuf; len = nk; len = fread(inbuf, 1, len, ifd); /* now read the buffer */ while (nk--) *kp++ = (MYFLT)*bp++; break; } case 4: { int16_t *bp = (int16_t*)inbuf; len = nk * 2; len = fread(inbuf, 1, len, ifd); /* now read the buffer */ while (nk--) *kp++ = (MYFLT)*bp++; break; } case 5: { int32_t *bp = (int32_t*)inbuf; len = nk * 4; len = fread(inbuf, 1, len, ifd); /* now read the buffer */ while (nk--) *kp++ = (MYFLT)*bp++; break; } case 6: { float *bp = (float*)inbuf; len = nk * sizeof(float); len = fread(inbuf, 1, len, ifd); /* now read the buffer */ while (nk--) *kp++ = (MYFLT)*bp++; break; } case 7: while (nk--) { char *bp = inbuf; do { /* Skip whitespace */ *bp = (char)getc(ifd); } while (isspace(*bp)); do { /* Absorb digits */ *(++bp) = (char)getc(ifd); } while (isdigit(*bp) || *bp=='-' || *bp=='+' || *bp=='.' || *bp=='e' ||*bp=='E'); ungetc(*bp, ifd); //fseek(ifd, -1L, SEEK_CUR); *bp = '\0'; #ifndef USE_DOUBLE CS_SSCANF(inbuf,"%f", kp); #else CS_SSCANF(inbuf,"%lf", kp); #endif kp++; } break; case 8: while (nk--) { char *bp = inbuf; do { /* Skip whitespace */ *bp = (char)getc(ifd); } while (isspace(*bp)); do { /* Absorb digits and such*/ *(++bp) = (char)getc(ifd); } while (!isspace(*bp)); (void)ungetc(*bp, ifd); //fseek(ifd, -1L, SEEK_CUR); *bp = '\0'; #ifndef USE_DOUBLE CS_SSCANF(inbuf,"%f", kp); #else CS_SSCANF(inbuf,"%lf", kp); #endif kp++; } break; default: csound->Warning(csound,Str("unknown kdump format")); } } int kread(CSOUND *csound, KREAD *p) { MYFLT kval[4]; if (--p->countdown <= 0) { p->countdown = p->timcount; nkread(csound, kval, p->f, p->format, 1); *p->k1 = p->k[0] = kval[0]; } else *p->k1 = p->k[0]; return OK; } int kread2(CSOUND *csound, KREAD2 *p) { MYFLT kval[4]; if (--p->countdown <= 0) { p->countdown = p->timcount; nkread(csound, kval, p->f, p->format, 2); *p->k1 = p->k[0] = kval[0]; *p->k2 = p->k[1] = kval[1]; } else { *p->k1 = p->k[0]; *p->k2 = p->k[1]; } return OK; } int kread3(CSOUND *csound, KREAD3 *p) { MYFLT kval[4]; if (--p->countdown <= 0) { p->countdown = p->timcount; nkread(csound, kval, p->f, p->format, 3); *p->k1 = p->k[0] = kval[0]; *p->k2 = p->k[1] = kval[1]; *p->k3 = p->k[2] = kval[2]; } else { *p->k1 = p->k[0]; *p->k2 = p->k[1]; *p->k3 = p->k[2]; } return OK; } int kread4(CSOUND *csound, KREAD4 *p) { MYFLT kval[4]; if (--p->countdown <= 0) { p->countdown = p->timcount; nkread(csound, kval, p->f, p->format, 4); *p->k1 = p->k[0] = kval[0]; *p->k2 = p->k[1] = kval[1]; *p->k3 = p->k[2] = kval[2]; *p->k4 = p->k[3] = kval[3]; } else { *p->k1 = p->k[0]; *p->k2 = p->k[1]; *p->k3 = p->k[2]; *p->k4 = p->k[3]; } return OK; } #define INITSIZE 1024 int krdsset_S(CSOUND *csound, KREADS *p) { /* open in curdir or pathname */ char soundiname[1024]; strncpy(soundiname, ((STRINGDAT *)p->ifilcod)->data, 1023); if (p->fdch.fd != NULL) fdclose(csound, &(p->fdch)); p->fdch.fd = csound->FileOpen2(csound, &(p->f), CSFILE_STD, soundiname, "rb", "SFDIR;SSDIR", 0, 0); if (UNLIKELY(p->fdch.fd == NULL)) return csound->InitError(csound, Str("Cannot open %s"), soundiname); fdrecord(csound, &p->fdch); if ((p->timcount = (int32)(*p->iprd * CS_EKR)) <= 0) p->timcount = 1; p->countdown = 0; p->lasts = (char*)csound->Calloc(csound, INITSIZE); p->lasts[0] = '\0'; if (p->str->data == NULL) { p->str->data = csound->Calloc(csound, INITSIZE); p->str->size = INITSIZE; } return OK; } int krdsset_p(CSOUND *csound, KREADS *p) { /* open in curdir or pathname */ char soundiname[1024]; if (csound->ISSTRCOD(*p->ifilcod)) strncpy(soundiname, get_arg_string(csound, *p->ifilcod), 1023); else csound->strarg2name(csound, soundiname, p->ifilcod, "readk.", 0); if (p->fdch.fd != NULL) fdclose(csound, &(p->fdch)); p->fdch.fd = csound->FileOpen2(csound, &(p->f), CSFILE_STD, soundiname, "rb", "SFDIR;SSDIR", 0, 0); if (UNLIKELY(p->fdch.fd == NULL)) return csound->InitError(csound, Str("Cannot open %s"), soundiname); fdrecord(csound, &p->fdch); if ((p->timcount = (int32)(*p->iprd * CS_EKR)) <= 0) p->timcount = 1; p->countdown = 0; p->lasts = (char*)csound->Malloc(csound, INITSIZE); p->lasts[0] = '\0'; if (p->str->data == NULL) { p->str->data = csound->Calloc(csound, INITSIZE); p->str->size = INITSIZE; } return OK; } int kreads(CSOUND *csound, KREADS *p) { if (--p->countdown <= 0) { p->countdown = p->timcount; if (UNLIKELY(fgets(p->lasts, INITSIZE-1, p->f)==NULL)) { csound->PerfError(csound, p->h.insdshead, Str("Read failure in readks")); } } strncpy((char*) p->str->data, p->lasts, INITSIZE); return OK; } csound-6.10.0/OOps/fftlib.c000066400000000000000000002666151321653344700154130ustar00rootroot00000000000000/* fftlib.c: FFT library based on public domain code by John Green original version is available at http://hyperarchive.lcs.mit.edu/ /HyperArchive/Archive/dev/src/ffts-for-risc-2-c.hqx ported to Csound by Istvan Varga, 2005 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include "csoundCore.h" #include "csound.h" #include "fftlib.h" #include "pffft.h" #define POW2(m) ((uint32) 1 << (m)) /* integer power of 2 for m<32 */ /* fft's with M bigger than this bust primary cache */ #define MCACHE (11 - (sizeof(MYFLT) / 8)) /* some math constants to 40 decimal places */ #define MYPI 3.141592653589793238462643383279502884197 /* pi */ #define MYROOT2 1.414213562373095048801688724209698078569 /* sqrt(2) */ #define MYCOSPID8 0.9238795325112867561281831893967882868224 /* cos(pi/8) */ #define MYSINPID8 0.3826834323650897717284599840303988667613 /* sin(pi/8) */ /***************************************************** * routines to initialize tables used by fft routines * *****************************************************/ static void fftCosInit(int M, MYFLT *Utbl) { /* Compute Utbl, the cosine table for ffts */ /* of size (pow(2,M)/4 +1) */ /* INPUTS */ /* M = log2 of fft size */ /* OUTPUTS */ /* *Utbl = cosine table */ unsigned int fftN = POW2(M); unsigned int i1; Utbl[0] = FL(1.0); for (i1 = 1; i1 < fftN/4; i1++) Utbl[i1] = COS((FL(2.0) * PI_F * (MYFLT)i1) / (MYFLT)fftN); Utbl[fftN/4] = FL(0.0); } static void fftBRInit(int M, int16 *BRLow) { /* Compute BRLow, the bit reversed table for ffts */ /* of size pow(2,M/2 -1) */ /* INPUTS */ /* M = log2 of fft size */ /* OUTPUTS */ /* *BRLow = bit reversed counter table */ int Mroot_1 = M / 2 - 1; int Nroot_1 = POW2(Mroot_1); int i1; int bitsum; int bitmask; int bit; for (i1 = 0; i1 < Nroot_1; i1++) { bitsum = 0; bitmask = 1; for (bit = 1; bit <= Mroot_1; bitmask <<= 1, bit++) if (i1 & bitmask) bitsum = bitsum + (Nroot_1 >> bit); BRLow[i1] = bitsum; } } /***************** * parts of ffts1 * *****************/ static void bitrevR2(MYFLT *ioptr, int M, int16 *BRLow) { /*** bit reverse and first radix 2 stage of forward or inverse fft ***/ MYFLT f0r; MYFLT f0i; MYFLT f1r; MYFLT f1i; MYFLT f2r; MYFLT f2i; MYFLT f3r; MYFLT f3i; MYFLT f4r; MYFLT f4i; MYFLT f5r; MYFLT f5i; MYFLT f6r; MYFLT f6i; MYFLT f7r; MYFLT f7i; MYFLT t0r; MYFLT t0i; MYFLT t1r; MYFLT t1i; MYFLT *p0r; MYFLT *p1r; MYFLT *IOP; MYFLT *iolimit; int Colstart; int iCol; unsigned int posA; unsigned int posAi; unsigned int posB; unsigned int posBi; const unsigned int Nrems2 = POW2((M + 3) / 2); const unsigned int Nroot_1_ColInc = POW2(M) - Nrems2; const unsigned int Nroot_1 = POW2(M / 2 - 1) - 1; const unsigned int ColstartShift = (M + 1) / 2 + 1; posA = POW2(M); /* 1/2 of POW2(M) complexes */ posAi = posA + 1; posB = posA + 2; posBi = posB + 1; iolimit = ioptr + Nrems2; for (; ioptr < iolimit; ioptr += POW2(M / 2 + 1)) { for (Colstart = Nroot_1; Colstart >= 0; Colstart--) { iCol = Nroot_1; p0r = ioptr + Nroot_1_ColInc + BRLow[Colstart] * 4; IOP = ioptr + (Colstart << ColstartShift); p1r = IOP + BRLow[iCol] * 4; f0r = *(p0r); f0i = *(p0r + 1); f1r = *(p0r + posA); f1i = *(p0r + posAi); for (; iCol > Colstart;) { f2r = *(p0r + 2); f2i = *(p0r + (2 + 1)); f3r = *(p0r + posB); f3i = *(p0r + posBi); f4r = *(p1r); f4i = *(p1r + 1); f5r = *(p1r + posA); f5i = *(p1r + posAi); f6r = *(p1r + 2); f6i = *(p1r + (2 + 1)); f7r = *(p1r + posB); f7i = *(p1r + posBi); t0r = f0r + f1r; t0i = f0i + f1i; f1r = f0r - f1r; f1i = f0i - f1i; t1r = f2r + f3r; t1i = f2i + f3i; f3r = f2r - f3r; f3i = f2i - f3i; f0r = f4r + f5r; f0i = f4i + f5i; f5r = f4r - f5r; f5i = f4i - f5i; f2r = f6r + f7r; f2i = f6i + f7i; f7r = f6r - f7r; f7i = f6i - f7i; *(p1r) = t0r; *(p1r + 1) = t0i; *(p1r + 2) = f1r; *(p1r + (2 + 1)) = f1i; *(p1r + posA) = t1r; *(p1r + posAi) = t1i; *(p1r + posB) = f3r; *(p1r + posBi) = f3i; *(p0r) = f0r; *(p0r + 1) = f0i; *(p0r + 2) = f5r; *(p0r + (2 + 1)) = f5i; *(p0r + posA) = f2r; *(p0r + posAi) = f2i; *(p0r + posB) = f7r; *(p0r + posBi) = f7i; p0r -= Nrems2; f0r = *(p0r); f0i = *(p0r + 1); f1r = *(p0r + posA); f1i = *(p0r + posAi); iCol -= 1; p1r = IOP + BRLow[iCol] * 4; } f2r = *(p0r + 2); f2i = *(p0r + (2 + 1)); f3r = *(p0r + posB); f3i = *(p0r + posBi); t0r = f0r + f1r; t0i = f0i + f1i; f1r = f0r - f1r; f1i = f0i - f1i; t1r = f2r + f3r; t1i = f2i + f3i; f3r = f2r - f3r; f3i = f2i - f3i; *(p0r) = t0r; *(p0r + 1) = t0i; *(p0r + 2) = f1r; *(p0r + (2 + 1)) = f1i; *(p0r + posA) = t1r; *(p0r + posAi) = t1i; *(p0r + posB) = f3r; *(p0r + posBi) = f3i; } } } static void fft2pt(MYFLT *ioptr) { /*** RADIX 2 fft ***/ MYFLT f0r, f0i, f1r, f1i; MYFLT t0r, t0i; /* bit reversed load */ f0r = ioptr[0]; f0i = ioptr[1]; f1r = ioptr[2]; f1i = ioptr[3]; /* Butterflys */ /* f0 - - t0 f1 - 1 - f1 */ t0r = f0r + f1r; t0i = f0i + f1i; f1r = f0r - f1r; f1i = f0i - f1i; /* store result */ ioptr[0] = t0r; ioptr[1] = t0i; ioptr[2] = f1r; ioptr[3] = f1i; } static void fft4pt(MYFLT *ioptr) { /*** RADIX 4 fft ***/ MYFLT f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; MYFLT t0r, t0i, t1r, t1i; /* bit reversed load */ f0r = ioptr[0]; f0i = ioptr[1]; f1r = ioptr[4]; f1i = ioptr[5]; f2r = ioptr[2]; f2i = ioptr[3]; f3r = ioptr[6]; f3i = ioptr[7]; /* Butterflys */ /* f0 - - t0 - - f0 f1 - 1 - f1 - - f1 f2 - - f2 - 1 - f2 f3 - 1 - t1 - -i - f3 */ t0r = f0r + f1r; t0i = f0i + f1i; f1r = f0r - f1r; f1i = f0i - f1i; t1r = f2r - f3r; t1i = f2i - f3i; f2r = f2r + f3r; f2i = f2i + f3i; f0r = t0r + f2r; f0i = t0i + f2i; f2r = t0r - f2r; f2i = t0i - f2i; f3r = f1r - t1i; f3i = f1i + t1r; f1r = f1r + t1i; f1i = f1i - t1r; /* store result */ ioptr[0] = f0r; ioptr[1] = f0i; ioptr[2] = f1r; ioptr[3] = f1i; ioptr[4] = f2r; ioptr[5] = f2i; ioptr[6] = f3r; ioptr[7] = f3i; } static void fft8pt(MYFLT *ioptr) { /*** RADIX 8 fft ***/ MYFLT w0r = (MYFLT)(1.0 / MYROOT2); /* cos(pi/4) */ MYFLT f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; MYFLT f4r, f4i, f5r, f5i, f6r, f6i, f7r, f7i; MYFLT t0r, t0i, t1r, t1i; const MYFLT Two = FL(2.0); /* bit reversed load */ f0r = ioptr[0]; f0i = ioptr[1]; f1r = ioptr[8]; f1i = ioptr[9]; f2r = ioptr[4]; f2i = ioptr[5]; f3r = ioptr[12]; f3i = ioptr[13]; f4r = ioptr[2]; f4i = ioptr[3]; f5r = ioptr[10]; f5i = ioptr[11]; f6r = ioptr[6]; f6i = ioptr[7]; f7r = ioptr[14]; f7i = ioptr[15]; /* Butterflys */ /* f0 - - t0 - - f0 - - f0 f1 - 1 - f1 - - f1 - - f1 f2 - - f2 - 1 - f2 - - f2 f3 - 1 - t1 - -i - f3 - - f3 f4 - - t0 - - f4 - 1 - t0 f5 - 1 - f5 - - f5 - w3 - f4 f6 - - f6 - 1 - f6 - -i - t1 f7 - 1 - t1 - -i - f7 - iw3- f6 */ t0r = f0r + f1r; t0i = f0i + f1i; f1r = f0r - f1r; f1i = f0i - f1i; t1r = f2r - f3r; t1i = f2i - f3i; f2r = f2r + f3r; f2i = f2i + f3i; f0r = t0r + f2r; f0i = t0i + f2i; f2r = t0r - f2r; f2i = t0i - f2i; f3r = f1r - t1i; f3i = f1i + t1r; f1r = f1r + t1i; f1i = f1i - t1r; t0r = f4r + f5r; t0i = f4i + f5i; f5r = f4r - f5r; f5i = f4i - f5i; t1r = f6r - f7r; t1i = f6i - f7i; f6r = f6r + f7r; f6i = f6i + f7i; f4r = t0r + f6r; f4i = t0i + f6i; f6r = t0r - f6r; f6i = t0i - f6i; f7r = f5r - t1i; f7i = f5i + t1r; f5r = f5r + t1i; f5i = f5i - t1r; t0r = f0r - f4r; t0i = f0i - f4i; f0r = f0r + f4r; f0i = f0i + f4i; t1r = f2r - f6i; t1i = f2i + f6r; f2r = f2r + f6i; f2i = f2i - f6r; f4r = f1r - f5r * w0r - f5i * w0r; f4i = f1i + f5r * w0r - f5i * w0r; f1r = f1r * Two - f4r; f1i = f1i * Two - f4i; f6r = f3r + f7r * w0r - f7i * w0r; f6i = f3i + f7r * w0r + f7i * w0r; f3r = f3r * Two - f6r; f3i = f3i * Two - f6i; /* store result */ ioptr[0] = f0r; ioptr[1] = f0i; ioptr[2] = f1r; ioptr[3] = f1i; ioptr[4] = f2r; ioptr[5] = f2i; ioptr[6] = f3r; ioptr[7] = f3i; ioptr[8] = t0r; ioptr[9] = t0i; ioptr[10] = f4r; ioptr[11] = f4i; ioptr[12] = t1r; ioptr[13] = t1i; ioptr[14] = f6r; ioptr[15] = f6i; } static void bfR2(MYFLT *ioptr, int M, int NDiffU) { /*** 2nd radix 2 stage ***/ unsigned int pos; unsigned int posi; unsigned int pinc; unsigned int pnext; unsigned int NSameU; unsigned int SameUCnt; MYFLT *pstrt; MYFLT *p0r, *p1r, *p2r, *p3r; MYFLT f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; MYFLT f4r, f4i, f5r, f5i, f6r, f6i, f7r, f7i; pinc = NDiffU * 2; /* 2 floats per complex */ pnext = pinc * 4; pos = 2; posi = pos + 1; NSameU = POW2(M) / 4 / NDiffU; /* 4 Us at a time */ pstrt = ioptr; p0r = pstrt; p1r = pstrt + pinc; p2r = p1r + pinc; p3r = p2r + pinc; /* Butterflys */ /* f0 - - f4 f1 - 1 - f5 f2 - - f6 f3 - 1 - f7 */ /* Butterflys */ /* f0 - - f4 f1 - 1 - f5 f2 - - f6 f3 - 1 - f7 */ for (SameUCnt = NSameU; SameUCnt > 0; SameUCnt--) { f0r = *p0r; f1r = *p1r; f0i = *(p0r + 1); f1i = *(p1r + 1); f2r = *p2r; f3r = *p3r; f2i = *(p2r + 1); f3i = *(p3r + 1); f4r = f0r + f1r; f4i = f0i + f1i; f5r = f0r - f1r; f5i = f0i - f1i; f6r = f2r + f3r; f6i = f2i + f3i; f7r = f2r - f3r; f7i = f2i - f3i; *p0r = f4r; *(p0r + 1) = f4i; *p1r = f5r; *(p1r + 1) = f5i; *p2r = f6r; *(p2r + 1) = f6i; *p3r = f7r; *(p3r + 1) = f7i; f0r = *(p0r + pos); f1i = *(p1r + posi); f0i = *(p0r + posi); f1r = *(p1r + pos); f2r = *(p2r + pos); f3i = *(p3r + posi); f2i = *(p2r + posi); f3r = *(p3r + pos); f4r = f0r + f1i; f4i = f0i - f1r; f5r = f0r - f1i; f5i = f0i + f1r; f6r = f2r + f3i; f6i = f2i - f3r; f7r = f2r - f3i; f7i = f2i + f3r; *(p0r + pos) = f4r; *(p0r + posi) = f4i; *(p1r + pos) = f5r; *(p1r + posi) = f5i; *(p2r + pos) = f6r; *(p2r + posi) = f6i; *(p3r + pos) = f7r; *(p3r + posi) = f7i; p0r += pnext; p1r += pnext; p2r += pnext; p3r += pnext; } } static void bfR4(MYFLT *ioptr, int M, int NDiffU) { /*** 1 radix 4 stage ***/ unsigned int pos; unsigned int posi; unsigned int pinc; unsigned int pnext; unsigned int pnexti; unsigned int NSameU; unsigned int SameUCnt; MYFLT *pstrt; MYFLT *p0r, *p1r, *p2r, *p3r; MYFLT w1r = FL(1.0) / FL(MYROOT2); /* cos(pi/4) */ MYFLT f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; MYFLT f4r, f4i, f5r, f5i, f6r, f6i, f7r, f7i; MYFLT t1r, t1i; const MYFLT Two = FL(2.0); pinc = NDiffU * 2; /* 2 floats per complex */ pnext = pinc * 4; pnexti = pnext + 1; pos = 2; posi = pos + 1; NSameU = POW2(M) / 4 / NDiffU; /* 4 pts per butterfly */ pstrt = ioptr; p0r = pstrt; p1r = pstrt + pinc; p2r = p1r + pinc; p3r = p2r + pinc; /* Butterflys */ /* f0 - - f0 - - f4 f1 - 1 - f5 - - f5 f2 - - f6 - 1 - f6 f3 - 1 - f3 - -i - f7 */ /* Butterflys */ /* f0 - - f4 - - f4 f1 - -i - t1 - - f5 f2 - - f2 - w1 - f6 f3 - -i - f7 - iw1- f7 */ f0r = *p0r; f1r = *p1r; f2r = *p2r; f3r = *p3r; f0i = *(p0r + 1); f1i = *(p1r + 1); f2i = *(p2r + 1); f3i = *(p3r + 1); f5r = f0r - f1r; f5i = f0i - f1i; f0r = f0r + f1r; f0i = f0i + f1i; f6r = f2r + f3r; f6i = f2i + f3i; f3r = f2r - f3r; f3i = f2i - f3i; for (SameUCnt = NSameU - 1; SameUCnt > 0; SameUCnt--) { f7r = f5r - f3i; f7i = f5i + f3r; f5r = f5r + f3i; f5i = f5i - f3r; f4r = f0r + f6r; f4i = f0i + f6i; f6r = f0r - f6r; f6i = f0i - f6i; f2r = *(p2r + pos); f2i = *(p2r + posi); f1r = *(p1r + pos); f1i = *(p1r + posi); f3i = *(p3r + posi); f0r = *(p0r + pos); f3r = *(p3r + pos); f0i = *(p0r + posi); *p3r = f7r; *p0r = f4r; *(p3r + 1) = f7i; *(p0r + 1) = f4i; *p1r = f5r; *p2r = f6r; *(p1r + 1) = f5i; *(p2r + 1) = f6i; f7r = f2r - f3i; f7i = f2i + f3r; f2r = f2r + f3i; f2i = f2i - f3r; f4r = f0r + f1i; f4i = f0i - f1r; t1r = f0r - f1i; t1i = f0i + f1r; f5r = t1r - f7r * w1r + f7i * w1r; f5i = t1i - f7r * w1r - f7i * w1r; f7r = t1r * Two - f5r; f7i = t1i * Two - f5i; f6r = f4r - f2r * w1r - f2i * w1r; f6i = f4i + f2r * w1r - f2i * w1r; f4r = f4r * Two - f6r; f4i = f4i * Two - f6i; f3r = *(p3r + pnext); f0r = *(p0r + pnext); f3i = *(p3r + pnexti); f0i = *(p0r + pnexti); f2r = *(p2r + pnext); f2i = *(p2r + pnexti); f1r = *(p1r + pnext); f1i = *(p1r + pnexti); *(p2r + pos) = f6r; *(p1r + pos) = f5r; *(p2r + posi) = f6i; *(p1r + posi) = f5i; *(p3r + pos) = f7r; *(p0r + pos) = f4r; *(p3r + posi) = f7i; *(p0r + posi) = f4i; f6r = f2r + f3r; f6i = f2i + f3i; f3r = f2r - f3r; f3i = f2i - f3i; f5r = f0r - f1r; f5i = f0i - f1i; f0r = f0r + f1r; f0i = f0i + f1i; p3r += pnext; p0r += pnext; p1r += pnext; p2r += pnext; } f7r = f5r - f3i; f7i = f5i + f3r; f5r = f5r + f3i; f5i = f5i - f3r; f4r = f0r + f6r; f4i = f0i + f6i; f6r = f0r - f6r; f6i = f0i - f6i; f2r = *(p2r + pos); f2i = *(p2r + posi); f1r = *(p1r + pos); f1i = *(p1r + posi); f3i = *(p3r + posi); f0r = *(p0r + pos); f3r = *(p3r + pos); f0i = *(p0r + posi); *p3r = f7r; *p0r = f4r; *(p3r + 1) = f7i; *(p0r + 1) = f4i; *p1r = f5r; *p2r = f6r; *(p1r + 1) = f5i; *(p2r + 1) = f6i; f7r = f2r - f3i; f7i = f2i + f3r; f2r = f2r + f3i; f2i = f2i - f3r; f4r = f0r + f1i; f4i = f0i - f1r; t1r = f0r - f1i; t1i = f0i + f1r; f5r = t1r - f7r * w1r + f7i * w1r; f5i = t1i - f7r * w1r - f7i * w1r; f7r = t1r * Two - f5r; f7i = t1i * Two - f5i; f6r = f4r - f2r * w1r - f2i * w1r; f6i = f4i + f2r * w1r - f2i * w1r; f4r = f4r * Two - f6r; f4i = f4i * Two - f6i; *(p2r + pos) = f6r; *(p1r + pos) = f5r; *(p2r + posi) = f6i; *(p1r + posi) = f5i; *(p3r + pos) = f7r; *(p0r + pos) = f4r; *(p3r + posi) = f7i; *(p0r + posi) = f4i; } static void bfstages(MYFLT *ioptr, int M, MYFLT *Utbl, int Ustride, int NDiffU, int StageCnt) { /*** RADIX 8 Stages ***/ unsigned int pos; unsigned int posi; unsigned int pinc; unsigned int pnext; unsigned int NSameU; int Uinc; int Uinc2; int Uinc4; unsigned int DiffUCnt; unsigned int SameUCnt; unsigned int U2toU3; MYFLT *pstrt; MYFLT *p0r, *p1r, *p2r, *p3r; MYFLT *u0r, *u0i, *u1r, *u1i, *u2r, *u2i; MYFLT w0r, w0i, w1r, w1i, w2r, w2i, w3r, w3i; MYFLT f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; MYFLT f4r, f4i, f5r, f5i, f6r, f6i, f7r, f7i; MYFLT t0r, t0i, t1r, t1i; const MYFLT Two = FL(2.0); pinc = NDiffU * 2; /* 2 floats per complex */ pnext = pinc * 8; pos = pinc * 4; posi = pos + 1; NSameU = POW2(M) / 8 / NDiffU; /* 8 pts per butterfly */ Uinc = (int) NSameU * Ustride; Uinc2 = Uinc * 2; Uinc4 = Uinc * 4; U2toU3 = (POW2(M) / 8) * Ustride; for (; StageCnt > 0; StageCnt--) { u0r = &Utbl[0]; u0i = &Utbl[POW2(M - 2) * Ustride]; u1r = u0r; u1i = u0i; u2r = u0r; u2i = u0i; w0r = *u0r; w0i = *u0i; w1r = *u1r; w1i = *u1i; w2r = *u2r; w2i = *u2i; w3r = *(u2r + U2toU3); w3i = *(u2i - U2toU3); pstrt = ioptr; p0r = pstrt; p1r = pstrt + pinc; p2r = p1r + pinc; p3r = p2r + pinc; /* Butterflys */ /* f0 - - t0 - - f0 - - f0 f1 - w0- f1 - - f1 - - f1 f2 - - f2 - w1- f2 - - f4 f3 - w0- t1 - iw1- f3 - - f5 f4 - - t0 - - f4 - w2- t0 f5 - w0- f5 - - f5 - w3- t1 f6 - - f6 - w1- f6 - iw2- f6 f7 - w0- t1 - iw1- f7 - iw3- f7 */ for (DiffUCnt = NDiffU; DiffUCnt > 0; DiffUCnt--) { f0r = *p0r; f0i = *(p0r + 1); f1r = *p1r; f1i = *(p1r + 1); for (SameUCnt = NSameU - 1; SameUCnt > 0; SameUCnt--) { f2r = *p2r; f2i = *(p2r + 1); f3r = *p3r; f3i = *(p3r + 1); t0r = f0r + f1r * w0r + f1i * w0i; t0i = f0i - f1r * w0i + f1i * w0r; f1r = f0r * Two - t0r; f1i = f0i * Two - t0i; f4r = *(p0r + pos); f4i = *(p0r + posi); f5r = *(p1r + pos); f5i = *(p1r + posi); f6r = *(p2r + pos); f6i = *(p2r + posi); f7r = *(p3r + pos); f7i = *(p3r + posi); t1r = f2r - f3r * w0r - f3i * w0i; t1i = f2i + f3r * w0i - f3i * w0r; f2r = f2r * Two - t1r; f2i = f2i * Two - t1i; f0r = t0r + f2r * w1r + f2i * w1i; f0i = t0i - f2r * w1i + f2i * w1r; f2r = t0r * Two - f0r; f2i = t0i * Two - f0i; f3r = f1r + t1r * w1i - t1i * w1r; f3i = f1i + t1r * w1r + t1i * w1i; f1r = f1r * Two - f3r; f1i = f1i * Two - f3i; t0r = f4r + f5r * w0r + f5i * w0i; t0i = f4i - f5r * w0i + f5i * w0r; f5r = f4r * Two - t0r; f5i = f4i * Two - t0i; t1r = f6r - f7r * w0r - f7i * w0i; t1i = f6i + f7r * w0i - f7i * w0r; f6r = f6r * Two - t1r; f6i = f6i * Two - t1i; f4r = t0r + f6r * w1r + f6i * w1i; f4i = t0i - f6r * w1i + f6i * w1r; f6r = t0r * Two - f4r; f6i = t0i * Two - f4i; f7r = f5r + t1r * w1i - t1i * w1r; f7i = f5i + t1r * w1r + t1i * w1i; f5r = f5r * Two - f7r; f5i = f5i * Two - f7i; t0r = f0r - f4r * w2r - f4i * w2i; t0i = f0i + f4r * w2i - f4i * w2r; f0r = f0r * Two - t0r; f0i = f0i * Two - t0i; t1r = f1r - f5r * w3r - f5i * w3i; t1i = f1i + f5r * w3i - f5i * w3r; f1r = f1r * Two - t1r; f1i = f1i * Two - t1i; *(p0r + pos) = t0r; *(p1r + pos) = t1r; *(p0r + posi) = t0i; *(p1r + posi) = t1i; *p0r = f0r; *p1r = f1r; *(p0r + 1) = f0i; *(p1r + 1) = f1i; p0r += pnext; f0r = *p0r; f0i = *(p0r + 1); p1r += pnext; f1r = *p1r; f1i = *(p1r + 1); f4r = f2r - f6r * w2i + f6i * w2r; f4i = f2i - f6r * w2r - f6i * w2i; f6r = f2r * Two - f4r; f6i = f2i * Two - f4i; f5r = f3r - f7r * w3i + f7i * w3r; f5i = f3i - f7r * w3r - f7i * w3i; f7r = f3r * Two - f5r; f7i = f3i * Two - f5i; *p2r = f4r; *p3r = f5r; *(p2r + 1) = f4i; *(p3r + 1) = f5i; *(p2r + pos) = f6r; *(p3r + pos) = f7r; *(p2r + posi) = f6i; *(p3r + posi) = f7i; p2r += pnext; p3r += pnext; } f2r = *p2r; f2i = *(p2r + 1); f3r = *p3r; f3i = *(p3r + 1); t0r = f0r + f1r * w0r + f1i * w0i; t0i = f0i - f1r * w0i + f1i * w0r; f1r = f0r * Two - t0r; f1i = f0i * Two - t0i; f4r = *(p0r + pos); f4i = *(p0r + posi); f5r = *(p1r + pos); f5i = *(p1r + posi); f6r = *(p2r + pos); f6i = *(p2r + posi); f7r = *(p3r + pos); f7i = *(p3r + posi); t1r = f2r - f3r * w0r - f3i * w0i; t1i = f2i + f3r * w0i - f3i * w0r; f2r = f2r * Two - t1r; f2i = f2i * Two - t1i; f0r = t0r + f2r * w1r + f2i * w1i; f0i = t0i - f2r * w1i + f2i * w1r; f2r = t0r * Two - f0r; f2i = t0i * Two - f0i; f3r = f1r + t1r * w1i - t1i * w1r; f3i = f1i + t1r * w1r + t1i * w1i; f1r = f1r * Two - f3r; f1i = f1i * Two - f3i; if ((int) DiffUCnt == NDiffU / 2) Uinc4 = -Uinc4; u0r += Uinc4; u0i -= Uinc4; u1r += Uinc2; u1i -= Uinc2; u2r += Uinc; u2i -= Uinc; pstrt += 2; t0r = f4r + f5r * w0r + f5i * w0i; t0i = f4i - f5r * w0i + f5i * w0r; f5r = f4r * Two - t0r; f5i = f4i * Two - t0i; t1r = f6r - f7r * w0r - f7i * w0i; t1i = f6i + f7r * w0i - f7i * w0r; f6r = f6r * Two - t1r; f6i = f6i * Two - t1i; f4r = t0r + f6r * w1r + f6i * w1i; f4i = t0i - f6r * w1i + f6i * w1r; f6r = t0r * Two - f4r; f6i = t0i * Two - f4i; f7r = f5r + t1r * w1i - t1i * w1r; f7i = f5i + t1r * w1r + t1i * w1i; f5r = f5r * Two - f7r; f5i = f5i * Two - f7i; w0r = *u0r; w0i = *u0i; w1r = *u1r; w1i = *u1i; if ((int) DiffUCnt <= NDiffU / 2) w0r = -w0r; t0r = f0r - f4r * w2r - f4i * w2i; t0i = f0i + f4r * w2i - f4i * w2r; f0r = f0r * Two - t0r; f0i = f0i * Two - t0i; f4r = f2r - f6r * w2i + f6i * w2r; f4i = f2i - f6r * w2r - f6i * w2i; f6r = f2r * Two - f4r; f6i = f2i * Two - f4i; *(p0r + pos) = t0r; *p2r = f4r; *(p0r + posi) = t0i; *(p2r + 1) = f4i; w2r = *u2r; w2i = *u2i; *p0r = f0r; *(p2r + pos) = f6r; *(p0r + 1) = f0i; *(p2r + posi) = f6i; p0r = pstrt; p2r = pstrt + pinc + pinc; t1r = f1r - f5r * w3r - f5i * w3i; t1i = f1i + f5r * w3i - f5i * w3r; f1r = f1r * Two - t1r; f1i = f1i * Two - t1i; f5r = f3r - f7r * w3i + f7i * w3r; f5i = f3i - f7r * w3r - f7i * w3i; f7r = f3r * Two - f5r; f7i = f3i * Two - f5i; *(p1r + pos) = t1r; *p3r = f5r; *(p1r + posi) = t1i; *(p3r + 1) = f5i; w3r = *(u2r + U2toU3); w3i = *(u2i - U2toU3); *p1r = f1r; *(p3r + pos) = f7r; *(p1r + 1) = f1i; *(p3r + posi) = f7i; p1r = pstrt + pinc; p3r = p2r + pinc; } NSameU /= 8; Uinc /= 8; Uinc2 /= 8; Uinc4 = Uinc * 4; NDiffU *= 8; pinc *= 8; pnext *= 8; pos *= 8; posi = pos + 1; } } static void fftrecurs(MYFLT *ioptr, int M, MYFLT *Utbl, int Ustride, int NDiffU, int StageCnt) { /* recursive bfstages calls to maximize on chip cache efficiency */ int i1; if (M <= (int) MCACHE) /* fits on chip ? */ bfstages(ioptr, M, Utbl, Ustride, NDiffU, StageCnt); /* RADIX 8 Stages */ else { for (i1 = 0; i1 < 8; i1++) { fftrecurs(&ioptr[i1 * POW2(M - 3) * 2], M - 3, Utbl, 8 * Ustride, NDiffU, StageCnt - 1); /* RADIX 8 Stages */ } bfstages(ioptr, M, Utbl, Ustride, POW2(M - 3), 1); /* RADIX 8 Stage */ } } static void ffts1(MYFLT *ioptr, int M, MYFLT *Utbl, int16 *BRLow) { /* Compute in-place complex fft on the rows of the input array */ /* INPUTS */ /* *ioptr = input data array */ /* M = log2 of fft size (ex M=10 for 1024 point fft) */ /* *Utbl = cosine table */ /* *BRLow = bit reversed counter table */ /* OUTPUTS */ /* *ioptr = output data array */ int StageCnt; int NDiffU; switch (M) { case 0: break; case 1: fft2pt(ioptr); /* a 2 pt fft */ break; case 2: fft4pt(ioptr); /* a 4 pt fft */ break; case 3: fft8pt(ioptr); /* an 8 pt fft */ break; default: bitrevR2(ioptr, M, BRLow); /* bit reverse and first radix 2 stage */ StageCnt = (M - 1) / 3; /* number of radix 8 stages */ NDiffU = 2; /* one radix 2 stage already complete */ if ((M - 1 - (StageCnt * 3)) == 1) { bfR2(ioptr, M, NDiffU); /* 1 radix 2 stage */ NDiffU *= 2; } if ((M - 1 - (StageCnt * 3)) == 2) { bfR4(ioptr, M, NDiffU); /* 1 radix 4 stage */ NDiffU *= 4; } if (M <= (int) MCACHE) bfstages(ioptr, M, Utbl, 1, NDiffU, StageCnt); /* RADIX 8 Stages */ else fftrecurs(ioptr, M, Utbl, 1, NDiffU, StageCnt); /* RADIX 8 Stages */ } } /****************** * parts of iffts1 * ******************/ static void scbitrevR2(MYFLT *ioptr, int M, int16 *BRLow, MYFLT scale) { /*** scaled bit reverse and first radix 2 stage forward or inverse fft ***/ MYFLT f0r; MYFLT f0i; MYFLT f1r; MYFLT f1i; MYFLT f2r; MYFLT f2i; MYFLT f3r; MYFLT f3i; MYFLT f4r; MYFLT f4i; MYFLT f5r; MYFLT f5i; MYFLT f6r; MYFLT f6i; MYFLT f7r; MYFLT f7i; MYFLT t0r; MYFLT t0i; MYFLT t1r; MYFLT t1i; MYFLT *p0r; MYFLT *p1r; MYFLT *IOP; MYFLT *iolimit; int Colstart; int iCol; unsigned int posA; unsigned int posAi; unsigned int posB; unsigned int posBi; const unsigned int Nrems2 = POW2((M + 3) / 2); const unsigned int Nroot_1_ColInc = POW2(M) - Nrems2; const unsigned int Nroot_1 = POW2(M / 2 - 1) - 1; const unsigned int ColstartShift = (M + 1) / 2 + 1; posA = POW2(M); /* 1/2 of POW2(M) complexes */ posAi = posA + 1; posB = posA + 2; posBi = posB + 1; iolimit = ioptr + Nrems2; for (; ioptr < iolimit; ioptr += POW2(M / 2 + 1)) { for (Colstart = Nroot_1; Colstart >= 0; Colstart--) { iCol = Nroot_1; p0r = ioptr + Nroot_1_ColInc + BRLow[Colstart] * 4; IOP = ioptr + (Colstart << ColstartShift); p1r = IOP + BRLow[iCol] * 4; f0r = *(p0r); f0i = *(p0r + 1); f1r = *(p0r + posA); f1i = *(p0r + posAi); for (; iCol > Colstart;) { f2r = *(p0r + 2); f2i = *(p0r + (2 + 1)); f3r = *(p0r + posB); f3i = *(p0r + posBi); f4r = *(p1r); f4i = *(p1r + 1); f5r = *(p1r + posA); f5i = *(p1r + posAi); f6r = *(p1r + 2); f6i = *(p1r + (2 + 1)); f7r = *(p1r + posB); f7i = *(p1r + posBi); t0r = f0r + f1r; t0i = f0i + f1i; f1r = f0r - f1r; f1i = f0i - f1i; t1r = f2r + f3r; t1i = f2i + f3i; f3r = f2r - f3r; f3i = f2i - f3i; f0r = f4r + f5r; f0i = f4i + f5i; f5r = f4r - f5r; f5i = f4i - f5i; f2r = f6r + f7r; f2i = f6i + f7i; f7r = f6r - f7r; f7i = f6i - f7i; *(p1r) = scale * t0r; *(p1r + 1) = scale * t0i; *(p1r + 2) = scale * f1r; *(p1r + (2 + 1)) = scale * f1i; *(p1r + posA) = scale * t1r; *(p1r + posAi) = scale * t1i; *(p1r + posB) = scale * f3r; *(p1r + posBi) = scale * f3i; *(p0r) = scale * f0r; *(p0r + 1) = scale * f0i; *(p0r + 2) = scale * f5r; *(p0r + (2 + 1)) = scale * f5i; *(p0r + posA) = scale * f2r; *(p0r + posAi) = scale * f2i; *(p0r + posB) = scale * f7r; *(p0r + posBi) = scale * f7i; p0r -= Nrems2; f0r = *(p0r); f0i = *(p0r + 1); f1r = *(p0r + posA); f1i = *(p0r + posAi); iCol -= 1; p1r = IOP + BRLow[iCol] * 4; } f2r = *(p0r + 2); f2i = *(p0r + (2 + 1)); f3r = *(p0r + posB); f3i = *(p0r + posBi); t0r = f0r + f1r; t0i = f0i + f1i; f1r = f0r - f1r; f1i = f0i - f1i; t1r = f2r + f3r; t1i = f2i + f3i; f3r = f2r - f3r; f3i = f2i - f3i; *(p0r) = scale * t0r; *(p0r + 1) = scale * t0i; *(p0r + 2) = scale * f1r; *(p0r + (2 + 1)) = scale * f1i; *(p0r + posA) = scale * t1r; *(p0r + posAi) = scale * t1i; *(p0r + posB) = scale * f3r; *(p0r + posBi) = scale * f3i; } } } static void ifft2pt(MYFLT *ioptr, MYFLT scale) { /*** RADIX 2 ifft ***/ MYFLT f0r, f0i, f1r, f1i; MYFLT t0r, t0i; /* bit reversed load */ f0r = ioptr[0]; f0i = ioptr[1]; f1r = ioptr[2]; f1i = ioptr[3]; /* Butterflys */ /* f0 - - t0 f1 - 1 - f1 */ t0r = f0r + f1r; t0i = f0i + f1i; f1r = f0r - f1r; f1i = f0i - f1i; /* store result */ ioptr[0] = scale * t0r; ioptr[1] = scale * t0i; ioptr[2] = scale * f1r; ioptr[3] = scale * f1i; } static void ifft4pt(MYFLT *ioptr, MYFLT scale) { /*** RADIX 4 ifft ***/ MYFLT f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; MYFLT t0r, t0i, t1r, t1i; /* bit reversed load */ f0r = ioptr[0]; f0i = ioptr[1]; f1r = ioptr[4]; f1i = ioptr[5]; f2r = ioptr[2]; f2i = ioptr[3]; f3r = ioptr[6]; f3i = ioptr[7]; /* Butterflys */ /* f0 - - t0 - - f0 f1 - 1 - f1 - - f1 f2 - - f2 - 1 - f2 f3 - 1 - t1 - i - f3 */ t0r = f0r + f1r; t0i = f0i + f1i; f1r = f0r - f1r; f1i = f0i - f1i; t1r = f2r - f3r; t1i = f2i - f3i; f2r = f2r + f3r; f2i = f2i + f3i; f0r = t0r + f2r; f0i = t0i + f2i; f2r = t0r - f2r; f2i = t0i - f2i; f3r = f1r + t1i; f3i = f1i - t1r; f1r = f1r - t1i; f1i = f1i + t1r; /* store result */ ioptr[0] = scale * f0r; ioptr[1] = scale * f0i; ioptr[2] = scale * f1r; ioptr[3] = scale * f1i; ioptr[4] = scale * f2r; ioptr[5] = scale * f2i; ioptr[6] = scale * f3r; ioptr[7] = scale * f3i; } static void ifft8pt(MYFLT *ioptr, MYFLT scale) { /*** RADIX 8 ifft ***/ MYFLT w0r = FL(1.0) / FL(MYROOT2); /* cos(pi/4) */ MYFLT f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; MYFLT f4r, f4i, f5r, f5i, f6r, f6i, f7r, f7i; MYFLT t0r, t0i, t1r, t1i; const MYFLT Two = FL(2.0); /* bit reversed load */ f0r = ioptr[0]; f0i = ioptr[1]; f1r = ioptr[8]; f1i = ioptr[9]; f2r = ioptr[4]; f2i = ioptr[5]; f3r = ioptr[12]; f3i = ioptr[13]; f4r = ioptr[2]; f4i = ioptr[3]; f5r = ioptr[10]; f5i = ioptr[11]; f6r = ioptr[6]; f6i = ioptr[7]; f7r = ioptr[14]; f7i = ioptr[15]; /* Butterflys */ /* f0 - - t0 - - f0 - - f0 f1 - 1 - f1 - - f1 - - f1 f2 - - f2 - 1 - f2 - - f2 f3 - 1 - t1 - i - f3 - - f3 f4 - - t0 - - f4 - 1 - t0 f5 - 1 - f5 - - f5 - w3 - f4 f6 - - f6 - 1 - f6 - i - t1 f7 - 1 - t1 - i - f7 - iw3- f6 */ t0r = f0r + f1r; t0i = f0i + f1i; f1r = f0r - f1r; f1i = f0i - f1i; t1r = f2r - f3r; t1i = f2i - f3i; f2r = f2r + f3r; f2i = f2i + f3i; f0r = t0r + f2r; f0i = t0i + f2i; f2r = t0r - f2r; f2i = t0i - f2i; f3r = f1r + t1i; f3i = f1i - t1r; f1r = f1r - t1i; f1i = f1i + t1r; t0r = f4r + f5r; t0i = f4i + f5i; f5r = f4r - f5r; f5i = f4i - f5i; t1r = f6r - f7r; t1i = f6i - f7i; f6r = f6r + f7r; f6i = f6i + f7i; f4r = t0r + f6r; f4i = t0i + f6i; f6r = t0r - f6r; f6i = t0i - f6i; f7r = f5r + t1i; f7i = f5i - t1r; f5r = f5r - t1i; f5i = f5i + t1r; t0r = f0r - f4r; t0i = f0i - f4i; f0r = f0r + f4r; f0i = f0i + f4i; t1r = f2r + f6i; t1i = f2i - f6r; f2r = f2r - f6i; f2i = f2i + f6r; f4r = f1r - f5r * w0r + f5i * w0r; f4i = f1i - f5r * w0r - f5i * w0r; f1r = f1r * Two - f4r; f1i = f1i * Two - f4i; f6r = f3r + f7r * w0r + f7i * w0r; f6i = f3i - f7r * w0r + f7i * w0r; f3r = f3r * Two - f6r; f3i = f3i * Two - f6i; /* store result */ ioptr[0] = scale * f0r; ioptr[1] = scale * f0i; ioptr[2] = scale * f1r; ioptr[3] = scale * f1i; ioptr[4] = scale * f2r; ioptr[5] = scale * f2i; ioptr[6] = scale * f3r; ioptr[7] = scale * f3i; ioptr[8] = scale * t0r; ioptr[9] = scale * t0i; ioptr[10] = scale * f4r; ioptr[11] = scale * f4i; ioptr[12] = scale * t1r; ioptr[13] = scale * t1i; ioptr[14] = scale * f6r; ioptr[15] = scale * f6i; } static void ibfR2(MYFLT *ioptr, int M, int NDiffU) { /*** 2nd radix 2 stage ***/ unsigned int pos; unsigned int posi; unsigned int pinc; unsigned int pnext; unsigned int NSameU; unsigned int SameUCnt; MYFLT *pstrt; MYFLT *p0r, *p1r, *p2r, *p3r; MYFLT f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; MYFLT f4r, f4i, f5r, f5i, f6r, f6i, f7r, f7i; pinc = NDiffU * 2; /* 2 floats per complex */ pnext = pinc * 4; pos = 2; posi = pos + 1; NSameU = POW2(M) / 4 / NDiffU; /* 4 Us at a time */ pstrt = ioptr; p0r = pstrt; p1r = pstrt + pinc; p2r = p1r + pinc; p3r = p2r + pinc; /* Butterflys */ /* f0 - - f4 f1 - 1 - f5 f2 - - f6 f3 - 1 - f7 */ /* Butterflys */ /* f0 - - f4 f1 - 1 - f5 f2 - - f6 f3 - 1 - f7 */ for (SameUCnt = NSameU; SameUCnt > 0; SameUCnt--) { f0r = *p0r; f1r = *p1r; f0i = *(p0r + 1); f1i = *(p1r + 1); f2r = *p2r; f3r = *p3r; f2i = *(p2r + 1); f3i = *(p3r + 1); f4r = f0r + f1r; f4i = f0i + f1i; f5r = f0r - f1r; f5i = f0i - f1i; f6r = f2r + f3r; f6i = f2i + f3i; f7r = f2r - f3r; f7i = f2i - f3i; *p0r = f4r; *(p0r + 1) = f4i; *p1r = f5r; *(p1r + 1) = f5i; *p2r = f6r; *(p2r + 1) = f6i; *p3r = f7r; *(p3r + 1) = f7i; f0r = *(p0r + pos); f1i = *(p1r + posi); f0i = *(p0r + posi); f1r = *(p1r + pos); f2r = *(p2r + pos); f3i = *(p3r + posi); f2i = *(p2r + posi); f3r = *(p3r + pos); f4r = f0r - f1i; f4i = f0i + f1r; f5r = f0r + f1i; f5i = f0i - f1r; f6r = f2r - f3i; f6i = f2i + f3r; f7r = f2r + f3i; f7i = f2i - f3r; *(p0r + pos) = f4r; *(p0r + posi) = f4i; *(p1r + pos) = f5r; *(p1r + posi) = f5i; *(p2r + pos) = f6r; *(p2r + posi) = f6i; *(p3r + pos) = f7r; *(p3r + posi) = f7i; p0r += pnext; p1r += pnext; p2r += pnext; p3r += pnext; } } static void ibfR4(MYFLT *ioptr, int M, int NDiffU) { /*** 1 radix 4 stage ***/ unsigned int pos; unsigned int posi; unsigned int pinc; unsigned int pnext; unsigned int pnexti; unsigned int NSameU; unsigned int SameUCnt; MYFLT *pstrt; MYFLT *p0r, *p1r, *p2r, *p3r; MYFLT w1r = FL(1.0) / FL(MYROOT2); /* cos(pi/4) */ MYFLT f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; MYFLT f4r, f4i, f5r, f5i, f6r, f6i, f7r, f7i; MYFLT t1r, t1i; const MYFLT Two = FL(2.0); pinc = NDiffU * 2; /* 2 floats per complex */ pnext = pinc * 4; pnexti = pnext + 1; pos = 2; posi = pos + 1; NSameU = POW2(M) / 4 / NDiffU; /* 4 pts per butterfly */ pstrt = ioptr; p0r = pstrt; p1r = pstrt + pinc; p2r = p1r + pinc; p3r = p2r + pinc; /* Butterflys */ /* f0 - - f0 - - f4 f1 - 1 - f5 - - f5 f2 - - f6 - 1 - f6 f3 - 1 - f3 - -i - f7 */ /* Butterflys */ /* f0 - - f4 - - f4 f1 - -i - t1 - - f5 f2 - - f2 - w1 - f6 f3 - -i - f7 - iw1- f7 */ f0r = *p0r; f1r = *p1r; f2r = *p2r; f3r = *p3r; f0i = *(p0r + 1); f1i = *(p1r + 1); f2i = *(p2r + 1); f3i = *(p3r + 1); f5r = f0r - f1r; f5i = f0i - f1i; f0r = f0r + f1r; f0i = f0i + f1i; f6r = f2r + f3r; f6i = f2i + f3i; f3r = f2r - f3r; f3i = f2i - f3i; for (SameUCnt = NSameU - 1; SameUCnt > 0; SameUCnt--) { f7r = f5r + f3i; f7i = f5i - f3r; f5r = f5r - f3i; f5i = f5i + f3r; f4r = f0r + f6r; f4i = f0i + f6i; f6r = f0r - f6r; f6i = f0i - f6i; f2r = *(p2r + pos); f2i = *(p2r + posi); f1r = *(p1r + pos); f1i = *(p1r + posi); f3i = *(p3r + posi); f0r = *(p0r + pos); f3r = *(p3r + pos); f0i = *(p0r + posi); *p3r = f7r; *p0r = f4r; *(p3r + 1) = f7i; *(p0r + 1) = f4i; *p1r = f5r; *p2r = f6r; *(p1r + 1) = f5i; *(p2r + 1) = f6i; f7r = f2r + f3i; f7i = f2i - f3r; f2r = f2r - f3i; f2i = f2i + f3r; f4r = f0r - f1i; f4i = f0i + f1r; t1r = f0r + f1i; t1i = f0i - f1r; f5r = t1r - f7r * w1r - f7i * w1r; f5i = t1i + f7r * w1r - f7i * w1r; f7r = t1r * Two - f5r; f7i = t1i * Two - f5i; f6r = f4r - f2r * w1r + f2i * w1r; f6i = f4i - f2r * w1r - f2i * w1r; f4r = f4r * Two - f6r; f4i = f4i * Two - f6i; f3r = *(p3r + pnext); f0r = *(p0r + pnext); f3i = *(p3r + pnexti); f0i = *(p0r + pnexti); f2r = *(p2r + pnext); f2i = *(p2r + pnexti); f1r = *(p1r + pnext); f1i = *(p1r + pnexti); *(p2r + pos) = f6r; *(p1r + pos) = f5r; *(p2r + posi) = f6i; *(p1r + posi) = f5i; *(p3r + pos) = f7r; *(p0r + pos) = f4r; *(p3r + posi) = f7i; *(p0r + posi) = f4i; f6r = f2r + f3r; f6i = f2i + f3i; f3r = f2r - f3r; f3i = f2i - f3i; f5r = f0r - f1r; f5i = f0i - f1i; f0r = f0r + f1r; f0i = f0i + f1i; p3r += pnext; p0r += pnext; p1r += pnext; p2r += pnext; } f7r = f5r + f3i; f7i = f5i - f3r; f5r = f5r - f3i; f5i = f5i + f3r; f4r = f0r + f6r; f4i = f0i + f6i; f6r = f0r - f6r; f6i = f0i - f6i; f2r = *(p2r + pos); f2i = *(p2r + posi); f1r = *(p1r + pos); f1i = *(p1r + posi); f3i = *(p3r + posi); f0r = *(p0r + pos); f3r = *(p3r + pos); f0i = *(p0r + posi); *p3r = f7r; *p0r = f4r; *(p3r + 1) = f7i; *(p0r + 1) = f4i; *p1r = f5r; *p2r = f6r; *(p1r + 1) = f5i; *(p2r + 1) = f6i; f7r = f2r + f3i; f7i = f2i - f3r; f2r = f2r - f3i; f2i = f2i + f3r; f4r = f0r - f1i; f4i = f0i + f1r; t1r = f0r + f1i; t1i = f0i - f1r; f5r = t1r - f7r * w1r - f7i * w1r; f5i = t1i + f7r * w1r - f7i * w1r; f7r = t1r * Two - f5r; f7i = t1i * Two - f5i; f6r = f4r - f2r * w1r + f2i * w1r; f6i = f4i - f2r * w1r - f2i * w1r; f4r = f4r * Two - f6r; f4i = f4i * Two - f6i; *(p2r + pos) = f6r; *(p1r + pos) = f5r; *(p2r + posi) = f6i; *(p1r + posi) = f5i; *(p3r + pos) = f7r; *(p0r + pos) = f4r; *(p3r + posi) = f7i; *(p0r + posi) = f4i; } static void ibfstages(MYFLT *ioptr, int M, MYFLT *Utbl, int Ustride, int NDiffU, int StageCnt) { /*** RADIX 8 Stages ***/ unsigned int pos; unsigned int posi; unsigned int pinc; unsigned int pnext; unsigned int NSameU; int Uinc; int Uinc2; int Uinc4; unsigned int DiffUCnt; unsigned int SameUCnt; unsigned int U2toU3; MYFLT *pstrt; MYFLT *p0r, *p1r, *p2r, *p3r; MYFLT *u0r, *u0i, *u1r, *u1i, *u2r, *u2i; MYFLT w0r, w0i, w1r, w1i, w2r, w2i, w3r, w3i; MYFLT f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; MYFLT f4r, f4i, f5r, f5i, f6r, f6i, f7r, f7i; MYFLT t0r, t0i, t1r, t1i; const MYFLT Two = FL(2.0); pinc = NDiffU * 2; /* 2 floats per complex */ pnext = pinc * 8; pos = pinc * 4; posi = pos + 1; NSameU = POW2(M) / 8 / NDiffU; /* 8 pts per butterfly */ Uinc = (int) NSameU * Ustride; Uinc2 = Uinc * 2; Uinc4 = Uinc * 4; U2toU3 = (POW2(M) / 8) * Ustride; for (; StageCnt > 0; StageCnt--) { u0r = &Utbl[0]; u0i = &Utbl[POW2(M - 2) * Ustride]; u1r = u0r; u1i = u0i; u2r = u0r; u2i = u0i; w0r = *u0r; w0i = *u0i; w1r = *u1r; w1i = *u1i; w2r = *u2r; w2i = *u2i; w3r = *(u2r + U2toU3); w3i = *(u2i - U2toU3); pstrt = ioptr; p0r = pstrt; p1r = pstrt + pinc; p2r = p1r + pinc; p3r = p2r + pinc; /* Butterflys */ /* f0 - - t0 - - f0 - - f0 f1 - w0- f1 - - f1 - - f1 f2 - - f2 - w1- f2 - - f4 f3 - w0- t1 - iw1- f3 - - f5 f4 - - t0 - - f4 - w2- t0 f5 - w0- f5 - - f5 - w3- t1 f6 - - f6 - w1- f6 - iw2- f6 f7 - w0- t1 - iw1- f7 - iw3- f7 */ for (DiffUCnt = NDiffU; DiffUCnt > 0; DiffUCnt--) { f0r = *p0r; f0i = *(p0r + 1); f1r = *p1r; f1i = *(p1r + 1); for (SameUCnt = NSameU - 1; SameUCnt > 0; SameUCnt--) { f2r = *p2r; f2i = *(p2r + 1); f3r = *p3r; f3i = *(p3r + 1); t0r = f0r + f1r * w0r - f1i * w0i; t0i = f0i + f1r * w0i + f1i * w0r; f1r = f0r * Two - t0r; f1i = f0i * Two - t0i; f4r = *(p0r + pos); f4i = *(p0r + posi); f5r = *(p1r + pos); f5i = *(p1r + posi); f6r = *(p2r + pos); f6i = *(p2r + posi); f7r = *(p3r + pos); f7i = *(p3r + posi); t1r = f2r - f3r * w0r + f3i * w0i; t1i = f2i - f3r * w0i - f3i * w0r; f2r = f2r * Two - t1r; f2i = f2i * Two - t1i; f0r = t0r + f2r * w1r - f2i * w1i; f0i = t0i + f2r * w1i + f2i * w1r; f2r = t0r * Two - f0r; f2i = t0i * Two - f0i; f3r = f1r + t1r * w1i + t1i * w1r; f3i = f1i - t1r * w1r + t1i * w1i; f1r = f1r * Two - f3r; f1i = f1i * Two - f3i; t0r = f4r + f5r * w0r - f5i * w0i; t0i = f4i + f5r * w0i + f5i * w0r; f5r = f4r * Two - t0r; f5i = f4i * Two - t0i; t1r = f6r - f7r * w0r + f7i * w0i; t1i = f6i - f7r * w0i - f7i * w0r; f6r = f6r * Two - t1r; f6i = f6i * Two - t1i; f4r = t0r + f6r * w1r - f6i * w1i; f4i = t0i + f6r * w1i + f6i * w1r; f6r = t0r * Two - f4r; f6i = t0i * Two - f4i; f7r = f5r + t1r * w1i + t1i * w1r; f7i = f5i - t1r * w1r + t1i * w1i; f5r = f5r * Two - f7r; f5i = f5i * Two - f7i; t0r = f0r - f4r * w2r + f4i * w2i; t0i = f0i - f4r * w2i - f4i * w2r; f0r = f0r * Two - t0r; f0i = f0i * Two - t0i; t1r = f1r - f5r * w3r + f5i * w3i; t1i = f1i - f5r * w3i - f5i * w3r; f1r = f1r * Two - t1r; f1i = f1i * Two - t1i; *(p0r + pos) = t0r; *(p0r + posi) = t0i; *p0r = f0r; *(p0r + 1) = f0i; p0r += pnext; f0r = *p0r; f0i = *(p0r + 1); *(p1r + pos) = t1r; *(p1r + posi) = t1i; *p1r = f1r; *(p1r + 1) = f1i; p1r += pnext; f1r = *p1r; f1i = *(p1r + 1); f4r = f2r - f6r * w2i - f6i * w2r; f4i = f2i + f6r * w2r - f6i * w2i; f6r = f2r * Two - f4r; f6i = f2i * Two - f4i; f5r = f3r - f7r * w3i - f7i * w3r; f5i = f3i + f7r * w3r - f7i * w3i; f7r = f3r * Two - f5r; f7i = f3i * Two - f5i; *p2r = f4r; *(p2r + 1) = f4i; *(p2r + pos) = f6r; *(p2r + posi) = f6i; p2r += pnext; *p3r = f5r; *(p3r + 1) = f5i; *(p3r + pos) = f7r; *(p3r + posi) = f7i; p3r += pnext; } f2r = *p2r; f2i = *(p2r + 1); f3r = *p3r; f3i = *(p3r + 1); t0r = f0r + f1r * w0r - f1i * w0i; t0i = f0i + f1r * w0i + f1i * w0r; f1r = f0r * Two - t0r; f1i = f0i * Two - t0i; f4r = *(p0r + pos); f4i = *(p0r + posi); f5r = *(p1r + pos); f5i = *(p1r + posi); f6r = *(p2r + pos); f6i = *(p2r + posi); f7r = *(p3r + pos); f7i = *(p3r + posi); t1r = f2r - f3r * w0r + f3i * w0i; t1i = f2i - f3r * w0i - f3i * w0r; f2r = f2r * Two - t1r; f2i = f2i * Two - t1i; f0r = t0r + f2r * w1r - f2i * w1i; f0i = t0i + f2r * w1i + f2i * w1r; f2r = t0r * Two - f0r; f2i = t0i * Two - f0i; f3r = f1r + t1r * w1i + t1i * w1r; f3i = f1i - t1r * w1r + t1i * w1i; f1r = f1r * Two - f3r; f1i = f1i * Two - f3i; if ((int) DiffUCnt == NDiffU / 2) Uinc4 = -Uinc4; u0r += Uinc4; u0i -= Uinc4; u1r += Uinc2; u1i -= Uinc2; u2r += Uinc; u2i -= Uinc; pstrt += 2; t0r = f4r + f5r * w0r - f5i * w0i; t0i = f4i + f5r * w0i + f5i * w0r; f5r = f4r * Two - t0r; f5i = f4i * Two - t0i; t1r = f6r - f7r * w0r + f7i * w0i; t1i = f6i - f7r * w0i - f7i * w0r; f6r = f6r * Two - t1r; f6i = f6i * Two - t1i; f4r = t0r + f6r * w1r - f6i * w1i; f4i = t0i + f6r * w1i + f6i * w1r; f6r = t0r * Two - f4r; f6i = t0i * Two - f4i; f7r = f5r + t1r * w1i + t1i * w1r; f7i = f5i - t1r * w1r + t1i * w1i; f5r = f5r * Two - f7r; f5i = f5i * Two - f7i; w0r = *u0r; w0i = *u0i; w1r = *u1r; w1i = *u1i; if ((int) DiffUCnt <= NDiffU / 2) w0r = -w0r; t0r = f0r - f4r * w2r + f4i * w2i; t0i = f0i - f4r * w2i - f4i * w2r; f0r = f0r * Two - t0r; f0i = f0i * Two - t0i; f4r = f2r - f6r * w2i - f6i * w2r; f4i = f2i + f6r * w2r - f6i * w2i; f6r = f2r * Two - f4r; f6i = f2i * Two - f4i; *(p0r + pos) = t0r; *p2r = f4r; *(p0r + posi) = t0i; *(p2r + 1) = f4i; w2r = *u2r; w2i = *u2i; *p0r = f0r; *(p2r + pos) = f6r; *(p0r + 1) = f0i; *(p2r + posi) = f6i; p0r = pstrt; p2r = pstrt + pinc + pinc; t1r = f1r - f5r * w3r + f5i * w3i; t1i = f1i - f5r * w3i - f5i * w3r; f1r = f1r * Two - t1r; f1i = f1i * Two - t1i; f5r = f3r - f7r * w3i - f7i * w3r; f5i = f3i + f7r * w3r - f7i * w3i; f7r = f3r * Two - f5r; f7i = f3i * Two - f5i; *(p1r + pos) = t1r; *p3r = f5r; *(p1r + posi) = t1i; *(p3r + 1) = f5i; w3r = *(u2r + U2toU3); w3i = *(u2i - U2toU3); *p1r = f1r; *(p3r + pos) = f7r; *(p1r + 1) = f1i; *(p3r + posi) = f7i; p1r = pstrt + pinc; p3r = p2r + pinc; } NSameU /= 8; Uinc /= 8; Uinc2 /= 8; Uinc4 = Uinc * 4; NDiffU *= 8; pinc *= 8; pnext *= 8; pos *= 8; posi = pos + 1; } } static void ifftrecurs(MYFLT *ioptr, int M, MYFLT *Utbl, int Ustride, int NDiffU, int StageCnt) { /* recursive bfstages calls to maximize on chip cache efficiency */ int i1; if (M <= (int) MCACHE) ibfstages(ioptr, M, Utbl, Ustride, NDiffU, StageCnt); /* RADIX 8 Stages */ else { for (i1 = 0; i1 < 8; i1++) { ifftrecurs(&ioptr[i1 * POW2(M - 3) * 2], M - 3, Utbl, 8 * Ustride, NDiffU, StageCnt - 1); /* RADIX 8 Stages */ } ibfstages(ioptr, M, Utbl, Ustride, POW2(M - 3), 1); /* RADIX 8 Stage */ } } static void iffts1(MYFLT *ioptr, int M, MYFLT *Utbl, int16 *BRLow) { /* Compute in-place inverse complex fft on the rows of the input array */ /* INPUTS */ /* *ioptr = input data array */ /* M = log2 of fft size */ /* *Utbl = cosine table */ /* *BRLow = bit reversed counter table */ /* OUTPUTS */ /* *ioptr = output data array */ int StageCnt; int NDiffU; const MYFLT scale = FL(1.0) / POW2(M); switch (M) { case 0: break; case 1: ifft2pt(ioptr, scale); /* a 2 pt fft */ break; case 2: ifft4pt(ioptr, scale); /* a 4 pt fft */ break; case 3: ifft8pt(ioptr, scale); /* an 8 pt fft */ break; default: /* bit reverse and first radix 2 stage */ scbitrevR2(ioptr, M, BRLow, scale); StageCnt = (M - 1) / 3; /* number of radix 8 stages */ NDiffU = 2; /* one radix 2 stage already complete */ if ((M - 1 - (StageCnt * 3)) == 1) { ibfR2(ioptr, M, NDiffU); /* 1 radix 2 stage */ NDiffU *= 2; } if ((M - 1 - (StageCnt * 3)) == 2) { ibfR4(ioptr, M, NDiffU); /* 1 radix 4 stage */ NDiffU *= 4; } if (M <= (int) MCACHE) ibfstages(ioptr, M, Utbl, 1, NDiffU, StageCnt); /* RADIX 8 Stages */ else ifftrecurs(ioptr, M, Utbl, 1, NDiffU, StageCnt); /* RADIX 8 Stages */ } } /****************** * parts of rffts1 * ******************/ static void rfft1pt(MYFLT *ioptr) { /*** RADIX 2 rfft ***/ MYFLT f0r, f0i; MYFLT t0r, t0i; /* bit reversed load */ f0r = ioptr[0]; f0i = ioptr[1]; /* finish rfft */ t0r = f0r + f0i; t0i = f0r - f0i; /* store result */ ioptr[0] = t0r; ioptr[1] = t0i; } static void rfft2pt(MYFLT *ioptr) { /*** RADIX 4 rfft ***/ MYFLT f0r, f0i, f1r, f1i; MYFLT t0r, t0i; /* bit reversed load */ f0r = ioptr[0]; f0i = ioptr[1]; f1r = ioptr[2]; f1i = ioptr[3]; /* Butterflys */ /* f0 - - t0 f1 - 1 - f1 */ t0r = f0r + f1r; t0i = f0i + f1i; f1r = f0r - f1r; f1i = f1i - f0i; /* finish rfft */ f0r = t0r + t0i; f0i = t0r - t0i; /* store result */ ioptr[0] = f0r; ioptr[1] = f0i; ioptr[2] = f1r; ioptr[3] = f1i; } static void rfft4pt(MYFLT *ioptr) { /*** RADIX 8 rfft ***/ MYFLT f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; MYFLT t0r, t0i, t1r, t1i; MYFLT w0r = 1.0 / MYROOT2; /* cos(pi/4) */ const MYFLT Two = FL(2.0); const MYFLT scale = FL(0.5); /* bit reversed load */ f0r = ioptr[0]; f0i = ioptr[1]; f1r = ioptr[4]; f1i = ioptr[5]; f2r = ioptr[2]; f2i = ioptr[3]; f3r = ioptr[6]; f3i = ioptr[7]; /* Butterflys */ /* f0 - - t0 - - f0 f1 - 1 - f1 - - f1 f2 - - f2 - 1 - f2 f3 - 1 - t1 - -i - f3 */ t0r = f0r + f1r; t0i = f0i + f1i; f1r = f0r - f1r; f1i = f0i - f1i; t1r = f2r - f3r; t1i = f2i - f3i; f2r = f2r + f3r; f2i = f2i + f3i; f0r = t0r + f2r; f0i = t0i + f2i; f2r = t0r - f2r; f2i = f2i - t0i; /* neg for rfft */ f3r = f1r - t1i; f3i = f1i + t1r; f1r = f1r + t1i; f1i = f1i - t1r; /* finish rfft */ t0r = f0r + f0i; /* compute Re(x[0]) */ t0i = f0r - f0i; /* compute Re(x[N/2]) */ t1r = f1r + f3r; t1i = f1i - f3i; f0r = f1i + f3i; f0i = f3r - f1r; f1r = t1r + w0r * f0r + w0r * f0i; f1i = t1i - w0r * f0r + w0r * f0i; f3r = Two * t1r - f1r; f3i = f1i - Two * t1i; /* store result */ ioptr[4] = f2r; ioptr[5] = f2i; ioptr[0] = t0r; ioptr[1] = t0i; ioptr[2] = scale * f1r; ioptr[3] = scale * f1i; ioptr[6] = scale * f3r; ioptr[7] = scale * f3i; } static void rfft8pt(MYFLT *ioptr) { /*** RADIX 16 rfft ***/ MYFLT w0r = 1.0 / MYROOT2; /* cos(pi/4) */ MYFLT w1r = MYCOSPID8; /* cos(pi/8) */ MYFLT w1i = MYSINPID8; /* sin(pi/8) */ MYFLT f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; MYFLT f4r, f4i, f5r, f5i, f6r, f6i, f7r, f7i; MYFLT t0r, t0i, t1r, t1i; const MYFLT Two = FL(2.0); const MYFLT scale = FL(0.5); /* bit reversed load */ f0r = ioptr[0]; f0i = ioptr[1]; f1r = ioptr[8]; f1i = ioptr[9]; f2r = ioptr[4]; f2i = ioptr[5]; f3r = ioptr[12]; f3i = ioptr[13]; f4r = ioptr[2]; f4i = ioptr[3]; f5r = ioptr[10]; f5i = ioptr[11]; f6r = ioptr[6]; f6i = ioptr[7]; f7r = ioptr[14]; f7i = ioptr[15]; /* Butterflys */ /* f0 - - t0 - - f0 - - f0 f1 - 1 - f1 - - f1 - - f1 f2 - - f2 - 1 - f2 - - f2 f3 - 1 - t1 - -i - f3 - - f3 f4 - - t0 - - f4 - 1 - t0 f5 - 1 - f5 - - f5 - w3 - f4 f6 - - f6 - 1 - f6 - -i - t1 f7 - 1 - t1 - -i - f7 - iw3- f6 */ t0r = f0r + f1r; t0i = f0i + f1i; f1r = f0r - f1r; f1i = f0i - f1i; t1r = f2r - f3r; t1i = f2i - f3i; f2r = f2r + f3r; f2i = f2i + f3i; f0r = t0r + f2r; f0i = t0i + f2i; f2r = t0r - f2r; f2i = t0i - f2i; f3r = f1r - t1i; f3i = f1i + t1r; f1r = f1r + t1i; f1i = f1i - t1r; t0r = f4r + f5r; t0i = f4i + f5i; f5r = f4r - f5r; f5i = f4i - f5i; t1r = f6r - f7r; t1i = f6i - f7i; f6r = f6r + f7r; f6i = f6i + f7i; f4r = t0r + f6r; f4i = t0i + f6i; f6r = t0r - f6r; f6i = t0i - f6i; f7r = f5r - t1i; f7i = f5i + t1r; f5r = f5r + t1i; f5i = f5i - t1r; t0r = f0r - f4r; t0i = f4i - f0i; /* neg for rfft */ f0r = f0r + f4r; f0i = f0i + f4i; t1r = f2r - f6i; t1i = f2i + f6r; f2r = f2r + f6i; f2i = f2i - f6r; f4r = f1r - f5r * w0r - f5i * w0r; f4i = f1i + f5r * w0r - f5i * w0r; f1r = f1r * Two - f4r; f1i = f1i * Two - f4i; f6r = f3r + f7r * w0r - f7i * w0r; f6i = f3i + f7r * w0r + f7i * w0r; f3r = f3r * Two - f6r; f3i = f3i * Two - f6i; /* finish rfft */ f5r = f0r + f0i; /* compute Re(x[0]) */ f5i = f0r - f0i; /* compute Re(x[N/2]) */ f0r = f2r + t1r; f0i = f2i - t1i; f7r = f2i + t1i; f7i = t1r - f2r; f2r = f0r + w0r * f7r + w0r * f7i; f2i = f0i - w0r * f7r + w0r * f7i; t1r = Two * f0r - f2r; t1i = f2i - Two * f0i; f0r = f1r + f6r; f0i = f1i - f6i; f7r = f1i + f6i; f7i = f6r - f1r; f1r = f0r + w1r * f7r + w1i * f7i; f1i = f0i - w1i * f7r + w1r * f7i; f6r = Two * f0r - f1r; f6i = f1i - Two * f0i; f0r = f3r + f4r; f0i = f3i - f4i; f7r = f3i + f4i; f7i = f4r - f3r; f3r = f0r + w1i * f7r + w1r * f7i; f3i = f0i - w1r * f7r + w1i * f7i; f4r = Two * f0r - f3r; f4i = f3i - Two * f0i; /* store result */ ioptr[8] = t0r; ioptr[9] = t0i; ioptr[0] = f5r; ioptr[1] = f5i; ioptr[4] = scale * f2r; ioptr[5] = scale * f2i; ioptr[12] = scale * t1r; ioptr[13] = scale * t1i; ioptr[2] = scale * f1r; ioptr[3] = scale * f1i; ioptr[6] = scale * f3r; ioptr[7] = scale * f3i; ioptr[10] = scale * f4r; ioptr[11] = scale * f4i; ioptr[14] = scale * f6r; ioptr[15] = scale * f6i; } static void frstage(MYFLT *ioptr, int M, MYFLT *Utbl) { /* Finish RFFT */ unsigned int pos; unsigned int posi; unsigned int diffUcnt; MYFLT *p0r, *p1r; MYFLT *u0r, *u0i; MYFLT w0r, w0i; MYFLT f0r, f0i, f1r, f1i, f4r, f4i, f5r, f5i; MYFLT t0r, t0i, t1r, t1i; const MYFLT Two = FL(2.0); pos = POW2(M - 1); posi = pos + 1; p0r = ioptr; p1r = ioptr + pos / 2; u0r = Utbl + POW2(M - 3); w0r = *u0r, f0r = *(p0r); f0i = *(p0r + 1); f4r = *(p0r + pos); f4i = *(p0r + posi); f1r = *(p1r); f1i = *(p1r + 1); f5r = *(p1r + pos); f5i = *(p1r + posi); t0r = Two * f0r + Two * f0i; /* compute Re(x[0]) */ t0i = Two * f0r - Two * f0i; /* compute Re(x[N/2]) */ t1r = f4r + f4r; t1i = -f4i - f4i; f0r = f1r + f5r; f0i = f1i - f5i; f4r = f1i + f5i; f4i = f5r - f1r; f1r = f0r + w0r * f4r + w0r * f4i; f1i = f0i - w0r * f4r + w0r * f4i; f5r = Two * f0r - f1r; f5i = f1i - Two * f0i; *(p0r) = t0r; *(p0r + 1) = t0i; *(p0r + pos) = t1r; *(p0r + posi) = t1i; *(p1r) = f1r; *(p1r + 1) = f1i; *(p1r + pos) = f5r; *(p1r + posi) = f5i; u0r = Utbl + 1; u0i = Utbl + (POW2(M - 2) - 1); w0r = *u0r, w0i = *u0i; p0r = (ioptr + 2); p1r = (ioptr + (POW2(M - 2) - 1) * 2); /* Butterflys */ /* f0 - t0 - - f0 f5 - t1 - w0 - f5 f1 - t0 - - f1 f4 - t1 -iw0 - f4 */ for (diffUcnt = POW2(M - 3) - 1; diffUcnt > 0; diffUcnt--) { f0r = *(p0r); f0i = *(p0r + 1); f5r = *(p1r + pos); f5i = *(p1r + posi); f1r = *(p1r); f1i = *(p1r + 1); f4r = *(p0r + pos); f4i = *(p0r + posi); t0r = f0r + f5r; t0i = f0i - f5i; t1r = f0i + f5i; t1i = f5r - f0r; f0r = t0r + w0r * t1r + w0i * t1i; f0i = t0i - w0i * t1r + w0r * t1i; f5r = Two * t0r - f0r; f5i = f0i - Two * t0i; t0r = f1r + f4r; t0i = f1i - f4i; t1r = f1i + f4i; t1i = f4r - f1r; f1r = t0r + w0i * t1r + w0r * t1i; f1i = t0i - w0r * t1r + w0i * t1i; f4r = Two * t0r - f1r; f4i = f1i - Two * t0i; *(p0r) = f0r; *(p0r + 1) = f0i; *(p1r + pos) = f5r; *(p1r + posi) = f5i; w0r = *++u0r; w0i = *--u0i; *(p1r) = f1r; *(p1r + 1) = f1i; *(p0r + pos) = f4r; *(p0r + posi) = f4i; p0r += 2; p1r -= 2; } } static void rffts1(MYFLT *ioptr, int M, MYFLT *Utbl, int16 *BRLow) { /* Compute in-place real fft on the rows of the input array */ /* The result is the complex spectra of the positive frequencies */ /* except the location for the first complex number contains the real */ /* values for DC and Nyquest */ /* INPUTS */ /* *ioptr = real input data array */ /* M = log2 of fft size */ /* *Utbl = cosine table */ /* *BRLow = bit reversed counter table */ /* OUTPUTS */ /* *ioptr = output data array in the following order */ /* Re(x[0]), Re(x[N/2]), Re(x[1]), Im(x[1]), Re(x[2]), Im(x[2]), */ /* ... Re(x[N/2-1]), Im(x[N/2-1]). */ MYFLT scale; int StageCnt; int NDiffU; M = M - 1; switch (M) { case -1: break; case 0: rfft1pt(ioptr); /* a 2 pt fft */ break; case 1: rfft2pt(ioptr); /* a 4 pt fft */ break; case 2: rfft4pt(ioptr); /* an 8 pt fft */ break; case 3: rfft8pt(ioptr); /* a 16 pt fft */ break; default: scale = 0.5; /* bit reverse and first radix 2 stage */ scbitrevR2(ioptr, M, BRLow, scale); StageCnt = (M - 1) / 3; /* number of radix 8 stages */ NDiffU = 2; /* one radix 2 stage already complete */ if ((M - 1 - (StageCnt * 3)) == 1) { bfR2(ioptr, M, NDiffU); /* 1 radix 2 stage */ NDiffU *= 2; } if ((M - 1 - (StageCnt * 3)) == 2) { bfR4(ioptr, M, NDiffU); /* 1 radix 4 stage */ NDiffU *= 4; } if (M <= (int) MCACHE) bfstages(ioptr, M, Utbl, 2, NDiffU, StageCnt); /* RADIX 8 Stages */ else fftrecurs(ioptr, M, Utbl, 2, NDiffU, StageCnt); /* RADIX 8 Stages */ frstage(ioptr, M + 1, Utbl); } } /******************* * parts of riffts1 * *******************/ static void rifft1pt(MYFLT *ioptr, MYFLT scale) { /*** RADIX 2 rifft ***/ MYFLT f0r, f0i; MYFLT t0r, t0i; /* bit reversed load */ f0r = ioptr[0]; f0i = ioptr[1]; /* finish rfft */ t0r = f0r + f0i; t0i = f0r - f0i; /* store result */ ioptr[0] = scale * t0r; ioptr[1] = scale * t0i; } static void rifft2pt(MYFLT *ioptr, MYFLT scale) { /*** RADIX 4 rifft ***/ MYFLT f0r, f0i, f1r, f1i; MYFLT t0r, t0i; const MYFLT Two = FL(2.0); /* bit reversed load */ t0r = ioptr[0]; t0i = ioptr[1]; f1r = Two * ioptr[2]; f1i = Two * ioptr[3]; /* start rifft */ f0r = t0r + t0i; f0i = t0r - t0i; /* Butterflys */ /* f0 - - t0 f1 - 1 - f1 */ t0r = f0r + f1r; t0i = f0i - f1i; f1r = f0r - f1r; f1i = f0i + f1i; /* store result */ ioptr[0] = scale * t0r; ioptr[1] = scale * t0i; ioptr[2] = scale * f1r; ioptr[3] = scale * f1i; } static void rifft4pt(MYFLT *ioptr, MYFLT scale) { /*** RADIX 8 rifft ***/ MYFLT f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; MYFLT t0r, t0i, t1r, t1i; MYFLT w0r = 1.0 / MYROOT2; /* cos(pi/4) */ const MYFLT Two = FL(2.0); /* bit reversed load */ t0r = ioptr[0]; t0i = ioptr[1]; f2r = ioptr[2]; f2i = ioptr[3]; f1r = Two * ioptr[4]; f1i = Two * ioptr[5]; f3r = ioptr[6]; f3i = ioptr[7]; /* start rfft */ f0r = t0r + t0i; /* compute Re(x[0]) */ f0i = t0r - t0i; /* compute Re(x[N/2]) */ t1r = f2r + f3r; t1i = f2i - f3i; t0r = f2r - f3r; t0i = f2i + f3i; f2r = t1r - w0r * t0r - w0r * t0i; f2i = t1i + w0r * t0r - w0r * t0i; f3r = Two * t1r - f2r; f3i = f2i - Two * t1i; /* Butterflys */ /* f0 - - t0 - - f0 f1 - 1 - f1 - - f1 f2 - - f2 - 1 - f2 f3 - 1 - t1 - i - f3 */ t0r = f0r + f1r; t0i = f0i - f1i; f1r = f0r - f1r; f1i = f0i + f1i; t1r = f2r - f3r; t1i = f2i - f3i; f2r = f2r + f3r; f2i = f2i + f3i; f0r = t0r + f2r; f0i = t0i + f2i; f2r = t0r - f2r; f2i = t0i - f2i; f3r = f1r + t1i; f3i = f1i - t1r; f1r = f1r - t1i; f1i = f1i + t1r; /* store result */ ioptr[0] = scale * f0r; ioptr[1] = scale * f0i; ioptr[2] = scale * f1r; ioptr[3] = scale * f1i; ioptr[4] = scale * f2r; ioptr[5] = scale * f2i; ioptr[6] = scale * f3r; ioptr[7] = scale * f3i; } static void rifft8pt(MYFLT *ioptr, MYFLT scale) { /*** RADIX 16 rifft ***/ MYFLT w0r = (MYFLT) (1.0 / MYROOT2); /* cos(pi/4) */ MYFLT w1r = MYCOSPID8; /* cos(pi/8) */ MYFLT w1i = MYSINPID8; /* sin(pi/8) */ MYFLT f0r, f0i, f1r, f1i, f2r, f2i, f3r, f3i; MYFLT f4r, f4i, f5r, f5i, f6r, f6i, f7r, f7i; MYFLT t0r, t0i, t1r, t1i; const MYFLT Two = FL(2.0); /* bit reversed load */ t0r = ioptr[0]; t0i = ioptr[1]; f4r = ioptr[2]; f4i = ioptr[3]; f2r = ioptr[4]; f2i = ioptr[5]; f6r = ioptr[6]; f6i = ioptr[7]; f1r = Two * ioptr[8]; f1i = Two * ioptr[9]; f5r = ioptr[10]; f5i = ioptr[11]; f3r = ioptr[12]; f3i = ioptr[13]; f7r = ioptr[14]; f7i = ioptr[15]; /* start rfft */ f0r = t0r + t0i; /* compute Re(x[0]) */ f0i = t0r - t0i; /* compute Re(x[N/2]) */ t0r = f2r + f3r; t0i = f2i - f3i; t1r = f2r - f3r; t1i = f2i + f3i; f2r = t0r - w0r * t1r - w0r * t1i; f2i = t0i + w0r * t1r - w0r * t1i; f3r = Two * t0r - f2r; f3i = f2i - Two * t0i; t0r = f4r + f7r; t0i = f4i - f7i; t1r = f4r - f7r; t1i = f4i + f7i; f4r = t0r - w1i * t1r - w1r * t1i; f4i = t0i + w1r * t1r - w1i * t1i; f7r = Two * t0r - f4r; f7i = f4i - Two * t0i; t0r = f6r + f5r; t0i = f6i - f5i; t1r = f6r - f5r; t1i = f6i + f5i; f6r = t0r - w1r * t1r - w1i * t1i; f6i = t0i + w1i * t1r - w1r * t1i; f5r = Two * t0r - f6r; f5i = f6i - Two * t0i; /* Butterflys */ /* f0 - - t0 - - f0 - - f0 f1* - 1 - f1 - - f1 - - f1 f2 - - f2 - 1 - f2 - - f2 f3 - 1 - t1 - i - f3 - - f3 f4 - - t0 - - f4 - 1 - t0 f5 - 1 - f5 - - f5 - w3 - f4 f6 - - f6 - 1 - f6 - i - t1 f7 - 1 - t1 - i - f7 - iw3- f6 */ t0r = f0r + f1r; t0i = f0i - f1i; f1r = f0r - f1r; f1i = f0i + f1i; t1r = f2r - f3r; t1i = f2i - f3i; f2r = f2r + f3r; f2i = f2i + f3i; f0r = t0r + f2r; f0i = t0i + f2i; f2r = t0r - f2r; f2i = t0i - f2i; f3r = f1r + t1i; f3i = f1i - t1r; f1r = f1r - t1i; f1i = f1i + t1r; t0r = f4r + f5r; t0i = f4i + f5i; f5r = f4r - f5r; f5i = f4i - f5i; t1r = f6r - f7r; t1i = f6i - f7i; f6r = f6r + f7r; f6i = f6i + f7i; f4r = t0r + f6r; f4i = t0i + f6i; f6r = t0r - f6r; f6i = t0i - f6i; f7r = f5r + t1i; f7i = f5i - t1r; f5r = f5r - t1i; f5i = f5i + t1r; t0r = f0r - f4r; t0i = f0i - f4i; f0r = f0r + f4r; f0i = f0i + f4i; t1r = f2r + f6i; t1i = f2i - f6r; f2r = f2r - f6i; f2i = f2i + f6r; f4r = f1r - f5r * w0r + f5i * w0r; f4i = f1i - f5r * w0r - f5i * w0r; f1r = f1r * Two - f4r; f1i = f1i * Two - f4i; f6r = f3r + f7r * w0r + f7i * w0r; f6i = f3i - f7r * w0r + f7i * w0r; f3r = f3r * Two - f6r; f3i = f3i * Two - f6i; /* store result */ ioptr[0] = scale * f0r; ioptr[1] = scale * f0i; ioptr[2] = scale * f1r; ioptr[3] = scale * f1i; ioptr[4] = scale * f2r; ioptr[5] = scale * f2i; ioptr[6] = scale * f3r; ioptr[7] = scale * f3i; ioptr[8] = scale * t0r; ioptr[9] = scale * t0i; ioptr[10] = scale * f4r; ioptr[11] = scale * f4i; ioptr[12] = scale * t1r; ioptr[13] = scale * t1i; ioptr[14] = scale * f6r; ioptr[15] = scale * f6i; } static void ifrstage(MYFLT *ioptr, int M, MYFLT *Utbl) { /* Start RIFFT */ unsigned int pos; unsigned int posi; unsigned int diffUcnt; MYFLT *p0r, *p1r; MYFLT *u0r, *u0i; MYFLT w0r, w0i; MYFLT f0r, f0i, f1r, f1i, f4r, f4i, f5r, f5i; MYFLT t0r, t0i, t1r, t1i; const MYFLT Two = FL(2.0); pos = POW2(M - 1); posi = pos + 1; p0r = ioptr; p1r = ioptr + pos / 2; u0r = Utbl + POW2(M - 3); w0r = *u0r, f0r = *(p0r); f0i = *(p0r + 1); f4r = *(p0r + pos); f4i = *(p0r + posi); f1r = *(p1r); f1i = *(p1r + 1); f5r = *(p1r + pos); f5i = *(p1r + posi); t0r = f0r + f0i; t0i = f0r - f0i; t1r = f4r + f4r; t1i = -f4i - f4i; f0r = f1r + f5r; f0i = f1i - f5i; f4r = f1r - f5r; f4i = f1i + f5i; f1r = f0r - w0r * f4r - w0r * f4i; f1i = f0i + w0r * f4r - w0r * f4i; f5r = Two * f0r - f1r; f5i = f1i - Two * f0i; *(p0r) = t0r; *(p0r + 1) = t0i; *(p0r + pos) = t1r; *(p0r + posi) = t1i; *(p1r) = f1r; *(p1r + 1) = f1i; *(p1r + pos) = f5r; *(p1r + posi) = f5i; u0r = Utbl + 1; u0i = Utbl + (POW2(M - 2) - 1); w0r = *u0r, w0i = *u0i; p0r = (ioptr + 2); p1r = (ioptr + (POW2(M - 2) - 1) * 2); /* Butterflys */ /* f0 - t0 - f0 f1 - t1 -w0- f1 f2 - t0 - f2 f3 - t1 -iw0- f3 */ for (diffUcnt = POW2(M - 3) - 1; diffUcnt > 0; diffUcnt--) { f0r = *(p0r); f0i = *(p0r + 1); f5r = *(p1r + pos); f5i = *(p1r + posi); f1r = *(p1r); f1i = *(p1r + 1); f4r = *(p0r + pos); f4i = *(p0r + posi); t0r = f0r + f5r; t0i = f0i - f5i; t1r = f0r - f5r; t1i = f0i + f5i; f0r = t0r - w0i * t1r - w0r * t1i; f0i = t0i + w0r * t1r - w0i * t1i; f5r = Two * t0r - f0r; f5i = f0i - Two * t0i; t0r = f1r + f4r; t0i = f1i - f4i; t1r = f1r - f4r; t1i = f1i + f4i; f1r = t0r - w0r * t1r - w0i * t1i; f1i = t0i + w0i * t1r - w0r * t1i; f4r = Two * t0r - f1r; f4i = f1i - Two * t0i; *(p0r) = f0r; *(p0r + 1) = f0i; *(p1r + pos) = f5r; *(p1r + posi) = f5i; w0r = *++u0r; w0i = *--u0i; *(p1r) = f1r; *(p1r + 1) = f1i; *(p0r + pos) = f4r; *(p0r + posi) = f4i; p0r += 2; p1r -= 2; } } static void riffts1(MYFLT *ioptr, int M, MYFLT *Utbl, int16 *BRLow) { /* Compute in-place real ifft on the rows of the input array */ /* data order as from rffts1 */ /* INPUTS */ /* *ioptr = input data array in the following order */ /* M = log2 of fft size */ /* Re(x[0]), Re(x[N/2]), Re(x[1]), Im(x[1]), */ /* Re(x[2]), Im(x[2]), ... Re(x[N/2-1]), Im(x[N/2-1]). */ /* *Utbl = cosine table */ /* *BRLow = bit reversed counter table */ /* OUTPUTS */ /* *ioptr = real output data array */ MYFLT scale; int StageCnt; int NDiffU; scale = (MYFLT)(1.0 / (double)((int)POW2(M))); M = M - 1; switch (M) { case -1: break; case 0: rifft1pt(ioptr, scale); /* a 2 pt fft */ break; case 1: rifft2pt(ioptr, scale); /* a 4 pt fft */ break; case 2: rifft4pt(ioptr, scale); /* an 8 pt fft */ break; case 3: rifft8pt(ioptr, scale); /* a 16 pt fft */ break; default: ifrstage(ioptr, M + 1, Utbl); /* bit reverse and first radix 2 stage */ scbitrevR2(ioptr, M, BRLow, scale); StageCnt = (M - 1) / 3; /* number of radix 8 stages */ NDiffU = 2; /* one radix 2 stage already complete */ if ((M - 1 - (StageCnt * 3)) == 1) { ibfR2(ioptr, M, NDiffU); /* 1 radix 2 stage */ NDiffU *= 2; } if ((M - 1 - (StageCnt * 3)) == 2) { ibfR4(ioptr, M, NDiffU); /* 1 radix 4 stage */ NDiffU *= 4; } if (M <= (int) MCACHE) ibfstages(ioptr, M, Utbl, 2, NDiffU, StageCnt); /* RADIX 8 Stages */ else ifftrecurs(ioptr, M, Utbl, 2, NDiffU, StageCnt); /* RADIX 8 Stages */ } } static void fftInit(CSOUND *csound, int M) { /* malloc and init cosine and bit reversed tables for a given size */ /* fft, ifft, rfft, rifft */ /* INPUTS */ /* M = log2 of fft size (ex M=10 for 1024 point fft) */ /* OUTPUTS */ /* private cosine and bit reversed tables */ MYFLT **UtblArray; int16 **BRLowArray; int i; if (!csound->FFT_max_size) { if (csound->FFT_table_1 == NULL) csound->FFT_table_1 = csound->Malloc(csound, sizeof(MYFLT*) * 32); if (csound->FFT_table_2 == NULL) csound->FFT_table_2 = csound->Malloc(csound, sizeof(int16*) * 32); for (i = 0; i < 32; i++) { ((MYFLT**) csound->FFT_table_1)[i] = (MYFLT*) NULL; ((int16**) csound->FFT_table_2)[i] = (int16*) NULL; } } UtblArray = (MYFLT**) csound->FFT_table_1; BRLowArray = (int16**) csound->FFT_table_2; /*** I did NOT test cases with M>27 ***/ /* init cos table */ UtblArray[M] = (MYFLT*) csound->Malloc(csound, (POW2(M) / 4 + 1) * sizeof(MYFLT)); fftCosInit(M, UtblArray[M]); if (M > 1) { /* init bit reversed table for cmplx FFT */ if (BRLowArray[M / 2] == NULL) { BRLowArray[M / 2] = (int16*) csound->Malloc(csound, POW2(M / 2 - 1) * sizeof(int16)); fftBRInit(M, BRLowArray[M / 2]); } } if (M > 2) { /* init bit reversed table for real FFT */ if (BRLowArray[(M - 1) / 2] == 0) { BRLowArray[(M - 1) / 2] = (int16*) csound->Malloc(csound, POW2((M - 1) / 2 - 1) * sizeof(int16)); fftBRInit(M - 1, BRLowArray[(M - 1) / 2]); } } csound->FFT_max_size |= (1 << M); } static inline int ConvertFFTSize(CSOUND *csound, int N) { if (N <= 0) return (-N); switch (N) { case 0x00000001: return 0; case 0x00000002: return 1; case 0x00000004: return 2; case 0x00000008: return 3; case 0x00000010: return 4; case 0x00000020: return 5; case 0x00000040: return 6; case 0x00000080: return 7; case 0x00000100: return 8; case 0x00000200: return 9; case 0x00000400: return 10; case 0x00000800: return 11; case 0x00001000: return 12; case 0x00002000: return 13; case 0x00004000: return 14; case 0x00008000: return 15; case 0x00010000: return 16; case 0x00020000: return 17; case 0x00040000: return 18; case 0x00080000: return 19; case 0x00100000: return 20; case 0x00200000: return 21; case 0x00400000: return 22; case 0x00800000: return 23; case 0x01000000: return 24; case 0x02000000: return 25; case 0x04000000: return 26; case 0x08000000: return 27; case 0x10000000: return 28; } csound->Warning(csound, Str(" *** fftlib.c: internal error: " "invalid FFT size: %d"), N); return 0; } static inline void getTablePointers(CSOUND *p, MYFLT **ct, int16 **bt, int cn, int bn) { if (!(p->FFT_max_size & (1 << cn))) fftInit(p, cn); *ct = ((MYFLT**) p->FFT_table_1)[cn]; *bt = ((int16**) p->FFT_table_2)[bn]; } /** * Returns the amplitude scale that should be applied to the result of * an inverse complex FFT with a length of 'FFTsize' samples. */ MYFLT csoundGetInverseComplexFFTScale(CSOUND *csound, int FFTsize) { IGN(FFTsize); IGN(csound); return FL(1.0); } /** * Returns the amplitude scale that should be applied to the result of * an inverse real FFT with a length of 'FFTsize' samples. */ MYFLT csoundGetInverseRealFFTScale(CSOUND *csound, int FFTsize) { IGN(FFTsize); IGN(csound); return FL(1.0); } /** * Compute in-place complex FFT * FFTsize: FFT length in samples * buf: array of FFTsize*2 MYFLT values, * in interleaved real/imaginary format */ void csoundComplexFFT(CSOUND *csound, MYFLT *buf, int FFTsize) { MYFLT *Utbl; int16 *BRLow; int M; M = ConvertFFTSize(csound, FFTsize); getTablePointers(csound, &Utbl, &BRLow, M, M / 2); ffts1(buf, M, Utbl, BRLow); } /** * Compute in-place inverse complex FFT * FFTsize: FFT length in samples * buf: array of FFTsize*2 MYFLT values, * in interleaved real/imaginary format * Output should be scaled by the return value of * csoundGetInverseComplexFFTScale(csound, FFTsize). */ void csoundInverseComplexFFT(CSOUND *csound, MYFLT *buf, int FFTsize) { MYFLT *Utbl; int16 *BRLow; int M; M = ConvertFFTSize(csound, FFTsize); getTablePointers(csound, &Utbl, &BRLow, M, M / 2); iffts1(buf, M, Utbl, BRLow); } /** * Compute in-place real FFT * FFTsize: FFT length in samples * buf: array of FFTsize MYFLT values; output is in interleaved * real/imaginary format, except for buf[1] which is the real * part for the Nyquist frequency */ void csoundRealFFT(CSOUND *csound, MYFLT *buf, int FFTsize) { MYFLT *Utbl; int16 *BRLow; int M; M = ConvertFFTSize(csound, FFTsize); getTablePointers(csound, &Utbl, &BRLow, M, (M - 1) / 2); rffts1(buf, M, Utbl, BRLow); } /** * Compute in-place inverse real FFT * FFTsize: FFT length in samples * buf: array of FFTsize MYFLT values; input is expected to be in * interleaved real/imaginary format, except for buf[1] which * is the real part for the Nyquist frequency * Output should be scaled by the return value of * csoundGetInverseRealFFTScale(csound, FFTsize). */ void csoundInverseRealFFT(CSOUND *csound, MYFLT *buf, int FFTsize) { MYFLT *Utbl; int16 *BRLow; int M; M = ConvertFFTSize(csound, FFTsize); getTablePointers(csound, &Utbl, &BRLow, M, (M - 1) / 2); riffts1(buf, M, Utbl, BRLow); } /** * Multiply two arrays (buf1 and buf2) of complex data in the format * returned by csoundRealFFT(), and leave the result in outbuf, which * may be the same as either buf1 or buf2. * An amplitude scale of 'scaleFac' is also applied. * The arrays should contain 'FFTsize' MYFLT values. */ void csoundRealFFTMult(CSOUND *csound, MYFLT *outbuf, MYFLT *buf1, MYFLT *buf2, int FFTsize, MYFLT scaleFac) { MYFLT re, im; int i; IGN(csound); if (scaleFac != FL(1.0)) { outbuf[0] = buf1[0] * buf2[0] * scaleFac; if (FFTsize < 2) return; outbuf[1] = buf1[1] * buf2[1] * scaleFac; for (i = 2; i < FFTsize; ) { re = ((buf1[i] * buf2[i]) - (buf1[i + 1] * buf2[i + 1])) * scaleFac; im = ((buf1[i] * buf2[i + 1]) + (buf2[i] * buf1[i + 1])) * scaleFac; outbuf[i++] = re; outbuf[i++] = im; } } else { outbuf[0] = buf1[0] * buf2[0]; if (FFTsize < 2) return; outbuf[1] = buf1[1] * buf2[1]; for (i = 2; i < FFTsize; ) { re = (buf1[i] * buf2[i]) - (buf1[i + 1] * buf2[i + 1]); im = (buf1[i] * buf2[i + 1]) + (buf2[i] * buf1[i + 1]); outbuf[i++] = re; outbuf[i++] = im; } } } /* New FFT interface VL, 2016 */ static void pffft_execute(CSOUND_FFT_SETUP *setup, MYFLT *sig) { int i, N = setup->N; float s, *buf; buf = (float *) setup->buffer; for(i=0;isetup, buf,buf,NULL,setup->d); s = (setup->d == PFFFT_BACKWARD ? (MYFLT) setup->N : FL(1.0)); for(i=0;i static void vDSP_execute(CSOUND_FFT_SETUP *setup, MYFLT *sig){ #ifdef USE_DOUBLE DSPDoubleSplitComplex tmp; #else DSPSplitComplex tmp; #endif int i,j; MYFLT s; int N = setup->N; tmp.realp = &setup->buffer[0]; tmp.imagp = &setup->buffer[N>>1]; for(i=j=0;isetup, &tmp, 1, setup->M,setup->d); #else vDSP_fft_zrip((FFTSetup) setup->setup, &tmp, 1, setup->M,setup->d); #endif s = (setup->d == -1 ? (MYFLT)(N) : FL(2.0)); for(i=j=0;iMalloc(csound, nb_bytes + ALIGN_BYTES); if(!p0) return (void *) 0; p = (void *) (((size_t) p0 + ALIGN_BYTES) & (~((size_t) (ALIGN_BYTES-1)))); *((void **) p - 1) = p0; return p; } int setupDispose(CSOUND *csound, void *pp){ IGN(csound); CSOUND_FFT_SETUP *setup =(CSOUND_FFT_SETUP *) pp; switch(setup->lib){ #if defined(__MACH__) case VDSP_LIB: vDSP_destroy_fftsetupD( #ifdef USE_DOUBLE (FFTSetupD) #else (FFTSetup) #endif setup->setup); break; #endif case PFFT_LIB: pffft_destroy_setup((PFFFT_Setup *)setup->setup); break; } return OK; } int isPowTwo(int N) { return (N != 0) ? !(N & (N - 1)) : 0; } void *csoundRealFFT2Setup(CSOUND *csound, int FFTsize, int d){ CSOUND_FFT_SETUP *setup; int lib = csound->oparms->fft_lib; if(lib == PFFT_LIB && FFTsize <= 16){ csound->Warning(csound, "FFTsize %d \n" "Cannot use PFFT with sizes <= 16\n" "--defaulting to FFTLIB", FFTsize); lib = 0; } setup = (CSOUND_FFT_SETUP *) csound->Calloc(csound, sizeof(CSOUND_FFT_SETUP)); setup->N = FFTsize; setup->p2 = isPowTwo(FFTsize); switch(lib){ #if defined(__MACH__) case VDSP_LIB: setup->M = ConvertFFTSize(csound, FFTsize); setup->setup = (void *) #ifdef USE_DOUBLE vDSP_create_fftsetupD(setup->M,kFFTRadix2); #else vDSP_create_fftsetup(setup->M,kFFTRadix2); #endif setup->d = (d == FFT_FWD ? kFFTDirection_Forward : kFFTDirection_Inverse); setup->lib = lib; break; #endif case PFFT_LIB: setup->setup = (void *) pffft_new_setup(FFTsize,PFFFT_REAL); setup->d = (d == FFT_FWD ? PFFFT_FORWARD : PFFFT_BACKWARD); setup->lib = lib; break; default: setup->lib = 0; setup->d = d; return (void *) setup; } setup->buffer = (MYFLT *) align_alloc(csound, sizeof(MYFLT)*FFTsize); csound->RegisterResetCallback(csound, (void*) setup, (int (*)(CSOUND *, void *)) setupDispose); return (void *) setup; } void csoundRealFFT2(CSOUND *csound, void *p, MYFLT *sig){ CSOUND_FFT_SETUP *setup = (CSOUND_FFT_SETUP *) p; switch(setup->lib) { #if defined(__MACH__) case VDSP_LIB: vDSP_execute(setup,sig); break; #endif case PFFT_LIB: pffft_execute(setup,sig); break; default: (setup->d == FFT_FWD ? csoundRealFFT(csound, sig,setup->N) : csoundInverseRealFFT(csound, sig,setup->N)); setup->lib = 0; } } void *csoundDCTSetup(CSOUND *csound, int FFTsize, int d){ CSOUND_FFT_SETUP *setup; setup = (CSOUND_FFT_SETUP *) csoundRealFFT2Setup(csound, FFTsize*4,d); if(setup->lib == 0){ setup->buffer = (MYFLT *) csound->Calloc(csound, sizeof(MYFLT)*setup->N); } return setup; } void pffft_DCT_execute(CSOUND *csound, void *p, MYFLT *sig){ IGN(csound); CSOUND_FFT_SETUP *setup = (CSOUND_FFT_SETUP *) p; int i,j, N= setup->N; float *buffer = (float *)setup->buffer; if(setup->d == FFT_FWD){ for(i=j = 0; i < N/2; i+=2, j++){ buffer[i] = FL(0.0); buffer[i+1] = sig[j]; } for(i=N/2,j=N/4-1; i < N; i+=2, j--){ buffer[i] = FL(0.0); buffer[i+1] = sig[j]; } pffft_transform_ordered((PFFFT_Setup *) setup->setup, buffer,buffer, NULL,PFFFT_FORWARD); for(i=j=0; i < N/2; i+=2, j++){ sig[j] = buffer[i]; } } else { buffer[0] = sig[0]; buffer[1] = -sig[0]; for(i=2,j=1; i < N/2; i+=2, j++){ buffer[i] = sig[j]; buffer[i+1] = FL(0.0); } buffer[N/2] = buffer[N/2+1] = FL(0.0); for(i=N/2+2,j=N/4-1; i < N; i+=2, j--){ buffer[i] = -sig[j]; buffer[i+1] = FL(0.0); } pffft_transform_ordered((PFFFT_Setup *) setup->setup, buffer,buffer, NULL,PFFFT_BACKWARD); for(i=j=0; i < N/2; i+=2, j++){ sig[j] = buffer[i+1]/N; } } } #if defined(__MACH__) void vDSP_DCT_execute(CSOUND *csound, void *p, MYFLT *sig){ IGN(csound); CSOUND_FFT_SETUP *setup = (CSOUND_FFT_SETUP *) p; int i,j, N= setup->N; #ifdef USE_DOUBLE DSPDoubleSplitComplex tmp; #else DSPSplitComplex tmp; #endif tmp.realp = &setup->buffer[0]; tmp.imagp = &setup->buffer[N>>1]; if(setup->d == kFFTDirection_Forward){ for(j=0;jsetup, #else vDSP_fft_zrip((FFTSetup) setup->setup, #endif &tmp, 1, setup->M,setup->d); for(j=0; j < N/4; j++){ sig[j] = tmp.realp[j]/FL(2.0); } } else { tmp.realp[0] = sig[0]; tmp.imagp[0] = -sig[0]; for(j=1; j < N/4; j++){ tmp.realp[j] = sig[j]; tmp.imagp[j] = FL(0.0); } tmp.realp[N/4] = tmp.imagp[N/4] = FL(0.0); for(i=N/4+1,j=N/4-1; i < N/2; i++, j--){ tmp.realp[i] = -sig[j]; tmp.imagp[i] = FL(0.0); } #ifdef USE_DOUBLE vDSP_fft_zripD((FFTSetupD) setup->setup, #else vDSP_fft_zrip((FFTSetup) setup->setup, #endif &tmp, 1, setup->M,setup->d); for(j=0; j < N/4; j++){ sig[j] = tmp.imagp[j]/N; } } } #endif void DCT_execute(CSOUND *csound, void *p, MYFLT *sig){ CSOUND_FFT_SETUP *setup = (CSOUND_FFT_SETUP *) p; int i,j, N= setup->N; MYFLT *buffer = setup->buffer; if(setup->d == FFT_FWD){ for(i=j = 0; i < N/2; i+=2, j++){ buffer[i] = FL(0.0); buffer[i+1] = sig[j]; } for(i=N/2,j=N/4-1; i < N; i+=2, j--){ buffer[i] = FL(0.0); buffer[i+1] = sig[j]; } csoundRealFFT(csound,buffer,N); for(i=j=0; i < N/2; i+=2, j++){ sig[j] = buffer[i]; } } else { buffer[0] = sig[0]; buffer[1] = -sig[0]; for(i=2,j=1; i < N/2; i+=2, j++){ buffer[i] = sig[j]; buffer[i+1] = FL(0.0); } buffer[N/2] = buffer[N/2+1] = FL(0.0); for(i=N/2+2,j=N/4-1; i < N; i+=2, j--){ buffer[i] = -sig[j]; buffer[i+1] = FL(0.0); } csoundInverseRealFFT(csound,buffer,N); for(i=j=0; i < N/2; i+=2, j++){ sig[j] = buffer[i+1]; } } } void csoundDCT(CSOUND *csound, void *p, MYFLT *sig){ CSOUND_FFT_SETUP *setup = (CSOUND_FFT_SETUP *) p; switch(setup->lib) { #if defined(__MACH__) case VDSP_LIB: vDSP_DCT_execute(csound,setup,sig); break; #endif case PFFT_LIB: pffft_DCT_execute(csound,setup,sig); break; default: DCT_execute(csound,setup,sig); setup->lib = 0; } } /* =======--====================*/ #if 0 #ifdef HAVE_VECLIB /* vDSP FFT interface */ #define ALIGN64 64 static void *vDSP_alloc(CSOUND *csound, size_t nb_bytes){ void *p, *p0 = csound->Malloc(csound, nb_bytes + ALIGN64); if(!p0) return (void *) 0; p = (void *) (((size_t) p0 + ALIGN64) & (~((size_t) (ALIGN64-1)))); *((void **) p - 1) = p0; return p; } static void vDSP_free(CSOUND *csound, void *p) { if(p)csound->Free(csound, *((void **) p - 1)); } /* reset vdsp */ int vDSP_reset(CSOUND *csound, void *pp){ IGN(pp); #ifdef USE_DOUBLE vDSP_destroy_fftsetupD(csound->vdsp_setup); #else vDSP_destroy_fftsetup(csound->vdsp_setup); #endif csound->vdsp_setup = NULL; vDSP_free(csound, csound->vdsp_buffer); return OK; } /* create setup if setup does not exist */ static void vDSP_setup(CSOUND *csound, int FFTsize){ int M = ConvertFFTSize(csound, FFTsize); if(csound->FFT_max_size < FFTsize){ #ifdef USE_DOUBLE if(csound->vdsp_setup != NULL) vDSP_destroy_fftsetupD(csound->vdsp_setup); csound->vdsp_setup = vDSP_create_fftsetupD(M,kFFTRadix2); #else if(csound->vdsp_setup != NULL) vDSP_destroy_fftsetup(csound->vdsp_setup); csound->vdsp_setup = vDSP_create_fftsetup(M,kFFTRadix2); #endif if(csound->vdsp_buffer != NULL) vDSP_free(csound, csound->vdsp_buffer); csound->vdsp_buffer = vDSP_alloc(csound, FFTsize*(sizeof(MYFLT))); if(csound->FFT_max_size == 0) csound->RegisterResetCallback(csound, (void*) NULL, (int (*)(CSOUND *, void *)) vDSP_reset); csound->FFT_max_size = FFTsize; } } static void vDSP_RealFFT(CSOUND *csound,int FFTsize,MYFLT *sig,FFTDirection d){ #ifdef USE_DOUBLE DSPDoubleSplitComplex tmp; #else DSPSplitComplex tmp; #endif int i,j; MYFLT s; vDSP_setup(csound, FFTsize); tmp.realp = &csound->vdsp_buffer[0]; tmp.imagp = &csound->vdsp_buffer[FFTsize>>1]; for(i=j=0;ivdsp_setup, &tmp, 1, ConvertFFTSize(csound, FFTsize), d); #else vDSP_fft_zrip(csound->vdsp_setup, &tmp, 1, ConvertFFTSize(csound, FFTsize), d); #endif s = (d == -1 ? (MYFLT)(FFTsize) : FL(2.0)); for(i=j=0;ivdsp_setup_fwd); vDSP_DFT_DestroySetupD(csound->vdsp_setup_inv); #else vDSP_DFT_DestroySetup(csound->vdsp_setup_fwd); vDSP_DFT_DestroySetup(csound->vdsp_setup_inv); #endif vDSP_free(csound, csound->vdsp_buffer); return OK; } /* create setup if setup does not exist */ static #ifdef USE_DOUBLE vDSP_DFT_SetupD #else vDSP_DFT_Setup #endif vDSP_setup_New(CSOUND *csound, int FFTsize, int d){ if(csound->vdsp_setup_fwd == NULL || csound->vdsp_setup_inv == NULL){ #ifdef USE_DOUBLE if(d == 1) csound->vdsp_setup_fwd = vDSP_DFT_zrop_CreateSetupD(csound->vdsp_setup_fwd, FFTsize, d); else csound->vdsp_setup_inv = vDSP_DFT_zrop_CreateSetupD(csound->vdsp_setup_inv, FFTsize, d); #else if(d == 1) csound->vdsp_setup_fwd = vDSP_DFT_zrop_CreateSetup(csound->vdsp_setup_fwd, FFTsize, d); else csound->vdsp_setup_inv = vDSP_DFT_zrop_CreateSetup(csound->vdsp_setup_inv, FFTsize, d); #endif } if(csound->FFT_max_size < FFTsize) { vDSP_free(csound, csound->vdsp_buffer); csound->vdsp_buffer = vDSP_alloc(csound, FFTsize*(sizeof(MYFLT))); } if(csound->FFT_max_size == 0) csound->RegisterResetCallback(csound, (void*) NULL, (int (*)(CSOUND *, void *)) vDSP_reset_New); csound->FFT_max_size = FFTsize; return d == 1 ? csound->vdsp_setup_fwd : csound->vdsp_setup_inv; } void vDSP_RealFFT_New(CSOUND *csound,int FFTsize,MYFLT *sig, FFTDirection d){ int i,j; MYFLT s; #ifdef USE_DOUBLE vDSP_DFT_SetupD setup; #else vDSP_DFT_Setup setup; #endif setup = vDSP_setup_New(csound, FFTsize, d); MYFLT *inr = &csound->vdsp_buffer[0]; MYFLT *ini = &csound->vdsp_buffer[FFTsize>>1]; for(i=j=0;isetup[i]) pffft_destroy_setup(csound->setup[i]); pffft_aligned_free(csound->vdsp_buffer); return OK; } /* create setup if setup does not exist */ static void pffft_setup(CSOUND *csound, int FFTsize, int M){ if(csound->FFT_max_size != FFTsize){ if(csound->FFT_max_size == 0) csound->RegisterResetCallback(csound, (void*) NULL, (int (*)(CSOUND *, void *)) pffft_reset); if(csound->setup[M] == NULL) csound->setup[M] = pffft_new_setup(FFTsize,PFFFT_REAL); if(csound->FFT_max_size < FFTsize) { pffft_aligned_free(csound->vdsp_buffer); csound->vdsp_buffer = (MYFLT *) pffft_aligned_malloc(FFTsize*(sizeof(float))); memset(csound->vdsp_buffer,0, FFTsize*(sizeof(float))); csound->FFT_max_size = FFTsize; } } } static void pffft_RealFFT(CSOUND *csound, int FFTsize,MYFLT *sig, int d){ int i; float s, *buf; int M = ConvertFFTSize(csound, FFTsize); pffft_setup(csound, FFTsize, M); buf = (float *)csound->vdsp_buffer; for(i=0;isetup[M], buf,buf,NULL,d); s = (d == PFFFT_BACKWARD ? (MYFLT)FFTsize : FL(1.0)); for(i=0;iids = p->lblblk->prvi; return OK; } int kgoto(CSOUND *csound, GOTO *p) { IGN(csound); CS_PDS = p->lblblk->prvp; return OK; } int icgoto(CSOUND *csound, CGOTO *p) { if (*p->cond) csound->ids = p->lblblk->prvi; return OK; } int kcgoto(CSOUND *csound, CGOTO *p) { IGN(csound); if (*p->cond) CS_PDS = p->lblblk->prvp; return OK; } /* an 'if-then' variant of 'if-goto' */ int ingoto(CSOUND *csound, CGOTO *p) { /* Make sure we have an i-time conditional */ if (p->h.optext->t.intype == 'b' && !*p->cond) csound->ids = p->lblblk->prvi; return OK; } int kngoto(CSOUND *csound, CGOTO *p) { IGN(csound); if (!*p->cond) CS_PDS = p->lblblk->prvp; return OK; } #ifdef VARGS /* an i-rate version that ALWAYS jumps at p-time */ int iingoto(CSOUND *csound, CGOTO *p) { if (!*p->cond) csound->ids = p->lblblk->prvi; return OK; } int kingoto(CSOUND *csound, CGOTO *p) { IGN(csound); CS_PDS = p->lblblk->prvp; return OK; } #endif int timset(CSOUND *csound, TIMOUT *p) { if (UNLIKELY((p->cnt1 = (int32)(*p->idel * CS_EKR + FL(0.5))) < 0L || (p->cnt2 = (int32)(*p->idur * CS_EKR + FL(0.5))) < 0L)) return csoundInitError(csound, Str("negative time period")); return OK; } int timout(CSOUND *csound, TIMOUT *p) { IGN(csound); if (p->cnt1) /* once delay has expired, */ p->cnt1--; else if (--p->cnt2 >= 0L) /* br during idur countdown */ CS_PDS = p->lblblk->prvp; return OK; } int rireturn(CSOUND *csound, LINK *p) { IGN(p); IGN(csound); return OK; } int reinit(CSOUND *csound, GOTO *p) { csound->reinitflag = p->h.insdshead->reinitflag = 1; csound->curip = p->h.insdshead; csound->ids = p->lblblk->prvi; /* now, despite ANSI C warning: */ if (csound->realtime_audio_flag == 0) { while ((csound->ids = csound->ids->nxti) != NULL && (csound->ids->iopadr != (SUBR) rireturn)) (*csound->ids->iopadr)(csound, csound->ids); csound->reinitflag = p->h.insdshead->reinitflag = 0; } else { csound->curip->init_done = 0; } return OK; } int rigoto(CSOUND *csound, GOTO *p) { if (p->h.insdshead->reinitflag) csound->ids = p->lblblk->prvi; return OK; } int tigoto(CSOUND *csound, GOTO *p) /* I-time only, NOP at reinit */ { if (p->h.insdshead->tieflag && !p->h.insdshead->reinitflag) csound->ids = p->lblblk->prvi; return OK; } int tival(CSOUND *csound, EVAL *p) /* I-time only, NOP at reinit */ { IGN(csound); if (!p->h.insdshead->reinitflag) *p->r = p->h.insdshead->tieflag; /* *p->r = (csound->tieflag ? FL(1.0) : FL(0.0)); */ return OK; } int ihold(CSOUND *csound, LINK *p) /* make this note indefinit duration */ { /* called by ihold statmnt at Itime */ IGN(csound); if (!p->h.insdshead->reinitflag) { /* no-op at reinit */ csound->curip->offbet = -1.0; csound->curip->offtim = -1.0; } return OK; } int turnoff(CSOUND *csound, LINK *p) /* terminate the current instrument */ { /* called by turnoff statmt at Ptime */ IGN(csound); INSDS *lcurip = CS_PDS->insdshead; if (p->h.insdshead->actflg) { /* IV - Oct 16 2002: check for subinstr and user opcode */ /* find top level instrument instance */ while (lcurip->opcod_iobufs) lcurip = ((OPCOD_IOBUFS*) lcurip->opcod_iobufs)->parent_ip; xturnoff(csound, lcurip); if (lcurip->xtratim <= 0) while (CS_PDS->nxtp != NULL) CS_PDS = CS_PDS->nxtp; /* loop to last opds */ } return OK; } /* turnoff2 opcode */ int turnoff2(CSOUND *csound, TURNOFF2 *p, int isStringArg) { MYFLT p1; INSDS *ip, *ip2, *nip; int mode, insno, allow_release; if (isStringArg) { p1 = (MYFLT) strarg2insno(csound, ((STRINGDAT *)p->kInsNo)->data, 1); } else if (csound->ISSTRCOD(*p->kInsNo)) { p1 = (MYFLT) strarg2insno(csound, get_arg_string(csound, *p->kInsNo), 1); } else p1 = *(p->kInsNo); if (p1 <= FL(0.0)) return OK; /* not triggered */ insno = (int) p1; if (UNLIKELY(insno < 1 || insno > (int) csound->engineState.maxinsno || csound->engineState.instrtxtp[insno] == NULL)) { return csoundPerfError(csound, p->h.insdshead, Str("turnoff2: invalid instrument number")); } mode = (int) (*(p->kFlags) + FL(0.5)); allow_release = (*(p->kRelease) == FL(0.0) ? 0 : 1); if (UNLIKELY(mode < 0 || mode > 15 || (mode & 3) == 3)) { return csoundPerfError(csound, p->h.insdshead, Str("turnoff2: invalid mode parameter")); } ip = &(csound->actanchor); ip2 = NULL; /* if ((mode & 4) && !ip->p1){ */ /* return csoundPerfError(csound, p->h.insdshead, */ /* Str("turnoff2: invalid instrument number")); */ /* } */ while ((ip = ip->nxtact) != NULL && (int) ip->insno != insno); if (ip == NULL) return OK; do { /* This loop does not terminate in mode=0 */ nip = ip->nxtact; if (((mode & 8) && ip->offtim >= 0.0) || ((mode & 4) && ip->p1.value != p1) || (allow_release && ip->relesing)) { ip = nip; continue; } if (!(mode & 3)) { if (allow_release) { xturnoff(csound, ip); } else { nip = ip->nxtact; xturnoff_now(csound, ip); } } else { ip2 = ip; if ((mode & 3) == 1) break; } ip = nip; } while (ip != NULL && (int) ip->insno == insno); if (ip2 != NULL) { if (allow_release) { xturnoff(csound, ip2); } else { xturnoff_now(csound, ip2); } } if (!p->h.insdshead->actflg) { /* if current note was deactivated: */ while (CS_PDS->nxtp != NULL) CS_PDS = CS_PDS->nxtp; /* loop to last opds */ } return OK; } int turnoff2S(CSOUND *csound, TURNOFF2 *p){ return turnoff2(csound, p, 1); } int turnoff2k(CSOUND *csound, TURNOFF2 *p){ return turnoff2(csound, p, 0); } int loop_l_i(CSOUND *csound, LOOP_OPS *p) { /* if ((indxvar += iincr) < ilimit) igoto l */ *(p->ndxvar) += *(p->incr); if (*(p->ndxvar) < *(p->limit)) csound->ids = p->l->prvi; return OK; } int loop_le_i(CSOUND *csound, LOOP_OPS *p) { /* if ((indxvar += iincr) <= ilimit) igoto l */ *(p->ndxvar) += *(p->incr); if (*(p->ndxvar) <= *(p->limit)) csound->ids = p->l->prvi; return OK; } int loop_g_i(CSOUND *csound, LOOP_OPS *p) { /* if ((indxvar -= idecr) > ilimit) igoto l */ *(p->ndxvar) -= *(p->incr); if (*(p->ndxvar) > *(p->limit)) csound->ids = p->l->prvi; return OK; } int loop_ge_i(CSOUND *csound, LOOP_OPS *p) { /* if ((indxvar -= idecr) >= ilimit) igoto l */ *(p->ndxvar) -= *(p->incr); if (*(p->ndxvar) >= *(p->limit)) csound->ids = p->l->prvi; return OK; } int loop_l_p(CSOUND *csound, LOOP_OPS *p) { /* if ((kndxvar += kincr) < klimit) kgoto l */ IGN(csound); *(p->ndxvar) += *(p->incr); if (*(p->ndxvar) < *(p->limit)) CS_PDS = p->l->prvp; return OK; } int loop_le_p(CSOUND *csound, LOOP_OPS *p) { /* if ((kndxvar += kincr) <= klimit) kgoto l */ IGN(csound); *(p->ndxvar) += *(p->incr); if (*(p->ndxvar) <= *(p->limit)) CS_PDS = p->l->prvp; return OK; } int loop_g_p(CSOUND *csound, LOOP_OPS *p) { /* if ((kndxvar -= kdecr) > klimit) kgoto l */ IGN(csound); *(p->ndxvar) -= *(p->incr); if (*(p->ndxvar) > *(p->limit)) CS_PDS = p->l->prvp; return OK; } int loop_ge_p(CSOUND *csound, LOOP_OPS *p) { /* if ((kndxvar -= kdecr) >= klimit) kgoto l */ IGN(csound); *(p->ndxvar) -= *(p->incr); if (*(p->ndxvar) >= *(p->limit)) CS_PDS = p->l->prvp; return OK; } csound-6.10.0/OOps/midiinterop.c000066400000000000000000000101601321653344700164460ustar00rootroot00000000000000/* midiinterop.c: Copyright (C) 2002 Michael Gogins This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "midiinterop.h" #include "math.h" #define dv127 (FL(1.0)/FL(127.0)) /* aops.c, table for CPSOCTL */ /* extern MYFLT cpsocfrc[]; */ int midinoteoff(CSOUND *csound, MIDINOTEON *p) { IGN(csound); if (!p->h.insdshead->m_chnbp) { return OK; } *p->xkey = p->h.insdshead->m_pitch; *p->xvelocity = p->h.insdshead->m_veloc; return OK; } int midinoteonkey(CSOUND *csound, MIDINOTEON *p) { IGN(csound); if (!p->h.insdshead->m_chnbp) { return OK; } *p->xkey = p->h.insdshead->m_pitch; *p->xvelocity = p->h.insdshead->m_veloc; return OK; } int midinoteoncps(CSOUND *csound, MIDINOTEON *p) { MYFLT octave; int32 longOctave; if (!p->h.insdshead->m_chnbp) { return OK; } octave = (MYFLT)(p->h.insdshead->m_pitch / FL(12.0) + FL(3.0)); longOctave = (int32)(octave * OCTRES); *p->xkey = (MYFLT)CPSOCTL(longOctave); *p->xvelocity = p->h.insdshead->m_veloc; return OK; } int midinoteonoct(CSOUND *csound, MIDINOTEON *p) { MYFLT octave; IGN(csound); if (!p->h.insdshead->m_chnbp) { return OK; } octave = (MYFLT)(p->h.insdshead->m_pitch / FL(12.0) + FL(3.0)); *p->xkey = octave; *p->xvelocity = p->h.insdshead->m_veloc; return OK; } int midinoteonpch(CSOUND *csound, MIDINOTEON *p) { double pitch; double octave; double integer; double fraction; IGN(csound); if (!p->h.insdshead->m_chnbp) { return OK; } pitch = (double)p->h.insdshead->m_pitch; octave = pitch / 12.0 + 3.0; fraction = modf(octave, &integer); fraction *= 0.12; *p->xkey = (MYFLT)(integer + fraction); *p->xvelocity = p->h.insdshead->m_veloc; return OK; } int midipolyaftertouch(CSOUND *csound, MIDIPOLYAFTERTOUCH *p) { MYFLT scale; IGN(csound); if (!p->h.insdshead->m_chnbp) { return OK; } scale = (*p->hhigh - *p->olow) * dv127; *p->xpolyaftertouch = *p->olow + p->h.insdshead->m_chnbp->polyaft[(int)*p->xcontroller] * scale; return OK; } int midicontrolchange(CSOUND *csound, MIDICONTROLCHANGE *p) { MYFLT scale; IGN(csound); if (!p->h.insdshead->m_chnbp) { return OK; } scale = (*p->hhigh - *p->olow) * dv127; *p->xcontrollervalue = *p->olow + p->h.insdshead->m_chnbp->ctl_val[(int)*p->xcontroller] * scale; return OK; } int midiprogramchange(CSOUND *csound, MIDIPROGRAMCHANGE *p) { IGN(csound); if (!p->h.insdshead->m_chnbp) { return OK; } *p->xprogram = p->h.insdshead->m_chnbp->pgmno; return OK; } int midichannelaftertouch(CSOUND *csound, MIDICHANNELAFTERTOUCH *p) { MYFLT scale; IGN(csound); if (!p->h.insdshead->m_chnbp) { return OK; } scale = (*p->hhigh - *p->olow) * dv127; *p->xchannelaftertouch = *p->olow + p->h.insdshead->m_chnbp->aftouch * scale; return OK; } int midipitchbend(CSOUND *csound, MIDIPITCHBEND *p) { MYFLT scale; IGN(csound); if (!p->h.insdshead->m_chnbp) { return OK; } scale = (*p->hhigh - *p->olow) * dv127; *p->xpitchbend = *p->olow + p->h.insdshead->m_chnbp->pchbend * scale; return OK; } int mididefault(CSOUND *csound, MIDIDEFAULT *p) { IGN(csound); if (!p->h.insdshead->m_chnbp) { return OK; } *p->xvalue = *p->xdefault; return OK; } csound-6.10.0/OOps/midiops.c000066400000000000000000000506461321653344700156040ustar00rootroot00000000000000/* midiops.c: Copyright (C) 1995 Barry Vercoe, Gabriel Maldonado, Istvan Varga, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* MIDIOPS.C */ #include "midiops.h" #include #include #include "namedins.h" /* IV - Oct 31 2002 */ #define dv127 (FL(1.0)/FL(127.0)) /* aops.c, table for CPSOCTL */ /*extern MYFLT cpsocfrc[];*/ extern int m_chinsno(CSOUND *csound, int chan, int insno, int reset_ctls); #define MIDI_VALUE(m,field) ((m != (MCHNBLK *) NULL) ? m->field : FL(0.0)) /* * m (=m_chnbp) can easily be NULL (the only place it gets set, as * of 3.484, is in MIDIinsert) so we should check for validity * [added by nicb@axnet.it] */ /* This line has reverted to checking the null pointer as the code in oload * does leaves it null if there is no chanel. The correct fix is to fix that * code so the test is not dynamic, but until I understand it.... */ #define pitchbend_value(m) MIDI_VALUE(m,pchbend) #define MGLOB(x) (((CSOUND*)csound)->midiGlobals->x) int midibset(CSOUND*, MIDIKMB*); /* IV - Oct 31 2002: modified to allow named instruments */ int massign_p(CSOUND *csound, MASSIGN *p) { int chnl = (int)(*p->chnl + FL(0.5)); int resetCtls; int retval = OK; resetCtls = (*p->iresetctls == FL(0.0) ? 0 : 1); if (--chnl >= 0) retval = m_chinsno(csound, chnl, (int) *p->insno, resetCtls); else { for (chnl = 0; chnl < 16; chnl++) { if (m_chinsno(csound, chnl, (int) *p->insno, resetCtls) != OK) retval = NOTOK; } } return retval; } int massign_S(CSOUND *csound, MASSIGNS *p) { int chnl = (int)(*p->chnl + FL(0.5)); int32 instno = 0L; int resetCtls; int retval = OK; if (UNLIKELY((instno = strarg2insno(csound, p->insno->data, 1)) <= 0L)) return NOTOK; resetCtls = (*p->iresetctls == FL(0.0) ? 0 : 1); if (--chnl >= 0) retval = m_chinsno(csound, chnl, (int) instno, resetCtls); else { for (chnl = 0; chnl < 16; chnl++) { if (m_chinsno(csound, chnl, (int) instno, resetCtls) != OK) retval = NOTOK; } } return retval; } int ctrlinit(CSOUND *csound, CTLINIT *p) { int16 chnl = (int16)(*p->chnl - FL(0.5)); int16 nargs = p->INOCOUNT; if (UNLIKELY((nargs & 0x1) == 0)) { return csound->InitError(csound, Str("uneven ctrl pairs")); } else { MCHNBLK *chn; MYFLT **argp = p->ctrls; int16 ctlno, nctls = nargs >> 1; chn = csound->m_chnbp[chnl]; do { ctlno = (int16)**argp++; if (UNLIKELY(ctlno < 0 || ctlno > 127)) { return csound->InitError(csound, Str("illegal ctrl no")); } chn->ctl_val[ctlno] = **argp++; } while (--nctls); return OK; } } int notnum(CSOUND *csound, MIDIKMB *p) /* valid only at I-time */ { *p->r = csound->curip->m_pitch; return OK; } /* cpstmid by G.Maldonado */ int cpstmid(CSOUND *csound, CPSTABLE *p) { FUNC *ftp; MYFLT *func; int notenum = csound->curip->m_pitch; int grade; int numgrades; int basekeymidi; MYFLT basefreq, factor, interval; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->tablenum)) == NULL)) { return csound->InitError(csound, Str("cpstabm: invalid modulator table")); } func = ftp->ftable; numgrades = (int)*func++; interval = *func++; basefreq = *func++; basekeymidi = (int)*func++; if (notenum < basekeymidi) { notenum = basekeymidi - notenum; grade = (numgrades-(notenum % numgrades)) % numgrades; factor = - (MYFLT)(int)((notenum+numgrades-1) / numgrades) ; } else { notenum = notenum - basekeymidi; grade = notenum % numgrades; factor = (MYFLT)(int)(notenum / numgrades); } factor = POWER(interval, factor); *p->r = func[grade] * factor * basefreq; return OK; } int veloc(CSOUND *csound, MIDIMAP *p) /* valid only at I-time */ { *p->r = *p->ilo + csound->curip->m_veloc*(*p->ihi - *p->ilo) * dv127; return OK; } int pchmidi(CSOUND *csound, MIDIKMB *p) { IGN(csound); INSDS *lcurip = p->h.insdshead; double fract, oct, ioct; oct = lcurip->m_pitch / 12.0 + 3.0; fract = modf(oct, &ioct); fract *= 0.12; *p->r = (MYFLT)(ioct + fract); return OK; } int pchmidib(CSOUND *csound, MIDIKMB *p) { INSDS *lcurip = p->h.insdshead; double fract, oct, ioct; MCHNBLK *xxx = csound->curip->m_chnbp; MYFLT bend = pitchbend_value(xxx); oct = (lcurip->m_pitch + (bend * p->scale)) / FL(12.0) + FL(3.0); fract = modf(oct, &ioct); fract *= 0.12; *p->r = (MYFLT)(ioct + fract); return OK; } int pchmidib_i(CSOUND *csound, MIDIKMB *p) { midibset(csound, p); pchmidib(csound, p); return OK; } int octmidi(CSOUND *csound, MIDIKMB *p) { IGN(csound); INSDS *lcurip = p->h.insdshead; *p->r = lcurip->m_pitch / FL(12.0) + FL(3.0); return OK; } int octmidib(CSOUND *csound, MIDIKMB *p) { IGN(csound); INSDS *lcurip = p->h.insdshead; *p->r = (lcurip->m_pitch + (pitchbend_value(lcurip->m_chnbp) * p->scale)) / FL(12.0) + FL(3.0); return OK; } int octmidib_i(CSOUND *csound, MIDIKMB *p) { midibset(csound, p); octmidib(csound, p); return OK; } int cpsmidi(CSOUND *csound, MIDIKMB *p) { INSDS *lcurip = p->h.insdshead; int32 loct; /* loct = (long)(((lcurip->m_pitch + * pitchbend_value(lcurip->m_chnbp) * p->iscal)/ 12.0f + 3.0f) * OCTRES); */ loct = (int32)((lcurip->m_pitch/ FL(12.0) + FL(3.0)) * OCTRES); *p->r = CPSOCTL(loct); return OK; } int icpsmidib(CSOUND *csound, MIDIKMB *p) { INSDS *lcurip = p->h.insdshead; int32 loct; MYFLT bend = pitchbend_value(lcurip->m_chnbp); p->prvbend = bend; loct = (int32)(((lcurip->m_pitch + bend * p->scale) / FL(12.0) + FL(3.0)) * OCTRES); *p->r = CPSOCTL(loct); return OK; } int icpsmidib_i(CSOUND *csound, MIDIKMB *p) { midibset(csound, p); icpsmidib(csound, p); return OK; } int kcpsmidib(CSOUND *csound, MIDIKMB *p) { INSDS *lcurip = p->h.insdshead; MYFLT bend = pitchbend_value(lcurip->m_chnbp); if (bend == p->prvbend || lcurip->relesing) *p->r = p->prvout; else { int32 loct; p->prvbend = bend; loct = (int32)(((lcurip->m_pitch + bend * p->scale) / FL(12.0) + FL(3.0)) * OCTRES); *p->r = p->prvout = CPSOCTL(loct); } return OK; } int ampmidi(CSOUND *csound, MIDIAMP *p) /* convert midi veloc to amplitude */ { /* valid only at I-time */ MYFLT amp; int32 fno; FUNC *ftp; amp = csound->curip->m_veloc / FL(128.0); /* amp = normalised veloc */ if ((fno = (int32)*p->ifn) > 0) { /* if valid ftable, */ if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) == NULL)) return NOTOK; /* use amp as index */ amp = *(ftp->ftable + (int32)(amp * ftp->flen)); } *p->r = amp * *p->imax; /* now scale the output */ return OK; } /* MWB 2/11/97 New optional field to set pitch bend range I also changed each of the xxxmidib opcodes, adding * p->scale */ int midibset(CSOUND *csound, MIDIKMB *p) { MCHNBLK *chn; IGN(csound); chn = p->h.insdshead->m_chnbp; if (*p->iscal > FL(0.0)) p->scale = *p->iscal; else if (chn != NULL) p->scale = chn->pbensens; else p->scale = FL(2.0); /* Start from sane position */ if (chn != NULL) p->prvbend = chn->pchbend; else p->prvbend = FL(0.0); return OK; } int aftset(CSOUND *csound, MIDIKMAP *p) { IGN(csound); p->lo = *p->ilo; p->scale = (*p->ihi - p->lo) * dv127; return OK; } int aftouch(CSOUND *csound, MIDIKMAP *p) { IGN(csound); INSDS *lcurip = p->h.insdshead; *p->r = p->lo + MIDI_VALUE(lcurip->m_chnbp, aftouch) * p->scale; return OK; } int imidictl(CSOUND *csound, MIDICTL *p) { int32 ctlno; if (UNLIKELY((ctlno = (int32)*p->ictlno) < 0 || ctlno > 127)) return csound->InitError(csound, Str("illegal controller number")); else *p->r = MIDI_VALUE(csound->curip->m_chnbp, ctl_val[ctlno]) * (*p->ihi - *p->ilo) * dv127 + *p->ilo; return OK; } int mctlset(CSOUND *csound, MIDICTL *p) { int32 ctlno; if (UNLIKELY((ctlno = (int32)*p->ictlno) < 0 || ctlno > 127)) return csound->InitError(csound, Str("illegal controller number")); else { p->ctlno = ctlno; p->scale = (*p->ihi - *p->ilo) * dv127; p->lo = *p->ilo; } return OK; } int midictl(CSOUND *csound, MIDICTL *p) { IGN(csound); INSDS *lcurip = p->h.insdshead; *p->r = MIDI_VALUE(lcurip->m_chnbp, ctl_val[p->ctlno]) * p->scale + p->lo; return OK; } int imidiaft(CSOUND *csound, MIDICTL *p) { int32 ctlno; if (UNLIKELY((ctlno = (int32)*p->ictlno) < 0 || ctlno > 127)) return csound->InitError(csound, Str("illegal controller number")); else *p->r = MIDI_VALUE(csound->curip->m_chnbp, polyaft[ctlno]) * (*p->ihi - *p->ilo) * dv127 + *p->ilo; return OK; } int maftset(CSOUND *csound, MIDICTL *p) { int32 ctlno; if (UNLIKELY((ctlno = (int32)*p->ictlno) < 0 || ctlno > 127)) return csound->InitError(csound, Str("illegal controller number")); else { p->ctlno = ctlno; p->scale = (*p->ihi - *p->ilo) * dv127; p->lo = *p->ilo; } return OK; } int midiaft(CSOUND *csound, MIDICTL *p) { IGN(csound); INSDS *lcurip = p->h.insdshead; *p->r = MIDI_VALUE(lcurip->m_chnbp, polyaft[p->ctlno]) * p->scale + p->lo; return OK; } /* midichn opcode - get MIDI channel number or 0 for score notes */ /* written by Istvan Varga, May 2002 */ int midichn(CSOUND *csound, MIDICHN *p) { *(p->ichn) = (MYFLT) (csound->GetMidiChannelNumber(p) + 1); return OK; } /* pgmassign - assign MIDI program to instrument */ int pgmassign_(CSOUND *csound, PGMASSIGN *p, int instname) { int pgm, ins, chn; chn = (int)(*p->ichn + 0.5); if (UNLIKELY(chn < 0 || chn > 16)) return csound->InitError(csound, Str("illegal channel number")); /* IV - Oct 31 2002: allow named instruments */ if (instname || csound->ISSTRCOD(*p->inst)) { MYFLT buf[128]; csound->strarg2name(csound, (char*) buf, p->inst, "", 1); ins = (int)strarg2insno(csound, buf, 1); } else ins = (int)(*(p->inst) + FL(0.5)); if (*(p->ipgm) < FL(0.5)) { /* program <= 0: assign all pgms */ if (!chn) { /* on all channels */ for (chn = 0; chn < 16; chn++) for (pgm = 0; pgm < 128; pgm++) csound->m_chnbp[chn]->pgm2ins[pgm] = ins; } else { /* or selected channel only */ chn--; for (pgm = 0; pgm < 128; pgm++) csound->m_chnbp[chn]->pgm2ins[pgm] = ins; } } else { /* program > 0: assign selected pgm */ pgm = (int)(*(p->ipgm) - FL(0.5)); if (UNLIKELY(pgm < 0 || pgm > 127)) { return csound->InitError(csound, Str("pgmassign: invalid program number")); } if (!chn) { /* on all channels */ for (chn = 0; chn < 16; chn++) csound->m_chnbp[chn]->pgm2ins[pgm] = ins; } else { /* or selected channel only */ chn--; csound->m_chnbp[chn]->pgm2ins[pgm] = ins; } } return OK; } int pgmassign_S(CSOUND *csound, PGMASSIGN *p){ return pgmassign_(csound,p,1); } int pgmassign(CSOUND *csound, PGMASSIGN *p){ return pgmassign_(csound,p,0); } int ichanctl(CSOUND *csound, CHANCTL *p) { int32 ctlno, chan = (int32)(*p->ichano - FL(1.0)); if (UNLIKELY(chan < 0 || chan > 15 || csound->m_chnbp[chan] == NULL)) return csound->InitError(csound, Str("illegal channel number")); if (UNLIKELY((ctlno = (int32)*p->ictlno) < 0 || ctlno > 127)) return csound->InitError(csound, Str("illegal controller number")); else *p->r = csound->m_chnbp[chan]->ctl_val[ctlno] * (*p->ihi - *p->ilo) * dv127 + *p->ilo; return OK; } int chctlset(CSOUND *csound, CHANCTL *p) { int32 ctlno, chan = (int32)(*p->ichano - FL(1.0)); if (UNLIKELY(chan < 0 || chan > 15 || csound->m_chnbp[chan] == NULL)) { return csound->InitError(csound, Str("illegal channel number")); } p->chano = chan; if (UNLIKELY((ctlno = (int32)*p->ictlno) < 0 || ctlno > 127)) { return csound->InitError(csound, Str("illegal controller number")); } else { p->ctlno = ctlno; p->scale = (*p->ihi - *p->ilo) * dv127; p->lo = *p->ilo; } return OK; } int chanctl(CSOUND *csound, CHANCTL *p) { *p->r = csound->m_chnbp[p->chano]->ctl_val[p->ctlno] * p->scale + p->lo; return OK; } int ipchbend(CSOUND *csound, MIDIMAP *p) { IGN(csound); *p->r = *p->ilo + (*p->ihi - *p->ilo) * pitchbend_value(p->h.insdshead->m_chnbp); return OK; } int kbndset(CSOUND *csound, MIDIKMAP *p) { IGN(csound); p->lo = *p->ilo; p->scale = *p->ihi - *p->ilo; return OK; } int kpchbend(CSOUND *csound, MIDIKMAP *p) { IGN(csound); INSDS *lcurip = p->h.insdshead; *p->r = p->lo + pitchbend_value(lcurip->m_chnbp) * p->scale; return OK; } int midiin_set(CSOUND *csound, MIDIIN *p) { p->local_buf_index = MGLOB(MIDIINbufIndex) & MIDIINBUFMSK; return OK; } int midiin(CSOUND *csound, MIDIIN *p) { unsigned char *temp; /* IV - Nov 30 2002 */ if (p->local_buf_index != MGLOB(MIDIINbufIndex)) { temp = &(MGLOB(MIDIINbuffer2)[p->local_buf_index++].bData[0]); p->local_buf_index &= MIDIINBUFMSK; *p->status = (MYFLT) (*temp & (unsigned char) 0xf0); *p->chan = (MYFLT) ((*temp & 0x0f) + 1); *p->data1 = (MYFLT) *++temp; *p->data2 = (MYFLT) *++temp; } else *p->status = FL(0.0); return OK; } int pgmin_set(CSOUND *csound, PGMIN *p) { p->local_buf_index = MGLOB(MIDIINbufIndex) & MIDIINBUFMSK; p->watch =(int)*p->ochan; return OK; } int pgmin(CSOUND *csound, PGMIN *p) { unsigned char *temp; if (p->local_buf_index != MGLOB(MIDIINbufIndex)) { int st,ch,d1; temp = &(MGLOB(MIDIINbuffer2)[p->local_buf_index++].bData[0]); st = *temp & (unsigned char) 0xf0; ch = (*temp & 0x0f) + 1; d1 = *++temp; /* d2 = *++temp; */ if (st == 0xC0 && (p->watch==0 || p->watch==ch)) { *p->pgm = (MYFLT)1+d1; *p->chn = (MYFLT)ch; } else { *p->pgm = FL(-1.0); *p->chn = FL(0.0); } p->local_buf_index &= MIDIINBUFMSK; } else { *p->pgm = FL(-1.0); *p->chn = FL(0.0); } return OK; } int ctlin_set(CSOUND *csound, CTLIN *p) { p->local_buf_index = MGLOB(MIDIINbufIndex) & MIDIINBUFMSK; p->watch1 =(int)*p->ochan; p->watch2 =(int)*p->onum; return OK; } int ctlin(CSOUND *csound, CTLIN *p) { unsigned char *temp; if (p->local_buf_index != MGLOB(MIDIINbufIndex)) { int st,ch,d1,d2; temp = &(MGLOB(MIDIINbuffer2)[p->local_buf_index++].bData[0]); st = *temp & (unsigned char) 0xf0; ch = (*temp & 0x0f) + 1; d1 = *++temp; d2 = *++temp; if (st == 0xB0 && (p->watch1==0 || p->watch1==ch) && (p->watch2==0 || p->watch2==d2)) { *p->data = (MYFLT)d1; *p->numb = (MYFLT)d2; *p->chn = (MYFLT)ch; } else { *p->data = FL(-1.0); *p->numb = FL(-1.0); *p->chn = FL(0.0); } p->local_buf_index &= MIDIINBUFMSK; } else { *p->data = FL(-1.0); *p->numb = FL(-1.0); *p->chn = FL(0.0); } return OK; } /* MIDIARP by Rory Walsh, 2016 */ int midiarp_set(CSOUND *csound, MIDIARP *p) /* MIDI Arp - Jan 2017 - RW */ { srand(time(NULL)); p->flag=1, *p->arpMode=0, p->direction=2, p->noteIndex=9; p->maxNumNotes=10, p->noteCnt=0, p->status=0, p->chan=0; p->data1=0, p->data2=0; p->local_buf_index = MGLOB(MIDIINbufIndex) & MIDIINBUFMSK; int cnt; for(cnt=0;cnt<10;cnt++) p->notes[cnt] = 0; return OK; } void sort_notes(int notes[], int n) { int j,i,tmp; for (i = 0; i < n; ++i){ for (j = i + 1; j < n; ++j){ if (notes[i] > notes[j]){ tmp = notes[i]; notes[i] = notes[j]; notes[j] = tmp; } } } } void zeroNoteFromArray(int notes[], int noteNumber, int size) { int i; for(i=0;icurphs; if (phs == 0.0 && p->flag) { p->metroTick = FL(1.0); p->flag = 0; } else if ((phs += *p->arpRate * CS_ONEDKR) >= 1.0) { p->metroTick = FL(1.0); phs -= 1.0; p->flag = 0; } else p->metroTick = FL(0.0); p->curphs = phs; return p->metroTick; } int midiarp(CSOUND *csound, MIDIARP *p) { int i=0; unsigned char *temp; if (p->local_buf_index != MGLOB(MIDIINbufIndex)) { temp = &(MGLOB(MIDIINbuffer2)[p->local_buf_index++].bData[0]); p->local_buf_index &= MIDIINBUFMSK; p->status = (MYFLT) (*temp & (unsigned char) 0xf0); p->chan = (MYFLT) ((*temp & 0x0f) + 1); p->data1 = (MYFLT) *++temp; p->data2 = (MYFLT) *++temp; if(p->status==144 && p->data2>0){ p->notes[p->noteCnt] = p->data1; for(i = 0 ; i < p->maxNumNotes ; i++) p->sortedNotes[i] = p->notes[i]; p->noteCnt = (p->noteCnt>p->maxNumNotes-1 ? p->maxNumNotes-1 : p->noteCnt+1); sort_notes(p->sortedNotes, 10); } else if(p->status==128 || (p->status==144 && p->data2==0)){ zeroNoteFromArray(p->notes, p->data1, p->maxNumNotes); for(i = 0 ; i < p->maxNumNotes ; i++) p->sortedNotes[i] = p->notes[i]; p->noteCnt = (p->noteCnt<0 ? 0 : p->noteCnt-1); sort_notes(p->sortedNotes, p->maxNumNotes); } } else p->status = FL(0.0); if(p->noteCnt != 0) { // only when some note/s are pressed *p->counter = metroCounter(p); if(*p->counter == 1){ if(p->noteIndexmaxNumNotes && p->sortedNotes[p->noteIndex]!=0) *p->noteOut = p->sortedNotes[p->noteIndex]; if(*p->arpMode==0){ //up and down pattern if(p->direction>0) { p->noteIndex = (p->noteIndex < p->maxNumNotes-1 ? p->noteIndex+1 : p->maxNumNotes - p->noteCnt); if(p->noteIndex==p->maxNumNotes-1) p->direction = -2; } else{ p->noteIndex = (p->noteIndex > p->maxNumNotes - p->noteCnt ? p->noteIndex-1 : p->maxNumNotes-1); if(p->noteIndex==p->maxNumNotes-p->noteCnt) p->direction = 2; } } else if(*p->arpMode==1) { //up only pattern p->noteIndex = (p->noteIndex < p->maxNumNotes-1 ? p->noteIndex+1 : p->maxNumNotes - p->noteCnt); }else if(*p->arpMode==2) { //down only pattern p->noteIndex = (p->noteIndex > p->maxNumNotes - p->noteCnt ? p->noteIndex-1 : p->maxNumNotes-1); } else if(*p->arpMode==3) { //random pattern int randIndex = ((rand() % 100)/100.f)*(p->noteCnt); p->noteIndex = p->maxNumNotes-randIndex-1; } else{ csound->Message(csound, Str("Invalid arp mode selected:" " %d. Valid modes are 0, 1, 2, and 3\n"), (int)*p->arpMode); } } } return OK; } csound-6.10.0/OOps/midiout.c000066400000000000000000000414201321653344700156000ustar00rootroot00000000000000/* midiout.c: Copyright (C) 1997 Gabriel Maldonado, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /****************************************/ /** midiout UGs by Gabriel Maldonado **/ /****************************************/ /* Some modifications by JPff for general use */ #include #include "csoundCore.h" #include "midiout.h" #define MGLOB(x) (((CSOUND*)csound)->midiGlobals->x) #define NUMCHN (16) #define EXTRA_TIME (1) extern void openMIDIout(CSOUND *); /* static MYFLT invkr; */ void note_on(CSOUND *, int chan, int num, int vel); void note_off(CSOUND *, int chan, int num, int vel); void control_change(CSOUND *, int chan, int num, int value); void after_touch(CSOUND *, int chan, int value); void program_change(CSOUND *, int chan, int num); void pitch_bend(CSOUND *, int chan, int lsb, int msb); void poly_after_touch(CSOUND *, int chan, int note_num, int value); void send_midi_message(CSOUND *, int status, int data1, int data2); int release_set(CSOUND *csound, REL *p) { IGN(csound); if (p->h.insdshead->xtratim < EXTRA_TIME) /* if not initialised by another opcode */ p->h.insdshead->xtratim = EXTRA_TIME; return OK; } int release(CSOUND *csound, REL *p) { IGN(csound); if (p->h.insdshead->relesing) *p->r = FL(1.0); /* TRUE */ else *p->r = FL(0.0); /* FALSE */ return OK; } int xtratim(CSOUND *csound, XTRADUR *p) { IGN(csound); int *xtra = &(p->h.insdshead->xtratim); int tim = (int)(*p->extradur * p->h.insdshead->ekr); if (*xtra < tim) /* gab-a5 revised */ *xtra = tim; return OK; } int mclock_set(CSOUND *csound, MCLOCK *p) { IGN(csound); p->period= CS_EKR / *p->freq; p->clock_tics = p->period; p->beginning_flag = TRUE; return OK; } int mclock(CSOUND *csound, MCLOCK *p) { if (UNLIKELY(p->beginning_flag)) { /* first time */ send_midi_message(csound, 0xF8, 0, 0); /* clock message */ p->beginning_flag=FALSE; return OK; } else if ((MYFLT) CS_KCNT > p->clock_tics) { send_midi_message(csound, 0xF8, 0, 0); /* clock message */ p->clock_tics += p->period; } return OK; } int mrtmsg(CSOUND *csound, MRT *p) { switch ((int)*p->message) { case 0: send_midi_message(csound, 0xFC, 0, 0); /* stop */ break; case 1: send_midi_message(csound, 0xFA, 0, 0); /* start */ break; case 2: send_midi_message(csound, 0xFB, 0, 0); /* continue */ break; case -1: send_midi_message(csound, 0xFF, 0, 0); /* system_reset */ break; case -2: send_midi_message(csound, 0xFE, 0, 0); /* active_sensing */ break; default: return csound->InitError(csound, Str("illegal mrtmsg argument")); } return OK; } int iout_on(CSOUND *csound, OUT_ON *p) { note_on(csound, (int)*p->ichn-1,(int)*p->inum,(int)*p->ivel); return OK; } int iout_off(CSOUND *csound, OUT_ON *p) { note_off(csound, (int)*p->ichn-1,(int)*p->inum,(int)*p->ivel); return OK; } int iout_on_dur_set(CSOUND *csound, OUT_ON_DUR *p) { int temp; if (p->h.insdshead->xtratim < EXTRA_TIME) /* if not initialised by another opcode */ p->h.insdshead->xtratim = EXTRA_TIME; p->chn = (temp = abs((int)*p->ichn-1)) < NUMCHN ? temp : NUMCHN-1; p->num = (temp = abs((int)*p->inum)) < 128 ? temp : 127; p->vel = (temp = abs((int)*p->ivel)) < 128 ? temp : 127; note_on(csound, p->chn,p->num, p->vel); p->istart_time = (MYFLT)CS_KCNT * CS_ONEDKR; p->fl_expired = FALSE; p->fl_extra_dur = FALSE; return OK; } int iout_on_dur(CSOUND *csound, OUT_ON_DUR *p) { if (!(p->fl_expired)) { MYFLT actual_dur = (MYFLT) CS_KCNT * CS_ONEDKR - p->istart_time; MYFLT dur = *p->idur; if (dur < actual_dur) { p->fl_expired = TRUE; note_off(csound, p->chn, p->num, p->vel); } else if (p->h.insdshead->relesing) { p->fl_expired = TRUE; note_off(csound, p->chn, p->num, p->vel); } } return OK; } int iout_on_dur2(CSOUND *csound, OUT_ON_DUR *p) { if (!(p->fl_expired)) { MYFLT actual_dur = (MYFLT)CS_KCNT * CS_ONEDKR - p->istart_time; MYFLT dur = *p->idur; if (dur < actual_dur) { p->fl_expired = TRUE; note_off(csound, p->chn, p->num, p->vel); } else if (p->h.insdshead->relesing || p->fl_extra_dur) { if (!p->fl_extra_dur && dur > actual_dur) { p->h.insdshead->offtim += dur - actual_dur+ FL(1.0); p->h.insdshead->relesing =0; p->fl_extra_dur=TRUE; } else if (dur <= actual_dur) { note_off(csound, p->chn, p->num, p->vel); } } } return OK; } int moscil_set(CSOUND *csound, MOSCIL *p) { IGN(csound); if (p->h.insdshead->xtratim < EXTRA_TIME) /* if not initialised by another opcode */ p->h.insdshead->xtratim = EXTRA_TIME; p->istart_time = (MYFLT)CS_KCNT * CS_ONEDKR; p->fl_first_note = TRUE; p->fl_note_expired = TRUE; p->fl_end_note = FALSE; return OK; } int moscil(CSOUND *csound, MOSCIL *p) { if (p->fl_first_note) { p->fl_first_note = FALSE; goto first_note; } if (!(p->fl_note_expired)) { if (p->h.insdshead->relesing) { p->fl_note_expired = TRUE; p->fl_end_note = TRUE; note_off(csound, p->last_chn, p->last_num, p->last_vel); } else if (p->last_dur < (MYFLT)CS_KCNT * CS_ONEDKR - p->istart_time) { p->fl_note_expired = TRUE; note_off(csound, p->last_chn, p->last_num, p->last_vel); } } else { if (!p->fl_end_note && p->last_pause + p->last_dur < (MYFLT)CS_KCNT * CS_ONEDKR - p->istart_time && !(p->h.insdshead->relesing)) { MYFLT ftemp; p->istart_time = p->istart_time + p->last_pause + p->last_dur; p->last_dur = /* dur must be at least 1/kr */ (ftemp = *p->kdur) > 0 ? ftemp : CS_ONEDKR; p->last_pause = (ftemp = *p->kpause) > 0 ? ftemp : CS_ONEDKR; first_note: { int temp; p->last_chn = (temp = abs((int)*p->kchn-1)) < NUMCHN ? temp : NUMCHN-1; p->last_num = (temp = abs((int)*p->knum)) < 128 ? temp : 127; p->last_vel = (temp = abs((int)*p->kvel)) < 128 ? temp : 127; } p->fl_note_expired = FALSE; note_on(csound, p->last_chn, p->last_num, p->last_vel); } } return OK; } int kvar_out_on_set(CSOUND *csound, KOUT_ON *p) { IGN(csound); if (p->h.insdshead->xtratim < EXTRA_TIME) /* if not initialised by another opcode */ p->h.insdshead->xtratim = EXTRA_TIME; p->fl_first_note = TRUE; return OK; } int kvar_out_on(CSOUND *csound, KOUT_ON *p) { if (p->fl_first_note) { int temp; p->last_chn = (temp = abs((int)*p->kchn-1)) < NUMCHN ? temp : NUMCHN-1; p->last_num = (temp = abs((int)*p->knum)) < 128 ? temp : 127; p->last_vel = (temp = abs((int)*p->kvel)) < 128 ? temp : 127; p->fl_first_note = FALSE; p->fl_note_expired = FALSE; note_on(csound, p->last_chn, p->last_num, p->last_vel); } else if (p->fl_note_expired) return OK; else { if (p->h.insdshead->relesing) { note_off(csound, p->last_chn, p->last_num, p->last_vel); p->fl_note_expired = TRUE; } else { int temp; int curr_chn = (temp = abs((int)*p->kchn-1)) < NUMCHN ? temp : NUMCHN-1; int curr_num = (temp = abs((int)*p->knum)) < 128 ? temp : 127; int curr_vel = (temp = abs((int)*p->kvel)) < 128 ? temp : 127; if ( p->last_chn != curr_chn || p->last_num != curr_num || p->last_vel != curr_vel ) { note_off(csound, p->last_chn, p->last_num, p->last_vel); p->last_chn = curr_chn; p->last_num = curr_num; p->last_vel = curr_vel; note_on(csound, curr_chn, curr_num, curr_vel); } } } return OK; } int out_controller (CSOUND *csound, OUT_CONTR *p) { if (!(p->h.insdshead->prvinstance)) { /* if prev instance already allocated in the same MIDI chan */ int value; MYFLT min = *p->min; value = (int)((*p->value - min) * FL(127.0) / (*p->max - min)); value = (value < 128) ? value : 127; value = (value > -1) ? value : 0; if (value != p->last_value || *p->chn != p->lastchn || *p->num != p->lastctrl) { /* csound->Message(csound, "out contr value: %d\n", value); */ control_change(csound, (int)*p->chn-1,(int)*p->num ,value); p->last_value = value; p->lastchn = *p->chn; p->lastctrl = *p->num; } } return OK; } int out_aftertouch (CSOUND *csound, OUT_ATOUCH *p) { if (!(p->h.insdshead->prvinstance)) { /* if prev instance already allocated in the same MIDI chan */ int value; MYFLT min = *p->min; value = (int)((*p->value - min) * FL(127.0) / (*p->max - min)); value = value < 128 ? value : 127; value = value > -1 ? value : 0; if (value != p->last_value || *p->chn != p->lastchn) { after_touch(csound, (int)*p->chn-1, value); p->last_value = value; p->lastchn = *p->chn; } } return OK; } int out_poly_aftertouch (CSOUND *csound, OUT_POLYATOUCH *p) { int value; MYFLT min = *p->min; value = (int)((*p->value - min) * FL(127.0) / (*p->max - min)); value = value < 128 ? value : 127; value = value > -1 ? value : 0; if (value != p->last_value || *p->chn != p->lastchn || *p->num != p->lastctrl) { poly_after_touch(csound, (int)*p->chn-1, (int)*p->num, value); p->last_value = value; p->lastchn = *p->chn; p->lastctrl = *p->num; } return OK; } int out_progchange (CSOUND *csound, OUT_PCHG *p) { if (!(p->h.insdshead->prvinstance)) { /* if prev instance already allocated in the same MIDI chan */ int prog_num; MYFLT min = *p->min; prog_num = (int)((*p->prog_num - min) * FL(127.0) / (*p->max - min)); prog_num = prog_num < 128 ? prog_num : 127; prog_num = prog_num > -1 ? prog_num : 0; if (prog_num != p->last_prog_num || *p->chn != p->lastchn) { program_change(csound, (int)*p->chn-1, prog_num); p->last_prog_num = prog_num; p->lastchn = *p->chn; } } return OK; } int out_controller14 (CSOUND *csound, OUT_CONTR14 *p) { if (!(p->h.insdshead->prvinstance)) { /* if prev instance already allocated in the same MIDI chan */ int value; MYFLT min = *p->min; value = (int)((*p->value - min) * FL(16383.0) / (*p->max - min)); value = (value < 16384) ? value : 16383; value = (value > -1) ? value : 0; if (value != p->last_value || *p->chn != p->lastchn || *p->msb_num != p->lastctrl) { unsigned int msb = value >> 7; unsigned int lsb = value & 0x7F; csound->Warning(csound, Str("out contr14 msb:%x lsb:%x\n"), msb, lsb); control_change(csound, (int)*p->chn-1, (int)*p->msb_num, msb); control_change(csound, (int)*p->chn-1, (int)*p->lsb_num, lsb); p->last_value = value; p->lastchn = *p->chn; p->lastctrl = *p->msb_num; } } return OK; } int out_pitch_bend(CSOUND *csound, OUT_PB *p) { if (p->h.insdshead->prvinstance) { /* if prev instance already allocated in the same MIDI chan */ return OK; } else { int value; MYFLT min = *p->min; value = (int)((*p->value - min) * FL(16383.0) / (*p->max - min)); value = (value < 16384 ? value : 16383); value = (value > -1 ? value : 0); if (value != p->last_value || *p->chn != p->lastchn ) { unsigned int msb = value >> 7; unsigned int lsb = value & 0x7F; pitch_bend(csound, (int)*p->chn - 1, lsb, msb); p->last_value = value; p->lastchn = *p->chn; } } return OK; } int kon2_set(CSOUND *csound, KON2 *p) { IGN(csound); /* if not initialised by another opcode */ if (p->h.insdshead->xtratim < EXTRA_TIME) p->h.insdshead->xtratim = EXTRA_TIME; /*p->fl_first_note = TRUE;*/ p->fl_note_expired = FALSE; return OK; } int kon2(CSOUND *csound, KON2 *p) { /* if (p->fl_first_note) { register int temp; p->last_chn = (temp = abs((int)*p->kchn)) < NUMCHN ? temp : NUMCHN-1; p->last_num = (temp = abs((int)*p->knum)) < 128 ? temp : 127; p->last_vel = (temp = abs((int)*p->kvel)) < 128 ? temp : 127; p->fl_first_note = FALSE; p->fl_note_expired = FALSE; note_on(csound, p->last_chn, p->last_num, p->last_vel); } */ /*else */ if (p->fl_note_expired) return OK; else { if (p->h.insdshead->relesing) { note_off(csound, p->last_chn,p->last_num,p->last_vel); p->fl_note_expired = TRUE; } else { int temp; int curr_chn = (temp = abs((int)*p->kchn-1)) <= NUMCHN ? temp : NUMCHN; int curr_num = (temp = abs((int)*p->knum)) < 128 ? temp : 127; int curr_vel = (temp = abs((int)*p->kvel)) < 128 ? temp : 127; if ((int)(*p->ktrig +FL(0.5)) != 0 )/* i.e. equal to 1 */ /* p->last_chn != curr_chn || p->last_num != curr_num || p->last_vel != curr_vel ) */ { note_off(csound, p->last_chn, p->last_num, p->last_vel); p->last_chn = curr_chn; p->last_num = curr_num; p->last_vel = curr_vel; note_on(csound, curr_chn, curr_num, curr_vel); } } } return OK; } int midiout(CSOUND *csound, MIDIOUT *p) /*gab-A6 fixed*/ { int st, ch, d1, d2; st = (int)(*p->in_type + FL(0.5)); if (!st) return OK; st = (st & 0x70) | 0x80; ch = (int)(*p->in_chan - FL(0.5)) & 0x0F; d1 = (int)(*p->in_dat1 + FL(0.5)) & 0x7F; d2 = (int)(*p->in_dat2 + FL(0.5)) & 0x7F; send_midi_message(csound, st | ch, d1, d2); return OK; } int nrpn(CSOUND *csound, NRPN *p) { int chan = (int)*p->chan-1, parm = (int)*p->parm_num; int value = (int)*p->parm_value; if (chan != p->old_chan || parm != p->old_parm || value != p->old_value) { int status = 176 | chan; int parm_msb = parm >> 7; int parm_lsb = parm & 0x7f; int value_msb = (value + 8192) >> 7; int value_lsb = (value + 8192) % 128; send_midi_message(csound, status, 99, parm_msb); send_midi_message(csound, status, 98, parm_lsb); send_midi_message(csound, status, 6, value_msb); send_midi_message(csound, status, 38, value_lsb); p->old_chan = chan; p->old_parm = parm; p->old_value = value; } return OK; } int mdelay_set(CSOUND *csound, MDELAY *p) { IGN(csound); p->read_index = 0; p->write_index = 0; memset(p->status, 0, DELTAB_LENGTH); return OK; } int mdelay(CSOUND *csound, MDELAY *p) /*gab-A6 fixed*/ { int read_index = p->read_index % DELTAB_LENGTH; int write_index = p->write_index % DELTAB_LENGTH; MYFLT present_time = CS_KCNT * CS_ONEDKR; if (((int)*p->in_status == 0x90 || (int)*p->in_status == 0x80)) { p->status[write_index] = (int)*p->in_status; p->chan[write_index] = (int)*p->in_chan-1; p->dat1[write_index] = (int)*p->in_dat1; p->dat2[write_index] = (int)*p->in_dat2; p->time[write_index] = present_time; (p->write_index)++; } if (p->status[read_index] && p->time[read_index] + *p->kdelay <= present_time) { int number = p->dat1[read_index]; int velocity = p->dat2[read_index]; send_midi_message(csound, p->status[read_index] | p->chan[read_index], ((number > 127) ? 127 : number), ((velocity > 127) ? 127 : velocity)); (p->read_index)++; } return OK; } csound-6.10.0/OOps/mxfft.c000066400000000000000000000607341321653344700152630ustar00rootroot00000000000000/* mxfft.c: Copyright (C) 2002 Trevor Wishart, Keith Henderson This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* This program converted from the FORTRAN routines by Singleton in * Section 1.4 of "Programs for Digital Signal Processing", IEEE Press, 1979. * Conversion by Trevor Wishart and Keith Henderson, York Univ. */ /* static char *rcsid = "$Id$"; */ /* * $Log$ * Revision 1.15 2008-12-04 14:55:04 jpff * Branch prediction * * Revision 1.14 2005/08/13 14:44:37 istvanv * Minor code changes * * Revision 1.13 2005/08/12 19:01:23 istvanv * Renamed ENVIRON to CSOUND * * Revision 1.12 2005/08/10 09:57:07 istvanv * Use CSOUND* type for Csound instance pointers instead of void* * * Revision 1.11 2005/07/15 10:13:28 istvanv * Removed cs.h * * Revision 1.10 2005/06/05 16:36:24 istvanv * Minor code improvements * * Revision 1.9 2005/06/05 13:07:08 istvanv * Added mxfft.c functions to API * * Revision 1.8 2005/05/28 13:00:02 istvanv * Minor code changes (tabs etc.) * * Revision 1.7 2005/04/17 17:56:25 jpff * Warnings * * Revision 1.6 2005/02/18 16:21:14 istvanv * added csound pointer to csound->Malloc, auxalloc, and other functions * * Revision 1.5 2005/01/27 19:22:50 istvanv * Merged changes from 4.24.1, including new localization system, * timers, and allow use of underscore character in opcode names * * Revision 1.4 2004/09/27 05:52:31 jpff * Minor coding * * Revision 1.3 2004/06/07 11:33:09 jpff * line endings * * Revision 1.2 2004/05/31 15:53:06 jpff * Removing warnings mainly * * Revision 1.1.1.1 2003/06/19 11:11:53 jpff * Initial upload of sources * * Revision 1.2 2003/05/21 11:31:06 jpff * Added Copyright notices * * Revision 3.4 1994/10/31 17:37:28 martin * Starting with rcs * */ #include "csoundCore.h" #include #include static void fft_(CSOUND *,MYFLT *, MYFLT *, int, int, int, int); static void fftmx(MYFLT *, MYFLT *, int, int, int, int, int, int*, MYFLT *, MYFLT *, MYFLT *, MYFLT *, int *, int[]); static void reals_(CSOUND *,MYFLT *, MYFLT *, int, int); /* *----------------------------------------------------------------------- * subroutine: fft * multivariate complex fourier transform, computed in place * using mixed-radix fast fourier transform algorithm. *----------------------------------------------------------------------- * * this is the call from C: * fft_(anal,banal,&one,&N2,&one,&mtwo); * CHANGED TO:- * fft_(csound,anal,banal,one,N2,one,mtwo); */ static void fft_(CSOUND *csound, MYFLT *a, MYFLT *b, int nseg, int n, int nspn, int isn) /* *a, pointer to array 'anal' */ /* *b; pointer to array 'banal' */ { int32 nfac[32]; /* These are one bigger than needed */ /* because wish to use Fortran array */ /* index which runs 1 to n, not 0 to n */ int32 m = 0, k, kt, jj, j, nf, ntot, maxf, maxp=-1; /* work space pointers */ void *buf; MYFLT *at, *ck, *bt, *sk; int *np; /* reduce the pointers to input arrays - by doing this, FFT uses FORTRAN indexing but retains compatibility with C arrays */ a--; b--; /* * determine the factors of n */ k = nf = abs(n); if (nf==1) return; nspn = abs(nf*nspn); ntot = abs(nspn*nseg); for (m=0; !(k%16); nfac[++m]=4,k/=16); assert(m<16); for (j=3,jj=9; jj<=k; j+=2,jj=j*j) for (; !(k%jj); nfac[++m]=j,k/=jj); if (k<=4) { kt = m; nfac[m+1] = k; if (k != 1) m++; } else { if (k%4==0) { nfac[++m]=2; k/=4; } kt = m; maxp = (kt+kt+2 > k-1 ? kt+kt+2 : k-1); for (j=2; j<=k; j=1+((j+1)/2)*2) if (k%j==0) { nfac[++m]=j; k/=j; } } if (m <= kt+1) maxp = m + kt + 1; if (UNLIKELY(m+kt > 15)) { csound->Warning(csound, Str("\nerror - fft parameter n has " "more than 15 factors : %d"), n); return; } if (kt!=0) { j = kt; while (j) nfac[++m]=nfac[j--]; } maxf = nfac[m-kt]; if (kt > 0 && maxf Calloc(csound, sizeof(MYFLT) * 4 * maxf + sizeof(int) * maxp); at = (MYFLT*) buf; ck = (MYFLT*) at + (int) maxf; bt = (MYFLT*) ck + (int) maxf; sk = (MYFLT*) bt + (int) maxf; np = (int*) ((void*) ((MYFLT*) sk + (int) maxf)); /* decrement pointers to allow FORTRAN type usage in fftmx */ at--; bt--; ck--; sk--; np--; /* call fft driver */ fftmx(a, b, ntot, nf, nspn, isn, m, &kt, at, ck, bt, sk, np, nfac); /* release working storage before returning - assume no problems */ csound->Free(csound,buf); } /* *----------------------------------------------------------------------- * subroutine: fftmx * called by subroutine 'fft' to compute mixed-radix fourier transform *----------------------------------------------------------------------- */ static void fftmx(MYFLT *a, MYFLT *b, int ntot, int n, int nspan, int isn, int m, int *kt, MYFLT *at, MYFLT *ck, MYFLT *bt, MYFLT *sk, int *np, int nfac[]) { int i,inc, j,jc,jf, jj, k, k1, k2, k3=0, k4, kk,klim,ks,kspan, kspnn, lim, maxf,mm, nn,nt; double aa, aj, ajm, ajp, ak, akm, akp, bb, bj, bjm, bjp, bk, bkm, bkp, c1, c2=0, c3=0, c72, cd, dr, rad, sd, s1, s2=0, s3=0, s72, s120; double xx; /****** ADDED APRIL 1991 *********/ inc=abs(isn); nt = inc*ntot; ks = inc*nspan; /******************* REPLACED MARCH 29: *********************** rad = atan(1.0); **************************************************************/ rad = 0.785398163397448278900; /******************* REPLACED MARCH 29: *********************** s72 = rad/0.625; c72 = cos(s72); s72 = sin(s72); **************************************************************/ c72 = 0.309016994374947451270; s72 = 0.951056516295153531190; /******************* REPLACED MARCH 29: *********************** s120 = sqrt(0.75); **************************************************************/ s120 = 0.866025403784438707600; /* scale by 1/n for isn > 0 ( reverse transform ) */ if (isn < 0) { s72 = -s72; s120 = -s120; rad = -rad;} else { ak = 1.0/(double)n; for (j=1; j<=nt;j += inc) { a[j] *= (MYFLT)ak; b[j] *= (MYFLT)ak; } } kspan = ks; nn = nt - inc; jc = ks/n; /* sin, cos values are re-initialised each lim steps */ lim = 32; klim = lim * jc; i = 0; jf = 0; maxf = m - (*kt); maxf = nfac[maxf]; if ((*kt) > 0 && maxf < nfac[*kt]) maxf = nfac[*kt]; /* * compute Fourier transform */ lbl40: dr = (8.0 * (double)jc)/((double)kspan); /*************************** APRIL 1991 POW & POW2 not WORKING.. REPLACE ******* cd = 2.0 * (pow2 ( sin(0.5 * dr * rad)) ); *******************************************************************************/ xx = sin(0.5 * dr * rad); cd = 2.0 * xx * xx; sd = sin(dr * rad); kk = 1; if (nfac[++i]!=2) goto lbl110; /* * transform for factor of 2 (including rotation factor) */ kspan /= 2; k1 = kspan + 2; do { do { k2 = kk + kspan; ak = a[k2]; bk = b[k2]; a[k2] = (a[kk]) - (MYFLT)ak; b[k2] = (b[kk]) - (MYFLT)bk; a[kk] = (a[kk]) + (MYFLT)ak; b[kk] = (b[kk]) + (MYFLT)bk; kk = k2 + kspan; } while (kk <= nn); kk -= nn; } while (kk <= jc); if (kk > kspan) goto lbl350; lbl60: c1 = 1.0 - cd; s1 = sd; mm = (k1/2 < klim ? k1/2 :klim); goto lbl80; lbl70: ak = c1 - ((cd*c1)+(sd*s1)); s1 = ((sd*c1)-(cd*s1)) + s1; c1 = ak; lbl80: do { do { k2 = kk + kspan; ak = a[kk] - a[k2]; bk = b[kk] - b[k2]; a[kk] = a[kk] + a[k2]; b[kk] = b[kk] + b[k2]; a[k2] = (MYFLT)((c1 * ak) - (s1 * bk)); b[k2] = (MYFLT)((s1 * ak) + (c1 * bk)); kk = k2 + kspan; } while (kk < nt); k2 = kk - nt; c1 = -c1; kk = k1 - k2; } while (kk > k2); kk += jc; if (kk <= mm) goto lbl70; if (kk < k2) goto lbl90; k1 += (inc + inc); kk = ((k1-kspan)/2) + jc; if (kk <= (jc+jc)) goto lbl60; goto lbl40; lbl90: s1 = ((double)((kk-1)/jc)) * dr * rad; c1 = cos(s1); s1 = sin(s1); mm = (k1/2 < mm+klim ? k1/2 : mm+klim); goto lbl80; /* * transform for factor of 3 (optional code) */ lbl100: k1 = kk + kspan; k2 = k1 + kspan; ak = a[kk]; bk = b[kk]; aj = a[k1] + a[k2]; bj = b[k1] + b[k2]; a[kk] = (MYFLT)(ak + aj); b[kk] = (MYFLT)(bk + bj); ak += (-0.5 * aj); bk += (-0.5 * bj); aj = (a[k1] - a[k2]) * s120; bj = (b[k1] - b[k2]) * s120; a[k1] = (MYFLT)(ak - bj); b[k1] = (MYFLT)(bk + aj); a[k2] = (MYFLT)(ak + bj); b[k2] = (MYFLT)(bk - aj); kk = k2 + kspan; if (kk < nn) goto lbl100; kk -= nn; if (kk <= kspan) goto lbl100; goto lbl290; /* * transform for factor of 4 */ lbl110: if (nfac[i] != 4) goto lbl230; kspnn = kspan; kspan = kspan/4; lbl120: c1 = 1.0; s1 = 0; mm = (kspan < klim ? kspan : klim); goto lbl150; lbl130: c2 = c1 - ((cd*c1)+(sd*s1)); s1 = ((sd*c1)-(cd*s1)) + s1; /* * the following three statements compensate for truncation * error. if rounded arithmetic is used, substitute * c1=c2 * * c1 = (0.5/(pow2(c2)+pow2(s1))) + 0.5; * s1 = c1*s1; * c1 = c1*c2; */ c1 = c2; lbl140: c2 = (c1 * c1) - (s1 * s1); s2 = c1 * s1 * 2.0; c3 = (c2 * c1) - (s2 * s1); s3 = (c2 * s1) + (s2 * c1); lbl150: k1 = kk + kspan; k2 = k1 + kspan; k3 = k2 + kspan; akp = a[kk] + a[k2]; akm = a[kk] - a[k2]; ajp = a[k1] + a[k3]; ajm = a[k1] - a[k3]; a[kk] = (MYFLT)(akp + ajp); ajp = akp - ajp; bkp = b[kk] + b[k2]; bkm = b[kk] - b[k2]; bjp = b[k1] + b[k3]; bjm = b[k1] - b[k3]; b[kk] = (MYFLT)(bkp + bjp); bjp = bkp - bjp; if (isn < 0) goto lbl180; akp = akm - bjm; akm = akm + bjm; bkp = bkm + ajm; bkm = bkm - ajm; if (s1 == 0.0) goto lbl190; lbl160: a[k1] = (MYFLT)((akp*c1) - (bkp*s1)); b[k1] = (MYFLT)((akp*s1) + (bkp*c1)); a[k2] = (MYFLT)((ajp*c2) - (bjp*s2)); b[k2] = (MYFLT)((ajp*s2) + (bjp*c2)); a[k3] = (MYFLT)((akm*c3) - (bkm*s3)); b[k3] = (MYFLT)((akm*s3) + (bkm*c3)); kk = k3 + kspan; if (kk <= nt) goto lbl150; lbl170: kk -= (nt - jc); if (kk <= mm) goto lbl130; if (kk < kspan) goto lbl200; kk -= (kspan - inc); if (kk <= jc) goto lbl120; if (kspan==jc) goto lbl350; goto lbl40; lbl180: akp = akm + bjm; akm = akm - bjm; bkp = bkm - ajm; bkm = bkm + ajm; if (s1 != 0.0) goto lbl160; lbl190: a[k1] = (MYFLT)akp; b[k1] = (MYFLT)bkp; a[k2] = (MYFLT)ajp; b[k2] = (MYFLT)bjp; a[k3] = (MYFLT)akm; b[k3] = (MYFLT)bkm; kk = k3 + kspan; if (kk <= nt) goto lbl150; goto lbl170; lbl200: s1 = ((double)((kk-1)/jc)) * dr * rad; c1 = cos(s1); s1 = sin(s1); mm = (kspan < mm+klim ? kspan : mm+klim); goto lbl140; /* * transform for factor of 5 (optional code) */ lbl210: c2 = (c72*c72) - (s72*s72); s2 = 2.0 * c72 * s72; lbl220: k1 = kk + kspan; k2 = k1 + kspan; k3 = k2 + kspan; k4 = k3 + kspan; akp = a[k1] + a[k4]; akm = a[k1] - a[k4]; bkp = b[k1] + b[k4]; bkm = b[k1] - b[k4]; ajp = a[k2] + a[k3]; ajm = a[k2] - a[k3]; bjp = b[k2] + b[k3]; bjm = b[k2] - b[k3]; aa = a[kk]; bb = b[kk]; a[kk] = (MYFLT)(aa + akp + ajp); b[kk] = (MYFLT)(bb + bkp + bjp); ak = (akp*c72) + (ajp*c2) + aa; bk = (bkp*c72) + (bjp*c2) + bb; aj = (akm*s72) + (ajm*s2); bj = (bkm*s72) + (bjm*s2); a[k1] = (MYFLT)(ak - bj); a[k4] = (MYFLT)(ak + bj); b[k1] = (MYFLT)(bk + aj); b[k4] = (MYFLT)(bk - aj); ak = (akp*c2) + (ajp*c72) + aa; bk = (bkp*c2) + (bjp*c72) + bb; aj = (akm*s2) - (ajm*s72); bj = (bkm*s2) - (bjm*s72); a[k2] = (MYFLT)(ak - bj); a[k3] = (MYFLT)(ak + bj); b[k2] = (MYFLT)(bk + aj); b[k3] = (MYFLT)(bk - aj); kk = k4 + kspan; if (kk < nn) goto lbl220; kk -= nn; if (kk <= kspan) goto lbl220; goto lbl290; /* * transform for odd factors */ lbl230: k = nfac[i]; kspnn = kspan; kspan /= k; if (k==3) goto lbl100; if (k==5) goto lbl210; if (k==jf) goto lbl250; jf = k; s1 = rad/(((double)(k))/8.0); c1 = cos(s1); s1 = sin(s1); ck[jf] = FL(1.0); sk[jf] = FL(0.0); for (j=1; j jf) jj -= jf; } while (k < jf); k = jf - j; a[k1] = (MYFLT)(ak - bj); b[k1] = (MYFLT)(bk + aj); a[k2] = (MYFLT)(ak + bj); b[k2] = (MYFLT)(bk - aj); j++; if (j < k) goto lbl270; kk += kspnn; if (kk <= nn) goto lbl250; kk -= nn; if (kk<=kspan) goto lbl250; /* * multiply by rotation factor (except for factors of 2 and 4) */ lbl290: if (i==m) goto lbl350; kk = jc + 1; lbl300: c2 = 1.0 - cd; s1 = sd; mm = (kspan < klim ? kspan : klim); goto lbl320; lbl310: c2 = c1 - ((cd*c1) + (sd*s1)); s1 = s1 + ((sd*c1) - (cd*s1)); lbl320: c1 = c2; s2 = s1; kk += kspan; lbl330: ak = a[kk]; a[kk] = (MYFLT)((c2*ak) - (s2 * b[kk])); b[kk] = (MYFLT)((s2*ak) + (c2 * b[kk])); kk += kspnn; if (kk <= nt) goto lbl330; ak = s1*s2; s2 = (s1*c2) + (c1*s2); c2 = (c1*c2) - ak; kk -= (nt - kspan); if (kk <= kspnn) goto lbl330; kk -= (kspnn - jc); if (kk <= mm) goto lbl310; if (kk < kspan) goto lbl340; kk -= (kspan - jc - inc); if (kk <= (jc+jc)) goto lbl300; goto lbl40; lbl340: s1 = ((double)((kk-1)/jc)) * dr * rad; c2 = cos(s1); s1 = sin(s1); mm = (kspan < mm+klim ? kspan :mm+klim); goto lbl320; /* * permute the results to normal order---done in two stages * permutation for square factors of n */ lbl350: np[1] = ks; if (!(*kt)) goto lbl440; k = *kt + *kt + 1; if (m < k) k--; np[k+1] = jc; for (j=1; j < k; j++,k--) { np[j+1] = np[j] / nfac[j]; np[k] = np[k+1] * nfac[j]; } k3 = np[k+1]; kspan = np[2]; kk = jc + 1; k2 = kspan + 1; j = 1; if (n != ntot) goto lbl400; /* * permutation for single-variate transform (optional code) */ lbl370: do { ak = a[kk]; a[kk] = a[k2]; a[k2] = (MYFLT)ak; bk = b[kk]; b[kk] = b[k2]; b[k2] = (MYFLT)bk; kk += inc; k2 += kspan; } while (k2 < ks); lbl380: do { k2 -= np[j++]; k2 += np[j+1]; } while (k2 > np[j]); j = 1; lbl390: if (kk < k2) { goto lbl370; } kk += inc; k2 += kspan; if (k2 < ks) goto lbl390; if (kk < ks) goto lbl380; jc = k3; goto lbl440; /* * permutation for multivariate transform */ lbl400: do { do { k = kk + jc; do { ak = a[kk]; a[kk] = a[k2]; a[k2] = (MYFLT)ak; bk = b[kk]; b[kk] = b[k2]; b[k2] = (MYFLT)bk; kk += inc; k2 += inc; } while (kk < k); kk += (ks - jc); k2 += (ks - jc); } while (kk < nt); k2 -= (nt - kspan); kk -= (nt - jc); } while (k2 < ks); lbl420: do { k2 -= np[j++]; k2 += np[j+1]; } while (k2 > np[j]); j = 1; lbl430: if (kk < k2) goto lbl400; kk += jc; k2 += kspan; if (k2 < ks) goto lbl430; if (kk < ks) goto lbl420; jc = k3; lbl440: if ((2*(*kt))+1 >= m) return; kspnn = *(np + *(kt) + 1); j = m - *kt; nfac[j+1] = 1; lbl450: nfac[j] = nfac[j] * nfac[j+1]; j--; if (j != *kt) goto lbl450; *kt = *(kt) + 1; nn = nfac[*kt] - 1; jj = 0; j = 0; goto lbl480; lbl460: jj -= k2; k2 = kk; kk = nfac[++k]; lbl470: jj += kk; if (jj >= k2) goto lbl460; np[j] = jj; lbl480: k2 = nfac[*kt]; k = *kt + 1; kk = nfac[k]; j++; if (j <= nn) goto lbl470; /* Determine permutation cycles of length greater than 1 */ j = 0; goto lbl500; lbl490: k = kk; kk = np[k]; np[k] = -kk; if (kk != j) goto lbl490; k3 = kk; lbl500: kk = np[++j]; if (kk < 0) goto lbl500; if (kk != j) goto lbl490; np[j] = -j; if (j != nn) goto lbl500; maxf *= inc; /* Perform reordering following permutation cycles */ goto lbl570; lbl510: j--; if (np[j] < 0) goto lbl510; jj = jc; lbl520: kspan = jj; if (jj > maxf) kspan = maxf; jj -= kspan; k = np[j]; kk = (jc*k) + i + jj; k1 = kk + kspan; k2 = 0; lbl530: k2++; at[k2] = a[k1]; bt[k2] = b[k1]; k1 -= inc; if (k1 != kk) goto lbl530; lbl540: k1 = kk + kspan; k2 = k1 - (jc * (k + np[k])); k = -(np[k]); lbl550: a[k1] = a[k2]; b[k1] = b[k2]; k1 -= inc; k2 -= inc; if (k1 != kk) goto lbl550; kk = k2; if (k != j) goto lbl540; k1 = kk + kspan; k2 = 0; lbl560: k2++; a[k1] = at[k2]; b[k1] = bt[k2]; k1 -= inc; if (k1 != kk) goto lbl560; if (jj) goto lbl520; if (j != 1) goto lbl510; lbl570: j = k3 + 1; nt -= kspnn; i = nt - inc + 1; if (nt >= 0) goto lbl510; return; } /* *----------------------------------------------------------------------- * subroutine: * reals * used with 'fft' to compute fourier transform or inverse for real data *----------------------------------------------------------------------- * this is the call from C: * * reals_(anal,banal,N2,mtwo); * which has been changed from CARL call * reals_(csound,anal,banal,&N2,&mtwo); */ static void reals_(CSOUND *csound, MYFLT *a, MYFLT *b, int n, int isn) /* *a, a refers to an array of floats 'anal' */ /* *b; b refers to an array of floats 'banal' */ /* See IEEE book for a long comment here on usage */ { IGN(csound); int inc, j, k, lim, mm,ml, nf,nk,nh; double aa,ab, ba,bb, cd,cn, dr, em, rad,re, sd,sn; double xx; /******* ADDED APRIL 1991 ******/ /* adjust input array pointers (called from C) */ a--; b--; inc = abs(isn); nf = abs(n); nk = (nf*inc) + 2; nh = nk/2; /***************************** rad = atan((double)1.0); ******************************/ rad = 0.785398163397448278900; dr = -4.0/(double)(nf); /********************************** POW2 REMOVED APRIL 1991 ***************** cd = 2.0 * (pow2(sin((double)0.5 * dr * rad))); *****************************************************************************/ xx = sin((double)0.5 * dr * rad); cd = 2.0 * xx * xx; sd = sin(dr * rad); /* * sin,cos values are re-initialised each lim steps */ lim = 32; mm = lim; ml = 0; sn = 0.0; if (isn<0) { cn = 1.0; a[nk-1] = a[1]; b[nk-1] = b[1]; } else { cn = -1.0; sd = -sd; } for (j=1;j<=nh;j+=inc) { k = nk - j; aa = a[j] + a[k]; ab = a[j] - a[k]; ba = b[j] + b[k]; bb = b[j] - b[k]; re = (cn*ba) + (sn*ab); em = (sn*ba) - (cn*ab); b[k] = (MYFLT)((em-bb)*0.5); b[j] = (MYFLT)((em+bb)*0.5); a[k] = (MYFLT)((aa-re)*0.5); a[j] = (MYFLT)((aa+re)*0.5); ml++; if (ml!=mm) { aa = cn - ((cd*cn)+(sd*sn)); sn = ((sd*cn) - (cd*sn)) + sn; cn = aa;} else { mm +=lim; sn = ((MYFLT)ml) * dr * rad; cn = cos(sn); if (isn>0) cn = -cn; sn = sin(sn); } } return; } /** * Compute in-place real FFT, allowing non power of two FFT sizes. * * buf: array of FFTsize + 2 MYFLT values; output is in interleaved * real/imaginary format (note: the real part of the Nyquist * frequency is stored in buf[FFTsize], and not in buf[1]). * FFTsize: FFT length in samples; not required to be an integer power of two, * but should be even and not have too many factors. */ void csoundRealFFTnp2(CSOUND *csound, MYFLT *buf, int FFTsize) { if (!(FFTsize & (FFTsize - 1))) { /* if FFT size is power of two: */ csound->RealFFT(csound, buf, FFTsize); buf[FFTsize] = buf[1]; } else { if (UNLIKELY(FFTsize < 2 || (FFTsize & 1))) { csound->Warning(csound, Str("csoundRealFFTnp2(): invalid FFT size, %d"), FFTsize); return; } buf[FFTsize] = buf[FFTsize + 1] = FL(0.0); fft_(csound, buf, &(buf[1]), 1, (FFTsize >> 1), 1, -2); reals_(csound, buf, &(buf[1]), (FFTsize >> 1), -2); } buf[1] = buf[FFTsize + 1] = FL(0.0); } /** * Compute in-place inverse real FFT, allowing non power of two FFT sizes. * The output does not need to be scaled. * * buf: array of FFTsize + 2 MYFLT values, in interleaved real/imaginary * format (note: the real part of the Nyquist frequency is stored * in buf[FFTsize], and not in buf[1]). * FFTsize: FFT length in samples; not required to be an integer power of two, * but should be even and not have too many factors. */ void csoundInverseRealFFTnp2(CSOUND *csound, MYFLT *buf, int FFTsize) { if (UNLIKELY(FFTsize < 2 || (FFTsize & 1))){ csound->Warning(csound, Str("csoundInverseRealFFTnp2(): invalid FFT size")); return; } buf[1] = buf[FFTsize + 1] = FL(0.0); reals_(csound, buf, &(buf[1]), (FFTsize >> 1), 2); fft_(csound, buf, &(buf[1]), 1, (FFTsize >> 1), 1, 2); buf[FFTsize] = buf[FFTsize + 1] = FL(0.0); } void csoundInverseComplexFFTnp2(CSOUND *csound, MYFLT *buf, int FFTsize) { if (UNLIKELY(FFTsize < 2 || (FFTsize & 1))){ csound->Warning(csound, Str("csoundInverseRealFFTnp2(): invalid FFT size")); return; } fft_(csound, buf, buf, 1, FFTsize, 1, 2); } void csoundComplexFFTnp2(CSOUND *csound, MYFLT *buf, int FFTsize) { if (UNLIKELY(FFTsize < 2 || (FFTsize & 1))) { csound->Warning(csound, Str("csoundRealFFTnp2(): invalid FFT size")); return; } fft_(csound, buf, buf, 1, FFTsize, 1, -2); } csound-6.10.0/OOps/oscils.c000066400000000000000000000354741321653344700154360ustar00rootroot00000000000000/* oscils.c: Copyright (C) 2002 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* ------ oscils, lphasor, and tablexkt by Istvan Varga (Jan 5 2002) ------ */ #include "csoundCore.h" #include #define CSOUND_OSCILS_C 1 #include "oscils.h" /* ------------- set up fast sine generator ------------- */ /* Input args: */ /* a: amplitude */ /* f: frequency (-PI - PI) */ /* p: initial phase (0 - PI/2) */ /* Output args: */ /* *x: first output sample */ /* *c, *v: coefficients for calculating next sample as */ /* shown below: */ /* v = v + c * x */ /* x = x + v */ /* These values are calculated by: */ /* x = y[0] */ /* c = 2.0 * cos(f) - 2.0 */ /* v = y[1] - (c + 1.0) * y[0] */ /* where y[0], and y[1] are the first, and */ /* second sample of the sine wave to be */ /* generated, respectively. */ /* -------- written by Istvan Varga, Jan 28 2002 -------- */ static void init_sine_gen(double a, double f, double p, double *x, double *c, double *v) { double y0, y1; /* these should be doubles */ y0 = sin(p); y1 = sin(p + f); *x = y0; *c = 2.0 * cos(f) - 2.0; *v = y1 - *c * y0 - y0; /* amp. scale */ *x *= a; *v *= a; } /* -------- oscils set-up -------- */ int oscils_set(CSOUND *csound, OSCILS *p) { int iflg; iflg = (int) (*(p->iflg) + FL(0.5)) & 0x07; /* check flags */ if (UNLIKELY(iflg & 1)) return OK; /* skip init, nothing to do */ p->use_double = (iflg & 2 ? 1 : 0); /* use doubles internally */ init_sine_gen((double)*(p->iamp), (double)(*(p->icps) * csound->tpidsr), (double)(*(p->iphs) * TWOPI_F), &(p->xd), &(p->cd), &(p->vd)); if (!(p->use_double)) { p->x = (MYFLT) p->xd; /* use floats */ p->c = (MYFLT) p->cd; p->v = (MYFLT) p->vd; } return OK; } /* -------- oscils performance -------- */ int oscils(CSOUND *csound, OSCILS *p) { IGN(csound); uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *ar, x, c, v; double xd, cd, vd; /* copy object data to local variables */ ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } if (p->use_double) { /* use doubles */ xd = p->xd; cd = p->cd; vd = p->vd; for (n=offset; nxd = xd; p->vd = vd; } else { /* use floats */ x = p->x; c = p->c; v = p->v; for (n=offset; nx = x; p->v = v; } return OK; } /* -------- lphasor set-up -------- */ int lphasor_set(CSOUND *csound, LPHASOR *p) { IGN(csound); if (UNLIKELY(*(p->istor) != FL(0.0))) return OK; /* nothing to do */ p->phs = (double)*(p->istrt); /* start phase */ p->lps = (double)*(p->ilps); /* loop start */ p->lpe = (double)*(p->ilpe); /* loop end */ p->loop_mode = (int) (*(p->imode) + FL(0.5)) & 0x03; /* loop mode */ if (p->lpe <= p->lps) p->loop_mode = 0; /* disable loop */ p->dir = 1; /* direction */ return OK; } /* -------- lphasor performance -------- */ int lphasor(CSOUND *csound, LPHASOR *p) { IGN(csound); uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int loop_mode, dir; MYFLT *ar, *xtrns; double trns, phs, lps, lpe, lpt; int assxtr = IS_ASIG_ARG(p->xtrns); /* copy object data to local variables */ ar = p->ar; xtrns = p->xtrns; phs = p->phs; lps = p->lps; lpe = p->lpe; lpt = lpe - lps; loop_mode = p->loop_mode; trns = (double)*xtrns; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; ndir ? trns : -trns); if (loop_mode) { dir = (trns < 0.0 ? !(p->dir) : p->dir); if (dir && (phs >= lpe)) { phs += lpt * (double)((int)((lps - phs) / lpt)); if (loop_mode & 2) { phs = lps + lpe - phs; /* reverse direction */ p->dir = !(p->dir); } } else if (!dir && (phs <= lps)) { phs += lpt * (double)((int)((lpe - phs) / lpt)); if (loop_mode & 1) { phs = lps + lpe - phs; /* reverse direction */ p->dir = !(p->dir); } } } } /* store phase */ p->phs = phs; return OK; } /* -------- tablexkt set-up -------- */ int tablexkt_set(CSOUND *csound, TABLEXKT *p) { IGN(csound); p->wsize = (int)(*(p->iwsize) + 0.5); /* window size */ if (UNLIKELY(p->wsize < 3)) { p->wsize = 2; } else { p->wsize = ((p->wsize + 2) >> 2) << 2; /* round to nearest */ if (p->wsize > 1024) p->wsize = 1024; /* integer multiply of 4 */ } /* constant for window calculation */ p->win_fact = (FL(1.0) - POWER(p->wsize * FL(0.85172), -FL(0.89624))) / ((MYFLT)((p->wsize * p->wsize) >> 2)); p->ndx_scl = (*(p->ixmode) == FL(0.0) ? 0 : 1); /* index mode */ p->wrap_ndx = (*(p->iwrap) == FL(0.0) ? 0 : 1); /* wrap index */ /* use raw index values without scale / offset */ if ((*(p->ixoff) != FL(0.0)) || p->ndx_scl) p->raw_ndx = 0; else p->raw_ndx = 1; return OK; } /* -------- tablexkt opcode -------- */ int tablexkt(CSOUND *csound, TABLEXKT *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int i, wsize, wsized2, wrap_ndx, warp; double ndx, d, x, c, v, flen_d, onedpi_d, pidwarp_d; int32 ndx_i=0, flen; MYFLT *ar, *xndx, ndx_f, a0, a1, a2, a3, v0, v1, v2, v3, *ftable; MYFLT onedwarp, win_fact; FUNC *ftp; int asgx = IS_ASIG_ARG(p->xndx); /* window size */ wsize = p->wsize; if (UNLIKELY((wsize < 2) || (wsize > 1024))) { return csound->PerfError(csound, p->h.insdshead, Str("tablexkt: not initialised")); } wsized2 = wsize >> 1; /* check ftable */ if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->kfn)) == NULL)) return NOTOK; /* invalid table */ if (UNLIKELY((ftable = ftp->ftable) == NULL)) return NOTOK; flen = ftp->flen; /* table length */ flen_d = (double)flen; /* copy object data to local variables */ ar = p->ar; xndx = p->xndx; wrap_ndx = p->wrap_ndx; if ((wsize > 4) && UNLIKELY((*(p->kwarp) > FL(1.001)))) { warp = 1; /* enable warp */ onedwarp = FL(1.0) / *(p->kwarp); pidwarp_d = PI / (double)*(p->kwarp); /* correct window for kwarp */ x = v = (double)wsized2; x *= x; x = 1.0 / x; v *= (double)onedwarp; v -= (double)((int)v) + 0.5; v *= 4.0 * v; win_fact = (MYFLT)(((double)p->win_fact - x) * v + x); } else { warp = 0; onedwarp = FL(0.0); pidwarp_d = 0.0; win_fact = p->win_fact; } onedpi_d = 1.0 / PI; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nraw_ndx)) { ndx += (double)*(p->ixoff); if (p->ndx_scl) ndx *= flen_d; } /* integer and fractional part of table index */ ndx_i = (int32)ndx; ndx_f = (MYFLT) (ndx - (double)ndx_i); if (ndx_f < FL(0.0)) { ndx_f++; ndx_i--; } /* wrap or limit to allowed range */ if (wrap_ndx) { while (ndx_i >= flen) ndx_i -= flen; while (ndx_i < 0) ndx_i += flen; } else { /* limit */ if (UNLIKELY(ndx_i < 0)) { ndx_i = 0; ndx_f = FL(0.0); } else if (UNLIKELY(ndx_i >= flen)) { ndx_i = flen; ndx_f = FL(0.0); } } switch (wsize) { case 2: /* ---- linear interpolation ---- */ ar[n] = ftable[ndx_i]; if (++ndx_i >= flen) ndx_i = (wrap_ndx ? ndx_i - flen : flen); ar[n] += (ftable[ndx_i] - ar[n]) * ndx_f; break; case 4: /* ---- cubic interpolation ---- */ /* sample 0 */ v1 = ftable[ndx_i]; /* sample -1 */ if (ndx_i) { v0 = ftable[ndx_i - 1L]; } else { v0 = ftable[(wrap_ndx ? flen - 1L : 0L)]; } /* sample +1 */ if (++ndx_i >= flen) ndx_i = (wrap_ndx ? ndx_i - flen : flen); v2 = ftable[ndx_i]; /* sample +2 */ if (++ndx_i >= flen) ndx_i = (wrap_ndx ? ndx_i - flen : flen); v3 = ftable[ndx_i]; a3 = ndx_f * ndx_f; a3--; a3 *= FL(0.1666666667); a2 = ndx_f; a2++; a0 = (a2 *= FL(0.5)); a0--; a1 = FL(3.0) * a3; a2 -= a1; a0 -= a3; a1 -= ndx_f; ar[n] = (a0 * v0 + a1 * v1 + a2 * v2 + a3 * v3) * ndx_f + v1; break; default: /* ---- sinc interpolation ---- */ ar[n] = FL(0.0); /* clear output */ ndx = (double)ndx_f; ndx_i += (int32)(1 - wsized2); d = (double)(1 - wsized2) - ndx; if (warp) { /* ---- warp enabled ---- */ init_sine_gen(onedpi_d, pidwarp_d, pidwarp_d * d, &x, &c, &v); /* samples -(window size / 2 - 1) to -1 */ i = wsized2 - 1; do { a1 = (MYFLT) d; a1 = FL(1.0) - a1 * a1 * win_fact; a1 = a1 * a1 / (MYFLT) d; ar[n] += ftable[(ndx_i < 0L ? (wrap_ndx ? ndx_i + flen : 0L) : ndx_i)] * (MYFLT) x * a1; ndx_i++; d++; v += c * x; x += v; } while (--i); /* sample 0 */ /* avoid division by zero */ if (UNLIKELY(ndx < 0.00003)) ar[n] += onedwarp * ftable[ndx_i]; else { a1 = (MYFLT) d; a1 = FL(1.0) - a1 * a1 * win_fact; a1 = a1 * a1 / (MYFLT) d; ar[n] += (MYFLT) x * a1 * ftable[ndx_i]; } d++; v += c * x; x += v; if (++ndx_i >= flen) ndx_i = (wrap_ndx ? ndx_i - flen : flen); /* sample 1 */ /* avoid division by zero */ if (ndx > 0.99997) ar[n] += onedwarp * ftable[ndx_i]; else { a1 = (MYFLT) d; a1 = FL(1.0) - a1 * a1 * win_fact; a1 = a1 * a1 / (MYFLT) d; ar[n] += (MYFLT) x * a1 * ftable[ndx_i]; } d++; v += c * x; x += v; if (++ndx_i >= flen) ndx_i = (wrap_ndx ? ndx_i - flen : flen); /* samples 2 to (window size / 2) */ i = wsized2 - 1; do { a1 = (MYFLT) d; a1 = FL(1.0) - a1 * a1 * win_fact; a1 = a1 * a1 / (MYFLT) d; ar[n] += (MYFLT) x * a1 * ftable[ndx_i]; d++; v += c * x; x += v; if (++ndx_i >= flen) ndx_i = (wrap_ndx ? ndx_i - flen : flen); } while (--i); } else { /* ---- warp disabled ---- */ /* avoid division by zero */ if (UNLIKELY(ndx < 0.00001)) { ndx_i += (int32) (wsized2 - 1); /* no need to check here */ ar[n] = ftable[ndx_i]; } else if (ndx > 0.99999) { ndx_i += (int32) wsized2; /* does need range checking */ if (ndx_i >= flen) ndx_i = (wrap_ndx ? ndx_i - flen : flen); ar[n] = ftable[ndx_i]; } else { /* samples -(window size / 2 - 1) to 0 */ i = wsized2 >> 1; do { a1 = (MYFLT) d; a1 = FL(1.0) - a1 * a1 * win_fact; a1 = a1 * a1 / (MYFLT) d; ar[n] += ftable[(ndx_i < 0L ? (wrap_ndx ? ndx_i + flen : 0L) : ndx_i)] * a1; d+=1.0; ndx_i++; a1 = (MYFLT) d; a1 = FL(1.0) - a1 * a1 * win_fact; a1 = a1 * a1 / (MYFLT) d; ar[n] -= ftable[(ndx_i < 0L ? (wrap_ndx ? ndx_i + flen : 0L) : ndx_i)] * a1; d+=1.0; ndx_i++; } while (--i); /* samples 1 to (window size / 2) */ i = wsized2 >> 1; do { a1 = (MYFLT) d; a1 = FL(1.0) - a1 * a1 * win_fact; a1 = a1 * a1 / (MYFLT) d; ar[n] += a1 * ftable[ndx_i]; d+=1.0; if (++ndx_i >= flen) ndx_i = (wrap_ndx ? ndx_i - flen : flen); a1 = (MYFLT) d; a1 = FL(1.0) - a1 * a1 * win_fact; a1 = a1 * a1 / (MYFLT) d; ar[n] -= a1 * ftable[ndx_i]; d+=1.0; if (++ndx_i >= flen) ndx_i = (wrap_ndx ? ndx_i - flen : flen); } while (--i); ar[n] *= SIN(PI_F * ndx) / PI_F; } } break; } } return OK; } csound-6.10.0/OOps/pffft.c000066400000000000000000002031511321653344700152340ustar00rootroot00000000000000/* Copyright (c) 2013 Julien Pommier ( pommier@modartt.com ) Based on original fortran 77 code from FFTPACKv4 from NETLIB (http://www.netlib.org/fftpack), authored by Dr Paul Swarztrauber of NCAR, in 1985. As confirmed by the NCAR fftpack software curators, the following FFTPACKv5 license applies to FFTPACKv4 sources. My changes are released under the same terms. FFTPACK license: http://www.cisl.ucar.edu/css/software/fftpack5/ftpk.html Copyright (c) 2004 the University Corporation for Atmospheric Research ("UCAR"). All rights reserved. Developed by NCAR's Computational and Information Systems Laboratory, UCAR, www.cisl.ucar.edu. Redistribution and use of the Software in source and binary forms, with or without modification, is permitted provided that the following conditions are met: - Neither the names of NCAR's Computational and Information Systems Laboratory, the University Corporation for Atmospheric Research, nor the names of its sponsors or contributors may be used to endorse or promote products derived from this Software without specific prior written permission. - Redistributions of source code must retain the above copyright notices, this list of conditions, and the disclaimer below. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the disclaimer below in the documentation and/or other materials provided with the distribution. THIS 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 CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 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 WITH THE SOFTWARE. PFFFT : a Pretty Fast FFT. This file is largerly based on the original FFTPACK implementation, modified in order to take advantage of SIMD instructions of modern CPUs. */ /* ChangeLog: - 2011/10/02, version 1: This is the very first release of this file. */ #include "pffft.h" #include #include #include /* detect compiler flavour */ #if defined(_MSC_VER) # define COMPILER_MSVC #elif defined(__GNUC__) # define COMPILER_GCC #endif #ifdef COMPILER_MSVC #define _USE_MATH_DEFINES #endif #include #if defined(COMPILER_GCC) # define ALWAYS_INLINE(return_type) inline return_type __attribute__ ((always_inline)) # define NEVER_INLINE(return_type) return_type __attribute__ ((noinline)) # define RESTRICT __restrict # define VLA_ARRAY_ON_STACK(type__, varname__, size__) type__ varname__[size__]; #elif defined(COMPILER_MSVC) # define ALWAYS_INLINE(return_type) __forceinline return_type # define NEVER_INLINE(return_type) __declspec(noinline) return_type # define RESTRICT __restrict # define VLA_ARRAY_ON_STACK(type__, varname__, size__) type__ *varname__ = (type__*)_alloca(size__ * sizeof(type__)) #endif /* vector support macros: the rest of the code is independant of SSE/Altivec/NEON -- adding support for other platforms with 4-element vectors should be limited to these macros */ // define PFFFT_SIMD_DISABLE if you want to use scalar code instead of simd code //#define PFFFT_SIMD_DISABLE /* Altivec support macros */ #if !defined(PFFFT_SIMD_DISABLE) && (defined(__ppc__) || defined(__ppc64__)) typedef vector float v4sf; # define SIMD_SZ 4 # define VZERO() ((vector float) vec_splat_u8(0)) # define VMUL(a,b) vec_madd(a,b, VZERO()) # define VADD(a,b) vec_add(a,b) # define VMADD(a,b,c) vec_madd(a,b,c) # define VSUB(a,b) vec_sub(a,b) inline v4sf ld_ps1(const float *p) { v4sf v=vec_lde(0,p); return vec_splat(vec_perm(v, v, vec_lvsl(0, p)), 0); } # define LD_PS1(p) ld_ps1(&p) # define INTERLEAVE2(in1, in2, out1, out2) { v4sf tmp__ = vec_mergeh(in1, in2); out2 = vec_mergel(in1, in2); out1 = tmp__; } # define UNINTERLEAVE2(in1, in2, out1, out2) { \ vector unsigned char vperm1 = (vector unsigned char)(0,1,2,3,8,9,10,11,16,17,18,19,24,25,26,27); \ vector unsigned char vperm2 = (vector unsigned char)(4,5,6,7,12,13,14,15,20,21,22,23,28,29,30,31); \ v4sf tmp__ = vec_perm(in1, in2, vperm1); out2 = vec_perm(in1, in2, vperm2); out1 = tmp__; \ } # define VTRANSPOSE4(x0,x1,x2,x3) { \ v4sf y0 = vec_mergeh(x0, x2); \ v4sf y1 = vec_mergel(x0, x2); \ v4sf y2 = vec_mergeh(x1, x3); \ v4sf y3 = vec_mergel(x1, x3); \ x0 = vec_mergeh(y0, y2); \ x1 = vec_mergel(y0, y2); \ x2 = vec_mergeh(y1, y3); \ x3 = vec_mergel(y1, y3); \ } # define VSWAPHL(a,b) vec_perm(a,b, (vector unsigned char)(16,17,18,19,20,21,22,23,8,9,10,11,12,13,14,15)) # define VALIGNED(ptr) ((((long)(ptr)) & 0xF) == 0) /* SSE1 support macros */ #elif !defined(PFFFT_SIMD_DISABLE) && (defined(__x86_64__) || defined(_M_X64) || defined(i386) || defined(_M_IX86)) #include typedef __m128 v4sf; # define SIMD_SZ 4 // 4 floats by simd vector -- this is pretty much hardcoded in the preprocess/finalize functions anyway so you will have to work if you want to enable AVX with its 256-bit vectors. # define VZERO() _mm_setzero_ps() # define VMUL(a,b) _mm_mul_ps(a,b) # define VADD(a,b) _mm_add_ps(a,b) # define VMADD(a,b,c) _mm_add_ps(_mm_mul_ps(a,b), c) # define VSUB(a,b) _mm_sub_ps(a,b) # define LD_PS1(p) _mm_set1_ps(p) # define INTERLEAVE2(in1, in2, out1, out2) { v4sf tmp__ = _mm_unpacklo_ps(in1, in2); out2 = _mm_unpackhi_ps(in1, in2); out1 = tmp__; } # define UNINTERLEAVE2(in1, in2, out1, out2) { v4sf tmp__ = _mm_shuffle_ps(in1, in2, _MM_SHUFFLE(2,0,2,0)); out2 = _mm_shuffle_ps(in1, in2, _MM_SHUFFLE(3,1,3,1)); out1 = tmp__; } # define VTRANSPOSE4(x0,x1,x2,x3) _MM_TRANSPOSE4_PS(x0,x1,x2,x3) # define VSWAPHL(a,b) _mm_shuffle_ps(b, a, _MM_SHUFFLE(3,2,1,0)) # define VALIGNED(ptr) ((((long)(ptr)) & 0xF) == 0) /* ARM NEON support macros */ #elif !defined(PFFFT_SIMD_DISABLE) && (defined(__arm__) || defined(IOS)) # include typedef float32x4_t v4sf; # define SIMD_SZ 4 # define VZERO() vdupq_n_f32(0) # define VMUL(a,b) vmulq_f32(a,b) # define VADD(a,b) vaddq_f32(a,b) # define VMADD(a,b,c) vmlaq_f32(c,a,b) # define VSUB(a,b) vsubq_f32(a,b) # define LD_PS1(p) vld1q_dup_f32(&(p)) # define INTERLEAVE2(in1, in2, out1, out2) { float32x4x2_t tmp__ = vzipq_f32(in1,in2); out1=tmp__.val[0]; out2=tmp__.val[1]; } # define UNINTERLEAVE2(in1, in2, out1, out2) { float32x4x2_t tmp__ = vuzpq_f32(in1,in2); out1=tmp__.val[0]; out2=tmp__.val[1]; } # define VTRANSPOSE4(x0,x1,x2,x3) { \ float32x4x2_t t0_ = vzipq_f32(x0, x2); \ float32x4x2_t t1_ = vzipq_f32(x1, x3); \ float32x4x2_t u0_ = vzipq_f32(t0_.val[0], t1_.val[0]); \ float32x4x2_t u1_ = vzipq_f32(t0_.val[1], t1_.val[1]); \ x0 = u0_.val[0]; x1 = u0_.val[1]; x2 = u1_.val[0]; x3 = u1_.val[1]; \ } // marginally faster version //# define VTRANSPOSE4(x0,x1,x2,x3) { asm("vtrn.32 %q0, %q1;\n vtrn.32 %q2,%q3\n vswp %f0,%e2\n vswp %f1,%e3" : "+w"(x0), "+w"(x1), "+w"(x2), "+w"(x3)::); } # define VSWAPHL(a,b) vcombine_f32(vget_low_f32(b), vget_high_f32(a)) # define VALIGNED(ptr) ((((long)(ptr)) & 0x3) == 0) #else # if !defined(PFFFT_SIMD_DISABLE) # warning "building with simd disabled !!!!!!!!!!!!!!\n"; # define PFFFT_SIMD_DISABLE // fallback to scalar code # endif #endif // fallback mode for situations where SSE/Altivec are not available, use scalar mode instead #ifdef PFFFT_SIMD_DISABLE typedef float v4sf; # define SIMD_SZ 1 # define VZERO() 0.f # define VMUL(a,b) ((a)*(b)) # define VADD(a,b) ((a)+(b)) # define VMADD(a,b,c) ((a)*(b)+(c)) # define VSUB(a,b) ((a)-(b)) # define LD_PS1(p) (p) # define VALIGNED(ptr) ((((long)(ptr)) & 0x3) == 0) #endif // shortcuts for complex multiplcations #define VCPLXMUL(ar,ai,br,bi) { v4sf tmp; tmp=VMUL(ar,bi); ar=VMUL(ar,br); ar=VSUB(ar,VMUL(ai,bi)); ai=VMUL(ai,br); ai=VADD(ai,tmp); } #define VCPLXMULCONJ(ar,ai,br,bi) { v4sf tmp; tmp=VMUL(ar,bi); ar=VMUL(ar,br); ar=VADD(ar,VMUL(ai,bi)); ai=VMUL(ai,br); ai=VSUB(ai,tmp); } #ifndef SVMUL // multiply a scalar with a vector #define SVMUL(f,v) VMUL(LD_PS1(f),v) #endif #if !defined(PFFFT_SIMD_DISABLE) typedef union v4sf_union { v4sf v; float f[4]; } v4sf_union; #include #define assertv4(v,f0,f1,f2,f3) assert(v.f[0] == (f0) && v.f[1] == (f1) && v.f[2] == (f2) && v.f[3] == (f3)) /* detect bugs with the vector support macros */ void validate_pffft_simd() { float f[16] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }; v4sf_union a0, a1, a2, a3, t, u; memcpy(a0.f, f, 4*sizeof(float)); memcpy(a1.f, f+4, 4*sizeof(float)); memcpy(a2.f, f+8, 4*sizeof(float)); memcpy(a3.f, f+12, 4*sizeof(float)); t = a0; u = a1; t.v = VZERO(); printf("VZERO=[%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3]); assertv4(t, 0, 0, 0, 0); t.v = VADD(a1.v, a2.v); printf("VADD(4:7,8:11)=[%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3]); assertv4(t, 12, 14, 16, 18); t.v = VMUL(a1.v, a2.v); printf("VMUL(4:7,8:11)=[%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3]); assertv4(t, 32, 45, 60, 77); t.v = VMADD(a1.v, a2.v,a0.v); printf("VMADD(4:7,8:11,0:3)=[%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3]); assertv4(t, 32, 46, 62, 80); INTERLEAVE2(a1.v,a2.v,t.v,u.v); printf("INTERLEAVE2(4:7,8:11)=[%2g %2g %2g %2g] [%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3], u.f[0], u.f[1], u.f[2], u.f[3]); assertv4(t, 4, 8, 5, 9); assertv4(u, 6, 10, 7, 11); UNINTERLEAVE2(a1.v,a2.v,t.v,u.v); printf("UNINTERLEAVE2(4:7,8:11)=[%2g %2g %2g %2g] [%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3], u.f[0], u.f[1], u.f[2], u.f[3]); assertv4(t, 4, 6, 8, 10); assertv4(u, 5, 7, 9, 11); t.v=LD_PS1(f[15]); printf("LD_PS1(15)=[%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3]); assertv4(t, 15, 15, 15, 15); t.v = VSWAPHL(a1.v, a2.v); printf("VSWAPHL(4:7,8:11)=[%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3]); assertv4(t, 8, 9, 6, 7); VTRANSPOSE4(a0.v, a1.v, a2.v, a3.v); printf("VTRANSPOSE4(0:3,4:7,8:11,12:15)=[%2g %2g %2g %2g] [%2g %2g %2g %2g] [%2g %2g %2g %2g] [%2g %2g %2g %2g]\n", a0.f[0], a0.f[1], a0.f[2], a0.f[3], a1.f[0], a1.f[1], a1.f[2], a1.f[3], a2.f[0], a2.f[1], a2.f[2], a2.f[3], a3.f[0], a3.f[1], a3.f[2], a3.f[3]); assertv4(a0, 0, 4, 8, 12); assertv4(a1, 1, 5, 9, 13); assertv4(a2, 2, 6, 10, 14); assertv4(a3, 3, 7, 11, 15); } #endif //!PFFFT_SIMD_DISABLE /* SSE and co like 16-bytes aligned pointers */ #define MALLOC_V4SF_ALIGNMENT 64 // with a 64-byte alignment, we are even aligned on L2 cache lines... void *pffft_aligned_malloc(size_t nb_bytes) { void *p, *p0 = malloc(nb_bytes + MALLOC_V4SF_ALIGNMENT); if (!p0) return (void *) 0; p = (void *) (((size_t) p0 + MALLOC_V4SF_ALIGNMENT) & (~((size_t) (MALLOC_V4SF_ALIGNMENT-1)))); *((void **) p - 1) = p0; return p; } void pffft_aligned_free(void *p) { if (p) free(*((void **) p - 1)); } int pffft_simd_size() { return SIMD_SZ; } /* passf2 and passb2 has been merged here, fsign = -1 for passf2, +1 for passb2 */ static NEVER_INLINE(void) passf2_ps(int ido, int l1, const v4sf *cc, v4sf *ch, const float *wa1, float fsign) { int k, i; int l1ido = l1*ido; if (ido <= 2) { for (k=0; k < l1ido; k += ido, ch += ido, cc+= 2*ido) { ch[0] = VADD(cc[0], cc[ido+0]); ch[l1ido] = VSUB(cc[0], cc[ido+0]); ch[1] = VADD(cc[1], cc[ido+1]); ch[l1ido + 1] = VSUB(cc[1], cc[ido+1]); } } else { for (k=0; k < l1ido; k += ido, ch += ido, cc += 2*ido) { for (i=0; i 2); for (k=0; k< l1ido; k += ido, cc+= 3*ido, ch +=ido) { for (i=0; i 2); for (k = 0; k < l1; ++k, cc += 5*ido, ch += ido) { for (i = 0; i < ido-1; i += 2) { ti5 = VSUB(cc_ref(i , 2), cc_ref(i , 5)); ti2 = VADD(cc_ref(i , 2), cc_ref(i , 5)); ti4 = VSUB(cc_ref(i , 3), cc_ref(i , 4)); ti3 = VADD(cc_ref(i , 3), cc_ref(i , 4)); tr5 = VSUB(cc_ref(i-1, 2), cc_ref(i-1, 5)); tr2 = VADD(cc_ref(i-1, 2), cc_ref(i-1, 5)); tr4 = VSUB(cc_ref(i-1, 3), cc_ref(i-1, 4)); tr3 = VADD(cc_ref(i-1, 3), cc_ref(i-1, 4)); ch_ref(i-1, 1) = VADD(cc_ref(i-1, 1), VADD(tr2, tr3)); ch_ref(i , 1) = VADD(cc_ref(i , 1), VADD(ti2, ti3)); cr2 = VADD(cc_ref(i-1, 1), VADD(SVMUL(tr11, tr2),SVMUL(tr12, tr3))); ci2 = VADD(cc_ref(i , 1), VADD(SVMUL(tr11, ti2),SVMUL(tr12, ti3))); cr3 = VADD(cc_ref(i-1, 1), VADD(SVMUL(tr12, tr2),SVMUL(tr11, tr3))); ci3 = VADD(cc_ref(i , 1), VADD(SVMUL(tr12, ti2),SVMUL(tr11, ti3))); cr5 = VADD(SVMUL(ti11, tr5), SVMUL(ti12, tr4)); ci5 = VADD(SVMUL(ti11, ti5), SVMUL(ti12, ti4)); cr4 = VSUB(SVMUL(ti12, tr5), SVMUL(ti11, tr4)); ci4 = VSUB(SVMUL(ti12, ti5), SVMUL(ti11, ti4)); dr3 = VSUB(cr3, ci4); dr4 = VADD(cr3, ci4); di3 = VADD(ci3, cr4); di4 = VSUB(ci3, cr4); dr5 = VADD(cr2, ci5); dr2 = VSUB(cr2, ci5); di5 = VSUB(ci2, cr5); di2 = VADD(ci2, cr5); wr1=wa1[i], wi1=fsign*wa1[i+1], wr2=wa2[i], wi2=fsign*wa2[i+1]; wr3=wa3[i], wi3=fsign*wa3[i+1], wr4=wa4[i], wi4=fsign*wa4[i+1]; VCPLXMUL(dr2, di2, LD_PS1(wr1), LD_PS1(wi1)); ch_ref(i - 1, 2) = dr2; ch_ref(i, 2) = di2; VCPLXMUL(dr3, di3, LD_PS1(wr2), LD_PS1(wi2)); ch_ref(i - 1, 3) = dr3; ch_ref(i, 3) = di3; VCPLXMUL(dr4, di4, LD_PS1(wr3), LD_PS1(wi3)); ch_ref(i - 1, 4) = dr4; ch_ref(i, 4) = di4; VCPLXMUL(dr5, di5, LD_PS1(wr4), LD_PS1(wi4)); ch_ref(i - 1, 5) = dr5; ch_ref(i, 5) = di5; } } #undef ch_ref #undef cc_ref } static NEVER_INLINE(void) radf2_ps(int ido, int l1, const v4sf * RESTRICT cc, v4sf * RESTRICT ch, const float *wa1) { static const float minus_one = -1.f; int i, k, l1ido = l1*ido; for (k=0; k < l1ido; k += ido) { v4sf a = cc[k], b = cc[k + l1ido]; ch[2*k] = VADD(a, b); ch[2*(k+ido)-1] = VSUB(a, b); } if (ido < 2) return; if (ido != 2) { for (k=0; k < l1ido; k += ido) { for (i=2; i 5) { wa[i1-1] = wa[i-1]; wa[i1] = wa[i]; } } l1 = l2; } } /* cffti1 */ v4sf *cfftf1_ps(int n, const v4sf *input_readonly, v4sf *work1, v4sf *work2, const float *wa, const int *ifac, int isign) { v4sf *in = (v4sf*)input_readonly; v4sf *out = (in == work2 ? work1 : work2); int nf = ifac[1], k1; int l1 = 1; int iw = 0; assert(in != out && work1 != work2); for (k1=2; k1<=nf+1; k1++) { int ip = ifac[k1]; int l2 = ip*l1; int ido = n / l2; int idot = ido + ido; switch (ip) { case 5: { int ix2 = iw + idot; int ix3 = ix2 + idot; int ix4 = ix3 + idot; passf5_ps(idot, l1, in, out, &wa[iw], &wa[ix2], &wa[ix3], &wa[ix4], isign); } break; case 4: { int ix2 = iw + idot; int ix3 = ix2 + idot; passf4_ps(idot, l1, in, out, &wa[iw], &wa[ix2], &wa[ix3], isign); } break; case 2: { passf2_ps(idot, l1, in, out, &wa[iw], isign); } break; case 3: { int ix2 = iw + idot; passf3_ps(idot, l1, in, out, &wa[iw], &wa[ix2], isign); } break; default: assert(0); } l1 = l2; iw += (ip - 1)*idot; if (out == work2) { out = work1; in = work2; } else { out = work2; in = work1; } } return in; /* this is in fact the output .. */ } struct PFFFT_Setup { int N; int Ncvec; // nb of complex simd vectors (N/4 if PFFFT_COMPLEX, N/8 if PFFFT_REAL) int ifac[15]; pffft_transform_t transform; v4sf *data; // allocated room for twiddle coefs float *e; // points into 'data' , N/4*3 elements float *twiddle; // points into 'data', N/4 elements }; PFFFT_Setup *pffft_new_setup(int N, pffft_transform_t transform) { PFFFT_Setup *s = (PFFFT_Setup*)malloc(sizeof(PFFFT_Setup)); int k, m; /* unfortunately, the fft size must be a multiple of 16 for complex FFTs and 32 for real FFTs -- a lot of stuff would need to be rewritten to handle other cases (or maybe just switch to a scalar fft, I don't know..) */ if (transform == PFFFT_REAL) { assert((N%(2*SIMD_SZ*SIMD_SZ))==0 && N>0); } if (transform == PFFFT_COMPLEX) { assert((N%(SIMD_SZ*SIMD_SZ))==0 && N>0); } //assert((N % 32) == 0); s->N = N; s->transform = transform; /* nb of complex simd vectors */ s->Ncvec = (transform == PFFFT_REAL ? N/2 : N)/SIMD_SZ; s->data = (v4sf*)pffft_aligned_malloc(2*s->Ncvec * sizeof(v4sf)); s->e = (float*)s->data; s->twiddle = (float*)(s->data + (2*s->Ncvec*(SIMD_SZ-1))/SIMD_SZ); if (transform == PFFFT_REAL) { for (k=0; k < s->Ncvec; ++k) { int i = k/SIMD_SZ; int j = k%SIMD_SZ; for (m=0; m < SIMD_SZ-1; ++m) { float A = -2*M_PI*(m+1)*k / N; s->e[(2*(i*3 + m) + 0) * SIMD_SZ + j] = cos(A); s->e[(2*(i*3 + m) + 1) * SIMD_SZ + j] = sin(A); } } rffti1_ps(N/SIMD_SZ, s->twiddle, s->ifac); } else { for (k=0; k < s->Ncvec; ++k) { int i = k/SIMD_SZ; int j = k%SIMD_SZ; for (m=0; m < SIMD_SZ-1; ++m) { float A = -2*M_PI*(m+1)*k / N; s->e[(2*(i*3 + m) + 0)*SIMD_SZ + j] = cos(A); s->e[(2*(i*3 + m) + 1)*SIMD_SZ + j] = sin(A); } } cffti1_ps(N/SIMD_SZ, s->twiddle, s->ifac); } /* check that N is decomposable with allowed prime factors */ for (k=0, m=1; k < s->ifac[1]; ++k) { m *= s->ifac[2+k]; } if (m != N/SIMD_SZ) { pffft_destroy_setup(s); s = 0; } return s; } void pffft_destroy_setup(PFFFT_Setup *s) { pffft_aligned_free(s->data); free(s); } #if !defined(PFFFT_SIMD_DISABLE) /* [0 0 1 2 3 4 5 6 7 8] -> [0 8 7 6 5 4 3 2 1] */ static void reversed_copy(int N, const v4sf *in, int in_stride, v4sf *out) { v4sf g0, g1; int k; INTERLEAVE2(in[0], in[1], g0, g1); in += in_stride; *--out = VSWAPHL(g0, g1); // [g0l, g0h], [g1l g1h] -> [g1l, g0h] for (k=1; k < N; ++k) { v4sf h0, h1; INTERLEAVE2(in[0], in[1], h0, h1); in += in_stride; *--out = VSWAPHL(g1, h0); *--out = VSWAPHL(h0, h1); g1 = h1; } *--out = VSWAPHL(g1, g0); } static void unreversed_copy(int N, const v4sf *in, v4sf *out, int out_stride) { v4sf g0, g1, h0, h1; int k; g0 = g1 = in[0]; ++in; for (k=1; k < N; ++k) { h0 = *in++; h1 = *in++; g1 = VSWAPHL(g1, h0); h0 = VSWAPHL(h0, h1); UNINTERLEAVE2(h0, g1, out[0], out[1]); out += out_stride; g1 = h1; } h0 = *in++; h1 = g0; g1 = VSWAPHL(g1, h0); h0 = VSWAPHL(h0, h1); UNINTERLEAVE2(h0, g1, out[0], out[1]); } void pffft_zreorder(PFFFT_Setup *setup, const float *in, float *out, pffft_direction_t direction) { int k, N = setup->N, Ncvec = setup->Ncvec; const v4sf *vin = (const v4sf*)in; v4sf *vout = (v4sf*)out; assert(in != out); if (setup->transform == PFFFT_REAL) { int k, dk = N/32; if (direction == PFFFT_FORWARD) { for (k=0; k < dk; ++k) { INTERLEAVE2(vin[k*8 + 0], vin[k*8 + 1], vout[2*(0*dk + k) + 0], vout[2*(0*dk + k) + 1]); INTERLEAVE2(vin[k*8 + 4], vin[k*8 + 5], vout[2*(2*dk + k) + 0], vout[2*(2*dk + k) + 1]); } reversed_copy(dk, vin+2, 8, (v4sf*)(out + N/2)); reversed_copy(dk, vin+6, 8, (v4sf*)(out + N)); } else { for (k=0; k < dk; ++k) { UNINTERLEAVE2(vin[2*(0*dk + k) + 0], vin[2*(0*dk + k) + 1], vout[k*8 + 0], vout[k*8 + 1]); UNINTERLEAVE2(vin[2*(2*dk + k) + 0], vin[2*(2*dk + k) + 1], vout[k*8 + 4], vout[k*8 + 5]); } unreversed_copy(dk, (v4sf*)(in + N/4), (v4sf*)(out + N - 6*SIMD_SZ), -8); unreversed_copy(dk, (v4sf*)(in + 3*N/4), (v4sf*)(out + N - 2*SIMD_SZ), -8); } } else { if (direction == PFFFT_FORWARD) { for (k=0; k < Ncvec; ++k) { int kk = (k/4) + (k%4)*(Ncvec/4); INTERLEAVE2(vin[k*2], vin[k*2+1], vout[kk*2], vout[kk*2+1]); } } else { for (k=0; k < Ncvec; ++k) { int kk = (k/4) + (k%4)*(Ncvec/4); UNINTERLEAVE2(vin[kk*2], vin[kk*2+1], vout[k*2], vout[k*2+1]); } } } } void pffft_cplx_finalize(int Ncvec, const v4sf *in, v4sf *out, const v4sf *e) { int k, dk = Ncvec/SIMD_SZ; // number of 4x4 matrix blocks v4sf r0, i0, r1, i1, r2, i2, r3, i3; v4sf sr0, dr0, sr1, dr1, si0, di0, si1, di1; assert(in != out); for (k=0; k < dk; ++k) { r0 = in[8*k+0]; i0 = in[8*k+1]; r1 = in[8*k+2]; i1 = in[8*k+3]; r2 = in[8*k+4]; i2 = in[8*k+5]; r3 = in[8*k+6]; i3 = in[8*k+7]; VTRANSPOSE4(r0,r1,r2,r3); VTRANSPOSE4(i0,i1,i2,i3); VCPLXMUL(r1,i1,e[k*6+0],e[k*6+1]); VCPLXMUL(r2,i2,e[k*6+2],e[k*6+3]); VCPLXMUL(r3,i3,e[k*6+4],e[k*6+5]); sr0 = VADD(r0,r2); dr0 = VSUB(r0, r2); sr1 = VADD(r1,r3); dr1 = VSUB(r1, r3); si0 = VADD(i0,i2); di0 = VSUB(i0, i2); si1 = VADD(i1,i3); di1 = VSUB(i1, i3); /* transformation for each column is: [1 1 1 1 0 0 0 0] [r0] [1 0 -1 0 0 -1 0 1] [r1] [1 -1 1 -1 0 0 0 0] [r2] [1 0 -1 0 0 1 0 -1] [r3] [0 0 0 0 1 1 1 1] * [i0] [0 1 0 -1 1 0 -1 0] [i1] [0 0 0 0 1 -1 1 -1] [i2] [0 -1 0 1 1 0 -1 0] [i3] */ r0 = VADD(sr0, sr1); i0 = VADD(si0, si1); r1 = VADD(dr0, di1); i1 = VSUB(di0, dr1); r2 = VSUB(sr0, sr1); i2 = VSUB(si0, si1); r3 = VSUB(dr0, di1); i3 = VADD(di0, dr1); *out++ = r0; *out++ = i0; *out++ = r1; *out++ = i1; *out++ = r2; *out++ = i2; *out++ = r3; *out++ = i3; } } void pffft_cplx_preprocess(int Ncvec, const v4sf *in, v4sf *out, const v4sf *e) { int k, dk = Ncvec/SIMD_SZ; // number of 4x4 matrix blocks v4sf r0, i0, r1, i1, r2, i2, r3, i3; v4sf sr0, dr0, sr1, dr1, si0, di0, si1, di1; assert(in != out); for (k=0; k < dk; ++k) { r0 = in[8*k+0]; i0 = in[8*k+1]; r1 = in[8*k+2]; i1 = in[8*k+3]; r2 = in[8*k+4]; i2 = in[8*k+5]; r3 = in[8*k+6]; i3 = in[8*k+7]; sr0 = VADD(r0,r2); dr0 = VSUB(r0, r2); sr1 = VADD(r1,r3); dr1 = VSUB(r1, r3); si0 = VADD(i0,i2); di0 = VSUB(i0, i2); si1 = VADD(i1,i3); di1 = VSUB(i1, i3); r0 = VADD(sr0, sr1); i0 = VADD(si0, si1); r1 = VSUB(dr0, di1); i1 = VADD(di0, dr1); r2 = VSUB(sr0, sr1); i2 = VSUB(si0, si1); r3 = VADD(dr0, di1); i3 = VSUB(di0, dr1); VCPLXMULCONJ(r1,i1,e[k*6+0],e[k*6+1]); VCPLXMULCONJ(r2,i2,e[k*6+2],e[k*6+3]); VCPLXMULCONJ(r3,i3,e[k*6+4],e[k*6+5]); VTRANSPOSE4(r0,r1,r2,r3); VTRANSPOSE4(i0,i1,i2,i3); *out++ = r0; *out++ = i0; *out++ = r1; *out++ = i1; *out++ = r2; *out++ = i2; *out++ = r3; *out++ = i3; } } static ALWAYS_INLINE(void) pffft_real_finalize_4x4(const v4sf *in0, const v4sf *in1, const v4sf *in, const v4sf *e, v4sf *out) { v4sf r0, i0, r1, i1, r2, i2, r3, i3; v4sf sr0, dr0, sr1, dr1, si0, di0, si1, di1; r0 = *in0; i0 = *in1; r1 = *in++; i1 = *in++; r2 = *in++; i2 = *in++; r3 = *in++; i3 = *in++; VTRANSPOSE4(r0,r1,r2,r3); VTRANSPOSE4(i0,i1,i2,i3); /* transformation for each column is: [1 1 1 1 0 0 0 0] [r0] [1 0 -1 0 0 -1 0 1] [r1] [1 0 -1 0 0 1 0 -1] [r2] [1 -1 1 -1 0 0 0 0] [r3] [0 0 0 0 1 1 1 1] * [i0] [0 -1 0 1 -1 0 1 0] [i1] [0 -1 0 1 1 0 -1 0] [i2] [0 0 0 0 -1 1 -1 1] [i3] */ //cerr << "matrix initial, before e , REAL:\n 1: " << r0 << "\n 1: " << r1 << "\n 1: " << r2 << "\n 1: " << r3 << "\n"; //cerr << "matrix initial, before e, IMAG :\n 1: " << i0 << "\n 1: " << i1 << "\n 1: " << i2 << "\n 1: " << i3 << "\n"; VCPLXMUL(r1,i1,e[0],e[1]); VCPLXMUL(r2,i2,e[2],e[3]); VCPLXMUL(r3,i3,e[4],e[5]); //cerr << "matrix initial, real part:\n 1: " << r0 << "\n 1: " << r1 << "\n 1: " << r2 << "\n 1: " << r3 << "\n"; //cerr << "matrix initial, imag part:\n 1: " << i0 << "\n 1: " << i1 << "\n 1: " << i2 << "\n 1: " << i3 << "\n"; sr0 = VADD(r0,r2); dr0 = VSUB(r0,r2); sr1 = VADD(r1,r3); dr1 = VSUB(r3,r1); si0 = VADD(i0,i2); di0 = VSUB(i0,i2); si1 = VADD(i1,i3); di1 = VSUB(i3,i1); r0 = VADD(sr0, sr1); r3 = VSUB(sr0, sr1); i0 = VADD(si0, si1); i3 = VSUB(si1, si0); r1 = VADD(dr0, di1); r2 = VSUB(dr0, di1); i1 = VSUB(dr1, di0); i2 = VADD(dr1, di0); *out++ = r0; *out++ = i0; *out++ = r1; *out++ = i1; *out++ = r2; *out++ = i2; *out++ = r3; *out++ = i3; } static NEVER_INLINE(void) pffft_real_finalize(int Ncvec, const v4sf *in, v4sf *out, const v4sf *e) { int k, dk = Ncvec/SIMD_SZ; // number of 4x4 matrix blocks /* fftpack order is f0r f1r f1i f2r f2i ... f(n-1)r f(n-1)i f(n)r */ v4sf_union cr, ci, *uout = (v4sf_union*)out; v4sf save = in[7], zero=VZERO(); float xr0, xi0, xr1, xi1, xr2, xi2, xr3, xi3; static const float s = M_SQRT2/2; cr.v = in[0]; ci.v = in[Ncvec*2-1]; assert(in != out); pffft_real_finalize_4x4(&zero, &zero, in+1, e, out); /* [cr0 cr1 cr2 cr3 ci0 ci1 ci2 ci3] [Xr(1)] ] [1 1 1 1 0 0 0 0] [Xr(N/4) ] [0 0 0 0 1 s 0 -s] [Xr(N/2) ] [1 0 -1 0 0 0 0 0] [Xr(3N/4)] [0 0 0 0 1 -s 0 s] [Xi(1) ] [1 -1 1 -1 0 0 0 0] [Xi(N/4) ] [0 0 0 0 0 -s -1 -s] [Xi(N/2) ] [0 -1 0 1 0 0 0 0] [Xi(3N/4)] [0 0 0 0 0 -s 1 -s] */ xr0=(cr.f[0]+cr.f[2]) + (cr.f[1]+cr.f[3]); uout[0].f[0] = xr0; xi0=(cr.f[0]+cr.f[2]) - (cr.f[1]+cr.f[3]); uout[1].f[0] = xi0; xr2=(cr.f[0]-cr.f[2]); uout[4].f[0] = xr2; xi2=(cr.f[3]-cr.f[1]); uout[5].f[0] = xi2; xr1= ci.f[0] + s*(ci.f[1]-ci.f[3]); uout[2].f[0] = xr1; xi1=-ci.f[2] - s*(ci.f[1]+ci.f[3]); uout[3].f[0] = xi1; xr3= ci.f[0] - s*(ci.f[1]-ci.f[3]); uout[6].f[0] = xr3; xi3= ci.f[2] - s*(ci.f[1]+ci.f[3]); uout[7].f[0] = xi3; for (k=1; k < dk; ++k) { v4sf save_next = in[8*k+7]; pffft_real_finalize_4x4(&save, &in[8*k+0], in + 8*k+1, e + k*6, out + k*8); save = save_next; } } static ALWAYS_INLINE(void) pffft_real_preprocess_4x4(const v4sf *in, const v4sf *e, v4sf *out, int first) { v4sf r0=in[0], i0=in[1], r1=in[2], i1=in[3], r2=in[4], i2=in[5], r3=in[6], i3=in[7]; /* transformation for each column is: [1 1 1 1 0 0 0 0] [r0] [1 0 0 -1 0 -1 -1 0] [r1] [1 -1 -1 1 0 0 0 0] [r2] [1 0 0 -1 0 1 1 0] [r3] [0 0 0 0 1 -1 1 -1] * [i0] [0 -1 1 0 1 0 0 1] [i1] [0 0 0 0 1 1 -1 -1] [i2] [0 1 -1 0 1 0 0 1] [i3] */ v4sf sr0 = VADD(r0,r3), dr0 = VSUB(r0,r3); v4sf sr1 = VADD(r1,r2), dr1 = VSUB(r1,r2); v4sf si0 = VADD(i0,i3), di0 = VSUB(i0,i3); v4sf si1 = VADD(i1,i2), di1 = VSUB(i1,i2); r0 = VADD(sr0, sr1); r2 = VSUB(sr0, sr1); r1 = VSUB(dr0, si1); r3 = VADD(dr0, si1); i0 = VSUB(di0, di1); i2 = VADD(di0, di1); i1 = VSUB(si0, dr1); i3 = VADD(si0, dr1); VCPLXMULCONJ(r1,i1,e[0],e[1]); VCPLXMULCONJ(r2,i2,e[2],e[3]); VCPLXMULCONJ(r3,i3,e[4],e[5]); VTRANSPOSE4(r0,r1,r2,r3); VTRANSPOSE4(i0,i1,i2,i3); if (!first) { *out++ = r0; *out++ = i0; } *out++ = r1; *out++ = i1; *out++ = r2; *out++ = i2; *out++ = r3; *out++ = i3; } static NEVER_INLINE(void) pffft_real_preprocess(int Ncvec, const v4sf *in, v4sf *out, const v4sf *e) { int k, dk = Ncvec/SIMD_SZ; // number of 4x4 matrix blocks /* fftpack order is f0r f1r f1i f2r f2i ... f(n-1)r f(n-1)i f(n)r */ v4sf_union Xr, Xi, *uout = (v4sf_union*)out; float cr0, ci0, cr1, ci1, cr2, ci2, cr3, ci3; static const float s = M_SQRT2; assert(in != out); for (k=0; k < 4; ++k) { Xr.f[k] = ((float*)in)[8*k]; Xi.f[k] = ((float*)in)[8*k+4]; } pffft_real_preprocess_4x4(in, e, out+1, 1); // will write only 6 values /* [Xr0 Xr1 Xr2 Xr3 Xi0 Xi1 Xi2 Xi3] [cr0] [1 0 2 0 1 0 0 0] [cr1] [1 0 0 0 -1 0 -2 0] [cr2] [1 0 -2 0 1 0 0 0] [cr3] [1 0 0 0 -1 0 2 0] [ci0] [0 2 0 2 0 0 0 0] [ci1] [0 s 0 -s 0 -s 0 -s] [ci2] [0 0 0 0 0 -2 0 2] [ci3] [0 -s 0 s 0 -s 0 -s] */ for (k=1; k < dk; ++k) { pffft_real_preprocess_4x4(in+8*k, e + k*6, out-1+k*8, 0); } cr0=(Xr.f[0]+Xi.f[0]) + 2*Xr.f[2]; uout[0].f[0] = cr0; cr1=(Xr.f[0]-Xi.f[0]) - 2*Xi.f[2]; uout[0].f[1] = cr1; cr2=(Xr.f[0]+Xi.f[0]) - 2*Xr.f[2]; uout[0].f[2] = cr2; cr3=(Xr.f[0]-Xi.f[0]) + 2*Xi.f[2]; uout[0].f[3] = cr3; ci0= 2*(Xr.f[1]+Xr.f[3]); uout[2*Ncvec-1].f[0] = ci0; ci1= s*(Xr.f[1]-Xr.f[3]) - s*(Xi.f[1]+Xi.f[3]); uout[2*Ncvec-1].f[1] = ci1; ci2= 2*(Xi.f[3]-Xi.f[1]); uout[2*Ncvec-1].f[2] = ci2; ci3=-s*(Xr.f[1]-Xr.f[3]) - s*(Xi.f[1]+Xi.f[3]); uout[2*Ncvec-1].f[3] = ci3; } void pffft_transform_internal(PFFFT_Setup *setup, const float *finput, float *foutput, v4sf *scratch, pffft_direction_t direction, int ordered) { int k, Ncvec = setup->Ncvec; int nf_odd = (setup->ifac[1] & 1); // temporary buffer is allocated on the stack if the scratch pointer is NULL int stack_allocate = (scratch == 0 ? Ncvec*2 : 1); VLA_ARRAY_ON_STACK(v4sf, scratch_on_stack, stack_allocate); const v4sf *vinput = (const v4sf*)finput; v4sf *voutput = (v4sf*)foutput; v4sf *buff[2] = { voutput, scratch ? scratch : scratch_on_stack }; int ib = (nf_odd ^ ordered ? 1 : 0); assert(VALIGNED(finput) && VALIGNED(foutput)); //assert(finput != foutput); if (direction == PFFFT_FORWARD) { ib = !ib; if (setup->transform == PFFFT_REAL) { ib = (rfftf1_ps(Ncvec*2, vinput, buff[ib], buff[!ib], setup->twiddle, &setup->ifac[0]) == buff[0] ? 0 : 1); pffft_real_finalize(Ncvec, buff[ib], buff[!ib], (v4sf*)setup->e); } else { v4sf *tmp = buff[ib]; for (k=0; k < Ncvec; ++k) { UNINTERLEAVE2(vinput[k*2], vinput[k*2+1], tmp[k*2], tmp[k*2+1]); } ib = (cfftf1_ps(Ncvec, buff[ib], buff[!ib], buff[ib], setup->twiddle, &setup->ifac[0], -1) == buff[0] ? 0 : 1); pffft_cplx_finalize(Ncvec, buff[ib], buff[!ib], (v4sf*)setup->e); } if (ordered) { pffft_zreorder(setup, (float*)buff[!ib], (float*)buff[ib], PFFFT_FORWARD); } else ib = !ib; } else { if (vinput == buff[ib]) { ib = !ib; // may happen when finput == foutput } if (ordered) { pffft_zreorder(setup, (float*)vinput, (float*)buff[ib], PFFFT_BACKWARD); vinput = buff[ib]; ib = !ib; } if (setup->transform == PFFFT_REAL) { pffft_real_preprocess(Ncvec, vinput, buff[ib], (v4sf*)setup->e); ib = (rfftb1_ps(Ncvec*2, buff[ib], buff[0], buff[1], setup->twiddle, &setup->ifac[0]) == buff[0] ? 0 : 1); } else { pffft_cplx_preprocess(Ncvec, vinput, buff[ib], (v4sf*)setup->e); ib = (cfftf1_ps(Ncvec, buff[ib], buff[0], buff[1], setup->twiddle, &setup->ifac[0], +1) == buff[0] ? 0 : 1); for (k=0; k < Ncvec; ++k) { INTERLEAVE2(buff[ib][k*2], buff[ib][k*2+1], buff[ib][k*2], buff[ib][k*2+1]); } } } if (buff[ib] != voutput) { /* extra copy required -- this situation should only happen when finput == foutput */ assert(finput==foutput); for (k=0; k < Ncvec; ++k) { v4sf a = buff[ib][2*k], b = buff[ib][2*k+1]; voutput[2*k] = a; voutput[2*k+1] = b; } ib = !ib; } assert(buff[ib] == voutput); } void pffft_zconvolve_accumulate(PFFFT_Setup *s, const float *a, const float *b, float *ab, float scaling) { int Ncvec = s->Ncvec; const v4sf * RESTRICT va = (const v4sf*)a; const v4sf * RESTRICT vb = (const v4sf*)b; v4sf * RESTRICT vab = (v4sf*)ab; #ifdef __arm__ __builtin_prefetch(va); __builtin_prefetch(vb); __builtin_prefetch(vab); __builtin_prefetch(va+2); __builtin_prefetch(vb+2); __builtin_prefetch(vab+2); __builtin_prefetch(va+4); __builtin_prefetch(vb+4); __builtin_prefetch(vab+4); __builtin_prefetch(va+6); __builtin_prefetch(vb+6); __builtin_prefetch(vab+6); # ifndef __clang__ # define ZCONVOLVE_USING_INLINE_NEON_ASM # endif #endif float ar, ai, br, bi, abr, abi; #ifndef ZCONVOLVE_USING_INLINE_ASM v4sf vscal = LD_PS1(scaling); int i; #endif assert(VALIGNED(a) && VALIGNED(b) && VALIGNED(ab)); ar = ((v4sf_union*)va)[0].f[0]; ai = ((v4sf_union*)va)[1].f[0]; br = ((v4sf_union*)vb)[0].f[0]; bi = ((v4sf_union*)vb)[1].f[0]; abr = ((v4sf_union*)vab)[0].f[0]; abi = ((v4sf_union*)vab)[1].f[0]; #ifdef ZCONVOLVE_USING_INLINE_ASM // inline asm version, unfortunately miscompiled by clang 3.2, at least on ubuntu.. so this will be restricted to gcc const float *a_ = a, *b_ = b; float *ab_ = ab; int N = Ncvec; asm volatile("mov r8, %2 \n" "vdup.f32 q15, %4 \n" "1: \n" "pld [%0,#64] \n" "pld [%1,#64] \n" "pld [%2,#64] \n" "pld [%0,#96] \n" "pld [%1,#96] \n" "pld [%2,#96] \n" "vld1.f32 {q0,q1}, [%0,:128]! \n" "vld1.f32 {q4,q5}, [%1,:128]! \n" "vld1.f32 {q2,q3}, [%0,:128]! \n" "vld1.f32 {q6,q7}, [%1,:128]! \n" "vld1.f32 {q8,q9}, [r8,:128]! \n" "vmul.f32 q10, q0, q4 \n" "vmul.f32 q11, q0, q5 \n" "vmul.f32 q12, q2, q6 \n" "vmul.f32 q13, q2, q7 \n" "vmls.f32 q10, q1, q5 \n" "vmla.f32 q11, q1, q4 \n" "vld1.f32 {q0,q1}, [r8,:128]! \n" "vmls.f32 q12, q3, q7 \n" "vmla.f32 q13, q3, q6 \n" "vmla.f32 q8, q10, q15 \n" "vmla.f32 q9, q11, q15 \n" "vmla.f32 q0, q12, q15 \n" "vmla.f32 q1, q13, q15 \n" "vst1.f32 {q8,q9},[%2,:128]! \n" "vst1.f32 {q0,q1},[%2,:128]! \n" "subs %3, #2 \n" "bne 1b \n" : "+r"(a_), "+r"(b_), "+r"(ab_), "+r"(N) : "r"(scaling) : "r8", "q0","q1","q2","q3","q4","q5","q6","q7","q8","q9", "q10","q11","q12","q13","q15","memory"); #else // default routine, works fine for non-arm cpus with current compilers for (i=0; i < Ncvec; i += 2) { v4sf ar, ai, br, bi; ar = va[2*i+0]; ai = va[2*i+1]; br = vb[2*i+0]; bi = vb[2*i+1]; VCPLXMUL(ar, ai, br, bi); vab[2*i+0] = VMADD(ar, vscal, vab[2*i+0]); vab[2*i+1] = VMADD(ai, vscal, vab[2*i+1]); ar = va[2*i+2]; ai = va[2*i+3]; br = vb[2*i+2]; bi = vb[2*i+3]; VCPLXMUL(ar, ai, br, bi); vab[2*i+2] = VMADD(ar, vscal, vab[2*i+2]); vab[2*i+3] = VMADD(ai, vscal, vab[2*i+3]); } #endif if (s->transform == PFFFT_REAL) { ((v4sf_union*)vab)[0].f[0] = abr + ar*br*scaling; ((v4sf_union*)vab)[1].f[0] = abi + ai*bi*scaling; } } #else // defined(PFFFT_SIMD_DISABLE) // standard routine using scalar floats, without SIMD stuff. #define pffft_zreorder_nosimd pffft_zreorder void pffft_zreorder_nosimd(PFFFT_Setup *setup, const float *in, float *out, pffft_direction_t direction) { int k, N = setup->N; if (setup->transform == PFFFT_COMPLEX) { for (k=0; k < 2*N; ++k) out[k] = in[k]; return; } else if (direction == PFFFT_FORWARD) { float x_N = in[N-1]; for (k=N-1; k > 1; --k) out[k] = in[k-1]; out[0] = in[0]; out[1] = x_N; } else { float x_N = in[1]; for (k=1; k < N-1; ++k) out[k] = in[k+1]; out[0] = in[0]; out[N-1] = x_N; } } #define pffft_transform_internal_nosimd pffft_transform_internal void pffft_transform_internal_nosimd(PFFFT_Setup *setup, const float *input, float *output, float *scratch, pffft_direction_t direction, int ordered) { int Ncvec = setup->Ncvec; int nf_odd = (setup->ifac[1] & 1); // temporary buffer is allocated on the stack if the scratch pointer is NULL int stack_allocate = (scratch == 0 ? Ncvec*2 : 1); VLA_ARRAY_ON_STACK(v4sf, scratch_on_stack, stack_allocate); float *buff[2]; int ib; if (scratch == 0) scratch = scratch_on_stack; buff[0] = output; buff[1] = scratch; if (setup->transform == PFFFT_COMPLEX) ordered = 0; // it is always ordered. ib = (nf_odd ^ ordered ? 1 : 0); if (direction == PFFFT_FORWARD) { if (setup->transform == PFFFT_REAL) { ib = (rfftf1_ps(Ncvec*2, input, buff[ib], buff[!ib], setup->twiddle, &setup->ifac[0]) == buff[0] ? 0 : 1); } else { ib = (cfftf1_ps(Ncvec, input, buff[ib], buff[!ib], setup->twiddle, &setup->ifac[0], -1) == buff[0] ? 0 : 1); } if (ordered) { pffft_zreorder(setup, buff[ib], buff[!ib], PFFFT_FORWARD); ib = !ib; } } else { if (input == buff[ib]) { ib = !ib; // may happen when finput == foutput } if (ordered) { pffft_zreorder(setup, input, buff[!ib], PFFFT_BACKWARD); input = buff[!ib]; } if (setup->transform == PFFFT_REAL) { ib = (rfftb1_ps(Ncvec*2, input, buff[ib], buff[!ib], setup->twiddle, &setup->ifac[0]) == buff[0] ? 0 : 1); } else { ib = (cfftf1_ps(Ncvec, input, buff[ib], buff[!ib], setup->twiddle, &setup->ifac[0], +1) == buff[0] ? 0 : 1); } } if (buff[ib] != output) { int k; // extra copy required -- this situation should happens only when finput == foutput assert(input==output); for (k=0; k < Ncvec; ++k) { float a = buff[ib][2*k], b = buff[ib][2*k+1]; output[2*k] = a; output[2*k+1] = b; } ib = !ib; } assert(buff[ib] == output); } #define pffft_zconvolve_accumulate_nosimd pffft_zconvolve_accumulate void pffft_zconvolve_accumulate_nosimd(PFFFT_Setup *s, const float *a, const float *b, float *ab, float scaling) { int i, Ncvec = s->Ncvec; if (s->transform == PFFFT_REAL) { // take care of the fftpack ordering ab[0] += a[0]*b[0]*scaling; ab[2*Ncvec-1] += a[2*Ncvec-1]*b[2*Ncvec-1]*scaling; ++ab; ++a; ++b; --Ncvec; } for (i=0; i < Ncvec; ++i) { float ar, ai, br, bi; ar = a[2*i+0]; ai = a[2*i+1]; br = b[2*i+0]; bi = b[2*i+1]; VCPLXMUL(ar, ai, br, bi); ab[2*i+0] += ar*scaling; ab[2*i+1] += ai*scaling; } } #endif // defined(PFFFT_SIMD_DISABLE) void pffft_transform(PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction) { pffft_transform_internal(setup, input, output, (v4sf*)work, direction, 0); } void pffft_transform_ordered(PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction) { pffft_transform_internal(setup, input, output, (v4sf*)work, direction, 1); } csound-6.10.0/OOps/pstream.c000066400000000000000000000667311321653344700156150ustar00rootroot00000000000000/* pstream.c: Copyright (C) 2001 Richard Dobson, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* TODO: split into two files: pvsimp.c for just the CARL anal/synth code, under LGPL, pvsops.c for everythng else, under ???? */ #include "csoundCore.h" #include "pstream.h" #include "pvfileio.h" #ifdef _DEBUG #include #endif int fsigs_equal(const PVSDAT *f1, const PVSDAT *f2) { if ((f1->overlap == f2->overlap) && (f1->winsize == f2->winsize) && (f1->wintype == f2->wintype) /* harsh, maybe... */ && (f1->N == f2->N) && (f1->format == f2->format) && (f1->sliding == f2->sliding) ) return 1; return 0; } /* Pandora's box opcode, but we can make it at least plausible, by forbidding copy to different format. */ int fassign_set(CSOUND *csound, FASSIGN *p) { int32 N = p->fsrc->N; p->fout->N = N; p->fout->overlap = p->fsrc->overlap; p->fout->winsize = p->fsrc->winsize; p->fout->wintype = p->fsrc->wintype; p->fout->format = p->fsrc->format; p->fout->sliding = p->fsrc->sliding; /* sliding needs to be checked */ if (p->fsrc->sliding) { p->fout->NB = p->fsrc->NB; csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT) * csound->ksmps, &p->fout->frame); return OK; } if (p->fsrc->format < 0){ p->fout->frame.auxp = p->fsrc->frame.auxp; p->fout->frame.size = p->fsrc->frame.size; //csound->Message(csound, Str("fsig = : init\n")); } else csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame); p->fout->framecount = 1; //csound->Message(csound, Str("fsig = : init\n")); return OK; } int fassign(CSOUND *csound, FASSIGN *p) { int32 framesize; float *fout,*fsrc; fout = (float *) p->fout->frame.auxp; fsrc = (float *) p->fsrc->frame.auxp; if (fout == fsrc) { //csound->Message(csound, Str("fsig = : no cpy\n")); return OK; } // if (UNLIKELY(!fsigs_equal(p->fout,p->fsrc))) //return csound->PerfError(csound,p->h.insdshead, // Str("fsig = : formats are different.\n")); if (p->fsrc->sliding) { memcpy(p->fout->frame.auxp, p->fsrc->frame.auxp, sizeof(MYFLT)*(p->fsrc->N+2)*csound->ksmps); return OK; } framesize = p->fsrc->N + 2; if (p->fout->framecount == p->fsrc->framecount) {/* avoid duplicate copying*/ memcpy(fout, fsrc, framesize*sizeof(float)); p->fout->framecount++; } return OK; } /************* OSCBANK SYNTH ***********/ int pvadsynset(CSOUND *csound, PVADS *p) { /* get params from input fsig */ /* we trust they are legit! */ int i; PVSDAT *fs = p->fsig; int32 N = fs->N; int32 noscs,n_oscs; int32 startbin,binoffset; MYFLT *p_x; if (UNLIKELY(fs->sliding)) return csound->InitError(csound, Str("Sliding version not yet available")); p->overlap = fs->overlap; /* a moot question, whether window params are relevant for adsyn?*/ /* but for now, we validate all params in fsig */ p->winsize = fs->winsize; p->wintype = fs->wintype; p->fftsize = N; noscs = N/2 + 1; /* max possible */ n_oscs = (int32) *p->n_oscs; /* user param*/ if (UNLIKELY(n_oscs <=0)) csound->InitError(csound, Str("pvadsyn: bad value for inoscs\n")); /* remove this when I know how to do it... */ if (UNLIKELY(fs->format != PVS_AMP_FREQ)) return csound->InitError(csound, Str("pvadsyn: format must be amp-freq (0).\n")); p->format = fs->format; /* interesting question: could noscs be krate variable? * answer: yes, but adds complexity to oscbank, as have to set/reset each osc when started and stopped */ /* check bin params */ startbin = (int32) *p->ibin; /* default 0 */ binoffset = (int32) *p->ibinoffset; /* default 1 */ if (UNLIKELY(startbin < 0 || startbin > noscs)) return csound->InitError(csound, Str("pvsadsyn: ibin parameter out of range.\n")); if (UNLIKELY(startbin + n_oscs > noscs)) return csound->InitError(csound, Str("pvsadsyn: ibin + inoscs too large.\n")); /* calc final max bin target */ p->maxosc = startbin + (n_oscs * binoffset); if (UNLIKELY(p->maxosc > noscs)) return csound->InitError(csound, Str("pvsadsyn: " "ibin + (inoscs * ibinoffset) too large.")); p->outptr = 0; p->lastframe = 0; /* p->one_over_sr = (float) csound->onedsr; */ /* p->pi_over_sr = (float) csound->pidsr; */ p->one_over_overlap = (float)(FL(1.0) / p->overlap); /* alloc for all oscs; in case we can do something with them dynamically, one day */ csound->AuxAlloc(csound, noscs * sizeof(MYFLT),&p->a); csound->AuxAlloc(csound, noscs * sizeof(MYFLT),&p->x); csound->AuxAlloc(csound, noscs * sizeof(MYFLT),&p->y); csound->AuxAlloc(csound, noscs * sizeof(MYFLT),&p->amps); csound->AuxAlloc(csound, noscs * sizeof(MYFLT),&p->lastamps); csound->AuxAlloc(csound, noscs * sizeof(MYFLT),&p->freqs); csound->AuxAlloc(csound, p->overlap * sizeof(MYFLT),&p->outbuf); /* initialize oscbank */ p_x = (MYFLT *) p->x.auxp; for (i=0;i < noscs;i++) p_x[i] = FL(1.0); return OK; } /* c/o John Lazzaro, for SAOL, and many other sources */ static inline MYFLT fastoscil(MYFLT *a, MYFLT *x, MYFLT *y) { *x = *x - *a * *y; *y = *y + *a * *x; /* expensive, but worth it for evenness ? */ if (*y < FL(-1.0)) *y = FL(-1.0); if (*y > FL(1.0)) *y = FL(1.0); return *y; } static void adsyn_frame(CSOUND *csound, PVADS *p) { int i,j; int32 startbin,lastbin,binoffset; MYFLT *outbuf = (MYFLT *) (p->outbuf.auxp); float *frame; /* RWD MUST be 32bit */ MYFLT *a,*x,*y; MYFLT *amps,*freqs,*lastamps; MYFLT ffac = *p->kfmod; MYFLT nyquist = csound->esr * FL(0.5); /* we add to outbuf, so clear it first*/ memset(p->outbuf.auxp,0,p->overlap * sizeof(MYFLT)); frame = (float *) p->fsig->frame.auxp; a = (MYFLT *) p->a.auxp; x = (MYFLT *) p->x.auxp; y = (MYFLT *) p->y.auxp; amps = (MYFLT *) p->amps.auxp; freqs = (MYFLT *) p->freqs.auxp; lastamps = (MYFLT *) p->lastamps.auxp; startbin = (int32) *p->ibin; binoffset = (int32) *p->ibinoffset; lastbin = p->maxosc; /*update amps, freqs*/ for (i=startbin;i < lastbin;i+= binoffset) { amps[i] = frame[i*2]; /* lazy: force all freqs positive! */ freqs[i] = ffac * FABS(frame[(i*2)+1]); /* kill stuff over Nyquist. Need to worry about vlf values? */ if (freqs[i] > nyquist) amps[i] = FL(0.0); a[i] = FL(2.0) * SIN(freqs[i] * csound->pidsr); } /* we need to interp amplitude, but seems we can avoid doing freqs too, for pvoc so can use direct calc for speed. But large overlap size is not a good idea. If compiler cannot inline fastoscil, would be worth doing so by hand here ? */ for (i=startbin;i < lastbin;i+=binoffset) { MYFLT thisamp = lastamps[i]; MYFLT delta_amp = (amps[i] - thisamp) * p->one_over_overlap; for (j=0;j < p->overlap;j++) { outbuf[j] += thisamp * fastoscil(a+i,x+i,y+i); thisamp += delta_amp; } lastamps[i] = amps[i]; } } static MYFLT adsyn_tick(CSOUND *csound, PVADS *p) { MYFLT *outbuf = (MYFLT *) (p->outbuf.auxp); if (p->outptr== p->fsig->overlap) { adsyn_frame(csound, p); p->outptr = 0; p->lastframe = p->fsig->framecount; } return outbuf[p->outptr++]; } int pvadsyn(CSOUND *csound, PVADS *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT *aout = p->aout; if (UNLIKELY(p->outbuf.auxp==NULL)) { return csound->PerfError(csound,p->h.insdshead, Str("pvsynth: Not initialised.\n")); } if (UNLIKELY(offset)) memset(aout, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&aout[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset;i < nsmps;i++) aout[i] = adsyn_tick(csound, p); return OK; } /******* PVSCROSS ***********/ int pvscrosset(CSOUND *csound, PVSCROSS *p) { PVSDAT *fsrc = p->fsrc; PVSDAT *fout = p->fout; int32 N = fsrc->N; /* source fsig */ p->overlap = fsrc->overlap; p->winsize = fsrc->winsize; p->wintype = fsrc->wintype; p->fftsize = N; p->format = fsrc->format; /* make sure fdest is same format */ if (UNLIKELY(!fsigs_equal(fsrc,p->fdest))) return csound->InitError(csound, Str("pvscross: source and dest signals " "must have same format\n")); fout->N = N; fout->overlap = p->overlap; fout->winsize = p->winsize; fout->wintype = p->wintype; fout->format = p->format; // fout->format = p->fsrc->sliding; if (fsrc->sliding) { fout->NB = fsrc->NB; csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT) * CS_KSMPS, &fout->frame); return OK; } /* setup output signal */ /* RWD MUST be 32bit */ csound->AuxAlloc(csound, (N + 2) * sizeof(float), &fout->frame); fout->framecount = 1; p->lastframe = 0; return OK; } int pvscross(CSOUND *csound, PVSCROSS *p) { int32 i,N = p->fftsize; MYFLT amp1 = FABS(*p->kamp1); MYFLT amp2 = FABS(*p->kamp2); float *fsrc = (float *) p->fsrc->frame.auxp; /* RWD all must be 32bit */ float *fdest = (float *) p->fdest->frame.auxp; float *fout = (float *) p->fout->frame.auxp; if (UNLIKELY(fout==NULL)) return csound->PerfError(csound,p->h.insdshead, Str("pvscross: not initialised\n")); /* make sure sigs have same format as output */ if (UNLIKELY(!fsigs_equal(p->fout,p->fsrc))) return csound->PerfError(csound,p->h.insdshead, Str("pvscross: mismatch in fsrc format\n")); if (UNLIKELY(!fsigs_equal(p->fout,p->fdest))) return csound->PerfError(csound,p->h.insdshead, Str("pvscross: mismatch in fdest format\n")); if (p->fsrc->sliding) { CMPLX *fout, *fsrc, *fdest; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int NB = p->fsrc->NB; nsmps -= early; for (n=offset; nfsrc->frame.auxp +n*NB; /* RWD all must be 32bit */ fdest = (CMPLX *) p->fdest->frame.auxp +n*NB; fout = (CMPLX *) p->fout->frame.auxp +n*NB; for (i=0; ilastframe < p->fsrc->framecount) { #ifdef _DEBUG assert(p->fsrc->framecount==p->fdest->framecount); #endif for (i=0;i < N+2;i+=2) { fout[i] = (float) ((fsrc[i] * amp1) + (fdest[i] * amp2)); /* copy src freqs to output, unmodified */ fout[i+1] = (float) fsrc[i+1]; } p->fout->framecount = p->lastframe = p->fsrc->framecount; } return OK; } /******** PVSFREAD ************/ static int pvsfreadset_(CSOUND *csound, PVSFREAD *p, int stringname) { PVOCEX_MEMFILE pp; uint32 N; char pvfilnam[MAXNAME]; if (stringname) strncpy(pvfilnam, ((STRINGDAT*)p->ifilno)->data, MAXNAME-1); else if (csound->ISSTRCOD(*p->ifilno)) strncpy(pvfilnam, get_arg_string(csound, *p->ifilno), MAXNAME-1); else csound->strarg2name(csound, pvfilnam, p->ifilno, "pvoc.", 0); if (UNLIKELY(PVOCEX_LoadFile(csound, pvfilnam, &pp) != 0)) { return csound->InitError(csound, Str("Failed to load PVOC-EX file")); } p->ptr = 0; p->overlap = pp.overlap; p->winsize = pp.winsize; p->fftsize = pp.fftsize; p->wintype = pp.wintype; p->format = pp.format; p->chans = pp.chans; p->nframes = pp.nframes; p->arate = csound->esr / (MYFLT) pp.overlap; p->membase = (float*) pp.data; if (UNLIKELY(p->overlap < (int)CS_KSMPS || p->overlap < 10)) return csound->InitError(csound, Str("Sliding version not yet available")); if (UNLIKELY(p->nframes <= 0)) return csound->InitError(csound, Str("pvsfread: file is empty!\n")); /* special case if only one frame - it is an impulse response */ if (UNLIKELY(p->nframes == 1)) return csound->InitError(csound, Str("pvsfread: file has only one frame " "(= impulse response).\n")); if (UNLIKELY(p->overlap < (int)CS_KSMPS)) return csound->InitError(csound, Str("pvsfread: analysis frame overlap " "must be >= ksmps\n")); p->blockalign = (p->fftsize+2) * p->chans; if (UNLIKELY((*p->ichan) >= p->chans)) return csound->InitError(csound, Str("pvsfread: ichan value exceeds " "file channel count.\n")); if (UNLIKELY((int32) (*p->ichan) < 0)) return csound->InitError(csound, Str("pvsfread: ichan cannot be negative.\n")); N = p->fftsize; /* setup output signal */ csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame); /* init sig with first frame from file, regardless (always zero amps, but with bin freqs) */ p->chanoffset = (int32) MYFLT2LRND(*p->ichan) * (N + 2); memcpy((float *) p->fout->frame.auxp, /* RWD MUST be 32bit */ (float *) pp.data + (int32) p->chanoffset, /* RWD MUST be 32bit */ (size_t) ((int) (N + 2) * (int) sizeof(float))); p->membase += p->blockalign; /* move to 2nd frame in file, as startpoint */ p->nframes--; p->fout->N = N; p->fout->overlap = p->overlap; p->fout->winsize = p->winsize; p->fout->wintype = p->wintype; p->fout->format = p->format; p->fout->framecount = 1; p->lastframe = 0; return OK; } int pvsfreadset(CSOUND *csound, PVSFREAD *p){ return pvsfreadset_(csound,p, 0); } int pvsfreadset_S(CSOUND *csound, PVSFREAD *p){ return pvsfreadset_(csound,p, 1); } int pvsfread(CSOUND *csound, PVSFREAD *p) { int i,j; MYFLT pos = *p->kpos; MYFLT framepos,frac; int32 frame1pos,/*frame2pos,*/framesize,n_mcframes; float *pmem,*pframe1,*pframe2; /* RWD all MUST be 32bit */ float *fout = (float *) p->fout->frame.auxp; if (UNLIKELY(fout==NULL)) return csound->PerfError(csound,p->h.insdshead, Str("pvsfread: not initialised.\n")); pmem = (float *) p->membase; framesize = p->fftsize+2; n_mcframes = p->nframes / p->chans; if (p->ptr>=p->overlap) { if (UNLIKELY(pos < FL(0.0))) pos = FL(0.0); /* or report as error... */ framepos = pos * p->arate; frame1pos = (int32) framepos; if (frame1pos>= n_mcframes -1) { /* just return final frame */ pframe1 = pmem + (p->blockalign * (n_mcframes -1)) + p->chanoffset; /* for (i=0;i < framesize;i++) */ /* *fout++ = *pframe1++; */ memcpy(fout, pframe1, sizeof(float)*framesize); } else { /* gotta interpolate */ /* any optimizations possible here ? Avoid v samll frac values ? higher-order interp ? */ //frame2pos = frame1pos+p->chans; frac = framepos - (MYFLT) frame1pos; pframe1 = pmem + (frame1pos * p->blockalign) + p->chanoffset; pframe2 = pframe1 + p->blockalign; for (i=0;i < framesize;i+=2) { MYFLT amp,freq; j = i+1; amp = pframe1[i] + frac * (pframe2[i] - pframe1[i]); freq = pframe1[j] + frac * (pframe2[j] - pframe1[j]); fout[i] = (float) amp; fout[j] = (float) freq; } } p->ptr -= p->overlap; p->fout->framecount++; p->lastframe = p->fout->framecount; } p->ptr += CS_KSMPS; return OK; } /************* PVSMASKA ****************/ int pvsmaskaset(CSOUND *csound, PVSMASKA *p) { unsigned int i; MYFLT *ftable; uint32_t N = p->fsrc->N; uint32_t nbins = N/2 + 1; /* source fsig */ p->overlap = p->fsrc->overlap; p->winsize = p->fsrc->winsize; p->wintype = p->fsrc->wintype; p->format = p->fsrc->format; p->fftsize = N; if (UNLIKELY(!(p->format==PVS_AMP_FREQ) || (p->format==PVS_AMP_PHASE))) return csound->InitError(csound, Str("pvsmaska: " "signal format must be amp-phase or amp-freq.")); /* setup output signal */ p->fout->N = N; p->fout->overlap = p->overlap; p->fout->winsize = p->winsize; p->fout->wintype = p->wintype; p->fout->format = p->format; p->fout->sliding = p->fsrc->sliding; if (p->fsrc->sliding) { csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT) * CS_KSMPS, &p->fout->frame); p->fout->NB = p->fsrc->NB; } else { /* RWD MUST be 32bit */ csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame); p->fout->framecount = 1; p->lastframe = 0; } p->maskfunc = csound->FTnp2Find(csound, p->ifn); if (UNLIKELY(p->maskfunc==NULL)) return NOTOK; /* require at least size of nbins */ if (UNLIKELY(p->maskfunc->flen + 1 < nbins)) return csound->InitError(csound, Str("pvsmaska: ftable too small.\n")); /* clip any negative values in table */ ftable = p->maskfunc->ftable; for (i=0;i < p->maskfunc->flen+1;i++) if (ftable[i] < FL(0.0)) ftable[i] = FL(0.0); p->nwarned = p->pwarned = 0; return OK; } int pvsmaska(CSOUND *csound, PVSMASKA *p) { int i; int32 /*flen, */nbins; MYFLT *ftable; float *fout,*fsrc; /* RWD MUST be 32bit */ float margin, depth = (float)*p->kdepth; //flen = p->maskfunc->flen + 1; ftable = p->maskfunc->ftable; fout = (float *) p->fout->frame.auxp; /* RWD both MUST be 32bit */ fsrc = (float *) p->fsrc->frame.auxp; if (UNLIKELY(fout==NULL)) return csound->PerfError(csound,p->h.insdshead, Str("pvsmaska: not initialised\n")); if (depth < FL(0.0)) { /* need the warning: but krate linseg can give below-zeroes incorrectly */ if (UNLIKELY(!p->nwarned)) { csound->Warning(csound, Str("pvsmaska: negative value for kdepth; " "clipped to zero.\n")); p->nwarned = 1; } depth = 0.0f; } if (UNLIKELY(depth > 1.0f)) { if (UNLIKELY(!p->pwarned)) { csound->Warning(csound, Str("pvsmaska: kdepth > 1: clipped.\n")); p->pwarned = 1; } depth = 1.0f; } /* massage into internal mapping */ /* user 0 --> my 1 user 1 ---> my 0 user 0.75 -->my 0.25 */ depth = (1.0f - depth); margin = 1.0f - depth; if (p->fsrc->sliding) { int NB = p->fsrc->NB; CMPLX *fout, *fsrc; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT amp = FL(1.0); nsmps -= early; for (n=offset; nfout->frame.auxp +n*NB; fsrc = (CMPLX *) p->fsrc->frame.auxp +n*NB; for (i=0; ifftsize/2 + 1; /* only process when a new frame is ready */ if (p->lastframe < p->fsrc->framecount) { MYFLT amp = FL(1.0); int aindex, findex; for (i=0;i < nbins;i++) { amp = depth + margin * ftable[i]; aindex = i*2; findex = aindex +1; fout[aindex] = (float)(fsrc[aindex] * amp); /* freqs are unmodified */ fout[findex] = (float) fsrc[findex]; } p->fout->framecount = p->lastframe = p->fsrc->framecount; } return OK; } /**************PVSFTW ******************/ int pvsftwset(CSOUND *csound, PVSFTW *p) { int i; MYFLT *ftablea,*ftablef; float *fsrc; /* RWD MUST be 32bit */ int32 flena,flenf,nbins, N = p->fsrc->N; /* source fsig */ p->overlap = p->fsrc->overlap; p->winsize = p->fsrc->winsize; p->wintype = p->fsrc->wintype; p->format = p->fsrc->format; p->fftsize = N; p->outfna = p->outfnf = NULL; p->lastframe = 0; if (UNLIKELY(!(p->format==PVS_AMP_FREQ) || (p->format==PVS_AMP_PHASE))) return csound->InitError(csound, Str("pvsftw: signal format must be " "amp-phase or amp-freq.\n")); if (UNLIKELY(*p->ifna < 1.0f)) return csound->InitError(csound, Str("pvsftw: bad value for ifna.\n")); if (UNLIKELY(*p->ifnf < 0.0f)) /* 0 = notused */ return csound->InitError(csound, Str("pvsftw: bad value for ifnf.\n")); p->outfna = csound->FTnp2Find(csound, p->ifna); if (UNLIKELY(p->outfna==NULL)) return NOTOK; if (UNLIKELY(p->fsrc->sliding)) return csound->InitError(csound, Str("Sliding version not yet available")); fsrc = (float *) p->fsrc->frame.auxp; /* RWD MUST be 32bit */ /* init table, one presumes with zero amps */ nbins = p->fftsize/2 + 1; flena = p->outfna->flen + 1; if (UNLIKELY(flena < nbins)) return csound->InitError(csound, Str("pvsftw: amps ftable too small.\n")); /* init tables */ ftablea = p->outfna->ftable; for (i=0;i < nbins;i++) ftablea[i] = fsrc[i*2]; /* freq table? */ if ((int32) *p->ifnf >= 1) { p->outfnf = csound->FTnp2Find(csound, p->ifnf); if (UNLIKELY(p->outfnf==NULL)) return NOTOK; ftablef = p->outfnf->ftable; if (ftablef) { flenf = p->outfnf->flen+1; if (UNLIKELY(flenf < nbins)) return csound->InitError(csound, Str("pvsftw: freqs ftable too small.\n")); for (i=0;i < nbins;i++) ftablef[i] = fsrc[(i*2) + 1]; } } return OK; } int pvsftw(CSOUND *csound, PVSFTW *p) { int i; int32 nbins; MYFLT *ftablea, *ftablef = NULL; float *fsrc; /* RWD MUST be 32bit */ ftablea = p->outfna->ftable; fsrc = (float *) p->fsrc->frame.auxp; if (UNLIKELY(fsrc==NULL)) return csound->PerfError(csound,p->h.insdshead, Str("pvsftw: not initialised\n")); if (UNLIKELY(ftablea==NULL)) return csound->PerfError(csound,p->h.insdshead, Str("pvsftw: no amps ftable!\n")); if (p->outfnf) { ftablef = p->outfnf->ftable; if (UNLIKELY(ftablef==NULL)) return csound->PerfError(csound,p->h.insdshead, Str("pvsftw: no freqs ftable!\n")); } nbins = p->fftsize/2 + 1; /* only write when a new frame is ready */ if (p->lastframe < p->fsrc->framecount) { /* write amps */ for (i=0;i < nbins;i++) ftablea[i] = fsrc[i*2]; /* freqs */ if (ftablef) for (i=0;i < nbins;i++) ftablef[i] = fsrc[i*2 + 1]; p->lastframe = p->fsrc->framecount; /* tell everyone about it */ *p->kflag = FL(1.0); } else *p->kflag = FL(0.0); return OK; } /************ PVSFTR ****************/ int pvsftrset(CSOUND *csound, PVSFTR *p) { int i; float *fdest; /* RWD MUST be 32bit */ int32 flena,flenf,nbins, N = p->fdest->N; /* source fsig */ p->overlap = p->fdest->overlap; p->winsize = p->fdest->winsize; p->wintype = p->fdest->wintype; p->format = p->fdest->format; p->fftsize = N; p->infna = p->infnf = NULL; p->ftablea = p->ftablef = NULL; p->lastframe = 0; nbins = p->fftsize/2 + 1; if (UNLIKELY(!(p->format==PVS_AMP_FREQ) || (p->format==PVS_AMP_PHASE))) return csound->InitError(csound, Str("pvsftr: signal format must be " "amp-phase or amp-freq.\n")); /* ifn = 0 = notused */ if (UNLIKELY(*p->ifna < FL(0.0))) return csound->InitError(csound, Str("pvsftr: bad value for ifna.\n")); if (UNLIKELY(*p->ifnf < FL(0.0))) return csound->InitError(csound, Str("pvsftr: bad value for ifnf.\n")); /* if ifna=0; no amps to read; one assumes the user ias changing freqs only, otherwise, there is no change! */ if ((int32) *p->ifna != 0) { p->infna = csound->FTnp2Find(csound, p->ifna); if (UNLIKELY(p->infna==NULL)) return NOTOK; p->ftablea = p->infna->ftable; flena = p->infna->flen + 1; if (UNLIKELY(flena < nbins)) return csound->InitError(csound, Str("pvsftr: amps ftable too small.\n")); } if (UNLIKELY(p->overlap < (int)CS_KSMPS || p->overlap < 10)) return csound->InitError(csound, Str("Sliding version not yet available")); fdest = (float *) p->fdest->frame.auxp; /* RWD MUST be 32bit */ /*** setup first frame ?? */ if (p->ftablea) for (i=0;i < nbins;i++) fdest[i*2] = (float) p->ftablea[i]; /* freq table? */ if ((int32) *p->ifnf >= 1) { p->infnf = csound->FTnp2Find(csound, p->ifnf); if (UNLIKELY(p->infnf==NULL)) return NOTOK; p->ftablef = p->infnf->ftable; flenf = p->infnf->flen+1; if (UNLIKELY(flenf < nbins)) return csound->InitError(csound, Str("pvsftr: freqs ftable too small.\n")); for (i=0;i < nbins;i++) fdest[(i*2) + 1] = (float) p->ftablef[i]; } return OK; } int pvsftr(CSOUND *csound, PVSFTR *p) { int i; int32 nbins; float *fdest; /*RWD MUST be 32bit */ fdest = (float *) p->fdest->frame.auxp; if (UNLIKELY(fdest==NULL)) return csound->PerfError(csound,p->h.insdshead, Str("pvsftr: not initialised\n")); nbins = p->fftsize/2 + 1; /* only write when a new frame is ready */ if (p->lastframe < p->fdest->framecount) { if (p->ftablea) { for (i=0;i < nbins;i++) fdest[i*2] = (float) p->ftablea[i]; } if (p->ftablef) { for (i=0;i < nbins;i++) fdest[(i*2) + 1] = (float) p->ftablef[i]; } p->lastframe = p->fdest->framecount; } return OK; } /************** PVSINFO ***********/ int pvsinfo(CSOUND *csound, PVSINFO *p) { IGN(csound); #ifdef _DEBUG /* init stage opcode : this should always be a proper fsig */ assert(p->fsrc->frame.auxp != NULL); #endif *p->ioverlap = (MYFLT) p->fsrc->overlap; *p->inumbins = (MYFLT) (p->fsrc->N / 2) + 1; *p->iwinsize = (MYFLT) p->fsrc->winsize; *p->iformat = (MYFLT) p->fsrc->format; return OK; } csound-6.10.0/OOps/pvfileio.c000066400000000000000000001023201321653344700157400ustar00rootroot00000000000000/* pvfileio.c: Copyright (C) 2000 Richard Dobson (C) 2005 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* pvfileio.c * pvocex format test routines * * Initial version RWD May 2000. * All rights reserved: work in progress! * * Manifestly not a complete API yet! * In particular, error returns are kept very simplistic at the moment. * (and are not even very consistent yet...) * In time, a full set of error values and messages will be developed. * * NB: the RIFF functions only look for, and accept, a PVOCEX format file. * NB also: if windows.h is included anywhere (should be no need in this file, * or in pvfileio.h), * the WAVE_FORMAT~ symbols may need to be #ifndef-ed. */ /* very simple CUSTOM window chunk: * * * * where size as usual gives the size of the data in bytes. * the size in samples much match dwWinlen (which may not be the same * as N (fft length) * the sample type must be the same as that of the pvoc data itself * (only floatsams supported so far) * values must be normalised to peak of 1.0 */ /* CSOUND NB: floats must be kept as 'float', not MYFLT, as only 32bit floats supported at present. */ #include "csoundCore.h" #include "pvfileio.h" #if !defined(WAVE_FORMAT_EXTENSIBLE) #define WAVE_FORMAT_EXTENSIBLE (0xFFFE) #endif #ifndef WAVE_FORMAT_PCM #define WAVE_FORMAT_PCM (0x0001) #endif #define WAVE_FORMAT_IEEE_FLOAT (0x0003) #define PVFILETABLE ((PVOCFILE**) ((CSOUND*) csound)->pvFileTable) const GUID KSDATAFORMAT_SUBTYPE_PVOC = { 0x8312b9c2, 0x2e6e, 0x11d4, { 0xa8, 0x24, 0xde, 0x5b, 0x96, 0xc3, 0xab, 0x21 } }; typedef struct pvoc_file { WAVEFORMATEX fmtdata; PVOCDATA pvdata; int32 datachunkoffset; int32 nFrames; /* no of frames in file */ int32 FramePos; /* where we are in file */ FILE *fp; void *fd; int32 curpos; int to_delete; int readonly; char *name; float *customWindow; } PVOCFILE; static const char *pvErrorStrings[] = { Str_noop("\npvsys: (no error)"), /* 0 */ Str_noop("\npvsys: unknown error"), /* -1 */ Str_noop("\npvsys: already initialised"), /* -2 */ Str_noop("\npvsys: bad arguments"), /* -3 */ Str_noop("\npvsys: bad format parameter"), /* -4 */ Str_noop("\npvsys: bad window type"), /* -5 */ Str_noop("\npvsys: too many files open"), /* -6 */ Str_noop("\npvsys: unable to create file"), /* -7 */ Str_noop("\npvsys: Internal error: NULL data arrays"), /* -8 */ Str_noop("\npvsys: unable to open file"), /* -9 */ Str_noop("\npvsys: error reading Source format data"), /* -10 */ Str_noop("\npvsys: not a WAVE_EX file"), /* -11 */ Str_noop("\npvsys: bad size for fmt chunk"), /* -12 */ Str_noop("\npvsys: error reading Extended format data"), /* -13 */ Str_noop("\npvsys: not a PVOC-EX file"), /* -14 */ Str_noop("\npvsys: error reading Extended pvoc format data"), /* -15 */ Str_noop("\npvsys: unknown pvocex Version"), /* -16 */ Str_noop("\npvsys: error reading header"), /* -17 */ Str_noop("\npvsys: not a RIFF file"), /* -18 */ Str_noop("\npvsys: file too small"), /* -19 */ Str_noop("\npvsys: not a WAVE file"), /* -20 */ Str_noop("\npvsys: error reading format chunk"), /* -21 */ Str_noop("\npvsys: PVXW chunk found before fmt chunk."), /* -22 */ Str_noop("\npvsys: PVXW chunk found but custom window not specified"),/* -23 */ Str_noop("\npvsys: error reading window data."), /* -24 */ Str_noop("\npvsys: bad RIFF file"), /* -25 */ Str_noop("\npvsys: bad format, data chunk before fmt chunk"), /* -26 */ Str_noop("\npvsys: custom window chunk PVXW not found"), /* -27 */ Str_noop("\npvsys: error skipping unknown WAVE chunk"), /* -28 */ Str_noop("\npvsys: bad format in RIFF file"), /* -29 */ Str_noop("\npvsys: error writing header"), /* -30 */ Str_noop("\npvsys: error writing fmt chunk"), /* -31 */ Str_noop("\npvsys: error writing window data."), /* -32 */ Str_noop("\npvsys: error updating data chunk"), /* -33 */ Str_noop("\npvsys: error updating riff chunk"), /* -34 */ Str_noop("\npvsys: error seeking to end of file"), /* -35 */ Str_noop("\npvsys: file does not exist"), /* -36 */ Str_noop("\npvsys: file not open"), /* -37 */ Str_noop("\npvsys: bad file descriptor"), /* -38 */ Str_noop("\npvsys: error writing data"), /* -39 */ Str_noop("\npvsys: error reading data"), /* -40 */ Str_noop("\npvsys: error rewinding file"), /* -41 */ Str_noop("\npvsys: unable to close file on termination"), /* -42 */ NULL /* -43 */ }; static int pvoc_writeheader(CSOUND *csound, PVOCFILE *p); static int pvoc_readheader(CSOUND *csound, PVOCFILE *p, WAVEFORMATPVOCEX *pWfpx); /* thanks to the SNDAN programmers for this! */ /* return 1 for big-endian machine, 0 for little-endian machine */ static inline int byte_order(void) { const int one = 1; return (!*((char*) &one)); } /* low level file I/O */ static inline int pvfile_read_tag(PVOCFILE *p, char *s) { if (UNLIKELY((int) fread(s, 1, 4, p->fp) != 4)) { s[0] = '\0'; return -1; } s[4] = '\0'; return 0; } static inline int pvfile_write_tag(PVOCFILE *p, const char *s) { if (UNLIKELY((int) fwrite((void*) s, 1, 4, p->fp) != 4)) return -1; return 0; } static inline int32 pvfile_read_16(PVOCFILE *p, void *data, int32 cnt) { int32 n = (int32) fread(data, sizeof(uint16_t), (size_t) cnt, p->fp); if (byte_order()) { int32 i; uint16_t tmp; for (i = 0; i < n; i++) { tmp = ((uint16_t*) data)[i]; tmp = ((tmp & (uint16_t) 0xFF) << 8) | ((tmp & (uint16_t) 0xFF00) >> 8); ((uint16_t*) data)[i] = tmp; } } return n; } static inline int pvfile_write_16(PVOCFILE *p, void *data, int32 cnt) { int32 n; if (byte_order()) { uint16_t tmp; for (n = 0; n < cnt; n++) { tmp = ((uint16_t*) data)[n]; tmp = ((tmp & (uint16_t) 0xFF) << 8) | ((tmp & (uint16_t) 0xFF00) >> 8); if (fwrite(&tmp, sizeof(uint16_t), 1, p->fp) != (size_t) 1) break; } } else n = fwrite(data, sizeof(uint16_t), (size_t) cnt, p->fp); return (n != cnt); } static inline int32 pvfile_read_32(PVOCFILE *p, void *data, int32 cnt) { int32 n = (int32) fread(data, sizeof(uint32_t), (size_t) cnt, p->fp); if (byte_order()) { int32 i; uint32_t tmp; for (i = 0; i < n; i++) { tmp = ((uint32_t*) data)[i]; tmp = ((tmp & (uint32_t) 0x000000FFU) << 24) | ((tmp & (uint32_t) 0x0000FF00U) << 8) | ((tmp & (uint32_t) 0x00FF0000U) >> 8) | ((tmp & (uint32_t) 0xFF000000U) >> 24); ((uint32_t*) data)[i] = tmp; } } return n; } static inline int pvfile_write_32(PVOCFILE *p, void *data, int32 cnt) { int32 n; if (byte_order()) { uint32_t tmp; for (n = 0; n < cnt; n++) { tmp = ((uint32_t*) data)[n]; tmp = ((tmp & (uint32_t) 0x000000FFU) << 24) | ((tmp & (uint32_t) 0x0000FF00U) << 8) | ((tmp & (uint32_t) 0x00FF0000U) >> 8) | ((tmp & (uint32_t) 0xFF000000U) >> 24); if (fwrite(&tmp, sizeof(uint32_t), 1, p->fp) != (size_t) 1) break; } } else n = fwrite(data, sizeof(uint32_t), (size_t) cnt, p->fp); return (n != cnt); } static int write_guid(PVOCFILE *p, const GUID *pGuid) { int err = 0; err |= pvfile_write_32(p, (void*) &(pGuid->Data1), 1L); err |= pvfile_write_16(p, (void*) &(pGuid->Data2), 1L); err |= pvfile_write_16(p, (void*) &(pGuid->Data3), 1L); err |= ((int) fwrite(&(pGuid->Data4[0]), 1, 8, p->fp) != 8); return err; } static int compare_guids(const GUID *gleft, const GUID *gright) { const char *left = (const char *) gleft, *right = (const char *) gright; return !memcmp(left, right, sizeof(GUID)); } static int write_pvocdata(PVOCFILE *p) { int err = 0; err |= pvfile_write_16(p, &(p->pvdata.wWordFormat), 1L); err |= pvfile_write_16(p, &(p->pvdata.wAnalFormat), 1L); err |= pvfile_write_16(p, &(p->pvdata.wSourceFormat), 1L); err |= pvfile_write_16(p, &(p->pvdata.wWindowType), 1L); err |= pvfile_write_32(p, &(p->pvdata.nAnalysisBins), 1L); err |= pvfile_write_32(p, &(p->pvdata.dwWinlen), 1L); err |= pvfile_write_32(p, &(p->pvdata.dwOverlap), 1L); err |= pvfile_write_32(p, &(p->pvdata.dwFrameAlign), 1L); err |= pvfile_write_32(p, &(p->pvdata.fAnalysisRate), 1L); err |= pvfile_write_32(p, &(p->pvdata.fWindowParam), 1L); return err; } static int write_fmt(PVOCFILE *p) { int err = 0; err |= pvfile_write_16(p, &(p->fmtdata.wFormatTag), 1L); err |= pvfile_write_16(p, &(p->fmtdata.nChannels), 1L); err |= pvfile_write_32(p, &(p->fmtdata.nSamplesPerSec), 1L); err |= pvfile_write_32(p, &(p->fmtdata.nAvgBytesPerSec), 1L); err |= pvfile_write_16(p, &(p->fmtdata.nBlockAlign), 1L); err |= pvfile_write_16(p, &(p->fmtdata.wBitsPerSample), 1L); err |= pvfile_write_16(p, &(p->fmtdata.cbSize), 1L); return err; } static int pvoc_writeWindow(PVOCFILE *p, float *window, uint32_t length) { return (pvfile_write_32(p, window, (int32) length)); } static int pvoc_readWindow(PVOCFILE *p, float *window, uint32_t length) { return (pvfile_read_32(p, window, (int32) length) != (int32) length); } const char *pvoc_errorstr(CSOUND *csound) { int i = -(csound->pvErrorCode); if (UNLIKELY(i < 0 || i > 42)) i = 1; return (const char *) Str(pvErrorStrings[i]); } /***** loosely modelled on CDP sfsys ****** * This is a static array, but could be made dynamic in an OOP sort of way. * The idea is that all low-level operations and data * are completely hidden from the user, so that internal * format changes can be made with little or no disruption * to the public functions. * But avoiding the full monty of a C++ implementation. *******************************************/ int init_pvsys(CSOUND *csound) { if (UNLIKELY(csound->pvNumFiles)) { csound->pvErrorCode = -2; return 0; } csound->pvErrorCode = 0; return 1; } static inline PVOCFILE *pvsys_getFileHandle(CSOUND *csound, int fd) { if (UNLIKELY(fd < 0 || fd >= csound->pvNumFiles)) return (PVOCFILE*) NULL; return (PVFILETABLE[fd]); } static int pvsys_createFileHandle(CSOUND *csound) { int i; for (i = 0; i < csound->pvNumFiles; i++) { if (PVFILETABLE[i] == NULL) break; } if (i >= csound->pvNumFiles) { PVOCFILE **tmp; int j = i; /* extend table */ if (!csound->pvNumFiles) { csound->pvNumFiles = 8; tmp = (PVOCFILE**) csound->Malloc(csound, sizeof(PVOCFILE*) * csound->pvNumFiles); } else { csound->pvNumFiles <<= 1; tmp = (PVOCFILE**) csound->ReAlloc(csound, csound->pvFileTable, sizeof(PVOCFILE*) * csound->pvNumFiles); } if (tmp == NULL) return -1; csound->pvFileTable = (void*) tmp; for ( ; j < csound->pvNumFiles; j++) PVFILETABLE[j] = (PVOCFILE*) NULL; } /* allocate new handle */ PVFILETABLE[i] = (PVOCFILE*) csound->Malloc(csound, sizeof(PVOCFILE)); if (PVFILETABLE[i] == NULL) return -1; memset(PVFILETABLE[i], 0, sizeof(PVOCFILE)); return i; } static void prepare_pvfmt(WAVEFORMATEX *pfmt, uint32 chans, uint32 srate, pv_stype stype) { pfmt->wFormatTag = WAVE_FORMAT_EXTENSIBLE; pfmt->nChannels = (uint16_t) chans; pfmt->nSamplesPerSec = srate; switch (stype) { default: case (STYPE_16): pfmt->wBitsPerSample = (uint16_t) 16; pfmt->nBlockAlign = (uint16_t) (chans * 2 * sizeof(char)); break; case (STYPE_24): pfmt->wBitsPerSample = (uint16_t) 24; pfmt->nBlockAlign = (uint16_t) (chans * 3 * sizeof(char)); break; case (STYPE_32): case (STYPE_IEEE_FLOAT): pfmt->wBitsPerSample = (uint16_t) 32; pfmt->nBlockAlign = (uint16_t) (chans * 4 * sizeof(char)); break; } pfmt->nAvgBytesPerSec = pfmt->nBlockAlign * srate; /* if we have extended WindowParam fields, or something, will need to adjust this */ pfmt->cbSize = 62; } /* lots of different ways of doing this! * we will need one in the form: * int pvoc_fmtcreate(const char *fname, PVOCDATA *p_pvfmt, * WAVEFORMATEX *p_wvfmt); */ /* a simple minimalist function to begin with!*/ /* set D to 0, and/or dwWinlen to 0, to use internal default */ /* fWindow points to userdef window, or is NULL */ /* NB currently this does not enforce a soundfile extension; */ /* probably it should... */ int pvoc_createfile(CSOUND *csound, const char *filename, uint32 fftlen, uint32 overlap, uint32 chans, uint32 format, int32 srate, int stype, int wtype, float wparam, float *fWindow, uint32 dwWinlen) { int fd; int32 N, D; char *pname; PVOCFILE *p = NULL; float winparam = 0.0f; N = fftlen; /* keep the CARL varnames for now */ D = overlap; csound->pvErrorCode = -1; if (UNLIKELY(N == 0 || (int) chans <= 0 || filename == NULL || D > N)) { csound->pvErrorCode = -3; return -1; } if (UNLIKELY(/*format < PVOC_AMP_FREQ ||*/ format > PVOC_COMPLEX)) { csound->pvErrorCode = -4; return -1; } if (UNLIKELY(!(wtype >= PVOC_DEFAULT && wtype <= PVOC_CUSTOM))) { csound->pvErrorCode = -5; return -1; } /* load it, but can not write until we have a PVXW chunk definition... */ if (wtype == PVOC_CUSTOM) { } else if (wtype == PVOC_DEFAULT) wtype = PVOC_HAMMING; else if (wtype == PVOC_KAISER) if (wparam != 0.0f) winparam = wparam; /* will need an internal default for window parameters... */ fd = pvsys_createFileHandle(csound); if (UNLIKELY(fd < 0)) { csound->pvErrorCode = -6; return -1; } p = pvsys_getFileHandle(csound, fd); pname = (char *) csound->Malloc(csound, strlen(filename) + 1); strcpy(pname, filename); p->customWindow = NULL; /* setup rendering inforamtion */ prepare_pvfmt(&p->fmtdata, chans, srate, stype); p->pvdata.wWordFormat = PVOC_IEEE_FLOAT; p->pvdata.wAnalFormat = (uint16_t) format; if (stype == STYPE_IEEE_FLOAT) p->pvdata.wSourceFormat = WAVE_FORMAT_IEEE_FLOAT; else p->pvdata.wSourceFormat = WAVE_FORMAT_PCM; p->pvdata.wWindowType = wtype; p->pvdata.nAnalysisBins = (N >> 1) + 1; if (dwWinlen == 0) p->pvdata.dwWinlen = N; else p->pvdata.dwWinlen = dwWinlen; if (D == 0) p->pvdata.dwOverlap = N / 8; else p->pvdata.dwOverlap = D; p->pvdata.dwFrameAlign = p->pvdata.nAnalysisBins * 2 * sizeof(float); p->pvdata.fAnalysisRate = (float) srate / (float) p->pvdata.dwOverlap; p->pvdata.fWindowParam = winparam; if (fWindow != NULL) { p->customWindow = csound->Malloc(csound, dwWinlen * sizeof(float)); memcpy(p->customWindow, fWindow, dwWinlen * sizeof(float)); } p->fd = csound->FileOpen2(csound, &(p->fp), CSFILE_STD, filename, "wb", "", CSFTYPE_PVCEX, 0); if (UNLIKELY(p->fd == NULL)) { csound->Free(csound, pname); if (p->customWindow) csound->Free(csound, p->customWindow); csound->Free(csound, p); PVFILETABLE[fd] = NULL; csound->pvErrorCode = -7; return -1; } p->name = pname; if (pvoc_writeheader(csound, p) != 0) { csound->FileClose(csound, p->fd); (void)remove(p->name); csound->Free(csound, p->name); if (p->customWindow) csound->Free(csound, p->customWindow); csound->Free(csound, p); PVFILETABLE[fd] = NULL; return -1; } csound->pvErrorCode = 0; return fd; } int pvoc_openfile(CSOUND *csound, const char *filename, void *data_, void *fmt_) { WAVEFORMATPVOCEX wfpx; char *pname; PVOCFILE *p = NULL; int fd; PVOCDATA *data = (PVOCDATA *) data_; WAVEFORMATEX *fmt = (WAVEFORMATEX *) fmt_; csound->pvErrorCode = -1; if (UNLIKELY(data == NULL || fmt == NULL)) { csound->pvErrorCode = -8; return -1; } fd = pvsys_createFileHandle(csound); if (UNLIKELY(fd < 0)) { csound->pvErrorCode = -6; return -1; } p = pvsys_getFileHandle(csound, fd); p->customWindow = NULL; p->fd = csound->FileOpen2(csound, &(p->fp), CSFILE_STD, filename, "rb", "SADIR", CSFTYPE_PVCEX, 0); if (UNLIKELY(p->fd == NULL)) { csound->pvErrorCode = -9; csound->Free(csound, p); PVFILETABLE[fd] = NULL; return -1; } pname = (char*) csound->Malloc(csound, strlen(filename) + 1); strcpy(pname, filename); p->name = pname; p->readonly = 1; if (UNLIKELY(pvoc_readheader(csound, p, &wfpx) != 0)) { csound->FileClose(csound, p->fd); csound->Free(csound, p->name); if (p->customWindow) csound->Free(csound, p->customWindow); csound->Free(csound, p); PVFILETABLE[fd] = NULL; return -1; } memcpy(data, &(wfpx.data), sizeof(PVOCDATA)); memcpy(fmt, &(wfpx.wxFormat.Format), SIZEOF_WFMTEX); csound->pvErrorCode = 0; return fd; } static int pvoc_readfmt(CSOUND *csound, PVOCFILE *p, WAVEFORMATPVOCEX *pWfpx) { WAVEFORMATEXTENSIBLE *wxfmt = &(pWfpx->wxFormat); WAVEFORMATEX *fmt = &(wxfmt->Format); int err = 0; memset(pWfpx, 0, sizeof(WAVEFORMATPVOCEX)); err |= (pvfile_read_16(p, &(fmt->wFormatTag), 1L) != 1L); err |= (pvfile_read_16(p, &(fmt->nChannels), 1L) != 1L); err |= (pvfile_read_32(p, &(fmt->nSamplesPerSec), 1L) != 1L); err |= (pvfile_read_32(p, &(fmt->nAvgBytesPerSec), 1L) != 1L); err |= (pvfile_read_16(p, &(fmt->nBlockAlign), 1L) != 1L); err |= (pvfile_read_16(p, &(fmt->wBitsPerSample), 1L) != 1L); err |= (pvfile_read_16(p, &(fmt->cbSize), 1L) != 1L); if (UNLIKELY(err)) { csound->pvErrorCode = -10; return err; } /* the first clues this is pvx format...*/ if (UNLIKELY(fmt->wFormatTag != WAVE_FORMAT_EXTENSIBLE)) { csound->pvErrorCode = -11; return -1; } if (UNLIKELY(fmt->cbSize != 62)) { csound->pvErrorCode = -12; return -1; } err |= (pvfile_read_16(p, &(wxfmt->Samples.wValidBitsPerSample), 1L) != 1L); err |= (pvfile_read_32(p, &(wxfmt->dwChannelMask), 1L) != 1L); err |= (pvfile_read_32(p, &(wxfmt->SubFormat.Data1), 1L) != 1L); err |= (pvfile_read_16(p, &(wxfmt->SubFormat.Data2), 1L) != 1L); err |= (pvfile_read_16(p, &(wxfmt->SubFormat.Data3), 1L) != 1L); err |= ((int) fread(&(wxfmt->SubFormat.Data4[0]), 1, 8, p->fp) != 8); if (UNLIKELY(err)) { csound->pvErrorCode = -13; return -1; } /* ... but this is the clincher */ if (UNLIKELY(!compare_guids(&(pWfpx->wxFormat.SubFormat), &KSDATAFORMAT_SUBTYPE_PVOC))) { csound->pvErrorCode = -14; return -1; } err |= (pvfile_read_32(p, &(pWfpx->dwVersion), 1L) != 1L); err |= (pvfile_read_32(p, &(pWfpx->dwDataSize), 1L) != 1L); err |= (pvfile_read_16(p, &(pWfpx->data.wWordFormat), 1L) != 1L); err |= (pvfile_read_16(p, &(pWfpx->data.wAnalFormat), 1L) != 1L); err |= (pvfile_read_16(p, &(pWfpx->data.wSourceFormat), 1L) != 1L); err |= (pvfile_read_16(p, &(pWfpx->data.wWindowType), 1L) != 1L); err |= (pvfile_read_32(p, &(pWfpx->data.nAnalysisBins), 1L) != 1L); err |= (pvfile_read_32(p, &(pWfpx->data.dwWinlen), 1L) != 1L); err |= (pvfile_read_32(p, &(pWfpx->data.dwOverlap), 1L) != 1L); err |= (pvfile_read_32(p, &(pWfpx->data.dwFrameAlign), 1L) != 1L); err |= (pvfile_read_32(p, &(pWfpx->data.fAnalysisRate), 1L) != 1L); err |= (pvfile_read_32(p, &(pWfpx->data.fWindowParam), 1L) != 1L); if (UNLIKELY(err)) { csound->pvErrorCode = -15; return -1; } if (UNLIKELY(pWfpx->dwVersion != PVX_VERSION)) { csound->pvErrorCode = -16; return -1; } return 0; } static int pvoc_readheader(CSOUND *csound, PVOCFILE *p, WAVEFORMATPVOCEX *pWfpx) { char tag[5]; uint32_t size; uint32_t riffsize; int fmtseen = 0, windowseen = 0; if (UNLIKELY(pvfile_read_tag(p, &(tag[0])) != 0 || strcmp(tag, "RIFF") != 0 || pvfile_read_32(p, &size, 1L) != 1L)) { csound->pvErrorCode = -17; return -1; } if (UNLIKELY(size < 24 * sizeof(uint32_t) + SIZEOF_FMTPVOCEX)) { csound->pvErrorCode = -19; return -1; } riffsize = size; if (UNLIKELY(pvfile_read_tag(p, &(tag[0])) != 0 || strcmp(tag, "WAVE") != 0)) { csound->pvErrorCode = -20; return -1; } riffsize -= sizeof(uint32_t); /* loop for chunks */ while (riffsize > (uint32_t) 0) { if (UNLIKELY(pvfile_read_tag(p, &(tag[0])) != 0 || pvfile_read_32(p, &size, 1L) != 1L)) { csound->pvErrorCode = -17; return -1; } riffsize -= 2 * sizeof(uint32_t); if (strcmp(tag, "fmt ") == 0) { /* bail out if not a pvoc file: not trying to read all WAVE formats!*/ if (UNLIKELY((int) size < (int) SIZEOF_FMTPVOCEX)) { csound->pvErrorCode = -14; return -1; } if (UNLIKELY(pvoc_readfmt(csound, p, pWfpx) != 0)) { csound->pvErrorCode = -21; return -1; } riffsize -= SIZEOF_FMTPVOCEX; fmtseen = 1; memcpy(&(p->fmtdata), &(pWfpx->wxFormat), SIZEOF_WFMTEX); memcpy(&(p->pvdata), &(pWfpx->data), sizeof(PVOCDATA)); } else if (strcmp(tag, "PVXW") == 0) { if (UNLIKELY(!fmtseen)) { csound->pvErrorCode = -22; return -1; } if (UNLIKELY(p->pvdata.wWindowType != PVOC_CUSTOM)) { /* whaddayado? can you warn the user and continue? */ csound->pvErrorCode = -23; return -1; } p->customWindow = csound->Malloc(csound, p->pvdata.dwWinlen * sizeof(float)); if (UNLIKELY(pvoc_readWindow(p, p->customWindow, p->pvdata.dwWinlen) != 0)) { csound->pvErrorCode = -24; return -1; } windowseen = 1; } else if (strcmp(tag, "data") == 0) { if (UNLIKELY((uint32_t) riffsize != size)) { csound->pvErrorCode = -25; return -1; } if (UNLIKELY(!fmtseen)) { csound->pvErrorCode = -26; return -1; } if (p->pvdata.wWindowType == PVOC_CUSTOM) { if (UNLIKELY(!windowseen)) { csound->pvErrorCode = -27; return -1; } } p->datachunkoffset = (int32) ftell(p->fp); p->curpos = p->datachunkoffset; /* not m/c frames, for now */ p->nFrames = size / p->pvdata.dwFrameAlign; return 0; } else { /* skip any unknown chunks */ riffsize -= 2 * sizeof(uint32_t); if (UNLIKELY(fseek(p->fp, (int32) size, SEEK_CUR) != 0)) { csound->pvErrorCode = -28; return -1; } riffsize -= size; } } /* if here, something very wrong! */ csound->pvErrorCode = -29; return -1; } static int pvoc_writeheader(CSOUND *csound, PVOCFILE *p) { uint32_t version, size = (uint32_t) 0; int err = 0; err |= pvfile_write_tag(p, "RIFF"); err |= pvfile_write_32(p, &size, 1L); if (UNLIKELY(err)) { csound->pvErrorCode = -30; return -1; } size = SIZEOF_WFMTEX + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(GUID) + 2 * sizeof(uint32_t) + sizeof(PVOCDATA); err |= pvfile_write_tag(p, "WAVE"); err |= pvfile_write_tag(p, "fmt "); err |= pvfile_write_32(p, &size, 1L); if (UNLIKELY(err)) { csound->pvErrorCode = -30; return -1; } if (UNLIKELY(write_fmt(p) != 0)) { csound->pvErrorCode = -31; return -1; } if (UNLIKELY(pvfile_write_16(p, &(p->fmtdata.wBitsPerSample), 1L) != 0)) { csound->pvErrorCode = -31; return -1; } /* we will take this from a WAVE_EX file, in due course */ size = 0; /* dwChannelMask */ if (UNLIKELY(pvfile_write_32(p, &size, 1L) != 0)) { csound->pvErrorCode = -31; return -1; } if (UNLIKELY(write_guid(p, &KSDATAFORMAT_SUBTYPE_PVOC) != 0)) { csound->pvErrorCode = -31; return -1; } version = (uint32_t) 1; size = sizeof(PVOCDATA); if (UNLIKELY(pvfile_write_32(p, &version, 1L) != 0 || pvfile_write_32(p, &size, 1L) != 0)) { csound->pvErrorCode = -31; return -1; } if (UNLIKELY(write_pvocdata(p) != 0)) { csound->pvErrorCode = -31; return -1; } /* VERY experimental; may not even be a good idea...*/ if (p->customWindow) { if (UNLIKELY(pvfile_write_tag(p, "PVXW") != 0)) { csound->pvErrorCode = -30; return -1; } size = p->pvdata.dwWinlen * sizeof(float); if (UNLIKELY(pvfile_write_32(p, &size, 1L) != 0)) { csound->pvErrorCode = -30; return -1; } if (UNLIKELY(pvoc_writeWindow(p, p->customWindow, p->pvdata.dwWinlen) != 0)) { csound->pvErrorCode = -32; return -1; } } /* no other chunks to write yet! */ if (UNLIKELY(pvfile_write_tag(p, "data") != 0)) { csound->pvErrorCode = -30; return -1; } /* we need to update size later on... */ size = (uint32_t) 0; if (UNLIKELY(pvfile_write_32(p, &size, 1L) != 0)) { csound->pvErrorCode = -30; return -1; } p->datachunkoffset = (int32) ftell(p->fp); p->curpos = p->datachunkoffset; return 0; } static int pvoc_updateheader(CSOUND *csound, int ofd) { PVOCFILE *p = pvsys_getFileHandle(csound, ofd); uint32_t riffsize, datasize; if (UNLIKELY(p == NULL)) { csound->pvErrorCode = -38; return 0; } if (UNLIKELY(fseek(p->fp, (int32) (p->datachunkoffset - sizeof(uint32_t)), SEEK_SET) != 0)) { csound->pvErrorCode = -33; return 0; } datasize = p->curpos - p->datachunkoffset; if (UNLIKELY(pvfile_write_32(p, &datasize, 1L) != 0)) { csound->pvErrorCode = -33; return 0; } if (UNLIKELY(fseek(p->fp, (int32) sizeof(uint32_t), SEEK_SET) != 0)) { csound->pvErrorCode = -33; return 0; } riffsize = p->curpos - 2 * sizeof(uint32_t); if (UNLIKELY(pvfile_write_32(p, &riffsize, 1L) != 0)) { csound->pvErrorCode = -34; return 0; } if (UNLIKELY(fseek(p->fp, 0L, SEEK_END) != 0)) { csound->pvErrorCode = -35; return 0; } return 1; } int pvoc_closefile(CSOUND *csound, int ofd) { PVOCFILE *p = pvsys_getFileHandle(csound, ofd); int rc = 1; csound->pvErrorCode = 0; if (UNLIKELY(p == NULL)) { csound->pvErrorCode = -36; return 0; } if (UNLIKELY(p->fd == NULL)) { csound->pvErrorCode = -37; csound->Free(csound, p); PVFILETABLE[ofd] = NULL; return 0; } if (!p->readonly) if (!pvoc_updateheader(csound, ofd)) rc = 0; csound->FileClose(csound, p->fd); if (p->to_delete && !p->readonly) (void)remove(p->name); csound->Free(csound, p->name); csound->Free(csound, p->customWindow); csound->Free(csound, p); PVFILETABLE[ofd] = NULL; return rc; } /* does not directly address m/c streams, or alternative numeric formats, yet... * so for m/c files, write each frame in turn, for each channel. * The format requires multi-channel frames to be interleaved in the usual way: * if nChannels= 4, the file will contain: * frame[0][0],frame[0][1],frame[0][2],frame[0][3],frme[1][0],frame[1][1]..... * * The idea is to offer e.g. a floats version and a longs version ONLY, but * independently of the underlying representation, so that the user can write * a floats block, even though the underlying format might be longs or doubles. * Most importantly, the user does not have to deal with byte-reversal, which * would otherwise always be the case it the user had direct access to the file. * * So these functions are the most likely to change over time!. * * return 0 for error, 1 for success. This could change.... */ int pvoc_putframes(CSOUND *csound, int ofd, const float *frame, int32 numframes) { PVOCFILE *p = pvsys_getFileHandle(csound, ofd); int32 towrite; /* count in 'words' */ if (UNLIKELY(p == NULL)) { csound->pvErrorCode = -38; return 0; } if (UNLIKELY(p->fd == NULL)) { csound->pvErrorCode = -37; return 0; } /* NB doubles not supported yet */ towrite = (int32) p->pvdata.nAnalysisBins * 2L * numframes; if (UNLIKELY(pvfile_write_32(p, (void*) frame, towrite) != 0)) { csound->pvErrorCode = -39; return 0; } p->FramePos += numframes; p->curpos += towrite * sizeof(float); return 1; } /* Simplistic read function * best practice here is to read nChannels frames * return -1 for error, 0 for EOF, else numframes read */ int pvoc_getframes(CSOUND *csound, int ifd, float *frames, uint32 nframes) { PVOCFILE *p = pvsys_getFileHandle(csound, ifd); int32 toread, got; if (UNLIKELY(p == NULL)) { csound->pvErrorCode = -38; return -1; } if (UNLIKELY(p->fd == NULL)) { csound->pvErrorCode = -37; return -1; } toread = (int32) p->pvdata.nAnalysisBins * 2L * (int32) nframes; got = pvfile_read_32(p, frames, toread); if (got != toread) { if (UNLIKELY(ferror(p->fp))) { csound->pvErrorCode = -40; return -1; } p->curpos += (int32) (got * sizeof(float)); got = got / (int32) (p->pvdata.nAnalysisBins * 2); p->FramePos += got; return (int) got; } p->curpos += (toread * sizeof(float)); p->FramePos += (int32) nframes; return (int) nframes; } int pvoc_fseek(CSOUND *csound, int ifd, int offset) { PVOCFILE *p = pvsys_getFileHandle(csound, ifd); int32 pos, skipframes, skipsize; if (UNLIKELY(p == NULL)) { csound->pvErrorCode = -38; return -1; } if (UNLIKELY(p->fd == NULL)) { csound->pvErrorCode = -37; return -1; } if (offset == 1) skipframes = (int32) p->fmtdata.nChannels; else skipframes = offset; skipsize = p->pvdata.dwFrameAlign * skipframes; pos = p->datachunkoffset + skipsize; if (UNLIKELY(fseek(p->fp, (int32) pos, SEEK_SET) != 0)) { csound->pvErrorCode = -41; return -1; } p->curpos = pos; p->FramePos = skipframes; return 0; } /* may be more to do in here later on */ int pvsys_release(CSOUND *csound) { int i; csound->pvErrorCode = 0; for (i = 0; i < csound->pvNumFiles; i++) { if (pvsys_getFileHandle(csound, i) != NULL) { if (UNLIKELY(!pvoc_closefile(csound, i))) { csound->pvErrorCode = -42; } } } if (csound->pvNumFiles) { csound->Free(csound, csound->pvFileTable); csound->pvFileTable = NULL; csound->pvNumFiles = 0; } return (csound->pvErrorCode == 0 ? 1 : 0); } /* return raw framecount: channel-agnostic for now */ int pvoc_framecount(CSOUND *csound, int ifd) { PVOCFILE *p = pvsys_getFileHandle(csound, ifd); if (UNLIKELY(p == NULL)) { csound->pvErrorCode = -38; return -1; } return p->nFrames; } csound-6.10.0/OOps/pvsanal.c000066400000000000000000001132561321653344700156010ustar00rootroot00000000000000/* pvsanal.c: Copyright (C) 2002 Richard Dobson (C) 2007 John ffitch/Richard Dobson (SDFT) This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* pvsanal.c */ /* functions based on CARL pvoc.c (c) Mark Dolson. The CARL software distribution is due to be released under the GNU LPGL. */ #include #include "csoundCore.h" #include "pstream.h" double besseli(double x); static void hamming(MYFLT *win, int winLen, int even); static void vonhann(MYFLT *win, int winLen, int even); static void generate_frame(CSOUND *, PVSANAL *p); static void process_frame(CSOUND *, PVSYNTH *p); /* generate half-window */ static CS_NOINLINE int PVS_CreateWindow(CSOUND *csound, MYFLT *buf, int type, int winLen) { double fpos, inc; MYFLT *ftable; int i, n, flen, even; even = (winLen + 1) & 1; switch (type) { case 0: /* Hamming */ hamming(buf, (winLen >> 1), even); return OK; case 1: /* Hanning */ vonhann(buf, (winLen >> 1), even); return OK; case 2: /* Kaiser */ { double beta = 6.8; double x, flen2, besbeta; flen2 = 1.0 / ((double)(winLen >> 1) * (double)(winLen >> 1)); besbeta = 1.0 / besseli(beta); n = winLen >> 1; x = (even ? 0.5 : 0.05); for (i = 0; i < n; i++, x += 1.0) buf[i] = (MYFLT)(besseli(beta * sqrt(1.0 - x * x * flen2)) * besbeta); buf[i] = FL(0.0); } return OK; default: if (UNLIKELY(type >= 0)) return csound->InitError(csound, Str("invalid window type")); } /* use table created with GEN20 */ flen = csoundGetTable(csound, &ftable, -(type)); if (UNLIKELY(flen < 0)) return csound->InitError(csound, Str("ftable for window not found")); inc = (double)flen / (double)(winLen & (~1)); fpos = ((double)flen + (double)even * inc) * 0.5; n = winLen >> 1; /* this assumes that for a window with even size, space for an extra */ /* sample is allocated */ for (i = 0; i < n; i++) { double frac, tmp; int pos; frac = modf(fpos, &tmp); pos = (int) tmp; buf[i] = ftable[pos] + ((ftable[pos + 1] - ftable[pos]) * (MYFLT) frac); fpos += inc; } buf[n] = (even ? FL(0.0) : ftable[flen]); return OK; } int pvssanalset(CSOUND *csound, PVSANAL *p) { /* opcode params */ int N = MYFLT2LRND(*p->winsize); int NB; int i; int wintype = MYFLT2LRND(*p->wintype); if (N<=0) return csound->InitError(csound, Str("Invalid window size")); /* deal with iinit and iformat later on! */ N = N + N%2; /* Make N even */ NB = N/2+1; /* Number of bins */ /* Need space for NB complex numbers for each of ksmps */ if (p->fsig->frame.auxp==NULL || CS_KSMPS*(N+2)*sizeof(MYFLT) > (unsigned int)p->fsig->frame.size) csound->AuxAlloc(csound, CS_KSMPS*(N+2)*sizeof(MYFLT),&p->fsig->frame); else memset(p->fsig->frame.auxp, 0, CS_KSMPS*(N+2)*sizeof(MYFLT)); /* Space for remembering samples */ if (p->input.auxp==NULL || N*sizeof(MYFLT) > (unsigned int)p->input.size) csound->AuxAlloc(csound, N*sizeof(MYFLT),&p->input); else memset(p->input.auxp, 0, N*sizeof(MYFLT)); csound->AuxAlloc(csound, NB * sizeof(double), &p->oldInPhase); if (p->analwinbuf.auxp==NULL || NB*sizeof(CMPLX) > (unsigned int)p->analwinbuf.size) csound->AuxAlloc(csound, NB*sizeof(CMPLX),&p->analwinbuf); else memset(p->analwinbuf.auxp, 0, NB*sizeof(CMPLX)); p->inptr = 0; /* Pointer in circular buffer */ p->fsig->NB = p->Ii = NB; p->fsig->wintype = wintype; p->fsig->format = PVS_AMP_FREQ; /* only this, for now */ p->fsig->N = p->nI = N; p->fsig->sliding = 1; /* Need space for NB sines, cosines and a scatch phase area */ if (p->trig.auxp==NULL || (2*NB)*sizeof(double) > (unsigned int)p->trig.size) csound->AuxAlloc(csound,(2*NB)*sizeof(double),&p->trig); { double dc = cos(TWOPI/(double)N); double ds = sin(TWOPI/(double)N); double *c = (double *)(p->trig.auxp); double *s = c+NB; p->cosine = c; p->sine = s; c[0] = 1.0; s[0] = 0.0; // assignment to s unnecessary as auxalloc zeros /* direct computation of c and s may be better for large n c[i] = cos(2*M_PI*i/n); s[i] = sin(2*M_PI*i/n); if (i % 16 == 15) { c[i] = cos(2*M_PI*(i+1)/n); s[i] = sin(2*M_PI*(i+1)/n); */ for (i=1; ifftsize); uint32_t overlap = (uint32_t) *(p->overlap); uint32_t M = (uint32_t) *(p->winsize); int wintype = (int) *p->wintype; /* deal with iinit and iformat later on! */ if (overlapInitError(csound, Str("pvsanal: fftsize of 32 is too small!\n")); /* check N for powof2? CARL fft routines and FFTW are not limited to that */ N = N + N%2; /* Make N even */ if (UNLIKELY(M < N)) { csound->Warning(csound, Str("pvsanal: window size too small for fftsize")); M = N; } if (UNLIKELY(overlap > N / 2)) return csound->InitError(csound, Str("pvsanal: overlap too big for fft size\n")); #ifdef OLPC if (UNLIKELY(overlap < CS_KSMPS)) return csound->InitError(csound, Str("pvsanal: overlap must be >= ksmps\n")); #endif halfwinsize = M/2; buflen = M*4; p->arate = (float)(csound->esr / (MYFLT) overlap); p->fund = (float)(csound->esr / (MYFLT) N); nBins = N/2 + 1; /* we can exclude/simplify all sorts of stuff in CARL * as we will never do time-scaling with this opcode */ /*Lf =*/ Mf = 1 - M%2; csound->AuxAlloc(csound, overlap * sizeof(MYFLT), &p->overlapbuf); csound->AuxAlloc(csound, (N+2) * sizeof(MYFLT), &p->analbuf); csound->AuxAlloc(csound, (M+Mf) * sizeof(MYFLT), &p->analwinbuf); csound->AuxAlloc(csound, nBins * sizeof(MYFLT), &p->oldInPhase); csound->AuxAlloc(csound, buflen * sizeof(MYFLT), &p->input); /* the signal itself */ csound->AuxAlloc(csound, (N+2) * sizeof(MYFLT), &p->fsig->frame); /* make the analysis window*/ analwinbase = (MYFLT *) (p->analwinbuf.auxp); analwinhalf = analwinbase + halfwinsize; if (UNLIKELY(PVS_CreateWindow(csound, analwinhalf, wintype, M) != OK)) return NOTOK; for (i = 1; i <= halfwinsize; i++) *(analwinhalf - i) = *(analwinhalf + i - Mf); if (M > N) { double dN = (double)N; /* sinc function */ if (Mf) *analwinhalf *= (MYFLT)(dN * sin(PI*0.5/dN) / (PI*0.5)); for (i = 1; i <= halfwinsize; i++) *(analwinhalf + i) *= (MYFLT) (dN * sin((double)(PI*(i+0.5*Mf)/dN)) / (PI*(i+0.5*Mf))); for (i = 1; i <= halfwinsize; i++) *(analwinhalf - i) = *(analwinhalf + i - Mf); } /* get net amp */ sum = FL(0.0); for (i = -halfwinsize; i <= halfwinsize; i++) sum += *(analwinhalf + i); sum = FL(2.0) / sum; /* factor of 2 comes in later in trig identity */ for (i = -halfwinsize; i <= halfwinsize; i++) *(analwinhalf + i) *= sum; /* p->invR = (float)(FL(1.0) / csound->esr); */ p->RoverTwoPi = (float)(p->arate / TWOPI_F); p->TwoPioverR = (float)(TWOPI_F / p->arate); p->Fexact = (float)(csound->esr / (MYFLT)N); p->nI = -(halfwinsize / overlap) * overlap; /* input time (in samples) */ /*Dd = halfwinsize + p->nI + 1; */ /* in streaming mode, Dd = ovelap all the time */ p->Ii = 0; p->IOi = 0; p->buflen = buflen; p->nextIn = (MYFLT *) p->input.auxp; p->inptr = 0; /* and finally, set up the output signal */ p->fsig->N = N; p->fsig->overlap = overlap; p->fsig->winsize = M; p->fsig->wintype = wintype; p->fsig->framecount = 1; p->fsig->format = PVS_AMP_FREQ; /* only this, for now */ p->fsig->sliding = 0; if (!(N & (N - 1))) /* if pow of two use this */ p->setup = csound->RealFFT2Setup(csound,N,FFT_FWD); return OK; } static void generate_frame(CSOUND *csound, PVSANAL *p) { int got, tocp,i,j,k,ii; int N = p->fsig->N; int N2 = N/2; int32 buflen = p->buflen; int32 analWinLen = p->fsig->winsize/2; int32 synWinLen = analWinLen; float *ofp; /* RWD MUST be 32bit */ MYFLT *fp; MYFLT *anal = (MYFLT *) (p->analbuf.auxp); MYFLT *input = (MYFLT *) (p->input.auxp); MYFLT *analWindow = (MYFLT *) (p->analwinbuf.auxp) + analWinLen; MYFLT *oldInPhase = (MYFLT *) (p->oldInPhase.auxp); MYFLT angleDif,real,imag,phase; double rratio; got = p->fsig->overlap; /*always assume */ fp = (MYFLT *) (p->overlapbuf.auxp); tocp = (got<= input + buflen - p->nextIn ? got : input + buflen - p->nextIn); got -= tocp; while (tocp-- > 0) *(p->nextIn++) = *fp++; if (got > 0) { p->nextIn -= buflen; while (got-- > 0) *p->nextIn++ = *fp++; } if (p->nextIn >= (input + buflen)) p->nextIn -= buflen; /* analysis: The analysis subroutine computes the complex output at time n of (N/2 + 1) of the phase vocoder channels. It operates on input samples (n - analWinLen) thru (n + analWinLen) and expects to find these in input[(n +- analWinLen) mod ibuflen]. It expects analWindow to point to the center of a symmetric window of length (2 * analWinLen +1). It is the responsibility of the main program to ensure that these values are correct! The results are returned in anal as succesive pairs of real and imaginary values for the lowest (N/2 + 1) channels. The subroutines fft and reals together implement one efficient FFT call for a real input sequence. */ /* for (i = 0; i < N+2; i++) *(anal + i) = FL(0.0); */ /*initialize*/ memset(anal, 0, sizeof(MYFLT)*(N+2)); j = (p->nI - analWinLen - 1 + buflen) % buflen; /*input pntr*/ k = p->nI - analWinLen - 1; /*time shift*/ while (k < 0) k += N; k = k % N; for (i = -analWinLen; i <= analWinLen; i++) { if (UNLIKELY(++j >= buflen)) j -= buflen; if (UNLIKELY(++k >= N)) k -= N; /* *(anal + k) += *(analWindow + i) * *(input + j); */ anal[k] += analWindow[i] * input[j]; } if (!(N & (N - 1))) { /* csound->RealFFT(csound, anal, N);*/ csound->RealFFT2(csound,p->setup,anal); anal[N] = anal[1]; anal[1] = anal[N + 1] = FL(0.0); } else csound->RealFFTnp2(csound, anal, N); /* conversion: The real and imaginary values in anal are converted to magnitude and angle-difference-per-second (assuming an intermediate sampling rate of rIn) and are returned in anal. */ #ifdef NOTDEF /* may support this later on */ if (format == PVS_AMP_PHASE) { /* PVOCEX uses plain (wrapped) phase format, ref Soundhack */ for (i=0,i0=anal,i1=anal+1,oi=p->oldInPhase; i <= N2; i++,i0+=2,i1+=2, oi++) { real = *i0; imag = *i1; *i0 = HYPOT(real, imag); /* phase unwrapping */ /*if (*i0 == 0.)*/ if (UNLIKELY(*i0 < FL(1.0E-10))) /* angleDif = 0.0f; */ phase = FL(0.0); else { phase = ATAN2(imag,real); /*angleDif = (phase = (float)rratio) - *oi; *oi = phase; phase = (MYFLT)rratio; */ } *i1 = phase; } } #endif /*if (format==PVS_AMP_FREQ) {*/ for (i=ii=0 /*,i0=anal,i1=anal+1,oi=oldInPhase*/; i <= N2; i++,ii+=2 /*i0+=2,i1+=2, oi++*/) { real = anal[ii] /* *i0 */; imag = anal[ii+1] /* *i1 */; /**i0*/ anal[ii] = HYPOT(real, imag); /* phase unwrapping */ /*if (*i0 == 0.)*/ if (UNLIKELY(/* *i0 */ anal[ii] < FL(1.0E-10))) angleDif = FL(0.0); else { rratio = atan2((double)imag,(double)real); angleDif = (phase = (MYFLT)rratio) - /**oi*/ oldInPhase[i]; /* *oi */ oldInPhase[i] = phase; } if (angleDif > PI_F) angleDif = angleDif - TWOPI_F; if (angleDif < -PI_F) angleDif = angleDif + TWOPI_F; /* add in filter center freq.*/ /* *i1 */ anal[ii+1] = angleDif * p->RoverTwoPi + ((MYFLT) i * p->Fexact); } /* } */ /* else must be PVOC_COMPLEX */ fp = anal; ofp = (float *) (p->fsig->frame.auxp); /* RWD MUST be 32bit */ for (i=0;i < N+2;i++) /* *ofp++ = (float)(*fp++); */ ofp[i] = (float) fp[i]; p->nI += p->fsig->overlap; /* increment time */ if (p->nI > (synWinLen + p->fsig->overlap)) p->Ii = /*I*/p->fsig->overlap; else if (p->nI > synWinLen) p->Ii = p->nI - synWinLen; else { p->Ii = 0; /* for (i=p->nO+synWinLen; i 0) *(output+i) = 0.0f; */ } p->IOi = p->Ii; } static void anal_tick(CSOUND *csound, PVSANAL *p,MYFLT samp) { MYFLT *inbuf = (MYFLT *) (p->overlapbuf.auxp); if (p->inptr== p->fsig->overlap) { generate_frame(csound, p); p->fsig->framecount++; p->inptr = 0; } //printf("inptr = %d fsig->overlap=%d\n", p->inptr, p->fsig->overlap); inbuf[p->inptr++] = samp; } static inline double mod2Pi(double x) { x = fmod(x,TWOPI); if (x <= -PI) { return x + TWOPI; } else if (x > PI) { return x - TWOPI; } else return x; } int pvssanal(CSOUND *csound, PVSANAL *p) { MYFLT *ain; int NB = p->Ii, loc; int N = p->fsig->N; MYFLT *data = (MYFLT*)(p->input.auxp); CMPLX *fw = (CMPLX*)(p->analwinbuf.auxp); double *c = p->cosine; double *s = p->sine; double *h = (double*)p->oldInPhase.auxp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; int wintype = p->fsig->wintype; if (UNLIKELY(data==NULL)) { return csound->PerfError(csound,p->h.insdshead, Str("pvsanal: Not Initialised.\n")); } ain = p->ain; /* The input samples */ loc = p->inptr; /* Circular buffer */ nsmps -= early; for (i=offset; i < nsmps; i++) { MYFLT re, im, dx; CMPLX* ff; int j; /* printf("%d: in = %f\n", i, *ain); */ dx = *ain - data[loc]; /* Change in sample */ data[loc] = *ain++; /* Remember input sample */ /* get the frame for this sample */ ff = (CMPLX*)(p->fsig->frame.auxp) + i*NB; /* fw is the current frame at this sample */ for (j = 0; j < NB; j++) { double ci = c[j], si = s[j]; re = fw[j].re + dx; im = fw[j].im; fw[j].re = ci*re - si*im; fw[j].im = ci*im + si*re; } loc++; if (UNLIKELY(loc==p->nI)) loc = 0; /* Circular buffer */ /* apply window and transfer to ff buffer*/ /* Rectang :Fw_t = F_t */ /* Hamming :Fw_t = 0.54F_t - 0.23[ F_{t-1}+F_{t+1}] */ /* Hamming :Fw_t = 0.5 F_t - 0.25[ F_{t-1}+F_{t+1}] */ /* Blackman:Fw_t = 0.42F_t - 0.25[ F_{t-1}+F_{t+1}]+0.04[F_{t-2}+F_{t+2}] */ /* Blackman_exact:Fw_t = 0.42659071367153912296F_t - 0.24828030954428202923 [F_{t-1}+F_{t+1}] + 0.038424333619948409286 [F_{t-2}+F_{t+2}] */ /* Nuttall_C3:Fw_t = 0.375 F_t - 0.25[ F_{t-1}+F_{t+1}] + 0.0625 [F_{t-2}+F_{t+2}] */ /* BHarris_3:Fw_t = 0.44959 F_t - 0.24682[ F_{t-1}+F_{t+1}] + 0.02838 [F_{t-2}+F_{t+2}] */ /* BHarris_min:Fw_t = 0.42323 F_t - 0.2486703 [ F_{t-1}+F_{t+1}] + 0.0391396 [F_{t-2}+F_{t+2}] */ switch (wintype) { case PVS_WIN_HAMMING: for (j=0; jWarning(csound, Str("Unknown window type; replaced by rectangular\n")); case PVS_WIN_RECT: memcpy(ff, fw, NB*sizeof(CMPLX)); /* for (j=0; jesr * (j + angleDif)/N; } /* if (i==9) { */ /* printf("Frame as Amp/Freq %d\n", i); */ /* for (j = 0; j < NB; j++) */ /* printf("%d: %f\t%f\n", j, ff[j].re, ff[j].im); */ /* } */ } p->inptr = loc; return OK; } int pvsanal(CSOUND *csound, PVSANAL *p) { MYFLT *ain; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; ain = p->ain; if (UNLIKELY(p->input.auxp==NULL)) { return csound->PerfError(csound,p->h.insdshead, Str("pvsanal: Not Initialised.\n")); } { int overlap = (int)*p->overlap; if (overlap<(int)nsmps || overlap<10) /* 10 is a guess.... */ return pvssanal(csound, p); } nsmps -= early; for (i=offset; i < nsmps; i++) anal_tick(csound,p,ain[i]); return OK; } int pvsynthset(CSOUND *csound, PVSYNTH *p) { MYFLT *analwinhalf; MYFLT *synwinhalf; MYFLT sum; int32 halfwinsize,buflen; int i,nBins,Mf,Lf; double IO; /* get params from input fsig */ /* we TRUST they are legal */ int32 N = p->fsig->N; int32 overlap = p->fsig->overlap; int32 M = p->fsig->winsize; int wintype = p->fsig->wintype; p->fftsize = N; p->winsize = M; p->overlap = overlap; p->wintype = wintype; p->format = p->fsig->format; if (p->fsig->sliding) { /* get params from input fsig */ /* we TRUST they are legal */ int wintype = p->fsig->wintype; /* and put into locals */ p->wintype = wintype; p->format = p->fsig->format; csound->AuxAlloc(csound, p->fsig->NB * sizeof(double), &p->oldOutPhase); csound->AuxAlloc(csound, p->fsig->NB * sizeof(double), &p->output); return OK; } /* and put into locals */ halfwinsize = M/2; buflen = M*4; IO = (double)overlap; /* always, no time-scaling possible */ p->arate = csound->esr / (MYFLT) overlap; p->fund = csound->esr / (MYFLT) N; nBins = N/2 + 1; Lf = Mf = 1 - M%2; /* deal with iinit later on! */ csound->AuxAlloc(csound, overlap * sizeof(MYFLT), &p->overlapbuf); csound->AuxAlloc(csound, (N+2) * sizeof(MYFLT), &p->synbuf); csound->AuxAlloc(csound, (M+Mf) * sizeof(MYFLT), &p->analwinbuf); csound->AuxAlloc(csound, (M+Mf) * sizeof(MYFLT), &p->synwinbuf); csound->AuxAlloc(csound, nBins * sizeof(MYFLT), &p->oldOutPhase); csound->AuxAlloc(csound, buflen * sizeof(MYFLT), &p->output); synwinhalf = (MYFLT *) (p->synwinbuf.auxp) + halfwinsize; /* synthesis windows */ if (M <= N) { if (UNLIKELY(PVS_CreateWindow(csound, synwinhalf, wintype, M) != OK)) return NOTOK; for (i = 1; i <= halfwinsize; i++) *(synwinhalf - i) = *(synwinhalf + i - Lf); sum = FL(0.0); for (i = -halfwinsize; i <= halfwinsize; i++) sum += *(synwinhalf + i); sum = FL(2.0) / sum; for (i = -halfwinsize; i <= halfwinsize; i++) *(synwinhalf + i) *= sum; sum = FL(0.0); /* no timescaling, so I(nterpolation) will always = D(ecimation) = overlap */ for (i = -halfwinsize; i <= halfwinsize; i+=overlap) sum += *(synwinhalf + i) * *(synwinhalf + i); } else { /* have to make analysis window to get amp scaling */ /* so this ~could~ be a local alloc and free...*/ double dN = (double)N; analwinhalf = (MYFLT *) (p->analwinbuf.auxp) + halfwinsize; if (UNLIKELY(PVS_CreateWindow(csound, analwinhalf, wintype, M) != OK)) return NOTOK; for (i = 1; i <= halfwinsize; i++) analwinhalf[-i] = analwinhalf[i - Mf]; // sinc function if (Mf) *analwinhalf *= (MYFLT)(dN * sin(PI*0.5/dN) / ( PI*0.5)); for (i = 1; i <= halfwinsize; i++) *(analwinhalf + i) *= (MYFLT) (dN * sin((double)(PI*(i+0.5*Mf)/dN)) / (PI*(i+0.5*Mf))); for (i = 1; i <= halfwinsize; i++) *(analwinhalf - i) = *(analwinhalf + i - Mf); /* get net amp */ sum = FL(0.0); for (i = -halfwinsize; i <= halfwinsize; i++) sum += *(analwinhalf + i); sum = FL(2.0) / sum; /* factor of 2 comes in later in trig identity */ if (UNLIKELY(PVS_CreateWindow(csound, synwinhalf, wintype, M) != OK)) return NOTOK; for (i = 1; i <= halfwinsize; i++) *(synwinhalf - i) = *(synwinhalf + i - Lf); if (Lf) *synwinhalf *= (MYFLT)(IO * sin((double)(PI*0.5/IO)) / (PI*0.5)); for (i = 1; i <= halfwinsize; i++) *(synwinhalf + i) *= (MYFLT) ((double)IO * sin((double)(PI*(i+0.5*Lf)/IO)) / (PI*(i+0.5*(double)Lf))); for (i = 1; i <= halfwinsize; i++) *(synwinhalf - i) = *(synwinhalf + i - Lf); } if (!(N & (N - 1L))) sum = csound->GetInverseRealFFTScale(csound, (int) N)/ sum; else sum = FL(1.0) / sum; for (i = -halfwinsize; i <= halfwinsize; i++) *(synwinhalf + i) *= sum; /* p->invR = FL(1.0) / csound->esr; */ p->RoverTwoPi = p->arate / TWOPI_F; p->TwoPioverR = TWOPI_F / p->arate; p->Fexact = csound->esr / (MYFLT)N; p->nO = -(halfwinsize / overlap) * overlap; /* input time (in samples) */ p->Ii = 0; /* number of new outputs to write */ p->IOi = 0; p->outptr = 0; p->nextOut = (MYFLT *) (p->output.auxp); p->buflen = buflen; if (!(N & (N - 1))) /* if pow of two use this */ p->setup = csound->RealFFT2Setup(csound,N,FFT_INV); return OK; } static MYFLT synth_tick(CSOUND *csound, PVSYNTH *p) { MYFLT *outbuf = (MYFLT *) (p->overlapbuf.auxp); if (p->outptr== p->fsig->overlap) { process_frame(csound, p); p->outptr = 0; } return outbuf[p->outptr++]; } static void process_frame(CSOUND *csound, PVSYNTH *p) { int i,j,k,ii,NO,NO2; float *anal; /* RWD MUST be 32bit */ MYFLT *syn, *output; MYFLT *oldOutPhase = (MYFLT *) (p->oldOutPhase.auxp); int32 N = p->fsig->N; MYFLT *obufptr,*outbuf,*synWindow; MYFLT mag,phase,angledif, the_phase; int32 synWinLen = p->fsig->winsize / 2; int32 overlap = p->fsig->overlap; /*int32 format = p->fsig->format; */ /* fsigs MUST be corect format, as we offer no mechanism for assignment to a different one*/ NO = N; /* always the same */ NO2 = NO/2; syn = (MYFLT *) (p->synbuf.auxp); anal = (float *) (p->fsig->frame.auxp); /* RWD MUST be 32bit */ output = (MYFLT *) (p->output.auxp); outbuf = (MYFLT *) (p->overlapbuf.auxp); synWindow = (MYFLT *) (p->synwinbuf.auxp) + synWinLen; /* reconversion: The magnitude and angle-difference-per-second in syn (assuming an intermediate sampling rate of rOut) are converted to real and imaginary values and are returned in syn. This automatically incorporates the proper phase scaling for time modifications. */ if (LIKELY(NO <= N)) { for (i = 0; i < NO+2; i++) syn[i] = (MYFLT) anal[i]; } else { for (i = 0; i <= N+1; i++) syn[i] = (MYFLT) anal[i]; for (i = N+2; i < NO+2; i++) syn[i] = FL(0.0); } #ifdef NOTDEF if (format==PVS_AMP_PHASE) { for (ii=0 /*, i0=syn, i1=syn+1*/; ii<= NO2; ii+=2 /* i++, i0+=2, i1+=2*/) { mag = syn[ii]; /* *i0; */ phase = syn[ii+1]; /* *i1; */ /* *i0 */ syn[ii] = (MYFLT)((double)mag * cos((double)phase)); /* *i1 */ syn[ii+1] = (MYFLT)((double)mag * sin((double)phase)); } } else if (format == PVS_AMP_FREQ) { #endif for (i=ii=0 /*, i0=syn, i1=syn+1*/; i<= NO2; i++, ii+=2 /*i0+=2, i1+=2*/) { mag = syn[ii]; /* *i0; */ /* RWD variation to keep phase wrapped within +- TWOPI */ /* this is spread across several frame cycles, as the problem does not develop for a while */ angledif = p->TwoPioverR * ( /* *i1 */ syn[ii+1] - ((MYFLT)i * p->Fexact)); the_phase = /* *(oldOutPhase + i) */ oldOutPhase[i] + angledif; if (i== p->bin_index) the_phase = (MYFLT) fmod(the_phase,TWOPI); /* *(oldOutPhase + i) = the_phase; */ oldOutPhase[i] = the_phase; phase = the_phase; /* *i0 */ syn[ii] = (MYFLT)((double)mag * cos((double)phase)); /* *i1 */ syn[ii+1] = (MYFLT)((double)mag * sin((double)phase)); } #ifdef NOTDEF } #endif /* for phase normalization */ if (++(p->bin_index) == NO2+1) p->bin_index = 0; /* else it must be PVOC_COMPLEX */ /* synthesis: The synthesis subroutine uses the Weighted Overlap-Add technique to reconstruct the time-domain signal. The (N/2 + 1) phase vocoder channel outputs at time n are inverse Fourier transformed, windowed, and added into the output array. The subroutine thinks of output as a shift register in which locations are referenced modulo obuflen. Therefore, the main program must take care to zero each location which it "shifts" out (to standard output). The subroutines reals and fft together perform an efficient inverse FFT. */ if (!(NO & (NO - 1))) { /*printf("N %d %d \n", NO, NO & (NO-1));*/ syn[1] = syn[NO]; /* csound->InverseRealFFT(csound, syn, NO);*/ csound->RealFFT2(csound,p->setup,syn); syn[NO] = syn[NO + 1] = FL(0.0); } else csound->InverseRealFFTnp2(csound, syn, NO); j = p->nO - synWinLen - 1; while (j < 0) j += p->buflen; j = j % p->buflen; k = p->nO - synWinLen - 1; while (k < 0) k += NO; k = k % NO; for (i = -synWinLen; i <= synWinLen; i++) { /*overlap-add*/ if (++j >= p->buflen) j -= p->buflen; if (++k >= NO) k -= NO; /* *(output + j) += *(syn + k) * *(synWindow + i); */ output[j] += syn[k] * synWindow[i]; } obufptr = outbuf; for (i = 0; i < p->IOi;) { /* shift out next IOi values */ int todo = (p->IOi-i <= output+p->buflen - p->nextOut ? p->IOi-i : output+p->buflen - p->nextOut); /*outfloats(nextOut, todo, ofd);*/ /*copy data to external buffer */ /*for (n=0;n < todo;n++) *obufptr++ = p->nextOut[n]; */ memcpy(obufptr, p->nextOut, sizeof(MYFLT)*todo); obufptr += todo; i += todo; /* for (j = 0; j < todo; j++) *p->nextOut++ = FL(0.0); */ memset(p->nextOut, 0, sizeof(MYFLT)*todo); p->nextOut += todo; if (p->nextOut >= (output + p->buflen)) p->nextOut -= p->buflen; } /* increment time */ p->nO += overlap; if (p->nO > (synWinLen + /*I*/overlap)) p->Ii = overlap; else if (p->nO > synWinLen) p->Ii = p->nO - synWinLen; else { p->Ii = 0; for (i=p->nO+synWinLen; ibuflen; i++) if (i > 0) output[i] = FL(0.0); } p->IOi = p->Ii; } int pvssynth(CSOUND *csound, PVSYNTH *p) { int i, k; int ksmps = CS_KSMPS; int N = p->fsig->N; int NB = p->fsig->NB; MYFLT *aout = p->aout; CMPLX *ff; double *h = (double*)p->oldOutPhase.auxp; double *output = (double*)p->output.auxp; /* Get real part from AMP/FREQ */ for (i=0; ifsig->frame.auxp) + i*NB; for (k=0; kesr/N; /* get bin deviation from freq deviation */ tmp *= TWOPI /csound->esr; /* add the overlap phase advance back in */ tmp += (double)k*TWOPI/N; h[k] = phase = mod2Pi(h[k] + tmp); output[k] = ff[k].re*cos(phase); } a = FL(0.0); for (k=1; kh.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT *aout = p->aout; if (UNLIKELY(p->output.auxp==NULL)) { return csound->PerfError(csound,p->h.insdshead, Str("pvsynth: Not Initialised.\n")); } if (p->fsig->sliding) return pvssynth(csound, p); if (UNLIKELY(offset)) memset(aout, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&aout[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset; i> 31); tmp2 = (tmp2 & (uint32_t) 0x7FFFFFFF) + (tmp2 >> 31); (*seedVal) = (int) tmp2; return (int) tmp2; } /* Period parameters */ #define N (624) #define M (397) #define MATRIX_A 0x9908B0DFU /* constant vector a */ #define UPPER_MASK 0x80000000U /* most significant w-r bits */ #define LOWER_MASK 0x7FFFFFFFU /* least significant r bits */ static CS_NOINLINE void MT_update_state(uint32_t *mt) { /* mag01[x] = x * MATRIX_A for x=0,1 */ const uint32_t mag01[2] = { (uint32_t) 0, (uint32_t) MATRIX_A }; int i; uint32_t y; for (i = 0; i < (N - M); i++) { y = (mt[i] & UPPER_MASK) | (mt[i + 1] & LOWER_MASK); mt[i] = mt[i + M] ^ (y >> 1) ^ mag01[y & (uint32_t) 1]; } for ( ; i < (N - 1); i++) { y = (mt[i] & UPPER_MASK) | (mt[i + 1] & LOWER_MASK); mt[i] = mt[i + (M - N)] ^ (y >> 1) ^ mag01[y & (uint32_t) 1]; } y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ mag01[y & (uint32_t) 1]; } /* generates a random number on [0,0xffffffff]-interval */ PUBLIC uint32_t csoundRandMT(CsoundRandMTState *p) { int i = p->mti; uint32_t y; if (i >= N) { /* generate N words at one time */ MT_update_state(&(p->mt[0])); i = 0; } y = p->mt[i]; p->mti = i + 1; /* Tempering */ y ^= (y >> 11); y ^= (y << 7) & (uint32_t) 0x9D2C5680U; y ^= (y << 15) & (uint32_t) 0xEFC60000U; y ^= (y >> 18); return y; } /* initialise by an array with array-length */ /* init_key is the array for initialising keys */ /* key_length is its length */ /* slight change for C++, 2004/2/26 */ PUBLIC void csoundSeedRandMT(CsoundRandMTState *p, const uint32_t *initKey, uint32_t keyLength) { int i, j, k; uint32_t x; /* if array is NULL, use length parameter as simple 32 bit seed */ x = (initKey == NULL ? keyLength : (uint32_t) 19650218); p->mt[0] = x; for (i = 1; i < N; i++) { /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ /* In the previous versions, MSBs of the seed affect */ /* only MSBs of the array mt[]. */ /* 2002/01/09 modified by Makoto Matsumoto */ x = ((uint32_t) 1812433253 * (x ^ (x >> 30)) + (uint32_t) i); p->mt[i] = x; } p->mti = N; if (initKey == NULL) return; i = 0; j = 0; k = (N > (int) keyLength ? N : (int) keyLength); for ( ; k; k--) { x = p->mt[i++]; p->mt[i] = (p->mt[i] ^ ((x ^ (x >> 30)) * (uint32_t) 1664525)) + initKey[j] + (uint32_t) j; /* non linear */ if (i == (N - 1)) { p->mt[0] = p->mt[N - 1]; i = 0; } if (++j >= (int) keyLength) j = 0; } for (k = (N - 1); k; k--) { x = p->mt[i++]; p->mt[i] = (p->mt[i] ^ ((x ^ (x >> 30)) * (uint32_t) 1566083941)) - (uint32_t) i; /* non linear */ if (i == (N - 1)) { p->mt[0] = p->mt[N - 1]; i = 0; } } /* MSB is 1; assuring non-zero initial array */ p->mt[0] = (uint32_t) 0x80000000U; } /* called from csoundPreCompile() */ void csound_init_rand(CSOUND *csound) { uint32_t tmp; csound->csRandState = &(csound->randState_); csound->randSeed1 = 15937; tmp = (uint32_t) csound->GetRandomSeedFromTime(); while (tmp >= (uint32_t) 0x7FFFFFFE) tmp -= (uint32_t) 0x7FFFFFFE; csound->randSeed2 = ((int) tmp + 1); csound->SeedRandMT(&(csound->randState_), NULL, (uint32_t) 5489); } csound-6.10.0/OOps/remote.c000066400000000000000000000621271321653344700154300ustar00rootroot00000000000000 /* remote.c: Copyright (C) 2006 by Barry Vercoe This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "remote.h" /* Somewhat revised from the original. Pete G. Nov 2012 More correct, I think, but I could be wrong... (:-/) */ /* #ifdef HAVE_SOCKETS */ /* #ifndef WIN32 */ /* #include */ /* #ifdef LINUX */ /* #include */ /* #endif */ /* #ifdef __HAIKU__ */ /* #include */ /* #endif */ /* #include */ /* #include */ /* #include */ /* extern int inet_aton (const char *, struct in_addr *); */ /* #include */ /* #else */ /* #include */ /* #endif /\* not WIN32 *\/ */ /* #endif /\* HAVE_SOCKETS *\/ */ #define MAXREMOTES 10 #define ST(x) (((REMOTE_GLOBALS*) ((CSOUND*)csound)->remoteGlobals)->x) void remote_Cleanup(CSOUND *csound); void remoteRESET(CSOUND *csound) { /* Recover space */ if (csound->remoteGlobals) csound->Free(csound, csound->remoteGlobals); csound->remoteGlobals = NULL; } #if defined(HAVE_SOCKETS) #if !defined(WIN32) || defined(__CYGWIN__) #include #endif #if 0 static int foo(char *ipaddr) { /* VL 12/10/06: something needs to go here */ /* gethostbyname is the real answer; code below is unsafe */ char hostname[1024]; struct hostent *he; struct sockaddr_in sin; gethostname(hostname, sizeof(hostname)); printf("hostname=%s\n", hostname); he = gethostbyname(hostname); memset(&sin, 0, sizeof (struct sockaddr_in)); memmove(&sin.sin_addr, he->h_addr_list[0], he->h_length); strcpy(ipaddr, inet_ntoa (sin.sin_addr)); printf("IP: %s\n", ipaddr); return 0; } #endif /* get the IPaddress of this machine */ static int getIpAddress(char *ipaddr) { #if defined(WIN32) && !defined(__CYGWIN__) /* VL 12/10/06: something needs to go here */ /* gethostbyname is the real answer; code below is unsafe */ char hostname[1024]; struct hostent *he; struct sockaddr_in sin; if (gethostname(hostname, sizeof(hostname))<0) return 1; if ((he = gethostbyname(hostname))==NULL) return 1; memset(&sin, 0, sizeof (struct sockaddr_in)); memmove(&sin.sin_addr, he->h_addr_list[0], he->h_length); strcpy(ipaddr, inet_ntoa (sin.sin_addr)); return 0; #else int ret = 1; struct ifreq ifr; int fd; fd = socket(AF_INET,SOCK_DGRAM, 0); if (fd >= 0) { char *dev = getenv("CS_ETHER"); if (dev) strncpy(ifr.ifr_name, dev, IFNAMSIZ-1); else { #ifdef MACOSX strncpy(ifr.ifr_name, "en0", IFNAMSIZ-1); #else strncpy(ifr.ifr_name, "eth0", IFNAMSIZ-1); #endif } ifr.ifr_name[IFNAMSIZ-1] = '\0'; if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) { char *local; local = inet_ntoa(((struct sockaddr_in *)(&ifr.ifr_addr))->sin_addr); strcpy(ipaddr, local); printf("IP for remote: %s: %s\n", ifr.ifr_name, ipaddr); ret = 0; } else { strncpy(ifr.ifr_name, "wlan0", IFNAMSIZ-1); ifr.ifr_name[IFNAMSIZ-1] = '\0'; if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) { char *local; local = inet_ntoa(((struct sockaddr_in *)(&ifr.ifr_addr))->sin_addr); strcpy(ipaddr, local); printf("IP for remote: %s: %s\n", ifr.ifr_name, ipaddr); ret = 0; } } } if (fd>=0) close(fd); return ret; #endif } char remoteID(CSOUND *csound) { int len = strlen(ST(ipadrs)); return ST(ipadrs)[len-1]; } static int callox(CSOUND *csound) { if (csound->remoteGlobals == NULL) { csound->remoteGlobals = csound->Calloc(csound, sizeof(REMOTE_GLOBALS)); if (UNLIKELY(csound->remoteGlobals == NULL)) { csound->Message(csound, Str("insufficient memory to initialise remote" " globals.")); goto error; } ST(remote_port) = REMOT_PORT; } ST(socksout) = (SOCK*)csound->Calloc(csound,(size_t)MAXREMOTES * sizeof(SOCK)); if (UNLIKELY(ST(socksout) == NULL)) { csound->Message(csound, Str("insufficient memory to initialise outgoing " "socket table.")); goto error; } ST(socksin) = (int*) csound->Calloc(csound,(size_t)MAXREMOTES * sizeof(int)); if (UNLIKELY(ST(socksin) == NULL)) { csound->Message(csound, Str("insufficient memory to initialise incoming " "socket table.")); goto error; } ST(insrfd_list) = (int*) csound->Calloc(csound,(size_t)MAXREMOTES * sizeof(int)); if (UNLIKELY(ST(insrfd_list) == NULL)) { csound->Message(csound, Str("insufficient memory to initialise " "insrfd_list.")); goto error; } ST(chnrfd_list) = (int*) csound->Calloc(csound,(size_t)MAXREMOTES * sizeof(int)); if (UNLIKELY(ST(chnrfd_list) == NULL)) { csound->Message(csound, Str("insufficient memory to initialise " "chnrfd_list.")); goto error; } ST(insrfd) = (int*) csound->Calloc(csound,(size_t)129 * sizeof(int)); if (UNLIKELY(ST(insrfd) == NULL)) { csound->Message(csound, Str("insufficient memory to initialise " "insrfd table.")); goto error; } ST(chnrfd) = (int*) csound->Calloc(csound,(size_t)17 * sizeof(int)); if (UNLIKELY(ST(chnrfd) == NULL)) { csound->Message(csound, Str("insufficient memory to initialise " "chnrfd table.")); goto error; } ST(ipadrs) = (char*) csound->Calloc(csound,(size_t)15 * sizeof(char)); if (UNLIKELY(ST(ipadrs) == NULL)) { csound->Message(csound, Str("insufficient memory to initialise " "local ip address.")); goto error; } /* get IP adrs of this machine */ /* FIXME: don't hardcode eth0 */ if (UNLIKELY(getIpAddress(ST(ipadrs)) != 0)) { csound->Message(csound, Str("unable to get local ip address.")); goto error; } return 0; error: /* Clean up anything we may have allocated before running out of memory */ remote_Cleanup(csound); return -1; } /* Cleanup the above; called from musmon csoundCleanup */ void remote_Cleanup(CSOUND *csound) { int fd; if (csound->remoteGlobals == NULL) return; if (ST(socksout) != NULL) { SOCK *sop = ST(socksout), *sop_end = sop + MAXREMOTES; for ( ; sop < sop_end; sop++) if ((fd = sop->rfd) > 0) close(fd); csound->Free(csound,(char *)ST(socksout)); ST(socksout) = NULL; } if (ST(socksin) != NULL) { int *sop = ST(socksin), *sop_end = sop + MAXREMOTES; for ( ; sop < sop_end; sop++) if ((fd = *sop) > 0) close(fd); csound->Free(csound,(char *)ST(socksin)); ST(socksin) = NULL; } if (ST(insrfd_list) != NULL) { csound->Free(csound, ST(insrfd_list)); ST(insrfd_list) = NULL; } if (ST(chnrfd_list) != NULL) { csound->Free(csound, ST(chnrfd_list)); ST(chnrfd_list) = NULL; } if (ST(insrfd) != NULL) { csound->Free(csound, ST(insrfd)); ST(insrfd) = NULL; } if (ST(chnrfd) != NULL) { csound->Free(csound, ST(chnrfd)); ST(chnrfd) = NULL; } if (ST(ipadrs) != NULL) { csound->Free(csound, ST(ipadrs)); ST(ipadrs) = NULL; } ST(insrfd_count) = ST(chnrfd_count) = 0; csound->Free(csound, csound->remoteGlobals); csound->remoteGlobals = NULL; } static int CLopen(CSOUND *csound, char *ipadrs) /* Client -- open to send */ { int rfd, i; SOCK *sop = ST(socksout), *sop_end = sop + MAXREMOTES; do { if (ipadrs == sop->adr) /* if socket already exists */ return sop->rfd; /* return with that */ } while (++sop < sop_end); /* create a STREAM (TCP) socket in the INET (IP) protocol */ if (UNLIKELY(( rfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)) { return csound->InitError(csound, Str("could not open remote port")); } memset(&(ST(to_addr)), 0, sizeof(ST(to_addr))); /* clear sock mem */ ST(to_addr).sin_family = AF_INET; /* set as INET address */ /* server IP adr, netwk byt order */ #if defined(WIN32) && !defined(__CYGWIN__) ST(to_addr).sin_addr.S_un.S_addr = inet_addr((const char *)ipadrs); #else inet_aton((const char *)ipadrs, &(ST(to_addr).sin_addr)); #endif ST(to_addr).sin_port = htons((int) ST(remote_port)); /* port we will listen on, network byte order */ for (i=0; i<10; i++){ if (UNLIKELY(connect(rfd, (struct sockaddr *) &ST(to_addr), sizeof(ST(to_addr))) < 0)) csound->Message(csound, Str("---> Could not connect \n")); else goto conok; } close(rfd); return csound->InitError(csound, Str("---> Failed all attempts to connect. \n")); conok: csound->Message(csound, Str("---> Connected. \n")); for (sop = ST(socksout); sop < sop_end; sop++) if (sop->adr == NULL) { sop->adr = ipadrs; /* record the new socket */ sop->rfd = rfd; break; } return rfd; } int CLsend(CSOUND *csound, int conn, void *data, int length) { int nbytes; if (UNLIKELY((nbytes = write(conn, data, length)) <= 0)) { csound->ErrorMsg(csound, Str("write to socket failed")); return NOTOK; } /* csound->Message(csound, "nbytes sent: %d \n", nbytes); */ return OK; } static int SVopen(CSOUND *csound) /* Server -- open to receive */ { int conn, socklisten,opt; char ipadrs[15]; int *sop = ST(socksin), *sop_end = sop + MAXREMOTES; #if defined(WIN32) && !defined(__CYGWIN__) int clilen; #else socklen_t clilen; #endif opt = 1; if (UNLIKELY((socklisten = socket(PF_INET, SOCK_STREAM, 0)) < 0)) { return csound->InitError(csound, Str("creating socket\n")); } else csound->Message(csound, Str("created socket \n")); /* set the addresse to be reusable */ #if defined(WIN32) && !defined(__CYGWIN__) if (UNLIKELY( setsockopt(socklisten, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(opt)) < 0 )) #else if (UNLIKELY( setsockopt(socklisten, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0 )) #endif return csound->InitError(csound, Str("setting socket option to reuse the address\n")); memset(&(ST(to_addr)), 0, sizeof(ST(to_addr))); /* clear sock mem */ ST(local_addr).sin_family = AF_INET; /* set as INET address */ /* our adrs, netwrk byt order */ #if defined(WIN32) && !defined(__CYGWIN__) ST(to_addr).sin_addr.S_un.S_addr = inet_addr((const char *)ipadrs); #else inet_aton((const char *)ipadrs, &(ST(local_addr).sin_addr)); #endif /* ST(local_addr).sin_port = htons((int)REMOT_PORT); */ ST(local_addr).sin_port = htons((int) ST(remote_port)); /* port we will listen on, netwrk byt order */ /* associate the socket with the address and port */ if (UNLIKELY(bind (socklisten, (struct sockaddr *) &ST(local_addr), sizeof(ST(local_addr))) < 0)) { shutdown(socklisten, SHUT_RD); return csound->InitError(csound, Str("bind failed")); } if (UNLIKELY(listen(socklisten, 5) < 0)) { /* start the socket listening for new connections -- may wait */ shutdown(socklisten, SHUT_RD); return csound->InitError(csound, Str("listen failed")); } clilen = sizeof(ST(local_addr)); /* FIX THIS FOR MULTIPLE CLIENTS !!!!!!!*/ conn = accept(socklisten, (struct sockaddr *) &ST(local_addr), &clilen); if (UNLIKELY(conn < 0)) { shutdown(socklisten, SHUT_RD); return csound->InitError(csound, Str("accept failed")); } else { csound->Message(csound, Str("accepted, conn=%d \n"), conn); for (sop = ST(socksin); sop < sop_end; sop++) if (*sop == 0) { *sop = conn; /* record the new connection */ break; } } shutdown(socklisten, SHUT_RD); return OK; } int SVrecv(CSOUND *csound, int conn, void *data, int length) { struct sockaddr from; /* VL, 12/10/06: I'm guessing here. If someone knows better, fix it */ #if defined(WIN32) && !defined(__CYGWIN__) #define MSG_DONTWAIT 0 int clilen = sizeof(from); #else socklen_t clilen = sizeof(from); #endif size_t n; IGN(csound); n = recvfrom(conn, data, length, MSG_DONTWAIT, &from, &clilen); /* if (n>0) csound->Message(csound, "nbytes received: %d \n", (int)n); */ return (int)n; } /* ///////////// INSTR 0 opcodes ///////////////////// */ int remoteport(CSOUND *csound, REMOTEPORT *p) { if (csound->remoteGlobals==NULL) { if (UNLIKELY(callox(csound) < 0)) { return csound->InitError(csound, Str("failed to initialise remote globals.")); } } if (ST(socksin) == NULL) { if (*p->port <= FL(0.0)) ST(remote_port) = REMOT_PORT; else ST(remote_port) = (int)(*p->port+FL(0.5)); return OK; } return NOTOK; } int insremot(CSOUND *csound, INSREMOT *p) /* declare certain instrs for remote Csounds */ { /* INSTR 0 opcode */ int16 nargs = p->INOCOUNT; if (csound->remoteGlobals==NULL || ST(socksin) == NULL) { if (UNLIKELY(callox(csound) < 0)) { return csound->InitError(csound, Str("failed to initialise remote globals.")); } } if (UNLIKELY(nargs < 3)) { return csound->InitError(csound, Str("missing instr nos")); } /* csound->Message(csound, Str("*** str1: %s own:%s\n"), */ /* (char *)p->str1 , ST(ipadrs)); */ if (strcmp(ST(ipadrs), (char *)p->str1->data) == 0) { /* if client is this adrs */ MYFLT **argp = p->insno; int rfd = 0; if ((rfd = CLopen(csound, (char *)p->str2->data)) < 0) /* open port to remote */ return NOTOK; for (nargs -= 2; nargs--; ) { int16 insno = (int16)**argp++; /* & for each insno */ if (UNLIKELY(insno <= 0)) { close(rfd); return csound->InitError(csound, Str("illegal instr no")); } if (UNLIKELY(ST(insrfd)[insno])) { close(rfd); return csound->InitError(csound, Str("insno already remote")); } ST(insrfd)[insno] = rfd; /* record file descriptor */ } ST(insrfd_list)[ST(insrfd_count)++] = rfd; /* and make a list */ } else if (!strcmp(ST(ipadrs),(char *)p->str2->data)) { /* if server is this adrs*/ /* csound->Message(csound, Str("*** str2: %s own:%s\n"), */ /* (char *)p->str2 , ST(ipadrs)); */ /* open port to listen */ if (UNLIKELY(SVopen(csound) == NOTOK)){ return csound->InitError(csound, Str("Failed to open port to listen")); } } return OK; } int insglobal(CSOUND *csound, INSGLOBAL *p) /* declare certain instrs global remote Csounds */ { /* INSTR 0 opcode */ int16 nargs = p->INOCOUNT; if (csound->remoteGlobals==NULL || ST(socksin) == NULL) { if (UNLIKELY(callox(csound) < 0)) { return csound->InitError(csound, Str("failed to initialise remote globals.")); } } if (UNLIKELY(nargs < 2)) { return csound->InitError(csound, Str("missing instr nos")); } csound->Message(csound, Str("*** str1: %s own:%s\n"), (char *)p->str1->data , ST(ipadrs)); if (strcmp(ST(ipadrs), (char *)p->str1->data) == 0) { /* if client is this adrs */ MYFLT **argp = p->insno; for (nargs -= 1; nargs--; ) { int16 insno = (int16)**argp++; /* for each insno */ if (UNLIKELY(insno <= 0 || insno > 128)) { return csound->InitError(csound, Str("illegal instr no")); } if (UNLIKELY(ST(insrfd)[insno])) { return csound->InitError(csound, Str("insno already specific remote")); } ST(insrfd)[insno] = GLOBAL_REMOT; /* mark as GLOBAL */ } } return OK; } int midremot(CSOUND *csound, MIDREMOT *p) /* declare certain channels for remote Csounds */ { /* INSTR 0 opcode */ int16 nargs = p->INOCOUNT; if (csound->remoteGlobals==NULL || ST(socksin) == NULL) { if (UNLIKELY(callox(csound) < 0)) { return csound->InitError(csound, Str("failed to initialise remote globals.")); } } if (UNLIKELY(nargs < 3)) { return csound->InitError(csound, Str("missing channel nos")); } if (strcmp(ST(ipadrs), (char *)p->str1->data) == 0) { /* if client is this adrs */ MYFLT **argp = p->chnum; int rfd; /* open port to remote */ if (UNLIKELY((rfd = CLopen(csound, (char *)p->str2->data)) < 0)) return NOTOK; for (nargs -= 2; nargs--; ) { int16 chnum = (int16)**argp++; /* & for each channel */ if (UNLIKELY(chnum <= 0 || chnum > 16)) { /* THESE ARE MIDCHANS+1 */ close(rfd); return csound->InitError(csound, Str("illegal channel no")); } if (UNLIKELY(ST(chnrfd)[chnum])) { close(rfd); return csound->InitError(csound, Str("channel already remote")); } ST(chnrfd)[chnum] = rfd; /* record file descriptor */ } ST(chnrfd_list)[ST(chnrfd_count)++] = rfd; /* and make a list */ } else if (!strcmp(ST(ipadrs), (char *)p->str2->data)) { /* if server is this adrs */ /* open port to listen */ if (UNLIKELY(SVopen(csound) == NOTOK)){ return csound->InitError(csound, Str("Failed to open port to listen")); } csound->oparms->RMidiin = 1; /* & enable rtevents in */ } return OK; } int midglobal(CSOUND *csound, MIDGLOBAL *p) /* declare certain chnls global remote Csounds */ { /* INSTR 0 opcode */ int16 nargs = p->INOCOUNT; if (csound->remoteGlobals==NULL || ST(socksin) == NULL) { if (UNLIKELY(callox(csound) < 0)) { return csound->InitError(csound, Str("failed to initialise remote globals.")); } } if (UNLIKELY(nargs < 2)) { return csound->InitError(csound, Str("missing channel nos")); } /* csound->Message(csound, Str("*** str1: %s own:%s\n"), */ /* (char *)p->str1 , ST(ipadrs)); */ if (strcmp(ST(ipadrs), (char *)p->str1->data) == 0) { /* if client is this adrs */ MYFLT **argp = p->chnum; for (nargs -= 1; nargs--; ) { int16 chnum = (int16)**argp++; /* for each channel */ if (UNLIKELY(chnum <= 0 || chnum > 16)) { return csound->InitError(csound, Str("illegal channel no")); } if (UNLIKELY(ST(chnrfd)[chnum])) { return csound->InitError(csound, Str("channel already specific remote")); } ST(chnrfd)[chnum] = GLOBAL_REMOT; /* mark as GLOBAL */ } } return OK; } /* //////////////// MUSMON SERVICES //////////////// */ int insSendevt(CSOUND *csound, EVTBLK *evt, int rfd) { REMOT_BUF *bp = &ST(CLsendbuf); EVTBLK *cpp = (EVTBLK *)bp->data; /* align an EVTBLK struct */ int nn; MYFLT *f, *g; cpp->pinstance = NULL; cpp->strarg = NULL; /* copy the initial header */ cpp->scnt = 0; cpp->opcod = evt->opcod; cpp->pcnt = evt->pcnt; f = &evt->p2orig; g = &cpp->p2orig; for (nn = evt->pcnt + 3; nn--; ) /* copy the remaining data */ *g++ = *f++; bp->type = SCOR_EVT; /* insert type and len */ bp->len = (char *)g - (char *)bp; if (UNLIKELY(CLsend(csound, rfd, (void *)bp, (int)bp->len) < 0)) { csound->ErrorMsg(csound, Str("CLsend failed")); return NOTOK; } else return OK; } int insGlobevt(CSOUND *csound, EVTBLK *evt) /* send an event to all remote fd's */ { int nn; for (nn = 0; nn < ST(insrfd_count); nn++) { if (UNLIKELY(insSendevt(csound, evt, ST(insrfd_list)[nn]) == NOTOK)) return NOTOK; } return OK; } int MIDIsendevt(CSOUND *csound, MEVENT *evt, int rfd) { REMOT_BUF *bp = &ST(CLsendbuf); MEVENT *mep = (MEVENT *)bp->data; /* align an MEVENT struct */ *mep = *evt; /* & copy the data */ bp->type = MIDI_EVT; /* insert type and len */ bp->len = sizeof(int) * 2 + sizeof(MEVENT); if (UNLIKELY(CLsend(csound, rfd, (void *)bp, (size_t)bp->len) < 0)) { csound->ErrorMsg(csound, Str("CLsend failed")); return NOTOK; } else return OK; } int MIDIGlobevt(CSOUND *csound, MEVENT *evt) /* send an Mevent to all remote fd's */ { int nn; for (nn = 0; nn < ST(chnrfd_count); nn++) { if (UNLIKELY(MIDIsendevt(csound, evt, ST(chnrfd_list)[nn]) == NOTOK)) return NOTOK; } return OK; } int MIDIsend_msg(CSOUND *csound, MEVENT *evt, int rfd) { REMOT_BUF *bp = &ST(CLsendbuf); MEVENT *mep = (MEVENT *)bp->data; /* align an MEVENT struct */ *mep = *evt; /* & copy the data */ bp->type = MIDI_MSG; /* insert type and len */ bp->len = sizeof(int) * 2 + sizeof(MEVENT); if (UNLIKELY(CLsend(csound, rfd, (void *)bp, (size_t)bp->len) < 0)) { csound->ErrorMsg(csound, Str("CLsend failed")); return NOTOK; } else return OK; } /* send an M chnmsg to all remote fd's */ int MIDIGlob_msg(CSOUND *csound, MEVENT *evt) { int nn; for (nn = 0; nn < ST(chnrfd_count); nn++) { if (UNLIKELY(MIDIsend_msg(csound, evt, ST(chnrfd_list)[nn]) == NOTOK)) return NOTOK; } return OK; } int getRemoteInsRfd(CSOUND *csound, int insno) { if (csound->remoteGlobals && ST(insrfd)) return ST(insrfd)[insno]; else return 0; } int getRemoteInsRfdCount(CSOUND *csound) { if (csound->remoteGlobals) return ST(insrfd_count); else return 0; } int getRemoteChnRfd(CSOUND *csound, int chan) { if (csound->remoteGlobals && ST(chnrfd)) return ST(chnrfd)[chan]; else return 0; } int* getRemoteSocksIn(CSOUND *csound) { if (csound->remoteGlobals) return ST(socksin); else return 0; } #else /* HAVE_SOCKETS not defined */ char remoteID(CSOUND *csound) { return '\0'; } /* Cleanup the above; called from musmon csoundCleanup */ void remote_Cleanup(CSOUND *csound) { csound->remoteGlobals = NULL; return; } int SVrecv(CSOUND *csound, int conn, void *data, int length) { return 0; } /* INSTR 0 opcodes */ int remoteport(CSOUND *csound, REMOTEPORT *p) { csound->Warning(csound, Str("*** This version of Csound was not " "compiled with remote event support ***\n")); return OK; } int insremot(CSOUND *csound, INSREMOT *p) /* declare certain instrs for remote Csounds */ { csound->Warning(csound, Str("*** This version of Csound was not " "compiled with remote event support ***\n")); return OK; } int insglobal(CSOUND *csound, INSGLOBAL *p) /* declare certain instrs global remote Csounds */ { csound->Warning(csound, Str("*** This version of Csound was not " "compiled with remote event support ***\n")); return OK; } int midremot(CSOUND *csound, MIDREMOT *p) /* declare certain channels for remote Csounds */ { csound->Warning(csound, Str("*** This version of Csound was not " "compiled with remote event support ***\n")); return OK; } int midglobal(CSOUND *csound, MIDGLOBAL *p) /* declare certain chnls global remote Csounds */ { csound->Warning(csound, Str("*** This version of Csound was not " "compiled with remote event support ***\n")); return OK; } /* MUSMON SERVICES */ int insSendevt(CSOUND *csound, EVTBLK *evt, int rfd) { return OK; } int insGlobevt(CSOUND *csound, EVTBLK *evt) /* send an event to all remote fd's */ { return OK; } int MIDIsendevt(CSOUND *csound, MEVENT *evt, int rfd) { return OK; } int MIDIGlobevt(CSOUND *csound, MEVENT *evt) /* send an Mevent to all remote fd's */ { return OK; } int getRemoteInsRfd(CSOUND *csound, int insno) { return 0; } int getRemoteInsRfdCount(CSOUND *csound) { return 0; } int getRemoteChnRfd(CSOUND *csound, int chan) { return 0; } int* getRemoteSocksIn(CSOUND *csound) { return NULL; } #endif /* HAVE_SOCKETS */ csound-6.10.0/OOps/schedule.c000066400000000000000000000421071321653344700157250ustar00rootroot00000000000000/* schedule.c: Copyright (C) 1999, 2002 rasmus ekman, Istvan Varga, John ffitch, Gabriel Maldonado, matt ingalls This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "csoundCore.h" #include "namedins.h" #include "linevent.h" /* Keep Microsoft's schedule.h from being used instead of our schedule.h. */ #ifdef _MSC_VER #include "H/schedule.h" #else #include "schedule.h" #endif extern void csoundInputMessageInternal(CSOUND *, const char *); int eventOpcodeI_(CSOUND *csound, LINEVENT *p, int s, char p1); int eventOpcode_(CSOUND *csound, LINEVENT *p, int s, char p1); int schedule(CSOUND *csound, SCHED *p) { LINEVENT pp; int i; pp.h = p->h; char c[2] = "i"; pp.args[0] = (MYFLT *) c; pp.args[1] = p->which; pp.args[2] = p->when; pp.args[3] = p->dur; pp.argno = p->INOCOUNT+1; for (i=4; i < pp.argno ; i++) { pp.args[i] = p->argums[i-4]; } pp.flag = 1; return eventOpcodeI_(csound, &pp, 0, 'i'); } static void add_string_arg(char *s, const char *arg) { int offs = strlen(s) ; //char *c = s; s += offs; *s++ = ' '; *s++ ='\"'; while(*arg != '\0') { if(*arg == '\"') *s++ = '\\'; *s++ = *arg++; } *s++ = '\"'; *s = '\0'; //printf("%s \n", c); } int schedule_N(CSOUND *csound, SCHED *p) { int i; int argno = p->INOCOUNT+1; char s[16384]; sprintf(s, "i %f %f %f", *p->which, *p->when, *p->dur); for (i=4; i < argno ; i++) { MYFLT *arg = p->argums[i-4]; if (csoundGetTypeForArg(arg) == &CS_VAR_TYPE_S) { add_string_arg(s, ((STRINGDAT *)arg)->data); //sprintf(s, "%s \"%s\" ", s, ((STRINGDAT *)arg)->data); } else sprintf(s, "%s %f", s, *arg); } csoundInputMessageInternal(csound, s); return OK; } int schedule_SN(CSOUND *csound, SCHED *p) { int i; int argno = p->INOCOUNT+1; char s[16384]; sprintf(s, "i \"%s\" %f %f", ((STRINGDAT *)p->which)->data, *p->when, *p->dur); for (i=4; i < argno ; i++) { MYFLT *arg = p->argums[i-4]; if (csoundGetTypeForArg(arg) == &CS_VAR_TYPE_S) //sprintf(s, "%s \"%s\" ", s, ((STRINGDAT *)arg)->data); add_string_arg(s, ((STRINGDAT *)arg)->data); else sprintf(s, "%s %f", s, *arg); } //printf("%s\n", s); csoundInputMessageInternal(csound, s); return OK; } int schedule_S(CSOUND *csound, SCHED *p) { LINEVENT pp; int i; pp.h = p->h; char c[2] = "i"; pp.args[0] = (MYFLT *) c; pp.args[1] = p->which; pp.args[2] = p->when; pp.args[3] = p->dur; pp.argno = p->INOCOUNT+1; for (i=4; i < pp.argno ; i++) { pp.args[i] = p->argums[i-4]; } pp.flag = 1; return eventOpcodeI_(csound, &pp, 1, 'i'); } int ifschedule(CSOUND *csound, WSCHED *p) { /* All we need to do is ensure the trigger is set */ IGN(csound); p->todo = 1; return OK; } int kschedule(CSOUND *csound, WSCHED *p) { if (p->todo && *p->trigger != FL(0.0)) { LINEVENT pp; int i; pp.h = p->h; char c[2] = "i"; pp.args[0] = (MYFLT *) c; pp.args[1] = p->which; pp.args[2] = p->when; pp.args[3] = p->dur; pp.argno = p->INOCOUNT+1; for(i=4; i < pp.argno ; i++) { pp.args[i] = p->argums[i-4]; } p->todo =0; pp.flag = 1; if (IS_STR_ARG(p->which)){ return eventOpcode_(csound, &pp, 1, 'i'); } else { pp.flag = 0; return eventOpcode_(csound, &pp, 0, 'i'); } } else return OK; } /* tables are 4096 entries always */ #define MAXPHASE 0x1000000 #define MAXMASK 0x0ffffff int lfoset(CSOUND *csound, LFO *p) { /* Types: 0: sine 1: triangles 2: square (biplar) 3: square (unipolar) 4: saw-tooth 5: saw-tooth(down) */ int type = (int)*p->type; if (type == 0) { /* Sine wave so need to create */ int i; if (p->auxd.auxp==NULL) { csound->AuxAlloc(csound, sizeof(MYFLT)*4097L, &p->auxd); p->sine = (MYFLT*)p->auxd.auxp; } for (i=0; i<4096; i++) p->sine[i] = SIN(TWOPI_F*(MYFLT)i/FL(4096.0)); /* csound->Message(csound,"Table set up (max is %d)\n", MAXPHASE>>10); */ } else if (UNLIKELY(type>5 || type<0)) { return csound->InitError(csound, Str("LFO: unknown oscilator type %d"), type); } p->lasttype = type; p->phs = 0; return OK; } int lfok(CSOUND *csound, LFO *p) { int32 phs; MYFLT fract; MYFLT res; int32 iphs; phs = p->phs; switch (p->lasttype) { default: return csound->PerfError(csound, p->h.insdshead, Str("LFO: unknown oscilator type %d"), p->lasttype); case 0: iphs = phs >> 12; fract = (MYFLT)(phs & 0xfff)/FL(4096.0); res = p->sine[iphs]; res = res + (p->sine[iphs+1]-res)*fract; break; case 1: /* Trangular */ res = (MYFLT)((phs<<2)&MAXMASK)/(MYFLT)MAXPHASE; if (phs < MAXPHASE/4) {} else if (phs < MAXPHASE/2) res = FL(1.0) - res; else if (phs < 3*MAXPHASE/4) res = - res; else res = res - FL(1.0); break; case 2: /* Bipole square wave */ if (phsxcps * MAXPHASE * CS_ONEDKR); phs &= MAXMASK; p->phs = phs; *p->res = *p->kamp * res; return OK; } int lfoa(CSOUND *csound, LFO *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 phs; MYFLT fract; MYFLT res; int32 iphs, inc; MYFLT *ar, amp; phs = p->phs; inc = (int32)((*p->xcps * (MYFLT)MAXPHASE) * csound->onedsr); amp = *p->kamp; ar = p->res; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nlasttype) { default: return csound->PerfError(csound, p->h.insdshead, Str("LFO: unknown oscilator type %d"), p->lasttype); case 0: iphs = phs >> 12; fract = (MYFLT)(phs & 0xfff)/FL(4096.0); res = p->sine[iphs]; res = res + (p->sine[iphs+1]-res)*fract; break; case 1: /* Triangular */ res = (MYFLT)((phs<<2)&MAXMASK)/(MYFLT)MAXPHASE; if (phs < MAXPHASE/4) {} else if (phs < MAXPHASE/2) res = FL(1.0) - res; else if (phs < 3*MAXPHASE/4) res = - res; else res = res - FL(1.0); break; case 2: /* Bipole square wave */ if (phsphs = phs; return OK; } /******************************************************************************/ /* triginstr - Ignite instrument events at k-rate from orchestra. */ /* August 1999 by rasmus ekman. */ /* Changes made also to Cs.h, Musmon.c and Insert.c; look for "(re Aug 1999)" */ /******************************************************************************/ /******************************************************************************/ /* triginstr - Ignite instrument events at k-rate from orchestra. */ /* August 1999 by rasmus ekman. */ /******************************************************************************/ static void unquote(char *dst, char *src, int maxsize) { if (src[0] == '"') { int len = (int) strlen(src) - 2; strncpy(dst, src + 1, maxsize-1); if (len >= 0 && dst[len] == '"') dst[len] = '\0'; } else strncpy(dst, src, maxsize); } static int ktriginstr_(CSOUND *csound, TRIGINSTR *p, int stringname); int triginset(CSOUND *csound, TRIGINSTR *p) { p->prvmintim = *p->mintime; p->timrem = 0; /* An instrument is initialised before kcounter is incremented for this k-cycle, and begins playing after kcounter++. Therefore, if we should start something at the very first k-cycle of performance, we must thus do it now, lest it be one k-cycle late. But in ktriginstr() we'll need to use kcounter-1 to set the start time of new events. So add a separate variable for the kcounter offset (-1) */ if (csound->global_kcounter == 0 && *p->trigger != FL(0.0) /*&& *p->args[1] <= FL(0.0)*/) { p->kadjust = 0; /* No kcounter offset at this time */ ktriginstr_(csound, p, 0); } p->kadjust = -1; /* Set kcounter offset for perf-time */ /* Catch p3==0 (i-time only) event triggerings. */ if (csound->global_kcounter > 0 && *p->trigger != FL(0.0) && p->h.insdshead->p3.value == 0) ktriginstr_(csound, p,0); return OK; } int triginset_S(CSOUND *csound, TRIGINSTR *p) { p->prvmintim = *p->mintime; p->timrem = 0; /* An instrument is initialised before kcounter is incremented for this k-cycle, and begins playing after kcounter++. Therefore, if we should start something at the very first k-cycle of performance, we must thus do it now, lest it be one k-cycle late. But in ktriginstr() we'll need to use kcounter-1 to set the start time of new events. So add a separate variable for the kcounter offset (-1) */ if (csound->global_kcounter == 0 && *p->trigger != FL(0.0) /*&& *p->args[1] <= FL(0.0)*/) { p->kadjust = 0; /* No kcounter offset at this time */ ktriginstr_(csound, p, 1); } p->kadjust = -1; /* Set kcounter offset for perf-time */ /* Catch p3==0 (i-time only) event triggerings. */ if (csound->global_kcounter > 0 && *p->trigger != FL(0.0) && p->h.insdshead->p3.value == 0) ktriginstr_(csound, p, 1); return OK; } static int get_absinsno(CSOUND *csound, TRIGINSTR *p, int stringname) { int insno; /* Get absolute instr num */ /* IV - Oct 31 2002: allow string argument for named instruments */ if (stringname) insno = (int)strarg2insno_p(csound, ((STRINGDAT*)p->args[0])->data); else if (csound->ISSTRCOD(*p->args[0])) { char *ss = get_arg_string(csound, *p->args[0]); insno = (int)strarg2insno_p(csound, ss); } else insno = (int)FABS(*p->args[0]); /* Check that instrument is defined */ if (UNLIKELY(insno < 1 || insno > csound->engineState.maxinsno || csound->engineState.instrtxtp[insno] == NULL)) { csound->Warning(csound, Str("schedkwhen ignored. " "Instrument %d undefined\n"), insno); csound->perferrcnt++; return -1; } return insno; } static int ktriginstr_(CSOUND *csound, TRIGINSTR *p, int stringname) { /* k-rate event generator */ long starttime; int i, argnum; EVTBLK evt; char name[512]; memset(&evt, 0, sizeof(EVTBLK)); if (p->timrem > 0) p->timrem--; if (*p->trigger == FL(0.0)) /* Only do something if triggered */ return OK; /* Check if mintime has changed */ if (p->prvmintim != *p->mintime) { int32 timrem = (int32) (*p->mintime * CS_EKR + FL(0.5)); if (timrem > 0) { /* Adjust countdown for new mintime */ p->timrem += timrem - p->prvktim; p->prvktim = timrem; } else p->timrem = 0; p->prvmintim = *p->mintime; } if (*p->args[0] >= FL(0.0) || csound->ISSTRCOD(*p->args[0])) { /* Check for rate limit on event generation */ if (*p->mintime > FL(0.0) && p->timrem > 0) return OK; /* See if there are too many instances already */ if (*p->maxinst >= FL(1.0)) { INSDS *ip; int absinsno, numinst = 0; /* Count active instr instances */ absinsno = get_absinsno(csound, p, stringname); if (UNLIKELY(absinsno < 1)) return NOTOK; ip = &(csound->actanchor); while ((ip = ip->nxtact) != NULL) if (ip->insno == absinsno) numinst++; if (numinst >= (int) *p->maxinst) return OK; } } /* Create the new event */ if (stringname) { evt.p[1] = csound->strarg2insno(csound,((STRINGDAT *)p->args[0])->data, 1); evt.strarg = NULL; evt.scnt = 0; /*evt.strarg = ((STRINGDAT*)p->args[0])->data; evt.p[1] = SSTRCOD;*/ } else if (csound->ISSTRCOD(*p->args[0])) { unquote(name, get_arg_string(csound, *p->args[0]), 512); evt.p[1] = csound->strarg2insno(csound,name, 1); evt.strarg = NULL; /* evt.strarg = name; */ evt.scnt = 0; /* evt.p[1] = SSTRCOD; */ } else { evt.strarg = NULL; evt.scnt = 0; evt.p[1] = *p->args[0]; } evt.opcod = 'i'; evt.pcnt = argnum = p->INOCOUNT - 3; /* Add current time (see note about kadjust in triginset() above) */ starttime = CS_KSMPS*(csound->global_kcounter + p->kadjust); /* Copy all arguments to the new event */ for (i = 1; i < argnum; i++) evt.p[i + 1] = *p->args[i]; /* Set start time from kwhen */ if (UNLIKELY(evt.p[2] < FL(0.0))) { evt.p[2] = FL(0.0); csound->Warning(csound, Str("schedkwhen warning: negative kwhen reset to zero")); } /* Reset min pause counter */ if (*p->mintime > FL(0.0)) p->timrem = (int32) (*p->mintime * CS_EKR + FL(0.5)); else p->timrem = 0; return (insert_score_event_at_sample(csound, &evt, starttime) == 0 ? OK : NOTOK); } int ktriginstr_S(CSOUND *csound, TRIGINSTR *p){ return ktriginstr_(csound,p,1); } int ktriginstr(CSOUND *csound, TRIGINSTR *p){ return ktriginstr_(csound,p,0); } /* Maldonado triggering of events */ int trigseq_set(CSOUND *csound, TRIGSEQ *p) /* by G.Maldonado */ { FUNC *ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->kfn)) == NULL)) { return csound->InitError(csound, Str("trigseq: incorrect table number")); } p->done = 0; p->table = ftp->ftable; p->pfn = (int32)*p->kfn; p->ndx = (int32)*p->initndx; p->nargs = p->INOCOUNT-5; return OK; } int trigseq(CSOUND *csound, TRIGSEQ *p) { if (p->done) return OK; else { int j, nargs = p->nargs; int32 start = (int32) *p->kstart, loop = (int32) *p->kloop; int32 *ndx = &p->ndx; MYFLT **out = p->outargs; if (p->pfn != (int32)*p->kfn) { FUNC *ftp; if (UNLIKELY((ftp = csound->FTFindP(csound, p->kfn)) == NULL)) { return csound->PerfError(csound, p->h.insdshead, Str("trigseq: incorrect table number")); } p->pfn = (int32)*p->kfn; p->table = ftp->ftable; } if (*p->ktrig) { int nn = nargs * (int)*ndx; for (j=0; j < nargs; j++) { *out[j] = p->table[nn+j]; } if (loop > 0) { (*ndx)++; *ndx %= loop; if (*ndx == 0) { if (start == loop) { p->done = 1; /* Was bug here -- JPff 2000 May 28*/ return OK; } *ndx += start; } } else if (loop < 0) { (*ndx)--; while (*ndx < start) { if (start == loop) { p->done = 1; return OK; } *ndx -= loop + start; } } } } return OK; } csound-6.10.0/OOps/sndinfUG.c000066400000000000000000000264701321653344700156530ustar00rootroot00000000000000/* sndinfUG.c: Copyright (C) 1999 matt ingalls, Richard Dobson (C) 2006 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* sndinfUG.c -matt 7/25/99 ugens to retrieve info about a sound file */ #include "csoundCore.h" #include #include "soundio.h" #include "sndinfUG.h" #include "pvfileio.h" #include "convolve.h" static int getsndinfo(CSOUND *csound, SNDINFO *p, SF_INFO *hdr, int strin) { char *sfname, *s, soundiname[1024]; SNDFILE *sf; SF_INFO sfinfo; int csFileType; memset(hdr, 0, sizeof(SF_INFO)); /* leap thru std hoops to get the name */ if (strin) strncpy(soundiname, ((STRINGDAT*)p->ifilno)->data, 1023); else if (csound->ISSTRCOD(*p->ifilno)){ strncpy(soundiname, get_arg_string(csound, *p->ifilno), 1023); } else csound->strarg2name(csound, soundiname, p->ifilno, "soundin.",0); sfname = soundiname; if (strcmp(sfname, "-i") == 0) { /* get info on the -i */ if (UNLIKELY(!csound->oparms->infilename)) { /* commandline inputfile */ return csound->InitError(csound, Str("no infile specified in the commandline")); } sfname = csound->oparms->infilename; } s = csoundFindInputFile(csound, sfname, "SFDIR;SSDIR"); if (s == NULL) { /* open with full dir paths */ s = csoundFindInputFile(csound, sfname, "SADIR"); if (UNLIKELY(s == NULL)) { /* RWD 5:2001 better to exit in this situation ! */ return csound->InitError(csound, Str("diskinfo cannot open %s"), sfname); } } sfname = s; /* & record fullpath filnam */ csFileType = CSFTYPE_UNKNOWN; memset(&sfinfo, 0, sizeof(SF_INFO)); sf = sf_open(sfname, SFM_READ, &sfinfo); if (sf == NULL) { /* open failed: maybe analysis or raw file ? */ if (*(p->irawfiles) == FL(0.0)) { csound->Free(csound, sfname); return 0; } /* check for analysis files */ memset(hdr, 0, sizeof(SF_INFO)); { /* convolve */ FILE *f; CVSTRUCT cvdata; f = fopen(sfname, "rb"); if (f != NULL) { int n = (int)fread(&cvdata, sizeof(CVSTRUCT), 1, f); fclose(f); if (n == 1) { if (cvdata.magic == (int32)CVMAGIC && cvdata.dataFormat == (int32)CVMYFLT && cvdata.Format == (int32)CVRECT) { hdr->frames = (sf_count_t)cvdata.Hlen; hdr->samplerate = (int)(cvdata.samplingRate + FL(0.5)); hdr->channels = (cvdata.channel == (int32)ALLCHNLS ? (int)cvdata.src_chnls : 1); csFileType = CSFTYPE_CVANAL; } } } } if (csFileType == CSFTYPE_UNKNOWN) { /* PVOC */ int fd; PVOCDATA pvdata; WAVEFORMATEX fmt; /* RWD: my prerogative: try pvocex file first! */ fd = csound->PVOC_OpenFile(csound, sfname, &pvdata, &fmt); if (fd >= 0) { hdr->frames = (sf_count_t) (((int32)csound->PVOC_FrameCount(csound, fd) / (int)fmt.nChannels) * (sf_count_t)pvdata.dwOverlap); hdr->samplerate = (int)fmt.nSamplesPerSec; hdr->channels = (int)fmt.nChannels; csound->PVOC_CloseFile(csound, fd); csFileType = CSFTYPE_PVCEX; } } if (csFileType == CSFTYPE_UNKNOWN) { memset(&sfinfo, 0, sizeof(SF_INFO)); sfinfo.samplerate = (int)(csound->esr + FL(0.5)); sfinfo.channels = 1; sfinfo.format = (int)FORMAT2SF(csound->oparms->outformat) | (int)TYPE2SF(TYP_RAW); /* try again */ sf = sf_open(sfname, SFM_READ, &sfinfo); } } if (UNLIKELY(sf == NULL && csFileType == CSFTYPE_UNKNOWN)) { return csound->InitError(csound, Str("diskinfo cannot open %s"), sfname); } if (sf != NULL) { csFileType = sftype2csfiletype(sfinfo.format); memcpy(hdr, &sfinfo, sizeof(SF_INFO)); sf_close(sf); } /* FIXME: PVOC_OpenFile has already notified since it calls FileOpen2(), even if the file was not a PVOC file. */ if (csFileType != CSFTYPE_PVCEX) csoundNotifyFileOpened(csound, sfname, csFileType, 0, 0); csound->Free(csound, sfname); return 1; } int filelen(CSOUND *csound, SNDINFO *p) { SF_INFO hdr; if (getsndinfo(csound, p, &hdr, 0)) *(p->r1) = (MYFLT)((int32)hdr.frames) / (MYFLT)hdr.samplerate; else *(p->r1) = FL(0.0); return OK; } int filelen_S(CSOUND *csound, SNDINFO *p) { SF_INFO hdr; if (getsndinfo(csound, p, &hdr, 1)) *(p->r1) = (MYFLT)((int32)hdr.frames) / (MYFLT)hdr.samplerate; else *(p->r1) = FL(0.0); return OK; } int filenchnls_S(CSOUND *csound, SNDINFO *p) { SF_INFO hdr; getsndinfo(csound, p, &hdr, 1); *(p->r1) = (MYFLT)hdr.channels; return OK; } int filesr_S(CSOUND *csound, SNDINFO *p) { SF_INFO hdr; getsndinfo(csound, p, &hdr, 1); *(p->r1) = (MYFLT)hdr.samplerate; return OK; } int filebit_S(CSOUND *csound, SNDINFO *p) { SF_INFO hdr; int bits, format; getsndinfo(csound, p, &hdr, 1); format = hdr.format & SF_FORMAT_SUBMASK; if (format < 5) bits = format*8 ; else if (format == 5) bits = 8; else if (format == 6) bits = -1; else if (format == 7) bits = -2; else bits = -format; /* non-PCM data */ *(p->r1) = (MYFLT) bits; return OK; } int filenchnls(CSOUND *csound, SNDINFO *p) { SF_INFO hdr; getsndinfo(csound, p, &hdr, 0); *(p->r1) = (MYFLT)hdr.channels; return OK; } int filesr(CSOUND *csound, SNDINFO *p) { SF_INFO hdr; getsndinfo(csound, p, &hdr, 0); *(p->r1) = (MYFLT)hdr.samplerate; return OK; } int filebit(CSOUND *csound, SNDINFO *p) { SF_INFO hdr; int bits, format; getsndinfo(csound, p, &hdr, 0); format = hdr.format & SF_FORMAT_SUBMASK; if (format < 5) bits = format*8 ; else if (format == 5) bits = 8; else if (format == 6) bits = -1; else if (format == 7) bits = -2; else bits = -format; /* non-PCM data */ *(p->r1) = (MYFLT) bits; return OK; } /* RWD 8:2001: now supports all relevant files, */ /* and scans overall peak properly */ int filepeak_(CSOUND *csound, SNDINFOPEAK *p, char *soundiname) { int channel = (int)(*p->channel + FL(0.5)); char *sfname; void *fd; SNDFILE *sf; double peakVal = -1.0; int fmt, typ; SF_INFO sfinfo; sfname = soundiname; if (strcmp(sfname, "-i") == 0) { /* get info on the -i */ sfname = csound->oparms->infilename; /* commandline inputfile */ if (UNLIKELY(sfname == NULL)) return csound->InitError(csound, Str("no infile specified in the commandline")); } memset(&sfinfo, 0, sizeof(SF_INFO)); /* open with full dir paths */ fd = csound->FileOpen2(csound, &sf, CSFILE_SND_R, sfname, &sfinfo, "SFDIR;SSDIR", CSFTYPE_UNKNOWN_AUDIO, 0); if (UNLIKELY(fd == NULL)) { /* RWD 5:2001 better to exit in this situation ! */ return csound->InitError(csound, Str("diskinfo cannot open %s"), sfname); } if (channel <= 0) { if (sf_command(sf, SFC_GET_SIGNAL_MAX, &peakVal, sizeof(double)) == SF_FALSE) { csound->Warning(csound, Str("%s: no PEAK chunk was found, scanning " "file for maximum amplitude"), sfname); if (sf_command(sf, SFC_CALC_NORM_SIGNAL_MAX, &peakVal, sizeof(double)) != 0) peakVal = -1.0; } } else { double *peaks; size_t nBytes; if (UNLIKELY(channel > sfinfo.channels)) return csound->InitError(csound, Str("Input channel for peak exceeds number " "of channels in file")); nBytes = sizeof(double)* sfinfo.channels; peaks = (double*)csound->Malloc(csound, nBytes); if (sf_command(sf, SFC_GET_MAX_ALL_CHANNELS, peaks, nBytes) == SF_FALSE) { csound->Warning(csound, Str("%s: no PEAK chunk was found, scanning " "file for maximum amplitude"), sfname); if (sf_command(sf, SFC_CALC_NORM_MAX_ALL_CHANNELS, peaks, nBytes) == 0) peakVal = peaks[channel - 1]; } csound->Free(csound, peaks); } if (UNLIKELY(peakVal < 0.0)) return csound->InitError(csound, Str("filepeak: error getting peak value")); /* scale output consistently with soundin opcode (see diskin2.c) */ fmt = sfinfo.format & SF_FORMAT_SUBMASK; typ = sfinfo.format & SF_FORMAT_TYPEMASK; if ((fmt != SF_FORMAT_FLOAT && fmt != SF_FORMAT_DOUBLE) || (typ == SF_FORMAT_WAV || typ == SF_FORMAT_W64 || typ == SF_FORMAT_AIFF)) *p->r1 = (MYFLT)(peakVal * (double)csound->e0dbfs); else *p->r1 = (MYFLT)peakVal; csound->FileClose(csound, fd); return OK; } int filepeak(CSOUND *csound, SNDINFOPEAK *p){ char soundiname[1024]; if (csound->ISSTRCOD(*p->ifilno)){ strncpy(soundiname, get_arg_string(csound, *p->ifilno), 1023); } else csound->strarg2name(csound, soundiname, p->ifilno, "soundin.", 0); return filepeak_(csound, p, soundiname); } int filepeak_S(CSOUND *csound, SNDINFOPEAK *p){ char soundiname[1024]; strncpy(soundiname, ((STRINGDAT*)p->ifilno)->data, 1023); return filepeak_(csound, p, soundiname); } /* From matt ingalls */ int filevalid(CSOUND *csound, FILEVALID *p) { char soundiname[1024]; /* There is no check on this length */ *p->r1 = 0; if (csound->ISSTRCOD(*p->ifilno)){ strncpy(soundiname, get_arg_string(csound, *p->ifilno), 1023); } else csound->strarg2name(csound, soundiname, p->ifilno, "soundin.", 0); if (UNLIKELY(strcmp(soundiname, "-i") == 0)) { /* get info on the -i */ if (csound->oparms->infilename) /* commandline inputfile */ *p->r1 = 1; return OK; } if (LIKELY(csound->FindInputFile(csound, soundiname, "SFDIR;SSDIR"))) *p->r1 = 1; return OK; } int filevalid_S(CSOUND *csound, FILEVALID *p) { char soundiname[1024]; /* There is no check on this length */ *p->r1 = 0; strncpy(soundiname, ((STRINGDAT*)p->ifilno)->data, 1023); if (UNLIKELY(strcmp(soundiname, "-i") == 0)) { /* get info on the -i */ if (csound->oparms->infilename) /* commandline inputfile */ *p->r1 = 1; return OK; } if (LIKELY(csound->FindInputFile(csound, soundiname, "SFDIR;SSDIR"))) *p->r1 = 1; return OK; } csound-6.10.0/OOps/str_ops.c000066400000000000000000001022661321653344700156250ustar00rootroot00000000000000/* str_ops.c: Copyright (C) 2005, 2006 Istvan Varga (C) 2005 Matt J. Ingalls, John ffitch (C) 2013 V Lazzarini (new string code) This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #define CSOUND_STR_OPS_C 1 #include "str_ops.h" #include #ifdef HAVE_CURL #include #include "corfile.h" #endif #define STRSMAX 8 #ifndef HAVE_SNPRINTF /* add any compiler/system that has snprintf() */ #if defined(HAVE_C99) #define HAVE_SNPRINTF 1 #endif #endif int s_opcode(CSOUND *csound, STRGET_OP *p){ if (p->r->data == NULL){ p->r->data = (char *) csound->Malloc(csound, 15); p->r->size = 15; } else if (p->r->size < 15){ p->r->data = (char *) csound->ReAlloc(csound, p->r->data, 15); p->r->size = 15; } snprintf(p->r->data, p->r->size, "%f", *p->indx); return OK; } int s_opcode_k(CSOUND *csound, STRGET_OP *p){ IGN(csound); snprintf(p->r->data, p->r->size, "%f", *p->indx); return OK; } /* strset by John ffitch */ static void str_set(CSOUND *csound, int ndx, const char *s) { if (csound->strsets == NULL) { csound->strsmax = STRSMAX; csound->strsets = (char **) csound->Calloc(csound, (csound->strsmax + 1) * sizeof(char*)); } if (ndx > (int) csound->strsmax) { int i, newmax; /* assumes power of two STRSMAX */ newmax = (ndx | (STRSMAX - 1)) + 1; csound->strsets = (char**) csound->ReAlloc(csound, csound->strsets, (newmax + 1) * sizeof(char*)); for (i = (csound->strsmax + 1); i <= newmax; i++) csound->strsets[i] = NULL; csound->strsmax = newmax; } if (UNLIKELY(ndx < 0)) { /* -ve index */ csound->InitError(csound, Str("illegal strset index")); return; } if (csound->strsets[ndx] != NULL) { if (strcmp(s, csound->strsets[ndx]) == 0) return; if (csound->oparms->msglevel & WARNMSG) { csound->Warning(csound, Str("strset index conflict at %d"), ndx); csound->Warning(csound, Str("previous value: '%s', replaced with '%s'"), csound->strsets[ndx], s); } csound->Free(csound, csound->strsets[ndx]); } csound->strsets[ndx] = (char*) csound->Malloc(csound, strlen(s) + 1); strcpy(csound->strsets[ndx], s); if ((csound->oparms->msglevel & 7) == 7) csound->Message(csound, "Strsets[%d]: '%s'\n", ndx, s); } int strset_init(CSOUND *csound, STRSET_OP *p) { str_set(csound, (int) MYFLT2LRND(*p->indx), p->str->data); return OK; } /* for argdecode.c */ void strset_option(CSOUND *csound, char *s) { int indx = 0; if (UNLIKELY(!isdigit(*s))) { csound->Warning(csound, Str("--strset: invalid format")); return; } do { indx = (indx * 10) + (int) (*s++ - '0'); } while (isdigit(*s)); if (UNLIKELY(*s++ != '=')){ csound->Warning(csound, Str("--strset: invalid format")); return; } str_set(csound, indx, s); } int strget_init(CSOUND *csound, STRGET_OP *p) { int indx; if (csound->ISSTRCOD(*(p->indx))) { char *ss = csound->currevent->strarg; if (ss == NULL) return OK; ss = get_arg_string(csound, *p->indx); if (p->r->data == NULL) { p->r->data = cs_strdup(csound, ss); p->r->size = strlen(ss)+1; } else if ((int) strlen(ss) >= p->r->size) { csound->Free(csound, p->r->data); p->r->data = cs_strdup(csound, ss); p->r->size = strlen(ss) + 1; } else { p->r->size = strlen(ss) + 1; strncpy(p->r->data, ss, strlen(ss)); p->r->data[p->r->size - 1] = '\0'; } return OK; } indx = (int)((double)*(p->indx) + (*(p->indx) >= FL(0.0) ? 0.5 : -0.5)); if (indx < 0 || indx > (int) csound->strsmax || csound->strsets == NULL || csound->strsets[indx] == NULL) return OK; if (UNLIKELY((int) strlen(csound->strsets[indx]) >= p->r->size)){ int size = strlen(csound->strsets[indx]); p->r->data = csound->ReAlloc(csound, p->r->data, size + 1); p->r->size = size + 1; } strcpy((char*) p->r->data, csound->strsets[indx]); return OK; } static CS_NOINLINE int StrOp_ErrMsg(void *p, const char *msg) { CSOUND *csound = ((OPDS*) p)->insdshead->csound; const char *opname = csound->GetOpcodeName(p); if (UNLIKELY(csound->ids != NULL && csound->ids->insdshead == csound->curip)) return csound->InitError(csound, "%s: %s", opname, Str(msg)); else if (UNLIKELY(((OPDS*) p)->insdshead->pds != NULL)) return csound->PerfError(csound, ((OPDS*)p)->insdshead, "%s: %s", opname, Str(msg)); else csound->Warning(csound, "%s: %s", opname, Str(msg)); return NOTOK; } /* strcpy */ int strcpy_opcode_S(CSOUND *csound, STRCPY_OP *p) { char *newVal = p->str->data; if (p->r->data == NULL) { p->r->data = cs_strdup(csound, newVal); p->r->size = strlen(p->str->data) + 1; //printf("NULL str:%p %p \n", p->r, p->r->data); return OK; } if (p->r->data == p->str->data){ //printf("sameptr str:%p %p \n", p->r->data); return OK; } if (UNLIKELY((int) strlen(newVal) >= p->r->size)){ csound->Free(csound, p->r->data); p->r->data = cs_strdup(csound, newVal); p->r->size = strlen(newVal) + 1; //printf("dup str:%p %p \n", p->r, p->r->data); } else { strcpy((char*) p->r->data, newVal); p->r->size = strlen(newVal) + 1; //printf("str:%p %p \n", p->r, p->r->data); } return OK; } int strassign_opcode_S(CSOUND *csound, STRCPY_OP *p) { IGN(csound); p->r->data = p->str->data; p->r->size = p->str->size; return OK; } int strassign_opcode_Sk(CSOUND *csound, STRCPY_OP *p) { IGN(csound); if (strcmp(p->r->data, p->str->data)!=0){ p->r->data = p->str->data; p->r->size = p->str->size; } //csound->Message(csound, p->r->data); return OK; } int str_changed(CSOUND *csound, STRCHGD *p) { if (p->mem == NULL) { csound->Free(csound, p->mem); p->mem = cs_strdup(csound, p->str->data); } *p->r = 0; return OK; } int str_changed_k(CSOUND *csound, STRCHGD *p) { if (p->str->data && ( p->mem == NULL || strcmp(p->str->data, p->mem)!=0)) { csound->Free(csound, p->mem); p->mem = cs_strdup(csound, p->str->data); *p->r = 1; } else *p->r = 0; return OK; } extern char* get_strarg(CSOUND *csound, MYFLT p, char *strarg); int strcpy_opcode_p(CSOUND *csound, STRGET_OP *p) { if (csound->ISSTRCOD(*p->indx)) { char *ss; ss = get_arg_string(csound, *p->indx); if (ss == NULL){ if (UNLIKELY(((OPDS*) p)->insdshead->pds != NULL)) return csoundPerfError(csound, ((OPDS*)p)->insdshead, Str("NULL string \n")); else return csoundInitError(csound, Str("NULL string \n")); } if (p->r->data == NULL) { p->r->data = cs_strdup(csound, ss); p->r->size = strlen(ss)+1; } else if ((int) strlen(ss) >= p->r->size) { csound->Free(csound, p->r->data); p->r->data = cs_strdup(csound, ss); p->r->size = strlen(ss) + 1; } else { strcpy(p->r->data,ss); p->r->size = strlen(ss) + 1; } } else { p->r->data = csound->strarg2name(csound, NULL, p->indx, "soundin.", 0); p->r->size = strlen(p->r->data) + 1; } return OK; } /* strcat */ int strcat_opcode(CSOUND *csound, STRCAT_OP *p) { int size; char *str1 = cs_strdup(csound, p->str1->data), *str2 = cs_strdup(csound, p->str2->data); if (str1 == NULL || str2 == NULL){ csound->Free(csound,str1); csound->Free(csound,str2); if (UNLIKELY(((OPDS*) p)->insdshead->pds != NULL)) return csoundPerfError(csound, ((OPDS*)p)->insdshead, "NULL string \n"); else return csoundInitError(csound, "NULL string \n"); } size = strlen(str1) + strlen(str2); if (p->r->data == NULL) { p->r->data = csound->Calloc(csound, size+1); p->r->size = size+1; } else if (UNLIKELY((int) size >= p->r->size)) { char *nstr = csound->ReAlloc(csound, p->r->data, size + 1); if (p->r->data == p->str1->data){ p->str1->data = nstr; p->str1->size = size + 1; } if (p->r->data == p->str2->data){ p->str2->data = nstr; p->str2->size = size + 1; } p->r->data = nstr; p->r->size = size + 1; } strncpy((char*) p->r->data, str1, p->r->size-1); strcat((char*) p->r->data, str2); csound->Free(csound, str2); /* not needed anymore */ csound->Free(csound, str1); return OK; } /* strcmp */ int strcmp_opcode(CSOUND *csound, STRCMP_OP *p) { int i; if (p->str1->data == NULL || p->str2->data == NULL){ if (UNLIKELY(((OPDS*) p)->insdshead->pds != NULL)) return csoundPerfError(csound, ((OPDS*)p)->insdshead, "NULL string \n"); else return csoundInitError(csound, "NULL string \n"); } *(p->r) = FL(0.0); if (p->str1 == p->str2) return OK; i = strcmp((char*) p->str1->data, (char*) p->str2->data); if (i < 0) *(p->r) = FL(-1.0); else if (i > 0) *(p->r) = FL(1.0); return OK; } /* perform a sprintf-style format -- based on code by Matt J. Ingalls */ static CS_NOINLINE int sprintf_opcode_(CSOUND *csound, void *p, /* opcode data structure pointer */ STRINGDAT *str, /* pointer to space for output string */ const char *fmt, /* format string */ MYFLT **kvals, /* array of argument pointers */ int numVals, /* number of arguments */ int strCode) /* bit mask for string arguments */ { int len = 0; char *strseg, *outstring = str->data; MYFLT *parm = NULL; int i = 0, j = 0, n; const char *segwaiting = NULL; int maxChars, siz = strlen(fmt) + numVals*7 + 1; for (i = 0; i < numVals; i++) { if (UNLIKELY(IS_ASIG_ARG(kvals[i]))) { return StrOp_ErrMsg(p, Str("a-rate argument not allowed")); } } if (UNLIKELY((int) ((OPDS*) p)->optext->t.inArgCount > 31)){ StrOp_ErrMsg(p, Str("too many arguments")); return NOTOK; } strseg = csound->Malloc(csound, siz); i = 0; while (1) { if (UNLIKELY(i >= siz)) { // return StrOp_ErrMsg(p, "format string too long"); siz *= 2; strseg = csound->ReAlloc(csound, strseg, siz); } if (*fmt != '%' && *fmt != '\0') { strseg[i++] = *fmt++; continue; } if (fmt[0] == '%' && fmt[1] == '%') { strseg[i++] = *fmt++; /* Odd code: %% is usually % and as we know the value of *fmt the loads are unnecessary */ strseg[i++] = *fmt++; continue; } /* if already a segment waiting, then lets print it */ if (segwaiting != NULL) { maxChars = str->size - len; strseg[i] = '\0'; if (UNLIKELY(numVals <= 0)) { csound->Free(csound, strseg); return StrOp_ErrMsg(p, Str("insufficient arguments for format")); } numVals--; /* if (UNLIKELY((*segwaiting == 's' && !(strCode & 1)) || */ /* (*segwaiting != 's' && (strCode & 1)))) { */ /* return StrOp_ErrMsg(p, "argument type inconsistent with format"); */ /* } */ strCode >>= 1; parm = kvals[j++]; switch (*segwaiting) { case 'd': case 'i': case 'o': case 'x': case 'X': case 'u': case 'c': #ifdef HAVE_SNPRINTF if ((int)strlen(strseg) + 24 > (int)maxChars) { int offs = outstring - str->data; str->data = csound->ReAlloc(csound, str->data, str->size + 24); if(str->data == NULL) { return StrOp_ErrMsg(p, Str("memory allocation failure")); } str->size += 24; maxChars += 24; outstring = str->data + offs; //printf("maxchars = %d %s\n", maxChars, strseg); //printf("size: %d \n",str->size); } n = snprintf(outstring, maxChars, strseg, (int) MYFLT2LRND(*parm)); #else n = sprintf(outstring, strseg, (int) MYFLT2LRND(*parm)); #endif break; case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': #ifdef HAVE_SNPRINTF //printf("%d %d \n", str->size, strlen(str->data)); if (strlen(strseg) + 24 > (unsigned)maxChars) { int offs = outstring - str->data; str->data = csound->ReAlloc(csound, str->data, str->size + 13); if(str->data == NULL) { return StrOp_ErrMsg(p, Str("memory allocation failure")); } str->size += 24; maxChars += 24; outstring = str->data + offs; //printf("maxchars = %d %s\n", maxChars, strseg); } //printf("%d %d \n", str->size, strlen(str->data)); n = snprintf(outstring, maxChars, strseg, (double)*parm); #else n = sprintf(outstring, strseg, (double)*parm); #endif break; case 's': if (((STRINGDAT*)parm)->data == str->data) { csound->Free(csound, strseg); return StrOp_ErrMsg(p, Str("output argument may not be " "the same as any of the input args")); } if ((((STRINGDAT*)parm)->size+strlen(strseg)) >= (unsigned)maxChars) { int offs = outstring - str->data; str->data = csound->ReAlloc(csound, str->data, str->size + ((STRINGDAT*)parm)->size + strlen(strseg)); if(str->data == NULL){ return StrOp_ErrMsg(p, Str("memory allocation failure")); } str->size += ((STRINGDAT*)parm)->size + strlen(strseg); maxChars += ((STRINGDAT*)parm)->size + strlen(strseg); outstring = str->data + offs; } n = snprintf(outstring, maxChars, strseg, ((STRINGDAT*)parm)->data); break; default: csound->Free(csound, strseg); return StrOp_ErrMsg(p, Str("invalid format string")); } if (n < 0 || n >= maxChars) { /* safely detected excess string length */ int offs = outstring - str->data; str->data = csound->ReAlloc(csound, str->data, maxChars*2); if (str->data == NULL) { return StrOp_ErrMsg(p, Str("memory allocation failure")); } outstring = str->data + offs; str->size = maxChars*2; // VL: Coverity says this is unused. (which is true) // maxChars += str->size; } outstring += n; len += n; i = 0; } if (*fmt == '\0') break; /* copy the '%' */ strseg[i++] = *fmt++; /* find the format code */ segwaiting = fmt; while (!isalpha(*segwaiting) && *segwaiting != '\0') segwaiting++; } if (UNLIKELY(numVals > 0)) { csound->Free(csound, strseg); return StrOp_ErrMsg(p, Str("too many arguments for format")); } csound->Free(csound, strseg); return OK; } int sprintf_opcode(CSOUND *csound, SPRINTF_OP *p) { int size = p->sfmt->size+ 18*((int) p->INOCOUNT); //printf("%d %d \n", p->r->size, strlen(p->r->data)); if (p->r->data == NULL || p->r->size < size) { /* this 10 is 1n incorrect guess which is OK with numbers*/ p->r->data = csound->Calloc(csound, size); p->r->size = size; } if (UNLIKELY(sprintf_opcode_(csound, p, p->r, (char*) p->sfmt->data, &(p->args[0]), (int) p->INOCOUNT - 1,0) == NOTOK)) { ((char*) p->r->data)[0] = '\0'; return NOTOK; } return OK; } static CS_NOINLINE int printf_opcode_(CSOUND *csound, PRINTF_OP *p) { STRINGDAT buf; int err; buf.size = /*strlen(p->sfmt->data) +*/ 3072; buf.data = csound->Calloc(csound, buf.size); err = sprintf_opcode_(csound, p, &buf, (char*) p->sfmt->data, &(p->args[0]), (int) p->INOCOUNT - 2,0); if (LIKELY(err == OK)) csound->MessageS(csound, CSOUNDMSG_ORCH, "%s", buf.data); csound->Free(csound, buf.data); return err; } int printf_opcode_init(CSOUND *csound, PRINTF_OP *p) { if (*p->ktrig > FL(0.0)) return (printf_opcode_(csound, p)); return OK; } int printf_opcode_set(CSOUND *csound, PRINTF_OP *p) { (void) csound; p->prv_ktrig = FL(0.0); return OK; } int printf_opcode_perf(CSOUND *csound, PRINTF_OP *p) { if (*p->ktrig == p->prv_ktrig) return OK; p->prv_ktrig = *p->ktrig; if (p->prv_ktrig > FL(0.0)) return (printf_opcode_(csound, p)); return OK; } int puts_opcode_init(CSOUND *csound, PUTS_OP *p) { p->noNewLine = (*p->no_newline == FL(0.0) ? 0 : 1); if (*p->ktrig > FL(0.0)) { if (!p->noNewLine) csound->MessageS(csound, CSOUNDMSG_ORCH, "%s\n", (char*) p->str->data); else csound->MessageS(csound, CSOUNDMSG_ORCH, "%s", (char*) p->str->data); } p->prv_ktrig = *p->ktrig; return OK; } int puts_opcode_perf(CSOUND *csound, PUTS_OP *p) { if (*p->ktrig != p->prv_ktrig && *p->ktrig > FL(0.0)) { p->prv_ktrig = *p->ktrig; if (!p->noNewLine) csound->MessageS(csound, CSOUNDMSG_ORCH, "%s\n", (char*) p->str->data); else csound->MessageS(csound, CSOUNDMSG_ORCH, "%s", (char*) p->str->data); } return OK; } int strtod_opcode_p(CSOUND *csound, STRTOD_OP *p) { char *s = NULL, *tmp; double x; if (csound->ISSTRCOD(*p->str)) s = get_arg_string(csound, *p->str); else { int ndx = (int) MYFLT2LRND(*p->str); if (ndx >= 0 && ndx <= (int) csound->strsmax && csound->strsets != NULL) s = csound->strsets[ndx]; } if (UNLIKELY(s == NULL)) return StrOp_ErrMsg(p, Str("empty string")); while (isblank(*s)) s++; if (UNLIKELY(*s == '\0')) return StrOp_ErrMsg(p, Str("empty string")); x = cs_strtod(s, &tmp); if (UNLIKELY(*tmp != '\0')) return StrOp_ErrMsg(p, Str("invalid format")); *p->indx = (MYFLT) x; return OK; } int strtod_opcode_S(CSOUND *csound, STRSET_OP *p) { IGN(csound); char *s = NULL, *tmp; double x; s = (char*) p->str->data; while (isblank(*s)) s++; if (UNLIKELY(*s == '\0')) return StrOp_ErrMsg(p, Str("empty string")); x = cs_strtod(s, &tmp); if (UNLIKELY(*tmp != '\0')) return StrOp_ErrMsg(p, Str("invalid format")); *p->indx = (MYFLT) x; return OK; } int strtol_opcode_S(CSOUND *csound, STRSET_OP *p) { IGN(csound); char *s = NULL; int sgn = 0, radix = 10; int32 x = 0L; s = (char*) p->str->data; while (isblank(*s)) s++; if (UNLIKELY(*s == '\0')) return StrOp_ErrMsg(p, Str("empty string")); if (*s == '+') s++; else if (*s == '-') sgn++, s++; if (*s == '0') { if (s[1] == 'x' || s[1] == 'X') radix = 16, s += 2; else if (s[1] != '\0') radix = 8, s++; else { *p->indx = FL(0.0); return OK; } } if (UNLIKELY(*s == '\0')) return StrOp_ErrMsg(p, Str("invalid format")); switch (radix) { case 8: while (*s >= '0' && *s <= '7') x = (x * 8L) + (int32) (*s++ - '0'); break; case 10: while (isdigit(*s)) x = (x * 10L) + (int32) (*s++ - '0'); break; default: while (1) { if (isdigit(*s)) x = (x * 16L) + (int32) (*s++ - '0'); else if (*s >= 'A' && *s <= 'F') x = (x * 16L) + (int32) (*s++ - 'A') + 10L; else if (*s >= 'a' && *s <= 'f') x = (x * 16L) + (int32) (*s++ - 'a') + 10L; else break; } } if (UNLIKELY(*s != '\0')) return StrOp_ErrMsg(p, Str("invalid format")); if (sgn) x = -x; *p->indx = (MYFLT) x; return OK; } int strtol_opcode_p(CSOUND *csound, STRTOD_OP *p) { char *s = NULL; int sgn = 0, radix = 10; int32 x = 0L; if (csound->ISSTRCOD(*p->str)) s = get_arg_string(csound, *p->str); else { int ndx = (int) MYFLT2LRND(*p->str); if (ndx >= 0 && ndx <= (int) csound->strsmax && csound->strsets != NULL) s = csound->strsets[ndx]; } if (UNLIKELY(s == NULL)) return StrOp_ErrMsg(p, Str("empty string")); while (isblank(*s)) s++; if (UNLIKELY(*s == '\0')) return StrOp_ErrMsg(p, Str("empty string")); if (*s == '+') s++; else if (*s == '-') sgn++, s++; if (*s == '0') { if (s[1] == 'x' || s[1] == 'X') radix = 16, s += 2; else if (s[1] != '\0') radix = 8, s++; else { *p->indx = FL(0.0); return OK; } } if (UNLIKELY(*s == '\0')) return StrOp_ErrMsg(p, Str("invalid format")); switch (radix) { case 8: while (*s >= '0' && *s <= '7') x = (x * 8L) + (int32) (*s++ - '0'); break; case 10: while (isdigit(*s)) x = (x * 10L) + (int32) (*s++ - '0'); break; default: while (1) { if (isdigit(*s)) x = (x * 16L) + (int32) (*s++ - '0'); else if (*s >= 'A' && *s <= 'F') x = (x * 16L) + (int32) (*s++ - 'A') + 10L; else if (*s >= 'a' && *s <= 'f') x = (x * 16L) + (int32) (*s++ - 'a') + 10L; else break; } } if (UNLIKELY(*s != '\0')) return StrOp_ErrMsg(p, Str("invalid format")); if (sgn) x = -x; *p->indx = (MYFLT) x; return OK; } /** * Sdst strsub Ssrc[, istart[, iend]] * Sdst strsubk Ssrc, kstart, kend * * Extract a part of Ssrc, from istart to iend; if istart or iend is * less than 0, or greater than the length of the source string, it is * interpreted as the end of the source string. istart > iend will * reverse the string. The default parameters are istart = 0, iend = -1. */ int strsub_opcode(CSOUND *csound, STRSUB_OP *p) { const char *src; char *dst; int i, len, strt, end, rev = 0; if (p->Ssrc->data == NULL) return NOTOK; if (p->Sdst->data == NULL || p->Sdst->size < p->Ssrc->size) { int size = p->Ssrc->size; if (p->Sdst->data != NULL) csound->Free(csound, p->Sdst->data); p->Sdst->data = csound->Calloc(csound, size); p->Sdst->size = size; } src = (char*) p->Ssrc->data; dst = (char*) p->Sdst->data; len = (int) strlen(src); #if defined(MSVC) || (defined(__GNUC__) && defined(__i386__)) strt = (int) MYFLT2LRND(*(p->istart)); end = (int) MYFLT2LRND(*(p->iend)); #else strt = (int) (*(p->istart) + FL(1.5)) - 1; end = (int) (*(p->iend) + FL(1.5)) - 1; #endif if (strt < 0 || strt > len) strt = len; if (end < 0 || end > len) end = len; if (strt == end) { /* trivial case: empty output */ dst[0] = '\0'; return OK; } if (strt > end) { int tmp = strt; /* reverse output */ strt = end; end = tmp; rev = 1; } src += strt; len = end - strt; if (UNLIKELY(len >= p->Sdst->size)) { p->Sdst->data = csound->ReAlloc(csound, p->Sdst->data, len+1); p->Sdst->size = len+1; dst = (char*) p->Sdst->data; } i = 0; if (!rev || p->Sdst->data == p->Ssrc->data) { /* copying in forward direction is safe */ /* even if Ssrc and Sdst are the same */ do { dst[i] = src[i]; } while (++i < len); dst[i] = '\0'; if (rev) { int j; /* if the destination string variable is the same as the source, */ /* reversing needs to be handled in a special way */ i = 0; j = len - 1; while (i < j) { char tmp = dst[i]; dst[i++] = dst[j]; dst[j--] = tmp; } } } else { /* reverse string out of place (Ssrc and Sdst are not the same) */ int j = len; do { dst[i] = src[--j]; } while (++i < len); dst[i] = '\0'; } return OK; } /** * ichr strchar Sstr[, ipos] * kchr strchark Sstr[, kpos] * * Return the ASCII code of the character in Sstr at ipos (defaults to 0). * If ipos is out of range, 0 is returned. */ int strchar_opcode(CSOUND *csound, STRCHAR_OP *p) { int len = (int) strlen((char*) p->Ssrc->data); #if defined(MSVC) || (defined(__GNUC__) && defined(__i386__)) int pos = (int) MYFLT2LRND(*(p->ipos)); #else int pos = (int) (*(p->ipos) + FL(1.5)) - 1; #endif (void) csound; if (pos < 0 || pos >= len) *(p->ichr) = FL(0.0); else *(p->ichr) = (MYFLT) ((int) ((unsigned char) ((char*) p->Ssrc->data)[pos])); return OK; } /** * ilen strlen Sstr * klen strlenk Sstr * * Return the length of a string. */ int strlen_opcode(CSOUND *csound, STRLEN_OP *p) { (void) csound; if (p->Ssrc->size) *(p->ilen) = (MYFLT) strlen(p->Ssrc->data); else *(p->ilen) = FL(0.0); return OK; } /** * Sdst strupper Ssrc * Sdst strupperk Ssrc * Sdst strlower Ssrc * Sdst strlowerk Ssrc * * Convert a string to upper or lower case. */ int strupper_opcode(CSOUND *csound, STRUPPER_OP *p) { const char *src; char *dst; int i; if (p->Ssrc->data == NULL) return NOTOK; if (p->Sdst->data == NULL || p->Sdst->size < p->Ssrc->size) { int size = p->Ssrc->size; if (p->Sdst->data != NULL) csound->Free(csound, p->Sdst->data); p->Sdst->data = csound->Calloc(csound, size); p->Sdst->size = size; } (void) csound; src = (char*) p->Ssrc->data; dst = (char*) p->Sdst->data; for (i = 0; src[i] != '\0'; i++) { unsigned char tmp; tmp = (unsigned char) src[i]; dst[i] = (char) (islower(tmp) ? (unsigned char) toupper(tmp) : tmp); } return OK; } int strlower_opcode(CSOUND *csound, STRUPPER_OP *p) { const char *src; char *dst; int i; if (p->Ssrc->data == NULL) return NOTOK; if (p->Sdst->data == NULL || p->Sdst->size < p->Ssrc->size) { int size = p->Ssrc->size; if (p->Sdst->data != NULL) csound->Free(csound,p->Sdst->data); p->Sdst->data = csound->Calloc(csound, size); p->Sdst->size = size; } (void) csound; src = (char*) p->Ssrc->data; dst = (char*) p->Sdst->data; for (i = 0; src[i] != '\0'; i++) { unsigned char tmp; tmp = (unsigned char) src[i]; dst[i] = (char) (isupper(tmp) ? (unsigned char) tolower(tmp) : tmp); } return OK; } /** * Sval getcfg iopt * * Returns the value of a global setting (e.g. input file name) as a * string. */ int getcfg_opcode(CSOUND *csound, GETCFG_OP *p) { const char *s; #if defined(MSVC) || (defined(__GNUC__) && defined(__i386__)) int opt = (int) MYFLT2LRND(*(p->iopt)); #else int opt = (int) (*(p->iopt) + FL(0.5)); #endif char buf[32]; if (p->Sdst->size < 32){ csound->Free(csound, p->Sdst->data); p->Sdst->data = csound->Calloc(csound,32); p->Sdst->size = 32; } //((char*) p->Sdst->data)[0] = '\0'; buf[0] = '\0'; s = &(buf[0]); switch (opt) { case 1: /* maximum length of variable */ snprintf(&(buf[0]), 32, "%d", (int) p->Sdst->size - 1); break; case 2: /* input sound file name */ s = (csound->oparms->sfread && !csound->initonly ? csound->oparms->infilename : (char*) NULL); break; case 3: /* output sound file name */ s = (csound->oparms->sfwrite && !csound->initonly ? csound->oparms->outfilename : (char*) NULL); break; case 4: /* is real-time audio being used ? (0: no, 1: yes) */ buf[0] = '0'; buf[1] = '\0'; if ((csound->oparms->sfread && !csound->initonly && check_rtaudio_name(csound->oparms->infilename, NULL, 0) >= 0) || (csound->oparms->sfwrite && !csound->initonly && check_rtaudio_name(csound->oparms->outfilename, NULL, 1) >= 0)) buf[0] = '1'; break; case 5: /* is beat mode being used ? (0: no, 1: yes) */ buf[0] = (csound->oparms->Beatmode ? '1' : '0'); buf[1] = '\0'; break; case 6: /* host OS name */ #ifdef LINUX s = "Linux"; #elif defined(WIN32) s = "Win32"; #elif defined(MACOSX) s = "MacOSX"; #else s = "unknown"; #endif break; case 7: /* is the channel I/O callback set ? (0: no, 1: yes) */ buf[0] = 0; buf[1] = '\0'; break; default: return csound->InitError(csound, Str("invalid option code: %g"), *(p->iopt)); } if (s != NULL) { if (p->Sdst->data == NULL) { int size = strlen(s) + 1; p->Sdst->data = csound->Calloc(csound, size); p->Sdst->size = size; } else if (UNLIKELY((int) strlen(s) >= p->Sdst->size)) { p->Sdst->data = csound->ReAlloc(csound, p->Sdst->data, strlen(s) + 1); p->Sdst->size = strlen(s) + 1; } strcpy((char*) p->Sdst->data, s); } return OK; } /** * ipos strindex Sstr1, Sstr2 * kpos strindexk Sstr1, Sstr2 * * Return the position of the first occurence of Sstr2 in Sstr1, * or -1 if not found. If Sstr2 is empty, 0 is returned. */ int strindex_opcode(CSOUND *csound, STRINDEX_OP *p) { const char *s1 = (char*) p->Ssrc1->data; const char *s2 = (char*) p->Ssrc2->data; int i, j; (void) csound; /* search substring from left to right, */ /* and return position of first match */ i = j = 0; while (s2[j] != '\0') { if (s1[i] == '\0') { *(p->ipos) = -FL(1.0); return OK; } j = (s1[i] != s2[j] ? 0 : j + 1); i++; } *(p->ipos) = (MYFLT) (i - j); return OK; } /** * ipos strrindex Sstr1, Sstr2 * kpos strrindexk Sstr1, Sstr2 * * Return the position of the last occurence of Sstr2 in Sstr1, * or -1 if not found. If Sstr2 is empty, the length of Sstr1 is * returned. */ int strrindex_opcode(CSOUND *csound, STRINDEX_OP *p) { const char *s1 = (char*) p->Ssrc1->data; const char *s2 = (char*) p->Ssrc2->data; int i, j, k; (void) csound; /* search substring from left to right, */ /* and return position of last match */ i = j = 0; k = -1; while (1) { if (s2[j] == '\0') { k = i - j; j = 0; } if (s1[i] == '\0') break; j = (s1[i] != s2[j] ? 0 : j + 1); i++; } *(p->ipos) = (MYFLT) k; return OK; } #ifdef HAVE_CURL int str_from_url(CSOUND *csound, STRCPY_OP *p) { char *newVal = p->str->data; if (strstr(newVal, ":/")==NULL) return strcpy_opcode_S(csound, p); { CORFIL *mm = copy_url_corefile(csound, newVal,0); int len = corfile_length(mm); if (p->r->data == NULL) { p->r->data = cs_strdup(csound, corfile_body(mm)); p->r->size = len + 1; goto cleanup; } if (UNLIKELY(len >= p->r->size)) { csound->Free(csound, p->r->data); p->r->data = cs_strdup(csound, corfile_body(mm)); p->r->size = len + 1; } else strcpy((char*) p->r->data, corfile_body(mm)); cleanup: corfile_rm(csound, &mm); return OK; } } #endif #if !defined(HAVE_STRLCAT) && !defined(strlcat) && !defined(EMSCRIPTEN) /* Direct from BSD sources */ size_t strlcat(char *dst, const char *src, size_t siz) { char *d = dst; const char *s = src; size_t n = siz; size_t dlen; /* Find the end of dst and adjust bytes left but don't go past end */ while (n-- != 0 && *d != '\0') d++; dlen = d - dst; n = siz - dlen; if (n == 0) return (dlen + strlen(s)); while (*s != '\0') { if (n != 1) { *d++ = *s; n--; } s++; } *d = '\0'; return (dlen + (s - src)); /* count does not include NUL */ } #endif /* Debugging opcode for testing runtime type identification */ int print_type_opcode(CSOUND* csound, PRINT_TYPE_OP* p) { char* ptr = (char*)p->inVar; CS_TYPE* varType = *(CS_TYPE**)(ptr - CS_VAR_TYPE_OFFSET); csound->Message(csound, "Variable Type: %s\n", varType->varTypeName); return OK; } csound-6.10.0/OOps/ugens1.c000066400000000000000000002126321321653344700153350ustar00rootroot00000000000000/* ugens1.c: Copyright (C) 1991 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* UGENS1.C */ #include "ugens1.h" #include #define FHUND (FL(100.0)) int linset(CSOUND *csound, LINE *p) { double dur; if (LIKELY((dur = *p->idur) > FL(0.0))) { p->incr = (*p->ib - *p->ia) / dur * csound->onedsr; p->kincr = p->incr*CS_KSMPS; p->val = *p->ia; } return OK; } int kline(CSOUND *csound, LINE *p) { *p->xr = p->val; /* rslt = val */ p->val += p->kincr; /* val += incr */ return OK; } int aline(CSOUND *csound, LINE *p) { double val, inc; MYFLT *ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; ar = p->xr; val = p->val; inc = p->incr; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } //p->val += inc;/* nxtval = val + inc */ //inc /= (nsmps - offset); for (n=offset; nval = val; return OK; } int expset(CSOUND *csound, EXPON *p) { double dur, a, b; //printf("kr = %f , 1/kr = %f \n",CS_EKR, CS_ONEDKR); if (LIKELY((dur = *p->idur) > FL(0.0) )) { a = *p->ia; b = *p->ib; if (LIKELY((a * b) > FL(0.0))) { p->mlt = POWER(b/a, csound->onedsr/dur); p->kmlt = POWER(b/a, CS_ONEDKR/dur); p->val = a; } else if (a == FL(0.0)) return csound->InitError(csound, Str("arg1 is zero")); else if (b == FL(0.0)) return csound->InitError(csound, Str("arg2 is zero")); else return csound->InitError(csound, Str("unlike signs")); } return OK; } int kexpon(CSOUND *csound, EXPON *p) { *p->xr = p->val; /* rslt = val */ p->val *= p->kmlt; /* val *= mlt */ return OK; } int expon(CSOUND *csound, EXPON *p) { double val, mlt;//, inc;//, nxtval; MYFLT *ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; val = p->val; mlt = p->mlt; // nxtval = val * mlt; ar = p->xr; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } //inc = nxtval - val; //inc /= (nsmps - offset); /* increment per sample */ for (n=offset; nval = nxtval; /* store next value */ p->val = val; return OK; } int lsgset(CSOUND *csound, LINSEG *p) { SEG *segp; int nsegs; MYFLT **argp; double val; if (!(p->INCOUNT & 1)){ return csound->InitError(csound, Str("incomplete number of input arguments")); } /* count segs & alloc if nec */ nsegs = (p->INOCOUNT - (!(p->INOCOUNT & 1))) >> 1; /* VL: 29.05.17 allocating one extra empty segment so that the breakpoint version of this opcode can work properly without a fencepost bug */ if (UNLIKELY((p->cursegp = (SEG *) p->auxch.auxp) == NULL || (nsegs+1)*sizeof(SEG) < (unsigned int)p->auxch.size)) { csound->AuxAlloc(csound, (int32)(nsegs+1)*sizeof(SEG), &p->auxch); p->cursegp = (SEG *) p->auxch.auxp; segp = p->cursegp + 1; /* point to first seg */ p->cursegp->cnt = 0; /* zero duration of segment 0 */ segp[nsegs-1].cnt = MAXPOS; /* set endcount for safety */ } else segp = p->cursegp + 1; /* point to first seg */ argp = p->argums; val = (double)**argp++; if (UNLIKELY(**argp <= FL(0.0))) return OK; /* if idur1 <= 0, skip init */ p->curval = val; p->curcnt = 0; /* VL: 29.05.17 this was causing a fencepost error in the breakpoint version (linsegb) */ //p->cursegp = segp - 1; /* else setup null seg0 */ p->segsrem = nsegs + 1; do { /* init each seg .. */ double dur = (double)**argp++; segp->nxtpt = (double)**argp++; if (UNLIKELY((segp->cnt = (int32)(dur * CS_EKR + FL(0.5))) < 0)) segp->cnt = 0; if (UNLIKELY((segp->acnt = (int32)(dur * csound->esr + FL(0.5))) < 0)) segp->acnt = 0; segp++; } while (--nsegs); p->xtra = -1; return OK; } int lsgset_bkpt(CSOUND *csound, LINSEG *p) { int32 cnt = 0, bkpt = 0; int nsegs; int n; SEG *segp; n = lsgset(csound, p); if (UNLIKELY(n!=0)) return n; nsegs = p->segsrem; segp = p->cursegp; do { if (UNLIKELY(cnt > segp->cnt)) return csound->InitError(csound, Str("Breakpoint %d not valid"), bkpt); segp->cnt -= cnt; cnt += segp->cnt; segp++; bkpt++; } while (--nsegs); return OK; } int klnseg(CSOUND *csound, LINSEG *p) { *p->rslt = p->curval; /* put the cur value */ if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; /* RWD fix */ if (p->segsrem) { /* done if no more segs */ if (--p->curcnt <= 0) { /* if done cur segment */ SEG *segp = p->cursegp; if (UNLIKELY(!(--p->segsrem))) { p->curval = segp->nxtpt; /* advance the cur val */ return OK; } p->cursegp = ++segp; /* find the next */ if (UNLIKELY(!(p->curcnt = segp->cnt))) { /* nonlen = discontin */ p->curval = segp->nxtpt; /* poslen = new slope */ /* p->curval += p->curinc; ??????? */ return OK; } else { p->curinc = (segp->nxtpt - p->curval) / segp->cnt; p->curval += p->curinc; return OK; } } if (p->curcnt<10) /* This is a fiddle to get rounding right! */ p->curinc = (p->cursegp->nxtpt - p->curval) / p->curcnt; /* recalc */ p->curval += p->curinc; /* advance the cur val */ } return OK; err1: return csound->InitError(csound, Str("linseg not initialised (krate)\n")); } int linseg(CSOUND *csound, LINSEG *p) { double val, ainc; MYFLT *rs = p->rslt; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; /* RWD fix */ val = p->curval; /* sav the cur value */ if (UNLIKELY(offset)) memset(rs, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rs[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nsegsrem)) { /* if no more segs putk */ if (--p->curcnt <= 0) { /* if done cur segment */ SEG *segp = p->cursegp; chk1: if (UNLIKELY(!--p->segsrem)) { /* if none left */ val = p->curval = segp->nxtpt; goto putk; /* put endval */ } p->cursegp = ++segp; /* else find the next */ //printf("newseg: nxtpt=%f acnt=%d\n", segp->nxtpt, segp->acnt); if (UNLIKELY(!(p->curcnt = segp->acnt))) { val = p->curval = segp->nxtpt; /* nonlen = discontin */ goto chk1; } /* poslen = new slope */ p->curainc = (segp->nxtpt - val) / segp->acnt; // p->curainc = p->curinc * CS_ONEDKSMPS; } // p->curval = val + p->curinc; /* advance the cur val */ if (UNLIKELY((ainc = p->curainc) == FL(0.0))) goto putk; rs[n] = (MYFLT)val; val += ainc; } else { /* no more segments */ putk: rs[n] = (MYFLT)val; } } p->curval = val; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("linseg: not initialised (arate)\n")); } /* **** ADSR is just a construction and use of linseg */ static int adsrset1(CSOUND *csound, LINSEG *p, int midip) { SEG *segp; int nsegs; MYFLT **argp = p->argums; double dur; MYFLT len = csound->curip->p3.value; MYFLT release = *argp[3]; int32 relestim; //printf("len = %f\n", len); if (UNLIKELY(len<=FL(0.0))) len = FL(100000.0); /* MIDI case set int32 */ nsegs = 6; /* DADSR */ if ((segp = (SEG *) p->auxch.auxp) == NULL || nsegs*sizeof(SEG) < (unsigned int)p->auxch.size) { csoundAuxAlloc(csound, (size_t) nsegs * sizeof(SEG), &p->auxch); p->cursegp = segp = (SEG *) p->auxch.auxp; segp[nsegs-1].cnt = MAXPOS; /* set endcount for safety */ } else if (**argp > FL(0.0)) memset(p->auxch.auxp, 0, (size_t)nsegs*sizeof(SEG)); if (**argp <= FL(0.0)) return OK; /* if idur1 <= 0, skip init */ p->curval = 0.0; p->curcnt = 0; p->cursegp = segp - 1; /* else setup null seg0 */ p->segsrem = nsegs; //printf("args: %f %f %f %f %f\n", // *argp[0], *argp[1], *argp[2], *argp[3],* argp[4]); /* Delay */ dur = (double)*argp[4]; segp->nxtpt = FL(0.0); segp->cnt = (int32)(dur * CS_EKR + FL(0.5)); //printf("delay: dur=%f cnt=%d\n", dur, segp->cnt); segp++; /* Attack */ dur = (double)*argp[0]; segp->nxtpt = FL(1.0); segp->cnt = (int32)(dur * CS_EKR + FL(0.5)); if (UNLIKELY((segp->acnt = (int32)(dur * csound->esr + FL(0.5))) < 0)) segp->acnt = 0; //printf("attack: dur=%f cnt=%d acnt=%d nxt=%f\n", // dur, segp->cnt, segp->acnt, segp->nxtpt); segp++; /* Decay */ dur = *argp[1]; segp->nxtpt = *argp[2]; segp->cnt = (int32)(dur * CS_EKR + FL(0.5)); if (UNLIKELY((segp->acnt = (int32)(dur * csound->esr + FL(0.5))) < 0)) segp->acnt = 0; //printf("decay: dur=%f cnt=%d acnt=%d nxt=%f\n", // dur, segp->cnt, segp->acnt, segp->nxtpt); segp++; /* Sustain */ /* Should use p3 from score, but how.... */ dur = len - *argp[4] - *argp[0] - *argp[1] - *argp[3]; if (!midip && dur <0.0) csound->Warning(csound, Str("length of ADSR note too short")); segp->nxtpt = *argp[2]; segp->cnt = (int32)(dur * CS_EKR + FL(0.5)); if (UNLIKELY((segp->acnt = (int32)(dur * csound->esr + FL(0.5))) < 0)) segp->acnt = 0; //printf("sustain: dur=%f cnt=%d acnt=%d nxt=%f\n", // dur, segp->cnt, segp->acnt, segp->nxtpt); segp++; /* Release */ dur = *argp[3]; segp->nxtpt = FL(0.0); segp->cnt = (int32)(release * CS_EKR + FL(0.5)); if (UNLIKELY((segp->acnt = (int32)(release * csound->esr + FL(0.5))) < 0)) segp->acnt = 0; //printf("release: dur=%f cnt=%d acnt=%d nxt=%f\n", // dur, segp->cnt, segp->acnt, segp->nxtpt); if (midip) { relestim = (p->cursegp + p->segsrem - 1)->cnt; p->xtra = relestim; /* VL 4-1-2011 was (int32)(*argp[5] * CS_EKR + FL(0.5)); this seems to fix it */ if (relestim > p->h.insdshead->xtratim) p->h.insdshead->xtratim = (int)relestim; } else p->xtra = 0L; return OK; } int adsrset(CSOUND *csound, LINSEG *p) { return adsrset1(csound, p, 0); } int madsrset(CSOUND *csound, LINSEG *p) { return adsrset1(csound, p, 1); } /* End of ADSR */ int lsgrset(CSOUND *csound, LINSEG *p) { int32 relestim; if (lsgset(csound,p) == OK){ relestim = (p->cursegp + p->segsrem - 1)->cnt; p->xtra = relestim; /* VL 4-1-2011 was -1, making all linsegr releases in an instr => xtratim set to relestim seems to fix this */ if (relestim > p->h.insdshead->xtratim) p->h.insdshead->xtratim = (int)relestim; return OK; } else return NOTOK; } int klnsegr(CSOUND *csound, LINSEG *p) { *p->rslt = p->curval; /* put the cur value */ if (p->segsrem) { /* done if no more segs */ SEG *segp; if (p->h.insdshead->relesing && p->segsrem > 1) { while (p->segsrem > 1) { /* reles flag new: */ segp = ++p->cursegp; /* go to last segment */ p->segsrem--; } /* get univ relestim */ segp->cnt = p->xtra>= 0 ? p->xtra : p->h.insdshead->xtratim; goto newi; /* and set new curinc */ } if (--p->curcnt <= 0) { /* if done cur seg */ chk2: if (p->segsrem == 2) return OK; /* seg Y rpts lastval */ if (!(--p->segsrem)) return OK; /* seg Z now done all */ segp = ++p->cursegp; /* else find nextseg */ newi: if (!(p->curcnt = segp->cnt)) { /* nonlen = discontin */ p->curval = segp->nxtpt; /* reload & rechk */ goto chk2; } /* else get new slope */ p->curinc = (segp->nxtpt - p->curval) / segp->cnt; } p->curval += p->curinc; /* advance the cur val */ } return OK; } int linsegr(CSOUND *csound, LINSEG *p) { MYFLT val, ainc, *rs = p->rslt; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(offset)) memset(rs, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rs[nsmps], '\0', early*sizeof(MYFLT)); } val = p->curval; /* sav the cur value */ for (n=offset; nsegsrem)) { /* if no more segs putk */ SEG *segp; if (p->h.insdshead->relesing && p->segsrem > 1) { while (p->segsrem > 1) { /* release flag new: */ segp = ++p->cursegp; /* go to last segment */ p->segsrem--; } /* get univ relestim */ segp->acnt = (p->xtra >=0 ? p->xtra : p->h.insdshead->xtratim)*CS_KSMPS; goto newi; /* and set new curinc */ } if (--p->curcnt <= 0) { /* if done cur seg */ chk2: if (p->segsrem == 2) goto putk; /* seg Y rpts lastval */ if (!(--p->segsrem)) goto putk; /* seg Z now done all */ segp = ++p->cursegp; /* else find nextseg */ newi: if (!(p->curcnt = segp->acnt)) { /* nonlen = discontin */ val = p->curval = segp->nxtpt; /* reload & rechk */ goto chk2; } /* else get new slope */ p->curainc = (segp->nxtpt - val) / segp->acnt; // p->curainc = p->curinc * CS_ONEDKSMPS; } //p->curval = val + p->curainc*CS_KSMPS; /* advance the cur val */ if ((ainc = p->curainc) == FL(0.0)) goto putk; rs[n] = val; val += ainc; } else { putk: rs[n] = val; } } p->curval = val; return OK; } int xsgset(CSOUND *csound, EXXPSEG *p) { XSEG *segp; int nsegs; MYFLT d, **argp, val, dur, nxtval; int n=0; if (!(p->INCOUNT & 1)) { return csound->InitError(csound, Str("incomplete number of input arguments")); } /* count segs & alloc if nec */ nsegs = (p->INOCOUNT - (!(p->INOCOUNT & 1))) >> 1; if ((segp = (XSEG *) p->auxch.auxp) == NULL || nsegs*sizeof(XSEG) < (unsigned int)p->auxch.size) { csound->AuxAlloc(csound, (int32)nsegs*sizeof(XSEG), &p->auxch); p->cursegp = segp = (XSEG *) p->auxch.auxp; (segp+nsegs-1)->cnt = MAXPOS; /* set endcount for safety */ } argp = p->argums; nxtval = **argp++; if (**argp <= FL(0.0)) return OK; /* if idur1 <= 0, skip init */ p->cursegp = segp; /* else proceed from 1st seg */ segp--; p->segsrem = nsegs; do { segp++; /* init each seg .. */ val = nxtval; dur = **argp++; nxtval = **argp++; if (UNLIKELY(val * nxtval <= FL(0.0))) goto experr; d = dur * CS_EKR; segp->val = val; segp->mlt = (MYFLT) pow((double)(nxtval / val), (1.0/(double)d)); segp->cnt = (int32) (d + FL(0.5)); d = dur * csound->esr; segp->amlt = (MYFLT) pow((double)(nxtval / val), (1.0/(double)d)); segp->acnt = (int32) (d + FL(0.5)); } while (--nsegs); segp->cnt = MAXPOS; /* set last cntr to infin */ segp->acnt = MAXPOS; /* set last cntr to infin */ return OK; experr: n = segp - p->cursegp + 1; if (val == FL(0.0)) return csound->InitError(csound, Str("ival%d is zero"), n); else if (nxtval == FL(0.0)) return csound->InitError(csound, Str("ival%d is zero"), n+1); return csound->InitError(csound, Str("ival%d sign conflict"), n+1); } int xsgset_bkpt(CSOUND *csound, EXXPSEG *p) { XSEG *segp; int nsegs; MYFLT d, **argp, val, dur, dursum = FL(0.0), bkpt, nxtval; int n=0; if (!(p->INCOUNT & 1)){ return csound->InitError(csound, Str("incomplete number of input arguments")); } /* count segs & alloc if nec */ nsegs = (p->INOCOUNT - (!(p->INOCOUNT & 1))) >> 1; if ((segp = (XSEG *) p->auxch.auxp) == NULL || nsegs*sizeof(XSEG) < (unsigned int)p->auxch.size) { csound->AuxAlloc(csound, (int32)nsegs*sizeof(XSEG), &p->auxch); p->cursegp = segp = (XSEG *) p->auxch.auxp; (segp+nsegs-1)->cnt = MAXPOS; /* set endcount for safety */ } argp = p->argums; nxtval = **argp++; if (**argp <= FL(0.0)) return OK; /* if idur1 <= 0, skip init */ p->cursegp = segp; /* else proceed from 1st seg */ segp--; p->segsrem = nsegs; do { segp++; /* init each seg .. */ val = nxtval; bkpt = **argp++; if (UNLIKELY(bkpt < dursum)) return csound->InitError(csound, Str("Breakpoint time %f not valid"), bkpt); dur = bkpt - dursum; dursum += dur; nxtval = **argp++; if (UNLIKELY(val * nxtval <= FL(0.0))) goto experr; d = dur * CS_EKR; segp->val = val; segp->mlt = (MYFLT) pow((double)(nxtval / val), (1.0/(double)d)); segp->cnt = (int32) (d + FL(0.5)); d = dur * csound->esr; segp->amlt = (MYFLT) pow((double)(nxtval / val), (1.0/(double)d)); segp->acnt = (int32) (d + FL(0.5)); } while (--nsegs); segp->cnt = MAXPOS; /* set last cntr to infin */ segp->acnt = MAXPOS; return OK; experr: n = segp - p->cursegp + 1; if (val == FL(0.0)) return csound->InitError(csound, Str("ival%d is zero"), n); else if (nxtval == FL(0.0)) return csound->InitError(csound, Str("ival%d is zero"), n+1); return csound->InitError(csound, Str("ival%d sign conflict"), n+1); } int xsgset2b(CSOUND *csound, EXPSEG2 *p) { XSEG *segp; int nsegs; MYFLT d, **argp, val, dur, dursum = FL(0.0), bkpt, nxtval; int n; if (!(p->INCOUNT & 1)){ return csound->InitError(csound, Str("incomplete number of input arguments")); } /* count segs & alloc if nec */ nsegs = (p->INOCOUNT - (!(p->INOCOUNT & 1))) >> 1; if ((segp = (XSEG*) p->auxch.auxp) == NULL || (unsigned int)nsegs*sizeof(XSEG) > (unsigned int)p->auxch.size) { csound->AuxAlloc(csound, (int32)nsegs*sizeof(XSEG), &p->auxch); p->cursegp = segp = (XSEG *) p->auxch.auxp; (segp+nsegs-1)->cnt = MAXPOS; /* set endcount for safety */ } argp = p->argums; nxtval = **argp++; if (**argp <= FL(0.0)) return OK; /* if idur1 <= 0, skip init */ p->cursegp = segp; /* else proceed from 1st seg */ segp--; do { segp++; /* init each seg .. */ val = nxtval; bkpt = **argp++; if (UNLIKELY(bkpt < dursum)) return csound->InitError(csound, Str("Breakpoint time %f not valid"), bkpt); dur = bkpt - dursum; dursum += dur; nxtval = **argp++; /* if (dur > FL(0.0)) { */ if (UNLIKELY(val * nxtval <= FL(0.0))) goto experr; d = dur * csound->esr; segp->val = val; segp->mlt = POWER((nxtval / val), FL(1.0)/d); segp->cnt = (int32) (d + FL(0.5)); d = dur * csound->esr; segp->amlt = (MYFLT) pow((double)(nxtval / val), (1.0/(double)d)); segp->acnt = (int32) (d + FL(0.5)); /* } */ /* else break; /\* .. til 0 dur or done *\/ */ } while (--nsegs); segp->cnt = MAXPOS; /* set last cntr to infin */ segp->acnt = MAXPOS; return OK; experr: n = segp - p->cursegp + 1; if (val == FL(0.0)) return csound->InitError(csound, Str("ival%d is zero"), n); else if (nxtval == FL(0.0)) return csound->InitError(csound, Str("ival%d is zero"), n+1); return csound->InitError(csound, Str("ival%d sign conflict"), n+1); } int xsgset2(CSOUND *csound, EXPSEG2 *p) /*gab-A1 (G.Maldonado) */ { XSEG *segp; int nsegs; MYFLT d, **argp, val, dur, nxtval; int n; if (!(p->INCOUNT & 1)){ return csound->InitError(csound, Str("incomplete number of input arguments")); } /* count segs & alloc if nec */ nsegs = (p->INOCOUNT - (!(p->INOCOUNT & 1))) >> 1; if ((segp = (XSEG*) p->auxch.auxp) == NULL || (unsigned int)nsegs*sizeof(XSEG) > (unsigned int)p->auxch.size) { csound->AuxAlloc(csound, (int32)nsegs*sizeof(XSEG), &p->auxch); p->cursegp = segp = (XSEG *) p->auxch.auxp; (segp+nsegs-1)->cnt = MAXPOS; /* set endcount for safety */ } argp = p->argums; nxtval = **argp++; if (**argp <= FL(0.0)) return OK; /* if idur1 <= 0, skip init */ p->cursegp = segp; /* else proceed from 1st seg */ segp--; do { segp++; /* init each seg .. */ val = nxtval; dur = **argp++; nxtval = **argp++; /* if (dur > FL(0.0)) { */ if (UNLIKELY(val * nxtval <= FL(0.0))) goto experr; d = dur * csound->esr; segp->val = val; segp->mlt = POWER((nxtval / val), FL(1.0)/d); segp->cnt = (int32) (d + FL(0.5)); d = dur * csound->esr; segp->amlt = (MYFLT) pow((double)(nxtval / val), (1.0/(double)d)); segp->acnt = (int32) (d + FL(0.5)); /* } */ /* else break; /\* .. til 0 dur or done *\/ */ } while (--nsegs); segp->cnt = MAXPOS; /* set last cntr to infin */ segp->acnt = MAXPOS; return OK; experr: n = segp - p->cursegp + 1; if (val == FL(0.0)) return csound->InitError(csound, Str("ival%d is zero"), n); else if (nxtval == FL(0.0)) return csound->InitError(csound, Str("ival%d is zero"), n+1); return csound->InitError(csound, Str("ival%d sign conflict"), n+1); } /***************************************/ int expseg2(CSOUND *csound, EXPSEG2 *p) /* gab-A1 (G.Maldonado) */ { XSEG *segp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT val, *rs; segp = p->cursegp; val = segp->val; rs = p->rslt; if (UNLIKELY(offset)) memset(rs, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rs[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; ncnt < 0) { p->cursegp = ++segp; val = segp->val; } rs[n] = val; val *= segp->mlt; } segp->val = val; return OK; } /* **** XDSR is just a construction and use of expseg */ int xdsrset(CSOUND *csound, EXXPSEG *p) { XSEG *segp; int nsegs; MYFLT **argp = p->argums; MYFLT len = csound->curip->p3.value; MYFLT delay = *argp[4], attack = *argp[0], decay = *argp[1]; MYFLT sus, dur; MYFLT release = *argp[3]; if (UNLIKELY(lencurip->p3.value-delay-attack-decayWarning(csound, Str("length of XADSR note too short")); len -= release; /* len is time remaining */ if (UNLIKELY(lencurip->p3.value; len = FL(0.0); } nsegs = 5; /* DXDSR */ if ((segp = (XSEG *) p->auxch.auxp) == NULL || nsegs*sizeof(XSEG) < (unsigned int)p->auxch.size) { csound->AuxAlloc(csound, (int32)nsegs*sizeof(XSEG), &p->auxch); segp = (XSEG *) p->auxch.auxp; } segp[nsegs-1].cnt = MAXPOS; /* set endcount for safety */ if (**argp <= FL(0.0)) return OK; /* if idur1 <= 0, skip init */ p->cursegp = segp; /* else setup null seg0 */ p->segsrem = nsegs; delay += FL(0.001); if (delay > len) delay = len; len -= delay; attack -= FL(0.001); if (attack > len) attack = len; len -= attack; if (decay > len) decay = len; len -= decay; sus = len; segp[0].val = FL(0.0001); /* Like zero start, but exponential */ segp[0].mlt = FL(1.0); segp[0].cnt = (int32) (delay*CS_EKR + FL(0.5)); segp[0].amlt = FL(1.0); segp[0].acnt = (int32) (delay*CS_ESR + FL(0.5)); dur = attack*CS_EKR; segp[1].val = FL(0.0001); segp[1].mlt = POWER(FL(1000.0), FL(1.0)/dur); segp[1].cnt = (int32) (dur + FL(0.5)); dur = attack*CS_ESR; segp[1].amlt = POWER(FL(1000.0), FL(1.0)/dur); segp[1].acnt = (int32) (dur + FL(0.5)); //printf("attack: %f %f %d / %f %d\n", // segp[1].val,segp[1].mlt,segp[1].cnt,segp[1].amlt, segp[1].acnt); dur = decay*CS_EKR; segp[2].val = FL(1.0); segp[2].mlt = POWER(*argp[2], FL(1.0)/dur); segp[2].cnt = (int32) (dur + FL(0.5)); dur = decay*CS_ESR; segp[2].amlt = POWER(*argp[2], FL(1.0)/dur); segp[2].acnt = (int32) (dur + FL(0.5)); //printf("decay: %f %f %d %f %d\n", // segp[2].val,segp[2].mlt,segp[2].cnt,segp[2].amlt, segp[2].acnt); segp[3].val = *argp[2]; segp[3].mlt = FL(1.0); segp[3].cnt = (int32) (sus*CS_EKR + FL(0.5)); segp[3].amlt = FL(1.0); segp[3].acnt = (int32) (sus*CS_ESR + FL(0.5)); //printf("sustain: %f %f %d %f %d\n", // segp[3].val,segp[3].mlt,segp[3].cnt,segp[3].amlt, segp[3].acnt); dur = release*CS_EKR; segp[4].val = *argp[2]; segp[4].mlt = POWER(FL(0.001)/(*argp[2]), FL(1.0)/dur); segp[4].cnt = MAXPOS; /*(int32) (dur + FL(0.5)); */ dur = release*CS_ESR; segp[4].amlt = POWER(FL(0.001)/(*argp[2]), FL(1.0)/dur); segp[4].acnt = MAXPOS; /*(int32) (dur + FL(0.5)); */ //printf("releaase: %f %f %d %f %d\n", // segp[4].val,segp[4].mlt,segp[4].cnt,segp[4].amlt, segp[4].acnt); return OK; } /* end of XDSR */ int kxpseg(CSOUND *csound, EXXPSEG *p) { XSEG *segp; segp = p->cursegp; if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; /* RWD fix */ while (--segp->cnt < 0) p->cursegp = ++segp; *p->rslt = segp->val; segp->val *= segp->mlt; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("expseg (krate): not initialised")); } int expseg(CSOUND *csound, EXXPSEG *p) { XSEG *segp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *rs = p->rslt; if (UNLIKELY(offset)) memset(rs, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rs[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; ncursegp; if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; while (--segp->acnt < 0) { //printf("seg: val=%f amlt=%f\n", segp->val,segp->amlt ); p->cursegp = ++segp; //printf("nxtseg: val=%f amlt=%f acnt=%d\n", // segp->val,segp->amlt,segp->acnt); } rs[n] = segp->val; segp->val *= segp->amlt; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("expseg (arate): not initialised")); } int xsgrset(CSOUND *csound, EXPSEG *p) { int relestim; SEG *segp; int nsegs, n = 0; MYFLT **argp, prvpt; if (!(p->INCOUNT & 1)){ return csound->InitError(csound, Str("incomplete number of input arguments")); } //p->xtra = -1; /* count segs & alloc if nec */ nsegs = (p->INOCOUNT - (!(p->INOCOUNT & 1))) >> 1; if ((segp = (SEG *) p->auxch.auxp) == NULL || (unsigned int)nsegs*sizeof(SEG) > (unsigned int)p->auxch.size) { csound->AuxAlloc(csound, (int32)nsegs*sizeof(SEG), &p->auxch); p->cursegp = segp = (SEG *) p->auxch.auxp; } argp = p->argums; prvpt = **argp++; if (**argp < FL(0.0)) return OK; /* if idur1 < 0, skip init */ p->curval = prvpt; p->curcnt = 0; /* else setup null seg0 */ p->cursegp = segp - 1; p->segsrem = nsegs + 1; do { /* init & chk each real seg .. */ MYFLT dur = **argp++; segp->nxtpt = **argp++; if ((segp->cnt = (int32)(dur * CS_EKR + FL(0.5))) <= 0) segp->cnt = 0; else if (segp->nxtpt * prvpt <= FL(0.0)) goto experr; if ((segp->acnt = (int32)(dur * CS_ESR )) <= 0) segp->acnt = 0; prvpt = segp->nxtpt; segp++; } while (--nsegs); relestim = (int)(p->cursegp + p->segsrem - 1)->cnt; p->xtra = relestim; if (relestim > p->h.insdshead->xtratim) p->h.insdshead->xtratim = relestim; return OK; experr: n = segp - p->cursegp;// + 2; if (prvpt == FL(0.0)) return csound->InitError(csound, Str("ival%d is zero"), n); else if (segp->nxtpt == FL(0.0)) return csound->InitError(csound, Str("ival%d is zero"), n+1); return csound->InitError(csound, Str("ival%d sign conflict"), n+1); } /* **** MXDSR is just a construction and use of expseg */ int mxdsrset(CSOUND *csound, EXPSEG *p) { int relestim; SEG *segp; int nsegs; MYFLT **argp = p->argums; MYFLT delay = *argp[4], attack = *argp[0], decay = *argp[1]; MYFLT rel = *argp[3]; nsegs = 4; /* DXDSR */ if ((segp = (SEG *) p->auxch.auxp) == NULL || nsegs*sizeof(SEG) < (unsigned int)p->auxch.size) { csound->AuxAlloc(csound, (int32)nsegs*sizeof(SEG), &p->auxch); segp = (SEG *) p->auxch.auxp; } if (**argp <= FL(0.0)) return OK; /* if idur1 <= 0, skip init */ p->cursegp = segp-1; /* else setup null seg0 */ p->segsrem = nsegs+1; p->curval = FL(0.001); p->curcnt = 0; /* else setup null seg0 */ delay += FL(0.001); attack -= FL(0.001); segp[0].nxtpt = FL(0.001); segp[0].cnt = (int32) (delay*CS_EKR + FL(0.5)); segp[0].acnt = (int32) (delay*CS_ESR + FL(0.5)); segp[1].nxtpt = FL(1.0); segp[1].cnt = (int32) (attack*CS_EKR + FL(0.5)); segp[1].acnt = (int32) (attack*CS_ESR + FL(0.5)); segp[2].nxtpt = *argp[2]; segp[2].cnt = (int32) (decay*CS_EKR + FL(0.5)); segp[2].acnt = (int32) (decay*CS_ESR + FL(0.5)); segp[3].nxtpt = FL(0.001); segp[3].cnt = (int32) (rel*CS_EKR + FL(0.5)); segp[3].acnt = (int32) (rel*CS_ESR + FL(0.5)); relestim = (int)(p->cursegp + p->segsrem - 1)->cnt; p->xtra = relestim;//(int32)(*argp[5] * CS_EKR + FL(0.5)); /* Release time?? */ if (relestim > p->h.insdshead->xtratim) p->h.insdshead->xtratim = relestim; return OK; } /* end of MXDSR */ int kxpsegr(CSOUND *csound, EXPSEG *p) { *p->rslt = p->curval; /* put the cur value */ if (p->segsrem) { /* done if no more segs */ SEG *segp; if (p->h.insdshead->relesing && p->segsrem > 1) { while (p->segsrem > 1) { /* reles flag new: */ segp = ++p->cursegp; /* go to last segment */ p->segsrem--; } /* get univ relestim */ segp->cnt = p->xtra>=0 ? p->xtra : p->h.insdshead->xtratim; goto newm; /* and set new curmlt */ } if (--p->curcnt <= 0) { /* if done cur seg */ chk2: if (p->segsrem == 2) return OK; /* seg Y rpts lastval */ if (!(--p->segsrem)) return OK; /* seg Z now done all */ segp = ++p->cursegp; /* else find nextseg */ newm: if (!(p->curcnt = segp->cnt)) { /* nonlen = discontin */ p->curval = segp->nxtpt; /* reload & rechk */ goto chk2; } if (segp->nxtpt == p->curval) /* else get new mlt */ p->curmlt = FL(1.0); else p->curmlt = (MYFLT) pow(segp->nxtpt/p->curval, 1.0/segp->cnt); } p->curval *= p->curmlt; /* advance the cur val */ } return OK; } int expsegr(CSOUND *csound, EXPSEG *p) { MYFLT val, amlt, *rs = p->rslt; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(offset)) memset(rs, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rs[nsmps], '\0', early*sizeof(MYFLT)); } /* sav the cur value */ val = p->curval; for (n=offset; nsegsrem) { /* if no more segs putk */ SEG *segp; if (p->h.insdshead->relesing && p->segsrem > 1) { while (p->segsrem > 1) { /* if reles flag new */ segp = ++p->cursegp; /* go to last segment */ p->segsrem--; } /* get univ relestim */ segp->acnt = (p->xtra>=0 ? p->xtra : p->h.insdshead->xtratim)*CS_KSMPS; goto newm; /* and set new curmlt */ } if (--p->curcnt <= 0) { /* if done cur seg */ chk2: if (p->segsrem == 2) goto putk; /* seg Y rpts lastval */ if (!(--p->segsrem)) goto putk; /* seg Z now done all */ segp = ++p->cursegp; /* else find nextseg */ newm: if (!(p->curcnt = segp->acnt)) { /* nonlen = discontin */ val = p->curval = segp->nxtpt; /* reload & rechk */ goto chk2; } /* else get new mlts */ if (segp->nxtpt == val) { p->curmlt = p->curamlt = FL(1.0); p->curval = val; goto putk; } else { p->curmlt = POWER((segp->nxtpt/val), FL(1.0)/segp->cnt); p->curamlt = POWER(p->curmlt, FL(1.0)/(MYFLT)(nsmps-offset)); } } if ((amlt = p->curamlt) == FL(1.0)) goto putk; rs[n] = val; val *= amlt; } else { putk: rs[n] = val; } } p->curval = val; return OK; } int lnnset(CSOUND *csound, LINEN *p) { MYFLT a,b,dur; MYFLT len = csound->curip->p3.value; if ((dur = *p->idur) > FL(0.0)) { MYFLT iris = *p->iris, idec = *p->idec; if (len<(irisWarning(csound, Str("p3 too short in linen")); p->cnt1 = (int32)(iris * CS_EKR + FL(0.5)); if (p->cnt1 > (int32)0) { p->inc1 = FL(1.0) / (MYFLT) p->cnt1; p->val = FL(0.0); } else p->inc1 = p->val = FL(1.0); a = dur * CS_EKR + FL(0.5); b = idec * CS_EKR + FL(0.5); if ((int32) b > 0) { p->cnt2 = (int32) (a - b); p->inc2 = FL(1.0) / b; } else { p->inc2 = FL(1.0); p->cnt2 = (int32) a; } p->lin1 = FL(0.0); p->lin2 = FL(1.0); } return OK; } int alnnset(CSOUND *csound, LINEN *p) { MYFLT a,b,dur; MYFLT len = csound->curip->p3.value; if ((dur = *p->idur) > FL(0.0)) { MYFLT iris = *p->iris, idec = *p->idec; if (len<(irisWarning(csound, Str("p3 too short in linen")); p->cnt1 = (int32)(*p->iris * CS_ESR + FL(0.5)); if (p->cnt1 > (int32)0) { p->inc1 = FL(1.0) / (MYFLT) p->cnt1; p->val = FL(0.0); } else p->inc1 = p->val = FL(1.0); a = dur * CS_ESR + FL(0.5); b = *p->idec * CS_ESR + FL(0.5); if ((int32) b > 0) { p->cnt2 = (int32) (a - b); p->inc2 = FL(1.0) / b; } else { p->inc2 = FL(1.0); p->cnt2 = (int32) a; } p->lin1 = FL(0.0); p->lin2 = FL(1.0); } return OK; } int klinen(CSOUND *csound, LINEN *p) { MYFLT fact = FL(1.0); if (p->cnt1 > 0) { fact = p->lin1; p->lin1 += p->inc1; p->cnt1--; } if (p->cnt2 > 0) p->cnt2--; else { fact *= p->lin2; p->lin2 -= p->inc2; } *p->rslt = *p->sig * fact; return OK; } int linen(CSOUND *csound, LINEN *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t flag=0, n, nsmps = CS_KSMPS; MYFLT *rs,*sg,val; int asgsg = IS_ASIG_ARG(p->sig); val = p->val; rs = p->rslt; sg = p->sig; if (UNLIKELY(offset)) memset(rs, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rs[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; ncnt1 > 0) { flag = 1; val = p->lin1; p->lin1 += p->inc1; p->cnt1--; } if (p->cnt2 > 0){ p->cnt2--; } else { val *= p->lin2; p->lin2 -= p->inc2; flag = 1; } /*if (p->cnt2 <= 0) { flag = 1; val = p->lin2; p->lin2 -= p->inc2; } else p->cnt2--; */ if (flag) { if (asgsg) rs[n] = sg[n] * val; else rs[n] = *sg * val; } else { if (asgsg) rs[n] = sg[n]; else rs[n] = *sg; } } p->val = val; return OK; } int lnrset(CSOUND *csound, LINENR *p) { p->cnt1 = (int32)(*p->iris * CS_EKR + FL(0.5)); if (p->cnt1 > 0L) { p->inc1 = FL(1.0) / (MYFLT)p->cnt1; p->val = FL(0.0); } else p->inc1 = p->val = FL(1.0); if (*p->idec > FL(0.0)) { int relestim = (int)(*p->idec * CS_EKR + FL(0.5)); if (relestim > p->h.insdshead->xtratim) p->h.insdshead->xtratim = relestim; if (UNLIKELY(*p->iatdec <= FL(0.0))) { return csound->InitError(csound, Str("non-positive iatdec")); } else p->mlt2 = POWER(*p->iatdec, CS_ONEDKR / *p->idec); } else p->mlt2 = FL(1.0); p->lin1 = FL(0.0); p->val2 = FL(1.0); return OK; } int alnrset(CSOUND *csound, LINENR *p) { p->cnt1 = (int32)(*p->iris * CS_ESR); if (p->cnt1 > 0L) { p->inc1 = FL(1.0) / (MYFLT)p->cnt1; p->val = FL(0.0); } else p->inc1 = p->val = FL(1.0); if (*p->idec > FL(0.0)) { int relestim = (int)(*p->idec * CS_EKR + FL(0.5)); if (relestim > p->h.insdshead->xtratim) p->h.insdshead->xtratim = relestim; if (UNLIKELY(*p->iatdec <= FL(0.0))) { return csound->InitError(csound, Str("non-positive iatdec")); } else p->mlt2 = POWER(*p->iatdec, csound->onedsr / *p->idec); } else p->mlt2 = FL(1.0); p->lin1 = FL(0.0); p->val2 = FL(1.0); return OK; } int klinenr(CSOUND *csound, LINENR *p) { MYFLT fact = FL(1.0); if (p->cnt1 > 0L) { fact = p->lin1; p->lin1 += p->inc1; p->cnt1--; } if (p->h.insdshead->relesing) { fact *= p->val2; p->val2 *= p->mlt2; } *p->rslt = *p->sig * fact; return OK; } int linenr(CSOUND *csound, LINENR *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t flag=0, n, nsmps = CS_KSMPS; MYFLT *rs,*sg,val; int asgsg = IS_ASIG_ARG(p->sig); val = p->val; rs = p->rslt; sg = p->sig; if (UNLIKELY(offset)) memset(rs, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rs[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; ncnt1 > 0L) { flag = 1; val = p->lin1; p->lin1 += p->inc1; p->cnt1--; } if (p->h.insdshead->relesing) { flag = 1; val = p->val2; p->val2 *= p->mlt2; } if (flag) { if (asgsg) rs[n] = sg[n] * val; else rs[n] = *sg * val; } else { if (asgsg) rs[n] = sg[n]; else rs[n] = *sg; } } p->val = val; p->val2 = val; return OK; } int evxset(CSOUND *csound, ENVLPX *p) { FUNC *ftp; MYFLT ixmod, iatss, idur, prod, diff, asym, nk, denom, irise; int32 cnt1; MYFLT len = csound->curip->p3.value; if ((ftp = csound->FTFind(csound, p->ifn)) == NULL) return NOTOK; p->ftp = ftp; if ((idur = *p->idur) > FL(0.0)) { if (UNLIKELY((iatss = FABS(*p->iatss)) == FL(0.0))) { return csound->InitError(csound, "iatss = 0"); } if (iatss != FL(1.0) && (ixmod = *p->ixmod) != FL(0.0)) { if (UNLIKELY(FABS(ixmod) > FL(0.95))) { return csound->InitError(csound, Str("ixmod out of range.")); } ixmod = -SIN(SIN(ixmod)); prod = ixmod * iatss; diff = ixmod - iatss; denom = diff + prod + FL(1.0); if (denom == FL(0.0)) asym = FHUND; else { asym = FL(2.0) * prod / denom; if (FABS(asym) > FHUND) asym = FHUND; } iatss = (iatss - asym) / (FL(1.0) - asym); asym = asym* *(ftp->ftable + ftp->flen); /* +1 */ } else asym = FL(0.0); if ((irise = *p->irise) > FL(0.0)) { if (irise + *p->idec > len) csound->Warning(csound, Str("p3 too short in envlpx")); p->phs = 0; p->ki = (int32) (CS_KICVT / irise); p->val = *ftp->ftable; } else { p->phs = -1; p->val = *(ftp->ftable + ftp->flen)-asym; irise = FL(0.0); /* in case irise < 0 */ } if (UNLIKELY(!(*(ftp->ftable + ftp->flen)))) { return csound->InitError(csound, Str("rise func ends with zero")); } cnt1 = (int32) ((idur - irise - *p->idec) * CS_EKR + FL(0.5)); if (cnt1 < 0L) { cnt1 = 0; nk = CS_EKR; } else { if (*p->iatss < FL(0.0) || cnt1 <= 4L) nk = CS_EKR; else nk = (MYFLT) cnt1; } p->mlt1 = POWER(iatss, (FL(1.0)/nk)); if (*p->idec > FL(0.0)) { if (UNLIKELY(*p->iatdec <= FL(0.0))) { return csound->InitError(csound, Str("non-positive iatdec")); } p->mlt2 = POWER(*p->iatdec, (CS_ONEDKR / *p->idec)); } p->cnt1 = cnt1; p->asym = asym; } return OK; } int knvlpx(CSOUND *csound, ENVLPX *p) { FUNC *ftp; int32 phs; MYFLT fact, v1, fract, *ftab; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; /* RWD fix */ if ((phs = p->phs) >= 0) { fract = (MYFLT) PFRAC(phs); ftab = ftp->ftable + (phs >> ftp->lobits); v1 = *ftab++; fact = (v1 + (*ftab - v1) * fract); phs += p->ki; if (phs >= MAXLEN) { /* check that 2**N+1th pnt is good */ p->val = *(ftp->ftable + ftp->flen ); if (UNLIKELY(!p->val)) { return csound->PerfError(csound, p->h.insdshead, Str("envlpx rise func ends with zero")); } p->val -= p->asym; phs = -1L; } p->phs = phs; } else { fact = p->val; if (p->cnt1 > 0L) { p->val *= p->mlt1; fact += p->asym; p->cnt1--; if (p->cnt1 == 0L) p->val += p->asym; } else p->val *= p->mlt2; } *p->rslt = *p->xamp * fact; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("envlpx(krate): not initialised")); } int aevxset(CSOUND *csound, ENVLPX *p) { FUNC *ftp; MYFLT ixmod, iatss, idur, prod, diff, asym, nk, denom, irise; int32 cnt1; MYFLT len = csound->curip->p3.value; if ((ftp = csound->FTFind(csound, p->ifn)) == NULL) return NOTOK; p->ftp = ftp; if ((idur = *p->idur) > FL(0.0)) { if (UNLIKELY((iatss = FABS(*p->iatss)) == FL(0.0))) { return csound->InitError(csound, "iatss = 0"); } if (iatss != FL(1.0) && (ixmod = *p->ixmod) != FL(0.0)) { if (UNLIKELY(FABS(ixmod) > FL(0.95))) { return csound->InitError(csound, Str("ixmod out of range.")); } ixmod = -SIN(SIN(ixmod)); prod = ixmod * iatss; diff = ixmod - iatss; denom = diff + prod + FL(1.0); if (denom == FL(0.0)) asym = FHUND; else { asym = FL(2.0) * prod / denom; if (FABS(asym) > FHUND) asym = FHUND; } iatss = (iatss - asym) / (FL(1.0) - asym); asym = asym* *(ftp->ftable + ftp->flen); /* +1 */ } else asym = FL(0.0); if ((irise = *p->irise) > FL(0.0)) { if (irise + *p->idec > len) csound->Warning(csound, Str("p3 too short in envlpx")); p->phs = 0; p->ki = (int32) ((FMAXLEN / CS_ESR )/ irise); p->val = *ftp->ftable; } else { p->phs = -1; p->val = *(ftp->ftable + ftp->flen)-asym; irise = FL(0.0); /* in case irise < 0 */ } if (UNLIKELY(!(*(ftp->ftable + ftp->flen)))) { return csound->InitError(csound, Str("rise func ends with zero")); } cnt1 = (int32) ((idur - irise - *p->idec) * CS_ESR); if (cnt1 < 0L) { cnt1 = 0; nk = CS_ESR; } else { if (*p->iatss < FL(0.0) || cnt1 <= 4L) nk = CS_ESR; else nk = (MYFLT) cnt1; } p->mlt1 = POWER(iatss, (FL(1.0)/nk)); if (*p->idec > FL(0.0)) { if (UNLIKELY(*p->iatdec <= FL(0.0))) { return csound->InitError(csound, Str("non-positive iatdec")); } p->mlt2 = POWER(*p->iatdec, (csound->onedsr / *p->idec)); } p->cnt1 = cnt1; p->asym = asym; } return OK; } int envlpx(CSOUND *csound, ENVLPX *p) { int32 phs; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; long pos, lobits, lomask; MYFLT fact, *xamp, *rslt, val, asym, mlt, mlt2, v1, fract, *ftab, lodiv; int asgsg = IS_ASIG_ARG(p->xamp); xamp = p->xamp; rslt = p->rslt; val = p->val; mlt = p->mlt1; mlt2 = p->mlt2; asym = p->asym; if (UNLIKELY(p->ftp==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("envlpx(krate): not initialised")); ftab = p->ftp->ftable; lobits = p->ftp->lobits; lomask = p->ftp->lomask; lodiv = p->ftp->lodiv; if (UNLIKELY(ftab[p->ftp->flen] == 0.0)) return csound->PerfError(csound, p->h.insdshead, Str("envlpx rise func ends with zero")); if (UNLIKELY(offset)) memset(rslt, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rslt[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nphs) >= 0L) { fract = ((phs) & lomask) * lodiv; pos = (long) (phs >> lobits); v1 = ftab[pos+1]; fact = (v1 + (ftab[pos] - v1) * fract); phs += p->ki; if (phs >= MAXLEN) { val = ftab[p->ftp->flen]; val -= p->asym; phs = -1; } p->phs = phs; } else { fact = val; if (p->cnt1 > 0L) { val *= mlt; fact += asym; p->cnt1--; if (p->cnt1 == 0L) val += asym; } else val *= mlt2; } if (asgsg) rslt[n] = xamp[n] * fact; else rslt[n] = *xamp * fact; } p->val = val; return OK; } int evrset(CSOUND *csound, ENVLPR *p) { FUNC *ftp; MYFLT ixmod, iatss, prod, diff, asym, denom, irise; if ((ftp = csound->FTFind(csound, p->ifn)) == NULL) return NOTOK; p->ftp = ftp; if (UNLIKELY((iatss = FABS(*p->iatss)) == FL(0.0))) { return csound->InitError(csound, "iatss = 0"); } if (iatss != FL(1.0) && (ixmod = *p->ixmod) != FL(0.0)) { if (UNLIKELY(FABS(ixmod) > FL(0.95))) { return csound->InitError(csound, Str("ixmod out of range.")); } ixmod = -SIN(SIN(ixmod)); prod = ixmod * iatss; diff = ixmod - iatss; denom = diff + prod + FL(1.0); if (denom == FL(0.0)) asym = FHUND; else { asym = FL(2.0) * prod / denom; if (FABS(asym) > FHUND) asym = FHUND; } iatss = (iatss - asym) / (FL(1.0) - asym); asym = asym * *(ftp->ftable + ftp->flen); /* +1 */ } else asym = FL(0.0); if ((irise = *p->irise) > FL(0.0)) { p->phs = 0; p->ki = (int32) (CS_KICVT / irise); p->val = *ftp->ftable; } else { p->phs = -1; p->val = *(ftp->ftable + ftp->flen)-asym; /* irise = FL(0.0); */ /* in case irise < 0 */ } if (UNLIKELY(!(*(ftp->ftable + ftp->flen)))) { return csound->InitError(csound, Str("rise func ends with zero")); } p->mlt1 = POWER(iatss, CS_ONEDKR); if (*p->idec > FL(0.0)) { int32 rlscnt = (int32)(*p->idec * CS_EKR + FL(0.5)); if ((p->rindep = (int32)*p->irind)) p->rlscnt = rlscnt; else if (rlscnt > p->h.insdshead->xtratim) p->h.insdshead->xtratim = (int)rlscnt; if (UNLIKELY((p->atdec = *p->iatdec) <= FL(0.0) )) { return csound->InitError(csound, Str("non-positive iatdec")); } } p->asym = asym; p->rlsing = 0; return OK; } int aevrset(CSOUND *csound, ENVLPR *p) { FUNC *ftp; MYFLT ixmod, iatss, prod, diff, asym, denom, irise; if ((ftp = csound->FTFind(csound, p->ifn)) == NULL) return NOTOK; p->ftp = ftp; if (UNLIKELY((iatss = FABS(*p->iatss)) == FL(0.0))) { return csound->InitError(csound, "iatss = 0"); } if (iatss != FL(1.0) && (ixmod = *p->ixmod) != FL(0.0)) { if (UNLIKELY(FABS(ixmod) > FL(0.95))) { return csound->InitError(csound, Str("ixmod out of range.")); } ixmod = -SIN(SIN(ixmod)); prod = ixmod * iatss; diff = ixmod - iatss; denom = diff + prod + FL(1.0); if (denom == FL(0.0)) asym = FHUND; else { asym = FL(2.0) * prod / denom; if (FABS(asym) > FHUND) asym = FHUND; } iatss = (iatss - asym) / (FL(1.0) - asym); asym = asym * *(ftp->ftable + ftp->flen); /* +1 */ } else asym = FL(0.0); if ((irise = *p->irise) > FL(0.0)) { p->phs = 0; p->ki = (int32) ((FMAXLEN / CS_ESR)/ irise); p->val = *ftp->ftable; } else { p->phs = -1; p->val = *(ftp->ftable + ftp->flen)-asym; /* irise = FL(0.0); */ /* in case irise < 0 */ } if (UNLIKELY(!(*(ftp->ftable + ftp->flen)))) { return csound->InitError(csound, Str("rise func ends with zero")); } p->mlt1 = POWER(iatss, csound->onedsr); if (*p->idec > FL(0.0)) { int32 rlscnt = (int32)(*p->idec * CS_EKR + FL(0.5)); if ((p->rindep = (int32)*p->irind)) p->rlscnt = rlscnt; else if (rlscnt > p->h.insdshead->xtratim) p->h.insdshead->xtratim = (int)rlscnt; if (UNLIKELY((p->atdec = *p->iatdec) <= FL(0.0) )) { return csound->InitError(csound, Str("non-positive iatdec")); } } p->asym = asym; p->rlsing = 0; return OK; } int knvlpxr(CSOUND *csound, ENVLPR *p) { MYFLT fact; int32 rlscnt; if (!p->rlsing) { /* if not in reles seg */ if (p->h.insdshead->relesing) { p->rlsing = 1; /* if new flag, set mlt2 */ rlscnt = (p->rindep) ? p->rlscnt : p->h.insdshead->xtratim; if (rlscnt) p->mlt2 = POWER(p->atdec, FL(1.0)/rlscnt); else p->mlt2 = FL(1.0); } if (p->phs >= 0) { /* do fn rise for seg 1 */ FUNC *ftp = p->ftp; int32 phs = p->phs; MYFLT fract = PFRAC(phs); MYFLT *ftab = ftp->ftable + (phs >> ftp->lobits); MYFLT v1 = *ftab++; fact = (v1 + (*ftab - v1) * fract); phs += p->ki; if (phs < MAXLEN || p->rlsing) /* if more fn or beg rls */ p->val = fact; /* save cur val */ else { /* else prep for seg 2 */ p->val = *(ftp->ftable + ftp->flen) - p->asym; phs = -1L; } p->phs = phs; } else { fact = p->val + p->asym; /* do seg 2 with asym */ p->val *= p->mlt1; if (p->rlsing) /* if ending, rm asym */ p->val += p->asym; } } else fact = p->val *= p->mlt2; /* else do seg 3 decay */ *p->rslt = *p->xamp * fact; return OK; } int envlpxr(CSOUND *csound, ENVLPR *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 rlscnt; long lobits, lomask, pos, phs = p->phs; MYFLT fact, *xamp, *rslt, val, asym, mlt, v1, fract, *ftab, lodiv; int asgsg = IS_ASIG_ARG(p->xamp); xamp = p->xamp; rslt = p->rslt; val = p->val; mlt = p->mlt1; //mlt2 = p->mlt2; asym = p->asym; if (UNLIKELY(p->ftp==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("envlpx(krate): not initialised")); ftab = p->ftp->ftable; lobits = p->ftp->lobits; lomask = p->ftp->lomask; lodiv = p->ftp->lodiv; if (UNLIKELY(ftab[p->ftp->flen] == 0.0)) return csound->PerfError(csound, p->h.insdshead, Str("envlpx rise func ends with zero")); if (UNLIKELY(offset)) memset(rslt, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rslt[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nrlsing) { /* if not in reles seg */ if (p->h.insdshead->relesing) { p->rlsing = 1; /* if new flag, set mlt2 */ rlscnt = (p->rindep) ? p->rlscnt : p->h.insdshead->xtratim; rlscnt *= CS_KSMPS; if (rlscnt) p->mlt2 = POWER(p->atdec, FL(1.0)/rlscnt); else p->mlt2 = FL(1.0); } if (p->phs >= 0) { /* do fn rise for seg 1 */ fract = ((phs) & lomask) * lodiv; pos = (long) (phs >> lobits); v1 = ftab[pos+1]; fact = (v1 + (ftab[pos] - v1) * fract); phs += p->ki; if (phs >= MAXLEN) { val = ftab[p->ftp->flen]; val -= p->asym; phs = -1; } else val = fact; /* JPff: in case very early release */ p->phs = phs; } else { fact = val + asym; val *= mlt; if (p->rlsing) val += asym; } } else fact = val *= p->mlt2; /* else do seg 3 decay */ if (asgsg) rslt[n] = xamp[n] * fact; else rslt[n] = *xamp * fact; } p->val = val; return OK; } int csgset(CSOUND *csound, COSSEG *p) { SEG *segp, *sp; int nsegs; MYFLT **argp; double val, y1, y2; if (!(p->INCOUNT & 1)){ return csound->InitError(csound, Str("incomplete number of input arguments")); } /* count segs & alloc if nec */ nsegs = (p->INOCOUNT - (!(p->INOCOUNT & 1))) >> 1; //printf("nsegs = %d\n", nsegs); if ((segp = (SEG *) p->auxch.auxp) == NULL || nsegs*sizeof(SEG) < (unsigned int)p->auxch.size) { csound->AuxAlloc(csound, (int32)(1+nsegs)*sizeof(SEG), &p->auxch); p->cursegp = 1+(segp = (SEG *) p->auxch.auxp); segp[nsegs-1].cnt = MAXPOS; /* set endcount for safety */ segp[nsegs-1].acnt = MAXPOS; } sp = segp; argp = p->argums; y1 = val = (double)**argp++; if (UNLIKELY(**argp <= FL(0.0))) return OK; /* if idur1 <= 0, skip init */ p->curcnt = 0; p->cursegp = segp+1; /* else setup first seg */ p->segsrem = nsegs; //printf("current seg = %p segp = %p\n", p->cursegp, segp); do { /* init each seg .. */ double dur = (double)**argp++; segp->nxtpt = (double)**argp++; if (UNLIKELY((segp->cnt = (int32)(dur * CS_EKR + FL(0.5))) < 0)) segp->cnt = 0; if (UNLIKELY((segp->acnt = (int32)(dur * CS_ESR)) < 0)) segp->acnt = 0; //printf("i: %d(%p): cnt=%d nxtpt=%f\n", // p->segsrem-nsegs, segp, segp->cnt, segp->nxtpt); segp++; } while (--nsegs); p->y1 = y1; p->y2 = y2 = sp->nxtpt; p->x = 0.0; if (IS_ASIG_ARG(p->rslt)) { p->inc = (y2!=y1 ? 1.0/(sp->acnt) : 0.0); p->curcnt = sp->acnt; } else { p->inc = (y2!=y1 ? 1.0/(sp->cnt) : 0.0); p->curcnt = sp->cnt; } //printf("incx, y1,y2 = %g, %f, %f\n", p->inc, p->y1, p->y2); p->val = p->y1; return OK; } int csgset_bkpt(CSOUND *csound, COSSEG *p) { int32 cnt, bkpt = 0; int nsegs; int n; SEG *segp; n = csgset(csound, p); if (UNLIKELY(n!=0)) return n; cnt = p->curcnt; nsegs = p->segsrem-1; segp = p->cursegp; if (IS_ASIG_ARG(p->rslt)) do { if (UNLIKELY(cnt > segp->acnt)) return csound->InitError(csound, Str("Breakpoint %d not valid"), bkpt); segp->acnt -= cnt; cnt += segp->acnt; segp++; bkpt++; } while (--nsegs); else do { //csound->Message(csound, "%d/ %d: %d, %d ", nsegs, bkpt, cnt, segp->cnt); if (UNLIKELY(cnt > segp->cnt)) return csound->InitError(csound, Str("Breakpoint %d not valid"), bkpt); segp->cnt -= cnt; cnt += segp->cnt; //csound->Message(csound, "-> %d, %d %f\n", cnt, segp->cnt, segp->nxtpt); segp++; bkpt++; } while (--nsegs); return OK; } int csgrset(CSOUND *csound, COSSEG *p) { int32 relestim; if (csgset(csound,p) != 0) return NOTOK; relestim = (p->cursegp + p->segsrem-2)->cnt; p->xtra = relestim; if (relestim > p->h.insdshead->xtratim) p->h.insdshead->xtratim = (int)relestim; return OK; } int kosseg(CSOUND *csound, COSSEG *p) { double val1 = p->y1, val2 = p->y2, x = p->x; double inc = p->inc; if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; /* RWD fix */ if (LIKELY(p->segsrem)) { /* if no more segs putk */ if (--p->curcnt <= 0) { /* if done cur segment */ SEG *segp = p->cursegp; chk1: p->y1 = val1 = val2; if (UNLIKELY(!--p->segsrem)) { /* if none left */ p->y2 = val2 = segp->nxtpt; goto putk; /* put endval */ } //printf("new seg: %d %f\n", segp->cnt, segp->nxtpt); val2 = p->y2 = segp->nxtpt; /* Base of next segment */ inc = p->inc = (segp->cnt ? 1.0/(segp->cnt) : 0.0); x = 0.0; p->cursegp = segp+1; /* else find the next */ if (UNLIKELY(!(p->curcnt = segp->cnt))) { val2 = p->y2 = segp->nxtpt; /* nonlen = discontin */ inc = p->inc = (segp->cnt ? 1.0/(segp->cnt) : 0.0); goto chk1; } /* poslen = new slope */ } { double mu2 = (1.0-cos(x*PI))*0.5; *p->rslt = (MYFLT)(val1*(1.0-mu2)+val2*mu2); x += inc; } } else { putk: *p->rslt = (MYFLT)val1; } p->x = x; return OK; err1: return csound->InitError(csound, Str("cosseg not initialised (krate)\n")); } int cosseg(CSOUND *csound, COSSEG *p) { double val1 = p->y1, val2 = p->y2, x = p->x; MYFLT *rs = p->rslt; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; double inc = p->inc;///(nsmps-offset); if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; if (UNLIKELY(offset)) memset(rs, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rs[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nsegsrem)) { /* if no more segs putk */ if (--p->curcnt <= 0) { /* if done cur segment */ SEG *segp = p->cursegp; chk1: p->y1 = val1 = val2; if (UNLIKELY(!--p->segsrem)) { /* if none left */ p->y2 = val2 = segp->nxtpt; goto putk; /* put endval */ } val2 = p->y2 = segp->nxtpt; /* Base of next segment */ p->inc = (segp->acnt ? 1.0/(segp->acnt) : 0.0); x = 0.0; p->cursegp = segp+1; /* else find the next */ if (UNLIKELY(!(p->curcnt = segp->acnt))) { val2 = p->y2 = segp->nxtpt; /* nonlen = discontin */ p->inc = (segp->acnt ? 1.0/(segp->acnt) : 0.0); goto chk1; } /* poslen = new slope */ } double mu2 = (1.0-cos(x*PI))*0.5; rs[n] = (MYFLT)(val1*(1.0-mu2)+val2*mu2); x += inc; } else { putk: rs[n] = (MYFLT)val1; } } p->inc = inc; p->x = x; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("cosseg: not initialised (arate)\n")); } int cossegr(CSOUND *csound, COSSEG *p) { double val1 = p->y1, val2 = p->y2, x = p->x, val = p->val; MYFLT *rs = p->rslt; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t n, nsmps = CS_KSMPS; double inc = p->inc; memset(rs, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; for (n=offset; nsegsrem)) { /* if no more segs putk */ SEG *segp = p->cursegp; if (p->h.insdshead->relesing && p->segsrem > 1) { while (p->segsrem > 1) { /* release flag new: */ segp = ++p->cursegp; /* go to last segment */ p->segsrem--; } segp--; /* get univ relestim */ segp->acnt = (p->xtra >=0 ? p->xtra : p->h.insdshead->xtratim)*CS_KSMPS; //p->y1 = val1 = val2; p->y1 = val1 = val; //printf("%d(%p): cnt=%d strt= %f nxtpt=%f\n", // p->segsrem, segp, segp->cnt,val1, segp->nxtpt); goto newi; /* and set new curinc */ } if (p->segsrem == 1 && !p->h.insdshead->relesing) { goto putk; } if (--p->curcnt <= 0) { /* if done cur segment */ chk1: p->y1 = val1 = val2; if (UNLIKELY(!--p->segsrem)) { /* if none left */ p->y2 = val2 = segp->nxtpt; goto putk; /* put endval */ } newi: //printf("new seg: %d %f\n", segp->cnt, segp->nxtpt); val2 = p->y2 = segp->nxtpt; /* Base of next segment */ inc =p->inc = (segp->acnt ? 1.0/(segp->acnt) : 0.0); x = 0.0; p->cursegp = segp+1; /* else find the next */ if (UNLIKELY(!(p->curcnt = segp->acnt))) { val2 = p->y2 = segp->nxtpt; /* nonlen = discontin */ inc = p->inc = (segp->acnt ? 1.0/(segp->acnt) : 0.0); goto chk1; } /* poslen = new slope */ //printf("New segment incx, y1,y2 = %g, %f, %f\n", inc, val1, val2); } { double mu2 = (1.0-cos(x*PI))*0.5; val = rs[n] = (MYFLT)(val1*(1.0-mu2)+val2*mu2); x += inc; //if (x>1 || x<0) printf("x=%f out of range\n", x); } } else { putk: rs[n] = (MYFLT)val1; } } p->inc = inc; p->x = x; p->val = val; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("cossegr: not initialised (arate)\n")); } #if 0 int cossegr(CSOUND *csound, COSSEG *p) { double val1 = p->y1, val2 = p->y2, x = p->x; MYFLT *rs = p->rslt; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t n, nsmps = CS_KSMPS; double inc = p->inc/(nsmps-offset); memset(rs, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; if (LIKELY(p->segsrem)) { /* if no more segs putk */ SEG *segp = p->cursegp; if (p->h.insdshead->relesing && p->segsrem > 1) { while (p->segsrem > 1) { /* release flag new: */ segp = ++p->cursegp; /* go to last segment */ p->segsrem--; } /* get univ relestim */ segp->cnt = p->xtra >=0 ? p->xtra : p->h.insdshead->xtratim; goto newi; /* and set new curinc */ } if (--p->curcnt <= 0) { /* if done cur segment */ chk1: p->y1 = val1 = val2; if (UNLIKELY(!--p->segsrem)) { /* if none left */ p->y2 = val2 = segp->nxtpt; goto putk; /* put endval */ } newi: //printf("new seg: %d %f\n", segp->cnt, segp->nxtpt); val2 = p->y2 = segp->nxtpt; /* Base of next segment */ p->inc = (segp->cnt ? 1.0/(segp->cnt) : 0.0); inc /= nsmps; x = 0.0; p->cursegp = segp+1; /* else find the next */ if (UNLIKELY(!(p->curcnt = segp->cnt))) { val2 = p->y2 = segp->nxtpt; /* nonlen = discontin */ p->inc = (segp->cnt ? 1.0/(segp->cnt) : 0.0); inc /= nsmps; //printf("zero length: incx, y1,y2 = %f, %f, %f\n", inc, val1, val2); goto chk1; } /* poslen = new slope */ //printf("New segment incx, y1,y2 = %g, %f, %f\n", inc, val1, val2); } for (n=offset; n1 || x<0) printf("x=%f out of range\n", x); } } else { putk: //printf("ending at %f\n", val1); for (n=offset; nx = x; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("cossegr: not initialised (arate)\n")); } #endif int kcssegr(CSOUND *csound, COSSEG *p) { double val1 = p->y1, val2 = p->y2, x = p->x, val = p->val; double inc = p->inc; if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; /* RWD fix */ if (LIKELY(p->segsrem)) { /* if no more segs putk */ SEG *segp = p->cursegp; if (p->h.insdshead->relesing && p->segsrem > 1) { while (p->segsrem > 1) { /* reles flag new: */ segp = ++p->cursegp; /* go to last segment */ p->segsrem--; } segp--; /* get univ relestim */ segp->cnt = p->xtra>= 0 ? p->xtra : p->h.insdshead->xtratim; p->y1 = val1 = val; goto newi; /* and set new curinc */ } if (p->segsrem == 1 && !p->h.insdshead->relesing) { goto putk; } if (--p->curcnt <= 0) { /* if done cur segment */ chk1: p->y1 = val1 = val2; if (UNLIKELY(!--p->segsrem)) { /* if none left */ p->y2 = val2 = segp->nxtpt; goto putk; /* put endval */ } newi: val2 = p->y2 = segp->nxtpt; /* Base of next segment */ inc = p->inc = (segp->cnt ? 1.0/(segp->cnt) : 0.0); x = 0.0; p->cursegp = segp+1; /* else find the next */ if (UNLIKELY(!(p->curcnt = segp->cnt))) { val2 = p->y2 = segp->nxtpt; /* nonlen = discontin */ inc = p->inc = (segp->cnt ? 1.0/(segp->cnt) : 0.0); goto chk1; } /* poslen = new slope */ } { double mu2 = (1.0-cos(x*PI))*0.5; val = *p->rslt = (MYFLT)(val1*(1.0-mu2)+val2*mu2); x += inc; } } else { putk: *p->rslt = (MYFLT)val1; } p->x = x; p->val = val; return OK; err1: return csound->InitError(csound, Str("cosseg not initialised (krate)\n")); } csound-6.10.0/OOps/ugens2.c000066400000000000000000001525371321653344700153450ustar00rootroot00000000000000/* ugens2.c: Copyright (C) 1991 Barry Vercoe, John ffitch, Robin Whittle This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* UGENS2.C */ #include "ugens2.h" #include /* Macro form of Istvan's speedup ; constant should be 3fefffffffffffff */ /* #define FLOOR(x) (x >= FL(0.0) ? (long)x : (long)((double)x - 0.999999999999999)) */ /* 1.0-1e-8 is safe for a maximum table length of 16777216 */ /* 1.0-1e-15 could incorrectly round down large negative integers, */ /* because doubles do not have sufficient resolution for numbers like */ /* -1000.999999999999999 (FLOOR(-1000) might possibly be -1001 which is wrong)*/ /* it should be noted, though, that the above incorrect result would not be */ /* a problem in the case of interpolating table opcodes, as the fractional */ /* part would then be exactly 1.0, still giving a correct output value */ #define MYFLOOR(x) (x >= FL(0.0) ? (int32)x : (int32)((double)x - 0.99999999)) int phsset(CSOUND *csound, PHSOR *p) { MYFLT phs; int32 longphs; if ((phs = *p->iphs) >= FL(0.0)) { if (UNLIKELY((longphs = (int32)phs))) { csound->Warning(csound, Str("init phase truncation\n")); } p->curphs = phs - (MYFLT)longphs; } return OK; } int ephsset(CSOUND *csound, EPHSOR *p) { MYFLT phs; int32 longphs; if ((phs = *p->iphs) >= FL(0.0)) { if (UNLIKELY((longphs = (int32)phs))) { csound->Warning(csound, Str("init phase truncation\n")); } p->curphs = phs - (MYFLT)longphs; } p->b = 1.0; return OK; } int ephsor(CSOUND *csound, EPHSOR *p) { double phase; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *rs, *aphs, onedsr = csound->onedsr; double b = p->b; double incr, R = *p->kR; rs = p->sr; if (UNLIKELY(offset)) memset(rs, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rs[nsmps], '\0', early*sizeof(MYFLT)); } aphs = p->aphs; phase = p->curphs; if (IS_ASIG_ARG(p->xcps)) { MYFLT *cps = p->xcps; for (n=offset; n= 1.0)) { phase -= 1.0; b = pow(R, 1.0+phase); } else if (UNLIKELY(phase < 0.0)) { phase += 1.0; b = pow(R, 1.0+phase); } } } else { incr = (double)(*p->xcps * onedsr); for (n=offset; n= 1.0)) { phase -= 1.0; b = pow(R, 1.0+phase); } else if (UNLIKELY(phase < 0.0)) { phase += 1.0; b = pow(R, 1.0+phase); } } } p->curphs = phase; p->b = b; return OK; } int kphsor(CSOUND *csound, PHSOR *p) { double phs; *p->sr = (MYFLT)(phs = p->curphs); if (UNLIKELY((phs += (double)*p->xcps * CS_ONEDKR) >= 1.0)) phs -= 1.0; else if (UNLIKELY(phs < 0.0)) phs += 1.0; p->curphs = phs; return OK; } int phsor(CSOUND *csound, PHSOR *p) { double phase; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *rs, onedsr = csound->onedsr; double incr; rs = p->sr; if (UNLIKELY(offset)) memset(rs, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rs[nsmps], '\0', early*sizeof(MYFLT)); } phase = p->curphs; if (IS_ASIG_ARG(p->xcps)) { MYFLT *cps = p->xcps; for (n=offset; n= FL(1.0))) /* VL convert to MYFLT to avoid rounded output exceeding 1.0 on float version */ phase -= 1.0; else if (UNLIKELY((MYFLT)phase < FL(0.0))) phase += 1.0; } } else { incr = (double)(*p->xcps * onedsr); for (n=offset; n= FL(1.0))) { phase -= 1.0; } else if (UNLIKELY((MYFLT)phase < FL(0.0))) phase += 1.0; } } p->curphs = phase; return OK; } #ifdef SOME_FINE_DAY /*****************************************************************************/ /*****************************************************************************/ /* Table read code - see TABLE data structure in ugens2.h. */ /*************************************/ /* itblchk() * * This is called at init time by tblset() to set up the TABLE data * structure for subsequent k and a rate operations. * * It is also called at init time by itable() and itablei() prior to * them calling ktable() and ktabli() respectively to produce a single * result at init time. * * A similar function - ptblchk() does the same job, but reports * errors in a way suitable for performance time. */ /* If the specified table number can be found, then the purpose is to * read the three i rate input variables and the function table number * input variable - (which we can assume here is also i rate) to set * up the TABLE data structure ready for the k and a rate functions. */ static int itblchk(CSOUND *csound, TABLE *p) { if (UNLIKELY((p->ftp = csound->FTnp2Find(csound, p->xfn)) == NULL)) return NOTOK; /* Although TABLE has an integer variable for the table number * (p->pfn) we do not need to write it. We know that the k * and a rate functions which will follow will not be * expecting a changed table number. * * p->pfn exists only for checking table number changes for * functions which are expecting a k rate table number. */ /* Set denormalisation factor to 1 or table length, depending * on the state of ixmode. */ if (*p->ixmode) p->xbmul = p->ftp->flen; else p->xbmul = 1L; /* Multiply the ixoff value by the xbmul denormalisation * factor and then check it is between 0 and the table length. * * Bug fix: was p->offset * *p->ixoff */ if (UNLIKELY((p->offset = p->xbmul * *p->ixoff) < FL(0.0) || p->offset > p->ftp->flen)) { return csound->InitError(csound, Str("Offset %f < 0 or > tablelength"), p->offset); } p->wrap = (int)*p->iwrap; return OK; } /* ptblchk() * * This is called at init time by tblsetkt() to set up the TABLE data * structure for subsequent k and a rate operations which are * expecting the table number to change at k rate. * * tblsetkt() does very little - just setting up the wrap variable in * TABLE. All the other variables depend on the table number. This is * not available at init time, so the following 4 functions must look * for the changed table number and set up the variables accordingly - * generating error messages in a way which works at performance time. * * k rate a rate * * ktablekt tablekt Non interpolated * ktablikt tablikt Interpolated * */ static int ptblchk(CSOUND *csound, TABLE *p) { IGN(csound); /* Argument is needed to fit structure */ /* TABLE has an integer variable for the previous table number * (p->pfn). * * Now (at init time) we do not know the function table number * which will be provided at perf time, so set p->pfn to 0, so * that the k or a rate code will recognise that the first table * number is different from the "previous" one. */ p->pfn = 0; /* The only other thing to do is write the wrap value into the * immediate copy of it in TABLE. */ p->wrap = (int)*p->iwrap; return OK; } /*---------------------------------------------------------------------------*/ /* tblset() */ int tblset(CSOUND *csound, TABLE *p) { if (UNLIKELY(p->XINCODE != p->XOUTCODE)) { const char *opname = csound->GetOpcodeName(p); const char *msg = Str("%s: table index type inconsistent with output"); if (UNLIKELY(CS_KSMPS == 1)) csound->Warning(csound, msg, opname); else { return csound->InitError(csound, msg, opname); } } p->h.iopadr = (SUBR) itblchk; return itblchk(csound, p); } /* tblsetkt() */ int tblsetkt(CSOUND *csound, TABLE *p) { if (UNLIKELY(p->XINCODE != p->XOUTCODE)) { const char *opname = csound->GetOpcodeName(p); const char *msg = Str("%s: table index type inconsistent with output"); if (UNLIKELY(CS_KSMPS == 1)) csound->Warning(csound, msg, opname); else { return csound->InitError(csound, msg, opname); } } p->h.iopadr = (SUBR) ptblchk; return ptblchk(csound, p); } /*************************************/ /* Special functions to use when the output value is an init time * variable. * * These are called by the opodlst lines for itable and itablei ugens. * * They call itblchk() and if the table was found, they call the k * rate function just once. * * If the table was not found, an error will result from ftfind. */ int ktable(CSOUND *,TABLE*); int ktabli(CSOUND *,TABLE*); int ktabl3(CSOUND *,TABLE*); int itable(CSOUND *csound, TABLE *p) { if (LIKELY(itblchk(csound,p)==OK)) return ktable(csound,p); return NOTOK; } int itabli(CSOUND *csound, TABLE *p) { if (LIKELY(itblchk(csound,p)==OK)) return ktabli(csound,p); return NOTOK; } int itabl3(CSOUND *csound, TABLE *p) { if (LIKELY(itblchk(csound,p)==OK)) return ktabl3(csound,p); return NOTOK; } /*---------------------------------------------------------------------------*/ /* Functions which read the table. * * First we have the four basic functions for a and k rate, non * interpolated and interpolated reading. These all assume that the * TABLE data structure has been correctly set up - they are not * expecting the table number to change at k rate. * * These are: * k rate a rate * * ktable table Non interpolated * ktabli tabli Interpolated * ktabl3 tabl3 Interpolated with cubic * * Then we have four more functions which are expecting the table * number to change at k rate. They deal with this, and then call one * of the above functions to do the reading. * * These are: * k rate a rate * * ktablekt tablekt Non interpolated * ktablikt tablikt Interpolated * */ /* ktable() and ktabli() * --------------------- * * These both read a single value from the table. ktabli() does it * with interpolation. * * This is typically used for k rate reading - where they are called * as a result of being listed in a line in engineState.opcodlst. They are also * called by two functions which after they have coped with any change * in the k rate function table number. * * ktablekt() and ktablikt(). * * In addition, they can be called by the init time functions: * itable() and itabli(). * * * tablefn() and tabli() * ------------------- * * These do the reading at a rate with an a rate index. * * They are called directly via their entries in engineState.opcodlst, and also by * two functions which call them after they have coped with any change * in the k rate function table number. * * tablekt() and tablikt(). * * */ /*************************************/ /* ktable() */ int ktable(CSOUND *csound, TABLE *p) { FUNC *ftp; int32 indx, length; MYFLT ndx; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; /* RWD fix */ ndx = *p->xndx; length = ftp->flen; /* Multiply ndx by denormalisation factor, and add in the offset * - already denormalised - by tblchk(). * xbmul = 1 or table length depending on state of ixmode. */ ndx = (ndx * p->xbmul) + p->offset; /* ndx now includes the offset and is ready to address the table. * * The original code was: * indx = (long) (ndx + p->offset); * * This is a problem, causes problems with negative numbers. * */ indx = (int32) MYFLOOR((double)ndx); /* Now for "limit mode" - the "non-wrap" function, depending on * iwrap. * * The following section of code limits the final index to 0 and * the last location in the table. * * It is only used when wrap is OFF. The wrapping is achieved by * code after this - when this code is not run. */ if (!p->wrap) { /* Previously this code limited the upper range of the indx to * the table length - for instance 8. Then the result was ANDed * with a mask (for instance 7). * * This meant that when the input index was 8 or above, it got * reduced to 0. What we want is for it to stick at the index * which reads the last value from the table - in this example * from location 7. * * So instead of limiting to the table length, we limit to * (table length - 1). */ if (UNLIKELY(indx > length - 1)) indx = length - 1; /* Now limit negative values to zero. */ else if (UNLIKELY(indx < 0L)) indx = 0L; } /* The following code uses an AND with an integer like 0000 0111 * to wrap the current index within the range of the table. In * the original version, this code always ran, but with the new * (length - 1) code above, it would have no effect, so it is now * an else operation - running only when iwrap = 1. This may save * half a usec or so. */ else indx &= ftp->lenmask; /* Now find the address of the start of the table, add it to the * index, read the value from there and write it to the * destination. */ *p->rslt = *(ftp->ftable + indx); return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("table(krate): not initialised")); } /* tablefn() */ /* table() is similar to ktable() above, except that it processes an * array of input indexes, to send results to another array. These * arrays are ksmps long. */ /*sbrandon: NeXT m68k does not like 'table' */ int tablefn(CSOUND *csound, TABLE *p) { FUNC *ftp; MYFLT *rslt, *pxndx, *tab; int32 indx, mask, length; uint32_t koffset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT ndx, xbmul, offset; int wrap = p->wrap; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; /* RWD fix */ rslt = p->rslt; if (UNLIKELY(koffset)) memset(rslt, '\0', koffset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rslt[nsmps], '\0', early*sizeof(MYFLT)); } length = ftp->flen; pxndx = p->xndx; xbmul = (MYFLT)p->xbmul; offset = p->offset; mask = ftp->lenmask; tab = ftp->ftable; for (n=koffset; n length - 1)) indx = length - 1; else if (UNLIKELY(indx < (int32)0)) indx = 0L; } /* do the wrap code only if we are not doing the non-wrap code. */ else indx &= mask; rslt[n] = tab[indx]; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("table: not initialised")); } /* ktabli() */ /* ktabli() is similar to ktable() above, except that it uses the * fractional part of the final index to interpolate between one value * in the table and the next. * * This means that it may read the guard point. In a table of * "length" 8, the guardpoint is at locaton 8. The normal part of the * table is locations 0 to 7. * * In non-wrap mode, when the final index is negative, the output * should be the value in location 0. * * In non-wrap mode, when the final index is >= length, then the * output should be the value in the guard point location. */ int ktabli(CSOUND *csound, TABLE *p) { FUNC *ftp; int32 indx, length; MYFLT v1, v2, fract, ndx; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; ndx = *p->xndx; length = ftp->flen; /* Multiply ndx by denormalisation factor. * xbmul is 1 or table length depending on state of ixmode. * Add in the offset, which has already been denormalised by * tblchk(). */ ndx = (ndx * p->xbmul) + p->offset; indx = (int32) MYFLOOR((double)ndx); /* We need to generate a fraction - How much above indx is ndx? * It will be between 0 and just below 1.0. */ fract = ndx - indx; /* Start of changes to fix non- wrap bug. * * There are two changes here: * * 1 - We only run the wrap code if iwrap = 1. Previously it was * always run. * * 2 - The other change is similar in concept to limiting the * index to (length - 1) when in non-wrap mode. * * This would be fine - the fractional code would enable us to * interpolate using an index value which is almost as high as the * length of the table. This would be good for 7.99999 etc. * However, to be a little pedantic, what we want is for any index * of 8 or more to produce a result exactly equal to the value at * the guard point. * * We will let all (non negative) values which are less than * length pass through. This deals with all cases 0 to 7.9999 * . . . * * However we will look for final indexes of length (8) and above * and take the following steps: * * fract = 1 * indx = length - 1 * * We then continue with the rest of code. This causes the result * to be the value read from the guard point - which is what we * want. * * Likewise, if the final index is negative, set both fract and * indx to 0. */ if (!p->wrap) { if (UNLIKELY(ndx > length)) { indx = length - 1; fract = FL(1.0); } else if (UNLIKELY(indx < 0L)) { indx = 0L; fract = FL(0.0); } } /* We are in wrap mode, so do the wrap function. */ else indx &= ftp->lenmask; /* Now read the value at indx and the one beyond */ v1 = *(ftp->ftable + indx); v2 = *(ftp->ftable + indx + 1); *p->rslt = v1 + (v2 - v1) * fract; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("tablei(krate): not initialised")); } int ktabl3(CSOUND *csound, TABLE *p) { FUNC *ftp; int32 indx, length; MYFLT v1, v2, fract, ndx; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; ndx = *p->xndx; length = ftp->flen; /* Multiply ndx by denormalisation factor. * xbmul is 1 or table length depending on state of ixmode. * Add in the offset, which has already been denormalised by * tblchk(). */ ndx = (ndx * p->xbmul) + p->offset; indx = (int32) MYFLOOR((double)ndx); /* We need to generate a fraction - How much above indx is ndx? * It will be between 0 and just below 1.0. */ fract = ndx - indx; /* Start of changes to fix non- wrap bug. * * There are two changes here: * * 1 - We only run the wrap code if iwrap = 1. Previously it was * always run. * * 2 - The other change is similar in concept to limiting the * index to (length - 1) when in non-wrap mode. * * This would be fine - the fractional code would enable us to * interpolate using an index value which is almost as high as the * length of the table. This would be good for 7.99999 etc. * However, to be a little pedantic, what we want is for any index * of 8 or more to produce a result exactly equal to the value at * the guard point. * * We will let all (non negative) values which are less than * length pass through. This deals with all cases 0 to 7.9999 * . . . * * However we will look for final indexes of length (8) and above * and take the following steps: * * fract = 1 * indx = length - 1 * * We then continue with the rest of code. This causes the result * to be the value read from the guard point - which is what we * want. * * Likewise, if the final index is negative, set both fract and * indx to 0. */ if (!p->wrap) { if (UNLIKELY(ndx > length)) { indx = length - 1; fract = FL(1.0); } else if (UNLIKELY(indx < 0L)) { indx = 0L; fract = FL(0.0); } } /* We are in wrap mode, so do the wrap function. */ else indx &= ftp->lenmask; /* interpolate with cubic if we can, else linear */ if (UNLIKELY(indx<1 || indx==length-1 || length <4)) { v1 = *(ftp->ftable + indx); v2 = *(ftp->ftable + indx + 1); *p->rslt = v1 + (v2 - v1) * fract; } else { MYFLT *tab = ftp->ftable; MYFLT ym1 = tab[indx-1], y0 = tab[indx]; MYFLT y1 = tab[indx+1], y2 = tab[indx+2]; MYFLT frsq = fract*fract; MYFLT frcu = frsq*ym1; MYFLT t1 = y2 + y0+y0+y0; *p->rslt = y0 + FL(0.5)*frcu + fract*(y1 - frcu/FL(6.0) - t1/FL(6.0) - ym1/FL(3.0)) + frsq*fract*(t1/FL(6.0) - FL(0.5)*y1) + frsq*(FL(0.5)* y1 - y0); } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("table3(krate): not initialised")); } /* tabli() */ /* tabli() is similar to ktabli() above, except that it processes an * array of input indexes, to send results to another array. */ int tabli(CSOUND *csound, TABLE *p) { FUNC *ftp; int32 indx, mask, length; uint32_t koffset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *rslt, *pxndx, *tab; MYFLT fract, v1, v2, ndx, xbmul, offset; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; rslt = p->rslt; if (UNLIKELY(koffset)) memset(rslt, '\0', koffset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rslt[nsmps], '\0', early*sizeof(MYFLT)); } length = ftp->flen; pxndx = p->xndx; xbmul = (MYFLT)p->xbmul; offset = p->offset; mask = ftp->lenmask; tab = ftp->ftable; /* As for ktabli() code to handle non wrap mode, and wrap mode. */ if (!p->wrap) { for (n=koffset; n= length)) { rslt[n] = tab[length]; continue; } /* We need to generate a fraction - How much above indx is ndx? * It will be between 0 and just below 1.0. */ fract = ndx - indx; /* As for ktabli(), read two values and interpolate between * them. */ v1 = tab[indx]; v2 = tab[indx + 1]; rslt[n] = v1 + (v2 - v1)*fract; } } else { /* wrap mode */ for (n=koffset; nPerfError(csound, p->h.insdshead, Str("tablei: not initialised")); } int tabl3(CSOUND *csound, TABLE *p) /* Like tabli but cubic interpolation */ { FUNC *ftp; int32 indx, mask, length; uint32_t koffset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *rslt, *pxndx, *tab; MYFLT fract, v1, v2, ndx, xbmul, offset; int wrap = p->wrap; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; rslt = p->rslt; if (UNLIKELY(koffset)) memset(rslt, '\0', koffset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rslt[nsmps], '\0', early*sizeof(MYFLT)); } length = ftp->flen; pxndx = p->xndx; xbmul = (MYFLT)p->xbmul; offset = p->offset; mask = ftp->lenmask; tab = ftp->ftable; for (n=koffset; n length)) { indx = length - 1; fract = FL(1.0); } else if (UNLIKELY(indx < 0L)) { indx = 0L; fract = FL(0.0); } } else indx &= mask; /* interpolate with cubic if we can */ if (UNLIKELY(indx <1 || indx == length-1 || length<4)) { /* Too short or at ends */ v1 = tab[indx]; v2 = tab[indx + 1]; rslt[n] = v1 + (v2 - v1)*fract; } else { MYFLT ym1 = tab[indx-1], y0 = tab[indx]; MYFLT y1 = tab[indx+1], y2 = tab[indx+2]; MYFLT frsq = fract*fract; MYFLT frcu = frsq*ym1; MYFLT t1 = y2 + y0+y0+y0; rslt[n] = y0 + FL(0.5)*frcu + fract*(y1 - frcu/FL(6.0) - t1/FL(6.0) - ym1/FL(3.0)) + frsq*fract*(t1/FL(6.0) - FL(0.5)*y1) + frsq*(FL(0.5)* y1 - y0); } } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("table3: not initialised")); } /*************************************/ /* Four functions to call the above four, after handling the k rate * table number variable. * * tblsetkt() does very little - just setting up the wrap variable in * TABLE. All the other variables depend on the table number. This is * not available at init time, so the following 4 functions must look * for the changed table number and set up the variables accordingly - * generating error messages in a way which works at performance time. * * k rate a rate * * ktablekt tablekt Non interpolated * ktablikt tablikt Interpolated * * Since these perform identical operations, apart from the function * they call, create a common function to do this work: * * ftkrchk() */ static int ftkrchk(CSOUND *csound, TABLE *p) { /* Check the table number is >= 1. Print error and deactivate if * it is not. Return NOTOK to tell calling function not to proceed * with a or k rate operations. * * We must do this to catch the situation where the first call has * a table number of 0, and since that equals pfn, we would * otherwise proceed without checking the table number - and none * of the pointers would have been set up. */ if (*p->xfn < 1) goto err1; /* Check to see if table number has changed from previous value. * On the first run through, the previous value will be 0. */ if (p->pfn != (int32)*p->xfn) { /* If it is different, check to see if the table exists. * * If it doesn't, an error message should be produced by * csoundFTFindP() which should also deactivate the instrument. * * Return 0 to tell calling function not to proceed with a or * k rate operations. */ if (UNLIKELY((p->ftp = csound->FTFindP(csound, p->xfn) ) == NULL)) { return NOTOK; } /* p->ftp now points to the FUNC data structure of the newly * selected table. * * Now we set up some variables in TABLE ready for the k or a * rate functions which follow. */ /* Write the integer version of the table number into pfn so * we can later decide whether subsequent calls to the k and a * rate functions occur with a table number value which points * to a different table. */ p->pfn = (int32)*p->xfn; /* Set denormalisation factor to 1 or table length, depending * on the state of ixmode. */ if (*p->ixmode) p->xbmul = p->ftp->flen; else p->xbmul = 1L; /* Multiply the ixoff value by the xbmul denormalisation * factor and then check it is between 0 and the table length. */ if (UNLIKELY((p->offset = p->xbmul * *p->ixoff) < FL(0.0) || p->offset > p->ftp->flen)) goto err2; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("k rate function table no. %f < 1"), *p->xfn); err2: return csound->PerfError(csound, p->h.insdshead, Str("Offset %f < 0 or > tablelength"), p->offset); } /* Now for the four functions, which are called as a result of being * listed in engineState.opcodlst in entry.c */ int ktablekt(CSOUND *csound, TABLE *p) { if (LIKELY(ftkrchk(csound,p)==OK)) return ktable(csound,p); return NOTOK; } int tablekt(CSOUND *csound, TABLE *p) { if (LIKELY(ftkrchk(csound,p)==OK)) return tablefn(csound,p); return NOTOK; } int ktablikt(CSOUND *csound, TABLE *p) { if (LIKELY(ftkrchk(csound,p)==OK)) return ktabli(csound,p); return NOTOK; } int tablikt(CSOUND *csound, TABLE *p) { if (LIKELY(ftkrchk(csound,p)==OK)) return tabli(csound,p); return NOTOK; } int ktabl3kt(CSOUND *csound, TABLE *p) { if (LIKELY(ftkrchk(csound,p)==OK)) return ktabl3(csound,p); return NOTOK; } int tabl3kt(CSOUND *csound, TABLE *p) { if (LIKELY(ftkrchk(csound,p)==OK)) return tabl3(csound,p); return NOTOK; } #endif /* SOME_FINE_DAY */ int ko1set(CSOUND *csound, OSCIL1 *p) { FUNC *ftp; if (UNLIKELY((ftp = csound->FTFind(csound, p->ifn)) == NULL)) return NOTOK; if (UNLIKELY(*p->idur <= FL(0.0))) { /*csound->Warning(csound, Str("duration < zero\n"));*/ p->phs = MAXLEN-1; } else p->phs = 0; p->ftp = ftp; p->dcnt = (int32)(*p->idel * CS_EKR); p->kinc = (int32) (CS_KICVT / *p->idur); if (p->kinc==0) p->kinc = 1; return OK; } int kosc1(CSOUND *csound, OSCIL1 *p) { FUNC *ftp; int32 phs, dcnt; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; phs = p->phs; *p->rslt = *(ftp->ftable + (phs >> ftp->lobits)) * *p->kamp; if ((dcnt = p->dcnt) > 0) dcnt--; else if (dcnt == 0) { phs += p->kinc; if (UNLIKELY(phs >= MAXLEN)){ phs = MAXLEN; dcnt--; } else if (UNLIKELY(phs < 0)){ phs = 0; dcnt--; } p->phs = phs; } p->dcnt = dcnt; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("oscil1(krate): not initialised")); } int kosc1i(CSOUND *csound, OSCIL1 *p) { FUNC *ftp; MYFLT fract, v1, *ftab; int32 phs, dcnt; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; phs = p->phs; fract = PFRAC(phs); ftab = ftp->ftable + (phs >> ftp->lobits); v1 = *ftab++; *p->rslt = (v1 + (*ftab - v1) * fract) * *p->kamp; if ((dcnt = p->dcnt) > 0) { dcnt--; p->dcnt = dcnt; } else if (dcnt == 0) { phs += p->kinc; if (UNLIKELY(phs >= MAXLEN)) { phs = MAXLEN; dcnt--; p->dcnt = dcnt; } else if (UNLIKELY(phs < 0)){ phs = 0; dcnt--; } p->phs = phs; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("oscil1i(krate): not initialised")); } int oscnset(CSOUND *csound, OSCILN *p) { FUNC *ftp; if (LIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) != NULL)) { p->ftp = ftp; p->inc = ftp->flen * *p->ifrq * csound->onedsr; p->index = FL(0.0); p->maxndx = ftp->flen - FL(1.0); p->ntimes = (int32)*p->itimes; return OK; } else return NOTOK; } int osciln(CSOUND *csound, OSCILN *p) { MYFLT *rs = p->rslt; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(p->ftp==NULL)) goto err1; if (UNLIKELY(offset)) memset(rs, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rs[nsmps], '\0', early*sizeof(MYFLT)); } if (p->ntimes) { MYFLT *ftbl = p->ftp->ftable; MYFLT amp = *p->kamp; MYFLT ndx = p->index; MYFLT inc = p->inc; MYFLT maxndx = p->maxndx; for (n=offset; n maxndx)) { if (--p->ntimes) ndx -= maxndx; else if (UNLIKELY(n==nsmps)) return OK; else goto putz; } } p->index = ndx; } else { n=0; /* Can jump out of previous loop into this one */ putz: memset(&rs[n], 0, (nsmps-n)*sizeof(MYFLT)); /* for (; nPerfError(csound, p->h.insdshead, Str("osciln: not initialised")); } static int fill_func_from_array(ARRAYDAT *a, FUNC *f) { int lobits, ltest, flen, i; int nonpowof2_flag = 0; flen = f->flen = a->sizes[0]; flen &= -2L; for (ltest = flen, lobits = 0; (ltest & MAXLEN) == 0L; lobits++, ltest <<= 1) ; if (UNLIKELY(ltest != MAXLEN)) { lobits = 0; nonpowof2_flag = 1; } f->ftable = a->data; f->lenmask = ((flen & (flen - 1L)) ? 0L : (flen - 1L)); /* init hdr w powof2 data */ f->lobits = lobits; i = (1 << lobits); f->lomask = (int32) (i - 1); f->lodiv = FL(1.0) / (MYFLT) i; /* & other useful vals */ f->nchanls = 1; /* presume mono for now */ f->flenfrms = flen; if (nonpowof2_flag) f->lenmask = 0xFFFFFFFF; return OK; } int oscsetA(CSOUND *csound, OSC *p) { FUNC *ftp = &p->FF; int x; if (*p->iphs >= 0) p->lphs = ((int32)(*p->iphs * FMAXLEN)) & PHMASK; //check p->ifn is a valid array with power-of-two length x = ((ARRAYDAT*)p->ifn)->sizes[0]; if (LIKELY((x != 0) && !(x & (x - 1)))) { p->ftp = ftp; fill_func_from_array((ARRAYDAT*)p->ifn, ftp); return OK; } else return csound->InitError(csound, "array size not pow-of-two \n"); } int oscset(CSOUND *csound, OSC *p) { FUNC *ftp; if (LIKELY((ftp = csound->FTFind(csound, p->ifn)) != NULL)) { p->ftp = ftp; if (*p->iphs >= 0) p->lphs = ((int32)(*p->iphs * FMAXLEN)) & PHMASK; return OK; } return NOTOK; } int koscil(CSOUND *csound, OSC *p) { FUNC *ftp; int32 phs, inc; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; phs = p->lphs; inc = (int32) (*p->xcps * CS_KICVT); *p->sr = ftp->ftable[phs >> ftp->lobits] * *p->xamp; phs += inc; phs &= PHMASK; p->lphs = phs; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("oscil(krate): not initialised")); } int osckk(CSOUND *csound, OSC *p) { FUNC *ftp; MYFLT amp, *ar, *ftbl; int32 phs, inc, lobits; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; ftbl = ftp->ftable; phs = p->lphs; inc = MYFLT2LONG(*p->xcps * csound->sicvt); lobits = ftp->lobits; amp = *p->xamp; ar = p->sr; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;n> lobits] * amp; /* phs += inc; */ /* phs &= PHMASK; */ phs = (phs+inc)&PHMASK; } p->lphs = phs; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("oscil: not initialised")); } int oscka(CSOUND *csound, OSC *p) { FUNC *ftp; MYFLT *ar, amp, *cpsp, *ftbl; int32 phs, lobits; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT sicvt = csound->sicvt; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; ftbl = ftp->ftable; lobits = ftp->lobits; amp = *p->xamp; cpsp = p->xcps; phs = p->lphs; ar = p->sr; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;n> lobits] * amp; phs += inc; phs &= PHMASK; } p->lphs = phs; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("oscil: not initialised")); } int oscak(CSOUND *csound, OSC *p) { FUNC *ftp; MYFLT *ar, *ampp, *ftbl; int32 phs, inc, lobits; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; ftbl = ftp->ftable; lobits = ftp->lobits; phs = p->lphs; inc = MYFLT2LONG(*p->xcps * csound->sicvt); ampp = p->xamp; ar = p->sr; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;n> lobits] * ampp[n]; phs = (phs+inc) & PHMASK; } p->lphs = phs; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("oscil: not initialised")); } int oscaa(CSOUND *csound, OSC *p) { FUNC *ftp; MYFLT *ar, *ampp, *cpsp, *ftbl; int32 phs, lobits; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT sicvt = csound->sicvt; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; ftbl = ftp->ftable; lobits = ftp->lobits; phs = p->lphs; ampp = p->xamp; cpsp = p->xcps; ar = p->sr; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;n> lobits] * ampp[n]; phs = (phs+inc) & PHMASK; } p->lphs = phs; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("oscil: not initialised")); } int koscli(CSOUND *csound, OSC *p) { FUNC *ftp; int32 phs, inc; MYFLT *ftab, fract, v1; phs = p->lphs; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; fract = PFRAC(phs); ftab = ftp->ftable + (phs >> ftp->lobits); v1 = ftab[0]; *p->sr = (v1 + (ftab[1] - v1) * fract) * *p->xamp; inc = (int32)(*p->xcps * CS_KICVT); phs += inc; phs &= PHMASK; p->lphs = phs; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("oscili(krate): not initialised")); } int osckki(CSOUND *csound, OSC *p) { FUNC *ftp; MYFLT fract, v1, amp, *ar, *ft, *ftab; int32 phs, inc, lobits; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY((ftp = p->ftp)==NULL)) goto err1; lobits = ftp->lobits; phs = p->lphs; inc = MYFLT2LONG(*p->xcps * csound->sicvt); amp = *p->xamp; ar = p->sr; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } ft = ftp->ftable; for (n=offset; n> lobits); v1 = ftab[0]; ar[n] = (v1 + (ftab[1] - v1) * fract) * amp; phs = (phs+inc) & PHMASK; } p->lphs = phs; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("oscili: not initialised")); } int osckai(CSOUND *csound, OSC *p) { FUNC *ftp; MYFLT *ar, amp, *cpsp, fract, v1, *ftab, *ft; int32 phs, lobits; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT sicvt = csound->sicvt; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; lobits = ftp->lobits; amp = *p->xamp; cpsp = p->xcps; phs = p->lphs; ar = p->sr; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } ft = ftp->ftable; for (n=offset;n> lobits); v1 = ftab[0]; ar[n] = (v1 + (ftab[1] - v1) * fract) * amp; phs += inc; phs &= PHMASK; } p->lphs = phs; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("oscili: not initialised")); } int oscaki(CSOUND *csound, OSC *p) { FUNC *ftp; MYFLT v1, fract, *ar, *ampp, *ftab, *ft; int32 phs, inc, lobits; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; lobits = ftp->lobits; phs = p->lphs; inc = MYFLT2LONG(*p->xcps * csound->sicvt); ampp = p->xamp; ar = p->sr; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } ft = ftp->ftable; for (n=offset;n> lobits); v1 = ftab[0]; ar[n] = (v1 + (ftab[1] - v1) * fract) * ampp[n]; phs = (phs+inc) & PHMASK; } p->lphs = phs; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("oscili: not initialised")); } int oscaai(CSOUND *csound, OSC *p) { FUNC *ftp; MYFLT v1, fract, *ar, *ampp, *cpsp, *ftab, *ft; int32 phs, lobits; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT sicvt = csound->sicvt; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; ft = ftp->ftable; lobits = ftp->lobits; phs = p->lphs; ampp = p->xamp; cpsp = p->xcps; ar = p->sr; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;n> lobits); v1 = ftab[0]; ar[n] = (v1 + (ftab[1] - v1) * fract) * ampp[n]; phs = (phs+inc) & PHMASK; } p->lphs = phs; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("oscili: not initialised")); } int koscl3(CSOUND *csound, OSC *p) { FUNC *ftp; int32 phs, inc; MYFLT *ftab, fract; int32 x0; MYFLT y0, y1, ym1, y2, amp = *p->xamp; phs = p->lphs; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; ftab = ftp->ftable; fract = PFRAC(phs); x0 = (phs >> ftp->lobits); x0--; if (UNLIKELY(x0<0)) { ym1 = ftab[ftp->flen-1]; x0 = 0; } else ym1 = ftab[x0++]; y0 = ftab[x0++]; y1 = ftab[x0++]; if (UNLIKELY(x0>(int32)ftp->flen)) y2 = ftab[1]; else y2 = ftab[x0]; { MYFLT frsq = fract*fract; MYFLT frcu = frsq*ym1; MYFLT t1 = y2 + y0+y0+y0; *p->sr = amp * (y0 + FL(0.5)*frcu + fract*(y1 - frcu/FL(6.0) - t1/FL(6.0) - ym1/FL(3.0)) + frsq*fract*(t1/FL(6.0) - FL(0.5)*y1) + frsq*(FL(0.5)* y1 - y0)); } inc = (int32)(*p->xcps * CS_KICVT); phs += inc; phs &= PHMASK; p->lphs = phs; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("oscil3(krate): not initialised")); } int osckk3(CSOUND *csound, OSC *p) { FUNC *ftp; MYFLT fract, amp, *ar, *ftab; int32 phs, inc, lobits; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 x0; MYFLT y0, y1, ym1, y2; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; ftab = ftp->ftable; lobits = ftp->lobits; phs = p->lphs; inc = MYFLT2LONG(*p->xcps * csound->sicvt); amp = *p->xamp; ar = p->sr; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;n> lobits); x0--; if (UNLIKELY(x0<0)) { ym1 = ftab[ftp->flen-1]; x0 = 0; } else ym1 = ftab[x0++]; y0 = ftab[x0++]; y1 = ftab[x0++]; if (UNLIKELY(x0>(int32)ftp->flen)) y2 = ftab[1]; else y2 = ftab[x0]; /* printf("fract = %f; y = %f, %f, %f, %f\n", fract,ym1,y0,y1,y2); */ { MYFLT frsq = fract*fract; MYFLT frcu = frsq*ym1; MYFLT t1 = y2 + y0+y0+y0; /* MYFLT old = (y0 + (y1 - y0) * fract) * amp; */ /* double x = ((double)(x0-2)+fract)*twopi/32.0; */ /* MYFLT tr = amp*sin(x); */ ar[n] = amp * (y0 + FL(0.5)*frcu + fract*(y1 - frcu/FL(6.0) - t1/FL(6.0) - ym1/FL(3.0)) + frsq*fract*(t1/FL(6.0) - FL(0.5)*y1) + frsq*(FL(0.5)* y1 - y0)); /* printf("oscilkk3: old=%.4f new=%.4f true=%.4f (%f; %f)\n", */ /* old, *(ar-1), tr, fabs(*(ar-1)-tr), fabs(old-tr)); */ } phs = (phs+inc) & PHMASK; } p->lphs = phs; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("oscil3: not initialised")); } int oscka3(CSOUND *csound, OSC *p) { FUNC *ftp; MYFLT *ar, amp, *cpsp, fract, *ftab; int32 phs, lobits; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 x0; MYFLT y0, y1, ym1, y2; MYFLT sicvt = csound->sicvt; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; ftab = ftp->ftable; lobits = ftp->lobits; amp = *p->xamp; cpsp = p->xcps; phs = p->lphs; ar = p->sr; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;n> lobits); x0--; if (UNLIKELY(x0<0)) { ym1 = ftab[ftp->flen-1]; x0 = 0; } else ym1 = ftab[x0++]; y0 = ftab[x0++]; y1 = ftab[x0++]; if (UNLIKELY(x0>(int32)ftp->flen)) y2 = ftab[1]; else y2 = ftab[x0]; { MYFLT frsq = fract*fract; MYFLT frcu = frsq*ym1; MYFLT t1 = y2 + y0+y0+y0; ar[n] = amp * (y0 + FL(0.5)*frcu + fract*(y1 - frcu/FL(6.0) - t1/FL(6.0) - ym1/FL(3.0)) + frsq*fract*(t1/FL(6.0) - FL(0.5)*y1) + frsq*(FL(0.5)* y1 - y0)); } phs = (phs+inc) & PHMASK; } p->lphs = phs; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("oscil3: not initialised")); } int oscak3(CSOUND *csound, OSC *p) { FUNC *ftp; MYFLT fract, *ar, *ampp, *ftab; int32 phs, inc, lobits; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 x0; MYFLT y0, y1, ym1, y2; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; ftab = ftp->ftable; lobits = ftp->lobits; phs = p->lphs; inc = MYFLT2LONG(*p->xcps * csound->sicvt); ampp = p->xamp; ar = p->sr; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;n> lobits); x0--; if (UNLIKELY(x0<0)) { ym1 = ftab[ftp->flen-1]; x0 = 0; } else ym1 = ftab[x0++]; y0 = ftab[x0++]; y1 = ftab[x0++]; if (UNLIKELY(x0>(int32)ftp->flen)) y2 = ftab[1]; else y2 = ftab[x0]; { MYFLT frsq = fract*fract; MYFLT frcu = frsq*ym1; MYFLT t1 = y2 + y0+y0+y0; ar[n] = ampp[n] *(y0 + FL(0.5)*frcu + fract*(y1 - frcu/FL(6.0) - t1/FL(6.0) - ym1/FL(3.0)) + frsq*fract*(t1/FL(6.0) - FL(0.5)*y1) + frsq*(FL(0.5)* y1 - y0)); } phs = (phs+inc) & PHMASK; } p->lphs = phs; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("oscil3: not initialised")); } int oscaa3(CSOUND *csound, OSC *p) { FUNC *ftp; MYFLT fract, *ar, *ampp, *cpsp, *ftab; int32 phs, lobits; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 x0; MYFLT y0, y1, ym1, y2; MYFLT sicvt = csound->sicvt; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; ftab = ftp->ftable; lobits = ftp->lobits; phs = p->lphs; ampp = p->xamp; cpsp = p->xcps; ar = p->sr; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;n> lobits); x0--; if (UNLIKELY(x0<0)) { ym1 = ftab[ftp->flen-1]; x0 = 0; } else ym1 = ftab[x0++]; y0 = ftab[x0++]; y1 = ftab[x0++]; if (UNLIKELY(x0>(int32)ftp->flen)) y2 = ftab[1]; else y2 = ftab[x0]; { MYFLT frsq = fract*fract; MYFLT frcu = frsq*ym1; MYFLT t1 = y2 + y0+y0+y0; ar[n] = ampp[n] *(y0 + FL(0.5)*frcu + fract*(y1 - frcu/FL(6.0) - t1/FL(6.0) - ym1/FL(3.0)) + frsq*fract*(t1/FL(6.0) - FL(0.5)*y1) + frsq*(FL(0.5)* y1 - y0)); } phs = (phs+inc) & PHMASK; } p->lphs = phs; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("oscil3: not initialised")); } csound-6.10.0/OOps/ugens3.c000066400000000000000000000704011321653344700153330ustar00rootroot00000000000000/* ugens3.c: Copyright (C) 1991 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* UGENS3.C */ #include "ugens3.h" #include int foscset(CSOUND *csound, FOSC *p) { FUNC *ftp; if (LIKELY((ftp = csound->FTFind(csound, p->ifn)) != NULL)) { p->ftp = ftp; if (*p->iphs >= 0) p->cphs = p->mphs = (int32)(*p->iphs * FMAXLEN); p->ampcod = IS_ASIG_ARG(p->xamp) ? 1 : 0; p->carcod = IS_ASIG_ARG(p->xcar) ? 1 : 0; p->modcod = IS_ASIG_ARG(p->xmod) ? 1 : 0; return OK; } return NOTOK; } int foscil(CSOUND *csound, FOSC *p) { FUNC *ftp; MYFLT *ar, *ampp, *modp, cps, amp; MYFLT xcar, xmod, *carp, car, fmod, cfreq, mod, ndx, *ftab; int32 mphs, cphs, minc, cinc, lobits; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT sicvt = csound->sicvt; ar = p->rslt; ftp = p->ftp; if (UNLIKELY(ftp == NULL)) goto err1; ftab = ftp->ftable; lobits = ftp->lobits; mphs = p->mphs; cphs = p->cphs; ampp = p->xamp; cps = *p->kcps; carp = p->xcar; modp = p->xmod; amp = *ampp; xcar = *carp; xmod = *modp; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } if (p->ampcod || p->carcod || p->modcod) { for (n=offset;nampcod) amp = ampp[n]; if (p->carcod) xcar = carp[n]; if (p->modcod) xmod = modp[n]; car = cps * xcar; mod = cps * xmod; ndx = *p->kndx * mod; minc = (int32)(mod * sicvt); mphs &= PHMASK; fmod = *(ftab + (mphs >>lobits)) * ndx; mphs += minc; cfreq = car + fmod; cinc = (int32)(cfreq * sicvt); cphs &= PHMASK; ar[n] = *(ftab + (cphs >>lobits)) * amp; cphs += cinc; } } else { MYFLT amp = *ampp; cps = *p->kcps; car = cps * *carp; mod = cps * *modp; ndx = *p->kndx * mod; minc = (int32)(mod * sicvt); for (n=offset;n>lobits)) * ndx; mphs += minc; cfreq = car + fmod; cinc = (int32)(cfreq * sicvt); cphs &= PHMASK; ar[n] = *(ftab + (cphs >>lobits)) * amp; cphs += cinc; } } p->mphs = mphs; p->cphs = cphs; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("foscil: not initialised")); } int foscili(CSOUND *csound, FOSC *p) { FUNC *ftp; MYFLT *ar, *ampp, amp, cps, fract, v1, car, fmod, cfreq, mod; MYFLT *carp, *modp, xcar, xmod, ndx, *ftab; int32 mphs, cphs, minc, cinc, lobits; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT sicvt = csound->sicvt; MYFLT *ft; ar = p->rslt; ftp = p->ftp; if (UNLIKELY(ftp == NULL)) goto err1; /* RWD fix */ ft = ftp->ftable; lobits = ftp->lobits; mphs = p->mphs; cphs = p->cphs; ampp = p->xamp; cps = *p->kcps; carp = p->xcar; modp = p->xmod; amp = *ampp; xcar = *carp; xmod = *modp; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } if (p->ampcod || p->carcod || p->modcod) { for (n=offset;nampcod) amp = ampp[n]; if (p->carcod) xcar = carp[n]; if (p->modcod) xmod = modp[n]; car = cps * xcar; mod = cps * xmod; ndx = *p->kndx * mod; minc = (int32)(mod * sicvt); mphs &= PHMASK; fract = PFRAC(mphs); ftab = ft + (mphs >>lobits); v1 = *ftab++; fmod = (v1 + (*ftab - v1) * fract) * ndx; mphs += minc; cfreq = car + fmod; cinc = (int32)(cfreq * sicvt); cphs &= PHMASK; fract = PFRAC(cphs); ftab = ft + (cphs >>lobits); v1 = *ftab++; ar[n] = (v1 + (*ftab - v1) * fract) * amp; cphs += cinc; } } else { cps = *p->kcps; car = cps * *carp; mod = cps * *modp; ndx = *p->kndx * mod; minc = (int32)(mod * sicvt); for (n=offset;n>lobits); v1 = *ftab++; fmod = (v1 + (*ftab - v1) * fract) * ndx; mphs += minc; cfreq = car + fmod; cinc = (int32)(cfreq * sicvt); cphs &= PHMASK; fract = PFRAC(cphs); ftab = ft + (cphs >>lobits); v1 = *ftab++; ar[n] = (v1 + (*ftab - v1) * fract) * amp; cphs += cinc; } } p->mphs = mphs; p->cphs = cphs; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("foscili: not initialised")); } int losset(CSOUND *csound, LOSC *p) { FUNC *ftp; if ((ftp = csound->FTnp2Find(csound,p->ifn)) != NULL) { uint32 maxphs = ftp->flenfrms; //printf("****maxphs = %d (%x)\n", maxphs, maxphs); p->ftp = ftp; if (*p->ibas != FL(0.0)) p->cpscvt = (ftp->cvtbas / *p->ibas)/LOFACT; else if (UNLIKELY((p->cpscvt = ftp->cpscvt) == FL(0.0))) { p->cpscvt = FL(261.62561); /* Middle C */ csound->Warning(csound, Str("no legal base frequency")); } //printf("****cpscvt = %g\n", p->cpscvt); if ((p->mod1 = (int16) *p->imod1) < 0) { if (UNLIKELY((p->mod1 = ftp->loopmode1) == 0)) { csound->Warning(csound, Str("loscil: sustain defers to " "non-looping source")); } p->beg1 = ftp->begin1; p->end1 = ftp->end1; } else if (UNLIKELY(p->mod1 < 0 || p->mod1 > 3)) goto lerr2; else { p->beg1 = *p->ibeg1; p->end1 = *p->iend1; if (!p->beg1 && !p->end1) /* default to looping the whole sample */ p->end1 = /* These are the same!! */ (p->mod1 ? (MYFLT)maxphs : (MYFLT)ftp->flenfrms); else if (UNLIKELY(p->beg1 < 0 || p->end1 > maxphs || p->beg1 >= p->end1)) { csound->Message(csound, "beg: %g, end = %g, maxphs = %d\n", p->beg1, p->end1, maxphs); goto lerr2; } } if ((p->mod2 = (int16) *p->imod2) < 0) { p->mod2 = ftp->loopmode2; p->beg2 = ftp->begin2; p->end2 = ftp->end2; } else { p->beg2 = *p->ibeg2; p->end2 = *p->iend2; if (UNLIKELY(p->mod2 < 0 || p->mod2 > 3 || p->beg2 < 0 || p->end2 > (int32)maxphs || p->beg2 >= p->end2)) { goto lerr3; } } p->beg1 = (p->beg1 >= 0L ? p->beg1 : 0L); p->end1 = (p->end1 < (int32)maxphs ? p->end1 : (int32)maxphs); if (UNLIKELY(p->beg1 >= p->end1)) { p->mod1 = 0; p->beg1 = 0L; p->end1 = maxphs; } p->beg2 = (p->beg2 >= 0L ? p->beg2 : 0L); p->end2 = (p->end2 < (int32)maxphs ? p->end2 : (int32)maxphs); if (UNLIKELY(p->beg2 >= p->end2)) { p->mod2 = 0; p->beg2 = 0L; } if (!p->mod2 && !p->end2) /* if no release looping */ p->end2 = maxphs; /* set a reading limit */ p->lphs = 0; p->seg1 = 1; if ((p->curmod = p->mod1)) p->looping = 1; else p->looping = 0; if (p->OUTOCOUNT == 1) { p->stereo = 0; if (UNLIKELY(ftp->nchanls != 1)) return csound->InitError(csound, Str( "mono loscil cannot read from stereo ftable")); } else { p->stereo = 1; if (UNLIKELY(ftp->nchanls != 2)) return csound->InitError(csound, Str( "stereo loscil cannot read from mono ftable")); } return OK; } return NOTOK; lerr2: return csound->InitError(csound, Str("illegal sustain loop data")); lerr3: return csound->InitError(csound, Str("illegal release loop data")); } static inline void loscil_linear_interp_mono(MYFLT *ar, MYFLT *ftbl, MYFLT phs, int32 flen) { MYFLT fract, tmp; int32 x; fract = MODF(phs, &tmp); x = (int32) tmp; //printf("phs=%d+%f\n",x, fract); tmp = ftbl[x]; x = (x < flen ? (x + 1) : flen); *ar = tmp + ((ftbl[x] - tmp) * fract); } static inline void loscil_linear_interp_stereo(MYFLT *arL, MYFLT *arR, MYFLT *ftbl, MYFLT phs, int32 flen) { MYFLT fract, tmpL, tmpR; int x; fract = MODF(phs, &tmpL); x = (int32) tmpL; //printf("phs=%d+%f\n",x, fract); tmpL = ftbl[x]; tmpR = ftbl[x + 1]; x = (x < ((int) flen - 1) ? (x + 2) : ((int) flen - 1)); *arL = tmpL + ((ftbl[x] - tmpL) * fract); *arR = tmpR + ((ftbl[x + 1] - tmpR) * fract); } static inline void loscil_cubic_interp_mono(MYFLT *ar, MYFLT *ftbl, MYFLT phs, int32 flen) { MYFLT fract, tmp, a0, a1, a2, a3; int x; fract = MODF(phs, &tmp); x = (int32) tmp; //printf("phs=%d+%f\n",x, fract); a3 = fract * fract; a3 -= FL(1.0); a3 *= (FL(1.0) / FL(6.0)); a2 = fract; a2 += FL(1.0); a0 = (a2 *= FL(0.5)); a0 -= FL(1.0); a1 = FL(3.0) * a3; a2 -= a1; a0 -= a3; a1 -= fract; a0 *= fract; a1 *= fract; a2 *= fract; a3 *= fract; a1 += FL(1.0); tmp = ftbl[(x >= 0 ? x : 0)] * a0; tmp += ftbl[++x] * a1; x++; tmp += ftbl[(x < (int) flen ? x : (int) flen)] * a2; x++; tmp += ftbl[(x < (int) flen ? x : (int) flen)] * a3; *ar = tmp; } static CS_NOINLINE void loscil_cubic_interp_stereo(MYFLT *arL, MYFLT *arR, MYFLT *ftbl, MYFLT phs, int32 flen) { MYFLT fract, tmpL, tmpR, a0, a1, a2, a3; int x; fract = MODF(phs, &tmpL); x = (int32) tmpL; //printf("phs=%d+%f\n",x, fract); a3 = fract * fract; a3 -= FL(1.0); a3 *= (FL(1.0) / FL(6.0)); a2 = fract; a2 += FL(1.0); a0 = (a2 *= FL(0.5)); a0 -= FL(1.0); a1 = FL(3.0) * a3; a2 -= a1; a0 -= a3; a1 -= fract; a0 *= fract; a1 *= fract; a2 *= fract; a3 *= fract; a1 += FL(1.0); tmpL = ftbl[(x >= 0 ? x : 0)] * a0; tmpR = ftbl[(x >= 0 ? (x + 1) : 1)] * a0; x += 2; tmpL += ftbl[x] * a1; tmpR += ftbl[x + 1] * a1; x = (x < ((int) flen - 1) ? (x + 2) : ((int) flen - 1)); tmpL += ftbl[x] * a2; tmpR += ftbl[x + 1] * a2; x = (x < ((int) flen - 1) ? (x + 2) : ((int) flen - 1)); tmpL += ftbl[x] * a3; tmpR += ftbl[x + 1] * a3; *arL = tmpL; *arR = tmpR; } /* *********************** needs total rewrite **************** */ int loscil(CSOUND *csound, LOSC *p) { FUNC *ftp; MYFLT *ar1, *ar2, *ftbl, *xamp; MYFLT phs; MYFLT inc, beg, end; uint32_t n = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nsmps = CS_KSMPS; int aamp; MYFLT xx; ftp = p->ftp; ftbl = ftp->ftable; if ((inc = (*p->kcps * p->cpscvt)) < 0) inc = -inc; xamp = p->xamp; xx = *xamp; aamp = IS_ASIG_ARG(p->xamp) ? 1 : 0; if (p->seg1) { /* if still segment 1 */ beg = p->beg1; end = p->end1; if (UNLIKELY(p->h.insdshead->relesing)) /* sense note_off */ p->looping = 0; } else { beg = p->beg2; end = p->end2; } phs = p->lphs; ar1 = p->ar1; if (UNLIKELY(n)) memset(ar1, '\0', n*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar1[nsmps], '\0', early*sizeof(MYFLT)); } if (p->stereo) { ar2 = p->ar2; if (UNLIKELY(n)) memset(ar2, '\0', n*sizeof(MYFLT)); if (UNLIKELY(early)) memset(&ar2[nsmps], '\0', early*sizeof(MYFLT)); goto phsck2; } phschk: if (phs >= end && p->curmod != 3) { //printf("****phs = %f end = %d\n", phs,end); goto put0; } switch (p->curmod) { case 0: for (; nflen); if (aamp) xx = xamp[n]; ar1[n] *= xx; if ((phs += inc) >= end) { //printf("****phs, end = %f, %d\n", phs, end); goto nxtseg; } } break; case 1: for (; nflen); if (aamp) xx = xamp[n]; ar1[n] *= xx; if (UNLIKELY((phs += inc) >= end)) { if (!(p->looping)) goto nxtseg; phs -= end - beg; } } break; case 2: case2: for (; nflen); if (aamp) xx = xamp[n]; ar1[n] *= xx; if ((phs += inc) >= end) { if (!(p->looping)) goto nxtseg; phs -= (phs - end) * 2; p->curmod = 3; if (++nflen); if (aamp) xx = xamp[n]; ar1[n] *= xx; if (UNLIKELY((phs -= inc) < beg)) { phs += (beg - phs) * 2; p->curmod = 2; if (++nseg1) { p->seg1 = 0; if ((p->curmod = p->mod2) != 0) p->looping = 1; if (++n>nsmps) { beg = p->beg2; end = p->end2; p->lphs = phs; goto phschk; } break; } if (LIKELY(++nlphs = phs; return OK; phsout: p->lphs = phs; put0: //printf("****put0\n"); memset(&ar1[n], '\0', sizeof(MYFLT)*(nsmps-n)); return OK; phsck2: /*VL increment for stereo */ inc *= 2; end *= 2; if (phs >= end && p->curmod != 3) goto put0s; /* for STEREO: */ switch (p->curmod) { case 0: for (; nflen); if (aamp) xx = xamp[n]; ar1[n] *= xx; ar2[n] *= xx; if (UNLIKELY((phs += inc) >= end)) goto nxtseg2; } break; case 1: for (; nflen); if (aamp) xx = xamp[n]; ar1[n] *= xx; ar2[n] *= xx; if (UNLIKELY((phs += inc) >= end)) { if (!(p->looping)) goto nxtseg2; phs -= end - beg; } } break; case 2: case2s: for (; nflen); if (aamp) xx = xamp[n]; ar1[n] *= xx; ar2[n] *= xx; if (UNLIKELY((phs += inc) >= end)) { if (!(p->looping)) goto nxtseg2; phs -= (phs - end) * 2; p->curmod = 3; if (++nflen); if (aamp) xx = xamp[n]; ar1[n] *= xx; ar2[n] *= xx; if (UNLIKELY((phs -= inc) < beg)) { phs += (beg - phs) * 2; p->curmod = 2; if (++nseg1) { p->seg1 = 0; if ((p->curmod = p->mod2) != 0) p->looping = 1; if (++nbeg2; end = p->end2; p->lphs = phs; goto phsck2; } break; } if (LIKELY(++nlphs = phs; return OK; phsout2: p->lphs = phs; put0s: memset(&ar1[n], '\0', sizeof(MYFLT)*(nsmps-n)); memset(&ar2[n], '\0', sizeof(MYFLT)*(nsmps-n)); return OK; } int loscil3(CSOUND *csound, LOSC *p) { FUNC *ftp; MYFLT *ar1, *ar2, *ftbl, *xamp; MYFLT phs; MYFLT inc, beg, end; uint32_t n = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nsmps = CS_KSMPS; int aamp; MYFLT xx; ftp = p->ftp; ftbl = ftp->ftable; if ((inc = (*p->kcps * p->cpscvt)) < 0) inc = -inc; xamp = p->xamp; xx = *xamp; aamp = IS_ASIG_ARG(p->xamp) ? 1 : 0; if (p->seg1) { /* if still segment 1 */ beg = p->beg1; end = p->end1; if (p->h.insdshead->relesing) /* sense note_off */ p->looping = 0; } else { beg = p->beg2; end = p->end2; } phs = p->lphs; ar1 = p->ar1; if (UNLIKELY(n)) memset(ar1, '\0', n*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar1[nsmps], '\0', early*sizeof(MYFLT)); } if (p->stereo) { ar2 = p->ar2; if (UNLIKELY(n)) memset(ar1, '\0', n*sizeof(MYFLT)); if (UNLIKELY(early)) memset(&ar2[nsmps], '\0', early*sizeof(MYFLT)); goto phsck2; } phschk: if (UNLIKELY(phs >= end && p->curmod != 3)) goto put0; switch (p->curmod) { case 0: for (; nflen); if (aamp) xx = xamp[n]; ar1[n] *= xx; if (UNLIKELY((phs += inc) >= end)) goto nxtseg; } break; case 1: for (; nflen); if (aamp) xx = xamp[n]; ar1[n] *= xx; if (UNLIKELY((phs += inc) >= end)) { if (!(p->looping)) goto nxtseg; phs -= end - beg; } } break; case 2: case2: for (; nflen); if (aamp) xx = xamp[n]; ar1[n] *= xx; if (UNLIKELY((phs += inc) >= end)) { if (!(p->looping)) goto nxtseg; phs -= (phs - end) * 2; p->curmod = 3; if (++nflen);; if (aamp) xx = xamp[n]; ar1[n] *= xx; if (UNLIKELY((phs -= inc) < beg)) { phs += (beg - phs) * 2; p->curmod = 2; if (++nseg1) { p->seg1 = 0; if ((p->curmod = p->mod2) != 0) p->looping = 1; if (--nsmps) { beg = p->beg2; end = p->end2; p->lphs = phs; goto phschk; } break; } if (LIKELY(++nlphs = phs; return OK; phsout: p->lphs = phs; put0: memset(&ar1[n], 0, sizeof(MYFLT)*(nsmps-n)); /* do { */ /* *ar1++ = FL(0.0); */ /* } while (--nsmps); */ return OK; phsck2: /*VL increment for stereo */ inc *= 2; end *= 2; if (UNLIKELY(phs >= end && p->curmod != 3)) goto put0s; /* for STEREO: */ switch (p->curmod) { case 0: for (; nflen); if (aamp) xx = xamp[n]; ar1[n] *= xx; ar2[n] *= xx; if (UNLIKELY((phs += inc) >= end)) goto nxtseg2; } break; case 1: for (; nflen); if (aamp) xx = xamp[n]; ar1[n] *= xx; ar2[n] *= xx; if (UNLIKELY((phs += inc) >= end)) { if (!(p->looping)) goto nxtseg2; phs -= end - beg; } } break; case 2: case2s: for (; nflen); if (aamp) xx = xamp[n]; ar1[n] *= xx; ar2[n] *= xx; if (UNLIKELY((phs += inc) >= end)) { if (!(p->looping)) goto nxtseg2; phs -= (phs - end) * 2; p->curmod = 3; if (++nflen); if (aamp) xx = xamp[n]; ar1[n] *= xx; ar2[n] *= xx; if (UNLIKELY((phs -= inc) < beg)) { phs += (beg - phs) * 2; p->curmod = 2; if (++nseg1) { p->seg1 = 0; if ((p->curmod = p->mod2) != 0) p->looping = 1; if (++nbeg2; end = p->end2; p->lphs = phs; goto phsck2; } break; } if (LIKELY(++nlphs = phs; return OK; phsout2: p->lphs = phs; put0s: memset(&ar1[n], '\0', sizeof(MYFLT)*(nsmps-n)); memset(&ar2[n], '\0', sizeof(MYFLT)*(nsmps-n)); return OK; } #define ISINSIZ 32768L #define ADMASK 32767L static int adset_(CSOUND *csound, ADSYN *p, int stringname) { int32 n; char filnam[MAXNAME]; MEMFIL *mfp; int16 *adp, *endata, val; PTLPTR *ptlap, *ptlfp, *ptlim; int size; if (csound->isintab == NULL) { /* if no sin table yet, make one */ int16 *ip; csound->isintab = ip = (int16*) csound->Malloc(csound, ISINSIZ * sizeof(int16)); for (n = 0; n < ISINSIZ; n++) *ip++ = (int16) (sin(TWOPI * n / ISINSIZ) * 32767.0); } if (stringname) strncpy(filnam, ((STRINGDAT*)p->ifilcod)->data, MAXNAME-1); else if (csound->ISSTRCOD(*p->ifilcod)) strncpy(filnam, get_arg_string(csound, *p->ifilcod), MAXNAME-1); else csound->strarg2name(csound, filnam, p->ifilcod, "adsyn.", 0); if ((mfp = p->mfp) == NULL || strcmp(mfp->filename,filnam) != 0) { /* readfile if reqd */ if (UNLIKELY((mfp = ldmemfile2withCB(csound, filnam, CSFTYPE_HETRO, NULL)) == NULL)) { return csound->InitError(csound, Str("ADSYN cannot load %s"), filnam); } p->mfp = mfp; /* & record */ } adp = (int16 *) mfp->beginp; /* align on file data */ endata = (int16 *) mfp->endp; size = 1+(*adp == -1 ? MAXPTLS : *adp++); /* Old no header -> MAXPIL */ if (p->aux.auxp==NULL || p->aux.size < (uint32_t)sizeof(PTLPTR)*size) csound->AuxAlloc(csound, sizeof(PTLPTR)*size, &p->aux); ptlap = ptlfp = (PTLPTR*)p->aux.auxp; /* find base ptl blk */ ptlim = ptlap + size; do { if ((val = *adp++) < 0) { /* then for each brkpt set, */ switch (val) { case -1: ptlap->nxtp = ptlap + 1; /* chain the ptl blks */ if (UNLIKELY((ptlap = ptlap->nxtp) >= ptlim)) goto adsful; ptlap->ap = (DUPLE *) adp; /* record start amp */ ptlap->amp = ptlap->ap->val; break; case -2: if (UNLIKELY((ptlfp += 1) >= ptlim)) goto adsful; ptlfp->fp = (DUPLE *) adp; /* record start frq */ ptlfp->frq = ptlfp->fp->val; ptlfp->phs = 0; /* and clr the phase */ break; default: return csound->InitError(csound, Str("illegal code %d encountered"), val); } } } while (adp < endata); if (UNLIKELY(ptlap != ptlfp)) { return csound->InitError(csound, Str("%d amp tracks, %d freq tracks"), (int) (ptlap - (PTLPTR*)p->aux.auxp) - 1, (int) (ptlfp - (PTLPTR*)p->aux.auxp) - 1); } ptlap->nxtp = NULL; /* terminate the chain */ p->mksecs = 0; return OK; adsful: return csound->InitError(csound, Str("partial count exceeds MAXPTLS")); } int adset(CSOUND *csound, ADSYN *p){ return adset_(csound,p,0); } int adset_S(CSOUND *csound, ADSYN *p){ return adset_(csound,p,1); } #define ADSYN_MAXLONG FL(2147483647.0) int adsyn(CSOUND *csound, ADSYN *p) { PTLPTR *curp, *prvp; DUPLE *ap, *fp; int16 curtim, diff, ktogo; int32 phs, sinc, amp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *ar = p->rslt; MYFLT ampscale, frqscale; int32 timkincr, nxtim; if (UNLIKELY(csound->isintab == NULL)) { /* RWD fix */ return csound->PerfError(csound, p->h.insdshead, Str("adsyn: not initialised")); } /* IV - Jul 11 2002 */ ampscale = *p->kamod * csound->e0dbfs; /* since 15-bit sine table */ frqscale = *p->kfmod * ISINSIZ * csound->onedsr; /* 1024 * msecs of analysis */ memset(p->rslt,0,sizeof(MYFLT)*nsmps); if (UNLIKELY(early)) nsmps -= early; timkincr = (int32)(*p->ksmod*FL(1024000.0)*CS_ONEDKR); curtim = (int16)(p->mksecs >> 10); /* cvt mksecs to msecs */ curp = (PTLPTR*)p->aux.auxp; /* now for each partial: */ while ((prvp = curp) && (curp = curp->nxtp) != NULL ) { ap = curp->ap; fp = curp->fp; while (curtim >= (ap+1)->tim) /* timealign ap, fp */ curp->ap = ap += 1; while (curtim >= (fp+1)->tim) curp->fp = fp += 1; if ((amp = curp->amp)) { /* for non-zero amp */ sinc = (int32)(curp->frq * frqscale); phs = curp->phs; /* addin a sinusoid */ for (n=offset; nisintab[phs]*(MYFLT)amp)/ADSYN_MAXLONG; phs += sinc; phs &= ADMASK; } curp->phs = phs; } if ((nxtim = (ap+1)->tim) == 32767) { /* if last amp this partial */ prvp->nxtp = curp->nxtp; /* remov from activ chain */ curp = prvp; } else { /* else interp towds nxt amp */ if ((diff = (int16)((ap+1)->val - amp))) { ktogo = (int16)(((nxtim<<10) - p->mksecs + timkincr - 1) / timkincr); if (ktogo == 0) curp->amp += diff; else curp->amp += diff / ktogo; } if ((nxtim = (fp+1)->tim) != 32767 /* & nxt frq */ && (diff = (fp+1)->val - curp->frq)) { ktogo = (int16)(((nxtim<<10) - p->mksecs + timkincr - 1) / timkincr); if (ktogo == 0) curp->frq += diff; else curp->frq += diff / ktogo; } } } p->mksecs += timkincr; /* advance the time */ return OK; } csound-6.10.0/OOps/ugens4.c000066400000000000000000000637201321653344700153420ustar00rootroot00000000000000/* ugens4.c: Copyright (C) 1991 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* UGENS4.C */ #include "ugens4.h" #include /* The branch prediction slows it down!! */ int bzzset(CSOUND *csound, BUZZ *p) { FUNC *ftp; if (LIKELY((ftp = csound->FTFind(csound, p->ifn)) != NULL)) { p->ftp = ftp; if (*p->iphs >= 0) p->lphs = (int32)(*p->iphs * FL(0.5) * FMAXLEN); p->ampcod = IS_ASIG_ARG(p->xamp) ? 1 : 0; p->cpscod = IS_ASIG_ARG(p->xcps) ? 1 : 0; p->reported = 0; /* No errors yet */ return OK; } return NOTOK; } int buzz(CSOUND *csound, BUZZ *p) { FUNC *ftp; MYFLT *ar, *ampp, *cpsp, *ftbl; int32 phs, inc, lobits, dwnphs, tnp1, lenmask; MYFLT sicvt2, over2n, scal, num, denom; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 nn; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; /* RWD fix */ ftbl = ftp->ftable; sicvt2 = csound->sicvt * FL(0.5); /* for theta/2 */ lobits = ftp->lobits; lenmask = ftp->lenmask; ampp = p->xamp; cpsp = p->xcps; if ((nn = (int)*p->knh) < 0) nn = -nn; if (UNLIKELY(nn == 0)) { /* fix nn = knh */ nn = 1; } tnp1 = (nn<<1) + 1; /* calc 2n + 1 */ over2n = FL(0.5) / (MYFLT)nn; scal = *ampp * over2n; inc = (int32)(*cpsp * sicvt2); ar = p->ar; phs = p->lphs; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { //printf("early=%d\n", early); nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nampcod) scal = ampp[n] * over2n; if (p->cpscod) inc = (int32)(cpsp[n] * sicvt2); dwnphs = phs >> lobits; denom = ftbl[dwnphs]; if (denom > FL(0.0002) || denom < -FL(0.0002)) { num = ftbl[dwnphs * tnp1 & lenmask]; ar[n] = (num / denom - FL(1.0)) * scal; } else ar[n] = *ampp; phs += inc; phs &= PHMASK; } p->lphs = phs; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("buzz: not initialised")); } int gbzset(CSOUND *csound, GBUZZ *p) { FUNC *ftp; if (LIKELY((ftp = csound->FTFind(csound, p->ifn)) != NULL)) { p->ftp = ftp; if (*p->iphs >= 0) { p->lphs = (int32)(*p->iphs * FMAXLEN); p->prvr = FL(0.0); } p->ampcod = IS_ASIG_ARG(p->xamp) ? 1 : 0; p->cpscod = IS_ASIG_ARG(p->xcps) ? 1 : 0; p->reported = 0; p->last = FL(1.0); return OK; } return NOTOK; } static inline MYFLT intpow1(MYFLT x, int32 n) /* Binary positive power function */ { MYFLT ans = FL(1.0); while (n!=0) { if (n&1) ans = ans * x; n >>= 1; x = x*x; } return ans; } MYFLT intpow(MYFLT x, int32 n) /* Binary power function */ { if (n<0) { n = -n; x = FL(1.0)/x; } return intpow1(x, n); } int gbuzz(CSOUND *csound, GBUZZ *p) { FUNC *ftp; MYFLT *ar, *ampp, *cpsp, *ftbl; int32 phs, inc, lobits, lenmask, k, km1, kpn, kpnm1; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT r, absr, num, denom, scal, last = p->last; int32 nn, lphs = p->lphs; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; ftbl = ftp->ftable; lobits = ftp->lobits; lenmask = ftp->lenmask; ampp = p->xamp; cpsp = p->xcps; k = (int32)*p->kk; /* fix k and n */ if ((nn = (int32)*p->kn)<0) nn = -nn; if (UNLIKELY(nn == 0)) { /* n must be > 0 */ nn = 1; } km1 = k - 1; kpn = k + nn; kpnm1 = kpn - 1; if ((r = *p->kr) != p->prvr || nn != p->prvn) { p->twor = r + r; p->rsqp1 = r * r + FL(1.0); p->rtn = intpow1(r, nn); p->rtnp1 = p->rtn * r; if ((absr = FABS(r)) > FL(0.999) && absr < FL(1.001)) p->rsumr = FL(1.0) / nn; else p->rsumr = (FL(1.0) - absr) / (FL(1.0) - FABS(p->rtn)); p->prvr = r; p->prvn = (int16)nn; } scal = *ampp * p->rsumr; inc = (int32)(*cpsp * csound->sicvt); ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nampcod) scal = p->rsumr * ampp[n]; if (p->cpscod) inc = (int32)(cpsp[n] * csound->sicvt); phs = lphs >>lobits; denom = p->rsqp1 - p->twor * ftbl[phs]; num = ftbl[phs * k & lenmask] - r * ftbl[phs * km1 & lenmask] - p->rtn * ftbl[phs * kpn & lenmask] + p->rtnp1 * ftbl[phs * kpnm1 & lenmask]; if (LIKELY(denom > FL(0.0002) || denom < -FL(0.0002))) { ar[n] = last = num / denom * scal; } else if (last<0) ar[n] = last = - (p->ampcod ? ampp[n] : *ampp); else ar[n] = last = (p->ampcod ? ampp[n] : *ampp); lphs += inc; lphs &= PHMASK; } p->last = last; p->lphs = lphs; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("gbuzz: not initialised")); } #define PLUKMIN 64 static int16 rand15(CSOUND *); static int16 rand16(CSOUND *); int plukset(CSOUND *csound, PLUCK *p) { int n; int32 npts, iphs; char *auxp; FUNC *ftp; MYFLT *ap, *fp; MYFLT phs, phsinc; if (UNLIKELY((npts = (int32)(csound->esr / *p->icps)) < PLUKMIN)) { /* npts is wavelen in sampls */ npts = PLUKMIN; /* (but at least min size) */ } if ((auxp = p->auxch.auxp) == NULL || npts > p->maxpts) { /* get newspace */ csound->AuxAlloc(csound, (npts+1)*sizeof(MYFLT),&p->auxch); auxp = p->auxch.auxp; p->maxpts = npts; /* if reqd */ } ap = (MYFLT *)auxp; /* as MYFLT array */ if (*p->ifn == 0.0) for (n=npts; n--; ) /* f0: fill w. rands */ *ap++ = (MYFLT) rand16(csound) * DV32768; else if ((ftp = csound->FTnp2Find(csound, p->ifn)) != NULL) { fp = ftp->ftable; /* else from ftable */ phs = FL(0.0); phsinc = (MYFLT)(ftp->flen/npts); for (n=npts; n--; phs += phsinc) { iphs = (int32)phs; *ap++ = fp[iphs]; } } *ap = *(MYFLT *)auxp; /* last = copy of 1st */ p->npts = npts; /* tuned pitch convt */ p->sicps = (npts * FL(256.0) + FL(128.0)) * csound->onedsr; p->phs256 = 0; p->method = (int16)*p->imeth; p->param1 = *p->ipar1; p->param2 = *p->ipar2; switch(p->method) { case 1: /* ignore any given parameters */ break; case 2: /* stretch factor: param1 >= 1 */ if (UNLIKELY(p->param1 < FL(1.0))) return csound->InitError(csound, Str("illegal stretch factor(param1) value")); else p->thresh1 = (int16)(FL(32768.0) / p->param1); break; case 3: /* roughness factor: 0 <= param1 <= 1 */ if (UNLIKELY(p->param1 < FL(0.0) || p->param1 > FL(1.0))) return csound->InitError(csound, Str("illegal roughness factor(param1) value")); else p->thresh1 = (int16)(FL(32768.0) * p->param1); break; case 4: /* rough and stretch factor: 0 <= param1 <= 1, param2 >= 1 */ if (UNLIKELY(p->param1 < FL(0.0) || p->param1 > FL(1.0))) return csound->InitError(csound, Str("illegal roughness factor(param1) value")); else p->thresh1 = (int16)(FL(32768.0) * p->param1); if (UNLIKELY(p->param2 < FL(1.0))) return csound->InitError(csound, Str("illegal stretch factor(param2) value")); else p->thresh2 = (int16)(FL(32768.0) / p->param2); break; case 5: /* weighting coeff's: param1 + param2 <= 1 */ if (UNLIKELY(p->param1 + p->param2 > 1)) return csound->InitError(csound, Str("coefficients too large " "(param1 + param2)")); break; case 6: /* ignore any given parameters */ break; default: return csound->InitError(csound, Str("unknown method code")); } return OK; } int pluck(CSOUND *csound, PLUCK *p) { MYFLT *ar, *fp; int32 phs256, phsinc, ltwopi, offset; uint32_t koffset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT frac, diff; if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; /* RWD FIX */ ar = p->ar; phsinc = (int32)(*p->kcps * p->sicps); phs256 = p->phs256; ltwopi = p->npts << 8; if (UNLIKELY(phsinc > ltwopi)) goto err2; if (UNLIKELY(koffset)) memset(ar, '\0', koffset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=koffset; n> 8; fp = (MYFLT *)p->auxch.auxp + offset; /* lookup position */ diff = fp[1] - fp[0]; frac = (MYFLT)(phs256 & 255) / FL(256.0); /* w. interpolation */ ar[n] = (fp[0] + diff*frac) * *p->kamp; /* gives output val */ if ((phs256 += phsinc) >= ltwopi) { int nn; MYFLT newval, preval; phs256 -= ltwopi; /* at phase wrap, */ fp=(MYFLT *)p->auxch.auxp; preval = fp[0]; /* copy last pnt */ fp[0] = fp[p->npts]; /* to first, */ fp++; /* apply smoothing */ nn = p->npts; /* up to npts+1 */ switch(p->method) { case 1: do { /* simple averaging */ newval = (*fp + preval) * FL(0.5); preval = *fp; *fp++ = newval; } while (--nn); break; case 2: do { /* stretched avrging */ if (rand15(csound) < p->thresh1) { newval = (*fp + preval) * FL(0.5); preval = *fp; *fp++ = newval; } else preval = *fp++; } while (--nn); break; case 3: do { /* simple drum */ if (rand15(csound) < p->thresh1) newval = -(*fp + preval) * FL(0.5); else newval = (*fp + preval) * FL(0.5); preval = *fp; *fp++ = newval; } while (--nn); break; case 4: do { /* stretched drum */ if (rand15(csound) < p->thresh2) { if (rand15(csound) < p->thresh1) newval = -(*fp + preval) * FL(0.5); else newval = (*fp + preval) * FL(0.5); preval = *fp; *fp++ = newval; } else preval = *fp++; } while (--nn); break; case 5: do { /* weighted avraging */ newval = p->param1 * *fp + p->param2 * preval; preval = *fp; *fp++ = newval; } while (--nn); break; case 6: do { /* 1st order recursive filter*/ preval = (*fp + preval) * FL(0.5); *fp++ = preval; } while (--nn); break; } } } p->phs256 = phs256; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("pluck: not initialised")); err2: return csound->PerfError(csound, p->h.insdshead, Str("pluck: kcps more than sample rate")); } #define RNDMUL 15625 #define MASK16 0xFFFF #define MASK15 0x7FFF /* quick generate a random int16 between -32768 and 32767 */ static int16 rand16(CSOUND *csound) { csound->ugens4_rand_16 = (csound->ugens4_rand_16 * RNDMUL + 1) & MASK16; return (int16) ((int16_t) csound->ugens4_rand_16); } /* quick generate a random int16 between 0 and 32767 */ static int16 rand15(CSOUND *csound) { csound->ugens4_rand_15 = (csound->ugens4_rand_15 * RNDMUL + 1) & MASK15; return (int16) csound->ugens4_rand_15; } /*========================================================================= * * randint31() * * 31 bit Park Miller PRNG using Linus Schrage's method for doing it all * with 32 bit variables. * * Code adapted from Ray Garder's public domain code of July 1997 at: * http://www.snippets.org/RG_RAND.C Thanks! * * Based on "Random Number Generators: Good Ones Are Hard to Find", * S.K. Park and K.W. Miller, Communications of the ACM 31:10 (Oct 1988), * and "Two Fast Implementations of the 'Minimal Standard' Random * Number Generator", David G. Carta, Comm. ACM 33, 1 (Jan 1990), p. 87-88 * * Linear congruential generator: f(z) = (16807 * z) mod (2 ** 31 - 1) * * Uses L. Schrage's method to avoid overflow problems. */ #define BIPOLAR 0x7FFFFFFF /* Constant to make bipolar */ #define RIA (16807) /* multiplier */ #define RIM 0x7FFFFFFFL /* 2**31 - 1 */ #define dv2_31 (FL(4.656612873077392578125e-10)) int32 randint31(int32 seed31) { uint32 rilo, rihi; rilo = RIA * (int32)(seed31 & 0xFFFF); rihi = RIA * (int32)((uint32)seed31 >> 16); rilo += (rihi & 0x7FFF) << 16; if (rilo > RIM) { rilo &= RIM; ++rilo; } rilo += rihi >> 15; if (rilo > RIM) { rilo &= RIM; ++rilo; } return (int32)rilo; } int rndset(CSOUND *csound, RAND *p) { p->new = (*p->sel!=FL(0.0)); if (*p->iseed >= FL(0.0)) { if (*p->iseed > FL(1.0)) { /* As manual suggest seed in range [0,1] */ uint32 seed; /* I reinterpret >1 as a time seed */ seed = csound->GetRandomSeedFromTime(); csound->Warning(csound, Str("Seeding from current time %u\n"), seed); if (!p->new) { p->rand = (int32) (seed & 0xFFFFUL); } else { p->rand = (int32) (seed % 0x7FFFFFFEUL) + 1L; } } else { if (p->new) { MYFLT seed = *p->iseed; if (seed==FL(0.0)) seed = FL(0.5); p->rand = (int32) (seed * FL(2147483648.0)); p->rand = randint31(p->rand); p->rand = randint31(p->rand); } else p->rand = ((int16)(*p->iseed * FL(32768.0)))&0xffff; } } p->ampcod = IS_ASIG_ARG(p->xamp) ? 1 : 0; /* (not used by krand) */ return OK; } int krand(CSOUND *csound, RAND *p) { if (p->new) { int32 r = randint31(p->rand); /* result is a 31-bit value */ p->rand = r; *p->ar = *p->base + dv2_31 * (MYFLT)((int32)((unsigned)r<<1)-BIPOLAR) * *p->xamp; } else { int16 rand = (int16)p->rand; rand *= RNDMUL; rand += 1; /* IV - Jul 11 2002 */ *p->ar = *p->base + (MYFLT)rand * *p->xamp * DV32768; p->rand = rand; } return OK; } int arand(CSOUND *csound, RAND *p) { MYFLT *ar; int16 rndmul = RNDMUL; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT ampscl; MYFLT base = *p->base; ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } if (!p->new) { int16 rand = p->rand; if (!(p->ampcod)) { ampscl = *p->xamp * DV32768; /* IV - Jul 11 2002 */ for (n=offset;nxamp; for (n=offset;nrand = rand; /* save current rand */ } else { int rand = p->rand; if (!(p->ampcod)) { ampscl = *p->xamp * dv2_31; for (n=offset;nxamp; for (n=offset;nrand = rand; /* save current rand */ } return OK; } int rhset(CSOUND *csound, RANDH *p) { p->new = (*p->sel!=FL(0.0)); if (*p->iseed >= FL(0.0)) { /* new seed: */ if (*p->iseed > FL(1.0)) { /* As manual suggest sseed in range [0,1] */ uint32 seed; /* I reinterpret >1 as a time seed */ seed = csound->GetRandomSeedFromTime(); csound->Warning(csound, Str("Seeding from current time %u\n"), seed); if (!p->new) { p->rand = (int32) (seed & 0xFFFFUL); p->num1 = (MYFLT) ((int16) p->rand) * DV32768; } else { p->rand = (int32) (seed % 0x7FFFFFFEUL) + 1L; p->num1 = (MYFLT) ((int32) ((unsigned)p->rand<<1) - BIPOLAR) * dv2_31; } } else if (!p->new) { p->rand = 0xffff&(int16)(*p->iseed * 32768L); /* init rand integ */ p->num1 = *p->iseed; /* store fnum */ } else { MYFLT ss = *p->iseed; if (ss>FL(1.0)) p->rand = (int32) ss; else p->rand = (int32) (*p->iseed * FL(2147483648.0)); p->rand = randint31(p->rand); p->rand = randint31(p->rand); p->num1 = (MYFLT) ((int32) ((unsigned)p->rand<<1) - BIPOLAR) * dv2_31; } p->phs = 0; /* & phs */ } p->ampcod = IS_ASIG_ARG(p->xamp) ? 1 : 0; /* (not used by krandh) */ p->cpscod = IS_ASIG_ARG(p->xcps) ? 1 : 0; return OK; } int krandh(CSOUND *csound, RANDH *p) { /* IV - Jul 11 2002 */ *p->ar = *p->base + p->num1 * *p->xamp; /* rslt = num * amp */ p->phs += (long)(*p->xcps * CS_KICVT); /* phs += inc */ if (p->phs >= MAXLEN) { /* when phs overflows, */ p->phs &= PHMASK; /* mod the phs */ if (!p->new) { int16 rand = (int16)p->rand; rand *= RNDMUL; /* & recalc number */ rand += 1; p->num1 = (MYFLT)rand * DV32768; /* IV - Jul 11 2002 */ p->rand = rand; } else { int32 r = randint31(p->rand); /* & recalc number */ p->rand = r; p->num1 = (MYFLT)((int32)((unsigned)r<<1)-BIPOLAR) * dv2_31; } } return OK; } int randh(CSOUND *csound, RANDH *p) { long phs = p->phs, inc; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *ar, *ampp, *cpsp; MYFLT base = *p->base; cpsp = p->xcps; ampp = p->xamp; ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } inc = (long)(*cpsp++ * csound->sicvt); for (n=offset;nnum1 * *ampp; /* rslt = num * amp */ if (p->ampcod) ampp++; phs += inc; /* phs += inc */ if (p->cpscod) inc = (long)(*cpsp++ * csound->sicvt); if (phs >= MAXLEN) { /* when phs o'flows, */ phs &= PHMASK; if (!p->new) { int16 rand = p->rand; rand *= RNDMUL; /* calc new number */ rand += 1; p->num1 = (MYFLT)rand * DV32768; /* IV - Jul 11 2002 */ p->rand = rand; } else { int32 r = randint31(p->rand); /* calc new number */ p->rand = r; p->num1 = (MYFLT)((int32)((unsigned)r<<1)-BIPOLAR) * dv2_31; } } } p->phs = phs; return OK; } int riset(CSOUND *csound, RANDI *p) { p->new = (*p->sel!=FL(0.0)); if (*p->iseed >= FL(0.0)) { /* new seed: */ if (*p->iseed > FL(1.0)) { /* As manual suggest sseed in range [0,1] */ uint32 seed; /* I reinterpret >1 as a time seed */ seed = csound->GetRandomSeedFromTime(); csound->Warning(csound, Str("Seeding from current time %u\n"), seed); if (!p->new) { int16 rand = (int16)seed; /* int16 ss = rand; */ /* IV - Jul 11 2002 */ p->num1 = (MYFLT)(rand) * DV32768; /* store num1,2 */ rand *= RNDMUL; /* recalc random */ rand += 1; /* IV - Jul 11 2002 */ p->num2 = (MYFLT)(p->rand=rand) * DV32768; /* printf("seed, rand, num1, num2 = %d(%x), %d*%x), %f, %f\n", */ /* ss,ss,p->rand, p->rand, p->num1, p->num2); */ } else { p->rand = randint31((int32) (seed % 0x7FFFFFFEUL) + 1L); p->rand = randint31(p->rand); p->num1 = (MYFLT)(p->rand<<1) * dv2_31; /* store num1,2 */ p->rand = randint31(p->rand); p->num2 = (MYFLT)(p->rand<<1) * dv2_31; } } else if (!p->new) { int16 rand = (int16)(*p->iseed * FL(32768.0)); /* init rand integ */ rand *= RNDMUL; /* to 2nd value */ rand += 1; p->num1 = *p->iseed; /* store num1,2 */ p->num2 = (MYFLT)rand * DV32768; /* IV - Jul 11 2002 */ p->rand = rand; } else { MYFLT ss = *p->iseed; if (ss>FL(1.0)) p->rand = (int32) ss; else p->rand = (int32) (*p->iseed * FL(2147483648.0)); p->rand = randint31(p->rand); p->rand = randint31(p->rand); p->num1 = (MYFLT)(p->rand<1) * dv2_31; /* store num1,2 */ p->rand = randint31(p->rand); p->num2 = (MYFLT)(p->rand<<1) * dv2_31; } p->phs = 0; /* & clear phs */ p->dfdmax = (p->num2 - p->num1) / FMAXLEN; /* & diff */ } p->ampcod = IS_ASIG_ARG(p->xamp) ? 1 : 0; /* (not used by krandi) */ p->cpscod = IS_ASIG_ARG(p->xcps) ? 1 : 0; return OK; } int krandi(CSOUND *csound, RANDI *p) { /* rslt = (num1 + diff*phs) * amp */ /* IV - Jul 11 2002 */ *p->ar = *p->base + (p->num1 + (MYFLT)p->phs * p->dfdmax) * *p->xamp; p->phs += (long)(*p->xcps * CS_KICVT); /* phs += inc */ if (p->phs >= MAXLEN) { /* when phs overflows, */ p->phs &= PHMASK; /* mod the phs */ if (!p->new) { int16 rand = p->rand; rand *= RNDMUL; /* recalc random */ rand += 1; p->num1 = p->num2; /* & new num vals */ p->num2 = (MYFLT)rand * DV32768; /* IV - Jul 11 2002 */ p->rand = rand; } else { int32 r = randint31(p->rand); /* recalc random */ p->rand = r; p->num1 = p->num2; /* & new num vals */ p->num2 = (MYFLT)((int32)((unsigned)r<<1)-BIPOLAR) * dv2_31; } p->dfdmax = (p->num2 - p->num1) / FMAXLEN; } return OK; } int randi(CSOUND *csound, RANDI *p) { long phs = p->phs, inc; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *ar, *ampp, *cpsp; MYFLT base = *p->base; cpsp = p->xcps; ampp = p->xamp; ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } inc = (long)(*cpsp++ * csound->sicvt); for (n=offset;nnum1 + (MYFLT)phs * p->dfdmax) * *ampp; if (p->ampcod) ampp++; phs += inc; /* phs += inc */ if (p->cpscod) inc = (long)(*cpsp++ * csound->sicvt); /* (nxt inc) */ if (phs >= MAXLEN) { /* when phs o'flows, */ phs &= PHMASK; if (!p->new) { int16 rand = p->rand; rand *= RNDMUL; /* calc new numbers*/ rand += 1; p->num1 = p->num2; p->num2 = (MYFLT)rand * DV32768; /* IV - Jul 11 2002 */ p->rand = rand; } else { int32 r = randint31(p->rand); /* calc new numbers*/ p->rand = r; p->num1 = p->num2; p->num2 = (MYFLT)((int32)((unsigned)r<<1)-BIPOLAR) * dv2_31; } p->dfdmax = (p->num2 - p->num1) / FMAXLEN; } } p->phs = phs; return OK; } csound-6.10.0/OOps/ugens5.c000066400000000000000000001257721321653344700153510ustar00rootroot00000000000000/* ugens5.c: Copyright (C) 1991 Barry Vercoe, John ffitch, Gabriel Maldonado This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* UGENS5.C */ #include "ugens5.h" #include /* * LPC storage slots */ #define MAX_LPC_SLOT 20 int porset(CSOUND *csound, PORT *p) { p->c2 = pow(0.5, (double)CS_ONEDKR / *p->ihtim); p->c1 = 1.0 - p->c2; if (LIKELY(*p->isig >= FL(0.0))) p->yt1 = (double)(*p->isig); p->ihtim_old = *p->ihtim; return OK; } int kporset(CSOUND *csound, PORT *p) { return porset(csound, p); } int port(CSOUND *csound, PORT *p) { p->yt1 = p->c1 * (double)*p->ksig + p->c2 * p->yt1; *p->kr = (MYFLT)p->yt1; return OK; } int kport(CSOUND *csound, KPORT *p) { if (p->ihtim_old != *p->ihtim) { p->c2 = pow(0.5, (double)CS_ONEDKR / *p->ihtim); p->c1 = 1.0 - p->c2; p->ihtim_old = *p->ihtim; } p->yt1 = p->c1 * (double)*p->ksig + p->c2 * p->yt1; *p->kr = (MYFLT)p->yt1; return OK; } int tonset(CSOUND *csound, TONE *p) { double b; p->prvhp = (double)*p->khp; b = 2.0 - cos((double)(p->prvhp * csound->tpidsr)); p->c2 = b - sqrt(b * b - 1.0); p->c1 = 1.0 - p->c2; if (LIKELY(!(*p->istor))) p->yt1 = 0.0; return OK; } int ktonset(CSOUND *csound, TONE *p) { double b; p->prvhp = (double)*p->khp; b = 2.0 - cos((double)(p->prvhp * CS_ONEDKR *TWOPI)); p->c2 = b - sqrt(b * b - 1.0); p->c1 = 1.0 - p->c2; if (LIKELY(!(*p->istor))) p->yt1 = 0.0; return OK; } int ktone(CSOUND *csound, TONE *p) { double c1 = p->c1, c2 = p->c2; double yt1 = p->yt1; if (*p->khp != (MYFLT)p->prvhp) { double b; p->prvhp = (double)*p->khp; b = 2.0 - cos((double)(p->prvhp * CS_ONEDKR *TWOPI)); p->c2 = c2 = b - sqrt(b * b - 1.0); p->c1 = c1 = 1.0 - c2; } yt1 = c1 * (double)(*p->asig) + c2 * yt1; *p->ar = (MYFLT)yt1; p->yt1 = yt1; return OK; } int tone(CSOUND *csound, TONE *p) { MYFLT *ar, *asig; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; double c1 = p->c1, c2 = p->c2; double yt1 = p->yt1; if (*p->khp != (MYFLT)p->prvhp) { double b; p->prvhp = (double)*p->khp; b = 2.0 - cos((double)(p->prvhp * csound->tpidsr)); p->c2 = c2 = b - sqrt(b * b - 1.0); p->c1 = c1 = 1.0 - c2; } ar = p->ar; asig = p->asig; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nyt1 = yt1; return OK; } int tonsetx(CSOUND *csound, TONEX *p) { /* From Gabriel Maldonado, modified for arbitrary order */ { double b; p->prvhp = *p->khp; b = 2.0 - cos((double)(*p->khp * csound->tpidsr)); p->c2 = b - sqrt(b * b - 1.0); p->c1 = 1.0 - p->c2; } if (UNLIKELY((p->loop = (int) (*p->ord + FL(0.5))) < 1)) p->loop = 4; if (!*p->istor && (p->aux.auxp == NULL || (unsigned int)(p->loop*sizeof(double)) > p->aux.size)) csound->AuxAlloc(csound, (int32)(p->loop*sizeof(double)), &p->aux); p->yt1 = (double*)p->aux.auxp; if (LIKELY(!(*p->istor))) { memset(p->yt1, 0, p->loop*sizeof(double)); /* Punning zero and 0.0 */ } return OK; } int tonex(CSOUND *csound, TONEX *p) /* From Gabriel Maldonado, modified */ { MYFLT *ar = p->ar; double c2 = p->c2, *yt1 = p->yt1,c1 = p->c1; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int j, lp = p->loop; if (*p->khp != p->prvhp) { double b; p->prvhp = (double)*p->khp; b = 2.0 - cos(p->prvhp * (double)csound->tpidsr); p->c2 = b - sqrt(b * b - 1.0); p->c1 = 1.0 - p->c2; } memmove(ar,p->asig,sizeof(MYFLT)*nsmps); if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (j=0; j< lp; j++) { /* Should *yt1 be reset to something?? */ for (n=0; nc2, yt1 = p->yt1; if (*p->khp != p->prvhp) { double b; p->prvhp = *p->khp; b = 2.0 - cos((double)(*p->khp * CS_ONEDKR *TWOPI)); p->c2 = c2 = b - sqrt(b * b - 1.0); /* p->c1 = c1 = 1.0 - c2; */ } sig = *p->asig; x = yt1 = c2 * (yt1 + sig); *p->ar = (MYFLT)x; yt1 -= sig; /* yt1 contains yt1-xt1 */ p->yt1 = yt1; return OK; } int atone(CSOUND *csound, TONE *p) { MYFLT *ar, *asig; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; double c2 = p->c2, yt1 = p->yt1; if (*p->khp != p->prvhp) { double b; p->prvhp = *p->khp; b = 2.0 - cos((double)(*p->khp * csound->tpidsr)); p->c2 = c2 = b - sqrt(b * b - 1.0); /* p->c1 = c1 = 1.0 - c2; */ } ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } asig = p->asig; for (n=offset; nyt1 = yt1; return OK; } int atonex(CSOUND *csound, TONEX *p) /* Gabriel Maldonado, modified */ { MYFLT *ar = p->ar; double c2 = p->c2, *yt1 = p->yt1; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int j, lp = p->loop; if (*p->khp != p->prvhp) { double b; p->prvhp = *p->khp; b = 2.0 - cos((double)(*p->khp * csound->tpidsr)); p->c2 = b - sqrt(b * b - 1.0); /*p->c1 = 1. - p->c2;*/ } memmove(ar,p->asig,sizeof(MYFLT)*nsmps); if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (j=1; jscale = scale = (int)*p->iscl; if (UNLIKELY(scale && scale != 1 && scale != 2)) { return csound->InitError(csound, Str("illegal reson iscl value, %f"), *p->iscl); } p->prvcf = p->prvbw = -100.0; if (!(*p->istor)) p->yt1 = p->yt2 = 0.0; p->asigf = IS_ASIG_ARG(p->kcf); p->asigw = IS_ASIG_ARG(p->kbw); return OK; } int krsnset(CSOUND *csound, RESON *p){ return rsnset(csound,p); } int kreson(CSOUND *csound, RESON *p) { uint32_t flag = 0; double c3p1, c3t4, omc3, c2sqr; double yt0, yt1, yt2, c1 = p->c1, c2 = p->c2, c3 = p->c3; IGN(csound); if (*p->kcf != (MYFLT)p->prvcf) { p->prvcf = (double)*p->kcf; p->cosf = cos(p->prvcf * (double)(CS_ONEDKR *TWOPI)); flag = 1; /* Mark as changed */ } if (*p->kbw != (MYFLT)p->prvbw) { p->prvbw = (double)*p->kbw; c3 = p->c3 = exp(p->prvbw * (double)(-CS_ONEDKR *TWOPI)); flag = 1; /* Mark as changed */ } if (flag) { c3p1 = c3 + 1.0; c3t4 = c3 * 4.0; omc3 = 1.0 - c3; c2 = p->c2 = c3t4 * p->cosf / c3p1; /* -B, so + below */ c2sqr = c2 * c2; if (p->scale == 1) c1 = p->c1 = omc3 * sqrt(1.0 - c2sqr / c3t4); else if (p->scale == 2) c1 = p->c1 = sqrt((c3p1*c3p1-c2sqr) * omc3/c3p1); else c1 = p->c1 = 1.0; } yt1 = p->yt1; yt2 = p->yt2; yt0 = c1 * ((double)*p->asig) + c2 * yt1 - c3 * yt2; *p->ar = (MYFLT)yt0; p->yt1 = yt0; p->yt2 = yt1; /* Write back for next cycle */ return OK; } int reson(CSOUND *csound, RESON *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t flag = 0, n, nsmps = CS_KSMPS; MYFLT *ar, *asig; double c3p1, c3t4, omc3, c2sqr; double yt1, yt2, c1 = p->c1, c2 = p->c2, c3 = p->c3; int asigf = p->asigf; int asigw = p->asigw; asig = p->asig; ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } yt1 = p->yt1; yt2 = p->yt2; for (n=offset; nkcf[n] : *p->kcf; MYFLT bw = asigw ? p->kbw[n] : *p->kbw; if (cf != (MYFLT)p->prvcf) { p->prvcf = (double)cf; p->cosf = cos(cf * (double)(csound->tpidsr)); flag = 1; /* Mark as changed */ } if (bw != (MYFLT)p->prvbw) { p->prvbw = (double)bw; c3 = p->c3 = exp(bw * (double)(csound->mtpdsr)); flag = 1; /* Mark as changed */ } if (flag) { c3p1 = c3 + 1.0; c3t4 = c3 * 4.0; omc3 = 1.0 - c3; c2 = p->c2 = c3t4 * p->cosf / c3p1; /* -B, so + below */ c2sqr = c2 * c2; if (p->scale == 1) c1 = p->c1 = omc3 * sqrt(1.0 - c2sqr / c3t4); else if (p->scale == 2) c1 = p->c1 = sqrt((c3p1*c3p1-c2sqr) * omc3/c3p1); else c1 = p->c1 = 1.0; flag = 0; } yt0 = c1 * ((double)asig[n]) + c2 * yt1 - c3 * yt2; ar[n] = (MYFLT)yt0; yt2 = yt1; yt1 = yt0; } p->yt1 = yt1; p->yt2 = yt2; /* Write back for next cycle */ return OK; } int rsnsetx(CSOUND *csound, RESONX *p) { /* Gabriel Maldonado, modifies for arb order */ int scale; p->scale = scale = (int) *p->iscl; if ((p->loop = (int) (*p->ord + FL(0.5))) < 1) p->loop = 4; /* default value */ if (!*p->istor && (p->aux.auxp == NULL || (unsigned int)(p->loop*2*sizeof(double)) > p->aux.size)) csound->AuxAlloc(csound, (int32)(p->loop*2*sizeof(double)), &p->aux); p->yt1 = (double*)p->aux.auxp; p->yt2 = (double*)p->aux.auxp + p->loop; if (UNLIKELY(scale && scale != 1 && scale != 2)) { return csound->InitError(csound, Str("illegal reson iscl value, %f"), *p->iscl); } p->prvcf = p->prvbw = -100.0; if (!(*p->istor)) { memset(p->yt1, 0, p->loop*sizeof(double)); memset(p->yt2, 0, p->loop*sizeof(double)); } return OK; } int resonx(CSOUND *csound, RESONX *p) /* Gabriel Maldonado, modified */ { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t flag = 0, n, nsmps = CS_KSMPS; int j; MYFLT *ar; double c3p1, c3t4, omc3, c2sqr; double *yt1, *yt2, c1,c2,c3; int asgf = IS_ASIG_ARG(p->kcf); int asgw = IS_ASIG_ARG(p->kbw); ar = p->ar; c1 = p->c1; c2 = p->c2; c3 = p->c3; yt1 = p->yt1; yt2 = p->yt2; ar = p->ar; memmove(ar,p->asig,sizeof(MYFLT)*nsmps); if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (j=0; j< p->loop; j++) { for (n=offset; nkcf[n] : *p->kcf; MYFLT bw = asgw ? p->kbw[n] : *p->kbw; if (cf != (MYFLT)p->prvcf) { p->prvcf = (double)cf; p->cosf = cos(cf * (double)(csound->tpidsr)); flag = 1; } if (bw != (MYFLT)p->prvbw) { p->prvbw = (double)bw; c3 = exp(bw * (double)(csound->mtpdsr)); flag = 1; } if (flag) { c3p1 = c3 + 1.0; c3t4 = c3 * 4.0; omc3 = 1.0 - c3; c2 = c3t4 * p->cosf / c3p1; /* -B, so + below */ c2sqr = c2 * c2; if (p->scale == 1) c1 = omc3 * sqrt(1.0 - (c2sqr / c3t4)); else if (p->scale == 2) c1 = sqrt((c3p1*c3p1-c2sqr) * omc3/c3p1); else c1 = 1.0; flag =0; } x = c1 * ((double)ar[n]) + c2 * yt1[j] - c3 * yt2[j]; yt2[j] = yt1[j]; ar[n] = (MYFLT)x; yt1[j] = x; } } p->c1 = c1; p->c2 = c2; p->c3 = c3; return OK; } int kareson(CSOUND *csound, RESON *p) { uint32_t flag = 0; double c3p1, c3t4, omc3, c2sqr; //, D = 2.0; /* 1/RMS = root2 (rand) */ /* or 1/.5 (sine) */ double yt1, yt2, c1, c2, c3; IGN(csound); if (*p->kcf != (MYFLT)p->prvcf) { p->prvcf = (double)*p->kcf; p->cosf = cos(p->prvcf * (double)(CS_ONEDKR *TWOPI)); flag = 1; } if (*p->kbw != (MYFLT)p->prvbw) { p->prvbw = (double)*p->kbw; p->c3 = exp(p->prvbw * (double)(-CS_ONEDKR *TWOPI)); flag = 1; } if (flag) { c3p1 = p->c3 + 1.0; c3t4 = p->c3 * 4.0; omc3 = 1.0 - p->c3; p->c2 = c3t4 * p->cosf / c3p1; c2sqr = p->c2 * p->c2; if (p->scale == 1) /* i.e. 1 - A(reson) */ p->c1 = 1.0 - omc3 * sqrt(1.0 - c2sqr / c3t4); else if (p->scale == 2) /* i.e. D - A(reson) */ p->c1 = 2.0 - sqrt((c3p1*c3p1-c2sqr)*omc3/c3p1); else p->c1 = 0.0; /* cannot tell */ } c1 = p->c1; c2 = p->c2; c3 = p->c3; yt1 = p->yt1; yt2 = p->yt2; if (p->scale == 1 || p->scale == 0) { double sig = (double) *p->asig; double ans = c1 * sig + c2 * yt1 - c3 * yt2; yt2 = yt1; yt1 = ans - sig; /* yt1 contains yt1-xt1 */ *p->ar = (MYFLT)ans; } else if (p->scale == 2) { double sig = (double) *p->asig; double ans = c1 * sig + c2 * yt1 - c3 * yt2; yt2 = yt1; yt1 = ans - 2.0 * sig; /* yt1 contains yt1-D*xt1 */ *p->ar = (MYFLT)ans; } p->yt1 = yt1; p->yt2 = yt2; return OK; } int areson(CSOUND *csound, RESON *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t flag = 0, n, nsmps = CS_KSMPS; MYFLT *ar, *asig; double c3p1, c3t4, omc3, c2sqr;//, D = 2.0; /* 1/RMS = root2 (rand) */ /* or 1/.5 (sine) */ double yt1, yt2, c1, c2, c3; if (*p->kcf != (MYFLT)p->prvcf) { p->prvcf = (double)*p->kcf; p->cosf = cos(p->prvcf * (double)(csound->tpidsr)); flag = 1; } if (*p->kbw != (MYFLT)p->prvbw) { p->prvbw = (double)*p->kbw; p->c3 = exp(p->prvbw * (double)(csound->mtpdsr)); flag = 1; } if (flag) { c3p1 = p->c3 + 1.0; c3t4 = p->c3 * 4.0; omc3 = 1.0 - p->c3; p->c2 = c3t4 * p->cosf / c3p1; c2sqr = p->c2 * p->c2; if (p->scale == 1) /* i.e. 1 - A(reson) */ p->c1 = 1.0 - omc3 * sqrt(1.0 - c2sqr / c3t4); else if (p->scale == 2) /* i.e. D - A(reson) */ p->c1 = 2.0 - sqrt((c3p1*c3p1-c2sqr)*omc3/c3p1); else p->c1 = 0.0; /* cannot tell */ } asig = p->asig; ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } c1 = p->c1; c2 = p->c2; c3 = p->c3; yt1 = p->yt1; yt2 = p->yt2; if (p->scale == 1 || p->scale == 0) { for (n=offset; nscale == 2) { for (n=offset; nyt1 = yt1; p->yt2 = yt2; return OK; } /* * * LPREAD opcode : initialisation phase * * */ int lprdset_(CSOUND *csound, LPREAD *p, int stringname) { LPHEADER *lph; MEMFIL *mfp; int32 magic; int32 totvals; char lpfilname[MAXNAME]; /* Store adress of opcode for other lpXXXX init to point to */ if (csound->lprdaddr == NULL || csound->currentLPCSlot >= csound->max_lpc_slot) { csound->max_lpc_slot = csound->currentLPCSlot + MAX_LPC_SLOT; csound->lprdaddr = csound->ReAlloc(csound, csound->lprdaddr, csound->max_lpc_slot * sizeof(LPREAD*)); } ((LPREAD**) csound->lprdaddr)[csound->currentLPCSlot] = p; /* Build file name */ if (stringname) strncpy(lpfilname, ((STRINGDAT*)p->ifilcod)->data, MAXNAME-1); else if (csound->ISSTRCOD(*p->ifilcod)) strncpy(lpfilname, get_arg_string(csound, *p->ifilcod), MAXNAME-1); else csound->strarg2name(csound, lpfilname, p->ifilcod, "lp.", 0); /* Do not reload existing file ? */ if (UNLIKELY((mfp = p->mfp) != NULL && strcmp(mfp->filename, lpfilname) == 0)) goto lpend; /* rtn if file prv known */ /* Load analysis in memory file */ /* else read file */ if (UNLIKELY((mfp = ldmemfile2withCB(csound, lpfilname, CSFTYPE_LPC, NULL)) == NULL)) { return csound->InitError(csound, Str("LPREAD cannot load %s"), lpfilname); } /* Store memory file location in opcode */ p->mfp = mfp; /* & record facts */ /* Take a peek to the header if exisiting. Else take input arguments */ lph = (LPHEADER *) mfp->beginp; magic=lph->lpmagic; if (LIKELY((magic==LP_MAGIC)||(magic==LP_MAGIC2))) { p->storePoles = (magic==LP_MAGIC2); csound->Warning(csound, Str("Using %s type of file.\n"), p->storePoles?Str("pole"):Str("filter coefficient")); /* Store header length */ p->headlen = lph->headersize; /* Check if input values where available */ if (*p->inpoles || *p->ifrmrate) { csound->Warning(csound, Str("lpheader overriding inputs")); } /* Check orc/analysis sample rate compatibility */ if (lph->srate != csound->esr) { csound->Warning(csound, Str("lpfile srate != orch sr")); } p->npoles = lph->npoles; /* note npoles, etc. */ /* Store header info in opcode */ p->nvals = lph->nvals; p->framrat16 = lph->framrate * FL(65536.0);/* scaled framno cvt */ } else if (UNLIKELY(BYTREVL(lph->lpmagic) == LP_MAGIC)) { /* Header reversed: */ return csound->InitError(csound, Str("file %s bytes are in wrong order"), lpfilname); } else { /* No Header on file:*/ p->headlen = 0; p->npoles = (int32)*p->inpoles; /* data from inargs */ p->nvals = p->npoles + 4; p->framrat16 = *p->ifrmrate * FL(65536.0); if (UNLIKELY(!p->npoles || !p->framrat16)) { return csound->InitError(csound, Str("insufficient args and no file header")); } } /* Check pole number */ csound->AuxAlloc(csound, (int32)(p->npoles*8*sizeof(MYFLT)), &p->aux); p->kcoefs = (MYFLT*)p->aux.auxp; /* if (UNLIKELY(p->npoles > MAXPOLES)) { */ /* return csound->InitError(csound, Str("npoles > MAXPOLES")); */ /* } */ /* Look for total frame data size (file size - header) */ totvals = (mfp->length - p->headlen)/sizeof(MYFLT); /* Store the size of a frame in integer */ p->lastfram16 = (((totvals - p->nvals) / p->nvals) << 16) - 1; if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, Str( "npoles %d, nvals %d, totvals %d, lastfram16 = %x\n"), p->npoles, p->nvals, totvals, p->lastfram16); lpend: p->lastmsg = 0; return OK; } int lprdset(CSOUND *csound, LPREAD *p){ return lprdset_(csound, p, 0); } int lprdset_S(CSOUND *csound, LPREAD *p){ return lprdset_(csound, p, 1); } #ifdef TRACE_POLES static void DumpPolesF(int poleCount, MYFLT *part1, MYFLT *part2, int isMagn, char *where) { int i; csound->Message(csound, "%s\n", where); for (i=0; iMessage(csound, Str("magnitude: %f Phase: %f\n"), part1[i], part2[i]); else csound->Message(csound, Str("Real: %f Imag: %f\n"), part1[i], part2[i]); } } #endif static void SortPoles(int poleCount, MYFLT *poleMagn, MYFLT *polePhas) { int i, j; MYFLT diff, fTemp; int shouldSwap; /* DumpPolesF(poleCount, poleMagn, polePhas, 1, "Before sort"); */ for (i=1; iFL(1.0e-10)) shouldSwap = 1; else if (diff>-FL(1.0e-10)) { diff = poleMagn[j]-poleMagn[i]; if (diff>FL(1.0e-10)) shouldSwap = 1; else if (diff>-FL(1.0e-10)) { if (polePhas[j]>polePhas[i]) shouldSwap = 1; } } if (shouldSwap) { fTemp = poleMagn[i]; poleMagn[i] = poleMagn[j]; poleMagn[j] = fTemp; fTemp = polePhas[i]; polePhas[i] = polePhas[j]; polePhas[j] = fTemp; } } } /* DumpPolesF(poleCount, poleMagn, polePhas, 1, "After sort"); */ } static int DoPoleInterpolation(int poleCount, MYFLT *pm1, MYFLT *pp1, MYFLT *pm2, MYFLT *pp2, MYFLT factor, MYFLT *outMagn, MYFLT *outPhas) { int i; if (UNLIKELY(poleCount%2!=0)) { printf (Str("Cannot handle uneven pole count yet \n")); return (0); } for (i=0; i=0; k--) { cr = polyReal[k]; ci = polyImag[k]; polyReal[k] = -(cr*pr-ci*pi); polyImag[k] = -(ci*pr+cr*pi); if (LIKELY(k>0)) { polyReal[k] += polyReal[k-1]; polyImag[k] += polyImag[k-1]; } } } /* Makes it 1+a1.x+...+anXn */ pr = polyReal[0]; for (j=0; j<=poleCount; j++) polyReal[j] /= pr; } /* * * LPREAD k/a time access. This will setup current pole values * */ int lpread(CSOUND *csound, LPREAD *p) { MYFLT *bp, *np, *cp; int32 nn, framphase; MYFLT fract; int i, status; MYFLT *poleMagn1 = p->kcoefs + 2*p->npoles; MYFLT *polePhas1 = poleMagn1 + p->npoles; MYFLT *poleMagn2 = polePhas1 + p->npoles; MYFLT *polePhas2 = poleMagn2 + p->npoles; MYFLT *interMagn = polePhas2 + p->npoles; MYFLT *interPhas = interMagn + p->npoles; if (UNLIKELY(p->mfp==NULL)) { return csound->PerfError(csound, p->h.insdshead, Str("lpread: not initialised")); } /* Locate frame position range */ if (UNLIKELY((framphase = (int32)(*p->ktimpt*p->framrat16)) < 0)) { /* for kfram reqd*/ return csound->PerfError(csound, p->h.insdshead, Str("lpread timpnt < 0")); } if (framphase > p->lastfram16) { /* not past last one */ framphase = p->lastfram16; if (UNLIKELY(!p->lastmsg)) { p->lastmsg = 1; csound->Warning(csound, Str("lpread ktimpnt truncated to last frame")); } } /* Locate frames bounding current time */ bp = (MYFLT *)(p->mfp->beginp + p->headlen); /* locate begin frame data */ nn = (framphase >> 16) * p->nvals; bp = bp + nn; /* locate begin this frame */ np = bp + p->nvals; /* & interp betw adj frams */ fract = (framphase & 0x0FFFFL) / FL(65536.0); /* Interpolate freq/amplpitude and store in opcode */ *p->krmr = *bp + (*np - *bp) * fract; bp++; np++; /* for 4 rslts */ *p->krmo = *bp + (*np - *bp) * fract; bp++; np++; *p->kerr = *bp + (*np - *bp) * fract; bp++; np++; *p->kcps = *bp + (*np - *bp) * fract; bp++; np++; /* Interpolate filter or poles coef values and store in opcode */ cp = p->kcoefs; /* This is where the coefs get stored */ if (p->storePoles) { for (i=0; inpoles; i++) { poleMagn1[i] = *bp++; polePhas1[i] = *bp++; poleMagn2[i] = *np++; polePhas2[i] = *np++; } status = DoPoleInterpolation(p->npoles,poleMagn1,polePhas1,poleMagn2, polePhas2,fract,interMagn,interPhas); if (UNLIKELY(!status)) { return csound->PerfError(csound, p->h.insdshead, Str("Interpolation failed")); } for (i=0; inpoles; i++) { *cp++ = interMagn[i]; *cp++ = interPhas[i]; } } else { for (nn = 0; nn< p->npoles; nn++) { cp[nn] = bp[nn] + (np[nn] - bp[nn]) * fract; } } /* if (csound->oparms->odebug) { csound->Message(csound, "phase:%lx fract:%6.2f rmsr:%6.2f rmso:%6.2f kerr:%6.2f kcps:%6.2f\n", framphase,fract,*p->krmr,*p->krmo,*p->kerr,*p->kcps); cp = p->kcoefs; nn = p->npoles; do { csound->Message(csound, " %6.2f",*cp++); } while (--nn); csound->Message(csound, "\n"); } */ return OK; } int lpformantset(CSOUND *csound, LPFORM *p) { LPREAD *q; /* connect to previously loaded lpc analysis */ /* get adr lpread struct */ p->lpread = q = ((LPREAD**) csound->lprdaddr)[csound->currentLPCSlot]; csound->AuxAlloc(csound, p->lpread->npoles*sizeof(MYFLT), &p->aux); return OK; } int lpformant(CSOUND *csound, LPFORM *p) { LPREAD *q = p->lpread; MYFLT *coefp, sr = csound->esr; MYFLT *cfs = (MYFLT*)p->aux.auxp; MYFLT *bws = cfs+p->lpread->npoles/2; int i, j, ndx = *p->kfor; double pm,pp; if (q->storePoles) { coefp = q->kcoefs; for (i=2,j=0; inpoles*2; i+=4, j++) { pm = coefp[i]; pp = coefp[i+1]; cfs[j] = pp*sr/TWOPI; /* if (pm > 1.0) csound->Message(csound, Str("warning unstable pole %f\n"), pm); */ bws[j] = -LOG(pm)*sr/PI; } } else { csound->PerfError(csound, p->h.insdshead, Str("this opcode only works with LPC " "pole analysis type (-a)\n")); return NOTOK; } j = (ndx < 1 ? 1 : (ndx >= p->lpread->npoles/2 ? p->lpread->npoles/2 : ndx)) - 1; if (bws[j] > sr/2 || isnan(bws[j])) bws[j] = sr/2; if (bws[j] < 1.0) bws[j] = 1.0; if (cfs[j] > sr/2 || isnan(cfs[j])) cfs[j] = sr/2; cfs[j] = FABS(cfs[j]); *p->kcf = cfs[j]; *p->kbw = bws[j]; return OK; } /* * * LPRESON: initialisation time * * */ int lprsnset(CSOUND *csound, LPRESON *p) { LPREAD *q; /* connect to previously loaded lpc analysis */ /* get adr lpread struct */ p->lpread = q = ((LPREAD**) csound->lprdaddr)[csound->currentLPCSlot]; csound->AuxAlloc(csound, (int32)((q->npoles<<1)*sizeof(MYFLT)), &p->aux); /* Initialize pointer to circulat buffer (for filtering) */ p->circjp = p->circbuf = (MYFLT*)p->aux.auxp; p->jp2lim = p->circbuf + (q->npoles << 1); /* npoles det circbuflim */ return OK; } /* * * LPRESON: k & a time access. Will actually filter the signal * Uses a circular buffer to store previous signal values. */ int lpreson(CSOUND *csound, LPRESON *p) { LPREAD *q = p->lpread; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *coefp, *pastp, *jp, *jp2, *rslt = p->ar, *asig = p->asig; MYFLT x; double poleReal[MAXPOLES], poleImag[MAXPOLES]; double polyReal[MAXPOLES+1], polyImag[MAXPOLES+1]; int i, nn; double pm,pp; jp = p->circjp; jp2 = jp + q->npoles; /* If we where using poles, we have to compute filter coefs now */ if (q->storePoles) { coefp = q->kcoefs; for (i=0; inpoles; i++) { pm = *coefp++; pp = *coefp++; /* csound->Message(csound, "pole %d, fr=%.2f, BW=%.2f\n", i, pp*(csound->esr)/6.28, -csound->esr*log(pm)/3.14); */ if (fabs(pm)>0.999999) pm = 1/pm; poleReal[i] = pm*cos(pp); poleImag[i] = pm*sin(pp); } /* DumpPoles(q->npoles,poleReal,poleImag,0,"About to filter"); */ InvertPoles(q->npoles,poleReal,poleImag); synthetize(q->npoles,poleReal,poleImag,polyReal,polyImag); coefp = q->kcoefs; for (i=0; inpoles; i++) { /* MR_WHY - somthing with the atan2 ? */ coefp[i] = -(MYFLT)polyReal[q->npoles-i]; } } if (UNLIKELY(offset)) memset(rslt, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rslt[nsmps], '\0', early*sizeof(MYFLT)); } /* For each sample */ for (n=offset; nMessage(csound, "Asig=%f\n", *asig); #endif x = asig[n]; coefp = q->kcoefs; /* using lpread interp coefs */ pastp = jp; nn = q->npoles; do { #ifdef TRACE_FILTER csound->Message(csound, "\t%f,%f\n", *coefp, *pastp); #endif x += *coefp++ * *pastp++; } while (--nn); #ifdef TRACE_FILTER csound->Message(csound, "result=%f\n", x); #endif /* Store result signal in circular and output buffers */ *jp++ = *jp2++ = x; rslt[n] = x; /* Check if end of buffer reached */ if (jp2 >= p->jp2lim) { jp2 = jp; jp = p->circbuf; } } p->circjp = jp; return OK; } /* * * LPFRESON : Initialisation time * */ int lpfrsnset(CSOUND *csound, LPFRESON *p) { /* Connect to previously loaded analysis file */ if (((LPREAD**) csound->lprdaddr)[csound->currentLPCSlot]->storePoles) { return csound->InitError(csound, Str("Pole file not supported " "for this opcode !")); } p->lpread = ((LPREAD**) csound->lprdaddr)[csound->currentLPCSlot]; p->prvratio = FL(1.0); p->d = FL(0.0); p->prvout = FL(0.0); csound->AuxAlloc(csound, (int32)(p->lpread->npoles*sizeof(MYFLT)), &p->aux); p->past = (MYFLT*)p->aux.auxp; return OK; } /* * * LPFRESON : k & a time : actually filters the data * */ int lpfreson(CSOUND *csound, LPFRESON *p) { LPREAD *q = p->lpread; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, n, nsmps = CS_KSMPS; MYFLT *coefp, *pastp, *pastp1, *rslt = p->ar, *asig = p->asig; MYFLT x, temp1, temp2, ampscale, cq; if (*p->kfrqratio != p->prvratio) { /* for new freqratio */ if (*p->kfrqratio <= FL(0.0)) { return csound->PerfError(csound, p->h.insdshead, Str("illegal frqratio, %5.2f"), *p->kfrqratio); } /* calculate d */ p->d = (*p->kfrqratio - FL(1.0)) / (*p->kfrqratio + FL(1.0)); p->prvratio = *p->kfrqratio; } if (p->d != FL(0.0)) { /* for non-zero d, */ coefp = q->kcoefs; nn = q->npoles - 1; do { temp1 = p->d * *coefp++; /* shift formants */ *coefp += temp1; } while (--nn); ampscale = FL(1.0) / (FL(1.0) - p->d * *coefp); /* & reset scales */ cq = (FL(1.0) - p->d * p->d) * ampscale; } else { cq = FL(1.0); ampscale = FL(1.0); } x = p->prvout; if (UNLIKELY(offset)) memset(rslt, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rslt[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nnpoles - 1; pastp = pastp1 = p->past + nn; temp1 = *pastp; *pastp = cq * x - p->d * *pastp; pastp--; do { temp2 = *pastp; *pastp = (*pastp1 - *pastp) * p->d + temp1; pastp--; pastp1--; temp1 = temp2; } while (--nn); x = asig[n]; pastp = p->past; coefp = q->kcoefs; nn = q->npoles; do { x += *coefp++ * *pastp++; } while (--nn); rslt[n] = x * ampscale; } p->prvout = x; return OK; } int rmsset(CSOUND *csound, RMS *p) { double b; b = 2.0 - cos((double)(*p->ihp * csound->tpidsr)); p->c2 = b - sqrt(b*b - 1.0); p->c1 = 1.0 - p->c2; if (!*p->istor) p->prvq = 0.0; return OK; } int gainset(CSOUND *csound, GAIN *p) { double b; b = 2.0 - cos((double)(*p->ihp * csound->tpidsr)); p->c2 = b - sqrt(b*b - 1.0); p->c1 = 1.0 - p->c2; if (!*p->istor) p->prvq = p->prva = 0.0; return OK; } int balnset(CSOUND *csound, BALANCE *p) { double b; b = 2.0 - cos((double)(*p->ihp * csound->tpidsr)); p->c2 = b - sqrt(b*b - 1.0); p->c1 = 1.0 - p->c2; if (!*p->istor) p->prvq = p->prvr = p->prva = 0.0; return OK; } int rms(CSOUND *csound, RMS *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *asig; double q; double c1 = p->c1, c2 = p->c2; q = p->prvq; asig = p->asig; if (UNLIKELY(early)) nsmps -= early; for (n=offset; nprvq = q; *p->kr = (MYFLT) sqrt(q); return OK; } int gain(CSOUND *csound, GAIN *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *ar, *asig; double q, a, m, diff, inc; double c1 = p->c1, c2 = p->c2; q = p->prvq; asig = p->asig; if (UNLIKELY(early)) nsmps -= early; for (n = offset; n < nsmps-early; n++) { double as = (double)asig[n]; q = c1 * as * as + c2 * q; } p->prvq = q; if (q > 0.0) a = *p->krms / sqrt(q); else a = *p->krms; ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } if ((diff = a - p->prva) != 0.0) { m = p->prva; inc = diff / (double)(nsmps-offset); for (n = offset; n < nsmps; n++) { ar[n] = asig[n] * m; m += inc; } p->prva = a; } else { for (n = offset; n < nsmps; n++) { ar[n] = asig[n] * a; } } return OK; } int balance(CSOUND *csound, BALANCE *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *ar, *asig, *csig; double q, r, a, m, diff, inc; double c1 = p->c1, c2 = p->c2; q = p->prvq; r = p->prvr; asig = p->asig; csig = p->csig; ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { double as = (double)asig[n]; double cs = (double)csig[n]; q = c1 * as * as + c2 * q; r = c1 * cs * cs + c2 * r; } p->prvq = q; p->prvr = r; if (LIKELY(q != 0.0)) a = sqrt(r/q); else a = sqrt(r); if ((diff = a - p->prva) != 0.0) { m = p->prva; inc = diff / (double)(nsmps-offset); for (n = offset; n < nsmps; n++) { ar[n] = asig[n] * m; m += inc; } p->prva = a; } else { for (n = offset; n < nsmps; n++) { ar[n] = asig[n] * a; } } return OK; } /* * Set current lpc slot */ int lpslotset(CSOUND *csound, LPSLOT *p) { int n; n = (int) *(p->islotnum); if (UNLIKELY(n < 0)) return csound->InitError(csound, Str("lpslot number should be positive")); else { if (n >= csound->max_lpc_slot) { csound->max_lpc_slot = n + MAX_LPC_SLOT; csound->lprdaddr = csound->ReAlloc(csound, csound->lprdaddr, csound->max_lpc_slot * sizeof(LPREAD**)); } csound->currentLPCSlot = n; } return OK; } int lpitpset(CSOUND *csound, LPINTERPOL *p) { if (UNLIKELY((unsigned int) ((int) *(p->islot1)) >= (unsigned int) csound->max_lpc_slot || (unsigned int) ((int) *(p->islot2)) >= (unsigned int) csound->max_lpc_slot)) return csound->InitError(csound, Str("LPC slot is not allocated")); /* Get lpread pointers */ p->lp1 = ((LPREAD**) csound->lprdaddr)[(int) *(p->islot1)]; p->lp2 = ((LPREAD**) csound->lprdaddr)[(int) *(p->islot2)]; /* Check if workable */ if (UNLIKELY((!p->lp1->storePoles) || (!p->lp2->storePoles))) { return csound->InitError(csound, Str("lpinterpol works only " "with poles files..")); } if (UNLIKELY(p->lp1->npoles != p->lp2->npoles)) { return csound->InitError(csound, Str("The poles files " "have different pole count")); } #if 0 /* This is incorrect C */ if (&p->kcoefs-p != &p->lp1->kcoefs-p->lp1) return csound->InitError(csound, Str("padding error")); #endif p->npoles = p->lp1->npoles; csound->AuxAlloc(csound, (int32)(p->npoles*8*sizeof(MYFLT)), &p->aux); p->kcoefs = (MYFLT*)p->aux.auxp; p->storePoles = 1; ((LPREAD**) csound->lprdaddr)[csound->currentLPCSlot] = (LPREAD*) p; return OK; } int lpinterpol(CSOUND *csound, LPINTERPOL *p) { int i,status; MYFLT *cp,*cp1,*cp2; MYFLT *poleMagn1 = p->kcoefs + 2*p->npoles; MYFLT *polePhas1 = poleMagn1 + p->npoles; MYFLT *poleMagn2 = polePhas1 + p->npoles; MYFLT *polePhas2 = poleMagn2 + p->npoles; MYFLT *interMagn = polePhas2 + p->npoles; MYFLT *interPhas = interMagn + p->npoles; /* RWD: guessing this... */ if (UNLIKELY(p->lp1==NULL || p->lp2==NULL)) { return csound->PerfError(csound, p->h.insdshead, Str("lpinterpol: not initialised")); } cp1 = p->lp1->kcoefs; cp2 = p->lp2->kcoefs; for (i=0; inpoles; i++) { poleMagn1[i] = *cp1++; polePhas1[i] = *cp1++; poleMagn2[i] = *cp2++; polePhas2[i] = *cp2++; } status = DoPoleInterpolation(p->npoles,poleMagn1,polePhas1,poleMagn2, polePhas2,*p->kmix,interMagn,interPhas); if (UNLIKELY(!status)) { return csound->PerfError(csound, p->h.insdshead, Str("Interpolation failed")); } cp = p->kcoefs; /* This is where the coefs get stored */ for (i=0; inpoles; i++) { *cp++ = interMagn[i]; *cp++ = interPhas[i]; } return OK; } int klimit(CSOUND *csound, LIMIT *p) { MYFLT sig=*p->sig, min=*p->min, max=*p->max; if (LIKELY((sig <= max) && (sig >= min))) { *p->ans = sig; } else { if ( min >= max) { *p->ans = FL(0.5) * (min + max); } else { if (sig > max) *p->ans = max; else *p->ans = min; } } return OK; } int limit(CSOUND *csound, LIMIT *p) { MYFLT *ans, *asig; MYFLT min=*p->min, max=*p->max, aver; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; ans = p->ans; asig = p->sig; if (UNLIKELY(offset)) memset(ans, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ans[nsmps], '\0', early*sizeof(MYFLT)); } if (min >= max) { aver = (min + max) * FL(0.5); for (n=offset; n= min)) { ans[n] = asig[n]; } else { if (asig[n] > max) ans[n] = max; else ans[n] = min; } } return OK; } csound-6.10.0/OOps/ugens6.c000066400000000000000000001142771321653344700153500ustar00rootroot00000000000000/* ugens6.c: Copyright (C) 1991-2000 Barry Vercoe, John ffitch, Jens Groh, Hans Mikelson, Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* UGENS6.C */ #include "ugens6.h" #include #define log001 (-FL(6.9078)) /* log(.001) */ int downset(CSOUND *csound, DOWNSAMP *p) { if (UNLIKELY((p->len = (unsigned int)*p->ilen) > CS_KSMPS)) return csound->InitError(csound, "ilen > ksmps"); return OK; } int downsamp(CSOUND *csound, DOWNSAMP *p) { MYFLT *asig, sum; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; int len, n; if (p->len <= 1) *p->kr = p->asig[offset]; else { asig = p->asig; sum = FL(0.0); len = p->len; if (len>(int)(CS_KSMPS-early)) len = early; for (n=offset; nkr = sum / p->len; } return OK; } int upsamp(CSOUND *csound, UPSAMP *p) { MYFLT kval = *p->ksig; MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) ar[n] = kval; return OK; } int a_k_set(CSOUND *csound, INTERP *p) { p->prev = FL(0.0); p->init_k = 0; /* IV - Sep 5 2002 */ return OK; } int interpset(CSOUND *csound, INTERP *p) { if (*p->istor == FL(0.0)) { p->prev = (*p->imode == FL(0.0) ? *p->istart : FL(0.0)); p->init_k = (*p->imode == FL(0.0) ? 0 : 1); /* IV - Sep 5 2002 */ } return OK; } int interp(CSOUND *csound, INTERP *p) { MYFLT *ar, val, incr; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; ar = p->rslt; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } if (p->init_k) { p->init_k = 0; p->prev = *p->xsig; } val = p->prev; incr = (*p->xsig - val) / (nsmps-offset); for (n=offset; nprev = val; return OK; } int indfset(CSOUND *csound, INDIFF *p) { if (*p->istor == FL(0.0)) /* IV - Sep 5 2002 */ p->prev = FL(0.0); return OK; } int kntegrate(CSOUND *csound, INDIFF *p) { *p->rslt = p->prev += *p->xsig; return OK; } int integrate(CSOUND *csound, INDIFF *p) { MYFLT *rslt, *asig, sum; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; rslt = p->rslt; if (UNLIKELY(offset)) memset(rslt, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rslt[nsmps], '\0', early*sizeof(MYFLT)); } asig = p->xsig; sum = p->prev; for (n=offset; nprev = sum; return OK; } int kdiff(CSOUND *csound, INDIFF *p) { MYFLT tmp; tmp = *p->xsig; /* IV - Sep 5 2002: fix to make */ *p->rslt = tmp - p->prev; /* diff work when the input and */ p->prev = tmp; /* output argument is the same */ return OK; } int diff(CSOUND *csound, INDIFF *p) { MYFLT *ar, *asig, prev, tmp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; ar = p->rslt; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } asig = p->xsig; prev = p->prev; for (n=offset; nprev = prev; return OK; } int samphset(CSOUND *csound, SAMPHOLD *p) { if (!(*p->istor)) p->state = *p->ival; p->audiogate = IS_ASIG_ARG(p->xgate) ? 1 : 0; return OK; } int ksmphold(CSOUND *csound, SAMPHOLD *p) { if (*p->xgate > FL(0.0)) p->state = *p->xsig; *p->xr = p->state; return OK; } int samphold(CSOUND *csound, SAMPHOLD *p) { MYFLT *ar, *asig, *agate, state; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; ar = p->xr; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } asig = p->xsig; state = p->state; if (p->audiogate) { agate = p->xgate; for (n=offset; n FL(0.0)) state = asig[n]; ar[n] = state; } } else { if (*p->xgate > FL(0.0)) { for (n=offset; nstate = state; return OK; } int delset(CSOUND *csound, DELAY *p) { int32 npts; char *auxp; if (UNLIKELY(*p->istor && p->auxch.auxp != NULL)) return OK; /* Round not truncate */ if (UNLIKELY((npts = MYFLT2LRND(*p->idlt * csound->esr)) <= 0)) { return csound->InitError(csound, Str("illegal delay time")); } if ((auxp = p->auxch.auxp) == NULL || npts != p->npts) { /* new space if reqd */ csound->AuxAlloc(csound, (int32)npts*sizeof(MYFLT), &p->auxch); auxp = p->auxch.auxp; p->npts = npts; } else if (!(*p->istor)) { /* else if requested */ memset(auxp, '\0', npts*sizeof(MYFLT)); } p->curp = (MYFLT *) auxp; return OK; } int delrset(CSOUND *csound, DELAYR *p) { uint32_t npts; MYFLT *auxp; if (UNLIKELY(!IS_ASIG_ARG(p->ar))) return csound->InitError(csound, Str("delayr: invalid outarg type")); /* fifo for delayr pointers by Jens Groh: */ /* append structadr for delayw to fifo: */ if (csound->first_delayr != NULL) /* fifo not empty */ ((DELAYR*) csound->last_delayr)->next_delayr = p; else /* fifo empty */ csound->first_delayr = (void*) p; csound->last_delayr = (void*) p; csound->delayr_stack_depth++; p->next_delayr = NULL; if (p->OUTOCOUNT > 1) { /* set optional output arg if specified */ *(p->indx) = (MYFLT)-(csound->delayr_stack_depth); } if (UNLIKELY(*p->istor != FL(0.0) && p->auxch.auxp != NULL)) return OK; /* ksmps is min dely */ if (UNLIKELY((npts=(uint32_t)MYFLT2LRND(*p->idlt*csound->esr)) < CS_KSMPS)) { return csound->InitError(csound, Str("illegal delay time")); } if ((auxp = (MYFLT*)p->auxch.auxp) == NULL || /* new space if reqd */ npts != p->npts) { csound->AuxAlloc(csound, (int32)npts*sizeof(MYFLT), &p->auxch); auxp = (MYFLT*)p->auxch.auxp; p->npts = npts; } else if (*p->istor == FL(0.0)) { /* else if requested */ memset(auxp, 0, npts*sizeof(MYFLT)); } p->curp = auxp; return OK; } int delwset(CSOUND *csound, DELAYW *p) { /* fifo for delayr pointers by Jens Groh: */ if (UNLIKELY(csound->first_delayr == NULL)) { return csound->InitError(csound, Str("delayw: associated delayr not found")); } p->delayr = (DELAYR*) csound->first_delayr; /* adr delayr struct */ /* remove structadr from fifo */ if (csound->last_delayr == csound->first_delayr) { /* fifo will be empty */ csound->first_delayr = NULL; } else /* fifo will not be empty */ csound->first_delayr = ((DELAYR*) csound->first_delayr)->next_delayr; csound->delayr_stack_depth--; return OK; } static DELAYR *delayr_find(CSOUND *csound, MYFLT *ndx) { DELAYR *d = (DELAYR*) csound->first_delayr; int n = (int)MYFLT2LRND(*ndx); if (UNLIKELY(d == NULL)) { csound->InitError(csound, Str("deltap: associated delayr not found")); return NULL; } if (!n) return (DELAYR*) csound->last_delayr; /* default: use last delayr */ else if (n > 0) n = csound->delayr_stack_depth - n; /* ndx > 0: LIFO index mode */ else n = -n; /* ndx < 0: FIFO index mode */ if (UNLIKELY(n < 1 || n > csound->delayr_stack_depth)) { csound->InitError(csound, Str("deltap: delayr index %.0f is out of range"), (double)*ndx); return NULL; } /* find delay line */ while (--n) d = d->next_delayr; return d; } int tapset(CSOUND *csound, DELTAP *p) { p->delayr = delayr_find(csound, p->indx); return (p->delayr != NULL ? OK : NOTOK); } int delay(CSOUND *csound, DELAY *p) { MYFLT *ar, *asig, *curp, *endp; uint32_t offset = 0; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; /* RWD fix */ ar = p->ar; if (csound->oparms->sampleAccurate) { uint32_t early = p->h.insdshead->ksmps_no_end; offset = p->h.insdshead->ksmps_offset; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } } asig = p->asig; curp = p->curp; endp = (MYFLT *) p->auxch.endp; for (n=offset; n= endp)) curp = (MYFLT *) p->auxch.auxp; } p->curp = curp; /* sav the new curp */ return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("delay: not initialised")); } int delayr(CSOUND *csound, DELAYR *p) { MYFLT *ar, *curp, *endp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; /* RWD fix */ ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } curp = p->curp; endp = (MYFLT *) p->auxch.endp; for (n=offset; n= endp)) curp = (MYFLT *) p->auxch.auxp; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("delayr: not initialised")); } int delayw(CSOUND *csound, DELAYW *p) { DELAYR *q = p->delayr; MYFLT *asig, *curp, *endp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(q->auxch.auxp==NULL)) goto err1; /* RWD fix */ asig = p->asig; curp = q->curp; endp = (MYFLT *) q->auxch.endp; if (UNLIKELY(early)) nsmps -= early; for (n=offset; n= endp)) curp = (MYFLT *) q->auxch.auxp; } q->curp = curp; /* now sav new curp */ return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("delayw: not initialised")); } int deltap(CSOUND *csound, DELTAP *p) { DELAYR *q = p->delayr; MYFLT *ar, *tap, *endp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(q->auxch.auxp==NULL)) goto err1; /* RWD fix */ ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } tap = q->curp - MYFLT2LRND(*p->xdlt * csound->esr); while (tap < (MYFLT *) q->auxch.auxp) tap += q->npts; endp = (MYFLT *) q->auxch.endp; for (n=offset; n= endp)) tap -= q->npts; ar[n] = *tap++; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("deltap: not initialised")); } int deltapi(CSOUND *csound, DELTAP *p) { DELAYR *q = p->delayr; MYFLT *ar, *tap, *prv, *begp, *endp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 idelsmps; MYFLT delsmps, delfrac; if (UNLIKELY(q->auxch.auxp==NULL)) goto err1; ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } begp = (MYFLT *) q->auxch.auxp; endp = (MYFLT *) q->auxch.endp; if (!IS_ASIG_ARG(p->xdlt)) { if(*p->xdlt == INFINITY) goto err2; delsmps = *p->xdlt * csound->esr; idelsmps = (int32)delsmps; delfrac = delsmps - idelsmps; tap = q->curp - idelsmps; while (tap < begp) tap += q->npts; for (n=offset; n= endp)) tap -= q->npts; if (UNLIKELY((prv = tap - 1) < begp)) prv += q->npts; ar[n] = *tap + (*prv - *tap) * delfrac; tap++; } } else { MYFLT *timp = p->xdlt, *curq = q->curp; for (n=offset; nesr; idelsmps = (int32)delsmps; delfrac = delsmps - idelsmps; tap = curq++ - idelsmps; if (UNLIKELY(tap < begp)) tap += q->npts; else if (UNLIKELY(tap >= endp)) tap -= q->npts; if (UNLIKELY((prv = tap - 1) < begp)) prv += q->npts; ar[n] = *tap + (*prv - *tap) * delfrac; } } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("deltapi: not initialised")); err2: return csound->PerfError(csound, p->h.insdshead, Str("deltapi: INF delaytime")); } /* ***** From Hans Mikelson ************* */ /* Delay N samples */ int deltapn(CSOUND *csound, DELTAP *p) { DELAYR *q = p->delayr; MYFLT *ar, *tap, *begp, *endp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 idelsmps; MYFLT delsmps; if (UNLIKELY(q->auxch.auxp==NULL)) goto err1; ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } begp = (MYFLT *) q->auxch.auxp; endp = (MYFLT *) q->auxch.endp; if (!IS_ASIG_ARG(p->xdlt)) { delsmps = *p->xdlt; idelsmps = (int32)delsmps; tap = q->curp - idelsmps; while (tap < begp) tap += q->npts; for (n=offset; n= endp )) tap -= q->npts; while (UNLIKELY(tap < begp)) tap += q->npts; ar[n] = *tap; tap++; } } else { MYFLT *timp = p->xdlt, *curq = q->curp; for (n=offset; nnpts; else if (UNLIKELY(tap >= endp)) tap -= q->npts; ar[n] = *tap; } } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("deltapn: not initialised")); } /* **** JPff **** */ int deltap3(CSOUND *csound, DELTAP *p) { DELAYR *q = p->delayr; MYFLT *ar, *tap, *prv, *begp, *endp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 idelsmps; MYFLT delsmps, delfrac; if (UNLIKELY(q->auxch.auxp==NULL)) goto err1; ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } begp = (MYFLT *) q->auxch.auxp; endp = (MYFLT *) q->auxch.endp; if (!IS_ASIG_ARG(p->xdlt)) { if(*p->xdlt == INFINITY) goto err2; delsmps = *p->xdlt * csound->esr; idelsmps = (int32)delsmps; delfrac = delsmps - idelsmps; tap = q->curp - idelsmps; while (tap < begp) tap += q->npts; for (n=offset; n= endp)) tap -= q->npts; if (UNLIKELY((prv = tap - 1) < begp)) prv += q->npts; if (UNLIKELY(prv - 1 < begp)) y2 = *(prv-1+q->npts); else y2 = *(prv-1); if (UNLIKELY(tap + 1 >= endp)) ym1 = *(tap+1-q->npts); else ym1 = *(tap+1); y0 = *tap; y1 = *prv; { MYFLT w, x, y, z; z = delfrac * delfrac; z--; z *= FL(0.16666666666667); y = delfrac; y++; w = (y *= FL(0.5)); w--; x = FL(3.0) * z; y -= x; w -= z; x -= delfrac; ar[n] = (w*ym1 + x*y0 + y*y1 + z*y2) * delfrac + y0; } tap++; } } else { MYFLT *timp = p->xdlt, *curq = q->curp; for (n=offset; nesr; idelsmps = (int32)delsmps; delfrac = delsmps - idelsmps; if (UNLIKELY((tap = curq++ - idelsmps) < begp)) tap += q->npts; else if (UNLIKELY(tap >= endp)) tap -= q->npts; if (UNLIKELY((prv = tap - 1) < begp)) prv += q->npts; if (UNLIKELY(prv - 1 < begp)) y2 = *(prv-1+q->npts); else y2 = *(prv-1); if (UNLIKELY(tap + 1 >= endp)) ym1 = *(tap+1-q->npts); else ym1 = *(tap+1); y0 = *tap; y1 = *prv; { MYFLT w, x, y, z; z = delfrac * delfrac; z--; z *= FL(0.1666666667); y = delfrac; y++; w = (y *= FL(0.5)); w--; x = FL(3.0) * z; y -= x; w -= z; x -= delfrac; ar[n] = (w*ym1 + x*y0 + y*y1 + z*y2) * delfrac + y0; } } } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("deltap3: not initialised")); err2: return csound->PerfError(csound, p->h.insdshead, Str("deltapi: INF delaytime")); } /* deltapx and deltapxw opcodes by Istvan Varga */ int tapxset(CSOUND *csound, DELTAPX *p) { p->delayr = delayr_find(csound, p->indx); if (UNLIKELY(p->delayr == NULL)) return NOTOK; p->wsize = (int)(*(p->iwsize) + FL(0.5)); /* window size */ p->wsize = ((p->wsize + 2) >> 2) << 2; if (UNLIKELY(p->wsize < 4)) p->wsize = 4; if (UNLIKELY(p->wsize > 1024)) p->wsize = 1024; /* wsize = 4: d2x = 1 - 1/3, wsize = 64: d2x = 1 - 1/36 */ p->d2x = 1.0 - pow((double)p->wsize * 0.85172, -0.89624); p->d2x /= (double)((p->wsize * p->wsize) >> 2); return OK; } int deltapx(CSOUND *csound, DELTAPX *p) /* deltapx opcode */ { DELAYR *q = p->delayr; MYFLT *out1, *del, *buf1, *bufp, *bufend; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 indx, maxd, xpos; if (UNLIKELY(q->auxch.auxp == NULL)) goto err1; /* RWD fix */ out1 = p->ar; del = p->adlt; if (UNLIKELY(offset)) memset(out1, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out1[nsmps], '\0', early*sizeof(MYFLT)); } buf1 = (MYFLT *) q->auxch.auxp; indx = (int32) (q->curp - buf1); maxd = q->npts; bufend = buf1 + maxd; if (p->wsize != 4) { /* window size >= 8 */ double d, x1, n1, w, d2x; int i2, i; i2 = (p->wsize >> 1); /* wsize = 4: d2x = 1 - 1/3, wsize = 64: d2x = 1 - 1/36 */ d2x = p->d2x; for (n=offset; nesr; while (x1 < 0.0) x1 += (double)maxd; xpos = (int32)x1; x1 -= (double)xpos; while (xpos >= maxd) xpos -= maxd; if (x1 > 0.00000001 && x1 < 0.99999999) { xpos -= i2; while (xpos < 0) xpos += maxd; d = (double)(1 - i2) - x1; bufp = buf1 + xpos; i = i2; n1 = 0.0; do { w = 1.0 - d * d * d2x; if (UNLIKELY(++bufp >= bufend)) bufp = buf1; n1 += w * w * (double)*bufp / d; d++; w = 1.0 - d * d * d2x; if (UNLIKELY(++bufp >= bufend)) bufp = buf1; n1 -= w * w * (double)*bufp / d; d++; } while (--i); out1[n] = (MYFLT)(n1 * sin(PI * x1) / PI); } else { /* integer sample */ xpos = MYFLT2LRND((double)xpos + x1); /* position */ if (xpos >= maxd) xpos -= maxd; out1[n] = buf1[xpos]; } indx++; } } else { /* window size = 4, cubic interpolation */ double x, am1, a0, a1, a2; for (n=offset; nesr; while (am1 < 0.0) am1 += (double)maxd; xpos = (int32) am1; am1 -= (double)xpos; a0 = am1 * am1; a2 = 0.16666667 * (am1 * a0 - am1); /* sample +2 */ a1 = 0.5 * (a0 + am1) - 3.0 * a2; /* sample +1 */ am1 = 0.5 * (a0 - am1) - a2; /* sample -1 */ a0 = 3.0 * a2 - a0; a0++; /* sample 0 */ bufp = (xpos ? (buf1 + (xpos - 1L)) : (bufend - 1)); while (bufp >= bufend) bufp -= maxd; x = am1 * (double)*bufp; if (UNLIKELY(++bufp >= bufend)) bufp = buf1; x += a0 * (double)*bufp; if (UNLIKELY(++bufp >= bufend)) bufp = buf1; x += a1 * (double)*bufp; if (UNLIKELY(++bufp >= bufend)) bufp = buf1; x += a2 * (double)*bufp; indx++; out1[n] = (MYFLT)x; } } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("deltap: not initialised")); } int deltapxw(CSOUND *csound, DELTAPX *p) /* deltapxw opcode */ { DELAYR *q = p->delayr; MYFLT *in1, *del, *buf1, *bufp, *bufend; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 indx, maxd, xpos; if (UNLIKELY(q->auxch.auxp == NULL)) goto err1; /* RWD fix */ in1 = p->ar; del = p->adlt; if (UNLIKELY(early)) nsmps -= early; buf1 = (MYFLT *) q->auxch.auxp; indx = (int32) (q->curp - buf1); maxd = q->npts; bufend = buf1 + maxd; if (p->wsize != 4) { /* window size >= 8 */ double d, x1, n1, w, d2x; int i2, i; i2 = (p->wsize >> 1); /* wsize = 4: d2x = 1 - 1/3, wsize = 64: d2x = 1 - 1/36 */ d2x = p->d2x; for (n=offset; nesr; while (x1 < 0.0) x1 += (double)maxd; xpos = (int32) x1; x1 -= (double)xpos; while (xpos >= maxd) xpos -= maxd; if (x1 > 0.00000001 && x1 < 0.99999999) { n1 = (double)*in1 * (sin(PI * x1) / PI); xpos -= i2; while (xpos < 0) xpos += maxd; d = (double)(1 - i2) - x1; bufp = buf1 + xpos; i = i2; do { w = 1.0 - d * d * d2x; if (UNLIKELY(++bufp >= bufend)) bufp = buf1; *bufp = (MYFLT)((double)*bufp + w * w * n1 / d); d++; w = 1.0 - d * d * d2x; if (UNLIKELY(++bufp >= bufend)) bufp = buf1; *bufp = (MYFLT)((double)*bufp - w * w * n1 / d); d++; } while (--i); } else { /* integer sample */ xpos = MYFLT2LRND((double)xpos + x1); /* position */ if (UNLIKELY(xpos >= maxd)) xpos -= maxd; buf1[xpos] += in1[n]; } indx++; } } else { /* window size = 4, cubic interpolation */ double x, am1, a0, a1, a2; for (n=offset; nesr; while (am1 < 0.0) am1 += (double)maxd; xpos = (int32) am1; am1 -= (double)xpos; a0 = am1 * am1; a2 = 0.16666667 * (am1 * a0 - am1); /* sample +2 */ a1 = 0.5 * (a0 + am1) - 3.0 * a2; /* sample +1 */ am1 = 0.5 * (a0 - am1) - a2; /* sample -1 */ a0 = 3.0 * a2 - a0; a0++; /* sample 0 */ x = (double)in1[n]; bufp = (xpos ? (buf1 + (xpos - 1L)) : (bufend - 1)); while (bufp >= bufend) bufp -= maxd; *bufp += (MYFLT)(am1 * x); if (UNLIKELY(++bufp >= bufend)) bufp = buf1; *bufp += (MYFLT)(a0 * x); if (UNLIKELY(++bufp >= bufend)) bufp = buf1; *bufp += (MYFLT)(a1 * x); if (UNLIKELY(++bufp >= bufend)) bufp = buf1; *bufp += (MYFLT)(a2 * x); indx++; } } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("deltap: not initialised")); } int del1set(CSOUND *csound, DELAY1 *p) { if (!(*p->istor)) p->sav1 = FL(0.0); return OK; } int delay1(CSOUND *csound, DELAY1 *p) { MYFLT *ar, *asig; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nsmps = CS_KSMPS; ar = p->ar; /* asig = p->asig - 1; */ asig = p->asig; ar[offset] = p->sav1; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } memmove(&ar[offset+1], &asig[offset], sizeof(MYFLT)*(nsmps-1-offset)); p->sav1 = asig[nsmps-1]; return OK; } int cmbset(CSOUND *csound, COMB *p) { int32 lpsiz, nbytes; if (*p->insmps != 0) { if (UNLIKELY((lpsiz = MYFLT2LRND(*p->ilpt))) <= 0) { return csound->InitError(csound, Str("illegal loop time")); } } else if (UNLIKELY((lpsiz = MYFLT2LRND(*p->ilpt * csound->esr)) <= 0)) { return csound->InitError(csound, Str("illegal loop time")); } nbytes = lpsiz * sizeof(MYFLT); if (p->auxch.auxp == NULL || (uint32_t)nbytes != p->auxch.size) { csound->AuxAlloc(csound, (int32)nbytes, &p->auxch); p->pntr = (MYFLT *) p->auxch.auxp; p->prvt = FL(0.0); p->coef = FL(0.0); } else if (!(*p->istor)) { /* Does this assume sizeof(MYFLT)==sizeof(int32)?? */ p->pntr = (MYFLT *) p->auxch.auxp; memset(p->auxch.auxp, '\0', nbytes); p->prvt = FL(0.0); p->coef = FL(0.0); } return OK; } int comb(CSOUND *csound, COMB *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *ar, *asig, *xp, *endp; MYFLT coef = p->coef; if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; /* RWD fix */ if (p->prvt != *p->krvt) { p->prvt = *p->krvt; /* * The argument to exp() in the following is sometimes a small * enough negative number to result in a denormal (or worse) * on Alpha. So if the result would be less than 1.0e-16, we * just say it's zero and don't call exp(). heh 981101 */ double exp_arg = (double)(log001 * *p->ilpt / p->prvt); if (UNLIKELY(exp_arg < -36.8413615)) /* ln(1.0e-16) */ coef = p->coef = FL(0.0); else coef = p->coef = (MYFLT)exp(exp_arg); } xp = p->pntr; endp = (MYFLT *) p->auxch.endp; ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } asig = p->asig; for (n=offset; n= endp)) xp = (MYFLT *) p->auxch.auxp; } p->pntr = xp; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("comb: not initialised")); } int invcomb(CSOUND *csound, COMB *p) { int n, nsmps = csound->ksmps; MYFLT *ar, *asig, *xp, *endp; MYFLT coef = p->coef; if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; /* RWD fix */ if (p->prvt != *p->krvt) { p->prvt = *p->krvt; /* * The argument to exp() in the following is sometimes a small * enough negative number to result in a denormal (or worse) * on Alpha. So if the result would be less than 1.0e-16, we * just say it is zero and do not call exp(). heh 981101 */ double exp_arg = (double)(log001 * *p->ilpt / p->prvt); if (UNLIKELY(exp_arg < -36.8413615)) /* ln(1.0e-16) */ coef = p->coef = FL(0.0); else coef = p->coef = (MYFLT)exp(exp_arg); } xp = p->pntr; endp = (MYFLT *) p->auxch.endp; ar = p->ar; asig = p->asig; MYFLT out; for (n=0; n= endp)) xp = (MYFLT *) p->auxch.auxp; } p->pntr = xp; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("combinv: not initialised")); } int alpass(CSOUND *csound, COMB *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *ar, *asig, *xp, *endp; MYFLT y, z; MYFLT coef = p->coef; if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; /* RWD fix */ if (p->prvt != *p->krvt) { p->prvt = *p->krvt; coef = p->coef = EXP(log001 * *p->ilpt / p->prvt); } xp = p->pntr; endp = (MYFLT *) p->auxch.endp; ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } asig = p->asig; for (n=offset; n= endp)) xp = (MYFLT *) p->auxch.auxp; } p->pntr = xp; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("alpass: not initialised")); } static const MYFLT revlptimes[6] = {FL(0.0297), FL(0.0371), FL(0.0411), FL(0.0437), FL(0.0050), FL(0.0017)}; void reverbinit(CSOUND *csound) /* called once by oload */ { /* to init reverb data */ const MYFLT *lptimp = revlptimes; int32 *lpsizp = csound->revlpsiz; int n = 6; if (csound->revlpsum==0) { csound->revlpsum = 0; for (n=0; n<6; n++) { lpsizp[n] = MYFLT2LRND(lptimp[n] * csound->esr); csound->revlpsum += lpsizp[n]; } } } int rvbset(CSOUND *csound, REVERB *p) { if (p->auxch.auxp == NULL) { /* if no space yet, */ int32 *sizp = csound->revlpsiz; /* allocate it */ csound->AuxAlloc(csound, csound->revlpsum * sizeof(MYFLT), &p->auxch); p->adr1 = p->p1 = (MYFLT *) p->auxch.auxp; p->adr2 = p->p2 = p->adr1 + *sizp++; p->adr3 = p->p3 = p->adr2 + *sizp++; /* & init ptrs */ p->adr4 = p->p4 = p->adr3 + *sizp++; p->adr5 = p->p5 = p->adr4 + *sizp++; p->adr6 = p->p6 = p->adr5 + *sizp++; if (UNLIKELY(p->adr6 + *sizp != (MYFLT *) p->auxch.endp)) { return csound->InitError(csound, Str("revlpsiz inconsistent\n")); } p->prvt = FL(0.0); } else if (!(*p->istor)) { /* else if istor = 0 */ memset(p->adr1, '\0', csound->revlpsum * sizeof(MYFLT)); p->p1 = p->adr1; /* and reset */ p->p2 = p->adr2; p->p3 = p->adr3; p->p4 = p->adr4; p->p5 = p->adr5; p->p6 = p->adr6; p->prvt = FL(0.0); } return OK; } int reverb(CSOUND *csound, REVERB *p) { MYFLT *asig, *p1, *p2, *p3, *p4, *p5, *p6, *ar, *endp; MYFLT c1,c2,c3,c4,c5,c6; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; /* RWD fix */ if (UNLIKELY(p->prvt != *p->krvt)) { /* People rarely change rvt */ const MYFLT *lptimp = revlptimes; MYFLT logdrvt = log001 / *p->krvt; c1=p->c1 = EXP(logdrvt * *lptimp++); c2=p->c2 = EXP(logdrvt * *lptimp++); c3=p->c3 = EXP(logdrvt * *lptimp++); c4=p->c4 = EXP(logdrvt * *lptimp++); c5=p->c5 = EXP(logdrvt * *lptimp++); c6=p->c6 = EXP(logdrvt * *lptimp++); p->prvt = *p->krvt; /* JPff optimisation?? */ } else { c1=p->c1; c2=p->c2; c3=p->c3; c4=p->c4; c5=p->c5; c6=p->c6; } p1 = p->p1; p2 = p->p2; p3 = p->p3; p4 = p->p4; p5 = p->p5; p6 = p->p6; endp = (MYFLT *) p->auxch.endp; ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } asig = p->asig; for (n=offset; n= p->adr2)) p1 = p->adr1; if (UNLIKELY(p2 >= p->adr3)) p2 = p->adr2; if (UNLIKELY(p3 >= p->adr4)) p3 = p->adr3; if (UNLIKELY(p4 >= p->adr5)) p4 = p->adr4; if (UNLIKELY(p5 >= p->adr6)) p5 = p->adr5; if (UNLIKELY(p6 >= endp)) p6 = p->adr6; } p->p1 = p1; p->p2 = p2; p->p3 = p3; p->p4 = p4; p->p5 = p5; p->p6 = p6; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("reverb: not initialised")); } int panset(CSOUND *csound, PAN *p) { FUNC *ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) == NULL)) return NOTOK; p->ftp = ftp; p->xmul = (*p->imode == FL(0.0) ? FL(1.0) : (MYFLT)ftp->flen); p->xoff = (*p->ioffset == FL(0.0) ? (MYFLT)ftp->flen * FL(0.5) : FL(0.0)); return OK; } int pan(CSOUND *csound, PAN *p) { MYFLT flend2, xndx_f, yndx_f, xt, yt, ch1, ch2, ch3, ch4; int32 xndx, yndx, flen; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; FUNC *ftp; ftp = p->ftp; if (UNLIKELY(ftp == NULL)) goto err1; /* RWD fix */ xndx_f = (*p->kx * p->xmul) - p->xoff; yndx_f = (*p->ky * p->xmul) - p->xoff; flen = ftp->flen; flend2 = (MYFLT)flen * FL(0.5); xt = FABS(xndx_f); yt = FABS(yndx_f); if (xt > flend2 || yt > flend2) { if (xt > yt) yndx_f *= (flend2 / xt); else xndx_f *= (flend2 / yt); } xndx_f += flend2; yndx_f += flend2; xndx = MYFLT2LRND(xndx_f); yndx = MYFLT2LRND(yndx_f); xndx = (xndx >= 0L ? (xndx < flen ? xndx : flen) : 0L); yndx = (yndx >= 0L ? (yndx < flen ? yndx : flen) : 0L); ch1 = ftp->ftable[flen - xndx] * ftp->ftable[yndx]; ch2 = ftp->ftable[xndx] * ftp->ftable[yndx]; ch3 = ftp->ftable[flen - xndx] * ftp->ftable[flen - yndx]; ch4 = ftp->ftable[xndx] * ftp->ftable[flen - yndx]; if (UNLIKELY(offset)) { memset(p->r1, '\0', offset*sizeof(MYFLT)); memset(p->r2, '\0', offset*sizeof(MYFLT)); memset(p->r3, '\0', offset*sizeof(MYFLT)); memset(p->r4, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&p->r1[nsmps], '\0', early*sizeof(MYFLT)); memset(&p->r2[nsmps], '\0', early*sizeof(MYFLT)); memset(&p->r3[nsmps], '\0', early*sizeof(MYFLT)); memset(&p->r4[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nasig[n]; p->r1[n] = sig * ch1; p->r2[n] = sig * ch2; p->r3[n] = sig * ch3; p->r4[n] = sig * ch4; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("pan: not initialised")); } csound-6.10.0/OOps/ugrw1.c000066400000000000000000001264621321653344700152050ustar00rootroot00000000000000/* ugrw1.c: Copyright (C) 1997 Robin Whittle This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* These files are based on Robin Whittle's * ugrw1.c of 27 August 1996 * and ugrw1.h of 7 January 1995 * * In February 1997, John Fitch reformatted the comments and * cleaned up some code in printksset() - which was working fine * but was inelegantly coded. * In February 1998, John Fitch modified the code wrt types so it * compiled with MicroSoft C without warnings. * * * Copyright notice - Robin Whittle 25 February 1997 * * Documentation files, and the original .c and .h files, with more * spaced out comments, are available from http://www.firstpr.com.au * * The code in both ugrw1 and ugrw2 is copyright Robin Whittle. * Permission is granted to use this in whole or in part for any * purpose, provided this copyright notice remains intact and * any alterations to the source code, including comments, are * clearly indicated as such. */ #include "csoundCore.h" #include "ugrw1.h" #include #include /*****************************************************************************/ /*****************************************************************************/ /* The zak system - patching i, k and a rate signals in a global set of * patch points - one set for i and k,* the other for a rate. * See doco at the start of this file. */ /* There are four global variables which are used by these ugens. */ /* Starting addresses of zk and za spaces */ /* MYFLT *zkstart = NULL, *zastart = NULL; */ /* Number of the last location in zk/za space */ /* long zklast = 0, zalast = 0; */ /* There are currently no limits on the size of these spaces. */ /* zakinit is an opcode which must be called once to reserve the memory * for zk and za spaces. */ int zakinit(CSOUND *csound, ZAKINIT *p) { int32 length; /* Check to see this is the first time zakinit() has been called. * Global variables will be zero if it has not been called. */ if (UNLIKELY((csound->zkstart != NULL) || (csound->zastart != NULL))) { return csound->InitError(csound, Str("zakinit should only be called once.")); } if (UNLIKELY((*p->isizea <= 0) || (*p->isizek <= 0))) { return csound->InitError(csound, Str("zakinit: both isizea and isizek " "should be > 0.")); } /* Allocate memory for zk space. * This is all set to 0 and there will be an error report if the * memory cannot be allocated. */ csound->zklast = (int32) *p->isizek; length = (csound->zklast + 1L) * sizeof(MYFLT); csound->zkstart = (MYFLT*) csound->Calloc(csound, length); /* Likewise, allocate memory for za space, but do it in arrays of * length ksmps. * This is all set to 0 and there will be an error report if the * memory cannot be allocated. */ csound->zalast = (int32) *p->isizea; length = (csound->zalast + 1L) * sizeof(MYFLT) * CS_KSMPS; csound->zastart = (MYFLT*) csound->Calloc(csound, length); return OK; } /*---------------------------------------------------------------------------*/ /* I and K rate zak code. */ /* zkset() is called at the init time of the instance of the zir, zkr * zir and ziw ugens. It complains if zk space has not been allocated yet. */ int zkset(CSOUND *csound, ZKR *p) { (void) p; if (UNLIKELY(csound->zkstart == NULL)) { return csound->InitError(csound, Str("No zk space: " "zakinit has not been called yet.")); } return OK; } /*-----------------------------------*/ /* k rate READ code. */ /* zkr reads from zk space at k rate. */ int zkr(CSOUND *csound, ZKR *p) { int32 indx; /* Check to see this index is within the limits of zk space. */ indx = (int32) *p->ndx; if (UNLIKELY(indx > csound->zklast)) { *p->rslt = FL(0.0); csound->Warning(csound, Str("zkr index > isizek. Returning 0.")); } else if (UNLIKELY(indx < 0)) { *p->rslt = FL(0.0); csound->Warning(csound, Str("zkr index < 0. Returning 0.")); } else { MYFLT *readloc; /* Now read from the zk space and write to the destination. */ readloc = csound->zkstart + indx; *p->rslt = *readloc; } return OK; } /*-----------------------------------*/ /* zir reads from zk space, but only at init time. * * Call zkset() to check that zk space has been allocated, then do * similar code to zkr() above, except with csoundInitError() instead of * csoundPerfError(). */ int zir(CSOUND *csound, ZKR *p) { /* See zkr() for more comments. */ int32 indx; if (UNLIKELY(zkset(csound, p) != OK)) return NOTOK; /* Check to see this index is within the limits of zk space. */ indx = (int32) *p->ndx; if (UNLIKELY(indx > csound->zklast)) { csound->Warning(csound, Str("zir index > isizek. Returning 0.")); *p->rslt = FL(0.0); } else if (UNLIKELY(indx < 0)) { csound->Warning(csound, Str("zir index < 0. Returning 0.")); *p->rslt = FL(0.0); } else { MYFLT *readloc; /* Now read from the zk space. */ readloc = csound->zkstart + indx; *p->rslt = *readloc; } return OK; } /*-----------------------------------*/ /* Now the i and k rate WRITE code. zkw writes to zk space at k rate. */ int zkw(CSOUND *csound, ZKW *p) { int32 indx; /* Check to see this index is within the limits of zk space. */ indx = (int32) *p->ndx; if (UNLIKELY(indx > csound->zklast)) { return csound->PerfError(csound, p->h.insdshead, Str("zkw index > isizek. Not writing.")); } else if (UNLIKELY(indx < 0)) { return csound->PerfError(csound, p->h.insdshead, Str("zkw index < 0. Not writing.")); } else { MYFLT *writeloc; /* Now write to the appropriate location in zk space. */ writeloc = csound->zkstart + indx; *writeloc = *p->sig; } return OK; } /*-----------------------------------*/ /* ziw writes to zk space, but only at init time. * * Call zkset() to check that zk space has been allocated, then use * same code as zkw() except that errors go to csoundInitError(). */ int ziw(CSOUND *csound, ZKW *p) { int32 indx; if (UNLIKELY(zkset(csound, (ZKR*) p) != OK)) return NOTOK; indx = (int32) *p->ndx; if (UNLIKELY(indx > csound->zklast)) { return csound->InitError(csound, Str("ziw index > isizek. Not writing.")); } else if (UNLIKELY(indx < 0)) { return csound->InitError(csound, Str("ziw index < 0. Not writing.")); } else { MYFLT *writeloc; /* Now write to the appropriate location in zk space. */ writeloc = csound->zkstart + indx; *writeloc = *p->sig; } return OK; } /*-----------------------------------*/ /* i and k rate zk WRITE code, with a mix option. */ /* zkwm writes to zk space at k rate. */ int zkwm(CSOUND *csound, ZKWM *p) { int32 indx; /* Check to see this index is within the limits of zk space. */ indx = (int32) *p->ndx; if (UNLIKELY(indx > csound->zklast)) { return csound->PerfError(csound, p->h.insdshead, Str("zkwm index > isizek. Not writing.")); } else if (UNLIKELY(indx < 0)) { return csound->PerfError(csound, p->h.insdshead, Str("zkwm index < 0. Not writing.")); } else { MYFLT *writeloc; /* Now write to the appropriate location in zk space. */ writeloc = csound->zkstart + indx; /* If mix parameter is 0, then overwrite the data in the * zk space variable, otherwise read the old value, and write * the sum of it and the input sig. */ if (*p->mix == 0) *writeloc = *p->sig; else *writeloc += *p->sig; } return OK; } /*-----------------------------------*/ /* ziwm writes to zk space, but only at init time - with a mix option. * * Call zkset() to check that zk space has been allocated, then run * similar code to zkwm() to do the work - but with errors to csoundInitError(). */ int ziwm(CSOUND *csound, ZKWM *p) { int32 indx; if (UNLIKELY(zkset(csound, (ZKR*) p) != OK)) return NOTOK; indx = (int32) *p->ndx; if (UNLIKELY(indx > csound->zklast)) { return csound->InitError(csound, Str("ziwm index > isizek. Not writing.")); } else if (UNLIKELY(indx < 0)) { return csound->InitError(csound, Str("ziwm index < 0. Not writing.")); } else { MYFLT *writeloc; writeloc = csound->zkstart + indx; if (*p->mix == 0) *writeloc = *p->sig; else *writeloc += *p->sig; } return OK; } /*-----------------------------------*/ /* k rate ZKMOD subroutine. */ int zkmod(CSOUND *csound, ZKMOD *p) { MYFLT *readloc; int32 indx; int mflag = 0; /* set to true if should do the modulation with multiplication rather than addition. */ /* If zkmod = 0, then just copy input to output. We want to make * this as fast as possible, because in many instances, this will be * the case. * * Note that in converting the zkmod index into a long, we want * the normal conversion rules to apply to negative numbers - * so -2.3 is converted to -2. */ if ((indx = (int32)*p->zkmod) == 0) { *p->rslt = *p->sig; return OK; } /* Decide whether index is positive or negative. Make it postive. */ if (UNLIKELY(indx < 0)) { indx = - indx; mflag = 1; } /* Check to see this index is within the limits of zk space. */ if (UNLIKELY(indx > csound->zklast)) { return csound->PerfError(csound, p->h.insdshead, Str("zkmod kzkmod > isizek. Not writing.")); } else { /* Now read the value from zk space. */ readloc = csound->zkstart + indx; /* If mflag is 0, then add the modulation factor. Otherwise multiply it.*/ if (mflag == 0) *p->rslt = *p->sig + *readloc; else *p->rslt = *p->sig * *readloc; } return OK; } /*-----------------------------------*/ /* zkcl clears a range of variables in zk space at k rate. */ int zkcl(CSOUND *csound, ZKCL *p) { MYFLT *writeloc; int32 first = (int32) *p->first, last = (int32) *p->last, loopcount; /* Check to see both kfirst and klast are within the limits of zk space * and that last is >= first. */ if (UNLIKELY((first > csound->zklast) || (last > csound->zklast))) return csound->PerfError(csound, p->h.insdshead, Str("zkcl first or last > isizek. Not clearing.")); else if (UNLIKELY((first < 0) || (last < 0))) { return csound->PerfError(csound, p->h.insdshead, Str("zkcl first or last < 0. Not clearing.")); } else if (UNLIKELY(first > last)) { return csound->PerfError(csound, p->h.insdshead, Str("zkcl first > last. Not clearing.")); } else { /* Now clear the appropriate locations in zk space. */ loopcount = last - first + 1; writeloc = csound->zkstart + first; memset(writeloc, 0, loopcount*sizeof(MYFLT)); } return OK; } /*---------------------------------------------------------------------------*/ /* AUDIO rate zak code. */ /* zaset() is called at the init time of the instance of the zar or zaw ugens. * All it has to do is spit the dummy if za space has not been allocated yet. */ int zaset(CSOUND *csound, ZAR *p) { if (csound->zastart == NULL) { return csound->InitError(csound, Str("No za space: " "zakinit has not been called yet.")); } else return (OK); } /*-----------------------------------*/ /* a rate READ code. */ /* zar reads from za space at a rate. */ int zar(CSOUND *csound, ZAR *p) { MYFLT *readloc, *writeloc; int32 indx; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nsmps = CS_KSMPS; /*-----------------------------------*/ writeloc = p->rslt; /* Check to see this index is within the limits of za space. */ indx = (int32) *p->ndx; if (UNLIKELY(indx > csound->zalast)) { memset(writeloc, 0, nsmps*sizeof(MYFLT)); return csound->PerfError(csound, p->h.insdshead, Str("zar index > isizea. Returning 0.")); } else if (UNLIKELY(indx < 0)) { memset(writeloc, 0, nsmps*sizeof(MYFLT)); return csound->PerfError(csound, p->h.insdshead, Str("zar index < 0. Returning 0.")); } else { /* Now read from the array in za space and write to the destination. * See notes in zkr() on pointer arithmetic. */ readloc = csound->zastart + (indx * CS_KSMPS); if (UNLIKELY(offset)) memset(writeloc, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&writeloc[nsmps], '\0', early*sizeof(MYFLT)); } memcpy(&writeloc[offset], &readloc[offset], (nsmps-offset)*sizeof(MYFLT)); } return OK; } /*-----------------------------------*/ /* zarg() reads from za space at audio rate, with gain controlled by a * k rate variable. Code is almost identical to zar() above. */ int zarg(CSOUND *csound, ZARG *p) { MYFLT *readloc, *writeloc; MYFLT kgain; /* Gain control */ int32 indx; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; /*-----------------------------------*/ writeloc = p->rslt; kgain = *p->kgain; /* Check to see this index is within the limits of za space. */ indx = (int32) *p->ndx; if (UNLIKELY(indx > csound->zalast)) { memset(writeloc, 0, nsmps*sizeof(MYFLT)); return csound->PerfError(csound, p->h.insdshead, Str("zarg index > isizea. Returning 0.")); } else { if (UNLIKELY(indx < 0)) { memset(writeloc, 0, nsmps*sizeof(MYFLT)); return csound->PerfError(csound, p->h.insdshead, Str("zarg index < 0. Returning 0.")); } else { /* Now read from the array in za space multiply by kgain and write * to the destination. */ readloc = csound->zastart + (indx * CS_KSMPS); if (UNLIKELY(offset)) memset(writeloc, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&writeloc[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nh.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nsmps = CS_KSMPS; /* Set up the pointer for the source of data to write. */ readloc = p->sig; /* Check to see this index is within the limits of za space. */ indx = (int32) *p->ndx; if (UNLIKELY(indx > csound->zalast)) { return csound->PerfError(csound, p->h.insdshead, Str("zaw index > isizea. Not writing.")); } else if (UNLIKELY(indx < 0)) { return csound->PerfError(csound, p->h.insdshead, Str("zaw index < 0. Not writing.")); } else { /* Now write to the array in za space pointed to by indx. */ writeloc = csound->zastart + (indx * CS_KSMPS); if (UNLIKELY(offset)) memset(writeloc, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&writeloc[nsmps], '\0', early*sizeof(MYFLT)); } memcpy(&writeloc[offset], &readloc[offset], (nsmps-offset)*sizeof(MYFLT)); } return OK; } /*-----------------------------------*/ /* a rate WRITE code with mix facility. */ /* zawm writes to za space at a rate. */ int zawm(CSOUND *csound, ZAWM *p) { MYFLT *readloc, *writeloc; int32 indx; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; /*-----------------------------------*/ /* Set up the pointer for the source of data to write. */ readloc = p->sig; /* Check to see this index is within the limits of za space. */ indx = (int32) *p->ndx; if (UNLIKELY(indx > csound->zalast)) { return csound->PerfError(csound, p->h.insdshead, Str("zaw index > isizea. Not writing.")); } else if (UNLIKELY(indx < 0)) { return csound->PerfError(csound, p->h.insdshead, Str("zaw index < 0. Not writing.")); } else { /* Now write to the array in za space pointed to by indx. */ writeloc = csound->zastart + (indx * CS_KSMPS); if (*p->mix == 0) { /* Normal write mode. */ if (UNLIKELY(offset)) memset(writeloc, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&writeloc[nsmps], '\0', early*sizeof(MYFLT)); } memcpy(&writeloc[offset], &readloc[offset], (nsmps-offset)*sizeof(MYFLT)); } else { /* Mix mode - add to the existing value. */ if (UNLIKELY(early)) nsmps -= early; for (n=offset; nh.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; /* Make a local copy of the pointer to the input signal, so we can auto- * increment it. Likewise the location to write the result to. */ readsig = p->sig; writeloc = p->rslt; if (UNLIKELY(offset)) memset(writeloc, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&writeloc[nsmps], '\0', early*sizeof(MYFLT)); } /* If zkmod = 0, then just copy input to output. */ if ((indx = (int32) *p->zamod) == 0) { memcpy(&writeloc[offset], &readsig[offset], (nsmps-offset)*sizeof(MYFLT)); return OK; } /* Decide whether index is positive or negative. Make it postive. */ if (indx < 0) { indx = - indx; mflag = 1; } /* Check to see this index is within the limits of za space. */ if (UNLIKELY(indx > csound->zalast)) { return csound->PerfError(csound, p->h.insdshead, Str("zamod kzamod > isizea. Not writing.")); } else { /* Now read the values from za space. */ readloc = csound->zastart + (indx * CS_KSMPS); if (UNLIKELY(early)) nsmps -= early; if (mflag == 0) { for (n=offset; nfirst; last = (int32) *p->last; /* Check to see both kfirst and klast are within the limits of za space * and that last is >= first. */ if (UNLIKELY((first > csound->zalast) || (last > csound->zalast))) return csound->PerfError(csound, p->h.insdshead, Str("zacl first or last > isizea. Not clearing.")); else { if (UNLIKELY((first < 0) || (last < 0))) { return csound->PerfError(csound, p->h.insdshead, Str("zacl first or last < 0. Not clearing.")); } else { if (UNLIKELY(first > last)) { return csound->PerfError(csound, p->h.insdshead, Str("zacl first > last. Not clearing.")); } else { /* Now clear the appropriate locations in za space. */ loopcount = (last - first + 1) * CS_KSMPS; writeloc = csound->zastart + (first * CS_KSMPS); memset(writeloc, 0, loopcount*sizeof(MYFLT)); } } } return OK; } /*****************************************************************************/ /*****************************************************************************/ /* Subroutines for reading absolute time. */ /* timek() * * Called at i rate or k rate, by timek, itimek, timesr or itemes. * * This is based on global variable kcounter in insert.c. * Since is apparently is not declared in a header file, we must declare it * an external. * Actually moved to the glob structure -- JPff march 2002 */ int timek(CSOUND *csound, RDTIME *p) { /* Read the global variable kcounter and turn it into a float. */ *p->rslt = (MYFLT) CS_KCNT; return OK; } /* timesr() */ int timesr(CSOUND *csound, RDTIME *p) { /* Read the global variable kcounter divide it by the k rate. */ *p->rslt = (MYFLT) CS_KCNT * CS_ONEDKR; return OK; } /*-----------------------------------*/ /* Subroutines to read time for this instance of the instrument. */ /* instimset() runs at init time and keeps a record of the time then * in the RDTIME data structure. * Returns 0. */ int instimset(CSOUND *csound, RDTIME *p) { p->instartk = CS_KCNT; *p->rslt = FL(0.0); return OK; } /* instimek() * * Read difference between the global variable kcounter and the starting * time of this instance. Return it as a float. */ int instimek(CSOUND *csound, RDTIME *p) { *p->rslt = (MYFLT) (CS_KCNT - p->instartk); return OK; } /* insttimes() * * Read difference between the global variable kcounter and the starting * time of this instance. Return it as a float in seconds. */ int instimes(CSOUND *csound, RDTIME *p) { *p->rslt = (MYFLT) (CS_KCNT - p->instartk) * CS_ONEDKR; return OK; } /*****************************************************************************/ /*****************************************************************************/ /* Printing at k rate - printk. */ /* printkset is called when the instance of the instrument is initialised. */ int printkset(CSOUND *csound, PRINTK *p) { /* Set up ctime so that if it was 0 or negative, it is set to a low value * to ensure that the print cycle happens every k cycle. This low value is * 1 / ekr */ if (*p->ptime < CS_ONEDKR) p->ctime = CS_ONEDKR; else p->ctime = *p->ptime; /* Set up the number of spaces. Limit to 120 for people with big screens or printers. */ p->pspace = (int32) *p->space; if (UNLIKELY(p->pspace < 0L)) p->pspace = 0L; else if (UNLIKELY(p->pspace > 120L)) p->pspace = 120L; /* Set the initime variable - how many seconds in absolute time * when this instance of the instrument was initialised. */ p->initime = (MYFLT) CS_KCNT * CS_ONEDKR; /* Set cysofar to - 1 so that on the first call to printk - when * cycle = 0, then there will be a print cycle. */ p->cysofar = -1; p->initialised = -1; return OK; } /*************************************/ /* printk * * Called on every k cycle. It must decide when to do a print operation. */ int printk(CSOUND *csound, PRINTK *p) { MYFLT timel; /* Time in seconds since initialised */ int32 cycles; /* What print cycle */ /*-----------------------------------*/ /* Initialise variables. */ if (UNLIKELY(p->initialised != -1)) csound->PerfError(csound, p->h.insdshead, Str("printk not initialised")); timel = ((MYFLT) CS_KCNT * CS_ONEDKR) - p->initime; /* Divide the current elapsed time by the cycle time and round down to * an integer. */ cycles = MYFLT2LRND(timel / p->ctime); /* Now test if the cycle number we arein is higher than the one in which * we last printed. If so, update cysofar and print. */ if (p->cysofar < cycles) { p->cysofar = cycles; /* Do the print cycle. * Print instrument number and time. Instrument number stuff from * printv() in disprep.c. */ csound->MessageS(csound, CSOUNDMSG_ORCH, " i%4d ", (int)p->h.insdshead->p1.value); csound->MessageS(csound, CSOUNDMSG_ORCH, Str("time %11.5f: "), csound->icurTime/csound->esr); /* Print spaces and then the value we want to read. */ if (p->pspace > 0L) { char s[128]; /* p->pspace is limited to 120 in printkset() above */ memset(s, ' ', 128 /*(size_t) p->pspace */); s[p->pspace] = '\0'; csound->MessageS(csound, CSOUNDMSG_ORCH, "%s", s); } csound->MessageS(csound, CSOUNDMSG_ORCH, "%11.5f\n", *p->val); } return OK; } /*---------------------------------------------------------------------------*/ /* printks() and printksset() */ /* Printing at k rate with a string * and up to four variables - printks. */ #define ESC (0x1B) /* printksset is called when the instance of the instrument is initialised. */ int printksset_(CSOUND *csound, PRINTKS *p, char *sarg) { char *sdest; char temp, tempn; p->initialised = -1; if (*p->ptime < CS_ONEDKR) p->ctime = CS_ONEDKR; else p->ctime = *p->ptime; p->initime = (MYFLT) CS_KCNT * CS_ONEDKR; p->cysofar = -1; memset(p->txtstring, 0, 8192); /* This line from matt ingalls */ sdest = p->txtstring; /* Copy the string to the storage place in PRINTKS. * * We will look out for certain special codes and write special * bytes directly to the string. * * There is probably a more elegant way of doing this, then using * the look flag. I could use goto - but I would rather not. */ /* This is really a if then else if... * construct and is currently grotty -- JPff */ while (*sarg) { temp = *sarg++; tempn = *sarg--; /* Look for a single caret and insert an escape char. */ if ((temp == '^') && (tempn != '^')) { *sdest++ = ESC; } /* Look for a double caret and insert a single caret - stepping forward one */ else if ((temp == '^') && (tempn == '^')) { *sdest++ = '^'; sarg++; } /* Look for a single tilde and insert an escape followed by a '['. * ESC[ is the escape sequence for ANSI consoles */ else if ((temp == '~') && (tempn != '~')) { *sdest++ = ESC; *sdest++ = '['; } /* Look for a double tilde and insert a tilde caret - stepping forward one. */ else if ((temp == '~') && (tempn == '~')) { *sdest++ = '~'; sarg++; } /* Look for \n, \N etc */ else if (temp == '\\') { switch (tempn) { case 'r': case 'R': *sdest++ = '\r'; sarg++; break; case 'n': case 'N': *sdest++ = '\n'; sarg++; break; case 't': case 'T': *sdest++ = '\t'; sarg++; break; case 'a': case 'A': *sdest++ = '\a'; sarg++; break; case 'b': case 'B': *sdest++ = '\b'; sarg++; break; case '\\': *sdest++ = '\\'; sarg++; break; default: *sdest++ = tempn; sarg++; break; } } /* This case is from matt ingalls */ else if (temp == '%' && tempn != '%' ) { /* an extra option to specify tab and return as %t and %r*/ /* allowing for %% escape -- VL */ switch (tempn) { case 'r': case 'R': *sdest++ = '\r'; sarg++; break; case 'n': case 'N': *sdest++ = '\n'; sarg++; break; case 't': case 'T': *sdest++ = '\t'; sarg++; break; case '!': /* and a ';' */ *sdest++ = ';'; sarg++; break; // case '%': /* Should we do this? JPff */ // *sdest++ = '%'; /* No. VL */ // sarg++; // break; default: *sdest++ = temp; break; } } else { /* If none of these match, then copy the character directly * and try again. */ *sdest++ = temp; } /* Increment pointer and process next character until end of string. */ ++sarg; } return OK; } int printksset_S(CSOUND *csound, PRINTKS *p){ char *sarg; sarg = ((STRINGDAT*)p->ifilcod)->data; if (sarg == NULL) return csoundInitError(csound, Str("null string\n")); p->old = cs_strdup(csound, sarg); return printksset_(csound, p, sarg); } int printksset(CSOUND *csound, PRINTKS *p){ char* arg_string = get_arg_string(csound, *p->ifilcod); if (arg_string == NULL) { return csoundInitError(csound, Str("null string\n")); } return printksset_(csound, p, arg_string); } //perform a sprintf-style format -- matt ingalls /* void sprints_local(char *outstring, char *fmt, MYFLT **kvals, int32 numVals) */ /* { */ /* char strseg[8192]; */ /* int i = 0, j = 0; */ /* char *segwaiting = 0; */ /* puts(fmt); */ /* while (*fmt) { */ /* if (*fmt == '%') { */ /* /\* if already a segment waiting, then lets print it *\/ */ /* if (segwaiting) { */ /* MYFLT xx = (j>=numVals? FL(0.0) : *kvals[j]); */ /* /\* printf("***xx = %f (int)(xx+.5)=%d round=%d mode=%d\n", *\/ */ /* /\* xx, (int)(xx+.5), MYFLT2LRND(xx), fegetround()); *\/ */ /* strseg[i] = '\0'; */ /* switch (*segwaiting) { */ /* case 'd': */ /* case 'i': */ /* case 'o': */ /* case 'x': */ /* case 'X': */ /* case 'u': */ /* case 'c': */ /* snprintf(outstring, 8196, strseg, (int)MYFLT2LRND(xx)); */ /* break; */ /* case 'h': */ /* snprintf(outstring, 8196, strseg, (int16)MYFLT2LRND(xx)); */ /* break; */ /* case 'l': */ /* snprintf(outstring, 8196, strseg, (int32)MYFLT2LRND(xx)); */ /* break; */ /* default: */ /* printf("strseg:%s - %c\n", strseg, *segwaiting); */ /* CS_SPRINTF(outstring, strseg, xx); */ /* break; */ /* } */ /* outstring += strlen(outstring); */ /* i = 0; */ /* segwaiting = 0; */ /* // prevent potential problems if user didnt give enough input params */ /* if (j < numVals-1) */ /* j++; */ /* } */ /* /\* copy the '%' *\/ */ /* strseg[i++] = *fmt++; */ /* /\* find the format code *\/ */ /* segwaiting = fmt; */ /* while (*segwaiting && !isalpha(*segwaiting)) */ /* segwaiting++; */ /* } */ /* else */ /* strseg[i++] = *fmt++; */ /* } */ /* if (i) { */ /* strseg[i] = '\0'; */ /* if (segwaiting) { */ /* MYFLT xx = (j>=numVals? FL(0.0) : *kvals[j]); */ /* /\* printf("***xx = %f (int)(xx+.5)=%d round=%d mode=%d\n", *\/ */ /* /\* xx, (int)(xx+.5), MYFLT2LRND(xx), fegetround()); *\/ */ /* switch (*segwaiting) { */ /* case 'd': */ /* case 'i': */ /* case 'o': */ /* case 'x': */ /* case 'X': */ /* case 'u': */ /* case 'c': */ /* snprintf(outstring, 8196, strseg, (int)MYFLT2LRND(xx)); */ /* break; */ /* case 'h': */ /* snprintf(outstring, 8196, strseg, (int16)MYFLT2LRND(xx)); */ /* break; */ /* case 'l': */ /* snprintf(outstring, 8196, strseg, (int32)MYFLT2LRND(xx)); */ /* break; */ /* default: */ /* CS_SPRINTF(outstring, strseg, xx); */ /* break; */ /* } */ /* } */ /* else */ /* snprintf(outstring, 8196, "%s", strseg); */ /* } */ /* } */ /* VL - rewritten 1/16 escaping %% correctly now. */ static int sprints(char *outstring, char *fmt, MYFLT **kvals, int32 numVals) { char tmp[8],cc; int j = 0; int len = 8192; while (*fmt) { if (*fmt == '%') { if (*(fmt+1) == '%') { *outstring++ = *fmt++; /* *outstring++ = */ fmt++; len-=1; } else if (*(fmt+1) && isspace(*(fmt+1))) { *outstring++ = *fmt++; *outstring++ = '%'; *outstring++ = *fmt++; len-=3; } else { int n = 1; char check='%'; tmp[0] = check; while (*(fmt+n) && !isblank(*(fmt+n))) { tmp[n] = *(fmt+n); if (isalpha(tmp[n])) { check = tmp[n]; break;} n++; } tmp[n] = *(fmt+n); tmp[n+1] = '\0'; n++; if (j>=numVals) return NOTOK; switch (check) { case 'd': case 'i': case 'o': case 'x': case 'X': case 'u': snprintf(outstring, len, tmp, MYFLT2LRND(*kvals[j])); break; case 'c': cc = (char) MYFLT2LRND(*kvals[j]); if (cc == '%') { *outstring++ = '%'; } snprintf(outstring, len, tmp, cc); break; default: //puts(fmt); snprintf(outstring, len, tmp, *kvals[j]); break; } if (j < numVals-1) j++; fmt += n; outstring += strlen(outstring); len -= strlen(outstring); } } else { *outstring++ = *fmt++; *outstring = '\0'; len--; } } return OK; } /*************************************/ /* printks is called on every k cycle * It must decide when to do a * print operation. */ int printks(CSOUND *csound, PRINTKS *p) { MYFLT timel; int32 cycles; char string[8192]; /* matt ingals replacement */ if (csound->ISSTRCOD(*p->ifilcod) == 0) { char *sarg; sarg = ((STRINGDAT*)p->ifilcod)->data; if (sarg == NULL) return csoundPerfError(csound, p->h.insdshead, Str("null string\n")); if (strcmp(sarg, p->old) != 0) { printksset_(csound, p, sarg); csound->Free(csound, p->old); p->old = cs_strdup(csound, sarg); } } /*-----------------------------------*/ if (UNLIKELY(p->initialised != -1)) csound->PerfError(csound, p->h.insdshead, Str("printks not initialised")); timel = ((MYFLT) CS_KCNT * CS_ONEDKR) - p->initime; /* Divide the current elapsed time by the cycle time and round down to * an integer. */ cycles = MYFLT2LRND(timel / p->ctime); /* printf("cysofar = %d cycles = %d (%f / %f)\n", p->cysofar, cycles, timel, p->ctime); */ /* Now test if the cycle number we are in is higher than the one in which * we last printed. If so, update cysofar and print. */ if (p->cysofar < cycles) { p->cysofar = cycles; /* Do the print cycle. */ //string[0]='\0'; /* incase of empty string */ memset(string,0,8192); if (sprints(string, p->txtstring, p->kvals, p->INOCOUNT-2)==NOTOK) return csound->PerfError(csound, p->h.insdshead, Str("Insufficient arguments in formatted printing")); csound->MessageS(csound, CSOUNDMSG_ORCH, "%s", string); } return OK; } /* matt ingalls -- i-rate prints */ int printsset(CSOUND *csound, PRINTS *p) { PRINTKS pk; char string[8192]; MYFLT ptime = 1; string[0] = '\0'; /* necessary as sprints is not nice */ pk.h = p->h; pk.ifilcod = p->ifilcod; pk.ptime = &ptime; printksset(csound, &pk); memset(string,0,8192); if (sprints(string, pk.txtstring, p->kvals, p->INOCOUNT-1)==NOTOK) return csound->InitError(csound, Str("Insufficient arguments in formatted printing")); csound->MessageS(csound, CSOUNDMSG_ORCH, "%s", string); return OK; } int printsset_S(CSOUND *csound, PRINTS *p) { PRINTKS pk; char string[8192]; MYFLT ptime = 1; string[0] = '\0'; /* necessary as sprints is not nice */ pk.h = p->h; pk.ifilcod = p->ifilcod; pk.ptime = &ptime; printksset_S(csound, &pk); if (strlen(pk.txtstring) < 8191){ memset(string,0,8192); if (sprints(string, pk.txtstring, p->kvals, p->INOCOUNT-1)==NOTOK) return csound->InitError(csound, Str("Insufficient arguments in formatted printing")); csound->MessageS(csound, CSOUNDMSG_ORCH, "%s", string); } else { csound->Warning(csound, Str("Formatting string too long: %s"), pk.txtstring); } return OK; } /*****************************************************************************/ /* peakk and peak ugens */ /* peakk() * * Write the absolute value of the input argument to the output if the former * is higher. */ int peakk(CSOUND *csound, PEAK *p) { if (*p->kpeakout < FABS(*p->xsigin)) { *p->kpeakout = FABS(*p->xsigin); } return OK; } /* peaka() * * Similar to peakk, but looks at an a rate input variable. */ int peaka(CSOUND *csound, PEAK *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *peak, pp; MYFLT *asigin; asigin = p->xsigin; peak = p->kpeakout; pp = *peak; if (UNLIKELY(early)) nsmps -= early; for (n=offset;npspace = (int)*p->space; if (UNLIKELY(p->pspace < 0)) p->pspace = 0; else if (UNLIKELY(p->pspace > 120)) p->pspace = 120; p->oldvalue = FL(-1.12123e35); /* hack to force printing first value */ return OK; } /* Gab 21-8-97 */ /* print a k variable each time it changes (useful for MIDI control sliders) */ int printk2(CSOUND *csound, PRINTK2 *p) { MYFLT value = *p->val; if (p->oldvalue != value) { csound->MessageS(csound, CSOUNDMSG_ORCH, " i%d ", (int)p->h.insdshead->p1.value); if (p->pspace > 0) { char s[128]; /* p->pspace is limited to 120 in printk2set() above */ memset(s, ' ', (size_t) p->pspace); s[p->pspace] = '\0'; csound->MessageS(csound, CSOUNDMSG_ORCH, "%s", s); } csound->MessageS(csound, CSOUNDMSG_ORCH, "%11.5f\n", *p->val); p->oldvalue = value; } return OK; } int printk3set(CSOUND *csound, PRINTK3 *p) { p->oldvalue = FL(-1.12123e35); /* hack to force printing first value */ p->sarg = ((STRINGDAT*)p->iformat)->data; return OK; } int printk3(CSOUND *csound, PRINTK3 *p) { MYFLT value = *p->val; if (p->oldvalue != value) { char buff[8196]; MYFLT *vv[1]; vv[0] = &value; buff[0] = '\0'; if (sprints(buff, p->sarg, vv, 1)==NOTOK) return csound->PerfError(csound, p->h.insdshead, Str("Insufficient arguments in formatted printing")); csound->MessageS(csound, CSOUNDMSG_ORCH, "%s", buff); p->oldvalue = value; } //else printf("....%f %f\n", p->oldvalue, value); return OK; } /* inz writes to za space at a rate as many channels as can. */ int inz(CSOUND *csound, IOZ *p) { int32 indx, i; int nchns = csound->nchnls; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; /* Check to see this index is within the limits of za space. */ indx = (int32) *p->ndx; if (UNLIKELY((indx + csound->nchnls) >= csound->zalast)) goto err1; else if (UNLIKELY(indx < 0)) goto err2; else { MYFLT *writeloc; /* Now write to the array in za space pointed to by indx. */ writeloc = csound->zastart + (indx * nsmps); early = nsmps - early; for (i = 0; i < nchns; i++) for (n = 0; n < nsmps; n++) *writeloc++ = ((n>=offset && nPerfError(csound, p->h.insdshead, Str("inz index > isizea. Not writing.")); err2: return csound->PerfError(csound, p->h.insdshead, Str("inz index < 0. Not writing.")); } /* outz reads from za space at a rate to output. */ int outz(CSOUND *csound, IOZ *p) { int32 indx; int i; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int nchns = csound->nchnls; MYFLT *spout = csound->spraw; /* Check to see this index is within the limits of za space. */ indx = (int32) *p->ndx; if (UNLIKELY((indx + csound->nchnls) >= csound->zalast)) goto err1; else if (UNLIKELY(indx < 0)) goto err2; else { MYFLT *readloc; /* Now read from the array in za space and write to the output. */ readloc = csound->zastart + (indx * nsmps); early = nsmps-early; if (!csound->spoutactive) { memset(spout, '\0', nchns*nsmps*sizeof(MYFLT)); for (i = 0; i < nchns; i++) { memcpy(&spout[i * nsmps+offset], readloc+offset, (early-offset)*sizeof(MYFLT)); readloc += nsmps; } csound->spoutactive = 1; } else { for (i = 0; i < nchns; i++) { for (n = offset; n < nsmps-early; n++) { spout[n + i*nsmps] += readloc[n]; } readloc += nsmps; } } } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("outz index > isizea. No output")); err2: return csound->PerfError(csound, p->h.insdshead, Str("outz index < 0. No output.")); } csound-6.10.0/OOps/ugtabs.c000066400000000000000000000565521321653344700154270ustar00rootroot00000000000000/* ugtabs.c: new implementation of table readers and writers Copyright (C) 2013 V Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "ugtabs.h" #include "ugens2.h" #include //(x >= FL(0.0) ? (int32)x : (int32)((double)x - 0.99999999)) #define MYFLOOR(x) FLOOR(x) int tabler_init(CSOUND *csound, TABL *p) { int ndx, len; int mask; if (UNLIKELY((p->ftp = csound->FTnp2Find(csound, p->ftable)) == NULL)) return csound->InitError(csound, Str("table: could not find ftable %d"), (int) *p->ftable); mask = p->ftp->lenmask; p->np2 = mask ? 0 : 1; len = p->ftp->flen; if (*p->mode) p->mul = len; else p->mul = 1; ndx = FLOOR((*p->ndx + *p->offset)*p->mul); if (*p->wrap) { if (p->np2) { while(ndx >= len) ndx -= len; while(ndx < 0) ndx += len; } else ndx &= mask; } else { if (UNLIKELY(ndx >= len)) ndx = len - 1; else if (UNLIKELY(ndx < 0)) ndx = 0; } *p->sig = p->ftp->ftable[ndx]; return OK; } int tabl_setup(CSOUND *csound, TABL *p) { if(p->ftp == NULL) { /* check for this only on first allocation */ if (UNLIKELY(IS_ASIG_ARG(p->ndx) != IS_ASIG_ARG(p->sig))) { if (CS_KSMPS != 1) return csound->InitError(csound, Str("table: index type inconsistent with output")); } } if (UNLIKELY((p->ftp = csound->FTnp2Find(csound, p->ftable)) == NULL)) return csound->InitError(csound, Str("table: could not find ftable %d"), (int) *p->ftable); p->np2 = p->ftp->lenmask ? 0 : 1; if (*p->mode) p->mul = p->ftp->flen; else p->mul = 1; p->len = p->ftp->flen; p->iwrap = (int32) *p->wrap; return OK; } int tabler_kontrol(CSOUND *csound, TABL *p) { int ndx, len = p->len; int mask = p->ftp->lenmask; IGN(csound); ndx = MYFLOOR((*p->ndx + *p->offset)*p->mul); if (p->iwrap) { if (p->np2) { while(ndx >= len) ndx -= len; while(ndx < 0) ndx += len; } else ndx &= mask; } else { if (UNLIKELY(ndx >= len)) ndx = len - 1; else if (UNLIKELY(ndx < 0)) ndx = 0; } *p->sig = p->ftp->ftable[ndx]; return OK; } int tabler_audio(CSOUND *csound, TABL *p) { int ndx, len = p->len, n, nsmps = CS_KSMPS; int mask = p->ftp->lenmask; MYFLT *sig = p->sig; MYFLT *ndx_f = p->ndx; MYFLT *func = p->ftp->ftable; MYFLT offset = *p->offset; MYFLT mul = p->mul; int32 iwrap = p->iwrap; uint32_t koffset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; if (UNLIKELY(koffset)) memset(sig, '\0', koffset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&sig[nsmps], '\0', early*sizeof(MYFLT)); } for (n=koffset; n < nsmps; n++) { ndx = MYFLOOR((ndx_f[n] + offset)*mul); if (iwrap) { if (p->np2) { while(ndx >= len) ndx -= len; while(ndx < 0) ndx += len; } else ndx &= mask; } else { if (UNLIKELY(ndx >= len)) ndx = len - 1; else if (UNLIKELY(ndx < 0)) ndx = 0; } p->sig[n] = func[ndx]; } return OK; } int tableir_init(CSOUND *csound, TABL *p) { int ndx, len; int mask; MYFLT tmp, frac; MYFLT x1, x2; if (UNLIKELY((p->ftp = csound->FTnp2Find(csound, p->ftable)) == NULL)) return csound->InitError(csound, Str("table: could not find ftable %d"), (int) *p->ftable); mask = p->ftp->lenmask; p->np2 = mask ? 0 : 1; len = p->ftp->flen; if (*p->mode) p->mul = len; else p->mul = 1; tmp = (*p->ndx + *p->offset)*p->mul; ndx = MYFLOOR(tmp); frac = tmp - ndx; if (*p->wrap) { if (p->np2) { while(ndx >= len) ndx -= len; while(ndx < 0) ndx += len; } else ndx &= mask; } else { if (UNLIKELY(ndx >= len)) ndx = len - 1; else if (UNLIKELY(ndx < 0)) ndx = 0; } x1 = p->ftp->ftable[ndx]; x2 = p->ftp->ftable[ndx+1]; *p->sig = x1 + (x2 - x1)*frac; return OK; } int tableir_kontrol(CSOUND *csound, TABL *p) { int ndx, len = p->len; int mask = p->ftp->lenmask; MYFLT tmp, frac; MYFLT x1, x2; IGN(csound); tmp = (*p->ndx + *p->offset)*p->mul; ndx = MYFLOOR(tmp); frac = tmp - ndx; if (p->iwrap) { if (p->np2) { while(ndx >= len) ndx -= len; while(ndx < 0) ndx += len; } else ndx &= mask; } else { if (UNLIKELY(ndx >= len)) ndx = len - 1; else if (UNLIKELY(ndx < 0)) ndx = 0; } x1 = p->ftp->ftable[ndx]; x2 = p->ftp->ftable[ndx+1]; *p->sig = x1 + (x2 - x1)*frac; return OK; } int tableir_audio(CSOUND *csound, TABL *p) { int ndx, len = p->len, n, nsmps = CS_KSMPS; int mask = p->ftp->lenmask; MYFLT *sig = p->sig; MYFLT *ndx_f = p->ndx; MYFLT *func = p->ftp->ftable; MYFLT offset = *p->offset; MYFLT mul = p->mul, tmp, frac; int32 iwrap = p->iwrap; uint32_t koffset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; if (UNLIKELY(koffset)) memset(sig, '\0', koffset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&sig[nsmps], '\0', early*sizeof(MYFLT)); } for (n=koffset; n < nsmps; n++) { MYFLT x1, x2; tmp = (ndx_f[n] + offset)*mul; ndx = MYFLOOR(tmp); frac = tmp - ndx; if (iwrap) { if (p->np2) { while(ndx >= len) ndx -= len; while(ndx < 0) ndx += len; } else ndx &= mask; } else { if (UNLIKELY(ndx >= len)) ndx = len - 1; else if (UNLIKELY(ndx < 0)) ndx = 0; } x1 = func[ndx]; x2 = func[ndx+1]; p->sig[n] = x1 + (x2 - x1)*frac; } return OK; } int table3r_init(CSOUND *csound, TABL *p) { int ndx, len; int mask; MYFLT tmp, frac; MYFLT x0, x1, x2, x3; MYFLT fracub, fracsq, temp1; MYFLT *func; if (UNLIKELY((p->ftp = csound->FTnp2Find(csound, p->ftable)) == NULL)) return csound->InitError(csound, Str("table: could not find ftable %d"), (int) *p->ftable); mask = p->ftp->lenmask; p->np2 = mask ? 0 : 1; len = p->ftp->flen; func =p->ftp->ftable; if (*p->mode) p->mul = len; else p->mul = 1; tmp = (*p->ndx + *p->offset)*p->mul; ndx = MYFLOOR(tmp); frac = tmp - ndx; if (*p->wrap) { if (p->np2) { while(ndx >= len) ndx -= len; while(ndx < 0) ndx += len; } else ndx &= mask; } else { if (UNLIKELY(ndx >= len)) ndx = len - 1; else if (UNLIKELY(ndx < 0)) ndx = 0; } if (UNLIKELY(ndx<1 || ndx==len-1 || len <4)) { x1 = func[ndx]; x2 = func[ndx+1]; *p->sig = x1 + (x2 - x1)*frac; } else { x0 = func[ndx-1]; x1 = func[ndx]; x2 = func[ndx+1]; x3 = func[ndx+2]; fracsq = frac*frac; fracub = fracsq*x0; temp1 = x3+FL(3.0)*x1; *p->sig = x1 + FL(0.5)*fracub + frac*(x2 - fracub/FL(6.0) - temp1/FL(6.0) - x0/FL(3.0)) + frac*fracsq*(temp1/FL(6.0) - FL(0.5)*x2) + fracsq*(FL(0.5)*x2 - x1); } return OK; } int table3r_kontrol(CSOUND *csound, TABL *p) { int ndx, len = p->len; int mask = p->ftp->lenmask; MYFLT tmp, frac; MYFLT x0, x1, x2, x3; MYFLT *func =p->ftp->ftable; MYFLT fracub, fracsq, temp1; IGN(csound); tmp = (*p->ndx + *p->offset)*p->mul; ndx = MYFLOOR(tmp); frac = tmp - ndx; if (p->iwrap) { if (p->np2) { while(ndx >= len) ndx -= len; while(ndx < 0) ndx += len; } else ndx &= mask; } else { if (UNLIKELY(ndx >= len)) ndx = len - 1; else if (UNLIKELY(ndx < 0)) ndx = 0; } if (UNLIKELY(ndx<1 || ndx==len-1 || len <4)) { x1 = func[ndx]; x2 = func[ndx+1]; *p->sig = x1 + (x2 - x1)*frac; } else { x0 = func[ndx-1]; x1 = func[ndx]; x2 = func[ndx+1]; x3 = func[ndx+2]; fracsq = frac*frac; fracub = fracsq*x0; temp1 = x3+FL(3.0)*x1; *p->sig = x1 + FL(0.5)*fracub + frac*(x2 - fracub/FL(6.0) - temp1/FL(6.0) - x0/FL(3.0)) + frac*fracsq*(temp1/FL(6.0) - FL(0.5)*x2) + fracsq*(FL(0.5)*x2 - x1); } return OK; } int table3r_audio(CSOUND *csound, TABL *p) { int ndx, len = p->len, n, nsmps = CS_KSMPS; int mask = p->ftp->lenmask; MYFLT *sig = p->sig; MYFLT *ndx_f = p->ndx; MYFLT *func = p->ftp->ftable; MYFLT offset = *p->offset; MYFLT mul = p->mul, tmp, frac; int32 iwrap = p->iwrap; uint32_t koffset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; if (UNLIKELY(koffset)) memset(sig, '\0', koffset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&sig[nsmps], '\0', early*sizeof(MYFLT)); } for (n=koffset; n < nsmps; n++) { MYFLT x0,x1,x2,x3,temp1,fracub,fracsq; tmp = (ndx_f[n] + offset)*mul; ndx = MYFLOOR(tmp); frac = tmp - ndx; if (iwrap) { if (p->np2) { while(ndx >= len) ndx -= len; while(ndx < 0) ndx += len; } else ndx &= mask; } else { if (UNLIKELY(ndx >= len)) ndx = len - 1; else if (UNLIKELY(ndx < 0)) ndx = 0; } if (UNLIKELY(ndx<1 || ndx==len-1 || len <4)) { x1 = func[ndx]; x2 = func[ndx+1]; p->sig[n] = x1 + (x2 - x1)*frac; } else { x0 = func[ndx-1]; x1 = func[ndx]; x2 = func[ndx+1]; x3 = func[ndx+2]; fracsq = frac*frac; fracub = fracsq*x0; temp1 = x3+x1+x1+x1; p->sig[n] = x1 + FL(0.5)*fracub + frac*(x2 - fracub/FL(6.0) - temp1/FL(6.0) - x0/FL(3.0)) + fracsq*frac*(temp1/FL(6.0) - FL(0.5)*x2) + fracsq*(FL(0.5)*x2 - x1); } } return OK; } int tablkt_setup(CSOUND *csound, TABL *p) { if (UNLIKELY(IS_ASIG_ARG(p->ndx) != IS_ASIG_ARG(p->sig))) { if (CS_KSMPS != 1) return csound->InitError(csound, Str("tablekt: index type inconsistent with output")); } p->iwrap = (int32) *p->wrap; return OK; } int tablerkt_kontrol(CSOUND *csound, TABL *p) { if (UNLIKELY((p->ftp = csound->FTnp2Find(csound, p->ftable)) == NULL)) return csound->PerfError(csound, p->h.insdshead, Str("table: could not find ftable %d"), (int) *p->ftable); p->np2 = p->ftp->lenmask ? 0 : 1; if (*p->mode) p->mul = p->ftp->flen; else p->mul = 1; p->len = p->ftp->flen; return tabler_kontrol(csound,p); } int tablerkt_audio(CSOUND *csound, TABL *p) { if (UNLIKELY((p->ftp = csound->FTnp2Find(csound, p->ftable)) == NULL)) return csound->PerfError(csound, p->h.insdshead, Str("table: could not find ftable %d"), (int) *p->ftable); p->np2 = p->ftp->lenmask ? 0 : 1; if (*p->mode) p->mul = p->ftp->flen; else p->mul = 1; p->len = p->ftp->flen; return tabler_audio(csound,p); } int tableirkt_kontrol(CSOUND *csound, TABL *p) { if (UNLIKELY((p->ftp = csound->FTnp2Find(csound, p->ftable)) == NULL)) return csound->PerfError(csound, p->h.insdshead, Str("table: could not find ftable %d"), (int) *p->ftable); p->np2 = p->ftp->lenmask ? 0 : 1; if (*p->mode) p->mul = p->ftp->flen; else p->mul = 1; p->len = p->ftp->flen; return tableir_kontrol(csound,p); } int tableirkt_audio(CSOUND *csound, TABL *p) { if (UNLIKELY((p->ftp = csound->FTnp2Find(csound, p->ftable)) == NULL)) return csound->PerfError(csound, p->h.insdshead, Str("table: could not find ftable %d"), (int) *p->ftable); p->np2 = p->ftp->lenmask ? 0 : 1; if (*p->mode) p->mul = p->ftp->flen; else p->mul = 1; p->len = p->ftp->flen; return tableir_audio(csound,p); } int table3rkt_kontrol(CSOUND *csound, TABL *p) { if (UNLIKELY((p->ftp = csound->FTnp2Find(csound, p->ftable)) == NULL)) return csound->PerfError(csound, p->h.insdshead, Str("table: could not find ftable %d"), (int) *p->ftable); p->np2 = p->ftp->lenmask ? 0 : 1; if (*p->mode) p->mul = p->ftp->flen; else p->mul = 1; p->len = p->ftp->flen; return table3r_kontrol(csound,p);; } int table3rkt_audio(CSOUND *csound, TABL *p) { if (UNLIKELY((p->ftp = csound->FTnp2Find(csound, p->ftable)) == NULL)) return csound->PerfError(csound, p->h.insdshead, Str("table: could not find ftable %d"), (int) *p->ftable); p->np2 = p->ftp->lenmask ? 0 : 1; if (*p->mode) p->mul = p->ftp->flen; else p->mul = 1; p->len = p->ftp->flen; return table3r_audio(csound,p); } int tablew_init(CSOUND *csound, TABL *p) { int ndx, len; int mask; MYFLT *func; int32 iwrap = *p->wrap; if (UNLIKELY((p->ftp = csound->FTnp2Find(csound, p->ftable)) == NULL)) return csound->InitError(csound, Str("table: could not find ftable %d"), (int) *p->ftable); func = p->ftp->ftable; mask = p->ftp->lenmask; p->np2 = mask ? 0 : 1; len = p->ftp->flen; if (*p->mode) p->mul = len; else p->mul = 1; ndx = MYFLOOR((*p->ndx + *p->offset)*p->mul + (iwrap==2 ? 0.5:0)); if (iwrap) { ndx = iwrap == 2 ? MYFLOOR(ndx+0.5) : ndx; if (p->np2) { while(ndx >= len) ndx -= len; while(ndx < 0) ndx += len; } else ndx &= mask; } else { if (UNLIKELY(ndx >= len)) ndx = len - 1; else if (UNLIKELY(ndx < 0)) ndx = 0; } p->ftp->ftable[ndx] = *p->sig; if (ndx == 0 && iwrap==2) func[len] = func[ndx]; return OK; } int tablew_kontrol(CSOUND *csound, TABL *p) { int ndx, len = p->len; int mask = p->ftp->lenmask; MYFLT *func = p->ftp->ftable; int32 iwrap = p->iwrap; IGN(csound); ndx = MYFLOOR((*p->ndx + *p->offset)*p->mul + (iwrap==2 ? 0.5:0)); if (iwrap) { if (p->np2) { while(ndx >= len) ndx -= len; while(ndx < 0) ndx += len; } else ndx &= mask; } else { if (UNLIKELY(ndx >= len)) ndx = len - 1; else if (UNLIKELY(ndx < 0)) ndx = 0; } func[ndx] = *p->sig; if (ndx == 0 && iwrap==2) func[len] = func[ndx]; return OK; } int tablew_audio(CSOUND *csound, TABL *p) { int ndx, len = p->len, n, nsmps = CS_KSMPS; int mask = p->ftp->lenmask; MYFLT *sig = p->sig; MYFLT *ndx_f = p->ndx; MYFLT *func = p->ftp->ftable; MYFLT offset = *p->offset; MYFLT mul = p->mul; int32 iwrap = p->iwrap; uint32_t koffset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; if (UNLIKELY(early)) nsmps -= early; for (n=koffset; n < nsmps; n++) { ndx = MYFLOOR((ndx_f[n] + offset)*mul + (iwrap==2 ? 0.5:0)); if (iwrap) { if (p->np2) { while(ndx >= len) ndx -= len; while(ndx < 0) ndx += len; } else ndx &= mask; } else { if (UNLIKELY(ndx >= len)) ndx = len - 1; else if (UNLIKELY(ndx < 0)) ndx = 0; } func[ndx] = sig[n]; if (iwrap==2 && ndx == 0) func[len] = func[ndx]; } return OK; } int tablewkt_kontrol(CSOUND *csound, TABL *p) { if (UNLIKELY((p->ftp = csound->FTnp2Find(csound, p->ftable)) == NULL)) return csound->PerfError(csound, p->h.insdshead, Str("table: could not find ftable %d"), (int) *p->ftable); p->np2 = p->ftp->lenmask ? 0 : 1; if (*p->mode) p->mul = p->ftp->flen; else p->mul = 1; p->len = p->ftp->flen; return tablew_kontrol(csound,p); } int tablewkt_audio(CSOUND *csound, TABL *p) { if (UNLIKELY((p->ftp = csound->FTnp2Find(csound, p->ftable)) == NULL)) return csound->PerfError(csound, p->h.insdshead, Str("table: could not find ftable %d"), (int) *p->ftable); p->np2 = p->ftp->lenmask ? 0 : 1; if (*p->mode) p->mul = p->ftp->flen; else p->mul = 1; p->len = p->ftp->flen; return tablew_audio(csound,p);; } int table_length(CSOUND *csound, TLEN *p) { FUNC *ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->ftable)) == NULL)) { csound->Warning(csound, Str("table: could not find ftable %d"), (int) *p->ftable); *p->ans = FL(-1.0); return NOTOK; } else *p->ans = (MYFLT) ftp->flen; return OK; } int table_gpw(CSOUND *csound, TGP *p) { FUNC *ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->ftable)) == NULL)) { csound->Warning(csound, Str("table: could not find ftable %d"), (int) *p->ftable); return NOTOK; } ftp->ftable[ftp->flen] = ftp->ftable[0]; return OK; } int table_copy(CSOUND *csound, TGP *p) { FUNC *dest, *src; int32 len1, len2, i, rp; if (UNLIKELY((dest = csound->FTnp2Find(csound, p->ftable)) == NULL || (src = csound->FTnp2Find(csound, p->ftsrc)) == NULL)) { csound->Warning(csound, Str("table: could not find ftables %d and/or %d"), (int) *p->ftable, (int) *p->ftsrc); return NOTOK; } len1 = dest->flen; len2 = src->flen; for (i=rp=0; iftable[i] = src->ftable[rp]; rp = rp == len2 ? 0 : rp+1; } return OK; } int table_mix(CSOUND *csound, TABLMIX *p) { int32 np2, np21, np22; FUNC *ftp, *ftp1, *ftp2; int32 len, len1, len2, flen; MYFLT g1, g2, *func, *func1, *func2; int32 off, off1, off2; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->tab)) == NULL)) { csound->Warning(csound, Str("table: could not find ftable %d"), (int) *p->tab); return NOTOK; } np2 = ftp->lenmask ? 0 : 1; if (UNLIKELY((ftp1 = csound->FTnp2Find(csound, p->tab1)) == NULL)) { csound->Warning(csound, Str("table: could not find ftable %d"), (int) *p->tab1); return NOTOK; } np21 = ftp1->lenmask ? 0 : 1; if (UNLIKELY((ftp2 = csound->FTnp2Find(csound, p->tab2)) == NULL)) { csound->Warning(csound, Str("table: could not find ftable %d"), (int) *p->tab2); return NOTOK; } np22 = ftp2->lenmask ? 0 : 1; len = MYFLOOR(*p->len); flen = ftp->flen; len1 = ftp1->flen; len2 = ftp2->flen; func = ftp->ftable; func1 = ftp1->ftable; func2 = ftp2->ftable; off = *p->off; off1 = *p->off1; off2 = *p->off2; g1 = *p->g1; g2 = *p->g2; if (len>0) { int i, p0, p1, p2; for (i=0; i < len; i++) { p0 = i+off; p1 = i+off1; p2 = i+off2; if (np2) { while(p0 < 0) p0 += flen; while(p0 >= len1) p0 -= flen; } else p0 &= ftp->lenmask; if (np21) { while(p1 < 0) p1 += len1; while(p1 >= len1) p1 -= len1; } else p1 &= ftp1->lenmask; if (np22) { while (p2 < 0) p2 += len2; while (p2 >= len2) p2 -= len2; } else p2 &= ftp2->lenmask; func[p0] = func1[p1]*g1 + func2[p2]*g2; } } else { int i, p0, p1, p2; for (i=0; i > len; i--) { p0 = i+off; p1 = i+off1; p2 = i+off2; if (np2) { while(p0 < 0) p0 += flen; while(p0 >= len1) p0 -= flen; } else p0 &= ftp->lenmask; if (np21) { while(p1 < 0) p1 += len1; while(p1 >= len1) p1 -= len1; } else p1 &= ftp1->lenmask; if (np22) { while(p2 < 0) p2 += len2; while(p2 >= len2) p2 -= len2; } else p2 &= ftp2->lenmask; func[p0] = func1[p1]*g1 + func2[p2]*g2; } } return OK; } int table_ra_set(CSOUND *csound, TABLRA *p) { IGN(csound); return OK; } int table_ra(CSOUND *csound, TABLRA *p) { int32 pos, np2, nsmps, len, i; MYFLT *sig= p->sig, *func; int mask; FUNC *ftp; uint32_t koffset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; nsmps = CS_KSMPS; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->ftable)) == NULL)) return csound->PerfError(csound, p->h.insdshead, Str("table: could not find ftable %d"), (int) *p->ftable); np2 = ftp->lenmask ? 0 : 1; mask = ftp->lenmask; pos = *p->strt + *p->off; if (pos < 0) return csound->PerfError(csound, p->h.insdshead, Str("table: could not read negative pos %d"), pos); if (UNLIKELY(koffset)) memset(sig, '\0', koffset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&sig[nsmps], '\0', early*sizeof(MYFLT)); } func = ftp->ftable; len = ftp->flen; for (i=koffset; i < nsmps; i++) { if (np2) pos %= len; else pos &= mask; sig[i] = func[pos]; pos++; } return OK; } int table_wa_set(CSOUND *csound, TABLWA *p) { IGN(csound); if(!*p->skipinit) p->pos = 0; p->pos += *p->off; return OK; } int table_wa(CSOUND *csound, TABLWA *p) { int32 pos, np2, nsmps, len, i; MYFLT *sig= p->sig, *func; int mask; FUNC *ftp; uint32_t koffset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; nsmps = CS_KSMPS; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->ftable)) == NULL)) return csound->PerfError(csound, p->h.insdshead, Str("table: could not find ftable %d"), (int) *p->ftable); np2 = ftp->lenmask ? 0 : 1; mask = ftp->lenmask; pos = p->pos; /*+ *p->off;*/ if (pos < 0) return csound->PerfError(csound, p->h.insdshead, Str("table: could not read negative pos %d"), pos); if (UNLIKELY(early)) nsmps -= early; func = ftp->ftable; len = ftp->flen; for (i=koffset; i < nsmps; i++) { if (np2) pos %= len; else pos &= mask; func[pos] = sig[i]; pos++; } p->pos = pos; *p->strt = pos; return OK; } csound-6.10.0/OOps/vdelay.c000066400000000000000000001305141321653344700154150ustar00rootroot00000000000000/* vdelay.c: Copyright (C) 1994, 1998, 2000, 2001 Paris Smaragdis, Richard Karpen, rasmus ekman, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* vdelay, multitap, reverb2 coded by Paris Smaragdis 1994 */ /* Berklee College of Music Csound development team */ /* Copyright (c) May 1994. All rights reserved */ #include "csoundCore.h" #include #include "vdelay.h" //#define ESR (csound->esr/FL(1000.0)) #define ESR (csound->esr*FL(0.001)) int vdelset(CSOUND *csound, VDEL *p) /* vdelay set-up */ { uint32 n = (int32)(*p->imaxd * ESR)+1; if (!*p->istod) { if (p->aux.auxp == NULL || (uint32_t)(n * sizeof(MYFLT)) > p->aux.size) /* allocate space for delay buffer */ csound->AuxAlloc(csound, n * sizeof(MYFLT), &p->aux); else { /* make sure buffer is empty */ memset(p->aux.auxp, '\0', n*sizeof(MYFLT)); } p->left = 0; } p->maxd = n - 1; return OK; } int vdelay(CSOUND *csound, VDEL *p) /* vdelay routine */ { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, nsmps = CS_KSMPS; int32 maxd, indx; MYFLT *out = p->sr; /* assign object data to local variables */ MYFLT *in = p->ain; MYFLT *del = p->adel; MYFLT *buf = (MYFLT *)p->aux.auxp; MYFLT esr = ESR; if (UNLIKELY(buf==NULL)) goto err1; /* RWD fix */ maxd = p->maxd; indx = p->left; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } if (IS_ASIG_ARG(p->adel)) { /* if delay is a-rate */ for (nn=offset; nn=" instead of a ">" comparison. The order of the comparisons * has been swapped as well (a bit of a nit, but comparing a * possibly negative number to an unsigned isn't a good idea--and * broke on Alpha). * heh 981101 */ while (UNLIKELY(fv1 < FL(0.0))) fv1 += (MYFLT)maxd; while (UNLIKELY(fv1 >= (MYFLT)maxd)) fv1 -= (MYFLT)maxd; if (LIKELY(fv1 < maxd - 1)) /* Find next sample for interpolation */ fv2 = fv1 + FL(1.0); else fv2 = FL(0.0); v1 = (int32)fv1; v2 = (int32)fv2; out[nn] = buf[v1] + (fv1 - v1) * ( buf[v2] - buf[v1]); if (UNLIKELY(++indx == maxd)) indx = 0; /* Advance current pointer */ } } else { /* and, if delay is k-rate */ MYFLT fdel=*del; for (nn=offset; nn= (MYFLT)maxd)) fv1 -= (MYFLT)maxd; if (LIKELY(fv1 < maxd - 1)) /* Find next sample for interpolation */ fv2 = fv1 + FL(1.0); else fv2 = FL(0.0); v1 = (int32)fv1; v2 = (int32)fv2; out[nn] = buf[v1] + (fv1 - v1) * ( buf[v2] - buf[v1]); if (UNLIKELY(++indx == maxd)) indx = 0; /* Advance current pointer */ } } p->left = indx; /* and keep track of where you are */ return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("vdelay: not initialised")); } int vdelay3(CSOUND *csound, VDEL *p) /* vdelay routine with cubic interp */ { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, nsmps = CS_KSMPS; int32 maxd, indx; MYFLT *out = p->sr; /* assign object data to local variables */ MYFLT *in = p->ain; MYFLT *del = p->adel; MYFLT *buf = (MYFLT *)p->aux.auxp; MYFLT esr = ESR; if (UNLIKELY(buf==NULL)) goto err1; /* RWD fix */ maxd = p->maxd; if (UNLIKELY(maxd == 0)) maxd = 1; /* Degenerate case */ indx = p->left; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } if (IS_ASIG_ARG(p->adel)) { /* if delay is a-rate */ for (nn=offset; nn= (int32)maxd)) v1 -= (int32)maxd; } /* Find next sample for interpolation */ v2 = (v1 == (int32)(maxd - 1UL) ? 0L : v1 + 1L); if (maxd<4) { out[nn] = buf[v1] + fv1 * (buf[v2] - buf[v1]); } else { v0 = (v1==0 ? maxd-1 : v1-1); v3 = (v2==(int32)maxd-1 ? 0 : v2+1); { /* optimized by Istvan Varga (Oct 2001) */ MYFLT w, x, y, z; z = fv1 * fv1; z--; z *= FL(0.1666666667); y = fv1; y++; w = (y *= FL(0.5)); w--; x = FL(3.0) * z; y -= x; w -= z; x -= fv1; out[nn] = (w*buf[v0] + x*buf[v1] + y*buf[v2] + z*buf[v3]) * fv1 + buf[v1]; } } if (UNLIKELY(++indx == maxd)) indx = 0; /* Advance current pointer */ }; } else { /* and, if delay is k-rate */ MYFLT fv1, w, x, y, z; int32 v0, v1, v2, v3; fv1 = *del * -esr; v1 = (int32)fv1; fv1 -= (MYFLT) v1; v1 += (int32)indx; /* Make sure Inside the buffer */ if ((v1 < 0L) || (fv1 < FL(0.0))) { fv1++; v1--; while (UNLIKELY(v1 < 0L)) v1 += (int32)maxd; } else { while (UNLIKELY(v1 >= (int32)maxd)) v1 -= (int32)maxd; } if (maxd<4) { for (nn=offset; nn= (int32)maxd)) v1 -= (int32)maxd; if (UNLIKELY(++indx >= maxd)) indx -= maxd; } } else { /* calculate interpolation coeffs */ z = fv1 * fv1; z--; z *= FL(0.1666666667); /* IV Oct 2001 */ y = fv1; y++; w = (y *= FL(0.5)); w--; x = FL(3.0) * z; y -= x; w -= z; x -= fv1; for (nn=offset; nn= (int32)maxd)) v1 -= (int32)maxd; if (UNLIKELY(++indx >= maxd)) indx -= maxd; /* Advance current pointer */ } } } p->left = indx; /* and keep track of where you are */ return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("vdelay3: not initialised")); } /* vdelayx, vdelayxs, vdelayxq, vdelayxw, vdelayxws, vdelayxwq */ /* coded by Istvan Varga, Mar 2001 */ int vdelxset(CSOUND *csound, VDELX *p) /* vdelayx set-up (1 channel) */ { unsigned int n = (int)(*p->imaxd * csound->esr); if (UNLIKELY(n == 0)) n = 1; /* fix due to Troxler */ if (!*p->istod) { if (p->aux1.auxp == NULL || (uint32_t)(n * sizeof(MYFLT)) > p->aux1.size) /* allocate space for delay buffer */ csound->AuxAlloc(csound, n * sizeof(MYFLT), &p->aux1); else memset(p->aux1.auxp, 0, n*sizeof(MYFLT)); p->left = 0; p->interp_size = 4 * (int) (FL(0.5) + FL(0.25) * *(p->iquality)); p->interp_size = (p->interp_size < 4 ? 4 : p->interp_size); p->interp_size = (p->interp_size > 1024 ? 1024 : p->interp_size); } p->maxd = (uint32) n; return OK; } int vdelxsset(CSOUND *csound, VDELXS *p) /* vdelayxs set-up (stereo) */ { unsigned int n = (int)(*p->imaxd * csound->esr); if (UNLIKELY(n == 0)) n = 1; /* fix due to Troxler */ if (!*p->istod) { if (p->aux1.auxp == NULL || (uint32_t)(n * sizeof(MYFLT)) > p->aux1.size) /* allocate space for delay buffer */ csound->AuxAlloc(csound, n * sizeof(MYFLT), &p->aux1); else memset(p->aux1.auxp, 0, n*sizeof(MYFLT)); if (p->aux2.auxp == NULL || (uint32_t)(n * sizeof(MYFLT)) > p->aux2.size) csound->AuxAlloc(csound, n * sizeof(MYFLT), &p->aux2); else memset(p->aux2.auxp, 0, n*sizeof(MYFLT)); p->left = 0; p->interp_size = 4 * (int) (FL(0.5) + FL(0.25) * *(p->iquality)); p->interp_size = (p->interp_size < 4 ? 4 : p->interp_size); p->interp_size = (p->interp_size > 1024 ? 1024 : p->interp_size); } p->maxd = (uint32) n; return OK; } int vdelxqset(CSOUND *csound, VDELXQ *p) /* vdelayxq set-up (quad channels) */ { unsigned int n = (int)(*p->imaxd * csound->esr); if (UNLIKELY(n == 0)) n = 1; /* fix due to Troxler */ if (!*p->istod) { if (p->aux1.auxp == NULL || (uint32_t)(n * sizeof(MYFLT)) > p->aux1.size) /* allocate space for delay buffer */ csound->AuxAlloc(csound, n * sizeof(MYFLT), &p->aux1); else memset(p->aux1.auxp, 0, n*sizeof(MYFLT)); if (p->aux2.auxp == NULL || (uint32_t)(n * sizeof(MYFLT)) > p->aux2.size) csound->AuxAlloc(csound, n * sizeof(MYFLT), &p->aux2); else memset(p->aux2.auxp, 0, n*sizeof(MYFLT)); if (p->aux3.auxp == NULL || (uint32_t)(n * sizeof(MYFLT)) > p->aux3.size) csound->AuxAlloc(csound, n * sizeof(MYFLT), &p->aux3); else memset(p->aux3.auxp, 0, n*sizeof(MYFLT)); if (p->aux4.auxp == NULL || (uint32_t)(n * sizeof(MYFLT)) > p->aux4.size) csound->AuxAlloc(csound, n * sizeof(MYFLT), &p->aux4); else memset(p->aux4.auxp, 0, n*sizeof(MYFLT)); p->left = 0; p->interp_size = 4 * (int) (FL(0.5) + FL(0.25) * *(p->iquality)); p->interp_size = (p->interp_size < 4 ? 4 : p->interp_size); p->interp_size = (p->interp_size > 1024 ? 1024 : p->interp_size); } p->maxd = (uint32) n; return OK; } int vdelayx(CSOUND *csound, VDELX *p) /* vdelayx routine */ { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, nsmps = CS_KSMPS; int32 indx, maxd; MYFLT *out1 = p->sr1; /* assign object data to local variables */ MYFLT *in1 = p->ain1; MYFLT *del = p->adel; MYFLT *buf1 = (MYFLT *)p->aux1.auxp; int wsize = p->interp_size; double x1, x2, w, d, d2x, n1; int32 i, i2, xpos; if (UNLIKELY(buf1 == NULL)) goto err1; /* RWD fix */ maxd = p->maxd; if (UNLIKELY(maxd == 0)) maxd = 1; /* Degenerate case */ indx = p->left; i2 = (wsize >> 1); d2x = (1.0 - pow ((double)wsize * 0.85172, -0.89624)) / (double)(i2 * i2); if (UNLIKELY(offset)) memset(out1, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out1[nsmps], '\0', early*sizeof(MYFLT)); } for (nn=offset; nnesr); while (x1 < 0.0) x1 += (double)maxd; xpos = (int32)x1; x1 -= (double)xpos; x2 = sin (PI * x1) / PI; while (xpos >= maxd) xpos -= maxd; if (x1 * (1.0 - x1) > 0.00000001) { xpos += (1 - i2); while (xpos < 0) xpos += maxd; d = (double)(1 - i2) - x1; for (i = i2; i--;) { w = 1.0 - d*d*d2x; w *= (w / d++); n1 += (double)buf1[xpos] * w; if (UNLIKELY(++xpos >= maxd)) xpos -= maxd; w = 1.0 - d*d*d2x; w *= (w / d++); n1 -= (double)buf1[xpos] * w; if (UNLIKELY(++xpos >= maxd)) xpos -= maxd; } out1[nn] = (MYFLT) (n1 * x2); } else { /* integer sample */ xpos = (int32)((double)xpos + x1 + 0.5); /* position */ if (UNLIKELY(xpos >= maxd)) xpos -= maxd; out1[nn] = buf1[xpos]; } if (UNLIKELY(++indx == maxd)) indx = 0; } p->left = indx; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("vdelay: not initialised")); } int vdelayxw(CSOUND *csound, VDELX *p) /* vdelayxw routine */ { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, nsmps = CS_KSMPS; int32 maxd, indx; MYFLT *out1 = p->sr1; /* assign object data to local variables */ MYFLT *in1 = p->ain1; MYFLT *del = p->adel; MYFLT *buf1 = (MYFLT *)p->aux1.auxp; int wsize = p->interp_size; double x1, x2, w, d, d2x, n1; int32 i, i2, xpos; if (UNLIKELY(buf1 == NULL)) goto err1; /* RWD fix */ maxd = p->maxd; if (UNLIKELY(maxd == 0)) maxd = 1; /* Degenerate case */ indx = p->left; i2 = (wsize >> 1); d2x = (1.0 - pow ((double)wsize * 0.85172, -0.89624)) / (double)(i2 * i2); if (UNLIKELY(offset)) memset(out1, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out1[nsmps], '\0', early*sizeof(MYFLT)); } for (nn=offset;nnesr); while (x1 < 0.0) x1 += (double)maxd; xpos = (int32)x1; x1 -= (double)xpos; x2 = sin (PI * x1) / PI; while (xpos >= maxd) xpos -= maxd; if (LIKELY(x1 * (1.0 - x1) > 0.00000001)) { n1 = (double)in1[nn] * x2; xpos += (1 - i2); while (xpos < 0) xpos += maxd; d = (double)(1 - i2) - x1; for (i = i2; i--;) { w = 1.0 - d*d*d2x; w *= (w / d++); buf1[xpos] += (MYFLT) (n1 * w); if (UNLIKELY(++xpos >= maxd)) xpos -= maxd; w = 1.0 - d*d*d2x; w *= (w / d++); buf1[xpos] -= (MYFLT) (n1 * w); if (UNLIKELY(++xpos >= maxd)) xpos -= maxd; } } else { /* integer sample */ xpos = (int32)((double)xpos + x1 + 0.5); /* position */ if (UNLIKELY(xpos >= maxd)) xpos -= maxd; buf1[xpos] += in1[nn]; } out1[nn] = buf1[indx]; buf1[indx] = FL(0.0); if (UNLIKELY(++indx == maxd)) indx = 0; } p->left = indx; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("vdelay: not initialised")); } int vdelayxs(CSOUND *csound, VDELXS *p) /* vdelayxs routine */ { int32 maxd, indx; MYFLT *out1 = p->sr1; /* assign object data to local variables */ MYFLT *out2 = p->sr2; MYFLT *in1 = p->ain1; MYFLT *in2 = p->ain2; MYFLT *del = p->adel; MYFLT *buf1 = (MYFLT *)p->aux1.auxp; MYFLT *buf2 = (MYFLT *)p->aux2.auxp; int wsize = p->interp_size; double x1, x2, w, d, d2x, n1, n2; int32 i, i2, xpos; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY((buf1 == NULL) || (buf2 == NULL))) goto err1; /* RWD fix */ maxd = p->maxd; if (UNLIKELY(maxd == 0)) maxd = 1; /* Degenerate case */ indx = p->left; i2 = (wsize >> 1); d2x = (1.0 - pow ((double)wsize * 0.85172, -0.89624)) / (double)(i2 * i2); if (UNLIKELY(offset)) { memset(out1, '\0', offset*sizeof(MYFLT)); memset(out2, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&out1[nsmps], '\0', early*sizeof(MYFLT)); memset(&out2[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nesr); while (UNLIKELY(x1 < 0.0)) x1 += (double)maxd; xpos = (int32)x1; x1 -= (double)xpos; x2 = sin (PI * x1) / PI; while (UNLIKELY(xpos >= maxd)) xpos -= maxd; if (x1 * (1.0 - x1) > 0.00000001) { xpos += (1 - i2); while (UNLIKELY(xpos < 0)) xpos += maxd; d = (double)(1 - i2) - x1; for (i = i2; i--;) { w = 1.0 - d*d*d2x; w *= (w / d++); n1 += (double)buf1[xpos] * w; n2 += (double)buf2[xpos] * w; if (UNLIKELY(++xpos >= maxd)) xpos -= maxd; w = 1.0 - d*d*d2x; w *= (w / d++); n1 -= (double)buf1[xpos] * w; n2 -= (double)buf2[xpos] * w; if (UNLIKELY(++xpos >= maxd)) xpos -= maxd; } out1[n] = (MYFLT) (n1 * x2); out2[n] = (MYFLT) (n2 * x2); } else { /* integer sample */ xpos = (int32)((double)xpos + x1 + 0.5); /* position */ if (UNLIKELY(xpos >= maxd)) xpos -= maxd; out1[n] = buf1[xpos]; out2[n] = buf2[xpos]; } if (UNLIKELY(++indx == maxd)) indx = 0; } p->left = indx; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("vdelay: not initialised")); } int vdelayxws(CSOUND *csound, VDELXS *p) /* vdelayxws routine */ { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 maxd, indx; MYFLT *out1 = p->sr1; /* assign object data to local variables */ MYFLT *out2 = p->sr2; MYFLT *in1 = p->ain1; MYFLT *in2 = p->ain2; MYFLT *del = p->adel; MYFLT *buf1 = (MYFLT *)p->aux1.auxp; MYFLT *buf2 = (MYFLT *)p->aux2.auxp; int wsize = p->interp_size; double x1, x2, w, d, d2x, n1, n2; int32 i, i2, xpos; if (UNLIKELY((buf1 == NULL) || (buf2 == NULL))) goto err1; /* RWD fix */ maxd = p->maxd; if (UNLIKELY(maxd == 0)) maxd = 1; /* Degenerate case */ indx = p->left; i2 = (wsize >> 1); d2x = (1.0 - pow ((double)wsize * 0.85172, -0.89624)) / (double)(i2 * i2); if (UNLIKELY(offset)) { memset(out1, '\0', offset*sizeof(MYFLT)); memset(out2, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&out1[nsmps], '\0', early*sizeof(MYFLT)); memset(&out2[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nesr); while (UNLIKELY(x1 < 0.0)) x1 += (double)maxd; xpos = (int32)x1; x1 -= (double)xpos; x2 = sin (PI * x1) / PI; while (UNLIKELY(xpos >= maxd)) xpos -= maxd; if (x1 * (1.0 - x1) > 0.00000001) { n1 = (double)in1[n] * x2; n2 = (double)in2[n] * x2; xpos += (1 - i2); while (UNLIKELY(xpos < 0)) xpos += maxd; d = (double)(1 - i2) - x1; for (i = i2; i--;) { w = 1.0 - d*d*d2x; w *= (w / d++); buf1[xpos] += (MYFLT) (n1 * w); buf2[xpos] += (MYFLT) (n2 * w); if (UNLIKELY(++xpos >= maxd)) xpos -= maxd; w = 1.0 - d*d*d2x; w *= (w / d++); buf1[xpos] -= (MYFLT) (n1 * w); buf2[xpos] -= (MYFLT) (n2 * w); if (UNLIKELY(++xpos >= maxd)) xpos -= maxd; } } else { /* integer sample */ xpos = (int32)((double)xpos + x1 + 0.5); /* position */ if (UNLIKELY(xpos >= maxd)) xpos -= maxd; buf1[xpos] += in1[n]; buf2[xpos] += in2[n]; } out1[n] = buf1[indx]; buf1[indx] = FL(0.0); out2[n] = buf2[indx]; buf2[indx] = FL(0.0); if (UNLIKELY(++indx == maxd)) indx = 0; } p->left = indx; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("vdelay: not initialised")); } int vdelayxq(CSOUND *csound, VDELXQ *p) /* vdelayxq routine */ { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 maxd, indx; MYFLT *out1 = p->sr1; /* assign object data to local variables */ MYFLT *out2 = p->sr2; MYFLT *out3 = p->sr3; MYFLT *out4 = p->sr4; MYFLT *in1 = p->ain1; MYFLT *in2 = p->ain2; MYFLT *in3 = p->ain3; MYFLT *in4 = p->ain4; MYFLT *del = p->adel; MYFLT *buf1 = (MYFLT *)p->aux1.auxp; MYFLT *buf2 = (MYFLT *)p->aux2.auxp; MYFLT *buf3 = (MYFLT *)p->aux3.auxp; MYFLT *buf4 = (MYFLT *)p->aux4.auxp; int wsize = p->interp_size; double x1, x2, w, d, d2x, n1, n2, n3, n4; int32 i, i2, xpos; /* RWD fix */ if (UNLIKELY((buf1 == NULL) || (buf2 == NULL) || (buf3 == NULL) || (buf4 == NULL))) goto err1; maxd = p->maxd; if (UNLIKELY(maxd == 0)) maxd = 1; /* Degenerate case */ indx = p->left; i2 = (wsize >> 1); d2x = (1.0 - pow ((double)wsize * 0.85172, -0.89624)) / (double)(i2 * i2); if (UNLIKELY(offset)) { memset(out1, '\0', offset*sizeof(MYFLT)); memset(out2, '\0', offset*sizeof(MYFLT)); memset(out3, '\0', offset*sizeof(MYFLT)); memset(out4, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&out1[nsmps], '\0', early*sizeof(MYFLT)); memset(&out2[nsmps], '\0', early*sizeof(MYFLT)); memset(&out3[nsmps], '\0', early*sizeof(MYFLT)); memset(&out4[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nesr); while (UNLIKELY(x1 < 0.0)) x1 += (double)maxd; xpos = (int32)x1; x1 -= (double)xpos; x2 = sin (PI * x1) / PI; while (UNLIKELY(xpos >= maxd)) xpos -= maxd; if (LIKELY(x1 * (1.0 - x1) > 0.00000001)) { xpos += (1 - i2); while (UNLIKELY(xpos < 0)) xpos += maxd; d = (double)(1 - i2) - x1; for (i = i2; i--;) { w = 1.0 - d*d*d2x; w *= (w / d++); n1 += (double)buf1[xpos] * w; n2 += (double)buf2[xpos] * w; n3 += (double)buf3[xpos] * w; n4 += (double)buf4[xpos] * w; if (UNLIKELY(++xpos >= maxd)) xpos -= maxd; w = 1.0 - d*d*d2x; w *= (w / d++); n1 -= (double)buf1[xpos] * w; n2 -= (double)buf2[xpos] * w; n3 -= (double)buf3[xpos] * w; n4 -= (double)buf4[xpos] * w; if (UNLIKELY(++xpos >= maxd)) xpos -= maxd; } out1[n] = (MYFLT) (n1 * x2); out2[n] = (MYFLT) (n2 * x2); out3[n] = (MYFLT) (n3 * x2); out4[n] = (MYFLT) (n4 * x2); } else { /* integer sample */ xpos = (int32)((double)xpos + x1 + 0.5); /* position */ if (UNLIKELY(xpos >= maxd)) xpos -= maxd; out1[n] = buf1[xpos]; out2[n] = buf2[xpos]; out3[n] = buf3[xpos]; out4[n] = buf4[xpos]; } if (UNLIKELY(++indx == maxd)) indx = 0; } p->left = indx; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("vdelay: not initialised")); } int vdelayxwq(CSOUND *csound, VDELXQ *p) /* vdelayxwq routine */ { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 maxd, indx; MYFLT *out1 = p->sr1; /* assign object data to local variables */ MYFLT *out2 = p->sr2; MYFLT *out3 = p->sr3; MYFLT *out4 = p->sr4; MYFLT *in1 = p->ain1; MYFLT *in2 = p->ain2; MYFLT *in3 = p->ain3; MYFLT *in4 = p->ain4; MYFLT *del = p->adel; MYFLT *buf1 = (MYFLT *)p->aux1.auxp; MYFLT *buf2 = (MYFLT *)p->aux2.auxp; MYFLT *buf3 = (MYFLT *)p->aux3.auxp; MYFLT *buf4 = (MYFLT *)p->aux4.auxp; int wsize = p->interp_size; double x1, x2, w, d, d2x, n1, n2, n3, n4; int32 i, i2, xpos; /* RWD fix */ if (UNLIKELY((buf1 == NULL) || (buf2 == NULL) || (buf3 == NULL) || (buf4 == NULL))) goto err1; maxd = p->maxd; if (UNLIKELY(maxd == 0)) maxd = 1; /* Degenerate case */ indx = p->left; i2 = (wsize >> 1); d2x = (1.0 - pow ((double)wsize * 0.85172, -0.89624)) / (double)(i2 * i2); if (UNLIKELY(offset)) { memset(out1, '\0', offset*sizeof(MYFLT)); memset(out2, '\0', offset*sizeof(MYFLT)); memset(out3, '\0', offset*sizeof(MYFLT)); memset(out4, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&out1[nsmps], '\0', early*sizeof(MYFLT)); memset(&out2[nsmps], '\0', early*sizeof(MYFLT)); memset(&out3[nsmps], '\0', early*sizeof(MYFLT)); memset(&out4[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nesr); while (UNLIKELY(x1 < 0.0)) x1 += (double)maxd; xpos = (int32)x1; x1 -= (double)xpos; x2 = sin (PI * x1) / PI; while (UNLIKELY(xpos >= maxd)) xpos -= maxd; if (x1 * (1.0 - x1) > 0.00000001) { n1 = (double)in1[n] * x2; n2 = (double)in2[n] * x2; n3 = (double)in3[n] * x2; n4 = (double)in4[n] * x2; xpos += (1 - i2); while (UNLIKELY(xpos < 0)) xpos += maxd; d = (double)(1 - i2) - x1; for (i = i2; i--;) { w = 1.0 - d*d*d2x; w *= (w / d++); buf1[xpos] += (MYFLT) (n1 * w); buf2[xpos] += (MYFLT) (n2 * w); buf3[xpos] += (MYFLT) (n3 * w); buf4[xpos] += (MYFLT) (n4 * w); if (UNLIKELY(++xpos >= maxd)) xpos -= maxd; w = 1.0 - d*d*d2x; w *= (w / d++); buf1[xpos] -= (MYFLT) (n1 * w); buf2[xpos] -= (MYFLT) (n2 * w); buf3[xpos] -= (MYFLT) (n3 * w); buf4[xpos] -= (MYFLT) (n4 * w); if (UNLIKELY(++xpos >= maxd)) xpos -= maxd; } } else { /* integer sample */ xpos = (int32)((double)xpos + x1 + 0.5); /* position */ if (UNLIKELY(xpos >= maxd)) xpos -= maxd; buf1[xpos] += in1[n]; buf2[xpos] += in2[n]; buf3[xpos] += in3[n]; buf4[xpos] += in4[n]; } out1[n] = buf1[indx]; buf1[indx] = FL(0.0); out2[n] = buf2[indx]; buf2[indx] = FL(0.0); out3[n] = buf3[indx]; buf3[indx] = FL(0.0); out4[n] = buf4[indx]; buf4[indx] = FL(0.0); if (UNLIKELY(++indx == maxd)) indx = 0; } p->left = indx; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("vdelay: not initialised")); } int multitap_set(CSOUND *csound, MDEL *p) { uint32_t n, i; MYFLT max = FL(0.0); //if (UNLIKELY(p->INOCOUNT/2 == (MYFLT)p->INOCOUNT*FL(0.5))) /* Should this test just be p->INOCOUNT&1 == */ if (UNLIKELY((p->INOCOUNT&1)==0)) return csound->InitError(csound, Str("Wrong input count in multitap\n")); for (i = 0; i < p->INOCOUNT - 1; i += 2) { if (max < *p->ndel[i]) max = *p->ndel[i]; } n = (uint32_t)(csound->esr * max * sizeof(MYFLT)); if (p->aux.auxp == NULL || /* allocate space for delay buffer */ n > p->aux.size) csound->AuxAlloc(csound, n, &p->aux); else { memset(p->aux.auxp, 0, n); } p->left = 0; p->max = (int32)(csound->esr * max); return OK; } int multitap_play(CSOUND *csound, MDEL *p) { /* assign object data to local variables */ int indx = p->left, delay; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, n, nsmps = CS_KSMPS; MYFLT *out = p->sr, *in = p->ain; MYFLT *buf = (MYFLT *)p->aux.auxp; MYFLT max = (MYFLT)p->max; if (UNLIKELY(buf==NULL)) goto err1; /* RWD fix */ if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nINOCOUNT - 1; i += 2) { delay = indx - (int32)(csound->esr * *p->ndel[i]); if (UNLIKELY(delay < 0)) delay += (int32)max; v += buf[delay] * *p->ndel[i+1]; /* Write output */ } out[n] = v; } p->left = indx; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("multitap: not initialised")); } /* nreverb coded by Paris Smaragdis 1994 and Richard Karpen 1998 */ #define LOG001 (-6.9077552789821370521) /* log(.001) */ static const int smallprime[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571}; static int prime(int val) { int i, last; if (val < 3572) { for (i = 0; smallprime[i] < val; i++) ; return (smallprime[i] == val ? 1 : 0); } last = (int) sqrt((double)val); for (i = 0; smallprime[i] < (last < 3572 ? last : 3572); i++) { if (UNLIKELY((val % smallprime[i]) == 0)) return 0; } for (i = 3573; i <= last; i += 2) { if (UNLIKELY((val % i) == 0)) return 0; } return 1; } /* * Based on nreverb coded by Paris Smaragdis 1994 and Richard Karpen 1998. * Changes made to allow user-defined comb and alpas constant in a ftable. * Sept 2000, by rasmus ekman. * Memory allocation fixed April 2001 by JPff * */ /* The original reverb2 constants were in samples at sample rate 25641.0 * (suggestedly being "probably CCRMA 'samson box' sampling-rate"). * Used to be defined in single-purpose header revsets.h. * Get rid of this right here so we can use them as times in the code. */ #define orgCombs 6 #define orgAlpas 5 static const MYFLT cc_time[orgCombs] = { FL(0.055887056) /* 1433.0 / 25641.0 */, FL(0.062439062) /* 1601.0 / 25641.0 */, FL(0.072813073) /* 1867.0 / 25641.0 */, FL(0.080067080) /* 2053.0 / 25641.0 */, FL(0.087789088) /* 2251.0 / 25641.0 */, FL(0.093561094) /* 2399.0 / 25641.0 */ }; static const MYFLT cc_gain[orgCombs] = { FL(0.822), FL(0.802), FL(0.773), FL(0.753), FL(0.753), FL(0.753) }; static const MYFLT ca_time[orgAlpas] = { FL(0.013533014) /* 347.0 / 25641.0 */, FL(0.0044070044) /* 113.0 / 25641.0 */, FL(0.0014430014) /* 37.0 / 25641.0 */, FL(0.0023010023) /* 59.0 / 25641.0 */, FL(0.0016770017) /* 43.0 / 25641.0 */ }; static const MYFLT ca_gain[orgAlpas] = { FL(0.7), FL(0.7), FL(0.7), FL(0.7), FL(0.7) }; int reverbx_set(CSOUND *csound, NREV2 *p) { int32 i, n; /* Temp holder of old or user constants. */ const MYFLT *c_orgtime, *a_orgtime; int c_time, a_time; int cmbAllocSize, alpAllocSize; if (UNLIKELY(*p->hdif > FL(1.0) || *p->hdif < FL(0.0))) return csound->InitError(csound, Str("High frequency diffusion not in (0, 1)\n")); /* Init comb constants and allocate dynamised work space */ if (*p->inumCombs < FL(1.0)) { /* Using old defaults */ /* Get nreverb defaults */ p->numCombs = orgCombs; c_orgtime = cc_time; p->c_orggains = cc_gain; } else { /* User provided constants */ FUNC *ftCombs; p->numCombs = (int) *p->inumCombs; /* Get user-defined set of comb constants from table */ if (UNLIKELY((ftCombs = csound->FTnp2Find(csound, p->ifnCombs)) == NULL)) return NOTOK; if (UNLIKELY(ftCombs->flen < (uint32_t)p->numCombs * 2)) { return csound->InitError(csound, Str("reverbx; Combs ftable must have " "%d time and %d gain values"), p->numCombs, p->numCombs); } c_orgtime = ftCombs->ftable; p->c_orggains = (ftCombs->ftable + p->numCombs); } /* Alloc a single block and get arrays of comb pointers from that */ cmbAllocSize = p->numCombs * sizeof(MYFLT); csound->AuxAlloc(csound, 4 * cmbAllocSize + 2 * (p->numCombs + 1) * sizeof(MYFLT*), &p->caux2); p->c_time = (MYFLT*) p->caux2.auxp; p->c_gain = (MYFLT*) ((char*) p->caux2.auxp + 1 * cmbAllocSize); p->z = (MYFLT*) ((char*) p->caux2.auxp + 2 * cmbAllocSize); p->g = (MYFLT*) ((char*) p->caux2.auxp + 3 * cmbAllocSize); p->cbuf_cur = (MYFLT**) ((char*) p->caux2.auxp + 4 * cmbAllocSize); p->pcbuf_cur = p->cbuf_cur + (p->numCombs + 1); /* ...and allpass constants and allocs */ if (*p->inumAlpas < FL(1.0)) { /* Get nreverb defaults */ p->numAlpas = orgAlpas; a_orgtime = ca_time; p->a_orggains = ca_gain; } else { /* Have user-defined set of alpas constants */ FUNC *ftAlpas; p->numAlpas = (int) *p->inumAlpas; if (UNLIKELY((ftAlpas = csound->FTnp2Find(csound, p->ifnAlpas)) == NULL)) return NOTOK; if (UNLIKELY(ftAlpas->flen < (unsigned int)p->numAlpas * 2)) { return csound->InitError(csound, Str("reverbx; Alpas ftable must have" " %d time and %d gain values"), p->numAlpas, p->numAlpas); } a_orgtime = ftAlpas->ftable; p->a_orggains = (ftAlpas->ftable + p->numAlpas); } /* Dynamic alloc of alpass space */ alpAllocSize = p->numAlpas * sizeof(MYFLT); csound->AuxAlloc(csound, 2 * alpAllocSize + 2 * (p->numAlpas + 1) * sizeof(MYFLT*), &p->aaux2); p->a_time = (MYFLT*) p->aaux2.auxp; p->a_gain = (MYFLT*) ((char*) p->aaux2.auxp + 1 * alpAllocSize); p->abuf_cur = (MYFLT**) ((char*) p->aaux2.auxp + 2 * alpAllocSize); p->pabuf_cur = (MYFLT**) ((char*) p->aaux2.auxp + 2 * alpAllocSize + (p->numAlpas + 1) * sizeof(MYFLT*)); /* Init variables */ if (*p->istor == FL(0.0) || p->temp.auxp == NULL || p->temp.sizeAuxAlloc(csound, CS_KSMPS * sizeof(MYFLT), &p->temp); n = 0; for (i = 0; i < p->numCombs; i++) { MYFLT ftime = c_orgtime[i]; /* Use directly as num samples if negative */ if (ftime < FL(0.0)) c_time = (int) -ftime; else { /* convert from to seconds to samples, and make prime */ c_time = (int) (ftime * csound->esr); /* Mangle sample number to primes. */ if (c_time % 2 == 0) c_time += 1; while (!prime(c_time)) c_time += 2; } p->c_time[i] = (MYFLT) c_time; n += c_time; p->c_gain[i] = (MYFLT) exp((double)(LOG001 * (p->c_time[i] * csound->onedsr) / (p->c_orggains[i] * *p->time))); p->g[i] = *p->hdif; p->c_gain[i] = p->c_gain[i] * (FL(1.0) - p->g[i]); p->z[i] = FL(0.0); } csound->AuxAlloc(csound, n * sizeof(MYFLT), &p->caux); /* unnecessary as Auxlloc clears to 0 */ /* for (i = 0; i < n; i++) { */ /* ((MYFLT*) p->caux.auxp)[i] = FL(0.0); */ /* } */ p->pcbuf_cur[0] = p->cbuf_cur[0] = (MYFLT*)p->caux.auxp; for (i = 0; i < p->numCombs; i++) { p->pcbuf_cur[i + 1] = p->cbuf_cur[i + 1] = p->cbuf_cur[i] + (int) p->c_time[i]; p->c_time[i] *= csound->onedsr; /* Scale to save division in reverbx */ } n = 0; for (i = 0; i < p->numAlpas; i++) { MYFLT ftime = a_orgtime[i]; if (ftime < FL(0.0)) a_time = (int) -ftime; else { /* convert seconds to samples and make prime */ a_time = (int) (ftime * csound->esr); if (a_time % 2 == 0) a_time += 1; while (!prime(a_time)) a_time += 2; } p->a_time[i] = (MYFLT) a_time; p->a_gain[i] = (MYFLT) exp((double)(LOG001 * (p->a_time[i] * csound->onedsr) / (p->a_orggains[i] * *p->time))); n += a_time; } csound->AuxAlloc(csound, n * sizeof(MYFLT), &p->aaux); /* unnecessary as AuxAlloc clears */ /* for (i = 0; i < n; i++) { */ /* ((MYFLT*) p->aaux.auxp)[i] = FL(0.0); */ /* } */ p->pabuf_cur[0] = p->abuf_cur[0] = (MYFLT*) p->aaux.auxp; for (i = 0; i < p->numAlpas; i++) { p->pabuf_cur[i + 1] = p->abuf_cur[i + 1] = p->abuf_cur[i] + (int) p->a_time[i]; p->a_time[i] *= csound->onedsr; /* Scale to save division in reverbx */ } } p->prev_time = *p->time; p->prev_hdif = *p->hdif; return OK; } int reverbx(CSOUND *csound, NREV2 *p) { int32 i; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *in, *out = p->out, *buf, *end; MYFLT gain, z; MYFLT hdif = *p->hdif; MYFLT time = *p->time; int numCombs = p->numCombs; int numAlpas = p->numAlpas; if (UNLIKELY(p->temp.auxp == NULL)) goto err1; buf = (MYFLT*) p->temp.auxp; in = p->in; memcpy(buf, in, nsmps*sizeof(MYFLT)); memset(out, 0, nsmps*sizeof(MYFLT)); if (UNLIKELY(early)) nsmps -= early; if (*p->time != p->prev_time || *p->hdif != p->prev_hdif) { if (UNLIKELY(hdif > FL(1.0))) { csound->Warning(csound, Str("High frequency diffusion>1\n")); hdif = FL(1.0); } if (UNLIKELY(hdif < FL(0.0))) { csound->Warning(csound, Str("High frequency diffusion<0\n")); hdif = FL(0.0); } if (UNLIKELY(time <= FL(0.0))) { csound->Warning(csound, Str("Non positive reverb time\n")); time = FL(0.001); } for (i = 0; i < numCombs; i++) { p->c_gain[i] = EXP((LOG001 * p->c_time[i] / (p->c_orggains[i] * time))); p->g[i] = hdif; p->c_gain[i] = p->c_gain[i] * (FL(1.0) - p->g[i]); p->z[i] = FL(0.0); } for (i = 0; i < numAlpas; i++) p->a_gain[i] = EXP((LOG001 * p->a_time[i] / (p->a_orggains[i] * time))); p->prev_time = time; p->prev_hdif = hdif; } for (i = 0; i < numCombs; i++) { buf = p->pcbuf_cur[i]; end = p->cbuf_cur[i + 1]; gain = p->c_gain[i]; in = (MYFLT*) p->temp.auxp; out = p->out; for (n=offset;nz[i] * p->g[i]; p->z[i] = *buf; *buf *= gain; *buf += in[n]; if (UNLIKELY(++buf >= end)) buf = (MYFLT*) p->cbuf_cur[i]; } p->pcbuf_cur[i] = buf; } for (i = 0; i < numAlpas; i++) { in = (MYFLT*) p->temp.auxp; out = p->out; memcpy(in+offset, out+offset, (nsmps-offset)*sizeof(MYFLT)); buf = p->pabuf_cur[i]; end = p->abuf_cur[i + 1]; gain = p->a_gain[i]; for (n=offset;n= end)) buf = (MYFLT*) p->abuf_cur[i]; } p->pabuf_cur[i] = buf; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("reverbx: not initialised")); } csound-6.10.0/OSX/000077500000000000000000000000001321653344700135525ustar00rootroot00000000000000csound-6.10.0/OSX/.gitignore000066400000000000000000000000271321653344700155410ustar00rootroot00000000000000*DS_Store csound-OSX-* csound-6.10.0/OSX/CHANGELOG000066400000000000000000013567461321653344700150120ustar00rootroot000000000000002012-02-09 john ffitch * Opcodes/ugsc.c (hilbertset): Remove unnecessary arrays 2012-02-06 john ffitch * H/version.h: VERSION 5.16.1 2011-11-30 john ffitch * Opcodes/pitch.c (impulse): If next is negative time, make it absolute value 2011-10-28 john ffitch * Opcodes/socksend.c (send_send, send_sendS): Added optional format message as INT16_LE and remove MTFU check 2011-10-14 John ff * Opcodes/tabvars.c (ftab2tab): (tab2ftab): New opcodes 2011-10-12 John ff * VERSION 5.14 2011-06-21 john ffitch * Opcodes/wiimote.c (wii_data_init): Return value missing (wii_data_inits): Ditto 2011-05-25 John ff * Engine/fgens.c (nextval): Ensure c moves on if not a number 2011-05-19 john ffitch * OOps/cmath.c (exprndiset, kexprndi, aexprndi): New code for exprandi opcode; also cauchyi 2011-05-05 john ffitch * SConstruct (optionsFilename): Try to check that the custom.py exists 2011-04-10 john ffitch * OOps/aops.c (is_NaN, is_NaNa): New function (is_inf, is_infa): New function 2011-03-17 john ffitch * Engine/csound_orc_expressions.c (csound_orc_expand_expressions): Generate kgoto rather than goto. Not totally sure this is right yet 2011-02-09 john ffitch * util1/csd_util/makecsd.c (main): new options for MIDI files and score processing; licence control as well * util1/csd_util/base64.c (encode_file): Added extra arg to select tags 2011-01-20 john ffitch * Opcodes/mp3in.c (mp3len): New code * SConstruct: Add building of fareyseq/fareygen which got lost 2011-01-17 john ffitch * H/version.h: VERSION 5.13 2011-01-13 john ffitch * OOps/ugens2.c (ko1set): ensure that the increment cannot be zero 2011-01-10 john ffitch * Engine/fgens.c (gen49): Use csound->FileOpen2 rather than open to get searching (gen49): buffer used was in wrong units (chars v shorts) 2010-12-28 john ffitch * Engine/symbtab.c (add_token): remove message if Opcode/Function confusion 2010-12-18 john ffitch * Opcodes/gab/tabmorph.c (atabmorphia): Fixed editing error that would have caused opcode to scribble over memory 2010-12-17 John ff * Opcodes/gab/vectorial.c: Lots of optimisations and corrections 2010-12-10 john ffitch * Opcodes/gab/gab.c (isChanged_set): Initialise p->old_inargs 2010-12-05 john ffitch * H/aops.h (struct INCH): Rewritten * OOps/aops.c (inch_opcode): Rewritten * Engine/entry1.c: Allow multiple args in inch * Engine/csound_orc.l (do_at): New code to support @ and @@ operators 2010-11-28 john ffitch * Engine/symbtab.c: Added cent as function 2010-11-27 john ffitch * OOps/ugens3.c (adsyn): check that ktogo is never zero 2010-11-16 John ff * Top/main.c (csoundCompile): and call macro inits * Engine/csound_orc.l: Add standard macro initialisation code to lexer 2010-11-12 John ff * Engine/csound_orc_semantics.c (handle_polymorphic_opcode): Calculating c before switch can lead to following a null pointer. Moved calculation to where it is needed. 2010-11-05 John ff * OOps/ugens4.c (riset, rndset, rhset): Use Warning rather than Message 2010-11-04 John ff * Opcodes/pvsbasic.c (MAXOUTS): Extend upto 16 outputs (localops): Use F format in pvstanal 2010-10-12 john ffitch * Engine/csound_orc.y: Allow labels in exprlists 2010-10-08 John ff * OOps/cmath.c (ipow, apow): If normalisation is zero make it 1; Needed in new parser as optional arg not handled * csound_orc.l: Many changes in macros and stack of inputs 2010-09-23 john ffitch * Opcodes/fout.c (sprints): Attempt to fix %%->% problem 2010-09-18 john ffitch * Engine/csound_orc_expressions.c (create_expression): Unary minus should use i rate if it can 2010-09-17 john ffitch * SConstruct: * Top/csound.c: Make new parser default 2010-09-02 Michael Gogins * Corrected signature of fluidAllOut opcode, and fencepost error in that opcode. * Fixed order of processing in CsoundVST audio output callbacks. 2010-09-02 Michael Gogins * Migrated Windows compiler to MinGW GCC 4.4.0 from Qt for all third party and Csound executables. This compiler generates dw2 exception handling code. * Fixed up examples to execute in their own directories. * Changed csoundSetMessageCallback to reset the callback to csoundDefaultMessageCallback if the user sets the callback to null, in order to prevent segment faults. 2010-09-01 john ffitch * Opcodes/gab/gab.c (adsynt2): Phase not handled correctly 2010-08-31 john ffitch * Engine/csound_orc_expressions.c: Many changes to make if_then etc work 2010-08-28 Michael Gogins * Replaced csound-build.tex with How_to_Build_Csound_on_Windows.doc, in Microsoft Word format, which should be more accessible to users. * Changed multi-threading in the head branch to use OpenMP instead of PThreads, for greater clarity and maintainability. 2010-08-26 john ffitch * Engine/csound_orc_expressions.c (create_cond_expression): New code to deal with (a?b:c) variant (is_expression_node): Added S_Q to expression operators (create_expression): Call create_cond_expression 2010-08-25 John ff * Engine/insert.c (insert): In pset case no not zero excess opcodes 2010-08-10 Michael Gogins * Engine/typetabl.h: Supplied missing type mask for 'J' type code, i.e. k-rate scalar defaulting to -1, used in "STK" opcodes and others. * Opcodes/stk/STKOpcodes.cpp: Changed threading from 5 to 3, changed MIDI controller number and value parameters to 'J' type. * Updated environment, build, and installer scripts for new Windows version built on new Core i7, Windows 7 computer. 2010-08-09 john ffitch * InOut/libsnd.c (sfopenin): Correct warning message * Top/csound.c ("C"): Default value of inchnls is now -1 * Engine/otran.c (oload): Set inchnls to nchnls if not explicit 2010-08-03 john ffitch * Engine/csound_orc.y (ifac): Typo -- used S_MOD rather than S_DIV 2010-08-01 john ffitch * Top/csound.c (csoundAddSpinSample): Needs to use nchnls_i 2010-07-31 john ffitch * Engine/csound_orc_semantics.c (handle_optional_args): * Engine/rdorch.c (getoptxt): Added J arg type 2010-07-28 John ff * Opcodes/urandom.c (urand_run, urand_init, urand_deinit): New code (LINUX ONLY) 2010-07-27 john ffitch * Top/csmodule.c (csoundCheckOpcodeDeny): Complete function vis CS_OMIT_LIBS environment 2010-07-26 john ffitch * Top/csmodule.c (csoundCheckOpcodeDeny): New function (INCOMPLETE) (csoundLoadModules): Check to see if library denied 2010-07-20 john ffitch * Engine/sort.c (ordering): Fixed stupidity of using int where MYFLT was needed * Opcodes/grain.c (ags): Added check that kglen is strictly positive 2010-07-19 john ffitch * Engine/sort.c (ordering): take account of negative p3 2010-07-14 john ffitch * Opcodes/mp3in.c (mp3in): Deal with case of end of data 2010-07-13 john ffitch * Engine/fgens.c (gen23): Typo in check for extra numbers removed 2010-07-08 john ffitch * OOps/sndinfUG.c (filevalid): * Engine/entry1.c: * H/entry1.h: Added filevalid opcode * H/sndinfUG.h (struct): Added FILEVALID structure 2010-07-04 john ffitch * Engine/musmon.c (process_midi_event): * Engine/insert.c (insert, MIDIinsert, insert_event): * Engine/auxfd.c (auxchprint): Print name of instrument if available (fdchprint): ditto 2010-07-03 john ffitch * Engine/sort.c (ordering): Rewrote to make clearer and complete * H/sort.h (srtblk): Changed order of fields to avoid overwrite * Engine/extract.c: Added lineo field to dummy events 2010-06-28 john ffitch * Opcodes/pitch0.c (maxalloc, cpuperc, instcount) Allow named instruments 2010-06-24 john ffitch * Engine/sort.c (ordering): Added ordering on line number if all else fails * H/csoundCore.h (EVTBLK): Added array of chars for strings 2010-05-26 john ffitch * Opcodes/ftgen.c (ftgen): Need to deal with fp[5] in named gen case 2010-05-23 john ffitch * Engine/fgens.c (hfgens): Check was against GENMAX rather than csound->genmax * Opcodes/ftgen.c (ftgen): Allow for named GENs * Top/csound.c (csoundGetNamedGens): New API function * Opcodes/fareyseq.c (tableshuffle): New code for two opcodes 2010-05-16 john ffitch * Opcodes/pitch.c (medfiltset): (medfilt): New code 2010-05-10 john ffitch * Opcodes/fareygen.c: * Opcodes/fareyseq.c: New code * SConstruct: Added farey sequence GEN and opcodes 2010-05-09 john ffitch * install.py: Added atsa to binaries 2010-05-03 john ffitch * OOps/ugens6.c (delay1): use memmove rather than a loop 2010-04-25 john ffitch * Opcodes/uggab.c (lineto): Some changes -- seems better * OOps/ugens3.c (adsyn): Sorted out confusion over int32 and MYFLT * OOps/ugens5.c (atonex): Fix bug; it was repeating the filter to the input rather than cascading (resonx): (tonex): Same error as atonex * Opcodes/gab/gab.c (adsynt2_set): Brought into line with adsynt_set, and revised (adsynt2_set): Initialisation of amp and frequency table was totally wrong 2010-04-10 john ffitch * Engine/fgens.c (gen41): Added check for positive probability 2010-04-05 john ffitch * Opcodes/sndwarp.c (sndwarp): The attempt to give only one warning message was wrong. Think OK now?? 2010-03-24 john ffitch * Top/main.c (csoundCompile): Removed spurious BETA check 2010-03-23 jpff * Engine/sread.c (sget1): Remove repeats free 2010-03-22 john ffitch * Engine/fgens.c (gen28): Typo -- freed x rather than y 2010-03-16 john ffitch * Engine/sort.c: Code replaced with smoothsort code 2010-03-13 john ffitch * Engine/smoothsort.c (sort): Deal with case of no e event 2010-03-12 jpff * SConstruct: Added smoothSort option to control building * Engine/smoothsort.c: New drop-in replacement for sort.c using a fancier sort algorithm 2010-02-28 john ffitch * OOps/ugrw1.c (sprints): A format with a % but no arg would cause a crash 2010-02-25 john ffitch * Opcodes/gab/gab.c: Added range checks to the fast table opcodes 2010-02-21 john ffitch * OOps/aops.c (aassign): Correct typo in arguments * Engine/rdorch.c (splitline): Rework \ inside strings 2010-02-15 jpff * Engine/typetabl.h (]): Need to add p to I case * Engine/rdorch.c (rdorchfile): Do not increment lincnt in line continuation mode 2010-02-13 john ffitch * OOps/aops.c (minit): Ensure a,b=b,a works 2010-02-12 john ffitch * OOps/aops.c (minit, mainit): new code for multiple init * Engine/entry1.c: Changed init to multiple version 2010-01-24 john ffitch * Engine/sread.c (init_smacros): Define INF macro in scores as well (getscochar): Read 'z' as infinity * Engine/rdorch.c (init_math_constants_macros): Added INF macro for infinity in orchestra 2010-01-17 john ffitch * VERSION 5.12 a2010-01-16 john ffitch * Engine/otran.c (oload): Need to check the first 6 variables, up from 5 due to input channel code 2010-01-11 john ffitch * Engine/fgens.c (gen28, gen31, gen32, gen33, gen34): Used malloc/free for local memory * InOut/widgets.cpp (fl_callbackExecButton): Freed memory allocated in Windows case 2010-01-08 mantaraya36 * Engine/insert.c: Allow turning off non-indefinite instruments from negative score events. By John ffitch. 2010-01-08 john ffitch * Engine/musmon.c (musmon): Corrected csound->inchnls to csound->nchnls * Engine/csound_orc.y (param): Alter precedence of ? operator 2010-01-06 jpff * Opcodes/fout.c (fprintf_set): Set line buffering 2010-01-02 john ffitch * Opcodes/uggab.c (loopxseg): Fixed bug on shape 2009-12-28 john ffitch * Engine/linevent.c (sensLine): * Engine/musmon.c (insert_score_event_at_sample): Allow too few arguments in f -x case 2009-12-27 john ffitch * Opcodes/uggab.c (loopxseg): New code for loopxseg opcode 2009-12-26 john ffitch * Opcodes/uggab.c (nterpol_init): Check to stop division by zero 2009-12-25 john ffitch for Francois Pinot * Opcodes/crossfm.h: * Opcodes/crossfm.c: New code 2009-12-23 john ffitch * Opcodes/sfont.c: Set pitches on module creation rather than on every load. 2009-12-22 john ffitch * Opcodes/sfont.c (SfLoad): Added check to see if too many sound fonts are loaded. * Opcodes/pitch.c (trnsetr, trnset): Check argument count is 1mod3 2009-12-20 john ffitch * Engine/csound_orc_semantics.c (handle_optional_args): If there are no arguments yet we still need to add optionals 2009-12-13 john ffitch * Opcodes/nlfilt.c (pinit): New code to implement passign opcode 2009-12-11 john ffitch * Engine/rdorch.c (splitline): Allow \" in strings * Top/one_file.c (readOptions): Reset linecount after reading .csoundrc 2009-11-29 john ffitch * Opcodes/cross2.c (getmag): If magnitude is zero do not scale! 2009-11-28 john ffitch * Opcodes/pitch.c (clockon, clockoff): Reading the clock should be incremental. (correcting bug introduced by Istvan) 2009-11-24 jpff * Engine/musmon.c (gettempo): Fixed stupid error 2009-11-09 john ffitch * Opcodes/pan2.c (pan2run): Fixed editing error in type 3 (thanks to Sigurd Saue) 2009-11-03 john ffitch * Opcodes/p5glove.c (p5glove_find): Use thread to read the USB glove. 2009-10-16 jpff * Opcodes/pvsbasic.c (pvsshiftset): Change MYFLT to float in memset 2009-10-02 jpff * Opcodes/pitch.c (trnsetr, ktrnsegr, trnsegr): New code * Opcodes/spectra.c: declare transegr 2009-09-22 jpff * H/version.h: VERSION 5.11.1 * Opcodes/bilbar.c (bar_run): Fix typo in right end type 1 (bar_run): Loop needs to be one more for right end 2009-09-14 jpff * Engine/fgens.c (gen32): And allow extended here as well, via aux function 2009-09-10 jpff * Engine/fgens.c (gen52, gen51): Added extended arg support 2009-08-27 jpff * H/csoundCore.h (PMAX): Reduced by 2 (EVTBLK): Added c.extra field to EVTBLK * Engine/fgens.c: LOTS of changes to allow extension of arguments uses. * Engine/sread.c (ifa): removed limit of PMAX arguments to events * Engine/rdscor.c (rdscor): Allow reading of more than PMAX fields * Engine/fgens.c (gen23): Total rewrite 2009-08-19 jpff * Engine/fgens.c (hfgens): Correct error string to 1, 23 or 28 for deferred size. 2009-08-12 jpff * Engine/fgens.c (hfgens): Do not extend table of ftables unnecessarily; it used to always extend even if spare slots existed. 2009-08-10 jpff * Opcodes/tabsum.c (tabsum): Fixed silly error that made it all wrong. 2009-07-25 Michael Gogins * The Windows installer now provides the user with options for core, custom, or complete installation. Custom options include independent installation of C/C++, Lua, Python, Java, and Lisp interfaces; independent installation of csnd and CsoundAC; and independent installation of front ends and various other options. 2009-07-21 * OOps/cmath.c (seedrand): if positive would still seed from time 2009-07-20 jpff * OOps/ugrw1.c (printsset): Set string[0] to null as otherwise sprints does wrong thing on empty string 2009-07-18 Michael Gogins * SConstruct now builds completely independent shared libraries for Python, Lua, and Java wrappers. * Reorganized examples directory to put all examples for C, C++, Python, Lua, Java, and Lisp wrappers in separate subdirectories. Opcode demos also go into a separate subdirectory. The root examples directory should now contain only complete pieces or tutorial pieces. 2009-07-05 jpff * Opcodes/spectra.c (mute opcode): Should be type T to accept string or number. * SConstruct (cf): Check that libintl.h exists in the GETTEXT version 2009-06-10 jpff * Engine/csound_orc.l: Corrected continuation line pattern 2009-06-05 jpff * Engine/csound_orc.y (ident): Added unary + * H/version.h: Marked as 5.10.90 and 5.11rc1 2009-06-04 jpff * Engine/csound_orc_expressions.c (create_goto_token) (get_boolean_arg, create_boolean_expression) (create_synthetic_ident, csound_orc_expand_expressions): Create and use Boolean variables with either k or i type as required 2009-05-05 jpff * Engine/csound_orc.l: Deal with \+NL 2009-05-01 jpff * Engine/csound_orc.y (if, ifthen, elsif): Removed requirement for brackets round condition. 2009-04-30 jpff * Engine/csound_orc.y: Remove two globals to the CSOUND structure and start numbered instruments. 2009-04-29 Victor Lazzarini * InOut/FL_graph.cpp: fixed the redrawing of graphs so that only selected ones get redrawn. 2009-04-28 jpff * H/csoundCore.h ("C"): Declare * Top/csound.c ("C"): Initialise floatsize * Engine/musmon.c (musmon): Set csound->floatsize 2009-04-27 Victor Lazzarini * Opcodes/pvsbasic.c: added rounding bin code to pvsscale * Opcodes/ftgen.c: added NP2 support for ftload and ftsave * Engine/fgen.c: moved a PerfError to a Warning when tables are resized to enable ftload to resize deferred-allocation tables. * OOps/ugens5.c: experimental LPC read opcode * H/ugens.h: as above * Engine/oentry1.c: as above 2009-04-24 Anthony Kozar * SConstruct: Define WORDS_BIGENDIAN for hrtfnew opcodes when appropriate. * H/prototyp.h: * H/csoundCore.h: * Top/csound.c: * Engine/memfiles.c: New API function pointer ldmemfile2withCB() which is a version of ldmemfile() allowing a callback to be set and called exactly once to process the MEMFIL buffer after it is loaded. * H/version.h: Increased API version to 2.1. * Engine/memfiles.c (Load_File_): * Opcodes/hrtfopcodes.c: Moved byteswapping code for HRTF opcodes to hrtfnew module utilizing ldmemfile2withCB(). * H/csound.h: Removed file type CSFTYPE_FLOATS_BINARY_SW 2009-04-19 jpff * Opcodes/p5glove.c: New code to controlP5 Glove directly * Engine/csound_orc_semantics.c (handle_polymorphic_opcode): Added polymorphic type 0xfffd 2009-04-17 jpff * Engine/memfiles.c (Load_File_): Add option for byteswap from LITTLE- to BIG-ENDIAN if necessary (CSFTYPE_FLOATS_BINARY_SW) * H/csound.h: New file type CSFTYPE_FLOATS_BINARY_SW 2009-04-08 Michael Gogins * Opcodes/mixer.cpp: Added MixerSetLevel_i, an init-time only version of MixerSetLevel, so that it is possible to set the levels of mixer sends in the orchestra header. 2009-03-30 jpff * OOps/diskin.c (diskin_read_buffer): Typo corrected 2009-03-24 Michael Gogins * frontends/CsoundAC/Score.cpp: * interfaces/CsoundFile.cpp: Implemented importation of MusicXML v2 files into the CsoundAC Score class and the csnd CsoundFile class, using the Grame MusicXML library. 2009-03-22 jpff * OOps/oscils.c (tablexkt): Line adding to ar removed as wrong 2009-03-18 Anthony Kozar * SConstruct: * Opcodes/syncgrain.c: Added config test for values.h. * frontends/cscore/cscoremain.c: * frontends/cscore/cscoremain_MacOS9.c: * util1/scot/scot_main.c: Changed Scot and Cscore to take an optional second commandline argument specifying the output file. 2009-03-16 jpff * InOut/rtalsa.c (set_device_params): Change to snd_pcm_hw_params_set_rate_near rather than exact samplerate from "Pete G." 2009-03-15 jpff * Top/one_file.c (createExScore): Added new facility to have score generated by external code (read_unified_file): and call it 2009-03-14 jpff * util/lpc_export.c (lpc_export): Fix from Martin Rocamora on line 83 * util/lpcx_main.c (main): Fix from Martin Rocamora on line 82 2009-03-04 jpff * Opcodes/wiimote.c: New code (still experimental) to use wiimote in Csound (Linux only at present) 2009-03-01 jpff * Opcodes/mp3in.c: New code to read MP3 files (still experimental) 2009-02-28 Anthony Kozar * H/ugens5.h: * OOps/ugens5.c (lprdset, lpread): Fixed bad assumptions in doubles build when skipping over the LPC file header. 2009-02-23 jpff * Engine/fgens.c (gen49): New gen to read MP3 files using mpadec library 2009-02-07 jpff * Engine/rdorch.c (rdorchfile): * Engine/sread.c (sget1): Mane mname grow rather than being fixed size 2009-02-06 jpff * H/csoundCore.h ("C"): Added GetChannelLock to API * OOps/bus.c (csoundGetChannelLock): New function, deployed as well all over this file * H/csound.h ("C"): Added csoundGetChannelLock 2008-12-19 jpff * H/version.h: VERSION 5.10.1 2008-12-18 jpff * Opcodes/pitch.c (hsboscset): Bug whereby two internal variables may be unititialised fixed. 2008-12-17 Anthony Kozar * SConstruct: Add libintl on OS X when useGettext=1. Commented out -fno-rtti option on OS X. Revised Python detection logic so that it works on multiple versions of OS X. 2008-12-15 jpff * H/version.h (CS_APIVERSION): Upped version to 2/0 * H/csoundCore.h: Cleaned up unused fields in struct CSOUND_ and added some expansions. Tidied timing counters as well. Involved a number of small changes elsewhere 2008-12-04 mantaraya36 * Opcodes/pmidi.c : Added option to listen on all MIDI ports using 'a' instead of a device number. 2008-12-04 jpff * Opcodes/midiops3.c (islider32bit14): I think it should have 32 as arg to ISLIDER14 2008-12-02 jpff * Engine/insert.c: * Engine/linevent.c: * Engine/musmon.c: * Engine/otran.c: * H/csoundCore.h: * H/prototyp.h: * InOut/libsnd.c: * InOut/midisend.c: * OOps/schedule.c: * OOps/ugrw1.c: * Opcodes/OSC.c: * Top/csound.c: Change curTime to integer and work in samples rather than seconds. Same for beatTime 2008-11-30 jpff * Engine/fgens.c (csoundFTAlloc): Make size change with active instruments a PerfError 2008-11-21 jpff * Opcodes/filter.c (izfilter): Loop went 1 too many for coeffs->dcoeffs 2008-11-01 jpff * Opcodes/pitch.c (pitchamdf): Arrange that if peri is zero not to return NaN or Inf values. Suggests some algorithmic error (pitchamdfset): Initialise rmsmedian buffer -- it was undefined. No idea how it ever could work. 2008-10-31 jpff * Engine/otran.c (otran): Experimentally set locale to C numeric before parsing orchestra. 2008-10-27 jpff * OOps/aops.c (outo): Channel 6 was wrong, (outh): also here. 2008-10-18 jpff * InOut/rtwinmm.c (open_device): Dither only if requested. * H/csoundCore.h ("C"): Move dither to visible. * InOut/rtpa.c (set_device_params): Dither only if requested. (paBlockingReadWriteOpen): Ditto. * InOut/rtalsa.c (set_format): Dither only if requested. (MYFLT_to_short_no_dither): New function. 2008-10-09 Victor Lazzarini * Engine/fgens.c: added an optional parameter for GEN20 (type 6, Gaussian), to set the variance (default = 1.0). 2008-09-29 jpff * OOps/diskin.c (diskin_read_buffer): mea culpa; zeros written to wrong place. 2008-09-13 Michael Gogins * H/csound.h: Added Doxygen "mainpage" introductory section at top of file; switched to HTML format for API documentation (replacing LaTeX/PDF format). 2008-09-17 jpff * RELEASE VERSION 5.09 2008-09-13 Michael Gogins * frontends/CsoundAC/Score.cpp: Implemented importation of MusicXML v2 files into the CsoundAC Score class, using the Grame MusicXML library. 2008-09-13 Michael Gogins * custom-mingw.py: Updated for more recent third party packages. * frontends/fltk_gui/CsoundGUIMain.cpp: Score editor works properly now. * examples: Updated CsoundAC.csd and CsoundAC-midi.csd, removed some obsolete precursors of them, added Drone.py Tk GUI example. * csound-build.tex: Detailed instructions for building the Windows installers. * Top/csound.c, H/csoundCore.h: Corrected spinlocks for thread-safe access to spin and spout buffers, added to dummy slots of the CSOUND structure to preserve backwards API compatibility. 2008-09-10 jpff * Opcodes/scoreline.c (localops): Wrong structure named in entry -- probably benign * H/version.h (CS_PACKAGE_STRING): VERSION 5.09 2008-09-09 Anthony Kozar * H/csound.h (csoundSpinLock, csoundSpinUnLock): Removed attempt at printing warnings when spinlocks are not implemented. * Opcodes/sfont.c (SfPlayMono): More declaration before code fixes. * Opcodes/shape.c (PDHalfX): Fixed unitialized variable. * Engine/rdorch.c (skiporccomment): * Opcodes/Vosim.c (vosimset): Added missing return values. 2008-09-08 Anthony Kozar * Top/threads.c (csoundRunCommand, csoundSleep): Consolidated dummy versions to avoid multiple definitions. 2008-09-08 jpff * Top/csound.c ("C"): Do not load pthreads in mac_clasic * Top/threads.c (csoundRunCommand, csoundSleep): Added mac_classic dummy versions * OOps/aops.c (outs): Declarations before code in C 2008-09-02 jpff * H/ugrw1.h: * OOps/ugrw1.c (printkset, printk, printksset, printks): Check that opcode is initialised 2008-08-31 jpff * H/version.h: 5.08.99 2008-08-14 jpff * Engine/csound_orc.l: Added #include and macros (currently without arguments) 2008-08-12 jpff * Opcodes/uggab.c (poscaa, poscka): Ensure frequency is not overwritten if variable is shared 2008-07-26 jpff * Engine/rdorch.c (skiporccomment): Correct stupid error in multiple * characters 2008-07-23 jpff * Engine/fgens.c (gen23): Allow scientific notation (as was in csound4!) 2008-07-05 jpff * Opcodes/ambicode1.c: Added new file with Furse/Wiggins decoders 2008-06-30 Steven Yi * Engine/musmon.c: reverted sensevents to set EVTBLK to outside of while loop; caused bug where using event opcode with "e" would cause a segfault and hang csound 2008-06-26 jpff * SConstruct: Allow selectable version if TCL and TK (needed for OpenSuSE11.0) 2008-06-12 jpff * Engine/memalloc.c (mfree): (mrealloc): Improvements to coding 2008-05-28 Michael Gogins * Top/threads.c: For the Csound threading API, on the Windows platform, I removed the native Windows threading implementation and replaced it with the POSIX threads implementation already used for Linux and OS X. This is to facilitate development of multi-threading in Csound, and to simplify the maintenance of Csound. 2008-05-28 jpff * Opcodes/ugens7.c (harmon): Make constant totally 64bit safe * Opcodes/vbap.c: Change argument types to akOO from akoo etc 2008-05-18 Michael Gogins * Opcodes/chua/ChuaOscillator.cpp: Csound opcode implementation of Chua's Oscillator, a nonlinear dynamical system capable of many kinds of periodic and chaotic behavior, including multiple simultaneous attractors. See the reference manual entry for "chuap" for documentation. See examples/chuap.csd and examples/chuas_oscillator/ChuasOscillatorApp.py for sample Csound usage. * Opcodes/linear_algebra.cpp: Csound i-rate and k-rate opcodes for much standard linear algebra over real and complex vectors and matrices: elementwise arithmetic, norms, transpose and conjugate, inner products, matrix inverse, LU decomposition, QR decomposition, and QR-based eigenvalue decomposition. Includes copying vectors to and from a-rate signals, function tables, and f-signals. See the source code for preliminary documentation and tests/test24.csd for sample Csound usage. 2008-05-17 jpff * util/lpanal.c: Removed static variables to a structure 2008-05-08 jpff * util/envext.c: * util/het_export.c: * util/het_import.c: * util/heti_main.c: * util/lpc_export.c: * util/lpc_import.c: * util/lpci_main.c: * util/lpcx_main.c: * util/mixer.c: * util/pv_export.c: * util/pv_import.c: * util/scale.c: * util/srconv.c: * util/xtrct.c: * util1/sortex/smain.c: * util1/sortex/xmain.c: Corrected licence to LGPL 2008-05-06 jpff * Engine/rdorch.c (skiporccomment): New function to handle /* .. */ (rdorchfile): Call it * Engine/sread.c (sget1): Do not expand macros in /* .. */ context 2008-04-30 jpff * H/sysdep.h: Introduce macros for MYFLT versions of functions * OOps/aops.c: Use macro for exp/expf etc all over 2008-04-28 jpff * OOps/ugens4.c (buzz): Restructured for speed (gbuzz): Ditto 2008-04-24 jpff * Top/argdecode.c (argdecode): OLPC now have dummy R,N and H options 2008-04-15 jpff * OOps/diskin.c (sndo1set): Deprecate soundout in favour of fout 2008-03-23 jpff * Top/argdecode.c (decode_long): Change incorrect %n to %d (shades of BCPL) 2008-03-18 jpff * Opcodes/Vosim.c: New file and opcode 2008-02-27 jpff * Opcodes/vbap.c (localops): Changed vbap* to gave a k-rate last required arg. 2008-03-16 jpff * H/version.h: 5.08.2 2008-03-08 Anthony Kozar * H/prototyp.h: * Top/argdecode.c: * Top/main.c: * Top/one_file.c (readOptions, read_unified_file): readOptions() only prints "missing " message when reading from CSD file. 2008-03-02 Michael Gogins * SConstruct, csoundd.nsi: Many changes to enable building and installing Csound built with MSVC 2008 or MinGW 4.2.1 * CsoundAC: Build as static library to try to work around problem with MSVC corrupting data in C++ classes exported but based on non-exported STL classes. * API Reference: Updated to reflect recent changes. 2008-02-23 Michael Gogins * InOut/widgets.cpp: Fixed a major bug in which the Csound memory manager (C style) was allocating and deallocating a C++ structure (WIDGETS_GLOBALS). If new is not called for WIDGETS_GLOBALS, the constructors of its std::vector collections are not called. Then in the widget csoundDestroyModule function, invalid vectors are iterated, causing an access violation. Fixed by using standard C++ new and delete for the structure to ensure proper creation of its vector members. This is OK because by calling csoundModuleInit and csoundModuleDestroy, Csound is permitting the module to manage its own memory. The code accessed FLTK flags as a value when the flags had not been initialized as a global variable. This caused an access violation in csoundModuleDestroy. The code has been changed to get the flags as a pointer, and only dereference the pointer if it is not null. * Opcodes/vst4cs/src/vst4cs.cpp: Cleaned up csoundModuleDestroy code for Windows MSVC build, which was causing an access violation. 2008-02-22 Michael Gogins * SConstruct: Many changes to enable all features of Csound to build with Microsoft Visual C++ 2008 (MSVC). Also changes to enable build with MinGW 3.4.5/MSys 1.0.11/SCons 0.97. * custom-mingw.py, custom-msvc.py: Rationalized locations of third-party libraries in network mounted "U:/" drive root directory. * Frontends/CsoundAC/Counterpoint.cpp: Many changes to enable MSVC compilation. * CsoundVST: Renamed CsoundVST.exe to CsoundVstShell.exe to enable MSVC build. Exported new RunCsoundVST function to enable CsoundVstShell to run with MSVC build. * Engine/sread.c (nested_repeat, do_repeat, sread, etc.): Renamed struct in_stack_s to avoid debugging conflict with rdorch.c. Fixed some endless loops caused by the 'm' and 'n' statements. Prevented 'm' and 'n' statements from eating next line. Fixed line counts when using 'm' and 'n'. nested_repeat() does not need to change event opcode to 's'. Fixed 'r' repeats to work with optional p1 of 's' and 'e' statements. '{' statement should not reset clock_base, warp_factor, or prvp2. 2008-02-01 Anthony Kozar * H/version.h (CS_APISUBVER): Increased to 6 for Csound 5.08. * Top/getstring.c: Added stub for csoundSetLanguage(). 2008-01-31 Anthony Kozar * H/csound.h (CSOUND_FILETYPES): Added CSFTYPE_IMAGE_PNG. * Opcodes/imageOpcodes.c (__doOpenImage, __doSaveImage): Use FileOpen2() and FileClose() instead of fopen() and fclose(). Other minor fixes. 2008-01-30 jpff * retagged 5.08b 2008-01-29 veplaini * Opcodes/hrtfopcodes.c: New HRTF opcodes by Brian Carty * Opcodes/syncgrain.c: fixed bug in period counter preventing accurate tuning of grain frequency * SConstruct: added token NOGETTEXT to useGettext=0 option 2008-01-29 jpff * H/dumpf.h: Commented out the interpolation argument as not implemented. 2008-01-29 Anthony Kozar * Top/one_file.c (readOptions, checkVersion, etc.): Fixed version checks; prevented crashes in readOptions(), and improved error reporting for CSD. 2008-01-27 Anthony Kozar * Top/one_file.c (read_unified_file, checkLicence): Added as an acceptable alternate spelling of . 2008-01-27 jpff * version 5.08Beta * installer/linux/installer.fl: * installer/linux/new_install.cxx: Added support for installing locales 2008-01-22 Anthony Kozar * Top/argdecode.c (decode_long): Added --csd-line-nums= option. 2008-01-21 Anthony Kozar * Engine/sread.c (scorerr, sreaderr, getscochar, sread, getpfld, etc.): Major changes to score error reporting; now accurately reports the line numbers for the chain of inputs for most errors. Many error messages were changed to avoid redundancy and for clarity. 2008-01-20 Anthony Kozar * H/csoundCore.h (CSOUND): * Top/csound.c: * Top/main.c (csoundCompile): Save the original CSD file name. * Engine/sread.c (scorerr, sget1): Fixed backtrace of score includes in scorerr() and a possible crash when a #include file is not found. 2008-01-19 Anthony Kozar * H/csoundCore.h (CSOUND): * Top/csound.c: * Top/one_file.c (read_unified_file, etc.): * Engine/rdorch.c (synterr): Count lines while reading a CSD and save the offsets of the orchestra and score; add offset to line numbers reported with errors in the orchestra. (Score yet to be done). 2008-01-13 jpff * Opcodes/pan2.c (pan2): Corrected so it agrees with documentation 2008-01-06 jpff * H/version.h (CS_PATCHLEVEL): If subversion goes up,patchlevelneeds to be reset. 2007-12-27 jpff * Opcodes/imageOpcodes.h: * Opcodes/imageOpcodes.c: New code 2007-12-25 jpff * po/french.po: * po/american.po: Translations * po/csound.po: New; gettext template * Top/getstring.c (init_getstring): Alternative version for GNU gettext version * InOut/widgets.cpp: Correct double negatives in error messages 2007-12-17 * H/csoundCore.h (CSOUND): added fields delayederrormessages and printerrormessagesflag and reduced number of dummies * Top/csmodule.c (csoundLoadExternal): Store messages about non-modules * Top/csound.c (csoundPreCompile): Print delayed messages at end if any and in API version * Top/main.c (csoundCompile): If delayed messages print after arg decode 2007-12-15 jpff * Opcodes/pvsband.c (pvsbrej): New opcode for band reject 2007-12-14 Anthony Kozar * Opcodes/shape.c: Added unipolar option to pdclip, pdhalf, and pdhalfy, making it the default. 2007-12-11 Anthony Kozar * Engine/sread.c (ifa, getpfld): New "no-carry" operator (!) for score language that prevents implicit carrying of p-fields in i-statements. (eg. i 2 1 1 4.0 ! will only have 4 p-fields regardless of whether previous i2 statements had more). 2007-12-11 jpff * H/version.h (CS_PATCHLEVEL): 3 * Opcodes/pvsband.c: New code * Opcodes/pvs_ops.c (csoundModuleInit): Initialise pvsband 2007-12-06 Anthony Kozar * SConstruct: * Opcodes/shape.c: New opcodes powershape, polynomial, chebyshevpoly, pdclip, pdhalf, pdhalfy, and syncphasor. 2007-12-03 Anthony Kozar * Engine/sread.c (sread, flushlin, getpfld): Improved line counts for error reporting (still much to do though). Fixed some potential buffer overflows. Fixed {} repeat opcodes and improved their parameter reading (similarly to previous changes for 'r' statement). Now flushing rest of line after finding an illegal character in getpfld(). 2007-11-30 jpff * Opcodes/pvsbasic.c (pvsscale): Improved algorithm for SDFT case so no ampltitude variation 2007-11-29 Anthony Kozar * Top/argdecode.c (argdecode, decode_long): * Top/main.c (csoundCompile): * Top/csound.c (const cenviron_): * Engine/otran.c (otran): * H/csoundCore.h (struct OPARMS): Added --check-syntax-only commandline flag (exclusive with --i-only). otran() and csoundCompile() return early when just checking syntax. --i-only sets --nosound same as -I Added initial value for numThreads to OPARMS. * Top/one_file.c (read_unified_file): CSD read should fail when no tag found so that performance is aborted. * Ops/str_ops.c (getcfg_opcode): Added mac_classic case for host OS name. 2007-11-21 Anthony Kozar * Opcodes/sfont.c: Corrected code for C89 (all declarations at top). 2007-11-07 Felipe Sateler * H/csound.h,frontends/csladspa/csladspa.cpp,interfaces/CsoundFile.hpp, interfaces/filebuilding.h * SConstruct (CheckGcc4): Added stuff to limit visibility of symbols 2007-10-01 jpff * VERSION 5.07 2007-09-30 jpff * OOps/goto_ops.c (turnoff2): Patch from Jonathan Murphy in mode4 case * OOps/pstream.c (pvscross): SDFT support 2007-09-29 jpff * OOps/ugens1.c (xsgset2, xsgset): Allow negative amd zero length segments 2007-10-03 Michael Gogins * Updated Windows installers to current versions: libsndfile, PortAudio, Fluidsynth, Synthesis Toolkit in C++. * Restored Synthesis Toolkit in C++ Csound opcode wrappers for native STK C++ code, as STK now has BSD-type license. * Convenience wrappers in high-level CsoundAC.Composition class for Csound.Score.arrange(), csnd.CppSound.setOrchestra(), and csnd.CppSound.setScoreHeader(), for more intuitive use of CsoundAC with Csound. * Updated Csound API documentation to reflect splitup between CsoundAC and CsoundVST. 2007-09-28 jpff * Opcodes/pan2.c: New code * Opcodes/pvsbasic.c (pvsoscprocess): Added SDFT support 2007-09-21 jpff * Opcodes/pvsbasic.c: Added tests all over to warn if the same f-signal is used as in and out in the same opcode 2007-09-20 jpff * Opcodes/pvsbasic.c (pvsblurset, pvsblur): Added SDFT support 2007-09-19 jpff * Opcodes/pvsbasic.c (pvsfilterset, pvsfilter): Added SDFT support 2007-09-18 jpff * Opcodes/pvsbasic.c (pvsmix): Added SDFT support 2007-09-17 jpff * Opcodes/pvsbasic.c (pvsmoothprocess): Added SDFT support; also a-rate parameters is wanted 2007-09-09 jpff * Made SDFT dependent of SDFT macro and adjust SConstruct to set it * Opcodes/pvsbasic.c (pvsshift, pvsscale): Added SDFT support 2007-09-08 jpff * Opcodes/pvsbasic.h (_pvsfreez): Remove unused lastfreq 2007-08-28 Steven Yi * InOut/rtwinmm.c: midi_in_close had incorrect check causing device not to be closed properly 2007-09-06 jpff * Opcodes/pvsdemix.c (pvsdemix_init): Added (under BETA) support for streamed SDFT. * Opcodes/pvsbasic.h (_pvsfreez): Added field in SDFT case * Opcodes/pvsbuffer.c (pvsbufreadset, pvsbufferset): Added (under BETA) support for streamed SDFT. * Opcodes/pvscent.c (pvscentset, pvscent, pvsscent) (pvspitch_init): Added (under BETA) support for streamed SDFT. Includes a-rate opcode for pvscent * Opcodes/pvsbasic.c (pvsinit, pvsfwriteset, pvsdiskinset) (pvsfreezeset, pvssfreezeprocess, pvsfreezeprocess, pvsoscset) (pvsbinprocess, pvsbinprocessa, pvsmoothset, pvsmixset, pvsmix) (pvsfilterset, pvsscaleset, pvsshiftset, pvsshift, pvsblurset) (pvstencilset, pvstencil): Added (under BETA) support for streamed SDFT. Includes a-rate opcode for pvsbinprocess * OOps/pvsanal.c (pvssanalset, pvsanalset, pvssanal, pvsanal) (pvsynthset, pvssynth, pvsynth): Added (under BETA) support for streamed SDFT * H/pstream.h: Added (under BETA) support for streamed SDFT. Changes to PVSDAT and PVSANAL 2007-08-31 Anthony Kozar * OOps/aops.c: * Engine/entry1.c: * H/entry1.h: Added new value conversion functions to convert from Midi note number to Csound's three pitch formats (cpsmidinn, pchmidinn, and octmidinn). 2007-08-28 Steven Yi * Opcodes/fluidOpcodes/fluidOpcodes.c: modified fluidEngine opcode to take optional number of channels (range 16-256, default to 256) and polyphony (range 16-4096, default to 4096) to use. 2007-08-21 Steven Yi * Opcodes/fluidOpcodes/fluidOpcodes.c: added new fluidSetInterpMethod opcode that wraps fluidSynth's fluid_set_interp_method API method; allows user to choose interpolation method from 0 (none), 1 (Linear), 4 (4th order, default), and 7 (7th order, highest quality) on a per channel basis 2007-08-21 * Opcodes/sfont.c: removed all global static variables 2007-08-16 * SConstruct: Separate Word64 (for PIC) and Lib64 for library name 2007-08-14 * SConstruct: Use .Program rather than .Command in cseditor 2007-07-24 Michael Gogins * Folded all NSIS windows installer scripts into one script, csoundd.nsi. See the top of this script for command-line options to build float sample or double sample versions of Csound, or to omit or include non-free software components. The script automatically detects Python, and can install Python if it is not available; if Python is not available, copies Python features of Csound to a backup directory. * Renamed some example .csd files for greater clarity. * Improved GUI for CsoundVST. * Updated the Csound reference manual for the new installer script, CsoundAC, and changes in CsoundVST. 2007-07-28 jpff * Engine/musmon.c (tempset): Cannot set tempo if beatmode not in force 2007-07-24 Michael Gogins * Removed CsoundVST, vst4cs, and stk.dll (the C++ version of the STK opcodes) from the default Windows installers, in order to bring the Windows installers into line with SourceForge licensing guidelines. * Moved the "Silence" algorithmic composition classes out of the CsoundVST shared library and into a new shared library, Python extension module, and CVS directory, CsoundAC (for "Csound algorithmic composition"). * Created new NSIS installer scripts that do include CsoundVST, vst4cs, and the STK opcodes as a convenience for those who will build these components from source code. * Speeded up the CsoundAC.Voicelead, CsoundAC.VoiceleadingNode, and CsoundAC.Score class methods that work with chord voicings by using a new algorithm to iterate through all voicings of a chord in a specified by range by adding octaves to the lowest and most compact voicing, instead of building a set of all voicings in memory (which would get much too large for complex chords). 2007-07-13 * util/atsa.c (init_sound): Check to see if no partials (ie silence) and stop 2007-07-12 * Opcodes/ugnorman.c: Added scaling by 0dbfs and some code tidying 2007-07-06 * InOut/rtwinmm.c (csoundModuleCreate): Quieten startup message in line with other modules * Opcodes/ugnorman.c (atsaddnzset): Complain about a negative number of bands 2007-07-05 Michael Gogins * Opcodes/vst4cs: Fixed a bug in the vstnote opcode whereby NOTE OFF messages were scheduled, but not always dispatched. NOTE OFF messages are now both scheduled and dispatched. 2007-07-05 jpff * Opcodes/ambicode.c: Used P type for gains in bformenc. Added negative setup to give "controlled opposites" rather than spherical harmonics. Tidied code to make kbeta explicit in encoding. Other code reworking. * Engine/entry1.c: * Engine/rdorch.c (getoptxt): * Engine/csound_orc_semantics.c (handle_polymorphic_opcode): Added P as k-rate defaulting to 1 2007-06-30 jpff * OOps/goto_ops.c (turnoff2): ip->nxtact can be overwritten in mode 0 so need to remember the value before calling deact 2007-06-24 jpff * OOps/ugens2.c (koscl3): The amplitude was being ignored. Multiply by *p->xamp to fix 2007-06-08 jpff * Opcodes/ugsc.h: * Opcodes/ugsc.c: Make filters work in doubles internally 2007-06-04 jpff * VERSION 5.06 * interfaces/cs_glue.h: Removed as it was empty * Opcodes/grain4.c (grainsetv4): Supress messages if no warnings * H/soundio.h (SF2TYPE): Masked off top nibble with SF_FORMAT_TYPEMASK 2007-06-03 Anthony Kozar * Top/cscorfns.c (cscoreRESET & cscoreFileOpen): Fixed deallocation of SPACE blocks. Clarified some error messages. Searches in INCDIR now when opening extra score files and calls csoundNotifyFileOpened(). 2007-06-02 Anthony Kozar * util/dnoise.c: * util/hetro.c: * util/sndinfo.c: * util/srconv.c: Added calls to csound->NotifyFileOpened() as needed. * Opcodes/fout.c (fout_open_file): Changed FileOpen() to FileOpen2(), but the result is not ideal yet because we cannot always know the correct file type for files opened with the fiopen opcode. * H/csoundCore.h: * H/csound.h: Added sftype2csfiletype() function pointer to CSOUND. * Opcodes/py/pythonopcodes.c (exec_file_in_given_context): * Opcodes/py/pyx-gen.py: * Opcodes/py/pyx.auto.c: Replaced fopen() call with FileOpen2() in exec_file_in_given_context(), adding a CSOUND* to the function arguments, and updating the pyexec* opcode routines to pass it. * InOut/virtual_keyboard/KeyboardMapping.cpp: * Top/main.c (csoundCompile): Call csoundNotifyFileOpened() if a dummy score file is created. * InOut/libsnd.c (sfopenin & sfopenout): Call csoundNotifyFileOpened() for the primary input and output soundfiles. 2007-06-01 jpff * OOps/diskin2.c (diskin2_init): * OOps/diskin.c (newsndinset): Supress warning messages when no warnings requested * Top/csound.c (kperf): Restore other way of running chain. Unsafe in presence of delete but needed in turnoff 2007-06-01 Anthony Kozar * Engine/envvar.c (csoundFileOpenWithType): When opening a sound file for reading, replace CSFTYPE_UNKNOWN_AUDIO with actual file type. * InOut/libsnd_u.c (sftype2csfiletype): Ignore endian bits of format. * OOps/sndinfUG.c (getsndinfo): Fixed a small bug in yesterday's changes and worked around opening of PVOC files being reported twice. 2007-05-31 Anthony Kozar * H/csoundCore.h: * H/csound.h: Moved CSOUND_FILETYPES enum to csound.h for host and plugin access. Added more file type constants. * InOut/libsnd_u.c: * OOps/diskin.c * util/mixer.c: * util/scale.c: * util/xtrct.c: type2csfiletype() now does more audio formats and uses sample-encoding information to distinguish between AIFF and AIFC. * H/csound.h: * H/csoundCore.h: * H/prototyp.h: * Engine/memfiles.c: * Top/csound.c: * OOps/ugens3.c: * OOps/ugens5.c: * Opcodes/hrtferX.c: * Opcodes/scansynx.c: * Opcodes/ugens9.c: * Opcodes/ugnorman.c: * util/het_export.c: New API function pointer ldmemfile2() to replace ldmemfile(). Takes an additional parameter for the type of file being opened. Updated all calls to ldmemfile() to use ldmemfile2() instead. New API function pointer NotifyFileOpened() that calls the FileOpenCallback when set. * InOut/winEPS.c: * Opcodes/ftgen.c: * Opcodes/sfont.c: Replaced fopen() calls with FileOpen2(). * Top/main.c: * Top/one_file.c * Engine/musmon.c: * Engine/rdorch.c: * OOps/sndinfUG.c: * Opcodes/Loris/lorisgens5.C: * Opcodes/fluidOpcodes/fluidOpcodes.c: Added calls to csoundNotifyFileOpened() after uses of fopen() within Csound. Added csound->NotifyFileOpened() to fluidLoad and lorisread. lorisread now looks in SADIR for input files. Tracks whether orc and sco files are temporary files. * Top/cscore_internal.c: * Top/csound.c: * H/prototyp.h: Rename internal cscore function to cscore_() to avoid linker warnings for duplicate symbol with standalone cscore programs. 2007-05-30 jpff * Top/argdecode.c (decode_long): Correct string length count in --m-warnings and a few others 2007-05-27 jpff * OOps/aops.c (MOD): Changed to non-integer values can be returned -- reverting to pre Feb2007 version but better code 2007-05-17 Andrés Cabrera * InOut/widgets.cpp, InOut/widgets.h: Added FlslidBnk2, FlvslidBnk, FlvslidBnk2, by Gabriel Maldonado 2007-05-14 Andrés Cabrera * InOut/widgets.cpp, InOut/widgets.h, Opcodes/gab/hvs.c, Opcodes/gab/newgabopc.c, Opcodes/gab/sliderTable.c, Opcodes/gab/tabmorph.c: Added new opcodes from CsoundAV by Gabriel Maldonado: hvs1, hvs2, hvs3, vphaseseg, inrg, outrg, lposcila, lposcilsa, lposcilsa2, tabmorph, tabmorpha, tabmorphak, tabmorphi, trandom, vtable1k, slider8table, slider16table, slider32table, slider64table, slider8tablef, slider16tablef, slider32tablef, slider64tablef, sliderKawai and an a-rate version of ctrl7. * Opcodes/gab/vectorial.c,Opcodes/gab/vectorial.c: Added new optional isize argument to vrandh and vrandi for more similarity with randh and randi 2007-05-02 Michael Gogins * ScoreGen.dll can now act as a MIDI effect as well as a VST plugin that can send MIDI events to the host. I.e., ScoreGen can act as a Python-programmable score generator in VST hosts. As a MIDI effect, ScoreGen can "freeze" generated events into a MIDI part for manual editing or notation, using Cubase's "Free MIDI Modifiers" command. * A number of serious bugs were fixed in ScoreGen's VST event processing. It will now properly play generated scores. 2007-05-07 jpff * Opcodes/pitch.c (pitchset): Do not change parameters! * Opcodes/partikkel.h: * Opcodes/partikkel.c: Remove failed attempt at aliasing-prevention that might result in segfaults or hangs when using kdist. Small optimisations. Some cosmetic stuff. 2007-05-04 * util/het_export.c (het_export): Improved error checks as suggest in bug report 2007-05-02 Michael Gogins * Updated the csnd and CsoundVST Python extension modules to be compatible with Python version 2.5. * Split all SWIG-generated Python stub code off into shared libraries _csnd.pyd and _CsoundVST.pyd. * All remaining code from the old _csnd.dll and _CsoundVST.dll is now in csnd.dll and CsoundVST.dll. * Many classes and functions in CsoundVST are now exported so that they can dynamically link with _CsoundVST.pyd. * "Glue" code for message buffers, etc. has been moved into the csound.h and csound.c files. 2007-04-29 Anthony Kozar * Engine/envvar.c, Engine/fgens.c, Engine/memfiles.c, * Engine/new_orc_parser.c, Engine/rdorch.c, Engine/sread.c, H/csound.h, * H/csoundCore.h, H/envvar.h, H/prototyp.h, H/soundio.h, InOut/libsnd_u.c, * InOut/midifile.c, InOut/midisend.c, OOps/diskin.c, OOps/diskin2.c, * OOps/dumpf.c, OOps/pvfileio.c, OOps/sndinfUG.c, Top/argdecode.c, * Top/csound.c, Top/main.c, Top/one_file.c, util/atsa.c, util/cvanal.c, * util/hetro.c, util/lpanal.c, util/mixer.c, util/pvanal.c, util/scale.c, * util/xtrct.c: New API function pointer FileOpen2() to replace FileOpen(). Takes additional parameters for the type of file being opened and whether it is a temp file. This information (along with filename, etc.) is passed to a new host callback that can be set with csoundSetFileOpenCallback(). Updated most uses of FileOpen() to use FileOpen2() instead. 2007-04-28 Anthony Kozar * Opcodes/ampmidid.cpp: #include "OpcodeBase.hpp", not . * Top/csound.c (kperfThread): * Top/main.c: * Opcodes/gab/vectorial.c (vrand*): Move declarations before other code and kperfThread() should return unsigned long instead of int. 2007-04-22 Michael Gogins * Corrected the logic in the CsoundVST ImageToScore class. * Added support for PNG and JPEG formats to the ImageToScore class. 2007-04-19 jpff * Opcodes/partikkel.h: * Opcodes/partikkel.c: New code from Oeyvind 2007-03-24 jpff * H/version.h (CS_APISUBVER): Increase * Top/csound.c: * Top/argdecode.c: * H/csoundCore.h: Rearrange code on sr/kr override 2007-03-19 Andrés Cabrera * Fixed vrandh and vrandi scaling problems and added optional idstoffset, iseed and ioffset arguments 2007-03-12 Andrés Cabrera * Added preliminary support for vst4cs on linux 2007-03-12 jpff * Opcodes/system_call.c (localops): system was not called at k-rate 2007-03-11 Andrés Cabrera * Added Plastic look for FLslider, FlslidBnk, FLbutton and FLbutBnk 2007-03-07 jpff * VERSION 5.05 2007-03-04 Steven Yi * Engine/sread.c: Applied patch from John McCullough from SourceForge bug 1666632 "Heap Overflow in Marker Parsing" 2007-02-18 Steven Yi * Opcodes/dam.{c.h}: Moved initialization code of power buffer to performance time function as it depends on krate var (kthreshold) 2007-02-17 jpff * OOps/aops.c (MOD): Attempt to fix bad code in MOD 2007-02-14 jpff * Top/cscore.c: Top/cscormai.c: Removed old code 2007-02-13 Anthony Kozar * Top/cscorfns.c: cscoreCopyEvent() was writing past the end of the EVENT struct. Also added new static atEOF to fix an infinite loop caused by a change in the behavior of rdscor(). * Top/cscormai.c: * Top/cscore.c: Moved to frontends/cscore/ * examples/cscore/: Added a number of examples of using Cscore. * util1/cscore/: Removing this directory as it is obsolete. 2007-02-13 jpff * Opcodes/fm4op.h (TwoPole): Not used 2007-02-02 jpff * Opcodes/pitch.c (trnset): Fixed bug in allocation 2007-01-26 jpff * Opcodes/gab/vectorial.c (vexpv_i): Aparent typo used uninitialied variable 2007-01-25 jpff * Opcodes/butter.c: Optimisations and accuracy improvements. Also deleted butter.h and incorporated into source 2007-01-16 Steven Yi * InOut/widgets.cpp (csoundModuleDestroy): wrapped deinit code with a check to see if widgetGlobals is not NULL (was causing segfault when running "csound" or "csound --help") 2007-01-15 Steven Yi * Manually merged in work from New Parser branch; to compile, must enable in build using buildNewParser=1; to use at runtime, use --new-parser flag; notes added to To-fix-and-do file; added tests directory for use with testing new parser (python scripts) 2007-01-15 jpff * Opcodes/wave-terrain.c (wtinit): No need to copy tables * Opcodes/scansyn.c (scsnu_initw): Initialise x2 and x3 as in scansynx 2007-01-07 Anthony Kozar * OOps/remote.c (remoteport): Stub version for platforms without sockets. * SConstruct: Use sys.byteorder to set flags for sfonts and STK opcodes. 2007-01-07 Steven Yi * Engine/envvar.c (csoundGetDirectoryForPath): added call to csoundConvertPathname at top of function to fix bug on Windows where path's with forward slashes were causing segfaults (Recommended by Anthony Kozar on Dev list) 2007-01-07 jpff * Engine/entry1.c: Allow printf and printf_i not have zero arguments after trigger (reverted as causes other problems) * Opcodes/system_call.c: new code 2006-12-02 Michael Gogins * Completed implementation of algorithmic composition helper classes for voice-leading and chord progression in CsoundVST: Voicelead, VoiceleadingNode, Conversions, and Score. These implement orthogonal arithmetical operations for changing interval structure ('prime chord' or P), chord transposition ('transposition' or T), and voicing or inversion within a range ('voicing' or V), as well as arithmetic upon pitch-class set numerals ('Mason number' or M). These operations can be used both to generate scores, and to filter existing scores. 2006-12-23 jpff * InOut/widgets.cpp (save_snap): fl_ask() is depricated so replace by fl_choice() 2006-12-14 jpff * Opcodes/pitch0.c (pfun): Commented out printing 2006-12-02 Michael Gogins * Added CppSound::getInstrumentNames() to return a map of instrument numbers to names for a loaded Csound orchestra. * Added ampmidid opcodes, which map MIDI velocity variable to peak amplitude using the method of Dannenberg (ICMC 2006), according to a user-specified dynamic range in dB. 2006-11-28 Steven Yi * InOut/virtual_keyboard: Modified FLvkeybd to take in width and height, make keyboard resizable 2006-11-26 Steven Yi * InOut/virtual_keyboard: Added FLvkeybd opcode to embed virtual keyboard into FLTK Widget panel; only one allowed per project; useful for demo versions of MIDI orchestras 2006-11-25 Steven Yi * InOut/widgets.cpp: Added FLcloseButton and FLexecButton opcodes; closeButton closes the window panel it is a member of, while execButton runs a command given to it 2006-11-16 jpff * OOps/diskin.c: (and many others) * OOps/remote.c: Use InitError correctly 2006-11-15 Steven Yi * InOut/virtual_keyboard: Added 10 MIDI Sliders to virtual keyboard 2006-11-13 jpff * OOps/remote.c (remoteport): New opcode to set remote port * install.py: Added cseditor to package system 2006-11-09 jpff * VERSION 5.04 2006-10-29 Simon Schampijer * OOps/remote.c: Added the patch from Dan Williams which: 1) Fixes detection of the IP address by correctly converting the uint32 to a string format using inet_ntoa() on Linux. There was something wrong with the manual conversion code that was there which caused only the last octet to be recognized, which meant the remote plugin was mismatching the IP addresses and playing everything locally. I have no idea why it worked before, but my patch is clearly correct (to me at least!) 2) fixes up error handling on plugin init; If the machine runs out of memory while starting the remote plugin, it should return an error in callox() so that CSound is alerted to the error as well. Furthermore, if detection of the local IP address fails for any reason, the plugin should fail to initialize. 2006-10-27 David Akbari * frontends/cseditor/*: * SConstruct: Added build options and targets for basic Csound syntax highlighting text editor that uses FLTK. 2006-10-27 Anthony Kozar * H/sysdep.h: #define for inline with Metrowerks CodeWarrior compiler. * OOps/remote.c: Removed troublesome inline declarations. 2006-10-27 Steven Yi * InOut/virtual_keyboard/*: * SConstruct: Added new FLTK virtual keyboard MIDI driver; enable use by using "-+rtmidi=virtual -M0"; sends MIDI notes in the same way as any real MIDI device; useful for testing and in situations without MIDI gear; still needs a little work 2006-10-26 Anthony Kozar * SConstruct: Check for socket-related headers and define HAVE_SOCKETS if they are found. * Top/main.c: * Engine/musmon.c: * H/remote.h: * OOps/remote.c: #ifdefed remove events based on HAVE_SOCKETS. Created stub functions for when they are not available. Expanded musmon.c interface to remote.c so that no internal knowledge of remote globals is necessary. Remote opcodes still exist on non-socket builds but print a warning message that remove events are not available. 2006-10-26 Anthony Kozar * Top/main.c: * Engine/namedins.c: * Engine/envvar.c: Couple more fixes for concatenating paths. 2006-10-25 jpff * OOps/midiops.c (pgmin): Added optional channel parameter to restrict watch 2006-10-25 Steven Yi * H/csoundCore.h (OPARMS): * Top/argdecode(decode_long): * Top/main.c (csoundCompile): added command line flags --no-default-paths and --default-paths to disable and reenable using path(s) of CSD/ORC/SCO as part of search paths 2006-10-24 Steven Yi * Top/main.c (csoundCompile): changed CSD/ORC/SCO directory to append instead of prepending search paths 2006-10-24 Anthony Kozar * Top/main.c: * Engine/rdorch.c: * Engine/envvar.c: * H/envvar.h: Many changes & improvements to file searching. - New internal interface for X-platform path manipulation. - CSD/ORC/SCO directory prepended to environment variables instead of appended (so that they are searched later). - Relative paths beginning with "./" or "../" now work when specifying filenames in ORC and SCO. - Many bug fixes to MacOS 9 path manipultion. 2006-10-23 jpff * OOps/midiops.c (pgmin): Make program changes in range 1-128 rather than 0-127 * OOps/remote.c (insremot): Need to check csound->remoteGlobals before access 2006-10-22 jpff * OOps/midiops.c: Added pgmchn opcode * Engine/entry1.c: Midiin was not being initialised; also added pgmchn opcode 2006-10-21 jpff * Opcodes/harmon.c: New code from Barry Vercoe 2006-10-19 Steven Yi * Top/main.c (csoundCompile): now adds directory of CSD, or ORC and SCO to INCDIR, SADIR, SSDIR, and MFDIR; SCO path's are currently added before ORC path * Engine/envvar.c (csoundGetDirectoryForPath): New function added to find absolute path given a path as string 2006-10-19 jpff * frontends/winsound/main.cxx (cs_compile_run): If orchname starts with / or \\ change directory to location 2006-10-19 Anthony Kozar * H/cscore.h: Fixed Cscore includes. * Top/csmodule.c: Now searches for & auto-loads plugins on MacOS 9. 2006-10-18 Steven Yi * Engine/musmon.c (process_rt_event): Fixed to check if remoteGlobals is initialized when processing MIDI events 2006-10-17 * util/pv_import.c (pv_import): Chancge exits to returns and replaced printing to stderr by calls to csound->Message 2006-10-16 Anthony Kozar * H/csound.h: * H/cscore.h: * H/cvgvar.h: Added Mac pragmas to export PUBLIC functions. * util/pv_import.c: Fixed check for failure to open output file. 2006-10-12 Michael Gogins * Added Voicelead class to the Silence system in CsoundVST. It finds the closest voice-leadings first by smoothness, then by parsimony, optionally avoiding parallel fifths, between two sets of pitches. * Added methods to the Score class in the Silence system for identifying the prime chord, transposition of prime chord, and voicing index for segments of scores; setting the same properties in segments of scores; and voice-leading between segments of scores. 2006-10-12 jpff * OOps/remote.c: * H/remote.h: New code for remote performance (OLPC) * Engine/entry1.c: Add opcodes insremot, midremot, insglobal and midglobal * Engine/musmon.c: New code for this * H/csoundCore.h: New fields for remote * InOut/midirecv.c: minor chjange for remote 2006-10-12 Steven Yi * Top/one_file.c (readOptions): fixed parsing of quoted strings 2006-09-24 jpff * Engine/musmon.c (print_maxamp): Allow coloured numbers in raw context as well as dB 2006-09-21 Steven Yi * Opcodes/biquad.c (mode): added mode opcode, a translation of François Blanc's mode UDO to C 2006-09-20 jpff * Opcodes/sfont.c (SfLoad): Allow string or number and strset code for file 2006-09-18 Steven Yi * Opcodes/flanger.c (wguide2set): fixed wguide2, code was looking at wrong arguments for xincod values, also check for comparison between the two xincod's was incorrect 2006-09-16 Michael Gogins * Added plugin SDK to Windows installers. 2006-09-15 jpff * util/lpcx_main.c: * util/lpci_main.c: * util/heti_main.c: Simpler versions that do not depend on all of csound for stand-alone versions 2006-09-12 jpff * Engine/sread.c (sread): isdigit is faster than strchr * Engine/insert.c (xinset): strings as arguments (xoutset): Ditto * Engine/otran.c (parse_opcode_args): Tracking strings as UDO arguments 2006-09-12 Steven Yi * Renamed Opcodes/avarops.c to Opcodes/vaops.c, renamed avar_get and avar_set opcodes to vaget and vaset (as requested on Csound list) 2006-09-09 Michael Gogins * Removed Loris from Windows installers as new versions do not run on Windows, and ATS opcodes are similar. * Upgraded LuaJIT to version 1.1.0 for Windows installer. * Upgraded libsndfile to version 1.0.17 for Windows installer. * Added information on Csound syntax coloring for SciTE to tutorial. * Added high-resolution versions of trapped.csd and xanadu.csd. 2006-09-08 Steven Yi * Engine/rdorch.c (rdorchfile, init_math_constants_macros): added math constants found in math.h as a default set of macros (M_PI is $M_PI, etc.) 2006-09-04 Steven Yi * Opcodes/avarops.c: added avar_get and avar_set opcodes to read from and write values to a-rate variables at k-rate 2006-08-28 jpff * Opcodes/newfils.c (moogladder_process): Minor optimisation (loop invariant) 2006-08-25 jpff * Engine/insert.c (delete_instr): Allowed named instruments as well 2006-08-23 veplaini * frontends/tclcsound/commands.c, tclcsound.h: added pvs bus channel interface to tclcsound. Not tested yet. Manual pages for all new opcodes have also been added. 2006-08-23 jpff * Opcodes/biquad.c (tbvcf): Use doubles inside filter * util/atsa.c: All over removed compiler warnings -- mainly missing casts and inappropriate use of floor 2006-08-23 veplaini * csoundCore.h, csound.h, bus.h, bus.c, csound.c, entry1.c : pvs bus now called pvsin/pvsout. * csound.hpp: added a user-friendly interface to pvsin/out * disprep.*, entry1.c: added pvsdisp opcode * pvsbasic.*: added pvsbin, pvsosc and pvsfwrite opcodes * pvscent.c: added pvspitch opcode by Alan OCinneide Manual pages to follow 2006-08-22 jpff * Opcodes/biquad.c (moogvcf, rezzy): Minor optimisations 2006-08-21 jpff * util/lpanal.c (polyzero): Replace pow(..,2.0) by direct calculation twice * SConstruct (stdutilSources): Added build of pv_import/export utilities * Engine/insert.c: Include delete in non-Beta version * util/pvi_main.c, util/pvx_main.c: New code 2006-08-20 veplaini * csoundCore.h, csound.h, bus.h, bus.c, csound.c, entry1.c : added fsig to chani/chano bus interface (now called pvsin/pvsout). * csoundCore.h: commented out redefinition of printf to eliminate warnings (on OLPC build) 2006-08-17 jpff * Top/csmodule.c (csoundLoadExternal): Even if not BETA display the reason that a module failed to load rather than -1 2006-08-15 jpff * Version 5.03 released 2006-08-11 Andres Cabrera * opcodes/Gab/vectorial.c: Added kverbose optional argument and other bug fixes. 2006-08-07 Andres Cabrera * opcodes/Gab/vectorial.c: Added optional arguments isrcoffset and idstoffset to most vectorial opcodes. * opcodes/Gab/vectorial.c: Added i-rate versions of most vectorial opcodes. 2006-07-30 jpff * util/cvanal.c (cvanal): Added termination message 2006-07-27 jpff * Opcodes/biquad.c (moogvcfset): Corrected mind error (divide and divide). Thanks to IV 2006-07-26 jpff * Opcodes/biquad.c (moogvcfset, moogvcf): Allow for scaling to 0dbfs and improve accuracy of filter by using doubles. (rezzyset, rezzy, bqrezset, bqrez): Use doubles in filter 2006-07-21 Michael Gogins * Added new long options for routing MIDI note on message key and velocity numbers to specified pfields: --midi-key=, --midi-key-cps=, --midi-key-oct=, --midi-key-pch=, --midi-velocity=, --midi-velocity-amp=. * Added tutorial LaTeX file tutorial/tutorial.tex. 2006-07-19 Victor Lazzarini * Opcodes/sndloop.c: added flooper2 opcode * Opcodes/syncgrain.*: added syncloop opcode Manual pages also added to cvs * frontends/tclcsound/commands.c: removed -d flag, added csPlayAll command, fixed csCompilelist bug. 2006-07-18 jpff * frontends/csound/sched.c (set_rt_priority): Comment out the check to see if running as root. Will fail later perhaps if cannot set priority. 2006-07-16 jpff * Top/one_file.c (readOptions): Remove trailing spaces in input 2006-07-12 jpff * Opcodes/nlfilt.c (pcount, pvalue): New opodes after IV suggestion * Opcodes/pitch.c (pitchset): Moved some filter coeffieients to double 2006-07-08 jpff * H/csoundCore.h: Removed unused macros and typedefs * Opcodes/physmod.c (make_DLineA): * Opcodes/physutil.c (make_DLineL): No need to zero allocated array * Opcodes/vst4cs/src/vst4cs.cpp: **EXPERIMENTAL** try to make programs 1-16 * Opcodes/osc-sock.c (osc_send_set, oscInitUDP): Use memset rather than deprecated bzero 2006-07-07 Istvan Varga * Engine/entry1.c: corrected opcode data size for inh and ino * Opcodes/bilbar.c (play_pp): use fabs() instead of abs() * Opcodes/biquad.c (nestedapset): do not assume sizeof(MYFLT) == sizeof(long) 2006-06-30 jpff * OOps/midiops.c: * OOps/ugrw1.c: * Opcodes/oscbnk.c: * Opcodes/physmod.c: * Opcodes/uggab.c: * Opcodes/wave-terrain.c: Similar changes to previous 2006-06-30 Istvan Varga * Opcodes/vbap_*.c (vbap_*): Replace 1/ksmps by the precomputed value 2006-06-28 jpff * Opcodes/vst4cs/src/: Many changes bringing code closer to Istvan's fork 2006-06-27 jpff * OOps/cmath.c (exprand): (biexprand): Restored safety checks for negative argument 2006-06-26 jpff * util/pv_import.c: Inverse of pv_export * util/pv_export.c: Code to convert .pvx file to comma-separated text, as a utility 2006-06-23 Istvan Varga * Opcodes/loscilx.c: experimental new opcodes: loscilx, sndload 2006-06-23 jpff * OOps/disprep.c (tempest): If we are in a mask situation retain previous best estimate of tempo 2006-06-18 Istvan Varga * OOps/sndinfUG.c: filelen, filenchnls, filesr opcodes: allow for getting parameters of convolve and PVOC files unless the "enable raw files" flag is zero 2006-06-17 Istvan Varga * OOps/ugens2.c: allow inconsistent table index and output type in table read opcodes if ksmps is 1, but print a warning message 2006-06-16 Istvan Varga * Engine/rdorch.c: experimental implementation of nested #ifdef/#ifndef and #else 2006-06-15 jpff * util/hetro.c (init_het): skip was not initialised 2006-06-15 Istvan Varga * Engine/rdorch.c: added #ifndef * InOut/libsnd_u.c: more quietening of messages 2006-06-14 Istvan Varga * Made messages less verbose in soundin, diskin, diskin2, and sfpassign. * Engine/otran.c: fixed (hopefully) incorrect offset calculation of string variables 2006-06-13 Istvan Varga * New API functions: csoundSetCallback(), csoundRemoveCallback() * OOps/bus.c: sensekey opcode: use new callback interface * H/version.h: updated API version to 1.02 * InOut/widgets.cpp: experimental implementation of sensekey using FLTK (activated with a new optional argument to FLpanel; only one window can receive keyboard events) 2006-06-12 jpff * InOut/midifile.c (csoundMIDIFileOpen): Added MFDIR 2006-06-11 Istvan Varga * Updated version to 5.03.0 beta. * Opcodes/midiops2.c: new opcode: ipgm midipgm [ichn] 2006-06-10 * Csound 5.02.1 release 2006-06-10 Istvan Varga * Engine/sread.c: fixed parsing of score expressions * OOps/aops.c: fixed memory access errors and string channels with numeric channel ID in invalue and outvalue * frontends/winsound/main.cxx, frontends/CsoundVST/CsoundVST.cpp: minor fixes * frontends/fltk_gui/CsoundPerformance.cpp: fixed bug related to display callbacks 2006-06-09 Istvan Varga * OOps/bus.c: Added new optional output argument to sensekey opcode. * Engine/rdorch.c: Made excess number of output arguments a syntax error, rather than silently ignoring them. 2006-06-04 Michael Gogins * Changed the MIDI interoperability opcodes (OOps/midiinterop.c) midinoteoncps, midinoteonoct, midinoteonpch to leave key and velocity unchanged for score-driven performance. 2006-06-04 * Csound 5.02 release 2006-06-04 Istvan Varga * Engine/otran.c: work around constndx() not being compiled correctly 2006-06-03 Istvan Varga * Engine/fgens.c, InOut/libsnd_u.c, OOps/diskin.c, OOps/diskin2.c: GEN01, diskin, diskin2, soundin: with an iformat value of -1, reject headerless files, rather than assuming the same format as the one specified on the command line GEN01: added format codes 7 (8 bit unsigned), 8 (24 bit), and 9 (doubles) * Engine/entry1.c, H/sndinfUG.h, OOps/sndinfUG.c: filelen, filenchnls, filesr: added optional i-time argument that defaults to 1, and if zero, will make the opcodes return zero on headerless files rather than some possibly incorrect defaults * Opcodes/fout.c: fixed bug in fini opcode (negative numbers were read incorrectly) * Engine/sread.c, Engine/swrite.c, Engine/twarp.c: fixes to reading numbers in [] score expressions fixed 's' and 'e' score opcodes with time parameter 2006-06-02 Istvan Varga * New string opcodes: Sdst strsub Ssrc[, istart[, iend]] Sdst strsubk Ssrc, kstart, kend ichr strchar Sstr[, ipos] kchr strchark Sstr[, kpos] ilen strlen Sstr klen strlenk Sstr Sdst strupper Ssrc Sdst strupperk Ssrc Sdst strlower Ssrc Sdst strlowerk Ssrc Sval getcfg iopt ipos strindex Sstr1, Sstr2 kpos strindexk Sstr1, Sstr2 ipos strrindex Sstr1, Sstr2 kpos strrindexk Sstr1, Sstr2 * Engine/express.c, Engine/otran.c: fixed parsing of numbers in exponential notation also some parser fixes related to 0dbfs 2006-06-01 Istvan Varga * Added callback interface to the software bus with named channels, using new opcodes chnrecv and chnsend. The callback function can be set with csoundSetChannelIOCallback(). 2006-05-31 jpff * util/sndinfo.c: Added option to print looping information etc. 2006-05-31 Istvan Varga * InOut/widgets.cpp: FLbutton type 1 callback now sets the output to "ion" 2006-05-30 Istvan Varga * Opcodes/fout.c: new opcode: ficlose 2006-05-30 ma++ ingalls * aops.c, aops.h, csound.h: invalue/outvalue updates as per Istvan's comments * csound.c: changed "early return" comments to debug only * hetro.c: added pollevents inside processing loop * lpanal.c: added warning message with -g flag * sockrecv.c: took out usleep() declaration - was causing compile error 2006-05-28 ma++ ingalls * frontends/CsoundX: added to cvs * aops.c, entry1.c, entry1.h, csound.h: added hack to invalue/outvalue to support strings 2006-05-27 Istvan Varga * Added ATS analysis utility. 2006-05-26 ma++ ingalls * frontends/CsoundVST/AEffect.h: commented out 2 PRAGMAS causing compile error on mac * Opcodes/vst4cs/vsthost.c: added plug-in loading for MACH-O mac. commented out #includes that caused compile error on mac * Opcodes/vst4cs/vsthost.h: commented out #includes that caused compile error on mac * Opcodes/vst4cs/fxbank.h: commented out #includes that caused compile error on mac * OOps/aops.c: added i-rate support to invalue/outvalue 2006-05-24 Istvan Varga * InOut/rtalsa.c: changed default device from "default" to "plughw" * InOut/rtjack.c: list available device names for -i adc or -o dac if an invalid device is specified 2006-05-23 Istvan Varga * Opcodes/ugnorman.c: fixed "not initialised" bug in ATSbufread 2006-05-22 Istvan Varga * OOps/midiops.c: massign(): interpret channel number <= 0 as all channels * H/csoundCore.h, Top/csound.c: added new function GetCurrentThreadID() to CSOUND structure 2006-05-21 Michael Gogins * New API function: csoundGetCurrentThreadId() 2006-05-20 Istvan Varga * Opcodes/stackops.c: added new stack opcodes (stack, push, pop, push_f, pop_f); also moved monitor opcode here. * Reworked user defined opcodes to allow for up to 256 input/output arguments. * Opcodes/bilbar.c: removed use of C++ style comments. 2006-05-16 jpff * Engine/entry1.c: Change args of xin to match OPCODENUMOUTS 2006-05-15 Anthony Kozar * Top/cscormai.c: Fixed #includes. * interfaces/CsoundFile.cpp: isspace() is in and supposed to be in std namespace * H/csoundCore.h: Increased OPCODENUMOUTS to 64 as requested. 2006-05-15 Istvan Varga * Opcodes/monitor.c: added new opcode: monitor 2006-05-14 jpff * util/pvlook.c (pvlook): Rewritten for .pvx format 2006-05-13 jpff * util/pvanal.c: Added -B # argument to give a beta to the Kaiser window; still defaults to 6.8 2006-05-12 Istvan Varga * frontends/csound/csound_main.c: overwrite old log files, rather than appending messages 2006-05-08 Istvan Varga * New API functions: csoundCreateMutex, csoundLockMutex, csoundLockMutexNoWait, csoundUnlockMutex, csoundDestroyMutex, csoundRunCommand 2006-05-04 Istvan Varga * InOut/rtalsa.c: added new "devfile" MIDI driver that uses device files in /dev, based on code from Csound 4.23 mididevice.c 2006-05-03 Istvan Varga * InOut/FL_graph.cpp, InOut/widgets.cpp: * InOut/winFLTK.c, InOut/winFLTK.h: added more FLTK flags (see winFLTK.h) 2006-05-02 Istvan Varga * InOut/widgets.cpp, InOut/winFLTK.c, InOut/winFLTK.h: disable threads by default if graphs are used * OOps/sndinfUG.c: filepeak opcode now uses PEAK chunks with libsndfile >= 1.0.16 2006-04-30 Istvan Varga * Attempt to fix thread locks on MacOS X. * util/srconv.c: fixed output amplitude when downsampling allow utility to be stopped by yield callback * install.py, installer/misc/mkpackage.py: install TclCsound command documentation 2006-04-29 Istvan Varga * Made it possible to control the behavior of the FLTK plugin from the host application. This can be done with the following code between calling csoundPreCompile() and csoundCompile(): CSOUND *csound; ... csoundCreateGlobalVariable(csound, "FLTK_Flags", sizeof(int)); *((int*) csoundQueryGlobalVariable(csound, "FLTK_Flags")) = flags; where 'flags' can be the sum of any of the following values: 1: disable widget opcodes 2: disable FLTK graphs 4: disable the use of a separate thread for widget opcodes 8: disable the use of Fl::lock() and Fl::unlock() 16: disable the use of Fl::awake() additionally, after calling csoundCompile(), the same variable can be checked to find out if graphs or widget opcodes are used: 32: FLrun opcode was called 64: callbacks for FLTK graphs are set * Top/main.c: fixed crash on registering opcodes from the host application * frontends/fltk_gui: new GUI frontend that uses the Csound 5 API and FLTK 2006-04-19 Michael Gogins * Updated Lua to version 5.1 (current version), changed lua_example.lua to use Class:method calls. 2006-04-17 John ffitch * Opcodes/bilbar.c: Added prepared piano string model * H/entry1.h: * Engine/entry1.c: Added remove opcode. Probably should be an API function rather than opcode * Engine/insert.c (delete_instr): New code to delete non-active instruments. Still needs to be checked as it may leave structures dangling. 2006-04-15 Istvan Varga * Engine/namedins.c, Engine/otran.c: optimizations in orchestra parser * interfaces/lua_interface.i: wrap cs_glue.hpp and csPerfThread.hpp 2006-04-09 Istvan Varga * Engine/envvar.c: csoundFileOpen(): check for files with .sd2 extension, and use sf_open() in this case if sf_open_fd() fails * InOut/FL_graph.cpp: wait for the window to be closed by the user at end of performance * InOut/libsnd.c: fixes in enabling peak chunks and dithering * InOut/libsnd_u.c: type2string(): added SD2 to file types * InOut/rtpa.c: print warning if the buffer size (-b) is not an integer multiple of ksmps in full-duplex mode * InOut/window.c: moved deferred loading of widgets plugin from main.c to make graphs work in utilities * Opcodes/compress.c: made rms levels relative to 0dBFS in distort opcode * H/csoundCore.h, Top/csound.c: added dispinit() function pointer to CSOUND structure, for use by utilities * H/version.h: updated API version to 1.01 to reflect change to CSOUND structure * util/pvanal.c: implemented graph displays (limited to 30 frames at this time) * util/sndinfo.c: clear SF_INFO structure before calling sf_open() 2006-04-08 Istvan Varga * OOps/sndinfUG.c: restored filepeak opcode 2006-04-07 Istvan Varga * H/version.h: updated version number to 5.02.0 to reflect addition of new opcodes * Opcodes/compress.c: fixed a few minor errors 2006-04-04 Michael Gogins * Changed FluidSynth opcodes slightly, with fluidEngine iChorusOn, iReverbOn pfields, defaulting to "on"; this can reduce noise in low frequencies in SoundFont rendering. * Updated Windows FluidSynth opcodes to use latest FluidSynth sources. 2006-03-28 jpff * Opcodes/compress.c: New code for distort and compress/expander from Barry Vercoe 2006-03-25 Istvan Varga * Engine/entry1.c, H/aops.h, H/entry1.h, OOps/bus.c, opcodes.dir, Opcodes/pitch.c, Opcodes/pitch.h, Opcodes/spectra.c, Top/csound.c: fixes in sensekey opcode 2006-03-22 Michael Gogins * Added ScoreGeneratorVST, a VST plugin for generating scores in VST hosts using Python. * Updated Windows installer for new targets, including Winsound. 2006-03-22 Istvan Varga * interfaces/cs_glue.cpp: * interfaces/cs_glue.hpp: - added new classes to wrap MIDI I/O: CsoundMidiInputStream sends MIDI input messages CsoundMidiOutputStream polls MIDI output messages - added MIDI I/O callbacks to CsoundCallbackWrapper - made it possible to use the message buffer in multiple threads, to allow for redirecting the message output of a CsoundPerformanceThread 2006-03-21 Istvan Varga * SConstruct, Makefile-win32: renamed Csound library to csound{32,64}.dll.5.1 on Windows * SConstruct: attempts to fix install target (still needs a lot of work) * Engine/namedins.c, OOps/bus.c: fixed a-rate channel allocation in user defined opcode with local ksmps * Engine/linevent.c: various minor fixes and code improvements 2006-03-16 Istvan Varga * Updated version number to 5.01.1 beta. * Opcodes/sftype.h: check for MacOS 9 or PowerPC, and define WORDS_BIGENDIAN on those platforms. 2006-03-13 Anthony Kozar * Top/main.c: Made TYP_AIFF the default for MacOS 9. * Engine/entry1.c: Removed duplicate OENTRYs. 2006-03-12 jpff * Opcodes/bilbar.c (bar_run): Corrected boundary condition 2006-03-11 Istvan Varga * Engine/express.c: fixes in extending tokenstring buffer 2006-03-10 Anthony Kozar * Opcodes/minmax.c: * SConstruct: Added new 'minmax' plugin library with opcodes for finding minimum and maximum values among several signals. 2006-03-10 Michael Gogins * CSD style command lines in CsoundVST are now translated to orc/sco style before performance in order to save having to edit the command line after loading some CSD files. 2006-03-08 Istvan Varga * Made it possible to load opcode plugins only when the opcode is actually used. 2006-03-07 jpff * Engine/otran.c: Removed DTYPE and lclnxtdcnt as not used 2006-02-25 Michael Gogins * Updated SConstruct, custom.py, and Windows installer to build and install PortMidi. 2006-02-24 Istvan Varga * InOut/rtjack.c: Use thread locks instead of calling usleep() in a loop to implement blocking I/O; the -+jack_sleep_time option is now deprecated and ignored. Allow non power of two values for -B. Setting -b to the same value as the JACK buffer size is no longer required. * Engine/insert.c: * Engine/musmon.c: Alternate fix to problems on very short (less than 1/2 control period) notes; the previous fix introduced a new bug that resulted in early termination of the score in some cases. * H/version.h: * installer/misc/csound.spec.in: Updated version number from 5.00.1 to 5.01.0 to reflect the addition of new opcodes. 2006-02-24 Victor Lazzarini * Opcodes/psynth.c new track processing opcodes (also added manual pages): trscale, trshift, trsplit, trmix, trfilter, trcross, trhighest, trlowest, binit. 2006-02-15 Istvan Varga * InOut/widgets.h: moved file from H/ * InOut/widgets.cpp: bug fixes in FLsetVal and FLsetVal_i allow buttons and button banks in FLsetVal fixed handle output of FLbutBank (not sure if this is safe) implemented cursor size parameter for FLknob 2006-02-13 Istvan Varga * OOps/ugrw1.c: fixed bugs in i-rate ZAK opcodes 2006-02-09 Istvan Varga * Engine/rdorch.c: splitline(): made checking for invalid characters stricter fixed labels before else/endif allow bitwise NOT operator in UTF-8 format 2006-02-06 Istvan Varga * Engine/entry1.c: cogoto requires an i-rate conditional * Engine/musmon.c: fixed hang on very short note before end of score or section * Engine/rdorch.c: added hacks to fix the problem of the else branch of an if/then/else always being executed at i-time. Fixed crash on 'then' or 'goto' in variable names in conditional expression for if/elseif (still does not work if there are no parentheses around the conditional expression). 2006-02-03 Istvan Varga * Engine/rdorch.c: fixed crash on extra ) in expressions * Engine/rdorch.c: fixed crash on missing whitespace between if/elseif and ( this needs more testing 2006-01-25 Istvan Varga Anthony Kozar * Opcodes/mixer.cpp: "OpcodeBase.hpp", not * Opcodes/py/pythonopcodes.c: Added support for MacOS 9 Python quirks. * H/sysdep.h: MacOS 9 changes so that Python stuff will compile. 2006-01-11 Istvan Varga * fixed temporary file bug on Windows (do not try to remove extension) * new opcodes: chnmix asig, Schn (mixes to audio output channel) chnclear Schn (clears audio output channel at perf time) * allow dot in channel names (but not as first character) 2006-01-04 Michael Gogins * Updated Windows installer script to be compatible with Istvan Varga's zip file layout; also includes vst4cs, csoundapi~, FluidSynth opcodes, CsoundVST, tclcsound, Loris opcodes, STK C++ opcodes. Also includes manual and API reference. Now uses Python 2.4. 2006-01-04 Istvan Varga * changed default output file type to AIFF on MacOS X * added support for writing MIDI output to a file (--midioutfile=FNAME); not really useful, so may be removed later * various fixes related to creating temporary files 2006-01-03 Istvan Varga * added new optional argument to massign (defaults to 1), which, if zero, skips resetting of MIDI controllers * fixed bugs in pan opcode * added support for named instruments to turnon opcode 2005-12-28 jpff * Engine/fgens.c (gen01raw): Restore looping stuff, which requires libsndfile 1.0.13pre3 or later, so protected by BETA still 2005-12-19 John ffitch * SConstruct (else): Added -fPIC again for 64bit machines (else): Fix path for python for 64bit machines * Opcodes/fluidOpcodes/fluidOpcodes.cpp (fluidLoadIopadr): Cast to int to avoid error (csoundModuleDestroy): Ditto 2005-11-12 Michael Gogins * Removed csoundThrowMessage APIs as redundant with csoundMessage, and not used. * Removed strdup and boost from all but CsoundVST. * Fixes in interfaces and frontends/CsoundVST so that CsoundVST works again. 2005-11-03 Istvan Varga * Changed csoundInitialize() to return a positive value if it was already called earlier. 2005-11-01 Istvan Varga * Removed support for Cygwin. * Fixes in Python opcodes. Also implemented a temporary hack in Top/csmodule.c to fix importing modules from Python opcodes on Linux. * installer/linux/csound.spec.in: * installer/linux/makespec.sh: * installer/linux/mkpackage.py: preliminary tools for creating Linux packages 2005-10-31 Michael Gogins * Moved external language interfaces from frontends/CsoundVST into interfaces directory. * Created interfaces for Python, Java, Lua (all "csnd" module). Wraps H/csound.h, H/cfgvar.h, H/csound.hpp, interfaces/CsoundFile.hpp, interfaces/CppSound.hpp. * Moved CLisp interface to interfaces directory. Wraps H/csound.h (csound.lisp) and interfaces/filebuilding.h (filebuilding.lisp). * Modified CsoundVST to work with "csnd" Python module. * Removed Java interface from CsoundVST. * The Java interface in csnd.jar has a rudimentary GUI front end: run with "java -jar csnd.jar". * Other interfaces have test scripts in interfaces directory. 2005-10-25 John ff * SConstruct: Make building interfaces optional 2005-10-05 Victor Lazzarini * Added Tcl/TK frontends (cstclsh and cswish) 2005-10-15 Michael Gogins * Fixed SConstruct to build CsoundVST using Csound as a shared library. * Added csound.lisp FFI for CLisp (experimental). 2005-10-15 Anthony Kozar * Top/csmodule.c: Implemented csoundOpenLibrary, csoundCloseLibrary, and csoundGetLibrarySymbol for platform (mac_classic). 2005-10-13 John ff * InOut/OSCrecv.c: Many changes to allow listening on multiple ports. Uses same patterns though. 2005-10-12 Anthony Kozar * Top/cscorfns.c: cscoreGetEvent(): Check for file closed to avoid loop. csoundInitializeCscore(): Set next->op = '\0'. * Top/one_file.c: createOrchestra(), createScore(): Make messages debug only. * Opcodes/gab/vectorial.c: Fixed small bugs in checking table size. 2005-10-11 Anthony Kozar * H/cscore.h, Top/cscorfns.c, Top/cscore_internal.c: Renamed all Cscore functions that are to be exported in the "Cscore API". Made all of these take a CSOUND* argument if they did not yet. Added some glue for cscoreListPlay() (not done yet though). * H/csound.h, H/prototyp.h, Engine/musmon.c: Added new API function csoundInitializeCscore() to replace internal cscorinit() call. It sets up the input/output files for Cscore and allows a host to function in "standalone Cscore" mode. * Top/cscormai.c: Transformed this main() stub for standalone Cscore processing into a client of the API. (Still needs more work!) 2005-10-09 John ff * Opcodes/psynth.c (psynth2_init, psynth_init): Added cast to unsigned to avoid compiler warnings. Also change && to || as I think that is more likely correct. 2005-10-07 Anthony Kozar * H/csound.h, H/csoundCore.h, Top/csound.c, Engine/musmon.c: Added new API function csoundSetCscoreCallback() for using an external cscore routine. * SDIF/sdif-mem.h: Changed #include "H/sdif.h" to "sdif.h". 2005-10-02 Istvan Varga * restored Tcl/Tk control opcodes * xyin fixes 2005-09-30 Istvan Varga * new API functions for random numbers: csoundRand31(), csoundSeedRandMT(), csoundRandMT() * removed all uses of rand(), csoundRandMT() is used instead in the "x-class" random opcodes and GEN21, and csoundRand31() in all other opcodes that previously used rand() * attempts to get xyin working 2005-09-25 Istvan Varga * frontends/CsoundVST/CppSound.cpp, frontends/CsoundVST/CppSound.hpp: * frontends/CsoundVST/CsoundVST.cpp: * flcsound/synthesizer.cpp: * H/csoundCore.h, H/csound.h, Top/csound.c: removed the following API functions: csoundSetFLTKThreadLocking() (FLTK moved out of libcsound) csoundGetFLTKThreadLocking() (FLTK moved out of libcsound) csoundGetProgress() (was unimplemented) csoundGetProfile() (was unimplemented) csoundGetCpuUsage() (was unimplemented) * InOut/FL_graph.cpp, InOut/widgets.cpp, InOut/winFLTK.c: * InOut/window.c, Makefile-win32, SConstruct: moved FLTK display code from libcsound to the widgets plugin 2005-09-22 Istvan Varga * frontends/csound/csound_main.c: allow logging to file (-O NAME or --logfile=NAME) * frontends/csound/sched.c: --sched can be used in the format --sched=P,C,T now, where the parameters are: P: priority (-20 to -1: nice, 0: normal, 1 to 99: SCHED_RR) C: maximum allowed CPU usage (1 to 99 percents) T: time interval to check CPU usage (1 to 60 seconds) 2005-09-18 Istvan Varga * Engine/namedins.c, H/csound.h: more complete implementation of bus interface (may still need some changes) * Engine/entry2.c, H/str_ops.h, OOps/str_ops.c: new opcodes 2005-09-17 Istvan Varga * Engine/namedins.c: started to implement bus with named channels; this is not complete yet * Engine/oload.c, Engine/otran.c, Top/csound.c: moved some parts of oload.c to otran.c while others to csound.c removed oload.c * H/csound.h, H/csoundCore.h: new API functions, and variables in CSOUND structure * Engine/otran.c, Top/csmodule.c, Top/csound.c, Top/utility.c: improved warning message for undefined OPCODEDIR/OPCODEDIR64 * Top/csound.c, Top/one_file.c: new command line flag (-+ignore_csopts) to disable the use of options specified in a CSD file one_file.c: minor fixes in parsing CSD files 2005-09-01 Michael Gogins * Added CsoundVST.Soundfile wrapper class for Python access to libsndfile. 2005-09-01 Istvan Varga * Top/csmodule.c: revised code for loading plugin libraries new function: csoundModuleInfo() can be used in plugin libraries to allow for checking API version and MYFLT type * Top/dl_opcodes.c: merged into csmodule.c; removed file * Engine/oload.c, H/csoundCore.h, OOps/ugens3.c, OOps/ugens5.c: removed static variables from ugens3.c and ugens5.c * Top/csound.c: removed adsyn/lpc RESET routines that are no longer needed * Opcodes/hrtferX, Opcodes/natben.c, Top/natben.c, SConstruct: removed unused endianness conversion code * SConstruct: fixed bug that broke building libcsound as a shared library 2005-08-30 Istvan Varga * Opcodes/ugnorman.c: renamed opcodes from ats* to ATS* to avoid namespace pollution 2005-08-28 Istvan Varga * Opcodes/ugnorman.c, Opcodes/ugnorman.h: new opcodes 2005-08-22 Istvan Varga * Engine/musmon.c, H/csound.h, InOut/libsnd.c, Top/csound.c: new API function: csoundSetHostImplementedAudioIO() allows the host application to implement sound I/O with direct access to the spin/spout buffers (or, with a non-zero buffer size parameter and using csoundPerformBuffer(), the input/output buffers), ignoring any -i, -o, -b, and -B options * H/csound.h, H/csoundCore.h, Top/threads.c: added return value to csoundWaitThreadLock(); non-zero if the function returns on timeout instead of the lock being notified 2005-08-20 Istvan Varga * Engine/oload.c, H/csound.h, H/csoundCore.h, Top/threads.c: new API function: csoundWaitThreadLockNoTimeout() similar to csoundWaitThreadLock(), but with infinite timeout, allowing for a possibly more efficient implementation * Top/threads.c: csoundWaitThreadLock(): implemented timeout for Linux * H/csoundCore.h, H/envvar.h, SConstruct: removed envvar.h from installation 2005-08-19 Istvan Varga * Engine/namedins.c, Engine/otran.c, Engine/rdorch.c: * Opcodes/fout.c, Opcodes/oscbnk.c: removed unneeded/redundant RESET code * H/csound.h, H/csoundCore.h, Top/threads.c: * InOut/rtpa.c, InOut/widgets.cpp, InOut/OSCrecv.c, Opcodes/OSC.c: attempts to clean up thread interface * H/prototyp.h: moved declaration of csoundYield() here from csound.h * examples/fl_controller/fl_controller.cpp: fixed a few minor errors 2005-08-18 Istvan Varga * Engine/namedins.c: * Top/csound.c: * Top/main.c: changes to allow host applications to register opcodes with csoundAppendOpcode(); should be called between csoundPreCompile() and csoundCompile() * Engine/oload.c: * H/csound.h: * H/csoundCore.h: removed csoundLoadExternal() and csoundLoadExternals() from public interface * H/opcode.h: removed file * Top/opcode.c: implemented csoundNewOpcodeList() and csoundDisposeOpcodeList() currently, the opcodes can only be listed after loading an orchestra with csoundCompile() 2005-08-12 Istvan Varga * renamed struct ENVIRON_ to struct CSOUND_, and ENVIRON to CSOUND * replaced uses of void* Csound instance pointers with CSOUND* * changes to header files to clean up the API; more need to be done * attempts to fix CsoundVST build - still not quite right 2005-08-03 Steven Yi * Engine/Entry1.c, Engine/fgens.c, H/ftgen.h: New ftfree opcode, takes in table number and free time arg, if zero frees at opcode init time, otherwise at opcode deinit time 2005-08-01 Istvan Varga * Minor fixes in DSSI opcodes (still have problems) * Engine/rdorch.c, Engine/entry1.c, Opcodes/uggab.c: minor parser changes, including the addition of a new code (fffb) for selecting opcode name based on the first input argument (i-, k-, and a-rate, but not constant) * Engine/insert.c: fixes related to re-initialisation of user defined opcodes * Engine/Entry2.c, H/str_ops.h, OOps/str_ops.c: new opcodes: printf, printf_i * Engine/Entry2.c, H/insert.h, OOps/goto_ops.c: new opcodes: loop_l, loop_le, loop_g, loop_ge 2005-07-31 John ff * SConstruct (opts): Added buildDSSI option 2005-07-23 John ff * Opcodes/bowedbar.c (bowedbarset): ADSR not initialised correctly. Still has over hash attack. Also adjust gain. 2005-07-17 Istvan Varga * Engine/rdorch.c: fixed crash on missing endin * Engine/rdorch.c, Engine/sread.c: fixed error message on $ without macro name * H/diskin.h, OOps/diskin.c: fixed soundout crash on Win32 with doubles 2005-07-15 Istvan Varga * removed use of cs.h; replaced with csoundCore.h * util1/sortex/smain.c, util1/sortex/xmain.c: fixed compiler warnings * OOps/diskin2.c: minor fixes in soundin and diskin2 * Engine/entry1.c: added soundouts; diskin extended to 24 channels * H/diskin.h, OOps/diskin.h: replaced diskin with new implementation based on diskin2 (should fix many problems, and allows up to 24 channels instead of the original limit of 4) fixed bug in soundout that resulted in not writing the last buffer to disk implemented soundouts opcode (stereo soundout) * Engine/fgens.c: fixed memory error in GEN20 * Engine/rdorch.c: minor fix in parsing of comments 2005-07-13 Istvan Varga * InOut/midirecv.c: reset controllers 7-11 to 0 in raw controller mode 2005-06-25 Victor Lazzarini * Added Opcodes/partials.c and Opcodes/psynth.c, streaming spectral partial track analysis/synthesis opcodes. 2005-06-23 Victor Lazzarini * Improvements/Fixes to rtcoreaudio.c, addition of non-interleaved audio support * Added Opcodes/ifd.c, Instantaneous Frequency Distribution spectral streaming opcode. 2005-06-23 John ffitch * Engine/sread.c (sread): Do not attempt to read a name in r if at end of line 2005-06-21 John ffitch * Opcodes/biquad.c (biquada, biquad, biquadset): * OOps/ugens5.c (porset, port, tonset, tone, tonsetx, tonex, atone, atonex, rsnset, reson, rsnsetx, resonx, areson): Work in doubles internally 2005-06-20 John ffitch * InOut/OSCrecv.c (OSC_listdeinit): Fixed a typo 2005-06-15 John ff * InOut/OSCrecv.c: New file for OSC listening 2005-06-15 John ffitch * SConstruct: Fixed TAGS so it looks at C files as well 2005-06-13 Victor Lazzarini * Top/dl_opcodes.c: commented out old code that was causing conflict on OSX 10.4 2005-06-09 Victor Lazzarini * InOut/rtcoreaudio.c : further improvements to coreaudio RT IO 2005-06-03 Istvan Varga * Engine/oload.c: * H/csoundCore.h: added (some) PVOC related functions to API * OOps/pvfileio.c: extensively revised code (needs testing): use ANSI C functions for file I/O, removed dependencies on sizeof(long)==4 and endianness, removed limit on number of files * util/pvanal.c: allow the use of PVOC-EX format again (still no displays though) 2005-06-03 Victor Lazzarini * OOps/pvfileio.c: removed statics and added csound* to functions; changed all relevant function calls elsewhere in the code to match the new prototypes 2005-06-01 Victor Lazzarini * Opcodes/pvsbasic.c pvsbasic.h added opcode pvsinit for fsig initialisation 2005-05-31 Istvan Varga * Engine/otran.c: allow global f-signals code changes for faster name lookup in global/local pools * Engine/rdorch.c: store line numbers in variables of type 'int' rather than 'short' TODO: clean up file reading (correct handling of EOL characters, use csoundFileOpen(), do not depend on being able to call ungetc() multiple times) probaly the same needs to be done in sread.c as well * H/oload.h: removed many unused typedefs and macros * OOps/fftlib.c: fixed crash on 64 bit platforms minor code changes 2005-05-30 Istvan Varga * New API functions: csoundAppendOpcodes(): appends a list of opcodes (OENTRY*) csoundRegisterResetCallback(): adds a function to be called by csoundReset() * Top/dl_opcodes.c: unload plugin opcodes (called from csoundReset()) * Top/dl_opcodes.c, Top/main.c: use API functions for adding opcodes, rather than changing opcodlst directly 2005-05-30 Michael Gogins * CsoundVST now supports multiple instantiation of VST plugins; it is not completely stable yet. * The Mixer opcodes now support multiple instantiation of Csound. * OpcodeBase.hpp now works with the new OENTRY structure. The OpcodeBase class now automatically registers a deinit callback, which by default does nothing. * The C++ STK opcodes now use RegisterDeinitCallback and the csoundModule* initialization and deinitialization routines. 2005-05-27 Steven Yi * Opcodes/fluidOpcodes/fluidOpcodes.cpp: modified fluidNote to use RegisterDeinitCallback, removed krate function call 2005-05-27 Istvan Varga * Added new API functions: csoundListUtilities(): returns alphabetically sorted list of registered utilities csoundSetUtilitiyDescription(): sets description text for an utility csoundGetUtilitiyDescription(): returns description text of an utility csoundRegisterDeinitCallback(): registers a function to be called at note deactivation csoundLoadSoundFIle(): loads an entire sound file into memory (similar to ldmemfile()) * Removed OENTRY.dopadr, and all related code, as it is not really needed now (can use csoundModuleDestroy and RegisterDeinitCallback instead). 2005-05-25 Istvan Varga * Engine/insert.c: fixed bug in ihold opcode * Engine/rdorch.c: attempts at fixing else and endif bugs * Added new macros (MYFLT2LONG and MYFLT2LRND) for converting floating point values to integers. 2005-05-24 Victor Lazzarini * changes to rtcoreaudio.c to enable channel independence 2005-05-23 Victor Lazzarini * late entry to the log: added InOut/rtcoreaudio.c * late entry to the log: added Opcodes/sndloop.c (sndloop, flooper, pvsarp, pvsvoc) * late entry to the log: fixed globals in rtpa.c * late entry to the log: added full-duplex support to the portaudio module (rtpa.c pa_blocking.c), aimed primarily at coreaudio 2005-05-23 Steven Yi * Engine/rdorch.c (splitline): Ported over ithen check from Csound4 source, added ithen to IFLABEL struct accordingly 2005-05-17 John ffitch * Engine/swrite.c (swrite): Charge to expand "s #" and "e #" to "f0 #\ns" 2005-05-16 Anthony Kozar * Top/argdecode.c: * Top/csound.c: * Top/main.c: * Engine/filopen.c: * Engine/insert.c: * Engine/linevent.c: * Engine/musmon.c: Converted mills_macintosh to mac_classic or MAC as appropriate or removed code if dependent on Mills globals. 2005-05-15 Anthony Kozar * Top/getstring.c: #include "cs.h", not * Top/threads.c: Added stubs for csound*ThreadLock functions. * Engine/envvar.c: Fixes for MacOS pathnames (more may be needed). 2005-05-15 John ffitch * Top/main.c: Prototype for mytmpnam 2005-05-14 John ffitch * Top/argdecode.c (decode_long): Allow definition of macros * Engine/sread.c (init_smacros): * Engine/rdorch.c (init_omacros): New functions to define macros 2005-05-11 John ffitch * Opcodes/ugmoss.c (valpass): Added cache of p->maxlpt to avoid overwriting arguments 2005-05-08 Michael Gogins * Added examples/Orbifold.py, an interactive display of the 3-dimensional orbifold of all close voice-leadings between 3-tone chords (based on the work of Professor Dmitri Tymoczko of Princeton). Also demonstrates controlling Csound from Python for real-time performance, and the use of 3-dimensional graphics for constructing graphical user interfaces. 2005-05-07 Istvan Varga * Opcodes/biquad.c: * Opcodes/biquad.h: added new optional argument to distort1 opcode (defaults to zero), to select amplitude scaling mode (0: default, compatible with original version; 1: relative to 0dBFS, same as mode 0 if 0dbfs is 32768; 2: unscaled) code changes to improve performance of some opcodes: biquad, vco, pareq, and distort1 improved vco opcode for more accurate output * Engine/rdorch.c: * OOps/aops.c: '=.a' opcode is automatically replaced with 'upsamp' if input is not a-rate, the actual a-rate version has been simplified, and '=' is removed by the parser if the output argument is the same as the input * OOps/ugens6.c: deltapx/deltapxw revised for speed 2005-05-06 Istvan Varga * H/msg_attr.h: * Top/csound.c: new message attributes: CSOUNDMSG_WARNING, CSOUNDMSG_FG_UNDERLINE * Engine/entry2.c: * H/ugens6.h: * OOps/ugens6.c: added new optional argument to delayr and all deltap opcodes, to allow delay taps to read from any of the nested delayr/delayw pairs, not just the last (from Csound 4.23.4.1) 2005-05-05 Istvan Varga * Engine/entry1.c: * Engine/express.c: added k() function for converting i-rate values to k-rate 2005-05-01 Istvan Varga * H/csound.h: * Top/threads.c: new functions: csoundLock(), csoundUnLock() * Top/argdecode.c: added ENVIRON* argument to usage() and dieu() * Top/csound.c: * Top/main.c: - maintain a global list of allocated Csound instances, delete all on exit or fatal signal - new interface function: csoundInitialize(), for global initialisation of Csound library; if not done yet, the first call of csoundCreate() will also call csoundInitialize() - moved signal handler from main.c to csound.c (still not quite right, should really be done by host application) - removed some unused/useless static variables 2005-04-30 Istvan Varga * removed global variable O - use csound->oparms instead * Top/csound.c: - dynamically allocate and destroy Csound instances, rather than using cenviron. Some old code still uses cenviron (and is thus now broken), and should be revised. - made calls to deprecated functions csoundPrintf() (#defined as printf()) and err_printf() fatal errors. 2005-04-29 Istvan Varga * removed all static variables from Engine/sread.c 2005-04-30 Michael Gogins * Disabled GUI options for Python mode and for auto-play when in VST plugin mode, to prevent side effects. * Improved version of CsoundVST.csd orchestra for VST plugin use, using the Csound mixer and some effects. * Updated CsoundVST for removal of various static variables in Csound. 2005-04-24 John ffitch * Top/one_file.c (read_unified_file): Added licence top level field 2005-04-23 John ffitch * SConstruct (guiProgramEnvironment): Need dl and pthreads even without FLTK 2005-04-14 Michael Gogins * Added (very) basic Java GUI front end for Csound. It is the main class in CsoundVST.jar. To be extended. The purpose of this work is to embed Csound5 in Kandid, an interactive graphics program for evolving pictures, and adapt Kandid for evolving pieces. 2005-04-18 Istvan Varga * Top/utility.c, H/cs_util.h: new files for dynamically loading utilities * cvanal.c, dnoise.c, hetro.c, lpanal.c, pvanal.c, pvlook.c, sndinfo.c: moved from Top/ to util/ utilities converted to plugin libraries (not done yet for hetro, lpanal, and pvlook; also pvanal is limited to old format for now) * H/pvoc.h, OOps/pvoc.c: moved functions only used by pvanal to pvanal.c * H/prototyp.h: removed prototypes for utilities * Engine/oload.c, H/csoundCore.h, Top/argdecode.c: ENVIRON: API functions for adding and running utilities changed command line parser for new utility API 2005-04-16 John ffitch * InOut/libsnd.c (sfopenin): Changed in and out channel mismatch to a warning. Trest with care! 2005-04-14 Michael Gogins * Changed CsoundVST to print log messages to stderr (used to be stdout) by default. * Added option to CsoundVST to automatically open the output soundfile for editing or listening at end of performance. * Upgraded Windows installer to set OPCODEDIR, RAWWAVE_PATH, PYTHONPATH, and PATH environment variables (uninstall does not work for PYTHONPATH). 2005-04-12 John ffitch * Opcodes/wave-terrain.c (wtPerf): Improved phase accumulation problem 2005-04-10 Michael Gogins * Updated the STK opcodes to take from 0 to 4 optional krate controller-value pairs. 2005-04-10 John ff * OOps/ugens2.c (itabl3): Missing return 2005-04-09 Michael Gogins * Added "STKName" (e.g. "STKBowed") opcodes for all Perry Cook's Synthesis Toolkit in C++ (STK) 4.2.0 instruments in his "demo" program, using Cook's original C++ code with minimal wrapping (about 25 opcodes, varying in quality from mediocre to very good). To build the opcodes, copy the STK sources into the csound5/Opcodes/stk directory, as instructed in SConstruct. All opcodes have the same signature: asignal STKName ifrequency iloudness {kcontroller kvalue} The RAWWAVE_PATH environment variable must be set to point to the directory containing the "rawwaves" samples. 2005-04-09 John ffitch * InOut/libsnd.c (sndinset): * H/soundio.h: * InOut/libsnd_u.c (sndgetset): Fix skipinit for soundin 2005-04-06 Istvan Varga * Engine/fgens.c: use csound->Message() instead of printf() added ENVIRON* pointer and variable arg list to fterror() replaced use of deprecated FFT functions with csound->RealFFT() limited line length to 80 characters * Engine/oload.c: * H/cs.h: * H/csoundCore.h: removed deprecated functions from ENVIRON: err_printf, IsPowerOfTwo, FFT2torlpacked, FFT2realpacked, cxmult, csoundPrintf * H/fft.h, H/ugens9.h, OOps/disprep.c, OOps/dsputil.c, OOps/fft.c: * OOps/pvinterp.c, OOps/pvread.c, OOps/ugens8.c, OOps/ugens9.c: * OOps/vpvoc.c, Opcodes/oscbnk.c, SConstruct, Top/cvanal.c: * Top/pvanal.c: removed deprecated FFT functions; use fftlib.c interface instead * H/prototyp.h: declare err_printf and csoundPrintf here (deprecated functions) * InOut/widgets.cpp: use csound->Message() instead of csound->Printf() * Top/csound.c: deprecated functions: err_printf, csoundPrintf * Top/main.c: do not call fftRESET() (this function was removed) err_printf moved to Top/csound.c 2005-04-05 Istvan Varga * Engine/sread.c: * H/sort.h: attempts to fix bugs in reading large score files * Engine/namedins.c, Engine/oload.c, H/csdl.h, H/cs.h, H/csoundCore.h: * H/namedins.h, H/OpcodeBase.hpp, H/prototyp.h, H/sftype.h, H/ugrw1.h: * OOps/ugens9.c, OOps/ugrw1.c, Opcodes/babo.h, Opcodes/biquad.h: * Opcodes/brass.h, Opcodes/dam.h: * Opcodes/fluidOpcodes/fluidOpcodes.cpp, Opcodes/Loris/lorisgens5.h: * Opcodes/pitch0.c, Opcodes/py/csoundmodule.c, Opcodes/spat3d.h: * Opcodes/vst4cs/src/vst4cs.h, Opcodes/vst4cs/src/vsthost.h: * Opcodes/wave-terrain.h: minor header changes removed some macros * H/csoundCore.h: * OOps/aops.c: fixed crash in cpsoct() and similar functions on out of range arg 2005-04-03 Steven Yi * SConstruct: added arch and cpu commandline options to fine tune gcc3opt flags for -march and -mcpu 2005-04-03 Istvan Varga * removed macro definitions for ksmps, esr, ekr, and some others; use csound->Message() instead of printf() and err_printf(); (large number of changes in many files) * Engine/namedins.c: * Engine/express.c: removed static and global variables 2005-03-31 Istvan Varga * Engine/entry1.c: * OOps/aops.c: added a-rate int() and frac(), and round(), floor(), and ceil() * Engine/express.c: * Engine/rdorch.c: * Top/main.c: * H/prototyp.h: added << and >> operators, fixed order of precedence express(), expRESET(): use ENVIRON *csound pointer use less obvious label names for if...then * Engine/oload.c: * H/csoundCore.h: * Top/csound.c: moved static invalue/outvalue function pointers to ENVIRON * Opcodes/ugmoss.c: implemented << and >> shift operators fixed bitwise OR at k- and a-rate 2005-03-31 John ffitch * Engine/express.c: Removed statics to environment structure 2005-03-30 Istvan Varga * Engine/oload.c: * Engine/twarp.c: * H/csoundCore.h: * InOut/libsnd_u.c: * OOps/fftlib.c: * OOps/fout.c: * OOps/sdif.c: * Top/csound.c: minor fixes; removed a few more static variables * Engine/express.c: * Engine/rdorch.c: * Opcodes/ugmoss.c: fixed binary operators * OOps/ugrw1.c: fixed printk2 opcode 2005-03-30 John ff * Engine/swrite.c: Remove statics from swrite.c * Engine/oload.c: * Engine/twarp.c: Removed statics from file twarp.c 2005-03-29 Istvan Varga * more API changes (affecting a large number of files) * Opcodes/newfils.c: fixed statevar bug 2005-03-28 Istvan Varga * Engine/auxfd.c, Engine/fgens.c, Engine/insert.c, Engine/oload.c: * H/csdl.h, H/csoundCore.h, H/prototyp.h, InOut/pa_blocking.c: * InOut/rtpa_new.c, InOut/widgets.cpp, OOps/aops.c, OOps/diskin2.c: * OOps/disprep.c, OOps/midiops.c, OOps/pstream.c, OOps/pvadd.c: * OOps/pvinterp.c, OOps/pvread.c, OOps/pvsanal.c, OOps/schedule.c: * OOps/ugens1.c, OOps/ugens2.c, OOps/ugens3.c, OOps/ugens4.c: * OOps/ugens5.c, OOps/ugens6.c, OOps/ugens8.c, OOps/ugens9.c: * OOps/ugrw1.c, OOps/vbap_eight.c, OOps/vbap_four.c: * OOps/vbap_sixteen.c, OOps/vbap_zak.c, OOps/vdelay.c, OOps/vpvoc.c: * Opcodes/babo.c, Opcodes/bbcut.c, Opcodes/biquad.c: * Opcodes/bowedbar.c, Opcodes/cross2.c, Opcodes/filter.c: * Opcodes/flanger.c, Opcodes/fm4op.c, Opcodes/freeverb.c: * Opcodes/ftconv.c, Opcodes/gab/gab.c, Opcodes/gab/vectorial.c: * Opcodes/grain4.c, Opcodes/grain.c, Opcodes/locsig.c: * Opcodes/mandolin.c, Opcodes/metro.c, Opcodes/midiops2.c: * Opcodes/midiops3.c, Opcodes/modal4.c, Opcodes/moog1.c: * Opcodes/nlfilt.c, Opcodes/oscbnk.c, Opcodes/physmod.c: * Opcodes/physutil.c, Opcodes/pitch.c, Opcodes/pluck.c: * Opcodes/pvsbasic.c, Opcodes/pvsdemix.c, Opcodes/repluck.c: * Opcodes/reverbsc.c, Opcodes/scansyn.c, Opcodes/scansynx.c: * Opcodes/seqtime.c, Opcodes/sfont.c, Opcodes/singwave.c: * Opcodes/sndwarp.c, Opcodes/space.c, Opcodes/spat3d.c: * Opcodes/spectra.c, Opcodes/syncgrain.c, Opcodes/ugens7.c: * Opcodes/ugensa.c, Opcodes/uggab.c, Opcodes/ugmoss.c, Opcodes/ugsc.c: * Opcodes/vdelayk.c, Opcodes/wave-terrain.c, Top/csound.c: API changes * OOps/diskin2.c: minor optimization in init routine * Opcodes/ugens6.c: * util2/mixer/extract.c: removed unused files 2005-03-27 Istvan Varga * SConstruct: * InOut/libsnd.c: * InOut/rtpa_new.c: new PortAudio plugin (enabled by useOldPortAudioPlugin=0) * Engine/entry2.c: * Engine/insert.c: * H/insert.h: new opcode: turnoff2 (can turn off other instruments) 2005-03-25 Istvan Varga * InOut/midirecv.c: * Engine/express.c: * Engine/fgens.c: fixed compiler warnings * OOps/diskin.c: * Engine/entry1.c: use diskin2 functions to emulate diskin * Opcodes/hrtferX.c, Top/dnoise.c, Top/cvanal.c, Opcodes/oscbnk.c: * Engine/fgens.c, OOps/ugens9.c, H/ugens8.h, H/pvinterp.h: * H/vpvoc.h, H/disprep.h, Top/pvanal.c, OOps/ugens8.c: * OOps/vpvoc.c, OOps/pvinterp.c, OOps/disprep.c, Engine/oload.c: * H/csdl.h, H/fft.h, OOps/fft.c, H/csoundCore.h: removed redundant (and often slow) FFT code * Top/dnoise.c: fixed sound file output * InOut/libsnd.c: print message correctly when closing output file * H/diskin.h: * OOps/dnfft.c: removed files 2005-03-23 Istvan Varga * OOps/ugens2.c: * Opcodes/biquad.c: * Opcodes/lowpassr.c: * Top/one_file.c: minor fixes 2005-03-22 Istvan Varga * H/diskin2.h: * OOps/diskin2.c: various minor code changes * Top/one_file.c: fixed CsFileB tag * util1/csd_util/base64.c: * util1/csd_util/cs.c: * util1/csd_util/csb64enc.c: * util1/csd_util/makecsd.c: new utilities 2005-03-21 Istvan Varga * Engine/entry1.c: * H/diskin2.h: * OOps/diskin2.c: new opcode * InOut/libsnd_u.c: * OOps/sndinfUG.c: bug fixes in opening sound files * OOps/diskin.c: fixed (partly) clicks in multichannel input; still some bugs * H/soundio.h: fixed soundin crash (was actually caused by unused SOUNDIN.kfrqratio) 2005-03-21 John ffitch * Engine/sread.c (MARGIN): Increase to 600, but needs to be rethought 2005-03-18 Istvan Varga * Engine/oload.c: * H/csoundCore.h: * H/fftlib.h: * OOps/fftlib.c: minor code changes related to FFT functions * Opcodes/ftconv.c: removed use of direct convolution due to patent issues * H/csdl.h: removed some unused macros (fewer is better) * Engine/fgens.c: minor GEN52 fix 2005-03-15 Michael Gogins * The Loris opcodes now work. * Removed pyrun.dll and -lswigpy from SConstruct, as SWIG 1.3.24 (current stable version) does not use it. * The Java wrappers are now built as a jar containing the CsoundVST package. * Added option to not build Java wrappers; as a result, CsoundVST builds on Linux again. * Removed documentation from the Windows installer. 2005-03-15 John ffitch * H/soundio.h (SOUNDIN): * InOut/libsnd.c (sndinset): * OOps/diskin.c (newsndinset): * H/diskin.h (SOUNDINEW): Added skipinit argument to diskin and soundin 2005-03-14 John ffitch * Opcodes/modal4.c (marimbaset): Make zero valid probability for multiple strikes 2005-03-14 Istvan Varga * SConstruct: * Engine/oload.c: * H/csound.h: * H/csoundCore.h: * H/fftlib.h: * OOps/fftlib.c: added new FFT code (faster than functions in fft.c) new API functions: csoundComplexFFT(), csoundInverseComplexFFT(), csoundRealFFT(), csoundInverseRealFFT(), csoundRSpectProd() TODO: make allocation of tables safe with reentrant operation and multiple instances (currently uses statics which is ugly) * Opcodes/ftconv.c: use new FFT functions; opcode is faster now 2005-03-13 Istvan Varga * SConstruct: * Opcodes/ftconv.c: new opcode (zero delay multichannel convolve, reads IR from ftable) not fully tested yet * Engine/fgens.c: added GEN52: creates interleaved multichannel table from other tables * Opcodes/spat3d.c: fixed spat3dt slowdown at end of table made it possible to run spat3dt from the orchestra header (instr 0) 2005-03-13 John ffitch * SConstruct (opts): make installation optional 2005-03-13 Istvan Varga * Engine/fgens.c: * H/ftgen.h: added GEN51 * Opcodes/reverbsc.c: minor code improvements 2005-03-13 John ffitch * Opcodes/ftest.c (gentune): Added Gabriel's gen to the loadable gens under the name gentune 2005-03-12 Istvan Varga * SConstruct: * Opcodes/screverb.c: new opcode (Sean Costello's waveguide reverb) 2005-03-11 Istvan Varga * InOut/widgets.cpp: * Top/csound.c: * Top/pvanal.c: fixed calls of csoundYield() with NULL pointer * Engine/entry1.c: fixed rtclock opcode (should be 0xffff, not 0xfffd) 2005-03-10 Istvan Varga * Engine/entry2.c: run miditempo opcode both at init and performance time * Engine/musmon.c: check for extra MIDI note-offs also when sustaining * Opcodes/freeverb.c: attempts to correct high frequency attenuation for sample rate * Top/argdecode.c: load external modules before printing opcode list 2005-03-09 Istvan Varga * Engine/insert.c: * OOps/schedule.c: fixes in schedule opcodes * SConstruct: removed checks for some unused headers * H/sysdep.h: set DIRSEP to '\\' on Windows * Engine/envvar.c: try_file_open(): do not test for directory on Windows (breaks WINE) * H/csdl.h: removed macro definiton for AppendOpcode * InOut/libsnd.c: * OOps/diskin.c: fixed soundin and diskin amplitude * Opcodes/freeverb.c: new opcode 2005-03-08 Istvan Varga * Engine/insert.c: MIDIinsert(): allow muting instrument by 'q' score opcode * Engine/linevent.c: fixes in RTclose(); do not use atexit() to call this function allow use of 'q' score opcode * Engine/musmon.c: cleanup(): call RTclose() to close line input (-L) * InOut/libsnd.c: do not close line input here; this is done by RTclose() * Top/argdecode.c: allow use of -L stdin on Windows (mills_macintosh still disabled) * Top/csound.c: csoundScoreEvent(): add p2 to current time, not section start time 2005-03-08 Istvan Varga * Engine/entry2.c: added "event_i" opcode (same as "event" but runs at i-time) * Engine/fgens.c, Engine/memalloc.c, Engine/memfiles.c: * Engine/musmon.c, H/prototyp.h: * OOps/pstream.c, OOps/pvadd.c, OOps/pvread.c: * OOps/ugens3.c, OOps/ugens5.c, OOps/ugens8.c, OOps/ugens9.c: * OOps/vpvoc.c, Opcodes/hrtferX.c, Opcodes/scansynx.c: major changes to memfile functions added ENVIRON* argument to allow for multiple instances prototypes in prototyp.h rather than all around in various .c files * Engine/linevent.c: rewritten event opcode to use insert_score_event() added eventOpcodeI() (i-time version of eventOpcode()) * Engine/musmon.c: removed unused #includes and declarations improvements and fixes in sensevents() and insert_score_event() * Engine/oload.c: * H/csoundCore.h: ENVIRON: cosmetic change: moved mrealloc pointer to after mcalloc ldmemfile prototype changed, and also renamed to ldmemfile_ added MEMFIL* pointers memfiles and rwd_memfiles changed SSTRCOD to less trivial value * examples/trapped.csd: * examples/trappedrt.csd: fixed bug in instr 13 that caused various stability problems * H/csdl.h, Opcodes/clfilt.c, Opcodes/follow.c: * Opcodes/hrtferX.c, Opcodes/modal4.c, Opcodes/sndwarp.c: removed "oparm" macro (there are still way too many macros) * H/csoundCore.h: * H/csound.h: * Top/csound.c: return type of csoundScoreEvent() changed to int (zero on success) * H/foo.h: removed file: was unused * H/linevent.h: new file: defines LINEVENT (why was it in schedule.h ?) * H/schedule.h: * OOps/schedule.c: removed sensOrcEvent(); this is now a simple macro in musmon.c * InOut/libsnd.c: print message correctly * Opcodes/py/csoundmodule.c: use insert_score_event(), but file is unused anyway (remove ?) * Opcodes/ugens9.c: removed file: was unused (and redundant as well, also found in OOps) * util2/exports/het_export.c: call csoundCreate() and csoundPreCompile() - needed to fix crash added &cenviron to ldmemfile() call 2005-03-07 Michael Gogins * Added CsoundVST, Loris, and the Csound API headers and libraries to the install target in SConstruct. * Added the Csound manual and the API documentation to the Windows installer. * Updated Loris with v1.2 sources from Loris CVS. Note: lorismorph doesn't work and is awaiting fixes from Kelly Fitz. Other loris opcodes may be broken as well. However, the Loris Python extension module built here does seem to work. 2005-03-07 Istvan Varga * Engine/entry2.c: removed event_set; no longer needed * Engine/insert.c: made deact and schedofftim static xturnoff: always remove instance from schedofftim chain minor fixes * Engine/linevent.c: removed event_set; no longer needed eventOpcode: rewritten to use new insert_score_event() function newevent: removed this function * Engine/musmon.c: new function: insert_score_event made it sure that -B is always greater than and is an integer multiple of -b if real time audio is used various fixes, removed unused prototypes, etc. * Engine/oload.c: * H/csoundCore.h: replaced EVTNODE OrcTrigEvts_ with EVTNODE *OrcTrigEvts in ENVIRON set initial value of dbfs_to_float to 1/DFLT_DBFS * frontends/CsoundVST/CppSound.cpp: removed unused declarations * H/csdl.h: * H/cs.h: removed macro definitons for OrcTrigEvts * H/csoundCore.h: * Opcodes/oscbnk.c: removed EVTBLK.offtim (was not used anywhere) changed EVTNODE for use with insert_score_event and related code * H/oload.h: removed TRNON * H/prototyp.h: removed prototypes for undefined functions newevent and csoundDefaultMidiOpen added int insert_score_event(ENVIRON*, EVTBLK*, double, int); * H/schedule.h: * OOps/schedule.c: added ENVIRON* argument to sensOrcEvent() * InOut/midirecv.c: * OOps/schedule.c: removed unused function prototypes * InOut/widgets.cpp: rewritten ButtonSched to use insert_score_event cleanup() prototype was wrong * OOps/schedule.c: * Top/csound.c: changes for using insert_score_event() to schedule events 2005-03-06 Istvan Varga * Engine/insert.c: * Engine/musmon.c: * InOut/midirecv.c: started to rework event processing code (sensevents() and other functions); still a long way to go, and bugs may heve been introduced * Engine/oload.c: cenviron_: removed sensType, added evt_poll_cnt and evt_poll_maxcnt * csound/csound_main.c: do not call csoundYield() in main loop, kperf() will call it frequently enough; improves performance * H/cs.h: * H/csdl.h: removed macro definitions for sensType * H/csoundCore.h: changes in INSDS, sensEvents_t, and ENVIRON for new event processing code removed MCHNBLK.ksusptr[] and ENVIRON.sensType_ * H/prototyp.h: added prototypes for xturnoff() and xturnoff_now() * InOut/midifile.c: changed miditempo opcode to print score tempo when MIDI file is not available * OOps/schedule.c: minor cosmetic changes (removed old commented out code etc.) * Top/csound.c: * Top/main.c: removed frsturnon * Top/opcode.c: minor fix: print opcodes like oscil.kk correctly 2005-03-03 Istvan Varga * Engine/envvar.c: * H/envvar.h: added SNAPDIR to environment variable list (used by widget opcodes) new API functions: csoundFindInputFile() and csoundFindOutputFile() * Engine/filopen.c: sssfinit(), openin(), openout(), fopenin(): rewritten to use new file search interface isfullpath(), catpath(): removed functions * Engine/memfiles.c: * Engine/rdorch.c: * InOut/widgets.cpp: * InOut/winEPS.c: * OOps/diskin.c: * OOps/pvfileio.c: * OOps/sndinfUG.c: * Opcodes/sfont.c: use new file search functions defined in Engine/envvar.c * Engine/oload.c: * H/csdl.h: * H/cs.h: * H/csoundCore.h: * H/prototyp.h: * Opcodes/fluidOpcodes/fluidOpcodes.cpp: new API functions: csoundFindInputFile() and csoundFindOutputFile() removed isfullpath(), catpath(), sadirpath, sfdirpath, and ssdirpath * OOps/pvfileio.c: use mmalloc() instead of malloc() * Top/argdecode.c: * Top/main.c: * Top/one_file.c: removed unused 'envoutyp' argument from argdecode() and decode_long() * Top/main.c: check SFOUTYP after reading all options, but only if no file type option was specified 2005-03-02 Michael Gogins * Added rule for SConstruct to build Java wrappers for CsoundVST if jni.h is present. 2005-03-02 Istvan Varga * anal/adsyn/het_main.c: * anal/convol/cvl_main.c: * anal/lpc/lpc_main.c: * anal/pvoc/pvc_main.c: * util1/cscore/cscore_main.c: * util1/sortex/smain.c: * util1/sortex/xmain.c: * util2/dnoise.dir/dnoise_main.c: * util2/dnoise.dir/srconv.c: * util2/envext/envext.c: * util2/exports/lpc_import.c: * util2/exports/pv_export.c: * util2/mixer/mixer.c: * util2/mixer/xtrct.c: * util2/pvlook.dir/pvl_main.c: * util2/scale.dir/scale.c: removed ustub library, attempts to fix standalone utilities * Engine/envvar.c: * H/envvar.h: new files for dealing with environment variables * Engine/filopen.c: * Engine/rdorch.c: * InOut/winEPS.c: * InOut/winFLTK.c: * InOut/winX11.c: * Opcodes/fluidOpcodes/fluidOpcodes.cpp: * Top/csmodule.c: * Top/csound.c: * Top/dl_opcodes.c: * Top/dnoise.c: * Top/main.c: * Top/one_file.c: use new environment variable functions * Engine/musmon.c: * frontends/csound/csound_main.c: print benchmark information in cleanup() instead of main() * Engine/oload.c: * H/csoundCore.h: ENVIRON: removed (*SetEnv)(), added envVarDB added csound instance pointer to (*GetEnv)() * H/csdl.h: define macro for GetEnv, but not for SetEnv * H/csound.h: * Top/csound.c: removed csoundGetEnv() and csoundSetEnv() (now in envvar.c) * H/ustub.h: * Top/ustub.c: * util2/mixer/extract.c: removed files * SConstruct: allow building dynamic Csound library (static is still the default) ustub library is no longer built * Top/argdecode.c: new command line option: --env (sets/appends to environment variable) removed empty function argdecodeRESET() * H/soundio.h: added prototypes for type2sf() and sf2type() * OOps/sndinfUG.c: fixes in filelen, filenchnls, and filesr (filepeak is still broken) * Top/csound.c: removed use of CSRTAUDIO environment variable * sndinfo/sndinfo_main.c: fixed crash 2005-03-01 Michael Gogins * Updated CsoundVST code to use Istvan Varga's MIDI driver system, so that CsoundVST works again as a VST plugin, at least in "Csound classic" mode. 2005-03-01 Istvan Varga * Opcodes/gab/gab.c: fixes in Maldonado opcodes * Top/dl_opcodes.c: fixed -v crash * Engine/memalloc.c: print function names correctly * Engine/entry2.c: allow opcode names like FLpanel_end, FLgroup_end, etc. * InOut/midirecv.c: restored original algorithm for assignment of default instr numbers * InOut/libsnd_u.c: * OOps/pvxanal.c: * OOps/ugens8.c: * Top/pvanal.c: bug fixes in sound I/O, pvanal, and pvoc 2005-02-28 Istvan Varga * cleanup.sh: new script to remove files generated during compilation * OOps/fout.c: * Opcodes/fluidOpcodes/fluidOpcodes.cpp: * Opcodes/OSC-Kit/OSC-priority-queue.c: * Opcodes/OSC-Kit/OSC-timetag.c: * util2/mixer/xtrct.c: fixed compiler warnings * American.xmg: * English.xmg: * csound.pdf: * csound.xmg: removed files from repository 2005-02-27 Steven Yi * frontends/CsoundVST/CppSound.hpp: changed #include of cs.h to csoundCore.h 2005-02-27 Michael Gogins * Changed fluid* opcodes: removed Gogins version, merged option to print presets to fluidLoad and added fluidControl opcode from Gogins version, added new fluidAllOut opcode to collect all audio from all Fluidsynth engines in a performance. * Removed Opcodes/fluid directory (Opcodes/fluidOpcodes now implements all features formerly found there). * Updated H/OpcodeBase.hpp to work properly with new SUBR signature. * Updated examples/Koch.py to use fluidOpcodes. 2005-02-27 Istvan Varga * Engine/entry2.c: * H/midiops.h: * OOps/midiops.c: added optional i-time parameter (defaults to 0) to pgmassign, selects MIDI channel (zero means all channels) * Engine/musmon.c: fixed terminating on end of MIDI file (-T flag) * H/csoundCore.h: moved pgm2ins[] from MGLOBAL to MCHNBLK to allow setting per channel other changes in MCHNBLK and MGLOBAL * H/midiops.h: * InOut/midirecv.c: do not use MIDI controllers (<128) for storing Csound internal data Roland NRPNS (VIB_RATE etc.) moved to controllers 128-135 removed MOD_VOLUME removed BENDSENS (replaced with MYFLT MCHNBLK.pbensens) removed DATENABL (replaced with int MCHNBLK.datenabl) * InOut/midifile.c: reduced memory usage of event list do not print any text meta events when message level is zero allow muting tracks with -+mute_tracks option (for example, -+mute_tracks=0010001 will mute the third and seventh tracks; tempo events are still used even if a track is muted) * InOut/midirecv.c: allow setting program change to instrument routing per channel implemented "raw" controller mode (-+raw_controller_mode=yes), which means all control changes are simply stored without handling e.g. RPNs or sustain pedal changes in a special way do not "pollute" controller space with Csound internal data cleaned up code * OOps/midiops.c: cpsmidib and similar opcodes now use bend range RPN information cleaned up code * Top/csound.c: do not initialise pgm2ins[] here (now done by m_chn_init_all()) new command line option: -+mute_tracks=STRING new command line option: -+raw_controller_mode=BOOLEAN 2005-02-26 Istvan Varga * InOut/libsnd_u.c: fixed bug in sndgetset(): sfinfo structure was uninitialised * InOut/midirecv.c: fixed bug in reading MIDI device and file at the same time 2005-02-25 Istvan Varga * Engine/entry2.c: added miditempo opcode (returns current tempo of MIDI file at control rate) * Engine/insert.c: allow muting MIDI channels (massign to 0) in MIDIinsert() * Engine/musmon.c: initialise all MIDI channels before oload() merged MIDI device and file input code (removed sensFMidi) made use of MCHNBLK.insno and MCHNBLK.pgmno more consistent * H/csoundCore.h: * Top/csound.c: increased MIDI input buffer size changes in MGLOBAL for new MIDI file code * H/midifile.h: * InOut/midifile.c: new implementation for reading MIDI files (supports multiple tracks) miditempo opcode * InOut/midirecv.c: changes for using new MIDI file input removed sensFMidi (both device and file input is done by sensMidi) removed FMidiOpen, vlendatum, Fnxtdeltim, fsexdata, and Rnxtdeltim made use of MCHNBLK.insno and MCHNBLK.pgmno more consistent m_chinsno: allow massign to <= 0 (mutes channel) m_chn_init_all: new function m_getchnl: no longer need to check if channel exists * InOut/midisend.c: * InOut/pmidi.c: allow sending simple system messages (clock etc.) * OOps/midiops.c: allow massign to <= 0 (mutes channel) * SConstruct: compile InOut/midifile.c 2005-02-24 Istvan Varga * Engine/oload.c: * H/csdl.h: * H/cs.h: * H/csoundCore.h: removed unused or redundant variables (dbfs_to_short, short_to_dbfs, float_to_dbfs, dbfs_to_long, long_to_dbfs) * H/soundio.h: removed some unused macros and typedefs moved #defines of sf_read_MYFLT and sf_write_MYFLT here set buffer size defaults more usable for real time audio * InOut/libsnd.c: moved #defines of sf_read_MYFLT and sf_write_MYFLT to soundio.h replaced uses of redundant variable float_to_dbfs with e0dbfs * InOut/libsnd_u.c: * OOps/diskin.c: moved #defines of sf_read_MYFLT and sf_write_MYFLT to soundio.h bug fixes (hopefully) in opening and reading sound files removed unused or redundant variables (dbfs_to_short etc.) soundout opcode fixes (clip non-float formats, do not scale) minor cosmetic changes (line length etc.) * OOps/fout.c: moved #defines of sf_read_MYFLT and sf_write_MYFLT to soundio.h * OOps/ugens2.c: * OOps/ugrw1.c: minor tweaks in tabli() made use of FLOOR() macro with negative integer argument safer * Top/cvanal.c: always scale input (actually to revert dbfs scaling done in getsndin(); FFT always expects data in the range 0 to 1) minor cosmetic changes (line length etc.) 2005-02-24 John ffitch * OOps/ugens2.c: Added FLOOR macro to speed up floor throughout and other speedups * OOps/ugrw1.c: Added FLOOR macro to speed up floor Changed a couple of longs to ints as there is no need for values beyond 2 2005-02-23 John ffitch * OOps/ugens2.c (tabli): Unwrap the two case so tests outside loop 2005-02-23 Istvan Varga * InOut/midisend.c: * OOps/midiout.c: Fixed 2 byte messages (program change and channel pressure). 2005-02-22 Istvan Varga * Engine/musmon.c: * Engine/oload.c: * H/csdl.h: * H/cs.h: * H/csoundCore.h: * H/csound.h: * H/midiops2.h: * H/midiops.h: * H/prototyp.h: * InOut/midirecv.c: * InOut/midisend.c: * InOut/pmidi.c: * OOps/midiops.c: * OOps/midiout.c: * Opcodes/midiops2.c: * SConstruct: * Top/argdecode.c: * Top/csound.c: * Top/main.c: MIDI changes: added support for real time MIDI modules (there is only one currently, pmidi.c); implemented both MIDI in and out using PortMIDI in pmidi.c; removed many static variables from MIDI code * InOut/libsnd.c: clip integer format sound files, fixed sfcloseout() * InOut/widgets.cpp: fixed ButtonSched() crash * OOps/diskin.c: fixed soundout opcode * SConstruct: made useJack=1 and useALSA=1 the default again * H/sysdep.h: added integer types 2005-02-22 John ff * SConstruct: Added Word64 as an option. This could be done automatically but one needs to select 64 or 32 bit on a 64 bit machine. 2005-02-20 Istvan Varga * Top/argdecode.c: * Top/main.c: allow orc/sco names in CSD (may be broken), but not in .csoundrc * InOut/mididevice.c: * InOut/midirecv.c: moved files here from OOps * InOut/fmidi.c: removed file, all platform independent MIDI code is in midirecv.c now * InOut/mididevice.c: * InOut/midirecv.c: * InOut/pmidi.c: started to clean up MIDI code; still a long way to go file input and PortMIDI work, but mididevice.c is currently a stub * Engine/oload.c: reset rtaudio function pointers in oloadRESET() * H/csoundCore.h: removed PortMIDI specific function prototypes * H/midiops.h: define MBUFSIZ here * OOps/midiops.c: added function prototypes (should be in midiops.h too ?) * Top/csound.c: removed PortMIDI specific function definitions 2005-02-20 Michael Gogins * Added '--help' to short usage list. * Permit .orc and .sco filenames in .csd files. * Added Sequence node in CsoundVST: child nodes of a Sequence node follow each other in strict temporal order, in the same order that the child nodes were added to the Sequence; the duration of each node is the total duration of all notes that it produces. 2005-02-19 Istvan Varga * Engine/musmon.c: fixed orcompact bug (takes a Csound instance pointer) * Engine/oload.c: * H/csoundCore.h: * H/csdl.h: * H/cs.h: removed variables from ENVIRON (midi_out and oplibs) * frontends/csound/csound_main.c: check for the case when csoundCompile() aborts but there is no error (--help or -U utilname) * H/csdl.h: define Str() for plugin libraries * H/csoundCore.h: define return value for longjmp() to report success: CSOUND_EXITJMP_SUCCESS OPARMS.Midioutname on all platforms, not only BeOS * OOps/midisend.c: Linux midiout writes to device file in non-blocking mode instead of using OSS /dev/sequencer * Top/argdecode.c: replaced redundant definitions of short option list with a single one exit (longjmp) with success after --help, -z, and utility call (-U) various changes to make argdecode safe to call multiple times accumulate rather than overwrite --opcode-lib list minor fixes, removed static variable, etc. * Top/csmodule.c: search OPCODEDIR64 first if MYFLT=double * Top/csound.c: on systems other than WIN32 and mills_macintosh, print messages to stderr instead of stdout so that -o stdout does not get corrupted * Top/cvanal.c: removed exit() call return value is zero on success, -1 on error (other utilities may need similar changes) * Top/dl_opcodes.c: search OPCODEDIR64 first if MYFLT=double load redundant (specified multiple times) opcode libraries only once fixes in opcode library loading * Top/main.c: return value from setjmp() on failure (forced to negative sign) replaced some uses of '&cenviron' with 'csound' removed useless format option warning/errors run a second pass of argdecode after reading a CSD so that options will be overridden correctly moved some code from argdecode here to make multiple calls to argdecode safe call MidiClose() earlier * Engine/oload.c: fixed memory leak (overwrite of ENVIRON.memalloc_db by oloadRESET()) 2005-02-18 Istvan Varga * Engine/auxfd.c, Engine/express.c, Engine/fgens.c, Engine/insert.c: * Engine/linevent.c, Engine/memalloc.c, Engine/memfiles.c: * Engine/musmon.c, Engine/namedins.c, Engine/oload.c, Engine/otran.c: * Engine/rdorch.c, Engine/rdscor.c, Engine/sread.c, Engine/twarp.c: * H/csoundCore.h, H/prototyp.h: * InOut/fmidi.c, InOut/libsnd.c, InOut/libsnd_u.c, InOut/pa_blocking.c: * InOut/pmidi.c, InOut/widgets.cpp, InOut/winX11.c, InOut/winascii.c: * OOps/aops.c, OOps/disprep.c, OOps/fft.c, OOps/fout.c: * OOps/lptrkfns.c, OOps/midiops.c, OOps/midirecv.c, OOps/mxfft.c: * OOps/pstream.c, OOps/pvadd.c, OOps/pvinterp.c, OOps/pvoc.c: * OOps/pvread.c, OOps/pvsanal.c, OOps/schedule.c, OOps/sndinfUG.c: * OOps/ugens1.c, OOps/ugens3.c, OOps/ugens4.c, OOps/ugens5.c: * OOps/ugens6.c, OOps/ugens8.c, OOps/ugens9.c, OOps/ugrw1.c: * OOps/vbap_eight.c, OOps/vbap_four.c, OOps/vbap_sixteen.c: * OOps/vbap_zak.c, OOps/vdelay.c, OOps/vpvoc.c: * Opcodes/babo.c, Opcodes/bbcut.c, Opcodes/biquad.c: * Opcodes/bowedbar.c, Opcodes/cross2.c, Opcodes/filter.c: * Opcodes/flanger.c, Opcodes/grain.c, Opcodes/locsig.c: * Opcodes/nlfilt.c, Opcodes/oscbnk.c, Opcodes/physmod.c: * Opcodes/physutil.c, Opcodes/pitch.c, Opcodes/pluck.c: * Opcodes/pvsbasic.c, Opcodes/pvsdemix.c, Opcodes/repluck.c: * Opcodes/scansyn.c, Opcodes/scansynx.c, Opcodes/sndwarp.c: * Opcodes/space.c, Opcodes/spat3d.c, Opcodes/spectra.c: * Opcodes/syncgrain.c, Opcodes/ugens6.c, Opcodes/ugens7.c: * Opcodes/ugens9.c, Opcodes/ugensa.c, Opcodes/uggab.c: * Opcodes/ugmoss.c, Opcodes/ugsc.c, Opcodes/vdelayk.c: * Opcodes/wave-terrain.c, Opcodes/gab/gab.c, Opcodes/gab/vectorial.c: * Opcodes/py/csoundmodule.c: * Top/argdecode.c, Top/cscorfns.c, Top/csound.c, Top/cvanal.c: * Top/dl_opcodes.c, Top/dnoise.c, Top/hetro.c, Top/lpanal.c: * Top/main.c, Top/one_file.c, Top/opcode.c, Top/threads.c: * util2/dnoise.dir/srconv.c, util2/envext/envext.c: * util2/exports/pv_export.c, util2/mixer/extract.c: * util2/mixer/mixer.c, util2/mixer/xtrct.c, util2/scale.dir/scale.c: added Csound instance pointer to mmalloc(), mcalloc(), mrealloc(), mfree(), memRESET(), auxalloc(), and auxchfree() nbytes argument of mmalloc(), mcalloc(), and mrealloc() was changed from long to size_t * Top/main.c: read .csoundrc both from HOME directory and from current directory 2005-02-17 Istvan Varga * Top/csound.c: the CSRTAUDIO environment variable can be used to set default for -+rtaudio * Engine/cfgvar.h: * Engine/cfgvar.c: added documentation for interface functions * Top/main.c: fixed opening .csoundrc * H/csoundCore.h: * Top/argdecode.c: removed unused O.Volume and -V option * Top/argdecode.c: * Top/main.c: * Top/one_file.c: fixes in parsing string options such as file names 2005-02-16 Istvan Varga * InOut/libsnd.c: print correct audio block sizes audrecv/rtrecord returns the number of bytes read * InOut/rtjack.c: do not connect to JACK server if real time audio is not used * InOut/rtpa.c: audrecv/rtrecord returns the number of bytes read * Opcodes/deps: removed unused file * Opcodes/oscbnk.c: * Opcodes/oscbnk.h: added new opcodes from 4.24.1 (denorm, delayk, vdel_k, and rbjeq) a-rate rnd31 was made faster improved seeding from time removed all static variables (hopefully did not break anything...) * Top/argdecode.c: fixed output to raw sound files (set O.filetyp = TYP_RAW) * Top/csound.c: print newline at end of various "early return" error messages more error checking in dummy rtaudio functions; allow -+rtaudio=null audrecv/rtrecord returns the number of bytes read fixed return value in csoundAppendOpcode (should be zero on success) 2005-02-13 John ffitch * Opcodes/uggab.c (lpshold, loopseg, loopseg_set): Changed to agree with csoundAV 2005-02-11 John ffitch * Opcodes/pvsdemix.[ch]: New files from Victor Lazzarini * SConstruct: Added pvsdemic 2005-02-10 Istvan Varga * frontends/csound/csound_main.c * Top/argdecode.c: Improved --sched option, now accepts a priority value (--sched=N). Priority settings in the range 1 to 99 request the use of SCHED_RR, zero is SCHED_OTHER (not real-time but still locks memory), and -20 to -1 for setting nice level. * Opcodes/gab/vectorial.c: Fixed sequence point warnings. 2005-02-10 Istvan Varga * InOut/rtjack: Implemented JACK real time audio plugin (experimental). * InOut/libsnd.c: Do not call audrecv() after opening sound input in sfopenin(). * Engine/musmon.c: Print correct maxamp info in cleanup(), even if performance is terminated (e.g. by ^C) rather than finished normally. * SConstruct: Added new options noDebug (do not add -g and -gstabs to CCFLAGS), gcc3opt (add optimisation flags for gcc 3.3.x and later), and useGprof (compile and link with -pg). All are disabled by default. Changes to allow compilng JACK plugin. * Top/main.c: Terminate (call longjmp()) if initialisation of modules has failed for some reason. * Top/csound.c: playopen_dummy() and recopen_dummy() now fail if --sched is used, to avoid locking up the machine. Expanded tabs to spaces. * Engine/oload.c: * H/csoundCore.h: * InOut/libsnd.c: * Top/argdecode.c: * Top/csound.c: Use csoundGlobalVariable and csoundConfigurationVariable system for new sound file ID tag options added by Michael Gogins, rather than changing OPARMS, oload.c, argdecode.c, etc. The options are now: -+id_title -+id_copyright -+id_software -+id_artist -+id_comment -+id_date argdecode.c: expanded tabs to spaces 2005-02-09 Michael Gogins * Add long options to set ID tags in output soundfile: --id-title=TITLE Title tag in output soundfile (no spaces) --id-copyright=COPY Copyright tag in output soundfile (no spaces) --id-software=SOFTWARE Software tag in output soundfile (no spaces) --id-artist=ARTIST Artist tag in output soundfile (no spaces) --id-comment=COMMENT Comment tag in output soundfile (no spaces) --id-date=DATE Date tag in output soundfile (no spaces) 2005-02-07 Istvan Varga * Engine/insert.c: Fixed uses of INSDS.xtratim where it was assumed to be short. * Engine/musmon.c: Use ENVIRON.sensEvents_state instead of csoundGlobalVariables, to reduce CPU usage of sensevents(). * Engine/oload.c: * H/csoundCore.h: Added GetRtRecordUserData(), GetRtPlayUserData(), sensEvents_state, rtRecord_userdata, and rtPlay_userdata to ENVIRON. In csoundCore.h: new structure type sensEvents_t. * H/csound.h: * Top/csound.c: New functions void **csoundGetRtRecordUserData(void *csound) and void **csoundGetRtPlayUserData(void *csound). * InOut/rtalsa.c: Use user data pointers instead of csoundGlobalVariables to store device instance data; reduces CPU usage. 2005-02-06 Istvan Varga * Engine/sread.c: Fixed memory corruption bugs that were caused by mixed use of mmalloc and realloc. * Top/main.c: Fixed bug in setting cenviron.exitjmp_. * frontends/csound/csound_main.c: Better checking for real time audio in set_rt_priority(). * Engine/memalloc.c: Rewritten functions mmalloc, mrealloc, etc. 2005-02-05 Istvan Varga * Engine/insert.c: Reworked kperf() so that it always performs one k-period, and does not check for real-time events (that is now done by sensevents()). beatexpire() and timexpire() take double argument instead of MYFLT. * Engine/musmon.c: Call orcompact() in cleanup(). Set real-time audio buffer sizes to more usable defaults. Replaced sensevents() with new version that always senses events for one k-period, and also handles real-time events; this new implementation of sensevents is also not as prone to drop notes as the original, but may still need some tweaking. playevents now simply calls sensevents() and kperf() in a loop, to eliminate redundant code. Misc. changes related to new kperf/sensevents. * H/csound.h: * Top/csound.c: * Top/main.c: Fixes to re-entrancy bugs reported by Michael Gogins. New API function: int csoundPreCompile(void *csound), is optionally called before csoundCompile * H/prototyp.h: * InOut/FL_graph.cpp: Changed kperf prototype to 'void kperf(ENVIRON *csound)'. Global variable 'kcnt' has been removed. * InOut/rtpa.c: Fixed bug in module selection (incorrect use of strcmp). 2005-02-03 Istvan Varga * SConstruct: Fixed (hopefully) the PortMIDI compile error. * Engine/musmon.c: Made it sure that cleanup() is done only once, no matter how many times it is called; fixed closing sound I/O (still not sure if it is correct); remove temporary files in cleanup(). * H/prototyp.h: * Top/main.c: * Top/one_file.c: add_tmpfile() and remove_tmpfiles() now take a void *csound pointer to remove the temporary files of a particular Csound instance. Also removed the static global variable 'toremove'. In main.c, cleanup() is called instead of rtclose to close sound output (cleanup is more useful as it will also close files, remove temporaries, etc.). * InOut/libsnd.c: * InOut/pa_blocking.c: * InOut/rtalsa.c: * InOut/rtpa.c: Incrementing ENVIRON.nrecs_ is now done in libsnd.c, and not in the plugins. Closing line input was also moved to libsnd.c. Fixed memory access problem in rtalsa.c (allocated space was too small in some cases) that caused crashes and odd errors. Attempts were made to make the closing of sound I/O more reliable; this is still not perfect in the case of PortAudio, but ALSA is better now. 2005-02-02 Istvan Varga * Top/main.c: * frontends/csound/csound_main.c: Moved set_rt_priority() and calling of init_getstring() from main.c to csound_main.c. Various changes to use new interfaces. * H/csmodule.h: * Top/csmodule.c: New plugin interface to be used by non-opcode libraries (e.g. real time audio). * H/csoundCore.h: Added new API functions to ENVIRON. * H/csound.h: * H/csoundCore.h: * Top/csound.c: * H/pa_blocking.h: * InOut/libsnd.c: * InOut/pa_blocking.c: * InOut/rtalsa.c: * InOut/rtpa.c: * SConstruct: Code related to real time audio has been revised to allow for loadable modules and multiple instances. * H/cfgvar.h: * Engine/cfgvar.c: New files that implement an interface that allows dynamic creation of options. * Engine/oload.c: Added new function pointers to cenviron_. * Engine/namedins.c: Made the table non-static so that it can be accessed from other files (also renamed it to use a less trivial name). Fixed bug in csoundDestroyGlobalVariable(). * Engine/insert.c: * Engine/musmon.c: * Engine/otran.c: Changes to use new plugin based audio I/O interface. Some functions now take void *csound as the first argument. These include spinrecv(), spoutran(), nzerotran(), spoutsf(), and other related functions. * H/new_opts.h: * Top/new_opts.c: New files for parsing options dynamically created by functions in cfgvar.c. * H/prototyp.h: * Top/argdecode.c: * Top/one_file.c: The functions argdecode(), readOptions(), and read_unified_file() now take 'void *csound' as the first argument. In argdecode.c: use functions from Top/new_opts.c. * H/ustub.h: * Top/ustub.c: Removed old unused prototypes. * install.sh: Install script for Linux. 2005-02-01 John ffitch * frontends/csound/csound_main.c (main): Corrected incorrect C 2005-01-29 Istvan Varga * SConstruct: * InOut/rtalsa.c: added ALSA real-time audio; disabled by default, as it is currently quite limited (no device selection, only float samples are supported). 2005-01-29 Istvan Varga * H/csound.h, H/csoundCore.h: * Engine/namedins.c, Engine/oload.c, Top/csound.c: new function: csoundQueryGlobalVariableNoCheck() functions moved from csound.c to namedins.c * OOps/aops.c: use csoundQueryGlobalVariableNoCheck() 2005-01-28 Istvan Varga * H/csoundCore.h, Engine/oload.c: added void **namedGlobals, int namedGlobalsCurrLimit, and int namedGlobalsMaxLimit to ENVIRON * Top/main.c, frontends/csound/csound_main.c: print compile times (real and CPU) if bit 7 of O.msglevel is set * H/csound.h, Top/csound.c: implemented functions for creating named global "variables" * OOps/aops.c: rtclock opcode uses new timer functions * Top/main.c: print_benchmark_info(): new function (activated by O.msglevel & 128) call csoundDeleteAllGlobalVariables() on RESET create global timer struct that counts from Csound instance start-up; use these calls to get the current real/CPU time in seconds (return value is double): timers_get_real_time(csoundQueryGlobalVariable(csound, "csRtClock")) timers_get_CPU_time(csoundQueryGlobalVariable(csound, "csRtClock")) 2005-01-27 Istvan Varga * Engine/express.c, Engine/oload.c, Engine/rdorch.c, H/csoundCore.h: * Top/argdecode.c: implemented --expression-opt 2005-01-27 Istvan Varga * Engine/entry1.c: * Engine/entry2.c: * Engine/express.c: * Engine/otran.c: * Engine/rdorch.c: use '.' instead of '_' in internal opcode names (e.g. osc.kk instead of osc_kk); this allows the use of the underscore character in real opcode names. Many files in Opcodes/ were also changed. * strings/makedb.c: * strings/all_strings, strings/english-strings, strings/french-strings: * H/text.h: * Top/getstring.c: new implementation for localized messages. Uses Str("...") instead of Str(X_nnnn,"..."). This also needed replacement of Str() in a large number of files. * Engine/oload.c, Engine/otran.c, H/csoundCore.h: use 'int' type for variable indexes instead of 'short'; needs some testing * Engine/oload.c, Top/main.c, Top/one_file.c: removed API function prototypes, use csound.h instead * Top/csound.c, H/csound.h, Engine/oload.c, Engine/otran.c: incorporated some changes from the 'unofficial' 4.24.1 version, including timer functions, better checking of sr/kr/ksmps, and some fixes * Engine/memalloc.c: removed references to free_strings() * H/csdl.h: use csoundLocalizeString() instead of getstring() * InOut/widgets.cpp: include instead of , and use stringstream instead of strstream * Opcodes/midiops3.c: fixed undefined order of operations * SConstruct: added /usr/X11R6/include to include paths on Linux 2005-01-25 Steven Yi * frontends/csound/csound_main.c: set stdout to not buffer if csound output not going to terminal 2005-01-25 John ffitch * InOut/widgets.cpp (FL_run): Need to pass argument to threads in Linux/Mach cases 2005-01-22 Michael Gogins * Added csoundSetFLTKThreadLocking and csoundGetFLTKThreadLocking calls to the Csound API. This controls whether or not the FLTK widget thread calls Fl::lock and Fl::unlock (the default), or not. Programs with their own performance thread or FLTK thread may wish to disable Csound's FLTK thread locking. 2005-01-20 Michael Gogins * Created a working NSIS installer for Windows -- does not install source code. 2005-01-18 John ffitch * Opcodes/newfils.c: New code * Opcodes/syncgrain.c: New code * InOut/widgets.cpp (fl_joystick): Change to way up of joystick 005-01-16 John ffitch * InOut/pa_blocking.c (paBlockingWriteStreamCallback): Fixed incorrect declaration 2005-01-12 Michael Gogins * Call Pa_Terminate after Pa_AbortStream calls in rtclose_. This helps with restarting Csound and CsoundVST. 22005-01-06 John ffitch * All over added first arg to opcodes of the ENVIRON structure 2004-12-23 John ffitch * InOut/pmidi.c (GetMIDIData): Read to wrong place! 2004-12-20 John ffitch * OOps/mididevice.c: * Top/main.c (signal_handler, csoundCompile): * InOut/widgets.cpp (SNAPSHOT): * H/sysdep.h: * H/csoundCore.h: Added code to allow MSVC compilation 2004-12-19 Michael Gogins * Added Java wrapper for the Csound API via CppSound. CsoundVST and Python support do not currently work, but it is now possible to run Csound natively from Java. This is designed mostly for using Csound in Mathematica through J/Link. 2004-12-19 John ff * InOut/pmidi.c (sensMidi): major rehack for PortMIDI structure. Not verified yet. 2004-12-18 John ffitch * Engine/fgens.c (hfgens): Ensure gensub array is initialised 2004-12-14 John ffitch * SConstruct: All over use strings for options rather than numbers. Seems to work but take care! 2004-12-12 Michael Gogins * Updated to FLTK 1.1.6, libsndfile 1.1.11, CVS PortAudio, CVS Loris for Windows pre-built binaries. * Added Loris API documentation to Csound reference manual. 2004-12-10 John ffitch * InOut/libsnd.c: and code * OOps/sndinfUG.c (getsndinfo): Removed unused called to readheader 2004-12-03 Michael Gogins * Tried to remove most remaining compiler warnings: mostly returning int from main, sscanf for %lf with USE_DOUBLE, type casting, etc. 2004-12-02 John ffitch * SConstruct (else): Added PortMIDI build option to aid experimentation. 2004-11-30 John ffitch * Top/main.c (signal_handler): Move message to after check for alarm 2004-11-25 Michael Gogins * Initial implementation of CounterpointNode -- generates species 1, 2, or 3 counterpoint for cantus firmi selected from notes generated by child nodes. Based on code from Bill Schottstaedt's species counterpoint generator (thanks, Bill!). * Optimized the build for boost::ublas matrix code in CsoundVST Node classes. 2004-11-28 John ffitch * OOps/pvfileio.c (write_pvocdata, pvoc_readfmt): Use a union rather than dubious casts. 2004-11-23 John ffitch * OOps/midirecv.c (m_chanmsg): Removed initial values for volume/balance/pan/expressions/bend/mastvol 2004-11-16 John ffitch * OOps/ugens2.c (itable, itabli, itabl3): Need to check OK rather than assume true=OK * Engine/fgens.c: All over removed statics into the environment or into arguments. Make ftfind etc take extra argument. Should assist with reentrance. 2004-11-14 John ffitch * util2/exports/het_import.c (main): Open output as binary stream * Top/main.c (mainRESET): ftRESET takes environment argument * Engine/fgens.c: Move many statics into a single static. Adjust args to gens to reflect this -- statics almost unnecessary 2004-11-11 Michael Gogins * Changed the Python interface to CsoundVST to allow Python programmers to derive new classes in Python from CsoundVST.Node, and these new classes will function as C++ Node * objects in the CsoundVST C++ internals. This enables Python-derived Nodes to function just like regular C++ Nodes in music graphs. 2004-11-11 John ffitch * Engine/fgens.c: Removed static variables ftp and nargs and used arguments instead. Simplifications all over 2004-11-10 John ffitch * H/csdl.h (FLINKAGE): defined * Top/dl_opcodes.c: Allow definitions of fgens * H/csoundCore.h: Added NGFENS structure 2004-11-09 John ffitch * Engine/fgens.c (fgens): Started named fgens (fterror): Allow named gens in error messages (allocgen): New function to allocate new names 2004-10-24 Michael Gogins * Fixes to rtpa.c and pa_callback.c for duplex audio, and libsnd_u.c forsoundfile input, by Victor Lazzarini. * CsoundVST changes directory to that of loaded files. 2004-11-07 John ffitch * H/ftgen.h (GENMAX): set to 43 (really part is fgens below) 2004-11-06 John ffitch * Engine/musmon.c (sensevents): Need to reset nxtim and nxtbt at end of section (not needed in playevents model) 2004-11-05 John ffitch * Opcodes/pvsbasic.c: New file and opcodes * Engine/fgens.c: Added gen43 2004-11-02 John Fitch * Top/threads.c: OSX threads like Linux * InOut/rtpa.c: Use callback stuff for OSX 2004-10-24 Michael Gogins * Renamed libsndfile.dll.0.0.19. * Updated documentation to provide improved directions for extending Csound with builtin or plugin opcodes. * Fixed badly formatted tables in documentation. * Improved API documentation with simple examples. 2004-10-26 John ffitch * OOps/ugrw1.c: Simplified some of the error reporting * H/ugrw1.h (zkwm): and remove value from domix 2004-10-25 John ffitch * OOps/ugens6.c (cmbset): Round rather than truncate 2004-10-24 Michael Gogins * Updated build system for gcc 3.4.2 (candidate), changed some flags to avoid DLL relocation errors on Windows that caused problems with restarting CsoundVST, and with debugging. * First draft of complete Csound 5 manual with Kevin Conder documentation included. There are as yet many errors with tables and graphics, but all (or almost all) of the text appears to be good. 2004-10-21 John ffitch * OOps/ugens6.c (delset, delrset): Round not truncate (deltap): Round not truncate 2004-10-20 John ffitch * OOps/ugens6.c (delrset): NULL list of delays for safety, 2004-09-12 Michael Gogins * Added csound::Score::getCsoundScore method in CsoundVST for easier use of algorithmic composition classes in other Csound-based systems. * Updated csound.pdf with API documentation. * Restored real-time audio code to more functional version. 2004-10-16 John ffitch * Opcodes/sfont.c (Sfplist, filter_string): Removed static array to local in caller 2004-10-07 Steven Yi * Top/dl_opcodes.c (csoundOpenLibrary): Fixed to work with cygwin * Top/thread.s : Fixed to work with cygwin 2004-09-17 John ffitch * util2/exports/pv_export.c (main): Free malloced space 2004-09-12 Michael Gogins * Restored PortAudio to ASIO only, re-ordered 'notify' and 'wait' for better logic and performance. * Improved PortAudio stop/restart by returning PaAbort from callbacks. * Moved Windows DLLs to csound5 root directory. * Added SIGINT to Windows signals handled. * Improved order of directives and comments in custom.py. * Updated csound.pdf to reflect the above. 2004-09-11 Steven Yi * SConstruct: Changed to use prefix directory from command line argument, defaults to /usr/local * SConstruct: Changed install-opcodes to install to "prefix + /lib/csound/opcodes" 2004-09-11 Steven Yi * SConstruct: Added install, install-executables, and install-opcodes targets 2004-09-08 John ffitch * SConstruct (ustub): Added bus.c * Opcodes/bus.c: New code for IO bus * Engine/oload.c: Initialise below * H/csoundCore.h (ENVIRON_): Added busik_, busia_, busok_, busia_ * H/csdl.h (busik, busia, busok, busia): Added macros 2004-08-22 John ffitch * Opcodes/biquad.h: * Opcodes/biquad.c (vcoset, bqrezset, pareqset, tbvcfset): Skip initialisation option 2004-08-21 John ffitch * Opcodes/biquad.c (moogvcfset, rezzyset): Added iskip to avoid initialisation * Opcodes/biquad.h: Added iskip options to moogvcf abd rezzy 2004-08-18 John ffitch * Engine/fgens.c (gen20): Corrected sinc window 2004-08-12 Michael Gogins * Re-arranged sections in csound.pdf to be more helpful for beginners. * Updated csound.pdf to reflect availability of ASIO on Windows. 2004-08-10 Michael Gogins * Implemented threads and mutexes in the Csound API for Windows and Linux, in Top/threads.c. * Implemented low-latency PortAudio with a blocking wrapper that uses mutexes for asynchronus ASIO on MinGW/Windows, in InOut/pa_blocking.c and H/pa_blocking.h. * Fixed Top/threads.c so it compiles on Linux. 2004-08-05 Michael Gogins * Rewrote fluid opcode to break it up into fluidload, fluidcontrol, and fluidout. Added documentation html file. 2004-07-31 Michael Gogins * Removed many warnings, especially by using %lf in sscanf for USE_DOUBLE and re-ordering ctor lists. * Added section to build Loris from sources if present. * SWIG-generated .py files now generated in root directory. 2004-07-25 Michael Gogins * Added csoundTableLength, csoundTableGet, csoundTableSet to API. * Added pyinit opcode. 2004-07-24 Michael Gogins * Python opcodes: imported Maurizio Umberto Puxeddu's Python opcodes for Csound 4 from Gabriel Maldonado's CsoundAV sources, updated for Csound 5 with opcode error status return values. Currently these opcodes only work in CsoundVST, but I may add a pyinit opcode to make them work in command-line csound. 2004-07-23 Michael Gogins * Loris: added sources (for Csound 5 opcode ONLY) and prebuilt binaries (for MinGW/Windows with USE_DOUBLE ONLY) for _loris.dll, which is both a plugin Csound 5 opcode and a Python extension module. * Modified dl_opcodes.c to print debugging info off the -v option, and made the messages clearer. 2004-07-21 Michael Gogins * vst4cs: implemented sample-accurate timing for NOTE ON and NOTE OFF. Renamed opcodes for greater intelligiblity. 2004-07-19 Michael Gogins * Andres Cabrera suggested a global vst audio output opcode, so I added vstplugg to do that. I changed the documentation to reflect it. 2004-07-18 Steven Yi * Engine/oload.c (oload): Moved call to sssfinit to above init0 as recommended by Matt Ingalls, instr 0 opcodes that use fopenin() now function correctly 2004-07-18 John ffitch * OOps/vpvoc.c (vpvset): Ditto * OOps/ugens8.c (pvset): Ditto * OOps/midiops.c (pgmassign): Ditto * OOps/aops.c (invalset,outvalset ): Allow score strings 2004-07-17 Michael Gogins * Andres Cabrera added bank loading to vst4cs. I added plugin editor dialogs and program setting, also refined log message levels and made VST opcode diagnostic messages more informative. 2004-07-17 John ffitch * OOps/dumpf.c (krdset): Allow strings from score and in kdmpset (4 cases each) * OOps/ugens9.c (pconvset): New code (pconvolve): New code 2004-07-13 John Fitch * InOut/widgets.cpp: Various changes to make __MACH__ machines be line Linux. (save_snap): Use fl_ask 2004-07-11 Michael Gogins * Added vst4cs plugin opcode by Andres Cabrera for hosting VST plugins in Csound. Made a number of bug fixes and changes. More changes coming. This is alpha code. Currently building only on mingw. 2004-07-09 John ffitch * Engine/musmon.c (playevents): matt's suggestion to avoid missing events due to rounding. * OOps/ugrw1.c (itablew): Wrong result returned and elsewhere * Engine/otran.c (otran): Move initialisation of pool to start of otran so strings work! (constndx): from here 2004-07-05 Anthony Kozar * Top/argdecode.c (argdecode): don't keep tmp files on Mac * Engine/sread.c (ifa): Rest of ^+ bug fix from csound module. 2004-07-04 John ffitch * strings/all_strings: Added string 226 2004-07-04 Anthony Kozar * Engine/sread.c (ifa): fixed bugs and improved error reporting in ^+ and ^- code. 2004-06-27 Michael Gogins * Fixed (and simplified) real-time audio input. 2004-06-25 Michael Gogins * The CsoundVST Python module now prints Csound messages to Python sys.stdout when running in IDLE. 2004-06-25 Anthony Kozar * These are all changes to allow compilation on MacOS 9 * Top/csound.c: In declaration of csoundExternalMidiRead(), made mbuf unsigned char* to match other calls. * OOps/diskin.c: (newsndinset) changed if (sinfd > 0) to if (sinfd != NULL). * Top/dl_opcodes.c: added #else case for platforms without shared libraries. * InOut/libsnd.c: added #include "MacTransport.h" for Mac builds. * Top/main.c: commented out conditional exclusion of err_printf() for Mac. * OOps/sdif-mem.c: * SDIF/sdif-mem.c: * H/sdif-mem.h: * SDIF/sdif-mem.h: * OOps/sdif.c: * SDIF/sdif.c: changed #include to #include "H/sdif-mem.h" and to "H/sdif.h". * H/sftype.h: #defined PACKED for mac_classic * H/sysdep.h: undefined mills_macintosh (now defined in Prefix.h) and temporarily undefined RTAUDIO for Mac build until PortAudio working. 2004-06-15 John ffitch * OOps/aops.c (outo): Skipped +6 case! 2004-06-12 John ffitch * OOps/ugens2.c (ftkrchk): * OOps/ugrw1.c: Results of some opcodes were reporting errors incorrectly 2004-06-07 Michael Gogins * Changed the CsoundVST module to create a global csound instance of CsoundVST.CppSound that will work both in CsoundVST and in the standalone Python interpreter. 2004-06-02 Michael Gogins * CsoundVST now opens the Python or csd file given on the command line. 2004-05-31 John ffitch * OOps/midirecv.c: declare csoundIsExternalMidiEnabled, csoundExternalMidiDeviceOpen, csoundExternalMidiDeviceClose and OpenMIDIDevice external * Engine/auxfd.c (fdchclose): fd should have been curchp->fd * InOut/libsnd_u.c (SAsndgetset): Return a SNDFILE* rather than an int 2004-05-27 John ffitch * InOut/widgets.cpp (fl_setWidgetValue_set, fl_setWidgetValue): New code stolen from CsoundAV and changed to Csound5 format * Engine/entry2.c: Change entry for FLsetVal * InOut/widgets.cpp: SNAPSHOT::get returns error state (get_snap): and used 2004-05-16 Michael Gogins * Amended SConstruct to keep a list of all dependencies to make sure that zipfiles get built at the very end. * Updated csound.pdf with information about -odac:xxx on ALSA. 2004-05-20 John ffitch * InOut/rtpa.c (playopen_): Decode dac:xxx rather than environment variable * InOut/libsnd.c (sfopenin, sfopenout): Decode dac:xxx style device * H/csoundCore.h (ENVIRON_): type in instance was wrong (missing *) * H/csoundCore.h (ENVIRON_): * H/cs.h (rtin_devs, rtout_devs): * H/csdl.h (rtin_devs, rtout_devs): * Engine/oload.c: Added rtin_devs and rtout_devs for device names rather than just numbers 2004-05-19 John ffitch * Engine/entry1.c: Added "tablew" as a 0xfffe opcode * SConstruct (customSHLINKFLAGS): Darwin seems to need -dynamic * Top/dl_opcodes.c (dlsymIntern): SLOOKUPSYMBOLINIMAGE_OPTION_BIND -> NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 2004-05-18 John ffitch * Opcodes/vdelayk.c (partial_maximum): Added maxk opcode 2004-05-17 John * SConstruct: Use -Wl,-Bdynamic as it is linker option * strings/makedb.c (main): Correct format in printf twice for longs * Top/main.c (install_signal_handler): Restore signal handling 2004-05-17 John ffitch * InOut/rtpa.c (playopen_): Allow selection of ALSA device via environment variable * Engine/entry1.c: Restored tablekt and tableikt 2004-05-16 Michael Gogins * frontends/CsoundVST/CsoundVstFltk.cpp: fixed problem with linefeeds in message lines. 2004-05-12 John ffitch * SConstruct: Set makeDynamic=1 for linux 2004-05-09 Michael Gogins * Added high-level "C" API for CsoundVST (frontends/CsoundVST/csoundvst_api.h and .c). * Fixed random number generator bug in CsoundVST::StrangeAttractor. 2004-05-07 Michael Gogins * Fixed some bugs in rtpa.c to enable lower-latency real-time audio. 2004-05-05 Michael Gogins * Fixed Fl_graph.cpp and widgets.cpp event handling with thread protection. FLTK widgets work now (at least on Windows). 2004-05-05 John ffitch * strings/all_strings: * strings/english-strings: Heavily revised * Top/pvanal.c (pvanal): 1781->1771 * Engine/oload.c (oload): 1711->1704 as overuse * OOps/pvfileio.c (pvoc_readfmt): Minor typo in string (pvoc_readheader): 1555 instead of 1635 (pvoc_putframes): 1527 instead of 1657 * OOps/pvxanal.c (pvxanal): Minor typo in string * Opcodes/scansynx.c Many string renumering for uniqueness * OOps/fout.c (outfile_set): 1463->1451 as overuse * Opcodes/uggab.c (rsnsety): 1453->1453 as overuse * Top/dnoise.c (dnoise): 1198->1199 as overuse (dnoise): Minor type in string * OOps/diskin.c (newsndinset): Minor string correction * OOps/ugrw1.c (printksset): 1136->1135 as overuse * Top/dnoise.c (dnoise): Changed 1052 to 1016 as overuse * Opcodes/ugmoss.c (vcombset): Unified string 668 * OOps/cmath.c (seedrand): String 458 made same as other uses * Top/argdecode.c (longusage): Typo in 425 * Opcodes/uggab.c (kDiscreteUserRand, aDiscreteUserRand) (kContinuousUserRand, aContinuousUserRand): Inconsidtent use of String 315 * Opcodes/ugsc.c (phaser2set): String 243 double used -- changed to 245 * OOps/mididevice.c (OpenMIDIDevice): Typo in string 210 * Top/argdecode.c (decode_long): String 95 was repeated; changed to 97 which was free * OOps/pvread.c (pvreadset, pvocex_loadfile): * OOps/pvinterp.c (pvbufreadset, pvinterpset, pvcrossset): * OOps/pvadd.c (pvaddset): * OOps/pstream.c (pvx_loadfile): String 63 * Top/dnoise.c (dnoise): String 61 * OOps/diskin.c (sngetset): Typing error in string 58 * Engine/insert.c (insert_event): Format string had naked % 2004-05-04 Michael Gogins * Added more Fl::lock and ::unlock calls to CsoundVstFltk.cpp, to protect against Xlib: unexpected async operation errors. CsoundVST now actually works on Linux. 2004-05-03 Michael Gogins * Fixed midiinterop opcodes that were broken when moved to csound5. 2004-05-01 Michael Gogins * Added a new csoundPerformKsmpsAbsolute API function for calling kperf without a score. * Restored external MIDI interface callbacks to working order. Renamed the Open and Close callbacks to DeviceOpen and DeviceClose to clarify their actual function. * Many fixes in CsoundVST to get it working for Csound 5. 2004-04-29 Michael Gogins * Made inbuf and outbuf MYFLT * throughout the sources. * Moved "extern" function and data declarations from csound.c to prototyp.h as much as possible, in order to prevent inconsistencies from spreading. 2004-04-27 John ffitch * Engine/oload.c: Initialise file_opened_ * H/csoundCore.h (ENVIRON_): Added file_opened_ to environment 2004-04-26 Michael Gogins * Added scoreRESET to enable multiple renderings with one Csound API instance. 2004-04-08 John ffitch * InOut/widgets.cpp (fl_knob): Added retuirn to initerror call (fl_button): 2004-04-06 John ffitch * InOut/FL_graph.cpp (draw): Initialise win_h 2004-04-05 John ffitch * H/csound.h: rtplay__ needs to have void* argument * OOps/midirecv.c (csoundDefaultMidiOpen): Needs void* argument * Top/csound.c: mainRESET needs an argument * Engine/linevent.c (newevent): needs csound argument 2004-03-14 John ffitch * OOps/fout.c (infile_act): renamed from infile to avoid name clash with linsndfile support 2004-03-11 John ffitch * InOut/libsnd.c (sfopenout): Added test.au as a default name 2004-03-03 John ffitch * Engine/scxtract.c (scxtract): Added call to sread_init() as suggested by Anthony Kozar 2004-02-29 Steven Yi * InOut/rtpa.c: modifed code to use PortAudio device 1 by default if none given. Messages are now given to user if defaulting to device 1 or what device user has selected. * Top/main.c: changed strcmp to strncmp when looking for dac or devaudio to allow use of --sched when using on linux and selecting PortAudio devices (i.e. dac1, devaudio3) 2004-02-28 Steven Yi * Engine/entry2.c: Added reverbx_set and reverbx back in as well as opcode entries for nreverb/reverb2 2004-02-28 John D. Ramsdell * Makefile.am: Removed _SOURCES vars from conditionals and made plugins libs begin with "lib" so that this automake file works with older version of automake. * configure.ac: Removed AC_PROG_RANLIB and added $srcdir to include so that VPATH works. 2004-02-25 Michael Gogins Modified sources to #ifdef for HAVE_LIBSNDFILE as defined by configure.ac, not _SNDFILE_. Removed jpff_glue.c as its function is now performed by csound.c. Deleted load_opcodes.c after merging it with dl_opcodes.c. 2004-02-22 Michael Gogins New configure.ac, which is a modified version of John Ramsdell's configure.ac. Thanks to John for providing a framework, implementing the required tests, and enabling me to understand the online documentation. All new Makefile.am, which puts all source configuration in one file for all targets. Renamed some "main.c" files to prevent naming conflicts caused by having a single Makefile.am. Moved some opcodes from Opcodes back to OOps due to tangled dependencies. Plugin opcodes are loaded from the directory pointed to by the OPCODEDIR environment variable. The --shared-lib flag is still effective. Enabled PortAudio in Csound 5 together with libsndfile, and changed PortAudio support from v18 to v19. Renamed libanal.a to libustub.a and moved as much code as possible from analysis and utility program "main" files to ustub.c. 2004-02-20 John ffitch * Opcodes/grain.c (ags): Use memcpy rather than a loop to copy back 2004-01-29 John ffitch * Engine/insert.c (ingoto): Check that we are in i-rate case 2004-01-13 John ffitch * Opcodes/sfont.c: casts in many debug statements * Opcodes/mandolin.c (mandolin, mandolinset): Use ENVIRON* argument to Delayline functions 2004-01-01 John ffitch * Opcodes/pluck.c (filter3Set): Need to initialise ->x1 and ->x2 to zero * Opcodes/flanger.c (wguide2, wguide1): Avoid frequencies below 5Hz 2003-11-30 Steven Yi * Engine/insert.c (orcompact): Added calls to deinitialize i-time opcodes 2003-11-29 Steven Yi * H/cs.h: all thing except compability macros moved out to csoundCore.h * H/csoundCore.h: contains everything except compability macros * Top/csound.c: edited to use ENVIRON, #include csoundCore.h instead of cs.h (macros were getting in the way of compiling), still needs to be reconciled with main.c::csoundCompile before being usable 2003-11-25 John ffitch * OOps/vbap_zak.c (vbap_zak_moving_init): Fix zastart/zkstart * Opcodes/bowedbar.c (make_DLineN): Envionment as argument * Opcodes/scansynx.c (listget): Added environment as argument and in calls * H/csdl.h (perferror): Point via p->h.insdshead->csound-> and name changes * H/cs.h (GLOBALS_): Added _ to names in many places * Top/dl_opcodes.c (csoundLoadExternals): resetter function needs environment as argument * Top/jpff_glue.c (csoundReset): Added argument of environment 2003-11-22 John ffitch * Opcodes/grain.c (ags): Check gcount against 1 rather than 0.1 2003-11-07 John D. Ramsdell * Top/getstring.c (init_getstring): The default location for the csound.xmg file is passed in by defining XMGDIR to be a directory string. 2003-11-05 John * util2/sndinfo/main.c (main): * util2/dnoise.dir/srconv.c (main): * util2/dnoise.dir/dnoise.c (main): Initialise e0dbfs in main as it is now in O structure 2003-11-05 John ffitch * Opcodes/ugens6.c: reverb was not declared in opcode table 2003-11-04 John D. Ramsdell * configure.in: Added AM_INIT_AUTOMAKE, AM_PROG_CC_STDC, and code that adds -Wall when using GCC. 2003-11-02 John D. Ramsdell * AUTHORS, INSTALL, NEWS: Added empty files to be filled in when we comply with the GNU Coding Standards. 2003-11-1 Steven Y. Yi * rdorch.c: fixed printf statement in synterr() to use %c instead of %f 2003-10-29 John D. Ramsdell * csound.spec.in: Added an RPM spec for Csound. 2003-10-16 John ffitch * H/csdl.h (getstring): * Engine/oload.c: and initialise * H/cs.h (GLOBALS_): Added auxalloc and getstring 2003-10-14 John ffitch * Top/main.c (mainRESET): Cannot call rtclose if no rtaudio 2003-10-13 John D. Ramsdell * uggab.c (anterpol): Made loop expression unambiguous. * ugens4.c: Int constants changed to unsigned long, as they do not fit as ints. 2003-07-24 John ffitch * widgets.cpp (fl_slider_bank): Remove extern decl of zkstart/zklast * H/csdl.h: * H/cs.h: * Engine/oload.c: * Opcodes/ugrw1.c: Moved zkstart/zklast to gloal structure 2003-06-18 John ffitch * H/ugens6.h: Added revlpsum and revlpsiz fields * Opcodes/ugens6.c (rvbset): Make reverbinit called internally to reverb to avoiud static array. 2003-06-16 John ffitch * dl_opcodes.c (csoundLoadExternals): Added support for RESET function in modules. 2003-06-04 John ffitch * wave.c (wavWriteHdr): peakdata.chunkDataSize needs lenlong call 2003-05-20 John ffitch * biquad.c (bqrez): Make mode positive integer 2003-05-12 John ffitch * Added Copyright/LGPL to all files 2003-05-06 John ffitch * entry2.c: schedwhen should have arguments kSkkm (first two were inverted) 2003-04-13 John ffitch * vpvoc.c (vpvset): Fixed typo of <- instead of <= 2003-03-12 John * diskin.h (struct): inbuf array needs to be longest of SNDINEWBUFSIZ and SNDINEWBUFSIZ_24 2003-03-08 John ffitch * modal4.c (agogobel): Need to set amp/freq in performance part as well as init (vibraphn): Amplitude of vibraophone needs setting at perf time. (marimba): ditto * marimba.h: vibraphn.h: Added first field * fgens.c (hfgens): In allocating table numbers do not overwrite any existing table 2003-03-04 John ffitch * one_file.c (readOptions): Ignore white space before tags (createScore, createOrchestra, createMIDI, createMIDI2) (createSample, createFile, read_unified_file): 2003-02-27 John ffitch * pstream.c (adsyn_frame): The memset should be 64bit 2003-02-19 John ffitch * version.h (VERSION): 4.23f02 * sread.c (getpfld): Reconstruct extending of curmem, especially so as to correct the frstbp chain pointers 2003-02-16 John * version.h (VERSION): 4.23f01 * sread.c (sread_init): new function to separate include files from sections (sread): Removed resetting of str and the unwinding after section ends * scsort.c (scsort): Call sread-init 2003-02-02 John * cs.h: Changed types of xtratim to int and of relesing and actflg to char 2003-01-27 John ffitch * dcblockr.c (dcblockrset): Check that filter is stable 2002-12-21 John * VERSION 4.23 * biquad.c (bqrez): Replaced to do other cases 2002-12-18 John ffitch * widgets.cpp: Windows needs strstrea rather than strstream 2002-12-16 John ffitch * entry1.c: Added fprints fprintks and prints opcodes * aops.c: * entry2.c: removed "ink" and "outk" * biquad.c (vco): Changed parameter range of pw to 0-1 * midiops2.h (MIDIINBUFMAX): Upped buffer size, and simplified code * insert.c (subinstrset): Code moved so "too many p-fields" initerror call does not result in a crash or other errors. 2002-12-15 John ffitch * otran.c (otran): Fencepost error in nulling extension of instrtxtp array 2002-12-07 John * winsound.rc: Added dither box to Extras (seems to have got lost somewhere) * ugens1.c (adsrset1): Need to test <=0 for length rather than zero (fixes madsr) 2002-12-04 John ffitch * musmon.c (gettempo): Result should be 60/betsiz rather than betsiz 2002-12-03 John ffitch * fgens.c (ftgen): Allow negative fcodes in string case (1,23,28) * insert.c (insert_event): insert here * schedule.c: Removed insert_event * midiops2.c (midiin): Replaced (initc7,initc14,initc21): Check that channel exists * namedins.c (strsav_create, strsav_string, strsav_destroy): New code * linevent.c (sensLine): Check that there is a Linefd (event_set): revised to fix some bugs, including crashes that occur when real-time audio, or schedule opcodes are used 2002-11-30 John * biquad.c (bqrezset, bqrez): New filter 2002-11-24 John ffitch * insert.c (deact): revised (beatexpire, timexpire): use revised deact (subinstrset, subinstr, xinset, xoutset) rewritten * insert.h: structure OPCOD_IOBUFS * cs.h: New structure INSTRNAME (Istvan) * rtlinux.c: replaced dspfd with dspfd_in and dspfd_out in various places. This might allow full-duplex operation on some cards (Istvan) * cs.h (rtin_dev, rtout_dev): define * oload.c: Initialise rtin_dev and rtout_dev 2002-11-21 John ffitch * oscbnk.c (vco2init): replaced to fix bugs in setting default parameters * express.c: Use printf rather than putstrg * otran.c: Removed putstrg from here as not used * mididevice.c: new code from Istvan for real-time MIDI input under Win32 * rtalsa.c: New code from Istvan 2002-11-16 John * util2/mixer/xtrct.c (ExtractSound): removed incorrect declaration of samples which stopped extraction except from start (main): Called init-getstring 2002-11-14 John ffitch * modal4.c (agogobelset1): * midiout.c (kvar_out_on_set1): removed deprecated code * argdecode.c (usage): Corrected typo in message 425 2002-11-13 John ffitch * flanger.c (wguide2set): Should have checked arg1 and looked at arg2 * vdelay.c: * ugsc.c: * ugmoss.c: * ugens7.c: * ugens4.c: * ugens3.c: * sndwarp.c: * pitch.c: * oscils.c: * oscbnk.c * grain.c: * flanger.c: * biquad.c: Use macros all over * cs.h (XINARG1, XINARG2, XINARG3, XINARG4): New macros to look at x flags for first 4 arguments (so we can straighten this out) 2002-11-06 John * jpff_glue.c: Only declare/use playopen_ etc if RTAUDIO is defined 2002-11-04 John ffitch * sdif2adsyn.c (main): Minor changes to variables and initialisation 2002-11-02 John ffitch * soundin.c (soundin): Code changed system address, so need a local array for r. 2002-10-30 John ffitch * lowpassr.c (lowprx): Use k field, fixing bug (lowpr_setx): Initialise k and also okr/okf which were not (lowpr, lowpr_set): Same * lowpassr.h: Added k as field to LOWPRX and LOWPR * fgens.c (gen08): Minor fixes to stop compiler warnings (gen01raw): return after error (gen18): ditto * midirecv.c (m_chanmsg): Deal with case when msb=1 and lsb is not known 2002-10-28 John * fgens.c (gen01raw, gen01): Same * oscbnk.c (oscbnk_flen_setup): Moved function so will compile on 68000 * sfont.c (SfPlay_set, SfPlayMono_set, SfInstrPlay_set) (SfInstrPlayMono_set): use ioffset and other minor changes * sfont.h: * entry1.c: Added additional option arg to sfont opcodes * sfont.c (SfPlay_set): Changes from Steven Yi to bring in line with SfPlayMono 2002-10-28 John ffitch * fgens.c (ftRESET): fence post error in freeing flist * cwin.cpp (cwin_exit): Call csoundReset * main.c (mainRESET): Changed order of resets * memalloc.c (all_free): Reset apsize as well 2002-10-20 John * control.c (readvalues): removed \n from the read from the Tcl/Tk process 2002-10-15 John ffitch * VERSION 4.22 * soundio.c (floatran_noscl): New code (floatrecv_noscl): ditto (iotranset): Use it (iotranset): twice 2002-10-14 John ffitch * uggab.c (resony): Use the local buffer so as not to overwrite (rsnsety): Initialise buffer * uggab.h: Added buffer field to RESONY 2002-10-14 John ffitch * ugens5.c (areson): Ensure areson can use same answer variable as input 2002-10-13 John * swrite.c (swrite): * sort.c (sort): * sread.c (sread, getop): * musmon.c (playevents): Add q score event * entry2.c: Added mute opcode * pitch.c (mute_inst): New function * pitch.h: Added MUTE structure * otran.c (tranRESET): Free instrumentName structure * cs.h: Added muted field to INSTRTXT which is a short and aids padding! (GLOBALS_): Added instrumentName to globals 2002-10-12 John * insert.c (insert): Added code to pad parameters with zero if too few provided. 2002-10-09 John * uggab.c (posckk, poscaa, poscka, poscak): replace poscil * entry1.c: Added poscil as _kk, _ka, _ak, _aa opcode * fgens.c (fgens): Allow non power-of-two table sizes (negative lenth) (gen10): use rem rather than mask so allows non-power-of-two * memalloc.c (all_free): call rlsmemfiles * diskin.c (newsndinset): Set length right at beginnin (sreadinew): Add WAV to list of types with known header info 2002-10-08 John ffitch * wave.c (wavReWriteHdr): * soundio.c (sfopenout): * sndinfo.c (sndinfo): * diskin.c (newsndinset, soundinew): * aiff.c (is_aiff_formtype): * aifc.c (aifcReWriteHdr): Changed non-ANSI tell to call to lseek for completeness (aifcReadHeader): Ditto (is_aifc_formtype): Ditto (aifcReWriteHdr): Use SEEK_SET instead of 0 which could be wrong * FL_graph.cpp: and the rest of the winFLTK support. May merge later. * winFLTK.c: New code to replace winX11.c using FLTK rather than raw X 2002-10-07 John ffitch * memalloc.c (all_free): and here * memfiles.c (rlsmemfiles): Add nulling of memfiles for reentrance * oscbnk.c: many changes in vco2 (and related) code (Istvan) * oscbnk.h: similarly to oscbnk.c, all vco2 stuff was replaced by new version * entry2.c: replaced entry for "vco2init" 2002-10-06 John * soundin.c (sndinset): Patch from RWD to reopen input; still looks wrong 2002-10-03 John * rtcoreaudio.c: * mw_menu.c: * midirecv.c: * cscore_main.c: Improved deprecated declarations 2002-09-28 John * insert.h: Added 8 to args in XOUT (Istvan) * fgens.c (ftRESET): call vco2_tables_destroy() * oscbnk.c: added vco2 and related opcodes (Istvan) * oscbnk.h: New structures for vco2 (Istvan) * diskin.c (newsndinset): Fix related to skip time going beyond file end * ugmoss.c (vcomb): Changes from Pete Moss (valpass): Ditto 2002-09-26 John * butter.c (butter_filter): Deal with underflow on pentiums which gets seriously lost (RWD's idea) 2002-09-25 John * uggab.c (loopseg): Wrap segments (lpshold): Ditto and other fixes 2002-09-22 Istvan Varga * linevent.c: Added global_kcounter instead of kcounter 2002-09-21 John ffitch * cs.h (GLOBALS_): Added global forms of ksmps etc * oload.c: Added initialisation * insert.h: New typedef INSTRNAME, OPCOD_IOBUFS, UOPCODE, XIN, XOUT, SETKSMPS * jpff_glue.c (csoundMessageS): New function like csoundMessageV but to stdout * main.c (install_signal_handler): Leave SIGALRM alone if FLTK in use (dribble_printf): Make it dribble, and use csoundMessageS to use stdout 2002-09-21 Istvan Varga * cs.h (OPCODE, ENDOP): Added these and renumber * disprep.c (printv): print (int) p1 instead of insno (works better with user defined opcodes) * entry2.c: Added oscilikt, osciliktp and oscilikts * jpff_glue.c (MakeXYin): Arguments should be MYFLT * oscbnk.h: Added OSCKT and OSCKTP structures * oscbnk.c: various optimisations in oscbnk, grain2, and grain3 minor bug fix in oscbnk new opcodes oscilikt, oscilikts, and osciliktp bug fix in error checking code of all oscilikt opcodes 2002-09-20 John ffitch * soundin.c (soundin): Generalise to <24 channels * soundio.h: Change r1 to r[0] etc in SOUNDIN 2002-09-18 John ffitch * fgens.c (ftRESET): Free table space as well * rdorch.c (splitline): Generation of temporary labels was wrong in then/else 2002-09-17 John ffitch * musmon.c (cleanup): Only close scfp if not already closed * express.c (express): Need to treat a(k) as a special case as well as i(k) 2002-09-16 John ffitch * cwin.cpp (CArg::OnOrchestra): Promote use of unified files 2002-09-08 John * express.c (express): Silly error of && replaced by || in precedence of | and # * ugmoss.c: Rounded conversions in and/or/xor/not 2002-08-30 John * cwin.cpp (Run): Set O and cglob from O_ and cglob_ * soundio.c: recopen and playopen changed to use float rather than MYFLT (sfopenin): Cast sr to (float) in call of recopen (sfopenout): and in recplay 2002-08-25 John * soundin.c (soundin): Use an array for outputs rather than case statement. Generalises but possibly slower 2002-08-24 John * pvsanal.c (pvsynthset): Check size of buffers as well as existence (pvsanalset): Ditto 2002-08-21 John ffitch * VERSION 4.21 * cmath.c (ipow): Added normalisation and check for NaN (kpow): Check (apow): Check more complex here 2002-08-20 John ffitch * fgens.c: Code for ftload, ftloadk, ftsave and ftsavek * entry2.c: Added ftload and ftsave 2002-07-21 John * aops.c: added ink, outk, invalue, and outvalue opcodes * rdorch.c: added 'z' output type 2002-07-18 John * Incorporated the API code which meant minor changes in ustub.h, winX11.c, oload.c, one_file.c, cs.h, cwindow.h, rt*.c, and other places. main.c in all anal directory modified. 2002-07-18 John ffitch * rdorch.c: * otran.c: * insert.c (ingoto, kngoto, subinstrset,subinstr): New code from matt * insert.h (SUBINSR): new structure * soundio.c (longtran): fixed RWD bug that could result in overflows in some cases with positive out of range samples) * cs.h: removed definitions of "dv32768" variable that is no longer needed * cvanal.c (takeFFT): * hrtferX.c (hrtferxk): * grain4.c (grand, grainsetv4): bug in random code with incorrect scaling * oload.c (oload): removed code related to dv32768 * pvanal.c (takeFFTs): * ugens3.c (adsyn): use dbfs_to_float instead of dv32768 * ugens4.c: removed declaration of short_to_dbfs as it is not needed(Istvan) (plukset, krand, arand, rhset, randh, riset, randi): fixed a large number of RWD bugs, all related to 0dbfs scaling of 16 bit random numbers (completely wrong); replaced all occurrences of dv32768 with DV32768, and removed all DBFS code 2002-07-14 John * midiops.c (mctlset, maftset): fixed bugs in initialisation code (Istvan) 2002-07-13 John * soundin.c (dbfs_init): printing to stderr so as not to confuse -o stdout 2002-07-12 John * musmon.c: Printing of amplitudes done with new function print_maxamp including colour printing.. (Istvan) * ugens2.c (tabli): Fixed bug in no-wrap case (tabl3): Ditto * ugensa.c (newpulse, fogset): Ditto * ugens7.c (newpulse): Newpulse only if not iskip (fofset0): Skip lots of initialisation if iskip * ugensa.h (struct): * ugens7.h: Added iskip argument to FOFS and FOGS * pvoc.c: * midisend.c: * main.c (set_rt_priority): * dpwelib.h: FreeBSD case * aops.c (rtclock): Include in Linux case * LINUXaudio.c (setsndparms): FreeBSD code 2002-07-10 John * oload.c (oload): Fencepost error in when to enlarge strsets vector * anal/convol/makef: * anal/convol/main.c: New files * anal/makef (cvl): Include compilation of cvanal stand-alone 2002-07-09 John * soundio.c (audwrt4): #ifdef'ed out as not used 2002-07-04 John ffitch * sread.c (sget1): Make failure to include an include file into a hard error using scorerr * rdorch.c (rdorchfile, rdorchfile): Allow {{ }} long strings (splitline): * sread.c (getscochar): Trap $ without a name (thanks to Maurizio) * ugens5.c: Make lprdadr flexible rather than 20 long (lpcRESET, lprdset, lpslotset, lpitpset): 2002-07-03 John * ugens6.c (a_k_set): New function 2002-07-02 John * dl_opcodes.c (csoundLoadAllOpcodes): Early exit if no libraries to load 2002-06-29 John * util2/envext/envext.c (main): * util2/mixer/extract.c (main): * util2/mixer/xtrct.c (main): * util2/mixer/mixer.c (main): * util2/scale.dir/scale.c (main): * util2/dnoise.dir/dnoise.c (main): * util2/dnoise.dir/srconv.c (main): Initialise dbfs stuff 2002-06-28 John * windin.c (xyinset): * wave-terrain.c (scanhinit, scantinit): * ugsc.c (resonzset): * ugrw2.c (krsnset): Return after initerror * ugrw1.c (zir): initerror->warning * uggab.c (rsnsety): * ugens5.c (rsnset, rsnsetx): * ugens1.c (evxset): * spectra.c (spdspset, spfilset): * schedule.c (lfoset): * scansynx.c (scsnux_init, scsnux_init, scsnsx_init): * scansyn.c (scsnu_init, scsns_init): * pitch.c (pinkset): * midiops.c (cpstmid, chctlset): * midiops2.c (midic7set): Return after initerror * follow.c (flwset): initerror replaced by warning as it can carry on here * disprep.c (fftset): Return after initerror 2002-06-27 John * dumpf.c (kdmpset, kdmp2set, kdmp3set, kdmp4set, krdset) (krd2set, krd3set, krd4set): Return after initerror 2002-06-24 John * entry1.c: Changes arguments of vco to "xxikppovo" 2002-06-22 John * ustub.h (perferror): Added dummy definition * vpvoc.c (ktableseg, ktablexseg, voscili): * vdelay.c (vdelay, vdelay3, vdelayxw, vdelayxs, vdelayxws) (vdelayxq, vdelayxwq): * ugmoss.c (vcomb, valpass): * uggab.c (vibrato, vibr): * ugens9.c (convolve): * ugens8.c (pvoc): * ugens7.c (fof): * ugens6.c (delay, delayr, delayw, deltap, deltapi, deltapn) (deltap3, deltapx, deltapxw, comb, alpass, reverb, pan): * ugens4.c (buzz, gbuzz, pluck): * ugens3.c (foscil, foscili, adsyn): * ugens2.c (ktable, tablefn, ktabli, ktabl3, tabli, tabl3, kosc1) (kosc1i, osciln, koscil, osckk, oscka, oscak, oscaa, koscli) (osckki, osckai, oscaki, oscaai, koscl3, osckk3, oscka3, oscak3) (oscaa3): * spectra.c (noctdft, specdisp, specptrk, specsum, specaddm) (specdiff, specscal, spechist, specfilt): * spat3s.c (spat3d, spat3di): * spat3d.c (spat3d, spat3di): * space.c (space, spdist): * soundin.c (soundin): * sndwarp.c (sndwarp, sndwarpst): * pvinterp.c (pvbufread, pvinterp, pvcross): * pvadd.c (pvadd): * pitch.c (pitch, adsynt, hsboscil, pitchamdf, kphsorbnk) (phsorbnk, Fosckk, Foscak, Foscka, Foscaa, trnseg): * oscils.c (tablexkt): * oscbnk.c (oscbnk, grain2, grain3, rnd31k, rnd31a): * nlfilt.c (nlfilt): * hrtferX.c (hrtferxk): * grain.c (ags): * grain4.c (graingenv4): * disprep.c (kdsplay, kdspfft, tempest): * biquad.c (vco): initerror->perferror (nestedap): Ditto 2002-06-20 John ffitch * ugens1.c (linseg, kxpseg, expseg, knvlpx, envlpx): Should use perferror rather than initerror, and return 2002-06-17 John * Removed tabs and trailing spaces throughout (again) 2002-06-15 John * csdl.h: New file to be used in dynamic libraries * dl_opcodes.c (csoundLoadAllOpcodes): New code for Linux to load dynamic libraries. * main.c (create_opcodlst): Call csoundLoadAllOpcodes in any case * argdecode.c (decode_long): make static, and add opcode-lib= option 2002-06-13 * scansynx.c (scsnsmapx): New code 2002-06-10 John * oload.c: Initialisation of tran_0dbfs was in wrong place * window.c: Initialise exitFn to NULL (dispexit): More checking -- to deal with case when no exitFn * one_file.c (deleteOrch): make global * main.c (remove_plname): make global (was static) (remove_scnam): ditto * entry2.c: Initialisation method for linevent 2002-06-01 John * VERSION 4.20 * midiops.c (pchmidib): Same for pitchbend_value expansion * linevent.c (RTLineset): Local copy of Linepine to avoid OSX compiler bug * rdscor.c (flushline): Get local copy of scfp as mac OSX compiler has a bug in getc/macro expansion (scanflt): Ditto (dumpline): Ditto (rdscor): Ditto * wave.c (write_wavpeak): different scale if 0DBFS * vpvoc.c (vpvset): different scale if 0DBFS * ugens8.c (pvset): different scale if 0DBFS * ugens4.c: (arand, krandh, randh, krandi, randi): different scale if 0DBFS * ugens3.c (adsyn, adsyn): different scale if 0DBFS * soundio.c: (shortran, longtran, floatran, int24ptran, shortrecv, longrecv) (floatrecv): different scale if 0DBFS * soundin.c: (getsndin, soundin): different scale if 0DBFS * rdorch.c (argtyp, argtyp): different scale if 0DBFS * pvxanal.c (chan_split): different scale if 0DBFS * pvinterp.c (pvinterpset, pvcrossset): different scale if 0DBFS * pvanal.c (pvanal): different scale if 0DBFS * pstream.c (pvx_loadfile): different scale if 0DBFS * pitch.c: different scale if 0DBFS * otran.c (tranRESET, otran, plgndx): different scale if 0DBFS * oload.c: (oloadRESET, oload): different scale if 0DBFS * main.c: (MAIN): different scale if 0DBFS * lpanal.c (lpanal): different scale if 0DBFS * hrtferX.c (hrtferxk): different scale if 0DBFS * hetro.c (hetro, writesdif): different scale if 0DBFS * grain4.c (grainsetv4, grand): different scale if 0DBFS * diskin.c: (sreadinew, sndwrt1, sndwrtu) (sndwrt2rev, sndwrt2, sndwrt3, sndwrt3rev, sndwrt4rev, sndwrt4): different scale if 0DBFS * cvanal.c (takeFFT): different scale if 0DBFS * aops.c (dbfsamp): different scale if 0DBFS (ampdbfs, aampdbfs): * aiff.c (write_aiffpeak): scale peak chunk * physutil.h: dbfs_to_float * cs.h: Declare e0dbfs, dbfs_to_float tran_0dbfs in cglob 2002-05-30 John * linevent.c: Changes from matt * opcode.h: new file * opcode.c: Internal reorganisation from matt * entry2.c: New opcodes midinoteoff, midinoteonkey, midinoteoncps, midinoteonoct, midinoteonpch, midipolyaftertouch, midicontrolchange, midiprogramchange, midichannelaftertouch, midipitchbend, mididefault * midiinterop.c: * midiinterop.h: New code, from Michael Gogins with some changes 2002-05-21 John * midirecv.c (m_chanmsg): reset aftertouch (m_chanmsg): Use mapping array (FMidiOpen): Additional check for null channel * midiops.c (midichn, pgmassign): New code * entry2.c: new opcodes midichn, pgmassign, scantable, scanhammer * wave-terrain.c (scanhinit): New code (scantinit, scantPerf): Also new code 2002-05-21 John ffitch * filopen.c (catpath): use characters rather than strings * pvfileio.c (pvoc_openfile): added search of SADIR if not a full path and not in current directory 2002-05-17 John ffitch * oscils.c (tablexkt): Function corrected in cubic interpolation case, and strings updated * midirecv.c (m_chinsno): Missing argument in printf added (FMidiOpen): Allow Format 1 with single track 2002-05-15 John ffitch * clfilt.c: New version with more cases 2002-05-05 John * physmod.c (clarinset): p->v_time should be initialised (clarinset): amp is not know at init time so do it all on first cycle 2002-04-30 John * entry2.c: Added clfilt opcode * fft.c (fftRESET): New function to clear lroot * disprep.c (disprepRESET): New function to clear fftcoefs 2002-04-28 John * entry2.c: Added xscanmap opcode * scansynx.h (struct PSCSNMAPX): New struct * scansynx.c (scsnmapx_init, scsnmapx): New code for xscanmap (scsnux_hammer): Add XALL and correct code 2002-04-27 John * argdecode.c (argdecodeRESET): New function to reset static stdinassgn * main.c (mainRESET): Added argdecodeRESET * fgens.c (gen30): Replaced with new version from Istvan 2002-04-21 John * sndinfUG.c (filepeak): Ensure channel is properly rounded * pvfileio.c (pvoc_getframes): Add setting of rc to nframes in bytereverse case * midiout.c (release_set): No need to check MIDIoutDone * main.c (MAIN): Check for null scorename or empty string * dnoise.c (dnoise): various changes to mill_macintosh stuff * argdecode.c: Message 1704 was wrong in source * aifc.c: * aiff.h: Change name of ApplicationSpecificChunk to AIFFAppSpecificChunk (avoiding mac problems 2002-04-17 John ffitch * otran.c (insprep): Assignment to ngotos was unnecessary 2002-04-04 John * diskin.c (sndwrtf): 32/64 float problem fixed (Istvan) (sndwrtfrev): Ditto 2002-04-01 John * pitch.c (Fosckk, Foscak, Foscka, Foscaa): New experimental code for oscil without power-of-two 2002-03-31 John * everywhere: glob -> cglob as it clashes on MacOSX 2002-03-29 John * sread.c (sget1): Must not call flushlin after #include 2002-03-28 John * VERSION 4.19 * midirecv.c (m_chanmsg): Removed code relating to non-functioning sysex 2002-03-26 John * soundin.c (getsndin): Various incorrect MYFLT changed to float (getsndin): twice 2002-03-24 John * biquad.c (vcoset): Changes from Hans (vco): * vbap_sixteen.c (vbap_SIXTEEN): removed references to p->counter as never given a value * vbap_four.c (vbap_FOUR_moving): Correct typo 2002-03-23 John * oscbnk.c (grain2): Whole function replaced (istvan) 2002-03-19 John * fgens.c (gen33,gen34): New gens 2002-03-18 John * entry2.c: Make second argument of vcomb and valpass an x-rate * fgens.c: Interpolation in gen18 * ugmoss.c: Revised code from pete moss 2002-03-13 John * entry2.c: Added terrain opcode * wave-terrain.h: * wave-terrain.c: New file 2002-03-12 John * midiops2.c (midic7): * insert.c (turnoff): rename curip to lcurip to avoid macro problems * cmath.c: holdrand moved to glob structure * ugens3.c: All over loscal -> LOSCAL * cs.h (LOSCAL): Defined as a constant 2002-03-11 John * argdecode.c (longusage): New function (decode_long): Complete all options 2002-03-10 John * pitch.c (isense): Now works in unix case * vbap_zak.c (vbap_zak_moving, vbap_zak): Off by one? (vbap_zak_init): Initialisation of gains vectors was wrong * vbap_eight.c (vbap_EIGHT_init): Change malloc to auxalloc, and adjust structure. Also use 'natural' output addresses (vbap_EIGHT_moving_init): Ditto * Ditto for vbap_four and vbap_sixteen 2002-03-09 John * cs.h: Define GLOBALS (onept, log10d20): made macros * main.c: Deploy a globals structure 2002-02-26 John ffitch * rdorch.c (getoptxt): Another fix in z,y,Z type arguments which affected event opcode (matt) * musmon.c (musmon): Correct editing error in ~MacClassic case 2002-02-21 John ffitch * sfont.c (fill_SfPointers): Add a skip for unknown chunks 2002-02-19 John * argdecode.c (argdecode): Changed -- to -O and started to add --long options 2002-02-17 John * sread.c (getscochar, sread): Adjust str if inputs changes * argdecode.c (argdecode): ignore --sched option * main.c (set_rt_priority): New code for Linux scheduling (Istvan) 2002-02-16 John * rdorch.c (getoptxt): Allow name translation on answerless opcodes * musmon.c (musmon): * main.c (MAIN): Added BETA message if appropriate * rdorch.c (getoptxt): Allow more x-rate arguments (why not?) * soundio.c (sfopenout): Typo in->out in PIPE code, and added modification of AIFC type to IRCAM 2002-02-15 John * fgens.c (gen12): Change name from gen22 at Gabriel's request * ugens4.c (pluck): Wrong error message (X_1478->X_1480) * sfheader.c (readheader): Clear the hdr structure before use * cwin.cpp (cwin_exit): Call _exit rather than exit * musmon.c (musmon): Change to setting of O.inbufsamps, now from O.oMaxLag 2002-02-14 John * VERSION 4.18 * cwin.cpp (OnMIDI): Added dialog and new class to deal with MIDI Not yet complete * ugmoss.c (dconv): i was not initialised * rdorch.c (splitline): C-comment fails if */ is at beginning of a line 2002-02-13 John * rtwin32.c: Fixes from RWD to separate in and out devices * rdorch.c (rdorchfile): * sread.c (sread): Changes so nesting of #include is unlimited 2002-02-12 John * pvdlg.cpp (DoDataExchange): Remove incorrect frame-size test * ugens4.c (riset): Typo (p->rand<1) should be (p->rand<<1) (riset): Also an else missing (riset): Rewrite clock/old initialisation 2002-01-31 * sfont.c (ChangeByteOrder): reverse bytes in MACOSX, and a number of bugs fixed in this one function * entry2.c: Added oscils, lphasor, tablexkt opcodes * oscils.c, oscils.h: new files 2002-01-30 * oscbnk.c: small changes all over * oscbnk.h: Some fields removed * spat3d.c (spat3d_init_wall): Revisions from Istvan (spat3d_wall_perf): and many others * spat3d.h: New fields 2002-01-26 * cs.h (PMAX): Increased to 1000, which will waste some space..... * oload.h (GVBAS): Redefine as VBAS + PMAX as in comment * fgens.c (FTPMAX): Increased to 150 * insert.c (orcompact): Call doadr if exixts * cscrorfns.c, express.c, fgens.c, insert.c, main.c, memalloc.c, musmon.c, oload.c, otran.c, rdorch.c, soundin.c, ugens3.c, ugens5.c, ugrw1.c: Made RESET code into mainstream * sfont.c (SoundFontLoad): Arcane bug fix in threaded activity * window.c (dispkill): Protect against no kill fn * getstring.c (init_getstring): SSOUND fix * argdecode.c (usage): In reentrant case do not die * musmon.c (musmon): External MIDI again Make kcnt externally visible * midirecv.c (csoundDefaultMidiOpen): New code for SSOUND (sensMidi): Allow user-defined MIDI input in SSOUND * memalloc.c (mfree): Check is all is NULL first (Michael) * main.c: Main main into MAIN and define macros for it to simplify going around * filopen.c (die): IN SSOUND case throw message * fgens.c (ftRESET): Revised for SSOUND (Michael) (gen22): Renamed from gen18 as that was misleading! * cscorfns.c (cscoreRESET): Fixes from Michael Gogins * cs.h: Added deinit field to OPDS and OENTRY 2002-01-22 * filopen.c: undef tell macro before using on mac * sndinfUG.c (filelen): Use aydsize field of p (getsndinfo): and set this field (getsndinfo): New code to look at -i file on command line * sndinfUG.h (struct): Added audsize to structures * sysdep.h (SYS5): Define in macintosh case * soundio.c (iotranset): Added check for rtplay in AE_FLOAT case * main.c (main): mill_macintosh -> mac_classic * linevent.c (RTLineset): mac_classic case needs setvbuf call (RTclose): similar * cs.h (POLL_EVENTS): Corrected mac optional stuff 2002-01-20 * sread.c (operate): Added bitwise operations (getscochar): Added bit operations to [], possibly wrong precedence? * gets.r: Added new strings and corrections * rdorch.c (getoptxt): Decoding or y z and Z arguments changed (intyperr): Additional argument for expected type 2002-01-13 * ugmoss.c (not_k, not_a): New code * fgens.c (hfgens): (fgens): Remove message about increasing number of tables * scansynx.c (scsnux_init): Add range check 2002-01-11 * ugens6.c (cmbset): Initialise p->coef to zero 2002-01-08 * entry2.c: Added opcode vcomb, valpass and ftmorf * ugmoss.h: New structures for new code * ugmoss.c (dconv): Code revised and optimised (Pete) (and_kk, and_kk, and_aa, and_ak, and_ka, or_kk, or_aa, or_ak) (or_ka, xor_kk, xor_aa, xor_ak, xor_ka): New functions for bit arithmetic (vcombset, vcomb, valpass, ftmorfset, ftmorf): New code * fgens.c (gen18): New GEN from Pete Moss 2002-01-06 * VERSION 4.17 * fgens.c (ftRESET): clear ftevt as well (ftgen): Allow gens 23 and 28 in ftgen opcode with strings * util2/mixer/extract.c (main): * util2/mixer/xtrct.c (main): * util2/mixer/mixer.c (main): * sysdep.h: * dpwelib.h: * pvoc.c: * pvanal.c (pvanal): * musmon.c (musmon): * main.c (main): * lpanal.c: * linevent.c: * filopen.c (isfullpath): * dsputil.c: * midirecv.c: Removed ZPC options 2002-01-05 * rdorch.c (getoptxt): Gabriel's (?) typo corrected * aops.c (ftchnls): added code for same * entry1.c: added opcode ftchnls 2002-01-01 * aops.c (cpsoctinit): * fgens.c (gen11): * physmod.c (BowTabl_lookup): * ugens7.c (newpulse): * ugensa.c (newpulse): * ugsc.c (phaser2): Use intpow function * ugens4.c (buzz): Minor optimisation (gbuzz): also minor optimisations (gbuzz): Use version of pow for integers, as should be faster 2001-12-31 * insert.c (infoff): Revised code from Gabriel for delaying off event during release * fgens.c (gen32): New gen (Istvan) 2001-12-27 * schedule.c (ktriginstr): From re to make initialisation in score order 2001-12-25 * scansyn.c: pinterp was plain wrong 2001-12-22 * entry2.c: Added k-rate active opcode * scansyn.c (scsnu_init): Space was wrong size in PHASE_INTERP != 3 case. * entry2.c: Added event opcode (is it needed?) * linevent.c (eventOpcode): New code from matt * musmon.c (playevents): Revised code from rasmus 2001-12-21 * musmon.c (playevents): Fixed another memory leak (re) (playevents): and reorganisation (sensevents): Same fixes 2001-12-19 * entry1.c: parsing of tablew was wrong in that it failed to check k- and a-rate versions. Same for tablewkt * main.c: Include * scansyn.c (listadd): The list of instances was not used properly. 2001-12-16 * spat3d.c (spat3di): Check for depth should be against maxdep not mindep * otran.c (otran): Reworked default sr/kr/ksmps code * oload.c: Initialise esr etc from trans_sr etc so defaults work 2001-12-14 * pvanal.c (pvanal): * lpanal.c (lpanal): * hetro.c (filedump, writesdif): * fout.c (outfile_set, koutfile_set, fiopen, kinfile_set) (i_infile): * sfont.c (SoundFontLoad): Removed code which changed access options for sfont files and others as it seems totally wrong to me. 2001-12-12 * musmon.c (sensevents): Free memory in schedule case (playevents): Ditto 2001-12-11 * sfont.c (SoundFontLoad): In access stuff after looking in SSDIR and SFDIR the check should be on pathnam. Still not sure why it does this! 2001-12-09 * VERSION 4.16 2001-12-08 * main.c (signal_to_string): Not for OSX 2001-12-07 * fgens.c (besseli): #define out * pvxanal.c (besseli): use this version 2001-12-06 * musmon.c (fillbuffer): Fix to allow scheduled events (matt) 2001-12-05 * fgens.c (besseli): Do all calculation in doubles as the MYFLTs were a delusion. * pvxanal.c (pvxanal): Check for all versions of .pvx wrt case * ugens1.c (klnseg): Rewrite to avoid rounding error, but at a cost 2001-12-04 * cwin.cpp (cwin_args): Remove zapping of O.outformat * ugens8.c: corrected reading of pvocex files for multiple notes (RWD) * soundio.c: Added floating noscasler and better checking 2001-12-01 * sread.c (sread): Added x to score language * ugens1.c (xdsrset): Make last segment very long * pvlook.c (pvlook): Added calls to POLL_EVENTS * vpvoc.c (vpvoc): initerror should be perferror * ugrw1.c (zkr): Call warning rather than perferror * uggab.c (trig): * ugensa.c (fog): * ugens7.c (fof): return needed after perferror * ugens5.c (lpread): initerror should be perferror (lpinterpol): initerror should be perferror (lpread): return needed after perferror * singwave.c (make_Modulatr, make_SingWave): Returns after perferror and also make make_Modulatr return a 1 if it failed * ugens4.c (pluck): * ugens1.c (knvlpx): * pitch.c (macset): * physmod.c (clarinset, fluteset, bowedset, brassset): * modal4.c (make_Modal4, marimbaset, vibraphnset, agogobelset): * mandolin.c (mandolinset): return needed after perferror * fm4op.c (make_FM4Op, FM4Op_loadWaves, tubebellset, rhodeset) (wurleyset, heavymetset, b3set, FMVoiceset, percfluteset): Returns after perferror and also make FM4Op_loadWaves return a 1 if it failed. * aops.c (cpstun_i, cpstun, inz): return needed after perferror * ugens1.c (adsrset1): Change test for empty segment to <= 0 from < 2001-11-21 * winEPS.c: Minor fix for Irix6.5 * musmon.c: Reorganisation from matt to allow external calling 2001-11-20 * soundio.c: Arg to open should not have b option 2001-11-19 * fgens.c: New gens 30 and 31 (Istvan) * soundin.c (sndgetset): Count was off-by-one in skipping * cvanal.c (takeFFT): Do not normalise raw or IRCAM formats 2001-11-18 * oscbnk.c (grain2set): New code (grain2, grain3set, grain3, rnd31set, rnd31i, rnd31k): New code (Istvan) * ugens6.c (deltap3): As below * vdelay.c (vdelay3): Optimisations from Istvan * *ALL OVER* introduce mac_classic and mills_macintosh macros * winEPS.c (PS_MakeGraph): Deal file file directory separator * soundio.c (sfopenout): Simplify last case * rtmacintosh.c (rtclose): Remove code marked HACK * pvoc.c: Use sysdep.h rather than special code * pvfileio.c: change write(files[ofd]->fd,(const char*)&... to write(files[ofd]->fd,(char*)&.... to compile on Mac * getstring.c (getstring): More cautious test for strings 2001-11-16 John ffitch * ugsc.c (svf): if provided Q is too small force to 1 (svf): Optimise code 2001-11-14 John ffitch * soundio.c (sfopenout): Added IRCAM format to 3:2000 case 2001-11-11 * sfont.c (SoundFontLoad): Extensive rewrite so it looks in multiple directories. * filopen.c: make ssdirpath and sfdirpath external 2001-11-10 John ffitch * biquad.c (moogvcf): check max is acceptable; if zero make 1 2001-11-07 * ugrw1.c (zakRESET): New function (Gabriel) * main.c (mainRESET): Added zakRESET * sfont.c: Corrected various constants * ugsc.c (resonr): Improved speed by using immediate variables rather than indirect. (resonz): ditto 2001-11-04 * sread.c (sread): Remove call to extend_nxp after label again as it was wrong. Allow salcblk to do this safely 2001-10-29 * biquad.c (rezzy): Protect filter if rez is zero * sread.c (getpfld): if ( = ) should have been if ( == ) (getpfld): twice 2001-10-22 * sread.c (sget1): Apparent off-by-one error in macro args fixed (expand_nxp): Should be mcalloc rather than mmalloc (salcinit): Ditto 2001-10-20 * sfont.c (SoundFontLoad): Improved error message when failing to open 2001-10-13 * pvfileio.c (pvoc_updateheader): Change variable pos to signed 2001-10-07 * cwin.cpp: Added BUTTON_DAC and supporting functions * oscbnk.h (OSCBNK_PHS2INT): Revised definition to improve phase calc (Ivan) 2001-10-06 * fgens.c: Extend fgen table to 42 (gen24, gen40, gen41, gen42): New code * uggab.c (ikRangeRand, aRangeRand, randomi_set, krandomi) (randomi, randomh_set, krandomh, randomh, random3_set, random3) (random3a): New Code * entry2.c: Added opcode cuserrnd and function urd * uggab.c (ikDiscreteUserRand, aDiscreteUserRand) (ikContinuousUserRand, aContinuousUserRand): New code 2001-10-01 * uggab.c (jitters_set, jitter_set, jitter2_set): Added initialisation of p->phs * pvread.c (pvreadset): * ugens8.c (pvset): Added additional checks (RWD) 2001-09-29 * VERSION 4.15 * getstring.c (getstring): Added a second argument to be the default string (init_getstring): Allow null db * aops.c (cpstun_i, cpstun): New functions * oscbnk.h: * oscbnk.c: New code * entry2.c: Added oscbnk * spat3d.c (spat3d): Corrected mindep to maxdep (Istvan) * uggab.c (jitter2_set, jitter2, jitter_set, jitter, jitters_set) (jitters, jittersa): New code from Gabriel * uggab.h: Added JITTER, JITTER2 and JITTERS * cmath.c (seedrand): Added holdrand to remember last random number (for vibrato) * entry2.c: Added vibrato and vibr; jitter, jitter2, jspline * uggab.c (vibrato_set, vibrato, vibr_set, vibr): New code from Gabriel * uggab.h: Added VIBRATO and VIBR 2001-09-02 * schedule.c (triginset): Added code from re to enable proper i-time operation (ktriginstr): and enable deferred-action instrument turnoff 2001-08-31 John ffitch * biquad.c (biquada): New code * entry1.c: Added biquada opcode 2001-08-26 * cwin.rc: Correct layout * ugens1.c (adsrset1): Clear out space if not skipping init * musmon.c (gettempo): New function * midiops.h (struct GTEMPO): * entry2.c: Add tempoval opcode 2001-08-25 * pvanal.c (pvanal): Allow .pvx, .Pvx etc * soundio.c (int24ptran): Need to output 0/1/2 or 1/2/3 depending on endianness * argdecode.c: Add declaration of readOptions * vdelay.c (reverbx_set): The division by esr was not assigned * entry1.c: Entry for soundin had 4 too few m's 2001-08-20 * pvxanal.c (pvxanal): Add total_sampsread * main.c (main): Call init_pvsys to be sure 2001-08-19 * VERSION 4.13 (yes i know should have been 4.14) * uggab.c (lpshold, loopseg, loopseg_set): New code * mxfft.c: * pvxanal.c: * pvsanal.c: * pstream.c * pvfileio.c: New code * memalloc.c: changes to avoid potential memory leaks * memfiles.c (find_memfile): New function (add_memfil): new function * sndinfUG.c (filelen): Handle pvoxex files (filepeak): Handle peak-chunks in all formats (anal_filelen): New function * ugens8.h: Added fields frInc and chans to PVOC structure * ugens8.c: Support for pvocex (pvset): Ditto (pvoc): Concern about memory leak (pvx_loadfile): New function * pvread.c (pvocex_loadfile): New function Support for pvocex files (pvreadset): Ditto * pvanal.c: Added pvstream stuff * entry2.c: Added opcodes =_f, pvsanal, pvsynth, pvsadsyn, pvscross, pvsfread, pvsmaska, pvsftw, pvsftr, pvsinfo * rdorch.c (argtyp): Allow f type, and simplify code (getoptxt): Ditto (intyperr): Ditto * otran.c: Added pvstreaming; include pstream.h, new variables lclpcnt and lclnxtpcnt (otran): Initialise lblnxtpcnt (otran): set in ip structure (insprep): Initialise lplnxtcpcnt (lclnamset): Recognise f variables (lcloffndx): ditto * cs.h: filename array larger in MEMFIL new field lblpcnt in INSTRTXT 2001-08-17 * soundio.c: * midirecv.c: * linevent.c: Added MACOSX case 2001-08-14 * entry1.c: Added deltapx and deltapxw opcodes * ugens6.h: Structures for deltap * ugens6.c (tapxset, deltapx, deltapxw): New functions * vdelay.c: patches from Istvan * entry2.c: Added spat3d. spat3di and spat3dt * spat3d.h: * spat3d.c: New code 2001-08-13 * bbcut.h: * bbcut.c: New code * entry2.c: Added bbcut opcodes 2001-08-08 J P Fitch * midirecv.c (sensMidi): Stupid typing error lost MIDI on Mac (Thanks to matt pointing this out) 2001-08-01 * oload.c (oload): Changed test for integer overflow to unsigned short * express.c: * otran.c: Removed (commented out) various messages about extending pools etc 2001-07-14 John ffitch * ugens4.h: New field in GBUZZ to remember last * ugens4.c (gbuzz): Remember last value to get sign of small denom case right (gbzset): Initial last to +1 2001-07-01 * makedb.c: * getstring.c: * Makefile: Changed extension from .txt to .xmg to avoid confusions 2001-06-18 * soundin.c (sndgetset): (sndinset): Use the field * soundio.h: Added a datapos field to SOUNDIN * lowpassr.h: Added data for recalculation avoidance * lowpassr.c (lowpr): Recalculate coefficients only if there has been a change (lowprx): Ditto 2001-06-14 * wave.c: * soundio.h: * soundio.c: * soundin.c (getstrformat, getsizformat, bytrev3, sndgetset) * sndinfUG.c (filelen, getsndinfo): * sfheader.c (readheader): 24bit support * diskin.c (sngetset, newsndinset, soundinew, sndwrt3) (sndwrt3rev, sndwrtfrev, sndo1set, sndo1set): 24bit support and bug fixes * cwin.cpp (class CArg, OnInitDialog): * cvanal.c (takeFFT): * argdecode.c (argdecode): * aiff.c (aiffReadHeader): Added 24bit support (write_aiffpeak): Ditto 2001-06-06 J P Fitch * fout.c (infile_set): Bug fix from Gabriel 2001-05-26 * ugens8.c (pvset): Remember value of mfp which seemed to be missing 2001-05-24 * soundin.c: Add n-channel support message, and change t0 input from upto 24 channels. * soundio.h: Changes to SOUNDIN structure to match * english-strings: new string 1556 2001-05-20 * vpvoc.c (vpvset): * ugens9.c (cvset): * ugens5.c (lprdset): * ugens3.c (adset): * soundin.c (sndgetset): * sndinfUG.c (getsndinfo): * pvread.c (pvreadset): * pvinterp.c (pvbufreadset, pvinterpset): * pvadd.c (pvaddset): * diskin.c (newsndinset, sndo1set): * OSC-sock.c (osc_send_set): * ugens8.c (pvset): Fence post. Need to check <= to use strset. 2001-05-18 * fgens.c (gen01raw): No need to check p->channel greater than ALLCHNLS with new value of that variable * cs.h (ALLCHNLS): redefined as 0x7fff which is maximum positive 2001-05-15 * dnoise.c: Merge back macintosh changes * babo.c (bround): changed name to avoid macintosh problems 2001-05-12 * perf.c (InitSioux): Make title string a Pascal string 2001-05-09 * pvanal.c (pvanal): Added -H option to control window type (Hamming/hanning) (takeFFTs): Use window type from variable WindowType 2001-05-05 * VERSION 4.13 * dnoise on macintosh fixed etc * argdecode.c (argdecode): Added -@ option to read command line from a file, using readOptions from csd format 2001-05-04 * linevent.c (sensLine): read may have got more than one line. Fix due to Timo Thomas 2001-05-03 * memfiles.c (LoadFile): Remove unused argument foo (ldmemfile): and in call * pvoc.c (PVReadFile): Remove function as seems unused 2001-05-01 * soundio.c (sfopenout): Added /dev/dsp as a synonym for dac on GNU/Linux 2001-04-18 * vdelay.c (vdelay): Ensure delay line is 1 longer for safety 2001-04-14 * pitch.h (struct PFUN): and structure * pitch.c (pfun): New function * entry2.c: Added p() function 2001-04-08 * insert.c: Declaration of opcodlst was wrong; make OENTRY* * vdelay.c (reverbx_set): Rewrote memory allocation to avoid nested auxch as that does not work (reverbx): and change usage in here 2001-04-07 * vdelay.c (reverbx_set): Increase size of auxalloc call as it was too small. 2001-04-03 * one_file.c (readOptions): Move the argv++ to after the tracing; and then remove totally as it is wrong 2001-03-25 * VERSION 4.12 * hetro.c (hetro): Need %lf in case 'M' as it is double (thanks to Jim Croson) 2001-03-20 J P Fitch * vdelay.c (vdelayxw,vdelayxws,vdelayxwq): Modifications from Ivan 2001-03-18 * rtwin32.c (recopen): Typing error (OUT instead of IN) corrected (thanks to Bobby McNulty Junior) 2001-03-06 * vdelay.c: Added opcodes * entry1.c: Added opcodes vdelayxwq, vdelayxws, vdelayxw, vdelayxq, vdelayxs and vdelayx * soundio.h: * sfheader.h: Ircam format should be float (not MYFLT) 2001-03-04 * uggab.c (mirror): A return added in xlow >= xhigh case 2001-02-28 * midiops.c (imidiaft, maftset, midiaft): New code for polyaft opcode * entry1.c: Added polyaft opcode * ugmoss.c: New file * ugmoss.h: New file * entry2.c: Added dconv opcode 2001-02-24 * pitch.c (maca): Ensure that it can be used with overlapping answer and argument variable (mac): Ditto * sread.c (expand_nxp): New function to expand space, and called from a number of places some new. * vdelay.c (reverbx_set): Correct level problem in reverb2 * uggab.c (sum): Ensure that it can be used with overlapping answer and argument variable (product): Ditto 2001-02-21 John ffitch * rdorch.c (rdorchfile): * sread.c (sget1): Allow escaped # in macro body 2001-02-18 * swrite.c: Allow sign after exponential (thanks to Paul Isaacson) 2001-02-17 * ugens6.c (delay): Allow input signal to be the same as output signal (log001): Make a #define constant rather than a variable 2001-02-14 * vdelay.c (reverbx): Copy the input into the temp buffer for the combs so input and output variables can be the same. 2001-02-13 * main.c (signal_to_string): Renamed sig2str as signal_to_string to avoid possible name clashes 2001-02-13 * one_file.c: Define L_tmpnam in Windows case as was too small. Also put the extensions back 2001-02-07 * one_file.c: Changed calls to tmpnam so they do not add the .orc or other extension as that seems to kill Windows2K 2001-02-06 * one_file.c (blank_buffer): Failed to increment i!! Thanks Gabriel. 2001-02-04 * VERSION 4.11 * pitch.h (struct): New field noinsert * pitch.c (waveset): Correct case when pointers meet 2001-02-03 * main.c (main): and use it * one_file.c (read_unified_file): Change argument to be char ** 2001-01-31 * pitch.c (wavesetset): Make length test for <=1 incase of MIDI use 2001-01-27 * util2/dnoise.dir/dnoise.c (main): Some messages corrected 2001-01-26 * one_file.c (read_unified_file): remove strcpy as there was no guarantee of sufficient space 2001-01-21 * lpanal.c (gauss): Removed false code based on assumption of pivot. 2001-01-20 * entry2.c: Added barriage opcode * pitch.c (wavesetset): New function (waveset): New function and opcode 2001-01-12 John ffitch * aifc.c (aifcReadHeader): General confusions fixed I hope (thanks RWD and Jim Crosson) * cwin.cpp (DisplayText): New function for flashtext 2001-01-11 John ffitch * soundio.c (sfopenin, sfopenout): "devaudio" has 8 characters not 7! * entry1.c: rtclock_i should not have had an argument but ftlen_i should 2001-01-06 * nsliders.tk (settext): New code to display text boxes (deltext): and to delete them * control.c (textflash): New function to display text windows * control.h (struct): New TXTWIN structure 2001-01-05 * VERSION 4.10 * soundio.c (sfopenout): Allow devaudio# and dac# as realtime players. 2001-01-02 * physmod.c: Comment out DLineA_clear as not used * hrtferX.c (hrtferxk): Make crossfade unused as it created clicks * express.c (copystring): New function -- like strdup but uses mmalloc (express): use copystring rather than fixed size arguments 2000-12-31 * util2/mixer/mixer.c (main): make default output have .wav or .aif tag as in main system 2000-12-30 * util2/dnoise.dir/: new utility to remove noise from samples * entry1.c: Added tbvcf opcode * biquad.c (tbvcfset, tbvcf): New code from Hans 2000-12-29 * entry2.c: Change name of opcode to "sensekey" * entry1.c: Change vco to have optional arguments * rdorch.c (splitline): A little more cautious in /* ... */ comments wrt newlines. (splitline): and fix some unclear bug by rewriting 2000-12-23 * entry2.c: Added keyhit as an opcode * entry1.c: rtclock opcode as _i and _k * aops.c (rtclock): Support for reading rt-clock * ugens4.c (rndset): Allow seed from clock is >1 (rhset, riset): Ditto * entry2.c: Entry for sense was wrong (needs 2 rather than 3 as no init) 2000-12-20 * entry1.c: Added additional optional argument to comb and alpass * ugens6.c (cmbset): Allow delay in samples for comb and alpass * ugens6.h (COMB): Add insmps optional argument to COMB 2000-12-18 * vbap_zak.c (vbap_zak_control, vbap_zak_moving_control): * vbap_sixteen.c (vbap_SIXTEEN_control) (vbap_SIXTEEN_moving_control): * vbap_eight.c (vbap_EIGHT_control, vbap_EIGHT_moving_control): * vbap_four.c (vbap_FOUR_control, vbap_FOUR_moving_control): It was possible for these to overwrite; loop now starts at 1 * sfheader.c (writeheader): * midirecv.c: * linevent.c (RTLineset): Minor preprocessing error * cs.h: Set _macintosh when necessary 2000-12-17 * entry2.c: New opcode lpf18 * pitch.h (struct LPF18): * pitch.c (lpf18set, lpf18db): New code for LPF with 18dB falloff. 2000-12-15 * swrite.c: Replaced fltout by fprintf -- still not sure about this! * pitch.c (ksense): Added use of _kbhit and _getch for Windows/DOS * pvdlg.cpp (DoDataExchange): Two cases were plain wrong! 2000-12-14 * lpanal.c: Some general code tidying 2000-12-11 * many files: standardise on _macintosh flag 2000-12-08 * argdecode.c (argdecode): Set utility title in mac * soundio.c (audwrt4): Skip code for now (audwrtrev4): Ditto * soundin.c (getsndin): from matt -- only set gain if positive 2000-12-08 J P Fitch * aops.c (dbfsamp): (ampdbfs): (aampdbfs): New code for full scale dB 2000-12-08 * argdecode.c (argdecode): Added call to create_opcodlst to ensure opcode list is made. * main.c (create_opcodlst): Cannot be static as needed elsewhere, like opcodes 2000-12-07 * sfont.c (fill_SfPointers): Added check for sfont format, and new X_1555 2000-12-06 * entry2.c: Added varicol opcode * pitch.c (varicolset): (varicol): New code for variable coloured noise. * pitch.h (struct): New structure for variable coloured noise 2000-12-05 * Cwin.cpp (OnSliders): Display sliders 1 rather than zero 2000-12-03 * VERSION 4.09: released * pluck.c: * wavegde.c: Rewrite significant parts; in particular remove general filter for 3 point FIR which is all that is used 2000-11-27 * aiff.c (aiffReadHeader): Str X_65 had arguments in wrong order in printf 2000-11-26 * pluck.c (pluckExcite): Move pickup point from here (pluckGetSamps): To here 2000-11-25 * wavegde.c (error): String 259 was wrong * pluck.c (pluckPluck): Change spurious floating point constants to FL() or integer. 2000-11-24 * uggab.c (lposc_set): Change from Gabriel/Rasmus * ugens3.c (loscil3): Added check for exact end of loop (loscil): (loscil): (loscil3): on advice from Hedman 2000-11-21 * fgens.c: Declare gen16 and add to table (gen16): New function 2000-11-19 * sftype.h: * sf.h: Corrected MSVC pack command * pitch.h: NSEG and TRANSEG structures * pitch.c (trnset, trnseg, ktrnseg): New code for transeg opcode * entry2.c: transeg opcode 2000-11-18 * ugens1.c (xsgset): Fixed potential bug in xsgset with reusing vector * sf.h: Added pack(1) for macintosh 2000-11-12 * sfont.c (filter_string): new function to remove unprintable characters which kill xterms etc 2000-11-06 * sfheader.c (readheader): Inadvertent change of AUDIO_ENCODING_FLOAT to AUDIO_ENCODING_MYFLT (writeheader): and again 2000-10-25 * entry2.c: setctrl allowed string argument * nsliders.tk: New function, setlab * control.c (ocontrol): Added case 4 to set label to slider 2000-10-16 * one_file.c (checkVersion): New function to allow version checking in .csd files (read_unified_file): And call it 2000-10-14 * ugens4.c (BIPOLAR): New constant (krand): (arand): (krandh): (randh): (krandi): (randi): Make 31-bit PRNG give bipolar results. * entry2.c: Added babo opcode * babo.c: * babo.h: New code [Note special copyright terms] from Nicola * ustub.h: Add peakchunks * oload.c (instance): * otran.c (insprep): * oload.h (LABELIM): Changed MINSHORT to MIN_SHORT to avoid silly problems 2000-10-11 * aiff.c (aiffWriteHdr): (aiffReWriteHdr): * wave.c (wavWriteHdr): Do not write PEAK if not wanted (wavReWriteHdr): Ditto * argdecode.c (argdecode): Case K for peak chunks * main.c (main): Add peakchunk variable 2000-10-08 * BeAudio.c: * Makefile.be: * argdecode.c: * cs.h: * main.c: * midirecv.c: * midisend.c: * rtBe.c: * sysdep.h: * vbap.c: * winBe.c: BeOS patches from Jens Kilian 2000-10-01 * one_file.c (readOptions): Added // and /* */ comments * rtlinux.c: Changed some floats to MYFLT (thanks to Nicola Bernardini) 2000-09-30 * vdelay.c: Simplified constants for cc_time and ca_time; comment out the original nreverb code * entry2.c: Made reverbx the nreverb code as it is a strict superset 2000-09-27 * vdelay.c (reverbx_set): (reverbx): New code, replacing vreverb code. * entry2.c: Added reverbx from re (replacing vreverb) 2000-09-25 J P Fitch * wave.c (wavReWriteHdr): One case of MYFLOAT should have been float (Nicola B.) 2000-09-24 * entry2.c: Added vreverb opcode * vdelay.c (vreverb_set): New code (vreverb): New code * vdelay.h (VREV): new struct * pitch.c (ksense): New code to read keyboard input * main.c (create_opcodlst): New function to create entry table from bits. (main): and use it * rdorch.c: Changed opcodlst to * from [] * oload.c: * otran.c: * opcode.c: * schedule.c * oload.c: Add declarations of opcodlst and oplstend as really here * entry1.c: * entry2.c: Replace entry.c 2000-09-22 * pitch.c (ksense): Added CWIN version of keysensing 2000-09-21 John Fitch * VERSION 4.08 * musmon.c (musmon): * main.c (main): Change banner to indicate 64bit version 2000-09-19 John Fitch * CSliders.cpp: New code for buttons and checks * CSliders.h: Ditto * Cwin.cpp: and the same * control.c (check_set): (check): (button_set): (button): Added for Windows 2000-09-17 * dumpf.c (nkread): Reading needs to take account of MYFLT * entry.c: Added button and checkbox opcodes * control.c (check_set): (check): (button_set): (button): New functions; also reorganise code for starting and reading * nsliders.tk: Added title. and pack -after for sliders. Should allow placement of buttons * pitch.c (impulse,impulse_set): Code for mpulse opcode 2000-09-16 * entry.c: Added impulse opcode (mpulse) 2000-08-27 John ffitch * phisem.c (bambooset): Shake_damp needs to be set; maybe on others as well? (wuterset): Ditto (sleighset): Ditto (guiroset): Ditto (tambourset): Ditto 2000-08-18 * Rename window.h to cwindow.h to avoid Windows problem. Change in many files including makefiles * ALL: FLOAT -> MYFLT to avoid problems with Windows * hetro.c: * soundio.c: * pitch.c: * aifc.c: * aiff.c: * aops.c: * argdecode.c: * biquad.c: * bowedbar.c: * butter.c: * cmath.c: * cross2.c: * cs.h: * cscorfns.c: * cvanal.c: * dam.c: * dcblockr.c: * diskin.c: * disprep.c: * dsputil.c: * dsputil.h: * dumpf.c: * extract.c: * fft.c: * fgens.c: * flanger.c: * fm4op.c: * follow.c: * fout.c: * grain.c: * grain4.c: * hrtferX.c: * insert.c: * interpol.c: * linevent.c: * locsig.c: * lowpassr.c: * lpanal.c: * lptrkfns.c: * mandolin.c: * midiops.c: * midiops2.c: * midiops3.c: * midiout.c: * midirecv.c: * modal4.c: * moog1.c: * moog1.h: * musmon.c: * musmon.c: * nlfilt.c: * oload.c: * otran.c: * phisem.c: * physmod.c: * physutil.h: * pluck.c: * ptrigtbl.h: * pvadd.c: * pvanal.c: * pvinterp.c: * pvocext.c: * pvread.c: * rdscor.c: * repluck.c: * revsets.h: * scansyn.c: * schedule.c: * sfont.c: * shaker.c: * singwave.c: * sndinfo.c: * sndwarp.c: * soundin.c: * soundio.h: * space.c: * spectra.c: * sread.c: * sysdep.h: * twarp.c: * ugens1.c: * ugens2.c: * ugens3.c: * ugens4.c: * ugens5.c: * ugens6.c: * ugens7.c: * ugens8.c: * ugens9.c: * ugensa.c: * uggab.c: * ugrw1.c: * ugrw2.c: * ugsc.c: * vbap.c: * vbap.h: * vbap_eight.c: * vbap_four.c: * vbap_sixteen.c: * vbap_zak.c: * vdelay.c: * vpvoc.c: * wavegde.c: * winEPS.c: * wincwin.c: * windin.c: * window.c: Deal with floating constants and in a few places corrected confusions between float and FLOAT ***** SPELL-CHECKED TO HERE ***** 2000-08-17 * soundio.c: flinbufp and floutbufp shoudl be float (not FLOAT) * pitch.c (GardnerPink_init): Variable float -> FLOAT * fout.c (infile_float): Sort out confusion between float and FLOAT * ugens1.h (struct EXPSEG2): float -> FLOAT 2000-08-15 * anal/adsyn/makef (OBJS): Include sdif code * sdif-mem.c: * sdif.c: * sdif.h: * sdif-mem.h: New file (SDIF again) * text.h (X_MAXNUM): Increase to 1551 * Hetro.c: added SDIF stuff 2000-08-14 * midisend.c: Added FreeBSD code for soundcard * argdecode.c (usage): Error message number changed for dithering to 1537. 2000-08-13 * entry.c: Add optinal argument to guiro -- a bug fix * sread.c (sget1): Typing error ommits c== in c=='_', twice 2000-08-07 * VERSION 4.07 * midiops.c (mctlset): Change default value to lo setting 2000-08-06 * entry.c: Added opcodes cabasa, "crunch", "sekere", "sandpaper", "stix", "guiro", "tambourine", "bamboo", "waterdrip", "sleighbells" * phisem.c: * phisem.h: New files for phisem instruments from STK 3.1 2000-08-05 * vbap.c (choose_ls_triplets): Move array connections to malloced space as rather too big for some architectures. * vdelay.c (nreverb): Set time to 0.001 instead of zero which gives inf values. Also test for <=0 rather than just negative. Also change error message 356 (reverb2_play): Ditto 2000-08-02 * main.c (install_signal_handler): Added support for OS/2 2000-07-30 * soundin.c (sreadin): Added WAV to code for AIFF/AIFC 2000-07-25 * swrite.c (fpnum): Allow E and e format in numbers 2000-07-22 * bowedbar.c: File file from STK3.1 * bowedbar.h: File file from STK3.1 * entry.c: Added wgbowedbar opcode 2000-07-17 * modal4.c (vibraphnset): Strike position was not set at all (agogobelset): Strike position now used, and modified gains * fm4op.c: All over changed ADSR parameters to STK3.1 values 2000-07-16 * physutil.c (ADSR_setAllTimes): New function to keep in step with STK3.1 * modal4.c (agogobelset): Change filter gains to value in STK3.1 (marimbaset): Ditto 2000-07-14 * aiff.c (aiffReadHeader): Added missing argument to message 2000-07-13 * filopen.c (sssfinit): Editing error corrected ## -> # * physmod.c (bowedset): Instantiated teh length/2 code as in later STK 2000-07-02 John Fitch * pvlook.c: Added code to log output from Windows * pvlookdlg.cpp: Added dialog info for output 2000-07-01 John Fitch * pvdlg.cpp (DoDataExchange): Check for illegal hopsize was backwards 2000-07-01 * sread.c (getscochar): * rdorch.c (rdorchfile): Patch (in part) from Istvan Varga for _ in macro names more safely 2000-06-26 * entry.c: Added clip opcode * one_file.c (createSample): New function to read base64 encoded samples (read_base64): New function to allow multiple use (deleteSamp): Delete samples created (read_unified_file): Added option and (createFile): Create file locally if safe from Base64 2000-06-23 * util1/sortex/xmain.c (fopen_path): * util1/sortex/smain.c (fopen_path): $s should be %s twice 2000-06-19 * rdorch.c (rdorchfile): * sread.c (sget1): Allow _ as a part of a macro name * one_file.c (createMIDI2): Added Base64 encoded MIDI files (read_unified_file): and direct to it 2000-05-28 * VERSION 4.06 * entry.c: Added trigseq and seqtime opcodes 2000-05-26 * pitch.c: Added pinkish code. * pitch.h (struct): Added PINKISH structure * entry.c: Added pinkish opcode (re) 2000-05-25 * entry.c: Added opcodes sfplay3, sfplay3m, sfinstr3, sfinstr3m * sfont.c etc: many changes. Lots of ANSI corrections and layout 2000-05-14 * entry.c: control and setctrl for Tcl/Tk and renamed for CWin * sliders.tk: New file (needs serch paths?) * control.c: Added Tcl/Tk version of sliders 2000-05-13 * getstring.c (init_getstring): Removed unnecessary new name variable, as also wrong! 2000-05-10 * aops.c (inall): Change to read a single numbered channel only 2000-05-09 * vbap.h: Added zak opcoes, increased channels to 64 * vbap_zak.c: New file * entry.c: Added vbap_zak opcodes 2000-05-08 * schedule.c: Change to triggering on negative triggers etc * midirecv.c: (MidiOpen): (MidiOpen): Added OS2 support * main.c (main): Added OS2 support 2000-05-07 * soundio.c (audwrite_norm): (audwrite): Make Heartbeat==3 use title bar in CWIN case * fgens.c (gen23): Use fopenin rather than fopen (gen28): Ditto * filopen.c (fopenin): Like openin, but also looks in INCDIR * vpvoc.c: Check that there is a segment table * aops.c (outz): New opcode to link XAK to output (inz): and input to zak * cs.h (MAXCHNLS): Change max number of channels to larger number 256 * aops.c (inn): New function for below (in16): (in32): (inall): New opcodes for larger numbers of channels * entry.c: Added opcodes inx, in32 and inc 2000-05-02 * makefile (CSRCH): Added vbap.c vbap_four.c vbap_eight.c vbap_sixteen.c * vbap.c: * vbap_four.c: * vbap_eight.c: * vbap_sixteen.c: * vbap.h: New files for VBAP opcodes * entry.c: Added vbap opcodes 2000-04-26 * entry.c: Change madsr to call madsrset as below * ugens1.c (adsrset1): Only set xtra time if in MIDI context. Rename function from adsrset (adsrset): New function to use above (madsrset): Ditto 2000-04-23 * rdorch.c (getoptxt): Decode out->outx/outX * aops.c (outn): new function to handle multi-channel outouts (outx): (outX): Use for 16 and 32 (outch): New code to write to numbered channel (outall): Write all channels of any number * aops.h: New structures OUTX and OUTCH * entry.c: New opcodes outx, out32 and outch 2000-04-22 * sread.c (getpfld): Check for curmem overflow in the loops (yeak!) 2000-04-21 * sftype.h: * sf.h: Added PACKED and pack() attributes 2000-04-16 * entry.c: Added additional argument to scans * scansyn.c (scsns_init): Made oscil_interp a selectable variable, defaulting to 4 (scsns_play): And at play time * scansyn.h (struct): Added variables to select interpolation scheme 2000-04-10 John Fitch * VERSION 4.05 released * fout.c (outfile_int_head): (close_files): * soundio.c (sfcloseout): (audwrite_norm): (audwrite): * wave.c (write_wavpeak): (wavReWriteHdr): * aifc.c (aifcReWriteHdr): * aiff.c (aiffReWriteHdr): Added verbose argument to control peak message 2000-04-04 * winX11.c (DrawGraph): Patch to deal with large graphs (David Ogborn) 2000-04-04 J P Fitch * fgens.c (gen23): Corrected deferred case 2000-04-03 * fgens.c: patched from David Ogborn 2000-04-03 J P Fitch * diskin.c (sreadinew): More peak stuff (sngetset): Ditto 2000-04-03 * util1/sortex/xmain.c (dies): Define this function * util1/sortex/smain.c (dies): Define this function 2000-04-02 * musmon.c (playevents): remove calls to write peak chunk as done elsewhere * soundio.c (audwrite_norm): Added normalisation stuff for WAVE floats (audwrtrev4): Same here (audwrt4): Abd fir none bytereversing version (sfopenout): FLOATS and LONGS now similar Call non-reversing fixups correctly 2000-03-31 * soundin.c: Changes all over to take account of gain stuff * sndinfo.c (sndinfo): Small change in case no data * sread.c (sread): Check can open file * one_file.c (read_unified_file): Check file was opned OK (createScore): Ditto * wave.c (wavWriteHdr): many changes to set correct variable-header length etc (RWD) (wavReWriteHdr): Ditto * aiff.c (aiffWriteHdr): Incorporate Peak chunk fully (aiffReWriteHdr): ditto (aiffReadHeader): ditto (aiffReadHeader): ditto (write_aiffpeak): Correct code (all RWD) * aifc.c: Extensive incorporation of Peak chuncks and other such (RWD) 2000-03-26 John ffitch * entry.c: Added opcodes scsnu,scsns, sfload, sfpreset, sfplay, sfplaym, sfplist, sfilist, sfpassign, sfinstrm, sfinstr * sf.h, sftype.h sfenum.h: * sfont.c: New files 2000-03-26 John * midiops3.c: * midiops3.h: Change char to unsigned char throughout 2000-03-25 John * scansyn.[ch]: New file implementing scanned synthesis * rdorch.c (lblfound): realloc forgot to multiply by sizeof(LBLREQ) (lblrequest): Did not extend in this case. * main.c (main): Added general signal handler to call exit so can do temporary clean-up 2000-03-22 John * musmon.c (musmon): Remove extraneous fclose(scfp) 2000-03-21 John ffitch * soundio.c (bytetran): Add optional dithering of output * main.c: Added declaration of dither_output * argdecode.c: Added -Z option, and new string 1485 2000-03-17 John ffitch * VERSION 4.04 (Linux only: no notes) * ugens5.c (atone): output could destroy input before it was used. (atonex): Ditto 2000-02-22 John ffitch * otran.c (otran): Calculation of tran_kr was wrong 2000-02-20 John ffitch * VERSION 4.03 * ugens4.c (krand): Added support for a base value (arand): (krandh): (randh): (krandi): (randi): * aiff.c (aiffReadHeader): If no loop in sample, pretend loops whole sample (experimental at present) * sfheader.c: Move definition of maxpos etc to this file * sndinfo.c: Change size of arrays to MAXCHNLS 2000-02-15 John ffitch * soundio.h: New structures for peaks * wave.c (write_wavpeak): * aiff.c (write_aiffpeak): New function * musmon.c (playevents): Call functions to write peak chunk * grain.c (agsset): Clear buffer if reusing 2000-02-13 John ffitch * wave.c (wavReadHeader): Started support for WAV loops * wave.h: Added smpl and SampleLoop structures * schedule.c (lfoa): Calculation of inc was wrong 2000-02-12 John ffitch * ugens3.c (losset): Default base freq to middle C if missing * entry.c: follow2 opcode * follow.c (envset): (envext): New code * follow.h (struct ENV): New structure 2000-02-07 John Fitch * one_file.c (mytmpnam): New function in WIN32 case * cs.h: Use mytmpnam of WIN32 systems 2000-02-06 John Fitch * util2/scale.dir/scale.c (main): Added code for M and P options (FindAndReportMax): Make return a value of maximum 2000-02-04 J P Fitch * util2/pvlook/pvl_main.c: Add #include for 2000-02-03 John ffitch * pvanal.c (pvanal): Set trfil to stdout in code rather than in initialisation. * midirecv.c (FMidiOpen): Set mfp to stdin in the open code rather than in initialisation. * getstring.c (init_getstring): #endif was one wrong line which broke CSTRINGS mechanism 2000-01-29 John ffitch * VERSION 4.02 * sread.c (ifa): Need tp set prvp2 in . and + cases, as well a ^ 2000-01-13 John ffitch * diskin.c, insert.c, memfiles.c, midirecv.c, pvanal.c * rtaudio.c, rtdirectX.c, rtwin32.c, wincwin.c, window.c, winwat.c Change IGNORE to IGN to please Windows 2000-01-07 John ffitch * musmon.c (musmon): Close the scfp file (sorted score) so it can be deleted. 2000-01-06 John ffitch * insert.c (kperf): Removed check for interaction in instr loop 2000-01-05 John ffitch * rtwin32.c: Change type of indev to HWAVEIN as it should have been * schedule.c (queue_event): Added cast to float for insno * cwin.cpp (OnHScroll): Incorrect & changed to && (AfterSizeChange): Ditto * cs.h (POLL_EVENTS): Error in cwin case? * ugrw1.c (tablew): Incorrect & changed to && (ktablew): Ditto 1999-12-05 John ffitch * fgens.c (gen23): Allow for negative numbers in reading, and initilaise p in open case. * insert.c (kperf): On Windows and Mac/BeOs silences were too long, possibly upto 127 cycles too long. 1999-11-27 John ffitch * midiops3.c: Throughout slider code ensure min++ is obeyed after the assignment (undefined in ANSI C) 1999-11-23 * Cwin.cpp (cwin_exit): Use special code rather than AwaitInput, using wait_for_char variable (cwin_exit): Ditto (OnChar): Set wait_for_char every time 1999-11-21 John ffitch * VERSION 4.01 * uggab.c (resony): Read flag field for log or linear separation * uggab.h: New field in RESONY structure * entry.c: Change in arguments to resony * schedule.c (queue_event): New function to schedule score events into future (schedule): Call insert_event or queue_event depending on when; note midi will only work on now events (kschedule): Same fix. 1999-11-20 John Fitch * wincwin.c (DrawGraph): Add call to cwin_paint back * cwin.cpp (cwin_show): If picture in ontop do not redraw 1999-11-20 John ffitch * all_strings, english-strings: Make version number print in x.xx format (237) * space.c (space): Use local variables rather than p->ch1 etc (RK) 1999-11-18 John ffitch * pvinterp.c (pvbufreadset): * pvread.c (pvreadset): Change test to less than 128 for small frame size (RK) 1999-11-18 John Fitch * argdecode.c (usage): Added message for -t0 and also error string 425 1999-11-07 John ffitch * VERSION 4.00 -- Version for CD-ROM * midirecv.c: Added AMIGA loading of * musmon.c (musmon): Only complain about no score if also no line events. * main.c (main): In normal use use a temporary for scorename and playscore; if -t0 use score.srt * argdecode.c (argdecode): usurp -t0 to mean keep tempraries 1999-11-02 John ffitch * flanger.c (wguide2): Separate a- and k- rate cases, for speed against mixing (wguide1): Ditto * english-strings: Added error message 424 1999-10-31 John ffitch * VERSION 3.591 * shaker.c (shakerset): Do not crash is number of beans is zero * fgens.c (gen21): Ensure a scale of zero is make 1 if argument is missing * midirecv.c (MidiOpen): Misplaced #endif moved () 1999-10-25 John ffitch * otran.c (insprep): Remove reassignment to nlabels, so it will act as a maximum. 1999-10-24 John ffitch * rdorch.c (skiporchar): New function to skip to end of line, string or file * fgens.c (besseli): Make besseli a double->double function (gen20): rewrite kaiser case for effeciency and accuracy * cmath.h: Make besseli a double->double function * ugens6.c (delwset): Remove nulling of last_delayr (delrset): Check for first-delayr rather than last-delatr (Groh) 1999-10-16 John ffitch * one_file.c (createScore): (createOrchestra): Use fputs rather than fprintf as should not interpret formats 1999-10-11 John ffitch * VERSION 3.59 * one_file.c (deleteScore): no longer static (same for sconame) * main.c (main): If no score given generate f0 86400 score, and arrange to delete at end 1999-10-10 John ffitch * main.c (main): Rearrange order of code to allow MIDI initialisation * one_file.c (my_fgets): New function to deal with PC/Unix/Mac files equally. * entry.c: Added ktableseg for tutorials * midiop2.c: * midiops3.h: Separate SLIDER* structs and code * entry.c: Correct structs for sliders 1999-10-09 John ffitch * otran.c (constndx): Initial poolcount set to 1 for SSTRCOD * vpvoc.c (vpvset): If a table is given use it rather than remembered table[x]seg * vpvoc.h (struct): New field in VPVOC structure for optional argument to set table from f ops * one_file.c (createMIDI): Skip to newline after reading a MIDI file (read_unified_file): Set O.FMidiin if a MIDI file was given 1999-10-05 John ffitch * linevent.c: If event is e no not complain about number of args * insert.c (MIDIinsert): Deal with pset in MIDI case (MIDIinsert): No error if psetdata set * one_file.c (read_unified_file): Only change Midi file if read (createMIDI): set flag * ugens1.h: Extra field xtra in LINSEG and EXPSEG * ugens1.c (mxdsrset): Added additional argument to length of release (lsgset): Set xtra to -1 (adsrset): Deal with additional release (lsgrset): Set to -1 (klnsegr): (linsegr): (xsgrset): (expsegr): (kxpsegr): More of same change 1999-10-02 John ffitch * biquad.c: * entry.c: removed "nlalp" pending clarification of IPR 1999-09-26 John ffitch * ugens5.c (tonset): Initialise constants more carefully (tonsetx): The same (tone): The same (tonex): The same (atone): The same (atonex): The same * ugens1.c (klnseg): Rewritten to be same as linseg wrt new segments 1999-09-25 John ffitch * nlfilt.c (nlfilt): Protect L field * cross2.c (Xsynthset): Stop changing ovlp and take new field (Xsynth): Use new field * windin.c (xyinset): Protect a number of fields * grain.c (ags): Stop p->kglen being overwritten * vdelay.c (nreverb): Ensure p->hdif and p->time are not overwritten * repluck.c (wgpsetin): Ensure p->plk is not changed * otran.c (constndx): Removed attempt to have unique constants as it breaks otherthings, not understood 1999-09-22 John ffitch * ugsc.c (phaser1set): Fix array limitations (phaser2set): Similar 1999-09-22 John ffitch * entry.c: Added phaser1, phaser2 and lowpass2 * ugsc.c (phaser1): (phaser2): (lp2): New code 1999-09-12 John ffitch * entry.c: Adjust args to wguide1/wguid2 * aops.c (powoftwoa): New function (logbasetwoa): New function 1999-09-09 John ffitch * express.c (express): Added a^p case whicg was missing * entry.c: removed opcodes from entry as well * ugrw1.c: remove deprecated instime[sk] * dumpf.c: Remove depricated names 1999-09-08 John ffitch * biquad.c (nlalp): (nlalp_set): New functions * biquad.h (struct NLALP): New structure * entry.c: Added nlalp 1999-09-07 John ffitch * musmon.c (musmon): Change commented-out test to O.Linein 1999-09-05 John ffitch * schedule.c: New code for schedkwhen * musmon.c (playevents): * insert.c (kperf): Look for orcevents as well * cs.h: Added OrcEvts field to OPARMS * entry.c: Add schedkwhen * ugens2.c (kphsor): Make phs a double, and consequent changes (phsor): phase and incr double, and consequents * ugens2.h: Make curphs double rather than FLOAT * uggab.c (posc): (kposc): (posc3): (kposc3): Allow negative freq * cwin.cpp (cwin_args): Set FMidiin when teh profile has one * ugens4.c (pluck): Error check for kcps exceeding sample rate * fgens.c (fgens): Typing error == instead of = 1999-08-30 John ffitch * otran.c (constndx): Sharing constants leads to problems so make each one unique 1999-08-29 John ffitch * pitch.c (pitch): Slight code shifting (re) * pitch.c (phsorbnk): New code for new opcode 1999-08-27 John ffitch * VERSION 3.58 * entry.c: New opcode pitchamdf * pitch.c (pitchamdfset): (medianvalue): (pitchamdf): New functions 1999-08-25 John ffitch * midiops.h: Removed MIDIVAL and MIDISCL as they are really MIDIKMB * midiops.c (midibset): Initialise prvbend as it was random (pitchbend_value): reinstate null check * entry.c: New opcodes adsynt and hsboscil * pitch.c (adsyntset): (adsynt): (hsboscset): (hsboscil): New functions * pitch.h (struct ADSYNT, HSBOSC): New structs 1999-08-23 John ffitch * repluck.c (streson): Change sign of output sample * one_file.c (eat_to_eol): New function to handle comments in <> context. (readOptions): Alow empty lines * sread.c (ifa): in case3 with warpin check for i or f opcodes 1999-08-20 John ffitch * ugensa.c (fogset): * ugens7.c (fofset0): Only allocate space if phs is positive; may allow legato * dumpf.c (krdset): (krd2set): (krd3set): (krd4set): openout shoudl have been openin * midisend.c: Define __RPCASYNC_H__ for VC++ v6 (Michael Gogins) * sread.c (sget1): * rdorch.c (rdorchfile): Deal with spaces in macro definitions (re) * one_file.c (read_unified_file): Close unf file before return 1999-08-05 John ffitch * wincwin.c (MakeXYin): (ReadXYin): Rewritten to use whole screen 1999-08-04 John ffitch * sread.c (sget1): * rdorch.c (rdorchfile): Make number of arguments flexible in macros 1999-08-02 John ffitch * VERSION 3.57 * pitch.c (cpuperc): New function to set cpu load (maxalloc): Ditto (prealloc): Ditto * cs.h: Added cpuload field to INSTRTXT 1999-08-02 J P Fitch * argdecode.c (argdecode): variable outformch made static (argdecode): Make it a warning rather than an error to have two values * main.c (main): [rasmus ekman] the default sampel size was set before the .csd decode. Now moved to after 1999-08-01 John Fitch * physmod.c (DLineA_tick): Test for wrapround was wrong 1999-08-01 John Fitch * vdelay.h: Added nreverb header to this fiel and remove nreverb.h * modal4.c (marimbaset): multiple strikes controlled by optional arguments * entry.c: marimba gains two optional arguments * modal4.c (marimbaset): Triple strike could not happen; fixed. Also made messages look at message level 1999-07-31 John ffitch * argdecode.c (argdecode): Make utility decode table driven, and add pvlook * util2/pvlook/pvl_main.c: New file to call pvlook * pvlook.c: New file (from Richard Karpen) changed to utility 1999-07-30 John ffitch * ugens6.c (delrset): (delwset): (tapset): Added FIFO * ugens6.h: Added delay FIFO to DELAYR 1999-07-29 John Fitch * diskin.c: Reconstructed after matt * insert.c: Reworked all POLLEVENTS stuff after matt * sndinfUG.c: New file for interrogation of snd files * entry.c: Added filelen, filenchnls, filesr and filepeak opcodes * musmon.c (playevents): Simplification of calls to POLLEVENTS * fout.c: mark non ANSI stuff as not on macintosh * one_file.c (macgetstring): Renamed function from getstring * argdecode.c (argdecode): -P option for Macintosh 1999-07-26 John Fitch * aops.c (init_powers): (init_logs): (powoftwo_set): (logbasetwo_set): (powoftwo): (logbasetwo): New functions for fast 2^ and log_2 * sread.c (sget1): Change test to >MARGS rather than >=MARGS * cscormai.c (main): Call init_getstring * natben.c: New file (for cscormai.c really, but could be used elsewhere) 1999-07-26 John ffitch * fgens.c (gen23): Added deferred allocation by counting first (fgens): Admit gen23 for deferred (hfgens): Ditto * ugens1.c (xsgset2): New function (expseg2): New function * entry.c: Added expsega 1999-07-25 John Fitch * rdorch.c (getoptxt): DIVZ case was confused with peak case; changed tag to 0xfffc * entry.c: Ditto * insert.c (beatexpire): Count deallocation (timexpire): Ditto 1999-07-25 John ffitch * entry: Added active opcode * pitch.c (instcount): New function to recover active count * insert.c (insert,MIDIinsert): Count new activation (deact): and uncount * cs.h: Added active filed to INSTRTXT * ugens4.c (buzz): (gbuzz): Take absolute value on khd and suppress warning 1999-07-20 John Fitch * rtwin32.c: Reworking by RWD after NT experience 1999-07-20 J P Fitch * pitch.c (clockset): Got clocks wrong in setup -- all mapped to clock 0 1999-07-19 John ffitch * RELEASED VERSION 3.56 * one_file.c (blank_buffer): new function to allow blank lines in gap * fout.c: New file * fout.h: New file 1999-07-18 John Fitch * winX11.c (ExitGraph): Ignore any errors 1999-07-18 John ffitch * sread.c (getscochar): Allowed @ in arithmetic part, and @@ for guard. Gives next power of 2 up, between 1 and 0x40000000 Also corrected ~ case 1999-07-10 John ffitch * uggab.c (fold): New function (after Gabriel, but optimised) (fold_set): * entry.c: Added resony, fold opcodes * uggab.c (rsnsety): (resony): New functions (after Gabriel to remove restriction) * uggab.h (struct): New structures for resony and fold 1999-07-08 John ffitch * insert.c (insert): Added psetdata handling on insert 1999-06-27 * Cwin.cpp (class CSenv): Dialog to set SSDIR etc (CArg): Remember last env in registry, and reset in non-null * winsound.rc: New Dialog for setting environment 1999-06-26 * getstring.c (init_getstring): Ensure name is remembered in Winsound * Cwin.cpp (OnEditOrch): Change to NOWAIT spawn of editor (OnEditScore): Ditto (cwin_exit): Interrupt playing if character typed 1999-06-26 John Fitch * follow.c (follow): Read off end of input; change to post increment 1999-06-20 John ffitch * VERSION 3.55 released * util1/scot/main.c (main): * util2/mixer/extract.c (main): * util2/mixer/mixer.c (main): * lpanal.c (lpanal): * sndinfo.c: * pvanal.c: Accept -j * getstring.c (init_getstring): Look for environment variable CSSTRNGS as well * argdecode.c (argdecode): Skip -j option * main.c (main): init_getstring needs arguments * getstring.c (init_getstring): Check for a -j command line parameter to change strings database. Messy! 1999-06-15 J P Fitch * cwin.cpp (OnExtras): Set Beatmode as well as Cmdtempo when needed 1999-06-05 John ffitch * aops.c: editting error, LIB1 rather than LIBA in asin to log10 (thanks Nicola) 1999-06-04 John Fitch * getstring.c (init_getstring): Change error string 1999-05-30 John ffitch * mandolin.c (mandolin): Rescale sound to get amplitude correct (infoTick): allDone was not initialised * mandolin.c (mandolinset): Added 50Hz as lowest frequency for Mandolin 1999-05-29 John Fitch * rdorch.c (getoptxt): Allow Z as an argument type for a list strating with a kvar, and alternating with avar 1999-05-29 John ffitch * ugens3.c (loscil3): There was no multiply by the amplitude. 1999-05-28 John ffitch * cwin.cpp (cwin_args): Do not add .wav/.aif if dac/devaudio 1999-05-27 John Fitch * text.h: New message * pitch.c (mac, macset): Added new opcode * ugsc.h: * ugsc.c: New files * entry.c: Added opcodes svfilter, hilbert, resonr, resonz. mac 1999-05-24 John Fitch * ugens4.c (buzz): Report knh <=0 once once per note (gbuzz): Same * ugens4.h: New field reported in BUZZ/GBUZZ to suppress excess messages 1999-05-20 J P Fitch * ugens1.c (linseg): (linsegr): (klnsegr): (kxpsegr): (expsegr): (klnseg): Test for out of count was wrong -- replaced by <= 1999-05-17 J P Fitch * VERSION 3.54 released * getstring.c: New file * cs.h: #include text.h * makedb.c: New file to build strings database 1999-05-10 John ffitch * ALL FILES nearly: Added STR macro to strings in preparation for localisation. Later changed to Str 'cos of Irix4 * text.h: new file for localisation. 1999-04-27 John Fitch * uggab.c (product): New code * entry.c: New opcode product 1999-04-27 J P Fitch * entry.c: Rename nsamp to nsamp_i so it can be used! 1999-04-18 John ffitch * main.c (main): Check for .csd and .CSD as DOS messes endings 1999-04-17 John ffitch * biquad.c (biquad): Optimise by using local variables more (pareq): The same (rezzy): The same (moogvcf): Same 1999-04-10 John ffitch * fgens.c (fgens): Added 0.5 to avoid rounding problems * musmon.c (playevents): * linevent.c: Accept e event 1999-04-09 John ffitch * entry.c: Added sum opcode * uggab.c (sum): Added new function * biquad.c (pareq): Changes /2 to *0.5, and stopped recalculation of sqrt 1999-04-06 John ffitch * rdorch.c (getoptxt): Gabriel changes for y and z argument types 1999-04-05 John ffitch * fm4op.c (FM4Op_loadWaves): Initialise w_time array to zero 1999-04-02 John ffitch * cwin.cpp (cwin_args): Add .wav or .aif if no . in name * soundio.c (sfopenout): Default name to test.wav test.aif or test depending on filetyp * rdorch.c (rdorchfile): Check for argument being too long * argdecode.c (argdecode): Section brackets neded in case 'o' due to #ifdef badly used. 1999-04-01 John ffitch * pvread.c (pvreadset): Correct error mesage to say PVREAD rather than PVOC 1999-03-31 John ffitch * biquad.c (vco): * vpvoc.c (voscili): * ugens7.c: * ugens4.c: * ugens3.c: * pvadd.c (pvadd): * spectra.c: * grain.c (ags): * disprep.c (tempeset): * ugensa.c: * ugens2.c: PMASK -> PHMASK for clarity, avoiding Solaris problem and consistency with Barry's sources. 1999-03-25 John ffitch * soundio.c (sfopenout): Piped output must be raw or IRCAM format. Force AIFF and WAv to IRCAM 1999-03-23 John ffitch * cmath.c (irate randoms): All improved coding to minor effect 1999-03-21 John ffitch * VERSION 3.53 * sread.c (getscochar): Accept ~ to indicate a random number * entry.c: Added pitch opcode * pitch.h: * pitch.c: New file * physmod.c (flute): Code improvements to save reading variables inside nsmps loop. 1999-03-20 John ffitch * sysdep.h (tell): Define tell is SYS5 case as it seems to be rare 1999-03-19 J P Fitch * entry.c: use 0xffd for peak opcode * rdorch.c (getoptxt): Use code 0xffd for discrimination on first argument (and not answer) 1999-03-19 John ffitch * soundin.c (soundin): * diskin.c (soundinew): only do code after filend in ngoto is strictly positive 1999-03-14 John Fitch * midiops.c (cpsmidi): Remove pitchbend stuff from cpsmidi * entry.c: Size field in aftouch was wrong 1999-03-11 J P Fitch * sread.c (stof): NeXT fix confusing ramps 1999-03-11 John Fitch * physmod.c (clarinset): (fluteset): (bowedset): (brassset): Assume 50Hz lowest freq if not given 1999-03-10 John Fitch * physmod.c (fluteset): Assume intital amplitude is maximum to avoid a problem with zero. Do not understand this yet, but something to do with ADSR AttackRate. 1999-03-09 John ffitch * entry.c: opcode envlpxr had wrong structure, so could have crashed 1999-03-05 John Fitch * mandolin.c (mandolinset): Allow for skipping initialisation, and add error check. * shaker.h: File not transferred to PC leading to crashes 1999-02-21 John ffitch * entry.c: Change names ondur/ondur2 to the more natural noteondur/noteondur2 Also chanctrl base opcode was missing * aops.c (ftlen): Change to call ftnp2find so any deferred table is loaded before giving teh length. 1999-02-20 John Fitch * ustub.h: Added declaration of currevent * vdelay.c (vdelay3): Setting of v0 could be wrong (possibly?) * pvadd.c (pvaddset): * pvinterp.c (pvcrossset): (pvbufreadset): (pvinterpset): * ugens9.c (cvset): * ugens5.c (lprdset): * ugens3.c (adset): * soundin.c (sndgetset): * diskin.c (newsndinset): Added support for string arguments in score (GAB) * rtnext.c: New file * Makefile: * diskin.c: * entry.c: * linevent.c: * midirecv.c: * sfheader.c: * soundin.c: * soundio.c: * soundio.h: * sread.c: * ugens2.c: Added NeXT code 1999-02-18 J P Fitch * entry.c: The ftsr opcode got lost * biquad.c (nestedapset): New code (nestedap): New code (lorenzset): New code (lorenz): New code * biquad.h: Added NESTEDAP and LORENZ struct 1999-02-14 John ffitch VERSION 3.52 * dumpf.c: Added readk code * dumpf.h: Added KREAD structures * entry.c: Added readk, readk2, readk3 and readk4 * ugens6.c (deltap): Safer test for tap point (deltapi): Ditto (deltapn): Ditto (deltap3): Ditto * swrite.c (pfout): (expramp): Allow () as alternatives to {} * sread.c (operate): Added % and ^ to arithmetic operations (getscochar): Ditto * uggab.h: Add structs for poscil and lposcil * uggab.c: Add code for poscil and lposcil and cubic forms * entry.c: Added poscil and lposcil, poscil3 and lposcil3 * follow.c (follow): Make it follow max abs value rather than max and min separately. Recode for speed as well. (flwset): Recoding for speed later 1999-02-13 John Fitch * sread.c (getscochar): Typing error strlen(b+1)=>strlen(b)+1 1999-02-13 John ffitch * ugens5.c (rsnsetx): Test for new buffer was wrong (tonsetx): Ditto 1999-02-12 John ffitch * ugrw1.c: Deprecated itable* opcodes * modal4.c: Added deprecated message to agogobel * entry.c: Changed all iout* to outi*, kout* to outk* ion/ioff -> noteon/noteoff. midic#/imidi# unified ctrl#/ictrl# unified itable* -> tablei* with deprecated version with message 1999-02-11 John ffitch * entry.c: Changes islider# to slider#_i, similar for slider# and dummy entry. ilimit removed for limit_i etc, itableleng itimes/k 1999-02-09 John ffitch * ugens5.c (tonsetx): Only create buffer of states if initialising and buffer not present. Should remove some clicks. (rsnsetx): Same change 1999-02-08 J P Fitch * aiff.c (aiffReadHeader): Recognise Name, Author, Copyright and Annotation chunks 1999-02-07 John Fitch * oload.h: LABELIM needs to reference nlabels rather than NLABELS * otran.c (insprep): Ensure that goto list is long enough, not just expanded -- probably not necessary * rdorch.c (rdorchfile): Need to extend srclin array as well as linadr array when run out of lines. 1999-02-06 John ffitch * entry.c: Change distort1 to appoo at HM's suggestion 1999-02-05 John ffitch * aiff.c (aiffReadHeader): Skip unknown chunks * biquad.c (biquadset): If reinit field is not zero skip initialisation * entry.c: Added optional extra arg to biquad to control reinit 1999-01-31 John ffitch * VERSION 3.511 * rtaudio.c: split into platform specific bits, and Makefile changed for this. * midiops.c (pitchbend_value): Remove subtraction (and comment) as now handled in midirecv.c * entry.c: all 3 midip_k opcodes shoudl have thread of 3 * distort1 should have thread of 4 not 5 * physmod.c (fluteset): Length of deay line set wrong if optional last argument omitted 1999-01-27 J P Fitch * ugens1.c (adsrset): Length incorrectly set in MIDI subcase. * diskin.c (newsndinset): Function replaced from matt 1999-01-26 John ffitch * sndwarp.c (sndwarp): New line from RK to handle rounding oddity (sndwarpst): Ditto 1999-01-26 J P Fitch * rdorch.c (fopen_path): Correct typing error of $s instead of %s 1999-01-26 J P Fitch * biquad.c * butter.c * cmath.c * dsputil.c * dsputil.h * filter.c * locsig.c * lpanal.c * modal4.c * oload.c * pvinterp.c * space.c * spectra.c * ugens8.c * vpvoc.c * wavegde.c * ugens3.c * fgens.c * prototype.h: Removed variable pi and twopi and used macros instead. In places improved code (ie use TWOPI rather than 2.0*pi) and in spectra.c corrected constants 1999-01-25 John ffitch * express.c (express): Deal with ^ when second argument is c k or i 1999-01-24 John Fitch * VERSION 3.51 * rdorch.c (rdorchfile): Change treatment of \ line continuations 1999-01-24 John Fitch * main.c (main): If argdecode returns zero then exit as all done 1999-01-24 John ffitch * one_file.c (readOptions): Lines starting ; or # treated as comments. Also options starting ; or # end line * follow.c (follow): Improved coding, removing divison etc 1999-01-23 John ffitch * entry.c: Added xadsr and mxadsr opcodes * ugens1.c (adsrset): Added release stuff for MIDI case (xdsrset): New function (mxdsrset): New function 1999-01-23 John ffitch * one_file.c: Changed some printing to _DEBUG only * main.c (main): Check for empty score string as well as null in .csd case * ugens1.c (adsrset): Calculation of length remaining corrected * cwin.cpp (OnOrchestra): Look for .csd files as well 1999-01-22 J P Fitch * one_file.c (readOptions): Check for \r as well as \n as terminator 1999-01-19 John ffitch * sread.c (sget1): Allow /* */comments in scores * rdorch.c (splitline): Correct /* */ comments * ugens2.c (koscl3): Bug in reading table fixed 1999-01-17 John Fitch * argdeccode.c: Take account of AE_24INT in part * soundio.h: Added AE_24INT * cmath.c (ipow, apow, kpow): * cmath.h: (POW) rename pow filed to powerOf to avoid Mac problem * physmod.c (bowed): All code for setting frequency and betaratio was wrong; re-writen. 1999-01-16 John ffitch * entry.c: Added envlpxr opcode which was missing 1999-01-15 John ffitch * physmod.c (bowed): Set slope field as was missing 1999-01-13 J P Fitch * VERSION 3.50 * otran.c (otran): Zeroing instrument table started in wrong place (insprep): Reset ngotos and nlabels at start of function 1999-01-12 John ffitch * vdelay.c (deltapn): Added deltapn 1999-01-10 John ffitch * biquad.c and biquad.h: Added pareq opcode * ugens6.c (deltap3): New function * ugens2.c: Cubic interpolating versions of foscl, loscil and table * entry.c: Change parameter of foscil(i) to xkxxkio * ugens3.h (FOSC): Added new fields for below * ugens3.c (foscili): (foscil): Make more parameters a-rate possibly * entry.c: Added p parameter to moodvcf * biquad.h (MOOGVCF): and max field * biquad.c (moogvcf): Added max scaling 1999-01-04 John Fitch * entry.c: slider (MIDI) opcodes added * midiops3.h: * midiops3.c: New files * entry.c: Added Gabriel Maldonado's slider opcodes 1999-01-04 John Fitch * ugens2.c (koscl3): (osckk3): (oscka3): (oscak3): (oscaa3): New code for oscilators with cubic interpolation * entry.c: Added oscil3 family of opcodes 1998-12-29 John Fitch * ugens1.c (adsrset): Adjust ADSR for sustain too short etc 1998-12-25 John ffitch * aops.c: Added mod?? functions * entry.c: Added mod?? opcodes * express.c (express): Added % operator as mod, somewhat odd as a float. * entry.c: octmidib had flag wrong (editing error I suspect) * midiops.c (icpsmidib_i): (octmidib_i): (pchmidib_i): New functions * entry.c: *midib in i context needs new functions so it is initialised * cs.h: Remove posbend field as not used now. * midirecv.c (m_chanmsg): Remove posbend field (m_chinsno): Send pchbend field * midiops.c (pitchbend_value): Use pchbend field rather than posbend 1998-12-20 John Fitch * version.h; VERSION 3.494 * main.c (main): Decode .csoundrc file * argdecode.c: New file with argdecode funcion * main.c (main): Call argdecode rather than in line * one_file.c (readOptions): Implement reading of options, calling argdecode * schedule.c (lfok): Phase calculation for sine was wromg (schedule): Added code to kill stragglers on reinit (schedwatch): Clear list when done (kschedule): Ditto 1998-12-19 John Fitch * schedule.c (kschedule): Argument count in call to insert_event was wrong by one 1998-12-12 John Fitch * entry.c: New opcode streson * repluck.c (stresonset,streson): New functions * repluck.h: New structure STRES 1998-12-01 John ffitch * rdorch.c (lexerr): Variable mm had incorrect initialisation (re) 1998-11-24 John ffitch * physmod.c (bowedset): Set 'unknown state' values to -1 as the value of zero could be found in the product. 1998-11-21 John ffitch * ugens4.c (arand): Correct a typing error which gave noise in short rand vresion. 1998-11-20 John Fitch * aiff.c, cvanal.c, filopen.c, hetro.c, insert.c, linevent.c: * lpanal.c, main.c, memalloc.c, memfiles.c, midirecv.c, midisend.c: * musmon.c, mw_menu.c, one_file.c, otran.c, pvanal.c, pvoc.c: * rdorch.c, rtaudio.c, sfheader.c, sndinfo.c, soundio.c, wave.c: * windin.c, dpwelib.h, scot.h, sysdep.h, cs.h: Changed __MWERKS__ for macintosh so as not to confuse the BeOS port 1998-11-18 John ffitch * PVDLG.CPP (DoDataExchange): Confusion over hopsize and frame ince sorted out * Cwin.cpp (OnExtras): Move saving of profile into tested area so m_midiselector is valid (rasmus ekman) 1998-11-16 John ffitch * express.c (express): Start to add ^ to expressions for pow 1998-11-14 John Fitch * VERSION 4.392 * aiff.c (aiffReadHeader): Make message understand n-channels * wave.c (wavReadHeader): Added line giving file name as helps sndinfo. Also extended to multi-channel * rdorch.c (getorchar): Ignore ^Z from a file so as not to upset MS-DOS files * ugens4.c: Incorporate new 31bit rand into old opcodes with selector * ugens4.h (struct): Added new field to RAND RANDI and RANDH to select which PRNG 1998-11-14 John ffitch * rdorch.c (getoptxt): Use linopnum to check size as flag rather than many calls to strcmp (getoptxt): Change wrong out[sqho] to a warning and patch * entry.c: Added dummy pow (I had forgotten) * rdorch.c (getoptxt): Added pow to list of translation opcodes 1998-11-09 John Fitch * entry.c: Added opcodes rand2, rand2h and rand2i * ugens4.c: New set of random operators based on 31 bit Park Miller PRNG using Linus Schrage's method for a better version 1998-11-09 John ffitch * midirecv.c: Many changes in LINUX code 1998-11-08 John ffitch * rdorch.c (getoptxt): Added filter2, and fixed bug in intrpol (should be ntrpol). * dumpf.c (old_kdmpset, old_kdmp2set, old_kdmp3set, old_kdmp4set): New functions for kdmpset etc with warning * entry.c: New opcode midion (same as kon), and rename kon2 as midion2. Added dump for kdump etc. kfilter2 and filter2 as filter2_z * midiout.c (kvar_out_on_set1): New function, same as kvar_out_on_set except prints message asking to use midion. 1998-11-07 John ffitch * midiout.h (struct): Many new structures * midiops2.h (MIDIIN): New struct * oload.h: New type PCTL_INIT * entry.c: Added opcodes pctrlinit and dpctrlinit (GAB) midiin, midiout kon2 nrpn cpstmid * oload.c (instance): Channel searching (GAB?) (ctlinit): New function * midisend.c: Changes to LINUX code * midiout.c (iout_on): (iout_off): (iout_on_dur_set): (moscil): (kvar_out_on): (out_controller): (out_aftertouch): (out_poly_aftertouch): (out_progchange): (out_controller14): (out_pitch_bend): Channel has 1 subtracted (GAB) * midiout.c (xtratim): Extend only more required * midiops.c (aftouch): (imidictl): (midictl): (pchmidib): (octmidib): (cpsmidi): (icpsmidib): (kcpsmidib): (ipchbend): (kpchbend): Use MIDI_VALUE or pitchbend_value * midiops.c (massign): Additional code to check instr exists * midiops.c (MIDI_VALUE): (pitchbend_value): Added new macros to check null case 1998-11-03 John ffitch * vdelay.c (vdelay): At last someone [Ed Hall] has sorted out this confused comparison (vdelay): and again * ugens6.c (comb): Alpha exponential problem [Ed Hall] * sread.c (salcblk): * otran.c (otran): Alpha alighment again [Ed Hall] * opcode.c (list_opcodes): Deal with setting n in a beter and portable way [Ed Hall] * oload.c (oload): On alpha need to ensure alignment [Ed Hall] * insert.c (showallocs): On Alpha print in %p format [Ed Hall] * soundio.c (audwrite_norm): * linevent.c: * aiff.c: Added LINUX to non-options (was MAC only) [Ed Hall)] 1998-11-02 John ffitch * ugens1.c (adsrset): segsrem set one too high I think. 1998-11-01 John ffitch * hetro.c (TWOPI): Correct constant from 6.28308530 to 6.28318530 1998-10-29 John ffitch * linevent.c: * soundio.c: * rtaudio.c: pipe etc renaming for LINUX as well as SGI 1998-10-25 John ffitch * schedule.h: * schedule.c: New files 1998-10-25 John ffitch * insert.c: Make tieflag visible for schedule (showallocs): Make visible externally 1998-10-22 John ffitch * entry.c: Added schedule and schedwhen 1998-10-20 John ffitch * version.h: VERSION 3.49 1998-10-20 John ffitch * entry.c: Added envlpr opcode * ugens1.c (evrset): (knvlpxr): (envlpxr): New functions * ugens1.h (struct ENVLPR): Replaced definition as was not used anyway 1998-10-19 John Fitch * entry.c: ntrpol incorrectly specified **************** Send to Matt and Dave ********************** 1998-10-18 John ffitch * entry.c: Added madsr opcode, uses linsegr and adsr code 1998-10-18 John ffitch * sread.c (getpfld): Allow {} and ~ characters in scores (ifa): ^ refers to previous event of any instrument; needs new variable which is set to -1 and reinitialialed at sections etc * swrite.c (pfout): Added {} as calls to expramp and ~ to randramp (expramp): New function (randramp): New function 1998-10-17 John ffitch * entry.c: Added opcodes biquad, moogvcf and rezzy * biquad.c: * biquad.h: New files * musmon.c (musmon): Change name CsMidiOpen to MacMidiOpen * midisend.c: Support for MAC * midirecv.c: MAC declaration of MacSensMidi (m_chanmsg): Now global (m_chn_init): Now global (sensMidi): Code for MAC * main.c (main): Minor changes for MWERKS (dribble_printf): New MAC version * aifc.c (aifcReadHeader): Changes for Matt 1998-10-13 John ffitch * version.h: VERSION 3.49 1998-10-11 John ffitch * entry.c: New opcode adsr * ugens1.c (adsrset): Added adsr opcode to link to linseg 1998-10-11 John ffitch * swrite.c (swrite): Avoid extra space at end of score components 1998-10-11 John ffitch * cs.h: Mke size field in OENTRY a short again!! * swrite.c (swrite): REemoved some extra code in Unix sources * Pvread.h (struct PVREAD): Make fftBuf of type AUXCH * Pvread.c (pvreadset): Fill in fftBuf as a dynamic structure with auxmalloc (pvread): And in its single place of use 1998-10-07 John ffitch * ugens8.h (PVFRAMSIZE): Increased to 8196 and consequent changes * cs.h: Make size field in OENTRY an int 1998-10-06 John ffitch * fgens.c (gen23): New table generator * entry.c: Added wguide1 and wguide2 * aiff.h (Float32Name): Change at Matt's suggestion * main.c (main): Call fflush in case 'V' * soundin.c (sndgetset): Remember curr_func_sr in gen struct * fgens.c (gen01raw): Added memory of curr_func_sr 1998-10-05 John ffitch * aops.c (ftsr): Put ftsr back! * entry.c: rename to ntrpol 1998-09-19 * entry.c: Added intrpol_X opcodes and trig * uggab.c: * uggab.h: New files * rdorch.c (getoptxt): Translate mirror and wrap in _i context 1998-09-16 * ugens5.c (tonsetx): New function after Maldonado (tonex): Ditto (atonex): Ditto (rsnsetx): Ditto (resonx): Ditto * entry.c: Added opcodes tonex atonex resonx * ugens5.h: Added TONEX and RESONX structures 1998-08-25 John ffitch * musmon.c (musmon): Load orchestra before opening MIDI file 1998-08-24 John ffitch * entry.c: Entry for specptrk not in agreement with manual specdisp shudl have last argument optional 1998-08-23 John ffitch * oload.c (oload): NULL out new part of strsets when extending 1998-08-22 John ffitch * ugens4.c (rhset): Correctiosn to older version (buzz): Change the error on knh<=0 to warning and assume 1 1998-08-21 John ffitch * spectra.h: * spectra:c Added spectrum opcode * rdorch.c: Allow w op s,.. opcodes * fgens.c (GENUL): Added this function to stand for unknown gens * entry.c: Add spectrum opcode 1998-08-20 John ffitch * entry.c: Rename kport -> portk etc * wincwin.c: Remove tracing * sread.c (sget1): Another attempt at the interaction between \ and comments * entry.c: ktableseg and ktablexseg renamed as tableseg and tablexseg * midirecv.c (MidiOpen): Ensure m_chnbp array is NULLed and re-layout * soundio.c: * soundin.c: * sndinfo.c: * main.c: * diskin.c: * aifc.c: Change string AIFC to AIFF-C for consistency * midirecv.c (m_chanmsg): Add PROGRAM_TYPE case as was missing * opcode.c: In full case try to maintain better layout * lowpassr.c: Various adjustments * opcode.c: Change to 3 columns 1998-08-19 John ffitch * sread.c (sread): Correct typing error od 1.1 to 1.0 (ifa): Only warp p3 in i case 1998-08-18 John ffitch * ugens5.c (reson): Save value of asig at end (areson): ditto 1998-08-15 John ffitch * vpvoc.c (vpvset): * ugens9.c (cvset): * ugens8.c (pvset): * ugens5.c (lprdset): * ugens3.c (adset): * pvread.c (pvreadset): * pvinterp.c (pvbufreadset): * pvadd.c (pvaddset): * diskin.c (newsndinset): Allow strset in opening * oload.h (STRSMAX): Reduce this to 8 as it grows * oload.c (oload): Make strsmax a variable and expand table as required 1998-08-07 John ffitch * lowpassr.h * lowpassr.c: New code * entry.c: Added opcodes lowres, lowresx and vlowres * oload.c (instance): Deal with strset and pset specially * otran.c: Make ngotos visible * soundin.c (sndgetset): Treat strsets in opening a file * soundio.c (sfopenout): Treat output null as /dev/null * sfheader.c (rewriteheader): Support for /dev/null selection * cwin.cpp (set_up_argv): Allocate 1 longer to argv as it was bust 1998-08-06 John ffitch * otran.c: Make nlabel visible externally * oload.c (oload): Try copying string in STRSET (instance): Make nlabels into an extern and allocate lopds dynamically. * otran.c (otran): Deal with strset specially 1998-08-05 John ffitch * musmon.c (beep): On CWIN use system function Beep 1998-08-04 John ffitch * midirecv.c (m_chinsno): Check diasslowed instr 0 * sread.c (getscochar): * rdorch.c (getorchar): Map '\r' to '\n' * midirecv.c (m_chanmsg): Chsange O.SusPThresh to non zero * cs.h: Remove O.SusPThresh field * cwin.cpp (class CSextras): Remove m_pedal and all references 1998-08-03 John ffitch * rdorch.c (LENMAX): Reduce LENMAX to 100 as rather too generous 1998-08-02 John ffitch * RELEASE VERSION 3.484 1998-08-01 John ffitch * sread.c (sread): Introduce warp_factor for local time warping -- multiple scales etc. Defaults to 1.0, reset at section. Uses v * rdorch.c (lexerr): * sread.c (scorerr): Initialise mm * soundio.c: Changes to reporting in sfopenin/out * aifc.c (aifcWriteHdr): Argument order in memcpy wrong 1998-07-31 John ffitch * rdorch.c (splitline): Use realloc rather than alloc and copy for extending groups (twice) 1998-07-29 John ffitch * entry.c: Change addxx to add_xx etc * express.c (express): Another place where ki should be i_k Also change tags to _xx * flanger.c (flanger): Fix a JPff error in flanger 1998-07-28 John ffitch * entry.c: Last argument to flanger shoudl be v (optional 0.5 default) * sread.c (sget1): Use fopen_path function * rdorch.c (fopen_path): New function to use pathnames in include -- and elsewhere perhaps (rdorchfile): Use function 1998-07-26 John ffitch * sread.c (scorerr): New function for score errors in macros etc (getscochar): Give it an argument to say if we are expanding $ and [ 1998-07-25 John ffitch * lpanal.c (alpol): Removed reclaration of arrays a and x from alpol as it was inside the loop! * cwin.cpp (cwin_ensure_screen): Make it into a int function for new POLL_EVENTS() * aifc.c: New File * aiff.c (is_aiff_formtype): New function * aiff.h: AIFC-32 float support (MWERK only??) * windin.c (xyin): MWERKS version * wave.c (wavResetFrameSize): New fn for MWERKS * soundio.c: * sfheader.c: * sndinfo.c: MWERKS and AIFC support * rtaudio.c: MWEKS support all over * main.c: MWERKS suport and changes for AIFC * wavegde.c: * sysdep.h: * pvinterp.c: * pvanal.c: * otran.c (insprep): * musmon.c: * midirecv.c: * memfiles.c: * memalloc.c (memdie): * lpanal.c (lpanal): * linevent.c: * insert.c (kperf): * hetro.c (hetro): Added MWERK support * fgens.c: fmax renamed maxfnum 'cos of MWERKS name conflict * ftgen.h (MAXFNUM): Chane of name from fmax * filopen.c: * DPWELIB.H: MWERKS support * cvanal.c (cvanal): Add MWEKS to SYMANTEC if defined * cs.h (POLL_EVENTS): Make -i in cases when not used * butter.c: Added MWERKS support 1998-07-24 John ffitch * opcode.c (list_opcodes): Comparison stops at _ by copying strings * sread.c (sget1): heck #include file opened * rdorch.c: Use linepos rather than the broken atbol (rdorchfile): Check that #include file can be opened 1998-07-23 John ffitch * rdorch.c: * sread.c: Allow digits in macro names in both definition and use, by isdigit when not first chararcter 1998-07-22 John ffitch * soundin.c (sndgetset): Bug fix from Matt 1998-07-21 John ffitch * rdorch.c (getoptxt): Translate to divz_..; and for oscil(i_.. * entry.c: Put _ in divz opcodes and oscil(i) 1998-07-20 John ffitch * entry.c: Make gauss etc using the translate flag * rdorch.c (getoptxt): Us a flag of 0xffff to indicate ned for name translation. Move various midi ops to this syste 1998-07-19 John ffitch * main.c: Removed all references to Scot * fgens.c: Changed GEN01 to GEN1 in error messages etc. (gen20): Replaced large declared arrays with mmalloc'ed space which extends. * physmod.c (JetTabl_lookup): Remove fictious JetTable class, as it did not use the provious value. (flute): Change arguements to JetTabl_looup * flute.h: Added lastJet field Remove JetTabl field as not used * physmod.c (flute): Reorganise flute, setting of frequency when changed only etc. Sounds better. (fluteset): Minor initialisations of lastFreq and lastJet. 1998-07-18 John ffitch * physmod.c (DLineA_setDelay): Check that it is initialised; also fix serious typo in initialisation skip. * otran.c (otran): I had missed changing string "r=" to "=_r" Also check string has second char of _ rather than first of r * sread.c: New variable (flushing) to indicate when not to deal with [] things in scores (getscochar): Use it (flushlin): And set it 1998-07-17 John ffitch * physmod.c: For all physical models in theis file, if lowestfreq is negative, skip initialisation. (clarinet, flute, bowed, brass) 1998-07-13 John ffitch * flanger.h: * flanger.c: New file * entry.c: Added flanger entry * fgens.c (fgens): It cleared new part of table one too soon (hfgens): Ditto twice [Thanks Matt] 1998-07-11 John ffitch * otran.c (otran): It checked against MAXINSNO rather than maxinsno and so wiped out all instrs over 200! * fgens.c (gen01raw): Check against ALLCHNS-1 rather than 4 for channel count. (gen04): Suspected editing error as it went off end of the array. Moved an assignment outside loop. Should check old code. * winsound.rc: Change OK button to Render * ugens4.c (rhset): If seed provided is greated that 1 use it directly rather than scaling. * entry.c: Many function renames from axxx -> xxx_a etc * express.c (express): Make functions have _k at end rather than k at start. Fixes name polution problems. 1998-07-10 John ffitch * sfheader.h: Remove readopensf macro as not used anywhere! 1998-06-27 * otran.c (otran): Mistype of MAXINSNO instead of maxinsno 1998-06-25 John ffitch * entry.c: Removed voscili * vpvoc.c: 1998-06-24 John ffitch * entry.c: Removed extra argument in shaker opcode 1998-06-24 J P Fitch * shaker.h: Removed numtimes from structure as not used. 1998-06-23 J P Fitch * version.h: VERSION 3.483 * entry.c: Arguments for aftouch were wrong; made 2 optional * otran.c (otran): Allow STRSET in header blk 1998-06-15 J P Fitch * diskin.c (newsndinset): Bug fix from Matt * soundin.c (sndgetset): Bug fix from Matt 1998-06-02 * version.h: VERSION 3.482 1998-05-29 * Fgens.c (ftresdisp): Only call display if not already displayed displayed new variable. Many tables were getting displayed twice. May be better ways to do this though (fgens): Initialised this variable 1998-05-20 John ffitch * linevent.c (sensLine): If n negative Linend was wrongly set 1998-05-17 * rdorch.c (rdorchfile): Make stray # into a warning rather than error (getorchar): Remember when at start of line (rdorchfile): Only check # when at beginning of line 1998-05-15 John ffitch * sread.c (sread): Correct 'b' case of character in score which is unwanted. * wincwin.c (DrawGraph): Remove call to cwin_paint which was causing each graph to nbe drawn twice 1998-05-14 John ffitch * Cwin.cpp (cwin_args): Set o.outbufsamps from oMaxLag from profile. (OnExtras): Set value to half m_buffer. * pvdlg.cpp (Cpvdlg): Editing errors had left LPC in the initialisations * ugens5.c (tone): (atone): (areson): Coding improvements * soundio.c: Remove incorrect sol support (actually elsewhere) * rtaudio.c: Added solaris support from Sweden * winX11.c: Added casrs to (Window) in various unnecssary places * solarisAudio.h: * solarisAudio.c: New files * cs.h (VARGMAX): Increase to 801 as I cannot see how to make dynmaic yet. 1998-05-11 John ffitch * sread.c (getop): Include 'c' as valid score opcode 1998-05-09 John ffitch * FLUTE.H: lastamp field defined * sread.c (sread): Introduce 'c' as score option to reset a clock base, declare variable, and add top2 fields 1998-05-08 John ffitch * PHYSMOD.C (flute): Reset maxPressure aas a result of k-rate amp 1998-05-02 * rdorch.c: Changes to record names of files and macros and line numbers; new function lexerr to decode all this. 1998-04-28 John ffitch * main.c (main): Allow SET SFOUTYP=IRCAM, and -J option to set it. * soundio.h (TYP_IRCAM): Define new constant 1998-04-27 J P Fitch * otran.c (otran): Need to NULL realloced proportion of instrtxtp array. 1998-04-22 J P Fitch * version.h: Version 3.481 * dcblockr.h: * dcblockr.c: New file * entry.c: Added dcblock opcode 1998-04-21 John ffitch * cross2.c (Xsynthset): The treatment of the base of the buffer would lead to problems with second use or memory recovery. Do not change base. 1998-04-16 J P Fitch * rtaudio.c (rtclose): Use *pcurp2 * musmon.c: Make new variable pcurp2 for WIN32 case. * ugensa.c (newpulse): Extra line setting ovp->formphs added at suggestion of rasmus.ekman 1998-04-15 John ffitch * VERSION 3.48 Tue Apr 14 12:41:54 1998 * oload.c: Remove second declaration of gbloffbas as reduntant. 1998-04-12 John ffitch * util1/sortex/xmain.c (synterr): Added definition * util1/sortex/smain.c (synterr): Added definition of synterr * shaker.h: New field, freq, for below. * shaker.c (shaker): Take acount of frequency argument by calling the filter. * soundio.c (audwrite_norm): Heartbeat formats 1 (as before), 2 (string if .s) and 3 (time in output). (audwrite): The same * main.c (main): Accept a digit after -H for various styles of reporting 1998-04-12 John Fitch * space.h: * locsig.h: * locsig.c: * space.c: New files * entry.c: Added new opcodes for location/space * fgens.c: Added gen28 to tables (fgens): Defer allocation for gen28 as well (hfgens): Same 1998-04-10 * linevent.c (RTLineset): Allow pipes as input to -L * entry.c: Added printk2 opcode * ugrw1.c (printk2set): (printk2): New functions for new opcode * ugrw1.h (struct): PRINTK2 added * linevent.c (RTLineset): Set no buffering if no fcntl function case * rtaudio.c (rtplay): Coding changes to stop re-evaluations [Windows version] Many changes to record for Windows and closing 1998-04-08 * ugensa.c (newpulse): Change to *fund!=0 case [Ekman] * ugens7.c (fof): Treat fractions of grain properly in fof2 case [Ekman] * entry.c: asin, acos and atan renamed sininv, cosinv and taninv Also rename atan2 as taninv2 1998-04-05 John ffitch * entry.c: Aded atan2 operations * aops.c: Added atan2 operations 1998-04-05 * sread.c (getscochar): Add /* */ comments in scores * rdorch.c (copy_arglist): New function to copy argument definition from fixed buffer to new space (getoptxt): Use fixed nxtarglist and copy (getoptxt): Optional arguments are special case * diskin.c (newsndinset): Round error fix from Matt. 1998-04-04 * rdorch.c (rdorchfile): Moved allocation of ARGSPACE to place where orchestra size is known. (rdorchfile): Extend ortext area as needed. 1998-04-03 * rdorch.c (getoptxt): Try to extend ARGSPACE array with realloc * cwin.cpp (OnMouseMove): Remember mouse position on movement * wincwin.c (MakeXYin): Implement (ReadXYin): Implement 1998-04-02 * sread.c: Many changes to add macros and repeats 1998-03-27 * pvadd.c: New file * pvadd.h: New file * entry.c: Add pvadd opcode 1998-03-26 J P Fitch * filopen.c (WR_OPTS): Correct order so Microsoft format is seen before WIN32 (which is really Watcom I guess) 1998-03-24 * rdorch.c (splitline): Added support for C-style comments 1998-03-23 * rdorch.c: Major changes to add macro facility, #include also 1998-03-16 * midirecv.c (m_chanmsg): Change insalloc to instrtxtp->instance * oload.c: Remove declaration of insalloc * insert.c (insdealloc): Removed reference to insalloc array as never initialised. Use instance field of instrtxtp instead 1998-03-15 * physmod.c (bowed): DlineL_setDelat was not set if no vibrato 1998-03-14 * physutil.c (DLineL_setDelay): Add check for delay too big * physmod.c (fluteset): Remove calls to OnePole and DCBlock clear * physutil.c (DCBlock_clear): remove (OnePole_clear): Remove * physutil.h: Remove lastOutput from OnePole and DCBlock * AIFF.C (aiffReadHeader): SEEK_CUR -> SEEK_SET (aiffReadHeader): twice 1998-03-13 * FILOPEN.C: Add WR_OPTS case for MSVC 1998-03-06 * Cwin.cpp (OnExtras): Set O.FMidiin when a midi file is specified (OnMidifile): Add *.mf midi files to types recognised 1998-03-04 J P Fitch * physmod.c (clarinset): (fluteset): (bowedset): (brassset): Cannot be sure frequency given, so reorganise initialisation of frequency, including moving code to the performance function 1998-03-01 * cwin.cpp (cwin_exit): Use cwin_full_program_name for repeat use rather than plain winsound; hence does not have to be in search path * otran.c (otran): and use argument * rdorch.c (getoptxt): Give function an argument for reinit 1998-02-27 * lptrkfns.c (TWOPI): Replace variables by #defines * cross2.c (getmag): max was not intitalised so could have random results. * vdelay.c (multitap_set): max was not intitalised so could have random results. 1998-02-25 * physmod.c (bowed): When checking to see if betaRatio has changed one needs to incorporate frequency. Made lastbeta field into product of beta and freq (bowedset) Consequence of above 1998-02-22 * soundio.c (sfopenin): Added | syntax in -i files (sfopenout): and -o files (sfclosein): Deal with pipes in closing (sfcloseout): and the other kind 1998-02-21 John Fitch * soundin.c (sreadin): Denormalise floating WAV files * rtaudio.c (getWaveOutDevices): New Function (getWaveOutName): New Function (playopen): Allow menu selection if device * midisend.c (openMIDIout): Replace NULL be 0 twice for ignored arguments (openMIDIout): Firest argument to sscanf missing! * dpwelib.h: Add _MSC_VER as well as SYS5 for strchr etc * soundio.c (audwrite_norm): New function for normalised floats (sfopenout): And arrange to call it * hetro.c (hetro): * sndinfo.c (sndinfo): exit onlt for non-CWIN * lpanal.c (lpanal): Use return in CWIN rather than exit (lpanal): Again * pvanal.c (pvanal): Use exit if in CWIN variant * ugens3.c: Moved declaration of isintab to top * wave.c: Many changes for completing floating samples * memalloc.c (memreset): Correct typing error 1998-02-17 J P Fitch * entry.c: Added nreverb opcode, and make reverb2 the same * nreverb.h: New file * vdelay.c (nreverb): New function (nreverb_set): New function (reverb2_play): (reverb2_set): Removed (well #defined out) 1998-02-05 John Fitch * rdorch.c (getoptxt): Add 'h' case 1998-02-01 John Fitch * VERSION.H: 3.473 * shaker.c (shaker): Change type of shake to float * shaker.h: Removed shake_times as not used. Also change some longs to int. 1998-01-19 John Fitch * VERSION.H: 3.47 * hetro.c: Make hmax a short so gets written correctly. 1998-01-07 John Fitch * fm4op.c (hammondB3): Only reset frequencies if there is a modulation, and do it inside main loop 1998-01-06 John Fitch * aops.c: Added tan, asin, acos, sinh, cosh, tanh, log10 support * entry.c: Added functions tan, asin, acos, sinh, cosh, tanh, log10 1998-01-02 John Fitch * entry.c: Added entries for tablekt and tableikt having found them in ugens2.c 1997-12-31 John Fitch * mandolin.c (mandolin): Arrange frequency is at k rate (mandolinset): If no lowest frequency need to multiply by 0.9 -- minimum suggested detune. * mandolin.c: NEW FILE * physutil.c (ADSR_setReleaseRate): (ADSR_setDecayRate): (ADSR_setAttackRate): Correction by NORM_RATE was missing. * fm4op.c (FM4Alg4_tick): Corrected mistaken use of wave[0] 4 times. * shaker.h: * singwave.h: * moog1.h: * fm4op.h: * shaker.c: * singwave.c: * moog1.c: * fm40op.c: NEW FILE 1997-12-28 John Fitch * fgens.c (fgens): Apparent 'hole' at 300 tables. Fix this? * filter.c (FPMAX): Change name from FMAX as that is used elsewhere 1997-12-26 John Fitch * ugensa.h: Make riphs field unsigned as Watcom gave false negative anser! * ugens2.c (kosc1): Will not compile with Symantec PowerC so remove optimisations (koscil): Ditto 1997-12-24 John Fitch * sread.c (getpfld): Allow E and e in numbers 1997-12-23 J P Fitch * entry.c: Added atan in three forms * aops.c: Added atan function. 1997-12-20 John Fitch * wincwin.c (MakeGraph): Remove caption and call to cwin_show (DrawGraph): Added call to cwin_show * cwin.cpp (class CGrapicsWindow): Add methods for Next and Prev Added vectors to remember old graphs (Clear): Copy old picture to the vectors if not already saved. (Next): Next function to cycle through graphs (Prev): And previous graph Altered menus etc to fit, and calls from main window 1997-12-19 John Fitch * rtaudio.c (playopen): Select win_dev in WIN32 if in range, else zero. Declare win_dev. * soundio.c (sfopenin): Accept devaudio# and adc# as valid RT audio in WIN32 situation. 1997-12-17 John Fitch * vibraphn.h: * marimba.h: * modal4.h: * modal4.c: New File, for marimba, vibraphone and agogobel 1997-12-15 John Fitch * fgens.c (gen01raw): Added check that length actually exceeded 1997-12-10 John Fitch * util2/exports/het_import.c (main): And again * util2/exports/het_export.c (main): Deal with header Sat Dec 06 16:44:29 1997 John Fitch * ugens3.c (adsyn): Get pointer to partials (adset): Read header and allocate space via aux * ugens3.h (ADSYN): Make ptlptrs into an aux structure * hetro.c (filedump): Write a header of number of partials 1997-11-24 John Fitch * sread.c (sget1): Deal with \ escapes 1997-11-23 John Fitch * soundin.c (sndgetset): Prepare for AIFC (newsndinset): Ditto (sndo1set): Ditto * soundio.c (sfcloseout): Add TYP_AIFC in preparation (sfopenin): Ditto (sfopenout): Ditto (sfopenout): Ditto * aiff.h: Added CommChunk3 definition * soundio.h (TYP_AIFC): Define new constant * cs.h: Added maxamps field to AIFFDAT structure 1997-11-20 J P Fitch * wave.c (wavReadHeader): Allow floats in input of WAV (wavWriteHdr): Allow floats in writing headers. * main.c (main): Allow WAV format floats 1997-11-18 John Fitch * fgens.c: Increased number of gens to 27; added gen25 and gen27. 1997-11-15 John Fitch * entry.c: Added opcode wgclar, wgflute, wgbow, wgbrass, marimba, vibes, agogobel, shaker, fmbell, fmrhode, fmwurlie, fmmetal, fmb3, fmvoice, fmpercfl * clarinet.h: * flute.h: * bowed.h: * brass.h: * physmod.c: * physutil.h: * physutil.c: New File * rdorch.c: Make lblreq into a dynamic object (rdorchfile): Alloc space to lblreq and initialise lblmax (lblrequest): Rewrite to use arrary access (lblfound): Rewrite to allow gro (lblchk): And again 1997-11-09 John Fitch * sread.c (ifa): Allow ^n in second field of score (getpfld): Admit ^ in scores 1997-11-01 John Fitch * makefile: * Makefile: * cross2.c: * all_files: Rename cross.c as cross2.c for consistency 1997-10-30 John Fitch * midisend.c: Further revision on LINUX version In SGI case ensure only one call to write (for 2 or 3 bytes) for each MIDI output call. * main.c: Added LINUX-specific forward declarations (main): -Q option in LINUX 1997-10-28 John Fitch * midisend.c: Various LINUX changes * ugens1.c (xsgrset): Setting of relestim was missing 1997-10-27 John Fitch * midiops2.c (TRUE): Protect definition in case already exists 1997-10-26 John Fitch * midisend.c: Added LINUX code * ugens1.c (lsgset): Allocation of segment space only checked for NULL and not being long enough (the common bug!) -- by inspection (lsgset): Wrote off end of SEG list. * SGIplay.c (play_on): Argument format to ANSI (play_set): Ditto ... and other functions * midiops2.c (initc7): Added void type (initc14): Ditto (initc21): Ditto * vpvoc.c (vpvset): Declaration of ldmemfil corrected * pvread.c (pvreadset): Declaration of ldmemfil corrected * pvinterp.c (pvbufreadset): Many %d -> %ld * scxtract.c (scxtract): Make functiomn type explicit * pvanal.c (takeFFTs): Correct format %d -> %ld * ugens7.c: Forward declaration of newpulse made ANSI * ugens4.c: Forward declarations of rand15 and rand16 made ANSI * ugens2.c (ptblchk): Added void type * ugens1.c (lsgset): Remopve variable d as not used * midirecv.c (m_chanmsg): Unwrapped ambiguous code * insert.c (MIDIinsert): Removed m_chnbp as not used * express.c (express): Added cast to char* * otran.c (constndx): Added cast to float* in case of C++ compiler * ugrw1.c (itablew): Declaration on ktablew (tableng): %f in format should be %p, or argument dereferenced (itableng): Ditto (tablegpw): Ditto (printksset): Remove false \c and \p cases (zawm): Unwrapped undefined code * fgens.c: Argument type in declaration of gen01raw * entry.c: Use sndwarpgetset * sndwarp.c (sndwarpset): Remove sndwarpset as not used * repluck.c (wgpsetin): Correct no-pluck case, and some code reorganisation to save space flapping 1997-10-15 John Fitch * aops.c (cps2pch): Corrected a rounding error in table case. (cpsxpch): Ditto 1997-10-12 John Fitch * ugens4.h: * ugens4.c: * ugens3.h: * ugens3.c: * entry.c: Remove doscil and poscil 1997-10-10 J P Fitch * aops.h (struct XENH): Correct argument order to fit documentation * cross.c (Xsynthset): Need to check that previous buffer is big enough (same bug as was in grain) (Xsynth): Re-construct due to JPff errors (Xsynth): Wrapping of n was at odd place?? 1997-09-30 John Fitch * ugens2.c (itblchk): Replace NULL by 0 for types Wed Sep 24 15:10:38 1997 J P ffitch * midirecv.c: Prototype for midNotesOff * musmon.c: Need a prototype for xturnon * zroots.c, laguer.c, nrutil.c: Removed, Code moved into filter.c Tue Sep 16 07:54:37 1997 John ffitch * wavegde.c pluck.c filter.c zroots.c complex.c laguer.c nrutil.c: New files for plucked string and filter opcodes * cmath.c (seedrand): If seed of the random number is given as zero, seed from clock. * entry.c: Added new opcodes wgpluck, filter2, kfilter2, and zfilter2 * repluck.c: * repluck.h (struct): Rename WGPLUCK to WGPLUCK2 * entry.c: Renamed wgpluk to wgpluck2, and renamed structure * midirecv.c (m_chinsno): Remove test for maxinsno as there is no such thing really! * ugens2.c (ftkrchk): Moved return to end so all routes return a value. * rdorch.c (rdorchfile): Revise as MACRO now claimed by ADI Thu Sep 11 16:31:41 1997 John ffitch * cwin.cpp (OnGShow): Remove code related to backtrace as irrelevent (OnStop): Added stop and continue menu items as also as ^S-^Q These changes allow scrolling etc Wed Sep 10 11:49:53 1997 John ffitch * ugrw1.c (ftkrchkw): This function did not return any value in one case. Make it return 1 * otran.c (otran): Make sure ksmps is integer * ugrw1.c (timesr): (timesr): (instimes): (printkset): (printk): (printk): (printksset): (printks): Changed 1/ekr to onedkr to save division (zkset): Change value 0 for a float* to NULL as that is what is meant (zakinit): Do this twice more, (and for declarations) (zaset): Also for zastart Mon Sep 08 20:12:58 1997 John ffitch * ugens3.c: Prototype for turnoff * hrtferX.c: Removed function round as not used Fri Sep 05 11:44:30 1997 John ffitch * ugrw1.c (peakk): Changed abs to fabs which is clearly what is needed. Use of abs changes to int and then back. (Whittle code) (peaka): Ditto Thu Sep 04 11:54:26 1997 John ffitch * ugrw1.c (printksset): Tidyup string decode to make it compatable with C wrt \ character. Still needs work. * otran.c (otran): Allocate instrtxtp dynamically and allow to grow with mrealloc. Removes restricton on largest instrument number. * musmon.c (playevents): * midirecv.c (m_chinsno): (m_chn_init): * oload.c (oload): New variable maxinsno replaces constant Wed Sep 03 10:55:46 1997 John ffitch * fgens.c (hfgens): If automatic numbering, it did not always allocate space in table * rdorch.c (getoptxt): Count 'm' in defaults section to remove error in ftgen * insert.c (MIDIinsert): Remove aging and overlap stuff * cs.h: Removed olap and age fields in INSDS * midiops.c: Removed midiolap and midiage * entry,c: Removed octdown and noctdft opcodes, also midiolap and midiage * spectra.c: Removed code for octdown as it is ADI proprietry Fri Aug 29 15:25:59 1997 John ffitch * util2/mixer/mixer.c (main): * cwin.cpp (class CArg): * wave.c (wavReadHeader): * soundio.c (iotranset): * soundin.c (sndo1set etc): * main.c (main): * LINUXaudio.c (setsndparms): * soundio.h (AE_UNCH): Renamed from AE_BYTE to AE_UNCH Thu Aug 28 12:27:48 1997 John ffitch * rtaudio.c (playopen): New variable ntmp as multiple use of ndev was causing problems. * dpwelib.h: * dsputil.c: Removed nested comments * repluck.c: New file * entry.c: Added wgpluck and repluck opcodes Wed Aug 27 14:35:52 1997 John ffitch * ugens5.c: Reorder code so RESET might work Declare DumpPoles instead of DumpPolesF, and comment out call! Tue Aug 26 11:35:48 1997 John ffitch * cross.c: Incorporated fhtfun.c into cross.c * fhtfun.c: REMOVE file * UTIL2/scale.dir/scale.c: Declarations of functions * midiops2.c: New file * entry.c: Added midicontroller message stuff * midiops2.h: New file * grain4.c (graingenv4): Code tidy on *xx++ type code (envv4): Change way of commenting out to #ifdef never 1997-08-20 John Fitch * midisend.c (send_midi_message): (note_on): (note_off): (control_change): (after_touch): (program_change): (pitch_bend): (poly_after_touch): Wrote WIN32 code for these as calls to midiOutShortMsg (openMIDIout): Open device 0 only for now * midioops.h (MD_CHANPRESS, etc): MIDI opcodes * midiout.c: Added calls to openMIDIout in each initialisation function. May seem expensive but is minimal disturbance. 1997-08-18 John Fitch * SENT TO DAVE * midisend.c: Totally new file 1997-08-17 John Fitch * pvanal.c (pvanal): * lpanal.c (lpanal): * cvanal.c (cvanal): * hetro.c (filedump): Ensure analysis file is read-write. Some systems seem to get this wrong * rtaudio.c (playopen): If more than 1 possible output in WIN32 then allow user to choise which. Also added some more checking (rtplay): Remove called to waveOutUnprepareHeader and waveOutPrepareHeader as they seem unnecessary (according to GAB) (rtclose): Change strategy for wrap-up * midiout.h: New file (Gabriel M) * midiout.c: New file (Gabriel M) * entry.c: Added MIDI output opcodes 1997-08-11 John Fitch * rdorch.c: Added type 'h' to argument type -- needed in MIDI 1997-08-06 John Fitch * ugens1.h: Define struct EXXPSEG * ugens1.c (xsgrset): Rewrite function 1997-08-05 John Fitch * otran.c: Remove txtcpy in favour of memcpy, and define macro 1997-08-01 John Fitch * dam.h: New file * dam.c: New file * makefile (dam.u): Added dam target * entry.c: Added dam opcode 1997-07-13 John Fitch * cross.c: New File * fhtfun.c: New File (support for cross) * ugens2.c (oscnset): New function (osciln): New function (for osciln opcode) * ugens2.h: New structure OSCILN * entry.c: Declarations for cross2 opcode Also osciln opcode * soundio.h (IOBUFSAMPS): Larger default buffers for Windows95 1997-07-07 John Fitch * ugens1.h: New fields in EXPSEG * entry.c: Added expsegr * ugens1.c (xsgrset): (kxpsegr): (expsegr): New functions * ugens3.h: New structure DOSC * oload.c (instance): Set chanel if MIDI * insert.c (insert): Add check for MIDI instruments from score 1997-07-05 John Fitch * ugens3.c (dosset, doscil): New functions * entry.c: Added doscil opcode * soundin.c (sndwrt1): (sndwrtu): (sndwrt2rev): (sndwrt2): (sndwrt4rev): (sndwrt4): (sndwrtf): New functions * soundio.h: New structs SNDCOM, SNDOUT and SNDOUTS * soundin.c (sndo1set): New function (soundout): New function (sndo2set): (soundouts): New but null functions * soundio.h (SNDOUTSMPS): New constant * midiops.c (ipchbend): New function (kbndset): New function (kpchbend): New function * entry.c: Added ipchbend and kpchbend, modify pchbend Added soundout. Also soundouts but I think it is a failure Sun Jun 22 11:54:43 1997 John Fitch * midirecv.c: Many changes and new functions for revised MIDI code * cs.h: New struct DPARM, DKLST and DPEXCL * ugens1.c (klnseg): Rewrite (lsgset): Rewrite (linseg): Rewrite * ugens1.h: Defien SEG type/struct * oload.c (oload): Define dvensmps * ugens1.h: Add new fields to LINSEG for releases * rdorch.c (rdorchfile): Added MACRo support Tue Jun 17 15:48:29 1997 John Fitch * entry.c: Added linsegr opcode Mon Jun 16 21:50:39 1997 John Fitch * rdorch.c (rdorchfile): Treat \ ... \n as ignorable Fri Jun 13 21:34:01 1997 John Fitch * entry.c: Added turnon opcode Tue Jun 10 09:02:58 1997 John Fitch * midiops.c (ichanctl): (chctlset): (chanctl): New functions * midiops.h: Added CHANCTL structure * entry.c: Added chanctrl opcodes Mon Jun 9 21:43:27 1997 John Fitch * entry.c: Added extra optional argument to [ik]midictrl * midiops.c (mctlset): Added scaling * midiops.h: Changed MIDICTL to lo and hi from sc and base * midiops.c (imidictl): (midictl): Added scaling * midiops.h: Added MIDIMAP structure * entry.c: Added optonal arguments to veloc * midiops.c (veloc): Added scaling to veloc Removed f128 in favour of a constant Sat Jun 7 20:06:53 1997 John Fitch * entry.c: Added ftlptim opcode * ugens4.c (posset): New function (poscil): New function * ugens4.h: POSC structure * entry.c: Added rnd and birnd in i and k formats Added poscil * aops.c (rnd1): (birnd1): New functions for direct use in orchestras Fri Jun 6 09:20:31 1997 John Fitch * cs.h: Added posbend field to MCHNBLK Thu Jun 5 21:48:00 1997 John Fitch * cs.h: Added mdepends field to INSTRTXT Wed Jun 4 11:46:03 1997 John Fitch * aiff.c (aiffReadHeader): initialised markersp to NULL Tue May 27 08:17:57 1997 John Fitch * cs.h: Added #defines for VSET etc * oload.h (struct): Lots of new structures for Vprogs and the like * midiops.h: Added MASSIGN and CTLINIT structures Sun May 25 17:22:09 1997 John Fitch * ftgen.h: New file * entry.c: Entry for ftgen opcode * fgens.c (hfgens): New code (ftgen): New code; together for ftgen opcode Sat May 24 18:36:41 1997 John Fitch * cs.h: Added fno to FUNC Tue May 20 10:29:02 1997 John Fitch * ugens7.c (harmset): New function (BV) (harmon): Ditto * entry.c: Entry for harmon * ugens7.h (struct): Added HARMON struct Mon May 19 21:51:31 1997 John Fitch * ugensa.c (newpulse): Changes abs to fabs as that is clearly what is needed. Mon May 19 12:20:51 1997 John Fitch * winX11.c: Added include of Mon May 19 08:50:44 1997 John Fitch * rdscor.c (scanflt): treat comments when reading a number Sat May 17 17:31:47 1997 John Fitch * cscormai.c (scfopen): Move this function from rdscor.c as only used in stand-alone cscore * rdscor.c: Delete scfopen function Fri May 16 10:01:41 1997 John Fitch * memalloc.c (memdie): Made function void type * ugens5.c: Added int type to currentLPCSlot, and moved to top of file * midirecv.c: Added int type to sexcnt * winX11.c: Added int type for winstance Sat May 10 23:44:12 1997 John Fitch * ugrw1.c: Change name of times function to timesr to avoid problems with Mac * entry.c: Change name of times function to timesr to avoid problems with Mac Wed May 7 21:04:55 1997 John Fitch * butter.c (butter_filter): Changed declaration on n to long for consistency. Sun May 4 08:58:44 1997 John Fitch * version.h: NEW VERSION 3.46 * fgens.c (fgens): Expand the number of tables available dynamically. Declare fmax etc (gen04): (ftfind): (ftfindp): (ftnp2find): FMAX->fmax * rtaudio.c (RTwavclose): New function to close on early exit (playopen): Minor revisions to Win95, including CWIN->_WIN32 (rtplay): Change _WIN32 way of playing buffers (rtclose): Change _WIN32 close down * prototyp.h: Add argument to getoptxt if RESET * soundin.c (soundinreset): New function protected by RESET (sndinset): Reset file position if already open (soundin): Check initialisation (soundinew): Check initialisation * sndwarp.c (sndwarp): (sndwarpst): Check initialisation * rdorch.c (orchreset): New function protected by RESET (getoptxt): Added argument if RESET and use it for reseting * memalloc.c (memreset): New function protected by RESET * fgens.c (ftreset): New function protected by RESET; code tidying * cscorfns.c (cscorereset): New function protected by RESET Also some code shuffling Sat May 3 19:38:45 1997 John Fitch * spectra.c (koctdown): (octdown): (noctdft): (spdspset): (specdisp): (specptrk): (specsum): (specaddm): (spdifset): (specdiff): (spsclset): (specscal): (sphstset): (spechist): (spfilset): (specfilt): Check initialisations * musmon.c (musreset): New function protected by RESET * disprep.c (kdsplay): (kdspfft): (dspfft): (tempest): Check initialisation * otran.c (tranreset): New function protected by RESET * oload.c (oloadreset): New function protected by RESET * ugens3.c (foscil): (foscili): (adsyn): Check initialisations * ugens4.c (buzz): (gbuzz): (pluck): Check initialisation * ugens5.c (lpcreset): New function protected by RESET (lpinterpol): (lpread): Check initialisation * wave.c (wavReadHeader): Set hdrsize to include non-data chunks * grain4.c (graingenv4): Check initialisation * ugens9.c (convolve): Check initialisation * insert.c (insertreset): New function, protected by RESET (insert): Only print new alloc message if messages 2 set (initerror): Check there is an ids (perferror): and a pds * grain.c (ags): Check initialisation (ags): Check for zero density * express.c (expreset): New function, protected by RESET macro * hrtferX.c (hrtferxk): Check initialisation * ugens2.c (ktable): (table): (ktabli): (tabli): (kosc1): (kosc1i): (koscil): (osckk): (oscka): (oscak): (oscaa): (koscli): (osckki): (osckai): (oscaki): (oscaai): Check initialisation * ugens7.c (fof): Check initialisation * ugens6.c (delay): (delayr): (delayw): (deltap): (deltapi): (comb): (alpass): (reverb): (pan): Check initialisation * ugens8.c (pvoc): Check initialisation * sread.c (pcopy): Another place where fabs is needs in case of negative p3 in score. * nlfilt.c (nlfilt): Check initialisation * ugens1.c: Remove register declarations (klnseg): (linseg): (kxpseg): (expseg): (knvlpx): (envlpx): Check for initialisations * vdelay.c (vdelay): (multitap_play): (reverb2_play): Check for initialisation * pvinterp.c (pvbufread): (pvinterp): (pvcross): Check they are initialised * vpvoc.c (ktableseg):(ktablexseg): (voscili): (vpvoc): Check they are initialised * winX11.c (myXprintLines): ANSIfied function * pvoc.c: * dsputil.c: Removed FLOATARG as it is a mistaken idea * pvoc.h: * dsputil.h: Removed non ANSI stuff, and the horrid FLOATARG * aoscilx.c (aoscilxplay): Check opcode is initialised * follow.c (flwset): Check that length given is not zero (RWD suggestion but moved to init function) Sun Apr 27 13:06:00 1997 John Fitch * cscormai.c (main): Added dribble initialisation (dribble_printf): New function (err_printf): New function * Makefile, makefile: Added new files * all_files: Added new files * ugensa.h: New file * ugensa.c: New file for FOG * entry.c: Add opcode fog Sun Mar 23 18:08:01 1997 John Fitch * otran.c (otran): Revise check for consistent sr/kr=ksmps (otran): Check for finishing inside an instrument Fri Mar 21 21:21:22 1997 John Fitch * entry.c: Added diskin opcode * soundin.c: New code for diskin opcode (Matt Ingalls) * diskin.h: New file * cs.h (DFLT_SR): Change to 44100 (DFLT_KR): Change to 4410 (DFLT_KSMPS): Remains 10 (!) * ugens2.c: Changes to table stuff (Whittle) Thu Mar 20 22:17:00 1997 John Fitch * entry.c: Put Whittle opcodes back * fgens.c (ftfindp): New function (Whittle) Wed Mar 19 13:25:43 1997 John Fitch * otran.c (otran): Set initial tran_{sr,kr,ksmps} to -1 and correct in otran. Sun Mar 16 12:26:50 1997 John Fitch * ugens8.c (pvoc): Simplify initialisation when specwp greater than zero. (Richard Karpen) Sat Mar 8 15:30:34 1997 John Fitch * hrtferX.c: Declaration of bytrevhost * main.c: Added #include for isdigit Fri Mar 7 13:16:37 1997 John Fitch * main.c (err_printf): Same error as before -- code in wrong order. No idea how it got undone. * rtaudio.c (playopen): Comment out line about BitsPerSample on advice Fri Mar 7 09:54:31 1997 John Fitch * opcode.c (list_opcodes): Use mmalloc/mfree rather than malloc/free (list_opcodes): Reorganize argument to mmalloc as well Thu Mar 6 21:43:31 1997 John Fitch * entry.c: Added entry for soundin2 * soundin.c (soundin2): New function, implements soundin2 (sndinset): Initialisation for soundin2 added * soundio.h: Added new fields to SOUNDIN structure for soundin2 Wed Mar 5 10:59:32 1997 John Fitch * hrtferX.c (hrtferxkSet): Reverse bytes after reading HRTFcompact if necessary (as shown by byrevhost) * Makefile (CSRCS): CSRC7 was missing from CSRCS! * makefile (CSRCS): CSRC7 was missing from CSRCS! Tue Mar 4 14:24:47 1997 John Fitch * opcode.c (list_opcodes): The malloc did not get enough memory -- needed multiplication by the sizeof thingy Tue Feb 25 10:33:22 1997 John Fitch * aops.c: Removed register declarations * wave.c: Removed various register declarations * swrite.c (fltout): Reinstated multiplication by precmult for LINUX only. This is still wrong way to do it! Tue Feb 18 08:57:08 1997 John Fitch * sread.c: Remove register declarations throughout (stof): Replace body by call to strtod for simplicity and shorter code. (Experimental I guess) Sun Feb 16 15:49:57 1997 John Fitch * sread.c (ifa): Take absoulte value of previous p3 when reading a score, in order to deal with portamento etc Fri Feb 14 21:49:51 1997 John Fitch * midirecv.c (m_chanmsg): Further midi chages to controllers from Mike Berry Thu Feb 13 21:01:42 1997 John Fitch * midiops.h: sc and base fields in MIDICTRL and irange field in MIDIVAL * midiops.c (midibset): New function from Mike Berry (cpsmidib): Allow scaled pitchbend (octmidib): Ditto (pchmidib): Ditto (mctlset): Deal with controller 0 * rdorch.c (getoptxt): Add code from Mile Berry to fix bug that prevented an opcode with only optional arguments from properly loading defaults * entry.c: Declared midisetb Added optional argument to ipchmidib, ioctmidib, icpsmidib, kpchmidib, koctmidib, kcpsmidib, imidictrl, kmidictrl. Needed initialisation for some Fri Feb 7 08:15:28 1997 John Fitch * ugens7.c (fof): In penultimate line removed * in *ar++ as it does not do anything, and I think it is spurious. Also remove register declarayions all over Wed Feb 5 17:53:54 1997 John Fitch * ugens7.c (newpulse): Corrected code (JPff mistake) Mon Feb 3 09:48:32 1997 John Fitch * version.h (SUBVER): CHANGE VERSION NUMBER TO 3.45 * swrite.c (fltout): Remove precmult as it does nothing and increase precision by one digit * sndwarp.c (sndwarpstgetset): New code from Richard Karpen (sndwarpstset): Ditto (sndwarpst): Ditto * fgens.c (ftfindp): Remove Whittle code Sun Feb 2 12:22:01 1997 John Fitch * util2/mixer/mixer.c (main): Moved line assigning to O.filetyp to before AIFF/WAV sanity checks (MixSound): Second argument to audtran was size when shoudl have been length Sat Feb 1 16:43:33 1997 John Fitch * swrite.c (fltout): Work in doubles internally (RK), but then replaced by fprintf anyway?? * ugens2.c: Remove Whittle code * ugens2.h: Remove Whittle code * main.c (main): Add -z0 and -z1 * Remove ugrw* from makefiles * entry.c: Remove Whittle opcodes Tue Jan 28 07:54:58 1997 John Fitch * entry.c: Add fof2 opcode * ugens7.c (fofset0): Rename fofset and add argument to distinguish fof and fof2 initialisation ; also set fmtmod field in fof call only (fofset): Call fofset0 with true (fofset2): Call fofset0 with false (fof): fof and fof2 cases differ at start of loop (newpulse): Deal with fof2 case at end * ugens7.h: Add glissbas and sampct fields to OVRLAP and foftype field to FOFS * opcode.c: New file * prototyp.h: Added declaration of list_opcodes * main.c (main): Add -z option to list opcodes Sun Jan 26 14:02:06 1997 John Fitch * cmath.c (auniform): Add new function for completeness (ikuniform): Ditto * ugens2.c: Changes to table stuff (Whittle) * ugens2.h: Added pfn field to TABLE for Whittle * ugrw1.c: New file (Whittle) * ugrw2.c: New file (Whittle) * prototyp.h: Added declaration of ftfindp * fgens.c (ftfindp): New function (Whittle) * ugens2.c: Remove register declarations Fri Jan 24 18:52:01 1997 John Fitch * cmath.c: Removed register declarations throughout; also some improved layout of comments Mon Jan 20 08:48:56 1997 John Fitch * lpanal.c (lpanal): Return after exit for compiler (lpanal): Only declare polyReal and polyImag if used * linevent.c (sensLine): Comment out unused variables * ieee80.c: Remove nested comment * hetro.c (hetro): Add a return after exit to keep compilers quiet * fft.c: Remove nested comments in 3 places, and a print statement * aiff.c (aiffReadHeader): Comment out unused vaiables * main.c (main): By use of %n arrange that a numeric argument can be follwed directly by another argument. Wed Jan 15 20:39:12 1997 John Fitch * window.c (DummyRFn): Made it return zero rather than 1 as there does not seem to be an error here. Thanks Marc! Sat Jan 11 16:53:59 1997 John Fitch * vdelay.h: Added istod field to VDEL struct * entry.c: Add optional istod argument to vdelay * vdelay.c (vdelset): Skip initialisation if istod set * ugens6.c: Removed register declarations * vdelay.h (struct): Added istor field to STVB * vdelay.c (reverb2_set): Skip initialisation if istor set and have buffers. * entry.c: Added optional istor argument to reverb2 * butter.c (bbutset): (butset): Skip initialisation if istor non-zero * butter.h (struct): Added istor filed to BFIL and BBFIL * entry.c: Added optional extra argument to all butterworth filters Tue Jan 7 10:32:09 1997 John Fitch * version.h (SUBVER): CHANGE VERSION NUMBER TO 3.44 in Windows * winsound.rc: Added postscript and Oldformat fields to DIALOG_1 and DIALOG_LPC respectively. Some reshuffling to make it fit * cwin.cpp (class CArg): Added m_postscript member (class CArg): and afx command (CArg): Set m_postscript from profile (OnInitDialog): Set initial value of Postscript (cwin_args): Set O.postscript after dialog * lpcdlg.cpp (class Clpcdlg): Added oldf to constructor, and m_oldf to the members. (class Clpcdlg): New afx OnOldFormat (Clpcdlg): Use oldf in constructor (lpanal_dialog): Oldf stuff Mon Jan 6 10:25:31 1997 John Fitch * version.h (SUBVER): CHANGE VERSION NUMBER TO 3.44 * aops.c (cpsxpch): Added table form of cpsxpch and cps2pch * lpanal.c (lpanal): Various fixes after new code. Sun Jan 5 23:17:19 1997 John Fitch * ugens5.c (lpslotset): New function (lpitpset): New function (lpinterpol): New function : other changes throughout * ugens5.h: New field in LPREAD * (struct): New structures * lpc.h (LP_MAGIC2): New definition * lpanal.c: Incorporated Marc Reseibois' alternative format. Many changes all over Sat Jan 4 19:25:23 1997 John Fitch * oload.c: Added postscript filed to initialisation of O structure * main.c (main): Remove O initialisation as in wrong place Fri Jan 3 14:39:30 1997 John Fitch * Files sent to Mills College Thu Jan 2 17:29:17 1997 John Fitch * main.c: Make scorename a global for winEPS Add initialisation of O fields * winEPS.c: New file for Encapsulated PostScript output * cs.h: Added postscript field * window.c (display): (dispexit): (dispset): Call Postscript stuff * main.c (main): Added -G option fopr Postscript printing * hrtferX.c: New code for 3D sound * entry.c: Added hrtfer opcode Mon Dec 30 16:13:40 1996 John Fitch * entry.c: Added opcodes "sndwarp", "ktableseg", "ktablexseg", "voscili", "vpvoc", "pvread", "pvcross", "pvbufread", "pvinterp" * pvinterp.c: * pvread.c: * vpvoc.c: * sndwarp.c: New files added, from Richard Karpen, with some optimisations. Sun Dec 29 13:15:57 1996 John Fitch * aops.c (cps2pch): New function for ET tuning (cpsxpch): Remove attempt at optional arguments * entry.c: Added cps2pch for ET tunings * linevent.c: (sensLine): Use strtod to read floating argument rather than use longs. Untested! Fri Dec 27 14:42:53 1996 John Fitch * util2/exports/het_export.c (err_printf): Define it (dribble_printf): Define it * util2/exports/pv_export.c (err_printf): Define it (mfree): Define it Fri Dec 20 17:45:34 1996 John Fitch * rtaudio.c (rtclose): Modify close down for arbitrary buffers * ugens3.c (adset): Change length of filnam to MAXNAME * ugens5.c: Change length of lpfilnam to MAXNAME * ugens9.c (cvset): Change length of cvfilnam to MAXNAME * ugens8.c: Change length of pvfilnam to MAXNAME * cs.h (MAXNAME): Defined here * filopen.c (isfullpath): In PC case (and Atari) check for a: type names as well as / (MAXNAME): removed from this file Mon Dec 02 15:23:53 1996 * AOPS.c (cpsxpch): New function of equal temprament not 12/octave * AOPS.h (XENH): Structure for tuning Fri Nov 27 14:49:00 1996 John Fitch * rdscor.c (rdscor): Added comments after 'e' Tue Nov 26 16:40:26 1996 * cwin.cpp: Added NONSTOP feature and a button to control it Mon Nov 04 15:38:40 1996 John Fitch * FILOPEN.C (openin): If the file does not exist but SFDIR does it fails to notice a non-existent file. Remove an else! Mon Oct 28 10:13:55 1996 John Fitch * RDORCH.C (synterr): Remove register declarations; so new layout Thu Oct 24 15:36:34 1996 * VDELAY.c (vdelset): Only zero buffer if not new (multitap_set): Ditto (multitap_play): Remove division for assignment Mon Oct 21 21:08:52 1996 * version.h: (SUBVER): CHANGE VERSION NUMBER TO 3.43 * rtaudio.c (playopen): Fixed allocation of buffer in CWIN case (rtplay): Use quadruple bufering correctly Thu Oct 17 18:44:10 1996 John Fitch * VDELAY.c (multitap_set): Fixed the regular bug in allocation of buffer. Thu Oct 17 17:34:15 1996 * butter.c: New variable pidsr, set in both setters and used for pi/esr Thu Oct 17 16:26:20 1996 John Fitch * CMATH.c: Many code tidying operation -- all minor Wed Oct 09 16:27:49 1996 John Fitch * rtaudio.c (playopen): Allocate each buffer with its own GlobalAlloc/GlobalLock Tue Oct 08 16:10:24 1996 John Fitch * LPCDLG.CPP (class Clpcdlg): Added graphics selection -- most of code was there but not visible! Tue Oct 08 15:29:09 1996 John Fitch * CWIN.CPP (OnOrchestra): Change title of dialog window and hide read-only button (OnScore): Change title of dialog window and hide read-only button (OnSoundfile): Change title of dialog window Mon Sep 30 14:06:52 1996 * grain4.c (graingenv4): Took array access out of loop with direct increments and similar use of local names Fri Sep 13 10:45:09 1996 John Fitch * vdelay.c (vdelset): Bracket expression to get binding right (vdelset): Check size of buffer as well as existence (cf grain) (vdelay): Ensure max delay is at least 1 (vdelset): Clear at least one slot Thu Aug 15 05:36:11 1996 John Fitch * version.h (SUBVER): CHANGE VERSION NUMBER TO 3.42 * memalloc.c (mcalloc): If calls for 0 bytes do not give an error * memalloc.c (memdie): Add argument to print size of failure (mfree): Use 0 argument for free (mrealloc): In CWIN set negative (mrealloc): Add argument in general case (mmalloc): Add argument in general case (mcalloc): Add argument in general case Mon Jul 22 08:49:44 1996 John Fitch * fgens.c (gen21): Argument for Weibull ignore p6 so shuffle them down. (gen21): Check for at least 1 argument first, and treat the other two specials in the switch; saves code and very little cost. * cmath.c (exprand): I think algorithm was wrong in assuming lambda always 1. Allowed range and lambda (biexprand): Code had lambda as always 1; make parameter 1/lambda (pcauchrand): Code was plain wrong * fgens.c (gen21): Add range to exponential distribution as well as spread. * cmath.h: Change prototype * cmath.c (unifrand): Add argument so as to give a range. Sat Jul 20 18:55:39 1996 John Fitch * cmath.c (cauchrand): Limit answers to [-1,1]. Despite theory of 99.9% I get some outside. (pcauchrand): The same range limiting. * fgens.c (gen21): For type 7 and 8 (Cauchy) it asked for an additional argument, and ignored the usual one. As it was undocumented fixed to one argument Tue Jul 16 09:29:48 1996 John Fitch * cwin.cpp (OnInitDialog): Format buttons started at _8 rather than _U8. * version.h (SUBVER): CHANGE VERSION NUMBER TO 3.41 * rtaudio.c (rtplay): Triple buffering system (playopen): Create 3 buffers from one GlobalAlloc call (rtclose): Flush buffers before Reset. [All CWIN case] Mon Jul 15 11:31:02 1996 John Fitch * rtaudio.c (rtplay): Remove the memcpy and cycle buffers. Get WHDR_DONE correct and other simplifications. Sun Jul 14 12:35:14 1996 John Fitch * rtaudio.c: Added draft Windows Multimedia support (playopen): Ditto (rtplay): Ditto (rtclose): Ditto Tue Jul 9 21:25:27 1996 John Fitch * util2/mixer/xtrct.c: Change name of variable time to stime cos the Irix6.2 system complains. Fri Jul 5 20:51:58 1996 John Fitch * all_files: SGIplay.c was missing Sun Jun 16 20:58:01 1996 John Fitch * soundio.c (sfcloseout): Make datasize into unsigned long (especially for 68K) Wed Jun 12 08:09:35 1996 John Fitch * wave.c (wavReadHeader): Add cast to (void*) 'cos Mac compiler complained * Transferred files to MAC Mon Jun 10 08:59:57 1996 John Fitch * version.h (SUBVER): CHANGE VERSION NUMBER TO 3.40 * wincwin.c: Include and add variaous ignoring of arguments. (DrawGraph): Add cwin_paint() call * util2/exports/lpc_export.c: * util2/exports/het_import.c: Include which had been missed * ugens9.c: * ugens8.c: Move inclusion of earlier to avoid an arcane VC problem * filopen.c: Add _WIN32 to definitions of RD_OPTS and WR_OPTS (openin): After open the test should be >=0 * fgens.c (gen20): Remove register storage class from array as upsets VC and does no good anyway * pvanal.c (pvanal): * lpanal.c (lpanal): * hetro.c (hetro): * cvanal.c (cvanal): * fgens.c (gen01raw): Check on negative return from sndgetset as consequence of previous change * soundin.c (sndgetset): Change function to return -1 on failure instead of 0 as that does not rely on zero being in use for stdin (SAsndgetset): Also return -1 on failure Sun Jun 9 16:31:48 1996 John Fitch * sysdep.h: Add _WIN32 support * pvoc.c: Add _WIN32 support * main.c (main): Add _WIN32 (main): and again for SYS5 * scot.c (efindword): Change type to void * scot.h: Change type of efindword to void * dsputil.c (hypot): Define hypot as _hypot for Visual C++ * vdelay.c (reverb2_play): Change return type to void * midirecv.c (MidiOpen): Add _WIN32 to SYMANTEC Add _WIN32 to list of o/s which to not load ioctl.h (MidiOpen): Add _WIN32 to non SYS5 list (MidiOpen): Add _WIN32 to systems without ioctl * wave.c (wavReWriteHdr): Value check on result of lseek was wrong. (wavReadHeader): Add code to skip odd chunks in reading a header * dpwelib.h: Add _WIN32 to systems which include * linevent.c (RTclose): Add _WIN32 to list of systems which do not know about fcntl (RTLineset): Ditto * dumpf.c (kdmpset): Change test on openout to <0 (kdmp2set): Ditto (kdmp3set): Ditto (kdmp4set): Ditto Sat Jun 8 16:11:56 1996 John Fitch * cmath.c (gaussrand): Change floating value for n to an integer Mon Jun 3 08:35:11 1996 John Fitch * lpanal.c (lpanal): Allocate coef and cc dynamically * hetdlg.cpp (DoDataExchange): Remove limit of 50 in number of harmonics * hetro.c (hetro): Allocate MAGS and FREQS dynamically (hetro): Allow more than HMAX harmonics (filedump): Allocate mags and freqs dynamically Sun Jun 2 12:53:06 1996 John Fitch * cwin.cpp (cwin_almost_ensure_screen): (cwin_ensure_screen): (cwin_poll_window_manager): (CMainWindow): Change GetSystemTime -> GetLocalTime * memalloc.c (mfree): New function (all_free): Do not free NULL pointers * prototyp.h: Declare mfree * wguide.c (wgpset): * sread.c (sfree): * sndinfo.c (sndinfo): * rdorch.c (rdorchfile): (splitline): * pvoc.c (PVFree): * otran.c (otran): (insprep): * oload.c (oload): * memfiles.c (rlsmemfiles): * insert.c (orcompact): * hetro.c (hetro): (filedump): * fgens.c (fgens): (gn1314): (ftalloc): * cscorfns.c (filclose): * auxfd.c (auxalloc): (auxchfree): * aiff.c (aiffReadHeader): change free -> mfree Thu May 2 21:37:23 1996 John Fitch * version.h (SUBVER): CHANGE VERSION NUMBER TO 3.39 * butter.c (ROOT2): Define ROOTS as a macro rather than recalculate it for each k-rate * memalloc.c: CWIN only -- allow a flexible number of allocs by reallocing the array. Thu Apr 18 11:00:11 1996 John Fitch * grain.c (ags): Optimisations in many places to save recalculation and memory fetches. Moves some stuff out of inner loop. * grain.h (struct): Changed type of PGRA.pr to float Thu Mar 28 08:35:43 1996 John Fitch * version.h (SUBVER): CHANGE VERSION NUMBER TO 3.38 * main.c (main): Add date of compilation to banner * musmon.c (musmon): Add date of compilation to banner * musmon.c (musmon): Removed test for !O.RTevents as it seems to stop score tables being read in MIDI case. Thu Mar 21 09:29:42 1996 John Fitch * main.c (main): Add LATTICE to SYNANTEC to avoid a setlinebuf * midirecv.c: Add LATTICE to options with PC stuff * linevent.c (RTLineset): Add LATTICE to options when do not use fcntl etc Tue Mar 5 23:13:51 1996 John Fitch * sread.c (copylin): Change EOF to EOL in structure. Mends bug about bad characters. Sat Feb 24 14:56:31 1996 John Fitch * otran.c (putop): Correct typing error of \t instead of \n Sun Feb 18 11:37:15 1996 John Fitch * version.h (SUBVER): CHANGE VERSION NUMBER TO 3.37 * rdscor.c (scanflt): Use fscanf rather than read floats character at a time. Not sure that this is necessarily a good thing. * hetro.c (hetro): Added a check that -hn has n>=1 (David Whelan) Sat Feb 17 11:53:57 1996 John Fitch * musmon.c (musmon): Close dribble file at end * auxfd.c (fdchprint): * express.c (putoklist) (putokens): * midirecv.c (sensFMidi): * musmon.c: * otran.c: * rdorch.c: * rdscor.c (dumpline): * winascii.c (DrawAscii): use putc to dribble file as well * version.h: NEW FILE to carry version numbers only * cs.h: include version.h * swrite.c: * sort.c: * pvoc.c: * ieee80.c: Include cs.h to declare dribble stuff * util2/scale.dir/scale.c: * util2/mixer/xtrct.c: * util2/mixer/mixer.c: Added -- option and change all printf/stderr printing to new style * cs.h: Add extern declaration of dribble * lpanal.c (lpanal): * pvanal.c (pvanal): * hetro.c (hetro): Added -- option to log Fri Feb 16 07:37:55 1996 John Fitch * util2/sndinfo/main.c (main): ANSIfy and add dribble stuff * util2/mixer/xtrct.c: * util2/envext/envext.c: * util1/sortex/smain.c: * util1/sortex/xmain.c: * anal/pvoc/main.c: * anal/lpc/main.c: * anal/adsyn/main.c: Added functions dribble_printf and err_printf Thu Feb 15 10:13:40 1996 John Fitch * DECaudio.c * DECplay.c * blaster.c * cvanal.c * hetro.c * ieee80.c * linevent.c * lpanal.c * main.c * memalloc.c * midirecv.c * musmon.c * otran.c * pvanal.c * pvoc.c * rdorch.c * rtaudio.c * sfheader.c * sort.c * spectra.c * sread.c * swrite.c * twarp.c * wave.c * winSGI.c * winbor.c * winfg.c * winwat.c: fprintf(stderr,...) -> err_printf(...) * main.c (dribble_printf): New function to write to stdout and dribble. (err_printf): dito for stderr. * cs.h: Macro printf to dribble_printf and declare it. * main.c (endif): Make -- option for a log/dribble file. Declare dribble variable. Mon Feb 12 08:53:29 1996 John Fitch * musmon.c (musmon): Added guard to opening O.playscore as at least Linux barfs (thabks to Richard Furse). Thu Feb 1 09:41:00 1996 John Fitch * lpanal.c (gauss): Change all *(b+..) of b[...] for clarity (alpol): Calcular error at end more simply -- less arithmetic but some danger of overflow (but I think not) Mon Jan 29 09:51:34 1996 John Fitch * lpanal.c (lpanal, alpol): Allocate array x once in lpanal rather than on every call of alpol. (gauss): Similar for aold Sun Jan 28 15:50:00 1996 John Fitch * lpanal.c (alpol): Optimise a pow(..., 2.0) to a product * mw_menu.c (dlgUtilLpAnal): Set mark in box for Verbose and Graphics boxs (dlgUtilPvAnal): The same. (dlgFileOpen): Allow direct editing of orc and sco file names. Also requires change in Csound.rsrc (dlgUtilLpAnal): Added a Debug option and corrected verbose to give -v1 Mon Jan 22 08:53:45 1996 John Fitch * Csound.rsrc: (Mac only) added titles to dialogs and fixed mini-typo in dialog linking Sun Jan 21 20:15:40 1996 John Fitch * musmon.c (musmon): Remove call to RTclose as atexit does it * linevent.c (RTLineset): Use atexit to arrange call to RTclose Sun Jan 14 21:25:06 1996 John Fitch * sysdep.h: * soundio.c: * pvoc.c: * otran.c: * mw_menu.c: * midirecv.c: * memfiles.c: * main.c: * linevent.c: * filopen.c: * dpwelib.h: * cs.h: Changed THINK_C to SYMANTEC as need to modify their library as bug in I/O. Sun Jan 7 14:49:44 1996 John Fitch * Change type of cscore to void for consistency Thu Jan 4 08:15:53 1996 John Fitch * grain4.c (graingenv4): Changed a 1.0* to a float for speed * cs.h (SUBVER): CHANGE VERSION NUMBER TO 3.36 * grain.c (agsset): Added a size check in the decision to get a new buffer. Wed Jan 3 07:46:39 1996 John Fitch * winX11.c (ExitGraph): Added a check to the CSNOSTOP environment variable to avoid the final wait for click. Mon Jan 1 18:56:08 1996 John Fitch * main.c (endif): Need an exit(0) after call to cvanal Thu Dec 28 16:55:27 1995 John Fitch * util2/mixer/mixer.c (MixSound): In output buffer step by number of channels * util2/mixer/mixer.c: Added prototypes and includes Wed Dec 27 21:16:29 1995 John Fitch * util2/mixer/mixer.c (InitScaleTable): Deal with same x values in table in different way. * util2/mixer/mixer.c (MixSound): Add code to handle stereo etc inputs correctly, with additional field in structure. Mon Dec 25 14:38:20 1995 John Fitch * util2/mixer/mixer.c (main): Added AE_BYTE format (bytetran): New function Fri Dec 22 10:14:06 1995 John Fitch * grain4.c (grainsetv4): Various spelling corrections and minor optimisations. Also changes exit(1) to initerror calls and return. Tue Dec 19 09:34:52 1995 John Fitch * cs.h: Upped VERSION to 3.35 * grain4.c: NEW FILE for granular synthesis * entry.c: Added buthp, butlp, butbp, butbr as synonyms for butterXX, and convle and an abbreviation for convolve. Added grain4 operator * cs.h: Added a next field in MEMFIL to relax memfiles.c * memfiles.c (rlsmemfiles): Adjust to delete from the revised structure (ldmemfile): Follow list of MEMFILs while looking for file Sat Dec 16 14:35:22 1995 John Fitch * mw_menu.c: Added utilities dialogs, and other stuff. * pvanal.c (takeFFTs): Added POLL_EVENTS at end of loop * lpanal.c (lpanal): Added call to POLL_EVENTS at end of loop for Mac and PC. * winsound.ico, dream.ico: Changed to have screen background Sun Dec 3 09:35:05 1995 John Fitch * soundio.c (audwrite): For macintosh make heartbeat use the metronome cursor. * rdscor.c (rdscor): Close score file at EOF. Sat Dec 2 18:04:03 1995 John Fitch * main.c (main): Correct the check for WAV+format and AIFF+format Tue Nov 21 07:22:20 1995 John Fitch * soundio.h: (solaris) include * soundio.c: (solaris) define audiofd variable (sfopenout): (solaris) write header specially * sfheader.c: Solaris support, include (readheader): No need for ininfop, and do rewind (solaris) (writeheader): Solaris has different checks for devaudio when opening. * rtaudio.c: Add solaris support * rdorch.c: Include for solaris * midirecv.c: Add Solaris support * makefile: Added Solaris2.4 library stuff Mon Oct 30 07:16:41 1995 John Fitch * cwin.h: Remove referrences to Greek. Sun Oct 29 10:27:53 1995 John Fitch * winsound.rc: Modified Dialog_1 for unsigned 8bit and reshape Made file names wider, and reposition on screen * cs.h (SUBVER): Increased to 34 * wave.c (wavWriteHdr): Set len0 filed to databytes+36 as suggested by Mohr (wavReWriteHdr): Set len0 to 8 bytes less than end -- seems odd (wavReadHeader): Force BYTE format * soundio.c (iotranset): Set up BYTE format, twice (bytetran): New function for unsigned 8-bit samples (bzerotran): New function ditto (byterecv): New function ditto * soundin.c (getstrformat): Add AE_BYTE format (getsizformat): formatsiz longer for new format, and test against AE_LAST (sndgetset): Add AE_BYTE (getsndin): BYTE format again, in all and select channel forms (soundin): BYTE format * rtaudio.c: Includes and defines for LINUX (recopen): Open for LINUX (playopen): Open and set volume for LINUX (rtrecord): Get LINUX bytes (rtplay): Write LINUX bytes (rtclose): and LINUX close * midirecv.c: Add #defines for LINUX * makefile: Comment on options for LINUX * soundio.h (AE_BYTE): Defined for unsigned 8bit (AE_LAST): Defined for checking purposes * main.c (main): Added -8 option for unsigned 8bit samples. (main): In WAV format must be -8 or -s format (main): Add -V for volume option (LINUX only) (usage): and extend message tp reflect all this * cs.h: Added Volume field to OPARMS structure for LINUX only Mon Oct 23 09:53:37 1995 John Fitch * cs.h (SUBVER): Up subversion number to 33 * cwin.cpp (cwin_args): Set play_on_exit to false unless it is a WAV format. (CDialog): Add OnPlay method * dialogs.h: Add check box for play on exit * winsound.rc: Add Check box for play_on_exit Sun Oct 22 21:31:06 1995 John Fitch * cwin.cpp (cwin_exit): Added code to play sound file on exit and a flag set. No link to set flag yet. Tue Oct 17 22:37:08 1995 John Fitch * main.c (main): Add printing of Version number at start; may revise this. Mon Oct 16 21:07:23 1995 John Fitch * pvdlg.cpp (Cpvdlg::Cpvdlg): Initialise input and output from registry (pvanal_dialog): Write file names back to registry * lpcdlg.cpp (Clpcdlg::Clpcdlg): Initialise input and output from registry (lpanal_dialog): Write file names back to registry * hetdlg.cpp (Chetdlg::Chetdlg): Initialise input and output from registry (hetro_dialog): Write file names back to registry * cvdlg.cpp (Ccvdlg::Ccvdlg): Initialise input and output from registry (cvanal_dialog): Write file names back to registry Mon Oct 16 06:06:57 1995 John Fitch * cwin.cpp: Remove declaration of CTheApp class * cwin.h: Move delaration of CTheApp class to C++ section and get external reference to theApp * cwin.cpp: Generally remove Symbol fonts and Greek (CArg::CArg): Initialise from the registry (cwin_args): Write values back to registry (CArg): Declare csound_section (CArg::OnExtras): Initialize and save in registry (CArg::OnInitDialog): Initialise butons as in registry (CSextras::DoDataExchange): Use DDX to initialise check boxes rather than methods * wave.c (wavWriteHdr): Improved comments Sun Oct 1 16:43:18 1995 John Fitch * WINDOWS Version: Now can distribute cwin.cpp and associated files Sun Sep 24 09:44:59 1995 John Fitch * DOS VERSION: Renames cspent.* to csound.* and change the project accordingly. Wed Sep 20 21:33:40 1995 John Fitch * oload.c (oload): In test for inconsistent sr/kr!=ksmps add extra printing to look for possible MAC bug. Sat Aug 12 15:38:36 1995 John Fitch * memfiles.c (RD_OPTS): Extra cases for DOSGCC, LATTICE and the rest (LoadFile): IGNORE foo argument, and use RD_OPTS as arg to open Sun Jul 30 10:20:57 1995 John Fitch * oload.c (oload): Mac specific STasks -> POLL_EVENTS * winascii.c (MakeAscii): Add second (unused) argument so agrees with design (DrawAscii): POLL_EVENTS in the loop (not mac only STasks) * rdorch.c: For SUN computers need to define SEEK_SET etc as their compiler is not true ANSI (splitline): Mac specific STasks -> POLL_EVENTS * scsort.c: include cs.h for POLL_EVENTS (scsort): Now a void function, and Mac specific STasks -> POLL_EVENTS * otran.c (insprep): Remove unused variable newlabs (insprep): Remove unused variable newlarg (insprep): Mac only STasks -> POLL_EVENTS (constndx): Remove old (commented out) code to read numbers as the scanf version seems more secure. * insert.c (kperf): Layout (kperf): Changed Mac specific STasks to POLL_EVENTS for generality (rireturn): Explicit IGNORE of argument to keep compiler quiet (reinit): Add explicit cast to keep type system sweet * cs.h: Include : __ZTC__ -> __ZPC__ and WATCOMC support : LATTICE C support incorporated from Atari : Declare structures only if in C (not C++) Declare POLL_EVENTS as STasks in Mac, nothing in C, and leave in WINDOWS; for CWIN need to macro fprintf and printf to window-writing versions Sat Jul 29 15:22:05 1995 John Fitch * soundio.h: ANSI only prototypes * filopen.c: Declare soundfile_pointer if on MetroWerks compiler (sssfinit): Add __MWERKS__ to THINK_C (isfullpath): Add __MWERKS__ to THINK_C (catpath): Add __MWERKS__ to THINK_C (unquote): Add __MWERKS__ to THINK_C : Definition of RD_OPTS and WR_OPTS for MetroWerks Define O_BINARY if not done already and use in teh RD/WR OPTS (openout): Not defined for MWERKS, and totally new version, and define tell * soundio.c (audwrite): POLL_EVENTS after heartbeat (sfopenout): For Mac direct output is in AE_SHORT format (sfopenout): Add Mac Headers and Creator (Mac only!) (chartran): Add cast to long as appropriate * sfheader.c (readheader): MetroWerks support (for powerPc) (readheader): Remove unused variable n (readheader): Tidy up #if...#elif... structure (readheader): Do a SEEK to end before closing file to get size, rather than use calculated value, and better general case (writeheader): Add casts in call to write (writeheader): Support fotr Mac file type moved elsewhere Sat Jul 15 15:11:47 1995 John Fitch * pvanal.c: ANSI prototypes only __ZTC__ -> __ZPC__ so Mac compiles (pvanal): Now an int valued function, and calls dialog in WINDOWS case (pvanal): Added -V and -v options for tracing, and print PV data if verbose is set (quit): Change usage message for -v and -V (takeFFTs): IGNORE outputPVH argument (takeFFTs): Do not print simple messages is verbose is set (takeFFTs): but print it later in detail (PrintBuf): Print trace to the trace file * pvoc.c: __ZTC__ -> __ZPC__ * ustub.h: __ZTC__ -> __ZPC__ * musmon.c (musmon): __ZTC__ -> __ZPC__ (musmon): Added calls to POLL_EVENTS all over the place (musmon): If LINEin in use call RTClose as part of clean up (playevents): Call POLL_EVENTS in the loop * lpanal.c: __ZTC__ -> __ZPC__ (lpanal): Now a int valued function, returning non zero for success (lpanal): Remove unused variable nsamps (lpanal): Call dialog system for WINDOWS (lpanal): __ZTC__ -> __ZPC__ (lpanal): Remove unused variable fp2 * linevent.c: Declare stdmode to save old mode of tty (RTLineset): __ZTC__ -> __ZPC__ (RTLineset): Remember old tty mode in stdmode (UNIX only) (RTclose): If output was to tty restore the mode in UNIX cases [Last two fix bug about disapprearing Xterms] (sensLine): ANSI header * sysdep.h: __ZTC__ -> __ZPC__ * dsputil.c: Change __ZTC__ to __ZPC_ and add support for WATCOMC (Rect2Polar): Remove unused variable pha (MakeHalfWin): Removed unused variable a,b and i * dpwelib.h: Change __ZTC__ to __ZPC__ as it interferes with Macintosh compiler * midirecv.c: __ZTC__ -> __ZPC__ (MidiOpen): IGNORE arg if not SGI (m_timcod_QF): IGNORE arguments (m_song_pos): IGNORE arguments (m_song_sel): IGNORE arguments * main.c: __ZTC__ -> __ZPC__ : for Windows declare dialog functions, and rename main to cwin_main (main): add POLL_EVENTS and for Windows call cwin_atexit to free space; call dialog system (main): WATCOM C support (dialog_arguments): WINDOWS only call dialog for arguments Tue Jun 11 11:30:15 1995 John Fitch * memalloc.c (all_free): WINDOWS only function to return all space controlled by at_exit; record up to 1024 blocks (mcalloc): Record space (WINDOWS only) (mmalloc): Record space (WINDOWS only) (mrealloc): Record space (WINDOWS only) Sun Jul 9 16:51:13 1995 John Fitch * hetro.c (hetro): Make it a int function rather than void, and add dialog support for Windows (hetro): POLL_EVENTS() added, and also some debugging code Thu Jun 8 08:49:11 1995 John Fitch * ugens9.c: Correct prototype for writeFromCircBuf * ugens3.c (losset): Proper ANSI prototype for ftnp2find * wave.c (wavReadHeader): IGNORE fname argument * winwat.c (my_term): IGNORE argument (MakeGraph): IGNORE arguments (DrawGraph): Remove unused variables ma,mi and c (DrawGraph): and nx and ny (KillGraph): IGNORE argument (MakeXYin): IGNORE arguments (ReadXYin): IGNORE argument * winfg.c (MakeGraph): Add some debugging as it sometimes get screen wrong * disprep.c (tempeset): Comment out unused variables coef and log001 (tempest): Remove unused xscale variable * ugens8.c: Remove unused variables fzero and fone (pvset): Remove unused variables cp and pvp (pvoc): Remove unused variables nsmps and samp * vdelay.c (ESR): Extra brackets (reverb2_play): Remove unused variable temp, and shorten some warnings (for 286!) Sun Jun 4 13:40:29 1995 John Fitch * scot.c: ANSIfied all declarations * scot.h: and the same * prototyp.h: Change hetro, lpanal, pvanal and cvanal into returning int so the dialogs can indicate success; declare macro IGNORE for general use, and for CWIN declare all_free function * ieee80.c (myUlongToDouble): Layout (myDoubleToUlong): Layout * window.c: ANSI prototypes (DummyFn2): IGNORE arguments (DummyFn1): IGNORE arguments (RdXYDummy): IGNORE arguments (dispinit): The functions assigned are now differentiated as their type differ (dispkill): ANSI format (display): ANSI format * fft.c (FFT2torlpacked): Removed unused variable mm (FFT2realpacked): Removed unused variable mm (FFT2rawpacked): Removed unused variable i Sat Jun 3 17:29:39 1995 John Fitch * express.c (express): Remove unused variable p Sun May 14 18:15:18 1995 John Fitch * dumpf.c (nkdump): Increase precision of output from %4.2 to %6.4 in two places Sat May 13 10:19:24 1995 John Fitch * aiff.c: various debugging statements added, all commented out. Thu Apr 27 15:47:36 1995 John Fitch * sndinfo.c (sndinfo): Add POLL_EVENTS at the start of the function (not sure it is necessary?) * cvanal.c (cvanal): Added support for cvanal_dialog in Windows (quit): Return 1 rather than zero in exit. (takeFFT): Added call to POLL_EVENTS() twice (cvanal): Return 1 as value (true) * blaster.c: In dmaChannel structure use shorts instead of ints (SB_DMA2): Remove macro for DMA2 as now table driven (sb_wait): Count down check so to avoid a hang (sbplay): Mask Channel down to 2 bits (not necessary but clean) Sun Feb 26 1995 John Fitch * winSGI.c (Graphable): ANSI void added (drawAxes): and again * window.h: ANSI format prototypes only * winX11.c: ANSI prototypes only (myXwinWait): ANSI declaration (myXwait): ANSI declaration (myXWaitForExpose): ANSI declaration (Graphable): ANSI declaration (MakeWindow): ANSI declaration (MakeGraph): ANSI declaration (MakeXYin): ANSI declaration (DrawGraph): ANSI declaration (ReadXYin): ANSI declaration (KillWin): ANSI declaration (KillGraph): ANSI declaration (KillXYin): ANSI declaration (ExitGraph): ANSI declarationoa csound-6.10.0/OSX/Csound OSX Examples/000077500000000000000000000000001321653344700171765ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples.xcodeproj/000077500000000000000000000000001321653344700246165ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples.xcodeproj/project.pbxproj000066400000000000000000001321241321653344700276750ustar00rootroot00000000000000// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ C41F0AD219738B8F00997479 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C41F0AD119738B8F00997479 /* Cocoa.framework */; }; C41F0ADC19738B8F00997479 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = C41F0ADA19738B8F00997479 /* InfoPlist.strings */; }; C41F0ADE19738B8F00997479 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C41F0ADD19738B8F00997479 /* main.m */; }; C41F0AE219738B8F00997479 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = C41F0AE019738B8F00997479 /* Credits.rtf */; }; C41F0AE519738B8F00997479 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = C41F0AE419738B8F00997479 /* AppDelegate.m */; }; C41F0AE819738B8F00997479 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = C41F0AE619738B8F00997479 /* MainMenu.xib */; }; C41F0AEA19738B8F00997479 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C41F0AE919738B8F00997479 /* Images.xcassets */; }; C41F0B5F1973913D00997479 /* CsoundObj.m in Sources */ = {isa = PBXBuildFile; fileRef = C41F0B591973913D00997479 /* CsoundObj.m */; }; C41F0B611973913D00997479 /* LICENSE.TXT in Resources */ = {isa = PBXBuildFile; fileRef = C41F0B5E1973913D00997479 /* LICENSE.TXT */; }; C41F0B631973921C00997479 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C41F0B621973921C00997479 /* AudioToolbox.framework */; }; C41F0B651973922900997479 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C41F0B641973922900997479 /* AudioUnit.framework */; }; C41F0B671973923700997479 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C41F0B661973923700997479 /* AVFoundation.framework */; }; C41F0B691973924500997479 /* CoreMIDI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C41F0B681973924500997479 /* CoreMIDI.framework */; }; C41F0B871973AB5500997479 /* IV.csd in Resources */ = {isa = PBXBuildFile; fileRef = C41F0B861973AB5500997479 /* IV.csd */; }; C41F0B891973AB5C00997479 /* test.csd in Resources */ = {isa = PBXBuildFile; fileRef = C41F0B881973AB5C00997479 /* test.csd */; }; C448A0BA1A870923005DF13D /* TrappedGeneratorWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = C448A0B81A870923005DF13D /* TrappedGeneratorWindowController.m */; }; C448A0BB1A870923005DF13D /* TrappedGeneratorWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = C448A0B91A870923005DF13D /* TrappedGeneratorWindowController.xib */; }; C448A0BE1A870958005DF13D /* trapped.csd in Resources */ = {isa = PBXBuildFile; fileRef = C448A0BD1A870958005DF13D /* trapped.csd */; }; C45DCDAA199F289900A667B6 /* CsoundButtonBinding.m in Sources */ = {isa = PBXBuildFile; fileRef = C45DCDA5199F289900A667B6 /* CsoundButtonBinding.m */; }; C45DCDAB199F289900A667B6 /* CsoundSliderBinding.m in Sources */ = {isa = PBXBuildFile; fileRef = C45DCDA7199F289900A667B6 /* CsoundSliderBinding.m */; }; C45DCDAC199F289900A667B6 /* CsoundUI.m in Sources */ = {isa = PBXBuildFile; fileRef = C45DCDA9199F289900A667B6 /* CsoundUI.m */; }; C45DCDAF199F3E9600A667B6 /* CsoundMomentaryButtonBinding.m in Sources */ = {isa = PBXBuildFile; fileRef = C45DCDAE199F3E9600A667B6 /* CsoundMomentaryButtonBinding.m */; }; C46B769719B6FE33000D4F95 /* InstrumentEditorWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = C46B769519B6FE33000D4F95 /* InstrumentEditorWindowController.m */; }; C46B769819B6FE33000D4F95 /* InstrumentEditorWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = C46B769619B6FE33000D4F95 /* InstrumentEditorWindowController.xib */; }; C46B769B19B6FF11000D4F95 /* instrumentEditor.csd in Resources */ = {isa = PBXBuildFile; fileRef = C46B769A19B6FF11000D4F95 /* instrumentEditor.csd */; }; C478097E1984C164000FD79F /* audioInTest.csd in Resources */ = {isa = PBXBuildFile; fileRef = C478097A1984C164000FD79F /* audioInTest.csd */; }; C47809841984C18E000FD79F /* AudioInTestWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = C47809821984C18E000FD79F /* AudioInTestWindowController.m */; }; C47809851984C18E000FD79F /* AudioInTestWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = C47809831984C18E000FD79F /* AudioInTestWindowController.xib */; }; C47809881985EF27000FD79F /* harmonizer.csd in Resources */ = {isa = PBXBuildFile; fileRef = C47809871985EF27000FD79F /* harmonizer.csd */; }; C478098C1985EF3C000FD79F /* HarmonizerWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = C478098A1985EF3C000FD79F /* HarmonizerWindowController.m */; }; C478098D1985EF3C000FD79F /* HarmonizerWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = C478098B1985EF3C000FD79F /* HarmonizerWindowController.xib */; }; C4B5D43319914B350072A430 /* BaseCsoundWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = C4B5D43219914B350072A430 /* BaseCsoundWindowController.m */; }; C4B5D4391991A26C0072A430 /* recordTest.csd in Resources */ = {isa = PBXBuildFile; fileRef = C4B5D4351991A26C0072A430 /* recordTest.csd */; }; C4B5D43A1991A26C0072A430 /* RecordTestWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = C4B5D4371991A26C0072A430 /* RecordTestWindowController.m */; }; C4B5D43B1991A26C0072A430 /* RecordTestWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = C4B5D4381991A26C0072A430 /* RecordTestWindowController.xib */; }; C4EBCDE519761D6A00A7C7C1 /* ConsoleOutputWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = C4EBCDE319761D6A00A7C7C1 /* ConsoleOutputWindowController.m */; }; C4EBCDE619761D6A00A7C7C1 /* ConsoleOutputWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = C4EBCDE419761D6A00A7C7C1 /* ConsoleOutputWindowController.xib */; }; C4EBCDEB1976504200A7C7C1 /* consoleoutput.csd in Resources */ = {isa = PBXBuildFile; fileRef = C4EBCDEA1976504200A7C7C1 /* consoleoutput.csd */; }; C4EBCDEF1976636D00A7C7C1 /* AudioFileTestWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = C4EBCDED1976636D00A7C7C1 /* AudioFileTestWindowController.m */; }; C4EBCDF01976636D00A7C7C1 /* AudioFileTestWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = C4EBCDEE1976636D00A7C7C1 /* AudioFileTestWindowController.xib */; }; C4EBCDFA1976F4A700A7C7C1 /* CsoundLib64.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C41F0B6A1973927900997479 /* CsoundLib64.framework */; }; C4EBCDFB1978C7E700A7C7C1 /* testAudioFile.aif in Resources */ = {isa = PBXBuildFile; fileRef = C4EBCDF71976654800A7C7C1 /* testAudioFile.aif */; }; C4EBCDFD1978C9E000A7C7C1 /* audiofiletest.csd in Resources */ = {isa = PBXBuildFile; fileRef = C4EBCDFC1978C9E000A7C7C1 /* audiofiletest.csd */; }; C4F2B9D019749CBD006EE12F /* test2.csd in Resources */ = {isa = PBXBuildFile; fileRef = C4F2B9CF19749CBD006EE12F /* test2.csd */; }; C4F2B9D81974A2C3006EE12F /* buttonTest.csd in Resources */ = {isa = PBXBuildFile; fileRef = C4F2B9D71974A2C3006EE12F /* buttonTest.csd */; }; C4F2B9DE1974AB7B006EE12F /* ButtonTestWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = C4F2B9DC1974AB7B006EE12F /* ButtonTestWindowController.m */; }; C4F2B9DF1974AB7B006EE12F /* ButtonTestWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = C4F2B9DD1974AB7B006EE12F /* ButtonTestWindowController.xib */; }; C4F2B9E31974C476006EE12F /* CsoundHaiku4WindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = C4F2B9E11974C476006EE12F /* CsoundHaiku4WindowController.m */; }; C4F2B9E41974C476006EE12F /* CsoundHaiku4WindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = C4F2B9E21974C476006EE12F /* CsoundHaiku4WindowController.xib */; }; C4F2B9E81974C693006EE12F /* SimpleTest1WindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = C4F2B9E61974C693006EE12F /* SimpleTest1WindowController.m */; }; C4F2B9E91974C693006EE12F /* SimpleTest1WindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = C4F2B9E71974C693006EE12F /* SimpleTest1WindowController.xib */; }; C4F2B9ED1974C6A7006EE12F /* SimpleTest2WindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = C4F2B9EB1974C6A7006EE12F /* SimpleTest2WindowController.m */; }; C4F2B9EE1974C6A7006EE12F /* SimpleTest2WindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = C4F2B9EC1974C6A7006EE12F /* SimpleTest2WindowController.xib */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ C41F0ACE19738B8F00997479 /* Csound OSX Examples.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Csound OSX Examples.app"; sourceTree = BUILT_PRODUCTS_DIR; }; C41F0AD119738B8F00997479 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; C41F0AD419738B8F00997479 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; C41F0AD519738B8F00997479 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; C41F0AD619738B8F00997479 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; C41F0AD919738B8F00997479 /* Csound OSX Examples-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Csound OSX Examples-Info.plist"; sourceTree = ""; }; C41F0ADB19738B8F00997479 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; C41F0ADD19738B8F00997479 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; C41F0ADF19738B8F00997479 /* Csound OSX Examples-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Csound OSX Examples-Prefix.pch"; sourceTree = ""; }; C41F0AE119738B8F00997479 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; C41F0AE319738B8F00997479 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; C41F0AE419738B8F00997479 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; C41F0AE719738B8F00997479 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; C41F0AE919738B8F00997479 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; C41F0AF019738B8F00997479 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; C41F0B581973913D00997479 /* CsoundObj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CsoundObj.h; sourceTree = ""; }; C41F0B591973913D00997479 /* CsoundObj.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CsoundObj.m; sourceTree = ""; }; C41F0B5E1973913D00997479 /* LICENSE.TXT */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE.TXT; sourceTree = ""; }; C41F0B621973921C00997479 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; C41F0B641973922900997479 /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = System/Library/Frameworks/AudioUnit.framework; sourceTree = SDKROOT; }; C41F0B661973923700997479 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; C41F0B681973924500997479 /* CoreMIDI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMIDI.framework; path = System/Library/Frameworks/CoreMIDI.framework; sourceTree = SDKROOT; }; C41F0B6A1973927900997479 /* CsoundLib64.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CsoundLib64.framework; path = ../../../../../../../Library/Frameworks/CsoundLib64.framework; sourceTree = ""; }; C41F0B861973AB5500997479 /* IV.csd */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = IV.csd; path = CsoundHaiku4/IV.csd; sourceTree = ""; }; C41F0B881973AB5C00997479 /* test.csd */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = test.csd; path = SimpleTest1/test.csd; sourceTree = ""; }; C448A0B71A870923005DF13D /* TrappedGeneratorWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TrappedGeneratorWindowController.h; path = TrappedGenerator/TrappedGeneratorWindowController.h; sourceTree = ""; }; C448A0B81A870923005DF13D /* TrappedGeneratorWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TrappedGeneratorWindowController.m; path = TrappedGenerator/TrappedGeneratorWindowController.m; sourceTree = ""; }; C448A0B91A870923005DF13D /* TrappedGeneratorWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = TrappedGeneratorWindowController.xib; path = TrappedGenerator/TrappedGeneratorWindowController.xib; sourceTree = ""; }; C448A0BD1A870958005DF13D /* trapped.csd */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = trapped.csd; path = TrappedGenerator/trapped.csd; sourceTree = ""; }; C45DCDA4199F289900A667B6 /* CsoundButtonBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CsoundButtonBinding.h; sourceTree = ""; }; C45DCDA5199F289900A667B6 /* CsoundButtonBinding.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CsoundButtonBinding.m; sourceTree = ""; }; C45DCDA6199F289900A667B6 /* CsoundSliderBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CsoundSliderBinding.h; sourceTree = ""; }; C45DCDA7199F289900A667B6 /* CsoundSliderBinding.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CsoundSliderBinding.m; sourceTree = ""; }; C45DCDA8199F289900A667B6 /* CsoundUI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CsoundUI.h; sourceTree = ""; }; C45DCDA9199F289900A667B6 /* CsoundUI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CsoundUI.m; sourceTree = ""; }; C45DCDAD199F3E9600A667B6 /* CsoundMomentaryButtonBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CsoundMomentaryButtonBinding.h; sourceTree = ""; }; C45DCDAE199F3E9600A667B6 /* CsoundMomentaryButtonBinding.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CsoundMomentaryButtonBinding.m; sourceTree = ""; }; C46B769419B6FE33000D4F95 /* InstrumentEditorWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InstrumentEditorWindowController.h; path = InstrumentEditor/InstrumentEditorWindowController.h; sourceTree = ""; }; C46B769519B6FE33000D4F95 /* InstrumentEditorWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = InstrumentEditorWindowController.m; path = InstrumentEditor/InstrumentEditorWindowController.m; sourceTree = ""; }; C46B769619B6FE33000D4F95 /* InstrumentEditorWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = InstrumentEditorWindowController.xib; path = InstrumentEditor/InstrumentEditorWindowController.xib; sourceTree = ""; }; C46B769A19B6FF11000D4F95 /* instrumentEditor.csd */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = instrumentEditor.csd; path = InstrumentEditor/instrumentEditor.csd; sourceTree = ""; }; C478097A1984C164000FD79F /* audioInTest.csd */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = audioInTest.csd; sourceTree = ""; }; C47809811984C18E000FD79F /* AudioInTestWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioInTestWindowController.h; sourceTree = ""; }; C47809821984C18E000FD79F /* AudioInTestWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AudioInTestWindowController.m; sourceTree = ""; }; C47809831984C18E000FD79F /* AudioInTestWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AudioInTestWindowController.xib; sourceTree = ""; }; C47809871985EF27000FD79F /* harmonizer.csd */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = harmonizer.csd; sourceTree = ""; }; C47809891985EF3C000FD79F /* HarmonizerWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HarmonizerWindowController.h; sourceTree = ""; }; C478098A1985EF3C000FD79F /* HarmonizerWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HarmonizerWindowController.m; sourceTree = ""; }; C478098B1985EF3C000FD79F /* HarmonizerWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = HarmonizerWindowController.xib; sourceTree = ""; }; C4B5D43119914B350072A430 /* BaseCsoundWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BaseCsoundWindowController.h; sourceTree = ""; }; C4B5D43219914B350072A430 /* BaseCsoundWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BaseCsoundWindowController.m; sourceTree = ""; }; C4B5D4351991A26C0072A430 /* recordTest.csd */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = recordTest.csd; sourceTree = ""; }; C4B5D4361991A26C0072A430 /* RecordTestWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecordTestWindowController.h; sourceTree = ""; }; C4B5D4371991A26C0072A430 /* RecordTestWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RecordTestWindowController.m; sourceTree = ""; }; C4B5D4381991A26C0072A430 /* RecordTestWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = RecordTestWindowController.xib; sourceTree = ""; }; C4EBCDE219761D6A00A7C7C1 /* ConsoleOutputWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConsoleOutputWindowController.h; path = ConsoleOutput/ConsoleOutputWindowController.h; sourceTree = ""; }; C4EBCDE319761D6A00A7C7C1 /* ConsoleOutputWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ConsoleOutputWindowController.m; path = ConsoleOutput/ConsoleOutputWindowController.m; sourceTree = ""; }; C4EBCDE419761D6A00A7C7C1 /* ConsoleOutputWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = ConsoleOutputWindowController.xib; path = ConsoleOutput/ConsoleOutputWindowController.xib; sourceTree = ""; }; C4EBCDEA1976504200A7C7C1 /* consoleoutput.csd */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = consoleoutput.csd; path = ConsoleOutput/consoleoutput.csd; sourceTree = ""; }; C4EBCDEC1976636D00A7C7C1 /* AudioFileTestWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioFileTestWindowController.h; path = AudioFileTest/AudioFileTestWindowController.h; sourceTree = ""; }; C4EBCDED1976636D00A7C7C1 /* AudioFileTestWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AudioFileTestWindowController.m; path = AudioFileTest/AudioFileTestWindowController.m; sourceTree = ""; }; C4EBCDEE1976636D00A7C7C1 /* AudioFileTestWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = AudioFileTestWindowController.xib; path = AudioFileTest/AudioFileTestWindowController.xib; sourceTree = ""; }; C4EBCDF71976654800A7C7C1 /* testAudioFile.aif */ = {isa = PBXFileReference; lastKnownFileType = file; name = testAudioFile.aif; path = AudioFileTest/testAudioFile.aif; sourceTree = ""; }; C4EBCDFC1978C9E000A7C7C1 /* audiofiletest.csd */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = audiofiletest.csd; path = AudioFileTest/audiofiletest.csd; sourceTree = ""; }; C4F2B9CF19749CBD006EE12F /* test2.csd */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = test2.csd; path = SimpleTest2/test2.csd; sourceTree = ""; }; C4F2B9D71974A2C3006EE12F /* buttonTest.csd */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = buttonTest.csd; path = ButtonTest/buttonTest.csd; sourceTree = ""; }; C4F2B9DB1974AB7B006EE12F /* ButtonTestWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ButtonTestWindowController.h; path = ButtonTest/ButtonTestWindowController.h; sourceTree = ""; }; C4F2B9DC1974AB7B006EE12F /* ButtonTestWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ButtonTestWindowController.m; path = ButtonTest/ButtonTestWindowController.m; sourceTree = ""; }; C4F2B9DD1974AB7B006EE12F /* ButtonTestWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = ButtonTestWindowController.xib; path = ButtonTest/ButtonTestWindowController.xib; sourceTree = ""; }; C4F2B9E01974C476006EE12F /* CsoundHaiku4WindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CsoundHaiku4WindowController.h; path = CsoundHaiku4/CsoundHaiku4WindowController.h; sourceTree = ""; }; C4F2B9E11974C476006EE12F /* CsoundHaiku4WindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CsoundHaiku4WindowController.m; path = CsoundHaiku4/CsoundHaiku4WindowController.m; sourceTree = ""; }; C4F2B9E21974C476006EE12F /* CsoundHaiku4WindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = CsoundHaiku4WindowController.xib; path = CsoundHaiku4/CsoundHaiku4WindowController.xib; sourceTree = ""; }; C4F2B9E51974C693006EE12F /* SimpleTest1WindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SimpleTest1WindowController.h; path = SimpleTest1/SimpleTest1WindowController.h; sourceTree = ""; }; C4F2B9E61974C693006EE12F /* SimpleTest1WindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SimpleTest1WindowController.m; path = SimpleTest1/SimpleTest1WindowController.m; sourceTree = ""; }; C4F2B9E71974C693006EE12F /* SimpleTest1WindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = SimpleTest1WindowController.xib; path = SimpleTest1/SimpleTest1WindowController.xib; sourceTree = ""; }; C4F2B9EA1974C6A7006EE12F /* SimpleTest2WindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleTest2WindowController.h; sourceTree = ""; }; C4F2B9EB1974C6A7006EE12F /* SimpleTest2WindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SimpleTest2WindowController.m; sourceTree = ""; }; C4F2B9EC1974C6A7006EE12F /* SimpleTest2WindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SimpleTest2WindowController.xib; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ C41F0ACB19738B8F00997479 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( C4EBCDFA1976F4A700A7C7C1 /* CsoundLib64.framework in Frameworks */, C41F0B631973921C00997479 /* AudioToolbox.framework in Frameworks */, C41F0B651973922900997479 /* AudioUnit.framework in Frameworks */, C41F0B671973923700997479 /* AVFoundation.framework in Frameworks */, C41F0AD219738B8F00997479 /* Cocoa.framework in Frameworks */, C41F0B691973924500997479 /* CoreMIDI.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ C41F0AC519738B8F00997479 = { isa = PBXGroup; children = ( C41F0B561973913D00997479 /* csound-OSX */, C41F0AD719738B8F00997479 /* Csound OSX Examples */, C41F0AD019738B8F00997479 /* Frameworks */, C41F0ACF19738B8F00997479 /* Products */, ); sourceTree = ""; }; C41F0ACF19738B8F00997479 /* Products */ = { isa = PBXGroup; children = ( C41F0ACE19738B8F00997479 /* Csound OSX Examples.app */, ); name = Products; sourceTree = ""; }; C41F0AD019738B8F00997479 /* Frameworks */ = { isa = PBXGroup; children = ( C41F0B6A1973927900997479 /* CsoundLib64.framework */, C41F0B681973924500997479 /* CoreMIDI.framework */, C41F0B661973923700997479 /* AVFoundation.framework */, C41F0B641973922900997479 /* AudioUnit.framework */, C41F0B621973921C00997479 /* AudioToolbox.framework */, C41F0AD119738B8F00997479 /* Cocoa.framework */, C41F0AF019738B8F00997479 /* XCTest.framework */, C41F0AD319738B8F00997479 /* Other Frameworks */, ); name = Frameworks; sourceTree = ""; }; C41F0AD319738B8F00997479 /* Other Frameworks */ = { isa = PBXGroup; children = ( C41F0AD419738B8F00997479 /* AppKit.framework */, C41F0AD519738B8F00997479 /* CoreData.framework */, C41F0AD619738B8F00997479 /* Foundation.framework */, ); name = "Other Frameworks"; sourceTree = ""; }; C41F0AD719738B8F00997479 /* Csound OSX Examples */ = { isa = PBXGroup; children = ( C41F0AE319738B8F00997479 /* AppDelegate.h */, C41F0AE419738B8F00997479 /* AppDelegate.m */, C41F0AE619738B8F00997479 /* MainMenu.xib */, C41F0B761973A0CE00997479 /* Window Controllers */, C41F0AE919738B8F00997479 /* Images.xcassets */, C41F0AD819738B8F00997479 /* Supporting Files */, ); path = "Csound OSX Examples"; sourceTree = ""; }; C41F0AD819738B8F00997479 /* Supporting Files */ = { isa = PBXGroup; children = ( C41F0AD919738B8F00997479 /* Csound OSX Examples-Info.plist */, C41F0ADA19738B8F00997479 /* InfoPlist.strings */, C41F0ADD19738B8F00997479 /* main.m */, C41F0ADF19738B8F00997479 /* Csound OSX Examples-Prefix.pch */, C41F0AE019738B8F00997479 /* Credits.rtf */, ); name = "Supporting Files"; sourceTree = ""; }; C41F0B561973913D00997479 /* csound-OSX */ = { isa = PBXGroup; children = ( C41F0B571973913D00997479 /* classes */, C41F0B5E1973913D00997479 /* LICENSE.TXT */, ); path = "csound-OSX"; sourceTree = ""; }; C41F0B571973913D00997479 /* classes */ = { isa = PBXGroup; children = ( C41F0B581973913D00997479 /* CsoundObj.h */, C41F0B591973913D00997479 /* CsoundObj.m */, C45DCDA2199F289900A667B6 /* Bindings */, ); path = classes; sourceTree = ""; }; C41F0B6F19739ADE00997479 /* CsoundHaiku4 */ = { isa = PBXGroup; children = ( C41F0B861973AB5500997479 /* IV.csd */, C4F2B9E01974C476006EE12F /* CsoundHaiku4WindowController.h */, C4F2B9E11974C476006EE12F /* CsoundHaiku4WindowController.m */, C4F2B9E21974C476006EE12F /* CsoundHaiku4WindowController.xib */, ); name = CsoundHaiku4; sourceTree = ""; }; C41F0B751973A0B200997479 /* SimpleTest1 */ = { isa = PBXGroup; children = ( C41F0B881973AB5C00997479 /* test.csd */, C4F2B9E51974C693006EE12F /* SimpleTest1WindowController.h */, C4F2B9E61974C693006EE12F /* SimpleTest1WindowController.m */, C4F2B9E71974C693006EE12F /* SimpleTest1WindowController.xib */, ); name = SimpleTest1; sourceTree = ""; }; C41F0B761973A0CE00997479 /* Window Controllers */ = { isa = PBXGroup; children = ( C4B5D43119914B350072A430 /* BaseCsoundWindowController.h */, C4B5D43219914B350072A430 /* BaseCsoundWindowController.m */, C4EBCDF11976637200A7C7C1 /* AudioFileTest */, C47809791984C164000FD79F /* AudioInTest */, C4F2B9D41974A297006EE12F /* ButtonTest */, C4EBCDE719761D7200A7C7C1 /* ConsoleOutput */, C41F0B6F19739ADE00997479 /* CsoundHaiku4 */, C47809861985EF27000FD79F /* Harmonizer */, C46B769919B6FE3B000D4F95 /* InstrumentEditor */, C4B5D4341991A26C0072A430 /* RecordTest */, C41F0B751973A0B200997479 /* SimpleTest1 */, C4F2B9CC19747A7E006EE12F /* SimpleTest2 */, C448A0BC1A870928005DF13D /* TrappedGenerator */, ); name = "Window Controllers"; sourceTree = ""; }; C448A0BC1A870928005DF13D /* TrappedGenerator */ = { isa = PBXGroup; children = ( C448A0BD1A870958005DF13D /* trapped.csd */, C448A0B71A870923005DF13D /* TrappedGeneratorWindowController.h */, C448A0B81A870923005DF13D /* TrappedGeneratorWindowController.m */, C448A0B91A870923005DF13D /* TrappedGeneratorWindowController.xib */, ); name = TrappedGenerator; sourceTree = ""; }; C45DCDA2199F289900A667B6 /* Bindings */ = { isa = PBXGroup; children = ( C45DCDA3199F289900A667B6 /* User Interface */, ); name = Bindings; path = bindings; sourceTree = ""; }; C45DCDA3199F289900A667B6 /* User Interface */ = { isa = PBXGroup; children = ( C45DCDA8199F289900A667B6 /* CsoundUI.h */, C45DCDA9199F289900A667B6 /* CsoundUI.m */, C45DCDA4199F289900A667B6 /* CsoundButtonBinding.h */, C45DCDA5199F289900A667B6 /* CsoundButtonBinding.m */, C45DCDAD199F3E9600A667B6 /* CsoundMomentaryButtonBinding.h */, C45DCDAE199F3E9600A667B6 /* CsoundMomentaryButtonBinding.m */, C45DCDA6199F289900A667B6 /* CsoundSliderBinding.h */, C45DCDA7199F289900A667B6 /* CsoundSliderBinding.m */, ); name = "User Interface"; path = ui; sourceTree = ""; }; C46B769919B6FE3B000D4F95 /* InstrumentEditor */ = { isa = PBXGroup; children = ( C46B769A19B6FF11000D4F95 /* instrumentEditor.csd */, C46B769419B6FE33000D4F95 /* InstrumentEditorWindowController.h */, C46B769519B6FE33000D4F95 /* InstrumentEditorWindowController.m */, C46B769619B6FE33000D4F95 /* InstrumentEditorWindowController.xib */, ); name = InstrumentEditor; sourceTree = ""; }; C47809791984C164000FD79F /* AudioInTest */ = { isa = PBXGroup; children = ( C478097A1984C164000FD79F /* audioInTest.csd */, C47809811984C18E000FD79F /* AudioInTestWindowController.h */, C47809821984C18E000FD79F /* AudioInTestWindowController.m */, C47809831984C18E000FD79F /* AudioInTestWindowController.xib */, ); path = AudioInTest; sourceTree = ""; }; C47809861985EF27000FD79F /* Harmonizer */ = { isa = PBXGroup; children = ( C47809871985EF27000FD79F /* harmonizer.csd */, C47809891985EF3C000FD79F /* HarmonizerWindowController.h */, C478098A1985EF3C000FD79F /* HarmonizerWindowController.m */, C478098B1985EF3C000FD79F /* HarmonizerWindowController.xib */, ); path = Harmonizer; sourceTree = ""; }; C4B5D4341991A26C0072A430 /* RecordTest */ = { isa = PBXGroup; children = ( C4B5D4351991A26C0072A430 /* recordTest.csd */, C4B5D4361991A26C0072A430 /* RecordTestWindowController.h */, C4B5D4371991A26C0072A430 /* RecordTestWindowController.m */, C4B5D4381991A26C0072A430 /* RecordTestWindowController.xib */, ); path = RecordTest; sourceTree = ""; }; C4EBCDE719761D7200A7C7C1 /* ConsoleOutput */ = { isa = PBXGroup; children = ( C4EBCDEA1976504200A7C7C1 /* consoleoutput.csd */, C4EBCDE219761D6A00A7C7C1 /* ConsoleOutputWindowController.h */, C4EBCDE319761D6A00A7C7C1 /* ConsoleOutputWindowController.m */, C4EBCDE419761D6A00A7C7C1 /* ConsoleOutputWindowController.xib */, ); name = ConsoleOutput; sourceTree = ""; }; C4EBCDF11976637200A7C7C1 /* AudioFileTest */ = { isa = PBXGroup; children = ( C4EBCDFC1978C9E000A7C7C1 /* audiofiletest.csd */, C4EBCDF71976654800A7C7C1 /* testAudioFile.aif */, C4EBCDEC1976636D00A7C7C1 /* AudioFileTestWindowController.h */, C4EBCDED1976636D00A7C7C1 /* AudioFileTestWindowController.m */, C4EBCDEE1976636D00A7C7C1 /* AudioFileTestWindowController.xib */, ); name = AudioFileTest; sourceTree = ""; }; C4F2B9CC19747A7E006EE12F /* SimpleTest2 */ = { isa = PBXGroup; children = ( C4F2B9CF19749CBD006EE12F /* test2.csd */, C4F2B9EA1974C6A7006EE12F /* SimpleTest2WindowController.h */, C4F2B9EB1974C6A7006EE12F /* SimpleTest2WindowController.m */, C4F2B9EC1974C6A7006EE12F /* SimpleTest2WindowController.xib */, ); name = SimpleTest2; sourceTree = ""; }; C4F2B9D41974A297006EE12F /* ButtonTest */ = { isa = PBXGroup; children = ( C4F2B9D71974A2C3006EE12F /* buttonTest.csd */, C4F2B9DB1974AB7B006EE12F /* ButtonTestWindowController.h */, C4F2B9DC1974AB7B006EE12F /* ButtonTestWindowController.m */, C4F2B9DD1974AB7B006EE12F /* ButtonTestWindowController.xib */, ); name = ButtonTest; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ C41F0ACD19738B8F00997479 /* Csound OSX Examples */ = { isa = PBXNativeTarget; buildConfigurationList = C41F0AFF19738B8F00997479 /* Build configuration list for PBXNativeTarget "Csound OSX Examples" */; buildPhases = ( C41F0ACA19738B8F00997479 /* Sources */, C41F0ACB19738B8F00997479 /* Frameworks */, C41F0ACC19738B8F00997479 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = "Csound OSX Examples"; productName = "Csound OSX Examples"; productReference = C41F0ACE19738B8F00997479 /* Csound OSX Examples.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ C41F0AC619738B8F00997479 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0510; }; buildConfigurationList = C41F0AC919738B8F00997479 /* Build configuration list for PBXProject "Csound OSX Examples" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = C41F0AC519738B8F00997479; productRefGroup = C41F0ACF19738B8F00997479 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( C41F0ACD19738B8F00997479 /* Csound OSX Examples */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ C41F0ACC19738B8F00997479 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( C46B769B19B6FF11000D4F95 /* instrumentEditor.csd in Resources */, C4EBCDF01976636D00A7C7C1 /* AudioFileTestWindowController.xib in Resources */, C4F2B9D81974A2C3006EE12F /* buttonTest.csd in Resources */, C47809851984C18E000FD79F /* AudioInTestWindowController.xib in Resources */, C41F0B891973AB5C00997479 /* test.csd in Resources */, C478098D1985EF3C000FD79F /* HarmonizerWindowController.xib in Resources */, C4F2B9E41974C476006EE12F /* CsoundHaiku4WindowController.xib in Resources */, C46B769819B6FE33000D4F95 /* InstrumentEditorWindowController.xib in Resources */, C478097E1984C164000FD79F /* audioInTest.csd in Resources */, C4F2B9E91974C693006EE12F /* SimpleTest1WindowController.xib in Resources */, C4EBCDFB1978C7E700A7C7C1 /* testAudioFile.aif in Resources */, C448A0BE1A870958005DF13D /* trapped.csd in Resources */, C4F2B9DF1974AB7B006EE12F /* ButtonTestWindowController.xib in Resources */, C47809881985EF27000FD79F /* harmonizer.csd in Resources */, C41F0ADC19738B8F00997479 /* InfoPlist.strings in Resources */, C448A0BB1A870923005DF13D /* TrappedGeneratorWindowController.xib in Resources */, C41F0AEA19738B8F00997479 /* Images.xcassets in Resources */, C41F0B611973913D00997479 /* LICENSE.TXT in Resources */, C4B5D4391991A26C0072A430 /* recordTest.csd in Resources */, C4F2B9EE1974C6A7006EE12F /* SimpleTest2WindowController.xib in Resources */, C41F0AE219738B8F00997479 /* Credits.rtf in Resources */, C4EBCDE619761D6A00A7C7C1 /* ConsoleOutputWindowController.xib in Resources */, C4B5D43B1991A26C0072A430 /* RecordTestWindowController.xib in Resources */, C4EBCDFD1978C9E000A7C7C1 /* audiofiletest.csd in Resources */, C41F0AE819738B8F00997479 /* MainMenu.xib in Resources */, C41F0B871973AB5500997479 /* IV.csd in Resources */, C4EBCDEB1976504200A7C7C1 /* consoleoutput.csd in Resources */, C4F2B9D019749CBD006EE12F /* test2.csd in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ C41F0ACA19738B8F00997479 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( C45DCDAB199F289900A667B6 /* CsoundSliderBinding.m in Sources */, C45DCDAA199F289900A667B6 /* CsoundButtonBinding.m in Sources */, C4F2B9ED1974C6A7006EE12F /* SimpleTest2WindowController.m in Sources */, C41F0AE519738B8F00997479 /* AppDelegate.m in Sources */, C41F0B5F1973913D00997479 /* CsoundObj.m in Sources */, C47809841984C18E000FD79F /* AudioInTestWindowController.m in Sources */, C41F0ADE19738B8F00997479 /* main.m in Sources */, C45DCDAC199F289900A667B6 /* CsoundUI.m in Sources */, C45DCDAF199F3E9600A667B6 /* CsoundMomentaryButtonBinding.m in Sources */, C4F2B9E31974C476006EE12F /* CsoundHaiku4WindowController.m in Sources */, C448A0BA1A870923005DF13D /* TrappedGeneratorWindowController.m in Sources */, C4EBCDE519761D6A00A7C7C1 /* ConsoleOutputWindowController.m in Sources */, C4EBCDEF1976636D00A7C7C1 /* AudioFileTestWindowController.m in Sources */, C4B5D43A1991A26C0072A430 /* RecordTestWindowController.m in Sources */, C46B769719B6FE33000D4F95 /* InstrumentEditorWindowController.m in Sources */, C4B5D43319914B350072A430 /* BaseCsoundWindowController.m in Sources */, C4F2B9E81974C693006EE12F /* SimpleTest1WindowController.m in Sources */, C4F2B9DE1974AB7B006EE12F /* ButtonTestWindowController.m in Sources */, C478098C1985EF3C000FD79F /* HarmonizerWindowController.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ C41F0ADA19738B8F00997479 /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( C41F0ADB19738B8F00997479 /* en */, ); name = InfoPlist.strings; sourceTree = ""; }; C41F0AE019738B8F00997479 /* Credits.rtf */ = { isa = PBXVariantGroup; children = ( C41F0AE119738B8F00997479 /* en */, ); name = Credits.rtf; sourceTree = ""; }; C41F0AE619738B8F00997479 /* MainMenu.xib */ = { isa = PBXVariantGroup; children = ( C41F0AE719738B8F00997479 /* Base */, ); name = MainMenu.xib; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ C41F0AFD19738B8F00997479 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.9; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; }; name = Debug; }; C41F0AFE19738B8F00997479 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.9; SDKROOT = macosx; }; name = Release; }; C41F0B0019738B8F00997479 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(LOCAL_LIBRARY_DIR)/Frameworks", ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Csound OSX Examples/Csound OSX Examples-Prefix.pch"; HEADER_SEARCH_PATHS = ( "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, /Library/Frameworks/CsoundLib64.framework/Headers, ); INFOPLIST_FILE = "Csound OSX Examples/Csound OSX Examples-Info.plist"; LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; name = Debug; }; C41F0B0119738B8F00997479 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(LOCAL_LIBRARY_DIR)/Frameworks", ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Csound OSX Examples/Csound OSX Examples-Prefix.pch"; HEADER_SEARCH_PATHS = ( "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, /Library/Frameworks/CsoundLib64.framework/Headers, ); INFOPLIST_FILE = "Csound OSX Examples/Csound OSX Examples-Info.plist"; LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ C41F0AC919738B8F00997479 /* Build configuration list for PBXProject "Csound OSX Examples" */ = { isa = XCConfigurationList; buildConfigurations = ( C41F0AFD19738B8F00997479 /* Debug */, C41F0AFE19738B8F00997479 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; C41F0AFF19738B8F00997479 /* Build configuration list for PBXNativeTarget "Csound OSX Examples" */ = { isa = XCConfigurationList; buildConfigurations = ( C41F0B0019738B8F00997479 /* Debug */, C41F0B0119738B8F00997479 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = C41F0AC619738B8F00997479 /* Project object */; } csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/000077500000000000000000000000001321653344700226225ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/AppDelegate.h000066400000000000000000000017051321653344700251510ustar00rootroot00000000000000/* AppDelegate.h: Copyright (C) 2014 Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import @interface AppDelegate : NSObject @property (assign) IBOutlet NSWindow *window; @end csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/AppDelegate.m000066400000000000000000000100651321653344700251550ustar00rootroot00000000000000/* AppDelegate.m: Copyright (C) 2014 Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "AppDelegate.h" #import "AudioFileTestWindowController.h" #import "AudioInTestWindowController.h" #import "ButtonTestWindowController.h" #import "ConsoleOutputWindowController.h" #import "CsoundHaiku4WindowController.h" #import "HarmonizerWindowController.h" #import "InstrumentEditorWindowController.h" #import "RecordTestWindowController.h" #import "SimpleTest1WindowController.h" #import "SimpleTest2WindowController.h" #import "TrappedGeneratorWindowController.h" @interface AppDelegate() { AudioFileTestWindowController *audioFileTestWC; AudioInTestWindowController *audioInTestWC; ButtonTestWindowController *buttonTestWC; ConsoleOutputWindowController *consoleOutputWC; CsoundHaiku4WindowController *csoundHaiku4WC; HarmonizerWindowController *harmonizerWC; InstrumentEditorWindowController *instrumentEditorWC; RecordTestWindowController *recorsTestWC; SimpleTest1WindowController *simpleTest1WC; SimpleTest2WindowController *simpleTest2WC; TrappedGeneratorWindowController *trappedWC; } @end @implementation AppDelegate - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { // Insert code here to initialize your application } - (IBAction)loadAudioFileTest:(id)sender { audioFileTestWC = [[AudioFileTestWindowController alloc] initWithWindowNibName:@"AudioFileTestWindowController"]; [audioFileTestWC window]; } - (IBAction)loadAudioInTest:(id)sender { audioInTestWC = [[AudioInTestWindowController alloc] initWithWindowNibName:@"AudioInTestWindowController"]; [audioInTestWC window]; } - (IBAction)loadButtonTest:(id)sender { buttonTestWC = [[ButtonTestWindowController alloc] initWithWindowNibName:@"ButtonTestWindowController"]; [buttonTestWC window]; } - (IBAction)loadConsoleOutput:(id)sender { consoleOutputWC = [[ConsoleOutputWindowController alloc] initWithWindowNibName:@"ConsoleOutputWindowController"]; [consoleOutputWC window]; } - (IBAction)loadCsoundHaiku4:(id)sender { csoundHaiku4WC = [[CsoundHaiku4WindowController alloc] initWithWindowNibName:@"CsoundHaiku4WindowController"]; [csoundHaiku4WC window]; } - (IBAction)loadHarmonizer:(id)sender { harmonizerWC = [[HarmonizerWindowController alloc] initWithWindowNibName:@"HarmonizerWindowController"]; [harmonizerWC window]; } - (IBAction)loadInstrumentEditor:(id)sender { instrumentEditorWC = [[InstrumentEditorWindowController alloc] initWithWindowNibName:@"InstrumentEditorWindowController"]; [instrumentEditorWC window]; } - (IBAction)loadRecordTest:(id)sender { recorsTestWC = [[RecordTestWindowController alloc] initWithWindowNibName:@"RecordTestWindowController"]; [recorsTestWC window]; } - (IBAction)loadSimpleTest1:(id)sender { simpleTest1WC = [[SimpleTest1WindowController alloc] initWithWindowNibName:@"SimpleTest1WindowController"]; [simpleTest1WC window]; } - (IBAction)loadSimpleTest2:(id)sender { simpleTest2WC = [[SimpleTest2WindowController alloc] initWithWindowNibName:@"SimpleTest2WindowController"]; [simpleTest2WC window]; } - (IBAction)loadTrappedGenerator:(id)sender { trappedWC = [[TrappedGeneratorWindowController alloc] initWithWindowNibName:@"TrappedGeneratorWindowController"]; [trappedWC window]; } @end csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/AudioFileTest/000077500000000000000000000000001321653344700253235ustar00rootroot00000000000000AudioFileTestWindowController.h000066400000000000000000000017331321653344700333560ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/AudioFileTest/* AudioFileTestWindowController.h: Copyright (C) 2014 Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import #import "BaseCsoundWindowController.h" @interface AudioFileTestWindowController : BaseCsoundWindowController @end AudioFileTestWindowController.m000066400000000000000000000035751321653344700333710ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/AudioFileTest/* AudioFileTestWindowController.m: Copyright (C) 2014 Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "AudioFileTestWindowController.h" @interface AudioFileTestWindowController () @property (strong) IBOutlet NSSlider *pitchSlider; @end @implementation AudioFileTestWindowController - (void)windowDidLoad { NSString *csdPath = [[NSBundle mainBundle] pathForResource:@"audiofiletest" ofType:@"csd"]; [self.csound addListener:self]; CsoundUI *csoundUI = [[CsoundUI alloc] initWithCsoundObj:self.csound]; [csoundUI addSlider:_pitchSlider forChannelName:@"pitch"]; [self.csound play:csdPath]; } - (IBAction)play:(NSButton *)sender { NSString *audioFilePath = [[NSBundle mainBundle] pathForResource:@"testAudioFile" ofType:@"aif"]; NSString *score = [NSString stringWithFormat:@"i1 0 1 \"%@\"", audioFilePath]; NSLog(@"Sending Score %@", score); [self.csound sendScore:score]; } #pragma mark CsoundObjListener - (void)csoundObjStarted:(CsoundObj *)csoundObj { NSLog(@"Csound Started"); } - (void)csoundObjCompleted:(CsoundObj *)csoundObj { NSLog(@"Csound Completed"); } @end AudioFileTestWindowController.xib000066400000000000000000000103561321653344700337120ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/AudioFileTest csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/AudioFileTest/audiofiletest.csd000066400000000000000000000007511321653344700306620ustar00rootroot00000000000000 -o dac -+rtmidi=null -+rtaudio=null -d -+msg_color=0 -M0 -m0 -i adc sr = 44100 ksmps = 256 nchnls = 2 0dbfs = 1 instr 1 S_file strget p4 ilen filelen S_file S_score sprintfk {{ i 2 0 %f "%s" }}, ilen, S_file scoreline S_score, 1 turnoff endin instr 2 kpitch chnget "pitch" aL, aR diskin2 p4, kpitch aL = aL aR = aR outs aL, aR endin f0 100000 csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/AudioFileTest/testAudioFile.aif000066400000000000000000076706161321653344700305740ustar00rootroot00000000000000FORMqAIFFCOMMI@DINST<MARKAPPLauFMSSNDq,                        !""#!       %*.36;<A B EEEDC@=961/*' #!"$)+/269<?@ AAA@!?'>,<1:5783:0:,;(;#:9740,' "         $&),-.-.----+*('$!  '#1*93B;IBNISOXU[Z]_`caeaf_f\fXdSaN]HXBS:M4G-A):$3,$  $+3:DKT\dlsy{}|{vrjd\SKA8/& $,18=ADFGGEB@<61)"   yywwvxz{~ $+08:=<;61,&yxpqlomrty| !%),/14452/,(#  !& .'5*>1F5N;VB]FeOkQr\y]heus~{{qpb~auSnOeE]=W8P-J+A:!0(    &$, )3-5.!0 (!%! !!   }xwsuswx{~{unf^VPJGDDDEHMR~Zxbsjitf[\W]Y]^eiqx!$(((''%%$# !%',058<?CHLQUY\] _^&`;^?_P\T]aYbXiUkOeIbDd<_5W,N$C;/"  ,9BMT[cfm qtqrn!i$e%_&Z&T&N%J$H#D"D C?????DGNRW[`bdh j$m)o-r2u8u<xAzE{H{JyKxHvFvAu=t8t3s*p#mgbZRK>3)  !(18?BGFGB;3*  !)49?@A=#9+22*7!;; <;83-&    !#%%   (/6=IQ]ajik ggda^\ \"Z#V"T"LI>8- )%&$##"# "(,149;; :840!)%&'('% # "0=L[hv(};CT^luy|oufqYgMc@X3P"GC >;722++&% #"&).269 <>ACGFJGJEB<5+y{{!1HTep{ !+,0}2q2k0[-U*H#C95 /+)%&',/6:@GJOOROPNLIA; -)'/5:=CDFEEA>:0+$  wj`RLC? ;=?!A$H-J/T2W5e8l9:<<?<=9:.71220 1 14 044474:7<6"=6 <483 4 44546440370020111//--..3599>>CCEHHFJGHHFB=61+&xhZM@7)% (0:ISbl{~ndXQLLQWakz $)//2.-)% +>Vj -8 @EEFA =6/# ~{z~yyoh{]aTCK"A70$}\ B* "(4;KU`nw(1# ti^MA5%&)-01323579;>@C@@DHKOV_ht"#&! o]}P>},wt qnpoqssoptpdjy{}y|~tojfc\XTQ|PkR[VHW9`)gh qv +7GThyo[E/ &Dc ! )+*$#,38AHP\jq{ #,<L]m{{rovfo[aNYEK9<+-  wumgb\[UYW^afnw}  znjegkx.Hk$29=; : ,$ f|mp^lUdIbH`E`H_O^P^[^^dljqx.CU\gjjh`[RsGZ)C-z`Lk=bBQ$NJJPS`+g9~Um$(27=GGUQfZwYl[jSaLS??3(#unyhpfjfeqiyg~qsx@BLXa ie g$a.\*X0R$K(G@7 -   #.$/$, -6GLUajqz !",+v+^*a*W&G*= &&&    %*(%#uxhn`iWaL]JYOZWadipw  3Lc~$2J[gw  wmmTRH:7 $ ~w{t=tJwkxx}\L!|iXM@v9m0`1Q.X6N6BJFWJrO~Vigbclt~}mYJ7+  '6F\t  +8>B;4%zhZSO PV&^3m>|IWj} +D^svnd]TJB;4/*(# ~ { v nd\R'G2=@6N2V)]!c.d7_:[:V=T:T8Q?NCFH=Q.T X[aihhkhffiihga]O@C>740-$ -$=#P*].l5u@{GQ]jtzoaTKAA<s<i6_2P/:336,=IZ j{  yus[e9P9! +;HKQ\ahqy&6HVbnvz&),09B|CiAUB;<3& oQ5{[IIHNYgy7Sn52VOve}!BU[jpv{i[OIFBEIR_l{/ARajpwtrl\M<(oL})b L3 z &=T_jqw{|~~p|esSgMQC72(}wldu\mVPS@PSR ONKFA;60* rdWF>x;u9b:UBUHPPEV5f>t5&% 6'H&V b o3/5[k  %*'2=<5EBQCM&Y+U Z]jr!"AZos^H, b>  &7%G-S=[;dRoqo~rppjf^UH?4-%"#%2<Tc~%<D[e+Gh)& !   sLg.U9%   3RDrecjh] A((C"_nh=kqNa5K 4 }ojignv{oY?$uqogfg{G,}z$5G_u  lH,6,NFh` %2IVtu  7M[vqY:~pf|VdEO9:'''Hj7_-@P\_\ L%9" v}]c@E'$0 L(hJf3Rn0Jcs~~rdL3yhT?|*Y7*<Na~*?W n rZ@*r[C,xdR;z+f%O;+ #.:EUi{uleZKpFT@>>'> )trpwsw"xEg"<Ufqxxx|3w9lBY1A-~ufIdB_&YY[dq.@(I>XQ_c}{&Znvxg}y|kYJ7*shVNNEHNShf0hBwSfs|!!0FP[WcfhwngcY]NWCL;G22+,'0!'268A=AGV\gv!0?=9PVV^K^f^l Y[[J? 9" rW8" !4G`l}Bg#,8@HBM<//i J3  u`E ; ;  (7K \o(0864",}jW?,g]5xka_amz $9Qtzjb}nyupfPF)'<LZ`^N;)\ .Rt eu7c[OQqWEamC51KK'i7SI[O=]I_%_d[[L-|L"}Pl`fdn.Fp;g B&<V @Y",&,(9 y[@& &Be)9Ql|zlbL8' ;Sl$>Wx;Pdw}{vM3|a8yZL7/q"=UigL[&H 4`IZee&nHjfYUJHLJS\0b?iCrA|2zU9:Vx~m^TR*G36720)&eM4""4Gaw|vL9!(;ITZ\sVbM]@[+YYJNdhzqxL`)`YUPt%DncM94.08A-o-'  # mY3[3 7M"a4u:6Yfmt,dQn~sfOF% |zxqh]OB0 3_~!1GxdIK3 !*<CN`m;Q L`cup\C&  ! 8J/aDzc'<C PHA 8(+  x[;$ zts{eb`VcYcGn@B5GNRcj-uKgnB;$+ ytI[+A*!}1m?aOQ\JoO}JJVHCJy-V! ~jN?7:-37?gNeA AFdv Jf;WmufW}Ek1ZA"5Q u-+353OV^i f ipvspxvv{xltXqFj9q*tjly t orj%m:|Qm!=T.hLnGqY{s\C>j?Wv3]1]9 Z0=$(> g!$\%TTRlJ\ +Oaiyi\tEb.nW.&` ImS~*EvvEYVl_s(sm R;8jCUEjjEZZ=|0[(6yM qU?#vlifip{hKKKH;052RN_cJZfT #'O/g9<<DA 7$/S`mbC!uhror =o $<an 0 ogD'vQgA,W"Y6 1S{#S~2_"_5H ch aaK+ `B(pX8 8*eKm$UBX~y=|^.y0Kz D>yX=/',?]N{q^6l|#d-K`fQf(f#K-~dHvBO{?b UOZD_}RRT  {eI1  8Ygz #9)JALR WOOOM?1&qnaMc&E } pggm} 1 cG`e|Et )11<94EBMPM[StMiHfE:f2a4},f![M7)4,wi[YPN$S:\E^NjoozAUfclt_f5a[VH?7o#a.P)91.+4BXq=Q\mx{(6+<L09<hT;!h|`vOy>8 !Acy00'0* qW >'{[D6"  (*9G[lzo%[A>Xlg<x{ ,] K6dd3pYMbM69+(oO5)@cpjsYAd~\* E*-G'm--$/_D(>>OQI2,R5,)f&wqq|b1= Qllr4a1*>MJ<%^Bwk\H`BC3,3 3 )C`-<HhXz7Xj{1Ud{yaAs2l.J7Rs "+4&B8TJfJT8.5.)(   sm J,8ADSA_)tJDo}zB9? !!!)Dbh/Mb)}zqqkz"4/))jO@( "Cm9Q3cl$9=4X$[ X1c]WB9h+"d!?TQ|BAf~~cd8E6rYr&5DGz7: eRkt^zk5zVbrXX.{ oZ8d<l; zwhdqUzIsOU\qAr)TE  tX3 h1aB) ! '!%$8Ni |]oM7q[H$?4<JEiUg =h*  .Mu'7:GSYl1rPy]scJ1pZ`5J A88;GjTKg8%% %%+z;A (ogZADtH+.Ji ,1aZ7,]Q|tl[_HR8F/& )Hk&U " _  Dy (Ee{nkkiNGA-h{xx[hxUwEhB~EkB;ODhT{75Uo}tq]pmZ}@}&c -@3Gssz:Y,zvBskpj`Y/SiVsy v6` )ZPVc3pj]O-)V"rrlYHEEB;BHBXyiuK- t * TDWj;x G^_vf? 0Di7+01'kN3--0=Jh ,I`z~]}J_"BoAxg= mC"r:1 zpj`O}?}2w(FB5.;88cfRm?Ys '1#s}\O;zX-T/tW9%+P(FcQA8HcN\`OJ:}RD wWX3M kI!0 -V&*1#lCz} %%6966963,}JX@x];gEAq4H ) %G{m_NKNjX_<69~XQJ@L(gyZ1qO=%Xf/$/gCZlVdu:V9qt,`_Y\(KNJX2_X\D(qcu>[' Fehzeaehv4Ih4aH,uLk|V-o'L#;3?)?)J0N:QLNk\mj -BejKD-%LekeSA;)"iQ.a03wV^F; 1?&{*&1#_# (%( ~i^{IXL[IXIFIFLFIFOFLJLFOJOJVfZxelvzx\1ykk`=YRNHqD5DDDDGDxK{Gt@m5m'~ wtB vK+ Y95.Q| =o "I1iF_|*9 528K<h@}@JY`u*58%<[@<@8598~99< DN@YNds~ 6=LaptbW=3$ uFX8wex]uOBHHK KOZaewiSZZD66/9/ 9E^e*9@d@p@w*llZ^##*.+25.2#tq=$iq I yn:/>>ILE>/qA$}EtG.+ Ecy1ou=_xB(!PnX7 p mitxb97oqL5QTIrzvoXJ!")-Q434,%%]GC0-VC] sow   +:Lg!%(Y;]h{XMMQ/wl YC;4( ;\CJ]s!l'3 :$+ a?pG00!rT=#%)!8?4ZrxLa.K"mm| &-<O^xqeVG0 iO88-")-11-<-@)O4V1b)q00-)-! !4G^usX`A *=Py}ynf[7L;<7-73 mx|5b+Dlu)5LDf5"9\M~sXI`coX"Hg:~MTdsos`X\="oP-mRiqx -1kET\c1ogz4RbnyfG, 4Ok%zD_~!Hff!DcooP\5oQ2\6M=6.#xdlt'Q6&3YpdEA"-P&#Mx:G r,8,evWx4"v(u:t\E5)pt Wwid`t-lP5tthp|#26:6!.Dcw#7;^V}^fn rGrrvySvrfbZJ;+s8@KvN3 +K^jfVK_rrj"_6WBORG^?ZJ2r[VC>;6GF_Zeu6W?&Nb=amqRieVB2g"WGGgWC{/+' ?wGKgs3Sk` O(HD@H8H4D,<,4($ y]l10x8pP8,`4wwxdD/0 D\lx||\|7tdK+VA%mM[)3s?6tNTZ?^7f?rSw QPyy"J}kuyy`uwsk3kGg[^cNW>S&W[[gk1fJfok{ M} 5AE=515-(!-AZ~%r>,k)Rl?os)BnUM0 = l*4UnBfc9cke#Vp\KwKwOo[jxsV#mP$w=n8q']/Pu/]y  rM~Y0{fQQ$EANVk)cW:Wk:pdpWG>6a7u|?t l`hlG2" +T|_>cZ5(u/~ecT)C+sAwV4$0INZsoR9$d2qG2`5c<Y n{%9N[>+yf-l']{dfUa]-7 nL;H;U]nn\-lL~.ieT~7PGu%\7h}o_MOA[@tUt{5? 2.e`''',m#B%qXX-KBK\ChGh2h&l2l\uyqdddcdd d'l^6e]z1msYpOzrC,UW Bd}#7NY{ Z'p]+. Kx6X#Of4 K>{o#O 4oOGKBXrnT4,64YK}j|naaw}M |ajFeO=0+0=X'>#f]3*lR__R@.![fo0diJAAX8'/3W"S(w>T&@[rkCCo 9fsd@x]:.Q$ :GCLg(Qcp~6uM^H?- PL QbUL5#(PCZp~)2@D<L.yI#G.T7GA,<NWw< ^PlwUR6.%yE^rB>P^kZ=1c '"BLV aKZPCy:yGy^pulu+aD vT'" &#1BDoQ_qvJzxqdVD(_j)3s.A )nn)nw@:q6$_I)A@]daX8v7_DRWzb?hz$-]M{ g2 6ME;$Es8O]^TK!W|`@nsR)i: @eMwRCh><otVK,c`@.` 2.E`E1{M,_>_rvhV{6_6\W))XX. 7N%XAffjaN2~4T yA6Of% 7 }!t2f yO.)XXA3a%Fk "00>d5&+'"''+m,H'~F~~tkoxuJ3 xoS)Yad0DI6C u@;R2}y3za b) #fufk^~36? FKv8 K8^P^YFP  gY:r[|>>!Gw>+ PA ofaWIt\Ouwc= mZG=8/*%  )..y3oAjU\^eh\hamo}%=&Y9^/l!{TF./CnX)=d^h YKUmKF88=K^mmr8s!pJd#=##i&g6(;JIb1]zf&NQxXa }[>9joaaRoo,y&V9414a!-o-H]wiRQGdRKb]>gM~.+ayjW2#7JLTYh^JEHFe+:`xQjL[`QsQj+pIB|P_ .#(#pD& n_9C+DWRWWFMw+d `4223<Lxe/K k0 MtyWW0:0]I]"#?7IDI]mcYYcr,Nlc wS<J,Y^OZw<A5-O@z0Y,~'~,oj}W5C5:9aO'  ' ~,"@ 3L[W9#c5@) N0}30)<U5inn{IkNn+W 00+pCi\WR0w %a*HYaz< 6;TA?6 W]!TkR4v]W4\f hYwX!IS?]q5T J;1ZT3Lt`et3B2Q.fza8z3G(Ai^XY! e0jXJz(g<[n>F ;TY,F0~.F,5gzRRk0 e(49dx it4{X7ZdttZvK*7<d dPe[wJLjOPP;xS5cr(hVT[:Uz-[2^h&c0 %INxr /3DfNul-QGQQGG-(w(X[*= ]fBg]XgRR (G|{QR)CWIcchcYvDM* pB]$Mp3u[F1,""~MvG:h3^ M\ZHUe|KgKb1q&JBqk@&3Y|3V =&7$+}x01+ @Ak3AG2h?4DvhgaFV`zh\b-qM\vl=|B\>b.yZi!__ZiHw+i.]Or$YxY*$Ty~m_>;t~iTT?/%Inc4>Xx/YsX>N}y?w  P^4;8:((p8InX5UQe+ +Ku_p~Dzj%sO @ {MMs*Bk{;2 0lAzI#|alQKaHqjJ_(Y] @F|(%N99R3//a|wlr+HY;{Y8^8tFEv_4y!4zm >0d1uz_Ii pT|O:)eK kt@Ffqg+gWLxAg +L}}}wbAF6~bXXA,x+U u7TLm]XB&&A\g+wq4YHHNtpk`UOJ99>0DrT#o*m6Jp|J{]AA]QbrT*Cr0<x)lDEJ*D4Wi7|/&2tSM,!K!Bcn[$K[v8j_TIl[P4[x~WM6 0Fxs:vQnb$U5:q@\s;0ByBq 9k>"|?.#9IOOv_vpUJUv{(Bou_!>2M&uYTd{X"uT-z!7c ,N-AUqB| q`>I#{C4#d,-Y2Huhh0&d6]hy2BBN&N2NzSN=T^{mugggmE}aU?), ,2Hp"Dq)X]h2*"v!yBJ^z\jH |KA,Y}E#, cT/:AEg4"aD}9rUPf fl]l[P4|nF = Zq~ZT`+e|<1zT=5+&7K'<`*n&Nk#vsp_I!'2Z|Uk8`-O-m)b: 'O.DP|ag"9fV!OqxElw9U lwO- ~aD"9x)Wwf=oz0GnQ\/[[Nixm4AjDl`@)tpD9z]LwZ 7{ZRk|vwN7^AwxDVR>wCFo&IkX>~g*BM~J k"e7  ,Zj>YxNBB1==BC_sTJkC&N~[?3@+M Ai9s2O%kw}q`C+`H Y}ANb1B-NYk'xBm (G^ uuuj^^0A LXL;); XFR5A:)uoi\5:M6)<RXRdA:/X?jGQnK{EQtX4tE "ei4,IUO2g a\ZVDjVyK:c8.S+e7~SEIbWz 24cL6@T#lf=AP%z16%kVKot(6}+R~jI/U:[=uY)D*!AVGGe"{ s"N q<r7'\ X85efC\\! I&gw?RI-dU?8/\5a5n;\/&O9t@ z=8 39/o4p:ju ''V8s&y&sOIrTC%5G^|$S0k6|ekkBkr^kSkY~^qqZw<_| icv||e/Gv5wwYMSS_)k%+=++?t oDUY+n@`MxVDtni"X|ua_..VV@A vC.k4nO7s%a%[1=a(j.j:/f0'-p- ^A.*(KTz-~L_WWu@ r 9S'`|Dc:Oasum7|F]fX H]!H;1#U>W??VW[o`_Y.eWD<7  T-K mVE(xBX&}u@3R]i8, KocUU N<y$m* %y %Pz7n\$>UlnS744:k#SGxk`=rmmbsDuujuE{IKnoy[/lH5Ml)ZAfz$HaH60] fA.  v3(GqONHt?w%iweXF9F]K9}a}}m)NaQf&f f2p*=51 .'_ V=\Pci7vP%x(h~~5rrlul=l`M.wXRb9&&y9AK(^"j("C`z*=l1A\z).U:r!ryf g \s1`G85""5AA`svn< GZSsaZAhZgBH$Yi`Js-y'Z.4SYl`!L4!F-k_ Xw& 2Ed%WQww?vpX2^E_y''M~lxey:fT;!yyM:E.&!pW8xY >W>w Q% 8%^8dj@l-y:Y/y6fnF%DAl8cxa {)X9rkT,qP(~H>dz1ml>$i4Tz!s:gZG`(j>g{nn,~_q~RKXRC?\?o?9iCU)l3d 8hI<) bO66cx%!Ggsm`Y@ Ml9n rnn6gA:3ZZaA]-o{[T;4.TmE0UG8j%eN+}evJUI}kP8%r2[nHB5naU.;5Z!.TLl ? yYFLS fS,zztEtz,LB <-Vmii\<T&|c5s@[ZG_s,+&R,rf![Sfz]zsfSppd ~wk; ?sYS"SYQY_&,339lF9FWZ@'5R,lV5 zL < y lv/Lil `S]z F>yuO;..Q.4a4HN=h [[ABjP0pf%Sm|H(<] :u yG@I-Mz`$gtg1g+=d~GE [ %T??w_l$LgLfR=?y a%?_d7 JQc:;+Fl/xNj }  4+ |f    s O9  dhhd'cyyb)D8>zs` JK Q=q=/Ad/ ~/~uPA< q"(c!}cpjjI<N<(4u5\v!!vIjwpN!c|h[@H3-3|3&,&z *xtJfzS xb}NS ]c4Qx=`h_A=_{`mR#1z/)k']bGoP|, @>m$nPja8'B\c&BVwx jc-]]dx;II't'_.K'X5K.Ro?)Y|`7 Lma Fs& 7a&PWZyCT`$\h#VxH~F>7+S_5Z t''Wu Zj ;BeYP"7  )L)7 )'wY`S`eb){/YKK4 of^X6{)[|jrN9tBh}]ZVD ## 7Faioo+4lG>  I>^w[ Jm;BnQgfD@tu.u<?q#*QlmfFD]l] o}v|z4".~mJd2rFM*)SVgX#WzCY8?~- u|D Azxx_.=KK`ni8MM#uugX4u,ggCp<t`,zbT>=`|5}E BV,s =bx%C6mQ(C5.whoKRh<?{pB1%l ?x3i+:1:9*]%]yy*xN\yrx\*M1#T8"jxoU}jqj/Y(Sx"MiG8 1qkN9G@:T0B'u 70  "(a0!-O<\& \  bK((bZZ@@U.%qYY\L^y\UB*\w!bPQ $UxI1<"VD2~+priaZ&SuE/"G4MkG#4k -J),0H }vohU<lr]HHo559*7j,l $2o=U)H)lFq(wJN* vE+,W]/4nJ;B;4i;,]Lb dz]mEfmy@|B)8Fo8&?"qH g4-Y/9c)?q'o E*vHGkL`_uWHMkDF18Ud80 @+}nZ>\@z*VOh&O~~#V&#osH" 1OOVO8@le++{t9m+e+Hv`uYYQ{Q:n;;B}vX:4^H+,#XH2m_:3JQ<w$ W6Sq;<c'TM yUbm/I&Y  C  WT I{Q /'YY$n:0}#m1+.8zWp(Y{=]f]Wp!>V>omk00a2rg3T"+P=_ nu&aFqD]?X5=S*fNJ Zni2W8^=u^P9# [/,\ }Q k0Q!Fo+{CeV^stVle^G8`"+ 3Bhu4!zM_!5l3 `}B,$hPX~vUXJRXyX"0]'Qb LQBVauOUJ*M- `rE /P(/>hcC--YCRSq@]~8q'.[{0n#&AW"es{?{]*@IYHvk'wlM8GP9 oBB#B~XJ`~XXvH2**#}"8^u7V7TF/i3c'R+aBRZ,Z  i&rTzS'-T4'.bqb=w.}*m1Shl\> "m 5js&M]U}Cii4{j Fg 8O^^H1{0$Tut7 (M{n~C%Zq4x<4}#,G_j(hSPBA~PCi l@C}x,:LL<r,n c&EIQ:#Ba2~=j? e/VeO]78cA*ENS+-S|yMUG]&d?utuE/|76tN{sse]Ml{dt77Eul}}={dm/7u{=!0)zS4,4;KZyn0e.tU S <FF >F$V^ONNz/v6R f@6mr*ae&eQ!j _!)CAHPH.HFPv0( +<<Sr{Gj{k,C 9O{[+)}OTA/G}__ 5:@U_qL (GvWOg?''.Gn5\dBb[b[S]fj+:Rz&:_"BCbJZMWW@'/77gO~]%4>mp<dg]LCdZ-OENw=A\RD{s\"*Z]r vFNA&aqNv&fq9!'qGy7wIa !HpyH91`1HY_a/x8P0!O8/ On'//6/7//^%&]~5e%5 f%--M}N^7%VP~Gx X"?Qc=\=&7./7'?'~v-V<UCS y1##\`|/6eph?07f0'\' 7':/M[7 pa @hf&ySy`papyuF$ "Rk=sm{_[2r$]62J-_$[""`@H7P~E( z :X*y2c+|F&!"]S  .6W]foW63_h D(fH.Cow^jg!gn>:ZjzQI1j(v n@HDp' 2K|W.d>x}-2S kaRh<Q qv-vY$s,{p=@vY=*Mfv ~W{1eA`z&%4c)Bu#8Naj~.0MC?MxO+m!YRAYFUqb\eF`.Xhxxih``---P--$Y^z4b ]d+C+ }CSu\J2kRkJASl(lj1s9Lm!J"A\JR t9tZRI@a?ryRXRxs17_p&( K & 6 p e diZ`:,4$H)Z8{/q4TJB//UW)wHgNN5%Ng^hr.HXm%aQ|;nJH|wt!/)SWl SM4WqSt|Ss.U%9(+;"v'-F}RXaDu c{ji$i$d}Bo?I#;0qBcN(,8tJc=O%A%4/#jJ|A^54$J [Y 8S< H@THX'.miS!]HBGC." =wL l > zr P 6 a. P% /- > y U&u;EZNn*{XB!p|FsQNS~T & N = t )0 T A s 5 @ u  e  c 8 vW3@$LnqPk&"!WIswkO@5^.rZk(IbW G=_ *B"QDWU!DHW=Yw7 \Jd! Gzs $ r ] r P }%@$8dBYAm G CLCCS{dRKeAy?aaO.yz!$n_[2[eSvL\((=1)G)-1d~a6  1l` h(S \Vl~=~2!22KTTTT!L!e!ULL4onL3<f""^3^C_Lx <E%^^L 7" j   2 tK I 8 8 1 AB A~ S l) u~ ~ K !  U 2 <  M NyLv Oa|a/H5{.x6]};@<{-1tIg<<93R#}\"U";Uw2*"*#g M~;xQQ5]QWm%V  r]  9q d   E   (  n C  I [ ]   . F ip i ` XC -  c 8  & @ Q t r O   l Jx 3  d  { |  x: Hepe|#s fV[ \GM/])kuY_HHpDj)ufc[n8T@@[aIc}-^3t g3G"s2MSaC"y$@(".Db.k!3D<*"fIg^lqE+<m8OERo.bq +lQ@?p(3czhhpV!|/k6ho:9[>8#VOi+Q0%Ax<' W Nsh(mjV0[ + f  :d f > w o ;1 o a~.;R}X= ABmS'G0!Jer; H }  `   ( /d kgz 'I:_ou  W  d|  PH_O$.v'WL z^c)U"EYc'9o]_|y ;Q) Dpe=Rp.w_I *{,;xKR( z13T TT w7e9t   Z  2 ,x  G ]Y-$$ Ldg/  q n (  ]< g Y M Q_.*$Wl"X|}G- $?>jP-,55OGa{"p3bP#xxf9 ksd[Rrmr =Oc{8mk'`?Ql'~nmB fhr Y  * V z %  q W 4 Q . tW6  $mcm '@  . gI [ v E  e    { 4 n 3 &-,O$A8?.jyB-rlRwR?8j+_ Ox\T97ZTwn%AZ  [aUfF>&sCdy3,~|B/l(gOy|18vnRe)q)2;PWT rE] It|<ef Puz{0mYjI*'0>}TP111}u5yU}-< 8p:09]x6l}!_LGx(+#j&4e\ERi{.{2h;!#d}@T  @c:6~hG.:m?V~ O    K K x T 1   O  c   ; ~1f_XL\AF8"An#kdhLImS&aYPPPa]|<!N{fc h{%jhBQ)/wYa!{gA=Hv3<iis+sa 4qG+FjrK  )RE)P ME{lj!a p *    'y ^ N   Sl - 5  - Q [  x \ BZ  2  u~l&lzZ-^;9EQ^q{DsR41*|q0Kp?@l>?!z=O'FyF3"+3fOFxXKKfTipLg]t+BKK_]/fhL% $   6i d* d m [= S S    JYpP4hM~vs8BPypL' c9]>#T~/l\f\J88//?8JQ\/[Sv SeSS\wwIIe%SoS-S6--8$%o.ck"%4[tY#R\e$$dn7GaR*?j>I?ch 7v[06[ 1% ;\ 1\ )] f ] S )f o oxqVxD]2S88JfLJx>px1Md`Rjh:I g99]/N/d?0mv \f_&CqoL<?K`;ux_tH'zhEb2}tjbOyXgO&4!m<#!!4FsOibs~aD 8ZV$AoI6@]q Pku1 u7:_."Zp.ue{Mm-HL+"pZtK@oEokT%O^m5|`|eD r:\;+U19L~+oa@ %*b8 UJpgU49<*5]^tujZjbU$?fN oO t b  V q q _ ( . >p =% SKoF 3 "B3F.p~PYG* /// }S3%"b*^^KIpGhhSq4hL E,=fnnm) B )   C t-)d2aW`Zj^"?EkBJ7mltr5A\A, "LAke ht}lx+#=z"/]M=,q2QXX_p%..7/^a*|0H{i|irT9>.R#P>FjT"PruBSC ? n{ o f - qr _ XDYbE[)H73TlbAWpj  ( N : Xb+Qxg]jKW`DNtk)XukFk!EZ*tt~ nc19GFD0jhjso-EO>d+=3!!\!=#y#nqB{ sE-]FzKah)qh_A%//= "%hM_q+f %h 2a  Gm  T R o s Gmw/w8PVB 0 0  }  B - >EhLBqK8.D5o5taaDh: HR6-~1M1QM!Pt/`t*]N~^v|@PV!Sz}1W}+x.ax&-z D t b mb ^u Ek\uE6_F  ?0 k zg  bT|<QQbZOYv^8bqOsLR0! n0\ e"M\X#>E&`  U    ~ a 6D f0 : W   S U -c 7 . ^   4   7z{% U ` j \} }M &+}d^*EKvfC )   E fX UK?Bj9(CRa&v!83c|floBL]'*"V(sD}j]ZADdKxtgnvKQok ^D~n%&^~T  IR   % G nh n   /  R  ; + % r  D@gqq h+7U  1S d g  U# % lI,tO4z.j6/;wK;*G4Q1VTx4Rr,BLMX'Z)DBe*fG3 { 6 ` t &r - NVd tW{M"M~rK#877hKr6SS\4<6:b-9k/_7L"qNc!+;+?R'NuyfR&5W!Lg7",}\W>D u*~L\+^,q+5RHp\p>eo ZoYd1Y 9xC/9J&|&X)>j.fi!7^{J,@^]qi3>HgS@h/@j]{y]e6<'C~S~t&{X0}t :b/wP_)#x/B^Gg*\ >pv5  / ~ + R f    $  4 Q x  8 U3 _Z }w  T r N  | A $b 1 :YmZ[<HP@mPmo5wZ` 0Gpf%yYpH@2KD%"KG,!v0o86G^ @5p)*; k  ) Z wx<daF) [(+wSK , #} $ C DEFMQ9?]hsMW~j`M49R{hk'LwQEd6|7VkNlO=;FvluW_rE5 >eoGe'<:DNkN'C_d^Fg e)w:&so7*p\[+P; '   U#  i " jfNpH- 8 W  ^  / :[;FH>5]"^`#D_mdm._ A11] Fx \AW/tDLd-FK3>!$&:Ono"ghps [jC9)`dN6fv:&t]+iP%L.@wc D     ~jM~C_C/@Xg>#_~yl\5? f Wy Df;\PR5+gVqM{{ 3 :Qn(%7Lrg+<m2@cH '* D X u  ! u Ng ";S)yG*w(? u , j  % M .    R; eK,^V..MN~tj`d)>i7p+"\q)b|^A#AqxPVEv/ 0 D X 'P;eZ od )Z~;l )u E<2G k H 9 t r  8    $ 8F U }4   h6 h S }p8e& 2E3 Q4cP ,o  d (Of'9~B\JAVh~vS?Q[ ShB^+B}lg X! Z 2  & 9 9 &K   NG  jv2hw GR  `g $6  r  5h-=i%teGD* '1Xp5 I/  #` 8W `` tlW3WC/TwX4w &GH'59 Ax<5o:ZCVm>--+T^Sr"]{-r??,R!!55x5<\@ +ZY 0 k D  a X a  0 c ExP+{ TAVBBjsbT)*HHw{2| X  } _ B L UC 8 B X C cf,"TdtG?SDh$~'tC85XojiZT@Gw RowvC#6]{+>5PXQjZ':Y 'b D N D A' q Zf3Q x3oZQ>e*>\ * 4  . M NYx *QKZ}bM9CW9VCW`C9Ahru|  e,]gS,Ax\}~L9~ 2;C~CBKqM+p-6 g HJg6^7A|^A]_y[jFWu~7F    t 9 [e4 k 6u ^N B /FmdPm3FP`dNwddwmwbN&`9WWC`bN+3,A.QpxH@-#B`_O~``t}A~i5? HynuQm}bK/h%]"\{+ QE  a  M   _   } } s i } _ U ] $5   d C v aaY//m`j`eQto9Gekxx[=?? 6  K O ]!X63T }9Lu: ' v2'N M8ZKQr\|Ts^ThXKAE7A]v>3N.r@4N( a C  #1  7y*3 k  W0 X a ~ `  D c2F)GG y  e I "3  ( T  N t  0 }c  -G   s    < }! @ Mr / Hlqd*yX7 C?XqSS":u|M~_%_jNT|F6J@q^q9!*x2<x*NM >.sd#r:&[5GZu&76RC?t6%j.i m#o] ] Xh @VVic.XtLAM:Z$>C:\( J T $ G]{![| A~}s^%"juMx3dvq D`  j . h 6 q Hg5G*FB!'Dk$M!_8i-.t3lE   9G  ^ " T  . tP Y<B4|]yRq@]-"sxf 6   }dW[f{kbN91HqmZPPmwwdZPZ<33)Pw\u&}A??[4lkj l  k uE kb Dt  x</(._<}s*]#KN fpJBjO"^(%~x:#PB/1e34*p -.\5B#?RJpy w [D XD1lXZC[}, xP <M^_p AT^NK#VTWJ@J"S.qW+ZHfGR{q?Q*oZF'Os 7 N k{ 5 9 d ' $ ._ B L L i5    #l ^ D  " @ qo d {E q0 S  I} "A   K y i  9 R34"!KU9:Q @ A m'JZW4yS#8RW?!n4Jh#_Lt~96b7D:M Dj_WjqIVthV-""!FG)CPd^2[ 3't%#K"+SR * s 7  XpoiF|ZmZF"o q 6 ^  ^ t-  a^Y(@{\4<Fm>!{ cBtu kw p W] T i t U  <   7 r < 6 c ?DC=xs1kBUtkz(+<q3@ K:/88Tg/ 0v7F ( :x MQ 8 p , ] ! AR    p2RRH5 } M ' " y 6  | r N   I ? \xq)6)|#}_L . 6 A .t k5d=  ]! ! A U M]  k Y d", J+pheBkDLQ{"Q}Z~0 'l k 9 ~  2 Y v 7 h N  M ] V5pTJf\ g > # )  ~ ' u;ZMHB_ssM}}}!s@|V&-^O)SxR+f6K }>.[[GC  bD'yR?v1!H/RpB|Hyf+gJp}xw&Nb`%JLrO ip.J`hiM}ts.#V^__6{5 #K<TKc#9BLk^{oyp 3SX6"7H|hhK -  X8UUL88$B/sX^1S=4 S r   } B  @ t ?  vG GZR6Xw H5b"[rK7AK ^,OS]gk]]C@s-7}r.t&@bDP [ }Nuu*d  `  _ f ])\  Z    p +  @ 8 `7 u}MP'*dp)+  P+H\ypH+,Ns`jrBZ<] K -,)PoDwZs<LCxOQ yQ]FJMf*}#&Vg+\:o#<mw Pm F `)  }  # ^3 |<         d P @< {F d w+f=[)xx>x]e4R e { R K{ " 8 A 0OwKXf5J-:L hV`EB}^26N5~% |3Y5 ~[L-.%%2L k | / ` (  8 iT [ |  {qp*(e o  Q 8   A+ r | , | U   :  I q  !HSG/u3F)G? T " 7 BWe5@w>mQ5"7*_P c|Z,E{'+D+N?NfD0:'> PD ' N   /X ` ~ ~ ~ t t t j C " H Q )  O  u u k uE a :3 oO  h B / !]*#pW|miLG%?LsqS76^^^AA#}BtCd!JbN0jcE'2DY8N@joK:W<Xj~98}-KT\|A}k(h#> L~xZcQ0GGxqFRw>`Z3-q5\ypfR\RGH RRpp5GP + p } ^Q I? )Z1'b;Mtj ` |W C  |uXWmuPD<) 'Nu3kF'w(1D'Wd'3 A|ZMSDkCWtr~j{`t ZOj '9  9  b .' ^3  @\ g " HVfjXp'R "0 u T  W j V >R{T"Wg5?Qy4xff5FF<,37 s` )D)mn b>+t@.h-K6q-H52` 0  g  N> FDk  : N X D 0kuXDD Db 5~gi@^gh-4dsl% :    9 j    9 j' M 9 / / Cf W `] t 7  / $ L & ~ # K r hA Ar | MK uiW/^.&jp}@#T"GH!*J t|-TK-"6i|/7l^k@pQ*nZ/w6wmPZ)Bo>Q\    A"  gA RtwG4 df ?Oq0J:XNA1. `e 0 Y d)o/eb[QQ[R[o^tZ O240^_:^dq[>>> x3Yxshg p j s h S?Pq?k/3^[R!  G K }P  Y>p   %WvY<;>fqwPA) C  3e \qG -%~`Mt8\HT5G3 q"K*i mCNj i*\Je;t X b ` c  A ) ?>xFRFH)\ *[  | ' } ~ L M u+Y[ m5guj8B:-A^|B|hNA#OA|wgdZ5n dnwmdwO 0 l & jM | jJ M / > 01w9.fT7}6/5me*o?g[r*s~f!;@e7?}8@jhb}V8.3BseG#*"p\4S--8SM%Kq 9 K 8 +T4[o4e4Zf  q _ ^  8    's_2LiP #|JQ?Hp6.Mb\+xShDA3B*pj5/!+feM<;B_:iLC~C.iX P !,sV-Li_}$Arq8}yhQ"R1>9~dVNMT8r-],Sp{o<HEYQY)dm(p|m9<oS\86M78uk~kXX1bu) pg&_0X'  S'Xh-!,[6SPq1!p}>hHN3 :|  @-SPfO :'    -  I f  I4 o  }  & 2G)FqF3<_):P GyR { ] En* \T,N2u)D4'fX|MsLKjW@99pC`Y's-%?.%x sBr{HH Pbj X  $* Z  ^  I RG4o(x  0 :H D : D K '   j l<EeVD2l4 D p  M " B   Md X?P"x^##-7/KkT^T 7p]hAr{!}dc:}siL.{5 tujC`WMM@WCfjd 8EV}}} '} N 9 A  8q U ip s } i i i } _ 8  j  ;  M   K   @& g' g3 IG "p r  C yGg|]#T8.`9dGM~}.`-JP(M~q\QF1|C,0YP; 4 k \ jH \ f U Q  7d T ^ ^b K  i g H > F NM LA@ y  S ] ] rS ,J JJ]xJ" <FPhos\ : #d L ~ !gFAH_LJB8TV$88CB8.18BdBBVBL?V6T"5@] {[)mD5R&f.fi\Hsi]},s_VsA|@h]^ApQxsL8QR6|$B%s9#:PS*SxTFD8/.~9#hD@lq Re*4Q*xZwvO j u C p BG } `   A  LJ  M! yEP>G5, )3PP 3!+{D-(`;Y/M^,qpQ`.?GP!M,Ks!DQ[P!;" : K 9 L }. ^ ] Lfis4 -d|J1c!levY<Gx4? "H  # } q /S u6>hR7{#K|qr8&,@S4q?{{qg{s/\*3&D`WV_KS!R~fXF [Gx5<(qgNV? pG [[xk/irP! x d''E'' :X W /  -  {^*]Zqc5N/ M*`*jM%fRX5O@*R I# K BB 9 0j('FQ'>mGQ [yeSA8kE[!q P-XCM_:A |hXAW8sAiVq858Ls3b~A|,v6 :S   B  T5 R @y y[\?S(TBX& mX@KYVM02 F Q f vh<ANg!R4o5 <7w lM:X'8 |D6N/wu~L-o{dYy D /e  7n  "E I S @ ,:   C , ] 7+]RRfGyyfHC? r ],   [   / u  k   M t j M Cm &[ f N.kE Em<Fx?oQ64hi\BSL}7%,fk<H J~^8,Cf '>~B6r%6e Ev 0 W B ( Al | : C A} 7 s j l-E]( :jPepep<S A C  }~  D 6 +4*Sd;C0k::'''v0(DkP[C~ I | } r 0Ymof]>7xFwWtYsw^]e RQ3;Z~VAe@HQRP,|-vV :  M .  -' w ]) x?>\ GxqJ6""GT? i $   / :;3~ j&uYZdiwkO;3'o& Bph?G)X5\j *TQwY|rb-LL.]?TMpxDd,^d<_LoLG Tp?,JSqg#]].@,/ oHh6-TsLL8.W89_&A9`]Bs-qgS]pq DHCM C 94&QQQNeP A/~XEFEe "(;OiB'LN_u#jB5KF@?/*oshP{?X4CeCxkFNXD1X~t#BSAS4H3Qxo43xpy@,8|AM:iwZZZPWwCw&1kb1&C3`WxMMM!9&W: ;P)Z'b/bj8}A#Ty>rh7D}` P@C_V`AJNX5k*9dYL D K  C  " J ] LS U6 i _ . K ~  i 'B28 VQS"t:+>\ 'B M X /O WP jG WH &6 T XWcWB^q 4(Edvc'luY(&Mje@BTLW:h q}oM3'3GyqJf*^lii-|c";;?;2G;EdYOcE(CFxV }qT&-bT[@HfJmA1Bt& a/ &~ s8 i A | | K i V t. EMk'TtDuj/T~}GTk,@_,||@gsXwxpqT8!3[J6Ah-sKiiJ_VsQ v'}}7_{W\uG "|5W@#2[/+q@MsK@\"g`Q@  $ B- rS qR?>GwkQ/9H/ /   C Ct EsZfQFO N Md B 7;  ? u  e / C C   X=\   , s | K  { ij $ Z W K . XO(  frQ 'w 1W4RS52Dj4Z{],hZj  Y P _ A "<  0jYK Xu,SuJX]{Y<  5 H H R\m\G?5?,HKfskZ>eo43Py?gK9bv'wN[?k;5bq'-m}4KRzow{ShtBB}9#hk'q> D%TjFi  sS +fx[` 8$Q %p\ff f p p \yy4@ rG-x3m1/}%8~#rPe6]?\fff?#Bq`7OiZ /13;k DkgH4C}|q@RP QV 3]Z5wO 0   m Z dpdGZ FFvPddmwwimd<*.597Esw " 75 .S /^ 's(3Q\g)oR{>JH]r,{HQ)N)<FZP<eZE '  ]  - } 5M=Feyge|=rp6 g "q { ] U T (B<Q&R]TV2~wQoG5 @*G|x7LFnj92lk' bE&~).eAS{,y*oFqDpMPDVBrq!fLMGo:xdyqJi@-Jgxm?Oy : - p S+ !,5+r  6$ #& s ln +@r93@?f"h  !f,+r$j``~Ap>\>3 u&%}-AgR|pM!")e-8JM}D~oWW+`K_L#t9{HGuxbkbu[> WLq 4?e>w9d'K9R.<L  # T ~  Bq  R  G    F id $w Z < &  u xOoxdo\>"h\S|X pwP,)KTF]DR[d WjX}7\X98oVF}(  # sA K^ ^ ||hKQ# A+^ |    & 'T#umx8htj.t~~j~B}#B!i>3T ^uA-#`~_B~CMuuuMMLs7A6,\5y;;E(\{Z |L4p5d4@7"|sAL%%8Vi}AAh||rT#V%}B~CW/k:Z&<~33iP@'u|Xqp[)P u  > L  } _T $ `& u  ;Z <x fPq27}W9TNyZ GHDq`iTTV@]gq9S6"b"0 J++5!+v?55?\pyf\fR+]'}WW}7' H4pkq86TA|B~/|^777k-bAh/].\h[+m   m & D  B L/ U~ B $. s  M  a(f}@__|s#i}7ii}RZv X .  C t/ D ) M\  " ai~fk:TCP*:NXr_u&& dGH9`?V rd?Y'd&jV$q_+^<, ! t[ u 9 I H [xwO 0 < < ) 7  6G  5 { 6       j  :ZFQ?!]hhi}`tXP\A&DlXenF<4PwZ2v&LbM Z.}BThh A-{5}i_iiEs j i# h ^  q, S5{=?y 4Qe[ QQ54   T * GExd+FmK:L&W_&q Qeo[:*y!H]h/k +S,#88jC/Mjjjt$S5 65 [|6o[*XjH5}?HH"\y?[m ev ud C  9   % L s  j  B k `;dd4p 53mD]}@h,]? |E- :s   M/ N . $  + JlK4s_#.$sB...$`/t91wX oRvcYTYvj0NE.r";cp 'W1.qHAJw'!jG wqE?   > j  U< m - |  ( ,; IE I( ,  < K  R `{ 4H)][|69# Bxt>W/0yEH5)Jo*|\W?!Gp#iR&Xxu `b}t%4m Kd N  r   OQe :e u=     9 j  4 o . } 3 #d   { y [<Z pm {P   Q H  f J  wGf]r`}1Ff:q<#./,1Ki2~nP: ;3d'WchSkH&e9 y;uRxq!}xA )3  GGQ>**4 4e*m4>4O>QxOZe>  56A%o><+f]6h^}X}}Fe*^R"S{6?f^-4GeL`3&w bkW2BK6\[d`. D t  s  # #  R }   Z  ' EloRA    0i :8 D 0 ' '/ k lZ2m[!!@AhL.MkZ[kX\00S'D^Xu8u(9t[HBq-|-,@"#@hqJy?oekcCj]^qQ?G[ 3wH1uq"jsq+,]d2p   U[ #  g f 5  ]\  S L j- }Cy<%>`D?Z!R[GG >Q>G>4 *3 PdmZZfZdd{mdZr3io[to`WWW)`~1u$s&-`SBy}43PdmmsdLFWx41)\?RL: *+5y\?*!xRym4ob `PLc'7bT|CJsqhR5 G: 9Fw}K 2qEEyE2Q(33OG '! Dq X D '.M[?K}tMX 'ZEe[dG)>e4 yf\+RRH,frs4~&duN0j$DuJ/F_9]7!?*xd( P w ~ L  R 'DXbNDN1? gm rP s3 ` Do4]y{y{i/&ECtZ<)B)3FAZ+E l ''bDbb'`Z.xeTex"f34d m1'uW9t~%CXWPxbQ:> *4[dZZmm:N7CqBoxs*LH`/S"h^7`#Br,d2    B  A   " "  i |%  st b Nlo?,ShKM'y? [,<|hT(TcTT^^^ ^K'-:NbWT.SG>dM$~y8[<17K^r6hhphhh rrc  : k      D|72wGZHf"@hiB/&D Nwv vH"T :ksB$W.$87BB]88LQVL_bss}i}sJH>#^3dgw?m< Go[f<w@1rW}8&-|3*?r]A--}8j7MrM9/"6@SSgq/{`Sh8}rt69?u[X' 1~7g[)<PPFd)F Gop*f7@.h9bi3}x #p]6RA[$F':ul&K}9W~b2.V9"#?A[^rV>6qL|5HRw\OR 0R H R BH + K   g  5R\pfH+  ] 66  ^ r U  % :u*dH{>g&XA$j@ruX&:b F*X!C@.TV#i_BKjM&&[9~$W#.,q+!*Gww :b3e?kbTbk8kkMbXkNbX N ' :DkZ&`e*.}f+-^JR\[oFZb:8/,BfTe{F2ec(YY(mcF()  <F<d Qq#i&13D456e785`"On  2wF;0k&CW jt3~Zw LEcTJf ZX tM.}"K+ 6o{ Pf*Ovwk9   :} N a| a X@ 0 vO >5Rfgpf\VRH5u![S]-%/uN0Hwv '; uv   9 `   Y     F     o 8Q _Q Q 4    B H W  ,Em^KCkC1<<>fF,m^XAAKCTh%W7.[`+6rT7`AT8rT]{!5>ZC1}-9fLG)T X" {  ? s  x 7 ^m | O  D  ~   .  s    # #  K } 8 . t W / u  k 'cZO d5 ,e_+&@1TFL&Q Z>y+ys9 404*2ZH>],>|3K7##9K|V^]J]y{xmk!RWy84xrd] :!5RjRR\VR}?!}i.{@&-VxW,1^Q:")h-o[QG4* -KhHS6,SrK!-H#f-^QSXjs^,DRWi|Go  C    I o[4o p5G6 q A ^   W & <eqH#6s7`skD:tN`uMM``9tt~j&k8Vd}eH7h@h@i?Gtjjj~&iiH#rd 6 u@ @ 6 / C /  a ;|rZT->?6T#A^%|j,u{'HZ4Gk?t_S^@",qrTAA#]6i8|hTt7/kV%O~j`MC M;CW`'WMC~C9/-H9m`1.K6{tjjWWWWj~8sH^ 6c +   L[   @ !;HvRH!  Iv O  8 C DZ23ei*W1 fHK`X'g6vvvvl(rKF_o &yXH!P+R[)3<3)Y)Mo>#,HemY N 9   Q {+3G:m::wPm<o K x Bx W 0)cP2m Zo\d N?S}K2Br9NvnvYfl5+RD>W{8f|ePX<Ml8u`.+^>6JJS@,3]mH v k   _g   c g ? - SR*yRc  @  Tv ( i P ~ Q  D5 Y  <  i ! tg   D%`lE R{d)9 EJ3Gy5p,Jb(h 76ir..Cuuu..BLBLL_i&9M^jt,~~f>3v80hKqH)N"Cy% }`7+hQw  t L   S H6] !?RRR H ?   7 J .  /r # :iE8jdXF 33eo*q-sQ:w3m6r/ ;F R4y{!g]SJSSS|]Kq!A!!Spo!&RQ^w2S{@1~"fgJ , &" .   {y|*Te#x}GL .f+ ~ ` qM 69 9 W ~     . 8 V 8 |. K   9 X (F|%gryBBteh:lnonZZ]wUc$Nj$7_U#S6]p*\x3"GrGQ$oMokeee[Q {> T4  <p7Hb qS7@"6S;gn\+\J|#oVw%DWW/8ikN1-r1D6u+BQ{R*Qr]?*?'jM%.Z..%{AB}iB.|$8{L}x7F@ i? A He 3w(u~.v1-r6 f  p A *   DF lQ 0 N7 k  & k X o(]mo$WH-s!'P1EdT+`0|hrcEq2 w#w~{Z2KOqlwO N C  8M  h  8 qs 5 ?ZD /9_Bsh@U5uQ { A  )) !|Qb*Rfi!{g76%~r9-sB/C`tt`&8_&K`"?%888.gFiw. i  A 73YN@%!} #AA<#ws`wdYFf  e 4  B  C  u 'e)vEv  d C t o   !   h   &/ X "!T"0e?P,->.MHcF !3HPyw>o ( ;P;EOYccvj:A9~+ZB LiT,K|QJ p a o & C C3 P Z w  N 'v1ENbu9VhP4h!#g}&:*?ZgG$ ~bp \fy[NXM~9tt`8MiCC`~7T|$s7rJ^7>kA7]g\?y **  y!J5^qhMB:`Z'<)P)3<P)m3Zw 1k:NbkXX9NM:j'~Z ~>~ftj{WC9^}iLuD CZO!n])KoG* _8 $*[.Lw}OAN~6r\,4y)Zu9W~Bi.i^x#w-K r    g5rT# VZ5 { ] 9 aTi)xMH@#}Mssi}iiB%7|t6Mg1?w\xR4x,37s./}7~~pG. s M A -  g] ! R qp " A 4 `o cZ35:XqbbkhNXN1s%w`3 wx[*4y* *>G/[DxYpJT7A^x,Q4? ]!<x N'Mt~.i_$`X ~<`G/H 6 1 2 p4p*@h#i~Mq&Ku#X^NNbg?Wfp$HB_sShBAChu c"c6661,"W"6Jg5qe5 L|_Fr : kq   y  *  k kP X a uY    M ' N    " 9 jH  G  s m -   I  F+[! , 7 @ B 9 h    M uJ7sJ/_ m`[XR];T3~oN<,RK]}K`b1}}T {:Rtor6NCVB|-79AL^^|gfoZE ' i  | K R*QK|xG5| ^ g7  | # _ } V CL . D$8cL}<|!]JriMRy\_p25rgb|?7NET,HoOD~.~sA^@qs+)pGZ%] u /  I re " rHwLr] ! m! )!G![G![!4?  > | , 8r ~ (Pz6A_Ej\ $X u {/J 91NQk!u8j l/Z//&Gp5&M{g_J6@@J"]gpeY@As9Dh,>fyq X [`%K+iBeE% V 9 }- -  I 5!d ;[e}*7p 5 @ < $ W tK*\57d.2  M & f49YjN8C_~ii~_j8/a`(Nm   2mq`^b}lbN<94rJ5H 6A]V5tP//bAkuu & t - LFAJ.rpP0/LADS{gT:TV  8& amyZ|pSL- x~BXv+wq- ;MlXvmvvE1wdBdn E C}0!x~:_KgS3Req1 W / Bi K @h5S!N>LeTSzz]o, +{M6^#*5 SV T U W~ XMc&m/WtMuR.`j/:!P"#QH2gFe#"}$t/A{IGuZbND:#q YvOfw3)e4 &~_4o|wqc FLc| "  f 8 A w  ]'  !/+`++  V  S   K     j # 7 X7AAO7-P}GBf/gX-}P4b?g5qK/.k~/<Z  9 O L a - T  T ` A  i   ` D  ` ) Newg#?{.t'dP4xpG+HS"T,LK9$ukYbbFx /ty8fp7S4x )Pk~`sT{@R*p /xBZ- ,;{lH*oOdw2v>!   ' _  <ovY2q78dF)W//CjLKg4o3*bHq&C#WWM~C9b/9dC`>f_+h@?Q?\dc X  M4 [ $ }  73 7d # i1 k ~ :/j%"i-89TDPe rms2 ~ CM 9 & - & @9 MH~ Qo*$.8HB V L "V V |i 7s } . tA  :qy(33u*.{-%qCX!dfefg^Gioy!?ef4\]r-4xZ:K@yeydX[/wr"? >we)xx>oG6hp?]K,Ks1:PnooR^69AbVjeuJ -FLtWMMZMj _W-,y*k93NWi|jL uR ` L # Y '  <   {:H WP.O7'KDA0#8C (HP o y T g T . `  DxOH<*pHqr6}_(nN H"K|-_~&i_LuBb8N80888BL;VVZisQ?-]|@h-!Q#Arc'q}HK,Q;N/VKHxRGOx D Z  M1 tk  `   _  #   @   5 f   j C  *  0 v f),QKpVj|k}~ZQ pp65_]&,vdx" Sf!!\ G+[\[[[*eoxPxo;xNjd-q~o }DrM,g%+T\,>5 GZ w2OYl    M   8 sl Y E      d Z < )  i L .  e >     `R   k6vTFVMD)?|hs~.9G]TiuuMbD:/N`b9BtVsrq -Kwr2t"V]7,+*HFyu ["p3(  1 K /<jlLq! n_Q%y/Ik9NX:v':N 5 { / ~ L _  X7Z"Sq+g{S^es+C9[\{"Nh;K77K|g5* <3v'WM~MbZ ]A.9XB_c}wP<)7 AT^hr||<w(l|Dr^WTK}7#?#AhbC.g"+H>ZG w   k   8  # rC  i "  # A K7  B _ W(P'ov G. j 6 m s e ~  H  : ]l#E2}($ `DwF Yo\wn,dnn`Om >?~{6A\,gXH sx#gw>1Nd '/ ` M  L  A  "  5\yf! t qM / | B : <P[64|**%G~1?lE{"|Kwnw Y'#7CK^^"]Xf/ Sw>/3h,O P X   9 / j 7 S B }\   #Q Ko ^ h r[ ^* -  + _ 6  K / 8 O  X Rd JV'm&N*l4"hg7V$}iVWV_i:;KF6+y43wFYb~/s#SR 5\yy| w>le N /  P , f1GDNN X)N<:<:): :D:o' 'f  ^F   to O\+*p{]8@j,hi2WPob6Y8(vV:#9"Lf @d4bd$k#C@8BB.!.\Vo-|w,/Sqi{{qS6>Tx}oW> d?*S?rg86jMCWSs+K4qxHfp'f?Wq#8Ls`bdKepg^V6`]u{<[  >xq"whlibMCm$ LyVL"8|8W NO ;n< d3 )PQ cyf:RR&Rfyp4>e)m@@}~1YE E EXCVr6x&LX|`_tL--K[r N{  \ L x  I  0  ) i  r E ,E ]; {( { ] , P ^ x $ Wp   ,    & Dl)Gy#i7NWe0?w }H`bq]2]{sp+M:!;f<*e< l+tq6BVVr8ACs:L% 4~`MM`esEKgp{[H3FY:N/WX1B71@X9edX,M?%>3rS;v!yc*(Gew[Gx>5H_6174{V.hit~WMN&YubX: 12 lwX3j*$\}-Jr7"JgV.$.BV!_5iR}f}ps}i_VL>B[8o$toMQ/*N v;dGf?+fH!!5fQ]5KqL,q.5@[y wP'k&}Mjht~"+p    y5{7_WtjNWC/3&&&Q/9MWt%Li }Q <m}u/V7#,gRpEE ~ 8 . | K  , q\     I p |? _ { r ( s< G 9H JTO_t[ gH#T&8kW*RD{O DcP4@e> Bt/  D4 GenE1bWLV^x+w~<DyoZL;  { H L h :  @ SL I 6|    #H  B  CQ o 0x[>  *R\g]r7L.9Mk:d Hq|}?~uqv"nep-{ij1W /&&N9W~.$ig+Kw;"q&H8 rx SZ5[.P^uHs73ve 3 /  i  M  S rp  eZ=()  3[ 4!  | 8   ' l"Axi+wKG`?6m#}5qC*+"|ijug>hI7$K?5 d(lN98#]5H o2ZXEWiN#SWfP]!?x~VA " _  m : %  C `. jB t$ j W 9 u   ) [  - s M 9  } a     lYE ;o2(wx y q   L ~ 2w]- {xT7B8`C///V&K?Xw;mZ~P.FF^FF]FPdfm 4>QexmP<<b~8yeZFOw X M LX -  /`ew1E; m~QW 6 hD  XZ3 m[y]A_CG4HH@#]K[~5D2) =e Iqy" "]d+OGXWkW.LTS7f|x,6@JSSS]gVq#?x!Hf a  t  .* G x T S 3y DO MC_8}7|-Khh7^T$Aj-d4   _ )-^J]uPf4+,7V(j : kF  p q u N _%v;F %_[4rg\yH[dSv"-_`rDS 5e !mr:sCW%uLNiDi:sDiXiu_L./`8Ls#K{6H*)DO D   t   . X B / U L B $ I     ` CF &         k X DP 'lGx   #6 _T _ WD|h88 e?67}L`~bv@ndwi~; u1  ,DH&x~L;7MJ>L}rS 5d  u #W 6.54 d(    8u   |  " g \ & X    4 \ { I  8 ` K L ? ] | 020lQy!{6Ks#B8%%#B7B^LL.J`f4k3)2eX?.^g,Ao.Ftkb`v(Ldh3 ]femve [ [ [ Q > L> 4 Q x   P ( B j t X} d y?SeT}%%tW7MWJ`t!p ~ Mk\ [h97ui E$QMuR{SxS ]{H]?"er^AP7- -cAK ^b|&]sKR,!Z4 ZYW0SW!_O  7 t $ T y 6 x w+5k!M  _ I r  - f s  d &  0 : ; ` 3 _ G T R  ]J  -   ~ N ] , Af @ $  C  D&('GO@)|o MwpffGyG2u/ 4QxfQ3r)63))*3<Z<<OFFP 'P :Z Xd ad km km Nm 0ZPF<Y<<FPmdFd)mm dd dZ)PP)m o;>ly?c{,Z4AyLtCp]TV`) \+M$?yTo<5pOXGeWsK<,d+D>mC'Ls|T"J?>43(w ' &  :  /  [ B   c    } U  O  tw / G  u : " ^  l 2(ZJiMNPeFy[6p^JVt/ )xexM.g&Dli/4:q;7E-|SpT @! c'}}7K?!o>xuWxG}p7qJ|f7 x}L3%E D% . B &L W_ _ i _ V L .  M  tO:Ghy8Q'$Edl)RSK#l#7Z^[,4  *>F[0=tOT:\M9(7 iL\8.8]BL_}A}8Ah~C,S{!Cft*_TO{!V#Fo kyR+4f!g?"fr->8wj2ubZ/f^"$54'Ykd /~[4V >#[7--7w7727-- 7XK^|/jSLHA x{d*O N N   | 6   e  :2v 0   M4  p    J ,    6 ~] j ` W M! CH C\ Cf 9\ &?   6 :E Gpq6rV`&*y6iMDc+x{QQhodl ~7V7qfew$Kg9WVr{4 ~F . : ^  6t { 8 !^5?HJ?5 ! ? {? 6+  |   J ~  K2ZoLpqh_``9NF>?6AL`P yk'qm# L!W#&Bjuubu9X#{WH $ r.gASRfo wok`L)-PG ' & w $d d -P F "< 3) [ Pww[F4y f R #+ 8 M klw+RyTQ.Pt9C]?/ Mtv :    A  He~<M& uDd d) y >  Ay _ t ulZ4L'`l fQCgh>}_`_Xsl#erSzpfp<ovd9'_jJ^x3! GFE~Qe8)sdrNSHG<:H~QBoLoL[84ftM&}k9'<[[6|?`"v|-dx -he@_\t"k^eSGyVh9V:cM w< 9t <wV| SC+h,Qe3mXt'DVbu#/Wiss_h___]__Vis+s5i+V8,C-j3F*o{,|KBCV8N..8L}^ 0bp&~o$m:7"M?VeKD]L\JQ*F3wY N ; 9Y l l sl c #Y hO 2     d  | #[  f t 6  C!u5q}"KtDb(v>5qJ66J{Du FMi~shh]qR> <bK%>m6   + R f f \ +  { J5|4Qt[QN* e J A B b(|_/nPP]P#PddG(+b/MDvB#>gJHGdC6{}#Ie?w;ts | j  AY S. +y*G[edQG  _  f!m ;  Su  j K $ _ s 8    t M    kL W;k3E>!    t% 0Wx-_CE\[]h\k]@c66@n6=6@JSgq {)Z(g]Skg~%5qR>GFYuN5i#_]f4  jd   r T  Z _) /x >  'OyR+dF3g@x[> 6gp5+,?H^HHsH+j+!Dxg!,{#KjVXlM n<kXXXNDP:::N;bv&`''B}v;#hdqF  ;my?"K_t"TijN0YOn!Q>r .4~G9oF &/MB.TS@?Q[w1~ )'@pg!x4<<;ZlwwwwmvmEddmZY     8  T  @F m 5f\\H  I   8 W adlmeoRJK\LWu]"eH!+SRf4>dZD(M;E2 wj&4H1]d|>_pRHRp4Ft:W&N: xPH\h_BtCvw9j).NLissri@L.`j%C"yubXGXebxQW \r]gH %[mG5"e _pWJXrVd`x>byEff\\\n\F\f [<wd EcX0stK,V!T]\> mE: D M   8   u '#7;AKKA 7!{g]q}_L8+.y*xFdmZ%3L[|y]]Riobl < [ L  y+\\efyd YG<lZ;w)wZQ<H e  T \  ]Kb<}i_s}s_L;$d?W"uAvLdPPd.2sKC{+h"vXGC.dNoW3.iB6Ar\o6w!cf 0   /4 > G .G i> 4   - Kp ^! ^ TS A -T  B } .& ` < 0!q +@sKVCWbNd[vR(]r0l;xHX6K/j}.MB&888.$/$`_V^g|[! eMbCS>P2kW8 D#    W ~F   D  . W B L L U U U A B | $  t , C @  S g u g  { {c q ] S3 @ G  R  hJ - -  U   9 X E*QRg"/Nw6|@gtuRGEPnF3:k)<PwO:_T]p/C`sTJ \ W Q  h<  !lx 3Y<)  o4R7 L I` u # tp  S,2"J)R*e+q|j8Ls`u sBP~Q/by1\R?5!'XM}T+Hqf\ *GQ[e[Qp>+ {f5#"W7FLt?hb:LMDb0 ~_:bT{9tQBXs.7"Ad|@ `R  I y !Qmw    h , HPy { h  L s ` k tc F * ;P1 w>Q? gJ,f,?,,6Jg]{6|^KAAKAKT!^?fg>Fo Pu(WB N 7  W@  +  L s  P   Y   - ' K N h k   @ u g k D  ;  3   \ q , K h  }M  t w NxZf!HS5++5/+++5??\HHHJ?+"@{{ggp]]>q w?Dx9 ~k/8BBg8H*~& N k L < T x , { \ 5{5@! r ,K # A C uyS--TG"JqjNEPRo @e}<C:uN /`vO( %Ls ;-K1h/^JRx t6S>q|HR Q T m:E`_K 0 k ! y     R    a^ '/EXw    q  &A Dct4bym Te N?]6N|7@sB]||LT?S; wH't|RKq,p  Oe a W   A x G  , @ If S I @ @g @6 @ I S {  +RpprR^+K -  ]  | L L  j 0l15g)[9k!qx,p^#,TiL.}_8tMMu:E2wZx[ 5fqR"fyrT4AK)T|c6sT56Y V~B!S>)QO'j  ' 0 :L Ds D D D N XA ah k u u uJ     e  9F M W Mc C    k '  0 E)Y5q[V]moy5],G^6_LtXOn= Q\I^89!zN11dDEk19LthsN\~4 w18|?r][R>E s i K A "  y[ ;w:(%/w   6G |   { j K E .  C* p u '^Y% ~ZX oy!S7.`tb+YSZ&*uH >qg]\]H]?qH{RyQ+Ry<*x;<2&D8TBHxduN9C%KJy*?Z\fEf?  0S : 0^ Vc()PH46\Tg8KC&Nmux'y{h_MF:(> !+J|.`/`/W9#ion6cb`VK"kM[ ]DM*%}#D|6/`8imO7 D  9q   _H    * Q o  U   Co Q ' lfq79 P4+]dGR?5,R][+vQX9$w'W%iT"{J!55p55+4xP5 pO4x)YFPZF) >g+#W_ Gy4R{i.:Po[e:xtdiTE,b5/ iGo-SRG [Dou9~%Lei>  }_.~/yp\'5F*JJrKBA-#u#2K|"(GMX{KR*4jm%Yh  D kp  *  k :3w2v< '4   &6 ~|   _C  G  _]  h W DV>\g|4f#.Libv2Ah<x,o6[Se{x)+Hfcu>L)ZJe' bDt`}|.{B_p}edE} :8  C j $& u # K r3 [ R r -g B| i 'E9Zepv{rdsj[kmxJArTKK^Dh2@w!F[[c\Cr66T<u}_V_#""!R >F#v] a ' W`  B   h  , { ! s\    g  y? g @ L K 2 LF Q ~R S A 0.&( {H7q|Yudq*XkfY,ZerP[8fIj5W?WR`zt*3Bvi'jh7"T|6{uj+_TgoEY0i&$7JM\o>  8 R' :  /#   6 S S @  C #  ';Fc> ?G@  h # s _  k `P/R]ubhN#:'V`w/P33)u3D<333Z<)Pme*NR/Wg~S,8VissiVB%,S{`!pu wp'):*b5JT& /YW~Ek%8~L_sK}?o K|Cg%_y e 3FPP_<. `XK)[MmSGh\}${@`Nr^EK7-#n#Z#PPZw#7KEh:,igK6! f)D4~PHV # & $ f  !O* =   R 8 i - U t    } LH q  j i  XCOP*y+b:J)A s\9D3>\g/"(h^^ rE,Sh{S\*!RyJGwk9 4GLo AP|:"N@X]Dq{F e{]JAiTVj`C:&[CtSBB}~;ArQH"Sg{|K-#7^@+ 5Rp)w E*>[ob`$ ^3Z]4NNWLsT{+g3 Y) X;  & 0 & . i  T } " _ @ 8 ]  { j W! C5 CR C\ Wf `y jy jy ty tp jf WR 9? ! ' g  P  _   :lw*oppg|h8&:O )wQZFp3)),r#}.ot4DHl)]">R@S![|rrJ"H+4PYC( aS   M tF ~& j C8  7  a g2?Rdffppof4\H5f5@]7#i~tkZQL&blZ o+?{@6@grrr+y*"60St+|6)oONN`Msi"-h*o"]<X4M;L   6   d3;1 '   _B   qA^T [Q H ? U 2 h  ^  D@q|$s8(Z3).)_{4 WF i K `  6 S_ ] I "   A  Bs % & `Y)3p4g5]Th7s_VB.%jCW&bd /x`> A \4 [P_'AiPh N  , "    K   :%/21w )[>RR!q"h_tCqN, |#mP_) :v( cF: ~XVAJf_&K},+f D >  g dYu%B  ' D# NA NK N7 D '_`;DF dx> , Af L W algw6xpg|TAL9'})8*5JMhD:3xpf,g|#7B_~%WV9&^S9tL^|qB\+o2   / PlkA`.,@gJ@"h,s#}C');eFG? "A  &m G;b< (lk0OXRFq>?ShDm&K}wF)X)3wPe!bq,WVAgf,,,6@y@fSfq\H?5R?R4yZ ou9 Z b\4 `tL.}]F #- - j- .#   ]GP(Xua: EZ#-x7ApT r @   B  <"[6pJ]{+Hp,Ks4ec) <ZdddZKFL M#.&CA8;JgKBWlb(WL -*Qpffbz%e@+WpBAS>p0P4`El     @pEwO kx+9{C%%M<4o ]  K 7 / EQ}si]_L..Wkd[`?9l<uuC/virH;w1%8hhS5e! ?\l\H`6|6TbM%?7rSY?y  4QoY2e*Z!)"[ %jf ^#/8uMb \[-H}MS,"u,u]+WGs -:`V2 0"   ! \ y 0Yy\5x+^_{gCS6X'rAB9wZk) e4{R^VT9i.k0 $X}T`SBf-"XtGs)AZJgqSd,)xK>RV8%{g.]Lgiq}B{q{/qg']J" R{K$tbs__v_OiE}YvDAh~i6gKg5+HRfypf\RpR?f!*<?p.e7Z"u!Ry-,!ed 4o<d< ;QEE;yfR????H6R\p}/kP)\ !sQbRG@]#-_$`W/9jsT9jq4Bs/._}}}sV8T,y>.s,-He"R  x  h ,O \ a  C[   x Q  j f c      ~  F"T4C?N{Er V< H;lhBbC`u'L;KwF ]? Z)nX~YKj!843h YgHGcdXxC\_,,y*9wN D ` L  A1 |D N N N D 1 h 7 F . o / R2w^HC-YPMx1*Px**?Zq6v^M$-]pE>QPS-8NC9&CBjA{-!R3*v   8 ^  i   i  ~y 4 Dwl  X   5 { u X- : .t/Y(P ukGbXN5:JTY8/dF)* R<],c,jS8p <4X +Q&w8  j7 L ,  S RH*[eeQ*fyJ+ K g  |W U  aHg<x'lA}& Rw!\+pq46PhD-i}Bq!Wo/ Cu8k}bbbkAkhkuuuJggS,KBW//b//P&&>//H/&]s$~`MC/&j.\& C`~i$As"KP \ & G 8 3 - ^ `  L  ,T 6 6J , ?     <  | T( c  _  j  D    Gfqr_Mv:Y2d~)uve*+f!h6V8.TBs}8T,j/Rk1lN/d)pxG[> t%hqyfppQppZy 0  i4 -Q e xx=xoeQ0> ~if5sq6/A ] B Wg/N_5M 0k&-WVcB}7f"6{R>"Fk_MyxQv3G _  g}?5   " 0U9bjW !"<k""Y"""m[!!= y  - L tj : Ff!MgQi  D w O)|BnQ?5,Mw 37evSZe^zAB$z[LZK+xcJT3d&"HQHF2  L h ${  K m ,O ' + f  7  mR c  "    9 XOlw<xy I3 [ $ ` r <[y`X;nF#)_ YG4 q?r]L,tC&rr9|j@V\ N {fG)W~.8rAq4x3 D  } ^ rJ @5!  uu /M   # S  gp    *    S "f   K@   8   C( ) = R X g    E d< ^.[ b3 yyyySyf#Rs5!bqG6priS&u^- s_LVs@A,s5`[M `~X/}^]pP i#;]\'X 3WBO#g '5 X ) : &W t   B* sw  & } _ $  t  D0Wt%'v*f` X  8 `E w<Kb>K>4* 8Cp5N]mPh< Lj&[*D5Fq[ApB?j{W@WjsTJS{p!Hp:C8|@yHp\\*poF4mQoZ3xZ! :k7sbND:L10dn[o p\JHHRp*x6)gv+y4.mT:!9G~ ._~L-^r|JTVJ~:AdL>~p@PAoQ>*} _VL*VQimT"b/j k%%/.sW&Ah@q9jV{KS"r#"6BJJ@&6X^3#e>* iV84em~jXWC&/t8k_N' _w.ZF3)))3<Pm1uM~Ls`9b #y7RT5r+++5@5{?\He G3x:k3FPF3&CMW4M9f-.& &Cj .y}+#hq,TV|AtCB`Nd QbyC_6|g-58~~&sTu6:3YD a `/ _8 - g ? " ] Hy o  Oy  D { X X 7 : s  2(F[f?]TL^C:.345@Tsd(dHr.)3XPdEwnxmG< x?4qHS@@@q|#z iZV(L VVi}6p(^hqPRbW Bo]3dR4'k3/Wtl  X     } t ^C  ]' ) q , r h U L  D9bH{BNtd}][G>44)>GN[ojs^x"e{G*+ [3f?! a j { _S , A  Sh - } L $ I h $j jM 99~L@4\e-kj70qEy*oP3)<3dPw ;;lu&j;wx5`_uvd2\h(Y8 9XsAOnFk)&7S!\o[G*pR5  {J 4hQ7Z2:WK}RLM'bP/` pr8__}jC/&-/TMtJi|e?*dEP :  : X Cb `X WD M & w aF  YeG]>>hGoiPi}`#TLrh5o r^(7 :  9 V 8.  -  ~ {j W+Cp9/9 9QCxC`~.QL __y_L 8 @  7  M / kNmdXdmw-H i v,Zb)Y dRg[,G4*6 *Go[F<@"Zl|T# 0 N aV k a N/ 'Xlw P*Q5?@KhL.`:; HZF]<,<FZ"@2glR'u>dt$st8^#J^!fr-*_ejbZQ?r@LQ~`M9Y/& D& 9 W ~  & 9 /8 }  h D,!G xD5A^"eOF N * & C? C / S :-O.3 p26P) C13wPdwo RJ(7Ys'u~9&tXs0 -@\ oN:/tM}s^Tq6*fm GxM^f l 0 ) F d &w 9 C /  m F  :[Ew |4_RCgD#m Le~ NpRZ? +!>p\+RR\pQZ eC) #,_pJGG   k     x [ 0G* m\~!N{r|B%j )4o+,rs,/{f:RphR5B&0Od+!! 4>Ge<):Nj/C%Mi`t-h"Jq.L}+?THpS? G[eooeG *   t  $p i?    S  s 8 ^ - C  uvZ y#-h#s1Pe/pDm 0xl4Qf+]@rh}KK^C@?x)Mb9Lq5Jwp1[i#3p>'` N B  _T  ]  H ?yoyH3 < < "3   i [  0Y5@K6|}%BCW&kmkPD<3)dx4 \\,|@^#(#^9bgHZ>x4F : 4/xP^:,R ew~}Or] 0R G /< : B9 8 -A S f @ q   " ? Q Z O S0 "  i - ^ U  `, @ D@" d-!Sjh}~ xf S K B a9DlJ p"r|/sD`ObPcQwRgrTkE)Eb~%qfNe&w6\|e MsJ >m :  T Z  0 N  `/ ~    $ .M    l C  u[c   -o i  " 'AcV`kZ["R-].r/13>Nf;AVYbV_-rH"JZ]gkS@9"hLi7rM/]!/CWj D  . L XivA>R]@TL9y ow &X.KJHxQmd 'c j C 7 T g R[)3FDFu)u4X'! q d #) Mx G 0*;< [G)?X^&b\  -| " _=jN l(H { d } W >Hf?u+d![+pRp[P&lu9l_ w  _ 8 $   Q   ( ` 9 N  a ;F04YF|\ }  T / u X< G?g5AC@|($&wwk:O:u&t8}|,e)oj%F^SM+\Ly#^pR!{@|7r7B}8&DjZWM[W`Htr8t9:ZFo> " >ehTTh3wJvNR/ . *A5f5)O ? e dNv//VM97k^rE|    | r^KA-#V iF8!g9BN~Z( de +y+rq}@_L_K|H4)J2:+`}GN /.7# GxoYG f ' 0 NZ a  4 H J X# L(/G0v; [+bE_8et>W 9&f!g6rrhuhDhrrrdrhTx-HLqMr-bPiLy8.@8V}$At/65/t4$o ";Rq*#s{.T8&18FsxA\JS5yAs>o9k )FcdN9~(v80h&,.^?!>d\u@~7hMJFpRe@AV[Cfkch%~'RGK?&gOrA-P-=AZhSujH>4PXW&~Rs-CJbZ+\>y!y@fRHK?+!!+5-H7\ApA-B`f:?vgv6vv^:.9~'V hHRS,kW8,]\ov 0 b  . } - h g  \ , 6 6o , , " "P w  " , @ S; {Y  R  ' X * G Q G *  :?c  ,F r  H 7e5/~:3g+7i $?{js9jkbM~ti}#^y[g<(\ G<|@1Q9~wu/%8BV8_VisVs8_8~/tu:ZZx* 5?]S"""Jgqf+p[web dW .X}/#t7ATLTKT-^rS![|3 N    h   } B N m~ `?Cg&&9W~F[8i_#T2nnYAbs~/MkjZQfL7{,f\QF`8'9ft  Dt / 9 X i' # r d P g< < P5mp'/p!V  I  # s s 8 j D4puP*VZY2R@72_cM0kXCYjdx4fI5+8+?f,* wO R d j $ } ^ 35QS 3  8; 'u9W4M<9ku /`j)`[%p qk ^ .1 Zxz]^BN H^ B 9 t: Ye48djGXOZc4P=FwQ;wu2& f>)D~}K, 3DCF8-"WT a!   ie  |  q3 F5ZZP<xfQ!  g   K\ ? }  ~  DJGrf7{|}~Vm[?9"Nw\@"|iB.O8_-Eg&fVGSwE>Nw WB#}K]Q\k Qs{)35)*ee x[q*%W*f3, A iV_ds(NT/CSXyQ P k   hJ5 ? #  B A ` bZ=4QG*$f S T i  ~ 9 u 2tmi {?@|w(X&jh8n4jMu4g7Kyi>L L_i7-|@R+4fZ q~sh|}B%gV* T>]E Mp K+xdW E5c*YP;?]| +] !6Kv_F~ rY  Zx|Q*N !p6  4> >;>w4*Q*4QIx+5 p4kw/E'.TGm E l ' ~ L  A  ,  \Re <4e;co=f    ^2  < Hy6b:)ZJDBZ~M[9>9Q9oM`~F.ib9A{Tpx %|@q6{5R[[D)dwO3 X[   ]    u G$j{:rYwWF kXD:)<ZwF >;H0ts{],RT-#-K|"\@q 9 _ | ]6e3vrA'ND.&cF  3 o xFD&35oQw-{5i>M'xOnS 7f_!Hi -]Y et$(ry(43dpJDKuiMW~M9Mjb~ x?%B_}.j7rqWVRyA"fS?{{7BWD 5y xFDj:Xhufdb: ;YllFOxd*oyyR?5Hf7}G.W'&CVA""|u-D _w~G1Rd]xK ~5:@PPO0  at . g + Xd(`^p?[TdE W a u WD   8P B B .x jf  6YTV+@TksEwOccl\llcqE"hZN " T4 }f AC-Vb~04\ {7v;c3 ZP-Z_&lb1kDC8'MUs{y[G32 u / / A h g6 +R\R q  R -  U -  /o  k  _ O v<Ke]4R4 Ylf(?<,,-$ - V ~ F+q6AhLMNF*~DTB]&fuDo'1Nb`i&`r6V^yx 1`.r| @PP+*  M  ~ ] _5 7  v:Y~Ut_}B`i(W3   o B+ 2 } #d~>_KC1)4?JTRijb|O)sj^uO 2PF';BNg+vD#{fQZcujL7 3[D9% q D   `  .P   rv  6 N 9+ p B  r 4 Q!eo oeQ3 d\d)  o  f _ "  | X   ` Q2mh?%7 W>ZR \{h$~9u0 d>*R?g,+f ,)lywi;7y*Sd!XZ/W~_t#W^9,]kD wmdPPFHF3 Px>l f N! / ~  i H  A h  N h #~  B  K5|K9it&/'kbbu0j7{*XPP3[)\x ) ,) h)    2de?"K}T<1[Fp[{f{}`DMb'^ .'X&IiKr$$A?egC8^#PAT&^}hr?&i  ` $" @ |J J @+" |P7;Ltkxl!{P74$ M b' ^Bc&( F 9)uPn(*c "bT&8S!hqb9nYN@WV\T]\*G>)>*Wf_6AhKLWr'^K-Z#)#7^xx@xx?QP2(e HP6Q^yi{j^kBvwPf,qJ#6JB{H`MFW(j'Cs.+,Rq[E< a ` B ' ' 6 !<+ G , K _  [ 9 d j k% D 0 6RO  >[m[G 4p?@67h%}k}FG^H,!f>QQ{>6!8J`r8OjCF/ &/MjZ l0CCL1Kd+G3bR?`5?.\- |e3,g!t\B#T|\|]^K-T_V8~WW9&k:FX xSr@}|~FgX78)Wf062h##-fT?!!S?pf4n;KBruF-!q  a i   W I + L }  4 G #= 7* A K Tf ^ h { r - i  rd T> -  B L m ` :7)v[n#SVT1--7e^5"{5]y"[T#)}7!Tr;,Z@S]+]J,"-,J{7"yQxn PAwFF _x*4pFD]/B`"bZ+>!d'OO X [ j y +  ]{ q g q {  ?  C* NO ;v ' k  j` } i- { + A T T3 7 N 9 ~ %F8eBLVVAVis/N^ FZ[  H t q   r # / LEdop~]`KW.MMMMC99#VNN( ve5neVy2fnfy >d\{*g^nQs5 w(do>pz,*|^ZT;h:`]fc}Q d^N)E9 Xj W B #  R m~W &1YvNc<E Qm\4H S 7 5  t > :3b&J~%iCK*rf7W",D,,v,"Z3 Kx[B> C\!d{Se" y5]"^-"]+>##)7A;T^rCS N Sdt % _ | "*<;yt*>8Q_[se_o$xWOw[4   \   06|PoB 9yNfH!)QJRT"/NLZ[RJ7v./D)YxQeexRH\dlQ t;By>{\4kM775JQ+3*(xY<w ' a   ( M t   d    WH   &3:oPo-_#}'Mwu4'#s.'X9tL.LsTJ#K^RrewX""9,`6@JJJ@8"_rrJhhprwE 6 _? #  ] H/yB! K  T@ s j5 N xpPW l\ " N 0 W F $) B3 LZ _ _ Lc 8 $ 9 S  t C3 X X&Y`?gtM'&mp@A}98jL|$V]y-r eJHyx4 p +  ]|R^A7-S#--7KKThr|s|Vr8T#~.MC1Cx5^AGW 9L>hH*+(fl*F    >lww#4Jf\eZE & ' / ` M:  XP-LtK21[QGG[e*dAS \QF):)33)r)3gFd!5HDRf h[R  Y)333l[e-  L ?g&N.1'':Xbu_/hj"q.iHp###\5SBthN8 ~R08~c ;O +OgXSS9Sg8Kf?o)c'b.T!e ,?O4   t ' _  ~  h  L } K i } $ W M   c)>H>SAL"M|D384+kx \>{fTA%Lj/9_.i]+T"{f  Q <XQC%} X # r B " r  Hy e= Z<PZcP< 0 k   I N |   wQGJ~N1Po":r$FQk?<{]@,,,3"d,6,(@S{N9?L "Ey`P.&f}*@:?9*e.9 <XZ dmwZm)P3)PGkRS~-B9h)JoL5tH??+<+g@?|A4i 8C}~`C69&HQbwZ1kxy9gsTrL{M\:43 Nc D L 9 $ 7  B r @ {  2 N W L 7 { ,+  ^  s  j  ' ql    <TJyL#&B0c. iAZ<]))3xP3w(L}}LPWXx[FG>QGQf[{J"<,Sc5/ r)@1Ft9B_i7V8{!C[1Z2*f  : NB :~ D D' N N X a) X X Do 'Q>4*>OG[xd>)Z\vgDhWi%`/L 8 ?C`ja`WM9&f3F< k*'wyZJ A r $L tF N0'0Nb;d&M6rV%rJ!O)u &E7kSt+yh64[lbW_TS\[[d4b`VTJ5   y MH    J  ,| ] {  qt ] N T o 8 ~+ )*Bt9/k~OBw#)6RxexQ Q[1xMB<#v]C5 F  A   Z  L $ A  S 7? ^  m  ; "v , 6 , E   A  L R M  TY   W H ]r}>*5gSATBst~:tt?q$sh0Ow,]g7!LHf~M999W ~>eihd{Do)j~B_K6#+|6@JrJ@@6,,w62,"  M    A 6 Hi* tdM9ObcZ3+H ] ~7 a2.,WM e2.w3 oy7F%w~CY0&CCj}7.>A:qW?L 73"c p`4h")mxP2'l    '     E  Q wOJ.tPO4p)5!![5 \? G ]) "w T: u 8 C EwN3_/Q\?9]|*Lj(M9&>&/9Mj e.il^]AR4vbj_^b]\~[<6B5K@g<qS,dhF7xeAG|4 65*>eQoY   `  }  K   " I So SQ @4   |p   " ~  sY/ >yb)h$P jN2*dPd Q3uttLo(FNt_#\ sA~iQK 6! D   T "  ym[(ul~NLD8 <Mey Y | i C    f  W{rstVu&'2Fv[nepRJ{A%7)>IsgV89%}TgckG&bW[B7'@H-QPGDCkB7!~m(6 u  D  ~   ,= < OHaWL-yf ? Z  ]  F  An   U@ A .  / 3 a Y s G[#"'}yJ-$MCEXw')Z> +F]Zn|w_92cX&)Z}|q(ORv x:uFC~  B}1Dk/j>F.'LsC%Vs7K^^TA-}V%i98W)&>RkgX:| 8mtZF< 8  ->["P\Y*t)8Pw ;kmJF:QRx+"  ` $8 ~ h S3 [  B gj 6 | - > Uy `, u7 ETFSGQyf\,\\fp7S\Q <4 Qo  /  8   ^   ,o gG    p!+?RR"H5#  {W  7) e L C c2F+[@T_t77biXbu'l/Af!\ +\`L- [FZWc#:{+MfV4e>.4>CGQbex[\x![>S"\?5|+?Rf,]*Qx5p4>[4*y J-yRL+j/{Ju1hAZ#3xe[G*fA7ri{L8y. $.m81LsA |( '" &S { ] Ry4ee[ X\ / I  s  C a^|"@]{"T/{SvKFiMkFwco&6^"^oV)~W/sX0V/0kW>i@K@?`['W~.@Jy [ O/s   {5l2 QedeeQG4pySJArK:F>i~~uDwf"*R"K,i`&r9tiDKKqO&!5HHb?.5++ : h [/LKR@ xm` A3S5?q|>sx`0?  s e*Z ?_{MDZL1wG\]{@5 hKAbKhj"{+ 9>ekxF!@^ )33)7ioQk* v *Ge2u 3PVwNoZO&:j/$8_}e}iLX`9%s1-mKh|Q>>Qx d1/8^{p QxQ*"6SqRqHp7L>jk<1mmFod*Q??,^|-9LHW{/L&'Wl(LsY7hJ~K?'3/kLhqrR"] >>*]"p?T]"&r% &XRd{S@@@Jq?yem3 3X<) /MjtotQt*jCpXg^)B4/+0;_dM>DO\+3o?[[eGow(FvLC_q5 M  L  |]  I o 5ER k  t* [ _o e Q r=   ,p ] { { A  N q ] ,   " ^A #s  _:  * Wy   ^ :/Obm<)Re*gy\?qy{ ]J,vN&KSL!w1:~< h@6VSqu;Q!{S6"_tj~@]%_-rgH>?\dk9 >QoNf  N   e! 435,Wi_N#-8#L/~(OZxe 5  kEsVViC#qA\dw Q5'"/Xi7ZqQ4H*[4GQ?[[ eooxvx0xxxx]5 ~<LZm5 v   wZ)Eo4d\*+6h-_BX. m)`59|uBNkOvcnYYlx> NyH9qLSJ-J]pp[[ddb:~_A#\v D   s #o < g R X  G $o  7 e @4  H!   |  $ j \! F qx    T   / ucFZe]f-S-t:M 3Z!H]h.ji~2&[b0f ]66@q!>N6`O.iV\AuJ{x : *!)Hyt4[xKx[4r-pi\59 g KS 6 uQ&d"6Jg0w!y[xm WhAV8]8VR*h3+mY:&d3+>F>YuRJi'PxQL 'N M L e 7 \  gg \^#G7h)m@fu`LZ7 ,4!3 { D # i ~  D8F7|\,"gs5M[w p# V )E)4,K##-K|qxe+>Gf5ZJZ)7Gspgu"d>JRHq@/<r^@A# N r }QV.gQ.LshxG6!R ),A$&tW~~` / r  u1o3kFktTJ +>q[)XL6O 0 k @  m  9 &} 9 9 M MG 9 m   E :OEc PF>*yhuB(Rb . [ @Js8t7tyw}&*x?p.?uD[11PNvM~V.]J5o)'Ms`% <vp-q QC_|3FPF3   } T  x4Q<\ YYumd x ? T,  `T #E-"h78C"Dq3 ?y kQOFGm\k`_BMAkhDDb|MhKV#]+ }V.W&pGNt.dh3{Hoo*eFN[`H"V|9X-m#of]^8_`WuXPxQf\]]6,r6SVfG<;8X#`hL"A@SgJ5y\*[w3b9Ci-7f*@c R  `  }  T     "   p \ H ^+ #   Uq 6   jr C- &  V   j  u Xk 'wcweQ5]#BMKNdosB$7$.BiChWJ8fr6FCj-L#gy4GPFEll2clO(3 l2.39DeF>!,kK(V]MDB[io|qoF< u7Wgs'~fJ>  f r I(=mddl4  6E K B  !dS/ m? ^ `LO> s|WjXlx39Z*F"U;%k~WM^j6! LU\c1d'r_@gwO['  j u Lj i ^ ^S H 4 , ]  u  U K q I   q A ! i+ ! W  c  ,  h+ J s^ s Ct kP(>w+f6-_@|t%`MCCuCDC1WDWuWMCC&8}'Z7rQ+"g^yBMvX:0'N9:.jTG?me d r IX<Dj|"SzqI&h/9CWM`jjt~~  ^ . w>Bi7|@:? )o <5] N 9h `# t `s M &    F=e*\, e3OO F=$z>]"s56q  / 8I #  ofndNv D4uwM{4aw k U; 6Zu[+ {4 Z b U0  t8F_xsiB1FEey2FQQf s &M>li9F  =vNPG*pniq!]x]{Brf> <  ' R.or)d?4PP'=::?: 1 ' ^' : N Wb / #4]H][rE a  ` d U } \ } L $ C CN Y 'ZQ\g|+@K&LMXZ[fZq | HF{lV&jB:76HOx22;Mv6'dWg  : 7 3lsANg+}+7S#6_qtkE!R  T  eld^8c ' u R &  r . }_  KC " S { 9 ~ .  ]   K  8  Nk WG.}h7KjK71_~9NPo P\!Q S"hK7-*#Q3n#7;TY|lvvl,cJcqlvH0>t ZVTN{u4FkD}hZ @+Q  o< l X * Q  & & ) F d um ;3?d8Pj3 eog[>K4*i***~*C4>>>4* 9tL| qGx>Fw'~b8#97W-j#}B8_WAu|D,g5ywm4memw 3d'N&V7"wZ)R4*Q\xgxGAHNqwrB-Vb' +G@yy,Sq 4e32g@:/|^AL###qAT\|>wJD+Mf_4oKFmS{d<{ g@Gh?-J_|Kj-C##7hubD@1! > Dh6mP)m2 W   K) P Sw f*444*\ 6 # m d 0ZEPFF><!3~1pxQ 9dp 5|B 5q!+~?MH0\p&Ct} **4pG*Qo~e]qo>L?J#} { ^ 8: d8~bD[lv\{'KX$jMkL7Fhx*q5) xbnLJ~$G|d+Y e D u    k :o4Y3\5QH6{#gS@":)[prh]^^T^hV|96H>`Z-/g}#4gPGNd`Y : 8 B CB 8 %   t $& . u  w 3 j 9 x > NyH3[R!S5H\sf\H:+m 5f4 3eD,jLL.shtJd-Q`Sc# # #   s8k%j}u,'fd3 *G[G*o5Q4T}Z |  2R*Qix*({K~NrY_OMYXXPG GcxL d<2H ti6hw g y 3Okuj&UAs#g*34 mb a : N .D 0  ^ b  d   | 7"    Y  p E B >RF9NZD[H,@#&F(Fi!j6w eeS=p2*k&F ]l?*:  js"?[-T|8|SQ!jGc 9` #_h{R  C _ r} {f* !xd""c"E"O"w1"2!!Gd    I  n $? W uO, A V 8` kZu9l<5/lTh%ukcnA߮x8 \޹VK5pH=3('0BUgpQ.^{j L#-@\Gxl  , &R     ^ 8 h 6  H%$Q?   gY   r   8;  CP  D5;Sh<iW[D(! J r Br }[W! mk P*,rDv#,_hbCl dP[ w E4o: jZ;h,uC%vN &3Eb~q5:B|p>  v  3 &  . ( #O v " !e)P  0 D k; O Y E  / WZ ~ * p   $ B . ` 8 u .v d Q 5 ~ 9  aZYG? 6QAVt/: PR[pLC12Feye[[]o3hEh|g+*DZ ]39|f)G;) : &    6 \4  / 8 Kd ]fowEccDllY(,S*gq!S "  h  } C %av[ @ r U 9V yJd4ogR@7-$/`Dc2ZoS:tCw>Ct8Kefn>s^S?4)2 0CB#K"S!f o   t $5 G -Z Y N  /    @ 7  .=  33>+,#VdM:3 4p? @ ^  . M& kv  fZTo~e[b>4m* **e> [p? F2ut}!!!@p3qkS,i#|\^ KA77 XK &^ | g+,S(f0 a a'9vim*y f  #> L  P<oElJ '8 D X N' Dd 'l"A_FjuQH6_LNuQY5J (rOVX9:}Yh3g>e3vXr{5[pwhZQY  ,p;u9 8G3N@"`g_I]hRh} D & B ^/ ]5=<Z  {   u(v{dMx\ @_ ( j 5 N NLO?FqV|}XD(5dgZ)WC+"Tn.+{55^(uK-(Pinx1&Hd(_MMOg[i7k~  0{ M MpO\Zr8 NX\M` <DlZx SC @ :   N 8& i 0@ a[xqgH ,7T S" g"! .U}4b/)[LY#\TK 6 / w MDHdT~) p?yC];|&rM6hn |/^] :," jd X <)] I9N\;HX p D cp ] \<E   N 1GTQ # ,9  Sp/1.  +   ,   j C (D#E}s- Y| eL{ޥ1 y5#}BD_2Q/MY2E| As("3p* kpZ X8LYr9 L } 6ZFpR W>S(ky+#S,/@F\Op IK>. S  } !V|)/js~<>e-<#d  5(@S   [Jl.w)G L- hS ? Br KP 4@H 6q+x #,o|oW}t&XY @(/c\`0{bPm:7:/or{+ Ae. & q 8 K P)  Sw { qP  ; c i }  hz  M  af   B  WQ QmG1`R 9EK88Cj)gL} MPd/w.bejiO0~h~m^^7?t8>8wVtrWch"q!B*ZP#b)1 )  Lm  C ^  u  U    E HT=}<"6Iu8jc \o  1 .P Y;. C4=?j1_lHx5H`gR$D&3uLFC>^WSLiVCpIb}  9 $/  xh "h , ` /< [[Q>?\%)5x\_TL[ N"_xt <^< ^hT@|-h1*$Wb)w.0P6,oQ ^, 7 "G x ~ pBX9x#i6}/\\Nj~T?P8كJeYߚvcJ NSU }  C g :i D# k N 8? R  N; Q ]f3   _-f/a B"sSA\Eb l=CGEh*Fl0-Gq.Yd}T !wd JFL*Sh4(}ntQxNN+sވ=mp 76 b  X   &7 #7ei  G) / s` r} htZg!$ S# ! j "'O.+" (" k R o7b +sj5p h 9 PQw$+yZ|\g6Ag0:>4F] M!H8Q^~ {,`(L v"xe"W?<f'A|^t4P7js-@P  G,e 'gZ#T4ior58F g8R9d,m uj<`^bye!Mg]`5x5_6}y\\kRHjk76tw}|`@6Hg F1C*  O|+-d##p q cA3} 6H4 )R  \ - }   v es Eg7%Sx uj!)6JNbW%7^I*PGSh VQ3q-y  5  W s:  iY K ?1,hSR[[fP5d \J[e# i  :f $ .@ J & ; &T " S  Z[u& ^=<V)8[C<v$f#+ GC?giDZ%.j.k7MH~jxqMhu65!>Jg+o#mS'P31q#t#u P ) y> D.nQ::E0:U472qM P0G; jO & 2d YlDm\ll2N[Mpo"s6tfY C 9 {@R~]K[7rQ%Rq4!u>Ij;#pcL= | RcWDB{ $p4 \5,GU!z z -[ ; R=PE8_ ^Q @[ZFa!Ei,iZ u3% Fs}F_  uvB S _O   2 Y4p Liw u%SXm(\FWGA}jWHN'   { F )1_MP%^X>a @  @ '  o 1  !0 ^ PF{~=O a8!  D /4 L ~`Zj 8A b IoJd_^  { \[(wl } ;<Y L S^   r L& 6G7 8}  qgq  Pi !+|[?c#L|BKWB XxK| %@|SA  yv  c kb . . @ : kiVM D!i Vy`@{,s3egH*w D ZqW2tB JSfGR_   ~Z 4[1  r =C   l ^ ]3Z  qV AxK : ~ e}Csk\{7`J,dct&|RpW:,LQr<-;[i:Wrua},o]av}|o&q6,{}8FB.HAo)NB V^ i g3?) D  u// $t :!(#Om" R' 6X_! k4 u 0 s _e{fpH >swh ?_Z:8 pgݰrgLY9h6f_\*0nC=9jW&,\H (;NH[__ B*@KZ jB     =\< Tj - P  C * a;C s E Y  i #E I  S  ^ a # j< =G  Lv & #; tS U a  b OB ' q X*Z#J&$LC/Km4Br"g&tV6\n(>e!NL7:?QPR4\3\X BE >}MbfEz=>Z)kF5g>[22Y fb!LV.N:WS?}px XR   s d la ~O3 kp q n @5QL{+y q  4|r6&k /@5(-<N}V@,'1h+)pEKtp:]T[JNKZFJVm5 CxMp3%XxP`@:{TG17ehy  s / F? }G U 6 { 9 $; y - qf,%2NR Rs5( N]t}JT>XcA+{ )<E |c U p  /Ns $  4 , Cr q T L6 YKg a9+}\5+Tw(> 8)'`or%`x<$FO[ c 0#J^?j5C!`9Nh_JyeC',@ ZN!-:Bf}?1.*yy]edf|qw9i N1u0h7~'vt8*Tr/#Prmc:p3 eZ XdG dq2h7{] Ke- NG  $ &Z3 E  K r J  rv!{ #KE  j 8\?6d .{`XXK(vcJZw]'d2s"F3G]s'rkS4k? d PC   `w x X $d  F$ } B 7  T ^ L  w %FOB 9[ T< h j-   k ,~ t 9`& , /+qkb3Nd3lY6# }nP\h_DE3O @ }fD> sC_hG"[n1lXZT9r:(C 7G\D '(-**Fl  : f  H!!c(**H*-*/K=15'1?12 21p0--N-+m(%M 6"F H 7z H 5r  |]C<}q:,ju1W^?9r~@m[PfYp-W&DI?!+C(4&c<7R tA|!!!ZS ];d Lq }if m C )Hl ".L- ! ys!d^&I]lR7^ u*OG / 3?KC!`:ci"nKDE,=@5sss=Oiu:NXݰ݉ܔ@߮s[ko3L:DYgqW#@}gP9 jG W. q m h |  L  <*# ~w? K ]<D*H\m 1  ( @ a 4 L : F  a j r B   g ;   [ t Xv N*oyQV$ ]`~  F NN @Qg+>)-+(-1AFo 6oB4*M Rd^ 0ZF-=I7 wRZn oP3 1X%B1 xLBy";/% k) @  -~`, q>Y[ s X M |  O ~(=`hs_Zh*G Z_{y3rJ7[#!+"eh=L2sP D:i9Mrs9+Yqp0bYJ!!, bD4eD6yOgXsS]  g S j  M t i$   Xsz  614~ UAd' l} g " [  N : :  h58T} & c*ml{frQ]v *_^Vxi.Q?rplx>ur| 7&5H)\` N3 X Z ts ? ]c ) Gi8T 6h8h>OSt9+[1x'T(~NAK]Px2Cw2-CKsj,iP/::O ^ Nl )H@N[ 3cxZFQ UL~  Q  u     3WkQ%" .%WL0~(Gj.IL1 Mx_L .   r+Ck;GJ}r7 >&'4S+i\gw*c GfF'}r*N)]w(b2)36 )rub-BoVd<fR[? #E)K  f  B r  g@D.%) 8 h g Y qxy?-B A 6jT X  q e F u 65  hdb e MJ j : xV^pj |F :>L f߸?SUr߸Wߚݺ7S%HA3z9trs?r?!Q p  7)\ T5HA[8"e y4 y%&%#(]'A&}$6$ #T""Z. R#O8VRKr,+ Lo J@e$MD|3y 9;>BD'*G<*Y\!sݦCr.5HR\4=[j,5&M t(cE*T)|se}M.L*R>PZc (  #l 0 XW k   ~[ & C< E)yl .gv D!@8UBx  W]+W 8$ #OSc[Z,!FN@o.f13Z3bN L#SGh] ugEM Wh r~B:`:8g|^jS[ \>L  `%? X X  *O 3 Xx]G[y5e!r * Ho SH NE U  A @d HG IH  gx N ^V*`^K7+w5NjZoo8f~_, F++Ha>/gg, m, & ] B W P ( ) , ?A`f>%D;d%oJ)p  D # A IG  u ;O/F_q|k@%bGH?|KLB#6~wB : |ddymk>&k:ToS!qh5}*WQqMX&OMTR?\tI| |"!Yob d7d,tg7rV,Jb8"c M  =NRNd*  _ BFYF)R],_7a q' D;:iAp?0gZ$^1qS5xDbbfdxxtlp avNr4FQq_5A8bAK- ]?OddwGEFS! 'SJ{jHq?m9tLxVo\/4 4}oj*NkJRqp@7 6%gN@\WD6X, _' fP 1Yt(,7-lC ?d SjT0)?VHt'vcciDr`9t-V|Qn5 fk4WL(A::3pK_#]RGP2 aO  ]  i$7#'-_Mtl*3 dR g T M U XL@4hxh//[G!Z]*7JsW7/X5Qx_wurMY)Rw) 3 )0lkcXWlttMMWT~/"sq8C%j^_RDG c D 0  2 3  ` &) W O  ~  X2 j - N D :y : N tiA N ` o ~  * !3 g RZxpxTd/[[M[Cee+5e 6 - + L  i l0x>O||Z38dWc [,H{~W-~8+gYn*ZRr]q4Jh 7 ^ r Fpw=29 {M4L=! 0 6  C s W k c - _\ T+   . M BdG?+@"TPW{g[xmdvmN [*hut~:w}xAiR+{fqS6")))38m._AW69Jvr*et8mJ{\[ 0n E $ C | l(mAKi6RRL3.  &  _  H_i_VUAB6?Ky.*L V L8O}<pA#rh:-w<T*5 {8 .   /SCZ1NS)R3k)`1YiOh[@y{g$6SYJ3S q  - ~r7Rs_B@r9VF&yt/q6Ki/>1;=7Q8IgDAD-0A'|0u/!B|L{;R6GCgZw' C j ![#qjBxdq!4   w  1 7Y    I q {O q S @<   \ T     O : @  M"<,9e`:( <Gf"Ais1WF'>pl!l N9+p_4K]p (s'T&,$R7qxFP(&T"8ho)\v b ~C % . s    ( N t i 8 * Z j   u 'q5c(n)dFwwZx*nf\!^g6%kA<}.! q~ & - u  t N< Zx>!Spr!~]kFr srjck cSdko;R+]B!f_UYf>V3#;NteFH'b7{H w8E  9P v U  K s T  " I {\  e   P w  S "   | 7  m LZ F ) `    :G(?3  6 ? g   uF @At:x |{`(n@^%E)oxf\oeFv7V#w o^P+( |wSj5T 5 t Ly#3e) m N . T S > ! r! "< " ," S" g" g" S"P ,! ! R rg T . B  / ycNwo + {#MFy$( p56q,Er^e^rR!,{??4>P3/Osk@%HT*5oPmm dl< XeC~KLM|)x+xS)8C0J!ZG\ N  S  7 S |+ry|  *g44* owy5 N ] V  ^ g   x  aNt4?s@AT89,:FQpp[P_c9 u: .E  ^ +;4cw D(EE;/99)/R Z |WcclyDo<&`20ML}VKA6rySQ d+51HuRR\&\Wf~yyGPDjM9iN4 x?367(_OvjCCt_76HevY;'( W#Z@H4Gy62Ti 't X  3 & Wo  f ! B } ] , # ^  @| gr h T 7 A - { I } 7L $  jW uD]E#3o[c4?%2RtN<F e[g<^lKU~VJepPQO3kS3yMG  c  . 9 8Z   ^{   u   , I+ "     " |H Q hP K1 7  C  . L}   t W i  a a; Q\y9t u\d Q R ,P7VD F^QXy!R,%M?Yyw)[<) wvOXbML}AK6x?<*bG8d#Z@gZ'!?1fNk ko/P%X8L^"qS!q\Ye 4 4     ^   q Z   ; O Y   ] D    | -  } $O  ~ &P  kx vy @FAe?wA*}H{Ks~[X(@risCW1u 5Sv|22 tkvOEEOm'b1`87S+MH{2uP7 ~  w5Q6 D  PQ ER 0%u H0!:"#$(%w&U&n' '("("A(L'''A&&%9$D #( ! _ y /8kxH"K&? DMEj\J2:|Q9 AD Ai8C3݉y1 ݓٗݝ?ݦݦt!Rߤ١A"ڳ5noEDWjߑ\xEvxY9-/4d :& ~  >! N  # {u/_}5Ar ;vT^l#)91PD=o q T A   F V<gdrxu-}C?]rs j=kx(*xz>fpG xd:t(s837]p_e)XD+E1  U-  Qm  k ]C m_YNKr#|s./NpO ) e K  9 _ N (E;PAMgAuYn #(9*5Jr}~fkzYw>] ( MXCthbon#<9"/fj[L 9ev\ He_ | HNIhsucB q 7  }iCo -~/kq!_rNH?+ Cg ]#C%P5~k$ED!4fS^7%/?''EN"e*y \$>rn `ON^/4#r W 6  ><>c9EP^dR!6 < H u  &      # B X  & r El@ "[yfT76C^E[L ^   . &_Oc LM@t1[VOiV#p!-. V76~\xxF@R=!)Y}rZK ({$&FMpLk B ' ^+ A B `(u U% _   u .9$H /^R~zTC3w   Z=O 'S  8A 7 . ~X  : _Q; jm,s9E\{d]+B8q%_BpS?qK~~ ^en>$CQ>& Bh xe_3! $b5] k e 8  ) _q Z* /  UhZO1gG(SS)|(#0D-( ! %`y! ? k:=otsi"5?Vv3wwt){ S{/_s&rl^3>T}@H+QktfYi6 ,  K w  b8`8?  ty "w #([!G ( (z&!n"TArT B s* Q p Q  " }   ' #w } J 7}to 5 # N A'9wEJ_3yQ^," < |P m  f[11n & g S | ] I 9 K{ }A M +)-ft k@i,E>(-B%ir߸RektA*D# )r.p{  ]\ %/9dFu  0' kt B } @4c|N|T7i90= I ,G$ 9L }  " +06k B EWucfg"DM۩DsyԓӱNҕ:*X2Xc8\u C87@ I4H tNޒd|" (L]RObb-~emA 4 &  ~zZvf! +" H#!`%%~$#E "$"<"s$uo w" 5!e"B$k&1'r&$))R ' $"&! $ o$h#kg:"M~  #l 6"!P8l]w  ?srl`\U^hX{s%XZpޒ(ܱw׭eՈږLUؘ)ܻ١ԺEL4f3Q{PENDp0Bo_D\iy-p. : r   " ,$k$|#b}'^'&U%]$u #6$ `%"") y"&s 7!r#;%V%t$"w&$a!xMt`  A5} ho %H{3?C ,o`Zg)yOHVh\|uk#}Vk3PoZ;KCQ(;rcG88e {s}4t _H, L*"! +euU8ry ?d | sK uTw#R)Yo< .15_hK'3Z?O,%\8SD=W|@xYs'_C5R@   ;J7 ! }  A!T3V R"*O ~ k  uO  @ ] p T[ - A_ /  7    rd?  ]E +Zdl>  I  a+\e\? $ B U  XR 08 : k D :  C L 5 s  , + ^ 8  &x?.d '-'q[> _! *e2W.m>GM6} iJ.eKMv " c]% ZM'[q5uRX`#8<K|%h{ QPkgx : 6>_5b . buq1R _epB%l ![HHe(3J(\Qr%gXOGyB \u8|Xg3'1!d8P  9 lFlP $ {md _ i 0 a .:S###" fN!GB  6 mn)jT@&Cb|krCr,#g.>,(]O!fw|4޹(Yr@&,!6W ! ~Y6 6vP0xNZ6j;'89?\oDArq`$'G$ab#q#S![olF :1 0Z    :Z s]y{p  C  j mx|3f^}.;\(ZE\JeXdWbZQ7z9\)P QYTҁ9@idxrޯ2O t X1\v '"<#("w !d"2X! :EN.!$%$&&B&**)!%G)&3# fq  K   k9[!\K+4V]W@Rs"P}LK6i . & 9 rs>: >?)pH& gTo|f*t 0+P:!6zx u  e10=1F~p@LOX 0  b 5lY 0 M !Q! "!xoed.}^  } W6Z-)\P987i:>;[Z&ZA'*[V-zJEy\S^XRll r:'&}hXvgK\bD#L%uHNf4RPzb7g W JB5s@W 0\kTM^'-.L e +y< : b sWNAx l B  O3akW 7&%M(!x   6m /w iQ?X$e4'ddD/*)/GS /Gg _qVJ@%^[&<`f Pd .  <3YYmVGbp"%CT#C$vE@?g#`cqH&kkr)aw.XN4bN_`p}2pi`vP6MpfWh3oC(T6}AP ,[ IdE   #%" f,\+)%l(<&%$$!Hm=pP7^y  / 0E* I9  /fg-ou; Jddo=d>Z E\d.xw)}*v ږo(O4;g=Ѝ1(} ָ٫V܊$%b  /n #*&(, ( ',b+*$)(|'r%!x~:P+` $ 8 L  a{ 9 7#"2q0q3~G U^F2 iTBs|+vWSp!XB& $ I ~mao9cܧ*&MӊեX̹}$կs25~BSeC'xT*lnsK/hxg kv 9 qZfY*[  #l)P*e*x"'*x.j-,,*Q)f%5&U4#1p!e*.+*G(qA#U GQ~5;0#  Umd  #]WMFDyvݺ\bڪ֑Зb֚\J;LևBۋ4"w??ǫrb׏ ua P~ 9Ms&tT"}rJZf@   B)Z3m S"YPDx8QB+a S k LZ2<"?*~ '*7}US !!_!4&I"2 ?F~Oi!;|\ s^bhO_@kݓ<%r ߚڂc֮] i%JDb݉ Xu7 &,Prw9,9J׏ aܞ  ,yKOPV?\m< 1me  u# .  W[bcl 8 & : W @ L 4 ap_ 7o$u\% %/#%$N^""PD 7hJ5 /}~VJF><* D E ;ZneT|ݦ~]$*j? - 5 o#XdRsepq,}۲ܻ^Xw?ہRݦߤu!aufcVxQy!, qZ /[ {vd4('7!AB$9E W  >"#<#;%%%M#7$Wh# r![6MlH  VRKbf}I~]q*5 w s S @& 4FZ}tYY^.edK~>d6Bll V |   :+h*X 1  g| }5  @+* *  dw  z   | /  %p 0[Q\H?}`v?*&M:|VV6S@_h!*YF+ 4.SE6[DR&ER` ~h  g  ub ^Xeu9N,GP ]H5u|"z.J>6edE+lX ) tOWFjE^6cfA-bt ) 0H 'aQ We& V#S B &(,x~&L^F^4sCJ([xF4 L 3 )   UW]td}{m& 8= t j  y u~}m Ut7 _ TvlXq"-/HET>)-\O(3  w W { A%d{6M1&`\7#3!Z}-T~,c WJ?x![EVW>nVPQ)/@F{]Wb^>`R3 wM M W  u{Re k [S]qR_W\VC* 3h'njF5/y~G][--KS+?#w.:B O1$E1GWP X `3- S , e7kBq~ty# h p{~ C3km1]Fd de< xon'X\P%$W HF  g rv(H  6 M L A  x I4  " U$\"  ~ G8K]=`k&uOnMyNtA%\ b,8; j@j4jg7"J%Vm# + j}L Zh*7 hDb"-+(]/!3&il" X Rcm].x,KuR !^k2 N\RSv?5 R URfTdT B[H9h'kFGs $  ' S *LixKi? {>.!n""Y y%#Y' e#sCKp p h h TG$@TBq-w63wJR-?^ } W iJ`"`:~,.@"])eNf @kj5'~xQ^jk%CyKfWYCKBBBe)]QLCrowyd@Jv S 03 6#w<;I|GqF l  &  r R - `dyg  6 & c O N /+q>Dyun|( GB:6_1[Rfv.#VH3%Z8j)s8H( "~ #b&c&}S2f D3 13-N<3(2yn.C%(6#' f#' R}e~[(+ 7 K4!/wB r?   Wm ] 6Ui ^F { Gl u[oE?-Q JAX`'B21N3Lz'^SDNvܻݺbވߚ  XsK))9s]vf/n7{S6mjBg : c  |    La  ~ /3    O  s6 N mIFPM=""Zm X!  Kq  T f!ig#V ")_"2()_* 7)5-,*4m'A'$ {%|l a G [O,Pk,Fs^Ib(q4|0D1#*+7buhQ+ L1DRvM%l~+_ %_Vyo,5..#yo1 7i!3ysVoM),7|  (lr    # L&s 8$;,36 U zezp  _C,%!BMRi7# a  C  3) k_fdD N ?  Uv<(ݓ|Bn h :֤ԓY}j/Ͽ*կ̹uі,NgM9+}cw3l)FWs]_ {!Y  L  k ]T .R k  :<o9<z9 >!Qd')*'#1',*='{#" !4 R    I< #  # M  0@j[ 7!r`w i*9 v X!cJ\WF$>\) k 1eSW<&Lgۼ.P[>QL_b Q4lPh&gG X\  (FS >!n"! "Zi b 661$v; 5;mQ  1s/y~tyF! X   pG) M OHH b@zN4wng h"SH k B %WQ [1HX i V N>qg~/5 P @  9 lBw{*Fg  #G#A81ftoyF . DF HOZe(9T|s+b$g)>' Ge f\~4 _ cPQjq.S k f?%dd@ %x  rP ,-hHS!D})3!X'0C<*M|~dX;k( dd h-BC/N>g+3   :>H~r;e"}i.?fx SyLNFxy  U  >]@_e5[1[ [? \ &He*_g:H$<1_"-<x MS BJ  f2 g  9 & t    th   C D JcLwH^\!d~WhH;:hAJ_f7 W $8  >  9:ET*H{/+|Ax F}SL (]t&R!,6+)Zf9 :Bj,+Z} lx2BdgPG>.3f\c= I}  v*'b8ZiwNd1xV@O q AOm k `  # L &<} NT5sok3h >@)6g@Ky*y*d{Eo AoHGXdB!j !$[r +5 PfO;  } r- jre0/k(F B ;\ M|Wg!p'kJEL . r W! L(!.jt \33KM@_"Z4J?{/^z6f@fx;+Hji&38i6  QQH I < [ }k& / p"'~; *G C v 8- IC  6=   U? f   0  |e # U  : Sl r b [o:@xw/lo.18Zxc  Tk Ko  ~ m afo*iy)5Gi4 tj W   d%YJr:<fye " P[f-'Z<`L/-8sCvF\o,)-xa3OO*Q>8PTb%hqvl@[uerTm o2. +   &  ge@)QvTYkN;$N#f!"#v!x"D x  #   . ~s   ' . H  UT XLQwi6Wgp\`1% aD3'd c&Mm':as1$kg':Z2(v.kSWE|J[[  } ,o{y  @ SfQ  ue avl1<< \!  >  "   9 a X !d ]J_H\SsBhsNjXY"wO3Z O"P&}4wwGoZ4"qqbr-rdvq,9M^s-Eq{M5 &?W]kjh/RO / D #u}Kd<ZZ: +[X|L@B6D -9"x  N U  ^4  } F+y|/MZXx[?o?3dq lt;2d[!fSf6,",S]|{rq .KqG&3%v7WR4@ wY^53?qf<g|<B2icc/b C DN 0'N 'b|9bMt~:Cu:Py e< w'f/4`Qd/C4}wb< <box+Hqp*xN[< 7~%L{{[@ j ~   B j   N m F  , CJ   L >~fCb`bbd[k\v"7/M:kMvLqHq rdVB_.KBqKF^ ' a! 2 ^  A!<:P^Eoaj  ^  ]p@[ywg/`/%c Z K 8 2 g  -- A jpQdzI4a,b(wHb V8 ޯH.,޹ݝAޥ|~/ޛޥJ,'5jO_-,Zv/>\Q`!O+~Vi}r  4bYL|}6p*6+4Z5Ea;V} ks    .  ^ gfo~w9(q^0P} ]. 9 &k ;+ C \ VPk")`xM/ FJg7%0z1r7isjsVA"SqNPb/7p)D+DgL  X a . .7 ^ .h -   I A  ]    h3 KF < L   O2ZE); 0F k   CP M & 9  5 t4 q  C ~@ W ] u" a^ X 'C2`u;<HfA_Vj7wyg+J]'gR"S-Ai`(\ Z)\9ZM;rtb$6fQq~u`RL+K|)F k3  ~  +E FPIc<rP1< 7 ] ^ r  / t0  :( X<G \ J B h 0 "9DLM DZo4{"r@~W2 r% /2V#T]2sppB.iAg]5Sg DC*\MjrA{m 8 Tj # ]mq:p).)BZ |c 0 H  t  y BH T r   @6 h 5p`  6  { u  q  | K  _t 4 XQmT&9b2x& `#&h&Z4qtWq=76o6d\ [e ;DsiTh en2:Bq,%H-3   s   R y K[  I< 1\pDjMPBU$LBU'(UDWDk(Xwp         bdp#8W7Pb,p8gi2BFW> l6|oioW!1!IB\N$ t}7K'a\V4=IWbn|CF<J-dCK ; U qw v0u_@x43fM mdMFd^<x_\9/@B tP=c\d@Q-!  M 9  :G I   o<}?PB/Rs {#tu;OE3gKCw'ZYsH/VLBe cXV -@p3W5#S25 N  h  ? XP XY   t ^ z  8 5 # # P ^ K T  ; ^N  = [   ~ u :  NX   h {oK-jufd7kG+S,6^rA/Ojo[0\b|0kk:D1D`9Dki98KS+![* *[%o^gNJo:_"|hTQF{"YK M@ i"  K ]#5ohgB M99s|M]&6X)brX"u}~cdKKs-    ~# kK>A>"rL/-u<AGT-f,BV8VtD;w1\g_"@cp6S=J* 1!+Xbg^\?E4B*.* '~~,,! N ` Wy  x s } -  SeZ HpZ 5x qQ >   A fQ { " L^  D  o  X\q5T57-4G4|?1MCt2cs T,L5xqTGq   Z   g DcMNM r'a8KO8/H I K 4 C= a  B ]:s*s"d!^sL}}W1:c;x i1&Xtu+9p UE& TQ Vix1W   B   K ]  6Rf SQ[ep fe? \ ?  A a sE sZ e `    K /P<)++-p]7r8|$MM9 NRl d)3`R+wg@3@g[5! !Q?4GkcDu|H>>+f3 N  &   : Kt  @ ]  =Rdy5 W B $ $ L r u K I; @w    @ 6  | # h _ W t M k p)k[gb@%_7s&WD&+*r_o-lL)kP4Z ~KXiEg@q" eOB3_!p!\yJf6 {8jX^L8M}BS@'fAK"wF X  ` ] U r $ r . &  d[3Zoe dE+ : P N p/jFDnd k(K*.dB:\0x 9 > vpoex1q4BQx[bx_~N'e5d+L#E;qunb`V.8Wmh4 B g .)  T P  q ) # # C  '   g  9O3F)K ;gPdwF> d< ^X~t.1Q  &~ `  B ix $I  ( k>m>w;>v& 9G9Y8FW#6 `R a_; DM|i}RAM29FY AN.   L :h y `(4wfZ j B@ s Tc    o Ul Lc  ! :  F   e _ yG  Dve | # jVj[@AR :! 9'WekT(g/  -  ] ?o=@  4 j CH~ 7 C'm+rS)u`_I|?} b4R~+df.FytfPH&G \ wJYhvs4߇ N Uض ڪGL!u >$W%%W# ' 'l$#( "!'w  W(c>1qP K  } n Q  F}wm 5+Bq &fhT&^Vs~]rܧ2!DdM}-0݉d۲U-ߑ߇GQu=Kl&d*4>'E? O2M:~1@Q )  $ ,% 2_43 .C8B5q0*GW($:9 A " p =]<KA7hcYfY h , )    p*X<\ 4 I 8Mؘٗ/XٵK9#oZ(FYdG>{+T ZN 26 :lWܱ ZUYݓDq3 W}>  e  ~ R#,E.07`077/6d3  .0-+)  )rx { aX ^ I  S ?fyM-ni<A:%? / kkQ 9?M١ߚ٫HD׏CB<י)fҁڽυv֮ږi0x`By, fd5 Y3: "X  u s ]"W Ar t5f X{(g'$z! H66$t)Cp+7OC%PD  &f4{v6`F I Z  g3  h jkGQxJ +~:pb@,4WaD`NN'A05$DέcVL^O׆N~k3 ] " . r3 Y,G@L?8۟hON%1(P y'3Y -f /%\s o%![(#*",1%C/s"-&(n+)f%  f  \e=<#$+# $#v"< U)i@gyo kF :p &~ R vX  X ,hq)8# X~ ~"P9(s[<  C qs,* Q;P;{.@LgM#'b41x()eRis1FG5RcCPX=P-WCGr:-!^sA"@3dbK>3 G &) B% S. y  > @ s ,>V7Q<+4 r?$.[%M* -\,l8sA86ky2 |8s5B2H.)'&("2 u T  yWg .5Jg"!kbHE, `d;6d7<ض7V:r2M }@W4vߑ,hmZ=O8@d !".V 6M[:'7#? iWnyR[%~ $ |_[$g!# $ %% y$a$%$#v $ Zo q ~G[ +3EP >>(AV;AF?[@ 'o~[ڪB ;I('C:O` '*"ك׏١vN>ڪi^  g6aXw 1  mj5{<- O ILco2 X qXlmVS-%s f j>(Z^RXg[f[r~M!ZE&Hy\ y10u wn7|FU81)   dC m^* 2q  k|  S u [ s   "gF&W$2y{[h&/|rjtKN29XcY:{ WuF0*r(! W  mfF  S S 8* $)E9R<~LY T=Y`z?^t* 5!"<#v# R" +#9" ,YO B?W7 q}uT\rZnX3 F 2 k )a a Q (ZZ}>7(L7N2H'gQL.S"c y \*7 i  g njJJc{7R1iu$Gn)3b.)[O M h  c S     H K Q7 P<% 4  ~7* x rs tI $7 : }7 5%Qa  i @c K) \ | ?HH }U( h lH /`A-v9v*&3b{pT Zyv,UdlR K _  o<1!)pX_}vw|..8'[C} 'V8B31P. tA 3qq'N_wzMdy,p:g @ & */ MH!4\) YWe3 XM!+6P{2>h܊5SKLe15 >BTp-`i<~"  t 7 (h' {o h :.{X$bv9$}9\ U6KK)#?#Y 6 o #!  " ^Y l Q]{q}3)WQ l- E{bf C|q/W=r't  a kg 6YvD. AC,w   7 q 5 6 d5   u  Xi\ 5    ,?  B - Q T ~a)E! L4B.w*)!@DSԝWNչ~7Qكw0D8wun&]^kShM >kvP,Z>rjU,H?( uq//e2  a */01!9"w: ;>8 ::8h52! ./8 .C .B%$W$a%/9"-mV w ]mzs.$k# $ $ S%t %~ $ ") " T<y [:U1 #nR(EO ~8mVrXL.q@~\ s / 0FhY#g;u.L D  kR* TNk[SRqWvLN&ASx39|PLR g4  FP* k ?em)~$N<"Y@ &U R$: !@7sYXtpN ke M ~  S x 6vG_P r L ]G5$ @ B < , jmPM,/xX͇۟]-Ǎs;Ck`եLNW^=u I۲h)(Jv&Bu=cj. {f9#m!Z? x)l Hm  u{E!$'-<)o '"*[, C/1]0^1-2<4<g4"<2"1,%2,v1,v.*e($u* -&*Q$k%9T"l5v _ G r;1T  D) . n@PH)?iu'N)k*<}Qc2(:j9i&Tָp&\Qx;u h)< Sj X6">"B {te+\+8v@fRhrh i!e%J'?&8.0.9Q*x-.`, /(S% fk * 7* }D + fwcP_tJ?RWg p= ! @v! UddsN-! ?  ( +Z :e _<r BpF JR>7/v wX*6Sk)oRY \c rE \ CrbD\6N@~9KXgK[  @7q`!t$N%T,1+*U&m, r) '# F4}Bd=R R>*m+Hp|gv{Q   } >*kx 5,sV GwEMPK$qk}]N||A;e7 B.QE ~ CMS\ ҁ ] <Зp?|dI6c_xhl`Ch4  ~,1,z&!L$| 3y lpZ U ]YY-<1))fZ' >+`) k!!- "0 Y4I\*m K 38gd>d4FGqAu!A xe twM} 5 9 9 !nA!4#&x%I"'{!lm   ]C,e8DC6vgdBn+q>po')n*__4}\ݺ-߮MMB={1$g׭2*тB  7L )<\ } *4!R"{"PKuV J Ko  gx( ~< "#Y) +%- '-:'-2633522f/*=1?6-1z)+#1" 5+Lt 8&*TbR*%X~WQ6%r5kܔיg|̹cMƬS"ߑݝ&1ΆS٫h*!ڪ(\oA%G1AjJ8u &BoR u a( a F| HN~(`UiUtJ7YHf4 7 B S{ M 6{> j")+(~'W"*U&s![ ! s  {h 'u,- 5 PifSYT?_yzq]+%^fMd["?PN>868.^-Q6[!-q\9;33V  am< 0P }a}Q9?S<[ Y NMlj@cE |5v@Q+' FL~O+}V)>) $a'&}DN iWfPdLQuVC*Psw#$S*e  \<ju g&8 C&K%2" '-#G"~"< ' diM^ s _ SZ#XH^@t$?@9^ V ] h  W 9]dGX5  }|J Vy6XRq7?m$N"YUHD># V 9  9  -c)i) I r,* 7 k g9G ;*q$5Sxr&!4N"# 0**+&F 5Z% "  gZ N  < 4<>]~IFJ7P'ە(ܧH{/>?@ 0rDZYi(tC7` }. 0 '6PRd i t `/^ .C *?Ko1Di#,{  ^=  %$tY^"'#Y*!=+*302]0v+ /8+2'#h$0 ( N`gFD 'i 5I3 CQ foP!:sP{Xa1mݺ@BNw ;XIl%"Kd> *Q4y%\a6}l K"Sry|Hxw M {*S7d*:!=#1 &# &$ ) #+Z )f &K(6&.Z$&! J7 ~  ]>]#p}S:dk7b8 j5Rx4 V<|bq W  9 7{ 0 :cW?@ %Y~/r&K_:=Hit!4FlTPofp_.Q &dF# ?>5  c'I /3Z'(R_] I :x `n - d @ S K E@ D8  s0o8 Co oZ+)OK"Jd&] W y6 Id$@^m"R!Grq6Vry{*ReVyHl5R>3l ZW8_&y 5iE^P><o%1 V:{En1'=4b$vdZ R7"P@.+H$&T~!    Jc;'Roy3`g_[Jy&of2 ggjL/|^;s8/El-:9 # 7 ~  ` yu.(}-o@XZA<oi{$]bE5Jricdd4I *pU 5 slHM*+@H<5;b/b!V|)pBocA5h9~D,A  : $\ s ^S " $W N" /-)R'!,?**%) R@V :P6)hoy!36C[ : 6?t ?G8KV*t 7 :VU wj^bi#R6}  $ }2 S  w~#}x"G{-Hy L3 jF  u|..[i_A_hY2jj#0A١GۋgU!RQrܱ%f)=alYIvqPqP! :  Sl i hHPBv9BHZGv4y k t ! # -x   b X 6!X9 Le  ibkl_oWGd _yORt+fC] E>w.tt#`M&rmHRX/qANDsj  /7 =Wi" a! e + P00  d  A 94{bC,p 0wjQC egxt 9# i""<< !"(!)5 &B"T&$x"rzo   h 9ݦڠ.@٫ٍ5ybۋp1-ޯo!pw+67QP7 rZ][]r\ [p5&g l un%'z|WPe8MxtkS<Vg F "y "e f w 6.;  @M/!A" !xY8 >!p%;&& '(+'(6(I''A%" RR>]Pb%HeOp  R i `IH"  -.\ r S N gSBc \!=ACMt"W[4[GCm OsڂFc+؎|ږryvkK%4_bec _ :   m 9;cHy   T "Ql)b ayf *H  " `H!&(,22\_32087C M4m /s D0T- + )P g  as -!Ty+5rr`G[BRDP"ݰ.ܞޛTIt^ָՈ*yv/6PJ<^u fS)JgprTV!#(c k   : A    # N  a > #v t") j h  a;lm S+]U#"N{+P k" { #!Q H X 0 _ V CPY l8b@Tx??^*G,5_-P1hh _ -. ߤ i D sqڳF"XSjKQf0$`3dm@oV{P5FwmWj~jtVZbu t  F5ZwY_ V54  r' : @  d5l\  L K/ { 6+[p B " +  6 S @\w KN r!e -lR _ B { H Y N?Z\"^unZAY8h*e?xl+|kY3P[@gA\|\x"P4,Le\e~-h7`]J d+ $ b qwjwEr j # -\i+3_^Q$/3we , 7R q x { }  ~G S   @ + F q I  j  K 7 '[Z5W3&65ZZy=^-i%87@0MamFc\sGK q;,'A97"pd < k 8  t C Le h 7 W+PB/UN}nb;#d ! $   L  A+?@^kDA!Ah.n*<[epT7"6J++(>]:{/.`\R4 9N <p X a[EPH+ T< {Z!3 fHR< qF r3 7 R 6W $ : u)7 . & t  L  t$ ` F58Gii, riZK@BK{B|_\VT-sF8W p2wKsSf\r^q R6)4kljD9/BsG(+@G;<{ L)m1G'G$epFx}[ : 3?feh*y:tD;&8%NwN ]QN 7? ! h g, ,*P3* 08K\T } * Q G* &o~;Bi>F#O.c|].J]KuYJVK@VSR7Rh>GM B 7g ~ BlA c   Wo  |@ A _{    K   jq  i@ N j Ue . L  ) o # \  ^ #     B $<\oJ }Ar7R?pJ2|9w3o4T|i~` g,+*-?s?:,4s@f5 '  q!xe ~ ` ivcY9n^lz  "!"""c""#$0#;#O""Z ! H!! :wH?uWY  kZ   (?`\fCuf Rtvg,~>kwq>d>*yQP3ZmROOt'q*.^V(tDL+PDS*E u S  6 %Eh 0=<}PU;i86Y)1(Rm  , Ko K 3 N  g : g Sv A ` /  D  ' aS  )  Bdk.$kO?*,4syyz/-vt*yEjD0-lP )o*R,FC>}w ]wFd=x\G<: [F(2kbPc  H 5 Nv Yc w=c rE E P  J"f7!s628xq7:Yu9M=%Qf,cJ%fyT]Z3/$F^c 'c a D / T . U4  D S # I  p _  v 9Dx 8\5 iy ] i^ o H*utLeqV:& eIqg! ]69neoSAR7z"H enck':.J9D" '+ :  r  5 a7,1yC'U8K.,@gq H f Q ]6#89FRQ , /   h . ~ &X2' {y&{NjDWYG H#@iT#A;hK5V{6Xn 3$8`WkuOMuC/9wt4d) <:1T>F   X| H  p   QS!e{=g \ 6p |+ f  d s   H    o avQ Qx G  @e H  $ N("m#"m5K`Rif]bA{@Kjb$l.gR5y]---y;R PHJK sddn)dk` M`$CAhi{q3'#ih{VD_}  ~ # #y G |: b D A ^ $    } _, i, f -    `* > x /m    e      uP : k    W } r?  FQ)fP ]  d o f  q j t JE. k & 9% 0yop+KBWWbb&XEt&G8$W,+gETSJKJ@BR fc2 +eJ6&i+ e)YPd D8C`RVE"bp?;c4   r -/  7  |6  C) E 4   7 6M <\yP I Q rf Q 0 g S TE_ i T ]Wy ki'Tse^ T |i _L 8 }O\vCn'cQ ,[4eppf1l e 9/@@h_jS6 & )+VAj7ipe3J1_, .;_%}%MvC[!Q=  fzhx C @ # 1 Qw 4[p@X D"P} ] ^v l@s.'P3|)%9CiFR4+?wpJy,H"?6eR:5"|6wq$f4L.|F p U   ,yGqQ3w uf j g {  # 8  -    6  RB 6  ] ' _ tiOLBVp!t<[> I # CH 0P[1[Z+',BL*Nir ;d */iA`kk5 H+nGwDDuo883i2X7jLBs,o6J -&{L*@  i" @]34F@Q* <  `E! $ $0 N%~ W& ) *[ 7* |+ * ,v5,p,5***'$N$k0!n%MeBc  M= q U Wo76w.`464aL:jCZE oږ۟*pJrڪ٫dߑ4}ہ,ݰsrCYL-$5N Be6q > dmM6x:E A  !x#%/$U$D^#$$P$0v#vX"# !n!  M*08D5H  ]8 sX   R s u >Yjmppg_<dK:E C2]+o6 %`01cmW(Kt07[K4+",8'%Nk9rf[t s kT ^d + R , |& KV c  * %   `F N pc AO  { ? q A \ yd.l~ 3) He K . _2mk [A)y|Tg/_ p>6 H=)b'cW^N4Mx^&hq tCe1XK3<0f\4H4GwD~hb'~QA|, `Z;( & ^ 0 Cx2m `F C} W} i     MH  }  a ' X  : "   \  U * }x #  KXR E  t t Q! w   L s- #P@ hdx8  il 0CpqHMG > uoE|- ^U |reIf_2JLAmf94v0}`A-SnH Q>}pK-L8p P6uyG\HՒ(7n0{Qf:y14  qE G[mwgw%cm S  d[|`YR>WxRs* bNi^!IK' $g!6V8[G! y(g'LSNti~y :  qH[`3@ hOi_ Dr %N u ږܧ{9i]H\ף h0 MkLkSQ*4HR5n A0YPK= g vCz9dtBK_Mh+N  KG$P)>E/.4< 5! A#EE"D!@CgF"C? o@};4,+ ( 0J~8EgYw!lH[}'֑AٍP_P6b~{>rDmGlwiQݝ۲ϿkʀʊF2È!B*75Mɼ;RS} J  /YNg1w}+ ) & 7p8K\4j^ws ]10 - O;-z$*,OS-W<*=2 > <= Ex|B&C??==FF:6635t2 -&(g%~!t   ~M # lO+]~ #>-;g%O+ W B! " U1 E,/HևL>a\A\b޾۩ܱC+f*-ЄR7hk5t v+#`$N"a'% l@n! I ` }0 t/F R "m"#1&8'),+c,07R2!f0)_-A)$sg"X\_90+]5DOiq 95q3LB%|m3\BCw;~&]ӱ'ϢŐ"3 Y~H|c4u"B } } Jg+J ? @L7%-آj١cOہYM+B(xS4} 6P*n$,#*!e"9+)))>+z#"<8,;1 P?v=^ zl  &4 M Mi*Co8=# A+GZ'm]p w i5p@Hr <`K\-*JS{p{G~8Hq63_>Wh ZIJ2'C)TLAVnX@ۋ(тج9]LWLHW /!e /" ~T # -#1 ! L!   * !w  @ unL~JQkBxf#s+D 8 \+)S(%9?/)uM ] ~  p uu#M(J[%Ə#mT.AтW)<:M2d 9  '5x _ 8\`]~\AߤQߤѽW '&]%"0!D\yc/g*d-W 16 .774c2 525/ 33 7+)y) 1s!e /<` hj )! )y:%V +?) ' # "2 !w#ddFd) &v1 N' YuCnbL&i%Gp9i[4ʻ\Pج֚X׭ۋHjH3Q     k3v @ A<  ^ B}tbOs?c{A]y D o @ YG.M!"'hZ#E)49 -kY߸SrsC)Ոܱ]0~7Z   `#A u2x- Ti 9 N: (MDDl X Ec%a" fz") a! XO[`&' & !d#!Nt [gL<+-29 HKs()#"86<8[8"y$D *f H SEd[G\^syX !Zq ,7 ߮p@(ARH*-bfP bgMj#   3xBef^*pfQ| ~*,XYC h]?   iH!"!!!*C*x*)f)&'(6&&_$D"!"w#Q%P;Z=]! )kje>o!fNo>GR~1/}*| .s  f 8 Np%|e5n3 JB{=m۩Az=ЫlYLMӻ)Ւ p [\,'^$ wL a 5^oB'' Q5VH* "{"9rB% d1l" # i#  5 (?&Kf# @!*{we h 8 Q~ ^  ~ JfS>>P\Phbq `FY_B.rH - $wC^~DytwqQٵڠ'IFvFgPRs~A<< D [ h u  m  v  sx8eqZ   e  r <   /kraFZ_;hN .# " aG 5CJ5 'fY^0()߮ض~&gn"Mdr& q.(:J7[ ugLex8M BX֚j]q8կ֤4F<7^B)KdP . qV<Lb"w?!!QS#U4)d D .  v5-LyC>O ' _ eMkp<h #Y!"$k- o D wGC/ 3P:DmuX >,F 9g\`  6 4* *|i4Ew jvJ~;_8',L_Kk`@h6 3  k  | a!oAk$  ? ]{&yPܔd*ضJܧX߮і?O~ KNc/BO:'ZwK | y3KXpڪZ6$O ] j ;)+J,Y!-#O3+3-4+w4(3/1,.,**'T$%V% "a A PH>v\6yx+Hd/  T 2 Y#-|8n_hہbڌڌw}կD6o '~?:ٍDpy2ҋ1m w nJu 4# $ g# { ]&8Z#EPg1t ) 0 $1t]r\")! ! ' {'75%y$N$%~U$"$&$k@$"$"k 6mLxG L?w}] T 8*B}Eڌۼ߸Dg4')[ҩmqn.qQ } ,8 |S j!F   &?[i)IoF=&rM,Ls$:$"F $##Y" 5*r5OZ454m (G iJ5,}{Z M4Nm\eFsrjj  SBP?vdPyf / 36XXxF#Tok@8J"!A ߇>-S/8WSK;`Obt KmEO }Z~DDu _MG{rLD {-5?D @#Z"^=^~ 0 .  #5 jm~,=aі ɲ< ܊ؿALS Z9{m\% % ,$ H o. ) g / _ 7 k3 t\ .@G* &x1@  } y  "  I~ ^g R @ c8K!_rVI s5QpbQPZ]֮$كK*qܻ49Dk "Vp-**pk * N#oB2"jE< ^!liw7coCt@ y]$D1dv03  d7g s q ݦ,Q߇K=Uc%y!2T.~ ~f=g t dHr|PWt0 K }kP c jK)y4= \7*!*C"Py1zO4w1 , 3G2/0u-X(g'{P)!-ruu YPE=o Bq sLBQ[ WN &Cgo))~3B. KV T}' L XoF]~gFSߤپ,ř%_㪻ٿ79٫2 aPvHO-TC,  N#1 s ,!x u%r !4!G#4&5!6!z;Cr ; n;O%t8,5;okCG GETT?SPiVS"L!=FC%`=$3q+:* `WG469ٵ١zgyӔԦ:ؿfۋޛrRt* p'Ͽ;-))Sǡaɼŭu[qJgƢɩAFоZկgsacD  1 D  !Q(S.)yt)+.5.* %9$ # #oG<O-5: Yu+"  (i u# -u 0 25 "=A$ @/;y$Cy@m;1340b)+"zv=/ 'd x 2OSAoݰeR׭[fUܧdBٗESڪcO@7#s@L^^O{2hw+ވ#{tu<E$>7åHǵӀ.0>ݦ+rqo*"uk#%M %/ ' T( &$uMAA xPe,5W=* R j k2V ka "2 y "#O#1 "m x<mSA: S Q  tB[L ""uJ ZPہ)>  'H sF 6 \ 3Q*^bqyv[ԝԉe,̥XΙ=϶ѽd]9Ze^~K`2R?E H# R$M"w1A0-**h a#( $Zj@W" a-(<cf8'J&O$:(R'#%%$0X! R o!![%"2#g#"_"" ]`P {a ?iևA-]ҁtdWC ?e a  !A#O" `:   X VSe"@6N5{FnA F ~Qi P  `QBW ;u0 D  DK}"`~(9k?':I /?::61*%["3 i .jQVqݰfb| ,),)>14w16+w!e$!Q Vj%?LBti1dkp(Nآ>ԝ37ЍAQ-Ȍ&t X<h@,/. }) 86a0(q" +Z&}#  %9;9 Wp|#'J'#0-1 0r- 0J&B.*Q-+0;4'=w&0A) #mBy v $K84֚JX{=yǫX핾+Խ)nK~  a( -#%'f2>S2/')5v1i,+' \T~  & ^{~?-~fQk Mm''T*j,=3a4P6D2y :28.5.t.~4* %9K O?|; ~%vD-I: isڂ|GH!ssLX {! ho_y]v[V ga f4 ΐc1K)J*)x5cQV k^ }fm C #E i$ & W. ].+mZ# 'r"? T# (R:jJ.yD\Ml i(jF_I%ۼs,ʔG̒mrm tRѪҩyږKSD<G~ d@d4   r A* B "  T)@D9D?gcj7y""{|\FޛsQI!*Wp%N&U$$u"^%%Mu $h(Xm ږ`t٫ܻza=qVԉ_L>ܞAף=׏ݰP0E ~ q:x # > ] #5#  U 7{? *K91I$1!W 5xFk ݺ\5K f)00rm,s7(]5*1g)!)$) /".+$a :%/|!Q8kZ&f IN:X4LNGW 9xF"#;- /.C)2f,o&g#jZC? [ضNR݉R&ߚdpԝmOU߮5!|CIR[X3tW~&),S {=  ^ 9 :  ( Qe DZNX,cYRilTH]KڠD4gވn- H5(C/ s!4""%`%0" o Ee-wZ  / :  M>+'Zxs\F~P Vu(Z-02!?aS?E@R?:FD A S6 ?"2!i% g%#Y  $ " #@ (Q/p  .5aK# "Z##(122078_8.7t4Z >3 \4Z![-!-"-N"-#)H#)")"* ( '7#Y]"Ps  I W\^;Z ~ BhybdvC 1Q{Jԉo ЫyfY޹‰Ii͇ѳLdÜcaU>Ȗ˰V"O@ ^{[CNS ~ 06%? M @\akݺ%߮Cj~h)~8 W^p \ o 0#zp  AiN j ~D!,-,uX L2dc ^q[#^$"8"W9)R\Leo e8  M    7# IG 6E)  i 'miRVk' ~CSe6S"JW>f  $ad%0J1/8-*4-2#07}(IO9 q T /,o)\%-J&|@QZs36g,  U @ L rZa! _#DH! A ;,aWfu퟿tף)"+2{ .h' !! Zx }qL2pX$roBDof'  \S ] acf hJGr,:w` } UE  { XG : s[+ ?[HSte׆֑u*q-> /ܱ Uw8"F;"#Y!+!4 L!G$D&V9V R)gBRo  M!#Kg/{ 2KrFr /i))R9(b'A+)6+",1@)+&k$%`t$aD ]w\">`]!y /<~IEt4R)NZޛtr fM] y& .> #yY  DD g݉ *ٵ2xv[Wy֑ӻK4ٗJbsTBwiy iD B 4  D K MWL|b$Gl9SR*Mo: mR0%"ci%9A%% !%`"hf) _wW{&EܞEvWGf No#AfwHl   O ] \ N 2J[]jSA$X!"K:\1'|#{w s ( Hr; r`('7UHTL.uXޥܱ$?vJ ָC?mݺL@&O_C  B7iG   y -N(T JH OV B5Zu!$a%'./?,*Q$C)* $U5Eft gHXti(^Q;]}6+6&]OdCV#N i S\>4v$L|#C<8o@ >?ܔԓҋ/8͇ηGоE|KޯS:8;X N &GF 7-E` "J5 +!8L Il '{"wR##$>"w,$ a#E ym[76's:]?udG <~k?rgr>SX#>s} ?/t@S&[4x.'b x6Y!r}6')S H N$|QjfKXm 7 8 DF.^~^3SfmAW Z1 }x)8lO  *hX d;4`5o6*umX^cݺݺ:dV 6 kߑ _ PPVw [ M7Br."@3NewxOeH%pmi@'q[E ~ x`]j_8h:N&Of8R~u'&w4RZd8sJK  h3A< !Nm  # ugb $)r~ ]  9#sR\?dZ = l . } 4Nd#Z:~&'x 2)d55u\UV1ьоѳ߮P߇Ւ41'6{#M';~r^g j /f  Ke++QGgn/:`:/v"*&sH(5*4246W97:.:,T::H:?G7`541F/G+)+&}R"mr^/Fd[ rm MFQ  &gf F 0,Jtr{WܻbؿӊcQ*?f)Ѫmn^Ժyxbm<*i)b"</,TD  %GZ S T Mke{F?s O ,Q#cL?7z+^`G~ svGU]rp14o?]!_]h:H K[#q`VjBRHJJ[h!srTBd Zid}h+sR6'?w8W. _Ar W @Q8mN`%/') * ,{ 3>@g%68JB] kn s: I}e8sfgc  l {c B14KEPTP{qrA{S*l 0 U #< su{/~W{/tbZp\ "  hv '"vC N{5kRCNOp6dLe2]LX3vN_-}r7" *'`}M`$K?7|!gH.Sy\pgM:1xXX 'M < w W ie & 'l8m>NP <2k j # }  XwuC'ce S gKJ@-r:b1e%n C xn,7tmJ[ i  i ^ D@ Q .v  8t ] @f'  ! @Rff ! |  u4fA{ef)*H g ` 9 {41%iTGsgwLqcR , 8 2t$SsB8s`8.$r?*5.^/>bY+vm-"&t+V`_RvhR- >Nt-Tgp[[ x U@  { (F0^?Hy@77h qsg9]7{Go#ox|`& M ~!81#!AxF)   j  M  HQJ5B 7 ~$ atGsi`V^T@S@GA]@? {O2;Mphf5g@Od'NvooWln;>}n@,\5 a ,f y<Q|H S 7  m< ZwxJSZZGle< <HZ  ~b X C M  C 8J  X3?4?|r5Ji7^pr|[}xC1t C )GLhZ  ` : B' }N ~ a  S 9wLi _  M g  fQ[*)fG 4f>p! @ $h B23 o}h@6r)@ xk"&mu1M^DufMp)/ X w 3 |3]3H[:,u<6y8 E  ky -;u 6F[E0'T8@T+CJT7r~r.b'#9Ah]|f PW1k%R  N Kr @L J  I .V 0 m.m b  r 4 F `l  ,N 6 q: SD Tl  *e"[H[WH J5| G0l[ x{o)4 [x` +F W {  K    ;;h)85|WsKZ,R9\t8 e{#{jik9jg@") k    j {th* f*& I | ^ QdeY  `  AA ` r O ^d K T v  1 a)IQ>@{g]Yg#Vb5PVAH D L  M ; w k )  `v t 9 _8  &RLxc@"6fG[Q=x<G)l4 |G `)vKn3*K`}()*"K N L HKt!Q~+W 1:kUot ux)3=CeXqL9ud*b X m].f_ Xr ,  | y  x[)>Z\^}FC<whA[:Y . 5z4z7hhgWgbd=>-*(uWpZ86\GDMN&"~+qS*Nc-   t @Y0 :2B3t\8`90qkgOeG ' ? #p\+op5 Z   w O5 ?  W  'Nd\+_@4 ,N?/t} 6  u5 ~*!f{R1|xRG` bkNC9LC8]_V3FCkr_|,rL>D u w +FmkD:Wp <'RVLPl-FtGcyc4n<H+HGf OoCxRo5v]:q@hr#@eSSAR4m M C#Si 5e7Yu.* ^<  X kOBh k% `  vwdyhriu} ]{"'`whwKn C1bC.p{"FgrSS SW)"{e O M C ` h - + S r T L r a ^Y  KZ | o ]    6   K M ~  u   j 9( L) TG y  g C  #f { A # s lHLf3GgE'9[)Kw+fH_,~&KBfRg  pbs]P  ^V0-jC6T/:~Aiq7q;7:!V5>' B i*,>Z)>lP 0 9M   L  | 8 s  @ { dwu1#X o// 5P S 3  6R r TC  # o5    | I ;  }d  jmfO "6  DA(,x3T\8&YG^ S|wGS{68 2[(e`kP/9u'V_|f[p^_RVi# : _?KySy) do a & 8 A L H 7 =[~LzXfV"2#(#B$$&U%$u(##! >|EwH _ E[ A Z)>kEe" TT>,@VNXPg*IsV%AA~JA|o:_}GYCBv.qZT{JN^_ks_k# !)i >E / t T ?5oQP   , "_ A  ] , 7  _ QH!HvD'NU~yIqs1 I B ' !Z8J S9~+ R;kjj#]fG~5i^-i*AjY")Q[' >_Pq2 fD;(Z9{_@FosX]/D 1Ag[{Zw \  - #* XK0j C>{O; , t L  >\# } u R # %$#1))%t z"u )  uq3?|ވAP[A*uX*k:f& M) c24`S L .q ul$'^,b,(,56 3v02\1-j, W&$0#v #[ddC!X h } = Q' |e; g1"^v EHߚJ>Y9Wo U'pP\#Y%$2P2p0{>*Q.)/$:,* 's]k>Bb+,i|}  9;p'- 'r # *[ :($gC }DF> e3\4R8ڌ[[ k ݺ SeZe"Y(nPo "  iu ) :!46>|VZ7??ZK&{*$E^ 3o$ A*!!%("&'r(@0('A##Y "!Q{Ze }Lʻ$ɩ|jz(A#$ 7$(])*Q&})H%t! w  twx@JIM߇= C M 6-)bp98B U O] 5 _<EZpPs* $͇[͸"x{]BeZ[ Dw <w19,6*!g"A#! y 8 |oR@+!VFf@.t 8.] #U$d"R O *D| : mp"07 W_~S  rޥ߸!/U]CW l  qA@;c rh 5=}Wyu:{ܞ܊MGؿ NI6&%)S.M/Y09>97W2f 8. 40^(%!BO_x~"<6LE I/&f,Wy 7ki!$WH"1w1p,16-72.-Nޥ'"ڌiף/֚0 ~ե WיI٫4wECgon 6$ 7b 7Q4 2 rHvq {A~i YqOE2Qn!*)\i8UrK4?0Te,(*e߸uoA* i u ]/  UB @V$[ ,U7u/xREG ) t4 |7w|_,Xj?Jl )4 t]Q@ {.}ii5ָȖqυі۲P֚!6+5.  #0} $ *&%$}!7# * 9 Q1&*١'جv N f\[ f] |ywy [bX*'k2  fl4KY` krXX0}U <)d K " O rF r j?/ج8oG'  WoUXi } q S 8lWl5MgR?E    94 | T | g s im  s Q!^S|?NtZJYكpf'0 t s p`?(Y(tl j @e xP V Yn ` uqw>>4J DnqPM y{[ j's!G!*, / / M:B  3 8 5FC# \")L 5+X#p'C(,()++w,*-1/0-.-0*,).C$D)+@&(#"Z # rIL(C2 K  # j#J#b*+Z(\- * )R $#k_Qr A63r%)~ghgw"|X-R%a3BnD'EN'~ {e{lmuv5 RO!Cheآ1#y&ȃЄu/{åÒćUѳA#Ǎ &̯A.f0 RF/8[q :+ j+ )wi\k !<3#l&:+.` /6o7` ^5/0$7y2!-#+$%~$&!&K #!qM* : J  M/&}:)K {x x fy5izAhG:OBn[G]c؅߇=)N[$q M} M cw4g{7[Wh  N ?!*!<j +cL)\$0T #l  P hJ9}u+ ;B')J%() )>00e,(*n+)'7#")^)o&_r94 :x VZ:t)r0#>o2F4`^W &JSJ|&XV{omt>;X׏b^o %4CH7u} :GRWYi _!PQV? 0uyw=zZ64R Dw7 A.9?3,' !  ) Zs ^V 7;{h%fu M+!= %qJgqm^|@o݉~c:uKuKoҁՒڳ `]k1(~W[p ah k " , +5F DQ,N42]3W:y׆ ܻ$Ӏ"P')*t+ 4Z3L0)&0T&,"c$&."P,%/Qj  qevsTZ0ԓ]ΣbisDdp B k-NqqOH#@\ ju*<NrX k! s I5^T?*E-337?yN L1py ۼۋM4eޥj+#G29 Xz !**" ##FFG'X' Xݺ a ޯ+?P]px[R[Q)%; I+ gwo\ 0 Wf S T -8  .h +5F{ )_+Ho6,{"!(X q$c4nd_C%[sض3ޥ  [wW"<") +  D t9 '`v MDCE(+l&r(Yώ4B5Ϙ ņ sɩ SҼՒs)6"\Q{z f-<" :j. 8:wm x} ݓ԰>\]O+ fC@LZFq  9"cl^+ y B!n("F!sq'ەҟҕ(8mӞ+֚ :NuKb]`] Nr g,~O]b  i"L \ \O R&T%M! 0! 0 <m q 8 y1g] 4g,u݉6q aHa _% "Q,4} FlH F*Hs[ES,_XO8$_{OeLgL^~&`E~ 1 s  s)<   t aa uC  X $ 'T &_E+w ,E;*(G(H&q yr?7 CF84)%C )--7.--u}2.f*Q$ $_ tx\v+jhdd\y0}DW , u|o> ] }Bj ۋ wؿ-K۲l&N;ϘoVc"g" 8x`SFVa>)e"  xR & ; :6-rMe?|%[` |^uxix p5>wK \eq)S ' \'R"_`'CP%[? L+`4lQpJ T)^Q w :L9"?RdUeR6++B; `|Kj@!* " P'#%#   7 }* h%p6( 1 '8 B"r##O8`)C%E"4JW 'i&#YPsF    !^k"/-'P <4pLu C 7 <3dD]*USe  _ *+ a  h 9 "m C . sN O jeGMju[C =-]Zp?{  `pGP/#V=:b޹ևDtև܀19 ږDsf7e - | >Db"yn /Peebl7P {Qjt .< Z cOG7I"j#b}!e!Q"Fk"W'[# ifq|  h { sm19H^+hvj?<hu!Qp .aF[ CE|OE5ffjZ(nB7t5+u? v N   S  N +x[DX ^ uT! } B L  b x  gt ە ޹ ض /٫}>&7(  A\  5%*"F  Ai 93 A6D3!?M.C}P !%/&A#../s.+d&$&# ! ]  .o o*< < @ Sk\w X  5yeF<%w\) 9Cm{G+h5XhcB$ZXy4*}[ /lYF?\p !"M RO"]`0-ΙK1q|Q /^7TR } ^ { XcH3 / S) B C ^ 8 W v 5 # Cq 8 #  @: G Ejjs$hymdg GS,G:&O j P Wy*YH5+.,$&B!G  #Oh@ E!sga'hS[H j%y & re- B : *&+d E[C D | \ 0Gg"r"mC$$u(6&)H?*%j#%/i%%.|t"B*0 s 5 9 g ! :F:D_>$>|[?c [u i  rma 8 xuX8/ܱ6 Sf"˓%C ƅJ`Ոo0;N?34wSW"?tSc~{ TD2hP+H u c  % ? k5V!"EeY"9!!Udݓ"w5h # :hr;Aw !"\g!(&U u$N!. H%c4[gN{> "3\ R+^_bH k~ f&D=ڌݺ8o]; J oQQp4 }#v#v {! ."m[X^ ] @ <?HLLc;>WVzbJ{'-FO" d  Yg{:PS bdBs\` "+u)A:e a8 Z g[DC\ \u io N U@?5X^ w3t v*(@85O41S)!$f! ~GXwe ׭Eep ہ݉i    /  _ s8  09mD*1 +"v CPIGxX)6Njٵݝuv (LXiai! V+  j C1(H? s F (ۋJMdT}kLR jwfCS7*b+D! "( B   @  S% _ kt8;I.xkfSh_/MD& ? i+4 YbF5 ?N~/Lmuv{ (p6'S{A\?x*Rere_#8u~p!CbF/ M| + |:sr-g,9r+ڪ١s׆#sgAZKt { B ( -( 0 425 ? @ r@ 7< 8MGY?fH@ 6 Qch}~+1u T v Y WX {".dq)}h Ip $ j'X IZ 5 >4%G~5     Ulsg`T"5$##!Q T@M  yZl?6}fb+Z%c@ |, o1\S|b&`9ڌ:8e p f]Gs LDp/oky^+~c+A+\u9_Bd`E -4A %'{)+J, \/-x* %("E"087A"!0!]^1[v-Q!e## ) '-m" K#[q8Dy p s? M@0@gQ8?C4w]M~Wףj١np|9OLo* S "{ 6!{V#`4`jq?q\v  _\ &3Z  q ]]; 4w%:RJ$S_`*:41JH<?wN 8* jnOZ 74`6R c   f  k  f P gF{[ *u= k g 0Ed)7:w?u` gcr  LQ 2W|OYy+XXdl\ { S | h :4 k5 fd ` j)iT4T/ !{ fX#"e!"!)]Phe7a HP Z>*iWvbD)TS;l3NFL$q}@^8S}  Ko | ?  o2 ,  u m)y m q BG ^,I"$'A&j#%"   W gw 7 D _WCsk.n$1t߸Z__`Kki71N( &;9]0@?gO3| 8YR|LTWe&V-p v 2  tu . Nlq, i sQWe/0T!P(**U)5/i,/8,{(S&$"! A./   W & q \ _[ T *  f=Qx  A  M Q>]f3l?JJB`9rk[&MbH-*ATKfeIJV5E4?\=Z P _tr X ~_b7q W@ #3 ocO t*f9!9 Z <pV|BArC qyp[H4S"  T7^Mh.sUyJM@^-?%  ,(  AD(Z\Gt6`}V)RR*0p!Zr<E[*R)Qx<) {7"-hHt|,3{Zw/Ps%"M5H[PpyG-Qc"u|&q2 E   =G%wnMO0Y0 ] (  yf%7uo/Ly^W|+modMLJ}y xmQ ' M 'P;T3J _y fJ9kh _4W:t|p6   ]O F  k`/- h_R( , B  F m^ fy?Qwq#[8@"86bfr`8oM"@UM86>q\:Y%_r L)(W`_MhlKh7emku^i@\\G uR  8  6)   ^t5?7 fW4fuSA.(u   t d5Gr[R  \G Zq@t9FolE0(_l) u7$U-~c~1,&FtxL ' $2`wM) i { | U ~  -  rRl ` j Lj @kx9ME:j4   vQ@Y+` iO ] N}\Si*-*(R.P s ` B K r@ ? jQ >R6tXGL|i8LQ}ht5j]KgWt0 G6$.WsK h,h  (M`Bu;1{  Lt^?m0RlKPK OdCVr\m+x & #d K 7 g: @ - sL  k ohKwm@ / : E  M jx  /  WZ kdc'v~jMb2DX<)0}XK Xk'#b/ t% j_ gix_Y~0uND * A - u #pKghNT#:+!H@!{"6TilG|TMnXKh0U/P,RYu,$_.~vmtC7>E o =KT!4p y Ry@ BLkG    k t  B  W 7 B  | | < #  -X"Z.1 )'p'^]|RtH_H6%.,TX0\XoJ-@y[lQ}TAAHxF?53@pp~.DQHm) :` D P / F G k  8 Ni*e*Q#  a k A# %    K t ,  M g |@ u  "  ~ {  [ -!  )W@&M D 3[ PPwF:~/g/Lg{AH{4og;w3VFtC}*Ts?x"{w Xc & Iy!Rdx~s99yku[ G [ \  =oCd~(X]3 0 x n ^  + @ g  } 8 e  ^  v 3 :mwG@ti&O *fr3GhjXdQpp?e^u7D}2m9Vwk&Y j1.x!RfRw]wr9^i.{`w _ pB%;.3s_j9U u v / :\     0+E ; j />  A 6sfd)m/N'NN'/N/Y+XAEmo<"V=+y @i r h .8(hi?AitX~M~wBEL@ZdeDj <8>\wlo: O C/ubdOE!<@)rB|9|~9Y)# o[ 2 |pHeo& 4RF D ~ a W; $ _  DS!O:k;T  ~  i  @ Smd3 4 @ K . k&xv4>4f6#WCiWC6~Nwf*S 6(F,B.acDgzYlroY0r6JI'i~X_|n86p|,ip`T8[`r!; W +*[/uu}cWF uO  $ |Rm 6,cRy n Kx |  W2To49Xa6 s  B` _r|_ K f[MW:&9Msu}G5HO'tb&sL@\qf> <  `-  _ K  }, } _ )  /   h  j :d u  U   L4 0  r#N2 P7XR_KxZuD !x,\--)~w$EhXi7CRu$k8)Y2:'&n^&     S~ su |C 8Fw`opLM7}@8<  t a   6  ^e I ] @ M _ N j 62 ytD^#XeFT?8E>xhBx8PCOvPPP<QZQ0YMM e  O 6   , S ,  g : h 3 H  h% '~wEm  # { =   xlNMaM#<A  7  j5 #MkCwO[''uTC'hG[KB;# $ktw1ߑ++"&|*/ X>b} QQ*t)t u D  $  q G # L/K}$O @ _ &  *q<HqrpA?^#^&$/ dqx.17W3PwY08QW&q> QLAXi@st<i l {F V/Qp&Wpsv > ~ ,%OK%L0i D I HhV}e f :d4Mw  J]{i.g;{F @ &]#_'p-Cc oQHpqS84@w;9b._Zx*> : : Nwm f1@jKTr-S7{ZxXP[de*4+T S|vrrgF`%4ZJl5l     ` 'xo&KE9RG45yl&ot2H~s-"rrW]Hx{hk bZ4k?AvMw:c}P/<G ^  CF5 C Y RF  ` @ Qw7s@r-T{bAR &> ' t  X0 YpG   T5Ac,` egu:7AiL,^,A>]C77C6i   KP ^Y=! g8[PCv>El :LF )  t i( ^pAypQ {p & P29@>jU k۩A Ld9:jٵӻ9AUQ]g>[cQQ F   6`1yCCF}y  X {N.  s$ $:c 6 !n! ! #O"P ! a I!JSqIOu): b X  l+  ~_ '! 9 5Qdm5cp0qGP "&A M "M/*CT5!e)"sXgE C #)(|~;boJ qv/ 6v$ay&!"9.%+' ":m ^2e X o> W ۋ N!݉0| 9 A^_K5 <.Dr^K5qZu3υӀd/;o |CWmȴ CӔ ׆K5Imq6R{W C]K R':!>#&UZ%r&K*e*n'+)-u,.C--&0T.%1-1p,11'/i&./$-'0)8)(- ( 'rS&("0*S*,Y/_0!3`6:6a88 K6R9K8}400u-'")Eh" eu١}bԉӀ$υؿ֚Nѽ>t\կDչgO܀3W.;y.K9g0(wfox p8B9Zܞ Iەݺ~Zl K7)u..xbr* S9T, 356CPEGZFBhqCa@?W!x\$0"p q    m y !x+(% '#Y"A9< wmt 9'{w/j%ώ7԰۟և ܞiҩ73>)!ƘT ~bqĮfţhΣ2 "IO-,)u,jx=Z)&g j '&(+P!)"w25-3 254c41S70#6u/806'5'&1"0#,Y&%'![")O;A4$`ovF4?  X+  L | 8cH :P W uxbY vڳ pי{֑m2Ժܱչ۟[U\}\B 9 r ` w tr KJ'$_yi#-iVC+vrD9k8i$ SGp*Ff |rln:Zfk # # $ ##.#!!J7]W w ZKC`LWC70D-"Hw j hW,#K"Po<<z9  UR7+@"QMڽv{*|![)R%-[/;= '9J3G-9 4 -W "$OY (@ [ ~ S6և aԉ O 6֤ @b &=LfH'0 2VBH< f*O^h - $ޥЍNU7BeС`ĚͤіȌ)ͮZѽZq=ώ"B8e|كE!ݓvt !y"o"<$"<tdA:t~t4Op3=YC{#"<3&.K(P/| g424w30{7%3G%`,"< $DBh# j* "'n&B2506:%:] AK KT |JU jDeiS N ^G=g<480.=cڳfضŐX:F"M 'ϘC/SPRUQKt2 uA=:'ۼt3 py+ ҩ@N}@*nږ֤:ڂږ9 o&8F)'hDFqe"F    Yd`d  T X4GFF+z 8w s!$ C$ ~# #$ #  u! @ , Sf7zmmo2݉ Xr J |?. ?y-4 1 t 7 j4F;%H.  {^ [\,76exOcM^{ YBIB_.b.~-kN)-*Gw'h# )_up3!?P/bZ-|y-*  Lnjw;zsN&p[   s DY$t9o[?":!*g"Pٍ0xկ!wHw k\*Khiuݝ>Le-?m  (DkADN hc :) i q v/G")$"c& (S q& "^ h {3 { k/$+?gu&}~+FR*}o,"]8'NT.K<3sXye};lף,*[EzfPsDZ :P*dO xL " ')@(H)R1IC-,)5),;'&%%v M  "Z  {lH?gulp :  L Aq'J(,W&5# &%$Bٗm?w+L ` F(ʞQH10j\0* %![> RbE 9 X  ]vm5f/(*y_4ZqqC~ )&+97J<=(9EuC>E2F2o+"b &BG ڌە[FcVԺbf 1vDi ' g+ h  gy -(y8jlXEC>^MI6,wn۟!ޥ^Qb A & E[$|VRrM|Q< t QUv# '#(%%)/q1?2H3564.p/)y$&5  L03^`7m| -%'{~$/.)+.9*, )y%&8$u)o'$[I): y 7 X +ReA*"-#Ӕ 9&$%}%~i",IS v 5 /F #O fd؎eFiƅ M|c  ǡH]͚tҩ{$(g[%> B#B#:=D\)A =wk7/KP+E(g1~4*!)>" 80cP ׆ :#o +#*%.C5/,;$l1b-"i% S' / ܔ Rہ%`t,bg)+mT-1о4d2Ӕ.CV)fܻ1zN+j#1!9AoPR@[F #R fb!d"C slB t7@2L 7)b!e%|%'J1(,&.Q%$%~iv+|@E߸ @LK i'a\ `N ,S=6Z% ; V ,mw|&stHdTضw }5q ~eJ(g>-D/2\V89#>6!1, K:" 5 ^0 (] &)>E#l]=k lH,J+Ӕ6ΆRr{ܞ%d%+Mx$ a>u\!b H"! ZZX J5}:@#Z x~3tJgiXPXMg *eVx<#uJW%'(%C// -'-(V'-V"ALl D |#|Q9#jwVy~2> ~A \A I @ | Ks  xXg ' Q<I  eO{ * 0b'@dMeR K*י-~ڳ[SՒ۲O A4LK?B[#r(6Q l  ]r܀ږm.sQuHgf{ JD {O i?pR,Kt *Lk   "fp /Z' E} ,H / +iw\8pZ\&rd2xQHQ@M +B"!n`! xb i ;O( NYrH9S:F~ Y 4BY}j./0.&$_.`'*(6%t'{s&*($% !Qs )JoppAq q׆ c]uo/gη&zv>ЍECz3+ /) C c WMCF! u% YϿ*6t1f޵얹`K%| ʱ$x$0܀5d:gf4c;H63+'7 ~" #?B1 -o\8  .  r!GQP! # %.j(. S+m(&v1.*['p%$u$LTlqK[93%M %#O(,%[$#1' SN3]dM {2 'bs؅Ւf7&ߚ'0*@+[c/i̥aLHHvT V#(#J \- eZ 7 NQ(-_e{@o 5tf IJn N3" 1_5$4)/8->9>^V<e,F C    +v ,j&.$!j!4 ) -[ ݓ8H0t)po6{Tbt B)sDsL^?M,(  ,i G3e_i@ q @Bg 4N\ ]g$k['-D/+2/U5/i4);\:z|7bGѠE' Ւޛҩչ֑\Ͽޒ"M[qx~V6ޛ,_x6 W^ M:KQEOwy"^ i p W J  A%AH%R9m*50"m KlTuA]e  j.fP6 #l ' M(qI0?2f1}./l4w42-+c' t#Rw Bb%ߤk@tMmgmiw+Js$ &ޯa.WIԝv5s=:.kA 4,+ }- .#)')+e' 5b52-&%-'^+('#%$!(g%" \)of[ .  8A`Di^j  L  ij h  c  A :PtYL:JbQcFɋù<<ˉԉzĚەņoAZR]ԉ)ڠܔX5:d%DeC"#%,lo.)-R+w 2!0-P)H(%)$&Yu t ^ W A[Nss0F4A \\! #<'$W&U%')y5+[-+$+ˉ DCN")>4F9;HBqOP"S.PI/qVoOGv::1)#LyK dy/V | ]9Cw#!rGe 7 ^^Z0:X !{c˦ʊqq:Ü ř ׶ﻮ\*ݹ9*R}ZƏ&s0AsKtQŐVϘҟ՛۲ 0 5 /",""-$!%$$& \'!'(})+*&A(m%(I%"mA!3" '# _# F v!xF#$k "3 N&F$:m]/W L>_ŐUȃt °۟*ڳV۩֤т&߸p_ܧsޥg*o%>"~B![ fm3It%9'|(I*x*-W+G+*e*x(% "w >!:x#-d hs]Uh VG i I%WUK"2#l $(Ii(5(,((I%`#r!Jݺݦ sFX6Er!qN'B :Nlf,c[%|.d6W'ҋ_ΆҟXr*3Q,O^B; &o$p  %# ,I/wR  A _]"%J+C|wX tZ#})+<*d5!6$6k&i3("9#,15+w0T)+(g&U*n'F# H ~rJ |r=5HL߮5\P  'ko; ]Mo p/+29n3(C mOB!$u_!:$R  c)( alb<*8Qk_y/  "IM"FU$: +.C!1""/")+w&i6:#b511p-Dd-* )-(Z ? M' *  ^  | x  8 9  $  K  s N$ ]{}Q Eт-˓*]bgXԦ¦)[Ы˝h[h֮܊]iu5n &8(59-::M6;93*e-&s(pRBi~Y[% L؅'dt  !n-,*=#z%)]*0.-0 3[1I3S1x22y1.u-0,,+ '-%b%" 0!,E\  _O   }hZ1,Ews-$s| , Sp`#  T  tq q 1 y%ږo߇hJbhҁ[ҲmkE== QO `KJ lx gO U6 1k ! Sk* A4 tu^%V(,F,O <=?Z=7nI/GC!Q:![? ;>r71'J"cl r  2ds'M?i }a|(wCq( Sa"2%P!*r)(]"Z5"wr%m ݺ ݦ 8'9 -' O5yE ވ_*(6\1KST+3" _H<3V5GE(4S#%C=#v$a'%^'h&&$(I='#"Zv# . N + , `\}~Ng+S | * )*3 NQp+IKpj!t~ 0 o K;T~x! G x)J*}fJ)9*eC ^ i) N tcx h l#?(, /,O, |7 9T8s5H:pr74Z /,&$&"<B}0y!yXA<&B8Qwf@@[4H=,?p]]wv:>ZCm $W%%'c&$(qu%&()(&? AG 'k\n 7 &,%0q* I..w.9T?:4c/3g.`")$ H`!# #l!hC,priض˓GS  g j V 7 8 S Is `{Y : l7r F*q|68 F{U^D޹ۼۋgވz۩,\JB O0F \ .sw) a 8LoaY Uu\+Ժ|ܔ . C. !:#G"O!X!4Z%PX  # '!#'-*7%|%`%C~"$ ~%KZ@2*w J<|8~I>L /0 j! \x ko<[g X /oTe -[6/~Wi'  L d7F563NCf1 Tܻ:2n 8 5?N6# A T T ,);GD :ۼ١oڪݺId\lA j  ##*#(,*'&/B .,i+ '^$Q#3tk_ jGҩp>[]:@ v8x~d }5x+ u_*Xp<f5X S;{.ZW!Jb6֚ZK;b ;5O"mج"_-)8J; SS 8P q . k B  @XP P G= 4{E  C Phh8!_ oD%X   _ # T _ #  ^ G ^f "t *_V s \uE#!9$r&!j]%o'$$a-! -'r+(<S(x^0*e j  [E/   3 &i] j_:$T~h"Fu!- @ p D_pX&  _Yi"O!6ہnrKK>bwL2xܞ@ FPbe`LX]_2߇=I\W-߮EC.Ks{2m ig *Eqw    ] sC IH!1q'_N\w!#"`!["g##6""m"P3#M%'%VK%&'(]S&T$X \"C'L p "w|_3r6\"g8 eS+\-z< uEwu^ >y[xBT`^?7V|"sZ^- G0-xtjJf ZL!z~t !!**!eh#Q$# !GX!  %tE)A-NQ**,/$-r)$l# / S h ,O!K~)M^ 3v\I+,fuV?]]DS$Ju8y;}r,c,d7U-s5d  ,N~%[Y/M%< ]+G!e+;TQ)N! pFQ{5g\+A>9)M *1}k<~V dV % %s,\-"!xB@{Znx|o5{2 u  v '    5 ( 8) ( &5)> L' ,%j ]% @ a "  p } \'v LnG3^ ^eAexK,yepo -<Wu Dc3e"]Aߚ$49Bk ,k|#v Q #7 fo #  a  oe e:vc  A+ [X ~,%M%j #E s &UG%V /-H wd*oRt@Dpk8~{QV"O'a{1VcP,Qvݦcbz8q}\6j<GS?PxnY  0ke9r$ks4uf*a# P @U  c ^w (hWCLiF ,  /' 0:d  /  g t(Z  yH si"\ppfs^DW-SWt~;s;,v Rw")E I S . qv}8a' lGd Y . ^ J    J   ??"\r ] qk on1>>+&<[&ie UiqnSP@ ' :} a>=ZSg1yHf9  _  XAPG O<p  s 1  7 /{ T E  FW` . !  '  a&\R V <D 'Z3X   }k + 5 TM O U4 :]:]^B&<mp/#Si~M@:kvC(3Qe "fi-Z sp Q B bvVc/v]FT+ q  ZkG3GDd4Hjpjo7f8G2H,WD/RL7 F|S9SljD"/J9)S   |) ; r )  _ OD[xswK % j -  r B '2}&<b*d4 : ?d;<P("z}  Q,&w 2}8|oJ.(Gx!VfB\  g?WX{.;AkAq)&gK M . G3 6 [ #4  S  !o p+  CPP`hK>}kO: ! # -Q $P " 'p # 7x  ZEG< c  }E y  >pJfOYvEG5h6.'|77sX,JH Dkk| 7e|yoJ$YLE.;&_+]g-vR  9 ^ FYy } M"d0GDR)ST [wX!#xC  .  yOHf+R18f   Sm   j ~ ` j. 0S>Op6Xkw3+PP5]^vK1DR~ WFN#?`5jA\N`!:7?MHpqKA'ii5od Bm(?7%ZY 8} U'r}+b@4Uj  3 ]H\  ^e $ h "  } # | H^gV3J87Y|?`-M{S^Cu 2Y)!|    , q+H {*  <x [-hr{;Z4Mg 0;  i . `   ! " eEd3h\tH_0gy ^  7{ru  8 $>iL'#.9u'v N2#YiY[7NF] L,#]`Pu]M[~ %A@f N 9 L    }T Mr B 3T+8^t%~7Mu Nm t 4R0e;C  f43n5XYBy   .w     C\H;q3_2ce#q>2 Q%mmd0L B~7&l r::`:_U|7 vPL'   m9`_Uz?1!- M W  0wQy*G S g ,^ q ,o 7G >  2 /di4$Or&!GKH**= g5@O Y#?h6 4t19 t u%Q?wKh(cF|\ kp g 9 7H/[iq,.@s@rSwp { 9 { o } LuQ 4pR\h~-Z- [` (2Wi?@RHfA)o 6*:1oen*o i~WxX7<l  h SmxO     Q9  j 9k 'l;1Uc9GPfnn "#"$W$% # #O ! UvVQy  tTTxrL.T^pm :ݺ8|qP586@V_H۟HVҋs`=ҕկ?^ek[}b&CQt&h< X? j{   9x6j0. C & u)<*gXpd{z@ T%`Cxd x ]  ' { 9 u _2a?Ku #, NF?{@].j`C;:3{?C6Wj: l60[ 0 s  |b M `/ 99 c< E[hTr>h3uQR|5 Spvyc ZGp fN]fNg{4 ]1W:`}J^!o(h5:psJfd+::G3 +gL-g5dQMje F\ [ rQf +!E 3  W ^ +e 6 A _  DNf\ g B jD^~KkL' Fmo/$e}PmS#yJe@Ab/7s5}>XbOcO v4W'}khhJ]YH6h6qS -Rr U8   &R < ,ZJkT D #@`1t:xl ; Kv B Z3 G^G@ s k  9_XF},ii,u#F_B! TF1lcjw5f_%8k3p3@0_ݓ0۲^2P:Uo5\*EWB`+W*AN'XXX*h  sP H<eO  h$!A0s$"]t_"H !H RS yA!T !!x#(!"F! f q  K   $  cF S kb`{6RqG6JfX6kD w H45^nNJi~nܔnO יRrڳZt<&u) -Z.4,Q!b 9lJ<}&LJjJ\M+y*X < + # -|1+`$ DV`jS  St 7F ` 5ggf > H EhZ[Q=lXZp @ "    9 td FOc\o6k Ag$YEu/ulljxC#NvI:AbbF oc|!dwp9`|uk  fuiv}RAAEBlj97sSo>9"9  ] L  m 3\a-S^U,`a   L E%+y[Sp#g-Kq]7j79ssFH?r^sQ\&ju1o~sAZ2+(3 l$&{#iK[} BP;ell;)x k? 3uJST+h & L <'YGep q qT>FT:L~Ro @?  h Aop  @C tR"  A gvsdP (  NWEc4<?!-^+,6)e #D-2x HYW[.>MA@ 1E p j) Xf U@s,gQ% s  gf4+: <[e  +  #g  rA~ rt~ f 4T{u.!AHLF&i;5F+ PVfz]pK:O1Kb||[]oLO N_ P  i  7 r 9 A x _.0^ -vIxRh|=x;[ b:  h ./ 7L y 8Q4[^/Z^' tN|ivVSxx\K^:? b3-!3] 3%4;pڪ"ܧ֮Tٍ ' ۲xՒM mt5   u ~  K  s _  K  t I( 2T c 9 T 0EgUyH< x  @ h< 6 7Ew4XWV^/o>qs 5Z "u ts( C Yc}wR S %  5P<soPh.0ktN O; ./T<M 5>J/4sSWw 8M\)Awh5Q" WvM )VQ 0RBDZ /7 X-+SB\H >|b4o\>Gphr)*]`!,AoC 5 6 4 `W# g {d\ 4  x SXOdf ! `n|_.8V5vLx`iArx-N,r70dk'OeLQ5pcYNq !KKGT[oXy x &eC- Uw _ B[9i Cc s gvc)Y ! Z|{  `SC<'>[_/6S G t3F deXvd u m)wQ(6Y,g.!v - # m-< "V;5ݓӔ jQ^e QJq@) Fs}ih|+W|M>٫$9k_p9vlryE4b  >  jO0CZ9hYdNo 7 ]ues/J|ue6SDQ5h9fgSE:W _; c:+j+Z_Cy q :  gT SMr dll L LJ C0?   o i\ p>wO SWwQ9NjL~F"?XCMqF'!sH1CC(Q.r!; W, 7 Yy 9%{ m] W g (9kGbZt? a : { E G!M   KTZ$^ 9  Q@RPTAVW3QpL{C[L?q[1we^]R3.W^yK&  r kjxK` gf i "LqiR*uy6 !!&Q*_d|bw efl UR[?^rq")Q'p8dBG{7AuXW5 ZwB]4M+MJlHV?h>;2 B  1  n) j  S VAv OS NqxA9c< '=B0-y[DE rlf0) f *H_ /  `^W  _BLQ8l .L<%\x}A]qpK3/_lS 52rOF-:V-6r*QwxY6 dNFwF"s_TXOZo -<  l hZ[Z"(&_ 8$*'*0-@+<)(' & )  +gr< %Q@[>Riy~M38f"\ k~7^y "}j +9OYAE|=DƢnCǫ| ףU  t  h! I)`hOLd1@",1l&U B' )5 **[..(! (,v/7}(' &`%p*&"m & ((gl,lu%'&.%"<  sE" g- 8 1آSX$S09[b%M J&Fw."(rN8NLh@|Mf$x5Hsе5sC-=ݺurqL_[=#\ 7PK#;-D 03=3C3u><*7142> 3N6u(\'4)-#]  ~l:z"~3t!4 &."#!#! ( H BwE g[  /sPK~0ߚ8nݓ(+Bi>]6ۋa߸ߚe~cuVM7SMo*~2z$ Cp8uda@i"t_YQX_\ .3 wJ~"t%M)-.0A0#/" 9 ApP e TES=lt #P  D r t3$xD!?$_)ԉEhJe O [96%lc}OE>w>wh_cMcr2 Kw   C` m 96'HM {!wd1F )PhJDh,1 LJJ - m  |   | jRuh<5G   W ^ .! CxW  u!I4"d`UF]2"*5Yub&zvV\8Kږb+(&"N +|!%*1zP/8M4   DPsH/e #6wT X *?,! g\ P{m 6  MHh`B](GFC0rV 9W7<83 ! {)L}G,' DE /E $P!hNL_b G   N#  s{1K< T C*_,"do?tTSrE.2w6JN*oFt.; q>j5H& JgeiSve [PJ iD< U U  t-E UV ' ^9- *tbBb \u/6y t Z ['5 0h ksR &].b-Wi"`g{|YKb \>@^V 9 Yl B $ S H I /T2vd "A ^!pHbiR'=Y'u K(l r ;! *ei Hbn h Sv}B4% 7C \,^ / o9f\G) htm d ?du `h9  @Z/Ej}N5jAme |8Q$hfY? 6N X35&F&Hu)= > kJW 'w \J SK)y A-5e } qDp^ a-G b-_M MGJr C t A8 >e&-L [ A9  I5<8+<-ZpA\-7,e__  &S }L.^Hgpr w T` 3 d%0"!u%% _sd~  FNf&_ ;  %>?"F![D(W#@A 82<>7BPR#R9N{VR}k W = y  fb 4Heu 0 ^݉0!3E4w=+A>PRX+*n[P} 7* ! cE_YPxJ]? N?[ Adbx6x  (#"'B.\#_$$"! +gFsDO|ai_W{!E7}\X>/ G }4O -7!|RB+Z"ޯ>׷՛Z~V<jH\o! a[")*'A+m,2+ 1 1" I,'+s$ R!d%`#FZ } T"; Y   /O  M p O[ [y 9 I  6  ;3 j -j p[ B:>R]&ݺہ!ӊxі D@ե4|߇.9eShf[Dp] +kS9 hdP?S< e ~Y8O3b&SF~ 8 ` Q? >\  L *M ~ubW)! !_$` dCZ 3-xR| R.  ~ GM 8c]d<K Z  \/ ^-) '7e f!/  D 93 { } >f3s0b@ Ju-9Q3 0  l)c~>}2Cd4R  Kkgm"q#!u'_ ^p   : " A Y *  hfh ,H=, W :6|$ 8 j D   \/    "w S 9)""%KLn@zBw ݓ,ڂ۟N}`]iYNA\X ܧbkFa,?]e:emWX0BWe  *k@![ f#1#;"   rxC P")b;dR*=}1g C-C E@'Hy44FO~ u O M> #t 9 )L6vQ!G 7NQk5ynG +wCGc D{7C ]_pSK0LCD^8 N&SQ9%  o-/y uF M 6  L!kYrXF-kd [Ql=>|o;ݦ },M~3 $.")t(@+) ' -**^(S/#v f BN As<H  jPXP?87]|b 3v }2 8 \/LhZ1  &hR>cK i&JB*ؘlۋELH o \ ~*i%".(S(&_!5!"Pj:T6  _ q ]|xRAG@h 5?d]TM/Y;B0Sw ?/~iV_06b?d`:كڽI-,XhPl<1:_j+b2?@pG4-wqBn A5O12*Nt XhP+ 4! 5?3 < W T@ ;s!gQG$a8%#p-0{2! \6#l4<46"c9#&42>/s&)!Y#!9 |%tqx?YC '.k<'J yFQhsX!eeN-?&f.,۩٫zg6ָE`eu#ވZK<֚|aؿ|" AX  ~1 R  j@ X3LWKg? {4 C .ylqs3p#s%UK"P[%%)  ,1+P,*G(#V ?oFx.6^2YC> tO#GV(&[~S&cP3mTcl6 5 ,yA4>8 "MpJ?M  ' -A 9 k &  "    { ^+R  f uO t j &dq 3 Nd D* FF|2 -,; x q T5QP# ] %M"NvG\B>V` %R-*5Vb)5 6 X L5  :Qph  T ^ t &5  vU۲}A@ٍ  {fG8kQ  yU  !!7}  g*/Gb`o9&.SOpJ)n u kPb "K} ^Cg~YTSկkirҁXNUeܻD׏- 53x]fL&b7 7M Rs # ` + 7  0PR @`9+: ] 77mD  M: rv" 7 a m# I A \u,3 I , "p.M-x"S@">4V@ 3;Z) & I"'!#tOj &\Z /fe ?JC<)j_A-sxf _ AZ1 X!x$W8&& /'r$ a.Q r  L   Q o5 X5OJ> A{H Hf+ B4 `XuTto .H 1g۩]rҁϬ`+qjK6 J Z]M"3O(M K`uF^GP@qoKce~TZj-CZ eB |k)_)P#GZ(xD B , u/  y Xd~f L R aR0 ;YIZ\;A ' g;V> R M/>BM0]X2gcBYV?R^X;Wc\W  L "@Dg^   &) S  ~ 9 id uGwm))SgWD r ' u s #!d =M u3< _ hdw;_e}Du[E-JkV&^rw^G3G  i)3 ,l3kSt\ ,\ a "| \ ^ ވ [KX9*,D-_4`^? 9}M7mA~B NA ?&t@0q$(O(,'%q*)u+<.t*%'7.&'T&Y%'(S&U"PP s#x B1 0 CAC144|Rۋ1oc&rU>}o|߸<eP i ) o H mdq TK ^  ~f/ * J B , S" 'G([,33 5 6;68|8BY;![41'% %Z  "?+?E> 0c :^;!+dEP)~r ZYP&y7*0ƢFi@“}З6jA+fLLvnTy! lMtPm6b5? vdMLk rm JRe N 7!4 a" ! S &(qF(L+2y'(K*e$.("5&(6%"3 >$Z%mQ!= ,  -h, pwKFJ>. 5+4_ pBfdsXN*ޛZQ١JVnEr]i~60AgہapڪN0pF/fYZ\A QDWS #6%, 'PCK){8d_BJ;mE 'dxv>!n%tT$ &)+-aB() %C. %#rAbFrNyZ  3<> ] mZgD[Ene!qLe#vSW8iWEFfM7bP۟ Mbo){ xEdS{9% [@ ^ I   j  1' ~.i?.jd@ l_ # W }+pt<? lErscG!SQ,i gsT k#A   `^ ]3]6 6] X{%3]<q< w[y6R  | {z    | , wbH8Dv -4&v M R `  F<( : Or%#8VN>EFE)`iosA^@M}bczݦ$XQpc k MQ |e 7 D ] B d   $ ,c _ x 6goxw347p oB < S  6@hAJ8G6EQp  -+ , DZ"NcPHmED -> 3 : v k| ' q5M*JCXp)B|'xbFd3@(t  4, @$% N&i+ -k ./ /)y ( & $ }PD2x'7ahN j q " iC L pH ^  / &ff)c Y  V Qy / _ Xo@p{ @M r19YW֮rff kck۟kP!Hrcm&=MW~)8}T|3T:p{?h -. $]j! #$&Bt&`'&%`%&"")Q \E'`>d   ''4 ~ S} ! q# 2c?:|y.j t | ] 3p ]  o 6 ,: 0;@q/}R֮~`K`J۩ZYߚߚApq$+EV!44 Wfl:LV!e-"#"""P!0n|l9p\h4<bTT @?Ef - ?  ui $ KP  T r  }G? ]  w O K @N|{N!Ze<ee xj s FaS[y< L _s 3gg : j t[ q %@@M'P3|Xk6n+R G \ us>{[S,]{wY^  ` t AD s `Q Sp}rw+ Kq; @=Rd( !!! !!x v7t<_hB l>ic .S~qCiY `@R R; R |R c*<t[r. Fz I   0 3 D  D[ UD {: , V @R w . Y [egLLA)  D |}?3~c~<oEF  {:f9UMVWqxFMtq + w x{sSx 0   B d ~!sjFa&Ev ^ x #  #5) I @| - SH hQ r ^i   { t B9  M<G_bk!DEKsVY k9t%}Y*8 ^ WF'MbF4,\Ls&A i 1a x%  W r    0-zR `f#zM"h2 dQ O  ^ - ~ 4 UG G ' LF 8 s  :E`RdQHH]oC*3{erxU-H4ou[ k^8Sro"PT8He?d u . _  J s 6 , 4  6  + f f R s      [4e   j } I  F)p @  K 7  N[4h7^F:F1b?6Ci-j.WO<eGK+g{:r#,|B$%L^8)%#POe$ F\CNrkZ#%Ke5#^f@?Z D  h|Ge   g5c$}D  < "8Lk pB gB i &$0i kZ p,AN%XE\[)r24]WRk{6/>_.5 e 9 t  s V WL K/ r?@6]@Fk[K+S 5 E ] \ A+(  9~# U=! g  p/Y3 O7{hh&4,fqT7&$Ak|}N&nvPZt3Y9|.G6,@R"||k ]"7{b1"IuC7dffldM.Tq*" C my_#=,0I67-"E R/ "[ g S   C$  B aN D 9  '  w g  U KeLH/|0esxkSN"8vE()%0 tPErDd~'X-MH|Hr<L"9b ;( #  ]O   F(*x   87 jrie&`AL`KAQ4 #v!)\ eP`4's g 7+  ~O;+S@re3! [ N s $$  K r< Xko'}AV&{,9lp o 4 7 { ^O _G  TZ    _l D3 N5"R5#6BW4}q J" $"i  ^C  j M m6uchlL]f['^1Mo<XF:xKJo;FJhT#9Hp<  k  WskR^st MW=uE|Enf Y _  a  ~6  Uw k  o r  "     y O ;yg9!#Rs 9Z dR  + 40g-cj.!u+n n    |  l EdA6!.,XOs%of M 2  #N}:-sQdDF?7rN ܧZ7ہ'wu9V߮\nXS%pz;+`}C,t^6'h"#hXWtlX buL#q^rF  y  e m 6t+PmutY:gM=   I hR t  t }Q>fd [  NP m,g-Z&CXpd_ber~_kbdP}Hh`ML)%osK 1X-YYNj:}9*&>oEf Vv`+L6uF x  7?" T)[}3f n  ' :m* J   Ofx #  E@ h } u jE ^Y],Mj7c}dEkViX?dcd4>:*_!gtC"<]8}-[oD. &]p   9 B   I   @ `T  gSJ  o ~    (=t Sv  + - g }    !?   ?ST3( M m v k  t i r! g! 3EpV\#/mN7)Z'<"sq2dWQl MW}YrFYkh>j? BD4D#t= CKg O -@?P DDZ vB D B! D 8 e s\s _ Oq B D i\Sj @LZ>X |1VEP6eM?|6LN/{q#\-c#Bmy68 8 k|v su0Q8u`:qR    } 5"^] 9okiy>[[l( {! Bw\( h]B[;T (.Z ~+ p%Q 5  ?   |5M ` dyf}-m+(THkqs}u# K *yT]^5Z"M3u_AZ9M6f w-vTd)>Xe  v %Jk R t!c Z 6fp KO") F^ eBe*S`x 6b:_ Q u ,+ FH2HJw|BwF@t#Fo_B?j]G:\8-x 0  - %  e~ "{y?c:>\hqhFP)Z g ?>.Y ` eG~>W]r'_u s @( cc \7 dANpBX) vNu.u19A8<5 " N2 { 0 :.On3 p,j\]GXA ]p   W*H M;i`}'G p gf C  K  E3 jRe CK.x]N4'-+P9j8n-[)KqioRh@ l Cm 2 `   ; ?|} Q pG= u N{ D  + q  ,   T o! *b-Z`A o tfs\P0 SwY s /NL,T24KW'b2_DX١կ[/djW~եVDfܔ rz6e?ds.x"s,2 :C `EKZp]J !?n^'  5!= R&$[ #!*'g$# y  "mM&gg@LsSiK-KN s  k $Q'reD^m*O6ܞAjp߸M: ޹ߤi9cLWrZ-Oܔj^Ro+\A d%(G,0J0^+/i ,Y ) |( 7   \X, Y , dayada Ps |L w90'yt#:  ) |@d7o+|~BvKVVVrYf>g!\LwH+khH]6}'8v,[B( Q?;u9 cEQ eD\k:M9]LR- g~{w PuY) S: |toD3    qXU}  (A e |_/+m8 48  c / jj- u  aqtj+p]tQ[,m*7L " n;?|W޹h1EXݓumZݓ9|S|AޥMc.t,M+? IA&qx7_ %Q*<7'W;hm ^pu%O q)H3 z%[qo0 < *  -  I T _ 0 \X    rP H S ^ Ss R+OM(kW3Gzm["3')m/Zi#V~eOBKB"KZ&,BRHBt[QzH?2)Ox M I & ) -   `G    9 . SZ a jF #  ' d   / 6 /.HZ } oM #Gq?D|yQ,%"{sBl2m&uF.]0_ W"46u f R[?.C.JwFh\ l B  e  @ 6<o !  $ q  "hR+2RD} 0kC04  [l B Y @- g ":"p 2Y . )l1"%q6uI` N D @<E :dWm (KXedE|ZID~~|4o[E  ~te%` 7P5d+s|r:QK 4s#G C / _ $. ' 4E} h%oBc 4f w`lxu@?oeqf*{\rBq0~  N  c 8#,giktDR_ܱcs^/^3 t^  @ + ,^ # N8dG#9`qW93hRg6R L  uh^$ D UK$##Y"%K%j~$W $k! .\3l  D D  ^ "NY <ibP!!Ly+rphyd}jn0Z?v*DwbMlkn+U:(8@p/< >J Dj LK $>Vd u gQEF j 6 lR)  |fO+  l0(yY s   _ v  _ X 9 Zx,x6/j?jLvE>^7H{pC~xb^ &RH, 2 iL9t&ZK?1`yZ :S")Kv8\@W_ f Ox{B|r[_mNj#  tVe! X)B U2 g !* g\akPq u C7lS 6e+A p k `\xS8ك^ݓ$A:`"+L!Jsk+9 #\ kn/]?jvKG}X7Wv ^j y[GL '$LRj|GMmGKK `O?p)s<? m :(Q! k N Km O ag2 h`  {F;o   : ;F :?. `jVj%jHAViZR^or.Zh/, C ]  _  $ u gl  \qp V[woD*JpY4Yb~rLw wi~^`JF6sX-`d `5sbV1b5LcK OQA68MIAtm -y*r@_UgPL;MM!JKLBPwmd3L &kDBA*#W(He.d-Lr>J^iu&xF) \r o PV(hI~O'G W6 Q uD_1JPDN@#y~bFxR@!  s    is H ( ] Yr b s c&ږ5?{csOݰtGI^_+d~Oyb@R'## ]3C<Pl_b\jDLfj!+n6oB } qG .  x8gFKu#fgj^5QxG>fRp5?oD OS< 0 8J } ?  5* @  # r ~ iR  T@ t   /cO\(v-:w |um) NG u N DuG /9t\4<{#:/+E))BL9h'7r/OYN  B_RI 6UBy^ LyA. ANo5_:V]!}g"// j  7 4:   &pVS%# % h`xE 4 de\/[-C3g/P\9 6Kyte9)xT]Pbj"\ J@Z x :k? ;MLjJVrP66|:u B A  jH/l!&DC`dH BF73 @! 5 X d    :P S X/ 8 tY!7ڌיV93kЍ2ԉ~׷ڂX'*zK{Zf* S u _"L5/`3~ ?WEue-F9q6rN]e%  LB !"X*o? Do 6 S ,   yH|? {c)9ro' q@xSIL2 c gu8| Z   |G q w 6 [@6JibQ/h!",+Ppe/%s3Lw:CSgJ A$QA]#M0 }W; _W  $G &3A ip ~/oY m" #(g!*)o-a+.*,'4&84%5(I5+1S!x/|6- y.#%r33 q1 qs2$u(i$CCr~N<[bE)lWwޒ(ہܧM PپJك8}ݓݺ86]Wb7fIc|]l2F#Y t} . } 6q"   g  S# (0^* ")>%a("F&#v$!$!&s#&'h&##"m"m #bv#" >8!"j +b,"wc(  e#3seOQ rl#D5.s Y.ѽС϶B?ָ+]_E ڪ? ^1@2~ ?-(f\.6B^=vwEޥSe@ij|4*<+o!c 1KC B }#(q.,w,/ /!x0h+)'"cD"^UEm K< #(lo)-4 k?xR&6, 7 gj!HFv|J6#Gko>dYh/59s+QV9GH]a ~ S , t  X B ? s  } D? "  ghM@R!x!<#E#*4 S( '-%t( $),lC2 $:%x$!LkC (  =;R*/]u 2IKߑ8QjR2X~'_K߮APR͇CvB?ޛ[ޛ(aLagpH  D *  &| U e ~O# ^! 7 ? ? Tq Nd   wv~ S  @W53 %tz,\jSAI%6GT }jFFtuvv.|'&;Lo . 6 I! SHtt ;.AR~&K% - N4 p G * - .b J4+xt"!3  ?"FX};/TW  [ [ U}4.n/j; 6Y !N!$&)\,!!x9k+rP1 PC,%I|b۲dە!۩߇S.]rD ]: fQA\vj>exYl(|,N|17 W /  L []'?*"wdHr*  i e d1^ -YcYp {jceu*Bbbw[ X o A6 J avO_+g 5$?":K8 kOi;W W~ l mX "o LG!"m/F$ -r vj@C"Hj Y:x 0 < U N{ Cf b@ N[ `1 r x I*]f5KU'~4l rcSGjb.5_"[PeOJ{G'f%o^C+JbR~3  p K sW a!8K^/jBM]27 ~y ,x } M   qF \  # Rm - h 0" -~U8  :)n@ߤQh$t: 8{XDR #  q]#q k<,+YdXMA)9  _)C>+L:2tB!^չMJܱ|!+ j $L   ?%Rj _eg# SoG   ~ & jh  " 6 ? ~?>e5g.]YKLm7.J` |6Xn"iTbN85_/tO/8o}n'kdd5!|\ NJ & ^^hFf!p {l  )eT7-n__-E/  44  &p ? $ g 9 yphT/xB>1)?!mw MXlMJhS[d++upl   r #jxH1"A߮D)e sڳ\EJjY5,QP B xD/aSQ(CSs.?_5?e @S2t?{Ij?&v GJx ' _AqA4p=\7e H ! ?e * G   P i  L .7;?/9DZ#y!"d {]L";g3-Lk!XVK֑KٍH١d-+<iL]3 W ,R^G_y ,7drrSDn @7 c-gcy K%vN(lcW g >. -[\' %'-* |,Y0- .M<-)\&&K a *@ ? _ *J+TEu}~k9j ?L6l ^SQF s?] : 5e4֚$ɁϘ\ogۋAkW!`MqH/HXN/ afJm1   K2),?4 0 k 7[^ fp#Y!A$&r%)f''*',*7*,1)t+(w'#4'&#} C oY :Mp1;c |]D/E0.b}2sk/ftL}54 #  p Svh t] rD ہҲT ʊ]Vҁ׆ޒrCC[AKd .qQ ;= B D "6:gT+ߚTL7)QE o!fd#D]CBL(g> k.*-t+4 D `  Ms';9  tr)TgS8 rJ1gBT4{ V /& \ES @) )u  /-^ $ Q5b :s,`A"sc SP v\ofO[DNkV./ rXix$iq"Rp RZ}iS  /f:,f[<3z^k4O &m M&RNM|YgP$n Xd4  }* g2!0_r~6 ?6 &e$tsSdMGVjl ^251%or_r`6P?8H$djjWeWO#O2Q  h WG / iY# _rl" ; O+wAT,~?k5t'KRi; /X22RE@KKݝ`BMJ6 $lQ\ T #-a+'8 x 1* f H 5' XS 5 3h KG=`|"w %M i*Q + ,1p+m,1G) 'T #Y x:Rdc1C LjtfO?9>"~',F81!t!P||b],oNkOd=LP]A.b L7q|P t  j .+ R W\ # s 7 ~B5  kf(f XWOKk-^$*h ~OndZ Yv&ZG     f S4TY 5a ^@`]xD)-s^Brk"P{k)fb #OpOGXf*J$bc>K9F/Qn?t ߸ܧٵW?J%+%١߸Qޥݓ߮v = o; t H [ `9 6 M xE  6  *G)?!p1   6xp` +-AW) 5!Q  B 9 (4 e[ f!O 5    LrK7 K   _ ]F p   En3 EYlg&wޒ۲ڌٍ٫rָo٫١(ܻޛPIYnhnuQPN u&  j `) M .q   C ku D2 < o2 E2 : ZbVQ /!5@|.`xETB#Em $OK,IfY `}jM#gJ-  _ K - hs  NG#k|@uRu(p &  ~V  BG `  b%jL! D ?  H ]    "M hH l'SMt0 & { -t Xp T X jQ 8+ 6 h M CEe`C^`LNg2޹[ܧ[M!]3-C{ 0 ,l/` ~ W8H}yw ' ( i=_o F   V)JRj=qdwE3 < :   '  p \ E:x*~ V M*RQfkQN.!  LF : 4 i s4Y&.V"9w8B"r :[W%Z}^+`\FD ;$ s.+<O 'Q j O Rr\!= h! RJ^ac  K   x ,+ q :  /   9BE:;  K &K7&pF.,:~_|SSo]1eMV_\|q^4w+~B;M&0X4-%kRgb&jV67VB?"+ ': :_ i  j  Nl#   /^lti# kh C ~5  /  9 + B k  Dd`ynTZu}Y0j/WW-Y|R rKm7-9 :}qj;ZeYkTvy1~%jsu \wlX|KeQ,X &vL}L/Bp@! ac _ U r I  P ~[ M4 D #p # , 533oeG  |d*f_5^,`O  _ >eLAMu0;v4yq]fO  p  RJ :5(Pqg)Ay@fh0 {6iWf2]Q>NG Vm\ j< D 2FH/[ox3   H  : &   t/=*7#'vvv :  T i M4<X p~e0 !F\! ,n):^!8dk-#J7\teW N  .& L B  W  D ;, oEZ:<~[iQwfqbxQ{yj!^GE])g27t}07 zP %[d{q#@*oMR-vhPjO"G* aP } h  ^  5 ~  67 8 }G t  fG_*1\+ R | 3<[/`k 2*n[ ey@ 2G8)x4 :! .p@u#~ ?~"6KsZZ< W[C5^sqS_9-,ch$8^}tC9Bg\| ^lF>dd Y @( >Yxl6d"x\   0 D/ %GM\V?WfSh.j9m\e,D~/lHTW\W9_! ] o 5 'e M D("dn*[*A|{~iNj/"%AT9QK*{eqHJ]#  ~| |7pJ//m|,(]GQ!*  ,-L7G3[< A  j 9wO;?rKYdphyR{\wE'2k-{:X7 kM;.wt 2Wrl>33NZL7x 3 K> Z:o8Low3  t h  7(]5T& DX8i87;3@gT}V:D`:hRuvKr]_4P$ B q  _   __ r + Hp gPgmeXd(  u(  #  [   1 ' & 9p |  ^   2 G   Q   4 C $  XE4 |KBVbDZ0J 'M0;v)4dseKyB]GBo)lYBDCZ;l6_eSJug%vDnsSuyECKH( Gl  0 ' 'm  7x  d?N8s|B]0#O. *F*rS G86.,P|F*~9DNcCJgs@#HW)M5~t#*,>*0[G.,G  C ~ ,qOF^(A[A g\?o N     j  M t 45)^<K"h%j3Y9N?:)E9 i,Gn![?Pu5 Hw[t^p S 4psuz8@,s#9W u t &ts7R f N  ?@yV7%d3<Z : Go! T#w#A_+]hq5R5Z3>>JJ@mSM4 Qml~#r D8  R * 3 $D /  ~ 8'x )G3,e4w))Xj&Px[G,R-K"F@ 8 8f $ / \ cbFX]_s_CFd[V\wP -HjBN9 8O~i/f(<w:` _ . N: / jY0)5m rR2d!&  ;)R|u3VrskQqG5p-tLdW,:܀dcpٗؿb3~ߤ'kk:/t N@""}Ah#]LW/  Tro R ~  B'^&$k`] O -    D -H |(.'8$a &_ r%% 'J %(%,!# I!=!x8u?t  JROwg ܞ,υP&nƬ]YCH&֑T9N5xZ3hgZ .j[;}{w۩YҼ#?%~FP) " Q !/'A0'/_'r$ /**&#"w9W< TRq}" u i?ps&"m '%jf%3I6k 54c,+w7C*3n&.!'#%j@U#c  H _g#.fsD'?o 6XyHzo6SA܀Z3ףυPT.ӧЍ{rKy<ɼυIpՒB a6c U * S%j'A$ +2(S $k5 '`LEk}M) 8L'{.#6(;H>XF CKEK?IMSUK^P1ExK#:B7A.9#%1' ku  Z .8&  f_ܻb}FwY/ j! I4f< C!*v Aae'TyηףҲ]q]ѠȠӱٍAywKsHS  SjX$ 5 0!%daP p o%  {,8 #! Ts,,* ##*')('r*[&_.j{/g2#.v--v.V)'%M#D""! i tvQUB<ۼт=ڌ}Sntg0ŐCkE&z;cܔ(Jѳ}ӧկXӻչɲ԰4} _т/ j - '* X '_X kp26I%G%+@4 !m#E*/_/_0B4PE34PE=0@DRICH>Gv3dAU@;4:6a44,'(z"%C(h) "  Pc4!xX&(6('635x3- 7j7`31g,&)M'!L \! QX߇!A26i">iٍ!ЫЍdك"]ՈoGE"hoH{&}jw4> wڌ{ږqh*ޒuam?CHm"r a 5s uy} !%`$N)R%)$2,4*5'*9,O6* 4)/*0T%/,#&# #;!x 6l 5 +kZ)?@1cW c?!R G;e 0p M  I'f"tC! K   d U| &B|$,'A%D'&&$w%j!#Z#5$ |!|$N)!)(' &U %/s-R*,+4)d(@[Om blu#RFQ PQi[*_ӊܞہ<ەm1 +)Kh rqGT+vM06 T( H*,E2R/6 -a3'/B7A1=m$51' 2-N '95}U/uT%N m{ fk" t.{ 8pWpݺ_+׆#>"*ѠWF" /wXb;\ %HOPJcV 1k% 2F# y  F/!45",\+!-%*$D(,#b'J%&.%t$&"&}!" #X'{ 5 |y!$ S S    h  U h   xPu\'|\]եO<43>֑oT+ӻJɕݰ2կC>G5 w` Z Sh5$]OL<% 4 _%(&U515,#+23$9< t5h{W(!r߮<ώ'VsUq`ɟ˓rN u[n x WW ?R|v_%>+POnjE8%6 6`p t* -k +l,;C.~-(I$a!xUtV\ ^f!8 tu B G -&$D  dTd zK(ݰ ܔeجmnٍ-Cܞ(ܔ,ܔm Th1 ^ !(@)y'{K" %T4? T! >#vnZh$}2uju[b{] }Y D)E*%< y &Q%#bc,F $m+\ gH p r? l P ^  &i h 7 "'R{$#Y4-:"+c/328&5062(z8 xG"2$ҩ/ 7Kҋe WH< j#E$F''J&& D%Cd")nt.< / l!Ȍߚu[D6`$a?V[HF׷V>W_(F = @ { #e   ^# # Z  A  t )x  } W DrvjaZ.#( "\ bk9L "7 QO{rk; U79Z ~EQ-)$ZFmf5IifewU$clF` H`/UIH"c+  #r ~ (o >w o%CT-$'{\,R6:=d; 9G HuG;h@`H&`FmaA9:3,&$!4} D KS1\MJ *<[^8P & - 8 $ E`R!${6I(zΐ/ʔƬrz@u'\:ȃt;آĤOGܧf1ѽ؅l# 4  9"S%tO$ #1 ޒ@z!QA *Y"t$')>' ,b *'f%V%!6%&8/#1(!$&m")q i-H.:XFF!" rU 8$$ #(j#1f"#v#"0 j.93 qS&`9E.}`:8)ՒW{\Ѡ%Y 7n3B~VPivO?'a\ tF_ Ls |E B E \1 R  wk [O5v*iеi+ѠOވeM5`]T <" !Q&#("w' 0h@-$'^DE#v}F 4  :t{9M ߸&Rbd c+*I%` '%%! \ '#b%K"qX 7Tf? t |(|X~s*8zX+e6 ZF |, _ L4?  > | Pst30LEoQ _!ms4G  X Ilkjf ~ P0XCP # ) )yx1b &)t<r- ?cm:"',h1]F2f].%'z/s*#OD)Z1Nzr* `sAxR? jb~:! !_#"#,,&}!D)y'"<7*pu } uf*0![d3cG})\vP[  ?[ZV 'KA;_cHC   ~wEp.Kvd RAjd?&uZgv- `-  .T]F"VZE X 7+<exyf\*  sq4H>i|[uL9^ly"Q Q T j: h W{[7  /C4yvg!kh@vm&+MP] MG +Wh.aV# 0#l' B( {$ & 7( %C _$ /#( "wS}MX0 jJ A^j~ld@ "c%&U$ 3=%3$N2+P+/.(I* y% !h) I@=hN߇*t)T]Ǎ踷Z0oNhIG٫\؅Y ӧ 18@:XT]$Eqt' [j=< e\ +F 4n! B$ $&,a,I+'J%,+&E!4P {vO0[ T^(I'&+)_%(v+ 4fye"CKr` s K.3^_̜۲{ugGȪ#ʞk˰VNQOǍҲfӧåӻ)ޛܔ[go: RZB$ /|&1$25,%4!0 *Y$  ). j} M'S 5#)\ +# 3[.8s0:"1:/s?k6W?4F<1"4*:,2(+F$!Q! An; &ZRbYFBinun֤1 η ˺ PX:׷ݝ{ ^l޹w  q׭ suFO)u4c a "ܱ! }t?l@-% gD ; /  Zrh pZ, l j  "!*_#= #;d M  %t 0; ' M]'4k U&Y ^L[X  htW&W3C.%ǡȴ=߸\L\5ӞtږDڂߤߚJ'K)}xCReLy%RC!!] \S_dQN58QmxY%AQ@5 +_%V(]+a+)'/%.",vd%`! (]$? AfvDZf t  '\\#  Z R!" *  '7%%i Hn{@ݓ Kڠ ޒ,ӱ_`T/@i{4fCKsh? [' P{ _cew P {] kS[hwGJh>CG xj(G*W, pi7$B'&9;>7/?D`;47ts4m/KN*&kpP h1~u=zr['._ BCC%$+F+.2H)H8CF J7I:TJ8Q4NG.En#GbA R<[!2e+ 'A$D" , & :D } N g  *qޥؿӱ!GwM̈+Uɟ9?ӱaHC'hG ǾZʻ\p/tg*us/L,S ( ' ppT  U S  { !*&U_(^')8(#+M,,("x'{p)y("&s -&\%9#(P > Bg$w . $@d,V )O2 d#XPH5|NY߸1?kqB yb/YVS / ޥ g < 7 gm Xv! k=2',' 3@*vە۩zIGܧCc" D L[.$T) *e,,vb-Wz2H4)p2RO26 9h3 6 8 < 58c9T : M? ? : t8:S 7O4.-)t'h-"{M}% 9  B   u Rtf W5 bq/ӻ5cdҁЍv r5 o7iӧٍ4ەh{= =-'fdUpт!*؅yԉևk.q&iݦE($1r!=" }#g)$ "P !$)\0-&i.C - /2+1p{2 *-+c(S"r R0z .Sm+$!*(l)\ )! 3 i5b 2 /1] * ' #1  R U3Jj {f/ 844OY ^Ly#c0ZlJCdNPU0ۼ^f,Swu] F_U}߇4jz _#N G -O OGrV +D o"![!eR$k%"F#%s'Z$%$%)\!&%$%%!%9(/s%- '.(Ik"FT    9Ve2+ Sߑ 0w]:+1ޥ߮@/ DpeX&h, :NV"\|T3 dF" 03FR4 " " 5  o|3%V6\e _ myCU$# ] q <-D; [|{iI/ۋܱ]DH :cOCa9G42^ ߤ5 8 C9+-F+Kٗ&ӊs{,m Q rg < 5#rl? 9} V  \ hw"Qhyl _Q!^ -( T5Q 5Ep9 ohw&moMpFsCjbtd 5dv WK j: )  ] ޯ 3C}~@9j_e) F X r  E   ~ @ D jE+&{5Bu(k0Xh 0  j & /zI "W$$ \%$5 5xU  . Qf )C'&viHR>7K8,9 E4\eP):  ]+ }r {G AG Z2C7f5o9 js\CB  }%6; T3^ .  S5 ]1  R# "A3/_ E  W fGT {1 # 3fQn[{["f g o ~ `enFsH x"jWkPCK]o(>P73  L ` w K /   _uX#P\ 5Hn5#o3q F>  A _D  $h s   G #  X2le7 3 }f gH OQ ]Pa b?& W &W(Ysw N(Js, B  ^`  i . c   e 0T?D!e+6VN9ed 7gMQ)Np-Z9/j[XrB?^-wKNX@'x9ep+hk$Tv\YW } @ Q?jNkX\c[RJ p p sGh[|i* u # Q~.:B  -XxW)s Wu|`q5 k  v L  $ . _Y   m   0DQ)hdYZ z6#X_u|QrQ3! \st= f@p A l l v\\Hg3,R9HX.u[0Lw5? } %HO'RUGfc7lCl-H ? { d :  ~G D% tu U' &? N kv*E4L1fq&[r : $ X?B  UB " / t4 .r q y&  0 Y TNH 7s $id[-oA ' &# 7 IX4:Uq| 0  }w B K  l \ K Q ! :8lpq91bP > B^$C.JcQQOC;k(l9k y,jx;)MY,ep  U  + @ 34 e`p/QA}|._LD/H %(_+8Ms><frpuKZFw;KC%@n<]Ah\JK<{. &t/A?y`!A &  u"   m N   M \,#{{ #+^F T) a 3 4 au 6 ]  '  R , 6    W ay2    " i W & &/9Fk4Z"~:FXg,.{rWt m@Rrk":'+DjFT7-p! @K><  9  H K  G 9GP 3 X & A g 6P<  ! & = p  (op S / { 9 ] 8Q \~^[@]w/CtB{F6A.C_Wo+[I!ePmk3uDlr'|SK4)YO & . , ]  9 ;opu0ymX)KA ~ =p  %  umO{ &p_V,G 3 Sy9i|15yQ?Oc1` A7s!A4dd|q}i N  R A h !o t { 6~ "f  h  k y  2 [ F . q U ?5  ); .v(-s  - j u u<{=R 4 }MRuM2)5hhXvB&Ld9xX) "JvW.7LT qHOE '< s Ct | s  g _7m0`Q<h@y4 5   ' a [ ? . (  y    ` t L^ '0n R"}Ak%kD'nSd[U \E O* F=~_>HGcjEe/0g9xDh m  40M[\  NV7 { `}Y =Gp?H$D P> d Q d D T iqp(> {<H ' / F ?B|_yT&0 ?70D&uMY&/)&N-t]LJ#8h&!Dt8[K q \jg(!51)%.]p o  , *V^Ic C d  1Z. ]-9=?:  Bdde  %   ~ &< x 'dJxQ>_%!^u2Dtw`XK8A,<C!QQv q 8 `]   X6?R!6'j3gM k `/ L r S   \       up"<!`"6brPje9H r-y"g6KyoFGQ)3'p?x3Q^pjt#MB#fNu'DL'm. sHO}<Qyx]S< :S y  8  s _   # k r a 7 }  9 a Y i : } 0 ~( k;o&b pTpCfZ p *,3qVT.]b2@MWl^3|"l9XiL8e{R+PQl/t_8_}V]y{WP D C K  j ` S I5 !uYl[*<v H  " { 7 S t W 9 B  l D Y 9  a} ` W|F9:BhF cXZ=uPC`8bJ{,6">838Y.' EO O0nBY~"Z6 x5 V 1s6z2QZEO  .* yt eRrCGl'dQ  fx  Z  0 x a 94wG}Q kHw~(B.W9kbZze?:* ^dk|?55& . U 9 TQ  K  xk%R0M   X'1![]\h  $ g3vP 9 lq+K.h8Vk >R|'R0}|k!|+^T!Dj;E p"gh~-iEW8V^~AMo@5t 0 ' ^x{_F9j29 :N . g _ o ( +  EQld)Kt 'a*p , U : "7 D q5K&EbmHG4TAr*rb+RnQ!dJ(@AjL&jrV#<1BHfRCV|k \   g < $e(Ss PG5y ,  X i :u HyQH  /v~9jbKQE^e_21SK.9%NNV9iXgXAC~sqR`.rJg]E&[Hy ])/  3tQm u  "eQ9-rg] Ry +5   ]wg[  e d  A  Y2l k C .[  # q6 t sC L A-C| _zYBV$t 5pz?VxrrUqXAz5 4d11r.,[4OO`#-;; 9 | & ,CiajYO~N0EZ   \ _ O_y: B T [ ? `h p3` (>o5C7i`(X)v:WTi@NV&wB S3QipsT)PH{S?*7"shY :#QhLM HR#|>j,12c)CbYus6r]]4{)YYb~Ls6VN'Hffg6AK{pGRGP: X . ` 8* j    # | ^     " u - G  -@  ^ N a("trK;<:S^uLBM'~kPC7lr ;0N ,yg  o+R1weRJ , B| &0{-*Tr|;l -   /?&? r A V kPeegA_jbW exe*>lkD-ArA/rOO)?+pFZK|]uBB&V|4m x D  ak  <Z/Ec } U g} | 6 {e n  i@ \ $ N t(`O*U'3HGp     < 8 :2!5?qB~e!LPn?>,q,,iu^ #&."qJ,f 14mOOBr8#8AS u5_Ov`NNV,6'iskAM{b ' L E h K2  rR 4 Y T $   j uu  i.  ^ 1  D<P<0Cl '\ ^ 4  q  `R Fd>P!}"xD{-'G!q,U|W=MDpQXM\wj#t/~rty +"@?[?bRM53O  AJ _  + r h  | s  h i+ 9  *xw MYEPP*  # [  BMe7, [!Q?Z@]bdpS]Xy_%xB_>J_es78"kp`H[Z,3YZ0~M|)`F jZ e\u lsAS ;  q 6 G`E8  ]  .Y y8V& 74^1'+o$)p2~u6S-e d`AubW9Ffb  X`3cK" RF:< u,   e  ~ | g $ !'*o Ty  /aPZ%F h  ?h9w*$fA!@@V]q5!0Lg4p[lQc:1%  vQ<[C .A B U<)\^,XP^s.J  y[+t  U5 * +cc[ 1 v2X^vMOo4dR> h > F Ky ? {rO*&7s??$fi"fV^.K,K jGy6w+{NX2T nw[D9Zu: DnWR}i7G`*XlV/Sfc 8( + 6EZY'^BXd(f3+OJFg  a / U 8x _ {cuQFelQ ! K5 +S  ll*qx A = _uGK x,\R7`;:;/wsg7-|Jt% pvlT0E^6rX\y(ZO  c q x /  @U gx5a\$hCY ^ ` O gP #  jH P )  To  de*O|/  p  Pes^/Z# 6he20u}n^A!gqG@@%J:Nq 3Y h+yg/`?]KYk]"|j Aut% h5-W`b9kd DyHpCMjLijAghJh^K_6JdGyw}6|8eP"*pZo  0w&xCqG*o5{+-+9XFPeAL_|{qS\r^go&mp^ p X  dl;  Cv wJhS i\ P , B5 \ 7  c ~ 0 l>R  -5 QERg|5LKu;P]-e ^t^o8<=ە۩ݝ޹ ym"Wf7`E)|uss V  3d[T "  g   j t 0/ W    `w  ]  &  0D  3 '\.g_QCGN<o5  a9>WFgW XU-<^:8%WABL,?G'W:tNVS~51k 0 , m/#+yR"DX(1Mogofwmv\14 )  u q Io ,, 7^  ] ]N  ?p+E(`W;`O    H3YO/Dm ` . N oNq!:|Qs*?A?"|!67E,Qghm2t:Nk(W17'bD9Mj'7?Q \f q!PRtP~ES D :v   q :+ ^F  ,l Y gx *``/77|IGvO_ }f   , } 0PI*H2Cuz7tve ^?d4An@8}/uEdR J-2Spt2VJs4!7*QS&-qJh,+h)D6q<) [  o M G * P #[ 7 } < " X T 7    .k C : , a}      d<QPA/y Q _  y_1+>.]5p]67-'_KxfyqX8-qA&o >  S A   H[( 0 N1/ W M $ s  Ko<lC/x  h XZh1 h X ]m-+7WtxY[(r!SClZFd{S@_7_YSzeJE , RJdqK  9r ,Z'[];6dUf X  M!P 6 [  Jw^ D>SC<pcFMP(N)4 x(k?/.f 0d ' OiA\vuv] 6 p    #  < _3  - 9 C T  "  s A { ^      {Y a  C S I<  "G   o ] $L i  9O kl@ k"rLFAJoeX|K5k/t HCHrfD~/NX`M5SjYuhQ3E^[gCJ >F4+ jS k & <; 0  ky X t<  C ~ ~B :L    ~ 3 o ,x 8y N3] !@SuFS,H oi-D +%.XJ*_p-S(#;>wllX&]Z9#i;'85FjKRCEW ji r }Tp`j[,f [ O  & * "  . b ,3  -& h Si   J r   /   Wq 7    ~ j D  6 N%Vu@  jZWR ^ J..W'EBTf|eKB`3cS@1 " gxw !>5[<<E  .V  u 8 @}[95 ! "5 S WKv~# :o a P   ` 9 N  k .    DrOp%d^ oY4g'8za-25}@DH&ڳX3ݦBߚ}bSp^)3T"6 QD}`jxCB   C,B 9 L t j  I Wkx]^qqLMWO1dv3 3G # 8I  W  Sv . /H _ x[,95A߮j'ܻo=c-.XrQ&P! W"N|"m 0 #  qyO-X A uh7xyMHU_?^4 # o~~Y7![G"2 #1  + SzCd SZc"tݓdkoF4on5ؿ-J{(i߸Ij9!8=w31G' U}F (&aMr :7dZ `   q.  IT h^ S 5 $3 O   9   ` IQBLMgZIw^ _    u ' j / W } 9 jE  C B / X  G)Ze46f-6C]*w6664siON{(o:GC~fg,|e[W*b)b ) D~T|g8Hh!TP  a L ! u-O9Rr5mGe! i  =Q2p# T\  <S0%Ps LL *]M ]/!u`+MVZh")h(YRoJsjW)k,G})B=s Qs7 ,7wR&H $ ?:/wT D#;$A&B*r+<*-)o)f&&$EIxL   eG   t 1> u'HSS: 8prl*zRg0Aܔ.kޒgS!d&BK5Ge_{ [0fXw9 0$ ~ r[!bP*PY : -P`U0iDaa7]BA+6!7/]Bs  _ K  {  -&tB0GhW/EvYnu]2AfIonc{"DKbtVNu:'2$hRG5:-:V-~"qfeh4l.LFZ t E?}4)"7!!4R6|!K %":xP [ ! SJ f 9 N)5B|Wgi6L*;{C/ O(Tj)E&.hOKsNhY,|  dY NW ">iHH  Y ,f H  p s 7 E  /t5  2[ Tw H G##$^#K!" !*e >p.SdRX(5 oZ|[ M]}^mc; ?<oHT^ hc8K  K 7shm^cL? =dv  Q!^ 8!  _'A fnxM(/e%F9/ T07C6`  shAti )n4i[x Hy^^.%C%e,s3~Z,:ZjBW+c_- _n  F E | h 9 < '0 LQ#q qRF! ip   P Y w 1 v t v XlGv+ A M  L |  `  AQ C  W 9 s ~ B . i & mdL.~}F->?*L.xo V|.@t`v8jKY _ } }T #  ? o Po(l  A  j  , !  H  &)wdRwPvO  jX  f K2w`]9 G4)N ^ t 'l5~ eRs!Q/1jF/ Me d - ?\k,o4 5xRZMXkkr`Vc2X!Y>RSqkO#M} 5/k#`}#x`+_mk  o },@# R y  _ *+, q" hd\ " @_ ?v  g  ^ L ~cx2ePHm+5?h-ReHqVwsF*M+S9݉VXݝGMr>,,w?f9:" |! W#! w L } 0  5 Cd aBg*r ,9|,Z  B  mPT[_y#ty { 8 S  q  &y j D'lbFJ+q4!dG6,.3{Q1XQl7g}A+heS4N5J+:dC\Ey"\l< ` !}MZU#  U T      - i~ } 7+Ea8htr:c%N 6N k @ 3 r  X ;x(L /P a6}[@i)XZtii:j:~2(7u8 R9CB NL1 %)U5u 6% K#?@|q4 kvlmi }V|TspVfj`0AjvYd><H!PJ,%#-ow2oJ3D}8?|*yQb:<3"@78]W&N*77 [c ) j u } CV p } . .  0 _ @ e / u('\F89,]rL#o  h -  D N Oc Y :wx w!5u!J+p)k #  "! yZFe_7xQSQ B ||  q r $ t 1  G ^Y~M d3G dG&)j7 7ST'/`x~6" 7iuu &D : T0 X | 6"x]JJ  J ^ \"^7W,YNWS.JHoJ)?Vum1|(eZ*\@7tSW-BX@~u3 p*N@ N I[V%. i 8 l1[:5N@mPDc `  s -  " y+?p T ~ i v yQ7:fQgAL&'o3y\,cso?sU%B4 jF:y\'C.<r5( b ,">1tS Dp |=Q G$5S5UUD0s0kcRC  6'  CZe <e N ^N Dxq2]qfVyH,^QJ\|-``oM7}\ -vjA\~ou"|1xBet-LJqG?YE sj q} T {d F7    y*wcA DC  x s AJTX,=kis(dvMZ~|~fP9k f<  B=+G accN ~vcl)<c1 Mp?jW{0X@7BLG   N u:3S -:X7PN<\QH6**\-G%'fXCHi+TTHKsN kjK 0V Nq :S+(F[J],A%J\o L j |w " J + /4OF4[;-K M `"7-LCDNyQ0QHX9lCu& 9 L &N\p I7 |T ^  @ t X)[:hK`A%TBL."BS"!QRy5 Qn5#-q8}.k./~W/&Nd Ghh^uq(Q ~V4Z ]  t ].1gZ4`;~ &   {5Ff    { \  s W )G~i}svet M  k uu D-wt'[FLA9LT CHGfpg.#mbuNDBJ)h+ b&_K  N  R   j  i   q t ~vW8B$|i6^UE8UU= w  DY+d S LT  L=o5jw3n(Du.}+]DLq 5Y!Ezs3F8)F7=u+nyr?i-`v s  r{ 1 } 8 ~  " {     W X  N l 4< K /  Tv )x*4HR%qW L[U*:>OpH5" q^  V gh'k6}qKi u ]/1DE_67r_iMykeo~9wWB #Z?8!&yP(hSE x B B  |v   |  7 7 g ^!  } ')DkNg'i(tH/ _ p "MTrt.LjNT/t0wH+S q|F)0x!0.qt2 `uWL&S5D DY/J}4?[q,js^x `G j;    t  N s tY ; 4 j]rr}p |  /:WLjjw G!|T#!L8P~>KPl%?2j`ji"7Gf> (mZ  4 3  ' 6  F1Ea%A W .I -  Iy#/e G* d K W      ,  2wqs@dhNFZ qcWNR^ߤ߸r ettig[ kC')9Vhe,+K  Q 'm s X T      d  1 '02Y9HXA(Or B -(qXraK:CD-_WZ1<%ZQf u ln lRw3J:-j8KL=J[{-,-Jq|sCu))4q)rYeL(tb1l Wh`MV N#qy3/V  f[f  i jMx 9AKV7  ""P"#%Vi# :!X"m"mC!nv/xa\ 6vCR   A6Mc|i`uq;5*V+r"WNZu5bAXa-r8~|{y550/G.C3ir9SM)Pf{F 'O L S D 0*  c 0OLBo f Rr T  r L  D9S&-3L8~ *op}w_:/>e ]H|BB%^sii-Kh`bESk"Op[3r)WCO 58eyd&Osi7A{l) } ] ^ ] n mQeQ1R3-4/aQ1Z S  @  | s h B t ~ a c 0 0 E,&!PgA+"G{!yB|[.qWkY&kZ( v)f]g~?:`CHn9E/`28tysP7gB <Mssv  / $   p ty + &H W+ e : j** k  3Z  w DG  i A M   " K i Ct F Dx5RRfT5-7BtA\l5|qC35$߮8rLW:BY|}c2*`khn|s(< RJ\!w:iCxFcPTGP <"F   K g . s  G:4 RL\+   r3 y  Z F w "   K^ ] "LEp< Ip | r r N   S  >  xSg8l5@h"BX [xy-Ft:(X^ z%uiHo\>~ 'f a[ w 1 l'/8P TP P (%TK6S De f kY   & D% Xl N5f  h    | rTHy q {xrp.?9 h <F6DE!}8}bOt`W]|h_/ P6Y-Gb6S4H6#K,J.JLAetiC+#RL,H,ht?V6@@ [ Q* G &1 X H A |  5 ]w   B    K     . 8 . ] `] C+ C ?:`u NZ5,r1bP[k]K5L+V&_aXBXw? GlW|H#D"%)6 q)v a ! 5 ] T #p4  @ 8  DG G  r @ r  ' q!7`qix&gfV9`~;=)0k v:\[K.{/`.(^4  C   N X6 QY\Z;?}&-.mk~HjLZh R   H)E  M 9yH Y<   ') H ], % L~Zymm@Q x &Q  p_)[et<5 ~+ bdp#a߸TE#0 )u:~ !( B54H1/f  } \y4A '@J ' ' hf "j @ BxP#4[(Xj(<<Q  =pGQh= e A |R &5nh6D3cfk2= -aSm 7 .&;B &ZFg{s+uv|?45l|F yLL6F]" S^z [[3>n? \*p* fxut##M#H(%ML ' ZB5/n I  kut,\*:M PsxX;q 9 & -H!= 6#%*+)$E,; !'^%;gff .RƘǵ˦$վ+uЄZ2']wtK4 O L f;oBLkj!&^vTgy]  ~mT~GXjMe +$@" #v %'M)5)!' #Z('{!H N #G) ~@gd;AVwK-߇}ޯQ  w0u&"w  INQ t /gE[E fXBܱ^˰P'7ώ$5JBN_߸ߑniSK9 y$u%('\**(&x"F #Z   " ;Yr.%~QkW/|"D'))\33 3 o,d4.}(]C&8&_"w'$W![%9."w J՛׭cw٫_j c#?KR*} MV  x'pWR H\~    X o!Zhfh  &R ri P Cty 5!*%$)&8* *6$' %3  Eg=H_m\тv3}ە_RUuCQx[tXY(QNc9l!?WO2f%FQd#[~  6 7e&I:_ 9 W g 5q~)0%UX M /ey6t]'xآ% ݓd"KUe"w&By/4:z>bBq B BhE@GO@,7/,;.($'#Yxt&.s$ 9Yٵy_ 0o2O "w%C?'7497<A8 C"CFHa#F%B%B%9;++6:,1*/+2&'!%M"gpn  < G@QHX9 ")! >"#T#[1m  BPe5+B71՛[{uiÒCPV| Ƣfm A8+͑ ڌ ^پtbG4"^]~Ko8E Y +t=y v^!W N  ^  m'J:*k-,(/8H0J1S 0T3 1].+ ,YY'%CQ \p   @w "L&grXciwFMF ShQz= !F]3ۼ؅=RU>V4ƬuZ#9d{y<:Z#RA3f   'd Ygug!%t{!=!C+P}y D 6 a] 8*ޒ ߚXRi_$#E@*25XR@%!DEVF<X0XtS_tX<SK.MD<[3d -: U)> r|58\>{,G,ECydv; k 7  _^!% ]v׆H{cǵaw)cᘸc2"ܱ=Ü#AۋuAJ9s1,/(T*5''))R$uv}cn( ~+ aQ  i T - H| RL 3  % ((;!{0rH-a}'gS m^># i k4  \d Io ݺy/6ͮr #!`ٗ|ܔޯ6^DT .um9s4+_^7J^.P2>iWڌOKc՛۩آ :Q] k#n()&07L7)5bO2!4FZ2> 15k%#O#b&Hr~9"Z 1[ 9 reP/ZPuh> U0A / *Go8m2,1b#b ! <"" "!n[$#Y 5?aV\ߚ5pss>EеO>ҟȃ=L[9ף -ۼx }S/W i  6 } ;gsT*<iF|!yfCsB?1xZvcx _y @!l  x  ! !y % !?  ^   B _ 9 }*83p ++n  rSx+4^2rEVnB_]d4]@4n2Skl>]*ߚݓCAD  ߸ vBlrN g } A > @)3 % N a8ZK6s48t;"]# @- t( 5"i%&.]:p<;5v 7B#>:4w1+&$WS+ 3Fjz'k e 9#T#,* ) # , ~  E ^  s#}w:h, K[P_k?   p"%,.M-)R-*G &B |J }/;nRڂ8٫[IZ%L 5 f4Jn:)%h  ebFuw = O wNp ~ l w"s~VP  G;P ,  *\JZKqV7XNߚP׏pp1e܀߇3 8  k U k "$&%&(Z&g" #UN]\&$" 7 ! * { _G  u !$0)!-02X2!!=2y" 3!1?T*C&U,"l?!qMOrG[//͇aG LVڪ X ,BGOx9#5"2,HJ _%,h}ߚ]Nhn.QJ j  [ 0#;!"2"P"! f'-''i''^ 9(S**[&}k%f#$NB ܊r* Kw { +yGOR ] E 6 +]ZpSn}gkAB^ gHO ~o*>uA3jYZ OԺc^ g "`Vn5#_hE"N- 8ޒ  iDgUNy;"P]S6 H% w%3'H))?*xT,,l* %s'#vT Y $N 1++c4)mڽD:C U,.g#v,v.p+F$7C3,bJ1-kq(67#GiTC'j]*w|Y j hx0[z!$#s) Y'7 #O! @}0L _!n"s![&$۟"ʀη(xˉ+ ӀY5bSVR]B WKFR Cl?P@QyA9 w:OkkA-)v?h'4 2   Q\3 ,? $ K$a #&3&p%!p7XEJl9 #Q_I6|eݓޛrԝ%,*"ҕN<n3ۼbiOx!^SGfK6 -c55)1e-*N \ 64 s;o5bHE_"tq;6*X2 Ko ES@QoQ   c r gm N 7 3 Qy5 z [cMi`5w M 'YEka*NRnK Fm @zSG!mk!"<C#"*%t!! ,  d wW~eg,6^lv%0C  8 R%$ }.7V34, &0- ,b S&. S!Hy  \ & P2.u)jWZsM[u\ S s!A4+!-|0H w g tYT;7`cdIaڌ:ܔ߮=;5YJuDb+  smZ $  s 3   k -? G4p)cOF(2f xiHD7 YA -L?zkv)]-,>w]%pvJ g 9"GSl2cD,^ ySsj5 H 8 )>(]"<' $uD'-'-&*![( %#(   kG ^ ;[P{M%qm  NMd  ""F)_''%(!&+$Q)oE*%:4X9^0n*&ܧ9 v^[ : 9G MWD[B3*N} 5< " 8܊EMU('!,) ' $A"#Z0~20-0. * 0' #b ! mDm 6; {c)l(|zZh@ARxBBG(XoOo  F 8!CF`&s#Z<З+JćƬЫӀ ׷ JX|[aT!|@m E U-  N ף+v 0\/;%!b"(X/]G 4|pE4? ]# -DH* 3 ' 7Q  )!   $!x+),*n&O- * %dFhX| A?Fz4@ڂg,SL}yҁXi!&' g  u  - So 7:j{,Cj޹,Z@%B (NA'}+ (22\ 2! M. 0;,E($^{G]_ !=o.<H@}֮ Kآ gݺ ߤ ZR$1#a$W !*S9t< g   x 6dP&;'M B^ U  jiF+S 6%Ab??&''e!KT$V ޯ[ܔ\u\2BؘWa5oiq *j,YW2ho 6pD(:k]7f @\)"ti%"F<e'! uj;/PHy12fz 0l{F 6S S }\yx3,u]1C6Ds 8 6  }v\ si H4` uC x$ $D"c)d'&##!! %[i V7GdTK^qG  U!H!%l(%~N8* & @  8*p# r&m [!Q5*@y`atabQ_y4F*l M  k K3ry<6m>Yw;2gndW 6o@]0A r^)9 A [, 1]'%V$k! u) % q$aQ!sQPe[R  unqs= ޛD+٫d B= 92Iv)4Nьa~ΐ3DָX:Vf V  L Iy vR r$u`''-$u1,1]./"<w*%!*t) D   ~O'QHu=y 2v"c )!q47f5e.tqE@6W&4Z* _$ V {.c߸hk+O;T^ GQQ6.l,c? U  /2  w8-sҼ B\1c{:D q -A#(,1,1 45+5X2!*2y70-k\*& # > %9_'%C 0h0 '0J -D>/- 0-,Y L"o!=%"2"4?q4!G_Sl { `z T 5~ S9կxӔĚL:}h DŽݺuitnۋVR wnKD]/=vVpݝX$^=${ R w } Sp*n[hDa L ] _,mTiDtHOCV8d| i"A(gY(y$i+6)"'J&", ./|1.3xO2H ./ +)#3.a< q:7{ 01&A;r_t 8 4vqsZ  { WQ ە۟f>L6Pܧ!D߸ߑ܀K" L1f'4,O/_=<>';oF26@ < 6D , +F'-Z$  R }  9!= #'"%l) o1)R.-1-D3,l5:;;=:=5 ;\E7}80^/05*/#b'TzC b8R]ݰ1ٵ%N|ە*PjC#g>O@J*uJM[| ޯ5 ZQqxU/z͇v9ԓu"ޛ5qMfKFJgHrESۋF}C܀ٵnڂ y!gozb 1 M yr: ^ b N w3P#x g 9,O1"6D(6(G 8$I997J$5G+P=P:SNQ3 L/H+mC%=Z!7/_' !i?Fd! [S_)?* I VG+ A_O O'#_E,܀lָ6M8eP=H̒EHϬlMT1,ܻ}bne=6P!yv0,c  fHR7-  r4 v  6iE=.L z~=#YnOs.NrkL . # 8+{ _j ^g '  wOxc   o:۲)EU ܞF߇K]" \pRLtX& K  `?T ہآآ \ޒNڪݺK-?֑,2X kt*^gY02+Z-$;y81I.~ :) k'(%{Yh=m "  T p-  C ]{TW+R$&())H k.~. *4("C'#6 k%t #b T^%!pE=!' ( |R,  & S w\[D\{kWIٍwޛ-vt k6[ \Sy*I E%e`Ki0 [} vx 38 6VxX \ 8N , y :  !' F  ^ C `3 V Q| /T}&^Sq!^ J k]-H!&?   ^ YCcs"`w<+F \ 26C5FvdS<,[A;E }(u':t$Y ,Oe U 0r"S8[ZTy" +  Sn/L \d  :p^ B s]4G{J%JK](c*2f4VfTvIe*Du8d4:b!rm>H! iwpX k $g "+ " | 8 7  /OGyFpCK2dY>\4[** H~3_ uIm~;Z [ ;+6Sx** h"!eReiuy C 8: I8dbOO(F3qG % X L `I ';em D5  W . S95mruoh6;j8``i D%Ig M|dp9M PPR3L"T-S-fA,1{r+{!!lu]x5;fq)Rd1xdkCiosv X t J s\ 9_MF'J> ![~tML@1V; & 7 6Z5O+f Y-If $ Dx[Fi~X_}yR , |3:o3qf/6: i+}BO+v *1ZCV[R*)l2;f wx"sMTrV*txW f b K +V-!Z X #+$aa/sdN 6 { H  L>byu+ ,DS7P5 o 9 M%sx/5; 8UNtwPN) uo[G[pW8$&#'fy:|^#J a u  *? : ~ =,5%]Ti;i[C @1 i) \ VL1(oh@h}C8Xh"qibR=g=3drO0's9{DwV3 &2  Q m g  gY  Y  Z e\"Vr'-`"-Y H $Q a   5YmQy+skgS6@h|9LADw>@*,M>( Zf3R fR D_-#y:bQB*r |+f(s ~ypuW?k 8_mMC%[KhL7QxF^F}j^^^ @c  k  .d   R     C#    jdQ)tJ55 g,"7yMfwH :o ux>GiLEc 7P 8[5KLWBT9JMQ9sNi/u_L :u/DeGK,Li&oYO-NlcO9j}A! ]1mdN  k    , -  8 T8 r  s -  | .L   } ~   M! &  t ~  < #P qZw  aa /W XL 9 ~ IM ` ,+ !Y 7 _i _cPLG*qcn>-{_osK+YGR]6F;?lceDNC2}lX-+gFpdg]Ef"YOT| _ / :  m t x i3 h F r   K %  {  7 s5 t " q N V?{Mrk9/4&p~QR%\y.JBH'hmhd/3D9~>e}HfSQQ6frx4GZD wOFtd_S5@ 9 8 W I  ,xx9. ~ . O@mP)>4R| OX"V.S "u>Q3x"+8No|.B9~/jbHcm1ZBf#WR|=~mY*eA8|HkMiAfT({ R  jJ   ,  ,\\eQ3Zd  }  s TG  Z  ^ _  D +6_&X?9 C :/YT*\Q+\" / @ 8h }  ^_ $1 k c(\g:Mbb9 3sw}j+s[gRF ur>mG[sgt-~B~V}#.8H>wuo-JZmQ, ief#B`:6cbC!}|[fqdo|ku fxGo :Cyb@S] H 5 |,+-!. ' q7 2>p""7|Mh@cpk(]!q 5 ` P   qm YY lvc OOwo!  "| C #  V 0@ ' t   ` B .   /  & \N[&e>J, M6Rzh!B@6p-y>2E E C S4+G,KFOiyL'@  ~  - I ] 5     G o  LP  ( /   0 :W  j  0Y1wf   EMBf[)oE fR}8TN;vc+,60ENuD[u"MQ1-^x-{ C  &  & " S ]7fx PF: .~ U 1N|yd.- `jD~B Q Up N Y )q 7VM&u"ZgK2NoDE R7@Wld L8L YWB9K$qQj`furm<j ~h +qc ]!  x   60 p: dG5v<P Z<Fdd#YF  P O &e4p+?  d   'K2&rPk!-W9.MX4qjaj%B[L[ \*LTRf4G4F3<(MB3GpZ=ubS^\Y}-G^&\LAS)wpo  8  L j L G8j_!r'!  j D/Z';mE_P gw ,b d P ~[EeO4[{BG&3D$]*~W`Vh|%C:-q6Af, JpQ2Z; D ^eD8TKRX*+1 lxD:{u'iu:y e !W4=  B # q  :E8o+"hh^h$H;<= ey ?  l 1xo} 7H jX33 vHcFKfY tQldZEEq " &j]kY,YMDZKb-AzV@D3 Gw;D ~ & 96A6Psq m A' @fIN^V[ru !f#%%`)$&&#Y -~j?h \ 4*H7&86x Mg }u9  I U(B M6ܻL=ض !V}WCiկgu  K "I "Qb1;mx_ 5 Tw  u ( Ms4 PRX j1V'lKEHCtf` KM L @F4 ;S`%&p%"l9EGE&E2'j?' 7F1d#4 f>+7  _vLAeZ3wl :s N @  C  : : X p )TkWu/\57ABVM9ݰ&uߚ7o%p}\ D &    @   B :^29dtE~  ~ M~G~.pA^y]; }l ~   k f h k)eHLq:ZQQ`>K'K N .b Y  v   + _ ' 3B~5bHd<[G d > Dq ^ '/   ( !Rs",  t wN}ukxdp!6!WW~ =}E 't7( @ H \ x *  i  N X7-G3]FX^DQ 5{@u tq/y5 &y 7f @Z;6,8jB g rt I` - 9x tY/cxl hl3<;XRK5 T# 7 9'c  qMK 4R6,%r"\z"cL#G .; /-Dk1Q: g  km&s'`sr RX & s r Kp P a .L  !eNZ~b   s   *jXJ5} Q}g\`{0y_qy [MA)^~~ZjuD/j}.T8Z7  t ` P :l D  7 >H B  C X #  N]2p9HkXQe?A&W.CnW]w_L\A]7gdB7w6 xk` w*f]e^gqf,M$_ue(lT}(*<     s . X[7~!>W:_A2rB@B)k#&Q  T x  Y|u\5  a3 & 0@rW{k<+]N_8B!sRjSE3(nRPT"SE 9 B $ 8 &E DloqS6.H xnZ ^%Q7V    J^?+? G 0 x  | -d , I ? 4\i?[o \1og3*w    #  9 LC(@!CtAbh1 C*!pq">_h{~ _>e+4+ ;Xv)*e x<`\"!e4),m6`X XA\#*t s1Bviq;\2YWL_f1L\!)l; } t l ( B LC  / 0 + K 7^w|}A-^8^T]S!H?sMB#smG?|89;[K8j/'`-kKCprE N U } ) )cF%[ k  \ 5m35 R_)CMMNE]{\).Mt`?];nj e"-0D'CRD|v8 .vJ4O<<|F&{YnPW Y3 0k$S]$"JB9%]_< K+C/"cD[v ; UO  WsC>BL^q$!A|}&fis~6':\N%:2x)nNtC,#kM ` o  hc+MjQ d/Q[)g* 6 v  *  >  H[RR)!+6" j8 `C t : F<? h'w?6D]vR(xOEWaH tU"JiLZeG=$^~}Ayur! h[Te u ,mm^, !Z  D;<3/ U~[p P [ 6 )Ow  DN C O wP RBHpmGf! g .oC<C [A g#V82bus?7,T,\WEyRP55 yHZ,rDB:T,TiDibY*n_ a , qO I  Y 7* ?q>_F!M_&Mu Jv k  ] > ^ . _Y tv w]9XP?@W<yKq~)~kKQiكzNܧWq&FqO~3r  ; '!  f M. c.vgv3> > 6  i f !!"P!Y  QYB891:OLd!z"-"F ")!=f{ %  De4  !   D#p3H>{?K-}kxYVoW'Z4eOJ(n;_; Mkk7Mo9~ ip:s-H{+_?fkJG[^ ex 0E    d#  DI ! " $e&U&''h&?&%MQ#b!G\dm5 :`H6wJ5+@D2DM,"?[~Wn'Q5\A_L9.Krx}4 kr ;t23 uQ gpgKSV !#"u":!:Ma.E y)!c 'S $z  r S L   $ T Cc{(wy<x +xKqAQB^I[r>#4K@[m*<Q7AC'0'rc}_Th_..,V *DI :"2#;" /"P ! ! q"5  hF  ] tl Z[ g! S  )fS/p2vX   Ni X  CX C    6Ew7}b^VEV?_\]EAN.i -"d"P)\pG\ *o uB @ 'My)\{Z :y`s5SJY OG >R9PNdrC*#fZQ*uTGHw    ~D6! < :P) u q k//o=,VT{2 C |eo .p  ' N 9  B M   0j NZx - ]8hH(O k & ^ v IH*f<= - t')x@RLZ87u 4:4uB>PHrX2jOf{h!.ZCuVxWm~ ul_Bu/3 X'"ZcH]CB4 o @  Civ.\'( s5/ voy ^. w4VRD6t@s! p O  U |Ly$Q*Wv Y3  : '15ۼNh6>Bև$ףzږ܀{e '  R E-:A$dSc ev u]  &   t U s x "; ] [ (e )iT_ 4!Pd_ ul `     +\  q   Td -<    8^ A `. j & &  $ ;  {- S P 7> ( 3 :w # X }JG5g4]il jK -+[5DQ4* <  DReCp}#~@  &c|'4N . |51 4t5a&k9Z)\  0jtKvbf_'Bv PX1SH  .R y f  L k@"9xq6RPC$Kc5:M`H$y+x-e7>Bk>SV,dr UZ2$h*CTL;V@ m  " \  ( T u W x 5 B C C> p TZdPxpo\ HPGw N  r @cv  u  `"8#;#$#Y"<!GU'Nd   DF> I_  a[+V\2}x @ S+]H*Cf2Z(/ r   o1}NCET95 Wv*Oe  /cGR]0|MikCka y@>.ckbu(0)ZG@NAPkj~9,}?8yL!r 4E_ f   :) J g2:W4) f 0"%3,d "Y!G  +6yb }x/ ^ jDe0Do!JX@]  S ]du]U@>f1I,Y`5 7 &OC#F W>'2:~LAJxgN-?-86 C hNUIX RC!XB!"Cg7*ZA<_P8Byf W 1 C2Phkg(X2qhFjM^0D}< aFsjd%Y r|N kIޒ&e܊(ܧ tZ޹-z n\ rEP KQm $ `~0O  @f dg_A /SN?NGw* ~   Q ` A y d ` 1E G *Z gr",Tq  N@ @ I  {LyBR+  r |7 t Xx *]A'3#uP7%^J?,F}JNRoE_ Mv  \(QDPd4 ?k K jC (wTG7@^ust6sd*eEcbhH ^3  & tz$0%&$ # " i  X+  TVOO_o`[nPn8y-NV4<vs ~  WEGR63&M2t\{*eP E)@:|S?6N[?+-e5,3x>3ZN{<5,E6 C .- | f  M4#" R  8y%[6tmbQ/g +xM@.E\Zt `  c  , ej3Fy '  L D <sk]rb '@7|\*L L R<E  8%#_7Im q  Mc< g }^ :e[s(TZ,y.huY'~CC<3|5<d>y,& !f\-fH EbW!QJ*`<8V\ Nw < x2llj :XwZ4  |w]+d&8V8bd[& FllENw.ryc D2Y^NNXt:fo5<  } SN4gw%98E. M/ Ua[DF " K lk3f 5 0oC")4[q>; F f y*+Ge   ` OJj9fQjLO9.M t#B kD}7R<qK_ m\|-|6f+yWH$gJ|h#`9$P7T.jx`cV8)u~,eNi[+oi *; X KN1ip# jA  B  Y G   9!d!hrK""6)   @ $1 6 ~=t/   t (  ~sRK&}MP+TDBcHy<:}M3 8 TlB!1^6 pH Y } M   L MZ hf | i A  h r  Bq   <m )6i-}L<[_5~i@8|}VsWkrv|(|FJJq~s,C`{\F y6wFr@_/Y05G'&[ &L,   ` K   t<5"x^R~@8:5Jtoq.,8P     W$HR@ # T D i ^ kR,|T7+B #)gy]K9ln 4K>[g"6|vXLtV1bH Ej)qDX'`/;_  h 54)rw { !   /   m  > 9d  M CO  X C5 /  9 &m y  7V_v.2#Jlo X _ j ` u -   x  ? h q}O6HJrzQ5 V Rm `dw j ]#5.VY\lY # x k i  , A V : 0 lL29u X j: h *ts @<x X  8 ?By:  * = [ _ o@v1 =5]@Bg 1s5j=ZgeP<) 't*G[ywGcQ9):Xy?, . T {JRO\t'IL< k` - "#6%C&O'-''$&K$"!V9QQ-H  # MDg 8;^ Bh}K8$hh* \ +\c~#VJ\k\opOSvKg?n[Xw`| |)7w$||giE_   i "kO~.  | $ }i.T  1 gD  W / ;;smG6$yt"TV:X23V)Od3j-?EHX}W" `2 6 ~ U   L B 7 7`' x+ s B  a9 '  'hY" 9m 0 M    ~0  9u(e=G y   ? .@    9 / ~  L i j _ (!cH)GH6h_DCvh+DF?^b{O)KQoo+YL \1߮+ia'۩ N% "Z]ݓ߇J J j k  d(;u i5hh^ss|H   D C w;Kp*1L-F,uF !! yQ! "2! f!7t:_.~You  lo`@,"Q\5y?pp0ei{k2T9@!G"Z9{_ C^  *J+f k s &;<E u ^ L   X  LU  |seeAMCX$')9|p R  .n > QGJ@|p)4F{vht L",b6 G=F*/ 9 V tyjf~xY =  . ~q),!kL7*L`;' ` :[bmCWh"{S@xo#LRJ3KR C C -m _< / h    ,K #  " 5  _  s /e -:j J}'3 5XJy-"_/Zjn`7 e2FsjD/*D3 k 6D=(tRi {Z;! S /T   L  ~ & /  #( P o !  KA |  U .  ` ivund HGS   v u 8 " x +  J D#}j m [cAPWQDPy5y{H)OC*[ R\,Ti[ ew_o7A\]*[4Fc33E; QfV>D  U+  AhgoS?v`hlF2  UH h  t $  kE4YTQRptJ/ *JQioni'E;uX:kK,A+]f s};Al(G  5 d C  D(G-K3VVJ Y3TxX3~2  7$ " h - A .jjXKc}./ ~t^A>RdR o[ \pRDho,A}K#ApuMpg,xF9 NM X  M :98q_`Q]hiEH)Poye5ovCS?)gs][ e  E O - s _ K s  e D w  OO NuF`YNYG !! ]g ZR sqF3OfR{r j/)_ZsBo2@+gLCjn2NP_)6oGJD-|aL_RM]!7:q&{wj & _ q\*'; `  6 #O  I {Y  < cR5y9  ` t     ` / D '>3Bx?dA%)X;mlPZf5!?hb6AMs9hV-V%7%tM:_D}} #y76r?CQ3DV|pv  8 G?':Ker Q  D Xcw*`Qc5" { TT C  @R^gh5f5*T)9 "tRZ+sL'.?^,->Y9j98#6i|ywel[l0L }\fG 'l B: rdk5!"M  ] > :+ D k j  K  B  j2A@':u 7itk# jk | X0j9' f kej*;Ptk"bri*e\  BIH+zkDYqqY"6^{\3u ^Zhv&1ir2h}RHH   O   3A*_%t!M~Z^G2,C\6 =(L"Fo$$a<+ + (z B& $,r/ I!tw[ j+RZ-Cd C%() .+*$3%1-!%.' r CTHwߚV тfqHP0uRN>h31ʻ7 #԰o| |P`t) -#-%)%6,5,1?+Z)\')\+$( %9 \ 2  ql\v"+\S/S9C  MMHCL'{ +_ _ 5("P?ٍڽ%١|odۼa8ٗܧ9:Q\]AZV-4>Vk6< 9 ' xTjcis*A.h(xd . 0p@V&tb p3V9  {?kV"%~#t7\+m @)! #Q%!x " aMTh,=u_A'zY- "7 ވ"h)܀ҼYߑ17cR E ;Qq=%! s;R ZӀt4ӻ+DX<T74fl z 9$* E, k, 01/s0-N*x)&B"F5 <$w~yC8i|gK|)l&B#2  $3 s1l M '*(, ")\ h%P +< MC<+ҟG _wV p`y<׭ۼ{'qCe. ' qE"Pp  .\, E Mbہ:-߇h h j wRO 'vg;=a%)f*(-b-WT,y+)o*Q &f#`!nF'Jf i 5\5D ہ&}e9AD)Gߤ*2;=r.mx#Q>{7kپ]DYDӱCY+Z#w# 94 ( BP"Zuk%CV.&(q*>)fT0,@(,I~*eK$N;{`/' |sG>/ G AvMD##%Vh#1/B32522\-k;R3:/9+)5$6"1,)K H!YT#߇ƅƬ&X|OtSϿJӱ5B6-]QTJ;( Rie1t|<H P  , (v5fPwo*ܔҲHߤь?T70y**=,1'g`."P-#)>" $D B~ jg( jWlZ ([ەt D 8\K G;OZ^tj1 Kp  {  F"P&f F3g?3߮"EP7X9x?{$f!H "v "Ps(h,l4A. x sxupA<2hl5   9%.%`$78i5lR.6N6k2> ,#! BA ]dm {[[NfL,پt4 8 W" TuE7(@$ *&K&$ '("'r O c=pjʞٗʻ׷R?=8 * i:mtS_' *+P.(.,W)$ f f  [$4g6juW4lpdM~42Nyi'+wb- s +  =fhX;e. $X UpCE3ihJ)B8gqf SAu( A<B]g`9@"cMc_!bXJH)4"F=Bxqj%y*b~w  ]^^ H\ # j@j Y@r[}u-T3HiD1E! s* ]%dtN.glTX!% ! %~!e%`$N  `  u Y {OG,E<6jqPn_ JY> LA^ I"  X9t|BW u  9Gf*_R)"l@xߑ(ZU&@G M el i<|i~#% $! ""m)5%t'A$#!7 ^ r P"OjNM,ڠMvF.f\ .  b"2!n ,nw - hDE M PVZ 4p5{, 1%͸XD՛>Y} 8}A** WZ,G  . !*t+F*G&s;zt gہܻqՈD0Eږٗڌzܞ9%!5]~oV< @  5: +  & ol0dich= & @ 0~sFy   R= l~LJ* %&J''%Mp'&.g%}$S^%7/D " /QN:W$&h&(!%{ T e &_h!ҟzЄ:ӱo˦UЗ?LyJd? WZE' (&d! #+Z+'#,(i0^+*2!x+1S z@J].?kr`.Mo4l5SL3R\ Z Pp|yFdm-luP  d & DrCߑ3ҲhB%eiLٗؿ*AؘMV mNY"3k\  h ofkh^[moG f K  }tGrgn Lh W 9/*#9(9J">b$?W$;!"KT+gC#Cc}_jA D(M oyE  .  GNQ.Pu2C3F04} j , AmOv ! "w o;+l*(# %#bB '-y0B  V N/1HoAߑY0԰GQJSVq<8)A^!D =  I J g t ` .  2 } |[?hjr9F?[K\je.xp3M^ZH `;&86' '-S%j,O \)%Vh_13\ $ ')YF]sf5)@m'=<-%" "w"< #!6C t^ 11؅չپ'-ݺ_$D~$P2y?/Bg& ] uL 4H9_*z]JB7IѽDԺn?كh! A p{!<$D!Q/0/+F-+)'[^:e ; g 9 4jBJ N e@0u^ޒL58 A3w,{C")&@#lX %#\V)E{.q$|Kf$c@qJwLߑ2xjEgiKO`uGMy X W|/g7H%)$SLQ9#yF7f^ VLYwb>,! Dy\ q1|]n !! &Kg(])+(- P-&,+ZD+m+V)!$#l=@)3{ c K2]Qj2y  i 7iT k""" # 0#v  7) )r3kKBLTѠ2M<ȠǍ5ȴ Wʊ 74%T{ "<"+$u% H)&i')H'Si, )fR+0a }) չ{eЄՒBQ%V')=w,B/C,=<%%J,G *C")!7%4V+<#% :|-'v0Ur 5݉ w6 I91\ k6Z hy@8+zZ2 +pKz6ǿgLaWڌ̯ڪηףώPwO)ܱv%Et$5soO'-o N* ܞ ([gFvU[ v t!\[ ev^0o"+20A .8 =?J| >M#L%G1.P0MH/BG+>1>0-8,4F'2"!<G jmvAPbv`o]bږݦd"uv'>.ZKcK LW*TV J4Wz "4qہD93԰zlЗlՒӱ Rd 7x g(W Z H$aMB/OE gY 9 YfQ )E~1+j--W*:8m4.M /. ,by) &$9 ] I ~  .p_ 5D[Gi_cd pbޥtL {X5~G_Ms<*V^g:!Z# q% Q 5 k3 8T iWK] BF͑)ȠWLd(J7!!^5X7/ 6k*0:c8i 5v1s)RF&g$u$6veZy$6ԝڽ ج֮Uܻsic /j8{ As  _@EmHV{Sik9.hH@ # @? G g"cw  "m!#V%e%&_ %"$:"$Ja:޹% :4U)QHe`r : M"w!)6&i%V"mW2  ]'Df( ` g~(4 : 9 } C *q .n|"W?Bv]f5)2 \ K qH)Ma# y $(H+{QRI2OÒÜ#&yȽQ˦TӀRdJ5}, }AA G$:%C%9#" BdH+%  XQd Y (.o^a`] aO"0tf?ޯܻڽ ݦ߮آ۟ܔvd9Y!  67 "B  { X Lf|`}Ax?پZ\ܔ(7݉#9?  C W  3< 6m[!%5*<-BsSVj%&  L@~^_3J f *l@Bt] rX Dc"#C1B;55gmqn)[0eo}:FPk-4sX ,F*-.9&42 /q($0 \ 8 s }/(h  H i 6 )UCrA@S'(;bpO(3SBRMZ a bels X$o H#@L}~$`)0NZ\4"KXZDiRe>Yn|u2&z}KwWO} gJ  "   * q @g g| uf WL l:Z  kM)  7L q OF~gU  _R)N1 \!Rhv} 0m r : :TPy%M  } 0 s mi=c3R25PyE.ޒ4J* 1+dB2 #d q* T\ UT  # ) T;YvV)Vf^""}1VfvR8Hg ;F<cOsZxGkggfN&K87X a  ' ? #|F |E /Q W Z(YD g (  & 6 y P '   $ ~g }pd ' t@ _   M ` B |    5LH   = ~ | pCkMRQo!-BbDS]\SJd]Futx>DQYcSR+oy!'{v/e"Vp~'?(nC?k" fkj NO  L @Q?RA5H  @  A; .   i  tP 9 _  j  Si "R1 ii=_ W }KQHx\ n:#Nj{ZMsFI.7gޒ&j*,ncNCsctA:LMu84 8&S*rD8]H C    q<Eu R!4:$')o"2+%.&/8'J0+ /+1,-,E--)\,O'*!(]%t"ZD ] y f ,gs4L> 7C X WjL~7_u4 7][vgv40Os a   Ui K  S  m pF Sl W } h s<@v\P E"!BCj,_ y+ kY8m_tX*{~="R_MX'' :f")XL!{<5 4.wSf:m3 M< hP u3yb?"?   A [i1aB'I\m<XHv0  ux{d Ml+VE2lLZ2\S"T, (XN*8:-rGRDsYEXCVye3F-@] EO 0  \  R 9   E j N ~ /  . D (  7 f t , s s t j  g  o w So S!R A y ro uvqw58qK#/^%b\4g'3454^#S%WM~R4 E93|lG:3y-: #FSss~ Q /|R]H( 0 8 S y   +(  f  Pei 7 7  v v!E{Y66Ae^k#C~8}%i9N~&:dW[>Rxd@XS'AKm 0   ]M r J q? g I A $ O ~;Y> ymG~*uDFpQ q{{ /{ C5 Up 8 W &H u]G#}JSZwe@Hm"dJ"T-#DAbK7*f@qKf$s'V~7gF?c :H &  s Y)`R! s}j#%s('`,'9J\F;( :  ^       S  ' + 9^ s u~( ]X : D%2 '  d a P  M   :*gQeJsWnjfr A!|G;~.r~:X`t`}9h|-o#)/*D*s r  HQ cFCm a 4     S q}x   ^ 5kw:3D\lHq?//T$8;p # :reqdL~o,,CT_~~j.(7] *WM]"S-AU_?N98' 431; u  ^ P ~ ~ M  uvehMR9:E ^ - 0Mep8J|fc1Xxp6 e\7~u?Oxt]uxd8M^?#4hC^@KK^% ' W uj X92& %Tx!Pt^FXTWA ,   hfXO@ u * D  &l  ) yee,.AiKb:Ew    t X!7hBHg$`:\ZyH  % 0Bf >u1YYZ+2kl1F `^t{{*GcejxJ/]/,T-8~Bi-tRir`Sc(pN/vE"2* / j    KJ  .  B N  ~ C & k lfoACYeQ:'p??<cXw8ef>P:| :Nf>qH%SXkDkk4\?i|7A?Sj#D&-x_ & : Q<am0EHldau   ~  tl '  7D v K?%NDu:KX-e/ S m R  /J74D-Q,V1O[VODtsM,?`[\n.3`;Wq_JJ q}ySd D / $ i   ,_ " ] 6 , I ^r h | A| r  Q w !ec(  K X   ?GH gR  jfEe q  b P / &4:Y_m{i1n#gP=I"gވ5ވZ߸S,o.#!*%+5\x]h3<F4GM p><ktMH#]w 7 g yZvlj/UL D5  EyQ,pZy* e OF |N_WeqGf#`Ch6e{X`uWu3g-^x|73*|So[o\Gy'^hA j4&9g+}Qq]-!\\ff5!7-e<<FtEN''oH6SeL,T|M|VF:R.3DTq 4  0 k> f2{Odi_@js/l` |f}}O*V(O]*"*o*uw 9/&8*eF3l. ZpHb:e[r&@ N[ ]  B l W  h T yGe  I   i   X0k!3p Ib B9 ?}QudGR{LC~t8r_8fp4Fk{~S4yQR)Ff} "ke$J ?vWbg6c - 0Hm(]k\+ > fR^h~ZY  0t? A jO; OX2 cc ssv.3sj.: 2L2`GPo[Q6~8Y2CV^hJ\F@:U 3'u9.b| Vj&/!d~7%h5 Z   C p + o @<jc]Ttp?T(0+BY h P R W+>8L7/N>G-Jx[ZG\Lyi[ T  QwR^ K`c #}ܻޒd 0ڽӊhu;B,}{d. kL GX {0aco? ;  s BF A p3hVF:sfW!9 Wh4[Hyk   N >h`G ] K) r '>,S]l`<qZ; /? ~n *e]rt>co ") /Xy Ry H9[F 7wS(HXAl'MdC]9\u.F~&< b A , - 6c : S:.4 >Hqy ?PQ |\Rp ]Mi 5 y5+2l+m$'e]{*&$e g4  i a<_-rr*DF*}  M sU  & q$ i }* ~*wInd%WDKLڠ˰جe&C9@ Dq 8"#1F  B !.,.ވ  ͚4hҕw0Api\ K '( ~ -d ,c &B#A;E  .E  IY -T : ,d R_9sD ~" 8 KN !w:uSqFbD61 !O49m,-6+2%`W)f3&_ r"d/}y2 t ޯ6K']q(t1x^wsd'R7C,Dn}2Gq+3DKg&[7> J>Nwu   L"m {  _ _+ I} c   &p#19q޹ݦi(.iFm _M.&* *&h+27,v)$:I kvC9mq͇߮؎nѮćΦM-,E 'ȠĸOҲ]ZZ3g%C6$&/&K."w&G$#Y",y~t*4 ,} S ڠ d i K s) H X  +! 3 R X N@6&.*Q- ^-W4! 7 879V:-98`4)l3.9h& {_ j|@&{uqIKڽ˰O L՛Uo7 #c 9 i g e ]lDy g  Σ"i έ$}XPV2Q]SC }< F t kJd"<&Lvi~R Mn M) $1_H/-I[Sti!"mF Hh$u / W 3yj Mt  ^,rv55Hc˝*Ƞ̜Q{ؘL6ACQ ]# '* b   ~Sp.%DwQ( U<]"*GGEܞף|]WGDN׆*v DTB})($&(q#6&%V<$@%EBFGF GCz< 2> 1f( }x T f(W$n6.T@3 1C4 w;? w@ J@l W0s%}ߚK#(ٵ!5nވbܧ~owcL3ERGv/B9  k7޹H("`yC @A$a"& Hz \7 i+AA?t) ~]  >C'x mWrp(F/  \rw r<X F5_Z%P#&yj fx #<470 H:S1z^"ml i)3ekҾp鏮&тپS8 7L} ##;$S& jmNw#  b( *;RR?nͮ~, kvÒaZpGT7h 6R \ n%xl6Y t -  jX$A8kQ .?P3(rtD,Daoffx J'!4,L-&$(g=w"2:x6 +>1g*' $0D S 1A)EG+ZBGT6FuFB " K>26[=sE[ :! mЗ I եB9۲ujer: j ; 42"dSQm!V :   KFj BWFu9@sXp}[" F u alJ~+f$"f T1`PX(3 0  { KvU A 3/%.ڌ߸[p>&=n7s6s( 4t!Q$'&,Ol--)(I6&#  S{ 'K(+Wibپe+{I؎x̜֤5԰a}D(tSt  I`! !Q -/4w,E4P%M/K)4 '{3Q$1!.w$0 ^h yA - K  #c K&*D)_!ޯ A8k-k&Q#uS 9aO '@4[) $|6%>f \2dk+~ x M9'@D Xb{O08_ ' BZ i 7p  /%KE? j, ^l\ 7c8mrK ` 9'-/Ƣ5C'Pӻ-V C.r,B+$u'w&}!!'%;".:i[^Ld[-_-XF{D/H 3[t--;#&* n/,$O(#*G0)d//q,$)+# AKZޒFz4NrkTrJ +,,i)',+.)%!GZ h3qt7XPߤۋ٫=MeV>ҋ6: L R  /jw$r- yh76L*C'8[@ ~ I,QX0![ 7 5Xy6h*rP R A |kh|iDlf' k, iw y1 C*4q _1y!e! $N!x! y ^;N[- |tsq;# pP_ \  Bw ? c9! u[=F-+ٗEzŸSؽ^)H԰v|Ni$b<O! q~ `X k 0!w6 U /* a  ? RQ }vBWk6ףΣѳ}=lR_ aoo g f , h   ) B  \Qy\w _m yx -2)Xi ߇\?v׆ڂoK}֚-1P  ##C P6 %b=# {I / ,7[3 S lX*Zg\#@v D t+ ## .,9$0 #Y?%   `}:JUٵPHߤPo h h I %_c"c%# ($D?"Z `Ra @2 C ~Z݉չeVJ9"Vd֤sӻٗosDdXp? N D KX"##1"m!S794-F D9qr^ \֑]'ԉv1*[5F ^ y]M QOU?:< - 5 # $%%j9&$m%[&$a!n!_Srt rJz!r07 ѳmttpgNKJ~ &e '('#0&#4U T q 'd7DL>S*j,ؿjSLSU^E''J$ &+)'^"< o  e   u ]&/ ~ -sjA+7 B3l  a"o&}R(Q)f/j.jT)R"#(/9 A6>3K)VpuQ_i%~# o!7)]K-#!! i w+YSSޛd}^'ЄѪSa׏ ՛BW|Z( ! Hx:M-gJ&%M $ @! !RAMj P k[@ U 6 NxN3TF3[y (@/3 T2 L jL 'F9-MREs;/4< +P!*/E!p3<^ޥ ԰Oʻ,>i{-$ѳǡ Ά&ۋfyVcq^ Z ` |YO4? ^r]uJ%KneW ?3c ) ; u0H~  v" qrN" ! w" ! 8 +8tpL] DrfRk 7  k8).4-mw4 h TGesvQZn gP ^5 rwb`Nefi{/w 9ewf_ DW  " C qo  ؅+^@ :@R2L };  +$n~%%+)!x0&$3*;\*<=+:+@0>;/.8.)0.%(Ir >D{ 7j>W~%Oе!<ڳYErk<69^{ B(H 1 a U -[K@ 55Qߚ جV^϶K6ƶGo6b3[",2MpܞFm7"@ 7uJ: $wF3@!!n !*'^,&w!  "w% &M% ,$Wg"! (/%bfd]; 8w  -2g Te }}J o 8 gQ##vh,* >$,l< O "(_BBZGٵ8 C?%& C :%Q 8 C 3,܀י|Ԧh4qDF*23!  JB **--u,.*-0#2.C1+2-&$)H'hu"V*\^h|s(Zޯ?Z34| T -tfo$a]&"<'h !(&$&&.!%$u6$$ I 0`! N){۩sYĤ7ٵ5}yB˦Į̈~آr͚dՈ ݦ isa $] X }hXa$T#Oؘ&۟&-Nڂ,M'7!%@P'?Z^85fu)' Sە V r K\ A z 9ky)'M~ + -F,'{V5#4'3G+/,+:z)j$=hd p  FPVbjvV * @7VGmCrQQi\(<" R$Nf } #~a#-6%9Q9-~2 GEC 79 1K(U ~9)[n^njutޯKޛDdV|k@84ySYp%( '{e%L#b'!q* {: 5 c"ޯ]vȃVɋzآqѽw&ږՒ@j2uD!P+5 "fFc s.-! &U%>> 6 &$8 /B$D T)fr; jMj!*#Y6}4?/B#l0)5#;,:a C Ji5ܧw  W 7Susw jk(S&_!=ݝy<+N8 s! :}0ws[flfq# K׏C߸OnB0 M1 /6%!6a$:/_$0(%%M'T+1v!4l#b'o0 !y!x 5w" D  aU > Cb@B 7%X&ܻNŐ%ԓA3{gt  u MT9R{x} F}f RC( t5_{h*C8:ߚ¦jȴ'BϢip @ݦg Q%#k  83| -$uY+2-Nu,G*G0{-&jw ;P8r+ӻ Q֑?1p 7#1t!Q 564n-k 4<u/i g)5#0;FKAyfXf3n7$Do1 _!wzd $:cUo׭Ѡ{0} UoR }! }! 6)dShM? Wg^3~& D 'hhg T ]   kX  WX^ 0 s}{ )(w4 w"%$9(;%+^=H4'W&6-P%[d v۩# q/OA i + S8A !(dq.`[X*c* {km3 JGVS)\Ыӊ9vȪeέ6O8s t /iJ }  #t$D) 'J%t!d^ZQ'rxTcnDضDT{rcmӧB@9'ݦO>l| e L0p#1 @B*3Bj~n?>*`N(X; ! g~& FK WI,4"^:~ f  ' e  \_^`&i<%G%C!*] \Jrj kS` B{ f p  8p6<Ll u><{?N*=pa L S-R>O/IQGFUJK&b7 '" PC*c \ 7 gn7A $hE܀Rcج[L׷$+  }? 9%",&-(>+<@t,?&,;8+2@/+;f)4'+ o" UpZ0 <-I*H0bپܧA>|<B8P3 WGRf E7 o !NXUy(% Yu)R1o*ޥ`R)̯?UҟW7ЄsFnQ8tVg|y Q WUt"c'!'&$* ,$5O y3 /KD'{ ^2He+.#PPns'vjw  iV-/K0/.)>&/3..'(IH| # ,;,tML@֮#((cLX*py.\$&$L#+" zSTޯ,IؘҁZcY=xף>޹Z~-H_\E-  +$"%M @@L/>+7#+:j50"Vhc -bf DR (k Au}tDFcv]w_ S: k      g I Q :b jm< .YqmcyzݰiS 5?VwedÈHjі+<\ i\) Ne()NvBsjvG `apWm { X 4C> -?h%k5 `  ' \($'Y!*SVSvd\ r %Zexv ~) h, #B:R& Y3AMp S[ $ XV7`Bj*Mz۟K߇7F*Ay&8d5j!xo![q oG^X`&$6=e . _xN 7 eZJ W"v[_S!_E U  V#"ZECJ,((I!W  AF5 "ZhnC[0{+m VH CO A _hO qTxϿyҁ<ڠՒs&J #gZP $mNw#Y+#b!%9%"-3ku2Z  B[ = S-= [rIjڪN:.K\uՈە԰ߚܱ&7^7'1/ I4$6@( ~y :<([  hXj|@G&gR ~/ iq sUGi!4 y\  /m R' 5$8Ye-o|*B Ah!#!x-hya8  #ZSrs_4MdwUIMrz)u4  mxf&$"r] M K*i jJ$r_,TLי8]&?r8t;u7 W +*!G"mp!,"! 8 > S Dd" i f %2 `RTLLJ>#=3'L'B*_KbcPXhyyS  ) VcչjYse"١sپ{NuY $ " [ZC~Ye w< qMM<~RM[  | xIm/#&U 8()y T+F,v-W+ZE):($m#lq_f x h!r9JLOT}[9ZER ZeH A N/;&J2v[?AVjr`g(&-~J_)NX}|hK,_fc@  @"1+.@Mu*%H a  L {   =uotgN;!# g$u,lO,+")- ,(!) -&K=# $Nz!GaF +<*\dAވ#Є]]ܻ/gΐy`nږ}h!L"BNi\QjBG2h 213^tkh_:yrH$_+,< _ M udZF TZaj/K} "=# #1v"P#v#Y%1# !4II"j)[     `Gi3,X ;(D!}t9wܻXM.|YI?N߮!ޥكV԰Ҳm'*<֑:*kVE!~ 8Ge [6J,C J t C w } |A[uB} % \!4S!*Q'/U)1z(1&K<*+=+<* ?(q<';y%9J%%5 0-,+$&N] g}'  &O\QiW1 \VQ]: (@^#yj|{QVE~\5AݺA4ؘ݉չҩs"eώa*ԓ2Es.nxPdZ| @o   ZgZ#  ' iZ i[ 9 U  . j  R T N;ENT y # $['7 & % " $!|FTd awu [  vT-`Vx "&fEVhpwQ'kR.RrLyim4-)  7 < q   k0 0;f u= 8 U #    AF W: X ^tFwdZCwvQM  w;$\(;HK h~ k4[k|V 5xu@qp2}/cq[Il^|q .T@gSqt.@*bd y SPC8A')/qS Dx O> T   ! x   > w  { 7  + ,Z q  q   S U 0 R G esXgN_PK  ' H e  , <bZY*GHf7+j3QGd  vwD(8G $i[G>RhN 8JZ on-?j~9B   \3  & C ) Xwf@qF 9 ^: $ u)w^ D <]mCu/{37  U -s f" q WR Y q-pq{Lup[/h)bf9//@*">^{eP(#5^   ]P=e p^kD RY8G <  !L},19 .*{ ] }] q .   } 2v(5!6%oW f6ciLVb?O^ti6g w    .  @  TV/DQ@H# h b79-R) D i: yV~hweg0,8<*zu'u  WpGHoqh%Nr48}#.M~^+X;(  ?nH\FFRx o2(< )c-Et1);!eO2\BephY)ur}, :V9T(@o2+  Y _ s &  - 6?54   r   ~ k 9 W D L Mw+ A<+i&CbdBxh (lN@-[ J6-"#_|K&-k1X(P*XFV/BLsA   "65|4\p F  af r$*CQ,A#7q7,?V.LXDLV6i,_GB }WtA-N."k jo } ]HE u**c     . B ~w w<>pbyW7rjrK7?S75-@EF(: 7  NJ 4 w2Y <4@K&XPo48cFo RNr`py,*Zk wxH>(X(N {<! xBg\rQ & L .?   N  3R9 ][  ^K s 0R   y   O M   Y '"[!+J^}0vl+l Z22bl0k(Oik~#r+\`?{R^+T#W| LgQ s   kV  C Wx < j ' C   ` &  ^   +?xQ[ # .  c r - Py Q^`w%WjP`).J ST9VjOegANG3xaFbjMVTS|o*vL| h j:V]"/:E $ @ ZMML 6* W  ;k<eGfI\ {T B  lR  u _kQsA>#?7\,+S! e\Z3!JK#9V)LW2)&rr6SwRt"J?4Nhj\LE 6 H I   O aG k i  OYCusdglK)R} . I  k  r |    Z   SG o 3   :[+  q# r :[!Xjl;cY2t(/YNDDl Z&GuSz\|-U-\ anm~{|   _ )    L k 7V   L  8V  (    K U *)lwX  S,    E  :w+>"iv\ As5h݉i12_,86r5? 't^W}u^ 6H2vtcRC#b. A {>?   8 A# o 7! I!\!H ? y Ry*LFj1Ot3]ZPb(Y]A3+ K 2x ] A T   : m^pD4sb:oۼ)|%b,Oٗ O۟Y0OV1k"8,8|>Q[0qk:7"Li;Y.M8D7wyk Xh &   ~ W wKR*P *  3 :$/HLPWOYtNQdtM 6W 8Y q?pAl^_N  7* R k!Rr>r>S>[& MClM`SWC 0V:0H73v=pvv$*+[9c 9 ? J--^gu~I]/,K As S?Y ~ b QswoqUQ nn B(w.:7GRbGc & 2fe11_;mMoCyr q + $ X / q tT ^c [u+D_hYL!;+=YU  NJ;Q1yoXr3  $N0&{&(o+<)\66:u2.C+7h5Ob1,-a*('q^_TnN[k>r #S"  .   @|pqXu| 9& N_ _XdZ ܊GWi _UԝN Ո    @j fx[oߑ =0&+rC$l` . S C ] GE(  Q!)>0#46&4mDCC?>DB7=7t3.|*'  ߇ & w6[olC <Zk&3+o1[1 |KR;<ڌ؅A$L%$0З"<&s%̒"m*˺w{oQߑv_U@ ~9ERv }?AL@!&B(*+w , `-u +'(( 'h(+!#1'{"#%M0*-0{15;9>?;\6C@/݉8$ވ*[1q+wZ#co `RH@% pp$Hda+G h #! d;S\QFjh)D * ({de U#(ָ!=s#H!˰ !̜L;CϢԓ v4(wUFi:y F &vg T5: 6vwp_| ^&euZAY2;Z3?iB  Sp  f 5 M} 8dE>^J} y\ 2! V~rݺPf m~+5-I/\BiE~>%WZ,<:y ? F3DgK s 6 X g+e}{|v&5O f! |! U[  &t@d3G #C \  0 TuL%)&i8)h+2s(,v))(#lON3K}-< Lv97d>' XA]PweH[ K ~ MuC)NjLX1 v(;&`j$ }X8 .CC`kuSl#3<>okfr?! O?- -e    7 | _   t( ^deQB*# +"F -!  )\$`Vhyd]"SqOC6 Gf{5Ts~_6q_p ϿώZdIƢxkM_η؎4HBR$O>4 7 !5^ktyP T ~ c #^$!qp#!# "(zo)8'-#Y&%#vW"h9_ *pnx  gL  L#:C9 S\0[ޯ3HIض}ܧ}ܱM ܔ|yXd.KGOW C ^ s "Y    0Fr+ &  { &   iވ Z UM s  A eA } _y_Bo~Z  pyEt-F @ 0QjH)gD"=c 6 U( hD!gaw* }P~H?5sgy-Brp% P sY Wߤ,* tpE4 f  g g bsPEk   j sb|'kJV(  Gb ,(+c,440N-_.,($!A3?  } | 6)|Y2  4)D JNw>kG1a3P ""@'-&# ofJN# i)7\w*^ ivvc9X'\D=kh! Rdsk`m R u -E UC5 j[f[S /, Br>*D"^&-u " \R4Q!#;Z#""F#% :K:)6F0ՈMҩOLYʞ Ӕyu {ܻ S K#< 87 B rtij[ ' UO7u>ߑ9ܧTC]jV+eFq,O0r'0^./979-4d-:p2.B(x!n\Zp Ip^y T A& i_ 8Z|,4[  : - L i /*+ 2 dB=vj]O"˺#H$0f$O)5'6$ɲе#1Ѡ݉l V1oj k q~ Sy]~YR9-#uN#m dNxTCވY*Q41p Rܧ>~i" &4#(%<&+F +2* (S)*[($ yxeu c# 6 Y%R ?Wt  8bU*bg:]WB3hA {3l  B7`&ܔ#'Ts#O8'^Z+(@AS\Wx+F>4G^O+ A ] yWCi)G r,ߚ  y$6C!0&J-/2f2 <94+1S*^!9 ~>BKSB6Є a gH1=k :~ %N* j(ؿڂ6ec߮fdS B\^5UbL?/'o k p[^ _ y#O()yd5E5l6W4c:@7/541. * _( /# L   .   d`?' e59lTKNV$FZ|}s^  d* x7]AtQ }5$F( `v?i T&rQ. 's ""<!'^&# \Vjo+ ivCA!ys  A!8#vu@-d.(,d(F'u((+R~0t5SfT3^B0`7P r\ M~p0%[g0ޛڂ O4`ЄЗ5X̜LTߑ[>ITL2 6 3\qf! 5  uXj+TX'2w p,$&?*e,@.056 2O53<0'! %$ "F$)%Cf# `"  XYdjm| EږԺ|,Te X CHxn!SSGdڂ ]|5u8sZ>ҕQ$e$5iuٗM q -"<<5  n;|=`  f + ^ .O:o9 # 6/ k  {K  K g LDqPq= !n&%`$a"$$" , t 8 K ZKu6ևhM"ݝt:ݦC"{ P)m wJtZ,Kj[(zףh۩My:ہj߮$ߚ'?($h--9+'hs% "!Qr ClWrRkT~ @tO^{ _  t$Z#,zc  8;:_! r%(*d1,3x͑4 )1W54y1,9)!$Dw({' NdTn*[**@~5}[f)j1C~R!?iQ&|qec|{۲NNՒ^Q  ݰG/b &.M")&+ 1 h/ ]11(0`8X4.0.)\T"c`,TOB8g^\&}w+T+K0~-i/"Pp!*v M&^&8$q!"s\U  Ap5Ѫ 2 -CxEz۟M)ڠWfP9RgD s$ t6PS &xm '>޹0ݦ ~ 9 L & FPI_j}"&((@$x/,1@%C8(l#b^ Og~> v^m4n9ZL&(z ) (g-/U .-7+,)*)f['$u4"w!.a<n bv<J 5/$ +$(+ZN,D0#1S0{*3.(@)$k&0 hX,? PNw?8#%$=߿ ] scCe0')'E"j-,1)$04 ,T0V TDR.}կ>Ӟե \}0՛'ե֚ I)ܞ<ne$ W_/oKh e#.?"( A K S5#PmV#%(*)5J(..-&+-: ')"P! O,9 #r }* _] MM hU Dڠڌ ?7~ԝՒLԓz;ҋҁ  f%Ѡ'r(g&( )(S(6չ'$!")ևkj 8|E&hE84ҼYӱ̯֚=qRBپiZ24K>3[ XNP7%+90K4)=dBqE[EFPMRO M*JHpFA;!y50-u! ~ G\ Xw  0Xt,],[s L\(c3 $}[e y"" K W֚o˺ “ m61fV Ԭ ַQwņG!B m} 9h?] '/ j*X oqPO`#iTC{#|+ r uG)m t .iC6E',1S-2>K9:;:SGVQ:RcwGQB 8P5rby'^*Qr(]%r("#&#!"ws#1 z + "19 >6"M#S֮rHؿ Xv2 ]<  $ ]  | s;|G:s`4EpP79)I+75#  QQB''S$bo?Rjp܊ x) Ѝ ֮pKj9,KkjDG$&1&K&% )'h %$D!j}s_8 ?  GA|I^ gCP  ;g*l @ y" I%B#wLK @*H sH /k #$#!#"FCqdhC&Z?ya{bg &3i*{~$0')*0J054K38^72*,&JD @y ' ; '߸1 NaxmCMf'%[j$.B#;yT !"Z" [" @!Qt 0!n,YaP] ׆ ,Y5hVsڂp,߇@H#6   K lx!*\!4# &$'T /'A)!(h*n\)5'h&x&$b"ͮ6 Üʊs>N4! d 5 / X W  h jv hi [  ' Ve"u]6`}$Bk3 ڌ ږO,^![#E-uw.tj-* .,(@#lz y_#Ym   @. P ? EG>  I M uQ>6!*3-!} k'ڽ#|$&}Ւ*1/.+/KU.ǫ-u/$+/K?/,)(qu&.#YT! _(F _ZM { !9 YNkOM6}([jp L# ~q#!}F zP=;)x+7Jj!,u#Ƞ(gk+m+e)ج$0~.)(&}# 7 ! ] ] S: #  Q M|=iBaX &Tm١Rޒۼ`S$ ~ 1SB #v%M"P/s.C,',O))fQ(q'PQ' tcwx4<5ZM Z(Y/W]O!NT  ^ ` 9g oq GY hڂR١[ڳ##1d$0g׭ԉڂڠ ݉ H\pZ  &ض)З8 " dUN &7/U,BW?B ?u.U| ! &Uv(,)(" 2*0z.C070A,1l&M#Y .= 6Hj%~(6-&+->>W;3D@9-1v.+L Y  $`Y [k/c}kكX ,L &KԺ4> D?w#+,P.Vb*?2 .C-Y+P'h#; B4_1d_tH W] O0C ? h!#Yx# (;*))q'TS%#r F MdOf k9Huݝܱ 6 H b% yE:@$u,#(1*1"+-a6!-'J .NP{ڽcg1K Ƚp XnYҟ)<FBKMWk-E>{XR D[#r !" * (e*4(S"(%$$DN.q i  #h%K&%,.M2 L7 16 12o`1I/.~(#)R%&$#" )>%97 N )|  G&<Q|88{&q#;'e&"w~7m7Ժ=Σ,#qٿ¦ hD*kbUF Rry+ Sc `h.TJMЫ9?|ƅP3͑тKiHk t  Maw e6:*%M -%e1..3[ B6EEHkIH&N,OY!N"wM!&H$G1" F< E$:r5.( R SgrP7ՒѪg)7ǡέ˦T ԦآV 1^ߚ cxBoj0^wGK `$tQMƏ62_˓Kg(Y(oJC+x G{rj&&X#g%$ "%u[$cz^%j[&i *4 |. T/; ;4!872!AU=873n,&/ { r, 7_"PJ#&)oP)5&.''$G!5Y` 6 *L*x 2b&!W+ӻؘh} jh @"[]?+H߮СҼ;LYoP[#D'7)fX.16':< >AsG FY=HEEH0D=%460# + r$ <[# u  F#   B   tQ1 "!Q%%ݦ#۟`@wG $Fs"Z}M+2Ϙ2ڳ]_3B8|Z[K`7_GC)V76xRDr 5")+#Y# *q+/K+1683d599k;\A< 9=R=ZE o-Ki0|J g ~ Vq! hCb(h[4LޥF߮ u TDb*< k @ ^EL  3- }(\Z0| fݦ%$kb"cӊ(N(q&$ԝ&$չ!ڠ7^diU- \t$0D%j=# -D U- *l&'X$: 5L0^S{pӧ&-. ٫ 3 ݉lUJXuqtT6fG S}Wxm$*ݺ`۲۲C!I܀$ t'Jވ$,E+Z-*x+w:*[#*4<*$&5&'#o( a!B( ghht!X g  dy r  \~ "#$&B)!}'V%@)f*x*=_&%%9w$0!:d \ T )F(y F   I  #  9`*l4ICY5o 5~d;V;r]})_c^{3W|d824g/ -  A:8!  0pI Oe r ' } 2 r h | 4 2 A ' T "  @ A  ` u lA 6#WwkesMA`!"    PPY }) TrO4 xeH{]jXL   ; r 4K`3y?  'L) ?[yX~\64f `gSXZii, N ]F     = I6 s + voG| ^ q3!|S\@u=d2\- fd "x y P M Wd hH N / X _5 g@8u([h6S3! ynE"k'~S & Af Uq A\  / xdF _#;Wd`wsD5}y?AH) 9 uuR+r/_   w Z?  V 7oEq+DyVip q2 $L1K # % qS'j (-vLisgo oD k7\! & _ A{  3 K j  Qc @ k< V/1x{YS3s\Aw v} ?-w8NK @::= Yh-].HS88 N s # ?H `5n <XP&\'%v{eQ2;'wTB2FPeG>K>ip*8 kv  o>MB\:dL))z/  g5x-F)hF^A X 9 I `B&8FG5? ] KRhf9tAf X`YQcA5F $}   7\]Z +  sr tt :/+*X Ah6oY :  ' F Y B x K  s X F .5  o]L(9R/e&XtTGT4[ [ C , U X C Y4+(@Y(P<y{\SJ?D_!wD4i/{6| L _ <VI.!xhgc,SR \ > ^ _  UX B h sp M ~7 M\  8'3~- p1i"4!XT9XPG " ( - _N&ujh \Qll   , /] X, p Z b q4[cf  Q  ] L B   0CZ<_/J{g",AIJ\SpS)3+@IkX.F` &Q so :  IW ] ~p  vl\-dC+/22GjPO,?]F X B fWDPR S u B   Q5 F4[G g " a C x i  w XEo_P &-;xfF  3^qBLr]Kv*FgqAAMlGG4HyGO{+;9Q:Fp3wd[ZMLV.7~~/!B+#V5e2>L[w3!3\)>NBJv jb ~  r3 Z u1)* d Yc $  ~=  8 y\ ^O   .]{2 Vi .#7`q&rsr6:]`>\gh?_*>gdG{T\GgQQ4G>>yWsPJ \!yN+{J/SVr},<yoAob / } {5/);X'&$_}UiNQ R !L0N4<8F8VVVic^`,&Cp uJ/.X0HhAg%J< ;`G{d i}HSxd ER1:N g N<RbL34+^N)O#0:@~[_c> W ^QX8M*!E[G) g< ^  N@ d{f 2yDKgVVK8muw k 8P r ~p4`PO/^Bg]qI[ H h 8R a_!j0wF[LK(h8[9kJjf-}!8he, ,z! o /e P  Eh.70g7J* e6\JLkEx ] ~[2L\]L[c ev33(k<:Mb/e8Rl} -4  Y@_g ]p  '8 if &YGj9*\*f;e@  @] ]5RQ5D# kuqkm9oF - h . 8 _ ,  KQ ' V I SL o  ~ 7 $ ZOwH C  .   e aic/2\zoe}x6 8 Lgp)oyG  Z4e'MNQ{uB 9E Nsx_FYby CE0,3ZD e>-\Zg54wYo2 C\z c*Kd  D 'Xu  _ i{ $+Orm,F5Em*LMxG- , J :]#h]"yT+D ~  {4+*FPS,rM*rC<rhX MY#Q { rQ  )?.dGpS^L%kBcZ[co^Ag |6f3() :;!  h  @s@g Y U  S 6R w k kTc{"0VuS{uM]M?9B:)4A$bCZe\= S 7% 8cGlD4^i?x2wbeCG5s7e$!3xE[ 41?H*H>,Jh&KB+jD}h>v, Q M | G gHVqyp R N W } T  KH h ~ O*Z|jZ P*Q T  L YEuNGf]K|[^!K~W`b^KbTiZ _? l /zIq-(|e  'O@~^6\7|o  jv!v`   2T( |CroKG!)  ~Dy,Qhi>.8KT#"j,r]@V7T^ VXAhK62+5Hr2v_#JG*<'Tp<f K uh  a j j[  'wP@  J  9 8 i ) }3  _ 'dh{'Pb' m)r9mo:7+2&\>CMtX|GWm0 :_ | @o:S.fw<k c Sx .  C*wK:w!SxvKl1AO~_7 w: D wlMZjw p3l  &4   N 7 7{ -  0{ '.R# F @gZ{ <7Q)2[j D7 H!RHgd+ u|  L_ / / 8 bOu~5 ij`H :OCwTr{q6%.A,@4Py@ k0AW{y  Uh :.V k&3/hRQVr}XqAV+B^os _3o  =hr-Hh#1% &$u#v'% \#" ! "w,-)o!(%Tj*8 y 8 *:%epr: 9{s4 AghSDt8Ss3M4 VejxkG+;M2p)k ldQ-v;vx`F41)!N [AQ&nҕ;ԉۋG X\K0E@ۼFL٫ 7y} 3 .L!pP@{ o Xci^{)oc@bd #^ D ?"S XpY:hhR{[qo\d|PA2X"zm%|150+ p2/|-a*g  {% RL37( x @ A  :Vu3q2jH]KɩHnŷŷkɲіuL ܧ7,9p3 &c *kSP(l { 0 "Po#Y"F L]hI6su |;6 T e :YݦO*Bߑ$}hE{ ^6#'(6"972:&^1t+3%CwqJ1VKߤ{:n-F!H%\t ? gmTNBoJ IuO=5!!( R2#$oeJY7  Ce,r)I]T&i&&!w'& &$W{i JOW ?cMù**υ?׷ޛڳ׏^֮آ?5by55 Dy R y*+.+c6:74-&]0T.*x%.7<  C5Q De ^ sKFxmwl h4  >[(5 Lw ] B5 TS#\" %9 h& }*G 0 0h -,Y1.`r(]$u7!$߮|ݝ ҕ =1n ӀP)o۩;] ZK ; Z /j[,Q? j L '9@LB=?՛UI UѽN}AέKqgC0$:3G(7(@8$4m@2>X0<*6/;)7L#1p+'h!   Vwd~QSu!J? w D  R&!%"ZVuA4ǵ hFE BƏ5L~`32(F$b &'74#*~0.d(J-GZ~\4GGGS"K8Z6O\5oT*qh g4 a1eKe+ /[<$u! |"2~YO (  &.S Wj0KrM(&Xv 't<x ND7w^m q/9 9%) )s981u%5.t"Zi3 MAl A5}GzMN"EESw;9u(,%#"ds !Fe"?J.my5N) Uf F~e ~#RnMjH$&&ڠ%۩#i&}%"FK\p Fx2f%V #1 !n-j,F'A S=$u "}4 XPL2'ږ=h չ'-\@ӻ+ѽï~؎Dܻ8HB"Rb76[F84tufEH~ &< T8<Dub ,N [ +$O# j!\ a# Ml z \ r  | `  w!%9),E/406 M7f2~,Ys47/Bu( +_,PTr/H.@  )#) g gt+2A)j'h T% K K'v"ܞ T>֤2Aۼ۟-bg DOܻ'^j[!,wܱLKە_6HnJa ӻ}B ׏جm2dC,3K X%y! I#va"#1y% &&.#m""!AXF4IkY ` *$,)/-0/_06N2 563G5/i8_0{6- 3&/.+e"Z0 0fZCl/鲮$ ѱ:pºI?ŷX~,Ӏڳ߮+Q&e`H W?99_nW\nW65KCKju͚zҋ$#ޛ2n65E* B ^ L   y|_^~f DDs Q <M$|[+ &.*(6/U+<1-,548.18*60q8sD9#4-K(,'eږ Ƭ(TPBɩ{t݉F@ +Z h"eVRhd^fXWۋu 0 K.!8&%/ٗ0R/[.t+Q0',&7{S^`2 hAy(~P:g p O} ܀SW tKrl'-10h/B.t-) 5O2 3.t./&)R $"^G[ ]qJf SJk)e(\+~'?mT S "0 , q }: :O#p8&|HNC< Lt+*gM "s S>u1)Rp_`ߑQqپ55ǵˉ \̯ڠV__kkC_NHS !x y%!$uw&p1Z3 "0h ]- T31,E(#>$ N T } d]#KB7o|k  9 6 !  #cwVkb n7C  $qv tsL94HSSqbgb{47Y?kt?@df-.Zv 0+uIp[/j 'S-5EZe |T#%/%/$&(g$ |e j!Y>"(+{[ oCPGXxrE*XpG\RnOg'~ M}y ~ޒ:ߚehۼeJXMLl[CASE#x #J y '"'%(&U',+,Y++Z-'-k((]&8&U $WkZ Y! *!th#I9VH  9 0O%H7 @ T j QJ , Mf%:? U -Fp 'A + ; jCT.{NrF Ao iPgj&߇fKTtN@!o^ _^<|*e/25+W:99#k1/,+c/B)m<P~m TP  9 . 6 e oqYr!!}.=r  Z 4)+[]\QW~-V"Y {sA(H |yd 0Wu` 'd߮\7WޯrbH. `HX3MB#;)M,(#O;$>'?%7)RG1)RCI$<;R2( Jp#$ږBӞіЫļȖJsCk}y+!*'*q: > |= 8t!{3Q 7` @3 , =4:2\y(%t .+ t!q]݉~MG۟]u=Bh  B/;{%]%if3 ro`PTM5;9h#L ": ?Jt'yA<_]iFv k g Kҟ 1dضk T (jN J    ?sUq -w # %d!w#lQ#0B/-%2 E-$R "jCe ӧވEtwf1H/, *j"2-- *)'^ g^s i)FG!:5Oznևzؘ@fBu_[on`> "PqA$b&#)-+%V!4 +ig\+ uX+#^ -]i$2 74m1 *e<;o7/|&B >&$&&B()\{)'#f% MD{r CqWN~[C_Bވ4.@T۟d j z 7 Te u - hW WVbMW5Y0z`RTt0cGND8Xv2` Z4GLeu % A9*%t#%%%C|$ ) %j!xUqA! '! T&8"]c  }  +&  %1 tl7BGS A }[ DEy :@ 'r>G<\W9 5$I?ەQ?#֚Ͽ5dh>>;̯ V AΆ a j >tF N-\ a I bN[4}=l̈ g Tҕ>xLw߮ 3 `` iK@Z,P! 7. -. - 4 1 90 -W<-k(b)(L+߸ 7ZGP޹bָ܀h߸kIb۟ۋ % B  M$Y/R' ")f076340(9##6k,4'T$u d;d0Fܱ aږ  Tږޒx[ P H[1ڌ 6Ԧ 6I ͇4?0J{5'@`$>1!0<9 8N23n33 *+O&) fE+ ^W c }׭СNQ*{Ҳl yQjH@ "<+'? =m07>:z4/U* A#v "# a#5r~[5 et* v $#pzB^י""~9?Mɕ MĚ ɕPH/p ƘnˉCmjە) YZ D  $$0 y , $8{ Yj=B7s,qE!I**+..*e f2.?'#o#1i  Dh{T |^$hEA9$N'#k0D) w) oWqA}1Zf :( @8ԓK̜#͇%Ϙ"*(Ҳ*='rs&׭&U#ض!Z)hc . (!x5 RvR@F6m$Z" X ( Kt  X " /vc> V5PZkb 'aPgl8hP "* zT V ׭܀w~Y>s6![A \   mP  j$ g)E5X; 2F-M`#i_.B"c"AYu L ]O*[6:m/oP?1M4=  pScfs$]] `+M|,/}E8:&??,N1A(*+]DsQr%28Oo  o 2 |Qv5.5 L d L /!_Gt #Y @,u&1o463VPEC .U3gM"Z)"qq #E#1 !#""F  $ B  @! #OA0 ;?>Qؘy5%Ȍ;/Z=м9F{:_cB׏tVeO 5  &&9e0,**$k8!eBB v*E@ 7ەC%`[#B&.$0./ ,$Nw,#Wjm U! ^#Y#~#lv'h ,'.%Y%B(F)f+)"  !D(?xb-k1p0)Rw6N5O/$}$ yBgB O8O SDѳx ,[5iȃ˓V*؅ݰdޛޛiBi9F%[i)WC$\<5<ڳ ׭Ӏҋ`_ԉ+(++ږ*G^5l4203Q1/-u& $W !7 8j 33 ^Zn]U+OTs[ LFdw  'Pd3 *%~y( *= g& *4 `+c &_&_ tE+H4%@.|e _ᬺnI~rj-C˺xԓK UQ9e-@v 50sdru+ 9+F 'JM+ɕ.V7º; }< 8|A“>P: 2H2* [#b X ' {\ZUm߮fZH mH#h$:L<=7LDe@\:H/, '7 aLQnw9CM!PFeWqҕt˰ 'Ϭhdq ii{ج uވ C D %C   p5zF4Z\ވEVZ q}uUSd+cA+(V) k% D  Ot.QL]$ o]Td\`  B A) s w  u ]! &s(6(H.Y,)%4)R" x9 \- :91Q^HWOF*#O#"wJ(zl Rkxu 7eVSecFbXqdBGSָg j ܞ3 'r3H,X8O}߸~ָݰ%q iU k~`+MOk 5,QewMc-xe!K`I &(r)f$ //.+"#l"mS7  !o - r{ t\ Mdh#18"y}r(H}۟Zج!ږRr+6a9WJ]@iJXE*n ! A.^wOpߚF:J^B3Nx-%N L ")[ ] @ m "Z )5 :;BmFE Z aYV>O X REJUyA 9;y 4Z.` '(^  Dx ~F k + 5\ ue! A j'n6 7Ӕ3z* Ӕ<؅BvSnE؎)mؘ٫H=7; ! hbRv9'8# #g?0~<ޥyԦAewg+TK t" '*G'.>2@/4)>ADeAEA|G> H >CS9#Bq51C/8F">>=`;9-J4,?{#'(Q/ R|KvnҼ3T \¦+F{sϿɼ ѪAףۼ&s? / AVZu A x #Y 1Bs.{| L|US'zv_.7ۼU~0xHWI l Ə ɟ ͚Ւە 6  LP"m-D9O?kAib?uP#OI}!=Dg=4)y >#+#9n!4 V1&Z6  a7< k Q]puz"v F sBe{J0!e qވRRNd c '-#   g}m')yӻvfs?5ضɼwºvS(2[~h/!")>)H.-2/12y0J-/.%/.-/s#(S&80$a$ HkpNj  .[Q~KWhbtWT < X&W*)J'10-,E&&" L/ "Z i86t\B46"2L"wK" ?"%t$Wo!7BQ%GZE ': 7 'bέ0f#!I7Z];Yw>z// o hV g L f +Dm: ZS#ZH16u'-  9E IX  W 9#' YH/?f A{(}r| Mv#" a( +m,+<_?}OXGx  ia\7 O8yk a r$D%M;& u-, +G)5"P$!  \f ' M UP :" K  8 L  t D / SW|c/r1B +l;8xGQ7 ^x{ '_Z4.QWo5o+]+ Y W r, ~  )|j9@R5H&r77[l]x >  HH `5 T ``"mT$W."wN6 !n 7j6F uoooxuJG8pj Q  ( W  UG  |+l ~ yJ/  YQ45'PKho~ Hhow*< "י\zi#7#v"P##!*TUw [ ' ` 6 ^h @ T B ~t h % * PRJ=JE3 "p @ ,Z e $9Y 75q c 9S& oG > i@ C TC *j*Tpkq\Rm1_AM\ : Q8v1? }9ms!dSSQ)BE* Dem? ,!%"'#((\**|'*xh(Ij# yly],J h 1pwx>g3xGi:9JF:js"_A:.kuF3Zkq-'O-@) MY9;j_ >"#(r&$&%M!nzp~g#, I5 N"g9f tF'Wo-3 Z  0  C % # S f :yv j}; 7I g(y3DPX,=I{ZM9Yhq &;<;uB.V]g7MWVi%qo]O 7 e ) F.~/$B^+7N" E m  F '` : p s B6  &q9xD <<)u*s! zX[>} CWi'7MN[پ < > r IBZo=,0*GC%<D(4s4  N @1qf{w3^ u DW.SE ""V%'TH&$B""u!xtcO ?_6-:x=Z-;XAVi K6LHFi| S  *cO8b`9].fkj5)DA a(@   / ( )|9%p 5 G4k?#p- i , /Xa^.L|ET U\%  sm'[56 $ ' !F'?r{!RROCyLF/WB_.YY-$/E l h eH8 i 4Ocf 5d jdlOiՒ[͚ ʊ tg ~p Wq AE v~*B 7u{FmlcEl   . `  a 9 :     u >  { 43;4E2 o u T a z  X(U/  f |_8&r*]{A=P;N=ed=Pw7?_dt  0GjA*"!KihC2$bS^P{ `f QX u~  j,  ^ }  , I    t?Z  ` r  4 g  ;mgk`,X'ouOd  RI:cipsY8jFhL\BQn_SqS3^V3gp^2 X wl?Vj   W } TP : K 8 CH;^4m qO9 i AB ] [Q)+YU%`Z(e 7 _  A 0 .w  NY&G5#%0lFeoQNF5{t_R} KKq[ oYNM4gd)tK3RBs    (CF PffC ]}   ^!* !e "c " T y | H  S_ V ]  = @g  ; d 8 / c,3S:;H)?J!ip[px}"=BPXP98-lkj98khv6cXYhqR4&#S|J9  X>7o  F3'`W4R)m    I<BQD+ Yl )+S  .  :uH;3/5vEMKFWRb/uoyZg :l/ C Z7! <~{)'tBS sf4hb? Xc2_}T_tD6R@.p6{' }[  hHeQ A &c<J7 0 j 7 8 b c2W 9@ j  - ^Y!So5`W7J|/te u  ~Q& g  L FHtGbdZ2H.fEY"Fj gtB.:#6*x < >CdJLhEN11'Qk<.HApe ' 6 H;Ab4J$C3`!vd k8dWN Yw <],S#":dH]cW<Z/t a^ 0  _ 9  w s\ q.  '  i 8 K5GSkM\ w&u " T  ]F[OqA]ei r )q{N q 7N$ GW(l / & od> "G ';@}A{^f~}+W}}b+f 7`G//'*gq^h<p+'; 1 & rJ@3;wBwj }D!W\\ 2P|/y[AyC -.`7Xt''f fpDq)]uB!o t 7P qN B * B oZP@lCbhkk.}|C|[VKV,4 Q>4q8s>@0;}!@ |+p[cC%$j<[x@ qi 8 ' XsmWRo@D|k:-/XO k MN /E V& m_7!YP q ~ g{ pxSxrx"c } q @, S Bd W>~d4  7_ L}q, !my|h :P3 [ $ C MZx4_rWAFB-BN^GWSYI D&8A3Y  g 0|  9j+&)PW7,+W @^1w.b'EyKI%. ,f  N Nh & !hZy6"$$%&Uj$j!*`6})t Esg\:APTK-wn:1#G4erR4*T^AbbT B  7i>Pv`0^)oS MjpT   M  J{aljOM  `E B Y  x N )PT*y< LO !f"{Ebi\Q1ppBAh7tet7tKk_Q!^S8|)-d F~i q\ a  -(xggww3c )  ,F )2WfuG,] ?QC#5g : 5  SI Iho 6  E   _ s;(G<"##bx#@gdooH\G^^%cO QkP.EVO|q*44V{")s&bAhB7/LPMi.9"S;G" q   |< gY  | `d>qL^ *P :  -1s3= : @ `  X  y f h2F%.BEMphp xK,$|KgG"`'#\_"pykT|i <$Y'  [A7 I#O$N#(w. 7`B~  6  S \ >^P?.`V@FOcQ & s' "RY _N ,g UBAmt/V6bRzL^pN?XA-6gv!9ei/kLۼ65-#͸'h=͸:L3NhR Ew !* $ 8$<366: 0{ {6 ^5 2+ ,by(S!$G#flK :GZ )Y | HO ~9w' C3*g g  ay @" }Pfqk~RvgdSt6_]8}DpDp5/fDw72"6- Y\M)q[ rDT;\. }% (Ie)',b3+Q)5 ])o j'-%o"| 51Mh$*16 /E|x - f mght,AHչf׭ۋs?ޛ! B _#Am/#* L?NGif)F) hd NN0-ޥ]Q{ Q^V̈KԺȪgC6е3\la'w{%3B@k #%)R*(],+(( oCi H9b7:, Tu g| 6?@`[y'g*m!-   Pv(  M IlS ;|3,J , '  } ?v=K+W oc :w uDcElhC-WR<5t>+opis08_eTP%7DT)q t A !J!4r$+ + )l'C$6$"%/u[r G  I cRS w(dLW' ' Q 6( [1d {xY   YL(0 7 #XnQ )hOS4@tQ۲\MS@rkfT!B O*cp,Pys06ҁ:Pg82@%G~ N|u~</#l#OL!wXs$( Z9kq9;[' HE W BeQw2eDF lD?0hsݝn { fPY {@{Oѳ"FH>C!6764񮷟FX3|=Vuk_! Ja &))(,5-7/i5,1g>3[?&2<16>&s<&9@#6$.Vu('l) $ 9D7%+')y(q1312R.t51t+F")$q /Q  \!@RrsnY_bc!8.98r?P]B޹#U׷Ӏ֤آSE25ȃcϘQ05wm &    G6! ! 8$ 9$a %&}  $"6"!$W&i"))R(/&U0T -N & .jo) U%HwY&B eE-U/Pָsܱٗx]<{'Ghy Y  s%)+- .V144T3Q1-u(![lrAi }?1ƢOo $тKe¥_ƾ5Ѫ2̈tr%# @ $>bX%9),E..`,1 i(I %9 !G{3 G ! C } a + t U+  ] % &i='{&}/E+'"#l(6&# (t(")y$) * * " q +/R+@ 0]TL.W3Rr k {GoP:M X aR Ww"\NyzWMԦM:׆4Y۩4[{]h,miWV+2B rp"%C40.-,@&_R1- &s #YX1i Ioވyf$K b+e<~RLVFG }  I!)>!(#1(@* 4,4/21?,(1?,v3+ 60+7j*e-uP-&,3). W@ iJ)0i)PGq?DG|T{Q d YSR ~#b߮5ڪ{-`6\]@qAAuΙH ԝLQ ,K  V\eQhQՈSڌhw$! Z;XThV##l!"F34kANX'i!%)=' "* ,),* )#$k&K$*Q !*)5%x,A*='"K!Q@F; qwr ]H,:C%8}]DD}RT~ՈI!t$u#۲I$!4-x{ M"h?L&$iт#&ʔږSebQ6С4̒l]1 ! r rYq~*5v9^5B7@E[dB:C50,gJ:!i%9 !n "% T**,q-/#1)H1,-/,b+P93=.>)^BfL  A`2A4QƢUDWƘ@ ۩ܧS:`K6r|h" C7K!t)Ao#o3Jc@ǵM2ߚi()K?&8Qz*6ݓ6j[d:! / Al '^9*Qm.3[F8Y; `:I9h" >"?0!8'0^,0A-,;+2$,Y0^1g(1^,0 0.+wv$#v f0{{߮'Z DyI j6 ~6 x    B  7  &A ~ K H `AB)p|BV؎ & 'և#0#MNl V$ߑ߸]d DVyr[CNO p$%q"J41I)8(t&S$ T  M  8%mxBL C <2 3l .Z|LđIř rv u ^ SP ,V! ,W% (& 33[H1,9,E-s*;&! v K,! VXoܔNO֑܀'uJ84E} S*1]GlNLIMEG^SYNV=F:>.#H  7k%%rLT#v9PY6>ޒP ]zHfX$&)*.C/&0./<,v6+*j( !l2H56:4Ex'E =Z6=7.j(/ ] 3p-7%f 3 ZMQBsnZޒkM^bޒF2ܻ}n݉߸ vlEi/bB\grATX/(" P( PsQ"2d%%X&)+)M+m )+)*4 +**Q"2)'#'* &*n'7%7V"6 0{!x4P-&Y- _F#s4Vl_͸r{ hy y!* #"Fk5l51 "0r 60c1,")<> $X<ܔڂ=T/h4eXη/9;ώ'كݝj/c`pShF_W@s 63ޛ 5  / ELcm@B ,-*o# S4/)5e"P&Ko()+c .jp))(I^$" 3 pU_ p :VMGݰ(Zі%y_ҲxԦe9BY?hq!G }u *+F*>(1- )/'r$![M }hu4x<7`*Q1L*G!*"cRvo=X IG+3_b-|f2gFڠLyAV܊ 1?Ym޹g`1+ ;& Q*V6gYY n / *ru?t;' e |؅և"\#\-VyLNS {l %{+) o*.#& 0o8ڠM$ӱ$$oQ:^apST !SELhn pk;  GZ35Sև֤߸TkW>YViJ5Bl`"d"<}274<#4w#,34727130;o)9@&6k(2,1-* M)(!;  Ql ' KM^{'Mѿ "E7طQvdƿy{Sfج^A9'r+3E:{f*{*xf { QA],Sڽ$f!X"A|] 9  k%%%M yq0#10$.~",(%(%$"2" ~$a? w)3QSxi(B r|-  U+ Y a&y!ܱ3߇vb=*gZ|!7y7cPI4>BX)9 -Sc7pDO6Bc`@c)!/] |3 B[{Zj,\r"ae]>    t } 9_4R[ 0Q;Q  s Ni 7&6'% y 5'7";  ^1k;͑l+Ibʔ_Hx/8849 : t C O X i6=?  8 c>TR/hwF {1#*{5O?!&Zp4*2,c_68 n u"  g)' '`L  h LFkhk&I}!L"c&,]6dFN / f^x A  <t<CuO,PK\&. '] 4Hx5Ly 9"  e e@ w &7 Lr&.}hT\oiF`rw+֮ebu'Z.+ٵ;e  " Te)V+w+m%"w."-0{.~$!=/ o fTn}Pk! |QX7""w"c .LAt<% { 6 7xGv4Wq_@ V] CF  [+ muO > 4t(*ÈVt9bW[ΐ<37+GJ5<rV0 \,c6^ R o5l    CWLP&w+'ALN:ZR|05-].A MpY8qF,E1S-1].CF$QNB /]TTci k  AYAN z   _  $Q Cݺ(fؿ  YȺCj%$ ڳOA ^iT  u h i 0] D(wHm <5/'O^! w#!e"P%f 1!&6LF}  N ,  -   W  _d 0!} w  tG   & \ Q&ьÒIέIE>oOAHsH7Od! !lxLxT ~N'#۟(]L'=&* 3,1z85 u-1,6;$a7`(I:6%9:(@:'6"w0J6:.#wjo,AK:_CD3ҕe]X{߇Z~5Z Q&+D0ҕݰ8]Ϙ^p4 ٫K9D  v  U [ _qfi{ضxS}mF9 Cz'(0JX/ * iM !-k /4S8j9@">E$DA#C?&.?&U@%!x=4< 3d* 7!*N #FbmYPƶw:O .Ҽ޹mE   BYY=5\ s r +G@FbgW*oj*Ye_w (6(h%%0?( cB{ be!!R܀b4sי5؅3*:-^cOh)@5q@ Z, _[ { O  8  to<R>O s%   O 3 mvL5* ]'ݺi^pݰ߮G @ ~ sD#G Cff  t 6 Li ,`p o `@})<,S a~igXk8m &:"-kQ\"$"Fr!*n)%!!6 +Bv 3  :6iRq7pX36l i?C }!!!   2 +o@xsb!iOb 8r G=~X"{$kT"W,("m3Ckj:JP~ٵہs۲FͮXЄ߇qݓтҕeaRkhu9< 8 g kYPg#_ 5ly /K<F M))t*,)/,/,(#OT"$!)! 'EG u: o W1  f # wC}LI !j!6z& $#l" !$Z#lMJbu7B.XEވJΆb]ף&R : X<D  4E s[/Hb۩3ma?Aߑ-"Te2K #0p$,(5m:%=>#FY'7E&@%:%XجP9ޒQnYGEy-NN  KyTiW%9pn ywo.I߸⺜ɋ0[@9m[L,j0")2*407/9T,>'5636N,2$4m&./I,=%  I2V47H'>@* X Kwlc):H 02]dTpFRZKF&%X* T[:1R J iL)\%\H)iUHȌȃdض}S٫R"M3 M. 1Z1]+!53=}/}+ r!   "BQ .5^iXQ*5?o \Y A Ks ^5 ,P 93gp!:y\2K[o C" "c gp6{b_Z:rnH:1Vp37ms {;U L_ \.DsDq4S!! `\ tB i }YyA!%jR,!51 C: :;:pGvH A7#;?k"P;R !4+#!x!D#*Y Dy fZHY78_ZޯsFg(EۼH܊Co֑KչҲ B w&׆)ޥ |CX :?XL.[ A\ {Gl3&Bv)+m*Q T6 -7/ 42 .t7t4 &22!-& *G,ba%/$y"wl#S f"!#b"M`] {e h 6 G  qg  , 8   sl  k ; t tv B H ^ T { W ]m!J}  . Z@ {6LpYq*ug`g5 { Ydq*S~?4J:K6d W$ k  G)SP+ 3):f p I  t & k l >*[*^ 0PmP>fo^3 $XyUiQ~$Q`}ٍ֮ڂ.ؿہk(:} Q@XhtވiEWk{ Qf9M?  K5,IB8XC8 ^f,Fxv Z  }4S^ dk _ @ J U T M  { -S  vsE  * ' ."X[V"ly5W34'CY.s?6>>ZJ {'o:7*}}fMs= \LAY57 H"(@*nE) m'^ %% }$ U$N !Q $E   '    Xc-:[M> *1{?XS@ |*-#KAon!58Se[X/q#Q-Pl%sQ^WnYft ?IUz_/,]DwSD /* 05~_{+y+ ],h$Zp @[{Q?HP&Fu  tK  j ~  ]YgU4 E * uH%* 9hmXkH9?2fj.HkHXKL'v^S?g2&1 >Rg_W D,uI ;DQNbtjLX."?7!e@\h  ::we i"  9 qkm,R?<d7 {L q5  [  c  -+  B   RpR  i Q3dq :t _4  W } F S :4~TN`1L+H)DDNN^".@r_Wc'1(DcP{(Sk?XN,\ k } , , g'     XEO U4 x  5G3o3G: ( I /   N 4 m<LP|&As~Wt%~kBWWLj%ZKK &C{.}X|?Xemp)*V s hbN1Wu~1&uVPoN[k+{|_~r7rVu 6{p)<Zm7*+v-} -  IX F5[*[R  e [4`~5s0o (j;cQ@  @H1 ,Tts.&~[cvr8x6%BJ q 2wD0HV4(uJ"M^5S[HlGp X kw / D& uC 9 T    .V . u ) D D $ 3 h< @ ] eBcTV^WT5_|68Ta tHC/*8rEp s :oN[MZ)p " /lj?E'd-nN)P1oLx .^cKE09E/ Z& <Qf[3YF 0 ~M /T  ` it   T   R a  ( ,  : ~2 a[(\T@KKkwN'>P!be-/SF4m4 ;2* D T  y M  v  S 9  `v 3*)SwE1*8Bk~_7^<c3[!hLrJ%KeH.P-c/f X & 1+w R<3Z eQ1 ,|  | <   & | N  <lN3%3>r]6)F|#%{dA A @pAqw-KRg'bE <5J~uLX>pYz |"'.,o' 3N]96u/y~@DKN-bAL:rqB5?& J oE) 7 ? + )9MsB~F ]qK4  t(Q?   0< h[4#g,:80WXoH,|~|`(!A"TVB4@^USrLxow'u b.l;i&y 2#s|h2  |J {y ^  T   ) _  7 " p<M"r;i:"' DZM    ! /  ( 4-owR 9`yY6N-?o}?SW8uBa}'ic[>FJr~i'&(yZ H2CSg<3 _  ^4 hy  ac uE s - ;r  . A r K h gBt    QY{(q4je-  B (5]@\7q|XsNN!q4!Z3O;BoJ%BC'Pu\Yq6jB" d,C#m: & |*E#Gc _] | "+Pp`fr`BFX  Qd r }  h8 w H $   ' D:SYw{ " 0 M $b (xdsTV !\8X+Ygk/vBAX[4FXO"2R#V1j W  W.]Spl  t; A2 } 8  :    6 K j* x*Jx?p"@BJ_Q ^lP O<5o)+]f]2on@<sj39Z>2N)nwfZ^]VTJ\fsyg +y t t y } Xy } V |Z1Xo+ |5 t / x<Fw 3<)*[o!@@!Z\+~"+pf ' gh V c@wcY x4g+q!5"K7oVG:ew Ro{G4h*QSZi(,o4oRG"(Vdo s<_B4gR XK?}?3       w w o  KF * Rd!JL + 6 u uj,d<W|`4;F n P .  ` aC[rcO!gjv-n;;bCjq}*<'8CiB o5mi;0KEjr" D"%@{p# k-  : F j xG H R * {  7   G :4  I : k  ^ &H\p"P@`>,>Sfpt."0irM}T}_i7/QxQ Z&M*L_Lg%u'97G"WS  T | 3tLi]]/m  v e.+:wy]4b:FWthk~]GF@xli8>FxH?^4$pW;X((*  n  PPCY` }Gg@u.-ZM}oSl kY N C N(  ) ( cEccv3lF   }y?Mr!] : k t q+  + SmQ "^ h. &,h4q 5@,{}%..m81 + e &Ci)]>25P@ 6GHWfHWv -9E%lBieFA!xB Q T  C !j< ) T2T;gChV3)+c>c / ~ /  k " Z _x qP R L t  9j~S+d#/%%]k:?qu&G @8f 9 F;>huMn~9CbYX w3dٍؘٗgWrfLM(?P  rJZs-~ !$S{kqJiy  @5 "cm|w,lB@LNn P;NDy-QNfH><7_41p\CK?Dܞ3^Ǘ:ԉ?bIqeɩJӷkӞg(7Ӕ[5܊OUv 5 y!]?"@!nbg^%3fx5: "K\+ J h,1'h..M/0+*G;oG9J$7H/@t6N3nNZ0rM*xH&sG$NHM$LNB@?k>~=<%8l1,<&$* $u A8^ ' Q/Nf%s!%6[t\C[+p>{Y"=ڂ]X".7OA^i|fZ9i.p 2 6 w #p9v7 qB(S=)+י+)؅)!u&]%*$&8 R%e Ko$-| A"m#i#497|7 B*@V)><':S)\8_'3#-'#; # Mf)*ވR9JǍ̹ćrǗ=*(8`2֮ 3ҁL1o;M~<~'2 ^8s ԺB"!g$:%)+L*>.~C./8, .!.(,+2+)>+<[+c@+>-0:6+B,C].tD/K>'0>1S>1,B1:1,;+167/6-a60+P3*n,l)&B%(S##"" !Dw7 ga* VuK/ٗ@ۼ{onXI؎׆+V`'˝ f kWp]+6PfE չNݓT9f3,]q8_u:23=86<244m4w "7/ g5E 0 |);41",+'-%#;G   |RD-@h!e-Fr'/mk4au ֤iTjs˿߻`V*Y >^26-O  Oٍ$J|ج'׷+1">51 :Sv?CGFcJLNLM! MR9K{JEx?>9J42+Z&F@ .* a,S?iz!e9V!WO"Al)v, %#P%9%V k%j k("&5#lM  i]eh$b{ɩP큼Ž8gpZJpH4̹#=W{,? at   K  ~q h  hQnwzG$u%Z$"%$8$""  `T ! 4=5BsC { : j'Q}T T W wf  a@E8*xw+*QC#X0-%~B9 ^q9˓Zν տeŬ 0 q ~p:zpon+GV8E֚)yέP͑e8L͸Ѝ԰>ޯ IT #l'A U% "<',N)>! ^ t^ "2KݦS?]AP߸a2[gi ` q  U$!Q "P " L" BV\U O  8t #E%y#P1[/i^)!)a m  | q]$--^zԓm Cޛ49 BM/qޒLhS+k o|d@J?GgZ3 SJ /35 F)"RHH k{ sb YQ ) P 9R k   m   h |h !.&-3 5@CA|<9FD4?94 .j 7'r Ple ,r X+f4 zv颙楋z'LآϿu|< U- qHX! )H* Z fH$Y:U~ ^)";p9|h !40z %  {he # _ [.g)$'A)g',Y*)>("r$] T~  I ڳ١Yо:̯4fT{VAcQx֤fjWe_J,vOGR W ,q)m 3 P ?o{;&&8-5N>OOQ0fNHaa<x^,;T- V\NdG<[,!0g6S7|a3١ B4(03$AIyf6<hS@k ͮ@\Ԧ R5Zc+cGwb B  ai  & E}$'-((,-W-)$i*-'7rc  |  S+ \ A 6&}6"Q ^op- I?W_F5e9KL  Kw  3[f~\@3WQ'*}ܧ _vz 5@,5ٗ ܔ}\* jX1 4  S   6.("!jQ D `K+S*io"$9ܞBވ+3.f )  }<'T&_+0A3Q#8!8;f9z;7L6+2o~/);)*  \  D[  ~  Y *>pDyFu{i!i&+iވk },~VD f+Vw_Y&YS[*#i$ST%#t It 0:^nkDw!P{pC?\]TB!c*RV3fY#;%Mk'hr*[+-.H.t-l,v'?N:?0:8$7 7L+1)\]'ru)3Ae yC 6 (  DF'F9υɼ fʺtCᶽ @3⍺۽NƘʞauڌRR.|;% j ;m%^^) !%C$ V$ swNX g%V/s 2 7t>E[DyJN MV tT SK KJ|K B: }.4"  G! AJ*X^Z\b<եKٗԓ١zn؅$uC0Kw9\ԝ֤YGM׆pA'=2,9A?_R,{WWbQtk"W+f h ?H om=H D   /4r  g ]gi{C$:4-'6N< @>=<;okMKE>v:KvGE @)=:gj6u/.*)'^J`qLm~XmQO0YF ЍaJ&XеAJök3{MǼ~nȪ=}|?2=ك@ݓ h n"W !$u&k&*&B'|(|)*&*') ,$%~(@8+ ,'T& ',(#+-:)+5%2կ٫AܧVڂwW .ifH   Bq"!GX'r)f+-+,e.~0#2 + 2,(,,# "Zi!&w) 3Q 7t8_6@@?'H;><95.23 X6u L( |(q S) -)!  9O%e  iS -vܔ5Oۋ|ƶ~~]3ƿ-(8`Ͽǵʞt-@ck t.2|v5M} ەX+m+ g4.-]_( Q"$&K '{_'0% +/*3)H5%/25*C(,D'#E$A8$E$DR%C'A@"=%;)<'6N*45,4-04.3/81-0).+w.&+ o)y$" L< <u5t:p7:8 sq۟Dz!lӔӞD,0U)ԺKsؿ#$ÜQ͇Bԓ"-4۲Nqi#:vh^ك_ $)  &[*ޯ$rfJhL>>2N  X G&s]! &-9'=F(AU)D>(qG/RV0Q .K,bRB*N*eJU(gB:3'/**  #WSp `bLod~M{NjAnOcxnA&$gN/je|ٗ7]/L/Pg66}ʨXˉ N}ΐM_TVϬЗ1׏\&WWT,\:   Q B6  o&%M#&&&}(#v/|'/$'h4F$9;@VCSDAKELKH>XOHC `? 8| 2 s+ q'KH\ !$m$DT"<&NU!Jh i^ sZ$p&$-a14956397:]p<9=ZL<h=F =<>E5= >l::W954Z0X) yPma ` Q,    "ڂ $ a ˓q,+ b|Mb<qCJR  ` mfA   KT YQNBG4)V0] ʀNgw,BC`^/u3Mb([S \ S8:R-!#Y#&}&'{(_%~fXlz91N.P,Ptf," 6 X{ROn  Ge_w " I  ]FY  B-<O60V2tXX`!k!b| % SK `Bm3 B? r QM;&sJs{^ B *L#&8. 37jA|EPB=HE?[949.4+< * it)+:9ld' t R . >]b,o .ݺX@߸y Dc U kkfO#* ( K{SBS%kYlX2e15о(1Tw+Q $qxe  3 W /T Civ7 :N ^ jr}"%~&s&<q)H'^{&s! `x > 3xf]  ad 9c a e36p3uBd.VAh T   7 3 h wkM7 RdExK.܀wʨfU͹<AB2~ϼtqO '@ 60#)!G &8 +l)+6+P.3/860! /_"c/!=/$ H.`,+'#v!  //P,Zr[D" "2$e"F F& q" - x. ~4JoXcvFYX ; m+o? 4 "ogm5Cf(YbgD/>=ۋl~p6Nr8|]sc + u^ }w N w!`i/^Y {Tg * _~iCu:w0 3Z# " Ij s" -0 s U 3  k   !9!?!_+/0D1q5i6 331p12!1,&7h1iRWpn>IWтP_YLcMj٥5ʩˬd뗷dpQ"XfB^]܊>tY#qY{x(~ *=H?0Q[ @ I5  wxmwpg !"",(I->2O; L=>uJA{K-H:2@VGXB;5.~'"l3 j 8!=7i/\+Hp& gd &AyO1KG o^):@ Cd ?K U ~v~ W<  9F  K* p5R; ) wc hg }-  fs%$%jv"K%%Vn%($a#%G+F%z%n%t`%&%/!| rJ~ k",> Dݦݝޛ|V'EjСьԝe<܊ 6 / 0zPZyRHD W_`MM\h\z# R!""w"!"F"q}k,w6 "  h D%~(})D7};4{=:FPEGFP`CI~D S@<@ t>b s4 / r.C -& r Q Rn~gefЄkBaͮYԺ|:f5eZ ֤ь"Gʱ ȴȽKry?׏)kQb6Ab: k"W :Y+9~BAuCP~] y !Z   &v|-:G<p & u )"##V&$+c('^#%$&$:%3}/N 794u 6 RM\4C64j^\ޯWZ߮-72'F{EFOO4.5{`Pb? :c 75 j#4)u_Q4@< _ ` 9x1"$U$7((&.$'r)5C!  y  ! sg+B*tWMu kv:( K? $ _hw%r%XX'<.LB>тPd#w޹o1;bEfLk3{ .ot :],*s6gr 9.XH s PO:}IN1Gxx B4%-r1_+!}  ~ =3 uAFly   ho 5 * w   $BpC  (;}RtmCG/v7]*y _@7Re 0h>WUpfD N~9p G8t}70;#X0 > 7 ] ^ {G(  u:"2"2" q$ {$a ]$k!G  ^ - f   ^Q g ? 5 ~ s  hti47A`Z"*?"\U`'N:Ni-keoV9  rb/euH ,*-AChfuegH|nEO M ~du`^_9 1v tq5 "2 D$N N%C '(I & L# ^ g  U*A  C  d - AA_;+i|x( x @ / hf$L 5[d9iXrߑrgUOqV=WNBAX.";+d  WY 9!  Z k?  W p X9  S !4 # "!xQ!   L  _4 So A T8 h,*_cM1EJ=A/lEp]6 XG}=K}g"p)N$q'|8:F ^ h }g<kc4\ E8er#Izh^ix  ( )f&, Kr[/2#]yK@~ u)e=gp{c+5AduX!up}^ASRyuQALg:9 : B  HD4LP.kS@H-}U D X# ' ' )\)(,0*(%`#!C I A T {`; 0M 0 vF\rMr"<`? ]:/0iUn4;Q)t-25Pb2Pve!J` F[O r .  ,~wv : ~| q6s~b u ) Zk W.3)[ Xm q B @- =HYxc p g - L6!o^LSJB:'-~A&{NopCtkh^ >xruQv(jw-< b=N(FZ1  5ye= yy>e4!o,Q@ %&Of B  }  _9F-.o67 / ;! Y1 'lT-\ :E*{De~;{_K5]>6PyHy94gx#"3q GGRVy?J vA K  Ur si ]-F+cJDNAvkQ9gP  :8K}w` ]N L [ : 0   S 6fg6)`:H  MnxxJ@K89u9nW9':P]DB8O=\p44p[ Nju!PWuM" 9 gb:DS jLkhq'Edd*i& 0e   s 7 sw TE - M a^ Zy_.}9M eKr~02F* 7dfw.'",.eZm!N#k`{"bs]AI&ffG 0g : `! ]G~(Cj8R4WG^(RD<] YP e `  -i W  . & { T  Yc  _c M 7G,I:ePe|_~bX ,n :Wt3"Vcnj*}LgponOJNQxq-~RxN*> U mlT1 C} ! yZ 5~4V1 M    O y  a 5 xFmG>{6 yr>Ry9bwY@. 7 < TX 6 c (o%h.-9AA{2 p}|2ZZCg5}# {   k Bi ^ 6 "*l)) 3EAf  I  ) k lFj{6 gSVe   A4 >o! ,  / LPy"ht ]T9kc(B3lA:m5f[?E :  / {kktio8+@:<4Jq^  wX'B+?Lp ^Mu , D;.Jo[q?T_D2,2<3)v  cZ;:~%"5 >Durb( W7 $* TQ " 6 {W & |N F } 9 :Ly\xFPx '{ot>ex!q;dGQ!@<-6rMA:-X-6<uk^&f y D  `F w X ' N33"*f*yyo4``b M>mO< a ' a c'x4]ceIL8vA|XSAq+\J>x  ` W *  o # 5 y pY wm 0  :o ~4 o xNF @ZP q :7O}pitQ0itl.Kc)< pq}y%r_sW<ig?x3|M~Xik9p5=l]  vq2>X?\3<S@ . | - } " -6 T !7<d: C  U |R/ Tx@4y  -      _Z +  ' d ,)y  E  |V # E>j&[B`9/ENG{>gqijD"pe!{^i-<9:&~fe>uZ`c 'F ,X ]5y -  i lEO( _    4 #[ -   N  M a   S 6 R \ S { k ( P 3;P ZqcA.i ZRGnqXb<g~M @(9ksY6bs:jJpKi& Mq *3w ' t (AgBG3X`LAy  > 6ff3y;' ku Ene)!F } sC 0 X}  :Z 3*\ a< sT*"2'2!jy|@AQ&tk; F4{QB(  _:Z2O+ vr^ f8`dy_8eD ~ }9k,s{p>}^.&;~ t T2(vw#!wjwa D T {:n!~QKJ.'R  @ B31 pHo[j+j_   a C |Y(Ze = }m n\.1; t OPl^7B%thpb!!ey:`V:AE#5h1w$\6}KNRc gnPZ[PlXK_si:q63l N |4 %: )9Q^(_s$Ed'p "r  B K p*`7MHumR"6)#   o   _u ^  N $ &\  oc Nep?&!>=`}P8F3y_`kZ?96|-}Z>L;jCoL6yd]<( Mr __;   )< 3W(HK0Cl  gB @T uFwe]%5)[BNE < }H x\#Gs"ss -3Sdr6fczS]h|cCkM bF7|W޹k  5]]`g= e ld [qGDq  W! " {"#Y"!$W#!q! U^Ph `Z= K?~}-QN\Gxbd[E 5|oz6eW _   _ ^ ''/ ! \,,\u   @  ~Bp~MD q jEa[۩]8HەN,8-]_x}4!Pt r3J &i++w>(q*4+ -& ) '7!n ! M`< u@,u5G" jb #& Lc0B `eB LPx?%Z WYKףOBѽӧĮ [{zbeآu-b@ )~YC >& 1 p{^ARa{͇xӞhZs48GQy4@4(/|3=>rB#@LLdI BqG1aA_N:2G+$?z iR\q'9 6t  R Y [J|Cx I^XT 5 9w uP   t 9 9  X _x g5.J`1~!o=7ZnT{@kFsL IA*H  G[m* k ` bKy$0%c#FS"Z!y"gm} H k [ j; K}p(%ru5a-bbjr N SQ iWؿ]1+JqhTd t { q q {H  ]y)0 N2=tڪ4Y_)J3߮ y=Jfv-t+,..3M} )ӊ{0B[C C ,tte *#v|z'$ ,"\hql / J)kbq"ޛ!Q\/ t3  p?  _ + A /QeS "@ u W IW N; d| U^Pd';r,h 8 /  A jOgكHu ˰ s' ηLC9!t\3Tpq +g 9%pt . w5Y  o ( {5  6[? #W}Iܞ R5ܔ2ܱJ5zBZ l&A/_585 En FwFC6D8A_?&;.'$a G  jVkAxt +JGm5 w X5 4 yPږ]#}Q? ] {l L H7#EJ!G5/s/.*-$(I$kv ~&Lv 9 $54G{  Є Ι@,mIޛ32q*Qݦ()o()f)>*&>?ft j4   M2 c 8 m | 6R _ @ :h 3qb ' [?  CX 7$yCbK-K|pa[ A }7 ͰEcɞ;&ohF3miŷt$ "P&D!!G27RRU 0 .  m3 3p T N\"^*nd,O$+F(6775;@@[@@B7@%:"7`-0(, E MrQ !"w!Ѡ(%!"r.fx!}: +$|!C &P}Mig2ZO~ h\_;~mP1ۼӔ j̒[#p#M3Ȳ_Ge˝ףՒ8}ԝ=*pdmԺ`^m17#4$.' -N5B<=EdBGvC6!P]KB^2m71Iq,(=v?? ! @ W) [ D: a  Z iUL "%)+&$&B)?- +&"?l 7 6E 8o 1FMF˻`"]ȵ9?Z`˝\ Uaa+Ƞ$̯UsȃVӊV(@!O4(|l . i - :p"(k.3x:A?iCXFjK7_M!gLLKIL D4p@:? 51U%9 $a %%/K"<&#,? `3 gg k."Khux~>G!?pj!G  ? ML| WB|]@#%:f0+ڽAZuX{ݓXfߚ&n׷7"(Rؿݰ0D+ O -5'- ./ ,N;;|8$h1zR33/-,3} K >vJW"dxC  3   c[^[  /d?  mdN$[  x}+d MX{+ SI gyPySo-g*Q $2%Bcsy M4 q>[,߇H N 0 _Ygض ݓ[ u  0E \Q{B d %3CoRiԺE Ӕe˓D͚9ΆЗ Z]a!d!  wV# %`%M-N'2/|6W190<-:?4*ԓ5B7?ݦQpcfp,# * c y-&**/8. @/B'. 53-0"$0(,,*-#.92d362+q3 0^-k!)%:  { ܱ Qجج֤\a؎ڌbܱ8(ہh_wGW:Fy8p {"\~3 @ H2 7>T)zT G$|3 Sb\!)++d+ (+)>(]$b |x{ /| Q  ('ҕ*q -B  `$EXrz̹̜k̈P8o8,۲ z2=u72sf"'^* J(g(-,.//U..2+2/)y*%%M#!nQl C oM%&Pك׆ Q@e8Nވ0ڠii$*|;i} C:  423d./5!420A,#1}E[c  9PD>qcf&/ 5Whc8m 0o\ ^H   $\ , s D]\pi<_ ,# &HdBW4 2 j ? $ 2,6) -Z11euR }6g0S[N4  A5 1s .M  `   yR w  ^ ' g ]Q  {6 @ پ BԺ No$ɿ[\>TBPFSwt$zVޛ?kK%50 7 ; 7:?krB@<[594 07C. ^ V & #  ] | Dy s#uL<mOs$D`([ tM%tj"Yq Mw I_/m-H3 pEAMX ~ 3<(^ k#՛ ף Ƭ "V+!Ѡ)ùoU = W|ە܊L=.r  :A!n&+^/./1 11/U,l'{F##s S qP ,3|e,  I {  H B ! j>S| [3kN v " 6<  5!=f#!%`z&)+'$D! I /*$Ml!@ߔwl3⫶B>-h̯Sߚ]v=F| R z@M{  B  Q # H D $$`&(&K"<])@)4+!=Fe$b\\IsFQ   #( &_#&E++<`(@-!R$i,s k#WtK }q < _ H& ~ {ef 2wdxQCsuD̥ҕ|8#>]t A} /FΆ Sdޒ !e%5&r$0:! '7'%$!e#"%!(z) H$&% &&.    ~i# 3 ^rɁ)7 $ !e%j H' H&)$/8&.&i.%(($(6C'7 "l 9 A P :8%[6Nsu#YΐB&"\xQ*n) q#<0d /{d|f[ pkI7.ٵ4IڂFC[܊߸mudKG C  r!*5]w] @ "k7 a(Ck I & \ Qa" g#! 7A  7a GD)ic2P6)?q޹C۩*${,_M :o) B0[4Y0VBD!>v)2+"ZV1("$Y#`5Y7G3./J.9,- )( !_'? 97#A*?,Ƣ jp Wxl . ~b } gV! ]0&$(zv(I"%B"gX3ef7^ L')>+233,1>,v@/8 +'C|.  #-qBOxeG'% Id,W h\G "&v"{4T  @ ,V C  % 8m{ ' N:/XWnEqeޒ Eη~5oӀ f i #& .j - 6G K J C :QLI!D?i7VX.&()R  Q 73 t ' L5c׏ }˦H̒ Cw>I#˝I %gԝ2q.!4S ($k! Xp TyQJ?' `xu &h S d"#."P+./I,11,Oq-W*Q#  +ll)%jv&Bޒ$آ&#%{ 0d \7U3ݓ}L=}v3  W3 4 !;RH4  @E+Cy6ܱE~ʱ /TbΙ@ԝ<XC_~b r pO} 9$a% -.-3+<3'T07(SC$C::)A3[,E A# >=ϘPsGѿ `(#*NA"?G;. c tN +%(@%&Bh$*![\qyrA  % + aAO8/ k(oh ,gc^ޛ߸.+ydZ7 `fo5A."i^<kv Pnv%(%i9O|  tV 3P2  %EA@-~(g(%!Ҳ%9"_qϘk9!lV 3ԓѽPKf&)  o (;+X**:S"="=h8%<%:"9s0n-D-$ ` !#7Fn ޛ^@ ߇R"_6r MvO''%& R%`#O["  u  .s Ov gCx5@|NpCbw7h+BUBtdshm** ";=!L$N&--* /&_ +R''")a$&'$D!)* *+(S6&K%t") hv^HN < $ ^ t8q#F[:\'h>#>[]'DەVە:-6%2+YK e2MNR    _ H #E)~ m "; kN K1 Ѡ  M sҲ  $ & '2" k  0h 9F>l:VwUfM! !S!xN"D!Q4#+#!4hGf~ӱP_s@aN߮E۲bOe{ b : :ݰFp. &l[ ; Tm} &d<7v p B'" h ~?U KL2 2 vҼGٵu 6L%i$:")L6c* ( ,1,)3&2fj1I/$.++wN,$D!nL ZPH9t`d @ A -z  gCos}'ӻ*ٗL,|׏֚ʨ8=N۟ݦ] 1^~ \ |\  ;  ` : /f+nR]0 1YtWGp{ !ߤ 5*E~_ ,K6aO9q 75bQ!T{ 7O JS O sJA;7 M.%( S @ Nx hہ4 _˝NG{K5(b١؅ہm6ӱ %ڽ v"w+#!~3 o ZG+)Ci{{6`6|'+ZC*&$30^*Zi8 m ?`bܞK9%$֑  ݺ_ݦ.ָ yD!!Ai[LC],F F[ ?  8S)Hr*=,O+17-) !2"> I } ܊ З]~2yh4KsYFeW e=  P #O@#?$0\%H'Jf'x%)%!!Y Tw B iE6>+Qw~`nI\ņ{[9 8ج%W Y%j '&Uf&H$ %^#Yz 6 f "4  My%:4PJk=!NQ &k.23DmDe?60C< :4 &_ :( g  W | W;RlZK2 #x(> ] &Hi-dL@%jޛVz W,k `8_ 8,q("3߇G\֮7Qhe%b߳KX\B[JGNg0_ !7#Y:!4;>O\;H?D /= : {7F*QY$W !x=wl LoDhud `T   @Sgj7-Ny/_05S64c0.R+)'#lZd 5<Wx B  ܞ ^d dnhܔ;UKZ$5H5g\8g.S"67+{Lk`ۋxïWu3>G(\[ %w**G$:00,%~#!#bG&K,  $D['^)fa(z/&$.t(,1'#)H$&)+)%) %q o=@( k!x ^ a: ٍ۩HNL>Dk;"}S f qct D 6sT*7gG؎|7vf~Ƞs\كFfS # %'&U0J1x2fi1-'SXhcFr?We?h߮')< j/ : |aY|@I -m&."KXu( ^ N  ~ lZp[C & T2{f,6%ku Z3 i]7p\70%'6? \ G M " KAwHi#Sp!( N 9 ,  ^  vv~81MbX ,}ad 6o ,_|U߇E߇OJ:v %B{]i#1 o / B`Zs+ $|^ٍވFp2RENjNC#ye3Log .yf3R>^[d  B G*Z6!;}d }  4l]|iX4 f%j"Q!41QfjX 6{J6hȴ`ui{P+ݰK߇@߇߮uSwhhG}i*D6.q!l P M c7ewQ]E !zWN! "կKP*p7pPkh,Pw);/!4 k 8_|aQ{3 C34 #`T f ~(@(gF%*"<(%! Rv  yxZv 0c-  ] g  B !]~ضBтu, Ͽ]n f&e)y > ؘnޒ5d zqx`b4{c+Tq;4\hB9 $ &+0J/B.^1u2y.9+<'7w%M! &B*,l , ./.j)&%k"L@#u5Yp B_9;FqYZ L T *D[B9.l* ]# #i2]ML'Wc|'] Gls,|A J S iT[=]6Q S $dL!iP Ry Y ^  m;(O M(dn_* <h%dk R- 'H"[nf:P {Y ,\ jq LN]\L^C(^@m .p $M+o'f}۲gvޥo߇aH+!Lr&WN1Bgm*sbYt8R  :m ~!  :K , }? i WCjr)9Do    k a  ' i*_9l q y (x;0J ]/4 >/tN[ & @ d   ZlsdcZotvOcP3R4);w.dkS '  ZtxTHb5 T  L "ATS@\7 " i?4 ]'.J,f vN  av   W    Wq   Zy wQ)Wt!2@pAOA-LAߑ#Khg]" +jrJ>Xvu.~Nn+)"vS4rxZg Q ckfxQ3 'Z a _ |   8 _ 9 <*?sb<jCk: i + p_ M K4 j5~ku ' spm|P~Td-7f)*H=)$s+.-<}FfkK6-)4 , W5xXYt+aPk~T6"m#""#% #; f!F!n;%uHTn  5[R.J`?  &+ݺ^܊/۩<ޒKG_, V| %\?h3D$(E%|?91Ze) iz {g{i]z+):! h^C,gq2Q Y {Y G ; uO` w !x   9 / F r6 b4F{j9K'K_?9B - 03)+ i i & 6 yp4mq,v()o`5lL qAnrvKu{s"H:LG1[T  p  7I !  g   f g { S+ I Ip    +dbpk8:V"ERd[e]\    g  a[151"?~~ s!?Rp]xJ4f2>E0EbtB~dog"r|Rv u|H( :  M; E U  kd w 'Y u 0y"(  < N[  !R A |Jx*@  B L< w (    h d'f  *4M*?4ۋUzϬJ͇ˉ^ɟEIӔڠ߮F|'v -? Ke q -&ZL>^[j k H ]qw\\IPyD&G9i<*3Q / b   g eGe]5h    l4p\ 6 A h U tP*"%b/A[Czaq>w4( L _ M & ]ޥ I i tB 0)K|V[Z-u lD}>s?P # $! h   @v 'O))3?:k|Bt9G\3^ _ @t 8- K2@ ; f<m9jFdMy-1 AGXi"'*M.'jf* L #8 |B %  -h  n &qf:%& k DMNNDAb'u *p - Ee34yRpg]9 :lO  U : _ 6 .Q u } # /y  0 0tO?|q !wGx#.~  Q "LVDAAh|OL'kLVh,q| "x3{ , \Ob)\{VrM72%^*Gl~kLok} p<  B K3Z Fx*?sp-qgf\peY l 9 # "fn\4o wH4yM    N>D,9pQH@N#_}uu/D`.%ik-&.~q Q*Cis ^ Spw ' _$ Ty B\@#Hd[e=#~9:xG h | W2n3o oe 37~Rx54)  q V j' w tRc~2*B!LO1 ) f?b.I]n <%q*;` P j ,c#i=&1+U@i-![8]r !q#E@#be$#9$%_$^""!]>!zTHw5  s m\!}\"g#.COe-57%BX,R3V'rSh\9T~t~riQrTXkK8s5 )G*9 r ~%!^Hs' != " $ '(]'()](''F$DH", !Z`d 0 :GN`8eKPJeP~@o\4 dZdwy.is8^sL#}z51n:5VkNMܧݰ..S)t_%/^`w  I5 KVtBh+\5q-| h7# t@||+KUft3/  O   }3  j @ ~  X2)}Rjmt.y"E/Gc l >|*(/ TR_GLQ Cp 3 # t 'A8:'`oW?Wh8V64D0 $ 1 ,`-'sH?atlF )[u} 7&DW.de.]Q|/_MW N  }, [4F(_j[ R 9 A Z qy S T D QE 4d7Bq  8 ~Q#5Ww*;  8{ :r9 2N*?RLi{RHedH6pXm N c '@ x(wLl\8&8uoxN9G8eN9Zh Wv 6 f K<mlud;N! I# S<{$' mH.T N7}#b kfCZ.G] @RG+Zvr }  ! K E 3 u  p?T!!./iNu1}Q(b m u/!F.)sw(H1\&a!\H'Do;rd3* 8< a L &S  x K\8 \A&dwك9xF{Iף!;-+(_iqA :| 7 r ^8SrB]?5)qw:B"\>1_|fY / t {!xO^+?4n eQ6q.X$0p \H $E . V : K8F4۟ *xfؘ+ږ)޹\!=PP; CeVdG*$wW07AV[CH eY 0  }v8 P0w_?Q u  Xv ; gQ     i i{r8}Y , r G B I 0   L A Gk7vVcV  4 *,-Nncd/ ۋ?%/zك P  .C R   : 7sy!x"D"Z !Q"! >K["fpDO q 9 9';O+;@ I9}?{<E  o  K      0<w\^Yj1Sڌ \!+ߑ.N9ALSto  q^ir4 =YI.! i8r)~ :G|L `5B-Q]87RL  :O"X DJj= ~+SQޯgޥپڪ{nB8 aV } o @k T^ : `5 9WAR6GP a8 6 C# ~ H+-hٗH߇w:hb-y |9*{F ux  N g jA vp+3 _f 5 :|M-V'/ijiCb ~(  *; m|Zw_ S 8PJ;\'5gHYT-\J(5QB8m6 bEJYj`` y +B^edGGW 5 Iu Uܞؘ@`ӱ|)ԝ(fv M) "]:![!e 5%&}/$D07q(\)(IB$0x.r s;3 $}\>h+5@[:d֚0{5`K* ^P!LWYPpy=v  `?Bf3SRK!u7< mNI]"(#""w," -SY#U[sTF p  I Ne * qYKx@D<c)` !wEqjs'&gPiCE IS [1[_O 5 uQi{|1 B6xd5.UJPY @TO2FEgpv-  3 " 8b\gp3b 9G ԰KK uJ NgCgj)#4'Ty*QI+c,/B"F0- R-*Q,( #$N0pFA5036nGxjs [NbE$U] "i4"P: C ?E_'!W!FYT&? "R c V 55 XB[*x)T9N3E1Q ڪ ^1R%XQ`CFV?7t@48? XZ :] v | 0Z ~ , &Q&!D/*n)H*&"'D? j  xjH+QY &J Y5irgG#dK1B)W\d ^.tAT'e ؎*ڂݝ*Wmߚ6^ by ,  B~?"3F*Y  X   M[ _J hB & {awFsxYG   '  4 5  !\ Sd)bKot0ܱsy!te/e 6)h#uru#rqR |  k g <}hxu~er4@:* Ԧج~۩N||2C + k%)\*+2|0A0.+c%)y a%V !o >ZPL +% B.m `tF! f ~ g q)Xw5,~u  ~mVaGX"(XkM3(ܔ?=O "ݺ_J Y:FM9q@0'Ak9  ". bzu TN?` } "~n_xd  ':4nN@JEP0lIF#KAS +T! G]%&Q%~ "!!^p6 - i4_9Y 9u V!@'0>4Z2i/<8'1$s&8 &.}jHٗޒHӔ*СЄ_͑EȠʊaciYҁ*ؘQI|ޒ e  | 0p\, Q!hV@4E`_$ 0w \ 9 r " Nhv^vTU:NNv3LM  "7>[sOR)-z+82 ]!C\5lOd9)t.CB  bt4 Ir6 f 1'g*JԦ/E~CіJ\HNج ?I+m    p( 5 -_,=rw#wnUA U !x&(S%%-"0A#/8"A8 B^@V_<> 69@ :2!*e#YE`fqvmV_+xJat^NoiI"h1"/YoECH@͵z @-߮): ,&_-: 0,G[EV@%6kF=c D5b-ND%nAs^*\ fM@+ ih>\-R"1#Y!H 3#" 8ZR# G j  +q;m? \`i -SH,V  Nc c b%Ai"7h:]pX oW.!*`%i,+<+*n(K0{+P"Pe!Qn s}N(ic &| #RH)g ?)z?Kn^"RrLӔC-8DTL~?7ĤtLо1@O5M.  T 3m ~wZ\"HjBb>  Sz##&.%&_'^518i4:2:,8|4B0#A,(?&=!=83nS-W (!=9w8 ) XpR e _jr"t%h$|"!4 h!iw_?#>z͚K^;7Sԉx١݉p}GL .v jCs *\ G)a<gCS/I   (!g#m*/K./*$,(&j#(~C MkRev CC tKR]If &c(, (6&$!42o/%-s&Lg rLwAEg 9;qƅ!޿L5PĚHsʊ755եuTrew]sA`Ks ; KDO KR) 34yO^Xc  .#E"7t;H71>E ;H29?606-,-Wp]JT6^0 XR[AMit9BSD[ qm!3 kf s $;Ydo uC_9uy.jp L T K ~D:mP c &{ڌbևL֤2j6c܀-N=VףKB,* كҁFض[p6&. _?t #JoVZEvm W-.(tV y$uك!e=*i6ݓ7ޒ<=9OcKLS@HJDR := @3 )f6#;n",   L*;+   B `-t@71wv QG0!*#Y#b" RUg kc VOAVY,| /kAk"Ki5snH=xޯ5RI3p9pIOi";+;i>,;4 PFM>E6uDW?7 ' 6 f 6ie LS`7pQ- F    i _Y 5> { @y iTEI]B'yZLtH8>(N\_ؘN/! о ! I: ە t PS A *I>oc9} 'E"mF,5;xH~OUzhT8bX]bX\5Q [ T L C S:g ^1, .,b)!8~*E ir8<?6i)eJ a u LT Tu o? Ո p tե N֤ aޥP߇Kf]L< x!'jlcߤ6C,E\w׆nEΆ7l _5˦cVgo]g:կ,y:QP'/8.q8n7TCGcICsG/E=sC6DeQ?b70#-)\("fxGqv ' ] X M9 ? C>  ,+N"$0wh l  ?Yw1!(!U! h!=آ"<$&  -S,7NNx-d 4qߚ'#߸jώn*1͚N'U߮2ܧc P`  Q.'7B.t.--[<<:6k84m@4c1}'N$#57C   ixN  )- Y,@j;|f_:Ag[ P  `     v@\;/?W[DR,b?'0Z} dy UѪ4pbؘd/$u$N4 \wxgdXaEzu2L)P "  ,W5 q  Sb   /, . Fe  *tV*]7|4  j 't,6g"&-"e&\  [G% $8) Z j wg @ I ! ܧ۟ ߇ ) 0OF  vf g!G 'T4) )$04$/'AS+h&.M<| T ^k$  N=o E ;Q(Zy5E= ʔ c̜GYy[8  rj3%v b0OpZFH  BW@ x|Q1ri73Q  ~L  @ p5 Ku[ 4N/ a J$]$:ڌ%M$a"P.$![OVB[o A)>LY / ] $o l!yLݰWE)dηJ6OV3+<<f} 4 B *4-A-(0^0.+F ,~!  Z P n6 .h`\*4K XH B i+ # . Z UY q- / ,}~C\5v} >F-LAs;gZBH3Nb˺HҶ-! $% ?gݓVhjE:$6u_;*> 4 8zyK, G&JK82 & rIDWv4Fn N$4wBiEg @:nqLUK,GDdC.Gf .8 {ZY M)   W; D;% s$& N  *"2TXL'e L! x/{'SڽzZ>ڌ,&`Rks9 h v9NZQ*@B B$`Z]$Z/1-*no07(;^)2ܞ ˓  ޲eKҽƅOa, )#., z#86.0h%*n $a:6DUkNT]G!`B} Rk!n R + Z  ~?( HXeo,R(QfoеnΆi-?gFqk׆0nF?"[@"u%.&8 +)u(z} 8 [)" y#" /s .~ U( q$&);:^X, xM?<kui  `w 7RKL*ij>ޒI}"TMq|mITJ4w6W}H?#'7&8g=@s> 6ZM%\\ tJn@!W)-01"G8T8i94 074(.&.Y R JڂwޒvCͤA°*Y(V.Qr {dE + W :T< < N $m : C x b 'rb)v/B3[7r:=C?> @AA@;+=F(q7$W11I,+))#b&  >] MTU ,0 y"!?S;Q*Nr0kd ,  g  f #%# pK e#%ݺ9w >7ٵf}Eޛm~FrJ!i-hC]K?1 ,PLO7u P; - sy) ) gx#XP` @ 9-L^{. :1|O S f e` s @ _m  N" "Fr%%&ږ&-#(W&̹$0"#l ɟ|< $Q'%S"t&؅ΐ K- GyY K Qk=.RT:,M_ K \#)y,1S84 T7C9}:]8.:$ 7&B3'-$+'&'#!'D&_ `dw _ K B,x>"GH]c?} n c HW]aGD. S=9XD*z.^e Qqrr{<ۼkUܱ`۲կݦי ە^P ՛ٵ,[_$Zw)(itA " # !"i!r oC?nv! B61 FRR!pN |sN 5Sp? C\ :Y ^  Dypw.J#H c #d` o3'^/+K1p8$<=>O{;HEx?q9Tg.3N*n !j߸X:chy3gկӀj"ָ>*(xkcjf_ZC 87?4gO+|t0  v  T,j '9x @+>(B_iI&Ւ^ C)5i8D:-#)c269@NA< 0Z=F3 k&U $D M 5p_>^Ӕ~3оi%6:FB1<QB< C 9!1U _lP ] C< .   T G|@8-#</bf k!8C2  RO3!t%o'r>1p2y07K+X9^4S/ / @- +2 '=" q {)S8k #O l}lfJ6BD9MiS75mR&fH ]]50 2W~Y/7&d`h#9l&'2GVjm%US{"  ]G .Y1?7j8.7B^)A? i< ;d7#4FW0-(g%C"5!* O.. , N A S ^ s _ .c }QSwF1v7 0K1B|i"ySJ & es(Q6b8H_}* WD* 4!,^/O+o4qS!})GuPFAJVh_u{]i  67Kd `U^gjbIeg!#v _$ %"##M%C o VmwzA+  L - 36l / ij9GBBRDB_G6qd9^MwiCXZL x<C41  hbMC4w?Y _ /M h- {dZc/ce^ . < p+HY^."T!oq$!!Ge Wu 0 5  /Km#ejGYjND+K\IBY: +fq@;_e?^:  X ,&5 jsYYdx7x<r)  h*8Df N /[>9 |#K6"c"  H&%V#(C@ NU;\ Ux[R(-H' v&0MWGG;)O&k;; |q5\-wO &P <  S ^ 0C {mhS'G_51ߤtߚs݉er  c 5[<w3j  `Mhqg_$p   X 0 uYo-g~F!? T`. ( * rR - @sL _  b u ] ;}JrXANDH% K '3iT^OB^%FR`k[1yGt, g 3LpE1 D'  = S F I ,  k@%~x\+6i*,>6p5xH>eTN+"?GTKqRNJpt}/`8D>[y*"-'fp"9VdP߮ EږqڂJO!8] ZVcsL9XG' {k " hN M/K\JP{ u q?'I^x@ :YF < Wg qB " }  /U a    :  `,  . i6 hg   r" K } R Y &e  _9 s `'dS|"]}q!>vV?WHg!]r8^{p J6ZRXE,  W i }3  N    Y m@>B![5Dy{ w D ` k LA W . / _ S S;u`+D) { tqFLHSGFcJ{7*! 3H`?K:yB.3x RK3P#N \ @ K ';v8m,o^  R/=!~!N,3 q% &k6s~ZZL<C86Qo; : B; k @  rt c/o\(' ' X 5 <4p|+{)+*> ]yrT7C!C 5q)){QB{%H^FW/ukm %w\Q[G7$}V&'/ $}-uxS7(Kv a Uc Bi U   jo RgXPoL`_C12OUk Kp@]Rwdsb7 G5 :G   K . & $ u Dgcu"tV#",L5xT p . - r " . / ''" b&1Qe?BW^oR#9FL# U \E1YB3 <)' |7  j NZ<dho@+`hCCR6CCL?+qFi 'K *f| 0  M W [ N Dq-jkS sFsLS|@G<* tkW~AfS*_ A yh  '6z~V"Ch~W;D < jD)P`74 44ZDM   X C :msxLoMJAy`F[}jsb#.C i.Proe-TkVvNu7Y40)u P } GDP| B 7w T|Yv?dR % S6  ! t2*jSFr/3{N/.:}O>]RxhN4((}(O t N  LG r   L? Cx j  X W W C Cw:P# /<YH!7 BfN; 0 l ]u L,!fH ?! #  /lH["^tHuol2 v } / _  # 0\\LY6*}[AhߤAMkZ>4HB@Zt6 yQ`.>wK"p[b<Jy]>mZZ13:4igBig&S {2 7 [{]H%8)rXG| x ZUZ3FP? H  j@  _.}TTHyx3 _# BD 8 }) K $c@M.hxvGrV8iC&\ Y t65L$^3|mr-2> 4 t x Q WR  >^@4uL:GhEv(eto{@eS3p4}"C3 @  7P\<c    Fg\5,x-  9i  q   7' C[ h "t D*c ' * t q[X iE25M9>o>f3Yu  W j :<q'!pEg;O0%1 EYluui;[-Sd) 0 \G@;   8M|g=  <PpH,FU Px , ivfR/3'M4to!_ L, ]?8Tqe?qT^0~3Lu  dHB,uvL1޹ڳ%ږc@aqvt4@x<(s&>AwCxT2  T f3V[   - q [  9 C ~ y1.<%  c*>E, 3 Ld4| w{RK/K( K $ h EPp[!Qp  J u?(foPnyw1g1 N~WA^6J19 qNj,o ~ A L5  , U -  | h  8 j $  / &` }Y 7 ^ @ Q=f3kj4 * ?*x3  L!h J4q u JT , &9H suv QDeZo{,O6in{^Zs,+]Qt4+b=-ro j .> av  rw /  hp 6P  " |m+|eWE+qy(f5K0 kQ^) 7FfRC+ `^[7"O/ 9 P['6+R-j6j -9IAjqݺ>ޥ_n(Qo`qfH a4  F Cy  + R  `# /7  e;P^*^0,  R  ! t")}jK z;  , -hT]*)>56is W &;ww  ]%[!*g<5bE06~2eBPc_6oDX'8&  ic`| qu&xOkxT6 m w#n36Yl {Q] (ƅL۩yh\)% (F/< 5# $ ) * U* +c ''&8x#O]hePsK c*5[ in5:-C7a 5$k!*rz@())3tb/s]9a^y]u`?Z9enc 'x `& %Qi P96F"  !^ @l#},OB zQ6E  ~p6  s G)r2|5k+rC'^sN  64m>fjٍףR,ݓecԓb)t[\ -Y_6? GYpJJ]s8ۋ:+3ףFS%xX<"%~,'r.V'^-,b+,&-+P3(3G#/*O'"T , /3 }y<4  M hi US $    f{ _o|R&:ewC1XA bWwloCfy91P1rcLsϢCѳ)׆ʀ#sBa*fp 1^ {4[ /k 9wgX1 gH|p+h drv< $&%V%#$0!7' $a!C)@s ԰ɲ!ɼvU#[sml 7߇ _پ c  y s-:Wq%,kwlj&Av7Bx  h ,N+-*d { S 6  ~ :mv _QpV!.`9p4"B5Kz=)?w> 6 T { !Pi   @#)/0- @88| 3 +/|*ek$.r~bB݉.i"&L 8(  B Qc)xQ]'y?MR4 tԝ}qF[[ Ոs-*$*+!ЄeP*Ӟi ]rCS _Gp$,3 8i~ACDD!A >vB M9 "./(6u BYD۩t'ݝ ("C!&& 5863 F51- i' +N  A@jDDCWgk5D\DkGFHn!Z\56<<2n<[a%!-{f6xoD8tԓӧk֑_=s*7̈TJeo 2XM(7+2 )f$&F"/$ ?)>x,1 .j / 552\143d/+w'S$3!  t* G* <(0uT["P0uz[" B 4s~i)F a*~ ?"1F7AL= +z'iͤE-˝@̒U/ЗϿb ވ5Iz3 U&]!$%&U:$!0C- 2wCh 459p& R!&U7t ;K@JKG@"?#9$&5#1g&!'(q%9 #$'{ G o# 'r!!!=\##!nkq7ޥ t: ';߸v7gld6M8ZL MK#(@M5kDncoSaXہ|O,4ٍہضLoՈZuoKA  J%C'r&BQ#/*&*+ *GK+2(%%M]#"2 ( `# I7( `kd5e  "  - | ^: ,Ւ6='rg* 4 _Ho  N7,{G89| V je[41 e ^7 MG T h R   H %  9 2Z zg"V(sf| st|*)H@;   | EyG (SQ_ aHk W] ~|& { & n~@ !=% >$a8"P)!%J: : LS (e_hxY_$2 D "OBT ! r|c!Lm?iC'W |XC<8lA"ߤW_ivRdD\ kF""\#p~.NAZ J4X+,1x)]#V,)&#   /  A U [f D -H %$$#$&##!] f [ 4o|1i PՈ-̒,'XeȴWkºƏo52l-OіӀ7AeFRu!N71 JGZ'h4'J%C ,B'\!=Az CYf?F j/e7 F kO I"<(S)=?W;@9:JEQ AK>v~:,4w &.l#;l) d_ IA߇l1 \f Z_ J#ض$bbHPPqW#~%wn +Wy a { uFQ? Tn:!9kbKhd! ZRZfF w!g>Y:b"NZKPt@FV4dm\@ P.] & -} Sw"Pj!*o}L=08f;,KD F41iCk`okřSBpCw i@V)\-M*FG k@}&HA,91#t; @9Sg8o /ѽoіҁ;/ԝr4XJ T W'#,2\579 = u;4 8 2 3 &,v '@ ' _ y! yYYSm"# #vO#Y)'%j $b!xh9\@ ^ @5y') '^ H  B W ={u    iH1 k ,5B# ] .a  C 4֚׏8U!?!߮i -BxYFnη2IQa_K ޵F(FɕDG<6Sv kv! $& s+,E*_)*D'"w##1^ +$ a# >^Xo u !S2 u `} H ;a,)Q]CM { eL({uyپ00[^f51>fcfCK1D|X[vW C Am AO !J"~&$$k) !+<J-d/ 2>50, g/ -;(! }w\ 3/M>{l#lE$~%/r"'D$&pO[\DSE{I LV[Cy3n~ }Fc M9yf |ć®)ګ-0q@9xMʨoԦ9 'S`"4N~c)Ih.8  ~F L  9 L  5Cr G % &**,O3*3[Q3n4-W)4207('h" 7f q 3v '  Q  i Qs oH(Ww*@8>{3\( eZ) %\aZo¦SÈΆACV-̒N"1VMxU'A`(q*+*=*4*,K$#Y !C]p*x ivw -D d _5 iRNI`$ uGSVHe  fs~M`@c au+/7ZF^LA8upgQZE|w7dL::{  Mu b 14w 2 %9 =2 5$ s R ` D%'+8Zgҟ.ݦb6rk 6'*$^$N >{"wt%M+c܀%%O&_j%$%/_!tH K 8] b x  M  !fTUg.Q U U M 9.)m^Z?%nWpJfo | F]Jru]PS'~udr ! ~P}2 h/F\ tuzVR_bwKg#J+/-DoBJ"#'K&#v-D,,v:*' %V,&\X=Z p A<*oki;sٵSdȴT?VU Es) Qs }g?WFG  . k#; S$ L#l'^& $! f6SGAm6- ~} } B NwG<i>sxi f=z&8+(g( 0 1 D-** +P&` ;J {8Xޛ!ܻs_ٗHP7ޥ&[ c   # !ed N Qzȃy ǹY#۵z 2Ѝ3u݉? |l351 ':, 9 '3mB7AK=92>9/.r+Z)#f8 , }& 9 p3Sv%VQ@; " 0!G / qN(P%%  7i & F&eC1yxx, $ K FH!cSwGy|߮ҕto ʔCYxd ";E D y ,&  ) KZ  ))[oW     [ 9%g|lnv`t g | S U L #"CT j'3$ +!Z,cX{?<@xu3,AԺ4ώaǾŭi+hG JkU-˰c>P՛ޛw>D;Rd#TYqm< - A  6x~} ub"2!#g)++ ()57+*4]#( \v4# '+ g % ecmݓipXz[^R5kX}5$o1 f d 0 G, 7t< f W_"o6GnK  s  \  h9Fye *Mk"F'r(85X4+50q#L: ވt܊E܀$%ؘ&La9Ǘη0 i+  ?+.80 6S85K9+ܔ41P8՛sf9eMѽ o(ҟ*֤6!aZ݉7qs|?Ny{ CE 1$-5LLzGX"^!x[PK3KCo[d Sxu&60 @% TDfDe?SUOROwSKA[73*  DQ`WuV} ӱ ѳ M +2t6' !!=SH7 ~<e 6`q5_fd e'duZgn٫Z?*]k*݉K  1eh?l^b͑6ApGυZ%i@}4 B]N]B# t5vyl+w"2*&$2:S6 86 /1S")>*Q O U3j `"F'-  "\Q) +)\*#,$N0#/-&-)y%~,Z'T 3C , 9 7^ s%D 'N)mZ `R+fU~=W$MZ)!߇߸to׭o]Of'\˺5J0Azqfg}jR^j/)) :B4UE 1 *= L?^ #!q(g($)(i%9"P %/! H6 CY  B 'xܧ ӧώ xʔ E 'e /s mE$g e 3 r } VY#Y'3q; "2#( \X&%!"<+}  - g p ;=}@,U /0l  NFW*Fv3m& B%dGf;1 [ $ h ky 8 W~}u)@c108 h E k*/9K<QE s y9չNև7_tX u\! 5PIH<,v\.`.,vf+f)*%VOO5 ۟tg]6:Ϭ M8F_jmz YGuL _ K f[ ~P:o-)&|G4  h {=E]6 ! "mF#"!Q!! .C,'- *O*e(T&"(M 5$,*,*1/.%X*e"  N 5`ەX77Ȍ4sifɋέEjlݝKl]t rg5]|&M g'! %Zf7?1-~3~>4bZ^Q Su /$>3[-<3<%4e!e(  0e [ L | 9 OH\ ] 7 J B  & p((6~ gqk 45uF-GtR Wp[ A3Q2w\3H(BgLf*upDA j!o&h^sΣQĚʻ 'ΐ Ӕ ' Dm9Z .:P!""w"w +h!*K#O/ * Q a &  K gOT @  #%  W"'hw) +.%l/ .*ew/v,("#t Q r81LC pU *;7WT%Xv& & .O eu CZ & E 0~o1E(6gr,= .MuCjB\ :eqs5,t'+ &, >/%,&Y2 / (6*%j!#;k7<b -e E(5_V6`RxyO'T m:=z yw+w1 J*?m>;%iOX+D}! h_qe ')y  3 Lv  /Y7( r?{!\aۋk  #,.R,? gO+2  T _" 9 ( SzjY g m B 3"H-!}$#Ys'$D<9՛%aaӔsӊM?7L߸ ~+!w y@!*Q8 I:+.Y{Q[  `\80Pߚ>ۼ_6 `q W @ ( qG >H~"!_h f/iZ o b>.+XO# # *;Vcw^RN f  < ^[b &  num {e?[iph1r+!'JX&!SM?0 S<sR?pi?k6+Q'V@, ԉ[Y|]6< NQ b  7 k k +R]y ,]Z"v)+ 2 @20eٗ`?ϬDVm7FZ Q   j   - T r C/L.(nasޒy} _}M T Tk-W  D Ah \T}J Y +O  ' , fBo+~3DC*Mkrwk  Ks t ^^ I 7 B B 3(  U `   m ^  9 Kx M jA yB&X  S YuZEJ 8 & L ~O P) TD\ hAs mܱZN4{ZjrN6 T_ |pQ(sX} `  Licecd r@hV " R 6@. re.P ^ND(3'T#-*j# Y wT _:\gp H-*&pM١ڪfѽAυPYώOtP%=gG-̥ޒK(2qޒqWe_AES@Z] )YB;!5 g[xEfz!g%$ g(y-u,/i.-g(6r.%%xpf98u4N({˰)A=? [ ]\;@Hbo8 lpDKtVO0;ztRcH_ ad 2Ear&(?'-#*%V)" RuycD ~d 3 rE% ^  K# a  H J C 7k 0-KtOu   BOg\i[{uo sY )e|P]!4ZLtsK-ZHD %$0?X6X-|w\~gx q Ib S ߇ | ݓ/]thYB A4B]~7 J#{ p9<6P1}O3 _+6@*V|.es[,l7~S*  rTr[} Ie o ^` K+ T +   F -PGlNNw1!(9!R  :!}ZF#B6u-nk9OZ  QGFqi{55xj N ujP &d r 0M 2 \ D0yBc 4!e"" !ei%/"P#IT"  v|lvx 8 p . : ;c X # & Y  ^t ܊ aCY{ܱI j-=(?`;~K C*Mc3|~)GxKOaWݰAoJH@ tc(| Cljt r.3Bgk=f>- p` 7X RF "Y  L - y H 8m  {r /x x [mPqzR|oT .v0\ } uY"XouZ|-u2 2qJZ!= aLAS C}f`< tpoM|MR,F0 !! JAebb   Ax SQ*)uf^ui%9e  :eDS;(FP<#3nf S n }I++޹v 'g|Q&,4\nPN,:C) OOkRb&Z2 ?NbDK"{)] M p    8 s - _   o  rZ K -  & g /y H  + _ h T X; kPEQfjWFN,o DD~ Q+=rEX{WL]|e@cd|)*p7Hd?KH `G B4 K SO U ` '.r6J{@jZ&F:M``t)BDf B ,}*M$X!!V##;""D!e_rd  A CA*WLl ] } ',: vyNl-,,~q ?Nxd6dwqSf? g CiG>*e)H<+^@vXD&NeK,G O ,=uTgy\Q)+z-//8J r Go/"hJARN~}t4(ZZ.W([ &T mEIAS A"#;%9^%$%~$:"=Wk)f?F0h5 @tY  L S+2?! 5/ S U ~ SxO+L{!( D  ,C\P%>%aj]Zo H A ~2L>,ZNF[[  A   @? L M  X{ 0r sL j W T j -p@w Fe/EJ*2 # B *d71{ 94eMXuNpl . - T`di0LSH,0 a a[ of( r  7  B . j  N iXwB~p3!ZJB/th8'K/,i#s?TrK,{\.T.4L]`4GnlKk /]   ( 9  L B 3 Z  @f_  y;:CW>e* c 3q "[j !!Bh^K{+){yR]L.e&59kO)S? ? 8 6z< v F.f v  %# 0 ! ^oe?Qoy  6  }  L^  M3 ;  v   <   _ pp _YwbRjt/g8N[EG[p ^ r E6.lnQK?}/j+1 b;buo9Pf YC,.M / U_ $fF&D9~bDkF'CK/*b)%Hz\} ] T . G@O$itaWtbO $G*)P  c*.mj^KZf / L ' c Y9{.+wj*W+6& k '&N06yHqQ`<~wuF  S}  C ^lL)+ N AV T _J6]" Q[ [ - WQ|[i[LGdQH/p_["qf e9e@5c,Y- m?Bg VVH:LTy??tt"RxJ )Q 5 rtAdJe"Z, ' 0T 9g + P +jAp@ e X . `T <Z< ^^xo4 !uX*@!f 97 # S~Zv ]GPR= S'  BP *B %  s k b /b rk_X:*[ #$9Vj0._,wjT~!D KQxAy {G @ ~c C '7 ' dC?Ji:4d;[mQG4}8AiZ?{$QM34  8 }; L2 a@<\$eQ?^W!&vV/!?T CFpOe  j @B @   -  9 c5)o"j/'w xtyHHVRdpb K9@w : / [ 6H F n {3. M 0H 6 A C{TL[p6\cL4r7.Bn%#QGqOi|C)0,$&Dy*4 q "qL,zG!P v(ZJ)!4 pgH~ 0P ? ? "  " $ /   J  o H4- g A JB`^_!?f689Yt2^~^u )b|h1:1Nets%(gw  u s u )\.   !m#$#1#1"N#v rJ  .'J-}8 8 h _W){h@66n{.N@=/&%E#aq8,:ru{QX?pETu..3^JS"+g{4d'9kRBw}r r M p* 5 !4!n"c##1H!n *PRM  S   'hY^<^hc N7vTO  |W3{R[56u!v5ZP /mIBe?MX=- 4 [*(s7"<D!^GH _  W^ B .   # 7 |_  (Hkf N4 @) ^ Tx  j*?  - 8 XEZNQ 4#(Rߑ߮i@uq?Ob),3=WTBR>rQJ<mxG^-L|%82]1ku_Kp( k/   q  I 7S    _+   r U @u " .?   7VmJ0`;~v'u8_"o~wLsA+< dN o C< F K o > \$ p+ 75 J ]  & Tv^'8.`KcN((_g $ a'}\x3^P2Qy.?5R3PCjV9\)eyc9 D } 4 -  $ dG %O++*Jl6,@xZ& ## [  q  6  [ 'acL  wf   8   G 9< [  _ R&@'jB`{-9@.q_T| Rxj ~[L8TBA-8@t _$- oP"2 HKY   F t1w*fjFpt? 3}mL{>Fm0/( >$'"w  }hK -]o(K%~$-- C'-#/!Xix3$ dXk fY XP~{B-{ dIT:r.qSDpW7 ^@8H4PD2@@_MWc!|'x sYt/)!*e("!4'N$a  R LN $ bdG (l3 i!!"#(--N&2,# CgL r? Se{i, n+i(c֮o؎pt_5:+DOBFco!Z6Zj!_5+lnQ#8FQ2Ss? e k AolA C }G_5eyB' Tk#'J(z&.G-'-(,$& $& + 5ElX U,4B|^\I{l^p+n=J+tq x 6DBBf $$ U2 7 } } ;j+\]1rk,Z{5Y~dse49],Qg /  "f!OX)>&GO@~P-T 6!" * H L  -w8%G/ Qؘ^@D|CWЗb]d!{Hx)$T&Fd, |lW8T,X7 N _m]C]b}*@(!< ` K B 9C 5[4u=١_fd!  "|  , U |"~ S fG  $ "eɕ8`y7&"w6|A7=;5,WSgJ1J$7D@9Ai%M"'J67 >o#Lpa VP +T9Ehis5*i 6qd>WtW1BJ\ X5@lBǫkQ \$(m(:/i~/$-0&)"$!(+ ~'#(habZGZ :Mc6lQi\$8QJD#rp `Q{#!W qEQ"o%:V}?;S >,.*=,#sO4<)(!{ |NT }ӔC2J(2f.R|hN B-x?:>: @2x; 5b *"w S7//6?ܻe@|^IOF 1qfNo{ KS A K8W׆cܻr3ߑ -ӔnY_t/F#,/Y1n'bؘ!k_ v%f (D*r6-e3L7$Ni"&i+c,0.7.5b4J2L/J(A.-K'G"wCv?p6v7 :,6+*+R.~(""&$,$DNx  r}WX(4tA?[YQ"rZٍ|pgᢲVUWA3KTB8?")#b *[f&KC ,/+5~wqW y Ȗ x X ҩ3-' 09 K Y ,5Y/#T/|7L@M[ ]dB%ir)sDpgzrpgYb R uFc :9^ A-0 rp2l PR9  l5 o=e,-&&.8'{MSFYpآ b$yHіEn>:“ LU8>1\)]_pAi* .q 'I8DzC,X 6'X' 'H I>ʀ[# _#!  #(E  #+pg $&E#q"4c( 9 8  H I    .P   -3qq96ވȪ:>ͮڪwn<جXXk-gmWy /  .dW h7 Pj .pF P_=wݝuָGؘA>יrz8JW.C-.,Y+(&B$^E5 A ;Ph"c# R$%t!'&"/s.d,b *e&%/#`K3!rj{GG_)0K U 2т -ѽ @Σ+̈ ^е y + ,׏  L aFo|J ^{$&E* i3d042$20.V-:(8Frd E`5'o֮ہ TL6ݓC<=vKW(H%v #Z4 u\guW} tz~"),g& (] sb~r"o#Y|#1#E&&s%"#!!Pgp1 M6h,٫b\4)p !|'f&Km![' #r9 k0! 59{۩-ҋ;ʱWKٵ`yù0vLc>W~_B) r q '.) f <  ry:h!X!*4i#" qJ60-3*'An883S)H%/!   3 4 "Y8#^w  G'v,xJHJWj 1hP&*;+L3Q 40R6h/8(:.Qo Le{SYo_{WfMpYkY. 7 W2|2 k/_.7 C7 1zGaCzZ9M*1g'K %k** 0ڽwcY 9 8ߑ ߸ ݦ0L3:m x u m?x~ Q4!q[ #[hki-\0CiL <k 4D|Be.k݉iضڠߑgf5A>rڂeٗwؘu \:F`q Hj$N?$3G 3/ 7 2\ h,%   Gv ! ] M 'f1#;E#l,$-"Q K%"FB)D ,lz7yZot &:y 0 3 1eARC@ I:?;oy9^l7/i5O6%l$a)%Ca1Wo q=LtlgZXt{w+FrpO]Q U:#.o^wmj݉u Ѫ ](YuޛP)cw= ^ 0!G  3sM  v<) ԝ 5ǍQҕ7d!Lz~MMRzg ] ?Xf~+$uC& #)/B( ''%9T(@DYMX 1'?> ,еv9.t.2@Fxߤ+S (   `W$s 5o7tN7@gq#FOJ1D^g]X8! ~ <H4   /   5YMr LS^ ,$dZij sP 1    M(SFKڌ ""2'r0*;y,B4]6a6`16S4jm1aF.~U(N"ZC];R5Z ? ^ } `w1[ߤ bR&#֑uώVυu^&LEg߸ߤar {kx 'Oт'zX4ř~ !haRKCI<5vxf$v Uo t }  ` q #&i ?*%+&5c{rE;ufDJ,M؎Ӏs F#ӧ]"*+xx e* %Vf6"A%MLBYn_ds5X . LX#F /k D6 <qTddh3 s - t E*2]!4&%V(6%M4%-:%/(I0#'##v# ].ǿy a=GɻʱON|!cQ;{Cޥ#ڌ^3Z>T^TH F4+N ܔwoJ j_ U.*L w+)Nu\DYmm@c,33 { t z n D+u ie^$:,;o>8ZQ&A:7", KYt+3 S ۲1_ uF, ; <2 I:6-WV7! k  Bs9/tLNmX<kn.JjLO>k;ywo2'/-Hqy8sNͮ9̒԰8ڌ B A~q N  8ZO #)G,;3Q6N6u A uE N>KC@4=Y6k(2o -k (qjcdJDBA,` @,^x%]H1o  BXg8W 5о!!$!#q"J#O"9#Q"! Ff ?U .(+ -  :!B:#4`_lc9kE'Q֮݉B$׷w0&e)@+ҁI f1 c5Ud踰нq@o"RN`Mrb"|$8%K'^+c \%/"c)y 0A 61g1R+"5S.#" t^-Z\ r&+)%*xCEEq=Z ,(-A9f. "cva ut T&.SR i<] &810)FA83nS93 &| T>%L!Zc)@Iݓ߸8|HN(p祾է;魠Cf!쳙*%]-?NS(x h;!F,Y C Txk/i ,1  #j  T \jr` x; g4#>! SEtK X/ g֮sX!e|%t ' ^&0%/B(Z*& _! m u6jչo@t(4oߚ0$gBM^".\^k^ [jQ".,1d-FwGl?alW NQC?2 ~9 '2HG/Tu  rX L+Ri>5a5 f![D$$%V8 +@g![IS : {' X  _ '([ B .7& +2 ;y }: 0C6>2d$D(k{sq'Lp ~IV8t7势 :tHCƏÜiɟ԰h!C7S #MP g=.HtW:/R!oQ/, ,@,Ji>>L=84Vij+ o q+'{|+G;wI 8"2"w R&.'#r#O?!!nP7 MyP$ C$u<C"m o 9!*(#9 W%ep E7+5֮b^cڪ7 ~IPV t(& 5  KQ8 N( @#;&*Z+~8|z< ?&>1+A*E0?2y?N2@/25@t/B:.j4/.-'h,$N%/!"  x V +h0qyorzh-0ӻ],f"Ug  ֑I ;?\Owi 8w` Lj.n o-QN>&a^   i}| 9\4e?h$jS1|T i$$$ g%V@((&!")3;bEF 'jgAG~es܀Ѡf̒a1v{祷Up'/;y*,۟9 2DM* ۋA١YoTsپZmIv S!`g  jw g*g@FQ  ^ j X SJN0+q@ D # -9H~ O'P-` 0cM0]-:R8\3xV*)H+)@%M70J PU)4#t ~JHPr.4  5} ~ $\y-۲ܧ";_G'&[ޯQ HFG"?Gn   6 >[l  & #E ] )R8e  ^[H6 Wҩ k &6 $ 3Bd[)tk3^ "|J0h-$ R*UC :N6u`Lkޒܱd6vكh'(L.BJi # t e q',u D f t `(!n")H&.$(#Oj w u  qu/ QmA.&.|% S0r2+  G-3 Ku9' n! - K \ `e"Erd _JpDTG9/q_"FСD?&ҁ]u#00\J&Lآca,ߑ6 8 2b6q   =\+$#*Q0r#;o" <:!CpB;R91IM(S^! h5  BFOe = j D p/ F}I2MYG  9+"yq@PwAM=5)p. WhvF?ե5)[u_6t9="Az Ϣآߑ>wKC, S_C$$0/A>7?DFJKJRNJF<F:7B4'%v**] U!$)+-: ,lP;93G ;447. '7!GE @ui8",$! e! f`R L!NgEH(ɲfE<bTATmV-5j^[KDu!ajݓܞ0jӀPg~ Q2 7 70HkGBhi8B=7j2o%9 S!* h weR< U  X i  :TgL}$Kvpף ԓڂ j ޯ 63   7Zb,l-TbB^ !4:5AxD,~Kݝޛ+*D [*S^}\,u W!VDM #%$Ng&((n+,E(K+*% >   A h  e    ]s  h)\ %  T 1H&O # g 5 LPZ3 &>&NT63ָwh :\ {p /H   h t` OR`2n4f,Mڂ&3K,'/ w QgQ;%`B5?w uHu_7Dk( , VtN>-S"x3"xF _R0r & {  !e # $ @$ L% X$W"m+! _SdsD O^u;V_BJ+@N[NQumJp{`X.=ssV[f6|߇^7 iJVKNR_.T6]4``fZ _? . ^oAX 8if ^ puN/cLyoS s  I {upViCDm\6 u =df2|X5 J h o T  iW Nx#?-#us ,:. 5W96^W/cy].^}CChar[yr.R1   rR :Ywl'+ qC = 8 0d  0]5 .BSh[qGs <L M   6   K( q .! 7 N r ! 8  i  r ^ ^ | ]y @ "S q _ K ) (^Nwb-dodoyW1FF o D M  j  9j#L$ } 8k  X . M  9 sL@4Al; : W u 5vcO&g?V+|tlOm  W :Sb{&;D) 1- k0/iC+q{]fR5quld: u& {~:g" +"#1!x#;'! J`A"r[ !\i):~(q5 e _ " "[>W.-\m4mn D H   $ab * sj "xiRt{1u-~,"-Lh7e34xT_7\ q j @.$+  }] |_ $  ) x X < i/v-eF9D8 tHFDh< y!! "m !      KwW6 { qE0XlDbXA}7+oD:ikF,3"f{|@J/_ ^K`& J kE D _ W~_+[5 BS 7 q6 BSr $F([c CG2WT  GgH"p}W: i{~un(*z,"p BL*rLgQ?H* k&sp4:k^LhM Zx k  {  @ 9 " Uo a!.M#97rt{d Pck<W{T^^Gx ; C j   K+ " C &Z k  Sg @s  24\\|0wYPFYJ:xTwW/s7g6p].9<\*8sYAEM~g( ] rmB | S Q 9Q  qgE D  3r3{]gwqvM t  D 9 W  ~ .W Jx 0   ^ #_ t {3 s; G @8|]xRSf%)9LV{TwkO8#!f'GtP9^ ]5mP-.'\gC/{`{-`J})Jx?<S6pBbFj/ )3CqG"F!2{rh4%>MeLe '.G.]`X)yCuuuw!D#]*. ^?sf  \ aq(\ ~h 34*,"NOb~e4(P26 M wcQMv}l7 C $ 6 1R K $   wB>TwEFg*tTfQZ :ZCH~hBj'4o"+[ 4.}") kZ64?*)"8,*\{O (  8} T5Gdau.Yx[ ~ ( K) r - 5 HdG W -+ :(9%c!F  +RLY{ b t ` q CB X&2&Bov:>o3opq-ts My8 1kQ/l} 'J |  4v98jt%bp X bHXMoXY@fGH)f&4F'tk j p7wT-ph /8 w}38 wc;Rf hh iG_>Bi |2'?$} kN ^NMF({R\ ^ DLuw3:{pc4M-3bAQ   {)(E u 'd  <}w}4A[1dZc / XiGQNi+  WBsV:d&XD qHoe+Yps pd |.-+8g,c  }7 K%  X h ) ? j 6HZ,;{pEP3 Y  /- S 8  s |Gh ~ +\ 7 t XP[AyHxR < *]rH m(N'N%.hrO|k,<`M.<dZT+  &   ?H\ { ]   [!Q H 4_J/F4PpguZ[{f']&S~\5yS]J_B!+NCdxZ*J8t f;<xBk'?,qK{y M  8S  9 r t 'X'|SYt59[u {' r 9 ^ li }& N8& 6 3wSW_k>vJ:kXCN?PtX 7;*S-fjD(` x  r   h5fPdek  ~5 Yd{   nQ\"DX*:,rE7#-Q\O4 S?! g #" _  <(.G|_) ^< ! ~n (bprLS![-")5 s K 4 7 + <d%8M^]$D $5 CTN}8!n""m"![h!-X7y74rs}7B X -bDF~u3,W mPsL+uQ,p   @X  Em*|CX0 EQS YY&IL[ D  o(Q-_QMyD\9 t/ q  ^ #   u^[v(  8S-RvDVZ! o5 hu!  oN[xOe"/*+3d4v$2FlkDfW~,MY9w3IK!F:Pn4/{%$D:]$5$0$+%$$$k"m J`0j7E= 0s<}c#sX ݉'ևM)uggX *.\$}ߑ7UQ7߸7zfP2os9i3&9hQl( s!e axOxFRYtٗ۩ 0 ^_1Sq$n)>X,1S59@;>=P>16?u4>4F;4.<<9=P6810/s33,0,/$&$0!z "]/Dq"]=5$#Eo!Qwar# ! f*L|$!0*؎.^8|ʱǗjJ] bN7Ǿ _Oיۼ \ i1 Nk [ AQ ,N1?dL><ܞUauߤT j: &!,Y#0#7V&:%<# +=;Rk6ke51S+& "c Nv  N jpR 9= & `  i x Ex hX:\ Q V<~767!F5ni%پCѪ\  ͸ZAY3[ָMڌ7 `6ވ߮V:Eڳ°UpGۼn/Jڠyǝ}㽪$蚵żRVЄ  %~'X(S((I #(z )~)&_'$),&'&)>*++P0*,;=c.:243=@%5=778-=*>O&>#19 A?<8{: L5O .j+$8 g o^5C:ڌڌSF43;vU 1ӀiMk8Ft5@Bވ&} 5Xw]JC9PϿYoȖ{g6p|N"z}԰=ߚ,Y(ieL"  > M""Z yV#1* (*l/B 4 u5X53p=K9h4,02. )"- W A*   #u$X$N@L$G#!=|f-v- MxY@(L A, q y'$iC({Gڪ4ϿS:n)H廵֯wh=䁫ݬʶصn/͇ҩu,\2*y( 33!:"s B {n!IK D  G$%(+.51.6C6:Z:8s%6e0 /s)o"Z7n Zw X v_5$ rF0 t2\,0&nQ JqeN' 'T$'*&1$4m" 16;f=mQ=F;2 @.+ $Eh  _u YF܀tʻr#%S&+wώ,؎,\*=,*'r3"!x9")=% #l!4%jKCKww"  &B:&s&8 >{$! x$00l,jZpѠUɁZAz,ȃɁ̥uHB,[ %_rGNSt[e8_R\"w$D%+c+ '")!( #h , /q eHoK^@pR #&)F&,y)*_KH%Ewvuh(o '#yi O.T+%ږy2g"Dޛ-aAᅴ^eo[كZE k! !'"F)>&)&("')'('&&8"I"   TCjv B*  ^P  I hr | "pL+T7py~ bv@ VY K;ebWVqKP%},5> 3 U ~ G Su|dե >]7/ϼ臾pF}IȠ^X9׭] :'SNd S_/. L  ?#'h,/d/U?> 7d./61I *4uj=7Bu *HhiG.M / `  5?W\iwL3,bbVh\e F h }Z } _+ wZQr B&m˓Σ͚PY'A|{C<  ' ^ q;R  <iFP5 1? t  43hZ]& qxnwR Rddp' L 0 R gQ  IP  w-M_,5H 0 r[ +5PF v _cPuyCctHԺVϘdm ̥>/ * ^   q _6&u(S(I")% fkIDe #<|O-~p@oJ > UZd RqRd 8*  ~#T(,vi-uT)5)6*G/i*x#.~,;/B%9.-0*>'J/#eh\ 62yܧڂJje { d :!Q IPi ~F|-Y_-\t4كF6XӞvт BG-S>-۩еԉܔ{fuZF~I9 \JU%I**OF,N.KJ,OL3H0D-?0"c9'A4!-a3$ }p$]`WdVjoQܻczޛ"4k)%W⡿4S" ="/ǾiRG7]v3eFZ 0\5Hc} 0 @EVW f #N" R6&(#*2y2 3Q2 N4=31p.)!+1)H6&7% JL;F9q:KD 60x&K> 5mr/r?q4N^VЄW9"ù=JE1Cid@tRܔd 0יӊcXͤ;2͚s؎=4d\ۼ܀\ ) K~@f*Bf'^WeQ\fpC$"#&s.j.,!* /$k.)o- ,,.*Q/)+'-2%9/ +< +"&#]fl #   |* `- ݓ 6V 8ҲpT ֮ե %=e<2Aޛ5ݦk ;1'fKdʱANFۼcY ;1 # ,3dk8BEQA|;HuDr=5;6+m ݺ {,L: N)mR u V !;#N!O~ kt " ] ( & q=Xm I*3 W?c( ׆ Ҳ u uT;/ʔC-Wԓ7ѪWn4Ya' : - y#b$(|*nA(]0*p)_%B( 5ly ,;[9vD2Ӕ#7߇(&*G(g4 j5OO/13 . (x"mj N4;Ks$_.AC:~4 qvQqF&N6-.2ָ؎t=^ Ww$#1,'#=PAK?U6WN F99{- Ss>c\VEžLIcΐ*YЍDҩ)3_q8 , 3 Us i7 e C R+__M[Kv>B9Is#Y i"$" # S$N=31S)!/|!+! & ! I g K8p .~s: @/cKK  |*@#!e ov"$!x@ Xv;g :pXv"&E `q!X(HC ?`$;&F y C$ E3SW) &iz  X- DR5w ؿD,1`p_, - HX#P&l# 0 -=(#(fB v"'ߚvܞOA Mҕe ҕ -_xݰ (riR* `  W;  HrTdmB pt~{ySN#Xje`GGf2 5!E [eN ]. 1 t(`Fyx*gO5Lv^p+TP P w$a%~!"m%$!=,u**l$a% S" S .3 hDw  s IR^ NL@GV wDܱcp \/*fw ` 0S,+l0r2fK.p3x1/&C 4F+9psX\$>B$;ߚT =w@X 2 ?u6,@/u:4DP7} F/>H~h _A 9mMJ"$%&}'7'8&#!f" "DQ+sp y_Pbb M } _QPlxsD%# 6+0 s )؎!0]9ݺbqLX@H!R$ B1MkC:!k$W$u+c*G'W _ R8NLUh ?9v> !Vs+cAzi[G : {)7gx!BK R$ ',(M$01.`8++'7!8F`y}7Id/o #\͸ć<å  ]!]3z)<v jd2i 969d8L/CS-<[<3= /("P.3$Ev#Sη]{>S+v< @ B <=P TBM\vGYv TrD!* \] '**G',&}7C$9!8. 52"m:g8i 2 .)&9"nus̥<ř < 0͇ #ZmK$ != Da<|% y @Hf;Xro@2 K*^OFq  جף]KhՒ/ָ 5֮9\_԰|԰Q3e|ZE#Ob#Y| f.Cۼ,E'!(# @xV  C udZ֮%}ӻ H2 С"d%tx%(,)!,l-:.123v5 66:5O45b"24$a4"31z!*0rq0,*j';&8 "7N0fu ay.ՈADǾȪȽCկ:?2Kk%o(ҁYZ˺Yg[ip&.Ɂ** 2о3dչ/d)A0-z(! q 7pv  *  L(! ӀqС86oc>WF?3J s]$$!#1P354c>0=~:I:]864m<0J'h$W$ .I 2 S O !s*'!|Nc+e h B gS" M -siv1 $& [-WTva( Mf|:%n9w@F/e2ߤZp| @d _  U- > $k #&_ ++q)5K# )$i [~DW:]6 ,<w , Pٵ = `nJZq8uR ?NC4&8+ .4C: = NA B-F.GF3[+<3=.,'(I Y-5{>ٗQج4+)5 O>aR.GOeKW{;gbe>@qݰ>>7,e _wݰ$*G4*%M;B92 < 7t?5- '#v!A" [h[B0 , { d e i} r AtQMu%$:W!q$" e~,q B$N9$8*Y*$: h4g(ڠ߮lrڪ^I?MnWݝ ʻG8b&b;m7 'YF ](q'h"P #O >)Xf   FJE-Y8Syj-V)"*&U)o-W0A2 0J8.'9T9{;;p<*S=9 894<32f1g /U.V( %/$1  A3T3 P-#b߮ߑyR%oh1 O Kؿ*axZҋiϬώ]A ]%'9yC$:'L* -k .d0r5,+F6()]D- XuzoܞcyҲ$Q!$j().0-10/H./ 8+(6^$!*rV|Bj+< q. .yRg1w62O{Nd?*5ܞߑ<߇ݰ߮ ޯ6 54* -Y/S-1+U'%C$fFi&+5 qw9 R  0Pc@5Ek`CthE9dbT4@ %_ G7[  I N  g a2 U W;wX>mf߇V,7/h"[ e-34:UX[VXhjche[(YS_K;yq/$%CcaxN:o|[ɋ̜_Cӧ &f uw(rr  w kAo#T//߇0S Z6/k9uR r l$ wP!%)$:\ڌPs̯qԝ(/l$k, @ 7J N Gy^p]hUTKD7 + !f'>AWx2d:=QE8y w_x]V"n_ Bb Pp#D*<!8gt-OZZ )8 ,DD;_ 342D2NĤ뾱(M"r&K{?eq&f] NR%09l@` N qQNdX[V   SK  B h  g h ^ 6 `s i7  { t &( W C  B - s %[R    eg[[8_h wRqivڽ׷L7P s ZT$gСڌ5QbS^}<9"<)0;;@9 B &?W I gE X 5 j/_ #..rK 48Cy <_ :g%f%t$NZ aI N 3 h @Q9|{r[Wr(l  CXuUI5:J,K?Cm$FϿʀmf\@G :'Yb#(h(K:<<9; 99 6D /1 , '#$:w[XgU^ I  78 @ FHe߸|R M j9ߤ(RܻD 0܀ W   'O 2QtypxebJj$jcI"QNX$TMZc?^ 8  1 #YZ B  ikB |n_~>dxd**tU( <t=,W6bu-W.e1~ xP)k ^#ڽK9Kw۾29}qˉN<[Rk+A% <I #1 #$ $a^# !-#*-V0d AG j.CF|9dl k } W! u l q q 3.@|"g50Q* .FvG:!yكԺ 5@}&(.f\Ƙ H'Krڠ~QO *p |/ !4D"<!e[ S  .  N'*g!<^RiJ-t qd  iZ (#!$.9.O } 7  ! xu`"w#g!=#xrf ]" N O+֤.O=?n⾿ᬾz1ݝú:wޥeʾ0i-dέNjMN l i 9R rti[}alWeu~<h#3F{ >? "m!"  !e$D %/ 5&B&'%`"<zK] ,# "cRq&N<  </4*)63N?C9^5XpB35,3@ 3 T  {     wcd q k  eN;aELq! r0~3-tdo WfjR][*\[;Z'A >YM ' Q A r i ݓ o آvٵڽڪmBz\9KWQ>o\f@ Y6:e|Bq0g:_ ~ h  }5 j ~ ~\  G@+?x8aG4 V~]_e]>TH;   :( ]HYWI?Z ![y$$D"$#lC$D 3j 3  'Wr | Dwx 0jf$7.-BR}{>e44=o Y?p۩1߇Oߚ r)y\1Lq4T@},O ?y.[- a k!  p  B  " q  I= A  ks 0 d.    SQ1U") o# # .# $&#+#"7%LsK  ]eE9  X13CrJP9W;S|5P?4L8WvKWuXOM'9R_?*T_"F?_>j) j # ^Mu@,!= 9" &.Z&.%~,'7()i' &"(g#*$($0%#$#'"$![l;? s>hA_3l#rh-%?iD]= {s%sn'N' z%_g0 YzpM{aqݺVCq\}  dxzg6)= = G zRSeFZ.)g6;gu,*iUz#Mv`)Q A _ 7u<M> I s , D5 V4CߑߚdݝqELu:r4f$ RR+DI"-P2*XfRgfRoCZ9qp. >P  $ }6 " >#w%c& ')H ) A( q' %C"26f $ " `" ! f" &!Q  # ~ jN Wv / Xc    k)_uAOP4J>oj~,BArUhM u nRf}\'hJ] +HR*   M^ 5  X   h o t u W ;  iD rV S'P%UH | U dZe  q  9 X4>3g   UC s d :ZphK!R߮Xy6L.v4~XBY=+9p5?*ODAL"SO?D 8 gv"W,yTN!*"<#("h!""  I uV ~ ~3  #;\      k t G+N3.= +  X, AN fuez!$WjVtO!%EC[)xe6t}9Wrqm5!ڠ7Mvߑ3ڠFڪe.[ڌ[gk7p1ov Jrfo;VVl,^*' G_36"*4)4w5b[ X + , D A jfXeu3u 4m'Lw  j ~ {!5@g]  M/m}G#! |  Tg`..X1W)H A8-6\S9-c DAd o~=<C_\)x{3>  @+P X+f \H2 2? X \  "  7s 8 W  Nd!*3#&&Bx''T%tp#G"dA'  7 ~>cx[p7S@@>3bWMx1rC`o#i2'c|+R.qg,[)jV&*@W5}Zjhu+: ^ j  , "y     69   kM     h g W  <  h s TM i T Ar  hH  "\=Z"7 `   ;  Z>9hB{:$3 3T!B_ "}TSq!AhF/;Zi!GJfv4Yd_-V^mp~nL   ^}@SRRc  W Be { k q/  h  U| { up  *  M }] ]o++4   E kv8  ~@%Pu.6|vP}dl G %suO b  @ 7 9 $ 7SMSGBk\A?RxtLPt  B y-Pm g2 U a   TS8.a( ?Q .muTkG]G4?>jUvNSl)N/bJ hv F q&VC,@R'W9s-7G*j8Fh7{}?<3_j;j 9 9 ]  V i @] 6   TR   ~ t6 -x]xd W   "& MH> * ]  2   X8deR}D&@dNDC !M]/~g*c)T/`jhs,v q;&?A N)1JTK}pWyK]yADQ L 7; ',Ye!'a;  r  ^  "P @ v ]> ( Sk1ui9-ZJG1FY9)1\d=eS4|?wz A ߸%!~f'pje 8Mf)bF-J o 8}AdP" !ED0y]"c$k#8 >8#($N#GU  U h~~iCswfNDdG 6G,L5pq+**j.P7J *;q35,.xSRCIZ3X{ A:Go:N`Fdf5rGh4N  N 6B V "" R#$$:(!2!e4!6a 3=9@%3%/k&.![+R? oq hL 6Sl 6kk EnSa74""LrߚHHN dP)  {WV5>l3bws4R -\45 Nj ;QSQ!*!!"$!G%~"&U"P!* *n&91( %O1 ,߮ ڂ6Z8t׭*Iy2Jޛ6$F..W !?|jdBBZu\P}cqpݦہ wڽ /mC&Hs - ! jp `5\;3;_ 4uWF1**GkH4s>TuB 7 h?| . Z 8@Y +""P$:%j,$D#!n~9A  { 'fZ .3#\ $ !j!|  +"u# . GvX AJ7Rg +*r{7Xfw{PݓtpZDD?s]: r[~!}ry:"#"1! Jo?[ N u,b5{7N'Z/ Y' A,  Tps3[g (+)+F,3l5433dL2>Z/K(S0%!e3'No T c',gi8q8C-]5vqKA EEbD.K  "6.x@%xL '@LMX>.O/MjmQ!QBcA`Uk!S+w35R K&)9F!e> R $ #O ?eM S thFAfA3@^Fj* + JwvlM]GĮP“°NiG6Ѷo. “Z ۟I[k} # 9 &..B 4#  HojEC3N_ K .7C2!$#$&'$"Q"wQ + $;*_*G-,.#,+51-) ,i*K&"a]64\bj$v,[о h ` ˰ η r RR9E#߸9.ޒڌ]جwOt?W)2" - X! #v(F*+''r['G#;5r_ Sxm) H? k&Bf@,?-\"i B 7 a.4Hw)=[.5[p7?ys te` k 1K~yf#$&) r&KA&$&_~j+{ :  NE%/s#7t 7-R߇D',Ҽ[{ 'Ϙ }f W+ q' ׷ N ^LB*vs[Pm~bR{4WK߸ݰ/ܞ^Pn BxQI$ 'TC)&U,)f]%` #~_! k-166/;- :z979J:g8K(:g3=49A>J12i4 53-$%/,Y'{"%t# ' $a+pt WB5Hht9) @PR+}  &  ~[ ^Fh k 5' 0 ݰ \nR$ɼ_]ɟf8ԓi_V~". 83'r*x+F'6 492.//-w-%t &} {* Z4< %jX(,l1/1j-5X1*( t # A(?W7)_:|EsřfǗ} ~; ЫP = gdc|Q8J \v4| 9OMQ4=jpEF)<ee i"#1 + t& !Q\G!N-^z!#' }$, ! P"Zi# "!*i_9f fQ r !d1>ѳ{З**zӔ~h܀Q\{[(4" a& * .M .0T+1\4m + )y)%h Y u VCqָ[<ҟu+OFXMJ k T gi|$$3@yPG[ M gw+)*x|")&i"WVp o  T I p I=e= {B }  M"TވiR ^@TQ^d6?>mOH!(S++P'A1-* "1sG!" A q 43PoR < T) ] :b Dm # e<g yWd2e_Hf u ,  i?!B%~%9 ! 0#-0i$k'h# 9L] wuQ=A Ykh syxktjv -W u)X&8V)f+)X-W ./Y.H+n)(g!Q5Rv)-4Q"Òef_5ܰ;S ' _3 H 4DCe #93E3/#H+**eMpqKq `? ! tY? R S BXP۲Сԓt*۟ Zr"p-1^6uM6gBA;/(3Y*/%Mz@P :Ar! L% ut( u6 f xt} WR* ~'( U C-BT@*m+c)0^ 1 2!v1.).t.'{ +$a 8d wZ}Q{) sɼٳU*fvp٫v 7YnH  1 F  9)V6 Dт͚ ͤ̒0Qsΐ%Ͽ&Kҟ"r(R(0$u/T ->  I/;<V { ~  kQ6 Z :y !!bAq %/R+F-!Q%M(69*Q&)','^*,.V,(*= >'-'r#{dbSu:. ̒X(S׏p֤3߸:s +w42*`;y 91*=[!6*h6uWp߸ 9\ܔ Iq qV g5>A'W`ccH\- U .C.)yN,l(S#^"m(  ,PpA"Yj' :ۋsUs+SK '4 ^5+Zq(!n( M _1sr(#vq[ U8,#\&U '%9>(x'T$$ R9 DKd ώ ܻ8OfwHdh4ec>d[*>Jo_s(rf  Cd +c-)!407)] ?Nxr9%<-Rx&":urJGu } X4H!4x4  f N    q 6    `  L; "EZBz!>FLŷ <ĤGCa/ٍ9hL,/+^OWEi y yki{ f?D  vS"sL-lV>\hk ]9c L>De  ?P L| }"$!o2 3+ 2/_*4f!G ), p y MRK^6R&q_RPh=Nqi t @  w<^ $ yik 6oG S uf&TZ) (Z _eg!KەyӔ |5`Ffpwʨ!ݺaB  3. - 5' |9?IoLN) LTRMRHFC;o2+ !   T $s . D ܞyL7J]ؿ>Y:&Qo R"&ߚ*4|,-54w/'r.e&=: 9GCoix<P-.W3v15K֮9? J t;եvo!e! ') +*[P+m+-uy--L*)>'A#Yl?-y $ B (~E; $  . +S   6 T M"YZqp_g/"4"P]P"! {_޹ވQi  jPK Q uc1[]OTm~ . SJP fA8  9%i_#yvXoT+ jk1fJ/ m&4;@ FmJ_6arf#apz o k }aObXYRVF(r=w5'*{8gjBQ, r %krM:%zxR--޹۩DS7Rߤ3wضԦ3ԝ֤thC 4#R_ _ 9B?[V)"G l U N  9 m l |` ' uz e   " SbbBJ %9%"(&" $-ge6:  !! E'% gN>B|j1}-η6=KuS!ԉۋH3T [5)4b'~#`, 54| '1z)3.~6@p:]/_j' Do:& 9| u׏R5.TJ)(G#l*'{""cJbo2W.9x("+ %B#(L%iM1!k;oy Z w`Lm h  R~R +F K>fN&^{(Wk's_ٵA \'T'#3=<;i2 ;Hj8. j f  j L) E An Ui ܔ 64n[5cP3 u  *R&dEu ZCe#( f  %/! m 0>dNd<%u 7 3 e 4) y? JxJ36&|)5#|(I 5(/DsssN%ʞ8ʨTѳo/23u4D<<mAp+ Tg7G%Dd|H4; & י 4 ~ t u(Z_|  T %'7"Fv1>-&# @6MD/3+,er[af _vHx<o\&}#"-Z, @ ap5R l X]G:Kw@R$43vtfsG(d6s N X N vi*Q(&Km#!G!rL.NhJ@1)khqݰEވb-7 P4?x s@qf".2+v0-)yr,+%$a u B ]  " Z ^}o2:`F*/u}eP''dBm Cy5-   : K  Y aMq9jv,rrM`j yKf-e XdA(rRAhCSA]r>HixlSq8 f%F })AN 788B<  "2- +%'F>,\ L MVSzz * uG>N@ D i]+7*nP vs%9$![# D!*  %g W   .p YآmO <`>V6hT=X.V12 *=tDj@`681"4$n L4bSHڪǡƅCfȃr!2R ] 0YO=:p4uRXƢZ4 ⾗ 85 ( #s ~ {z<7>\=HH=J.HILF h?D81g-$kB1:?M9h ݰ 5 `կyQ۲ 0Q Su^= L< W7,*e 5;;" i ]E $ L7C%| $|r4w _?G*%*@G 38p"p\0L:1O#rC(hH)#[ /@G,RwW +w. % :!*f$-Z120/<*&855:P5O /. t- )#PF PGH e KHQq>oև.׏m~w^' 3;  :9L*p,R ( "x"Z8Q}-zBߑepf}d A1v+~u, WG  dW K x]<?2pQ  ,+ Wh  z&}% A J !F 'D @p<c'd( N W #{F sK]ydrtiF i   t ~  &2,۟ەݰtV)8E$,KHk~ r ^ BK=3  fsGQbdFbCd _ ('{(z50'.t( ( $W G j '@63Zج?UbLԓΆۼB 4T/ T ',-K&%Q=g&VJUgsij-p!c 5Rq$WyP+t?. 6 7u S`  N86Rz*cT^ uYl ! 02>1S+Fj65l!3dt/8P-k./M- q>5 }>uKCPh֮,˝B"å|Ǘ:϶-ͮ9XH{s : I8Y   $: A ^ | Y ZZgrb D8M > (w yX:I"(  @Oy_ fmdPG*~Cp kRWs! J #1 /!G U 96OI@ua4hӱuіBwk̜̥-8jo3yS")A/X*?pyG A `   h ,h m> L  PH  w!#&K /,;k*G./-W"!n,O    $  l) hS - :B:\|_  ,  PM `!}DQ { X  r)%9 2{AP0S)GݓE~qp!p!8y!g6f57kW F_TQN+{[ m ] (4s+ O e0vZd"l #Oc#2%e&#$h)o(I'i)) +P)>)%V('(  , tj|8؎sP_Q ;W5X&]/zI 75_BstJIPCQbFj2\WTu/N!`m<K^6y ? u 30"C$D.#`"!i$}.Ed ZA K Y_e=^7V9L+%kM'u~GA*6 |W#k"&i#MN.j~)#,-@B3& b:Z N - 8 9[ f XxpCd|XWo]Y+Q   "p)^* T  6 q) xhy  _LW <`RRg4 ^[fd Z,T(3~s/N '6k!_}^=-B&t4"-.B"p hOdl.Q.h/uT ac7t Xda[\5\9h9|G'x 2 u  sx  #  d |  d ke'4@     N@4[ ^Ap(b/e F$W"<~-,O(Ih%&"@r7})>}b<@/f"\ w#2[J SRo47_<}Ah8Zkd--  & j Uy  @  T q 2  d  .GE 6   )  ` _ a!  .O X!5 4f S  ]` Xl!:g#j TuWX*C1>!)b:T8u\y"kSFh^s<&8 ^ q # T h< 8Adq ofYykv`Tm~&( y -  ]x.b_> Ii K: &2>}xRo<$rM"ZXko*ekw T|['t'{ TAh_' \k7}Vj7~@#@{Wv7x:G/_ j p X / L ' ]  ^  3 w|]jjtr|4(B ' H I/  ] X  U cOKDh 7_qK3S?RJ, LKhT76\?~SyR7JoQdE/[!TA<g2 ,  Ny D3</N?hb%[1jP 6f {Axvx  q! 1Z 3Pno^P3x5i* ]vDui{+m#r`^Z"h8GpqpyKo5oi44w^'mZG#+~ ~ T ,SqECN(  $ . [+<xuf? sJ;r'Z.5]5S!"rbZ[RW_=xL  k X M De)\|&9o <],PoXPW'x @q?"s<^g&&?Gq TeN<NQMCo  s[V T7ZV`M:b@pD) E 9n U> } F  [?A[_pA2_ u D jA W    ( w S4 u {|iWx:[xSF" +wWwh  c  h  df ,  N jyD@JS gR4?p)-+g>Gc";'X?o3t1&V8]|ArvK2h7[m.`y5d's|_2  ]x;Q5N8wpGzgk p A Kh{Nde]<.jmj3f /2/NHoN+:"T`Z c?w+<RD>wEhx>EQ ~ &k9Mgxqge<4 Y e  W _ \ T?  # /c / X  Uv [ 3 Et   hKfv0 {} dWt tOZ}cFx] q  @(ZBo~fu}l #|v)R C -4  3  /v ue    :  X D3 U%J8  NA6tMVDp5pn1!]E-4^M)K% *f"_X?{߸+L& }8ޛ'ޥC@B0V!k+l c ^H(4!v5kN<Y j |}\7q g |  gvpe K BJ 6lc u B6 ]Ax[5 Mm |5\FE  K JTcpig'E}OLX48lU*2 iF x * !bS&>ne -Q"g"*Q)MS }Np>,->Go   H|eh%hrrAg"hMN R { } j DiYp<d i [: {Xp  XJ/Fen")_X{']Z[-t  oO  O\V3kP3Xi=HI* w 0 k kGvD? w7%,..6o    4fGB a B i 7C p  I K  MtH*hr D BF ]+yxq vn $vQ.;3LLY*/ ~OK_7B#$euN_o ; U  : Wr+6L \d # ] EjA* 6 D  @\ L9PlVd4  =gox54p 7 NP - ]T:'{crf72VbP;ceOo2wO;(e)Wfy"iE t^ @UQ$%!Q n 9L6KNrC3C T qG 8 "y dH :>UP-&h/epNZc K ] g8v#?HG?5G<s96 g _S"j-Ct{,dETwPs f<_< XFVHg79+Pox p* I A TxRSA\&r:E |Sph!s]vyZt$*f /x %@  O  &  h |'fyH\! " G  ']m?Gq~u7!|hG-JQeW . u8w kR5  ! Xe,!f{[74d!j5p>PAu\>d41v_k@?A,C;3wP 0R.URE~bV<CQ` 'F @ n  > ~ i  Y 3*oAXw,?wgJL"d("G /4 _ T%/ "+2 .9 3 64 3 1 r0 - #*[ % "m ij   a5O yE\sh^1{6. ,i!GoDt;~6  JTh]@\/ihH j {   bPy}&91?i-R4 qsNLVhN_CpG VhyH W $hxb N & "c[#Y"P"w$&"#X :X 5x%te ] I | 6 b \  N"f/dP5ވݰڠBd'5!پJ9-!WjsVNTq!5*lNl#M9/!eEClj/V6FP  ?  GcC[!<#F""")5 : ]a $E 5?|iWR{s! d } -p\|v  rw   EP3rf7!GH6t]|De2lE hX9Gx,qNc4;jEtO6<HP4 p X ^ *wX>X v@m-$ yKY~ H \r Q_4:7k ]p 4<AVCl## R   9 )`+` I  ^:  ~^/i9)_s#XC&2:km=1}] !Re, ~ K,2?AbN>cLY@KRm]w*NZ}S3y ~* q M 9P  1 ~ ZePpx , mNe4Re9 H  D{ 9p|T+?@4"!Qb?C9}*eHqSN^"8G@3r0PJ%PeDNW$kYe X}&KgHS   q S  Y{\@.6~   YZ Z[P'9_B  M-   < K UJ X^Z %PEYq$^X#!Fuf `qp{rNb4Cޥߑ'd9bNJvV A  wD &t r}j~9/nm* 1d3  ~?   8 A  D6~y]f#&v |  C AC}N6h?+NV~H\Z>;_%]G8co _*H 9 ]q xg C d4Gw$Ly E  y! \_')` @Dx3kXK\#RyF{ G 04 eYVm [Af"s&_oNun4^{RQ#e7|AJAc 5 q A 5    $  ^ -  /@ c  6 @s9r 9 @P#A,6N|hP _ ^P\- IK  &o  ZyR`@-&tW t@tM|_Xgux9qGW0^leDm`i"5QV3D9f`ADC Qg6MthJcw u ` / D TRP   T  ] " ( J,7wE 4*d Q ; ![,W.J9Z8 ([&Ae}b>c OyG XNjBG  6      +b  } S t@PZ SrR1C+GG\\{b4"(uox v~'~Z& 7QYlunNfV>DkWk'+dDG >*) F x<o ]JC-(C9'uwbib}DB%v  ! Z m @ ] tPp4{ N[ZZ,< S`['Z& K\c I [U RUT$VUm\h8  65yk&B3 DA o /;W4gfBkNaS}%fWF) } Uk ~O*DtQvnuT_o"%&_%/Oҟ'еHP)ӻ ևYt>tL8wwZ WB  . wr+PL w U ,#e x < S  Co2Ef]CP\ RJ # ~_[ M  2 @Nq. 6FTN 4Tr@"eSO` p(\JR,v  : r ]kgTL y:~>9 }r '  A 6\(4 d D u     "   r w l *#fmlwr@\y7:$q3k[~ B5\ !G  "<#v,")^-! " Q[<(t0BZؘM7pV>N|z /> :  :Ywk"D>8]k#Mn! [(u& 84/   d `>eP#~d '8g  : Z]}$TBS>S) igPSO~8! q!!e~d`c ^g/CI h.7ue{GJQ(:LGSxbqyi#K  k ! o[%Xs1 G  ~ c]PhuP4pke"JJH  b ::  "]^S9 '^W7Gd 3 x A-:\Rd,v3*-c)G t|\k/8?A;6 JyV0s"N_L*b6-_O8!^A}?[ Nmo<L d+ix 9n we;S:D8BG  f B4(Yru'n2"|f!]R Au6u@B} K ^*~ S4 r  L/ R UT `  k X;SZ;#]`"/d _  B47 :iH Kh joo <1'ud:   Pr@C9J[!  y('v8*CD Ix Z U ~ F D!aFpW7{[`FSyL _ . !fCsN*Jjkqd^5hM*;|` Yhi z+;Wv.f X  2Z-#x s h ,~`9x 0 _ Yv&>kRZDt> U` M  h m  " 7 a]4KMNZg77g!|[P7<b 1[L,<`h;QZ N< L Sy\yoNH <t #4* )) ^  C5\>5_ dX,--e 0t *"f^-qm  O?d+?Po? Lx]!P٫4h7f؅+>yNyS7t WuHe81}Burd6u^Q ^ -L & oC8]MMuh[QZ>VgRZ^ ) M , F N-Lt}]wqR`;' B e vZyx@/S`:Q4!c s~ ~ j@/")_"PA#O!"mE&K(%G"Q# "ZqCPIF joV<4q Bd,+wG   Hp,tAFj{&~ VApk)95(  !  w  T .y S 8 NHt]Nq!^[4CQTr D k ; {"#;"2_h smlk_o&4% :>4Z::cV$0-!s!_T`h" , J U? H ?H" )dP%#6# $ rr eG N^Xp=H  I . IRe^o \ | a?9qDg&NHA * %> !x? 53`'9@ەہ,n41 8 ]9~`L9!ec[,lb!bs`- e; y C j   H G   RWekxa5X"y  |eMoL $pa"~@Rq,4iF ` 8< p ^ # #r Lt T_1<\ ' 2hdue#W;-PdkfL^[[&8 <]sv hvF 8 `*bR.TZQ j?5^ #3VMZo#hJ[e   ak#pw 0 W K a ,6  -  iQjܻw7չp7١|4PiD_j_\JHtv SUUt@A@B}6pCKo! 8#WCwm( _he ,t y gcod u_cc `  OQl19"pn ?P]wd  /-7 qsk [{-,V_rkh[y~ `D  - K #-.Z0G5 ] _|j f   Vpc:m48Rw@<)mfxj G#| 1G ' X t  M 9M NI,uJ$XlE39o4<mF   j j<  0  5 p} ]. #E /(j'}xqgAwVbVSQ \,pFb[_&v9v &CtbCwMj$-)0t"*Z 9J <5e?A4 D / "p]n5Mti%3p6 PFvQh<Sm{^ f;i "PMx!,`   _^y~] jFYl 9D /dYwV[*WP.q/5xNRCg uLRNb`,-* <tENyxM   # M D  }v  `H+ihLj! u6,13IrQ M IqoYL  } ljQ3@J6 " C]6v{P*%]l C  ~ Xmy >   { Q Bhm1TRkJX!px~&} L tbzg(-ZOs . TA ,H'xMP 0 TPF9j8}]!GR"%C'#&r%9V%~#'!4m( +%SoG!Sb`Mp_ہ* h^Du׆L<8M9qA  TK q- r^pdNC EyE#KT^8dP*'mvkP  P/ js6!G!"c#v<"7   \I0S R ;e)~EiS@7SB7_~#pGK/9K$FL*,TJpb`dQu*.d-l|<3@+`op3xE*cdX2FiFH; '  = ;E!c!%/F'& 7& `'Y'%M##(!,lp\\  BlV^>b;Rw`gJLq^VQl/5uZ15K#j%<|JjNo{AV7 HsG*PN8o#Q;(kGsv   / u '  `C E 2qm#w/ho) m  V P  S XS     #R9>40&y(sMuu!n,/H:_ _ 6? B 8 L #v  W Nl w|O N$x*9~ !N^W2d(jd^3d: ,vO$Oh5ONr?HS     / o :h ku k k2qj2+XD3}e D oE]MrPh5 -FmO\_A3 Y5 c 5 '& H' mbl{f'6 # u[FH@{u`!~eJg<)  s :  {$ ' j `dwww `*, ,ujTg" Rw?i @ v$ $f 4 ~'  8 8?e< y , j   U> G 8 C <  PeP>*PXMbh{KLK}K_R3DW`obP\T\]]^Lsx H,Z0h_* &yMH3jJ'Hm*5M[hV(   $   ' MR  ?5  + " S e  _f  #  wQ9>&Buuc)3PSoedd_ M: =[)^H5D ; :G :Rxw]H(/sh]fcNMD9-!pw &o 8  4QrwN_,_}7#]4SA3F\r).vx U )@A_mo6K^}o~O~E"d? ^ K}  AW ( `wm34 +|V ?km%9'}4We3 ua  rZ1 ( ( jm4L4|r  @   9 # A | r 5\)LPhi fK g  Bc^b?q6Au\ @JiKWY(gJEc:4uf^K{^]s>|7h0HQZ'W`]d:CW8A{yLSKK~Q Q _ AK+9d'wd  =H C\T  -    _ s W /! h  X 'FP(EP9et?N  ^  P%tr( - (OH>(Ndv]1< ;GvxC)$KRSSp5QQN6*y  ^ &$  X+_i0'X_eK; + S5lS|}}i j "  Nw y Lk3C4DdSLtA]ZGw{O N P %c7S*%Mݦ(ڌZnpQQ+yV ]9zt86Y* i+Z2~ W ~: qO ^1 L1 W W G /  $  K i W?cdFfTB|xT] +@ U( D   <]SA JWEj[N}+|G?@Ct5W/QJ~&9kf>*}e24pFW(pJYI  X<u.]-H.#L  _lhL@Pq#;&'7 ( *x -+ h) )5 '^ |%j #  y t ( M  S< ^&Q4\{^t4g]^r qf*P(]CT{z H5' `M78]RC L:&8vp RmT!3(E1:A X:W~eO N t  ) : T |n u[ 1$&s'(S* *40(%%`# !!4!=U!n*! ^ N)\"$ d .>!K~s%ocPPyb<yyts'2GDB2\-i,~#Dٵu   d .  ]<Qi r -bQX !^!*z!Z$a(`&$&^'r&%t}"j7Pt j\ r YE @s{V##L2>X\s2K)+UߚFr>ߚ,p&x"YKRDt7]r:~rC5m&\ 9AY8i!#%K&^) ((j)>('- % %"w GmMLlk5( .! D I C  O G[h\_wF,=AtRBq4P`0^b[gxx~)[nv&{AV(K'O v r qFR4bd)zOkp 9~ o`#$N&`''&/'%%"!G@m  q / K S  A NCeh#dS~w)73@+Zd3tIEKiy@Z4?NddWL_TSg_rcAK?[q ( 4 E ~ o  c Q\! X 6CAse.k|"A###"f$!!e5* ^ Z  6 u 9Z Q  P # 8B M)]^jtHs`Xl%2w `]K]> 0?"r_P*'*3+;T\Dhf3:fJwtN  -*k~8+kjbVI![e!w H 6<q0DG'; P<+  *O[C }e=gz-gtF *>Gp)CxjrrB ~@Z[]oޯ ەޛ_KL^Vgu 5eZ@S!""wr%/&$$$$c## " j" "   }H1 6   foSf X -  8[4U[ 2 )3K{7t82Zn*7sMtݓ8 ߸!sdKAKX*ZE:$! V^} 0$x87&V oH ! 5w = Ny ~x@BN1VoBzN8)f'5 _  |Ymx! "m%%t#^""P:MD : Dt12wߑ6.4Hto<3n{Qk70.^_+`t,NLDCA' W |+),8 0'%a{DD;l%w~ BV  !|aP<1x5 ID  ^  #   L<  0 D B Zw|&i9dM<~ޛ}8re dJ,WRq90co8~,>?5em-%  K 6?u"e<)l  X G Wq q ?F:n$33!#Y4$ =$k$ "2"2 o U  O aE0( ] / a cB;#s<8y3%E?U~g3ڪ(ڪ`nip 0 _Q.K'? 7 U 'G"#Kj-#m|\7Ah9r{o> f^9-;KIj`1XT{TdT0dD9s)tY34u!tfRJ;' k ` }R ! 8 { #    O  5g@<Py  }MVM\Bf\ "Z+  r&?|H_qR3 8 & db Q#qwUASޛ7eYEN#rXqd u\:6 4  nfPc(lf< ], # qH9?gJ` 5O; k 3g < +D    Q {  l N}HPgx"%'_?,)pR_#b0TsBXD 8Vkj9@?(o_rG  4o!{pSbkZ4 x [4gtHZYP sjkA '} z  != +_sy4 . h XvY 6 -92 N B B  S W; "TtPڌgi6L#܀ ) L;E |in^Y@N\[)m L<MDNme {ZE~HT 3 T \X '  ^  f 4  q k 8 7)5HWw15jH`CW~/!.B+$$pb9kKA`6e o y j  Xu H.*P#kh\->5=p9\Tc([&d  N  K -NOSwo*@R# ~ UX `   (N748M:V k IgYk  i -C B7<hN L p* rX:u OoD^nMqNZ1 Tm[?6q,sFV 7@"!D :[E)OPdtiA(3T C "; dK)yxH ,`   y :Q f , `8 } 8 i  -g . pF4?+ h9 ' /;dpcA) eM}tMci ~}2-t>5^w{cXXpk-L?9[DLT Z  )3   3VPXv MAAqQC8K,c? x?p.!W# # "$q"crS I^#g g 7 ^u k L8 M 5 4R  _5Q~wgL$A + TFT` XcMw r # X-($ޛ/ܻmzA]`,7ك& -V,S?WX\W2DW[J*% B4YDTO8Gp jeOT k B8,l   gh*! ##(#<#"  Kt  MEpao Ct{LWuc w5@ߚ#})L1?(Yl 9jji%ALt," 6K`bCDB1~r8?NW,! m j ~ r   L 6ow1m(dJQ 1,WM%#   lF6p3^ \?Zu v wQOkH0 "Z ] *i:iBnܔOe:dWە~.bAV;eV1_*x[u|{Cs8fFP8QV]u,4;     ^ O hB j  ~!* %(. 25'4>334).j8*G'^b"Pm<[* #KBM-Fq*ވڪg٫]6ٗܔP!Q^P>RnTC*So*  C  } i e w  `H ~A & 'M[>Z D 7 , kfM\WW$ I # #S A w &   s  8  S w <G h4 # / d+*h?!LyJ   W |L B$ M#+`# <,,ThwS u :DsV@P}!KwSw O s7 _ $ 0 T S vp4#I6i{`  kRKHh6& C8*L"$W$K%`{&}!%") cO1" -dYW4m,p@ !y ]Bsr9~ BS>`j(a#ܻض`@9vqrGn-i #^/|/ Bt~@1+Fe wH{SJgxo1Wi?P Q C p dHph9'Z> NG1x}JBTsTe udl X~ r - 6 S   iM,k1:3r4 Mq  T++  : NvH 5KTs<\0*ylFm'%ARe j ^gwdB.3 ~ j0+F~ 3OQ xkBo} y*$  7  U  a  G6u @%S )Y%&- d-1fj  X 8 B%Q}Mup | .Q?@9$SW\dw2E;!E(2hu9_h@G5>@oF|2 tk R,  ]k 0 / = XO (@[# ^^cm }  K? =  Q 6kOx  +Qq@V+KbHV;V '00ijCt:/eeF{ k )0)2]dpN wj(  I f< _ - +    < M u i   9   j%<5 B 7^[4}iZ "w_ <]r]qXK+: 2  ` i{Kiv'4W7+|0%,VsqeB5 3!e,HN6eP'c : ` E  u k & 7 4e ~br  lM"hq g  l  $ D + $] oHfT vF.odbxJ=:UlP,4Rf)ffg"?@G)x!|!\i|QN  k+E u B   A k"*h8$}3 d # K1^ M; j 6 !"Z""D!nw Hp spm+&Q^TM5ѳG?hMrЄ^%Lu5JTCD,o 7x: 9bu & ~ .0Sh ku /X Af_S  ppo^}vE "S5>;'qQ( W #C;B ' dQ 1j0Nj9htJPЗ XӀmVwQX_`r`~ _`N9q!td'&W8k q \dk ;  j B _ ;!jpB 9 sZ K M ?Q b  T &y  ;P.!*!!@ #AsQ7  V\4 +  " 3N/X޹7! QA-^'oqrcZ8?<[2 B\ 6 RRf 8 ] _ )mR8*{KHB Jeek1D W  <  ;D[fh`11G7o N9%A~TgQ@)8 21m?L/Dl9r\Gex< g, !\+GW u ~  t + /f Z7C3G?WM 8c:7}^Aw7V-  7!2 'v N  "  W &(B]? <(p3_!b$n"Y#Y!9 K 5gKw'4M8Loif&GibDY7; 03 j{4+cPXy:=XnR`,@   E ]z#&&&'7I$_ 5< T gOi^ߑ} > _rD  85*mQlC'B%w-Jqh50O& B 8AX!/AXd.Jt7NT_  XWM^'q 5H"   Q } ?RCh8) >v/Nc  A {  jrYhx|f, f .\Ma8T p'-D/K2b4M7`41"_07}+F_%8F jCbKNMx|D~18uj _A:j/  ?  l0N8o/yr$ qprjs_i9#NKPoGwV14 e W_Pys"q88'  4(Q75 #iZ5 s 0wR\Qk  2R HMQ*Ro6]H\ h 9 i <9Z] \(  d u~+yL |L^, ^ ~ s A_x|7SQ.\@>Hi~,! h\UQmg# LEE EG#vj[+f 8k  73 '(mQ4 a ;wgiWChT*L#R{ddNcb k ?SyP-[-"77>hy HTwRPU}Y[f p qyj F S$X"& '+Z,Ot*/(I'# 9*t 3< Cx sLo5\f8'*OvSfW.>gcd kY i4W E 8  R h  . q^qjO q!f۲ r bpʀguʊ`ЄXol c s I 65 #- .  O" (!-k0^0T1M13h/)'^g'~"Vn*U6 gfF oTd kd &  s 6lH1gsJm"Z8hQ`b>'Xy&({< S C.M%05;}yA/Oo  ~dZ(q   -x , .i lp%eSX#-A%  W ]Wkc&N*QRkI:G A  4.TA.ytJ]  + g5/64w7  $ H @ eJfLts|4: * NLxk)ti3mQGm3ZK`k f /y0Q! , K L Z  p R s .:~p"qnpsA X` ,s.S:3:?  U[  -  a S vbk"+WFXeYQ_gf$kpۋ Z/gd"fV xq G!n$-&B'(z&s$"ZRJi qVs[$BWPr$nٵ~~3ہ&\\{u` T  + -  `H1D49Qdch 9 / C) ( i # L   ~  $ i  ul 9 No;pqd@*KeS|6GxP  k  / C  D  A h A A1s=F|hl4"C>9yp _ t 6W\H  K S X Hw4$\dOFg*fw`| F ^=70 o  h XP*4 UxkT4t[:C<eZ): E|g p;(  g - j*ia~@ifZl Lv9TA4oqp7|28A&IX"n4WC! *RkJ :! q$: %&'J+('AX$a(!*Od7 <m  $h)Z +!R"f#J^p?\iJWN"3+HA?*Lkll +o }a m(Fn(C TT3rn7׭q׷wtۋ?/܊]I fFL~qY JX  . L {2 C "@OEi)7}?` t /`.!"_oHd/qj)>+ @ !!  [ Sp!}g8{` q@ T(S^89x|vc / L Rf 6 g | Lh }F-n$}sodEe  $ BK     \ p  L QoeBdrZ ^emG M5R,SJ\#rA]R CX [(O D < }) -   ` . jY' >Cs ޛ w A |    xF9y .o7 ,yk9-;;DF#y   U   t & N)*J?W o,-L{P[ kn Y , /T,G?5R & M~ Mt>t iTjTNKN.pZ;sQ  Xy Yc   .7NNs!NLIv1zjL*P ' L -5AM D  '@:""4#b$ $N s! L  2do ]?%}c@Os&;S YxF'}h )WW @olG}< FG&$'|&q&.'$uP!QY ' C = Z w[L4 _D"C `} _ 5 1 T) xPP q T*  ; HOs Y ;RXA._4 P4e !5>8  fK LToT @bNB$E_jO7-6~ }$ b Nm X: W  #@ 6( | 8 ) l   0".$b(,w**++-B.`t,+),;(W'7%/{$#Y%A7f of,z?P߮M܊ݝfߑIHڪ:[;ڂܻ@>kdQ sR 5s    p q  //du ,  S5` a !Pur<2j8Ji*v fa ] gU ! &. , 1I u2>15'55|31-D)+'7"#1j DOS)V[76i?6UߤB1t7۩4پEoܻc_rmhd_X_"\H&J/it,D?S-EO  & W   9 M d i T GMQ cG#t"c (, h- a3 6aH:}?W?@`{@t-@pL"'b39d,kYG[F3j,#e 4nve0_4>Ph  I_  { ]O 2])G?CfJJ6 ) ( @Rh?R  } s  a4;_2z!$a#c!) q86jM !VkZ8J(u;}8 Fp9ZT!}]^r%gA[}"wV&`~k!Zt`A"E ] 8     ]p    E  W kQ ;wFsx[Rm4[p q H N5 QRLsi,:7 7-bbND@&B4o8X:'ZQ uVlM ZAPE;;k/.Dfok'DLwG?1Bv&\q|-! c~MAN[Kb[ZYw X " \  x #o   ]e  QR= =po S ,   1 (E;dce\-  K  #6A^.q~0\eMCtA^Zh!QHq,S#jwm4}~&:@VN{6p&/gvT TG  W =vai\T C=  A < /4OY u    _ Z e R 6! T D _ aeFhf/% *VZ6/XAi0:h@q-~x o3n6J(:h&V+7il9PCKov   $ h pq}, DI    1X!5fX=p!R UYphu3ZCbz6W9$Y K<Lk+hXb(|V.h|ZqXiSy f Q9o%9&Z1[w~7 k  q =oaM7#O&g(*+++wU)W'&[% (_V0+ 9 ^~6X@e8r@5+ a|  N IF(?7 % B P lVrC*Gc ?h76sTe@r}OCtvNK W:*)'kTNy)( 0 T a Dw u f ~f C 9 q ? pj:04;e hb 9u&F<:dpd mPCy7   U M   B DHm   f?e:J\N{ |X 9 h6n/?U:$7?/  A Z q  )8id?Wj{&Hpo $/  rx FJLE3G5":;M!uL /  S;  hx U4 * .Q  SfEZP+( ;nGe[85I,,7BBW$E*! 7 _ 7   (}JPq3xskI/ ,Ru^F}p7g &0v]+ q  j o  \  W& H # v  [ f M,Y^d}`>$Y*\_'N ۩I pܻI^C<\3v}!Qq#f w t W, s s - k Mg7+Z 'EVRyCP-;f!k.~7kgp S -  )w*yt>]4C4^!$Z>ezte^Pl N t ~ t rS3*ypG6 Z-s-f8ub X !:W1w*sRAWof 8 W! u 9* v /=BOC ky -(   3?{#A.veDkRy%\ "MR2}DsKo2x(L[_3|LEl ;FuF'r~_H xYNd ) t #F2 I S # C@ ("ZA6)9-  * I\ Hw?K S8 C*Dx\G$+FFnF+76-F8ugxc5 /K 9s C Xyp v1 _ `x6`rR[Qco H'd>*R5eEk?J>W 0 @  J  8, L &  0l?*?3@|cAOr  By-!_]{q4ff?PfD_O~ ZERE]Z75rC vdCnDnr<^2sb;O1/tC:%u_k]uL8 g[y4 ?!p?C6Ali%JBT$kaPU[e yj mZH6,? P $ |N 1 DF4 ] h #g - X  x4{ L)Pm4QZ5J82DpMb\3 pp{J( : CZ ~0    6 tg W\  N ;YRe"y!{m\* jn " lHNrr V ~ .M~i<{v  K+*h]7x)o+d E -EFQz.ArqD$ xf bCbtLC~_y?dx1(  @6*56QDhyK /* {2 A A _ - / `c _     ]  {8 +~  r  `Gxy*!|@W|`7FA%13O+!5SLgpZ{s D{ B0 # '  qw ) * ]v8 ?4 MO;m)@%9bk:9q_gR : _P @ 8<@>vUP  /  { t c 2c3pmG?gF*DD J'g~hT Ni?#{r_8hVr`$k9```M8WF8KK+R< a) RoZN*Yx P  &f  L ' t[  7 k EcNo*%&` ;KS>S/d+9S1]Wh-_O^l\T ~D w[<{?;Z] < A WZ ~    7     B ~ eBL22NqBV C C.  ^  <J(7T >  UM XX@i~Z3mPjdPdm<(5l}vH:bNl&:`Cs][KR :  dXs-u}X8w:xO ] , Q_]iB.V?"uH3* p - / A - @ XD9: {-sMju95m5-?*x `d / .  -#i?,u wQfTRM jm.k!`{5'g~R+p]{|o.;Q|}MkDwLm\( D2 uO'dro\3^? u ^  # { - IK  i _t8JTjM.'+4   /  _ T _ ,  8*     a :jP:q  h N^f]oLDZK_st%9M%`7THj6bfAQ L*Mhe 0v C b : : " kk? ; EY.lx/lw  0}   , ^ ?F DlX@ X:dQF "b B@v{V@ qw b P!r;B &j 7l j1 9 'KMg,$w-^$vC'2 b"W`1 i~V )(9s.x8jh6b|-s}B-| SETtS! $ $DF!:  \!<6FN mN&$NkVZx 4A`'JqTO D ^ZSEYzcQB Sk  # Lb N 9 a)+C2~MTZ/(N<o . SJW"C"\#Y6##!![, @ k(O&Ks*jC3Cm?XWT&^]8 MF mxvHvZ  o:tJ+A-T]KT<'\e&A  m $1  | ,V ,# . kS-:[Kq5)sQ4eDVp;y\d:LH7r#j!FL k g9sQx@xumV76TpE`    ? T 0 ]OPx>y>d~  / :gqxg { @dt`wtsNn0v`Ekj&B"T4FP?#:xXh_@>pqB?D;71o+!7f:o:G 0 * i B8  ? X\ :\ `5   j ~ T 6ujrLa : # LY *`F !WL U7=hZhuT5 > T].:o$e+]eT"t`--Thr@@R?*f!L|,S"e-#;- u| 7J *ax:j.,L a 9  * Q3<*3?P      . ] N;;DPr>dq<@HpJuQR-jR+rRIn +V^qEd+\I} ?  #R aG NiXGo * *S@#9k D | /4AiTV3Jtmqo2P y  ga\o >HJ D  . C \KX%es!Mn1 ,][L4w3Ot %7Tch| {[F00%`:|/SfF-6HkVJF  x .  :#iv74 ,YM_< -i |R*?1 . ,; m84qv,(k_o c 3Ygl\w?  ~t NP}*F*R..]03Lk "$V}@J;hqf[m `C  + IG W L#^ , @ K  ` &G]o7y:_dE q~neq  !  ]h ! SLY  t[ h9Yp{sX(@\"Yw "Y+ |*9 3 N : N B> -C0.h=W+S (}{ PPL  5   I   q q ,9 ^ iO  ~ ~o `  a Wj s Wl)WUP-h!xO S*iL`.):Cx yL>PVE|D@sdS@2 7+9qpn`7X  jkL &8.W)p5"  F  ' t N  W 9w 9 `G   }   ( 7 D  d 1@9aEfc= .GL~#CR7d) !m=l] X9@t+ _GA^vp4!-iRk8y.i  s6E Z ",  _  ;O3!H&F>,~# / c /n|J4NWs#Bbh6Q nyo]# 6PWf 9jSqJw.E* ZS, xWT>DkV7x^  <a qo3 .&-q N  Sd{)IG%k_S  , |2 c Do@V7.sR2sZ{b+fA+,T}^4/F, a 2  3^ r " X  &-E_QRS9 9T#C>9@1N~_s # j  N'OXu { iai A*Cv+fS,gr@ 1s  Qf+SXOse}fD;*#b%&8e&&& } *TOQ ?T=  HM g w{8mb%dG " K r\e6 +mo1. G* ] s U  sQ s s5 wJLH8VXy<H}xdE O c D at Wr -g  WO355b8E3Qy."]5i)5_RqoX); k b 9 x # - r- Q h ~ 3 ^ 1 A  U  C M r  D  &clm|QD*mp>p@KK8_L8%iZ~ b#G{S7] #q664}N y}|[ [33q#}8 /7LSdZv u  ` B  .LNBsh#q6E% $  ] {e-mWOb' }{m j ugV_wEHGZ .5 I gS6R]9 ^^p NioA[ ە W M .Ѫ 8 $s MY<ɲ2 Bܱg`D}|M f yQ# #;! N Xt DOZ ^%F 1 ^w=j Zd>} +`#m 8lAClR.EYm@199Bj^q{y/'pMwAor+*}X.9@Gc / @ @ [ ~ X t   8  2 8 a 9 ~ s D  / T  ~? OQd(6  k7 ',fy R-s d[O]2SY1r3@bfc=w3eW_opR |Xk ? !*$'P/$v342813/B*=#X-:[KWt&[]LM0 b 3tBoo  S+P y iH @ 3  A  3  ^ s3 3Epp5u>\j@mw>Wl'O<[Lq 66 >W!7 alwh}  j!jWix>Ke Bq>` 1 i h j*L  L 9cOnSf%rN9,q5 h"q@,,{@JSJD?w)1 V K@,??6J  iNbLE3u2eO[@QV9VpD  @.4  /~G TQojd:C_MT0K$A&eNO 4 ]*_BF. `T7h4S59W 9'T`& 8 N : : hX ^ N2PbtuuPiPDGp:uNt . x ( )p-W<` v~E7# k # ? \6+S ^ 6K-T-}V~9j&CM|-Xg>433O(; :uA   I(^/n  %<G'k {E7IWsdw;JXWE3/X^&Y4 Bs x kRm[+U iA )OAp}5BN*2&L4^"]%ks:U6}!W,:Ol V$Bs\&I\2]ە5)y 8'sb߇$t-iV7wB }BK,`>"gr6@8^}}ht44F $P|!x'^-!14589{783dN/o+{%] 5 e&(0#_,|3Z2m#j:d45 rl`0_4$%$ވ.ih,"pqoo)1#W+Lv+ / # 4<MQI\"#OT$D$%j&%$8"i R7-7f*)  : 7 : C- M 0YG?F>Jh"B8K|sA|_^7%dGR+JTuYQ4[XfxL/09OBG7}wLTCu L[0-%J oo!PDMB 8s \j&d@l3Oq*d}{Z C}A$ p tb7DuGNNb:P _3T_\Y-DrpHtef)kAXNkRmmT.bjC7u&XZE ' C L ^ hP q5+\ <   ' r ~4   m  j ^ @^  06c5"7bH]6i}# | t}WWWt9 6h 63W\_|6fmw]+[@ ^  l|F3+۲ A mь3d5'@יF1 R9`[  8j gQ;M#M!"#Y#vF! lf%B[ #?B*^ ,6Ot6ALvJ , i']x^ B=zds ZM ]syTC8$o +~@ 7 S.Lsi{Iy>7ee _|s <$'#)-,+F(?'$ k\C / i o}^sVG|Tg]#^PT|APcF: F2AHC;?}T 8 Z]^ ^ oL2 N   f[E|Day NvvuVZeqy + |"P C!! myM=) Cl|~'YEUޛ޹ޒ>l{d7";T`4rRpWp#e7utsr>CQ" ~! 3c$ m  , 0 C  ( T R6p A T  ` QS} BA!9v ^  q# FpG?[S$j)H:xJ-5^Vg+fT"]r3. 7# %fAmy !?[]   6Y  { 08gC SDcYDoiv : 9i$c  Bx,Jw}*N.Ftb4l C# -A {^  K v|qEF:(guZ^ B~E ah 7}1N ~* Bn~]_QYޯtdb ;/x,H W( _ .   s  XU3TfgGLk 'm#^|A;r#SBV X WhA}k m{X?o]P1;((* r5ڂD q ri`v   V!O j GE 0N  / s h     grH4x  *f At  :|LE ~Rr$+;u)8^*j X B t _ L j" vv!A  U  L p L   feq%%Wwm mZ  J 6 JT#qsK w  ;FWq "@%9 *g q5*4j RSr}%&߸H?hBlV A, d|.pD e&Tj!4mv(" B~e3 *@@l|fx+ sovb 1 A QbkX<b! u N LX .w2ff-J_}&9u{s9c ~n%(#)bX9 &3 =\'WZ8p  $ $K[}-F8('wbGAGSQd:  , $ K &6  D2^>{9 ^+rTi.e*A@*S  N gs%$.& ' DQbbTtI[$ <0dPL}<( JMK^H&8XbW  y w  do /j   ]  k"R6!Wow>Xbt 6 ?tQw   iik9MS>Wy?kZ Xg / aO gh3.[``f%hK6K`DNw7*6{J6C{rehF A6[7c  } F  } $ .  2N,$~rC 1k/r,!p &$ 0 0!fG4hbyS>}d1t #nE:   I 6  T 8:Nmd9< }oQ> s gS9{ {5 9?o 4&.-O4 eo7CVJQqp@gh-t~YCY~s,5<eJ X #3 IZ ) 4'u&%U7KhS^q^BAPG@ a9PZ8G}5G<\@[oD?h5Y : L }W t Uj _x .3w:rKZ6!6 S~[6)fXGPYo~    9 . l`TjFb7 H!x"""A!- #Np 2|Z("|!|4p-:d:2E*!5vlxd/}|LplwK6d Ms _ T qH{J JSJq+]   rm  .   C M j W WS  OPG3o!6pmG l9 C. s K    h }  j& <[r}DP*}`~&f69&Q v/OPnl :us9B7@xO9V*_j kDWbC~.^7|{mf [ # >lX 4 ! M .} L B sA L| W XGb+KR% wP  & s 4o&Q3d4H  E uP@jpj7-[6^=@%V2 E_XZ/BgZt8Pk9.f|o3\Q  &2 E  8 s3 8    lBmB@3-F<K^MSq{535f ~ A? \    ]  A  W. : uRPeB5S ,sCbb!SRAA7.e7*3l.D^T+&]s  -|SSSf^7Y!P45    e)Pi3 <)S-K*o) ),7VM-VLjC)/y $ $ '  ,6CtC}{~f[Wmu 3+Xw3 R w[w) h9^9x(w( a } $ i .w L: :vEx%k7g5{A; u  if r w]1; M _   {Y I    D M<} 1[!5[pv!lh8uN<\ N U |  Hr  - w x\x,*)) )6a ANj< s y 8 EQPN0O41 P  j Ic U\ "]..H#`+ev[ kx "x5E[vwOr 6 ^+ ~?c{BuGq&ol\xqM.CXWYiU@&WABeXrS^  _8Zy 6Q E  Re[4s2} 9 5Pt r$   ,p@Zs l%OF5[^\} ,  9? 'pd # SC.?kM:;4XuH8!^]Hp i^6[p+5!y}toGo7 ~) c;77H 9{J j)  Y5-v"u,r`  $a  y "F   ~ C{gpG)Xt6s]oVF`2Ovv6)oPR~D3p&.Vicn)w*%v &' _& . q| @ ? [ ^    X!Q4\vq  ` .M  D "o ]f q, g` 7 \@or',m30O wY[Zi>8W.u [\xb /C A% ^e   E   | ]  3  @  A  i  Y :fwJH|KRr8+G:W72W5ZvL,!Jor)/0Ck/jK{iAi1HfO@ a Mh .s W 7i _W S ow"{Zq;L X :E>*Zb~B6X?H5?sTBDH >/phg{re } 8 jQe  Y_S6_Y PNrj}L}.CidFN."3Xrt8 B   ~ rM /  /  a_ X-P*3 . $X #' 6 < T _w 9B5R-M :< \ R h _ 9.9>7H,].{]S#-WXlg<* > *bP(:pPLR o -  y5  \ : uHy  .C `LZ/}Ze#\ +  3x*@} (p`bYh; Wij+b1J ShVHSrr:tq-Nk' geZ N)L[X" Pi(Y]wf,.; X  Ww . k t  ivs)Bii&Mxu!,h -^A,1,C@Q D  K * #  L ~<6[gsi<?`vNWj D8 tK  ) ~ 8 :xqe ?;+ ? 0RO_O <xOg XA } ` *:g\Fd 1/[jQ*Zqxo#e_j6N\w,Q5R?G>*>[e y ?gA$M:  MsJxJ Do }  $ @dy5  = S } | C   c u    . 9 o[?[[~ Q n`~HZ>>]}9;N@WBi.1c}Pr-Zl R+;Eo( eB2yYNO- }  7 T }  ,Y ] f  | N  M XvS  )    * T C W O@F] "32Fef:|"'[=c8gSd/'{*5 \rR{Svi &XcfpJ _PM.`B_{  ` # . o  .; 8 N m H  &D|K$q ^c#B:_eR7/LBgB-[ ny{#hCSL6 "T#o _)~`9].Zs~d : 0d  %  ue uk ` .* i  L . B8  ] 'f`hu{@` 0! &{  :]NikTg>yZD+f!L&7L NL<@+2   8`  .s W}  k-TA'5{vu98 K{!H5NHs  ax 9<   ._ S &< k  B~w| * i$j`DFd ( - < + 6 K R$D1Hg r Jp, P~'ODP f6F\|N1N0@(w?C,m9*6  t #W  fo>wpwY%?3aw:  k Y<Evv  r } & Dw    s  T X  .F < m:/|/X3p-+}1{jjt%%%-_Eq4t9/~ej1s7{>du_ /g } ? Gsd(M0  A   F>fR hOM 97 J!o 1m0ta  ;   v12(pR#dbPJ>078;~NyQ/F{ t  M )[7Sw7-A.%3.  #gAh7 u) W '* T | H  U /J?|Kt_1J*Ck~VK,1Wi?|6Rq_[25#t-wH y/!|gSJJ"" |f' mh$HP U[\@d@i7 C% s  =HH & g " } 9X NtVK!],B/L`3J]}ok(I*P #yl?6#3\R*RS}!yooZ:@8 *   ]  }% i G s-}.ryE ' H I ,F{  * :FweWS?4NQ +6#fi:_M`7#yg?GP3 _w#*|{j\[32 Xe `n }N C }yV1 v  S=Yw  F aF + g |Z Bx {l.MMm$ #[+F'9P.  ^ "5+p @J ^- 0 'wf8Nb+G[N( (9 kM"^eufw D+ .)   caW@]T7[ @vo\ "  YZQyiq]He X   U\  ~ Y~GS4AEeH!,7}yoTI%MV4P A P T+ 3!T  H  } fl0l:3  6 1  'm>fagSNf>)Ts  8P } -  ^ r _ ~  Ncm/Qfp:3+A~6BWXX'&E~B^B@jG K;Nt5NNM2~^^d`" 0)  YoP}X/I!$a% %C L$& |# "2?  S    c c}me >d 9 T h\ $;!\6+wf4@S/{>VsL 1h d GYd\HA^Ysi jjCmsKF}<.Qw\@^_ql^i-"JHd*&Z.`@ p } .c j k ` M X 84 _ Th T  7 #e{Tkw X@dFfj Q  CigKs@?+!Jbh,T> $<  !T%_%/$0%$'%!79KZ6\ |  A]!] x$ #B~A#}>Jsei}#tbg9WxJd3EV S.H{gEt5!Xc ,8^B vPF KhHKL#cKSTS9M!+j@srHyxn X/oi]ox>7 BK@uR:j  C M t ~  7 { DJ~PW))G kje> \}gTKC}Bi%/hXmhx|\C 7w'4!6TRCj%Rs /A @3 dlR ZMB.'TRd;C} m; -f YXYU~,rL 9uXuMC}~@o?F ' W  ߚ &k ]  eN7/f}?z?j|_r,grP<* X  'w4B,[2~i+9< Y*`B*}"5qrQ  U7Wpg?BQ^ ޯmޯ87߇@\ G+liN"y1QNwO_b(TL`!GVjs{v ;Eq&nxBkB%\   } @ @ r Q DuR>+] K ;5]~CLWt#J.B~#-{?>  M ' :;HkjK0WSq!t6  dw~T)Y>B@|rg%f><<""g3f)<t~ 1`kwBZ#3TJ5  h*+ePZY? 0 " /  ~? 8# }P }L U B t W a u^*p{RwZYxG D\  v s) 5 ^ tR  kPf h1udMGf 6{  8 9lPG"\P6AAxVHh|\%6l e :o+6~SY"9ppu2frGQM 8 LB a   L R~D eJ<  "e< k  M|  B _ D  P [ k3[5{6K>BO&9R\ jyVN86q @ \+{fC'WoOefgQTL"@H~y&B 7lM]^SSup>G3 / :8<f4[33<43VG5,r8^h3R Y  & T w 0 M gB s    ]"\G6hY . QgV&/(F# m ?\g , r - B M 9 O(<Qy#g\TL9 w @ody!5QPk 3KvKN7C_x?]K_Mgx)-]qp@,B\\ZQ0A kj~} HRpHf5T6 #hbn"Qygxu!Soi qD w %   ;\  u  3 h@ .t &  P( "Q+fhj,l# 8.pj9_>@Quu,kqkk>8'j~~%H`sW!Q"zoK$ b+o[+8is *}*?[V7}[Pjl 0 $  aYde>hK|s%\B-i $;  A q1+lK: L j'&l$^RJ h<W!Xqk <2]cSBpDH [Z53Vq%8` @o(Ewev)jD XX Qp <kB) +$T!.t'm iyI`_\N  5 4lTG7(GANw)Zs "xx Nt}#}6 ;P4HqZj@+: y g a+  :qKN \ uy8Q^  spS*vD-398h/pb e u  9 .i h A@ 5G3'&~ 1 CmOQeb{% ?O'%&q[G[*vH~,4M ;W^f#Qyi}nG^# F%jZ6}=RPޯg/F0ZޥreQb, k0PvNP? O   , o $ CvN 9  q/a o "! ,E0 KhCZ#P^[Q}b# T # r ]@ , [{H_V6OR#oi&6 L!5+\fOREM\/5;<; buE B U .  ~ a 5y!@qX:7J~%S+? O ވ= ۋ*ڽ>ܞQ;Y>(3GJ]@}L+7vxH{@rj+\-9S[ eRQ{hP89P 8**er)  c'-9l | j%rC<`  + B  A  r K O s & N Hn_<<5-1M~dFu:u69  TLiqWq{,   :Bprwte\{}d}(f1%Yj~QL^6f ZtcHNs ) )%W-|Jg6j ~ H^9jDbM6QX.J 0 -   F1N?CO  g  ~9^F%"* `  ?f  knXH_[v Zu b$d|,2]Kx@p74 f WT _ 0w>/2v? u B  S\ex@f   "@mxp4?T " G Nc:o/GZY  j  8 I   m s $v  M  m 'wFE! H   #o Tp 8q %' @i3Xca {^trڽ0CQRo 5%FuLx @ ?'CH% nQe>W Ni / q .! )bYR P ~ $q , ! ^$  ! }e 9 &7 -,mQ N  N1 Mx lY][`{{E-$0(`ݝ@^\MYf8}bq6J\]@]J|cZs @e{ #%%%M}#6"w W D + q u**oQx OR ? S   CT E   oRq^t q A\ " B $  "SGl~U|x" ,ybwk4d+ٍٗO4hd_+|bMiK; k~ N-w*]Z^<j4& +6K!xvFfH j #KDR C s T 6 " I * B . RSh_' /p0gTHh&k_6PGE    K | ~ rp  P D  @` Vky +Babi:J # ,}7V41ZZu9857A }2.~L3TH\  W 8    I 6 + , $    / :NZ)L 'x+wlbM88|$'"+7" 5 e[? " 7S `)|3tFt 4Gf\]!^I$*=c:HT@pQ<JZ1}*   i T ika Xa"ZKe%?v ,  j r mjbF|4b5".#Ma_BiU_B,i- {jpG:AX ix!~e P*RqSOF)*HE a  C  B5 t\ Nyx*e/Bly47?_G >+)qGq+J@J,hA-]Tl9xGk6<s8[ Gbr/nnub1O k:s~Jr7J!?rfp \ H+4,g@Q66{6gR>2Fs4eJLlSF*A  F%k-j.GhT|G7}Bh1Po)p X" M| po#(+  T  } T @ / 9?  W j*   T  [H7D\L,t\"\DOb(_lSQDW`SPg~Jmo Y ` . ^ q y  3 W ; 1{lt{ ^ 9h#|N|Kh 5RQm}W4~%Bi   Cj C U r: " S  4! " lW9cx^Wtsh\]ggwS`L.v&h*TKW|%%|__BW ux:c1[C}1+i`K Wth-h}~+WX ~N HFd3n x>%p-~MQj L6BpfoFP )m*1+h@]]M,]Jf*)MKr4 8 } h 6m ?FH > q ` pR?y4\"D$M7XX W.}h-g!:>RF!>mj>1dJ(   S \  G^ [5 -@  U `m ;     W[ /J B O|Td_*^p]x|}0sdrj!MW>MPmF Aoi9\k#V& &$`^0\ J s S 5** 0! 7V r ~p>61DDI4yg0.Wkl7}vp9WVK g 8  @ed GR  r  N 8 W X<Qg-^66Sgg/". MXZ9C~CjCd9E&Yuk~D'0 bj8l33  [  p f wys6E  $  h x   .* 9 @||A::DlPxiKR Zu^Y *+ Rv@7BiX8;ZGf 6 A\ LH y / v>)Q!]$Bh*Rt]i{g"V+Pw:Nux1'Z&/K'S'\xP< [ > @ A L C  K }[ ty D[-9sVBb"*h.W'&y> )VZ7ZF1 >4F?6K,L | IBLKLBQMw3 j4 7 6 !) GCGeR/ 6 # gh4JB:d[R"Go4X T5bw!D@N7kZC_@leYOjBu@H  [c- X! a(  F A  \ S  KJ _ /rmAbhR^CG7 S / F U T g   I  #E l P2qZR!}:kpl{ ]jN&%T>&0NuKR  s `  I  S T T X F t5 &-F!T/v Q; t<X.#!R `+hV^"@]26?#^8~8&C`jt __`Pvjl*9.}AJpp\k @5)4>ewe[[ ))4x+G{_ p55?cH  M> 7 {~ .  g  \ ~x3!4BbeBKL seBS>\ XG |M7q@ m  M  U i }r . : w 9 i D ;;?i*__i}_B90LYd*&{@/P^[@y{hF/9$iL|S5_[&0Vv^l{Q_wk +\./ D t s T_ ,& 2H]T%CH  1   &8 _LeHP~lbd_R{,&V!# 9J BH [ K3   s -  aY,QT %rG<[ XH \Z9S/r[ a K;~,goyZH"sWW& (~9WxRqt /#Q D ~t  $ u \[6"L;ZoRr{b"A+[@] 9{ + 4   & Xv6 Yo    F c<p:hWR#%T5@!1 )35 B  0MFL(dwu{ jG NB6y " ^ VKB}\Bhj  D I  #89AK^)-*!Cb+dwYhD`$ih:5c*3)ot_^-%p*< N7  t j  .  NE>Ev 9m j 1 u 8~ 8 A ^ tK ;,[m  e !yK=_\t?.#5etX&VKjp?4N3*F3X5r|W:Z**f{!Ql :F `)   w!M^:X{u @TN9k FSk- : & . [w Y w3Q f  7CuX3dWx]5>E$hK KC%|,eyGK?F)Ov6v|-;D[<QbH HRRKF*~p  `  )  h    ## __ `% D1*x  A2Hu]./![/"Rie7lK|mjBdWbvH.#DT82} Nh A*?P* ~  %pW~ZRZ7h<HF ' M U |   K)    w*fAgLS'8'H ~i|   -    C  Jm oS\k#sPZcYF "uN9S!##@$0{$g"@!=,,vR< {Rkj;V#({o! XCm'+/3LhHv & $ ^ q]xK W(lc(om|-Qi#+ {5  Q|74S!`C&W Q6: < *6h.#RR(SwZ hcg PO!W8L,5cd]*696d - ]^H*{"? t!y  { 6 I  ! ##" @\[B4 iHQ M   : uxADM"T J{snft}:D=Xn(*vq1~Z5WQ!ReY0qd}J1hg K #fimB'UM,      g  O9FU5 ++ @Gw ]R Q8MDRltE(]_N we3Z3S,x1[ lV,r@#{u:t=_5Q\CVi\\{. +d '   U Pw]vO;* !e ^" ""Q!=#r~0 5?.!E x + I  h-   i M+H@#XQ,8h ߸YDM] 'E8GDC_L-qv?@Q#V/(WGZ@58e,m K ,3D9l7(qE5w'u/x!h/ 3 Tx s!s8}7r_g:&\{l2 W  W 6 ] g  |j }  m , [srNiP yxx(IY:*W  R  - kuZkH9:h`"y o   3hp  GF2 a ~ 4 {r*+Zh7S-  h  y  HA88tF~Gs6c" E6!^?Z*Q4 fEki ;D%H#)'we KJ i _K -3?#ejs F6.Z3  &6 $ ~ t 9W ;}PTZd;/ X "   ^Q Xrkgap5  <{^o9wMp_0v # | L   C 'G YFF> 4,w]M B,ucAaEZ\e)bApZS   j - ] ? @   hL{B ^ 23  q"@qy%Z7 lixS_@pl X h _ &MQ<O>c5:,x 5 i 0[Ewr]^metf C  #>5P.geJ@,  |   uc?CN}q.?M\G:cd,yh {{f|||& 4X8JQ[\, . | ]+&L\  "? #o  a; \w  ` K I> GD]x5( .     99Zy#_ S~ ;o4,ߚ~BF(sid5! /{*RF1OW &8  Ae{"{ @6"p]*,d'  _4 XQ{&A7w.0DcEwbX'd[[p `\y>6]-} pwri/0NX ~ sAhpe6q5j 8MASS]AsA9ux 0p]?`uk`88Q+JP  (1$e|pg?5]?QQ\y *>? ^Qi56  ^8%~]RC@#"!py@+R6~8Ws3r*0= ]oXtXYC?7q G OXj>L|5!;JAPi~HkEEd< F ~ ` q gF\N4Q98 8 qL I / : ) g @ M 3 y , r k%m])l X  r . #4 A _ Z/qj9$ dxb!q .p^^Vw%D  ^  # u 6_ ]T L T      4h^ij~my9 L/Z/1i6-Mi"JGS'R}GAKFWbkuP:P*:\u_d*&~Jig#y@3Zg3S * ( * $ 6!M=<L71K1) Y TQ  |[ )i7Xp_gX_f%w#]PxxftSP@*gp@TWs"P&DNbb mCCL7NqY=6 4]MJ@{S!Q 60K?  7MZ.!"+ ^ @<d\OCSbs6QOl Nu  / y De+\TWZ#C iXSdj%+#wd  P pRy g  S ` 8F 'w| jQ3lw e!P w ,W}x"nNcR 6 p 4Ge6.* 5"u^O_+.c_26p "17tJ@2 |  W "Z$0%`4'p& g$ !  d B[ H0J^};&aN;;i<p 3v:LW`+:٫$֮.ӻTlg6܊5tGdD9 iOZO |  W   M j6 W 4 B `w 6   usv)R ,-k DYh8P T ;2efn3p[Q+G\yR^5VQSR,y^^hK-Nx._}s^GZv_%[\ m U ;  Y : 5  W 6 i g s - s E  :c>y6qT D T rFe^.wS GkpR{7&cNsXOM9Hd"4 ) Q b>_* :~2]<3) 0 E <2Cw#r",^W ie" F M "oJ ~<H R)!5\HaYwe\ + s aFB/?b{Wr.Cp;E nknI|W} kXFel ~P |?f7݉'ݝ r < rF   Z  v* {MN<D5?pp$xt[`t}7F6S8p[9Z~ci hoL#H dB( NY . M g+Y!5   U x,1T*ՒҁNҋ'Ւ~P@ߚ[ZE; A gH3 ^ DU(m[5 T\ ~Sh` )sZWX9_ !n C  YWB~7j"t+L `0:M5RRA^ T\sp  | P - g ^q9Z.Cs#hW=5s,S p ")?l4F}wd*o ] k 2u{?hh_(ZFD/KyQn~s 7d  - g_i-<`7A!#}%.'#j'{&}$)#>!h h[1,{HY4<D޹~*Vn{ ) ~ ,>!@~^`kk @ X,"@s`"Dwx ?qD\Q8 ?o+q]4{!6<Ac.?Y 8{yxdM}g> ) R-grko!t@^; C  (Z;YB eQ? %LA]?[  @  ~k W! B Mc ? l).?,T4_ 8  ATTqS 5: 6Z5kJ^9ܞu/ޛ :mR 4 SKh '` rbv 2Ju_M. OT"Rn4Q SZw X TF Ap  {  ` 7  # W ^ q bV  jx hp!D  }Th^\U%YG o~Kb'=8Ye9C1_{KZLp Xg ixAzw`x} L9net;57)5W|  j  M   g fWC8 _4^   "! | XO(xqiruEwdxxQFqb8_LoZbOk cvYS:#$Mvy6&&qh/7w#VTX} & l/ ) a  Pc^ ~  '* A oarn2- k u 9g  M e Xt x^f Vl`^k2Fߑ[ޒ!+t?! ~S-v_dlZ x }Mbhd]'8kd~%$iL}6[isL}+}GV w`kmdFvF Xd t b~<80g 5 W q,f_m `\1qwH:RP&/jtx`>`tXx|Mlx f?C?++g?]\+s!OJ,$r081Vs$8* ZT_$0(+Z-/ &- 8+ ^( %9 ] ] g   ~Ad>x*Ti.2N BG1o,eG<F sw  N#rJWqSSB{"t|L : k/ NJFwFP>WVrQ_|}K"cHw'yLK Bq ^ K 8 W +v,K_ujbZey*A # A75{\j[}jl,  >yN@g7L.::{D`Ny|qld);_`^K"* & 3ZF<a>y= - HQ6]?JLR,<}bqWs]7{cf\   6@F7M_6 Ntfr #gF?>o 6S'p>Pv3x"KL6+< :A 6 y [ q 6  # k,d+%3xl"7G};&ZV )eP),x 0e {r7_W LP7 g 5 cQR~k}\yDx (& ` . BF h  ' 5%wu3R !cqJ]36wx4_vj1 X  M & D  {l{\4=u_98tVK;geJEO[p\Gwb" NLp+/,%^~]NS4qQ?>c O +7 Z  oIm< SF3c`[ ~,qT3% P  8i u2  !h{op 3fJ78/uko{Y#j+/OV!fo^&b&ZiA$,#4.\ Zh ;  2 (  Y"R== 0 u! I .  !  l  X Z@Cg'mp{q|x5Wg^HE& s: Y)`pd  }^%YDeR`,8j9Wv;lu$}px6~^'q!~ 3wnc   k}  p G &;G2 D 99 & :X ;P[>Hp5!+oH qG{g[:::'NkDw\wy<]--  k+ _  &6 R(e)Mll;b2*(w8R7_|8QNs.@)& N  i 4 4 .J uKPGt  } 7r #]   U $ Q o e ` j C &P  ~ uW2B[KHp/Qdg $ v   T  |S -6 -+ o  L u ~ 9 Xk)YPJ5wFFd~b{TG1tFw)wqqq@b !?PQG3i&_#{J]4?7VVBr.W]Be_ ^J]H[ < kt't\pk#'} D&Lj!q    i5 }! R    C  Fm2BjPN[3** @@ eM4QF:YF4*q^F_` dy3/.T}s( m* ? ^>}X-r@ f D  7 +67 ~W FD4tp  " Kh h - ~  D2HVZRgg@_gSr{,hK8GZ<>e(/*6},CMxV[3 [%R.A(7@o<rtS+4-      - r U j~ c :..foO  M ^ g G m W / b >{MDFvK Bv/'D)Qg!|PVfHC"{S@w"jAj@|>>@+Ku2?^-O=w).!;L F 6Zo /   \H!F    +  ^; Ah$K0c# 6 Q M hwJS) p  MluCP!C!Y>+tT8DXDb)\Ty?HQn'bt.+ ]ZRp }x^> 3 S  L# 6&H4 FZ;vX  /!%7q!f$im"5w)<[|ff"4Ts9 kePe ?SFr@}|74df(` (  N54Qt`-54|x } I5H XdZHNCTp#|!p    + - h] A 7  | W N ;*3t{> | u~  9 k k6sxAC - kwFQfSY3w:~' KE&+GmS+&G>~G1p@.~CRVJh}[uYf cY M V U .5 (  ]<&G\{c@;oP[ '* 9 @  RK VV  %mA]d \v7  M ` C< [ yF4bPWy]_tdk!OTZgTLDO<+"J6:xC  [H4"+3o;h{^?bN^\)-S v6 6 U  f A t dc91)Mj Y-OyOoOZ1  / ) e  s K t |  _ g W <+fqj`A9deH,Ks6h`}: r:N}iUA6"PD}tRux"!o " ^  C_  t X  & MP ~ 9u $t s ^i  {T!" qf[    @d*m"Xf8r%09O + sY 0sk{9FC 99@BO/u>>*sWF(hRuCC7  3f6!w 'c / C C } & 0 D ([>8/+^!\&++l  kwG@ffq5-g/_ ~  vbq,.Wkq AY-V lOc32*b/.S3W}8h6?4fx5r#kNe%\5f y L4 x B ~ ` 9 N5E;c 0 9 N _ j : vN%J^ g \  u :o)Pr>p]JAs&le:5]h:k)A ]pG>G4cGni,ktV8KqJ)yGr\w: ' 1 s - |   #s>W\r~$?"?G ~ #M em)(L : /     ' ,E i 4mL_9+tQ,i^3]V@|,Q3 \uuL fqw]/k'EVo(DdD d ' $  / V ^JH P;X&_5 " 7  /    / N    d   ! NYFoHV#LiAir@w fRrFF +qS~ 3R4^5kf2fo;WlO_z^!Qn0i+{VAXJLSq"K8CN+[X>: *f@c tJ 6 hP|YA:u^QR qy * kfAd9*vc_cj3:yZ#/<R?|5C8Z`w|+wci4!Y+t{77\_ 't}-nZV<.D:DX0bOev+05pg M| ?D  u X ' )e I4 |f s !m >,k83p[  {*uE-eSRp ,e s cE D '9y^B:[XX~]HWT;pcX:we[+;@@eN7^v~H {tAx{ 7 <dnvcs1cEZ@ev+ S A A _4  &  cY)   t _v oRS4FYOb @ * Dey? [w(u'p&.BR>B!e5"$ uG"[Bjwu}f[[<q#b\w39:9Je W hG0nhv}sXBOV,Tf {MJQS^kG^hB. b{$!4YZ< |"vXC3j`c&Xjs"y"NR%>gy?R!6&T ^'B  k_ N  G sZ  NV[Pdavw  h . a}4{}W^;9;MO9.~CM7j~'0?Wu3~x\xG?AJ\a-qdtp~3h S$bNW`YjtHW_Wt  L\@\,   J ~  L9 C I M%47]e3Zdx*yH*e ge :  T . jf ) WlH)g ^JMWj#_ip.x)mc4O3P45J(b&s1.Q6o!dP"F%X4ZRHL&{O_YfAm+L;  A B MT j &';p"k &  NTWyB7M7g}M  T P   @]>6]L^hy L9k:GXkZW_9^_(qp scweeR SoQDVw5PB?! / T+D)HO 7l v3lS mD h r B CG o u &1 a'>".T|qD)Y & t X sRl;  @ ( Lo*M}dZ!"-J"g!}vMKpp WBF# ySq-9{+}f 8 NT,oPBp*  B   \ D!  q ~ r k D  M 'crog_y'>uKiPc$@ {[TO lwFw5s&-[}"h u TNAAM,@q R >QF0: 6H 3"( 0 t 8/ s  . - g cFF"'<%>y:{d@[p@z{"6,:" elh`WX-5J h1tb}usg 0 k M8Dr;(y)[ c*d8{s8D/WXmGH{FV  - [ )R SX  s~ LJrr#KwT^-^0T-A{TG@2 YV%[Z*X [RrSgS:"]SKKx, %!Q b  / u~EoO; bk&_. ~RgJ"*feV'E5b,R4gwmd dk_/ ]X"7i M FJ/:|Sp*~#~F5w%)=*y/T".9 SXPm F G ,Xf?yBpMOpYjU Q&>FqD1XC3e G $ Q['lttj`RW'^KomY Y  C+  B  A ~ , `Zx?q} '۲ddF߇j ]bZX>D'GkC)2:^h{GFS;K% X fydq6A|sKhA\ wY Wj)_w,5d45 D C t  U V _} Bs }  g.b~f_O Q7 vV_)_\y W -  R h   B a 7 M $ # h $ & T  LdkI6?Ayi{XRZF&V|m C sV ` A ^ r tX aM(rxg L gMjD;<E  my:9KdT{LkEHfQo?4+?JSJgq|_K~D })V_"H PgWV7 "& y3sb X 9P 8E  i @@  -  F  cew :A}RfeH[F.d^ ywhh#BBxAK7rS=fQ[)=K~? P Ch]5 * Kv //^lKRLM  | "V.,i-tԺ-ؘq*tP '  ,!5!s T   v ^A|js<6j.;N wO1&d{A *ou a ,fL6[{#qS{?GE<dPZ Z9%^h!BFd GPSBE|?J"Q2#X3 hi M;  R}#w [@5S,"\! |*3J2 i 1R3׏)%ָpݰ'1',O+kGy{4Y/ ) \4.  ] Y X a  HJwP 0 . ?xhl s ][r sKr9  aZ f #  Q 6EN ) A g++pIi>  (  9 C$ / @!$go\<L DwWZ,4#Q5*R\"#V8kdjc@XCTlSx'js5cswZ19i* q +_ o"Z y7e[>pX3) <Z9c -  a / C  _| } / }^ _[  ! CE u l mHo)VZ Q  , ~h VYjceEOlFEhc9k`kB[34k{AX(m3G N Q< 0  -Q {fH o Z(E]Z[ "< #y L  Edqi*H'697}BjP . e;15  u05H,_j<bi0!WxL~6!4 3V: eZpF _  WB W 9) M  62 ~,R@rLWNvBLh@ G;El+Pd> R SVH Sw  M!.El;O(^;(wF33Z\jN&)*) GS7]x{ZODr7bV%BVB7K *GsOA 0 k   4 d X ' c)JTRMSFR.';1? SP T} $ Wc7N   } ( K+ - B C(Xg%%~6X| e ,5FQ[ W ue^S!Hd))3r@<,ZTZ Q" &E hn! G=Y  k/jr}e@@q+; T' -9 ~jD NOF[\ogg gqrx)~M  #  6 ] 6  ! $ cZl^6t|9'0TyL, _{!$V&'&&K6$"K e|pF&H<\eG4O'r hlT ^ t B^ |#)M3 tbDM}F 6  J-Am8i&0_;cObM# @!Of +  C}*9~(XP oX]`ABS`PASCr}F"p&>w'jIjs|Q  `F 2 N " q @ iy5 jp(@ Q   D uh;mfM.K3>?E>%i;99?K)Z52 / j=  / XKc2~E^vR u) B Ts    * X[[1R\7ii]\Hem!B! $& &(" (I %9 Hy[  ` \  ^  :rjr=t tTA 6V4| @   + 5 E# erx8x %)| ? U `k~9L+ d87J{yFV~ k  at  e5.juuP*^R6| 3_V_.~ cV0Qb|:d8 kj}Z  K K ]? " $jRk9e}|2vu 9h } r ! + ;   >+  CxyC^-#o j 7B sB $``~.V^>T [ i<fmo [ | A i? Jr-:Btj`'Kddf >O<NCHP   @3 'N_ yq-8~ #DculN2^Lhm{jRwNtV.~8.M!XQZ[Gf+gA$sMiDK6:yD C B$ s ^ g +8*HF#Z|3-݉L٫Y,W@qD85thx w"QKE}GD g^c &LdA,R  vXFX_.l$w8UKw Q )gy[ ' Xd Q DDV]~9'*Rfw#}$(/.j.go `_ ,}}G$ i j &bk'O'  &: N 8D 0v(Px"j,cQ  C d U[ q s  kYr~h%&]:d 9sp['AF C 3 K( :  / ` $ vb+AW`XYVQi,Q{ +~ 'Z*qu+ YQGGiGqLCp0!R}Zo3X. a. L # AA 7 KQr]"+qPFk3? Hkh$lxFQ5 " didY-`kV)fF ~$A.K]5kg <9@^_g) k ` 'G Bu:R/rJ!Hp6KbP $k%9&s&t%!e9 }Q-pT4DtkrCK[jb^sWmcvWfO]P%Q } Xd ;   ] j4HHm  I ] - _ Jh ? Jk@h &^ 7s_^% o!`"C#Y"!D "w >]P7 j)[qpV HZFww2i.LjBV?Z`t?jqRKY~! i*M}^R]_[t'C'-NDw`B }):1 N  A %m) d H g K 7 eHilE pTbfi;)lD]]6.6}{hH| KeK A#2;lwdt9XZvd wd!2f"(/J!E2 _ a! G  }  v  w F B[    c 3 c?@7Bt9`{?VKJ_f+el3 i(4 , &< /N C~ W_ j v/4 RS}Wju. 4RvJT"+e^lH7!64!Pf#9q |-T!y`[h\m* 6/hWE ]fdt_|? o   ||3OYET;" ! ' K .e C NYmQy)fid 'w)wepR!NLSerw*LJ A |i*Y~<j*0 U~ 1uye?cw NQ  2 N j! U ^ & F  $ 5 ~4Fg[}+{3qb^>^    k B   | | ; h  L\ c _> ') ?\ZXX%pD=  r co_' i]TmsqQefW+~O_c~:PA +J~T@)49 t U 5y5f!b I  0^ ' 8H Rv'N~c+%w\ 6 S  >"#1$Q#1" f`0B ' 6b?6+esYp( G!!4"H{CrVdi5P[![;+/:6*K1 3+ <;~ t  B " r ^ ~ Edx!" #B_VM.8#i&'r.'T((,&r%#"! pF[gjd) 6 T' */ROQߤ5ޥ]WTL-r@AR lW`^-f\Rfm  M-  ~  t # L 9@!G)DT$Rw3"\3 C: T  "?O2dGZ[y omMgL6T#|s 4 K b_;Z@[@b!> pF1'M%fB+{p!hpM+b JO$5JdE Q s B hp  gM q  B    M^ X; , `|w?,-QM-ws)Q V-!w :,#hT.Q|-/EBfK9Kd{7J|`KD`k&![Y3e8*h{Jq{pg*gS]_h-)V8/7gZ r WP%#G[5d>s|B`k<[  ?S t^ -_#/15 3 eo+vn@,^g8j+\GePd0DNXkX`| b. ^ S 5 Q Z :  CO}-r{D]:X5o) ! & $   H   i } 6 | $ s2    l:ZMe"{_|W'Vu9C:`seKr6#_-#b-2F5!5;E`rqx1P:bXPb4V#8^>d2lE  ~   "g {HfD  ` 7C   D;Hg"  K I[Bo 9R , ' 9dcF[[ysN"DPTV>k.:3<8Q[2`>THkOs-\"Ho{JK"AVjVDkcX?q@rrK^|qgp[eml : M K\Q<2 D ' /j   ${  t0 9P  pZ $43!Qe*D]]R[smK&i?s_/qMN)cjN78( ^ g 'Ek~@ y L N~eA+s483& D N/ 0M~v.mxHgqS%De NZeHR\RQx2cYXW3V 8bi^7VcL)G4HSgBpH t)Z3uND`[i6^rT8rjukGb{H?>w`}rc ` TgeTDVMC%A#A$?Wq?ym!Q,  TK jvB%"64?&; 0 > XR +t:dL+].,r<)o!e- M[ ?"S$8_j(K qWsnR\#[dd M L # |  Y c   ' C k  0 Z  :e N v4mZ X M f   @ `!5E5 g 6 C  -\/TWnp77v- uh 7>y \Xg.,[]6 MJgJ.7spO t Z @x Go   U  .G s    B 7     A TT i / F*]Wwf|: g^.*j/+/`6VK,!7eT#ThAJ|@]-LgV `-u'  X  ~ $ T T 3 Bc5 + 5  "  A h7  A  .< e & DEwG5@H_CCBeb!Sw#RshBi.MS\`S8&MQ\sSrh+_x8y{,r5G'w<:dT:i2(}PxfF "\!_!BR p(Q)bN7?|^|f#{^^?+Q&8 < q 1gkpGP l -F+Z`t`!$f+,SAs9X2?x@A"!~TRd&.gQ3YRvZe)]H.   q~yj&/ / j r t   B  / . %lZ[yq~&s/j )XD}FN4<dA}LYR [4:o[RGo&"|?4>kFDj h  ])5p/!$?WK  Cjg}mR:*G9x ).%>iL4}>i #^4gd4 dNv-Z;  & & t% HM8^ KRbQ<-:C&g$?Vm}[i}6-6rH,\Q\x8<9Nn3d<lyjoP a j i # M M &R  9 9 j 7 = km lk;Zo ;\H0yyR#"|  '4p q`8Nc^>JGfR<"tX.@#>H}ko3ݝ*Kl^"J^mV 8 "+[! " A $? < #,H3QF! &  s ,  93  D E  */  e* ^x8fC N  } 9)C!.93+ utfgt#^}FxZ->sG.$PLBh"?4t)9s|qG;ovc  Nw  & t{ q   , f W      M j  te  )]-4C 1 qQ<mMPskCW G) "l .    Cb ^(|MnWwdܱ1cj|ZA'  &*Qe=\d S ^ U  8Y  | Riy&xG+J g  C N a kf '[ZB)Kp* 6A X C k : [ f,qt[ Nji5)9B+,#S\P Jk9_(F(w\2ZO  e_F`wwx ? `/}~B/\ 9d s |! (   ]  } t.+- {H D$E!*k,WKTR^ +{p)b  W   8g   t:<fS78"DPHQp5?*4HF :'?|MjO.+%@ssAgQ@Vri#jt k U  | #" kvdGuyGdp[2w Y-c9v;qOSY Zog5 ,3Tl D X ' y f qXPS`R\PsPNQ\!p3<-6ANSLxu o*g{^FWKShS1?b~h  kS  `     jZ & ;  D l  F x  A H g f I |_ - 8v `P*HG?!M9`u/MV1A<S?4 r 8j5<A}q}W3c*f+Rdk[)~bi-~`P) S : / 'JR^?"qm2#X  m / /  aE[:[#/DWw{v ^y.]OtgqgoF   foff]64G[R , kV :~vdXA0k_T{} XE ^Rx 4!^$S*j|| |{  g { a  &q]6phTC7V8.Ht9Zkw)\56-,&:c}d[JpSpxn   $@ - ;)K@?#B4>QpPgrr[*  t 1 @5! @ 7 U  HGO4~yq?^s$q~miu|{ k i PXA]q'qq @ } rm}ooGOuy >p\QwJSHGwGb>wPYl D j  x :y\(6>-1bJ}8b%"sCD1jFQyDp%{*xZ w k;P<RLCqGgQ3:e;x?wn!Z\Z]? tBqHqQgwW#FQQ:8f55v 9   A 7 $ KL K LX 9k :*<l;)#>-yx oQ "% x,?ho7Z5Bjk)? +{gvH<5Eo0dBobiA_Lg*fis.9SWD PCrv kvP X  ~  a  < '   { ,@ }6 C  g8n 4b$y Fd chrb`9VB-}LrhLT}s&k:d3Z,|Fw3io^"+5x{X,q a 9   ]~  W , / ku:XHkVH?]]S@5pZ1B^.] 0  NOd>Kh9{yHgrgyo<e9 HDS'h7~vY3,M0YYY+:C{Sgp>Q!g!{%_itsLlAZHF4'HHR- p ` !Qy)  q # ;  ,  x= {b h _ FR ls   t  /M j M M_ MK ]2+JFj  5(5Ru8k]B80&f(P]MQ5[W k$o7,ydb ` |C {/ Ct M  [*B\GR?"#-8R  WqyS\][h8*2  ad D Jpr8B]!GG3w/L hg Hx4 4@3Z  ` ; } K  t   X 0E:) :6"hiMA6R@u(kyFquT.s\9mme:H|%j(BlN w#TkKD,myDQMfQoew3)*oQ     @ !7p^y8y? [   7  _ W ` Z G \J7RM{_FsdKwhmk5!/f5L89joyNZ>'Vcy?BWsh >V@r  G   NE : R { 0A`5,G;3!eHh5pg5Rv$~T8Au`B}7_~{-D8vw/F9Zs6tT@6C7/ ` #b 1=WM$ `  dPl SPq=h\    t :3REq~1I+@hV8Z.K"@"h"}#uslOs;;Os|:rW]rP{f,:h ! S   6  U B  A  ?%o<Z   ($%a! FO 1\enHq S | ~ 0ew3y % J o@L|M8//98~8RrTP>  'dY ;Ldxp4QbxLx <xd(vY a( / . 7 ,.m1M o_4*Kx|roAfJ#lB  B J]9"oRG]K9dCt~/Vtk.Jl< * ~ U H  5 I < 2 /D XWyt>Wp4cFE(ECY.c{[Q D F 9 $ B i j - #~ Ti h h T, #   Z  / ; cv)* ?J\])- C  t h8(CbwxP!3<}w%~ '`_JT& @+\y\!F{,!V\HDJV D9s [GVED 0 ~ H g N5y!+  @ e  i o xw;2mc u*  y gRHfUoS SsYC g . DgAVQ@/hjtqPR,,r :F y3h w@{c/H"hCiLBi# y D B yM  L} &AoS6.: 4>[QG*q,}t&fX>w X`}K6/<oov  s  )+F<Q+   L ltDd<)PN1]}g>f?fJA6!V>Q/RbJrBc( "<'[oGy\)5D!?HRGyRE.jVT tihV}8juuk7:,k]CQ#@c  ; W C        #' {2LNEtn*Tn$ lYOd(YlvlbM`gMWct22;^Y"YJclw: C B  ,  *  :C "<4 X g  6TH xVjQ K ew+>[XD'jN@>/}%#?K| T*~u+3 8TD7G3h!],T3h@l|GN_OhJ!q{9:3K sT8Wr0@'pk4'}rJ*,pel!H>^md*(J((X 6AApGjL.y_' u$H:`8`88j!m4 D / K: T   X Y3{|/TxfmQE  7 t   * H t } C?}/By+hJw-@ox< _7qyWL_KTK/brhs_"7\s 44#pKS"K{? %cwe? C, 8 L4*L _ } -A jJ_1x : | t _   { kOpQe?S9$M%kvnsD(VCh"H+P bVN}1&@_qi6BG~RgZ--"{f W.g*E   ' / 8 . K ` , 9 XE)}Z> + }q Mq)p)kV+)_W ~ w WxoxKtF {}tMscSy }**w+{u(  !#B rQf S"5ttb  ! n3d( [Dy g  BMs_9_.[$LB)1)CD_< l D A  } } B "  g  D O d  , # h~ }  :sQ-5W S}g+3Lu/d FZF:uGNy1d}VQt6.VALH\}g +}\?( k > Q  xQy   7 | .* / 8v]P [pjTZ7 @A 5,Dpx *4Reo<o*<m\X@diu{Sru-^>r\T{gSJ"@qp|-BYWC~Z$eRgHq`oNyC %yf3 ' w  2[ Xw   W =  8 ^  Td     [ ]! I Si  9  7O ; B t; v:`.@eWlBh q +(>3Xv ' h  `{ t 9  Z*yXpx@{.gC,kEAYNK#>A/{>p) XG9GB Ag5\]- k W B  4 pfCR SE  l  ave Z ~ !HR,^ 8 a  y `S{.DY ?nF|VcnH & B 0 Ee*". 4W789"DXDp`.>5!Y,c0Tc7-  }384C9jDE?q|T*s^RVWv `# K [w1<G{v Sd5 @8 r }3  u*m;l9Z T e P>5{BAxs&? 3 We hHwLw  4?{r@_dirSRJ\kNm|?@p~ZLvvOme p5FqC%Tp p2 'f g    qZ {Hb S / F]S98S5 D   @ *44x4B T $Lq~P]qelw(0B ?bJ}-r'2n<;G NQ W l Kk TM 8L  +dTk/mSp8ye[FD5:":ug+5F5Ql: 't D 'v?kH`g~-j.Wk.dBxK@K,i!Q QeMuVFPqRQow?u`q@",@,,J{{6H8D4<[v :9c(L_f/{>]g55\H?!gNKCxd)Y * C 9 p \ff 4GGYNRW|P8Nj}KZPrF3Ft2N$J]"<{ pC>xLwVF8BxiB@Z.4*6  cw`" :!  } 9 &     3vm m '    ` BD 3 > T\ 7q }h sucKunQZ:1&@J{@   W  t{ w(o}o+ u W< o f  #{ 5 i? [ /: ]v(Pm3 9 A x >   -  4 e <f;%vPYP-}yMbs2}DZc7&:9`)V}G>6xPXA5\|6Pfo|PkvZX xQGJ3]!i++ eD LX m |  IH I IJ ,] A >  M ,  {AQj 'X sR K'XkOcjX__q_i8C b  + c~&TBp"@?Ao({fCry, * 3 *D4 " G ;4|Hv+pVx 3~Y#    v c   Ne#gG 6/TcY;C">`OH )t3LF OZ % &  c(wqJr*`CFMtCuCWW^u"1Dyok/c a &  i  K9 / , F *5y+!J 6 K Di[09ZVed[G!g>|e}WDN hjpJR*e\D`}6\sfMDE hw2f-6kbW"]&{\,#VCoN5ZA>'ST:|Sv2Yjk? k . { R Q dY1j3SWBt}WD&c~8 -,jejLh!( [ P 'OtL#i|tx  ]sq]D0b7~L 9LS  & M pi ,# r | hA-6}w<  7{st 9YB3\gZ+;:}f !#r{ qJgS"6[FFku&}Jhg"osxq)ox;  ~ U  h T: -E 3 x Z2 E'tBrQw#eee N3 .u _M . W- kwHkmY~ldE %;\`V u5Ai"B##T4n,~"h|2< e 0 'vHeB  u/ Nu3bbW}^{Qv) F w ^ Sj!Af]  K }A C^)V_8%BT?"!8cc+E@,S}]+{PXYOPFu`d|b/q6* @&K8h6kb96 d,  7 i  f e4f@ ]g ^q BH 9N:`sh> 3n Mw 7l'UWg_T  RJ|0T }.]t|h\`WgB#,RFkP`e}5KR) . Kh ,!iQ;c@({P?4+ @ A 8 uNZj~#Nk&{#VsA raZ ~V*. , C{fq_'&vo) H^H}Y@fd.\pxsZ5 '  X (GmOD  Ml,8yF<>H .Ww:EWr @4e eGS 6ET V MW b _ ^  @ ~ 8?X"#Yb Q,# ^`of w_~6m| &y   ^P |d T2  l C; Z4pTNL</Q+ww5>Mr| m(vqE$d~oHsjuQeyN@@iL}KeJ3peZ:t  +x o > _   8  ` k:?_pqK \,)MJTPpP Z3'`h.8LWBjbkZv+g-kL...857b]D>1mbtG@3 a W t t _   g @? " G [  . M  0FE <   sR q  T V ` &: jb616joA]) ]  r i  8 -hx}p]@kkM6,] gCS^dE)BEO"t6#g*GW  ` ' _ -  K ]  _ } _ g S    . '  d ue;F|i@/W+?]MN-c#ZxASe[*+J!t P)>O gr&7KA-H; XexCP}wVu`&t~`*PR N . ^, *yel) X  Y vv)w3 RO : 6 #   *d3xjH:SF[rp%L:.8@ Nkt~/;n '?, ,d +D " $ x]-_j8W+mMW<jt6%_ O7hZg3\SEq $ / U! T ~ 7& k `& '.Qg|)+FGO w [D*  Gx6nY}0O4 ,` /jQ`A~u~5C u[x QS1^7|S_\oRkx. 4Z@~h|B ! L | Rx  X V k J+[P& %3i-e < 3 8F - 1XZXDX3oG q M^F9c4Px56P 7K]>m1XtCKD>?q#~1>8@-,q"FqS*- 8~RGe@7||Jyp  `M _ @[p[<;o  3 9G6L@RL8#K>p?w\ { 1uU#gPf' W k_75N6|!0j-X v7ll |{| a N j! /? CH M!   & ]  ^.&DryBJrmoM>/`'Hx&`]myG5!{^cwe?1eS4.D@ r_.wiFF3dMbS#<D9wLrq a -  B j B &o!hLkkl[F|Kh;CfF '9D i Tr K& _b W av|55)5S-\$*$. s 27;{HG k   /}  a  l>xXR |T@sKJ@G\[PlgK{gM/s|P?J|V"oRt@^,^^fgGw) N 7W?%uKy+oy*"j 9Gh\$LdoFE:cw#]oASl/ GSE@#[>HNNi EQox {dvyxO'+oT7omOg D^ k NBCEFQ rS_H9&!6K. 9  6 WprR, ? ,e w N s  ` <ZRJ2K:xGRBM9o:9Vu^D+ND`$}#,H'M }8-<Wp_KG'@c f"B|-s : C Un : _ q 8G u :2wE    |  "  UQ 9F5s/&Ze+#0Bxf d9D  ~{ e  u     # . < HT`JwG| } V _ } - x-E X /    & "wf>)T%KFF3+S|<s:j.rk f~f]3TiQdvXZVdH{Gr7  ,5=>wk-  6    :O  5 K +Qp[S|`Bh!x1wG}|V{\B/Bq^,E  uH   *YRdS4N2<\fG>n^^H~PW-P  L  S 5 = B F } B[  ~  04{rs`NZ6R+ +[mK#StfEG( '] / . A g h\  #_&"Kg%rMZ&^J@m)W2Bl7K Ar-&V_JW'_^,fQ! 1  j7   < c     ~ * kH pc [5> @[B9BKj@s-|,qK!+M+t+i#R4&Djp@ZN#G,VHeL\@Z*  .C     2 : & O m      L  / :2Qt"+VD]]s[l &   K #  d     y$eJX[ o-s}KT*g!sP(0 MvL-(g FG?B4 /d e \eg18(C / ` 2B[9e8KRL  Cu X Bk .`  2?!br`ZJo~)b0uA*_Z\ N ;  Q\5J  y" {{ - QM3S 9~Ks##{6R,+X7 sKTX]4 <W@g\W [3eZHY{Bfq<{C!fJ , |A td}&xp S  D !<xp5+y+Jgr{i`yJ #xPE)Q3f4?p+{\r8cpYMSvvuG W  . ^   :(<  p  @ S  r  } 0Ml QPy ?5\Q !w@KmWr$/:Num*t.&] {^NL&jL{1|!fN b~i9u- :LC^{ ePxc C B P T `  M D2[ N"   Iu3PQw)x/  ^  g x|\qF#D.CTNOo*|5%CfxndY./gjv#3xo !4vF ; iN - " {   i ~  ;!P=m d<2 4 ` -  ]  \  5  % W vX<yh9*b~vo`ottNmo@Q7;&\uuxZdj7yyo!ceZJ)_N@9y%XrV6qSc  U S=dq6?,="F*"!Sk{ {  , L { J+u|x6B.XP~Q!#PeyAg#KK_,Ruw2'Du:NNcbwb&`bLc)|Qqe+o4)A'X.: 6DrRnH"&-j0}     ,-^.Ludhgx  ZfmRH+:\-g.g?rjHw oZ3\~)c D  \}d`yD}C 0 F'M& xgr_r-|7{9uQ3fYu^h##JJffPDob9 M4M`6`j%CWj_|D" <9 AQ4r* 8 e4oL))mP9Pd q Q]Gf!Hy_8Z9.Z5*!@}C5c ;x,{{To imjN bc:d nvQu*}pHv\yX>%6Pe:j D8K2r|<*\gh}Dr778~DTw+f7Vj W9v/W  : V ([*5]!f\f?f# `X/Y&w13)o? Bu!<.-gq Qw X & 9V /  kd&s-M>><lr L jW D ' ~0 lW.{h5G.t 9&tsAT78#^}`Ng@F<+e#.#mVw&HvQrQ`t7Ju?PeQL- x]k Zx3rp X : & ~  `E &l Z @ s abPHt S7S>    _ :  9 op5R`/n,8u}e^3tA!})S)2      'V~o_g"ohT\/< < ]y?5 I - _? /;  rA^K|[JHFFQ 4Ho@#5gXyk++P\xno)RX2b :  D 3 \_LPXqY:.3 M V T J -  L &[veG 7fi.^8si913"8;Z[ES.L}]s^qu!7Pd )  / . Ub $   kpodf"rHZ*u?_{"5G_YBc8;_Y2^F[fH*_u9*_* -#j"%pv: X t ` 07Ei3 MC&~8[=HkJ!)7B*d ~ ~  i s, 8   M 0x2em ZdF)rG GwGkmb'9)4 Xp ] ,+ R 9wtT N7 s W   ( ,Y O(Q} X G mC. e +"[YRe;V187`>>4Z!,S1HBTxQPbP}{@ : fF-+ ??   B W T0    6  # ^ s  8 ~ k  &2  P t &G  :A 8{/u 4f! S-hs,>n>r OnK6lq9"S3 ^KVWG3f WMdM` a | C q H e ) 93  XdObFh)m c[      S? +}ffZH[ ?  A A".y'Qg)@+g@rJ}[d_]mH&&g|:ZtD \)Jd73:b{'\j ?c  S ]{?Fo)dN @W t 87~hTi>P~ZVe >gB.*F2 :   x M Q#3~N]W%kB~ZZRO`0qH 3lM+7r|gTyBR_ & 8ht&uDCDWutgBR-*6\j", DH 9    ^  r K  _  dwwM"-/CXsT 6P<x><ZqF[~!Shut.D#]G-VsVb<"ik! ^WL6+3 $#gKR?) ` j h   , @ t T    0{(.Z%2- : NG d   _d >  oahcw^[ -K ~r|CWLrqgJ]J]qq!r>}tFnX;ODnG!"MAs#ATl O   ' l>lG R w`}K]q|oO\g " B^ s"qTBj9)p!))nf'Q&'FK|S+u!' AZv)P  F` _33ewW&sJfyYQ  .m w |  ] ,   . MP<N t|4 x Q4!6K_txx8>>HJ[|idZZeo+7Mu;\[?y5g7t]-qfw:O a X a  F! [d/2{(qp3 ~ q Psd<, ?? {> ^x $ 3 Rg|M8&'X#";)TAKgW+Ke22E2B3e N? M Bg @   ] e P " . p ))i63 + / 9V L ~,87i~A9Wp~oB Fr,]{yg{]M"_Hx!c/_.f k `_ V % .iKJ4fqnTK7%CS3^!?OqJ;!-L`k%:AqN<CV7B+  * ^  ? #  j 'P'"W3R~X]SQD!R  n Y i: _9 _ / ) XW8Jgkq6?BXZ<3 d)&xsH|{S#VgKvO/ut2,h#f&5  $ H&Bkx1dbw9oy ]A r 6 S {  XSK u V %  ` % 8  / M  ?/NK c[cb u[b~K !,7,42/ )*RR!]  yrT #xy   $ XM<6!H<x  GCW:x;K(3 \w, CF1`di{i.  j L& T gfDmF vmib]h!JS?AQ$P(   P }@ T * , @ I " ) < Z a ~%6F.L >x l*d dE'W}~r di|9f b]~,GFQX`pT *d& }} :d8zf4  k g A / W 9u Z y X  $2*fDT{r~A7K]fWVK#h?q,M-pVX<4|MuN1: ~ZsPpdl:sWm~Q3  j   9H 0Ydh.yZe@i uPZLhe4  jG }  N  $ ~ g5  xy391 y5SS7xN-~s,  B 7 h # Lo m!}T.]m| % Ms r #    ` 0 ZqY R _/6NjOE R'#rSJ!C8,@,TdL %9_MWk9BK2"RG@> [x4Gw*  C  Uc } i  i k $ & &   :P2od"#r.i8R."s,"h]p|ZsE:2sr2XAl)H~CiHCD.|5 xO L_ @ \rQo* ?  t j  W YE4 a  M p  *[l  4  j  B6 U` 8 $ ~ j [ q(.NJ^s`sX7mxq5"#.Wb(iduC$hA%MbT\?5HH JP%. k X N X g C??ip|QY  m Z 6R*E;QHe 5 l#x@.0? O!SDfF9I5gPwshSS3vg,^Kw_GM-1l < )eE ak'G Sm - N#J>y4 : W( i u K " 5 piy@+ P "b h } ja  =I&1m  |-_)hM M?g.M..K54|TE8C?u 4T6ur^\x)WgPeY5 k W7  i i H 5 / uf2wmo+lS C  h K<#;vYiiLf.  h 8 `&d5DKmx4p"#k2F>yRc;{{O{"DTT,VyV %Afo Z . |9 qBR| 1<3< * NR S \)5  6   :GF3Z C*NW%grH8  E@vK -)7|TgM5)*+<|sPF@r_#_em; / ~ R 8> $ j   -  G 8< s } C 8  / B N ; 9 "814,A'+p"SJKBSCkmV8 '   N ]1\u/p * C I} ^ _ &cpNM&e9g'Nc<2c't.B-@f7j M O  4hsmP F B` # 3F3B+Y< j Feop !O!utgJB{\[d'sC}_qm u $~ K9   r 8 0t_?]q9nBN1\Jc~F|O<F  g@qsMb { w)!qpRT?H\>/wX) 1NN1_~ G;30nFd)F[4*[[4 d:2jlb&-/Cj4>e>{JBs7^h5h^Fr-K-7Z D   & / & 8  XjWvPFS-fHVM^u&b4(5{KtV9A:qEyF\\eHeo?G w  j"  y ;QKPoX;+`}o-_]H7fd  ^  4    O4+" I 7  k}0Q-.lPo.5If\x,FE||6?y s 4)Y p R #R <iD5G,s2M8MVN`%&}GF w ^ w 5`6tt4 +A($t&,`||q+GEwL1f'Bo!peSK,7%bSf*Vd)1?9LrKC,Du.?_9VK-6]y-*oby"g}^2!c``hH68So  | EG   K - $  l  A  _V D?,MDcc&ky?L[opV]#@8qW@7.l)J_PVu9cFBGAS?f?wm {je%YL`T?q)5G}PcOE46^F~/[ QWmVXAt>ym) u W ~ I |    v ;  YG  .t mH Hy-r)`"@\eFED/KK.!QA&|SGGw ;u x4P X  Tq 6\H  q ,  ! M [ :dd(c+vO| w~DPW@"\iZ4#?]^^KJT+T4<lGVGjiA|"6}]"CbMR?+{*T*- w_ktV7@6:e) w : U W r M u l <   DTQX!% 8Q4B>w|6~f%- dDRD'o F >Rq` y4G9Z {Wr"O:ybt >Q[>[?,i X_h3H j s! H <c NaL:Tf| - rd^A.L#NjvcvXD +'   Cpfs  7 ~J[,+kxd< ' i j T h + afR)lCQ}4XN@!gFgrT,dO X< &   r 8  {tjQ8;0{_LiL w\\ Lx <iPkNdP nY*rHR*Tvb<4Gg45Fyl#+[ ;Jv;qO(jF >r Y-2AlRTY 9 K pw X L $O(Y ]; w]x\ Ih M ~cG i TDMM^H%>xo4), ST~P6r9xs],"MJhpoZJl5<#<<e4y  :l   /R W W M q / T  8 k k  ,ED3PGo[ eo:e:C~ tQD,h^TSBMuc&Ptxs"-6#({pY&|-{R6eylX &s   ?2w ]m he s MR@h6hT|e u k T X  x 0 X? b[~5FV:T,"ASkg(7P_o*4vu6RY_!pHR Rjr"R5y!q{gTJT"TTpSe+m o 8 |k %|>)j(  B B  g`\yG+ 8 4@jZyTj3QZbl:Lj_%_CC1koX`+srK|h(EmD#BuQ4Sx|n ZlD2t)- /x,H. #PNM5p+BBqAr-7i8\?y4.7<oH  `   g95 [Qe5Qf+ Dc`p_})]j< yFJFd#C:X0.}K+m!RedhB`fvOn;'WJ9q d < . }  L  } :YA<T_Q'ydHoRy+xPHHpWxB<|B"wq6l_of%{^V4j-sE;0jTqQd kuhT7?p%+uqQ\4<"^L!G~;.(rJ+?Qw7]o#VPZF)L[^+xq #9fd  W ^ B   ,iRwRZ "A|Lrt6P{>py<8RmsX O / $ $<   * 9 \?3,RN nJ@:~fhJy[> 55gA,B@BqS^@@RQZve  ]% +56 ] q@ ,  ~ 6ei p"Wy:O~4 4e )P;[u)9cdbCZM8}WBT8qMD w5 D a PE23P(m Qwww6<H [?!O* q q kg]qs/7]XQ8tbi):DvV6xf !gerK-i#sT,HHG-WE/QdT~gx e` ) [/'tf|@  - M Z 8  8T / kvfP,B\Pi kC}vEPQ6#}i.7{LxT k # | ](+d3CJrA}^JR*(i - 9 J { K  {q K+ qP ] .B C :2-h/8'o:pgA.6`)*_y\4>qo,{k 6Jq)w+'+1+R9p`*xAE K@JfKqPj  # b Rbp! 7 vh)8e oyR? D ,  7*1HZ o | U+ #9"bB ;Q3! @P24Xi7k"FkmQ&H9ju9[o"r7A"rDq72  B r + go S I - M   9 k    \ B6  %`km F<%2j   B }   7 _  s%3r&X{d vp3AKu:g Y*lF((DX`$LAQh`QR o t H L] L $ / & amvdwGXp3x Ce @d teDPw\F  `% JTVt;j.-{qS KPEb)MV3|jkl;K(Z :,-7"A,<X `PVW! G  { }   ;  a h . X   adHxrP}8%%.csP^eHfL 9 : 9  &C } Sf/4Q: fhsjSW}|GTT#JAJ+(vNc7m\G_!3goe f\yf&)>F  L   P) %u $J a&J&V9$hq!9 /~ L6g75W%|56NS]r, Kc9 b;< pK8WC9&.%<8|B} DB WL L     T   sLHjXF) <3'L K'{k)Kqxo4dp+ !^WK:|)*+S[P^8-J|5R>HZ"Red,O s 9M ~M jM & $ a7g4LbW8m9; & j k | @ Hm~.A?/Jr_W&o:|"f7-"T!:We( u #  " " #   |%` G XDb3`~%Mc  j j8 M v PxH Rp\~ kmedyK.~Bt/`)8HX  W  M  )ZPKe1hwBd3kX%bhW>L;r  x ,'    h {R  8 af \ h  +C'u[!{6gg[<E'D/9M8L$_iLp` k<o \+5!m!f<kGdAMv K M  + Ap |   } y KfVjw Q|R~0N50N*HuR-c 0 / F  $*  A W w!wA>Wckqd`&C&C_t\B \*4)\Dt]s7r_qpQ~Zbw)P GR>3p??R[  9x 8 w   M $ ~ XA45H 49Q4Dy6r<`'JAjuPZPeZen(9M-""Z\ @3Y  `8     8   @^ "58L,#"!4\3 b7Yq R  M 2  D   : & : NZ 4BR?SAt#3S7srWt_t -Sp]eNL~b'M v+3r}Qee[hP D8`}R 9w & {Zl0* XYR  2^AKG{RGf / { K Iy GHPp 7 _q vh9@tOj3 WCWV&^[Cfgpe w/PG{3u)#SJRKQ<#-  k  kv:rJ8Hfo!wWHMB 1C Vh @  BR  | r R  s ~ <@6%&dF>oHq+R@>PP3:"y -KG7t1yDJ/LrE)ZbwvONN9/qyp4>4Qf6gh7,_?W h~"}g76!ft4S4c u `  i4 y { L7 .  0m *,#C` tWh.}Cru!c :;jMXs)G^6SJE{{"7-EM:2P:rt8!'OD[ d A@M+ iRP^"x% / :  5  x':x/j i ]          l (     2!PK9Z?gr^}."hiq [Dj7s",nJ JF g#kVKHD`85p. ~R wZOY a    :iw-p?!![3 9 9#  B $L q Wx l < i Jx/Z;lY}(F* ? chh){!dw* [bZ/;9:j'-w6 6^{Aq}$f EWR 8"r6 t L\ + "H ]\ ! H {4 6 Tk  $ M kGld X4 W    m " h A P  SN 9 I  K. } 2*N9gVK/NY)Qi6 r67_mti,A6MZ r}~jLM}&9.}%!C>P lwG]^D87r6qwFb&2  7 C  @ ^q  q]+\^f5.  " r < ` DY?w>{SHq5?Gdxbe9[8\NQr>VyC]ML#}Qu^f@rKLiLBL.VV}i_rS>3X:c9 jM 9'iQ?%g<6p6 hS !w166,6v N, R  > DD&Kh}`RH!TuiM468@:Vu2ZzfzH nb?pZx c ' 8 oh,QkFo' b &-p#dV2 A 6 t C  k; E>F3(-23Qx!{7k5l(Of:SbCB8&gV+-Hn*(> \&g/j7\f*hh-}7-^T|x7KT  M @ 7 gQ )R'~i|*?[G2 k 8p \ Ie r l N N2ayas(  | ^} $~ N u]tCQ}A,-*si 8 Gv wZd4b*`QLT}P2h u h  |r^_B tP9/Q o:3d C"^^L@WyO Fnmd2<&o6MeBGjK_Z<V@5G< Q X> a5 a5 :\{S5,J^i|~BVPZgH*; X  M  ` ~ 4oG+=9  DV>MDCD KD9/bccDw:/tNN)~B_0Ns}s_L%].LVL}8hA T '^ Cr U    @fJyg?+\   [  _ lFJ[i!@HA7B/9'i}+L]_Ro8/s1eST 8 B  t l 2*@}\&J@3|7-6;:qT3DL"[Y X#  C M  u4 S : m K g[*X% Rw5 JyT|h|]9Hub&9W`@`mCk//Ls/w|.g5*2 w l sD ` ^ r r KG <  L  ^ p 63(*|5qSJGJX S A[$4j[s Pt&TLJqRq SY6   ^ W L  j & b b <<wZkbt88-|.rg-M7%`ZdbP:G?9^_i.5&}t8%ih@+[w 9s,!yQf?w<x@$KAKku@k`}Zq<>Aw  ~ .Y     U , %[8<]q`oow  Tw P o  9 T ` &l j]TFp#x}{l<,-rhbJ5 =x3&Y D Y /  e(d&>%qq??RypR-pAy]?*-Z+ N  y x  3[Lj1!l` rl XO@ijBr/vfBXb&F8QT#.|$7}{W+Xy;p(RObKj.W W`9`G8- X Rw>XwTg+Zgoh4$y1  C?<dWu99&VjA\>)3Fo[?}sF8l |s~WxCtdR]N1 s tL i i +MR? & @ & M / uST&tB#Kq@!5o xE D: `  Ds?y-*n+5#5Y! \B,Gp* 3 r9 J  6 } f#b\9"_`cb(mDM}{H,;TV.7$."8s5fSy1~h8?|7 j L @?D[o= $ N8P$5[?Q0w_||^h   ) M r # .x "!#  ~'_ x.\4sb}Fj9tH+f3C6w/{J3E) a  N  '834J&wR+?yg)qcR83.6  ~ *   ] I  K L  \r~m9.HE<  * /dYFN?MA}`>bsh'gdyx{TV/M`2tQGCxC~Fl:&Xs-#&c*mv1PdCin%.V_L8%He w8K  !OOEOlv ( W  Lo } { 8|  ~ Nx!:19Q]B}S6}q@|* p3QHvq{Rx6r-L$&rk"SX!/H\BGDT9K_gP t  A gH* `  x1Ovv;t8PU8BU   a 2x5]  8 xGA!weHh@A7AAg-7y^QTA8'';dx^ r6!Qvk@`7R D W B .  "& ] ]/ " _ ^A   mm [ U+ h ?Cb\ 1 u <&C']rF}9byJbB7j,y mpfygiSr1QR!{JSq]]]JgTWH/pk 7>?4 *Geo ydbC^J+  ; : uC d B 'uvb4p ^Pj81rw>p3!mHc w T`4rOrTpfLF:o+>]`]+AFSi!7RRR/H:q@,^r-K8jod1D9)%_sZDjVK@? *4+gy!#r'j)Qw\Gy\\Rx~] )l  k  R Od?> g   &le5!rtjg-~u0j0{\8QKF"'SqKS?\? G: ~ KK[}s"A&M88_s%9DdQ#9B~KW3uJ>?xRE] / jr ^ r 2@<![d\:xXk!ubX:d3o  j< d=Nu}4_w9 9  )]m8wu! $M 9x#r?k]*gZ 'E@g*+fXmx f ?efGGJTVWuV}t-!)+:os&<@Jo)cv s U K L h 7  8d jG X(] Z) GFDkk[/.B@rp7  | WA T   . .%ftiZ<eZ?FFwAX$;d\b"~@ wDLtJ[uuR : 0 X 0+fZd dZ:YM :  C  \ o  l & N  9l P  { 6   {i  # _ u k(|h.&WDdpi+ytu y5N"b|s9hb'>5P\ 9 L  AS A D  :3,^%  : D8 }l^6Fyx[F YR  k    ? kpve!F%O k C_ /  $ 8Z L B e je D)vx\C".At6'?y6 FcP9L_i_`:Cd!q^`iXt`~-Ag^S5\>ZoF]* 1) 9Z s x q!y!4Je@oe=y!  g{  r! -y  U  N C    h   @ q u Dq qm,6,`S \}-{1ofLJt NGl6EODsFr{t 0CBZ7bD1>)w:N:&_W8,hJH &  \  l   X7Iv!GHqH-r./  }e\L ?Z@*C6VOwQRZ+!If 1c#'&LWhxjC"p`BkTN]' ' `k  s4Zc0yMxdWXY D M K h Z   }[   (#Cpq}u<H3X~BKJRpe{<2U09UgC u /}<3 @q*yuG#JwR bx/G .*Ke) {!HGF3P<Q   (  u2\jb_< !x{\S|`./(w4 9G2'./VL8KfWfY [Jp|JWD,v{EO\l NZ&Y8r7*kbL! kM V - ,4 f ] ] @r|Kk)*#R-|??Gdv N C $ K [ I { g 6 ^-  Yt/fkN:ux9s<7BFtBW-X)S+y"iQ/bOn3 3 QygJ]@SFC7+  ./ gO~ET<GY B L \[*^e[95 ] rG 8 EH G.e)D/8]-]y4(Mw%SgH{,D\\gS_qGR\tR\IxncWB|GXVhp B;i2BWfg F_o&Dp+p[P1jjg F  Mf U KO  W!  6  s   ,^ G6` <4"<,*g?!y $n;X]Myyyg?pyy?#,r'bY2\F9d O)oDW$T uVSh t~ |,  ` Z[lG%+  }I tz ]w#"e u m g<wjx<Ak/rsrC!pQpR5S,A}TW(53ixQQVGQe?xc9AFfv:T'#}q{[ED       d #( i M & [ i -h  q  H 6  A! iy `* N2  L!TV D%   8 Ii i i     _ XViW3:mxy]AV&v7dGe%j`bi#! 4oo H]K}bL8B7`PrJT|@xF; / h*41dBqveE(  8 T I , H   T B (9 ET8' >^HQ2 N  ~9 J  W t N(odp ]  _ ` 1 _) Q C DH8utM#CC`4tjJt_r gdw` eFF  a XOF{tV*Cs~PtS`!Af53 ' p Aq #)&wXm <o3d w s / yj_Xw*Zo+CX0Dbu; .K(cpCe.o Ve+>SXM5qH7:2uS9o8Y &R "!T**G\ M L s # 9  g Q    gV   t i  9V ;qf G ? 0  "  K XL<4V9&<X1BuQRZNF;`0C}>BLTV{B}ZK ' D@ DJ 'v>eFE1we4p]'e+<t_AYHv0 >*B#5|mb`tN>P3 O3dkZ[58K]H\LMeNX!T8}`81^m".bO7^K#Ek_j`HkGw_ k M  / M ~   `J )uE8w\ 4 k     * :o(PH@AZeR]h9/t3QS!q6\rV`bghhTvv.'L_BM8h"9WVA6\{y\!x3 \ D " @ sJ # ! {eR H8  -  ] E5, i|&<Nkeo9FVc'7ST_g1[_RXV;M&M~N$-@] 3 .`!~%L u. .  f1[P<mo   6  H  ZPE[fPA}C 1AEd(mYmFN[}\]F,*+#V_M~&&`KJ5:*xp<<'ND!4 ~Qi+TqJyBoW/w&w& W2L E63 wx2! Ng  i  a2o3^V`$~B!h"Jr"|hTJA#eP7Eb-|!*)6i?L/fRy>wmdN%9Ti@qH{(ll.E~t[~ysX&meV/!]->i84_L88c}0BVS9/>9)W~1q: Px\G oypQ>! wbhBLCru!XNuSX j]t`__G-^h4-: TJZ0 F^oJS 6> h~d7 <rVJ(v  \G(Ra  { 6   R $   0()GKr<@A)}P~XkN~XX/4PX&A_L""/N3V7'e*5R#{s6.2e8j#e  ~ . " _?   i 3 <    5 6 O  2Hwid?J,]g-yQ3C}ysG)} t4\"yMs? pf+GNPB]CKVT]#D  - h S d 2 "2 T i M4 RSKp,N`) :P XC<E P   h { p+f , , 7 K   *Q@.e!S,R]gq`5?~LTSh.~}]Q1(h2<`iZ\ QHm]:^B/1WW*&f]bJ:5< 1~*Q s[ Rxw1E/ET6f S Z  r M `< R & :wvZ  w<@Zd3C[8,_P{"A}|DSm+4F'6hBTgW{MjrBZqhVVju3l C ? Gp gi h" . F2.^sLpk! mRoM"f4<  3 m  ]H4R="[eZpQ| 63 # Sh5_AV&r+g)b(. "v:  M Bb 7E T KZ L fJK7L@`!PPPG[ egw6D"&SH+)>k  ?   s a i  w AMG$Kk -P 9FEDW~@*oyZ  8 s 8j 68_O[{h#.9kO Yb6e'%`4o\Z@o7fs]`io@" p QZw^m   4 r " @ " | M 7  G 9 aK'f@dG+|&b ^wZcnY?DiNg!!odWNk.uBLCDkPL^jNZk[RH{6KKi,/ $n7 qf5+Mb!:R  [wmu[`**s[hG4J*S6RT,/uW:HD7#[TdJ H<"/W.Gi[<Y9k`d+ e!4wD M& j 8 i B. _ ~ |8CXs<iLD&C:3X1?ubA}sVh5ot g)7_j!,v-8`GR(5(M6!m&bqC twW9 9 Z Wp !+8o31|}8kDDkV_jWmQHTg"HHr^Kgm+w:3Z'*"54B)2uj"@ b`C_kh:,wd< rT3A<<d1uKW8T-^LjACkj%i~CnD: w9s8J[{.7V+*pRb]c.&'M!},KgMS7~.#65| {>S8~y ,K}BhNl(K A(l_V}M^,4q3|:/CCRC9/k:GdZm)dxQQ[o+gFVON& Mjq,M{?N 3)A[#VLA06 ZFPnv:;- Dg u 0KZo#i~k8<CWlWdyH~R9& DP/> \5&%Vqt:lZgx|-Vl%itM)uWXL-wi[u PJApVRRfH?HHNRfpgy* -\ |! 6 gS  K K i 8 Q~jMV&F&G9pMjB }OKFx>{5+GyGFYi7@d\ sr"@J^.P6A_'ooeQQWo#5> T\ {5 6GK , _ umR|Jg+v oNM}P7"?>Z[3xxRe]#?H}R$!BJ+p6@@ w5[ '<CVs?8&{NHk8uWsG  o F  c  cowM fyTVG8~}Kq|H|oA)mm&FXm*eR^@W#3} ' 3Hxf{:+yDq>ZEnl W.<!K:j}h]*H*hmv N8  r k X" N 0Vc2W M~mPKZFq*<Q3?+7V~4 9}~j`Co *5f[<us? :4 <od(1N v 8q ,5  t 'X]`|'H `w/2JlOOtlbe * > : k  a c~i"V]ei0/((%2}vT"{9fi7Go5F)3FvHiMXo4G* H`\{QDe8Z N w  6H5"TLjf  < [ X [{r}vk !uCG[sGh+]JT}5:?!:r!) PqE uO   2GpE^BsRj`Ctk1D): aZ G p a;J|f}__5G0 dJ t , ! Q ) qP 6  XOQgJs \.W&&&h+: O` 9 K+7 RWdXE & 8W`XB Rg|F0`A\Z o ~y ig 7|  C\'[)[3FH< Sm  QDCC[s^|h D u uC V)A4}!,AGkye6}t v;SD9jsM 8hLV ,{ "F .  m k   GS0uk i k |; 8n Pww +}R`Y  ~  7 p5 +H+ 5 L YBo@bfZ5#"+2oz:q|h"8-3v]+q ZN| C < _:  L K 77 #r #  @ L  + 9p e;)l{ ar j8 } w <@7sjr6Yg h~w* gT_S1fSk.)[%8Lh{R' 4Q_ H_BbTP3dh `cn}^6wloPsq u   ae   q}O~Lctm { fE71 |56{]{Nt-sH5 D &? {  # h/ | K4 BK t kOOuF~@R9VAH"{\^ M_si5omb~9CBu}i%<`xGo[yKTiq*CZY  e SG4* \ S A TArtf-hs&:mGv? S | i $  . j N/>SBLD"+[l}7Hb a X M ` 9 , 0Z:$!g^#}L  t C _ _ .  0E3{-mq*+@|\f??5S+d!HVHH?pYp ! " r 6 { W k g A l YG:kM'wh{ R>pk5&{%._`k)Px>  @mX~"]5 Z O?i?o%  `# 7 LK #  sL  b<+'ZHQ 1oFkDKg?DGQ4S\@-umLCC),y!3FFYF2PE3_f<besSfeui}&peFo~p.]ATSV?j djmTh-GmBlW Nb M W `5 & k"chZ i~9GD7l'c@""lZ` r7J]J|"}KLNY< [GQpxXj?y%8w%YX%L |Wqy*p+ & .  h# V St g S I I 9  7  A ` S6@KDd M >& TJQ{J6-h# j4 G b^?1tZ^O"JyhGWC~dBBf"#VM`ub :m'7]tVCh]]+) Y a  X a 3Oxy6>?SAPoR@7k_9vOY9:&Wp~+$iEf,j#W_C8[l\dQ1' eoFp`f?fKy@H\?qL~TNjqCPn>f?qJ"_gfWNc|d4?M{foxy 5:]7uLDM/PCeQ[|[g fQ4!Qo)Rw| >5 fG : u   D(YEWVmFupA\V/Xw[!@""6]T5 fS<'c I @ ] ]x  3 EQp t d5oP~S^ - ^T aSG 7:WQWe:)$/rM,p[)DCmo p!e3gKdP)Cdc k N ' Q3Y2c PQ!( v ajL,#C e3MNB.S`|L3tj~R+_!+7pxQnwNs-C"q[*5H@"tA[%r./bbX)))PC  q ! H[\+ I  i[ v,-"Z*NwiKx6QQG3,Y^0}/BTm Z9:!vGZ3  - i 6 Iy "3 T }  pY)*y5}t <{RKLN&CexFMGTBAJ<    6y  @ -  D  7jFA{_#W/Ls&]fVc7-^8MRQ3d4m R+JHhsj?kf1N>M%'85>)yZ a2  u ' :l; .`rExcyP>5 P49^ish5e<`|iiJRioc!  0  t N     U  -  au +k.F/D4yp*5G?#Q)Bj`jXtDj N D/@-}C@b>3WD&T@kJ[r j _ gj/ 'M(GA+ p Q &lm D    t '3*)H6Me5e"#LSt~V -"CJjxgW 7H Dm C K @  ! j g U /  F  J  iM 8 Z e & k@"c@2 ,>{y>4GQ) m  U h: ": u?\9 .  r 8  HG_'!tc]>k2#{q__PW/ XXVqwol  aH D@dq[y*D) M`\ W k = mO+N,a-;V` C W B-"p._HD NX  kEPF HxJ H.]`.CttvF~F&D1c''N#8A :   wl>   9 s #  I R yH+ G 3  X4hh1 Wq6" @f K}   6< , |  _ . [ /{ :bQ[Q[o.&D3(eEW D3W@SV@^g+[<u5F\&#Y?  U | gye*5J^4Kr I  H G48-Kov ' v4o3R',~%^q|h+}/koy ]{i_XYwQEZ32'/9BS^J<[q mG 9 @ J ~{ ?H 1Z"tPM( D q  8 8 ~ } t / up )QPH6A% : ' !"A).y~Ju:kyu"7Mj9$_&`s__`@k\F>? gsn0 FrGZwE( ak ~ } C / ` &)  D dfxef32L M N DFd*g^DR]\OdPFm:LkA9<:jM~j&u39G5:!v|[`/o/ZOVbhG#.wi.vWuvEXmbQ9%5^K6Hj&>oP&wteLr%k-F#L7Bt'JYO:O< o~Hi#q5yRfp3!v@'.s&X+'Q'03.:1Sx;' ` F h e \5 5  ! hy Lo  ue^!b5H+"#Btq'rH%C# R"g?6@upt>5x>P+Xop4xP5`<o<+@"X6g? ?+Kbi}M&j $\ $ . u / h u ) uLN'<[4\J?f.M`>9fV"B> n1<WFdtWEWkMB/Ai#?*9    ) S  9 ` I   &  C  :;#FV.ot '5dJ%t9DdG{7idLe-F|JHRyf!D968#}{SJJ)JxG>*G"FSlut:&!h4W{gg  u   &S  Xp2Pl  W" r  -    T - ^  u;6{qr8JZAx. `4/Co~FVmi}>~HMqC-&Yx$ PGpBj`h-]\?f _HR\ ~oA)gu(K  0p o(Yd  ke x : XF < ` $ e   s p qJh~i*]&hbL)C /!CRQhgqy]eT X}  9/ k 0 >v#`$^kH76+"m4 0Z  M } ! W> ZuWJ_R"^h$6+_#OH  F M1 B   h ^K Tr   8  u^rTK|@_V?37Zw74`b35H P\|K.&;ZFiZAdrC3]+| \edP1Lr:G|os)`NJoE< &  SpbeC<L]-7|rT3- 7  C2!iV_8`N<[tQ_{]xPk'cv (c;C>f|J{CySrs9:/:3Z]ydv:&.RR! ` |!_DD_P g e j4 o ?\>3YY u  N t  $ U  _ .  W /  .  H q T| 8 TC Ak $ ` E!mX'DyDSb'8jP(HdBSNL%Bu&_#@H 0:[tQLG#6Mee1 M  xd X L ,uYd/i Sh i \d,&1 [? 8qf7D FbZ9OBT f 0oOkxPj*'@-h: BB8hVs($p t%]G>  ^Y5 0w   - 6 H  \ 7  _ M(H _isSg| : 9 }S  9 5 WwS|V$_bb`g?reReQ> ? o4"A\J.Li|-%]X+\xLW195#"rAv a M 9 xL@>B#GO C |g{OHDaE_h{  p   t  3ll   J  kF*! , ms.giO9-d9"Wje%c & sy , , R 8P & QL M  M t / 'Yj<9oGLGAGqmF(   8] #  { ] h # " T B  X~k~ZqZE v V&g79m_|SHpe]w"! 4*y7_$&BBKi]-@Z u R[o e OcPQ? ] r 1  r ac  <Hk.{]?e53[)Q5B52  ay@ p#@gn`bsIvߤ~-av-qTxb}J CK!N:>2  9 +s3v7vAc( Rp4  1 j _ g ~  ~ X t  R  8; $  / W uNdE*,Ri s0#W5p cvg9gJ6kB$u~.W M U 0 0 _0  ` rXFDkeSl\8 PZ9)7e*d5@  ki  u 'N<[qbTsA]RqeA8/0PE[?e\+AjuX|m> }iE 4\ SAg@ (ZPn7wB,TG 8 6Sc/D1dG G wN &PLA gfp>@ _mW 1*k+]s$\iV-@hT_/E@f@Sgg'gYgw?;\yQ<*F928`VM$-Xd5[ |NMBiL89rXS)pe6d}`~8p_%%H j/_u m)S3G N  qTid`bm2nx y rR y t Z & M  s  7 | 0 | K ^ S M5 @  l@GT,_C9G7t9v4-v Qw99mUF:7+|B9+ [C~k_ly:)FC&4D 0o <mw3o/~m k  p ]  $ &fp ~)) G!R!Hp{  Jye4 '' D5|^q#\-T)cvZv(3435  aC D ;G rtyX<Gge|_1kjbu':N:DW }-,R@ 63'^%F, , #7 sJ+x XE3#VCk}.jZ9 +u54`i-& J|"hAT]d-CrZ2>u)S) x4R5y"4Sg+t> D[P8Y "  x)3(G(Y6Lj^9>FpyD38C"_+QdFv~ :} !RDm; & _ c 72 -( ( Bc t; N2 3@7hV{WyGb: b`+V*Fgd++";% ' a j  _   \  L3 B  &2 N;2<}[>RqMNvgTBt >fj_A6[i5#,S]0! o'{ V< C  h G @ ^ #} ~ M565& m7vp 0  D   _ j T a Y      R4 ? q |/ 8N d+5h!Tchnlsr tK8.o.8.V#@Pf*i"P  j<_O##Lx ` 8 X-VD+ H+pR2 D  H iQ  m  DcY?Y3{^. ,,|&bEQpq^TST|f.L.xHMJb: w4) TQL?`qBx>0<9V86 o}!S3 F W; i  C j   P   A p%xL`Ca w6: ~}0,g{lTiLj7WoZ1/Cs|3|rT.wXk8Xt'DP\'gX-LMMAHhq & & P#'hJ5)R! t K t R J DLK-BCZx : ^  B&  7 h y ? Rc[4AP9681l#^Aq\*rh^N}kMk9xS-#|8.4DNbH 3: 4xw>O[:)LKGXX6 j tV B7 " - ^ |( r } . I   g4 , | % wGF\]"B@6{5*b;<C]jhi~wN oe4 ]Phe!qlh}[ `w&&2V#M{.!*fiK{H M  | @  6  @ r F BF ~ 0lZQ596@!]+T}8Z.DVj-_J3&,XZBMoD3Q//Bfu)>Zq""FACx\g uSL#2+: .:r@TJ {<q9_%|ts~M8k^ujPL t d u 7t 8 T,#xxQ3y 5{+519:s2@q]@i:-7hqrK7,7-TJ{~}B~BPX-VjB8BAjyFo25 0 ddQ3-.j bCs8u}v#)=,*JRGJooJ<'CKp?{q@d32fDuCh3 ~s gFWh+*Q]}Hi M0<#;tnp 6pJ DS R }l Q u  a :[l;v{7<xo_@D@H"@?[~NdZs.B[?.689`sH;y<QR_VC&{Fp[`ye]*oE< C o =<oofb  VE-1r0[}Tx@)3O 0 & 7 J?ka ^ g NR]) *d$i_})#7ALD'YPOZ [\R,|hp C#FYs f[O\5(N/{!>!jg5#  _ +QudOM8+G '  M    W Xo-cZ+o{N^N+FX>2PBuAuk;F8 6V~E2unXXubuC/XjiD `#Hm : -rX dr @ , Br K Rew? ^ j),9= ] L\ +yA<: ;EuCpsA76\<?u( K#G|JMk&jv.J777.K|B7S*gnk7VQ<YulP!  XR u   :57S#7*7    G8 sN_'_  C : T lk!^M:Mo&@}NF6#LMXND&;l %A <Q2 bWh^8"QD~g6]gKj{'Z~ke'xw[3:`LrT / i  | # _ ~fQB)s-pKP||`qBLiA{^>Th-7,#wG: :G3Nf@ W  _ ~3 vee 6Ve.G9C9M-u<>K\P DJ " h {H!# 6 i /l<\RLyCobjNT'D`%`T~g`qgN@*6GqoA"F RZ'Ye() Er S  '>)G<W)Z{KFWd<G"ps]3P[+qV s*).<|DirS X!L ? k  .   `  m $4   j&  {hEEOl D W |  LZ&"fx'<0 k   f . 6 _ - W  3 N rfASc>;;{XW|jS]i{{6Jg)NLx37:KC^"RF : ~ .   L  { Drjp8sK&koZ h L CW Mk 9 uP)Z]v["e3b3n`E/NE7,!t^{pGWA&/E9  Ddj?HMP(M)<HG3;H 0 { u /l P   '(T}w*kHv $MkEZoRHB/iV&WLq#ewF'(B8fd%,[.O / SAGG~8 SL # C^ J*RhV!%}- p e tm N    G|'O)G U_2/kB;`2D]"G8R/(Sg QEw ]B.M5  3/b)wc"@}^"3\K}r"]T2_R,A_2i 8 8 C ` r 2>*Lp,x3o7|Bt:?4p!Z"1/o!#qyN>Nbd0<4TCy~p   KZ S+'Wy   ] Hl<#RB8~9 `&/H4b1NN|/+}o x $ c - 0   _(  CR   X` :[y a K A CK /^ WA ~ ~  K7 +Ls i  g"9f4b\{$d4J,iJrgRRmfCseK yy+gB&uA^"*3.iq?[pO \ y 5e7[Q=G ,>yQ  f +  '{Z K,^-hTAhsK%7`Arog}}C~/]McVwr6C[@ G}sips\-Jw)DXDf+\  , Iffo   T 4 yfE!(gZ6{[y-/4pmw3>'kkdL7Ybv{F#_lc~cBr])OkK)V+P(^ D k  ^ qg ]J~|NA^|xKyr6{J|qJB690id \ZV3# a ! {Fe  5[6\- @  Fyg.'Eh3t4O[AYvF:C^g5oO ]]q-{MHV%.#kR/*_|*m u &   U    #p  r . $*  &j aO>!!.Ne3oG d;0~BC.iCCWRh.h|#J_X(nqA LOX:pdF_ZF C2 ueE$sB-TT#^:s 7Gs[o@hPm' ~CN3m!HJ{J@"-6}6`6k] 6bB/}N^,PT%*]36{ ` tZe5YY  EQBhJ*NqsK(pc$w's7+>,*hifX6w78)} X<9~/M~[9 G)b6p3& uA<NM*4"6>qKTEB\r^@g]ST!B%KjDVlM>o H J45 RSjS;M 1 Y | {k~+ " ^ i }P #   $ Oge!#@q_;XmepTYiO&;~vPx|T,1{+ixThtM:WEic(-Eiy~ 0 y-H\]4\?Xe~   ;p *2 vTOE4 F M|VNt|i&ZLx!3(eNey]! "3F4GDh=[^rR7R7z#> sXj*i$ri?D N  <Zl: t4x49?]J"o ^ K jle\]ik9p6-hsD#\QZsge D j LG $  t _GyR";# ' u  k a X 0K$Q?xg1-GK"wxMr.fkj"ttDc 22cFlZcYXr  !)fj~ |1 .D _i.uWFi[Q{L'c%P}#AjA(7|>Ti( t h4 Fc+FqG-f g  y DAi_h.*-d,oRgH?\f9.q4#8d, '$ ` k  A A i: M/ %7FK7$rCLCbu`~gQ8cr,?f3 Ne B  8 h | 7  iV  C  R]@6F,GSf6-\G"w 53  C         e6A_/b3'2}6g__{@A7L7L,]5Q3d uNVD}i:'}tkm<XV><"pF2 R B@ r Qx Hm]<7QT K - - hl[Thwg\Hb\8 G+p!* +!>5ZooP > \ 6\y   KsNe?T"^AT-r||S?>?<Xo`5io  "  # h  qb ' r  k v<X1ksu9Rc\  - x4P4  1 Ik |D w{46cWVr \A'.j&wR3)Npu?bb6gsoHLD%.K%gpeBL  _ iBm~)W)9 k3XX & t C r BS H 74 h d  8Z ~QP*%yF@hBWiGs}5}sV##A-@g+(~sLDVv} # C H  .   j  ` KvG,C&vE`vrT?"B,B % C U u r  r> Q k   B ti   'lEvbmWL-g{6higq!!}\ftf`8{KS#BNW.i&K{f^x|<9"s7LVb4R|^#+ 6$|FJ!oC)6xppxg[S37l 1 . 3P@!R 5*e?ZMc k]1yyJ-0 u~^,f4>N.s*G>A 4,[o7V0tC&SH:oZXC`55j\uxl ' 8|  - |- K, U ~ X(3[xS5yp  _ ]O N'H p :_N5li`PBo#G->p.R$,8|sjcF[G4,QR G 2L'9 :8_.8we.s?Sq]5!Moq  & 7 {[(5p^pR6H@Ji 6w  &d[4G!S5-BB58.yyx)&w/k~ZjDw"o#yi,^b EdH4P k~57}8Wrw?!CBuSv\(f\H@S|xK7rgER QZ; Q & tR   8 sS s   8 u eGGq |4B>q.k2X4D\'SJ_> M7fd)~TX5 k` ~ C - ^ # F ywV9X}x9pb)Qy LquXYNudFt- ] iZ $ `   N,{(g]<]S ,TSh^/@3D>6-Asu_%ris J/Wo3iE!kj$L"E Nt 8 ~  T $h  W 8S.-LsN-qT7A/uxD   L - | A  u  8|  .\ M4  )<3J Hj<'L(iy [))BAv!Z3/!}"ot3'FF>]yf*!]6"A4v_8 NV Ns X7Oy[FmwXW(sYH+GH]T#)r pH]@G,eq FPb?t-]+ HPh}/To}T_L_vdLLj>~&4`+`rq^\F~BDkXX1V<4P#0 bF&>\V#Rg4df0  [   0S8W' R* 6HQPb1(FouXFQ+,gjv!Qd9l Lu V KJ x c t h h  i[   0Q2   DwgHNXKkMLD^4@\7!V+\fP5p o5w+:GP8~k,\@,Ve,yK>)( 0 /M # pHoV!m8{GG    o   'c<S 4P.W%&M i T_#,S8>@x4 ,"rK_V&bs ?{)PLF`X /x@5HGS"^KV|}VV8J]W{D?+\+qS@."/:S@O k&tTZ},yYw*lf{S,@^tTK[Kr0 EY(c:?H' 0 # 9{ `     W  i i , 8  &x@!*. Nd 7 W | : U v3  it&8<#f-TBVt3))Qb\`q>1 cSo '!h6+AYb  ~ |  @ qB _ g  7  ~ &Z[!,+b!4>QoxQ[f[ * Me*   / /  aYyAtLdH}TM-lp5ojS~j^e@ y-N_M-Xwe)yXM%r-^WMW8`MM45LHl '[ u< u DB26pG 9A  L &`FjWEW;MFt& KD W5JN-f_jCxMpg,{H[n jx'.  F e[Gg*typ"-MK'QF 4Q )dm@ xW%F_  ^   r A K8 ` _Z $Q `R q"}K~gHe<CMLi__  i` 5xul:0uN'95 } K6+3E ^Ow6*5C&W%&qQOt\ "E~M)sX}%^ 't:_thi"Rxp &  p!oc.t0uL e k u $X Dvbj%|*.ZdRF>W>,*1-^9du;uE27{JJ# x?97Dd?{qdbB~t~ 8  | # | |  |  76/-"w5<f2!6?Kk hZs[Q DVh7$y1 R    2eQV#KG0!Y Jh7 ,+q|B>j)WZ~D;98Ap^.]"  -&`kt9[R@ #  'cm[ )9 a &. 8s s  Ah*33 " ^H7 "  W_/FgH!v OZ k,*44j>  p&]J);9 uN w  > D\{xs?0` 1:eW.Reo/F R  lpQp53v5p+ ? Dx5qJsVh}K#T#K7:L ) 34+TVN!J\Nk&1sh+%(/~18F|gdK D- r ^ W  ?  - A ^4 > x r A d Uk M /B -Oe 0H  W  B ? f  s   o<5%*Nfp|gitK'#|+rhhEH*?F,:K/_ARJ+ )l7qL~k<t8_VL8%ij-KNFrQ{oexw DN`|Bs E K | ] { ?+)?O q r _ t    r   3 |\ |  &k ),\CR, L5*d9_+ps[.#A$@/</~62Nv)xfqQG}Tm ]{^8WJ}:3}4Zm~.|S\QdP<E[lfY@(`Do+y\6JGFS:696,Rho} D' ;Qmp*qjPXY83qZ! if>bXkHV19c~-q5LK8 3 IG { q K 7 L8 jm@Bi37|ZJ'y4D[W;/cjc38x8g'Lr~.XO 4eG! s&J+,>4749X<C4t[NwYv$+81A~]y]!?W,AMLttj:]uFoXG@ : ~  J g  |> Z CY%^A'"Z{+<$?GD+Tq,%+``^G$NX d[|Rxo6 du_Mpho313C.x \f[)JOA  / ~ i 8 M jQ:mgh^$&j0~V.6.?j4FXdk<r*]%^^q|{^tx' H,*g3oowNLC'u'F< vv vGe8PZ3!ePF RHK.,^.tQGW(D-'Fbk 1  ) \ ] CB XWO<dreL*C *dGlT?>Y`+XR_\@f ` Z k &   9  p Q  kZ2P[3q#j:}qV$`Y _ lki$%C]')  ^dN-P~f%y#J\\\kg* `bDjwZ.L}XssiW_tjCMDd >Rx-B3~GKm]\ G WZ j t. `A S Y<Fepq    0iLB%W.84%.-8&N`DbWDLp*rd.w [G\^G'7<^ut.B(V 18@\G5  h 4+y=of) k A9 L r  'FZ / ^u}$%'Z* { S E`[sMvZ>)F2c :[o=b9On0Bp/C/|~%?c DM  D 3Xoj\i|gpSQ   W #% (,|^sr-  c x i?8y+V[5\+Ym8:?BBsTB6j!\R]7}7WV'BLc(Tq(5bbts+QH  . h bCX%/f v \ ,  s C     B q A AB /    T $ W XY<5Q\fi& x! 75L"^Jk4x3eee<[H?:C]7fLek'j\flX 8 ] [ 9b /B /  )  N  E _ Z   !  ]  | | 7 U  L.ot7/k mL*+6^7#AG|O h! {C\i 6 r .3 l  # @ fu I ^ .b c.&[?qT'Aw<?+P<)b31l$R]WAe-]_jb'3'(k t M . _ A T  |! p  4   I , "  Z  hO -  9 L    rF 4 8H 9g s|CuOgrnVo}..K_-T#|g,!)Gv&"ur\F +ujqVp\HZ   } | \Z G KQ  vdG5*[64 rr 6   t^ '@D9dQ!&v!ksN&X evlEYO,b*cAuqQ5 ? K I 6   ? A U j i ^ J 5  }o  T m qcQ N  je  H q K W :(Fx\rW3eJWlno3:fd)`@'pe`FL3rT^A8@$_H{*RQPmXtW?T[x5 *fm]2#L :C N N  ~ : . /  T h  "{ S I   K - 8 jF 3 x[wGGodLdPj*_?"]{r^AT_Ws:.yj`sC%C~rA :y4Z :]pN;3  0 D XP : u~Yy l m 8) 7  ))R ?< P 6Z ^w _ mw+Z7)*M<G53R"dd]|3X jNMw%-H-`/`3B@P?f!d*h\-}-H`WtMS# H  o  udqAV*`d.m/: h,+6\T`p:h ZQ0+qW g3XCy@+lo+jJ:}%$eB!"K_%._&@^\>&hy" p  l i `  B  N E uycXO\@ - V . K K 7 >Z`KF : x " T 6} r . b(d@G\@|4[r,5ovi eN kuu\pgi~'7q-0*F&J7 wt-Fct#x<   s H A h r, ^ | T 9^ h|yJsW:eZdE '\  + T  |\ 7 je@@jpGKnx[ !{WLhA]AHGJ<uCjXf3|S C WJ<(w X CG p q # ^   " "(   |r    qLtg-sk`&Mi7_"q\*[d _+ +WT30{-?Nx{l iJ'*'d9 $ } ^ K_ U t& :uRs9&}T@5* J5j%`-#6cq  B {p\\R 5   :{ QdiZ ( 9 DN u  : DY-P!D*gBcsV8SwSoHxsdlv3i"h"|K8.~Nx"|`lb C 5 ] r .s t <SF3 ,'c|]Ho2M'"Y+ u[ M }   S  j\ k++{hrf"J-fYy 3,n#}N< -)V)oL[yJCKS vbi~/o8K{fg4:(WZ?{o)iv uk  ~w w s : # A&   s  uAcr)^Akt3S7VWBk  05WhBL8TBr_rh-SiV_s$!SHu4%<b[  to  U  ic $   :lvF >?*4 5[e44F*l, u7 C ~ W t ' F>4?,Grg :eYn_))ZjBh7]D;-uSp*R @'c xo>w!bQ_  +.?p c } (R]{-Lyj>/WtLV|>P:HeoD@|J^#-o|J\W9y{%pxd)1\ ):?uo:4G!@r/kl' 1  Vjo:~ : j  A C v*!`*]]J"1'X":]bMB->A-s /: ZPH ?p7i%/NZ ' W U 7   K kZ4V4 dyw@F5STS_MRb3M_ncK_"Z  Af|ZK'}r]]~M|`MX&G& C ` c ]Vk-mo[>\eyj!{pGtm6.W9.v 'eMBF".[7oud<}2Y : S x    t & C `    ao N : N i  m e MR 9 "  k+o; kS T  I1FZ1S ". 8~ NJ'SY'8 / WwnEDMs\ 98?ojwr,6GKwshJT 7 { H  :  s S & :2  K  b  . 9 u-R##@P+4H4g[eAxxe^G[@[*wHx NH #  S  Sv 7j) M}]/Gku3$ K . hf x KZ .X & OX3FQ[p{g7$Cb~/cb X&`tg~k B  S3dlP> S { t+ N;H,`,ymbB .3Mb-F HA}!?\\H?iZx D Q  / (3  BW |1 3QZ# 6 } ;7xh7"@o*KQ&bl>x!p+{?]pS6*KEV`  d]> Y ,\)Q)-{w  s ^5 Mq i6 # hg  5 f  G mmohP^fgL{H-92o x1Q].^B~wi"?'cR|t^? g`\}o^n,++qHqf, gG\%  { | 5RHX!j}|""i7MDXf N>w>jO[9.-JVVrY2m^\"[|Mb:5CVXp> T=`p-L`M h S   . ^   W m D vvF,48#F` r.M] C)OcSNCBN^ Z=tF7)x( b ~9 } B ! 9 l |?\)kBwe X_^<8 W r/  +9H\_\R+ H p/s ~D<5o5 g r c l NX4}9KFRN3G!M#is~`@JqSCA~1%Vx#Tp|+]!{{ P?:+?CpppW/e1;3Q7pw@TQi.  }. T"l+a9FB8D$`m 6` P9rL_`-:Pge5!fM f\q`@XS(g++`Q24#  &4  } } . tR k/7r~g>+|8jkLXt'}<9895 X  B 0m 0f "   m G +gph K h i MJj1..Ws34i\#!!qH+R+{ r' BZeHL4d :(wW5t!W{b16:bbkdO:j9}4#8qK6+H\45J>-\#Ag^|s^i/_P| Sxy4y ?[GJ\6|7_dA4p6gg|^5r ZS +jo9 '3 )?M.:l{Qf [4[FPED j @m)x,bf : M u  M' & M 8TY 3doqK,L6/1VmF y? !4?H@Q#.tD8#W#] h   4FdEcZ? 4  g#i'3o~&\'w!Hf?f]GeE>P*o6HJ}^ssLN3o p!XB#A|xd@+8 ~s"3 N | 8  x   x {  K } L c 'l#`em+{7N:D [4] *PG o<3eHA$'`e`d*x *>QowWLET]\ueFbWK{y~u b4&#^,\8 D jB B  q Ip {   I     | 6[ ! q 6  - 8: &Fw xT>d!Q66AB@$fQ3'C`Fuw Om dPn3cV/1Yn1/6sy+  j  U  `  8 ~J a>JF E1P N W/  . s  T  5 f /H !  ~ 9 q  7 i + \VYdB1Xu]HeW :XN`/DXZdsT{/w jT # ?F;e:<m S*  MSPKK%V9_bVd8,rt9t0X2 Pex5!_5y>d2~~8sTTSbwurg !y ' ~   " g + T _g ,>,  q5 t;C ~ h?x>l0{lZ5 f \ ?  N6 {-M&5<*/5]4+q+!5>ZX[M_lXxC$# , ! i  A A  }i - & !Q^1)?<P3~'XjP7Zm{? wZ  ty-L8/D`m1w?4+f*)Djigy>3 XF  u N\g;Z%qF|>%tWQ %b#jJsK@>poeRR#s}~~XDP G#jkS'X8Cih@R k7LMA%%~bBu7"F H  hc  ^ _  . j B/Z ZH  `X@*J4?Zjt&r#Cu&o$5-@?V3i9yQD)FD jsb#`rsH6Sg  hN`$}9gNS]gpg { _  ?x\ *>G?|#T#A5}|WB F)ZOsMsT#x*i3#1RF 'W  r _[T"  R  aQdpAt (-7HF78  |'w0~ spg$TYVQ T]eCTuBqrJX> MBXIM3DB._'e--7S-+^AxG}L.8-.%B&T[\f*p>  ~   U[ L   4xG 9 8 Q]|s^o]7kxC4*[@d(N 98 K<]pePNM .8.BLY_ is+iV"_"_V!L VbBhqt\*x s   B #X W ?!   C v kx9W6S PpJgKA@R4<VVL^/]R4G/Q41\F33PQ{5"h_|K,"y>\ FXO&Y;7*\"-8A//[byJh#]}V?_4#[|xG@!f,Q^P-:&j|@.8.k8~_`*3 D< o M ! q r j- } uVZh8`:3RGQo xQ5{@g#-_PeA,RA#o--m-Km J{?Cfp0RRfuf/R$??65??N"]ReF  N X, 'gOpxmB1MbN w`P)ud*'fM]-,!,G"oQy^t.HMXo5b6Nr0'}V'%:Xqjy_TD6~+4Pu kZGvP : k; E c Y E a ZO>Zx^?qbAVd< eHqHr^T"||#.9AN}v W 22cDJ8hw{NfpC4Q[3 FQ44e DXuWV^k   j jp ! ;<{5wD2V]h@Nq+1f3y^5gkA}]?*QQ,7yLJrDsjcE();o\-pJG?y:p?"+SHB$KB}7>Rqy#oW/7Q9 t 8 $+s-r " S 8] ,whBsFW@7;dPrnJE' 6yR{,5DR+ F,xeieQG w \ 4,[FN9S$-,o<i/^VqHS?p>])6vr# ' NB X D EZd)op\!q,|Hy8'oy5f{6hLV/9':0D~&Lh8sP.~/u 'D  Ob\96$~5}tv((YvVlF55G"Arhxr>p6{"pr-#FKZ<"q+JTb8M.[fS+_* y5"P)K_/DF)G;NhR*ujt.KpKQK)^#&}%sB|\_>8)   M  i  % #i 7  | U ." ]  W + H N5T#9o:Axd  u &  \Rf [ gP E 0 C  d } -" } g ) * /50  d l'{|i|/,[<7. 1DV'7 >k!W_{{H8eM)uCVs(7Fr<n";?f$fK!{Sw#8_FwEc"r2[X6'ruW|k]\Pd oN[4*sA,yy*)  & ` `  \ D c r  ) _ L i; . H  D8\q}rhsjxXx_:MudOGvY2pHZx?@yhx_3s9g7p6 R e 3+?'u mC~iQpv W / We  w--V5x;w;  0 a Xl S@MC iy6f]|-]#GG0Zf:MK}q?[{4y>fdDDWPx|+@@PJ Nx }     ] FmW+q~ _j+ hD m?h4uP\*HS@h"T^^?|6FRb&wM/XbN3GFHJ Af@Pe>q4b`V|S3H*gdF   $m  x } H M XOT{`:&t3ufot|,!N 5B/3! ].}i,|6g8J|6@6x,m,2T>'pw>+]Vr`C9CWM}#$Fl[ 3  K S`H4%ZBwLmB%  # jM MtxB@-5hfY*e \Q[7f63A_WNKwJo?p @mX,C~5BG#QQ : 7 +x(7zf!px Pu:_w T M q!yq7x<cE :Y  `u j Ws - h|r"T_A-dG}R8q-`97KC]$+-, e)xG' `\+L]7|"Jqb`qT .  ~ B/ s  s:   XvZ<)Q+AfA[J^:C*x[*W5JNhPuFQGf{!K"}8iT#yxwpGZ6R  o   # r | h3 -   6Ks[u} `'41u6/r^^Tt79ki1CdXxy @POFx~Qg6P@]l+:n;`sTq"\qowD/_-rtvhP7)VZO&k#qMi"y#  B U  ^9 @ / ~  .  T "   Bh j BjmbG+?Z?>G 5uWVA{@"y""xe*|KA-8Z*s_pBH5q{@`tTrV|g6>x)bu``%_%Bi8.MF*i& qF[T*^r3 Xqqp> ]LxhO 0  a  j ( P >  U }  4y8R)ok qtT8i"A,H 'o & V 0f SZN +F5*d)-gkf*.h!"R k g a- O DnZ n8'ZLrV`kHPZbj 8(TRZC\t+C{D^_jXlP3)FF3 Co>{ZRsgv ^ W . 89 0 ; Jcf y x`) .s#!^eJ u 9 ? } G  s O `  N  ~ .  7 r 7  p$o0?woN=2>JAs~~*X.\o!!p[dE$(^ \fF?/{ThM s S3 > 7     r ,<  e&X: u  j  0GTZ1*8?J^~$CV0/ ( R'TK9ht@.3:`/J clAchbB9<*ZGL+xe w 9N 9 $L ir { p ix L $c  ~ M   u   aV<GHJ-7jP ]\]" ||shSA[A:T|>B ~CwD |w*|}0DXu2~vW B3A169+>FKX/^|^^7#KrWX,H7\fBf5`/qC~}8#`4p|s]$q"~T8`}7P|RSr#7V^r|57"!k4/Z}-."J8M|.k: tjt:8bs~#T|AhK{# 8Q[*upq!#sh/V1Wd:>2?g,"JO'+MyfhR{"pG} 9wNEOD:&d1Pu~_}^r]@Rey   } + T   #% W  >4h FbWLAV,Qsc 0 *m ~_rggt{Se^3bo{K3O kL-J'u.y<_ +*JZ|OL  W X b -/ -B -T # i C  k Q 7 S4rA4-- - ^ _ @dS*6J}WKCDrmip]k^0N9/b:Dk <`B-s VN~gR]*N  5qM@q`:YbZZ6fQF1h!A-!l   O A A X  ax,+Ar.b~ \8s-h4Sg]gJA>dk`VKS"t4oZ>P Z*!K<sXrN;m X > R Gp[[ b Bi^pFf\F<dd<(&os wkV,<\rh.|T`WL& 3Q@:AmT"Bo*F5Y"  W Lv n  R + 5 H 8 Q t ?+o.9b']:b@M?jWxWtj<9dFwoQo+J)tD 0ugJJy{!]mf @ 7  3 sJ  NOQh X\?@ /'Dgb~3Bw44p3]K8j8bX#&},j+Q we + o 3 g: j?! R  { # - B q   POvEPr  B  t :WyS74x?g]GP)@/0 Dn) F<x%5K^A{qyWbmN39 P@ > T}| @  # o 6 gP ]    ;(c  k^ D ; /w 9 C M MZ C `  s ! / k[@}9SGKp\V <DXbD)QRb6CV0r,PH?5 X E  0}7 1P{R-o3v[;eZ3x4u ~|]5HoS| f7_6g@b"lT2;0 $+KSqiW`/>v 9 $?e3(_ #  U %~ZH<Qop?Rgye"<{ +MGhgQ+HR+q.MTE_P3~</ZcD`W"_R| WJ g q @     + R /RF6kyA.8M&)s-cdo&pV"L%,` s M' ~).Qiy|i8-Aj^ADC)X)J+@E|K^Ak;F-*@5FYF.1n'9Mr/+><' m?g&}9$`sV-f:e`d  H i > o ,e   { S  A&  M{ /(FF[T%mL ^S&(XVNN:N9fj8\#gJ-5eDhV#|5?-Hf\6:ADiQKp+.?S:%tN:mFjPmiT1MpG[jQZ+e\rLCbGQfZc0VT+'BJ[vQ ~ K   & 1 (;3= t N :mf{4]SgjHvEQYw:}hS!oW31P<)4?A.;P[!]5>6P p /~ C+jb'"<fG 2)cd:{N-:1Ny6MNtiA8]}'WB}g4pAfPS !gX3!Suhx[[.K,Yb+p^yR:"h+e : G X,;mhGr63muW/%"G 5H?   y6S?*~ X&]KVss.bX&kwC$]ASf34eZ:eGA@ " @ ] {*!HffR+ , } d}1HmZ4Rgg5FvD~FowHC< -sOw; ~QCt?4bP. ' > y { r}G[4G? { ^ 8 &Q! Xad "Mg8ST-.P ) 8 g ? j 0vd   Wl>xjG6~pfS7v 53I5(63K\iB\ `/ ' D D2t}iw;T Yw}e+'Ke{SOfR6K.+$Cb)ZM+g" tKrT %/P4g =w*l#_7El{>EjR L<S[O1 D D _1 Z [\9S),#ey\p ^#;_/:uN dv2  F W aQ:+7@)rL:id``6t~t=8"Q#H`<g]!Qm&b1M #-#_3.GtW4oNXFof/JrgSr|K9<*#Q7A-:-}685[wc 0 ~ $ V :sEZT-k@ qHe &X%/.ArT\T)7d7w-F-K|Q@R{JSg+{{+yo3/NB9`e`F( &: Z i<  _  Z  X'v&xR@iT_W#u-7<T^xhQ|[[ewDu|D^-}eV.8\}pr"x3    |    h S  @ ] ^ B I T Y   :*lS\",Sr?h^A*AoTr|TxA>7?}6%7M ZAr@@}5u ROS:EGHe:)%,u&   ZZuM 9 /  0 ; Z x 9 X  c 8  w P NF DP k  (  / X  B  _  r L   M    #P  @ 2mmp!y['w( N  &  ujs |d]3%MYOd Qw*\R"r}x3&kt|sK@5 [e  L e G<H+EOq6)G r h A-LA}L%*r.8Bhh4?[?Z3Cmd2?lO#wt1~N* \q;D0 N3!O ~q63yc u &   $ " t  {]qT-/u3f5)xD/.rA]G\Q 3 j sY # v 2  3  $ A9C7P_?/~_|ggH1u a 9 b W Gm5} @X#8*Cs..8R![uKL6ZkCW}8D>dJ]8j^T:hP]x> NdCuC%V7,9*m>5,(T_C3e )Ghy.6["8g<4 "A}i#J_-+?n{j"6|Bj9.~1`fs+\4edu&^VVEB   ,`p d(lv#L { N ;  EG`0O+wxyHh5_f4)xey#E}t/`//C~/$DV l K'JTHQ3) : uuW}N-wh H~F\8 # jZW+t^$ CXujH8-g4* |+y>"-i`N mW ?+@4@S?  YBMr-q5Hx-G i\rV C A SR =~ | B C Wx?@eBjS.   ~ ; t 9  # a v *Q!Jy  KL ~WW!} %"V8sus3Q>TiSo|T- '^ 47 rfJ6Mq4]!X5M\s 'eV N L I*/i4_fSK 8 W@/Cjf-C#dG6fRQ3wme+S{!V!@b)N)Pg`3yGED ' - /   + a ;  m [k Ly?}!.+f4* [ x (tx\GJT}\jWJ&/AB_|J/HQ))`Lm`jZh]g??r+-ss}}{qq"g]SSSggAqqgygxgFq{?E4Gese4xpp]T]~@"s##![:F K{ye$C&MFx.TPJ52    ?AgTF:e+fff?*er: 3L[q?_GWe J9x xiJg]{@8-t`iC/9/Wk~wZ 3_dr, yX>wu/C`1`W<`joj~5tW&T9uucbXwbNe[edx>y);X.xKhGA7 d_.9rVrS"]6PKqiEL aV t U TA  S A  . > `_'3(>S2r^QTKThrWr')hLBj:YdlxqTxip'6rT(-u-/A.Th|<"gL?Q Zob`<BE'!5?i5#,A<9sNm<)")m| N8CPfbg3o{TQ&uuWbXMDEw qo-H(Jy{+cv'j6l:W*~FMMwjP8hSFNx3Y FO3v4lim ]?{c.[ *wx3Qyg54h)/Wuj;PPAk Ql\:~8jg+*o6 RX[P&<N!j:e 4 q4T[ibXi:7`{@H*?_g,"gg]|qTJhVi.tCWtt`LX}m3BCP Ppd\ u! / ] 6 8 i L7 A T A r /  NJ(y)>o*dmfZ+ 6Hi9Wb:D {JCjTtjtL9W1/F`~5_#8M,u nZhXgWsfR m-8Cuev '{ 6 `@ {   $'   W  u  M B  A[ h K+  i h O}8id7@@c[EYZ28ErE[P/i6r}JHHbd,fA.8&Nb~"wbObr{?Z a?  ` # 6   4 e /= c ] 3 LQ drSMRA"].[ W D * d  Dpg5*#7G)^o>E[x{F R2[cX%'"N*( / _ i+A4,!Z4PXM).ey Sg  +\ ffybypf!i{."_^r^-kM7h)hewi~Cj`tQ+SBs)^C-5,w72_j8:6Q!H!{g"g|q{R'cxGMe#<TOTA|!t8 v  ?lv:  T } J 1 d S 6 | } /{o}*bJ| kcw Ggb|^77s"fyxvu X k :h6lpG3P Gu5C.J,,"J5J{ QoeRoy[>Q4* w>o9.s2 K kr   N|^]8bgK0Y$` &oVoAScX9${yQc3 : 9 B T M@ M  Q k e+Z<8MoQ>jspR!  - DF4k+,-i? 8 bODXC6#sM)B>f7HR8?!T88}:AP{d1*s|[p, N ` }i rV I \ Q3[ 7?g   ( 0 k 2  i " r  u @Z  g! "] L 8 t u &*bZP"d'rrVK^G,{ C l Mk { gm<g  "2=FYlW4/"C5:x    @ e T> 4 * 8> x    P ~ t 9( c '3<_<?{NOyd w k] 6  YFK|:hy]ASLN'0'0yuZ&M]h,O 1;9d)8}d  s 7 IfWM0.W950E< O -  cwO,<DxQ+S{6S"6JS"^TL.jmG+"{#rLMCb:Xs]p 21[C-iP;i2wbd)3F><<mR!ww4 ;K X  `  # 8} _ C } L  / bM6B'AH{(q"7_Wj&SgSkN81C: 3G\BqW`%}^"!^4FJsZ Xkbr1GZ$P ?H*NT3ww; D  ` * x ^ " Qp36|E G +  W#Vkbb ki[_"\ Ztw"*<fSNK!,";7`b^vneG{olC3uV" j ,)  xY < PQ g J">+Rx3 X/%s2_Z<[ qA~No5J eAKJSlkC}hg+ @w* DMV j |5K@_|\sk oo  K) j<33g^Q?j{/t.#S#sMJ0-LOm `(:v,:j{\+ FAyvV/CZ/Ct  X  L X}Ow7r|M&}|^h"K+A4T)h   & MA ` `i  ER,,hLX$B]}CJx|uM|6BV_i8:9t8TS35GR@#mW'mGX\{5]{7<)N  , ' Ol k j e   I q  M  lm PyZs'9rJy.4 t`H`WS/&9WB`W/L)x7J-T$-&|0c4/'Vy}Vktp) : gYXDDOW_?  h ',N]q]6@6qhK|7@+>d.MDAdJ],xer9XO`^jy8?K2 D  C  h   NC.[$f8!L_L$Hux; f%f;-L5 98krFy G>, r{T---#-?^G| u/tjrM7N}m`\g,{`+[jX:sWm'oH@7#vVnof]k:KDsh@ :Df   H fHR=3@3Ai  h  i|BNGd   0 OLP_Px]^#~0ftDEZx pPg=8YbtW7`~LJj,ofPx<bEO }3^e6SG99"5QFK @   0 $ W L A T ^ r r K A _ ` ' $ ~ Rxy2nL7DuETq5Ze RH@|^Z][ZE+'f4KZ)5Q ` A<{vkdE N % k Nv<(  s 4>Zx\m2!R)o_p+S{|B~(oZH}]sg*bE+$ h6{B5}\ [V~C/9`Lq-R{xF  ` \ s  / B B # Am4E  F tpRVH+(]78MqWqgf?OppBGZeXLVrpg+-f75?gr i% v U ctWMjL`C4 `P/4~!JVhAK#A^6^-!y\C?+XSP[i5 !\~*D(t_^66@p!4 4FvyV]RDiC&)W~tYjc; tt3`45XWd {C w Dbk'X D:T' \d<7P+mZ!bh9`  ~wi]CA[PR[ w LyHx]`_|i}9:<>+<,7id&/Bw|{!!kM^e r  ,OK kg5  f9  B-s./k:\b*<Vr]m5 '      g r  D @erl2\UY' b&$LT>F^65 {F w  ,m\*x "  tF*ptfd* 7ZXWt_5~`X/Vq  "#W].}t { v}.XtK9x+b@DgpKbx|T7e-Ah"\*J<BB! M" g]c}[  -b 9;Z4x> o!o73kCSg+mo1<tdVm#w3w(} W : W ~ t / u\'b|89`~XD/KB[2A&SR>3De" 0R 9   &   F  6 h `  4yp^G}9K&m` } L ^ 6 +pL? I: d :]^#8##m45@K7s-XiEX2vENc/E2v6HD>j'bX\ZxP:5/]RG)P)oQQ)>*C>}Q*<  0 h `  "  r ^ ^ _ -   Y  *A`g6F6"6gq,/h.%C^bP"T:q{WJgF5oo  _]Zf'_m 0m    B } d _   <Q qL _   L  `  k /d L A  657R8!~   Y[*q*4H,#Jrc?XE22P;Do>Z!em)to@!q:W8_-/+HWH+RkM.w   oc   `  K |  j|  Xi;Zl*yf   {Lp*?6LS F51Xuf<*c?btA):;: ~Lx_o_x8$$FLDAj>s7"V '  }#)T;atD) ? C++\^ Nm1{iPL#| 6 ' :5 ( * ??8L~jkkld@fqLCiu::D93-SoeP,\oDb4y9t-}Bt&g5ubx3'VT~% aL L V } o ^46 ] TS g ]P@p,^/Frf7hn_4LV_VV&VBY9w c fu/-VZoNp+!?9f[3Cj.A V; 4 i  yu0M8MKSFf { > o4qe?4|iW^NP8>Ht"'@qcFp"{^|T_6+mVhig]&S.|[QDBWs#*^,4]:7p 1GTQFw) wF <p{-we QQ7$_Q|@\5otNh f[$O\gs<t[MCjqJL5tewou\WSL786M?MyjyyyL\+SGKb&Dbk'S4 :JMi  KET:X&l'w | ZBj38gyCQu)(wwwZPcPd/ /?So 4xoQ5@?#$c&k) f"r}j9Q'&XC~WjtS<_iXV88.DtZQjjM]MWW}tW9W.hig}'{.  'j  ,kp[wd):  hC ` 09Z/RTkC<*W]?K}Me5v6hPej?kbgukATJhYs6W@W : 7 M Q    j   DvCXmv   <  Y 2 0  j  8 s~ } > ? gqK{R d|TT1AmLA~X&0f]cx{)F'ZCd_mhF@o\!STg_tkmF HYH~/9S?8FK.SFLHHy > s #3 hm T B Xd*j}b \~i| X  W  U  L  # 7 I A A 7   r } : .  j  N6LOWkD50w^<[o`q+w5!/!LQxR{SRZN!&wSL a^ +F:Q<^(q R & 8 -  ipF  yS    8k &!}]h -(W}[__^s  # K r!5 "  s  #y}Anf]B-C&^J H; MW. h    ^+? s "L T_ s WT*q?7 ~ZRv 0V u & N/.lFpQMg^FLBFK "Hf7BCb4> \@|h|@1m<y[wY p a N>woQk*~2F4mJ':k'%&fjZ.Kb]2  {";:7_D9m ' 7P  3RyVTB$ .ys Z%TFr ] R W   ~ M  X<[1QS,[gP3nA(N}`X:VF ] Fw X X W ` C  E)tkL>hBRWfud)/B rFEl 0 X :b9%!g@fL`?,K&bvdF7 |Z""8TgyV_+,,@|Sd 5g5F,H#$y~[Y3 X q( d:1? t2}h*Kx}pt*:X*r!pRRW\B#Qw_9~Vm>Ks,W{XgE]PS[,^6|gT^iqfe:dv}\D j.7[w6] '@ k XTd8x9u0 /NmtxQ>Kew+Q"!  PNmb4uCwf+BgMSbg{ORb<!t`-T|:h#,5to ?*f,7JfD*f]6S{?B/o yk6`jA]tg_~u3']k;1d<4 6hc|2[n&QV^]fyxpR~%}Q V/C8D#ldPcSN`}p B#R"g  / W 9  XOqA~tcxZ!"AZ#b<kXC3,*<8/6C/6N PB^o ?9L-,+*2 X  j{ p }>  |P  q   w  e g  ^   /C uu) e5SK^Th6"@*JLCtuF.VKt2]S#M:dc=~WZ BQy3iJ4f Lf> d Y ~ 0 $ t  T e   S. PHyC {   BZ 81oQG Q [ooe[G &yB,tH PO:kO-(:k&H| Ng CR 4 8 L  9  NsvmAGJ]CJ,|"r.^NRd[*y\JpQ)cR>E3'[psWyN>Zo<dF iLCk# tcEYhT&@>'p\)~}ryH*R\,sjX1F[#6VK$$]L}pxTm61!H!S/&8j:2;c0 Jf5HMiTx!FfwypH&,hT !3my\\w x>NW_T"h^-}L/BD3P>\T{p@Q74RV9j@u:l2t;]b&`L#K65@ypy GXe[~L -F"w5QkZVA] d (  "  N k :ENp@4 I 'fWq0B( 3[]Rj+^bg/crL+ [k w +,T}FYP PVr)JZ!!J7 \u{\$jND 6u"]}r>{fY:mu}-q/pkFPkLxQ->* qGxfemN XC    T ^ I ! , q g  7\ U t k2 6C og5]Yi&p]^*t`xP_O7]|RN3R|5\ X- W  i L C D}y6_TFFpQ<:C_\y :G  d  p F4Ff) C T 1P k[{ d~XNTy Hx3dD2% 'V _ V   X v@#j.&GD^2.0 (D vK)u|XmGP>5*g|J \K?^\| q\Q!)(3wq9Au1F5[ovPew! `yqt4Q3T)>dY '  x >  k?  |?gV|sNGGf*{G@6Sq+shqfd*  Z ) . x _ 8p \ M? k+f4y6)X)%|y,??y  yC+q|h""68A`}M`j.+-6@G(F Kdf6[^ Nx5JH7gPTV^}/`Mb $v!w/g2uWB D- @ uR 0GMV/X e>B/7_]|g3qm<F3  b3ZwGd)+ SH"{@S{*Qd>>N 0   ` t C1 >;fPq[hyL -sGM+ufw)wcNWs|)D`}Kh^7BjN .h^7*77h-L-&K/J?!p2/-Q+)Chx 0 p  ,^dD=Z  D@ ^-BCdu0cT2 }BB}Ou9@?(> :  t 9 DQ?qQrKFT?"y5e w08B{oC E    ;\PfG! g ^  'eeoFA &VXhgH9b1* PG 5? e&~hg%dXCB#Jt?`5Ck], 74V!q` 8)~MC9/ `.Am P 1 e.xT    uJ ]g H9'  'k /v~_T H]``0'O O;EEllX'sN^k"xPj%/~Lrl Dy />   |  | , _   Oofm;< uo  R \ ^ " !pX+ s @    }wuG3$' :voG GJe{\o uBb*A>fT X X/ ^-k[D { it :3iM" RFW:/uM9i_]4  P 8Z # @ g S , . M c2g;70s,C  W a D3olVjCj5r,6Jd)?5+xHe\[f[\xpZ:y,';dufp ~B^-4r6}qd\ly   MQ    3 t< 3 )OG{f{97}sKNS d) k  Q h^H2 'g:k\u4u=v-9Y`BLK6q!\.h[4:/ B 8A hS I  N  # Qy gD ^ L 5c0V_W</yKb y[Q!2{}GJjD2W[+pYTL+xTX5 vMi c)[KRf[nrKW#KK, }pH4 d : D k 90 Wv M H  X < Fgf<@` *7y}qj"^y"&6T"bl @Xt,JDO^4 d  $ o   fQ*~}3 =c  a N    0hOs`>\g^ik: [4F e"dNbwXebD#8M?'];$~Olu29<q+ Q NpWVx nw:M_|, N~! [ Z   GP)d 3AQy: }g &|ix8s^84/ZuD34qp8 y"K#)"r-8j6(HnP)dl $hF|6`?A^T7VR?~J)oK.`}DWCe9[/GM *e.imrDg9`)WD9u 1tiK{#f}BWfH!kX!:  " V':bb):>DfbdWRb`8DvyG31eX4: QeR<6X#TM/C[`.t_rTJ{p cM  " f o dyO N5 k a    Xdxxyg^i_93QQ\,S,J]gqSqG]"MhA@-]^ggJS,#1'3kQ K#R7h6!!Ry\H f Ge[ex>u?69^7Jp~s}s\L8B8R%.}GfKA,{p[Bf3Z  W Ll 7  i , S+ 6y \ ^ - 6  j  m Dc2k<!*{fq{"rQbZQww?@w3|o?{V'vb(; cO'D9&B{!g!xHg9*5f-890El3o;o:`;iV5/bx4Q\+!{pM0@ju/q$TQ;  : a a N D Do a   9  .I  - q  ,K @L S @ 3 y A 8   'OMd[[H+J-#V&kqK$v'O((F p2OcfQu&;~X$}7/9/@f& jd8bW%#Sy1x`Fs(| aH  o  XFEZdZed\w]mr}~Ym kQ G Q WG t[ 3 m ` /X t  k a a@ : 0R a 4 o e 4  ? 'JY-wQu!C^F?-CefqS-feK^!SVn!lQY \  W ~      y   p t+ W WJ M &|     #  kS :+)l; k t B  |y  { ^ | _7  } cF/oD pqWnd T./:tv92`(LXM!i*F?bjLC|*gd{qSL"78twQ5"@g7$5N4d3v u ) W ~E t' `9 M C y k XY4xFx>y5{^L-#A!J]#[ $P_is-rr<JQJg,phQ`FX: j :juX/9G9WWWM/+bs'w< o B  ? g  h 8 &\_3O(c:8`3&D9/j|6B@8_##r~gN G<b}7J.7@Qq)( 0p  Q  | v g ' ~ I ^ u D;Ror%J-Grco " fx*F;0Ns7h5]QH4) ) .xxo7|@C8!|\pZ  $ -p ,5 R]fR?^ - - 7^ L RF' P< G {0$`\q 4 u[2FGuL ,x!3pw\g#sjkD Z)>Y+dg"Gf6fy!pf o< xwF2oyJj}h+ ,{ p rt_r^kc : g  L l _ $ ~Z   9"6yDF~}rqH2*<E nYB3o3gG]5_f6%j/&~ V7>(/|M1i Y N $ 8 M k 2F?V xG ~ Mb ( W( v '/HZ_*{Q9 oHgQh<Bl&.Sj-!@  Cx  _ st si UK  66,4}Ai~Mk)xWG_fRfpffvp  uy \ &R 5 Ng5V^#?#`NK|dPdn"Eg5`L74G* fbjqSJj]uHW{ehRqK6pQ/Bho  U fwey ] J J $" OT6}h8^,fxj9 ZNd<F*g,LhsjCD3 /jNLc7wJRe^tt/j`bB3{7 .`'+rT{qppe[mFu`v8  N ]  H  'Q;3E}&c<4o\!RMfKA 9 i A  AT } j 0G tYpogr7# 4Kqj0(n%#fF>>D4\kkW%hN;")@4]?5p5o5Z+?5Vg&J^s u9  Nvt2.[l  u uF QGqK'{]h~+_pKHJqhHVo)]WF[RSnCubkAR&P Di $7  5o^ + v C    +G<X1l;X   O `E<\|>u&.Td7.?5x7 x  8 N j $ K T  _ L k  of6#LoVC`k%7S? , ^|B][) , }j D TO Tw # p\py qrWDX}N-XX"u+%px)u` L /   f  `[ c fe>SR? NH`.>o<e) :2lCOjt~CeN4\G?6#9YEE[ln&oVby*  P ] 15DpD?: { w T<  'QE*d*Q6e| %C7.Q;wO< 4R"t~ kme6W e!k`_#W,#>!ge69.7^hAi.8~jjC9G9eP1 v L1 9 cF '* D r  w J~Xmw!QyK,}~jCuD''DCt.-~d`D/&',E\>@y!|h6TZKrf]m?Rp &p R 4m"u-/8$8D`R4q r _ C @_!Pg rf[F-(&85-"[ZPmt s#|hgs+j*D 2lOE Y C .u L - 7 T{ A?  $ t  N mx2vc|Z.j\kd[H"~t3LK<^hA;% R5-s$R ~)'}/_+m  & . K    o  h E U N  2 /d M W  ] k(F.QCrB'~Zfyq5S,S|\$PuW0b/:Wm~e?@~|tt$~_5sA'hf*o  k   XkP1Pg-Ri,s.1$F`~e B*eXjf]   L*  -p A     0x;fPS>Ts}9;64 7*e7qAGZjV\gYy : a4 N> OmoJ\A,b&Q2 o>dtjssAeEpW|R<\C,-so& <)Z +qV99W'/>Wf}rW" EP:W(l3c : | 9 t Wo 3b!M^`4Sj%'B_F7w^;r,SV{_,8Wy7}/hb,buu}>"SKgS{H qS,oprrrT| F^3)_ P:w> N+{@&D"qZ+*QHJbykJuj9Q#s WbZ -k&ih5qPg!"c gF!!qO-g#X-K"j:*FF@)@[89X3%Qfp>|#Fw)RAhhBtZxr \.9{;r-< KZSF]9q` b ]PG;v)7 -CRle:)&.(A;@+/h6+f>]32 08 M U h ]$!A")+we9)p   0 t '  aG^@}rR}S]?x8MTb ^SR DkF &8&iWtL}iA.69qN+ :oM1~76SfRGFGG2[o Q 9> > G >  p=?m@w `  `OX&GH{,$ Zk;Sh?sB#r]KR^xqr+o 96+bPjVA*6?" X  X +l <ud#[Fc Ny !  S    XSo!yLe T?]2hni/oeerZZO~'u:$^,?Q<_, FYD N  " R #* r 3 P -  >  W?  :6d"g \q!HTyj [x +P6wTdmPMDQ4 u9.qA@d>5!,5Kf.p+W]-2}Ll^S>3 jP 7)  Hu'c!y * x . 2Fwr:oTl/nMM*Wtt~Qw8hph R[g.~9|WLq7GxEY;}J 3  k P G f { A qV  K t C [X+WD kX' X<E m a<   ')cZ<JN}bt>%gR5DG ixFk;uQ]#s3W|R 8 T , #  ^  9 L  9 cCZN3wovG* Mp !  -  I\ <  q ~ - .8 *-^/Z{ph? dee{>A_?CSh~VKJVvWqk>NW"':4uQ9]M^/.ko!6K,{MN#'{ 3D M R[1\F= kH I #  ' Sd_x?:de [lCD&$He[PFwd Z < xdx*m Jrt_KJ?ROA V 0vt~Q!t`t$T!Sr[-d-|]wFou*W.6p]RRpJ|Qw):t`_XAJyb[xjxGqR?*{1,j4PE   S  B 8 H ty p56"hNd>_tWZ.3?Xxy!Ts 8 ._ -;F 7]QwO( ;EX/8T yd]_pA  T ^ - K    M6 ?{Lrm %C" ^}L`bOd\ ++yfG\ n6^ilWDX3QoQ 4*W>#[oe Z "j_O^N{`8(    ! p*4nFw;O'NM4rZ6 !x"<T##z$%9&&'TI'((A()i(((~(C)L'J%ja#!;=3\qritu 6Y ) C   #) x :Gpp4/ ' D 0 Yd"&F<]@wjN-GhM 4RSV.tD3xDur.B~hu]1 l{YO^(s~uEwdg3-*Qj{d^,߸C_ہyz~آ&,u,:qپcO9(ߤ!e2VkK_$^z9):dvwFwo= H =kb.V-^,75+%@j/W:COCM99?06=[I"|-78W}ݦm v`%hx@]{Z?Ef/*G_^34Gi4 [ 5 ^   R # ^G " +G`P8ZKR?Q @w Y D a j s ^ Sq? s..VEYT:Sa\~F}# k /f = 3 h( "' yG  !)"w#E#E$D$u$/$$:#"" JNaaXY[Y 1 4lPD[Iy?!!,U#`L'Co 6 i | t : {Ro C N , f t  s %   SA      h "    $ 0 &  a  5g8  W C $  @O}-I? P10~V}BJ{7{-T}}CD1j})`a @l   O[[ cE :  Ck  i  ^ N  I gl gE I  K  1 Evd[H]9LLs/^X"PwGc :y 5  B  ? TR |p   r K f  s $ ] M s & j k O FP3)H3)@FK;  9h   \ @[ d?;H5 9 ] t r s j `   XvGZ .`De'hgyG qRq%&'e,jtNOpP{Q^V`]cgf*W_|ht!?RF!wS)sS.8.ti/#K^ruTkNLb(4<)+ )FYH?!l"  sQpg'-c)v3 \7ssAqedcXC|"SfRJS5Av_#{`v&^j#LFX6tstYM0Slr }Gf"^.i}si7s^|Kr,r-RsR1l"AwVd) k ed! qp^If}v.7$h*'!{lDv~:8Xi:iLZgW/C`~Zx.p|"5P8Y| WN~C9N; !n,)7=.d&=N)PdZ4dJ YhCA#r6!#rJy+>"^E%2~\"~WH*ou)wl D  | M      ~ L # j M  H   k a X X kG   m       A  ]    @  A  & C CY M j \ S . U L _ M }    7 ^  | j U  SH !  Ps#@1O+;\pm !5z       7G   _  A X  y   I  7g:qK.:ucY<)Hx * 6  r #    A  Q 53o l  X%ua0Yd3 { h L   m {4  HA %38 ^Jd+xp* fG!e!x!P4m[x( [)>+ \    }  9+  [ w3;Q  9  L  ^ y   " " \ f Ty f f }y .   ~ M[    NZO Gy-_/2cP p,;di8R'ZtQ`jjWWtew1LWr#S|,dk7}L{~HC*&W   V } 7 # ,A Ih 6r ^ #7 U `V N(C@ # +4+#x8\WK2Bn<._eA*R+]6]T\ j +@kt8[@!sHeI3P\PPPdPtPZeMBv70hKC$B[}^gEHdGdQw4w yON7j%MgH>c3 j?t^kBx~8COD B8V1NDK:'@O+ n)=Fuv1VV#q _ t;&/M|6oYDe+kc eLBH.$|$7it.&.Vib g00DkWuXDkX . n*?5]}LM`:C&bkv~[#RS{oco0nu!9`u|6qJRhG3EwDj@<q{`K?&A?! 9\   6* I4 *  H /{YhLBx5"Bw/RbRD[ O( y;Y RJ'^'Nkt*yBS]g! +1&(%A_]Rd\2  N _ | M q ? 8 x  @ <fPFo  )  I    I j  . `  cZF3Z>\l  X      ? ero)>J+'kde0{q]WxV ! [ d c 6 D t  .5 5 + T! r! + H R AR p }  = /  kP '(:9  :    t  ii  K`  , { f    t u?  " h ?  `J  (, qEHy*lGEeFZl  x `G G .e _ i i L m   Ox4cPxFY u^  +cTf5[4dlF k3 ` 8n   A!k* ,  &5      $ Q      i # 6 p o , +c=Ex<xG    y   gd  |    ~r  uL M   m[*p!H xP6u"V.< ~ & - "  Kt  s ${     6   *  ` 9w  ;     &  W   $ E    3   .[ > G 0O)m\ S ~h LV  |  G \ {  ]   v?d)*]3wnvpu~{],~MhX_N.8W^"|gfoZk~_|"yRdCy+8s@sss}|f4Oh- D k} D jO:mo5h8KFAe'XEZ216^9t~~94OS,Jlq5~_ T]ZfEe1dCO:xBDK6J!+53Zw>m[Fdxe*NukQb'wx!Gg T8WXf(\H HR?g!r@~bVEF Qf2EO#vMnF *zqn2/}J\L7gYrbg\b4Qw[3QQoQGG>4 >G4 fJ@s8`jX3 :\HyBG q9L?KfS\!\+[JQA@/^u};?n<Fn.(:9Lsi|}VpBL_ _sKH,"egWpeRF *X\X:))G+g]K@{L*VJp][GEv;W\`cF1e 5+'\M<7({HV#4Q[y[e4[ox[<>m p16h~}jDhSxZ  k{ & U  hM  i  K   _   i . 0(`/<&& CjoeQ{pRyf ?Q!xe {gf{+{ggg@,"{{,6,6|6-8CNrhhZTFKZ^hh|_J!!v+ H R p +*4< E` kj  `: v   .!  ~ 9   :3l(3v u  a W r  _   G s . x t*  D!v 6 -x $y ]c-.W,3>F>m MTj{.sT+fJ{{{(  M .Q ) ( a?   "(l'vD;(  P 3 s ` NO[PGQ\q!|}   1 w  `Q f!dQ5{hg#,"%@g`?NQ|GNyfMGF 5sqHp Dl : }      @  7 D   k!E  < Xee#psfj!Cy9yy[uDFm?Z7<e*NpYd-V>W]5}@4 Hk!JHyQd13(Y,Ny&oK<<)5{!@?6^}6/S'SmJS6"gKT~]N)1 &y6AVHjp5?f_p!{{xOZj@1\4[e >l'`5,",@SH* @mQ'DXjN'p3g[A gP@cudtL$#B#!sL[88wB}1uuD#^r7x9'-i?``Dv`3x[->>Q]QxJ<-wi(cEFc cO|;VWNEF x[G F  / g>n VHGZ)H<qAvBY;``tPWQS1h-F #xQ*}%fWX"FK V!~&]u:TLYEC( '(c( `LET{Pro;v1'( ?gwTZ8F/P'<3 3kwLg]yl  k uP  u l   C ] 8 s  sq # X uFP4 e,K"s~%^gb5 Qe >1Dk+b*!p, 7wK u M P ^  qr     ] v   cv)F]To&>C'.CVTh"{!+yePo(Ol(w[GG >p>os4~?B6Gh7  # q7xhw)J R  B lRyL]Wq` 3.Dj#}gd5\2clv;2;  Ec( 2*YGcEQ[\R]-KBsVj/.B_sC.q7gS*"| 3PF]F\D*9   X@   5 k :dd;!7lVOjbwPe5]TTWh]?3w:VW,7q@q]6"T.&D'yJ#LN 'R0uMVR r,@@,J /@BSq"g{?,p74fQx1up>Mti8i,ggsJBi:F  " key@-RBjhkuM~ubu(/$`|y$Q8e.4WSrkiC2:EP< *H3|#Y&-8T6<19CZ&ANS1yd p6H-$JVT+ f<uCJH3X{9p8j&X f]c6lg+0xP20/&Xl?3.Ot& }q?Ots_^#S+"go3ZqZ")r[}6MhFC*5Y n+Ryb [) 4m/Ms9#k7,T:8HLTTi?/>umNmy),N9r@{+yQ|KdNi&8Wtt`jW/'Fo4/> h,BQe#>KKKA-L`XX)G< p?!{S]x>yR!peHQjVmr g\GV-;v oOmoQ>\]{7JqqgB@^XsdFPm7hD"~JJS-g\mlSA\ f!WCM[M9mjb.~|}@hHJ3qqOgJ  0 :# X N_ N X k    W.  $  K Tr T -    "q*?K % )?<fx[>3H:@~97ug!xG5q<Z3A4}i7_^N <kd3<gwXmEi-mY! kJ  t  L L s % _  r A A ^  m O  M 7 W L t aSfS^iwj[?6 TeyMfffy&~ @yM Z%ti 7ZQ]6gHo"P]K[{  W\ B >  ]3mPo  q @ |  /% Dc&w{-'LmMu E>yw<| V930nlf@b6]bkBT9,t84#x@o Q[" ap   0 B W s r @ - Af   8  g  ( < > +; #Bt}1mD)FxGR+]g-sXDc()*+P5E'k8MjkB-rBqn53pF[Fr[C]5( : a : !mS +]L7by xR]""6"iu&;EF[ > wFvlb7W3't9t  <h.&3'ZcnPnED}Juk&p_p#!|{WfoijEb ' uY aD 0~l$Z|{5ypb 6tb2 O0\5`+]"WC'2n|gHduvBW#^]r+.wbMsr<{\ *+<wFf GQP4RmJ[K%0&O' l@jr$7,_Ly.*8s7CSV4hZkwl ` $ u  h 73  M {Jhj^|p@#xutV#7|?Sx\mfRF6*\{ 'y5)!\Nv4 **  *j*X Z4x[7P8 W%.}/7| \KL|.@-fG31t`md;   )   H N{Ti!%JB|_iC-N6HNxtw_r '  / ~  $ a _ s k s 0 _ .  < Xe[hB&iwg^Wku'CDQ_u#~5[mS"{Hh)M E1O(wob?~#8s-LT@}5p]H4 3x < Z $m }P   [ s \ C ^()G~6'F[tpu3 R{7}5f9pNf5qo^\\\Vp`djEDB7*M@7{E D ( N  j s _ # i L 6  g S & , Y  .<  > y qZLx:5@*h_pHD+mo\,JKhLMsbP``Q4$44^QSpe)md;l?*bBg_DV ]y5\R\yHR\pH\5]|{@iC/,j{p"G[eHGf+Jr]}h }[LL+iSKqx<DBT88/bN;J22;_Y9D_AM6584A f^F|r7k}MDu:o1D!k&VKJ^B$B\s"9q+D ZX9+$APZJ>?fL/ *G|xiVi*!8/8 )t[~8_}rrq,+f4 m0M`~M.uiZ#*h5qR[f>9 d^Xyt>L X  t  B _ .V  ~  &FQb516'A1V1:kDm ?3*!S,{"r,S{MC!~ys7Q[+xQd3AFPF{){]J"Q,qpp+f\\FHW8q}]S]LM 9`PXjshqyecF      6 c  F  >E\Rqb-s%.j&k' 134?:X|V&~`&iK"C{V?{H>e#\6  y o<2vCl w R ^ &rRmNjv9pqbDKXu-/,h,#,e hT'K^Mqf*`xPG\[R w >xSm')l  r J ^+  , @< , (     / l;33[>f5{{{Hqq]"@-~8F9? hyBjuX!Ry[ /[f<FPF3 D a > k D "Tm#]6/ZPrZ65\!S ^ 9  _  ` t&*b^mPP5m Lb~&8WK.J^qq4Nq6iK+L/OE*m*RR!]7{S|r}7^C!tHRp74?o:<|,CHi?!|,{rsv :   $.  #  , }  Wy  ?5Sr^/mw&XXtYT l\#gp\jR7H++cH p . -  S[ g "   ~< :dS;Glv,v|v}Os2;P#>T@J5ij<~u.bX7X|XX^DDLDD:Nk#u1.P-e4H 3:XbDy?W_5-fh^[)tu t>}{K,T7,sgZ!*fyr\52,@sb *'udW;iXK9tT8$L~jjj`hj~6yGi3:7Wgy4): N :s 2J58RCX7B9+D3 A!,T`k c<> Q pR!qrS6!Rrp^K7K|,Nw[[PpObtT}i_wNBg^e )<dmPPm6g'+W>^oo>y-_~oyf]|8WWujbbk}q!5!NY^Ek/q5ZX/`G2Bvc#rZ {f\"A43t:Ywv )wY(u<`Q?rg6S^67#TAh8rh~r&|hD7<84`{1[J5pGgZqbg`g_T6?Gd'!u&9)We`~H?e% s.K.8V\}>[KG*Jy!* h  s  r& 6 Ny* k 5 H @x    /  # P }   , h!S&Vjj1sP6 p!p#iy!CX#B'Mk:M6r8t`~/W.jM7/R js#7g?e  /  > $ $p  S ~  r XTglw k(  t X s  D    B  W| i :~(D>Rk]jA/kNop 'NkG<X1<o?ht8j//_A@p^,/i] 0  M    Y $    ac 5SPAs/)dC;B-K^-cVG4?]^L89:V*?hS^"5fY (* x 2FYD/C..AKKTrK-i^7`L:twPuX>NuH&{J@6h@" [3:&-K*7>V`]"&Mj6jS9@D|>fW8 ?S^0} DnWo 8p6\p 4[xppJK.)Z #OvV_Abe /WV)4qqy KFKhh`|r!R>[[ ZfbJL`66"xA LWRkZ qr.VLCDg2wQ<*"S6RA. '4ve8?Srh!&*F/ZCPW tGf`{&KuGP*&fF#sL0%cEYPNhj5 #.6p? o>GF+Xi-:y<*<wl  WB  L 6  # -? -    . e & Fe{ hfijj'4y~pDR!<STQ'(Z  Hg.r#>}isVrJhRdS~'u5~LCg(d EBb^}6K6fxdK{@\AL ~FDv) ' ` <  L1 B  i &A kvP+*To1 3Z|2  !]or-]P#\Arrd]*Jfr*[qpe>x P2 G>s7 )rD`L-y{|[s45NWB^-.?km3)<Pdp@|<Q 4y+-}?.QtMDG Rl"E($ X((xcRkLR \;4r:9Zu`LB|]5xm(ilB%YG%B/8WjDd[)e!Vdxup6cMYlJ0iC S|,XlQd=nx[4Ax;\5+5Hp_ x Z   Mj / L NKG\{@hq{{T{J@R|o_ WZ[4 \Hq!6f 73.bt4L?SVi8W` ' d  [3;Xm u.9^SQ`X<4\55w\OG 'm    U  -  , q { X I j v ~)  T2B`1d<&No +"|G`Xljn} ^>]5f *wvyr6!|@F4p @ - 6 g@ q p  q @    } o (;O2)|S|_WD-|'""`LA|#,]p{<@*5A@@L!/*nWwPFm.u+tdi^ vJqFq]gS%9:P H|H|| |r TMA-#e  8 h_ ]%R ` , r U kY1>@ h:}$W%$Ls^})V8:uN LP7h*RJAA}_V}Wh" x*Dt>oZFmd eT+5J?7g,j6{b+P uW[V|f! { M] ] J @ 6 @@@Q@gCpQV<D.BV_t&/kt dgx+\6Z-sd.i4+][Dt]8LQLdj9d 49y`B}8:_Zb+\!+p+[Rp<*4>G>) Gy+,#$:9dPu ; b/WMs7}  !9.[rZ1hsM~DN~.W/h1Q ) u4 & s p Af ^p A U ~ XQ o3w{ik3[5.KZ_BjgZM&:<t&7:y ZE:kWBKN{'`miZdf : be\/j!?fy^\\J\?!6RA[mO13owpJ#NHO_3   L3 d j d33QRqo*#5JiAfi[Z2u D  u :G )H>L4TB!\w [ G4e>e*o 53)JP}C DWB|9@FyxK2Pc N k ` 9  W M   T r  K    7  '[x5e}hJ]J7)Fs< Wkx mG{TRSm4|-#_~jMVW~VV^r5,e5pb/$ Tx4W|(  x w ^l N   i h  " { o  R   6R  # }o  PdZ3^[B91P]x7"jhK73Rs9iXt0 vD2 M;~~`X/j@C|}rXc :e  < _d  h  Y q 0 i h ] I    }3   kw ;x {o 7  +QJKh.FG?67_q^i0Z3v[FZ(( O c &Y 9(   YR 4\q..~u:j :i^Wr6_q{S1PMTLx5@$_T##L7~}'8OF}w,lXf9)"?:eWs76TReFS   a q J D;|7s8/)NQf o]Jr^^87-Kh:| T'-ushig}p-]hNRy/yR@`&#CCBisV%FZZZ1P3PG[p"^ e)isVC.j~/'3ZZR;,^uC ,E\nx H\5>ycDS9.{HPe<4*b[Cm.~_B|g_%"8jLp]K8p&:l j 8>  U >H3'Dr`B&:Tc3R[ m1*XokE&tjiTVSR*@eC8EVL 08 %  & W ~ ~ tw `< / < :X;.*i?}67%<`JDPqB)iC7#TJV5uRR RQR?!St{{b0?k/ xmX3u9~Brg{]5{ oh<BPdmtmdZFb <*?[Q"^ Q>yJW|rB,.!5!y,T`-&97jhLS^+p4e@J!<'T%|  ! i  * [ } .  &  E)Pm;>  +lK.3&ehqB-&.W \c2-Es0k/.78JA!>gPbp Ve3#K:AurSp7   " { +R> d2 g   L : W : X Y)Se|}sW:3>HiqMDYswtWHMW?LGZ- rY,qXM5yL @o tjL%Q)(c  .  j s W j  0 :d[vEmiG&HSP J|@J]gq6oA+iqt6MCjsgp[PuD8]xY  W W S f 8*    G  + q L  j B D   NZ  * ' D u  h  / W8 ` /t & FbG:9 *^OLex'9<Bd^gZf J7Lj< e [+NMi|!Z?H H H + ^ {  A i- 98<yW~X$YEw2x2;Y]:A-#LK{f4 |lZ ( M X t   D6 s<ey?_jP'3d gDkk&-`6fe3l% N   M N 1O3Q[psk'\ 1jj8}.--VMjQ6O",nJF x:~B4Hjj )x k)  ; 9  '  D   MF ~o   ] $ . 8 Li 8   ~9 a>!]3eZ^1x9mtFt/KNJi"-YV)~>'yOonY,uZCiL}F7|dJG?yQW)GTq|Awhc^ :r  _ 6 7 ^ h+ Ky  } m C &xqp?+ 5ZRc l4EQ[4>p6r'o\$Hg{rrB&NY Q&+ eQd9s)'}]#6!\q*   h47[ex d^;, ' Q  / C 9 a  Y  y]<7xg6L9B:[$yq^8`lD]-.QW!WB5Kg[;K9]?B dX9#K}-"hp,4JJ&_fx[ 0 t  a ] 9 p  h \    U  )m@Q+C'g]Bj9 /O/`3$iFY7KT7^VS&ppR !ZZ  YCZG-*Q,>g>{{(@/KX^^S*wc :u M  L ^ A ]   I S! I , g | h . W8 O\d3< \ )_PwDo>`)}C|]!>{" 8GM\X{mxi,jW._7r-7r7r7r#_JWXDW::X"q`+sH-!q!ger)K1kCBKS"gHw[   )    ' p{#/Nd\R{!JygsT!HH+H+f]qA`B j!uPQ9y`JLh"@\R>D /j_B}eB^S-*Too*6pqAii}W^465Hg 6QJe*!y6<T97-_#JVSM-NFoqrw_Q>MQQX O2(-EqD~B5x_F6f(ll;y?<[@HLe/)k(cF)vOG34\#%h&iL$.}8t7DSobXbN1FS"|G8D~A86Ry yfP?+kjS..i&~Cdub[b*4[bk ZNu&%b}1^Z@xG>!Qx qmr/#}8`Sq]d6TW'u0Nbj`sh5-[9Zu ~ L\#{rf\}"u3G K9'Bv2C}.8#"!*~<tNt9tt\*m~vjM 09 / / W & 9 W8 W & ^  k"{lPg{|%` PH*g5|-{gV{9'vq]6[RT#Rn;}'i`}}hg\*Nj.L]_VRVLB\LBBV7}sK6d[Qf+cc;Zy+S 'Dd98-,!FXE k-   `   j WK   Cck{--1ikk2H;V&&&tsT B f \R?K,S!f[g,9T,\}ie_V_V8 %E`9cw4Nf rd8xf\@@u/Y09BVT#g'9%WhBrBsoL.O<.eLsyp}iLFM' ,\?p*>5ep ZoD3X8A<YAltP<fSfg],{! pFd w43>x* {A4G Q*QQ* |pLg@6"@`gWy"  7 SpgR5  6[ T . 2GTp1qyS||}}%_}~9gpu'&_d P+"m|3A7Tp"6^!:Qm@47H7-{-{p E e t  ig  s  ` w  s\WNrwi8MB'pQx5m]AAAMAA}r-"6?\ D u v *)4>eHgm.8k7M%dO , {  q , uKmG#D~Q,0>'F~bR B|p{ERycfR+,,-7%C.j)&Q4G/ZMt|Q M;EX d}[94qf\_f[.-)gFHd4w'-kJpWL N ^ " B Uy _ _ $F   'ZE) 5"uPG3pGS*@N!Ve^NJ]`JJ_|^TT#P _.~O:dGp1Wir{5O[ ) M   j] &  c Z?>!.6/Ai|jL&u:cm<H)ET&.V/u8Q4^>Q][R*(w~$+3eh% x46RJ{]J,>",Z6,b6]qgqJrj+RNy:Dk>&dhS:Rk>ubD 9R/DPQSHR>)D~{S^@"@S!fpH*J| Q4R   p U G4^3Fm*+@'hu$&tCVT/~!$#q ?  Z?=k :XkuX)eO  G I ^ _Z ` NX@~?k1 W Z<< xP)l:@Bf4"hVCk ?[V QTS3wOV?P'`}Hr]$` 5vj -2jv :gb#89uB7W}]!}>^,Pf(l '"E-sB%48Vp7@J!?\?R>5Zg!#x/jBJ 56,7L`ER3LQOf!--]y5*)26}yLWj8s'sV.%)W&wuN1u/ ':bj.}A65]P4ZeG3xo!AgA]h"6,\JSg*GG4!y!++qffH^!]i8T/kLPhPq2*LZRuC[. V    q  - ,A ^   N6fS6S6.jD1b"CgHy6HyoH !Og N  9T    B  M   0tMe:K:Qx\y?!S,5,6[SX5d Y ' Z < 3 7 K) KF 7  : _ &  9 s  X :K 0| N   ~   K6 ] S 55y4R+ < {   K ; };   tP    u gOAF }jx[*  +]yT{%K:) 7R5+RN &JJ [     (vG RcJ_eH  m Z }P P m  0'kO tc# 0S  R j    \ W ] Xw8QjZ~5qhTr0'XfGV_h^b &p:_u'Oun93VQh*]pRg+!K?yP@lVMB99#MiSdx<w 9 p_rL}jLuDk+@cKE_2`;EOYw) 0ZC}hR_# g-Vq&u:$A@m5P3e)3<<M"s+{+df6A]C7.b~9CtX'Vmsx_4CpRFHRffy,TG} dsV81bWu/NNP00eQ>'*'4NG[W P^6 ?uxCs8rv " ]    , "  T  q 6E|q#`D)d)FQ14t\]!pS,pJ,@6@6"\JhK`Wij_`fM>Wj8^BTFY5e  'w EO ' N u  d /3 `   .[ _  H K ^] T KK 7 8  _`  b 1Fm<?qo>8Xy)fffxf[\[R?5Z!/q6_r^}TLr~@kH1yGw*3 (    . ?    _  .`  D/4V#"6@",]|p>M)?e++{\TiQjPXMMVrByFmL~w)DGZq[}W9W*[8rbJM%}]A-K}A-sB<D%_V7Ae|  'r -l83eW\JD-dQffJ^J#H4!PM)d|"+3eR+qV/N`Zoiqsyo<| ~H| JNk!eD <md3m xR<{d_/M_RF]!EYEp!m"^s\tX")r^&Ndxp{p;p Z` ZRu~j}' ?_#fiLCkwO61W-]*# ,B7"Z]Fgg]"RKj}XP>9"XKs&bDeDeDbFjui&A"V?o'_/9C m !MCcTPT|3\w*O'C9VwMX/_#8@JM6b),J{ZJ|L C:PP Hm]u79`-T"\j CD!6e&bn[# B~b*w:uC$\y:`^.E A t . " 6 "  i # / X%cmxp:7_&D:NXNNXDXNX/bu8jLB}9}kVW_MC_7/`J{iA{@g4sWb9k@x?4 y"*4AGexL%L|@GHR x!Z*v  & 9 ,  }g,H^i&8YMw<:Fdc >Ly?poZ!fd*e * N/3.dF D Q ` L [ - h3 k   I8 ] I7 6 @ "     7 S q   &R (dH:rfjJKP+qW#/_B&VC}j-B#|y{<4sbK_?6  ?ppqf8\t?!:5\mGDl N Mr Ug K+ 6+*QG(@Ecc1&X3 \ " K aVG$L5K~rJ6H8*~)w9BF)!^]u@HQwdkZ/Q^p,5+4Hm *   r ;  u | ~  / L 0 i } s\ 8@ K L :YF |3m>?g"hKT"6@q?GP XJbh' `64hx [5+qAUBM-9&605j\H!}7pJxrsTM ZcY=vY w5]-\]0GdoUV)jZuܧ2ہlڠ:yQ*9jjWzXؘK*֚](Zіhf75оH$ҋKcXM6և5\ܔah] Hy+SHK[}Ceu :1R'S hwe.t\5\1OFQcX&Wn8esr}}VDBܱLOi۩۟72vANsޯ8ߚ.}H|Xh5G:Z`iOA06`q@{\r-NdYwZ3D)dY7]gS Kyqf^gtC|&gC~R. [7@?4<wC&9_DL*\~WM^tB|,J+efM >o `)  = N  : U j T   , @ I ,  U   A ,  $p G M   u '%l m3Xvd*Ad d K . M c 'c Nc X N :  Xv 2   9  E U K u q  W `o W3 &  :  k kU  |  B - Sy=exxx[4R e)ym[YGR@ 5!ec"wP#le$k%C% {&K & & & &B % %C 6$ q# " !x f I AL+CHNpFf 5 + { 6  r AT    }} BU .  W      B } t  _^   6S zpx3;6:A#rCIjeUF1-|@^S6@U-~_taYP=    M8 tXJYYhcrYY;J5p5 q   $   k *o  D   ~e *    \ {5 H+Rp5   ]  -   & D k   c $(  KO  { : ! C  { i S , A " r  r h - $  rY   $ jp dgQ"5,gTsf GZ w+SZ">|#L~R,kAXB0&'Ovw2dRq3{;\wq\G)8A&^8n>Cy?:P+\4Q"b"@{LSr8L/&OZ xpSur%4+l]nS)]gq 3dw{d@ZZO g! \ el|JCi #K#Ks8jW0&uPkD J=|^^6@{}!Mf\KbjN/2k= >>z\f Nl jst7g~5.s ch Nq?Ry 3l uuDuvF(n*75Lj@2Kd=3ZN7%-65 ;A DNND#::Nu?/Q.3dx 2cccYSO(R\+26lk$&'_2#GEr  e 9 M C & $ D . Y  ~ 9F  al)Fw  E!K#-^"  D o   Z U  # |  m P )  < F -P w U w `F  '>FS+{}%|%L-rJqi85?\y8fi5}q}.TM13Z*j03o \y we(4u9s-rhf7+}q$J,"~SWW~?$B588B686$RLx#]3+x5!R^sS`DACgr}lDev?OEcHNQFWlBs'NMj_~ttMD;n2f>QF[vF.;+N 9BsAhh^78}`/k'cwn3> gh[Vt5qu"1rOh^hdrxq|"_6L@8]%]Lq-pe31&!p@eRpH@K3sw`&$hbD{:1y' : XW\!.q-+s3;O:``&2nZo4lpH(+@V#"?[n?i;:@{g&C-$E.<Gt"CrkAk@tnObBjV76* NZ%}s.dC*'HZ] AefL${.]_]{Hy [F3R3!Pmw1uMq.}^K#--p*[V.F~C/hb,1yN Wc? X  M k  U +  r :   8 _ . | | |'    r h - F C k6vmepN^b_8LWbmY ' U : 7 &     T  s     '7cr;Ocq? : > /  $  K  " 9  ? Bp s _ $  `  a [OEPOYl((cO;( e(Y+  , X   `     9 P :v4H4ySrfo}Bm ' % V   T  A S  { 5!\p =ox exQ G4 N   i  |  , g o  <!\cC *^f6?@+@R, oDc4d[f ] q r 3!o%@)q}rj~99&CbL1rm6<3FfdD#[* M)    G   t  R q T  ` d > \ N @] 'e ad l  a W B $ L U B " $ I @ " C  k h  w B   u6r(d%GgBA}.9_W*Ny3"^>.fM{KiC.V}^,qBCRbo'm:8}*A"]( '+ p `   &\ Sr} eb fH5!:tJi"6qL+p<5Bbnrp`1bNDSJS{n5f,|>-xn &(A1%6]|S!!?R?+qSe]){X59y& [?g S[g+ye <)yp\Q?q^Nx!_9eDO!d g]?{+?5+Sq@.6bNb//g\b5L#rASJ?RH5QSw &Vf}}@sBT9sL.|c J$t(& OG h_%pI5j!9/+tR^6)?4 uSjC8,LsBis87^j&16mpPPe'N&~B.|-{">5pOy5 0 Td'364hR{ C @;rF`[>E 4[dZYbn_Yk`D&i#T,5KQ93mmuP)Coe}#<\'Q3w u m MF   . U4 U LH   jh  _(CZ&)& MGgyH5g\VqAN:L':MN/CC`&ts_A|6q+|Q~ZP w  k A / q 47oSx\4w2 { k r & L M / / a 0Y<[4 ( E    ' XR u kq k" k N :S : pxl2w(OmlZYmcw  9  w  , H*grswuP[  / 2iTi? . - & { + C  X ; 4 ' '\!2) R ]l :   _ #g  Ho3y t i T @!oRF]rsE1*o  A i3 EsK64<Oy \ 0? qK|stsi}<Ahdu`V6SJ@,E^}lW1 f<o7*}D>ZQb\Ri-oO  &  Z . .  D ~ k   N  X2;)do+yi h7#iAhBLsr#".eD<W6Ai/ E:F [R4++ R*[43PwYX9Ls.}Ci} Z^f++54exx[ X!tBs}s'i_*LH%Cus~`StABV ;#A -xeB/0 5Jh/&CCk. X&}sB^yQS +yMsQhw '78@jj8~9L:#^ ?6|S7{7|p{{qs-,HR5+{6h_CC'p{+_$D;`k2OX;Yi-b`Z$DMuukuvE uDcVKY];yO i,f  kB  :F K4%So?!"##B:8:]`+sKE"'qbb0p; w f-\\R?pK@y>YQG*@R/}{GS" TQs$Rrs.S*%iPK|P h#xV`u:tQ_+Ag6,?pJ{ 4!QpG o5)J|A&%#iL"t5u )Q[>[G,^i`GNeFeG4HR@^rA\_[BL}8T!y* Lu t }i ^ W] HZ<-Fd[e9yu4) [LR|qR>x(P:M i h g f[<Y 2  cP Q5&{6m |T-)}iXVLV8#T[Jw+; cec;<G\"^"T`ub'Z NZju.MLrJ y `      Nc u k D c1Y;QZ)\   ^ o Q &> XQoPyS[#p%~1.C'4 ?g x$9:ukD'':uX:t8A]' Xkr`{B#!5"\p Qw X 3 &P `Z Z P m  t2 9  u v     Q  C ~       * j> [ NQQGd  p5,.B'tFxR4Hq]#V8|LK^sB$!.GBVQTPc"@g`{]@\ [/ookQ \E"drPAP#w#(A|'jqB#?! >oPk<]X55!SKsB.%b81VimiV>yCVmeY\HH\py(;EyY\vHHRR\:Rb5+?5+bE<3eG**4[3)22uCX\<&&P`G6s>`MCW.q+x6FRFQ:?kuX)x p"rQ5`5F2MDWisoV3`&C~:W2kP ~)NZ;FxYf?&?}7L/Vx^68 P%'d !P]J]+S|?*PN+"j`PSA8}VVVVB_i-isR #^j8h,Jq!g*# skFNxZ@+"J6f{QR Fw1j% :6?t%iQ<VEMvbdNoR/~]8,}s%rh`hr/jT}A9@qNdo+5\55+]@JSpKF}.CB]KgH4R g TSs_&u:d*4o%^){<3RP Q xu9e} ^H!{[7_ F~ j2Ol8vY7;(S[mF  aG   M ` W 9 . t av)4+J]iL88 _H{-pGKg?*<A#JgfY > DG k* N ?P]-8tuF' ')u:jt7A5, (J(Ph-_\9Z  p<QPm1x CC-BWk1PGoRff54 HdpX[k:ZFDk`Lr\   *of{+A%WydX)` }  ~ $ F 7w 7 } m<qe<]i&|0-c}__EW">!ZqB6{\\S^L"6N])+G P 4os73ZR 4G4dFR gB ZJ|!{~X^kH8*# mKDSq]s}_d`6N}(eJB~bb ME%-q(nnP;DN&Bf*bD' & t:b%.%Cb: dd))ZkM%|"6i}/ub4f6h_W&DcEn >x eeex3n YN:&M685LViQixiseG*A h*G@wq}h]R>qE,  :A X X} '/'5[,\Z@ }t"6qOYqbq]j@@,-r^|T}s}s8}}~i/}"/t_hq"pxHyZ1CsA*Qe3)P 'd   C j t `  Z XlQdR4yy]pH#q.T'PJ5B"jj,L?-*JZ\o`PDu.%~uDG3*7\L$.i5)`|Q+mE 0  & M Cv 2  uPyg|_8:MbX'&w_F][*> 5 , A L .C t' v"6K/tpCqukkkkkp49b.#k|q>fRS Te_jmv(';MbMV_hx \Pd & L  B 7 s | } U 8 r  ^ - t / _ $ N  E t /<   :y2-FV>R3g4\h+5fL*>W>*b\PSG9~kD''u{|L%-,~543}K6`R'~/ 5qM#8}T#Sw17|S!gm[3 u j 9   L B  &  ;mAw4w>.tjD(3([d@<DXuduW/8T#g]!R?@Jr#|i.B8M8VKtgV5qG?Pb9_%Ks#.jj&F!9}h#@5Q<PZFF3iB*~CJ|&x`y_}sA@R6g{{p+g"@TL) lE$E&OX(D;s@6?4o%'@`+!fq*Td/(DYFEG(+Ze@drZ2/$< 13#FJmH4m'kd&MQ`j`W/b w@6hECubjusjQ##f pP  k9H%[?C6K}~MLrSTH[d@Xg/qgJ7^,"}B~jj``"M]9u+N+'! Dq]6/MWK`jC~N:Q)Hoy{RH?+!?fSy"T >ess<u^A6Q3:@h&_C%Wt8shV|oZ{2  &e   P 9d ZF <)7w[[*\!-6s}s-u{fF[ L G 03 : 2+,7VZj !4{"GrK7-X9%}}jTW/]o3 uX:me)3cG( Z?,Kw;c;F}LA}jW&/CXiZTe"5q75\$yt/\!g8j9~_jrb5vc 8~9b\?354gR{#J,8&v|Z7e_bQ*vkj*RdFx2yo w u  /    ) 2 'f 4   B s s UL 8 r  I Cq  q I28oWX!;S r , ` F)f?.JPr|irjT72F)j'#tJ%BeB8Pjj`i```S~ sm|w-\6'P7i%g~#CLN/Z:4Y,)hp&u6cTP<33{H@7.2n -iyRHfb0 eX54PmE  D D '*v"r.W%&`&C's#Dt^qHp  X p  _ S K  i  9 rN 7 Lw w / ' uu M(L)xTJ,A?LM NZx)m"AZ*pq"V$BS7+*[e<'[ ^H!ro%~mD<2e+ q Kv_OE22Oc. 6 ' '4<:eR%~]R*<9X''FbQHrfxf3Q ~3 $m  7w m F B emy {^#op#T]T+*ZqAQ4Z N   HkD = ZRx     ,Z|Kq-&-A{hSQ54>[Nv8C"}#5gx)PmwPS o \SpS>,"@%]A]fx+d\Ey y f ? `   ~h /  0Z4jXtYuw *Ry5?++5fR* [P2 D3PPZ$ZZTZZZ\P3 3oM5"|9$t:0OH, O|K'AKWr$,@Ho'k3)X4Py66r^9AKb|::Jk&xdLD98qGpP[ 1:x:41HP7LM Xw?xy678V/jW`Wt~LV]o{'u &PN P<< G \3gPA D#9rj6~`yC4km*fx4^}+M]u6j6-qJR\ Q`*#,K_{~!E53,#P2X~F-QJ*\p35:@/W7`M/Lk`/< W.  fY6>^@BjiW1 > y\J^!yo-1&{!.L<L8tj8.PGjD5 eH!Q ],,]|]++e)u&lAfEdwce+7mju%Ww:mmFd ZP<G[H4 S7fH!7]y 3] -FiB[$ 8Vs*eAh|d|rNKTkN]Nbu/jB2T 06 u 5   e  N [2xKs]3t:y|oLFt'1'F' QP xpfR@5LSuTYN)v5w,:8@^f4(6X66""p&876][\ FomFm<C8[iRK6|A_t7NBu5]yqgq}q^qy5ef f^B dDx3DN/$.K.?t3m'4C`,j~6V5|P !WQm^Y : N D D 0 ,];\P*x><(fc5vvc;S"mhQL+&qbA3sj[>: f"7 *4>GhGG,Q[+eo xdb3umk::kdM~VwATDrjK@g{y[?y Gx[)qZAW X22Z) <pw^bCdXoyx6r-@^sAs-}#|JArHG"{3HuedN&NB wA<6{Hym:R{7%s_}Lr`_&BLi#/|SKR4wEk   tM ~   `  :OjZ`QM9jDFekJ:Ki$ '11'$'L^ 1@:NbR o3b u3jB!-hA}VV_}^{SfQP'Fw{w5P xGdRoo|LLH6T`jpo h@O+ M:9VK@f+e\{ZD:m/t\]@@Sjq+\y/jeB)-1,gCj~`9gA: %k'wkQ9~p+8V}{gSJJSSJ6"i%A w$4`y{rhrSA*! j.PSDkJuANVW<ud3wxGu 9p?V!f*BPu/k% ^*R7{B{D5>oR)w!xFXQ%!S]T--5TH+qg>"Xrjr|_i%T9%WXu<X ::rD.Xu'Y&wWn(L}ji}V.7@g~ttgj6`W9-_uDPZ\GKp!/\/[8ug9R4 -"gi{{"J{|s&g@Po*hA##7 T4hx),dg1u?fC~f5.L]__|B%tu&k<Q 4*p  *44{4* H 4k9hGf3bf+C]s|^_"!tR9pyfHu!bND{:6NbX#DN8X:kdZ>4p!Hq@,SqR{ **!?{{!\Roo)D.`K6B}55#+A!,]g6hs8g~hM#bLFWe\k S37[$MHuXq0J:@uJSg8]5HpGF' es3T'|AWL%898%X'j9':k&WCB_sLs%`:G_@%#98k1 sDuCM.*s<2   &  V D`'Hx&o5!9 5pl;;*ceDMT,e>Wy#"h*LG[eo!S# cYvy0qt._kRl()E''0j8w< *Fbjsh6df14>~ if-rq"SJ@g6g@ggSJ"7{8~VN'm*5Z eH\ ,xdVX`j~&&:iT +J]TVj+Hp(d FQPd1@CD%LL\.*>*~~~|Vt``~W_XZ-TQhh5^7@rL^rMSNf]7$:wt/*RMBf7Q6bR&[^P'?py/\M``JWC#su:'mwJo.p!N0~fB#  P<NC%NkJ+pyN!,<>BRkgmA}_ LmLsX&76y~&PXuMQ%BLpLH.tg&@"k d||x|||||TR]|jNu::XOO9N|q Cso3b&;9/ 0& u  a1 (d) p5!5f [F)PZF&[gH@^_jX<*!c#BdtrYB(2Y.b&tX'. K0b"S^?yQQ 'mCk~BsTsBQ)&b  9 .m w u $j  s N 5HJy^}Re]|8jeH-|SHp>xFDb9%iK%C ZKL@`:,gp1GCmi :NXbbN81WF5K-|qu`8g 1?kypj?i66A\BQ`xk Np:111t1'1pDbkuwY-{M~'CB.B8@JM-bw' P4HfSy]\o wrqyQ<c D Z  Ue     _ Wd 4 FL&@s`}j#M/&R9 `~j_i^Kr,|T?HHt5J^L&Px[ee*4Eo)_#t!Gx`:em*xq+K$g|3K7A^eql k~m3Nj.s%^"tQZ)mZQ 4R5SL!R/1G13NwuWw)L}*SLtM::'NmP3)K3 kD9 m#Q{+fp+gSJ@,?,@SgqVDHG e!)S urT/#t}__Cs'F|G+X9*ogZN G[8[*|"?y]rsB\%.V@KT|"i,8"~&Kk8Fk"K s5gEju 0:G$2Jux)AuxF_'S!chlSE(ydv : u( c   D   )e GpN)~kQF4 4[) FhOS~V-q@[3KsPbHmm,,kC-C/.k')o\J@VA~9 TW@sp,>Ro3wbM%d)7^|[|^#p+_CJFp"q{\R[x3'MVs|7,KJ7@"_A`LX`Z'>w3 fH5+?HRy *>4x 4+fS+7{qg]q-R] of<d)o Q+g{#}X5Gi{A{|6x!F4w`}-S6<S6+L~JV\@13]m> uj}%7h{6y{ 4> ]R-^uNw) ee4>*>4Q[o)F 'kX/~X3t&N.WmO4y5(NS,xZ,g+_*rd f`GhwfE  0 u Y    ac <) yJ^L+q^-~`/p4:<X jy@#&B3Q\~{}bv;2\ODshi{"+![]rsCf7iCb8m-){35?N!W{_"KKBMbA).o`?D{PJ"o["GJ>{G[xf eP3d 'Z13:NXk[49\`+t+R xt`mMMjt~.,V++-Thgr7s|^73V\~b{qZ[HpQS d hXhr|/~V",,-"Tr|hAr^LTT9Th weS5p qSSqbM+p.Grxgo>+ 555p+\+\5p??R[pP9}f66rr_ 'Z,KsR&g:,Xp/emL:h/M]`tjC{6rA-&-9KC|9&1*PZ[kfMg|.L_i_`L.W~`CAZb1 M`jFWX[ FyH!e[eF?G%m|:,+5b ]Z#LxC'!{7S66@;gZ)R3dv N ML-yR5g!y[ ?pQ)PZX1&LhS">FT}2E~;F<[o!Gq  8444>D4 : `*4]4H>>e)8 7#[_pSr$_tLvqNy7%Kwgfi>Hl  &    E j  N!S|9:*f@1u" ')m Xxu:g"r TA--"-#r#AK#r#A|@@?\[ DX&~sr^!   rA5"}|%.t&/uk1F :)ud'WW~AqtCp*QQXG'+mZ PPF<)V3`FCdM.X`4TL\ZY ;<*R*{K&uP:[e4f>o mRu[_Z] N 3FF3e M~hBL.ViiN_B<..8[BGLQ_})MiB-@!yy_5qA|{s+yuD11RDk,j#iWhFJ]J?"#s7'sZi?q6,,>S:5/wX&~j/BiX}L9wXH/`7~TJZ:.B_^RAyyyH]@5K\fsffftf9R!{s:w]$1WmxH"V&t`sA]`p8Kx?mwuD978S-!K+T!TA76#7~u7<Jpeee4oQeeQ*Fp DquC'P**Ry7_i/vXXnkW3}q?g di9iGPT( u  ^ &   a`l PGx*"7 eZhS X /  d N C%pW*d#rl  DK u L     N*   7  :Y o+d&HumuPQ4*?b;Sn)B`M`3~$E:g.[PR NkXubs:Fs%4CHDhPo 0Edf?+]Ai8!%f8iGhP"N\`>x8se4}\.M]:|KxR,K86`!C&/W BD9Wj~i~.tjW`9C///DMY8KFyG>pHV,?++GFSEN7`_i.%A8i{7,f!\4peR ))Me4Eyp\(Hv5! kM57H|\p,]5  [ u/\!g,+|)_;Y~OW2CCWFeif{J\>-3:MLAJHd44? 9 g ig {  - #H  o W 3w{hidF yo5x38+iH}\sfLyC>1meb5gB"yJo<p o & b $ 8 } - C \ d A ' F  j  }  B }  #8 -i A A 7# #^   s, S { j ! :RO QZFmeG1>b4  ` L h !Gm\+c a  `  ${ s      + i? H ? + X\"hDi V_|$J+M4&Z9~ i 6yy[ Zo=w)y>5  S ] ,A T #K U .& _   /   0 aY  m &   N];K*Lft:w)ox*H5?qJ @[J]PR P 'do!Sh t $  -l | r  l & NvsT6Hx@)CSq+R>* d 0   t  3   y  ~ C L ~ 0mvef4gK@,"&",Z"[ ^7+@}V7LLs`Nh;{Po)t. D8!hq@5K. >QeoQZ>)4 > [3P&K5c G [ > r , ++# i q #D L W N>;i$)o`H/6uXNXuSM+L ^3q']xso95 ks`C/M,_p n7g-P1b^ ) N Xw e 9 C? 9 J N||<"S4!q"@h#V&uNHS?h}~gS @,O"|2rl|N6CRB>7r )3Pw c:j]!^*fw <t:79,j{j/q@')r-fiJ.h`ikwWyJuXDhT77cA;KT^rrd|Fr<| > j : 5]SKT7-,r,5HRH+"?.j@)8~R JH"]Lfk[(98-v"/p^4,mZ; ` k 8 i Ws _ B . 8 i    #i A hh r"      ~ . r A   $ L  u `  0>Rq[@9|m&CD3>p?'kg`6%r^TA-"#@#J-JAJhJ,,R*J)wyeZ1D;Nk   / ~/ M ` $t . . 8 % i  `-   0qE?34o{|o>85W/STCj_VW:-AKdA<#)3F_m'`bA8_K|#-J-!fLtbmxRpq+^q8gggCqb5D'[):u:uk/XWNtNNbj9Wu'%i< i.t9FmNuWL7u|:3GAZK49!Xd"^TiT]yBQ37"Xp4M~j%^C]3x{yqyg]]gq>qog]]J6," |\K{i-~sb$e~C.NCNY;n\Q]4J*]>o4ncO /`i#|GpQ)o*Xf9q6.7"S@+5 y wGkWF_lLt12d*+"F*yo>{4@Q2@+iA RtCu9R9)V2OhE+ Gy"O6O><Fl[v\\of433GyXJrK77TD|x**6 rBtftR??ip>ZqgR4GYQ> k  &H j ]   #  ~ j_ `8 j% t   8 U_ }   T r r h K  B  ~ &Fx>*M 4e) )FZd )Fd '''DbZ3  C~<w-Lhr"h u j L_ #  M5k : '+: X  9t{j`M/9MtMW`WC@HN>we eGG57s>de:?~{{_HT[u/h-^i.y`&yuX1|.kmdd<DmP<33 <DFuZC'bL#]&&H* d2k;D;'2  m f]w7wLj D'Nu/WtZ~CG?DA3Mo'4 O?E,Nh--d"pM``P9D  j4&b[NNbu`itBvh   @ g   {J|t-X<}*%?qMD.d)$_T |3Z:ruA/V`~~tMvZ[QHy\\S@@ ]n;0+CfsG L   *Z4[v m : D 0& sE   <(Y 0[ u  " T s :l dGG@5#,87MLX.%E.LsR]K@{qdcbq`"i|A{fBQ)bMZLe ^f?+,S]+{\eF!HDf/%  K|\q|^T-`iL[88Bs8`^u!fw*>e 4)[m wO0 : u V -  :ZQ [ (?];ZK*i96mh>A#+,r#L}iVMV}X"w)dNo/ T6,_`Tb0'NiBMig!%Vxw#T:u-AThp+JS5^fK7#yH_,# P>'FRqJxheK[G4 _ 88}A"*px>):/L_KgJ\q+?\yfRf\5Tsq~-opLtAL7.W5>uN md:NNeN 1\d{Q]]\SRAQZ&ub0'0sb7/|K""6JS4SJ6 ,"[?,@]jg{D{]v@E" T2;l89X'9e5B,#7gsH`fp\H!kbk]"&feZwuMt_}#|-AJThHr^>K-Pv_  C k L  + { U,  /| KOi.9~X3D ;3 ;4GpR!qq{gqgggqg{]SS]{R[p ZC;Dj?+/}?*>* a  M? qw  {4 ] I ,J      t C &  | h 7 / W B  % a}#h^`yqh _*`?bJcTn_jk,e}?`&HC4rcJNHMeLTg&pseF[ti#q^rhKij\+XPo5[ex[P);d  dO E<dxpoJ*#\eH@@^|W:g!v;4w3)we1*/f.+#@{!pqJe^vD_%%V7^|o<v Xh K -   a V(9QXS<LxG* 44ey\RNR\y7{*G\o3F<k<'FZFZZd?mgm|F DxGO4 ** 2*> Q[`e[>f?4,X`WV}N'}8wCFk FQ 4dobdL k6/R% K>[qQ*4pF2S 0# a u_ u X~ 0& Dlv' X u W C Lt   ^ |  r  g  ` >mp #BN 07vjjbiC_ 9[_<|{pG8m#r  FG6ggsHWQ'P : %J((((3Y k)  4 C M / 7 _ t 4SH_CSu0r#s 0MTgs+iii V>8[e[>W/y\\k1 ouWZBASy  3 ZwQw :u&5 }   L,   a*EPP(G 0 J  / t t 9 8 t u l2FQ yprSV9# BS-tt2sd#44WGJF2K{/~Y '$ s i#  S] pR4ox =y  ]   8M j X 3e-i' P 1Nk 5gBN8yA6| KN"f_$t9|6pxZlM~ D L W T 8 6 A 5 , 4 ?FpyXyRW  8 7B _% W : t&pk} PA fS*T{5}4KvbCHJ>5o\R!G,y$6~X/Nct6_r7P-|^{!YP D a kC D#Z]f+] eV9<du'1u :~.W-r,\j *>>G "rg~b:D`^ ZH*G5J,",@{x*\?[6Ks.3sn @ t_h8A,xt<)^^Q-.#8jCDPeX:"A:br{W5_T+?e 4>5   ;Q<}RC0;rZ_ typ    Y sv Y M FwQ4_qKs%7ii}BT"?Qxrx-e*}$RMSD7nbfF"4KH-g6@gF!jA5m<uM^pd! '*  - ]H        u 0  @ h   H]rsQj6G |Gr^A<:N 5Srx\P65|Kr7SfQP\l4)@:M/Vh#g\{4!xO uc  M  C U ~ K t 9 I uR :  4 0o k     _Q  h , @ g ^ L &  S     : & NcS-DvK})>'mp>\R5Rf"h[s iP}}2#h}@K5>)D& DC W ~t  i   #L 7 - # r   iS   ` \ a2>xRPm%w`md4G,e] '?p_# RxyFS)PQ>@K{i88j [+LqJ#6rJpJ {w15p14m!3{wrX7/J99/&d:DhZ po4  p@ G-x`FZwP3  "\Jq, ]d !\& 8Q8Mm:k/ZFF.Zs ^C,Sqfg @dTEsO2`'P[oHyrS.^#DBQMN-v}2siisZ<)sV8F2Nh@3:ijT DHoc8 '_   9 &  Xi%9b~9Z:X&9/'&u&~/M`A~8iQ7rQ@q-}{FJx|AA_C0Mb;d[(fvN6`r,Q6qyM)BbsB./}}'P T6mqNj{6ATJM!+>,JAsT7KC|NqH>eo'Q*p}Tg6K LOW X/ / M _ 'SFef]A%q?T<8c_cr3e\3rB.hX"SFS@Q|yH?LRf94PX1b'1uPW4_|{{^f77QT)g;4EE2 &w<i A[^ hh^RA_%.t`M9&/CNjBP |>J\5HH6!|-|.}~}1wA>6!"[-L`_C&~ii8JM&<rW@LP7EhEm[+^A#s_s#ATqf-Lp/!{Zf}"9PB>f+$}^g*3{@:&|KiAgVLip7G@ Z1erh#}}.9juNPe[R |*~xDZ(XWF))_Fw7h0]!Hf&yBKJp+\H m67P9k q^.7W-7r2Jop*( ' ke  k '()j4$}6&Q*Nt}7Fo!*4eQw xo[jQV4K S\QF?1Ssir@J@"e hRs{.Ki.sr5`/[3w9`m~y.i^SR9*0P'bj&Lt#8Si}]"#-TAKKK_^%r/NqwRGmN98KS\[ ZQ; F & 1 k ` abFoPGB{r:_4LBL\i5T!+JH\pyy>p[\x?!@^3LwCD9C`C9s&#1)tLe@\]{#6t*Nm' 'NWM7i"{J!\55 5e!>f6gJNhip`q'hw^ZhF<))S3P\mx CjjMNF3H?,{#,B"j6C]//Ct}qH43f:9>87H1b\{&MrB%#j,WMW\~>8xT)6<<*[epe*p^gKA77#XL>ghZGB5]#$Ls^$@q]?*i5S yXF/v   & WZ W M  N '  (   G X Yhw%/ Rb1g,|hA34}8{/-bw/x\CrB`lxZZ'[%>>#Q|x"62S]StSL@7,t"L]5!RxfRZ5! ;Yv{Jc;A3LxtMf/&&9{W{i\-GA<tP:5"|}^#Kn+wQYmuu&jB]!^3'uN%F'Qd >?]NKh6-ho,O :   &: &  & j vL<!Kq,iC+D??+3o[>]6f?h#_t/N!1!++!mQ+?f*{J/`~~`"&J{1w3+5+! Pu~q6|T-@-^S!5HRRR?!wqE@ u  9 j| tT j- C   0}LZpW&6s&X[N!g)*Tg}-L$$WW~tj]j~d1}#$S885B} |+pe @1K9Vi9-|SC%Kr{,|^r-B8&kw)*`/p?+!!+?RfpyXyypfF\R5 !Rg6rh^5TyK7*<ui/B.|@8VPTZ@ !pJ*[_WDPDkC~.im<^>J!!@7m8WHqjVJ7S!ssk9-,r"\f[Q)))<<3Q+[]*|T-H!g,^KLG1MGs@AT_^hCT7:L'X//:~Z.4hS\ Q:PC_NiVV_}K\ &G/[/[C>W t+^D].jC&Xc 2MW}T^"@[Rbp!-"r >\|hTAL779AThNDDk,gt!Kp\> od9Qpi  6h.j9/C#jK|B@ASSJ,Sh!sH%pt>`oC&P NutBuX71g!\?H,H5^@^BS~PkWw<iT"6,7o8GXf)xmx[*:bg9Mt)V4ApRRy4 KM_%&BLbL83~[9 u [x Yo:GM?h"Sd;r^KKT^r|@!Gm ku 9 `  | ,L _ps_[8 9'*md+d K k &~%_s`bdx}s7sssi_L8<Gf/kB 3NQ*  b  KyRQ53!(/V!|!+ +m++L+  C L - !y5y+>  I D  _ C ~ M % s N|2@o]]"^FCu7k?hi}}~t^B{#?] e woxA[4}%~\9!g6&tV|,"6466Z"#>/HbJ7L@N-Eins [ KyH,!q5p?f>w( 1/*o6Z+DH\RH&HM\jyo8iO   A | A   "+@5]g ] @S @   uETSs.~t\t~q"~jMk^ -} `{ -;Bn3~ttdO$i^gNj\fo* dmO: 0D uD 1   / C W ` `1 WD 9N X X X 0N1Y1 <df<, )}Fmj1uFW p!8_,_BrWD) E+gwr 7v#TV",RfxG XZ}K,Z[lp  C r B _ i Ut 8M 9 C W` NL P{Sfs oCm'M%LLDL3&*Dw"^xyi5B$qS$6B,_,@gT"\4*d m`b^yk [<[xp[*S@f@+]]H^GB9Z1kbXuWV&`7"gW!HX\\RF5xgQ">>rQo~ZxG+g\i!Wu'!p ' jbV`rLS75"*HF/ sHq?g,Ge^x-e>i59rbM) o3QGQ[ FmD/XsC#.?h[3PF7 V9{ -ms>'Rd{q7{L`F5R>yeeXWS~j.#L_Q_VB %   r  6j SC 6 7 b : / awmw]A}8Dj_7.TV^i^iTi#_BWb N[5FJ[* *[6gZH'*Q :Xu 9jP'i`h8]?re",, Fdw-8kdP [4fK\yM ko1 FmwFwfZPF^F<8Fdt/'9kjsMtA{fom&V%i^+*q)+HYRfR?Yq<J,7Vr~T7<*p5qs,V8|#VjCt&0bE'dOQ bjyKR+Hq@m~8|J{+f5y[f?<Zwqw]wSdJFJJ@@x@>@6fH?K?5s5Rtfy1 [egmkV0lT {eyfed\x< F-JQp\]]8GtP mw>Zy)#e_ybHYP33<n('`g,KLQM:)mPQ1XpkukXT1:Xu}ii`sL^#^gR,{ G[\G ey ]Z9NXkmh}$`L-Wfk o2Po [?+|+xZWYgCZVr^Oh k   W ' Q*J!^ixVB888B`_b yDGCi7A+qG?3' b*uDH)JhR%#j9T,&W+GVm7|~_,J]]]6}7.%jtkZ1p{Z3ge> f>exo>H!|hV$9NlOv2(Y0'i-`8F|]&\io9VVT9Sk+Gxp]6,S3FHdQw(Ocl.lc7E Jq4{g@S|hT-`iX CD'm_>g  x4x[w?uqMq%Ri-^.|| |m^A   i  , C\b1 f ?N S9   h}  h . q &  E3;+S r    W: *   ~ 97 k_ qGV >y,7k`V_^.q$8._^{A { W  A3 ^ TX - j } } t r Nq(pFx[GYQ[ e Xo e [ G    ?  J  u :_ l)E[6wZF_<8P$w$8Vis}Zs _V[B.p6r.V^V/]b'fGDtdX]jePBs'XusL./~tVC|u154d< ); 3 aP w / W ` C  :wF>*y?6K_WN1FQdZZm*DYut.:JF4db9kMj~~jMdu:utw}<oQ>t4.>Q^o""Pr71k_.9C9j/DbFDDDJA_tkM'/9/d& /Mx`*jjpt@K~t8jjj~```CjMt.V^"|]m:foss_.M'*iy,t7b }}dP|PmR'uX9BBAATK-,g}j S!"A-BjvOM'tLc72(;*vPbW8/sfqR4qd%C b'w:DDDJ' i~ZbNb jd.:MT-]pKGV)PCZdPu3bkGW\i#q"hj8/"Nw*6?qLt^yg_^Bi~b;P$8V}Z#Y\*5GCP}N/[    r ^  r -/ b  W k v?mefrqB}tW`hB+^Z!t e}To J|Kd[\ShC*k:\'!0XtHrJ+>:goZD ( EYwO<2 FQZH':g:611',S\ 1X*u4 Huu"uh&~PV\^gJ"R@ {[H[Fdw'dPM<_x>L?JM-&k k)[4W*4[iKFgNj )({+H2oy\?#Ljeq]5@"Jr7"fL83kjCV&}u8D/@|8:}/_AS\[FsL a.   C 9   l.irC{ZF[> 4 G s[ # ] <w?H+ q h Z >RfSgA.&-:Z_8$g|-L}#-h!qQHw e`)Fdm%mdZZdj&Nu CP.^ <,@S'g{q~g]BSJ6,-"AA-"6@]_RC:Zd v \ D a@ k a- D sB8;V "mdGF) XP<`QH&Fx+]7}`si-t]^6ZMut&j9.k Vj1m(d+Gq7>LP8VJ!  {pR*eE x u   S   8 t DP2mH"[^H]7|h6L?&'p+Gyg/.Nvt [bRNNX{{&$!|@! ;/}S#JGRP mewd<33[333Rg)Fw|Vb&k_'A"{mmw\Zyqe\uFrLh.j0Y3`$73]M3BuAh/W~|~Tt-jWC}/8&~9M`V|,wO ` & tB t /# ^""_"&JT}s}L.^g.V} 76:D:?pP*f+f6qrq{}Rii>}Z-r"HK,q<:u!!]6b)o pS6,@q)|KNjs_9TNdGTs%4j9`-9Jj{g%@VsA}isBMMk bNPDXu` ZiT@WH*<~wMw3ubebXXSNNND::'w d){]]q<pou WXsB@Kp]e3PZgF@3ehps]7C8M&3o[9[MotF'uj99Wuj'jjW&mmdd:d:ubMt9.V_7#^hS,Jy]{[m{S"7Zs `@|-Cs`_tV~V~VjV9VLLV_i iHsqi_V8/2W  (XldN yiAJ"h #Ah"p[HFD`}o<-c_ ' X kd X :Q v(woQd?S7r|r^|.'Zx#i/b|07'NL`&u#gw3[ooxCF t}/bg!fd)R])dK:}ki_VL_u:#AKK?78_tNul2F2>c\D|gH HyN/4~oZj/:X wW3%L__ LF81`ub/C*MRW{C&Wk'YsHJ]4h<}$1NX~N1$}ZK,[*!o<D4xW3Bk}9Bsi%s_jBkWm:Q?!@^s9Db`$Mx.q5>FQN W)3x4tM&?HeCtZb%_WVA#-7q7-!#f Q#7Kr@]ogGg*g J"h GiW3d<Qm3!x@]#rAju8/Z3bYQ lf!CST#W^KSg+Ry\*\\H5+ <!c? up t s T " \* '[ x x te *    t  u ^    0OrdB!.gtK:FxxKP6D]{Mt?G~`Z9XB-|Fd,g'y^c  J /  $ }! H f     .  M  :<f5]V&N+\wmdP3*4* x pR!J@7-BBtMC/X/`d$ZwKb[t378g]*e}&b+g[$ ~H@LA#}f84 tCL,uN'f ZR)@x AH%6bBFob2>x;mX1W}M#q%+iZ W}B_-C|DP"">\|-q@"B""6jS9{55+9Wt~S"jJM/!*Dd<x.yLVqL%7M'F #Ah^-B~xG XDDHXu`"RxwD{@//&7LbM)bo*c;;v u t*4GK[of F *>]oR(`~L_7A,ed:8dh !y*6VMEYlbl1YE(1 bmtFL##_x[*MuHqd|i/ x  N u  o a> OR![%WdHy o[ ZFm13DDx:']ZVXQ 3 R++]?ry7 oPN`iArh{@*RP 2vZc3My,.|BL.LV_bism TQ* \f!e6^oG \!{g]SSJ@6,hHr7W}#/d?{T8Ltt c3N1Q'1X u4xc/099/kxZ b[+qB:  M0utg]!HyFX/fMHM+C/]u,:rd#Lxje[uQ[mex !xe]QG>^>#Qx3m  Lw3M \TWi8"?>$} dhDpG`s#Bi@JT%:^@!6?RR|Hh5h!|{6,gr}Cq6y+@L}T6fJ45>+><F2  D u  _ k N &' [LmZNPD p5?yX4M<Xi`h8,66"}%MT# Pi.8`j9'O ;kubX8XXbJk*)9`1' .iZ7)|@oeQQ5eRpFbCsp5^6rh/V1Cm3)[$3j0:OC .EV} }VV%"/HuppRm536KVd~&`Lj77"f>t)V#{ ay   & 9 9   H '{m# R_7~tW~Dd.se4-^ *QFZddP|)ALG ~u' GwN:jjL%#},Kg|J""~"X,@mSg!PHyD~ .Gog!oow*(RYv"^lEd3Qy*HV]"";@ q HYD >eVo#o[ ydgW.W_}} _\B,ht#CuD'K"{? Dkm9D.t.77J]?RffH?S4o#_3Pdmw dvPF)P))3ZGy2SD9jXm_T-8AT^trtB,^]?\xm>DkF1k9j9W~8s8}7|TSJHg{ {4q>]4J,H|SA#}VjXN fo5K"~KssY}E;;Y-| "X{5`V4G[e^eoo6oo!y>< wD:t~B%}7|7^"SqrqKS"}ABLjkC/&[/9Wjt~h~7tM#&7T|)"]*5S5HH#?+s$~q9"#s$C~`W`_AsJ6+>uw`VAW"Be-7O#vi;.d*tpM/FboD'g h:uW-V^#77-^#}8L9`&d to*iRf5G!!85R^fy6{qS64eduCr_^K#h},8]/!NHyP y"^&HO,3h3n8E`WX. dP<3:3<t<<L<F<)#G i8R~qjJW,W,j@g_*Tb+9ewgE O(d 5oJT8+T`1&Fvcl<:9WiJJ>mX&dC)```M/!tkW%F#@xfxF<m'wNu f%Ck R|./~MttL%LKs}N_.s~|9"@bJ6dKZZm_DtWMtWj}Vy7Q] )P" 7`Z d 4qR-9Z+Qfp+GF1++C!`t{,|LiT$gRLA *?e WyK"#q.!WHfk'4eP3om4 EYcY(>[!]N>+@K_$3mt91C}h]jR.G3"52> Z<! @K 8&w3>A~&e8uTM.fdmb (XFQ +yqpy-L[)tt:jtt~Tq8R_4[o#oAehQ HJg@A+fs>V8wtDud ?u]X1|.d)jxeQM4_#Rg+5{Q]@,Z,, 6u@]WqV|?*!x?*fy xg"<'hTtA7.-}#Liuk)e*f,|V_~/:X&W&.$KV!eT@?x8}9sJ+f}yLyCfR5b1JhV:d d3e [ y?\g"q@h7J{K,5Ry\>)*[bW 3PmN.L_-@?Ar*GQ4!A^_CCmdGe4 p!yygJ6,",G@JSgFq{:`}H-r4x Z^N}WGy\HR\*e)jZ9 XDZ/3`8L__o_[_>i _ is*4-4^4* ,SRg!q{{gS6?^#*[VdMb&kb^bb"k{u+HRH5g}:Mw1Z 6)d]+GXm<hGpRGK<dmmZ< oT 5]]fT*Z1C8_KrSRGi.~33) xQ*5R,@AiBX eRg.}7AJVy.*D8iLrrqq+pG G&eL<PZZ_F%)CoN5 Jrwi%Nt9jVD- ,FqQ gpAH!8tXS^ygV6$,@q! ).T]*wb'9BF)T<,m@JJJk@,M8|}K-Ts|.~M&^7bDi:B1    ~ ` 9  k1dP >g )F^w_MwmPPduuC..|r,6p o 3) *y3<))>[?S,A#-Chk@D'':buj.9}W~L`&MuNe+-19b&(W%i;#0Kr~r.rhAoBF/~QrA~h/#i/M$JXHX[kZut}t|SB!-[]FP3! ?Re\R?6q,KKBA|`,gN P GHV6F7xi@$_~Wt`9i|6{Q ~Bb"jHyB_is_yLR%5Mq]J66u@@Jg&~_+K\q44>* J|5]j_:3o *?gL*9[u0 :oCQ48^?3b`B4eA 6/]{7?f e*>QGQ[Q5>*, _&p?P>Jff!As9b53*xZHN{7skt9FG+M"sr-"#fh@<k[3~rJJf+\ yyf#Ri?+!!!e!!5+?q?6555@q{,hm8bCukDN'Z ZGQ!q5@{,hA#"J!R7Kr*>,oR4G dy5b{]WJgLp-G<@D/4%oA|GAgsiKW.'/x: !g]S{ 1 bm1/`AftCHN',ABd<M bo3> Gp\f+ffy!\*o xPwXtj8%#rV"@&@,^[_p&)+f S,"6&q?KZ51>6 5*!RA{`|:smj<D 3Zwk`.'Nk%b:k*Zf3 ^hqZ'e4T55S QhA#[47\|g@oF1@gy!f dG )mElm   QRlJh<psisK-1^dS!{fh*LP$OVA  gl5P\f\f5"rgi#~.j~t/sr`qB5y{po\6#</O c[E 6F*Vj6%~Dm$rg!\FPyZ?ZF]#sGY#Q*B**oM3v'M8\} d::3-@^Ti"E\ QGF1MLG-Fh2'6g/}#^S|TT__Cj kd\w<})FwMvNt&j_V|##g#R PK  >'CBi:W_%i9:7dKA7QVC [NmmZPuZw/~B:iXsu}_8Mk4N1+ 6Zh Q_.5.i@#rK-! o )<# 1t`LA#|qySe)3)g6QHh#7}sL.1%d%+BqLV#_iiiji/iV8~&buGX:5g6lOnPX):'''1|D,Xu\4o&`x4p8VJsBXPx*sfRu?++Q5?H6f _[B8B}X#|/{LpK|k9~"6.JBSL]Lg8qg]J@W,&kKbXXbiBMjW/{oD)mdo*f+do{S,+6^rT8A7-##-Kh.Vigss?sVG.:`~%:^FSGH?\gpp\+rrggApi`w:XPs[,\+!55?![]w'#VLtMWt+R\_H+J> ^ :-     s -V A% -  W M u'w<f*SA!V`u7eVy.5.HVo7w ytG8L<VmL.WNmwdeZPRZw]^kTh9]V[)#77-}-KGZ(v-hlg;?F e>3\3+4{!gq]]]]S1JF,e@^TsC >yK^"LqWR9Mt 4Qe7oeeeQ>  i-q GJx-FCXZo _7"Q!P PB;5OO4E3 *"-#8.//' 6"rAs.9tWkM'`LK'{:Xuou/j.LK5^)#u8}~7&bRF) GY;  4ye@9Qk:f'']:Nb,b1R3G*3'Ss/Wj`W9NDbj3T*y*R ~8RVVL>. FWmk1dwFep6QVM\?+b5bR*BFCfQ3{HiP6E2JP^ sytr1.m Xe<e yfyf5yJGxTo4!A676V+yM 4>/4~*V , G*>Qeo/Wj`M Fkbd` 7G**?Qv~}Av(m">H-6BBb[Gy#}rA`#k-N^DNu,MR$*<{5'yDbkkX:'\ 5m)o{{@!p*J)Hbu`TL#5F G Xe e MG   f  {  `  k8(~/+Sur: wZF3Ask2(l)3~PZw]fGNdC :uTC"tJS]BS,7|6A+_?.RRH!jWC9gM"jK8s}.AhtWC9&bKP}%G9@DP`o0O*l:tVTLqS\*|65e Hy6^^}`'CFuXD3Nk/9~#6%L_i_L@%sW'Dd3p[{ qy Z4'er)@P <F'<1 :'x *\m{<^i%38ms b|qj\B>s)3sB*`J')*1m5g\{"|||S5o@)?s T)fX[x^*5"A/^wV%eQ[xt``Pt'`__7|"J]sq8gJ"M^uD%&Z wZq<K##A[>S\eH!d1JD"D')"]*+S16.[it8,###-!-gK&Nw}i?_B%riB8BVtj``rW`]`j\txb~&M/&'bFm >@]7LLMN'_0bhtxZ7N9%gujfL-RR[])#3i Q<x5@V_d&>\&js?p-4oJ{<XM~!C!!!5XH1\ pwd P*)GeQ?{" K)#))<#FTFPZdgmw!G F1Nk:uk: dkN:{'i8$.V:u|MH^,uRM~G~M:Gw !Q^f%5!!b5H3>j\WWj{SS%]{|gpR4Go&e*By{T}Bj:M3No*Z e4>e P1Db b k4kQkobxbxbxNxXxux9twXiWT.}|BKti8Z4T8V}7qQWr-K!^ *4 R|As`/:bw<Q eG*4FXpff_fff{y! x4xQ ee5oee7[QGG>*P [*** \Rf Q*QZ P/bj`VtC7Dr "]wmm!HppDRb+g"9hW#`ti9D<~ejWC&H5!b: wgS6G\ghA-^##-TKg]RHe [9TtH.Be8%P Y`&   COt~34]88B8BtB.F~5/B\^]S^7+5+@K7^L9S' xoox*xQF s<:CAL|TS5"3(h2(LmtxD\ ,}:/&~bD.1}''1A:hN|buhKkNi1 kZo[q75LJ~|rirrgR?Po&CiTS!i8|`/*?]/.jCsA&~S#{5{P"7jjBDiPo}iL8d%C.Li._-r6_y8o/<: ) *5P[gS]]{y1ZF!_-hA-GKrdEYE*ww xj5{M&'PQ*p6AQ<&7}gfS>{@Fr'WNk+qKiVb_: PqQpx+Zg Xr-/MW#Wh`j@jtpt j`jbt/~hHL*xA@e ?JfpfR!*Sfg.`,kf1 )N` 8:bT,96C,CC/Tk1uZP *>!p@g"7iB.g$$R8V}F`^7@,\!>H\Pf\HC!TJR>^-FddZF)o #Kr+gK}KCu. &PP[ \p5,A{iqV{Vi!y-Gq\1[b<:uXNXN: Z3 'NPu'C~Ls#^{Jg5qJ TfV|%.~ d %yV{-r|hr@gJ],w1r_X/ kdR|G }ttsr 4QooF<Vw|'JkWi{#@,T+Ly*Wx uP1wmPZ<<FGZw+ .'WDXkk>bN1S hZsL[8.LR}gS@?@Jxgb!~\yV##RB!WS"DPe 6f?f++53\&4imr:J/WttWJ'#d.9GD m*QQ)X&B*Qx-^r|hK}>9+D@PTxs pjH`?~?Rp8# o"Hw[kZ1&CW&jj`C&.Vu'<ArQp\H?5+!+5HHRfyhAi. t*C4G[ooxkN1w3Fm NG~RV!-6!?\++ *>Q6QQKG4*Ckwyg ^*VGWok)dGN&Q8hc'H[ fF*ddF'ejf,WL'9k'+1u9Ri#Qh3d A  }kwPP[y\\p 3Zmwu}^"{w?dpF3))3Pw Df+{69CC|97&1G#y-AAqA6A78&:dG, g! GxwZD:&MtB~`9}8bjD:1:uNXkD:DbMuB/stBKA",]{!Ry@fT+q%t&sWb:N)Zd<kjVoeQ#GT>|>4444>G^oL ZM'1[]+!Gxg )|P-w'X79!jQwE%...Ojw&xN\SPA[i `f5!!Hy49xj<8m_}}V%~mP3Nw QQfy5\H???R\p+\*F1 >9eVhPg+y'N b*>G4  Rb: gZSS]qe4 5R\ppf\? @  AWp5*fS"||8^K-#V|Rm7'Tr~#"AS7qtq] @*"H]rCbJ'ky`[P1jLL#-\-#esZwwZu) H{J|K#8-9^uDJ P! H\efpff\H!Sh{AJAhrK7-]7ATp|e6P*:w1CLj6+j9 b )RG]Hi]'7w*HAJf!\*4 4* 44* ?R"^6|i-8BsT6h5g4RP e 3'w:NbD&tCsjr..88^8BLV_}`/^JHpup1R!Z,eARBr&$~X>c fH55HYfN ~Q.|Z"?u4/BPmwdF89NP1'~kiCABh"{,"\ >|e7xxoVeG* M&bf:R +wZ3S |7eB4Cp!X 6P^AAxTQr "RQ P>xN9w:|MgR x~`C&4+&79sWtDe8R_{"K|q!J>?)4Zxwwd<4e4!T\5!~!HNPo o k/pfgf!px  l 0 N a X N 0 O*[wZ yeHw :JXuu^ubXBD1&:X'w~<L#,g )Pq@1kK}9.MW`Wj`M&:dN>?6hNiWtW9L/}9MMt7T$h}|A"yerTF#u}8/B`9/h/96Mj\ G[Q4~MH@uiZ&G yQf RR\p Q QP1 u &[9 M`Rt~~@~t`W^CK/KTh"]ubD5fd)*Qx4#{Vh`A7Ab^FS 5yQ)PF b':9D1_dh *"J+]q,K{{qig_g}]SJ7JS@qJ]{>'+\WV A*>QqQG>f5>e@L )1FZwQRwZJ3o JH+] himtN'`w3%BVQ_issf?!K\h>"q+'CQ_mr gEv\vEf5@?{h}9kMQN?1{@1DX"J{W!BRip}}}_BWXf ?!d+p4<<:WWq85i3(c-wTr4p"Jq/X y,@g,5^4xLCPQ!Rg#6$h~A`#`#~-K|#{y\[FQ:PNJ&~R.s#^H]"@h]q{sL{.q]J,.LiTA_|J1<Hy[f+RqJJ"r}|T#'}wi)VV_}e[[A[[[geofooooewQ4X `R68V^s8sV..j,9e38qR&p9Myj\~5g^WVbmMGuhN'sjjtLT1NbeuP1ukhX:\dPfF!3)])h33_<P`dwuZ:<k))3Fd/CC9'&k:/W``CG\<7>586TL.}-,Bq-Hf]y?4G uM3wB:uCj}.VV8}%iBtX< H`&qD-iP`o ufX?:'q S @ , "",0@D]k?WG$iZ^D,+e jL-"kXDNbu C & Bj   s  A .  9J 2d!55+"TJu^P8x*N xy*GSe@xJgx[H4GmR]"LJ_.H joC3D/tCj8i._#7T-h7rAA-}Bt/6Sqk1wwmJmw7.D 'Q:N+bu6T--T&/J//9HCWj> %FiA:"N]bu+Rpy\+k"bbTbbLkCNZ9`Gypy*e <dtM bD'11: Nb CtFBoi 5J7rTrBt9&WKL_q1HF e Zp5k!jHp_>T3,dq{6|1Nk8jXCWj~~m~djmWmCw&b:P ^BC u 0 0Z3W _Q,4 pP >o_ZL~o>*41eb 9~M.MM96+yXdH SQf9+Xw!q5Tps4ixs h)6e yH+M!Hjy'>)F>XpfC~ <}rj]C\G3D  ~ <  WG  :v\+f6qJZ,4+,KW,/JCgtBr,+5oHRRk\f`fppy`d 44[?{)@d,@g'b!o<&CjP 'j 9  M D F W > +F6R@^h7##-#TA^,q^f4D wGD&h77rk"XD5DDXFu L/M@jt5~~tt j*` ` `j~R!8{V6}h7}LWbF 7]^r78~C&&rCTt-8^V%p4~kW&9}gX1q,A'X_BB&BW_~K@!55!,t^W/iWX'G)]4-p8R?j?&RpQ9~<. |N{`*mV /T%]7rf*[6x]oGRRQgA)FCF<FQH,!#,_-Btt&jt~b1 wP)>tjjR~g$s|A-+AoJC5G7PSX59G8exxKo[G4]pyG?J2v7LcWX)ZRG\_]^bid`e> l2 *4>G>O* 'kfMS|VB^`96&!WG8r SW!p. [A6Z+ybG/t8_[#T5|^6] +H-\Lftf\Hc5wq"^iC<w >O N9>i)^D+~x)Lu#L-K"s{!+!P*6?|qg8qtyk'edd3 &_\ )33R<FF,<)7 ./GX5d<{@)S4**>RQeZ1Mj~~t`9)PX1 Y01kCjT"VTJ!pg![p!d@VZ)d> p+{{,,hAJfG)_BXW9jDd~`o9yk6:|7 '}Niis&`^%Bgi+QAh<''^V9wPP35T_Z~N~.Bs#K^r@qrT-_9gSJbJJSgZ<3R3Fd NWC}i"7HS5pp?R@qhTs_.k'Lr+Dk< :   C ` W /  1 Z m>*@@_W~NF:Qu&fH5!,! {Q@e[G^4 0Y [dCooQ&pWs|TL@&!'d4x)<3PZZbPFj) #[S*f{56hLuq{Po R[)>xc) 0d N N 0 cw[F q[7*%Cb*XebZ`:.Ci|6J{y !+Z!2;S2 7Z V[?`9&@&/CjhK7%-}-7KK^,r|f>e|rT-e>}.y+~q")T#>p!-T|f@]4{Pq@BA-_jJg1dF3)3FdHy*Nek)FdwuX1mPd<Q 5x][G>>>_Qot9wDb1VdF-)ThrhK#L)~<<<))4Gf56gAAss-|@!?>F/%7xhG \!{J,rK-"Si+8e`Z/N9kXVNNNbku_/:<>pb'qSZ@,,,e64J]{g"fr5}{j6:K _$[* >Bnk9y4fN `wu8B./9WXF p!]6S!"S 3Rk e)'mo1'Kid;x+{4L[k3lOEElWb|6j #)@:fkkpD+gmrF_`b):Z:XbjMS+ Bi}b}i~L.L`L.kF9:?_]"O(2l,{:?t.4Fb[WD%sMjt`9sXNP7_ZDNOVZtL- X"   &  u aPVefSAi%B W +] 3i4W/&fC\~fy$>|d1eMd%%jwP3k)Z)FxG 4.o| ,mDG/(V  u    s  '&[?{^88ut C9MZ~ZmLr "XxMF 8js_L}u<<!fqg]q|TKphdS1f wg1+xBdK@]g]PJ,4fT#qSJSg5-4^d@2{  N k! k! X 0q(,)^#Rrs_BVV/_}b#rwd,dwb & _  -  9 M C6 &J J , NY|#Z_4+WS||/t.,pqx\>  F  M     d W  >Y? JQ|-h.C7rJ95%y7 gGe)PdeP4+ 6{}KM.DMd eQQ/[oVA<6bp /ojx>j&H1"T3%[WGGGNePw) 't)VFw|S:{bug6kN'r#sdLF.3 FwkMB`9K@u'\d,H|-@h}sB}`&7h"]ubD' Hpm< >o[4 3FHZm67'XLM~L%7]~GW&w:jZ8_}Gp}{iBr%VCtDttv(LrSO\b/t\Ls@|A}V.7^jC,fk:[ dmk<txs4K5q6@6#BTt%X9l:2) "K(cB'MkC~kXN.N_NXbu-AT^TK-#sL9$j$~ijWM7CMW`@j{~5f~t` M>/oy +{S6,),P,6@;J]0g{`{6{qS6-ATRr!,g?+HGpuj\+LSrTSL`MqC6CCMT`ti%tM/$.BVs#hJu?bD QmF)Pme[QQQ[o <1db/ C'MDCk9&&C`~%98~Vi_^#@-7AKT!^+h+|!"6Sq]]gJgJgJgJ]JJS6S"SSSS@,hAr}7L%}8~ttMt9j&jjjjjjj``WWMC9&/C9t9998CM`Tt"H.L_>s[}xxooe[QG-QT[|oS <d?y ;v*[  X 3 d & t   8 i   } LP   9x  ORq8BjWd&x*QC&_&&r&&]+ oX1)PwmZZcZdw D & jD   LC s   B  # K hT   @   ,H 6 6 6o ,  d   7  }    um;o[?+{""-7_j_&8NtCkwZFP)xfgJ)6Z""b,6@WJS]iggqhqqqSq{q!gRg]SSSgq?\yfR ?G+x{g J 6"<m|T71/_.8#W^:der4-8/X 4[w Z3PdFFFPZdwd<oG pR?D+b!+5HMf~ %[Ls)m#D7XKkh|ukXN6:Sgq{qwS36G7p.,~h/XZ-h>,\q5f{{{\!+?R\@\\hR?_+!Cc<!?H\y{ Go?Q)'9B A)q))? \yo4p\5y5q,rhr+|f "@ S gggS?@",hLJ+$GLi d N##N i8me~\j+j`jjt5f._ *G7[reee@Q{> H\45[ +)\333) >ee )Zp5bgWSJ@_66J7S^g|T!5?V??59!u]<"h7e[QGQ}[}o#r ,)\GxG 94jf~`@9|k}D8~W/'DbN/ZC<M)WW`3`F`ZWwWWWW`j1~DXbuuutCX/jmsF)r{<d4F X; 9 N~     %  X lWZkG:yH+ 'Dk!5RfyM~yR+.BVg_s}hs8.i7|6gsss{}gJ,h7_%i.jC&WX Z<3j<ZBh Xp jPVE;s8Z `y,D B8:KM".!s\KyR,gg7}%qW,&^/i`VV_8s^gAry  l|-i2~x 6h H&@ d,{X5%x^ZS'/SVrV/Ah'|P3V"y  T#\VML:3*>Hq]|h^r-@H7rP S~%5f^@pqR5!/<+\5Q3{g1q9%R 7|d,kJ]gqqgS@k1AFsG\q"[ TfH5+!!+555-5T+!"SSg{h-{gJ,iBhK7#$_#Arhqg%M\bm@G@H 4>o3Dm'1X::' odS8>:\5!k!C?fLh*ey<*eb[*CjHtSW&r7kw)x-QT>*4>Qo6SSSJ<6d"|^TA-m#F##-ATho|e[e<bh-/tsB8i._Ki86qW&+f*k[XXX X<bwk:99jjWCXumxxyf,gTT-7^Tq!+F w^D\CGWWC&kx4w+og^R5!+R->r)S1CHB #4rGQ> "HqThVB&ubZ ewFpH5+ ?\Fm>1Ndku'XukXXXXbuM_Ctr_g76HQqF@ OKvEsiZs}+JhV~j``jKj~J`9J:#d.9[N* ZPZwGx1F9:BC#BKh|K||hhh^T,T@TS^]h]r]|]J6hJA5 iB.  k   9 M C   u~9F:Hmxhs6`M79CW~7L|@r?6[Hmu 4M[o._}i8Mu )F)m[;OcvvQvlFcO21uZXeyd!)gxre-QGGQQ}[so}xsx.eQ>&* b F )* 4>GGG4 Zf+/S}6-f6]w  ? y 9 t > [ o $x Bo _[ i> s s s iy U? 8  { ~] 9S S g 0vRP  G!JV-V77~-uPi \jKNC3'4Op?c~i!!^!@\>q gF]wSJ@,Nu|T7kN1KJm)?Q*wH@M-8LB8;F` /Xx1x 3Pn m3n[P3\  oZ&W:~X~ktujkCbD1u'wG\qr s:NtkcCj<Q .88.yyyC1Z x4[\)nO+pb*/ }^~,i+7y4e^B3jFPd:wwP3 31Fbd9t/8}W#_o+t7bt<>v; y yE:4o&.PKD]R`4< 'DNNN1wP38 Vs 37d^|1jB|Khs%J{~/N mPq3g)S)S<SZ]wg{X&C`{jJ`W9|#VXjme Gy5H5?yyxo))NNCtk:MFD mxx5)S"tB"]HO x & Z $1 L _ _/ Ut 8   `   Dlt` C/&&+/9JW~KBhq#^,)q c!?R\RH5c!dQ]6\K{S,L~j`rjTA-iTg Z2;i2L.d< 8_3PKY6\v;fF5e6 ^fi@~KDwwN7h/~L,,"Ts._Wjk/'bZ:3 X)P:A&HtBm})}B>!9kh_<9e4kbbbuypf\RRRR\f/pCyW`j`WC/kD' Q:bF&j:%u}TCj|KBW/jCbD1 wXF1>3!4Jfh,Br`9iL8.89Ljs8K^SS?5 y FQ1FDwXXN:' wP woZ<RJ<"mgfX x Fwk13PeQ!yS,h-^_$jWC&biDL$ tM &:X&CM~}8SiZK~%J7"5@RJ\6\?!#LSj'hTAPAK^|6Fqw+fN*44*Dwpo+?STT8`LM9k0 LASR'GbmtL:k7{+p 4>GG>* f?!9j5LfQAr:&W|tA~`V9~X3*e R]y6*,xS)f'kGX[d)H"|73mhD@9\%Pi9#K_r^SrT#s{%Jj/78W&W9.ti.-sh,7gh^7q,s%#`V~:w:)F xxeQ><4**1*44&GtQo8LVVB %)<PZm D8WiLr^?"]Q3Hy(; ;>;em)e> >RRgg6A_r8T%-%8L_t9A|u1JqFQ\g]6768qtyC&D/`t}LT-,6f, erAe f#AV|~g`MMf`Gx_-[eR Fqdm|d<>9Hb|PLx`G &t. *Gro,q<m S:Nbru#B9~tW9&_r&"9{M`Hy%V}yHqTLVj/%bLDs' iL.t/':Db<>/9p9?&k'+w\< em u<m` X8`V___VB%##~#Mi8WjM9B&h,&//5/p&bHZ|Lw$`GbpNRD?D+b!W}{ST""h+Ap# Go7^),Fqd?> x1DbP M~1:::B:_1i1s'i'V'%1:DMXkuxg"&9MW`jtt"t6tJjSW]C]&ggg]uS:J6Z ohfK7#SK#7^_LLgV}y#*^xP@g{ 1Nk{ugS6ukN:rTA-##-dAFh3 @x[f4 Q3w N>u[oe> p?ubqN@1"wFG+JT,@sSgW?uuoumkCjtL8i#AT#^T^K7]spB>`w/D&k`Dde*R+5Rp G`x/: dx4 R@|7V. )333B3s<33Te#sQ.&!kJKw<8 &3Zx*1` o8LVLNB%jC.ViN}}sm_<LB88)BZ_}:A~qBH#x-#d}BM&m<x>&Cjp+BST^#",}"_B%Ait%W/`/k1d[HShuKDAK^m{P<\3[ d XjW:mFi Zh,@@P6 "e r\-S_h#W}BX1`9bN: C~P%o.48.R!Mu'!?3f[*4xm M>o%F^ u{WH8T"""f+@|V6qC?k:G)dd)of, .1NNkPQ&*M`~4eF~`9X9DC 9PDo[GG>G+Qex{g]gGQ<[o[53Sm, X,jg8y|o]w5k9>8 LVVB%Q`9&Tt&9NWtFQ!%.]BLLKVVV$VVWLB8D%vlvt`WXW`/j.Kq8_} P }1i1L'%W/mddwuk'bubb9bk%uA5CFj  u8 }   - h u")Jog{{#{Lg~S6)x+T-Ai8si_VVLVV_is~t`M9/s&V&B&%9Wt_W/76RX~-9`,p8 iGoxG}5L@jC^/A9-W--77V77#7-!V43 cm>  : N a k k- k a XV N8 :$ '$ 8_-lYJ;(! xZ 1(;/EtYl%..%v;mxj\C/,_/MC~D}w)r{eyQQGQ[oGyJ<Zm.j) o1::1-}dis}>7\|J],?\py"p,f,R,R,R"Rfy>rmw3FZ w'Db1b/`/~%iBVi^s}s@iVB.+\yyyfH!SK%%%%..W%%1m>W+k6x|K\--g-7T||@!Rx F[ }37FZ{mwGXZ7EcS\>PlE <ow3f6GL?] QrTA7\-!-##g,T}LVC`/u:/P~_|Q" eC} [|@Z1!H\p}T@qypffffff{p]yJ@@@Sg?>yR<g2h;28M<NZ>o +p?6!h-5\L4etC Xd)e>e>> wGxD FVNTC"V"|,r-R}yBtWRC!9&ShK7b-D7'A^6gwdZP<) {@>#5%SkrF W"Xh::Db/##h{5]dR'4.A Pq1b{6&9M7`t}`8sX mT>\SrAi.j@&gN w53H\f[pppf\\!H5],q@^7rK-#7TAhr"g6\S{+Fp bGW<dV-^1NkT_k1~F`C9*//y9+9CCM{MqCqC/5Nf<G*G+[o9o[>DH0{{WV+r[!P*Dwt'k8_}&}/_/8/&t9X'Po[GGGQ[oX')m<)FZmQ R!NCqS@6L,"hJ5 e3P"Z6PJ)g>?5fh4`1mF1ueex9`~ P'u&CjW9`WCX'DPw mdZxPePoFF< 3m u}A[> o)v u y p 9p Mf Cf \ \ R DH?v+ !3o !5R?yq ,[A)m8:uW9WbtD~:~1t'`'M19:DXkbN1M}A 1qX!p9`  ~M1yfHP+ ],^-PkC#t^JR >jG9G kR1{|w_dm9w')X>p/tJ%"_-"7,7J-]gqq{BqqqCq{'F+y* ZCb}#Cgs4--;OYVOE(jMd/)o*!uJX:A'% kZe+{, :KXus.~M//C&W&t9`8|S!y o<._:#Khr9|Wr`hjTjAW-C:idL.>tMH/!kb!NHDf:1''>'e'''111'''1DXueG* /j%L_} 4[ )FdwmZ<-AThx|4\|hK]#r-_.}V8.`$C./LsTkD6]Z3+?RepG*  p>H[+qx <bY9 't X u  B s   k :Y##w--e-#+#{##--}--C#>i%?tDg@"3e4 ",@yJpJ\SRS?]5g!q{gRJ"4 &VJ6pfb:p \\fwy< x[*<'f5i#hq]J,rK-rhTA7##Ah"Jq#gT@"{|K5GV~P9wk1 D 1Djbu_KrX|^7m >f}ssJ}r7#AThr||||7|^|rrrr@hqhhhT?Af-i%j/  4Go/~m%1Kg+\gpypR\5q\^@.79`'GCip\K\f"y54?o5)gZh%jm3F Q!!{]h!-o T&+To"J9gqq-]@J5h#GosB%xe> 8fV!gAJh6|666JS|gT{#}{9]6DFh[%?& {gxq{HHq]QS] gmX+p4 Xk/d>%8BHBB8.%%B\_ TmN]+Mo3OW:lP2[) GHH!@AV&N{]@T:b_CN' X'w:FkW hF6D?&.>7o@+3dG ' DN)X)XXND1x4 Hw@P3TxeG4 #Ty\5h#]6}9Xx46Sg{ppp{]6*[K_F.m '.1_:1'TJf*DZ jX89r`S+*o~j`C&[y!gu7u}%CuX'uudkbNe:RPq6eH{"|7,gH7[r"w{Hk Z&/'&9.s-T/`i6JAg{,@@6Ki`SNh<Q Xy\H5H5?,RpA84x P'bLT@qCVK+SHyR *eF D `}o pH]7.HC,X 7m8/>'![oS7L W)Fw'1lYY9l}:T6BfJ>ex 'MQy~J`9rL`C/&//99//&C`t~u1t`FCe bymR5Q!J|_`9&5Ry/Cj*o_d KN"S/W~%.88B88.5.f%*x%F8V's-KK^rr^,K@-6"BACBMkN'k 'P) 'Xo[9GC4C 9&fX5P] ,oQ4* *4"Gg[xf4PNN9`~~W/DbDd'3 )1ZDXb'kuu&u~kbXVD:::DNXk_%CD<xG* &94WGj[x. BLV_L 8~[9 D\!Z [4\ 1C L #4|G[o6@6,P|:T7&W~#7.A8KVTi^}^TK-iWusBC\u'd5F<F*m  1 N*k4G[xkXxDQ'*p?'N+\`[iFXK|tsK"^-}A8Lj&WN'ubbkwwwwwwwwwwXmdP<)) [yxQ"4 ^i*8Gom b$Bts%s77Sh54)r^A#/V}iLAB|8.Jgg@jC|7uDs 8ZjuxG F[pfR?]55|+5?R_pVVi*o7m' MZB}''3s8>MR!uD' ?y4):'bC8&CT`ttT`9VtX'3mxG [G4**4>Qe *Q<ZF :'b:NbkkkkbXX9XWXtXbku%B_}/CCCMC9&iV8X1W&mZZkP:P ZZdmdw< wdF Z b/}K <@Z{'k+5?HM?~HHHRRR\\ffpff\R?!~tJjWCK/_jub)D1x> wm m4mQwe:Nk  uN1 k*XQ:dwF'bx> &CpW?j~q8Si6"7^"Jg{S",@g~1?yGQ+J3^XKK^r/Wt@q+?~HjHMR9HH??HR\p&9 M>`ot~  Qj 9ykHd [p+g5J\@6@S{4[!p x3))))X)3FPdwC~mdVPPFK<<3@<<<<H<yFPZZddmyw?{6^_8d< ~ej*WMCCf9?9!CCCMMWWW``5`RjjttG~~~P~~jD`WMC9&9&CCMjb:B}7rDj.|K^}q.+WR\\H+kND]:1:NX8uMuw)e*DyF? qRJ,@rA6SqAh+?R\6fqy5\ [3 4b>>W44V ^J\ G?o"3-d8M1X1wmmuD NFCto4 j/ N*QxPx>3FF)oQ<*kM  >QoMPkbPC8_} )PswV. :k`&kN::DXuk:&jm8Ps<3))3FZs.'b:F9[t?L}!fo<}_uB8C...BBVs#T|_W,616,w)o7G*% W: w Z*F4FGd[o k9% )|3<6FFPZdm{ @'DbKi8/Wt8%i8BLVTV__"i]iss}}}!}!}ssi{V,B.#V`9/uX'DDN)kx 9~5_gJ6A"h,@ghAf i.P tbC&M`j`WM9&M8&9M^t8L^V#_____L8.Mu`X/D:1u1::DXkPCxjoooxxxxoeQG4jCuX:1''' 1>DeXk )C3t3<<FZm%%'NCu'Fo \b1qgPo<)mQ:yR/+WttWH/y [D dd X[*9W`j`W94[k'3mZ'bxQ>C4t4GoZj/DNC<j>~W1GZ woby9@BVhVhBr%~@9pkDQ 3 X:b&/M&8:Vs}FQyH?yoi)8D~/&W1~)tW>& u:Z3 Qd)'3bFZdmw&/CC9/mZ<kX>XNX\kJ&j%_|||"]sL+y[Fm%LimZF3)V)3CPb:m9< 8-7 -3d_D/M1B34R#],}L,St5Wp9 *4*&9CyWH`!t~~jW9!Rk14FFMiFm7KK'7NuL/tM/tb.Di1''-:rNu6{&`5%RV\}\H+iq.A&B:/<'4HRP\pXyC.Vs } s _L%t`WMW*jeLr%@Ap,>Rexxe> 5Rqg"%9rAkiF%j&uDue&W ~% B_so[> }_Bt/yD3 Q*Z?X~gJ^@6@Jy]{ ** ?pp] 49Qbo]-_$P8 sXr`@}H7 S444 R!]{Ag]SV]qjCH[D/tuX%:_7dh3,[@4@ 6,^# *GeV.3dtM/ Db/jw8[}5A@"J|gTqAq-g#S-6Kh^S#+yiB %G<Zw~`9 1''m' 4''f:Nk{@`},]Kg\>+??+3dq,:^Nbk}VB.%%%%....j&/1CWjF~eG*  *4G[tx`CkD3 7T |Q)w6S]bqqg/Sj67.8}.%'WP[ b: 4e:wNu'9CtLA.Lsri7B}LM~b~:8wVm}mmm#-#:XusV.~`C/Wi|u"Nq'5\ymZPyP\P+dwgT .'1j1bPdFo[oGe4e exR)d6bA&_W$t8tL~i.i#7#AhKKK@A-\}8 [W N3 44>G[eeoeoQe4[ G*yy\R5!],!\^-Q Vm.btW&M9C999C/CWj~NLm<hgfG #Khf?!h7i9N+Rdyx *RQxS"x[4 6Sf{H++Ry{4qGgQg[qeooox?fF w*4 GXGG>`4  sTpf\"R"R\pr-GBxC 3dbmF ) '1: ::3:P1mmZPm<<3)))e>*   4QxeQ)>Z*:9 t *4.>iQeox7^rr^xAo#[QG>>>>Q}e3wD##C#tiL.~jWC&tM/uX:9wWPtx>RH>t `WMXCC/CWj8}8-sAT^Ahr|6|+p| h>TQ7QG4 s8f!j&6N TPsVB88xBoVeso#T)d:,66M"rB7i}L~C}_L.&W8}-h.Ls,J]q{-AT^hh^TA-!_5%Rp~M *u*u*k u&yWR~+S%..%Ti8tW9&/Mt%VtW-/Kh|kN1|^A:X}&Vt.s-t`6WW`+jp~ *G[eoe[G*jy9?DS^w#dZdwV% N~Cj`WsMC79/@k?'R\\3\RH*5!y+q@]",,^J#{}5L%4FN&W%%%%tM/~W&&kMDt' .:BbVVB&.~.}9#khw[5KsC`kD'X'ZDkxWxxBiFm}iL.:NXkuu8k}XD-1 {yX C1tbM~M.k_}*?sgB^WiNLB8888w8m8d8d8d.mwj/b ''c'2 w<GYHN&SrhK-"q+\-Kr"S{ {gS@6,,,66@JJ J J*J46>,>*?,@S-5sy$4`o9&&<9d`.T"m5)y> ? {J"yHqS"S6SSgg\ wb&j],%|.K.i`V&LLVX_swP3-K^)|3Pw1b"6J]{C`~+~HjfCk'GeZ**4Qo)w1dF~)VheG* hp#\H5s5855H\y%_ T>Q6[[!Q*QH3Zwqw,mP)|[5"J]T5i CxwbD:kDNk9jWB}jCiBM~tWC9L9M`~-AKiKK#7{fi.G `Pk1d3wZ<e) p?!!+?H<Rm\\\R?+1Xu]/|`-sBt&TuJkkH*/etLT[f,^i.|hK7#-KrB6h\">52 v>>4lp(d]Q|S.jWk1Z[f?+5HpN4x9~ZB _'}11}mi_L[B8B?Lsg@,r6J6{yp>e/8x4^\g"^Ais%M`1Fb D1'1DXuFm b :d)wP34 5 FSmD`S8pre]mkM%BLgB,%K`BDwC[ kNDpD\NRX\uy>3mm3uX>:y@m< -oiG8yyyLr G"{F+y>~osTx]Q5gJ,KrTKVK^|~C6?ubN[NN XPbkukXF: o Z?F33tXd 4G[e oFoxo:eQ4WVRq-"77#A}VL.M$L#b|NDSDX5k e PC`td~3jM/x4pb51 qwgZgF{3)))H)* ) P w *>[x(22(F m 'DXkEvk0Nu19~$dVPF<3337G)QZ[exZ'uZ<`Bs[>s 84e~93b''uWdPFFPZdw`&13d3xQ*Q +*S>[x7s<_Zim}#|mJF54x>)f?C!%_5\ Q}PV%X9t~`WW.`_j%B_s####}-i7BATrt&16]<o>+H\py yGfoH!3gdA s'DXWkN' DuW&}CjA68{sA6]qg@q"J"T,]sL%RQ<FPP%F.388BV_ei s5@7^Tri86Sq.LiR>3#w-7777--#m[y7sA.hJ!f.i>x#h))6@6,[R|T7-q#S#6#,-,K,h@Sg6g+\g,*4r>->>48 CXfH!d3{ ])JP@6"1kMt|^-iB~j``%W.WB`V`ij}jttjj`7W^C9&J{!+!g,&C`~TsB%8BBtL`LML9L9L9L9V9_CiM}MMMC9A^D FQT*#}Bj4M[9//&//F9dCwMW```WC/mP<uD P >p5S6,Jg5\oyeG4 *QxHJ<Zw||"]?R\\R ?'''@ ^PV.xG.VyTyppJppp?pppfQ\xR?5e4g@fqA#7T6h]|!p Fk|jhK7._-K|,q\*e}V.xGWuR'wJe \|rrg|"h7@R 4>->A K^hr5|T.W,&@JS]g{&W8?pTQ?)Z*we wFex>G yH! *Ge]@"ZrNAuLXW'0Fl4d5]x,x3"ES'H~_ e#| "[wommmwxeG*1bp?Wg.6_}V.~|Mh/K-uskVk8bbC.%LssT7^6]hq#LW!9?&f&9W >oVr)F@dw\4ewmZF3xGfxG @|?-gi,L88Li||K,q6pf x <4dGG>* wP)f+Q],fH???\y@Q{53pZw>exomQd*dmH DJ`|B-K"^ShhT7?ys.*>QtQCG> R{,&rCA`#~%7L^i6{Hps8`pHbSFr# V)Z:t_8K_}6p*-xAKK3KZA7#sB~`MC99M`~8sA2|;EO6YgYYOE2g,P-_GHX JZTF3<Fm D-hM~JR x~ZCc u:  BZ  " HGd)ZNPu45 ] " k |: h ^ A Z  _[  ~ /  'l4ed  QFw+JT_jP43RQ {@*ed61q?L >#oKr||r^A[*?VJj9^#K,/M`!jyttj*W[CxxX[4m3H]eQr>-4**} V 8$$ .B_7r6fq?!{@q6h^TT^T-h|,Jq7r+H@f!\ * fHf!+]6?pQ"Jqo4R,rg6s.^A~#tjt7.hV},R4X/W}~s_VLtLWL/Vi}DZ7)T|,S{)Fw!D+k+!ubD{J<|Ke p_?8tW?/p*xX' ZvE1kd&<9MWWMC/)Zulkkuu&~/t_L##-^-#sLT~8jWMWWjuX8D:D7Nk@/`{@TL~tjjjt~.8B%LBLiB.#KrtM&,@JJ@6A/`B8&su'7mJZZdw+5'5b55+!WW&!?fb NQNNb)uw19btB7kD "qF?pe ypyf5e)J ~rK}-h,{+Rfp-pAfK\^?^hh^Kg7@_86g~j`5WpMMW*`Gte8s-h@g )<FdwqJ"2^O-l- K 'r D k     C t h -   L . B L& _ iX s s sF s _ U BQ $*  j C * G o  a D 0< Z   ' D a  W  L  - A K K A 7  U  C a wFO e Z5SQr LftH95gCJj,BshK7#Vs`V8D2jCd3bN1'3PdwmP<nZ3 e>G Ry\S?!|S^K7|-----V7KTh|~tjjjj~r^A-$B_}#iK.|`6b \l(*ewP)ex4[> y5g,ypf\r\rR|RH?+SH]">h[Axo[A4hSyp+fy\fpG4[e34Z\?;+Ylv!v5c?E\(pwFy\5o[Q@QeT}dL cu&~L$s#TqyS5\:yuk4:QoY2 3<;PvZd mbw/|wgwmRdZ PxFF Z4w*  * *(4;>YGcGlGc>Y*;ZHeq \h]itr/T7-#u-b7XTbruW6SqVT]@,]gg^S6B`ALFC>k:p\RRfywmmm4mommmdp++qg,h#|AiViVB_s#h,g8sHpKJ?\! @>Q|QG4BjRDcS2"r^TKwAn7Z#F)[i8pW@'rO_)~G`MWj.s G#e@f 3eFdw||||p|\rRrRh\hphhh^h h*h>rQ|[ee[QG4  "Jgp\R5RHRf\yy*wNi#5 e4>mGQ1[eeeeeoookx1ZQ3Pd 4GmQdQZQP>F*FFFPyZ?m{S61"kW"@gV^p4]? ~QsT "{!xH \\5\?_]`,b1":Sk+/~>8PT|EcvlY2hAd QsVL?L_}{J,7",@q]\Gp *dZ (2c2   0 0w 'P )vE eQ>w4F*)* *    ) Pw EvyR! ' D a uS "   u kh aK N# 0 Y;#OK| ' J  W  .5 R p |y  ,p {\ ?    g , { 6 h |-       0Y-whF),q)Pw5yE> '[ kx   o &[ /> /   R u ']l A)[%`\u15wpdddxdmPmmwvww 0w m d d 9Z WF j< j3 W) 9  NYdxxxoeex<d <m 1XCZ`~>RJAtW8/WuX: m1ZkF)9%soQ7 hf5rKS"i.|^KjKMK/T&h&/C`~JL?p-^*4>4*| Ki\?o{\gSgJ@6766,,i6V@LJV]i{K!?\y"S{p\R?55?qHg\ggq>xH)Z>wZkwFM~e \t!9q@pT-JA_iVB~BMB&Vi/M^j,q+\`&k'v E4([ x E)Fdj}"+[d3[ x>yHffpy]6 *Qo,JgoQ> qJKpR?B5++/5?RXp [ NFM'.b-,C`yt [~W/o> RuqkJu,u6S{Rb4:eZ3e4y5SFmT#Dk7/rW~g+Bi[m1XuuX: }iV<B.%Gf%+%..888+8f.%>3W&1NbbkkNP1 3[ > f S ,>e,S3w!NeZ/tN&.~_8L_VL#.----`-&#k: }_B%NC%L_i%_.V.8%Cj:k FF [*xx QZXZj'X_-7k-D#1DXNsD8:1'C':DDbZF/<`Fd%iuKM8,q|S!{gq6AiMtdkGZ 1NXjCt8_iiVL.~`/N ~Zt)j`WWMMCCCFMMM'MC9W/%Kk',]Po {S"pH+^B+RyjM/ &e&</9CCXMMC9&&C`tuDd)x> %B_}#KQ6ZgN9~.S_hV}VMk`'Nd F)m F)  3 P m3Fd'wNuwZ)kNo:*1''\:!Nu{/q~g]%g{K!]R5y>x >3QZ[me[G4mP)RQ g,H|^{KS-6""6Sq}i5V\L8%fHj!M9{{CtHy. _>e##--##x#Q-4- -AK^rypy*"Q""3FP^P-F3 Vo ~yW!/gr-kkbXNNNDKD::,Nbb?XN:e m 1mDZXPXPNP:Z'dd<XW%s<Am ,D]u/CW``Mq9J"b^mA-e f!{{iH8*xCmX'1bmP3ubN1xe Q>* 'pDHu+`LAS!?Rfyq@Gx^)dsBNu~`C/X'm)k[N1yH!d<x{)qwg]'J6"W%}|#Th-,@@@6,rT7##7T|6q?e)ZiB`m9Fo>yp/fM\jRH5!%8VSi}Ai$tCs_LB.&W~%8.BiV_i-ihii_"V]B%5\Wk' *4w4<44**x Q* >x *<>[oxX/Mj~o[> ~t`WC9&y&/9C CC C*94&4>GQeoD Zo)>< FPZddmw *Q o:NXbX3NF:Z'Z dddZZP3<3 3d <1Zbw9W'j1:DD:'%F%o ?~]~6"8,_Jq5f#4e )Fdw}V.tWC///9C`B}:#NAkTu^hhh^kKN7'#d)Q yyyy Gx#7AT^<hZrm||||wrd^PK37 [*}}ssssss>sxii_F_VLBX.%&&&jW9kD' wmmmmw9Wt8_7^mF)^7sB3dtb`M9&CjujuMk&kkuuN'ubmXPN<D3D3D3N<bFuZwM ~'NbjkCN1 Zk3XNNDNNbku)Z:u/`uX'~Z`39ubX NN3XPbmkDb/CCC9/N NmxZ*fo5G*  ?p 4>QQ[ eme[1[G4C Bif?}_8g@MD |rrmrP3)@Fgd!5'?1H1R1\\ fyP 4 R*>GQqegog{\ )eFZw'kCwmZP<) tj`WW`xtoooooo.oLes[G4 H@_%|K`:7Ph3  S3P+y'[k &3`PdddP3% %[*j/bmF))F m *>GbQeo9~L _)%9u Q3*[pHH+gSJJ]{+Rp?y *44Q>e4e*e Q 4 HJA LQx)Fdw8K6! om Z)xG QmdPF<N3) Mt~`9x[> 1P o>Ge* *dGoXd`XLC-Khr||rhTK~AM7-#N##w-P-37AKKT3TZTTTAD7/~__.#W7KKA-kbXbsk8t`&M9CM9`CjMtjtt~~_~-h6JJJ6"|%K8_}_%K|`C/"]&/C!jf4.oi)AF^P|PF)|^Ax*p_%]`&^A-#u-u7TrM@_g7"fQ{S"[ K!Sr87|9,HQCt%)i) 7rx*y6|A^VB9`kC 9CZMjBs3#XKhM_r{rHK#  i %CHuD]|7 'DsuV8%&Mt..8.%j/:tCm 4Nfqw6dZZd,wJq+:>Xk:ub:9 W``3W9 \Ng,mZPZd,w] !Nf4jo.iFms89XPZQ>R?gqT@A|S+|pT7 } _B.f5.BiK5]f+>fF >:Q[QQG&4& 1fmH+ H{,!?h\^^r*>@GqG>* ++f!5qq@6TrT_7W/97`^.,gK"+H?\fffG\eRx?x!oQ45S"K5\ QA|SFmHGo o>fw6P)^LoQ4 ~8}pR-5@? >Qee5[\G* >eR!X:'d 1Nbu 'k':1 111Z1)1'o[[[ex 3 P m '1m:ZN<Xbu[>* C ~ *.>i[-K<TwTT7Ns.C&&&bm< 3dC'~8`}^.."StM/J&KCj%jLsb#KmhPFPZm'X|rhhh^^^TTA7}L&MtCLAkXJD1'?  Gxe> 1N\k5/`%VAh|],7rhTBKAAWKTh|uX:111:DXM^.7i}8K|Mb6J]q{1k9~5Hp%8B8. %>[xtej>` ```5t~{K%~.9B_}kN:111#:7DKXTkT^^hhhrrC|M|W|M|Cr/hT7}BW/Ct%ikX-1h wJ<qx4f?!q@|A?fi 8owj1M9W~`M9/X'&/9Mm`<~%..%%Fwk`/C`~b'Z)xG Rt!M/S,k:rTAZ-<oe[[eeAorxS!f)//9/&ub N>:['xm F e 3F_xhP"5 GxPe  H3FdS"Db|rhhhr|uNm"x" ""\"""@"",A6@S}gL{$+R Pw':DNXb8bsXXNA:1, 5[m3Z< u/e48Vi_5L.St&^uLZ[f$\V\\f#yhJR\*5Ge]@")<"PJd{w!f:*ke 3/d~ 'Dbt9b Z9WjGHg"^A-tM&#A^|bD1@ g +?Rfywmd m*m[wZ:XXu9jukkkkutuMNd9<` B-<m"q!Rpyp\d5<{@[4^-yppp 7Q^d,S'qb/Wt!5?H\fy%88BfB?8.]AjC}8tbMN/:1'/'M'j1:DNkBi}kXD1}}}}s}} 1X7hW]+Bp}*->KGT>^*h^^K7\#!q6sL.h7~`WiMLM.MM`t`9Bik1w<[4_ .WX Qw3)w'xo`3d%%1k9j~ttj`WC/jC&&WBs-K^^^TAb-D}Lm< `[ k1p?dZPF<<"@q)Pm+pomZ<'u[C4t Gx8)Vds:7DTDh:||hT7Fo_ j\+:d*f{!@R4o6Zq5 y':NGNND:'F dwwmmmw:bC%sh@{]|- }%'~'/111:N:111'  d<1Nk9j8Pi:7KT9TtKA#8_}i8W/#7AAKKTTT/TMT`^t^^^^^~TjTMK&A-X_d%)~xCGD m< QdD9 ).<ZwK 1"X"uh-V%X1 ~tjd`Z`P`PjZtmNC~j.CL&VVVB%N1 `Xd<D 3Z/`1u%B_9st%%C}XsiVPL8.e%*%%%8BVi}G<m_8:D`N&ND'u Dd3dF)oG*  )4F[dZ'NXkM8/_C}M`t}~iL%j18_ZAr6@JJ@<,dw^#wZ.)jo 'P+ S"?S?e3X{M{{{.BLL!BR. G~W/d1uu9utuuuBisV%uN'WmXoFR>6\K{S,7|gpe^orZ,]b!RCj~*>Qt[We/e[[GD>4*d**4GGe )ymppy:u& 9*CGC[9o&xXo'[>Z)f?o[QGQe?y3do)1XNWBu_Xi:siV8tw9wNDkmPFFP&Z9wMWWW'MN9&&&&uD Z&&&&[&>/ / 9 M ` t>e%3Lws:uC`~s_L~8`.M.9.88LVi}/#`-AT^Br}||A|Trh^rKr#hT7i.L~Cj/b:'kkk :Xu9j/j8_}BsA^irB%~jWMCCCM`j~8Vi|hA#}L%sVB`%/ubN: 8imdZPKFhFPPZm|T#1Nb_.`/bD1kDF d[P < yfRHHHRfy3>Z[x DM.V}Q f!g,s_B%Jf~Gtj` MFCm&XZ3F [x Q*p 5q] J @4@GJ[Sogx{xeQ>?f\+>e{gS@," )3x3PdmwwmmWd&P<)X m>xoeR[+[[[[eeeooe![5[HG\4py\5y{fJR"?+Jq!Hy5y>e3FbDX9kMu`u`k`XMD9' k:mZPFZPdw[> D   /4WGje~~j)MP&mXZdFoee[x4 PyybMt 4[)Pwtj`WM MMM WW`jt~~d<<d'b9Wt~~jWC8/Vs7T|&9CW`"j"t"t~ttjWMr/K-kDi'L8%wmmmmmmmw~tjWM9& 1DXk9Mj9W~%8%_L}s7T-rAT^r6]{^-}8t{/JN^sZ3~ &NwF eG3*< Pd :GboM~3FPZ8d_dmmw-A^r1k/tV#^|^7,JSsS8SS@~6C:|Tw-< _x%G `y1\H+FeH!S?"\y*|[rrr|3mX"9@Wgt+f><:j9M`&~k:~jM/F>kyN51S"Pxr>h^^^R^^h|g@|^6AJ-]{+\ 4e#)7PKm^h|w"P,6@Sx]>qy?+RJp|h TA - #*#**  ###----f-H-+----7gAJT"rJ|rH^TA-Q3Z  7TmhP<)",6@xJeSQS>S SSSJ@@p6R,5"",@Sg!Hy5 \>o <>m[x'Nx/eMGj*~pf\\RHH?55~+t!jWM9&u{Nq'g ]]SSm]Fgq?pxx x[x3d )'FNmu'&D9bCMMMMC99/&&&/C&W&t/CM`.ti#^.Ls6JSSJ@,TsBsL`9W/uu9j/%WLti}s_B%%8BL_stW9&K|/"M]jR8_*Qx#7777#oseBQ>*WuDf5@^'NuV%M._8-_7}AA7-#7Tr"@]q-A^5rH\p|T#_typfuf'\ffwfPp3y)y)Fdypf\:H5W{V]@#-7r7K7##_B.}siis%8V}Ah7^|,@S]]S6h|ihTAC#um)eQG>G#[AoThr<d|r^ TK'A17:-:-1#1#'-- 77AAKK A7:-X#/tLA6SgqgJs"V.TW.MNk Fd<))Q34F w *NGe_-F|d""dT< s%o> CX' *e3kMm.FViiixV>8y?`J1"P xQ>4"4S>Qo!\<Z m>QeowxdP)>\{6xeQ|4| ,g\5?*{xS,3Z||wZ3 e>, Sq 4[{ S<6d|T-m< i8Gp+tW9gS@@@J/gMj+p.G8LL L'X<w&/D&kb1uwbFD1  m FxQ4 p\]SKi8S$RV #rw6X/yQBm- TDru||&rMht^TA-8_}}_8sL%W~t`DWMM)CCxM*W`tpH5!!%+V?\A*o,]3mDugJ"r^KA&-9#C`~%V7r6]#{7TrqJ""STL5R/fpy1yymp<\R?+ )Fm!5H:\XpuukN1p\H5{g J:6uC.}"6TJ]q"@Sgqg{]gSS66rK}_B8%6%S.gBVi}!s_8~W/5Hp/`*Qx%sK  @ g xgGJ"f+|T-Jr#_.~j-WAM^MhCrC|CM|WrjhtT7%L_s87^,@S8]iggqg]KSrJ@,""""^7}V.h7i.~C8uL1_sFQsyV58~qMg]g{X: +f 'GNu)P9j B_s }}}}i_wLP.) ~j`WWW`j<~d ''%F`/x4:Rw{36Q^ 7 Gx <m-AT^h'r1|11' mP3 )3<<<3),6JS][]*gggy]?]SJ@q6S666,666@"J6SSSq]gq+Hfy{gJ,h-V.8iT , S4q4>GG>4*qS,fh?7}S_"L8.$T.#BVs}iV7BrBBL6Vq_}!R#A^|*4>>>>>44444** ,6 Jg5\yyy y y4p>p>p>p4f \ RH5!yR!{Sq6J""Jg5f4e3d"6@:SXq!H&y999 />&o 3bd1m3:Xb[u*ukXD1yy ywdZF3)     *>QoPo:[uG4* / W ~ *>Qo%BLVFVVL8%N`C&&CWt%BV_s}9}W}t}s_V8~Mt`C/N'w9mWdtmw.Li 'Nu/9MW``jjjjj```W``jt8Li}}s_L8}iV8jCtW//&C&`tkD'~`C&:bbD&'`._ 1-NAkKKA7-&CWj}~_B%~jW9&ubXDD%D%N.b8u8BL_i/}W8VAsh}iL".~MrTb7:' 1Db&&&&X1 siwVdLZBZ8Z.m%%XM8s}V.`9&9~MWW/```WCk&N1D < e1*Dbppp/M`t [mDC`tt~`MC~/t&`M9&&/9CW`j&tC~j~~t%`BM_9sk}D_8wMZ3kF[4 3Pdm4GwedxP3o[QGxQeQQ[Go4* *> Qe pxfRH?F??HR f1pXu *>k>NG:>'> * f?!1Nk!5HX\1p P*Geo[G4 * ) 3 < <*<>Ao7-<Zw 'Db-K^C|t.LshT7}V8~}Mi&_VV_ib}D1 7^|,@SgqqggSJ, 1:NbhT7-/Mt#-7.AVA}A7-7^|s.Wbw<^-B M<dX1D k/wWdtP<) eG ~R+{gB]iSS]]q7Khr||h5TR7pVj b*44w>3GQ[eeo>x )yxxx\xxx@xh8/xxouoNe0e'[['[:eNouM `Qexkw3xxGe Q>*  > [4xQo < d3d'N1Xub:X1 wFwmxmQm4w 1:D N*N>DG:G'G G>4 d<\5{qqq{)Fw?'yX4o)&Z/////&:&XkukkbXND:'uXDmFwP3Q H {3@Z|Dhu^^^h|&&&"J{X?1y *[xP:XNuM.iX1 wsFBCux:mP3)3 1yD\X?k+!!5RpukbNGD1'3 mDkdF)Mjxe[[[oP1b/CMWjMMC//b1X 1 m< [>  :X 4Qe )NFdFx>y\?+!!++5??? ?'HNHk?55+!/CW`t!5Hft`C& QPubbXX'bNkuu/C`/tCM``jjj`M9&%%...%uX:'tWC& :NkuX1d&3& &&eQ4* *4Geuuku3mX/WM~BiBi7Tr-ATr^^^Ah#^^K7#V._.t`WMjM/MMW`Njjttdt3tj`WoCG& kN1ypff\\\\RRRR\1\X\ufpy9W~4Q.o8LVV_ _3_P_m_VVVV VV:VNVbVu_iis}}ukXD1s_8m<~CQ NR!d3qqgxqx{x 3Z+w5?R\fy >'x1DX)kmDCtC~L#T~W"/6JS]]uJX6D1'K it1m3xew[m[ZxP3 x*    **4>GQ[[[Q>%4% %%`9 [XF1 uCmZsPFF^FPZdwh7  _ .  mZF<3))3<PmtWC/b&`8L___VL8~W99`B}#T",66,"uNPxQ hAL *C>Q[:eoxZxxo[Q> Fw1uyp\RCRjp*[t)`dM9/&&:&X/k9uMu`ktbN1mFxoooxx~`Cx&o[> kDf'+ {@^7'-'K'h| dF)xe"e,[@eJogx+\ )FZmGowm P33P w[* dF4)[ 'y'f'H5wFgJ"xGrK#pR?+s_LBB+B?LR_f}y#^"gp5?p*ge,r 7)FZmimBw$wwww8_TJ5p *G[e ooo'e'[1Q1G1>:4: :1 1 1''  **444* yH''11]1"11''hK7 --7Khw,dgZw5y*[:b9jeQ.>B*V_ _ __ V4LGBo.%)db~jWC&9M&jt~~jW/uD &d9)WtoG  %BV}  #>Te|S<ZwR[3 d':DbuwF&CWxj>R.Lig@"#---r-^A-sL%s_tLC8%kXD'~` M9&kX:'mdZPwFFFwPmZmdmddmmD9~DuBW7hV,K,r,"rT7|T-iB%-ATh|||hT-LWb'm~Ft)j``WW `j3tZ~Du.BV9_Mi`its~siVL8~W&8V}kN7:h'',1@NSkSSJ,9tKB_V}%jC/}_B%W/ubN:'&9M`wtdF3)  )<~Ztw`M9/:M.s&CW#t^%B_s}_B|rht^/^^^b^^^hFh hh^e^4TKA-i L .>[o~jWMC9x9[9>9999y9?999/S/"&h^^^h|/M`~6gBs?f#7K^hr||  4G[x"6J]gg<gZ]wJ6As.dM3NGfdF3JrT7#[4 #7HATh|]"rTA7--|7hAKT-r@g+Hfy#Ah"p@\SH]+]]]J6gJ"rArT_AB#_8.tB9L_iiXssi_LY82$~W/u(u2EOYlv/j_AJ '!NHufW.}  K*4GQQ"[6e6e6o"x|KV.xeQ.>V*}##-##  4GQeooxsx_oLe8[$G4  $B_}-h, qGx+fF1 *>/Q~ex_Kr<d'Nu|hTA-b: w#F7ATh|<d,@Sq'NkR  *4**  \+&/CWSj"~rT%AL7}-7AT7h^|@{?fr^KA-#RJ^#-i7%AKTt^Ch&hhhrr&rCrjrrrr8r}|A,],J+]+{555+!!+?Rp!5? H \*p>yGQ[eoxxp\H5<d;{cqgg]]]S]{cE( qS,wdP<K)_WNZxooe[[QGQ4Q4G>GGGeGG>> >P>>44X44>GCG~[o.B V)_P_w_VLB8%22;2( Z)e% .88R888.]%,`CX'Z[4^7pR5iL.gS6.Li|hTKA777i7BATh|j9J{HpkXD1 p?wZ<]"rx7[>* }_B.yp\.RBHL?i5}+!-7A!A+K5K?AH7R-\ffpppf\iRLH85$!]6hK-$$.8BV_s}}_B$~W&}ikVX8D$0'''0DXu~~t~C~t8_}8ViB-^t9,u@kSX]Xqb{u{/j8L_ii_L8+Hjf9 u4bQXoNXXk 3FZ&mMwtww$w$w$m$ddZZPPF<<33)) $8BVis 3<#P-dAK^h| 1DNb|brk^uKu7u#kkbXND1' 7T |:kC",i6@J7S|gq,S{+Hp>[{o]@"|o|[|G|*|>eP:b|rhh^TKKA77-#ubXNNNXk&`L-ATrK@"]@qSg{q]J,^A#!5H\py-T|6q +R p*4>GQexp3\Z?!2Y{]@"  : X k      6 S q    & / 9! C+ C? M? M? W5 W! W W M C 9{ &J    T  k D LYj29ww &;Cl`~ ' N u 8 L i         - K ^ |       6 J g {                       a D cE({gwJP"3^#i%WX'dZPxPoZomooxN<dCt%L(i2;2( P}oi4L8%y?S"hA.BVsiB`/N _.P MG k'y>>}>sGsQi[iesxs} #7Tr"3@[x#7 7)AFAnKKKKA A2AY7v-#Dk/Mj~-KrtW9@gukb!b5b?k?u5+!/{WSj,^7#T8i,g#hHySR > }4s*_*L*B4B>8G8[BoL_s-3hPm"g!R1Dbu *G[o/CWt<d%B;Vls  0# DK N^ N| X N N D 0 '6 Sqvl!c+c+c+l+l!{J | K  ' ' 0s 0L : : 0 0 '   .Vs  : a7 K h r  / W ~                  6 ]     + tR Wy 9 / /   * > G Q Q kG D> 4 vY2 f?!gw@w,wwwwwmddZZZPPPZZZddmmww|hTA7-#wmdP<oQ4-AThrypff\"\,\6R6R@R@R@H@H6H,?"5!hqTS76h^KA77--###-AT^}hirL|8|%|rh^K7~t`iWBC/`//CMW``WWM9&uN'bDw'F e> 1Nk4Gex9CMWWWxWeMG9*& yk\DH5+dF!+?Rf)yf\qRgHJH6R\fyrK-4Qx}ssss s}} eG*p\RHHiHLH$R\p *Qo$B _})333) }_8oQ4` 9kN:y'yy 0:Xk  *4>&GCG`Q~QQG>4*  $8BViy}fH5!+?\p##-- 7G7e777-#<PmsVB.$.BLV_iiss's:sDsNsXsXsX}X}N}D}:}'mF)o#G7 Tryy,@Sg{4Qoq]@" ^7  s_VLBBBLLVisFw #:7uKTh|&Mj"Jgj5W\/ *X>1[ odP3 3Z 1bo[G4X*'F xQ>* * 4 Q>oe <)mP' N1uXu&&ubND1'&'C1jDNXbk%uLs-KrukXD1wP)[4",,6@yJfJRSH]?]5]+]+]+S5J?@H,R\fyrK#*>Q}[}osx}}#A^|3FZm,1SN{kR eZuN' d()(((e4 wZ3[4*G[oy\?+xeQ4pf\\\f!p+++++! Go)Z 51\Xu> Z(c  : ku b X D : 1 '   u N 'c;  ''1:::::1'mP)xwGm ddZZpPHZ!Zdm{qq q'Dbu!RyGx3Pd&&&& &&2&O&c/v/////&///9CMW`j~vY2 d)%.eB*VisyHq]J,h7}iVB}.V%%8L_}.L_ssV8t`#M#9///9CWj_8BiW/7TruN'mF)r^K7x[4yR+gJ#"7K^hrrh^TA7|#hK#i}._B$`99W~%...%~`~MW//bD1''1:Xkukkkkkk/u9CMCCC9/bDuX:l ; dd ypf\Hp5f!f\fy{G{q{ P1u!R&Mt>x<w`9Nuu: /CmMF`jt~~~~~x~xtotojo`oWoMoCe9[/Q/G/4/9CMW`pt?~]6~jM&rh^TbT'^h|F6xge[[e+o\*Z[:<jPZddLdsdZF3 xo-eAe^e|eeoox@g!?Rxfoy[G4 y\H!f?!g,|AqgsgL].]]gq{%Bi-!^Hf@q 4Qe+5?Rfy Q)xdeQ>*O  ' X  * > Q x     < d   1 N b k  u a X N D :u 0k 'X D : ' cE( 'DbmP3&CW`jj`W9 N3PdZ))dPF1koeM[~QQ[ex%8BLLLB8.)%)) oG.B_}R!Kq|S6,S{|hT7{S"}rL-Vj9j9uX19`.V} '1:DNNNNN_DBD:' ~~dF)%_-x|e[Q]GGG!GRQeoyRe5>f{!S6"@T}BjC&hK-&/s9VC8MMWWWWWWWW```jt~.B_s~j`MC/&}_B%kX:t`C9&c2 &9nCFM)W jt~~~~tjWC&3ZwbDEvmP0'4 444>>GGQ[[wemedeZeZ[PQPGP>P*FPPPZZdmw>e)Z :u&9CMMC/mdXP1<) mFoQ4efQ54 S6yppffff|py"@g 4G[ex5Rp  x x*x**4>GQeo)e 1 N)uPm&C`~ 1DXu&CWjtt~tj`M9&kX%N8DBDLDLDVDVNVbLkB8%9`tW/B_u}XD1''1DXk/-9KChCCC9&kXD:1111:DNk||rrr&rM|~|.Vi|r}^iKL-.~}MV8bND~:j1W1C:/DXbk9WtuX1mZF<3~3j3M39<PZw'DbkN1kN1 mP3'Nuoe[QG>94C*M*M M9 & NZxQ  *>GQ[eooxxooee[yQfQRG5>>44444q4]4J46>,>,>,G,G6Q@[Je]x{?p3PdGxZ1:::'wmZwPF<3)eG)*3F Zm  '*1*:*: :: ::11111f1H1!:DNXk/Mj!~Hp4%[BVs 3Zw':}NsbikVuLB8.%tu`uCk&u/CWj~uXD' wdP<3))<Fdw1X8Vs&C`~s_B.t`M%C8/BL_i}ukXN:' sVB% %'8'V'i''''#'-'-1-:#N#Xku}iVuLb8D.1%%%%8mBZLF_<i3}}iVx8oooooo~x`M/ &9<WP~m._ :N7bTkh|hT7&/}/i9LCBM.W%`%j%j.t8~BV_s}}V8~`9t9k:NwPm3ZPFFPZm3Pw1N1kb&MtjM&bN:1''1:Nk&CjtCk)GkDf?+Z)!5Hep4 *ep\H)5P!w{qmgZgPgGQQG>4 {qgSyJR6!"qJ",Jq6SqH4e+5HRR\)\)\)\)\\ \RRRRReRG\*fp 4>GQQo[eeeeee[Q)Q)G)>4 * oG y\5yR5q]SJ@66!65,R,f,,,66@ J>JQ]egxq{xx{oqegege]o]o]ggq )Pm!?f:X k>x <dubN 111::1'dP<) wmZ3F<>>>GQ[o<Zw)4* wwwww w w m*d*P4<4)>>GGGQQQ[[[eeeeeeee[ [)QPGm4* 'Nup\?+&9M`t~{gS@,rhTA-%.88BBBBBs8_.B%.ttWj9WMC9/&ubXNDDDNXbubD' /CwWPj3t ~~~ttxje`GM4C / y/pMfjf\\\\8\_\ffpy7Trypr\TH75}_q8J"h~Kt#j`WWWsWVW8WWWWWWWWM9/kDwZ<) $8 Li} ||yrfrRr?|5|555?HRfpy,@Sqyp\H5+!?\p!5Ry*>Qe*x[)Z >mGPG3[exo[G4 x[> pR?5+!!!+?H*f>y[o4[x3Fdm xoe eeeo1x:DNbku<Zu bX1D::D'ND:1mwZFF3)o[QGGGQ[x< d  oe[mQPG3GQ[oQ[e9o`x.BV_is s)i3V3B3.333) tj`WMC93/F&d2Y b :N a:   & M t  : .X L _ i } }/ `  } s _% LL .s      ~# `7 MA CT 9^ /r /| / / 9 9 C C C 9 /       N vr;hTA#Z)ixBo%eeox~`C&)<Pdmwwmd/ZMPjF<) .Lie>f5q@#^-7AKThriBj9rTAk#Di8wZ3`9xQ* ukbXyXpXfX\bRkHuH?55+!!!&!/+9?CHMRWfWpWyWyWyMpCf9H/+&S|-L~&C/CW`tk~N:'  tWC b 1 wP< v)v*.L_}*>Qe#x###o[>yH}}{}S@""A@^]{6+SRgp!+y5p?fH\H\HfRfRpRyHH??5+!4![x!+5x?QH R\\y\?\RH?g+6|{hST6TTT^r,"@@SSgqqq{{{qqg!]?SR@f@6,,,6@*SGq[eoxx?oyoeQ*Ge4  q]yJ\6H"5++!++5?H"R6fJpgpyyypf\!H55HR\ppyy{y]yJp@p6f,f6\6RJH]H{????!?R?HR \Qfpyd'by/pM\`Hj+jjj`MC/qS@,"6@Sg{kD!+P?H\pyxe[[ex4Qo < 3Nd`:b8_&&&&#&-&A&T/h/|99CMW`,`Sjqt~~!!!{S,.hL7iV.-ATh"6%S8gVs+Hfs _4LQ8e.x%.L_}7^|xxooeeereAooxs8jC)FZw/M;jYv  :. X. u8 8 . %         t ` M 9 / / & & / 9 C M ` t          % . k. N8 :. . %lY`EC;2(XD('(2 ;EE OO'ODObEE;;2&(W %.8(828;.Ocv~`M9/ & & & / 9 C W j c%;. BBBmB<.e4 j9pRk?:+ !wZF3)))3<PgZ@m"^- i'B1::DDD:::11''%8V'i'1:DXkC`}~_B%jM&~`/b:k: ZwQ)[3e[*x>Qe)P)w3[x@]F+dRy pR5!?f1Db4uoPDkkN1 wP) )/FMZtw%.BBBB8%mZPFt<M<<FPdubN::N::DX/uj8C_t8_-sA_KB^.hr6S{+Hff~H`C&JrkKX#ND::DNX}kiVL8%CtL}K|"6@JS%S8SL]i]}]SSSJJJS7]Kghq|{,@Sgq{g6K{}q8gSJ@`6/"&C`rTA#8Ls_Li}`/bD'1DX-TrCj"Jg%BVs{]6|}Ki_VL_B%BBBLjLM_/i}&/9MW`jjj`}WVM%/MuXX1'dPFFPdDwk/`DkB_s}iV8bND1'tM/'1DXuCt%Li}s_bBD%' `w9Pek>XD1''1:NXbk4u[uxuk bN:' xQ*w dZPFFFFPZm>e ':Nbu [*ubN1HqS@m6Z,P,<,36)@Sg {xo[G4*qS6yypffffp"pJyq5\ypH+{{yyp!fRf\R?*5[+3<<3{g SJ6"xQ y\?+!!5H\y r>TQ7[eee[Q>s*_ L88...f8RBHL5_+s++5H\y#Kh4e)"d6JS']bgggggC]W]tS~J@6"~j`M9&&99C|ChCK97&#k:w3o47T|f\RR,fJyg*o<:u&/CCCCC9//!&?&\&/9CM*`Q~x 38FVZsmwwmZF) }V.xQ*`XyfR?P555?HeR>f* *>4Q[ox3 Pm)333333/4  pR5{&]9@W"j~hTtAW-9b: mZF3))))3FZw ':XkuuskVXBD8'% dF%..88x8e8[.Q%GGGGGQ`[9[eeeNe[[GF> QyRy+R+{]66]{g]J5@f,*>GQQQG>|*| | ",66 @ 64,G[oxxh7xe[GV*tCRq6bD0^7vlY#OAEh2( ,g+\nP< *4x4e4[>G>>>>>4G>GGQQeoo)Z*6 S{fH+!!!!!!++5?Rf+yH\y >o >eZFNw92WOtlt`M /0:Nbkb: /M`~dF) eQ>*$8V i }*>[-3Am^r'b9"`@]{!+?t?WH9RRR\\fppy*4>GQ[[eoooxxuxXx:xxooee[QQwGw>w>w>>>>GQeoDk&C)W<`Pjdjmtj`WM9&ukkku/Mt ':NktM/kXD:1k1X1N1DD:N:b1k::DNXk9uMX`:~wmmmm%w8BL_is}1Nb-A^|ub6N]D1''+Hp'1DXky\&HM+jjM+/HpkXD*:41G1Q1['e1o1x11111'3FdmP3;Yxoeoo 3cdE(Duwmm/m9mMmMwWWMMC9/wdPF3 &//99//&b3DF'ZmmP<3)))3FwdmZF<)Dk / Mj)<Zm.(82L2_2s2( 7TwrP)o>f?|K#_{%qg]]j]C]S]]]]gggqqqqqqgg]SJ@6"&/99CCMMWW`jt~",6@JJS%SBSiJ@,-T|rAi.W&rT-b:sV8wdF3 jW9xoe[Q>4* 9WtyfR?+%8BBLLqBS8,.%hK-~jWM9}&_B.kN: wmmmw 1DNbkub~XtDj1`W MC99//&& 1NbuuukkkkuuukXD'wwumumumkmkmkmkmbmbmbmbmbdbdkZkPkFk\ \ RRH?55++++5?R4fQo Q)PwF1;Xvu 0 X u  & 9 C W ` t ~        8 L _ }      / C W j ~    i L .     t M & ~ ` C &  u k X N D : u: k: a: XD XN aN aX kb uk u      && &9 &M j ~      B _   u a X N7 D^ :| 0 0 ' ' ' ' ' ' ' ' '     |T7vYs2V.wP3 ~~x~`M/   &Cj%BV_ss}x}e}Qs>i _ VB8.%fH+{]6|hTA-tsjVWBC%/&jW9&&//9CuCkCbCXCN9D/D:1'bDwP)wed4ZPFPpZHd!m '{:qNgbgu]SJ@6,"ubN:1 r^A-}i_ L8$~j M9&dF)ubN:' xoe[[QvQcQOQE[2[[ eeee[[QdGP>34 eG4 *Ge)_8pH!~`9{]@,ubrX^DK1- msFL.xQ`*9 uX: 4[PmdZFN3u&x9GM `jt~\+g@h%A8#BLVVVLiBL8.%tjCCk1b:PY;eG4* wZ P*<>)Qe 3F Z dw wwmdZPF<3x3eP*Z w :XyfR5!k:q @m< hA#[>*   4>GQeoxxooee[[[eeox-ATr >GGGG>4* s iVVLLLVi}#K*|GoS 3Qe xo[G>4444>Qex <Z))))   )3dGwQQ[[eeeeowomxdZZZZZdm w)Fd :1kDbu&WBiuX7DT'rwP3 ,@]qxoee!eHofox*Go)<PZdmw<d (Ec:u9 ~ : a % V }    / M ` ~   } _ B  8 U s  t ` M C 79 ^/ |/ / 9 C M ` ,j It g~    ~ t`5CH&fyu:PxG  4[ *=QZexN&M~   . 8 LLV____)_)_3i<iFsP}Z}dmw (1s1B1;;;j;/1111X(1  :XuwdP3e=pR5!  9 W ~  8V!}!!     q I i L  r 7  ` / U $ b : t W 9   w d Z P F F P P Z d m m uw X : l; wmmw44* Du9Mpj\~5{~St"`M9&^7sL.9MjtWC&.BLVuVNVVLB.vO( ~~w~w~w~ww.B_snZs<V)8 joM[/>* yfR?+&9M`tqS6"^7t`sWVC./&jM9&&9M`~.BLVVLB.~W&k:ukbNdD<1 xQ*vlYOyEyEy;;22222*;Q;x;EEOOFYmYccllvvvvvvvvvmvPv) x[G4  1Nk9`ByifH+-]A6T^hr||K|-7^",@6Jg]g{+HRfp5yRp >e*)GPex2Y  Nu&xWQ~ y?8_S-^hA#@q?y#G-AK^hFrw|'NuC|t8sT"@q@{+\5Ry 4e 4G[ooQ *3PwpR 5(Ov  0 N k ! 5 H \ f /p Wy ~ $ Ly }p f R ? #5 T! |   , S q ! 5 R p5\yQ=)eZ 'FDdXbkuukbN:wZF3))<Pd(EYv ':Nbkuu0u:kDbNNX:a'k uudP<)))3FZw%/CDWu`t~&Mjt`M9&~t`M9%&&//9a9D9//&cE(wmZPF<&39)Mj  8_}o[#G7*AT^hr||ypf\RH?5+,!J]{      q I "+ 5 ? H hH -R R H }H 8? 5 + ~! C    a 0 lqOS(6 w|Z^3K -e4sV\B+%],jW9hK-k}biXLN.NNNNXXjbCkX1 &/dC<MW`jto~G~f?S"%h87BVi}sL.~jWC/ubXND:0' cO2}i_VnBZ.<%)xeQ>* .8L_pi\s?+}{ig_]LJ8@%6,~jW9&rhTA-bN:' }i_VB8.%wdZF<).8L_i} #7A)T)^3h3r3|)) o[G4 ,Jg5Ry *G[x )p<\F?P+Zdw(Ecv !'+05D?NHXRkRRRRRHH?5+9+M!j.Vi#Kr6S{q]J6"!!+5HRfyrh^TKA 74-G#eoxoooooox#-7A3[FxPdw )<Zm 2EYcv  ' 0 D N X' a1 a: kD kN ub uk uu u u u u u        / 9 9 C M W ` j t ~             . L _ }    & & /- 9T 9r M W ` t ~" J g         $! $! $+ $+ $! $!                . 8 L _ s }                { g S J , "         | r h ^ T T K K K K K T T ^ ^ h r r | |     } i U B .      | | r r h h h h h h $r .r B| L U i i s s } s s i _, L@ 8S $g q      t ` M / & { q ] J 6 "       | h T A k- N 0 cEmF) }si_oVQL48.pR+]~6tj``WrWKW#WWWWWWM}MiM_MLMBM8M%MMMCCCCCC999~9j9WC9C&CCCCCCCbCDC1C99/&&mZ< ek>X D:' \5gJ,hTA-}wim_mLd8Z$ZPPFF<<<<<333~3t3j3`3W3W[o3FZ&m/9CCMW'WN`u````&jMjtjjjjj%jBjVjsjttt~~#7Kh|,Jg!+55???55++!%.8B+B5LHV\VpV_______*V>LQLeBo8x.%%~j` WM3CF9d/w/& ((22(( wmdZPkFX<D<:3'3) ))) xxxxxxxxxxdP3eQ4   ))3 !p5\R?f!q4SQ6o")3*44 > GQeoxyyxyop[pGp>p*fff\\\RRHyHp?\5R5H+?+5!++!!{q]S@6"|hTA-{{qg]SJ@6,}"si_VLLBBB|BhBTB7L#LVV_iisi}V8tjWC9/&#7Kh|",@]q+Rpu k>b[XxD:'  )3m4* | h^TKA777-777AAKKyKpT\TRT?T5T!KKKAA7--##qg]SJ@6,,""#"#-77AKT"^"h"r"|,|,,,,,,,,,,,""|rh^TKA7-|#hTK7-#s_LB#.#-7AKKKTTtK`KMA97&-}iV8&$9CW`t~~~tjj`$`$`$`$`$`$j$jt~~~%~%%%%%%%8Li-7AKTT^^^^TTTKKKKKKKKKT^hr|",@J.J8SLS_SsSSSSJJ@@666666@JSgq!?Rp#-7 A A4K>TQ^[^ehxhhhhhh^^T T)K<KZAwA7---'-D-k------&-C-W-t-~--7777AAAAAAAAA77--######-7A.TBh_|s"6J]q#---------####q-g-]7JA6K,Th|6]{+H|frh^TK7#   s_VLLLBBBBLL L VV*_4i>iQs[}exoeQG4 }si_VL8. t ` C/ubXND:1' mPy<p\R?5!o[>*yfR?5!{g]SJ6"{gS@,rhT|K^AA7#-#iL$jM/ubD0 }si_VLvLlBc8Y8E.;%2% wnnddZZZZZddd~njn`wMwC9/&wwnndZZuPuFk<b3X)NN DD::11''' w mm)d3Z4*  1 Nk & C j **.4V>}>GGQQ#QAQ^QrQQGG>4* ,6Jygp{ff\\\\5\R\y\ffpyy>[x3ZwypfRH;5Y+v  0 N a    & 9 M W j ~  $ . 8q Lg U] _J _@ i6 i" i i _ _ U U L B 8 . $     " , @ J ] g q { { { q q g g g g q q { { ~ j W C 9 &   u X D{ 0q g]]SJJYJ2JJSS]wgPg)qeG* pR?!{]@"r^A-+5HRfpsiVB.ytpWfCf&\\\\fpykX:' >QowZF))3G[eoxxoe[QG>4    *4y>pGfQ\QR[He?e5o5o!ooooooooooxxx{qg]SJJ@66,"""xoeQGr4h*TA -ypff\}\}RsHi?_?V5L+B!8.{qgt]jSWSMSCS9S/]&gq{ukb!X!D+:51?'?H RR\\\ffffwfdfFf3\\\RRH?x?e5G+4!ypff\\\\\RRRHH??55+!+?\p!*+>5QHeRx\fy )TQT[KoA7-# )3<sP_ZLd8m%wtWC/uXD' dF ':DoNQX*b kuy\?!ugkSb@X"ND:1''''1:DXbk||rrhh^TKA7-#s&_/LC.M`j~~ttj`WM9/&~tj`WMMCCCCCCCCMM&W/W9`C`Wj`tjt~~$$.8BLV_is}}%.BLVis}}}}s}ssisis_i_i_i_i_i_i_i_i_i_s_s_}_____VVLLB8.%#-7AKTT^^^^^^^^^^TTT^^^h.hBrV|i|}}}}}}",6@S]]g}qi{VB..Li-!A!K+T+^5h?h?hHhR^R^\TfKpKyA77------7AKT^h|  *>G[exrTA# )<F_ZBm%~ ~t1tD~N~bu&9CMW`t~t`C/&%8L_&s/CWjt7Kh|~t`C/",6u@XJ:S]gq5Hfy  *>GQ[ewedoPo<oo eee[QQGxGe>[>Q>G>>>4>4G4G4Q4Q4[4e>oGxGQ[[eeooooee [ QG>4 ))))))))))))))  p\R?+!xo[QG>*  !+5HR\ppfy\R?5+{gS6rT7   *4>>}GsGsQiQiQ_G_GV>V>L4B B8 ..%%jWC&uX: *4G[moPx< o Q>*)))))))p ff\\RR\\ffy  ** x oe[QG4* >Qoypf)RX>NGDG:G'QQ QQ[[[eeoxwxdZZPPFPPZdmw  1:NXbku9M`~%.8BLLLLB8.%xxxxooo~e~e~[~[~Q~GG>44**     ***44444444*   %8Li}yf\RRH????????????55++!}}sssss{sqsg}]}]}S}S}S}S}SsSsSi]_]VgBg8q%{{t`MC/&&&/9CCMWW``jjjjj!j+j+`5`?W?W?M?M?C?C?C?959+9!99999CCCMqW]WJ`@`,jttt~~tttjj`WC9"/,&@J]q{!+?H\fpuk b*X>NGD[:e:o11'''111::DNXbkuuxooee[[QQGGG>>>uGkGbGXQN[D[:e:o1x1'''''11: ::3DFDZNwNXXXXX N'N:DX:u1' &CWtwmddZ%Z8PBPVP_FiFsFsF}<<<333) }}}sssiii______VV____is }})3<<FFFFFFF#<7<A3T3^)hr|       )3<FPPZdddddddZZPF<3) | rhT)K3AF7P-Z#mw}si__VLB8.%% ':DXbuukbbXXNN~NtXjXWbMkCu/&ukbXD:1' /9CW`jt~~~~tj`WWMC9//////99wCwMwWw`wjw~ww ~'t1j:WDMD9N/N&NXXXXXXXbbkuu&&/9CCMMMMMMC99/ubXND:11''''u'u'u1u1u:uDNXkuuuukkbXND:1mZP<3) &/CMWjtt~~~o~[~Qt>t*j ` MC9&&/9CCpMfM\WHW?W5W+W!WWWW``jjt~.8BLVV___VVLB88{%{qqqqqqqq{{%.+85L?VR_\ip}y#------## *>G[ex}}sii__VVLLB 8.%)%<FZdw 1DXk~~ttjj&j/`9`CWMWWMjCt9~9/&ukbXD:1'~~tttt~wdZF<)%8V isxoee[QG>4**        iVB.ypft\jRWHM?9+/!&&9CWj~t{WqCg&]SSJ@@666u6u,k,k6k6k6u66@@@@@@@@@@@66,"ubN:'||r hh^TKA7 -#wmdZZZZddmw-7KTh|mZF3, @S]q{ 3G)Q3[3e>>&>&G/>/>/>9>94949*9 //&&yfR?+&&&&&&&ukbX{NqDg:]1S1J'J'@@@@@@JS]gq{ wdPF3) !5Hfy*G[o )3~>44**      **44>.>BG_QsQ[eeooxx-KThr)<Pm1:D"N6X@XSb]bgbqk{kkkkkkkkk{kqkgu]uSu@u6"uuuuukkk"k6kJb]bqbbkkkkuuu&9CM`jt~!!++++!gJ6|h^TKKAAAAAAKKKKKKKKAA7-#}i_VB8..%%%%..88BBLLLLB%B%8%.%%%~`C&ubXD:1'  mZF)xxoooxx%%%...x.e.Q%G%4% %%%%%..8BLVis - A T h |   p\R?+!!+5??HR\\\ff\\RRH?5!||||rrh^TKA-#{q]SJ@@66}6i6_6V6B@8@%JSS]gqq{~`M/{qgu]bSNJ:@'6,"wmZF3eG*yp\RH??555+++!!!"6J]{qgSJ6"||rh^TTA7-#}s_VLB88..88BLVis+H\y#-AKT^ h>rQre|x||||||||||| |)GGG G>>'41*: :D DNNNNNDDD:y:p1f'\'\RHH ??555++!  {g]'J16:,DNXku/9MWjt|.h8^LK_Ai-}#}s_VB}.si_VLB88t.W.C.&..88BLVV_uikibsXsNsDsDs:s:i1_1_'V'LB88. %%%%%%.88BV_sm}ZP<) #-AKT^^hhhhhhxho^e^[^G^>T*TT TT^^^^^ph\hHh+r!rrr||||||||rh^TK7-{{qgs]iSVJL@8@.6%6,,,,,,,,,666666666,,,"|rrhhhhrr|"6@JS]gqq{{{~tj`WMC/&!+55??HH??u5u5k+b!bbXXNNNDD::11''+5H'R'\1p:y:DNXbbku 4GQeuxkbXND:1' ow[mQd>Z*P F <3)   *4>GGQ[[eeoooooxxxx ) F Zm  xxooe[QG>4*  '1:DDNXXybpbfbfb\b\b\b\b\b\b\b\b\k\kfkfufufpppyy&C`~.BVis}   **4>GGQ[}[}e}eeooooooooxxxx#x-xAxKxTxTx^^^^TTKA7-#  )3-3A<TFhP|Zdmw,66@@ JJ'@:@N6b6u,""&/CMW`jt~r^K-%.8BLV_is}-7AT^^hhhhh^TKA7-#####iL}.si_VL8t.WC/t`WC9/&/9CCMMMCC9/&kbXND1u'ukk uuukXD1wmdZPF<3m)P<)        oQ>) 3G[eoxxxxxxoooox )Fd 1':DDXNkNXbkuu&&//9CCMMW``jj~t~%%%%.BVi}#--777777%7.787BALAVKiTs^}hr|",66@@@@6,"si_VB8%|||rr~|t|`M9/"u,b,N6D@1@@ @@@@666,m,d"P"F3) "",,66@@@@@66,"xe[G4  |hTA7f#R?+#{#q#g#]-S-@#,#"#r^K-}sii_VVLLBBB888.....$$$}s_VB8.~tjj`WMC~/j&`MC/uukbbXXkNXNDD1DDDDDDDNXbku&9CCMWW``jwjmjdjPtFt>>>GGG!G5GRQfQyQQQGGG G*>>4Q4e*x   )3Q!e!x!!++++!!! )<FZm 2Ecv    ' 0 0 : D D N N X X a! k+ k? uH R \ f p y    & 9 C M ` j t ~         * 4 > G [ e o x   ) 3 ~< tF jZ Wd Mw C / &    ' : D X b uk au N : ' lY;( wdP3o[G*&//99CCfM?M!MMWWWqWJ`"`jjt~rT7iV%88%BV_s}~`9bD'} }ssiim_P_3_ ____xi[i4i ss}}f}?g@}}}siriK_#_VLLB_BB88....t.M./......u8X808.....%l%O%2nP<)%%%%...x.o.e%[%Q%>4*  %.88BLL VV V*V4V>LGLQB[8[.e%oxx 3Fd~~~2tYtvj``WM CC09D/X/k&u&/C`~8V}#ATh|kbXD:,1@'Sg{ 5H\pwd ZF <*)4> GQ[eox )4* % 8BVisypff\RHH??#5#5#5#+#+#+#+#+-+-+-+-+-+-+-+-!-!-!-!-####!#+-5-?7H7RA\AfKfKpTpTyTyTy^y^p^f^f^\^H^?^5^!^hhhhhhhrr||||rh^TA7#!!++5?H}HsR_fVpLyLB88..%%% % %*%>Qex ))33<FFPZm%w.BL_i} 1:Nbu}si__&V/LCLMB`BtBBBBBBBBL.LBLVLiV}VV____iiiiii____VVLLBBB888...%%%%#%-%-7AKKT^hhr||~ttj`WWMCC"9,96/J&S]gq{kbXND:1'{{ { {qqqqqqqqqqqqqqqwqmgdgZgP]<]3])SSS J JJ@@@66,,"xxxxxo|oro^oToKo7o-e#ee[[QQG>>44*   }si_VLB88. . %*%*44>GGQ[eeoox ~t)t3tFjPjZjdjmjwj`````WWMMC9/&ubXND1' w m dZP'F'<1<:3D)DNX X bbkkuuuuuukkkbXND:11' xo[Q>* ypf\RH?+!wmdZF<3)){q g ] S J @ 6 6 ,"")))))))) |rh ^ TKKA)73-3#<#<FFFFFFF<<33) xxoe[QG>44*  yyyppppffffffffffff#f#f#f#f#\#\-R-H-H#?#5#!####q]#J#6#,--77AKT^hr||r^TA-,6}@iJLS8g$q{!+?H\fy~ t j `WM C C 9 / / / / /// 9 9*C4M>WQ`[`ojt~)V[_ois} 3FPd#w7AThr':DXk",6@S]q{/CM`j~!++5555%585B5V5_+s+}+!!!#-!-!7!7+A+A5A5A?K?KHKHTRTR^\^\hfrf|fpyy6J]{ !*54H>\Qf[yeo  *>G[ox)<Zm xx(x(o2o2e;[;[EQOGO>Y>c4l*    ' : N a u    y p p f \ R R H ? 5 5 + !        & / C M ` t    q g ] S $@ 86 L, U" _ i s } } } } s s i _ _ U| Lr B^ 8T 8K .7 .- $ $ $ $ $ $ $ $ . . . 8 8} 8s 8_ 8V 8L .8 $. $%          ~~ jj WW C9 9& /    k N 1  m P < )   o [ Q > * u a N : ' p\H+qgv]vJl@l6c,Y"Y"OE2( mZP|0Q'eo )[x )Fd:Nk/Mj8Vs7Tr,@Sg{+H\p*>Qeoyyppppppppp py)y<yFyZydywyyyppff\R H?2+E!Ocl{q]SJ@,"|vrl^lTcAc-YYOOE;22( }si__VVLLLLmLdBPBFB3B)88 ..%xe[G4t ` M9&fR?+kXN:'{ gS@,mP3hTAx#[G*sV.ypfj\MR/H??5++!kXD1 dP3{qg]]SJo@[@>6*,,"|hTA-siVL8.$yf\R?5+~{~gtSt@t,jjjjjjjrjTj7jjjttttstVtBt.tttjj``WMCC9&~tj`WMCC9/&&/9CMW``jtt~~~/9$M8WLj_ts~#7K^h|,@$S$g.8BLV_is5}Rp *G[x## -7AK)T3^3hQeo7Tr",@)J3S<gFqP{Z{dmw!5?HR\fp y ''11::DNyXpXfb\kRuRH??55555555/?CHWHjR~\ffpy.BL_i}ypf\RRH#?75K+T+h!|",6@JSS]ggqq{{{qgS@,"|rh^TKKA7-#}s_LB!.+%5?HRfp *4GQ[eeoxxxxxxx~x~x~xtxtototototxtxtxtxtxt~~~~~~~ttjj`WMC/x&xoe[QQG>4** u kkb b b b kkuu  *44>GQQ[eeooxuxkbXN:1x'xxoo e [[QG>>4*      yf\H?+!mdZZPPFFF{FqFgF]F]PSPJP@Z@Z6Z,Z"Z"ZZZPFF<3) |rhx^oTeT[KQAG7>->-4#**  }iV8%yfR?!t`C&q]J6,ubND1' ||rh^^TKmAd7P#<3 }oi[_GL>B*8. $p\Rt?W+C&k{N]0J6 "|vrlhcTYKOAE7;#2( }si__VLLBB888...($2$;$E$OYclv ~~'t:tDtNjXjbjujjttt~~&/9CMW`t~.B$_.s8BL_is}#-7AKT^h|,@Sq#-7AKK+T5^5h?rH|R\\fpy" , @4JQSegxq3FZm+5?HR\ fy':DXk *9>WQtex%B_} )3FP-d7mKwT^hr|':Nbu"6J]{&9M`!t5~H\fy%. 8B*L>VQ_eixs}3Pm ;OYl   ' : D# X# a- u- 7 A K T ^ h r      & / 9 M W ` j j t" t, ~, ~6 ~6 ~6 ~@ ~@ ~@ ~@ ~@ ~@ ~@ tJ tJ tJ ~J ~S ~S ~] ~] g g q { {             { q g ] S J @ 6 , " ~ t ` W M C 9 / & &                u a D 0 cO; wdZP<3o[>*| rhTK7#f\H5!}s_VL8.%{q]J6"~rtTjAW#M9/s_L8%t`Cu&ukkbbXuNXD::1'mP<)wdPF3)xoe[Q>4*yfR?+!xoeQG>4*  {{qqgg]SSJ@@6,r^K7#}si__VB8.$.8BV_is }  *44>>GGGQQQQQQQQQQQQGGGGQQ#Q7QA[Te^eho|x ))33<"<,F@FJPSZ]dqm{w  !!+5?HR\py *4'>'Q1[:e:oDxNXXbkku )&)/39<CFCFMPWZWdWm`w`WWWMMCC9/ &&'1DNbk&//9CMWW`jt~uuukkkkkuuu~tjj`WWMMC99//&&uukkbbbbbbXXXXXNNuDkDb:X1D':11 ' wdZF<3 xooee[[[[[[eooxwwmdZZPPP FFF)F3F4*  wmydyZyPyFp4* $$...88 BB*L4LGVQVe_ois} #-)737FAPAZAdAmAAAA777--- --'-1-D-N7XAbKkTu^hr|",6@JS]gq{&/99CMWW`!`5`HjRjfjytttttt~~~ ~ 4>Qeo )3<FPZdmw~~~ ~~~'~1~:~DtXtbtktujj``WMMC9/&&u&k/k9b9XCNCDM:M1M'WW WWWW`````jjjjwtmtm~d~ZPPF<<3))  %%.8BBLV_is}}xxooee[[QQGG>>44**    ##############--7AKKT^hrr|",66@@JJJSSSSyJyJpJpJf@f@\6\6\6R,R,R,R"R"R"R"R"\"\"\"f"f"p"p"y"y",""""""   *4>GGQ[[eeeoooxxxxxxxxxxx|x|x|rrrhhhhhh^^^^TTTKAA7--}s_VB8.% ))3<FFPZZdmww~ttjj```WW` ``'`:`DjXjbtut~~~~~~ttjj``W&M/M/C9CC9C9M/W/`/`/j&t&~&&/////////999////&&%%%...88BBLLV_iis}-7AK^hr|",,6@&J/J9SCSM]W]`gjgjqtqtqtqtqtqtqtqtqtqtqjqjqjqjq`q`q`q`q`{j{j{jtt~%!%+.+.58585B?B?B?L?LHLHL?L?L?L?B5B5B+8+.!%~j`M{Cq9g&]SJ@6,"kXD1r^K7#mZF3 }siVLB8x.e%[QG>*  ~tp`\MH95/!ubN{:q1g] SJ@@6,"mZF<)|ror[hG^4TTKAAA777y-f-R-H-5-+#####qg]J@6"##--7|7r7hA^ATAKKAK7K7K-K#KKKKAAAAA777777777}7s7i7_ALABK8K.T$T^hhr||~~tjj`WMCC9//&&&,6@J&S&]&g/q/q9{9CCCMMMWWWW``````jjjjttt~~!+5?HR\py$8BLV_is}  *4>GQQ[-[7eKeToho|oooooxxxx,x@Sg{+5H3RFfPpdw 4G[o '1:D NX)k<uFZdm&9CWj~1:NXku%.BLVis/}CWj~#7K^r%.BLV_s},@J]q-AT^h|!+?H\p", 6@*J4JGSQ][geqoxx!+??HR\ffppyyyyxooe[QG>4**  ypf\RH5+!ypf\R?5!{qg]SJ@{6g,],S"@6"|r|hh^TTKK7A#7-##}siVLB.%}i_L8.tjWC/~j`WC9/&ubXD1' ubND1wmdPF<) wmdZPF<<3)xoe [ [QQGGGGG>>444*  xxxxxoyoyopefefe\[\[RQRGHGH>?4?*5*5 +! {yqp]fS\@R6H,?5++!|rhTKA-#}iVL8$~j`{W{Cq9q&qgggg]]]]]]k]b]N]D]0]']]] ]]]]]SSSSJJ@@@666,,v,v"l"c"Y"Y"O,O,E,;6;6;@2J2J2S2]2g;q;{EEOYclv !!'+05:?DHNRX\X\bfkpuy& 9M W*j4~>>GQ[eox$..8BLLV_s3}BGLGVQV[_[iesoxx#-77 AKK)T3T<^F^FhPhZrdrd|m|w ':X"k,,6@JJSS]/]C]W]j]~ggggggggqq%q8{B{L{_i}#7KTh|",6@S]q{+H\p{{qg]*S4JG@Q6[,ex|r rh^)^)T3T<K<AFAF7F-P#PPPPPPPPPPPPP}PiP_PLP8P.P%PPPZZZddmmwwtj`M9/ubN1 mZF3 wwwwwwmmmxmomemQmGm>m*d d dZZPPF<33)ypf \RH?5+!xoe[QG>4*  {qg]]SJ@66y,p"f"\H?5!{g]SJ6,"|r^TKA7-#"}"i,_,L,86.6@@JJSS]gg~qt{`{WC9/&ubXD:' wmdZP<3) o[G4  !++y5f?\HHR?\+f!pyq]J6" |h T A*-44>>GGQ[[eeoooxxxx}ssi_VLB8.$ )33^GhQhQr[re|o|o|x||||||rrrr||||| )33<FPPZddmww|rh^TKAA7-##'1:NXbk}s&i/_9VCLWB`8j.t.~%%%.8BBLV__iiiss}}}}~~tt#j#j#`#W#M#C#9#/#&#####----------###u#kkbXND:1' }i_VLBB8.%wmmdZPPFF<33))  ~tj`WMCC9//&&xoe[[QGG>>444*************  u k bXN D :1' ypf\\RH??55555+++55555??????HHH?w?m?m?d?Z5P5F5<53+)+)+++! !!!++++55??HHR\\fppy )33:>:GDGNGNQXQb[k[keueoxx  &&/9)C)M)W)`3j3t3~333<<<<FFPPZZdmw%%.88BLLV_is} ''1:-:ADKD^NhX|bku"6JSg{+?Rfy *4GQ[e&o&x&x///999CCCCCCCCCCC99999///////999CCCMMMWWW````jjjjjjjjj```x`x`oWoWeW[W[WQWGW>W>W4W*WW WW`````jjjjyjfj\jHj?j+```WWMMMCC99{/g/]&S&@&6"|r^K7#s_VB.%~t`M9&ubND1 mZP<)xeQ>*uuuukkkbbbXyXpNfN\DR:H:?151+'!' {qgSJ@,"|rhTKA7-}}ssssiwiwimimididiZiZiP_F_F_<_GQ[eo3>u>u>k>k>b>b>X>X>N>N>D>:>:>1>'>>> >>444***   w mdZPF<3))   yyypppff\\RRHH??x5x+o+o!oeee[[[QQGG>>44*   qg]J@,"yypffr\^\KRAR-R#RRHHHHHHHHHH}HsH_?V?B?.?%5555++++++t+`+M+9+/+55??HHRR\\ufkfXpNp:p'yy yyyyyyyywydyPy4*  yp\RH?5+!  *44>GQ[eox{qqg]SJ@6," )33<5>?>R>\>f4y4444*****  * 4 > GQeox)3FPZmw yy'y:yDpNpXpkpuppppppppppppppppppp&y/y9y9yCyMyWy`jt~%.8BLV_is}-7AKThr |   *4>GQ[eoxx",6JS]g{ )3<<!F5PHZ\dpmww 4GQex  ) 3FPZmw''''111:::::DDDDDNNNNNNNNXXXXbbbkkkuuuwwmddZZPPFF&F&<&</3/3/)/)999C C CCCMMMMMMMMMMoMeMQMGM4W WWWWWWWWWWWp`\`H`5`!````````{`]`@W,WWWWWW|W^WAW#WWWWWWiWBW%WWW```t``jCj&jjjjjjjb`D`1``````WdWFW3WWWWWWWoW[W>W M MMMMCCpC\9?9+9///&&gS@"|hTA-si_LB.$~tj``WMMCC99///&&&&&&&///99999CCCCCCCCCCC9999999999u9u9u9u9u9k9k9k9k9b9b9b9X9X9N9N9D9D9:90909'9999 9 9999CCCCCMMMWWW` ` jjtt~'00::DNNXXbbkuu&/CWj~~~ttjj`WWM.MBC_9s//&-K^|"6uSkqbXXND:1+'H'f 4Qo[x3Fxdxxxxooo(oEocooooooo e 0e Ne ae ue e e e e o o o o /o Co Wo jo ~o x x x x   . B L _ i }                               ) ) ) 3 3 < < F F P P Z Z d d m m w w } s s i _ U U L B B 8 . $ $    ~ t ` M 9 &  k X D 0  vcE2 wZF) x[>yR5qS,rT7sVB%~`C&bD' dF3x[>* fH+gJ,|^K-}iV8 $'11:D~DjNWNCN/XXXbbbkkkukbkNk:u'uuulYE;(wdZF3)uuuxkokekQbGb>b4b*b bX XXXXXXXXXXXXXNNNNDDD:::y:y1p1p1f1f1\'\'\'R'R1R1R1H1H:H:H:H:H:H:HDHDHDHDH:H:H:H:H:H1R1R'R'RRRR R R\\\\\\\\RRRRRRRHHHHHHHHHHHHHHHRRRR\\\\fffppppyyy *>G[ox)Qexuuu kk3bFbZbmbXXXXXXXN NN2NENONcNvNNDDD::::111 ' ' ' '' 0' : : D N N X X a a k k k k u u u u u u u u u u u k k k a a X X N N D D : 0 0 '    wwwmmmdddZvZlPcPYFY<O<E3;)2(   mdZF<3xxoooee[[xQoQ[GGG>>*>444***   y f \ H5!        **q*]*S*@4,4444444444|4h4T4A474#>>>GGQQ[[eo}oix_LB.%~j`MC/& )3<uFkPXZNd:m1' 'w:mDdNZXPbFk<3) &9M`j~xxooee[[%[.Q8QBQBQLGVG_G_>i>s>s4}4***         #--77AAAKKKKTTT^^hhrr|yppf|\|\rRhR^H^HTHT?K?K5A5A5A+A+7+7!7!7!7!7!7!-----###!!!!!!!!!+++++555s5i5_?V?L?B?8?.H%HHHRRRR\\\fffpptpjy`yMC9&ukkbXNND:1'  ***44>>>GwGmGdQZQPQFQ<[<[3[)[[[ [[[QQQQQQQQGGGxGeG[GQGGG>G*G GG >>>>>>444*** pf\RH ? 5 +!{qg]SJ@6,,"||rh^^TKKKAAA7777777777777777777 7 A AAAA A A A*K*K*K4K4K4K4T>T>T>T>^>^G^GhGhGrQrQrQ|[|[eeeoxx )3<FPdm"w",66@@JJSS]ggq q{'1:DNXXbku!+5?HR\fpy&/9CMW`jt~   *>%G8QB[Le_oix}#7A K^h)r)3<FPZdmw",6@S] g{1:DNXbku!+5?HHR\ffpy&/9CMW``jt ~  *4>>GQ[[eeoooxxx%.8BLVV_is}###--7777AAxAoAeK[KQKGK>K*K T TTT^^^hhyrfrR|?|+{q]S@6"rh^KA-#}siVLB8.~t`WC/kX|D|1|'|rrrhh^^TKwKdAP7<-3## xeQ>4  }si_y_pVfL\B\8R.H%?5+!~{tqtgj]`S`JW@M6M,C"99/&|rhTKA-#ukkbXNDD:1'' }ssi__VVLLBBB88w8m.d.Z.P$F$F$<$3$)$)$$$. . ..888BBBLLLVVVV_____xioiei[iQiGs>s4s*s s} }}}}ypf\RH?5+!{{{{{{{{{{{{#{#{-{-{-{7{7{7{A{A{K{K{TT^^hhrr|"",,66@@JJSS]]gq{{!!++55?HHRR+\5f?fRp\ypy 4G[o  )*<*P4m4>GQQ[e ox1Dbu&9M `t)3<PZdw.BVi} '1-:ADTNhX|ku",@S]q{&//9CCM!M5W?WH`\jfjptyt~   ***4%4%>.>8G8GBQLQL[V[Ve_eioiosxsx}}xxoee[[QQGG>>>44***   yfRH5!qgS@,|hT7#}_B.}}~sjiM_9V&VLB8..%kbN:1 wmZPF<3)  ~~~~~~~~~~~~~~~~~~~xxxoooeee~[~[~[~Q~QtQtGtGjGj>j>j>`>`>`>`>W>W>W>W>W>M>MGMGMGMQMQMQC[C[CeCeCe9o9o9x9x/////&&&&&&&&&&&&&&&&&&&&&&&&& ))333<<<FFFFFFPPPPuPuPkPkPbZXZXZNZNZNdDdDd:d:d:m:m:m1m1w1w1w1w1w1w11111''''' wmdZPF<3) xxowemed[ZQZGP>F4F*< 3 3)  yppf\RH?+!xxxxxxxxoooooooeeeee{e{e{[q[q[g[g[][]QSQSQJQJQ@Q@Q6Q6Q,Q,Q,Q"Q"Q"Q"["[[[["["e"e"e"o"o"o"x"x,x,,,,,,"""" ))3<FPPZddmww"""",,, 6 6@@JJ'S1]1]:g:gDqD{N{NXXbbkkkuuuuuuuukkkkbbbbbXX!X+X5X?XHXRX\b\bfbpbybkkkuu *4GQ[ox&/9CW`jt ~)3<FPZdmw%8BLLV_is}'1:DNXbku#-7AKT^hhr|&/9CM`jt~"",,%6.6.@8@B@BJLJVJ_J_JiJsJ}JJ@@@66,,""###---77AAKKT|Tr^hh^hTrAr7|-}s_VB8.t`WC/&|||rruhkhX^N^:T1K'KA A7--##wmdZPF<3) xoe[G>4*  }}}ssiii__VVLBB8..%yyyyyyyppppppppffffffffff\\\\\\\\\\\~\~\~R~R~RtRtRtRtRtRtRtHtHtHtHt?t?t?t?t5t5t5t+t+t+j!j!j``WWMCC9//&&{{qqqggg]]]SSSSJJJJ@@666,,""""u,u,u6k6k@k@bJbJbSbSX]X]XgNgNqDqD{:{1{1' wwwmmmddZZPPF!<+<+35)?)?HRR \ \fppy  *4x>oGoQe[[eQoGx>>4*   )3> >G*G4GGGQGeQoQQQQQQQGGGGGG GGG)G3Q3Q4* yp\H?+{gS @ , ''|1h1T:A:#DNNXXbbksu_uL8%t`M9&ubD1 wdP<)xeQ>*yfR?+&&&///{9g9S9@C,C"CCMMMMWWW|Wh`T`A`-jjjjttt~~}~iVB8$~t`WC/&kbN:'vcYE2wnZP<3) ~~~~ttttjjjjjjj```````WWWWWMMMMCCC9 99)/</F/Z/d&w&&&&&&&&&&(&;&O&c/v/////999'9D9b9u99999CC/CMCjCCCCCCCC8CLC_C}CCMMMMMM#MAMTMhM|MMMMMMCC6CJCgC{999///!/?&R&p&&  >Qo3FZm1DXu/CWj~%8L_suuuukk#k7bTbhb|bXXXXXXX"X6XJX]XqXXXbbbbkkk!k5uHuRufuyuu*>G[ox)<FZdw(2EYcv   ' 0 D N X a k u    & / 9 9 C M W ` ` j t t ~ ~ ~ t t j `u `k Wk Wb MX CX CN 9D /: &1 '    k X Dw :m 'd PF<3 lYE2 xe[G4m*Z<)eGp4f\R?5+!y\?+qS@"{qg]|S^JA@#6,"sV8tW9uX1||rmhP^3^TKKA7x-Q-4##f?!g@hK#}_B$jM/uXD0#v#Y#E-2-7 77AAKKKTTn^d^P^4*  "",,66@JJySpSp]fg\gRqR{H{?55++!!!+55?HR\!f!p!y++55??HHR\ffpy *4GQ[ex *4>G[e ox3Y4;*(   wZF)x[>* yyppfffH\+\\RRRHHqHSH6H?????55h5K5-++++!!!iL.~`C&kN1dF) eG* fH+gJ,|^K-!!++55s5_?L?8H$HRR\ffppy~t`WC/&kb X D: ' *4>>GQ[[eoxvlcYOE;2(  )33Qex 3FZm 1DXkuukbbXND:1'&'9M` j~%8L_swwmdZPP-FK<^3r))  "6J]{!5Hfy  >xQxoxoooeee[3[F[d[wQQQGGG G>;>O>l>444444 * 0* N* a* u* * * * * * * * &* 9* M* `* t ~   $ .* 8* L* U* _* i* s4 }4 4 4 > > > > G G G Q Q Q [ [ [ [ e e e o o o o x x x               } s i _ U L B 8 . $    ~ j ` W C 9 &       u a N) :) '3 3<<FFPPZvdcdEm2mw wmZ<)oQ>  p R ?!'11{1]:J:,DDNNNX|X^bAb#bbkkkusuVu8ujM9uX:wZ<x[> y\?!{g&J&6&/99CCMM|WhWK`7j#jtt~}iL8$t`M9&%%%..u8k8b8X8DB:B0B'LLL VVV__iiisss}}}vllccYYOOOEEE;;;2222((((((((((2222;;;;EEEOOOYYYcccllllvvv}}}sssii__VVVLLBB88..%%  ''0::DDNXXbkku~~tjj`&W/W9MMCWC`9t/~/&$.BLV_s}ukbXND:1' #-7KT^hr|wwmdZ"P,F6FJ>G4[*o*x   3FPdw 1DNbuyypppff&f9fM\`\t\\\\\\\\\%\8\V\i\}ffffffff#f7fKfhf|fffffff\"\6\J\]\g\{\\RR\\\\\\!\5\?\Rf\fpfyffpppppyyy yy *>GQ[eoox ))3 < FFPZ Z d*d*m*m4w4w>w>>GGQQ[[eeooxwwmddZPF<3)    xoeQG4*  )))))3333<<<pFfF\PHP?Z5Z+dmmww{qqg]SJJ@6,,"  '''11:::DDDDNN|N|N|XrXrXhXhXhX^b^bTbTbKbKkAkAk7u7u-u--###&&/99CCMWW``jjjtt~~~~%%%%....}8}8}8sBsBsBiLiLiL_V_VVVVVL_L_B_B_8i.i.i%iiiiiiiiiiiiiiiiiii~itsjs`sWsM}C}9}&}}}}u}b}XsDs:i'i_ _VVVLLBB88m.d.P.<%3% xe[G4 p\H5!~ttj``WW{MgMSC@C,C999////&&&r^TA7-}s_VLB8.$~tj`WMC99/&uukbbXNNDD::00' '0:DNXbku&9CWj~.8BV_i}#7ATh|,@J]q{ukkbbXXN!N+D?DR:\:p:y11'' *>G[eowmm3dFZZPdPwF<<3))  '1:DDNXXbkuxue[QG>4*  &/9CyCyMpWf`\jRtH~?55+!%.8LV_is}{{qg]]SJ@#6-,7"A"KT^r|",6@JSS]gq{||rrhh^^^TTTKKKKK!K+K5K?K?KHKRK\KfKpTyTTTTTTT^^^^^^^^^ ^h h*h*h4h>hGhGhQr[rererorx|x|||",6@@JS]gq{!+?HR\fy  *4>GQ[eox 3<FZdmxxoee[[QQ GGG'>1>D>N4X4b4k*u*    /9CMW`t~yppff\RRH??5++%!.!8BBLV_iss}{qqg]]SJJ@@6,,"##-77AAKKTTT^^|^rhhh^hTrTrKrKrA|7|7|-|#}s_VB8.~j`M9/kXD1|d|P|3rrhh^^TKeKGA477--#yfH5q]J6|hT7#}ssi__sV_VLL8BB88..%~`M/bN0vY~Et(j `WWMC9w9Z/F&)&xeQ4 yf\H5+uu{u{uququqkqkqkgkgkqbqbqbqbqX{X{N{NNDD::111''' + 5 ? H \ f p   4G[o3Fdw ;Ol''':'N'k'''''''/'C'`'~''''''$'B'_'s'1111::7:T:rDDDNNNX6XJXgXbbbbbb+bHbfbbbbXX X X>X[XxXXXbbbb3bFkdkkkuuu1Db/C`t%8Vi-ATr"6J]q{!+5HR\pyuuuuuuuuuuuu u u*u4u>uQu[ueuouxuuukkkkkkkkkk kkk)k3u<uFuZudumw2;OYlv  0 : N X k u     & / 9 C M W ` j t ~u u u u k k k k b b b b b b b X X X X X $X $N .N 8N BN BD LD UD U: _: i: s1 s1 }' '      w m m d Z P P }F s< i< _3 U3 L) B 8 .     ~ j ` M 9 &   k X Dx 'x ooooeeel[O[;[Q QQGGGGw>Z>F4)44***  x e G*pR5 !  *****g*S 6 "   hT7}_L.~`C&yykyNp1ppfff\\dRFR)R HHH??x5[5>5 5+++++p+R+5++++++{+]+6++++++|+^+A+#++++++s+V+85555555t?W?9?HRR\ffpbpDy'yvYE(nZ<)eQ>*yfR?+!{g]J@,"rh^KA- #   ***44s>i>_>VGLG8Q.Q%[eox~~ttjjj`````````` ` ` jjjjt)t)~33C[Mo`jt~<Zw;YvDb&Mj.Li%-%K%h...888"8JBgBBBLLLL5LRLpLLVVVV V4VQVoVVVVVVV3VFVdVVVVVV V'V:VXLuLLLLBBB/BMBjB~88888B%BBBVLsLVVVV__-_K_h_|______"_@_]_{______5_R_p_____ _*_G_e______i)iFidiiiiss s(sEscssssss s 's Ds as i i i i i i &i Ci `_ ~_ _ _ _ _ _ _ 8_ L_ i_ }_ _ V V V V V V -V AV TV hV |L L L L L L L L L ,L @L SL gL qL V V V V V _ _ _ V V V VLLBB88...!%!%!!!!+++++++++++++++!!  ~ ~ t t j j j ` ` W W M M C C {9 q9 g/ ]/ ]& S& I @ 6 , "     | r ^ T A 7 #     u k k b b X X sX iX _X LX BN .N $N D D : : 1 ' '   ~ j W C /    k X D : ' wwmddZvZcPOP;F(FF<<333)w)d)P<    xeG4  pR?+qS@,r^K7#s_L8%t`M/kX: dF3oQ4fH+gJ,rT7sV8~W9bD' cE( nP<oQ> p\H5!xooee[{QqQ]GSG@>6>"444** |r ^ T K7-#}si_VLB8.%%.BLVis}#7K^r|"6J]q5Hfy  4 Qo **34F4d>>GGQ[ [(eEocoxx0Nk&9Wt 8L)i))33<<<F-FKP^P|PZZZZdd,d@d]d{mmmmmmm5wRwpwww >[x 9[9999CC)CFCdCCCMM M(MOWlWW``` j 0j Nt kt t ~ ~ ~ ~ / M j      $ B U s       7 T r        , I ] q      +?Rf%%%%%...*.=.G.[8o8x8BBBBLLLV_ _is)}3}<FPZddmmwwwwmddZPF<3) xo[G=}*}}}}}}sssps\sHs5sss s s } } } q} ]} I} ,} } } } } } } |s hs Ks 7s s i i i i _ }_ i_ LV 8V V V V V L L tL `L CL &L L L L V V u_ X_ :_ iiiii_l_O_2VVLLB8w8Z.3%oG*yR+{S6~~t^jAj`WMCCs9V/.&&jM&X:d<oG*uyk\k?bXXNDDq:S:,1''rT7 i L .tWC/wmmdkZbPNF:F0<'33 )) vlcYOOE;2(( xxoooeeee[[[[[QQQQGGGG>>444**        ((2;;EOYYclvv '00::DNNXXbbbkkkuuyuyyyy&/9CMWjt~  $. B L*_4s>}>GQQ[[eoo#x7xK^r|,@Sgq !5)H)\3pQeo %)%3%F.P.d.m.w8888BBBBBBBB BBBB(B2B;B;BE8O8O8Y8c8c8l8l8l8v8v8888888888888888888888.....%%v%v%l%cYYOE;2( wmdZF<)xo[G>*p\H?+~~~ttqj]jJ`,`WWWMMMC|ChCK979999////s&_&L&8t`WC/kbND1' umudkZkFb<b3XXN NDD::11''x o e[QQG>44*  wwmmddZZPPFyFpFfdQdeZZPPFF< <3<3P)d))  1 N b/C`t%8Li}-ATr,@Sg{!5H\p  4>Qeo)<FPZmw    ))))333<<<F F FPPPZZZ(Z(d(d(d2d2m2m;m;m;m;wEwEwEwEwEEEEEEEEEEEE;;;;22(( wmZP<) o[G4 yfH5gS6"hT7s_B%t`C&kN1dF) x[> pR5qS@,|hK7#s_L8$~t`WC9&kbXN:0' wwwwwmmmmmmmmvmvmvmvmlmlmlmlmlmlmlmlmlmvmvmvmvmvmmmmmmmmmwwwwww '00:DNXbku&/9MW`j~.BL_i}#-AT^r|  ",@Sg{''11::DDN+N5NHX\Xpbbbkkkuuuu*>Qex )3<PZmw 1:DNXbku&//9CMW``&j&t&~&&&&&&&&&&&&&&&&&%&.&B&L&V&i&s&}/////999999CC#C-CACKCTC^ChCrC|CCCCMMMMMMMMWWWWW"`,`,`6`@`J`JjSj]j]jgjgjqj{j{jjjjj`````WWWWWMMMMMCCCCCCCCCC99999!9!/!/+/+/+&5&5&55?????????HHHHHHHRRRR\\\ffffppppyyyy  *44u>uGuGkQk[k[kebobxbxXXXXNNNNDDD:::11'''   ) )33<FFPPPZZddddmmmmmmmmmmmmmmmmmmmdddddddddddddddZZZZZZZZZZP P P P P F F F < < < 3 3 ) )           ''''x'o1e1[1G1>141 11:::::::::p:\:H:?:+::::DDDDD{DgDSD@D,NNNNNNNNN|NhN^NKD7D#DDDDDDDDDD}DiDVDLD8D.DDDDDDDNNNNNtN`DWDCD9D&DDDD:::::DDkDXDDD:D'NNNXXXbbbmbPb<k)kkkkkkkkkekQk>k*kkkkkkuuupu\u?u+uuuuuukkqkSk@b"bXXXNNDrDTD7:::1111i1L1.111111t1M'/''''kN0 vY2dP3eQ>*p\H5!{g]J@,"|rh^TKA7--###--7AKKT^hr|,6JSgq!5H\p   * G [ x3Pd;Yl 'DXu/C`~8Vsww7mTm|mddddZ@Z]Z{PPF<<3!)?Rp  4G[o )>94M4j*~*    .8L_s}#7KTyhyrpppff\\RRHH?,?@5J5]+g+q!{!!!+++55???HHRRR{\{\{\{\{f{f{f{fffffpppppppppppffff\\\\\\\\RRRRHHH????5555+++!!!!+55??HR\\fppy{qg]SJ@6,,"  **4>GQ[eeox|rrh^TKAA7--# )3<<FPPZddmw ':DXbu##-77A&A/A9KMKWT`Tj^~hhrr||.8LVis}#-7KT^r|||rh^"T,K@AJ7S-g#q{!!+5?H}HsRi\if_fVpLyB8.%            ~~~ t t tttjjj``WWWWWWW``jjt~~yp\RH.?85B+V!_is}{qg#]-S-J7@A6K"T^hr|||rhTK7-}i_LB.%~j`MC/&ukXND:1'|rh ^TKA-#}s_VB.wwmddZZPPtPWFCF&FF<<<33u)b)D1 wdF) xQ4xoe[yQRG5>*  qJ,|^7pf_\8R?5+!~`M/u{XgD]0SJ @6,"vY; nP<|r hTKA-#xoee[QQQGGGGGG}Q}QsQs[i[ieie_o_xVVLLBB888888888 ..).3.<$F$P$Z$d$w$$....8888(8;8O8cBBBLVV__0iNikiiisssss/sM}j}~}$BVs-A^|,Jg-7AKT^5h\rr|4[xFd",1@XJuS]q{9Wt%8Vi!+5?H7RT\hfpy6S{  *+4H>fQy[ex *>Qo3<PZ m)33<FFPPZZd dm'w:wDNXku (2;E&O/Y9cClWv`jtv%l.c8YBOLE_;i(s} mdPF<) ##--77AxAoK[KQK>K4K K KTTTTTTTTyTfKRK?A+AA7777777q7]7@7,777777AAAKKK|KhK^KKKAK-K#AAAAAAAAAKK}KiK_KLKBK8K.K%KKKKTTTTTKKKAA77~7t-j-`-W#W#M#MMCCCC99999999CCCMMMMCCCCCCCCCCCC999999CCMMMWW````jjjjtttttjj``WWMCC9/&}}si_VVuLbLNB:B'88 .%wwmddZZZPPFF<<<3333))~)~~t ttt~~~~~~~~~~o~[~G~4~ ~ ~ttttjj`p`\WHW5M!MMCC99/&g&J6rTA#ukXNsDV:B'$ tW9ubN:0m dZPF<3) xooe[QQG>>44*   ':DNbk/CWj~$.8BLV__issss}}}yyyppppppppppffff#\-\A\T\^\r\\\\\RRRR"R6RJR]RgR{RRRRRRRRRRRR!R+R5\?\H\R\\\ffyffffffppy 4G[ox)<P dw **4>GQ[e'o:xDXbku )33<FFPZddmw'&:/D9NCXMkMuW``jt~~&/9CW`jt~%.8BLV%V%_.i8iBsLsV}_i}-Kh|"6Sg{+5HR\py   *4GQ[ox}}ssiii ii3_F_Z_w_VVVLL LB;BYBl88.%   0 N a u          & /~ C~ Mt Wt `j jj t` ~` ~W ~M M C 9 / &    ~ ~ ~ ~ ~ t t ~ ~ ~ ~ ~u u k k k b b X N N D D : 1 1 ' '   w m d ~Z tZ `P MF 9< &3 3 )    u N 0 Y;xoe[QZG3G >44*o*G   \ 5g@"hK#  i L%   *~*`*944>GQQb[:eooxxwP)[4 yR+ g3J<6FPZdmw|h^K7-# '''11:DDNN}X}X}Xsbsbibibibib_b_b_b_b_b_bVbVbVXVXVXVXVXVX_X_X_bibiksksk}u}uuuuuu}si_VL8.uukkbbbbXXXtNjNWNMDCD/D&:::::::::11'' wmdZPF<3))u b XD0 vY;(x e[G>4w Z< x[> p\H5+yyyppppppppyyyyy!+?Rfy >[ x*>GQejot~3dNCt._-^,]!R%%G%x%%%%3Z;c  ' : N a           ~ t &j /` 9` 9W 9M CC C9 C/ 9& 9 / / & &     u b X N u: a1 N' D 0  lYE(wmddZPF<3w)d)ZF3)    xe[Q> 4 ))33<FPZdydfm\wH5!qgSJ@,"'1:DNXbku"6@S]q&/!9?C\MpW`jtt~ ~>[x )Fdw 2EYl         ' ' ' ' ' '       lcYE;(wZ3e>pH],~tj`hW-MMC9_/.&j9N'Zu3kbXND:e1> pR+w]m@d"ZPF<3|)^A# s_B.~j`xMo9e/[&[QGG>>44** & / 9MW`t~$8L_i}yyp-f7fA\KRTRhHr?|?5++!{{{qqq"qqggggg]]]]gggggggggqqq{{!+5?|HrRhR^\KfAp-y}iVB. *4>GQjQW[Ce/oxubN: lO;  )3/*9 CMWW`jty~f~H5!{g]S@6,"%8BLVV_iss}|rh^TKA7-###-777AAsAiA_AVALABA.A%A7--#}si_VLB.%t`%W%C./.&88BBBLLLLBBB8u.b.N%D1' jW9wmZPFk<D)'  d<[4x oe[QpGR>+4*  g@hA_B`y9yppf\\XR0RRRRHHcHEH(H HHH???w?d?P?Q [e:oNxk&/9CM W `jjtt)~3~>4**  #-7KThr,@Sg 5H f*y4>GGQ[ [ e>oQxex 3Pdw3  fH+qJ,wwmhd7dZPF<V3%) `/k: m<o4xooef[5QQG>q4@** | T#sL$`9ypufN\0R H?5!lO( nP3{g]SJe@G6*, "p\?+{]J6"|rh^^TTKAA77--########"#,#,-6-@7@7JASKST]^ghg|q{"@Sg!5!??HRRp\fp >[o )< P n *44>>G GQ(Q2[;eOeYococxlxvxvvvvvllccYYOOE;;2(( xxxooooeeeeeeeeeeeeeooo o xxx(2EOYcv 0:NXku )3<[o&/ 9M3WF`Zjmt~ ':DNXk%u.8BLVV_is}&&/9CCMW`jt~%8BVi}7Kh|6Sq!?\y >e 3Pw(Ol  : a       9 W t       # .# B# U- _- i- }7 7 7 A A A K K K K K K T T T T T T T T T T K K K }K }K sK iA _A UA LA B7 87 .7 $- - - # # #        t j W C 9 &          u k X N : 0 '  }ssii__VVLLB88 . % %  ' 0 0 : D N X k u            / C W~ `t tt j j ` W W M M C C 9 / / & $& . 8 B L U U _ i i s s } } } } } } s s i i _ U U L B 8 . $      u u u u k tk `k Mk 9k &k b b b b b b ub Xb :b 'b kkkkkkck;uuuuuuZ<[4 uuuyuRu5ukkkkbqbSb6bbXXXXXrXTNAN-NNNNNDDDDsD_DVDBD8D%DDDDDD::::1111'''~tt j W MC9/&ukkbXND:1' mZF<)xo[Q>4 p\H5gJ,wmmhdKd-ZZPPFFs>4* pR 5!{qgSJ@y6p,f,\"\RH??5++!!",,6@JS]gq{{qqg]]SJ@@6!,!"+"55?HHRR\\ffppppyyy  *44>GQQ[eox| |||)|3|<|F|P|Z|d|nw (2EYl :N"k,6@JS]q{9WjB_}+?H#\Aphy6Sq *>G[e5xRf 4G [o)3FPZdmw )3FZdw  ''1':1:1D:NDXNXNbXkXkbubukuu&/9CMW`jt~&/9CMMW`jt~%8BLVis}.8BLV_#s-}7AKT^hr|#-AK^hr",,"6,66@@@SJ]JgSqS{S]]]gggggqqqq!q5q?qRq\qpqyggggggg]]]] ]] S4S>SGSQS[SeSoJJJJJJJJ@@@@@6 666)63,3,<,F,F"P"Z"Z"ddmmmmwww  (22;;EEOOOYYYYcccccccYYYcccccllvv||rrhh^^TTKKKA A A 7 '7 07 D- N- X# k# #          / C W j ~         $ 8 B U i s           # - A} K} ^s hs |s i i _ _ _ V V L L L B B "8 ,8 6. @. I. S% ]% g g q { {                  { { { q g g ] S S I~ @~ 6~ ,t "t t j j j j ` ` ` ` ` W |W hW TW AW -W W W W W M M M sM _M BM $M C C C C C ~9 `9 99 9 9 9 / / u/ X/ 0/ //&&v&Y&2& &wP)e4 \5S"h7sBukbWX&ND:'b1 wFe4m ZF<)f5 qJ"oeQh>A4# iL$~p`fCRH?+!uX:lqOg;]S @6,"wdP3 |xrehG^4T K A7-#yfR?+}si{_qVgLSBJB@8,."$|rh^TKAA7--########--77AAKKT^^hr|$,.@8]BqLV_s}5Hf *G[#x-7AKT^r3|Pd2Ecv",, 6'@:JNSb]k]gqq{&/9CMW`jt~$$.8BLLVV__iiiisssssii!i+i5i5i?iHiRi\_f_p_y_y_____iiiiii_____ _VV V L*L4L4B>B>8G8Q.Q.[$[$e$ooxx )34*  ypfRH?!5+55+H!Rfpy  *4>GQ[eox!++5??HR\\fppyxoeQG4*y\?!{S,y|pKpf\R}RBH??5W+!N E<G f+g6{qrqAgg]S}SLJJ@@@M@@666N6,,,,O,,"""wP)eG4  *>Qex=n(c N",M6@JSVS]g-q|{gfx3YCsA{HP!u+59?HRB\fpAy]R*Ge x *4GQ[eoxe[>*fH! g)6)33<K<FF}P8PZZ`Zddm'mww3ww>HS^_W D2'1:3:DN>Xbb\kug6r^K77-u-k-b-b7XADT:h1' 6q!fwdQPF 3n); jVA6+*~xixxTxx@x+ xP D  M ) F LZ m - r , g : N k!Hp/M`t.fL?_}   { @   |# 77 T r _   t & 6 ] :{O?df4*GRog|<#Zw.Ck(12;EOZY)cllllllxlococoYoYxOE;2( <Z1bmZP</)`LKxeQ4J  RyQfH5P;lgJ 6 D u    C t h T 7 B# }   # ^   s IV B . 5y4xP(l0kCj%8L_s~`-CA%ThruN'l1<o*\   @   r| #r h ^ _T T K A W7 - #  N ;m[}s\i!_VLBS8".%%r^K7-###-7ATh|,Jq?~\~y~~~~t t*tGtejxj`WWMC9/&  )3<<FuPkZXdNm:1   wmdZwPPF)<3)e* y?STxoB[QG~>C*  k:mF)pfRo?G5 !pH!gJ,g@hA|A_.Btj/9DuNl2FY;oQ>*wdP<3 )*4G[x)3FPv vllcYOy;\(?!wF{]@"Q p|ghK-^B9iL.1;tdW/o4bzDR'+ qv]cSOJ;@(@JS ]q+f ([2EY=lEb'N9u9rjgRL47rO6qu&5~yiG- ^P'k"@S9]~]gg8gs]SJ@K,|"6]5Rp||| *>GQ[eox",@J]qxxoo+e?eR[pQG>4*   4G[exyf\H?+)<Pm:b9jVK@{{{5qpgSJ*@e," FwEvr^T 'A N- u      9 W t       $ . B L U} _} _} _} _} U} L} 8} $} } } } } } } t W 9 &       a N : ' #7K^r6Sgvlc+YHOf;2( 4Gew)w<wPwdwwww  (Ec 0 a    / j    L    - h m P < 6 ]   +oRGy  p*H=!Qexg@rKx#o[Q=4i L .tyW\9H+ u {b ]N 6: '  r ^ K 7 -m Z F 3  o Q >    y f R ? +    { g }] iJ L@ ., "    j C  k : vE m3Q y?q@rA}L%",6@~J`S9gq{kN:' +5H\fy w m4dGZ[Po<3 x)[3>FZmf?! 1DgNSb6u|hTKA777777AKKThr|"6kJX]D{1m!Z5\!{@K_$t9N#--c7AKTw^ R!"6J]qq@hT5AH-f#####-A4KQ^o|)6F]d5f1Nk 4[/)CFWZjnt(2;EOYcl ':N~btutj`WMC9///9999//ukbXuNXD::1 cE(mZnFP33 eQ4x e [QG>4**     * **4>4Q>eGxQQ[eox)Pn;l )D5>?4R*\*f*y*****4>>GQ[ex)<Zm:Xk *>G/[Moj .B<_P}m #;7OKl^h|  0 N a        9 M j       $ 8 U i }              | r h ^ T K A - #           }} is L_ 8V L 8 .    t M /      a : ~~l~Ot2t ttjjjmjPj3jjjjjttetGt*t ttjjjpjR`5``WWMMCq9]9J/6&"kXD|1|| |||mZF3x[G*|hyT\AH7+#{g}]iJ_6L"8.~t`WMC9/&",@Sg{uk!b5XHNfDy:' 4G[xmZF<) ' : NbupR5/9MWqj]tJ~6,"""t"j"WM9&rT7kXD:'_8jCwdXZ0P <3)cEnZ<)xoee[QGG>4x4x*o o oox x.G_Q[eoTx@{5y4o3%[8xVi -A^r e">6J]q{p?q6|Ai%CDF>+{"|-{gL]J6~"9D|vhOK7nP<)iV8%t`M /)<PdkN:'2 YNwuZF3&M~8i-x^oee["[SQQQQ[5[\[eoox>[xo):Pbw9:`bBi/Mj#Kh%8B6VS_qis}!5H\p} s4iQ_eVL8.3PwjM(/Elu X D: k  Cd `F )  $ Be _G }  p R +     # -g 7J A, K T ^ h h r| |h |K -  |s |_ rV ^B T8 A. -$      $ s. U8 .L V i } t M   7 kT :| vE, S{d)!o?4\yf!S A4>G}Q8eoxt9D Z)Q f5o[G4 S,|Kp#\?!iB{]6`/rbT:7Y;sVB$nZP<3)8V)s)GjGCG&QQQQGkG:>>4 d 3o> p\p?5+g,{]@|T-hK-s_LB88.}.i8V8BB.V_s7T|~t,j]`WMC!C\99//>/x///3/m99919uCCC/MtMW`%j_tT@{.Li!Ry7 T*|>Qeox6SgxoeQ> +Hf\+*{Q@or- 3PVwt&'D1bPx49WjyHgJ.,BL_s}"6S{?p## -G-77A<KT^ hNr|/~_A,@]Sgq5yGZc ! D+ + 5 5 ? C? jH H H H R R 8R LR _R sR R H H H ? ? 5 + ! !   s _ B $    ~ Wq ] J 6 u" :l(PhT7o#*?}JV8T_jCt&b:1 dmF[) yHxoe{QSG6GGGGGQ[[eox3P"w@]{'N+\MG8xs-Fh61{kHW*o8 sP;Ar  u @ q `   U5 \  A   " ]> [ xR=[xx[>oQ\4+{6p5 h   6} %  T~ & Bu  &w  Xo 2yd54SpK6h}LB$/Dtjmj3```jet4~ y\?!8V}7h@{!R+H*\[y 3Z  ***1*N*b*u  k*N>:QowP 3) Fde4y'R:!Nbug@r/KC#M`jtt}~itLt8j$`MC/uN1$BwVZs<-xKQr*\!,Jgg{"T!5LHfy`&u: v*24GQP[ oxx>H]6|rh^TT^^h|xo@egQG>4*5 \  Go3Pywf\H?+2Oc'Nu{{&{W{{{{{B{s{{{{{7{^6Sq!5?R\py!!++5 ?*H>RQ\efxy) F*dGw[o1NbxG/CM\`jtq~~rs~/b'O~~tj`nWZWFM39)/)&))33<FPdwubD1 (Olwd:Fu3MBxAeQ>]4  pe3mp f:\k\RRHHH&R9RM\W\`fjptptytj`WC/4bG:emF3ZxQ4:bf/5Wg,8_TK|}iV6B]BBBV_?sf->T[|x,])<P?dfmw 4e wFmdPFX3C8}oG TySHR], GTFwsB;`Y&vXm<eG*vcO;( d3[*\+4Ge]" ^37Z s:Vk8%C~.i#^J5p%8V i>o-^FmJ (R;OcvQP ;vv 'c DE X2 u     d <  u k X No :G ' p?g6lcY|OKE;;22V2%222;t;M2&22((b:     dP2<;Y l  N  W $ _  A r  @ ] q) < Z m q ] @1 "D b u ^ -   U/ C W j jt /   a O <G tyjRW!C/gJ"kD'hA#d3 sLQ% W\+b],d|Kx#> iyBf$\RHHHHR~RjRW\C\/\&fffffppy *G[x&F9wCW`tb~`.s.-B^Vis6Sq#7Kh|,q@@Sqh-B!C5H\DyPe *pG+exSK)Fdiw8`9'DXuuX: &9MWcjEt~dFeQ4  4Ge)P~ttOjj`W0WkMMMCWCCCCL9999T999"9g999H9CC>CCM3MMWWX``jjWjttt%tL~s~~~~tttjj``WMCi9./&~9NZ[ p!uSuuukTkkkkik.kkk~uCuuuuuuDuuuuvcYOOcv:u`}^JHQ/Z9CkMW~jt~{R*PY 0 k  % % &% M% `% t% ~% ~% ~ t ` C &    a 'cwot jWHC9g&|}jX3ubXDg:'K 8/'24*   1Db9` .i *>G^[ox,q?[)FZ3wwE1 0N ab   C ` ~/ M j       8 V s      # A ^ |    t j W" C@ /S q        k N! 05 HR\fplyEyPyypxfG\H?+y!H{@qSr67_.hK-`/k}:_B.wP3t`M9&xxxxubX3DZ:w':X9`wmdZ8PVPsF<3))# - -777-#sV8%  ))))333333%3.)8)B)L)V)_)is})))33s3_<B<<FFPPjPCPZZZZNddddwdNQ[oxW8#r] ? )e33<<<*f?],T_%j&b'm)o4y?@KV$wmtmCdZPFk<03)c (FxG\5xoe[QgG@G>44* r TA#    *#*74T>|GGQ[e,oSx{!Hy G3 w2)v33<:FFPPMZZZZ_ZdZ-ZrZZP@PF<3H) >xFwo'[NGu>*/CWj~p\RH5+~jW9&u{N{{qqgPg]SJeJ*@66y,?""JT_$~MNvO( nZF3)  )3FZnw(;Oc"v,6JSg{'DXu!?Rf9yWt $ L>sQo-^ ),F]dH &HCa~ QC~8L_%s_$U|"-J7gAKU^hr5|R|p )3=FPPZZ|ZrZrPhP^PUPKFAFA=73-3$) }i_VLB8.% (<EYcmv%%.8BLV_r|,6@J~Tk]agWpCz:z&zzvpbfN\<S(I?55+xdP3 rhpU\A?7+$^~Kt7a$M9&~jaMC0xxneee[[[QQQQQQQ[[[eenn0x9xMxWjt~$$$--77AAJJTT]ggq{xne\RH>+! *4HZdn '1;EMW!a+k>uR~\o&9Ma$t7JThr#,6 @J*T4TG]Q]dgmgwgqqqzzz     )<FPYmvwcO<)pR%6/"9LV_ii|s_|C|wY2 zS,||siiiC_UKB8y.R,jCmvGbXE2T#NyHfSI5+`/ dF)}}}}}}}}!+>Qeo"+;5b??IRR@[p[eeo2omoooo.o_ooee4[e[RHH:?k5+"?yC}>o}s`DVtM906p2l-]yOyvoogg#]J]qSSSIIIxnEe [QHB>5+!6lC]4auLlbbXIOOFFd<*22((a 1 | L % oS6ne[RHH>>??HR\fo/Li ) P v ,\ !)))U33=GGNPPYccGmwwApLrOu"#R,x6@J\fJpq&L| E%u9K_!{Z@z8/UhhL{ 'DWWt)Y+3[Obv@o8h+=Qd&wL| ;j# 5FIv\ex  ! > Z w       # # - 7 7 @ @ @ @ @ @ J J J J J J J J J lJ YJ FJ 3J J JJJ@@}@`@D@(6 6,,"{"U/gAoIc=wmmcYZ3QQG=t3E+ ! sC{K_0~tkb^O.E;)f@f?tjw`[WHM,D:1' ndQH4+!|||rrrhhhh__UU"U"L,B6B69?/I%R%[oy 7Ig{q7gT^pUKAA8/&%B^ &Lr0Lr|ri`8VULgC0'  %/8L|Ts^_hVqM{90& %9K^r|rr/iK___{VMMCCC989^9{0000080h::::CACpMMWW_Aigis}.Sz  . J g y    ' ' 1 : D N V ` ` j j s } } x} \ H , nQ5xdH+eH,o[?,xeRI5,#ne\RI?5~5t-t-j#a#WOE;2( uxkobeY\OIF@<6*#  yf\J7-vmdZZQG==5++"zpg^TKA7/"",6>HR[eow%%//7AA+K4TGT[^cfvpz 3FYbu##,66@2@DINIaRs[}[eooxx/7J^fy"x,e?QII[6n,xpT7*4FPsYalDu) vY>! (:DxN\`?i-s}qUA/  %8BtK`TNg;q1 #6>Q[m * <2O<aOkk~~ 0C Vi&//99BB%B7KTKpTTTT^^^?^Z]]]]]]<]b]]]SS7JfJA7.P2Wr _8M]06[tbE 33 Otwn&d9QLHU?^5g+q"zzzzpg]TKKA8.%  yyof|TiJV@C71%|~`lCO'= *~cG*xeSIf@J-%$tYE3xoe\SJ@7-$#,5?IR$[$n$w--77@JTT\\ffo ooo(f2f;fEfMfM\W\`\j\s\|T|TJAA.$ saND2xeR@{-r#iVLC0' lP=*y^K/$$$k.N.3...777AAeIJI.SSSSSSSuJYJ4A8.%gB%kFt!aOF3z*T!%k<yJb3^/!+4b=4GPZblpuK/ uZ>" 09{ChUU^Ch0{   )2c /7$J6]Io\ynx )<FXktneS @6$.7$@Sfn($1.;@NINSWe`xr| 1DV_r"{5?QZm"5=$P.k@~Sew '1CLUhtrczF4z+r=hF_Y_kUtUUUUUUUU__hhq-z6IR[nw*<Oj} '0909BKU^gppyysaO<3  qgUC90      &9CTq );Ws   +4>GPYbblllbYOGn>e+R?7$ rM)y]9}}ukkbXnORO6F$=4*!!vndddddnn{vr`M:(.?RxmfT8& /J]wpdI.eH1-C LVhqzlG+a= z{q_gD_(U C9' p^K:0'o ] JA/%  wm'd([1R:I:?C6L-V-_-h$q$z---66?IIR[dw!2<O`s%8IS+fFwb~$?[&v0BT^o y.Ie-RvofATeA/ &TxoR7C^v[?:C_zw\I .(;Vh  w2mDmWd`dr\{\\\\\\ddddmmmww%ASe  '11:CMM$U$^$h$q$zeSA%    w \ @ .ne\RxIoI\AKA8I%IIR\enwnS@% nR- mR&-7AJS]veQo-oxc6mH#mH-fJ8  %%//88o8]/K//& pTB& ofTyK]AB/'& q^L1 qhVyDy:y)yy{iWE 3 9K^o}jX OF/3B+J"]"ox""+,4=GYkt+GYt$-3?FHY[tclv!*=FNaujltc|[QH?-$*3EXi|2E`r$-555????1?C?_?q?????????0?B?]?p?HHHHQQQZ-ZHZZZlccccccccc"c4cFcXckc}cccllllluuu u*u;uE~N~W~_~i{!+4==FOOXXXXOOOE=4+!ulZQH5-$ &09AJT]]fnwwwwmee\RyIy@p8p%pgg ggggppyy-pHpbf~]ULB90*0D(` 0BUfo{qqi`WMDD<x3f)] K B/'  )22<DMV`iqzz     qiVD2)zh_M~Dk2Q >-y~h~^tLkDk;k1k(kktt~~)2C(L2_;hLpU_qy# 5Pb%t%.%.-%%%2C U_pyp_L;tbPy>p5h#^ULC;( zzqqhh}_}VtVtMkDkDk;k2b)k kkktt}}}~uld[ QH?1.:%BU^ ox $$.$6$I$R$[$l$v$### )22<<EEMMMxMoM]MTMBM:M0EEE <22)) }}}}}}}}}}ttjjaYYPGG>>4,,##!!**3<ENW`irz#4GYjz|riWNE3* /ASevnf]KB0' !))22;;DD~DlDcMQM?M6M%MMMMMMDDD;22)  vm[R@8& {{{{rrr|r|rsrsrjrjra|a|YYYPPPPPPPPPPPYY aa&j.j@sJ|[dv  %).:@CIUR^dplu "+'49FBNTW]aoj{!2DVgq#,4=FOXajs||""++++++""p^LC)  weS%A%&$..7777??}?k?ZHHH7H$HQQQQZZZZsZXZFZ,ZZZZZZQQQsHXHG?5?6--$ q`N<*yg|^|MsDi:`1X)OF=4,{saXO>5#{i`N<+xxxpqphpWgEg2g*^^ULLD;;2)) xp^UD;2 xog^LC;2)ypgUL:1 !!**33<GPYYa#j4sO|s5Y| Gs$6>PbHst|$P}$$G-s?Pbt -Pt#=Xr,4FO`ir{"+4<<<E<<44+""+{4r<rEiN`WX`OqFz=4,#!3EVhy#4=FXi{!;Mg+Nq):*UVoDp:KLf0n&/d8Rd~[.c&7 I #[ Gl a} {            $ 6 > G X za ii N{ 4 {X5sG    ! !t *H 3$ < E M M V} ^c gQ p@ p. x% %   % . 7 H Z t     # X    " W    C      C &  & / / / 8 m A A I R ? R k Z c l l c , l F l ` u z u u u } } } t t t q t _ k E k " b b Y Q H X ? # 6 - $  X  $  } @    J   t bT Q ? . g 2zW+u[I/|saaYYmY[YJYAY/Ya airr{ofTC1(!x*g;^LLU;g2o!xxxxxo^Lq;W =#qNs+P6Y-mR/m 8nn:L)h3z_cE/+wK)u[J/zh`WNNwEfNKN;N NW``hhqzqz`E,z}zbzIz.zzzzzeL(zrizXWF=5# cHc/@&noUTC;1) {jX{Fr5j$X OG>,$lS A' 1BTevwooff]ULLD;2)*! !.7HQct}"*3<<E M_#h4q=yFW`ir{{ i X(G1,: CCLT~]\f0o xxhE"u[I8'08AR['l0~ASl>r,FXr1f6b)C]3Vp &@Yt+EVpypgg_W WN0NAEREdEu<<<3333,,,,##,#>#E#W`rzz( 9BS#\4n=vO`q1J"e+<MVgy,FXi/7@QZbt}sa*O"Xi/AZl"+3D)M:VT^efwfoxxxxxxoofvfd^K^9VMD;2+"sYH-wpo_]EL4D"2!}ud[IB9'!3D^o  $$+4=FNNV_hpyyg|^kNc<6<$33 *""gN3fL2wneTCg;M)<"une]SKB;1!(~unnnnnn n1vCv\~n~2Tw#Eg!3;DU"];fUxn"+;DV^foxxofUL<3!w]L3!n]L ; 2!""+++++""" "3<LUgnwnnf]]UUULLLLLLUU]]enw*; U n #3#L#],v,,4444444!4)4;4C4K4T5]5e5m5v5v,v,v,v,v,v,m#m#e#\#S#KB:1 ##$,,5>FNW`qy~uulll le#e,e5d5\5\5\5S5S,J$JB91( yiXO>-(8A%R?[Xkj|6Oq/?Qj{=_2%L?nOiz1Km#=N_x8Rt /"7*?*?3?3?3?373/*&! |b@'fL<uS)oV4\2p_O>5% zriaPX>P.H? ?777???HP|YjaZjHr@{/ 5GWq}}}ttt!l2lClLl\kekvkkccccRJJJAA880((veTC*hO>% |~bvQm@m'e\\TTKKCC}Cd:S:C:):::::22222**w*g*^!V!MF==4,## $$,,5>,5>>FzFqNiNXWPWGW6_-````WWWNNG>6-}$tlc ZZRRRRRRZ[cl|ttlZRJB90((  &.6?GPX`!i(z1:BKSdm}*:Tm~&7@Pa.sHa{,EVo$,4=FNFNV_ g0p9xAxJR[ccccccc[RJA80!)2f:UCWq):KS!d2u:CKT[ddmmml%l6lGlWd`dq[TKB:1*!1::BKyShSh[_[W[O[O[F[F[>[>S>S5K5B5951-)-!-%%% y h V F5%}udSB:){sjYQI@8/'}ulc[KB:)!(/8{IsRsYjbbsb{YYYYYYYYbbbbj)j:jKs[sls}{{{{,=EU^ox{{{{ssjbbYRIA80p_F5% wo^UM~%+ETmxqh` `!W:O[Hs?7.(8Qaqzrjjaaaaaajjjjjrrrzzzy`P/iI(&|?[O;hu]L 4##,4<<EEEE<4,#gN.# 4<DLTj]Ie0muuuuu~ueuMm4me \TD<+xhXPo?N/-iA]-sc[RpJ?BB::B[B*JJRckfs=qX@''7P`q %=Vn||uulld\TLD<3$nN-qHhWH7lC#_t?c&K3 {ssokWs>s//O|xk[K;,*]" Qz-^(@XqqX@(^5 zI m5&.6Y?(FOW_]o,xzI eM, $,4=DMU]fm m%v=~Vv9j-^)cNw *Bb{ "+3CS&\6l>|NW^foowww0H`wywwwooo#fDgdg^^WOO/FX>y6.&; d'Ox3[|&F^ 8HX`qyy/y>yWoqyy @` * Ks3Kc{6Nn>^  Q1y@IYi,y[O9j#Lt6_  ( @ X q             x x p h h ` X X X P P P G G G G O O X X ` g x           1 A Y j          # 3 ; L S .c 6l ?l Nt V{ ^{ o{ ~{ t t k c [ [ K C : 2 2 /* @" O ` h w                              } m ] L 5 $        z b J : !   o V G 6 ' p W H /  ueUDu5e-UE 4% {jbRJ{:{2s*sss sssr{{xph`XP G?8#8,/4';;;;;;4+# rbR}Au:n*e]UME5-$ xiXHA0tcS;xhPr?[/B*qYA)yphh``x`h`P`@`0``hhpypgWG7(/?P_pq`I8) '008p@`@H@8G(GG@@880'p`H8(oW?(p`H8(iI) xhaX9H8(X0yQ0xpiYQH9i1Q)8!! "2ARzirrjbZZRK*KBCb;;33**#2#Qr :Zy2Ii''//' i%Q%2%&----r-R-2- -&&&z&[&;&&&&&&|&[.<.$. 66>>GO}OmV]^M^=g-o%ww~'//7?HH&O7W>WN_^_ng~hppppwwww5pNpep~ppphhh`%IEITIlAA9911(!!# 46')19@QYahppx'..6>FNV~^vfvnnvn}nf__WNNF>7/'#3BRjz(?Ofvh``XXPP II$A+A38;8C8K0S0[0c(k(k(s s z zzzzzrrrjjbZZRRKCC;33+r+j+Z#S#C#2+ ###**2::BJRZubmjer^yVNFF=66...&&&&&&&...&...6.=.=6E6M6M6U6U5U5U5U5U5U5U-U-M-D%D<5%wwph`XPIA91)) ||ll\\MU=E-=5 % xphaYQIA::222)111199AIIQYahppxxph`XPH@)!    $$ $####!#)#)#1#1#9#9#@#@#H#H#P#P#PXX``` ` ggggggoogggg__WwWgOWOGG8?(?80(  |eN>|dM6&||ummee]r]cUKU<N,NFF>>66...'q'aRB3# o`PA1!|tld]UME=6.&~~~~vvwwwwwww*:IYap ,CSjz'/7>>F5NEV\^semu}7F^m&5=MT\lt{&&..55==EMMTT\ddltt{&&&&&&&&&....666...&&tl\M5&ueN>/{ tld\TME=5u-f-V&G?/  (7N^u}8}O}f}}uuummmmf-WEOTOlO{OOGGGGGG??-?D?T?c?s??????GGGOO%W4WD_Sfcnsnv}$4CRbqy-5=MT\dt{ #*2:BJJQYY``hhhppppp%w-w-w5w5w<w<wDwDwKwKwSwSp[p[o[obobgbgbgjgjgj_j_j_j_jWSPSPSHSHK@K@K9C1C1;);"4, ,%oXI:" qYB*y[zCz$z sssskzkckEk-ccccccccvc_cPc9c)ck kkssszzwwpiiaaYYQQJJJzBzBsBkBcBcB[BTBTBLB5B-B&BJJJQQQYYaaaiiqqqxx~vng`XPHH@91)""  "*9@PXgw~yrj&b-Z-K5C=<=,D%LS S[cckksz||||||||zskc[SLD=5&--4<DLS[cckrrywgXA2 kSD-}nWG9)zrbZSL<4-%zsskdd\TTMMEE>>>6&6.656=.E.M.U.\.c.k.s.{...66666>>FFMMU\\+d:lBtQ{Yhw /6FN]dt{ {ttmmeeee]]]eeeemmu|| +3BJYap$+;JYhx-<Sbr&-<DSZbry(07?GNV]eemmmmttttttlllleee]]VVNNFF??700(     (0>FNVdlt "1AHW_nv    $$,33 ; ; B B J J J R R'R'R'R'R'R'R'R'Q'Q'Q/Q/Q/Q/J/J6J6B6B6:>:>2>2E+E#E EEEMMMMUU\\\ckkssz||||||ttt ttll l(l(e0e7e7]?]?VFVNNNNUFU?]?]7]0e(e(e lll lllsssssssllkkedd]]zUrUjUcM[MTELED>=>57.7./&/'   yrrjbZSLD<<5.&xqiaZRRKC<4,%yqjc[SLD=55.&qqwwwwww&..6==DLT[[cjryy$$$,,,3333;;;;;;;$$$$$$$$$$$$$$$   zzzzzzzzzzzzwpphaaYYQQJCC;;44,,%%%%%,,%,,,,,33z3z3z3r3r3r3k3k3k3k3k,d,d,d,d,d,\,\,\,\,\,\,\,\%\%\%\%\%\%\%\%d%d%d%d%k%k%k%k%s%s%s%z%z%z%%%%zskd]MzFz?s7s0k(kdd ]UUMF??70(!}}uunnnnff ff_!_(_0_8_?_?_F_N_U_]_e_k_s_{__ffgggnnnvv}}%%,,33;;;BBBJJ J JJJJ!J)J)J0J8J@J@JFJNJVJ]JeJeJlJsBeBlBsB{BBBBBBBBJJJJQQQQXXX`````ggggggoooooooooooooooggggggg`````XXXXXQQQQQQQQQQQQQQQQQQQQQQQQQQQQJJJJJJJJJBBBBBBB;;;;;;;;;;;;%;+;3;;;;;B;J;P;X;`;g;o;v;};;;;;:::::::::333333 +++% %(%(/66>EEMTT[[cjjrrryyyyyyyyyyyyyyyyyy|y|ytytymyfjfj^jWjWjOjOjHjAqAq9q2q2q*q#yyyy  xxqiibZZSLLD==55.''zzrrrkkk c c \\UUMFF>>800)!! |unPIB:3+$|m_H:+ "s)]1N1?81?"GG NV]]dls{{$3:BIPX_gm|$+2z2]:]AUIUINPNWNWG_G_GfGf?n?n?t?tG|G|G|GNNVVV]ddllss{|||ttnnfff__WWWPP$P+P3I:IAIHIPIWI_IfImImIuI|I|IIIIPPPPWWW___ffmmttt|||||||||%4;IX`nv$$++22::AI$O+W2^9f9fAmHtO{OV^emmt{  $*29AHHOVV^^eeelllllllllllee]]VVNNHH@ @ 991"1*11*8*?#G#NU\dk s y     ##*19@GNV]dls")7?FFMT[[ccjjjT[[[TTTMMF>>7/))!     !!((///666>===EEELLSZZbbippww~~~~~~~wwpi~awZpRiLaDR=L5D'= 5'   rjc[TMF?770((" "'-5 < D KRRYYYYYYYYQQQKCC<<4--&zs l ]VOH92$~pbZLE6'! &&&,,z,k,e,],N%G%@%2*#wpi}ZvSoKhEa=Y6R/J'D!=55.&         '.6=ESZapw     ''//66=$E$E+K2K2K:S:SAZAZAZAZAbAbAbAb9b9b2b2b+b$bbbbbbbbbbbbbbbjjjjp}pvxvxohhKDDD<<<<5555555555<<<DDD,J4RBRIYPY_`mhtoov}")7FTcq   #* 9 @GNNU]ddkkrryyy|ngXQC<-&  %--4;;CCIIPPXXX___ _ _________X X XXPPPIIIBBB;;444,,y%k%dUN@9*# yyyqykykqdqdq\k\kUkUcNcNcG\G\@\8U8U1U*N*N#G#GG@@ @ 88881111***## wppjb[TTLF??700))"  ##)088?F18?FMTT\cjjqxyyyrrkkdd]VVNNHAA922+$$yyqkkdd\\\UUUUNNNNNHHHHH@@@@@999992222$$$$$$$$$$$$%+22:AHOVV]elrz #*188?GMT\zcmcej^pWxPxB;3, ||| u uuuu"u"u)u)u0u0u7|7|>|>EEELLLSSSSS[[[[[ZZZZZZZSSSSLLLEE>>7700((!  !(6=KS`hv|~~wppjjjbb[[TTMMFF??88811)))##(.=DRYgu |  &4BJW^ms  #)8#?#L#T#b#i)w)))))))00000 00'05)C)Q)`)m)|####     %3:HVdky             ''.     ''.55<CJQX^fm{ #*17?FMTZaipw}}{{tttnnngggg``````XXXXXYYYYYYY`````ggggnnn|t|t|t|tu|u|u|unnngg___XX<<55/..''     ""))0~0~7w7w7w>p>pEiEiEiLaLaSaSZSZZZZZaTaTaThThToToToTvTvT}S}S}SSSSSSSSSSSSZZYYYYYYYYYYYYSSS600)!! sl]PI:-$$w+i+U+F292+229999999??u?h?Z?E?7?)?? ?99999222**##|uoaZSLE770)" ||||uuunnnnhhaaaYYRRKKEE > >770))"  }}}vvo|o|ovhohohoahahahaaZaZaZaZaSaSZSZSZSZMZMZMZMZF>F>F>F>F>?>?>?7?7?7?7?78787878787171717*7*7*7#7#???????FFFFMMMTTTZZaahhpww}$+18?FMMT[bippv} (/6=EKR`gmt{{     $$$$, , , 2 2 2 9 9 9 @@@@GGGNNNNNTTTTTTTT[[[[[[[[[\cccjjjqqw ww~ '.5;BPW^esz %,299@GGNNNUUUUUUUUNNGG@92,% ~rwdw^qPqBj4j&cc \\\\\\\\\\\\{ct\QcJcDj=j6q6w/w(~(""""""(((/6==DJQ_fm{(/=DQXfmt{ &4AHVcjqxxqc]OA:, zslzff_QX=X(QJD=66/(x(d"O":"&""""""((//66={=_D_JYJ_Q`X`_g_mftlssz &4BO]krxkVI4 zslfg_LX8QJ=6/"k P4 |ohZTMF???88??xFxFxMxTr[rbrirwr}kkkkkkd]]]VVVPPIIB B;!4/46.D.J'Q X _fmms s sssmmf_XQJD6/(   ''..q5d;V;IB;B5I'IP PPWWWW^^^^^^^^^^^ ^^'^5^B^PW^WkWWPPPPJJJCCC*<7^8^8^8^1^1]1]*]*]#]#]#WVVVVVPPPIIBB<5/(! zlXK>){hZF9%wpd]VOHHB;{;u5n5g.a.Z'T!M!F?2 +% {unh~awZwTpMpFi@i3c,c%]] VVOOOHHHBBB;x;j;^4W4I4<./."''!! uuuuuoooooooooooooooovvooooohhbb[UNGA:4& ||||vvvoohhaa[UzUsNmGf@`9Y9R3L-L&E?81 ++%%%,,299@FFMSZaahou{ou|||vpib[UOHA:4'  {tmgg`ZSLL F?9(9/25+B+I%V]djw~   $$$+++22222 2 2 222222++++&+&+,+,+,+3+3+:+:+A+A+G+G,M,T,T,[,[,b2h2h2n9u9u?|?FMMTZ`gnnu{|uunhaa[TTNGG@@::4444vooib \ \&U&N-H4H;BA;G4U4\.b(o(}!!  (;I\jv(5IV c p}""(((..55 <<C C I&I-O-O-V4V4]4c4c4j4p4p4w4~-~-&&&    &-:AGT[hn|~~x xqqk,k3d9d@^G^GWMWSPSPZJZJaKaDaDa=a=a=a7a7a7a7a7a7Z7Z7Z7Z7S7S7S=M=MDMDFKFKFQ@X@^@^9e9l2r2x,,& nnggaaaa[[[[[[[[[[[[[TTTTTTTTTMMMMMMMMGGGGGGGGAAAyAyAs:s:m:m3f3f-f-_-_&_&` ````f f fmmsz  &- 3:AG#T*[1a7g=nD{DKQQXX^^^^dddddkkkk kkk*k7k>eKeXe_elexeeeeeeeekkkrry!(5;HOUbiou|  -3@FTZgn{{uohb[THA:.' ~{w{qtktdmdm^gWgWgPaPaPZ0Z0Z0a0a0a0g0g0m0m0t0{00666===CCJPPW]djpw)0=JP]jp} ,29FMSY`fmsyy}pc]OI<6("yyrrllfff_____eeeelllrrx"x(x/x5e<eBeIlVl\lclilvl|lllllllkeeeee^^^^^XWWWWQQQQKKKDDD>>>77700***$$|ui\U H ;5(zzs{sususnsnshshsbzbzb[[[[[TTTTTT;;;4444444444 ..-!-'---4';'A'H'N!T![!a!ahnntt{{ { { {{{{{ttmhhaZTMG:4-'   -3@MZ`m z&3@MS`ms'!'4:AGMTZZaaa````ZZSMG@:3' slfYSLsFf9Y3S,F&@ 9 ,&       %,%,,2299???FFFLLRRRYYY___ffflllrryyyyxxrrkee_XXRqRkKeK_EX?R?E8?888+2%2+++$$$$$$$$$$$y$r$e$_$Y$R$E$?+9+9+2+,+%+%1%111188%8%>%>,>,>2E2E9E?JEJEQLQRQYW_We^e^kdrdxdjjjqqqqwwwwwqpppppppjjjddd^]WPPJD>>71*$$ xkeXK?9,|uoohhhbbhhhoou| ####))# |uoi\VOxIqBk6_0X)R#E?8 2+%   )%0+62=8I?PEVKbRiXvd|kq~  "%(%/+5+5+<+<2B2B2H2H2H+H+H+H+H%H%B;;;55/(("|vvppiicccc]]]]]ccciippv} %+28>DDKKKKK}KwKpDj>j>d8^2W+W%QKD D>>8822++%%%}}}%%%%%%+++++++++1111111118888+818>8D8Q8^>c>p>w>>>>>DDDDDD>DDDD DDD,D3D9DEDLDRDX>_>e>k>k8q8q1q1q+q+q%qqkkd _XRK?92& ~wqjd^XQKE?92,%  }wpjjd^XXQKE?922,%  viW~J~>x+xqqkkkeee____x_k_e_X_L_E_9_3_-_&e!eeekkkrr!x&x-39ELY_eq~ reRF3!"""r"`(M(4("(.....4444t4g4[4N5B;5;);#;;; ; AAAAGGGM MTTZ)Z0a>>9933,,,&&  &&& &&,228>DJQQW\ciiouu{{{{{{ { { u u o oib\WPJD>82+%  zztt$t$t*t0t6t=t=tBtHtOtUt[z[zazggmsszz $$**11777z<z<z<z<z<z<z<z<z7y700**$ sgaUH<0$ {uh\PJ>82&    ,28DJVcou*<HT`ms ##)//55;;AAGGMMMMTTTTTSYY~YsYlS`STSHS<S0SMMMMGGGAAA:::5u5i5]5W/K/?(!(""""""""""""""(((((.....555::::@@@@@FFFFFFFFFFLLLF FFF!F-F3F?FE@Q@W@d@o:v:::444..((("!! #))0066 < < A A A H HHNNNNNNNNN 6 6 < < < < < A A A A A A H H H H H HNNNNNNTTTTTZZZZZZ````____ffffffffffffffffffflll~r~r~x~xx~x~xxxrrrrrrrrrxxxxxx}}&}3}>}K\it#)5GS_q}}}xxrrkke _ _ ZTTMGG A < <5//)## vpdXLE:-"snga[UIIC=}7}1}+}%}%}wwww wwwqqqqkkkeeeeeee___________________eeeeeekkkkkkqqqqqqwwwww}}}}}|wqqke_YSMGA;5//)#   ####)#)#/)/)5)5#;#;#A#G#G#M#MSYY^ddjqww| xxxxxxxxxx~~~~~~~~~~~~~~~~~~~xxxxxrrrllllg g g aaa[[TUUNN"N"N"I(I(I.I.I.I4I4I4I:I:I:O@O@O@O@UFUFUFUF[F[F[FaFaFaFaFaFaFgFgFgEgElElEl?r?r?r?x?x?x?????????????9y????EEEEKKKQQQQWWWWW]]]\\y\y\y\y\s\s\s\m\mVgVgVgVaPaPaP[P[K[KUEUEUEO?O?O?J9J9D3D3D->->->'>'8'8!8!8!22222,,,,,,& & & & &&& !!!{uoic!]!X'R-L-F2@8:>4>.D(J"JPVV\ bhhmsy ".4@FRX]io{ysmmhb\VPKE93-'! }wwwqqkkkee_``ZZZZTTTNNNNHHHBB===7711+++%% zuoic]WQE@:4(" zni]WQE?:.(" ".:FQ]it !'-39?(D4J?PKPWVb\hatgmmsy #)/55;AFLLRXX^diiouu{  ##))//55;;AAGGGLLRRRXXX^^^ddddjjjjjjjooooooooouuuuuuuy{t{n{b{\VKE93("th\WK?:.( """""((((.....4444399999??????EEEEEEJJJJJJPPPPPPPPVVVVVVV\\VVV\\\\\aaaagggmmmmssxx x~~~"(-399?DJPV[aggmmssxx~~~~~~~~~~xxxssmmgaa[VPJDD>93-"|vpe_ZTIC=7 %   &,27=CIOTZ`flqw}   !!!'''----33339999>> > D DJJPPUU[[`fflrw} #.4:EKQW\bbgmss}y}~}~w~wwrrlllff~f~`y`yZsZsZmUgUgUaJEJ?J:D4D.>(>(>#9933 --'''!! }wwrllfff``ZZZUUUOOOOIIIIDDDDD>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>~>~>~>~>r!r!r!r!m!m!m!m!g!g!g!g!g!b!b!b'b'b'b'b'b-\-\-\3\3\3\8\8\>\>\C\I\O\O\U\Z\`bfbfbkbqbvb|bhhhhmmmmssssxxxx~~~ !!&&,,,,,222227777777777777777777777!!!     &&&&&++++1117777=====BBBBBBBBBBBBBBBB G G GGGGGGGGG!G!G'M'M,M,M2M2M8S=S=SCSCSISISNRTXTXYXYX_X_XeXkRkRpRpRvR{R{MMMMLGGGGAAAA<<<6600**%%{uupjje__YTNNHC=822,'! zzzzzzzzzzzzzzzzztttooiiiiddddd^^^^^^^^^^^^^^^^XXXXXXSSSSSMMMMHHHBB<<{7u7u7p2j2e,e&_&Y=8833- - -'''""""""""(((--3399>>CCIOOUZ__ekppv{{vvqke`ZZUOID>9 3 ..("  &&&,,,1 &&&,,,11177<<<BBGGMMSSXX]]cciinnsssyy  ~~~xxxxxxxxxxxx~~~~~~~~~~hhhnnnnnmmmmmmmmhhhhhhhbb b b]]]]]W W W W%R%R%R*R*R*R*R*R*L*L*L*L*L*L*L*L*L*L%L%L%L%L L L L LLLLLLLLLRRRRRRRWWR R W%W%W+W+R0R6R6R<RARFRLRQRWR\RbRgRmRrLwL}L}LLGGGGAAA&&&  %%%%+++11166;;AAFFLLRWW\\bggmmrww}}  %++16;;AFLQVV\bgmmrw}}}}wwqqlllg}g}gwaqalal\g\a\\\\\V\Q\L\L\F\@\;\;\6\0a0a+a%a%g gglllqq q ww|||||wwqqqlllgggaaaaa[[[[[[[[[[aaaaaaaaaaaaaaaaa~a~aayayayatatatatataoaoaoaoaoaoaoao[o[o[o[o[o[o[o[o[tVtVtVtVtVtVtVtVtQtQtQtQtQtQtKtKtKtKtKtFtFtFtFt@t@y@y@y;y;y;y;y6y6y6y6y0y+^+^+^+^%^%^%^%^%^%^%^%^YYYYYTTTTNNNNNNIIIIIIIIIIIIIOOOTTTZZ__ddjoouuzz %%%%*********%%%%%%   %**005::@EEKPUU[``fkkpu{  !!!!''',,,1%1%1%6%6%6%<%<%<AAAGGGLLLQQ<<A A G GGKKQQVV\\\aaafffllkqqqqqqqvvvvvvvqqqqqqkkkfffaaa[[[VVVPPKKKFFF@@@;;;5555000++++++++++++++++00005555:::@ @+ +///55%:%:*@/@5@5E:E?E?JEJJJJOPOPOTUTUZUZUZZ_Z_Z_Ze_e_e_e_e_e_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_j_o_oZoZoZoZoZtZtZtTtTzTzTzOOOIIIDDD??9944.*$$   yytnnyjydydt_tYtYnTnOnOnJiDi?i?i9d4d/d*d$d$_______ ________dddddddddddd______^^^^^^^YYYYYYTTTTTOOO|O|O|OxIxIxIrIrIrImDmDmDgDgDgDbDbDbD]D]D]DXDXDXIXIRIRIROMOMOMOMTHTHYHYCYC^C^>^>d>d>i8i8i8i3n3n3n-n-n.s)s#s#s#ssssssssss s ssnnnnniiiiidccc^^YYSSSSSNNNNNNNNIIIIII{IvIpIpIlIfIfIaI\IVIQIQILIGIGIAD<D7D7D2D2D-D'D'D"D"DDDDDDD > >>>>>>9999994444////))))$$$ $$)))//44999>>CCCCIIIINNNNNNNNNNNNNNNNNNNI I IIIIICC C C$C$>*>*>/9/95959:4?4?4D4D.J.J.O.O)T)Y)Y)^)d)d)i)n$s$s$y$~$$))))))))....)....4444888>>>>CCC CHHH N&N+N0S0S5S;X@XEXJ]J]O]UbZb_bdhihimomtryr~rww||| $$))..4488>>>CCHHHMMM3888>>>CCCCCHH|H|H|HwHwMwMqMqMqMlMlMlMgMgMgMbMbM]M]M]MWMWMRMRMMHMHMHHHHHCHCHCH=H=H8H8H8H3H3M3M3M.M.M.M.M)R)R)R)R)R#W#W#W#]#]#]#]#b#b#b#g#g#l#g)l)l)l)q)q)q.v.v.|.|3333888===CCCHHHHMMMMRMMMMRRRRRRRRRRRRRRRRRRRRRRRMMM M MMMMM!M!H&H+H+H0H0H5H;H;B?B?BEBJBJBO=O=T=T=Y8Y8^8^8d3d3i3i.i.n.n)n)s)s#s#x#xxx}}}}}}}}}}} } } }}}}}}}}}}}}}}}}}}}wwwww^ccccccccccccccccccccbbbbbb]]]]]]]]]]]]XXXXXXXXXSSSSSSSNNNMMMMHHHHHHHHCCCCCCCC>====99999933333....))))$$|||wwqqqqllllllllllllllqqqwww||zzzzzzuuuuuuuuuuuuuuuzzuuuuuzzzzzzzzuuuzzz|||||||||  !!&&&,,,11166;;@@EExJrJmOcO^TYTOYJYE^@^:c5c1h+h&m&m!rrwwcc h m r r w |   !!!&&,,,11166;;;@@EEEEJJ JJJJJJJE#E#E(E(@-@-;-;2626212,7,7'7'7"7777<<<<<<<77777777777;;;;;;@@@@@EE EEEEJJ"J"J'J'1'1,1216161;1A1A1F1K1K1P1P1U1U+Z+Z+Z&_&_&_&d!d!d!dddddd__ _ _ ZZZUUUPPPKKKKKKFFFFFFFFFKKKKKKKKKKPPPPUUZZ``einnty~ "'-26;AFFKOTTZZ__dddhhhhhhhhhhmmmmmhhmmmmsrrrxx}}}{{{{{vv v q q q l l g g b b ] ] XSNNIDD?::500+&&!     %%*0/499>>CCHHMMMRRR|R|RwRrWrWmWhRhRcR^RYRYRTRORJMEMEM@M;H6H1H,H,H'H"CCCCCC CCCCC>>>>====888883333///*))$$${vqllgb]XSOJ{D{?v:q6q1l,l'g"gcc]] XXSSNNJJEE@@;;611,,'"" vqhc^YTOJE@;61,'"   #)$.).3388<994400++&&!!  ~~yytppffa\\XXSSNNIIIDDD???????????????CC~C~C~C~H~HyHyHyMyMyMyMyMyRyRyRyRyRyRyRyRyRyRyRyRyRyRyRyMyMyMyMyHyHyHyCyCy?y>y:y:y5y5y0y+u&u&u!pppkk kfffaa\\\XSSNNIDD?;66}1x,n'i#`#QLC>40&!zuup{l{g{g{b{]{X{T{O{J{J{E{@<72-($ {wrmc_ZUKGB=84/*    %%).338=AAFKPUYY^chmqv{  # #(-26;@E!J!N%S*X*]/b/f4k8p8u=z=zB~GGKKPPUUZZ__ccchhmmmrrwww{{ !&&+0499>CGLQQVZ_ddinrw|  %%*// 3 3 8 8 = = = = B B BBBGGGGGGGFFF F F F F%F%F%K%K)K)K)K)K)K)K.FFFKKKKKKKPPPPPPPPPTTTTTTTT T T TTYYYYYYYYYY^^^^^^bbbbbggggllllqqqqquuuuzzzzzzzzzzzzzzzzzzzzzzzuuuuuuuuuuupppppppllllllllllllkkkkkk~k~k~kykykykukukpkpkpkkkkkgkgpgpbpbpbp]u]uYuYuYuTyTyOyOyJ~J~F~F~A~A~<8833.**%  }ytp kkfa]"X&X+S0O+3035.9.>*B*G%G%L P PUZZZ^^^ccc ccc c ^ ^ ^^YYUUPPLGGB=884/++&!!       %%**//33388<<<AAAFFAAAAAFFFFFFAAAA<<<733..)%    ""&+/449>BGK}KxPtUoZo^j^ecegal\q\uXuXzXSSSSNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNEEEEEEEE@@@@<<<77722...))$$$    $)).2 7 ; @ EINW\`ejnsw| $$$$$$$$$$$$$  { v vrmmid__[$[$V)R-R-M1M1H6H;D;D?DD?D?H?H;M;M;R;R;V;V;[;[;[;_;_;_;d?d?d?i?iDhDmDmDmDrDrDrDvDvD{H{H{HHHHHHMMMHHHHHHHHDDDD?$$$ |xztvovjqfqam]h]hXhTcOcO_J_J_F_F[B[B[B[=[=[=V8V8V8V8V8V8V8V8V8V8V=V=[=[=[BZBZB_B_B_BcFcFcKhKhKhOmOmTqTqYq]u]uazazffkoottxx}}otttxxxx}}}}}}}xxxxtttpppkkffffbbbbbbbbbfffkkppty}~~~~~~~~yyyyy uuuuuu$q(q(q-q1q1q6q6l:l:l?l?l?lCgCgCgCgGgGgGcGcGcGcGcGcGcGZ-Z-Z-Z-Z-Z-Z-Z-U-U-U(U(U(Q(Q(Q(L(L(G(G(C(C(?-:-5-5-1---(1#1155: :??CCGLLQUUZ^^bgglpptyy~~~zzvqqqmmhhhhhhhhhhmmmqqvvz    !!&&&***........333333333333333333332222222!!!!%%%))...277;??DDHMMQUZ^cgkpty~    ###'''' ' ' ' , , , , , ' ' ' ' # # # # #############''#'#'#'#'#'#'#'#'#'#'#'#'#'#'#'#'#######   ~z`[WRNNJEA<883/*&""  zvqqmiid``[WWSNJEEA=884//+''" }}}}yyyyuuupplpllglcgcc_c[_[[V[RVRRNNIIEIEE@@<<<8833/3+/&+"&&"       # #',059=AFFJOSW\`eeimqvzz~ ##(( ,11555 :>BFF"K&O+S/X3\8aAAFJJNRVVZ^cggkossw{    $$(((,,00004 4 4 4 8 8 88888888888888888888888888844#4#4#4#4#4#4#4#4#/#/#/#/#/#/#/#+#+#+#+#+++'''''''######      ~~zvrrniff~a~]zYvUrUnQiMfIaE]AYAU=Q9Q4M0I,E,@(@ =9440, ,(($$   zzvvvrrnnnjjfffbbb ^ ^ ^ Z ZVVVVRRRNNNNJJJJFFFBB>>>>:::::6666666222222222222222266666666:::::::>>>>>>>>>>>>>>>??::::::::::66666662222222222/////2{3w3s3p3k3g3c3_7[7W7S7S7O7K;G;C;?;??;?7?7C3C/C/G+G'G'K#K#OOOSSSWWW\\\\___cccdhhhlllpppttxxx||####''(,,,000003444448888888888888888888888844444444400000000000000000000000001111111111111 1 444448888=#=#=#A'A'A+E+E+I/I/M3M3M7Q7Q7U;U;Y?Y?]?aCaCeCeGiGiGmKmKqKqOuOuOuOySySyS}W}W}W}W[[[___cccgggkk}k}k}o}o}oysysywuwu{u{qqqmmmiiieeeaa^^^YYZUUUUQQQQQQMMMMMMMMMNNNNNNNNNNNNNNNRRRRRRRRRVVVVVVVZZZZZ^^^^^^bbbbbbffffffffjjjjjjjjjjjnnnnnnnnnnrrrrrrrvvvvvvzzzz~~~~~~zzvvrnnjffb^^ZVVRRNJJFFB>>;;7733//+++''###  ||||xxxxxxxxxxxxx|||||| """&&**..11599==AEEIIMPPTTX\\``ccgkkooossvvzz~~ ""&&))-115599==@@DDHHLLPPTTWW[[[__ccggkkknnrrvv v z zz~~~"""""%%%%)))))------11111155555588888<<<<<<@@@@@?CCCCGGGGGGKKKKJJJNNNNNNNRRRRRRRRRVVVVVVVVVVVVVVVYYYY]]]]aaaaddddhhhhlllllooooossssswwwwww{{{{{{{z~~~~~~~~~~~~~~|~|~|~xxxuuuuqqqqmmmmiiiieeeebaaaa^^^^ZZZZVVVRRRROONKKKGGGGCCCC}?}?}?}?}<}<}<}<}8}8}8}8}8|8y4y4y4y4y4y4x4x4x4u0u0u0u0t0t0t0q0q0q0q0q0m0m0m0m0m,i,i,e,e,e,a,a,])])])Z)Y)V)V)V)R%R%R%N%N%N%J!J!F!F!F!CCC??;;;7733300,,((($$ $                         ~~~~~~zzzzzzzzzzzzzzzzzzzzzvvvvvvvrrrrrrrrrrrrrrrrrrrrrrrrrrrrv v v v v v v vvvvvvyyyyy}}}}!!!!!$$$$$$$$$$$$$$$$$$$$$$$!!!!!!!               $$$'''+++///33366::===AAEEIILLLPPSSW|W|[x[t[t^p^mbmbibffbebi^i[iWmSmPpLpLpHtEtAtAx=x:x:{6{2{2//+'''$$  ~~{{{wwwssspppplllliiiiiieeeeeeeaaaaaaa^^^^^^^[[WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWTTTTTTTPPPPLLLIIIIEEEEBBBB>>>::::;77777777777777777;;;;;;;;;;;;;;;;;;;77777400---))%%&""" } } } y#y#y#y'u'u*u*r*r.r.r.n2n2n2k5k5k5g5g9g9c9c9c9c9`9`9`9\9\9\9\9Y9Y9Y9Y9U9U9U9U9Q9Q9Q9Q9N9N9N9N9J9J9J9J9G9G9G9G9C9C9C9C9?9?9?9?9<9<9<9<=8=8=8=5=5=5=5=1=1=1A.A.A.A.A*A*A*D&D&D&D#D#D#DDDDDDHHHHHKKKKKK O OOOOOOOOOOOOOOOOOOOOOOOOOOOLLLLLLLLLLLLLLOOOOOPSSSSSWWWWZZZZZZZ^^^^^^^^^^^^^^^bbbbbbbbbbbb^^^^^^^^^^^^^___________[[[[[[[[[[[[[[[[[[[[[[[[[[[XX~XXXX[X[{[{[{[{[{[{[{[{[{[w[w[w[w[w\w\w\x\x\x\x\x\x\x\x\x\x\t\t\t\t\t\t\t\x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\x\xXxXxX{X{X{X{X{X{U{U{U{U{U{UUUUUUUUUUUUUQQQQQNNNNKKKKGGGDDD@@==9966622222|/|/|/|/|/|/|/|+|+|+|+|+|+|(|(|(|(|(|(|%|%|%|%|!|!|!|!||||||| }}}}}}}}}}}}}}}}}}}}} !%%(,/2269==@DGKNQUUX\_cfjmqtw{ "%,/39=@DKNRU\_cfimpwz~   !$((+..255588<??CCFIIMPPTWZZ^addhkknrruy||                                 {{xutqqnnkggdda]]ZZWVSPPMMIIFBB?<99522.++((%!!    |yy u r o#o#l#h'e'e'b'^*[*[*X-T-Q-Q-N-K1K1G1D1A1A4>4:4:474444717-7*7*7'7#:#: :::::>>>>> A A A A ADDDDGGGGGJJJJNNNNQQQQTTTTTWWWW[[[[[^^^^^aaaaaaadddddddddhggggggggggggggggggggkkkkkk k k knnnnnnnqq q q#q#t&t&t*t*t*w-w-w0w0w3{3{3{6{6~:~:~:~===@@@@@CCCCCCCGGGCCCCCC@@@@@@@@@@@@@@@@@@@CCCCCCCCFFFF}J}J}J}J}M}M}M}P}P}PzSzSzWzVzZzZz]z]z`z`zczczg}g}j}m}m}p}p}p}s}s}s}w}w}w}z}z}z}z}z}}}}}}}}}}}}}}}}}}}}}z}z}zzzzzzvzvzvzszsvsvpvpvmvmsjsjsfscscp`p`p]pYpVmSmPmPmMiIiFiFiCfCf@f@f<c<c9c9c6`6`6`3`3]3]3]0Y0Y0Y0Y0V,V,V,S,S,S,S,P,P,P,L,L)L)L)I)I)I)I&F&F&F&F#C#C"C C @ @@@@<<<<9 9 999666622220////,,,,,)))))))&&&&&&&&&""""""""""""~~{{xxuuq n n k h e e a ^ ^ [ X U U R N N K H E B B ? < 8 8 5 2 2 / / , , ) ) )%%&&&"""""""""""""##&&"&"&"&"&"#%#%#%#%#%#%#)#)#)#)#)#)#)#) ) ) ) ) ) ) )))%%%%%%%""""""           """"%%%(((+++////21115 5 5 5 5 58888888888888888555555555511111111111............++++++++++(((((((((((((%%%%%%%%%%%%((((((((((++++++++............................+++++++((((((%%%%!!!     "%&(++/22588;!>!>!A!D!D!G!G!J!M!M!P$S$S$V$V$Y$Y$\$]'`'`'c'c'c'f'f'i*i*l*l*o*o*r*r*u-u-x-x-{-~-~--------------------*********'''''''''''$$$$$$$$$$$$$$$ $$$$$$$$ $$$'$*'-'0'0'3'6'9'9'<*?*?*B*E*E*H*H-K-N-N-Q-Q-T-T/T/W/W/Z/Z/]3]3]3`3c3c3f3f6i6i6l6o6o6r6u6u6x6{6{6~66666662222222/////----)))))&&&&####      !!$$'''**---000000022222255558888;;;;>>>>AAAAADDDDDGGGGJJJJJJMMMLLOOOOORRRRUUUUUXXXXXXX[[[[[[]]]]]]``````cccccccccccfffffffffccccb______________bbbbbbbbeeeeeeehhhhhhhhhhhgdddddddaaaaa^^^^^[[[[XXXUURRROOLLLIIFFFCC@@@==::77441..++(%%""    !!!!$$$$$$$$$$''$$$$$$$$$$$$$!!!!!!!~~~{{!{!y!y!v!v$v$s$s$p'p'p'm*m*m*j,j,j/g/g/g2e2e2e5b5b5b8b8_8_:_:_:\:\:\=\=Y=Y=Y=Y=V=V=V@V@V@T@T=T=T=T=T=Q=Q=Q=Q=Q:Q:Q:N:N8N8N8N8N5N5K5K5K2K2K2K/K/H/H/H,K,K,K,K*K*K*K*K)K'N'N'N'N'N'Q'Q'Q'Q'S'S'S'S'V'V'V'V'Y'Y'Y'Y'\'\'\)\)\)\)\)\,\,^,^,^,^/^/^/^/\2\2\2[2[2[4[4[4Y4Y4Y7Y7V7V7V7V7S7S:S:S:P:P:P:M:M:M:M=K=K=K=K=K=K=H=H=H=H=H=H?H?H?H?J?J?J?J?J?M?M?MBPBPBPBSBSBSBUEUEXEXE[E[E^H^HaHcGcGfJiJiJlJoJqMtMtMwPzP|PPSSSSUUUUXXX[[[^^^```cccfffiiikknnnqqqqtttvvvvyyyyy||||||~~~~~~~~~~~~~~~~~~~~~~~~~~~||||||||{{yyyyyyyyyyy~y~y~y~y{y{y{yyyyxxxxxvxvxvxvxsxsxs{s{p{p{p{p{m{m{m~k~k~k~h~h~eebb``]ZZWTRROLIGGDA><9641.+)&#  }}}}}{{{{xxxxxuuuuurrrrrrooooooooooooooooooooooooooooooooooooooooooooooooooo~o~o{l{l{lylylvlvivisisisgqgqgqgqgndndndnananakak_k_k_k\k\k\k\kYnYnYnVnVnVnSnSqSqSqQqQtQtNtNtNvNvKvKvKvHyHyHyHyFyFyFyC|C|C|C|@|@@>>>>;;;88866663330000---++*|*|(|(|(|(y%z%z%z%w"w"w"w"w t t t tttttttrrrrrrruuuu u u u u wwwwwzzzz}}}}}}}}zzxxuuussppmmkkhhffccc``^^^[[[YYYYYVVVVVVVVVVVYYYYY\\\^^^^_aaaadddfffiiilllllnnnnnnnnnnnnllllliiiigggdddbb____]]]ZZZZWWWWWWUUUUUUWWXXXXXXXXZZZZZ]]]]````bbbeeeghhjjjjjjmmmmmmmmmmmmmmmmmmmmmmmkkkkkhhhheeeeccc```^^^[[[YYYVVVTTTQQQQQOOOOOLLLLLLLLJJJJJJJGGGGGGGGGGGGGGGGHHHHHHHHHHH H H H H H H HHHHHHHJJJJJMMMPPPPRRRUUUUWWW!W!Z!Z#Z#Z#Z&Z&Z&Z(](](]+]+]+]-]-]-]0]0]0]0]3]3]3]5]5]5]5]8`8`8`8`:`:`:`:`:`=`=b=b=b?b?b?b?e?eBeBeBgBgBgBjDjDjDmDmDmDoDoGoGrGrGtGtGwGwGzGzI|I|IIIIIIIIILLLLLLLLLLLLLLLLNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNKKKKKKKKIIIIIIIFFFFFFFDDDDDAAAAA?????<<<<9999777744442222////----****(((((%%%%%%%%%%%####%%%%%%%%%%%%%%%%%%%%%%%%%%#######     """%%%%''''***,,,,///11133666888;;===@@@BBEEEGGJJLNNQSSVXX[]``begjlloqsvx{}  !!!!!!!!$$$$$$&&&&&((((++++----000222444777999;;;>>>@@@CCBEEEGGGJJJLLLLNN N N N Q Q Q Q Q Q S S S S S S S U U U U U U U U U U X X XXXXXXXXXXXXXXXZZZZZZZZZZZZZZZZ\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ZZZZZZZZZZYYWWWWWUUUUUURRRRRPPPPPMMMMKKKKKIIIIIFFFFFFDDDDDDAAAAA??????======::::8888666633331111///,,,,***'''%%%###  }}}}}}}}}{{{{{{{{{{{{{{{{{{{{{{{{xxxxxxxxxxvvvvvvvvvvvvvvvvvvvvvxxxxxxzzzz}||~~~||||yyyywwwwuuuusssspppnnnnlllliiigggeebbb``^^\\YYWUUSPPNLJJGECAA><:88531.,,*(%#!! ~||ywwuussqnnlljjhhffccaa__]][[XYVWTTRRPNNLLIIGGEECCAA??<<::886644222//--+++))''%%%""   ""$$&&))++-//22446688::==? ? ? A A C CEEHHJJLLLNOQQSSUUUWWWZZ Z \ \"^"^"^"`$`$b$b&e&e&g)i)i)k+k+m+m+p-p-r-r-t/t/v/v1x1x1{3{3}3}366668888:::::<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<999997777555533333111////,,,*****(((((&&&&&$$$$""""" !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!    ""$&&( ( * * , , . ..00333446669999;;;====?? ? ? >"A"A$A$A$A&A&A&A(A(A(A*@*@*@,C,C,C.C.C.C.C0C0B0B0B2B2B2B2B4B4B4B4B4B4B6B6B6B6@6@6@6@8@8@8@8@8@8@8B:B:B:B:B:B:B<B<B<D<D<D<D<D>D>D>F>F>F@F@F@F@HBHBHBHBHDHDJDJDJFJFJFJFLHLHLHLHLJNJNJNJNLNLPLPLPNPNPNRNRPRPRPTPTPTRTRVRVRVRVRXTXTXTXTZTZTZTZTZTZTZT\V\V\V\V\T\T\T\T\T\T\T\T\T\T\T\T\R\R\R\R\R\R\P\P\PZPZPZPZNXNXNXNXNVNVNVLVLVLTLTLTLTLTLSIQIQIQIQIQIQGQGQGPGPGPGPFPEOEOEOEOEOEOCOCOCOCOCOCOAOAOAMAMAMAM?M?M?M?M?M=M=O=O=O=O=O;O;O;O;O;O9O9O9O9Q9Q9Q7Q7Q7Q7S7S5S5S5S5S5S3S3S3S3S3S1S1S1S1S1U/U/U/U/U/U/U-U-U-U-U-U-U+W+W+W+W+W)W)W)W)W)W'W'W'W'W'W'W%W%W%W%W%Y%Y#Y#Y#Y#Y#Y#Y!Y!Y!Z!ZZZZZZZZZZZZ\\\\\\\\\\\\\\\\\\\\ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^^^^^^^^^^^^^^``^``^^^^^^^^^^^^^^^^^^^^^^^^^]][[[[[YYYYYYYYYYYYYYY[[[[[[[[[[[]]]]]]____aaaaccceeeeggiiikkkkmmnnnppprrtttvvvxxxzzzz|||||~~~~~~~}}}}}}}{{{{{{{{{{{yyyyyyyyyyyywwwwwwwwwuuuuussssssqqqqqooooooommmmmmmmkkkkkkkiiiiggggeeeccccaaaa___]]][[[YYWWVVTTRRPPNNLLJJHHFFDDBB@@>><<:::99775533311//--++))''&&&$$""                                                  ""$$%%'')))++,,...0022233355577888:::<<<==???AAAACCCDDDFFFFHHHHIIIIKKKKKMMMMMNNNNNPPPPPPPPRRRRRRRRRQQQQQQQQQQQQQQQQQQPPPPPPPONNNNNLLLLLLJJJJJJIIIIIIHGGGGGGGGGEEEEEEEEEEECCCCCCCCCAAAAAAAAAAA@@@@@@@@@@@@@@>>>>>>>>>> > > > > > > >>>>>>>>>>>>>>>>>>>>>!>#>#>$>$>&>(=(=)=+=+=+=-=-=.=.=0=2=2=3=3=5=7=7=8=:=:?<==?=???A?A?B?B?D?F?F?G?IAIAKALALANANAPAQAQASASBUBUBVBVBXBZBZB[B[B]B]B^B^B`B`BbBbBcBcBeBeBgBgBhBhBjBlBlBmBmBo@o@p@p@r@r@t@t@u@u@w?w?y?y?z>z>|=|=~=~====;;;;;;;99999999988888888888888888888888866666666666666666666666666666666644444444444222222211111//////-----,,,,*****((((''''''%%%%%%%#########""""""""" ~~|{yywuttrqqomlljhggecbb`_] ] [ Z X X V U SSRPNMMKIHHFECAA@>=;9864310.,++)(&$##!       " " # # % % % & &((()))++++,,,,......///////111111122222 2 2 2 2!2!2!2!4#4#4#4#4$4$4$4$4&4&4&4&4&4'4'5'5'5'5'5'5)5)7)7)7)7)7*7*7*7*7*7*7*7*8*8,8,8,8,8,8,:,:,:,:,:,;,;,;,;,;,=,=,=,=,=,>,>,>,>,>,@,@,@,@,@,@,A,A,A,A,A,A,A,A,A,C,C,C,C,C,C,C,C,C,C-C-C-C-C-C-C-D/D/D/D/D/D/D0D0D0D0E0E2E2E2E2E2E3E3E3E3E3E5E5E5E5E5E5E5E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E4E4E4D4D4D3D3D3D3D1C1C1C1C0C0C0C0C.C.C.C-C-C-C+C+C+C*C*C*C(C(C(C(C'C'C'C'C%C%C%C%C%C$C$C$C$C$C$C$C"C"C"C"B"B"B"B"B B A A A A A A @ @ @ @@@@@@>>>>>>=====;;;;;::::::8888877777 7 7 7 7 7 5 5 5 5 5 555555555554443333333333333333333333333333333332222222222222000000000//////------,,,,,,,*******)))))))'''''''%%%%%$$$$####!!!           ! ! ! # # # # $ $ $ % % % % ' ' ' ( ( ( ) ) ) + + + , , , , - - - / / / 0 0 0 0 1 1 1 1 3 3 3 3 3 3344444444555555555555555566666666666666666 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 3 3 3 3 2 22111//...--++***))''&%%##""!!   !!!!!!!!!!!!!!!!!!!!!                                  """##$$%%&&'''))**++,,--...00111223334444555566666688888777777777777777777777777766666666666655555554444422211110000///....,,,,++++*****)))))((((((((&&&&&&&&&&&&&&&&&&&&&&%%%%%%%%%%$$$$$$$$######"""""    !!""##$$%%&&&'''((()))***+++,,,---...///000111223334455455566777888999::::;;;;;;<<<< < < < < < < ; ; ; ; ; ; ; ; ; ; ; : : : : : : : : : : 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 8 8 8 8 88777777777777777777777777666666666666666666665555555444444333332222221111 1 1 1 0 0 0 0 0 0 0 0 0 / / / / / / / / / / / /.......-----,,,,++++*****)))))((((''''&&&&%%%$$$$####"""!!!!     !!!!!"""###$$$%%%%&&&'''''((((((())))))))))))(((((((( ( ( ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ''''(((( ( ( ( ( ( ( ( ) ) ) ) ) ) ) ) ) ) ) ) * * * * * * * * * * * * * * * ) ) ) ) ) ) ) ) ) ) ( ( ( ((((((((''''&&&&%%%$$$$###"""!!                                                                 !       !!!!!!!!!""""""""""""""" " " " " "!"!"!"!"!"!!"!"!"!"!"!"!"!"!" " " " " " """""""""##########$$$$$$$$$$$$$$%%%%%&&&&&&'''''''&''''''''''''((((((((((((''''''''''''''''''&&&&&&&&%%%%%%$$$$$$$$#######""""!!!!                                              !!"""""##$#$$%%&&&&''(((()****+,,,--.../000122233444566677788999::;;;<<====>>?????@@@A@@AAABBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBAAAAAAAAAA@@@???>>>>>>>>====<<<<<;;;;;:::99999988777766666554444433322222211000000////...-------,,,,+++++++****)))))))(((('''''&&&&&%%%$$$$$$$###"""""""!!!!                                                                                                                                                                                                                                                                                                               csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/AudioInTest/000077500000000000000000000000001321653344700250125ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/AudioInTest/AudioInTestWindowController.h000066400000000000000000000017301321653344700326100ustar00rootroot00000000000000/* AudioInTestWindowController.h: Copyright (C) 2014 Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import #import "BaseCsoundWindowController.h" @interface AudioInTestWindowController : BaseCsoundWindowController @end csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/AudioInTest/AudioInTestWindowController.m000066400000000000000000000044041321653344700326160ustar00rootroot00000000000000/* AudioInTestWindowController.m: Copyright (C) 2014 Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "AudioInTestWindowController.h" @interface AudioInTestWindowController () @property (strong) IBOutlet NSButton *startStopButton; @property (strong) IBOutlet NSSlider *leftDelaySlider; @property (strong) IBOutlet NSSlider *leftFeedbackSlider; @property (strong) IBOutlet NSSlider *rightDelaySlider; @property (strong) IBOutlet NSSlider *rightFeedbackSlider; @end @implementation AudioInTestWindowController - (IBAction)toggleStartStop:(id)sender { if([self.startStopButton.title isEqualToString:@"Start"]) { NSString *csdFile = [[NSBundle mainBundle] pathForResource:@"audioInTest" ofType:@"csd"]; [self.csound addListener:self]; CsoundUI *csoundUI = [[CsoundUI alloc] initWithCsoundObj:self.csound]; [csoundUI addSlider:self.leftDelaySlider forChannelName:@"leftDelayTime"]; [csoundUI addSlider:self.leftFeedbackSlider forChannelName:@"leftFeedback"]; [csoundUI addSlider:self.rightDelaySlider forChannelName:@"rightDelayTime"]; [csoundUI addSlider:self.rightFeedbackSlider forChannelName:@"rightFeedback"]; [self.csound play:csdFile]; } else { [self.csound stop]; } } #pragma mark CsoundObjListener -(void)csoundObjStarted:(CsoundObj *)csoundObj { self.startStopButton.title = @"Stop"; } -(void)csoundObjCompleted:(CsoundObj *)csoundObj { self.startStopButton.title = @"Start"; } @end AudioInTestWindowController.xib000066400000000000000000000250731321653344700330720ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/AudioInTest csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/AudioInTest/audioInTest.csd000066400000000000000000000010471321653344700277370ustar00rootroot00000000000000 -o dac -+rtmidi=null -+rtaudio=null -d -+msg_color=0 -M0 -m0 -i adc nchnls=2 0dbfs=1 ksmps=64 sr = 44100 instr 1 kldelay chnget "leftDelayTime" klfeedback chnget "leftFeedback" krdelay chnget "rightDelayTime" krfeedback chnget "rightFeedback" asig,asig1 ins a1 init 0 a2 init 0 a1 vdelay3 asig+a2*klfeedback, kldelay, 3000 a2 vdelay3 asig+a1*krfeedback, krdelay, 3000 outs a2,a1 endin f1 0 16384 10 1 i1 0 360000 csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/Base.lproj/000077500000000000000000000000001321653344700246215ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/Base.lproj/MainMenu.xib000066400000000000000000001664271321653344700270560ustar00rootroot00000000000000 Default Left to Right Right to Left Default Left to Right Right to Left csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/BaseCsoundWindowController.h000066400000000000000000000020011321653344700302460ustar00rootroot00000000000000/* BaseCsoundWindowController.h: Copyright (C) 2014 Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import #import "CsoundObj.h" #import "CsoundUI.h" @interface BaseCsoundWindowController : NSWindowController @property (nonatomic, strong) CsoundObj* csound; @end csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/BaseCsoundWindowController.m000066400000000000000000000032701321653344700302640ustar00rootroot00000000000000/* BaseCsoundWindowController.m: Copyright (C) 2014 Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "BaseCsoundWindowController.h" @implementation BaseCsoundWindowController - (id)initWithWindow:(NSWindow *)window { self = [super initWithWindow:window]; if (self) { // Initialization code here. self.csound = [[CsoundObj alloc] init]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowWillClose:) name:NSWindowWillCloseNotification object:nil]; } return self; } - (void)windowDidLoad { [super windowDidLoad]; // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. } - (void)windowWillClose:(NSNotification *)note { [self.csound stop]; } @end csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/ButtonTest/000077500000000000000000000000001321653344700247355ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/ButtonTest/ButtonTestWindowController.h000066400000000000000000000017261321653344700324630ustar00rootroot00000000000000/* ButtonTestWindowController.h: Copyright (C) 2014 Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import #import "BaseCsoundWindowController.h" @interface ButtonTestWindowController : BaseCsoundWindowController @end csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/ButtonTest/ButtonTestWindowController.m000066400000000000000000000052221321653344700324630ustar00rootroot00000000000000/* ButtonTestWindowController.m: Copyright (C) 2014 Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "ButtonTestWindowController.h" @interface ButtonTestWindowController () @property (strong) IBOutlet NSButton *startStopButton; @property (strong) IBOutlet NSButton *valueButton; @property (strong) IBOutlet NSSlider *durationSlider; @property (strong) IBOutlet NSSlider *attackSlider; @property (strong) IBOutlet NSSlider *decaySlider; @property (strong) IBOutlet NSSlider *sustainSlider; @property (strong) IBOutlet NSSlider *releaseSlider; @end @implementation ButtonTestWindowController -(IBAction) eventButtonHit:(id)sender { NSString *score = [NSString stringWithFormat:@"i2 0 %f", [_durationSlider floatValue]]; [self.csound sendScore:score]; } -(IBAction) toggleOnOff:(id)component { if(([self.startStopButton.title isEqualToString:@"Start"]) ) { NSString *csdFile = [[NSBundle mainBundle] pathForResource:@"buttonTest" ofType:@"csd"]; [self.csound stop]; [self.csound addListener:self]; CsoundUI *csoundUI = [[CsoundUI alloc] initWithCsoundObj:self.csound]; [csoundUI addMomentaryButton:self.valueButton forChannelName:@"button1"]; [csoundUI addSlider:_durationSlider forChannelName:@"duration"]; [csoundUI addSlider:_attackSlider forChannelName:@"attack"]; [csoundUI addSlider:_decaySlider forChannelName:@"decay"]; [csoundUI addSlider:_sustainSlider forChannelName:@"sustain"]; [csoundUI addSlider:_releaseSlider forChannelName:@"release"]; [self.csound play:csdFile]; } else { [self.csound stop]; } } #pragma mark CsoundObjListener -(void)csoundObjStarted:(CsoundObj *)csoundObj { self.startStopButton.title = @"Stop"; } -(void)csoundObjCompleted:(CsoundObj *)csoundObj { self.startStopButton.title = @"Start"; } @end csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/ButtonTest/ButtonTestWindowController.xib000066400000000000000000000225101321653344700330100ustar00rootroot00000000000000 csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/ButtonTest/buttonTest.csd000066400000000000000000000013501321653344700276020ustar00rootroot00000000000000 -o dac -d -+msg_color=0 -m0 nchnls=2 0dbfs=1 ksmps=64 sr = 44100 seed 0 instr 1 ktrigger chnget "button1" knotedur chnget "duration" if(ktrigger > 0) then event "i", 2, 0, knotedur endif endin instr 2 ;print p3 iattack chnget "attack" idecay chnget "decay" isustain chnget "sustain" irelease chnget "release" ;ipchMul rnd31 .5, -0.5 ;ipchMul = ipchMul + .5 ;ipch = 100 + (1000 * ipchMul) ipch = 100 + rnd(1000) ;print iattack ;print idecay ;print isustain ;print irelease a2 linsegr 0, iattack, 1, idecay, isustain, irelease, 0 a1 oscili a2 * .25, ipch, 1 outs a1,a1 endin f1 0 16384 10 1 i1 0 3600 csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/ConsoleOutput/000077500000000000000000000000001321653344700254455ustar00rootroot00000000000000ConsoleOutputWindowController.h000066400000000000000000000017331321653344700336220ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/ConsoleOutput/* ConsoleOutputWindowController.h: Copyright (C) 2014 Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import #import "BaseCsoundWindowController.h" @interface ConsoleOutputWindowController : BaseCsoundWindowController @end ConsoleOutputWindowController.m000066400000000000000000000041131321653344700336220ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/ConsoleOutput/* ConsoleOutputWindowController.m: Copyright (C) 2014 Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "ConsoleOutputWindowController.h" @interface ConsoleOutputWindowController () @property (strong) IBOutlet NSTextView *consoleOutputTextView; @property (nonatomic, strong) NSString *currentMessage; @end @implementation ConsoleOutputWindowController - (IBAction)render:(NSButton *)sender { _consoleOutputTextView.string = @""; [self.csound setMessageCallback:@selector(messageCallback:) withListener:self]; NSString *csdPath = nil; csdPath = [[NSBundle mainBundle] pathForResource:@"consoleoutput" ofType:@"csd"]; [self.csound play:csdPath]; } - (void)updateUIWithNewMessage:(NSString *)newMessage { NSString *oldText = _consoleOutputTextView.string; NSString *fullText = [oldText stringByAppendingString:newMessage]; _consoleOutputTextView.string = fullText; } - (void)messageCallback:(NSValue *)infoObj { @autoreleasepool { Message info; [infoObj getValue:&info]; char message[1024]; vsnprintf(message, 1024, info.format, info.valist); NSString *messageStr = [NSString stringWithFormat:@"%s", message]; [self performSelectorOnMainThread:@selector(updateUIWithNewMessage:) withObject:messageStr waitUntilDone:NO]; } } @end ConsoleOutputWindowController.xib000066400000000000000000000127121321653344700341540ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/ConsoleOutput csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/ConsoleOutput/consoleoutput.csd000066400000000000000000000005721321653344700310670ustar00rootroot00000000000000 -o dac -+rtmidi=null -+rtaudio=null -d -+msg_color=0 -M0 -m0 -i adc sr = 44100 ksmps = 512 nchnls = 2 0dbfs = 1 gicount init 5 instr 1 printf_i "countdown: %d\n", 1.0, gicount gicount = gicount - 1 endin i1 0 1 i1 1 1 i1 2 1 i1 3 1 i1 4 1 i1 5 1 e csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/Csound OSX Examples-Info.plist000066400000000000000000000017411321653344700302170ustar00rootroot00000000000000 CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIconFile CFBundleIdentifier com.csounds.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSMinimumSystemVersion ${MACOSX_DEPLOYMENT_TARGET} NSMainNibFile MainMenu NSPrincipalClass NSApplication csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/Csound OSX Examples-Prefix.pch000066400000000000000000000002541321653344700301760ustar00rootroot00000000000000// // Prefix header // // The contents of this file are implicitly included at the beginning of every source file. // #ifdef __OBJC__ #import #endif csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/CsoundHaiku4/000077500000000000000000000000001321653344700251235ustar00rootroot00000000000000CsoundHaiku4WindowController.h000066400000000000000000000017311321653344700327540ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/CsoundHaiku4/* CsoundHaiku4WindowController.h: Copyright (C) 2014 Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import #import "BaseCsoundWindowController.h" @interface CsoundHaiku4WindowController : BaseCsoundWindowController @end CsoundHaiku4WindowController.m000066400000000000000000000022241321653344700327570ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/CsoundHaiku4/* CsoundHaiku4WindowController.m: Copyright (C) 2014 Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "CsoundHaiku4WindowController.h" @implementation CsoundHaiku4WindowController - (IBAction)startPlayCSDFile:(id)sender { NSString *csdFile = [[NSBundle mainBundle] pathForResource:@"IV" ofType:@"csd"]; [self.csound play:csdFile]; } - (IBAction)stopPlayCSDFile:(id)sender { [self.csound stop]; } @end CsoundHaiku4WindowController.xib000066400000000000000000000252111321653344700333060ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/CsoundHaiku4 Csound Haiku - IV Iain McCurdy, 2011. <CsoundSynthesizer> <CsOptions> -odac -dm0 -+rtmidi=null -+msg_color=0 </CsOptions> <CsInstruments> sr = 44100 ksmps = 32 nchnls = 2 0dbfs = 1 gisine ftgen 0, 0, 4096, 10, 1 gioctfn ftgen 0, 0, 4096, -19, 1, 0.5, 270, 0.5 gasendL init 0 gasendR init 0 ginotes ftgen 0, 0, -100, -17, 0, 8.00, 10, 8.03, 15, 8.04, 25, 8.05, 50, 8.07, 60, 8.08, 73, 8.09, 82, 8.11 seed 0 ; alwayson "trigger_notes" ; alwayson "reverb" instr trigger_notes krate rspline 0.04, 0.15, 0.05, 0.1 ktrig metro krate gktrans init 0 gktrans trandom ktrig,-1, 1 gktrans = semitone(gktrans) idur = 15 schedkwhen ktrig, 0, 0, "hboscil_note", rnd(2), idur schedkwhen ktrig, 0, 0, "hboscil_note", rnd(2), idur schedkwhen ktrig, 0, 0, "hboscil_note", rnd(2), idur schedkwhen ktrig, 0, 0, "hboscil_note", rnd(2), idur endin instr hboscil_note ipch table int(rnd(100)),ginotes icps = cpspch(ipch)*i(gktrans)*semitone(rnd(0.5)-0.25) kamp expseg 0.001,0.02,0.2,p3-0.01,0.001 ktonemoddep jspline 0.01,0.05,0.2 ktonemodrte jspline 6,0.1,0.2 ktone oscil ktonemoddep,ktonemodrte,gisine kbrite rspline -2,3,0.0002,3 ibasfreq init icps ioctcnt init 2 iphs init 0 a1 hsboscil kamp, ktone, kbrite, ibasfreq, gisine, gioctfn, ioctcnt, iphs amod oscil 1, ibasfreq*3.47, gisine arm = a1*amod kmix expseg 0.001, 0.01, rnd(1), rnd(3)+0.3, 0.001 a1 ntrpol a1, arm, kmix a1 pareq a1/10, 400, 15, .707 a1 tone a1, 500 kpanrte jspline 5, 0.05, 0.1 kpandep jspline 0.9, 0.2, 0.4 kpan oscil kpandep, kpanrte, gisine a1,a2 pan2 a1, kpan a1 delay a1, rnd(0.1) a2 delay a2, rnd(0.1) kenv linsegr 1, 1, 0 a1 = a1*kenv a2 = a2*kenv outs a1, a2 gasendL = gasendL+a1/5 gasendR = gasendR+a2/5 endin instr reverb aL, aR reverbsc gasendL, gasendR, 0.9, 10000 outs aL, aR clear gasendL, gasendR endin </CsInstruments> <CsScore> f 0 3600 i "trigger_notes" 0 3600 i "reverb" 0 3600 e </CsScore> </CsoundSynthesizer> csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/CsoundHaiku4/IV.csd000066400000000000000000000037721321653344700261450ustar00rootroot00000000000000Csound Haiku - IV Iain McCurdy, 2011. -odac -dm0 -+rtmidi=null -+rtaudio=null -+msg_color=0 sr = 44100 ksmps = 32 nchnls = 2 0dbfs = 1 gisine ftgen 0, 0, 4096, 10, 1 gioctfn ftgen 0, 0, 4096, -19, 1, 0.5, 270, 0.5 gasendL init 0 gasendR init 0 ginotes ftgen 0, 0, -100, -17, 0, 8.00, 10, 8.03, 15, 8.04, 25, 8.05, 50, 8.07, 60, 8.08, 73, 8.09, 82, 8.11 seed 0 ; alwayson "trigger_notes" ; alwayson "reverb" instr trigger_notes krate rspline 0.04, 0.15, 0.05, 0.1 ktrig metro krate gktrans init 0 gktrans trandom ktrig,-1, 1 gktrans = semitone(gktrans) idur = 15 schedkwhen ktrig, 0, 0, "hboscil_note", rnd(2), idur schedkwhen ktrig, 0, 0, "hboscil_note", rnd(2), idur schedkwhen ktrig, 0, 0, "hboscil_note", rnd(2), idur schedkwhen ktrig, 0, 0, "hboscil_note", rnd(2), idur endin instr hboscil_note ipch table int(rnd(100)),ginotes icps = cpspch(ipch)*i(gktrans)*semitone(rnd(0.5)-0.25) kamp expseg 0.001,0.02,0.2,p3-0.01,0.001 ktonemoddep jspline 0.01,0.05,0.2 ktonemodrte jspline 6,0.1,0.2 ktone oscil ktonemoddep,ktonemodrte,gisine kbrite rspline -2,3,0.0002,3 ibasfreq init icps ioctcnt init 2 iphs init 0 a1 hsboscil kamp, ktone, kbrite, ibasfreq, gisine, gioctfn, ioctcnt, iphs amod oscil 1, ibasfreq*3.47, gisine arm = a1*amod kmix expseg 0.001, 0.01, rnd(1), rnd(3)+0.3, 0.001 a1 ntrpol a1, arm, kmix a1 pareq a1/10, 400, 15, .707 a1 tone a1, 500 kpanrte jspline 5, 0.05, 0.1 kpandep jspline 0.9, 0.2, 0.4 kpan oscil kpandep, kpanrte, gisine a1,a2 pan2 a1, kpan a1 delay a1, rnd(0.1) a2 delay a2, rnd(0.1) kenv linsegr 1, 1, 0 a1 = a1*kenv a2 = a2*kenv outs a1, a2 gasendL = gasendL+a1/5 gasendR = gasendR+a2/5 endin instr reverb aL, aR reverbsc gasendL, gasendR, 0.9, 10000 outs aL, aR clear gasendL, gasendR endin f 0 3600 i "trigger_notes" 0 3600 i "reverb" 0 3600 e csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/Harmonizer/000077500000000000000000000000001321653344700247405ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/Harmonizer/HarmonizerWindowController.h000066400000000000000000000017271321653344700324720ustar00rootroot00000000000000/* HarmonizerWindowController.h: Copyright (C) 2014 Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import #import "BaseCsoundWindowController.h" @interface HarmonizerWindowController : BaseCsoundWindowController @end csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/Harmonizer/HarmonizerWindowController.m000066400000000000000000000037061321653344700324760ustar00rootroot00000000000000/* HarmonizerWindowController.m: Copyright (C) 2014 Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "HarmonizerWindowController.h" @interface HarmonizerWindowController () @property (strong) IBOutlet NSButton *startStopButton; @property (strong) IBOutlet NSSlider *harmonyPitchSlider; @property (strong) IBOutlet NSSlider *gainSlider; @end @implementation HarmonizerWindowController - (IBAction)toggleStartStop:(id)sender { if([self.startStopButton.title isEqualToString:@"Start"]) { NSString *csdFile = [[NSBundle mainBundle] pathForResource:@"harmonizer" ofType:@"csd"]; [self.csound addListener:self]; CsoundUI *csoundUI = [[CsoundUI alloc] initWithCsoundObj:self.csound]; [csoundUI addSlider:self.harmonyPitchSlider forChannelName:@"slider"]; [csoundUI addSlider:self.gainSlider forChannelName:@"gain"]; [self.csound play:csdFile]; } else { [self.csound stop]; } } #pragma mark CsoundObjListener -(void)csoundObjStarted:(CsoundObj *)csoundObj { self.startStopButton.title = @"Stop"; } -(void)csoundObjCompleted:(CsoundObj *)csoundObj { self.startStopButton.title = @"Start"; } @end csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/Harmonizer/HarmonizerWindowController.xib000066400000000000000000000134241321653344700330220ustar00rootroot00000000000000 csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/Harmonizer/harmonizer.csd000066400000000000000000000007331321653344700276140ustar00rootroot00000000000000 -o dac -+rtaudio=null -dm0 -i adc nchnls=2 0dbfs=1 ksmps=64 sr = 44100 instr 3 asig,asig1 ins ksl chnget "slider" kgain chnget "gain" fsig1 pvsanal asig,2048,256,2048,1 fsig2 pvscale fsig1,0.75+ksl,1 fsig3 pvscale fsig1,(0.75+ksl)*1.25,1 fsig4 pvsmix fsig2, fsig3 a1 pvsynth fsig4 a1 = a1 * kgain outs a1, a1 endin f1 0 16384 10 1 i3 0.1 10000 csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/Images.xcassets/000077500000000000000000000000001321653344700256635ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/Images.xcassets/AppIcon.appiconset/000077500000000000000000000000001321653344700313605ustar00rootroot00000000000000Contents.json000066400000000000000000000016071321653344700337750ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/Images.xcassets/AppIcon.appiconset{ "images" : [ { "idiom" : "mac", "size" : "16x16", "scale" : "1x" }, { "idiom" : "mac", "size" : "16x16", "scale" : "2x" }, { "idiom" : "mac", "size" : "32x32", "scale" : "1x" }, { "idiom" : "mac", "size" : "32x32", "scale" : "2x" }, { "idiom" : "mac", "size" : "128x128", "scale" : "1x" }, { "idiom" : "mac", "size" : "128x128", "scale" : "2x" }, { "idiom" : "mac", "size" : "256x256", "scale" : "1x" }, { "idiom" : "mac", "size" : "256x256", "scale" : "2x" }, { "idiom" : "mac", "size" : "512x512", "scale" : "1x" }, { "idiom" : "mac", "size" : "512x512", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } }csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/InstrumentEditor/000077500000000000000000000000001321653344700261415ustar00rootroot00000000000000InstrumentEditorWindowController.h000066400000000000000000000017111321653344700350060ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/InstrumentEditor/* InstrumentEditorWindowController.h: Copyright (C) 2014 Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "BaseCsoundWindowController.h" @interface InstrumentEditorWindowController : BaseCsoundWindowController @end InstrumentEditorWindowController.m000066400000000000000000000030031321653344700350070ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/InstrumentEditor/* InstrumentEditorWindowController.m: Copyright (C) 2014 Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "InstrumentEditorWindowController.h" @interface InstrumentEditorWindowController () @property (strong) IBOutlet NSTextView *orchestraTextView; @end @implementation InstrumentEditorWindowController - (void)windowDidLoad { [super windowDidLoad]; NSString *csdFile = [[NSBundle mainBundle] pathForResource:@"instrumentEditor" ofType:@"csd"]; NSLog(@"FILE PATH: %@", csdFile); [self.csound stop]; self.csound = [[CsoundObj alloc] init]; [self.csound play:csdFile]; } - (IBAction)trigger:(id)sender { [self.csound updateOrchestra:self.orchestraTextView.string]; NSString *score = @"i1 0 1"; [self.csound sendScore:score]; } @end InstrumentEditorWindowController.xib000066400000000000000000000153151321653344700353460ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/InstrumentEditor instr 1 a1 oscili 0.5, 440 outs a1,a1 endin csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/InstrumentEditor/instrumentEditor.csd000066400000000000000000000003471321653344700322170ustar00rootroot00000000000000 -o dac -+rtaudio=null -dm0 nchnls=2 0dbfs=1 ksmps=64 sr = 44100 instr 1 a1 oscili 0.5, 440 outs a1,a1 endin csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/RecordTest/000077500000000000000000000000001321653344700247005ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/RecordTest/RecordTestWindowController.h000066400000000000000000000003751321653344700323700ustar00rootroot00000000000000// // RecordTestWindowController.h // Csound OSX Examples // // Created by Aurelius Prochazka on 7/27/14. // // #import #import "BaseCsoundWindowController.h" @interface RecordTestWindowController : BaseCsoundWindowController @end csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/RecordTest/RecordTestWindowController.m000066400000000000000000000056641321653344700324030ustar00rootroot00000000000000// // RecordTestWindowController.m // Csound OSX Examples // // Created by Aurelius Prochazka on 7/27/14. // // #import "RecordTestWindowController.h" #import @interface RecordTestWindowController () @property (strong) IBOutlet NSButton *recordButton; @property (strong) IBOutlet NSButton *playButton; @property (strong) IBOutlet NSSlider *gainSlider; @property (strong) IBOutlet NSLevelIndicator *audioLevelIndicator; @property (strong) IBOutlet NSTextField *gainLabel; @property (nonatomic, strong) AVAudioPlayer *audioPlayer; @end @implementation RecordTestWindowController - (void)windowDidLoad { [super windowDidLoad]; // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. CsoundUI *csoundUI = [[CsoundUI alloc] initWithCsoundObj:self.csound]; [csoundUI addSlider:self.gainSlider forChannelName:@"gain"]; self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[self recordingURL] error:nil]; [self.audioPlayer setDelegate:self]; } -(IBAction) recordOrStop:(id)sender { NSString *csdFile = [[NSBundle mainBundle] pathForResource:@"recordTest" ofType:@"csd"]; if ([self.recordButton.title isEqualToString:@"Record"]) { [self.csound record:csdFile toURL:[self recordingURL]]; self.recordButton.title = @"Stop"; } else { [self.csound stopRecording]; [self.csound stop]; self.recordButton.title = @"Record"; } } - (IBAction)changeGain:(id)sender { [self.gainLabel setStringValue:[NSString stringWithFormat:@"%.2f", self.gainSlider.floatValue]]; } - (IBAction)playOrStop:(id)sender { if ([self.playButton.title isEqualToString:@"Play"]) { self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[self recordingURL] error:nil]; [self.audioPlayer setDelegate:self]; [self.audioPlayer setCurrentTime:0]; [self.audioPlayer play]; self.playButton.title = @"Stop"; } else { [self.audioPlayer stop]; self.playButton.title = @"Play"; } } - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { [self.audioPlayer setCurrentTime:0]; self.playButton.title = @"Play"; } - (NSURL *)recordingURL { NSURL *localDocDirURL = nil; if (localDocDirURL == nil) { NSString *docDirPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; localDocDirURL = [NSURL fileURLWithPath:docDirPath]; } return [localDocDirURL URLByAppendingPathComponent:@"recording.wav"]; } #pragma mark CsoundObjListener -(void)csoundObjStarted:(CsoundObj *)csoundObj { // [self.csound recordToURL:[self recordingURL]]; } -(void)csoundObjCompleted:(CsoundObj *)csoundObj { [self close]; } @end csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/RecordTest/RecordTestWindowController.xib000066400000000000000000000146111321653344700327210ustar00rootroot00000000000000 csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/RecordTest/recordTest.csd000066400000000000000000000005701321653344700275130ustar00rootroot00000000000000 -o dac -+rtmidi=null -+rtaudio=null -d -+msg_color=0 -M0 -m0 -i adc nchnls=2 0dbfs=1 ksmps=64 sr = 44100 instr 1 kgain chnget "gain" asig1,asig2 ins chnset asig1, "meter" asig1 = asig1 * kgain asig2 = asig2 * kgain outs asig1, asig2 endin i1 0 360000 csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/SimpleTest1/000077500000000000000000000000001321653344700247745ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/SimpleTest1/SimpleTest1WindowController.h000066400000000000000000000017261321653344700325610ustar00rootroot00000000000000/* SimpleTest1WindowController.h: Copyright (C) 2014 Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import #import "BaseCsoundWindowController.h" @interface SimpleTest1WindowController : BaseCsoundWindowController @end csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/SimpleTest1/SimpleTest1WindowController.m000066400000000000000000000036211321653344700325620ustar00rootroot00000000000000/* SimpleTest1WindowController.m: Copyright (C) 2014 Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "SimpleTest1WindowController.h" @interface SimpleTest1WindowController() @property (strong) IBOutlet NSButton *toggleOnOffButton; @property (strong) IBOutlet NSSlider *slider; @end @implementation SimpleTest1WindowController - (IBAction)toggleOnOff:(id)sender { if([self.toggleOnOffButton.title isEqualToString:@"Start"]) { NSString *csdFile = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"csd"]; [self.csound addListener:self]; CsoundUI *csoundUI = [[CsoundUI alloc] initWithCsoundObj:self.csound]; [csoundUI addSlider:_slider forChannelName:@"slider"]; [self.csound play:csdFile]; } else { [self.csound stop]; } } #pragma mark CsoundObjListener -(void)csoundObjStarted:(CsoundObj *)csoundObj { NSLog(@"Csound started"); self.toggleOnOffButton.title = @"Stop"; [self.toggleOnOffButton setNeedsDisplay]; } -(void)csoundObjCompleted:(CsoundObj *)csoundObj { NSLog(@"Csound finished"); self.toggleOnOffButton.title = @"Start"; } @end SimpleTest1WindowController.xib000066400000000000000000000064461321653344700330410ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/SimpleTest1 csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/SimpleTest1/test.csd000066400000000000000000000006561321653344700264550ustar00rootroot00000000000000 -o dac -+rtaudio=null -dm0 nchnls=2 0dbfs=1 ksmps=64 sr = 44100 instr 1 isl chnget "slider" ksl chnget "slider" ksl port ksl, 0.01, isl a2 expsegr 0.001,0.01,p4,p3-0.01, 0.001, 0.1, 0.001 a1 oscili a2, p5*(1+ksl), 1 outs a1,a1 endin f1 0 16384 10 1 { 10 CNT i1 [$CNT*0.2] 0.5 0.5 [440*(2^[$CNT/12])] } csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/SimpleTest2/000077500000000000000000000000001321653344700247755ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/SimpleTest2/test2.csd000066400000000000000000000014371321653344700265360ustar00rootroot00000000000000 -o dac -+rtaudio=null -d -+msg_color=0 -m0 nchnls=2 0dbfs=1 ksmps=64 sr = 44100 seed 0 instr 1 inoterate chnget "noteRate" inotedur chnget "duration" ;print inoterate ;print inotedur event_i "i", 1, inoterate, 1 event_i "i", 2, 0, inotedur turnoff endin instr 2 iattack chnget "attack" idecay chnget "decay" isustain chnget "sustain" irelease chnget "release" ;ipchMul rnd31 .5, -0.5 ;ipchMul = ipchMul + .5 ;ipch = 100 + (1000 * ipchMul) ipch = 100 + rnd(1000) ;print iattack ;print idecay ;print isustain ;print irelease a2 linsegr 0, iattack, 1, idecay, isustain, irelease, 0 a1 oscili a2 * .3, ipch, 1 outs a1,a1 endin f1 0 16384 10 1 i1 0 1 f 0 3600 csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/SimpleTest2WindowController.h000066400000000000000000000017271321653344700304110ustar00rootroot00000000000000/* SimpleTest2WindowController.h: Copyright (C) 2014 Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import #import "BaseCsoundWindowController.h" @interface SimpleTest2WindowController : BaseCsoundWindowController @end csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/SimpleTest2WindowController.m000066400000000000000000000047071321653344700304170ustar00rootroot00000000000000/* SimpleTest2WindowController.m: Copyright (C) 2014 Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "SimpleTest2WindowController.h" @interface SimpleTest2WindowController() @property (strong) IBOutlet NSButton *startStopButton; @property (strong) IBOutlet NSSlider *rateSlider; @property (strong) IBOutlet NSSlider *durationSlider; @property (strong) IBOutlet NSSlider *attackSlider; @property (strong) IBOutlet NSSlider *decaySlider; @property (strong) IBOutlet NSSlider *sustainSlider; @property (strong) IBOutlet NSSlider *releaseSlider; @end @implementation SimpleTest2WindowController - (IBAction)toggleOnOff:(id)sender { if([self.startStopButton.title isEqualToString:@"Start"]) { NSString *csdFile = [[NSBundle mainBundle] pathForResource:@"test2" ofType:@"csd"]; [self.csound addListener:self]; CsoundUI *csoundUI = [[CsoundUI alloc] initWithCsoundObj:self.csound]; [csoundUI addSlider:_rateSlider forChannelName:@"noteRate"]; [csoundUI addSlider:_durationSlider forChannelName:@"duration"]; [csoundUI addSlider:_attackSlider forChannelName:@"attack"]; [csoundUI addSlider:_decaySlider forChannelName:@"decay"]; [csoundUI addSlider:_sustainSlider forChannelName:@"sustain"]; [csoundUI addSlider:_releaseSlider forChannelName:@"release"]; [self.csound play:csdFile]; } else { NSLog(@"try to stop csound"); [self.csound stop]; } } #pragma mark CsoundObjListener -(void)csoundObjStarted:(CsoundObj *)csoundObj { self.startStopButton.title = @"Stop"; } -(void)csoundObjCompleted:(CsoundObj *)csoundObj { self.startStopButton.title = @"Start"; } @end csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/SimpleTest2WindowController.xib000066400000000000000000000220741321653344700307420ustar00rootroot00000000000000 csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/TrappedGenerator/000077500000000000000000000000001321653344700260705ustar00rootroot00000000000000TrappedGeneratorWindowController.h000066400000000000000000000021401321653344700346610ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/TrappedGenerator/* TrappedGeneratorWindowController.h: Copyright (C) 2014 Steven Yi, Aurelius Prochazka This file is part of Csound iOS Examples. The Csound for iOS Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import #import "BaseCsoundWindowController.h" @interface TrappedGeneratorWindowController : BaseCsoundWindowController - (IBAction)generateTrappedToDocumentsFolder:(id)sender; @property (strong) IBOutlet NSTextField *statusTextField; @end TrappedGeneratorWindowController.m000066400000000000000000000035411321653344700346740ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/TrappedGenerator/* TrappedGeneratorWindowController.m: Copyright (C) 2014 Steven Yi, Aurelius Prochazka This file is part of Csound iOS Examples. The Csound for iOS Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "TrappedGeneratorWindowController.h" @interface TrappedGeneratorWindowController() @end @implementation TrappedGeneratorWindowController - (IBAction)generateTrappedToDocumentsFolder:(id)sender { NSString *csdPath = [[NSBundle mainBundle] pathForResource:@"trapped" ofType:@"csd"]; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *localFilePath = [documentsDirectory stringByAppendingPathComponent:@"trapped.wav"]; NSLog(@"OUTPUT: %@", localFilePath); [self.csound stop]; self.csound = [[CsoundObj alloc] init]; [self.csound addListener:self]; [self.csound record:csdPath toFile:localFilePath]; } #pragma mark CsoundObjListener - (void)csoundObjCompleted:(CsoundObj *)csoundObj { self.statusTextField.textColor = [NSColor blueColor]; self.statusTextField.stringValue = @"DONE! Check your Documents Folder."; } @end TrappedGeneratorWindowController.xib000066400000000000000000000113431321653344700352210ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/TrappedGenerator This will generate Dr. Richard Boulanger's "Trapped in Convert" to the Documents folder of this application. This example demonstrates how to use Csound as a batch renderer. csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/TrappedGenerator/trapped.csd000066400000000000000000001060561321653344700302320ustar00rootroot00000000000000 -+rtmidi=null -+rtaudio=null -Wd -+msg_color=0 ;============================================================================; ;============================================================================; ;============================================================================; ; == TRAPPED IN CONVERT == ; ; Richard Boulanger ; ;============================================================================; ;============================================================================; ; ORCHESTRA ; ;============================================================================; ;============================================================================; ;============================================================================; ; written July 1979 in music11 ; ; M.I.T. Experimental Music Studio ; ; revised June 1986 in Csound ; ; M.I.T. Media Lab ; ; revised July 1996 in SHARCsound ; ; Analog Devices Inc. ; ;============================================================================; ;============================================================================; ;=================================== HEADER =================================; ;============================================================================; sr = 48000 ksmps = 1000 nchnls = 2 ;============================================================================; ;=============================== INITIALIZATION =============================; ;============================================================================; garvb init 0 gadel init 0 ;============================================================================; ;================================== INSTRUMENTS =============================; ;============================================================================; ;==================================== IVORY =================================; ;============================================================================; instr 1 ; p6 = amp ifreq = cpspch(p5) ; p7 = vib rate ; p8 = glis. del time (default < 1) aglis expseg 1, p8, 1, p3 - p8, p9 ; p9 = freq drop factor k1 line 0, p3, 5 k2 oscil k1, p7, 1 k3 linseg 0, p3 * .7, p6, p3 * .3, 0 a1 oscil k3, (ifreq + k2) * aglis, 1 k4 linseg 0, p3 * .6, 6, p3 * .4, 0 k5 oscil k4, p7 * .9, 1, 1.4 k6 linseg 0, p3 * .9, p6, p3 * .1, 0 a3 oscil k6, ((ifreq + .009) + k5) * aglis, 9, .2 k7 linseg 9, p3 * .7, 1, p3 * .3, 1 k8 oscil k7, p7 * 1.2, 1, .7 k9 linen p6, p3 * .5, p3, p3 * .333 a5 oscil k9, ((ifreq + .007) + k8) * aglis, 10, .3 k10 expseg 1, p3 * .99, 3.1, p3 * .01, 3.1 k11 oscil k10, p7 * .97, 1, .6 k12 expseg .001, p3 * .8, p6, p3 * .2, .001 a7 oscil k12,((ifreq + .005) + k11) * aglis, 11, .5 k13 expseg 1, p3 * .4, 3, p3 * .6, .02 k14 oscil k13, p7 * .99, 1, .4 k15 expseg .001, p3 *.5, p6, p3 *.1, p6 *.6, p3 *.2, p6 *.97, p3 *.2, .001 a9 oscil k15, ((ifreq + .003) + k14) * aglis, 12, .8 k16 expseg 4, p3 * .91, 1, p3 * .09, 1 k17 oscil k16, p7 * 1.4, 1, .2 k18 expseg .001, p3 *.6, p6, p3 *.2, p6 *.8, p3 *.1, p6 *.98, p3 *.1, .001 a11 oscil k18, ((ifreq + .001) + k17) * aglis, 13, 1.3 outs a1 + a3 + a5, a7 + a9 + a11 endin ;============================================================================; ;==================================== BLUE ==================================; ;============================================================================; instr 2 ; p6 = amp ifreq = cpspch(p5) ; p7 = reverb send factor ; p8 = lfo freq k1 randi 1, 30 ; p9 = number of harmonic k2 linseg 0, p3 * .5, 1, p3 * .5, 0 ; p10 = sweep rate k3 linseg .005, p3 * .71, .015, p3 * .29, .01 k4 oscil k2, p8, 1,.2 k5 = k4 + 2 ksweep linseg p9, p3 * p10, 1, p3 * (p3 - (p3 * p10)), 1 kenv expseg .001, p3 * .01, p6, p3 * .99, .001 asig gbuzz kenv, ifreq + k3, k5, ksweep, k1, 15 outs asig, asig garvb = garvb + (asig * p7) endin ;============================================================================; ;================================== VIOLET ==================================; ;============================================================================; instr 3 ; p6 = amp ifreq = cpspch(p5) ; p7 = reverb send factor ; p8 = rand freq k3 expseg 1, p3 * .5, 30 ,p3 * .5, 2 k4 expseg 10, p3 *.7, p8, p3 *.3, 6 k8 linen p6, p3 * .333, p3, p3 * .333 k13 line 0, p3, -1 k14 randh k3, k4, .5 a1 oscil k8, ifreq + (p5 * .05) + k14 + k13, 1, .1 k1 expseg 1, p3 * .8, 6, p3 *.2, 1 k6 linseg .4, p3 * .9, p8 * .96, p3 * .1, 0 k7 linseg 8, p3 * .2, 10, p3 * .76, 2 kenv2 expseg .001, p3 * .4, p6 * .99, p3 * .6, .0001 k15 randh k6, k7 a2 buzz kenv2, ifreq + (p5 * .009) + k15 + k13, k1, 1, .2 kenv1 linen p6, p3 * .25, p3, p3 * .4 k16 randh k4 * 1.4, k7 * 2.1, .2 a3 oscil kenv1, ifreq + (p5 * .1) + k16 + k13, 16, .3 amix = a1 + a2 + a3 outs a1 + a3, a2 + a3 garvb = garvb + (amix * p7) endin ;============================================================================; ;==================================== BLACK =================================; ;============================================================================; instr 4 ; p6 = amp ifreq = cpspch(p5) ; p7 = filtersweep strtfreq ; p8 = filtersweep endfreq k1 expon p7, p3, p8 ; p9 = bandwidth anoise rand 8000 ; p10 = reverb send factor a1 reson anoise, k1, k1 / p9, 1 k2 oscil .6, 11.3, 1, .1 k3 expseg .001,p3 * .001, p6, p3 * .999, .001 a2 oscil k3, ifreq + k2, 15 outs (a1 * .8) + a2, (a1 * .6) + (a2 * .7) garvb = garvb + (a2 * p10) endin ;============================================================================; ;==================================== GREEN =================================; ;============================================================================; instr 5 ; p6 = amp ifreq = cpspch(p5) ; p7 = reverb send factor ; p8 = pan direction k1 line p9, p3, 1 ; ... (1.0 = L -> R, 0.1 = R -> L) k2 line 1, p3, p10 ; p9 = carrier freq k4 expon 2, p3, p12 ; p10 = modulator freq k5 linseg 0, p3 * .8, 8, p3 * .2, 8 ; p11 = modulation index k7 randh p11, k4 ; p12 = rand freq k6 oscil k4, k5, 1, .3 kenv1 linen p6, .03, p3, .2 a1 foscil kenv1, ifreq + k6, k1, k2, k7, 1 kenv2 linen p6, .1, p3, .1 a2 oscil kenv2, ifreq * 1.001, 1 amix = a1 + a2 kpan linseg int(p8), p3 * .7, frac(p8), p3 * .3, int(p8) outs amix * kpan, amix * (1 - kpan) garvb = garvb + (amix * p7) endin ;============================================================================; ;================================== COPPER ==================================; ;============================================================================; instr 6 ; p5 = FilterSweep StartFreq ifuncl = 8 ; p6 = FilterSweep EndFreq ; p7 = bandwidth k1 phasor p4 ; p8 = reverb send factor k2 table k1 * ifuncl, 19 ; p9 = amp anoise rand 8000 k3 expon p5, p3, p6 a1 reson anoise, k3 * k2, k3 / p7, 1 kenv linen p9, .01, p3, .05 asig = a1 * kenv outs asig, asig garvb = garvb + (asig * p8) endin ;============================================================================; ;==================================== PEWTER ================================; ;============================================================================; instr 7 ; p4 = amp ifuncl = 512 ; p5 = freq ifreq = cpspch(p5) ; p6 = begin phase point ; p7 = end phase point a1 oscil 1, ifreq, p10 ; p8 = ctrl osc amp (.1 -> 1) k1 linseg p6, p3 * .5, p7, p3 * .5, p6 ; p9 = ctrl osc func a3 oscili p8, ifreq + k1, p9 ; p10 = main osc func (f2 or f3) a4 phasor ifreq ; ...(function length must be 512!) a5 table (a4 + a3) * ifuncl, p10 ; p11 = reverb send factor kenv linen p4, p3 * .4, p3, p3 * .5 asig = kenv * ((a1 + a5) * .2) outs asig, asig garvb = garvb + (asig * p11) endin ;============================================================================; ;==================================== RED ===================================; ;============================================================================; instr 8 ; p4 = amp ifuncl = 16 ; p5 = FilterSweep StartFreq ; p6 = FilterSweep EndFreq k1 expon p5, p3, p6 ; p7 = bandwidth k2 line p8, p3, p8 * .93 ; p8 = cps of rand1 k3 phasor k2 ; p9 = cps of rand2 k4 table k3 * ifuncl, 20 ; p10 = reverb send factor anoise rand 8000 aflt1 reson anoise, k1, 20 + (k4 * k1 / p7), 1 k5 linseg p6 * .9, p3 * .8, p5 * 1.4, p3 * .2, p5 * 1.4 k6 expon p9 * .97, p3, p9 k7 phasor k6 k8 tablei k7 * ifuncl, 21 aflt2 reson anoise, k5, 30 + (k8 * k5 / p7 * .9), 1 abal oscil 1000, 1000, 1 a3 balance aflt1, abal a5 balance aflt2, abal k11 linen p4, .15, p3, .5 a3 = a3 * k11 a5 = a5 * k11 k9 randh 1, k2 aleft = ((a3 * k9) * .7) + ((a5 * k9) * .3) k10 randh 1, k6 aright = ((a3 * k10) * .3)+((a5 * k10) * .7) outs aleft, aright garvb = garvb + (a3 * p10) endin ;============================================================================; ;==================================== SAND ==================================; ;============================================================================; instr 9 ; p4 = delay send factor ifreq = cpspch(p5) ; p5 = freq ; p6 = amp k2 randh p8, p9, .1 ; p7 = reverb send factor k3 randh p8 * .98, p9 * .91, .2 ; p8 = rand amp k4 randh p8 * 1.2, p9 * .96, .3 ; p9 = rand freq k5 randh p8 * .9, p9 * 1.3 kenv linen p6, p3 *.1, p3, p3 * .8 a1 oscil kenv, ifreq + k2, 1, .2 a2 oscil kenv * .91, (ifreq + .004) + k3, 2, .3 a3 oscil kenv * .85, (ifreq + .006) + k4, 3, .5 a4 oscil kenv * .95, (ifreq + .009) + k5, 4, .8 amix = a1 + a2 + a3 + a4 outs a1 + a3, a2 + a4 garvb = garvb + (amix * p7) gadel = gadel + (amix * p4) endin ;============================================================================; ;==================================== TAUPE =================================; ;============================================================================; instr 10 ifreq = cpspch(p5) ; p5 = freq ; p6 = amp k2 randh p8, p9, .1 ; p7 = reverb send factor k3 randh p8 * .98, p9 * .91, .2 ; p8 = rand amp k4 randh p8 * 1.2, p9 * .96, .3 ; p9 = rand freq k5 randh p8 * .9, p9 * 1.3 kenv linen p6, p3 *.1, p3, p3 * .8 a1 oscil kenv, ifreq + k2, 1, .2 a2 oscil kenv * .91, (ifreq + .004) + k3, 2, .3 a3 oscil kenv * .85, (ifreq + .006) + k4, 3, .5 a4 oscil kenv * .95, (ifreq + .009) + k5, 4, .8 amix = a1 + a2 + a3 + a4 outs a1 + a3, a2 + a4 garvb = garvb + (amix * p7) endin ;============================================================================; ;==================================== RUST ==================================; ;============================================================================; instr 11 ; p4 = delay send factor ifreq = cpspch(p5) ; p5 = freq ; p6 = amp k1 expseg 1, p3 * .5, 40, p3 * .5, 2 ; p7 = reverb send factor k2 expseg 10, p3 * .72, 35, p3 * .28, 6 k3 linen p6, p3* .333, p3, p3 * .333 k4 randh k1, k2, .5 a4 oscil k3, ifreq + (p5 * .05) + k4, 1, .1 k5 linseg .4, p3 * .9, 26, p3 * .1, 0 k6 linseg 8, p3 * .24, 20, p3 * .76, 2 k7 linen p6, p3 * .5, p3, p3 * .46 k8 randh k5, k6, .4 a3 oscil k7, ifreq + (p5 * .03) + k8, 14, .3 k9 expseg 1, p3 * .7, 50, p3 * .3, 2 k10 expseg 10, p3 * .3, 45, p3 * .7, 6 k11 linen p6, p3 * .25, p3, p3 * .25 k12 randh k9, k10, .5 a2 oscil k11, ifreq + (p5 * .02) + k12, 1, .1 k13 linseg .4, p3 * .6, 46, p3 * .4, 0 k14 linseg 18, p3 * .1, 50, p3 * .9, 2 k15 linen p6, p3 * .2, p3, p3 * .3 k16 randh k13, k14, .8 a1 oscil k15, ifreq + (p5 * .01) + k16, 14, .3 amix = a1 + a2 + a3 + a4 outs a1 + a3, a2 + a4 garvb = garvb + (amix * p7) gadel = gadel + (amix * p4) endin ;============================================================================; ;==================================== TEAL ==================================; ;============================================================================; instr 12 ; p6 = amp ifreq = octpch(p5) ; p7 = FilterSweep StartFreq ifuncl = 8 ; p8 = FilterSweep PeakFreq ; p9 = bandwdth k1 linseg 0, p3 * .8, 9, p3 * .2, 1 ; p10 = reverb send factor k2 phasor k1 k3 table k2 * ifuncl, 22 k4 expseg p7, p3 * .7, p8, p3 * .3, p7 * .9 anoise rand 8000 aflt reson anoise, k4, k4 / p9, 1 kenv1 expseg .001, p3 *.1, p6, p3 *.1, p6 *.5, p3 *.3, p6 *.8, p3 *.5,.001 a3 oscil kenv1, cpsoct(ifreq + k3) + aflt * .8, 1 outs a3,(a3 * .98) + (aflt * .3) garvb = garvb + (anoise * p10) endin ;============================================================================; ;==================================== FOAM ==================================; ;============================================================================; instr 13 ; p6 = amp ifreq = octpch(p5) ; p7 = vibrato rate ; p8 = glis. factor k1 line 0, p3, p8 k2 oscil k1, p7, 1 k3 linseg 0, p3 * .7, p6, p3 * .3, 1 a1 oscil k3, cpsoct(ifreq + k2), 1 k4 linseg 0, p3 * .6, p8 * .995, p3 * .4, 0 k5 oscil k4, p7 * .9, 1, .1 k6 linseg 0, p3 * .9, p6, p3 * .1, 3 a2 oscil k6, cpsoct((ifreq + .009) + k5), 4, .2 k7 linseg p8 * .985, p3 * .7, 0, p3 * .3, 0 k8 oscil k7, p7 * 1.2, 1, .7 k9 linen p6, p3 * .5, p3, p3 * .333 a3 oscil k6, cpsoct((ifreq + .007) + k8), 5, .5 k10 expseg 1, p3 * .8, p8, p3 * .2, 4 k11 oscil k10, p7 * .97, 1, .6 k12 expseg .001, p3 * .99, p6 * .97, p3 * .01, p6 * .97 a4 oscil k12, cpsoct((ifreq + .005) + k11), 6, .8 k13 expseg .002, p3 * .91, p8 * .99, p3 * .09, p8 * .99 k14 oscil k13, p7 * .99, 1, .4 k15 expseg .001, p3 *.5, p6, p3 *.1, p6 *.6, p3 *.2, p6 *.97, p3 *.2, .001 a5 oscil k15, cpsoct((ifreq + .003) + k14), 7, .9 k16 expseg p8 * .98, p3 * .81, .003, p3 * .19, .003 k17 oscil k16, p7 * 1.4, 1, .2 k18 expseg .001, p3 *.6, p6, p3 *.2, p6 *.8, p3 *.1, p6 *.98, p3 *.1, .001 a6 oscil k18, cpsoct((ifreq + .001) + k17), 8, .1 outs a1 + a3 + a5, a2 + a4 + a6 endin ;============================================================================; ;==================================== SMEAR =================================; ;============================================================================; instr 98 asig delay gadel, .08 outs asig, asig gadel = 0 endin ;============================================================================; ;==================================== SWIRL =================================; ;============================================================================; instr 99 ; p4 = panrate k1 oscil .5, p4, 1 k2 = .5 + k1 k3 = 1 - k2 asig reverb garvb, 2.1 outs asig * k2, (asig * k3) * (-1) garvb = 0 endin ;============================================================================; ;============================================================================; ;============================================================================; ;============================================================================; instr 100 ;k0,1,k2 cpumeter 0.3 ; printk2 k0 ; printk2 k1, 10 ; printk2 k2, 20 endin ;============================================================================; ;============================================================================; ; == TRAPPED IN CONVERT == ; ; Richard Boulanger ; ;============================================================================; ;============================================================================; ; SCORE ; ;============================================================================; ;================================= PARAMETERS ===============================; ;============================================================================; ; i1: p6=amp,p7=vibrat,p8=glisdeltime (default < 1),p9=frqdrop ; ; i2: p6=amp,p7=rvbsnd,p8=lfofrq,p9=num of harmonics,p10=sweeprate ; ; i3: p6=amp,p7=rvbsnd,p8=rndfrq ; ; i4: p6=amp,p7=fltrswp:strtval,p8=fltrswp:endval,p9=bdwth,p10=rvbsnd ; ; i5: p6=amp,p7=rvbatn,p8=pan:1.0,p9=carfrq,p10=modfrq,p11=modndx,p12=rndfrq; ; i6: p5=swpfrq:strt,p6=swpfrq:end,p7=bndwth,p8=rvbsnd,p9=amp ; ; i7: p4=amp,p5=frq,p6=strtphse,p7=endphse,p8=ctrlamp(.1-1),p9=ctrlfnc ; ; p10=audfnc(f2,f3,f14,p11=rvbsnd ; ; i8: p4=amp,p5=swpstrt,p6=swpend,p7=bndwt,p8=rnd1:cps,p9=rnd2:cps,p10=rvbsnd; ; i9: p4=delsnd,p5=frq,p6=amp,p7=rvbsnd,p8=rndamp,p9=rndfrq ; ; i10: p4=0,p5=frq,p6=amp,p7=rvbsnd,p8=rndamp,p9=rndfrq ; ; i11: p4=delsnd,p5=frq,p6=amp,p7=rvbsnd ; ; i12: p6=amp,p7=swpstrt,p8=swppeak,p9=bndwth,p10=rvbsnd ; ; i13: p6=amp,p7=vibrat,p8=dropfrq ; ; i98: p2=strt,p3=dur ; ; i99: p4=pancps ; ;============================================================================; ;========================= FUNCTIONS ========================================; ;============================================================================; f1 0 8192 10 1 f2 0 512 10 10 8 0 6 0 4 0 1 f3 0 512 10 10 0 5 5 0 4 3 0 1 f4 0 2048 10 10 0 9 0 0 8 0 7 0 4 0 2 0 1 f5 0 2048 10 5 3 2 1 0 f6 0 2048 10 8 10 7 4 3 1 f7 0 2048 10 7 9 11 4 2 0 1 1 f8 0 2048 10 0 0 0 0 7 0 0 0 0 2 0 0 0 1 1 f9 0 2048 10 10 9 8 7 6 5 4 3 2 1 f10 0 2048 10 10 0 9 0 8 0 7 0 6 0 5 f11 0 2048 10 10 10 9 0 0 0 3 2 0 0 1 f12 0 2048 10 10 0 0 0 5 0 0 0 0 0 3 f13 0 2048 10 10 0 0 0 0 3 1 f14 0 512 9 1 3 0 3 1 0 9 .333 180 f15 0 8192 9 1 1 90 f16 0 2048 9 1 3 0 3 1 0 6 1 0 f17 0 9 5 .1 8 1 f18 0 17 5 .1 10 1 6 .4 f19 0 16 2 1 7 10 7 6 5 4 2 1 1 1 1 1 1 1 1 f20 0 16 -2 0 30 40 45 50 40 30 20 10 5 4 3 2 1 0 0 0 f21 0 16 -2 0 20 15 10 9 8 7 6 5 4 3 2 1 0 0 f22 0 9 -2 .001 .004 .007 .003 .002 .005 .009 .006 ;============================================================================; ;========================= SECTION I: 78 SECONDS ===========================; ;============================================================================; i1 0.0 24.12 0 11.057 200 0.001 17.8 0.99 i1 1.0 21.76 0 11.049 240 0.001 10.2 0.99 i1 3.6 17.13 0 11.082 390 0.001 11.3 0.99 i1 6.2 15.02 0 11.075 460 0.001 10.5 0.99 i1 8.4 13.85 0 11.069 680 0.001 13.8 0.99 i99 22.0 7.5 5 i2 22.0 4 0 9.029 600 0.6 23 10 0.52 i2 22.13 4 0 9.01 600 0.5 20 6 0.66 i1 26.5 5.6 0 12.019 500 4.0 5.8 0.98 i1 26.51 6.1 0 12.004 550 5.0 5.5 0.98 i1 26.52 5.4 0 12.026 600 5.2 5.6 0.98 i1 26.55 5 0 12.031 660 4.5 5.7 0.98 i99 31.3 0.7 22 i4 31.3 1 0 13.045 2200 6000 7000 30 0.5 i99 32.0 4 11 i2 32.0 4 0 14.107 900 0.4 19 13 0.21 i2 32.14 4 0 11.023 750 0.7 21 9 0.19 i2 32.19 4 0 11.029 589 0.97 20 10 0.22 i4 35.0 1 0 12.029 1000 4600 6500 33 0.6 i99 36.0 10 7 i3 36.0 7.6 0 13.087 800 0.8 57 i1 39.31 8.1 0 10.024 519 3.0 3.1 0.002 i1 39.32 8 0 10.031 520 5.1 3.7 0.001 i1 39.35 7.9 0 10.042 557 3.4 3.5 0.003 i1 39.37 7.86 0 10.050 547 4.2 3.3 0.004 i99 46.0 7.3 2 i5 46.0 0.9 0 4.09 3500 0.2 0.1 3 10 12 27 i5 49.2 1.1 0 3.07 4500 0.1 1.0 5 3 16 30 i99 53.3 9.6 5 i6 53.3 8.5 0.81 3000 17 10 0.6 1.6 i98 62.9 15.1 i99 62.9 15.1 3 i9 62.9 2.9 0.4 4.113 600 0.2 6.2 320 i9 62.93 2.85 0.43 4.115 640 0.23 6.1 300 i9 67.1 7.9 0.2 5.004 700 0.4 4.5 289 i9 67.14 7.78 0.17 5.007 700 0.43 4.4 280 ;s 80 i100 0 78 s ;============================================================================; ;========================= SECTION II: 49 SECONDS ===========================; ;============================================================================; i98 0 48.5 i99 0 4.5 1 i9 0 5 0.4 10.01 1200 0.2 28 39 i9 0 5 0.3 9.119 1200 0.4 29 37 i3 0.5 6.5 0 12.067 600 0.6 47 i99 4.5 2 7 i6 4.5 4.3 17 6000 9000 100 0.4 0.9 i99 6.5 9.9 0.7 i7 6.5 3.2 9999 5.023 0.2 0.7 0.6 2 3 0.12 i7 8 1.9 9800 5.039 0.01 0.9 1 3 2 0.23 i7 9 3.8 9900 10.001 0.99 0.1 0.3 3 2 0.12 i3 9.1 5.5 0 10.017 900 0.5 67 i7 9.2 2.5 9890 5.052 0.1 1.0 0.7 2 3 0.23 i8 11 4.6 4 20 8000 590 2 9.9 0.6 i8 15.5 3.1 3 50 4000 129 8 2.6 0.3 i8 16.2 4.3 2 10000 9000 200 12 17.9 1 i99 16.4 10.3 0.3 i7 16.4 3.5 8000 5.019 0.2 0.7 0.5 2 3 0.1 i7 19.3 6.4 8000 5.041 0.01 0.9 1 3 2 0.1 i9 20.2 4 0.4 9.021 1000 0.2 4 100 i9 21 4.2 0.4 9.099 1100 0.4 4 167 i9 21.1 8 0.4 9.043 1000 0.6 4 210 i9 21.25 5 0.4 9.062 1200 0.9 5 200 i99 26.7 5.3 11 i9 26.7 1.9 0.5 4.114 3100 0.1 5.9 300 i9 29.1 2.1 0.1 5.013 2900 0.2 4.2 390 i99 32 6.2 0.28 i9 32 9.1 0.34 5.051 2300 0.5 3.8 420 i9 32.1 9.0 0.4 5.0517 2500 0.4 4 430 i2 34.2 5 0 9.029 1900 0.3 23 10 0.42 i2 34.23 5 0 9.01 2100 0.2 20 6 0.29 i2 36 5 0 13.027 3500 0.5 27 9 0.38 i2 36.05 5 0 12.119 3399 0.1 21 3 0.30 i2 36.12 5 0 13.018 3709 0.4 17 12 0.33 i99 38.2 10.8 2 i2 38.2 7.3 0 8.062 5900 0.4 19 13 0.26 i2 38.4 7 0 7.077 4730 0.6 26 21 0.23 i4 38.9 3.1 0 10.001 2600 2000 3000 46 0.3 i4 39.7 2.3 0 9.0119 1200 1000 2000 50 0.2 i100 0 49 s ;============================================================================; ;========================= SECTION III: 56 SECONDS ==========================; ;============================================================================; i98 0 42 i99 0 42 0.0618 i9 0 7 0.6 11.031 1100 0.2 30 40 i9 0.1 7 0.2 11.042 1100 0.9 26 37 i9 0.3 6.2 0.9 11.049 1105 0.1 32 29 i9 0.6 5.8 0.4 11.021 1110 0.6 41 34 i11 3.7 8 0.2 5.02 2200 0.2 i13 7.0 4.5 0.4 11.064 1500 40.0 7 i9 9.3 9 0.8 7.098 1300 0.3 33 27 i9 9.8 7 0.2 7.087 1400 0.7 39 31 i2 10.9 4 0.2 8.113 5000 0.9 45 20 1 i11 12 5 0.2 4.101 3300 0.3 i2 12.9 5 0.2 9.108 5900 0.4 59 14 0.6 i8 15 4.7 2.5 8600 8900 900 13 11.1 0.7 i11 17.9 7 0.4 4.091 3000 0.1 i9 22 7 0.6 10.031 1000 0.2 30 40 i9 22.1 7 0.2 10.042 1000 0.9 26 37 i9 22.3 6.2 0.9 10.049 1005 0.1 32 29 i9 22.6 5.8 0.4 10.021 1010 0.6 41 34 i11 25.2 5.3 0.3 5.111 2500 0.2 i11 26.9 5.1 0.2 4.093 2330 0.1 i13 27.1 4 0.4 12.064 2000 40 7 i13 28.9 4 0.4 11.117 2000 30.0 5 i9 29.3 9 0.8 8.098 1000 0.3 33 27 i9 30.8 7 0.2 8.087 1200 0.7 39 31 i9 31.2 7.2 0.9 8.071 1400 0.9 29 40 i2 32.9 5 0.9 8.113 5000 0.8 45 20 1 i8 33.1 7 2 5000 6000 1000 17 15 0.3 i2 33.3 6 0.9 7.097 5100 0.5 51 18 0.3 i11 34 5 0.3 4.111 2000 0.5 i8 34.5 6 2 3000 100 500 8.3 9.8 0.1 i2 34.9 6 0.9 9.108 2900 0.4 59 14 0.4 i2 35 5 0.9 8.042 2800 0.6 39 20 0.3 i11 36.1 5 0.5 3.119 1200 0.4 i11 36.8 7 0.2 5.118 1800 0.4 i11 38 6 0.2 4.031 2000 0.2 i11 39 4 0.3 6.003 1300 0.1 i99 42 3.6 8.3 i4 42 1 9.6 13.061 3000 8000 20 10 0.9 i4 42 0.99 9.6 13.013 3110 6000 30 6 0.3 i4 42 1.01 9.6 12.119 2999 10000 25 15 0.7 i5 43 1.1 9.6 3.106 2500 0.4 1.0 8 3 17 34 i5 43.1 1 9.6 4.034 2500 0.2 0.1 2 7 19 29 i99 45.6 4.9 3.2 i5 45.6 3 3.2 4.022 2300 0.3 1.0 11 4 20 37 i5 46.1 2.4 3.2 3.049 2400 0.2 0.1 5 8 19 27 i99 50.5 5.5 8.3 i4 50.5 0.7 11 11.059 3000 7000 40 9 0.9 i4 50.5 0.7 11 10.038 3000 10000 20 20 0.7 i4 50.5 0.71 11 13.077 3000 9500 25 5 0.8 i4 50.52 0.64 11 12.016 3000 8500 18 14 0.5 i5 51 1.5 11 4.011 2000 0.1 1.0 3 11 13 28 i5 51 1.5 11 3.106 2000 0.4 0.1 7 5 15 34 i100 0 56 s ;============================================================================; ;========================= SECTION IV: 100 SECONDS =========================; ;============================================================================; ;========================= VARIABLE TEMPO ===================================; t 0 60 40 60 45 30 49 40 52 90 55 100 58 160 59 200 61 230 65 270 78 40 ;============================================================================; i99 0 1 2.8 i4 0 1 6.8 12.013 3700 9000 40 17 0.5 i4 0.01 1 6.8 12.061 3501 8500 30 20 0.3 i4 0.02 1 6.8 11.119 3399 7780 32 22 0.8 i4 0.03 1 6.8 12.042 3010 8600 41 27 0.45 i99 1 3.4 9.8 i12 1 3 6.8 5.06 1000 100 7000 16 0.2 i12 1.03 2.9 6.8 5.02 1000 60 6000 30 0.2 i99 4.4 3.6 4.8 i12 4.4 2.6 6.8 11.09 2000 1000 200 5 0.1 i99 8 2.1 7 i4 8 0.9 11 10.013 3000 9000 40 17 0.9 i4 8.1 0.9 11 10.061 3001 8500 30 20 0.8 i4 8.2 0.9 11 10.119 2999 7780 32 22 0.7 i99 10.1 1.1 21 i12 10.1 0.6 11 11.02 1000 1500 300 4 0.2 i99 11.2 6.8 2 i10 11.2 6 0 4.092 3000 0.3 6.9 200 i10 11.2 10 0 4.113 3000 0.1 7.2 278 i12 13 1.6 0.3 10.01 3000 2000 500 5.2 0.2 i10 13 1.6 0.4 9.012 3000 0.3 21 31 i4 15 0.7 0.4 13.023 5000 9000 40 17 0.9 i4 15 0.7 0.4 13.081 5001 8500 30 20 0.3 i4 15 0.7 0.4 13.019 4999 7780 32 22 0.7 i4 15 0.7 0.4 13.079 4550 9699 50 30 0.5 i4 15.7 1 0.4 9.013 1101 9000 40 17 0.9 i4 15.7 1 0.4 10.051 1051 8500 30 20 0.6 i4 15.7 1 0.4 7.119 1111 7780 32 22 0.2 i4 15.7 1 0.4 8.099 1100 10000 100 27 0.8 i12 17 2 0.4 9.02 3000 3000 1000 4 0.3 i99 18 3 9.3 i10 18 5 0 11.09 900 0.4 23 33 i10 18.1 5 0 11.08 900 0.4 20 40 i10 18.3 5 0 11.073 900 0.4 30 27 i10 18.6 5 0 11.068 900 0.4 33 33 i10 19 10 0 11.001 500 0.8 8 200 i10 20 9 0 11.022 500 0.8 9 300 i10 20.4 8.6 0 11.091 500 0.8 5 223 i99 21 56 0.15 i10 21 18 0 11.115 500 0.8 6.4 311 i10 21.6 17.4 0 12.041 500 0.8 7 276 i10 21.9 2.9 0 5.002 2000 0.3 4.1 200 i10 25.3 3.5 0 5.031 2300 0.5 3.6 160 i10 30.9 3.9 0 5.017 2500 0.7 3 100 i10 36.3 6.1 0 4.097 1770 0.8 4 200 i10 42 34.09 0 4.0017 6000 0.19 4.1 310 i8 45 26.9 0.79 190 500 11 1.9 2.7 0.1 i8 49 22.9 0.80 10000 8000 300 11 12.6 0.2 i8 52 19.1 0.85 7000 10000 16 4.1 4.8 0.3 i8 55 16.9 0.91 500 190 10 2.9 1.3 0.2 i8 58 13.9 0.98 40 9000 379 33 19 0.1 i8 60 12.9 0.99 3600 11000 19 17 22 0.3 i8 61 11.9 1.01 2000 3000 30 4 18.8 0.2 i99 77 23 0.09 i4 77 1.7 0.3 13.079 850 9699 50 30 0.8 i10 77.1 2.14 0 13.03 600 0.5 60 26 i10 77.6 2.3 0 13.02 800 0.6 62 24 i10 78.3 9.9 0 5.004 900 0.2 4.1 160 i10 78.7 9.8 0 5.001 800 0.3 1.4 220 i2 80.4 9 0 7.077 930 0.8 26 21 0.23 i2 80.7 8 0 8.077 830 0.7 24 19 0.13 i4 81.9 1.9 0.7 11.079 950 7699 40 20 0.7 i4 82 2.8 0.5 10.079 850 5699 60 40 0.5 i10 82.11 5.3 0 3.053 1800 0.1 4.0 210 i10 82.14 3.8 0 4.048 1100 0.2 71 33 i10 82.32 3.1 0 5.049 1000 0.2 68 27 i10 82.06 2.9 0 5.051 900 0.2 72 31 i10 84.04 9.9 0 4.003 1800 0.1 4.1 160 i10 84.06 9.8 0 4.002 1900 0.3 1.4 220 i10 84.618 9.8 0 5.005 900 0.4 4.1 180 i100 0 100 e ;============================================================================; ;======================= TOTAL TIME: 283 SECONDS ============================; ;============================================================================; 966 366 400 201 true 231 46 255 slider1 5 5 20 100 {86b9ad70-540b-4d5b-b0b9-07fa3da7466b} true 0 -3 0.00000000 1.00000000 0.00000000 lin continuous -1.00000000 false Version: 3 Render: Real Ask: Yes Functions: ioObject Listing: Window WindowBounds: 966 366 400 201 CurrentView: io IOViewEdit: On Options: ioView nobackground {59367, 11822, 65535} ioSlider {5, 5} {20, 100} 0.000000 1.000000 0.000000 slider1 csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/en.lproj/000077500000000000000000000000001321653344700243515ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/en.lproj/Credits.rtf000066400000000000000000000006641321653344700264710ustar00rootroot00000000000000{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} {\colortbl;\red255\green255\blue255;} \paperw9840\paperh8400 \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\b\fs24 \cf0 Engineering: \b0 \ Some people\ \ \b Human Interface Design: \b0 \ Some other people\ \ \b Testing: \b0 \ Hopefully not nobody\ \ \b Documentation: \b0 \ Whoever\ \ \b With special thanks to: \b0 \ Mom\ } csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/en.lproj/InfoPlist.strings000066400000000000000000000000551321653344700276730ustar00rootroot00000000000000/* Localized versions of Info.plist keys */ csound-6.10.0/OSX/Csound OSX Examples/Csound OSX Examples/main.m000066400000000000000000000016451321653344700237320ustar00rootroot00000000000000/* main.m: Copyright (C) 2014 Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import int main(int argc, const char * argv[]) { return NSApplicationMain(argc, argv); } csound-6.10.0/OSX/Csound OSX Examples/csound-OSX/000077500000000000000000000000001321653344700211405ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/csound-OSX/LICENSE.TXT000066400000000000000000000575651321653344700226450ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. csound-6.10.0/OSX/Csound OSX Examples/csound-OSX/classes/000077500000000000000000000000001321653344700225755ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/csound-OSX/classes/CsoundObj.h000066400000000000000000000102701321653344700246340ustar00rootroot00000000000000/* CsoundObj.h: Copyright (C) 2014 Steven Yi, Victor Lazzarini, Aurelius Prochazka This file is part of Csound for OS X. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import #import #import "csound.h" typedef struct csdata_ { CSOUND *cs; long bufframes; int ret; int nchnls; int nchnls_i; bool running; bool shouldRecord; bool shouldMute; bool useAudioInput; ExtAudioFileRef file; AudioUnit *aunit; __unsafe_unretained NSMutableArray *valuesCache; } csdata; typedef struct { CSOUND *cs; int attr; const char *format; va_list valist; } Message; // ----------------------------------------------------------------------------- # pragma mark - Protocols (Bindings and Listeners) // ----------------------------------------------------------------------------- @class CsoundObj; @protocol CsoundBinding - (void)setup:(CsoundObj *)csoundObj; @optional - (void)cleanup; - (void)updateValuesFromCsound; - (void)updateValuesToCsound; @end @protocol CsoundObjListener @optional - (void)csoundObjStarted:(CsoundObj *)csoundObj; - (void)csoundObjCompleted:(CsoundObj *)csoundObj; @end // ----------------------------------------------------------------------------- # pragma mark - CsoundObj Interface // ----------------------------------------------------------------------------- @interface CsoundObj : NSObject @property (nonatomic, strong) NSURL *outputURL; @property (assign) BOOL midiInEnabled; @property (assign) BOOL useAudioInput; - (void)sendScore:(NSString *)score; - (void)play:(NSString *)csdFilePath; - (void)updateOrchestra:(NSString *)orchestraString; - (void)stop; - (void)mute; - (void)unmute; // ----------------------------------------------------------------------------- # pragma mark - Recording // ----------------------------------------------------------------------------- - (void)record:(NSString *)csdFilePath toURL:(NSURL *)outputURL; - (void)record:(NSString *)csdFilePath toFile:(NSString *)outputFile; - (void)recordToURL:(NSURL *)outputURL; - (void)stopRecording; // ----------------------------------------------------------------------------- # pragma mark - Binding // ----------------------------------------------------------------------------- @property (nonatomic, strong) NSMutableArray *bindings; - (void)addBinding:(id)binding; - (void)removeBinding:(id)binding; // ----------------------------------------------------------------------------- # pragma mark - Listeners and Messages // ----------------------------------------------------------------------------- @property (assign) SEL messageCallbackSelector; - (void)addListener:(id)listener; - (void)setMessageCallback:(SEL)method withListener:(id)listener; - (void)performMessageCallback:(NSValue *)infoObj; // ----------------------------------------------------------------------------- # pragma mark - Csound Internals / Advanced Methods // ----------------------------------------------------------------------------- - (CSOUND *)getCsound; - (AudioUnit *)getAudioUnit; // get input or output that maps to a channel name and type, where type is // CSOUND_AUDIO_CHANNEL, CSOUND_CONTROL_CHANNEL, etc. - (MYFLT *)getInputChannelPtr:(NSString *)channelName channelType:(controlChannelType)channelType; - (MYFLT *)getOutputChannelPtr:(NSString *)channelName channelType:(controlChannelType)channelType; - (NSData *)getOutSamples; - (int)getNumChannels; - (int)getKsmps; @end csound-6.10.0/OSX/Csound OSX Examples/csound-OSX/classes/CsoundObj.m000066400000000000000000000376641321653344700246610ustar00rootroot00000000000000/* CsoundObj.m: Copyright (C) 2014 Steven Yi, Victor Lazzarini, Aurelius Prochazka This file is part of Csound for OS X. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import #import #import #import "CsoundObj.h" //#import "CsoundMIDI.h" OSStatus Csound_Render(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 dump, UInt32 inNumberFrames, AudioBufferList *ioData); void InterruptionListener(void *inClientData, UInt32 inInterruption); @interface CsoundObj() { NSMutableArray *listeners; csdata mCsData; id mMessageListener; } - (void)runCsound:(NSString *)csdFilePath; - (void)runCsoundToDisk:(NSArray *)paths; @end @implementation CsoundObj - (id)init { self = [super init]; if (self) { mCsData.shouldMute = false; _bindings = [[NSMutableArray alloc] init]; listeners = [[NSMutableArray alloc] init]; _midiInEnabled = NO; _useAudioInput = NO; } return self; } // ----------------------------------------------------------------------------- # pragma mark - CsoundObj Interface // ----------------------------------------------------------------------------- - (void)sendScore:(NSString *)score { if (mCsData.cs != NULL) { csoundReadScore(mCsData.cs, (char*)[score cStringUsingEncoding:NSASCIIStringEncoding]); } } - (void)play:(NSString *)csdFilePath { mCsData.shouldRecord = false; [self performSelectorInBackground:@selector(runCsound:) withObject:csdFilePath]; } - (void)updateOrchestra:(NSString *)orchestraString { if (mCsData.cs != NULL) { csoundCompileOrc(mCsData.cs, (char*)[orchestraString cStringUsingEncoding:NSASCIIStringEncoding]); } } - (void)stop { mCsData.running = false; } - (void)mute { mCsData.shouldMute = true; } - (void)unmute { mCsData.shouldMute = false; } // ----------------------------------------------------------------------------- # pragma mark - Recording // ----------------------------------------------------------------------------- - (void)record:(NSString *)csdFilePath toURL:(NSURL *)outputURL { mCsData.shouldRecord = true; self.outputURL = outputURL; [self performSelectorInBackground:@selector(runCsound:) withObject:csdFilePath]; } - (void)record:(NSString *)csdFilePath toFile:(NSString *)outputFile { mCsData.shouldRecord = false; [self performSelectorInBackground:@selector(runCsoundToDisk:) withObject:[NSMutableArray arrayWithObjects:csdFilePath, outputFile, nil]]; } - (void)recordToURL:(NSURL *)outputURL_ { // Define format for the audio file. AudioStreamBasicDescription destFormat, clientFormat; memset(&destFormat, 0, sizeof(AudioStreamBasicDescription)); memset(&clientFormat, 0, sizeof(AudioStreamBasicDescription)); destFormat.mFormatID = kAudioFormatLinearPCM; destFormat.mFormatFlags = kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsSignedInteger; destFormat.mSampleRate = csoundGetSr(mCsData.cs); destFormat.mChannelsPerFrame = mCsData.nchnls; destFormat.mBytesPerPacket = mCsData.nchnls * 2; destFormat.mBytesPerFrame = mCsData.nchnls * 2; destFormat.mBitsPerChannel = 16; destFormat.mFramesPerPacket = 1; // Create the audio file. OSStatus err = noErr; CFURLRef fileURL = (__bridge CFURLRef)outputURL_; err = ExtAudioFileCreateWithURL(fileURL, kAudioFileWAVEType, &destFormat, NULL, kAudioFileFlags_EraseFile, &(mCsData.file)); if (err == noErr) { // Get the stream format from the AU... // UInt32 propSize = sizeof(AudioStreamBasicDescription); // AudioUnitGetProperty(*(mCsData.aunit), kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &clientFormat, &propSize); // // ...and set it as the client format for the audio file. The file will use this // // format to perform any necessary conversions when asked to read or write. // ExtAudioFileSetProperty(mCsData.file, kExtAudioFileProperty_ClientDataFormat, sizeof(clientFormat), &clientFormat); // Warm the file up. ExtAudioFileWriteAsync(mCsData.file, 0, NULL); } else { printf("***Not recording. Error: %d\n", (int)err); err = noErr; } mCsData.shouldRecord = true; } - (void)stopRecording { mCsData.shouldRecord = false; ExtAudioFileDispose(mCsData.file); } // ----------------------------------------------------------------------------- # pragma mark - Bindings // ----------------------------------------------------------------------------- - (void)addBinding:(id)binding { if (binding != nil) { if (mCsData.running) [binding setup:self]; [_bindings addObject:binding]; } } - (void)removeBinding:(id)binding { if (binding != nil && [_bindings containsObject:binding]) { [_bindings removeObject:binding]; } } - (void)setupBindings { for (int i = 0; i < _bindings.count; i++) { id binding = [_bindings objectAtIndex:i]; [binding setup:self]; } } - (void)cleanupBindings { for (int i = 0; i < _bindings.count; i++) { id binding = [_bindings objectAtIndex:i]; if ([binding respondsToSelector:@selector(cleanup)]) { [binding cleanup]; } } } - (void)updateAllValuesToCsound { for (int i = 0; i < _bindings.count; i++) { id binding = [_bindings objectAtIndex:i]; if ([binding respondsToSelector:@selector(updateValuesToCsound)]) { [binding updateValuesToCsound]; } } } // ----------------------------------------------------------------------------- # pragma mark - Listeners and Messages // ----------------------------------------------------------------------------- - (void)addListener:(id)listener { [listeners addObject:listener]; } - (void)notifyListenersOfStartup { for (id listener in listeners) { if ([listener respondsToSelector:@selector(csoundObjStarted:)]) { [listener csoundObjStarted:self]; } } } - (void)notifyListenersOfCompletion { for (id listener in listeners) { if ([listener respondsToSelector:@selector(csoundObjCompleted:)]) { [listener csoundObjCompleted:self]; } } } static void messageCallback(CSOUND *cs, int attr, const char *format, va_list valist) { @autoreleasepool { CsoundObj *obj = (__bridge CsoundObj *)(csoundGetHostData(cs)); Message info; info.cs = cs; info.attr = attr; info.format = format; va_copy(info.valist,valist); NSValue *infoObj = [NSValue value:&info withObjCType:@encode(Message)]; [obj performSelector:@selector(performMessageCallback:) withObject:infoObj]; } } - (void)setMessageCallback:(SEL)method withListener:(id)listener { self.messageCallbackSelector = method; mMessageListener = listener; } - (void)performMessageCallback:(NSValue *)infoObj { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" [mMessageListener performSelector:self.messageCallbackSelector withObject:infoObj]; #pragma clang diagnostic pop } // ----------------------------------------------------------------------------- # pragma mark - Csound Internals / Advanced Methods // ----------------------------------------------------------------------------- - (CSOUND *)getCsound { if (!mCsData.running) { return NULL; } return mCsData.cs; } - (AudioUnit *)getAudioUnit { if (!mCsData.running) { return NULL; } return mCsData.aunit; } - (MYFLT *)getInputChannelPtr:(NSString *)channelName channelType:(controlChannelType)channelType { MYFLT *value; csoundGetChannelPtr(mCsData.cs, &value, [channelName cStringUsingEncoding:NSASCIIStringEncoding], channelType | CSOUND_INPUT_CHANNEL); return value; } - (MYFLT *)getOutputChannelPtr:(NSString *)channelName channelType:(controlChannelType)channelType { MYFLT *value; csoundGetChannelPtr(mCsData.cs, &value, [channelName cStringUsingEncoding:NSASCIIStringEncoding], channelType | CSOUND_OUTPUT_CHANNEL); return value; } - (NSData *)getOutSamples { if (!mCsData.running) { return nil; } CSOUND *csound = [self getCsound]; MYFLT *spout = csoundGetSpout(csound); int nchnls = csoundGetNchnls(csound); int ksmps = csoundGetKsmps(csound); NSData* data = [NSData dataWithBytes:spout length:(nchnls * ksmps * sizeof(MYFLT))]; return data; } - (int)getNumChannels { if (!mCsData.running) { return -1; } return csoundGetNchnls(mCsData.cs); } - (int)getKsmps { if (!mCsData.running) { return -1; } return csoundGetKsmps(mCsData.cs); } #pragma mark Csound Code OSStatus Csound_Render(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 dump, UInt32 inNumberFrames, AudioBufferList *ioData) { csdata *cdata = (csdata *) inRefCon; int ret = cdata->ret, nchnls = cdata->nchnls; CSOUND *cs = cdata->cs; int i,j,k; int slices = inNumberFrames/csoundGetKsmps(cs); int ksmps = csoundGetKsmps(cs); MYFLT *spin = csoundGetSpin(cs); MYFLT *spout = csoundGetSpout(cs); Float32 *buffer; AudioUnitRender(*cdata->aunit, ioActionFlags, inTimeStamp, 1, inNumberFrames, ioData); NSMutableArray* cache = cdata->valuesCache; for(i=0; i < slices; i++){ for (int i = 0; i < cache.count; i++) { id binding = [cache objectAtIndex:i]; if ([binding respondsToSelector:@selector(updateValuesToCsound)]) { [binding updateValuesToCsound]; } } /* performance */ if(cdata->useAudioInput) { for (k = 0; k < nchnls; k++){ buffer = (Float32 *) ioData->mBuffers[k].mData; for(j=0; j < ksmps; j++){ spin[j*nchnls+k] = buffer[j+i*ksmps]; } } } if(!ret) { ret = csoundPerformKsmps(cdata->cs); } else { cdata->running = false; } for (k = 0; k < nchnls; k++) { buffer = (Float32 *) ioData->mBuffers[k].mData; if (cdata->shouldMute == false) { for(j=0; j < ksmps; j++){ buffer[j+i*ksmps] = (Float32) spout[j*nchnls+k]; } } else { memset(buffer, 0, sizeof(Float32) * inNumberFrames); } } for (int i = 0; i < cache.count; i++) { id binding = [cache objectAtIndex:i]; if ([binding respondsToSelector:@selector(updateValuesFromCsound)]) { [binding updateValuesFromCsound]; } } } // Write to file. if (cdata->shouldRecord) { OSStatus err = ExtAudioFileWriteAsync(cdata->file, inNumberFrames, ioData); if (err != noErr) { printf("***Error writing to file: %d\n", (int)err); } } cdata->ret = ret; return 0; } - (void)runCsoundToDisk:(NSArray *)paths { @autoreleasepool { CSOUND *cs; cs = csoundCreate(NULL); char *argv[4] = { "csound", (char*)[[paths objectAtIndex:0] cStringUsingEncoding:NSASCIIStringEncoding], "-o", (char*)[[paths objectAtIndex:1] cStringUsingEncoding:NSASCIIStringEncoding]}; int ret = csoundCompile(cs, 4, argv); [self setupBindings]; [self notifyListenersOfStartup]; [self updateAllValuesToCsound]; if(!ret) { csoundPerform(cs); csoundCleanup(cs); csoundDestroy(cs); } [self cleanupBindings]; [self notifyListenersOfCompletion]; } } - (void)runCsound:(NSString *)csdFilePath { @autoreleasepool { CSOUND *cs; cs = csoundCreate(NULL); csoundSetMessageCallback(cs, messageCallback); csoundSetHostData(cs, (__bridge void *)(self)); // if (_midiInEnabled) { // [CsoundMIDI setMidiInCallbacks:cs]; // } char *argv[5] = { "csound", "-+ignore_csopts=0", "-+rtaudio=coreaudio", "-b256", (char*)[csdFilePath cStringUsingEncoding:NSASCIIStringEncoding]}; int ret = csoundCompile(cs, 5, argv); mCsData.running = true; if(!ret) { float coef = (float) SHRT_MAX / csoundGet0dBFS(cs); mCsData.cs = cs; mCsData.ret = ret; mCsData.nchnls = csoundGetNchnls(cs); mCsData.bufframes = (csoundGetOutputBufferSize(cs))/mCsData.nchnls; mCsData.running = true; mCsData.valuesCache = _bindings; mCsData.useAudioInput = _useAudioInput; MYFLT* spout = csoundGetSpout(cs); AudioBufferList bufferList; bufferList.mNumberBuffers = 1; [self setupBindings]; [self notifyListenersOfStartup]; if (mCsData.shouldRecord) { [self recordToURL:self.outputURL]; bufferList.mBuffers[0].mNumberChannels = mCsData.nchnls; bufferList.mBuffers[0].mDataByteSize = mCsData.nchnls * csoundGetKsmps(cs) * 2; // 16-bit PCM output bufferList.mBuffers[0].mData = malloc(sizeof(short) * mCsData.nchnls * csoundGetKsmps(cs)); } while (!mCsData.ret && mCsData.running) { for (int i = 0; i < _bindings.count; i++) { id binding = [_bindings objectAtIndex:i]; if ([binding respondsToSelector:@selector(updateValuesToCsound)]) { [binding updateValuesToCsound]; } } mCsData.ret = csoundPerformKsmps(mCsData.cs); // Write to file. if (mCsData.shouldRecord) { short* data = (short*)bufferList.mBuffers[0].mData; for (int i = 0; i < csoundGetKsmps(cs) * mCsData.nchnls; i++) { data[i] = (short)lrintf(spout[i] * coef); } OSStatus err = ExtAudioFileWriteAsync(mCsData.file, csoundGetKsmps(cs), &bufferList); if (err != noErr) { printf("***Error writing to file: %d\n", (int)err); } } for (int i = 0; i < _bindings.count; i++) { id binding = [_bindings objectAtIndex:i]; if ([binding respondsToSelector:@selector(updateValuesFromCsound)]) { [binding updateValuesFromCsound]; } } } } if (mCsData.shouldRecord) { ExtAudioFileDispose(mCsData.file); } csoundDestroy(cs); mCsData.running = false; [self cleanupBindings]; [self notifyListenersOfCompletion]; } } @end csound-6.10.0/OSX/Csound OSX Examples/csound-OSX/classes/bindings/000077500000000000000000000000001321653344700243725ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/csound-OSX/classes/bindings/ui/000077500000000000000000000000001321653344700250075ustar00rootroot00000000000000csound-6.10.0/OSX/Csound OSX Examples/csound-OSX/classes/bindings/ui/CsoundButtonBinding.h000066400000000000000000000020251321653344700311010ustar00rootroot00000000000000/* CsoundButtonBinding.h: Copyright (C) 2014 Steven Yi, Aurelius Prochazka This file is part of Csound for OSX. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import #import "CsoundObj.h" @interface CsoundButtonBinding : NSObject -(instancetype)initButton:(NSButton *)button channelName:(NSString *)channelName; @endcsound-6.10.0/OSX/Csound OSX Examples/csound-OSX/classes/bindings/ui/CsoundButtonBinding.m000066400000000000000000000035421321653344700311130ustar00rootroot00000000000000/* CsoundButtonBinding.m: Copyright (C) 2014 Steven Yi, Aurelius Prochazka This file is part of Csound for OSX. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "CsoundButtonBinding.h" @interface CsoundButtonBinding () { MYFLT channelValue; MYFLT *channelPtr; } @property (nonatomic, strong) NSString *channelName; @property (nonatomic, strong) NSButton *button; @end @implementation CsoundButtonBinding -(id)initButton:(NSButton *)button channelName:(NSString *)channelName { if (self = [super init]) { self.channelName = channelName; self.button = button; } return self; } -(void)updateChannelValueButtonStateChanged:(id)sender { channelValue = self.button.state; } -(void)setup:(CsoundObj *)csoundObj { channelValue = self.button.state; channelPtr = [csoundObj getInputChannelPtr:self.channelName channelType:CSOUND_CONTROL_CHANNEL]; [self.button setTarget:self]; [self.button setAction:@selector(updateChannelValueButtonStateChanged:)]; } -(void)updateValuesToCsound { *channelPtr = channelValue; } -(void)cleanup { [self.button setTarget:nil]; [self.button setAction:nil]; } @end csound-6.10.0/OSX/Csound OSX Examples/csound-OSX/classes/bindings/ui/CsoundMomentaryButtonBinding.h000066400000000000000000000020461321653344700330000ustar00rootroot00000000000000/* CsoundMomentaryButtonBinding.h: Copyright (C) 2014 Steven Yi, Aurelius Prochazka This file is part of Csound for OSX. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import #import "CsoundObj.h" @interface CsoundMomentaryButtonBinding : NSObject -(instancetype)initButton:(NSButton *)button channelName:(NSString *)channelName; @endcsound-6.10.0/OSX/Csound OSX Examples/csound-OSX/classes/bindings/ui/CsoundMomentaryButtonBinding.m000066400000000000000000000035611321653344700330100ustar00rootroot00000000000000/* CsoundMomentaryButtonBinding.m: Copyright (C) 2014 Steven Yi, Aurelius Prochazka This file is part of Csound for OSX. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "CsoundMomentaryButtonBinding.h" @interface CsoundMomentaryButtonBinding () { MYFLT channelValue; MYFLT *channelPtr; } @property (nonatomic, strong) NSString *channelName; @property (nonatomic, strong) NSButton *button; @end @implementation CsoundMomentaryButtonBinding -(instancetype)initButton:(NSButton *)button channelName:(NSString *)channelName { if (self = [super init]) { self.channelName = channelName; self.button = button; } return self; } -(void)updateChannelValue:(id)sender { channelValue = 1; } -(void)setup:(CsoundObj *)csoundObj { channelValue = self.button.state; channelPtr = [csoundObj getInputChannelPtr:self.channelName channelType:CSOUND_CONTROL_CHANNEL]; [self.button setTarget:self]; [self.button setAction:@selector(updateChannelValue:)]; } -(void)updateValuesToCsound { *channelPtr = channelValue; channelValue = 0; } -(void)cleanup { [self.button setTarget:nil]; [self.button setAction:nil]; } @end csound-6.10.0/OSX/Csound OSX Examples/csound-OSX/classes/bindings/ui/CsoundSliderBinding.h000066400000000000000000000020261321653344700310510ustar00rootroot00000000000000/* CsoundSliderBinding.h: Copyright (C) 2014 Steven Yi, Aurelius Prochazka This file is part of Csound for OSX. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import #import "CsoundObj.h" @interface CsoundSliderBinding : NSObject -(instancetype)initSlider:(NSSlider *)slider channelName:(NSString *)channelName; @end csound-6.10.0/OSX/Csound OSX Examples/csound-OSX/classes/bindings/ui/CsoundSliderBinding.m000066400000000000000000000035331321653344700310620ustar00rootroot00000000000000/* CsoundSliderBinding.m: Copyright (C) 2014 Steven Yi, Aurelius Prochazka This file is part of Csound for OSX. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "CsoundSliderBinding.h" @interface CsoundSliderBinding() { MYFLT channelValue; MYFLT *channelPtr; } @property (nonatomic, strong) NSString *channelName; @property (nonatomic, strong) NSSlider *slider; @end @implementation CsoundSliderBinding -(instancetype)initSlider:(NSSlider *)slider channelName:(NSString *)channelName { if (self = [super init]) { self.slider = slider; self.channelName = channelName; } return self; } -(void)updateChannelValue:(id)sender { channelValue = ((NSSlider *)sender).doubleValue; } -(void)setup:(CsoundObj *)csoundObj { channelPtr = [csoundObj getInputChannelPtr:self.channelName channelType:CSOUND_CONTROL_CHANNEL]; channelValue = self.slider.doubleValue; [self.slider setTarget:self]; [self.slider setAction:@selector(updateChannelValue:)]; } -(void)updateValuesToCsound { *channelPtr = channelValue; } -(void)cleanup { [self.slider setTarget:nil]; [self.slider setAction:nil]; } @end csound-6.10.0/OSX/Csound OSX Examples/csound-OSX/classes/bindings/ui/CsoundUI.h000066400000000000000000000023361321653344700266550ustar00rootroot00000000000000/* CsoundUI.h: Copyright (C) 2014 Steven Yi, Victor Lazzarini, Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import #import "CsoundObj.h" @interface CsoundUI : NSObject - (instancetype)initWithCsoundObj:(CsoundObj *)csound; - (void)addButton:(NSButton *)button forChannelName:(NSString *)channelName; - (void)addSlider:(NSSlider*)slider forChannelName:(NSString *)channelName; - (void)addMomentaryButton:(NSButton *)button forChannelName:(NSString *)channelName; @end csound-6.10.0/OSX/Csound OSX Examples/csound-OSX/classes/bindings/ui/CsoundUI.m000066400000000000000000000042401321653344700266560ustar00rootroot00000000000000/* CsoundUI.m: Copyright (C) 2014 Steven Yi, Victor Lazzarini, Aurelius Prochazka This file is part of Csound OSX Examples. The Csound for OSX Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "CsoundUI.h" #import "CsoundButtonBinding.h" #import "CsoundMomentaryButtonBinding.h" #import "CsoundSliderBinding.h" @interface CsoundUI () { CsoundObj *csoundObj; } @end @implementation CsoundUI - (instancetype)initWithCsoundObj:(CsoundObj *)csound { self = [super init]; if (self) { csoundObj = csound; } return self; } - (void)addButton:(NSButton *)button forChannelName:(NSString *)channelName { CsoundButtonBinding *buttonBinding; buttonBinding = [[CsoundButtonBinding alloc] initButton:button channelName:channelName]; [csoundObj addBinding:buttonBinding]; } - (void)addSlider:(NSSlider *)slider forChannelName:(NSString *)channelName { CsoundSliderBinding *sliderBinding; sliderBinding = [[CsoundSliderBinding alloc] initSlider:slider channelName:channelName]; [csoundObj addBinding:sliderBinding]; } - (void)addMomentaryButton:(NSButton *)button forChannelName:(NSString *)channelName { CsoundMomentaryButtonBinding *momentaryButtonBinding; momentaryButtonBinding = [[CsoundMomentaryButtonBinding alloc] initButton:button channelName:channelName]; [csoundObj addBinding:momentaryButtonBinding]; } @end csound-6.10.0/OSX/release.sh000077500000000000000000000007321321653344700155330ustar00rootroot00000000000000#!/bin/sh export RELEASE_DIR=csound-OSX-SDK-6.04.0 #remove backup files ending with ~ find . -name "*~" -exec rm {} \; rm -rf $RELEASE_DIR mkdir $RELEASE_DIR # Build Documentation #cd docs #pdflatex csound_OSX_manual.tex # Assemble release #cd ../$RELEASE_DIR cd $RELEASE_DIR #cp ../docs/csound_ios_manual.pdf . # COPYING HEADERS cp -R ../Csound\ OSX\ Examples . cp Csound\ OSX\ Examples/LICENSE.TXT . cp ../CHANGELOG . cd .. zip -r ${RELEASE_DIR}.zip ${RELEASE_DIR} csound-6.10.0/Opcodes/000077500000000000000000000000001321653344700144755ustar00rootroot00000000000000csound-6.10.0/Opcodes/3Dug.h000066400000000000000000000033711321653344700154540ustar00rootroot00000000000000/* 3Dug.h: Copyright (C) 1995, 2001 Eli Breder, David McIntyre This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _3DUG_H_ #define _3DUG_H_ #define SAMP_RATE 44100 /* sampling rate of HRTFs */ #define FILT_LEN 128L #define FILT_LENm1 (FILT_LEN-1) #define BUF_LEN (FILT_LEN*2) #define BLOCK_SIZE 1024 #define MIN_ELEV -40 #define MAX_ELEV 90 #define ELEV_INC 10 #define N_ELEV (((MAX_ELEV - MIN_ELEV) / ELEV_INC) + 1) #define MIN_AZIM -180 #define MAX_AZIM 180 /* * This array gives the total number of azimuths measured * per elevation, and hence the AZIMUTH INCREMENT. Note that * only azimuths up to and including 180 degrees actually * exist in file system (because the data is symmetrical. */ /* int elevation_data[N_ELEV] = {56, 60, 72, 72, 72, 72, 72, 60, 56, 45, */ /* 36, 24, 12, 1 }; */ typedef struct { MYFLT left[256]; /* left and right will hold FFTed values of HRTFs */ MYFLT right[256]; } HRTF_DATUM; #endif csound-6.10.0/Opcodes/AbletonLinkOpcodes/000077500000000000000000000000001321653344700202145ustar00rootroot00000000000000csound-6.10.0/Opcodes/AbletonLinkOpcodes/AbletonLinkOpcodes.sln000066400000000000000000000024451321653344700244560ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AbletonLinkOpcodes", "AbletonLinkOpcodes.vcxproj", "{4BDD4C7D-F572-4067-BE60-6E24B15D27DE}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {4BDD4C7D-F572-4067-BE60-6E24B15D27DE}.Debug|x64.ActiveCfg = Debug|x64 {4BDD4C7D-F572-4067-BE60-6E24B15D27DE}.Debug|x64.Build.0 = Debug|x64 {4BDD4C7D-F572-4067-BE60-6E24B15D27DE}.Debug|x86.ActiveCfg = Debug|Win32 {4BDD4C7D-F572-4067-BE60-6E24B15D27DE}.Debug|x86.Build.0 = Debug|Win32 {4BDD4C7D-F572-4067-BE60-6E24B15D27DE}.Release|x64.ActiveCfg = Release|x64 {4BDD4C7D-F572-4067-BE60-6E24B15D27DE}.Release|x64.Build.0 = Release|x64 {4BDD4C7D-F572-4067-BE60-6E24B15D27DE}.Release|x86.ActiveCfg = Release|Win32 {4BDD4C7D-F572-4067-BE60-6E24B15D27DE}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal csound-6.10.0/Opcodes/AbletonLinkOpcodes/AbletonLinkOpcodes.vcxproj000066400000000000000000000223101321653344700253460ustar00rootroot00000000000000 Debug Win32 Release Win32 Debug x64 Release x64 {4BDD4C7D-F572-4067-BE60-6E24B15D27DE} Win32Proj AbletonLinkOpcodes 8.1 DynamicLibrary true v140 Unicode DynamicLibrary false v140 true Unicode DynamicLibrary true v140_xp Unicode DynamicLibrary false v140_xp true Unicode true true D:\msys64\home\restore\link_vs2015\include\ableton;D:\msys64\home\restore\link_vs2015\include;D:\msys64\home\restore\link_vs2015\modules\asio-standalone\asio\include;$(IncludePath) ableton_link_opcodes false false D:\msys64\home\restore\link_vs2015\include\ableton;D:\msys64\home\restore\link_vs2015\include;D:\msys64\home\restore\link_vs2015\modules\asio-standalone\asio\include;$(IncludePath) ableton_link_opcodes Level3 Disabled WIN32;_DEBUG;_WINDOWS;_USRDLL;ABLETONLINKOPCODES_EXPORTS;%(PreprocessorDefinitions) Windows true Level3 Disabled _DEBUG;_WINDOWS;_USRDLL;ABLETONLINKOPCODES_EXPORTS;%(PreprocessorDefinitions);-D_WIN32_WINNT=0x0501;LINK_PLATFORM_WINDOWS;_WIN32_WINNT=0x0501 D:\msys64\home\restore\csound\include;D:\msys64\home\restore\link\include;D:\msys64\home\restore\link\modules\asio-standalone\asio\include;D:\msys64\home\restore\link\include\ableton\platforms;D:\msys64\home\restore\link\build\src;%(AdditionalIncludeDirectories) /wd4503 /wd4800 /wd4244 %(AdditionalOptions) Windows true $(OutDir)ableton_link_opcodes$(TargetExt) Level3 MaxSpeed true true WIN32;NDEBUG;_WINDOWS;_USRDLL;ABLETONLINKOPCODES_EXPORTS;%(PreprocessorDefinitions) Windows true true true Level3 MaxSpeed true true NDEBUG;_WINDOWS;_USRDLL;ABLETONLINKOPCODES_EXPORTS;%(PreprocessorDefinitions);-D_WIN32_WINNT=0x0501;LINK_PLATFORM_WINDOWS;_WIN32_WINNT=0x0501 D:\msys64\home\restore\csound\include;D:\msys64\home\restore\link\include;D:\msys64\home\restore\link\modules\asio-standalone\asio\include;D:\msys64\home\restore\link\include\ableton\platforms;D:\msys64\home\restore\link\build\src;%(AdditionalIncludeDirectories) /wd4503 /wd4800 /wd4244 %(AdditionalOptions) Windows true true true $(OutDir)ableton_link_opcodes$(TargetExt) D:\msys64\home\restore\link\include;D:\msys64\home\restore\link\include\ableton\platforms\asio;%(AdditionalIncludeDirectories) csound-6.10.0/Opcodes/CMakeLists.txt000066400000000000000000000347541321653344700172520ustar00rootroot00000000000000option(BUILD_CHUA_OPCODES "Build the chua opcodes" ON) option(BUILD_DSSI_OPCODES "Build the DSSI opcodes" ON) option(BUILD_FLUID_OPCODES "Build the fluidsynth opcodes" ON) option(BUILD_JACK_OPCODES "Build the JACK related opcodes" OFF) option(BUILD_LINEAR_ALGEBRA_OPCODES "Build the Linear Algebra Opcodes" ON) option(BUILD_OSC_OPCODES "Build the OSC Opcodes" ON) option(BUILD_IMAGE_OPCODES "Build the image opcodes" ON) option(BUILD_PYTHON_OPCODES "Build the Python opcodes" ON) option(BUILD_LUA_OPCODES "Build the Lua opcodes" ON) option(BUILD_WIIMOTE_OPCODES "Build the Wiimote opcodes" ON) option(BUILD_P5GLOVE_OPCODES "Build the P5Glove opcodes" ON) option(BUILD_SERIAL_OPCODES "Build the serial opcode" ON) option(BUILD_PLATEREV_OPCODES "Build the platerev opcode" ON) option(BUILD_FAUST_OPCODES "Build the Faust opcodes" OFF) option(BUILD_VST4CS_OPCODES "Build the vst4cs opcodes" OFF) option(BUILD_EXCITER_OPCODES "Build the exciter opcode" ON) option(BUILD_BUCHLA_OPCODES "Build the Buchla filter opcode" ON) option(BUILD_PADSYNTH_OPCODES "Build the Padsynth opcode" ON) option(BUILD_SCANSYN_OPCODES "Build the scansyn opcodes" ON) option(BUILD_SELECT_OPCODE "Build the select opcode" ON) option(BUILD_STACK_OPCODES "Build the stack opcodes" ON) message(STATUS "## Building Opcodes ##") #find_package (Eigen3 3.3 REQUIRED NO_MODULE) include(CheckIncludeFiles) check_include_file(ladspa.h LADSPA_H) check_include_file(fluidsynth.h FLUIDSYNTH_H) find_path(FLUIDSYNTH_INCLUDE_DIR "fluidsynth.h") find_library(FLUIDSYNTH_LIBRARY fluidsynth) find_library(JACK_LIBRARY jack) find_library(JACKDMP_LIBRARY jackdmp) check_include_file(jack/jack.h JACK_HEADER) check_include_file(lo/lo.h OSC_HEADER) find_path(OSC_HEADER_INC "lo/lo.h") find_library(LIBLO_LIBRARY lo) find_package(ZLIB) find_package(PNG) set(PYTHON_INCLUDE_DIRS /usr/include/Python2.7) set(Python_ADDITIONAL_VERSIONS 2.7) find_package(PythonLibs) check_include_file(wiiuse.h WIIUSE_H) find_library(WIIUSE_LIB wiiuse) check_include_file(p5glove.h P5GLOVE_H) find_library(P5GLOVE_LIB p5glove) if(BUILD_FAUST_OPCODES) find_package(LLVM) exec_program(llvm-config ARGS --libs OUTPUT_VARIABLE LLVM_LIBS) find_library(FAUST_LIBRARY libfaust.a HINTS /usr/local/lib) endif() ## OPCODE LIBS WITH NO EXTERNAL DEPENDENCIES ## make_plugin(mixer mixer.cpp) make_plugin(signalflowgraph signalflowgraph.cpp) make_plugin(ampmidid ampmidid.cpp) make_plugin(cs_date date.c) make_plugin(system_call system_call.c) make_plugin(doppler doppler.cpp) make_plugin(fractalnoise tl/fractalnoise.cpp) make_plugin(ftsamplebank ftsamplebank.cpp) make_plugin(getftargs getftargs.c) make_plugin(liveconv liveconv.c) make_plugin(fareygen fareygen.c) make_plugin(quadbezier quadbezier.c) if(APPLE) make_plugin(arrayops arrayops.cpp) set_target_properties(arrayops PROPERTIES COMPILE_FLAGS "-std=c++11") make_plugin(pvsops pvsops.cpp) set_target_properties(pvsops PROPERTIES COMPILE_FLAGS "-std=c++11") elseif(LINUX) include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG("-std=gnu++11" COMPILER_SUPPORTS_CXX11) if(COMPILER_SUPPORTS_CXX11) make_plugin(arrayops arrayops.cpp) set_target_properties(arrayops PROPERTIES COMPILE_FLAGS "-std=gnu++11") make_plugin(pvsops pvsops.cpp) set_target_properties(pvsops PROPERTIES COMPILE_FLAGS "-std=gnu++11") else() message(STATUS "Not building array operators as no C++11 support found.") endif() else() make_plugin(arrayops arrayops.cpp) make_plugin(pvsops pvsops.cpp) if(WIN32 AND NOT MSVC) set_target_properties(arrayops PROPERTIES COMPILE_FLAGS "-std=gnu++11") set_target_properties(pvsops PROPERTIES COMPILE_FLAGS "-std=gnu++11") endif() endif() if(BUILD_PADSYNTH_OPCODES) if(APPLE) make_plugin(padsynth padsynth_gen.cpp) set_target_properties(padsynth PROPERTIES COMPILE_FLAGS "-std=gnu++11 -stdlib=libc++" LINK_FLAGS "-std=gnu++11 -stdlib=libc++") elseif(LINUX) include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG("-std=gnu++11" COMPILER_SUPPORTS_CXX11) CHECK_CXX_COMPILER_FLAG("-std=gnu++0x" COMPILER_SUPPORTS_CXX0X) if(COMPILER_SUPPORTS_CXX11) make_plugin(padsynth padsynth_gen.cpp) set_target_properties(padsynth PROPERTIES COMPILE_FLAGS "-std=gnu++11") elseif(COMPILER_SUPPORTS_CXX0X) make_plugin(padsynth padsynth_gen.cpp) set_target_properties(padsynth PROPERTIES COMPILE_FLAGS "-std=gnu++0x") else() message(STATUS "Not building padsynth as no C++11 support found.") endif() else() make_plugin(padsynth padsynth_gen.cpp) if(WIN32 AND NOT MSVC) set_target_properties(padsynth PROPERTIES COMPILE_FLAGS "-std=gnu++11" LINK_FLAGS "-std=gnu++11") endif() endif() endif() make_plugin(cellular cellular.c) if(BUILD_SERIAL_OPCODES) make_plugin(serial serial.c) endif() if(BUILD_PLATEREV_OPCODES) make_plugin(platerev platerev.c m) endif() if(BUILD_SCANSYN_OPCODES) set(scansyn_SRCS scansyn.c scansynx.c) make_plugin(scansyn "${scansyn_SRCS}" m) endif() if(UNIX) make_plugin(control control.c) make_plugin(urandom urandom.c) endif() if(LINUX) #make_plugin(urandom urandom.c) make_plugin(joystick linuxjoystick.c) endif() ## OPCODES WITH EXTERNAL DEPENDENCIES ## check_deps(BUILD_CHUA_OPCODES EIGEN3_INCLUDE_PATH) if(BUILD_CHUA_OPCODES) make_plugin(chua chua/ChuaOscillator.cpp) target_include_directories(chua PRIVATE ${Boost_INCLUDE_DIRS}) endif() check_deps(BUILD_DSSI_OPCODES LINUX) if(BUILD_DSSI_OPCODES) set(dssi_SRC dssi4cs/src/load.c dssi4cs/src/dssi4cs.c) make_plugin(dssi4cs "${dssi_SRC}" dl) endif() check_deps(BUILD_FLUID_OPCODES FLUIDSYNTH_H FLUIDSYNTH_LIBRARY) if(BUILD_FLUID_OPCODES) make_plugin(fluidOpcodes fluidOpcodes/fluidOpcodes.cpp) if(EXISTS ${FLUIDSYNTH_INCLUDE_DIR}) target_include_directories(fluidOpcodes PRIVATE "${FLUIDSYNTH_INCLUDE_DIR}") endif() if(WIN32 AND NOT MSVC) set(FSYNTH_SUPPORT_LIBS dsound portaudio ${LIBSNDFILE_LIBRARY} ${LIBSNDFILE_SUPPORT_LIBS} wsock32 glib-2.0 intl iconv ws2_32 winmm Setupapi) target_link_libraries(fluidOpcodes ${FSYNTH_SUPPORT_LIBS}) target_compile_definitions(fluidOpcodes PRIVATE -DFLUIDSYNTH_NOT_A_DLL) else() target_link_libraries(fluidOpcodes ${FLUIDSYNTH_LIBRARY}) endif() add_dependency_to_framework(fluidOpcodes ${FLUIDSYNTH_LIBRARY}) endif() set(JACK_LIB (JACK_LIBRARY OR JACKDMP_LIBRARY)) check_deps(BUILD_JACK_OPCODES JACK_HEADER JACK_LIB) if(BUILD_JACK_OPCODES) set(jack_LIBS ${PTHREAD_LIBRARY}) if(JACKDMP_LIBRARY) list(APPEND jack_LIBS ${JACKDMP_LIBRARY}) else() list(APPEND jack_LIBS ${JACK_LIBRARY}) endif() make_plugin(jacko jacko.cpp "${jack_LIBS}") set_target_properties(jacko PROPERTIES COMPILE_FLAGS "-std=c++11") make_plugin(jackTransport jackTransport.c "${jack_LIBS}") endif() check_deps(BUILD_LINEAR_ALGEBRA_OPCODES GMM_FOUND) if(BUILD_LINEAR_ALGEBRA_OPCODES) make_plugin(linear_algebra linear_algebra.cpp) target_include_directories(linear_algebra PRIVATE ${GMM_INCLUDE_DIRS}) if (MSVC) target_compile_options(linear_algebra PRIVATE "/D_SCL_SECURE_NO_DEPRECATE") endif() endif() check_deps(BUILD_OSC_OPCODES LIBLO_LIBRARY OSC_HEADER) if(BUILD_OSC_OPCODES) make_plugin(osc OSC.c) if(WIN32) target_include_directories(osc PRIVATE ${OSC_HEADER_INC}) target_link_libraries(osc ${LIBLO_LIBRARY}) # FIXME how to build a static version of this? if(BUILD_STATIC_LIBRARY AND NOT MSVC) add_library(pthread_static STATIC IMPORTED) set_target_properties(pthread_static PROPERTIES IMPORTED_LOCATION ${PTHREAD_LIBRARY}) target_link_libraries(osc pthread_static) elseif(NOT MSVC) target_link_libraries(osc ${PTHREAD_LIBRARY}) endif() target_link_libraries(osc wsock32 ws2_32 iphlpapi) else() target_link_libraries(osc ${LIBLO_LIBRARY} pthread) endif() add_dependency_to_framework(osc ${LIBLO_LIBRARY}) endif() check_deps(BUILD_IMAGE_OPCODES PNG_FOUND) if(BUILD_IMAGE_OPCODES) make_plugin(image imageOpcodes.c) target_include_directories(image PRIVATE ${PNG_INCLUDE_DIR}) target_link_libraries(image ${PNG_LIBRARIES}) target_compile_definitions(image PRIVATE ${PNG_DEFINITIONS}) add_dependency_to_framework(image ${PNG_LIBRARY}) endif() check_deps(BUILD_PYTHON_OPCODES PYTHONLIBS_FOUND) if(BUILD_PYTHON_OPCODES) make_plugin(py py/pythonopcodes.c) target_include_directories(py PRIVATE ${PYTHON_INCLUDE_DIRS}) target_include_directories(py PRIVATE ${CMAKE_HOME_DIRECTORY}/include) target_link_libraries(py ${PYTHON_LIBRARIES}) endif() if(NOT APPLE) check_deps(BUILD_LUA_OPCODES LUAJIT_LIBRARY LUA_H_PATH) if(BUILD_LUA_OPCODES) make_plugin(LuaCsound LuaCsound.cpp ${LUAJIT_LIBRARY}) target_compile_options(LuaCsound PRIVATE ${OpenMP_CXX_FLAGS}) target_include_directories(LuaCsound PRIVATE ${LUA_H_PATH}) endif() endif() check_deps(BUILD_WIIMOTE_OPCODES WIIUSE_H WIIUSE_LIB) if(BUILD_WIIMOTE_OPCODES) make_plugin(wiimote wiimote.c ${WIIUSE_LIB}) add_dependency_to_framework(wiimote ${WIIUSE_LIB}) endif() if(BUILD_EXCITER_OPCODES) make_plugin(exciter exciter.c) endif() if(BUILD_BUCHLA_OPCODES) make_plugin(buchla buchla.c) endif() check_deps(BUILD_P5GLOVE_OPCODES P5GLOVE_H) if(BUILD_P5GLOVE_OPCODES) make_plugin(p5g p5glove.c ${P5GLOVE_LIB}) endif() if(BUILD_SELECT_OPCODE) make_plugin(select select.c) endif() if(BUILD_STACK_OPCODES) make_plugin(stackops stackops.c) endif() check_deps(BUILD_FAUST_OPCODES LLVM_FOUND FAUST_LIBRARY) if(BUILD_FAUST_OPCODES) make_plugin(faustcsound faustgen.cpp) if(APPLE) target_link_libraries(faustcsound -lcrypto) target_link_libraries(faustcsound -lcurses) target_link_libraries(faustcsound -lz) else() target_link_libraries(faustcsound -Wl,-no-as-needed -lcrypto) target_link_libraries(faustcsound -Wl,-no-as-needed -lcurses) target_link_libraries(faustcsound -Wl,-no-as-needed -lz) endif() target_link_libraries(faustcsound ${PTHREAD_LIBRARY}) target_compile_definitions(faustcsound PRIVATE "-DFAUSTFLOAT=double") if(APPLE) if(${OSX_VERSION} STREQUAL "10.6") target_link_libraries(faustcsound ${FAUST_LIBRARY} -ldl -L$ENV{HOME}/lib -L/usr/local/lib ${LLVM_LIBS}) else() target_compile_options(faustcsound PRIVATE "-stdlib=libc++") target_link_libraries(faustcsound ${FAUST_LIBRARY} -stdlib=libc++ -ldl -L$ENV{HOME}/lib -L/usr/local/lib ${LLVM_LIBS}) endif() else() target_link_libraries(faustcsound ${FAUST_LIBRARY} -ldl -L$ENV{HOME}/lib -L/usr/local/lib ${LLVM_LIBS}) endif() target_include_directories(faustcsound PRIVATE ${LLVM_INCLUDE_DIRS}) endif() # OGG Opcode previously was built only for OLPC #if(VORBISFILE_LIBRARY) # set(vorbis_LIBS ${libcsound_LIBS} ${VORBISFILE_LIBRARY}) # make_plugin(ogg ogg.c "${vorbis_LIBS}") #endif() check_deps(BUILD_VST4CS_OPCODES VSTSDK2X_FOUND FLTK_FOUND) message(STATUS "VSTSDK2X_INCLUDE_DIR: ${VSTSDK2X_INCLUDE_DIR}") if(BUILD_VST4CS_OPCODES) set(VST4CS_SRCS vst4cs/src/vst4cs.cpp vst4cs/src/vsthost.cpp vst4cs/src/fxbank.cpp ${VSTSDK2X_INCLUDE_DIR}/public.sdk/source/vst2.x/audioeffect.cpp ${VSTSDK2X_INCLUDE_DIR}/public.sdk/source/vst2.x/audioeffectx.cpp) add_library(vst4cs SHARED ${VST4CS_SRCS}) target_compile_definitions(vst4cs PRIVATE -DVST_FORCE_DEPRECATED=0 -DCS_VSTHOST) target_include_directories(vst4cs PRIVATE ${VSTSDK2X_INCLUDE_DIR}) target_include_directories(vst4cs PRIVATE ${VSTSDK2X_INCLUDE_DIR}/public.sdk/source/vst2.x) target_include_directories(vst4cs PRIVATE ${VSTSDK2X_INCLUDE_DIR}/pluginterfaces/source/vst2.x) target_include_directories(vst4cs PRIVATE ${FLTK_INCLUDE_DIR}) set_target_properties(vst4cs PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${BUILD_BIN_DIR} LIBRARY_OUTPUT_DIRECTORY ${BUILD_LIB_DIR} ARCHIVE_OUTPUT_DIRECTORY ${BUILD_LIB_DIR} ) target_link_libraries(vst4cs PRIVATE ${CSOUNDLIB} ${FLTK_LIBRARIES}) if(NOT MSVC) if(BUILD_STATIC_LIBRARY) if(WIN32) add_library(pthread STATIC IMPORTED) set_target_properties(pthread PROPERTIES IMPORTED_LOCATION ${PTHREAD_LIBRARY}) endif() target_link_libraries(vst4cs PRIVATE pthread) else() target_link_libraries(vst4cs PRIVATE ${PTHREAD_LIBRARY}) endif() endif() install(TARGETS vst4cs LIBRARY DESTINATION ${PLUGIN_INSTALL_DIR} ARCHIVE DESTINATION ${LIBRARY_INSTALL_DIR}) endif() check_deps(BUILD_ABLETON_LINK_OPCODES ABLETON_LINK_HOME) if(BUILD_ABLETON_LINK_OPCODES) message(STATUS "Ableton Link home: ${ABLETON_LINK_HOME}") if(APPLE) make_plugin(ableton_link_opcodes ableton_link_opcodes.cpp) set_target_properties(ableton_link_opcodes PROPERTIES COMPILE_FLAGS "-std=c++11 -stdlib=libc++ -Wno-multichar -DLINK_PLATFORM_MACOSX=1" LINK_FLAGS "-std=c++11 -stdlib=libc++") elseif(LINUX) include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG("-std=gnu++11" COMPILER_SUPPORTS_CXX11) if(COMPILER_SUPPORTS_CXX11) make_plugin(ableton_link_opcodes ableton_link_opcodes.cpp) set_target_properties(ableton_link_opcodes PROPERTIES COMPILE_FLAGS "-std=gnu++11 -Wno-multichar -DLINK_PLATFORM_LINUX=1") else() message(STATUS "Not building ableton_link_opcodes as no C++11 support found.") endif() else() make_plugin(ableton_link_opcodes ableton_link_opcodes.cpp) if(WIN32) if(MSVC) include_directories($ENV{INCLUDE}) include(${ABLETON_LINK_HOME}\\AbletonLinkConfig.cmake) target_link_libraries(ableton_link_opcodes Ableton::Link) else() set_target_properties(ableton_link_opcodes PROPERTIES COMPILE_FLAGS "-std=gnu++11 -Wno-multichar -DLINK_PLATFORM_WINDOWS=1" LINK_FLAGS "-std=gnu++11") target_link_libraries(ableton_link_opcodes wsock32 ws2_32 iphlpapi) endif() endif() endif() target_include_directories(ableton_link_opcodes PRIVATE ${ABLETON_LINK_HOME}/include) target_include_directories(ableton_link_opcodes PRIVATE ${ABLETON_LINK_HOME}/modules/asio-standalone/asio/include) install(TARGETS ableton_link_opcodes LIBRARY DESTINATION ${PLUGIN_INSTALL_DIR} ARCHIVE DESTINATION ${LIBRARY_INSTALL_DIR}) endif() add_subdirectory(stk) add_subdirectory(cuda) add_subdirectory(opencl) add_subdirectory(hdf5) add_subdirectory(websockets) add_subdirectory(framebuffer) add_subdirectory(emugens) csound-6.10.0/Opcodes/LuaCsound.cpp000066400000000000000000001023121321653344700170750ustar00rootroot00000000000000/* LuaCsound.cpp: Copyright (C) 2011 by Micael Gogins This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include using namespace std; using namespace csound; extern "C" { #include #include #include } // These redefinitions are required because for Android, // LuaJIT is built with gcc for the GNU runtime library; // but LuaCsound is built with the NDK for the bionic runtime library. #if defined(__ANDROID__) extern "C" { #undef stdin FILE *stdin = &__sF[0]; #undef stdout FILE *stdout = &__sF[1]; #undef stderr FILE *stderr = &__sF[2]; volatile int *__errno_location(void) { return __errno(); } int _IO_getc(FILE *file_) { return getc(file_); } int _IO_putc(int char_, FILE *file_) { return putc(char_, file_); } int __isoc99_fscanf(FILE *stream, const char *format, ...) { va_list arg; va_start(arg, format); return vfscanf(stream, format, arg); } } #endif /** * L U A O P C O D E S F O R C S O U N D * * Author: Michael Gogins * 1 September 2011 * * These opcodes require LuaJIT 2.0 or later with FFI to be installed with * Csound. They allow users to define new opcodes in Lua, a modern language * with simple sytax, full lexical scoping, support for classes, and support * for functional programming. These opcodes are designed to be thread-safe. * LuaJIT runs almost as fast as C and faster than Csound orchestra code. */ /** * Stores Lua references to opcode subroutines for greater efficiency of * calling. */ struct keys_t { keys_t() : init_key(0), kontrol_key(0), audio_key(0), noteoff_key(0) {} int init_key; int kontrol_key; int audio_key; int noteoff_key; }; struct LuaStateForThread { void *thread; lua_State *L; }; bool operator == (const LuaStateForThread &a, const LuaStateForThread &b) { if (a.thread == b.thread) { return true; } else { return false; } } /** * Thread-safe storage for Lua references to opcode subroutines. */ keys_t &manageLuaReferenceKeys(CSOUND *csound, const lua_State *L, const std::string &opcode, char operation) { void *reference_keys_mutex = 0; csound::QueryGlobalPointer(csound, "reference_keys_mutex", reference_keys_mutex); keys_t *keys = 0; { LockGuard criticalSection(csound, reference_keys_mutex); std::map > *luaReferenceKeys = 0; csound::QueryGlobalPointer(csound, "luaReferenceKeys", luaReferenceKeys); switch (operation) { case 'O': { keys = &(*luaReferenceKeys)[L][opcode]; } break; case 'C': { luaReferenceKeys->erase(L); } break; } } return *keys; } /** * Thread-safe storage for Lua states (virtual machines). There is one Lua state * per thread, rather than per instance of Csound, in case one instance of Csound * is running multiple threads with multiple instances of a Lua opcode. */ lua_State *manageLuaState(CSOUND *csound, char operation) { void *lua_states_mutex = 0; csound::QueryGlobalPointer(csound, "lua_states_mutex", lua_states_mutex); LockGuard criticalSection(csound, lua_states_mutex); std::vector *luaStatesForThreads = 0; csound::QueryGlobalPointer(csound, "luaStatesForThreads", luaStatesForThreads); LuaStateForThread luaStateForThread; luaStateForThread.thread = csound->GetCurrentThreadID(); std::vector::iterator it = std::find(luaStatesForThreads->begin(), luaStatesForThreads->end(), luaStateForThread); lua_State *L = 0; switch (operation) { case 'O': { if (it == luaStatesForThreads->end()) { luaStateForThread.L = lua_open(); luaL_openlibs(luaStateForThread.L); luaStatesForThreads->push_back(luaStateForThread); L = luaStateForThread.L; } else { L = it->L; } } break; case 'C': { if (it != luaStatesForThreads->end()) { manageLuaReferenceKeys(csound, it->L, "", 'C'); lua_close(it->L); luaStatesForThreads->erase(it); } } break; } return L; } /** * lua_exec Scode -- Execute an arbitrary block of Lua code at i-rate. */ class cslua_exec : public OpcodeBase { public: /** * No outputs. */ /** * Inputs. */ MYFLT *luacode_; int init(CSOUND *csound) { int result = OK; lua_State *L = manageLuaState(csound, 'O'); /* Ensure that Csound is available in the global environment. */ lua_pushlightuserdata(L, csound); lua_setfield(L, LUA_GLOBALSINDEX, "csound"); const char *luacode = ((STRINGDAT *)luacode_)->data; log(csound, "Executing (L: 0x%p) Lua code.\n", L); warn(csound, "\n%s\n", luacode); result = luaL_dostring(L, luacode); if (result == 0) { //log(csound, "Result: %d\n", result); } else { log(csound, "luaL_dostring failed with: %d\n%s\n", result, lua_tostring(L, -1)); } return result; } }; /** * lua_iopcall Sname, ... Calls a Lua opcode at i-rate only. Any number of * output and/or input arguments may be passed. * All arguments must be passed on the right-hand * side and outputs are returned in the argument. * Requires opname_init to be defined in Lua. * * lua_ikopcall Sname, ... Calls a Lua opcode at i-rate and k-rate. Any number of * output and/or input arguments may be passed. * All arguments must be passed on the right-hand * side and outputs are returned in the argument. * Requires opname_init and opname_kontrol to be * defined in Lua. * * lua_iaopcall Sname, ... Calls a Lua opcode at i-rate and a-rate. Any number of * output and/or input arguments may be passed. * All arguments must be passed on the right-hand * side and outputs are returned in the argument. * Requires opname_init and opname_audio to be defined * in Lua. * * Opcode that actually implements arbitrary Lua opcodes * by calling from Csound into Lua functions. * * Lua functions access elements of arguments as follows * (pointers to both scalars and arrays are dereferenced by the array * access operator): * ffi.cdef(' struct arguments_t { double *a_out, double *i_in, * double *i_txt, double *f_sig };'); * local arguments = ffi.cast("struct arguments_t *", carguments_lightuserdata) * for i = 0, ksmps -1 do begin carguments.a_out[i] = carguments.i_in[0] * 3 * end end */ class cslua_opcall: public OpcodeBase { public: MYFLT *opcodename_; /** * This will hold, slot by slot, first output parameters * and then input parameters, exactly as declared by intypes and outtypes. * These parameters must also be re-declared in the Lua code as a C struct * using FFI (i.e. using 'ffi.cdef("typedef xxx typename;")' and * 'ctype = ffi.typeof("typename"))' and accessed using FFI in Lua code * after performing a type cast (i.e.using 'cobject = ffi.cast(ctype, * lightuserdata)'). Each slot, in turn, will contain a pointer to MYFLT * that references a Csound argument type (i.e. string, i-rate or k-rate * scalar, a-rate vector, f-sig). Note that the C struct may contain * additional data, e.g. for opcode state, after the opcode output and * input arguments, as limited by the available space. */ MYFLT *arguments[1000]; const char *opcodename; public: /** * Calls a Lua function with the signature: * opcodename_init(csound [lightuserdata], * opcode [lightyserdata], * parameters [lightuserdata]) -> result [number]. */ int init(CSOUND *csound) { int result = OK; opcodename = ((STRINGDAT *)opcodename_)->data; lua_State *L = manageLuaState(csound, 'O'); keys_t &keys = manageLuaReferenceKeys(csound, L, opcodename, 'O'); lua_rawgeti(L, LUA_REGISTRYINDEX, keys.init_key); lua_pushlightuserdata(L, csound); lua_pushlightuserdata(L, this); lua_pushlightuserdata(L, &arguments); if (lua_pcall(L, 3, 1, 0) != 0) { log(csound, "Lua error in \"%s_init\": %s.\n", opcodename, lua_tostring(L, -1)); } result = lua_tonumber(L, -1); lua_pop(L, 1); return OK; } int kontrol(CSOUND *csound) { int result = OK; lua_State *L = manageLuaState(csound, 'O'); keys_t &keys = manageLuaReferenceKeys(csound, L, opcodename, 'O'); lua_rawgeti(L, LUA_REGISTRYINDEX, keys.kontrol_key); lua_pushlightuserdata(L, csound); lua_pushlightuserdata(L, this); lua_pushlightuserdata(L, &arguments); if (lua_pcall(L, 3, 1, 0) != 0) { log(csound, "Lua error in \"%s_kontrol\": %s.\n", opcodename, lua_tostring(L, -1)); } result = lua_tonumber(L, -1); lua_pop(L, 1); return result; } int audio(CSOUND *csound) { int result = OK; lua_State *L = manageLuaState(csound, 'O'); keys_t &keys = manageLuaReferenceKeys(csound, L, opcodename, 'O'); lua_rawgeti(L, LUA_REGISTRYINDEX, keys.audio_key); lua_pushlightuserdata(L, csound); lua_pushlightuserdata(L, this); lua_pushlightuserdata(L, arguments); if (lua_pcall(L, 3, 1, 0) != 0) { log(csound, "Lua error in \"%s_audio\": %s.\n", opcodename, lua_tostring(L, -1)); } result = lua_tonumber(L, -1); lua_pop(L, 1); return result; } }; /** * lua_iopcall_off Sname, ... Calls a Lua opcode at i-rate only. Any number of * output and/or input arguments may be passed. * All arguments must be passed on the right-hand * side and outputs are returned in the argument. * Requires opname_init to be defined in Lua. * * lua_ikopcall_off Sname, ... Calls a Lua opcode at i-rate and k-rate. Any * number of output and/or input arguments may be * passed. * All arguments must be passed on the right-hand * side and outputs are returned in the argument. * Requires opname_init and opname_kontrol to be * defined in Lua. * * lua_iaopcall_off Sname, ... Calls a Lua opcode at i-rate and a-rate. Any * number of output and/or input arguments may be * passed. * All arguments must be passed on the right-hand * side and outputs are returned in the argument. * Requires opname_init and opname_audio to be * defined in Lua. * * Opcode that actually implements arbitrary Lua opcodes * by calling from Csound into Lua functions; this variant * of the opcode always schedules a "note off" event that is called * when the intrument instances is removed from the active list, and * which can be used to release unneeded resources, reschedule the * instrument with a reverb tail, and so on. * * Lua functions access elements of arguments as follows * (pointers to both scalars and arrays are dereferenced by the array * access operator): * ffi.cdef(' struct arguments_t { double *a_out, double *i_in, * double *i_txt, double *f_sig };'); * local arguments = ffi.cast("struct arguments_t *", carguments_lightuserdata) * for i = 0, ksmps -1 do begin carguments.a_out[i] = carguments.i_in[0] * 3 * end end */ class cslua_opcall_off: public OpcodeNoteoffBase { public: MYFLT *opcodename_; /** * This will hold, slot by slot, first output parameters * and then input parameters, exactly as declared by intypes and outtypes. * These parameters must also be re-declared in the Lua code as a C struct * using FFI (i.e. using 'ffi.cdef("typedef xxx typename;")' and * 'ctype = ffi.typeof("typename"))' and accessed using FFI in Lua code * after performing a type cast (i.e.using 'cobject = ffi.cast(ctype, * lightuserdata)'). Each slot, in turn, will contain a pointer to MYFLT * that references a Csound argument type (i.e. string, i-rate or k-rate * scalar, a-rate vector, f-sig). Note that the C struct may contain * additional data, e.g. for opcode state, after the opcode output and * input arguments, as limited by the available space. */ MYFLT *arguments[1000]; const char *opcodename; public: /** * Calls a Lua function with the signature: * opcodename_init(csound [lightuserdata], * opcode [lightyserdata], * parameters [lightuserdata]) -> result [number]. */ int init(CSOUND *csound) { int result = OK; opcodename = ((STRINGDAT *)opcodename_)->data; lua_State *L = manageLuaState(csound, 'O'); keys_t &keys = manageLuaReferenceKeys(csound, L, opcodename, 'O'); lua_rawgeti(L, LUA_REGISTRYINDEX, keys.init_key); lua_pushlightuserdata(L, csound); lua_pushlightuserdata(L, this); lua_pushlightuserdata(L, &arguments); if (lua_pcall(L, 3, 1, 0) != 0) { log(csound, "Lua error in \"%s_init\": %s.\n", opcodename, lua_tostring(L, -1)); } result = lua_tonumber(L, -1); lua_pop(L, 1); return OK; } int kontrol(CSOUND *csound) { int result = OK; lua_State *L = manageLuaState(csound, 'O'); keys_t &keys = manageLuaReferenceKeys(csound, L, opcodename, 'O'); lua_rawgeti(L, LUA_REGISTRYINDEX, keys.kontrol_key); lua_pushlightuserdata(L, csound); lua_pushlightuserdata(L, this); lua_pushlightuserdata(L, &arguments); if (lua_pcall(L, 3, 1, 0) != 0) { log(csound, "Lua error in \"%s_kontrol\": %s.\n", opcodename, lua_tostring(L, -1)); } result = lua_tonumber(L, -1); lua_pop(L, 1); return result; } int audio(CSOUND *csound) { int result = OK; lua_State *L = manageLuaState(csound, 'O'); keys_t &keys = manageLuaReferenceKeys(csound, L, opcodename, 'O'); lua_rawgeti(L, LUA_REGISTRYINDEX, keys.audio_key); lua_pushlightuserdata(L, csound); lua_pushlightuserdata(L, this); lua_pushlightuserdata(L, arguments); if (lua_pcall(L, 3, 1, 0) != 0) { log(csound, "Lua error in \"%s_audio\": %s.\n", opcodename, lua_tostring(L, -1)); } result = lua_tonumber(L, -1); lua_pop(L, 1); return result; } int noteoff(CSOUND *csound) { int result = OK; lua_State *L = manageLuaState(csound, 'O'); keys_t &keys = manageLuaReferenceKeys(csound, L, opcodename, 'O'); lua_rawgeti(L, LUA_REGISTRYINDEX, keys.noteoff_key); lua_pushlightuserdata(L, csound); lua_pushlightuserdata(L, this); lua_pushlightuserdata(L, arguments); if (lua_pcall(L, 3, 1, 0) != 0) { log(csound, "Lua error in \"%s_noteoff\": %s.\n", opcodename, lua_tostring(L, -1)); } else { log(csound, "Lua called \"%s_noteoff\": %s.\n", opcodename, lua_tostring(L, -1)); } result = lua_tonumber(L, -1); lua_pop(L, 1); return result; } }; /** * lua_opdef Sname, Scode -- Define an opcode in Lua at i-rate. The opcode can * take any number of output and/or input arguments * of any type. * * Opcode that effectively defines new opcodes in Lua. The Lua code must * define all functions that will be called from Csound, * using the following naming convention, where opcodename * stands for the actual opcode name: *
    *
  • opcodename_init for the i-rate opcode subroutine. *
  • opcodename_kontrol for the k-rate opcode subroutine. *
  • opcodename_audio for the a-rate opcode subroutine. *
  • opcodename_noteoff for the note-off subroutine. *
* Each of these Lua functions will receive three lightuserdata * (i.e. pointer) arguments: the CSOUND object, the opcode instance, * and a pointer to the opcode arguments, which the Lua code must type cast * to a LuaJIT FFI ctype structure containing the opcode output arguments, * input arguments, and state variables. Using LuaJIT FFI, the elements of * this structure will be accessible as though they were Lua types. * * Each of these Lua functions must return 0 for success * or 1 for failure. * * The Lua functions may do absolutely anything, although of * course if real-time performance is expected, care must be * taken to disable Lua garbage collection and observe other * recommendations for real-time code. */ class cslua_opdef : public OpcodeBase { public: /** * No outputs. */ /** * Inputs. */ MYFLT *opcodename_; MYFLT *luacode_; public: int init(CSOUND *csound) { int result = OK; lua_State *L = manageLuaState(csound, 'O'); /* Ensure that Csound is available in the global environment. */ lua_pushlightuserdata(L, csound); lua_setfield(L, LUA_GLOBALSINDEX, "csound"); const char *opcodename = ((STRINGDAT *)opcodename_)->data; const char *luacode = ((STRINGDAT *)luacode_)->data; //log(csound, "Executing Lua code:\n%s\n", luacode); result = luaL_dostring(L, luacode); if (result == 0) { keys_t &keys = manageLuaReferenceKeys(csound, L, opcodename, 'O'); log(csound, "Opcode: %s\n", opcodename); log(csound, "Result: %d\n", result); char init_function[0x100]; snprintf(init_function, 0x100, "%s_init", opcodename); //h.optext->t.opcod); lua_getglobal(L, init_function); if (!lua_isnil(L, 1)) { keys.init_key = luaL_ref(L, LUA_REGISTRYINDEX); lua_pop(L, 1); } char kontrol_function[0x100]; snprintf(kontrol_function, 0x100, "%s_kontrol", opcodename); //h.optext->t.opcod); lua_getglobal(L, kontrol_function); if (!lua_isnil(L, 1)) { keys.kontrol_key = luaL_ref(L, LUA_REGISTRYINDEX); lua_pop(L, 1); } char audio_function[0x100]; snprintf(audio_function, 0x100, "%s_audio", opcodename); //h.optext->t.opcod); lua_getglobal(L, audio_function); if (!lua_isnil(L, 1)) { keys.audio_key = luaL_ref(L, LUA_REGISTRYINDEX); lua_pop(L, 1); } char noteoff_function[0x100]; snprintf(noteoff_function, 0x100, "%s_noteoff", opcodename); //h.optext->t.opcod); lua_getglobal(L, noteoff_function); if (!lua_isnil(L, 1)) { keys.noteoff_key = luaL_ref(L, LUA_REGISTRYINDEX); lua_pop(L, 1); } } else { log(csound, "luaL_dostring failed with: %d\n", result); } return result; } }; extern "C" { /** * The only difference between the luacall opcodes is the "thread" * defining when they are called, which has exactly the same meaning as * for a C opcode. The user must take care to define, in Lua, the opcode * routines required by that specific "thread." */ OENTRY oentries[] = { { (char *)"lua_exec", sizeof(cslua_exec), 0, 1, (char *)"", (char *)"TNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN" "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN" "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN" "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", (SUBR) cslua_exec::init_, (SUBR) 0, (SUBR) 0, }, { (char *)"lua_iopcall", sizeof(cslua_opcall), 0, 1, (char *)"", (char *)"TNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN" "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN" "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN" "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", (SUBR) cslua_opcall::init_, (SUBR) 0, (SUBR) 0, }, { (char *)"lua_ikopcall", sizeof(cslua_opcall), 0, 3, (char *)"", (char *)"TNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN" "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN" "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN" "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", (SUBR) cslua_opcall::init_, (SUBR) cslua_opcall::kontrol_, (SUBR) 0, }, { (char *)"lua_iaopcall", sizeof(cslua_opcall), 0, 5, (char *)"", (char *)"TNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN" "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN" "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN" "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", (SUBR) cslua_opcall::init_, (SUBR) 0, (SUBR) cslua_opcall::audio_, }, { (char *)"lua_iopcall_off", sizeof(cslua_opcall_off), 0, 1, (char *)"", (char *)"TNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN" "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN" "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN" "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", (SUBR) cslua_opcall_off::init_, (SUBR) 0, (SUBR) 0, }, { (char *)"lua_ikopcall_off", sizeof(cslua_opcall_off), 0, 3, (char *)"", (char *)"TNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN" "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN" "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN" "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", (SUBR) cslua_opcall_off::init_, (SUBR) cslua_opcall_off::kontrol_, (SUBR) 0, }, { (char *)"lua_iaopcall_off", sizeof(cslua_opcall_off), 0, 5, (char *)"", (char *)"TNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN" "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN" "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN" "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", (SUBR) cslua_opcall_off::init_, (SUBR) 0, (SUBR) cslua_opcall_off::audio_, }, { (char *)"lua_opdef", sizeof(cslua_opdef), 0, 1, // No outputs. (char *)"", // Inputs: name and Lua code. // The Lua code will usually be a multi-line string. (char *)"TT", (SUBR) cslua_opdef::init_, 0, 0, }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; PUBLIC int csoundModuleCreate(CSOUND *csound) { void *lua_states_mutex = csound->Create_Mutex(0); csound::CreateGlobalPointer(csound, "lua_states_mutex", lua_states_mutex); std::vector *luaStatesForThreads = new std::vector; csound::CreateGlobalPointer(csound, "luaStatesForThreads", luaStatesForThreads); void *reference_keys_mutex = csound->Create_Mutex(0); csound::CreateGlobalPointer(csound, "reference_keys_mutex", reference_keys_mutex); std::map > *luaReferenceKeys = new std::map >; csound::CreateGlobalPointer(csound, "luaReferenceKeys", luaReferenceKeys); return 0; } PUBLIC int csoundModuleInit(CSOUND *csound) { int status = 0; for (OENTRY *oentry = &oentries[0]; oentry->opname; oentry++) { status |= csound->AppendOpcode(csound, oentry->opname, oentry->dsblksiz, oentry->flags, oentry->thread, oentry->outypes, oentry->intypes, (int (*)(CSOUND *,void *)) oentry->iopadr, (int (*)(CSOUND *,void *)) oentry->kopadr, (int (*)(CSOUND *,void *)) oentry->aopadr); } manageLuaState(csound, 'O'); return status; } PUBLIC int csoundModuleDestroy(CSOUND *csound) { void *lua_states_mutex = 0; csound::QueryGlobalPointer(csound, "lua_states_mutex", lua_states_mutex); if (lua_states_mutex != 0) { csound->LockMutex(lua_states_mutex); std::vector *luaStatesForThreads = 0; csound::QueryGlobalPointer(csound, "luaStatesForThreads", luaStatesForThreads); if (luaStatesForThreads != 0) { for (std::vector::iterator it = luaStatesForThreads->begin(); it != luaStatesForThreads->end(); ++it) { lua_close(it->L); } } luaStatesForThreads->clear(); csound::DestroyGlobalPointer(csound, "luaStatesForThreads", luaStatesForThreads); csound->UnlockMutex(lua_states_mutex); csound->DestroyMutex(lua_states_mutex); csound::DestroyGlobalPointer(csound, "lua_states_mutex"); lua_states_mutex = 0; } void *reference_keys_mutex = 0; QueryGlobalPointer(csound, "reference_keys_mutex", reference_keys_mutex); if (reference_keys_mutex != 0) { csound->LockMutex(reference_keys_mutex); std::map > *luaReferenceKeys = 0; QueryGlobalPointer(csound, "luaReferenceKeys", luaReferenceKeys); if (luaReferenceKeys != 0) { luaReferenceKeys->clear(); csound::DestroyGlobalPointer (csound, "luaReferenceKeys", luaReferenceKeys); } csound->UnlockMutex(reference_keys_mutex); csound->DestroyMutex(reference_keys_mutex); csound::DestroyGlobalPointer(csound, "reference_keys_mutex"); reference_keys_mutex = 0; } return OK; } } csound-6.10.0/Opcodes/OSC.c000066400000000000000000000746651321653344700153070ustar00rootroot00000000000000/* OSC.c: Copyright (C) 2005 by John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csdl.h" #include #include #ifdef HAVE_UNISTD_H #include #endif #include #include //#define OSC_DEBUG /* structure for real time event */ /* typedef struct rtEvt_s { */ /* struct rtEvt_s *nxt; */ /* EVTBLK e; */ /* } rtEvt_t; */ typedef struct { OPDS h; /* default header */ MYFLT *kwhen; STRINGDAT *host; MYFLT *port; /* UDP port */ STRINGDAT *dest; STRINGDAT *type; MYFLT *arg[32]; /* only 26 can be used, but add a few more for safety */ lo_address addr; MYFLT last; char *lhost; int cnt; int multicast; CSOUND *csound; void *thread; MYFLT lasta; } OSCSEND; typedef struct osc_pat { struct osc_pat *next; union { MYFLT number; STRINGDAT string; void *blob; } args[31]; } OSC_PAT; typedef struct { lo_server_thread thread; CSOUND *csound; void *mutex_; void *oplst; /* list of opcodes listening on this port */ } OSC_PORT; /* structure for global variables */ typedef struct { CSOUND *csound; /* for OSCinit/OSClisten */ int nPorts; OSC_PORT *ports; } OSC_GLOBALS; /* opcode for starting the OSC listener (called once from orchestra header) */ typedef struct { OPDS h; /* default header */ MYFLT *ihandle; MYFLT *port; /* Port number on which to listen */ } OSCINIT; typedef struct { OPDS h; /* default header */ MYFLT *ihandle; STRINGDAT *group; MYFLT *port; /* Port number on which to listen */ } OSCINITM; typedef struct { OPDS h; /* default header */ MYFLT *kans; MYFLT *ihandle; STRINGDAT *dest; STRINGDAT *type; MYFLT *args[32]; OSC_PORT *port; char *saved_path; char saved_types[32]; /* copy of type list */ OSC_PAT *patterns; /* FIFO list of pending messages */ OSC_PAT *freePatterns; /* free message stack */ void *nxt; /* pointer to next opcode on the same port */ } OSCLISTEN; static int oscsend_deinit(CSOUND *csound, OSCSEND *p) { lo_address a = (lo_address)p->addr; if (LIKELY(a != NULL)) lo_address_free(a); p->addr = NULL; csound->Free(csound, p->lhost); return OK; } static int osc_send_set(CSOUND *csound, OSCSEND *p) { char port[8]; char *pp = port; char *hh; //unsigned int i; /* with too many args, XINCODE may not work correctly */ if (UNLIKELY(p->INOCOUNT > 31)) return csound->InitError(csound, Str("Too many arguments to OSCsend")); /* a-rate arguments are not allowed */ /* for (i = 0; i < p->INOCOUNT-5; i++) { */ /* if (strcmp("a", csound->GetTypeForArg(p->arg[i])->varTypeName) == 0) { */ /* return csound->InitError(csound, Str("No a-rate arguments allowed")); */ /* } */ /* } */ if (*p->port<0) pp = NULL; else snprintf(port, 8, "%d", (int) MYFLT2LRND(*p->port)); hh = (char*) p->host->data; if (UNLIKELY(*hh=='\0')) { hh = NULL; p->lhost = csound->Strdup(csound, "localhost"); } else p->lhost = csound->Strdup(csound, hh); if (hh && isdigit(*hh)) { int n = atoi(hh); p->multicast = (n>=224 && n<=239); } else p->multicast = 0; //printf("multicast=%d\n", p->multicast); p->addr = lo_address_new(hh, pp); // MKG: Seems to have been dropped from liblo. // But TTL 1 should be the default for multicast. if (UNLIKELY(p->multicast)) lo_address_set_ttl(p->addr, 1); p->cnt = 0; p->last = 0; csound->RegisterDeinitCallback(csound, p, (int (*)(CSOUND *, void *)) oscsend_deinit); p->thread = NULL; return OK; } static int osc_send(CSOUND *csound, OSCSEND *p) { /* Types I allow at present: 0) int 1) float 2) string 3) double 4) char 5) table as blob */ char port[8]; char *pp = port; char *hh; int cmpr = 0; if (UNLIKELY(*p->port<0)) pp = NULL; else snprintf(port, 8, "%d", (int) MYFLT2LRND(*p->port)); hh = (char*) p->host->data; if (UNLIKELY(*hh=='\0')) hh = NULL; /* can this be done at init time? It was note that this could be creating a latency penalty Yes; cached -- JPff */ // 152269 //if (!(hh==NULL && p->lhost == NULL) || strcmp(p->lhost, hh)!=0) { if (p->thread == NULL) { if (hh && p->lhost) cmpr = strcmp(p->lhost, hh); if (!(hh==NULL && p->lhost == NULL) || cmpr !=0) { if (p->addr != NULL) lo_address_free(p->addr); p->addr = lo_address_new(hh, pp); // MKG: This seems to have been dropped from liblo. // if (p->multicast) lo_address_set_ttl(p->addr, 2); if (UNLIKELY(p->multicast)) { u_char ttl = 2; #if defined(LINUX) if (UNLIKELY(setsockopt((long)p->addr, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl))==-1)) { csound->Message(csound, Str("Failed to set multicast")); } #else setsockopt((int)p->addr, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)); #endif } csound->Free(csound, p->lhost); if (hh) p->lhost = csound->Strdup(csound, hh); else p->lhost = NULL; } } if (p->cnt++ ==0 || *p->kwhen!=p->last) { int i=0; int msk = 0x20; /* First argument */ lo_message msg = lo_message_new(); char *type = (char*)p->type->data; MYFLT **arg = p->arg; p->last = *p->kwhen; for (i=0; type[i]!='\0'; i++, msk <<=1) { /* Need to add type checks */ switch (type[i]) { case 'i': lo_message_add_int32(msg, (int32_t) MYFLT2LRND(*arg[i])); break; case 'l': case 'h': lo_message_add_int64(msg, (int64_t) MYFLT2LRND(*arg[i])); break; case 'c': lo_message_add_char(msg, (char) (*arg[i] + FL(0.5))); break; case 'm': { union a { int32_t x; uint8_t m[4]; } mm; mm.x = *arg[i]+FL(0.5); lo_message_add_midi(msg, mm.m); break; } case 'f': lo_message_add_float(msg, (float)(*arg[i])); break; case 'd': lo_message_add_double(msg, (double)(*arg[i])); break; case 's': lo_message_add_string(msg, ((STRINGDAT *)arg[i])->data); break; case 'b': /* Boolean */ if (*arg[i]==FL(0.0)) lo_message_add_true(msg); else lo_message_add_false(msg); break; case 't': /* timestamp */ { lo_timetag tt; tt.sec = (uint32_t)(*arg[i]+FL(0.5)); msk <<= 1; i++; if (UNLIKELY(type[i]!='t')) return csound->PerfError(csound, p->h.insdshead, Str("Time stamp is two values")); tt.frac = (uint32_t)(*arg[i]+FL(0.5)); lo_message_add_timetag(msg, tt); break; } //#ifdef SOMEFINEDAY case 'G': /* fGen Table/blob */ { lo_blob myblob; int len, olen; FUNC *ftp; void *data; /* make sure fn exists */ if (LIKELY((ftp=csound->FTnp2Find(csound,arg[i]))!=NULL)) { len = ftp->flen; /* and set it up */ data = csound->Malloc(csound, olen=/*sizeof(FUNC)-sizeof(MYFLT*)+*/ sizeof(MYFLT)*len); // memcpy(data, ftp, sizeof(FUNC)-sizeof(MYFLT*)); memcpy(data/*+sizeof(FUNC)-sizeof(MYFLT*)*/, ftp->ftable, sizeof(MYFLT)*len); } else { return csound->PerfError(csound, p->h.insdshead, Str("ftable %.2f does not exist"), *arg[i]); } myblob = lo_blob_new(olen, data); lo_message_add_blob(msg, myblob); csound->Free(csound, data); lo_blob_free(myblob); break; } //#endif case 'a': /* Audio as blob */ { lo_blob myblob; MYFLT *data = csound->Malloc(csound, sizeof(MYFLT)*(CS_KSMPS+1)); data[0] = CS_KSMPS; memcpy(&data[1], arg[i], data[0]); myblob = lo_blob_new(sizeof(MYFLT)*(CS_KSMPS+1), data); lo_message_add_blob(msg, myblob); csound->Free(csound, data); lo_blob_free(myblob); break; } case 'A': /* Array/blob */ { lo_blob myblob; int len = 1; ARRAYDAT *ss; /* make sure fn exists */ if (LIKELY((ss = (ARRAYDAT*)arg[i]) !=NULL && ss->data != NULL)) { int j, d; for (j=0,d=ss->dimensions; d>0; j++, d--) len *= ss->sizes[j]; len *= sizeof(MYFLT); } else { return csound->PerfError(csound, p->h.insdshead, Str("argument %d is not an array"), i); } // two parts needed { void *dd = csound->Malloc(csound, len+sizeof(int)*(1+ss->dimensions)); memcpy(dd, &ss->dimensions, sizeof(int)); memcpy((char*)dd+sizeof(int), ss->sizes, sizeof(int)*ss->dimensions); memcpy((char*)dd+sizeof(int)*(1+ss->dimensions), ss->data, len); /* printf("dd length = %d dimensions = %d, %d %d %.8x %.8x %.8x %.8x\n", */ /* len+sizeof(int)*(1+ss->dimensions), ss->dimensions, */ /* ((int*)dd)[0], ((int*)dd)[1], ((int*)dd)[2], ((int*)dd)[3], */ /* ((int*)dd)[4], ((int*)dd)[5]); */ myblob = lo_blob_new(len, dd); csound->Free(csound, dd); } lo_message_add_blob(msg, myblob); lo_blob_free(myblob); break; } case 'S': csound->Warning(csound, "S unimplemented"); break; //#endif default: csound->Warning(csound, Str("Unknown OSC type %c\n"), type[1]); } } lo_send_message(p->addr, (char*)p->dest->data, msg); lo_message_free(msg); } return OK; } /* RESET routine for cleaning up */ static int OSC_reset(CSOUND *csound, OSC_GLOBALS *p) { int i; for (i = 0; i < p->nPorts; i++) if (p->ports[i].thread) { lo_server_thread_stop(p->ports[i].thread); lo_server_thread_free(p->ports[i].thread); csound->DestroyMutex(p->ports[i].mutex_); } csound->DestroyGlobalVariable(csound, "_OSC_globals"); return OK; } uintptr_t OSCthread(void *pp) { OSCSEND *p = (OSCSEND *) pp; osc_send(p->csound, p); return 0; } /* static int osc_send_async_set(CSOUND *csound, OSCSEND *p) { */ /* p->csound = csound; */ /* return osc_send_set(csound, p); */ /* } */ /* static int osc_send_async(CSOUND *csound, OSCSEND *p) { */ /* /\*RTCLOCK t; */ /* csound->InitTimerStruct(&t);*\/ */ /* if (*p->kwhen != p->lasta) { */ /* if (p->thread != NULL) { */ /* csound->JoinThread(p->thread); */ /* p->thread = NULL; */ /* } */ /* p->thread = csound->CreateThread(OSCthread, p); */ /* p->lasta = *p->kwhen; */ /* } */ /* // printf("wait: %.13f \n", (csound->GetRealTime(&t))*1000.); */ /* return OK; */ /* } */ /* get pointer to globals structure, allocating it on the first call */ static CS_NOINLINE OSC_GLOBALS *alloc_globals(CSOUND *csound) { OSC_GLOBALS *pp; pp = (OSC_GLOBALS*) csound->QueryGlobalVariable(csound, "_OSC_globals"); if (pp != NULL) return pp; if (UNLIKELY(csound->CreateGlobalVariable(csound, "_OSC_globals", sizeof(OSC_GLOBALS)) != 0)){ csound->ErrorMsg(csound, Str("OSC: failed to allocate globals")); return NULL; } pp = (OSC_GLOBALS*) csound->QueryGlobalVariable(csound, "_OSC_globals"); pp->csound = csound; csound->RegisterResetCallback(csound, (void*) pp, (int (*)(CSOUND *, void *)) OSC_reset); return pp; } /* ------------------------------------------------------------------------ */ static CS_NOINLINE OSC_PAT *alloc_pattern(OSCLISTEN *pp) { CSOUND *csound; OSC_PAT *p; size_t nbytes; csound = pp->h.insdshead->csound; /* number of bytes to allocate */ nbytes = sizeof(OSC_PAT); /* allocate and initialise structure */ p = (OSC_PAT*) csound->Calloc(csound, nbytes); return p; } static inline OSC_PAT *get_pattern(OSCLISTEN *pp) { OSC_PAT *p; if (pp->freePatterns != NULL) { p = pp->freePatterns; pp->freePatterns = p->next; return p; } return alloc_pattern(pp); } static int OSC_handler(const char *path, const char *types, lo_arg **argv, int argc, void *data, void *p) { OSC_PORT *pp = (OSC_PORT*) p; OSCLISTEN *o; CSOUND *csound = (CSOUND *) pp->csound; int retval = 1; pp->csound->LockMutex(pp->mutex_); o = (OSCLISTEN*) pp->oplst; //printf("opst=%p\n", o); while (o != NULL) { //printf("Looking at %s/%s against %s/%s\n", // o->saved_path, path,o->saved_types, types); if (strcmp(o->saved_path, path) == 0 && strcmp(o->saved_types, types) == 0) { /* Message is for this guy */ int i; OSC_PAT *m; //printf("handler found message\n"); m = get_pattern(o); if (m != NULL) { /* queue message for being read by OSClisten opcode */ m->next = NULL; if (o->patterns == NULL) o->patterns = m; else { OSC_PAT *mm; for (mm = o->patterns; mm->next != NULL; mm = mm->next) ; mm->next = m; } /* copy argument list */ for (i = 0; o->saved_types[i] != '\0'; i++) { switch (types[i]) { default: /* Should not happen */ case 'i': m->args[i].number = (MYFLT) argv[i]->i; break; case 'h': m->args[i].number = (MYFLT) argv[i]->i64; break; case 'c': m->args[i].number= (MYFLT) argv[i]->c; break; case 'f': m->args[i].number = (MYFLT) argv[i]->f; break; case 'd': m->args[i].number= (MYFLT) argv[i]->d; break; case 's': { // ***NO CHECK THAT m->args[i] IS A STRING char *src = (char*) &(argv[i]->s), *dst = m->args[i].string.data; if (m->args[i].string.size <= (int) strlen(src)) { if (dst != NULL) csound->Free(csound, dst); dst = csound->Strdup(csound, src); // who sets m->args[i].string.size ?? m->args[i].string.data = dst; m->args[i].string.size = strlen(dst)+1; } else strcpy(dst, src); break; } case 'b': { int len = lo_blobsize((lo_blob*)argv[i]); m->args[i].blob = csound->Malloc(csound,len); memcpy(m->args[i].blob, argv[i], len); #ifdef OSC_DEBUG { lo_blob *bb = (lo_blob*)m->args[i].blob; int size = lo_blob_datasize(bb); MYFLT *data = lo_blob_dataptr(bb); int *idata = (int*)data; printf("size=%d data=%.8x %.8x ...\n",size, idata[0], idata[1]); } #endif } } } retval = 0; } break; } o = (OSCLISTEN*) o->nxt; } pp->csound->UnlockMutex(pp->mutex_); return retval; } static void OSC_error(int num, const char *msg, const char *path) { fprintf(stderr, "OSC server error %d in path %s: %s\n", num, path, msg); } static int OSC_deinit(CSOUND *csound, OSCINIT *p) { int n = (int)*p->ihandle; OSC_GLOBALS *pp = alloc_globals(csound); OSC_PORT *ports; if (UNLIKELY(pp==NULL)) return NOTOK; ports = pp->ports; csound->Message(csound, "handle=%d\n", n); csound->DestroyMutex(ports[n].mutex_); ports[n].mutex_ = NULL; lo_server_thread_stop(ports[n].thread); lo_server_thread_free(ports[n].thread); ports[n].thread = NULL; csound->Message(csound, Str("OSC deinitiatised\n")); return OK; } static int osc_listener_init(CSOUND *csound, OSCINIT *p) { OSC_GLOBALS *pp; OSC_PORT *ports; char buff[32]; int n; /* allocate and initialise the globals structure */ pp = alloc_globals(csound); n = pp->nPorts; ports = (OSC_PORT*) csound->ReAlloc(csound, pp->ports, sizeof(OSC_PORT) * (n + 1)); ports[n].csound = csound; ports[n].mutex_ = csound->Create_Mutex(0); ports[n].oplst = NULL; snprintf(buff, 32, "%d", (int) *(p->port)); ports[n].thread = lo_server_thread_new(buff, OSC_error); if (UNLIKELY(ports[n].thread==NULL)) return csound->InitError(csound, Str("cannot start OSC listener on port %s\n"), buff); ///if (lo_server_thread_start(ports[n].thread)<0) /// return csound->InitError(csound, /// Str("cannot start OSC listener on port %s\n"), /// buff); lo_server_thread_start(ports[n].thread); pp->ports = ports; pp->nPorts = n + 1; csound->Warning(csound, Str("OSC listener #%d started on port %s\n"), n, buff); *(p->ihandle) = (MYFLT) n; csound->RegisterDeinitCallback(csound, p, (int (*)(CSOUND *, void *)) OSC_deinit); return OK; } static int osc_listener_initMulti(CSOUND *csound, OSCINITM *p) { OSC_GLOBALS *pp; OSC_PORT *ports; char buff[32]; int n; /* allocate and initialise the globals structure */ pp = alloc_globals(csound); n = pp->nPorts; ports = (OSC_PORT*) csound->ReAlloc(csound, pp->ports, sizeof(OSC_PORT) * (n + 1)); ports[n].csound = csound; ports[n].mutex_ = csound->Create_Mutex(0); ports[n].oplst = NULL; snprintf(buff, 32, "%d", (int) *(p->port)); ports[n].thread = lo_server_thread_new_multicast(p->group->data, buff, OSC_error); if (UNLIKELY(ports[n].thread==NULL)) return csound->InitError(csound, Str("cannot start OSC listener on port %s\n"), buff); ///if (lo_server_thread_start(ports[n].thread)<0) /// return csound->InitError(csound, /// Str("cannot start OSC listener on port %s\n"), /// buff); lo_server_thread_start(ports[n].thread); pp->ports = ports; pp->nPorts = n + 1; csound->Warning(csound, Str("OSC multicast listener #%d started on port %s\n"), n, buff); *(p->ihandle) = (MYFLT) n; csound->RegisterDeinitCallback(csound, p, (int (*)(CSOUND *, void *)) OSC_deinit); return OK; } static int OSC_listdeinit(CSOUND *csound, OSCLISTEN *p) { OSC_PAT *m; if (p->port->mutex_==NULL) return NOTOK; csound->LockMutex(p->port->mutex_); if (p->port->oplst == (void*) p) p->port->oplst = p->nxt; else { OSCLISTEN *o = (OSCLISTEN*) p->port->oplst; for ( ; o->nxt != (void*) p; o = (OSCLISTEN*) o->nxt) ; o->nxt = p->nxt; } csound->UnlockMutex(p->port->mutex_); lo_server_thread_del_method(p->port->thread, p->saved_path, p->saved_types); csound->Free(csound, p->saved_path); p->saved_path = NULL; p->nxt = NULL; m = p->patterns; p->patterns = NULL; while (m != NULL) { OSC_PAT *mm = m->next; csound->Free(csound, m); m = mm; } m = p->freePatterns; p->freePatterns = NULL; while (m != NULL) { OSC_PAT *mm = m->next; csound->Free(csound, m); m = mm; } return OK; } static int OSC_list_init(CSOUND *csound, OSCLISTEN *p) { //void *x; int i, n; OSC_GLOBALS *pp = (OSC_GLOBALS*) csound->QueryGlobalVariable(csound, "_OSC_globals"); if (UNLIKELY(pp == NULL)) return csound->InitError(csound, Str("OSC not running")); /* find port */ n = (int) *(p->ihandle); if (UNLIKELY(n < 0 || n >= pp->nPorts)) return csound->InitError(csound, Str("invalid handle")); p->port = &(pp->ports[n]); p->saved_path = (char*) csound->Malloc(csound, strlen((char*) p->dest->data) + 1); strcpy(p->saved_path, (char*) p->dest->data); /* check for a valid argument list */ n = csound->GetInputArgCnt(p) - 3; if (UNLIKELY(n < 1 || n > 28)) return csound->InitError(csound, Str("invalid number of arguments")); if (UNLIKELY((int) strlen((char*) p->type->data) != n)) return csound->InitError(csound, Str("argument list inconsistent with " "format string")); strcpy(p->saved_types, (char*) p->type->data); for (i = 0; i < n; i++) { const char *s; s = csound->GetInputArgName(p, i + 3); if (s[0] == 'g') s++; switch (p->saved_types[i]) { case 'G': case 'A': case 'D': case 'a': case 'S': p->saved_types[i] = 'b'; break; case 'c': case 'd': case 'f': case 'h': case 'i': if (UNLIKELY(*s != 'k')) return csound->InitError(csound, Str("argument list inconsistent " "with format string")); break; case 's': if (UNLIKELY(*s != 'S')) return csound->InitError(csound, Str("argument list inconsistent " "with format string")); break; default: return csound->InitError(csound, Str("invalid type")); } } csound->LockMutex(p->port->mutex_); p->nxt = p->port->oplst; p->port->oplst = (void*) p; csound->UnlockMutex(p->port->mutex_); (void) lo_server_thread_add_method(p->port->thread, p->saved_path, p->saved_types, OSC_handler, p->port); csound->RegisterDeinitCallback(csound, p, (int (*)(CSOUND *, void *)) OSC_listdeinit); return OK; } static int OSC_list(CSOUND *csound, OSCLISTEN *p) { OSC_PAT *m; /* quick check for empty queue */ if (p->patterns == NULL) { *p->kans = 0; return OK; } csound->LockMutex(p->port->mutex_); m = p->patterns; /* check again for thread safety */ if (m != NULL) { int i; /* unlink from queue */ p->patterns = m->next; /* copy arguments */ //printf("copying args\n"); for (i = 0; p->saved_types[i] != '\0'; i++) { //printf("%d: type %c\n", i, p->saved_types[i]); if (p->saved_types[i] == 's') { char *src = m->args[i].string.data; char *dst = ((STRINGDAT*) p->args[i])->data; if (src != NULL) { if (((STRINGDAT*) p->args[i])->size <= (int) strlen(src)){ if (dst != NULL) csound->Free(csound, dst); dst = csound->Strdup(csound, src); ((STRINGDAT*) p->args[i])->size = strlen(dst) + 1; ((STRINGDAT*) p->args[i])->data = dst; } else strcpy(dst, src); } } else if (p->saved_types[i]=='b') { char c = p->type->data[i]; int len = lo_blob_datasize(m->args[i].blob); //printf("blob found %p type %c\n", m->args[i].blob, c); //printf("length = %d\n", lo_blob_datasize(m->args[i].blob)); int *idata = lo_blob_dataptr(m->args[i].blob); if (c == 'D') { int j; MYFLT *data = (MYFLT *) idata; ARRAYDAT* arr = (ARRAYDAT*)p->args[i]; int asize = 1; for (j=0; j < arr->dimensions; j++) { asize *= arr->sizes[j]; } len /= sizeof(MYFLT); if (asize < len) { arr->data = (MYFLT *) csound->ReAlloc(csound, arr->data, len*sizeof(MYFLT)); asize = len; for (j = 0; j < arr->dimensions-1; j++) asize /= arr->sizes[j]; arr->sizes[arr->dimensions-1] = asize; } memcpy(arr->data,data,len*sizeof(MYFLT)); } else if (c == 'A') { /* Decode an numeric array */ int j; MYFLT* data = (MYFLT*)(&idata[1+idata[0]]); int size = 1; ARRAYDAT* foo = (ARRAYDAT*)p->args[i]; foo->dimensions = idata[0]; csound->Free(csound, foo->sizes); foo->sizes = (int*)csound->Malloc(csound, sizeof(int)*idata[0]); #ifdef OSC_DEBUG printf("dimension=%d\n", idata[0]); #endif for (j=0; jsizes[j] = idata[j+1]; #ifdef OSC_DEBUG printf("sizes[%d] = %d\n", j, idata[j+1]); #endif size*=idata[j+1]; } #ifdef OSC_DEBUG printf("idata = %i %i %i %i %i %i %i ...\n", idata[0], idata[1], idata[2], idata[3], idata[4], idata[5], idata[6]); printf("data = %f, %f, %f...\n", data[0], data[1], data[2]); #endif foo->data = (MYFLT*)csound->Malloc(csound, sizeof(MYFLT)*size); memcpy(foo->data, data, sizeof(MYFLT)*size); //printf("data = %f %f ...\n", foo->data[0], foo->data[1]); } else if (c == 'a') { MYFLT *data= (MYFLT*)idata; unsigned int len = (int)data[0]; if (len>CS_KSMPS) len = CS_KSMPS; memcpy(p->args[i], &data[1], len*sizeof(MYFLT)); } else if (c == 'G') { /* ftable received */ //FUNC* data = (FUNC*)idata; MYFLT *data = (MYFLT *) idata; int fno = MYFLT2LRND(*p->args[i]); FUNC *ftp; if (UNLIKELY(fno <= 0)) return csound->PerfError(csound, p->h.insdshead, Str("Invalid ftable no. %d"), fno); ftp = csound->FTnp2Find(csound, p->args[i]); if (UNLIKELY(ftp==NULL)) { return csound->PerfError(csound, p->h.insdshead, Str("OSC internal error")); } if (len > (int) (ftp->flen*sizeof(MYFLT))) ftp->ftable = (MYFLT*)csound->ReAlloc(csound, ftp->ftable, len*sizeof(MYFLT)); memcpy(ftp->ftable,data,len); #if 0 ftp = csound->FTFindP(csound, p->args[i]); if (UNLIKELY(ftp==NULL)) { // need to allocate ***FIXME*** return csound->PerfError(csound, p->h.insdshead, Str("OSC internal error")); } memcpy(ftp, data, sizeof(FUNC)-sizeof(MYFLT*)); ftp->fno = fno; #ifdef OSC_DEBUG printf("%d \n", len); #endif if (len > ftp->flen*sizeof(MYFLT)) ftp->ftable = (MYFLT*)csound->ReAlloc(csound, ftp->ftable, len-sizeof(FUNC)+sizeof(MYFLT*)); #endif { #ifdef OSC_DEBUG MYFLT* dst = ftp->ftable; MYFLT* src = (MYFLT*)(&(data->ftable)); //int j; printf("copy data: from %p to %p length %d %d\n", src, dst, len-sizeof(FUNC)+sizeof(MYFLT*), data->flen); printf("was %f %f %f ...\n", dst[0], dst[1], dst[2]); printf("will be %f %f %f ...\n", src[0],src[1], src[2]); memcpy(dst, src, len-sizeof(FUNC)+sizeof(MYFLT*)); #endif //for (j=0; jflen;j++) dst[j]=src[j]; //printf("now %f %f %f ...\n", dst[0], dst[1], dst[2]); } } else if (c == 'S') { } else return csound->PerfError(csound, p->h.insdshead, "Oh dear"); csound->Free(csound, m->args[i].blob); } else *(p->args[i]) = m->args[i].number; } /* push to stack of free message structures */ m->next = p->freePatterns; p->freePatterns = m; *p->kans = 1; } else *p->kans = 0; csound->UnlockMutex(p->port->mutex_); return OK; } #define S(x) sizeof(x) static OENTRY localops[] = { { "OSCsend_lo", S(OSCSEND), 0, 3, "", "kSkSS*", (SUBR)osc_send_set, (SUBR)osc_send, NULL,NULL }, { "OSCinit", S(OSCINIT), 0, 1, "i", "i", (SUBR)osc_listener_init, NULL, NULL, NULL }, { "OSCinitM", S(OSCINITM), 0, 1, "i", "Si", (SUBR)osc_listener_initMulti, NULL, NULL, NULL }, { "OSClisten", S(OSCLISTEN),0, 3, "k", "iSS*", (SUBR)OSC_list_init, (SUBR)OSC_list, NULL, NULL }, { "OSClisten", S(OSCLISTEN),0, 3, "k", "iSS", (SUBR)OSC_list_init, (SUBR)OSC_list, NULL, NULL }, /* { "OSCsendA", S(OSCSEND), _QQ, 3, "", "kSkSS*", */ /* (SUBR)osc_send_async_set, (SUBR)osc_send_async, NULL, NULL } */ }; PUBLIC long csound_opcode_init(CSOUND *csound, OENTRY **ep) { IGN(csound); *ep = localops; return (long) sizeof(localops); } PUBLIC int csoundModuleInfo(void) { return ((CS_APIVERSION << 16) + (CS_APISUBVER << 8) + (int) sizeof(MYFLT)); } csound-6.10.0/Opcodes/VST4CS_LINUX.md000066400000000000000000000034711321653344700167710ustar00rootroot00000000000000Building the vst4cs Opcodes and CsoundVST on Linux ================================================== The vst4cs opcodes which enable Csound to host VST plugins work just fine on Linux. So does CsoundVST which enables Csound itself to run as a VST plugin. For a possibly incomplete but very useful list of VST plugins (and VST hosts) available on Linux, see http://linux-sound.org/linux-vst-plugins.html. Please be aware that the Csound license permits building and linking code from Steinberg's VST SDK and Hermann Seib's VST Host, see the license text in the vst4cs and CsoundVST source code. To build and install the VST features on Linux: 1. Ensure that your environment and software are consistent with respect to CPU architecture. Csound on Linux by default is built for 64 bit CPU architecture, e.g. `amd64`, and for double-precision audio samples. Your target VST plugins and hosts should also be built for 64 bit CPU architecture. 2. Download Steinberg's VST SDK from https://www.steinberg.net/en/company/developers.html, e.g. https://download.steinberg.net/sdk_downloads/vstsdk368_08_11_2017_build_121.zip. Unpack the zip file in your home directory. 3. Patch ~/VST_SDK/VST2_SK/pluginterfaces/vst2.x/aeffect.h as follows. At about line 67, change ``` #elif defined(__GNUC__) ``` to ``` #elif defined(__MINGW32__) ``` 4. Do a fresh pull from the Csound GitHub repository. 5. Now you can build Csound with the VST features included. In your Csound build directory: 1. Configure CMake to build Csound with the VST features. Delete your `CMakeCache.txt` file. On the cmake command line, add: `-DVSTSDK2X_INCLUDE_DIR:PATH=~/VST_SDK/VST2_SDK -DBUILD_CSOUND_VST=1 -DBUILD_VST4CS_OPCODES=1`. You can also configure this using cmake-gui. Run cmake to regenerate your makefiles. 2. Run `make`. 3. Run `sudo make install.` csound-6.10.0/Opcodes/Vosim.c000066400000000000000000000130511321653344700157360ustar00rootroot00000000000000/* VOSIM.C: VOice SIMulation implementation * by rasmus ekman March 13, 2008, for Csound. * This code is released under the Csound license, * GNU Lesser General Public License version 2.1, * or (at your option) any later version. */ /* Programmer note: * Pre- and post-conditions are noted at function level. * These are essential for the code to work at all. * There are some complications because we accept weird user input: * (a) kfund < 0: This is forced to positive - no point in "backward" events. * (b) kform == 0: This leads to infinite length pulse, ie silence. * (c) kform < 0: Table is read backward. * If table is symmetric, kform and -kform should give bit-identical outputs. * * Don't fiddle with the code unless you understand how the table read * params pulsephs and pulseinc are used both to read table and to indicate that * a new pulse should start, and that pulseinc can be negative. */ //#include "csdl.h" #include "csoundCore.h" #include "interlocks.h" #include #include typedef struct { OPDS h; MYFLT *ar, *amp, *kfund, *kform, *kdamp, *knofpulse, *kpulsemul, *iftab, *iskip; FUNC *ftable; int32 timrem; /* samples left of event */ int32 pulstogo; /* count of pulses to produce in burst */ int32 pulsephs; /* index into table of this pulse (= MAXLEN / kform) */ int32 pulseinc; /* increment in table of pulse */ MYFLT pulseamp; /* amp of current pulse */ MYFLT ampdecay; /* subtract from amp on new pulse */ MYFLT lenfact; /* increase length of next pulse */ } VOSIM; /* Post: unless skipping init, timrem == 0 */ int vosimset(CSOUND* csound, VOSIM *p) { if (*p->iskip) return OK; p->ftable = csound->FTFind(csound, p->iftab); if (UNLIKELY(p->ftable == NULL)) { return csound->InitError(csound, Str("vosim: pulse table not found")); } p->timrem = p->pulstogo = p->pulsephs = p->pulseinc = 0; p->pulseamp = p->ampdecay = p->lenfact = FL(0.0); return OK; } /* Pre: timrem == 0. * Post: * IF kform >= 0, pulsephs >= FMAXLEN. * ELSE pulsephs < 0. * timrem > 0. */ void vosim_event(CSOUND* csound, VOSIM *p) { MYFLT fundabs = FABS(*p->kfund); /* count of pulses, (+1 since decr at start of pulse) */ p->pulstogo = 1+(int32)*p->knofpulse; if (UNLIKELY(fundabs == FL(0.0))) { /* infinitely long event */ p->timrem = INT_MAX; csound->Warning(csound, Str("vosim: zero kfund. 'Infinite' length event generated.")); } else { p->timrem = (int32)(CS_ESR / fundabs); if (UNLIKELY(p->timrem == 0)) { p->timrem = CS_KSMPS; p->pulstogo = 0; csound->Warning(csound, Str("vosim: kfund (%f) > sr. Generating ksmps silence."), *p->kfund); } } p->pulseinc = (int32)(*p->kform * csound->sicvt); p->pulsephs = (p->pulseinc >= 0)? MAXLEN : -1; /* starts a new pulse */ p->ampdecay = *p->kdamp; /* increase initial amp, since it's reduced at pulse start */ p->pulseamp = *p->amp + p->ampdecay; /* if negative, table is read alternately back-/forward */ p->lenfact = *p->kpulsemul; /* reduce table rate, since it's increased at pulse start */ if (p->lenfact != FL(0.0)) p->pulseinc /= p->lenfact; } /* Pre: pulsephs >= FMAXLEN OR pulsephs < 0. * Post: * pulstogo is decremented or zero. * 0 <= pulsephs < FMAXLEN. */ void vosim_pulse(CSOUND* csound, VOSIM *p) { int32 pulselen; p->pulsephs &= PHMASK; p->pulseinc *= p->lenfact; /* If pulse can't fit in remaining event time, skip and generate silence */ pulselen = (p->pulseinc != FL(0.0))? (int32)FABS(FMAXLEN / p->pulseinc) : INT_MAX; if (p->pulstogo-- <= 0 || pulselen > p->timrem) { p->pulstogo = 0; } p->pulseamp -= p->ampdecay; } int vosim(CSOUND* csound, VOSIM *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *ar = p->ar; MYFLT *ftdata; int32 lobits; FUNC *ftp = p->ftable; if (UNLIKELY(ftp == NULL)) goto err1; ftdata = ftp->ftable; lobits = ftp->lobits; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; ntimrem == 0) vosim_event(csound, p); /* new pulse? */ if (p->pulsephs >= MAXLEN || p->pulsephs < 0) vosim_pulse(csound, p); if (p->pulstogo > 0) { /* produce one sample */ p->pulsephs &= PHMASK; ar[n] = *(ftdata + (p->pulsephs >> lobits)) * p->pulseamp; --p->timrem; p->pulsephs += p->pulseinc; } else { /* silence after last pulse in burst: */ /* bypass regular synthesis and fill output with zeros */ while (p->timrem && ntimrem; n++; } n--; } } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("vosim: not initialised")); } /* ar vosim kamp, kFund, kForm, kDamp, kPulseCount, kPulseFactor, ifn [, iskip] */ #define S(x) sizeof(x) static OENTRY vosim_localops[] = { { "vosim", S(VOSIM), TR, 5, "a", "kkkkkkio", (SUBR)vosimset, NULL, (SUBR)vosim } }; LINKAGE_BUILTIN(vosim_localops) csound-6.10.0/Opcodes/ableton_link_opcodes.cpp000066400000000000000000000740321321653344700213640ustar00rootroot00000000000000/* This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #if defined(__MINGW64__) #include #include extern "C" { uint64_t htonll(uint64_t value) { _byteswap_uint64(value); } uint64_t ntohll(uint64_t value) { _byteswap_uint64(value); } } #endif #if defined(__ANDROID__) /* Ableton Link preupposes GNU libc, but we are using clang. * So we must replace all the ifaddrs code. * Pretend that ifaddrs.h has been included: */ #define _IFADDRS_H // Put in our own ifaddrs.h from https://raw.githubusercontent.com/libpd/abl_link/master/external/android-ifaddrs/ifaddrs.h. ////////////////////////////////////////////////////////////////////////////// /* * libjingle * Copyright 2013, Google Inc. * * 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 * 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. */ #ifndef TALK_BASE_IFADDRS_ANDROID_H_ #define TALK_BASE_IFADDRS_ANDROID_H_ #include #include // Implementation of getifaddrs for Android. // Fills out a list of ifaddr structs (see below) which contain information // about every network interface available on the host. // See 'man getifaddrs' on Linux or OS X (nb: it is not a POSIX function). struct ifaddrs { struct ifaddrs* ifa_next; char* ifa_name; unsigned int ifa_flags; struct sockaddr* ifa_addr; struct sockaddr* ifa_netmask; // Real ifaddrs has broadcast, point to point and data members. // We don't need them (yet?). }; int getifaddrs(struct ifaddrs** result); void freeifaddrs(struct ifaddrs* addrs); #endif // TALK_BASE_IFADDRS_ANDROID_H_ ////////////////////////////////////////////////////////////////////////////// // Put in our own ifaddrs.cpp from https://raw.githubusercontent.com/libpd/abl_link/master/external/android-ifaddrs/ifaddrs.cpp. ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// #endif // defined(__ANDROID__) /* * libjingle * Copyright 2012, Google Inc. * * 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 * 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. */ #if defined(ANDROID) #include "ifaddrs.h" #include #include #include #include #include #include #include #include #include #include #include #include struct netlinkrequest { nlmsghdr header; ifaddrmsg msg; }; namespace { const int kMaxReadSize = 4096; }; int set_ifname(struct ifaddrs* ifaddr, int interface) { char buf[IFNAMSIZ] = {0}; char* name = if_indextoname(interface, buf); if (name == NULL) { return -1; } ifaddr->ifa_name = new char[strlen(name) + 1]; strncpy(ifaddr->ifa_name, name, strlen(name) + 1); return 0; } int set_flags(struct ifaddrs* ifaddr) { int fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd == -1) { return -1; } ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, ifaddr->ifa_name, IFNAMSIZ - 1); int rc = ioctl(fd, SIOCGIFFLAGS, &ifr); close(fd); if (rc == -1) { return -1; } ifaddr->ifa_flags = ifr.ifr_flags; return 0; } int set_addresses(struct ifaddrs* ifaddr, ifaddrmsg* msg, void* data, size_t len) { if (msg->ifa_family == AF_INET) { sockaddr_in* sa = new sockaddr_in; sa->sin_family = AF_INET; memcpy(&sa->sin_addr, data, len); ifaddr->ifa_addr = reinterpret_cast(sa); } else if (msg->ifa_family == AF_INET6) { sockaddr_in6* sa = new sockaddr_in6; sa->sin6_family = AF_INET6; sa->sin6_scope_id = msg->ifa_index; memcpy(&sa->sin6_addr, data, len); ifaddr->ifa_addr = reinterpret_cast(sa); } else { return -1; } return 0; } int make_prefixes(struct ifaddrs* ifaddr, int family, int prefixlen) { char* prefix = NULL; if (family == AF_INET) { sockaddr_in* mask = new sockaddr_in; mask->sin_family = AF_INET; memset(&mask->sin_addr, 0, sizeof(in_addr)); ifaddr->ifa_netmask = reinterpret_cast(mask); if (prefixlen > 32) { prefixlen = 32; } prefix = reinterpret_cast(&mask->sin_addr); } else if (family == AF_INET6) { sockaddr_in6* mask = new sockaddr_in6; mask->sin6_family = AF_INET6; memset(&mask->sin6_addr, 0, sizeof(in6_addr)); ifaddr->ifa_netmask = reinterpret_cast(mask); if (prefixlen > 128) { prefixlen = 128; } prefix = reinterpret_cast(&mask->sin6_addr); } else { return -1; } for (int i = 0; i < (prefixlen / 8); i++) { *prefix++ = 0xFF; } char remainder = 0xff; remainder <<= (8 - prefixlen % 8); *prefix = remainder; return 0; } int populate_ifaddrs(struct ifaddrs* ifaddr, ifaddrmsg* msg, void* bytes, size_t len) { if (set_ifname(ifaddr, msg->ifa_index) != 0) { return -1; } if (set_flags(ifaddr) != 0) { return -1; } if (set_addresses(ifaddr, msg, bytes, len) != 0) { return -1; } if (make_prefixes(ifaddr, msg->ifa_family, msg->ifa_prefixlen) != 0) { return -1; } return 0; } int getifaddrs(struct ifaddrs** result) { int fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (fd < 0) { return -1; } netlinkrequest ifaddr_request; memset(&ifaddr_request, 0, sizeof(ifaddr_request)); ifaddr_request.header.nlmsg_flags = NLM_F_ROOT | NLM_F_REQUEST; ifaddr_request.header.nlmsg_type = RTM_GETADDR; ifaddr_request.header.nlmsg_len = NLMSG_LENGTH(sizeof(ifaddrmsg)); ssize_t count = send(fd, &ifaddr_request, ifaddr_request.header.nlmsg_len, 0); if (static_cast(count) != ifaddr_request.header.nlmsg_len) { close(fd); return -1; } struct ifaddrs* start = NULL; struct ifaddrs* current = NULL; char buf[kMaxReadSize]; ssize_t amount_read = recv(fd, &buf, kMaxReadSize, 0); while (amount_read > 0) { nlmsghdr* header = reinterpret_cast(&buf[0]); size_t header_size = static_cast(amount_read); for ( ; NLMSG_OK(header, header_size); header = NLMSG_NEXT(header, header_size)) { switch (header->nlmsg_type) { case NLMSG_DONE: // Success. Return. *result = start; close(fd); return 0; case NLMSG_ERROR: close(fd); freeifaddrs(start); return -1; case RTM_NEWADDR: { ifaddrmsg* address_msg = reinterpret_cast(NLMSG_DATA(header)); rtattr* rta = IFA_RTA(address_msg); ssize_t payload_len = IFA_PAYLOAD(header); while (RTA_OK(rta, payload_len)) { if (rta->rta_type == IFA_ADDRESS) { int family = address_msg->ifa_family; if (family == AF_INET || family == AF_INET6) { ifaddrs* newest = new ifaddrs; memset(newest, 0, sizeof(ifaddrs)); if (current) { current->ifa_next = newest; } else { start = newest; } if (populate_ifaddrs(newest, address_msg, RTA_DATA(rta), RTA_PAYLOAD(rta)) != 0) { freeifaddrs(start); *result = NULL; return -1; } current = newest; } } rta = RTA_NEXT(rta, payload_len); } break; } } } amount_read = recv(fd, &buf, kMaxReadSize, 0); } close(fd); freeifaddrs(start); return -1; } void freeifaddrs(struct ifaddrs* addrs) { struct ifaddrs* last = NULL; struct ifaddrs* cursor = addrs; while (cursor) { delete[] cursor->ifa_name; delete cursor->ifa_addr; delete cursor->ifa_netmask; last = cursor; cursor = cursor->ifa_next; delete last; } } #endif // defined(ANDROID) #include #include /** * A B L E T O N L I N K O P C O D E S * * Author: Michael Gogins * January 2017 * * These opcodes implement the Ableton Link protocol from: * * https://github.com/Ableton/link * * The purpose of Ableton Link is to sychronize musical time, beat, and phase * between musical applications performing in real time from separate * programs, processes, and network addresses. This is useful e.g. for laptop * orchestras. * * There is one global, peer-to-peer Link session that maintains a global time * and beat on the local area network. Any peer may set the global tempo, * and thereafter all peers in the session share that tempo. A process may * have any number of peers (i.e., any number of Link objects). Each peer * may also define its own "quantum" i.e. some multiple of the beat, e.g. a * quantum of 4 might imply 4/4 time. The phase of the time is defined w.r.t * the quantum, e.g. phase 0.5 of a quantum of 4 would be the second beat of * the measure. Peers may read and write timelines with local time, beat, and * phase, counting from when the peer is enabled, but the tempo and beat on * all timelines for all peers in the session will coincide. * * The first peer to enable a session determines the initial tempo. After * that, the tempo is changed only, and whenever, any peer explicity calls * the set tempo functon (link_tempo_set, in Csound). * * The Link tempo is independent of the Csound score tempo. Performances that * need to synchronize the score tempo with the Link tempo may use the tempo * opcode to set the score tempo from the Link tempo; or conversely, set the * Link tempo from the score tempo using the tempoval opcode. * * Please note, the phase and beat obtained or set by these opcodes is only as * precise as allowed by the duration of Csound's kperiod, the audio driver * used by Csound, the network stability, and the system's most precise clock. * * Build for testing with something like: * * g++ ableton_link_opcodes.cpp -std=gnu++11 -DLINK_PLATFORM_WINDOWS=1 -Werror -Wno-multichar -O2 -g -lcsound64 -I/home/restore/link/include -I/home/restore/link/modules/asio-standalone/asio/include -I../include -I../H -shared -oableton_link_opcodes.dll * g++ ableton_link_opcodes.cpp -std=gnu++11 -DLINK_PLATFORM_LINUX=1 -Werror -Wno-multichar -O2 -g -fPIC -lcsound64 -I/home/mkg/link/include -I/home/mkg/link/modules/asio-standalone/asio/include -I/usr/local/include/csound -I/home/mkg/csound/csound/include -shared -oableton_link_opcodes.so */ using namespace csound; static bool enable_debug = 0; #define debug(fmt, ...) \ do { if (enable_debug) fprintf(stderr, fmt, __VA_ARGS__); } while (0) using floating_point_microseconds = std::chrono::duration; using floating_point_seconds = std::chrono::duration; /** * This is used to perform a static type cast in a clear, obvious, and * bulletproof way. Here, we want a bit-for-bit cast between a Csound MYFLT * (usually a double) and a pointer. This will only work if sizeof(MYFLT) > * sizeof(void *). That is always the case on 32 bit CPU architecture, and * will be the case on 64 bit CPU architecture if MYFLT is double-precision. */ typedef union { MYFLT myflt; ableton::Link *pointer; } link_cast_t; // i_link link_create [j_bpm = 60] class link_create_t : public OpcodeBase { // Pfields out: MYFLT *r0_link; // Pfields in: MYFLT *p0_bpm; // State: link_cast_t link; double bpm; public: int init(CSOUND *csound) { if (*p0_bpm == FL(-1.0)) { bpm = 60; } else { bpm = *p0_bpm; } link.pointer = new ableton::Link(bpm); debug("link_create: bpm: %f link.pointer: %p link.myflt: %g\n", bpm, link.pointer, link.myflt); *r0_link = link.myflt; return OK; } }; // link_enable i_link [, P_enabled = 1] class link_enable_t : public OpcodeBase { // Pfields out: // Pfields in: MYFLT *p0_link; MYFLT *p1_enabled; // State: link_cast_t link; MYFLT prior_enabled; public: int init(CSOUND *csound) { link.myflt = *p0_link; link.pointer->enable(*p1_enabled); prior_enabled = *p1_enabled; debug("link_enable: link.pointer: %p link.myflt: %g p1_enabled: %f isEnabled: %d\n", link.pointer, link.myflt, *p1_enabled, link.pointer->isEnabled()); return OK; } int kontrol(CSOUND *csound) { if (prior_enabled != *p1_enabled) { link.pointer->enable(*p1_enabled); debug("link_enable: link.pointer: %p link.myflt: %g p1_enabled: %f isEnabled: %d\n", link.pointer, link.myflt, *p1_enabled, link.pointer->isEnabled()); prior_enabled = *p1_enabled; } return OK; } }; // k_is_enabled link_is_enabled i_link class link_is_enabled_t : public OpcodeBase { // Pfields out: MYFLT *r0_is_enabled; // Pfields in: MYFLT *p0_link; // State: link_cast_t link; public: int init(CSOUND *csound) { link.myflt = *p0_link; *r0_is_enabled = link.pointer->isEnabled(); return OK; } int kontrol(CSOUND *csound) { *r0_is_enabled = link.pointer->isEnabled(); return OK; } }; // link_tempo_set i_link, k_bpm [, P_at_time_seconds = current time] class link_tempo_set_t : public OpcodeBase { // Pfields out: // Pfields in: MYFLT *p0_link; MYFLT *p1_bpm; MYFLT *p2_at_time_seconds; // State: link_cast_t link; MYFLT prior_bpm; std::chrono::microseconds at_time_microseconds; public: int init(CSOUND *csound) { link.myflt = *p0_link; ableton::Link::Timeline timeline = link.pointer->captureAudioTimeline(); prior_bpm = *p1_bpm; if (*p2_at_time_seconds == FL(-1.0)) { at_time_microseconds = link.pointer->clock().micros(); } else { at_time_microseconds = std::chrono::duration_cast(floating_point_seconds(*p2_at_time_seconds)); } timeline.setTempo(prior_bpm, at_time_microseconds); link.pointer->commitAudioTimeline(timeline); return OK; } int kontrol(CSOUND *csound) { if (prior_bpm != *p1_bpm) { ableton::Link::Timeline timeline = link.pointer->captureAudioTimeline(); prior_bpm = *p1_bpm; if (*p2_at_time_seconds == FL(-1.0)) { at_time_microseconds = link.pointer->clock().micros(); } else { at_time_microseconds = std::chrono::duration_cast(floating_point_seconds(*p2_at_time_seconds)); } timeline.setTempo(prior_bpm, at_time_microseconds); link.pointer->commitAudioTimeline(timeline); } return OK; } }; // k_bpm link_tempo_get i_link class link_tempo_get_t : public OpcodeBase { // Pfields out: MYFLT *r0_bpm; // Pfields in: MYFLT *p0_link; // State: link_cast_t link; public: int init(CSOUND *csound) { link.myflt = *p0_link; ableton::Link::Timeline timeline = link.pointer->captureAudioTimeline(); *r0_bpm = timeline.tempo(); return OK; } int kontrol(CSOUND *csound) { ableton::Link::Timeline timeline = link.pointer->captureAudioTimeline(); *r0_bpm = timeline.tempo(); return OK; } }; // k_beat_number, k_phase, k_current_time_seconds link_beat_get i_link [, P_quantum = 1] class link_beat_get_t : public OpcodeBase { // Pfields out: MYFLT *r0_beat; MYFLT *r1_phase; MYFLT *r2_seconds; // Pfields in: MYFLT *p0_link; MYFLT *p1_quantum; // State: link_cast_t link; std::chrono::microseconds at_time_microseconds; public: int init(CSOUND *csound) { link.myflt = *p0_link; ableton::Link::Timeline timeline = link.pointer->captureAudioTimeline(); at_time_microseconds = link.pointer->clock().micros(); *r0_beat = timeline.beatAtTime(at_time_microseconds, *p1_quantum); *r1_phase = timeline.phaseAtTime(at_time_microseconds, *p1_quantum); *r2_seconds = std::chrono::duration_cast(at_time_microseconds).count(); return OK; } int kontrol(CSOUND *csound) { ableton::Link::Timeline timeline = link.pointer->captureAudioTimeline(); at_time_microseconds = link.pointer->clock().micros(); *r0_beat = timeline.beatAtTime(at_time_microseconds, *p1_quantum); *r1_phase = timeline.phaseAtTime(at_time_microseconds, *p1_quantum); *r2_seconds = std::chrono::duration_cast(at_time_microseconds).count(); return OK; } }; // k_trigger, k_beat, k_phase, k_current_time_seconds link_metro i_link [, P_quantum = 1] class link_metro_t : public OpcodeBase { // Pfields out: MYFLT *r0_trigger; MYFLT *r1_beat; MYFLT *r2_phase; MYFLT *r3_seconds; // Pfields in: MYFLT *p0_link; MYFLT *p1_quantum; // State: link_cast_t link; std::chrono::microseconds at_time_microseconds; MYFLT prior_phase; public: // The trigger is "on" when the new phase is less than the prior phase, and "off" // when the new phase is greater than the prior phase. int init(CSOUND *csound) { link.myflt = *p0_link; debug("link_metro i: link.pointer: %p link.myflt: %g\n", link.pointer, link.myflt); ableton::Link::Timeline timeline = link.pointer->captureAudioTimeline(); at_time_microseconds = link.pointer->clock().micros(); *r0_trigger = 0; *r1_beat = timeline.beatAtTime(at_time_microseconds, *p1_quantum); *r2_phase = timeline.phaseAtTime(at_time_microseconds, *p1_quantum); prior_phase = *r2_phase; *r3_seconds = std::chrono::duration_cast(at_time_microseconds).count(); debug("link_metro i: r0_trigger: %f r1_beat: %f r2_phase: %f r3_seconds: %f\n", *r0_trigger, *r1_beat, *r2_phase, *r3_seconds); return OK; } int kontrol(CSOUND *csound) { ableton::Link::Timeline timeline = link.pointer->captureAudioTimeline(); at_time_microseconds = link.pointer->clock().micros(); *r1_beat = timeline.beatAtTime(at_time_microseconds, *p1_quantum); *r2_phase = timeline.phaseAtTime(at_time_microseconds, *p1_quantum); if (*r2_phase < prior_phase) { *r0_trigger = 1; debug("link_metro k: r0_trigger: %f r1_beat: %f r2_phase: %f r3_seconds: %f\n", *r0_trigger, *r1_beat, *r2_phase, *r3_seconds); } else { *r0_trigger = 0; } prior_phase = *r2_phase; *r3_seconds = std::chrono::duration_cast(at_time_microseconds).count(); return OK; } }; // link_beat_request i_link k_beat [, J_at_time_seconds = current time [, P_quantum = 1]] class link_beat_request_t : public OpcodeBase { // Pfields out: // Pfields in: MYFLT *p0_link; MYFLT *p1_beat; MYFLT *p2_at_time_seconds; MYFLT *p3_quantum; // State: link_cast_t link; MYFLT prior_beat; MYFLT prior_at_time_seconds; MYFLT prior_quantum; std::chrono::microseconds at_time_microseconds; public: int init(CSOUND *csound) { link.myflt = *p0_link; prior_beat = *p1_beat; prior_at_time_seconds = *p2_at_time_seconds; prior_quantum = *p3_quantum; if (*p2_at_time_seconds == FL(-1.0)) { at_time_microseconds = link.pointer->clock().micros(); } else { at_time_microseconds = std::chrono::duration_cast(floating_point_seconds(*p2_at_time_seconds)); } ableton::Link::Timeline timeline = link.pointer->captureAudioTimeline(); timeline.requestBeatAtTime(prior_beat, at_time_microseconds, prior_quantum); link.pointer->commitAudioTimeline(timeline); return OK; } int kontrol(CSOUND *csound) { if ((prior_beat != *p1_beat) || (prior_at_time_seconds != *p2_at_time_seconds) || (prior_quantum != *p3_quantum)) { if (*p2_at_time_seconds == FL(-1.0)) { at_time_microseconds = link.pointer->clock().micros(); } else { at_time_microseconds = std::chrono::duration_cast(floating_point_seconds(*p2_at_time_seconds)); } ableton::Link::Timeline timeline = link.pointer->captureAudioTimeline(); timeline.requestBeatAtTime(prior_beat, at_time_microseconds, prior_quantum); link.pointer->commitAudioTimeline(timeline); prior_beat = *p1_beat; prior_at_time_seconds = *p2_at_time_seconds; prior_quantum = *p3_quantum; } return OK; } }; // link_beat_force i_link k_beat [, J_at_time_seconds = current time [, P_quantum = 1]] class link_beat_force_t : public OpcodeBase { // Pfields out: // Pfields in: MYFLT *p0_link; MYFLT *p1_beat; MYFLT *p2_at_time_seconds; MYFLT *p3_quantum; // State: link_cast_t link; MYFLT prior_beat; MYFLT prior_at_time_seconds; MYFLT prior_quantum; std::chrono::microseconds at_time_microseconds; public: int init(CSOUND *csound) { link.myflt = *p0_link; prior_beat = *p1_beat; prior_at_time_seconds = *p2_at_time_seconds; prior_quantum = *p3_quantum; if (*p2_at_time_seconds == FL(-1.0)) { at_time_microseconds = link.pointer->clock().micros(); } else { at_time_microseconds = std::chrono::duration_cast(floating_point_seconds(*p2_at_time_seconds)); } ableton::Link::Timeline timeline = link.pointer->captureAudioTimeline(); timeline.forceBeatAtTime(prior_beat, at_time_microseconds, prior_quantum); link.pointer->commitAudioTimeline(timeline); return OK; } int kontrol(CSOUND *csound) { if ((prior_beat != *p1_beat) || (prior_at_time_seconds != *p2_at_time_seconds) || (prior_quantum != *p3_quantum)) { if (*p2_at_time_seconds == FL(-1.0)) { at_time_microseconds = link.pointer->clock().micros(); } else { at_time_microseconds = std::chrono::duration_cast(floating_point_seconds(*p2_at_time_seconds)); } ableton::Link::Timeline timeline = link.pointer->captureAudioTimeline(); timeline.forceBeatAtTime(prior_beat, at_time_microseconds, prior_quantum); link.pointer->commitAudioTimeline(timeline); prior_beat = *p1_beat; prior_at_time_seconds = *p2_at_time_seconds; prior_quantum = *p3_quantum; } return OK; } }; // k_count link_peers i_link class link_peers_t : public OpcodeBase { // Pfields out: MYFLT *r0_peers; // Pfields in: MYFLT *p0_link; // State: link_cast_t link; public: int init(CSOUND *csound) { link.myflt = *p0_link; *r0_peers = link.pointer->numPeers(); return OK; } int kontrol(CSOUND *csound) { *r0_peers = link.pointer->numPeers(); return OK; } }; extern "C" { OENTRY oentries[] = { // i_link link_create [j_bpm = 60] { (char*)"link_create", sizeof(link_create_t), 0, 1, (char*)"i", (char*)"j", (SUBR) link_create_t::init_, 0, 0, }, // link_enable i_link [, P_enabled = 1] { (char*)"link_enable", sizeof(link_enable_t), 0, 3, (char*)"", (char*)"iP", (SUBR) link_enable_t::init_, (SUBR) link_enable_t::kontrol_, 0, }, // k_is_enabled link_is_enabled i_link { (char*)"link_is_enabled", sizeof(link_is_enabled_t), 0, 3, (char*)"k", (char*)"i", (SUBR) link_is_enabled_t::init_, (SUBR) link_is_enabled_t::kontrol_, 0, }, // link_tempo_set i_link, k_bpm [, J_at_time_seconds = current time] { (char*)"link_tempo_set", sizeof(link_tempo_set_t), 0, 3, (char*)"", (char*)"ikJ", (SUBR) link_tempo_set_t::init_, (SUBR) link_tempo_set_t::kontrol_, 0, }, // k_bpm link_tempo_get i_link { (char*)"link_tempo_get", sizeof(link_tempo_set_t), 0, 3, (char*)"k", (char*)"i", (SUBR) link_tempo_get_t::init_, (SUBR) link_tempo_get_t::kontrol_, 0, }, // k_beat_number, k_phase, k_current_time_seconds link_beat_get i_link [, P_quantum = 1] { (char*)"link_beat_get", sizeof(link_beat_get_t), 0, 3, (char*)"kkk", (char*)"iP", (SUBR) link_beat_get_t::init_, (SUBR) link_beat_get_t::kontrol_, 0, }, // k_trigger, k_beat, k_phase, k_current_time_seconds link_metro i_link [, P_quantum = 1] { (char*)"link_metro", sizeof(link_metro_t), 0, 3, (char*)"kkkk", (char*)"iP", (SUBR) link_metro_t::init_, (SUBR) link_metro_t::kontrol_, 0, }, // link_beat_request i_link k_beat [, J_at_time_seconds = current time [, P_quantum = 1]] { (char*)"link_beat_request", sizeof(link_beat_request_t), 0, 3, (char*)"", (char*)"ikJP", (SUBR) link_beat_request_t::init_, (SUBR) link_beat_request_t::kontrol_, 0, }, // link_beat_force i_link k_beat [, J_at_time_seconds = current time [, P_quantum = 1]] { (char*)"link_beat_force", sizeof(link_beat_force_t), 0, 3, (char*)"", (char*)"ikJP", (SUBR) link_beat_force_t::init_, (SUBR) link_beat_force_t::kontrol_, 0, }, // k_count link_peers i_link { (char*)"link_peers", sizeof(link_peers_t), 0, 3, (char*)"k", (char*)"i", (SUBR) link_peers_t::init_, (SUBR) link_peers_t::kontrol_, 0, }, { 0, 0, 0, 0, 0, 0, 0, 0, } }; PUBLIC int csoundModuleCreate(CSOUND *csound) { return 0; } PUBLIC int csoundModuleInit(CSOUND *csound) { int status = 0; for(OENTRY *oentry = &oentries[0]; oentry->opname; oentry++) { status |= csound->AppendOpcode(csound, oentry->opname, oentry->dsblksiz, oentry->flags, oentry->thread, oentry->outypes, oentry->intypes, (int (*)(CSOUND*,void*)) oentry->iopadr, (int (*)(CSOUND*,void*)) oentry->kopadr, (int (*)(CSOUND*,void*)) oentry->aopadr); } return status; } PUBLIC int csoundModuleDestroy(CSOUND *csound) { return 0; } } csound-6.10.0/Opcodes/ableton_link_test.csd000066400000000000000000000076731321653344700207050ustar00rootroot00000000000000 T E S T S F O R A B L E T O N L I N K O P C O D E S Michael Gogins 12 January 2017 These cover most of the things in Ableton Link's TEST-PLAN.md. This csd is to be used on conjunction with the command-line LinkHut application in the Ableton Link Git repository. There are two sections. In the first, we start LinkHut first and use it to control Csound's tempo. In the second, we start Csound first and use it to conrol LinkHut's tempo. This csd automatically performs its tests. The user has to manually operate LinkHut as instructed below. In all cases system audio should be enabled so the user can hear the beat, and both Csound and LinkHut should be run from the command line in separate, simultaeously visible terminal windows so the user can compare the diagnostic messages. FIRST LINKHUT, THEN CSOUND Start LinkHut, then start this csd. Test 1 -- Join Session without Changing Session Tempo, and Tempo Sync At first, both peers should show a tempo of 120 which is the default for this csd. Change tempo in LinkHut. Tempo in Csound should sync if Link is enabled, but not sync if Link is disabled. This csd will change tempo to 80 after 10 seconds. LinkHut should sync if Link is enabled, but not sync if Link is enabled. Test 2 -- Tempo Range Use LinkHut to change tempo from 20 to 999. Both sessions should show the full range. Test 3 -- Tempo Stability After 20 seconds this csd should disable Link, and after another 10 seconds Link should be re-enabled. The session tempo and beat should not change. Then, in LinkHut, manually disable and re-enable Link. The session tempo and beat should not change. Test 4 -- Beat Stability Kill and restart LinkHut while this csd is running. Enable and disable Link in LinkHut. The beat should continue without any temporal or rhythmic discontinuity. FIRST CSOUND, THEN LINKHUT Start this csd, then start LinkHut. Test 5 -- Join Session without Changing Session Tempo, and Tempo Sync At first, both peers should show a tempo of 72 which is the default for this csd. Change tempo in LinkHut. Tempo in Csound should sync if Link is enabled, but not sync if Link is disabled. This csd will change tempo to 80 after 10 seconds. LinkHut should sync if Link is enabled, but not sync if Link is enabled. Test 6 -- Beat Stability Kill and restart this csd while LinkHut is running. Enable and disable Link in LinkHut. The beat should continue without any temporal or rhythmic discontinuity. NOTE: At this time, Csound does not implement delay compensation, so testing for delay compensation is not applicable. By using the smallest practical audio latency in Csound, however, the sync should not be much looser than Ableton's minimum requirement of 3 milliseconds. This is approximately the accuracy of a really good performing musician. -m0 -d -odac sr = 44100 ksmps = 10 nchnls = 2 alwayson "LinkMonitor" gi_link link_create 72 gk_beat init 0 instr Beep asignal oscils 20000, p4, 0 outs asignal, asignal endin instr TexpoChaxge link_tempo_set gi_link, 80 endin instr LixkExable i_enabled = p4 link_enable gi_link, i_enabled endin instr LinkMonitor i_kperiod_seconds = ksmps / sr printf_i "kperiod: %9.6f seconds.\n", 1, i_kperiod_seconds printf_i "gi_link: %g\n", 1, gi_link link_enable gi_link, 1 k_trigger, gk_beat, k_phase, k_time link_metro gi_link, 1 k_peers link_peers gi_link k_tempo link_tempo_get gi_link k_enabled link_is_enabled gi_link k_hz = 1000 if floor(gk_beat % 4) == 0 then k_hz = 3000 else k_hz = 2000 endif schedkwhen k_trigger, 0, 1, "Beep", 0, 0.01, k_hz printf "LinkMonitor: gi_link: %g k_enabled: %9.4f k_trigger: %9.4f beat: %9.4f k_phase: %9.4f time: %9.4f tempo: %9.4f peers: %3d\n", k_trigger, gi_link, k_enabled, k_trigger, gk_beat, k_phase, k_time, k_tempo, k_peers endin f 0 360 i "TexpoChaxge" 10 80 i "LixkExable" 20 1 0 i "LixkExable" 30 1 1 csound-6.10.0/Opcodes/ableton_link_test_force.csd000066400000000000000000000101101321653344700220370ustar00rootroot00000000000000 T E S T S F O R A B L E T O N L I N K O P C O D E S Michael Gogins 12 January 2017 These cover most of the things in Ableton Link's TEST-PLAN.md. This csd is to be used on conjunction with the command-line LinkHut application in the Ableton Link Git repository. There are two sections. In the first, we start LinkHut first and use it to control Csound's tempo. In the second, we start Csound first and use it to conrol LinkHut's tempo. This csd automatically performs its tests. The user has to manually operate LinkHut as instructed below. In all cases system audio should be enabled so the user can hear the beat, and both Csound and LinkHut should be run from the command line in separate, simultaeously visible terminal windows so the user can compare the diagnostic messages. FIRST LINKHUT, THEN CSOUND Start LinkHut, then start this csd. Test 1 -- Join Session without Changing Session Tempo, and Tempo Sync At first, both peers should show a tempo of 120 which is the default for this csd. Change tempo in LinkHut. Tempo in Csound should sync if Link is enabled, but not sync if Link is disabled. This csd will change tempo to 80 after 10 seconds. LinkHut should sync if Link is enabled, but not sync if Link is enabled. Test 2 -- Tempo Range Use LinkHut to change tempo from 20 to 999. Both sessions should show the full range. Test 3 -- Tempo Stability After 20 seconds this csd should disable Link, and after another 10 seconds Link should be re-enabled. The session tempo and beat should not change. Then, in LinkHut, manually disable and re-enable Link. The session tempo and beat should not change. Test 4 -- Beat Stability Kill and restart LinkHut while this csd is running. Enable and disable Link in LinkHut. The beat should continue without any temporal or rhythmic discontinuity. FIRST CSOUND, THEN LINKHUT Start this csd, then start LinkHut. Test 5 -- Join Session without Changing Session Tempo, and Tempo Sync At first, both peers should show a tempo of 72 which is the default for this csd. Change tempo in LinkHut. Tempo in Csound should sync if Link is enabled, but not sync if Link is disabled. This csd will change tempo to 80 after 10 seconds. LinkHut should sync if Link is enabled, but not sync if Link is enabled. Test 6 -- Beat Stability Kill and restart this csd while LinkHut is running. Enable and disable Link in LinkHut. The beat should continue without any temporal or rhythmic discontinuity. NOTE: At this time, Csound does not implement delay compensation, so testing for delay compensation is not applicable. By using the smallest practical audio latency in Csound, however, the sync should not be much looser than Ableton's minimum requirement of 3 milliseconds. This is approximately the accuracy of a really good performing musician. -m0 -d -odac8 sr = 48000 ksmps = 10 nchnls = 2 alwayson "LinkMonitor" gi_link link_create 72 gk_beat init 0 instr Beep asignal oscils 20000, p4, 0 outs asignal, asignal endin instr TempoChange link_tempo_set gi_link, 80 endin instr LinkEnable i_enabled = p4 link_enable gi_link, i_enabled endin instr LinkForce print p4, p5, p6 k_beat init p4 k_time init p5 k_quantum init p6 link_beat_force gi_link, k_beat, k_time, k_quantum endin instr LinkMonitor i_kperiod_seconds = ksmps / sr printf_i "kperiod: %9.6f seconds.\n", 1, i_kperiod_seconds printf_i "gi_link: %g\n", 1, gi_link link_enable gi_link, 1 k_trigger, gk_beat, k_phase, k_time link_metro gi_link, 1 k_peers link_peers gi_link k_tempo link_tempo_get gi_link k_enabled link_is_enabled gi_link k_hz = 1000 if floor(gk_beat % 4) == 0 then k_hz = 3000 else k_hz = 2000 endif schedkwhen k_trigger, 0, 1, "Beep", 0, 0.01, k_hz printf "LinkMonitor: gi_link: %g k_enabled: %9.4f k_trigger: %9.4f beat: %9.4f k_phase: %9.4f time: %9.4f tempo: %9.4f peers: %3d\n", k_trigger, gi_link, k_enabled, k_trigger, gk_beat, k_phase, k_time, k_tempo, k_peers endin f 0 360 i "TempoChange" 5 80 i "LinkEnable" 10 1 0 i "LinkEnable" 15 1 1 i "LinkForce" 20 2 0 3 csound-6.10.0/Opcodes/afilters.c000066400000000000000000000552741321653344700164670ustar00rootroot00000000000000/* afilters.c: Copyright (C) 1991 Barry Vercoe, John ffitch, Gabriel Maldonado This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* AFILTERS.C */ #include "ugens5.h" #include extern int rsnset(CSOUND *csound, RESON *p); static int aresonaa(CSOUND *csound, RESON *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t flag = 0, n, nsmps = CS_KSMPS; MYFLT *ar, *asig; double c3p1, c3t4, omc3, c2sqr; /* 1/RMS = root2 (rand) */ /* or 1/.5 (sine) */ double yt1, yt2, c1, c2, c3; asig = p->asig; ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } c1 = p->c1; c2 = p->c2; c3 = p->c3; yt1 = p->yt1; yt2 = p->yt2; if (p->scale == 1 || p->scale == 0) { for (n=offset; nkcf[n] != (MYFLT)p->prvcf) { p->prvcf = (double)p->kcf[n]; p->cosf = cos(p->prvcf * (double)(csound->tpidsr)); flag = 1; } if (p->kbw[n] != (MYFLT)p->prvbw) { p->prvbw = (double)p->kbw[n]; p->c3 = exp(p->prvbw * (double)(csound->mtpdsr)); flag = 1; } if (flag) { c3p1 = p->c3 + 1.0; c3t4 = p->c3 * 4.0; omc3 = 1.0 - p->c3; p->c2 = c3t4 * p->cosf / c3p1; c2sqr = p->c2 * p->c2; if (p->scale == 1) /* i.e. 1 - A(reson) */ p->c1 = 1.0 - omc3 * sqrt(1.0 - c2sqr / c3t4); else if (p->scale == 2) /* i.e. D - A(reson) */ p->c1 = 2.0 - sqrt((c3p1*c3p1-c2sqr)*omc3/c3p1); else p->c1 = 0.0; /* cannot tell */ } ans = c1 * sig + c2 * yt1 - c3 * yt2; yt2 = yt1; yt1 = ans - sig; /* yt1 contains yt1-xt1 */ ar[n] = (MYFLT)ans; } } else if (p->scale == 2) { for (n=offset; nkcf[n] != (MYFLT)p->prvcf) { p->prvcf = (double)p->kcf[n]; p->cosf = cos(p->prvcf * (double)(csound->tpidsr)); flag = 1; } if (p->kbw[n] != (MYFLT)p->prvbw) { p->prvbw = (double)p->kbw[n]; p->c3 = exp(p->prvbw * (double)(csound->mtpdsr)); flag = 1; } if (flag) { c3p1 = p->c3 + 1.0; c3t4 = p->c3 * 4.0; omc3 = 1.0 - p->c3; p->c2 = c3t4 * p->cosf / c3p1; c2sqr = p->c2 * p->c2; if (p->scale == 1) /* i.e. 1 - A(reson) */ p->c1 = 1.0 - omc3 * sqrt(1.0 - c2sqr / c3t4); else if (p->scale == 2) /* i.e. D - A(reson) */ p->c1 = 2.0 - sqrt((c3p1*c3p1-c2sqr)*omc3/c3p1); else p->c1 = 0.0; /* cannot tell */ } ans = c1 * sig + c2 * yt1 - c3 * yt2; yt2 = yt1; yt1 = ans - 2.0 * sig; /* yt1 contains yt1-D*xt1 */ ar[n] = (MYFLT)ans; } } p->yt1 = yt1; p->yt2 = yt2; return OK; } static int aresonak(CSOUND *csound, RESON *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *ar, *asig; double c3p1, c3t4, omc3, c2sqr; /* 1/RMS = root2 (rand) */ /* or 1/.5 (sine) */ double yt1, yt2, c1, c2, c3; if (*p->kbw != (MYFLT)p->prvbw) { p->prvbw = (double)*p->kbw; p->c3 = exp(p->prvbw * (double)(csound->mtpdsr)); c3p1 = p->c3 + 1.0; c3t4 = p->c3 * 4.0; omc3 = 1.0 - p->c3; p->c2 = c3t4 * p->cosf / c3p1; c2sqr = p->c2 * p->c2; if (p->scale == 1) /* i.e. 1 - A(reson) */ p->c1 = 1.0 - omc3 * sqrt(1.0 - c2sqr / c3t4); else if (p->scale == 2) /* i.e. D - A(reson) */ p->c1 = 2.0 - sqrt((c3p1*c3p1-c2sqr)*omc3/c3p1); else p->c1 = 0.0; /* cannot tell */ } asig = p->asig; ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } c1 = p->c1; c2 = p->c2; c3 = p->c3; yt1 = p->yt1; yt2 = p->yt2; if (p->scale == 1 || p->scale == 0) { for (n=offset; nkcf[n] != (MYFLT)p->prvcf) { p->prvcf = (double)p->kcf[n]; p->cosf = cos(p->prvcf * (double)(csound->tpidsr)); c3p1 = p->c3 + 1.0; c3t4 = p->c3 * 4.0; omc3 = 1.0 - p->c3; p->c2 = c3t4 * p->cosf / c3p1; c2sqr = p->c2 * p->c2; if (p->scale == 1) /* i.e. 1 - A(reson) */ p->c1 = 1.0 - omc3 * sqrt(1.0 - c2sqr / c3t4); else if (p->scale == 2) /* i.e. D - A(reson) */ p->c1 = 2.0 - sqrt((c3p1*c3p1-c2sqr)*omc3/c3p1); else p->c1 = 0.0; /* cannot tell */ } ans = c1 * sig + c2 * yt1 - c3 * yt2; yt2 = yt1; yt1 = ans - sig; /* yt1 contains yt1-xt1 */ ar[n] = (MYFLT)ans; } } else if (p->scale == 2) { for (n=offset; nkcf[n] != (MYFLT)p->prvcf) { p->prvcf = (double)p->kcf[n]; p->cosf = cos(p->prvcf * (double)(csound->tpidsr)); c3p1 = p->c3 + 1.0; c3t4 = p->c3 * 4.0; omc3 = 1.0 - p->c3; p->c2 = c3t4 * p->cosf / c3p1; c2sqr = p->c2 * p->c2; if (p->scale == 1) /* i.e. 1 - A(reson) */ p->c1 = 1.0 - omc3 * sqrt(1.0 - c2sqr / c3t4); else if (p->scale == 2) /* i.e. D - A(reson) */ p->c1 = 2.0 - sqrt((c3p1*c3p1-c2sqr)*omc3/c3p1); else p->c1 = 0.0; /* cannot tell */ } ans = c1 * sig + c2 * yt1 - c3 * yt2; yt2 = yt1; yt1 = ans - 2.0 * sig; /* yt1 contains yt1-D*xt1 */ ar[n] = (MYFLT)ans; } } p->yt1 = yt1; p->yt2 = yt2; return OK; } static int aresonka(CSOUND *csound, RESON *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *ar, *asig; double c3p1, c3t4, omc3, c2sqr; /* 1/RMS = root2 (rand) */ /* or 1/.5 (sine) */ double yt1, yt2, c1, c2, c3; if (*p->kcf != (MYFLT)p->prvcf) { p->prvcf = (double)*p->kcf; p->cosf = cos(p->prvcf * (double)(csound->tpidsr)); c3p1 = p->c3 + 1.0; c3t4 = p->c3 * 4.0; omc3 = 1.0 - p->c3; p->c2 = c3t4 * p->cosf / c3p1; c2sqr = p->c2 * p->c2; if (p->scale == 1) /* i.e. 1 - A(reson) */ p->c1 = 1.0 - omc3 * sqrt(1.0 - c2sqr / c3t4); else if (p->scale == 2) /* i.e. D - A(reson) */ p->c1 = 2.0 - sqrt((c3p1*c3p1-c2sqr)*omc3/c3p1); else p->c1 = 0.0; /* cannot tell */ } asig = p->asig; ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } c1 = p->c1; c2 = p->c2; c3 = p->c3; yt1 = p->yt1; yt2 = p->yt2; if (p->scale == 1 || p->scale == 0) { for (n=offset; nkbw[n] != (MYFLT)p->prvbw) { p->prvbw = (double)p->kbw[n]; p->c3 = exp(p->prvbw * (double)(csound->mtpdsr)); c3p1 = p->c3 + 1.0; c3t4 = p->c3 * 4.0; omc3 = 1.0 - p->c3; p->c2 = c3t4 * p->cosf / c3p1; c2sqr = p->c2 * p->c2; if (p->scale == 1) /* i.e. 1 - A(reson) */ p->c1 = 1.0 - omc3 * sqrt(1.0 - c2sqr / c3t4); else if (p->scale == 2) /* i.e. D - A(reson) */ p->c1 = 2.0 - sqrt((c3p1*c3p1-c2sqr)*omc3/c3p1); else p->c1 = 0.0; /* cannot tell */ } ans = c1 * sig + c2 * yt1 - c3 * yt2; yt2 = yt1; yt1 = ans - sig; /* yt1 contains yt1-xt1 */ ar[n] = (MYFLT)ans; } } else if (p->scale == 2) { for (n=offset; nkbw[n] != (MYFLT)p->prvbw) { p->prvbw = (double)p->kbw[n]; p->c3 = exp(p->prvbw * (double)(csound->mtpdsr)); c3p1 = p->c3 + 1.0; c3t4 = p->c3 * 4.0; omc3 = 1.0 - p->c3; p->c2 = c3t4 * p->cosf / c3p1; c2sqr = p->c2 * p->c2; if (p->scale == 1) /* i.e. 1 - A(reson) */ p->c1 = 1.0 - omc3 * sqrt(1.0 - c2sqr / c3t4); else if (p->scale == 2) /* i.e. D - A(reson) */ p->c1 = 2.0 - sqrt((c3p1*c3p1-c2sqr)*omc3/c3p1); else p->c1 = 0.0; /* cannot tell */ } ans = c1 * sig + c2 * yt1 - c3 * yt2; yt2 = yt1; yt1 = ans - 2.0 * sig; /* yt1 contains yt1-D*xt1 */ ar[n] = (MYFLT)ans; } } p->yt1 = yt1; p->yt2 = yt2; return OK; } extern int tonset(CSOUND*, TONE*); extern int tonsetx(CSOUND *csound, TONEX *p); static int atonea(CSOUND *csound, TONE *p) { MYFLT *ar, *asig; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; double c2 = p->c2, yt1 = p->yt1; ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } asig = p->asig; for (n=offset; nkhp[n] != p->prvhp) { double b; p->prvhp = p->khp[n]; b = 2.0 - cos((double)(p->khp[n] * csound->tpidsr)); p->c2 = c2 = b - sqrt(b * b - 1.0); /* p->c1 = c1 = 1.0 - c2; */ } x = yt1 = c2 * (yt1 + sig); ar[n] = (MYFLT)x; yt1 -= sig; /* yt1 contains yt1-xt1 */ } p->yt1 = yt1; return OK; } static int tonea(CSOUND *csound, TONE *p) { MYFLT *ar, *asig; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; double c1 = p->c1, c2 = p->c2; double yt1 = p->yt1; double prvhp = p->prvhp; ar = p->ar; asig = p->asig; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nkhp[n] != prvhp) { double b; prvhp = (double)p->khp[n]; b = 2.0 - cos((double)(prvhp * csound->tpidsr)); c2 = b - sqrt(b * b - 1.0); c1 = 1.0 - c2; } yt1 = c1 * (double)(asig[n]) + c2 * yt1; ar[n] = (MYFLT)yt1; } p->yt1 = yt1; p->prvhp = prvhp; p->c1 = c1; p->c2 = c2; return OK; } static int tonexa(CSOUND *csound, TONEX *p) /* From Gabriel Maldonado, modified */ { MYFLT *ar = p->ar; double c2 = p->c2, *yt1 = p->yt1,c1 = p->c1; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int j, lp = p->loop; memmove(ar,p->asig,sizeof(MYFLT)*nsmps); if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (j=0; j< lp; j++) { /* Should *yt1 be reset to something?? */ for (n=offset; nkhp[n] != p->prvhp) { double b; p->prvhp = (double)p->khp[n]; b = 2.0 - cos(p->prvhp * (double)csound->tpidsr); p->c2 = b - sqrt(b * b - 1.0); p->c1 = 1.0 - p->c2; } x = c1 * ar[n] + c2 * yt1[j]; yt1[j] = x; ar[n] = (MYFLT)x; } } return OK; } static int atonexa(CSOUND *csound, TONEX *p) /* Gabriel Maldonado, modified */ { MYFLT *ar = p->ar; double c2 = p->c2, *yt1 = p->yt1; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int j, lp = p->loop; MYFLT prvhp = p->prvhp; memmove(ar,p->asig,sizeof(MYFLT)*nsmps); if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (j=1; jkhp[n] != prvhp) { double b; prvhp = p->khp[n]; b = 2.0 - cos((double)(p->prvhp * csound->tpidsr)); c2 = b - sqrt(b * b - 1.0); } x = c2 * (yt1[j] + sig); yt1[j] = x - sig; /* yt1 contains yt1-xt1 */ ar[n] = (MYFLT)x; } } p->c2 = c2; p->prvhp = prvhp; return OK; } typedef struct { OPDS h; MYFLT *sr, *ain, *afc, *istor; MYFLT lkf; double a[8]; } BFIL; typedef struct { OPDS h; MYFLT *sr, *ain, *kfo, *kbw, *istor; MYFLT lkf, lkb; double a[8]; } BBFIL; #define ROOT2 (1.4142135623730950488) extern int butset(CSOUND *csound, BFIL *p); static int bbutset(CSOUND *csound, BBFIL *p) /* Band set-up */ { if (*p->istor==FL(0.0)) { p->a[6] = p->a[7] = 0.0; p->lkb = FL(0.0); p->lkf = FL(0.0); } return OK; } static int hibuta(CSOUND *csound, BFIL *p) /* Hipass filter */ { MYFLT *out, *in; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nsmps = CS_KSMPS; double *a; double t, y; uint32_t nn; a = p->a; in = p->ain; out = p->sr; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } if (UNLIKELY(p->afc[0] <= FL(0.0))) { memcpy(&out[offset], &in[offset], (nsmps-offset)*sizeof(MYFLT)); return OK; } /* if (p->afc[0] != p->lkf) { */ /* p->lkf = p->afc[0]; */ /* c = tan((double)(csound->pidsr * p->lkf)); */ /* a[1] = 1.0 / ( 1.0 + ROOT2 * c + c * c); */ /* a[2] = -(a[1] + a[1]); */ /* a[3] = a[1]; */ /* a[4] = 2.0 * ( c*c - 1.0) * a[1]; */ /* a[5] = ( 1.0 - ROOT2 * c + c * c) * a[1]; */ /* } */ for (nn=offset; nnafc[nn] != p->lkf) { double c; p->lkf = p->afc[nn]; c = tan((double)(csound->pidsr * p->lkf)); a[1] = 1.0 / ( 1.0 + ROOT2 * c + c * c); a[2] = -(a[1] + a[1]); a[3] = a[1]; a[4] = 2.0 * ( c*c - 1.0) * a[1]; a[5] = ( 1.0 - ROOT2 * c + c * c) * a[1]; } t = (double)in[nn] - a[4] * a[6] - a[5] * a[7]; t = csoundUndenormalizeDouble(t); /* Not needed on AMD */ y = t * a[1] + a[2] * a[6] + a[3] * a[7]; a[7] = a[6]; a[6] = t; out[nn] = (MYFLT)y; } return OK; } static int lobuta(CSOUND *csound, BFIL *p) /* Lopass filter */ { MYFLT *out, *in; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nsmps = CS_KSMPS; double *a = p->a; double t, y; uint32_t nn; in = p->ain; out = p->sr; if (UNLIKELY(*p->afc <= FL(0.0))) { memset(out, 0, CS_KSMPS*sizeof(MYFLT)); return OK; } if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } /* if (p->afc[0] != p->lkf) { */ /* p->lkf = p->afc[0]; */ /* c = 1.0 / tan((double)(csound->pidsr * p->lkf)); */ /* a[1] = 1.0 / ( 1.0 + ROOT2 * c + c * c); */ /* a[2] = a[1] + a[1]; */ /* a[3] = a[1]; */ /* a[4] = 2.0 * ( 1.0 - c*c) * a[1]; */ /* a[5] = ( 1.0 - ROOT2 * c + c * c) * a[1]; */ /* } */ for (nn=offset; nnafc[nn] != p->lkf) { double c; p->lkf = p->afc[nn]; c = 1.0 / tan((double)(csound->pidsr * p->lkf)); a[1] = 1.0 / ( 1.0 + ROOT2 * c + c * c); a[2] = a[1] + a[1]; a[3] = a[1]; a[4] = 2.0 * ( 1.0 - c*c) * a[1]; a[5] = ( 1.0 - ROOT2 * c + c * c) * a[1]; } t = (double)in[nn] - a[4] * a[6] - a[5] * a[7]; t = csoundUndenormalizeDouble(t); /* Not needed on AMD */ y = t * a[1] + a[2] * a[6] + a[3] * a[7]; a[7] = a[6]; a[6] = t; out[nn] = (MYFLT)y; } return OK; } static int bppasxx(CSOUND *csound, BBFIL *p) /* Bandpass filter */ { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nsmps = CS_KSMPS; MYFLT *out, *in; double *a = p->a; double t, y; uint32_t nn; int asgbw = IS_ASIG_ARG(p->kbw), asgfr = IS_ASIG_ARG(p->kfo); in = p->ain; out = p->sr; if (UNLIKELY(p->kbw[0] <= FL(0.0))) { memset(out, 0, CS_KSMPS*sizeof(MYFLT)); return OK; } if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } /* if (p->kbw[0] != p->lkb || p->kfo[0] != p->lkf) { */ /* p->lkf = p->kfo[0]; */ /* p->lkb = p->kbw[0]; */ /* c = 1.0 / tan((double)(csound->pidsr * p->lkb)); */ /* d = 2.0 * cos((double)(csound->tpidsr * p->lkf)); */ /* a[1] = 1.0 / (1.0 + c); */ /* a[2] = 0.0; */ /* a[3] = -a[1]; */ /* a[4] = - c * d * a[1]; */ /* a[5] = (c - 1.0) * a[1]; */ /* } */ //butter_filter(nsmps, offset, in, out, p->a); for (nn=offset; nnkbw[nn] : *p->kbw); fr = (asgfr ? p->kfo[nn] : *p->kfo); if (bw != p->lkb || fr != p->lkf) { double c, d; p->lkf = fr; p->lkb = bw; c = 1.0 / tan((double)(csound->pidsr * bw)); d = 2.0 * cos((double)(csound->tpidsr * fr)); a[1] = 1.0 / (1.0 + c); a[2] = 0.0; a[3] = -a[1]; a[4] = - c * d * a[1]; a[5] = (c - 1.0) * a[1]; } t = (double)in[nn] - a[4] * a[6] - a[5] * a[7]; t = csoundUndenormalizeDouble(t); /* Not needed on AMD */ y = t * a[1] + a[2] * a[6] + a[3] * a[7]; a[7] = a[6]; a[6] = t; out[nn] = (MYFLT)y; } return OK; } static int bpcutxx(CSOUND *csound, BBFIL *p) /* Band reject filter */ { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nsmps = CS_KSMPS; MYFLT *out, *in; double *a = p->a; double t, y; uint32_t nn; int asgbw = IS_ASIG_ARG(p->kbw), asgfr = IS_ASIG_ARG(p->kfo); in = p->ain; out = p->sr; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } if (UNLIKELY(p->kbw[0] <= FL(0.0))) { memcpy(&out[offset], &in[offset], (nsmps-offset)*sizeof(MYFLT)); return OK; } for (nn=offset; nnkbw[nn] : *p->kbw); fr = (asgfr ? p->kfo[nn] : *p->kfo); if (bw != p->lkb || fr != p->lkf) { double c, d; p->lkf = fr; p->lkb = bw; c = tan((double)(csound->pidsr * bw)); d = 2.0 * cos((double)(csound->tpidsr * fr)); a[1] = 1.0 / (1.0 + c); a[2] = - d * a[1]; a[3] = a[1]; a[4] = a[2]; a[5] = (1.0 - c) * a[1]; } t = (double)in[nn] - a[4] * a[6] - a[5] * a[7]; t = csoundUndenormalizeDouble(t); /* Not needed on AMD */ y = t * a[1] + a[2] * a[6] + a[3] * a[7]; a[7] = a[6]; a[6] = t; out[nn] = (MYFLT)y; } return OK; } static OENTRY afilts_localops[] = { { "areson.aa", sizeof(RESON), 0,5,"a","aaaoo",(SUBR)rsnset,NULL,(SUBR)aresonaa}, { "areson.ak", sizeof(RESON), 0,5,"a","aakoo",(SUBR)rsnset,NULL,(SUBR)aresonak}, { "areson.ka", sizeof(RESON), 0,5,"a","akaoo",(SUBR)rsnset,NULL,(SUBR)aresonka}, { "atone.a", sizeof(TONE), 0,5,"a","ako", (SUBR)tonset,NULL,(SUBR)atonea }, { "atonex.a", sizeof(TONEX), 0,5, "a","aaoo",(SUBR)tonsetx,NULL,(SUBR)atonexa}, { "tone.a", sizeof(TONE), 0,5,"a","aao", (SUBR)tonset,NULL,(SUBR)tonea }, { "tonex.a", sizeof(TONEX), 0,5,"a","aaoo", (SUBR)tonsetx,NULL,(SUBR)tonexa }, { "butterhp.a", sizeof(BFIL), 0,5,"a","aao", (SUBR)butset,NULL,(SUBR)hibuta }, { "butterlp.a", sizeof(BFIL), 0,5,"a","aao", (SUBR)butset,NULL,(SUBR)lobuta }, { "buthp.a", sizeof(BFIL), 0,5,"a","aao", (SUBR)butset,NULL,(SUBR)hibuta }, { "butlp.a", sizeof(BFIL), 0,5,"a","aao", (SUBR)butset,NULL,(SUBR)lobuta }, { "butterbp", sizeof(BBFIL),0,5,"a","axxo", (SUBR)bbutset,NULL,(SUBR)bppasxx}, { "butbp", sizeof(BBFIL),0,5,"a","axxo", (SUBR)bbutset,NULL,(SUBR)bppasxx}, { "butterbr", sizeof(BBFIL),0,5,"a","axxo", (SUBR)bbutset,NULL,(SUBR)bpcutxx}, { "butbr", sizeof(BBFIL),0,5,"a","axxo", (SUBR)bbutset,NULL,(SUBR)bpcutxx}, }; LINKAGE_BUILTIN(afilts_localops) csound-6.10.0/Opcodes/ambicode.c000066400000000000000000000657751321653344700164300ustar00rootroot00000000000000/* ambicode.c: Copyright (C) 2005 Samuel Groner, Institute for Computer Music and Sound Technology, www.icst.net This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "interlocks.h" #include typedef struct { OPDS h; /* required header */ MYFLT *mw, *mx, *my, *mz, *mr, *ms, *mt, *mu, *mv, *mk, *ml, *mm, *mn, *mo, *mp, *mq; /* addr outarg */ MYFLT *asig, *kalpha, *kbeta, *kin[4]; /* addr inargs */ /* private dataspace */ double w, x, y, z, r, s, t, u, v, k, l, m, n, o, p, q; } AMBIC; typedef struct { OPDS h; /* required header */ MYFLT *m0, *m1, *m2, *m3, *m4, *m5, *m6, *m7; /* addr outarg */ MYFLT *isetup, *aw, *ax, *ay, *a[VARGMAX]; /* addr inargs */ /* private dataspace */ double w[8], x[8], y[8], z[8], r[8], s[8], t[8], u[8], v[8], k[8], l[8], m[8], n[8], o[8], p[8], q[8]; } AMBID; static int iambicode(CSOUND *csound, AMBIC *p) { csound->Warning(csound, Str("bformenc is deprecated; use bformenc1 instead\n")); /* check correct number of input and output arguments */ switch (p->OUTOCOUNT) { case 4: /* { */ /* /\* 2nd order *\/ */ /* if (p->INOCOUNT != 5) { */ /* return csound->InitError(csound, */ /* Str("Wrong number of input arguments! " */ /* "5 needed!")); */ /* } */ /* break; */ /* } */ case 9: /* { */ /* /\* 3rd order *\/ */ /* if (p->INOCOUNT != 6) { */ /* return csound->InitError(csound, */ /* Str("Wrong number of input arguments! " */ /* "6 needed!")); */ /* } */ /* break; */ /* } */ case 16: /* { */ /* /\* 4th order *\/ */ /* if (p->INOCOUNT != 7) { */ /* return csound->InitError(csound, */ /* Str("Wrong number of input arguments! " */ /* "7 needed!")); */ /* } */ /* break; */ /* } */ break; default: { return csound->InitError(csound, Str("Wrong number of output arguments! " "4, 9 or 16 needed!")); } } return OK; } static void ambicode_set_coefficients(AMBIC *p) { /* convert degrees to radian */ /* 0.017 = pi/180 */ double kalpha_rad = (double)(*p->kalpha)*0.0174532925199432957692369076848861; double kbeta_rad = (double)(*p->kbeta)*0.0174532925199432957692369076848861; /* calculate ambisonic coefficients (Furse-Malham-set) */ /* 0th order */ p->w = 0.707106781186547524400844362104849 /* (1.0 / sqrt(2.0)) */ ; /* 1st order */ { double ck = cos(kbeta_rad); p->x = cos(kalpha_rad) * ck; p->y = sin(kalpha_rad) * ck; p->z = sin(kbeta_rad); } /* 2nd order */ p->r = 0.5 * (3.0 * p->z * p->z - 1.0); p->s = 2.0 * p->x * p->z; p->t = 2.0 * p->y * p->z; p->u = p->x * p->x - p->y * p->y; p->v = 2.0 * p->x * p->y; /* 3rd order */ p->k = 0.5 * p->z * (5.0 * p->z * p->z - 3.0); p->l = (8.0 / 11.0) * p->y * (5.0 * p->z * p->z - 1.0); p->m = (8.0 / 11.0) * p->x * (5.0 * p->z * p->z - 1.0); p->n = 2.0 * p->x * p->y * p->z; p->o = p->z * (p->x * p->x - p->y * p->y); p->p = 3.0 * p->y * (3.0 * p->x * p->x - p->y * p->y); p->q = 3.0 * p->x * (p->x * p->x - 3.0 * p->y * p->y); } static int aambicode(CSOUND *csound, AMBIC *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; /* array size from orchestra */ /* init input array pointer */ MYFLT *inptp = p->asig; /* init output array pointer 0th order */ MYFLT *rsltp_w = p->mw; /* init output array pointers 1th order */ MYFLT *rsltp_x = p->mx; MYFLT *rsltp_y = p->my; MYFLT *rsltp_z = p->mz; /* init output array pointers 2nd order */ MYFLT *rsltp_r = p->mr; MYFLT *rsltp_s = p->ms; MYFLT *rsltp_t = p->mt; MYFLT *rsltp_u = p->mu; MYFLT *rsltp_v = p->mv; /* init output array pointers 3rd order */ MYFLT *rsltp_k = p->mk; MYFLT *rsltp_l = p->ml; MYFLT *rsltp_m = p->mm; MYFLT *rsltp_n = p->mn; MYFLT *rsltp_o = p->mo; MYFLT *rsltp_p = p->mp; MYFLT *rsltp_q = p->mq; /* update coefficients */ ambicode_set_coefficients(p); if (UNLIKELY(offset)) { memset(rsltp_w, '\0', offset*sizeof(MYFLT)); memset(rsltp_x, '\0', offset*sizeof(MYFLT)); memset(rsltp_y, '\0', offset*sizeof(MYFLT)); memset(rsltp_z, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&rsltp_w[nsmps], '\0', early*sizeof(MYFLT)); memset(&rsltp_x[nsmps], '\0', early*sizeof(MYFLT)); memset(&rsltp_y[nsmps], '\0', early*sizeof(MYFLT)); memset(&rsltp_z[nsmps], '\0', early*sizeof(MYFLT)); } if (p->OUTOCOUNT == 4 && p->INOCOUNT >= 5) { /* 1st order */ for (n=offset; nw * *p->kin[0]; /* 1st order */ rsltp_x[n] = inptp[n] * p->x * *p->kin[1]; rsltp_y[n] = inptp[n] * p->y * *p->kin[1]; rsltp_z[n] = inptp[n] * p->z * *p->kin[1]; } } else if (p->OUTOCOUNT == 9 && p->INOCOUNT >= 6) { /* 2nd order */ if (UNLIKELY(offset)) { memset(rsltp_r, '\0', offset*sizeof(MYFLT)); memset(rsltp_s, '\0', offset*sizeof(MYFLT)); memset(rsltp_t, '\0', offset*sizeof(MYFLT)); memset(rsltp_u, '\0', offset*sizeof(MYFLT)); memset(rsltp_v, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { memset(&rsltp_r[nsmps], '\0', early*sizeof(MYFLT)); memset(&rsltp_s[nsmps], '\0', early*sizeof(MYFLT)); memset(&rsltp_t[nsmps], '\0', early*sizeof(MYFLT)); memset(&rsltp_u[nsmps], '\0', early*sizeof(MYFLT)); memset(&rsltp_v[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nw * *p->kin[0]; /* 1st order */ rsltp_x[n] = inptp[n] * p->x * *p->kin[1]; rsltp_y[n] = inptp[n] * p->y * *p->kin[1]; rsltp_z[n] = inptp[n] * p->z * *p->kin[1]; /* 2nd order */ rsltp_r[n] = inptp[n] * p->r * *p->kin[2]; rsltp_s[n] = inptp[n] * p->s * *p->kin[2]; rsltp_t[n] = inptp[n] * p->t * *p->kin[2]; rsltp_u[n] = inptp[n] * p->u * *p->kin[2]; rsltp_v[n] = inptp[n] * p->v * *p->kin[2]; } } else if (p->OUTOCOUNT == 16 && p->INOCOUNT >= 7) { /* 3rd order */ if (UNLIKELY(offset)) { memset(rsltp_r, '\0', offset*sizeof(MYFLT)); memset(rsltp_s, '\0', offset*sizeof(MYFLT)); memset(rsltp_t, '\0', offset*sizeof(MYFLT)); memset(rsltp_u, '\0', offset*sizeof(MYFLT)); memset(rsltp_v, '\0', offset*sizeof(MYFLT)); memset(rsltp_k, '\0', offset*sizeof(MYFLT)); memset(rsltp_l, '\0', offset*sizeof(MYFLT)); memset(rsltp_m, '\0', offset*sizeof(MYFLT)); memset(rsltp_n, '\0', offset*sizeof(MYFLT)); memset(rsltp_o, '\0', offset*sizeof(MYFLT)); memset(rsltp_p, '\0', offset*sizeof(MYFLT)); memset(rsltp_q, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { memset(&rsltp_r[nsmps], '\0', early*sizeof(MYFLT)); memset(&rsltp_s[nsmps], '\0', early*sizeof(MYFLT)); memset(&rsltp_t[nsmps], '\0', early*sizeof(MYFLT)); memset(&rsltp_u[nsmps], '\0', early*sizeof(MYFLT)); memset(&rsltp_v[nsmps], '\0', early*sizeof(MYFLT)); memset(&rsltp_k[nsmps], '\0', early*sizeof(MYFLT)); memset(&rsltp_l[nsmps], '\0', early*sizeof(MYFLT)); memset(&rsltp_m[nsmps], '\0', early*sizeof(MYFLT)); memset(&rsltp_n[nsmps], '\0', early*sizeof(MYFLT)); memset(&rsltp_o[nsmps], '\0', early*sizeof(MYFLT)); memset(&rsltp_p[nsmps], '\0', early*sizeof(MYFLT)); memset(&rsltp_q[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nw * *p->kin[0]; /* 1st order */ rsltp_x[n] = inptp[n] * p->x * *p->kin[1]; rsltp_y[n] = inptp[n] * p->y * *p->kin[1]; rsltp_z[n] = inptp[n] * p->z * *p->kin[1]; /* 2nd order */ rsltp_r[n] = inptp[n] * p->r * *p->kin[2]; rsltp_s[n] = inptp[n] * p->s * *p->kin[2]; rsltp_t[n] = inptp[n] * p->t * *p->kin[2]; rsltp_u[n] = inptp[n] * p->u * *p->kin[2]; rsltp_v[n] = inptp[n] * p->v * *p->kin[2]; /* 3rd order */ rsltp_k[n] = inptp[n] * p->k * *p->kin[3]; rsltp_l[n] = inptp[n] * p->l * *p->kin[3]; rsltp_m[n] = inptp[n] * p->m * *p->kin[3]; rsltp_n[n] = inptp[n] * p->n * *p->kin[3]; rsltp_o[n] = inptp[n] * p->o * *p->kin[3]; rsltp_p[n] = inptp[n] * p->p * *p->kin[3]; rsltp_q[n] = inptp[n] * p->q * *p->kin[3]; } } return OK; } static void ambideco_set_coefficients(AMBID *p, double alpha, double beta, int index) { /* convert degrees to radian */ /* 0.017... = pi/180 */ double alpha_rad = alpha * 0.0174532925199432957692369076848861; double beta_rad = beta * 0.0174532925199432957692369076848861; /* calculate ambisonic coefficients (Furse-Malham-set) */ /* 0th order */ p->w[index] = 0.707106781186547524400844362104849; /* 1/sqrt(2) */ /* 1st order */ { double cbeta = cos(beta_rad); p->x[index] = cos(alpha_rad) * cbeta; p->y[index] = sin(alpha_rad) * cbeta; p->z[index] = sin(beta_rad); } /* 2nd order */ p->r[index] = 0.5 * (3.0 * p->z[index] * p->z[index] - 1.0); p->s[index] = 2.0 * p->x[index] * p->z[index]; p->t[index] = 2.0 * p->y[index] * p->z[index]; p->u[index] = p->x[index] * p->x[index] - p->y[index] * p->y[index]; p->v[index] = 2.0 * p->x[index] * p->y[index]; /* 3rd order */ p->k[index] = 0.5 * p->z[index] * (5.0 * p->z[index] * p->z[index] - 3.0); p->l[index] = (8.0/11.0) * p->y[index] * (5.0*p->z[index]* p->z[index] - 1.0); p->m[index] = (8.0/11.0) * p->x[index] * (5.0*p->z[index]* p->z[index] - 1.0); p->n[index] = 2.0 * p->x[index] * p->y[index] * p->z[index]; p->o[index] = p->z[index] * (p->x[index] * p->x[index] - p->y[index] * p->y[index]); p->p[index] = 3.0 * p->y[index] * (3.0 * p->x[index] * p->x[index] - p->y[index] * p->y[index]); p->q[index] = 3.0 * p->x[index] * (p->x[index] * p->x[index] - 3.0 * p->y[index] * p->y[index]); } static int iambideco(CSOUND *csound, AMBID *p) { int setup = (int)*p->isetup; csound->Warning(csound, Str("bformdec is deprecated; use bformdec1 instead\n")); if (setup<0) setup = -setup; /* check correct number of input arguments */ if (UNLIKELY((p->INOCOUNT != 5) && (p->INOCOUNT != 10) && (p->INOCOUNT != 17))) { return csound->InitError(csound, Str("Wrong number of input arguments!")); } switch (setup) { case 1: { if (UNLIKELY(p->OUTOCOUNT != 2)) { return csound->InitError(csound, Str("Wrong number of output cells! " "There must be 2 output cells.")); } else if (*p->isetup>0) { ambideco_set_coefficients(p, 330.0, 0.0, 0); /* left */ ambideco_set_coefficients(p, 30.0, 0.0, 1); /* right */ } else { int i; static double w[] = {0.707106781186547524400844362104849, 0.707106781186547524400844362104849}; /* static double x[] = {0.0, 0.0}; */ static double y[] = {0.5000,-0.5000}; /* static double z[] = {0.0, 0.0}; */ /* static double r[] = {0.0, 0.0}; */ /* static double s[] = {0.0, 0.0}; */ /* static double t[] = {0.0, 0.0}; */ /* static double u[] = {0.0, 0.0}; */ /* static double v[] = {0.0, 0.0}; */ for (i=0; i<2; i++) { p->w[i] = w[i]; p->x[i] = 0.0; p->y[i] = y[i]; p->z[i] = 0.0; p->r[i] = 0.0; p->s[i] = 0.0; p->t[i] = 0.0; p->u[i] = 0.0; p->v[i] = 0.0; p->k[i] = 0.0; p->l[i] = 0.0; p->m[i] = 0.0; p->n[i] = 0.0; p->o[i] = 0.0; p->p[i] = 0.0; p->q[i] = 0.0; } } break; } case 2: { if (UNLIKELY(p->OUTOCOUNT != 4)) { return csound->InitError(csound, Str("Wrong number of output cells! " "There must be 4 output cells.")); } else if (*p->isetup>0) { ambideco_set_coefficients(p, 45.0, 0.0, 0); ambideco_set_coefficients(p, 135.0, 0.0, 1); ambideco_set_coefficients(p, 225.0, 0.0, 2); ambideco_set_coefficients(p, 315.0, 0.0, 3); } else { int i; static double w[] = {0.3536, 0.3536, 0.3536, 0.3536}; static double x[] = {0.2434, 0.2434, -0.2434, -0.2434}; static double y[] = {0.2434, -0.2434, -0.2434, 0.2434}; /* static double z[] = {0.0, 0.0, 0.0, 0.0}; */ /* static double r[] = {0.0, 0.0, 0.0, 0.0}; */ /* static double s[] = {0.0, 0.0, 0.0, 0.0}; */ /* static double t[] = {0.0, 0.0, 0.0, 0.0}; */ /* static double u[] = {0.0, 0.0, 0.0, 0.0}; */ static double v[] = {0.0964, -0.0964, 0.0964, -0.0964}; for (i=0; i<4; i++) { p->w[i] = w[i]; p->x[i] = x[i]; p->y[i] = y[i]; p->z[i] = 0.0; p->r[i] = 0.0; p->s[i] = 0.0; p->t[i] = 0.0; p->u[i] = 0.0; p->v[i] = v[i]; p->k[i] = 0.0; p->l[i] = 0.0; p->m[i] = 0.0; p->n[i] = 0.0; p->o[i] = 0.0; p->p[i] = 0.0; p->q[i] = 0.0; } } break; } case 3: { if (UNLIKELY(p->OUTOCOUNT != 5)) { return csound->InitError(csound, Str("Wrong number of output cells! " "There must be 5 output cells.")); } else if (*p->isetup>0) { ambideco_set_coefficients(p, 330.0, 0.0, 0); /* left */ ambideco_set_coefficients(p, 30.0, 0.0, 1); /* right */ ambideco_set_coefficients(p, 0.0, 0.0, 2); /* center */ ambideco_set_coefficients(p, 250.0, 0.0, 3); /* surround L */ ambideco_set_coefficients(p, 110.0, 0.0, 4); /* surround R */ } else { int i; /* Furze controlled opposites */ static double w[] = {0.2828, 0.2828, 0.2828, 0.2828, 0.2828}; static double x[] = {0.2227, -0.0851, -0.2753, -0.0851, 0.2227}; static double y[] = {0.1618, 0.2619, 0.0000, -0.2619, -0.1618}; /* static double z[] = {0.0, 0.0, 0.0, 0.0}; */ /* static double r[] = {0.0, 0.0, 0.0, 0.0}; */ /* static double s[] = {0.0, 0.0, 0.0, 0.0}; */ /* static double t[] = {0.0, 0.0, 0.0, 0.0}; */ static double u[] = {0.0238, -0.0624, 0.0771, -0.0624, 0.0238}; static double v[] = {0.0733, -0.0453, 0.0000, 0.0453, -0.0733}; for (i=0; i<5; i++) { p->w[i] = w[i]; p->x[i] = x[i]; p->y[i] = y[i]; p->z[i] = 0.0; p->r[i] = 0.0; p->s[i] = 0.0; p->t[i] = 0.0; p->u[i] = u[i]; p->v[i] = v[i]; p->k[i] = 0.0; p->l[i] = 0.0; p->m[i] = 0.0; p->n[i] = 0.0; p->o[i] = 0.0; p->p[i] = 0.0; p->q[i] = 0.0; } } break; } case 4: { if (UNLIKELY(p->OUTOCOUNT != 8)) { return csound->InitError(csound, Str("Wrong number of output cells! " "There must be 8 output cells.")); } else if (*p->isetup>0) { ambideco_set_coefficients(p, 22.5, 0.0, 0); ambideco_set_coefficients(p, 67.5, 0.0, 1); ambideco_set_coefficients(p, 112.5, 0.0, 2); ambideco_set_coefficients(p, 157.5, 0.0, 3); ambideco_set_coefficients(p, 202.5, 0.0, 4); ambideco_set_coefficients(p, 247.5, 0.0, 5); ambideco_set_coefficients(p, 292.5, 0.0, 6); ambideco_set_coefficients(p, 337.5, 0.0, 7); } else { int i; static double w[] = {0.1768, 0.1768, 0.1768, 0.1768, 0.1768, 0.1768, 0.1768, 0.1768}; static double x[] = {0.1591, 0.0659, -0.0659,-0.1591, -0.1591,-0.0659, 0.0659, 0.1591}; static double y[] = {0.0659, 0.1591, 0.1591, 0.0659, -0.0659,-0.1591,-0.1591,-0.0659}; /* static double z[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; */ /* static double r[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; */ /* static double s[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; */ /* static double t[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; */ static double u[] = {0.0342,-0.0342,-0.0342, 0.0342, 0.0342,-0.0342,-0.0342, 0.0342}; static double v[] = {0.0342, 0.0342,-0.0342,-0.0342, 0.0342, 0.0342,-0.0342,-0.0342}; for (i=0; i<8; i++) { p->w[i] = w[i]; p->x[i] = x[i]; p->y[i] = y[i]; p->z[i] = 0.0; p->r[i] = 0.0; p->s[i] = 0.0; p->t[i] = 0.0; p->u[i] = u[i]; p->v[i] = v[i]; p->k[i] = 0.0; p->l[i] = 0.0; p->m[i] = 0.0; p->n[i] = 0.0; p->o[i] = 0.0; p->p[i] = 0.0; p->q[i] = 0.0; } } break; } case 5: { if (UNLIKELY(p->OUTOCOUNT != 8)) { return csound->InitError(csound, Str("Wrong number of output cells! " "There must be 8 output cells.")); } else if (*p->isetup>0) { ambideco_set_coefficients(p, 45.0, 0.0, 0); ambideco_set_coefficients(p, 45.0, 30.0, 1); ambideco_set_coefficients(p, 135.0, 0.0, 2); ambideco_set_coefficients(p, 135.0, 30.0, 3); ambideco_set_coefficients(p, 225.0, 0.0, 4); ambideco_set_coefficients(p, 225.0, 30.0, 5); ambideco_set_coefficients(p, 315.0, 0.0, 6); ambideco_set_coefficients(p, 315.0, 30.0, 7); } else { int i; static double w[] = {0.1768,0.1768,0.1768,0.1768, 0.1768,0.1768,0.1768,0.1768}; static double x[] = {0.1140, 0.1140,-0.1140,-0.1140, 0.1140, 0.1140,-0.1140,-0.1140}; static double y[] = {0.1140,-0.1140,-0.1140, 0.1140, 0.1140,-0.1140,-0.1140, 0.1140}; static double z[] = {-0.1140,-0.1140,-0.1140,-0.1140, 0.1140, 0.1140, 0.1140, 0.1140}; /* static double r[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; */ static double s[] = {-0.0369,-0.0369, 0.0369, 0.0369, 0.0369, 0.0369,-0.0369,-0.0369}; static double t[] = {-0.0369, 0.0369, 0.0369,-0.0369, 0.0369,-0.0369,-0.0369, 0.0369}; /* static double u[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; */ static double v[] = { 0.0369,-0.0369, 0.0369,-0.0369, 0.0369,-0.0369, 0.0369,-0.0369}; for (i=0; i<8; i++) { p->w[i] = w[i]; p->x[i] = x[i]; p->y[i] = y[i]; p->z[i] = z[i]; p->r[i] = 0.0; p->s[i] = s[i]; p->t[i] = t[i]; p->u[i] = 0.0; p->v[i] = v[i]; p->k[i] = 0.0; p->l[i] = 0.0; p->m[i] = 0.0; p->n[i] = 0.0; p->o[i] = 0.0; p->p[i] = 0.0; p->q[i] = 0.0; } } break; } case 6: { if (UNLIKELY(p->OUTOCOUNT != 5)) { return csound->InitError(csound, Str("Wrong number of output cells! " "There must be 5 output cells.")); } /* These are Wiggins' cpefficients */ /* L 30° {0.4724, 0.7143, 0.7258, 0.0000, 0.3456} R -30° {0.4724, 0.7143, -0.7258, 0.0000, -0.3456} C 0° {0.3226, 0.7719, 0.0000, 0.0000, 0.4724} LS 110° {0.9101, -0.7834, 0.9562, -0.0806, 0.0000} RS -110° {0.9101, -0.7834, -0.9562, -0.0806, 0.0000} */ { int i; static double w[] = {0.4724, 0.4724, 0.3226, 0.9101, 0.9101}; static double x[] = {0.7143, 0.7143, 0.7719,-0.7834,-0.7834}; static double y[] = {0.7258,-0.7258, 0.0000, 0.9562,-0.9562}; static double u[] = {0.0000,0.0000,0.0000,-0.0806,-0.0806}; static double v[] = {0.3456,-0.3456,0.4724,0.0000,0.0000}; for (i=0; i<5; i++) { p->w[i] = w[i]; p->x[i] = x[i]; p->y[i] = y[i]; p->z[i] = 0.0; p->r[i] = 0.0; p->s[i] = 0.0; p->t[i] = 0.0; p->u[i] = u[i]; p->v[i] = v[i]; p->k[i] = 0.0; p->l[i] = 0.0; p->m[i] = 0.0; p->n[i] = 0.0; p->o[i] = 0.0; p->p[i] = 0.0; p->q[i] = 0.0; } } break; } default: return csound->InitError(csound, Str("Not supported setup number!")); } return OK; } static int aambideco(CSOUND *csound, AMBID *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i=0, n, nsmps = CS_KSMPS; /* init input array pointer 0th order */ MYFLT *inptp_w = p->aw; /* init input array pointer 1st order */ MYFLT *inptp_x = p->ax; MYFLT *inptp_y = p->ay; MYFLT *inptp_z = p->a[0]; /* init input array pointer 2nd order */ MYFLT *inptp_r = p->a[1]; MYFLT *inptp_s = p->a[2]; MYFLT *inptp_t = p->a[3]; MYFLT *inptp_u = p->a[4]; MYFLT *inptp_v = p->a[5]; /* init input array pointer 3rd order */ MYFLT *inptp_k = p->a[6]; MYFLT *inptp_l = p->a[7]; MYFLT *inptp_m = p->a[8]; MYFLT *inptp_n = p->a[9]; MYFLT *inptp_o = p->a[10]; MYFLT *inptp_p = p->a[11]; MYFLT *inptp_q = p->a[12]; /* init output array pointer */ MYFLT *rsltp[8]; rsltp[0] = p->m0; rsltp[1] = p->m1; rsltp[2] = p->m2; rsltp[3] = p->m3; rsltp[4] = p->m4; rsltp[5] = p->m5; rsltp[6] = p->m6; rsltp[7] = p->m7; if (UNLIKELY(offset)) for (i = 0; i < p->OUTOCOUNT; i++) memset(rsltp[i], '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; for (i = 0; i < p->OUTOCOUNT; i++) memset(&rsltp[i][nsmps], '\0', early*sizeof(MYFLT)); } /* L = 0.5 * (0.9397*W + 0.1856*X - j*0.342*W + j*0.5099*X + 0.655*Y) R = 0.5 * (0.9397*W+ 0.1856*X + j*0.342*W - j*0.5099*X - 0.655*Y) */ if (p->INOCOUNT == 5) { for (n=offset; nOUTOCOUNT; i++) { /* calculate output for every used loudspeaker */ rsltp[i][n] = inptp_w[n] * p->w[i] + inptp_x[n] * p->x[i] + inptp_y[n] * p->y[i] + inptp_z[n] * p->z[i]; } } } else if (p->INOCOUNT == 10) { for (n=offset; nOUTOCOUNT; i++) { /* calculate output for every used loudspeaker */ rsltp[i][n] = inptp_w[n] * p->w[i] + inptp_x[n] * p->x[i] + inptp_y[n] * p->y[i] + inptp_z[n] * p->z[i] + inptp_r[n] * p->r[i] + inptp_s[n] * p->s[i] + inptp_t[n] * p->t[i] + inptp_u[n] * p->u[i] + inptp_v[n] * p->v[i]; } } } else if (p->INOCOUNT == 17) { for (n=offset; nOUTOCOUNT; i++) { /* calculate output for every used loudspeaker */ rsltp[i][n] = inptp_w[n] * p->w[i] + inptp_x[n] * p->x[i] + inptp_y[n] * p->y[i] + inptp_z[n] * p->z[i] + inptp_r[n] * p->r[i] + inptp_s[n] * p->s[i] + inptp_t[n] * p->t[i] + inptp_u[n] * p->u[i] + inptp_v[n] * p->v[i] + inptp_k[n] * p->k[i] + inptp_l[n] * p->l[i] + inptp_m[n] * p->m[i] + inptp_n[n] * p->n[i] + inptp_o[n] * p->o[i] + inptp_p[n] * p->p[i] + inptp_q[n] * p->q[i]; } } } return OK; } #define S(x) sizeof(x) static OENTRY localops[] = { { "bformenc", S(AMBIC), _QQ, 5, "mmmmmmmmmmmmmmmm", "akkPPPP", (SUBR)iambicode, NULL, (SUBR)aambicode }, { "bformdec", S(AMBID), _QQ, 5, "mmmmmmmm", "iaaay", (SUBR)iambideco, NULL, (SUBR)aambideco } }; int ambicode_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/ambicode1.c000066400000000000000000001202771321653344700164760ustar00rootroot00000000000000/* ambicode.c: Copyright (C) 2005 Samuel Groner, Institute for Computer Music and Sound Technology, www.icst.net. Modified 2008 Richard Furse (richard at muse dot demon dot co dot uk). In general, 'in-phase' decodes were selected as these generally work alright and are more robust to use by beginners. The 5.0 decode is provided by Bruce Wiggins (b dot j dot wiggins at derby dot ac dot uk). This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "interlocks.h" #include #include /* ------------------------------------------------------------------------- */ typedef struct { /* Required header: */ OPDS h; /* Output channels (4, 9 or 16 in use): */ MYFLT *aouts[16]; /* Input arguments: */ MYFLT *ain, *kangle, *kelevation; } AMBIC; typedef struct { /* Required header: */ OPDS h; /* Output channels (4, 9 or 16 in use): */ ARRAYDAT *tabout; /* Input arguments: */ MYFLT *ain, *kangle, *kelevation; } AMBICA; /* ------------------------------------------------------------------------- */ typedef struct { /* Required header: */ OPDS h; /* Output channels (up to eight supported here, depending on the isetup parameter). */ MYFLT *aouts[8]; /* Input arguments: */ MYFLT *isetup, *ains[VARGMAX]; } AMBID; typedef struct { /* Required header: */ OPDS h; /* Output channels (up to eight supported here, depending on the isetup parameter). */ ARRAYDAT *tabout; /* Input arguments: */ MYFLT *isetup; ARRAYDAT *tabin; uint32_t dim; } AMBIDA; /* ------------------------------------------------------------------------- */ #define ROOT27 (5.1961524227066318806) #define ROOT135d16 (0.72618437741389066597) /* sqrt(135.0/256.0) */ static int ibformenc(CSOUND * csound, AMBIC * p) { /* All we do in here is police our parameters. */ switch (p->OUTOCOUNT) { case 4: case 9: case 16: return OK; default: return csound->InitError (csound, Str("The numbers of input and output arguments are not valid.")); } } static int ibformenc_a(CSOUND * csound, AMBICA * p) { if (UNLIKELY(p->tabout->data==NULL || p->tabout->dimensions!=1)) return csound->InitError(csound, Str("array not initialised in ambibformenc1")); /* All we do in here is police our parameters. */ switch (p->tabout->sizes[0]) { case 4: case 9: case 16: return OK; default: return csound->InitError (csound, Str("The numbers of input and output arguments are not valid.")); } } static int abformenc(CSOUND * csound, AMBIC * p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t sampleCount, sampleIndex, channelCount, channelIndex; double angle, elevation, x, y, z; MYFLT coefficients[16], coefficient, * output, * input; MYFLT x2, y2, z2; /* Find basic mode & angles: */ sampleCount = CS_KSMPS; channelCount = p->OUTOCOUNT; angle = (double)(*(p->kangle)) * (PI / 180.0); elevation = (double)(*(p->kelevation)) * (PI / 180.0); /* Find direction cosines: */ x = cos(elevation); y = x; z = sin(elevation); x *= cos(angle); y *= sin(angle); x2 = x * x; y2 = y * y; z2 = z * z; /* Find directional coefficients: */ switch (channelCount) { case 16: /* Third order. */ coefficients[ 9] = (MYFLT)((2.5 * z2 - 1.5) * z); coefficients[10] = (MYFLT)(ROOT135d16 * x * (5.0 * z2 - 1)); coefficients[11] = (MYFLT)(ROOT135d16 * y * (5.0 * z2 - 1)); coefficients[12] = (MYFLT)(0.5*ROOT27 * z * (x2 - y2)); coefficients[13] = (MYFLT)(ROOT27 * x * y * z); coefficients[14] = (MYFLT)(x * (x2 - 3.0 * y2)); coefficients[15] = (MYFLT)(y * (3.0 * x2 - y2)); /* Deliberately no break;. */ case 9: /* Second order. */ coefficients[ 4] = (MYFLT)(1.5 * z2 - 0.5); coefficients[ 5] = (MYFLT)(2.0 * z * x); coefficients[ 6] = (MYFLT)(2.0 * y * z); coefficients[ 7] = (MYFLT)(x2 - y2); coefficients[ 8] = (MYFLT)(2.0 * x * y); /* Deliberately no break;. */ case 4: /* Zero and first order. */ coefficients[ 0] = SQRT(FL(0.5)); coefficients[ 1] = (MYFLT)x; coefficients[ 2] = (MYFLT)y; coefficients[ 3] = (MYFLT)z; break; default: /* Should never be reached as this is policed at init time. */ assert(0); } /* (There are some repeated multiplies in the code above, but I suggest these aren't removed until everyone is sure the unoptimised code is doing the right thing!) */ /* Process channels: */ if (UNLIKELY(early)) sampleCount -= early; for (channelIndex = 0; channelIndex < channelCount; channelIndex++) { coefficient = coefficients[channelIndex]; input = p->ain; output = p->aouts[channelIndex]; if (UNLIKELY(offset)) memset(output, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) memset(&output[sampleCount], '\0', early*sizeof(MYFLT)); for (sampleIndex = offset; sampleIndex < sampleCount; sampleIndex++) output[sampleIndex] = coefficient * input[sampleIndex]; } return OK; } static int abformenc_a(CSOUND * csound, AMBICA * p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t sampleCount, sampleIndex, channelCount, channelIndex, ksmps; double angle, elevation, x, y, z; MYFLT coefficients[16], coefficient, * output, * input; MYFLT x2, y2, z2; /* Find basic mode & angles: */ ksmps = sampleCount = CS_KSMPS; channelCount = p->tabout->sizes[0]; angle = (double)(*(p->kangle)) * (PI / 180.0); elevation = (double)(*(p->kelevation)) * (PI / 180.0); /* Find direction cosines: */ x = cos(elevation); y = x; z = sin(elevation); x *= cos(angle); y *= sin(angle); x2 = x * x; y2 = y * y; z2 = z * z; /* Find directional coefficients: */ switch (channelCount) { case 16: /* Third order. */ coefficients[ 9] = (MYFLT)((2.5 * z2 - 1.5) * z); coefficients[10] = (MYFLT)(ROOT135d16 * x * (5.0 * z2 - 1)); coefficients[11] = (MYFLT)(ROOT135d16 * y * (5.0 * z2 - 1)); coefficients[12] = (MYFLT)(0.5*ROOT27 * z * (x2 - y2)); coefficients[13] = (MYFLT)(ROOT27 * x * y * z); coefficients[14] = (MYFLT)(x * (x2 - 3.0 * y2)); coefficients[15] = (MYFLT)(y * (3.0 * x2 - y2)); /* Deliberately no break;. */ case 9: /* Second order. */ coefficients[ 4] = (MYFLT)(1.5 * z2 - 0.5); coefficients[ 5] = (MYFLT)(2.0 * z * x); coefficients[ 6] = (MYFLT)(2.0 * y * z); coefficients[ 7] = (MYFLT)(x2 - y2); coefficients[ 8] = (MYFLT)(2.0 * x * y); /* Deliberately no break;. */ case 4: /* Zero and first order. */ coefficients[ 0] = SQRT(FL(0.5)); coefficients[ 1] = (MYFLT)x; coefficients[ 2] = (MYFLT)y; coefficients[ 3] = (MYFLT)z; break; default: /* Should never be reached as this is policed at init time. */ assert(0); } /* (There are some repeated multiplies in the code above, but I suggest these aren't removed until everyone is sure the unoptimised code is doing the right thing!) */ /* Process channels: */ if (UNLIKELY(early)) sampleCount -= early; for (channelIndex = 0; channelIndex < channelCount; channelIndex++) { coefficient = coefficients[channelIndex]; input = p->ain; output = &p->tabout->data[ksmps*channelIndex]; if (UNLIKELY(offset)) memset(output, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) memset(&output[sampleCount], '\0', early*sizeof(MYFLT)); for (sampleIndex = offset; sampleIndex < sampleCount; sampleIndex++) output[sampleIndex] = coefficient * input[sampleIndex]; } return OK; } /* ------------------------------------------------------------------------- */ static int ibformdec(CSOUND * csound, AMBID * p) { /* All we do in here is police our parameters. */ if (UNLIKELY(p->INOCOUNT != 1 + 4 && p->INOCOUNT != 1 + 9 && p->INOCOUNT != 1 + 16)) { return csound->InitError(csound, Str("The number of input arguments is not valid.")); } else if (UNLIKELY(*(p->isetup) < 1 || *(p->isetup) > 5)) { return csound->InitError(csound, Str("The isetup value should be between 1 and 5.")); } else { /* Then we check the output arguments. */ if (*(p->isetup) == 1 && p->OUTOCOUNT == 2) { /* Stereo. */ return OK; } else if (*(p->isetup) == 2 && p->OUTOCOUNT == 4) { /* Quad. */ return OK; } else if (*(p->isetup) == 3 && p->OUTOCOUNT == 5) { /* Surround 5.0. */ return OK; } else if (*(p->isetup) == 4 && p->OUTOCOUNT == 8) { /* Octagon. */ return OK; } else if (*(p->isetup) == 5 && p->OUTOCOUNT == 8) { /* Cube. */ return OK; } else { return csound->InitError(csound, Str("The output channel count does not" " match the isetup value.")); } } return OK; /* Never used */ } static int abformdec(CSOUND * csound, AMBID * p) { /* All assert() calls in here should already have been validated in ibformdec(). I've also abused the notation a fair bit, often holding scaled values in w, x, y etc. */ /* (There are some repeated multiplies in the code below, but I suggest these aren't removed until everyone is sure the unoptimised code is doing the right thing!) */ uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t sampleCount = CS_KSMPS, sampleIndex; MYFLT p0, q, u, v, w, x, y, z; assert(p->INOCOUNT >= 5); switch ((int)*(p->isetup)) { case 1: /* Stereo */ assert(p->OUTOCOUNT == 2); /* Use a 90degree stereo decode, equivalent to a M+S microphone array at the origin. Works better than front-facing arrangements for most purposes, as a composer using this opcode probably wants to hear the back stage. */ if (UNLIKELY(offset)) { memset(p->aouts[0], '\0', offset*sizeof(MYFLT)); memset(p->aouts[1], '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { sampleCount -= early; memset(&p->aouts[0][sampleCount], '\0', early*sizeof(MYFLT)); memset(&p->aouts[1][sampleCount], '\0', early*sizeof(MYFLT)); } for (sampleIndex = offset; sampleIndex < sampleCount; sampleIndex++) { w = p->ains[0][sampleIndex] * SQRT(FL(0.5)); y = p->ains[2][sampleIndex] * FL(0.5); /* Left: */ p->aouts[0][sampleIndex] = w + y; /* Right: */ p->aouts[1][sampleIndex] = w - y; } break; case 2: /* Quad */ assert(p->OUTOCOUNT == 4); if (UNLIKELY(offset)) { memset(p->aouts[0], '\0', offset*sizeof(MYFLT)); memset(p->aouts[1], '\0', offset*sizeof(MYFLT)); memset(p->aouts[2], '\0', offset*sizeof(MYFLT)); memset(p->aouts[3], '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { sampleCount -= early; memset(&p->aouts[0][sampleCount], '\0', early*sizeof(MYFLT)); memset(&p->aouts[1][sampleCount], '\0', early*sizeof(MYFLT)); memset(&p->aouts[2][sampleCount], '\0', early*sizeof(MYFLT)); memset(&p->aouts[3][sampleCount], '\0', early*sizeof(MYFLT)); } /* Use a first-order 'in-phase' decode. */ for (sampleIndex = offset; sampleIndex < sampleCount; sampleIndex++) { w = p->ains[0][sampleIndex] * FL(0.35355); x = p->ains[1][sampleIndex] * FL(0.17677); y = p->ains[2][sampleIndex] * FL(0.17677); /* Front left: */ p->aouts[0][sampleIndex] = w + x + y; /* Back left: */ p->aouts[1][sampleIndex] = w - x + y; /* Back right: */ p->aouts[2][sampleIndex] = w - x - y; /* Front right: */ p->aouts[3][sampleIndex] = w + x - y; } break; case 3: /* 5.0 */ assert(p->OUTOCOUNT == 5); if (UNLIKELY(offset)) { memset(p->aouts[0], '\0', offset*sizeof(MYFLT)); memset(p->aouts[1], '\0', offset*sizeof(MYFLT)); memset(p->aouts[2], '\0', offset*sizeof(MYFLT)); memset(p->aouts[3], '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { sampleCount -= early; memset(&p->aouts[0][sampleCount], '\0', early*sizeof(MYFLT)); memset(&p->aouts[1][sampleCount], '\0', early*sizeof(MYFLT)); memset(&p->aouts[2][sampleCount], '\0', early*sizeof(MYFLT)); memset(&p->aouts[3][sampleCount], '\0', early*sizeof(MYFLT)); } /* This is a second order decoder provided by Bruce Wiggins. It is optimised for high frequency use within a dual-band decoder, however it has good a low-frequency response. It is not quite 'in-phase' but it is not far off. */ if (p->INOCOUNT == 1 + 4) { /* Matrix truncated to first order (not ideal). */ for (sampleIndex = offset; sampleIndex < sampleCount; sampleIndex++) { w = p->ains[0][sampleIndex]; x = p->ains[1][sampleIndex]; y = p->ains[2][sampleIndex]; /* Left: */ p->aouts[0][sampleIndex] = w * FL(0.405) + x * FL(0.32) + y * FL(0.31); /* Right: */ p->aouts[1][sampleIndex] = w * FL(0.405) + x * FL(0.32) - y * FL(0.31); /* Centre: */ p->aouts[2][sampleIndex] = w * FL(0.085) + x * FL(0.04); /* Surround Left: */ p->aouts[3][sampleIndex] = w * FL(0.635) - x * FL(0.335) + y * FL(0.28); /* Surround Right: */ p->aouts[4][sampleIndex] = w * FL(0.635) - x * FL(0.335) - y * FL(0.28); } } else { /* This is the full matrix. */ if (UNLIKELY(offset)) { memset(p->aouts[0], '\0', offset*sizeof(MYFLT)); memset(p->aouts[1], '\0', offset*sizeof(MYFLT)); memset(p->aouts[2], '\0', offset*sizeof(MYFLT)); memset(p->aouts[3], '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { sampleCount -= early; memset(&p->aouts[0][sampleCount], '\0', early*sizeof(MYFLT)); memset(&p->aouts[1][sampleCount], '\0', early*sizeof(MYFLT)); memset(&p->aouts[2][sampleCount], '\0', early*sizeof(MYFLT)); memset(&p->aouts[3][sampleCount], '\0', early*sizeof(MYFLT)); } for (sampleIndex = offset; sampleIndex < sampleCount; sampleIndex++) { w = p->ains[0][sampleIndex]; x = p->ains[1][sampleIndex]; y = p->ains[2][sampleIndex]; u = p->ains[7][sampleIndex]; v = p->ains[8][sampleIndex]; /* Left: */ p->aouts[0][sampleIndex] = (w * FL(0.405) + x * FL(0.32) + y * FL(0.31) + u * FL(0.085) + v * FL(0.125)); /* Right: */ p->aouts[1][sampleIndex] = (w * FL(0.405) + x * FL(0.32) - y * FL(0.31) + u * FL(0.085) - v * FL(0.125)); /* Centre: */ p->aouts[2][sampleIndex] = (w * FL(0.085) + x * FL(0.04) + u * FL(0.045)); /* Surround Left: */ p->aouts[3][sampleIndex] = (w * FL(0.635) - x * FL(0.335) + y * FL(0.28) - u * FL(0.08) + v * FL(0.08)); /* Surround Right: */ p->aouts[4][sampleIndex] = (w * FL(0.635) - x * FL(0.335) - y * FL(0.28) - u * FL(0.08) - v * FL(0.08)); } } break; case 4: /* Octagon: */ assert(p->OUTOCOUNT == 8); if (p->INOCOUNT == 1 + 4) { /* First order 'in-phase' decode: */ if (UNLIKELY(offset)) for (sampleIndex = 0; sampleIndex<8; sampleIndex++) memset(p->aouts[sampleIndex], '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { sampleCount -= early; for (sampleIndex = 0; sampleIndex<8; sampleIndex++) memset(&p->aouts[sampleIndex][sampleCount], '\0', early*sizeof(MYFLT)); } for (sampleIndex = offset; sampleIndex < sampleCount; sampleIndex++) { w = p->ains[0][sampleIndex] * FL(0.17677); x = p->ains[1][sampleIndex]; y = p->ains[2][sampleIndex]; /* About 11 o'clock: */ p->aouts[0][sampleIndex] = w + x * FL(0.11548) + y * FL(0.04783); /* About 10 o'clock: */ p->aouts[1][sampleIndex] = w + x * FL(0.04783) + y * FL(0.11546); /* About 8 o'clock: */ p->aouts[2][sampleIndex] = w - x * FL(0.04783) + y * FL(0.11546); /* About 7 o'clock: */ p->aouts[3][sampleIndex] = w - x * FL(0.11548) + y * FL(0.04783); /* About 5 o'clock: */ p->aouts[4][sampleIndex] = w - x * FL(0.11548) - y * FL(0.04783); /* About 4 o'clock: */ p->aouts[5][sampleIndex] = w - x * FL(0.04783) - y * FL(0.11546); /* About 2 o'clock: */ p->aouts[6][sampleIndex] = w + x * FL(0.04783) - y * FL(0.11546); /* About 1 o'clock: */ p->aouts[7][sampleIndex] = w + x * FL(0.11548) - y * FL(0.04783); } } else if (p->INOCOUNT == 1 + 9) { /* Second order 'in-phase' / 'controlled opposites' decode: */ if (UNLIKELY(offset)) for (sampleIndex = 0; sampleIndex<8; sampleIndex++) memset(p->aouts[sampleIndex], '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { sampleCount -= early; for (sampleIndex = 0; sampleIndex<8; sampleIndex++) memset(&p->aouts[sampleIndex][sampleCount], '\0', early*sizeof(MYFLT)); } for (sampleIndex = offset; sampleIndex < sampleCount; sampleIndex++) { w = p->ains[0][sampleIndex] * FL(0.17677); x = p->ains[1][sampleIndex]; y = p->ains[2][sampleIndex]; u = p->ains[7][sampleIndex] * FL(0.03417); v = p->ains[8][sampleIndex] * FL(0.03417); /* About 11 o'clock: */ p->aouts[0][sampleIndex] = w + x * FL(0.15906) + y * FL(0.06588) + u + v; /* About 10 o'clock: */ p->aouts[1][sampleIndex] = w + x * FL(0.06588) + y * FL(0.15906) - u + v; /* About 8 o'clock: */ p->aouts[2][sampleIndex] = w - x * FL(0.06588) + y * FL(0.15906) - u - v; /* About 7 o'clock: */ p->aouts[3][sampleIndex] = w - x * FL(0.15906) + y * FL(0.06588) + u - v; /* About 5 o'clock: */ p->aouts[4][sampleIndex] = w - x * FL(0.15906) - y * FL(0.06588) + u + v; /* About 4 o'clock: */ p->aouts[5][sampleIndex] = w - x * FL(0.06588) - y * FL(0.15906) - u + v; /* About 2 o'clock: */ p->aouts[6][sampleIndex] = w + x * FL(0.06588) - y * FL(0.15906) - u - v; /* About 1 o'clock: */ p->aouts[7][sampleIndex] = w + x * FL(0.15906) - y * FL(0.06588) + u - v; } } else { assert(p->INOCOUNT == 1 + 16); if (UNLIKELY(offset)) for (sampleIndex = 0; sampleIndex<8; sampleIndex++) memset(p->aouts[sampleIndex], '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { sampleCount -= early; for (sampleIndex = 0; sampleIndex<8; sampleIndex++) memset(&p->aouts[sampleIndex][sampleCount], '\0', early*sizeof(MYFLT)); } /* Third order 'in-phase' / 'controlled opposites' decode: */ for (sampleIndex = offset; sampleIndex < sampleCount; sampleIndex++) { w = p->ains[ 0][sampleIndex] * FL(0.176777); x = p->ains[ 1][sampleIndex]; y = p->ains[ 2][sampleIndex]; u = p->ains[ 7][sampleIndex] * FL(0.053033); v = p->ains[ 8][sampleIndex] * FL(0.053033); p0 = p->ains[14][sampleIndex]; q = p->ains[15][sampleIndex]; /* About 11 o'clock: */ p->aouts[0][sampleIndex] = (w + x * FL(0.173227) + y * FL(0.071753) + u + v + p0 * FL(0.004784) + q * FL(0.011548)); /* About 10 o'clock: */ p->aouts[1][sampleIndex] = (w + x * FL(0.071753) + y * FL(0.173227) - u + v - p0 * FL(0.011548) - q * FL(0.004784)); /* About 8 o'clock: */ p->aouts[2][sampleIndex] = (w - x * FL(0.071753) + y * FL(0.173227) - u - v + p0 * FL(0.004784) - q * FL(0.011548)); /* About 7 o'clock: */ p->aouts[3][sampleIndex] = (w - x * FL(0.173227) + y * FL(0.071753) + u - v - p0 * FL(0.011548) + q * FL(0.004784)); /* About 5 o'clock: */ p->aouts[4][sampleIndex] = (w - x * FL(0.173227) - y * FL(0.071753) + u + v - p0 * FL(0.004784) - q * FL(0.011548)); /* About 4 o'clock: */ p->aouts[5][sampleIndex] = (w - x * FL(0.071753) - y * FL(0.173227) - u + v + p0 * FL(0.011548) + q * FL(0.004784)); /* About 2 o'clock: */ p->aouts[6][sampleIndex] = (w + x * FL(0.071753) - y * FL(0.173227) - u - v - p0 * FL(0.004784) + q * FL(0.011548)); /* About 1 o'clock: */ p->aouts[7][sampleIndex] = (w + x * FL(0.173227) - y * FL(0.071753) + u - v + p0 * FL(0.011548) - q * FL(0.004784)); } } break; case 5: /* Cube: */ assert(p->OUTOCOUNT == 8); /* First order 'in-phase' decode: */ if (UNLIKELY(offset)) for (sampleIndex = 0; sampleIndex<8; sampleIndex++) memset(p->aouts[sampleIndex], '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { sampleCount -= early; for (sampleIndex = 0; sampleIndex<8; sampleIndex++) memset(&p->aouts[sampleIndex][sampleCount], '\0', early*sizeof(MYFLT)); } for (sampleIndex = offset; sampleIndex < sampleCount; sampleIndex++) { w = p->ains[0][sampleIndex] * FL(0.17677); x = p->ains[1][sampleIndex] * FL(0.07216); y = p->ains[2][sampleIndex] * FL(0.07216); z = p->ains[3][sampleIndex] * FL(0.07216); /* Front left bottom: */ p->aouts[0][sampleIndex] = w + x + y - z; /* Front left top: */ p->aouts[1][sampleIndex] = w + x + y + z; /* Back left bottom: */ p->aouts[2][sampleIndex] = w - x + y - z; /* Back left top: */ p->aouts[3][sampleIndex] = w - x + y + z; /* Back right bottom: */ p->aouts[4][sampleIndex] = w - x - y - z; /* Back right top: */ p->aouts[5][sampleIndex] = w - x - y + z; /* Front right bottom: */ p->aouts[6][sampleIndex] = w + x - y - z; /* Front right top: */ p->aouts[7][sampleIndex] = w + x - y + z; } break; default: assert(0); } return OK; } static int ibformdec_a(CSOUND * csound, AMBIDA * p) { int dim; if (p->tabout->data==NULL || p->tabout->dimensions!=1) return csound->InitError(csound, Str("bformdec1 output array not initilised")); dim = p->tabin->sizes[0]; /* All we do in here is police our parameters. */ if (UNLIKELY(dim != 4 && dim != 9 && dim != 16)) { return csound->InitError(csound, Str("The number of input arguments is not valid.")); } else if (UNLIKELY(*(p->isetup) < 1 || *(p->isetup) > 5)) { return csound->InitError(csound, Str("The isetup value should be between 1 and 5.")); } else { p->dim = dim = p->tabout->sizes[0]; /* Then we check the output arguments. */ if (*(p->isetup) == 1 && dim == 2) { /* Stereo. */ return OK; } else if (*(p->isetup) == 2 && dim == 4) { /* Quad. */ return OK; } else if (*(p->isetup) == 3 && dim == 5) { /* Surround 5.0. */ return OK; } else if (*(p->isetup) == 4 && dim == 8) { /* Octagon. */ return OK; } else if (*(p->isetup) == 5 && dim == 8) { /* Cube. */ return OK; } else { return csound->InitError(csound, Str("The output channel count does not" " match the isetup value.")); } } return OK; /* Never used */ } static int abformdec_a(CSOUND * csound, AMBIDA * p) { /* All assert() calls in here should already have been validated in ibformdec(). I've also abused the notation a fair bit, often holding scaled values in w, x, y etc. */ /* (There are some repeated multiplies in the code below, but I suggest these aren't removed until everyone is sure the unoptimised code is doing the right thing!) */ uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t sampleCount = CS_KSMPS, sampleIndex; uint32_t ksmps = sampleCount; MYFLT p0, q, u, v, w, x, y, z; uint32_t dim = p->dim; MYFLT *tabin = p->tabin->data, *tabout = p->tabout->data; switch ((int)*(p->isetup)) { case 1: /* Stereo */ /* Use a 90degree stereo decode, equivalent to a M+S microphone array at the origin. Works better than front-facing arrangements for most purposes, as a composer using this opcode probably wants to hear the back stage. */ if (UNLIKELY(offset)) { memset(&tabout[0], '\0', offset*sizeof(MYFLT)); memset(&tabout[ksmps], '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { sampleCount -= early; memset(&tabout[sampleCount], '\0', early*sizeof(MYFLT)); memset(&tabout[ksmps+sampleCount], '\0', early*sizeof(MYFLT)); } for (sampleIndex = offset; sampleIndex < sampleCount; sampleIndex++) { w = tabin[sampleIndex] * SQRT(FL(0.5)); y = tabin[2*ksmps+sampleIndex] * FL(0.5); /* Left: */ tabout[sampleIndex] = w + y; /* Right: */ tabout[ksmps+sampleIndex] = w - y; } break; case 2: /* Quad */ if (UNLIKELY(offset)) { memset(&tabout[0], '\0', offset*sizeof(MYFLT)); memset(&tabout[ksmps], '\0', offset*sizeof(MYFLT)); memset(&tabout[2*ksmps], '\0', offset*sizeof(MYFLT)); memset(&tabout[3*ksmps], '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { sampleCount -= early; memset(&tabout[sampleCount], '\0', early*sizeof(MYFLT)); memset(&tabout[ksmps+sampleCount], '\0', early*sizeof(MYFLT)); memset(&tabout[2*ksmps+sampleCount], '\0', early*sizeof(MYFLT)); memset(&tabout[3*ksmps+sampleCount], '\0', early*sizeof(MYFLT)); } /* Use a first-order 'in-phase' decode. */ for (sampleIndex = offset; sampleIndex < sampleCount; sampleIndex++) { w = tabin[sampleIndex] * FL(0.35355); x = tabin[ksmps+sampleIndex] * FL(0.17677); y = tabin[2*ksmps+sampleIndex] * FL(0.17677); /* Front left: */ tabout[sampleIndex] = w + x + y; /* Back left: */ tabout[ksmps+sampleIndex] = w - x + y; /* Back right: */ tabout[2*ksmps+sampleIndex] = w - x - y; /* Front right: */ tabout[3*ksmps+sampleIndex] = w + x - y; } break; case 3: /* 5.0 */ if (UNLIKELY(offset)) { memset(&tabout[0], '\0', offset*sizeof(MYFLT)); memset(&tabout[ksmps], '\0', offset*sizeof(MYFLT)); memset(&tabout[2*ksmps], '\0', offset*sizeof(MYFLT)); memset(&tabout[3*ksmps], '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { sampleCount -= early; memset(&tabout[sampleCount], '\0', early*sizeof(MYFLT)); memset(&tabout[ksmps+sampleCount], '\0', early*sizeof(MYFLT)); memset(&tabout[2*ksmps+sampleCount], '\0', early*sizeof(MYFLT)); memset(&tabout[3*ksmps+sampleCount], '\0', early*sizeof(MYFLT)); } /* This is a second order decoder provided by Bruce Wiggins. It is optimised for high frequency use within a dual-band decoder, however it has good a low-frequency response. It is not quite 'in-phase' but it is not far off. */ if (dim == 4) { /* Matrix truncated to first order (not ideal). */ for (sampleIndex = offset; sampleIndex < sampleCount; sampleIndex++) { w = tabin[sampleIndex]; x = tabin[ksmps+sampleIndex]; y = tabin[2*ksmps+sampleIndex]; /* Left: */ tabout[sampleIndex] = w * FL(0.405) + x * FL(0.32) + y * FL(0.31); /* Right: */ tabout[ksmps+sampleIndex] = w * FL(0.405) + x * FL(0.32) - y * FL(0.31); /* Centre: */ tabout[2*ksmps+sampleIndex] = w * FL(0.085) + x * FL(0.04); /* Surround Left: */ tabout[3*ksmps+sampleIndex] = w * FL(0.635) - x * FL(0.335) + y * FL(0.28); /* Surround Right: */ tabout[4*ksmps+sampleIndex] = w * FL(0.635) - x * FL(0.335) - y * FL(0.28); } } else { /* This is the full matrix. */ if (UNLIKELY(offset)) { memset(&tabout[0], '\0', offset*sizeof(MYFLT)); memset(&tabout[ksmps], '\0', offset*sizeof(MYFLT)); memset(&tabout[2*ksmps], '\0', offset*sizeof(MYFLT)); memset(&tabout[3*ksmps], '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { sampleCount -= early; memset(&tabout[0+sampleCount], '\0', early*sizeof(MYFLT)); memset(&tabout[ksmps+sampleCount], '\0', early*sizeof(MYFLT)); memset(&tabout[2*ksmps+sampleCount], '\0', early*sizeof(MYFLT)); memset(&tabout[3*ksmps+sampleCount], '\0', early*sizeof(MYFLT)); } for (sampleIndex = offset; sampleIndex < sampleCount; sampleIndex++) { w = tabin[sampleIndex]; x = tabin[ksmps+sampleIndex]; y = tabin[2*ksmps+sampleIndex]; u = tabin[7*ksmps+sampleIndex]; v = tabin[8*ksmps+sampleIndex]; /* Left: */ tabout[sampleIndex] = (w * FL(0.405) + x * FL(0.32) + y * FL(0.31) + u * FL(0.085) + v * FL(0.125)); /* Right: */ tabout[ksmps+sampleIndex] = (w * FL(0.405) + x * FL(0.32) - y * FL(0.31) + u * FL(0.085) - v * FL(0.125)); /* Centre: */ tabout[2*ksmps+sampleIndex] = (w * FL(0.085) + x * FL(0.04) + u * FL(0.045)); /* Surround Left: */ tabout[3*ksmps+sampleIndex] = (w * FL(0.635) - x * FL(0.335) + y * FL(0.28) - u * FL(0.08) + v * FL(0.08)); /* Surround Right: */ tabout[4*ksmps+sampleIndex] = (w * FL(0.635) - x * FL(0.335) - y * FL(0.28) - u * FL(0.08) - v * FL(0.08)); } } break; case 4: /* Octagon: */ if (p->tabin->sizes[0] == 4) { /* First order 'in-phase' decode: */ if (UNLIKELY(offset)) for (sampleIndex = 0; sampleIndex<8; sampleIndex++) memset(&tabout[ksmps*sampleIndex], '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { sampleCount -= early; for (sampleIndex = 0; sampleIndex<8; sampleIndex++) memset(&tabout[ksmps*sampleIndex+sampleCount], '\0', early*sizeof(MYFLT)); } for (sampleIndex = offset; sampleIndex < sampleCount; sampleIndex++) { w = tabin[sampleIndex] * FL(0.17677); x = tabin[ksmps+sampleIndex]; y = tabin[2*ksmps+sampleIndex]; /* About 11 o'clock: */ tabout[sampleIndex] = w + x * FL(0.11548) + y * FL(0.04783); /* About 10 o'clock: */ tabout[ksmps+sampleIndex] = w + x * FL(0.04783) + y * FL(0.11546); /* About 8 o'clock: */ tabout[2*ksmps+sampleIndex] = w - x * FL(0.04783) + y * FL(0.11546); /* About 7 o'clock: */ tabout[3*ksmps+sampleIndex] = w - x * FL(0.11548) + y * FL(0.04783); /* About 5 o'clock: */ tabout[4*ksmps+sampleIndex] = w - x * FL(0.11548) - y * FL(0.04783); /* About 4 o'clock: */ tabout[5*ksmps+sampleIndex] = w - x * FL(0.04783) - y * FL(0.11546); /* About 2 o'clock: */ tabout[6*ksmps+sampleIndex] = w + x * FL(0.04783) - y * FL(0.11546); /* About 1 o'clock: */ tabout[7*ksmps+sampleIndex] = w + x * FL(0.11548) - y * FL(0.04783); } } else if (p->tabin->sizes[0] == 9) { /* Second order 'in-phase' / 'controlled opposites' decode: */ if (UNLIKELY(offset)) for (sampleIndex = 0; sampleIndex<8; sampleIndex++) memset(&tabout[ksmps*sampleIndex], '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { sampleCount -= early; for (sampleIndex = 0; sampleIndex<8; sampleIndex++) memset(&tabout[ksmps*sampleIndex+sampleCount], '\0', early*sizeof(MYFLT)); } for (sampleIndex = offset; sampleIndex < sampleCount; sampleIndex++) { w = tabin[sampleIndex] * FL(0.17677); x = tabin[ksmps+sampleIndex]; y = tabin[2*ksmps+sampleIndex]; u = tabin[7*ksmps+sampleIndex] * FL(0.03417); v = tabin[8*ksmps+sampleIndex] * FL(0.03417); /* About 11 o'clock: */ tabout[sampleIndex] = w + x * FL(0.15906) + y * FL(0.06588) + u + v; /* About 10 o'clock: */ tabout[ksmps+sampleIndex] = w + x * FL(0.06588) + y * FL(0.15906) - u + v; /* About 8 o'clock: */ tabout[2*ksmps+sampleIndex] = w - x * FL(0.06588) + y * FL(0.15906) - u - v; /* About 7 o'clock: */ tabout[3*ksmps+sampleIndex] = w - x * FL(0.15906) + y * FL(0.06588) + u - v; /* About 5 o'clock: */ tabout[4*ksmps+sampleIndex] = w - x * FL(0.15906) - y * FL(0.06588) + u + v; /* About 4 o'clock: */ tabout[5*ksmps+sampleIndex] = w - x * FL(0.06588) - y * FL(0.15906) - u + v; /* About 2 o'clock: */ tabout[6*ksmps+sampleIndex] = w + x * FL(0.06588) - y * FL(0.15906) - u - v; /* About 1 o'clock: */ tabout[7*ksmps+sampleIndex] = w + x * FL(0.15906) - y * FL(0.06588) + u - v; } } else { assert(p->tabin->sizes[0]==16); if (UNLIKELY(offset)) for (sampleIndex = 0; sampleIndex<8; sampleIndex++) memset(&tabout[ksmps*sampleIndex], '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { sampleCount -= early; for (sampleIndex = 0; sampleIndex<8; sampleIndex++) memset(&tabout[ksmps*sampleIndex+sampleCount], '\0', early*sizeof(MYFLT)); } /* Third order 'in-phase' / 'controlled opposites' decode: */ for (sampleIndex = offset; sampleIndex < sampleCount; sampleIndex++) { w = tabin[ksmps* 0+sampleIndex] * FL(0.176777); x = tabin[ksmps* 1+sampleIndex]; y = tabin[ksmps* 2+sampleIndex]; u = tabin[ksmps* 7+sampleIndex] * FL(0.053033); v = tabin[ksmps* 8+sampleIndex] * FL(0.053033); p0 = tabin[ksmps*14+sampleIndex]; q = tabin[ksmps*15+sampleIndex]; /* About 11 o'clock: */ tabout[0+sampleIndex] = (w + x * FL(0.173227) + y * FL(0.071753) + u + v + p0 * FL(0.004784) + q * FL(0.011548)); /* About 10 o'clock: */ tabout[ksmps+sampleIndex] = (w + x * FL(0.071753) + y * FL(0.173227) - u + v - p0 * FL(0.011548) - q * FL(0.004784)); /* About 8 o'clock: */ tabout[2*ksmps+sampleIndex] = (w - x * FL(0.071753) + y * FL(0.173227) - u - v + p0 * FL(0.004784) - q * FL(0.011548)); /* About 7 o'clock: */ tabout[3*ksmps+sampleIndex] = (w - x * FL(0.173227) + y * FL(0.071753) + u - v - p0 * FL(0.011548) + q * FL(0.004784)); /* About 5 o'clock: */ tabout[ksmps*4+sampleIndex] = (w - x * FL(0.173227) - y * FL(0.071753) + u + v - p0 * FL(0.004784) - q * FL(0.011548)); /* About 4 o'clock: */ tabout[ksmps*5+sampleIndex] = (w - x * FL(0.071753) - y * FL(0.173227) - u + v + p0 * FL(0.011548) + q * FL(0.004784)); /* About 2 o'clock: */ tabout[ksmps*6+sampleIndex] = (w + x * FL(0.071753) - y * FL(0.173227) - u - v - p0 * FL(0.004784) + q * FL(0.011548)); /* About 1 o'clock: */ tabout[ksmps*7+sampleIndex] = (w + x * FL(0.173227) - y * FL(0.071753) + u - v + p0 * FL(0.011548) - q * FL(0.004784)); } } break; case 5: /* Cube: */ /* First order 'in-phase' decode: */ if (UNLIKELY(offset)) for (sampleIndex = 0; sampleIndex<8; sampleIndex++) memset(&tabout[ksmps*sampleIndex], '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { sampleCount -= early; for (sampleIndex = 0; sampleIndex<8; sampleIndex++) memset(&tabout[ksmps*sampleIndex+sampleCount], '\0', early*sizeof(MYFLT)); } for (sampleIndex = offset; sampleIndex < sampleCount; sampleIndex++) { w = tabin[sampleIndex] * FL(0.17677); x = tabin[ksmps+sampleIndex] * FL(0.07216); y = tabin[2*ksmps+sampleIndex] * FL(0.07216); z = tabin[3*ksmps+sampleIndex] * FL(0.07216); /* Front left bottom: */ p->tabout->data[sampleIndex] = w + x + y - z; /* Front left top: */ p->tabout->data[ksmps+sampleIndex] = w + x + y + z; /* Back left bottom: */ p->tabout->data[2*ksmps+sampleIndex] = w - x + y - z; /* Back left top: */ p->tabout->data[3*ksmps+sampleIndex] = w - x + y + z; /* Back right bottom: */ p->tabout->data[ksmps*4+sampleIndex] = w - x - y - z; /* Back right top: */ p->tabout->data[ksmps*5+sampleIndex] = w - x - y + z; /* Front right bottom: */ p->tabout->data[ksmps*6+sampleIndex] = w + x - y - z; /* Front right top: */ p->tabout->data[ksmps*7+sampleIndex] = w + x - y + z; } break; default: assert(0); } return OK; } /* ------------------------------------------------------------------------- */ #define S(x) sizeof(x) static OENTRY ambicode1_localops[] = { { "bformenc1.a", S(AMBIC), 0, 5, "mmmmmmmmmmmmmmmm", "akk", (SUBR)ibformenc, NULL, (SUBR)abformenc }, { "bformenc1.A", S(AMBIC), 0, 5, "a[]", "akk", (SUBR)ibformenc_a, NULL, (SUBR)abformenc_a }, { "bformdec1.a", S(AMBID), 0, 5, "mmmmmmmm", "iy", (SUBR)ibformdec, NULL, (SUBR)abformdec }, { "bformdec1.A", S(AMBIDA), 0, 5, "a[]", "ia[]", (SUBR)ibformdec_a, NULL, (SUBR)abformdec_a }, }; LINKAGE_BUILTIN(ambicode1_localops) csound-6.10.0/Opcodes/ampmidid.cpp000066400000000000000000000133411321653344700167670ustar00rootroot00000000000000/* ampmidid.cpp Copyright (C) 2006 Michael Gogins This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "OpcodeBase.hpp" using namespace csound; #include /** * Musically map MIDI velocity to peak amplitude * within a specified dynamic range in decibels: * a = (m * v + b) ^ 2 * where a = amplitude, * v = MIDI velocity, * r = 10 ^ (R / 20), * b = 127 / (126 * sqrt( r )) - 1 / 126, * m = (1 - b) / 127, * and R = specified dynamic range in decibels. * See Roger Dannenberg, "The Interpretation of MIDI Velocity," * in Georg Essl and Ichiro Fujinaga (Eds.), Proceedings of the * 2006 International Computer Music Conference, * November 6-11, 2006 (San Francisco: * The International Computer Music Association), pp. 193-196. */ class KAMPMIDID : public OpcodeBase { public: // Outputs. MYFLT *kamplitude; // Inputs. MYFLT *kvelocity; MYFLT *irdb; MYFLT *iuse0dbfs; // State. MYFLT ir; MYFLT im; MYFLT ib; MYFLT onedrms; MYFLT dbfs; KAMPMIDID() : kamplitude(0), kvelocity(0), irdb(0), iuse0dbfs(0), ir(0), im(0), ib(0), onedrms(0), dbfs(1) {} int init(CSOUND *csound) { // Convert RMS power to amplitude (assuming a sinusoidal signal). onedrms = MYFLT(1.0) / MYFLT(0.707); // Convert dynamic range in decibels to RMS dynamic range. ir = std::pow( MYFLT(10.0), *irdb / MYFLT(20.0) ); // Solve for coefficients of the linear conversion function given // RMS dynamic range. ib = MYFLT(127.0) / ( MYFLT(126.0) * std::sqrt(ir) ) - MYFLT(1.0) / MYFLT(126.0); im = ( MYFLT(1.0) - ib ) / MYFLT(127.0); if (*iuse0dbfs != FL(0.0)) { dbfs = csound->Get0dBFS(csound); } return OK; } int kontrol(CSOUND *csound) { *kamplitude = dbfs * std::pow( (im * (*kvelocity + ib) ), MYFLT(2.0) ) * onedrms; return OK; } }; class IAMPMIDID : public OpcodeBase { public: // Outputs. MYFLT *iamplitude; // Inputs. MYFLT *ivelocity; MYFLT *irdb; MYFLT *iuse0dbfs; // State. MYFLT ir; MYFLT im; MYFLT ib; MYFLT onedrms; MYFLT dbfs; IAMPMIDID() : iamplitude(0), ivelocity(0), irdb(0), iuse0dbfs(0), ir(0), im(0), ib(0), onedrms(0), dbfs(1) {} int init(CSOUND *csound) { // Convert RMS power to amplitude (assuming a sinusoidal signal). onedrms = MYFLT(1.0) / MYFLT(0.707); // Convert dynamic range in decibels to RMS dynamic range. ir = std::pow( MYFLT(10.0), *irdb / MYFLT(20.0) ); // Solve for coefficients of the linear conversion function given // RMS dynamic range. ib = MYFLT(127.0) / ( MYFLT(126.0) * std::sqrt(ir) ) - MYFLT(1.0) / MYFLT(126.0); im = ( MYFLT(1.0) - ib ) / MYFLT(127.0); if (*iuse0dbfs != FL(0.0)) { dbfs = csound->Get0dBFS(csound); } *iamplitude = dbfs * std::pow( (im * (*ivelocity + ib) ), MYFLT(2.0) ) * onedrms; return OK; } int noteoff(CSOUND *) { return OK; } }; extern "C" { PUBLIC int csoundModuleInit_ampmidid(CSOUND *csound) { int status = csound->AppendOpcode(csound, (char*)"ampmidid.k", sizeof(KAMPMIDID), 0, 3, (char*)"k", (char*)"kio", (int(*)(CSOUND*,void*)) KAMPMIDID::init_, (int(*)(CSOUND*,void*)) KAMPMIDID::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, (char*)"ampmidid.i", sizeof(IAMPMIDID), 0, 1, (char*)"i", (char*)"iio", (int (*)(CSOUND*,void*)) IAMPMIDID::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, (char*)"ampmidid", 0xffff, 0, 0, 0, 0, 0, 0, 0); return status; } #ifndef INIT_STATIC_MODULES PUBLIC int csoundModuleCreate(CSOUND *csound) { return 0; } PUBLIC int csoundModuleInit(CSOUND *csound) { return csoundModuleInit_ampmidid(csound); } PUBLIC int csoundModuleDestroy(CSOUND *csound) { return 0; } #endif } csound-6.10.0/Opcodes/arrayops.cpp000066400000000000000000000346371321653344700170560ustar00rootroot00000000000000/* arrayops.c: array operators Copyright (C) 2017 Victor Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include //extern inline MYFLT frac(MYFLT f) { return std::modf(f, &f); } //extern inline MYFLT lim1(MYFLT f) { return f > FL(0.0) ? (f < FL(1.0) ? f : FL(1.0)) : FL(0.0); } inline MYFLT limx(MYFLT f, MYFLT v1, MYFLT v2) { return f > v1 ? (f < v2 ? f : v2) : v1; } /** i-time, k-rate operator kout[] op kin[] */ template struct ArrayOp : csnd::Plugin<1, 1> { int process(csnd::myfltvec &out, csnd::myfltvec &in) { std::transform(in.begin(), in.end(), out.begin(), [](MYFLT f) { return op(f); }); return OK; } int init() { csnd::myfltvec &out = outargs.myfltvec_data(0); csnd::myfltvec &in = inargs.myfltvec_data(0); out.init(csound, in.len()); return process(out, in); } int kperf() { return process(outargs.myfltvec_data(0), inargs.myfltvec_data(0)); } }; /** i-time, k-rate binary operator kout[] op kin1[], kin2[] */ template struct ArrayOp2 : csnd::Plugin<1, 2> { int process(csnd::myfltvec &out, csnd::myfltvec &in1, csnd::myfltvec &in2) { std::transform(in1.begin(), in1.end(), in2.begin(), out.begin(), [](MYFLT f1, MYFLT f2) { return bop(f1, f2); }); return OK; } int init() { csnd::myfltvec &out = outargs.myfltvec_data(0); csnd::myfltvec &in1 = inargs.myfltvec_data(0); csnd::myfltvec &in2 = inargs.myfltvec_data(1); if (UNLIKELY(in2.len() < in1.len())) return csound->init_error(Str("second input array is too short\n")); out.init(csound, in1.len()); return process(out, in1, in2); } int kperf() { return process(outargs.myfltvec_data(0), inargs.myfltvec_data(0), inargs.myfltvec_data(1)); } }; /** i-time, k-rate binary operator with array and scalar kout[] op kin1[], kin2 */ template struct ArrayOp3 : csnd::Plugin<1, 2> { int process(csnd::myfltvec &out, csnd::myfltvec &in, MYFLT v) { for(MYFLT *s = in.begin(), *o = out.begin(); s != in.end(); s++, o++) *o = bop(*s, v); return OK; } int init() { csnd::myfltvec &out = outargs.myfltvec_data(0); csnd::myfltvec &in = inargs.myfltvec_data(0); MYFLT v = inargs[1]; out.init(csound, in.len()); return process(out, in, v); } int kperf() { return process(outargs.myfltvec_data(0), inargs.myfltvec_data(0), inargs[1]); } }; /** i-time, k-rate binary operator with array and two scalar kout[] op kin1[], kin2, kin3 */ template struct ArrayOp4 : csnd::Plugin<1, 3> { int process(csnd::myfltvec &out, csnd::myfltvec &in, MYFLT v1, MYFLT v2) { for(MYFLT *s = in.begin(), *o = out.begin(); s != in.end(); s++, o++) *o = trop(*s, v1, v2); return OK; } int init() { csnd::myfltvec &out = outargs.myfltvec_data(0); csnd::myfltvec &in = inargs.myfltvec_data(0); MYFLT v1 = inargs[1]; MYFLT v2 = inargs[2]; out.init(csound, in.len()); return process(out, in, v1, v2); } int kperf() { return process(outargs.myfltvec_data(0), inargs.myfltvec_data(0), inargs[1], inargs[2]); } }; /** i-time, k-rate operator kout[] sort[a,d] kin[] */ template struct ArraySort : csnd::Plugin<1, 1> { int process(csnd::myfltvec &out, csnd::myfltvec &in) { std::copy(in.begin(), in.end(), out.begin()); std::sort(out.begin(), out.end(), T()); return OK; } int init() { csnd::myfltvec &out = outargs.myfltvec_data(0); csnd::myfltvec &in = inargs.myfltvec_data(0); out.init(csound, in.len()); return process(out, in); } int kperf() { return process(outargs.myfltvec_data(0), inargs.myfltvec_data(0)); } }; /** dot product */ struct Dot : csnd::Plugin<1, 2> { MYFLT process(csnd::myfltvec &in1, csnd::myfltvec &in2) { return std::inner_product(in1.begin(), in1.end(), in2.begin(), 0.0); } int init() { csnd::myfltvec &in1 = inargs.myfltvec_data(0); csnd::myfltvec &in2 = inargs.myfltvec_data(1); if (UNLIKELY(in2.len() < in1.len())) return csound->init_error(Str("second input array is too short\n")); outargs[0] = process(in1, in2); return OK; } int kperf() { outargs[0] = process(inargs.myfltvec_data(0), inargs.myfltvec_data(1)); return OK; } }; template struct Accum : csnd::Plugin<1, 1> { MYFLT process(csnd::myfltvec &in1) { return std::accumulate(in1.begin(), in1.end(), FL(I), T()); } int init() { csnd::myfltvec &in1 = inargs.myfltvec_data(0); outargs[0] = process(in1); return OK; } int kperf() { outargs[0] = process(inargs.myfltvec_data(0)); return OK; } }; #include void csnd::on_load(Csound *csound) { csnd::plugin>(csound, "limit1", "i[]", "i[]", csnd::thread::i); csnd::plugin>(csound, "limit1", "k[]", "k[]", csnd::thread::ik); csnd::plugin>(csound, "ceil", "i[]", "i[]", csnd::thread::i); csnd::plugin>(csound, "ceil", "k[]", "k[]", csnd::thread::ik); csnd::plugin>(csound, "floor", "i[]", "i[]", csnd::thread::i); csnd::plugin>(csound, "floor", "k[]", "k[]", csnd::thread::ik); csnd::plugin>(csound, "round", "i[]", "i[]", csnd::thread::i); csnd::plugin>(csound, "round", "k[]", "k[]", csnd::thread::ik); csnd::plugin>(csound, "int", "i[]", "i[]", csnd::thread::i); csnd::plugin>(csound, "int", "k[]", "k[]", csnd::thread::i); csnd::plugin>(csound, "frac", "i[]", "i[]", csnd::thread::i); csnd::plugin>(csound, "frac", "k[]", "k[]", csnd::thread::ik); csnd::plugin>(csound, "powoftwo", "i[]", "i[]", csnd::thread::i); csnd::plugin>(csound, "powoftwo", "k[]", "k[]", csnd::thread::ik); csnd::plugin>(csound, "abs", "i[]", "i[]", csnd::thread::i); csnd::plugin>(csound, "abs", "k[]", "k[]", csnd::thread::ik); csnd::plugin>(csound, "log2", "i[]", "i[]", csnd::thread::i); csnd::plugin>(csound, "log2", "k[]", "k[]", csnd::thread::ik); csnd::plugin>(csound, "log10", "i[]", "i[]", csnd::thread::i); csnd::plugin>(csound, "log10", "k[]", "k[]", csnd::thread::ik); csnd::plugin>(csound, "log", "i[]", "i[]", csnd::thread::i); csnd::plugin>(csound, "log", "k[]", "k[]", csnd::thread::ik); csnd::plugin>(csound, "exp", "i[]", "i[]", csnd::thread::i); csnd::plugin>(csound, "exp", "k[]", "k[]", csnd::thread::ik); csnd::plugin>(csound, "sqrt", "i[]", "i[]", csnd::thread::i); csnd::plugin>(csound, "sqrt", "k[]", "k[]", csnd::thread::ik); csnd::plugin>(csound, "cos", "i[]", "i[]", csnd::thread::i); csnd::plugin>(csound, "cos", "k[]", "k[]", csnd::thread::ik); csnd::plugin>(csound, "sin", "i[]", "i[]", csnd::thread::i); csnd::plugin>(csound, "sin", "k[]", "k[]", csnd::thread::ik); csnd::plugin>(csound, "tan", "i[]", "i[]", csnd::thread::i); csnd::plugin>(csound, "tan", "k[]", "k[]", csnd::thread::ik); csnd::plugin>(csound, "cosinv", "i[]", "i[]", csnd::thread::i); csnd::plugin>(csound, "cosinv", "k[]", "k[]", csnd::thread::ik); csnd::plugin>(csound, "sininv", "i[]", "i[]", csnd::thread::i); csnd::plugin>(csound, "sininv", "k[]", "k[]", csnd::thread::ik); csnd::plugin>(csound, "taninv", "i[]", "i[]", csnd::thread::i); csnd::plugin>(csound, "taninv", "k[]", "k[]", csnd::thread::ik); csnd::plugin>(csound, "cosh", "i[]", "i[]", csnd::thread::i); csnd::plugin>(csound, "cosh", "k[]", "k[]", csnd::thread::ik); csnd::plugin>(csound, "sinh", "i[]", "i[]", csnd::thread::i); csnd::plugin>(csound, "sinh", "k[]", "k[]", csnd::thread::ik); csnd::plugin>(csound, "tanh", "i[]", "i[]", csnd::thread::i); csnd::plugin>(csound, "tanh", "k[]", "k[]", csnd::thread::ik); csnd::plugin>(csound, "cbrt", "i[]", "i[]", csnd::thread::i); csnd::plugin>(csound, "cbrt", "k[]", "k[]", csnd::thread::ik); csnd::plugin>(csound, "taninv", "i[]", "i[]i[]", csnd::thread::i); csnd::plugin>(csound, "taninv", "k[]", "k[]k[]", csnd::thread::ik); csnd::plugin>(csound, "pow", "i[]", "i[]i[]", csnd::thread::i); csnd::plugin>(csound, "pow", "k[]", "k[]k[]", csnd::thread::ik); csnd::plugin>(csound, "hypot", "i[]", "i[]i[]", csnd::thread::i); csnd::plugin>(csound, "hypot", "k[]", "k[]k[]", csnd::thread::ik); csnd::plugin>(csound, "fmod", "i[]", "i[]i[]", csnd::thread::i); csnd::plugin>(csound, "fmod", "k[]", "k[]k[]", csnd::thread::ik); csnd::plugin>(csound, "fmax", "i[]", "i[]i[]", csnd::thread::i); csnd::plugin>(csound, "fmax", "k[]", "k[]k[]", csnd::thread::ik); csnd::plugin>(csound, "fmin", "i[]", "i[]i[]", csnd::thread::i); csnd::plugin>(csound, "fmin", "k[]", "k[]k[]", csnd::thread::ik); csnd::plugin>>(csound, "sorta", "i[]", "i[]", csnd::thread::i); csnd::plugin>>(csound, "sortd", "i[]", "i[]", csnd::thread::i); csnd::plugin>>(csound, "sorta", "k[]", "k[]", csnd::thread::ik); csnd::plugin>>(csound, "sortd", "k[]", "k[]", csnd::thread::ik); csnd::plugin(csound, "dot", "i", "i[]i[]", csnd::thread::i); csnd::plugin(csound, "dot", "k", "k[]k[]", csnd::thread::ik); csnd::plugin,1>>(csound, "product", "k", "k[]", csnd::thread::ik); csnd::plugin,0>>(csound, "sum", "k", "k[]", csnd::thread::ik); csnd::plugin,1>>(csound, "product", "i", "i[]", csnd::thread::i); csnd::plugin,0>>(csound, "sum", "i", "i[]", csnd::thread::i); csnd::plugin>(csound, "limit", "i[]", "i[]ii", csnd::thread::i); csnd::plugin>(csound, "limit", "k[]", "k[]kk", csnd::thread::ik); csnd::plugin>(csound, "pow", "i[]", "i[]i", csnd::thread::i); csnd::plugin>(csound, "pow", "k[]", "k[]k", csnd::thread::ik); csnd::plugin>(csound, "fmod", "i[]", "i[]i", csnd::thread::i); csnd::plugin>(csound, "fmod", "k[]", "k[]k", csnd::thread::ik); csnd::plugin>(csound, "fmax", "i[]", "i[]i", csnd::thread::i); csnd::plugin>(csound, "fmax", "k[]", "k[]k", csnd::thread::ik); csnd::plugin>(csound, "fmin", "i[]", "i[]i", csnd::thread::i); csnd::plugin>(csound, "fmin", "k[]", "k[]k", csnd::thread::ik); } csound-6.10.0/Opcodes/arrays.c000066400000000000000000002700231321653344700161460ustar00rootroot00000000000000/* arrays.c: Copyright (C) 2011,2012 John ffitch, Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // #include "csdl.h" #include "csoundCore.h" #include "interlocks.h" #include "aops.h" #include "find_opcode.h" extern MYFLT MOD(MYFLT a, MYFLT bb); typedef struct { OPDS h; ARRAYDAT *arrayDat; } ARRAYDEL; typedef struct { OPDS h; ARRAYDAT* arrayDat; MYFLT *isizes[VARGMAX];} ARRAYINIT; typedef struct { OPDS h; ARRAYDAT* ans; MYFLT *iargs[VARGMAX]; } TABFILL; typedef struct { OPDS h; ARRAYDAT* arrayDat; void* value; MYFLT *indexes[VARGMAX]; } ARRAY_SET; typedef struct { OPDS h; MYFLT* out; ARRAYDAT* arrayDat; MYFLT *indexes[VARGMAX]; } ARRAY_GET; #ifdef SOME_FINE_DAY static int array_del(CSOUND *csound, void *p) { ARRAYDAT *t = ((ARRAYDEL*)p)->arrayDat; t->arrayType = NULL; // types cleaned up later csound->Free(csound, t->data); csound->Free(csound, p); /* Unlikely to free the p */ return OK; } #endif static inline void tabensure(CSOUND *csound, ARRAYDAT *p, int size) { if (p->data==NULL || p->dimensions == 0 || (p->dimensions==1 && p->sizes[0] < size)) { size_t ss; if (p->data == NULL) { CS_VARIABLE* var = p->arrayType->createVariable(csound, NULL); p->arrayMemberSize = var->memBlockSize; } ss = p->arrayMemberSize*size; if (p->data==NULL) p->data = (MYFLT*)csound->Calloc(csound, ss); else p->data = (MYFLT*) csound->ReAlloc(csound, p->data, ss); p->dimensions = 1; p->sizes = (int*)csound->Malloc(csound, sizeof(int)); p->sizes[0] = size; } } static int array_init(CSOUND *csound, ARRAYINIT *p) { ARRAYDAT* arrayDat = p->arrayDat; int i, size; int inArgCount = p->INOCOUNT; if (UNLIKELY(inArgCount == 0)) return csound->InitError(csound, Str("Error: no sizes set for array initialization")); for (i = 0; i < inArgCount; i++) { if (UNLIKELY(MYFLT2LRND(*p->isizes[i]) <= 0)) { return csound->InitError(csound, Str("Error: sizes must be > 0 for array initialization")); } } arrayDat->dimensions = inArgCount; arrayDat->sizes = csound->Calloc(csound, sizeof(int) * inArgCount); for (i = 0; i < inArgCount; i++) { arrayDat->sizes[i] = MYFLT2LRND(*p->isizes[i]); } size = arrayDat->sizes[0]; if (inArgCount > 1) { for (i = 1; i < inArgCount; i++) { size *= arrayDat->sizes[i]; } //size = MYFLT2LRND(size); // size is an int not float } { CS_VARIABLE* var = arrayDat->arrayType->createVariable(csound,NULL); char *mem; arrayDat->arrayMemberSize = var->memBlockSize; arrayDat->data = csound->Calloc(csound, var->memBlockSize*size); mem = (char *) arrayDat->data; for (i=0; i < size; i++) { var->initializeVariableMemory(csound, var, (MYFLT*)(mem+i*var->memBlockSize)); } } return OK; } static int tabfill(CSOUND *csound, TABFILL *p) { int nargs = p->INOCOUNT; int i; size_t memMyfltSize; MYFLT **valp = p->iargs; tabensure(csound, p->ans, nargs); if (UNLIKELY(p->ans->dimensions > 2)) { return csound->InitError(csound, Str("fillarrray: arrays with dim > 2 not " "currently supported\n")); } memMyfltSize = p->ans->arrayMemberSize / sizeof(MYFLT); for (i=0; ians->arrayType->copyValue(csound, p->ans->data + (i * memMyfltSize), valp[i]); } return OK; } static int array_err(CSOUND* csound, ARRAY_SET *p) { return csound->InitError(csound, Str("Cannot set i-array at k-rate\n")); } static int array_set(CSOUND* csound, ARRAY_SET *p) { ARRAYDAT* dat = p->arrayDat; MYFLT* mem = dat->data; int i; int end, index, incr; int indefArgCount = p->INOCOUNT - 2; if (UNLIKELY(indefArgCount == 0)) { csoundErrorMsg(csound, Str("Error: no indexes set for array set\n")); return CSOUND_ERROR; } if (UNLIKELY(indefArgCount>dat->dimensions)) { csound->Warning(csound, Str("Array dimension %d out of range " "for dimensions %d\n"), indefArgCount, dat->dimensions); return NOTOK; } end = indefArgCount - 1; index = MYFLT2LRND(*p->indexes[end]); if (UNLIKELY(index >= dat->sizes[end] || index<0)) { csound->Warning(csound, Str("Array index %d out of range (0,%d) " "for dimension %d"), index, dat->sizes[end]-1, indefArgCount); return NOTOK; } if (indefArgCount > 1) { for (i = end - 1; i >= 0; i--) { int ind = MYFLT2LRND(*p->indexes[i]); if (UNLIKELY(ind >= dat->sizes[i] || ind<0)){ csound->Warning(csound,Str("Array index %d out of range (0,%d) " "for dimension %d"), ind, dat->sizes[i]-1, i+1); return NOTOK; } index += ind * dat->sizes[i + 1]; } } incr = (index * (dat->arrayMemberSize / sizeof(MYFLT))); mem += incr; //memcpy(mem, p->value, dat->arrayMemberSize); dat->arrayType->copyValue(csound, mem, p->value); /* printf("array_set: mem = %p, incr = %d, value = %f\n", */ /* mem, incr, *((MYFLT*)p->value)); */ return OK; } static int array_get(CSOUND* csound, ARRAY_GET *p) { ARRAYDAT* dat = p->arrayDat; MYFLT* mem = dat->data; int i; int incr; int end; int index; int indefArgCount = p->INOCOUNT - 1; if (UNLIKELY(indefArgCount == 0)) csound->PerfError(csound, p->h.insdshead, Str("Error: no indexes set for array get")); if (UNLIKELY(indefArgCount>dat->dimensions)){ csound->Warning(csound, Str("Array dimension %d out of range " "for dimensions %d"), indefArgCount, dat->dimensions); return NOTOK; } end = indefArgCount - 1; index = MYFLT2LRND(*p->indexes[end]); if (UNLIKELY(index >= dat->sizes[end] || index<0)){ csound->Warning(csound, Str("Array index %d out of range (0,%d) " "for dimension %d"), index, dat->sizes[end]-1, end+1); return NOTOK; } if (indefArgCount > 1) { for (i = end - 1; i >= 0; i--) { int ind = MYFLT2LRND(*p->indexes[i]); if (UNLIKELY(ind >= dat->sizes[i] || ind<0)) { csound->Warning(csound, Str("Array index %d out of range (0,%d) " "for dimension %d"), ind, dat->sizes[i]-1, i+1); return NOTOK; } index += ind * dat->sizes[i + 1]; } } incr = (index * (dat->arrayMemberSize / sizeof(MYFLT))); mem += incr; // memcpy(p->out, &mem[incr], dat->arrayMemberSize); dat->arrayType->copyValue(csound, (void*)p->out, (void*)mem); return OK; } typedef struct { OPDS h; ARRAYDAT *ans, *left, *right; } TABARITH; typedef struct { OPDS h; ARRAYDAT *ans, *left; MYFLT *right; } TABARITH1; typedef struct { OPDS h; ARRAYDAT *ans; MYFLT *left; ARRAYDAT *right; } TABARITH2; typedef struct { OPDS h; MYFLT *ans, *pos; ARRAYDAT *tab; } TABQUERY; typedef struct { OPDS h; MYFLT *ans; ARRAYDAT *tab; MYFLT *opt; } TABQUERY1; typedef struct { OPDS h; ARRAYDAT *tab; MYFLT *kfn; } TABCOPY; typedef struct { OPDS h; ARRAYDAT *tab; MYFLT *kmin, *kmax; MYFLT *kstart, *kend; } TABSCALE; static int tabarithset(CSOUND *csound, TABARITH *p) { if (LIKELY(p->left->data && p->right->data)) { int size; if (UNLIKELY(p->left->dimensions!=1 || p->right->dimensions!=1)) return csound->InitError(csound, Str("Dimensions do not match in array arithmetic")); /* size is the smallest of the two */ size = p->left->sizes[0] < p->right->sizes[0] ? p->left->sizes[0] : p->right->sizes[0]; tabensure(csound, p->ans, size); p->ans->sizes[0] = size; return OK; } else return csound->InitError(csound, Str("array-variable not initialised")); } static int tabiadd(CSOUND *csound, ARRAYDAT *ans, ARRAYDAT *l, MYFLT r, void *p); // For cases with array as first arg static int tabarithset1(CSOUND *csound, TABARITH1 *p) { ARRAYDAT *left = p->left; if (p->ans->data == left->data) { printf("same ptr \n"); return OK; } if (LIKELY(left->data)) { int size; if (UNLIKELY(left->dimensions!=1)) return csound->InitError(csound, Str("Dimension does not match in array arithmetic")); size = left->sizes[0]; tabensure(csound, p->ans, size); p->ans->sizes[0] = size; return OK; } else return csound->InitError(csound, Str("array-variable not initialised")); } // For cases with array as second arg static int tabarithset2(CSOUND *csound, TABARITH2 *p) { ARRAYDAT *right = p->right; if (LIKELY(right->data)) { int size; if (UNLIKELY(right->dimensions!=1)) return csound->InitError(csound, Str("Dimension does not match in array arithmetic")); size = right->sizes[0]; tabensure(csound, p->ans, size); p->ans->sizes[0] = size; return OK; } else return csound->InitError(csound, Str("array-variable not initialised")); } static int tabadd(CSOUND *csound, TABARITH *p) { ARRAYDAT *ans = p->ans; ARRAYDAT *l = p->left; ARRAYDAT *r = p->right; int size = ans->sizes[0]; int i; if (UNLIKELY(ans->data == NULL || l->data==NULL || r->data==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (l->sizes[0]sizes[0]; if (r->sizes[0]sizes[0]; for (i=0; idata[i] = l->data[i] + r->data[i]; return OK; } static int tabsub(CSOUND *csound, TABARITH *p) { ARRAYDAT *ans = p->ans; ARRAYDAT *l = p->left; ARRAYDAT *r = p->right; int size = ans->sizes[0]; int i; if (UNLIKELY(ans->data == NULL || l->data==NULL || r->data==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (l->sizes[0]sizes[0]; if (r->sizes[0]sizes[0]; for (i=0; idata[i] = l->data[i] - r->data[i]; return OK; } /* static int tabneg(CSOUND *csound, TABARITH *p) */ /* { */ /* ARRAYDAT *ans = p->ans; */ /* ARRAYDAT *l = p->left; */ /* int size = ans->sizes[0]; */ /* int i; */ /* if (UNLIKELY(ans->data == NULL || l->data==NULL)) */ /* return csound->PerfError(csound, p->h.insdshead, */ /* Str("array-variable not initialised")); */ /* if (l->sizes[0]sizes[0]; */ /* for (i=0; idata[i] = - l->data[i]; */ /* return OK; */ /* } */ static int tabmult(CSOUND *csound, TABARITH *p) { ARRAYDAT *ans = p->ans; ARRAYDAT *l = p->left; ARRAYDAT *r = p->right; int size = ans->sizes[0]; int i; if (UNLIKELY(ans->data == NULL || l->data== NULL || r->data==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); //printf("sizes %d %d %d\n", l->sizes[0], r->sizes[0], size); if (l->sizes[0]sizes[0]; if (r->sizes[0]sizes[0]; for (i=0; idata[i] = l->data[i] * r->data[i]; return OK; } static int tabdiv(CSOUND *csound, TABARITH *p) { ARRAYDAT *ans = p->ans; ARRAYDAT *l = p->left; ARRAYDAT *r = p->right; int size = ans->sizes[0]; int i; if (UNLIKELY(ans->data == NULL || l->data== NULL || r->data==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (l->sizes[0]sizes[0]; if (r->sizes[0]sizes[0]; for (i=0; idata[i]!=0)) ans->data[i] = l->data[i] / r->data[i]; else return csound->PerfError(csound, p->h.insdshead, Str("division by zero in array-var at index %d"), i); return OK; } static int tabrem(CSOUND *csound, TABARITH *p) { ARRAYDAT *ans = p->ans; ARRAYDAT *l = p->left; ARRAYDAT *r = p->right; int size = ans->sizes[0]; int i; if (UNLIKELY(ans->data == NULL || l->data== NULL || r->data==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (l->sizes[0]sizes[0]; if (r->sizes[0]sizes[0]; for (i=0; idata[i] = MOD(l->data[i], r->data[i]); return OK; } static int tabpow(CSOUND *csound, TABARITH *p) { ARRAYDAT *ans = p->ans; ARRAYDAT *l = p->left; ARRAYDAT *r = p->right; int size = ans->sizes[0]; int i; MYFLT tmp; if (UNLIKELY(ans->data == NULL || l->data== NULL || r->data==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (l->sizes[0]sizes[0]; if (r->sizes[0]sizes[0]; for (i=0; idata[i]>=0) || MODF(r->data[i],&tmp)==FL(0.0)) ans->data[i] = POWER(l->data[i],r->data[i]); else return csound->PerfError(csound, p->h.insdshead, Str("undefined power in array-var at index %d"), i); return OK; } #define IIARRAY(opcode,fn) \ static int opcode(CSOUND *csound, TABARITH *p) \ { \ if (!tabarithset(csound, p)) return fn(csound, p); \ else return NOTOK; \ } IIARRAY(tabaddi,tabadd) IIARRAY(tabsubi,tabsub) IIARRAY(tabmulti,tabmult) IIARRAY(tabdivi,tabdiv) IIARRAY(tabremi,tabrem) IIARRAY(tabpowi,tabpow) // Add array and scalar static int tabiadd(CSOUND *csound, ARRAYDAT *ans, ARRAYDAT *l, MYFLT r, void *p) { int size = ans->sizes[0]; int i; if (UNLIKELY(ans->data == NULL || l->data== NULL)) return csound->PerfError(csound, ((TABARITH *) p)->h.insdshead, Str("array-variable not initialised")); if (l->sizes[0]sizes[0]; if (ans->sizes[0]sizes[0]; for (i=0; idata[i] = l->data[i] + r; return OK; } // K[]+K static int tabaiadd(CSOUND *csound, TABARITH1 *p) { ARRAYDAT *ans = p->ans; ARRAYDAT *l = p->left; MYFLT r = *p->right; return tabiadd(csound, ans, l, r, p); } // K+K[] static int tabiaadd(CSOUND *csound, TABARITH2 *p) { ARRAYDAT *ans = p->ans; ARRAYDAT *l = p->right; MYFLT r = *p->left; return tabiadd(csound, ans, l, r, p); } // Subtract K[]-K static int tabaisub(CSOUND *csound, TABARITH1 *p) { ARRAYDAT *ans = p->ans; ARRAYDAT *l = p->left; MYFLT r = *p->right; int size = ans->sizes[0]; int i; if (UNLIKELY(ans->data == NULL || l->data== NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (l->sizes[0]sizes[0]; if (ans->sizes[0]sizes[0]; for (i=0; idata[i] = l->data[i] - r; return OK; } // Subtract K-K[] static int tabiasub(CSOUND *csound, TABARITH2 *p) { ARRAYDAT *ans = p->ans; ARRAYDAT *l = p->right; MYFLT r = *p->left; int size = ans->sizes[0]; int i; if (UNLIKELY(ans->data == NULL || l->data== NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (l->sizes[0]sizes[0]; if (ans->sizes[0]sizes[0]; for (i=0; idata[i] = r - l->data[i]; return OK; } // Multiply scalar by array static int tabimult(CSOUND *csound, ARRAYDAT *ans, ARRAYDAT *l, MYFLT r, void *p) { int size = ans->sizes[0]; int i; if (UNLIKELY(ans->data == NULL || l->data== NULL)) return csound->PerfError(csound, ((TABARITH1 *)p)->h.insdshead, Str("array-variable not initialised")); if (l->sizes[0]sizes[0]; if (ans->sizes[0]sizes[0]; for (i=0; idata[i] = l->data[i] * r; return OK; } // K[] * K static int tabaimult(CSOUND *csound, TABARITH1 *p) { ARRAYDAT *ans = p->ans; ARRAYDAT *l = p->left; MYFLT r = *p->right; return tabimult(csound, ans, l, r, p); } // K * K[] static int tabiamult(CSOUND *csound, TABARITH2 *p) { ARRAYDAT *ans = p->ans; ARRAYDAT *l = p->right; MYFLT r = *p->left; return tabimult(csound, ans, l, r, p); } // K[] / K static int tabaidiv(CSOUND *csound, TABARITH1 *p) { ARRAYDAT *ans = p->ans; ARRAYDAT *l = p->left; MYFLT r = *p->right; int size = ans->sizes[0]; int i; if (UNLIKELY(r==FL(0.0))) return csound->PerfError(csound, p->h.insdshead, Str("division by zero in array-var")); if (UNLIKELY(ans->data == NULL || l->data== NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (l->sizes[0]sizes[0]; if (ans->sizes[0]sizes[0]; for (i=0; idata[i] = l->data[i] / r; return OK; } // K / K[] static int tabiadiv(CSOUND *csound, TABARITH2 *p) { ARRAYDAT *ans = p->ans; ARRAYDAT *l = p->right; MYFLT r = *p->left; int size = ans->sizes[0]; int i; if (UNLIKELY(ans->data == NULL || l->data== NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (l->sizes[0]sizes[0]; if (ans->sizes[0]sizes[0]; for (i=0; idata[i]==FL(0.0))) return csound->PerfError(csound, p->h.insdshead, Str("division by zero in array-var")); ans->data[i] = r / l->data[i]; } return OK; } // K[] % K static int tabairem(CSOUND *csound, TABARITH1 *p) { ARRAYDAT *ans = p->ans; ARRAYDAT *l = p->left; MYFLT r = *p->right; int size = ans->sizes[0]; int i; if (UNLIKELY(r==FL(0.0))) return csound->PerfError(csound, p->h.insdshead, Str("division by zero in array-var")); if (UNLIKELY(ans->data == NULL || l->data== NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (l->sizes[0]sizes[0]; if (ans->sizes[0]sizes[0]; for (i=0; idata[i] = MOD(l->data[i], r); return OK; } // K % K[] static int tabiarem(CSOUND *csound, TABARITH2 *p) { ARRAYDAT *ans = p->ans; ARRAYDAT *l = p->right; MYFLT r = *p->left; int size = ans->sizes[0]; int i; if (UNLIKELY(ans->data == NULL || l->data== NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (l->sizes[0]sizes[0]; if (ans->sizes[0]sizes[0]; for (i=0; idata[i]==FL(0.0))) return csound->PerfError(csound, p->h.insdshead, Str("division by zero in array-var at index %d"), i); else ans->data[i] = MOD(r,l->data[i]); } return OK; } // K[] pow K static int tabaipow(CSOUND *csound, TABARITH1 *p) { ARRAYDAT *ans = p->ans; ARRAYDAT *l = p->left; MYFLT r = *p->right; int size = ans->sizes[0]; int i; MYFLT tmp; int intcase = (MODF(r,&tmp)==FL(0.0)); if (UNLIKELY(ans->data == NULL || l->data== NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (l->sizes[0]sizes[0]; if (ans->sizes[0]sizes[0]; for (i=0; idata[i]>=0)) ans->data[i] = POWER(l->data[i], r); else return csound->PerfError(csound, p->h.insdshead, Str("undefined power in array-var at index %d"), i); return OK; } // K ^ K[] static int tabiapow(CSOUND *csound, TABARITH2 *p) { ARRAYDAT *ans = p->ans; ARRAYDAT *l = p->right; MYFLT r = *p->left; int size = ans->sizes[0]; int i; MYFLT tmp; int poscase = (r>=FL(0.0)); if (UNLIKELY(ans->data == NULL || l->data== NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (l->sizes[0]sizes[0]; if (ans->sizes[0]sizes[0]; for (i=0; idata[i],&tmp)==FL(0.0))) ans->data[i] = POWER(r,l->data[i]); else return csound->PerfError(csound, p->h.insdshead, Str("undefined power in array-var at index %d"), i); } return OK; } #define IiARRAY(opcode,fn) \ static int opcode(CSOUND *csound, TABARITH1 *p) \ { \ if (!tabarithset1(csound, p)) return fn(csound, p); \ else return NOTOK; \ } IiARRAY(tabaiaddi,tabaiadd) IiARRAY(tabaisubi,tabaisub) IiARRAY(tabaimulti,tabaimult) IiARRAY(tabaidivi,tabaidiv) IiARRAY(tabairemi,tabairem) IiARRAY(tabaipowi,tabaipow) #define iIARRAY(opcode,fn) \ static int opcode(CSOUND *csound, TABARITH2 *p) \ { \ if (!tabarithset2(csound, p)) return fn(csound, p); \ else return NOTOK; \ } iIARRAY(tabiaaddi,tabiaadd) iIARRAY(tabiasubi,tabiasub) iIARRAY(tabiamulti,tabiamult) iIARRAY(tabiadivi,tabiadiv) iIARRAY(tabiaremi,tabiarem) iIARRAY(tabiapowi,tabiapow) //a[]+a[] static int tabaadd(CSOUND *csound, TABARITH *p) { ARRAYDAT *ans = p->ans; ARRAYDAT *l = p->left; ARRAYDAT *r = p->right; int size = ans->sizes[0]; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; int i, n, nsmps = CS_KSMPS; if (UNLIKELY(ans->data == NULL || l->data==NULL || r->data==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (l->sizes[0]sizes[0]; if (r->sizes[0]sizes[0]; if (UNLIKELY(early)) { nsmps -= early; } for (i=0; idata[i]); b = (MYFLT*)&(r->data[i]); aa = (MYFLT*)&(ans->data[i]); if (UNLIKELY(offset)) memset(aa, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { memset(&aa[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nans; ARRAYDAT *l = p->left; ARRAYDAT *r = p->right; int size = ans->sizes[0]; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; int i, n, nsmps = CS_KSMPS; if (UNLIKELY(ans->data == NULL || l->data==NULL || r->data==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (l->sizes[0]sizes[0]; if (r->sizes[0]sizes[0]; for (i=0; idata[i]); b = (MYFLT*)&(r->data[i]); aa = (MYFLT*)&(ans->data[i]); if (UNLIKELY(offset)) memset(aa, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { memset(&aa[nsmps], '\0', early*sizeof(MYFLT)); } for (n=0; nans; ARRAYDAT *l = p->left; ARRAYDAT *r = p->right; int size = ans->sizes[0]; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; int i, n, nsmps = CS_KSMPS; if (UNLIKELY(ans->data == NULL || l->data==NULL || r->data==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (l->sizes[0]sizes[0]; if (r->sizes[0]sizes[0]; for (i=0; idata[i]); b = (MYFLT*)&(r->data[i]); aa = (MYFLT*)&(ans->data[i]); if (UNLIKELY(offset)) memset(aa, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { memset(&aa[nsmps], '\0', early*sizeof(MYFLT)); } for (n=0; nans; ARRAYDAT *l = p->left; ARRAYDAT *r = p->right; int size = ans->sizes[0]; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; int i, n, nsmps = CS_KSMPS; if (UNLIKELY(ans->data == NULL || l->data==NULL || r->data==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (l->sizes[0]sizes[0]; if (r->sizes[0]sizes[0]; for (i=0; idata[i]); b = (MYFLT*)&(r->data[i]); aa = (MYFLT*)&(ans->data[i]); if (UNLIKELY(offset)) memset(aa, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { memset(&aa[nsmps], '\0', early*sizeof(MYFLT)); } for (n=0; nPerfError(csound, p->h.insdshead, Str("division by zero in array-var " "at index %d/%d"), i,n); aa[n] = a[n] / b[n]; } } return OK; } // k * a[] static int tabkamult(CSOUND *csound, TABARITH2 *p) { ARRAYDAT *ans = p->ans; MYFLT l = *p->left; ARRAYDAT *r = p->right; int size = ans->sizes[0]; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; int i, n, nsmps = CS_KSMPS; if (UNLIKELY(ans->data == NULL || r->data==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (r->sizes[0]sizes[0]; for (i=0; idata[i]); aa = (MYFLT*)&(ans->data[i]); if (UNLIKELY(offset)) memset(aa, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { memset(&aa[nsmps], '\0', early*sizeof(MYFLT)); } for (n=0; nans; MYFLT l = *p->right; ARRAYDAT *r = p->left; int size = ans->sizes[0]; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; int i, n, nsmps = CS_KSMPS; if (UNLIKELY(ans->data == NULL || r->data==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (r->sizes[0]sizes[0]; for (i=0; idata[i]); aa = (MYFLT*)&(ans->data[i]); if (UNLIKELY(offset)) memset(aa, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { memset(&aa[nsmps], '\0', early*sizeof(MYFLT)); } for (n=0; nans; MYFLT l = *p->left; ARRAYDAT *r = p->right; int size = ans->sizes[0]; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; int i, n, nsmps = CS_KSMPS; if (UNLIKELY(ans->data == NULL || r->data==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (r->sizes[0]sizes[0]; for (i=0; idata[i]); aa = (MYFLT*)&(ans->data[i]); if (UNLIKELY(offset)) memset(aa, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { memset(&aa[nsmps], '\0', early*sizeof(MYFLT)); } for (n=0; nans; MYFLT l = *p->right; ARRAYDAT *r = p->left; int size = ans->sizes[0]; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; int i, n, nsmps = CS_KSMPS; if (UNLIKELY(ans->data == NULL || r->data==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (r->sizes[0]sizes[0]; for (i=0; idata[i]); aa = (MYFLT*)&(ans->data[i]); if (UNLIKELY(offset)) memset(aa, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { memset(&aa[nsmps], '\0', early*sizeof(MYFLT)); } for (n=0; nans; MYFLT l = *p->left; ARRAYDAT *r = p->right; int size = ans->sizes[0]; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; int i, n, nsmps = CS_KSMPS; if (UNLIKELY(ans->data == NULL || r->data==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (r->sizes[0]sizes[0]; for (i=0; idata[i]); aa = (MYFLT*)&(ans->data[i]); if (UNLIKELY(offset)) memset(aa, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { memset(&aa[nsmps], '\0', early*sizeof(MYFLT)); } for (n=0; nans; MYFLT l = *p->right; ARRAYDAT *r = p->left; int size = ans->sizes[0]; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; int i, n, nsmps = CS_KSMPS; if (UNLIKELY(ans->data == NULL || r->data==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (r->sizes[0]sizes[0]; for (i=0; idata[i]); aa = (MYFLT*)&(ans->data[i]); if (UNLIKELY(offset)) memset(aa, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { memset(&aa[nsmps], '\0', early*sizeof(MYFLT)); } for (n=0; nans; MYFLT l = *p->left; ARRAYDAT *r = p->right; int size = ans->sizes[0]; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; int i, n, nsmps = CS_KSMPS; if (UNLIKELY(ans->data == NULL || r->data==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (r->sizes[0]sizes[0]; for (i=0; idata[i]); aa = (MYFLT*)&(ans->data[i]); if (UNLIKELY(offset)) memset(aa, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { memset(&aa[nsmps], '\0', early*sizeof(MYFLT)); } for (n=0; nPerfError(csound, p->h.insdshead, Str("division by zero in array-var " "at index %d/%d"), i,n); aa[n] = l / b[n]; } } return OK; } // a[] / k static int tabakdiv(CSOUND *csound, TABARITH1 *p) { ARRAYDAT *ans = p->ans; MYFLT l = *p->right; ARRAYDAT *r = p->left; int size = ans->sizes[0]; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; int i, n, nsmps = CS_KSMPS; if (UNLIKELY(ans->data == NULL || r->data==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (UNLIKELY(l==FL(0.0))) csound->PerfError(csound, p->h.insdshead, Str("division by zero in array-var")); if (r->sizes[0]sizes[0]; for (i=0; idata[i]); aa = (MYFLT*)&(ans->data[i]); if (UNLIKELY(offset)) memset(aa, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { memset(&aa[nsmps], '\0', early*sizeof(MYFLT)); } for (n=0; nans; MYFLT *l = p->left; ARRAYDAT *r = p->right; int size = ans->sizes[0]; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; int i, n, nsmps = CS_KSMPS; if (UNLIKELY(ans->data == NULL || r->data==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (r->sizes[0]sizes[0]; for (i=0; idata[i]); aa = (MYFLT*)&(ans->data[i]); if (UNLIKELY(offset)) memset(aa, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { memset(&aa[nsmps], '\0', early*sizeof(MYFLT)); } for (n=0; ntab->data)) return OK; return csound->InitError(csound, Str("array-variable not initialised")); } static int tabqset1(CSOUND *csound, TABQUERY1 *p) { if (LIKELY(p->tab->data)) return OK; return csound->InitError(csound, Str("array-variable not initialised")); } static int tabmax(CSOUND *csound, TABQUERY *p) { ARRAYDAT *t = p->tab; int i, size = 0, pos = 0;; MYFLT ans; if (UNLIKELY(t->data == NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); /* if (UNLIKELY(t->dimensions!=1)) */ /* return csound->PerfError(csound, p->h.insdshead, */ /* Str("array-variable not vector")); */ for (i=0; idimensions; i++) size += t->sizes[i]; ans = t->data[0]; for (i=1; idata[i]>ans) { ans = t->data[i]; pos = i; } *p->ans = ans; if (p->OUTOCOUNT>1) *p->pos = (MYFLT)pos; return OK; } static int tabmax1(CSOUND *csound, TABQUERY *p) { if (tabqset(csound, p) == OK) return tabmax(csound, p); else return NOTOK; } static int tabmin(CSOUND *csound, TABQUERY *p) { ARRAYDAT *t = p->tab; int i, size = 0, pos = 0; MYFLT ans; if (UNLIKELY(t->data == NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); /* if (UNLIKELY(t->dimensions!=1)) */ /* return csound->PerfError(csound, p->h.insdshead, Str("array-variable not a vector")); */ for (i=0; idimensions; i++) size += t->sizes[i]; ans = t->data[0]; for (i=1; idata[i]data[i]; pos = i; } *p->ans = ans; if (p->OUTOCOUNT>1) *p->pos = (MYFLT)pos; return OK; } static int tabmin1(CSOUND *csound, TABQUERY *p) { if (LIKELY(tabqset(csound, p) == OK)) return tabmin(csound, p); else return NOTOK; } static int tabsum(CSOUND *csound, TABQUERY1 *p) { ARRAYDAT *t = p->tab; int i, size = 0; MYFLT ans; if (UNLIKELY(t->data == NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not initialised")); if (UNLIKELY(t->dimensions!=1)) return csound->PerfError(csound, p->h.insdshead, Str("array-variable not a vector")); ans = t->data[0]; for (i=0; idimensions; i++) size += t->sizes[i]; for (i=1; idata[i]; *p->ans = ans; return OK; } static int tabsum1(CSOUND *csound, TABQUERY1 *p) { if (LIKELY(tabqset1(csound, p) == OK)) return tabsum(csound, p); else return NOTOK; } static int tabscaleset(CSOUND *csound, TABSCALE *p) { if (LIKELY(p->tab->data && p->tab->dimensions==1)) return OK; return csound->InitError(csound, Str("array-variable not initialised")); } static int tabscale(CSOUND *csound, TABSCALE *p) { MYFLT min = *p->kmin, max = *p->kmax; int strt = (int)MYFLT2LRND(*p->kstart), end = (int)MYFLT2LRND(*p->kend); ARRAYDAT *t = p->tab; MYFLT tmin; MYFLT tmax; int i; MYFLT range; tmin = t->data[strt]; tmax = tmin; // Correct start and ending points if (end<0) end = t->sizes[0]; else if (end>t->sizes[0]) end = t->sizes[0]; if (strt<0) strt = 0; else if (strt>t->sizes[0]) strt = t->sizes[0]; if (enddata[i]data[i]; if (t->data[i]>tmax) tmax = t->data[i]; } /* printf("start/end %d/%d max/min = %g/%g tmax/tmin = %g/%g range=%g\n", */ /* strt, end, max, min, tmax, tmin, range); */ range = (max-min)/(tmax-tmin); for (i=strt; idata[i] = (t->data[i]-tmin)*range + min; } return OK; } static int tabscale1(CSOUND *csound, TABSCALE *p) { if (LIKELY(tabscaleset(csound, p) == OK)) return tabscale(csound, p); else return NOTOK; } typedef struct { OPDS h; ARRAYDAT *dst; ARRAYDAT *src; int len; } TABCPY; static int get_array_total_size(ARRAYDAT* dat) { int i; int size; if (UNLIKELY(dat->sizes == NULL)) { return -1; } size = dat->sizes[0]; for (i = 1; i < dat->dimensions; i++) { size *= dat->sizes[i]; } return size; } static int tabcopy(CSOUND *csound, TABCPY *p) { int i, arrayTotalSize, memMyfltSize; if (UNLIKELY(p->src->data==NULL) || p->src->dimensions <= 0 ) return csound->InitError(csound, Str("array-variable not initialised")); if (UNLIKELY(p->dst->dimensions > 0 && p->src->dimensions != p->dst->dimensions)) return csound->InitError(csound, Str("array-variable dimensions do not match")); if (UNLIKELY(p->src->arrayType != p->dst->arrayType)) return csound->InitError(csound, Str("array-variable types do not match")); if (p->src == p->dst) return OK; arrayTotalSize = get_array_total_size(p->src); memMyfltSize = p->src->arrayMemberSize / sizeof(MYFLT); p->dst->arrayMemberSize = p->src->arrayMemberSize; if (arrayTotalSize != get_array_total_size(p->dst)) { p->dst->dimensions = p->src->dimensions; p->dst->sizes = csound->Malloc(csound, sizeof(int) * p->src->dimensions); memcpy(p->dst->sizes, p->src->sizes, sizeof(int) * p->src->dimensions); if (p->dst->data == NULL) { p->dst->data = csound->Calloc(csound, p->src->arrayMemberSize * arrayTotalSize); } else { p->dst->data = csound->ReAlloc(csound, p->dst->data, p->src->arrayMemberSize * arrayTotalSize); memset(p->dst->data, 0, p->src->arrayMemberSize * arrayTotalSize); } } for (i = 0; i < arrayTotalSize; i++) { int index = (i * memMyfltSize); p->dst->arrayType->copyValue(csound, (void*)(p->dst->data + index), (void*)(p->src->data + index)); } return OK; } static int tabcopy1(CSOUND *csound, TABCPY *p) { int i, arrayTotalSize, memMyfltSize; if (UNLIKELY(p->src->data==NULL) || p->src->dimensions <= 0 ) return csound->InitError(csound, Str("array-variable not initialised")); if (p->dst->dimensions > 0 && p->src->dimensions != p->dst->dimensions) return csound->InitError(csound, Str("array-variable dimensions do not match")); // if (p->src->arrayType != p->dst->arrayType) // return csound->InitError(csound, Str("array-variable types do not match")); if (p->src == p->dst) return OK; arrayTotalSize = get_array_total_size(p->src); memMyfltSize = p->src->arrayMemberSize / sizeof(MYFLT); p->dst->arrayMemberSize = p->src->arrayMemberSize; if (arrayTotalSize != get_array_total_size(p->dst)) { p->dst->dimensions = p->src->dimensions; p->dst->sizes = csound->Malloc(csound, sizeof(int) * p->src->dimensions); memcpy(p->dst->sizes, p->src->sizes, sizeof(int) * p->src->dimensions); if (p->dst->data == NULL) { p->dst->data = csound->Calloc(csound, p->src->arrayMemberSize * arrayTotalSize); } else { p->dst->data = csound->ReAlloc(csound, p->dst->data, p->src->arrayMemberSize * arrayTotalSize); memset(p->dst->data, 0, p->src->arrayMemberSize * arrayTotalSize); } } for (i = 0; i < arrayTotalSize; i++) { int index = (i * memMyfltSize); p->dst->arrayType->copyValue(csound, (void*)(p->dst->data + index), (void*)(p->src->data + index)); } return OK; } static int tab2ftab(CSOUND *csound, TABCOPY *p) { FUNC *ftp; int fsize; MYFLT *fdata; ARRAYDAT *t = p->tab; int i, tlen = 0; if (UNLIKELY(p->tab->data==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("array-var not initialised")); if (UNLIKELY((ftp = csound->FTFindP(csound, p->kfn)) == NULL)) return csound->PerfError(csound, p->h.insdshead, Str("No table for copy2ftab")); for (i=0; idimensions; i++) tlen += t->sizes[i]; fsize = ftp->flen; fdata = ftp->ftable; if (fsizetab->data, sizeof(MYFLT)*tlen); return OK; } static int tab2ftabi(CSOUND *csound, TABCOPY *p) { FUNC *ftp; int fsize; MYFLT *fdata; ARRAYDAT *t = p->tab; int i, tlen = 0; if (UNLIKELY(p->tab->data==NULL)) return csound->InitError(csound, Str("array-var not initialised")); if (UNLIKELY((ftp = csound->FTFindP(csound, p->kfn)) == NULL)) return csound->InitError(csound, Str("No table for copy2ftab")); for (i=0; idimensions; i++) tlen += t->sizes[i]; fsize = ftp->flen; fdata = ftp->ftable; if (fsizetab->data, sizeof(MYFLT)*tlen); return OK; } typedef struct { OPDS h; ARRAYDAT *tab; MYFLT *start, *end, *incr; int len; } TABGEN; static int tabgen(CSOUND *csound, TABGEN *p) { MYFLT *data = p->tab->data; MYFLT start = *p->start; MYFLT end = *p->end; MYFLT incr = *p->incr; int i, size = (end - start)/incr + 1; //printf("start=%f end=%f incr=%f size=%d\n", start, end, incr, size); if (UNLIKELY(size < 0)) return csound->InitError(csound, Str("inconsistent start, end and increment parameters")); tabensure(csound, p->tab, size); if (UNLIKELY(p->tab->data==NULL)) { tabensure(csound, p->tab, size); p->tab->sizes[0] = size; } //else /* This is wrong if array exists only write to specified part */ //size = p->tab->sizes[0]; data = p->tab->data; for (i=0; i < size; i++) { data[i] = start; //printf("%f ", start); start += incr; } //printf("]\n"); return OK; } static int ftab2tabi(CSOUND *csound, TABCOPY *p) { FUNC *ftp; int fsize; MYFLT *fdata; int tlen; if (UNLIKELY((ftp = csound->FTFindP(csound, p->kfn)) == NULL)) return csound->InitError(csound,Str("No table for copy2ftab")); fsize = ftp->flen; if (UNLIKELY(p->tab->data==NULL)) { tabensure(csound, p->tab, fsize); p->tab->sizes[0] = fsize; } tlen = p->tab->sizes[0]; fdata = ftp->ftable; if (fsizetab->data, fdata, sizeof(MYFLT)*tlen); return OK; } static int ftab2tab(CSOUND *csound, TABCOPY *p) { FUNC *ftp; int fsize; MYFLT *fdata; int tlen; if (UNLIKELY((ftp = csound->FTFindP(csound, p->kfn)) == NULL)) return csound->PerfError(csound, p->h.insdshead, Str("No table for copy2ftab")); fsize = ftp->flen; if (UNLIKELY(p->tab->data==NULL)) { tabensure(csound, p->tab, fsize); p->tab->sizes[0] = fsize; } tlen = p->tab->sizes[0]; fdata = ftp->ftable; if (fsizetab->data, fdata, sizeof(MYFLT)*tlen); return OK; } typedef struct { OPDS h; ARRAYDAT *tab, *tabin; MYFLT *start, *end, *inc; int len; } TABSLICE; static int tabslice(CSOUND *csound, TABSLICE *p){ MYFLT *tabin = p->tabin->data; int start = (int) *p->start; int end = (int) *p->end; int inc = (int) *p->inc; int size = (end - start)/inc + 1; int i, destIndex; int memMyfltSize = p->tabin->arrayMemberSize / sizeof(MYFLT); if (UNLIKELY(size < 0)) return csound->InitError(csound, Str("inconsistent start, end parameters")); if (UNLIKELY(p->tabin->dimensions!=1 || end >= p->tabin->sizes[0])) { //printf("size=%d old tab size = %d\n", size, p->tabin->sizes[0]); return csound->InitError(csound, Str("slice larger than original size")); } if (UNLIKELY(inc<=0)) return csound->InitError(csound, Str("slice increment must be positive")); tabensure(csound, p->tab, size); for (i = start, destIndex = 0; i < end + 1; i+=inc, destIndex++) { p->tab->arrayType->copyValue(csound, p->tab->data + (destIndex * memMyfltSize), tabin + (memMyfltSize * i)); } return OK; } //#include "str_ops.h" //// This cheats using strcpy opcode fake //static int tabsliceS(CSOUND *csound, TABSLICE *p){ // // MYFLT *tabin = p->tabin->data; // int start = (int) *p->start; // int end = (int) *p->end; // int size = end - start + 1, i; // STRCPY_OP xx; // if (UNLIKELY(size < 0)) // return csound->InitError(csound, // Str("inconsistent start, end parameters")); // if (UNLIKELY(p->tabin->dimensions!=1 || size > p->tabin->sizes[0])) { // //printf("size=%d old tab size = %d\n", size, p->tabin->sizes[0]); // return csound->InitError(csound, Str("slice larger than original size")); // } // tabensure(csound, p->tab, size); // for (i=0; itab->data +i; // xx.str = tabin+start+i; // strcpy_opcode_S(csound, &xx); // } // //memcpy(p->tab->data, tabin+start,sizeof(MYFLT)*size); // return OK; //} typedef struct { OPDS h; ARRAYDAT *tab, *tabin; STRINGDAT *str; int len; OENTRY *opc; } TABMAP; static int tabmap_set(CSOUND *csound, TABMAP *p) { MYFLT *data, *tabin = p->tabin->data; int n, size; OENTRY *opc = NULL; EVAL eval; if (UNLIKELY(p->tabin->data == NULL)||p->tabin->dimensions!=1) return csound->InitError(csound, Str("array-var not initialised")); size = p->tabin->sizes[0]; if (UNLIKELY(p->tab->data==NULL)) { tabensure(csound, p->tab, size); p->tab->sizes[0] = size; } else size = size < p->tab->sizes[0] ? size : p->tab->sizes[0]; data = p->tab->data; opc = find_opcode_new(csound, p->str->data, "i", "i"); if (UNLIKELY(opc == NULL)) return csound->InitError(csound, Str("%s not found"), p->str->data); p->opc = opc; for (n=0; n < size; n++) { eval.a = &tabin[n]; eval.r = &data[n]; opc->iopadr(csound, (void *) &eval); } opc = find_opcode_new(csound, p->str->data, "k", "k"); p->opc = opc; return OK; } static int tabmap_perf(CSOUND *csound, TABMAP *p) { MYFLT *data = p->tab->data, *tabin = p->tabin->data; int n, size; OENTRY *opc = p->opc; EVAL eval; if (UNLIKELY(p->tabin->data == NULL) || p->tabin->dimensions !=1) return csound->PerfError(csound, p->h.insdshead, Str("array-var not initialised")); if (UNLIKELY(p->tab->data==NULL) || p->tab->dimensions !=1) return csound->PerfError(csound, p->h.insdshead, Str("array-var not initialised")); size = p->tab->sizes[0]; if (UNLIKELY(opc == NULL)) return csound->PerfError(csound, p->h.insdshead, Str("map fn not found at k rate")); for (n=0; n < size; n++) { eval.a = &tabin[n]; eval.r = &data[n]; opc->kopadr(csound, (void *) &eval); } return OK; } int tablength(CSOUND *csound, TABQUERY1 *p) { int opt = (int)*p->opt; if (UNLIKELY(p->tab==NULL || opt>p->tab->dimensions)) *p->ans = -FL(1.0); else if (UNLIKELY(opt<=0)) *p->ans = p->tab->dimensions; else *p->ans = p->tab->sizes[opt-1]; return OK; } typedef struct { OPDS h; ARRAYDAT *tabin; unsigned int len; } OUTA; static int outa_set(CSOUND *csound, OUTA *p) { int len = (p->tabin->dimensions==1?p->tabin->sizes[0]:-1); if (len>(int)csound->nchnls) len = csound->nchnls; if (UNLIKELY(len<=0)) return NOTOK; p->len = len; if (p->tabin->arrayMemberSize != (int)(CS_KSMPS*sizeof(MYFLT))) return NOTOK; return OK; } static int outa(CSOUND *csound, OUTA *p) { unsigned int n, nsmps = CS_KSMPS, nchns = csound->GetNchnls(csound); unsigned int l, pl = p->len; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = nsmps - p->h.insdshead->ksmps_no_end; MYFLT *data = p->tabin->data; MYFLT *sp= csound->spraw; if (!csound->spoutactive) { memset(sp, '\0', nsmps*nchns*sizeof(MYFLT)); for (l=0; lspoutactive = 1; } else { for (l=0; llen; l++) { for (n=offset; ntabin; // should call ensure here but it is a-rate aa->dimensions = 1; if (aa->sizes) csound->Free(csound, aa->sizes); if (aa->data) csound->Free(csound, aa->data); aa->sizes = (int*)csound->Malloc(csound, sizeof(int)); aa->sizes[0] = p->len = csound->inchnls; aa->data = (MYFLT*) csound->Malloc(csound, CS_KSMPS*sizeof(MYFLT)*p->len); aa->arrayMemberSize = CS_KSMPS*sizeof(MYFLT); return OK; } static int ina(CSOUND *csound, OUTA *p) { ARRAYDAT *aa = p->tabin; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, l, nsmps = CS_KSMPS; MYFLT *data = aa->data; MYFLT *sp= CS_SPIN; uint32_t len = (uint32_t)p->len; for (l=0; ltabin; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, j, l, nsmps = CS_KSMPS; MYFLT *data = aa->data; MYFLT *sp= CS_SPOUT; uint32_t len = (uint32_t)p->len; if (csound->spoutactive) { for (l=0; lGetNchnls(csound); j++) { if (iGetNchnls(csound)*sizeof(MYFLT)); } return OK; } static int monitora_init(CSOUND *csound, OUTA *p) { ARRAYDAT *aa = p->tabin; // should call ensure here but it is a-rate aa->dimensions = 1; if (aa->sizes) csound->Free(csound, aa->sizes); if (aa->data) csound->Free(csound, aa->data); aa->sizes = (int*)csound->Malloc(csound, sizeof(int)); aa->sizes[0] = p->len = csound->nchnls; aa->data = (MYFLT*) csound->Malloc(csound, CS_KSMPS*sizeof(MYFLT)*p->len); aa->arrayMemberSize = CS_KSMPS*sizeof(MYFLT); return OK; } /* transform operations */ typedef struct _fft { OPDS h; ARRAYDAT *out; ARRAYDAT *in, *in2; MYFLT *f; MYFLT b; int n; void *setup; AUXCH mem; } FFT; static unsigned int isPowerOfTwo (unsigned int x) { return x != 0 ? !(x & (x - 1)) : 0; } int init_rfft(CSOUND *csound, FFT *p){ int N = p->in->sizes[0]; if (UNLIKELY(p->in->dimensions > 1)) return csound->InitError(csound, Str("rfft: only one-dimensional arrays allowed")); if (isPowerOfTwo(N)){ tabensure(csound, p->out,N); p->setup = csound->RealFFT2Setup(csound, N, FFT_FWD); } else tabensure(csound, p->out, N+2); return OK; } int perf_rfft(CSOUND *csound, FFT *p){ int N = p->out->sizes[0]; memcpy(p->out->data,p->in->data,N*sizeof(MYFLT)); if (isPowerOfTwo(N)){ csound->RealFFT2(csound,p->setup,p->out->data); } else{ p->out->data[N] = FL(0.0); csound->RealFFTnp2(csound,p->out->data,N); } return OK; } int rfft_i(CSOUND *csound, FFT *p){ if (init_rfft(csound,p) == OK) return perf_rfft(csound, p); else return NOTOK; } int init_rifft(CSOUND *csound, FFT *p){ int N = p->in->sizes[0]; if (UNLIKELY(p->in->dimensions > 1)) return csound->InitError(csound, Str("rifft: only one-dimensional arrays allowed")); if (isPowerOfTwo(N)){ p->setup = csound->RealFFT2Setup(csound, N, FFT_INV); tabensure(csound, p->out, N); } else tabensure(csound, p->out, N+2); return OK; } int perf_rifft(CSOUND *csound, FFT *p){ int N = p->out->sizes[0]; memcpy(p->out->data,p->in->data,N*sizeof(MYFLT)); if (isPowerOfTwo(N)) csound->RealFFT2(csound,p->setup,p->out->data); else{ p->out->data[N] = FL(0.0); csound->InverseRealFFTnp2(csound,p->out->data,N); } return OK; } int rifft_i(CSOUND *csound, FFT *p){ if (init_rifft(csound,p) == OK) return perf_rifft(csound, p); else return NOTOK; } int init_rfftmult(CSOUND *csound, FFT *p){ int N = p->in->sizes[0]; if (UNLIKELY(N != p->in2->sizes[0])) return csound->InitError(csound, Str("array sizes do not match\n")); /*if (isPowerOfTwo(N))*/ tabensure(csound, p->out, N); /* else return csound->InitError(csound, Str("non-pow-of-two case not implemented yet \n"));*/ return OK; } int perf_rfftmult(CSOUND *csound, FFT *p){ int N = p->out->sizes[0]; csound->RealFFTMult(csound,p->out->data,p->in->data,p->in2->data,N,1); return OK; } /* these should have been in the CSOUND struct, but are not */ void csoundComplexFFTnp2(CSOUND *csound, MYFLT *buf, int FFTsize); void csoundInverseComplexFFTnp2(CSOUND *csound, MYFLT *buf, int FFTsize); int init_fft(CSOUND *csound, FFT *p){ int N2 = p->in->sizes[0]; if (UNLIKELY(p->in->dimensions > 1)) return csound->InitError(csound, Str("fft: only one-dimensional arrays allowed")); tabensure(csound,p->out,N2); return OK; } int perf_fft(CSOUND *csound, FFT *p){ int N2 = p->in->sizes[0]; memcpy(p->out->data,p->in->data,N2*sizeof(MYFLT)); if (isPowerOfTwo(N2)) csound->ComplexFFT(csound,p->out->data,N2/2); else { csoundComplexFFTnp2(csound,p->out->data,N2/2); } return OK; } int fft_i(CSOUND *csound, FFT *p){ if (init_fft(csound,p) == OK) return perf_fft(csound, p); else return NOTOK; } int init_ifft(CSOUND *csound, FFT *p){ int N2 = p->in->sizes[0]; if (UNLIKELY(p->in->dimensions > 1)) return csound->InitError(csound, Str("fftinv: only one-dimensional arrays allowed")); tabensure(csound, p->out, N2); return OK; } int perf_ifft(CSOUND *csound, FFT *p){ int N2 = p->out->sizes[0]; memcpy(p->out->data,p->in->data,N2*sizeof(MYFLT)); if (isPowerOfTwo(N2)){ csound->InverseComplexFFT(csound,p->out->data,N2/2); } else { csoundInverseComplexFFTnp2(csound,p->out->data,N2/2); } return OK; } int ifft_i(CSOUND *csound, FFT *p){ if (LIKELY(init_ifft(csound,p) == OK)) return perf_ifft(csound, p); else return NOTOK; } int init_recttopol(CSOUND *csound, FFT *p){ int N = p->in->sizes[0]; tabensure(csound, p->out, N); return OK; } int perf_recttopol(CSOUND *csound, FFT *p){ int i, end = p->out->sizes[0]; MYFLT *in, *out, mag, ph; in = p->in->data; out = p->out->data; for (i=2;iout->sizes[0]; MYFLT *in, *out, re, im; in = p->in->data; out = p->out->data; for(i=2;iin2->sizes[0] == p->in->sizes[0])){ int N = p->in2->sizes[0]-1; tabensure(csound, p->out, N*2); return OK; } else return csound->InitError(csound, Str("in array sizes do not match: %d and %d\n"), p->in2->sizes[0],p->in->sizes[0]); } int perf_poltorect2(CSOUND *csound, FFT *p){ int i,j, end = p->in->sizes[0]-1; MYFLT *mags, *phs, *out, re, im; mags = p->in->data; phs = p->in2->data; out = p->out->data; for(i=2,j=1;jin->sizes[0]; tabensure(csound, p->out, N/2+1); return OK; } int perf_mags(CSOUND *csound, FFT *p){ int i,j, end = p->out->sizes[0]; MYFLT *in, *out; in = p->in->data; out = p->out->data; for(i=2,j=1;jout->sizes[0]; MYFLT *in, *out; in = p->in->data; out = p->out->data; for(i=0,j=0;jout, p->in->sizes[0]); if (LIKELY(*((MYFLT *)p->in2))) p->b = 1/log(*((MYFLT *)p->in2)); else p->b = FL(1.0); return OK; } int perf_logarray(CSOUND *csound, FFT *p){ int i, end = p->out->sizes[0]; MYFLT bas = p->b; MYFLT *in, *out; in = p->in->data; out = p->out->data; if (LIKELY(bas)) for(i=0;iin->sizes[0]; tabensure(csound, p->out, N*2); return OK; } int perf_rtoc(CSOUND *csound, FFT *p){ int i,j, end = p->out->sizes[0]; MYFLT *in, *out; in = p->in->data; out = p->out->data; for(i=0,j=0;iin->sizes[0]; tabensure(csound, p->out, N/2); return OK; } int perf_ctor(CSOUND *csound, FFT *p){ int i,j, end = p->out->sizes[0]; MYFLT *in, *out; in = p->in->data; out = p->out->data; for(i=0,j=0;jin->sizes[0]; int i,type = (int) *p->f; MYFLT *w; tabensure(csound, p->out, N); if (p->mem.auxp == 0 || p->mem.size < N*sizeof(MYFLT)) csound->AuxAlloc(csound, N*sizeof(MYFLT), &p->mem); w = (MYFLT *) p->mem.auxp; switch(type){ case 0: for(i=0; iout->sizes[0], off = *((MYFLT *)p->in2); MYFLT *in, *out, *w; in = p->in->data; out = p->out->data; w = (MYFLT *) p->mem.auxp; while(off < 0) off += end; for(i=0;ifin->N; if (LIKELY(isPowerOfTwo(N))){ p->setup = csound->RealFFT2Setup(csound, N/2, FFT_FWD); tabensure(csound, p->out, N/2+1); } else return csound->InitError(csound, Str("non-pow-of-two case not implemented yet\n")); p->lastframe = 0; return OK; } int pvsceps_perf(CSOUND *csound, PVSCEPS *p){ if (p->lastframe < p->fin->framecount) { int N = p->fin->N; int i, j; MYFLT *ceps = p->out->data; MYFLT coefs = *p->coefs; float *fin = (float *) p->fin->frame.auxp; for(i=j=0; i < N; i+=2, j++){ ceps[j] = log(fin[i] > 0.0 ? fin[i] : 1e-20); } ceps[N/2] = fin[N/2]; csound->RealFFT2(csound, p->setup, ceps); if (coefs){ // lifter coefs for (i=coefs*2; i < N/2; i++) ceps[i] = 0.0; ceps[N/2] = 0.0; } p->lastframe = p->fin->framecount; } return OK; } int init_ceps(CSOUND *csound, FFT *p){ int N = p->in->sizes[0]-1; if (UNLIKELY(N < 64)) return csound->InitError(csound, Str("FFT size too small (min 64 samples)\n")); if (LIKELY(isPowerOfTwo(N))){ p->setup = csound->RealFFT2Setup(csound, N, FFT_FWD); tabensure(csound, p->out, N+1); } else return csound->InitError(csound, Str("non-pow-of-two case not implemented yet\n")); return OK; } int perf_ceps(CSOUND *csound, FFT *p){ int siz = p->out->sizes[0]-1, i; MYFLT *ceps = p->out->data; MYFLT coefs = *((MYFLT *)p->in2); MYFLT *mags = (MYFLT *) p->in->data; for(i=0; i < siz; i++){ ceps[i] = log(mags[i] > 0.0 ? mags[i] : 1e-20); } ceps[siz] = mags[siz]; csound->RealFFT2(csound, p->setup, ceps); if (coefs){ // lifter coefs for (i=coefs*2; i < siz; i++) ceps[i] = 0.0; ceps[siz] = 0.0; } return OK; } int init_iceps(CSOUND *csound, FFT *p){ int N = p->in->sizes[0]-1; if (LIKELY(isPowerOfTwo(N))) { p->setup = csound->RealFFT2Setup(csound, N, FFT_INV); tabensure(csound, p->out, N+1); } else return csound->InitError(csound, Str("non-pow-of-two case not implemented yet\n")); N++; if (p->mem.auxp == NULL || p->mem.size < N*sizeof(MYFLT)) csound->AuxAlloc(csound, N*sizeof(MYFLT), &p->mem); return OK; } int perf_iceps(CSOUND *csound, FFT *p){ int siz = p->in->sizes[0]-1, i; MYFLT *spec = (MYFLT *)p->mem.auxp; MYFLT *out = p->out->data; memcpy(spec, p->in->data, siz*sizeof(MYFLT)); csound->RealFFT2(csound,p->setup,spec); for(i=0; i < siz; i++){ out[i] = exp(spec[i]); } out[siz] = spec[siz]; /* Writes outside data allocated */ return OK; } int rows_init(CSOUND *csound, FFT *p){ if (p->in->dimensions == 2){ int siz = p->in->sizes[1]; tabensure(csound, p->out, siz); return OK; } else return csound->InitError(csound, Str("in array not 2-dimensional\n")); } int rows_perf(CSOUND *csound, FFT *p){ int start = *((MYFLT *)p->in2); if (LIKELY(start < p->in->sizes[0])) { int bytes = p->in->sizes[1]*sizeof(MYFLT); start *= p->in->sizes[1]; memcpy(p->out->data,p->in->data+start,bytes); return OK; } else return csound->PerfError(csound, p->h.insdshead, Str("requested row is out of range\n")); } int cols_init(CSOUND *csound, FFT *p){ if (LIKELY(p->in->dimensions == 2)){ int siz = p->in->sizes[0]; tabensure(csound, p->out, siz); return OK; } else return csound->InitError(csound, Str("in array not 2-dimensional\n")); } int cols_perf(CSOUND *csound, FFT *p){ int start = *((MYFLT *)p->in2); if (LIKELY(start < p->in->sizes[1])) { int j,i,collen = p->in->sizes[1], len = p->in->sizes[0]; for(j=0,i=start; j < len; i+=collen, j++) { p->out->data[j] = p->in->data[i]; } return OK; } else return csound->PerfError(csound, p->h.insdshead, Str("requested col is out of range\n")); } static inline void tabensure2D(CSOUND *csound, ARRAYDAT *p, int rows, int columns) { if (p->data==NULL || p->dimensions == 0 || (p->dimensions==2 && (p->sizes[0] < rows || p->sizes[1] < columns))) { size_t ss; if (p->data == NULL) { CS_VARIABLE* var = p->arrayType->createVariable(csound, NULL); p->arrayMemberSize = var->memBlockSize; } ss = p->arrayMemberSize*rows*columns; if (p->data==NULL) { p->data = (MYFLT*)csound->Calloc(csound, ss); p->dimensions = 2; p->sizes = (int*)csound->Malloc(csound, sizeof(int)*2); } else p->data = (MYFLT*) csound->ReAlloc(csound, p->data, ss); p->sizes[0] = rows; p->sizes[1] = columns; } } int set_rows_init(CSOUND *csound, FFT *p){ int sizs = p->in->sizes[0]; int row = *((MYFLT *)p->in2); tabensure2D(csound, p->out, row+1, sizs); return OK; } int set_rows_perf(CSOUND *csound, FFT *p){ int start = *((MYFLT *)p->in2); if (UNLIKELY(start < 0 || start >= p->out->sizes[0])) return csound->PerfError(csound, p->h.insdshead, Str("Error: index out of range\n")); int bytes = p->in->sizes[0]*sizeof(MYFLT); start *= p->out->sizes[1]; memcpy(p->out->data+start,p->in->data,bytes); return OK; } int set_cols_init(CSOUND *csound, FFT *p){ int siz = p->in->sizes[0]; int col = *((MYFLT *)p->in2); tabensure2D(csound, p->out, siz, col+1); return OK; } int set_cols_perf(CSOUND *csound, FFT *p){ int start = *((MYFLT *)p->in2); if (UNLIKELY(start < 0 || start >= p->out->sizes[1])) return csound->PerfError(csound, p->h.insdshead, Str("Error: index out of range\n")); int j,i,len = p->out->sizes[0]; for(j=0,i=start; j < len; i+=len, j++) p->out->data[i] = p->in->data[j]; return OK; } int shiftin_init(CSOUND *csound, FFT *p){ int sizs = CS_KSMPS; tabensure(csound, p->out, sizs); p->n = 0; return OK; } int shiftin_perf(CSOUND *csound, FFT *p){ uint32_t siz = p->out->sizes[0], n = p->n; MYFLT *in = ((MYFLT *) p->in); if (n + CS_KSMPS < siz) { memcpy(p->out->data+n,in,CS_KSMPS*sizeof(MYFLT)); } else { int num = siz - n; memcpy(p->out->data+n,in,num*sizeof(MYFLT)); memcpy(p->out->data,in+num,(CS_KSMPS-num)*sizeof(MYFLT)); } p->n = (n + CS_KSMPS)%siz; return OK; } int shiftout_init(CSOUND *csound, FFT *p){ int siz = p->in->sizes[0]; p->n = ((int)*((MYFLT *)p->in2) % siz); if (UNLIKELY((uint32_t) siz < CS_KSMPS)) return csound->InitError(csound, Str("input array too small\n")); return OK; } int shiftout_perf(CSOUND *csound, FFT *p){ uint32_t siz = p->in->sizes[0], n = p->n; MYFLT *out = ((MYFLT *) p->out); if (n + CS_KSMPS < siz) { memcpy(out,p->in->data+n,CS_KSMPS*sizeof(MYFLT)); } else { int num = siz - n; memcpy(out,p->in->data+n,num*sizeof(MYFLT)); memcpy(out+num,p->in->data,(CS_KSMPS-num)*sizeof(MYFLT)); } p->n = (n + CS_KSMPS)%siz; return OK; } int scalarset(CSOUND *csound, FFT *p){ uint32_t siz = 0 , dim = p->out->dimensions, i; MYFLT val = *((MYFLT *)p->in); for(i=0; i < dim; i++) siz += p->out->sizes[i]; for(i=0; i < siz; i++) p->out->data[i] = val; return OK; } int unwrap(CSOUND *csound, FFT *p){ int i,siz = p->in->sizes[0]; MYFLT *phs = p->out->data; for(i=0; i < siz; i++){ while(phs[i] >= PI) phs[i] -= 2*PI; while(phs[i] < -PI) phs[i] += 2*PI; } return OK; } void *csoundDCTSetup(CSOUND *csound, int FFTsize, int d); void csoundDCT(CSOUND *csound, void *p, MYFLT *sig); int init_dct(CSOUND *csound, FFT *p){ int N = p->in->sizes[0]; if (LIKELY(isPowerOfTwo(N))){ if (UNLIKELY(p->in->dimensions > 1)) return csound->InitError(csound, Str("dct: only one-dimensional arrays allowed")); tabensure(csound, p->out, N); p->setup = csoundDCTSetup(csound,N,FFT_FWD); return OK; } else return csound->InitError(csound, Str("dct: non-pow-of-two sizes not yet implemented")); } int kdct(CSOUND *csound, FFT *p){ int N = p->out->sizes[0]; memcpy(p->out->data,p->in->data,N*sizeof(MYFLT)); csoundDCT(csound,p->setup,p->out->data); return OK; } int dct(CSOUND *csound, FFT *p){ if (!init_dct(csound,p)){ kdct(csound,p); return OK; } else return NOTOK; } int init_dctinv(CSOUND *csound, FFT *p){ int N = p->in->sizes[0]; if (LIKELY(isPowerOfTwo(N))){ if (UNLIKELY(p->in->dimensions > 1)) return csound->InitError(csound, Str("dctinv: only one-dimensional arrays allowed")); tabensure(csound, p->out, N); p->setup = csoundDCTSetup(csound,N,FFT_INV); return OK; } else return csound->InitError(csound, Str("dctinv: non-pow-of-two sizes not yet implemented")); } int dctinv(CSOUND *csound, FFT *p){ if (LIKELY(!init_dctinv(csound,p))){ kdct(csound,p); return OK; } else return NOTOK; } int perf_pows(CSOUND *csound, FFT *p){ int i,j, end = p->out->sizes[0]; MYFLT *in, *out; in = p->in->data; out = p->out->data; for(i=2,j=1;jlen; int N = p->in->sizes[0]; if (LIKELY(L < N)) tabensure(csound, p->out, L); else return csound->InitError(csound, "mfb: filter bank size exceeds input array length"); if (p->bins.auxp == NULL || p->bins.size < (L+2)*sizeof(int)) csound->AuxAlloc(csound, (L+2)*sizeof(MYFLT), &p->bins); return OK; } int mfb(CSOUND *csound, MFB *p) { int i,j; int *bin = (int *) p->bins.auxp; MYFLT start,max,end; MYFLT g = FL(0.0), incr, decr; int L = p->out->sizes[0]; int N = p->in->sizes[0]; MYFLT sum = FL(0.0); MYFLT *out = p->out->data; MYFLT *in = p->in->data; MYFLT sr = csound->GetSr(csound); start = f2mel(*p->low); end = f2mel(*p->up); incr = (end-start)/(L+1); for(i=0;i N) bin[i] = N; start += incr; } for(i=0; i < L; i++){ start = bin[i]; max = bin[i+1]; end = bin[i+2]; incr = 1.0/(max - start); decr = 1.0/(end - max); for(j=start; j < max; j++){ sum += in[j]*g; g += incr; } g = FL(1.0); for(j=max; j < end; j++){ sum += in[j]*g; g -= decr; } out[i] = sum/(end - start); g = FL(0.0); sum = FL(0.0); } return OK; } int mfbi(CSOUND *csound, MFB *p){ if (LIKELY(mfb_init(csound,p) == OK)) return mfb(csound,p); else return NOTOK; } typedef struct _centr{ OPDS h; MYFLT *out; ARRAYDAT *in; } CENTR; int array_centroid(CSOUND *csound, CENTR *p){ MYFLT *in = p->in->data,a=FL(0.0),b=FL(0.0); int NP1 = p->in->sizes[0]; MYFLT f = csound->GetSr(csound)/(2*(NP1 - 1)),cf; int i; cf = f*FL(0.5); for(i=0; i < NP1-1; i++, cf+=f){ a += in[i]; b += in[i]*cf; } *p->out = a > FL(0.0) ? b/a : FL(0.0); return OK; } typedef struct _inout{ OPDS H; MYFLT *out, *in; } INOUT; int nxtpow2(CSOUND *csound, INOUT *p){ int inval = (int)*p->in; int powtwo = 2; while (powtwo < inval) powtwo *= 2; *p->out = powtwo; return OK; } // reverse, scramble, mirror, stutter, rotate, ... // jpff: stutter is an interesting one (very musical). It basically // randomly repeats (holds) values based on a probability parameter static OENTRY arrayvars_localops[] = { { "nxtpow2", sizeof(INOUT), 0, 1, "i", "i", (SUBR)nxtpow2}, { "init.0", sizeof(ARRAYINIT), 0, 1, ".[]", "m", (SUBR)array_init }, { "fillarray", 0xffff }, { "fillarray.k", sizeof(TABFILL), 0, 1, "k[]", "m", (SUBR)tabfill }, { "fillarray.i", sizeof(TABFILL), 0, 1, "i[]", "m", (SUBR)tabfill }, { "fillarray.s", sizeof(TABFILL), 0, 1, "S[]", "W", (SUBR)tabfill }, { "array", 0xffff }, { "array.k", sizeof(TABFILL), _QQ, 1, "k[]", "m", (SUBR)tabfill }, { "array.i", sizeof(TABFILL), _QQ, 1, "i[]", "m", (SUBR)tabfill }, #if 0 { "##array_set.i", sizeof(ARRAY_SET), 0, 1, "", "i[]im", (SUBR)array_set }, { "##array_init", sizeof(ARRAY_SET), 0, 1, "", ".[]im", (SUBR)array_set }, { "##array_set.k0", sizeof(ARRAY_SET), 0, 2, "", "k[]kz", NULL, (SUBR)array_set }, { "##array_set.i2", sizeof(ARRAY_SET), 0, 3, "", ".[].m", (SUBR)array_set, (SUBR)array_set }, { "##array_set.k", sizeof(ARRAY_SET), 0, 2, "", ".[].z", NULL, (SUBR)array_set }, { "##array_get.i", sizeof(ARRAY_GET), 0, 1, "i", "i[]m", (SUBR)array_get }, /*{ "##array_get.i", sizeof(ARRAY_GET), 0, 1, "S", "S[]m", (SUBR)array_get },*/ { "##array_get.k0", sizeof(ARRAY_GET), 0, 3, "k", "k[]z", (SUBR)array_get, (SUBR)array_get }, { "##array_get.i2", sizeof(ARRAY_GET), 0, 3, ".", ".[]m", (SUBR)array_get, (SUBR)array_get }, { "##array_get.k", sizeof(ARRAY_GET), 0, 3, ".", ".[]z", (SUBR)array_get, (SUBR)array_get }, #else { "##array_init", sizeof(ARRAY_SET), 0, 1, "", ".[].m", (SUBR)array_set }, { "##array_set.k", sizeof(ARRAY_SET), 0, 2, "", "k[]km", NULL,(SUBR)array_set}, { "##array_set.a", sizeof(ARRAY_SET), 0, 2, "", "a[]am", NULL, (SUBR)array_set}, { "##array_set.i", sizeof(ARRAY_SET), 0, 1, "", ".[].m", (SUBR)array_set }, { "##array_set.e", sizeof(ARRAY_SET), 0, 1, "", "i[].z", (SUBR)array_err }, { "##array_set.x", sizeof(ARRAY_SET), 0, 2, "", ".[].z", NULL, (SUBR)array_set}, { "##array_get.k", sizeof(ARRAY_GET), 0, 2, "k", "k[]m", NULL,(SUBR)array_get }, { "##array_get.a", sizeof(ARRAY_GET), 0, 2, "a", "a[]m",NULL, (SUBR)array_get }, { "##array_get.x", sizeof(ARRAY_GET), 0, 1, ".", ".[]m",(SUBR)array_get }, { "##array_get.K", sizeof(ARRAY_GET), 0, 2, ".", ".[]z",NULL, (SUBR)array_get}, { "i.Ai", sizeof(ARRAY_GET),0, 1, "i", "k[]m", (SUBR)array_get }, { "i.Ak", sizeof(ARRAY_GET),0, 1, "i", "k[]z", (SUBR)array_get }, #endif /* ******************************************** */ {"##add.[s]", sizeof(TABARITH), 0, 3, "a[]", "a[]a[]", (SUBR)tabarithset, (SUBR)tabaadd}, {"##add.[]", sizeof(TABARITH), 0, 3, "k[]", "k[]k[]", (SUBR)tabarithset, (SUBR)tabadd}, {"##add.[i]", sizeof(TABARITH), 0, 1, "i[]", "i[]i[]", (SUBR)tabaddi}, /* ******************************************** */ {"##sub.[a]", sizeof(TABARITH), 0, 3, "a[]", "a[]a[]", (SUBR)tabarithset, (SUBR)tabasub}, {"##sub.[]", sizeof(TABARITH), 0, 3, "k[]", "k[]k[]", (SUBR)tabarithset, (SUBR)tabsub}, {"##sub.[i]", sizeof(TABARITH), 0, 1, "i[]", "i[]i[]", (SUBR)tabsubi}, // {"##neg.[]", sizeof(TABARITH), 0, 3, "k[]", "k[]", // (SUBR)tabarithset1, (SUBR)tabneg}, {"##mul.[a]", sizeof(TABARITH), 0, 3, "a[]", "a[]a[]", (SUBR)tabarithset,(SUBR)tabamul}, {"##mul.[]", sizeof(TABARITH), 0, 3, "k[]", "k[]k[]", (SUBR)tabarithset,(SUBR)tabmult}, {"##mul.[i]", sizeof(TABARITH), 0, 1, "i[]", "i[]i[]", (SUBR)tabmulti}, {"##div.[a]", sizeof(TABARITH), 0, 3, "a[]", "a[]a[]", (SUBR)tabarithset,(SUBR)tabadiv}, {"##div.[]", sizeof(TABARITH), 0, 3, "k[]", "k[]k[]", (SUBR)tabarithset,(SUBR)tabdiv }, {"##div.[i]", sizeof(TABARITH), 0, 1, "i[]", "i[]i[]", (SUBR)tabdivi }, {"##rem.[]", sizeof(TABARITH), 0, 3, "k[]", "k[]k[]", (SUBR)tabarithset, (SUBR)tabrem}, {"##rem.[i]", sizeof(TABARITH), 0, 1, "i[]", "i[]i[]", (SUBR)tabremi}, {"##add.[i", sizeof(TABARITH1), 0, 3, "k[]", "k[]i", (SUBR)tabarithset1, (SUBR)tabaiadd }, {"##add.i[", sizeof(TABARITH2), 0, 3, "k[]", "ik[]", (SUBR)tabarithset2, (SUBR)tabiaadd }, {"##add.[p", sizeof(TABARITH1), 0, 1, "i[]", "i[]i", (SUBR)tabaiaddi }, {"##add.p[", sizeof(TABARITH2), 0, 1, "i[]", "ii[]", (SUBR)tabiaaddi }, {"##sub.[i", sizeof(TABARITH1), 0, 3, "k[]", "k[]i", (SUBR)tabarithset1, (SUBR)tabaisub }, {"##sub.i[", sizeof(TABARITH2), 0, 3, "k[]", "ik[]", (SUBR)tabarithset2, (SUBR)tabiasub }, {"##sub.[p", sizeof(TABARITH1), 0, 1, "i[]", "i[]i", (SUBR)tabaisubi }, {"##sub.p[", sizeof(TABARITH2), 0, 1, "i[]", "ii[]", (SUBR)tabiasubi }, {"##mul.[i", sizeof(TABARITH1), 0, 3, "k[]", "k[]i", (SUBR)tabarithset1, (SUBR)tabaimult }, {"##mul.i[", sizeof(TABARITH2), 0, 3, "k[]", "ik[]", (SUBR)tabarithset2, (SUBR)tabiamult }, {"##mul.[p", sizeof(TABARITH1), 0, 1, "i[]", "i[]i", (SUBR)tabaimulti }, {"##mul.p[", sizeof(TABARITH2), 0, 1, "i[]", "ii[]", (SUBR)tabiamulti }, {"##div.[i", sizeof(TABARITH1), 0, 3, "k[]", "k[]i", (SUBR)tabarithset1, (SUBR)tabaidiv }, {"##div.i[", sizeof(TABARITH2), 0, 3, "k[]", "ik[]", (SUBR)tabarithset2, (SUBR)tabiadiv }, {"##div.[p", sizeof(TABARITH1), 0, 1, "i[]", "i[]i", (SUBR)tabaidivi }, {"##div.p[", sizeof(TABARITH2), 0, 1, "i[]", "ii[]", (SUBR)tabiadivi }, {"##rem.[i", sizeof(TABARITH1),0, 3, "k[]", "k[]i", (SUBR)tabarithset1, (SUBR)tabairem }, {"##rem.i[", sizeof(TABARITH2),0, 3, "k[]", "ik[]", (SUBR)tabarithset2, (SUBR)tabiarem }, {"##rem.[p", sizeof(TABARITH1),0, 1, "i[]", "i[]i", (SUBR)tabairemi }, {"##rem.p[", sizeof(TABARITH2),0, 1, "i[]", "ii[]", (SUBR)tabiaremi }, {"##add.[k", sizeof(TABARITH1), 0, 3, "k[]", "k[]k", (SUBR)tabarithset1, (SUBR)tabaiadd }, {"##add.k[", sizeof(TABARITH2), 0, 3, "k[]", "kk[]", (SUBR)tabarithset2, (SUBR)tabiaadd }, {"##add.[ak", sizeof(TABARITH1), 0, 3, "a[]", "a[]k", (SUBR)tabarithset1, (SUBR)tabakadd }, {"##add.k[a", sizeof(TABARITH2), 0, 3, "a[]", "ka[]", (SUBR)tabarithset2, (SUBR)tabkaadd }, {"##sub.[k", sizeof(TABARITH1), 0, 3, "k[]", "k[]k", (SUBR)tabarithset1, (SUBR)tabaisub }, {"##sub.k[", sizeof(TABARITH2), 0, 3, "k[]", "kk[]", (SUBR)tabarithset2, (SUBR)tabiasub }, {"##sub.[ak", sizeof(TABARITH1), 0, 3, "a[]", "a[]k", (SUBR)tabarithset1, (SUBR)tabaksub }, {"##sub.k[a", sizeof(TABARITH2), 0, 3, "a[]", "ka[]", (SUBR)tabarithset2, (SUBR)tabkasub }, {"##mul.[k", sizeof(TABARITH1), 0, 3, "k[]", "k[]k", (SUBR)tabarithset1, (SUBR)tabaimult }, {"##mul.k[", sizeof(TABARITH2), 0, 3, "k[]", "kk[]", (SUBR)tabarithset2, (SUBR)tabiamult }, {"##mul.[ak", sizeof(TABARITH1), 0, 3, "a[]", "a[]k", (SUBR)tabarithset1, (SUBR)tabakmult }, {"##mul.k[a", sizeof(TABARITH2), 0, 3, "a[]", "ka[]", (SUBR)tabarithset2, (SUBR)tabkamult }, {"##mul.a[a", sizeof(TABARITH2), 0, 3, "a[]", "aa[]", (SUBR)tabarithset2, (SUBR)tabaamult }, {"##div.[k", sizeof(TABARITH1), 0, 3, "k[]", "k[]k", (SUBR)tabarithset1, (SUBR)tabaidiv }, {"##div.k[", sizeof(TABARITH2), 0, 3, "k[]", "kk[]", (SUBR)tabarithset2, (SUBR)tabiadiv }, {"##div.[ak", sizeof(TABARITH1), 0, 3, "a[]", "a[]k", (SUBR)tabarithset1, (SUBR)tabakdiv }, {"##div.k[a", sizeof(TABARITH2), 0, 3, "a[]", "ka[]", (SUBR)tabarithset2, (SUBR)tabkadiv }, {"##rem.[k", sizeof(TABARITH1),0, 3, "k[]", "k[]k", (SUBR)tabarithset1, (SUBR)tabairem }, {"##rem.k[", sizeof(TABARITH2),0, 3, "k[]", "kk[]", (SUBR)tabarithset2, (SUBR)tabiarem }, {"##pow.[]", sizeof(TABARITH), 0, 3, "k[]", "k[]k[]", (SUBR)tabarithset,(SUBR)tabpow }, {"##pow.[i]", sizeof(TABARITH), 0, 1, "i[]", "i[]i[]", (SUBR)tabpowi }, {"##pow.[i", sizeof(TABARITH1), 0, 3, "k[]", "k[]i", (SUBR)tabarithset1, (SUBR)tabaipow }, {"##pow.i[", sizeof(TABARITH2), 0, 3, "k[]", "ik[]", (SUBR)tabarithset2, (SUBR)tabiapow }, {"##pow.[p", sizeof(TABARITH1), 0, 1, "i[]", "i[]i", (SUBR)tabaipowi }, {"##pow.p[", sizeof(TABARITH2), 0, 1, "i[]", "ii[]", (SUBR)tabiapowi }, {"##pow.[k", sizeof(TABARITH1), 0, 3, "k[]", "k[]k", (SUBR)tabarithset1, (SUBR)tabaipow }, {"##pow.k[", sizeof(TABARITH2), 0, 3, "k[]", "kk[]", (SUBR)tabarithset2, (SUBR)tabiapow }, { "maxtab", 0xffff}, { "maxtab.k",sizeof(TABQUERY),_QQ, 3, "kz", "k[]", (SUBR) tabqset, (SUBR) tabmax }, { "maxarray", 0xffff}, { "maxarray.k", sizeof(TABQUERY), 0, 3, "kz", "k[]", (SUBR) tabqset,(SUBR) tabmax }, { "maxarray.i", sizeof(TABQUERY), 0, 1, "iI", "i[]",(SUBR) tabmax1, NULL }, { "mintab", 0xffff}, { "minarray", 0xffff}, { "mintab.k", sizeof(TABQUERY),_QQ, 3, "kz", "k[]", (SUBR) tabqset, (SUBR) tabmin }, { "minarray.k", sizeof(TABQUERY),0, 3, "kz", "k[]",(SUBR) tabqset, (SUBR) tabmin }, { "minarray.i", sizeof(TABQUERY),0, 1, "iI", "i[]",(SUBR) tabmin1 }, { "sumarray", 0xffff}, { "sumtab", sizeof(TABQUERY1),_QQ, 3, "k", "k[]", (SUBR) tabqset1, (SUBR) tabsum }, { "sumarray.k", sizeof(TABQUERY1),0, 3, "k", "k[]", (SUBR) tabqset1, (SUBR) tabsum }, { "sumarray.i", sizeof(TABQUERY1),0, 1, "i", "i[]", (SUBR) tabsum1 }, { "scalet", sizeof(TABSCALE), _QQ, 3, "", "k[]kkOJ", (SUBR) tabscaleset,(SUBR) tabscale }, { "scalearray", 0xffff}, { "scalearray.k", sizeof(TABSCALE), 0, 3, "", "k[]kkOJ", (SUBR) tabscaleset,(SUBR) tabscale }, { "scalearray.1", sizeof(TABSCALE), 0, 1, "", "i[]iiOJ", (SUBR) tabscale1 }, { "=.I", sizeof(TABCPY), 0, 1, "i[]", "i[]", (SUBR)tabcopy1, NULL }, { "=.J", sizeof(TABCPY), 0, 1, "i[]", "k[]", (SUBR)tabcopy1, NULL }, { "=.K", sizeof(TABCPY), 0, 3, "k[]", "i[]", (SUBR)tabcopy1, (SUBR)tabcopy1 }, { "=._", sizeof(TABCPY), 0, 3, ".[]", ".[]", (SUBR)tabcopy, (SUBR)tabcopy }, { "tabgen", sizeof(TABGEN), _QQ, 1, "k[]", "iip", (SUBR) tabgen, NULL }, { "tabmap_i", sizeof(TABMAP), _QQ, 1, "k[]", "k[]S", (SUBR) tabmap_set }, { "tabmap", sizeof(TABMAP), _QQ, 3, "k[]", "k[]S", (SUBR) tabmap_set, (SUBR) tabmap_perf}, { "tabmap", sizeof(TABMAP), _QQ, 3, "k[]", "k[]S", (SUBR) tabmap_set, (SUBR) tabmap_perf}, { "genarray.i", sizeof(TABGEN),0, 1, "i[]", "iip", (SUBR) tabgen, NULL }, { "genarray_i", sizeof(TABGEN),0, 1, "k[]", "iip", (SUBR) tabgen, NULL, NULL}, { "genarray.k", sizeof(TABGEN),0, 2, "k[]", "kkp", NULL, (SUBR)tabgen }, { "maparray_i", sizeof(TABMAP),0, 1, "k[]", "k[]S", (SUBR) tabmap_set }, { "maparray.k", sizeof(TABMAP), 0, 3, "k[]", "k[]S", (SUBR) tabmap_set, (SUBR) tabmap_perf }, { "maparray.i", sizeof(TABMAP), 0, 1, "i[]", "i[]S", (SUBR) tabmap_set }, /* { "maparray.s", sizeof(TABMAP), 0, 3, "S[]", "S[]S", (SUBR) tabmap_set, */ /* (SUBR) tabmap_perf }, */ { "tabslice", sizeof(TABSLICE), _QQ, 2, "k[]", "k[]iip", NULL, (SUBR) tabslice, NULL }, { "slicearray.i", sizeof(TABSLICE), 0, 1, "i[]", "i[]iip", (SUBR) tabslice, NULL, NULL }, { "slicearray.x", sizeof(TABSLICE), 0, 3, ".[]", ".[]iip", (SUBR) tabslice, (SUBR) tabslice, NULL }, // { "slicearray.s", sizeof(TABSLICE), 0, 3, "S[]", "[]ii", // (SUBR) tabsliceS, (SUBR) tabsliceS, NULL }, { "copy2ftab", sizeof(TABCOPY), TW|_QQ, 2, "", "k[]k", NULL, (SUBR) tab2ftab }, { "copy2ttab", sizeof(TABCOPY), TR|_QQ, 2, "", "k[]k", NULL, (SUBR) ftab2tab }, { "copya2ftab.k", sizeof(TABCOPY), TW, 3, "", "k[]k", (SUBR) tab2ftabi, (SUBR) tab2ftab }, { "copyf2array.k", sizeof(TABCOPY), TR, 3, "", "k[]k", (SUBR) ftab2tabi, (SUBR) ftab2tab }, { "copya2ftab.i", sizeof(TABCOPY), TW, 1, "", "i[]i", (SUBR) tab2ftabi }, { "copyf2array.i", sizeof(TABCOPY), TR, 1, "", "i[]i", (SUBR) ftab2tabi }, /* { "lentab", 0xffff}, */ { "lentab.i", sizeof(TABQUERY1), _QQ, 1, "i", "k[]p", (SUBR) tablength }, { "lentab.k", sizeof(TABQUERY1), _QQ, 1, "k", "k[]p", NULL, (SUBR) tablength }, { "lenarray.ix", sizeof(TABQUERY1), 0, 1, "i", ".[]p", (SUBR) tablength }, { "lenarray.kx", sizeof(TABQUERY1), 0, 2, "k", ".[]p", NULL, (SUBR)tablength }, { "out.A", sizeof(OUTA), 0, 5,"", "a[]", (SUBR)outa_set, NULL, (SUBR)outa}, { "in.A", sizeof(OUTA), 0, 5, "a[]", "", (SUBR)ina_set, NULL, (SUBR)ina}, { "monitor.A", sizeof(OUTA), 0, 5, "a[]", "", (SUBR)monitora_init, NULL, (SUBR)monitora_perf}, { "rfft", sizeof(FFT), 0, 3, "k[]","k[]", (SUBR) init_rfft, (SUBR) perf_rfft, NULL}, {"rfft", sizeof(FFT), 0, 1, "i[]","i[]", (SUBR) rfft_i, NULL, NULL}, {"rifft", sizeof(FFT), 0, 3, "k[]","k[]", (SUBR) init_rifft, (SUBR) perf_rifft, NULL}, {"rifft", sizeof(FFT), 0, 1, "i[]","i[]", (SUBR) rifft_i, NULL, NULL}, {"cmplxprod", sizeof(FFT), 0, 3, "k[]","k[]k[]", (SUBR) init_rfftmult, (SUBR) perf_rfftmult, NULL}, {"fft", sizeof(FFT), 0, 3, "k[]","k[]", (SUBR) init_fft, (SUBR) perf_fft, NULL}, {"fft", sizeof(FFT), 0, 1, "i[]","i[]", (SUBR) fft_i, NULL, NULL}, {"fftinv", sizeof(FFT), 0, 3, "k[]","k[]", (SUBR) init_ifft, (SUBR) perf_ifft, NULL}, {"fftinv", sizeof(FFT), 0, 1, "i[]","i[]", (SUBR) ifft_i, NULL, NULL}, {"rect2pol", sizeof(FFT), 0, 3, "k[]","k[]", (SUBR) init_recttopol, (SUBR) perf_recttopol, NULL}, {"pol2rect", sizeof(FFT), 0, 3, "k[]","k[]", (SUBR) init_recttopol, (SUBR) perf_poltorect, NULL}, {"pol2rect", sizeof(FFT), 0, 3, "k[]","k[]k[]", (SUBR) init_poltorect2, (SUBR) perf_poltorect2, NULL}, {"mags", sizeof(FFT), 0, 3, "k[]","k[]", (SUBR) init_mags, (SUBR) perf_mags, NULL}, {"pows", sizeof(FFT), 0, 3, "k[]","k[]", (SUBR) init_mags, (SUBR) perf_pows, NULL}, {"phs", sizeof(FFT), 0, 3, "k[]","k[]", (SUBR) init_mags, (SUBR) perf_phs, NULL}, {"log", sizeof(FFT), 0, 3, "k[]","k[]i", (SUBR) init_logarray, (SUBR) perf_logarray, NULL}, {"r2c", sizeof(FFT), 0, 1, "i[]","i[]", (SUBR) rtoc_i, NULL, NULL}, {"r2c", sizeof(FFT), 0, 3, "k[]","k[]", (SUBR) init_rtoc, (SUBR) perf_rtoc, NULL}, {"c2r", sizeof(FFT), 0, 1, "i[]","i[]", (SUBR) ctor_i, NULL, NULL}, {"c2r", sizeof(FFT), 0, 3, "k[]","k[]", (SUBR) init_ctor, (SUBR) perf_ctor, NULL}, {"window", sizeof(FFT), 0, 3, "k[]","k[]Op", (SUBR) init_window, (SUBR) perf_window, NULL}, {"pvsceps", sizeof(PVSCEPS), 0, 3, "k[]","fo", (SUBR) pvsceps_init, (SUBR) pvsceps_perf, NULL}, {"cepsinv", sizeof(FFT), 0, 3, "k[]","k[]", (SUBR) init_iceps, (SUBR) perf_iceps, NULL}, {"ceps", sizeof(FFT), 0, 3, "k[]","k[]k", (SUBR) init_ceps, (SUBR) perf_ceps, NULL}, {"getrow", sizeof(FFT), 0, 3, "k[]","k[]k", (SUBR) rows_init, (SUBR) rows_perf, NULL}, {"getcol", sizeof(FFT), 0, 3, "k[]","k[]k", (SUBR) cols_init, (SUBR) cols_perf, NULL}, {"setrow", sizeof(FFT), 0, 3, "k[]","k[]k", (SUBR) set_rows_init, (SUBR) set_rows_perf, NULL}, {"setcol", sizeof(FFT), 0, 3, "k[]","k[]k", (SUBR) set_cols_init, (SUBR) set_cols_perf, NULL}, {"shiftin", sizeof(FFT), 0, 5, "k[]","a", (SUBR) shiftin_init, NULL, (SUBR) shiftin_perf}, {"shiftout", sizeof(FFT), 0, 5, "a","k[]o", (SUBR) shiftout_init, NULL, (SUBR) shiftout_perf}, {"unwrap", sizeof(FFT), 0, 3, "k[]","k[]", (SUBR) init_recttopol, (SUBR) unwrap}, {"=.k", sizeof(FFT), 0, 3, "k[]","k", (SUBR) scalarset, (SUBR) scalarset}, {"dct", sizeof(FFT), 0, 3, "k[]","k[]", (SUBR) init_dct, (SUBR) kdct, NULL}, {"dct", sizeof(FFT), 0, 1, "i[]","i[]", (SUBR) dct, NULL, NULL}, {"dctinv", sizeof(FFT), 0, 3, "k[]","k[]", (SUBR) init_dctinv, (SUBR) kdct, NULL}, {"dctinv", sizeof(FFT), 0, 1, "i[]","i[]", (SUBR)dctinv, NULL, NULL}, {"mfb", sizeof(MFB), 0, 3, "k[]","k[]kki", (SUBR) mfb_init, (SUBR) mfb, NULL}, {"mfb", sizeof(MFB), 0, 1, "i[]","i[]iii", (SUBR)mfbi, NULL, NULL}, {"centroid", sizeof(CENTR), 0, 1, "i","i[]", (SUBR) array_centroid, NULL, NULL}, {"centroid", sizeof(CENTR), 0, 2, "k","k[]", NULL, (SUBR)array_centroid, NULL} }; LINKAGE_BUILTIN(arrayvars_localops) csound-6.10.0/Opcodes/babo.c000066400000000000000000000645401321653344700155550ustar00rootroot00000000000000 /* babo.c: Copyright (C) 2000 Davide Rocchesso, Nicola Bernardini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /*************************************************************************** * vi:set nowrap ts=4: * * Ball-within-a-box physical model reverberator * originally written by Paolo Filippi (paolfili@ml.swapnet.it) of CSC * (Centro di Sonologia Computazionale - Universita' di Padova, Italia) * * Model of a rectangular enclosure implemented by means of a * Circulant Feedback Delay Network * * The name BaBo and the whole structure of the model is * described in the article : * [1] D. Rocchesso "The Ball within the Box: a sound-processing * metaphor", Computer Music Journal, Vol 19, N. 4, * pp. 45-47, Winter 1995. * * Circulant Feedback Delay Networks (CFDN) are described in the article: * [2] D. Rocchesso and J.O. Smith "Circulant and Elliptic Feedback Delay Networks * for Artificial Reverberation", IEEE Trans. on Speech and * Audio Processing, vol. 5, n. 1, pp. 51-63, jan. 1997. * * Maximally-Diffusive CFDNs are described in the letter: * [3] D. Rocchesso "Maximally-Diffusive yet Efficient Feedback Delay Networks * for Artificial Reverberation", IEEE Signal Processing Letters, * vol. 4, n. 9, pp. 252-255, sep. 1997. * * This implementation has been developed under the advice of * Davide Rocchesso (rocchesso@sci.univr.it) and * Nicola Bernardini (nicb@axnet.it) * * $Id$ * ***************************************************************************/ /* * You will find the functions you are looking for (probably baboset() * and babo()) at the end of this file. Before that, there is some * explanation of the structure of babo and then a bunch of private * functions used by baboset() and babo(). */ /* * In general, (x,y,z) are coordinates in a three-dimensional space, either * of the sound source or of the pickup point (we use a pair of omnidi- * rectional pickups aligned with the x axis). * When the diffusion is maximal, each row of the matrix contains a * maximum-length sequence of +1 and -1. When the diffusion is minimal, the * matrix is diagonal. The continuous control of diffusion is done by moving * the eigenvalues along the unit circle and taking the inverse discrete fourier * transform of them [2,3]. */ /*------------------------------------------------------------------------*\ BABO STRUCTURE ^^^^ ^^^^^^^^^ ____ ------>| |tap0 (direct) input | |------>| | T |tap1 | | A |------>| | P |tap2 | | L |------>| _____________________________ | I | | | | | N |......>| +------------| g(0) g(1) g(2) ... g(14) |-------+ | E |tap6 | | +---------| g(14) g(0) g(1) ... g(13) |-----+ | | |------>| | | +------| g(13) g(14) g(0) ... g(12) |----+| | |____| | | | | | | .......................... | || | | | | | | | .......................... |....|| | | | | | | | .......................... | .|| | | | | | | +---| g(1) g(2) g(3) ... g(0) |-+ .|| | | | | | | | |_____________________________| | .|| | | | | | | | | .|| | | | | | | | | .|| | | | | | | | | .|| | ----|-(+)-|--|--|-----(z0)--------------------------+-.||-+ | | | | | | .|| | ----|----(+)-|--|--------------(z1)-----------------|-.|+ | | | | | | .|| | ----|-------(+)-|--------------------(z2)-----------|-.+| | | | | | .|| | ....|...........|...................................|.+|| | | | | | .|| | ----|----------(+)-------------------------(z14)----+ .|| | | tapline_out ( + ) | | | | | | | | early_diffuse | | v (1 - early_diffuse)->(*) |------------(*)----------------------------------(+) | |+--> \*-------------------------------------------------------------------------*/ /* Changes by JPff: #define'd out include of "config.h" Defined FLT_MAX Move static fn declarations out of function */ //#include "csdl.h" #include "csoundCore.h" #include "babo.h" #include #include "interlocks.h" #if !defined(FLT_MAX) #define FLT_MAX (1.0e38) #endif static const int sound_speed = 330; /* * private Babo tools */ #define square(x) ((x)*(x)) /* * Memory allocation object methods * * (this object is a bit funny because it is in fact a wrapper of the * memory allocation functions in csound) */ static BaboMemory * BaboMemory_create(CSOUND *csound, BaboMemory *this, size_t size_in_floats) { size_t size_in_bytes = size_in_floats * sizeof(MYFLT); csound->AuxAlloc(csound, size_in_bytes, &this->memptr); //memset(this->memptr.auxp, 0, size_in_bytes); this->samples = size_in_floats; return this; } static inline size_t BaboMemory_samples(const BaboMemory *this) { return this->samples; } static inline MYFLT * BaboMemory_start(const BaboMemory *this) { return (MYFLT *) this->memptr.auxp; } static inline MYFLT * BaboMemory_end(const BaboMemory *this) { return (MYFLT *) this->memptr.endp; } /* static inline MYFLT * */ /* BaboMemory_size(const BaboMemory *this) */ /* { */ /* return (MYFLT *) this->memptr.size; */ /* } */ /* * common delay/tapline methods */ static void _Babo_common_delay_create(CSOUND *csound, BaboDelay *this, MYFLT max_time) { size_t num_floats = (size_t)MYFLT2LRND((MYFLT)ceil((double)(max_time*CS_ESR))); BaboMemory_create(csound, &this->core, num_floats); } /* * Babo Delay object methods */ static BaboDelay * BaboDelay_create(CSOUND *csound, BaboDelay *this, MYFLT max_time) { _Babo_common_delay_create(csound, this, max_time); this->input = BaboMemory_start(&this->core); return this; } static MYFLT BaboDelay_input(BaboDelay *this, MYFLT input) { *this->input++ = input; if (this->input >= BaboMemory_end(&this->core)) this->input -= BaboMemory_samples(&this->core); return input; } static MYFLT BaboDelay_output(const BaboDelay *this) { size_t num_samples = BaboMemory_samples(&this->core); MYFLT *output_ptr = this->input - (num_samples - 1); if (output_ptr < BaboMemory_start(&this->core)) output_ptr += num_samples; return *output_ptr; } /* * Babo Tapline object methods */ /* * The tapline is created with a size that is dependent on the size * of the room (selected at i-time) */ static BaboTapline * BaboTapline_create(CSOUND *csound, BaboTapline *this, MYFLT x, MYFLT y, MYFLT z) { MYFLT max_time = (FL(2.0) * SQRT((x*x) + (y*y) + (z*z))) / sound_speed; _Babo_common_delay_create(csound, (BaboDelay *) this, max_time); this->input = BaboMemory_start(&this->core); return this; } static inline MYFLT BaboTapline_maxtime(CSOUND *csound, BaboDelay *this) { return (((MYFLT) BaboMemory_samples(&this->core)) * csound->onedsr); } static inline MYFLT BaboTapline_input(BaboTapline *this, MYFLT input) { return BaboDelay_input((BaboDelay *) this, input); } typedef struct { MYFLT attenuation; MYFLT delay_size; } BaboTapParameter; typedef struct { BaboTapParameter direct; BaboTapParameter tap[BABO_TAPS]; } BaboTaplineParameters; /* * BaboTapline_single_output: * this function calculates the delay output by doing linear interpolation * between the two adjacent integer sample delays of an otherwise fractional * delay time. This is why BaboTapParameter.delay_size is kept as a float * in the first place. */ /* a-rate function */ static MYFLT BaboTapline_single_output(const BaboTapline *this, const BaboTapParameter *pp) { /* * the assignment right below should be really a floor(p->delay_size), * but apparently floor() calls are really expensive on some * architectures (notably Pentiums), so we do a simple cast to a * size_t instead. This should always work, but I cannot test it on * other architectures than mine (k6), so it potentially is a source * of problems. [nicb@axnet.it] */ size_t delay_floor = (size_t) pp->delay_size; size_t delay_ceil = delay_floor + 1; MYFLT fractional = pp->delay_size - (MYFLT) delay_floor; MYFLT *output_floor = this->input - delay_floor; MYFLT *output_ceil = this->input - delay_ceil; MYFLT output = FL(0.0); if (output_floor < BaboMemory_start(&this->core)) output_floor += BaboMemory_samples(&this->core); if (output_ceil < BaboMemory_start(&this->core)) output_ceil += BaboMemory_samples(&this->core); output = (*output_floor*(1-fractional)) + (*output_ceil*fractional); return output * pp->attenuation; } /* k-rate function */ static inline void BaboTapline_preload_parameter(CSOUND *csound, BaboTapParameter *this, MYFLT distance) { /* * Direct sound parameters at the input of delay tap_lines. * Right and left direct_att is not really physical, but ensures that: * direct_att=(1/2) when distance is 1 m * direct_att=1 when distance is 0 m. */ this->delay_size = (distance / sound_speed) * CS_ESR; this->attenuation = FL(1.0) / (FL(1.0) + distance); } /* k-rate function */ static BaboTaplineParameters * BaboTapline_precalculate_parameters( CSOUND *csound, BaboTaplineParameters *results, MYFLT r_x, MYFLT r_y, MYFLT r_z, /* receiver position (i-rate) */ MYFLT s_x, MYFLT s_y, MYFLT s_z, /* source position (k-rate) */ MYFLT l_x, MYFLT l_y, MYFLT l_z) /* room coords (i-rate) */ { MYFLT sqr_xy, sqr_yz, sqr_xz, /* x^2+y^2 y^2+z^2 ....... */ sqr_diff_x, sqr_diff_y, sqr_diff_z; /* optimization temps */ /* image method distance calculation */ sqr_diff_x = square(r_x - s_x); sqr_diff_y = square(r_y - s_y); sqr_diff_z = square(r_z - s_z); sqr_yz = sqr_diff_y + sqr_diff_z; sqr_xz = sqr_diff_x + sqr_diff_z; sqr_xy = sqr_diff_x + sqr_diff_y; BaboTapline_preload_parameter(csound, &results->direct, SQRT(sqr_diff_x + sqr_yz)); BaboTapline_preload_parameter(csound, &results->tap[0], SQRT(square(l_x + r_x + s_x) + sqr_yz)); BaboTapline_preload_parameter(csound, &results->tap[1], SQRT(square(l_x - r_x - s_x) + sqr_yz)); BaboTapline_preload_parameter(csound, &results->tap[2], SQRT(sqr_xz + square(l_y - r_y - s_y))); BaboTapline_preload_parameter(csound, &results->tap[3], SQRT(sqr_xz + square(l_y + r_y + s_y))); BaboTapline_preload_parameter(csound, &results->tap[4], SQRT(sqr_xy + square(l_z - r_z - s_z))); BaboTapline_preload_parameter(csound, &results->tap[5], SQRT(sqr_xy + square(l_z + r_z + s_z))); return results; } /* a-rate function */ static MYFLT BaboTapline_output(CSOUND *csound, const BaboTapline *this, const BaboTaplineParameters *pars) { int i; MYFLT output = BaboTapline_single_output(this, &pars->direct); for (i = 0; i < BABO_TAPS; ++i) output += BaboTapline_single_output(this, &pars->tap[i]); return output; } /* * Babo lowpass filter object methods */ static BaboLowPass * BaboLowPass_create(BaboLowPass *this, MYFLT decay, MYFLT hidecay, MYFLT norm) { MYFLT real_decay = EXP(norm * LOG(decay)); MYFLT real_hidecay = EXP(norm * LOG(hidecay)); this->a0 = (real_decay + real_hidecay) * FL(0.25); this->a1 = (real_decay - real_hidecay) * FL(0.5); this->z1 = this->z2 = FL(0.0); return this; } static inline MYFLT BaboLowPass_input(BaboLowPass *this, MYFLT input) { this->z2 = this->z1; this->z1 = this->input; this->input = input; return input; } static inline MYFLT BaboLowPass_output(const BaboLowPass *this) { return (this->a0 * this->input) + (this->a1 * this->z1) + (this->a0 * this->z2); } /* * Babo node object methods */ static BaboNode * BaboNode_create(CSOUND *csound, BaboNode *this, MYFLT time, MYFLT min_time, MYFLT decay, MYFLT hidecay) { BaboDelay_create(csound, &this->delay, time); BaboLowPass_create(&this->filter, decay, hidecay, time/min_time); return this; } static inline MYFLT BaboNode_input(BaboNode *this, MYFLT input) { return BaboDelay_input(&this->delay, input); } static inline void BaboNode_feed_filter(BaboNode *this) { BaboLowPass_input(&this->filter, BaboDelay_output(&this->delay)); } static inline MYFLT BaboNode_output(const BaboNode *this) { return BaboLowPass_output(&this->filter); } /* * Babo Matrix object methods */ static void BaboMatrix_create_FDN(BaboMatrix *this, MYFLT diffusion) { int i,j; MYFLT _2PI_NODES = TWOPI_F / BABO_NODES; /* * The following sequence of eigenvalues provides, by IDFT, * the maximally diffusive sequence, i.e. a row of the circulant * feedback matrix. * eigenvalues are expressed in radians, because only the argument * is expressed, since the magnitude is one */ const MYFLT max_diffusion_eigenvalues[BABO_NODES]= { FL(3.142592), -FL(1.7370), -FL(2.1559), -FL(1.2566), -FL(2.9936), FL(1.0472), -FL(2.5133), -FL(1.6140), FL(1.6140), FL(2.5133), -FL(1.0472), FL(2.9936), FL(1.2566), FL(2.1559), FL(1.7370) }; /* * Here we multiply the arguments of the sequence of eigenvalues by * p->idiffusion_coeff. In this way we scale the amount of diffusion * Range of diffusion: 0 = no diffusion * 1 = maximum diffusion */ MYFLT real_X[BABO_NODES] = { FL(0.0) }, imaginary_X[BABO_NODES] = { FL(0.0) }, arg_X[BABO_NODES] = { FL(0.0) }, real_x[BABO_NODES] = { FL(0.0) }; for (i = 0; i < BABO_NODES; ++i) { real_X[i] = imaginary_X[i] = FL(0.0); arg_X[i] = max_diffusion_eigenvalues[i] * diffusion; real_X[i] = COS(arg_X[i]); imaginary_X[i] = SIN(arg_X[i]); } /* * The Real part of the InverseDFT of the eigenvalues supplies the * circulant matrix coefficients. */ for (i = 0; i < BABO_NODES; ++i) for (j = 0; j < BABO_NODES; ++j) real_x[j] += (real_X[j] * COS(_2PI_NODES*i*j)- imaginary_X[j] * SIN(_2PI_NODES*i*j))/BABO_NODES; for (i = 0; i < BABO_NODES; ++i) for (j = 0; j < BABO_NODES; ++j) this->fdn[i][j] = real_x[(j-i+15) % BABO_NODES]; } static MYFLT BaboMatrix_calculate_delays(MYFLT delay_time[], MYFLT x, MYFLT y, MYFLT z) { int i = 0; MYFLT min = FL(0.0); static const struct babo_diffusion_constants { int x, y, z; } BABO_DIRECTIONS[] = { /* * Each triplet is a mode identifier. * E.g. {1,0,0} is the first axial mode */ { 1, 0, 0 }, { 2, 1, 0 }, { 1, 1, 0 }, { 1, 2, 0 }, { 0, 1, 0 }, { 0, 2, 1 }, { 0, 1, 1 }, { 0, 1, 2 }, { 0, 0, 1 }, { 1, 0, 2 }, { 1, 0, 1 }, { 1, 1, 1 }, { 1, 2, 1 }, { 2, 1, 1 }, { 2, 0, 1 } }; /* * we calculate the delays related to each node, in the following * way: * * 2 * delay[i] = ----------------------------------------------- * +----------------------------------- * sound_speed * \ / | |2 | |2 | |2 * \/ | x[i] | | y[i] | | z[i] | * | ----- | + | ----- | + | ----- | * | X | | Y | | Z | * * and we keep a notion of the minimum delay path which is * needed later on to do the rescaling of the decay and hidecay * parameters. */ min = (MYFLT)FLT_MAX; /* let's initialize this with something really big */ for (i = 0; i < BABO_NODES; ++i) { const struct babo_diffusion_constants *dbdp = &BABO_DIRECTIONS[i]; delay_time[i] = FL(2.0) / (sound_speed * SQRT(((dbdp->x/x) * (dbdp->x/x)) + ((dbdp->y/y) * (dbdp->y/y)) + ((dbdp->z/z) * (dbdp->z/z)))); min = min > delay_time[i] ? delay_time[i] : min; } return min; } static BaboMatrix * BaboMatrix_create(CSOUND *csound, BaboMatrix *this, MYFLT diffusion, MYFLT x, MYFLT y, MYFLT z, MYFLT decay, MYFLT hidecay, MYFLT early_diffusion) { int i = 0; MYFLT delays[BABO_NODES]; MYFLT min_delay = BaboMatrix_calculate_delays(delays, x, y, z); this->complementary_early_diffusion = FL(1.0) - early_diffusion; BaboMatrix_create_FDN(this, diffusion); for (i = 0; i < BABO_NODES; ++i) BaboNode_create(csound, &this->node[i], delays[i], min_delay, decay, hidecay); return this; } static inline MYFLT BaboMatrix_coefficient(const BaboMatrix *this, int x, int y) { return this->fdn[x][y]; } /* a-rate function */ static void BaboMatrix_output(BaboMatrix *this, MYFLT outputs[], MYFLT input, MYFLT diffusion_coeff) { MYFLT filter_tmpout[BABO_NODES] = { FL(0.0) }, tmp2[BABO_NODES] = { FL(0.0) }; register int i = 0, j = 0; for (i = 0; i < BABO_NODES; ++i) { filter_tmpout[i] = BaboNode_output(&this->node[i]); BaboNode_feed_filter(&this->node[i]); } /* * Here the matrix-by-vector multiply takes place, xout is the * column vector. * The mod(BABO_NODES) operation allows to write the circulant matrix- * by-vector multiply in a compact way. */ for (i = 0; i < BABO_NODES; ++i) { for (j = 0; j < BABO_NODES; ++j) tmp2[i] += BaboMatrix_coefficient(this, i, j) * filter_tmpout[j]; BaboNode_input(&this->node[i], tmp2[i] + input); /* We add delayed signal at the input of ^^^^^ the delay lines. */ } outputs[0] = outputs[1] = BaboNode_output(&this->node[0]) + BaboNode_output(&this->node[4]) + BaboNode_output(&this->node[8]); outputs[0] += (diffusion_coeff * ((BaboNode_output(&this->node[7]) + BaboNode_output(&this->node[12])))); outputs[1] += (diffusion_coeff * ((BaboNode_output(&this->node[9]) + BaboNode_output(&this->node[13])))); outputs[0] *= this->complementary_early_diffusion; outputs[1] *= this->complementary_early_diffusion; } /* * private utility functions */ static void resolve_defaults(BABO *p); static void set_expert_values(CSOUND *csound, BABO *p); static void set_defaults(CSOUND *csound, BABO *p) { resolve_defaults(p); p->diffusion_coeff = p->diffusion_coeff < 0 ? BABO_DEFAULT_DIFFUSION_COEFF : p->diffusion_coeff; set_expert_values(csound,p); /* * the user supplies, optionally, the complete distance * or else it is set by default * we divide by two because it is more handy to deal * with half the distance in the program (i.e. the distance * from a center point) */ p->inter_receiver_distance *= FL(0.5); } static void resolve_defaults(BABO *p) { /* * in typical csound backward logic :), the defaults may or may not, * depending on how they're used in the orchestra definition, * turn out to run on the same pointer - so, basically all optional * argument values have to be copied (from last to first) in separate * "real" values inside the entry structure in order to be used */ p->expert_values = *(p->oexpert_values); p->diffusion_coeff = *(p->odiffusion_coeff); } static inline MYFLT load_value_or_default(const FUNC *table, int idx, MYFLT dEfault) { MYFLT result = (table != (FUNC *) NULL && idx < (int32)table->flen) ? table->ftable[idx] : dEfault; return result; } static void set_expert_values(CSOUND *csound, BABO *p) { FUNC *ftp = (FUNC *) NULL; /* brain-damaged function calling */ int n = 0; if (p->expert_values > 0) ftp = csound->FTnp2Find(csound, &(p->expert_values)); p->decay = load_value_or_default(ftp, n++, BABO_DEFAULT_DECAY); p->hidecay = load_value_or_default(ftp, n++, BABO_DEFAULT_HIDECAY); p->receiver_x = load_value_or_default(ftp, n++, BABO_DEFAULT_RECV_X); p->receiver_y = load_value_or_default(ftp, n++, BABO_DEFAULT_RECV_Y); p->receiver_z = load_value_or_default(ftp, n++, BABO_DEFAULT_RECV_Z); p->inter_receiver_distance = load_value_or_default(ftp, n++, BABO_DEFAULT_INTER_RECV_DISTANCE); p->direct = load_value_or_default(ftp, n++, BABO_DEFAULT_DIRECT); p->early_diffuse= load_value_or_default(ftp, n++, BABO_DEFAULT_DIFFUSE); } static void verify_coherence(CSOUND *csound, BABO *p) { if (UNLIKELY(*(p->lx) <= FL(0.0) || *(p->ly) <= FL(0.0) || *(p->lz) <= FL(0.0))) { csound->Warning(csound, Str("Babo: resonator dimensions are incorrect " "(%.1f, %.1f, %.1f)"), *(p->lx), *(p->ly), *(p->lz)); } } /* * PUBLIC FUNCTIONS - baboset(), babo() * * these get called from the csound engine * */ static int baboset(CSOUND *csound, void *entry) { BABO *p = (BABO *) entry; /* assuming the engine is right... :) */ set_defaults(csound,p); verify_coherence(csound,p); /* exits if call is wrong */ BaboTapline_create(csound,&p->tapline, *(p->lx), *(p->ly), *(p->lz)); BaboDelay_create(csound, &p->matrix_delay, BaboTapline_maxtime(csound, &p->tapline)); BaboMatrix_create(csound, &p->matrix, p->diffusion_coeff, *(p->lx), *(p->ly), *(p->lz), p->decay, p->hidecay, p->early_diffuse); return OK; } static int babo(CSOUND *csound, void *entry) { BABO *p = (BABO *) entry; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *outleft = p->outleft, *outright = p->outright, *input = p->input; BaboTaplineParameters left = { {FL(0.0)}, {{FL(0.0)}} }, right = { {FL(0.0)}, {{FL(0.0)}} }; BaboTapline_precalculate_parameters(csound, &left, p->receiver_x - p->inter_receiver_distance, p->receiver_y, p->receiver_z, *(p->ksource_x), *(p->ksource_y), *(p->ksource_z), *(p->lx), *(p->ly), *(p->lz)); BaboTapline_precalculate_parameters(csound, &right, p->receiver_x + p->inter_receiver_distance, p->receiver_y, p->receiver_z, *(p->ksource_x), *(p->ksource_y), *(p->ksource_z), *(p->lx), *(p->ly), *(p->lz)); if (UNLIKELY(offset)) { memset(outleft, '\0', offset*sizeof(MYFLT)); memset(outright, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&outleft[nsmps], '\0', early*sizeof(MYFLT)); memset(&outright[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; ntapline, input[n]); BaboDelay_input(&p->matrix_delay, input[n]); left_tapline_out = BaboTapline_output(csound, &p->tapline, &left) * p->early_diffuse; right_tapline_out = BaboTapline_output(csound, &p->tapline, &right) * p->early_diffuse; delayed_matrix_input = BaboDelay_output(&p->matrix_delay); BaboMatrix_output(&p->matrix, matrix_outputs, delayed_matrix_input, p->diffusion_coeff); outleft[n] = left_tapline_out + matrix_outputs[0]; outright[n] = right_tapline_out + matrix_outputs[1]; } return OK; } #define S(x) sizeof(x) static OENTRY babo_localops[] = { { "babo", S(BABO), TR, 5, "aa", "akkkiiijj",(SUBR)baboset, NULL, (SUBR)babo }, }; LINKAGE_BUILTIN(babo_localops) csound-6.10.0/Opcodes/babo.h000066400000000000000000000113121321653344700155470ustar00rootroot00000000000000/* babo.h: Copyright (C) 2000 Davide Rocchesso, Nicola Bernardini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /*-------------------------------------------------------------------------*\ * vi:set nowrap ts=4: * * $Id$ * * Header file for babo.c * * We choose 15 nodes for the BABO structure tryng to achieve * * sound quality results and minimal computational load according the rule * * that the nodes must be (2^N-1) * * \*------------------------------------------------------------------------*/ /* Changes by JPff: Fixed constant BABO_DEFAULT_DIFFUSION_COEFF */ #if !defined(__babo_h__) # define __babo_h__ #define BABO_NODES (15) /* Number of nodes of feedback delay network */ #define BABO_TAPS (6) /* Number of taps in the early reflections line */ typedef struct { AUXCH memptr; size_t samples; } BaboMemory; typedef struct { BaboMemory core; MYFLT *input; } BaboDelay; typedef BaboDelay BaboTapline; typedef struct { MYFLT a0, a1, z1, z2, input; } BaboLowPass; typedef struct { BaboDelay delay; BaboLowPass filter; } BaboNode; typedef struct { MYFLT complementary_early_diffusion; MYFLT fdn[BABO_NODES][BABO_NODES]; BaboNode node[BABO_NODES] ; } BaboMatrix; /* * The opcode functionality should be: * * ar,al babo asig,kx,ky,kz,ix,iy,iz[,idiff[,ifno]] * * where - mandatory arguments: * * kx,ky,kz - position of the source * ix,iy,iz - dimensions of the resonator (room) * * optional arguments: * * idiff - diffusion coefficient (a number from 0 to 1: default 1) * ifno - number of the GEN 02 function which holds all the other * defaulted parameters * * the optional size-8 gen 02 function may hold the following parameters: * * fn 0 8 2 decay hidecay rx ry rz rdistance direct early_diff * * where: * * decay - global decay coefficient (a number from 0 to 1: default 0.99) * hidecay - hi-freq decay coefficient (a number from 0 to 1: default 0.1) * rx,ry,rz - position of the receiver (default: 0, 0, 0) * rdistance - x distance between stereo receivers (e.g.: ears :) * (default: 0.3) * direct - direct delayed signal coefficient (default: 0.5) * early_diff - diffusion coefficient of the early reflections (default: 0.8) * */ typedef struct { OPDS h; /* defined in cs.h */ /* output args */ MYFLT *outleft,*outright, /* start input args */ *input, *ksource_x,*ksource_y,*ksource_z, *lx,*ly,*lz, /* optional args */ *odiffusion_coeff, *oexpert_values; /* end input args */ /* backward-logic optional args copy */ MYFLT diffusion_coeff, expert_values; /* internal values */ MYFLT decay, hidecay, receiver_x, receiver_y, receiver_z, inter_receiver_distance, direct, early_diffuse; BaboTapline tapline; /* early reflections */ BaboDelay matrix_delay; /* diffusion delay */ BaboMatrix matrix; /* diffusion */ } BABO; #define BABO_DEFAULT_DIFFUSION_COEFF (FL(1.0)) #define BABO_DEFAULT_DECAY (FL(0.99)) #define BABO_DEFAULT_HIDECAY (FL(0.1)) #define BABO_DEFAULT_RECV_X (FL(0.0)) #define BABO_DEFAULT_RECV_Y (FL(0.0)) #define BABO_DEFAULT_RECV_Z (FL(0.0)) #define BABO_DEFAULT_INTER_RECV_DISTANCE (FL(0.3)) #define BABO_DEFAULT_DIRECT (FL(0.5)) #define BABO_DEFAULT_DIFFUSE (FL(0.8)) #endif /* !defined(__babo_h__) */ csound-6.10.0/Opcodes/bbcut.c000066400000000000000000000434061321653344700157470ustar00rootroot00000000000000/* bbcut.c: Copyright (C) 2001 Nick Collins This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "interlocks.h" #include "bbcut.h" #include /* my auxilliary functions */ static inline int roundoffint(MYFLT x) { if (x > 0) return((int)(x + 0.500001)); /* in case of a close rounding error when x= 0.5 +- integer */ else return((int)(x - 0.5)); } static int random_number(CSOUND *csound, int a, int b) { MYFLT x; x = (MYFLT) (csound->Rand31(&(csound->randSeed1)) - 1) / FL(2147483645.0); return roundoffint((MYFLT) a + x * (MYFLT) (b - a)); } static MYFLT myfltrandom(CSOUND *csound, MYFLT a, MYFLT b) { MYFLT x; x = (MYFLT) (csound->Rand31(&(csound->randSeed1)) - 1) / FL(2147483645.0); return (a + x * (b - a)); } static int BBCutMonoInit(CSOUND *csound, BBCUTMONO *p) { /* call seed random at time now? */ /* later for efficiency- lookup table for grain envelope */ /* int i; */ /* MYFLT t; */ /* allocate space for a 256 point quarter sine/ exponential wavetable */ /* if (p->envbuffer.auxp == NULL) { */ /* csound->AuxAlloc(csound, 256*sizeof(MYFLT),&p->envbuffer); */ /* for (i=0;i<256;++i) { */ /* t= (PI*0.5*(MYFLT)i)/255.0; */ /* ((MYFLT*) (p->envbuffer.auxp))[i]=t; */ /* } */ /* } */ size_t M; /* A temporary */ /* have no knowledge of source length */ p->numbarsnow = 0; p->unitsdone = 0; p->totalunits = 0; p->unitblock = 0; p->repeats = 0; p->repeatsdone = 0; p->stutteron = 0; /* allocate space- need no more than a half bar at current tempo and barlength */ M = ((size_t)(CS_ESR*(*p->barlength)/(*p->bps)))*sizeof(MYFLT); if (p->repeatbuffer.auxp == NULL || p->repeatbuffer.sizeAuxAlloc(csound, M, &p->repeatbuffer); } p->repeatsampdone = 0; p->Subdiv = roundoffint(*p->subdiv); p->Phrasebars = roundoffint(*p->phrasebars); p->Numrepeats = roundoffint(*p->numrepeats); p->Stutterspeed = roundoffint(*p->stutterspeed); /* samp per unit= samp per bar/ subdiv */ /* = samp per beat * beats per bar /subdiv */ /* =(samp per sec / beats per sec)* (beats per bar/subdiv) */ p->samplesperunit = roundoffint(((MYFLT)CS_ESR*(FL(1.0)/(*p->bps)))* (*p->barlength/(MYFLT)p->Subdiv)); /* enveloping */ p->Envelopingon = roundoffint(*p->envelopingon); p->envsize = (p->Envelopingon) ? 64 : 0; return OK; } /* rounding errors will accumulate slowly with respect to bps, */ /* true tempo is determined by samplesperunit (which has been rounded off) */ /* only make floating point corrections for stutters with stutterspeed>1 */ static int BBCutMono(CSOUND *csound, BBCUTMONO *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; int oddmax,unitproj; int unitb,unitl,unitd; /* temp for integer unitblock calculations */ MYFLT envmult,out; /* intermedaites for enveloping grains */ if (UNLIKELY(offset)) memset(p->aout, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->aout[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset;iunitsdone+FL(0.000001))>=p->totalunits)) { /* a new phrase of cuts */ p->numbarsnow = random_number(csound, 1, p->Phrasebars); p->totalunits = p->numbarsnow*p->Subdiv; p->unitsdone = 0; p->unitsleft = (MYFLT)p->totalunits; /* must reset here */ p->repeats = 0; p->repeatsdone = 0; p->stutteron = 0; } if (p->repeatsdone>=p->repeats) { /* a new subphrase- a cut + some repeats of it */ p->repeatsdone = 0; /* STUTTER- only within half a bar of the end */ if (UNLIKELY((*p->stutterchance > myfltrandom(csound, FL(0.0), FL(1.0))) && (p->unitsleft<(p->Subdiv/2)))) { /* stutterspeed must be an integer greater than zero */ p->repeats = roundoffint(p->unitsleft*p->Stutterspeed); p->unitblock = FL(1.0)/(p->Stutterspeed); p->stutteron = 1; } else { /* NO STUTTER */ /* finding set of valid odd numbers for syncopated cuts */ /* integer division */ oddmax = p->Subdiv/2; if ((oddmax&1)==0) oddmax =(oddmax-2)/2; else oddmax = (oddmax-1)/2; unitb = random_number(csound, 0, oddmax); unitb = (2*unitb)+1; unitl = roundoffint(p->unitsleft); while (unitb> unitl) unitb = unitb-2; unitd = roundoffint(p->unitsdone); /* for debug testing */ /* if (unitblock<=0, {"this should never happen".postln}); */ /* p->repeats is the total number of repeats, including initial statement */ /* usually 1 or 2 */ p->repeats = random_number(csound, 1, p->Numrepeats + 1); /* take right arg as p->Numrepeats+1 if make param more sensible */ unitproj = (p->repeats*unitb)+ unitd; /* should be same logic as old algorithm for numrepeats=2 */ while (unitproj> p->totalunits) { p->repeats = p->repeats-1; if (p->repeats<=1) { p->repeats = 1; unitb = unitl; /* at this point is an integer */ } unitproj =(p->repeats*unitb)+ unitd; } /* convert integer to float */ p->unitblock = (MYFLT) unitb; } /* end of stutter/no stutter */ /* determine offset - this part is very different for the csound version */ /* there is no random access possible any more, only have now (and past) */ /* we must determine how long in samples a repeat is */ /* must persist between calls to this function */ p->repeatlengthsamp = roundoffint(p->unitblock*p->samplesperunit); p->repeatsampdone = 0; /* determine envelope size - default is always 0 if enveloping off, 128 if on; */ /* envsize must be at most a quarter of repeatsamplelength */ if ((p->Envelopingon) ==1) { if (p->repeatlengthsamp<256) { p->envsize = p->repeatlengthsamp/4; } } } /* AUDIO OUT */ if (p->repeatsdone==0) { out = p->ain[i]; /* pass in directly to out */ /* ENVELOPING */ envmult = FL(1.0); /* envelope in */ if (p->repeatsampdoneenvsize) { /* used sinusoid- prefer exponential */ /* envmult= sin(PI*0.5*(((MYFLT)(p->repeatsampdone))/(MYFLT)p->envsize)); */ envmult = (EXP((p->repeatsampdone)/(p->envsize))-FL(1.0))/ FL(1.7182818284590); } /* envelope out if necessary */ if (p->repeatsampdone>=(p->repeatlengthsamp-p->envsize)) { /* envmult = sin(PI*0.5* (((MYFLT)(p->repeatlengthsamp-p->repeatsampdone))/ (MYFLT)p->envsize)); */ envmult = (EXP(((p->repeatlengthsamp-p->repeatsampdone))/ (p->envsize))-FL(1.0))/ FL(1.7182818284590); } out *= envmult; /* /ENVELOPING DONE */ p->aout[i] = out; if (p->repeats>1) { /* if recording a repeat */ ((MYFLT*)(p->repeatbuffer.auxp))[p->repeatsampdone] = out; } } else { /* reading repeatbuffer for repeats */ p->aout[i] = ((MYFLT*)(p->repeatbuffer.auxp))[p->repeatsampdone]; } /* per sample accounting */ ++(p->repeatsampdone); /* if finished a cut, do accounting */ if (UNLIKELY(p->repeatsampdone>=p->repeatlengthsamp)) { ++(p->repeatsdone); p->repeatsampdone = 0; p->unitsdone = p->unitsdone + p->unitblock; p->unitsleft = p->totalunits - p->unitsdone; /* to account for floating point errors in unitblock when */ /* stuttering with stutterspeed > 1 */ if (UNLIKELY(p->stutteron && (p->repeatsdone==(p->repeats-1)))) { p->unitblock = p->unitsleft; } } } return OK; } /* Stereo versions */ /* This following code is excatly the same as above, but */ /* uses BBCUTSTEREO- changes are doubling of buffer size for interleaved stereo save and code in audio output part to cope with that, variables out1,out2 for 2 channels */ static int BBCutStereoInit(CSOUND *csound, BBCUTSTEREO * p) { /* call seed random at time now? */ /* later for efficiency- lookup table for grain envelope */ /* int i; */ /* MYFLT t; */ /* allocate space for a 256 point quarter sine/ exponential wavetable */ /* if (p->envbuffer.auxp == NULL) { */ /* csound->AuxAlloc(csound, ((int)(256*sizeof(MYFLT),&p->envbuffer); */ /* for (i=0;i<256;++i) */ /* { */ /* t= (PI*0.5*(MYFLT)i)/255.0; */ /* ((MYFLT*) (p->envbuffer.auxp))[i]=t; */ /* } */ /* } */ size_t M; /* temporary */ /* have no knowledge of source length */ p->numbarsnow = 0; p->unitsdone = 0; p->totalunits = 0; p->unitblock = 0; p->repeats = 0; p->repeatsdone = 0; p->stutteron = 0; /* allocate space- need no more than a half bar at current tempo and barlength */ M = 2*((size_t)(CS_ESR*(*p->barlength)/(*p->bps)))*sizeof(MYFLT); if (p->repeatbuffer.auxp == NULL || p->repeatbuffer.sizeAuxAlloc(csound, M, &p->repeatbuffer); } p->repeatsampdone = 0; p->Subdiv = roundoffint(*p->subdiv); p->Phrasebars = roundoffint(*p->phrasebars); p->Numrepeats = roundoffint(*p->numrepeats); p->Stutterspeed = roundoffint(*p->stutterspeed); /* samp per unit= samp per bar/ subdiv */ /* = samp per beat * beats per bar /subdiv */ /* =(samp per sec / beats per sec)* (beats per bar/subdiv) */ p->samplesperunit = roundoffint(((MYFLT)CS_ESR/ (*p->bps))*(*p->barlength/ (MYFLT)p->Subdiv)); /* enveloping */ p->Envelopingon = roundoffint(*p->envelopingon); p->envsize = (p->Envelopingon) ? 64 : 0; return OK; } /* rounding errors will accumulate slowly with respect to bps, */ /* true tempo is determined by samplesperunit (which has been rounded off) */ /* only make floating point corrections for stutters with stutterspeed>1 */ static int BBCutStereo(CSOUND *csound, BBCUTSTEREO *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; int oddmax,unitproj; int unitb,unitl,unitd; /* temp for integer unitblock calculations */ MYFLT envmult,out1,out2;/* intermediates for enveloping grains */ if (UNLIKELY(offset)) { memset(p->aout1, '\0', offset*sizeof(MYFLT)); memset(p->aout2, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&p->aout1[nsmps], '\0', early*sizeof(MYFLT)); memset(&p->aout2[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset;iunitsdone+FL(0.000001))>=p->totalunits)) { p->numbarsnow = random_number(csound, 1, p->Phrasebars); p->totalunits = p->numbarsnow*p->Subdiv; p->unitsdone = 0; p->unitsleft = (MYFLT)p->totalunits; /* must reset here */ p->repeats = 0; p->repeatsdone = 0; p->stutteron = 0; } if (UNLIKELY(p->repeatsdone>=p->repeats)) { /* a new subphrase- a cut + some repeats of it */ p->repeatsdone = 0; /* STUTTER- only within half a bar of the end */ if (UNLIKELY((*p->stutterchance > myfltrandom(csound, FL(0.0), FL(1.0))) && (p->unitsleft<(p->Subdiv/2)))) { /* stutterspeed must be an integer greater than zero */ p->repeats = roundoffint(p->unitsleft*p->Stutterspeed); p->unitblock = FL(1.0)/p->Stutterspeed; p->stutteron = 1; } else { /* NO STUTTER */ /* finding set of valid odd numbers for syncopated cuts */ /* integer division */ oddmax = p->Subdiv/2; if ((oddmax & 1)==0) oddmax = (oddmax-2)/2; else oddmax = (oddmax-1)/2; unitb = random_number(csound, 0, oddmax); unitb = (2*unitb)+1; unitl = roundoffint(p->unitsleft); while (unitb> unitl) unitb = unitb-2; unitd = roundoffint(p->unitsdone); /* for debug testing */ /* if (unitblock<=0, {"this should never happen".postln}); */ /* p->repeats is the total number of repeats, including initial statement */ /* usually 1 or 2 */ p->repeats = random_number(csound, 1, p->Numrepeats + 1); /* take right arg as p->Numrepeats+1 if make param more sensible */ unitproj = (p->repeats*unitb)+ unitd; /* should be same logic as old algorithm for numrepeats=2 */ while (unitproj> p->totalunits) { p->repeats = p->repeats-1; if (p->repeats<=1) { p->repeats = 1; unitb = unitl; /* at this point is an integer */ } unitproj = (p->repeats*unitb)+ unitd; } /* convert integer to float */ p->unitblock = (MYFLT) unitb; } /* end of stutter/no stutter */ /* determine offset- this part is very different for the csound version */ /* there is no random access possible any more, only have now (and past) */ /* we must determine how long in samples a repeat is */ /* must persist between calls to this function */ p->repeatlengthsamp = roundoffint(p->unitblock*p->samplesperunit); p->repeatsampdone = 0; /* determine envelope size- default is always 0 if enveloping off, 128 if on; */ /* envsize must be at most a quarter of repeatsamplelength */ if (p->Envelopingon ==1) { if (p->repeatlengthsamp<256) { p->envsize = p->repeatlengthsamp/4; } } } /* AUDIO OUT- some changes for buffer access */ if (p->repeatsdone == 0) { out1 = p->ain1[i]; /* pass in directly to out */ out2 = p->ain2[i]; /* ENVELOPING */ envmult = FL(1.0); /* envelope in */ if (p->repeatsampdoneenvsize) { /* used sinusoid- prefer exponential */ /* envmult = sin(PI*0.5*(((MYFLT)(p->repeatsampdone))/ (MYFLT)p->envsize)); */ envmult = (EXP((p->repeatsampdone)/ (p->envsize))- FL(1.0))/FL(1.7182818284590); } /* envelope out if necessary */ if (p->repeatsampdone>=(p->repeatlengthsamp-p->envsize)) { /* envmult = sin(PI*0.5*(((MYFLT)(p->repeatlengthsamp-p->repeatsampdone))/ (MYFLT)p->envsize)); */ envmult = (EXP(((p->repeatlengthsamp- p->repeatsampdone))/ (p->envsize))-FL(1.0))/ FL(1.7182818284590); } out1 *= envmult; out2 *= envmult; /* /ENVELOPING DONE */ p->aout1[i] = out1; p->aout2[i] = out2; if (p->repeats>1) { /* if recording a repeat */ /* STEREO INTERLEAVED */ ((MYFLT*)(p->repeatbuffer.auxp))[2*p->repeatsampdone] = out1; ((MYFLT*)(p->repeatbuffer.auxp))[2*p->repeatsampdone+1] = out2; } } else { /* reading repeatbuffer for repeats */ p->aout1[i] = ((MYFLT*)(p->repeatbuffer.auxp))[2*p->repeatsampdone]; p->aout2[i] = ((MYFLT*)(p->repeatbuffer.auxp))[2*p->repeatsampdone+1]; } /* per sample accounting */ ++(p->repeatsampdone); /* if finished a cut, do accounting */ if (p->repeatsampdone>=p->repeatlengthsamp) { ++(p->repeatsdone); p->repeatsampdone = 0; p->unitsdone = p->unitsdone+ p->unitblock; p->unitsleft = p->totalunits- p->unitsdone; /* to account for floating point errors in unitblock when */ /* stuttering with stutterspeed > 1 */ if (p->stutteron && (p->repeatsdone== (p->repeats-1))) { p->unitblock = p->unitsleft; } } } return OK; } #define S(x) sizeof(x) static OENTRY localops[] = { { "bbcutm",S(BBCUTMONO), 0, 5, "a","aiiiiipop", (SUBR)BBCutMonoInit, NULL, (SUBR)BBCutMono }, { "bbcuts",S(BBCUTSTEREO), 0, 5, "aa","aaiiiiipop", (SUBR)BBCutStereoInit, NULL, (SUBR)BBCutStereo} }; int bbcut_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/bbcut.h000066400000000000000000000076141321653344700157550ustar00rootroot00000000000000/* bbcut.h: Copyright (C) 2001 Nick Collins This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* mono and stereo automatic audio cutters */ /* mono version Nick Collins Aug 2 2001 */ /* added stereo Aug 10 2001 */ /* based on SuperCollider classes, latest Breakbeat5 available from http://www.axp.mdx.ac.uk/~nicholas15/ at time of writing some corrections for realtime audio, removal of random offset chance, panning of cuts and rest chance */ /* cmono audio in, i bps, subdiv,barlength,phrasebars,numrepeats, */ /* (optionals) p stutterspeed (defaulting to 1), o stutterchance (defaulting to 0=off), enveloping choice (defaulting to 1=on) */ #if !defined(__bbcut_h__) # define __bbcut_h__ /* Csound ugen struct- can't use same struct for Mono and Stereo version */ typedef struct { OPDS h; /* defined in cs.h */ /*inputs and outputs */ /* output first */ MYFLT *aout; /* inputs in order */ /* a rate */ MYFLT *ain; /* i rate */ MYFLT *bps; MYFLT *subdiv; MYFLT *barlength; /* in beats */ MYFLT *phrasebars; MYFLT *numrepeats; /* optionals */ MYFLT *stutterspeed; /* default 1 */ MYFLT *stutterchance; /* default 0 */ MYFLT *envelopingon; /* default 1 */ /* integer values */ int Subdiv,Phrasebars,Numrepeats; int Stutterspeed; /* internal data */ /* unsigned long int sampdone; */ int samplesperunit; int repeatlengthsamp; int repeatsampdone; int numbarsnow; /* unitblock can be a float if stutterspeed greater than 1 */ MYFLT unitblock,unitsleft,unitsdone; int totalunits; int repeats,repeatsdone; int stutteron; /* enveloping */ int Envelopingon,envsize; /* to hold repeat data */ AUXCH repeatbuffer; } BBCUTMONO; /* STEREO VERSION */ typedef struct { OPDS h; /* defined in cs.h*/ /* inputs and outputs */ /* output first- stereo */ MYFLT *aout1; MYFLT *aout2; /* inputs in order */ /* arate, stereo ins */ MYFLT *ain1; MYFLT *ain2; /* i rate */ MYFLT *bps; MYFLT *subdiv; MYFLT *barlength; /* in beats */ MYFLT *phrasebars; MYFLT *numrepeats; /* optionals */ MYFLT *stutterspeed; /* default 1 */ MYFLT *stutterchance; /* default 0 */ MYFLT *envelopingon; /* default 1 */ /* integer values */ int Subdiv,Phrasebars,Numrepeats; int Stutterspeed; /* internal data */ /* unsigned long int sampdone; */ int samplesperunit; int repeatlengthsamp; int repeatsampdone; int numbarsnow; /* unitblock can be a float if stutterspeed greater than 1 */ MYFLT unitblock,unitsleft,unitsdone; int totalunits; int repeats,repeatsdone; int stutteron; /* enveloping */ int Envelopingon,envsize; /* to hold repeat data- interleaved stereo buffer, twice size for mono version */ AUXCH repeatbuffer; } BBCUTSTEREO; #endif /* !defined(__bbcut_h__) */ csound-6.10.0/Opcodes/bilbar.c000066400000000000000000000500231321653344700160740ustar00rootroot00000000000000/* bilbar.c: Copyright (C) 2006 by Stefan Bilbao and John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ //#include "csdl.h" #include "csoundCore.h" #include /* %% bar sound synthesis translated from Mathlab and much changed */ /* Note: position of strike along bar (0 - 1), normalized strike velocity, and spatial width of strike. */ typedef struct { OPDS h; MYFLT *ar; /* Output */ MYFLT *kbcL, *kbcR, *iK, *ib, *kscan, *iT30; MYFLT *ipos, *ivel, *iwid; double *w, *w1, *w2; int step, first; double s0, s1, s2, t0, t1; int bcL, bcR, N; AUXCH w_aux; } BAR; static int bar_init(CSOUND *csound, BAR *p) { if (*p->iK >= FL(0.0) || p->w_aux.auxp == NULL) { double K = FABS(*p->iK); /* ~=3.0 stiffness parameter, dimensionless */ double T30 = *p->iT30; /* ~=5.0; 30 db decay time (s) */ double b = *p->ib; /* ~=0.001 high-frequency loss parameter (keep small) */ /* %%%%%%%%%%%%%%%%%% derived parameters */ double dt = (double)csound->onedsr; double sig = (2.0*(double)CS_ESR)*(pow(10.0,3.0*dt/T30)-1.0); double dxmin = sqrt(dt*(b+hypot(b, K+K))); int N = (int) (1.0/dxmin); double dx = 1.0/N; /* %%%%%%%%%%%%%%%%%%% scheme coefficients */ p->s0 = (2.0-6.0*K*K*dt*dt/(dx*dx*dx*dx)-2.0*b*dt/(dx*dx))/(1.0+sig*dt*0.5); p->s1 = (4.0*K*K*dt*dt/(dx*dx*dx*dx)+b*dt/(dx*dx))/(1.0+sig*dt*0.5); p->s2 = -K*K*dt*dt/((dx*dx*dx*dx)*(1.0+sig*dt*0.5)); p->t0 = (-1.0+2.0*b*dt/(dx*dx)+sig*dt*0.5)/(1.0+sig*dt*0.5); p->t1 = (-b*dt)/(dx*dx*(1.0+sig*dt*0.5)); /* csound->Message(csound,"Scheme: %f %f %f ; %f %f\n", p->s0, p->s1, p->s2, p->t0, p->t1); */ /* %%%%%%%%%%%%%%%%%%%%% create grid functions */ csound->AuxAlloc(csound, (size_t)3*((N+5)*sizeof(double)), &(p->w_aux)); p->w = (double *) p->w_aux.auxp; p->w1 = &(p->w[N + 5]); p->w2 = &(p->w1[N + 5]); p->step = p->first = 0; p->N = N; } /* else { if (UNLIKELY(p->w_aux.auxp == NULL)) return csound->InitError(csound, Str("No data to continue")); } */ p->first = 0; return OK; } static int bar_run(CSOUND *csound, BAR *p) { double xofreq = TWOPI* (*p->kscan)/CS_ESR; /* kspan ~=0.23; */ double xo, xofrac; int xoint; int step = p->step; int first = p->first; int N = p->N, rr; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; double *w = p->w, *w1 = p->w1, *w2 = p->w2; double s0 = p->s0, s1 = p->s1, s2 = p->s2, t0 = p->t0, t1 = p->t1; int bcL = (int)MYFLT2LONG(*p->kbcL); /* boundary condition pair */ int bcR = (int)MYFLT2LONG(*p->kbcR); /* 1: clamped, 2: pivoting, 3: free */ double SINNW = sin(xofreq*step); /* these are to calculate sin/cos by */ double COSNW = cos(xofreq*step); /* formula rather than many calls */ double SIN1W = sin(xofreq); /* Wins in ksmps>4 */ double COS1W = cos(xofreq); MYFLT *ar = p->ar; if (UNLIKELY((bcL|bcR)&(~3) && (bcL|bcR)!=0)) return csound->PerfError(csound, p->h.insdshead, Str("Ends must be clamped(1), " "pivoting(2) or free(3)")); if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { /* Fix ends */ if (bcL == 3) { w1[1] = 2.0*w1[2]-w1[3]; w1[0] = 3.0*w1[1]-3.0*w1[2]+w1[3]; } else if (bcL == 1) { w1[2] = 0.0; w1[3] = 0.0; } else if (bcL == 2) { w1[2] = 0.0; w1[1] = -w1[3]; } if (bcR == 3) { w1[N+3] = 2.0*w1[N+2]-w1[N+1]; w1[N+4] = 3.0*w1[N+3]-3.0*w1[N+2]+w1[N+1]; } else if (bcR == 1) { w1[N+1] = 0.0; w1[N+2] = 0.0; } else if (bcR == 2) { w1[N+2] = 0.0; w1[N+3] = -w1[N+1]; } /* Iterate model */ for (rr = 0; rr < N+1; rr++) { /* Is N+1 correct here?? */ w[rr+2] = s0*w1[rr+2] + s1*(w1[rr+3]+w1[rr+1]) + s2*(w1[rr+4]+w1[rr]) + t0*w2[rr+2] + t1*(w2[rr+3]+w2[rr+1]); } /* strike inputs */ if (first == 0) { p->first = first = 1; for (rr = 0; rr < N; rr++) { if (fabs(rr/(double)N - *p->ipos) <= *p->iwid) { w[rr+2] += (1.0/CS_ESR)*(*p->ivel)*0.5* (1.0+cos(PI*fabs(rr/(double)N-(*p->ipos))/(*p->iwid))); } } } /* readouts */ /* xo = (1.0/3.0) + 0.5*sin(TWOPI*xofreq*(step+1)/CS_ESR); */ /* sin((N+1)w) = sin(Nw)cos(w) + cos(Nw)sin(w) */ /* cos((N+1)w) = cos(Nw)cos(w) - sin(Nw)sin(w) */ /* so can calculate sin on next line by iteration at less cost */ /* But is xofreq were to change could be difficult! */ /* xo = 0.5 + 0.5*sin(TWOPI*xofreq*(step+1)/CS_ESR); */ { double xx = SINNW*COS1W + COSNW*SIN1W; double yy = COSNW*COS1W - SINNW*SIN1W; SINNW = xx; COSNW = yy; } xo = 0.5 + 0.5*SINNW; xoint = (int) (xo*N) + 2; xofrac = xo*N - (int)(xo*N); /* csound->Message(csound, "xo = %f (%d %f) w=(%f,%f) ", xo, xoint, xofrac, w[xoint], w[xoint+1]); */ ar[n] = (csound->e0dbfs)*((1.0-xofrac)*w[xoint] + xofrac*w[xoint+1]); step++; { double *ww = w2; w2 = w1; w1 = w; w = ww; } } p->step = step; p->w = w; p->w1 = w1; p->w2 = w2; return OK; } /* Prepared Piano string */ typedef struct { double pos; /* position along string of rattle */ double massden; /* mass density ratio (rattle/string) */ double freq; /* fundamental freq. of rattle */ double length; /* vertical length of rattle */ } RATTLE; typedef struct { double pos; /* position along string of rubber */ double massden; /* mass density ratio (rubber/string) */ double freq; /* fundamental freq. of rubber */ double loss; /* loss parameter of rubber */ } RUBBER; typedef struct { OPDS h; MYFLT *ar; MYFLT *ar1; MYFLT *ifreq; MYFLT *iNS; /* number of strings */ MYFLT *iD; /* detune parameter (multiple strings) in cents!!! */ MYFLT *K; /* stiffness parameter, dimensionless...set around 1 for low notes, set closer to 100 in high register */ MYFLT *iT30; /* 30 db decay time (s) */ MYFLT *ib; /* high-frequency loss parameter (keep this small) */ MYFLT *kbcl,*kbcr; /* Boundary conditions */ MYFLT *ham_massden, *ham_freq, *ham_initial; MYFLT *ipos; MYFLT *vel; MYFLT *scanfreq, *scanspread; MYFLT *rattle_tab, *rubber_tab; MYFLT *w, *w1, *w2; MYFLT *rat, *rat1, *rat2; MYFLT *rub, *rub1, *rub2; MYFLT *s0, *s1, s2, t0, t1; MYFLT *hammer_force; int stereo; uint32_t NS; int N, init, step; uint32_t rattle_num, rubber_num; int hammer_index, hammer_on, hammer_contact; MYFLT ham, ham1, ham2; AUXCH auxch; RATTLE *rattle; RUBBER *rubber; } CSPP; int init_pp(CSOUND *csound, CSPP *p) { if (*p->K >= FL(0.0)) { double K = *p->K; /* stiffness parameter, dimensionless */ double f0 = *p->ifreq; /* fundamental freq. (Hz) */ double T30 = *p->iT30; /* 30 db decay time (s) */ double b = *p->ib; /* high-frequency loss parameter (keep small) */ uint32_t NS = p->NS = (int)*p->iNS; /* number of strings */ double D = *p->iD; /* detune parameter (multiple strings) in cents */ /* I.e., a total of D cents diff between highest */ /* and lowest string in set */ /* initialize prepared objects and hammer */ /* derived parameters */ double dt = (double)csound->onedsr; double sig = (2.0*(double)CS_ESR)*(pow(10.0,3.0*dt/T30)-1.0); uint32_t N, n; double *c, /*dx,*/ dxmin = 0.0; /* for stability */ FUNC *ftp; csound->AuxAlloc(csound, NS*sizeof(double), &p->auxch); c = (double *)p->auxch.auxp; if (*p->rattle_tab==FL(0.0) || (ftp=csound->FTnp2Find(csound, p->rattle_tab)) == NULL) p->rattle_num = 0; else { p->rattle_num = (uint32_t)(*ftp->ftable); p->rattle = (RATTLE*)(&((MYFLT*)ftp->ftable)[1]); } if (*p->rubber_tab==FL(0.0) || (ftp=csound->FTnp2Find(csound, p->rubber_tab)) == NULL) p->rubber_num = 0; else { p->rubber_num = (uint32_t)(*ftp->ftable); p->rubber = (RUBBER*)(&((MYFLT*)ftp->ftable)[1]); } for (n=0; ndxmin) dxmin = x; } N = p->N = (uint32_t)(1.0/dxmin); //dx = 1.0/(double)N; csound->AuxAlloc(csound, 3*((1+(N+5))*NS+p->rattle_num+p->rubber_num)*sizeof(MYFLT), &p->auxch); p->s0 = (MYFLT*)p->auxch.auxp; p->s1 = &p->s0[NS]; p->hammer_force = &p->s1[NS]; for (n=0; ns0[n] = (2.0-6.0*K*K*dt*dt*N*N*N*N-2.0*b*dt*N*N- 2.0*c[n]*c[n]*dt*dt*N*N)/(1.0+sig*dt*0.5); p->s1[n] = (4*K*K*dt*dt*N*N*N*N+b*dt*N*N+ c[n]*c[n]*dt*dt*N*N)/(1.0+sig*dt*0.5); /* Above optimises to this */ /* g9 = N*N*dt; */ /* g15 = g9*K; */ /* g8 = g15*g15; */ /* g13 = g9*c[n]*c[n]*dt + g9*b; */ /* g6 = 0.5 * dt*sig + 1.0; */ /* p->s0[n] = (2.0*(1.0 - g13 - 3.0*g8))/g6; */ /* p->s1[n] = (g13 + 4.0*g8)/g4; */ } p->s2 = -K*K*dt*dt*N*N*N*N/(1.0+sig*dt*0.5); p->t0 = (-1.0+2.0*b*dt*N*N+sig*dt*0.5)/(1.0+sig*dt*0.5); p->t1 = (-b*dt)*N*N/(1.0+sig*dt*0.5); /* note, each of these is an array, of size N+5 by NS...i.e., need a separate N+5 element array per string. */ p->w = &p->hammer_force[NS]; p->w1 = &p->w[(N+5)*NS]; p->w2 = &p->w1[(N+5)*NS]; p->rat = &p->w2[(N+5)*NS]; p->rat1 = &p->rat[p->rattle_num]; p->rat2 = &p->rat1[p->rattle_num]; p->rub = &p->rat2[p->rattle_num]; p->rub1 = &p->rub[p->rubber_num]; p->rub2 = &p->rub1[p->rubber_num]; p->ham = 0; p->ham1 = 0; p->ham2 = 0; /*only one hammer */ p->step = 0; } p->init = 1; /* So we start the hammer */ if (p->OUTOCOUNT==1) p->stereo = 0; else p->stereo = 1; return OK; } int play_pp(CSOUND *csound, CSPP *p) { MYFLT *ar = p->ar; MYFLT *ar1 = p->ar1; uint32_t NS = p->NS; uint32_t N = p->N; int step = p->step; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t t, n, nsmps = CS_KSMPS; double dt = csound->onedsr; MYFLT *w = p->w, *w1 = p->w1, *w2 = p->w2, *rub = p->rub, *rub1 = p->rub1, *rub2 = p->rub2, *rat = p->rat, *rat1 = p->rat1, *rat2 = p->rat2; MYFLT *s0 = p->s0, *s1 = p->s1, s2 = p->s2, t0 = p->t0, t1 = p->t1; double SINNW = 0; /* these are to calculate sin/cos by */ double COSNW = 0; /* formula rather than many calls */ double SIN1W = 0; /* Wins in ksmps>4 */ double COS1W = 0; double SINNW2 = 0; double COSNW2 = 0; double SIN1W2 = 0; double COS1W2 = 0; if (p->stereo) { double f1 = (*p->scanfreq - FL(0.5)* *p->scanspread)/CS_ESR; double f2 = (*p->scanfreq + FL(0.5)* *p->scanspread)/CS_ESR; SINNW = sin(f1*TWOPI*step); /* these are to calculate sin/cos by */ COSNW = cos(f1*TWOPI*step); /* formula rather than many calls */ SIN1W = sin(f1*TWOPI); /* Wins in ksmps>4 */ COS1W = cos(f1*TWOPI); SINNW2 = sin(f2*TWOPI*step); COSNW2 = cos(f2*TWOPI*step); SIN1W2 = sin(f2*TWOPI); COS1W2 = cos(f2*TWOPI); } else { double f1 = *p->scanfreq/CS_ESR; SINNW = sin(f1*TWOPI*step); /* these are to calculate sin/cos by */ COSNW = cos(f1*TWOPI*step); /* formula rather than many calls */ SIN1W = sin(f1*TWOPI); /* Wins in ksmps>4 */ COS1W = cos(f1*TWOPI); } if (p->init) { p->hammer_on = 1; /* turns on hammer updating */ p->hammer_contact = 0; /* hammer not in contact with string yet */ p->hammer_index = 2+(int)(*p->ipos*N); /* find location of hammer strike */ p->ham2 = *p->ham_initial; p->ham1 = *p->ham_initial+dt*(*p->vel); /* initialize hammer */ p->init = 0; } if (UNLIKELY(offset)) { memset(ar, '\0', offset*sizeof(MYFLT)); if (p->stereo) memset(ar1, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); if (p->stereo) memset(&ar1[nsmps], '\0', early*sizeof(MYFLT)); } for (t=offset; thammer_force[n] = 0.0; /* set boundary conditions on last state w1 */ if ((int)*p->kbcl==1) { for (n=0; nkbcl==2) { for (qq=0; qqkbcr==1) { for (n=0; nkbcr==2) { for (n=0; nrattle_num) /* do this only if at least one rattle is specified */ for (qq=0; qqrattle_num; qq++) { int rattle_index = (int)(2+p->rattle[qq].pos*N); for (n=0; nrattle[qq].length*0.5; /* calc force (nonzero only when in contact) */ force = 0.5*(temp+fabs(temp))*(pos>0?1.0:-1.0); if (force!=0.0) { w[rattle_index*NS+n] += -dt*dt*(TWOPI*p->rattle[qq].freq)* (TWOPI*p->rattle[qq].freq)*p->rattle[qq].massden*force; } rat[qq] = 2*rat1[qq]-rat2[qq]+(TWOPI*p->rattle[qq].freq)* (TWOPI*p->rattle[qq].freq)*dt*dt*force-dt*dt*9.8; rat2[qq] = rat1[qq]; rat1[qq] = rat[qq]; } } if (p->rubber_num) { /* do this only if at least one rubber is specified */ for (qq=0; qqrubber_num; qq++) { int rubber_index = (int)(2+p->rubber[0].pos*N); MYFLT force = 0.0; for (n=0; nrubber[qq].freq)* (TWOPI*p->rubber[qq].freq)*p->rubber[qq].massden*force; rub[qq] = 2*rub1[qq]/(1+p->rubber[qq].loss*dt/2)- (1-p->rubber[qq].loss*dt/2)*rub2[qq]/(1+p->rubber[qq].loss*dt*0.5)+ (TWOPI*p->rubber[qq].freq)*(TWOPI*p->rubber[qq].freq)* dt*dt*(-rub1[qq]+force)/(1+p->rubber[qq].loss*dt*0.5); rub2[qq] = rub1[qq]; rub1[qq] = rub[qq]; } } } if (p->hammer_on) { MYFLT min_pos = 100; MYFLT hammer_force_sum = 0.0; /* do this while a strike is occurring */ for (qq=0; qqhammer_index*NS+qq]-p->ham1; if (pos>0.0) pos = 0.0; if (poshammer_contact = 1; p->hammer_force[qq] = -pos*pos*pos; hammer_force_sum += p->hammer_force[qq]; } /* if (min_pos<0.0) p->hammer_contact = 1; */ if (p->hammer_contact && min_pos>=0.0) { /* if hammer has been in contact, but now no longer is, turn off */ /* hammer updating */ p->hammer_on = p->hammer_contact=0; } p->ham = 2.0*p->ham1-p->ham2-dt*dt*hammer_force_sum* (TWOPI*(*p->ham_freq))*(TWOPI*(*p->ham_freq)); p->ham2 = p->ham1; p->ham1 = p->ham; for (qq=0; qqhammer_index*NS+qq] += dt*dt*(*p->ham_massden)* (TWOPI*(*p->ham_freq))*(TWOPI*(*p->ham_freq))*p->hammer_force[qq]; } { #define xoamp FL(0.3333) #define xoctr FL(0.3333) int xoint; MYFLT xofrac, xo; MYFLT out = 0.0; double xx = SINNW*COS1W + COSNW*SIN1W; double yy = COSNW*COS1W - SINNW*SIN1W; SINNW = xx; COSNW = yy; xo = xoctr + xoamp*SINNW; /* xo = xoctr+xoamp*(MYFLT)sin(TWOPI*(*p->scanfreq)*n*dt); */ xoint = (int)(xo*N)+2; xofrac = xo*N - xoint + FL(2.0); for (qq=0; qqe0dbfs; if (p->stereo) { /* Need to deal with stereo version here */ xx = SINNW2*COS1W2 + COSNW2*SIN1W2; yy = COSNW2*COS1W2 - SINNW2*SIN1W2; xo = xoctr + xoamp*SINNW2; /* xo = xoctr+xoamp*(MYFLT)sin(TWOPI*(*p->scanfreq)*n*dt); */ xoint = (int)(xo*N)+2; xofrac = xo*N - xoint + FL(2.0); for (qq=0; qqe0dbfs; SINNW2 = xx; COSNW2 = yy; } step++; } { uint32_t i; void *w3 = w2; w2 = w1; w1 = w; w = w3; for (i=0; iw = w; p->w1 = w1; p->w2 = w2; p->rub = rub; p->rub1 = rub1; p->rub2 = rub2; p->rat = rat; p->rat1 = rat1; p->rat2 = rat2; p->step = step; return OK; } #define S(x) sizeof(x) static OENTRY bilbar_localops[] = { {"barmodel", S(BAR), 0, 5, "a", "kkiikiiii", (SUBR) bar_init, NULL, (SUBR) bar_run}, { "prepiano", S(CSPP), 0, 5, "mm", "iiiiiikkiiiiiiioo", ( SUBR)init_pp, NULL, (SUBR)play_pp }, }; LINKAGE_BUILTIN(bilbar_localops) csound-6.10.0/Opcodes/biquad.c000066400000000000000000001502441321653344700161140ustar00rootroot00000000000000/* biquad.c: Copyright (C) 1998, 1999, 2001 by Hans Mikelson, Matt Gerassimoff, Jens Groh, John ffitch, Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /***************************************************************/ /* biquad, moogvcf, rezzy */ /* Biquadratic digital filter with K-Rate coeff. */ /* Moog VCF Simulation by Comajuncosas/Stilson/Smith */ /* Rezzy Filter by Hans Mikelson */ /* Nested allpass and Lorenz added */ /* October 1998 by Hans Mikelson */ /***************************************************************/ //#include "csdl.h" #include #include "biquad.h" #include "csound_standard_types.h" /***************************************************************************/ /* The biquadratic filter computes the digital filter two x components and */ /* two y values. */ /* Coded by Hans Mikelson October 1998 */ /***************************************************************************/ static int biquadset(CSOUND *csound, BIQUAD *p) { /* The biquadratic filter is initialised to zero. */ if (*p->reinit==FL(0.0)) { /* Only reset in in non-legato mode */ p->xnm1 = p->xnm2 = p->ynm1 = p->ynm2 = 0.0; } return OK; } /* end biquadset(p) */ static int biquad(CSOUND *csound, BIQUAD *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; double xn, yn; double xnm1 = p->xnm1, xnm2 = p->xnm2, ynm1 = p->ynm1, ynm2 = p->ynm2; double a0 = 1.0 / *p->a0, a1 = a0 * *p->a1, a2 = a0 * *p->a2; double b0 = a0 * *p->b0, b1 = a0 * *p->b1, b2 = a0 * *p->b2; if (UNLIKELY(offset)) memset(p->out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nin[n]; yn = b0*xn + b1*xnm1 + b2*xnm2 - a1*ynm1 - a2*ynm2; xnm2 = xnm1; xnm1 = xn; ynm2 = ynm1; ynm1 = yn; p->out[n] = (MYFLT)yn; } p->xnm1 = xnm1; p->xnm2 = xnm2; p->ynm1 = ynm1; p->ynm2 = ynm2; return OK; } /* A-rate version of above -- JPff August 2001 */ static int biquada(CSOUND *csound, BIQUAD *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *out, *in; double xn, yn; MYFLT *a0 = p->a0, *a1 = p->a1, *a2 = p->a2; MYFLT *b0 = p->b0, *b1 = p->b1, *b2 = p->b2; double xnm1 = p->xnm1, xnm2 = p->xnm2, ynm1 = p->ynm1, ynm2 = p->ynm2; in = p->in; out = p->out; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nxnm1 = xnm1; p->xnm2 = xnm2; p->ynm1 = ynm1; p->ynm2 = ynm2; return OK; } /***************************************************************************/ /* begin MoogVCF by Stilson & Smith of CCRMA, *****************************/ /* translated to Csound by Josep Comajuncosas, *****************************/ /* translated to C by Hans Mikelson *****************************/ /***************************************************************************/ static int moogvcfset(CSOUND *csound, MOOGVCF *p) { if (*p->iskip==FL(0.0)) { p->xnm1 = p->y1nm1 = p->y2nm1 = p->y3nm1 = 0.0; p->y1n = p->y2n = p->y3n = p->y4n = 0.0; } p->fcocod = IS_ASIG_ARG(p->fco) ? 1 : 0; p->rezcod = IS_ASIG_ARG(p->res) ? 1 : 0; if ((p->maxint = *p->max)==FL(0.0)) p->maxint = csound->e0dbfs; return OK; } static int moogvcf(CSOUND *csound, MOOGVCF *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *out, *in; double xn; MYFLT *fcoptr, *resptr; /* Fake initialisations to stop compiler warnings!! */ double fco, res, kp=0.0, pp1d2=0.0, scale=0.0, k=0.0; double max = (double)p->maxint; double dmax = 1.0/max; double xnm1 = p->xnm1, y1nm1 = p->y1nm1, y2nm1 = p->y2nm1, y3nm1 = p->y3nm1; double y1n = p->y1n, y2n = p->y2n, y3n = p->y3n, y4n = p->y4n; MYFLT zerodb = csound->e0dbfs; in = p->in; out = p->out; fcoptr = p->fco; resptr = p->res; fco = (double)*fcoptr; res = (double)*resptr; /* Only need to calculate once */ if (UNLIKELY((p->rezcod==0) && (p->fcocod==0))) { double fcon; fcon = 2.0*fco*(double)csound->onedsr; /* normalised freq. 0 to Nyquist */ kp = 3.6*fcon-1.6*fcon*fcon-1.0; /* Emperical tuning */ pp1d2 = (kp+1.0)*0.5; /* Timesaver */ scale = exp((1.0-pp1d2)*1.386249); /* Scaling factor */ k = res*scale; } if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nfcocod) { fco = (double)fcoptr[n]; } if (p->rezcod) { res = (double)resptr[n]; } if ((p->rezcod!=0) || (p->fcocod!=0)) { double fcon; fcon = 2.0*fco*(double)csound->onedsr; /* normalised frq. 0 to Nyquist */ kp = 3.6*fcon-1.6*fcon*fcon-1.0; /* Emperical tuning */ pp1d2 = (kp+1.0)*0.5; /* Timesaver */ scale = exp((1.0-pp1d2)*1.386249); /* Scaling factor */ k = res*scale; } xn = (double)in[n] * dmax/zerodb; xn = xn - k * y4n; /* Inverted feed back for corner peaking */ /* Four cascaded onepole filters (bilinear transform) */ /* y1n = xn * pp1d2 + xnm1 * pp1d2 - kp * y1n; */ /* y2n = y1n * pp1d2 + y1nm1 * pp1d2 - kp * y2n; */ /* y3n = y2n * pp1d2 + y2nm1 * pp1d2 - kp * y3n; */ /* y4n = y3n * pp1d2 + y3nm1 * pp1d2 - kp * y4n; */ /* why not */ y1n = (xn + xnm1 ) * pp1d2 - kp * y1n; y2n = (y1n + y1nm1) * pp1d2 - kp * y2n; y3n = (y2n + y2nm1) * pp1d2 - kp * y3n; y4n = (y3n + y3nm1) * pp1d2 - kp * y4n; /* ?? Algebraically the same and 4 fewer multiplies per sample. */ /* Clipper band limited sigmoid */ y4n = y4n - y4n * y4n * y4n / 6.0; xnm1 = xn; /* Update Xn-1 */ y1nm1 = y1n; /* Update Y1n-1 */ y2nm1 = y2n; /* Update Y2n-1 */ y3nm1 = y3n; /* Update Y3n-1 */ out[n] = (MYFLT)(y4n * max * zerodb); } p->xnm1 = xnm1; p->y1nm1 = y1nm1; p->y2nm1 = y2nm1; p->y3nm1 = y3nm1; p->y1n = y1n; p->y2n = y2n; p->y3n = y3n; p->y4n = y4n; return OK; } /***************************************************************/ /* This filter is the Mikelson low pass resonant 2-pole filter */ /* Coded by Hans Mikelson October 1998 */ /***************************************************************/ static int rezzyset(CSOUND *csound, REZZY *p) { if (*p->iskip==FL(0.0)) { p->xnm1 = p->xnm2 = p->ynm1 = p->ynm2 = 0.0; /* Initialize to zero */ } p->fcocod = IS_ASIG_ARG(p->fco) ? 1 : 0; p->rezcod = IS_ASIG_ARG(p->rez) ? 1 : 0; p->warn = 1; return OK; } /* end rezzyset(p) */ #define NEARONE (0.99999) static int rezzy(CSOUND *csound, REZZY *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *out, *fcoptr, *rezptr, *in; double fco, rez, xn, yn; double fqcadj, a=0.0, /* Initialisations fake */ csq=0.0, invb=0.0, tval=0.0; /* Temporary variables for the filter */ double xnm1 = p->xnm1, xnm2 = p->xnm2, ynm1 = p->ynm1, ynm2 = p->ynm2; double b1 = 0.0, b2 = 0.0; int warn = p->warn; in = p->in; out = p->out; fcoptr = p->fco; rezptr = p->rez; fco = (double)*fcoptr; rez = (double)*rezptr; /* Freq. is adjusted based on sample rate */ fqcadj = 0.149659863*(double)CS_ESR; /* Try to keep the resonance under control */ if (rez < 1.0) rez = 1.0; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } if (*p->mode == FL(0.0)) { /* Low Pass */ if (UNLIKELY((p->rezcod==0) && (p->fcocod==0))) { /* Only need to calculate once */ double c = fqcadj/fco; /* Filter constant c=1/Fco * adjustment */ double rez2 = rez/(1.0 + exp(fco/11000.0)); double b; a = c/rez2 - 1.0; /* a depends on both Fco and Rez */ csq = c*c; /* Precalculate c^2 */ b = 1.0 + a + csq; /* Normalization constant */ invb = 1.0/b; b1 = (-a-2.0*csq)*invb; b2 = csq*invb; // Stabalise { // POLES //Note that csq cannot be zero double p0, p1, pi, disc; disc=b1*b1-(4*b2); if (disc<0.0) { pi = sqrt(-disc)/2.0; p0 = p1 = (-b1)/2.0; if (p0*p0+pi*pi>=1.0) { double theta = atan2(pi, p0); if (warn) csound->Warning(csound, Str("rezzy instability corrected")); p0 = NEARONE * cos(theta); //pi = NEARONE * sin(theta); b1 = -2*p0; b2 = NEARONE*NEARONE; warn = 0; } } else { pi = 0; p0=(sqrt(disc)-b1)/2.0; p1=(-sqrt(disc)-b1)/2.0; if (p0*p0>=1.0 || p1*p1>=1) { if (warn) csound->Warning(csound, Str("rezzy instability corrected")); if (p0*p0>=1) p0 = NEARONE*(p0>0.0?1:(-1)); if (p1*p1>=1) p1 = NEARONE*(p1>0.0?1:(-1)); b1 = -(p0+p1); b2 = p0*p1; warn = 0; } } } //printf("Poles: (%f,%f) and (%f,%f) ", p0, pi, p1, -pi); } for (n=offset; nfcocod) { fco = (double)fcoptr[n]; } if (p->rezcod) { rez = (double)rezptr[n]; } if ((p->rezcod!=0) || (p->fcocod!=0)) { double c = fqcadj/fco; double rez2 = rez/(1.0 + exp(fco/11000.0)); double b; a = c/rez2 - 1.0; /* a depends on both Fco and Rez */ csq = c*c; /* Precalculate c^2 */ b = 1.0 + a + csq; /* Normalization constant */ invb = 1.0/b; b1 = (-a-2.0*csq)*invb; b2 = csq*invb; // Stabalise { // POLES double disc, p0, p1, pi; disc=b1*b1-(4*b2); if (disc<0.0) { pi = sqrt(-disc)/2.0; p0=p1=(-b1)/2.0; if (p0*p0+pi*pi>=1.0) { double theta = atan2(pi, p0); if (warn) csound->Warning(csound, Str("rezzy instability corrected")); //printf("b1, b2 = %f, %f ->", b1,b2); p0 = NEARONE * cos(theta); //pi = NEARONE * sin(theta); b1 = -2*p0; b2 = NEARONE*NEARONE; warn = 0; //printf(" b1, b2 = %f, %f\n", b1, b2); } } else { pi = 0; p0=(sqrt(disc)-b1)/2.0; p1=(-sqrt(disc)-b1)/2.0; if (p0*p0>=1.0 || p1*p1>=1) { if (warn) csound->Warning(csound, Str("rezzy instability corrected")); //printf("b1, b2= %f, %f ", b1, b2); if (p0*p0>=1) p0 = NEARONE*(p0>0.0?1:(-1)); if (p1*p1>=1) p1 = NEARONE*(p1>0.0?1:(-1)); b1 = -(p0+p1); b2 = p0*p1; warn = 0; //printf("b1, b2= %f, %f ", b1, b2); } } } //printf("Poles: (%f,%f) and (%f,%f) ", p0, pi, p1, -pi); } xn = (double)in[n]; /* Get the next sample */ /* Mikelson Biquad Filter Guts*/ //yn = (1.0/sqrt(1.0+rez)*xn - (-a-2.0*csq)*ynm1 - csq*ynm2)*invb; yn = invb/sqrt(1.0+rez)*xn - b1*ynm1 - b2*ynm2; xnm2 = xnm1; /* Update Xn-2 */ xnm1 = xn; /* Update Xn-1 */ ynm2 = ynm1; /* Update Yn-2 */ ynm1 = yn; /* Update Yn-1 */ out[n] = (MYFLT)yn; /* Generate the output sample */ } } else { /* High Pass Rezzy */ double c=0.0, rez2=0.0, cdrez2 = 0.0; if (UNLIKELY(p->fcocod==0 && p->rezcod==0)) { /* Only need to calculate once */ double b; c = fqcadj/fco; /* Filter constant c=1/Fco * adjustment */ rez2 = rez/(1.0 + sqrt(sqrt(1.0/c))); tval = 0.75/sqrt(1.0 + rez); csq = c*c; cdrez2 = c/rez2; b = (cdrez2 + csq); invb = 1.0/b; b1 = (1.0-cdrez2-2.0*csq)*invb; b2 = csq*invb; /* printf("c=%f rez2=%f tval=%f csq=%f b=%f ibvb=%f\n", */ /* c,rez2,tval,csq,b,invb); */ { // POLES double p0, p1, pi; double disc=b1*b1-(4*b2); if (disc<0.0) { pi = sqrt(-disc)/2.0; p0=p1=(-b1)/2.0; if (p0*p0+pi*pi>=1.0) { double theta = atan2(pi, p0); //printf("b1, b2= %f, %f ", b1, b2); if (warn) csound->Warning(csound, Str("rezzy instability corrected")); b1 = -p0*cos(theta); b2 = NEARONE*NEARONE; warn = 0; //printf("-> b1, b2= %f, %f\n", b1, b2); } } else { pi = 0; p0=(sqrt(disc)-b1)/2.0; p1=(-sqrt(disc)-b1)/2.0; if (p0*p0>=1.0 || p1*p1>=1) { //printf("b1, b2= %f, %f ", b1, b2); if (warn) csound->Warning(csound, Str("rezzy instability corrected")); if (p0*p0>=1.0) p0 = NEARONE*(p0>0?1:(-1)); if (p1*p1>=1.0) p1 = NEARONE*(p1>0?1:(-1)); b1 = -(p0+p1); b2 = p0*p1; warn = 0; //printf("-> b1, b2= %f, %f\n", b1, b2); } } } //printf("Poles: (%f,%f) and (%f,%f) ", p0, pi, p1, -pi); } for (n=offset; nfcocod) { fco = (double)fcoptr[n]; } if (p->rezcod) { rez = (double)rezptr[n]; } if (p->fcocod!=0 || p->rezcod!=0) { double b; c = fqcadj/fco; rez2 = rez/(1.0 + sqrt(sqrt(1.0/c))); tval = 0.75/sqrt(1.0 + rez); csq = c*c; cdrez2 = c/rez2; b = (cdrez2 + csq); invb = 1.0/b; b1 = (1.0-cdrez2-2.0*csq)*invb; b2 = csq*invb; { // POLES double p0, p1, pi; double disc=b1*b1-(4*b2); if (disc<0.0) { pi = sqrt(-disc)/2.0; p0=p1=(-b1)/2.0; if (p0*p0+pi*pi >=1.0) { double theta = atan2(pi,p0); //printf("b1, b2= %f, %f ", b1, b2); if (warn) csound->Warning(csound, Str("rezzy instability corrected")); b1 = -p0*cos(theta); b2 = NEARONE*NEARONE; warn = 0; //printf("-> b1, b2= %f, %f\n", b1, b2); } } else { pi = 0; p0=(sqrt(disc)-b1)/2.0; p1=(-sqrt(disc)-b1)/2.0; if (p0*p0>=1.0 || p1*p1>=1) { if (warn) csound->Warning(csound, Str("rezzy instability corrected")); if (p0*p0>=1.0) p0 = NEARONE*(p0>0?1:(-1)); if (p1*p1>=1.0) p1 = NEARONE*(p1>0?1:(-1)); b1 = -(p0+p1); b2 = p0*p1; warn = 0; } } //printf("Poles: (%f,%f) and (%f,%f)\n", p0, pi, p1, -pi); } } xn = (double)in[n]; /* Get the next sample */ /* Mikelson Biquad Filter Guts*/ yn = -b1*ynm1 - b2*ynm2 + (( cdrez2 + csq)*tval*xn + (-cdrez2 - 2.0*csq)*tval*xnm1 + csq*tval*xnm2)*invb; /* printf("ynm1=%f ynm2=%f xn=%f b1=%f, b2=%f => %f\n", */ /* ynm1, ynm2, xn, b1,b2, yn); */ /* printf("y..=%f x..= %f %f %f\n", */ /* -b1*ynm1 - b2*ynm2, (cdrez2 + csq)*tval*invb, */ /* (-cdrez2 - 2.0*csq)*tval*invb, csq*tval*invb); */ xnm2 = xnm1; /* Update Xn-2 */ xnm1 = xn; /* Update Xn-1 */ ynm2 = ynm1; /* Update Yn-2 */ ynm1 = yn; /* Update Yn-1 */ out[n] = (MYFLT)yn; /* Generate the output sample */ } } p->xnm1 = xnm1; p->xnm2 = xnm2; p->ynm1 = ynm1; p->ynm2 = ynm2; p->warn = warn; return OK; } /***************************************************************************/ /* The distortion opcode uses modified hyperbolic tangent distortion. */ /* Coded by Hans Mikelson November 1998 */ /***************************************************************************/ static int distort(CSOUND *csound, DISTORT *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *out, *in; MYFLT pregain = *p->pregain, postgain = *p->postgain; MYFLT shape1 = *p->shape1, shape2 = *p->shape2; MYFLT sig; in = p->in; out = p->out; if (*p->imode < FL(0.5)) { /* IV - Dec 28 2002 */ pregain *= FL(0.0002); postgain *= FL(20000.0); /* mode 0: original Mikelson version */ shape1 *= FL(0.000125); shape2 *= FL(0.000125); } else if (*p->imode < FL(1.5)) { /* mode 1: same with 0dBFS support */ pregain *= (FL(6.5536) * csound->dbfs_to_float); postgain *= (FL(0.61035156) * csound->e0dbfs); shape1 *= (FL(4.096) * csound->dbfs_to_float); shape2 *= (FL(4.096) * csound->dbfs_to_float); } else { /* mode 2: "raw" mode (+/- 1 amp.) */ shape1 *= pregain; shape2 *= -pregain; } /* IV - Dec 28 2002 */ shape1 += pregain; shape2 -= pregain; postgain *= FL(0.5); if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nmaxd * CS_ESR); FUNC *ftp; /* Pointer to a sine function */ //MYFLT ndsave; //ndsave = (MYFLT) ndel; if (UNLIKELY((ftp = csound->FTFind(csound, p->sine)) == NULL)) return NOTOK; p->ftp = ftp; if (LIKELY(*p->iphs >= FL(0.0))) p->lphs = (int32)(*p->iphs * FL(0.5) * FMAXLEN); /* Does it need this? */ else { printf("Initial value of lphs set to zero\n"); p->lphs = 0; } p->ampcod = IS_ASIG_ARG(p->xamp) ? 1 : 0; p->cpscod = IS_ASIG_ARG(p->xcps) ? 1 : 0; if (*p->iskip==FL(0.0)) { p->ynm1 = (*p->wave == FL(1.0)) ? -FL(0.5) : FL(0.0); p->ynm2 = FL(0.0); } /* finished setting up buzz now set up internal vdelay */ if (UNLIKELY(ndel == 0)) ndel = 1; /* fix due to Troxler */ if (p->aux.auxp == NULL || (unsigned int)(ndel*sizeof(MYFLT)) > p->aux.size) /* allocate space for delay buffer */ csound->AuxAlloc(csound, ndel * sizeof(MYFLT), &p->aux); else if (*p->iskip==FL(0.0)) { memset(p->aux.auxp, 0, ndel*sizeof(MYFLT)); } p->left = 0; if (*p->leak <= FL(0.0) || *p->leak >= FL(1.0)) { p->leaky = (*p->wave == FL(3.0)) ? FL(0.995) : FL(0.999); } else { p->leaky = *p->leak; } p->nyq = *p->inyq; return OK; } /* end vcoset(p) */ /* This code modified from Csound's buzz, integ, & vdelay opcodes */ static int vco(CSOUND *csound, VCO *p) { FUNC *ftp; MYFLT *ar, *ampp, *cpsp, *ftbl; int32 phs, inc, lobits, dwnphs, tnp1, lenmask, maxd, indx; MYFLT leaky, /*rtfqc,*/ amp, fqc; MYFLT sicvt2, over2n, scal, num, denom, pulse = FL(0.0), saw = FL(0.0); MYFLT sqr = FL(0.0), tri = FL(0.0); uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int knh; /* VDelay Inserted here */ MYFLT *buf = (MYFLT *)p->aux.auxp; MYFLT fv1, out1; int32 v1, v2; int wave = (int)MYFLT2LONG(*p->wave); /* Save recalculation and also round */ leaky = p->leaky; ftp = p->ftp; if (UNLIKELY(buf==NULL || ftp==NULL)) goto err1; /* RWD fix */ maxd = (uint32) (*p->maxd * CS_ESR); if (UNLIKELY(maxd == 0)) maxd = 1; /* Degenerate case */ indx = p->left; /* End of VDelay insert */ ftbl = ftp->ftable; sicvt2 = csound->sicvt * FL(0.5); /* for theta/2 */ lobits = ftp->lobits; lenmask = ftp->lenmask; ampp = p->xamp; cpsp = p->xcps; fqc = *cpsp; //rtfqc = SQRT(fqc); knh = (int)(CS_ESR*p->nyq/fqc); if (UNLIKELY((n = (int)knh) <= 0)) { csound->Warning(csound, "knh=%x nyq=%f fqc=%f\n" "vco knh (%d) <= 0; taken as 1\n", knh, p->nyq, fqc, n); n = 1; } tnp1 = n + n + 1; /* calc 2n + 1 */ over2n = FL(0.5) / n; amp = *ampp; scal = over2n; inc = (int32)(fqc * sicvt2); ar = p->ar; phs = p->lphs; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } /*-----------------------------------------------------*/ /* PWM Wave */ /*-----------------------------------------------------*/ if (wave==2) { MYFLT pw = *p->pw; for (n=offset; n> lobits; denom = *(ftbl + dwnphs); if (denom > FL(0.00001) || denom < -FL(0.00001)) { num = *(ftbl + (dwnphs * tnp1 & lenmask)); pulse = (num / denom - FL(1.0)) * scal; } else pulse = FL(1.0); phs += inc; phs &= PHMASK; if (p->ampcod) { amp = ampp[n]; scal = over2n; /* Why is this needed?? */ } if (p->cpscod) { fqc = cpsp[n]; inc = (int32)(fqc* sicvt2); } /* VDelay inserted here */ buf[indx] = pulse; fv1 = (MYFLT) indx - CS_ESR * pw / fqc; v1 = (int32) fv1; if (fv1 < FL(0.0)) v1--; fv1 -= (MYFLT) v1; /* Make sure Inside the buffer */ while (v1 >= maxd) v1 -= maxd; while (v1 < 0L) v1 += maxd; /* Find next sample for interpolation */ v2 = (v1 < (maxd - 1L) ? v1 + 1L : 0L); out1 = buf[v1] + fv1 * (buf[v2] - buf[v1]); if (++indx == maxd) indx = 0; /* Advance current pointer */ /* End of VDelay */ sqr = pulse - out1 + leaky*p->ynm1; p->ynm1 = sqr; ar[n] = (sqr + pw - FL(0.5)) * FL(1.9) * amp; } } /*-----------------------------------------------------*/ /* Triangle Wave */ /*-----------------------------------------------------*/ else if (wave==3) { MYFLT pw = *p->pw; for (n=offset; n> lobits; denom = *(ftbl + dwnphs); if (denom > FL(0.0002) || denom < -FL(0.0002)) { num = *(ftbl + (dwnphs * tnp1 & lenmask)); pulse = (num / denom - FL(1.0)) * scal; } /* else pulse = *ampp; */ else pulse = FL(1.0); phs += inc; phs &= PHMASK; if (p->ampcod) { /* scal = over2n; */ /* Why is this needed?? */ amp = ampp[n]; } if (p->cpscod) { fqc = cpsp[n]; inc = (int32)(fqc* sicvt2); } /* VDelay inserted here */ buf[indx] = pulse; fv1 = (MYFLT) indx - CS_ESR * pw / fqc; v1 = (int32) fv1; if (fv1 < FL(0.0)) v1--; fv1 -= (MYFLT) v1; /* Make sure Inside the buffer */ while (v1 >= maxd) v1 -= maxd; while (v1 < 0L) v1 += maxd; /* Find next sample for interpolation */ v2 = (v1 < (maxd - 1L) ? v1 + 1L : 0L); out1 = buf[v1] + fv1 * (buf[v2] - buf[v1]); if (UNLIKELY(++indx == maxd)) indx = 0; /* Advance current pointer */ /* End of VDelay */ /* Integrate twice and ouput */ sqr = pulse - out1 + leaky*p->ynm1; tri = sqr + leaky*p->ynm2; p->ynm1 = sqr; p->ynm2 = tri; ar[n] = tri * amp * fqc / (CS_ESR * FL(0.42) * (FL(0.05) + pw - pw * pw)); } } /*-----------------------------------------------------*/ /* Sawtooth Wave */ /*-----------------------------------------------------*/ else { for (n=offset; n> lobits; denom = *(ftbl + dwnphs); if (denom > FL(0.0002) || denom < -FL(0.0002)) { num = *(ftbl + (dwnphs * tnp1 & lenmask)); pulse = (num / denom - FL(1.0)) * scal; } /* else pulse = *ampp; */ else pulse = FL(1.0); phs += inc; phs &= PHMASK; if (p->ampcod) { /* scal = *(++ampp) * over2n; */ /* scal = over2n; *//* Why is this needed?? */ amp = ampp[n]; } if (p->cpscod) { fqc = cpsp[n]; inc = (int32)(fqc*sicvt2); } /* Leaky Integration */ saw = pulse + leaky*p->ynm1; p->ynm1 = saw; ar[n] = saw*FL(1.5)*amp; } } p->left = indx; /* and keep track of where you are */ p->lphs = phs; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("vco: not initialised")); } /***************************************************************************/ /* This is a simplified model of a planet orbiting in a binary star system */ /* Coded by Hans Mikelson December 1998 */ /***************************************************************************/ static int planetset(CSOUND *csound, PLANET *p) { if (*p->iskip==FL(0.0)) { p->x = *p->xval; p->y = *p->yval; p->z = *p->zval; p->vx = *p->vxval; p->vy = *p->vyval; p->vz = *p->vzval; p->ax = FL(0.0); p->ay = FL(0.0); p->az = FL(0.0); p->hstep = *p->delta; p->friction = FL(1.0) - *p->fric/FL(10000.0); } return OK; } /* end planetset(p) */ /* Planet orbiting in a binary star system coded by Hans Mikelson */ static int planet(CSOUND *csound, PLANET *p) { MYFLT *outx, *outy, *outz; MYFLT sqradius1, sqradius2, radius1, radius2, fric; MYFLT xxpyy, dz1, dz2, mass1, mass2, msqror1, msqror2; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; fric = p->friction; outx = p->outx; outy = p->outy; outz = p->outz; p->s1z = *p->sep*FL(0.5); p->s2z = -p->s1z; mass1 = *p->mass1; mass2 = *p->mass2; if (UNLIKELY(offset)) { memset(outx, '\0', offset*sizeof(MYFLT)); memset(outy, '\0', offset*sizeof(MYFLT)); memset(outz, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&outx[nsmps], '\0', early*sizeof(MYFLT)); memset(&outy[nsmps], '\0', early*sizeof(MYFLT)); memset(&outz[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nx * p->x + p->y * p->y; dz1 = p->s1z - p->z; /* Calculate Acceleration */ sqradius1 = xxpyy + dz1 * dz1 + FL(1.0); radius1 = SQRT(sqradius1); msqror1 = mass1/sqradius1/radius1; p->ax = msqror1 * -p->x; p->ay = msqror1 * -p->y; p->az = msqror1 * dz1; dz2 = p->s2z - p->z; /* Calculate Acceleration */ sqradius2 = xxpyy + dz2 * dz2 + FL(1.0); radius2 = SQRT(sqradius2); msqror2 = mass2/sqradius2/radius2; p->ax += msqror2 * -p->x; p->ay += msqror2 * -p->y; p->az += msqror2 * dz2; /* Update Velocity */ p->vx = fric * p->vx + p->hstep * p->ax; p->vy = fric * p->vy + p->hstep * p->ay; p->vz = fric * p->vz + p->hstep * p->az; /* Update Position */ p->x += p->hstep * p->vx; p->y += p->hstep * p->vy; p->z += p->hstep * p->vz; /* Output the results */ outx[n] = p->x; outy[n] = p->y; outz[n] = p->z; } return OK; } /* ************************************************** */ /* ******** Parametric EQ *************************** */ /* ************************************************** */ /* Implementation of Zoelzer's Parametric Equalizer Filters */ static int pareqset(CSOUND *csound, PAREQ *p) { /* The equalizer filter is initialised to zero. */ if (*p->iskip == FL(0.0)) { p->xnm1 = p->xnm2 = p->ynm1 = p->ynm2 = 0.0; p->prv_fc = p->prv_v = p->prv_q = FL(-1.0); p->imode = (int) MYFLT2LONG(*p->mode); } return OK; } /* end pareqset(p) */ static int pareq(CSOUND *csound, PAREQ *p) { MYFLT xn, yn; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (*p->fc != p->prv_fc || *p->v != p->prv_v || *p->q != p->prv_q) { double omega = (double)(csound->tpidsr * *p->fc), k, kk, vkk, vk, vkdq, a0; p->prv_fc = *p->fc; p->prv_v = *p->v; p->prv_q = *p->q; switch (p->imode) { /* Low Shelf */ case 1: { double sq = sqrt(2.0 * (double) p->prv_v); k = tan(omega * 0.5); kk = k * k; vkk = (double)p->prv_v * kk; p->b0 = 1.0 + sq * k + vkk; p->b1 = 2.0 * (vkk - FL(1.0)); p->b2 = 1.0 - sq * k + vkk; a0 = 1.0 + k / (double)p->prv_q + kk; p->a1 = 2.0 * (kk - 1.0); p->a2 = 1.0 - k / (double)p->prv_q + kk; } break; /* High Shelf */ case 2: { double sq = sqrt(2.0 * (double) p->prv_v); k = tan((PI - omega) * 0.5); kk = k * k; vkk = (double)p->prv_v * kk; p->b0 = 1.0 + sq * k + vkk; p->b1 = -2.0 * (vkk - 1.0); p->b2 = 1.0 - sq * k + vkk; a0 = 1.0 + k / (double)p->prv_q + kk; p->a1 = -2.0 * (kk - 1.0); p->a2 = 1.0 - k / (double)p->prv_q + kk; } break; /* Peaking EQ */ default: { k = tan(omega * 0.5); kk = k * k; vk = (double)p->prv_v * k; vkdq = vk / (double)p->prv_q; p->b0 = 1.0 + vkdq + kk; p->b1 = 2.0 * (kk - 1.0); p->b2 = 1.0 - vkdq + kk; a0 = 1.0 + k / (double)p->prv_q + kk; p->a1 = 2.0 * (kk - 1.0); p->a2 = 1.0 - k / (double)p->prv_q + kk; } } a0 = 1.0 / a0; p->a1 *= a0; p->a2 *= a0; p->b0 *= a0; p->b1 *= a0; p->b2 *= a0; } if (UNLIKELY(offset)) memset(p->out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->out[nsmps], '\0', early*sizeof(MYFLT)); } { double a1 = p->a1, a2 = p->a2; double b0 = p->b0, b1 = p->b1, b2 = p->b2; double xnm1 = p->xnm1, xnm2 = p->xnm2, ynm1 = p->ynm1, ynm2 = p->ynm2; for (n=offset; nin[n]; yn = b0 * xn + b1 * xnm1 + b2 * xnm2 - a1 * ynm1 - a2 * ynm2; xnm2 = xnm1; xnm1 = xn; ynm2 = ynm1; ynm1 = yn; p->out[n] = (MYFLT)yn; } p->xnm1 = xnm1; p->xnm2 = xnm2; p->ynm1 = ynm1; p->ynm2 = ynm2; } return OK; } /* Nested all-pass filters useful for creating reverbs */ /* Coded by Hans Mikelson January 1999 */ /* Derived from Csound's delay opcode */ /* Set up nested all-pass filter */ static int nestedapset(CSOUND *csound, NESTEDAP *p) { int32 npts, npts1=0, npts2=0, npts3=0; void *auxp; if (*p->istor && p->auxch.auxp != NULL) return OK; npts2 = (int32)(*p->del2 * CS_ESR); npts3 = (int32)(*p->del3 * CS_ESR); npts1 = (int32)(*p->del1 * CS_ESR) - npts2 -npts3; if (UNLIKELY(((int32)(*p->del1 * CS_ESR)) <= ((int32)(*p->del2 * CS_ESR) + (int32)(*p->del3 * CS_ESR)))) { return csound->InitError(csound, Str("illegal delay time")); } npts = npts1 + npts2 + npts3; /* new space if reqd */ if ((auxp = p->auxch.auxp) == NULL || npts != p->npts) { csound->AuxAlloc(csound, (size_t)npts*sizeof(MYFLT), &p->auxch); auxp = p->auxch.auxp; p->npts = npts; if (*p->mode == FL(1.0)) { if (UNLIKELY(npts1 <= 0)) { return csound->InitError(csound, Str("illegal delay time")); } p->beg1p = (MYFLT *) p->auxch.auxp; p->end1p = (MYFLT *) p->auxch.endp; } else if (*p->mode == FL(2.0)) { if (UNLIKELY(npts1 <= 0 || npts2 <= 0)) { return csound->InitError(csound, Str("illegal delay time")); } p->beg1p = (MYFLT *) p->auxch.auxp; p->beg2p = p->beg1p + npts1; p->end1p = p->beg2p - 1; p->end2p = (MYFLT *) p->auxch.endp; } else if (*p->mode == FL(3.0)) { if (UNLIKELY(npts1 <= 0 || npts2 <= 0 || npts3 <= 0)) { return csound->InitError(csound, Str("illegal delay time")); } p->beg1p = (MYFLT *) p->auxch.auxp; p->beg2p = (MYFLT *) p->auxch.auxp + (int32)npts1; p->beg3p = (MYFLT *) p->auxch.auxp + (int32)npts1 + (int32)npts2; p->end1p = p->beg2p - 1; p->end2p = p->beg3p - 1; p->end3p = (MYFLT *) p->auxch.endp; } } /* else if requested */ else if (!(*p->istor)) { memset(auxp, 0, npts*sizeof(int32)); } p->del1p = p->beg1p; p->del2p = p->beg2p; p->del3p = p->beg3p; p->out1 = FL(0.0); p->out2 = FL(0.0); p->out3 = FL(0.0); return OK; } static int nestedap(CSOUND *csound, NESTEDAP *p) { MYFLT *outp, *inp; MYFLT *beg1p, *beg2p, *beg3p, *end1p, *end2p, *end3p; MYFLT *del1p, *del2p, *del3p; MYFLT in1, g1, g2, g3; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; /* RWD fix */ outp = p->out; inp = p->in; if (UNLIKELY(offset)) memset(outp, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&outp[nsmps], '\0', early*sizeof(MYFLT)); } /* Ordinary All-Pass Filter */ if (*p->mode == FL(1.0)) { del1p = p->del1p; end1p = p->end1p; beg1p = p->beg1p; g1 = *p->gain1; for (n=offset; nout1 = *del1p - g1*in1; /* dw1 delay dr1, dt1 */ *del1p = in1 + g1 * p->out1; if (UNLIKELY(++del1p >= end1p)) del1p = beg1p; outp[n] = p->out1; } p->del1p = del1p; /* save the new curp */ } /* Single Nested All-Pass Filter */ else if (*p->mode == FL(2.0)) { del1p = p->del1p; end1p = p->end1p; beg1p = p->beg1p; g1 = *p->gain1; del2p = p->del2p; end2p = p->end2p; beg2p = p->beg2p; g2 = *p->gain2; for (n=offset; nout2 = *del2p - g2 * *del1p; p->out1 = p->out2 - g1 * in1; *del1p = in1 + g1 * p->out1; *del2p = *del1p + g2 * p->out2; /* delay 2 */ if (UNLIKELY(++del2p >= end2p)) del2p = beg2p; /* delay 1 */ if (UNLIKELY(++del1p >= end1p)) del1p = beg1p; outp[n] = p->out1; } p->del1p = del1p; /* save the new del1p */ p->del2p = del2p; /* save the new del2p */ } /* Double Nested All-Pass Filter */ else if (*p->mode == FL(3.0)) { del1p = p->del1p; end1p = p->end1p; beg1p = p->beg1p; g1 = *p->gain1; del2p = p->del2p; end2p = p->end2p; beg2p = p->beg2p; g2 = *p->gain2; del3p = p->del3p; end3p = p->end3p; beg3p = p->beg3p; g3 = *p->gain3; for (n=offset; nout2 = *del2p - g2 * *del1p; p->out3 = *del3p - g3 * p->out2; p->out1 = p->out3 - g1 * in1; *del1p = in1 + g1 * p->out1; *del2p = *del1p + g2 * p->out2; *del3p = p->out2 + g3 * p->out3; /* delay 1 */ if (UNLIKELY(++del1p >= end1p)) del1p = beg1p; /* delay 2 */ if (UNLIKELY(++del2p >= end2p)) del2p = beg2p; /* delay 3 */ if (UNLIKELY(++del3p >= end3p)) del3p = beg3p; outp[n] = p->out1; } p->del1p = del1p; /* save the new del1p */ p->del2p = del2p; /* save the new del2p */ p->del3p = del3p; /* save the new del3p */ } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("delay: not initialised")); } /***************************************************************************/ /* The Lorenz System */ /* Coded by Hans Mikelson Jauarary 1999 */ /***************************************************************************/ static int lorenzset(CSOUND *csound, LORENZ *p) { if (*p->iskip==FL(0.0)) { p->valx = *p->inx; p->valy = *p->iny; p->valz = *p->inz; } return OK; } /* Lorenz System coded by Hans Mikelson */ static int lorenz(CSOUND *csound, LORENZ *p) { MYFLT *outx, *outy, *outz; MYFLT x, y, z, xx, yy, s, r, b, hstep; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 skip; outx = p->outx; outy = p->outy; outz = p->outz; s = *p->s; r = *p->r; b = *p->b; hstep = *p->hstep; skip = (int32) *p->skip; x = p->valx; y = p->valy; z = p->valz; if (UNLIKELY(offset)) { memset(outx, '\0', offset*sizeof(MYFLT)); memset(outy, '\0', offset*sizeof(MYFLT)); memset(outz, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&outx[nsmps], '\0', early*sizeof(MYFLT)); memset(&outy[nsmps], '\0', early*sizeof(MYFLT)); memset(&outz[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; n0); /* Output the results */ outx[n] = x; outy[n] = y; outz[n] = z; } p->valx = x; p->valy = y; p->valz = z; return OK; } /**************************************************************************/ /* TBVCF by Hans Mikelson December 2000-January 2001 */ /* This opcode attempts to model some of the filter characteristics of */ /* a TB303. Euler's method is used to approximate the system rather */ /* than traditional filter methods. Cut-off frequency, Q and distortion */ /* are all coupled. Empirical methods were used to try to unentwine them */ /* but frequency is only approximate. */ /**************************************************************************/ static int tbvcfset(CSOUND *csound, TBVCF *p) { if (*p->iskip==FL(0.0)) { p->y = p->y1 = p->y2 = 0.0; } p->fcocod = IS_ASIG_ARG(p->fco) ? 1 : 0; p->rezcod = IS_ASIG_ARG(p->res) ? 1 : 0; return OK; } static int tbvcf(CSOUND *csound, TBVCF *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *out, *in; double x; MYFLT *fcoptr, *resptr, *distptr, *asymptr; double fco, res, dist, asym; double y = p->y, y1 = p->y1, y2 = p->y2; /* The initialisations are fake to fool compiler warnings */ double ih, fdbk, d, ad; double fc=0.0, fco1=0.0, q=0.0, q1=0.0; ih = 0.001; /* ih is the incremental factor */ /* Set up the pointers */ in = p->in; out = p->out; fcoptr = p->fco; resptr = p->res; distptr = p->dist; asymptr = p->asym; /* Get the values for the k-rate variables */ fco = (double)*fcoptr; res = (double)*resptr; dist = (double)*distptr; asym = (double)*asymptr; /* Try to decouple the variables */ if ((p->rezcod==0) && (p->fcocod==0)) { /* Calc once only */ q1 = res/(1.0 + sqrt(dist)); fco1 = pow(fco*260.0/(1.0+q1*0.5),0.58); q = q1*fco1*fco1*0.0005; fc = fco1*(double)csound->onedsr*(44100.0/8.0); } if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nfcocod) { fco = (double)fcoptr[n]; } if (p->rezcod) { res = (double)resptr[n]; } if ((p->rezcod!=0) || (p->fcocod!=0)) { q1 = res/(1.0 + sqrt(dist)); fco1 = pow(fco*260.0/(1.0+q1*0.5),0.58); q = q1*fco1*fco1*0.0005; fc = fco1*(double)csound->onedsr*(44100.0/8.0); } x = (double)in[n]; fdbk = q*y/(1.0 + exp(-3.0*y)*asym); y1 = y1 + ih*((x - y1)*fc - fdbk); d = -0.1*y*20.0; ad = (d*d*d + y2)*100.0*dist; y2 = y2 + ih*((y1 - y2)*fc + ad); y = y + ih*((y2 - y)*fc); out[n] = (MYFLT)(y*fc/1000.0*(1.0 + q1)*3.2); } p->y = y; p->y1 = y1; p->y2 = y2; return OK; } /* bqrez by Matt Gerassimoff */ static int bqrezset(CSOUND *csound, REZZY *p) { if (*p->iskip==FL(0.0)) { p->xnm1 = p->xnm2 = p->ynm1 = p->ynm2 = 0.0; /* Initialise to zero */ } p->fcocod = IS_ASIG_ARG(p->fco) ? 1 : 0; p->rezcod = IS_ASIG_ARG(p->rez) ? 1 : 0; return OK; } /* end rezzyset(p) */ static int bqrez(CSOUND *csound, REZZY *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *out, *fcoptr, *rezptr, *in; double fco, rez, xn, yn; double sin2 = 0.0, cos2 = 0.0, beta=0.0, alpha, gamma=0.0, mu, sigma, chi; double theta; double xnm1 = p->xnm1, xnm2 = p->xnm2, ynm1 = p->ynm1, ynm2 = p->ynm2; int mode = (int)MYFLT2LONG(*p->mode); in = p->in; out = p->out; fcoptr = p->fco; rezptr = p->rez; fco = (double)*fcoptr; rez = (double)*rezptr; if ((p->rezcod == 0) && (p->fcocod == 0)) { theta = fco * (double)csound->tpidsr; sin2 = sin(theta) * 0.5; cos2 = cos(theta); beta = (rez - sin2) / (rez + sin2); gamma = (beta + 1.0) * cos2; } if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } if (mode < 3) { if (mode == 0) { /* Low Pass */ chi = -1.0; mu = 2.0; sigma = 1.0; } else if (mode == 1) { /* High Pass */ chi = 1.0; mu = -2.0; sigma = 1.0; } else { /* Band Pass */ chi = 1.0; mu = 0.0; sigma = -1.0; } alpha = (beta + 1.0 + chi*gamma) * 0.5; for (n=offset; nfcocod) { fco = (double)fcoptr[n]; } if (p->rezcod) { rez = (double)rezptr[n]; } if ((p->rezcod == 1) || (p->fcocod == 1)) { theta = fco * (double) csound->tpidsr; sin2 = sin(theta) * 0.5; cos2 = cos(theta); beta = (rez - sin2) / (rez + sin2); gamma = (beta + 1.0) * cos2; alpha = (beta + 1.0 + chi*gamma) * 0.5; } xn = (double)in[n]; /* Get the next sample */ yn = alpha*(xn + mu*xnm1 + sigma*xnm2) + gamma*ynm1 - beta*ynm2; xnm2 = xnm1; /* Update Xn-2 */ xnm1 = xn; /* Update Xn-1 */ ynm2 = ynm1; /* Update Yn-2 */ ynm1 = yn; /* Update Yn-1 */ out[n] = (MYFLT)yn; /* Generate the output sample */ } } else if (mode == 3) { /* Band Stop */ alpha = (beta + 1.0) * 0.5; for (n=offset; nfcocod) { fco = (double)fcoptr[n]; } if (p->rezcod) { rez = (double)rezptr[n]; } if ((p->rezcod == 1) || (p->fcocod == 1)) { theta = fco * (double) csound->tpidsr; sin2 = sin(theta) * 0.5; cos2 = cos(theta); beta = (rez - sin2) / (rez + sin2); gamma = (beta + 1.0) * cos2; alpha = (beta + 1.0) * 0.5; } mu = -2.0*cos2; xn = (double)in[n]; /* Get the next sample */ yn = alpha*(xn + mu*xnm1 + xnm2) + gamma*ynm1 - beta*ynm2; xnm2 = xnm1; /* Update Xn-2 */ xnm1 = xn; /* Update Xn-1 */ ynm2 = ynm1; /* Update Yn-2 */ ynm1 = yn; /* Update Yn-1 */ out[n] = (MYFLT) yn; /* Generate the output sample */ } } else if (mode == 4) { /* All Pass */ for (n=offset; nfcocod) { fco = (double)fcoptr[n]; } if (p->rezcod) { rez = (double)rezptr[n]; } if ((p->rezcod == 1) || (p->fcocod == 1)) { theta = fco * (double) csound->tpidsr; sin2 = sin(theta) * 0.5; cos2 = cos(theta); beta = (rez - sin2) / (rez + sin2); gamma = (beta + 1.0) * cos2; } chi = beta; mu = -gamma; xn = (double)in[n]; /* Get the next sample */ yn = chi*xn + mu*xnm1 + xnm2 + gamma*ynm1 - beta*ynm2; xnm2 = xnm1; /* Update Xn-2 */ xnm1 = xn; /* Update Xn-1 */ ynm2 = ynm1; /* Update Yn-2 */ ynm1 = yn; /* Update Yn-1 */ out[n] = (MYFLT)yn; /* Generate the output sample */ } } p->xnm1 = xnm1; p->xnm2 = xnm2; p->ynm1 = ynm1; p->ynm2 = ynm2; return OK; } /* mode opcode - original UDO code by François Blanc, rewritten in C by * Steven Yi */ static int modeset(CSOUND *csound, MODE *p) { /* Initialize filter to zero if set to reinitialize. */ if (*p->reinit==FL(0.0)) { /* Only reset in in non-legato mode */ p->xnm1 = p->ynm1 = p->ynm2 = 0.0; p->a0 = p->a1 = p->a2 = p->d = 0.0; } p->lfq = -FL(1.0); p->lq = -FL(1.0); return OK; } static int mode(CSOUND *csound, MODE *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT lfq = p->lfq, lq = p->lq; MYFLT kfq = *p->kfreq; MYFLT kq = *p->kq; double xn, yn, a0=p->a0, a1=p->a1, a2=p->a2,d=p->d; double xnm1 = p->xnm1, ynm1 = p->ynm1, ynm2 = p->ynm2; int asgfr = IS_ASIG_ARG(p->kfreq), asgq = IS_ASIG_ARG(p->kq); if (UNLIKELY(offset)) memset(p->aout, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->aout[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nkfreq[n]; if (asgq) kq = p->kq[n]; //MYFLT kfq = IS_ASIG_ARG(p->kfreq) ? p->kfreq[n] : *p->kfreq; //MYFLT kq = IS_ASIG_ARG(p->kq) ? p->kq[n] : *p->kq; if (lfq != kfq || lq != kq) { double kfreq = kfq*TWOPI; double kalpha = (CS_ESR/kfreq); double kbeta = kalpha*kalpha; d = 0.5*kalpha; lq = kq; lfq = kfq; a0 = 1.0/ (kbeta+d/kq); a1 = a0 * (1.0-2.0*kbeta); a2 = a0 * (kbeta-d/kq); } xn = (double)p->ain[n]; yn = a0*xnm1 - a1*ynm1 - a2*ynm2; xnm1 = xn; ynm2 = ynm1; ynm1 = yn; yn = yn*d; p->aout[n] = (MYFLT)yn; } p->xnm1 = xnm1; p->ynm1 = ynm1; p->ynm2 = ynm2; p->lfq = lfq; p->lq = lq; p->d = d; p->a0 = a0; p->a1 = a1; p->a2 = a2; return OK; } #define S(x) sizeof(x) static OENTRY localops[] = { { "biquad", S(BIQUAD), 0, 5, "a", "akkkkkko", (SUBR)biquadset, NULL, (SUBR)biquad }, { "biquada", S(BIQUAD), 0, 5, "a", "aaaaaaao", (SUBR)biquadset, NULL,(SUBR)biquada }, { "moogvcf", S(MOOGVCF), 0, 5, "a", "axxpo", (SUBR)moogvcfset, NULL, (SUBR)moogvcf }, { "moogvcf2", S(MOOGVCF),0, 5, "a", "axxoo", (SUBR)moogvcfset, NULL, (SUBR)moogvcf }, { "rezzy", S(REZZY), 0, 5, "a", "axxoo", (SUBR)rezzyset, NULL, (SUBR)rezzy }, { "bqrez", S(REZZY), 0, 5, "a", "axxoo", (SUBR)bqrezset, NULL, (SUBR)bqrez }, { "distort1", S(DISTORT),TR, 4, "a", "akkkko", NULL, NULL, (SUBR)distort }, { "vco", S(VCO), TR, 5, "a", "xxiVppovoo",(SUBR)vcoset, NULL, (SUBR)vco }, { "tbvcf", S(TBVCF), 0, 5, "a", "axxkkp", (SUBR)tbvcfset, NULL, (SUBR)tbvcf }, { "planet", S(PLANET),0, 5,"aaa","kkkiiiiiiioo", (SUBR)planetset, NULL, (SUBR)planet}, { "pareq", S(PAREQ), 0, 5, "a", "akkkoo",(SUBR)pareqset, NULL, (SUBR)pareq }, { "nestedap", S(NESTEDAP),0, 5,"a", "aiiiiooooo", (SUBR)nestedapset, NULL, (SUBR)nestedap}, { "lorenz", S(LORENZ),0, 5, "aaa", "kkkkiiiio", (SUBR)lorenzset, NULL, (SUBR)lorenz}, { "mode", S(MODE), 0, 5, "a", "axxo", (SUBR)modeset, NULL, (SUBR)mode } }; int biquad_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/biquad.h000066400000000000000000000073111321653344700161150ustar00rootroot00000000000000/* biquad.h: Copyright (C) 1998, 1999, 2001 by Hans Mikelson, Matt Gerassimoff, John ffitch, Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* biquad.h */ #include "stdopcod.h" /* Structure for biquadratic filter */ typedef struct { OPDS h; MYFLT *out, *in, *b0, *b1, *b2, *a0, *a1, *a2, *reinit; double xnm1, xnm2, ynm1, ynm2; } BIQUAD; /* Structure for moogvcf filter */ typedef struct { OPDS h; MYFLT *out, *in, *fco, *res, *max, *iskip; double xnm1, y1nm1, y2nm1, y3nm1, y1n, y2n, y3n, y4n; MYFLT maxint; int16 fcocod, rezcod; } MOOGVCF; /* Structure for rezzy filter */ typedef struct { OPDS h; MYFLT *out, *in, *fco, *rez, *mode, *iskip; double xnm1, xnm2, ynm1, ynm2; int16 fcocod, rezcod; int16 warn; } REZZY; /* Structure for distortion */ typedef struct { OPDS h; MYFLT *out, *in, *pregain, *postgain, *shape1, *shape2, *imode; } DISTORT; /* Structure for vco, analog modeling opcode */ typedef struct { OPDS h; MYFLT *ar, *xamp, *xcps, *wave, *pw, *sine, *maxd, *leak, *inyq, *iphs, *iskip; MYFLT ynm1, ynm2, leaky, nyq; int16 ampcod, cpscod; int32 lphs; FUNC *ftp; /* Insert VDelay here */ AUXCH aux; /* AUXCH auxd; */ int32 left; /* End VDelay insert */ } VCO; typedef struct { OPDS h; MYFLT *outx, *outy, *outz, *mass1, *mass2, *sep, *xval, *yval, *zval; MYFLT *vxval, *vyval, *vzval, *delta, *fric, *iskip; MYFLT s1z, s2z, friction; MYFLT x, y, z, vx, vy, vz, ax, ay, az, hstep; } PLANET; typedef struct { OPDS h; MYFLT *out, *in, *fc, *v, *q, *mode, *iskip; double xnm1, xnm2, ynm1, ynm2; MYFLT prv_fc, prv_v, prv_q; double b0, b1, b2, a1, a2; int imode; } PAREQ; typedef struct { OPDS h; MYFLT *out, *in, *mode, *maxdel, *del1, *gain1, *del2, *gain2; MYFLT *del3, *gain3, *istor; MYFLT *curp, out1, out2, out3; MYFLT *beg1p, *beg2p, *beg3p, *end1p, *end2p, *end3p; MYFLT *del1p, *del2p, *del3p; int32 npts; AUXCH auxch; } NESTEDAP; typedef struct { OPDS h; MYFLT *outx, *outy, *outz, *s, *r, *b, *hstep, *inx, *iny, *inz, *skip, *iskip; MYFLT valx, valy, valz; } LORENZ; /* And also opcodes of Jens Groh, Munich, Germany. mail: groh@irt.de */ /* Structure for tbvcf filter */ typedef struct { OPDS h; MYFLT *out, *in, *fco, *res, *dist, *asym, *iskip; double y, y1, y2; int16 fcocod, rezcod; } TBVCF; /* Structure for mode opcode */ typedef struct { OPDS h; MYFLT *aout, *ain, *kfreq, *kq, *reinit; double xnm1, ynm1, ynm2, a0, a1, a2, d; MYFLT lfq,lq; } MODE; csound-6.10.0/Opcodes/bowed.h000066400000000000000000000050731321653344700157530ustar00rootroot00000000000000/* bowed.h: Copyright (C) 1996, 1997 Perry Cook, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /******************************************/ /* Bowed String model ala Smith */ /* after McIntyre, Schumacher, Woodhouse */ /* by Perry Cook, 1995-96 */ /* Recoded for Csound by John ffitch */ /* November 1997 */ /* */ /* This is a waveguide model, and thus */ /* relates to various Stanford Univ. */ /* and possibly Yamaha and other patents.*/ /* */ /******************************************/ #if !defined(__Bowed_h) #define __Bowed_h #include "physutil.h" /***********************************************/ /* Simple Bow Table Object, after Smith */ /* by Perry R. Cook, 1995-96 */ /***********************************************/ typedef struct BowTabl { MYFLT offSet; MYFLT slope; MYFLT lastOutput; } BowTabl; MYFLT BowTabl_lookup(CSOUND *,BowTabl*, MYFLT sample); typedef struct BOWED { OPDS h; MYFLT *ar; /* Output */ MYFLT *amp, *frequency; MYFLT *bowPress, *betaRatio, *vibFreq; MYFLT *vibAmt, *ifn, *lowestFreq; FUNC *vibr; MYFLT v_rate; /* Parameters for vibrato */ MYFLT v_time; MYFLT v_phaseOffset; MYFLT v_lastOutput; DLineL neckDelay; DLineL bridgeDelay; BowTabl bowTabl; OnePole reflFilt; BiQuad bodyFilt; ADSR adsr; MYFLT maxVelocity; MYFLT baseDelay; MYFLT vibrGain; MYFLT lastpress; MYFLT lastfreq; MYFLT lastbeta; MYFLT lastamp; MYFLT limit; int kloop; } BOWED; #endif csound-6.10.0/Opcodes/bowedbar.c000066400000000000000000000200501321653344700164230ustar00rootroot00000000000000/* bowedbar.c: Copyright (C) 1999 Perry Cook, Georg Essl, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /*********************************************/ /* Bowed Bar model */ /* by Georg Essl, 1999 */ /* For details refer to: */ /* G.Essl, P.R.Cook: "Banded Waveguides: */ /* Towards Physical Modelling of Bar */ /* Percussion Instruments", ICMC'99 */ /*********************************************/ // #include "csdl.h" #include "csoundCore.h" #include "bowedbar.h" /* Number of banded waveguide modes */ static void make_DLineN(CSOUND *csound, DLINEN *p, int32 length) { /* Writing before reading allows delays from 0 to length-1. Thus, if we want to allow a delay of max_length, we need a delay-line of length = max_length+1. */ p->length = length = length+1; csound->AuxAlloc(csound, length * sizeof(MYFLT), &p->inputs); p->inPoint = 0; p->outPoint = length >> 1; p->lastOutput = FL(0.0); } static void DLineN_setDelay(CSOUND *csound, DLINEN *p, int lag) { if (UNLIKELY(lag > p->length-1)) { /* if delay is too big, */ csound->Warning(csound, Str("DLineN: Delay length too big ... setting to " "maximum length of %d.\n"), p->length - 1); p->outPoint = p->inPoint + 1; /* force delay to max_length */ } else p->outPoint = p->inPoint - (int32) lag; /* read chases write */ while (p->outPoint<0) p->outPoint += p->length; /* modulo maximum length */ } static void DLineN_tick(DLINEN *p, MYFLT sample) /* Take one, yield one */ { MYFLT *xx = (MYFLT*)p->inputs.auxp; xx[p->inPoint++] = sample; /* Input next sample */ if (UNLIKELY(p->inPoint == p->length)) /* Check for end condition */ p->inPoint -= p->length; p->lastOutput = xx[p->outPoint++]; /* Read nxt value */ if (UNLIKELY(p->outPoint>=p->length)) /* Check for end condition */ p->outPoint -= p->length; } int bowedbarset(CSOUND *csound, BOWEDBAR *p) { int32 i; MYFLT amplitude = *p->amp * AMP_RSCALE; p->modes[0] = FL(1.0); p->modes[1] = FL(2.756); p->modes[2] = FL(5.404); p->modes[3] = FL(8.933); make_BiQuad(&p->bandpass[0]); make_BiQuad(&p->bandpass[1]); make_BiQuad(&p->bandpass[2]); make_BiQuad(&p->bandpass[3]); make_ADSR(&p->adsr); ADSR_setAllTimes(csound, &p->adsr, FL(0.02), FL(0.005), FL(0.9), FL(0.01)); if (LIKELY(*p->lowestFreq>=FL(0.0))) { /* If no init skip */ if (*p->lowestFreq!=FL(0.0)) p->length = (int32) (CS_ESR / *p->lowestFreq + FL(1.0)); else if (*p->frequency!=FL(0.0)) p->length = (int32) (CS_ESR / *p->frequency + FL(1.0)); else { csound->Warning(csound, Str("unknown lowest frequency for bowed bar -- " "assuming 50Hz\n")); p->length = (int32) (CS_ESR / FL(50.0) + FL(1.0)); } } p->nr_modes = NR_MODES; for (i = 0; idelay[i], p->length); DLineN_setDelay(csound, &p->delay[i], (int)(p->length/p->modes[i])); BiQuad_clear(&p->bandpass[i]); } /* p->gains[0] = FL(0.0); */ /* p->gains[1] = FL(0.0); */ /* p->gains[2] = FL(0.0); */ /* p->gains[3] = FL(0.0); */ p->adsr.target = FL(0.0); p->adsr.value = FL(0.0); p->adsr.rate = amplitude * FL(0.001); p->adsr.state = ATTACK; p->lastBowPos = FL(0.0); p->bowTarg = FL(0.0); p->freq = -FL(1.0); p->lastpos = -FL(1.0); p->lastpress = p->bowvel = p->velinput = FL(0.0); p->kloop = 0; p->bowTabl.offSet = p->bowTabl.slope = FL(0.0); return OK; } int bowedbar(CSOUND *csound, BOWEDBAR *p) { MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT amp = (*p->amp)*AMP_RSCALE; /* Normalise */ int32 k; int i; MYFLT maxVelocity; MYFLT integration_const = *p->integration_const; if (p->lastpress != *p->bowPress) p->bowTabl.slope = p->lastpress = *p->bowPress; if (p->freq != *p->frequency) { p->freq = *p->frequency; if (p->freq > FL(1568.0)) p->freq = FL(1568.0); p->length = (int)(CS_ESR/p->freq); p->nr_modes = NR_MODES; /* reset for frequency shift */ for (i = 0; ilength/p->modes[i]) > 4) DLineN_setDelay(csound, &p->delay[i], (int)(p->length/p->modes[i])); else { p->nr_modes = i; break; } } if (UNLIKELY(p->nr_modes==0)) return csound->InitError(csound, Str("Bowedbar: cannot have zero modes\n")); for (i=0; inr_modes; i++) { MYFLT R = FL(1.0) - p->freq * p->modes[i] * csound->pidsr; BiQuad_clear(&p->bandpass[i]); BiQuad_setFreqAndReson(p->bandpass[i], p->freq * p->modes[i], R); BiQuad_setEqualGainZeroes(p->bandpass[i]); BiQuad_setGain(p->bandpass[i], (FL(1.0)-R*R)*FL(0.5)); } } /* Bow position as well */ if (*p->position != p->lastpos) { MYFLT temp2 = *p->position * PI_F; p->gains[0] = FABS(SIN(temp2 * FL(0.5))) /* * pow(0.9,0))*/; p->gains[1] = FABS(SIN(temp2) * FL(0.9)); p->gains[2] = FABS(SIN(temp2 * FL(1.5)) * FL(0.9)*FL(0.9)); p->gains[3] = FABS(SIN(temp2 * FL(2.0)) * FL(0.9)*FL(0.9)*FL(0.9)); p->lastpos = *p->position; } if (*p->bowposition != p->lastBowPos) { /* Not sure what this control is? */ p->bowTarg += FL(0.02) * (*p->bowposition - p->lastBowPos); p->lastBowPos = *p->bowposition; ADSR_setTarget(csound, &p->adsr, p->lastBowPos); p->lastBowPos = *p->bowposition; } if (p->kloop>0 && p->h.insdshead->relesing) p->kloop=1; if ((--p->kloop) == 0) { ADSR_setReleaseRate(csound, &p->adsr, (FL(1.0) - amp) * FL(0.005)); p->adsr.target = FL(0.0); p->adsr.rate = p->adsr.releaseRate; p->adsr.state = RELEASE; } maxVelocity = FL(0.03) + (FL(0.5) * amp); if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nvelinput = FL(0.0); else p->velinput = integration_const * p->velinput; for (k=0; knr_modes; k++) { p->velinput += *p->GAIN * p->delay[k].lastOutput; } if (*p->trackVel) { p->bowvel *= FL(0.9995); p->bowvel += p->bowTarg; p->bowTarg *= FL(0.995); } else p->bowvel = ADSR_tick(&p->adsr)*maxVelocity; input = p->bowvel - p->velinput; input = input * BowTabl_lookup(csound, &p->bowTabl, input); input = input/(MYFLT)p->nr_modes; for (k=0; knr_modes; k++) { BiQuad_tick(&p->bandpass[k], input*p->gains[k] + *p->GAIN * p->delay[k].lastOutput); DLineN_tick(&p->delay[k], p->bandpass[k].lastOutput); data += p->bandpass[k].lastOutput; } ar[n] = data * AMP_SCALE * FL(20.0); /* 20 is an experimental value */ } return OK; } csound-6.10.0/Opcodes/bowedbar.h000066400000000000000000000055271321653344700164440ustar00rootroot00000000000000/* bowedbar.h: Copyright (C) 1999 Perry Cook, Georg Essl, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /*********************************************/ /* Bowed Bar model */ /* by Georg Essl, 1999 */ /* For details refer to: */ /* G.Essl, P.R.Cook: "Banded Waveguides: */ /* Towards Physical Modelling of Bar */ /* Percussion Instruments", ICMC'99 */ /*********************************************/ #if !defined(__BowedBar_h) #define __BowedBar_h #define NR_MODES (4) #include "physutil.h" #include "bowed.h" /*******************************************/ /* Non-Interpolating Delay Line */ /* Object by Perry R. Cook 1995-96. */ /* Revised by Gary Scavone, 1999. */ /* */ /* This one uses either a delay line of */ /* maximum length specified on creation */ /* or a default length of 2048 samples. */ /* A non-interpolating delay line is */ /* typically used in non-time varying */ /* (reverb) applications. */ /*******************************************/ typedef struct DLineN { AUXCH inputs; MYFLT lastOutput; int32 inPoint; int32 outPoint; int32 length; } DLINEN; typedef struct BowedBar { OPDS h; MYFLT *ar; /* Output */ MYFLT *amp, *frequency, *position, *bowPress, *GAIN; MYFLT *integration_const, *trackVel, *bowposition, *lowestFreq; BowTabl bowTabl; ADSR adsr; BiQuad bandpass[NR_MODES]; MYFLT maxVelocity; MYFLT modes[4]; DLINEN delay[4]; /* MYFLT Zs[4][2]; */ /* MYFLT coeffs[4][2]; */ /* MYFLT filtOut[4]; */ /* MYFLT filtIn[4]; */ /* MYFLT filtGain[4]; */ MYFLT freq; int nr_modes; /* Usually 4 */ int length; MYFLT gains[4]; MYFLT velinput; MYFLT bowvel, bowTarg, lastBowPos; MYFLT lastpos; /* int pluck; */ MYFLT lastpress; int kloop; } BOWEDBAR; #endif csound-6.10.0/Opcodes/brass.h000066400000000000000000000103511321653344700157600ustar00rootroot00000000000000/* brass.h: Copyright (C) 1996, 1997 Perry Cook, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /******************************************/ /* Simple Brass Instrument Model ala */ /* Cook (TBone, HosePlayer) */ /* by Perry R. Cook, 1995-96 */ /* */ /* This is a waveguide model, and thus */ /* relates to various Stanford Univ. */ /* and possibly Yamaha and other patents.*/ /* */ /* Controls: CONTROL1 = lipTension */ /* CONTROL2 = slideLength */ /* CONTROL3 = vibFreq */ /* MOD_WHEEL= vibAmt */ /******************************************/ #if !defined(__brass_h) #define __brass_h #include "physutil.h" #include /*******************************************/ /* */ /* AllPass Interpolating Delay Line */ /* Object by Perry R. Cook 1995-96 */ /* This one uses a delay line of maximum */ /* length specified on creation, and */ /* interpolates fractional length using */ /* an all-pass filter. This version is */ /* more efficient for computing static */ /* length delay lines (alpha and coeff */ /* are computed only when the length */ /* is set, there probably is a more */ /* efficient computational form if alpha */ /* is changed often (each sample)). */ /* */ /*******************************************/ typedef struct DLineA { AUXCH inputs; MYFLT lastOutput; int32 inPoint; int32 outPoint; int32 length; MYFLT alpha; MYFLT coeff; MYFLT lastIn; } DLineA; void make_DLineA(CSOUND *,DLineA *, int32 max_length); /* void DLineA_clear(DLineA *); */ int DLineA_setDelay(CSOUND *,DLineA *, MYFLT length); MYFLT DLineA_tick(DLineA *, MYFLT sample); /***********************************************/ /* Lip Filter Object by Perry R. Cook, 1995-96*/ /* The lip of the brass player has dynamics */ /* which are controlled by the mass, spring */ /* constant, and damping of the lip. This */ /* filter simulates that behavior and the */ /* transmission/reflection properties as */ /* well. See Cook TBone and HosePlayer */ /* instruments and articles. */ /***********************************************/ typedef BiQuad LipFilt; void make_LipFilt(LipFilt*); void LipFilt_clear(LipFilt*); void LipFilt_setFreq(CSOUND*,LipFilt*, MYFLT frequency); MYFLT LipFilt_tick(LipFilt*, MYFLT mouthSample,MYFLT boreSample); MYFLT LipFilt_lastOut(LipFilt*); /* ---------------------------------------------------------------------- */ typedef struct BRASS { OPDS h; MYFLT *ar; /* Output */ MYFLT *amp, *frequency; MYFLT *liptension, *dettack; MYFLT *vibFreq, *vibAmt, *ifn, *lowestFreq; FUNC *vibr; /* Table for vibrato */ MYFLT v_rate; /* Parameters for vibrato */ MYFLT v_time; /* MYFLT v_phaseOffset; */ DLineA delayLine; LipFilt lipFilter; DCBlock dcBlock; ADSR adsr; int32 length; MYFLT slideTarget; MYFLT maxPressure; MYFLT lipTarget; MYFLT frq; /* Remember previous value */ MYFLT lipT; /* and lip tension */ MYFLT limit; int kloop; } BRASS; #endif csound-6.10.0/Opcodes/buchla.c000066400000000000000000000217301321653344700161020ustar00rootroot00000000000000/* buchla.c: Copyright (C) 2014 by John ffitch, This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* buchla.c */ #include "csdl.h" #ifdef MSVC #define _USE_MATH_DEFINES #include #endif #define clip(a,b,c) (ac ? c : a) //#ifdef JPFF typedef struct { OPDS h; // results MYFLT *out1; //MYFLT *out2, *out3; // inputs MYFLT *ain1, *aenv, *knt, *kin3, *ain4, *ksw5, *ksw6; // Internal MYFLT so, sx, sd, xo; double f; } BUCHLA; static double kontrolconvert(CSOUND *csound, double in1, double in2); static int warn = 0; int poly_LPG_init(CSOUND* csound, BUCHLA *p) { p->so = p->sx = p->sd = p->xo = 0.0; if (warn==0) csound->Message(csound, "**** Experimental code ****\n"); warn++; #define C1 (1e-09) #define C2 (2.2e-10) p->f = 0.5/csound->GetSr(csound); return OK; } int poly_LPG_perf(CSOUND* csound, BUCHLA *p) { double c3, r3, rf, max_res, a, f=p->f, a1, a2, b1, b2, b3, b4; double Dmas, yx, yo, yd, tanh_xo, Dx, Do; MYFLT *x, *out1; //MYFLT *out2, *out3; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT e0dbfs = csound->Get0dBFS(csound); if (*p->ksw5 != FL(0.0)) c3 = 4.7e-09; else c3 = 0.0; //r1 = 1e3; // //#define rf (30.e3) r3 = *p->kin3; /* does this need to be audio? */ x = p->ain1; out1 = p->out1; /* out2 = p->out2; */ /* out3 = p->out3; */ //f = 2*pi * (in2+1e-3)*0.5/samplerate; b4 = c3/C2; tanh_xo= tanh(p->xo); if (UNLIKELY(offset)) { memset(out1, '\0', offset*sizeof(MYFLT)); /* memset(out2, '\0', offset*sizeof(MYFLT)); */ /* memset(out3, '\0', offset*sizeof(MYFLT)); */ } if (UNLIKELY(early)) { nsmps -= early; memset(&out1[nsmps], '\0', early*sizeof(MYFLT)); /* memset(&out2[nsmps], '\0', early*sizeof(MYFLT)); */ /* memset(&out3[nsmps], '\0', early*sizeof(MYFLT)); */ } if (*p->ksw6 != FL(0.0)) { double txo2 = tanh_xo*tanh_xo; double knt = *p->knt; for (n=offset; naenv[n], knt); max_res = 1.0*(2.0*C1*r3+(C2+c3)*(r3+rf))/(c3*r3); a = clip(p->ain4[n],0.0,max_res); a1 = 1.0/(C1*rf); a2 = -(1/rf+1/r3)/C1; b1 = 1.0/(rf*C2); b2 = -2.0/(rf*C2); b3 = 1.0/(rf*C2); Dx =1.0/(1.0-b2*f); Do =1.0/(1.0-a2*f); Dmas = 1.0/(1.0-Dx*(f*f*b3*Do*a1 + b4*f*a*(1.0-txo2)*Do*a1 - b4)); yx =(p->sx + f*b1*x[n]/e0dbfs + f*b3*Do*p->so + f*b4*(p->sd+(1.0/f)*a*(tanh_xo - p->xo*(1.0-txo2))) + b4*a*(1.0-txo2)*Do*p->so)*Dx*Dmas; yo =(p->so+f*a2*yx)*Do; yd = (p->sd+(1/f)*a*(tanh_xo - p->xo*(1.0-txo2))) + (1.0/f)*(a*((1.0-txo2))*yo - yx); p->sx += 2.0*f*(b1*x[n]/e0dbfs + b2*yx + b3*yo +b4*yd); p->so += 2.0*f*(a1*yx + a2*yo); p->sd = -(p->sd+(2.0/f)*a*(tanh_xo - p->xo*(1.0-txo2))) - (2.0/f)*(a*(1.0-txo2)*yo - yx); p->xo = yo; out1[n] = (MYFLT)yo*e0dbfs*25.0; /* JPff scaling */ /* out2[n] = (MYFLT)yx; */ /* out3[n] = (MYFLT)yd; */ } } else /* if (ksw6 < 0.5) */ { double knt = *p->knt; for (n=offset; naenv[n], knt); max_res = 1.0*(2.0*C1*r3+(C2+c3)*(r3+rf))/(c3*r3); a1 = 1.0/(C1*rf); a2 = -(1/rf+1/r3)/C1; b1 = 1.0/(rf*C2); b2 = -2.0/(rf*C2); b3 = 1.0/(rf*C2); a = clip(p->ain4[n],0.0,max_res); Dx = 1.0/(1.0-b2*f); Do = 1.0/(1.0-a2*f); Dmas = 1.0/(1.0-Dx*(f*f*b3*Do*a1 + b4*f*a*Do*a1 - b4)); yx = (p->sx + f*b1*x[n] + f*b3*Do*p->so + f*b4*p->sd + b4*a*Do*p->so)*Dx*Dmas; yo = (p->so+f*a1*yx)*Do; yd = p->sd + (1.0/f)*(a*yo-yx) ; p->sx += 2.0*f*(b1*x[n] + b2*yx + b3*yo +b4*yd); p->so += 2.0*f*(a1*yx + a2*yo); p->sd = -p->sd - (2.0/f)*(a*yo - yx); out1[n] = yo*25.0*e0dbfs; /* JPff scaling */ /* out2[n] = yx; */ /* out3[n] = yd; */ } } return OK; } //#endif typedef struct { OPDS h; MYFLT *out; MYFLT *inp; MYFLT *up; MYFLT *down; double s1; double a_base; double t_up; double t_down; } VACTROL; int vactrol_init(CSOUND *csound, VACTROL* p) { p->s1 = 0; p->a_base = 1000.0*M_PI/(csound->GetSr(csound)); p->t_down = *p->downdown; p->t_up = *p->upup; return OK; } int vactrol_perf(CSOUND *csound, VACTROL* p) { double s1 = p->s1; double a_base = p->a_base; double T_DOWN = p->t_down; // Fall time double T_UP = p->t_up; // Rise time uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *in = p->inp; MYFLT *out = p->out; double e0db = csound->Get0dBFS(csound); if (UNLIKELY(offset)) { memset(out, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; n= 0.0) x = dsl*a_up/(1.0+a_up); else x = dsl*a_down/(1.0+a_down); y = x + s1; s1 = y + x; out[n] = (MYFLT)y*e0db; /* JPff extra scale */ } p->s1 = s1; return OK; } //#ifdef JPFF //Nonlinear control circuit maps V_b to R_f (Vactrol Resistance) static double kontrolconvert(CSOUND *csound, double in1, double in2) { double R1, R2; double offset = 0.9999*in2 + 0.0001; double zerodb = csound->Get0dBFS(csound); double V3, Ia, If, Ifbound1, Ifbound2, Ifbound3; double Vb = in1/zerodb; double ans; #define scale (0.48) // This value is tuned for appropriate input range. // Constants #define A (3.4645912) #define B (1136.2129956) #define G (2.0e5) #define Ifmax (40.0e-3) #define Ifmin (10.1e-6) #define R2max (10.0e3) #define R3 (150.0e3) #define R4 (470.0e3) #define R5 (100.0e3) #define R6max (20.0e3) #define R7 (33.0e3) #define R8 (4.7e3) #define R9 (470) #define VB (3.9) #define VF (0.7) #define VT (26.0e-3) #define Vs (15.0) #define k0 (1.468e2) #define k1 (4.9202e-1) #define k2 (4.1667e-4) #define k3 (7.3915e-9) #define kl (6.3862) #define n (3.9696) #define gamma (0.0001) #define R6 (scale * R6max) #define alpha (1.0 + (R6+R7) * (1/R3 + 1/R5)) #define beta (((1/alpha) - 1)/(R6 + R7) - 1/R8) #define bound1 (600* alpha *n*VT/(G*(R6+R7-1/(alpha*beta)))) //Inputs R1 = (1-offset); R2 = offset; Ia = Vb/R5 + Vs/(R3*(1+R1/R2)); if (Ia <= -bound1) { V3 = -Ia/(alpha*beta); } else if ( Ia < bound1) { double x, w; x = G*Ia*(R6+R7-1/(alpha*beta))/(alpha*n*VT); w = k0 + k1*x + k2*x*x+ k3*x*x*x; V3 = -(alpha/G)*n*VT*w - Ia/(alpha*beta); } else { V3 = kl*alpha/G*n*VT-Ia*(R6+R7); } Ifbound1 = alpha*(Ifmin - beta*V3); Ifbound2 = VB/(R6+R7); Ifbound3 = (gamma*G*VB + alpha*R9*(VB*beta+Ifmax))/(gamma*G*(R6+R7) + R9); if (Ia <= Ifbound1) { If = Ifmin; } else if (Ia <= Ifbound2) { If = beta * V3 + Ia/alpha; } else if (Ia <= Ifbound3) { If = gamma * G *(Ia*(R6+R7) - VB)/(alpha*R9) - beta*VB + Ia/alpha; } else { If = Ifmax; } ans = (B + A / pow(If,1.4)); //printf("%f,%f (%f/%f/%f) -> %f\n", in1, in2, A, B, pow(If, 1.4), ans); return ans; } //#endif #define S sizeof static OENTRY buchla_localops[] = { //#ifdef JPFF { "buchla", S(BUCHLA), 0, 5, "a", "aakkaPP", (SUBR)poly_LPG_init, NULL, (SUBR)poly_LPG_perf }, //#endif { "vactrol", S(VACTROL), 0, 5, "a", "ajj", (SUBR)vactrol_init, NULL, (SUBR)vactrol_perf } }; LINKAGE_BUILTIN(buchla_localops) csound-6.10.0/Opcodes/butter.c000066400000000000000000000110401321653344700161420ustar00rootroot00000000000000/* butter.c: Copyright (C) 1994 Paris Smaragdis, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Butterworth filters coded by Paris Smaragdis 1994 */ /* Berklee College of Music Csound development team */ /* Copyright (c) May 1994. All rights reserved */ #include "stdopcod.h" typedef struct { OPDS h; MYFLT *sr, *ain, *kfc, *istor; MYFLT lkf; double a[8]; } BFIL; typedef struct { OPDS h; MYFLT *sr, *ain, *kfo, *kbw, *istor; MYFLT lkf, lkb; double a[8]; } BBFIL; #include #define ROOT2 (1.4142135623730950488) static void butter_filter(uint32_t, uint32_t, MYFLT *, MYFLT *, double *); int butset(CSOUND *csound, BFIL *p) /* Hi/Lo pass set-up */ { if (*p->istor==FL(0.0)) { p->a[6] = p->a[7] = 0.0; p->lkf = FL(0.0); } return OK; } static int hibut(CSOUND *csound, BFIL *p) /* Hipass filter */ { MYFLT *out, *in; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nsmps = CS_KSMPS; in = p->ain; out = p->sr; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } if (*p->kfc <= FL(0.0)) { memcpy(&out[offset], &in[offset], (nsmps-offset)*sizeof(MYFLT)); return OK; } if (*p->kfc != p->lkf) { double *a, c; a = p->a; p->lkf = *p->kfc; c = tan((double)(csound->pidsr * p->lkf)); a[1] = 1.0 / ( 1.0 + ROOT2 * c + c * c); a[2] = -(a[1] + a[1]); a[3] = a[1]; a[4] = 2.0 * ( c*c - 1.0) * a[1]; a[5] = ( 1.0 - ROOT2 * c + c * c) * a[1]; } butter_filter(nsmps, offset, in, out, p->a); return OK; } static int lobut(CSOUND *csound, BFIL *p) /* Lopass filter */ { MYFLT *out, *in; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nsmps = CS_KSMPS; in = p->ain; out = p->sr; if (*p->kfc <= FL(0.0)) { memset(out, 0, nsmps*sizeof(MYFLT)); return OK; } if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } if (*p->kfc != p->lkf) { double *a, c; a = p->a; p->lkf = *p->kfc; c = 1.0 / tan((double)(csound->pidsr * p->lkf)); a[1] = 1.0 / ( 1.0 + ROOT2 * c + c * c); a[2] = a[1] + a[1]; a[3] = a[1]; a[4] = 2.0 * ( 1.0 - c*c) * a[1]; a[5] = ( 1.0 - ROOT2 * c + c * c) * a[1]; } butter_filter(nsmps, offset, in, out, p->a); return OK; } /* Filter loop */ static void butter_filter(uint32_t n, uint32_t offset, MYFLT *in, MYFLT *out, double *a) { double t, y; uint32_t nn; for (nn=offset; nnAppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/cellular.c000066400000000000000000000074421321653344700164530ustar00rootroot00000000000000 /* pitch.c: Copyright (C) 2011 Gleb Rogozinsky This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csdl.h" // classical 1-D Cellular Automaton by Gleb Rogozinsky. // It is the modified version of vcella opcode by Gabriel Maldonado typedef struct { OPDS h; MYFLT *ktrig, *kreinit, *ioutFunc, *initStateFunc, *iRuleFunc, *ielements; MYFLT *currLine, *outVec, *initVec, *ruleVec; int elements, NewOld; AUXCH auxch; } CELL; static int cell_set(CSOUND *csound,CELL *p) { FUNC *ftp; int elements=0; MYFLT *currLine, *initVec = NULL; if (LIKELY((ftp = csound->FTnp2Find(csound,p->ioutFunc)) != NULL)) { p->outVec = ftp->ftable; elements = (p->elements = (int) *p->ielements); if (UNLIKELY( elements > (int)ftp->flen )) return csound->InitError(csound, Str("cell: invalid num of elements")); } else return csound->InitError(csound, Str("cell: invalid output table")); if (LIKELY((ftp = csound->FTnp2Find(csound,p->initStateFunc)) != NULL)) { initVec = (p->initVec = ftp->ftable); if (UNLIKELY(elements > (int)ftp->flen )) return csound->InitError(csound, Str("cell: invalid num of elements")); } else return csound->InitError(csound, Str("cell: invalid initial state table")); if (LIKELY((ftp = csound->FTnp2Find(csound,p->iRuleFunc)) != NULL)) { p->ruleVec = ftp->ftable; } else return csound->InitError(csound, Str("cell: invalid rule table")); if (p->auxch.auxp == NULL) csound->AuxAlloc(csound, elements * sizeof(MYFLT) * 2, &p->auxch); currLine = (p->currLine = (MYFLT *) p->auxch.auxp); p->NewOld = 0; memcpy(currLine, initVec, sizeof(MYFLT)*elements); /* do { */ /* *currLine++ = *initVec++; */ /* } while (--elements); */ return OK; } static int cell(CSOUND *csound,CELL *p) { if (*p->kreinit) { p->NewOld = 0; memcpy(p->currLine, p->initVec, sizeof(MYFLT)*p->elements); /* do { */ /* *currLine++ = *initVec++; */ /* } while (--elements); */ } if (*p->ktrig) { int j, elements = p->elements, jm1; MYFLT *actual, *previous, *outVec = p->outVec , *ruleVec = p->ruleVec; previous = &(p->currLine[elements * p->NewOld]); p->NewOld += 1; p->NewOld %= 2; actual = &(p->currLine[elements * p->NewOld]); // Cellular Engine for (j=0; j < elements; j++) { jm1 = (j < 1) ? elements-1 : j-1; outVec[j] = previous[j]; actual[j] = ruleVec[(int)(previous[jm1]*4 + previous[j]*2 + previous[(j+1) % elements])]; } } else { int elements = p->elements; MYFLT *actual = &(p->currLine[elements * !(p->NewOld)]); memcpy(p->outVec, actual, sizeof(MYFLT)*elements); /* do { */ /* *outVec++ = *actual++ ; */ /* } while (--elements); */ } return OK; } #define S sizeof static OENTRY localops[] = { {"cell", S(CELL), TB, 3, "", "kkiiii",(SUBR)cell_set, (SUBR)cell } }; LINKAGE // Author: Gleb Rogozinsky, October 2011 csound-6.10.0/Opcodes/chua/000077500000000000000000000000001321653344700154155ustar00rootroot00000000000000csound-6.10.0/Opcodes/chua/ChuaOscillator.cpp000066400000000000000000000500631321653344700210410ustar00rootroot00000000000000/* This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // function TimeSeries = chuacc(L,R0,C2,G,Ga,Gb,C1,E,x0,y0,z0,dataset_size,step_size) // %0.00945,7.5,2e-007,0.00105,0,-0.00121,1.5e-008,1.76e-005,0,-0.1,0.1,2500,5e-6 // % Syntax: TimeSeries=chua(L,R0,C2,G,Ga,Gb,C1,E,x0,y0,z0,dataset_size,step_size) // % ______________________________________ // % // % Chua's oscillator is described by a set of three // % ordinary differential equations called Chua's equations: // % // % dI3 R0 1 // % --- = - -- I3 - - V2 // % dt L L // % // % dV2 1 G // % --- = -- I3 - -- (V2 - V1) // % dt C2 C2 // % // % dV1 G 1 // % --- = -- (V2 - V1) - -- f(V1) // % dt C1 C1 // % // % where // % // % f(V1) = Gb V1 + - (Ga - Gb)(|V1 + E| - |V1 - E|) // % // % A solution of these equations (I3,V2,V1)(t) starting from an // % initial state (I3,V2,V1)(0) is called a trajectory of Chua's // % oscillator. // % // % This function uses a RungeKutta integration method optimised for the chua // % paradigm // % // % Reference: // % ABC - Adventures in Bifurication & Chaos ... Prof M.P Kennedy 1993 // % // % James McEvoy, Tom Murray // % // % University e-mail: 99375940@student.ucc.ie // % Lifetime e-mail: sacevoy@eircom.net // % Homepage: http://www.sacevoy.com // % // % 2 Nov 2002 // % Models Initial Variables // %------------------------- // %Initial Conditions set by x0,y0,z0 // TimeSeries = [x0, y0, z0]'; % models initial conditions // %x0 = I3, y0 = V2, z0 = V1 from datafiles // % Optimized Runge-Kutta Variables // %-------------------------------- // h = step_size; %*(G/C2); // h2 = (h)*(.5); // h6 = (h)/(6); // sys_variables(9:12) = [1.76e-005,0,-0.00121,0]; // k1 = [0 0 0]'; // k2 = [0 0 0]'; // k3 = [0 0 0]'; // k4 = [0 0 0]'; // M = [0 0 0]'; // % Calculate Time Series // %---------------------- // % values have to be switched around // M(1) = TimeSeries(3); %V1 // M(2) = TimeSeries(2); %V2 // M(3) = TimeSeries(1); %I3 // for i=1:dataset_size // % Runge Kutta // % Round One // k1(1) = (G*(M(2) - M(1)) - gnor(M(1),sys_variables))/C1; // k1(2) = (G*(M(1) - M(2)) + M(3))/C2; // k1(3) = (-(M(2) + R0*M(3)))/L; // % Round Two // k2(1) = (G*(M(2) + h2*k1(2) - (M(1) + h2*k1(1))) - gnor(M(1) + // h2*k1(1),sys_variables))/C1; // k2(2) = (G*(M(1) + h2*k1(1) - (M(2) + h2*k1(2))) + M(3) + h2*k1(3))/C2; // k2(3) = (-(M(2) + h2*k1(2) + R0*(M(3) + h2*k1(3))))/L; // % Round Three // k3(1) = (G*(M(2) + h2*k2(2) - (M(1) + h2*k2(1))) - gnor(M(1) + // h2*k2(1),sys_variables))/C1; // k3(2) = (G*(M(1) + h2*k2(1) - (M(2) + h2*k2(2))) + M(3) + h2*k2(3))/C2; // k3(3) = (-(M(2) + h2*k2(2) + R0*(M(3) + h2*k2(3))))/L; // % Round Four // k4(1) = (G*(M(2) + h*k3(2) - (M(1) + h*k3(1))) - gnor(M(1) + // h*k3(1),sys_variables))/C1; // k4(2) = (G*(M(1) + h*k3(1) - (M(2) + h*k3(2))) + M(3) + h*k3(3))/C2; // k4(3) = (-(M(2) + h*k3(2) + R0*(M(3) + h*k3(3))))/L; // %Finishes integration and assigns values to M(1), // M = M + (k1 + 2*k2 + 2*k3 + k4)*(h6); // %M(2) and M(3) // TimeSeries(3,i+1) = M(1); %TimeSeries 3 is V1 // TimeSeries(2,i+1) = M(2); %TimeSeries 2 is V2 // TimeSeries(1,i+1) = M(3); %TimeSeries 1 is I3 // i=i+1; // end // %gnor Calculates the cubic nonlinearity // function gnor = gnor(x,sys_variables) // a = sys_variables(9); // b = sys_variables(10); // c = sys_variables(11); // d = sys_variables(12); // gnor = a*(x.^3) + b*(x.^2) + c*x + d; #include #include #include using namespace csound; class ChuasOscillatorCubic : public OpcodeNoteoffBase { public: // OUTPUTS MYFLT *I3; MYFLT *V2; MYFLT *V1; // INPUTS // % L,R0,C2,G,Ga,Gb,E,C1,a,b,c,d // sys_variables = [system_vars(5:12),system_vars(23:26)]; // % x0,y0,z0,dataset_size,step_size // integ_variables = [system_vars(14:16),system_vars(1:2)]; // function TimeSeries = chuacc(L,R0,C2,G,Ga,Gb,C1,E,x0,y0,z0, // dataset_size,step_size) // Circuit elements. MYFLT *L_; MYFLT *R0_; MYFLT *C2_; MYFLT *G_; // Omit Ga, not used with cubic nonlinearity. // Omit Gb, not used with cubic nonlinearity. MYFLT *C1_; // Omit E, not used with cubic nonlinearity. // Initial values... // %x0 = I3, y0 = V2, z0 = V1 from datafiles MYFLT *I3_; MYFLT *V2_; MYFLT *V1_; MYFLT *step_size_; // STATE // Runge-Kutta step sizes. MYFLT h; MYFLT h2; MYFLT h6; // Runge-Kutta slopes. Eigen::VectorXd k1; Eigen::VectorXd k2; Eigen::VectorXd k3; Eigen::VectorXd k4; // Temporary value. Eigen::VectorXd M; // Polynomial for nonlinear element. MYFLT a; MYFLT b; MYFLT c; MYFLT d; size_t ksmps; public: int init(CSOUND *csound) { if (!csound->GetReinitFlag(csound) && !csound->GetTieFlag(csound)) { csound->RegisterDeinitCallback(csound, this, ¬eoff_); } // h = step_size; %*(G/C2); h = *step_size_; // h2 = (h)*(.5); h2 = h / 2.0; // h6 = (h)/(6); h6 = h / 6.0; // NOTE: The original MATLAB code uses 1-based indexing. // Although the MATLAB vectors are columns, // these are rows; it doesn't matter here. // k1 = [0 0 0]'; k1.resize(4); // k2 = [0 0 0]'; k2.resize(4); // k3 = [0 0 0]'; k3.resize(4); // k4 = [0 0 0]'; k4.resize(4); // M = [0 0 0]'; M.resize(4); // % values have to be switched around // M(1) = TimeSeries(3); %V1 M(1) = *V1_; // M(2) = TimeSeries(2); %V2 M(2) = *V2_; // M(3) = TimeSeries(1); %I3 M(3) = *I3_; // sys_variables(9:12) = [1.76e-005,0,-0.00121,0]; a = 1.76e-5; b = 0.0; c = -0.00121; d = 0.0; ksmps = opds.insdshead->ksmps; warn(csound, "ChuasOscillatorCubic::init: L: %f R0: %f C2: %f G: %f" " C1: %f V1: %f V2: %f I3: %f step: %f\n", *L_, *R0_, *C2_, *G_, *C1_, M(1), M(2), M(3), h); warn(csound, "ChuasOscillatorCubic::init: a: %f b: %f c: %f d: %f\n", a, b, c, d); return OK; } int noteoff(CSOUND *csound) { warn(csound, "ChuasOscillatorCubic::noteoff\n"); k1.resize(0); k2.resize(0); k3.resize(0); k4.resize(0); M.resize(0); return OK; } static int noteoff_(CSOUND *csound, void *opcode) { return ((ChuasOscillatorCubic *)opcode)->noteoff(csound); } int kontrol(CSOUND *csound) { // NOTE: MATLAB code goes into eigen3 C++ code pretty straightforwardly, // probaby by design. This is very handy and should prevent mistakes. // Start with aliases for the Csound inputs, in order // to preserve the clarity of the original code. uint32_t offset = opds.insdshead->ksmps_offset; uint32_t early = opds.insdshead->ksmps_no_end; uint32_t nsmps = opds.insdshead->ksmps; if (UNLIKELY(offset)) { memset(I3, '\0', offset*sizeof(MYFLT)); memset(V1, '\0', offset*sizeof(MYFLT)); memset(V2, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { memset(&I3[nsmps-early], '\0', early*sizeof(MYFLT)); memset(&V1[nsmps-early], '\0', early*sizeof(MYFLT)); memset(&V2[nsmps-early], '\0', early*sizeof(MYFLT)); } MYFLT &L = *L_; MYFLT &R0 = *R0_; MYFLT &C2 = *C2_; MYFLT &G = *G_; MYFLT &C1 = *C1_; // Recompute Runge-Kutta step sizes if necessary. if (h != *step_size_) { // h = step_size; %*(G/C2); h = *step_size_; // h2 = (h)*(.5); h2 = h / 2.0; // h6 = (h)/(6); h6 = h / 6.0; } // Standard 4th-order Runge-Kutta integration. for (size_t i = 0; i < ksmps; i++) { // TimeSeries(3,i+1) = M(1); %TimeSeries 3 is V1 // TimeSeries(2,i+1) = M(2); %TimeSeries 2 is V2 // TimeSeries(1,i+1) = M(3); %TimeSeries 1 is I3 V1[i] = M(1); V2[i] = M(2); I3[i] = M(3); // std::printf("%4d V1: %f V2: %f I3: %f\n", i, V1[i], V2[i], I3[i]); // Runge Kutta // Round One k1(1) = (G*(M(2) - M(1)) - gnor(M(1)))/C1; k1(2) = (G*(M(1) - M(2)) + M(3))/C2; k1(3) = (-1.0*(M(2) + R0*M(3)))/L; // Round Two k2(1) = (G*(M(2) + h2*k1(2) - (M(1) + h2*k1(1))) - gnor(M(1) + h2*k1(1)))/C1; k2(2) = (G*(M(1) + h2*k1(1) - (M(2) + h2*k1(2))) + M(3) + h2*k1(3))/C2; k2(3) = (- (M(2) + h2*k1(2) + R0*(M(3) + h2*k1(3))))/L; // Round Three k3(1) = (G*(M(2) + h2*k2(2) - (M(1) + h2*k2(1))) - gnor(M(1) + h2*k2(1)))/C1; k3(2) = (G*(M(1) + h2*k2(1) - (M(2) + h2*k2(2))) + M(3) + h2*k2(3))/C2; k3(3) = (- (M(2) + h2*k2(2) + R0*(M(3) + h2*k2(3))))/L; // Round Four k4(1) = (G*(M(2) + h*k3(2) - (M(1) + h*k3(1))) - gnor(M(1) + h*k3(1)))/C1; k4(2) = (G*(M(1) + h*k3(1) - (M(2) + h*k3(2))) + M(3) + h*k3(3))/C2; k4(3) = (- (M(2) + h*k3(2) + R0*(M(3) + h*k3(3))))/L; // Finishes integration and assigns values to M M = M + (k1 + 2*k2 + 2*k3 + k4)*(h6); } return OK; } MYFLT gnor(MYFLT x) { // Odd to use std::pow here for integer powers when there is intpow function return (a * std::pow(x, FL(3.0))) + (b * std::pow(x, FL(2.0))) + (c * x) + d; } }; // %%%%%%%%%%%%%%%%%%%%%% // % SubFunction (James)% // %%%%%%%%%%%%%%%%%%%%%% // function TimeSeries = chua(sys_variables,integ_variables) // % Syntax: TimeSeries=chua(sys_variables,integ_variables) // % sys_variables = [L,R0,C2,G,Ga,Gb,E,C1]; // % integ_variables = [x0,y0,z0,dataset_size,step_size]; // % Models Initial Variables // %------------------------- // L = sys_variables(1); // R0 = sys_variables(2); // C2 = sys_variables(3); // G = sys_variables(4); // Ga = sys_variables(5); // Gb = sys_variables(6); // E = sys_variables(7); // C1 = sys_variables(8); // x0 = integ_variables(1); // y0 = integ_variables(2); // z0 = integ_variables(3); // dataset_size = integ_variables(4); // step_size = integ_variables(5); // TimeSeries = [x0, y0, z0]'; % models initial conditions // % Optimized Runge-Kutta Variables // %-------------------------------- // h = step_size*G/C2; // h2 = (h)*(.5); // h6 = (h)/(6); // anor = Ga/G; // bnor = Gb/G; // bnorplus1 = bnor + 1; // alpha = C2/C1; // beta = C2/(L*G*G); // gammaloc = (R0*C2)/(L*G); // bh = beta*h; // bh2 = beta*h2; // ch = gammaloc*h; // ch2 = gammaloc*h2; // omch2 = 1 - ch2; // k1 = [0 0 0]'; // k2 = [0 0 0]'; // k3 = [0 0 0]'; // k4 = [0 0 0]'; // M = [0 0 0]'; // % Calculate Time Series // %---------------------- // M(1) = TimeSeries(3)/E; // M(2) = TimeSeries(2)/E; // M(3) = TimeSeries(1)/(E*G); // for i=1:dataset_size // % Runge Kutta // % Round One // k1(1) = alpha*(M(2) - bnorplus1*M(1) - (.5)*(anor - bnor)*(abs(M(1) + 1) // - abs(M(1) - 1))); // k1(2) = M(1) - M(2) + M(3); // k1(3) = -beta*M(2) - gammaloc*M(3); // % Round Two // temp = M(1) + h2*k1(1); // k2(1) = alpha*(M(2) + h2*k1(2) - bnorplus1*temp - // (.5)*(anor - bnor)*(abs(temp + 1) - abs(temp - 1))); // k2(2) = k1(2) + h2*(k1(1) - k1(2) + k1(3)); // k2(3) = omch2*k1(3) - bh2*k1(2); // % Round Three // temp = M(1) + h2*k2(1); // k3(1) = alpha*(M(2) + h2*k2(2) - bnorplus1*temp - // (.5)*(anor - bnor)*(abs(temp + 1) - abs(temp - 1))); // k3(2) = k1(2) + h2*(k2(1) - k2(2) + k2(3)); // k3(3) = k1(3) - bh2*k2(2) - ch2*k2(3); // % Round Four // temp = M(1) + h*k3(1); // k4(1) = alpha*(M(2) + h*k3(2) - bnorplus1*temp - // (.5)*(anor - bnor)*(abs(temp + 1) - abs(temp - 1))); // k4(2) = k1(2) + h*(k3(1) - k3(2) + k3(3)); // k4(3) = k1(3) - bh*k3(2) - ch*k3(3); // M = M + (k1 + 2*k2 + 2*k3 + k4)*(h6); // TimeSeries(3,i+1) = E*M(1); // TimeSeries(2,i+1) = E*M(2); // TimeSeries(1,i+1) = (E*G)*M(3); // i=i+1; // end class ChuasOscillatorPiecewise : public OpcodeNoteoffBase { public: // OUTPUTS MYFLT *I3; MYFLT *V2; MYFLT *V1; // INPUTS // sys_variables = system_vars(5:12); % L,R0,C2,G,Ga,Gb,E,C1 // % x0,y0,z0,dataset_size,step_size // integ_variables = [system_vars(14:16),system_vars(1:2)]; // function TimeSeries = chuacc(L,R0,C2,G,Ga,Gb,C1,E,x0,y0,z0, // dataset_size,step_size) // Circuit elements. MYFLT *L_; MYFLT *R0_; MYFLT *C2_; MYFLT *G_; MYFLT *Ga_; MYFLT *Gb_; MYFLT *E_; MYFLT *C1_; // Initial values... MYFLT *I3_; MYFLT *V2_; MYFLT *V1_; MYFLT *step_size_; // STATE // Runge-Kutta step sizes. MYFLT h; MYFLT h2; MYFLT h6; // Runge-Kutta slopes. Eigen::VectorXd k1; Eigen::VectorXd k2; Eigen::VectorXd k3; Eigen::VectorXd k4; // Temporary value. Eigen::VectorXd M; // Other variables. MYFLT step_size; MYFLT anor; MYFLT bnor; MYFLT bnorplus1; MYFLT alpha; MYFLT beta; MYFLT gammaloc; MYFLT bh; MYFLT bh2; MYFLT ch; MYFLT ch2; MYFLT omch2; MYFLT temp; size_t ksmps; int init(CSOUND *csound) { if (!csound->GetReinitFlag(csound) && !csound->GetTieFlag(csound)) { csound->RegisterDeinitCallback(csound, this, ¬eoff_); } // NOTE: The original MATLAB code uses 1-based indexing. // Although the MATLAB vectors are columns, // these are rows; it doesn't matter here. // k1 = [0 0 0]'; k1.resize(4); // k2 = [0 0 0]'; k2.resize(4); // k3 = [0 0 0]'; k3.resize(4); // k4 = [0 0 0]'; k4.resize(4); // M = [0 0 0]'; M.resize(4); // M(1) = TimeSeries(3)/E; M(1) = *V1_ / *E_; // M(2) = TimeSeries(2)/E; M(2) = *V2_ / *E_; // M(3) = TimeSeries(1)/(E*G); M(3) = *I3_ / (*E_ * *G_); ksmps = opds.insdshead->ksmps; warn(csound, "ChuasOscillatorPiecewise::init: L: %f R0: %f C2: %f G: " "%f Ga: %f Gb: %f E: %f C1: %f iI3: %f iV2:" " %f iV1: %f step: %f\n", *L_, *R0_, *C2_, *G_, *Ga_, *Gb_, *E_, *C1_, *I3_, *V2_, *V1_, step_size); return OK; } int noteoff(CSOUND *csound) { warn(csound, "ChuasOscillatorPiecewise::noteoff\n"); k1.resize(0); k2.resize(0); k3.resize(0); k4.resize(0); M.resize(0); return OK; } static int noteoff_(CSOUND *csound, void *opcode) { return ((ChuasOscillatorPiecewise *)opcode)->noteoff(csound); } int kontrol(CSOUND *csound) { // NOTE: MATLAB code goes into eigen3 C++ code pretty straightforwardly, // probaby by design. This is very handy and should prevent mistakes. // Start with aliases for the Csound inputs, in order // to preserve the clarity of the original code. uint32_t offset = opds.insdshead->ksmps_offset; uint32_t early = opds.insdshead->ksmps_no_end; if (UNLIKELY(offset)) { memset(I3, '\0', offset*sizeof(MYFLT)); memset(V1, '\0', offset*sizeof(MYFLT)); memset(V2, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { ksmps -= early; memset(&I3[ksmps], '\0', early*sizeof(MYFLT)); memset(&V1[ksmps], '\0', early*sizeof(MYFLT)); memset(&V2[ksmps], '\0', early*sizeof(MYFLT)); } MYFLT &L = *L_; MYFLT &R0 = *R0_; MYFLT &C2 = *C2_; MYFLT &G = *G_; MYFLT &Ga = *Ga_; MYFLT &Gb = *Gb_; MYFLT &E = *E_; MYFLT &C1 = *C1_; // Recompute Runge-Kutta stuff every kperiod in case kontrol variables // have changed. step_size = *step_size_; // h = step_size*G/C2; h = step_size * G / C2; // h2 = (h)*(.5); h2 = h / 2.0; // h6 = (h)/(6); h6 = h / 6.0; // anor = Ga/G; anor = Ga / G; // bnor = Gb/G; bnor = Gb / G; // bnorplus1 = bnor + 1; bnorplus1 = bnor + 1.0; // alpha = C2/C1; alpha = C2 / C1; // beta = C2/(L*G*G); beta = C2 / (L * G * G); // gammaloc = (R0*C2)/(L*G); gammaloc = (R0 * C2) / (L * G); // bh = beta*h; bh = beta * h; // bh2 = beta*h2; bh2 = beta * h2; // ch = gammaloc*h; ch = gammaloc * h; // ch2 = gammaloc*h2; ch2 = gammaloc * h2; // omch2 = 1 - ch2; omch2 = 1.0 - ch2; // Standard 4th-order Runge-Kutta integration. for (size_t i = offset; i < ksmps; i++) { // Stage 1. k1(1) = alpha*(M(2) - bnorplus1*M(1) - (.5)*(anor - bnor)*(abs(M(1) + 1) - abs(M(1) - 1))); k1(2) = M(1) - M(2) + M(3); k1(3) = -beta*M(2) - gammaloc*M(3); // Stage 2. temp = M(1) + h2*k1(1); k2(1) = alpha*(M(2) + h2*k1(2) - bnorplus1*temp - (.5)*(anor - bnor)*(abs(temp + 1) - abs(temp - 1))); k2(2) = k1(2) + h2*(k1(1) - k1(2) + k1(3)); k2(3) = omch2*k1(3) - bh2*k1(2); // Stage 3. temp = M(1) + h2*k2(1); k3(1) = alpha*(M(2) + h2*k2(2) - bnorplus1*temp - (.5)*(anor - bnor)*(abs(temp + 1) - abs(temp - 1))); k3(2) = k1(2) + h2*(k2(1) - k2(2) + k2(3)); k3(3) = k1(3) - bh2*k2(2) - ch2*k2(3); // Stage 4. temp = M(1) + h*k3(1); k4(1) = alpha*(M(2) + h*k3(2) - bnorplus1*temp - (.5)*(anor - bnor)*(abs(temp + 1) - abs(temp - 1))); k4(2) = k1(2) + h*(k3(1) - k3(2) + k3(3)); k4(3) = k1(3) - bh*k3(2) - ch*k3(3); M = M + (k1 + 2*k2 + 2*k3 + k4)*(h6); // TimeSeries(3,i+1) = E*M(1); V1[i] = E * M(1); // TimeSeries(2,i+1) = E*M(2); V2[i] = E * M(2); // TimeSeries(1,i+1) = (E*G)*M(3); I3[i] = (E * G) * M(3); // warn(csound, "%4d V1: %f V2: %f I3: %f\n", i, V1[i], V2[i], I3[i]); } return OK; } }; extern "C" { OENTRY oentries[] = { // { // (char*)"chuac", // sizeof(ChuasOscillatorCubic), // 0, // 5, // // kL, kR0, kC2, kG, kC1, iI3, iV2, iV1, kstep_size // // 0.00945, 7.5, 2e-007, 0.00105, 1.5e-008, 0, -0.1, 0.1, 5e-6 // (char*)"aaa", // (char*)"kkkkkiiik", // (SUBR) ChuasOscillatorCubic::init_, // 0, // (SUBR) ChuasOscillatorCubic::kontrol_, // }, { (char*)"chuap", sizeof(ChuasOscillatorPiecewise), 0, 5, // kL, kR0, kC2, kG, kGa, kGb, kE, kC1, // iI3, iV2, iV1, kstep_size // 0.00945, 7.5, 2e-007, 0.00105, 0, -0.00121, 1.76e-005, 1.5e-008, // 0, -0.1, 0.1, 5e-6 (char*)"aaa", (char*)"kkkkkkkkiiik", (SUBR) ChuasOscillatorPiecewise::init_, 0, (SUBR) ChuasOscillatorPiecewise::kontrol_, }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; PUBLIC int csoundModuleCreate(CSOUND *csound) { return 0; } PUBLIC int csoundModuleInit(CSOUND *csound) { int status = 0; for(OENTRY *oentry = &oentries[0]; oentry->opname; oentry++) { status |= csound->AppendOpcode(csound, oentry->opname, oentry->dsblksiz, oentry->flags, oentry->thread, oentry->outypes, oentry->intypes, (int (*)(CSOUND*,void*)) oentry->iopadr, (int (*)(CSOUND*,void*)) oentry->kopadr, (int (*)(CSOUND*,void*)) oentry->aopadr); } return status; } PUBLIC int csoundModuleDestroy(CSOUND *csound) { return 0; } } csound-6.10.0/Opcodes/clarinet.h000066400000000000000000000071041321653344700164510ustar00rootroot00000000000000/* clarinet.h: Copyright (C) 1996, 1997 Perry Cook, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /******************************************/ /* Clarinet model ala Smith */ /* after McIntyre, Schumacher, Woodhouse */ /* by Perry Cook, 1995-96 */ /* Recoded for Csound by John ffitch */ /* November 1997 */ /* */ /* This is a waveguide model, and thus */ /* relates to various Stanford Univ. */ /* and possibly Yamaha and other patents.*/ /* */ /******************************************/ #if !defined(__Clarinet_h) #define __Clarinet_h #include "physutil.h" /**********************************************/ /* One break point linear reed table object */ /* by Perry R. Cook, 1995-96 */ /* Consult McIntyre, Schumacher, & Woodhouse */ /* Smith, Hirschman, Cook, Scavone, */ /* more for information. */ /**********************************************/ typedef struct ReedTabl { MYFLT offSet; MYFLT slope; } ReedTabl; /*******************************************/ /* One Zero Filter Class, */ /* by Perry R. Cook, 1995-96 */ /* The parameter gain is an additional */ /* gain parameter applied to the filter */ /* on top of the normalization that takes */ /* place automatically. So the net max */ /* gain through the system equals the */ /* value of gain. sgain is the combina- */ /* tion of gain and the normalization */ /* parameter, so if you set the poleCoeff */ /* to alpha, sgain is always set to */ /* gain / (1.0 - fabs(alpha)). */ /*******************************************/ typedef struct OneZero { MYFLT gain; /* Filter subclass */ MYFLT inputs; MYFLT zeroCoeff; MYFLT sgain; } OneZero; void make_OneZero(OneZero*); MYFLT OneZero_tick(OneZero*, MYFLT); void OneZero_setGain(OneZero*, MYFLT); void OneZero_setCoeff(OneZero*, MYFLT); void OneZero_print(CSOUND*, OneZero*); /* ********************************************************************** */ typedef struct CLARIN { OPDS h; MYFLT *ar; /* Output */ MYFLT *amp, *frequency; MYFLT *reedStffns, *attack, *dettack, *noiseGain, *vibFreq; MYFLT *vibAmt, *ifn, *lowestFreq; FUNC *vibr; /* Table for vibrato */ MYFLT v_rate; /* Parameters for vibrato */ MYFLT v_time; /* MYFLT v_phaseOffset; */ DLineL delayLine; ReedTabl reedTable; OneZero filter; Envelope envelope; Noise noise; int32 length; MYFLT outputGain; int kloop; } CLARIN; /* int clarinetset(CLARINET *p); */ /* int clarinet(CLARINET *p) */ #endif csound-6.10.0/Opcodes/clfilt.c000066400000000000000000000456171321653344700161330ustar00rootroot00000000000000/* clfilt.c: Copyright (C) 2002 Erik Spjut This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /***************************************************************/ /* clfilt -The Classical Filters */ /* Lowpass, Highpass, Bandpass, Bandstop */ /* Butterworth, Chebycheff I, Chebycheff II, Elliptical */ /* Multi-section biquadratic digital filter with K-Rate coeff. */ /* Based on biquad by Hans Mikelson */ /* and reson by Barry Vercoe */ /* Transformation from continuous time to discrete time by */ /* bilinear z-transform. */ /* April/May 2002 by Erik Spjut */ /***************************************************************/ #include #include "stdopcod.h" #include "clfilt.h" static int clfiltset(CSOUND *csound, CLFILT *p) { MYFLT tanfpi, tanfpi2, cotfpi, cotfpi2; double eps, bethe, aleph, zee; int m, nsec; MYFLT pbr = *p->pbr, sbr = *p->sbr; /* As cannot change */ p->prvfreq = *p->freq; tanfpi = (MYFLT)tan(-csound->mpidsr*(*p->freq)); tanfpi2 = tanfpi*tanfpi; cotfpi = FL(1.0)/tanfpi; cotfpi2 = cotfpi*cotfpi; p->ilohi = (int)*p->lohi; if (UNLIKELY((p->ilohi < 0) || (p->ilohi > 1))) { return csound->InitError(csound, Str("filter type not lowpass or " "highpass in clfilt")); } p->ikind = (int)*p->kind; if (UNLIKELY((p->ikind < 0) || (p->ikind > 3))) { return csound->InitError(csound, Str("filter kind, %d, out of range in clfilt"), p->ikind); } if (UNLIKELY((*p->npol < FL(1.0)) || (*p->npol > 2*CL_LIM))) { return csound->InitError(csound, Str("number of poles, %f, out of range " "in clfilt"), *p->npol); /* p->nsec = nsec = 1; */ } else if (UNLIKELY(fmod((double)*p->npol,2.0) != 0.0)) { p->nsec = nsec = (int)((*p->npol+FL(1.0))*FL(0.5)); csound->Warning(csound, Str("odd number of poles chosen in clfilt," " rounded to %d"), 2*nsec); } else p->nsec = nsec = (int)((*p->npol)*FL(0.5)); switch (p->ilohi) { case 0: /* Lowpass filters */ switch (p->ikind) { case 0: /* Lowpass Butterworth */ for (m=0;m<=nsec-1;m++) { p->alpha[m] = (MYFLT)cos(PI*((m + 0.5)/(2.0*nsec) + 0.5)); p->beta[m] = (MYFLT)sin(PI*((m + 0.5)/(2.0*nsec) + 0.5)); p->a0[m] = (p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]) + cotfpi*(cotfpi-FL(2.0)*(p->alpha[m])); p->a1[m] = FL(2.0)*((p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]) - cotfpi2); p->a2[m] = (p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]) + cotfpi*(cotfpi+FL(2.0)*(p->alpha[m])); p->b0[m] = FL(1.0); p->b1[m] = FL(2.0); p->b2[m] = FL(1.0); } break; case 1: /* Lowpass Chebyshev type I */ if (UNLIKELY( pbr < FL(0.0) )) { pbr = -pbr; csound->Warning(csound, Str("passband ripple must be positive " "in clfilt. Set to %f"), pbr); } else if (UNLIKELY( pbr == FL(0.0) )) { pbr = FL(1.0); csound->Warning(csound, Str("passband ripple must be non-zero in " "clfilt. Set to %f"), pbr); } eps = sqrt(pow(10.0,(pbr/10.0))-1.0); aleph = 0.5/nsec*log(1.0/eps + sqrt(1.0/eps/eps +1.0)); for (m=0;m<=nsec-1;m++) { bethe = PI*((m + 0.5)/(2.0*nsec) + 0.5); p->alpha[m] = (MYFLT)(sinh(aleph)*cos(bethe)); p->beta[m] = (MYFLT)(cosh(aleph)*sin(bethe)); p->a0[m] = (p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]) + cotfpi*(cotfpi-2*(p->alpha[m])); p->a1[m] = FL(2.0)*((p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]) - cotfpi2); p->a2[m] = (p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]) + cotfpi*(cotfpi+FL(2.0)*(p->alpha[m])); if (m==0) { /* H0 and pole magnitudes */ p->b0[m] = ((p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]))*FL(1.0) /(MYFLT)sqrt(1.0+eps*eps); p->b1[m] = ((p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]))*FL(2.0) /(MYFLT)sqrt(1.0+eps*eps); p->b2[m] = ((p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]))*FL(1.0) /(MYFLT)sqrt(1.0+eps*eps); } else { /* pole magnitudes */ p->b0[m] = ((p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]))*FL(1.0); p->b1[m] = ((p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]))*FL(2.0); p->b2[m] = ((p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]))*FL(1.0); } } break; case 2: /* Lowpass Chebyshev type II */ if ( sbr == FL(1.0) ) { sbr = FL(-60.0); } else if (UNLIKELY( sbr > FL(0.0) )) { sbr = -sbr; csound->Warning(csound, Str("stopband attenuation must be negative " "in clfilt. Set to %f"), sbr); } else if (UNLIKELY( sbr == FL(0.0) )) { sbr = FL(-60.0); csound->Warning(csound, Str("stopband attenuation must be non-zero " "in clfilt. Set to %f"), sbr); } eps = sqrt(1.0/(pow(10.0,-(sbr/10.0))-1.0)); aleph = 0.5/nsec*log(1.0/eps + sqrt(1.0/eps/eps +1.0)); for (m=0;m<=nsec-1;m++) { zee = PI*(m + 0.5)/(2.0*nsec); bethe = PI*((m + 0.5)/(2.0*nsec) + 0.5); p->alpha[m] = (MYFLT)(sinh(aleph)*cos(bethe)); p->beta[m] = (MYFLT)(cosh(aleph)*sin(bethe)); p->odelta2[m] = (MYFLT)(cos(zee)*cos(zee)); p->a0[m] = (p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]) + tanfpi*(tanfpi - FL(2.0)*(p->alpha[m])); p->a1[m] = FL(2.0)*(tanfpi2 - ((p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]))); p->a2[m] = (p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]) + tanfpi*(tanfpi + FL(2.0)*(p->alpha[m])); p->b0[m] = p->odelta2[m] + tanfpi2; p->b1[m] = FL(2.0)*(tanfpi2 - p->odelta2[m]); p->b2[m] = p->odelta2[m] + tanfpi2; } break; case 3: /* Lowpass Elliptical */ return csound->InitError(csound, Str( "Lowpass Elliptical not implemented yet. Sorry!")); break; default: /* Because of earlier conditionals, should never get here. */ return csound->InitError(csound, Str("code error, ikind out of range")); } break; case 1: /* Highpass filters */ switch (p->ikind) { case 0: /* Highpass Butterworth */ for (m=0;m<=nsec-1;m++) { p->alpha[m] = (MYFLT)cos(PI*((m + 0.5)/(2.0*nsec) + 0.5)); p->beta[m] = (MYFLT)sin(PI*((m + 0.5)/(2.0*nsec) + 0.5)); p->a0[m] = (p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]) + tanfpi*(tanfpi - FL(2.0)*(p->alpha[m])); p->a1[m] = FL(2.0)*(tanfpi2-((p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]))); p->a2[m] = (p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]) + tanfpi*(tanfpi + FL(2.0)*(p->alpha[m])); p->b0[m] = FL(1.0); p->b1[m] = -FL(2.0); p->b2[m] = FL(1.0); } break; case 1: /* Highpass Chebyshev type I */ if (UNLIKELY( pbr < FL(0.0) )) { pbr = -pbr; csound->Warning(csound, Str("passband ripple must be positive in clfilt. " "Set to %f"), pbr); } else if (UNLIKELY( pbr == FL(0.0) )) { pbr = FL(1.0); csound->Warning(csound, Str("passband ripple must be non-zero " "in clfilt. Set to %f"), pbr); } eps = sqrt((pow(10.0,(pbr/10.0))-1.0)); aleph = 0.5/nsec*log(1.0/eps + sqrt(1.0/eps/eps +1.0)); for (m=0;m<=nsec-1;m++) { bethe = PI*((m + 0.5)/(2.0*nsec) + 0.5); p->alpha[m] = (MYFLT)(sinh(aleph)*cos(bethe)); p->beta[m] = (MYFLT)(cosh(aleph)*sin(bethe)); p->a0[m] = (p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]) + tanfpi*(tanfpi - FL(2.0)*(p->alpha[m])); p->a1[m] = FL(2.0)*(tanfpi2-((p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]))); p->a2[m] = (p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]) + tanfpi*(tanfpi + FL(2.0)*(p->alpha[m])); if (m==0) { /* H0 and pole magnitudes */ p->b0[m] = ((p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]))*FL(1.0) /(MYFLT)sqrt(1.0+eps*eps); p->b1[m] = -((p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]))*FL(2.0) /(MYFLT)sqrt(1.0+eps*eps); p->b2[m] = ((p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]))*FL(1.0) /(MYFLT)sqrt(1.0+eps*eps); } else { /* pole magnitudes */ p->b0[m] = ((p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]))*FL(1.0); p->b1[m] = -((p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]))*FL(2.0); p->b2[m] = ((p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]))*FL(1.0); } } break; case 2: /* Highpass Chebyshev type II */ if ( sbr == FL(1.0) ) { sbr = FL(-60.0); } else if (UNLIKELY( sbr > FL(0.0) )) { sbr = -sbr; csound->Warning(csound, Str("stopband attenuation must be negative " "in clfilt. Set to %f"), sbr); } else if (UNLIKELY( sbr == FL(0.0) )) { sbr = FL(-60.0); csound->Warning(csound, Str("stopband attenuation must be non-zero " "in clfilt. Set to %f"), sbr); } eps = sqrt(1.0/(pow(10.0,-(sbr/10.0))-1.0)); aleph = 0.5/nsec*log(1.0/eps + sqrt(1.0/eps/eps +1.0)); for (m=0;m<=nsec-1;m++) { zee = PI*(m + 0.5)/(2.0*nsec); bethe = PI*((m + 0.5)/(2.0*nsec) + 0.5); p->alpha[m] = (MYFLT)(sinh(aleph)*cos(bethe)); p->beta[m] = (MYFLT)(cosh(aleph)*sin(bethe)); p->odelta2[m] = (MYFLT)(cos(zee)*cos(zee)); p->a0[m] = (p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]) + cotfpi*(cotfpi - FL(2.0)*(p->alpha[m])); p->a1[m] = FL(2.0)*(-cotfpi2 + ((p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]))); p->a2[m] = (p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]) + cotfpi*(cotfpi + FL(2.0)*(p->alpha[m])); p->b0[m] = p->odelta2[m] + cotfpi2; p->b1[m] = FL(2.0)*(-cotfpi2 + p->odelta2[m]); p->b2[m] = p->odelta2[m] + cotfpi2; } break; case 3: /* Highpass Elliptical */ return csound->InitError(csound, Str("Highpass Elliptical " "not implemented yet. Sorry!")); break; default: /* Because of earlier conditionals, should never get here. */ return csound->InitError(csound, Str("code error, ikind out of range")); } break; default: /* Because of earlier conditionals, should never get here. */ return csound->InitError(csound, Str("code error, ihilo out of range")); } if (*p->reinit==FL(0.0)) { /* Only reset in in non-legato mode */ for (m=0;m<=nsec-1;m++) { p->xnm1[m] = p->xnm2[m] = p->ynm1[m] = p->ynm2[m] = FL(0.0); } } return OK; } /* end clfiltset(p) */ static int clfilt(CSOUND *csound, CLFILT *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int m, nsec; MYFLT *out, *in; MYFLT xn[CL_LIM+1], yn[CL_LIM]; MYFLT a0[CL_LIM], a1[CL_LIM], a2[CL_LIM]; MYFLT b0[CL_LIM], b1[CL_LIM], b2[CL_LIM]; MYFLT xnm1[CL_LIM], xnm2[CL_LIM], ynm1[CL_LIM], ynm2[CL_LIM]; MYFLT tanfpi, tanfpi2, cotfpi, cotfpi2; nsec = p->nsec; for (m=0;m<=nsec-1;m++) { a0[m] = p->a0[m]; a1[m] = p->a1[m]; a2[m] = p->a2[m]; b0[m] = p->b0[m]; b1[m] = p->b1[m]; b2[m] = p->b2[m]; xnm1[m] = p->xnm1[m]; xnm2[m] = p->xnm2[m]; ynm1[m] = p->ynm1[m]; ynm2[m] = p->ynm2[m]; } if (*p->freq != p->prvfreq) { /* Only reset if freq changes */ p->prvfreq = *p->freq; tanfpi = (MYFLT)tan(-csound->mpidsr*(*p->freq)); tanfpi2 = tanfpi*tanfpi; cotfpi = FL(1.0)/tanfpi; cotfpi2 = cotfpi*cotfpi; switch (p->ilohi) { case 0: /* Lowpass filters */ switch (p->ikind) { case 0: /* Lowpass Butterworth */ case 1: /* Lowpass Chebyshev type I */ for (m=0;m<=nsec-1;m++) { p->a0[m] = a0[m] = (p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]) + cotfpi*(cotfpi-FL(2.0)*(p->alpha[m])); p->a1[m] = a1[m] = FL(2.0)*((p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]) - cotfpi2); p->a2[m] = a2[m] = (p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]) + cotfpi*(cotfpi+FL(2.0)*(p->alpha[m])); } break; case 2: /* Lowpass Chebyshev type II */ for (m=0;m<=nsec-1;m++) { p->a0[m] = a0[m] = (p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]) + tanfpi*(tanfpi - FL(2.0)*(p->alpha[m])); p->a1[m] = a1[m] = FL(2.0)*(tanfpi2 - ((p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]))); p->a2[m] = a2[m] = (p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]) + tanfpi*(tanfpi + FL(2.0)*(p->alpha[m])); p->b0[m] = b0[m] = p->odelta2[m] + tanfpi2; p->b1[m] = b1[m] = FL(2.0)*(tanfpi2 - p->odelta2[m]); p->b2[m] = b2[m] = p->odelta2[m] + tanfpi2; } break; case 3: /* Lowpass Elliptical */ return csound->PerfError(csound, p->h.insdshead, Str("Lowpass Elliptical " "not implemented yet. Sorry!")); break; default: /* Because of earlier contditionals, should never get here. */ return csound->PerfError(csound, p->h.insdshead, Str("code error, ikind out of range")); } break; case 1: /* Highpass filters */ switch (p->ikind) { case 0: /* Highpass Butterworth */ case 1: /* Highpass Chebyshev type I */ for (m=0;m<=nsec-1;m++) { p->a0[m] = a0[m] = (p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]) + tanfpi*(tanfpi - FL(2.0)*(p->alpha[m])); p->a1[m] = a1[m] = FL(2.0)*(tanfpi2-((p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]))); p->a2[m] = a2[m] = (p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]) + tanfpi*(tanfpi + FL(2.0)*(p->alpha[m])); } break; case 2: /* Highpass Chebyshev type II */ for (m=0;m<=nsec-1;m++) { p->a0[m] = a0[m] = (p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]) + cotfpi*(cotfpi - FL(2.0)*(p->alpha[m])); p->a1[m] = a1[m] = FL(2.0)*(-cotfpi2 + ((p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]))); p->a2[m] = a2[m] = (p->alpha[m])*(p->alpha[m]) + (p->beta[m])*(p->beta[m]) + cotfpi*(cotfpi + FL(2.0)*(p->alpha[m])); p->b0[m] = b0[m] = p->odelta2[m] + cotfpi2; p->b1[m] = b1[m] = FL(2.0)*(-cotfpi2 + p->odelta2[m]); p->b2[m] = b2[m] = p->odelta2[m] + cotfpi2; } break; case 3: /* Highpass Elliptical */ return csound->PerfError(csound, p->h.insdshead, Str("Highpass Elliptical " "not implemented yet. Sorry!")); break; default: /* Because of earlier contditionals, should never get here. */ return csound->PerfError(csound, p->h.insdshead, Str("code error, ikind out of range")); } break; default: /* Because of earlier conditionals, should never get here. */ return csound->PerfError(csound, p->h.insdshead, Str("code error, ihilo out of range")); } } in = p->in; out = p->out; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nxnm1[m] = xnm1[m]; p->xnm2[m] = xnm2[m]; p->ynm1[m] = ynm1[m]; p->ynm2[m] = ynm2[m]; } return OK; } /* end clfilt(p) */ #define S sizeof static OENTRY localops[] = { { "clfilt", S(CLFILT), 0, 5, "a", "akiioppo",(SUBR)clfiltset, NULL, (SUBR)clfilt }, }; int clfilt_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/clfilt.h000066400000000000000000000026031321653344700161240ustar00rootroot00000000000000/* clfilt.h: Copyright (C) 2002 Erik Spjut This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* clfilt.h */ #define CL_LIM 40 /* The limit on the number of biquadratic sections */ /* Structure for biquadratic filter */ typedef struct { OPDS h; MYFLT *out, *in, *freq, *lohi, *npol, *kind, *pbr, *sbr, *reinit; MYFLT xnm1[CL_LIM], xnm2[CL_LIM], ynm1[CL_LIM], ynm2[CL_LIM], alpha[CL_LIM], beta[CL_LIM], odelta2[CL_LIM], b0[CL_LIM], b1[CL_LIM], b2[CL_LIM], a0[CL_LIM], a1[CL_LIM], a2[CL_LIM], prvfreq; int ilohi, nsec, ikind; } CLFILT; csound-6.10.0/Opcodes/compress.c000066400000000000000000000232041321653344700164750ustar00rootroot00000000000000/* compress.c: Copyright (C) 2006 by Barry Vercoe; adapted by John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ //#include "csdl.h" #include "csoundCore.h" #include "interlocks.h" typedef struct { OPDS h; MYFLT *ar, *aasig, *acsig, *kthresh, *kloknee, *khiknee; MYFLT *kratio, *katt, *krls, *ilook; MYFLT thresh, loknee, hiknee, ratio, curatt, currls; MYFLT envthrsh, envlo, kneespan, kneemul, kneecoef, ratcoef; double cenv, c1, c2, d1, d2, ampmul; MYFLT *abuf, *cbuf, *aptr, *cptr, *clim, lmax, *lmaxp; int32 newenv; AUXCH auxch; MYFLT bias; } CMPRS; typedef struct { /* this now added from 07/01 */ OPDS h; MYFLT *ar, *asig, *kdist, *ifn, *ihp, *istor; double c1, c2; MYFLT prvq, prvd, min_rms; MYFLT midphs, maxphs, begval, endval; FUNC *ftp; } DIST; static int compset(CSOUND *csound, CMPRS *p) { int32 delsmps; p->thresh = (MYFLT) MAXPOS; p->loknee = (MYFLT) MAXPOS; /* force reinits */ p->hiknee = (MYFLT) MAXPOS; p->ratio = (MYFLT) MAXPOS; p->curatt = (MYFLT) MAXPOS; p->currls = (MYFLT) MAXPOS; /* round to nearest integer */ if (UNLIKELY((delsmps = MYFLT2LONG(*p->ilook * csound->GetSr(csound))) <= 0L)) delsmps = 1L; /* alloc 2 delay bufs */ csound->AuxAlloc(csound, delsmps * 2 * sizeof(MYFLT), &p->auxch); p->abuf = (MYFLT *)p->auxch.auxp; p->cbuf = p->abuf + delsmps; /* for asig & csig */ p->clim = p->cbuf + delsmps; p->aptr = p->abuf; p->cptr = p->cbuf; p->lmaxp = p->clim - 1; p->lmax = FL(0.0); p->cenv = 0.0; p->newenv = 0; p->bias = FL(0.0); return OK; } /* compress2 is compress but with dB inputs in range [-90,0] rather than [0.90], by setting p->bias valuex -- JPff */ static int comp2set(CSOUND *csound, CMPRS *p) { int ret = compset(csound, p); p->bias = FL(90.0); return ret; } static int compress(CSOUND *csound, CMPRS *p) { MYFLT *ar, *ainp, *cinp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; /* VL: scale by 0dbfs, code is tuned to work in 16bit range */ MYFLT scal = FL(32768.0)/csound->e0dbfs; if (*p->kthresh != p->thresh) { /* check for changes: */ p->thresh = *p->kthresh; p->envthrsh = (MYFLT) exp((p->thresh+p->bias) * LOG10D20); } if (*p->kloknee != p->loknee || *p->khiknee != p->hiknee || *p->kratio != p->ratio) { MYFLT ratio, K; p->loknee = *p->kloknee; p->hiknee = *p->khiknee; p->ratio = *p->kratio; p->envlo = (MYFLT) exp((p->loknee+p->bias) * LOG10D20); if ((p->kneespan = p->hiknee - p->loknee) < FL(0.0)) p->kneespan = FL(0.0); if ((ratio = p->ratio) < FL(0.01)) /* expand max is 100 */ ratio = FL(0.01); K = (MYFLT) LOG10D20 * (FL(1.0) - ratio) / ratio; p->ratcoef = K; /* rat down per db */ if (p->kneespan > FL(0.0)) { p->kneecoef = K*FL(0.5) / p->kneespan; /* y = x - (K/2span)x*x */ p->kneemul = (MYFLT)exp(p->kneecoef * p->kneespan * p->kneespan); } else p->kneemul = FL(1.0); } if (*p->katt != p->curatt) { if ((p->curatt = *p->katt) < csound->onedsr) p->c2 = 0.0; else p->c2 = pow(0.5, csound->onedsr / p->curatt); p->c1 = 1.0 - p->c2; } if (*p->krls != p->currls) { if ((p->currls = *p->krls) < csound->onedsr) p->d2 = 0.0; else p->d2 = pow(0.5, csound->onedsr / p->currls); p->d1 = 1.0 - p->d2; } ar = p->ar; ainp = p->aasig; cinp = p->acsig; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; naptr; /* get signals from delay line */ csig = *p->cptr; *p->aptr = ainp[n]*scal; /* & replace with incoming */ lsig = FABS(cinp[n]*scal); //lsig = -lsig; /* made abs for control */ *p->cptr = lsig; if (p->cptr == p->lmaxp) { /* if prev ctrl was old lamax */ MYFLT *lap, newmax = FL(0.0); for (lap = p->cptr + 1; lap < p->clim; lap++) if (*lap >= newmax) { newmax = *lap; /* find next highest abs */ p->lmaxp = lap; } for (lap = p->cbuf; lap <= p->cptr; lap++) if (*lap >= newmax) { newmax = *lap; /* in lkahd circular cbuf */ p->lmaxp = lap; } p->lmax = newmax; } else if (lsig >= p->lmax) { /* else keep lkahd max & adrs */ p->lmax = lsig; /* on arrival */ p->lmaxp = p->cptr; } if (csig > p->cenv) /* follow a rising csig env */ p->cenv = p->c1 * csig + p->c2 * p->cenv; else if (p->cenv > p->lmax) /* else if env above lookahead */ p->cenv = p->d1 * csig + p->d2 * p->cenv; /* apply release */ else goto lvlchk; p->newenv = 1; lvlchk: if (p->cenv > p->envlo) { /* if env exceeds loknee amp */ if (p->newenv) { /* calc dbenv & ampmul */ double dbenv, excess; p->newenv = 0; dbenv = log(p->cenv + 0.001) / LOG10D20; /* for softknee */ if ((excess = dbenv - (p->loknee+p->bias)) < p->kneespan) p->ampmul = exp(p->kneecoef * excess * excess); else { excess -= p->kneespan; /* or ratio line */ p->ampmul = p->kneemul * exp(p->ratcoef * excess); } } asig *= (MYFLT)p->ampmul; /* and compress the asig */ } else if (p->cenv < p->envthrsh) asig = FL(0.0); /* else maybe noise gate */ ar[n] = asig/scal; if (++p->aptr >= p->cbuf) { p->aptr = p->abuf; p->cptr = p->cbuf; } else p->cptr++; } return OK; } static int distset(CSOUND *csound, DIST *p) { double b; FUNC *ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) == NULL)) return NOTOK; p->ftp = ftp; p->maxphs = (MYFLT)ftp->flen; /* set ftable params */ p->midphs = p->maxphs * FL(0.5); p->begval = ftp->ftable[0]; p->endval = ftp->ftable[ftp->flen]; b = 2.0 - cos((double) (*p->ihp * csound->tpidsr)); /* and rms coefs */ p->c2 = b - sqrt(b * b - 1.0); p->c1 = 1.0 - p->c2; p->min_rms = csound->e0dbfs * DV32768; if (!*p->istor) { p->prvq = FL(0.0); p->prvd = FL(1000.0) * p->min_rms; } return OK; } static int distort(CSOUND *csound, DIST *p) { MYFLT *ar, *asig; MYFLT q, rms, dist, dnew, dcur, dinc; FUNC *ftp = p->ftp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; asig = p->asig; q = p->prvq; for (n=offset; nc1 * asig[n] * asig[n] + p->c2 * q; } p->prvq = q; rms = SQRT(q); /* get running rms */ if (rms < p->min_rms) rms = p->min_rms; if ((dist = *p->kdist) < FL(0.001)) dist = FL(0.001); dnew = rms / dist; /* & compress factor */ dcur = p->prvd; asig = p->asig; ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } dinc = (dnew - dcur) / nsmps; for (n=offset; nmidphs * (FL(1.0) + sig); /* as index into table */ if (UNLIKELY(phs <= FL(0.0))) val = p->begval; else if (UNLIKELY(phs >= p->maxphs)) /* check sticky bits */ val = p->endval; else { int32 iphs = (int32)phs; MYFLT frac = phs - (MYFLT)iphs; /* waveshape the samp */ MYFLT *fp = ftp->ftable + iphs; val = *fp++; val += (*fp - val) * frac; } ar[n] = val * dcur; /* and restor the amp */ dcur += dinc; } p->prvd = dcur; return OK; } #define S(x) sizeof(x) static OENTRY compress_localops[] = { { "compress", S(CMPRS), 0, 5, "a", "aakkkkkki", (SUBR) compset, NULL, (SUBR) compress }, { "compress2", S(CMPRS), 0, 5, "a", "aakkkkkki", (SUBR) comp2set, NULL, (SUBR) compress }, { "distort", S(DIST), TR, 5, "a", "akiqo", (SUBR) distset, NULL, (SUBR) distort }, }; LINKAGE_BUILTIN(compress_localops) csound-6.10.0/Opcodes/control.c000066400000000000000000000247711321653344700163340ustar00rootroot00000000000000/* control.c: Copyright (C) 2000 John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csdl.h" #include "control.h" #include #include #include #if defined(__MACH__) #include #endif static CS_NOINLINE CONTROL_GLOBALS *get_globals_(CSOUND *csound) { CONTROL_GLOBALS *p; p = (CONTROL_GLOBALS*) csound->QueryGlobalVariable(csound, "controlGlobals_"); if (p != NULL) return p; if (csound->CreateGlobalVariable(csound, "controlGlobals_", sizeof(CONTROL_GLOBALS)) != 0){ csound->Warning(csound, Str("control: failed to allocate globals")); return NULL; } p = (CONTROL_GLOBALS*) csound->QueryGlobalVariable(csound, "controlGlobals_"); p->csound = csound; return p; } static inline CONTROL_GLOBALS *get_globals(CSOUND *csound, CONTROL_GLOBALS **p) { if (*p == NULL) *p = get_globals_(csound); return (*p); } static int kill_wish(CSOUND *csound, CONTROL_GLOBALS *p) { csound->Message(csound, Str("Closing down wish(%d)\n"), p->wish_pid); kill(p->wish_pid, 9); if (p->values != NULL) csound->Free(csound,p->values); if (p->minvals != NULL) csound->Free(csound,p->minvals); if (p->maxvals != NULL) csound->Free(csound,p->maxvals); if (p->buttons != NULL) csound->Free(csound,p->buttons); if (p->checks != NULL) csound->Free(csound,p->checks); fclose(p->wish_cmd); fclose(p->wish_res); return OK; } static void start_tcl_tk(CONTROL_GLOBALS *p) { int i; p->csound->Message(p->csound, "TCL/Tk\n"); if (UNLIKELY(pipe(p->pip1) || pipe(p->pip2))) { printf("Failed to create pipes"); return; } if ((p->wish_pid = fork()) < 0) return; if (p->wish_pid == 0) { /* Child process */ char *argv[7]; argv[0] = "sh"; argv[1] = "-c"; argv[2] = "wish"; argv[3] = "-name"; argv[4] = "sliders"; argv[5] = NULL; close(p->pip1[0]); close(p->pip2[1]); close(0); close(1); dup2(p->pip2[0], 0); dup2(p->pip1[1], 1); setvbuf(stdout, (char*) NULL, _IOLBF, 0); signal(SIGINT, SIG_IGN); /* child process should ignore ^C */ execvp("/bin/sh", argv); exit(127); } /* Main process -- create communications */ close(p->pip1[1]); close(p->pip2[0]); p->wish_res = fdopen(p->pip1[0], "r"); p->wish_cmd = fdopen(p->pip2[1], "w"); setvbuf(p->wish_cmd, (char*) NULL, _IOLBF, 0); setvbuf(p->wish_res, (char*) NULL, _IOLBF, 0); p->csound->RegisterResetCallback(p->csound, (void*) p, (int (*)(CSOUND *, void *)) kill_wish); fprintf(p->wish_cmd, "source nsliders.tk\n"); if (UNLIKELY(NULL==fgets(p->cmd, 100, p->wish_res))) { printf("Failed to read from child"); return; }; p->csound->Message(p->csound, "Wish %s\n", p->cmd); p->values = (int*) p->csound->Calloc(p->csound,8*sizeof(int)); p->minvals = (int*) p->csound->Calloc(p->csound,8* sizeof(int)); p->maxvals = (int*) p->csound->Calloc(p->csound,8* sizeof(int)); p->buttons = (int*) p->csound->Calloc(p->csound,8* sizeof(int)); p->checks = (int*) p->csound->Calloc(p->csound,8* sizeof(int)); p->max_sliders = 8; p->max_button = 8; p->max_check = 8; for (i = 0; i < p->max_sliders; i++) { p->minvals[i] = 0; p->maxvals[i] = 127; } p->csound->Sleep(1500); } static void ensure_slider(CONTROL_GLOBALS *p, int n) { /* p->csound->Message(p->csound, "Ensure_slider %d\n", n); */ if (p->wish_pid == 0) start_tcl_tk(p); if (n > p->max_sliders) { int i, nn = n + 1; p->values = (int*) p->csound->ReAlloc(p->csound,p->values, nn * sizeof(int)); p->minvals = (int*) p->csound->ReAlloc(p->csound,p->minvals,nn * sizeof(int)); p->maxvals = (int*) p->csound->ReAlloc(p->csound,p->maxvals,nn * sizeof(int)); for (i = p->max_sliders + 1; i < nn; i++) { p->values[i] = 0; p->minvals[i] = 0; p->maxvals[i] = 127; } p->max_sliders = n; } /* p->csound->Message(p->csound, "displayslider %d\n", n); */ fprintf(p->wish_cmd, "displayslider %d\n", n); } static void readvalues(CONTROL_GLOBALS *p) { fd_set rfds; struct timeval tv; /* Watch wish_res to see when it has input. */ FD_ZERO(&rfds); FD_SET(p->pip1[0], &rfds); tv.tv_sec = 0; tv.tv_usec = 0; /* Read all changes */ while (select(p->pip1[0] + 1, &rfds, NULL, NULL, &tv)) { int n, val; if (UNLIKELY(2!=fscanf(p->wish_res, "%d %d", &n, &val))) { printf("Failed to read from child"); return; } if (n>p->max_sliders); /* ignore error case */ else if (n > 0) p->values[n] = val; else if (n == 0) p->buttons[val] = 1; else p->checks[-n] = val; tv.tv_sec = 0; tv.tv_usec = 0; } } static int cntrl_set(CSOUND *csound, CNTRL *p) { ensure_slider(get_globals(csound, &(p->p)), (int) MYFLT2LONG(*p->kcntl)); return OK; } static int control(CSOUND *csound, CNTRL *p) { CONTROL_GLOBALS *pp = get_globals(csound, &(p->p)); readvalues(pp); *p->kdest = pp->values[(int)MYFLT2LONG(*p->kcntl)]; return OK; } static int ocontrol_(CSOUND *csound, SCNTRL *p, int istring) { CONTROL_GLOBALS *pp = get_globals(csound, &(p->p)); int c = (int) *p->which; int slider = (int) MYFLT2LONG(*p->kcntl); /* csound->Message(csound, "ocontrol: %d %d %f\n", slider, c, *p->val); */ ensure_slider(pp, slider); switch (c) { case 1: fprintf(pp->wish_cmd, "setvalue %d %d\n", slider, (int) *p->val); pp->values[slider] = (int) *p->val; break; case 2: if (pp->minvals[slider] != (int) *p->val) { fprintf(pp->wish_cmd, "setmin %d %d\n", slider, (int) *p->val); pp->minvals[slider] = (int) *p->val; } break; case 3: if (pp->maxvals[slider] != (int) *p->val) { fprintf(pp->wish_cmd, "setmax %d %d\n", slider, (int) *p->val); pp->maxvals[slider] = (int) *p->val; } break; case 4: { char buffer[100]; if (istring) { csound->strarg2name(csound, buffer, ((STRINGDAT *)p->val)->data, "Control ",istring); } else csound->strarg2name(csound, buffer, p->val, "Control ",istring); csound->Message(csound, Str("Slider %d set to %s\n"), slider, buffer); fprintf(pp->wish_cmd, "setlab %d \"%s\"\n", slider, buffer); break; } default: return csound->InitError(csound, Str("Unknown control %d"), c); } return OK; } static int ocontrol(CSOUND *csound, SCNTRL *p){ return ocontrol_(csound,p,0); } static int ocontrol_S(CSOUND *csound, SCNTRL *p){ return ocontrol_(csound,p,1); } static int button_set(CSOUND *csound, CNTRL *p) { CONTROL_GLOBALS *pp = get_globals(csound, &(p->p)); int n = (int) MYFLT2LONG(*p->kcntl); if (pp->wish_pid == 0) start_tcl_tk(pp); if (n > pp->max_button) { pp->buttons = (int*) csound->ReAlloc(csound, pp->buttons, (n + 1) * sizeof(int)); do { pp->buttons[++(pp->max_button)] = 0; } while (pp->max_button < n); } fprintf(pp->wish_cmd, "displaybutton %d\n", n); return OK; } static int button(CSOUND *csound, CNTRL *p) { CONTROL_GLOBALS *pp = get_globals(csound, &(p->p)); int t = (int)MYFLT2LONG(*p->kcntl); readvalues(pp); *p->kdest = pp->buttons[t]; pp->buttons[t] = 0; return OK; } static int check_set(CSOUND *csound, CNTRL *p) { CONTROL_GLOBALS *pp = get_globals(csound, &(p->p)); int n = (int) MYFLT2LONG(*p->kcntl); if (pp->wish_pid == 0) start_tcl_tk(pp); if (n > pp->max_check) { pp->checks = (int*) csound->ReAlloc(csound,pp->checks, (n + 1) * sizeof(int)); do { pp->checks[++(pp->max_check)] = 0; } while (pp->max_check < n); } fprintf(pp->wish_cmd, "displaycheck %d\n", n); return OK; } static int check(CSOUND *csound, CNTRL *p) { CONTROL_GLOBALS *pp = get_globals(csound, &(p->p)); readvalues(pp); *p->kdest = pp->checks[(int) MYFLT2LONG(*p->kcntl)]; return OK; } /* **** Text Windows **** */ static int textflash_(CSOUND *csound, TXTWIN *p, int istring) { CONTROL_GLOBALS *pp = get_globals(csound, &(p->p)); int wind = (int) MYFLT2LONG(*p->kcntl); char buffer[100]; if (pp->wish_pid == 0) start_tcl_tk(pp); if (istring) { csound->strarg2name(csound, buffer, ((STRINGDAT *)p->val)->data, "", istring); fprintf(pp->wish_cmd, "settext %d \"%s\"\n", wind, buffer); } else if (csound->ISSTRCOD(*p->val)) { csound->strarg2name(csound, buffer, csound->GetString(csound, *p->val), "", 1); } else { fprintf(pp->wish_cmd, "deltext %d\n", wind); } return OK; } static int textflash(CSOUND *csound, TXTWIN *p){ return textflash_(csound, p, 0); } static int textflash_S(CSOUND *csound, TXTWIN *p){ return textflash_(csound, p, 1); } #define S(x) sizeof(x) static OENTRY control_localops[] = { { "control", S(CNTRL), 0, 3, "k", "k", (SUBR) cntrl_set, (SUBR) control, NULL }, { "setctrl", S(SCNTRL), 0, 1, "", "iii", (SUBR) ocontrol, NULL, NULL }, { "setctrl.S", S(SCNTRL), 0, 1, "", "iSi", (SUBR) ocontrol_S, NULL, NULL }, { "button", S(CNTRL), 0, 3, "k", "k", (SUBR) button_set, (SUBR) button, NULL }, { "checkbox", S(CNTRL), 0, 3, "k", "k", (SUBR) check_set, (SUBR) check, NULL }, { "flashtxt", S(TXTWIN), 0, 1, "", "ii", (SUBR) textflash, NULL, NULL }, { "flashtxt.S", S(TXTWIN), 0, 1, "", "iS", (SUBR) textflash_S, NULL, NULL }, }; LINKAGE_BUILTIN(control_localops) csound-6.10.0/Opcodes/control.h000066400000000000000000000031701321653344700163270ustar00rootroot00000000000000/* control.h: Copyright (C) 2000 John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /********************************************/ /* Controls */ /********************************************/ #include "csdl.h" typedef struct CONTROL_GLOBALS_ { CSOUND *csound; char cmd[100]; int wish_pid; int pip1[2]; int pip2[2]; FILE *wish_cmd, *wish_res; int *values; int *minvals; int *maxvals; int max_sliders; int *buttons; int *checks; int max_button; int max_check; } CONTROL_GLOBALS; typedef struct { OPDS h; MYFLT *kdest, *kcntl; CONTROL_GLOBALS *p; } CNTRL; typedef struct { OPDS h; MYFLT *kcntl, *val, *which; CONTROL_GLOBALS *p; } SCNTRL; typedef struct { OPDS h; MYFLT *kcntl, *val; CONTROL_GLOBALS *p; } TXTWIN; csound-6.10.0/Opcodes/cpumeter.c000066400000000000000000000166471321653344700165030ustar00rootroot00000000000000/* cpupercent * * Copyright *c) 2011 John ffitch, based heavily on code: * Copyright (c) 2002, by: James C. Warner * All rights reserved. 8921 Hilloway Road * Eden Prairie, Minnesota 55347 USA * * * This file may be used subject to the terms and conditions of the * GNU Library General Public License Version 2, or any later version * at your option, as published by the Free Software Foundation. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. * */ // only available on Linux (no /proc/stat on OSX) #if defined(LINUX) #include "csoundCore.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*###### Miscellaneous global stuff ####################################*/ #define SMLBUFSIZ (512) #define TEST (0) typedef unsigned long long TIC_t; typedef long long SIC_t; typedef struct CPU_t { TIC_t u, n, s, i, w, x, y, z; // as represented in /proc/stat TIC_t u_sav, n_sav, s_sav, i_sav, w_sav, x_sav, y_sav, z_sav; unsigned id; // the CPU ID number } CPU_t; typedef struct { OPDS h; MYFLT *k0, *kk[8], *itrig; AUXCH cpu_a; CPU_t *cpus; uint32_t cpu_max; int cnt, trig; FILE *fp; } CPUMETER; /* * we preserve all cpu data in our CPU_t array which is organized * as follows: * cpus[0] thru cpus[n] == tics for each separate cpu * cpus[Cpu_tot] == tics from the 1st /proc/stat line */ static int cpupercent_renew(CSOUND *csound, CPUMETER* p); int cpupercent_init(CSOUND *csound, CPUMETER* p) { char buf[SMLBUFSIZ]; int k, num; TIC_t id, u, n, s, i, w, x, y, z; if (!(p->fp = fopen("/proc/stat", "r"))) return csound->InitError(csound, Str("Failed to open /proc/stat: %s"), strerror(errno)); if (!fgets(buf, sizeof(buf), p->fp)) return csound->InitError(csound, Str("failed /proc/stat read")); num = sscanf(buf, "cpu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu", &u, &n, &s, &i, &w, &x, &y, &z); for (k = 0; ; k++) { if (!fgets(buf, SMLBUFSIZ, p->fp)) return csound->InitError(csound,Str("failed /proc/stat read")); num = sscanf(buf, "cpu%llu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu", &id, &u, &n, &s, &i, &w, &x, &y, &z); if (num<4) break; } p->cpu_max = k-1; csound->AuxAlloc(csound,k*sizeof(CPU_t), &(p->cpu_a)); p->cpus = (CPU_t *) p->cpu_a.auxp; k = cpupercent_renew(csound, p); p->cnt = (p->trig = (int)(*p->itrig * csound->GetSr(csound))); return k; } static int cpupercent_renew(CSOUND *csound, CPUMETER* p) { #define TRIMz(x) ((tz = (SIC_t)(x)) < 0 ? 0 : tz) SIC_t u_frme, s_frme, n_frme, i_frme, w_frme, x_frme, y_frme, z_frme, tot_frme, tz; double scale; uint32_t k; CPU_t *cpu = p->cpus; char buf[SMLBUFSIZ]; rewind(p->fp); fflush(p->fp); k = p->cpu_max; if (!fgets(buf, SMLBUFSIZ, p->fp)) return csound->PerfError(csound, p->h.insdshead, Str("failed /proc/stat read")); /*num = */sscanf(buf, "cpu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu", &cpu[k].u, &cpu[k].n, &cpu[k].s, &cpu[k].i, &cpu[k].w, &cpu[k].x, &cpu[k].y, &cpu[k].z); u_frme = cpu[k].u - cpu[k].u_sav; s_frme = cpu[k].s - cpu[k].s_sav; n_frme = cpu[k].n - cpu[k].n_sav; i_frme = TRIMz(cpu[k].i - cpu[k].i_sav); w_frme = cpu[k].w - cpu[k].w_sav; x_frme = cpu[k].x - cpu[k].x_sav; y_frme = cpu[k].y - cpu[k].y_sav; z_frme = cpu[k].z - cpu[k].z_sav; tot_frme = u_frme + s_frme + n_frme + i_frme + w_frme + x_frme + y_frme + z_frme; if (tot_frme < 1) tot_frme = 1; scale = 100.0 / (double)tot_frme; *p->k0 = 100.0-(double)i_frme * scale; if (TEST) printf("**%5.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f\n", (double)u_frme * scale, (double)s_frme * scale, (double)n_frme * scale, (double)i_frme * scale, (double)w_frme * scale, (double)x_frme * scale, (double)y_frme * scale, (double)z_frme * scale ); // remember for next time around cpu[k].u_sav = cpu[k].u; cpu[k].s_sav = cpu[k].s; cpu[k].n_sav = cpu[k].n; cpu[k].i_sav = cpu[k].i; cpu[k].w_sav = cpu[k].w; cpu[k].x_sav = cpu[k].x; cpu[k].y_sav = cpu[k].y; cpu[k].z_sav = cpu[k].z; for (k=0; kcpu_max && k+1OUTOCOUNT; k++) { if (!fgets(buf, SMLBUFSIZ, p->fp)) return csound->PerfError(csound, p->h.insdshead, Str("failed /proc/stat read")); /*num = */ (void)sscanf(buf, "cpu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu", &cpu[k].u, &cpu[k].n, &cpu[k].s, &cpu[k].i, &cpu[k].w, &cpu[k].x, &cpu[k].y, &cpu[k].z); u_frme = cpu[k].u - cpu[k].u_sav; s_frme = cpu[k].s - cpu[k].s_sav; n_frme = cpu[k].n - cpu[k].n_sav; i_frme = TRIMz(cpu[k].i - cpu[k].i_sav); w_frme = cpu[k].w - cpu[k].w_sav; x_frme = cpu[k].x - cpu[k].x_sav; y_frme = cpu[k].y - cpu[k].y_sav; z_frme = cpu[k].z - cpu[k].z_sav; tot_frme = u_frme + s_frme + n_frme + i_frme + w_frme + x_frme + y_frme + z_frme; if (tot_frme < 1) tot_frme = 1; scale = 100.0 / (double)tot_frme; //if (p->kk[k]==NULL) break; *p->kk[k] = 100.0-i_frme * scale; if (TEST) printf("%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f\n", (double)u_frme * scale, (double)s_frme * scale, (double)n_frme * scale, (double)i_frme * scale, (double)w_frme * scale, (double)x_frme * scale, (double)y_frme * scale, (double)z_frme * scale); // remember for next time around cpu[k].u_sav = cpu[k].u; cpu[k].s_sav = cpu[k].s; cpu[k].n_sav = cpu[k].n; cpu[k].i_sav = cpu[k].i; cpu[k].w_sav = cpu[k].w; cpu[k].x_sav = cpu[k].x; cpu[k].y_sav = cpu[k].y; cpu[k].z_sav = cpu[k].z; *p->kk[k] = 100.0-i_frme * scale; } return OK; #undef TRIMz } static int cpupercent(CSOUND *csound, CPUMETER* p) { p->cnt -= CS_KSMPS; if (p->cnt< 0) { int n = cpupercent_renew(csound, p); p->cnt = p->trig; return n; } return OK; } typedef struct { OPDS h; MYFLT *ti; } SYST; static int systime(CSOUND *csound, SYST *p){ struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); *p->ti = round((ts.tv_sec + ts.tv_nsec/1.e9)*1000); return OK; } #define S(x) sizeof(x) static OENTRY cpumeter_localops[] = { { "cpumeter", S(CPUMETER), 0,5, "kzzzzzzzz", "i", (SUBR)cpupercent_init, (SUBR)cpupercent, NULL }, { "systime", S(SYST),0, 3, "k", "", (SUBR)systime, (SUBR)systime}, { "systime", S(SYST),0, 1, "i", "", (SUBR)systime} }; LINKAGE_BUILTIN(cpumeter_localops) #endif csound-6.10.0/Opcodes/cross2.c000066400000000000000000000241701321653344700160600ustar00rootroot00000000000000/* cross2.c: Copyright (C) 1997 Paris Smaragdis, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "stdopcod.h" #include "ptrigtbl.h" #include "fhtfun.h" #include "interlocks.h" #include #define CH_THRESH 1.19209e-7 #define CHOP(a) (a < CH_THRESH ? CH_THRESH : a) static int32 plog2(int32 x) { int32 mask, i; if (x == 0) return (-1); x--; for (mask = ~1 , i = 0; ; mask = mask+mask, i++) { if (x == 0) return (i); x = x & mask; } } static void getmag(MYFLT *x, int32 size) { MYFLT *i = x + 1, *j = x + size - 1, max = FL(0.0); int32 n = size/2 - 1; do { MYFLT ii = *i; MYFLT jj = *j; ii = HYPOT(ii,jj); if (ii > max) max = ii; *i = ii; i++; j--; } while (--n); if (LIKELY(max!=FL(0.0))) { int NN = size/2 + 1; for (n=0; n> 1 ; !( (k2 ^= k) & k) ; k >>= 1); if (k1 > k2) { a = fz[k1]; fz[k1] = fz[k2]; fz[k2] = a; } k1++; } while (k1 < n); k = 0; i = 1; do { k++; } while ( (i << k) < n); k &= 1; if (k == 0) { fi = fz; fn = fz + n; do { MYFLT f0, f1, f2, f3; f1 = fi[0] - fi[1]; f0 = fi[0] + fi[1]; f3 = fi[2] - fi[3]; f2 = fi[2] + fi[3]; fi[2] = f0 - f2; fi[0] = f0 + f2; fi[3] = f1 - f3; fi[1] = f1 + f3; fi += 4; } while (fi < fn); } else { fi = fz; fn = fz + n; gi = fi + 1; do { MYFLT s1, c1, s2, c2, s3, c3, s4, c4, g0, f0, f1, g1, f2, g2, f3, g3; c1 = fi[0] - gi[0]; s1 = fi[0] + gi[0]; c2 = fi[2] - gi[2]; s2 = fi[2] + gi[2]; c3 = fi[4] - gi[4]; s3 = fi[4] + gi[4]; c4 = fi[6] - gi[6]; s4 = fi[6] + gi[6]; f1 = s1 - s2; f0 = s1 + s2; g1 = c1 - c2; g0 = c1 + c2; f3 = s3 - s4; f2 = s3 + s4; g3 = SQRT2 * c4; g2 = SQRT2 * c3; fi[4] = f0 - f2; fi[0] = f0 + f2; fi[6] = f1 - f3; fi[2] = f1 + f3; gi[4] = g0 - g2; gi[0] = g0 + g2; gi[6] = g1 - g3; gi[2] = g1 + g3; fi += 8; gi += 8; } while (fi < fn); } if (n < 16) return; do { MYFLT s1, c1; k += 2; k1 = 1L << k; k2 = k1 << 1; k4 = k2 << 1; k3 = k2 + k1; kx = k1 >> 1; fi = fz; gi = fi + kx; fn = fz + n; do { MYFLT g0, f0, f1, g1, f2, g2, f3, g3; f1 = fi[0] - fi[k1]; f0 = fi[0] + fi[k1]; f3 = fi[k2] - fi[k3]; f2 = fi[k2] + fi[k3]; fi[k2] = f0 - f2; fi[0] = f0 + f2; fi[k3] = f1 - f3; fi[k1] = f1 + f3; g1 = gi[0] - gi[k1]; g0 = gi[0] + gi[k1]; g3 = SQRT2 * gi[k3]; g2 = SQRT2 * gi[k2]; gi[k2] = g0 - g2; gi[0] = g0 + g2; gi[k3] = g1 - g3; gi[k1] = g1 + g3; gi += k4; fi += k4; } while (fi < fn); TRIG_INIT(k, c1, s1); i = 1; do { MYFLT c2, s2; TRIG_NEXT(k, c1, s1); c2 = c1 * c1 - s1 * s1; s2 = 2 * c1 * s1; fn = fz + n; fi = fz + i; gi = fz + k1 - i; do { MYFLT a, b, g0, f0, f1, g1, f2, g2, f3, g3; b = s2 * fi[k1] - c2 * gi[k1]; a = c2 * fi[k1] + s2 * gi[k1]; f1 = fi[0] - a; f0 = fi[0] + a; g1 = gi[0] - b; g0 = gi[0] + b; b = s2 * fi[k3] - c2 * gi[k3]; a = c2 * fi[k3] + s2 * gi[k3]; f3 = fi[k2] - a; f2 = fi[k2] + a; g3 = gi[k2] - b; g2 = gi[k2] + b; b = s1 * f2 - c1 * g3; a = c1 * f2 + s1 * g3; fi[k2] = f0 - a; fi[0] = f0 + a; gi[k3] = g1 - b; gi[k1] = g1 + b; b = c1 * g2 - s1 * f3; a = s1 * g2 + c1 * f3; gi[k2] = g0 - a; gi[0] = g0 + a; fi[k3] = f1 - b; fi[k1] = f1 + b; gi += k4; fi += k4; } while (fi < fn); i++; } while (i < kx); } while (k4 < n); } static int Xsynthset(CSOUND *csound, CON *p) { uint32_t flen, bufsize; MYFLT *b; FUNC *ftp; MYFLT ovlp = *p->ovlp; flen = (int32)*p->len; if (UNLIKELY(flen<1)) return csound->InitError(csound, Str("cross2: length must be at least 1")); p->m = plog2(flen); flen = 1L << p->m; if (ovlp < FL(2.0)) ovlp = FL(2.0); else if (ovlp > (MYFLT)(flen+flen)) ovlp = (MYFLT)(flen+flen); ovlp = (MYFLT)(1 << (int)plog2((int32)ovlp)); bufsize = 10 * flen * sizeof(MYFLT); if (p->mem.auxp == NULL || bufsize > p->mem.size) csound->AuxAlloc(csound, bufsize, &p->mem); else memset(p->mem.auxp, 0, (size_t)bufsize); /* Replaces loop */ b = (MYFLT*)p->mem.auxp; p->buffer_in1 = b; b += 2 * flen; p->buffer_in2 = b; b += 2 * flen; p->buffer_out = b; b += 2 * flen; p->in1 = b; b += 2 * flen; p->in2 = b; b += 2 * flen; if ((ftp = csound->FTnp2Find(csound, p->iwin)) != NULL) p->win = ftp; else return NOTOK; p->count = 0; p->s_ovlp = ovlp; return OK; } static int Xsynth(CSOUND *csound, CON *p) { MYFLT *s, *f, *out, *buf1, *buf2, *outbuf, rfn; int32 size, div; int32 n, m; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, nsmps = CS_KSMPS; s = p->as; f = p->af; out = p->out; outbuf = p->buffer_out; buf1 = p->buffer_in1; buf2 = p->buffer_in2; size = (int32)*p->len; div = size / (int32)p->s_ovlp; rfn = (MYFLT)p->win->flen / (MYFLT)size; /* Moved here for efficiency */ n = p->count; m = n % div; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (nn = offset; nn < nsmps; nn++) { buf1[n] = s[nn]; buf2[n] = f[nn]; out[nn] = outbuf[n]; n++; m++; if (n == size) n = 0; /* Moved to here from inside loop */ if (m == div) { /* wrap */ int32 i, mask, index; MYFLT window; MYFLT *x, *y, *win; m = 0; mask = size - 1; win = p->win->ftable; x = p->in1; y = p->in2; for (i = 0 ; i < size ; i++) { window = win[(int32)(i * rfn)]; index = (i + n) & mask; x[i] = buf1[index] * window; y[i] = buf2[index] * window; } memset(&x[size], 0, sizeof(MYFLT)*size); memset(&y[size], 0, sizeof(MYFLT)*size); /* for (; i < 2 * size ; i++) { */ /* x[i] = FL(0.0); */ /* y[i] = FL(0.0); */ /* } */ if (*p->bias != FL(0.0)) { int nsize = (int)(size+size); do_fht( x, nsize); do_fht( y, nsize); getmag( y, nsize); lineaprox( y, nsize, 16); mult( x, y, nsize, *p->bias); do_ifht( x, nsize); } for (i = n + size - div ; i < n + size ; i++) outbuf[i&mask] = FL(0.0); window = FL(5.0) / p->s_ovlp; for (i = 0 ; i < size ; i++) outbuf[(i+n)&mask] += x[i] * window; } if (n == size) n = 0; /* Moved to here from inside loop */ } p->count = n; return OK; } #define S(x) sizeof(x) static OENTRY localops[] = { { "cross2", S(CON), TR, 5, "a", "aaiiik",(SUBR)Xsynthset, NULL, (SUBR)Xsynth} }; int cross2_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/crossfm.c000066400000000000000000000316641321653344700163270ustar00rootroot00000000000000/* crossfm.c: Copyright (C) 2005 Francois Pinot This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "interlocks.h" #include "crossfm.h" #include int xfmset(CSOUND *csound, CROSSFM *p) { FUNC *ftp1 = csound->FTnp2Find(csound, p->ifn1); FUNC *ftp2 = csound->FTnp2Find(csound, p->ifn2); if (UNLIKELY(ftp1 == NULL || ftp2 == NULL)) { return csound->InitError(csound, Str("crossfm: ftable not found")); } p->siz1 = (MYFLT)ftp1->flen; p->siz2 = (MYFLT)ftp2->flen; p->ftp1 = ftp1; p->ftp2 = ftp2; if (*p->iphs1 >= FL(0.0)) { p->phase1 = *p->iphs1; p->sig1 = FL(0.0); } if (*p->iphs2 >= FL(0.0)) { p->phase2 = *p->iphs2; p->sig2 = FL(0.0); } p->frq1adv = IS_ASIG_ARG(p->xfrq1) ? 1 : 0; p->frq2adv = IS_ASIG_ARG(p->xfrq2) ? 1 : 0; p->ndx1adv = IS_ASIG_ARG(p->xndx1) ? 1 : 0; p->ndx2adv = IS_ASIG_ARG(p->xndx2) ? 1 : 0; return OK; } int xfm(CSOUND *csound, CROSSFM *p) { MYFLT *out1, *out2; MYFLT *xfrq1, *xfrq2, *xndx1, *xndx2; MYFLT k, cps; MYFLT frq1, frq2, si1, si2; MYFLT siz1, siz2; MYFLT *tbl1, *tbl2; MYFLT phase1, phase2; MYFLT sig1, sig2; int n1, n2; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; out1 = p->aout1; out2 = p->aout2; xfrq1 = p->xfrq1; xfrq2 = p->xfrq2; xndx1 = p->xndx1; xndx2 = p->xndx2; siz1 = p->siz1; siz2 = p->siz2; tbl1 = p->ftp1->ftable; tbl2 = p->ftp2->ftable; cps = *p->kcps; k = csound->onedsr; phase1 = p->phase1; phase2 = p->phase2; sig1 = p->sig1; sig2 = p->sig2; if (UNLIKELY(offset)) { memset(out1, '\0', offset*sizeof(MYFLT)); memset(out2, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&out1[nsmps], '\0', early*sizeof(MYFLT)); memset(&out2[nsmps], '\0', early*sizeof(MYFLT)); } for (i = offset; i < nsmps; i++) { frq1 = *xfrq1 * cps; frq2 = *xfrq2 * cps; si1 = (frq1 + *xndx2 * frq2 * sig2) * k; si2 = (frq2 + *xndx1 * frq1 * sig1) * k; out1[i] = sig1; out2[i] = sig2; phase1 += si1; phase1 -= FLOOR(phase1); phase2 += si2; phase2 -= FLOOR(phase2); n1 = (int)(phase1 * siz1); n2 = (int)(phase2 * siz2); sig1 = tbl1[n1]; sig2 = tbl2[n2]; xfrq1 += p->frq1adv; xfrq2 += p->frq2adv; xndx1 += p->ndx1adv; xndx2 += p->ndx2adv; } p->phase1 = phase1; p->phase2 = phase2; p->sig1 = sig1; p->sig2 = sig2; return OK; } int xfmi(CSOUND *csound, CROSSFM *p) { MYFLT *out1, *out2; MYFLT *xfrq1, *xfrq2, *xndx1, *xndx2; MYFLT k, cps; MYFLT frq1, frq2, si1, si2; MYFLT siz1, siz2; MYFLT *tbl1, *tbl2; MYFLT phase1, phase2; MYFLT sig1, sig2; MYFLT x, y1, y2; int n1, n2; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; out1 = p->aout1; out2 = p->aout2; xfrq1 = p->xfrq1; xfrq2 = p->xfrq2; xndx1 = p->xndx1; xndx2 = p->xndx2; siz1 = p->siz1; siz2 = p->siz2; tbl1 = p->ftp1->ftable; tbl2 = p->ftp2->ftable; cps = *p->kcps; k = csound->onedsr; phase1 = p->phase1; phase2 = p->phase2; sig1 = p->sig1; sig2 = p->sig2; if (UNLIKELY(offset)) { memset(out1, '\0', offset*sizeof(MYFLT)); memset(out2, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&out1[nsmps], '\0', early*sizeof(MYFLT)); memset(&out2[nsmps], '\0', early*sizeof(MYFLT)); } for (i = offset; i < nsmps; i++) { frq1 = *xfrq1 * cps; frq2 = *xfrq2 * cps; si1 = (frq1 + *xndx2 * frq2 * sig2) * k; si2 = (frq2 + *xndx1 * frq1 * sig1) * k; out1[i] = sig1; out2[i] = sig2; phase1 += si1; phase1 -= FLOOR(phase1); phase2 += si2; phase2 -= FLOOR(phase2); x = phase1 * siz1; n1 = (int)x; y1 = tbl1[n1]; sig1 = (tbl1[n1+1]-y1) * (x - FLOOR(x)) + y1; x = phase2 * siz2; n2 = (int)x; y2 = tbl2[n2]; sig2 = (tbl2[n2+1]-y2) * (x - FLOOR(x)) + y2; xfrq1 += p->frq1adv; xfrq2 += p->frq2adv; xndx1 += p->ndx1adv; xndx2 += p->ndx2adv; } p->phase1 = phase1; p->phase2 = phase2; p->sig1 = sig1; p->sig2 = sig2; return OK; } int xpm(CSOUND *csound, CROSSFM *p) { MYFLT *out1, *out2; MYFLT *xfrq1, *xfrq2, *xndx1, *xndx2; MYFLT k, cps; MYFLT frq1, frq2, si1, si2; MYFLT siz1, siz2; MYFLT *tbl1, *tbl2; MYFLT phase1, phase2; MYFLT sig1, sig2; int n1, n2; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; out1 = p->aout1; out2 = p->aout2; xfrq1 = p->xfrq1; xfrq2 = p->xfrq2; xndx1 = p->xndx1; xndx2 = p->xndx2; siz1 = p->siz1; siz2 = p->siz2; tbl1 = p->ftp1->ftable; tbl2 = p->ftp2->ftable; cps = *p->kcps; k = csound->onedsr; phase1 = p->phase1; phase2 = p->phase2; sig1 = p->sig1; sig2 = p->sig2; if (UNLIKELY(offset)) { memset(out1, '\0', offset*sizeof(MYFLT)); memset(out2, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&out1[nsmps], '\0', early*sizeof(MYFLT)); memset(&out2[nsmps], '\0', early*sizeof(MYFLT)); } for (i = offset; i < nsmps; i++) { frq1 = *xfrq1 * cps; frq2 = *xfrq2 * cps; out1[i] = sig1; out2[i] = sig2; phase1 += (frq1 * k); si1 = phase1 + *xndx2 * sig2 / TWOPI_F; si1 -= FLOOR(si1); phase2 += (frq2 * k); si2 = phase2 + *xndx1 * sig1 / TWOPI_F; si2 -= FLOOR(si2); n1 = (int)(si1 * siz1); n2 = (int)(si2 * siz2); sig1 = tbl1[n1]; sig2 = tbl2[n2]; xfrq1 += p->frq1adv; xfrq2 += p->frq2adv; xndx1 += p->ndx1adv; xndx2 += p->ndx2adv; } p->phase1 = phase1 - FLOOR(phase1); p->phase2 = phase2 - FLOOR(phase2); p->sig1 = sig1; p->sig2 = sig2; return OK; } int xpmi(CSOUND *csound, CROSSFM *p) { MYFLT *out1, *out2; MYFLT *xfrq1, *xfrq2, *xndx1, *xndx2; MYFLT k, cps; MYFLT frq1, frq2, si1, si2; MYFLT siz1, siz2; MYFLT *tbl1, *tbl2; MYFLT phase1, phase2; MYFLT sig1, sig2; MYFLT x, y1, y2; int n1, n2; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; out1 = p->aout1; out2 = p->aout2; xfrq1 = p->xfrq1; xfrq2 = p->xfrq2; xndx1 = p->xndx1; xndx2 = p->xndx2; siz1 = p->siz1; siz2 = p->siz2; tbl1 = p->ftp1->ftable; tbl2 = p->ftp2->ftable; cps = *p->kcps; k = csound->onedsr; phase1 = p->phase1; phase2 = p->phase2; sig1 = p->sig1; sig2 = p->sig2; if (UNLIKELY(offset)) { memset(out1, '\0', offset*sizeof(MYFLT)); memset(out2, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&out1[nsmps], '\0', early*sizeof(MYFLT)); memset(&out2[nsmps], '\0', early*sizeof(MYFLT)); } for (i = offset; i < nsmps; i++) { frq1 = *xfrq1 * cps; frq2 = *xfrq2 * cps; out1[i] = sig1; out2[i] = sig2; phase1 += (frq1 * k); si1 = phase1 + *xndx2 * sig2 / TWOPI_F; si1 -= FLOOR(si1); phase2 += (frq2 * k); si2 = phase2 + *xndx1 * sig1 / TWOPI_F; si2 -= FLOOR(si2); x = si1 * siz1; n1 = (int)x; y1 = tbl1[n1]; sig1 = (tbl1[n1+1]-y1) * (x - FLOOR(x)) + y1; x = si2 * siz2; n2 = (int)x; y2 = tbl2[n2]; sig2 = (tbl2[n2+1]-y2) * (x - FLOOR(x)) + y2; xfrq1 += p->frq1adv; xfrq2 += p->frq2adv; xndx1 += p->ndx1adv; xndx2 += p->ndx2adv; } p->phase1 = phase1 - FLOOR(phase1); p->phase2 = phase2 - FLOOR(phase2); p->sig1 = sig1; p->sig2 = sig2; return OK; } int xfmpm(CSOUND *csound, CROSSFM *p) { MYFLT *out1, *out2; MYFLT *xfrq1, *xfrq2, *xndx1, *xndx2; MYFLT k, cps; MYFLT frq1, frq2, si1, si2; MYFLT siz1, siz2; MYFLT *tbl1, *tbl2; MYFLT phase1, phase2; MYFLT sig1, sig2; int n1, n2; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; out1 = p->aout1; out2 = p->aout2; xfrq1 = p->xfrq1; xfrq2 = p->xfrq2; xndx1 = p->xndx1; xndx2 = p->xndx2; siz1 = p->siz1; siz2 = p->siz2; tbl1 = p->ftp1->ftable; tbl2 = p->ftp2->ftable; cps = *p->kcps; k = csound->onedsr; phase1 = p->phase1; phase2 = p->phase2; sig1 = p->sig1; sig2 = p->sig2; if (UNLIKELY(offset)) { memset(out1, '\0', offset*sizeof(MYFLT)); memset(out2, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&out1[nsmps], '\0', early*sizeof(MYFLT)); memset(&out2[nsmps], '\0', early*sizeof(MYFLT)); } for (i = offset; i < nsmps; i++) { frq1 = *xfrq1 * cps; frq2 = *xfrq2 * cps; out1[i] = sig1; out2[i] = sig2; si1 = (frq1 + *xndx2 * frq2 * sig2) * k; phase1 += si1; phase1 -= FLOOR(phase1); phase2 += (frq2 * k); si2 = phase2 + *xndx1 * sig1 / TWOPI_F; si2 -= FLOOR(si2); n1 = (int)(phase1 * siz1); n2 = (int)(si2 * siz2); sig1 = tbl1[n1]; sig2 = tbl2[n2]; xfrq1 += p->frq1adv; xfrq2 += p->frq2adv; xndx1 += p->ndx1adv; xndx2 += p->ndx2adv; } p->phase1 = phase1; p->phase2 = phase2 - FLOOR(phase2); p->sig1 = sig1; p->sig2 = sig2; return OK; } int xfmpmi(CSOUND *csound, CROSSFM *p) { MYFLT *out1, *out2; MYFLT *xfrq1, *xfrq2, *xndx1, *xndx2; MYFLT k, cps; MYFLT frq1, frq2, si1, si2; MYFLT siz1, siz2; MYFLT *tbl1, *tbl2; MYFLT phase1, phase2; MYFLT sig1, sig2; MYFLT x, y1, y2; int n1, n2; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; out1 = p->aout1; out2 = p->aout2; xfrq1 = p->xfrq1; xfrq2 = p->xfrq2; xndx1 = p->xndx1; xndx2 = p->xndx2; siz1 = p->siz1; siz2 = p->siz2; tbl1 = p->ftp1->ftable; tbl2 = p->ftp2->ftable; cps = *p->kcps; k = csound->onedsr; phase1 = p->phase1; phase2 = p->phase2; sig1 = p->sig1; sig2 = p->sig2; if (UNLIKELY(offset)) { memset(out1, '\0', offset*sizeof(MYFLT)); memset(out2, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&out1[nsmps], '\0', early*sizeof(MYFLT)); memset(&out2[nsmps], '\0', early*sizeof(MYFLT)); } for (i = offset; i < nsmps; i++) { frq1 = *xfrq1 * cps; frq2 = *xfrq2 * cps; out1[i] = sig1; out2[i] = sig2; si1 = (frq1 + *xndx2 * frq2 * sig2) * k; phase1 += si1; phase1 -= FLOOR(phase1); phase2 += (frq2 * k); si2 = phase2 + *xndx1 * sig1 / TWOPI_F; si2 -= FLOOR(si2); x = phase1 * siz1; n1 = (int)x; y1 = tbl1[n1]; sig1 = (tbl1[n1+1]-y1) * (x - FLOOR(x)) + y1; x = si2 * siz2; n2 = (int)x; y2 = tbl2[n2]; sig2 = (tbl2[n2+1]-y2) * (x - FLOOR(x)) + y2; xfrq1 += p->frq1adv; xfrq2 += p->frq2adv; xndx1 += p->ndx1adv; xndx2 += p->ndx2adv; } p->phase1 = phase1; p->phase2 = phase2 - FLOOR(phase2); p->sig1 = sig1; p->sig2 = sig2; return OK; } #define S sizeof static OENTRY crossfm_localops[] = { { "crossfm", S(CROSSFM), TR, 5, "aa", "xxxxkiioo", (SUBR)xfmset, NULL, (SUBR)xfm }, { "crossfmi", S(CROSSFM), TR, 5, "aa", "xxxxkiioo",(SUBR)xfmset,NULL, (SUBR)xfmi }, { "crosspm", S(CROSSFM), TR, 5, "aa", "xxxxkiioo", (SUBR)xfmset, NULL, (SUBR)xpm }, { "crosspmi", S(CROSSFM), TR, 5, "aa", "xxxxkiioo",(SUBR)xfmset,NULL, (SUBR)xpmi }, { "crossfmpm", S(CROSSFM), TR, 5, "aa", "xxxxkiioo",(SUBR)xfmset,NULL,(SUBR)xfmpm}, { "crossfmpmi", S(CROSSFM),TR, 5, "aa", "xxxxkiioo", (SUBR)xfmset, NULL, (SUBR)xfmpmi }, }; LINKAGE_BUILTIN(crossfm_localops) csound-6.10.0/Opcodes/crossfm.h000066400000000000000000000067351321653344700163350ustar00rootroot00000000000000/* crossfm.h: Copyright (C) 2005 Francois Pinot This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /*********************************************************************/ /* Header file for the plugin opcode crossfm */ /* */ /* crossfm implements a crossed frequency modulation algorithm. */ /* The audio-rate output of oscillator #1 is used to modulate the */ /* frequency input of oscillator #2 and the audio-rate output of */ /* oscillator #2 is used to modulate the frequency input of */ /* oscillator #1. */ /* */ /* a1,a2 crossfm xfrq1, xfrq2, xndx1, xndx2, kcps, ifn1, ifn2 */ /* [, iphs1] [, iphs2] */ /* */ /* kcps - base frequency */ /* xfrq1 - frequency multiplier for oscillator #1. Oscillator #1 */ /* effective frequency is kcps * xfrq1 */ /* xfrq2 - frequency multiplier for oscillator #2. Oscillator #2 */ /* effective frequency is kcps * xfrq2 */ /* xndx1 - index of the modulation of oscillator #2 by oscillator #1 */ /* xndx2 - index of the modulation of oscillator #1 by oscillator #2 */ /* ifn1 - function table number for oscillator #1 */ /* ifn2 - function table number for oscillator #2 */ /* iphs1 - optional, initial phase of waveform in table #1 */ /* iphs2 - optional, initial phase of waveform in table #2 */ /* */ /*********************************************************************/ typedef struct { OPDS h; /* common to all opcodes */ MYFLT *aout1, *aout2; /* output args */ MYFLT *xfrq1, *xfrq2, *xndx1, *xndx2; /* input args */ MYFLT *kcps, *ifn1, *ifn2; /* input args */ MYFLT *iphs1, *iphs2; /* input args */ MYFLT phase1, phase2; /* phase of oscillators */ MYFLT sig1, sig2; /* a-rate oscillators outputs */ MYFLT siz1, siz2; /* size of funtion tables */ FUNC *ftp1, *ftp2; /* function table pointers */ short frq1adv, frq2adv, ndx1adv, ndx2adv; /* increment values for xargs */ /* pointers (0 for i-rate and */ /* k-rate, 1 for a-rate args */ } CROSSFM; csound-6.10.0/Opcodes/cuda/000077500000000000000000000000001321653344700154115ustar00rootroot00000000000000csound-6.10.0/Opcodes/cuda/CMakeLists.txt000066400000000000000000000047711321653344700201620ustar00rootroot00000000000000option(BUILD_CUDA_OPCODES "Build the CUDA GPU opcodes" OFF) if(BUILD_CUDA_OPCODES) FIND_PACKAGE(CUDA REQUIRED) check_deps(BUILD_CUDA_OPCODES CUDA_FOUND) if(BUILD_CUDA_OPCODES) function(make_cuda_plugin libname srcs) SET(LIB_TYPE_DYNAMIC) #set the lib type CUDA_ADD_LIBRARY(${libname} ${LIB_TYPE} ${srcs}) set(i 2) while( ${i} LESS ${ARGC} ) if(NOT MSVC OR NOT("${ARGV${i}}" MATCHES "m")) target_link_libraries(${libname} ${ARGV${i}}) endif() math(EXPR i "${i}+1") endwhile() set_target_properties(${libname} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${BUILD_PLUGINS_DIR} LIBRARY_OUTPUT_DIRECTORY ${BUILD_PLUGINS_DIR} ARCHIVE_OUTPUT_DIRECTORY ${BUILD_PLUGINS_DIR}) install(TARGETS ${libname} LIBRARY DESTINATION "${PLUGIN_INSTALL_DIR}" ) endfunction(make_cuda_plugin) #find_library(CUFFT cufft HINTS "/Developer/NVIDIA/CUDA-6.0/lib") include_directories(${CMAKE_HOME_DIRECTORY}/include) include_directories(/usr/local/include) if(APPLE) if(CMAKE_OSX_DEPLOYMENT_TARGET MATCHES 10.6) SET(CUDA_NVCC_FLAGS "-arch=sm_11 -use_fast_math" CACHE STRING "nvcc flags" FORCE) make_cuda_plugin(cudaop1 adsyn11.cu) make_cuda_plugin(cudaop2 pvsopsf.cu) make_cuda_plugin(cudaop3 slidingm.cu) make_cuda_plugin(cudaop4 convf.cu) make_cuda_plugin(cudaop5 pconv11.cu) CUDA_ADD_CUFFT_TO_TARGET(cudaop2) CUDA_ADD_CUFFT_TO_TARGET(cudaop5) # target_link_libraries(cudaop2 ${CUFFT}) #target_link_libraries(cudaop5 ${CUFFT}) else() SET(CUDA_NVCC_FLAGS "-ccbin /usr/bin/clang -arch=sm_30 -Xcompiler -stdlib=libstdc++ -use_fast_math" CACHE STRING "nvcc flags" FORCE) make_cuda_plugin(cudaop1 adsyn.cu) make_cuda_plugin(cudaop2 pvsops.cu) make_cuda_plugin(cudaop3 slidingm.cu) make_cuda_plugin(cudaop4 conv.cu) make_cuda_plugin(cudaop5 pconv.cu) CUDA_ADD_CUFFT_TO_TARGET(cudaop2) CUDA_ADD_CUFFT_TO_TARGET(cudaop5) #target_link_libraries(cudaop5 ${CUFFT}) #target_link_libraries(cudaop2 ${CUFFT}) endif() else() SET(CUDA_NVCC_FLAGS "-arch=sm_20 -use_fast_math" CACHE STRING "nvcc flags" FORCE) make_cuda_plugin(cudaop1 adsyn.cu) make_cuda_plugin(cudaop2 pvsops.cu) make_cuda_plugin(cudaop3 slidingm.cu) make_cuda_plugin(cudaop4 conv.cu) make_cuda_plugin(cudaop5 pconv.cu) CUDA_ADD_CUFFT_TO_TARGET(cudaop2) CUDA_ADD_CUFFT_TO_TARGET(cudaop5) #target_link_libraries(cudaop5 ${CUFFT}) #target_link_libraries(cudaop2 ${CUFFT}) endif() SET (CUDA_VERBOSE_BUILD ON CACHE BOOL "nvcc verbose" FORCE) endif() endif() csound-6.10.0/Opcodes/cuda/adsyn.cu000066400000000000000000000130051321653344700170570ustar00rootroot00000000000000// -*- c++ -*- /* adsyn.cu experimental cuda opcodes (c) Victor Lazzarini, 2013 based on M Puckette's pitch tracking algorithm. This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include typedef struct cudadsyn_ { OPDS h; MYFLT *asig; PVSDAT *fsig; MYFLT *kamp, *kfreq; MYFLT *inum; float *out; float *frame; int64_t *ndx; float *fp, *previous; AUXCH out_; int bins, blocks, threads; int count; int vsamps, mblocks, mthreads; int framecount; } CUDADSYN; static int destroy_cudadsyn(CSOUND *csound, void *pp); static int init_cudadsyn(CSOUND *csound, CUDADSYN *p){ int asize, ipsize, fpsize, blockspt; if(p->fsig->overlap > 1024) return csound->InitError(csound, "overlap is too large\n"); cudaDeviceProp deviceProp; cudaGetDeviceProperties(&deviceProp, 0); blockspt = deviceProp.maxThreadsPerBlock; if(deviceProp.major < 2) return csound->InitError(csound, "this opcode requires device capability 2.0 minimum. Device is %d.%d\n", deviceProp.major, deviceProp.minor ); p->bins = (p->fsig->N)/2; if(*p->inum > 0 && *p->inum < p->bins) p->bins = *p->inum; p->vsamps = p->fsig->overlap; p->threads = p->bins*p->vsamps; p->blocks = p->threads > blockspt ? p->threads/blockspt : 1; p->mthreads = p->bins; p->mblocks = p->mthreads > blockspt ? p->mthreads/blockspt : 1; p->threads /= p->blocks; p->mthreads /= p->mblocks; asize = p->vsamps*sizeof(float); ipsize = p->fsig->N*sizeof(int64_t)/2; fpsize = p->fsig->N*sizeof(float); cudaMalloc(&p->out, asize); cudaMalloc(&p->ndx, ipsize); cudaMalloc(&p->frame, fpsize); cudaMalloc(&p->previous, fpsize/2); cudaMemset(p->previous, 0, fpsize/2); cudaMemset(p->ndx, 0, ipsize); cudaMemset(p->out, 0, sizeof(float)*p->vsamps); asize = p->vsamps*sizeof(float); if(p->out_.auxp == NULL || p->out_.size < asize) csound->AuxAlloc(csound, asize , &p->out_); csound->RegisterDeinitCallback(csound, p, destroy_cudadsyn); p->count = 0; return OK; } __global__ void sample(float *out, float *frame, float pitch, int64_t *ph, float *amps, int vsize, float sr) { int t = (threadIdx.x + blockIdx.x*blockDim.x); int n = t%vsize; /* sample index */ int h = t/vsize; /* bin index */ //if(amps[h] < 0.001) return; int k = h<<1; int64_t lph; float a = amps[h], ascl = ((float)n)/vsize; int64_t d = (int64_t) round(frame[k+1]*pitch*FMAXLEN/sr); lph = ph[h] + n*d; a += ascl*(frame[k] - a); atomicAdd(&out[n], a*sinf((2*PI*lph)/FMAXLEN)); // if(n) return; // ph[h] = (ph[h] + vsize*d) & PHMASK; // amps[h] = frame[k]; } __global__ void update(float *frame, float *amps, int64_t *ph,float pitch, int vsize, float sr){ int h = threadIdx.x + blockIdx.x*blockDim.x; int k = h << 1; /* update phases and amps */ ph[h] = (ph[h] + (int64_t)(vsize*round(pitch*frame[k+1]*FMAXLEN/sr))) & PHMASK; amps[h] = frame[k]; } static int perf_cudadsyn(CSOUND *csound, CUDADSYN *p){ uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; float *out_ = (float *) p->out_.auxp; MYFLT *asig = p->asig; int count = p->count, vsamps = p->vsamps; p->fp = (float *) (p->fsig->frame.auxp); if (UNLIKELY(offset)) memset(asig, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&asig[nsmps], '\0', early*sizeof(MYFLT)); } for(n=offset; n < nsmps; n++){ if(count == 0) { cudaMemcpy(out_,p->out,vsamps*sizeof(float),cudaMemcpyDeviceToHost); update<<mblocks,p->mthreads>>>(p->frame, p->previous, p->ndx, *p->kfreq, vsamps, csound->GetSr(csound)); cudaMemset(p->out, 0, sizeof(float)*vsamps); cudaMemcpy(p->frame,p->fp,sizeof(float)*p->bins*2,cudaMemcpyHostToDevice); sample<<blocks,p->threads>>>(p->out,p->frame, *p->kfreq, p->ndx, p->previous, vsamps, csound->GetSr(csound)); count = vsamps; } asig[n] = (MYFLT) out_[vsamps - count]; count--; } p->count = count; return OK; } static int destroy_cudadsyn(CSOUND *csound, void *pp){ CUDADSYN *p = (CUDADSYN *) pp; cudaFree(p->out); cudaFree(p->ndx); cudaFree(p->previous); cudaFree(p->frame); return OK; } static OENTRY localops[] = { {"cudasynth", sizeof(CUDADSYN),0, 5, "a", "fkko", (SUBR) init_cudadsyn, NULL, (SUBR) perf_cudadsyn} }; extern "C" { LINKAGE } csound-6.10.0/Opcodes/cuda/adsyn11.cu000066400000000000000000000131541321653344700172260ustar00rootroot00000000000000// -*- c++ -*- /* adsyn11.cu (c) Victor Lazzarini, 2013 based on M Puckette's pitch tracking algorithm. This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include typedef struct cudadsyn_ { OPDS h; MYFLT *asig; PVSDAT *fsig; MYFLT *kamp, *kfreq; MYFLT *inum; float *out; float *frame; int64_t *ndx; float *fp, *previous; AUXCH out_; int bins, blocks, threads; int count; int vsamps, mblocks, mthreads; int framecount; } CUDADSYN; static int destroy_cudadsyn(CSOUND *csound, void *pp); static int init_cudadsyn(CSOUND *csound, CUDADSYN *p){ int asize, ipsize, fpsize, blockspt; if(p->fsig->overlap > 1024) return csound->InitError(csound, "overlap is too large\n"); cudaDeviceProp deviceProp; cudaGetDeviceProperties(&deviceProp, 0); blockspt = deviceProp.maxThreadsPerBlock; if(deviceProp.major < 1) csound->InitError(csound, "this opcode requires device capability 1.0 minimum. Device is %d.%d\n", deviceProp.major, deviceProp.minor ); p->bins = (p->fsig->N)/2; if(*p->inum > 0 && *p->inum < p->bins) p->bins = *p->inum; p->vsamps = p->fsig->overlap; p->threads = p->bins*p->vsamps; p->blocks = p->threads > blockspt ? p->threads/blockspt : 1; p->mthreads = p->bins; p->mblocks = p->mthreads > blockspt ? p->mthreads/blockspt : 1; p->threads /= p->blocks; p->mthreads /= p->mblocks; asize = p->vsamps*p->bins*sizeof(float); ipsize = p->fsig->N*sizeof(int64_t)/2; fpsize = p->fsig->N*sizeof(float); cudaMalloc(&p->out, asize); cudaMalloc(&p->ndx, ipsize); cudaMalloc(&p->frame, fpsize); cudaMalloc(&p->previous, fpsize/2); cudaMemset(p->previous, 0, fpsize/2); cudaMemset(p->ndx, 0, ipsize); asize = p->vsamps*sizeof(float); if(p->out_.auxp == NULL || p->out_.size < asize) csound->AuxAlloc(csound, asize , &p->out_); csound->RegisterDeinitCallback(csound, p, destroy_cudadsyn); p->count = 0; return OK; } __global__ void sample(float *out, float *frame, float pitch, int64_t *ph, float *amps, int bins, int vsize, float sr) { int t = (threadIdx.x + blockIdx.x*blockDim.x); int n = t%vsize; /* sample index */ int h = t/vsize; /* bin index */ int k = h<<1; int64_t lph; float a = amps[h], ascl = ((float)n)/vsize; float fscal = pitch*FMAXLEN/sr; lph = (ph[h] + (int64_t)(n*round(frame[k+1]*fscal))) & PHMASK; a += ascl*(frame[k] - a); out[t] = a*sinf((2*PI*lph)/FMAXLEN); if(t >= vsize) return; syncthreads(); for(int i=vsize; i < vsize*bins; i+=vsize) out[t] += out[t + i]; } __global__ void update(float *frame, float *amps, int64_t *ph,float pitch, int vsize, float sr){ int h = threadIdx.x + blockIdx.x*blockDim.x; int k = h << 1; /* update phases and amps */ ph[h] = (ph[h] + (int64_t)(vsize*round(pitch*frame[k+1]*FMAXLEN/sr))) & PHMASK; amps[h] = frame[k]; } static int perf_cudadsyn(CSOUND *csound, CUDADSYN *p){ uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; float *out_ = (float *) p->out_.auxp; MYFLT *asig = p->asig; int count = p->count, vsamps = p->vsamps; p->fp = (float *) (p->fsig->frame.auxp); if (UNLIKELY(offset)) memset(asig, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&asig[nsmps], '\0', early*sizeof(MYFLT)); } for(n=offset; n < nsmps; n++){ if(count == 0) { cudaMemset(p->out, 0, sizeof(float)*vsamps); cudaMemcpy(p->frame,p->fp,sizeof(float)*p->bins*2,cudaMemcpyHostToDevice); sample<<blocks,p->threads>>>(p->out,p->frame, *p->kfreq, p->ndx, p->previous, p->bins, vsamps, csound->GetSr(csound)); if (cudaDeviceSynchronize() != cudaSuccess) csound->Message(csound,"Cuda error: Failed to synchronize\n"); update<<mblocks,p->mthreads>>>(p->frame, p->previous, p->ndx, *p->kfreq, vsamps, csound->GetSr(csound)); cudaMemcpy(out_,p->out,vsamps*sizeof(float),cudaMemcpyDeviceToHost); count = vsamps; } asig[n] = (MYFLT) out_[vsamps - count]; count--; } p->count = count; return OK; } static int destroy_cudadsyn(CSOUND *csound, void *pp){ CUDADSYN *p = (CUDADSYN *) pp; cudaFree(p->out); cudaFree(p->ndx); cudaFree(p->previous); cudaFree(p->frame); return OK; } static OENTRY localops[] = { {"cudasynth", sizeof(CUDADSYN),0, 5, "a", "fkko", (SUBR) init_cudadsyn, NULL, (SUBR) perf_cudadsyn} }; extern "C" { LINKAGE } csound-6.10.0/Opcodes/cuda/build.sh000066400000000000000000000016741321653344700170540ustar00rootroot00000000000000#!/bin/sh # use -Xptxas="-v" to check register usage and --maxrregcount 32 to limit it echo "building cuda opcodes ..." nvcc -O3 -shared -o libcudaop1.dylib adsyn.cu -use_fast_math -I../../debug/CsoundLib64.framework/Headers -arch=sm_30 -I/usr/local/cuda/include -L/usr/local/cuda/lib nvcc -O3 -shared -o libcudaop2.dylib pvsops.cu -use_fast_math -g -I../../debug/CsoundLib64.framework/Headers -arch=sm_30 -I/usr/local/cuda/include -L/usr/local/cuda/lib -lcufft nvcc -O3 -shared -o libcudaop3.dylib slidingm.cu -use_fast_math -I../../debug/CsoundLib64.framework/Headers -arch=sm_30 -I/usr/local/cuda/include -L/usr/local/cuda/lib nvcc -O3 -shared -o libcudaop4.dylib conv.cu -I../../debug/CsoundLib64.framework/Headers -arch=sm_30 -I/usr/local/cuda/include -L/usr/local/cuda/lib nvcc -O3 -shared -o libcudaop5.dylib pconv.cu -I../../debug/CsoundLib64.framework/Headers -arch=sm_30 -I/usr/local/cuda/include -L/usr/local/cuda/lib -lcufft echo "...done" csound-6.10.0/Opcodes/cuda/conv.cu000066400000000000000000000115141321653344700167110ustar00rootroot00000000000000// -*- c++ -*- /* conv.cu (c) Victor Lazzarini, 2013 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include __global__ void convol(MYFLT *out, MYFLT *del, MYFLT *coefs, int irsize, int rp, int vsize) { int t = (threadIdx.x + blockIdx.x*blockDim.x); if(t >= irsize*vsize) return; int n = t%vsize; /* sample index */ int h = t/vsize; /* coeff index */ int end = irsize+vsize; rp += n + h; /* read point, oldest -> newest */ out[t] = del[rp < end ? rp : rp%end]*coefs[irsize-1-h]; /* single tap */ if(t >= vsize) return; syncthreads(); MYFLT a = 0.0; for(int i=1, j=vsize; i < irsize; i++, j+=vsize) a += out[n + j]; /* mix all taps */ out[n] += a; } // __device__ double atomicAdd(double* address, double val) // { // unsigned long long int* address_as_ull = // (unsigned long long int*)address; // unsigned long long int old = *address_as_ull, assumed; // do { // assumed = old; // old = atomicCAS(address_as_ull, assumed, // __double_as_longlong(val + // __longlong_as_double(assumed))); // } while (assumed != old); // return __longlong_as_double(old); // } // __global__ void convol2(MYFLT *out, MYFLT *del, MYFLT *coefs, int irsize, int rp, int vsize) { // int t = (threadIdx.x + blockIdx.x*blockDim.x); // if(t >= irsize*vsize) return; // int n = t%vsize; /* sample index */ // int h = t/vsize; /* coeff index */ // int end = irsize+vsize; // rp += n + h; /* read point, oldest -> newest */ // MYFLT s = del[rp < end ? rp : rp%end]*coefs[irsize-1-h]; /* single tap */ // t == n ? out[n] = s : atomicAdd(&out[n], s); // } typedef struct _CONV { OPDS h; MYFLT *aout, *asig, *ifn; MYFLT *coeffs, *out, *del; int wp, irsize; int blocks, threads; } CONV; static int destroy_conv(CSOUND *csound, void *pp){ CONV *p = (CONV *) pp; cudaFree(p->coeffs); cudaFree(p->del); cudaFree(p->out); return OK; } static int conv_init(CSOUND *csound, CONV *p){ FUNC *ftab = csound->FTnp2Find(csound, p->ifn); int irsize = ftab->flen; int nsmps = CS_KSMPS; int threads = irsize*nsmps; cudaMalloc(&p->coeffs, sizeof(MYFLT)*irsize); cudaMemcpy(p->coeffs, ftab->ftable, sizeof(MYFLT)*irsize, cudaMemcpyHostToDevice); cudaMalloc(&p->del, sizeof(MYFLT)*(irsize+nsmps)); cudaMalloc(&p->out, sizeof(MYFLT)*threads); cudaMemset(p->del,0,sizeof(MYFLT)*(irsize+nsmps)); cudaMemset(p->out, 0, sizeof(MYFLT)*threads); p->wp = 0; p->irsize = irsize; cudaDeviceProp deviceProp; cudaGetDeviceProperties(&deviceProp, 0); int blockspt = deviceProp.maxThreadsPerBlock; csound->Message(csound, "CUDAconv: using device %s (capability %d.%d)\n", deviceProp.name,deviceProp.major, deviceProp.minor); p->blocks = threads > blockspt ? ceil(threads/blockspt) : 1; p->threads = threads > blockspt ? blockspt : threads; csound->RegisterDeinitCallback(csound, p, destroy_conv); OPARMS parms; csound->GetOParms(csound, &parms); if(parms.odebug) csound->Message(csound, "blocks %d, threads %d - %d\n", p->blocks, p->threads, threads); return OK; } /* the delay size is irsize + vsize so that we can shift in a whole block of samples */ int conv_perf(CSOUND *csound, CONV *p){ int nsmps = CS_KSMPS; MYFLT *sig = p->asig, *aout = p->aout; MYFLT *del = p->del, *out = p->out, *coefs = p->coeffs; int irsize = p->irsize; int wp = p->wp; if(wp > irsize) { int front = wp - irsize; cudaMemcpy(&del[wp], sig, sizeof(MYFLT)*(nsmps-front), cudaMemcpyHostToDevice); cudaMemcpy(del, &sig[nsmps-front], sizeof(MYFLT)*front, cudaMemcpyHostToDevice); } else cudaMemcpy(&del[wp], sig, sizeof(MYFLT)*nsmps, cudaMemcpyHostToDevice); wp = (wp+nsmps)%(irsize+nsmps); /* wp is now the oldest sample in the delay */ convol<<blocks,p->threads>>>(out, del, coefs, irsize, wp, nsmps); cudaMemcpy(aout, out, sizeof(MYFLT)*nsmps, cudaMemcpyDeviceToHost); p->wp = wp; return OK; } static OENTRY localops[] = { {"cudaconv", sizeof(CONV),0, 5, "a", "ai", (SUBR) conv_init, NULL, (SUBR) conv_perf}, }; extern "C" { LINKAGE } csound-6.10.0/Opcodes/cuda/convf.cu000066400000000000000000000103701321653344700170560ustar00rootroot00000000000000// -*- c++ -*- /* convf.cu (c) Victor Lazzarini, 2013 based on M Puckette's pitch tracking algorithm. This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include __global__ void convol(float *out, float *del, float *coefs, int irsize, int rp, int vsize) { int t = (threadIdx.x + blockIdx.x*blockDim.x); if(t >= irsize*vsize) return; int n = t%vsize; /* sample index */ int h = t/vsize; /* coeff index */ int end = irsize+vsize; rp += n + h; /* read point, oldest -> newest */ out[t] = del[rp < end ? rp : rp%end]*coefs[irsize-1-h]; /* single tap */ if(t >= vsize) return; syncthreads(); float a = 0.0; for(int i=1, j=vsize; i < irsize; i++, j+=vsize) a += out[n + j]; /* mix all taps */ out[n] += a; } typedef struct _CONV { OPDS h; MYFLT *aout, *asig, *ifn; float *coeffs, *out, *del; int wp, irsize; AUXCH buf; int blocks, threads; } CONV; static int destroy_conv(CSOUND *csound, void *pp){ CONV *p = (CONV *) pp; cudaFree(p->coeffs); cudaFree(p->del); cudaFree(p->out); return OK; } static int conv_init(CSOUND *csound, CONV *p){ FUNC *ftab = csound->FTnp2Find(csound, p->ifn); int irsize = ftab->flen; int nsmps = CS_KSMPS,i; int threads = irsize*nsmps; float *tmp; cudaMalloc(&p->coeffs, sizeof(float)*irsize); tmp = (float*) malloc(sizeof(float)*irsize); for(i=0; i< irsize; i++) tmp[i] = (float) ftab->ftable[i]; cudaMemcpy(p->coeffs,tmp, sizeof(float)*irsize, cudaMemcpyHostToDevice); free(tmp); cudaMalloc(&p->del, sizeof(float)*(irsize+nsmps)); cudaMalloc(&p->out, sizeof(float)*threads); cudaMemset(p->del,0,sizeof(float)*(irsize+nsmps)); cudaMemset(p->out, 0, sizeof(float)*threads); p->wp = 0; p->irsize = irsize; cudaDeviceProp deviceProp; cudaGetDeviceProperties(&deviceProp, 0); int blockspt = deviceProp.maxThreadsPerBlock; csound->Message(csound, "CUDAconv: using device %s (capability %d.%d)\n", deviceProp.name,deviceProp.major, deviceProp.minor); p->blocks = threads > blockspt ? ceil(threads/blockspt) : 1; p->threads = threads > blockspt ? blockspt : threads; csound->RegisterDeinitCallback(csound, p, destroy_conv); OPARMS parms; csound->GetOParms(csound, &parms); if(parms.odebug) csound->Message(csound, "blocks %d, threads %d - %d\n", p->blocks, p->threads, threads); if(p->buf.auxp == NULL) csound->AuxAlloc(csound, sizeof(float)*CS_KSMPS, &p->buf); return OK; } /* the delay size is irsize + vsize so that we can shift in a whole block of samples */ int conv_perf(CSOUND *csound, CONV *p){ int nsmps = CS_KSMPS; MYFLT *sig = p->asig, *aout = p->aout; float *del = p->del, *out = p->out, *coefs = p->coeffs, *buf = (float *)p->buf.auxp; int irsize = p->irsize; int wp = p->wp, i; for(i=0; i < nsmps; i++) buf[i] = (float) sig[i]; if(wp > irsize) { int front = wp - irsize; cudaMemcpy(&del[wp], buf, sizeof(float)*(nsmps-front), cudaMemcpyHostToDevice); cudaMemcpy(del, &buf[nsmps-front], sizeof(float)*front, cudaMemcpyHostToDevice); } else cudaMemcpy(&del[wp], buf, sizeof(float)*nsmps, cudaMemcpyHostToDevice); wp = (wp+nsmps)%(irsize+nsmps); /* wp is now the oldest sample in the delay */ convol<<blocks,p->threads>>>(out, del, coefs, irsize, wp, nsmps); cudaMemcpy(buf, out, sizeof(float)*nsmps, cudaMemcpyDeviceToHost); for(i=0; i < nsmps; i++) aout[i] = (float) buf[i]; p->wp = wp; return OK; } static OENTRY localops[] = { {"cudaconv", sizeof(CONV),0, 5, "a", "ai", (SUBR) conv_init, NULL, (SUBR) conv_perf}, }; extern "C" { LINKAGE } csound-6.10.0/Opcodes/cuda/cuda_pvs_example.csd000066400000000000000000000012161321653344700214230ustar00rootroot00000000000000 ;--opcode-lib=./libcudaop2.dylib ksmps = 64 0dbfs = 1 instr 1 ifftsize = 4096 ihopsize = 512 asig = diskin2:a("flutec3.wav",1,0,1) fsig = cudanal(asig, ifftsize, ihopsize, ifftsize, 1) asig = cudasynth(fsig) asig = linenr(asig,0.005,0.01,0.01) out(asig) endin instr 2 S1 = "flutec3.wav" ifftsize = 32768 ihopsize = 512 asig diskin2 S1, 1, 0, 1 fsig pvsanal asig, ifftsize, ihopsize, ifftsize, 1 a1 pvsynth fsig a2 linenr a1*0.5,0.005,0.01,0.01 out a2 endin i1 0 60 csound-6.10.0/Opcodes/cuda/cuda_sliding_example.csd000066400000000000000000000005661321653344700222530ustar00rootroot00000000000000 --opcode-lib=./libcudaop3.dylib ksmps = 64 0dbfs = 1 instr 1 asig,adp diskin "metheny.wav",1,0,1 amod = p4; oscil:a(2,3) asig2 = cudasliding(asig,amod,p5) asig = linenr(asig2,0.005,0.01,0.01) out(asig*0.5) endin i1 0 60 1 512 ;i1 0 5 0.5 1024 csound-6.10.0/Opcodes/cuda/cudaconv.csd000066400000000000000000000005511321653344700177070ustar00rootroot00000000000000 --opcode-lib=libcudaop4.dylib ksmps = 128 i1 ftgen 1,0,1024,1,"/Users/victor/audio/church.wav",0,0,1 instr 1 asig diskin2 "/Users/victor/audio/cornetto.wav",1,01 a1 cudaconv asig,1 ;a1 dconv asig,ftlen(1),1 out a1/20 endin i1 0 10 csound-6.10.0/Opcodes/cuda/cudadsyn_pvs_example.csd000066400000000000000000000013321321653344700223200ustar00rootroot00000000000000 --opcode-lib=./libcudaop1.dylib --opcode-lib=./libcudaop2.dylib ksmps = 64 0dbfs = 1 instr 1 ifftsize = 2048 ihopsize = 512 ibins = 1024 asig1,adp diskin "/users/victor/audio/metheny.wav",1,0,1 fsig = pvsanal(asig1, ifftsize,ihopsize, ifftsize, 1) asig = cudasynth(fsig,1,1,ibins) asig = linenr(asig,0.001,0.01,0.01) out(asig*0.5) endin instr 2 ifftsize = 2048 ihopsize = 512 ibins = 1024 asig1,adp diskin "/users/victor/audio/metheny.wav",1,0,1 fsig = pvsanal(asig1, ifftsize,ihopsize, ifftsize, 1) asig = pvsadsyn(fsig,ibins,1) asig = linenr(asig,0.001,0.01,0.01) out(asig*0.5) endin i1 0 60 csound-6.10.0/Opcodes/cuda/cudapconv.csd000066400000000000000000000015121321653344700200650ustar00rootroot00000000000000 ksmps = 8 nchnls =2 i1 ftgen 1,0,0,1,"church.wav",0,0,1 i2 ftgen 2,0,64,1,"church.wav",0,0,1 ;i1 ftgen 1,0,65536,7,1,1,1,0,65534,0 i1 ftgen 1,0,0,1,"/Users/victor/audio/metheny.wav",0,0,1 instr 1 ;asig oscili 0dbfs/4, 440; asig diskin2 "/Users/victor/audio/cornetto.wav",1,0,1 a1 cudapconv asig,1,16384 ;a2 cudaconv asig,2 ;a1 ftconv asig,1,64 ;a1 pconvolve asig,"/Users/victor/audio/church_00.wav",1024 out a1/500, a1/500 endin i1 0 60 100 100 320 240 true 255 255 255 csound-6.10.0/Opcodes/cuda/pconv.cu000066400000000000000000000161031321653344700170700ustar00rootroot00000000000000// -*- c++ -*- /* pconv.cu (c) Victor Lazzarini, 2013 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include /* each kernel processes one bin */ __global__ void pconvol(float *out,float *in, float *coef,int rp, int dftsize, int nparts, int end) { float re,im,re2,im2; /* thread count */ int t = (threadIdx.x + blockIdx.x*blockDim.x); int k = t<<1; /* coef pos */ int n = k%(dftsize+2); /* inframe pos */ /* if beyond the buffer end, exit */ if(k >= end) return; rp += k/(dftsize+2); /* rp pos */ /* select correct input buffer */ in += (rp < nparts ? rp : rp%nparts)*(dftsize+2); re = coef[k]; im = coef[k+1]; re2 = in[n]; im2 = in[n+1]; /* complex multiplication + sums */ atomicAdd(&out[n], re*re2 - im*im2); (n || n != dftsize) ? atomicAdd(&out[n+1], re*im2 + re2*im) : im; } /* sample-by-sample overlap-save operation */ __global__ void olapsave(float *buf, float *in, int parts){ int n = (threadIdx.x + blockIdx.x*blockDim.x); buf[n] = in[n] + buf[parts+n]; buf[parts+n] = in[parts+n]; } typedef struct _pconv{ OPDS h; MYFLT *aout, *asig, *ifn, *parts; float *out, *coef, *in, *buf; AUXCH bufin, bufout; int wp, nparts, dftsize, cnt; cufftHandle plan, iplan; int threads, blocks, othreads, oblocks; } PCONV; int isPowerOfTwo (unsigned int x) { return ((x != 0) && !(x & (x - 1))); } static int destroy_pconv(CSOUND *csound, void *pp){ PCONV *p = (PCONV *) pp; cufftDestroy(p->plan); cufftDestroy(p->iplan); cudaFree(p->coef); cudaFree(p->in); cudaFree(p->out); cudaFree(p->buf); return OK; } int pconv_init(CSOUND *csound, PCONV *p){ FUNC *ftab = csound->FTnp2Find(csound, p->ifn); float *tmp; int tlen = ftab->flen; int end, i, j, k, parts = *p->parts, dftsize, nparts; MYFLT *tab = ftab->ftable; if(!isPowerOfTwo(parts)) return csound->InitError(csound, "partition size needs to be power of two\n"); if(parts > tlen) return csound->InitError(csound, "partition size too big \n"); end = tlen + parts - 1; nparts = end / parts; dftsize = parts << 1; end = nparts*(dftsize+2); cudaMalloc(&p->coef, sizeof(float)*end); cudaMalloc(&p->in, sizeof(float)*end); cudaMalloc(&p->out, sizeof(float)*(dftsize+2)); cudaMalloc(&p->buf, sizeof(float)*(dftsize)); cudaMemset(p->in,0,sizeof(float)*end); cudaMemset(p->out, 0, sizeof(float)*(dftsize+2)); cudaMemset(p->buf, 0, sizeof(float)*(dftsize)); cudaMemset(p->coef, 0, sizeof(float)*end); p->wp = 0; if(!p->bufin.auxp || p->bufin.size < sizeof(float)*dftsize) csound->AuxAlloc(csound, sizeof(float)*dftsize, &p->bufin); if(!p->bufout.auxp || p->bufout.size < sizeof(float)*parts) csound->AuxAlloc(csound, sizeof(float)*parts, &p->bufout); memset(p->bufout.auxp, 0, sizeof(float)*parts); tmp = (float *) p->bufin.auxp; cufftPlan1d(&p->plan, dftsize, CUFFT_R2C, 1); cufftSetCompatibilityMode(p->plan, CUFFT_COMPATIBILITY_NATIVE); cufftPlan1d(&p->iplan, dftsize, CUFFT_C2R, 1); cufftSetCompatibilityMode(p->iplan, CUFFT_COMPATIBILITY_NATIVE); for(i =0, k=0; i < nparts; i++){ for(j=0; j < dftsize; j++) tmp[j] = j < parts && k < tlen ? tab[k++] : 0.f; float *pp = p->coef + (nparts - 1 - i)*(dftsize+2); cudaMemcpy(pp, tmp, sizeof(float)*dftsize, cudaMemcpyHostToDevice); cufftExecR2C(p->plan,pp,(cufftComplex*)pp); } cudaDeviceSynchronize(); cudaDeviceProp deviceProp; cudaGetDeviceProperties(&deviceProp, 0); int blockspt = deviceProp.maxThreadsPerBlock; end >>= 1; p->blocks = end > blockspt ? ceil(end/blockspt) : 1; p->threads = end > blockspt ? blockspt : end; p->oblocks = parts > blockspt ? ceil(parts/blockspt) : 1; p->othreads = parts > blockspt ? blockspt : parts; csound->RegisterDeinitCallback(csound, p, destroy_pconv); OPARMS parms; csound->GetOParms(csound, &parms); if(parms.odebug) csound->Message(csound, "blocks %d - threads/block %d - threads %d - dftsize %d - parts %d\n", p->blocks, p->threads, end, dftsize, nparts); p->nparts = nparts; p->dftsize = dftsize; p->cnt = 0; return OK; } int pconv_perf(CSOUND *csound, PCONV *p){ int dftsize = p->dftsize, cnt = p->cnt, wp = p->wp, nparts = p->nparts; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; float *bufin = (float *) p->bufin.auxp, *bufout = (float *) p->bufout.auxp; MYFLT *asig = p->asig, *aout = p->aout; float *in = p->in, *out = p->out, *coef = p->coef, *buf = p->buf; int end = nparts*(dftsize+2); int parts = *p->parts; if (UNLIKELY(offset)) memset(asig, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&asig[nsmps], '\0', early*sizeof(MYFLT)); } for(n = offset; n < nsmps; n++){ bufin[cnt] = (float) asig[n]; aout[n] = (MYFLT) bufout[cnt]/dftsize; if(++cnt == parts){ /* in buffer pos */ int pos = wp*(dftsize+2); /* increment delay line pos so that it points to the oldest partition */ wp += 1; if(wp == nparts) wp = 0; /* copy current buffer into newest partition */ cudaMemset(out, 0, sizeof(float)*(dftsize+2)); cudaMemcpy(&in[pos],bufin,sizeof(float)*dftsize,cudaMemcpyHostToDevice); /* apply transform */ if(cufftExecR2C(p->plan,&in[pos],(cufftComplex*)&in[pos]) != CUFFT_SUCCESS) csound->Message(csound, "cuda fft error\n"); if (cudaDeviceSynchronize() != cudaSuccess) csound->Message(csound,"Cuda error: Failed to synchronize\n"); /* convolution */ pconvol<<blocks,p->threads>>>(out, in, coef, wp, dftsize, nparts, end); if (cudaDeviceSynchronize() != cudaSuccess) csound->Message(csound,"Cuda error: Failed to synchronize\n"); /* transform output */ if(cufftExecC2R(p->iplan,(cufftComplex*)out,out) != CUFFT_SUCCESS) csound->Message(csound, "cuda fft error\n"); /* overlap-save */ olapsave<<oblocks,p->othreads>>>(buf,out,parts); /* copy buffer out */ cudaMemcpy(bufout,buf, sizeof(float)*parts,cudaMemcpyDeviceToHost); cnt = 0; } } p->cnt = cnt; p->wp = wp; return OK; } static OENTRY localops[] = { {"cudapconv", sizeof(PCONV),0, 5, "a", "aii", (SUBR) pconv_init, NULL, (SUBR) pconv_perf}, }; extern "C" { LINKAGE } csound-6.10.0/Opcodes/cuda/pconv11.cu000066400000000000000000000170331321653344700172350ustar00rootroot00000000000000// -*- c++ -*- /* pconv.cu experimental cuda opcodes (c) Victor Lazzarini, 2013 based on M Puckette's pitch tracking algorithm. This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include /* each kernel processes one bin */ __global__ void pconvol(float *out,float *in, float *coef,int rp, int dftsize, int nparts, int end) { float re,im,re2,im2; /* thread count */ int t = (threadIdx.x + blockIdx.x*blockDim.x); int k = t<<1; /* coef pos */ int n = k%(dftsize+2); /* inframe pos */ /* if beyond the buffer end, exit */ if(k >= end) return; rp += k/(dftsize+2); /* rp pos */ /* select correct input buffer */ in += (rp < nparts ? rp : rp%nparts)*(dftsize+2); re = coef[k]; im = coef[k+1]; re2 = in[n]; im2 = in[n+1]; /* complex multiplication + sums */ out[k] = re*re2 - im*im2; out[k+1] = re*im2 + re2*im; if(t > dftsize+1) return; syncthreads(); for(int i=dftsize+2; i < end; i+=(dftsize+2)) out[t] += out[t + i]; } /* sample-by-sample overlap-save operation */ __global__ void olapsave(float *buf, float *in, int parts){ int n = (threadIdx.x + blockIdx.x*blockDim.x); buf[n] = in[n] + buf[parts+n]; buf[parts+n] = in[parts+n]; } typedef struct _pconv{ OPDS h; MYFLT *aout, *asig, *ifn, *parts; float *out, *coef, *in, *buf; AUXCH bufin, bufout; int wp, nparts, dftsize, cnt; cufftHandle plan, iplan; int threads, blocks, othreads, oblocks; } PCONV; int isPowerOfTwo (unsigned int x) { return ((x != 0) && !(x & (x - 1))); } static int destroy_pconv(CSOUND *csound, void *pp){ PCONV *p = (PCONV *) pp; cufftDestroy(p->plan); cufftDestroy(p->iplan); cudaFree(p->coef); cudaFree(p->in); cudaFree(p->out); cudaFree(p->buf); return OK; } int pconv_init(CSOUND *csound, PCONV *p){ FUNC *ftab = csound->FTnp2Find(csound, p->ifn); float *tmp; int tlen = ftab->flen; int end, i, j, k, parts = *p->parts, dftsize, nparts; MYFLT *tab = ftab->ftable; if(!isPowerOfTwo(parts)) return csound->InitError(csound, "partition size needs to be power of two\n"); if(parts > tlen) return csound->InitError(csound, "partition size too big \n"); end = tlen + parts - 1; nparts = end / parts; dftsize = parts << 1; end = nparts*(dftsize+2); cudaMalloc(&p->coef, sizeof(float)*end); cudaMalloc(&p->in, sizeof(float)*end); cudaMalloc(&p->out, sizeof(float)*end); cudaMalloc(&p->buf, sizeof(float)*(dftsize)); cudaMemset(p->in,0,sizeof(float)*end); cudaMemset(p->out, 0, sizeof(float)*end); cudaMemset(p->buf, 0, sizeof(float)*(dftsize)); cudaMemset(p->coef, 0, sizeof(float)*end); p->wp = 0; if(!p->bufin.auxp || p->bufin.size < sizeof(float)*dftsize) csound->AuxAlloc(csound, sizeof(float)*dftsize, &p->bufin); if(!p->bufout.auxp || p->bufout.size < sizeof(float)*parts) csound->AuxAlloc(csound, sizeof(float)*parts, &p->bufout); memset(p->bufout.auxp, 0, sizeof(float)*parts); cufftResult res; tmp = (float *) p->bufin.auxp; if((res = cufftPlan1d(&p->plan, dftsize, CUFFT_R2C, 1)) != CUFFT_SUCCESS) csound->Message(csound, "cuda fft setup error %d\n", res); cufftSetCompatibilityMode(p->plan, CUFFT_COMPATIBILITY_NATIVE); cufftPlan1d(&p->iplan, dftsize, CUFFT_C2R, 1); cufftSetCompatibilityMode(p->iplan, CUFFT_COMPATIBILITY_NATIVE); for(i =0, k=0; i < nparts; i++){ for(j=0; j < dftsize; j++) tmp[j] = j < parts && k < tlen ? tab[k++] : 0.f; float *pp = p->coef + (nparts - 1 - i)*(dftsize+2); cudaMemcpy(pp, tmp, sizeof(float)*dftsize, cudaMemcpyHostToDevice); if((res = cufftExecR2C(p->plan,pp,(cufftComplex*)pp)) != CUFFT_SUCCESS) csound->Message(csound, "cuda fft error %d\n", res); } cudaDeviceSynchronize(); cudaDeviceProp deviceProp; cudaGetDeviceProperties(&deviceProp, 0); int blockspt = deviceProp.maxThreadsPerBlock; end >>= 1; p->blocks = end > blockspt ? ceil(end/blockspt) : 1; p->threads = end > blockspt ? blockspt : end; p->oblocks = parts > blockspt ? ceil(parts/blockspt) : 1; p->othreads = parts > blockspt ? blockspt : parts; csound->RegisterDeinitCallback(csound, p, destroy_pconv); OPARMS parms; csound->GetOParms(csound, &parms); if(parms.odebug) csound->Message(csound, "blocks %d - threads/block %d - threads %d - dftsize %d - parts %d\n", p->blocks, p->threads, end, dftsize, nparts); p->nparts = nparts; p->dftsize = dftsize; p->cnt = 0; return OK; } int pconv_perf(CSOUND *csound, PCONV *p){ int dftsize = p->dftsize, cnt = p->cnt, wp = p->wp, nparts = p->nparts; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; float *bufin = (float *) p->bufin.auxp, *bufout = (float *) p->bufout.auxp; MYFLT *asig = p->asig, *aout = p->aout; float *in = p->in, *out = p->out, *coef = p->coef, *buf = p->buf; int end = nparts*(dftsize+2); int parts = *p->parts; if (UNLIKELY(offset)) memset(asig, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&asig[nsmps], '\0', early*sizeof(MYFLT)); } for(n = offset; n < nsmps; n++){ bufin[cnt] = (float) asig[n]; aout[n] = (MYFLT) bufout[cnt]/dftsize; if(++cnt == parts){ /* in buffer pos */ int pos = wp*(dftsize+2); /* increment delay line pos so that it points to the oldest partition */ wp += 1; if(wp == nparts) wp = 0; /* copy current buffer into newest partition */ cudaMemset(out, 0, sizeof(float)*(dftsize+2)); cudaMemcpy(&in[pos],bufin,sizeof(float)*dftsize,cudaMemcpyHostToDevice); /* apply transform */ if(cufftExecR2C(p->plan,&in[pos],(cufftComplex*)&in[pos]) != CUFFT_SUCCESS) csound->Message(csound, "cuda in fft error\n"); if (cudaDeviceSynchronize() != cudaSuccess) csound->Message(csound,"Cuda error: Failed to synchronize\n"); /* convolution */ pconvol<<blocks,p->threads>>>(out, in, coef, wp, dftsize, nparts, end); if (cudaDeviceSynchronize() != cudaSuccess) csound->Message(csound,"Cuda error: Failed to synchronize\n"); /* transform output */ if(cufftExecC2R(p->iplan,(cufftComplex*)out,out) != CUFFT_SUCCESS) csound->Message(csound, "cuda out fft error\n"); if (cudaDeviceSynchronize() != cudaSuccess) csound->Message(csound,"Cuda error: Failed to synchronize\n"); /* overlap-save */ olapsave<<oblocks,p->othreads>>>(buf,out,parts); /* copy buffer out */ cudaMemcpy(bufout,buf, sizeof(float)*parts,cudaMemcpyDeviceToHost); cnt = 0; } } p->cnt = cnt; p->wp = wp; return OK; } static OENTRY localops[] = { {"cudapconv", sizeof(PCONV),0, 5, "a", "aii", (SUBR) pconv_init, NULL, (SUBR) pconv_perf}, }; extern "C" { LINKAGE } csound-6.10.0/Opcodes/cuda/pvsops.cu000066400000000000000000000326521321653344700173040ustar00rootroot00000000000000// -*- c++ -*- /* pvsops.cu experimental cuda opcodes (c) Victor Lazzarini, 2013 based on M Puckette's pitch tracking algorithm. This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include /* kernel to convert from pvs to rectangular frame */ __global__ void frompvs(float* inframe, double* lastph, double scal, double fac) { int k = threadIdx.x + blockIdx.x*blockDim.x + 1; int i = k << 1; float mag = inframe[i]; double delta = (inframe[i+1] - k*scal)*fac; double phi = fmod(lastph[k-1] + delta, TWOPI); lastph[k-1] = phi; inframe[i] = (float) (mag*cos(phi)); inframe[i+1] = (float) (mag*sin(phi)); } __global__ void winrotate(float* inframe2, float* inframe, float *win, int N, int offset){ int k = (threadIdx.x + blockIdx.x*blockDim.x); inframe2[k] = win[k]*inframe[(k+offset)%N]; } typedef struct _pvsyn{ OPDS h; MYFLT *asig; PVSDAT *fsig; float *inframe; /* N */ float *inframe2; double *lastph; /* N/2 */ float *win; /* N */ int framecount; int curframe; AUXCH frames; AUXCH count; cufftHandle plan; double scal, fac; int bblocks, nblocks; int bthreads, nthreads; } PVSYN; static int destroy_pvsyn(CSOUND *csound, void *pp); static int pvsynset(CSOUND *csound, PVSYN *p){ int N = p->fsig->N; if((N != 0) && !(N & (N - 1))) { int hsize = p->fsig->overlap; int size, numframes, i, blockspt; MYFLT sum = 0.0, bins = N/2; float *win; cudaDeviceProp deviceProp; cudaGetDeviceProperties(&deviceProp, 0); blockspt = deviceProp.maxThreadsPerBlock; csound->Message(csound, "CUDAsynth: using device %s (capability %d.%d)\n", deviceProp.name,deviceProp.major, deviceProp.minor); if(p->fsig->wintype != 1) return csound->InitError(csound, "window type not implemented yet\n"); numframes = N/hsize; size = N*sizeof(float)*numframes; if(p->frames.auxp == NULL || p->frames.size < size) csound->AuxAlloc(csound, size, &p->frames); memset(p->frames.auxp, 0, size); size = sizeof(int)*numframes; if(p->count.auxp == NULL || p->count.size < size) csound->AuxAlloc(csound, size, &p->count); *((int *)(p->count.auxp)) = 0; for(i=1; i < numframes; i++) ((int *)(p->count.auxp))[i] = (i + (1.f - (float)i/numframes))*N; size = (N+2)*sizeof(float); cudaMalloc(&p->inframe, size); cudaMemset(p->inframe, 0, size); size = (N+2)*sizeof(float); cudaMalloc(&p->inframe2, size); size = (N+2)*sizeof(float); cudaMalloc(&p->lastph, size); cudaMemset(p->lastph, 0, size); size = N*sizeof(float); cudaMalloc(&p->win, size); win = (float *) malloc(sizeof(float)*(N+1)); for(i=0; i <= N; i++) win[i] = (float) (0.5 - 0.5*cos(i*TWOPI/N)); for(i = 0; i < N; i++) sum += win[i]; sum = FL(2.0) / sum; for(i = 0; i < N; i++) win[i] *= sum; sum = FL(0.0); for(i = 0; i <= N; i+=hsize) sum += win[i] * win[i]; sum = (1.0/N)/(sum); for(i = 0; i < N; i++) win[i] *= 3*sum/sqrt(numframes); cudaMemcpy(p->win,win,N*sizeof(float), cudaMemcpyHostToDevice); free(win); p->framecount = 0; p->curframe = 0; p->fac = TWOPI*hsize/csound->GetSr(csound); p->scal =csound->GetSr(csound)/N; cufftPlan1d(&p->plan, N, CUFFT_C2R, 1); cufftSetCompatibilityMode(p->plan, CUFFT_COMPATIBILITY_NATIVE); csound->RegisterDeinitCallback(csound, p, destroy_pvsyn); p->bblocks = bins > blockspt? bins/blockspt : 1; p->nblocks = N > blockspt ? N/blockspt : 1; p->bthreads = bins/p->bblocks; p->nthreads = N/p->nblocks; if(csound->GetDebug(csound)) csound->Message(csound, "%d (%d each), %d (%d each)\n", p->nblocks, p->nthreads, p->bblocks, p->bthreads); return OK; } return csound->InitError(csound, "fftsize not power-of-two \n"); } static int pvsynperf(CSOUND *csound, PVSYN *p){ int N = p->fsig->N, i; int hsize = p->fsig->overlap; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *asig = p->asig; float *frames = (float *) p->frames.auxp; int framecount = p->framecount; int numframes = N/hsize; int *count = (int *) p->count.auxp; if (UNLIKELY(offset)) memset(asig, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&asig[nsmps], '\0', early*sizeof(MYFLT)); } for(n=offset; n < nsmps; n++) { if(framecount == 0) { int curframe = p->curframe; /* start offset for current frame */ int start = N*curframe; float *cur = &(frames[start]); float *win = (float *) p->win; float *inframe = p->inframe; float *inframe2 = p->inframe2; float *fsig = (float *) p->fsig->frame.auxp; /* copy fsig data to device */ fsig[N+1] = fsig[1] = 0.f; cudaMemcpy(inframe,fsig,(N+2)*sizeof(float), cudaMemcpyHostToDevice); /* perf pvs to rect conversion */ frompvs<<bblocks,p->bthreads-1>>>(inframe,p->lastph,p->scal,p->fac); /* execute inverse real FFT */ if(cufftExecC2R(p->plan,(cufftComplex*)inframe,inframe) != CUFFT_SUCCESS) csound->Message(csound, "cuda fft error\n"); if (cudaDeviceSynchronize() != cudaSuccess) csound->Message(csound,"Cuda error: Failed to synchronize\n"); /* window and rotate data on device */ winrotate<<nblocks,p->nthreads>>>(inframe2,inframe,win,N,hsize*curframe); /* copy data to current out frame */ cudaMemcpy(cur,inframe2,N*sizeof(float),cudaMemcpyDeviceToHost); /* reset counter for this frame to the start */ count[curframe] = start; /* move current to next frame circularly */ p->curframe = ++(curframe) == numframes ? 0 : curframe; framecount = hsize; } asig[n] = FL(0.0); for(i=0; i < numframes; i++){ /* overlap-add */ asig[n] += frames[count[i]]; count[i]++; } framecount--; } p->framecount = framecount; return OK; } static int destroy_pvsyn(CSOUND *csound, void *pp){ PVSYN *p = (PVSYN *) pp; cufftDestroy(p->plan); cudaFree(p->inframe); cudaFree(p->inframe2); cudaFree(p->lastph); cudaFree(p->win); return OK; } __device__ double modTwoPi(double x) { x = fmod(x,TWOPI); return x <= -PI ? x + TWOPI : (x > PI ? x - TWOPI : x); } /* kernel to convert from rectangular to pvs frame */ __global__ void topvs(float* aframe, double* oldph, double scal, double fac) { int k = threadIdx.x + blockIdx.x*blockDim.x + 1; int i = k << 1; float re = aframe[i], im = aframe[i+1]; float mag = sqrtf(re*re + im*im); double phi = atan2f(im,re); double delta = phi - oldph[k-1]; oldph[k-1] = phi; aframe[i] = mag; aframe[i+1] = (float) ((modTwoPi(delta) + k*scal)*fac); } __global__ void rotatewin(float* aframe2, float *aframe, float *win, int N, int offset){ int k = threadIdx.x + blockIdx.x*blockDim.x; aframe2[(k+offset)%N] = win[k]*aframe[k]; } typedef struct _pvan { OPDS h; PVSDAT *fsig; MYFLT *asig,*fftsize,*hsize,*winsize,*wintype; float *aframe; /* N */ float *aframe2; double *oldph; /* N/2 */ float *win; /* N */ int framecount; int curframe; AUXCH frames; AUXCH count; cufftHandle plan; double scal, fac; int bblocks, nblocks; int bthreads, nthreads; } PVAN; static int destroy_pvanal(CSOUND *csound, void *pp); static int pvanalset(CSOUND *csound, PVAN *p){ int N = *p->fftsize; if((N != 0) && !(N & (N - 1))) { int size, numframes, i, bins = N/2; int hsize = *p->hsize, blockspt; float *win; cudaDeviceProp deviceProp; cudaGetDeviceProperties(&deviceProp, 0); blockspt = deviceProp.maxThreadsPerBlock; csound->Message(csound, "CUDAnal: using device %s (capability %d.%d)\n", deviceProp.name,deviceProp.major, deviceProp.minor); p->fsig->N = N; p->fsig->overlap = hsize; /* ignore winsize & wintype */ p->fsig->winsize = N; p->fsig->wintype = 1; p->fsig->framecount = 0; numframes = N/hsize; size = N*sizeof(float)*numframes; if(p->frames.auxp == NULL || p->frames.size < size) csound->AuxAlloc(csound, size, &p->frames); memset(p->frames.auxp, 0, size); size = (N+2)*sizeof(float); if(p->fsig->frame.auxp == NULL || p->fsig->frame.size < size) csound->AuxAlloc(csound, size, &p->fsig->frame); memset(p->fsig->frame.auxp, 0, size); size = sizeof(int)*numframes; if(p->count.auxp == NULL || p->count.size < size) csound->AuxAlloc(csound, size, &p->count); *((int *)(p->count.auxp)) = 0; for(i=1; i < numframes; i++) ((int *)(p->count.auxp))[i] = (i + (float)i/numframes)*N; size = (N+2)*sizeof(float); cudaMalloc(&p->aframe, size); size = (N+2)*sizeof(float); cudaMalloc(&p->aframe2, size); size = (N/2-1)*sizeof(double); cudaMalloc(&p->oldph, size); cudaMemset(p->oldph, 0, size); size = N*sizeof(float); cudaMalloc(&p->win, size); win = (float *) malloc(sizeof(float)*N); for(i=0; i < N; i++) win[i] = (float) (0.5 - 0.5*cos(i*TWOPI/N)); float sum = 0.0; for(i = 0; i < N; i++) sum += win[i]; sum = FL(2.0) / sum; for(i = 0; i < N; i++) win[i] *= sum; cudaMemcpy(p->win,win,N*sizeof(float), cudaMemcpyHostToDevice); free(win); p->framecount = 1; p->curframe = numframes-1; p->fac = csound->GetSr(csound)/(TWOPI*hsize); p->scal = (TWOPI*hsize)/N; cufftPlan1d(&p->plan, N, CUFFT_R2C, 1); cufftSetCompatibilityMode(p->plan, CUFFT_COMPATIBILITY_NATIVE); csound->RegisterDeinitCallback(csound, p, destroy_pvanal); p->bblocks = bins > blockspt? bins/blockspt : 1; p->nblocks = N > blockspt ? N/blockspt : 1; p->bthreads = bins/p->bblocks; p->nthreads = N/p->nblocks; if(csound->GetDebug(csound)) csound->Message(csound, "%d (%d each), %d (%d each)\n", p->nblocks, p->nthreads, p->bblocks, p->bthreads); return OK; } return csound->InitError(csound, "fftsize not power-of-two \n"); } static int pvanalperf(CSOUND *csound, PVAN *p){ int N = p->fsig->N, i; int hsize = p->fsig->overlap; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *asig = p->asig; float *frames = (float *) p->frames.auxp; int framecount = p->framecount; int numframes = N/hsize; int *count = (int *) p->count.auxp; if (UNLIKELY(offset)) memset(asig, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&asig[nsmps], '\0', early*sizeof(MYFLT)); } for(n=offset; n < nsmps; n++) { for(i=0; i < numframes; i++){ frames[count[i]] = asig[n]; count[i]++; } framecount++; if(framecount == hsize) { int curframe = p->curframe; /* start offset for current frame */ int start = N*curframe; float *cur = &(frames[start]); float *win = (float *) p->win; float *aframe = p->aframe; float *aframe2 = p->aframe2; float *fsig = (float *) p->fsig->frame.auxp; /* copy fsig data to device */ cudaMemcpy(aframe,cur,N*sizeof(float), cudaMemcpyHostToDevice); /* window and rotate data on device */ rotatewin<<nblocks,p->nthreads>>>(aframe2,aframe,win,N, hsize*(numframes-curframe)); /* execute inverse real FFT */ if(cufftExecR2C(p->plan,aframe2,(cufftComplex*)aframe2) != CUFFT_SUCCESS) csound->Message(csound, "cuda fft error\n"); if (cudaDeviceSynchronize() != cudaSuccess) csound->Message(csound,"Cuda error: Failed to synchronize\n"); /* perf rect to pvs conversion */ topvs<<bblocks,p->bthreads-1>>>(aframe2,p->oldph,p->scal,p->fac); /* copy data to current out frame */ cudaMemcpy(fsig,aframe2,(N+2)*sizeof(float),cudaMemcpyDeviceToHost); /* reset counter for this frame to the start */ fsig[N+1] = fsig[1] = 0.f; count[curframe] = start; /* move current to next frame circularly */ p->curframe = --(curframe) < 0 ? numframes-1 : curframe; framecount = 0; p->fsig->framecount++; } } p->framecount = framecount; return OK; } static int destroy_pvanal(CSOUND *csound, void *pp){ PVAN *p = (PVAN *) pp; cufftDestroy(p->plan); cudaFree(p->aframe); cudaFree(p->aframe2); cudaFree(p->oldph); cudaFree(p->win); return OK; } static OENTRY localops[] = { {"cudasynth", sizeof(PVSYN),0, 5, "a", "f", (SUBR) pvsynset, NULL, (SUBR) pvsynperf}, {"cudanal", sizeof(PVAN),0, 5, "f", "aiiii", (SUBR) pvanalset, NULL, (SUBR) pvanalperf} }; extern "C" { LINKAGE } csound-6.10.0/Opcodes/cuda/pvsops2-build.sh000066400000000000000000000004721321653344700204610ustar00rootroot00000000000000#!/bin/sh # use -Xptxas="-v" to check register usage and --maxrregcount 32 to limit it echo "building cuda opcodes ..." nvcc -O3 -shared -o libcudapvs2.dylib pvsops2.cu -use_fast_math -g -I../../debug/CsoundLib64.framework/Headers -arch=sm_30 -I/usr/local/cuda/include -L/usr/local/cuda/lib -lcufft echo "...done" csound-6.10.0/Opcodes/cuda/pvsops2.cu000066400000000000000000000372241321653344700173660ustar00rootroot00000000000000// -*- c++ -*- /* pvsops.cu experimental cuda opcodes (c) Victor Lazzarini, 2013 based on M Puckette's pitch tracking algorithm. This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include void AuxCudaAlloc(int size, AUXCH *p){ float *mem; cudaMalloc(&mem, size); cudaMemset(mem, 0, size); p->auxp = mem; p->size = size; } /* kernel to convert from pvs to rectangular frame */ __global__ void frompvs(float* inframe, float* fsig, double* lastph, double scal, double fac) { int k = threadIdx.x + blockIdx.x*blockDim.x; int i = k << 1; float mag = fsig[i]; double delta = (fsig[i+1] - k*scal)*fac; double phi = fmod(lastph[k] + delta, TWOPI); lastph[k] = phi; inframe[i] = (float) (mag*cos(phi)); inframe[i+1] = (float) (mag*sin(phi)); } __global__ void winrotate(float* inframe2, float* inframe, float *win, int N, int offset){ int k = (threadIdx.x + blockIdx.x*blockDim.x); inframe2[k] = win[k]*inframe[(k+offset)%N]; } typedef struct _pvsyn{ OPDS h; MYFLT *asig; PVSDAT *fsig; float *inframe; /* N */ float *inframe2; double *lastph; /* N/2 */ float *win; /* N */ int framecount; int curframe; AUXCH frames; AUXCH count; cufftHandle plan; double scal, fac; int bblocks, nblocks; int bthreads, nthreads; } PVSYN; static int destroy_pvsyn(CSOUND *csound, void *pp); static int pvsynset(CSOUND *csound, PVSYN *p){ int N = p->fsig->N; if((N != 0) && !(N & (N - 1))) { int hsize = p->fsig->overlap; int size, numframes, i, blockspt; MYFLT sum = 0.0, bins = N/2; float *win; cudaDeviceProp deviceProp; cudaGetDeviceProperties(&deviceProp, 0); blockspt = deviceProp.maxThreadsPerBlock; csound->Message(csound, "CUDAsynth: using device %s (capability %d.%d)\n", deviceProp.name,deviceProp.major, deviceProp.minor); if(p->fsig->wintype != 1) return csound->InitError(csound, "window type not implemented yet\n"); numframes = N/hsize; size = N*sizeof(float)*numframes; if(p->frames.auxp == NULL || p->frames.size < size) csound->AuxAlloc(csound, size, &p->frames); memset(p->frames.auxp, 0, size); size = sizeof(int)*numframes; if(p->count.auxp == NULL || p->count.size < size) csound->AuxAlloc(csound, size, &p->count); *((int *)(p->count.auxp)) = 0; for(i=1; i < numframes; i++) ((int *)(p->count.auxp))[i] = (i + (1.f - (float)i/numframes))*N; size = (N+2)*sizeof(float); cudaMalloc(&p->inframe, size); cudaMemset(p->inframe, 0, size); size = (N+2)*sizeof(float); cudaMalloc(&p->inframe2, size); size = (N/2)*sizeof(double); cudaMalloc(&p->lastph, size); cudaMemset(p->lastph, 0, size); size = N*sizeof(float); cudaMalloc(&p->win, size); win = (float *) malloc(sizeof(float)*(N+1)); for(i=0; i <= N; i++) win[i] = (float) (0.5 - 0.5*cos(i*TWOPI/N)); for(i = 0; i < N; i++) sum += win[i]; sum = FL(2.0) / sum; for(i = 0; i < N; i++) win[i] *= sum; sum = FL(0.0); for(i = 0; i <= N; i+=hsize) sum += win[i] * win[i]; sum = (1.0/N)/(sum); for(i = 0; i < N; i++) win[i] *= 3*sum/sqrt(numframes); cudaMemcpy(p->win,win,N*sizeof(float), cudaMemcpyHostToDevice); free(win); p->framecount = 0; p->curframe = 0; p->fac = TWOPI*hsize/csound->GetSr(csound); p->scal =csound->GetSr(csound)/N; cufftPlan1d(&p->plan, N, CUFFT_C2R, 1); cufftSetCompatibilityMode(p->plan, CUFFT_COMPATIBILITY_NATIVE); csound->RegisterDeinitCallback(csound, p, destroy_pvsyn); p->bblocks = bins > blockspt? bins/blockspt : 1; p->nblocks = N > blockspt ? N/blockspt : 1; p->bthreads = bins/p->bblocks; p->nthreads = N/p->nblocks; if(csound->GetDebug(csound)) csound->Message(csound, "%d (%d each), %d (%d each)\n", p->nblocks, p->nthreads, p->bblocks, p->bthreads); return OK; } return csound->InitError(csound, "fftsize not power-of-two \n"); } static int pvsynperf(CSOUND *csound, PVSYN *p){ int N = p->fsig->N, i; int hsize = p->fsig->overlap; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *asig = p->asig; float *frames = (float *) p->frames.auxp; int framecount = p->framecount; int numframes = N/hsize; int *count = (int *) p->count.auxp; if (UNLIKELY(offset)) memset(asig, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&asig[nsmps], '\0', early*sizeof(MYFLT)); } for(n=offset; n < nsmps; n++) { if(framecount == 0) { int curframe = p->curframe; /* start offset for current frame */ int start = N*curframe; float *cur = &(frames[start]); float *win = (float *) p->win; float *inframe = p->inframe; float *inframe2 = p->inframe2; float *fsig = (float *) p->fsig->frame.auxp; /* perf pvs to rect conversion */ frompvs<<bblocks,p->bthreads>>>(inframe,fsig,p->lastph,p->scal,p->fac); /* execute inverse real FFT */ if(cufftExecC2R(p->plan,(cufftComplex*)inframe,inframe) != CUFFT_SUCCESS) csound->Message(csound, "cuda fft error\n"); if (cudaDeviceSynchronize() != cudaSuccess) csound->Message(csound,"Cuda error: Failed to synchronize\n"); /* window and rotate data on device */ winrotate<<nblocks,p->nthreads>>>(inframe2,inframe,win,N,hsize*curframe); /* copy data to current out frame */ cudaMemcpy(cur,inframe2,N*sizeof(float),cudaMemcpyDeviceToHost); /* reset counter for this frame to the start */ count[curframe] = start; /* move current to next frame circularly */ p->curframe = ++(curframe) == numframes ? 0 : curframe; framecount = hsize; } asig[n] = FL(0.0); for(i=0; i < numframes; i++){ /* overlap-add */ asig[n] += frames[count[i]]; count[i]++; } framecount--; } p->framecount = framecount; return OK; } static int destroy_pvsyn(CSOUND *csound, void *pp){ PVSYN *p = (PVSYN *) pp; cufftDestroy(p->plan); cudaFree(p->inframe); cudaFree(p->inframe2); cudaFree(p->lastph); cudaFree(p->win); return OK; } __device__ double modTwoPi(double x) { x = fmod(x,TWOPI); return x <= -PI ? x + TWOPI : (x > PI ? x - TWOPI : x); } /* kernel to convert from rectangular to pvs frame */ __global__ void topvs(float *fsig, float *aframe, double* oldph, double scal, double fac) { int k = threadIdx.x + blockIdx.x*blockDim.x; int i = k << 1; float re = aframe[i], im = aframe[i+1]; float mag = sqrtf(re*re + im*im); double phi = atan2f(im,re); double delta = phi - oldph[k]; oldph[k] = phi; fsig[i] = mag; fsig[i+1] = (float) ((modTwoPi(delta) + k*scal)*fac); } __global__ void rotatewin(float* aframe2, float *aframe, float *win, int N, int offset){ int k = threadIdx.x + blockIdx.x*blockDim.x; aframe2[(k+offset)%N] = win[k]*aframe[k]; } typedef struct _pvan { OPDS h; PVSDAT *fsig; MYFLT *asig,*fftsize,*hsize,*winsize,*wintype; float *aframe; /* N */ float *aframe2; double *oldph; /* N/2 */ float *win; /* N */ int framecount; int curframe; AUXCH frames; AUXCH count; cufftHandle plan; double scal, fac; int bblocks, nblocks; int bthreads, nthreads; } PVAN; static int destroy_pvanal(CSOUND *csound, void *pp); static int pvanalset(CSOUND *csound, PVAN *p){ int N = *p->fftsize; if((N != 0) && !(N & (N - 1))) { int size, numframes, i, bins = N/2; int hsize = *p->hsize, blockspt; float *win; cudaDeviceProp deviceProp; cudaGetDeviceProperties(&deviceProp, 0); blockspt = deviceProp.maxThreadsPerBlock; csound->Message(csound, "CUDAnal: using device %s (capability %d.%d)\n", deviceProp.name,deviceProp.major, deviceProp.minor); p->fsig->N = N; p->fsig->overlap = hsize; p->fsig->format = -1; /* ignore winsize & wintype */ p->fsig->winsize = N; p->fsig->wintype = 1; p->fsig->framecount = 0; numframes = N/hsize; size = N*sizeof(float)*numframes; if(p->frames.auxp == NULL || p->frames.size < size) csound->AuxAlloc(csound, size, &p->frames); memset(p->frames.auxp, 0, size); size = (N+2)*sizeof(float); if(p->fsig->frame.auxp == NULL || p->fsig->frame.size < size) AuxCudaAlloc(size, &p->fsig->frame); size = sizeof(int)*numframes; if(p->count.auxp == NULL || p->count.size < size) csound->AuxAlloc(csound, size, &p->count); *((int *)(p->count.auxp)) = 0; for(i=1; i < numframes; i++) ((int *)(p->count.auxp))[i] = (i + (float)i/numframes)*N; size = (N+2)*sizeof(float); cudaMalloc(&p->aframe, size); size = (N+2)*sizeof(float); cudaMalloc(&p->aframe2, size); size = (N/2)*sizeof(double); cudaMalloc(&p->oldph, size); cudaMemset(p->oldph, 0, size); size = N*sizeof(float); cudaMalloc(&p->win, size); win = (float *) malloc(sizeof(float)*N); for(i=0; i < N; i++) win[i] = (float) (0.5 - 0.5*cos(i*TWOPI/N)); float sum = 0.0; for(i = 0; i < N; i++) sum += win[i]; sum = FL(2.0) / sum; for(i = 0; i < N; i++) win[i] *= sum; cudaMemcpy(p->win,win,N*sizeof(float), cudaMemcpyHostToDevice); free(win); p->framecount = 1; p->curframe = numframes-1; p->fac = csound->GetSr(csound)/(TWOPI*hsize); p->scal = (TWOPI*hsize)/N; cufftPlan1d(&p->plan, N, CUFFT_R2C, 1); cufftSetCompatibilityMode(p->plan, CUFFT_COMPATIBILITY_NATIVE); csound->RegisterDeinitCallback(csound, p, destroy_pvanal); p->bblocks = bins > blockspt? bins/blockspt : 1; p->nblocks = N > blockspt ? N/blockspt : 1; p->bthreads = bins/p->bblocks; p->nthreads = N/p->nblocks; if(csound->GetDebug(csound)) csound->Message(csound, "%d (%d each), %d (%d each)\n", p->nblocks, p->nthreads, p->bblocks, p->bthreads); return OK; } return csound->InitError(csound, "fftsize not power-of-two \n"); } static int pvanalperf(CSOUND *csound, PVAN *p){ int N = p->fsig->N, i; int hsize = p->fsig->overlap; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *asig = p->asig; float *frames = (float *) p->frames.auxp; int framecount = p->framecount; int numframes = N/hsize; int *count = (int *) p->count.auxp; if (UNLIKELY(offset)) memset(asig, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&asig[nsmps], '\0', early*sizeof(MYFLT)); } for(n=offset; n < nsmps; n++) { for(i=0; i < numframes; i++){ frames[count[i]] = asig[n]; count[i]++; } framecount++; if(framecount == hsize) { int curframe = p->curframe; /* start offset for current frame */ int start = N*curframe; float *cur = &(frames[start]); float *win = (float *) p->win; float *aframe = p->aframe; float *aframe2 = p->aframe2; float *fsig = (float *) p->fsig->frame.auxp; cudaMemcpy(aframe,cur,N*sizeof(float), cudaMemcpyHostToDevice); /* window and rotate data on device */ rotatewin<<nblocks,p->nthreads>>>(aframe2,aframe,win,N, hsize*(numframes-curframe)); /* execute inverse real FFT */ if(cufftExecR2C(p->plan,aframe2,(cufftComplex*)aframe2) != CUFFT_SUCCESS) csound->Message(csound, "cuda fft error\n"); if (cudaDeviceSynchronize() != cudaSuccess) csound->Message(csound,"Cuda error: Failed to synchronize\n"); /* perf rect to pvs conversion */ topvs<<bblocks,p->bthreads>>>(fsig,aframe2,p->oldph,p->scal,p->fac); /* reset counter for this frame to the start */ count[curframe] = start; /* move current to next frame circularly */ p->curframe = --(curframe) < 0 ? numframes-1 : curframe; framecount = 0; p->fsig->framecount++; } } p->framecount = framecount; return OK; } static int destroy_pvanal(CSOUND *csound, void *pp){ PVAN *p = (PVAN *) pp; cufftDestroy(p->plan); cudaFree(p->aframe); cudaFree(p->aframe2); cudaFree(p->oldph); cudaFree(p->fsig->frame.auxp); p->fsig->frame.size = 0; cudaFree(p->win); return OK; } typedef struct _cudapvsgain2 { OPDS h; PVSDAT *fout; PVSDAT *fa; MYFLT *kgain; int gridSize; // number of blocks in the grid (1D) int blockSize; // number of threads in one block (1D) uint32 lastframe; } CUDAPVSGAIN2; // kernel for scaling PV amplitudes __global__ void applygain(float* output, float* input, MYFLT g, int length) { int i = threadIdx.x + blockDim.x * blockIdx.x; int j = i<<1; if(j < length){ output[j] = (float) input[j] * g; output[j+1] = input[j+1]; } } static int free_device(CSOUND* csound, void* pp){ CUDAPVSGAIN2* p = (CUDAPVSGAIN2*) pp; cudaFree(p->fout->frame.auxp); return OK; } static int cudapvsgain2set(CSOUND *csound, CUDAPVSGAIN2 *p){ int32 N = p->fa->N; int size = (N+2) * sizeof(float); int maxBlockDim; int SMcount; int totNumThreads = (N+2)/2; cudaDeviceProp deviceProp; cudaGetDeviceProperties(&deviceProp,0); maxBlockDim = deviceProp.maxThreadsPerBlock; SMcount = deviceProp.multiProcessorCount; csound->Message(csound, "cudapvsgain2 running on device %s (capability %d.%d)\n", deviceProp.name, deviceProp.major, deviceProp.minor); p->fout->sliding = 0; if (p->fout->frame.auxp == NULL || p->fout->frame.size < size) AuxCudaAlloc(size, &p->fout->frame); p->blockSize = (((totNumThreads/SMcount)/32)+1)*32; if (p->blockSize > maxBlockDim) p->blockSize = maxBlockDim; p->gridSize = totNumThreads / p->blockSize + 1; p->fout->N = N; p->fout->overlap = p->fa->overlap; p->fout->winsize = p->fa->winsize; p->fout->wintype = p->fa->wintype; p->fout->format = p->fa->format; p->fout->framecount = 1; p->lastframe = 0; csound->RegisterDeinitCallback(csound, p, free_device); return OK; } static int cudapvsgain2(CSOUND *csound, CUDAPVSGAIN2 *p) { int32 framelength = p->fa->N + 2; MYFLT gain = *p->kgain; float* fo = (float*) p->fout->frame.auxp; float* fi = (float*) p->fa->frame.auxp; if (p->lastframe < p->fa->framecount) { if (cudaDeviceSynchronize() != cudaSuccess) csound->Message(csound,"Cuda error: Failed to synchronize\n"); applygain<<gridSize,p->blockSize>>>(fo, fi, gain, framelength); p->fout->framecount = p->fa->framecount; p->lastframe = p->fout->framecount; } return OK; } static OENTRY localops[] = { {"cudasynth2", sizeof(PVSYN),0, 5, "a", "f", (SUBR) pvsynset, NULL, (SUBR) pvsynperf}, {"cudanal2", sizeof(PVAN),0, 5, "f", "aiiii", (SUBR) pvanalset, NULL, (SUBR) pvanalperf}, {"cudapvsgain2", sizeof(CUDAPVSGAIN2), 0, 3, "f", "fk", (SUBR) cudapvsgain2set, (SUBR) cudapvsgain2, NULL} }; extern "C" { LINKAGE } csound-6.10.0/Opcodes/cuda/pvsopsf.cu000066400000000000000000000326471321653344700174560ustar00rootroot00000000000000// -*- c++ -*- /* pvsopsf.cu experimental cuda opcodes version using single-precision floats (c) Victor Lazzarini, 2013 based on M Puckette's pitch tracking algorithm. This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include /* kernel to convert from pvs to rectangular frame */ __global__ void frompvs(float* inframe, float* lastph, float scal, float fac) { int k = threadIdx.x + blockIdx.x*blockDim.x + 1; int i = k << 1; float mag = inframe[i]; float delta = (inframe[i+1] - k*scal)*fac; float phi = fmod((double)lastph[k-1] + delta, TWOPI); lastph[k-1] = phi; inframe[i] = (float) (mag*cos(phi)); inframe[i+1] = (float) (mag*sin(phi)); } __global__ void winrotate(float* inframe2, float* inframe, float *win, int N, int offset){ int k = (threadIdx.x + blockIdx.x*blockDim.x); inframe2[k] = win[k]*inframe[(k+offset)%N]; } typedef struct _pvsyn{ OPDS h; MYFLT *asig; PVSDAT *fsig; float *inframe; /* N */ float *inframe2; float *lastph; /* N/2 */ float *win; /* N */ int framecount; int curframe; AUXCH frames; AUXCH count; cufftHandle plan; float scal, fac; int bblocks, nblocks; int bthreads, nthreads; } PVSYN; static int destroy_pvsyn(CSOUND *csound, void *pp); static int pvsynset(CSOUND *csound, PVSYN *p){ int N = p->fsig->N; if((N != 0) && !(N & (N - 1))) { int hsize = p->fsig->overlap; int size, numframes, i, blockspt; MYFLT sum = 0.0, bins = N/2; float *win; cudaDeviceProp deviceProp; cudaGetDeviceProperties(&deviceProp, 0); blockspt = deviceProp.maxThreadsPerBlock; csound->Message(csound, "CUDAsynth: using device %s (capability %d.%d)\n", deviceProp.name,deviceProp.major, deviceProp.minor); if(p->fsig->wintype != 1) return csound->InitError(csound, "window type not implemented yet\n"); numframes = N/hsize; size = N*sizeof(float)*numframes; if(p->frames.auxp == NULL || p->frames.size < size) csound->AuxAlloc(csound, size, &p->frames); memset(p->frames.auxp, 0, size); size = sizeof(int)*numframes; if(p->count.auxp == NULL || p->count.size < size) csound->AuxAlloc(csound, size, &p->count); *((int *)(p->count.auxp)) = 0; for(i=1; i < numframes; i++) ((int *)(p->count.auxp))[i] = (i + (1.f - (float)i/numframes))*N; size = (N+2)*sizeof(float); cudaMalloc(&p->inframe, size); cudaMemset(p->inframe, 0, size); size = (N+2)*sizeof(float); cudaMalloc(&p->inframe2, size); size = (N+2)*sizeof(float); cudaMalloc(&p->lastph, size); cudaMemset(p->lastph, 0, size); size = N*sizeof(float); cudaMalloc(&p->win, size); win = (float *) malloc(sizeof(float)*(N+1)); for(i=0; i <= N; i++) win[i] = (float) (0.5 - 0.5*cos(i*TWOPI/N)); for(i = 0; i < N; i++) sum += win[i]; sum = FL(2.0) / sum; for(i = 0; i < N; i++) win[i] *= sum; sum = FL(0.0); for(i = 0; i <= N; i+=hsize) sum += win[i] * win[i]; sum = (1.0/N)/(sum); for(i = 0; i < N; i++) win[i] *= 3*sum/sqrt(numframes); cudaMemcpy(p->win,win,N*sizeof(float), cudaMemcpyHostToDevice); free(win); p->framecount = 0; p->curframe = 0; p->fac = TWOPI*hsize/csound->GetSr(csound); p->scal =csound->GetSr(csound)/N; cufftPlan1d(&p->plan, N, CUFFT_C2R, 1); cufftSetCompatibilityMode(p->plan, CUFFT_COMPATIBILITY_NATIVE); csound->RegisterDeinitCallback(csound, p, destroy_pvsyn); p->bblocks = bins > blockspt? bins/blockspt : 1; p->nblocks = N > blockspt ? N/blockspt : 1; p->bthreads = bins/p->bblocks; p->nthreads = N/p->nblocks; if(csound->GetDebug(csound)) csound->Message(csound, "%d (%d each), %d (%d each)\n", p->nblocks, p->nthreads, p->bblocks, p->bthreads); return OK; } return csound->InitError(csound, "fftsize not power-of-two \n"); } static int pvsynperf(CSOUND *csound, PVSYN *p){ int N = p->fsig->N, i; int hsize = p->fsig->overlap; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *asig = p->asig; float *frames = (float *) p->frames.auxp; int framecount = p->framecount; int numframes = N/hsize; int *count = (int *) p->count.auxp; if (UNLIKELY(offset)) memset(asig, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&asig[nsmps], '\0', early*sizeof(MYFLT)); } for(n=offset; n < nsmps; n++) { if(framecount == 0) { int curframe = p->curframe; /* start offset for current frame */ int start = N*curframe; float *cur = &(frames[start]); float *win = (float *) p->win; float *inframe = p->inframe; float *inframe2 = p->inframe2; float *fsig = (float *) p->fsig->frame.auxp; /* copy fsig data to device */ fsig[N+1] = fsig[1] = 0.f; cudaMemcpy(inframe,fsig,(N+2)*sizeof(float), cudaMemcpyHostToDevice); /* perf pvs to rect conversion */ frompvs<<bblocks,p->bthreads-1>>>(inframe,p->lastph,p->scal,p->fac); /* execute inverse real FFT */ if(cufftExecC2R(p->plan,(cufftComplex*)inframe,inframe) != CUFFT_SUCCESS) csound->Message(csound, "cuda fft error\n"); if (cudaDeviceSynchronize() != cudaSuccess) csound->Message(csound,"Cuda error: Failed to synchronize\n"); /* window and rotate data on device */ winrotate<<nblocks,p->nthreads>>>(inframe2,inframe,win,N,hsize*curframe); /* copy data to current out frame */ cudaMemcpy(cur,inframe2,N*sizeof(float),cudaMemcpyDeviceToHost); /* reset counter for this frame to the start */ count[curframe] = start; /* move current to next frame circularly */ p->curframe = ++(curframe) == numframes ? 0 : curframe; framecount = hsize; } asig[n] = FL(0.0); for(i=0; i < numframes; i++){ /* overlap-add */ asig[n] += frames[count[i]]; count[i]++; } framecount--; } p->framecount = framecount; return OK; } static int destroy_pvsyn(CSOUND *csound, void *pp){ PVSYN *p = (PVSYN *) pp; cufftDestroy(p->plan); cudaFree(p->inframe); cudaFree(p->lastph); cudaFree(p->win); return OK; } __device__ float modTwoPi(float x) { x = fmod((double)x,TWOPI); return x <= -PI ? x + TWOPI : (x > PI ? x - TWOPI : x); } /* kernel to convert from rectangular to pvs frame */ __global__ void topvs(float* aframe, float* oldph, float scal, float fac) { int k = threadIdx.x + blockIdx.x*blockDim.x + 1; int i = k << 1; float re = aframe[i], im = aframe[i+1]; float mag = sqrtf(re*re + im*im); float phi = atan2f(im,re); float delta = phi - oldph[k-1]; oldph[k-1] = phi; aframe[i] = mag; aframe[i+1] = (float) ((modTwoPi(delta) + k*scal)*fac); } __global__ void rotatewin(float* aframe2, float *aframe, float *win, int N, int offset){ int k = threadIdx.x + blockIdx.x*blockDim.x; aframe2[(k+offset)%N] = win[k]*aframe[k]; } typedef struct _pvan { OPDS h; PVSDAT *fsig; MYFLT *asig,*fftsize,*hsize,*winsize,*wintype; float *aframe; /* N */ float *aframe2; float *oldph; /* N/2 */ float *win; /* N */ int framecount; int curframe; AUXCH frames; AUXCH count; cufftHandle plan; float scal, fac; int bblocks, nblocks; int bthreads, nthreads; } PVAN; static int destroy_pvanal(CSOUND *csound, void *pp); static int pvanalset(CSOUND *csound, PVAN *p){ int N = *p->fftsize; if((N != 0) && !(N & (N - 1))) { int size, numframes, i, bins = N/2; int hsize = *p->hsize, blockspt; float *win; cudaDeviceProp deviceProp; cudaGetDeviceProperties(&deviceProp, 0); blockspt = deviceProp.maxThreadsPerBlock; csound->Message(csound, "CUDAnal: using device %s (capability %d.%d)\n", deviceProp.name,deviceProp.major, deviceProp.minor); p->fsig->N = N; p->fsig->overlap = hsize; /* ignore winsize & wintype */ p->fsig->winsize = N; p->fsig->wintype = 1; p->fsig->framecount = 0; numframes = N/hsize; size = N*sizeof(float)*numframes; if(p->frames.auxp == NULL || p->frames.size < size) csound->AuxAlloc(csound, size, &p->frames); memset(p->frames.auxp, 0, size); size = N*sizeof(float); if(p->fsig->frame.auxp == NULL || p->fsig->frame.size < size) csound->AuxAlloc(csound, size, &p->fsig->frame); memset(p->fsig->frame.auxp, 0, size); size = sizeof(int)*numframes; if(p->count.auxp == NULL || p->count.size < size) csound->AuxAlloc(csound, size, &p->count); *((int *)(p->count.auxp)) = 0; for(i=1; i < numframes; i++) ((int *)(p->count.auxp))[i] = (i + (float)i/numframes)*N; size = (N+2)*sizeof(float); cudaMalloc(&p->aframe, size); size = (N+2)*sizeof(float); cudaMalloc(&p->aframe2, size); size = (N/2-1)*sizeof(float); cudaMalloc(&p->oldph, size); cudaMemset(p->oldph, 0, size); size = N*sizeof(float); cudaMalloc(&p->win, size); win = (float *) malloc(sizeof(float)*N); for(i=0; i < N; i++) win[i] = (float) (0.5 - 0.5*cos(i*TWOPI/N)); float sum = 0.0; for(i = 0; i < N; i++) sum += win[i]; sum = FL(2.0) / sum; for(i = 0; i < N; i++) win[i] *= sum; cudaMemcpy(p->win,win,N*sizeof(float), cudaMemcpyHostToDevice); free(win); p->framecount = 1; p->curframe = numframes-1; p->fac = csound->GetSr(csound)/(TWOPI*hsize); p->scal = (TWOPI*hsize)/N; cufftPlan1d(&p->plan, N, CUFFT_R2C, 1); cufftSetCompatibilityMode(p->plan, CUFFT_COMPATIBILITY_NATIVE); csound->RegisterDeinitCallback(csound, p, destroy_pvanal); p->bblocks = bins > blockspt? bins/blockspt : 1; p->nblocks = N > blockspt ? N/blockspt : 1; p->bthreads = bins/p->bblocks; p->nthreads = N/p->nblocks; if(csound->GetDebug(csound)) csound->Message(csound, "%d (%d each), %d (%d each)\n", p->nblocks, p->nthreads, p->bblocks, p->bthreads); return OK; } return csound->InitError(csound, "fftsize not power-of-two \n"); } static int pvanalperf(CSOUND *csound, PVAN *p){ int N = p->fsig->N, i; int hsize = p->fsig->overlap; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *asig = p->asig; float *frames = (float *) p->frames.auxp; int framecount = p->framecount; int numframes = N/hsize; int *count = (int *) p->count.auxp; if (UNLIKELY(offset)) memset(asig, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&asig[nsmps], '\0', early*sizeof(MYFLT)); } for(n=offset; n < nsmps; n++) { for(i=0; i < numframes; i++){ frames[count[i]] = asig[n]; count[i]++; } framecount++; if(framecount == hsize) { int curframe = p->curframe; /* start offset for current frame */ int start = N*curframe; float *cur = &(frames[start]); float *win = (float *) p->win; float *aframe = p->aframe; float *aframe2 = p->aframe2; float *fsig = (float *) p->fsig->frame.auxp; /* copy fsig data to device */ cudaMemcpy(aframe,cur,N*sizeof(float), cudaMemcpyHostToDevice); /* window and rotate data on device */ rotatewin<<nblocks,p->nthreads>>>(aframe2,aframe,win,N, hsize*(numframes-curframe)); /* execute inverse real FFT */ if(cufftExecR2C(p->plan,aframe2,(cufftComplex*)aframe2) != CUFFT_SUCCESS) csound->Message(csound, "cuda fft error\n"); if (cudaDeviceSynchronize() != cudaSuccess) csound->Message(csound,"Cuda error: Failed to synchronize\n"); /* perf rect to pvs conversion */ topvs<<bblocks,p->bthreads-1>>>(aframe2,p->oldph,p->scal,p->fac); /* copy data to current out frame */ cudaMemcpy(fsig,aframe2,(N+2)*sizeof(float),cudaMemcpyDeviceToHost); /* reset counter for this frame to the start */ fsig[N+1] = fsig[1] = 0.f; count[curframe] = start; /* move current to next frame circularly */ p->curframe = --(curframe) < 0 ? numframes-1 : curframe; framecount = 0; p->fsig->framecount++; } } p->framecount = framecount; return OK; } static int destroy_pvanal(CSOUND *csound, void *pp){ PVAN *p = (PVAN *) pp; cufftDestroy(p->plan); cudaFree(p->aframe); cudaFree(p->oldph); cudaFree(p->win); return OK; } static OENTRY localops[] = { {"cudasynth", sizeof(PVSYN),0, 5, "a", "f", (SUBR) pvsynset, NULL, (SUBR) pvsynperf}, {"cudanal", sizeof(PVAN),0, 5, "f", "aiiii", (SUBR) pvanalset, NULL, (SUBR) pvanalperf} }; extern "C" { LINKAGE } csound-6.10.0/Opcodes/cuda/slidingm.cu000066400000000000000000000407261321653344700175610ustar00rootroot00000000000000// -*- c++ -*- /* slindingm.cu: Copyright (C) 2014 Russell Bradford, Victor Lazzarini, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // slindingm.cu // experimental cuda opcodes // using the sliding DFT // adapted from Russell Bradford & John ffitch // #include #include #include #include #include #include #include #include //#define RB #ifndef RB typedef float real; #else typedef double real; #endif #define real(x) x #define TWO_PI (2.0*M_PI) #define NBATCH (256) #define Re(z) ((z).x) #define Im(z) ((z).y) #define R(p) ((p).x) #define Theta(p) ((p).y) #define RectA (real(1.0)) #define RectB (real(0.0)) #define HannA (real(0.5)) #define HannB (real(-0.5)) #define A HannA #define B2 (HannB/real(2.0)) #define WINDOW typedef double2 complex; typedef double2 phasor; // Put a few things into constant memory to free up a couple of registers //__constant__ int N, N2; __constant__ real binbandwidth, nyquist; // array alignment __constant__ int offset; // process in batches of this size __constant__ int nbatch; #define CUDA(name, args ...) { name(args); checkcuda(csound, #name, __LINE__); } #define CHK(name) checkcuda(csound, #name, __LINE__) #define NEXT(p) p += offset void checkcuda(CSOUND *csound, char* name, int line) { cudaError_t err = cudaGetLastError(); if (err) { csound->Message(csound, "%s: %s\nLine: %d\n", name, cudaGetErrorString(err), line); exit(1); } } __device__ double atomicAdd(double* address, double val) { unsigned long long int* address_as_ull = (unsigned long long int*)address; unsigned long long int old = *address_as_ull, assumed; do { assumed = old; old = atomicCAS(address_as_ull, assumed, __double_as_longlong(val + __longlong_as_double(assumed))); } while (assumed != old); return __longlong_as_double(old); } __device__ complex conjugate(complex z) { return (complex){ Re(z), -Im(z) }; } // round up to multiple of 256 __host__ __device__ int roundup(int n) { return 1 + ((n - 1) | 0xff); } // Fin/Fout // thread k does bin k; parallel across bins in a batch item.. __global__ void slide(real deltas[/*nbatch*/], complex Fin[/*N*/], complex Fout[/*N*nbatch*/], real *sine, real *cosine, int N) { int k = blockIdx.x * blockDim.x + threadIdx.x; int b, N2 = N/2; complex f; real Fr, Fi, c, s; if (k > N2) return; f = Fin[k]; // in constant memory s = sine[k]; c = cosine[k]; for (b = 0; b < nbatch; b++) { Fr = Re(f) + deltas[b]; Fi = Im(f); f = (complex){ Fr*c - Fi*s, Fi*c + Fr*s }; Fout[k] = f; NEXT(Fout); } Fin[k] = f; } __device__ real mod2Pi(real x) { x = fmod(x, (real)TWO_PI); if (x > PI) return x - TWO_PI; if (x <= -PI) return x + TWO_PI; return x; } #ifdef RB // below is one thread per bin, as per other kernels // data is spread across blocks, but there is no sync across blocks // thus cannot do in-place window // parallel across bins in a batch item // could do bins*batches __global__ void window(complex Foutw[/*N*nbatch*/], complex Fout[/*N*nbatch*/], int N) { int k = blockIdx.x * blockDim.x + threadIdx.x; int b, N2 = N/2; complex F, Fm1, Fp1, f; real Fr, Fi; // in the last block if (k > N2) return; for (b = 0; b < nbatch; b++) { F = Foutw[k]; // conjugate reflection at edges Fp1 = k < N2 ? Foutw[k + 1] : conjugate(Foutw[N2-1]); Fm1 = k > 0 ? Foutw[k - 1] : conjugate(Foutw[1]); Fr = A*Re(F) + B2*(Re(Fm1) + Re(Fp1)); Fi = A*Im(F) + B2*(Im(Fm1) + Im(Fp1)); Re(f) = Fr; Im(f) = Fi; Fout[k] = f; NEXT(Fout); NEXT(Foutw); } } // parallel across batches // <<>> // what is memory access pattern? // small array sum, so not worth a tree reduction? // middle sample only, so +- on real parts __global__ void reconstruct(complex f[/*nbatch*N*/], real s[/*nbatch*/], int N) { int k = blockIdx.x * blockDim.x + threadIdx.x; complex *F = f + offset*k; real sum = real(0.0); int bin, N2 = N/2; if (k >= nbatch) return; for (bin = 0; bin < N; bin += 2) { real v0 = bin <= N2 ? Re(F[bin]) : Re(F[N - bin]); real v1 = bin < N2 ? Re(F[bin + 1]) : Re(F[N - bin - 1]); sum += v0 - v1; } s[k] = sum/N; } #else // the code below depends on fast single-precision // atomic addition // this parallelises across N*nbatch __global__ void window(complex Foutw[/*N*nbatch*/], complex Fout[/*N*nbatch*/], int N) { int n = blockIdx.x * blockDim.x + threadIdx.x; int N2 = N/2; int s = n/N; int k = n%N; complex F, Fm1, Fp1, f; real Fr, Fi; Foutw += s*offset; Fout += s*offset; // in the last block if (n > N*nbatch) return; F = Foutw[k]; Fp1 = k < N2 ? Foutw[k + 1] : conjugate(Foutw[N2-1]); Fm1 = k > 0 ? Foutw[k - 1] : conjugate(Foutw[1]); Fr = A*Re(F) + B2*(Re(Fm1) + Re(Fp1)); Fi = A*Im(F) + B2*(Im(Fm1) + Im(Fp1)); Re(f) = Fr; Im(f) = Fi; Fout[k] = f; } // this parallelises across N2*nbatch __global__ void reconstruct(complex f[/*nbatch*N*/], real s[/*nbatch*/], int N) { int n = blockIdx.x * blockDim.x + threadIdx.x, N2 = N/2; int k = n/N2; int bin = (n%N2)*2; complex *F = &f[offset*k]; if (n >= nbatch*N2) return; real v0 = bin <= N2 ? Re(F[bin]) : Re(F[N - bin]); real v1 = bin < N2 ? Re(F[bin + 1]) : Re(F[N - bin - 1]); atomicAdd(&s[k],v0-v1); } #endif __device__ phasor convert(complex f, real &oldiphase, int bin, int N) { real Fr, Fi; real phase, deltaphase; phasor pha; Fr = Re(f); Fi = Im(f); // magnitude is easy R(pha) = hypot(Fi, Fr); phase = atan2(Fi, Fr); deltaphase = phase - oldiphase; oldiphase = phase; // subtract expected phase diff deltaphase = mod2Pi(deltaphase - bin*TWO_PI/N); // find actual freq // scale by bin width to give freq Theta(pha) = binbandwidth * (bin + deltaphase*N/TWO_PI); return pha; } __device__ phasor harmonic_shift(phasor pha, real fm) { real sfreq; // tweak the freq using fm // same across all channels sfreq = Theta(pha)*fm; if (sfreq >= nyquist || sfreq <= -nyquist) R(pha) = real(0.0); Theta(pha) = sfreq; return pha; } __device__ real unconvert(phasor pha, real &oldophase, int N) { real bin, phase; bin = Theta(pha)/binbandwidth; phase = bin*TWO_PI/N; phase = mod2Pi(oldophase + phase); oldophase = phase; return R(pha)*cos(phase); } // parallelism across bins*channels __global__ void fmsyn(real inphase[/*N*/], complex F[/*nbatch*N*/], real fm[/*nbatch*/], real outphase[/*N*/], int N) { int k = blockIdx.x * blockDim.x + threadIdx.x; int b, N2 = N/2; real oldiphase, oldophase, val; phasor pha; if (k > N2) return; oldiphase = inphase[k]; oldophase = outphase[k]; for (b = 0; b < nbatch; b++) { pha = convert(F[k], oldiphase, k, N); // updates oldiphase pha = harmonic_shift(pha, fm[b]); // ignore imag part val = unconvert(pha, oldophase, N); // updates oldophase Re(F[k]) = val; NEXT(F); } inphase[k] = oldiphase; outphase[k] = oldophase; } // blocks a multiple of 32 threads // more blocks than multiprocessors // perhaps 128 threads per block, as long as you have more blocks than // multiprocessors void threadblock(int device, int n, int *nblocks, int *nthreads) { int nt, nb, nproc; cudaDeviceProp deviceProp; //printf("%d threads needed\n", n); cudaGetDeviceProperties(&deviceProp, device); nt = deviceProp.warpSize; // usually 32 threads nproc = deviceProp.multiProcessorCount; nb = 1 + (n - 1)/nt; //more blocks than procs if (nb >= 2*nproc) { nt *= 2; // 64 threads nb = 1 + (n - 1)/nt; } // // still more blocks than procs if (nb >= 2*nproc) { nt *= 2; // 128 threads nb = 1 + (n - 1)/nt; } if (nblocks) *nblocks = nb; if (nthreads) *nthreads = nt; } typedef struct _SPV { OPDS h; MYFLT *out, *in, *shift, *iN; int nbins, ptr, nbtch, nblocks, nblocks1, nthreads, nthreads1, rblocks, rthreads; real *deltas, *ddeltas, *dinphase, *doutphase, *dfm; real *sine, *cosine; complex *dFin, *dFout, *dFoutw; real *samples, srate; real *framesin, *framesout, *fm; AUXCH aframesfm, aframesout, aframesin; uint32_t count; } SPV; void init_tables(CSOUND *csound, SPV *p, int nbins) { int k; real s[nbins], c[nbins]; for (k = 0; k < nbins; k++) { sincos(TWO_PI*k/nbins, &s[k], &c[k]); } CUDA(cudaMemcpy, p->sine, s, nbins*sizeof(real), cudaMemcpyHostToDevice); CUDA(cudaMemcpy, p->cosine, c, nbins*sizeof(real), cudaMemcpyHostToDevice); } void cuinit(CSOUND *csound, SPV *p, uint32_t nframes, int nbins, int device) { int csize, rsize, off, nbins2; real binbw, nyq; cudaDeviceProp deviceProp; if(!p->aframesin.auxp || p->aframesin.size < sizeof(real)*NBATCH) csound->AuxAlloc(csound, sizeof(real)*NBATCH, &p->aframesin); if(!p->aframesout.auxp || p->aframesout.size < sizeof(real)*NBATCH) csound->AuxAlloc(csound, sizeof(real)*NBATCH, &p->aframesout); if(!p->aframesfm.auxp || p->aframesfm.size < sizeof(real)*NBATCH) csound->AuxAlloc(csound, sizeof(real)*NBATCH, &p->aframesfm); p->framesin = (real *) p->aframesin.auxp; p->framesout = (real *) p->aframesout.auxp; p->fm = (real *) p->aframesfm.auxp; p->nbins = nbins; nbins2 = nbins/2; p->nbtch = nframes; p->srate = (real) csound->GetSr(csound); binbw = p->srate/p->nbins; nyq = p->srate/real(2.0); CUDA(cudaSetDevice, device); cudaGetDeviceProperties(&deviceProp, device); // allocate contiguous arrays to aid cudaMemcpy; round up to align // arrays for coalescence csize = roundup(p->nbins*sizeof(complex)); rsize = roundup(p->nbins*sizeof(real)); off = csize/sizeof(complex); if (off != rsize/sizeof(real)) { csound->InitError(csound, "Something weird happening with offsets at line %d\n", __LINE__); } if (!csound->QueryGlobalVariable(csound, "::cusliding::init")) { csound->CreateGlobalVariable(csound, "::cusliding::init",1); #ifndef RB csound->Message(csound, "Sliding PV: using floats on device %s (capability %d.%d)\n", deviceProp.name, deviceProp.major, deviceProp.minor); #else csound->Message(csound, "Sliding PV: using doubles on device %s (capability %d.%d)\n", deviceProp.name, deviceProp.major, deviceProp.minor); #endif // global constants CUDA(cudaMemcpyToSymbol, offset, &off, sizeof(int)); CUDA(cudaMemcpyToSymbol, nbatch, &p->nbtch, sizeof(int)); CUDA(cudaMemcpyToSymbol, binbandwidth, &binbw, sizeof(real)); CUDA(cudaMemcpyToSymbol, nyquist, &nyq, sizeof(real)); } // N complexes CUDA(cudaMalloc, &p->dFin, csize); CUDA(cudaMemset, p->dFin, 0, csize); // N*nbatch complexes CUDA(cudaMalloc, &p->dFout, p->nbtch*csize); CUDA(cudaMalloc, &p->dFoutw, p->nbtch*csize); // N reals CUDA(cudaMalloc, &p->dinphase, p->nbins*sizeof(real)); CUDA(cudaMalloc, &p->doutphase, p->nbins*sizeof(real)); CUDA(cudaMemset, p->dinphase, 0, p->nbins*sizeof(real)); CUDA(cudaMemset, p->doutphase, 0, p->nbins*sizeof(real)); CUDA(cudaMalloc, &p->sine, p->nbins*sizeof(real)); CUDA(cudaMalloc, &p->cosine, p->nbins*sizeof(real)); // nbatch reals CUDA(cudaMalloc, &p->ddeltas, p->nbtch*sizeof(real)); CUDA(cudaMalloc, &p->dfm, p->nbtch*sizeof(real)); // circular history of nbins samples p->samples = (real*) csound->Calloc(csound, p->nbins*sizeof(real)); if (p->samples == NULL) { csound->InitError(csound, "calloc failed at line %d\n", __LINE__); return; } // pinned memory is marginally faster //CUDA(cudaHostAlloc, &deltas, p->nbtch*sizeof(real), cudaHostAllocDefault); p->deltas = (real*) csound->Malloc(csound, p->nbtch*sizeof(real)); if (p->deltas == NULL) { csound->InitError(csound, "malloc failed at line %d\n", __LINE__); return; } init_tables(csound, p, p->nbins); // index of oldest sample p->ptr = 0; #ifdef RB threadblock(device, p->nbtch, &p->rblocks, &p->rthreads); #else threadblock(device, p->nbtch*(nbins2), &p->rblocks, &p->rthreads); threadblock(device, p->nbtch*nbins, &p->nblocks1, &p->nthreads1); #endif threadblock(device, (nbins2+1), &p->nblocks, &p->nthreads); if(csound->GetDebug(csound)) { csound->Message(csound, "%d bins, %d actual\n", p->nbins, nbins2 + 1); csound->Message(csound, "csize = %d -> %d bytes, offset %d elements\n", (int) (p->nbins*sizeof(complex)), csize, off); csound->Message(csound, "%gHz bin bandwidth, Nyquist %gHz\n", binbw, nyq); csound->Message(csound, "period %d samples (%g sec)\n", p->nbtch, (real)p->nbtch/p->srate); csound->Message(csound, "%d multiprocessors\n", deviceProp.multiProcessorCount); csound->Message(csound, "%d blocks with %d threads = %d\n", p->nblocks, p->nthreads, p->nblocks1*p->nthreads); csound->Message(csound, "%d idle threads in last block\n", p->nblocks*p->nthreads - (nbins2 + 1)); csound->Message(csound, "%d blocks per SM\n", (int)ceil((double)p->nblocks/deviceProp.multiProcessorCount)); csound->Message(csound, "reconstruct using %d blocks of %d threads = %d\n", p->rblocks, p->rthreads, p->rblocks*p->rthreads); } } int cushutdown(CSOUND *csound, void *pp) { SPV *p = (SPV *) pp; csound->Free(csound, p->samples); CUDA(cudaFree, p->dinphase); CUDA(cudaFree, p->doutphase); CUDA(cudaFree, p->ddeltas); CUDA(cudaFree, p->dFoutw); CUDA(cudaFree, p->dFout); CUDA(cudaFree, p->dFin); CUDA(cudaFree, p->sine); CUDA(cudaFree, p->cosine); //CUDA(cudaFreeHost, deltas); csound->Free(csound, p->deltas); if(csound->GetDebug(csound)) csound->Message(csound, "cuda shutdown\n"); return OK; } // in samples with channels muxed 0 1 2 0 1 2 ... void cuprocess(CSOUND *csound, SPV *p, real in[/*nbatch*/], real out[/*nbatch*/], real fm[/*nbatch*/]) { int b; for (b = 0; b < p->nbtch; b++) { p->deltas[b] = in[b] - p->samples[p->ptr]; p->samples[p->ptr] = in[b]; p->ptr = (p->ptr + 1) % (p->nbins); } CUDA(cudaMemcpy, p->ddeltas, p->deltas, p->nbtch*sizeof(real), cudaMemcpyHostToDevice); slide<<nblocks,p->nthreads>>>(p->ddeltas, p->dFin, p->dFoutw, p->sine, p->cosine, p->nbins); cudaDeviceSynchronize(); CHK(slide); // Foutw and Fout must be separate to avoid data race #ifdef RB window<<nblocks,p->nthreads>>>(p->dFoutw, p->dFout, p->nbins); #else window<<nblocks1,p->nthreads1>>>(p->dFoutw, p->dFout, p->nbins); #endif cudaDeviceSynchronize(); CHK(window); CUDA(cudaMemcpy, p->dfm, fm, p->nbtch*sizeof(real), cudaMemcpyHostToDevice); fmsyn<<nblocks,p->nthreads>>>(p->dinphase, p->dFout, p->dfm, p->doutphase, p->nbins); // reuse ddeltas array reconstruct<<rblocks,p->rthreads>>>(p->dFout, p->ddeltas, p->nbins); CHK(reconstruct); // is is faster to transfer to pinned memory then copy; or just // transfer directly to out? CUDA(cudaMemcpy, out, p->ddeltas, p->nbtch*sizeof(real), cudaMemcpyDeviceToHost); #ifndef RB for(b=0; b < p->nbtch; b++) out[b] /= p->nbins; #endif } int spv_init(CSOUND *csound, SPV *p) { cuinit(csound,p,NBATCH,*p->iN,0); csound->RegisterDeinitCallback(csound, p, cushutdown); return OK; } int spv_perf(CSOUND *csound, SPV *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; uint32_t count = p->count; if (UNLIKELY(offset)) memset(p->out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->out[nsmps], '\0', early*sizeof(MYFLT)); } for(n=offset; n < nsmps; n++) { p->framesin[count] = p->in[n]; p->out[n] = p->framesout[count]; p->fm[count] = p->shift[n]; count++; if(count == NBATCH) { cuprocess(csound, p,p->framesin,p->framesout,p->fm); count = 0; } } p->count = count; return OK; } static OENTRY localops[] = { {"cudasliding", sizeof(SPV),0, 5, "a", "aai", (SUBR) spv_init, NULL, (SUBR) spv_perf} }; extern "C" { LINKAGE } csound-6.10.0/Opcodes/dam.c000066400000000000000000000102241321653344700154010ustar00rootroot00000000000000/* dam.c: Copyright (C) 1997 Marc Resibois This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "stdopcod.h" #include "dam.h" #include #define SQRT2 FL(1.41421356237309504880168872421) /* * Dynamic Amplitude Modifier. * * (C) Marc Resibois 1997 * * I place this source code in the public domain. Just * let me know if you do something you like with it ;-) * * For bugs, question, please write to Marc.Resibois@ping.be */ /* * Initialisation code */ static int daminit(CSOUND *csound, DAM *p) { /* Initialise gain value */ p->gain = FL(1.0); /* Compute the gain speed changes from parameter given by Csound */ /* the computed values are stored in the opcode data structure p */ /* for later use in the main processing */ p->rspeed = (*p->rtime)*csound->onedsr*FL(1000.0); p->fspeed = (*p->ftime)*csound->onedsr*FL(1000.0); p->kthr = -FL(1.0); return OK; } /* * Run-time computation code */ static int dam(CSOUND *csound, DAM *p) { MYFLT *ain,*aout; MYFLT threshold; MYFLT gain; MYFLT comp1,comp2; MYFLT *powerPos; MYFLT *powerBuffer; MYFLT power; MYFLT tg; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; /* Initialize power value and buffer at first ksamp computed as * it depends on kthreshold */ if (p->kthr < FL(0.0)) { MYFLT x = (p->kthr = *(p->kthreshold))/(MYFLT)POWER_BUFSIZE; p->power = p->kthr; /* Initialise table as threshhold changed */ for (i=0;ipowerBuffer[i] = x; } p->powerPos = p->powerBuffer; } ain = p->ain; aout = p->aout; threshold = *(p->kthreshold); gain = p->gain; comp1 = *(p->icomp1); comp2 = *(p->icomp2); powerPos = p->powerPos; powerBuffer = p->powerBuffer; power = p->power; /* Process ksmps samples */ if (UNLIKELY(offset)) memset(aout, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&aout[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset;ipowerBuffer; } power -= (*powerPos); /* Looks where the power is related to the threshold and compute target gain */ if (power>threshold) { tg = ((power-threshold)*comp1+threshold)/power; } else { tg = threshold*(POWER((power/threshold), FL(1.0)/comp2))/power; } /* move gain toward target */ if (gainrspeed; } else { gain -= p->fspeed; } /* compute output */ aout[i] = ain[i]*gain; } /* Store the last gain value for next call */ p->gain = gain; p->power = power; p->powerPos = powerPos; return OK; } #define S(x) sizeof(x) static OENTRY localops[] = { { "dam", S(DAM), 0, 5, "a", "akiiii",(SUBR)daminit, NULL, (SUBR)dam }, }; int dam_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/dam.h000066400000000000000000000025671321653344700154210ustar00rootroot00000000000000/* dam.h: Copyright (C) 1997 Marc Resibois This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csdl.h" #define POWER_BUFSIZE 1000 typedef struct { OPDS h ; MYFLT *aout ; /* Declare output array first */ MYFLT *ain ; /* Input array */ MYFLT *kthreshold ;/* sound level threshold */ MYFLT *icomp1 ; /* Compression factors */ MYFLT *icomp2 ; MYFLT *rtime ; /* Raise/Fall times */ MYFLT *ftime ; MYFLT rspeed ; MYFLT fspeed ; MYFLT gain ; MYFLT power ; MYFLT powerBuffer[POWER_BUFSIZE] ; MYFLT *powerPos ; MYFLT kthr; } DAM ; /* void daminit(DAM *p) ; */ /* void dam(DAM *p) ; */ csound-6.10.0/Opcodes/date.c000066400000000000000000000144741321653344700155700ustar00rootroot00000000000000/* date.c: Copyright (C) 2006 John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csdl.h" #include #include #if defined(__MACH__) #include #endif typedef struct { OPDS h; MYFLT *time_; MYFLT *nano; } DATEMYFLT; typedef struct { OPDS h; STRINGDAT *Stime_; MYFLT *timstmp; } DATESTRING; static int datemyfltset(CSOUND *csound, DATEMYFLT *p) { #ifdef USE_DOUBLE const time_t base = 0; #else /* time_t base = 946684800; */ /* 1 Jan 2000 */ const time_t base = 1262304000; /* 1 Jan 2010 */ #endif #ifdef LINUX struct timespec tp; clock_gettime(CLOCK_REALTIME, &tp); *p->time_ = (MYFLT) (tp.tv_sec-base); *p->time_ += (MYFLT)(tp.tv_nsec)*1.0e-9; if (p->OUTOCOUNT==2) *p->nano =(MYFLT)tp.tv_nsec; #else #ifdef __MACH // There may be more accurate methods..... struct timeval tp; int rv = gettimeofday(&tp, NULL); *p->time_ = (MYFLT)(tp.tv_sec-base); *p->time_ += (MYFLT)(tp.tv_usec)*1.0e-6; if (p->OUTOCOUNT==2) *p->nano =(MYFLT)(tp.tv_usec * 1000); #else *p->time_ = (MYFLT) (time(NULL)-base); if (p->OUTOCOUNT==2) *p->nano = FL(0.0); #endif #endif return OK; } static int datestringset(CSOUND *csound, DATESTRING *p) { time_t temp_time; char *time_string; /* char *q; */ int32 tmp; #if defined(MSVC) || (defined(__GNUC__) && defined(__i386__)) tmp = (int32) MYFLT2LRND(*(p->timstmp)); #else tmp = (int32) (*(p->timstmp) + FL(0.5)); #endif if (tmp <= 0) temp_time = time(NULL); else temp_time = (time_t)tmp; time_string = ctime(&temp_time); /* printf("Timestamp = %f\ntimestring=>%s<\n", *p->timstmp, time_string); */ /* q = strchr(time_string, '\n'); */ /* if (q) *q='\0'; */ if (p->Stime_->data != NULL) csound->Free(csound, p->Stime_->data); p->Stime_->data = csound->Strdup(csound, time_string); p->Stime_->size = strlen(time_string)+1; return OK; } typedef struct { OPDS h; STRINGDAT *Scd; } GETCWD; static int getcurdir(CSOUND *csound, GETCWD *p) { if (p->Scd->size < 1024) { p->Scd->size = 1024; p->Scd->data = csound->ReAlloc(csound, p->Scd->data, p->Scd->size); } if (p->Scd->data == NULL) { p->Scd->size = 1024; p->Scd->data = csound->Calloc(csound, p->Scd->size); } #if defined(__MACH__) || defined(LINUX) || defined(__HAIKU__) || defined(__CYGWIN__) if (UNLIKELY(getcwd(p->Scd->data, p->Scd->size-1)==NULL)) #else if (UNLIKELY( _getcwd(p->Scd->data, p->Scd->size-1)==NULL)) #endif { strncpy(p->Scd->data, "**Unknown**", p->Scd->size-1); return csound->InitError(csound, Str("cannot determine current directory: %s\n"), strerror(errno)); } return OK; } #ifndef MAXLINE #define MAXLINE 1024 #endif typedef struct { OPDS h; STRINGDAT *Sline; MYFLT *line; MYFLT *Sfile; FILE *fd; int lineno; } READF; static int readf_delete(CSOUND *csound, void *p) { READF *pp = (READF*)p; if (pp->fd) fclose(pp->fd); return OK; } static int readf_init_(CSOUND *csound, READF *p, int isstring) { char name[1024]; if(isstring) strncpy(name, ((STRINGDAT *)p->Sfile)->data, 1023); else csound->strarg2name(csound, name, p->Sfile, "input.", 0); p->fd = fopen(name, "r"); p->lineno = 0; if (p->Sline->size < MAXLINE) { if(p->Sline->data != NULL) csound->Free(csound, p->Sline->data); p->Sline->data = (char *) csound->Calloc(csound, MAXLINE); p->Sline->size = MAXLINE; } if (UNLIKELY(p->fd==NULL)) return csound->InitError(csound, Str("readf: failed to open file")); return csound->RegisterDeinitCallback(csound, p, readf_delete); } static int readf_init(CSOUND *csound, READF *p){ return readf_init_(csound,p,0); } static int readf_init_S(CSOUND *csound, READF *p){ return readf_init_(csound,p,1); } static int readf(CSOUND *csound, READF *p) { p->Sline->data[0] = '\0'; if (UNLIKELY(fgets(p->Sline->data, p->Sline->size-1, p->fd)==NULL)) { int ff = feof(p->fd); fclose(p->fd); p->fd = NULL; if (ff) { *p->line = -1; return OK; } else return csound->PerfError(csound, p->h.insdshead, Str("readf: read failure")); } *p->line = ++p->lineno; return OK; } static int readfi(CSOUND *csound, READF *p) { if (p->fd==NULL) if (UNLIKELY(readf_init(csound, p)!= OK)) return csound->InitError(csound, Str("readi failed to initialise")); return readf(csound, p); } static int readfi_S(CSOUND *csound, READF *p) { if (p->fd==NULL) if (UNLIKELY(readf_init_S(csound, p)!= OK)) return csound->InitError(csound, Str("readi failed to initialise")); return readf(csound, p); } static OENTRY date_localops[] = { { "date.i", sizeof(DATEMYFLT), 0, 1, "iI", "", (SUBR)datemyfltset }, { "date.k", sizeof(DATEMYFLT), 0, 3, "kz", "", (SUBR)datemyfltset, (SUBR)datemyfltset }, { "dates", sizeof(DATESTRING), 0, 1, "S", "j", (SUBR)datestringset }, { "pwd", sizeof(GETCWD), 0, 1, "S", "", (SUBR)getcurdir }, { "readfi", sizeof(READF), 0, 1, "Si", "i", (SUBR)readfi, }, { "readfi.S", sizeof(READF), 0, 1, "Si", "S", (SUBR)readfi_S, }, { "readf", sizeof(READF), 0, 3, "Sk", "i", (SUBR)readf_init, (SUBR)readf }, { "readf.S", sizeof(READF), 0, 3, "Sk", "S", (SUBR)readf_init_S, (SUBR)readf } }; LINKAGE_BUILTIN(date_localops) csound-6.10.0/Opcodes/dcblockr.c000066400000000000000000000142661321653344700164350ustar00rootroot00000000000000/* dcblockr.c: Copyright (C) 1998 John ffitch, 2008 V Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /*******************************************/ /* DC Blocking Filter */ /* by Perry R. Cook, 1995-96 */ /* This guy is very helpful in, uh, */ /* blocking DC. Needed because a simple */ /* low-pass reflection filter allows DC */ /* to build up inside recursive */ /* structures. */ /*******************************************/ #include "stdopcod.h" #include "dcblockr.h" static int dcblockrset(CSOUND *csound, DCBlocker* p) { p->outputs = 0.0; p->inputs = 0.0; p->gain = (double)*p->gg; if (p->gain == 0.0 || p->gain>=1.0 || p->gain<=-1.0) p->gain = 0.99; return OK; } static int dcblockr(CSOUND *csound, DCBlocker* p) { MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; double gain = p->gain; double outputs = p->outputs; double inputs = p->inputs; MYFLT *samp = p->in; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; noutputs = outputs; p->inputs = inputs; return OK; } /*******************************************/ /* DC Blocking Filter */ /* Improved DC attenuation */ /* V Lazzarini */ /*******************************************/ typedef struct _dcblk2 { OPDS h; MYFLT *output; MYFLT *input, *order, *iskip; AUXCH delay1; AUXCH iirdelay1, iirdelay2, iirdelay3, iirdelay4; double ydels[4]; int dp1,dp2; double scaler; } DCBlock2; static int dcblock2set(CSOUND *csound, DCBlock2* p) { int order = (int) *p->order; if (order == 0) order = 128; else if (order < 4) order = 4; if (p->delay1.auxp == NULL || p->delay1.size < (order-1)*2*sizeof(double)) csound->AuxAlloc(csound, (order-1)*2*sizeof(double), &p->delay1); if (p->iirdelay1.auxp == NULL || p->iirdelay1.size < (order)*sizeof(double)) csound->AuxAlloc(csound, (order)*sizeof(double), &p->iirdelay1); if (p->iirdelay2.auxp == NULL || p->iirdelay2.size < (order)*sizeof(double)) csound->AuxAlloc(csound, (order)*sizeof(double), &p->iirdelay2); if (p->iirdelay3.auxp == NULL || p->iirdelay3.size < (order)*sizeof(double)) csound->AuxAlloc(csound, (order)*sizeof(double), &p->iirdelay3); if (p->iirdelay4.auxp == NULL || p->iirdelay4.size < (order)*sizeof(double)) csound->AuxAlloc(csound, (order)*sizeof(double), &p->iirdelay4); p->scaler = 1.0/order; if (!*p->iskip) { memset(p->ydels, 0, 4*sizeof(double)); /* p->ydels[0] = 0.0; p->ydels[1] = 0.0; */ /* p->ydels[2] = 0.0; p->ydels[3] = 0.0; */ memset(p->delay1.auxp, 0, sizeof(double)*(order-1)*2); memset(p->iirdelay1.auxp, 0, sizeof(double)*(order)); memset(p->iirdelay2.auxp, 0, sizeof(double)*(order)); memset(p->iirdelay3.auxp, 0, sizeof(double)*(order)); memset(p->iirdelay4.auxp, 0, sizeof(double)*(order)); p->dp1 = 0; p->dp2 = 0; } return OK; } static int dcblock2(CSOUND *csound, DCBlock2* p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT *in = p->input; MYFLT *out = p->output; double *del1 = (double *)p->delay1.auxp; double *iirdel[4],x1,x2,y,del; double *ydels = p->ydels; double scale = p->scaler; int p1 = p->dp1; int p2 = p->dp2; int j,del1size, iirdelsize; iirdel[0] = (double *) p->iirdelay1.auxp; iirdel[1] = (double *) p->iirdelay2.auxp; iirdel[2] = (double *) p->iirdelay3.auxp; iirdel[3] = (double *) p->iirdelay4.auxp; del1size = p->delay1.size/sizeof(double); iirdelsize = p->iirdelay1.size/sizeof(double); if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset; i < nsmps; i++) { /* long delay */ del = del1[p1]; del1[p1] = x1 = (double)in[i]; /* IIR cascade */ for (j=0; j < 4; j++) { x2 = iirdel[j][p2]; iirdel[j][p2] = x1; y = x1 - x2 + ydels[j]; ydels[j] = y; x1 = y*scale; } out[i] = (MYFLT)(del - x1); p1 = (p1 == del1size-1 ? 0 : p1 + 1); p2 = (p2 == iirdelsize-1 ? 0 : p2 + 1); } p->dp1 = p1; p->dp2 = p2; return OK; } #define S(x) sizeof(x) static OENTRY localops[] = { { "dcblock", S(DCBlocker), 0, 5, "a", "ao", (SUBR)dcblockrset, NULL, (SUBR)dcblockr}, { "dcblock2", S(DCBlock2), 0, 5, "a", "aoo", (SUBR)dcblock2set, NULL, (SUBR)dcblock2} }; int dcblockr_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/dcblockr.h000066400000000000000000000017441321653344700164370ustar00rootroot00000000000000/* dcblockr.h: Copyright (C) 1998 John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ typedef struct DCBlocker { OPDS h; MYFLT *ar, *in, *gg; double outputs; double inputs; double gain; } DCBlocker; csound-6.10.0/Opcodes/doppler.cpp000066400000000000000000000235661321653344700166620ustar00rootroot00000000000000/* doppler.cpp Copyright (C) 2014 Michael Gogins This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #ifndef M_PI # define M_PI 3.14159265358979323846 #endif using namespace csound; /* *************** does not deal with unaligned signals ************** */ class RCLowpassFilter { public: void initialize(MYFLT sampleRate, MYFLT cutoffHz, MYFLT initialValue) { MYFLT tau = MYFLT(1.0) / (MYFLT(2.0) * M_PI * cutoffHz); alpha = MYFLT(1.0) / (MYFLT(1.0) + (tau * sampleRate)); value = initialValue; } MYFLT update(MYFLT inputValue) { value += alpha * (inputValue - value); return value; } protected: MYFLT alpha; MYFLT value; }; class LinearInterpolator { public: LinearInterpolator() : priorValue(MYFLT(0.0)), currentValue(MYFLT(0.0)) { } virtual void put(MYFLT inputValue) { priorValue = currentValue; currentValue = inputValue; } virtual MYFLT get(MYFLT fraction) { return priorValue + (fraction * (currentValue - priorValue)); } protected: MYFLT priorValue; MYFLT currentValue; }; class DelayLine : public std::vector { public: MYFLT sampleRate; int writingFrame; int size_; void initialize(size_t sampleRate_, MYFLT maximumDelay = 10.0) { sampleRate = (MYFLT) sampleRate_; size_ = (int) std::ceil(maximumDelay * sampleRate); //std::cout << "DelayLine::initialize: size: " << size_ << std::endl; //std::cout << "DelayLine::initialize: sampleRate: " << sampleRate << std::endl; resize(size_); writingFrame = 0; } void write(MYFLT value) { while (writingFrame >= size_) { writingFrame -= size_; } (*this)[(size_t) writingFrame] = value; //std::cout << "DelayLine::write: writingFrame: " << writingFrame << std::endl; writingFrame++; } MYFLT delaySeconds(MYFLT delaySeconds) { int delayFrames_ = (int) (delaySeconds * sampleRate); return delayFrames(delayFrames_); } MYFLT delayFrames(int delayFrames_) { //std::cout << "DelayLine::delayFrames: delayFrames: " // << delayFrames_ << std::endl; int readingFrame = writingFrame - delayFrames_; while (readingFrame < 0) { readingFrame += size_; } while (readingFrame >= size_) { readingFrame -= size_; } // std::cout << "DelayLine::delayFrames: readingFrame: " // << readingFrame << std::endl; return (*this)[(size_t) readingFrame]; } }; class Doppler : public OpcodeNoteoffBase { public: // Csound opcode outputs. MYFLT *audioOutput; // Csound opcode inputs. MYFLT *audioInput; MYFLT *kSourcePosition; // usually meters MYFLT *kMicPosition; // usually meters MYFLT *jSpeedOfSound; // usually meters/second MYFLT *jUpdateFilterCutoff; // Hz // Doppler internal state. MYFLT speedOfSound; // usually meters/second MYFLT smoothingFilterCutoff; // Hz MYFLT sampleRate; // Hz MYFLT samplesPerDistance; // usually samples/meter MYFLT blockRate; // Hz int blockSize; // samples RCLowpassFilter *smoothingFilter; LinearInterpolator *audioInterpolator; std::list< std::vector *> *audioBufferQueue; std::list *sourcePositionQueue; int relativeIndex; int currentIndex; int init(CSOUND *csound) { sampleRate = csound->GetSr(csound); blockRate = opds.insdshead->ekr; blockSize = opds.insdshead->ksmps; // Take care of default values. if (*jSpeedOfSound == MYFLT(-1.0)) { speedOfSound = MYFLT(340.29); } else speedOfSound = *jSpeedOfSound; if (*jUpdateFilterCutoff == MYFLT(-1.0)) { // MYFLT blockRateNyquist = blockRate / MYFLT(2.0); // *jUpdateFilterCutoff = blockRateNyquist / MYFLT(2.0); smoothingFilterCutoff = MYFLT(6.0); // very conservative } else smoothingFilterCutoff = *jUpdateFilterCutoff; samplesPerDistance = sampleRate / speedOfSound; audioInterpolator = new LinearInterpolator; smoothingFilter = NULL; audioBufferQueue = new std::list< std::vector *>; sourcePositionQueue = new std::list; currentIndex = 0; relativeIndex = 0; return OK; } int kontrol(CSOUND *csound) { MYFLT sourcePosition = *kSourcePosition; MYFLT micPosition = *kMicPosition; std::vector *sourceBuffer = new std::vector; sourceBuffer->resize(blockSize); for (size_t inputFrame = 0; inputFrame<(unsigned int)blockSize; inputFrame++) { (*sourceBuffer)[inputFrame] = audioInput[inputFrame]; } audioBufferQueue->push_back(sourceBuffer); sourcePositionQueue->push_back(sourcePosition); std::vector *currentBuffer = audioBufferQueue->front(); MYFLT targetPosition = sourcePositionQueue->front() - micPosition; // The smoothing filter cannot be initialized at i-time, // because it must be initialized from a k-rate variable. if (!smoothingFilter) { smoothingFilter = new RCLowpassFilter(); smoothingFilter->initialize(sampleRate, smoothingFilterCutoff, targetPosition); warn(csound, "Doppler::kontrol: sizeof(MYFLT): %10d\n", sizeof(MYFLT)); warn(csound, "Doppler::kontrol: PI: %10.3f\n", M_PI); warn(csound, "Doppler::kontrol: this: %10p\n", this); warn(csound, "Doppler::kontrol: sampleRate: %10.3f\n", sampleRate); warn(csound, "Doppler::kontrol: blockSize: %10.3f\n", blockSize); warn(csound, "Doppler::kontrol: blockRate: %10.3f\n", blockRate); warn(csound, "Doppler::kontrol: speedOfSound: %10.3f\n", speedOfSound); warn(csound, "Doppler::kontrol: samplesPerDistance: %10.3f\n", samplesPerDistance); warn(csound, "Doppler::kontrol: smoothingFilterCutoff: %10.3f\n", smoothingFilterCutoff); warn(csound, "Doppler::kontrol: kMicPosition: %10.3f\n", *kMicPosition); warn(csound, "Doppler::kontrol: kSourcePosition: %10.3f\n", *kSourcePosition); } for (size_t outputFrame = 0; outputFrame < (unsigned int)blockSize; outputFrame++) { MYFLT position = smoothingFilter->update(targetPosition); MYFLT distance = std::fabs(position); MYFLT sourceTime = relativeIndex - (distance * samplesPerDistance); int targetIndex = int(sourceTime); MYFLT fraction = sourceTime - targetIndex; relativeIndex++; for ( ; targetIndex >= currentIndex; currentIndex++) { if (currentIndex >= blockSize) { relativeIndex -= blockSize; currentIndex -= blockSize; targetIndex -= blockSize; delete audioBufferQueue->front(); audioBufferQueue->pop_front(); sourcePositionQueue->pop_front(); currentBuffer = audioBufferQueue->front(); targetPosition = sourcePositionQueue->front() - micPosition; } audioInterpolator->put((*currentBuffer)[currentIndex]); } MYFLT currentSample = audioInterpolator->get(fraction); audioOutput[outputFrame] = currentSample; } return OK; } int noteoff(CSOUND *csound) { int result = OK; if (audioBufferQueue) { while (!audioBufferQueue->empty()) { delete audioBufferQueue->front(); audioBufferQueue->pop_front(); } delete audioBufferQueue; audioBufferQueue = 0; } if (sourcePositionQueue) { delete sourcePositionQueue; sourcePositionQueue = 0; } if (audioInterpolator) { delete audioInterpolator; audioInterpolator = 0; } if (smoothingFilter) { delete smoothingFilter; smoothingFilter = 0; } return result; } }; extern "C" { OENTRY oentries[] = { { (char*)"doppler", sizeof(Doppler), 0, 3, (char*)"a", (char*)"akkjj", (SUBR) Doppler::init_, (SUBR) Doppler::kontrol_, 0, }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; PUBLIC int csoundModuleInit_doppler(CSOUND *csound) { int status = 0; for(OENTRY *oentry = &oentries[0]; oentry->opname; oentry++) { status |= csound->AppendOpcode(csound, oentry->opname, oentry->dsblksiz, oentry->flags, oentry->thread, oentry->outypes, oentry->intypes, (int (*)(CSOUND*,void*)) oentry->iopadr, (int (*)(CSOUND*,void*)) oentry->kopadr, (int (*)(CSOUND*,void*)) oentry->aopadr); } return status; } #ifndef INIT_STATIC_MODULES PUBLIC int csoundModuleCreate(CSOUND *csound) { return 0; } PUBLIC int csoundModuleInit(CSOUND *csound) { return csoundModuleInit_doppler(csound); } PUBLIC int csoundModuleDestroy(CSOUND *csound) { return 0; } #endif } csound-6.10.0/Opcodes/dsputil.c000066400000000000000000000356171321653344700163410ustar00rootroot00000000000000/* dsputil.c: Copyright (C) 1991 Dan Ellis, Barry Vercoe, John ffitch, Copyright (C) 1988 Codemist Ltd This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /******************************************************************/ /* dsputil.c */ /* DSP utility functions for Csound - dispfft, pvoc, and convolve */ /* 20apr90 dpwe */ /******************************************************************/ #include "pvoc.h" #include /* Do we do the whole buffer, or just indep vals? */ #define someof(s) (s) /* (1L+s/2L) is the indep vals in an FFT frame of length (s).. well */ /* (change to just (s) to work on whole buffer) */ #define actual(s) ((s-1L)*2L) /* if callers are passing whole frame size, make this (s) */ /* where callers pass s/2+1, this recreates the parent fft frame size */ /* assumes that FFTsize is an integer multiple of 4 */ void Polar2Real_PVOC(CSOUND *csound, MYFLT *buf, int FFTsize) { MYFLT re, im; int i; for (i = 0; i < FFTsize; i += 4) { re = buf[i] * COS(buf[i + 1]); im = buf[i] * SIN(buf[i + 1]); buf[i ] = re; buf[i + 1] = im; /* Offset the phase to align centres of stretched windows, not starts */ re = -(buf[i + 2] * COS(buf[i + 3])); im = -(buf[i + 2] * SIN(buf[i + 3])); buf[i + 2] = re; buf[i + 3] = im; } /* kill spurious imag at dc & fs/2 */ buf[1] = buf[i]; buf[i] = buf[i + 1] = FL(0.0); /* calculate inverse FFT */ csound->InverseRealFFT(csound, buf, FFTsize); } #define MMmaskPhs(p,q,s) /* p is pha, q is as int, s is 1/PI */ \ q = (int)(s*p); \ p -= PI_F*(MYFLT)((int)((q+((q>=0)?(q&1):-(q&1) )))); \ void RewrapPhase(MYFLT *buf, int32 size, MYFLT *oldPh) { int32 i; MYFLT *pha; MYFLT p,oneOnPi; int z; /* Phase angle was properly scaled when it came out of frqspace */ /* .. so just add it */ pha = buf + 1; oneOnPi = FL(1.0)/PI_F; for (i=0; i breakPoint) { /* we will do 2 in 1st loop, rest in 2nd. */ for (i=0; i breakPoint) { /* we will do 2 in 1st loop, rest in 2nd. */ for (i=0; i 1 ? FL(1.0) : lex) * (MYFLT) SPTS; /* If we are upsampling, LPF is at input frq => sinc pd matches */ /* downsamp => lpf at output rate; input steps at some fraction */ in2out = (int) ((MYFLT) SPDS * (fex < FL(1.0) ? FL(1.0) : fex)); /* number of input points contributing to each op: depends on LPF */ realInStep = stindex; stepInStep = fex; for (i = 0; idsputil_sncTab[nrst] + frac * (p->dsputil_sncTab[nrst + 1] - p->dsputil_sncTab[nrst])) * (MYFLT) inSnd[nrstInStep]; for (j=1L; j=0L ) { /* Brackets inserted here */ nrst = (int)negPhase; frac = negPhase - (MYFLT)nrst; } a += (p->dsputil_sncTab[nrst] + frac * (p->dsputil_sncTab[nrst + 1] - p->dsputil_sncTab[nrst])) * (MYFLT) inSnd[x]; if ( (x = nrstInStep+j)dsputil_sncTab[nrst] + frac * (p->dsputil_sncTab[nrst + 1] - p->dsputil_sncTab[nrst])) * (MYFLT) inSnd[x]; } outSnd[i] = (float)a; realInStep += stepInStep; } } /*--------------------------------------------------------------------*/ /*---------------------------- sinc module ---------------------------*/ /*--------------------------------------------------------------------*/ /* (ugens7.h) #define SPTS (16) */ /* How many points in each lobe */ void MakeSinc(PVOC_GLOBALS *p) /* initialise our static sinc table */ { int i; int stLen = SPDS*SPTS; /* sinc table is SPDS/2 periods of sinc */ MYFLT theta = FL(0.0); /* theta (sinc arg) reaches pi in SPTS */ MYFLT dtheta = (MYFLT)(SBW*PI)/(MYFLT)SPTS;/* SBW lowers cutoff to redcali */ MYFLT phi = FL(0.0); /* phi (hamm arg) reaches pi at max ext */ MYFLT dphi = PI_F/(MYFLT)(SPDS*SPTS); if (p->dsputil_sncTab == NULL) p->dsputil_sncTab = (MYFLT*) p->csound->Malloc(p->csound, (stLen + 1) * sizeof(MYFLT)); /* (stLen+1 to include final zero; better for interpolation etc) */ p->dsputil_sncTab[0] = FL(1.0); for (i = 1; i <= stLen; ++i) { /* build table of sin x / x */ theta += dtheta; phi += dphi; p->dsputil_sncTab[i] = SIN(theta) / theta * (FL(0.54) + FL(0.46) * COS(phi)); /* hamming window on top of sinc */ } } /****************************************/ /** prewarp.c module */ /****************************************/ /* spectral envelope detection: this is a very crude peak picking algorithm which is used to detect and pre-warp the spectral envelope so that pitch transposition can be performed without altering timbre. The basic idea is to disallow large negative slopes between successive values of magnitude vs. frequency. */ void PreWarpSpec( //PVOC_GLOBALS *p, MYFLT *spec, /* spectrum as magnitude,phase */ int32 size, /* full frame size, tho' we only use n/2+1 */ MYFLT warpFactor, /* How much pitches are being multd by */ MYFLT *dsputil_env) { MYFLT eps,slope; MYFLT mag, lastmag, nextmag, pkOld; int32 pkcnt, i, j; eps = -FL(64.0) / size; /* for spectral envelope estimation */ lastmag = *spec; mag = spec[2*1]; pkOld = lastmag; dsputil_env[0] = pkOld; pkcnt = 1; for (i = 1; i < someof(size); i++) { /* step thru spectrum */ if (i < someof(size)-1) nextmag = spec[2*(i+1)]; else nextmag = FL(0.0); if (pkOld != FL(0.0)) slope = ((MYFLT) (mag - pkOld)/(pkOld * pkcnt)); else slope = -FL(10.0); /* look for peaks */ if ((mag>=lastmag)&&(mag>nextmag)&&(slope>eps)) { dsputil_env[i] = mag; pkcnt--; for (j = 1; j <= pkcnt; j++) { dsputil_env[i - pkcnt + j - 1] = pkOld*(FL(1.0) + slope * j); } pkOld = mag; pkcnt = 1; } else pkcnt++; /* not a peak */ lastmag = mag; mag = nextmag; } if (pkcnt > 1) { /* get final peak */ int posi; mag = spec[2*(size/2)]; slope = ((MYFLT) (mag - pkOld) / pkcnt); dsputil_env[size / 2] = mag; pkcnt--; for (j = 1; j <= pkcnt; j++) { posi = size / 2 - pkcnt + j - 1; if (posi > 0 && posi < size) dsputil_env[posi] = pkOld + slope * j; } } for (i = 0; i < someof(size); i++) { /* warp spectral env. */ j = (int32)((MYFLT) i * warpFactor); mag = spec[2*i]; if ((j < someof(size)) && (dsputil_env[i] != FL(0.0))) spec[2 * i] *= dsputil_env[j] / dsputil_env[i]; else spec[2*i] = FL(0.0); } } csound-6.10.0/Opcodes/dsputil.h000066400000000000000000000040441321653344700163340ustar00rootroot00000000000000/* dsputil.h: Copyright (C) 1991 Dan Ellis, Barry Vercoe, John ffitch, This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /****************************************************************/ /* dsputil.h */ /* DSP utility functions for Csound - dispfft and pvoc */ /* Header file - just declarations */ /* 20apr90 dpwe */ /****************************************************************/ #define SPTS (16) /* SINC TABLE: How many points in each lobe */ #define SPDS (6) /* (was 8) How many sinc lobes to go out */ #define SBW 0.9 /* To compensate for short sinc, reduce bandw */ /* Predeclare static supporting functions */ void Polar2Real_PVOC(CSOUND *, MYFLT *, int); void RewrapPhase(MYFLT *, int32, MYFLT *); void FrqToPhase(MYFLT *, int32, MYFLT, MYFLT, MYFLT); void FetchIn(float *, MYFLT *, int32, MYFLT); void ApplyHalfWin(MYFLT *, MYFLT *, int32); void addToCircBuf(MYFLT *, MYFLT *, int32, int32, int32); void writeClrFromCircBuf(MYFLT *, MYFLT *, int32, int32, int32); void UDSample(PVOC_GLOBALS *, MYFLT *, MYFLT, MYFLT *, int32, int32, MYFLT); void MakeSinc(PVOC_GLOBALS *); void PreWarpSpec(MYFLT *, int32, MYFLT, MYFLT *); csound-6.10.0/Opcodes/dssi4cs/000077500000000000000000000000001321653344700160515ustar00rootroot00000000000000csound-6.10.0/Opcodes/dssi4cs/src/000077500000000000000000000000001321653344700166405ustar00rootroot00000000000000csound-6.10.0/Opcodes/dssi4cs/src/dssi.h000066400000000000000000000443111321653344700177560ustar00rootroot00000000000000/* -*- c-basic-offset: 4 -*- */ /* dssi.h DSSI version 0.9 Copyright (c) 2004 Chris Cannam, Steve Harris and Sean Bolton This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #ifndef DSSI_INCLUDED #define DSSI_INCLUDED #include "ladspa.h" #include #define DSSI_VERSION "0.9" #define DSSI_VERSION_MAJOR 0 #define DSSI_VERSION_MINOR 9 #ifdef __cplusplus extern "C" { #endif /* There is a need for an API that supports hosted MIDI soft synths with GUIs in Linux audio applications. In time the GMPI initiative should comprehensively address this need, but the requirement for Linux applications to be able to support simple hosted synths is here now, and GMPI is not. This proposal (the "DSSI Soft Synth Interface" or DSSI, pronounced "dizzy") aims to provide a simple solution in a way that we hope will prove complete and compelling enough to support now, yet not so compelling as to supplant GMPI or any other comprehensive future proposal. For simplicity and familiarity, this API is based as far as possible on existing work -- the LADSPA plugin API for control values and audio processing, and the ALSA sequencer event types for MIDI event communication. The GUI part of the proposal is quite new, but may also be applicable retroactively to LADSPA plugins that do not otherwise support this synth interface. */ typedef struct _DSSI_Program_Descriptor { /** Bank number for this program. Note that DSSI does not support MIDI-style separation of bank LSB and MSB values. There is no restriction on the set of available banks: the numbers do not need to be contiguous, there does not need to be a bank 0, etc. */ unsigned long Bank; /** Program number (unique within its bank) for this program. There is no restriction on the set of available programs: the numbers do not need to be contiguous, there does not need to be a program 0, etc. */ unsigned long Program; /** Name of the program. */ const char * Name; } DSSI_Program_Descriptor; typedef struct _DSSI_Descriptor { /** * DSSI_API_Version * * This member indicates the DSSI API level used by this plugin. * If we're lucky, this will never be needed. For now all plugins * must set it to 1. */ int DSSI_API_Version; /** * LADSPA_Plugin * * A DSSI synth plugin consists of a LADSPA plugin plus an * additional framework for controlling program settings and * transmitting MIDI events. A plugin must fully implement the * LADSPA descriptor fields as well as the required LADSPA * functions including instantiate() and (de)activate(). It * should also implement run(), with the same behaviour as if * run_synth() (below) were called with no synth events. * * In order to instantiate a synth the host calls the LADSPA * instantiate function, passing in this LADSPA_Descriptor * pointer. The returned LADSPA_Handle is used as the argument * for the DSSI functions below as well as for the LADSPA ones. */ const LADSPA_Descriptor *LADSPA_Plugin; /** * configure() * * This member is a function pointer that sends a piece of * configuration data to the plugin. The key argument specifies * some aspect of the synth's configuration that is to be changed, * and the value argument specifies a new value for it. A plugin * that does not require this facility at all may set this member * to NULL. * * This call is intended to set some session-scoped aspect of a * plugin's behaviour, for example to tell the plugin to load * sample data from a particular file. The plugin should act * immediately on the request. The call should return NULL on * success, or an error string that may be shown to the user. The * host will free the returned value after use if it is non-NULL. * * Calls to configure() are not automated as timed events. * Instead, a host should remember the last value associated with * each key passed to configure() during a given session for a * given plugin instance, and should call configure() with the * correct value for each key the next time it instantiates the * "same" plugin instance, for example on reloading a project in * which the plugin was used before. Plugins should note that a * host may typically instantiate a plugin multiple times with the * same configuration values, and should share data between * instances where practical. * * Calling configure() completely invalidates the program and bank * information last obtained from the plugin. * * Reserved and special key prefixes * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * The DSSI: prefix * ---------------- * Configure keys starting with DSSI: are reserved for particular * purposes documented in the DSSI specification. At the moment, * there is one such key: DSSI:PROJECT_DIRECTORY. A host may call * configure() passing this key and a directory path value. This * indicates to the plugin and its UI that a directory at that * path exists and may be used for project-local data. Plugins * may wish to use the project directory as a fallback location * when looking for other file data, or as a base for relative * paths in other configuration values. * * The GLOBAL: prefix * ------------------ * Configure keys starting with GLOBAL: may be used by the plugin * and its UI for any purpose, but are treated specially by the * host. When one of these keys is used in a configure OSC call * from the plugin UI, the host makes the corresponding configure * call (preserving the GLOBAL: prefix) not only to the target * plugin but also to all other plugins in the same instance * group, as well as their UIs. Note that if any instance * returns non-NULL from configure to indicate error, the host * may stop there (and the set of plugins on which configure has * been called will thus depend on the host implementation). * See also the configure OSC call documentation in RFC.txt. */ char *(*configure)(LADSPA_Handle Instance, const char *Key, const char *Value); #define DSSI_RESERVED_CONFIGURE_PREFIX "DSSI:" #define DSSI_GLOBAL_CONFIGURE_PREFIX "GLOBAL:" #define DSSI_PROJECT_DIRECTORY_KEY \ DSSI_RESERVED_CONFIGURE_PREFIX "PROJECT_DIRECTORY" /** * get_program() * * This member is a function pointer that provides a description * of a program (named preset sound) available on this synth. A * plugin that does not support programs at all should set this * member to NULL. * * The Index argument is an index into the plugin's list of * programs, not a program number as represented by the Program * field of the DSSI_Program_Descriptor. (This distinction is * needed to support synths that use non-contiguous program or * bank numbers.) * * This function returns a DSSI_Program_Descriptor pointer that is * guaranteed to be valid only until the next call to get_program, * deactivate, or configure, on the same plugin instance. This * function must return NULL if passed an Index argument out of * range, so that the host can use it to query the number of * programs as well as their properties. */ const DSSI_Program_Descriptor *(*get_program)(LADSPA_Handle Instance, unsigned long Index); /** * select_program() * * This member is a function pointer that selects a new program * for this synth. The program change should take effect * immediately at the start of the next run_synth() call. (This * means that a host providing the capability of changing programs * between any two notes on a track must vary the block size so as * to place the program change at the right place. A host that * wanted to avoid this would probably just instantiate a plugin * for each program.) * * A plugin that does not support programs at all should set this * member NULL. Plugins should ignore a select_program() call * with an invalid bank or program. * * A plugin is not required to select any particular default * program on activate(): it's the host's duty to set a program * explicitly. The current program is invalidated by any call to * configure(). */ void (*select_program)(LADSPA_Handle Instance, unsigned long Bank, unsigned long Program); /** * get_midi_controller_for_port() * * This member is a function pointer that returns the MIDI * controller number or NRPN that should be mapped to the given * input control port. If the given port should not have any MIDI * controller mapped to it, the function should return DSSI_NONE. * The behaviour of this function is undefined if the given port * number does not correspond to an input control port. A plugin * that does not want MIDI controllers mapped to ports at all may * set this member NULL. * * Correct values can be got using the macros DSSI_CC(num) and * DSSI_NRPN(num) as appropriate, and values can be combined using * bitwise OR: e.g. DSSI_CC(23) | DSSI_NRPN(1069) means the port * should respond to CC #23 and NRPN #1069. * * The host is responsible for doing proper scaling from MIDI * controller and NRPN value ranges to port ranges according to * the plugin's LADSPA port hints. Hosts should not deliver * through run_synth any MIDI controller events that have already * been mapped to control port values. * * A plugin should not attempt to request mappings from * controllers 0 or 32 (MIDI Bank Select MSB and LSB). */ int (*get_midi_controller_for_port)(LADSPA_Handle Instance, unsigned long Port); /** * run_synth() * * This member is a function pointer that runs a synth for a * block. This is identical in function to the LADSPA run() * function, except that it also supplies events to the synth. * * A plugin may provide this function, run_multiple_synths() (see * below), both, or neither (if it is not in fact a synth). A * plugin that does not provide this function must set this member * to NULL. Authors of synth plugins are encouraged to provide * this function if at all possible. * * The Events pointer points to a block of EventCount ALSA * sequencer events, which is used to communicate MIDI and related * events to the synth. Each event is timestamped relative to the * start of the block, (mis)using the ALSA "tick time" field as a * frame count. The host is responsible for ensuring that events * with differing timestamps are already ordered by time. * * See also the notes on activation, port connection etc in * ladpsa.h, in the context of the LADSPA run() function. * * Note Events * ~~~~~~~~~~~ * There are two minor requirements aimed at making the plugin * writer's life as simple as possible: * * 1. A host must never send events of type SND_SEQ_EVENT_NOTE. * Notes should always be sent as separate SND_SEQ_EVENT_NOTE_ON * and NOTE_OFF events. A plugin should discard any one-point * NOTE events it sees. * * 2. A host must not attempt to switch notes off by sending * zero-velocity NOTE_ON events. It should always send true * NOTE_OFFs. It is the host's responsibility to remap events in * cases where an external MIDI source has sent it zero-velocity * NOTE_ONs. * * Bank and Program Events * ~~~~~~~~~~~~~~~~~~~~~~~ * Hosts must map MIDI Bank Select MSB and LSB (0 and 32) * controllers and MIDI Program Change events onto the banks and * programs specified by the plugin, using the DSSI select_program * call. No host should ever deliver a program change or bank * select controller to a plugin via run_synth. */ void (*run_synth)(LADSPA_Handle Instance, unsigned long SampleCount, snd_seq_event_t *Events, unsigned long EventCount); /** * run_synth_adding() * * This member is a function pointer that runs an instance of a * synth for a block, adding its outputs to the values already * present at the output ports. This is provided for symmetry * with LADSPA run_adding(), and is equally optional. A plugin * that does not provide it must set this member to NULL. */ void (*run_synth_adding)(LADSPA_Handle Instance, unsigned long SampleCount, snd_seq_event_t *Events, unsigned long EventCount); /** * run_multiple_synths() * * This member is a function pointer that runs multiple synth * instances for a block. This is very similar to run_synth(), * except that Instances, Events, and EventCounts each point to * arrays that hold the LADSPA handles, event buffers, and * event counts for each of InstanceCount instances. That is, * Instances points to an array of InstanceCount pointers to * DSSI plugin instantiations, Events points to an array of * pointers to each instantiation's respective event list, and * EventCounts points to an array containing each instantiation's * respective event count. * * A host using this function must guarantee that ALL active * instances of the plugin are represented in each call to the * function -- that is, a host may not call run_multiple_synths() * for some instances of a given plugin and then call run_synth() * as well for others. 'All .. instances of the plugin' means * every instance sharing the same LADSPA label and shared object * (*.so) file (rather than every instance sharing the same *.so). * 'Active' means any instance for which activate() has been called * but deactivate() has not. * * A plugin may provide this function, run_synths() (see above), * both, or neither (if it not in fact a synth). A plugin that * does not provide this function must set this member to NULL. * Plugin authors implementing run_multiple_synths are strongly * encouraged to implement run_synth as well if at all possible, * to aid simplistic hosts, even where it would be less efficient * to use it. */ void (*run_multiple_synths)(unsigned long InstanceCount, LADSPA_Handle *Instances, unsigned long SampleCount, snd_seq_event_t **Events, unsigned long *EventCounts); /** * run_multiple_synths_adding() * * This member is a function pointer that runs multiple synth * instances for a block, adding each synth's outputs to the * values already present at the output ports. This is provided * for symmetry with both the DSSI run_multiple_synths() and LADSPA * run_adding() functions, and is equally optional. A plugin * that does not provide it must set this member to NULL. */ void (*run_multiple_synths_adding)(unsigned long InstanceCount, LADSPA_Handle *Instances, unsigned long SampleCount, snd_seq_event_t **Events, unsigned long *EventCounts); } DSSI_Descriptor; /** * DSSI supports a plugin discovery method similar to that of LADSPA: * * - DSSI hosts may wish to locate DSSI plugin shared object files by * searching the paths contained in the DSSI_PATH and LADSPA_PATH * environment variables, if they are present. Both are expected * to be colon-separated lists of directories to be searched (in * order), and DSSI_PATH should be searched first if both variables * are set. * * - Each shared object file containing DSSI plugins must include a * function dssi_descriptor(), with the following function prototype * and C-style linkage. Hosts may enumerate the plugin types * available in the shared object file by repeatedly calling * this function with successive Index values (beginning from 0), * until a return value of NULL indicates no more plugin types are * available. Each non-NULL return is the DSSI_Descriptor * of a distinct plugin type. */ const DSSI_Descriptor *dssi_descriptor(unsigned long Index); typedef const DSSI_Descriptor *(*DSSI_Descriptor_Function)(unsigned long Index); /* * Macros to specify particular MIDI controllers in return values from * get_midi_controller_for_port() */ #define DSSI_CC_BITS 0x20000000 #define DSSI_NRPN_BITS 0x40000000 #define DSSI_NONE -1 #define DSSI_CONTROLLER_IS_SET(n) (DSSI_NONE != (n)) #define DSSI_CC(n) (DSSI_CC_BITS | (n)) #define DSSI_IS_CC(n) (DSSI_CC_BITS & (n)) #define DSSI_CC_NUMBER(n) ((n) & 0x7f) #define DSSI_NRPN(n) (DSSI_NRPN_BITS | ((n) << 7)) #define DSSI_IS_NRPN(n) (DSSI_NRPN_BITS & (n)) #define DSSI_NRPN_NUMBER(n) (((n) >> 7) & 0x3fff) #ifdef __cplusplus } #endif #endif /* DSSI_INCLUDED */ csound-6.10.0/Opcodes/dssi4cs/src/dssi4cs.c000066400000000000000000001223741321653344700203710ustar00rootroot00000000000000/* * Copyright (C) 2005 Andres Cabrera * * The dssi4cs library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * The dssi4cs library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with The dssi4cs library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA * * Uses code by Richard W.E. Furse from the ladspa sdk */ #include "utils.h" #include "dssi4cs.h" #include #include #undef CS_KSMPS #define CS_KSMPS (csound->GetKsmps(csound)) //#define DEBUG 1 #define DSSI4CS_MAX_NUM_EVENTS 128 #if !defined(HAVE_STRLCAT) && !defined(strlcat) size_t strlcat(char *dst, const char *src, size_t siz) { char *d = dst; const char *s = src; size_t n = siz; size_t dlen; /* Find the end of dst and adjust bytes left but don't go past end */ while (n-- != 0 && *d != '\0') d++; dlen = d - dst; n = siz - dlen; if (n == 0) return (dlen + strlen(s)); while (*s != '\0') { if (n != 1) { *d++ = *s; n--; } s++; } *d = '\0'; return (dlen + (s - src)); /* count does not include NUL */ } #endif /* TODO accomodate plugins which return control outputs */ /**************************************************************************** dssiinit *****************************************************************************/ void info(CSOUND * csound, DSSI4CS_PLUGIN * DSSIPlugin_) { int Ksmps = csound->GetKsmps(csound); unsigned long PortCount = 0; LADSPA_Descriptor *Descriptor; uint32 i; if (DSSIPlugin_->Type == LADSPA) Descriptor = (LADSPA_Descriptor *) DSSIPlugin_->Descriptor; else Descriptor = (LADSPA_Descriptor *) DSSIPlugin_->DSSIDescriptor->LADSPA_Plugin; PortCount = Descriptor->PortCount; csound->Message(csound, "============Plugin %i" "========================================\n", DSSIPlugin_->PluginNumber); csound->Message(csound, "Plugin Type: %s\n", ((DSSIPlugin_->Type == LADSPA) ? "LADSPA" : "DSSI")); csound->Message(csound, "Plugin UniqueID: %lu\n", Descriptor->UniqueID); csound->Message(csound, "Label: %s\n", Descriptor->Label); csound->Message(csound, "Name: %s\n", Descriptor->Name); csound->Message(csound, "Maker: %s\n", Descriptor->Maker); csound->Message(csound, "Copyright: %s\n", Descriptor->Copyright); csound->Message(csound, "Number of Ports: %lu\n", PortCount); for (i = 0; i < PortCount; i++) { csound->Message(csound, " Port #%u: %s %s: %s - Range: ", i, (LADSPA_IS_PORT_CONTROL(Descriptor->PortDescriptors[i]) ? "Control" : "Audio"), (LADSPA_IS_PORT_INPUT(Descriptor->PortDescriptors[i]) ? "Input" : "Output"), Descriptor->PortNames[i]); if (LADSPA_IS_HINT_TOGGLED(Descriptor->PortRangeHints[i].HintDescriptor)) csound->Message(csound, "Toggle.\n"); else { if (LADSPA_IS_HINT_BOUNDED_BELOW (Descriptor->PortRangeHints[i].HintDescriptor)) csound->Message(csound, "%f", (Descriptor->PortRangeHints[i].LowerBound) * (LADSPA_IS_HINT_SAMPLE_RATE (Descriptor->PortRangeHints[i]. HintDescriptor) ? Ksmps : 1)); else csound->Message(csound, "-Inf"); if (LADSPA_IS_HINT_BOUNDED_ABOVE (Descriptor->PortRangeHints[i].HintDescriptor)) csound->Message(csound, " -> %f\n", Descriptor->PortRangeHints[i].UpperBound * (LADSPA_IS_HINT_SAMPLE_RATE (Descriptor->PortRangeHints[i]. HintDescriptor) ? Ksmps : 1)); else csound->Message(csound, " -> +Inf\n"); if (DSSIPlugin_->Type == DSSI) if ((LADSPA_IS_PORT_CONTROL(Descriptor->PortDescriptors[i])) && (LADSPA_IS_PORT_INPUT(Descriptor->PortDescriptors[i]))) csound->Message(csound, " MIDI cc: %i\n", DSSIPlugin_->DSSIDescriptor-> get_midi_controller_for_port(DSSIPlugin_->Handle, i)); } } csound->Message(csound, "Must run in realtime: %s\n", (LADSPA_IS_REALTIME(Descriptor->Properties) ? "YES" : "NO")); csound->Message(csound, "Is hard realtime capable: %s\n", (LADSPA_IS_HARD_RT_CAPABLE(Descriptor->Properties) ? "YES" : "NO")); csound->Message(csound, "Has activate() function: %s\n", ((Descriptor->activate) ? "YES" : "NO")); csound->Message(csound, "==============================" "===============================\n"); } DSSI4CS_PLUGIN *LocatePlugin(int PluginNumber, CSOUND * csound) { DSSI4CS_PLUGIN *DSSIPlugin_; DSSI4CS_PLUGIN *DSSIPlugin = (DSSI4CS_PLUGIN *) csound->QueryGlobalVariable(csound, "$DSSI4CS"); if (!DSSIPlugin) return NULL; DSSIPlugin_ = DSSIPlugin; if (UNLIKELY(PluginNumber > *DSSIPlugin->PluginCount)) { #ifdef DEBUG csound->Message(csound, "DSSI4CS: PluginNumber > *DSSIPlugin->PluginCount.\n"); #endif return NULL; } while (DSSIPlugin_->PluginNumber != PluginNumber) { #ifdef DEBUG csound->Message(csound, "DSSI4CS: Scanning plugin: %i.\n", DSSIPlugin_->PluginNumber); #endif if (UNLIKELY(!DSSIPlugin_->NextPlugin)) { return NULL; } DSSIPlugin_ = DSSIPlugin_->NextPlugin; } #ifdef DEBUG csound->Message(csound, "DSSI4CS: Plugin %i Located.\n", DSSIPlugin_->PluginNumber); #endif return DSSIPlugin_; } static int dssideinit(CSOUND * csound, DSSI4CS_PLUGIN * DSSIPlugin) { int i; for (i = 0; DSSIPlugin != NULL; i++) { DSSI4CS_PLUGIN *nxt = (DSSI4CS_PLUGIN *) DSSIPlugin->NextPlugin; if (DSSIPlugin->Descriptor) { if (DSSIPlugin->Type == LADSPA) { if (DSSIPlugin->Descriptor->deactivate != NULL) DSSIPlugin->Descriptor->deactivate(DSSIPlugin->Handle); if (DSSIPlugin->Descriptor->cleanup != NULL) DSSIPlugin->Descriptor->cleanup(DSSIPlugin->Handle); } else { if (DSSIPlugin->DSSIDescriptor->LADSPA_Plugin->deactivate != NULL) DSSIPlugin->DSSIDescriptor->LADSPA_Plugin-> deactivate(DSSIPlugin->Handle); if (DSSIPlugin->DSSIDescriptor->LADSPA_Plugin->cleanup != NULL) DSSIPlugin->DSSIDescriptor->LADSPA_Plugin->cleanup(DSSIPlugin->Handle); } } else csound->Message(csound, "missing descriptor\n"); if (i != 0) csound->Free(csound, DSSIPlugin); DSSIPlugin = nxt; } csound->DestroyGlobalVariable(csound, "$DSSI4CS"); #ifdef DEBUG csound->Message(csound, "DSSI4CS: Deinit OK.\n"); #endif return OK; } int dssiinit(CSOUND * csound, DSSIINIT * p) { /* TODO check if plugin has already been loaded and use same function */ csound = p->h.insdshead->csound; int SampleRate = (int) MYFLT2LRND(csound->GetSr(csound)); int Ksmps = csound->GetKsmps(csound); unsigned long i; int verbose = (int)*p->iverbose; LADSPA_Descriptor_Function pfDescriptorFunction; DSSI_Descriptor_Function pfDSSIDescriptorFunction; LADSPA_Descriptor *LDescriptor; char dssiFilename[MAXNAME]; unsigned long PluginIndex; void *PluginLibrary; unsigned long PortCount = 0; unsigned long ConnectedControlPorts = 0; unsigned long ConnectedAudioPorts = 0; LADSPA_PortDescriptor PortDescriptor; DSSI4CS_PLUGIN *DSSIPlugin_; DSSI4CS_PLUGIN *DSSIPlugin = (DSSI4CS_PLUGIN *) csound->QueryGlobalVariable(csound, "$DSSI4CS"); CS_TYPE* argType = csound->GetTypeForArg(p->iplugin); if (strcmp("S", argType->varTypeName) == 0) strncpy(dssiFilename,((STRINGDAT *)p->iplugin)->data, MAXNAME-1); else csound->strarg2name(csound, dssiFilename, csound->ISSTRCOD(*p->iplugin) ? csound->GetString(csound, *p->iplugin) : (char *) p->iplugin, "dssiinit.", (int) csound->ISSTRCOD(*p->iplugin)); PluginIndex = (unsigned long) *p->iindex; PluginLibrary = dlopenLADSPA(csound, dssiFilename, RTLD_NOW); if (UNLIKELY(!PluginLibrary)) return csound->InitError(csound, Str("DSSI4CS: Failed to load %s."), dssiFilename); if (!DSSIPlugin) { if (UNLIKELY(csound->CreateGlobalVariable(csound, "$DSSI4CS", sizeof(DSSI4CS_PLUGIN))) != 0) csound->Die(csound, Str("Error creating global variable '$DSSI4CS'")); DSSIPlugin = (DSSI4CS_PLUGIN *) csound->QueryGlobalVariable(csound, "$DSSI4CS"); csound->RegisterResetCallback(csound, DSSIPlugin, (int (*)(CSOUND*, void*)) dssideinit); DSSIPlugin->PluginNumber = 0; DSSIPlugin->PluginCount = (int *) csound->Malloc(csound, sizeof(int)); *DSSIPlugin->PluginCount = 1; DSSIPlugin_ = DSSIPlugin; if (verbose != 0) { csound->Message(csound, Str("DSSI4CS: Loading first instance.\n")); } } else { DSSIPlugin_ = LocatePlugin(*DSSIPlugin->PluginCount - 1, csound); if (verbose != 0) { csound->Message(csound, "DSSI4CS: Located plugin: %i.\n", DSSIPlugin_->PluginNumber); } DSSIPlugin_->NextPlugin = (DSSI4CS_PLUGIN *) csound->Malloc(csound, sizeof(DSSI4CS_PLUGIN)); DSSIPlugin_ = DSSIPlugin_->NextPlugin; DSSIPlugin_->PluginNumber = *DSSIPlugin->PluginCount; DSSIPlugin_->PluginCount = DSSIPlugin->PluginCount; *DSSIPlugin_->PluginCount = (*DSSIPlugin_->PluginCount) + 1; } *p->iDSSIHandle = DSSIPlugin_->PluginNumber; if (verbose != 0) { csound->Message(csound, "DSSI4CS: About to load descriptor function " "for plugin %i of %i.\n", DSSIPlugin_->PluginNumber, *DSSIPlugin_->PluginCount); } pfDSSIDescriptorFunction = (DSSI_Descriptor_Function) dlsym(PluginLibrary, "dssi_descriptor"); if (pfDSSIDescriptorFunction) { DSSIPlugin_->DSSIDescriptor = (DSSI_Descriptor *) csound->Calloc(csound, sizeof(DSSI_Descriptor)); DSSIPlugin_->DSSIDescriptor = (DSSI_Descriptor *) pfDSSIDescriptorFunction(PluginIndex); LDescriptor = (LADSPA_Descriptor *) DSSIPlugin_->DSSIDescriptor->LADSPA_Plugin; DSSIPlugin_->Type = DSSI; if (verbose != 0) { csound->Message(csound, "DSSI4CS: DSSI Plugin detected.\n"); } } else { pfDescriptorFunction = (LADSPA_Descriptor_Function) dlsym(PluginLibrary, "ladspa_descriptor"); if (pfDescriptorFunction==NULL) { dlclose(PluginLibrary); return csound->InitError(csound, Str("No ladspa descriptor\n")); } DSSIPlugin_->Descriptor = (LADSPA_Descriptor *) csound->Calloc(csound, sizeof(LADSPA_Descriptor)); /* DSSIPlugin_->Descriptor = */ /* (LADSPA_Descriptor *) pfDescriptorFunction(PluginIndex); */ LDescriptor = (LADSPA_Descriptor *) DSSIPlugin_->Descriptor; memcpy(LDescriptor, pfDescriptorFunction(PluginIndex), sizeof(LADSPA_Descriptor)); DSSIPlugin_->Type = LADSPA; if (verbose != 0) { csound->Message(csound, "DSSI4CS: LADSPA Plugin Detected\n"); } } if (UNLIKELY((!DSSIPlugin_->Descriptor) && (!DSSIPlugin_->DSSIDescriptor))) { const char *pcError = dlerror(); /* TODO: cleanup if error */ /* csound->Free(csound, DSSIPlugin_->Descriptor); */ if (pcError) csound->InitError(csound, Str("DSSI4CS: Unable to find " "ladspa_descriptor(%lu) function or\n" "dssi_descriptor(%lu) function in plugin " "file \"%s\": %s.\n" "Are you sure this is a LADSPA or " "DSSI plugin file ?"), PluginIndex, PluginIndex, dssiFilename, pcError); else csound->InitError(csound, Str("DSSI4CS: Unable to find " "ladspa_descriptor(%lu) function or\n" "dssi_descriptor(%lu) function in plugin " "file \"%s\".\n" "Are you sure this is a LADSPA or " "DSSI plugin file ?"), PluginIndex, PluginIndex, dssiFilename); dlclose(PluginLibrary); return NOTOK; } if (UNLIKELY(!LDescriptor)) { csound->InitError(csound, Str("DSSI4CS: No plugin index %lu in %s"), PluginIndex, dssiFilename); dlclose(PluginLibrary); return NOTOK; } if (verbose != 0) { csound->Message(csound, "DSSI4CS: About to instantiate plugin.\n"); } if (DSSIPlugin_->Type == LADSPA) { if (UNLIKELY(! (DSSIPlugin_->Handle = (LADSPA_Handle) DSSIPlugin_->Descriptor->instantiate(DSSIPlugin_-> Descriptor, SampleRate)))){ csound->InitError(csound, Str("DSSI4CS: Could not instantiate plugin: %s"), dssiFilename); dlclose(PluginLibrary); return NOTOK; } if (UNLIKELY(!DSSIPlugin_->Descriptor->run)) { return csound->InitError(csound, Str("DSSI4CS: No run() funtion in: %s"), LDescriptor->Name); } PortCount = DSSIPlugin_->Descriptor->PortCount; //dlclose(PluginLibrary); //return NOTOK; } else { if (UNLIKELY(! (DSSIPlugin_->Handle = (LADSPA_Handle) DSSIPlugin_->DSSIDescriptor->LADSPA_Plugin-> instantiate(DSSIPlugin_->DSSIDescriptor->LADSPA_Plugin, SampleRate)))) { unloadLADSPAPluginLibrary(csound, PluginLibrary); return csound->InitError(csound, Str("DSSI4CS: Could not instantiate plugin: %s"), dssiFilename); } if (UNLIKELY(!DSSIPlugin_->DSSIDescriptor->LADSPA_Plugin->run)) { unloadLADSPAPluginLibrary(csound, PluginLibrary); return csound->InitError(csound, Str("DSSI4CS: No run() funtion in: %s"), LDescriptor->Name); } PortCount = DSSIPlugin_->DSSIDescriptor->LADSPA_Plugin->PortCount; DSSIPlugin_->Events = (snd_seq_event_t *) csound->Calloc(csound, DSSI4CS_MAX_NUM_EVENTS * sizeof(snd_seq_event_t)); } if (verbose != 0) { if (DSSIPlugin_->Handle) csound->Message(csound, "DSSI4CS: Plugin instantiated.\n"); else csound->Message(csound, "DSSI4CS: Problem instantiating.\n"); } for (i = 0; i < PortCount; i++) { PortDescriptor = (DSSIPlugin_->Type == LADSPA ? DSSIPlugin_->Descriptor->PortDescriptors[i] : DSSIPlugin_->DSSIDescriptor->LADSPA_Plugin->PortDescriptors[i]); if (LADSPA_IS_PORT_CONTROL(PortDescriptor)) ConnectedControlPorts++; if (LADSPA_IS_PORT_AUDIO(PortDescriptor)) ConnectedAudioPorts++; } if (verbose != 0) { csound->Message(csound, "DSSI4CS: Found %lu control ports for: '%s'\n", ConnectedControlPorts, LDescriptor->Name); csound->Message(csound, "DSSI4CS: Found %lu audio ports for: '%s'\n", ConnectedAudioPorts, LDescriptor->Name); } DSSIPlugin_->control = (LADSPA_Data **) csound->Calloc(csound, ConnectedControlPorts * sizeof(LADSPA_Data *)); DSSIPlugin_->audio = (LADSPA_Data **) csound->Calloc(csound, ConnectedAudioPorts * sizeof(LADSPA_Data *)); // if (verbose != 0) { csound->Message(csound, "DSSI4CS: Created port array.\n"); // } ConnectedControlPorts = 0; ConnectedAudioPorts = 0; for (i = 0; i < PortCount; i++) { PortDescriptor = (DSSIPlugin_->Type == LADSPA ? DSSIPlugin_->Descriptor->PortDescriptors[i] : DSSIPlugin_->DSSIDescriptor->LADSPA_Plugin->PortDescriptors[i]); if (verbose != 0) { csound->Message(csound, "DSSI4CS: Queried port descriptor.\n"); } if (LADSPA_IS_PORT_CONTROL(PortDescriptor)) { DSSIPlugin_->control[ConnectedControlPorts] = (LADSPA_Data *) csound->Calloc(csound, sizeof(LADSPA_Data)); if (DSSIPlugin_->Type == LADSPA) { DSSIPlugin_->Descriptor->connect_port(DSSIPlugin_->Handle, i, (LADSPA_Data *) DSSIPlugin_-> control[ConnectedControlPorts]); } else { DSSIPlugin_->DSSIDescriptor->LADSPA_Plugin->connect_port( DSSIPlugin_->Handle, i, (LADSPA_Data *) DSSIPlugin_->control[ConnectedControlPorts]); } if (verbose != 0) { csound->Message(csound, "DSSI4CS: Created internal control port " "%lu for Port %lu.\n", ConnectedControlPorts, i); } ConnectedControlPorts++; } if (LADSPA_IS_PORT_AUDIO(PortDescriptor)) { DSSIPlugin_->audio[ConnectedAudioPorts] = (LADSPA_Data *) csound->Calloc(csound, Ksmps * sizeof(LADSPA_Data)); if (DSSIPlugin_->Type == LADSPA) DSSIPlugin_->Descriptor->connect_port(DSSIPlugin_->Handle, i, (LADSPA_Data *) DSSIPlugin_-> audio[ConnectedAudioPorts]); else DSSIPlugin_->DSSIDescriptor->LADSPA_Plugin->connect_port( DSSIPlugin_->Handle, i, (LADSPA_Data *) DSSIPlugin_->audio[ConnectedAudioPorts]); if (verbose != 0) { csound->Message(csound, "DSSI4CS: Created internal audio port" " %lu for Port %lu.\n", ConnectedAudioPorts, i); } ConnectedAudioPorts++; } } /* All ports must be connected before calling run() */ if (verbose != 0) { csound->Message(csound, "DSSI4CS: Created %lu control ports for: '%s'\n", ConnectedControlPorts, LDescriptor->Name); csound->Message(csound, "DSSI4CS: Created %lu audio ports for: '%s'\n", ConnectedAudioPorts, LDescriptor->Name); } DSSIPlugin_->Active = 0; DSSIPlugin_->EventCount = 0; if (verbose != 0) { csound->Message(csound, "DSSI4CS: Init Done.\n"); info(csound, DSSIPlugin_); } //dlclose(PluginLibrary); return OK; } /**************************************************************************** dssiactivate *****************************************************************************/ int ActivatePlugin(CSOUND * csound, DSSI4CS_PLUGIN * DSSIPlugin_, int ktrigger) { const LADSPA_Descriptor *Descriptor; if (!DSSIPlugin_) return -100; if (DSSIPlugin_->Type == LADSPA) Descriptor = (LADSPA_Descriptor *) DSSIPlugin_->Descriptor; else Descriptor = (LADSPA_Descriptor *) DSSIPlugin_->DSSIDescriptor->LADSPA_Plugin; if (Descriptor->activate != NULL) { if ((ktrigger == 1) && (DSSIPlugin_->Active == 0)) { Descriptor->activate(DSSIPlugin_->Handle); DSSIPlugin_->Active = 1; return 1; } if ((ktrigger == 0) && (DSSIPlugin_->Active == 1)) { DSSIPlugin_->Active = 0; if (Descriptor->deactivate != NULL) { Descriptor->deactivate(DSSIPlugin_->Handle); return 0; } return -2; } return 100; } else { if ((ktrigger == 1) && (DSSIPlugin_->Active == 0)) { DSSIPlugin_->Active = 1; return -1; } if ((ktrigger == 0) && (DSSIPlugin_->Active == 1)) { DSSIPlugin_->Active = 0; return -2; } } return -200; } int dssiactivate_init(CSOUND * csound, DSSIACTIVATE * p) { int Number = *p->iDSSIhandle; #ifdef DEBUG csound->Message(csound, "DSSI4CS: activate-Locating plugin %i\n", Number); #endif p->DSSIPlugin_ = LocatePlugin(Number, csound); p->printflag = -999; if (UNLIKELY((!p->DSSIPlugin_) || (Number > *p->DSSIPlugin_->PluginCount) || (!p->DSSIPlugin_->Handle))) return csound->InitError(csound, Str("DSSI4CS: Invalid plugin: %i (MAX= %i)."), Number, *p->DSSIPlugin_->PluginCount); #ifdef DEBUG csound->Message(csound, "DSSI4CS: activate-Finished locating plugin %i\n", p->DSSIPlugin_->PluginNumber); #endif return OK; } int dssiactivate(CSOUND * csound, DSSIACTIVATE * p) { LADSPA_Descriptor *Descriptor; if (p->DSSIPlugin_->Type == LADSPA) Descriptor = (LADSPA_Descriptor *) p->DSSIPlugin_->Descriptor; else Descriptor = (LADSPA_Descriptor *) p->DSSIPlugin_->DSSIDescriptor->LADSPA_Plugin; int val = ActivatePlugin(csound, p->DSSIPlugin_, *p->ktrigger); switch (val) { case -1: { if (p->printflag != -1) { csound->Message(csound, "DSSI4CS: '%s' activated (No activate function).\n", Descriptor->Name); p->printflag = -1; } } break; case 0: { if (p->printflag != 0) { csound->Message(csound, "DSSI4CS: Deactivate function called for: %s\n", Descriptor->Name); p->printflag = 0; } } break; case 1: { if (p->printflag != 1) { csound->Message(csound, "DSSI4CS: Activate function called for: %s\n", Descriptor->Name); p->printflag = 1; } } break; case -2: { if (p->printflag != -2) { csound->Message(csound, "DSSI4CS: '%s' deactivated " "(No deactivate function).\n", Descriptor->Name); p->printflag = -2; } } break; case -100: { if (p->printflag != -100) return csound->PerfError(csound, p->h.insdshead, "DSSI4CS: dssiactivate " "not properly initialised."); p->printflag = -100; } break; default: break; } return OK; } /**************************************************************************** dssiaudio *****************************************************************************/ int dssiaudio_init(CSOUND * csound, DSSIAUDIO * p) { /* TODO not realtime safe, try to make it so. */ int Number = *p->iDSSIhandle; int icnt = csound->GetInputArgCnt(p) - 1; int ocnt = csound->GetOutputArgCnt(p); if (UNLIKELY(icnt > DSSI4CS_MAX_IN_CHANNELS)) csound->Die(csound, Str("DSSI4CS: number of audio input channels " "is greater than %d"), DSSI4CS_MAX_IN_CHANNELS); if (UNLIKELY(ocnt > DSSI4CS_MAX_OUT_CHANNELS)) csound->Die(csound, Str("DSSI4CS: number of audio output channels " "is greater than %d"), DSSI4CS_MAX_OUT_CHANNELS); #ifdef DEBUG csound->Message(csound, "DSSI4CS: dssiaudio- %i input args, %i output args.\n", csound->GetInputArgCnt(p), csound->GetOutputArgCnt(p)); csound->Message(csound, "DSSI4CS: dssiaudio LocatePlugin # %i\n", Number); #endif p->DSSIPlugin_ = LocatePlugin(Number, csound); if (!p->DSSIPlugin_) return csound->InitError(csound, Str("DSSI4CS: dssiaudio: Invalid plugin handle.")); const LADSPA_Descriptor *Descriptor; if (p->DSSIPlugin_->Type == LADSPA) Descriptor = (LADSPA_Descriptor *) p->DSSIPlugin_->Descriptor; else Descriptor = (LADSPA_Descriptor *) p->DSSIPlugin_->DSSIDescriptor->LADSPA_Plugin; unsigned long PortIndex = 0; int ConnectedInputPorts = 0; int ConnectedOutputPorts = 0; int ConnectedPorts = 0; LADSPA_PortDescriptor PortDescriptor = 0; for (PortIndex = 0; PortIndex < Descriptor->PortCount; PortIndex++) { PortDescriptor = Descriptor->PortDescriptors[PortIndex]; if (LADSPA_IS_PORT_INPUT(PortDescriptor) && LADSPA_IS_PORT_AUDIO(PortDescriptor)) ConnectedInputPorts++; else if (LADSPA_IS_PORT_OUTPUT(PortDescriptor) && LADSPA_IS_PORT_AUDIO(PortDescriptor)) ConnectedOutputPorts++; } p->InputPorts = (unsigned long *) csound->Calloc(csound, ConnectedInputPorts * sizeof(unsigned long)); p->OutputPorts = (unsigned long *) csound->Calloc(csound, ConnectedOutputPorts * sizeof(unsigned long)); ConnectedInputPorts = 0; ConnectedOutputPorts = 0; ConnectedPorts = 0; for (PortIndex = 0; PortIndex < Descriptor->PortCount; PortIndex++) { PortDescriptor = Descriptor->PortDescriptors[PortIndex]; if (LADSPA_IS_PORT_INPUT(PortDescriptor) && LADSPA_IS_PORT_AUDIO(PortDescriptor)) { p->InputPorts[ConnectedInputPorts] = ConnectedPorts; #ifdef DEBUG csound->Message(csound, "DSSI4CS: Connected Audio port: " "%lu to Input port : %li\n", p->InputPorts[ConnectedInputPorts], PortIndex); #endif ConnectedInputPorts++; ConnectedPorts++; } else if (LADSPA_IS_PORT_OUTPUT(PortDescriptor) && LADSPA_IS_PORT_AUDIO(PortDescriptor)) { p->OutputPorts[ConnectedOutputPorts] = ConnectedPorts; #ifdef DEBUG csound->Message(csound, "DSSI4CS: Connected Audio Port: " "%lu to Output port: %li\n", p->OutputPorts[ConnectedOutputPorts], PortIndex); #endif ConnectedOutputPorts++; ConnectedPorts++; } } #ifdef DEBUG csound->Message(csound, "DSSI4CS: Connected %i audio input ports for: '%s'\n", ConnectedInputPorts, Descriptor->Name); csound->Message(csound, "DSSI4CS: Connected %i audio output ports for: '%s'\n", ConnectedOutputPorts, Descriptor->Name); #endif p->NumInputPorts = ConnectedInputPorts; p->NumOutputPorts = ConnectedOutputPorts; if ((p->NumInputPorts) < icnt) { if (p->NumInputPorts == 0) csound->Message(csound, Str("DSSI4CS: Plugin '%s' has %i audio input ports " "audio input discarded.\n"), Descriptor->Name, p->NumInputPorts); else return csound->InitError(csound, Str("DSSI4CS: Plugin '%s' " "has %i audio input ports."), Descriptor->Name, p->NumOutputPorts); } if (p->NumOutputPorts < ocnt) return csound->InitError(csound, Str("DSSI4CS: Plugin '%s' " "has %i audio output ports."), Descriptor->Name, p->NumOutputPorts); return OK; } int dssiaudio(CSOUND * csound, DSSIAUDIO * p) { const LADSPA_Descriptor *Descriptor; if (p->DSSIPlugin_->Type == LADSPA) Descriptor = (LADSPA_Descriptor *) p->DSSIPlugin_->Descriptor; else Descriptor = (LADSPA_Descriptor *) p->DSSIPlugin_->DSSIDescriptor->LADSPA_Plugin; unsigned int i, j; unsigned int icnt = csound->GetInputArgCnt(p) - 1; unsigned int ocnt = csound->GetOutputArgCnt(p); unsigned long Ksmps = (unsigned long) csound->GetKsmps(csound); if (p->DSSIPlugin_->Active == 1) { for (j = 0; j < icnt; j++) { for (i = 0; i < Ksmps; i++) { p->DSSIPlugin_->audio[p->InputPorts[j]][i] = p->ain[j][i] * (1.0/csound->Get0dBFS(csound)); } } Descriptor->run(p->DSSIPlugin_->Handle, Ksmps); for (j = 0; j < ocnt; j++) { for (i = 0; i < Ksmps; i++) p->aout[j][i] = p->DSSIPlugin_->audio[p->OutputPorts[j]][i] * csound->Get0dBFS(csound); } } else { for (j = 0; j < ocnt; j++) for (i = 0; i < Ksmps; i++) p->aout[j][i] = FL(0.0); } return OK; } /**************************************************************************** dssictls *****************************************************************************/ int dssictls_kk(CSOUND * csound, DSSICTLS * p) { LADSPA_Data Value = *p->val; if (!p->DSSIPlugin_) { return csound->PerfError(csound, p->h.insdshead, Str("DSSI4CS: Invalid plugin handle.")); } if (*p->ktrig == 1) { *p->DSSIPlugin_->control[p->PortNumber] = Value * (p->HintSampleRate); } return OK; } int dssictls_ak(CSOUND * csound, DSSICTLS * p) { csound->PerfError(csound, p->h.insdshead, Str("DSSI4CS: Audio Rate control " "ports not implemented yet.")); return NOTOK; } int dssictls_init(CSOUND * csound, DSSICTLS * p) { /* TODO warning possible crash or unpredictable behaviour if invalid port. Crash if audio port selected */ const LADSPA_Descriptor *Descriptor; int Number = *p->iDSSIhandle; int Sr = (int) MYFLT2LRND(csound->GetSr(csound)); unsigned long PortIndex = *p->iport; unsigned int i; unsigned long ControlPort = 0; unsigned long AudioPort = 0; unsigned long Port = 0; p->DSSIPlugin_ = LocatePlugin(Number, csound); if (!p->DSSIPlugin_) { return csound->InitError(csound, "DSSI4CS: Invalid plugin handle."); } if (p->DSSIPlugin_->Type == LADSPA) { Descriptor = p->DSSIPlugin_->Descriptor; } else { Descriptor = p->DSSIPlugin_->DSSIDescriptor->LADSPA_Plugin; } if (PortIndex >= Descriptor->PortCount) { return csound->InitError(csound, Str("DSSI4CS: Port %lu from '%s' does not exist."), PortIndex, Descriptor->Name); } p->HintSampleRate = (LADSPA_IS_HINT_SAMPLE_RATE (Descriptor->PortRangeHints[PortIndex].HintDescriptor) ? Sr : 1); #ifdef DEBUG csound->Message(csound, "DSSI4CS: Port %lu multiplier (HintSampleRate): %i.\n", PortIndex, p->HintSampleRate); #endif LADSPA_PortDescriptor PortDescriptor = Descriptor->PortDescriptors[PortIndex]; if (LADSPA_IS_PORT_OUTPUT(PortDescriptor)) return csound->InitError(csound, Str("DSSI4CS: Port %lu from '%s' is an " "output port."), PortIndex, Descriptor->Name); for (i = 0; i < PortIndex; i++) { PortDescriptor = Descriptor->PortDescriptors[i]; if (LADSPA_IS_PORT_CONTROL(PortDescriptor)) { ControlPort++; Port = ControlPort; } if (LADSPA_IS_PORT_AUDIO(PortDescriptor)) { AudioPort++; Port = AudioPort; } } p->PortNumber = Port; #ifdef DEBUG csound->Message(csound, "DSSI4CS: Port %lu using internal port %lu.\n", PortIndex, p->PortNumber); /*csound->Message(csound, "DSSI4CS: ArgMask: %lu.\n",*/ /* csound->GetInputArgAMask(p));*/ #endif // if ((int) csound->GetInputArgAMask(p) & 4) { // p->h.opadr = (SUBR) dssictls_ak; /* "iiak" */ // } // else { // p->h.opadr = (SUBR) dssictls_kk; /* "iikk" */ // } return OK; } int dssictls_dummy(CSOUND * csound, DSSICTLS * p) { csound->PerfError(csound, p->h.insdshead, Str("DSSI4CS: Not initialised or wrong argument types.")); return NOTOK; } /**************************************************************************** dssisynth *****************************************************************************/ int dssisynth_init(CSOUND * csound, DSSISYNTH * p) { /* TODO docs: dssisynth only for DSSI plugs */ return csound->InitError(csound, "DSSI4CS: dssisynth not implemented yet."); } int dssisynth(CSOUND * csound, DSSISYNTH * p) { return OK; } /**************************************************************************** dssinotes *****************************************************************************/ int dssinote_init(CSOUND * csound, DSSINOTE * p) { return csound->InitError(csound, Str("DSSI4CS: dssinote not implemented yet.")); } int dssinote(CSOUND * csound, DSSINOTE * p) { return OK; } int dssievent_init(CSOUND * csound, DSSINOTEON * p) { return csound->InitError(csound, Str("DSSI4CS: dssievent not implemented yet.")); } int dssievent(CSOUND * csound, DSSINOTEON * p) { return OK; } /**************************************************************************** dssilist *****************************************************************************/ static void LADSPADirectoryPluginSearch (CSOUND * csound, const char * pcDirectory, LADSPAPluginSearchCallbackFunction fCallbackFunction) { char *pcFilename; DIR *psDirectory; LADSPA_Descriptor_Function fDescriptorFunction; long lDirLength; long slen; long iNeedSlash; struct dirent *psDirectoryEntry; void *pvPluginHandle; lDirLength = strlen(pcDirectory); if (!lDirLength) return; if (pcDirectory[lDirLength - 1] == '/') iNeedSlash = 0; else iNeedSlash = 1; psDirectory = opendir(pcDirectory); if (!psDirectory) return; while (1) { psDirectoryEntry = readdir(psDirectory); if (!psDirectoryEntry) { closedir(psDirectory); //if (pvPluginHandle) closedir(pvPluginHandle); return; } pcFilename = csound->Malloc(csound, slen = (lDirLength + strlen(psDirectoryEntry->d_name) + 2)); strncpy(pcFilename, pcDirectory, slen); /*pcFilename[slen-1] = '\0';*/ if (iNeedSlash) strlcat(pcFilename, "/",slen); strlcat(pcFilename, psDirectoryEntry->d_name, slen); pvPluginHandle = dlopen(pcFilename, RTLD_LAZY); if (pvPluginHandle) { /* This is a file and the file is a shared library! */ dlerror(); fDescriptorFunction = (LADSPA_Descriptor_Function) dlsym(pvPluginHandle, "ladspa_descriptor"); if (dlerror() == NULL && fDescriptorFunction) { /* We've successfully found a ladspa_descriptor function. Pass it to the callback function. */ fCallbackFunction(csound, pcFilename, pvPluginHandle, fDescriptorFunction); } else { /* It was a library, but not a LADSPA one. Unload it. */ dlclose(pvPluginHandle); pvPluginHandle = NULL; //csound->Free(csound, pcFilename); } csound->Free(csound, pcFilename); } } } void LADSPAPluginSearch(CSOUND *csound, LADSPAPluginSearchCallbackFunction fCallbackFunction) { char *pcBuffer; const char *pcEnd; char *pcLADSPAPath; const char *pcDSSIPath; const char *pcStart; pcLADSPAPath = getenv("LADSPA_PATH"); pcDSSIPath = getenv("DSSI_PATH"); if (!pcLADSPAPath) { csound->Message(csound, Str("DSSI4CS: LADSPA_PATH environment variable not set.\n")); #ifdef LIB64 pcLADSPAPath = "/usr/lib64/ladspa/"; #else pcLADSPAPath = "/usr/lib/ladspa/"; #endif } if (!pcDSSIPath) { csound->Message(csound, Str("DSSI4CS: DSSI_PATH environment variable not set.\n")); pcStart = pcLADSPAPath; } else { int len = strlen(pcLADSPAPath)+strlen(pcDSSIPath)+2; char *tmp = (char*)malloc(len); snprintf(tmp, len, "%s:%s", pcLADSPAPath, pcDSSIPath); pcLADSPAPath = tmp; pcStart = (const char*)tmp; } // Search the list while (*pcStart != '\0') { pcEnd = pcStart; while (*pcEnd != ':' && *pcEnd != '\0') pcEnd++; pcBuffer = csound->Malloc(csound, 1 + (pcEnd - pcStart)); if (pcEnd > pcStart) { strncpy(pcBuffer, pcStart, pcEnd - pcStart); pcBuffer[pcEnd - pcStart] = '\0'; } LADSPADirectoryPluginSearch(csound, pcBuffer, fCallbackFunction); csound->Free(csound, pcBuffer); pcStart = pcEnd; if (*pcStart == ':') pcStart++; } if (pcDSSIPath) free(pcLADSPAPath); } void describePluginLibrary(CSOUND *csound, const char *pcFullFilename, void *pvPluginHandle, LADSPA_Descriptor_Function fDescriptorFunction) { const LADSPA_Descriptor *psDescriptor; int lIndex; csound->Message(csound, "Plugin: %s:\n", pcFullFilename); for (lIndex = 0; (psDescriptor = fDescriptorFunction(lIndex)) != NULL; lIndex++) csound->Message(csound, " Index: %i : %s (%lu/%s)\n", lIndex, psDescriptor->Name, psDescriptor->UniqueID, psDescriptor->Label); dlclose(pvPluginHandle); } int dssilist(CSOUND * csound, DSSILIST * p) { /* Most of this function comes from the ladspa sdk by Richard Furse */ char *pcBuffer; const char *pcEnd; char *pcLADSPAPath; const char *pcDSSIPath; const char *pcStart; const char *src; src = getenv("LADSPA_PATH"); if (src) pcLADSPAPath = strndup(src, 1024); else pcLADSPAPath = NULL; pcDSSIPath = getenv("DSSI_PATH"); src = getenv("DSSI_PATH"); if (src) pcDSSIPath = strndup(src, 1024); else pcDSSIPath = NULL; if (!pcLADSPAPath) { csound->Message(csound, Str("DSSI4CS: LADSPA_PATH environment variable not set.\n")); } if (!pcDSSIPath) { csound->Message(csound, Str("DSSI4CS: DSSI_PATH environment variable not set.\n")); } if ((!pcLADSPAPath) && (!pcDSSIPath)) /* Fixed - JPff */ return NOTOK; if (pcDSSIPath) { /* **** THIS CODE WAS WRONG -- NO SPACEALLOCATED **** */ if (pcLADSPAPath) { char *nn = (char*)malloc(strlen((char *) pcLADSPAPath)+strlen(pcDSSIPath)+2); strcpy(nn, pcLADSPAPath); strcat(nn, ":"); strcat(nn, pcDSSIPath); free(pcLADSPAPath); pcLADSPAPath = nn; } else { pcLADSPAPath = strdup(pcDSSIPath); } } pcStart = pcLADSPAPath; while (*pcStart != '\0') { pcEnd = pcStart; while (*pcEnd != ':' && *pcEnd != '\0') pcEnd++; pcBuffer = csound->Malloc(csound, 1 + (pcEnd - pcStart)); if (pcEnd > pcStart) strncpy(pcBuffer, pcStart, pcEnd - pcStart); pcBuffer[pcEnd - pcStart] = '\0'; LADSPADirectoryPluginSearch(csound, pcBuffer, describePluginLibrary); csound->Free(csound, pcBuffer); pcStart = pcEnd; if (*pcStart == ':') pcStart++; } free(pcLADSPAPath); free((void *)pcDSSIPath); return OK; } static OENTRY dssi_localops[] = { {"dssiinit", sizeof(DSSIINIT), 0, 1, "i", "Tip", (SUBR) dssiinit, NULL, NULL } , {"dssiactivate", sizeof(DSSIACTIVATE), 0, 3, "", "ik", (SUBR) dssiactivate_init, (SUBR) dssiactivate, NULL } , {"dssiaudio", sizeof(DSSIAUDIO), 0, 5, "mmmmmmmmm", "iMMMMMMMMM", (SUBR) dssiaudio_init, NULL, (SUBR) dssiaudio } , {"dssictls", sizeof(DSSICTLS), 0, 3, "", "iikk", (SUBR) dssictls_init, (SUBR) dssictls_kk, NULL } , {"dssilist", sizeof(DSSILIST), 0, 1, "", "", (SUBR) dssilist, NULL, NULL } #if 0 , {"dssisynth", sizeof(DSSISYNTH), 0, 5, "aa", "i", (SUBR) dssisynth_init, NULL, (SUBR) dssisynth} , {"dssinote", sizeof(DSSINOTE), 0, 3, "", "kikkk", (SUBR) dssinote_init, NULL, (SUBR) dssinote} , {"dssievent", sizeof(DSSINOTEON), 0, 3, "", "kikk", (SUBR) dssievent_init, NULL, (SUBR) dssievent} #endif }; LINKAGE_BUILTIN(dssi_localops) csound-6.10.0/Opcodes/dssi4cs/src/dssi4cs.h000066400000000000000000000067751321653344700204040ustar00rootroot00000000000000/* * Copyright (C) 2005 Andres Cabrera * The dssi4cs library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * The dssi4cs library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with The dssi4cs library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA */ #ifndef DSSI4CS_H #define DSSI4CS_H #include "csdl.h" #include "dssi.h" /* When changing these remember to change dssiaudio function */ #define DSSI4CS_MAX_IN_CHANNELS 9 #define DSSI4CS_MAX_OUT_CHANNELS 9 enum PluginType {LADSPA, DSSI}; typedef struct DSSI4CS_PLUGIN_ { const LADSPA_Descriptor * Descriptor; const DSSI_Descriptor * DSSIDescriptor; /* For Type 1=LADSPA 2=DSSI */ enum PluginType Type; LADSPA_Handle Handle; int Active; LADSPA_Data ** control; LADSPA_Data ** audio; snd_seq_event_t *Events; unsigned long EventCount; int PluginNumber; int * PluginCount; void * NextPlugin; /* float * kinputs_[]; */ /* float * koutputs_[]; */ } DSSI4CS_PLUGIN; typedef struct DSSIINIT_ { OPDS h; /* Inputs. */ MYFLT *iDSSIHandle; MYFLT *iplugin; MYFLT *iindex; MYFLT *iverbose; } DSSIINIT ; typedef struct DSSIACTIVATE_ { OPDS h; MYFLT *iDSSIhandle; MYFLT *ktrigger; int printflag; DSSI4CS_PLUGIN * DSSIPlugin_; } DSSIACTIVATE ; typedef struct DSSIAUDIO_ { OPDS h; /* Outputs. */ MYFLT *aout[DSSI4CS_MAX_OUT_CHANNELS]; /* Inputs. */ MYFLT *iDSSIhandle; MYFLT *ain[DSSI4CS_MAX_IN_CHANNELS]; /* MYFLT *ain1; */ /* MYFLT *ain2; */ /* MYFLT *ain3; */ /* MYFLT *ain4; */ int NumInputPorts; int NumOutputPorts; unsigned long * InputPorts; unsigned long * OutputPorts; DSSI4CS_PLUGIN * DSSIPlugin_; /* State. */ /* size_t framesPerBlock; */ /* size_t channels; */ } DSSIAUDIO ; typedef struct DSSICTLS_ { OPDS h; MYFLT *iDSSIhandle; MYFLT *iport; MYFLT *val; MYFLT *ktrig; /* float *Data; */ unsigned long PortNumber; int HintSampleRate; DSSI4CS_PLUGIN * DSSIPlugin_; } DSSICTLS; typedef struct DSSISYNTH_ { OPDS h; MYFLT *aout[DSSI4CS_MAX_OUT_CHANNELS]; /* Inputs. */ MYFLT *iDSSIhandle; int NumInputPorts; int NumOutputPorts; unsigned long * InputPorts; unsigned long * OutputPorts; DSSI4CS_PLUGIN * DSSIPlugin_; } DSSISYNTH; typedef struct DSSINOTE_ { OPDS h; /* Inputs. */ MYFLT *ktrigger; MYFLT *iDSSIhandle; MYFLT *knote; MYFLT *kveloc; MYFLT *kdur; } DSSINOTE; typedef struct DSSINOTEON_ { OPDS h; /* Inputs. */ MYFLT *ktrigger; MYFLT *iDSSIhandle; MYFLT *knote; MYFLT *kveloc; } DSSINOTEON; typedef struct DSSINOTEOFF_ { OPDS h; /* Inputs. */ MYFLT *ktrigger; MYFLT *iDSSIhandle; MYFLT *knote; MYFLT *kveloc; } DSSINOTEOFF; typedef struct DSSIPGMCH_ { OPDS h; /* Inputs. */ MYFLT *ktrigger; MYFLT *iDSSIhandle; MYFLT *kprogram; MYFLT *kbank; } DSSIPGMCH; typedef struct DSSILIST_ { OPDS h; } DSSILIST ; #endif csound-6.10.0/Opcodes/dssi4cs/src/ladspa.h000066400000000000000000000656431321653344700202730ustar00rootroot00000000000000/* ladspa.h Linux Audio Developer's Simple Plugin API Version 1.1[LGPL]. Copyright (C) 2000-2002 Richard W.E. Furse, Paul Barton-Davis, Stefan Westerfeld. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #ifndef LADSPA_INCLUDED #define LADSPA_INCLUDED #define LADSPA_VERSION "1.1" #define LADSPA_VERSION_MAJOR 1 #define LADSPA_VERSION_MINOR 1 #ifdef __cplusplus extern "C" { #endif /*****************************************************************************/ /* Overview: There is a large number of synthesis packages in use or development on the Linux platform at this time. This API (`The Linux Audio Developer's Simple Plugin API') attempts to give programmers the ability to write simple `plugin' audio processors in C/C++ and link them dynamically (`plug') into a range of these packages (`hosts'). It should be possible for any host and any plugin to communicate completely through this interface. This API is deliberately short and simple. To achieve compatibility with a range of promising Linux sound synthesis packages it attempts to find the `greatest common divisor' in their logical behaviour. Having said this, certain limiting decisions are implicit, notably the use of a fixed type (LADSPA_Data) for all data transfer and absence of a parameterised `initialisation' phase. See below for the LADSPA_Data typedef. Plugins are expected to distinguish between control and audio data. Plugins have `ports' that are inputs or outputs for audio or control data and each plugin is `run' for a `block' corresponding to a short time interval measured in samples. Audio data is communicated using arrays of LADSPA_Data, allowing a block of audio to be processed by the plugin in a single pass. Control data is communicated using single LADSPA_Data values. Control data has a single value at the start of a call to the `run()' or `run_adding()' function, and may be considered to remain this value for its duration. The plugin may assume that all its input and output ports have been connected to the relevant data location (see the `connect_port()' function below) before it is asked to run. Plugins will reside in shared object files suitable for dynamic linking by dlopen() and family. The file will provide a number of `plugin types' that can be used to instantiate actual plugins (sometimes known as `plugin instances') that can be connected together to perform tasks. This API contains very limited error-handling. */ /*****************************************************************************/ /* Fundamental data type passed in and out of plugin. This data type is used to communicate audio samples and control values. It is assumed that the plugin will work sensibly given any numeric input value although it may have a preferred range (see hints below). For audio it is generally assumed that 1.0f is the `0dB' reference amplitude and is a `normal' signal level. */ typedef float LADSPA_Data; /*****************************************************************************/ /* Special Plugin Properties: Optional features of the plugin type are encapsulated in the LADSPA_Properties type. This is assembled by ORing individual properties together. */ typedef int LADSPA_Properties; /* Property LADSPA_PROPERTY_REALTIME indicates that the plugin has a real-time dependency (e.g. listens to a MIDI device) and so its output must not be cached or subject to significant latency. */ #define LADSPA_PROPERTY_REALTIME 0x1 /* Property LADSPA_PROPERTY_INPLACE_BROKEN indicates that the plugin may cease to work correctly if the host elects to use the same data location for both input and output (see connect_port()). This should be avoided as enabling this flag makes it impossible for hosts to use the plugin to process audio `in-place.' */ #define LADSPA_PROPERTY_INPLACE_BROKEN 0x2 /* Property LADSPA_PROPERTY_HARD_RT_CAPABLE indicates that the plugin is capable of running not only in a conventional host but also in a `hard real-time' environment. To qualify for this the plugin must satisfy all of the following: (1) The plugin must not use malloc(), free() or other heap memory management within its run() or run_adding() functions. All new memory used in run() must be managed via the stack. These restrictions only apply to the run() function. (2) The plugin will not attempt to make use of any library functions with the exceptions of functions in the ANSI standard C and C maths libraries, which the host is expected to provide. (3) The plugin will not access files, devices, pipes, sockets, IPC or any other mechanism that might result in process or thread blocking. (4) The plugin will take an amount of time to execute a run() or run_adding() call approximately of form (A+B*SampleCount) where A and B depend on the machine and host in use. This amount of time may not depend on input signals or plugin state. The host is left the responsibility to perform timings to estimate upper bounds for A and B. */ #define LADSPA_PROPERTY_HARD_RT_CAPABLE 0x4 #define LADSPA_IS_REALTIME(x) ((x) & LADSPA_PROPERTY_REALTIME) #define LADSPA_IS_INPLACE_BROKEN(x) ((x) & LADSPA_PROPERTY_INPLACE_BROKEN) #define LADSPA_IS_HARD_RT_CAPABLE(x) ((x) & LADSPA_PROPERTY_HARD_RT_CAPABLE) /*****************************************************************************/ /* Plugin Ports: Plugins have `ports' that are inputs or outputs for audio or data. Ports can communicate arrays of LADSPA_Data (for audio inputs/outputs) or single LADSPA_Data values (for control input/outputs). This information is encapsulated in the LADSPA_PortDescriptor type which is assembled by ORing individual properties together. Note that a port must be an input or an output port but not both and that a port must be a control or audio port but not both. */ typedef int LADSPA_PortDescriptor; /* Property LADSPA_PORT_INPUT indicates that the port is an input. */ #define LADSPA_PORT_INPUT 0x1 /* Property LADSPA_PORT_OUTPUT indicates that the port is an output. */ #define LADSPA_PORT_OUTPUT 0x2 /* Property LADSPA_PORT_CONTROL indicates that the port is a control port. */ #define LADSPA_PORT_CONTROL 0x4 /* Property LADSPA_PORT_AUDIO indicates that the port is a audio port. */ #define LADSPA_PORT_AUDIO 0x8 #define LADSPA_IS_PORT_INPUT(x) ((x) & LADSPA_PORT_INPUT) #define LADSPA_IS_PORT_OUTPUT(x) ((x) & LADSPA_PORT_OUTPUT) #define LADSPA_IS_PORT_CONTROL(x) ((x) & LADSPA_PORT_CONTROL) #define LADSPA_IS_PORT_AUDIO(x) ((x) & LADSPA_PORT_AUDIO) /*****************************************************************************/ /* Plugin Port Range Hints: The host may wish to provide a representation of data entering or leaving a plugin (e.g. to generate a GUI automatically). To make this more meaningful, the plugin should provide `hints' to the host describing the usual values taken by the data. Note that these are only hints. The host may ignore them and the plugin must not assume that data supplied to it is meaningful. If the plugin receives invalid input data it is expected to continue to run without failure and, where possible, produce a sensible output (e.g. a high-pass filter given a negative cutoff frequency might switch to an all-pass mode). Hints are meaningful for all input and output ports but hints for input control ports are expected to be particularly useful. More hint information is encapsulated in the LADSPA_PortRangeHintDescriptor type which is assembled by ORing individual hint types together. Hints may require further LowerBound and UpperBound information. All the hint information for a particular port is aggregated in the LADSPA_PortRangeHint structure. */ typedef int LADSPA_PortRangeHintDescriptor; /* Hint LADSPA_HINT_BOUNDED_BELOW indicates that the LowerBound field of the LADSPA_PortRangeHint should be considered meaningful. The value in this field should be considered the (inclusive) lower bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also specified then the value of LowerBound should be multiplied by the sample rate. */ #define LADSPA_HINT_BOUNDED_BELOW 0x1 /* Hint LADSPA_HINT_BOUNDED_ABOVE indicates that the UpperBound field of the LADSPA_PortRangeHint should be considered meaningful. The value in this field should be considered the (inclusive) upper bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also specified then the value of UpperBound should be multiplied by the sample rate. */ #define LADSPA_HINT_BOUNDED_ABOVE 0x2 /* Hint LADSPA_HINT_TOGGLED indicates that the data item should be considered a Boolean toggle. Data less than or equal to zero should be considered `off' or `false,' and data above zero should be considered `on' or `true.' LADSPA_HINT_TOGGLED may not be used in conjunction with any other hint except LADSPA_HINT_DEFAULT_0 or LADSPA_HINT_DEFAULT_1. */ #define LADSPA_HINT_TOGGLED 0x4 /* Hint LADSPA_HINT_SAMPLE_RATE indicates that any bounds specified should be interpreted as multiples of the sample rate. For instance, a frequency range from 0Hz to the Nyquist frequency (half the sample rate) could be requested by this hint in conjunction with LowerBound = 0 and UpperBound = 0.5. Hosts that support bounds at all must support this hint to retain meaning. */ #define LADSPA_HINT_SAMPLE_RATE 0x8 /* Hint LADSPA_HINT_LOGARITHMIC indicates that it is likely that the user will find it more intuitive to view values using a logarithmic scale. This is particularly useful for frequencies and gains. */ #define LADSPA_HINT_LOGARITHMIC 0x10 /* Hint LADSPA_HINT_INTEGER indicates that a user interface would probably wish to provide a stepped control taking only integer values. Any bounds set should be slightly wider than the actual integer range required to avoid floating point rounding errors. For instance, the integer set {0,1,2,3} might be described as [-0.1, 3.1]. */ #define LADSPA_HINT_INTEGER 0x20 /* The various LADSPA_HINT_HAS_DEFAULT_* hints indicate a `normal' value for the port that is sensible as a default. For instance, this value is suitable for use as an initial value in a user interface or as a value the host might assign to a control port when the user has not provided one. Defaults are encoded using a mask so only one default may be specified for a port. Some of the hints make use of lower and upper bounds, in which case the relevant bound or bounds must be available and LADSPA_HINT_SAMPLE_RATE must be applied as usual. The resulting default must be rounded if LADSPA_HINT_INTEGER is present. Default values were introduced in LADSPA v1.1. */ #define LADSPA_HINT_DEFAULT_MASK 0x3C0 /* This default values indicates that no default is provided. */ #define LADSPA_HINT_DEFAULT_NONE 0x0 /* This default hint indicates that the suggested lower bound for the port should be used. */ #define LADSPA_HINT_DEFAULT_MINIMUM 0x40 /* This default hint indicates that a low value between the suggested lower and upper bounds should be chosen. For ports with LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.75 + log(upper) * 0.25). Otherwise, this should be (lower * 0.75 + upper * 0.25). */ #define LADSPA_HINT_DEFAULT_LOW 0x80 /* This default hint indicates that a middle value between the suggested lower and upper bounds should be chosen. For ports with LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.5 + log(upper) * 0.5). Otherwise, this should be (lower * 0.5 + upper * 0.5). */ #define LADSPA_HINT_DEFAULT_MIDDLE 0xC0 /* This default hint indicates that a high value between the suggested lower and upper bounds should be chosen. For ports with LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.25 + log(upper) * 0.75). Otherwise, this should be (lower * 0.25 + upper * 0.75). */ #define LADSPA_HINT_DEFAULT_HIGH 0x100 /* This default hint indicates that the suggested upper bound for the port should be used. */ #define LADSPA_HINT_DEFAULT_MAXIMUM 0x140 /* This default hint indicates that the number 0 should be used. Note that this default may be used in conjunction with LADSPA_HINT_TOGGLED. */ #define LADSPA_HINT_DEFAULT_0 0x200 /* This default hint indicates that the number 1 should be used. Note that this default may be used in conjunction with LADSPA_HINT_TOGGLED. */ #define LADSPA_HINT_DEFAULT_1 0x240 /* This default hint indicates that the number 100 should be used. */ #define LADSPA_HINT_DEFAULT_100 0x280 /* This default hint indicates that the Hz frequency of `concert A' should be used. This will be 440 unless the host uses an unusual tuning convention, in which case it may be within a few Hz. */ #define LADSPA_HINT_DEFAULT_440 0x2C0 #define LADSPA_IS_HINT_BOUNDED_BELOW(x) ((x) & LADSPA_HINT_BOUNDED_BELOW) #define LADSPA_IS_HINT_BOUNDED_ABOVE(x) ((x) & LADSPA_HINT_BOUNDED_ABOVE) #define LADSPA_IS_HINT_TOGGLED(x) ((x) & LADSPA_HINT_TOGGLED) #define LADSPA_IS_HINT_SAMPLE_RATE(x) ((x) & LADSPA_HINT_SAMPLE_RATE) #define LADSPA_IS_HINT_LOGARITHMIC(x) ((x) & LADSPA_HINT_LOGARITHMIC) #define LADSPA_IS_HINT_INTEGER(x) ((x) & LADSPA_HINT_INTEGER) #define LADSPA_IS_HINT_HAS_DEFAULT(x) ((x) & LADSPA_HINT_DEFAULT_MASK) #define LADSPA_IS_HINT_DEFAULT_MINIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ == LADSPA_HINT_DEFAULT_MINIMUM) #define LADSPA_IS_HINT_DEFAULT_LOW(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ == LADSPA_HINT_DEFAULT_LOW) #define LADSPA_IS_HINT_DEFAULT_MIDDLE(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ == LADSPA_HINT_DEFAULT_MIDDLE) #define LADSPA_IS_HINT_DEFAULT_HIGH(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ == LADSPA_HINT_DEFAULT_HIGH) #define LADSPA_IS_HINT_DEFAULT_MAXIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ == LADSPA_HINT_DEFAULT_MAXIMUM) #define LADSPA_IS_HINT_DEFAULT_0(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ == LADSPA_HINT_DEFAULT_0) #define LADSPA_IS_HINT_DEFAULT_1(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ == LADSPA_HINT_DEFAULT_1) #define LADSPA_IS_HINT_DEFAULT_100(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ == LADSPA_HINT_DEFAULT_100) #define LADSPA_IS_HINT_DEFAULT_440(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ == LADSPA_HINT_DEFAULT_440) typedef struct _LADSPA_PortRangeHint { /* Hints about the port. */ LADSPA_PortRangeHintDescriptor HintDescriptor; /* Meaningful when hint LADSPA_HINT_BOUNDED_BELOW is active. When LADSPA_HINT_SAMPLE_RATE is also active then this value should be multiplied by the relevant sample rate. */ LADSPA_Data LowerBound; /* Meaningful when hint LADSPA_HINT_BOUNDED_ABOVE is active. When LADSPA_HINT_SAMPLE_RATE is also active then this value should be multiplied by the relevant sample rate. */ LADSPA_Data UpperBound; } LADSPA_PortRangeHint; /*****************************************************************************/ /* Plugin Handles: This plugin handle indicates a particular instance of the plugin concerned. It is valid to compare this to NULL (0 for C++) but otherwise the host should not attempt to interpret it. The plugin may use it to reference internal instance data. */ typedef void * LADSPA_Handle; /*****************************************************************************/ /* Descriptor for a Type of Plugin: This structure is used to describe a plugin type. It provides a number of functions to examine the type, instantiate it, link it to buffers and workspaces and to run it. */ typedef struct _LADSPA_Descriptor { /* This numeric identifier indicates the plugin type uniquely. Plugin programmers may reserve ranges of IDs from a central body to avoid clashes. Hosts may assume that IDs are below 0x1000000. */ unsigned long UniqueID; /* This identifier can be used as a unique, case-sensitive identifier for the plugin type within the plugin file. Plugin types should be identified by file and label rather than by index or plugin name, which may be changed in new plugin versions. Labels must not contain white-space characters. */ const char * Label; /* This indicates a number of properties of the plugin. */ LADSPA_Properties Properties; /* This member points to the null-terminated name of the plugin (e.g. "Sine Oscillator"). */ const char * Name; /* This member points to the null-terminated string indicating the maker of the plugin. This can be an empty string but not NULL. */ const char * Maker; /* This member points to the null-terminated string indicating any copyright applying to the plugin. If no Copyright applies the string "None" should be used. */ const char * Copyright; /* This indicates the number of ports (input AND output) present on the plugin. */ unsigned long PortCount; /* This member indicates an array of port descriptors. Valid indices vary from 0 to PortCount-1. */ const LADSPA_PortDescriptor * PortDescriptors; /* This member indicates an array of null-terminated strings describing ports (e.g. "Frequency (Hz)"). Valid indices vary from 0 to PortCount-1. */ const char * const * PortNames; /* This member indicates an array of range hints for each port (see above). Valid indices vary from 0 to PortCount-1. */ const LADSPA_PortRangeHint * PortRangeHints; /* This may be used by the plugin developer to pass any custom implementation data into an instantiate call. It must not be used or interpreted by the host. It is expected that most plugin writers will not use this facility as LADSPA_Handle should be used to hold instance data. */ void * ImplementationData; /* This member is a function pointer that instantiates a plugin. A handle is returned indicating the new plugin instance. The instantiation function accepts a sample rate as a parameter. The plugin descriptor from which this instantiate function was found must also be passed. This function must return NULL if instantiation fails. Note that instance initialisation should generally occur in activate() rather than here. */ LADSPA_Handle (*instantiate)(const struct _LADSPA_Descriptor * Descriptor, unsigned long SampleRate); /* This member is a function pointer that connects a port on an instantiated plugin to a memory location at which a block of data for the port will be read/written. The data location is expected to be an array of LADSPA_Data for audio ports or a single LADSPA_Data value for control ports. Memory issues will be managed by the host. The plugin must read/write the data at these locations every time run() or run_adding() is called and the data present at the time of this connection call should not be considered meaningful. connect_port() may be called more than once for a plugin instance to allow the host to change the buffers that the plugin is reading or writing. These calls may be made before or after activate() or deactivate() calls. connect_port() must be called at least once for each port before run() or run_adding() is called. When working with blocks of LADSPA_Data the plugin should pay careful attention to the block size passed to the run function as the block allocated may only just be large enough to contain the block of samples. Plugin writers should be aware that the host may elect to use the same buffer for more than one port and even use the same buffer for both input and output (see LADSPA_PROPERTY_INPLACE_BROKEN). However, overlapped buffers or use of a single buffer for both audio and control data may result in unexpected behaviour. */ void (*connect_port)(LADSPA_Handle Instance, unsigned long Port, LADSPA_Data * DataLocation); /* This member is a function pointer that initialises a plugin instance and activates it for use. This is separated from instantiate() to aid real-time support and so that hosts can reinitialise a plugin instance by calling deactivate() and then activate(). In this case the plugin instance must reset all state information dependent on the history of the plugin instance except for any data locations provided by connect_port() and any gain set by set_run_adding_gain(). If there is nothing for activate() to do then the plugin writer may provide a NULL rather than an empty function. When present, hosts must call this function once before run() (or run_adding()) is called for the first time. This call should be made as close to the run() call as possible and indicates to real-time plugins that they are now live. Plugins should not rely on a prompt call to run() after activate(). activate() may not be called again unless deactivate() is called first. Note that connect_port() may be called before or after a call to activate(). */ void (*activate)(LADSPA_Handle Instance); /* This method is a function pointer that runs an instance of a plugin for a block. Two parameters are required: the first is a handle to the particular instance to be run and the second indicates the block size (in samples) for which the plugin instance may run. Note that if an activate() function exists then it must be called before run() or run_adding(). If deactivate() is called for a plugin instance then the plugin instance may not be reused until activate() has been called again. If the plugin has the property LADSPA_PROPERTY_HARD_RT_CAPABLE then there are various things that the plugin should not do within the run() or run_adding() functions (see above). */ void (*run)(LADSPA_Handle Instance, unsigned long SampleCount); /* This method is a function pointer that runs an instance of a plugin for a block. This has identical behaviour to run() except in the way data is output from the plugin. When run() is used, values are written directly to the memory areas associated with the output ports. However when run_adding() is called, values must be added to the values already present in the memory areas. Furthermore, output values written must be scaled by the current gain set by set_run_adding_gain() (see below) before addition. run_adding() is optional. When it is not provided by a plugin, this function pointer must be set to NULL. When it is provided, the function set_run_adding_gain() must be provided also. */ void (*run_adding)(LADSPA_Handle Instance, unsigned long SampleCount); /* This method is a function pointer that sets the output gain for use when run_adding() is called (see above). If this function is never called the gain is assumed to default to 1. Gain information should be retained when activate() or deactivate() are called. This function should be provided by the plugin if and only if the run_adding() function is provided. When it is absent this function pointer must be set to NULL. */ void (*set_run_adding_gain)(LADSPA_Handle Instance, LADSPA_Data Gain); /* This is the counterpart to activate() (see above). If there is nothing for deactivate() to do then the plugin writer may provide a NULL rather than an empty function. Hosts must deactivate all activated units after they have been run() (or run_adding()) for the last time. This call should be made as close to the last run() call as possible and indicates to real-time plugins that they are no longer live. Plugins should not rely on prompt deactivation. Note that connect_port() may be called before or after a call to deactivate(). Deactivation is not similar to pausing as the plugin instance will be reinitialised when activate() is called to reuse it. */ void (*deactivate)(LADSPA_Handle Instance); /* Once an instance of a plugin has been finished with it can be deleted using the following function. The instance handle passed ceases to be valid after this call. If activate() was called for a plugin instance then a corresponding call to deactivate() must be made before cleanup() is called. */ void (*cleanup)(LADSPA_Handle Instance); } LADSPA_Descriptor; /**********************************************************************/ /* Accessing a Plugin: */ /* The exact mechanism by which plugins are loaded is host-dependent, however all most hosts will need to know is the name of shared object file containing the plugin types. To allow multiple hosts to share plugin types, hosts may wish to check for environment variable LADSPA_PATH. If present, this should contain a colon-separated path indicating directories that should be searched (in order) when loading plugin types. A plugin programmer must include a function called "ladspa_descriptor" with the following function prototype within the shared object file. This function will have C-style linkage (if you are using C++ this is taken care of by the `extern "C"' clause at the top of the file). A host will find the plugin shared object file by one means or another, find the ladspa_descriptor() function, call it, and proceed from there. Plugin types are accessed by index (not ID) using values from 0 upwards. Out of range indexes must result in this function returning NULL, so the plugin count can be determined by checking for the least index that results in NULL being returned. */ const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index); /* Datatype corresponding to the ladspa_descriptor() function. */ typedef const LADSPA_Descriptor * (*LADSPA_Descriptor_Function)(unsigned long Index); /**********************************************************************/ #ifdef __cplusplus } #endif #endif /* LADSPA_INCLUDED */ /* EOF */ csound-6.10.0/Opcodes/dssi4cs/src/load.c000066400000000000000000000153671321653344700177370ustar00rootroot00000000000000/* load.c Free software by Richard W.E. Furse. Do with as you will. No warranty. */ /*****************************************************************************/ #include "utils.h" #include /*****************************************************************************/ /* This function provides a wrapping of dlopen(). When the filename is not an absolute path (i.e. does not begin with / character), this routine will search the LADSPA_PATH for the file. */ /* TODO static? */ void *dlopenLADSPA(CSOUND *csound, const char *pcFilename, int iFlag) { char *pcBuffer; const char *pcEnd; char *pcLADSPAPath = NULL; char *pcDSSIPath = NULL; const char *pcStart; int iEndsInSO; int iNeedSlash; size_t iFilenameLength; void *pvResult; char *tmp; iFilenameLength = strlen(pcFilename); pvResult = NULL; if (pcFilename[0] == '/') { /* The filename is absolute. Assume the user knows what he/she is doing and simply dlopen() it. */ pvResult = dlopen(pcFilename, iFlag); if (pvResult != NULL) return pvResult; } else { /* If the filename is not absolute then we wish to check along the LADSPA_PATH path to see if we can find the file there. We do NOT call dlopen() directly as this would find plugins on the LD_LIBRARY_PATH, whereas the LADSPA_PATH is the correct place to search. */ tmp = getenv("LADSPA_PATH"); if (tmp) pcLADSPAPath = strdup(tmp); tmp = getenv("DSSI_PATH"); if (tmp) pcDSSIPath = strdup(tmp); if (!pcLADSPAPath) { csound->Message(csound, Str("DSSI4CS: LADSPA_PATH environment " "variable not set.\n")); #ifdef LIB64 pcLADSPAPath = strdup("/usr/lib64/ladspa/"); #else pcLADSPAPath = strdup("/usr/lib/ladspa/"); #endif } if (pcDSSIPath) { int len = strlen(pcLADSPAPath)+strlen(pcDSSIPath)+2; char *tmp = (char*)malloc(len); snprintf(tmp, len, "%s:%s", pcLADSPAPath, pcDSSIPath); free(pcLADSPAPath); pcLADSPAPath = tmp; } if (pcLADSPAPath) { pcStart = pcLADSPAPath; while (*pcStart != '\0') { pcEnd = pcStart; while (*pcEnd != ':' && *pcEnd != '\0') pcEnd++; pcBuffer = csound->Malloc(csound, iFilenameLength + 2 + (pcEnd - pcStart)); if (pcEnd > pcStart) strncpy(pcBuffer, pcStart, pcEnd - pcStart); iNeedSlash = 0; if (pcEnd > pcStart) if (*(pcEnd - 1) != '/') { iNeedSlash = 1; pcBuffer[pcEnd - pcStart] = '/'; } strcpy(pcBuffer + iNeedSlash + (pcEnd - pcStart), pcFilename); pvResult = dlopen(pcBuffer, iFlag); csound->Free(csound, pcBuffer); if (pvResult != NULL) { if (pcLADSPAPath) free(pcLADSPAPath); if (pcDSSIPath) free(pcDSSIPath); return pvResult; } pcStart = pcEnd; if (*pcStart == ':') pcStart++; } } } if (pcLADSPAPath) free(pcLADSPAPath); if (pcDSSIPath) free(pcDSSIPath); /* As a last ditch effort, check if filename does not end with ".so". In this case, add this suffix and recurse. */ iEndsInSO = 0; if (iFilenameLength > 3) iEndsInSO = (strcmp(pcFilename + iFilenameLength - 3, ".so") == 0); if (!iEndsInSO) { pcBuffer = csound->Malloc(csound, iFilenameLength + 4); strcpy(pcBuffer, pcFilename); strcat(pcBuffer, ".so"); pvResult = dlopenLADSPA(csound, pcBuffer, iFlag); csound->Free(csound, pcBuffer); } if (pvResult != NULL) { return pvResult; } /* If nothing has worked, then at least we can make sure we set the correct error message - and this should correspond to a call to dlopen() with the actual filename requested. The dlopen() manual page does not specify whether the first or last error message will be kept when multiple calls are made to dlopen(). We've covered the former case - now we can handle the latter by calling dlopen() again here. */ return dlopen(pcFilename, iFlag); } /*****************************************************************************/ void *loadLADSPAPluginLibrary(CSOUND *csound, const char *pcPluginFilename) { void *pvPluginHandle; /* pvPluginHandle = dlopenLADSPA(csound, pcPluginFilename, RTLD_LAZY); */ pvPluginHandle = dlopenLADSPA(csound, pcPluginFilename, RTLD_NOW); if (!pvPluginHandle) { csound->Die(csound, Str("Failed to load plugin \"%s\": %s"), pcPluginFilename, dlerror()); } return pvPluginHandle; } /*****************************************************************************/ void unloadLADSPAPluginLibrary(CSOUND *csound, void *pvLADSPAPluginLibrary) { dlclose(pvLADSPAPluginLibrary); } /*****************************************************************************/ const LADSPA_Descriptor * findLADSPAPluginDescriptor(CSOUND *csound, void *pvLADSPAPluginLibrary, const char *pcPluginLibraryFilename, const char *pcPluginLabel) { const LADSPA_Descriptor *psDescriptor; LADSPA_Descriptor_Function pfDescriptorFunction; unsigned long lPluginIndex; dlerror(); pfDescriptorFunction = (LADSPA_Descriptor_Function) dlsym(pvLADSPAPluginLibrary, "ladspa_descriptor"); if (!pfDescriptorFunction) { const char *pcError = dlerror(); if (pcError) { csound->Die(csound, Str("Unable to find ladspa_descriptor() function " "in plugin library file \"%s\": %s.\n" "Are you sure this is a LADSPA plugin file ?"), pcPluginLibraryFilename, pcError); } else { csound->Die(csound, Str("Unable to find ladspa_descriptor() function " "in plugin library file \"%s\".\n" "Are you sure this is a LADSPA plugin file ?"), pcPluginLibraryFilename); } } for (lPluginIndex = 0; ; lPluginIndex++) { psDescriptor = pfDescriptorFunction(lPluginIndex); if (psDescriptor == NULL) break; if (strcmp(psDescriptor->Label, pcPluginLabel) == 0) return psDescriptor; } csound->Die(csound, Str("Unable to find label \"%s\" " "in plugin library file \"%s\"."), pcPluginLabel, pcPluginLibraryFilename); return NULL; /* compiler only; not reached */ } csound-6.10.0/Opcodes/dssi4cs/src/utils.h000066400000000000000000000061031321653344700201510ustar00rootroot00000000000000/* utils.h Free software by Richard W.E. Furse. Do with as you will. No warranty. Modified for csound by Andres Cabrera*/ #ifndef LADSPA_SDK_LOAD_PLUGIN_LIB #define LADSPA_SDK_LOAD_PLUGIN_LIB /*****************************************************************************/ #include "csdl.h" #include "ladspa.h" /*****************************************************************************/ /* Functions in load.c: */ /* This function call takes a plugin library filename, searches for the library along the LADSPA_PATH, loads it with dlopen() and returns a plugin handle for use with findPluginDescriptor() or unloadLADSPAPluginLibrary(). Errors are handled by writing a message to stderr and calling exit(1). It is alright (although inefficient) to call this more than once for the same file. */ void * dlopenLADSPA(CSOUND * csound, const char * pcFilename, int iFlag); void * loadLADSPAPluginLibrary(CSOUND * csound, const char * pcPluginFilename); /* This function unloads a LADSPA plugin library. */ void unloadLADSPAPluginLibrary(CSOUND * csound, void * pvLADSPAPluginLibrary); /* This function locates a LADSPA plugin within a plugin library loaded with loadLADSPAPluginLibrary(). Errors are handled by writing a message to stderr and calling exit(1). Note that the plugin library filename is only included to help provide informative error messages. */ const LADSPA_Descriptor * findLADSPAPluginDescriptor(CSOUND * csound, void * pvLADSPAPluginLibrary, const char * pcPluginLibraryFilename, const char * pcPluginLabel); /*****************************************************************************/ /* Functions in search.c: */ /* Callback function for use with LADSPAPluginSearch(). The callback function passes the filename (full path), a plugin handle (dlopen() style) and a LADSPA_DescriptorFunction (from which LADSPA_Descriptors can be acquired). */ typedef void LADSPAPluginSearchCallbackFunction (CSOUND * csound, const char * pcFullFilename, void * pvPluginHandle, LADSPA_Descriptor_Function fDescriptorFunction); /* Search through the $(LADSPA_PATH) (or a default path) for any LADSPA plugin libraries. Each plugin library is tested using dlopen() and dlsym(,"ladspa_descriptor"). After loading each library, the callback function is called to process it. This function leaves items passed to the callback function open. */ void LADSPAPluginSearch(CSOUND * csound, LADSPAPluginSearchCallbackFunction fCallbackFunction); /*****************************************************************************/ /* Function in default.c: */ /* Find the default value for a port. Return 0 if a default is found and -1 if not. */ int getLADSPADefault(CSOUND * csound, const LADSPA_PortRangeHint * psPortRangeHint, const unsigned long lSampleRate, LADSPA_Data * pfResult); /*****************************************************************************/ #endif csound-6.10.0/Opcodes/emugens/000077500000000000000000000000001321653344700161405ustar00rootroot00000000000000csound-6.10.0/Opcodes/emugens/CMakeLists.txt000066400000000000000000000003031321653344700206740ustar00rootroot00000000000000option(BUILD_EMUGENS_OPCODES "Build emugens opcodes" ON) if(BUILD_EMUGENS_OPCODES) # set(SOURCES emugens.c scugens.c) make_plugin(scugens scugens.c) make_plugin(emugens emugens.c) endif() csound-6.10.0/Opcodes/emugens/emugens.c000066400000000000000000000310651321653344700177540ustar00rootroot00000000000000/* emugens.c: Copyright (C) 2017 Eduardo Moguillansky This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include /* linlin linear to linear conversion ky = linlin(kx, kxlow, kxhigh, kylow, kyhigh) ky = (kx - kxlow) / (kxhigh - kxlow) * (kyhigh - kylow) + kylow linlin(0.25, 0, 1, 1, 3) ; --> 1.5 */ typedef struct { OPDS h; MYFLT *kout, *kx, *kx0, *kx1, *ky0, *ky1; } LINLINK; static int linlink(CSOUND *csound, LINLINK *p) { MYFLT x0 = *p->kx0; MYFLT y0 = *p->ky0; MYFLT x = *p->kx; MYFLT x1 = *p->kx1; if (UNLIKELY(x0 == x1)) return csound->PerfError(csound, p->h.insdshead, Str("linlin.k: Division by zero")); *p->kout = (x - x0) / (x1 -x0) * (*(p->ky1) - y0) + y0; return OK; } /* ------------- xyscale -------------- 2d linear interpolation (normalized) Given values for four points at (0, 0), (0, 1), (1, 0), (1, 1), calculate the interpolated value at a given coord (x, y) inside this square inputs: kx, ky, v00, v10, v01, v11 kx, ky: coord, between 0-1 This is conceptually the same as: ky0 = scale(kx, v01, v00) ky1 = scale(kx, v11, v10) kout = scale(ky, ky1, ky0) */ typedef struct { OPDS h; MYFLT *kout, *kx, *ky, *v00, *v10, *v01, *v11; MYFLT d0, d1; } XYSCALE; static int xyscalei_init(CSOUND *csound, XYSCALE *p) { p->d0 = (*p->v01) - (*p->v00); p->d1 = (*p->v11) - (*p->v10); return OK; } static int xyscalei(CSOUND *csound, XYSCALE *p) { // x, y: between 0-1 MYFLT x = *p->kx; MYFLT y0 = x*(p->d0)+(*p->v00); MYFLT y1 = x*(p->d1)+(*p->v10); *p->kout = (*p->ky)*(y1-y0)+y0; return OK; } static int xyscale(CSOUND *csound, XYSCALE *p) { // x, y: between 0-1 // x, y will interpolate between the values at the 4 corners MYFLT v00 = *p->v00; MYFLT v10 = *p->v10; MYFLT x = *p->kx; MYFLT y0 = x*(*p->v01 - v00)+v00; MYFLT y1 = x*(*p->v11 - v10)+v10; *p->kout = (*p->ky)*(y1-y0)+y0; return OK; } /* mtof -- ftom midi to frequency conversion kfreq = mtof(69) */ typedef struct { OPDS h; MYFLT *r, *k; MYFLT freqA4; } PITCHCONV; static int mtof(CSOUND *csound, PITCHCONV *p) { *p->r = POWER(FL(2.0), (*p->k - FL(69.0)) / FL(12.0)) * p->freqA4; return OK; } static int mtof_init(CSOUND *csound, PITCHCONV *p) { p->freqA4 = csound->GetA4(csound); mtof(csound, p); return OK; } static int ftom(CSOUND *csound, PITCHCONV *p) { *p->r = FL(12.0) * LOG2(*p->k / p->freqA4) + FL(69.0); return OK; } static int ftom_init(CSOUND *csound, PITCHCONV *p) { p->freqA4 = csound->GetA4(csound); ftom(csound, p); return OK; } static int pchtom(CSOUND *csound, PITCHCONV *p) { MYFLT pch = *p->k; MYFLT oct = FLOOR(pch); MYFLT note = pch - oct; *p->r = (oct-FL(3.0))*FL(12.0)+note*FL(100.0); return OK; } /* bpf --> break point function with linear interpolation Useful for smaller cases where: * defining a table is overkill * higher accuracy in the x coord * values are changing at k-rate ky bpf kx, kx0, ky0, kx1, ky1, ... */ #define INTERP_L(X, X0, X1, Y0, Y1) ((X) < (X0) ? (Y0) : \ (((X)-(X0))/((X1)-(X0)) * ((Y1)-(Y0)) + (Y0))) inline MYFLT interpol_l(MYFLT x, MYFLT x0, MYFLT x1, MYFLT y0, MYFLT y1) { return x < x0 ? y0 : ((x-x0)/(x1-x0) * (y1-y0) + y0); } #define INTERP_R(X, X0, X1, Y0, Y1) ((X) > (X1) ? (Y1) : \ (((X)-(X0))/((X1)-(X0)) * ((Y1)-(Y0)) + (Y0))) inline MYFLT interpol_r(MYFLT x, MYFLT x0, MYFLT x1, MYFLT y0, MYFLT y1) { return x > x1 ? y0 : ((x-x0)/(x1-x0) * (y1-y0) + y0); } #define INTERP_M(X, X0, X1, Y0, Y1) (((X)-(X0))/((X1)-(X0)) * ((Y1)-(Y0)) + (Y0)) inline MYFLT interpol_m(MYFLT x, MYFLT x0, MYFLT x1, MYFLT y0, MYFLT y1) { return (x-x0)/(x1-x0) * (y1-y0) + y0; } typedef struct { OPDS h; MYFLT *r, *x, *x0, *y0, *x1, *y1, *x2, *y2; } BPF3; static int bpf3(CSOUND *csound, BPF3 *p) { MYFLT x = *p->x; MYFLT n, m; if(x<*p->x1) { m = *p->x0; n = *p->y0; *p->r = INTERP_L(x, m, *p->x1, n, *p->y1); } else { m = *p->x1; n = *p->y1; *p->r = INTERP_R(x, m, *p->x2, n, *p->y2); } return OK; } typedef struct { OPDS h; MYFLT *r, *x, *x0, *y0, *x1, *y1, *x2, *y2, *x3, *y3; } BPF4; static int bpf4(CSOUND *csound, BPF4 *p) { MYFLT x = *p->x; MYFLT m, n; if(x < (*p->x1)) { m = *p->x0; n = *p->y0; *p->r = INTERP_L(x, m, *p->x1, n, *p->y1); } else if (x < (*p->x2)) { m = *p->x1; n = *p->y1; *p->r = INTERP_M(x, m, *p->x2, n, *p->y2); } else { m = *p->x2; n = *p->y2; *p->r = INTERP_R(x, m, *p->x3, n, *p->y3); } return OK; } typedef struct { OPDS h; MYFLT *r, *x, *x0, *y0, *x1, *y1, *x2, *y2, *x3, *y3, *x4, *y4; } BPF5; static int bpf5(CSOUND *csound, BPF5 *p) { MYFLT x = *p->x; if(x < (*p->x2)) { if(x < (*p->x1)) { *p->r = INTERP_L(x, *p->x0, *p->x1, *p->y0, *p->y1); } else { *p->r = INTERP_M(x, *p->x1, *p->x2, *p->y1, *p->y2); } } else if (x < (*p->x3)) { *p->r = INTERP_M(x, *p->x2, *p->x3, *p->y2, *p->y3); } else { *p->r = INTERP_R(x, *p->x3, *p->x4, *p->y3, *p->y4); } return OK; } /* ntom - mton midi to notename conversion imidi = ntom("A4-31") kmidi = ntom(Snotename) Snotename = mton(69.5) Snotename = mton(kmidi) */ typedef struct { OPDS h; MYFLT *r; STRINGDAT *notename; } NTOM; int _pcs[] = {9, 11, 0, 2, 4, 5, 7}; static int ntom(CSOUND *csound, NTOM *p) { /* formats accepted: 8D+ (equals to +50 cents), 4C#, 8A-31 7Bb+30 - no lowercase - octave is necessary and comes always first - no negative octaves, no octaves higher than 9 */ char *n = (char *) p->notename->data; int octave = n[0] - '0'; int pcidx = n[1] - 'A'; if (pcidx < 0 || pcidx >= 7) { csound->Message(csound, Str("expecting a char between A and G, but got %c\n"), n[1]); return NOTOK; } int pc = _pcs[pcidx]; int cents = 0; int cursor; if(n[2] == '#') { pc += 1; cursor = 3; } else if (n[2] == 'b') { pc -= 1; cursor = 3; } else { cursor = 2; } int rest = p->notename->size - 1 - cursor; if(rest > 0) { int sign = n[cursor] == '+' ? 1 : -1; if(rest == 1) { cents = 50; } else if(rest == 2) { cents = n[cursor+1] - '0'; } else if (rest == 3) { cents = 10*(n[cursor+1] - '0') + (n[cursor+2] - '0'); } else { csound->Message(csound,Str("format not understood\n")); return NOTOK; } cents *= sign; } *p->r = ((octave + 1)*12 + pc) + cents/FL(100.0); return OK; } typedef struct { OPDS h; STRINGDAT *Sdst; MYFLT *kmidi; } MTON; // C C# D D# E F F# G G# A Bb B int _pc2idx[] = {2, 2, 3, 3, 4, 5, 5, 6, 6, 0, 1, 1}; int _pc2alt[] = {0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 2, 0}; char _alts[] = " #b"; static int mton(CSOUND *csound, MTON *p) { char *dst; MYFLT m = *p->kmidi; int maxsize = 7; // 4C#+99\0 if (p->Sdst->data == NULL) { p->Sdst->data = csound->Calloc(csound, maxsize); p->Sdst->size = maxsize; } dst = (char*) p->Sdst->data; int octave = m / 12 - 1; int pc = (int)m % 12; int cents = round((m - floor(m))*100.0); int sign, cursor, i; if(cents == 0) { sign = 0; } else if (cents <= 50) { sign = 1; } else { cents = 100 - cents; sign = -1; pc += 1; if(pc == 12) { pc = 0; octave += 1; } } if(octave >= 0) { dst[0] = '0' + octave; cursor = 1; } else { dst[0] = '-'; dst[1] = '0' - octave; cursor = 2; } dst[cursor] = 'A' + _pc2idx[pc]; cursor += 1; int alt = _pc2alt[pc]; if(alt > 0) { dst[cursor++] = _alts[alt]; } if(sign == 1) { dst[cursor++] = '+'; if(cents < 10) { dst[cursor++] = '0'+cents; } else if(cents != 50) { dst[cursor++] = '0' + (int)(cents / 10); dst[cursor++] = '0' + (cents % 10); } } else if(sign == -1) { dst[cursor++] = '-'; if(cents < 10) { dst[cursor++] = '0'+cents; } else if(cents != 50) { dst[cursor++] = '0' + (int)(cents / 10); dst[cursor++] = '0' + (cents % 10); } } for(i=cursor; i", a2 aout cmp a1, "<=", k2 aout cmp a1, "==", 0 */ typedef struct { OPDS h; MYFLT *out, *a0; STRINGDAT *op; MYFLT *a1; int mode; } Cmp; static int cmp_init(CSOUND *csound, Cmp *p) { char *op = (char *) p->op->data; int opsize = p->op->size - 1; if (op[0] == '>') { p->mode = (opsize == 1) ? 0 : 1; } else if (op[0] == '<') { p->mode = (opsize == 1) ? 2 : 3; } else if (op[0] == '=') { p->mode = 4; } else { return csound->InitError(csound, Str("cmp: operator not understood. " "Expecting <, <=, >, >=, ==\n")); } return OK; } static int cmp_aa(CSOUND *csound, Cmp* p) { uint32_t n, nsmps = CS_KSMPS; MYFLT *out = p->out; MYFLT *a0 = p->a0; MYFLT *a1 = p->a1; switch(p->mode) { case 0: for(n=0; n a1[n]; } break; case 1: for(n=0; n= a1[n]; } break; case 2: for(n=0; nout; MYFLT *a0 = p->a0; MYFLT a1 = *(p->a1); switch(p->mode) { case 0: for(n=0; n a1; } break; case 1: for(n=0; n= a1; } break; case 2: for(n=0; n #include "csdl.h" #define LOG001 FL(-6.907755278982137) #define CALCSLOPE(next,prev,nsmps) ((next - prev)/nsmps) /* #define ZXP(z) (*(z)++) */ static inline MYFLT zapgremlins(MYFLT x) { MYFLT absx = fabs(x); // very small numbers fail the first test, eliminating denormalized numbers // (zero also fails the first test, but that is OK since it returns zero.) // very large numbers fail the second test, eliminating infinities // Not-a-Numbers fail both tests and are eliminated. return (absx > (MYFLT)1e-15 && absx < (MYFLT)1e15) ? x : (MYFLT)0.0; } static inline MYFLT sc_wrap(MYFLT in, MYFLT lo, MYFLT hi) { MYFLT range; // avoid the divide if possible if (in >= hi) { range = hi - lo; in -= range; if (in < hi) return in; } else if (in < lo) { range = hi - lo; in += range; if (in >= lo) return in; } else return in; if (hi == lo) return lo; // return in - range * floor((in - lo)/range); return in - range * FLOOR((in - lo) / range); } /* lag This is essentially the same as OnePole except that instead of supplying the coefficient directly, it is calculated from a 60 dB lag time. This is the time required for the filter to converge to within 0.01% of a value. This is useful for smoothing out control signals. ksmooth = lag(kx, klagtime, [initialvalue=0]) asmooth = lag(ka, klagtime, [initialvalue=0]) */ typedef struct { OPDS h; MYFLT *out, *in, *lagtime, *first; MYFLT lag, b1, y1; MYFLT sr; } LAG; static int lagk_next(CSOUND *csound, LAG *p) { MYFLT lag = *p->lagtime; MYFLT y0 = *p->in; MYFLT y1 = p->y1; MYFLT b1; if (lag == p->lag) { b1 = p->b1; p->y1 = y1 = y0 + b1 * (y1 - y0); *p->out = y1; return OK; } else { // faust uses tau2pole = exp(-1 / (lag*sr)) b1 = lag == FL(0.0) ? FL(0.0) : exp(LOG001 / (lag * p->sr)); *p->out = y0 + b1 * (y1 - y0); p->lag = lag; p->b1 = b1; return OK; } } static int lag_init0(CSOUND *csound, LAG *p) { p->lag = -1; p->b1 = FL(0.0); p->y1 = *p->first; return OK; } static int lagk_init(CSOUND *csound, LAG *p) { lag_init0(csound, p); p->sr = csound->GetKr(csound); return lagk_next(csound, p); } static int laga_init(CSOUND *csound, LAG *p) { lag_init0(csound, p); p->sr = csound->GetSr(csound); return OK; } static int laga_next(CSOUND *csound, LAG *p) { uint32_t n, nsmps = CS_KSMPS; MYFLT *in = p->in, *out = p->out; MYFLT lag = *p->lagtime; MYFLT y1 = p->y1; MYFLT b1 = p->b1; MYFLT y0; uint32_t offset = p->h.insdshead->ksmps_offset; // delayed onset uint32_t early = p->h.insdshead->ksmps_no_end; // early end of event if (UNLIKELY(offset)) memset(p->out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->out[nsmps], '\0', early*sizeof(MYFLT)); } if (lag == p->lag) { for (n=offset; ny1 = y1; return OK; } else { // faust uses tau2pole = exp(-1 / (lag*sr)) p->b1 = lag == FL(0.0) ? FL(0.0) : exp(LOG001 / (lag * p->sr)); MYFLT b1_slope = CALCSLOPE(p->b1, b1, nsmps); p->lag = lag; for (n=offset; ny1 = y1; return OK; } } // ------------------------- LagUD --------------------------- typedef struct { OPDS h; MYFLT *out, *in, *lagtimeU, *lagtimeD, *first; MYFLT lagu, lagd, b1u, b1d, y1; } LagUD; static int lagud_a(CSOUND *csound, LagUD *p) { MYFLT *out = p->out, *in = p->in, lagu = *p->lagtimeU, lagd = *p->lagtimeD, y1 = p->y1, b1u = p->b1u, b1d = p->b1d; uint32_t offset = p->h.insdshead->ksmps_offset; // delayed onset uint32_t early = p->h.insdshead->ksmps_no_end; // early end of event uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(offset)) memset(p->out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->out[nsmps], '\0', early*sizeof(MYFLT)); } if ((lagu == p->lagu) && (lagd == p->lagd)) { for (n=offset; n y1) y1 = y0 + b1u * (y1 - y0); else y1 = y0 + b1d * (y1 - y0); out[n]= y1; } } else { MYFLT sr = csound->GetSr(csound); // faust uses tau2pole = exp(-1 / (lag*sr)) p->b1u = lagu == FL(0.0) ? FL(0.0) : exp(LOG001 / (lagu * sr)); MYFLT b1u_slope = CALCSLOPE(p->b1u, b1u, nsmps); p->lagu = lagu; p->b1d = lagd == FL(0.0) ? FL(0.0) : exp(LOG001 / (lagd * sr)); MYFLT b1d_slope = CALCSLOPE(p->b1d, b1d, nsmps); p->lagd = lagd; for (n=offset; n y1) y1 = y0 + b1u * (y1-y0); else y1 = y0 + b1d * (y1-y0); out[n] = y1; } } p->y1 = zapgremlins(y1); return OK; } static int lagud_k(CSOUND *csound, LagUD *p) { MYFLT *in = p->in, lagu = *p->lagtimeU, lagd = *p->lagtimeD, y1 = p->y1; //uint32_t nsmps = CS_KSMPS; if ((lagu == p->lagu) && (lagd == p->lagd)) { MYFLT y0 = *in; if (y0 > y1) p->y1 = y1 = y0 + p->b1u * (y1 - y0); else p->y1 = y1 = y0 + p->b1d * (y1 - y0); *(p->out) = y1; } else { MYFLT sr = csound->GetKr(csound); // faust uses tau2pole = exp(-1 / (lag*sr)), sc uses log(0.01) p->b1u = lagu == FL(0.0) ? FL(0.0) : exp(LOG001 / (lagu * sr)); p->lagu = lagu; p->b1d = lagd == FL(0.0) ? FL(0.0) : exp(LOG001 / (lagd * sr)); p->lagd = lagd; MYFLT y0 = *in; if (y0 > y1) y1 = y0 + p->b1u * (y1 - y0); else y1 = y0 + p->b1d * (y1 - y0); *(p->out) = y1; } p->y1 = y1; return OK; } static int lagud_init(CSOUND *csound, LagUD *p) { p->lagu = -1; p->lagd = -1; p->b1u = FL(0.0); p->b1d = FL(0.0); p->y1 = *p->first; return OK; } // ------------------ Trig ------------------------- // trig(signal, duration) // Returns 1 for given duration whenever signal crosses from // non-positive to positiv typedef struct { OPDS h; MYFLT *out, *in, *dur; MYFLT level, prevtrig; long counter; } Trig; static int trig_a(CSOUND *csound, Trig *p) { MYFLT *out = p->out, *in = p->in; MYFLT dur = *p->dur, sr = csound->GetSr(csound), prevtrig = p->prevtrig, level = p->level; unsigned long counter = p->counter; uint32_t offset = p->h.insdshead->ksmps_offset; // delayed onset uint32_t early = p->h.insdshead->ksmps_no_end; // early end of event uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(offset)) memset(p->out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; n 0) { zout = --counter ? level : FL(0.0); } else { if (curtrig > FL(0.0) && prevtrig <= FL(0.0)) { counter = (long)(dur * sr + FL(0.5)); if (counter < 1) counter = 1; level = curtrig; zout = level; } else { zout = FL(0.0); } } prevtrig = curtrig; out[n] = zout; } p->prevtrig = prevtrig; p->counter = counter; p->level = level; return OK; } static int trig_k(CSOUND *csound, Trig *p) { MYFLT curtrig = *p->in; MYFLT dur = *p->dur; MYFLT kr = csound->GetKr(csound); MYFLT prevtrig = p->prevtrig; MYFLT level = p->level; unsigned long counter = p->counter; if (counter > 0) { *p->out = --counter ? level : FL(0.0); } else { if (curtrig > FL(0.0) && prevtrig <= FL(0.0)) { counter = (long)(dur * kr + FL(0.5)); if (counter < 1) counter = 1; level = curtrig; *p->out = level; } else { *p->out = FL(0.0); } } p->prevtrig = curtrig; p->counter = counter; p->level = level; return OK; } static int trig_init(CSOUND *csound, Trig *p) { p->counter = 0; p->prevtrig = FL(0.0); p->level = FL(0.0); trig_k(csound, p); return OK; } /* Phasor Phasor is a linear ramp between start and end values. When its trigger input crosses from non-positive to positive, Phasor's output will jump to its reset position. Upon reaching the end of its ramp Phasor will wrap back to its start. NOTE: N.B. Since end is defined as the wrap point, its value is never actually output. NOTE: If one wants Phasor to output a signal with frequency freq oscillating between start and end, then the rate should be (end - start) * freq / sr where sr is the sampling rate. Phasor is commonly used as an index control. aindex phasor atrig, xrate, kstart, kend, kresetPos kindex phasor ktrig, krate, kstart, kend, kresetPos trig: When triggered, jump to resetPos (default: 0, equivalent to start). rate: The amount of change per sample, i.e at a rate of 1 the value of each sample will be 1 greater than the preceding sample. start: Start point of the ramp. end: End point of the ramp. resetPos: The value to jump to upon receiving a trigger. */ typedef struct { OPDS h; MYFLT *out, *trig, *rate, *start, *end, *resetPos; MYFLT level, previn/*, resetk*/; } Phasor; static int phasor_init(CSOUND *csound, Phasor *p) { p->previn = 0; p->level = 0; /* p->resetk = 1; */ return OK; } /* static int phasor_init0(CSOUND *csound, Phasor *p) { */ /* p->previn = 0; */ /* p->level = 0; */ /* p->resetk = 0; */ /* return OK; */ /* } */ static int phasor_aa(CSOUND *csound, Phasor *p) { MYFLT *out = p->out; MYFLT *in = p->trig; MYFLT *rate = p->rate; MYFLT start = *p->start; MYFLT end = *p->end; //MYFLT resetPos = p->resetk ? (*p->resetPos) : 0; MYFLT resetPos = *p->resetPos; MYFLT previn = p->previn; MYFLT level = p->level; uint32_t offset = p->h.insdshead->ksmps_offset; // delayed onset uint32_t early = p->h.insdshead->ksmps_no_end; // early end of event uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(offset)) memset(p->out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; n FL(0.0)) { MYFLT frac = FL(1) - previn/(curin-previn); level = resetPos + frac * zrate; } out[n] = level; level += zrate; level = sc_wrap(level, start, end); previn = curin; } p->previn = previn; p->level = level; return OK; } static int phasor_ak(CSOUND *csound, Phasor *p) { MYFLT *out = p->out; MYFLT *in = p->trig; MYFLT rate = *p->rate; MYFLT start = *p->start; MYFLT end = *p->end; MYFLT resetPos = *p->resetPos; //MYFLT resetPos = p->resetk ? (*p->resetPos) : 0; MYFLT previn = p->previn; MYFLT level = p->level; uint32_t n; uint32_t offset = p->h.insdshead->ksmps_offset; // delayed onset uint32_t early = p->h.insdshead->ksmps_no_end; // early end of event uint32_t nsmps = CS_KSMPS; if (UNLIKELY(offset)) memset(p->out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; n FL(0.0)) { MYFLT frac = FL(1.0) - previn/(curin-previn); level = resetPos + frac * rate; } out[n] = level; level += rate; level = sc_wrap(level, start, end); previn = curin; } p->previn = previn; p->level = level; return OK; } static int phasor_kk(CSOUND *csound, Phasor *p) { MYFLT curin = *p->trig; MYFLT rate = *p->rate; MYFLT start = *p->start; MYFLT end = *p->end; MYFLT resetPos = *p->resetPos; //MYFLT resetPos = p->resetk ? (*p->resetPos) : 0; MYFLT previn = p->previn; MYFLT level = p->level; if (UNLIKELY(previn <= FL(0.0) && curin > FL(0.0))) { level = resetPos; } level = sc_wrap(level, start, end); *p->out = level; level += rate; p->previn = curin; p->level = level; return OK; } #define S(x) sizeof(x) static OENTRY localops[] = { { "sc_lag", S(LAG), 0, 3, "k", "kko", (SUBR)lagk_init, (SUBR)lagk_next, NULL, NULL }, { "sc_lag", S(LAG), 0, 5, "a", "ako", (SUBR)laga_init, NULL, (SUBR)laga_next, NULL }, { "sc_lagud", S(LagUD), 0, 3, "k", "kkko", (SUBR)lagud_init, (SUBR)lagud_k }, { "sc_lagud", S(LagUD), 0, 5, "a", "akko", (SUBR)lagud_init, NULL, (SUBR)lagud_a }, { "sc_trig", S(Trig), 0, 3, "k", "kk", (SUBR)trig_init, (SUBR)trig_k }, { "sc_trig", S(Trig), 0, 5, "a", "ak", (SUBR)trig_init, NULL, (SUBR)trig_a }, { "sc_phasor", S(Phasor), 0, 3, "k", "kkkkO", (SUBR)phasor_init, (SUBR)phasor_kk }, { "sc_phasor", S(Phasor), 0, 5, "a", "akkkO", (SUBR)phasor_init, NULL, (SUBR)phasor_ak }, { "sc_phasor", S(Phasor), 0, 5, "a", "aakkO", (SUBR)phasor_init, NULL, (SUBR)phasor_aa }, /* { "sc_phasor", S(Phasor), 0, 3, "k", "kkkk", */ /* (SUBR)phasor_init0, (SUBR)phasor_kk }, */ /* { "sc_phasor", S(Phasor), 0, 5, "a", "akkk", */ /* (SUBR)phasor_init0, NULL, (SUBR)phasor_ak }, */ /* { "sc_phasor", S(Phasor), 0, 5, "a", "aakk", */ /* (SUBR)phasor_init0, NULL, (SUBR)phasor_aa } */ }; LINKAGE csound-6.10.0/Opcodes/eqfil.c000066400000000000000000000050101321653344700157350ustar00rootroot00000000000000/* eqfil.c: Copyright (C) 2007 Victor Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // #include "csdl.h" #include "csoundCore.h" #include "interlocks.h" typedef struct _equ { OPDS h; MYFLT *out; MYFLT *sig, *fr, *bw, *g, *ini; /* in, freq, bw, gain, ini */ double z1,z2; /* delay memory */ MYFLT frv, bwv; /* bandwidth and frequency */ double c,d; /* filter vars */ } equ; static int equ_init(CSOUND *csound, equ *p) { if (*p->ini==0) { double sr = (double)CS_ESR; p->z1 = p->z2 = 0.0; p->frv = *p->fr; p->bwv = *p->bw; p->d = cos(2*PI*p->frv/sr); p->c = tan(PI*p->bwv/sr); } return OK; } static int equ_process(CSOUND *csound, equ *p) { double z1 = p->z1, z2 = p->z2,c,d,w,a,y; MYFLT *in= p->sig,*out=p->out,g; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; int i, ksmps = CS_KSMPS; if (*p->bw != p->bwv || *p->fr != p->frv){ double sr = (double)CS_ESR; p->frv = *p->fr; p->bwv = *p->bw; p->d = cos(2*PI*p->frv/sr); p->c = tan(PI*p->bwv/sr); } c = p->c; d = p->d; a = (1.0-c)/(1.0+c); g = *p->g; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { ksmps -= early; memset(&out[ksmps], '\0', early*sizeof(MYFLT)); } for (i=0; i < ksmps; i++){ w = (double)(in[i]) + d*(1.0 + a)*z1 - a*z2; y = w*a - d*(1.0 + a)*z1 + z2; z2 = z1; z1 = w; out[i] = (MYFLT) (0.5*(y + in[i] + g*(in[i] - y))); } p->z1 = z1; p->z2 = z2; return OK; } static OENTRY eqfil_localops[] = { {"eqfil", sizeof(equ), 0, 5, "a", "akkko", (SUBR)equ_init, NULL, (SUBR)equ_process}, }; LINKAGE_BUILTIN(eqfil_localops) csound-6.10.0/Opcodes/exciter.c000066400000000000000000000230541321653344700163100ustar00rootroot00000000000000/* exciter.c: Copyright (C) 2014 by John ffitch after Markus Schmidt (calf) This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csdl.h" /* EXCITER.C */ #include /********************************************************************** * EXCITER by Markus Schmidt **********************************************************************/ typedef struct { OPDS h; MYFLT *aout; MYFLT *ain; MYFLT *pfreq; MYFLT *pceil; MYFLT *pdrive; MYFLT *pblend; // Internals MYFLT freq_old, ceil_old; // biquad data double hp1[7], hp2[7], hp3[7], hp4[7]; double lp1[7], lp2[7]; // resampler double rs00[7], rs01[7], rs10[7], rs11[7]; // distortion double rdrive, rbdr, kpa, kpb, kna, knb, ap, an, imr, kc, srct, sq, pwrq; int over; double prev_med, prev_out; double blend_old, drive_old; } EXCITER; static inline double process(double st[7], double in/*, char *s */) { double tmp = in - st[5] * st[3] - st[6] * st[4]; double out = tmp * st[0] + st[5] * st[1] + st[6] * st[2]; st[6] = st[5]; st[5] = tmp; /* printf("%s: %f -> %f; %f %f\n", s, in, out, st[5], st[6]); */ return out; } /** Highpass filter based on Robert Bristow-Johnson's equations * @param fc resonant frequency * @param q resonance (gain at fc) */ static inline void set_hp_rbj(CSOUND *csound, double hp[7], double fc, double q) { double omega= (TWOPI*fc/(double)csound->GetSr(csound)); double sn=sin(omega); double cs=cos(omega); double alpha=(double)(sn/(2.0*q)); double inv=(double)(1.0/(1.0+alpha)); hp[2]/*a2*/ = hp[0]/*a0*/ = (inv*(1.0 + cs)*0.5); hp[1]/*a1*/ = -2.0 * hp[0]; hp[3]/*b1*/ = (-2.0*cs*inv); hp[4]/*b2*/ = ((1.0 - alpha)*inv); /* printf("hp_rbj: %f %f %f %f %f\n", hp[0], hp[1], hp[2], hp[3], hp[4]); */ return; } static inline void set_lp_rbj(double lp[7], double fc, double q, double sr) { double omega=(TWOPI*fc/sr); double sn=sin(omega); double cs=cos(omega); double alpha=(sn/(2*q)); double inv=(1.0/(1.0+alpha)); /* printf("fc = %f q = %f sr = %f: %f\n", fc, q, sr, TWOPI*fc/sr); */ /* printf("omega = %f, sn = %f, cs = %f, alpha = %f, inv = %f\n", */ /* omega, sn, cs, alpha, inv); */ lp[2] = lp[0] = inv*(1.0 - cs)*0.5; lp[1] = lp[0]+lp[0]; lp[3] = (-2.0*cs*inv); lp[4] = ((1.0 - alpha)*inv); /* printf("lp_rbj: %f %f %f %f %f\n", lp[0], lp[1], lp[2], lp[3], lp[4]); */ } static int exciter_init(CSOUND *csound, EXCITER *p) { p->freq_old = p->ceil_old = FL(0.0); p->hp1[5] = p->hp2[5] = p->hp3[5] = p->hp4[5] = 0.0; p->hp1[6] = p->hp2[6] = p->hp3[6] = p->hp4[6] = 0.0; p->lp1[5] = p->lp2[5] = 0.0; p->lp1[6] = p->lp2[6] = 0.0; p->rs00[5] = p->rs01[5] = p->rs10[5] = p->rs11[5] = 0.0; p->rs00[6] = p->rs01[6] = p->rs10[6] = p->rs11[6] = 0.0; p->rdrive = p->rbdr = p->kpa = p->kpb = p->kna = p->knb = p->ap = p->an = p->imr = p->kc = p->srct = p->sq = p->pwrq = p->prev_med = p->prev_out = 0.0; p->over = csound->GetSr(csound) * 2 > 96000 ? 1 : 2; p->blend_old = p->drive_old = -1.0; //resample_set_params(csound, p); { double srate = (double)csound->GetSr(csound); double ff = 25000.0; if (srate>50000) ff = srate*0.5; // set all filters set_lp_rbj(p->rs00, ff, 0.8, srate * 2); /* printf("resample filter: %f %f %f %f %f %f %f\n", */ /* p->rs00[0],p->rs00[1],p->rs00[2],p->rs00[3],p->rs00[4], */ /* p->rs00[5],p->rs00[6]); */ memcpy(p->rs01, p->rs00, 5*sizeof(double)); memcpy(p->rs10, p->rs00, 5*sizeof(double)); memcpy(p->rs11, p->rs00, 5*sizeof(double)); } return OK; } void upsample(EXCITER *p, double *tmp, double sample) { double tt = process(p->rs00,sample); tmp[0] = process(p->rs01,tt); //printf("up0:%f -> %f -> %f\n", sample, tt, tmp[0]); tt = process(p->rs00,0.0); tmp[1] = process(p->rs01,tt); //printf("up1:%f -> %f -> %f\n", 0.0, tt, tmp[1]); return; } double downsample(EXCITER *p, double *sample) { //printf("downsample: %f %f ->", sample[0], sample[1]); sample[0] = process(p->rs10, sample[0]); sample[0] = process(p->rs11, sample[0]); sample[1] = process(p->rs10, sample[1]); sample[1] = process(p->rs11, sample[1]); //printf(" %f\n", sample[0]); return sample[0]; } static inline double M(double x) { return (fabs(x) > 0.00000001) ? x : 0.0; } static inline double D(double x) { x = fabs(x); return (x > 0.00000001) ? sqrt(x) : 0.0; } static inline double distort(EXCITER *p, double in) { double samples[2], ans; int i; double ap = p->ap, an = p->an, kpa = p->kpa, kna = p->kna, kpb = p->kpb, knb = p->knb, pwrq = p->pwrq; //printf("in: %f\n", in); upsample(p, samples, in); for (i = 0; i < p->over; i++) { double proc = samples[i]; double med; //printf("%d: %f-> ", i, proc); if (proc >= 0.0) { med = (D(ap + proc * (kpa - proc)) + kpb) * pwrq; } else { med = - (D(an - proc * (kna + proc)) + knb) * pwrq; } proc = p->srct * (med - p->prev_med + p->prev_out); //printf("%f\n", proc); p->prev_med = M(med); p->prev_out = M(proc); samples[i] = proc; } ans = downsample(p, samples); //printf("out: %f\n", ans); return ans; } static inline void set_distort(CSOUND *csound, EXCITER *p) { // set distortion coeffs if ((p->drive_old != *p->pdrive) || (p->blend_old != *p->pblend)) { double srate = csound->GetSr(csound); /* printf("drive %f->%f; blend %f->%f\n", */ /* p->drive_old, *p->pdrive, p->blend_old, *p->pblend); */ p->drive_old = *p->pdrive; p->blend_old = *p->pblend; p->rdrive = 12.0 / p->drive_old; p->rbdr = p->rdrive / (10.5 - p->blend_old) * 780.0 / 33.0; p->kpa = D(2.0 * (p->rdrive*p->rdrive) - 1.0) + 1.0; p->kpb = (2.0 - p->kpa) / 2.0; p->ap = ((p->rdrive*p->rdrive) - p->kpa + 1.0) / 2.0; p->kc = p->kpa / D(2.0 * D(2.0 * (p->rdrive*p->rdrive) - 1.0) - 2.0 * p->rdrive*p->rdrive); p->srct = (0.1 * srate) / (0.1 * srate + 1.0); p->sq = p->kc*p->kc + 1.0; p->knb = -1.0 * p->rbdr / D(p->sq); p->kna = 2.0 * p->kc * p->rbdr / D(p->sq); p->an = p->rbdr*p->rbdr / p->sq; p->imr = 2.0 * p->knb + D(2.0 * p->kna + 4.0 * p->an - 1.0); p->pwrq = 2.0 / (p->imr + 1.0); /* printf("params: rdrive\trbdr\tkpa\tkpb\tkna\tknb\tap\tan" "\timr\tkc\tsrct\tsq\tpwrq\n"); */ /* printf("\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\n", */ /* p->rdrive, p->rbdr, p->kpa, p->kpb, p->kna, p->knb, p->ap, p->an, */ /* p->imr, p->kc, p->srct, p->sq, p->pwrq); */ } } static inline void params_changed(CSOUND *csound, EXCITER *p) { // set the params of all filters if (UNLIKELY(*p->pfreq != p->freq_old)) { set_hp_rbj(csound, p->hp1, *p->pfreq, 0.707); memcpy(p->hp2, p->hp1, 5*sizeof(double)); memcpy(p->hp3, p->hp1, 5*sizeof(double)); memcpy(p->hp4, p->hp1, 5*sizeof(double)); p->freq_old = *p->pfreq; } // set the params of all filters if (UNLIKELY(*p->pceil != p->ceil_old)) { set_lp_rbj(p->lp1, *p->pceil, 0.707, (double)csound->GetSr(csound)); memcpy(p->lp2, p->lp1, 5*sizeof(double)); p->ceil_old = *p->pceil; } // set distortion set_distort(csound, p); } int exciter_perf(CSOUND *csound, EXCITER *p) //uint32_t inputs_mask, uint32_t outputs_mask) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT zerodb = csound->Get0dBFS(csound); if (UNLIKELY(offset)) memset(p->aout, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->aout[nsmps], '\0', early*sizeof(MYFLT)); } params_changed(csound, p); // process for (n = offset; nain[n]/zerodb; // all pre filters in chain //printf("**** %f ****\n", in); out1 = process(p->hp2, process(p->hp1, in)); out = distort(p, out1); // saturate //printf("after distort %f -> %f -> %f\n", in, out1, out); // all post filters in chain out = process(p->hp4, process(p->hp3, out)); // all H/P post filters in chain (surely LP - JPff) out = process(p->lp1, process(p->lp2, out)); p->aout[n] = out*zerodb; } // cycle through samples return OK; } #define S(x) sizeof(x) static OENTRY excite_localops[] = { { "exciter", S(EXCITER), 0, 5, "a", "akkkk", (SUBR)exciter_init, NULL, (SUBR)exciter_perf }, }; LINKAGE_BUILTIN(excite_localops) csound-6.10.0/Opcodes/fareygen.c000066400000000000000000000206311321653344700164430ustar00rootroot00000000000000/* fareygen.c: Copyright (C) 2010 Georg Boenn This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csdl.h" #include #define MAX_PFACTOR 16 static const int MAX_PRIMES = 168; /* 168 primes < 1000 */ static const int primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997}; typedef struct pfactor_ { int expon; int base; } PFACTOR; typedef struct _rat { int p; int q; } RATIO; static int EulerPhi (int n); static int FareyLength (int n); static int PrimeFactors (int n, PFACTOR p[]); static void GenerateFarey (int n, RATIO flist[], int size); static int fareytable (FGDATA *ff, FUNC *ftp) { /* This Gen routine calculates a Farey Sequence F_n of the integer n. A Farey Sequence F_n of order n is a list of fractions in their lowest terms between 0 and 1 and in ascending order. Their denominators do not exceed n. This means a fraction a/b belongs to F_n if 0 <= a <= b <= n. In F_n, the numerator and denominator of each fraction is always coprime. 0 and 1 are included in F_n as the fractions 0/1 and 1/1. For example F_5 = {0/1, 1/5, 1/4, 1/3, 2/5, 1/2, 3/5, 2/3, 3/4, 4/5, 1/1} Some properties of the Farey Sequence: 1. If a/b and c/d are two successive terms of F_n, then bc - ad = 1. 2. If a/b, c/d, e/f are three successive terms of F_n, then: c/d = (a+e) / (b+f) c/d is called the mediant fraction between a/b and e/f. 3. If n > 1, then no two successive terms of F_n have the same denominator. The length of any Farey Sequence F_n is determined by |F_n| = 1 + SUM (phi(m)) FOR m=1, m<=n, m++ where phi(m) is Euler's totient function, which gives the number of integers <= m that are coprime to m. References: Hardy, G.M. and Wright, E.M. (1960), An Introduction to the Theory of Numbers, Oxford, 4th Edition, Chapter 3, p.23 http://mathworld.wolfram.com/FareySequence.html http://en.wikipedia.org/wiki/Totient Implementation Notes: The size of the array of fractions for any F_n is calculated with the help Euler's function phi(n), also called totient function. For its implementation we included an array of prime numbers and a function to determine the prime factor composition of a natural integer. The primes dividing the integer are stored locally in a small array of ints. Important: The length of the table declared by the user does not have to be equal to the length of the Farey Sequence. If the table is smaller, then only a part of the sequence is copied. If it is longer, then zeros are padded. */ int j, fareyseq, nvals, nargs, farey_length, mode; MYFLT *fp = ftp->ftable, *pp, *pp2; CSOUND *csound = ff->csound; RATIO *flist; nvals = ff->flen; nargs = ff->e.pcnt - 4; if (UNLIKELY(nargs < 2)) { return csound->ftError(ff, Str("insufficient arguments for fareytable")); } ff->e.p[4] *= -1; pp = &(ff->e.p[5]); fareyseq = (int) *pp; pp2 = &(ff->e.p[6]); mode = (int) *pp2; farey_length = FareyLength(fareyseq); flist = (RATIO*) csound->Calloc(csound, farey_length*sizeof(RATIO)); GenerateFarey (fareyseq, flist, farey_length); switch (mode) { default: case 0: /* output float elements of F_n */ for (j = 0; j < nvals; j++) { if (j < farey_length) fp[j] = (MYFLT) flist[j].p / (MYFLT) flist[j].q; } break; case 1: /* output delta values of successive elements of F_n */ { MYFLT last = FL(0.0); int i = 1; for (j = 0; j < nvals; j++, i++) { if (i < farey_length) { MYFLT current = (MYFLT) flist[i].p / (MYFLT) flist[i].q; fp[j] = current - last; last = current; } } break; } case 2: /* output only the denominators of the integer ratios */ for (j = 0; j < nvals; j++) { if (j < farey_length) fp[j] = (MYFLT) flist[j].q; } break; case 3: /* output the normalised denominators of the integer ratios */ { MYFLT farey_scale = (MYFLT) 1 / (MYFLT) fareyseq; for (j = 0; j < nvals; j++) { if (j < farey_length) fp[j] = (MYFLT) flist[j].q * farey_scale; } break; } case 4: /* output float elements of F_n + 1 for tuning tables*/ for (j = 0; j < nvals; j++) { if (j < farey_length) fp[j] = FL(1.0) + (MYFLT) flist[j].p / (MYFLT) flist[j].q; } break; } csound->Free(csound,flist); return OK; } /* utility functions. See the comments above. */ static int EulerPhi (int n) { int i; PFACTOR p[MAX_PFACTOR]; MYFLT result; if (n == 1) return 1; if (n == 0) return 0; memset(p, 0, sizeof(PFACTOR)*MAX_PFACTOR); /* for (i=0; i < MAX_PFACTOR; i++) { */ /* p[i].expon = 0; */ /* p[i].base = 0; */ /* } */ (void)PrimeFactors (n, p); result = (MYFLT) n; for (i = 0; i < MAX_PFACTOR; i++) { int q = p[i].base; if (!q) break; result *= (FL(1.0) - FL(1.0) / (MYFLT) q); } return (int) result; } static int FareyLength (int n) { int i = 1; int result = 1; n++; for (; i < n; i++) result += EulerPhi (i); return result; } static int PrimeFactors (int n, PFACTOR p[]) { int i = 0; int j = 0; int i_exp = 0; if (!n) return j; while (i < MAX_PRIMES) { int aprime = primes[i++]; if (j == MAX_PFACTOR || aprime > n) { return j; } if (n == aprime) { p[j].expon = 1; p[j].base = n; return (++j); } i_exp = 0; while (!(n % aprime)) { i_exp++; n /= aprime; } if (i_exp) { p[j].expon = i_exp; p[j].base = aprime; ++j; } } return j; } static void GenerateFarey (int n, RATIO flist[], int size) { int a, b, c, d, k, i; a = 0; b = 1, c = 1, d = n; i = 1; flist[0].p = a; flist[0].q = b; while (c < n) { k = (int) ((n + b) / d); int tempa = a; int tempb = b; a = c; b = d; c = k * c - tempa; d = k * d - tempb; flist[i].p = a; flist[i].q = b; if (i < size) i++; } } static NGFENS farey_fgens[] = { { "farey", fareytable }, { NULL, NULL } }; FLINKAGE_BUILTIN(farey_fgens) csound-6.10.0/Opcodes/fareyseq.c000066400000000000000000000653261321653344700164740ustar00rootroot00000000000000/* fareyseq.c: Copyright (C) 2010 Georg Boenn This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* The code for the tablefilter opcodes is based on the code for tablecopy by Robin Whittle, see source OOps/ugrw1.c */ #include "csoundCore.h" #include "interlocks.h" #include #include #define MAX_PFACTOR 16 const int MAX_PRIMES = 1229; const int primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, 8147, 8161, 8167, 8171, 8179, 8191, 8209, 8219, 8221, 8231, 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291, 8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369, 8377, 8387, 8389, 8419, 8423, 8429, 8431, 8443, 8447, 8461, 8467, 8501, 8513, 8521, 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597, 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677, 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741, 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831, 8837, 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929, 8933, 8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011, 9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109, 9127, 9133, 9137, 9151, 9157, 9161, 9173, 9181, 9187, 9199, 9203, 9209, 9221, 9227, 9239, 9241, 9257, 9277, 9281, 9283, 9293, 9311, 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377, 9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439, 9461, 9463, 9467, 9473, 9479, 9491, 9497, 9511, 9521, 9533, 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, 9629, 9631, 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733, 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811, 9817, 9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887, 9901, 9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973}; typedef struct pfactor_ { int expon; int base; } PFACTOR; /* opcodes striuctures */ typedef struct { OPDS h; MYFLT *result; /* returns the number of elements of the source table that have passed the filter operation*/ MYFLT *dft; /* Destination function table number. */ MYFLT *sft; /* Source function table number */ MYFLT *ftype; /* user selection of the filter type */ MYFLT *threshold; /* user variable to set filter */ /* Storage to remember what the table numbers were from a previous k cycle, and to store pointers to their FUNC data structures. */ int pdft; /* Previous destination */ int psft; /* source function table numbers. */ FUNC *funcd, *funcs; } TABFILT; typedef struct { OPDS h; MYFLT *sft; /* Source function table number */ /* Storage to remember what the table numbers were from a previous k cycle, and to store pointers to their FUNC data structures. */ int psft; /* source function table numbers. */ FUNC *funcs; } TABSHUFFLE; typedef struct { OPDS h; MYFLT *kr, *kn; } FAREYLEN; int tablefilter (CSOUND*,TABFILT *p); int tablefilterset (CSOUND*,TABFILT *p); int tableifilter (CSOUND*, TABFILT *p); int fareylen (CSOUND*, FAREYLEN *p); int tableshuffle (CSOUND*, TABSHUFFLE *p); int tableshuffleset (CSOUND*, TABSHUFFLE *p); int tableishuffle (CSOUND *, TABSHUFFLE *p); /* utility functions */ int EulerPhi (int n); int FareyLength (int n); int PrimeFactors (int n, PFACTOR p[]); MYFLT Digest (int n); void float2frac (CSOUND *csound, MYFLT in, int *p, int *q); void float_to_cfrac (CSOUND *csound, double r, int n, int a[], int p[], int q[]); /* a filter and table copy opcode for filtering tables containing Farey Sequences generated with fateytable GEN */ /* tablefilterset() * * Called at i time prior to the k rate function tablefilter (). * */ int tablefilterset(CSOUND *csound, TABFILT *p) { p->pdft = 0; p->psft = 0; *p->ftype = 1; *p->threshold = 7; return OK; } /* tablefilter() * * k rate version - see tableifilter () for the init time version. * */ static int dotablefilter (CSOUND *csound, TABFILT *p); int tablefilter (CSOUND *csound, TABFILT *p) { /* Check the state of the two table number variables. * Error message if any are < 1 and no further action. */ if (UNLIKELY((*p->dft < 1) || (*p->sft < 1))) { return csound->PerfError(csound, p->h.insdshead, Str("Farey: Table no. < 1 dft=%.2f sft=%.2f"), *p->dft, *p->sft); } if (UNLIKELY((*p->ftype < 1))) { return csound->PerfError(csound, p->h.insdshead, Str("Farey: Filter type < 1 ftype=%.2f"), *p->ftype); } /* Check each table number in turn. */ /* Destination */ if (p->pdft != (int)*p->dft) { /* Get pointer to the function table data structure. * csoundFTFindP() for perf time. csoundFTFind() for init time. */ if (UNLIKELY((p->funcd = csound->FTFindP(csound, p->dft)) == NULL)) { return csound->PerfError(csound, p->h.insdshead, Str("Farey: Destination dft table %.2f not found."), *p->dft); } /* Table number is valid. * Save the integer version of the table number for future reference.*/ p->pdft = (int)*p->dft; } /* Source */ if (p->psft != (int)*p->sft) { if (UNLIKELY((p->funcs = csound->FTFindP(csound, p->sft)) == NULL)) { return csound->PerfError(csound, p->h.insdshead, Str("Farey: Source sft table %.2f not found."), *p->sft); } p->psft = (int)*p->sft; } /* OK both tables present and the funcx pointers are pointing to * their data structures. */ dotablefilter (csound, p); return OK; } /*-----------------------------------*/ int tableifilter (CSOUND *csound, TABFILT *p) { /* Check the state of the two table number variables. * Error message if any are < 1 and no further action. */ if (UNLIKELY((*p->dft < 1) || (*p->sft < 1))) { return csound->InitError(csound, Str("Farey: Table no. < 1 dft=%.2f sft=%.2f"), *p->dft, *p->sft); } if (UNLIKELY((*p->ftype < 1))) { return csound->PerfError(csound, p->h.insdshead, Str("Farey: Filter type < 1 ftype=%.2f"), *p->ftype); } /* Check each table number in turn. */ /* Destination */ if (p->pdft != (int)*p->dft) { /* Get pointer to the function table data structure. * csoundFTFindP() for perf time. csoundFTFind() for init time. */ if (UNLIKELY((p->funcd = csound->FTnp2Find(csound, p->dft)) == NULL)) { return csound->InitError(csound, Str("Farey: Destination dft table %.2f not found."), *p->dft); } /* Table number is valid. * Save the integer version of the table number for future reference. */ p->pdft = (int)*p->dft; } /* Source */ if (p->psft != (int)*p->sft) { if (UNLIKELY((p->funcs = csound->FTnp2Find(csound, p->sft)) == NULL)) { return csound->InitError(csound, Str("Farey: Source sft table %.2f not found."), *p->sft); } p->psft = (int)*p->sft; } /* OK both tables present and the funcx pointers are pointing to * their data structures. */ dotablefilter (csound, p); return OK; } /*-----------------------------------*/ /* dotablefilter() * * * * */ static int dotablefilter (CSOUND *csound, TABFILT *p) { int32 loopcount; /* Loop counter. Set by the length of the dest table.*/ int32 indx = 0; /* Index to be added to offsets */ int32 indx2 = 0; /*index into source table*/ MYFLT *based, *bases; /* Base addresses of the two tables.*/ int32 masks; /* Binary masks for the source table */ MYFLT *pdest, *ps; MYFLT threshold; int32 ftype; MYFLT previous = FL(0.0); //int32 sourcelength; ftype = (int32) *p->ftype; threshold = Digest (*p->threshold); loopcount = p->funcd->flen; //sourcelength = loopcount; /* Now get the base addresses and length masks of the tables. */ based = p->funcd->ftable; bases = p->funcs->ftable; masks = p->funcs->lenmask; do { /* Create source pointers by ANDing index with mask, and adding to base * address. This causes source addresses to wrap around if the * destination table is longer. * Destination address is simply the index plus the base address since * we know we will be writing within the table. */ pdest = based + indx; ps = bases + (masks & indx2); switch (ftype) { default: case 0: *pdest = *ps; indx++; indx2++; break; case 1: { /* filter all above threshold */ int p, q = 0; float2frac (csound, *ps, &p, &q); if (Digest (q) > threshold) { indx2++; } else { *pdest = *ps; indx++; indx2++; } break; } case 2: { /* filter all below threshold */ int p, q = 0; float2frac (csound, *ps, &p, &q); if (Digest (q) < threshold) { indx2++; } else { *pdest = *ps; indx++; indx2++; } break; } case 3: { /* generate IOIs from source and write into destination */ if (*ps == FL(0.0)) { /* skip zeros in source table */ indx2++; break; } *pdest = *ps - previous; previous = *ps; indx++; indx2++; break; } } } while (--loopcount); *p->result = indx; return OK; } /*************************************** functions for shuffling an f-table ***************************************/ static int dotableshuffle (CSOUND *csound, TABSHUFFLE *p); int tableshuffleset(CSOUND *csound, TABSHUFFLE *p) { p->psft = 0; return OK; } int tableshuffle (CSOUND * csound, TABSHUFFLE *p) { if (UNLIKELY(*p->sft < 1)) { return csound->PerfError(csound, p->h.insdshead, Str("Table no. < 1 sft=%.2f"), *p->sft); } /* Source */ if (p->psft != (int)*p->sft) { if (UNLIKELY((p->funcs = csound->FTFindP(csound, p->sft)) == NULL)) { return csound->PerfError(csound, p->h.insdshead, Str("Source sft table %.2f not found."), *p->sft); } p->psft = (int)*p->sft; } dotableshuffle (csound, p); return OK; } int tableishuffle (CSOUND *csound, TABSHUFFLE *p) { if (UNLIKELY(*p->sft < 1)) { return csound->PerfError(csound, p->h.insdshead, Str("Table no. < 1 sft=%.2f"), *p->sft); } /* Source */ if (p->psft != (int)*p->sft) { if (UNLIKELY((p->funcs = csound->FTnp2Find(csound, p->sft)) == NULL)) { return csound->InitError(csound, Str("Source sft table %.2f not found."), *p->sft); } p->psft = (int)*p->sft; } dotableshuffle (csound, p); return OK; } /*-----------------------------------*/ /* dotableshuffle() * used to randomly shuffle the content of a csound f-table */ static int dotableshuffle (CSOUND *csound, TABSHUFFLE *p) { time_t now; unsigned int seed = (unsigned int) time (&now); MYFLT *bases; /* Base address of the source table.*/ MYFLT *temp; int32 sourcelength; int32 i = 0; srand (seed); sourcelength = p->funcs->flen; /* Now get the base address of the table. */ bases = p->funcs->ftable; temp = (MYFLT*) csound->Calloc (csound, sourcelength* sizeof(MYFLT)); memset (temp, 0, sizeof(MYFLT) * sourcelength); for (i = 0; i < sourcelength; i++) { int32 pos = rand() % sourcelength; while (temp[pos]) { pos--; if (pos < 0) pos = sourcelength - 1; } temp[pos] = bases[i]; } memcpy (bases, temp, sizeof(MYFLT) * sourcelength); csound->Free (csound, temp); return OK; } int fareylen (CSOUND *csound, FAREYLEN *p) { int n = (int) *p->kn; *p->kr = (MYFLT) FareyLength (n); return OK; } /* utility functions */ int EulerPhi (int n) { int i = 0; //int pcount; MYFLT result; PFACTOR p[MAX_PFACTOR]; memset(p, 0, sizeof(PFACTOR)*MAX_PFACTOR); if (n == 1) return 1; if (n == 0) return 0; (void)PrimeFactors (n, p); result = (MYFLT)n; for (i = 0; i < MAX_PFACTOR; i++) { int q = p[i].base; if (!q) break; result *= (FL(1.0) - FL(1.0) / (MYFLT) q); } return (int) result; } int FareyLength (int n) { int i = 1; int result = 1; n++; for (; i < n; i++) result += EulerPhi (i); return result; } int PrimeFactors (int n, PFACTOR p[]) { int i = 0; int j = 0; int i_exp = 0; int pcount = 0; if (!n) return pcount; while (i < MAX_PRIMES) { int aprime = primes[i++]; if (j == MAX_PFACTOR || aprime > n) { return pcount; } if (n == aprime) { p[j].expon = 1; p[j].base = n; return (++pcount); } i_exp = 0; while (!(n % aprime)) { i_exp++; n /= aprime; } if (i_exp) { p[j].expon = i_exp; p[j].base = aprime; ++pcount; ++j; } } return j; } /* ----------------------------------------------- * * Calculation of the digestibility of an integer * according to Clarence Barlow * See his work on 'Autobusk' and 'Musiquantics'. * Digest returns a weight for an integer according * to its prime number composition. It takes into * account both the prime and its exponent. * The smaller the weight the more 'digestible' the number, * whereas large prime numbers and large exponents * lead to penalties and the weight becomes heavier. * The order of the first 16 integers according to Digest is: * 1, 2, 4, 3, 8, 6, 16, 12, 9, 5, 10, 15, 7, 14 * ----------------------------------------------- */ MYFLT Digest (int n) { if (!n) return FL(0.0); { MYFLT result = FL(0.0); int i = 0; int exponent = 0; while( i < MAX_PRIMES ) { int prime = primes[i]; if (n == prime) { result += (((prime - 1)*(prime - 1)) / (MYFLT) prime); return (result + result); } while (!(n % prime)) { exponent++; n /= prime; } if (exponent) { result += (exponent * (((prime - 1)*(prime - 1)) / (MYFLT) prime)); } i++; exponent = 0; } return (result + result); } } /* interface for the function float_to_cfrac, which is a continued fraction expansion in order to convert a real number into an integer fraction with an error less than 10^-5 */ void float2frac (CSOUND *csound, MYFLT in, int *num, int *denom) { #define N (10) int a[N+1]; int p[N+2]; int q[N+2]; int P = 0; int Q = 0; int i; float_to_cfrac (csound, (double)in, N, a, p, q); for (i=0; i <= N; i++) { double temp; float error; if (!q[i+1]) continue; temp = (double) p[i+1] / (double) q[i+1]; error = in - temp; if ((fabs(error)) < 0.00001) { P = p[i+1]; Q = q[i+1]; break; } } *num = P; *denom = Q; } /* continued fraction expansion */ void float_to_cfrac (CSOUND *csound, double r, int n, int a[], int p[], int q[]) { int i; double r_copy; double *x; if (r == 0.0) { memset(a, 0, sizeof(int)*(n+1)); /* for (i = 0; i <= n; i++) { */ /* a[i] = 0; */ /* } */ memset(p, 0, sizeof(int)*(n+2)); /* for (i = 0; i <= n+1; i++) { */ /* p[i] = 0; */ /* } */ memset(q, 0, sizeof(int)*(n+2)); /* for ( i = 0; i <= n+1; i++ ) { */ /* q[i] = 0; */ /* } */ return; } x = csound->Calloc(csound, (n+1)* sizeof(double)); r_copy = fabs (r); p[0] = 1; q[0] = 0; p[1] = (int) r_copy; q[1] = 1; x[0] = r_copy; a[0] = (int) x[0]; for (i = 1; i <= n; i++) { x[i] = 1.0 / (x[i-1] - (double) a[i-1]); a[i] = (int) x[i]; p[i+1] = a[i] * p[i] + p[i-1]; q[i+1] = a[i] * q[i] + q[i-1]; } if (r < 0.0) { for (i = 0; i <= n+1; i++) { p[i] = -p[i]; } } csound->Free(csound, x); } #define S sizeof static OENTRY fareyseq_localops[] = { {"tablefilteri", S(TABFILT),TB, 1, "i", "iiii", (SUBR) tableifilter,NULL,NULL}, {"tablefilter", S(TABFILT), TB, 2, "k", "kkkk", (SUBR) tablefilterset, (SUBR) tablefilter, NULL}, {"fareyleni", S(FAREYLEN), TR, 1, "i", "i", (SUBR) fareylen, NULL, NULL}, {"fareylen", S(FAREYLEN), TR, 2, "k", "k", NULL, (SUBR) fareylen, NULL}, {"tableshufflei", S(TABSHUFFLE), TB, 1, "", "i", (SUBR) tableshuffle, NULL, NULL}, {"tableshuffle", S(TABSHUFFLE), TB, 2, "", "k", (SUBR) tableshuffleset, (SUBR) tableshuffle, NULL}, }; LINKAGE_BUILTIN(fareyseq_localops) csound-6.10.0/Opcodes/faustgen.cpp000066400000000000000000000504041321653344700170200ustar00rootroot00000000000000/* faustgen.cpp (c) Victor Lazzarini, 2013 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Faust Csound opcodes These four opcodes allow Faust to be embedded in Csound code: faustcompile: compiles a Faust program faustaudio: creates a DSP instance from a compiled Faust program (any number of instances from a single compiled program are allowed) faustctl: sets the value of a given control of a Faust DSP instance faustgen: compiles and creates a single DSP instance from a Faust program (convenient for one-off Faust programs) */ #include "csdl.h" #include #include "faust/dsp/llvm-dsp.h" #include "faust/gui/UI.h" #include #if defined(MACOSX) || defined(linux) || defined(HAIKU) #include #endif #define MAXARG 40 /** * Faust controls class for Csound * **/ class controls : public UI { struct ctl { MYFLT *zone; char label[64]; MYFLT min, max; ctl *nxt; } anchor; void addctl(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max){ ctl *pctl = &anchor; while(pctl->nxt) pctl = pctl->nxt; pctl->nxt = new ctl; pctl = pctl->nxt; strncpy(pctl->label,label, 63); pctl->zone = zone; pctl->min = min; pctl->max = max; pctl->nxt = NULL; } public: controls() { anchor.nxt = NULL; anchor.label[0] = '\0';} ~controls() { ctl *pctl = &anchor, *tmp; pctl = pctl->nxt; while(pctl) { tmp = pctl; pctl = pctl->nxt; delete tmp; } } virtual void openTabBox(const char* label) {}; virtual void openHorizontalBox(const char* label) {}; virtual void openVerticalBox(const char* label) {}; virtual void closeBox() {}; virtual void addSoundfile(const char* label, const char* filename, Soundfile** sf_zone) {}; virtual void addButton(const char* label, FAUSTFLOAT* zone) { addctl(label, zone, 0, 0); } virtual void addCheckButton(const char* label, FAUSTFLOAT* zone){ addctl(label, zone, 0, 0); } virtual void addVerticalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step){ addctl(label, zone, min, max); } virtual void addHorizontalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) { addctl(label, zone, min, max); } virtual void addNumEntry(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) { addctl(label, zone, min, max); } virtual void addHorizontalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max){}; virtual void addVerticalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max) {}; MYFLT *getZone(char *label){ ctl *pctl = &anchor; pctl = pctl->nxt; while(pctl){ if(strcmp(pctl->label, label) == 0) break; pctl = pctl->nxt; } if(pctl) return pctl->zone; else return NULL; } MYFLT getMax(char *label){ ctl *pctl = &anchor; pctl = pctl->nxt; while(pctl){ if(strcmp(pctl->label, label) == 0) break; pctl = pctl->nxt; } if(pctl) return pctl->max; else return 0; } MYFLT getMin(char *label){ ctl *pctl = &anchor; pctl = pctl->nxt; while(pctl){ if(strcmp(pctl->label, label) == 0) break; pctl = pctl->nxt; } if(pctl) return pctl->min; else return 0; } }; /** * Faust object handle * **/ struct faustobj { void *obj; controls *ctls; faustobj *nxt; unsigned long cnt; }; /** * Faust compile opcode usage: ihandle faustcompile Scode, Sargs[,istacksize] ihandle - handle to compiled code Scode - Faust program Sargs - Faust compiler args istacksize - compiler stack size in megabytes (default 1MB). **/ struct faustcompile { OPDS h; MYFLT *hptr; STRINGDAT *code; STRINGDAT *args; MYFLT *stacksize; llvm_dsp_factory *factory; pthread_mutex_t *lock; }; char **parse_cmd(CSOUND *csound, char *str, int *argc){ char **argv; int i = 0, n=0, end = strlen(str); while(str[i] == ' ') i++; if(str[i] != '\0') *argc = 1; while(str[i] != '\0'){ if(str[i] == ' ') { while (str[++i] == ' '); if(str[i] == '\0') break; (*argc)++; } i++; } argv = (char **) csound->Calloc(csound, sizeof(char *)*(*argc)); i = 0; while(str[i] == ' ') i++; for(n=0; n < *argc && i < end; n++) { argv[n] = &(str[i]); while(str[++i] != ' ' && i < end); if(i >= end) break; str[i] = '\0'; while(str[++i] == ' ' && i < end); } return argv; } int delete_faustcompile(CSOUND *csound, void *p) { faustcompile *pp = ((faustcompile *) p); faustobj *fobj, *prv, **pfobj; pfobj = (faustobj **) csound->QueryGlobalVariable(csound,"::factory"); fobj = *pfobj; prv = fobj; while(fobj != NULL) { if(fobj->obj == (void *) pp->factory) { prv->nxt = fobj->nxt; break; } prv = fobj; fobj = fobj->nxt; } if(fobj != NULL) { if(*pfobj == fobj) *pfobj = fobj->nxt; deleteDSPFactory(pp->factory); csound->Free(csound, fobj); } return OK; } struct hdata { faustcompile *p; CSOUND *csound; }; void *init_faustcompile_thread(void *pp) { faustcompile *p = ((hdata *) pp)->p; faustobj **pffactory, *ffactory; CSOUND *csound = ((hdata *) pp)->csound; llvm_dsp_factory *factory; int argc = 0; std::string err_msg; char *cmd = (char *) csound->Malloc(csound, p->args->size + 8); int ret; strcpy(cmd, p->args->data); #ifdef USE_DOUBLE strcat(cmd, " -double"); #endif const char **argv = (const char **) parse_cmd(csound, cmd, &argc); const char* varname = "::factory"; //Need to protect this csound->LockMutex(p->lock); //csound->Message(csound, "lock %p\n", p->lock); factory = createDSPFactoryFromString("faustop", (const char *) p->code->data,argc, argv, "", err_msg, 3); //csound->Message(csound, "unlock %p\n", p->lock); csound->UnlockMutex(p->lock); if(factory == NULL) { csound->Message(csound, Str("\nFaust compilation problem:\nline %s\n"), err_msg.c_str()); *(p->hptr) = FL(-2.0); // error code. csound->Free(csound, argv); csound->Free(csound, cmd); csound->Free(csound, pp); ret = -1; pthread_exit(&ret); } pffactory = (faustobj **) csound->QueryGlobalVariable(csound,varname); if(pffactory == NULL) { csound->CreateGlobalVariable(csound, varname, sizeof(faustobj *)); pffactory = (faustobj **) csound->QueryGlobalVariable(csound,varname); ffactory = (faustobj *) csound->Calloc(csound, sizeof(faustobj)); ffactory->obj = factory; ffactory->nxt = NULL; ffactory->cnt = 0; *pffactory = ffactory; } else { ffactory = *pffactory; while(ffactory->nxt){ ffactory = ffactory->nxt; } ffactory->nxt = (faustobj *) csound->Calloc(csound, sizeof(faustobj)); ffactory->nxt->cnt = ffactory->cnt+1; ffactory = ffactory->nxt; ffactory->obj = factory; } p->factory = factory; *p->hptr = (MYFLT) ffactory->cnt; csound->RegisterResetCallback(csound, p, delete_faustcompile); csound->Free(csound,argv); csound->Free(csound,cmd); csound->Free(csound,pp); return NULL; } #define MBYTE 1048576 int init_faustcompile(CSOUND *csound, faustcompile *p){ pthread_t thread; pthread_attr_t attr; hdata *data = (hdata *) csound->Malloc(csound, sizeof(hdata)); data->csound = csound; data->p = p; *p->hptr = -1; p->lock = (pthread_mutex_t *) csound->QueryGlobalVariable(csound,"::faustlock::"); if(p->lock == NULL) { csound->CreateGlobalVariable(csound,"::faustlock::", sizeof(pthread_mutex_t)); p->lock = (pthread_mutex_t *) csound->QueryGlobalVariable(csound,"::faustlock::"); pthread_mutex_init(p->lock, NULL); //csound->Message(csound, "lock created %p\n", p->lock); } pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, *p->stacksize*MBYTE); pthread_create(&thread, &attr,init_faustcompile_thread, data); return OK; } /** * faustgen and faustaudio opcodes usage: ihandle[,asig1,...] faustgen Scode[,ain1,...] ihandle[,asig1,...] faustaudio ifactory,[,ain1,...] Scode - Faust program ifactory - handle pointing to compiled code from faustcompile asig1 ... - audio outputs from Faust program ain1 ... - audio inputs to Faust program ihandle - handle identifying this Faust DSP instance **/ struct faustgen { OPDS h; MYFLT *ohptr; MYFLT *outs[MAXARG]; /* outputs */ STRINGDAT *code; /* faust code as string */ MYFLT *ins[VARGMAX]; /* inputs */ llvm_dsp *engine; /* faust DSP */ llvm_dsp_factory* factory; /* DSP factory */ controls *ctls; AUXCH memin; AUXCH memout; }; struct hdata2 { faustgen *p; CSOUND *csound; }; /* deinit function delete faust objects */ int delete_faustgen(CSOUND *csound, void *p) { faustgen *pp = (faustgen *) p; faustobj *fobj, *prv, **pfobj; pfobj = (faustobj **) csound->QueryGlobalVariable(csound,"::dsp"); fobj = *pfobj; prv = fobj; while(fobj != NULL) { if(fobj->obj == (void *) pp->engine) { prv->nxt = fobj->nxt; break; } prv = fobj; fobj = fobj->nxt; } if(fobj != NULL) { if(*pfobj == fobj) *pfobj = fobj->nxt; csound->Free(csound, fobj); delete pp->ctls; delete pp->engine; } else csound->Warning(csound, Str("could not find DSP %p for deletion"), pp->engine); if(pp->factory) deleteDSPFactory(pp->factory); return OK; } int init_faustaudio(CSOUND *csound, faustgen *p){ int factory; OPARMS parms; faustobj *fobj, **fobjp, **pfdsp, *fdsp; llvm_dsp *dsp; controls *ctls = new controls(); const char *varname = "::dsp"; #if defined(MACOSX) || defined(linux) || defined(HAIKU) while((int) *((MYFLT *)p->code) == -1) usleep(1); #else while((int) *((MYFLT *)p->code) == -1) Sleep(1); #endif factory = (int) *((MYFLT *)p->code); if(factory == -2) return csound->InitError(csound, Str("Faust code did not compile properly.\n" "Check above messages for Faust compiler errors\n")); fobjp = (faustobj **) csound->QueryGlobalVariable(csound,"::factory"); if(fobjp == NULL) return csound->InitError(csound, Str("no factory available\n")); fobj = *fobjp; while((int) fobj->cnt != factory) { fobj = fobj->nxt; if(fobj == NULL) return csound->InitError(csound, Str("factory not found %d\n"), (int) factory); } dsp = ((llvm_dsp_factory *)fobj->obj)->createDSPInstance(); if(dsp == NULL) return csound->InitError(csound, Str("Faust instantiation problem \n")); dsp->buildUserInterface(ctls); pfdsp = (faustobj **) csound->QueryGlobalVariable(csound,varname); if(pfdsp == NULL) { csound->CreateGlobalVariable(csound, varname, sizeof(faustobj *)); pfdsp = (faustobj **) csound->QueryGlobalVariable(csound,varname); fdsp = (faustobj *) csound->Calloc(csound, sizeof(faustobj)); fdsp->obj = dsp; fdsp->ctls = ctls; fdsp->nxt = NULL; fdsp->cnt = 0; *pfdsp = fdsp; } else { fdsp = *pfdsp; if(fdsp != NULL){ while(fdsp->nxt){ fdsp = fdsp->nxt; } fdsp->nxt = (faustobj *) csound->Calloc(csound, sizeof(faustobj)); fdsp->nxt->cnt = fdsp->cnt+1; fdsp = fdsp->nxt; fdsp->obj = dsp; fdsp->ctls = ctls; } else { fdsp = (faustobj *) csound->Calloc(csound, sizeof(faustobj)); fdsp->obj = dsp; fdsp->ctls = ctls; fdsp->nxt = NULL; fdsp->cnt = 0; *pfdsp = fdsp; } } p->factory = NULL; // this opcode does not own the factory p->engine = (llvm_dsp *) fdsp->obj; p->engine->init(csound->GetSr(csound)); if(p->engine->getNumInputs() != p->INCOUNT-1) { delete p->engine; return csound->InitError(csound, Str("wrong number of input args\n")); } if(p->engine->getNumOutputs() != p->OUTCOUNT-1){ delete p->engine; return csound->InitError(csound, Str("wrong number of output args\n")); } /* memory for sampAccurate offsets */ csound->GetOParms(csound, &parms); if(parms.sampleAccurate){ size_t size; size = p->engine->getNumInputs()*sizeof(MYFLT *); if(p->memin.auxp == NULL || p->memin.size < size) csound->AuxAlloc(csound, size, &p->memin); size = p->engine->getNumOutputs()*sizeof(MYFLT *); if(p->memout.auxp == NULL || p->memout.size < size) csound->AuxAlloc(csound, size, &p->memout); } p->ctls = ctls; csound->RegisterDeinitCallback(csound, p, delete_faustgen); *p->ohptr = (MYFLT) fdsp->cnt; return OK; } void *init_faustgen_thread(void *pp){ CSOUND *csound = ((hdata2 *) pp)->csound; faustgen *p = ((hdata2 *) pp)->p; OPARMS parms; std::string err_msg; int argc = 3; const char* argv[argc]; faustobj **pfdsp, *fdsp; llvm_dsp *dsp; controls *ctls = new controls(); const char *varname = "::dsp"; argv[0] = "-vec"; argv[1] = "-lv"; argv[2] = " 1"; p->engine = NULL; #ifdef USE_DOUBLE argv[3] = "-double"; argc += 1; #endif p->factory = createDSPFactoryFromString("faustop", (const char *) p->code->data, argc, argv, "", err_msg, 3); if(p->factory == NULL) { int ret = csound->InitError(csound, Str("Faust compilation problem: %s\n"), err_msg.c_str()); csound->Free(csound, pp); pthread_exit(&ret); } dsp = p->factory->createDSPInstance(); if(dsp == NULL) { int ret = csound->InitError(csound, Str("Faust instantiation problem \n")); csound->Free(csound, pp); pthread_exit(&ret); } dsp->buildUserInterface(ctls); pfdsp = (faustobj **) csound->QueryGlobalVariable(csound,varname); if(pfdsp == NULL) { csound->CreateGlobalVariable(csound, varname, sizeof(faustobj *)); pfdsp = (faustobj **) csound->QueryGlobalVariable(csound,varname); fdsp = (faustobj *) csound->Calloc(csound, sizeof(faustobj)); fdsp->obj = dsp; fdsp->ctls = ctls; fdsp->nxt = NULL; fdsp->cnt = 0; *pfdsp = fdsp; } else { fdsp = *pfdsp; while(fdsp->nxt){ fdsp = fdsp->nxt; } fdsp->nxt = (faustobj *) csound->Calloc(csound, sizeof(faustobj)); fdsp->nxt->cnt = fdsp->cnt++; fdsp = fdsp->nxt; fdsp->obj = dsp; fdsp->ctls = ctls; } p->engine = dsp; dsp->buildUserInterface(ctls); dsp->init(csound->GetSr(csound)); if(p->engine->getNumInputs() != p->INCOUNT-1) { int ret; delete p->engine; deleteDSPFactory(p->factory); csound->Free(csound, pp); ret =csound->InitError(csound, Str("wrong number of input args\n")); p->engine = NULL; pthread_exit(&ret); } if(p->engine->getNumOutputs() != p->OUTCOUNT-1){ int ret; delete p->engine; deleteDSPFactory(p->factory); csound->Free(csound, pp); ret = csound->InitError(csound, Str("wrong number of output args\n")); p->engine = NULL; pthread_exit(&ret); } /* memory for sampAccurate offsets */ csound->GetOParms(csound, &parms); if(parms.sampleAccurate){ size_t size; size = p->engine->getNumInputs()*sizeof(MYFLT *); if(p->memin.auxp == NULL || p->memin.size < size) csound->AuxAlloc(csound, size, &p->memin); size = p->engine->getNumOutputs()*sizeof(MYFLT *); if(p->memout.auxp == NULL || p->memout.size < size) csound->AuxAlloc(csound, size, &p->memout); } p->ctls = ctls; *p->ohptr = (MYFLT) fdsp->cnt; csound->RegisterDeinitCallback(csound, p, delete_faustgen); csound->Free(csound, pp); return NULL; } int init_faustgen(CSOUND *csound, faustgen *p){ pthread_t thread; pthread_attr_t attr; int *ret; hdata2 *data = (hdata2 *) csound->Malloc(csound, sizeof(hdata2)); data->csound = csound; data->p = p; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, MBYTE); pthread_create(&thread, &attr, init_faustgen_thread, data); pthread_join(thread, (void **) &ret); if(ret == NULL) return OK; else return NOTOK; } int perf_faust(CSOUND *csound, faustgen *p){ int nsmps = CS_KSMPS, i; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; MYFLT **in_tmp = (MYFLT **) p->memin.auxp; MYFLT **out_tmp = (MYFLT **) p->memout.auxp; AVOIDDENORMALS; if (UNLIKELY(early)) { for (i = 0; i < p->OUTCOUNT-1; i++) memset(p->outs[i], '\0', nsmps*sizeof(MYFLT)); nsmps -= early; } if(UNLIKELY(offset)) { /* offset pointers, save current pos */ for (i = 0; i < p->OUTCOUNT-1; i++){ memset(p->outs[i], '\0', nsmps*sizeof(MYFLT)); out_tmp[i] = p->outs[i]; p->outs[i] = &(p->outs[i][offset]); } for (i = 0; i < p->INCOUNT-1; i++){ in_tmp[i] = p->ins[i]; p->ins[i] = &(p->ins[i][offset]); } nsmps -= offset; } p->engine->compute(nsmps, p->ins, p->outs); if(UNLIKELY(offset)) { /* restore pos */ for (i = 0; i < p->OUTCOUNT-1; i++) p->outs[i] = out_tmp[i]; for (i = 0; i < p->INCOUNT-1; i++) p->ins[i] = in_tmp[i]; } return OK; } /** * faustctl opcode usage: faustctl idsp, Slabel, kval idsp - handle from an existing Faust DSP instance Slabel - name of control (in Faust program) kval - value to be sent to control **/ struct faustctl { OPDS h; MYFLT *inst; STRINGDAT *label; MYFLT *val; MYFLT *zone; MYFLT min, max; }; int init_faustctl(CSOUND *csound, faustctl *p){ faustobj *fobj, **fobjp; int instance = (int) *p->inst; fobjp = (faustobj **) csound->QueryGlobalVariable(csound,"::dsp"); if(fobjp == NULL) return csound->InitError(csound, Str("no dsp instances available\n")); fobj = *fobjp; while((int) fobj->cnt != instance) { fobj = fobj->nxt; if(fobj == NULL) return csound->InitError(csound, Str("dsp instance not found %d\n"), (int) *p->inst); } p->zone = fobj->ctls->getZone(p->label->data); if(p->zone == NULL) return csound->InitError(csound, Str("dsp control %s not found\n"), p->label->data); p->max = fobj->ctls->getMax(p->label->data); p->min = fobj->ctls->getMin(p->label->data); { MYFLT val = *p->val; if(p->min != p->max) val = val < p->min ? p->min : (val > p->max ? p->max : val); *p->zone = val; } return OK; } int perf_faustctl(CSOUND *csound, faustctl *p) { MYFLT val = *p->val; if(p->min != p->max) val = val < p->min ? p->min : (val > p->max ? p->max : val); *p->zone = val; return OK; } #define S(x) sizeof(x) static OENTRY localops[] = { { (char *) "faustgen", S(faustgen), 0, 5, (char *) "immmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", (char *)"SM",(SUBR)init_faustgen, NULL, (SUBR)perf_faust}, { (char *) "faustcompile", S(faustcompile), 0, 1, (char *) "i", (char *)"SSp",(SUBR)init_faustcompile, NULL, NULL}, { (char *) "faustaudio", S(faustgen), 0, 5, (char *) "immmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", (char *)"iM",(SUBR)init_faustaudio, NULL, (SUBR)perf_faust}, { (char *) "faustctl", S(faustgen), 0, 3, (char *) "", (char *)"iSk",(SUBR)init_faustctl, (SUBR) perf_faustctl} }; PUBLIC long csound_opcode_init(CSOUND *csound, OENTRY **ep) { IGN(csound); *ep = localops; return (long) sizeof(localops); } PUBLIC int csoundModuleInfo(void) { return ((CS_APIVERSION << 16) + (CS_APISUBVER << 8) + (int) sizeof(MYFLT)); } csound-6.10.0/Opcodes/fhtfun.h000066400000000000000000000046511321653344700161460ustar00rootroot00000000000000/* fhtfun.h: Copyright (C) 1997 Paris Smaragdis, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ typedef struct{ OPDS h; MYFLT *out, *as, *af, *len, *ovlp, *iwin, *bias; AUXCH mem; MYFLT *buffer_in1, *buffer_in2, *buffer_out; FUNC *win; MYFLT *in1, *in2, *w; int32 m, count; MYFLT s_ovlp; } CON; /* typedef struct{ */ /* OPDS h; */ /* MYFLT *out, *as, *imp, *iwin, *ienv; */ /* AUXCH mem; */ /* MYFLT *buffer_in, *buffer_out; */ /* FUNC *win; */ /* MYFLT *in, *in2, norm; */ /* int32 flen, count, count2; */ /* } CNV; */ /* typedef struct{ */ /* OPDS h; */ /* MYFLT *out, *as, *str, *len, *ovlp, *iwin; */ /* AUXCH mem; */ /* MYFLT *buffer_in, *buffer_out; */ /* FUNC *win; */ /* MYFLT *in; */ /* int32 m, count; */ /* } STCH; */ /* typedef struct{ */ /* OPDS h; */ /* MYFLT *out, *as, *af, *len, *ovlp, *iwin, *bias, *peaks; */ /* AUXCH mem; */ /* MYFLT *buffer_in, *buffer_in2, *buffer_out; */ /* FUNC *win; */ /* MYFLT *in, *in2, *mor; */ /* int32 *clx, *cly; */ /* int32 m, count; */ /* } MRH; */ static void getmag(MYFLT *x, int32 size); static void mult(MYFLT *x, MYFLT *y, int32 size, MYFLT w); static void lineaprox(MYFLT *x, int32 size, int32 m); static void do_fht(MYFLT *real, int32 n); static void do_ifht(MYFLT *real, int32 n); static void pfht(MYFLT *fz, int32 n); csound-6.10.0/Opcodes/filter.c000066400000000000000000000573541321653344700161440ustar00rootroot00000000000000/* filter.c: Copyright (C) 1997 Michael A. Casey, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* filter.c */ /* Author: Michael A. Casey * Language: C * Copyright (C) 1997 Michael A. Casey, MIT Media Lab, All Rights Reserved * * Implementation of filter opcode for general purpose filtering. * This opcode implements the following difference equation: * * (1)*y(n) = b(0)*x(n) + b(1)*x(n-1) + ... + b(nb)*x(n-nb) * - a(1)*y(n-1) - ... - a(na)*y(n-na) * * whose system function is represented by: * * -1 -nb * jw B(z) b(0) + b(1)z + .... + b(nb)z * H(e) = ---- = ---------------------------- * -1 -na * A(z) 1 + a(1)z + .... + a(na)z * * The syntax is as follows: * * xsig2 xfilter xsig1, nb, na, b(0), b(1), ..., b(nb), a(1), a(2), ..., a(na) * * xsig is either a k-rate or a-rate signal and xfilter is * the corresponding opcode: kfilter or filter respectively. * b(n) and a(n) are either i or k-rate arguments * nb and na are i-time arguments with the following limits: * * 1 <= nb <= 51 * 0 <= na <= 50 * * The filter is implemented with a direct form-II digital filter lattice * which has the advantage of requiring a single Nth-order delay line * [N = max(na,nb-1)], as well as negating the need for pole-zero * factorization which is required of type III and IV digital filter * lattice structures. * * * Examples of digital filtering using filter * ========================================== * * A first-order IIR filter with k-rate gain kG and k-rate pole coefficient * ka1 has the following syntax: * * asig2 filter asig1, 1, 1, kG, ka1 * * A first-order allpass IIR filter with i-var coefficient c has the * following syntax: * * asig2 filter asig1, 2, 1, -ic, 1, ic * * A first-order linear-phase lowpass FIR filter operating on a kvar signal * has the following syntax: * * ksig2 kfilter ksig1, 2, 0, 0.5, 0.5 * * Potential applications of filter * ================================ * * Since filter allows the implementation of generalised recursive filters, * it can be used to specify a large range of general DSP algorithms- very * efficiently. * * For example, a digital waveguide can be implemented for musical instrument * modeling using a pair of delayr and delayw opcodes in conjunction with the * filter opcode. * * * The zfilter opcode * ================== * * Whereas the above two opcodes, filter and kfilter, are static linear * time-invariant (LTI) filters, zfilter implements two pole-warping * operations to effect control over the filter at the k-rate. The * operations are radial pole-shear and angular pole-warp respectively. * * Pole shearing increases the magnitude of poles along radial lines in * the Z-plane. This has the affect of altering filter ring times. The * variable kmag is the parameters (-1:1) * * Pole warping changes the frequency of poles by moving them along angular * paths in the Z plane. This operation leaves the shape of the magnitude * response unchanged but alters the frequencies by a constant factor * (preserving 0 and pi). This alters the resonant frequencies of the filter * but leaves the "timbre" of the filter intact. * * The following example implements a forth-order all-pole model with pole * shear and warp factors kmag and kfreq and i-time IIR coefficient ia1...ia4. * * asig2 zfilter kmag, kfreq, 1, 4, 1, ia1, ia2, ia3, ia4 * * Notice * ====== * * This code is provided as is for the express purpose of enhancing Csound * with a general-purpose filter routine. No guarantees are made as to its * effectiveness for a particular application. The author reserves the right * to withdraw this code from the Csound distribution at any time without * notice. This code is not to be used for any purposes other than those * covered by the public Csound license agreement. For any other use, * including distribution in whole or part, specific prior permission * must be obtained from MIT. * */ /* Contains modifications by John ffitch, which have no restrictions attached * Main changes are to work in double precision internally */ #include #include "stdopcod.h" #include "filter.h" #include typedef struct FCOMPLEX {double r,i;} fcomplex; static double readFilter(FILTER*, int); static void insertFilter(FILTER*,double); #ifndef MAX #define MAX(a,b) ((a>b)?(a):(b)) #define MIN(a,b) ((a>b)?(b):(a)) #endif /*#define POLEISH (1) */ /* 1=poleish pole roots after Laguer root finding */ typedef struct FPOLAR {double mag,ph;} fpolar; /* Routines associated with pole control */ static void expandPoly(fcomplex[], double[], int); static void complex2polar(fcomplex[],fpolar[], int); static void polar2complex(fpolar[],fcomplex[], int); static void sortRoots(fcomplex roots[], int dim); static int sortfun(fpolar *a, fpolar *b); static void nudgeMags(fpolar a[], fcomplex b[], int dim, double fact); static void nudgePhases(fpolar a[], fcomplex b[], int dim, double fact); static void zroots(CSOUND*, fcomplex [], int, fcomplex []); static fcomplex Cadd(fcomplex, fcomplex); static fcomplex Csub(fcomplex, fcomplex); static fcomplex Cmul(fcomplex, fcomplex); static fcomplex Cdiv(fcomplex, fcomplex); static fcomplex Complex(double, double); static double Cabs(fcomplex); static fcomplex Csqrt(fcomplex); static fcomplex RCmul(double, fcomplex); /* Filter initialization routine */ static int ifilter(CSOUND *csound, FILTER* p) { int i; /* since i-time arguments are not guaranteed to propegate to p-time * we must copy the i-vars into the p structure. */ p->numa = (int)*p->na; p->numb = (int)*p->nb; /* First check bounds on initialization arguments */ if (UNLIKELY((p->numb<1) || (p->numb>(MAXZEROS+1)) || (p->numa<0) || (p->numa>MAXPOLES))) return csound->InitError(csound, Str("Filter order out of bounds: " "(1 <= nb < 51, 0 <= na <= 50)")); /* Calculate the total delay in samples and allocate memory for it */ p->ndelay = MAX(p->numb-1,p->numa); csound->AuxAlloc(csound, p->ndelay * sizeof(double), &p->delay); /* Initialize the delay line for safety ***NOT NEEDED AS AUXALLOC DOES THAT */ /* for (i=0;indelay;i++) */ /* ((double*)p->delay.auxp)[i] = 0.0; */ /* Set current position pointer to beginning of delay */ p->currPos = (double*)p->delay.auxp; for (i=0; inumb+p->numa; i++) p->dcoeffs[i] = (double)*p->coeffs[i]; return OK; } /* izfilter - initialize z-plane controllable filter */ static int izfilter(CSOUND *csound, ZFILTER *p) { fcomplex a[MAXPOLES]; fcomplex *roots; double *coeffs; int i, dim; /* since i-time arguments are not guaranteed to propagate to p-time * we must copy the i-vars into the p structure. */ p->numa = (int)*p->na; p->numb = (int)*p->nb; /* First check bounds on initialization arguments */ if (UNLIKELY((p->numb<1) || (p->numb>(MAXZEROS+1)) || (p->numa<0) || (p->numa>MAXPOLES))) return csound->InitError(csound, Str("Filter order out of bounds: " "(1 <= nb < 51, 0 <= na <= 50)")); /* Calculate the total delay in samples and allocate memory for it */ p->ndelay = MAX(p->numb-1,p->numa); csound->AuxAlloc(csound, p->ndelay * sizeof(double), &p->delay); /* Set current position pointer to beginning of delay */ p->currPos = (double*)p->delay.auxp; for (i=0; inumb+p->numa; i++) p->dcoeffs[i] = (double)*p->coeffs[i]; /* Add auxillary root memory */ csound->AuxAlloc(csound, p->numa * sizeof(fcomplex), &p->roots); roots = (fcomplex*) p->roots.auxp; dim = p->numa; coeffs = p->dcoeffs + p->numb; /* Reverse coefficient order for root finding */ a[dim] = Complex(1.0,0.0); for (i=dim-1; i>=0; i--) a[i] = Complex(coeffs[dim-i-1],0.0); /* NRIC root finding routine, a[0..M] roots[1..M] */ zroots(csound, a, dim, roots-1/*POLEISH*/); /* Sort roots into descending order of magnitudes */ sortRoots(roots, dim); return OK; } /* a-rate filter routine * * Implements the following difference equation * * (1)*y(n) = b(0)*x(n) + b(1)*x(n-1) + ... + b(nb)*x(n-nb) * - a(1)*y(n-1) - ... - a(na)*y(n-na) * */ static int afilter(CSOUND *csound, FILTER* p) { int i; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; double* a = p->dcoeffs+p->numb; double* b = p->dcoeffs+1; double b0 = p->dcoeffs[0]; double poleSamp, zeroSamp, inSamp; /* Outer loop */ if (UNLIKELY(offset)) memset(p->out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nin[n]; poleSamp = inSamp; zeroSamp = 0.0; /* Inner filter loop */ for (i=0; i< p->ndelay; i++) { /* Do poles first */ /* Sum of products of a's and delays */ if (inuma) poleSamp += -(a[i])*readFilter(p,i+1); /* Now do the zeros */ if (i<(p->numb-1)) zeroSamp += (b[i])*readFilter(p,i+1); } p->out[n] = (MYFLT)((b0)*poleSamp + zeroSamp); /* update filter delay line */ insertFilter(p, poleSamp); } return OK; } /* k-rate filter routine * * Implements the following difference equation at the k rate * * (1)*y(k) = b(0)*x(k) + b(1)*x(k-1) + ... + b(nb)*x(k-nb) * - a(1)*y(k-1) - ... - a(na)*y(k-na) * */ static int kfilter(CSOUND *csound, FILTER* p) { int i; double* a = p->dcoeffs+p->numb; double* b = p->dcoeffs+1; double b0 = p->dcoeffs[0]; double poleSamp, zeroSamp, inSamp; inSamp = *p->in; poleSamp = inSamp; zeroSamp = 0.0; /* Filter loop */ for (i=0; indelay; i++) { /* Do poles first */ /* Sum of products of a's and delays */ if (inuma) poleSamp += -(a[i])*readFilter(p,i+1); /* Now do the zeros */ if (i<(p->numb-1)) zeroSamp += (b[i])*readFilter(p,i+1); } *p->out = (MYFLT)((b0)*poleSamp + zeroSamp); /* update filter delay line */ insertFilter(p, poleSamp); return OK; } /* azfilter - a-rate controllable pole filter * * This filter allows control over the magnitude * and frequency response of the filter by efficient * manipulation of the poles. * * The k-rate controls are: * * kmag, kfreq * * The rest of the filter is the same as filter * */ static int azfilter(CSOUND *csound, ZFILTER* p) { int i; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; double* a = p->dcoeffs+p->numb; double* b = p->dcoeffs+1; double b0 = p->dcoeffs[0]; double poleSamp, zeroSamp, inSamp; fpolar B[MAXPOLES]; fcomplex C[MAXPOLES+1]; fcomplex *roots = (fcomplex*) p->roots.auxp; double kmagf = *p->kmagf; /* Mag nudge factor */ double kphsf = *p->kphsf; /* Phs nudge factor */ int dim = p->numa; /* Nudge pole magnitudes */ complex2polar(roots,B,dim); nudgeMags(B,roots,dim,kmagf); nudgePhases(B,roots,dim,kphsf); polar2complex(B,C,dim); expandPoly(C,a,dim); /* C now contains the complex roots of the nudged filter */ /* and a contains their associated real coefficients. */ /* Outer loop */ if (UNLIKELY(offset)) memset(p->out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nin[n]; poleSamp = inSamp; zeroSamp = 0.0; /* Inner filter loop */ for (i=0; i< p->ndelay; i++) { /* Do poles first */ /* Sum of products of a's and delays */ if (inuma) poleSamp += -(a[i])*readFilter((FILTER*)p,i+1); /* Now do the zeros */ if (i<(p->numb-1)) zeroSamp += (b[i])*readFilter((FILTER*)p,i+1); } p->out[n] = (MYFLT)((b0)*poleSamp + zeroSamp); /* update filter delay line */ insertFilter((FILTER*)p, poleSamp); } return OK; } /* readFilter -- delay-line access routine * * Reads sample x[n-i] from a previously established delay line. * With this syntax i is +ve for a time delay and -ve for a time advance. * * The use of explicit indexing rather than implicit index incrementing * allows multiple lattice structures to access the same delay line. * */ static double readFilter(FILTER* p, int i) { double* readPoint; /* Generic pointer address */ /* Calculate the address of the index for this read */ readPoint = p->currPos - i; /* Wrap around for time-delay if necessary */ if (readPoint < ((double*)p->delay.auxp) ) readPoint += p->ndelay; else /* Wrap for time-advance if necessary */ if (readPoint > ((double*)p->delay.auxp + (p->ndelay-1)) ) readPoint -= p->ndelay; return *readPoint; /* Dereference read address for delayed value */ } /* insertFilter -- delay-line update routine * * Inserts the passed value into the currPos and increments the * currPos pointer modulo the length of the delay line. * */ static void insertFilter(FILTER* p, double val) { /* Insert the passed value into the delay line */ *p->currPos = val; /* Update the currPos pointer and wrap modulo the delay length */ if (((double*) (++p->currPos)) > ((double*)p->delay.auxp + (p->ndelay-1)) ) p->currPos -= p->ndelay; } /* Compute polynomial coefficients from the roots */ /* The expanded polynomial is computed as a[0..N] in * descending powers of Z */ static void expandPoly(fcomplex roots[], double a[], int dim) { int j,k; fcomplex z[MAXPOLES],d[MAXPOLES]; z[0] = Complex(1.0, 0.0); for (j=1;j<=dim;j++) z[j] = Complex(0.0,0.0); /* Recursive coefficient expansion about the roots of A(Z) */ for (j=0;jmagmag) return 1; else if (a->mag==b->mag) return 0; else return -1; } /* nudgeMags - Pole magnitude nudging routine * * Find the largest-magnitude pole off the real axis * and nudge all non-real poles by a factor of the distance * of the largest pole to the unit circle (or zero if fact is -ve). * * This has the effect of changing the time-response of the filter * without affecting the overall frequency response characteristic. * */ static void nudgeMags(fpolar a[], fcomplex b[], int dim, double fact) { double eps = .000001; /* To avoid underflow comparisons */ double nudgefact; int i; /* Check range of nudge factor */ if (fact>0 && fact<=1) { /* The largest magnitude pole will be at the beginning of * the array since it was previously sorted by the init routine. */ for (i=0;ieps) /* Check if pole is complex */ break; nudgefact = 1 + (1/a[i].mag-1)*fact; /* Nudge all complex-pole magnitudes by this factor */ for (i=dim-1;i>=0;i--) if (fabs(b[i].i)>eps) a[i].mag *= nudgefact; } else if (fact < 0 && fact >=-1) { nudgefact = (fact + 1); /* Nudge all complex-pole magnitudes by this factor */ for (i=dim-1;i>=0;i--) if (fabs(b[i].i)>eps) a[i].mag *= nudgefact; } else { /* Factor is out of range, do nothing */ } } /* nudgePhases - Pole phase nudging routine * * Multiply phases of all poles by factor */ static void nudgePhases(fpolar a[], fcomplex b[], int dim, double fact) { double eps = .000001; /* To avoid underflow comparisons */ double nudgefact; int i; double phmax=0.0; /* Check range of nudge factor */ if (fact>0 && fact<=1) { /* Find the largest angled non-real pole */ for (i=0;iphmax) phmax = a[i].ph; phmax /= PI; /* Normalize to radian frequency */ nudgefact = 1 + (1-phmax)*fact; /* Nudge all complex-pole magnitudes by this factor */ for (i=dim-1;i>=0;i--) if (fabs(b[i].i)>eps) a[i].ph *= nudgefact; } else if (fact < 0 && fact >=-1) { nudgefact = (fact + 1); /* Nudge all complex-pole magnitudes by this factor */ for (i=dim-1;i>=0;i--) if (fabs(b[i].i)>eps) a[i].ph *= nudgefact; } else { /* Factor is out of range, do nothing */ } } /* ------------------------------------------------------------ */ /* Code from Press, Teukolsky, Vettering and Flannery * Numerical Recipes in C, 2nd Edition, Cambridge 1992. */ #define EPSS (1.0e-7) #define MR (8) #define MT (10) #define MAXIT (MT*MR) /* Simple definition is sufficient */ #define FPMAX(a,b) (a>b ? a : b) static void laguer(CSOUND *csound, fcomplex a[], int m, fcomplex *x, int *its) { int iter,j; double abx,abp,abm,err; fcomplex dx,x1,b,d,f,g,h,sq,gp,gm,g2; static const double frac[MR+1] = {0.0,0.5,0.25,0.75,0.13,0.38,0.62,0.88,1.0}; for (iter=1; iter<=MAXIT; iter++) { *its = iter; b = a[m]; err = Cabs(b); d = f = Complex(0.0,0.0); abx = Cabs(*x); for (j=m-1; j>=0; j--) { f = Cadd(Cmul(*x,f),d); d = Cadd(Cmul(*x,d),b); b = Cadd(Cmul(*x,b),a[j]); err = Cabs(b)+abx*err; } err *= (double)EPSS; if (Cabs(b) <= err) return; g = Cdiv(d,b); g2 = Cmul(g,g); h = Csub(g2,RCmul(2.0,Cdiv(f,b))); sq = Csqrt(RCmul((double) (m-1),Csub(RCmul((double) m,h),g2))); gp = Cadd(g,sq); gm = Csub(g,sq); abp = Cabs(gp); abm = Cabs(gm); if (abp < abm) gp = gm; dx = ((FPMAX(abp,abm) > 0.0 ? Cdiv(Complex((double) m,0.0),gp) : RCmul(exp(log(1.0+abx)), Complex(cos((double)iter), sin((double)iter))))); x1 = Csub(*x,dx); if (x->r == x1.r && x->i == x1.i) return; if (iter % MT) *x = x1; else *x = Csub(*x,RCmul(frac[iter/MT],dx)); } csound->Warning(csound, Str("too many iterations in laguer")); return; } #undef EPSS #undef MR #undef MT #undef MAXIT /* (C) Copr. 1986-92 Numerical Recipes Software *%&&"U^3. */ /* ------------------------------------------------------------ */ /* Code from Press, Teukolsky, Vettering and Flannery * Numerical Recipes in C, 2nd Edition, Cambridge 1992. */ #define EPS (2.0e-6) #define MAXM (100) static void zroots(CSOUND *csound,fcomplex a[], int m, fcomplex roots[]) { int i,its,j,jj; fcomplex x,b,c,ad[MAXM]; for (j=0; j<=m; j++) ad[j] = a[j]; for (j=m; j>=1; j--) { x = Complex(0.0,0.0); laguer(csound,ad,j,&x,&its); if (fabs(x.i) <= 2.0*EPS*fabs(x.r)) x.i = 0.0; roots[j] = x; b = ad[j]; for (jj=j-1; jj>=0; jj--) { c = ad[jj]; ad[jj] = b; b = Cadd(Cmul(x,b),c); } } /* if (poleish) */ for (j=1; j<=m; j++) laguer(csound,a,m,&roots[j],&its); for (j=2; j<=m; j++) { x = roots[j]; for (i=j-1; i>=1; i--) { if (roots[i].r <= x.r) break; roots[i+1] = roots[i]; } roots[i+1] = x; } } #undef EPS #undef MAXM /* (C) Copr. 1986-92 Numerical Recipes Software *%&&"U^3. */ /* Code from Press, Teukolsky, Vettering and Flannery * Numerical Recipes in C, 2nd Edition, Cambridge 1992. */ static fcomplex Cadd(fcomplex a, fcomplex b) { fcomplex c; c.r = a.r+b.r; c.i = a.i+b.i; return c; } static fcomplex Csub(fcomplex a, fcomplex b) { fcomplex c; c.r = a.r-b.r; c.i = a.i-b.i; return c; } static fcomplex Cmul(fcomplex a, fcomplex b) { fcomplex c; c.r = a.r*b.r-a.i*b.i; c.i = a.i*b.r+a.r*b.i; return c; } static fcomplex Complex(double re, double im) { fcomplex c; c.r = re; c.i = im; return c; } /* fcomplex Conjg(fcomplex z) */ /* { */ /* fcomplex c; */ /* c.r = z.r; */ /* c.i = -z.i; */ /* return c; */ /* } */ static fcomplex Cdiv(fcomplex a, fcomplex b) { fcomplex c; double r,den; if (fabs(b.r) >= fabs(b.i)) { r = b.i/b.r; den = b.r+r*b.i; c.r = (a.r+r*a.i)/den; c.i = (a.i-r*a.r)/den; } else { r = b.r/b.i; den = b.i+r*b.r; c.r = (a.r*r+a.i)/den; c.i = (a.i*r-a.r)/den; } return c; } static double Cabs(fcomplex z) { double x,y,ans; double temp; x = fabs(z.r); y = fabs(z.i); if (x == 0.0) ans = y; else if (y == 0.0) ans = x; else if (x > y) { temp = (y/x); ans = x*sqrt(1.0+temp*temp); } else { temp = (x/y); ans = y*sqrt(1.0+temp*temp); } return ans; } static fcomplex Csqrt(fcomplex z) { fcomplex c; double w; double x,y,r; if ((z.r == 0.0) && (z.i == 0.0)) { c.r = 0.0; c.i = 0.0; return c; } else { x = fabs(z.r); y = fabs(z.i); if (x >= y) { r = y/x; w = sqrt(x)*sqrt(0.5*(1.0+sqrt(1.0+r*r))); } else { r = x/y; w = sqrt(y)*sqrt(0.5*(r+sqrt(1.0+r*r))); } if (z.r >= 0.0) { c.r = w; c.i = z.i/(2.0*w); } else { c.i = (z.i >= 0.0) ? w : -w; c.r = z.i/(2.0*c.i); } return c; } } static fcomplex RCmul(double x, fcomplex a) { fcomplex c; c.r = x*a.r; c.i = x*a.i; return c; } #define S(x) sizeof(x) static OENTRY localops[] = { { "filter2",0xffff, }, { "filter2.a", S(FILTER), 0, 5, "a", "aiim", (SUBR)ifilter, NULL, (SUBR)afilter}, { "filter2.k", S(FILTER), 0, 3, "k", "kiim", (SUBR)ifilter, (SUBR)kfilter,NULL }, { "zfilter2", S(ZFILTER), 0, 5, "a", "akkiim", (SUBR)izfilter, NULL, (SUBR)azfilter} }; int filter_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/filter.h000066400000000000000000000050401321653344700161320ustar00rootroot00000000000000/* filter.h: Copyright (C) 1997 Michael A. Casey, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* filter.h */ /* Author: Michael A. Casey * Language: C * Copyright (C) 1997 Michael A. Casey, MIT Media Lab, All Rights Reserved * */ #ifndef __filter_h #define __filter_h #define MAXZEROS 50 /* Allow up to 50th-order digital filters */ #define MAXPOLES 50 /* Csound structure for FILTER opcode */ typedef struct { OPDS h; MYFLT *out; /* output signal */ MYFLT *in; /* input signal */ MYFLT *nb, *na; /* filter-order input arguments */ MYFLT *coeffs[MAXPOLES+MAXZEROS+1]; /* filter-coefficient input arguments */ MYFLT *d1,*d2; /* These allow ZFILTER to access FILTER routines */ int numa; /* i-var p-time storage registers */ int numb; double dcoeffs[MAXPOLES+MAXZEROS+1]; /* filter-coefficient double arguments */ AUXCH delay; /* delay-line state memory base pointer */ double* currPos; /* delay-line current position pointer */ /* >>Was float<< */ int ndelay; /* length of delay line (i.e. filter order) */ } FILTER; typedef struct { OPDS h; MYFLT *out; /* output signal */ MYFLT *in; /* input signal */ MYFLT *kmagf, *kphsf; /* magnitude and phase pole nudging factors */ MYFLT *nb, *na; /* filter-order input arguments */ MYFLT *coeffs[MAXPOLES+MAXZEROS+1]; /* filter-coefficient input arguments */ int numa; /* i-var p-time storage registers */ int numb; double dcoeffs[MAXPOLES+MAXZEROS+1]; /* filter-coefficient double arguments */ AUXCH delay; /* delay-line state memory base pointer */ double* currPos; /* delay-line current position pointer */ /* >>Was float<< */ int ndelay; /* length of delay line (i.e. filter order) */ AUXCH roots; /* pole roots memory for zfilter */ } ZFILTER; #endif csound-6.10.0/Opcodes/flanger.c000066400000000000000000000307241321653344700162650ustar00rootroot00000000000000/* flanger.c: Copyright (C) 1998 Gabriel Maldonado, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "stdopcod.h" /* Flanger by Maldonado, with coding enhancements by JPff -- July 1998 */ #include #include "flanger.h" static int flanger_set (CSOUND *csound, FLANGER *p) { /*---------------- delay -----------------------*/ p->maxdelay = (uint32)(*p->maxd * CS_ESR); csound->AuxAlloc(csound, p->maxdelay * sizeof(MYFLT), &p->aux); p->left = 0; p->yt1 = FL(0.0); p->fmaxd = (MYFLT) p->maxdelay; return OK; } static int flanger(CSOUND *csound, FLANGER *p) { /*---------------- delay -----------------------*/ uint32 indx = p->left; MYFLT *out = p->ar; /* assign object data to local variables */ MYFLT *in = p->asig; MYFLT maxdelay = p->fmaxd, maxdelayM1 = maxdelay-1; MYFLT *buf = (MYFLT *)p->aux.auxp; MYFLT *freq_del = p->xdel; MYFLT feedback = *p->kfeedback; MYFLT fv1; int32 v2; int32 v1; MYFLT yt1= p->yt1; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; n= maxdelay) fv1 -= maxdelay; /* Is this necessary? JPff */ v1 = (int32)fv1; v2 = (fv1 < maxdelayM1)? v1+1 : 0; /*Find next sample for interpolation*/ out[n] = yt1 = buf[v1] + (fv1 - v1) * ( buf[v2] - buf[v1]); if (UNLIKELY(++indx == maxdelay)) indx = 0; /* Advance current pointer */ } p->left = indx; p->yt1 = yt1; return OK; } #define MAXDELAY 0.2 /* 5 Hz */ static int wguide1set (CSOUND *csound, WGUIDE1 *p) { /*---------------- delay -----------------------*/ p->maxd = (uint32) (MAXDELAY * CS_ESR); csound->AuxAlloc(csound, p->maxd * sizeof(MYFLT), &p->aux); p->left = 0; /*---------------- filter -----------------------*/ p->c1 = p->prvhp = FL(0.0); p->c2 = FL(1.0); p->yt1 = FL(0.0); p->xdelcod = IS_ASIG_ARG(p->xdel) ? 1 : 0; return OK; } static int wguide1(CSOUND *csound, WGUIDE1 *p) { /*---------------- delay -----------------------*/ uint32 indx; MYFLT *out = p->ar; /* assign object data to local variables */ MYFLT *in = p->asig; MYFLT *buf = (MYFLT *)p->aux.auxp; MYFLT *freq_del = p->xdel; /*(1 / *p->xdel) * CS_ESR; */ MYFLT feedback = *p->kfeedback; MYFLT fv1, fv2, out_delay,bufv1 ; unsigned int maxdM1 = p->maxd-1; int32 v1; /*---------------- filter -----------------------*/ MYFLT c1, c2, yt1 = p->yt1; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; /*---------------- delay -----------------------*/ indx = p->left; /*---------------- filter -----------------------*/ if (*p->filt_khp != p->prvhp) { double b; p->prvhp = *p->filt_khp; b = 2.0 - cos((double)(p->prvhp * csound->tpidsr)); p->c2 = (MYFLT)(b - sqrt(b * b - 1.0)); p->c1 = FL(1.0) - p->c2; } c1= p->c1; c2= p->c2; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } if (p->xdelcod) { /* delay changes at audio-rate */ for (n=offset; nmaxd; } fv2 = (fv1 < maxdM1) ? fv1 + 1 : 0; /* Find next smpl for interpolation */ bufv1 = buf[v1=(int32)fv1]; out_delay = bufv1 + (fv1 - v1) * ( buf[(int32)fv2] - bufv1); if (UNLIKELY(++indx == p->maxd)) indx = 0; /* Advance current pointer */ /*---------------- filter -----------------------*/ out[n] = yt1 = c1 * out_delay + c2 * yt1; } } else { for (n=offset; nmaxd; } fv2 = (fv1 < maxdM1) ? fv1 + 1 : 0; /* Find next smpl for interpolation */ bufv1 = buf[v1=(int32)fv1]; out_delay = bufv1 + (fv1 - v1) * ( buf[(int32)fv2] - bufv1); if (UNLIKELY(++indx == p->maxd)) indx = 0; /* Advance current pointer */ /*---------------- filter -----------------------*/ out[n] = yt1 = c1 * out_delay + c2 * yt1; } } p->left = indx; p->yt1 = yt1; return OK; } static int wguide2set (CSOUND *csound, WGUIDE2 *p) { /*---------------- delay1 -----------------------*/ p->maxd = (uint32) (MAXDELAY * CS_ESR); csound->AuxAlloc(csound, p->maxd * sizeof(MYFLT), &p->aux1); p->left1 = 0; /*---------------- delay2 -----------------------*/ csound->AuxAlloc(csound, p->maxd * sizeof(MYFLT), &p->aux2); p->left2 = 0; /*---------------- filter1 -----------------------*/ p->c1_1 = p->prvhp1 = FL(0.0); p->c2_1 = FL(1.0); p->yt1_1 = FL(0.0); /*---------------- filter2 -----------------------*/ p->c1_2 = p->prvhp2 = FL(0.0); p->c2_2 = FL(1.0); p->yt1_2 = FL(0.0); p->old_out=FL(0.0); p->xdel1cod = IS_ASIG_ARG(p->xdel1) ? 1 : 0; p->xdel2cod = IS_ASIG_ARG(p->xdel2) ? 1 : 0; if (UNLIKELY(p->xdel1cod != p->xdel2cod)) return csound->InitError(csound, Str( "wguide2 xfreq1 and xfreq2 arguments must" " be both a-rate or k and i-rate")); return OK; } static int wguide2(CSOUND *csound, WGUIDE2 *p) { MYFLT *out = p->ar; MYFLT *in = p->asig; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT out1,out2, old_out = p->old_out; unsigned int maxdM1 = p->maxd-1; /*---------------- delay1 -----------------------*/ uint32 indx1; MYFLT *buf1 = (MYFLT *)p->aux1.auxp; MYFLT *freq_del1 = p->xdel1; /*(1 / *p->xdel1) * CS_ESR; */ MYFLT feedback1 = *p->kfeedback1; MYFLT fv1_1, fv2_1, out_delay1 ; int32 v1_1; /*---------------- filter1 -----------------------*/ MYFLT c1_1, c2_1, yt1_1; /*---------------- delay2 -----------------------*/ uint32 indx2; MYFLT *buf2 = (MYFLT *)p->aux2.auxp; MYFLT *freq_del2 = p->xdel2; /*(1 / *p->xdel2) * CS_ESR;*/ MYFLT feedback2 = *p->kfeedback2; MYFLT fv1_2, fv2_2, out_delay2 ; int32 v1_2; /*---------------- filter2 -----------------------*/ MYFLT c1_2, c2_2, yt1_2; /*-----------------------------------------------*/ indx1 = p->left1; indx2 = p->left2; if (*p->filt_khp1 != p->prvhp1) { double b; p->prvhp1 = *p->filt_khp1; b = 2.0 - cos((double)(p->prvhp1 * csound->tpidsr)); p->c2_1 = (MYFLT)(b - sqrt((b * b) - 1.0)); p->c1_1 = FL(1.0) - p->c2_1; } if (*p->filt_khp2 != p->prvhp2) { double b; p->prvhp2 = *p->filt_khp2; b = 2.0 - cos((double)(p->prvhp2 * csound->tpidsr)); p->c2_2 = (MYFLT)(b - sqrt((double)(b * b) - 1.0)); p->c1_2 = FL(1.0) - p->c2_2; } c1_1= p->c1_1; c2_1= p->c2_1; c1_2= p->c1_2; c2_2= p->c2_2; yt1_1= p->yt1_1; yt1_2= p->yt1_2; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } if (p->xdel1cod) { /* delays change at audio-rate */ for (n=offset;nmaxd; while (fv1_2 < 0) fv1_2 += p->maxd; fv2_1 = (fv1_1maxd)) indx1 = 0; /* Advance current pointer */ if (UNLIKELY(++indx2 == p->maxd)) indx2 = 0; /* Advance current pointer */ out1 = yt1_1 = c1_1 * out_delay1 + c2_1 * yt1_1; out2 = yt1_2 = c1_2 * out_delay2 + c2_2 * yt1_2; out[n] = old_out = out1 + out2; } } else { for (n=offset; nmaxd; while (fv1_2 < 0) fv1_2 += p->maxd; fv2_1 = (fv1_1maxd)) indx1 = 0; /* Advance current pointer */ if (UNLIKELY(++indx2 == p->maxd)) indx2 = 0; /* Advance current pointer */ out1 = yt1_1 = c1_1 * out_delay1 + c2_1 * yt1_1; out2 = yt1_2 = c1_2 * out_delay2 + c2_2 * yt1_2; out[n] = old_out = out1 + out2; } } p->left1 = indx1; p->left2 = indx2; p->old_out = old_out; p->yt1_1 = yt1_1; p->yt1_2 = yt1_2; return OK; } #define S(x) sizeof(x) static OENTRY localops[] = { { "flanger", S(FLANGER), 0, 5, "a", "aakv", (SUBR)flanger_set, NULL, (SUBR)flanger }, { "wguide1", S(WGUIDE1), 0, 5, "a", "axkk",(SUBR) wguide1set, NULL, (SUBR)wguide1 }, { "wguide2", S(WGUIDE2), 0, 5, "a", "axxkkkk",(SUBR)wguide2set, NULL, (SUBR)wguide2 } }; int flanger_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/flanger.h000066400000000000000000000036531321653344700162730ustar00rootroot00000000000000/* flanger.h: Copyright (C) 1998 Gabriel Maldonado, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ typedef struct { OPDS h; MYFLT *ar, *asig, *xdel, *kfeedback, *maxd; MYFLT yt1; /* filter instance variables */ AUXCH aux; /* delay instance variables */ int32 left; uint32 maxdelay; MYFLT fmaxd; } FLANGER; typedef struct { OPDS h; MYFLT *ar, *asig, *xdel, *filt_khp, *kfeedback; MYFLT c1, c2, yt1, prvhp; /* filter instance variables */ AUXCH aux; /* delay instance variables */ uint32 maxd; int32 left; int16 xdelcod; } WGUIDE1; typedef struct { OPDS h; MYFLT *ar, *asig, *xdel1, *xdel2, *filt_khp1; MYFLT *filt_khp2, *kfeedback1, *kfeedback2; MYFLT c1_1, c2_1, yt1_1, prvhp1; /* filter1 instance variables */ MYFLT c1_2, c2_2, yt1_2, prvhp2; /* filter1 instance variables */ AUXCH aux1; /* delay1 instance variables */ int32 left1; AUXCH aux2; /* delay1 instance variables */ int32 left2; uint32 maxd; MYFLT old_out; int16 xdel1cod, xdel2cod; } WGUIDE2; csound-6.10.0/Opcodes/fluidOpcodes/000077500000000000000000000000001321653344700171155ustar00rootroot00000000000000csound-6.10.0/Opcodes/fluidOpcodes/fluidOpcodes.cpp000066400000000000000000000744231321653344700222530ustar00rootroot00000000000000/** * FLUID SYNTH OPCODES * * Adapts Fluidsynth to use global engines, soundFonts, and outputs * * Based on work by Michael Gogins and Steven Yi. License is identical to * SOUNDFONTS VST License (listed below) * * Copyright (c) 2003 by Steven Yi. All rights reserved. * * [ORIGINAL INFORMATION BELOW] * * S O U N D F O N T S V S T * * Adapts Fluidsynth to be both a VST plugin instrument * and a Csound plugin opcode. * Copyright (c) 2001-2003 by Michael Gogins. All rights reserved. * * L I C E N S E * * This software is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include "csdl.h" #include "OpcodeBase.hpp" #include using namespace csound; /** * Template union for safely and efficiently * typecasting the value of a MYFLT variable * to the address of an array, and vice versa. */ template struct AddressCaster { union { A *a; F f; }; }; /** * Safely and efficiently typecast an address * to the value of a MYFLT variable. */ template void tof(A *a, F *f) { AddressCaster addressCaster; addressCaster.a = a; *f = addressCaster.f; }; /** * Safely and efficiently typecast the value * of a MYFLT variable to an address. */ template void toa(F *f, A *&a) { AddressCaster addressCaster; addressCaster.f = *f; a = addressCaster.a; }; class FluidEngine : public OpcodeBase { // Outputs. MYFLT *iFluidSynth; // Inputs. MYFLT *iChorusEnabled; MYFLT *iReverbEnabled; MYFLT *iChannelCount; MYFLT *iVoiceCount; // State. //fluid_synth_t *fluidSynth; //fluid_settings_t *fluidSettings; int chorusEnabled; int reverbEnabled; int channelCount; int voiceCount; void *mutex; public: int init(CSOUND *csound) { mutex = csound->Create_Mutex(0); LockGuard guard(csound, mutex); int result = OK; fluid_synth_t *fluidSynth = 0; fluid_settings_t *fluidSettings = 0; chorusEnabled = (int) *iChorusEnabled; reverbEnabled = (int) *iReverbEnabled; channelCount = (int) *iChannelCount; voiceCount = (int) *iVoiceCount; if (channelCount <= 0) { channelCount = 256; } else if (channelCount < 16) { channelCount = 16; } else if (channelCount > 256) { channelCount = 256; } if (voiceCount <= 0) { voiceCount = 4096; } else if (voiceCount < 16) { voiceCount = 16; } else if (voiceCount > 4096) { voiceCount = 4096; } fluidSettings = new_fluid_settings(); if (fluidSettings != NULL) { fluid_settings_setnum(fluidSettings, (char *)"synth.sample-rate", (double) csound->GetSr(csound)); fluid_settings_setint(fluidSettings, (char *)"synth.midi-channels", channelCount); fluid_settings_setint(fluidSettings, (char *)"synth.polyphony", voiceCount); fluidSynth = new_fluid_synth(fluidSettings); } if (!fluidSynth) { if (fluidSettings) { delete_fluid_settings(fluidSettings); } result = csound->InitError(csound, Str("error allocating fluid engine\n")); } else { fluid_synth_set_chorus_on(fluidSynth, chorusEnabled); fluid_synth_set_reverb_on(fluidSynth, reverbEnabled); log(csound, "Created fluidEngine 0x%p with sampling rate = %f, " "chorus %s, reverb %s, channels %d, voices %d.\n", fluidSynth, (double) csound->GetSr(csound), chorusEnabled ? "on" : "off", reverbEnabled ? "on" : "off", channelCount, voiceCount); tof(fluidSynth, iFluidSynth); { void *fluid_synths_mutex = 0; csound::QueryGlobalPointer(csound, "fluid_synths_mutex", fluid_synths_mutex); LockGuard synthsGuard(csound, fluid_synths_mutex); std::vector *fluid_synths = 0; csound::QueryGlobalPointer(csound, "fluid_synths", fluid_synths); fluid_synths->push_back(fluidSynth); } } return result; } }; class FluidLoad : public OpcodeBase { // Outputs. MYFLT *iInstrumentNumber; // Inputs. MYFLT *iFilename; MYFLT *iFluidSynth; MYFLT *iListPresets; // State. char *filename; char *filepath; fluid_synth_t *fluidSynth; int soundFontId; int listPresets; void *mutex; public: int init(CSOUND *csound) { mutex = csound->Create_Mutex(0); LockGuard guard(csound, mutex); int result = OK; soundFontId = -1; toa(iFluidSynth, fluidSynth); listPresets = (int) *iListPresets; CS_TYPE *argType = csound->GetTypeForArg(iFilename); if (strcmp("S", argType->varTypeName) == 0) { filename = csound->Strdup(csound, ((STRINGDAT *)iFilename)->data); } else filename = csound->strarg2name(csound, (char *) NULL, (std::isnan(*iFilename) ? csound->GetString(csound, *iFilename) : (char *) iFilename), (char *)"fluid.sf2.", std::isnan(*iFilename)); filepath = csound->FindInputFile(csound, filename, "SFDIR;SSDIR"); if (filepath && fluid_is_soundfont(filepath)) { log(csound, "Loading SoundFont : %s.\n", filepath); soundFontId = fluid_synth_sfload(fluidSynth, filepath, 0); log(csound, "fluidSynth: 0x%p soundFontId: %d.\n", fluidSynth, soundFontId); } *iInstrumentNumber = (MYFLT) soundFontId; if (UNLIKELY(soundFontId < 0)) { return csound->InitError(csound, Str("fluid: unable to load %s"), filename); } csound->NotifyFileOpened(csound, filepath, CSFTYPE_SOUNDFONT, 0, 0); if (soundFontId < 0) { result = NOTOK; } else if (listPresets) { fluid_sfont_t *fluidSoundfont = fluid_synth_get_sfont_by_id(fluidSynth, soundFontId); fluid_preset_t fluidPreset; fluidSoundfont->iteration_start(fluidSoundfont); OPARMS oparms; csound->GetOParms(csound, &oparms); if (oparms.msglevel & 0x7) while (fluidSoundfont->iteration_next(fluidSoundfont, &fluidPreset)) { log(csound, "SoundFont: %3d Bank: %3d Preset: %3d %s\n", soundFontId, fluidPreset.get_banknum(&fluidPreset), fluidPreset.get_num(&fluidPreset), fluidPreset.get_name(&fluidPreset)); } } return result; } }; class FluidProgramSelect : public OpcodeBase { // Inputs. MYFLT *iFluidSynth; MYFLT *iChannelNumber; MYFLT *iInstrumentNumber; MYFLT *iBankNumber; MYFLT *iPresetNumber; // State. fluid_synth_t *fluidSynth; int channel; unsigned int instrument; unsigned int bank; unsigned int preset; void *mutex; public: int init(CSOUND *csound) { mutex = csound->Create_Mutex(0); LockGuard guard(csound, mutex); toa(iFluidSynth, fluidSynth); channel = (int) *iChannelNumber; instrument = (unsigned int) *iInstrumentNumber; bank = (unsigned int) *iBankNumber; preset = (unsigned int) *iPresetNumber; fluid_synth_program_select(fluidSynth, channel, instrument, bank, preset); return OK; } }; class FluidCCI : public OpcodeBase { // Inputs. MYFLT *iFluidSynth; MYFLT *iChannelNumber; MYFLT *iControllerNumber; MYFLT *kVal; // State. fluid_synth_t *fluidSynth; int channel; int controller; int value; void *mutex; public: int init(CSOUND *csound) { mutex = csound->Create_Mutex(0); LockGuard guard(csound, mutex); toa(iFluidSynth, fluidSynth); channel = (int) *iChannelNumber; controller = (int) *iControllerNumber; value = (int) *kVal; fluid_synth_cc(fluidSynth, channel, controller, value); return OK; } }; class FluidCCK : public OpcodeBase { // Inputs. MYFLT *iFluidSynth; MYFLT *iChannelNumber; MYFLT *iControllerNumber; MYFLT *kVal; // State. fluid_synth_t *fluidSynth; int channel; int controller; int value; int priorValue; void *mutex; public: int init(CSOUND *csound) { mutex = csound->Create_Mutex(0); LockGuard guard(csound, mutex); toa(iFluidSynth, fluidSynth); priorValue = -1; return OK; } int kontrol(CSOUND *csound) { LockGuard guard(csound, mutex); value = (int) *kVal; if (value != priorValue) { priorValue = value; channel = (int) *iChannelNumber; controller = (int) *iControllerNumber; fluid_synth_cc(fluidSynth, channel, controller, value); } return OK; } }; class FluidNote : public OpcodeNoteoffBase { // Inputs. MYFLT *iFluidSynth; MYFLT *iChannelNumber; MYFLT *iMidiKeyNumber; MYFLT *iVelocity; // State. fluid_synth_t *fluidSynth; int channel; int key; int velocity; void *mutex; public: int init(CSOUND *csound) { mutex = csound->Create_Mutex(0); LockGuard guard(csound, mutex); toa(iFluidSynth, fluidSynth); channel = (int) *iChannelNumber; key = (int) *iMidiKeyNumber; velocity = (int) *iVelocity; fluid_synth_noteon(fluidSynth, channel, key, velocity); return OK; } int noteoff(CSOUND *csound) { LockGuard guard(csound, mutex); fluid_synth_noteoff(fluidSynth, channel, key); return OK; } }; class FluidOut : public OpcodeBase { // Outputs. MYFLT *aLeftOut; MYFLT *aRightOut; // Inputs. MYFLT *iFluidSynth; // State. fluid_synth_t *fluidSynth; float leftSample; float rightSample; int frame; int ksmps; void *mutex; public: int init(CSOUND *csound) { mutex = csound->Create_Mutex(0); LockGuard guard(csound, mutex); toa(iFluidSynth, fluidSynth); ksmps = opds.insdshead->ksmps; return OK; } int audio(CSOUND *csound) { LockGuard guard(csound, mutex); uint32_t offset = opds.insdshead->ksmps_offset; uint32_t early = opds.insdshead->ksmps_no_end; if (UNLIKELY(offset)) { memset(aLeftOut, '\0', offset*sizeof(MYFLT)); memset(aRightOut, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { ksmps -= early; memset(&aLeftOut[ksmps], '\0', early*sizeof(MYFLT)); memset(&aRightOut[ksmps], '\0', early*sizeof(MYFLT)); } for (frame = offset; frame < ksmps; frame++) { leftSample = 0.0f; rightSample = 0.0f; fluid_synth_write_float(fluidSynth, 1, &leftSample, 0, 1, &rightSample, 0, 1); aLeftOut[frame] = leftSample /* * csound->e0dbfs */; aRightOut[frame] = rightSample /* * csound->e0dbfs */; } return OK; } }; class FluidAllOut : public OpcodeBase { // Outputs. MYFLT *aLeftOut; MYFLT *aRightOut; // State. float leftSample; float rightSample; int frame; int ksmps; void *mutex; public: int init(CSOUND *csound) { mutex = csound->Create_Mutex(0); LockGuard guard(csound, mutex); ksmps = opds.insdshead->ksmps; return OK; } int audio(CSOUND *csound) { LockGuard guard(csound, mutex); uint32_t offset = opds.insdshead->ksmps_offset; uint32_t early = opds.insdshead->ksmps_no_end; if (UNLIKELY(offset)) { memset(aLeftOut, '\0', offset*sizeof(MYFLT)); memset(aRightOut, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { ksmps -= early; memset(&aLeftOut[ksmps], '\0', early*sizeof(MYFLT)); memset(&aRightOut[ksmps], '\0', early*sizeof(MYFLT)); } std::vector *fluid_synths = 0; csound::QueryGlobalPointer(csound, "fluid_synths", fluid_synths); void *fluid_synths_mutex = 0; csound::QueryGlobalPointer(csound, "fluid_synths_mutex", fluid_synths_mutex); LockGuard synthsGuard(csound, fluid_synths_mutex); for (frame = offset; frame < ksmps; frame++) { aLeftOut[frame] = FL(0.0); aRightOut[frame] = FL(0.0); for (size_t i = 0, n = fluid_synths->size(); i < n; i++) { fluid_synth_t *fluidSynth = (*fluid_synths)[i]; leftSample = FL(0.0); rightSample = FL(0.0); fluid_synth_write_float(fluidSynth, 1, &leftSample, 0, 1, &rightSample, 0, 1); aLeftOut[frame] += (MYFLT) leftSample /* * csound->e0dbfs */; aRightOut[frame] += (MYFLT) rightSample /* * csound->e0dbfs */; } } return OK; } }; class FluidControl : public OpcodeBase { // Inputs. MYFLT *iFluidSynth; MYFLT *kMidiStatus; MYFLT *kMidiChannel; MYFLT *kMidiData1; MYFLT *kMidiData2; // State. fluid_synth_t *fluidSynth; int midiStatus; int midiChannel; int midiData1; int midiData2; int priorMidiStatus; int priorMidiChannel; int priorMidiData1; int priorMidiData2; int printMsgs; void *mutex; public: int init(CSOUND *csound) { mutex = csound->Create_Mutex(0); LockGuard guard(csound, mutex); toa(iFluidSynth, fluidSynth); priorMidiStatus = -1; priorMidiChannel = -1; priorMidiData1 = -1; priorMidiData2 = -1; OPARMS oparms; csound->GetOParms(csound, &oparms); printMsgs = ((oparms.msglevel & 7) == 7 ? 1 : 0); return OK; } int kontrol(CSOUND *csound) { LockGuard guard(csound, mutex); midiStatus = 0xF0 & (int) *kMidiStatus; midiChannel = (int) *kMidiChannel; midiData1 = (int) *kMidiData1; midiData2 = (int) *kMidiData2; int result = -1; if (midiData2 != priorMidiData2 || midiData1 != priorMidiData1 || midiChannel != priorMidiChannel || midiStatus != priorMidiStatus) { switch (midiStatus) { case (int) 0x80: noteOff: result = fluid_synth_noteoff(fluidSynth, midiChannel, midiData1); if (printMsgs) csound->Message(csound, Str("result: %d \n Note off: c:%3d k:%3d\n"), result, midiChannel, midiData1); break; case (int) 0x90: if (!midiData2) { goto noteOff; } result = fluid_synth_noteon(fluidSynth, midiChannel, midiData1, midiData2); if (printMsgs) log(csound, "result: %d \nNote on: c:%3d k:%3d v:%3d\n",result, midiChannel, midiData1, midiData2); break; case (int) 0xA0: if (printMsgs) log(csound, "Key pressure (not handled): " "c:%3d k:%3d v:%3d\n", midiChannel, midiData1, midiData2); break; case (int) 0xB0: result = fluid_synth_cc(fluidSynth, midiChannel, midiData1, midiData2); if (printMsgs) log(csound, "Result: %d Control change: c:%3d c:%3d v:%3d\n",result, midiChannel, midiData1, midiData2); break; case (int) 0xC0: result = fluid_synth_program_change(fluidSynth, midiChannel, midiData1); if (printMsgs) log(csound, "Result: %d Program change: c:%3d p:%3d\n",result, midiChannel, midiData1); break; case (int) 0xD0: if (printMsgs) log(csound, "After touch (not handled): c:%3d v:%3d\n", midiChannel, midiData1); break; case (int) 0xE0: { int pbVal = midiData1 + (midiData2 << 7); fluid_synth_pitch_bend(fluidSynth, midiChannel, pbVal); if (printMsgs) log(csound, "Result: %d, Pitch bend: c:%d b:%d\n", result, midiChannel, pbVal); } break; case (int) 0xF0: if (printMsgs) log(csound, "System exclusive (not handled): " "c:%3d v1:%3d v2:%3d\n", midiChannel, midiData1, midiData2); break; } priorMidiStatus = midiStatus; priorMidiChannel = midiChannel; priorMidiData1 = midiData1; priorMidiData2 = midiData2; } return OK; } }; class FluidSetInterpMethod : public OpcodeBase { // Inputs. MYFLT *iFluidSynth; MYFLT *iChannelNumber; MYFLT *iInterpMethod; // State. fluid_synth_t *fluidSynth; int channel; int interpolationMethod; void *mutex; public: int init(CSOUND *csound) { LockGuard guard(csound, mutex); toa(iFluidSynth, fluidSynth); channel = (int) *iChannelNumber; interpolationMethod = (int) *iInterpMethod; if (UNLIKELY(interpolationMethod != 0 && interpolationMethod != 1 && interpolationMethod != 4 && interpolationMethod != 7)) { return csound->InitError(csound, Str("Illegal Interpolation Method: Must be " "either 0, 1, 4, or 7.\n")); } else { fluid_synth_set_interp_method(fluidSynth, channel, interpolationMethod); } return OK; } }; static OENTRY localops[] = { { (char *)"fluidEngine", sizeof(FluidEngine), 0, 1, (char *)"i", (char *)"ppoo", (SUBR) &FluidEngine::init_, (SUBR) 0, (SUBR) 0 }, { (char *)"fluidLoad", sizeof(FluidLoad), 0, 1, (char *)"i", (char *)"Tio", (SUBR) &FluidLoad::init_, (SUBR) 0, (SUBR) 0 }, { (char *)"fluidProgramSelect", sizeof(FluidProgramSelect), 0, 1, (char *)"", (char *)"iiiii", (SUBR) &FluidProgramSelect::init_, (SUBR) 0, (SUBR) 0 }, { (char *)"fluidCCi", sizeof(FluidCCI), 0, 1, (char *)"", (char *)"iiii", (SUBR) &FluidCCI::init_, (SUBR) 0, (SUBR) 0 }, { (char *)"fluidCCk", sizeof(FluidCCK), 0, 3, (char *)"", (char *)"ikkk", (SUBR) &FluidCCK::init_, (SUBR) &FluidCCK::kontrol_, (SUBR) 0 }, { (char *)"fluidNote", sizeof(FluidNote), 0, 3, (char *)"", (char *)"iiii", (SUBR) &FluidNote::init_, (SUBR) &FluidNote::kontrol_, (SUBR) 0 }, { (char *)"fluidOut", sizeof(FluidOut), 0, 5, (char *)"aa", (char *)"i", (SUBR) &FluidOut::init_, (SUBR) 0, (SUBR) &FluidOut::audio_ }, { (char *)"fluidAllOut", sizeof(FluidAllOut), 0, 5, (char *)"aa", (char *)"", (SUBR) &FluidAllOut::init_, (SUBR) 0, (SUBR) &FluidAllOut::audio_ }, { (char *)"fluidControl", sizeof(FluidControl), 0, 3, (char *)"", (char *)"ikkkk", (SUBR) FluidControl::init_, (SUBR) FluidControl::kontrol_, (SUBR) 0 }, { (char *)"fluidSetInterpMethod", sizeof(FluidSetInterpMethod), 0, 1, (char *)"", (char *)"iii", (SUBR) &FluidSetInterpMethod::init_, (SUBR) 0, (SUBR) 0 }, { 0, 0, 0, 0, 0, 0, (SUBR) 0, (SUBR) 0, (SUBR) 0 } }; PUBLIC int csoundModuleCreate(CSOUND *csound) { std::vector *fluid_synths = new std::vector(); int result = 0; result = csound::CreateGlobalPointer(csound, "fluid_synths", fluid_synths); void *fluid_synths_mutex = csound->Create_Mutex(0); result = csound::CreateGlobalPointer(csound, "fluid_synths_mutex", fluid_synths_mutex); return 0; } PUBLIC int csoundModuleInit(CSOUND *csound) { //printf("csoundModuleInit: %p \n", csound); OENTRY *ep; int err = 0; for (ep = (OENTRY *) &(localops[0]); ep->opname != NULL; ep++) { err |= csound->AppendOpcode(csound, ep->opname, ep->dsblksiz, ep->flags, ep->thread, ep->outypes, ep->intypes, (int (*)(CSOUND *, void *)) ep->iopadr, (int (*)(CSOUND *, void *)) ep->kopadr, (int (*)(CSOUND *, void *)) ep->aopadr); } return err; } /** * Called by Csound to de-initialize the opcode * just before destroying it. */ PUBLIC int csoundModuleDestroy(CSOUND *csound) { //printf("csoundModuleDestroy: %p \n", csound); void *fluid_synths_mutex = 0; csound::QueryGlobalPointer(csound, "fluid_synths_mutex", fluid_synths_mutex); if (fluid_synths_mutex) { std::vector *fluid_synths = 0; csound::QueryGlobalPointer(csound, "fluid_synths", fluid_synths); csound->LockMutex(fluid_synths_mutex); if (fluid_synths) { for (size_t i = 0, n = fluid_synths->size(); i < n; i++) { fluid_synth_t *fluidSynth = (*fluid_synths)[i]; //printf("deleting engine: %p \n", fluidSynth); fluid_settings_t *fluidSettings = fluid_synth_get_settings(fluidSynth); delete_fluid_synth(fluidSynth); delete_fluid_settings(fluidSettings); } fluid_synths->clear(); delete fluid_synths; fluid_synths = 0; } csound->UnlockMutex(fluid_synths_mutex); csound->DestroyMutex(fluid_synths_mutex); fluid_synths_mutex = 0; } return 0; } PUBLIC int csoundModuleInfo(void) { return ((CS_APIVERSION << 16) + (CS_APISUBVER << 8) + (int) sizeof(MYFLT)); } csound-6.10.0/Opcodes/fluidOpcodes/fluidOpcodes.h000066400000000000000000000056341321653344700217160ustar00rootroot00000000000000/* * FLUID SYNTH OPCODES * * Adapts Fluidsynth to use global engines, soundFonts, and outputs * * Based on work by Michael Gogins. License is identical to * SOUNDFONTS VST License (listed below) * * Copyright (c) 2003 by Steven Yi. All rights reserved. * * [ORIGINAL INFORMATION BELOW] * * S O U N D F O N T S V S T * * Adapts Fluidsynth to be both a VST plugin instrument * and a Csound plugin opcode. * Copyright (c) 2001-2003 by Michael Gogins. All rights reserved. * * L I C E N S E * * This software is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FLUIDOPCODE_H #define FLUIDOPCODE_H #include "csdl.h" #include typedef struct { OPDS h; /* OUTPUTS */ MYFLT *iEngineNum; MYFLT *iReverbEnabled; MYFLT *iChorusEnabled; MYFLT *iNumChannels; MYFLT *iPolyphony; } FLUIDENGINE; typedef struct { OPDS h; /* INPUTS */ MYFLT *iEngineNumber, *iChannelNumber, *iInterpMethod; } FLUID_SET_INTERP_METHOD; typedef struct { OPDS h; /* OUTPUTS */ MYFLT *iInstrumentNumber; /* INPUTS */ MYFLT *filename, *iEngineNum, *iListPresets; } FLUIDLOAD; typedef struct { OPDS h; /* INPUTS */ MYFLT *iEngineNumber, *iChannelNumber, *iInstrumentNumber, *iBankNumber; MYFLT *iPresetNumber; } FLUID_PROGRAM_SELECT; typedef struct { OPDS h; /* INPUTS */ MYFLT *iEngineNumber, *iChannelNumber, *iControllerNumber, *kVal; int priorMidiValue; fluid_synth_t *fluidEngine; } FLUID_CC; typedef struct { OPDS h; /* INPUTS */ MYFLT *iEngineNumber, *iChannelNumber, *iMidiKeyNumber, *iVelocity; int initDone, iChn, iKey; fluid_synth_t *fluidEngine; } FLUID_NOTE; typedef struct { OPDS h; MYFLT *aLeftOut, *aRightOut; MYFLT *iEngineNum; fluid_synth_t *fluidEngine; } FLUIDOUT; typedef struct { OPDS h; MYFLT *aLeftOut, *aRightOut; void *fluidGlobals; } FLUIDALLOUT; typedef struct { OPDS h; /* Inputs. */ MYFLT *iFluidEngine; MYFLT *kMidiStatus; MYFLT *kMidiChannel; MYFLT *kMidiData1; MYFLT *kMidiData2; /* No outputs. */ /* Internal state. */ int priorMidiStatus; int priorMidiChannel; int priorMidiData1; int priorMidiData2; fluid_synth_t *fluidEngine; } FLUIDCONTROL; #endif csound-6.10.0/Opcodes/fluidOpcodes/fluidOpcodes.html000066400000000000000000000053261321653344700224310ustar00rootroot00000000000000 fluidOpcodes

fluidOpcodes

fluidEngine - creates a fluid engine
fluidLoad - loads a soundfont into a fluid engine
fluidProgramSelect - assign a bank and preset of a soundFont to a midi channel as well as select
fluidCC - send midi controller data to fluid
fluidPlay - plays a note on a channel
fluidOut - outputs sound from a fluid engine

Description

This family of opcodes are meant to be used together to load and play SoundFonts using Peter Hannape's Fluidsynth. Use global engines, soundFonts, and outputs.

Based on work by Michael Gogins.

Syntax

iEngineNumber fluidEngine

iInstrumentNumber fluidLoad sfilename, iEngineNumber

fluidProgramSelect iEngineNumber, iChannelNumber, iInstrumentNumber, iBankNumber, iPresetNumber

fluidCC iEngineNumber, iChannelNumber, iControllerNumber, kValue

fluidNote iEngineNumber, iInstrumentNumber, iMidiKeyNumber, iVelocity

aLeft, aRight fluidOut iEngineNum

 

Initialization

iEngineNumber - engine number assigned from fluid_engine

iInstrumentNumber - instrument number assigned from fluid_load

sfilename - String specifying a SoundFont filename

aLeft - left channel audio output.

aRight - right channel audio output.

iMidiKeyNumber - midi key number to play (0-127)

iVelocity - midi velocity to play at (0-127)

iBankNum - bank number on soundfont to play

iPresetNum - preset number on soundfont to play

iprogram - Number of the fluidsynth program to be assigned to a MIDI channel.

Performance

In this implementation, SoundFont effects such as chorus or reverb are used if and only if they are defaults for the preset. There is no means of turning such effects on or off, or of changing their parameters, from Csound.

 

Examples

 

Credits

Opcode library created by Steven Yi, based on fluid opcode plugin by Michael Gogins.

 

csound-6.10.0/Opcodes/fluidOpcodes/test.csd000066400000000000000000000015371321653344700205750ustar00rootroot00000000000000 sr=44100 kr=441 ksmps=100 nchnls=2 giFluidEngine fluid_engine giSF_piano fluid_load "sf2/Piano Grand Steinway V1.0b (29,651KB).SF2", giFluidEngine giSF_mutedViolin fluid_load "sf2/MutedViolin.sf2", giFluidEngine fluid_program_select giFluidEngine, 0, giSF_piano, 0, 0 fluid_program_select giFluidEngine, 1, giSF_mutedViolin, 0, 0 instr 1 ;untitled fluid_play giFluidEngine, 0, p4, p5 endin instr 2 fluid_play giFluidEngine, 1, p4, p5 endin instr 10 ; fluid out instrument aleft, aright fluid_out giFluidEngine outs aleft * 0dbfs, aright * 0dbfs endin i1 0 2 60 110 i1 0 2 64 110 i1 0 2 67 110 i2 0 1 72 110 i2 0 1 76 70 i2 0 1 79 80 i10 0 6 e csound-6.10.0/Opcodes/flute.h000066400000000000000000000052671321653344700157770ustar00rootroot00000000000000/* flute.h: Copyright (C) 1996, 1997 Perry Cook, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /******************************************/ /* WaveGuide Flute ala Karjalainen, */ /* Smith, Waryznyk, etc. */ /* with polynomial Jet ala Cook */ /* by Perry Cook, 1995-96 */ /* Recoded for Csound by John ffitch */ /* November 1997 */ /* */ /* This is a waveguide model, and thus */ /* relates to various Stanford Univ. */ /* and possibly Yamaha and other patents.*/ /* */ /******************************************/ #if !defined(__Flute_h) #define __Flute_h #include "physutil.h" /**********************************************/ /* Jet Table Object by Perry R. Cook, 1995-96 */ /* Consult Fletcher and Rossing, Karjalainen, */ /* Cook, more, for information. */ /* This, as with many other of my "tables", */ /* is not a table, but is computed by poly- */ /* nomial calculation. */ /**********************************************/ typedef struct FLUTE { OPDS h; MYFLT *ar; /* Output */ MYFLT *amp, *frequency; MYFLT *jetRatio, *attack, *dettack, *noiseGain, *vibFreq; MYFLT *vibAmt, *ifn, *lowestFreq; MYFLT *jetRefl; /* Optional 0.5 */ MYFLT *endRefl; /* Optional 0.5 */ FUNC *vibr; MYFLT v_rate; /* Parameters for vibrato */ MYFLT v_time; /* MYFLT v_phaseOffset; */ DLineL jetDelay; DLineL boreDelay; OnePole filter; DCBlock dcBlock; Noise noise; ADSR adsr; MYFLT lastFreq; MYFLT lastJet; MYFLT maxPress; MYFLT vibrGain; MYFLT outputGain; MYFLT kloop; MYFLT lastamp; MYFLT limit; } FLUTE; #endif csound-6.10.0/Opcodes/fm4op.c000066400000000000000000001323361321653344700156760ustar00rootroot00000000000000/* fm4op.c: Copyright (C) 1998 Perry Cook, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /*********************************************************/ /* Master Class for 4 Operator FM Synth */ /* by Perry R. Cook, 1995-96; recoded John ffitch 97/98 */ /* This instrument contains 4 waves, 4 adsr, and */ /* various state vars. */ /* */ /* The basic Chowning/Stanford FM patent expired April */ /* 1995, but there exist follow-on patents, mostly */ /* assigned to Yamaha. If you are of the type who */ /* should worry about this (making money) worry away. */ /* */ /*********************************************************/ #include "csoundCore.h" #include "fm4op.h" /***********************************************************/ /* Two Zero Filter Class, */ /* by Perry R. Cook, 1995-96; recoded John ffitch 97/98 */ /* See books on filters to understand more about how this */ /* works. Nothing out of the ordinary in this version. */ /***********************************************************/ /* Used by moog1.c as well */ void make_TwoZero(TwoZero *p) { p->zeroCoeffs[0] = FL(0.0); p->zeroCoeffs[1] = FL(0.0); p->gain = FL(1.0); p->inputs[0] = FL(0.0); p->inputs[1] = FL(0.0); p->lastOutput = FL(0.0); } void TwoZero_setZeroCoeffs(TwoZero* p, MYFLT *coeffs) { p->zeroCoeffs[0] = coeffs[0]; p->zeroCoeffs[1] = coeffs[1]; } MYFLT TwoZero_tick(TwoZero *p, MYFLT sample) /* Perform Filter Operation */ { /* TwoZero is a two zero filter (duh!) */ /* Look it up in your favorite DSP text */ MYFLT lastOutput = p->zeroCoeffs[0] * p->inputs[0] + p->zeroCoeffs[1] * p->inputs[1]; p->inputs[1] = p->inputs[0]; p->inputs[0] = p->gain * sample; p->lastOutput = (lastOutput += p->inputs[0]); return lastOutput; } MYFLT Wave_tick(MYFLT *vTime, int len, MYFLT *data, MYFLT rate, MYFLT phase) { /* Tick on vibrato table */ int32 temp; MYFLT alpha; MYFLT lastOutput; MYFLT vvTime = *vTime; vvTime += rate; /* Update current time */ while (vvTime >= len) /* Check for end of sound */ vvTime -= len; /* loop back to beginning */ while (vvTime < FL(0.0)) /* Check for end of sound */ vvTime += len; /* loop back to beginning */ *vTime = vvTime; if (phase != FL(0.0)) { vvTime += phase; /* Add phase offset */ while (vvTime >= len) /* Check for end of sound */ vvTime -= len; /* loop back to beginning */ while (vvTime < FL(0.0)) /* Check for end of sound */ vvTime += len; /* loop back to beginning */ } temp = (int32) vvTime; /* Integer part of time address */ /* fractional part of time address */ alpha = vvTime - (MYFLT)temp; lastOutput = data[temp]; /* Do linear interpolation */ /* same as alpha*data[temp+1] + (1-alpha)data[temp] */ lastOutput += (alpha * (data[temp+1] - lastOutput)); /* End of vibrato tick */ return lastOutput; } /* ---------------------------------------------------------------------- */ static int FM_tabs_built = 0; static MYFLT FM4Op_gains[100]; static MYFLT FM4Op_susLevels[16]; static MYFLT FM4Op_attTimes[32]; void build_FM(void) { /* The following tables are pre-built */ MYFLT temp = FL(1.0); int i; for (i=99; i>=0; i--) { FM4Op_gains[i] = temp; temp *= FL(0.933033); } temp = FL(1.0); for (i=15; i>=0; i--) { FM4Op_susLevels[i] = temp; temp *= FL(0.707106781186547524400844362104849); } temp = FL(8.498186); for (i=0; i<32; i++) { FM4Op_attTimes[i] = temp; temp *= FL(0.707106781186547524400844362104849); } FM_tabs_built = 1; } int make_FM4Op(CSOUND *csound, FM4OP *p) { MYFLT tempCoeffs[2] = {FL(0.0), -FL(1.0)}; FUNC *ftp; if (!FM_tabs_built) build_FM(); /* Ensure tables exist */ make_ADSR(&p->adsr[0]); make_ADSR(&p->adsr[1]); make_ADSR(&p->adsr[2]); make_ADSR(&p->adsr[3]); make_TwoZero(&p->twozero); if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->vifn)) == NULL)) goto err1; p->vibWave = ftp; p->baseFreq = csound->A4; p->ratios[0] = FL(1.0); p->ratios[1] = FL(1.0); p->ratios[2] = FL(1.0); p->ratios[3] = FL(1.0); p->gains[0] = FL(1.0); p->gains[1] = FL(1.0); p->gains[2] = FL(1.0); p->gains[3] = FL(1.0); TwoZero_setZeroCoeffs(&p->twozero, tempCoeffs); p->twozero.gain = FL(0.0); return OK; err1: /* Expect sine wave */ return csound->PerfError(csound, p->h.insdshead, Str("No table for VibWaveato")); } static int FM4Op_loadWaves(CSOUND *csound, FM4OP *p) { FUNC *ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->ifn0)) == NULL)) goto err1; p->waves[0] = ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->ifn1)) == NULL)) goto err1; p->waves[1] = ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->ifn2)) == NULL)) goto err1; p->waves[2] = ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->ifn3)) == NULL)) goto err1; p->waves[3] = ftp; p->w_time[0] = p->w_time[1] = p->w_time[2] = p->w_time[3] = FL(0.0); return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("No table for FM4Op")); /* Expect sine wave */ } void FM4Op_setRatio(FM4OP *p, int whichOne, MYFLT ratio) { p->ratios[whichOne] = ratio; if (ratio>FL(0.0)) p->w_rate[whichOne] = p->baseFreq * ratio; else p->w_rate[whichOne] = ratio; } void FM4Op_keyOff(FM4OP *p) { ADSR_keyOff(&p->adsr[0]); ADSR_keyOff(&p->adsr[1]); ADSR_keyOff(&p->adsr[2]); ADSR_keyOff(&p->adsr[3]); } /*********************************************************/ /* Algorithm 5 (TX81Z) Subclass of 4 Operator FM Synth */ /* by Perry R. Cook, 1995-96; recoded John ffitch 97/98 */ /* This connection topology is 2 simple FM Pairs summed */ /* together, like: */ /* */ /* Alg 5 is : 4->3--\ */ /* + --> Out */ /* 2->1--/ */ /* */ /* Controls: control1 = mod index 1 */ /* control2 = crossfade of two outputs */ /* */ /*********************************************************/ MYFLT FM4Alg5_tick(FM4OP *p, MYFLT c1, MYFLT c2) { MYFLT temp,temp2; MYFLT lastOutput; temp = p->gains[1] * ADSR_tick(&p->adsr[1]) * Wave_tick(&p->w_time[1], (int)p->waves[1]->flen, p->waves[1]->ftable, p->w_rate[1], p->w_phase[1]); temp = temp * c1; p->w_phase[0] = p->waves[0]->flen * temp; /* addPhaseOffset */ p->w_phase[3] = p->waves[0]->flen * p->twozero.lastOutput; temp = p->gains[3] * ADSR_tick(&p->adsr[3]) * Wave_tick(&p->w_time[3], (int)p->waves[3]->flen, p->waves[3]->ftable, p->w_rate[3], p->w_phase[3]); TwoZero_tick(&p->twozero, temp); p->w_phase[2] = p->waves[2]->flen * temp; /* addPhaseOffset */ temp = (FL(1.0) - ( c2 * FL(0.5))) * p->gains[0] * ADSR_tick(&p->adsr[0]) * Wave_tick(&p->w_time[0], (int)p->waves[0]->flen, p->waves[0]->ftable, p->w_rate[0], p->w_phase[0]); temp += c2 * FL(0.5) * p->gains[2] * ADSR_tick(&p->adsr[2]) * Wave_tick(&p->w_time[2], (int)p->waves[2]->flen, p->waves[2]->ftable, p->w_rate[2], p->w_phase[2]); temp2 = Wave_tick(&p->v_time, (int)p->vibWave->flen, p->vibWave->ftable, p->v_rate, FL(0.0)) * *p->modDepth; /* Calculate amplitude mod */ temp = temp * (FL(1.0) + temp2); /* and apply it to output */ lastOutput = temp * FL(0.5); return lastOutput; } /***************************************************************/ /* Tubular Bell (Orch. Chime) Subclass of Algorithm 5 (TX81Z) */ /* Subclass of 4 Operator FM Synth by Perry R. Cook, 1995-96 */ /* Recoded in C by John ffitch 1997-98 */ /***************************************************************/ int tubebellset(CSOUND *csound, FM4OP *p) { MYFLT amp = *p->amp * AMP_RSCALE; /* Normalised */ MYFLT opt = *p->opt; if (UNLIKELY(make_FM4Op(csound,p))) return NOTOK; if (UNLIKELY(FM4Op_loadWaves(csound,p))) return NOTOK; /* 4 x "rawwaves/sinewave.raw" */ FM4Op_setRatio(p, 0, FL(1.0) * FL(0.995)); FM4Op_setRatio(p, 1, FL(1.414) * FL(0.995)); FM4Op_setRatio(p, 2, FL(1.0) * FL(1.005)); FM4Op_setRatio(p, 3, FL(1.414) ); p->gains[0] = amp * FM4Op_gains[94]; p->gains[1] = amp * FM4Op_gains[76]; p->gains[2] = amp * FM4Op_gains[99]; p->gains[3] = amp * FM4Op_gains[71]; if (opt<= FL(0.0)) opt = FL(4.0); ADSR_setAllTimes(csound, &p->adsr[0], FL(0.005), opt, FL(0.0), FL(0.04)); ADSR_setAllTimes(csound, &p->adsr[1], FL(0.005), opt, FL(0.0), FL(0.04)); ADSR_setAllTimes(csound, &p->adsr[2], FL(0.001),FL(0.5)*opt,FL(0.0), FL(0.04)); ADSR_setAllTimes(csound, &p->adsr[3], FL(0.004), opt, FL(0.0), FL(0.04)); /* ADSR_setAll(csound, &p->adsr[0], 0.03f,0.00001f,FL(0.0),0.02f); */ /* ADSR_setAll(csound, &p->adsr[1], 0.03f,0.00001f,FL(0.0),0.02f); */ /* ADSR_setAll(csound, &p->adsr[2], 0.07f,0.00002f,FL(0.0),0.02f); */ /* ADSR_setAll(csound, &p->adsr[3], FL(0.04),0.00001f,FL(0.0),0.02f); */ p->twozero.gain = FL(0.5); p->v_rate = FL(2.0) * p->vibWave->flen * csound->onedsr; /* Vib rate */ /* Set Freq */ p->baseFreq = *p->frequency; p->w_rate[0] = p->baseFreq * p->ratios[0] * p->waves[0]->flen * csound->onedsr; p->w_rate[1] = p->baseFreq * p->ratios[1] * p->waves[1]->flen * csound->onedsr; p->w_rate[2] = p->baseFreq * p->ratios[2] * p->waves[2]->flen * csound->onedsr; p->w_rate[3] = p->baseFreq * p->ratios[3] * p->waves[3]->flen * csound->onedsr; ADSR_keyOn(&p->adsr[0]); ADSR_keyOn(&p->adsr[1]); ADSR_keyOn(&p->adsr[2]); ADSR_keyOn(&p->adsr[3]); return OK; } int tubebell(CSOUND *csound, FM4OP *p) { MYFLT amp = *p->amp * AMP_RSCALE; /* Normalised */ MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT c1 = *p->control1; MYFLT c2 = *p->control2; /* Set Freq */ p->baseFreq = *p->frequency; p->gains[0] = amp * FM4Op_gains[94]; p->gains[1] = amp * FM4Op_gains[76]; p->gains[2] = amp * FM4Op_gains[99]; p->gains[3] = amp * FM4Op_gains[71]; p->w_rate[0] = p->baseFreq * p->ratios[0] * p->waves[0]->flen * csound->onedsr; p->w_rate[1] = p->baseFreq * p->ratios[1] * p->waves[1]->flen * csound->onedsr; p->w_rate[2] = p->baseFreq * p->ratios[2] * p->waves[2]->flen * csound->onedsr; p->w_rate[3] = p->baseFreq * p->ratios[3] * p->waves[3]->flen * csound->onedsr; p->v_rate = *p->vibFreq * p->vibWave->flen * csound->onedsr; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;namp * AMP_RSCALE; /* Normalised */ if (UNLIKELY(make_FM4Op(csound,p))) return NOTOK; if (UNLIKELY(FM4Op_loadWaves(csound,p))) return NOTOK; /* 3 times "sinewave.raw"; 1 x fwavblnk.raw */ FM4Op_setRatio(p, 0, FL(1.0)); FM4Op_setRatio(p, 1, FL(0.5)); FM4Op_setRatio(p, 2, FL(1.0)); FM4Op_setRatio(p, 3, FL(15.0)); p->gains[0] = amp * FM4Op_gains[99]; p->gains[1] = amp * FM4Op_gains[90]; p->gains[2] = amp * FM4Op_gains[99]; p->gains[3] = amp * FM4Op_gains[67]; ADSR_setAllTimes(csound, &p->adsr[0], FL(0.001), FL(1.50), FL(0.0), FL(0.04)); ADSR_setAllTimes(csound, &p->adsr[1], FL(0.001), FL(1.50), FL(0.0), FL(0.04)); ADSR_setAllTimes(csound, &p->adsr[2], FL(0.001), FL(1.00), FL(0.0), FL(0.04)); ADSR_setAllTimes(csound, &p->adsr[3], FL(0.001), FL(0.25), FL(0.0), FL(0.04)); /* ADSR_setAll(&p->adsr[0], 0.05f,0.00003f,FL(0.0),0.02f); */ /* ADSR_setAll(&p->adsr[1], 0.05f,0.00003f,FL(0.0),0.02f); */ /* ADSR_setAll(&p->adsr[2], 0.05f,0.00005f,FL(0.0),0.02f); */ /* ADSR_setAll(&p->adsr[3], 0.05f,0.0002f,FL(0.0),0.02f); */ p->twozero.gain = FL(1.0); p->v_rate = FL(2.0) * p->vibWave->flen * csound->onedsr; /* Vib rate */ /* Set Freq */ p->baseFreq = *p->frequency; p->w_rate[0] = p->baseFreq * p->ratios[0] * p->waves[0]->flen * csound->onedsr; p->w_rate[1] = p->baseFreq * p->ratios[1] * p->waves[1]->flen * csound->onedsr; p->w_rate[2] = p->baseFreq * p->ratios[2] * p->waves[2]->flen * csound->onedsr; p->w_rate[3] = p->baseFreq * p->ratios[3] * p->waves[3]->flen * csound->onedsr; ADSR_keyOn(&p->adsr[0]); ADSR_keyOn(&p->adsr[1]); ADSR_keyOn(&p->adsr[2]); ADSR_keyOn(&p->adsr[3]); return OK; } /***************************************************************/ /* Wurlitzer Electric Piano Subclass of Algorithm 5 (TX81Z) */ /* Subclass of 4 Operator FM Synth by Perry R. Cook, 1995-96 */ /* Recoded in C by John ffitch 1997-98 */ /***************************************************************/ int wurleyset(CSOUND *csound, FM4OP *p) { MYFLT amp = *p->amp * AMP_RSCALE; /* Normalised */ if (UNLIKELY(make_FM4Op(csound,p))) return NOTOK; if (UNLIKELY(FM4Op_loadWaves(csound,p))) return NOTOK; /* 3 x "sinewave.raw"; 1 x fwavblnk.raw */ FM4Op_setRatio(p, 0, FL(1.0)); FM4Op_setRatio(p, 1, FL(4.05)); FM4Op_setRatio(p, 2, -FL(510.0)); FM4Op_setRatio(p, 3, -FL(510.0)); p->gains[0] = amp * FM4Op_gains[99]; p->gains[1] = amp * FM4Op_gains[82]; p->gains[2] = amp * FM4Op_gains[82]; p->gains[3] = amp * FM4Op_gains[68]; ADSR_setAllTimes(csound, &p->adsr[0], FL(0.001), FL(1.50), FL(0.0), FL(0.04)); ADSR_setAllTimes(csound, &p->adsr[1], FL(0.001), FL(1.50), FL(0.0), FL(0.04)); ADSR_setAllTimes(csound, &p->adsr[2], FL(0.001), FL(0.25), FL(0.0), FL(0.04)); ADSR_setAllTimes(csound, &p->adsr[3], FL(0.001), FL(0.15), FL(0.0), FL(0.04)); /* ADSR_setAll(&p->adsr[0], 0.05f,0.00003f,FL(0.0),0.02f); */ /* ADSR_setAll(&p->adsr[1], 0.05f,0.00003f,FL(0.0),0.02f); */ /* ADSR_setAll(&p->adsr[2], 0.05f,0.0002f,FL(0.0),0.02f); */ /* ADSR_setAll(&p->adsr[3], 0.05f,0.0003f,FL(0.0),0.02f); */ p->twozero.gain = FL(2.0); /* Set Freq */ p->baseFreq = *p->frequency; p->w_rate[0] = p->baseFreq * p->ratios[0] * p->waves[0]->flen * csound->onedsr; p->w_rate[1] = p->baseFreq * p->ratios[1] * p->waves[1]->flen * csound->onedsr; p->w_rate[2] = p->ratios[2] * p->waves[2]->flen * csound->onedsr; p->w_rate[3] = p->ratios[3] * p->waves[3]->flen * csound->onedsr; ADSR_keyOn(&p->adsr[0]); ADSR_keyOn(&p->adsr[1]); ADSR_keyOn(&p->adsr[2]); ADSR_keyOn(&p->adsr[3]); return OK; } int wurley(CSOUND *csound, FM4OP *p) { MYFLT amp = *p->amp * AMP_RSCALE; /* Normalised */ MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT c1 = *p->control1; MYFLT c2 = *p->control2; /* Set Freq */ p->baseFreq = *p->frequency; p->gains[0] = amp * FM4Op_gains[99]; p->gains[1] = amp * FM4Op_gains[82]; p->gains[2] = amp * FM4Op_gains[82]; p->gains[3] = amp * FM4Op_gains[68]; p->w_rate[0] = p->baseFreq * p->ratios[0] * p->waves[0]->flen * csound->onedsr; p->w_rate[1] = p->baseFreq * p->ratios[1] * p->waves[1]->flen * csound->onedsr; p->w_rate[2] = p->ratios[2] * p->waves[2]->flen * csound->onedsr; p->w_rate[3] = p->ratios[3] * p->waves[3]->flen * csound->onedsr; p->v_rate = *p->vibFreq * p->vibWave->flen * csound->onedsr; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;n2-- + -->1-->Out */ /* */ /* Controls: control1 = total mod index */ /* control2 = crossfade of two modulators */ /* */ /*********************************************************/ MYFLT FM4Alg3_tick(FM4OP *p, MYFLT c1, MYFLT c2) { MYFLT temp; MYFLT lastOutput; temp = *p->modDepth * FL(0.2) * Wave_tick(&p->v_time, (int)p->vibWave->flen, p->vibWave->ftable, p->v_rate, FL(0.0)); p->w_rate[0] = p->baseFreq * (FL(1.0) + temp) * p->ratios[0]; p->w_rate[1] = p->baseFreq * (FL(1.0) + temp) * p->ratios[1]; p->w_rate[2] = p->baseFreq * (FL(1.0) + temp) * p->ratios[2]; p->w_rate[3] = p->baseFreq * (FL(1.0) + temp) * p->ratios[3]; temp = p->gains[2] * ADSR_tick(&p->adsr[2]) * Wave_tick(&p->w_time[2], (int)p->waves[2]->flen, p->waves[2]->ftable, p->w_rate[2], p->w_phase[2]); p->w_phase[1] = p->waves[1]->flen * temp; p->w_phase[3] = p->waves[3]->flen * p->twozero.lastOutput; temp = (FL(1.0) - (c2 * FL(0.5))) * p->gains[3] * ADSR_tick(&p->adsr[3]) * Wave_tick(&p->w_time[3], (int)p->waves[3]->flen, p->waves[3]->ftable, p->w_rate[3], p->w_phase[3]); TwoZero_tick(&p->twozero, temp); temp += c2 * FL(0.5) * p->gains[1] * ADSR_tick(&p->adsr[1]) * Wave_tick(&p->w_time[1], (int)p->waves[1]->flen, p->waves[1]->ftable, p->w_rate[1], p->w_phase[1]); temp = temp * c1; p->w_phase[0] = p->waves[0]->flen * temp; temp = p->gains[0] * ADSR_tick(&p->adsr[0]) * Wave_tick(&p->w_time[0], (int)p->waves[0]->flen, p->waves[0]->ftable, p->w_rate[0], p->w_phase[0]); lastOutput = temp * FL(0.5); return lastOutput; } int heavymetset(CSOUND *csound, FM4OP *p) { if (UNLIKELY(make_FM4Op(csound,p))) return NOTOK; if (UNLIKELY(FM4Op_loadWaves(csound,p))) return NOTOK; /* Mixed -- 2 x sine; 1 x fwavblnk */ FM4Op_setRatio(p, 0, FL(1.00) ); FM4Op_setRatio(p, 1, FL(4.00) * FL(0.999)); FM4Op_setRatio(p, 2, FL(3.00) * FL(1.001)); FM4Op_setRatio(p, 3, FL(0.50) * FL(1.002)); ADSR_setAllTimes(csound, &p->adsr[0], FL(0.001), FL(0.001), FL(1.0), FL(0.01)); ADSR_setAllTimes(csound, &p->adsr[1], FL(0.001), FL(0.010), FL(1.0), FL(0.50)); ADSR_setAllTimes(csound, &p->adsr[2], FL(0.010), FL(0.005), FL(1.0), FL(0.20)); ADSR_setAllTimes(csound, &p->adsr[3], FL(0.030), FL(0.010), FL(0.2), FL(0.20)); /* ADSR_setAll(&p->adsr[0], 0.050f, 0.0100f, FL(1.0), FL(0.001)); */ /* ADSR_setAll(&p->adsr[1], 0.050f, 0.0010f, FL(1.0), 0.0001f); */ /* ADSR_setAll(&p->adsr[2], FL(0.001), 0.0020f, FL(1.0), 0.0002f); */ /* ADSR_setAll(&p->adsr[3], 0.050f, 0.0010f, FL(0.2), 0.0002f); */ p->twozero.gain = FL(2.0); /* p->v_rate = 5.5 * p->vibWave->flen * csound->onedsr; Vib rate */ ADSR_keyOn(&p->adsr[0]); ADSR_keyOn(&p->adsr[1]); ADSR_keyOn(&p->adsr[2]); ADSR_keyOn(&p->adsr[3]); return OK; } int heavymet(CSOUND *csound, FM4OP *p) { MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT amp = *p->amp * AMP_RSCALE; /* Normalised */ MYFLT c1 = *p->control1; MYFLT c2 = *p->control2; MYFLT temp; p->baseFreq = *p->frequency; p->gains[0] = amp * FM4Op_gains[92]; p->gains[1] = amp * FM4Op_gains[76]; p->gains[2] = amp * FM4Op_gains[91]; p->gains[3] = amp * FM4Op_gains[68]; temp = p->baseFreq * csound->onedsr; p->w_rate[0] = temp * p->ratios[0] * p->waves[0]->flen; p->w_rate[1] = temp * p->ratios[1] * p->waves[1]->flen; p->w_rate[2] = temp * p->ratios[2] * p->waves[2]->flen; p->w_rate[3] = temp * p->ratios[3] * p->waves[3]->flen; p->v_rate = *p->vibFreq * p->vibWave->flen * csound->onedsr; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;n Out */ /* 3 -/| */ /* 4 -- */ /* */ /* Controls: control1 = op4 (fb) gain */ /* control2 = op3 gain */ /* */ /**********************************************************/ MYFLT FM4Alg8_tick(FM4OP *p, MYFLT c1, MYFLT c2) { MYFLT temp; MYFLT lastOutput; p->w_phase[3] = p->waves[3]->flen * p->twozero.lastOutput; temp = c1 * FL(2.0) * p->gains[3] * ADSR_tick(&p->adsr[3]) * Wave_tick(&p->w_time[3], (int)p->waves[3]->flen, p->waves[3]->ftable, p->w_rate[3], p->w_phase[3]); TwoZero_tick(&p->twozero, temp); temp += c2 * FL(2.0) * p->gains[2] * ADSR_tick(&p->adsr[2]) * Wave_tick(&p->w_time[2], (int)p->waves[2]->flen, p->waves[2]->ftable, p->w_rate[2], p->w_phase[2]); temp += p->gains[1] * ADSR_tick(&p->adsr[1]) * Wave_tick(&p->w_time[1], (int)p->waves[1]->flen, p->waves[1]->ftable, p->w_rate[1], p->w_phase[1]); temp += p->gains[0] * ADSR_tick(&p->adsr[0]) * Wave_tick(&p->w_time[0], (int)p->waves[0]->flen, p->waves[0]->ftable, p->w_rate[0], p->w_phase[0]); lastOutput = temp * FL(0.125); return lastOutput; } /**************************************************************/ /* Hammond(OID) Organ Subclass of Algorithm 8 (TX81Z) */ /* Subclass of 4 Operator FM Synth by Perry R. Cook, 1995-96 */ /* Recoded in C by John ffitch 1997-98 */ /**************************************************************/ int b3set(CSOUND *csound, FM4OP *p) { MYFLT amp = *p->amp * AMP_RSCALE; /* Normalised */ if (UNLIKELY(make_FM4Op(csound,p))) return NOTOK; if (UNLIKELY(FM4Op_loadWaves(csound,p))) return NOTOK; /* sines */ FM4Op_setRatio(p, 0, FL(0.999)); FM4Op_setRatio(p, 1, FL(1.997)); FM4Op_setRatio(p, 2, FL(3.006)); FM4Op_setRatio(p, 3, FL(6.009)); p->gains[0] = amp * FM4Op_gains[95]; p->gains[1] = amp * FM4Op_gains[95]; p->gains[2] = amp * FM4Op_gains[99]; p->gains[3] = amp * FM4Op_gains[95]; ADSR_setAllTimes(csound, &p->adsr[0], FL(0.005), FL(0.003), FL(1.0), FL(0.01)); ADSR_setAllTimes(csound, &p->adsr[1], FL(0.005), FL(0.003), FL(1.0), FL(0.01)); ADSR_setAllTimes(csound, &p->adsr[2], FL(0.005), FL(0.003), FL(1.0), FL(0.01)); ADSR_setAllTimes(csound, &p->adsr[3], FL(0.005), FL(0.001), FL(0.4), FL(0.03)); /* ADSR_setAll(&p->adsr[0], 0.05f, 0.03f, FL(1.0), FL(0.04)); */ /* ADSR_setAll(&p->adsr[1], 0.05f, 0.03f, FL(1.0), FL(0.04)); */ /* ADSR_setAll(&p->adsr[2], 0.05f, 0.03f, FL(1.0), FL(0.04)); */ /* ADSR_setAll(&p->adsr[3], 0.05f, FL(0.001),0.4f, 0.06f); */ p->twozero.gain = FL(0.1); ADSR_keyOn(&p->adsr[0]); ADSR_keyOn(&p->adsr[1]); ADSR_keyOn(&p->adsr[2]); ADSR_keyOn(&p->adsr[3]); return OK; } int hammondB3(CSOUND *csound, FM4OP *p) { MYFLT amp = *p->amp * AMP_RSCALE; /* Normalised */ MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT c1 = *p->control1; MYFLT c2 = *p->control2; MYFLT temp; p->baseFreq = *p->frequency; p->gains[0] = amp * FM4Op_gains[95]; p->gains[1] = amp * FM4Op_gains[95]; p->gains[2] = amp * FM4Op_gains[99]; p->gains[3] = amp * FM4Op_gains[95]; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;nmodDepth > FL(0.0)) { p->v_rate = *p->vibFreq * p->vibWave->flen * csound->onedsr; temp = FL(1.0) + (*p->modDepth * FL(0.1) * Wave_tick(&p->v_time, (int)p->vibWave->flen, p->vibWave->ftable, p->v_rate, FL(0.0))); temp *= p->baseFreq * csound->onedsr; p->w_rate[0] = p->ratios[0] * temp * p->waves[0]->flen; p->w_rate[1] = p->ratios[1] * temp * p->waves[1]->flen; p->w_rate[2] = p->ratios[2] * temp * p->waves[2]->flen; p->w_rate[3] = p->ratios[3] * temp * p->waves[3]->flen; } lastOutput = FM4Alg8_tick(p, c1, c2); ar[n]= lastOutput*AMP_SCALE; } return OK; } /************************************************************/ /* Algorithm 6 (TX81Z) Subclass of 4 Operator FM Synth */ /* by Perry R. Cook, 1995-96; recoded John ffitch 97-98 */ /* This connection topology is three Carriers and a common */ /* Modulator /->1 -\ */ /* 4-|-->2 - +-> Out */ /* \->3 -/ */ /* */ /* Controls: control1 = vowel */ /* control2 = spectral tilt */ /* */ /************************************************************/ MYFLT FM4Alg6_tick(CSOUND *csound, FM4OPV *q) { MYFLT temp,temp2; FM4OP *p = (FM4OP*)q; temp = p->gains[3] * ADSR_tick(&p->adsr[3]) * Wave_tick(&p->w_time[3], (int)p->waves[3]->flen, p->waves[3]->ftable, p->w_rate[3], p->w_phase[3]); /* Calculate frequency mod */ temp2 = Wave_tick(&p->v_time, (int)p->vibWave->flen, p->vibWave->ftable, p->v_rate, FL(0.0)) * *p->modDepth * FL(0.1); temp2 = (FL(1.0) + temp2) * p->baseFreq * csound->onedsr; p->w_rate[0] = temp2 * p->ratios[0] * p->waves[0]->flen; p->w_rate[1] = temp2 * p->ratios[1] * p->waves[1]->flen; p->w_rate[2] = temp2 * p->ratios[2] * p->waves[2]->flen; p->w_rate[3] = temp2 * p->ratios[3] * p->waves[3]->flen; p->w_phase[0] = p->waves[0]->flen * temp * q->mods[0]; p->w_phase[1] = p->waves[1]->flen * temp * q->mods[1]; p->w_phase[2] = p->waves[2]->flen * temp * q->mods[2]; p->w_phase[3] = p->waves[3]->flen * p->twozero.lastOutput; TwoZero_tick(&p->twozero, temp); temp = p->gains[0] * q->tilt[0] * ADSR_tick(&p->adsr[0]) * Wave_tick(&p->w_time[0], (int)p->waves[0]->flen, p->waves[0]->ftable, p->w_rate[0], p->w_phase[0]); temp += p->gains[1] * q->tilt[1] * ADSR_tick(&p->adsr[1]) * Wave_tick(&p->w_time[1], (int)p->waves[1]->flen, p->waves[1]->ftable, p->w_rate[1], p->w_phase[1]); temp += p->gains[2] * q->tilt[2] * ADSR_tick(&p->adsr[2]) * Wave_tick(&p->w_time[2], (int)p->waves[2]->flen, p->waves[2]->ftable, p->w_rate[2], p->w_phase[2]); return temp * FL(0.33); } MYFLT phonGains[32][2] = {{FL(1.0), FL(0.0)}, /* eee */ {FL(1.0), FL(0.0)}, /* ihh */ {FL(1.0), FL(0.0)}, /* ehh */ {FL(1.0), FL(0.0)}, /* aaa */ {FL(1.0), FL(0.0)}, /* ahh */ {FL(1.0), FL(0.0)}, /* aww */ {FL(1.0), FL(0.0)}, /* ohh */ {FL(1.0), FL(0.0)}, /* uhh */ {FL(1.0), FL(0.0)}, /* uuu */ {FL(1.0), FL(0.0)}, /* ooo */ {FL(1.0), FL(0.0)}, /* rrr */ {FL(1.0), FL(0.0)}, /* lll */ {FL(1.0), FL(0.0)}, /* mmm */ {FL(1.0), FL(0.0)}, /* nnn */ {FL(1.0), FL(0.0)}, /* nng */ {FL(1.0), FL(0.0)}, /* ngg */ {FL(0.0), FL(1.0)}, /* fff */ {FL(0.0), FL(1.0)}, /* sss */ {FL(0.0), FL(1.0)}, /* thh */ {FL(0.0), FL(1.0)}, /* shh */ {FL(0.0), FL(1.0)}, /* xxx */ {FL(0.0), FL(0.1)}, /* hee */ {FL(0.0), FL(0.1)}, /* hoo */ {FL(0.0), FL(0.1)}, /* hah */ {FL(1.0), FL(0.1)}, /* bbb */ {FL(1.0), FL(0.1)}, /* ddd */ {FL(1.0), FL(0.1)}, /* jjj */ {FL(1.0), FL(0.1)}, /* ggg */ {FL(1.0), FL(1.0)}, /* vvv */ {FL(1.0), FL(1.0)}, /* zzz */ {FL(1.0), FL(1.0)}, /* thz */ {FL(1.0), FL(1.0)} /* zhh */ }; MYFLT phonParams[32][4][3] = {{ { FL(273.0), FL(0.996), FL(0.0)}, /* eee (beet) */ {FL(2086.0), FL(0.945), -FL(16.0)}, {FL(2754.0), FL(0.979), -FL(12.0)}, {FL(3270.0), FL(0.440), -FL(17.0)}}, { { FL(385.0), FL(0.987), FL(10.0)}, /* ihh (bit) */ {FL(2056.0), FL(0.930), -FL(20.0)}, {FL(2587.0), FL(0.890), -FL(20.0)}, {FL(3150.0), FL(0.400), -FL(20.0)}}, { { FL(515.0), FL(0.977), FL(10.0)}, /* ehh (bet) */ {FL(1805.0), FL(0.810), -FL(10.0)}, {FL(2526.0), FL(0.875), -FL(10.0)}, {FL(3103.0), FL(0.400), -FL(13.0)}}, { { FL(773.0), FL(0.950), FL(10.0)}, /* aaa (bat) */ {FL(1676.0), FL(0.830), -FL(6.0)}, {FL(2380.0), FL(0.880), -FL(20.0)}, {FL(3027.0), FL(0.600), -FL(20.0)}}, { { FL(770.0), FL(0.950), FL(0.0)}, /* ahh (father) */ {FL(1153.0), FL(0.970), -FL(9.0)}, {FL(2450.0), FL(0.780), -FL(29.0)}, {FL(3140.0), FL(0.800), -FL(39.0)}}, { { FL(637.0), FL(0.910), FL(0.0)}, /* aww (bought) */ { FL(895.0), FL(0.900), -FL(3.0)}, {FL(2556.0), FL(0.950), -FL(17.0)}, {FL(3070.0), FL(0.910), -FL(20.0)}}, { { FL(637.0), FL(0.910), FL(0.0)}, /* ohh (bone) */ /*NOTE:: same as aww (bought) */ { FL(895.0), FL(0.900), -FL(3.0)}, {FL(2556.0), FL(0.950), -FL(17.0)}, {FL(3070.0), FL(0.910), -FL(20.0)}}, { { FL(561.0), FL(0.965), FL(0.0)}, /* uhh (but) */ {FL(1084.0), FL(0.930), -FL(10.0)}, {FL(2541.0), FL(0.930), -FL(15.0)}, {FL(3345.0), FL(0.900), -FL(20.0)}}, { { FL(515.0), FL(0.976), FL(0.0)}, /* uuu (foot) */ {FL(1031.0), FL(0.950), -FL(3.0)}, {FL(2572.0), FL(0.960), -FL(11.0)}, {FL(3345.0), FL(0.960), -FL(20.0)}}, { { FL(349.0), FL(0.986), -FL(10.0)}, /* ooo (boot) */ { FL(918.0), FL(0.940), -FL(20.0)}, {FL(2350.0), FL(0.960), -FL(27.0)}, {FL(2731.0), FL(0.950), -FL(33.0)}}, { { FL(394.0), FL(0.959), -FL(10.0)}, /* rrr (bird) */ {FL(1297.0), FL(0.780), -FL(16.0)}, {FL(1441.0), FL(0.980), -FL(16.0)}, {FL(2754.0), FL(0.950), -FL(40.0)}}, { { FL(462.0), FL(0.990), +FL(5.0)}, /* lll (lull) */ {FL(1200.0), FL(0.640), -FL(10.0)}, {FL(2500.0), FL(0.200), -FL(20.0)}, {FL(3000.0), FL(0.100), -FL(30.0)}}, { { FL(265.0), FL(0.987), -FL(10.0)}, /* mmm (mom) */ {FL(1176.0), FL(0.940), -FL(22.0)}, {FL(2352.0), FL(0.970), -FL(20.0)}, {FL(3277.0), FL(0.940), -FL(31.0)}}, { { FL(204.0), FL(0.980), -FL(10.0)}, /* nnn (nun) */ {FL(1570.0), FL(0.940), -FL(15.0)}, {FL(2481.0), FL(0.980), -FL(12.0)}, {FL(3133.0), FL(0.800), -FL(30.0)}}, { { FL(204.0), FL(0.980), -FL(10.0)}, /* nng (sang) NOTE:: same as nnn */ {FL(1570.0), FL(0.940), -FL(15.0)}, {FL(2481.0), FL(0.980), -FL(12.0)}, {FL(3133.0), FL(0.800), -FL(30.0)}}, { { FL(204.0), FL(0.980), -FL(10.0)}, /* ngg (bong) NOTE:: same as nnn */ {FL(1570.0), FL(0.940), -FL(15.0)}, {FL(2481.0), FL(0.980), -FL(12.0)}, {FL(3133.0), FL(0.800), -FL(30.0)}}, { {FL(1000.0), FL(0.300), FL(0.0)}, /* fff */ {FL(2800.0), FL(0.860), -FL(10.0)}, {FL(7425.0), FL(0.740), FL(0.0)}, {FL(8140.0), FL(0.860), FL(0.0)}}, { {FL(0.0), FL(0.000), FL(0.0)}, /* sss */ {FL(2000.0), FL(0.700), -FL(15.0)}, {FL(5257.0), FL(0.750), -FL(3.0)}, {FL(7171.0), FL(0.840), FL(0.0)}}, { { FL(100.0), FL(0.900), FL(0.0)}, /* thh */ {FL(4000.0), FL(0.500), -FL(20.0)}, {FL(5500.0), FL(0.500), -FL(15.0)}, {FL(8000.0), FL(0.400), -FL(20.0)}}, { {FL(2693.0), FL(0.940), FL(0.0)}, /* shh */ {FL(4000.0), FL(0.720), -FL(10.0)}, {FL(6123.0), FL(0.870), -FL(10.0)}, {FL(7755.0), FL(0.750), -FL(18.0)}}, { {FL(1000.0), FL(0.300), -FL(10.0)}, /* xxx NOTE:: Not Really Done Yet */ {FL(2800.0), FL(0.860), -FL(10.0)}, {FL(7425.0), FL(0.740), FL(0.0)}, {FL(8140.0), FL(0.860), FL(0.0)}}, { { FL(273.0), FL(0.996), -FL(40.0)}, /* hee (beet) (noisy eee) */ {FL(2086.0), FL(0.945), -FL(16.0)}, {FL(2754.0), FL(0.979), -FL(12.0)}, {FL(3270.0), FL(0.440), -FL(17.0)}}, { { FL(349.0), FL(0.986), -FL(40.0)}, /* hoo (boot) (noisy ooo) */ { FL(918.0), FL(0.940), -FL(10.0)}, {FL(2350.0), FL(0.960), -FL(17.0)}, {FL(2731.0), FL(0.950), -FL(23.0)}}, { { FL(770.0), FL(0.950), -FL(40.0)}, /* hah (father) (noisy ahh) */ {FL(1153.0), FL(0.970), -FL(3.0)}, {FL(2450.0), FL(0.780), -FL(20.0)}, {FL(3140.0), FL(0.800), -FL(32.0)}}, { {FL(2000.0), FL(0.700), -FL(20.0)}, /* bbb NOTE:: Not Really Done Yet */ {FL(5257.0), FL(0.750), -FL(15.0)}, {FL(7171.0), FL(0.840), -FL(3.0)}, {FL(9000.0), FL(0.900), FL(0.0)}}, { { FL(100.0), FL(0.900), FL(0.0)}, /* ddd NOTE:: Not Really Done Yet */ {FL(4000.0), FL(0.500), -FL(20.0)}, {FL(5500.0), FL(0.500), -FL(15.0)}, {FL(8000.0), FL(0.400), -FL(20.0)}}, { {FL(2693.0), FL(0.940), FL(0.0)}, /* jjj NOTE:: Not Really Done Yet */ {FL(4000.0), FL(0.720), -FL(10.0)}, {FL(6123.0), FL(0.870), -FL(10.0)}, {FL(7755.0), FL(0.750), -FL(18.0)}}, { {FL(2693.0), FL(0.940), FL(0.0)}, /* ggg NOTE:: Not Really Done Yet */ {FL(4000.0), FL(0.720), -FL(10.0)}, {FL(6123.0), FL(0.870), -FL(10.0)}, {FL(7755.0), FL(0.750), -FL(18.0)}}, { {FL(2000.0), FL(0.700), -FL(20.0)}, /* vvv NOTE:: Not Really Done Yet */ {FL(5257.0), FL(0.750), -FL(15.0)}, {FL(7171.0), FL(0.840), -FL(3.0)}, {FL(9000.0), FL(0.900), FL(0.0)}}, { { FL(100.0), FL(0.900), FL(0.0)}, /* zzz NOTE:: Not Really Done Yet */ {FL(4000.0), FL(0.500), -FL(20.0)}, {FL(5500.0), FL(0.500), -FL(15.0)}, {FL(8000.0), FL(0.400), -FL(20.0)}}, { {FL(2693.0), FL(0.940), FL(0.0)}, /* thz NOTE:: Not Really Done Yet */ {FL(4000.0), FL(0.720), -FL(10.0)}, {FL(6123.0), FL(0.870), -FL(10.0)}, {FL(7755.0), FL(0.750), -FL(18.0)}}, { {FL(2693.0), FL(0.940), FL(0.0)}, /* zhh NOTE:: Not Really Done Yet */ {FL(4000.0), FL(0.720), -FL(10.0)}, {FL(6123.0), FL(0.870), -FL(10.0)}, {FL(7755.0), FL(0.750), -FL(18.0)}} }; #define currentVowel (*q->control1) void FMVoices_setFreq(FM4OPV *q, MYFLT frequency) { MYFLT temp,temp2 = FL(0.0); int tempi,tempi2 = 0; if (currentVowel < 32) { tempi2 = (int)currentVowel; temp2 = FL(0.9); } else if (currentVowel < 64) { tempi2 =(int) currentVowel - 32; temp2 = FL(1.0); } else if (currentVowel < 96) { tempi2 = (int)currentVowel - 64; temp2 = FL(1.1); } else if (currentVowel < 128) { tempi2 = (int)currentVowel - 96; temp2 = FL(1.2); } q->baseFreq = frequency; temp = (temp2 * phonParams[tempi2][0][0] / q->baseFreq) + FL(0.5); tempi = (int) temp; FM4Op_setRatio((FM4OP*)q, 0, (MYFLT) tempi); temp = (temp2 * phonParams[tempi2][1][0] / q->baseFreq) + FL(0.5); tempi = (int) temp; FM4Op_setRatio((FM4OP*)q, 1, (MYFLT) tempi); temp = (temp2 * phonParams[tempi2][2][0] / q->baseFreq) + FL(0.5); tempi = (int) temp; FM4Op_setRatio((FM4OP*)q, 2, (MYFLT) tempi); q->gains[0] = FL(1.0); /* pow(10.0f,phonParams[tempi2][0][2] * 0.05f); */ q->gains[1] = FL(1.0); /* pow(10.0f,phonParams[tempi2][1][2] * 0.05f); */ q->gains[2] = FL(1.0); /* pow(10.0f,phonParams[tempi2][2][2] * 0.05f); */ } int FMVoiceset(CSOUND *csound, FM4OPV *q) { FM4OP *p = (FM4OP *)q; MYFLT amp = *q->amp * AMP_RSCALE; if (UNLIKELY(make_FM4Op(csound,p))) return NOTOK; if (UNLIKELY(FM4Op_loadWaves(csound,p))) return NOTOK; FM4Op_setRatio(p, 0, FL(2.00)); FM4Op_setRatio(p, 1, FL(4.00)); FM4Op_setRatio(p, 2, FL(12.0)); FM4Op_setRatio(p, 3, FL(1.00)); p->gains[3] = FM4Op_gains[80]; ADSR_setAllTimes(csound, &p->adsr[0], FL(0.050), FL(0.050), FM4Op_susLevels[15], FL(0.050)); ADSR_setAllTimes(csound, &p->adsr[1], FL(0.050), FL(0.050), FM4Op_susLevels[15], FL(0.050)); ADSR_setAllTimes(csound, &p->adsr[2], FL(0.050), FL(0.050), FM4Op_susLevels[15], FL(0.050)); ADSR_setAllTimes(csound, &p->adsr[3], FL(0.001), FL(0.010), FM4Op_susLevels[15], FL(0.500)); p->twozero.gain = FL(0.0); /* modDepth = 0.005; */ q->tilt[0] = FL(1.0); q->tilt[1] = FL(0.5); q->tilt[2] = FL(0.2); q->mods[0] = FL(1.0); q->mods[1] = FL(1.1); q->mods[2] = FL(1.1); p->baseFreq = FL(110.0); FMVoices_setFreq(q, FL(110.0)); q->tilt[0] = amp; q->tilt[1] = amp * amp; q->tilt[2] = amp * amp * amp; ADSR_keyOn(&p->adsr[0]); ADSR_keyOn(&p->adsr[1]); ADSR_keyOn(&p->adsr[2]); ADSR_keyOn(&p->adsr[3]); q->last_control = -FL(1.0); return OK; } int FMVoice(CSOUND *csound, FM4OPV *q) { FM4OP *p = (FM4OP *)q; MYFLT amp = *q->amp * AMP_RSCALE; MYFLT *ar = q->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (p->baseFreq != *q->frequency || *q->control1 != q->last_control) { q->last_control = *q->control1; p->baseFreq = *q->frequency; FMVoices_setFreq(q, p->baseFreq); } q->tilt[0] = amp; q->tilt[1] = amp * amp; q->tilt[2] = amp * amp * amp; p->gains[3] = FM4Op_gains[(int) (*p->control2 * FL(0.78125))]; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;n3--\ */ /* 2-- + -->1-->Out */ /* */ /* Controls: control1 = total mod index */ /* control2 = crossfade of two */ /* modulators */ /* */ /*********************************************************/ MYFLT FM4Alg4_tick(CSOUND *csound, FM4OP *p, MYFLT c1, MYFLT c2) { MYFLT temp; MYFLT lastOutput; temp = Wave_tick(&p->v_time, (int)p->vibWave->flen, p->vibWave->ftable, p->v_rate, FL(0.0)) * *p->modDepth * FL(0.2); temp = p-> baseFreq * (FL(1.0) + temp)* csound->onedsr; p->w_rate[0] = p->ratios[0] * temp * p->waves[0]->flen; p->w_rate[1] = p->ratios[1] * temp * p->waves[1]->flen; p->w_rate[2] = p->ratios[2] * temp * p->waves[2]->flen; p->w_rate[3] = p->ratios[3] * temp * p->waves[3]->flen; p->w_phase[3] = p->waves[3]->flen * p->twozero.lastOutput; temp = p->gains[3] * ADSR_tick(&p->adsr[3]) * Wave_tick(&p->w_time[3], (int)p->waves[3]->flen, p->waves[3]->ftable, p->w_rate[3], p->w_phase[3]); TwoZero_tick(&p->twozero, temp); p->w_phase[2] = p->waves[2]->flen * temp; temp = (FL(1.0) - (c2 * FL(0.5))) * p->gains[2] * ADSR_tick(&p->adsr[2]) * Wave_tick(&p->w_time[2], (int)p->waves[2]->flen, p->waves[2]->ftable, p->w_rate[2], p->w_phase[2]); temp += c2 * FL(0.5) * p->gains[1] * ADSR_tick(&p->adsr[1]) * Wave_tick(&p->w_time[1], (int)p->waves[1]->flen, p->waves[1]->ftable, p->w_rate[1], p->w_phase[1]); temp = temp * c1; p->w_phase[0] = p->waves[0]->flen * temp; temp = p->gains[0] * ADSR_tick(&p->adsr[0]) * Wave_tick(&p->w_time[0], (int)p->waves[0]->flen, p->waves[0]->ftable, p->w_rate[0], p->w_phase[0]); lastOutput = temp * FL(0.5); return lastOutput; } int percfluteset(CSOUND *csound, FM4OP *p) { MYFLT amp = *p->amp * AMP_RSCALE; /* Normalised */ if (UNLIKELY(make_FM4Op(csound,p))) return NOTOK; if (UNLIKELY(FM4Op_loadWaves(csound,p))) return NOTOK; /* 3 x sines; 1 x fwavblnk */ FM4Op_setRatio(p, 0, FL(1.50) ); FM4Op_setRatio(p, 1, FL(3.00) * FL(0.995)); FM4Op_setRatio(p, 2, FL(2.99) * FL(1.005)); FM4Op_setRatio(p, 3, FL(6.00) * FL(0.997)); p->gains[0] = amp * FM4Op_gains[99]; p->gains[1] = amp * FM4Op_gains[71]; p->gains[2] = amp * FM4Op_gains[93]; p->gains[3] = amp * FM4Op_gains[85]; ADSR_setAllTimes(csound, &p->adsr[0], FL(0.05), FL(0.05), FM4Op_susLevels[14], FL(0.05)); ADSR_setAllTimes(csound, &p->adsr[1], FL(0.02), FL(0.50), FM4Op_susLevels[13], FL(0.5)); ADSR_setAllTimes(csound, &p->adsr[2], FL(0.02), FL(0.30), FM4Op_susLevels[11], FL(0.05)); ADSR_setAllTimes(csound, &p->adsr[3], FL(0.02), FL(0.05), FM4Op_susLevels[13], FL(0.01)); p->twozero.gain = FL(0.0); /* modDepth = FL(0.005); */ ADSR_keyOn(&p->adsr[0]); ADSR_keyOn(&p->adsr[1]); ADSR_keyOn(&p->adsr[2]); ADSR_keyOn(&p->adsr[3]); return OK; } int percflute(CSOUND *csound, FM4OP *p) { MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT amp = *p->amp * AMP_RSCALE; /* Normalised */ MYFLT c1 = *p->control1; MYFLT c2 = *p->control2; p->baseFreq = *p->frequency; p->gains[0] = amp * FM4Op_gains[99] * FL(0.5); p->gains[1] = amp * FM4Op_gains[71] * FL(0.5); p->gains[2] = amp * FM4Op_gains[93] * FL(0.5); p->gains[3] = amp * FM4Op_gains[85] * FL(0.5); p->v_rate = *p->vibFreq * p->vibWave->flen * csound->onedsr; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;n #include "follow.h" static int flwset(CSOUND *csound, FOL *p) { p->wgh = p->max = FL(0.0); p->length = (int32)(*p->len * CS_ESR); if (UNLIKELY(p->length<=0L)) { /* RWD's suggestion */ csound->Warning(csound, Str("follow - zero length!")); p->length = (int32)CS_ESR; } p->count = p->length; return OK; } /* Use absolute value rather than max/min */ static int follow(CSOUND *csound, FOL *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *in = p->in, *out = p->out; MYFLT max = p->max; int32 count = p->count; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; n max) max = sig; if (UNLIKELY(--count == 0L)) { p->wgh = max; max = FL(0.0); count = p->length; } out[n] = p->wgh; } p->max = max; p->count = count; return OK; } /* The Jean-Marc Jot (IRCAM) envelope follower, from code by Bram.DeJong@rug.ac.be and James Maccartney posted on music-dsp; Transferred to csound by JPff, 2000 feb 12 */ static int envset(CSOUND *csound, ENV *p) { /* Note - 6.90775527898 -- log(0.001) */ p->lastatt = *p->attack; if (p->lastatt<=FL(0.0)) p->ga = EXP(- FL(69.0775527898)*csound->onedsr); else p->ga = EXP(- FL(6.90775527898)/(CS_ESR* p->lastatt)); p->lastrel = *p->release; if (p->lastrel<=FL(0.0)) p->gr = EXP(- FL(69.0775527898)*csound->onedsr); else p->gr = EXP(- FL(6.90775527898)/(CS_ESR* p->lastrel)); p->envelope = FL(0.0); return OK; } static int envext(CSOUND *csound, ENV *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT envelope = p->envelope; MYFLT ga, gr; MYFLT *in = p->in, *out = p->out; if (p->lastatt!=*p->attack) { p->lastatt = *p->attack; if (p->lastatt<=FL(0.0)) ga = p->ga = EXP(- FL(69.0775527898)*csound->onedsr); // EXP(-FL(10000.0)*csound->onedsr); else ga = p->ga = EXP(- FL(6.90775527898)/(CS_ESR* p->lastatt)); //EXP(-FL(1.0)/(CS_ESR* p->lastatt)); } else ga = p->ga; if (p->lastrel!=*p->release) { p->lastrel = *p->release; if (p->lastrel<=FL(0.0)) gr = p->gr = EXP(- FL(69.0775527898)*csound->onedsr); //EXP(-FL(100.0)*csound->onedsr); else gr = p->gr = EXP(- FL(6.90775527898)/(CS_ESR* p->lastrel)); //EXP(-FL(1.0)/(CS_ESR* p->lastrel)); } else gr = p->gr; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;nenvelope = envelope; return OK; } #define S(x) sizeof(x) static OENTRY localops[] = { { "follow", S(FOL), 0, 5, "a", "ai", (SUBR)flwset, NULL, (SUBR)follow }, { "follow2", S(ENV), 0, 5, "a", "akk", (SUBR)envset, NULL, (SUBR)envext } }; int follow_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/follow.h000066400000000000000000000027071321653344700161560ustar00rootroot00000000000000/* follow.h: Copyright (C) 1994, 1999 Paris Smaragdis, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Envelope follower by Paris Smaragdis */ /* Berklee College of Music Csound development team */ /* Copyright (c) August 1994. All rights reserved */ typedef struct { OPDS h; MYFLT *out, *in, *len; MYFLT max, wgh; int32 length; int32 count; } FOL; /* For implementation of Jot envelope follower -- JPff Feb 2000 */ typedef struct { OPDS h; MYFLT *out, *in, *attack, *release; MYFLT lastatt, lastrel, envelope, ga, gr; } ENV; csound-6.10.0/Opcodes/fout.c000066400000000000000000001450471321653344700156310ustar00rootroot00000000000000/* fout.c: Copyright (C) 1999 Gabriel Maldonado, John ffitch, Matt Ingalls (C) 2005, 2006 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Opcodes By Gabriel Maldonado, 1999 */ /* Code modified by JPff to remove fixed size arrays, allow AIFF and WAV, and close files neatly. Also bugs fixed */ #include "stdopcod.h" #include #include "fout.h" #include "soundio.h" #include /* remove a file reference, optionally closing the file */ static CS_NOINLINE int fout_deinit_callback(CSOUND *csound, void *p_) { FOUT_FILE *p = (FOUT_FILE*) p_; struct fileinTag *pp; p->sf = (SNDFILE*) NULL; p->f = (FILE*) NULL; if (p->idx) { pp = &(((STDOPCOD_GLOBALS*) csound->stdOp_Env)->file_opened[p->idx - 1]); p->idx = 0; if (pp->refCount) { pp->refCount--; /* VL 29/08/07: files were not being closed properly, changed check to 0 */ if (pp->refCount == 0/*0x80000000U*/) { pp->file = (SNDFILE*) NULL; pp->raw = (FILE*) NULL; csound->Free(csound, pp->name); pp->name = (char*) NULL; pp->do_scale = 0; pp->refCount = 0U; if (pp->fd != NULL) { if ((csound->oparms->msglevel & 7) == 7) csound->Message(csound, Str("Closing file '%s'...\n"), csound->GetFileName(pp->fd)); csound->FileClose(csound, pp->fd); pp->fd = NULL; } } } } return OK; } static CS_NOINLINE int fout_open_file(CSOUND *csound, FOUT_FILE *p, void *fp, int fileType, MYFLT *iFile, int isString, void *fileParams, int forceSync) { STDOPCOD_GLOBALS *pp = (STDOPCOD_GLOBALS*) csound->stdOp_Env; char *name; int idx, csFileType, need_deinit = 0; if (p != (FOUT_FILE*) NULL) p->async = 0; if (fp != NULL) { if (fileType == CSFILE_STD) *((FILE**) fp) = (FILE*) NULL; else *((SNDFILE**) fp) = (SNDFILE*) NULL; } /* if the opcode already uses a file, remove old reference first */ if (p != (FOUT_FILE*) NULL) { if (p->idx) fout_deinit_callback(csound, (void*) p); else need_deinit = 1; } /* get file name, */ if (isString) name = cs_strdup(csound, ((STRINGDAT *)iFile)->data); else if (csound->ISSTRCOD(*iFile)) name = cs_strdup(csound, get_arg_string(csound, *iFile)); /* else csound->strarg2name(csound, NULL, iFile, "fout.", 0);*/ else { /* or handle to previously opened file */ idx = (int) MYFLT2LRND(*iFile); if (UNLIKELY(idx < 0 || idx > pp->file_num || (fileType == CSFILE_STD && pp->file_opened[idx].raw == NULL) || (fileType != CSFILE_STD && pp->file_opened[idx].file == NULL))) { return csound->InitError(csound, Str("invalid file handle")); } goto returnHandle; } /* check for a valid name */ if (UNLIKELY(name == NULL || name[0] == '\0')) { csound->Free(csound, name); return csound->InitError(csound, Str("invalid file name")); } /* is this file already open ? */ if (fileType == CSFILE_STD) { for (idx = 0; idx <= pp->file_num; idx++) { if (pp->file_opened[idx].raw != (FILE*) NULL && strcmp(pp->file_opened[idx].name, name) == 0) goto returnHandle; } } else { for (idx = 0; idx <= pp->file_num; idx++) { if (pp->file_opened[idx].file != (SNDFILE*) NULL && strcmp(pp->file_opened[idx].name, name) == 0) goto returnHandle; } } /* allocate new file handle, or use an already existing unused one */ for (idx = 0; idx <= pp->file_num; idx++) { if (pp->file_opened[idx].fd == NULL) break; } if (idx > pp->file_num) { if (idx >= pp->file_max) { struct fileinTag *tmp; /* Expand by 4 each time */ pp->file_max = (idx | 3) + 1; tmp = (struct fileinTag *) csound->ReAlloc(csound, pp->file_opened, sizeof(struct fileinTag) * pp->file_max); pp->file_opened = tmp; memset(&(tmp[pp->file_num + 1]), 0, sizeof(struct fileinTag) * (pp->file_max - (pp->file_num + 1))); } pp->file_num = idx; } memset(&pp->file_opened[idx], 0, sizeof(struct fileinTag)); /* pp->file_opened[idx].file = (SNDFILE*) NULL; */ /* pp->file_opened[idx].raw = (FILE*) NULL; */ /* pp->file_opened[idx].fd = NULL; */ /* pp->file_opened[idx].name = (char*) NULL; */ /* pp->file_opened[idx].do_scale = 0; */ /* pp->file_opened[idx].refCount = 0U; */ /* attempt to open file */ if (fileType == CSFILE_STD) { FILE *f; void *fd; char *filemode = (char*)fileParams; /* akozar: csFileType cannot be as specific as I'd like since it is not possible to know the real file type until this handle is used */ if ((strcmp(filemode, "rb") == 0 || (strcmp(filemode, "wb") == 0))) csFileType = CSFTYPE_OTHER_BINARY; else csFileType = CSFTYPE_OTHER_TEXT; fd = csound->FileOpen2(csound, &f, fileType, name, fileParams, "", csFileType, 0); if (UNLIKELY(fd == NULL)) { csound->InitError(csound, Str("error opening file '%s'"), name); csound->Free(csound, name); return NOTOK; } /* setvbuf(f, (char *) NULL, _IOLBF, 0); */ /* Ensure line buffering */ pp->file_opened[idx].raw = f; pp->file_opened[idx].fd = fd; } else { SNDFILE *sf; void *fd; //int buf_reqd; int do_scale = 0; if (fileType == CSFILE_SND_W) { do_scale = ((SF_INFO*) fileParams)->format; csFileType = csound->sftype2csfiletype(do_scale); if (csound->realtime_audio_flag == 0 || forceSync == 1) { fd = csound->FileOpen2(csound, &sf, fileType, name, fileParams, "SFDIR", csFileType, 0); p->async = 0; } else { p->fd = fd = csound->FileOpenAsync(csound, &sf, fileType, name, fileParams, "SFDIR;SSDIR", CSFTYPE_UNKNOWN_AUDIO, p->bufsize, 0); p->async = 1; } p->nchnls = ((SF_INFO*) fileParams)->channels; } else { if (csound->realtime_audio_flag == 0 || forceSync == 1) { fd = csound->FileOpen2(csound, &sf, fileType, name, fileParams, "SFDIR;SSDIR", CSFTYPE_UNKNOWN_AUDIO, 0); p->async = 0; } else { p->fd = fd = csound->FileOpenAsync(csound, &sf, fileType, name, fileParams, "SFDIR;SSDIR", CSFTYPE_UNKNOWN_AUDIO, p->bufsize, 0); p->async = 1; } p->nchnls = ((SF_INFO*) fileParams)->channels; do_scale = ((SF_INFO*) fileParams)->format; } do_scale = (SF2TYPE(do_scale) == TYP_RAW ? 0 : 1); if (UNLIKELY(fd == NULL)) { csound->InitError(csound, Str("error opening sound file '%s'"), name); csound->Free(csound, name); return NOTOK; } if (!do_scale) { #ifdef USE_DOUBLE sf_command(sf, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE); #else sf_command(sf, SFC_SET_NORM_FLOAT, NULL, SF_FALSE); #endif } /* if (CS_KSMPS >= 512) buf_reqd = CS_KSMPS * ((SF_INFO*) fileParams)->channels; else buf_reqd = (1 + (int)(512 / CS_KSMPS)) * CS_KSMPS * ((SF_INFO*) fileParams)->channels; if (UNLIKELY(buf_reqd > pp->buf_size)) { pp->buf_size = buf_reqd; pp->buf = (MYFLT*) csound->ReAlloc(csound, pp->buf, sizeof(MYFLT) * buf_reqd); } */ /* VL - now using per-instance buffer */ pp->file_opened[idx].file = sf; pp->file_opened[idx].fd = fd; pp->file_opened[idx].do_scale = do_scale; } /* store file information */ pp->file_opened[idx].name = name; returnHandle: /* return 'idx' as file handle */ if (fp != NULL) { if (fileType == CSFILE_STD) *((FILE**) fp) = pp->file_opened[idx].raw; else *((SNDFILE**) fp) = pp->file_opened[idx].file; } if (p != (FOUT_FILE*) NULL) { if (fileType == CSFILE_STD) { p->sf = (SNDFILE*) NULL; p->f = pp->file_opened[idx].raw; } else { p->sf = pp->file_opened[idx].file; p->f = (FILE*) NULL; } p->idx = idx + 1; pp->file_opened[idx].refCount++; if (need_deinit) { p->h.insdshead = csound->ids->insdshead; /* FIXME: should check for error here */ csound->RegisterDeinitCallback(csound, p, fout_deinit_callback); } } return idx; } static int outfile(CSOUND *csound, OUTFILE *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, j, k, nsmps = CS_KSMPS; uint32_t nargs = p->nargs; MYFLT *buf = (MYFLT *) p->buf.auxp; if (UNLIKELY(early)) nsmps -= early; if (p->f.sf == NULL) { if (p->f.f != NULL) { /* VL: make sure there is an open file */ FILE *fp = p->f.f; for (k = offset; k < nsmps; k++) { for (j = 0; j < nargs; j++) fprintf(fp, "%g ", p->argums[j][k]); fprintf(fp, "\n"); } } } else { for (j = offset, k = p->buf_pos; j < nsmps; j++) for (i = 0; i < nargs; i++) buf[k++] = p->argums[i][j] * p->scaleFac; p->buf_pos = k; if (p->buf_pos >= p->guard_pos) { //#ifndef USE_DOUBLE //sf_write_float(p->f.sf, buf, p->buf_pos); //#else //sf_write_double(p->f.sf, buf, p->buf_pos); //#endif if (p->f.async==1) csound->WriteAsync(csound, p->f.fd, buf, p->buf_pos); else sf_write_MYFLT(p->f.sf, buf, p->buf_pos); p->buf_pos = 0; } } return OK; } static int outfile_array(CSOUND *csound, OUTFILEA *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, j, k, nsmps = CS_KSMPS; uint32_t nargs = p->tabin->sizes[0]; MYFLT *buf = (MYFLT *) p->buf.auxp; MYFLT *data = p->tabin->data; if (UNLIKELY(early)) nsmps -= early; if (p->f.sf == NULL) { if (p->f.f != NULL) { /* VL: make sure there is an open file */ FILE *fp = p->f.f; for (k = offset; k < nsmps; k++) { for (j = 0; j < nargs; j++) fprintf(fp, "%g ", data[j*CS_KSMPS+k]); fprintf(fp, "\n"); } } } else { for (j = offset, k = p->buf_pos; j < nsmps; j++) for (i = 0; i < nargs; i++) buf[k++] = data[i*CS_KSMPS+j] * p->scaleFac; p->buf_pos = k; if (p->buf_pos >= p->guard_pos) { //#ifndef USE_DOUBLE //sf_write_float(p->f.sf, buf, p->buf_pos); //#else //sf_write_double(p->f.sf, buf, p->buf_pos); //#endif if (p->f.async==1) csound->WriteAsync(csound, p->f.fd, buf, p->buf_pos); else sf_write_MYFLT(p->f.sf, buf, p->buf_pos); p->buf_pos = 0; } } return OK; } static const int fout_format_table[51] = { /* 0 - 9 */ (SF_FORMAT_FLOAT | SF_FORMAT_RAW), (SF_FORMAT_PCM_16 | SF_FORMAT_RAW), SF_FORMAT_PCM_16, SF_FORMAT_ULAW, SF_FORMAT_PCM_16, SF_FORMAT_PCM_32, SF_FORMAT_FLOAT, SF_FORMAT_PCM_U8, SF_FORMAT_PCM_24, SF_FORMAT_DOUBLE, /* 10 - 19 */ SF_FORMAT_WAV, (SF_FORMAT_PCM_S8 | SF_FORMAT_WAV), (SF_FORMAT_ALAW | SF_FORMAT_WAV), (SF_FORMAT_ULAW | SF_FORMAT_WAV), (SF_FORMAT_PCM_16 | SF_FORMAT_WAV), (SF_FORMAT_PCM_32 | SF_FORMAT_WAV), (SF_FORMAT_FLOAT | SF_FORMAT_WAV), (SF_FORMAT_PCM_U8 | SF_FORMAT_WAV), (SF_FORMAT_PCM_24 | SF_FORMAT_WAV), (SF_FORMAT_DOUBLE | SF_FORMAT_WAV), /* 20 - 29 */ SF_FORMAT_AIFF, (SF_FORMAT_PCM_S8 | SF_FORMAT_AIFF), (SF_FORMAT_ALAW | SF_FORMAT_AIFF), (SF_FORMAT_ULAW | SF_FORMAT_AIFF), (SF_FORMAT_PCM_16 | SF_FORMAT_AIFF), (SF_FORMAT_PCM_32 | SF_FORMAT_AIFF), (SF_FORMAT_FLOAT | SF_FORMAT_AIFF), (SF_FORMAT_PCM_U8 | SF_FORMAT_AIFF), (SF_FORMAT_PCM_24 | SF_FORMAT_AIFF), (SF_FORMAT_DOUBLE | SF_FORMAT_AIFF), /* 30 - 39 */ SF_FORMAT_RAW, (SF_FORMAT_PCM_S8 | SF_FORMAT_RAW), (SF_FORMAT_ALAW | SF_FORMAT_RAW), (SF_FORMAT_ULAW | SF_FORMAT_RAW), (SF_FORMAT_PCM_16 | SF_FORMAT_RAW), (SF_FORMAT_PCM_32 | SF_FORMAT_RAW), (SF_FORMAT_FLOAT | SF_FORMAT_RAW), (SF_FORMAT_PCM_U8 | SF_FORMAT_RAW), (SF_FORMAT_PCM_24 | SF_FORMAT_RAW), (SF_FORMAT_DOUBLE | SF_FORMAT_RAW), /* 40 - 49 */ SF_FORMAT_IRCAM, (SF_FORMAT_PCM_S8 | SF_FORMAT_IRCAM), (SF_FORMAT_ALAW | SF_FORMAT_IRCAM), (SF_FORMAT_ULAW | SF_FORMAT_IRCAM), (SF_FORMAT_PCM_16 | SF_FORMAT_IRCAM), (SF_FORMAT_PCM_32 | SF_FORMAT_IRCAM), (SF_FORMAT_FLOAT | SF_FORMAT_IRCAM), (SF_FORMAT_PCM_U8 | SF_FORMAT_IRCAM), (SF_FORMAT_PCM_24 | SF_FORMAT_IRCAM), (SF_FORMAT_DOUBLE | SF_FORMAT_IRCAM), /* 50 */ (SF_FORMAT_OGG | SF_FORMAT_VORBIS) }; static int fout_flush_callback(CSOUND *csound, void *p_) { OUTFILE *p = (OUTFILE*) p_; if (p->f.sf != NULL && p->buf_pos > 0) { //#ifndef USE_DOUBLE //sf_write_float(p->f.sf, (float*) p->buf.auxp, p->buf_pos); //#else //sf_write_double(p->f.sf, (double*) p->buf.auxp, p->buf_pos); //#endif if (p->f.async == 1) csound->WriteAsync(csound, p->f.fd, (MYFLT *) p->buf.auxp, p->buf_pos); else sf_write_MYFLT(p->f.sf, (MYFLT *) p->buf.auxp, p->buf_pos); } return OK; } static int fouta_flush_callback(CSOUND *csound, void *p_) { OUTFILEA *p = (OUTFILEA*) p_; if (p->f.sf != NULL && p->buf_pos > 0) { //#ifndef USE_DOUBLE //sf_write_float(p->f.sf, (float*) p->buf.auxp, p->buf_pos); //#else //sf_write_double(p->f.sf, (double*) p->buf.auxp, p->buf_pos); //#endif if (p->f.async == 1) csound->WriteAsync(csound, p->f.fd, (MYFLT *) p->buf.auxp, p->buf_pos); else sf_write_MYFLT(p->f.sf, (MYFLT *) p->buf.auxp, p->buf_pos); } return OK; } static int outfile_set_S(CSOUND *csound, OUTFILE *p/*, int istring*/) { SF_INFO sfinfo; int format_, n, buf_reqd; int istring = 1; memset(&sfinfo, 0, sizeof(SF_INFO)); format_ = (int) MYFLT2LRND(*p->iflag); if (format_ >= 51) sfinfo.format = SF_FORMAT_PCM_16 | SF_FORMAT_RAW; else if (format_ < 0) { sfinfo.format = FORMAT2SF(csound->oparms->outformat); sfinfo.format |= TYPE2SF(csound->oparms->filetyp); } else sfinfo.format = fout_format_table[format_]; if (!SF2FORMAT(sfinfo.format)) sfinfo.format |= FORMAT2SF(csound->oparms->outformat); if (!SF2TYPE(sfinfo.format)) sfinfo.format |= TYPE2SF(csound->oparms->filetyp); sfinfo.samplerate = (int) MYFLT2LRND(CS_ESR); p->nargs = p->INOCOUNT - 2; p->buf_pos = 0; if (CS_KSMPS >= 512) p->guard_pos = CS_KSMPS * p->nargs; else p->guard_pos = 512* p->nargs; if (CS_KSMPS >= 512) buf_reqd = CS_KSMPS * p->nargs; else buf_reqd = (1 + (int)(512 / CS_KSMPS)) * CS_KSMPS * p->nargs; if (p->buf.auxp == NULL || p->buf.size < buf_reqd*sizeof(MYFLT)) { csound->AuxAlloc(csound, sizeof(MYFLT)*buf_reqd, &p->buf); } p->f.bufsize = p->buf.size; sfinfo.channels = p->nargs; n = fout_open_file(csound, &(p->f), NULL, CSFILE_SND_W, p->fname, istring, &sfinfo, 0); if (UNLIKELY(n < 0)) return NOTOK; if (((STDOPCOD_GLOBALS*) csound->stdOp_Env)->file_opened[n].do_scale) p->scaleFac = csound->dbfs_to_float; else p->scaleFac = FL(1.0); csound->RegisterDeinitCallback(csound, p, fout_flush_callback); return OK; } /* static int outfile_set(CSOUND *csound, OUTFILE *p){ */ /* return outfile_set_(csound,p,0); */ /* } */ /* static int outfile_set_S(CSOUND *csound, OUTFILE *p){ */ /* return outfile_set_(csound,p,1); */ /* } */ static int outfile_set_A(CSOUND *csound, OUTFILEA *p) { SF_INFO sfinfo; int format_, n, buf_reqd; int len = p->tabin->sizes[0]; memset(&sfinfo, 0, sizeof(SF_INFO)); format_ = (int) MYFLT2LRND(*p->iflag); if (format_ >= 51) sfinfo.format = SF_FORMAT_PCM_16 | SF_FORMAT_RAW; else if (format_ < 0) { sfinfo.format = FORMAT2SF(csound->oparms->outformat); sfinfo.format |= TYPE2SF(csound->oparms->filetyp); } else sfinfo.format = fout_format_table[format_]; if (!SF2FORMAT(sfinfo.format)) sfinfo.format |= FORMAT2SF(csound->oparms->outformat); if (!SF2TYPE(sfinfo.format)) sfinfo.format |= TYPE2SF(csound->oparms->filetyp); sfinfo.samplerate = (int) MYFLT2LRND(CS_ESR); p->buf_pos = 0; if (CS_KSMPS >= 512) buf_reqd = p->guard_pos = CS_KSMPS * len; else { p->guard_pos = 512 * len; buf_reqd = (1 + (int)(512 / CS_KSMPS)) * p->guard_pos; // Or...... //buf_reqd = (1 + (int)(512 / CS_KSMPS)) * CS_KSMPS * len; } if (p->buf.auxp == NULL || p->buf.size < buf_reqd*sizeof(MYFLT)) { csound->AuxAlloc(csound, sizeof(MYFLT)*buf_reqd, &p->buf); } p->f.bufsize = p->buf.size; sfinfo.channels = len; n = fout_open_file(csound, &(p->f), NULL, CSFILE_SND_W, p->fname, 1, &sfinfo, 0); if (UNLIKELY(n < 0)) return NOTOK; if (((STDOPCOD_GLOBALS*) csound->stdOp_Env)->file_opened[n].do_scale) p->scaleFac = csound->dbfs_to_float; else p->scaleFac = FL(1.0); csound->RegisterDeinitCallback(csound, p, fouta_flush_callback); return OK; } static int koutfile(CSOUND *csound, KOUTFILE *p) { int i, k; int nargs = p->nargs; MYFLT *buf = (MYFLT *) p->buf.auxp; for (i = 0, k = p->buf_pos; i < nargs; i++) buf[k++] = p->argums[i][0] * p->scaleFac; p->buf_pos = k; if (p->buf_pos >= p->guard_pos) { //#ifndef USE_DOUBLE //sf_write_float(p->f.sf, buf, p->buf_pos); //#else //sf_write_double(p->f.sf, buf, p->buf_pos); //#endif if (p->f.async==1) csound->WriteAsync(csound, p->f.fd, buf, p->buf_pos); else sf_write_MYFLT(p->f.sf, buf, p->buf_pos); p->buf_pos = 0; } return OK; } static int koutfile_set_(CSOUND *csound, KOUTFILE *p, int istring) { SF_INFO sfinfo; int format_, n, buf_reqd; memset(&sfinfo, 0, sizeof(SF_INFO)); p->nargs = p->INOCOUNT - 2; p->buf_pos = 0; if (CS_KSMPS >= 512) p->guard_pos = CS_KSMPS * p->nargs; else p->guard_pos = 512 * p->nargs; sfinfo.channels = p->nargs; sfinfo.samplerate = (int) MYFLT2LRND(CS_EKR); format_ = (int) MYFLT2LRND(*p->iflag); if ((unsigned int) format_ >= (unsigned int) 10) sfinfo.format = SF_FORMAT_PCM_16 | SF_FORMAT_RAW; else sfinfo.format = fout_format_table[format_] | SF_FORMAT_RAW; if (CS_KSMPS >= 512) buf_reqd = CS_KSMPS * p->nargs; else buf_reqd = (1 + (int)(512 / CS_KSMPS)) * CS_KSMPS * p->nargs; if (p->buf.auxp == NULL || p->buf.size < buf_reqd*sizeof(MYFLT)) { csound->AuxAlloc(csound, sizeof(MYFLT)*buf_reqd, &p->buf); } p->f.bufsize = p->buf.size; n = fout_open_file(csound, &(p->f), NULL, CSFILE_SND_W, p->fname, istring, &sfinfo, 0); if (UNLIKELY(n < 0)) return NOTOK; if (((STDOPCOD_GLOBALS*) csound->stdOp_Env)->file_opened[n].do_scale) p->scaleFac = csound->dbfs_to_float; else p->scaleFac = FL(1.0); csound->RegisterDeinitCallback(csound, p, fout_flush_callback); return OK; } static int koutfile_set(CSOUND *csound, KOUTFILE *p){ return koutfile_set_(csound,p,0); } static int koutfile_set_S(CSOUND *csound, KOUTFILE *p){ return koutfile_set_(csound,p,1); } /*--------------*/ /* syntax: ihandle fiopen "filename" [, iascii] */ /* open a file and return its handle */ /* the handle is simply a stack index */ static int fiopen_(CSOUND *csound, FIOPEN *p, int istring) { char *omodes[] = {"w", "r", "wb", "rb"}; FILE *rfp = (FILE*) NULL; int idx = (int) MYFLT2LRND(*p->iascii), n; if (idx < 0 || idx > 3) idx = 0; n = fout_open_file(csound, (FOUT_FILE*) NULL, &rfp, CSFILE_STD, p->fname, istring, omodes[idx], 1); if (UNLIKELY(n < 0)) return NOTOK; if (idx > 1) setbuf(rfp, NULL); *p->ihandle = (MYFLT) n; return OK; } static int fiopen(CSOUND *csound, FIOPEN *p){ return fiopen_(csound, p, 0); } static int fiopen_S(CSOUND *csound, FIOPEN *p){ return fiopen_(csound, p, 1); } static int ficlose_opcode_(CSOUND *csound, FICLOSE *p, int istring) { STDOPCOD_GLOBALS *pp = (STDOPCOD_GLOBALS*) csound->stdOp_Env; int idx = -1; if (istring || csound->ISSTRCOD(*(p->iFile))) { char *fname = NULL; if (istring) fname = cs_strdup(csound, ((STRINGDAT *)p->iFile)->data); else if (csound->ISSTRCOD(*(p->iFile))) fname = cs_strdup(csound, get_arg_string(csound, *p->iFile)); if (UNLIKELY(fname == NULL || fname[0] == (char) 0)) { if (fname != NULL) csound->Free(csound, fname); return csound->InitError(csound, Str("invalid file name")); } for (idx = 0; idx <= pp->file_num; idx++) { if (pp->file_opened[idx].fd != NULL && pp->file_opened[idx].name != (char*) NULL && strcmp(fname, pp->file_opened[idx].name) == 0) break; } if (UNLIKELY(idx > pp->file_num)) { csound->Warning(csound, Str("cannot close '%s': " "not found in list of open files"), fname); csound->Free(csound, fname); return OK; } csound->Free(csound, fname); } else { idx = (int) MYFLT2LRND(*(p->iFile)); if (UNLIKELY(idx < 0 || idx > pp->file_num || pp->file_opened[idx].fd == NULL)) { csound->Warning(csound, Str("cannot close file #%d: not a valid handle"), idx); return OK; } } if (pp->file_opened[idx].refCount) { if (UNLIKELY(!(pp->file_opened[idx].refCount & 0x80000000U))) { pp->file_opened[idx].refCount |= 0x80000000U; csound->Warning(csound, Str("file #%d (%s) is in use, will be closed " "when released"), idx, pp->file_opened[idx].name); } } else { FOUT_FILE tmp; pp->file_opened[idx].refCount = 1; /*ref count was set to 0x80000001U, but it needs to be 1 */ memset(&tmp, 0, sizeof(FOUT_FILE)); tmp.h.insdshead = p->h.insdshead; tmp.idx = idx + 1; fout_deinit_callback(csound, (void*) &tmp); } return OK; } static int ficlose_opcode(CSOUND *csound, FICLOSE *p){ return ficlose_opcode_(csound,p,0); } static int ficlose_opcode_S(CSOUND *csound, FICLOSE *p){ return ficlose_opcode_(csound,p,1); } /* syntax: fouti ihandle, iascii, iflag, iarg1 [, iarg2, ...., iargN] */ static int ioutfile_set(CSOUND *csound, IOUTFILE *p) { STDOPCOD_GLOBALS *pp = (STDOPCOD_GLOBALS*) csound->stdOp_Env; MYFLT **args = p->argums; FILE *rfil; uint32_t j; int n = (int) MYFLT2LRND(*p->ihandle); if (UNLIKELY(n < 0 || n > pp->file_num)) return csound->InitError(csound, Str("fouti: invalid file handle")); rfil = pp->file_opened[n].raw; if (UNLIKELY(rfil == NULL)) return csound->InitError(csound, Str("fouti: invalid file handle")); if (*p->iascii == 0) { /* ascii format */ switch ((int) MYFLT2LRND(*p->iflag)) { case 1: { /* with prefix (i-statement, p1, p2 and p3) */ int p1 = (int) p->h.insdshead->p1.value; double p2 = (double) CS_KCNT * CS_ONEDKR; double p3 = p->h.insdshead->p3.value; if (p3 > FL(0.0)) fprintf(rfil, "i %i %f %f ", p1, p2, p3); else fprintf(rfil, "i %i %f . ", p1, p2); } break; case 2: /* with prefix (start at 0 time) */ if (pp->fout_kreset == 0) pp->fout_kreset = CS_KCNT; { int p1 = (int) p->h.insdshead->p1.value; double p2 = (double) (CS_KCNT - pp->fout_kreset) * CS_ONEDKR; double p3 = p->h.insdshead->p3.value; if (p3 > FL(0.0)) fprintf(rfil, "i %i %f %f ", p1, p2, p3); else fprintf(rfil, "i %i %f . ", p1, p2); } break; case 3: /* reset */ pp->fout_kreset = 0; return OK; } for (j = 0; j < p->INOCOUNT - 3; j++) { fprintf(rfil, " %f", (double) *args[j]); } putc('\n', rfil); } else { /* binary format */ for (j = 0; j < p->INOCOUNT - 3; j++) { if (UNLIKELY(1!=fwrite(args[j], sizeof(MYFLT), 1, rfil))) return NOTOK; } } return OK; } static int ioutfile_set_r(CSOUND *csound, IOUTFILE_R *p) { STDOPCOD_GLOBALS *pp = (STDOPCOD_GLOBALS*) csound->stdOp_Env; if (p->h.insdshead->xtratim < 1) p->h.insdshead->xtratim = 1; p->counter = CS_KCNT; p->done = 1; if (*p->iflag == 2 && pp->fout_kreset == 0) pp->fout_kreset = CS_KCNT; return OK; } static int ioutfile_r(CSOUND *csound, IOUTFILE_R *p) { STDOPCOD_GLOBALS *pp; MYFLT **args; FILE *rfil; uint32_t j; int n; if (!p->h.insdshead->relesing || !p->done) return OK; pp = (STDOPCOD_GLOBALS*) csound->stdOp_Env; args = p->argums; n = (int) MYFLT2LRND(*p->ihandle); if (UNLIKELY(n < 0 || n > pp->file_num)) return csound->InitError(csound, Str("fouti: invalid file handle")); rfil = pp->file_opened[n].raw; if (UNLIKELY(rfil == NULL)) return csound->InitError(csound, Str("fouti: invalid file handle")); if (*p->iascii == 0) { /* ascii format */ switch ((int) MYFLT2LRND(*p->iflag)) { case 1: { /* whith prefix (i-statement, p1, p2 and p3) */ int p1 = (int) p->h.insdshead->p1.value; double p2 = p->counter * CS_ONEDKR; double p3 = (double) (CS_KCNT - p->counter) * CS_ONEDKR; fprintf(rfil, "i %i %f %f ", p1, p2, p3); } break; case 2: /* with prefix (start at 0 time) */ { int p1 = (int) p->h.insdshead->p1.value; double p2 = (p->counter - pp->fout_kreset) * CS_ONEDKR; double p3 = (double) (CS_KCNT - p->counter) * CS_ONEDKR; fprintf(rfil, "i %i %f %f ", p1, p2, p3); } break; case 3: /* reset */ pp->fout_kreset = 0; return OK; } for (j = 0; j < p->INOCOUNT - 3; j++) { fprintf(rfil, " %f", (double) *args[j]); } putc('\n', rfil); } else { /* binary format */ for (j = 0; j < p->INOCOUNT - 3; j++) { if (UNLIKELY(1!=fwrite(args[j], sizeof(MYFLT), 1, rfil))) return NOTOK; } } p->done = 0; return OK; } /*----------------------------------*/ static int infile_set_(CSOUND *csound, INFILE *p, int istring) { SF_INFO sfinfo; int n, buf_reqd; p->nargs = p->INOCOUNT - 3; p->currpos = MYFLT2LRND(*p->iskpfrms); p->flag = 1; memset(&sfinfo, 0, sizeof(SF_INFO)); sfinfo.samplerate = (int) MYFLT2LRND(CS_ESR); if ((int) MYFLT2LRND(*p->iflag) == 0) sfinfo.format = FORMAT2SF(AE_FLOAT) | TYPE2SF(TYP_RAW); else sfinfo.format = FORMAT2SF(AE_SHORT) | TYPE2SF(TYP_RAW); sfinfo.channels = p->INOCOUNT - 3; if (CS_KSMPS >= 512) p->frames = CS_KSMPS; else p->frames = (int)(512 / CS_KSMPS) * CS_KSMPS; if (CS_KSMPS >= 512) buf_reqd = CS_KSMPS * sfinfo.channels; else buf_reqd = (1 + (int)(512 / CS_KSMPS)) * CS_KSMPS * p->nargs; if (p->buf.auxp == NULL || p->buf.size < buf_reqd*sizeof(MYFLT)) { csound->AuxAlloc(csound, sizeof(MYFLT)*buf_reqd, &p->buf); } p->f.bufsize = p->buf.size; n = fout_open_file(csound, &(p->f), NULL, CSFILE_SND_R, p->fname, istring, &sfinfo, 0); if (UNLIKELY(n < 0)) return NOTOK; if (((STDOPCOD_GLOBALS*) csound->stdOp_Env)->file_opened[n].do_scale) p->scaleFac = csound->e0dbfs; else p->scaleFac = FL(1.0); p->guard_pos = p->frames * p->nargs; p->buf_pos = p->guard_pos; if (p->f.async == 1) csound->FSeekAsync(csound,p->f.fd, p->currpos*p->f.nchnls, SEEK_SET); return OK; } static int infile_set(CSOUND *csound, INFILE *p){ return infile_set_(csound,p,0); } static int infile_set_S(CSOUND *csound, INFILE *p){ return infile_set_(csound,p,1); } static inline void tabensure(CSOUND *csound, ARRAYDAT *p, int size) { if (p->data==NULL || p->dimensions == 0 || (p->dimensions==1 && p->sizes[0] < size)) { uint32_t ss = sizeof(MYFLT)*size; if (p->data==NULL) p->data = (MYFLT*)csound->Malloc(csound, ss); else p->data = (MYFLT*) csound->ReAlloc(csound, p->data, ss); p->dimensions = 1; p->arrayMemberSize = sizeof(MYFLT); p->sizes = (int*)csound->Malloc(csound, sizeof(int)); p->sizes[0] = size; } } static int infile_set_A(CSOUND *csound, INFILEA *p) { SF_INFO sfinfo; int n, buf_reqd; p->currpos = MYFLT2LRND(*p->iskpfrms); p->flag = 1; memset(&sfinfo, 0, sizeof(SF_INFO)); sfinfo.samplerate = (int) MYFLT2LRND(CS_ESR); if ((int) MYFLT2LRND(*p->iflag) == 0) sfinfo.format = FORMAT2SF(AE_FLOAT) | TYPE2SF(TYP_RAW); else sfinfo.format = FORMAT2SF(AE_SHORT) | TYPE2SF(TYP_RAW); sfinfo.channels = p->INOCOUNT - 3; if (CS_KSMPS >= 512) p->frames = CS_KSMPS; else p->frames = (int)(512 / CS_KSMPS) * CS_KSMPS; p->chn = sfinfo.channels; if (CS_KSMPS >= 512) buf_reqd = CS_KSMPS * sfinfo.channels; else buf_reqd = (1 + (int)(512 / CS_KSMPS)) * CS_KSMPS * sfinfo.channels; if (p->buf.auxp == NULL || p->buf.size < buf_reqd*sizeof(MYFLT)) { csound->AuxAlloc(csound, sizeof(MYFLT)*buf_reqd, &p->buf); } p->f.bufsize = p->buf.size; n = fout_open_file(csound, &(p->f), NULL, CSFILE_SND_R, p->fname, 1, &sfinfo, 0); if (UNLIKELY(n < 0)) return NOTOK; if (((STDOPCOD_GLOBALS*) csound->stdOp_Env)->file_opened[n].do_scale) p->scaleFac = csound->e0dbfs; else p->scaleFac = FL(1.0); p->guard_pos = p->frames * p->chn; p->buf_pos = p->guard_pos; if (p->f.async == 1) csound->FSeekAsync(csound,p->f.fd, p->currpos*p->f.nchnls, SEEK_SET); tabensure(csound, p->tabout, p->chn); return OK; } static int infile_act(CSOUND *csound, INFILE *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, k, j = offset; uint32_t nsmps = CS_KSMPS, ksmps, nargs = p->nargs; MYFLT *buf = (MYFLT *) p->buf.auxp; ksmps = nsmps; if (UNLIKELY(offset)) for (i = 0; i < nargs; i++) memset(p->argums[i], '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; for (i = 0; i < nargs; i++) memset(&p->argums[i][nsmps], '\0', early*sizeof(MYFLT)); } if (p->flag) { if (p->buf_pos >= p->guard_pos) { if (UNLIKELY(p->f.async == 0)) { sf_seek(p->f.sf, p->currpos*p->f.nchnls, SEEK_SET); p->remain = (uint32_t) sf_read_MYFLT(p->f.sf, (MYFLT*) buf, p->frames*p->f.nchnls); p->remain /= p->f.nchnls; } else { p->remain = csoundReadAsync(csound,p->f.fd,(MYFLT *)buf, p->frames*p->f.nchnls); p->remain /= p->f.nchnls; } p->currpos += p->frames; p->buf_pos = 0; } if (p->remain < nsmps) nsmps = p->remain; for (k = (uint32_t)p->buf_pos; j < nsmps; j++) for (i = 0; i < nargs; i++) p->argums[i][j] = buf[k++] * p->scaleFac; p->buf_pos = k; p->remain -= ksmps; if (p->remain <= 0 && p->buf_pos < p->guard_pos) { p->flag = 0; for (; j < ksmps; j++) for (i = 0; i < nargs; i++) p->argums[i][j] = FL(0.0); } return OK; } for ( ; j < ksmps; j++) for (i = 0; i < nargs; i++) p->argums[i][j] = FL(0.0); return OK; } static int infile_arr(CSOUND *csound, INFILEA *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, k, j = offset; uint32_t nsmps = CS_KSMPS, ksmps, chn = p->chn; MYFLT *buf = (MYFLT *) p->buf.auxp; MYFLT *data = p->tabout->data; ksmps = nsmps; if (UNLIKELY(offset)) for (i = 0; i < chn; i++) memset(&data[i*chn], '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; for (i = 0; i < chn; i++) memset(&data[i*chn+nsmps], '\0', early*sizeof(MYFLT)); } if (p->flag) { if (p->buf_pos >= p->guard_pos) { if (UNLIKELY(p->f.async == 0)) { sf_seek(p->f.sf, p->currpos*p->f.nchnls, SEEK_SET); p->remain = (uint32_t) sf_read_MYFLT(p->f.sf, (MYFLT*) buf, p->frames*p->f.nchnls); p->remain /= p->f.nchnls; } else { p->remain = csoundReadAsync(csound,p->f.fd,(MYFLT *)buf, p->frames*p->f.nchnls); p->remain /= p->f.nchnls; } p->currpos += p->frames; p->buf_pos = 0; } if (p->remain < nsmps) nsmps = p->remain; for (k = (uint32_t)p->buf_pos; j < nsmps; j++) for (i = 0; i < chn; i++) data[i*chn+j] = buf[k++] * p->scaleFac; p->buf_pos = k; p->remain -= ksmps; if (p->remain <= 0 && p->buf_pos < p->guard_pos) { p->flag = 0; for (; j < ksmps; j++) for (i = 0; i < chn; i++) data[i*chn+j] = FL(0.0); } return OK; } for ( ; j < ksmps; j++) for (i = 0; i < chn; i++) data[i*chn+j] = FL(0.0); return OK; } /* ---------------------------- */ static int kinfile_set_(CSOUND *csound, KINFILE *p, int istring) { SF_INFO sfinfo; int n, buf_reqd; memset(&sfinfo, 0, sizeof(SF_INFO)); sfinfo.samplerate = (int) MYFLT2LRND(CS_EKR); if ((int) MYFLT2LRND(*p->iflag) == 0) sfinfo.format = FORMAT2SF(AE_FLOAT) | TYPE2SF(TYP_RAW); else sfinfo.format = FORMAT2SF(AE_SHORT) | TYPE2SF(TYP_RAW); sfinfo.channels = p->INOCOUNT - 3; p->nargs = p->INOCOUNT - 3; p->currpos = MYFLT2LRND(*p->iskpfrms); p->flag = 1; if (CS_KSMPS >= 512) p->frames = CS_KSMPS; else p->frames = (int)(512 / CS_KSMPS) * CS_KSMPS; if (CS_KSMPS >= 512) buf_reqd = CS_KSMPS * sfinfo.channels; else buf_reqd = (1 + (int)(512 / CS_KSMPS)) * CS_KSMPS * p->nargs; if (p->buf.auxp == NULL || p->buf.size < buf_reqd*sizeof(MYFLT)) { csound->AuxAlloc(csound, sizeof(MYFLT)*buf_reqd, &p->buf); } p->f.bufsize = p->buf.size; n = fout_open_file(csound, &(p->f), NULL, CSFILE_SND_R, p->fname, istring, &sfinfo, 0); if (UNLIKELY(n < 0)) return NOTOK; if (((STDOPCOD_GLOBALS*) csound->stdOp_Env)->file_opened[n].do_scale) p->scaleFac = csound->e0dbfs; else p->scaleFac = FL(1.0); p->guard_pos = p->frames * p->nargs; p->buf_pos = p->guard_pos; if (p->f.async == 1) csound->FSeekAsync(csound,p->f.fd, p->currpos*p->f.nchnls, SEEK_SET); return OK; } static int kinfile_set(CSOUND *csound, KINFILE *p){ return kinfile_set_(csound,p,0); } static int kinfile_set_S(CSOUND *csound, KINFILE *p){ return kinfile_set_(csound,p,1); } static int kinfile(CSOUND *csound, KINFILE *p) { int i, k; int nargs = p->nargs; MYFLT *buf = (MYFLT *) p->buf.auxp; if (p->flag) { if (p->buf_pos >= p->guard_pos) { if (UNLIKELY(p->f.async == 0)) { sf_seek(p->f.sf, p->currpos*p->f.nchnls, SEEK_SET); p->remain = (uint32_t) sf_read_MYFLT(p->f.sf, (MYFLT*) buf, p->frames*p->f.nchnls); p->remain /= p->f.nchnls; } else { p->remain = csoundReadAsync(csound,p->f.fd,(MYFLT *)buf, p->frames*p->f.nchnls); p->remain /= p->f.nchnls; } p->currpos += p->frames; p->buf_pos = 0; } if (p->remain > 0) { for (i = 0, k = p->buf_pos; i < nargs; i++) p->argums[i][0] = buf[k++] * p->scaleFac; p->buf_pos = k; p->remain--; return OK; } p->flag = 0; } for (i = 0; i < nargs; i++) p->argums[i][0] = FL(0.0); return OK; } static int i_infile_(CSOUND *csound, I_INFILE *p, int istring) { int j, n, nargs; FILE *fp = NULL; MYFLT **args = p->argums; char *omodes[] = {"r", "r", "rb"}; int idx = (int) MYFLT2LRND(*p->iflag); if (UNLIKELY(idx < 0 || idx > 2)) idx = 0; n = fout_open_file(csound, (FOUT_FILE*) NULL, &fp, CSFILE_STD, p->fname, istring, omodes[idx], 0); if (UNLIKELY(n < 0)) return NOTOK; nargs = p->INOCOUNT - 3; switch ((int) MYFLT2LRND(*p->iflag)) { case 0: /* ascii file with loop */ { char cf[64], *cfp; int cc; newcycle: for (j = 0; j < nargs; j++) { cfp = cf; while ((*cfp = cc = getc(fp)) == 'i' || isspace(*cfp)); if (cc == EOF) { fseek(fp, 0, SEEK_SET); goto newcycle; } while (isdigit(*cfp) || *cfp == '.' || *cfp == '+' || *cfp == '-') { *(++cfp) = (char)(cc = getc(fp)); } *++cfp = '\0'; /* Must terminate string */ *(args[j]) = (MYFLT) atof(cf); if (cc == EOF) { fseek(fp, 0, SEEK_SET); break; } } } break; case 1: /* ascii file without loop */ { char cf[64], *cfp; int cc; for (j = 0; j < nargs; j++) { cfp = cf; while ((*cfp = cc = getc(fp)) == 'i' || isspace(*cfp)); if (cc == EOF) { *(args[j]) = FL(0.0); break; } while (isdigit(*cfp) || *cfp == '.' || *cfp == '+' || *cfp == '-') { *(++cfp) = cc = getc(fp); } *++cfp = '\0'; /* Must terminate */ *(args[j]) = (MYFLT) atof (cf); if (cc == EOF) { *(args[j]) = FL(0.0); break; } } } break; case 2: /* binary floats without loop */ if (fseek(fp, p->currpos * sizeof(float) * nargs, SEEK_SET)<0) return NOTOK; p->currpos++; for (j = 0; j < nargs; j++) { if (1 == fread(args[j], sizeof(float), 1, fp)); else { p->flag = 0; *(args[j]) = FL(0.0); } } break; } return OK; } static int i_infile(CSOUND *csound, I_INFILE *p){ return i_infile_(csound,p,0); } static int i_infile_S(CSOUND *csound, I_INFILE *p){ return i_infile_(csound,p,1); } /*---------------------------*/ static int incr(CSOUND *csound, INCR *p) { MYFLT *avar = p->avar, *aincr = p->aincr; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(early)) nsmps -= early; for (n = offset; n < nsmps; n++) avar[n] += aincr[n]; return OK; } static int clear(CSOUND *csound, CLEARS *p) { uint32_t nsmps = CS_KSMPS, j; for (j = 0; j < p->INOCOUNT; j++) { memset(p->argums[j], 0, sizeof(MYFLT)*nsmps); } return OK; } /*---------------------------------*/ /* formatted output to a text file */ static int fprintf_set_(CSOUND *csound, FPRINTF *p, int istring) { int n; char *sarg = (char*) p->fmt->data; char *sdest = p->txtstring; memset(p->txtstring, 0, 8192); /* Nasty to have exposed constant in code */ if (p->h.opadr != (SUBR) NULL) /* fprintks */ n = fout_open_file(csound, &(p->f), NULL, CSFILE_STD, p->fname, istring, "w", 1); else /* fprints */ n = fout_open_file(csound, (FOUT_FILE*) NULL, &(p->f.f), CSFILE_STD, p->fname, istring, "w", 1); if (UNLIKELY(n < 0)) return NOTOK; setvbuf(p->f.f, (char*)NULL, _IOLBF, 0); /* Seems a good option */ /* Copy the string to the storage place in PRINTKS. * * We will look out for certain special codes and write special * bytes directly to the string. * * There is probably a more elegant way of doing this, then using * the look flag. I could use goto - but I would rather not. */ /* This is really a if then else if... * construct and is currently grotty -- JPff */ do { char temp = *sarg++; char tempn = *sarg--; /* Look for a single caret and insert an escape char. */ if ((temp == '^') && (tempn != '^')) { *sdest++ = 0x1B; /* ESC */ } /* Look for a double caret and insert a single caret - stepping forward one */ else if ((temp == '^') && (tempn == '^')) { *sdest++ = '^'; sarg++; } /* Look for a single tilde and insert an escape followed by a '['. * ESC[ is the escape sequence for ANSI consoles */ else if ((temp == '~') && (tempn != '~')) { *sdest++ = 0x1B; /* ESC */ *sdest++ = '['; } /* Look for a double tilde and insert a tilde caret - stepping forward one. */ else if ((temp == '~') && (tempn == '~')) { *sdest++ = '~'; sarg++; } /* Look for \n, \N etc */ else if (temp == '\\') { switch (tempn) { case 'r': case 'R': *sdest++ = '\r'; sarg++; break; case 'n': case 'N': *sdest++ = '\n'; sarg++; break; case 't': case 'T': *sdest++ = '\t'; sarg++; break; case 'a': case 'A': *sdest++ = '\a'; sarg++; break; case 'b': case 'B': *sdest++ = '\b'; sarg++; break; case '\\': *sdest++ = '\\'; sarg++; break; default: *sdest++ = tempn; sarg++; break; } } else if (temp == '%') { /* an extra option to specify tab and return as %t and %r */ switch (tempn) { case 'r': case 'R': *sdest++ = '\r'; sarg++; break; case 'n': case 'N': *sdest++ = '\n'; sarg++; break; case 't': case 'T': *sdest++ = '\t'; sarg++; break; case '!': /* and a ';' */ *sdest++ = ';'; sarg++; break; default: *sdest++ = temp; break; } } else { /* If none of these match, then copy the character directly * and try again. */ *sdest++ = temp; } /* Increment pointer and process next character until end of string. */ } while (*++sarg != 0); return OK; } static int fprintf_set(CSOUND *csound, FPRINTF *p){ return fprintf_set_(csound,p,0); } static int fprintf_set_S(CSOUND *csound, FPRINTF *p){ return fprintf_set_(csound,p,1); } /* perform a sprintf-style format -- matt ingalls */ void sprints1(char *outstring, char *fmt, MYFLT **kvals, int32 numVals) { char strseg[8192]; int len = 8192; int i = 0, j = 0; char *segwaiting = 0; while (*fmt) { if (*fmt == '%') { /* if already a segment waiting, then lets print it */ if (segwaiting) { strseg[i] = '\0'; switch (*segwaiting) { case '%': strncpy(outstring, "%%", len); j--; break; case 'd': case 'i': case 'o': case 'x': case 'X': case 'u': case 'c': snprintf(outstring, len, strseg, (int) MYFLT2LRND(*kvals[j])); break; case 'h': snprintf(outstring, len, strseg, (int16) MYFLT2LRND(*kvals[j])); break; case 'l': snprintf(outstring, len, strseg, (int32) MYFLT2LRND(*kvals[j])); break; default: snprintf(outstring, len, strseg, *kvals[j]); break; } len -= strlen(outstring); outstring += strlen(outstring); i = 0; segwaiting = 0; /* prevent potential problems */ /* if user didnt give enough input params */ if (j < numVals-1) j++; } /* copy the '%' */ strseg[i++] = *fmt++; /* find the format code */ segwaiting = fmt; while (*segwaiting && !isalpha(*segwaiting) && !(*segwaiting=='%')) segwaiting++; } else strseg[i++] = *fmt++; } if (i) { strseg[i] = '\0'; if (segwaiting) { switch (*segwaiting) { case '%': strncpy(outstring, "%%", len); j--; break; case 'd': case 'i': case 'o': case 'x': case 'X': case 'u': case 'c': snprintf(outstring, len, strseg, (int) MYFLT2LRND(*kvals[j])); break; case 'h': snprintf(outstring, len, strseg, (int16) MYFLT2LRND(*kvals[j])); break; case 'l': snprintf(outstring, len, strseg, (long) MYFLT2LRND(*kvals[j])); break; default: snprintf(outstring, len, strseg, *kvals[j]); break; } } else snprintf(outstring, len, "%s", strseg); } } static int fprintf_k(CSOUND *csound, FPRINTF *p) { char string[8192]; (void) csound; sprints1(string, p->txtstring, p->argums, p->INOCOUNT - 2); fprintf(p->f.f, "%s", string); return OK; } /* i-rate fprints */ static int fprintf_i(CSOUND *csound, FPRINTF *p) { char string[8192]; if (UNLIKELY(fprintf_set(csound, p) != OK)) return NOTOK; sprints1(string, p->txtstring, p->argums, p->INOCOUNT - 2); fprintf(p->f.f,"%s", string); /* fflush(p->f.f); */ return OK; } static int fprintf_i_S(CSOUND *csound, FPRINTF *p) { char string[8192]; if (UNLIKELY(fprintf_set_S(csound, p) != OK)) return NOTOK; sprints1(string, p->txtstring, p->argums, p->INOCOUNT - 2); fprintf(p->f.f, "%s", string); /* fflush(p->f.f); */ return OK; } #define S(x) sizeof(x) static OENTRY localops[] = { {"fprints", S(FPRINTF), 0, 1, "", "SSM", (SUBR) fprintf_i_S, (SUBR) NULL,(SUBR) NULL, NULL, }, {"fprints.i", S(FPRINTF), 0, 1, "", "iSM", (SUBR) fprintf_i, (SUBR) NULL,(SUBR) NULL, NULL}, { "fprintks", S(FPRINTF), WR, 3, "", "SSM", (SUBR) fprintf_set_S, (SUBR) fprintf_k, (SUBR) NULL, NULL,}, { "fprintks.i", S(FPRINTF), WR, 3, "", "iSM", (SUBR) fprintf_set, (SUBR) fprintf_k, (SUBR) NULL, NULL}, { "vincr", S(INCR), 0, 4, "", "aa", (SUBR) NULL, (SUBR) NULL, (SUBR) incr, NULL }, { "clear", S(CLEARS), 0, 4, "", "y", (SUBR) NULL, (SUBR) NULL, (SUBR) clear, NULL}, { "fout", S(OUTFILE), 0, 5, "", "Siy", (SUBR) outfile_set_S, (SUBR) NULL, (SUBR) outfile, NULL}, { "fout.A", S(OUTFILEA), 0, 5, "", "Sia[]", (SUBR) outfile_set_A, (SUBR) NULL, (SUBR) outfile_array, NULL}, /* { "fout.i", S(OUTFILE), 0, 5, "", "iiy", */ /* (SUBR) outfile_set, (SUBR) NULL, (SUBR) outfile, NULL}, */ { "foutk", S(KOUTFILE), 0, 3, "", "Siz", (SUBR) koutfile_set_S, (SUBR) koutfile, (SUBR) NULL, NULL }, { "foutk.i", S(KOUTFILE), 0, 3, "", "iiz", (SUBR) koutfile_set, (SUBR) koutfile, (SUBR) NULL, NULL }, { "fouti", S(IOUTFILE), 0, 1, "", "iiim", (SUBR) ioutfile_set, (SUBR) NULL, (SUBR) NULL, NULL }, { "foutir", S(IOUTFILE_R), 0, 3, "", "iiim", (SUBR) ioutfile_set_r, (SUBR) ioutfile_r, (SUBR) NULL, NULL}, { "fiopen", S(FIOPEN), 0, 1, "i", "Si", (SUBR) fiopen_S, (SUBR) NULL, (SUBR) NULL, NULL}, { "fiopen.i", S(FIOPEN), 0, 1, "i", "ii", (SUBR) fiopen, (SUBR) NULL, (SUBR) NULL, NULL}, { "ficlose", S(FICLOSE), 0, 1, "", "S", (SUBR) ficlose_opcode_S, (SUBR) NULL, (SUBR) NULL, NULL}, { "ficlose.S", S(FICLOSE), 0, 1, "", "i", (SUBR) ficlose_opcode, (SUBR) NULL, (SUBR) NULL, NULL }, { "fin.a", S(INFILE), 0, 5, "", "Siiy", (SUBR) infile_set_S, (SUBR) NULL, (SUBR) infile_act, NULL}, { "fin.A", S(INFILEA), 0, 5, "", "Siia[]", (SUBR) infile_set_A, (SUBR) NULL, (SUBR) infile_arr, NULL}, { "fin.i", S(INFILE), 0, 5, "", "iiiy", (SUBR) infile_set, (SUBR) NULL, (SUBR) infile_act, NULL}, { "fink", S(KINFILE), 0, 3, "", "Siiz", (SUBR) kinfile_set_S, (SUBR) kinfile, (SUBR) NULL, NULL}, { "fink.i", S(KINFILE), 0, 3, "", "iiiz", (SUBR) kinfile_set, (SUBR) kinfile, (SUBR) NULL, NULL}, { "fini", S(I_INFILE), 0, 1, "", "Siim", (SUBR) i_infile_S, (SUBR) NULL, (SUBR) NULL, NULL }, { "fini.i", S(I_INFILE), 0, 1, "", "iiim", (SUBR) i_infile, (SUBR) NULL, (SUBR) NULL, NULL} }; int fout_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/fout.h000066400000000000000000000070141321653344700156250ustar00rootroot00000000000000/* fout.h: Copyright (C) 1999 Gabriel Maldonado, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FOUT_H #define FOUT_H #include "stdopcod.h" typedef struct FOUT_FILE_ { OPDS h; SNDFILE *sf; FILE *f; void *fd; int bufsize; int nchnls; int async; int idx; /* file index + 1 */ } FOUT_FILE; typedef struct { OPDS h; MYFLT *fname, *iflag, *argums[VARGMAX]; MYFLT scaleFac; int nargs; int buf_pos; int guard_pos; AUXCH buf; FOUT_FILE f; } OUTFILE; typedef struct { OPDS h; MYFLT *fname, *iflag; ARRAYDAT* tabin; MYFLT scaleFac; int buf_pos; int guard_pos; AUXCH buf; FOUT_FILE f; } OUTFILEA; typedef struct { OPDS h; MYFLT *fname, *iflag, *argums[VARGMAX]; MYFLT scaleFac; uint32_t nargs; int buf_pos; int guard_pos; AUXCH buf; FOUT_FILE f; } KOUTFILE; typedef struct { OPDS h; MYFLT *fname, *iskpfrms, *iflag, *argums[VARGMAX]; MYFLT scaleFac; int32 currpos; int flag; int nargs; int buf_pos; int guard_pos; int frames; uint32_t remain; AUXCH buf; FOUT_FILE f; } INFILE; typedef struct { OPDS h; MYFLT *fname, *iskpfrms, *iflag; ARRAYDAT *tabout; MYFLT scaleFac; int32 currpos; int flag; int chn; int buf_pos; int guard_pos; int frames; uint32_t remain; AUXCH buf; FOUT_FILE f; } INFILEA; typedef struct { OPDS h; MYFLT *fname, *iskpfrms, *iflag, *argums[VARGMAX]; MYFLT scaleFac; int32 currpos; int flag; int nargs; int buf_pos; int guard_pos; int frames; int remain; AUXCH buf; FOUT_FILE f; } KINFILE; typedef struct { OPDS h; MYFLT *fname, *iskpfrms, *iflag, *argums[VARGMAX]; int32 currpos; int flag; } I_INFILE; typedef struct { OPDS h; MYFLT *avar, *aincr; } INCR; typedef struct { OPDS h; MYFLT *argums[VARGMAX]; } CLEARS; typedef struct { OPDS h; MYFLT *ihandle, *fname; /* iascii=0 open ascii (default), iflag=1 open binary */ MYFLT *iascii; } FIOPEN; typedef struct { OPDS h; MYFLT *iFile; } FICLOSE; typedef struct { OPDS h; MYFLT *ihandle, *iascii, *iflag, *argums[VARGMAX]; } IOUTFILE; typedef struct { OPDS h; MYFLT *ihandle, *iascii, *iflag, *argums[VARGMAX]; int32 counter; int done; } IOUTFILE_R; typedef struct { OPDS h; MYFLT *fname; STRINGDAT *fmt; MYFLT *argums[VARGMAX]; FOUT_FILE f; char txtstring[8192]; /* Place to store the string printed */ } FPRINTF; #endif /* FOUT_H */ csound-6.10.0/Opcodes/framebuffer/000077500000000000000000000000001321653344700167615ustar00rootroot00000000000000csound-6.10.0/Opcodes/framebuffer/CMakeLists.txt000066400000000000000000000003201321653344700215140ustar00rootroot00000000000000option(BUILD_FRAMEBUFFER_OPCODES "Build the framebuffer opcodes" ON) if(BUILD_FRAMEBUFFER_OPCODES) set(SOURCES Framebuffer.c OLABuffer.c OpcodeEntries.c) make_plugin(framebuffer "${SOURCES}") endif() csound-6.10.0/Opcodes/framebuffer/Framebuffer.c000066400000000000000000000157421321653344700213620ustar00rootroot00000000000000/* Framebuffer.c Framebuffer Created by Edward Costello on 10/06/2015. Copyright (c) 2015 Edward Costello. This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "Framebuffer.h" ArgumentType Framebuffer_getArgumentType(CSOUND *csound, MYFLT *argument); void Framebuffer_checkArgumentSanity(CSOUND *csound, Framebuffer *self); int Framebuffer_initialise(CSOUND *csound, Framebuffer *self) { self->inputType = Framebuffer_getArgumentType(csound, self->inputArgument); self->outputType = Framebuffer_getArgumentType(csound, self->outputArgument); self->elementCount = *self->sizeArgument; self->ksmps = csound->GetKsmps(csound); Framebuffer_checkArgumentSanity(csound, self); csound->AuxAlloc(csound, self->elementCount * sizeof(MYFLT), &self->bufferMemory); self->buffer = self->bufferMemory.auxp; if (self->outputType == KRATE_ARRAY) { ARRAYDAT *array = (ARRAYDAT *) self->outputArgument; array->sizes = csound->Calloc(csound, sizeof(int)); array->sizes[0] = self->elementCount; array->dimensions = 1; CS_VARIABLE *var = array->arrayType->createVariable(csound, NULL); array->arrayMemberSize = var->memBlockSize; array->data = csound->Calloc(csound, var->memBlockSize * self->elementCount); } return OK; } void Framebuffer_writeBuffer(CSOUND *csound, Framebuffer *self, MYFLT *inputSamples, int inputSamplesCount) { if (self->writeIndex + inputSamplesCount <= self->elementCount) { memcpy(&self->buffer[self->writeIndex], inputSamples, sizeof(MYFLT) * inputSamplesCount); self->writeIndex += self->ksmps; self->writeIndex %= self->elementCount; } else { int firstHalf = self->elementCount - self->writeIndex; memcpy(&self->buffer[self->writeIndex], inputSamples, sizeof(MYFLT) * firstHalf); int secondHalf = inputSamplesCount - firstHalf; memcpy(self->buffer, &inputSamples[firstHalf], sizeof(MYFLT) * secondHalf); self->writeIndex = secondHalf; } } void Framebuffer_readBuffer(CSOUND *csound, Framebuffer *self, MYFLT *outputSamples, int outputSamplesCount) { if (self->writeIndex + outputSamplesCount < self->elementCount) { memcpy(outputSamples, &self->buffer[self->writeIndex], sizeof(MYFLT) * outputSamplesCount); } else { int firstHalf = self->elementCount - self->writeIndex; memcpy(outputSamples, &self->buffer[self->writeIndex], sizeof(MYFLT) * firstHalf); int secondHalf = outputSamplesCount - firstHalf; memcpy(&outputSamples[firstHalf], self->buffer, sizeof(MYFLT) * secondHalf); } } void Framebuffer_processAudioInFrameOut(CSOUND *csound, Framebuffer *self) { Framebuffer_writeBuffer(csound, self, self->inputArgument, self->ksmps); ARRAYDAT *array = (ARRAYDAT *)self->outputArgument; Framebuffer_readBuffer(csound, self, array->data, array->sizes[0]); } void Framebuffer_processFrameInAudioOut(CSOUND *csound, Framebuffer *self) { ARRAYDAT *array = (ARRAYDAT *)self->inputArgument; Framebuffer_writeBuffer(csound, self, array->data, array->sizes[0]); Framebuffer_readBuffer(csound, self, self->outputArgument, self->ksmps); } int Framebuffer_process(CSOUND *csound, Framebuffer *self) { if (self->inputType == KRATE_ARRAY) { Framebuffer_processFrameInAudioOut(csound, self); } else if (self->inputType == ARATE_VAR) { Framebuffer_processAudioInFrameOut(csound, self); } return OK; } void Framebuffer_checkArgumentSanity(CSOUND *csound, Framebuffer *self) { if (UNLIKELY((uint32_t)self->elementCount < csound->GetKsmps(csound))) { csound->Die(csound, Str("framebuffer: Error, specified element " "count less than ksmps value, Exiting")); } if (self->inputType == ARATE_VAR) { if (UNLIKELY(self->outputType != KRATE_ARRAY)) { csound->Die(csound, Str("framebuffer: Error, only k-rate arrays " "allowed for a-rate var inputs, Exiting")); } } else if (LIKELY(self->inputType == KRATE_ARRAY)) { if (UNLIKELY(self->outputType != ARATE_VAR)) { csound->Die(csound, Str("framebuffer: Error, only a-rate vars " "allowed for k-rate array inputs, Exiting")); } ARRAYDAT *array = (ARRAYDAT *) self->inputArgument; if (UNLIKELY(array->dimensions != 1)) { csound->Die(csound, Str("framebuffer: Error, k-rate array input " "must be one dimensional, Exiting")); } if (UNLIKELY(array->sizes[0] > self->elementCount)) { csound->Die(csound, Str("framebuffer: Error, k-rate array input " "element count must be less than \nor equal " "to specified framebuffer size, Exiting")); } } else { csound->Die(csound, Str("framebuffer: Error, only a-rate var input with k-rate " "array output or k-rate\narray input with a-rate var " "output are valid arguments, Exiting")); } } ArgumentType Framebuffer_getArgumentType(CSOUND *csound, MYFLT *argument) { const CS_TYPE *csoundType = csound->GetTypeForArg((void *)argument); const char *type = csoundType->varTypeName; ArgumentType argumentType = UNKNOWN; if (strcmp("S", type) == 0) { argumentType = STRING_VAR; } else if (strcmp("a", type) == 0) { argumentType = ARATE_VAR; } else if (strcmp("k", type) == 0) { argumentType = KRATE_VAR; } else if (strcmp("i", type) == 0) { argumentType = IRATE_VAR; } else if (strcmp("[", type) == 0) { ARRAYDAT *array = (ARRAYDAT *)argument; if (strcmp("k", array->arrayType->varTypeName) == 0) { argumentType = KRATE_ARRAY; } else if (strcmp("a", array->arrayType->varTypeName) == 0) { argumentType = ARATE_ARRAY; } else if (strcmp("i", array->arrayType->varTypeName) == 0) { argumentType = IRATE_ARRAY; } } return argumentType; } csound-6.10.0/Opcodes/framebuffer/Framebuffer.h000066400000000000000000000031361321653344700213610ustar00rootroot00000000000000/* Framebuffer.h Framebuffer Created by Edward Costello on 10/06/2015. Copyright (c) 2015 Edward Costello. This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csdl.h" #ifdef __cplusplus extern "C" { #endif typedef enum ArgumentType { STRING_VAR, ARATE_VAR, KRATE_VAR, IRATE_VAR, ARATE_ARRAY, KRATE_ARRAY, IRATE_ARRAY, UNKNOWN } ArgumentType; typedef struct Framebuffer { OPDS h; MYFLT *outputArgument; MYFLT *inputArgument; MYFLT *sizeArgument; ArgumentType inputType; ArgumentType outputType; MYFLT *buffer; AUXCH bufferMemory; int elementCount; int writeIndex; int ksmps; } Framebuffer; int Framebuffer_initialise(CSOUND *csound, Framebuffer *self); int Framebuffer_process(CSOUND *csound, Framebuffer *self); #ifdef __cplusplus } #endif csound-6.10.0/Opcodes/framebuffer/OLABuffer.c000066400000000000000000000134031321653344700206730ustar00rootroot00000000000000/* OLABuffer.c Framebuffer Created by Edward Costello on 10/06/2015. Copyright (c) 2015 Edward Costello. This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "OLABuffer.h" #ifdef _MSC_VER // FIXME including this "equivalent" file seems to cause a ton of errors //#include #else #include #endif void OLABuffer_checkArgumentSanity(CSOUND *csound, OLABuffer *self); int OLABuffer_initialise(CSOUND *csound, OLABuffer *self) { OLABuffer_checkArgumentSanity(csound, self); self->inputArray = (ARRAYDAT *)self->inputArgument; self->frameSamplesCount = self->inputArray->sizes[0]; self->framesCount = *self->overlapArgument; self->overlapSamplesCount = self->frameSamplesCount / self->framesCount; csound->AuxAlloc(csound, self->frameSamplesCount * self->framesCount * sizeof(MYFLT), &self->frameSamplesMemory); csound->AuxAlloc(csound, self->framesCount * sizeof(MYFLT *), &self->framePointerMemory); self->frames = self->framePointerMemory.auxp; self->ksmps = csound->GetKsmps(csound); int i; for (i = 0; i < self->framesCount; ++i) { self->frames[i] = &((MYFLT *)self->frameSamplesMemory.auxp)[i * self->frameSamplesCount]; } self->overlapSampleIndex = self->overlapSamplesCount; return OK; } void OLABuffer_writeFrame(OLABuffer *self, MYFLT *inputFrame, int frameIndex) { int firstHalfOffset = self->overlapSamplesCount * frameIndex; int firstHalfCount = self->frameSamplesCount - firstHalfOffset; int secondHalfCount = self->frameSamplesCount - firstHalfCount; memcpy(&self->frames[frameIndex][firstHalfOffset], inputFrame, firstHalfCount * sizeof(MYFLT)); memcpy(self->frames[frameIndex], &inputFrame[firstHalfCount], secondHalfCount * sizeof(MYFLT)); } void OLABuffer_readFrame(OLABuffer *self, MYFLT *outputFrame, int outputFrameOffset, int olaBufferOffset, int samplesCount) { memcpy(&outputFrame[outputFrameOffset], &self->frames[0][olaBufferOffset], samplesCount * sizeof(MYFLT)); int i, j; for (i = 1; i < self->framesCount; ++i) { for (j = 0; j < samplesCount; ++j) { outputFrame[j + outputFrameOffset] += self->frames[i][j + olaBufferOffset]; } } } int OLABuffer_process(CSOUND *csound, OLABuffer *self) { int nextKPassSampleIndex = (self->readSampleIndex + self->ksmps) % self->overlapSamplesCount; if (nextKPassSampleIndex == 0) { OLABuffer_writeFrame(self, self->inputArray->data, self->frameIndex); OLABuffer_readFrame(self, self->outputArgument, 0, self->readSampleIndex, self->ksmps); self->frameIndex++; self->frameIndex %= self->framesCount; } else if (nextKPassSampleIndex < self->overlapSampleIndex) { int firstHalfCount = self->overlapSamplesCount - self->overlapSampleIndex; if (firstHalfCount != 0) { OLABuffer_readFrame(self, self->outputArgument, 0, self->readSampleIndex, firstHalfCount); } OLABuffer_writeFrame(self, self->inputArray->data, self->frameIndex); int secondHalfCount = self->ksmps - firstHalfCount; if (secondHalfCount != 0) { OLABuffer_readFrame(self, self->outputArgument, firstHalfCount, self->readSampleIndex, secondHalfCount); } self->frameIndex++; self->frameIndex %= self->framesCount; } else { OLABuffer_readFrame(self, self->outputArgument, 0, self->readSampleIndex, self->ksmps); } self->overlapSampleIndex += self->ksmps; self->overlapSampleIndex %= self->overlapSamplesCount; self->readSampleIndex += self->ksmps; self->readSampleIndex %= self->frameSamplesCount; return OK; } void OLABuffer_checkArgumentSanity(CSOUND *csound, OLABuffer *self) { MYFLT overlapCount = *self->overlapArgument; if (UNLIKELY(floor(overlapCount) != overlapCount)) { csound->Die(csound, Str("olabuffer: Error, overlap factor must be an integer")); } ARRAYDAT *array = (ARRAYDAT *) self->inputArgument; if (UNLIKELY(array->dimensions != 1)) { csound->Die(csound, Str("olabuffer: Error, k-rate array must be one dimensional")); } int frameSampleCount = array->sizes[0]; if (UNLIKELY(frameSampleCount <= (int)overlapCount)) { csound->Die(csound, Str("olabuffer: Error, k-rate array size must be " "larger than ovelap factor")); } if (UNLIKELY(frameSampleCount % (int)overlapCount != 0)) { csound->Die(csound, Str("olabuffer: Error, overlap factor must be " "an integer multiple of k-rate array size")); } if (UNLIKELY(frameSampleCount / (int)overlapCount < (int) csound->GetKsmps(csound))) { csound->Die(csound, Str("olabuffer: Error, k-rate array size divided " "by overlap factor must be larger than or equal " "to ksmps")); } } csound-6.10.0/Opcodes/framebuffer/OLABuffer.h000066400000000000000000000030001321653344700206700ustar00rootroot00000000000000/* OLABuffer.h Framebuffer Created by Edward Costello on 10/06/2015. Copyright (c) 2015 Edward Costello. This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csdl.h" #ifdef __cplusplus extern "C" { #endif typedef struct OLABuffer { OPDS h; MYFLT *outputArgument; MYFLT *inputArgument; MYFLT *overlapArgument; ARRAYDAT *inputArray; AUXCH frameSamplesMemory; AUXCH framePointerMemory; int frameIndex; int overlapSampleIndex; int readSampleIndex; int framesCount; int frameSamplesCount; int overlapSamplesCount; int ksmps; MYFLT **frames; } OLABuffer; int OLABuffer_initialise(CSOUND *csound, OLABuffer *self); int OLABuffer_process(CSOUND *csound, OLABuffer *self); #ifdef __cplusplus } #endif csound-6.10.0/Opcodes/framebuffer/OpcodeEntries.c000066400000000000000000000027421321653344700216750ustar00rootroot00000000000000/* OpcodeEntries.c Framebuffer Created by Edward Costello on 10/06/2015. Copyright (c) 2015 Edward Costello. All rights reserved. This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "Framebuffer.h" #include "OLABuffer.h" static OENTRY localops[] = { { .opname = "framebuffer", .dsblksiz = sizeof(Framebuffer), .thread = 3, .outypes = "*", .intypes = "*", .iopadr = (SUBR)Framebuffer_initialise, .kopadr = (SUBR)Framebuffer_process, .aopadr = NULL }, { .opname = "olabuffer", .dsblksiz = sizeof(OLABuffer), .thread = 3, .outypes = "a", .intypes = "k[]i", .iopadr = (SUBR)OLABuffer_initialise, .kopadr = (SUBR)OLABuffer_process, .aopadr = NULL } }; LINKAGE csound-6.10.0/Opcodes/freeverb.c000066400000000000000000000240211321653344700164400ustar00rootroot00000000000000/* freeverb.c: Copyright (C) 2005 Istvan Varga (based on public domain C++ code by Jezar) This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "stdopcod.h" #include #define DEFAULT_SRATE 44100.0 #define STEREO_SPREAD 23.0 #define MIN_SRATE FL(1000.0) #define NR_COMB 8 #define NR_ALLPASS 4 static const double comb_delays[NR_COMB][2] = { { 1116.0 / DEFAULT_SRATE, (1116.0 + STEREO_SPREAD) / DEFAULT_SRATE }, { 1188.0 / DEFAULT_SRATE, (1188.0 + STEREO_SPREAD) / DEFAULT_SRATE }, { 1277.0 / DEFAULT_SRATE, (1277.0 + STEREO_SPREAD) / DEFAULT_SRATE }, { 1356.0 / DEFAULT_SRATE, (1356.0 + STEREO_SPREAD) / DEFAULT_SRATE }, { 1422.0 / DEFAULT_SRATE, (1422.0 + STEREO_SPREAD) / DEFAULT_SRATE }, { 1491.0 / DEFAULT_SRATE, (1491.0 + STEREO_SPREAD) / DEFAULT_SRATE }, { 1557.0 / DEFAULT_SRATE, (1557.0 + STEREO_SPREAD) / DEFAULT_SRATE }, { 1617.0 / DEFAULT_SRATE, (1617.0 + STEREO_SPREAD) / DEFAULT_SRATE } }; static const double allpass_delays[NR_ALLPASS][2] = { { 556.0 / DEFAULT_SRATE, (556.0 + STEREO_SPREAD) / DEFAULT_SRATE }, { 441.0 / DEFAULT_SRATE, (441.0 + STEREO_SPREAD) / DEFAULT_SRATE }, { 341.0 / DEFAULT_SRATE, (341.0 + STEREO_SPREAD) / DEFAULT_SRATE }, { 225.0 / DEFAULT_SRATE, (225.0 + STEREO_SPREAD) / DEFAULT_SRATE } }; static const double fixedGain = 0.015; static const double scaleDamp = 0.4; static const double scaleRoom = 0.28; static const double offsetRoom = 0.7; static const double allPassFeedBack = 0.5; typedef struct { int nSamples; int bufPos; double filterState; MYFLT buf[1]; } freeVerbComb; typedef struct { int nSamples; int bufPos; MYFLT buf[1]; } freeVerbAllPass; typedef struct { OPDS h; MYFLT *aOutL; MYFLT *aOutR; MYFLT *aInL; MYFLT *aInR; MYFLT *kRoomSize; MYFLT *kDampFactor; MYFLT *iSampleRate; MYFLT *iSkipInit; freeVerbComb *Comb[NR_COMB][2]; freeVerbAllPass *AllPass[NR_ALLPASS][2]; MYFLT *tmpBuf; AUXCH auxData; MYFLT prvDampFactor; double dampValue; double srFact; } FREEVERB; static int calc_nsamples(FREEVERB *p, double delTime) { double sampleRate; sampleRate = (double) *(p->iSampleRate); if (sampleRate < MIN_SRATE) sampleRate = DEFAULT_SRATE; return (int) (delTime * sampleRate + 0.5); } static int comb_nbytes(FREEVERB *p, double delTime) { int nbytes; nbytes = (int) sizeof(freeVerbComb) - (int) sizeof(MYFLT); nbytes += ((int) sizeof(MYFLT) * calc_nsamples(p, delTime)); return ((nbytes + 15) & (~15)); } static int allpass_nbytes(FREEVERB *p, double delTime) { int nbytes; nbytes = (int) sizeof(freeVerbAllPass) - (int) sizeof(MYFLT); nbytes += ((int) sizeof(MYFLT) * calc_nsamples(p, delTime)); return ((nbytes + 15) & (~15)); } static int freeverb_init(CSOUND *csound, FREEVERB *p) { int i, j, k, nbytes; freeVerbComb *combp; freeVerbAllPass *allpassp; /* calculate the total number of bytes to allocate */ nbytes = 0; for (i = 0; i < NR_COMB; i++) { nbytes += comb_nbytes(p, comb_delays[i][0]); nbytes += comb_nbytes(p, comb_delays[i][1]); } for (i = 0; i < NR_ALLPASS; i++) { nbytes += allpass_nbytes(p, allpass_delays[i][0]); nbytes += allpass_nbytes(p, allpass_delays[i][1]); } nbytes += (int) sizeof(MYFLT) * (int) CS_KSMPS; /* allocate space if size has changed */ if (nbytes != (int) p->auxData.size) csound->AuxAlloc(csound, (int32) nbytes, &(p->auxData)); else if (*(p->iSkipInit) != FL(0.0)) /* skip initialisation */ return OK; /* if requested */ /* set up comb and allpass filters */ nbytes = 0; for (i = 0; i < (NR_COMB << 1); i++) { combp = (freeVerbComb*)((unsigned char*)p->auxData.auxp + (int) nbytes); p->Comb[i >> 1][i & 1] = combp; k = calc_nsamples(p, comb_delays[i >> 1][i & 1]); combp->nSamples = k; combp->bufPos = 0; combp->filterState = 0.0; for (j = 0; j < k; j++) combp->buf[j] = FL(0.0); nbytes += comb_nbytes(p, comb_delays[i >> 1][i & 1]); } for (i = 0; i < (NR_ALLPASS << 1); i++) { allpassp = (freeVerbAllPass*) ((unsigned char*) p->auxData.auxp + (int) nbytes); p->AllPass[i >> 1][i & 1] = allpassp; k = calc_nsamples(p, allpass_delays[i >> 1][i & 1]); allpassp->nSamples = k; allpassp->bufPos = 0; //memset(allpassp->buf, '\0', k*sizeof(MYFLT)); for (j = 0; j < k; j++) allpassp->buf[j] = FL(0.0); nbytes += allpass_nbytes(p, allpass_delays[i >> 1][i & 1]); } p->tmpBuf = (MYFLT*) ((unsigned char*)p->auxData.auxp + (int)nbytes); p->prvDampFactor = -FL(1.0); if (*(p->iSampleRate) >= MIN_SRATE) p->srFact = pow((DEFAULT_SRATE / *(p->iSampleRate)), 0.8); else p->srFact = 1.0; return OK; } static int freeverb_perf(CSOUND *csound, FREEVERB *p) { double feedback, damp1, damp2, x; freeVerbComb *combp; freeVerbAllPass *allpassp; int i; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; /* check if opcode was correctly initialised */ if (UNLIKELY(p->auxData.size <= 0L || p->auxData.auxp == NULL)) goto err1; /* calculate reverb parameters */ feedback = (double) *(p->kRoomSize) * scaleRoom + offsetRoom; if (*(p->kDampFactor) != p->prvDampFactor) { p->prvDampFactor = *(p->kDampFactor); damp1 = (double) *(p->kDampFactor) * scaleDamp; /* hack to correct high frequency attenuation for sample rate */ if (*(p->iSampleRate) >= MIN_SRATE) damp1 = pow(damp1, p->srFact); p->dampValue = damp1; } else damp1 = p->dampValue; damp2 = 1.0 - damp1; /* comb filters (left channel) */ memset(p->tmpBuf,0, sizeof(MYFLT)*nsmps); for (i = 0; i < NR_COMB; i++) { combp = p->Comb[i][0]; for (n = 0; n < nsmps; n++) { p->tmpBuf[n] += combp->buf[combp->bufPos]; x = (double) combp->buf[combp->bufPos]; combp->filterState = (combp->filterState * damp1) + (x * damp2); x = combp->filterState * feedback + (double) p->aInL[n]; combp->buf[combp->bufPos] = (MYFLT) x; if (UNLIKELY(++(combp->bufPos) >= combp->nSamples)) combp->bufPos = 0; } } /* allpass filters (left channel) */ for (i = 0; i < NR_ALLPASS; i++) { allpassp = p->AllPass[i][0]; for (n = 0; n < nsmps; n++) { x = (double) allpassp->buf[allpassp->bufPos] - (double) p->tmpBuf[n]; allpassp->buf[allpassp->bufPos] *= (MYFLT) allPassFeedBack; allpassp->buf[allpassp->bufPos] += p->tmpBuf[n]; if (UNLIKELY(++(allpassp->bufPos) >= allpassp->nSamples)) allpassp->bufPos = 0; p->tmpBuf[n] = (MYFLT) x; } } /* write left channel output */ if (UNLIKELY(offset)) memset(p->aOutL, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->aOutL[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) p->aOutL[n] = p->tmpBuf[n] * (MYFLT) fixedGain; /* comb filters (right channel) */ memset(p->tmpBuf, 0, sizeof(MYFLT)*nsmps); /* for (n = 0; n < nsmps; n++) */ /* p->tmpBuf[n] = FL(0.0); */ for (i = 0; i < NR_COMB; i++) { combp = p->Comb[i][1]; for (n = 0; n < nsmps; n++) { p->tmpBuf[n] += combp->buf[combp->bufPos]; x = (double) combp->buf[combp->bufPos]; combp->filterState = (combp->filterState * damp1) + (x * damp2); x = combp->filterState * feedback + (double) p->aInR[n]; combp->buf[combp->bufPos] = (MYFLT) x; if (UNLIKELY(++(combp->bufPos) >= combp->nSamples)) combp->bufPos = 0; } } /* allpass filters (right channel) */ for (i = 0; i < NR_ALLPASS; i++) { allpassp = p->AllPass[i][1]; for (n = 0; n < nsmps; n++) { x = (double) allpassp->buf[allpassp->bufPos] - (double) p->tmpBuf[n]; allpassp->buf[allpassp->bufPos] *= (MYFLT) allPassFeedBack; allpassp->buf[allpassp->bufPos] += p->tmpBuf[n]; if (UNLIKELY(++(allpassp->bufPos) >= allpassp->nSamples)) allpassp->bufPos = 0; p->tmpBuf[n] = (MYFLT) x; } } nsmps = CS_KSMPS; /* write right channel output */ if (UNLIKELY(offset)) memset(p->aOutR, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->aOutR[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) p->aOutR[n] = p->tmpBuf[n] * (MYFLT) fixedGain; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("freeverb: not initialised")); } /* module interface functions */ int freeverb_init_(CSOUND *csound) { return csound->AppendOpcode(csound, "freeverb", (int) sizeof(FREEVERB), 0, 5, "aa", "aakkjo", (int (*)(CSOUND*, void*)) freeverb_init, (int (*)(CSOUND*, void*)) NULL, (int (*)(CSOUND*, void*)) freeverb_perf); } csound-6.10.0/Opcodes/ftconv.c000066400000000000000000000265551321653344700161550ustar00rootroot00000000000000/* ftconv.c: Copyright (C) 2005 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "stdopcod.h" #include #define FTCONV_MAXCHN 8 typedef struct { OPDS h; MYFLT *aOut[FTCONV_MAXCHN]; MYFLT *aIn; MYFLT *iFTNum; MYFLT *iPartLen; MYFLT *iSkipSamples; MYFLT *iTotLen; MYFLT *iSkipInit; /* ------------------------- */ int initDone; int nChannels; int cnt; /* buffer position, 0 to partSize - 1 */ int nPartitions; /* number of convolve partitions */ int partSize; /* partition length in sample frames */ int rbCnt; /* ring buffer index, 0 to nPartitions - 1 */ MYFLT *tmpBuf; /* temporary buffer for accumulating FFTs */ MYFLT *ringBuf; /* ring buffer of FFTs of input partitions */ MYFLT *IR_Data[FTCONV_MAXCHN]; /* impulse responses (scaled) */ MYFLT *outBuffers[FTCONV_MAXCHN]; /* output buffer (size=partSize*2) */ void *fwdsetup, *invsetup; AUXCH auxData; } FTCONV; static void multiply_fft_buffers(MYFLT *outBuf, MYFLT *ringBuf, MYFLT *IR_Data, int partSize, int nPartitions, int ringBuf_startPos) { MYFLT re, im, re1, re2, im1, im2; MYFLT *rbPtr, *irPtr, *outBufPtr, *outBufEndPm2, *rbEndP; /* note: partSize must be at least 2 samples */ partSize <<= 1; outBufEndPm2 = (MYFLT*) outBuf + (int) (partSize - 2); rbEndP = (MYFLT*) ringBuf + (int) (partSize * nPartitions); rbPtr = &(ringBuf[ringBuf_startPos]); irPtr = IR_Data; outBufPtr = outBuf; /* clear output buffer to zero */ memset(outBuf, 0, sizeof(MYFLT)*(partSize)); /* do { */ /* *(outBufPtr++) = FL(0.0); */ /* *(outBufPtr++) = FL(0.0); */ /* } while (outBufPtr <= outBufEndPm2); */ /* multiply FFTs for each partition, and mix to output buffer */ /* note: IRs are stored in reverse partition order */ do { /* wrap ring buffer position */ if (rbPtr >= rbEndP) rbPtr = ringBuf; outBufPtr = outBuf; *(outBufPtr++) += *(rbPtr++) * *(irPtr++); /* convolve DC */ *(outBufPtr++) += *(rbPtr++) * *(irPtr++); /* convolve Nyquist */ re1 = *(rbPtr++); im1 = *(rbPtr++); re2 = *(irPtr++); im2 = *(irPtr++); re = re1 * re2 - im1 * im2; im = re1 * im2 + re2 * im1; while (outBufPtr < outBufEndPm2) { /* complex multiply */ re1 = rbPtr[0]; im1 = rbPtr[1]; re2 = irPtr[0]; im2 = irPtr[1]; outBufPtr[0] += re; outBufPtr[1] += im; re = re1 * re2 - im1 * im2; im = re1 * im2 + re2 * im1; re1 = rbPtr[2]; im1 = rbPtr[3]; re2 = irPtr[2]; im2 = irPtr[3]; outBufPtr[2] += re; outBufPtr[3] += im; re = re1 * re2 - im1 * im2; im = re1 * im2 + re2 * im1; outBufPtr += 4; rbPtr += 4; irPtr += 4; } outBufPtr[0] += re; outBufPtr[1] += im; } while (--nPartitions); } static inline int buf_bytes_alloc(int nChannels, int partSize, int nPartitions) { int nSmps; nSmps = (partSize << 1); /* tmpBuf */ nSmps += ((partSize << 1) * nPartitions); /* ringBuf */ nSmps += ((partSize << 1) * nChannels * nPartitions); /* IR_Data */ nSmps += ((partSize << 1) * nChannels); /* outBuffers */ return ((int) sizeof(MYFLT) * nSmps); } static void set_buf_pointers(FTCONV *p, int nChannels, int partSize, int nPartitions) { MYFLT *ptr; int i; ptr = (MYFLT*) (p->auxData.auxp); p->tmpBuf = ptr; ptr += (partSize << 1); p->ringBuf = ptr; ptr += ((partSize << 1) * nPartitions); for (i = 0; i < nChannels; i++) { p->IR_Data[i] = ptr; ptr += ((partSize << 1) * nPartitions); } for (i = 0; i < nChannels; i++) { p->outBuffers[i] = ptr; ptr += (partSize << 1); } } static int ftconv_init(CSOUND *csound, FTCONV *p) { FUNC *ftp; int i, j, k, n, nBytes, skipSamples; //MYFLT FFTscale; /* check parameters */ p->nChannels = (int) p->OUTOCOUNT; if (UNLIKELY(p->nChannels < 1 || p->nChannels > FTCONV_MAXCHN)) { return csound->InitError(csound, Str("ftconv: invalid number of channels")); } /* partition length */ p->partSize = MYFLT2LRND(*(p->iPartLen)); if (UNLIKELY(p->partSize < 4 || (p->partSize & (p->partSize - 1)) != 0)) { return csound->InitError(csound, Str("ftconv: invalid impulse response " "partition length")); } ftp = csound->FTnp2Find(csound, p->iFTNum); if (UNLIKELY(ftp == NULL)) return NOTOK; /* ftfind should already have printed the error message */ /* calculate total length / number of partitions */ n = (int) ftp->flen / p->nChannels; skipSamples = MYFLT2LRND(*(p->iSkipSamples)); n -= skipSamples; if (MYFLT2LRND(*(p->iTotLen)) > 0 && n > MYFLT2LRND(*(p->iTotLen))) n = MYFLT2LRND(*(p->iTotLen)); if (UNLIKELY(n <= 0)) { return csound->InitError(csound, Str("ftconv: invalid length, or insufficient" " IR data for convolution")); } p->nPartitions = (n + (p->partSize - 1)) / p->partSize; /* calculate the amount of aux space to allocate (in bytes) */ nBytes = buf_bytes_alloc(p->nChannels, p->partSize, p->nPartitions); if (nBytes != (int) p->auxData.size) csound->AuxAlloc(csound, (int32) nBytes, &(p->auxData)); else if (p->initDone > 0 && *(p->iSkipInit) != FL(0.0)) return OK; /* skip initialisation if requested */ /* if skipping samples: check for possible truncation of IR */ /* if (skipSamples > 0 && (csound->oparms->msglevel & WARNMSG)) { n = skipSamples * p->nChannels; if (n > (int) ftp->flen) n = (int) ftp->flen; for (i = 0; i < n; i++) { if (UNLIKELY(ftp->ftable[i] != FL(0.0))) { csound->Warning(csound, Str("ftconv: skipped non-zero samples, " "impulse response may be truncated\n")); break; } } }*/ /* initialise buffer pointers */ set_buf_pointers(p, p->nChannels, p->partSize, p->nPartitions); /* clear ring buffer to zero */ n = (p->partSize << 1) * p->nPartitions; memset(p->ringBuf, 0, n*sizeof(MYFLT)); /* for (i = 0; i < n; i++) */ /* p->ringBuf[i] = FL(0.0); */ /* initialise buffer index */ p->cnt = 0; p->rbCnt = 0; /* calculate FFT of impulse response partitions, in reverse order */ /* also apply FFT amplitude scale here */ //FFTscale = csound->GetInverseRealFFTScale(csound, (p->partSize << 1)); p->fwdsetup = csound->RealFFT2Setup(csound,(p->partSize << 1), FFT_FWD); p->invsetup = csound->RealFFT2Setup(csound,(p->partSize << 1), FFT_INV); for (j = 0; j < p->nChannels; j++) { i = (skipSamples * p->nChannels) + j; /* table read position */ n = (p->partSize << 1) * (p->nPartitions - 1); /* IR write position */ do { for (k = 0; k < p->partSize; k++) { if (i >= 0 && i < (int) ftp->flen) p->IR_Data[j][n + k] = ftp->ftable[i];// * FFTscale; else p->IR_Data[j][n + k] = FL(0.0); i += p->nChannels; } /* pad second half of IR to zero */ for (k = p->partSize; k < (p->partSize << 1); k++) p->IR_Data[j][n + k] = FL(0.0); /* calculate FFT */ csound->RealFFT2(csound, p->fwdsetup, &(p->IR_Data[j][n])); n -= (p->partSize << 1); } while (n >= 0); } /* clear output buffers to zero */ /*memset(p->outBuffers, 0, p->nChannels*(p->partSize << 1)*sizeof(MYFLT));*/ for (j = 0; j < p->nChannels; j++) { for (i = 0; i < (p->partSize << 1); i++) p->outBuffers[j][i] = FL(0.0); } p->initDone = 1; return OK; } static int ftconv_perf(CSOUND *csound, FTCONV *p) { MYFLT *x, *rBuf; int i, n, nSamples, rBufPos; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, nsmps = CS_KSMPS; if (p->initDone <= 0) goto err1; nSamples = p->partSize; rBuf = &(p->ringBuf[p->rbCnt * (nSamples << 1)]); if (UNLIKELY(offset)) for (n = 0; n < p->nChannels; n++) memset(p->aOut[n], '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; for (n = 0; n < p->nChannels; n++) memset(&p->aOut[n][nsmps], '\0', early*sizeof(MYFLT)); } for (nn = offset; nn < nsmps; nn++) { /* store input signal in buffer */ rBuf[p->cnt] = p->aIn[nn]; /* copy output signals from buffer */ for (n = 0; n < p->nChannels; n++) p->aOut[n][nn] = p->outBuffers[n][p->cnt]; /* is input buffer full ? */ if (++p->cnt < nSamples) continue; /* no, continue with next sample */ /* reset buffer position */ p->cnt = 0; /* calculate FFT of input */ for (i = nSamples; i < (nSamples << 1); i++) rBuf[i] = FL(0.0); /* pad to double length */ csound->RealFFT2(csound, p->fwdsetup, rBuf); /* update ring buffer position */ p->rbCnt++; if (p->rbCnt >= p->nPartitions) p->rbCnt = 0; rBufPos = p->rbCnt * (nSamples << 1); rBuf = &(p->ringBuf[rBufPos]); /* for each channel: */ for (n = 0; n < p->nChannels; n++) { /* multiply complex arrays */ multiply_fft_buffers(p->tmpBuf, p->ringBuf, p->IR_Data[n], nSamples, p->nPartitions, rBufPos); /* inverse FFT */ csound->RealFFT2(csound, p->invsetup, p->tmpBuf); /* copy to output buffer, overlap with "tail" of previous block */ x = &(p->outBuffers[n][0]); for (i = 0; i < nSamples; i++) { x[i] = p->tmpBuf[i] + x[i + nSamples]; x[i + nSamples] = p->tmpBuf[i + nSamples]; } } } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("ftconv: not initialised")); } /* module interface functions */ int ftconv_init_(CSOUND *csound) { return csound->AppendOpcode(csound, "ftconv", (int) sizeof(FTCONV), TR, 5, "mmmmmmmm", "aiiooo", (int (*)(CSOUND *, void *)) ftconv_init, (int (*)(CSOUND *, void *)) NULL, (int (*)(CSOUND *, void *)) ftconv_perf); } csound-6.10.0/Opcodes/ftest.c000066400000000000000000000120741321653344700157720ustar00rootroot00000000000000/* ftest.c: Copyright (C) 2004,2008 John ffitch, Victor Lazzarini 2012 Gleb Rogozinsky This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ //#include "csdl.h" #include "csoundCore.h" #include static int tanhtable(FGDATA *ff, FUNC *ftp) { MYFLT *fp = ftp->ftable; MYFLT start = ff->e.p[5]; MYFLT end = ff->e.p[6]; MYFLT resc = ff->e.p[7]; MYFLT step = (end - start) / (MYFLT) ftp->flen; MYFLT x; int i; for (i = 0, x = start; i <= (int) ftp->flen; i++, x += step) fp[i] = TANH(x); if (resc!=FL(0.0)) ff->e.p[4] *= -1; /*else ff->e.p[4] = 1;*/ return OK; } static int exptable(FGDATA *ff, FUNC *ftp) { /* CSOUND *csound = ff->csound; */ MYFLT *fp = ftp->ftable; MYFLT start = ff->e.p[5]; MYFLT end = ff->e.p[6]; MYFLT resc = ff->e.p[7]; MYFLT step = (end - start) / (MYFLT) ftp->flen; MYFLT x; int i; for (i = 0, x = start; i <= (int) ftp->flen; i++, x += step) fp[i] = EXP(x); if (resc!=FL(0.0)) ff->e.p[4] *= -1; /*else ff->e.p[4] = 1;*/ return OK; } /* Translation table from perceived to actual amplitude */ static int sonetable(FGDATA *ff, FUNC *ftp) { /* CSOUND *csound = ff->csound; */ MYFLT *fp = ftp->ftable; MYFLT start = ff->e.p[5]; MYFLT end = ff->e.p[6]; MYFLT eqlp = ff->e.p[7]; MYFLT resc = ff->e.p[8]; MYFLT step = (end - start) / (MYFLT) ftp->flen; MYFLT x; int i; if (eqlp==FL(0.0)) eqlp = FL(0.001); /* printf("Sone: %f %f %f %f\n", ff->e.p[5], ff->e.p[6], ff->e.p[7], ff->e.p[8]); */ for (i = 0, x = start; i <= (int) ftp->flen; i++, x += step) { fp[i] = x*POWER(x/eqlp, FL(33.0)/FL(78.0)); printf("%f -> %f\n", x, fp[i]); } if (resc!=FL(0.0)) ff->e.p[4] *= -1; /*else ff->e.p[4] = 1;*/ return OK; } /* GENwave by Gleb Rogozinsky 2012 */ typedef struct { MYFLT *pWF, *pSF; MYFLT *pFil[2]; unsigned int *size; } WAVELET; static int deconvolve(MYFLT *pInp, WAVELET *pwaveS, unsigned int *pnewLen, MYFLT *pBuf, int *pOrder) { unsigned int i, j; *pnewLen *= 2; for (j = 0; j < *pnewLen; j++) { for (i = 0; i < *pwaveS->size; i++) pBuf[(2*j+i) % *pnewLen] += pInp[j]*pwaveS->pFil[*pOrder][i]; } for (i = 0; i < *pnewLen; i++) { pInp[i] = pBuf[i]; pBuf[i] = FL(0.0); } return OK; } static int wavetable(FGDATA *ff, FUNC *ftp) { CSOUND *csound = ff->csound; MYFLT *fp = ftp->ftable; MYFLT *fp_filter, *pInp, *pBuf; MYFLT order = ff->e.p[6]; MYFLT resc = ff->e.p[7]; int ffilno = (int)ff->e.p[5]; unsigned int i; unsigned int steps, newLen, *pnewLen; int nargs = ff->e.pcnt - 4; int *pOrder, *xfree; FUNC *srcfil = csound->flist[ffilno]; MYFLT *mirr; WAVELET wave, *pwaveS; if (UNLIKELY(nargs < 3)) csound->Warning(csound, Str("insufficient arguments")); fp_filter = srcfil->ftable; newLen = srcfil->flen; mirr = (MYFLT*) csound->Malloc(csound, sizeof(MYFLT)*srcfil->flen); pnewLen = &newLen; pwaveS = &wave; pwaveS->pSF = fp_filter; pwaveS->size = &srcfil->flen; pwaveS->pWF = mirr; /* create QMF */ for (i = 0; i < srcfil->flen; i++) pwaveS->pWF[i] = POWER(FL(-1.0),i)*pwaveS->pSF[srcfil->flen-1-i]; pwaveS->pFil[0] = pwaveS->pSF; pwaveS->pFil[1] = pwaveS->pWF; pInp = (MYFLT*) csound->Calloc(csound, ftp->flen* sizeof(MYFLT)); pBuf = (MYFLT*) csound->Calloc(csound, ftp->flen* sizeof(MYFLT)); *pInp = FL(1.0); steps = (int)LOG2(ftp->flen/srcfil->flen); xfree = pOrder = (int*)csound->Malloc(csound, sizeof(int)*steps); /* DEC to BIN */ for (i = 0; i < steps; i++) pOrder[i] = ((int)order>>i) & 0x1; /* main loop */ for (i = 0; i < steps; i++) deconvolve(pInp, pwaveS, pnewLen, pBuf, pOrder++); for (i = 0; i < *pnewLen; i++) fp[i] = pInp[i]; csound->Free(csound,pBuf); csound->Free(csound,pInp); csound->Free(csound,xfree); csound->Free(csound,mirr); if (resc!=FL(0.0)) ff->e.p[4] *= -1; /*else ff->e.p[4] = 1;*/ return OK; } static NGFENS ftest_fgens[] = { { "tanh", tanhtable }, { "exp", exptable }, { "sone", sonetable }, { "wave", wavetable }, { NULL, NULL } }; FLINKAGE_BUILTIN(ftest_fgens) csound-6.10.0/Opcodes/ftgen.c000066400000000000000000000614511321653344700157530ustar00rootroot00000000000000/* ftgen.c: Copyright (C) 1991, 1994, 1995, 1998, 2000, 2004 Barry Vercoe, John ffitch, Paris Smaragdis, Gabriel Maldonado, Richard Karpen, Greg Sullivan, Pete Moss, Istvan Varga, Victor Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "stdopcod.h" #include #include #include "soundio.h" #include typedef struct { OPDS h; MYFLT *ifno, *p1, *p2, *p3, *p4, *p5, *argums[VARGMAX]; } FTGEN; typedef struct { OPDS h; MYFLT *ifilno, *iflag, *argums[VARGMAX]; } FTLOAD; /* gab 30 jul 2002 */ typedef struct { OPDS h; MYFLT *ifilno, *ktrig, *iflag, *argums[VARGMAX]; FTLOAD p; } FTLOAD_K; /* gab 30 jul 2002 */ typedef struct { OPDS h; MYFLT *iftno, *ifreeTime; } FTFREE; typedef struct { OPDS h; int fno; } FTDELETE; typedef struct namedgen { char *name; int genum; struct namedgen *next; } NAMEDGEN; static int ftable_delete(CSOUND *csound, void *p) { int err = csound->FTDelete(csound, ((FTDELETE*) p)->fno); if (UNLIKELY(err != OK)) csound->ErrorMsg(csound, Str("Error deleting ftable %d"), ((FTDELETE*) p)->fno); csound->Free(csound, p); return err; } static int register_ftable_delete(CSOUND *csound, void *p, int tableNum) { FTDELETE *op = (FTDELETE*) csound->Calloc(csound, sizeof(FTDELETE)); if (UNLIKELY(op == NULL)) return csound->InitError(csound, Str("memory allocation failure")); op->h.insdshead = ((OPDS*) p)->insdshead; op->fno = tableNum; return csound->RegisterDeinitCallback(csound, op, ftable_delete); } /* set up and call any GEN routine */ static int ftgen_(CSOUND *csound, FTGEN *p, int istring1, int istring2) { MYFLT *fp; FUNC *ftp; EVTBLK *ftevt; int n; *p->ifno = FL(0.0); ftevt =(EVTBLK*) csound->Malloc(csound, sizeof(EVTBLK)); ftevt->opcod = 'f'; ftevt->strarg = NULL; fp = &ftevt->p[0]; fp[0] = FL(0.0); fp[1] = *p->p1; /* copy p1 - p5 */ fp[2] = ftevt->p2orig = FL(0.0); /* force time 0 */ fp[3] = ftevt->p3orig = *p->p3; fp[4] = *p->p4; if (istring1) { /* Named gen */ NAMEDGEN *named = (NAMEDGEN*) csound->GetNamedGens(csound); while (named) { if (strcmp(named->name, ((STRINGDAT *) p->p4)->data) == 0) { /* Look up by name */ fp[4] = named->genum; break; } named = named->next; /* and round again */ } if (UNLIKELY(named == NULL)) { csound->Free(csound,ftevt); return csound->InitError(csound, Str("Named gen \"%s\" not defined"), (char *)p->p4); } else fp[4] = named->genum; } if (istring2) { /* string argument: */ n = (int) fp[4]; fp[5] = SSTRCOD; if (n < 0) n = -n; switch (n) { /* must be Gen01, 23, 28, 43, 49 */ case 1: case 23: case 28: case 43: case 49: ftevt->strarg = ((STRINGDAT *) p->p5)->data; break; default: csound->Free(csound, ftevt); return csound->InitError(csound, Str("ftgen string arg not allowed")); } } else { fp[5] = *p->p5; /* else no string */ } n = csound->GetInputArgCnt(p); ftevt->pcnt = (int16) n; n -= 5; if (n > 0) { MYFLT **argp = p->argums; fp += 6; do { *fp++ = **argp++; /* copy rem arglist */ } while (--n); } n = csound->hfgens(csound, &ftp, ftevt, 1); /* call the fgen */ csound->Free(csound, ftevt); if (UNLIKELY(n != 0)) return csound->InitError(csound, Str("ftgen error")); if (ftp != NULL) *p->ifno = (MYFLT) ftp->fno; /* record the fno */ return OK; } static int ftgen(CSOUND *csound, FTGEN *p) { return ftgen_(csound,p,0,0); } static int ftgen_S(CSOUND *csound, FTGEN *p) { return ftgen_(csound,p,1,0); } static int ftgen_iS(CSOUND *csound, FTGEN *p) { return ftgen_(csound,p,0,1); } static int ftgen_SS(CSOUND *csound, FTGEN *p) { return ftgen_(csound,p,1,1); } static int ftgentmp(CSOUND *csound, FTGEN *p) { int p1, fno; if (UNLIKELY(ftgen(csound, p) != OK)) return NOTOK; p1 = (int) MYFLT2LRND(*p->p1); if (p1) return OK; fno = (int) MYFLT2LRND(*p->ifno); return register_ftable_delete(csound, p, fno); } static int ftgentmp_S(CSOUND *csound, FTGEN *p) { int p1, fno; if (UNLIKELY(ftgen_(csound, p,0,1) != OK)) return NOTOK; p1 = (int) MYFLT2LRND(*p->p1); if (p1) return OK; fno = (int) MYFLT2LRND(*p->ifno); return register_ftable_delete(csound, p, fno); } static int ftgentmp_Si(CSOUND *csound, FTGEN *p) { int p1, fno; if (UNLIKELY(ftgen_(csound, p,1,0) != OK)) return NOTOK; p1 = (int) MYFLT2LRND(*p->p1); if (p1) return OK; fno = (int) MYFLT2LRND(*p->ifno); return register_ftable_delete(csound, p, fno); } static int ftgentmp_SS(CSOUND *csound, FTGEN *p) { int p1, fno; if (UNLIKELY(ftgen_(csound, p,1,1) != OK)) return NOTOK; p1 = (int) MYFLT2LRND(*p->p1); if (p1) return OK; fno = (int) MYFLT2LRND(*p->ifno); return register_ftable_delete(csound, p, fno); } static int ftfree(CSOUND *csound, FTFREE *p) { int fno = (int) MYFLT2LRND(*p->iftno); if (UNLIKELY(fno <= 0)) return csound->InitError(csound, Str("Invalid table number: %d"), fno); if (*p->ifreeTime == FL(0.0)) { if (UNLIKELY(csound->FTDelete(csound, fno) != 0)) return csound->InitError(csound, Str("Error deleting ftable %d"), fno); return OK; } return register_ftable_delete(csound, p, fno); } static int myInitError(CSOUND *csound, INSDS *p, const char *str, ...) { return csound->InitError(csound, "%s",str); } static int ftload_(CSOUND *csound, FTLOAD *p, int istring) { MYFLT **argp = p->argums; FUNC *ftp; char filename[MAXNAME]; int nargs = csound->GetInputArgCnt(p) - 2; FILE *file = NULL; int (*err_func)(CSOUND *, INSDS *, const char *, ...); FUNC *(*ft_func)(CSOUND *, MYFLT *); void *fd; if (strncmp(csound->GetOpcodeName(p), "ftload", 6) != 0) { nargs--; ft_func = csound->FTFindP; err_func = csound->PerfError; } else { ft_func = csound->FTnp2Find; err_func = myInitError; } if (UNLIKELY(nargs <= 0)) goto err2; if (!istring) { if (csound->ISSTRCOD(*p->ifilno)) csound->strarg2name(csound, filename, p->ifilno, "ftsave.", 0); else strncpy(filename, get_arg_string(csound,*p->ifilno), MAXNAME-1); } else { strncpy(filename, ((STRINGDAT *)p->ifilno)->data, MAXNAME-1); } if (*p->iflag <= FL(0.0)) { fd = csound->FileOpen2(csound, &file, CSFILE_STD, filename, "rb", "", CSFTYPE_FTABLES_BINARY, 0); if (UNLIKELY(fd == NULL)) goto err3; while (nargs--) { FUNC header; int fno = (int) MYFLT2LRND(**argp); MYFLT fno_f = (MYFLT) fno; size_t n; memset(&header, 0, sizeof(FUNC)); /* ***** Need to do byte order here ***** */ n = fread(&header, sizeof(FUNC) - sizeof(MYFLT) - SSTRSIZ, 1, file); if (UNLIKELY(n!=1)) goto err4; header.fno = (int32) fno; if (UNLIKELY(csound->FTAlloc(csound, fno, (int) header.flen) != 0)) goto err; ftp = ft_func(csound, &fno_f); // Do we need to check value of ftp->fflen? #27323 if (ftp->flen > 0x40000000) return csound->InitError(csound,Str("table length too long")); memcpy(ftp, &header, sizeof(FUNC) - sizeof(MYFLT*) - SSTRSIZ); memset(ftp->ftable, 0, sizeof(MYFLT) * ((uint64_t) ftp->flen + 1)); n = fread(ftp->ftable, sizeof(MYFLT), ftp->flen + 1l, file); if (UNLIKELY(n!=ftp->flen + 1)) goto err4; /* ***** Need to do byte order here ***** */ argp++; } } else { fd = csound->FileOpen2(csound, &file, CSFILE_STD, filename, "r", "", CSFTYPE_FTABLES_TEXT, 0); if (UNLIKELY(fd == NULL)) goto err3; while (nargs--) { FUNC header; char s[64], *s1; int fno = (int) MYFLT2LRND(**argp); MYFLT fno_f = (MYFLT) fno; uint32_t j; char *endptr; memset(&header, 0, sizeof(FUNC)); /* IMPORTANT!! If FUNC structure and/or GEN01ARGS structure will be modified, the following code has to be modified too */ if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; s1 = strchr(s, ' ')+1; header.flen = strtol(s1, &endptr, 10); if (UNLIKELY(endptr==NULL)) goto err4; if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; s1 = strchr(s, ' ')+1; header.lenmask = strtol(s1, &endptr, 10); if (UNLIKELY(endptr==NULL)) goto err4; if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; s1 = strchr(s, ' ')+1; header.lobits = strtol(s1, &endptr, 10); if (UNLIKELY(endptr==NULL)) goto err4; if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; s1 = strchr(s, ' ')+1; header.lomask = strtol(s1, &endptr, 10); if (UNLIKELY(endptr==NULL)) goto err4; if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; s1 = strchr(s, ' ')+1; header.lodiv = (MYFLT)strtol(s1, &endptr, 10); if (UNLIKELY(endptr==NULL)) goto err4; if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; s1 = strchr(s, ' ')+1; header.cvtbas = (MYFLT)strtol(s1, &endptr, 10); if (UNLIKELY(endptr==NULL)) goto err4; if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; s1 = strchr(s, ' ')+1; header.cpscvt = (MYFLT)strtol(s1, &endptr, 10); if (UNLIKELY(endptr==NULL)) goto err4; if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; s1 = strchr(s, ' ')+1; header.loopmode1 = (int16) strtol(s1, &endptr, 10); if (UNLIKELY(endptr==NULL)) goto err4; if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; s1 = strchr(s, ' ')+1; header.loopmode2 = (int16) strtol(s1, &endptr, 10); if (UNLIKELY(endptr==NULL)) goto err4; if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; s1 = strchr(s, ' ')+1; header.begin1 = strtol(s1, &endptr, 10); if (UNLIKELY(endptr==NULL)) goto err4; if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; s1 = strchr(s, ' ')+1; header.end1 = strtol(s1, &endptr, 10); if (UNLIKELY(endptr==NULL)) goto err4; if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; s1 = strchr(s, ' ')+1; header.begin2 = strtol(s1, &endptr, 10); if (UNLIKELY(endptr==NULL)) goto err4; if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; s1 = strchr(s, ' ')+1; header.end2 = strtol(s1, &endptr, 10); if (UNLIKELY(endptr==NULL)) goto err4; if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; s1 = strchr(s, ' ')+1; header.soundend = strtol(s1, &endptr, 10); if (UNLIKELY(endptr==NULL)) goto err4; if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; s1 = strchr(s, ' ')+1; header.flenfrms = strtol(s1, &endptr, 10); if (UNLIKELY(endptr==NULL)) goto err4; if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; s1 = strchr(s, ' ')+1; header.nchanls = strtol(s1, &endptr, 10); if (UNLIKELY(endptr==NULL)) goto err4; if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; s1 = strchr(s, ' ')+1; header.fno = strtol(s1, &endptr, 10); if (UNLIKELY(endptr==NULL)) goto err4; if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; s1 = strchr(s, ' ')+1; header.gen01args.gen01 = (MYFLT)cs_strtod(s1, &endptr); if (UNLIKELY(endptr==NULL)) goto err4; if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; s1 = strchr(s, ' ')+1; header.gen01args.ifilno = (MYFLT)cs_strtod(s1, &endptr); if (UNLIKELY(endptr==NULL)) goto err4; if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; s1 = strchr(s, ' ')+1; header.gen01args.iskptim = (MYFLT)cs_strtod(s1, &endptr); if (UNLIKELY(endptr==NULL)) goto err4; if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; s1 = strchr(s, ' ')+1; header.gen01args.iformat = (MYFLT)cs_strtod(s1, &endptr); if (UNLIKELY(endptr==NULL)) goto err4; if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; s1 = strchr(s, ' ')+1; header.gen01args.channel = (MYFLT)cs_strtod(s1, &endptr); if (UNLIKELY(endptr==NULL)) goto err4; if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; s1 = strchr(s, ' ')+1; header.gen01args.sample_rate = (MYFLT)cs_strtod(s1, &endptr); if (UNLIKELY(endptr==NULL)) goto err4; if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; s1 = strchr(s, ' ')+1; /* WARNING! skips header.gen01args.strarg from saving/loading in text format */ header.fno = (int32) fno; if (fno_f == fno) { ftp = ft_func(csound, &fno_f); if (ftp->flen < header.flen){ if (UNLIKELY(csound->FTAlloc(csound, fno, (int) header.flen) != 0)) goto err; } } else { if (UNLIKELY(csound->FTAlloc(csound, fno, (int) header.flen) != 0)) goto err; ftp = ft_func(csound, &fno_f); } memcpy(ftp, &header, sizeof(FUNC) - sizeof(MYFLT)); memset(ftp->ftable, 0, sizeof(MYFLT) * (ftp->flen + 1)); for (j = 0; j <= ftp->flen; j++) { if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; ftp->ftable[j] = (MYFLT) cs_strtod(s, &endptr); if (UNLIKELY(endptr==NULL)) goto err4; } if (UNLIKELY(NULL==fgets(s, 64, file))) goto err4; argp++; } } csound->FileClose(csound, fd); return OK; err: csound->FileClose(csound, fd); return err_func(csound, p->h.insdshead, Str("ftload: error allocating ftable")); err2: return err_func(csound, p->h.insdshead, Str("ftload: no table numbers")); err3: return err_func(csound, p->h.insdshead, Str("ftload: unable to open file")); err4: csound->FileClose(csound, fd); return err_func(csound, p->h.insdshead, Str("ftload: incorrect file")); } static int ftload(CSOUND *csound, FTLOAD *p) { return ftload_(csound, p, 0); } static int ftload_S(CSOUND *csound, FTLOAD *p) { return ftload_(csound, p, 1); } static int ftload_k(CSOUND *csound, FTLOAD_K *p) { if (*p->ktrig != FL(0.0)) return ftload_(csound, &(p->p),0); return OK; } static int ftload_kS(CSOUND *csound, FTLOAD_K *p) { if (*p->ktrig != FL(0.0)) return ftload_(csound, &(p->p), 1); return OK; } static int ftsave_(CSOUND *csound, FTLOAD *p, int istring) { MYFLT **argp = p->argums; char filename[MAXNAME]; int nargs = csound->GetInputArgCnt(p) - 3; FILE *file = NULL; int (*err_func)(CSOUND *, INSDS *, const char *, ...); FUNC *(*ft_func)(CSOUND *, MYFLT *); void *fd; if (strncmp(csound->GetOpcodeName(p), "ftsave.", 7) != 0) { ft_func = csound->FTFindP; err_func = csound->PerfError; } else { nargs = csound->GetInputArgCnt(p) - 2; ft_func = csound->FTnp2Find; err_func = myInitError; } if (UNLIKELY(nargs <= 0)) goto err2; if (!istring) { if (csound->ISSTRCOD(*p->ifilno)) csound->strarg2name(csound, filename, p->ifilno, "ftsave.", 0); else strncpy(filename, get_arg_string(csound,*p->ifilno), MAXNAME-1); } else { strncpy(filename, ((STRINGDAT *)p->ifilno)->data, MAXNAME-1); } if (*p->iflag <= FL(0.0)) { fd = csound->FileOpen2(csound, &file, CSFILE_STD, filename, "wb", "", CSFTYPE_FTABLES_BINARY, 0); if (UNLIKELY(fd == NULL)) goto err3; while (nargs--) { FUNC *ftp; //csound->Message(csound, "saving table %f \n", **argp); if ( *argp && (ftp = ft_func(csound, *argp)) != NULL) { MYFLT *table = ftp->ftable; int32 flen = ftp->flen; int n; n = fwrite(ftp, sizeof(FUNC) - sizeof(MYFLT) - SSTRSIZ, 1, file); if (UNLIKELY(n!=1)) goto err4; n = fwrite(table, sizeof(MYFLT), flen + 1, file); if (UNLIKELY(n!=flen + 1)) goto err4; } else goto err; argp++; } } else { fd = csound->FileOpen2(csound, &file, CSFILE_STD, filename, "w", "", CSFTYPE_FTABLES_TEXT, 0); if (UNLIKELY(fd == NULL)) goto err3; while (nargs--) { FUNC *ftp; if ((ftp = ft_func(csound, *argp)) != NULL) { int32 flen = ftp->flen; int32 j; MYFLT *table = ftp->ftable; /* IMPORTANT!! If FUNC structure and/or GEN01ARGS structure will be modified, the following code has to be modified too */ fprintf(file,"======= TABLE %d size: %d values ======\n", ftp->fno, ftp->flen); fprintf(file,"flen: %d\n", ftp->flen); fprintf(file,"lenmask: %d\n", ftp->lenmask); fprintf(file,"lobits: %d\n",ftp->lobits); fprintf(file,"lomask: %d\n",ftp->lomask); fprintf(file,"lodiv: %f\n",ftp->lodiv); fprintf(file,"cvtbas: %f\n",ftp->cvtbas); fprintf(file,"cpscvt: %f\n",ftp->cpscvt); fprintf(file,"loopmode1: %d\n", (int) ftp->loopmode1); fprintf(file,"loopmode2: %d\n", (int) ftp->loopmode2); fprintf(file,"begin1: %d\n",ftp->begin1); fprintf(file,"end1: %d\n",ftp->end1); fprintf(file,"begin2: %d\n",ftp->begin2); fprintf(file,"end2: %d\n",ftp->end2); fprintf(file,"soundend: %d\n",ftp->soundend); fprintf(file,"flenfrms: %d\n",ftp->flenfrms); fprintf(file,"nchnls: %d\n",ftp->nchanls); fprintf(file,"fno: %d\n",ftp->fno); fprintf(file,"gen01args.gen01: %f\n",ftp->gen01args.gen01); fprintf(file,"gen01args.ifilno: %f\n",ftp->gen01args.ifilno); fprintf(file,"gen01args.iskptim: %f\n",ftp->gen01args.iskptim); fprintf(file,"gen01args.iformat: %f\n",ftp->gen01args.iformat); fprintf(file,"gen01args.channel: %f\n",ftp->gen01args.channel); fprintf(file,"gen01args.sample_rate: %f\n", ftp->gen01args.sample_rate); /* WARNING! skips ftp->gen01args.strarg from saving/loading in text format */ fprintf(file,"---------END OF HEADER--------------\n"); for (j = 0; j <= flen; j++) { MYFLT val = table[j]; fprintf(file,"%f\n",val); } fprintf(file,"---------END OF TABLE---------------\n"); } else goto err; argp++; } } csound->FileClose(csound, fd); return OK; err: csound->FileClose(csound, fd); return err_func(csound, p->h.insdshead, Str("ftsave: Bad table number. Saving is possible " "only for existing tables.")); err2: return err_func(csound, p->h.insdshead, Str("ftsave: no table numbers")); err3: return err_func(csound, p->h.insdshead, Str("ftsave: unable to open file")); err4: return err_func(csound, p->h.insdshead, Str("ftsave: failed to write file")); } static int ftsave(CSOUND *csound, FTLOAD *p){ return ftsave_(csound,p,0); } static int ftsave_S(CSOUND *csound, FTLOAD *p){ return ftsave_(csound,p,1); } static int ftsave_k_set(CSOUND *csound, FTLOAD_K *p) { memcpy(&(p->p.h), &(p->h), sizeof(OPDS)); p->p.ifilno = p->ifilno; p->p.iflag = p->iflag; memcpy(p->p.argums, p->argums, sizeof(MYFLT*) * (csound->GetInputArgCnt(p) - 3)); return OK; } static int ftsave_k(CSOUND *csound, FTLOAD_K *p) { if (*p->ktrig != FL(0.0)) return ftsave_(csound, &(p->p), 0); return OK; } static int ftsave_kS(CSOUND *csound, FTLOAD_K *p) { if (*p->ktrig != FL(0.0)) return ftsave_(csound, &(p->p), 1); return OK; } static int ftgen_list(CSOUND *csound, FTGEN *p, int istring) { MYFLT *fp; FUNC *ftp; EVTBLK *ftevt; int n; *p->ifno = FL(0.0); ftevt =(EVTBLK*) csound->Malloc(csound, sizeof(EVTBLK)); ftevt->opcod = 'f'; ftevt->strarg = NULL; fp = &ftevt->p[0]; fp[0] = FL(0.0); fp[1] = *p->p1; /* copy p1 - p5 */ fp[2] = ftevt->p2orig = FL(0.0); /* force time 0 */ fp[3] = ftevt->p3orig = *p->p3; fp[4] = *p->p4; if (istring) { /* Named gen */ NAMEDGEN *named = (NAMEDGEN*) csound->GetNamedGens(csound); while (named) { if (strcmp(named->name, ((STRINGDAT *) p->p4)->data) == 0) { /* Look up by name */ fp[4] = named->genum; break; } named = named->next; /* and round again */ } if (UNLIKELY(named == NULL)) { csound->Free(csound,ftevt); return csound->InitError(csound, Str("Named gen \"%s\" not defined"), (char *)p->p4); } else fp[4] = named->genum; } ARRAYDAT *array = (ARRAYDAT*) (p->p5); n = array->sizes[0]; ftevt->pcnt = (int16) n+4; int i = 0; memcpy(&fp[5], array->data, n*sizeof(MYFLT)); while(i < n){ i++; } n = csound->hfgens(csound, &ftp, ftevt, 1); /* call the fgen */ csound->Free(csound,ftevt); if (UNLIKELY(n != 0)) return csound->InitError(csound, Str("ftgen error")); if (ftp != NULL) *p->ifno = (MYFLT) ftp->fno; /* record the fno */ return OK; } static int ftgen_list_S(CSOUND *csound, FTGEN *p){ return ftgen_list(csound,p,1); } static int ftgen_list_i(CSOUND *csound, FTGEN *p){ return ftgen_list(csound,p,0); } #define S(x) sizeof(x) static OENTRY localops[] = { { "ftgen", S(FTGEN), TW, 1, "i", "iiiiim", (SUBR) ftgen, NULL, NULL }, { "ftgen.S", S(FTGEN), TW, 1, "i", "iiiSim", (SUBR) ftgen_S, NULL, NULL }, { "ftgen.iS", S(FTGEN), TW, 1, "i", "iiiiSm", (SUBR) ftgen_iS, NULL, NULL }, { "ftgen.SS", S(FTGEN), TW, 1, "i", "iiiSSm", (SUBR) ftgen_SS, NULL, NULL }, { "ftgen", S(FTGEN), TW, 1, "i", "iiiii[]", (SUBR) ftgen_list_i, NULL }, { "ftgen", S(FTGEN), TW, 1, "i", "iiiSi[]", (SUBR) ftgen_list_S, NULL }, { "ftgentmp.i", S(FTGEN), TW, 1, "i", "iiiiim", (SUBR) ftgentmp, NULL, NULL }, { "ftgentmp.iS", S(FTGEN), TW, 1, "i", "iiiiSm", (SUBR) ftgentmp_S, NULL,NULL}, { "ftgentmp.Si", S(FTGEN), TW, 1, "i", "iiiSim", (SUBR) ftgentmp_Si,NULL,NULL}, { "ftgentmp.SS", S(FTGEN), TW, 1, "i", "iiiSSm", (SUBR) ftgentmp_SS,NULL,NULL}, { "ftfree", S(FTFREE), TW, 1, "", "ii", (SUBR) ftfree, NULL, NULL }, { "ftsave", S(FTLOAD), TR, 1, "", "iim", (SUBR) ftsave, NULL, NULL }, { "ftsave.S", S(FTLOAD), TR, 1, "", "Sim", (SUBR) ftsave_S, NULL, NULL }, { "ftload", S(FTLOAD), TR, 1, "", "iim", (SUBR) ftload, NULL, NULL }, { "ftload.S", S(FTLOAD), TR, 1, "", "Sim", (SUBR) ftload_S, NULL, NULL }, { "ftsavek", S(FTLOAD_K), TW, 3, "", "ikim", (SUBR) ftsave_k_set, (SUBR) ftsave_k, NULL }, { "ftsavek.S", S(FTLOAD_K), TW, 3, "", "Skim", (SUBR) ftsave_k_set, (SUBR) ftsave_kS, NULL }, { "ftloadk", S(FTLOAD_K), TW, 3, "", "ikim", (SUBR) ftsave_k_set, (SUBR) ftload_k, NULL }, { "ftloadk.S", S(FTLOAD_K), TW, 3, "", "Skim", (SUBR) ftsave_k_set, (SUBR) ftload_kS, NULL } }; int ftgen_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/ftsamplebank.cpp000066400000000000000000000277631321653344700176670ustar00rootroot00000000000000/* This file is part of Csound. Copyright (C) 2014 Rory Walsh The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "OpcodeBase.hpp" #include #include #include #include #include #include #include #include using namespace std; using namespace csound; /* this function will load all samples of supported types into function tables number 'index' and upwards. It return the number of samples loaded */ int loadSamplesToTables(CSOUND *csound, int index, char* directory, int skiptime, int format, int channel); //----------------------------------------------------------------- // i-rate class //----------------------------------------------------------------- class iftsamplebank : public OpcodeBase { public: // Outputs. MYFLT* numberOfFiles; // Inputs. STRINGDAT* sDirectory; MYFLT* index; // MYFLT* trigger; MYFLT* skiptime; MYFLT* format; MYFLT* channel; iftsamplebank() { channel = 0; index = 0; skiptime = 0; format = 0; index = 0; numberOfFiles = 0; sDirectory = NULL; } //init-pass int init(CSOUND *csound) { *numberOfFiles = loadSamplesToTables(csound, *index, (char* )sDirectory->data, *skiptime, *format, *channel); return OK; } int noteoff(CSOUND *) { return OK; } }; //----------------------------------------------------------------- // k-rate class //----------------------------------------------------------------- class kftsamplebank : public OpcodeBase { public: // Outputs. MYFLT* numberOfFiles; // Inputs. STRINGDAT* sDirectory; MYFLT* index; MYFLT* trigger; MYFLT* skiptime; MYFLT* format; MYFLT* channel; int internalCounter; kftsamplebank():internalCounter(0) { channel = 0; index = 0; skiptime = 0; format = 0; index = 0; trigger = 0; } //init-pass int init(CSOUND *csound) { *numberOfFiles = 0; //loadSamplesToTables(csound, *index, fileNames, // (char* )sDirectory->data, *skiptime, *format, *channel); //csound->Message(csound, (char* )sDirectory->data); *trigger=0; return OK; } int noteoff(CSOUND *) { return OK; } int kontrol(CSOUND* csound) { //if directry changes update tables.. if (*trigger==1) { *numberOfFiles = loadSamplesToTables(csound, *index, (char* )sDirectory->data, *skiptime, *format, *channel); *trigger = 0; } return OK; } }; //----------------------------------------------------------------- // load samples into function tables //----------------------------------------------------------------- int loadSamplesToTables(CSOUND *csound, int index, char* directory, int skiptime, int format, int channel) { if (directory) { DIR *dir = opendir(directory); std::vector fileNames; std::vector fileExtensions; int noOfFiles = 0; fileExtensions.push_back(".wav"); fileExtensions.push_back(".aiff"); fileExtensions.push_back(".ogg"); fileExtensions.push_back(".flac"); //check for valid path first if(dir) { struct dirent *ent; while((ent = readdir(dir)) != NULL) { std::ostringstream fullFileName; //only use supported file types for(int i=0;(size_t)id_name; if (fname.find(fileExtensions[i], (fname.length() - fileExtensions[i].length())) != std::string::npos) { if(strlen(directory)>2) { #if defined(WIN32) fullFileName << directory << "\\" << ent->d_name; #else fullFileName << directory << "/" << ent->d_name; #endif } else fullFileName << ent->d_name; noOfFiles++; fileNames.push_back(fullFileName.str()); } } } // Sort names std::sort(fileNames.begin(), fileNames.end() ); // push statements to score, starting with table number 'index' for(int y = 0; (size_t) y < fileNames.size(); y++) { std::ostringstream statement; statement << "f" << index+y << " 0 0 1 \"" << fileNames[y] << "\" " << skiptime << " " << format << " " << channel << "\n"; //csound->MessageS(csound, CSOUNDMSG_ORCH, statement.str().c_str()); csound->InputMessage(csound, statement.str().c_str()); } closedir(dir); } else { csound->Message(csound, Str("Cannot load file. Error opening directory: %s\n"), directory); } //return number of files return noOfFiles; } else return 0; } typedef struct { OPDS h; ARRAYDAT* outArr; STRINGDAT *directoryName; MYFLT* extension; } DIR_STRUCT; /* this function will looks for files of a set type, in a particular directory */ std::vector searchDir(CSOUND *csound, char* directory, char* extension); /* from Opcodes/arrays.c */ static inline void tabensure(CSOUND *csound, ARRAYDAT *p, int size) { if (p->data==NULL || p->dimensions == 0 || (p->dimensions==1 && p->sizes[0] < size)) { size_t ss; if (p->data == NULL) { CS_VARIABLE* var = p->arrayType->createVariable(csound, NULL); p->arrayMemberSize = var->memBlockSize; } ss = p->arrayMemberSize*size; if (p->data==NULL) p->data = (MYFLT*)csound->Calloc(csound, ss); else p->data = (MYFLT*) csound->ReAlloc(csound, p->data, ss); p->dimensions = 1; p->sizes = (int*)csound->Malloc(csound, sizeof(int)); p->sizes[0] = size; } } static int directory(CSOUND *csound, DIR_STRUCT* p) { int inArgCount = p->INOCOUNT; char *extension, *file; std::vector fileNames; if (inArgCount==0) return csound->InitError(csound, Str("Error: you must pass a directory as a string.")); if(inArgCount==1) { fileNames = searchDir(csound, p->directoryName->data, (char *)""); } else if(inArgCount==2) { CS_TYPE* argType = csound->GetTypeForArg(p->extension); if(strcmp("S", argType->varTypeName) == 0) { extension = csound->Strdup(csound, ((STRINGDAT *)p->extension)->data); fileNames = searchDir(csound, p->directoryName->data, extension); } else return csound->InitError(csound, Str("Error: second parameter to directory" " must be a string")); } int numberOfFiles = fileNames.size(); tabensure(csound, p->outArr, numberOfFiles); STRINGDAT *strings = (STRINGDAT *) p->outArr->data; for(int i=0; i < numberOfFiles; i++) { file = &fileNames[i][0u]; strings[i].size = strlen(file) + 1; strings[i].data = csound->Strdup(csound, file); } fileNames.clear(); return OK; } //----------------------------------------------------------------- // load samples into function tables //----------------------------------------------------------------- std::vector searchDir(CSOUND *csound, char* directory, char* extension) { std::vector fileNames; if(directory) { DIR *dir = opendir(directory); std::string fileExtension(extension); int noOfFiles = 0; //check for valid path first if(dir) { struct dirent *ent; while((ent = readdir(dir)) != NULL) { std::ostringstream fullFileName; if(std::string(ent->d_name).find(fileExtension)!= std::string::npos && strlen(ent->d_name)>2) { if(strlen(directory)>2) { #if defined(WIN32) fullFileName << directory << "\\" << ent->d_name; #else fullFileName << directory << "/" << ent->d_name; #endif } else fullFileName << ent->d_name; noOfFiles++; fileNames.push_back(fullFileName.str()); } } // Sort names std::sort(fileNames.begin(), fileNames.end() ); } else { csound->Message(csound, Str("Cannot find directory. " "Error opening directory: %s\n"), directory); } closedir(dir); } return fileNames; } extern "C" { PUBLIC int csoundModuleInit_ftsamplebank(CSOUND *csound) { int status = csound->AppendOpcode(csound, (char*)"ftsamplebank.k", sizeof(kftsamplebank), 0, 3, (char*)"k", (char*)"Skkkkk", (int(*)(CSOUND*,void*)) kftsamplebank::init_, (int(*)(CSOUND*,void*)) kftsamplebank::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, (char*)"ftsamplebank.i", sizeof(iftsamplebank), 0, 1, (char*)"i", (char*)"Siiii", (int (*)(CSOUND*,void*)) iftsamplebank::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); /* status |= csound->AppendOpcode(csound, (char*)"ftsamplebank", 0xffff, 0, 0, 0, 0, 0, 0, 0); */ status |= csound->AppendOpcode(csound, (char*)"directory", sizeof(DIR_STRUCT), 0, 1, (char*)"S[]", (char*)"SN", (int (*)(CSOUND*,void*)) directory, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); return status; } #ifndef INIT_STATIC_MODULES PUBLIC int csoundModuleCreate(CSOUND *csound) { return 0; } PUBLIC int csoundModuleInit(CSOUND *csound) { return csoundModuleInit_ftsamplebank(csound); } PUBLIC int csoundModuleDestroy(CSOUND *csound) { return 0; } #endif } csound-6.10.0/Opcodes/gab/000077500000000000000000000000001321653344700152265ustar00rootroot00000000000000csound-6.10.0/Opcodes/gab/examples/000077500000000000000000000000001321653344700170445ustar00rootroot00000000000000csound-6.10.0/Opcodes/gab/examples/changed.csd000066400000000000000000000007461321653344700211370ustar00rootroot00000000000000 -odac -B441 -b441 sr = 44100 kr = 100 ksmps = 441 nchnls = 2 gkvar init 0 instr 1 ktrig changed gkvar printk2 ktrig kvar init 0 if ktrig = 0 goto noevent printk 0,kvar kvar = kvar+5 noevent: endin instr 2 gkvar = gkvar +1 turnoff endin i 1 0 20 i 2 1 1 i 2 3 1 i 2 4 1 i 2 8 1 i 2 12 1 csound-6.10.0/Opcodes/gab/examples/exitnow.csd000066400000000000000000000005061321653344700212350ustar00rootroot00000000000000 -odac1 -B441 -b441 sr = 44100 kr = 100 ksmps = 441 nchnls = 2 instr 1 print 55665 endin instr 2 exitnow endin i 1 0 20 i 2 6 1 csound-6.10.0/Opcodes/gab/examples/metro.csd000066400000000000000000000004451321653344700206700ustar00rootroot00000000000000 -odac -B441 -b441 sr = 44100 kr = 100 ksmps = 441 nchnls = 2 instr 1 ktrig metro 0.2 printk2 ktrig endin i 1 0 20 csound-6.10.0/Opcodes/gab/examples/vrandi.csd000066400000000000000000000007561321653344700210320ustar00rootroot00000000000000 -odac1 -B441 -b441 sr = 44100 kr = 100 ksmps = 441 nchnls = 2 gindx init 0 instr 2 kout1 init 0 kout2 init 0 kout3 init 0 kout4 init 0 indx = p4 vrandi 1, 5, 2, 1 vtablek 1, 1, 0, 0, kout1, kout2, kout3, kout4 printk 0.5, kout1 printk 0.5, kout2 printk 0.5, kout3 printk 0.5, kout4 endin f 1 0 32 10 1 i 2 0 20 csound-6.10.0/Opcodes/gab/examples/vtable.csd000066400000000000000000000011211321653344700210070ustar00rootroot00000000000000 -odac1 -B441 -b441 sr = 44100 kr = 100 ksmps = 441 nchnls = 2 gindx init 0 instr 1 kindex init 0 ktrig metro 0.5 if ktrig = 0 goto noevent event "i", 2, 0, 0.5, kindex kindex = kindex + 1 noevent: endin instr 2 iout1 init 0 iout2 init 0 iout3 init 0 iout4 init 0 indx = p4 vtablei indx, 1, 1, 0, iout1,iout2, iout3, iout4 print iout1, iout2, iout3, iout4 turnoff endin f 1 0 32 10 1 i 1 0 20 csound-6.10.0/Opcodes/gab/gab.c000066400000000000000000000727031321653344700161340ustar00rootroot00000000000000 /* Copyright (C) 2002-2004 Gabriel Maldonado */ /* 2016 John ffitch (array changed) */ /* The gab library is free software; you can redistribute it */ /* and/or modify it under the terms of the GNU Lesser General Public */ /* License as published by the Free Software Foundation; either */ /* version 2.1 of the License, or (at your option) any later version. */ /* The gab library is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU Lesser General Public License for more details. */ /* You should have received a copy of the GNU Lesser General Public */ /* License along with the gab library; if not, write to the Free Software */ /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA */ /* 02111-1307 USA */ /* Ported to csound5 by: Andres Cabrera */ /* This file includes the opcodes from newopcodes.c */ /* TODO: Check if the authors (Peter Neubaeker and Jens Groh) are correct */ /*printi removed? I can't find the corresponding OENTRY- */ /*Left them commented out */ /*how should exitnow be safely implemented? */ /*Check the zak opcodes */ /*changed some comments to c-style */ /*Check csystem, exitnow */ /*Check other opcodes commented out in Oentry */ #include "stdopcod.h" #include "gab.h" #include #include "interlocks.h" #define FLT_MAX ((MYFLT)0x7fffffff) static int krsnsetx(CSOUND *csound, KRESONX *p) /* Gabriel Maldonado, modifies for arb order */ { int scale; p->scale = scale = (int) *p->iscl; if (UNLIKELY((p->loop = MYFLT2LRND(*p->ord)) < 1)) p->loop = 4; /*default value*/ if (!*p->istor && (p->aux.auxp == NULL || (unsigned int)(p->loop*2*sizeof(MYFLT)) > p->aux.size)) csound->AuxAlloc(csound, (long)(p->loop*2*sizeof(MYFLT)), &p->aux); p->yt1 = (MYFLT*)p->aux.auxp; p->yt2 = (MYFLT*)p->aux.auxp + p->loop; if (UNLIKELY(scale && scale != 1 && scale != 2)) { return csound->InitError(csound,Str("illegal reson iscl value, %f"), *p->iscl); } if (LIKELY(!(*p->istor))) { memset(p->yt1, 0, p->loop*sizeof(MYFLT)); memset(p->yt2, 0, p->loop*sizeof(MYFLT)); } p->prvcf = p->prvbw = -FL(100.0); return OK; } static int kresonx(CSOUND *csound, KRESONX *p) /* Gabriel Maldonado, modified */ { int flag = 0, j; MYFLT *ar, *asig; MYFLT c3p1, c3t4, omc3, c2sqr; MYFLT *yt1, *yt2, c1,c2,c3; if (*p->kcf != p->prvcf) { p->prvcf = *p->kcf; p->cosf = COS(*p->kcf * csound->tpidsr * CS_KSMPS); flag = 1; } if (*p->kbw != p->prvbw) { p->prvbw = *p->kbw; p->c3 = EXP(*p->kbw * csound->mtpdsr * CS_KSMPS); flag = 1; } if (flag) { c3p1 = p->c3 + FL(1.0); c3t4 = p->c3 * FL(4.0); omc3 = FL(1.0)- p->c3; p->c2 = c3t4 * p->cosf / c3p1; /* -B, so + below */ c2sqr = p->c2 * p->c2; if (p->scale == 1) p->c1 = omc3 * SQRT(FL(1.0) - (c2sqr / c3t4)); else if (p->scale == 2) p->c1 = SQRT((c3p1*c3p1-c2sqr) * omc3/c3p1); else p->c1 = FL(1.0); } c1 = p->c1; c2 = p->c2; c3 = p->c3; yt1 = p->yt1; yt2 = p->yt2; asig = p->asig; ar = p->ar; for (j=0; j< p->loop; j++) { *ar = c1 * *asig + c2 * yt1[j] - c3 * yt2[j]; yt2[j] = yt1[j]; yt1[j] = *ar; asig= p->ar; } return OK; } /* /////////////////////////////////////////// */ static int fastab_set(CSOUND *csound, FASTAB *p) { FUNC *ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->xfn)) == NULL)) { return csound->InitError(csound, Str("fastab: incorrect table number")); } p->table = ftp->ftable; p->tablen = ftp->flen; p->xmode = (int) *p->ixmode; if (p->xmode) p->xbmul = (MYFLT) p->tablen /*- FL(0.001)*/; else p->xbmul = FL(1.0); return OK; } static int fastabw(CSOUND *csound, FASTAB *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; FUNC *ftp = csound->FTnp2Find(csound, p->xfn); p->table = ftp->ftable; MYFLT *tab = p->table; MYFLT *rslt = p->rslt, *ndx = p->xndx; if (UNLIKELY(early)) nsmps -= early; if (p->xmode) { MYFLT xbmul = p->xbmul; /* load once */ int len = p->tablen; for (n=offset; n len || i<0)) { csound->Message(csound, "ndx: %f \n", ndx[n]); return csound->PerfError(csound, p->h.insdshead, Str("tabw off end")); } tab[i] = rslt[n]; } } else { int len = p->tablen; for (n=offset; n len || i<0)) { return csound->PerfError(csound, p->h.insdshead, Str("tabw off end")); } tab[i] = rslt[n]; } } return OK; } static int fastabk(CSOUND *csound, FASTAB *p) { int i; if (p->xmode) i = (int) (*p->xndx * p->xbmul); else i = (int) *p->xndx; if (UNLIKELY(i > p->tablen || i<0)) { return csound->PerfError(csound, p->h.insdshead, Str("tab off end %i"), i); } *p->rslt = p->table[i]; return OK; } static int fastabkw(CSOUND *csound, FASTAB *p) { int i; if (p->xmode) i = (int) (*p->xndx * p->xbmul); else i = (int) *p->xndx; if (UNLIKELY(i > p->tablen || i<0)) { return csound->PerfError(csound, p->h.insdshead, Str("tabw off end")); } p->table[i] = *p->rslt; return OK; } static int fastabi(CSOUND *csound, FASTAB *p) { FUNC *ftp; int32 i; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->xfn)) == NULL)) { return csound->InitError(csound, Str("tab_i: incorrect table number")); } if (*p->ixmode) i = (int32) (*p->xndx * ftp->flen); else i = (int32) *p->xndx; if (UNLIKELY(i >= (int32)ftp->flen || i<0)) { return csound->InitError(csound, Str("tab_i off end: table number: %d\n"), (int) *p->xfn); } *p->rslt = ftp->ftable[i]; return OK; } static int fastabiw(CSOUND *csound, FASTAB *p) { FUNC *ftp; int32 i; /*ftp = csound->FTFind(p->xfn); */ if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->xfn)) == NULL)) { return csound->InitError(csound, Str("tabw_i: incorrect table number")); } if (*p->ixmode) i = (int32) (*p->xndx * ftp->flen); else i = (int32) *p->xndx; if (UNLIKELY(i >= (int32)ftp->flen || i<0)) { return csound->PerfError(csound, p->h.insdshead, Str("tabw_i off end")); } ftp->ftable[i] = *p->rslt; return OK; } static int fastab(CSOUND *csound, FASTAB *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; FUNC *ftp = csound->FTnp2Find(csound, p->xfn); p->table = ftp->ftable; MYFLT *tab = p->table; MYFLT *rslt = p->rslt, *ndx = p->xndx; if (UNLIKELY(offset)) memset(rslt, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rslt[nsmps], '\0', early*sizeof(MYFLT)); } if (p->xmode) { MYFLT xbmul = p->xbmul; int len = p->tablen; for (i=offset; i len || n<0)) { return csound->PerfError(csound, p->h.insdshead, Str("tab off end %d"),n); } rslt[i] = tab[n]; } } else { int len = p->tablen; for (i=offset; i len || n<0)) { return csound->PerfError(csound, p->h.insdshead, Str("tab off end %d"),n); } rslt[i] = tab[n]; } } return OK; } static CS_NOINLINE int tab_init(CSOUND *csound, TB_INIT *p, int ndx) { MYFLT *ft; STDOPCOD_GLOBALS *pp; if (UNLIKELY(csoundGetTable(csound, &ft, MYFLT2LRND(*p->ifn)) < 0)) return csound->InitError(csound, Str("tab_init: incorrect table number")); pp = (STDOPCOD_GLOBALS*) csound->stdOp_Env; pp->tb_ptrs[ndx] = ft; return OK; } static CS_NOINLINE int tab_perf(CSOUND *csound, FASTB *p) { *p->r = (*p->tb_ptr)[(int) *p->ndx]; return OK; } static CS_NOINLINE int tab_i_tmp(CSOUND *csound, FASTB *p, int ndx) { STDOPCOD_GLOBALS *pp; pp = (STDOPCOD_GLOBALS*) csound->stdOp_Env; p->tb_ptr = &(pp->tb_ptrs[ndx]); p->h.iopadr = (SUBR) tab_perf; return tab_perf(csound, p); } static CS_NOINLINE int tab_k_tmp(CSOUND *csound, FASTB *p, int ndx) { STDOPCOD_GLOBALS *pp; pp = (STDOPCOD_GLOBALS*) csound->stdOp_Env; p->tb_ptr = &(pp->tb_ptrs[ndx]); p->h.opadr = (SUBR) tab_perf; return tab_perf(csound, p); } #ifdef TAB_MACRO #undef TAB_MACRO #endif #define TAB_MACRO(W,X,Y,Z) \ static int W(CSOUND *csound, TB_INIT *p) \ { return tab_init(csound, p, Z); } \ static int X(CSOUND *csound, FASTB *p) \ { return tab_i_tmp(csound, p, Z); } \ static int Y(CSOUND *csound, FASTB *p) \ { return tab_k_tmp(csound, p, Z); } TAB_MACRO(tab0_init, tab0_i_tmp, tab0_k_tmp, 0) TAB_MACRO(tab1_init, tab1_i_tmp, tab1_k_tmp, 1) TAB_MACRO(tab2_init, tab2_i_tmp, tab2_k_tmp, 2) TAB_MACRO(tab3_init, tab3_i_tmp, tab3_k_tmp, 3) TAB_MACRO(tab4_init, tab4_i_tmp, tab4_k_tmp, 4) TAB_MACRO(tab5_init, tab5_i_tmp, tab5_k_tmp, 5) TAB_MACRO(tab6_init, tab6_i_tmp, tab6_k_tmp, 6) TAB_MACRO(tab7_init, tab7_i_tmp, tab7_k_tmp, 7) TAB_MACRO(tab8_init, tab8_i_tmp, tab8_k_tmp, 8) TAB_MACRO(tab9_init, tab9_i_tmp, tab9_k_tmp, 9) TAB_MACRO(tab10_init, tab10_i_tmp, tab10_k_tmp, 10) TAB_MACRO(tab11_init, tab11_i_tmp, tab11_k_tmp, 11) TAB_MACRO(tab12_init, tab12_i_tmp, tab12_k_tmp, 12) TAB_MACRO(tab13_init, tab13_i_tmp, tab13_k_tmp, 13) TAB_MACRO(tab14_init, tab14_i_tmp, tab14_k_tmp, 14) TAB_MACRO(tab15_init, tab15_i_tmp, tab15_k_tmp, 15) /* ====================== */ /* opcodes from Jens Groh */ /* ====================== */ static int nlalp_set(CSOUND *csound, NLALP *p) { if (LIKELY(!(*p->istor))) { p->m0 = 0.0; p->m1 = 0.0; } return OK; } static int nlalp(CSOUND *csound, NLALP *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *rp; MYFLT *ip; double m0; double m1; double tm0; double tm1; double klfact; double knfact; rp = p->aresult; ip = p->ainsig; klfact = (double)*p->klfact; knfact = (double)*p->knfact; tm0 = p->m0; tm1 = p->m1; if (UNLIKELY(offset)) memset(rp, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rp[nsmps], '\0', early*sizeof(MYFLT)); } if (knfact == 0.0) { /* linear case */ if (UNLIKELY(klfact == 0.0)) { /* degenerated linear case */ m0 = (double)ip[0] - tm1; rp[offset] = (MYFLT)(tm0); for (n=offset+1; nm0 = tm0; p->m1 = tm1; return OK; } /* ----------------------------------------------- */ static int adsynt2_set(CSOUND *csound,ADSYNT2 *p) { FUNC *ftp; unsigned int count; int32 *lphs; MYFLT iphs = *p->iphs; p->inerr = 0; if (LIKELY((ftp = csound->FTFind(csound, p->ifn)) != NULL)) { p->ftp = ftp; } else { p->inerr = 1; return csound->InitError(csound, Str("adsynt2: wavetable not found!")); } count = (unsigned int)*p->icnt; if (UNLIKELY(count < 1)) count = 1; p->count = count; if (LIKELY((ftp = csound->FTnp2Find(csound, p->ifreqtbl)) != NULL)) { p->freqtp = ftp; } else { p->inerr = 1; return csound->InitError(csound, Str("adsynt2: freqtable not found!")); } if (UNLIKELY(ftp->flen < count)) { p->inerr = 1; return csound->InitError(csound, Str("adsynt2: partial count is greater " "than freqtable size!")); } if (LIKELY((ftp = csound->FTnp2Find(csound, p->iamptbl)) != NULL)) { p->amptp = ftp; } else { p->inerr = 1; return csound->InitError(csound, Str("adsynt2: amptable not found!")); } if (UNLIKELY(ftp->flen < count)) { p->inerr = 1; return csound->InitError(csound, Str("adsynt2: partial count is greater " "than amptable size!")); } if (p->lphs.auxp==NULL || p->lphs.size < sizeof(int32)*count) csound->AuxAlloc(csound, sizeof(int32)*count, &p->lphs); lphs = (int32*)p->lphs.auxp; if (iphs > 1) { unsigned int c; for (c=0; cRand31(&(csound->randSeed1)) - 1) / 2147483645.0) * FMAXLEN)) & PHMASK; } } else if (iphs >= 0) { unsigned int c; for (c=0; cpamp.auxp==NULL || p->pamp.size < (uint32_t)(sizeof(MYFLT)*p->count)) csound->AuxAlloc(csound, sizeof(MYFLT)*p->count, &p->pamp); else if (iphs >= 0) /* AuxAlloc clear anyway */ memset(p->pamp.auxp, 0, sizeof(MYFLT)*p->count); return OK; } static int adsynt2(CSOUND *csound,ADSYNT2 *p) { FUNC *ftp, *freqtp, *amptp; MYFLT *ar, *ftbl, *freqtbl, *amptbl, *prevAmp; MYFLT amp0, amp, cps0, cps, ampIncr, amp2; int32 phs, inc, lobits; int32 *lphs; int c, count; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; /* I believe this can never happen as InitError will remove instance */ /* The check should be on p->amptp and p->freqtp -- JPff */ if (UNLIKELY(p->inerr || p->amptp==NULL || p->freqtp==NULL)) { return csound->InitError(csound, Str("adsynt2: not initialised")); } ftp = p->ftp; ftbl = ftp->ftable; lobits = ftp->lobits; freqtp = p->freqtp; freqtbl = freqtp->ftable; amptp = p->amptp; amptbl = amptp->ftable; lphs = (int32*)p->lphs.auxp; prevAmp = (MYFLT*)p->pamp.auxp; cps0 = *p->kcps; amp0 = *p->kamp; count = p->count; ar = p->sr; memset(ar, 0, nsmps*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (c=0; csicvt); phs = lphs[c]; ampIncr = (amp - amp2) * CS_ONEDKSMPS; for (n=offset; n> lobits)) * amp2; phs += inc; phs &= PHMASK; amp2 += ampIncr; } prevAmp[c] = amp; lphs[c] = phs; } return OK; } static int exitnow(CSOUND *csound, EXITNOW *p) { (void) p; csound->LongJmp(csound, MYFLT2LRND(*p->retval)); return OK; /* compiler only */ } static int tabrec_set(CSOUND *csound,TABREC *p) { p->recording = 0; p->currtic = 0; p->ndx = 0; p->numins = p->INOCOUNT-4; return OK; } static int tabrec_k(CSOUND *csound,TABREC *p) { if (*p->ktrig_start) { if (*p->kfn != p->old_fn) { int flen; if (UNLIKELY((flen = csoundGetTable(csound,&(p->table),(int)*p->kfn)) < 0)) return csound->PerfError(csound, p->h.insdshead, Str("Invalid ftable no. %f"), *p->kfn); p->tablen = (long) flen; *(p->table++) = *p->numtics; p->old_fn = *p->kfn; } p->recording = 1; p->ndx = 0; p->currtic = 0; } if (*p->ktrig_stop) { if (p->currtic >= *p->numtics) { p->recording = 0; return OK; } p->currtic++; } if (p->recording) { int j, curr_frame = p->ndx * p->numins; MYFLT *table = p->table; MYFLT **inargs = p->inargs; if (curr_frame + p->numins < p->tablen) { /* record only if table is not full */ for (j = 0; j < p->numins; j++) table[curr_frame + j] = *inargs[j]; } (p->ndx)++; } return OK; } /*-------------------------*/ static int tabplay_set(CSOUND *csound,TABPLAY *p) { /* FUNC *ftp; */ /* if ((ftp = csound->FTFind(p->ifn)) == NULL) { */ /* csound->InitError(csound, Str("tabplay: incorrect table number")); */ /* return; */ /* } */ /* p->table = ftp->ftable; */ /* p->tablen = ftp->flen; */ p->playing = 0; p->currtic = 0; p->ndx = 0; p->numouts = p->INOCOUNT-3; return OK; } static int tabplay_k(CSOUND *csound,TABPLAY *p) { if (*p->ktrig) { if (*p->kfn != p->old_fn) { int flen; if (UNLIKELY((flen = csoundGetTable(csound, &(p->table),(int)*p->kfn)) < 0)) return csound->PerfError(csound, p->h.insdshead, Str("Invalid ftable no. %f"), *p->kfn); p->tablen = (long) flen; p->currtic = 0; p->ndx = 0; *(p->table++) = *p->numtics; p->old_fn = *p->kfn; } p->playing = 1; if (p->currtic == 0) p->ndx = 0; if (p->currtic >= *p->numtics) { p->playing = 0; return OK; } p->currtic++; p->currtic %= (long) *p->numtics; } if (p->playing) { int j, curr_frame = p->ndx * p->numouts; MYFLT *table = p->table; MYFLT **outargs = p->outargs; if (UNLIKELY(curr_frame + p->numouts < p->tablen)) { /* play only if ndx is inside table */ for (j = 0; j < p->numouts; j++) *outargs[j] = table[curr_frame+j]; } (p->ndx)++; } return OK; } static int isChanged_set(CSOUND *csound,ISCHANGED *p) { p->numargs = p->INOCOUNT; memset(p->old_inargs, 0, sizeof(MYFLT)*p->numargs); /* Initialise */ p->cnt = 1; return OK; } static int isChanged(CSOUND *csound,ISCHANGED *p) { MYFLT **inargs = p->inargs; MYFLT *old_inargs = p->old_inargs; int numargs = p->numargs, ktrig = 0, j; if (LIKELY(p->cnt)) for (j =0; j< numargs; j++) { if (*inargs[j] != old_inargs[j]) { ktrig = 1; break; } } if (ktrig || p->cnt==0) { for (j =0; j< numargs; j++) { old_inargs[j] = *inargs[j]; } } *p->ktrig = (MYFLT) ktrig; p->cnt++; return OK; } static int isChanged2_set(CSOUND *csound,ISCHANGED *p) { int res = isChanged_set(csound,p); p->cnt = 0; return res; } /* changed in array */ static int isAChanged_set(CSOUND *csound, ISACHANGED *p) { int size = 0, i; ARRAYDAT *arr = p->chk; //char *tmp; for (i=0; idimensions; i++) size += arr->sizes[i]; size *= arr->arrayMemberSize; csound->AuxAlloc(csound, size, &p->old_chk); /* tmp = (char*)p->old_chk.auxp; */ /* for (i=0; iold_chk.auxp, '\0', size); */ p->size = size; p->cnt = 0; return OK; } static int isAChanged(CSOUND *csound,ISACHANGED *p) { ARRAYDAT *chk = p->chk; void *old_chk = p->old_chk.auxp; int size = p->size; int ktrig = memcmp(chk->data, old_chk, size); memcpy(old_chk, chk->data, size); *p->ktrig = (p->cnt && ktrig)?FL(1.0):FL(0.0); p->cnt++; return OK; } /* ------------------------- */ static int partial_maximum_set(CSOUND *csound,P_MAXIMUM *p) { int flag = (int) *p->imaxflag; switch (flag) { case 1: p->max = 0; break; case 2: p->max = -FLT_MAX; break; case 3: p->max = FLT_MAX; break; case 4: p->max = 0; break; } p->counter = 0; return OK; } static int partial_maximum(CSOUND *csound,P_MAXIMUM *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int flag = (int) *p->imaxflag; MYFLT *a = p->asig; MYFLT max = p->max; if (UNLIKELY(early)) nsmps -= early; switch(flag) { case 1: /* absolute maximum */ for (n=offset; n max) max = temp; } if (max > p->max) p->max = max; break; case 2: /* actual maximum */ for (n=offset; n max) max = a[n]; } if (max > p->max) p->max = max; break; case 3: /* actual minimum */ for (n=offset; nmax) p->max = max; break; case 4: { /* average */ MYFLT temp = FL(0.0); p->counter += nsmps; for (n=offset; nmax += temp; } break; default: return csound->PerfError(csound, p->h.insdshead, Str("max_k: invalid imaxflag value")); } if (*p->ktrig) { switch (flag) { case 4: *p->kout = p->max / (MYFLT) p->counter; p->counter = 0; p->max = FL(0.0); break; case 1: *p->kout = p->max; p->max = 0; break; case 2: *p->kout = p->max; p->max = -FLT_MAX; break; case 3: *p->kout = p->max; p->max = FLT_MAX; break; } } return OK; } /* From fractals.c */ /* mandelbrot set scanner */ static int mandel_set(CSOUND *csound,MANDEL *p) { p->oldx=-99999; /*probably unused values */ p->oldy=-99999; p->oldCount = -1; return OK; } static int mandel(CSOUND *csound,MANDEL *p) { MYFLT px=*p->kx, py=*p->ky; if (*p->ktrig && (px != p->oldx || py != p->oldy)) { int maxIter = (int) *p->kmaxIter, j; MYFLT x=FL(0.0), y=FL(0.0), newx, newy; for (j=0; j= FL(4.0)) break; } p->oldx = px; p->oldy = py; if (p->oldCount != j) *p->koutrig = FL(1.0); else *p->koutrig = FL(0.0); *p->kr = (MYFLT) (p->oldCount = j); } else { *p->kr = (MYFLT) p->oldCount; *p->koutrig = FL(0.0); } return OK; } #define S(x) sizeof(x) OENTRY gab_localops[] = { {"resonxk", S(KRESONX), 0, 3, "k", "kkkooo", (SUBR) krsnsetx, (SUBR) kresonx, NULL }, { "tab_i",S(FASTAB), TR, 1, "i", "iio", (SUBR) fastabi, NULL, NULL }, { "tab",S(FASTAB), TR, 5, "a", "xio", (SUBR) fastab_set, (SUBR)NULL, (SUBR) fastab }, { "tab.k",S(FASTAB), TR, 3, "k", "kio", (SUBR) fastab_set, (SUBR)fastabk, NULL }, { "tabw_i",S(FASTAB), TW, 1, "", "iiio", (SUBR) fastabiw, NULL, NULL }, { "tabw",S(FASTAB), TW, 7, "", "xxio", (SUBR)fastab_set, (SUBR)fastabkw, (SUBR)fastabw }, { "tb0_init", S(TB_INIT), TR, 1, "", "i", (SUBR)tab0_init}, { "tb1_init", S(TB_INIT), TR, 1, "", "i", (SUBR)tab1_init}, { "tb2_init", S(TB_INIT), TR, 1, "", "i", (SUBR)tab2_init}, { "tb3_init", S(TB_INIT), TR, 1, "", "i", (SUBR)tab3_init}, { "tb4_init", S(TB_INIT), TR, 1, "", "i", (SUBR)tab4_init}, { "tb5_init", S(TB_INIT), TR, 1, "", "i", (SUBR)tab5_init}, { "tb6_init", S(TB_INIT), TR, 1, "", "i", (SUBR)tab6_init}, { "tb7_init", S(TB_INIT), TR, 1, "", "i", (SUBR)tab7_init}, { "tb8_init", S(TB_INIT), TR, 1, "", "i", (SUBR)tab8_init}, { "tb9_init", S(TB_INIT), TR, 1, "", "i", (SUBR)tab9_init}, { "tb10_init", S(TB_INIT), TR, 1, "", "i", (SUBR)tab10_init}, { "tb11_init", S(TB_INIT), TR, 1, "", "i", (SUBR)tab11_init}, { "tb12_init", S(TB_INIT), TR, 1, "", "i", (SUBR)tab12_init}, { "tb13_init", S(TB_INIT), TR, 1, "", "i", (SUBR)tab13_init}, { "tb14_init", S(TB_INIT), TR, 1, "", "i", (SUBR)tab14_init}, { "tb15_init", S(TB_INIT), TR, 1, "", "i", (SUBR)tab15_init}, /* tbx_t (t-rate version removed here) */ { "tb0.i", S(FASTB), 0, 1, "i", "i", (SUBR) tab0_i_tmp }, { "tb1.i", S(FASTB), 0, 1, "i", "i", (SUBR) tab1_i_tmp }, { "tb2.i", S(FASTB), 0, 1, "i", "i", (SUBR) tab2_i_tmp }, { "tb3.i", S(FASTB), 0, 1, "i", "i", (SUBR) tab3_i_tmp }, { "tb4.i", S(FASTB), 0, 1, "i", "i", (SUBR) tab4_i_tmp }, { "tb5.i", S(FASTB), 0, 1, "i", "i", (SUBR) tab5_i_tmp }, { "tb6.i", S(FASTB), 0, 1, "i", "i", (SUBR) tab6_i_tmp }, { "tb7.i", S(FASTB), 0, 1, "i", "i", (SUBR) tab7_i_tmp }, { "tb8.i", S(FASTB), 0, 1, "i", "i", (SUBR) tab8_i_tmp }, { "tb9.i", S(FASTB), 0, 1, "i", "i", (SUBR) tab9_i_tmp }, { "tb10.i", S(FASTB), 0, 1, "i", "i", (SUBR) tab10_i_tmp }, { "tb11.i", S(FASTB), 0, 1, "i", "i", (SUBR) tab11_i_tmp }, { "tb12.i", S(FASTB), 0, 1, "i", "i", (SUBR) tab12_i_tmp }, { "tb13.i", S(FASTB), 0, 1, "i", "i", (SUBR) tab13_i_tmp }, { "tb14.i", S(FASTB), 0, 1, "i", "i", (SUBR) tab14_i_tmp }, { "tb15.i", S(FASTB),0, 1, "i", "i", (SUBR) tab15_i_tmp }, { "tb0.k", S(FASTB), 0, 2, "k", "k", NULL, (SUBR) tab0_k_tmp, NULL }, { "tb1.k", S(FASTB), 0, 2, "k", "k", NULL, (SUBR) tab1_k_tmp, NULL }, { "tb2.k", S(FASTB), 0, 2, "k", "k", NULL, (SUBR) tab2_k_tmp, NULL }, { "tb3.k", S(FASTB), 0, 2, "k", "k", NULL, (SUBR) tab3_k_tmp, NULL }, { "tb4.k", S(FASTB), 0, 2, "k", "k", NULL, (SUBR) tab4_k_tmp, NULL }, { "tb5.k", S(FASTB), 0, 2, "k", "k", NULL, (SUBR) tab5_k_tmp, NULL }, { "tb6.k", S(FASTB), 0, 2, "k", "k", NULL, (SUBR) tab6_k_tmp, NULL }, { "tb7.k", S(FASTB), 0, 2, "k", "k", NULL, (SUBR) tab7_k_tmp, NULL }, { "tb8.k", S(FASTB), 0, 2, "k", "k", NULL, (SUBR) tab8_k_tmp, NULL }, { "tb9.k", S(FASTB), 0, 2, "k", "k", NULL, (SUBR) tab9_k_tmp, NULL }, { "tb10.k", S(FASTB), 0, 2, "k", "k", NULL, (SUBR) tab10_k_tmp, NULL }, { "tb11.k", S(FASTB), 0, 2, "k", "k", NULL, (SUBR) tab11_k_tmp, NULL }, { "tb12.k", S(FASTB), 0, 2, "k", "k", NULL, (SUBR) tab12_k_tmp, NULL }, { "tb13.k", S(FASTB), 0, 2, "k", "k", NULL, (SUBR) tab13_k_tmp, NULL }, { "tb14.k", S(FASTB), 0, 2, "k", "k", NULL, (SUBR) tab14_k_tmp, NULL }, { "tb15.k", S(FASTB), 0, 2, "k", "k", NULL, (SUBR) tab15_k_tmp, NULL }, { "nlalp", S(NLALP), 0, 5, "a", "akkoo", (SUBR) nlalp_set, NULL, (SUBR) nlalp }, { "adsynt2",S(ADSYNT2),TR, 5, "a", "kkiiiio", (SUBR) adsynt2_set, NULL, (SUBR)adsynt2 }, { "exitnow",S(EXITNOW), 0, 1, "", "o", (SUBR) exitnow, NULL, NULL }, /* { "zr_i", S(ZKR), 0, 1, "i", "i", (SUBR)zread, NULL, NULL}, */ /* { "zr_k", S(ZKR), 0, 2, "k", "k", NULL, (SUBR)zread, NULL}, */ /* { "zr_a", S(ZAR), 0, 5, "a", "a", (SUBR)zaset, NULL, (SUBR)zar}, */ /* { "k_i", S(ASSIGN), 0, 1, "k", "i", (SUBR)assign}, */ /* { "k_t", S(ASSIGN), 0, 2, "k", "t", NULL, (SUBR)assign}, */ /* { "a_k", S(INDIFF), 0, 5, "a", "k", (SUBR)a_k_set,NULL, (SUBR)interp }, */ { "tabrec", S(TABREC), 0, 3, "", "kkkkz", (SUBR) tabrec_set, (SUBR) tabrec_k, NULL }, { "tabplay", S(TABPLAY), TR, 3, "", "kkkz", (SUBR) tabplay_set, (SUBR) tabplay_k, NULL }, { "changed.k", S(ISCHANGED), _QQ, 3, "k", "z", (SUBR) isChanged_set, (SUBR)isChanged, NULL }, { "changed2.k", S(ISCHANGED), 0, 3, "k", "z", (SUBR) isChanged2_set, (SUBR)isChanged, NULL }, { "changed2.A", S(ISACHANGED), 0, 3, "k", ".[]", (SUBR) isAChanged_set, (SUBR)isAChanged, NULL }, /*{ "ftlen_k",S(EVAL), 0, 2, "k", "k", NULL, (SUBR)ftlen }, */ { "max_k", S(P_MAXIMUM), 0, 5, "k", "aki", (SUBR) partial_maximum_set, (SUBR) NULL, (SUBR) partial_maximum }, /*{ "maxk", S(P_MAXIMUM), 0, 5, "k", "aki", */ /* (SUBR) partial_maximum_set, (SUBR) NULL, (SUBR) partial_maximum }, */ { "mandel",S(MANDEL), 0, 3, "kk", "kkkk", (SUBR) mandel_set, (SUBR) mandel, NULL } }; int gab_gab_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(gab_localops[0]), (int) (sizeof(gab_localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/gab/gab.h000066400000000000000000000066311321653344700161360ustar00rootroot00000000000000/* Copyright (C) 2002-2004 Gabriel Maldonado The gab library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The gab library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the gab library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Ported to csound5 by:Andres Cabrera andres@geminiflux.com */ #ifndef GAB_H #define GAB_H #include "../stdopcod.h" #include "H/ugrw1.h" /* for zread function */ #include "ugens6.h" /* for a_k_set function */ typedef struct { OPDS h; MYFLT *ar, *asig, *kcf, *kbw, *ord, *iscl, *istor; int scale, loop; MYFLT c1, c2, c3, *yt1, *yt2, cosf, prvcf, prvbw; AUXCH aux; } KRESONX; typedef struct { OPDS h; MYFLT *rslt, *xndx, *xfn, *ixmode; MYFLT *table; MYFLT xbmul; int xmode; int tablen; } FASTAB; typedef struct { OPDS h; MYFLT *r, *ndx; MYFLT **tb_ptr; } FASTB; typedef struct { OPDS h; MYFLT *ifn; } TB_INIT; /* ====================== */ /* opcodes from Jens Groh */ /* ====================== */ typedef struct { /* for nlalp opcode */ OPDS h; /* header */ MYFLT *aresult; /* resulting signal */ MYFLT *ainsig; /* input signal */ MYFLT *klfact; /* linear factor */ MYFLT *knfact; /* nonlinear factor */ MYFLT *istor; /* initial storage disposition */ double m0; /* energy storage */ double m1; /* energy storage */ } NLALP; /* end opcodes from Jens Groh */ typedef struct { OPDS h; MYFLT *sr, *kamp, *kcps, *ifn, *ifreqtbl, *iamptbl, *icnt, *iphs; FUNC *ftp; FUNC *freqtp; FUNC *amptp; int count; int inerr; AUXCH lphs; AUXCH pamp; } ADSYNT2; typedef struct { OPDS h; MYFLT *retval; } EXITNOW; typedef struct { OPDS h; MYFLT *ktrig_start, *ktrig_stop, *numtics, *kfn, *inargs[VARGMAX]; int recording, numins; long currtic, ndx, tablen; MYFLT *table, old_fn; } TABREC; typedef struct { OPDS h; MYFLT *ktrig, *numtics, *kfn, *outargs[VARGMAX]; int playing, numouts; long currtic, ndx, tablen; MYFLT *table, old_fn; } TABPLAY; typedef struct { OPDS h; MYFLT *ktrig, *inargs[VARGMAX]; int numargs; /* Reordered for caching */ int cnt; MYFLT old_inargs[VARGMAX]; } ISCHANGED; typedef struct { OPDS h; MYFLT *ktrig; ARRAYDAT *chk; int size; int cnt; AUXCH old_chk; } ISACHANGED; typedef struct { OPDS h; MYFLT *commandLine; } CSSYSTEM; typedef struct { OPDS h; MYFLT *kout, *asig, *ktrig, *imaxflag; MYFLT max; int counter; } P_MAXIMUM; /* From fractals.h */ typedef struct { OPDS h; MYFLT *kr, *koutrig, *ktrig, *kx, *ky, *kmaxIter; MYFLT oldx, oldy; int oldCount; } MANDEL; #endif csound-6.10.0/Opcodes/gab/hvs.c000066400000000000000000000405501321653344700161760ustar00rootroot00000000000000/* Copyright (C) 2007 Gabriel Maldonado Csound is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ //#include "csdl.h" #include "csoundCore.h" #include "interlocks.h" /* -------------------------------------------------------------------- */ /* The iConfigTab is made up of the following parameters: f # time size -2 inactive_flag1 inactive_flag2 ... inactiveflagN a 1 value means that corresponding parameter is left unchanged by the HVS opcode The iPositionsTab is made up of the positions of the snapshots (contained in the iSnapTab) in the two-dimensional grid. Each subsequent element is actually a pointer representing the position in the iSnapTab. For example, in an HVS grid such as the following: 5 2 1 3 7 9 6 2 0 4 1 3 This represents the snapshot position within the grid (in this case a 4x3 grid). So, the first element 5, has index zero and represents the sixth (element zero is the first) element of the iSnapTab, the second element 2 represents the third element of iSnapTab and so on. Obviously, iOutTab size must be >= inumParms. */ typedef struct { OPDS h; MYFLT *kx, *inumParms, *inumPointsX, *iOutTab, *iPositionsTab, *iSnapTab, *iConfigTab; MYFLT *outTable, *posTable, *snapTable, *confTable; int iconfFlag; } HVS1; static int hvs1_set(CSOUND *csound, HVS1 *p) { FUNC *ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->iOutTab)) == NULL)) return csound->InitError(csound, Str("hvs: No out table")); p->outTable = ftp->ftable; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->iPositionsTab)) == NULL)) return csound->InitError(csound, Str("hvs: No positions table")); p->posTable = ftp->ftable; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->iSnapTab)) == NULL)) return csound->InitError(csound, Str("hvs: No snap table")); p->snapTable = ftp->ftable; if (UNLIKELY(*p->inumPointsX < 2 )) return csound->InitError(csound, Str("hvs1: a line segment must be " "delimited by 2 points at least")); if (*p->iConfigTab == 0) p->iconfFlag = 0; else { if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->iConfigTab)) == NULL)) return csound->InitError(csound, Str("hvs: no config table")); p->outTable = ftp->ftable; p->iconfFlag = 1; } return OK; } static int hvs1(CSOUND *csound, HVS1 *p) { MYFLT x = *p->kx * (*p->inumPointsX-1); int posX = (int) x; MYFLT fracX = x - posX; int noc = (int) *p->inumParms; // int linesX = (int) *p->inumPointsX; int ndx1 = (int) p->posTable[posX]; int ndx2 = (int) p->posTable[posX+1]; int j; if (p->iconfFlag) { for (j =0; j< noc; j++) { switch ((int) p->confTable[j]) { case -1: // ignore parameter break; case 0: // linear interpolation { MYFLT val1 = p->snapTable[ndx1 * noc + j]; MYFLT val2 = p->snapTable[ndx2 * noc + j]; MYFLT valu = (1 - fracX) * val1 + fracX * val2; p->outTable[j] = valu; } break; default: // special table=shaped interpolations ; // to be implemented... } } } else { for ( j =0; j< noc; j++) { MYFLT val1 = p->snapTable[ndx1 * noc + j]; MYFLT val2 = p->snapTable[ndx2 * noc + j]; MYFLT valu = (1 - fracX) * val1 + fracX * val2; p->outTable[j] = valu; } } return OK; } /* -------------------------------------------------------------------- */ typedef struct { OPDS h; MYFLT *kx, *ky, *inumParms, *inumlinesX, *inumlinesY, *iOutTab, *iPositionsTab, *iSnapTab, *iConfigTab; MYFLT *outTable, *posTable, *snapTable, *confTable; int iconfFlag; } HVS2; static int hvs2_set(CSOUND *csound, HVS2 *p) { FUNC *ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->iOutTab)) == NULL)) return csound->InitError(csound, Str("hvs: No out table")); p->outTable = ftp->ftable; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->iPositionsTab)) == NULL)) return csound->InitError(csound, Str("hvs: No positions table")); p->posTable = ftp->ftable; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->iSnapTab)) == NULL)) return csound->InitError(csound, Str("hvs: No snap table")); p->snapTable = ftp->ftable; if (UNLIKELY(*p->inumlinesX < 2 || *p->inumlinesY < 2)) return csound->InitError(csound, Str("hvs2: a square area must be " "delimited by 2 lines at least")); if (*p->iConfigTab == 0) p->iconfFlag = 0; else { if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->iConfigTab)) == NULL)) return csound->InitError(csound, Str("hvs: no config table")); p->outTable = ftp->ftable; p->iconfFlag = 1; } return OK; } static int hvs2(CSOUND *csound, HVS2 *p) { MYFLT x = *p->kx * (*p->inumlinesX-1); MYFLT y = *p->ky * (*p->inumlinesY-1); int posX = (int) x; int posY = (int) y; MYFLT fracX = x - posX; MYFLT fracY = y - posY; int noc = (int) *p->inumParms; int linesX = (int) *p->inumlinesX; int ndx1 = (int) p->posTable[posX + posY * linesX]; int ndx2 = (int) p->posTable[posX+1 + posY * linesX]; int ndx3 = (int) p->posTable[posX + (posY+1) * linesX]; int ndx4 = (int) p->posTable[posX+1 + (posY+1) * linesX]; int j; if (p->iconfFlag) { for ( j =0; j< noc; j++) { switch ((int) p->confTable[j]) { case -1: // ignore parameter break; case 0: // linear interpolation { MYFLT val1 = p->snapTable[ndx1 * noc + j]; MYFLT val2 = p->snapTable[ndx2 * noc + j]; MYFLT val3 = p->snapTable[ndx3 * noc + j]; MYFLT val4 = p->snapTable[ndx4 * noc + j]; MYFLT valX1 = (1 - fracX) * val1 + fracX * val2; MYFLT valX2 = (1 - fracX) * val3 + fracX * val4; MYFLT valu = (1 - fracY) * valX1 + fracY * valX2; p->outTable[j] = valu; } break; default: // special table=shaped interpolations ; // to be implemented... } } } else { for ( j =0; j< noc; j++) { MYFLT val1 = p->snapTable[ndx1 * noc + j]; MYFLT val2 = p->snapTable[ndx2 * noc + j]; MYFLT val3 = p->snapTable[ndx3 * noc + j]; MYFLT val4 = p->snapTable[ndx4 * noc + j]; MYFLT valX1 = (1 - fracX) * val1 + fracX * val2; MYFLT valX2 = (1 - fracX) * val3 + fracX * val4; MYFLT valu = (1 - fracY) * valX1 + fracY * valX2; p->outTable[j] = valu; } } return OK; } /* -------------------------------------------------------------------- */ typedef struct { OPDS h; MYFLT *kx, *ky, *kz, *inumParms, *inumlinesX, *inumlinesY, *inumlinesZ, *iOutTab, *iPositionsTab, *iSnapTab, *iConfigTab; MYFLT *outTable, *posTable, *snapTable, *confTable; int iconfFlag; } HVS3; static int hvs3_set(CSOUND *csound, HVS3 *p) { FUNC *ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->iOutTab)) == NULL)) return csound->InitError(csound, Str("hvs: No out table")); p->outTable = ftp->ftable; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->iPositionsTab)) == NULL)) return csound->InitError(csound, Str("hvs: No positions table")); p->posTable = ftp->ftable; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->iSnapTab)) == NULL)) return csound->InitError(csound, Str("hvs: No snap table")); p->snapTable = ftp->ftable; if (UNLIKELY(*p->inumlinesX < 2 || *p->inumlinesY < 2)) return csound->InitError(csound, Str("hvs3: a square area must be " "delimited by 2 lines at least")); if (LIKELY(*p->iConfigTab == 0)) p->iconfFlag = 0; else { if ((ftp = csound->FTnp2Find(csound, p->iConfigTab)) == NULL) return csound->InitError(csound, Str("hvs: no config table")); p->outTable = ftp->ftable; p->iconfFlag = 1; } return OK; } static int hvs3(CSOUND *csound, HVS3 *p) { MYFLT x = *p->kx * (*p->inumlinesX-1); MYFLT y = *p->ky * (*p->inumlinesY-1); MYFLT z = *p->kz * (*p->inumlinesZ-1); int posX = (int) x; int posY = (int) y; int posZ = (int) z; MYFLT fracX = x - posX; MYFLT fracY = y - posY; MYFLT fracZ = z - posZ; int noc = (int) *p->inumParms; int linesX = (int) *p->inumlinesX; int linesXY = linesX * (int) *p->inumlinesY; int ndx1 = (int) p->posTable[posX + posY * linesX + posZ * linesXY]; int ndx2 = (int) p->posTable[posX+1 + posY * linesX + posZ * linesXY]; int ndx3 = (int) p->posTable[posX + (posY+1) * linesX + posZ * linesXY]; int ndx4 = (int) p->posTable[posX+1 + (posY+1) * linesX + posZ * linesXY]; int ndx5 = (int) p->posTable[posX + posY * linesX + (posZ+1) * linesXY]; int ndx6 = (int) p->posTable[posX+1 + posY * linesX + (posZ+1) * linesXY]; int ndx7 = (int) p->posTable[posX + (posY+1) * linesX + (posZ+1) * linesXY]; int ndx8 = (int) p->posTable[posX+1 + (posY+1) * linesX + (posZ+1) * linesXY]; int j; if (p->iconfFlag) { for ( j =0; j< noc; j++) { switch ((int) p->confTable[j]) { case -1: // ignore parameter break; case 0: // linear interpolation { MYFLT val1 = p->snapTable[ndx1 * noc + j]; MYFLT val2 = p->snapTable[ndx2 * noc + j]; MYFLT val3 = p->snapTable[ndx3 * noc + j]; MYFLT val4 = p->snapTable[ndx4 * noc + j]; MYFLT valX1 = (1 - fracX) * val1 + fracX * val2; MYFLT valX2 = (1 - fracX) * val3 + fracX * val4; MYFLT valY1 = (1 - fracY) * valX1 + fracY * valX2; MYFLT valY2, valu; val1 = p->snapTable[ndx5 * noc + j]; val2 = p->snapTable[ndx6 * noc + j]; val3 = p->snapTable[ndx7 * noc + j]; val4 = p->snapTable[ndx8 * noc + j]; valX1 = (1 - fracX) * val1 + fracX * val2; valX2 = (1 - fracX) * val3 + fracX * val4; valY2 = (1 - fracY) * valX1 + fracY * valX2; valu = (1-fracZ) * valY1 + fracZ * valY2; p->outTable[j] = valu; } break; default: // special table=shaped interpolations ; // to be implemented... } } } else { for ( j =0; j< noc; j++) { MYFLT val1 = p->snapTable[ndx1 * noc + j]; MYFLT val2 = p->snapTable[ndx2 * noc + j]; MYFLT val3 = p->snapTable[ndx3 * noc + j]; MYFLT val4 = p->snapTable[ndx4 * noc + j]; MYFLT valX1 = (1 - fracX) * val1 + fracX * val2; MYFLT valX2 = (1 - fracX) * val3 + fracX * val4; MYFLT valY1 = (1 - fracY) * valX1 + fracY * valX2; MYFLT valY2, valu; val1 = p->snapTable[ndx5 * noc + j]; val2 = p->snapTable[ndx6 * noc + j]; val3 = p->snapTable[ndx7 * noc + j]; val4 = p->snapTable[ndx8 * noc + j]; valX1 = (1 - fracX) * val1 + fracX * val2; valX2 = (1 - fracX) * val3 + fracX * val4; valY2 = (1 - fracY) * valX1 + fracY * valX2; valu = (1-fracZ) * valY1 + fracZ * valY2; p->outTable[j] = valu; } } return OK; } /* -------------------------------------------------------------------- */ typedef struct { FUNC *function, *nxtfunction; double d; } TSEG2; typedef struct { OPDS h; MYFLT *kphase, *ioutfunc, *ielements,*argums[VARGMAX]; TSEG2 *cursegp; MYFLT *vector; int elements; long nsegs; AUXCH auxch; } VPSEG; static int vphaseseg_set(CSOUND *csound, VPSEG *p) { TSEG2 *segp; int nsegs,j; MYFLT **argp; double dur, durtot = 0.0, prevphs; FUNC *nxtfunc, *curfunc, *ftp; nsegs = p->nsegs =((p->INCOUNT-3) >> 1); /* count segs & alloc if nec */ if ((segp = (TSEG2 *) p->auxch.auxp) == NULL) { csound->AuxAlloc(csound, (long)(nsegs+1)*sizeof(TSEG2), &p->auxch); p->cursegp = segp = (TSEG2 *) p->auxch.auxp; //(segp+nsegs)->cnt = MAXPOS; } argp = p->argums; if (UNLIKELY((nxtfunc = csound->FTnp2Find(csound, *argp++)) == NULL)) return csound->InitError(csound, Str("vphaseseg: the first function is " "invalid or missing")); if (LIKELY((ftp = csound->FTnp2Find(csound, p->ioutfunc)) != NULL)) { p->vector = ftp->ftable; p->elements = (int) *p->ielements; } else return csound->InitError(csound, Str("Failed to find ftable")); if (UNLIKELY(p->elements > (int)ftp->flen)) return csound->InitError(csound, Str("vphaseseg: invalid num. of elements")); /* vector = p->vector; */ /* flength = p->elements; */ memset(p->vector, 0, sizeof(MYFLT)*p->elements); /* do *vector++ = FL(0.0); */ /* while (--flength); */ if (UNLIKELY(**argp <= 0.0)) return NOTOK; /* if idur1 <= 0, skip init */ //p->cursegp = tempsegp =segp; /* else proceed from 1st seg */ segp--; do { segp++; /* init each seg .. */ curfunc = nxtfunc; dur = **argp++; if (UNLIKELY((nxtfunc = csound->FTnp2Find(csound, *argp++)) == NULL)) return csound->InitError(csound, Str("vphaseseg: function invalid or missing")); if (LIKELY(dur > 0.0f)) { durtot+=dur; segp->d = dur; //* ekr; segp->function = curfunc; segp->nxtfunction = nxtfunc; //segp->cnt = (long) (segp->d + .5); } else break; /* .. til 0 dur or done */ } while (--nsegs); segp++; segp->function = nxtfunc; segp->nxtfunction = nxtfunc; nsegs = p->nsegs; segp = p->cursegp; for (j=0; j< nsegs; j++) segp[j].d /= durtot; /* This could be a memmove */ for (j=nsegs-1; j>= 0; j--) segp[j+1].d = segp[j].d; segp[0].d = prevphs = 0.0; for (j=0; j<= nsegs; j++) { segp[j].d += prevphs; prevphs = segp[j].d; } return OK; } static int vphaseseg(CSOUND *csound, VPSEG *p) { TSEG2 *segp = p->cursegp; double phase = *p->kphase, partialPhase = 0.0; int j, flength; MYFLT *curtab = NULL, *nxttab = NULL, curval, nxtval, *vector; while (phase >= 1.0) phase -= 1.0; while (phase < 0.0) phase = 0.0; for (j = 0; j < p->nsegs; j++) { TSEG2 *seg = &segp[j], *seg1 = &segp[j+1]; if (phase < seg1->d) { curtab = seg->function->ftable; nxttab = seg1->function->ftable; partialPhase = (phase - seg->d) / (seg1->d - seg->d); break; } } if (UNLIKELY(curtab==NULL)) return NOTOK; flength = p->elements; vector = p->vector; do { curval = *curtab++; nxtval = *nxttab++; *vector++ = (MYFLT) (curval + ((nxtval - curval) * partialPhase)); } while (--flength); return OK; } /* -------------------------------------------------------------------- */ #define S(x) sizeof(x) OENTRY hvs_localops[] = { { "hvs1", S(HVS1), TB, 3, "", "kiiiiio", (SUBR)hvs1_set, (SUBR)hvs1, (SUBR)NULL }, { "hvs2", S(HVS2), TB, 3, "", "kkiiiiiio", (SUBR)hvs2_set, (SUBR)hvs2, (SUBR)NULL }, { "hvs3", S(HVS3), TB, 3, "", "kkkiiiiiiio", (SUBR)hvs3_set, (SUBR)hvs3, (SUBR)NULL }, { "vphaseseg", S(VPSEG), TB, 3, "", "kiim", (SUBR)vphaseseg_set, (SUBR)vphaseseg } }; int hvs_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(hvs_localops[0]), (int) (sizeof(hvs_localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/gab/newgabopc.c000066400000000000000000000542111321653344700173420ustar00rootroot00000000000000/* Copyright (C) 2007 Gabriel Maldonado Csound is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "interlocks.h" /* (Shouldn't there be global decl's for these?) */ #define INCR (0.001f) /* -------------------------------------------------------------------- */ typedef struct { OPDS h; MYFLT *xfn, *outargs[VARGMAX]; int nargs; long pfn; MYFLT *ftable; } MTABLE1; static int mtable1_set(CSOUND *csound, MTABLE1 *p) /* mtab by G.Maldonado */ { FUNC *ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->xfn)) == NULL)) return csound->InitError(csound, Str("vtable1: incorrect table number")); p->ftable = ftp->ftable; p->nargs = p->INOCOUNT-1; p->pfn = (long) *p->xfn; return OK; } static int mtable1_k(CSOUND *csound, MTABLE1 *p) { int j, nargs = p->nargs; MYFLT **out = p->outargs; MYFLT *table; if (p->pfn != (long)*p->xfn) { FUNC *ftp; if (UNLIKELY( (ftp = csound->FTFindP(csound, p->xfn) ) == NULL)) return csound->PerfError(csound, p->h.insdshead, Str("vtable1: incorrect table number")); p->pfn = (long)*p->xfn; p->ftable = ftp->ftable; } table= p->ftable; for (j=0; j < nargs; j++) *out[j] = table[j]; return OK; } /* -------------------------------------------------------------------- */ #if 0 static void unquote(char *dst, char *src) { if (src[0] == '"') { int len = (int) strlen(src) - 2; strcpy(dst, src + 1); if (len >= 0 && dst[len] == '"') dst[len] = '\0'; } else strcpy(dst, src); } PUBLIC int Sched(CSOUND *csound, MYFLT *args[], int numargs) { double starttime; int i; EVTBLK evt; char name[512]; /* if (p->XSTRCODE) { evt.strarg = (char*) p->args[0]; evt.p[1] = SSTRCOD; } else */ if (*args[1] == SSTRCOD) { unquote(name, csound->currevent->strarg); evt.strarg = name; evt.p[1] = SSTRCOD; evt.scnt = 1; } else { evt.strarg = NULL; evt.scnt = 0; evt.p[1] = *args[1]; } evt.opcod = (char) *args[0]; if (evt.opcod == 0) evt.opcod = 'i'; evt.pcnt = numargs -1; /* Add current time (see note about kadjust in triginset() above) */ starttime = *args[2]; if(starttime < FL(0.0)) { starttime = FL(0.0); } starttime += (double) csound->GetKcounter(csound) / (double) csound->GetKr(csound); /*starttime += (double) csound->global_kcounter / (double)csound->global_ekr;*/ /* Copy all arguments to the new event */ for (i = 0; i < numargs; i++) evt.p[i] = *args[i]; if (evt.p[2] < FL(0.0)) { evt.p[2] = FL(0.0); } return (csound->insert_score_event(csound, &evt, starttime) == 0 ? OK : NOTOK); } /* These opcode has not been implemented because very similar ones exist */ typedef struct { /* GAB 11/Jan/2001 */ OPDS h; MYFLT *trigger; MYFLT *args[PMAX+1]; } SCHEDK; static int schedk(CSOUND *csound, SCHEDK *p) { /* based on code by rasmus */ if (*p->trigger) /* Only do something if triggered */ Sched(csound, p->args, p->INOCOUNT-1); return OK; } static int schedk_i(CSOUND *csound, SCHEDK *p) { /* based on code by rasmus */ OPARMS *O = csound->oparms; O->RTevents = 1; /* Make sure kperf() looks for RT events */ /* O->ksensing = 1; */ /* O->OrcEvts = 1; */ /* - of the appropriate type */ if (CS_KCNT > 0 && *p->trigger != FL(0.0) && p->h.insdshead->p3 == 0) schedk(csound,p); return OK; } /* -------------------------------------------------------------------- */ /* These opcodes have not been implemented */ typedef struct { /* GAB 11/Jan/2001 */ OPDS h; MYFLT *trigger; MYFLT *args[PMAX+1]; MYFLT args2[PMAX+1]; MYFLT *argums[PMAX+1]; int nargs, done, doneRel; char *relesing; MYFLT frac; } SCHEDINTIME; static int schedInTime_set(CSOUND *csound, SCHEDINTIME *p) { int *xtra; int j; OPARMS *O = csound->oparms; /* hugly hack, needs to be inserted in the CSOUND structure */ static MYFLT frac = 0; O->RTevents = 1; /* Make sure kperf() looks for RT events */ /* O.ksensing = 1; */ /* O.OrcEvts = 1; \/\* - of the appropriate type */ p->frac = frac; p->nargs = p->INOCOUNT; /* num of arguments */ for( j = 1; j < p->nargs; j++) { p->args2[j] = *p->args[j-1]; p->argums[j]= &p->args2[j]; } p->args2[0]=0; p->argums[0]=&p->args2[0]; if (CS_KCNT > 0 && *p->trigger != 0 && p->h.insdshead->p3 == 0) { if (*p->argums[3] >= 0) *p->argums[3] = -1; /* start a held note */ *p->argums[1] += p->frac; Sched(csound, p->argums, p->nargs); p->done = 1; /* only once */ } else p->done = 0; p->doneRel = 0; xtra = &(p->h.insdshead->xtratim); if (*xtra < 1) *xtra = 1; p->relesing = &(p->h.insdshead->relesing); frac += INCR; frac = (frac >= 1) ? frac = 0 : frac; return OK; } static int schedInTime(CSOUND *csound, SCHEDINTIME *p) { if (*p->trigger && !p->done) {/* Only do something if triggered */ if (*p->argums[3] >= 0) *p->argums[3] = -1; /* start a held note */ *p->argums[1] += p->frac; Sched(csound, p->argums, p->nargs); p->done = 1; /* only once */ } if (*p->relesing && !p->doneRel) { *p->argums[1] = -*p->argums[1]; /* turn off the note with a negative p1 */ Sched(csound, p->argums, p->nargs); p->doneRel = 1; /* only once */ } return OK; } /* -------------------------------------------------------------------- */ /* These opocdes were not implemented because the functionality of */ /* CopyTabElements has already been included in vcopy and vcopy_i */ typedef struct { /* GAB 11/Jan/2001 */ OPDS h; MYFLT *ktrigger, *idestTab, *kdestIndex, *isourceTab, *ksourceIndex, *inumElems; MYFLT *dTable, *sTable; long sLen, dLen; } COPYTABELEMS; static int copyTabElems_set(CSOUND *csound, COPYTABELEMS *p) { FUNC *ftp; int nelems = (int) *p->inumElems; if ((ftp = csound->FTnp2Find(csound, p->idestTab)) == NULL) return csound->InitError(csound, Str("copyTabElems: incorrect destination " "table number")); p->dLen = ftp->flen; if (nelems > p->dLen) return csound->InitError(csound, Str("copyTabElems: destination table too short " "or number of elements to copy too big")); p->dTable = ftp->ftable; if ((ftp = csound->FTnp2Find(csound, p->isourceTab)) == NULL) return csound->InitError(csound, Str("copyTabElems: incorrect source table number")); p->sLen = ftp->flen; if (nelems > p->sLen) return csound->InitError(csound, Str("copyTabElems: source table size less than " "the number of elements to copy")); p->sTable = ftp->ftable; return OK; } static int copyTabElems(CSOUND *csound, COPYTABELEMS *p) { if(*p->ktrigger) { int nelems = (int) *p->inumElems; int j, sNdx = (int) *p->ksourceIndex * nelems, dNdx = (int) *p->kdestIndex * nelems; if (sNdx + nelems > p->sLen) return csound->PerfError(csound, p->h.insdshead, Str("copyTabElems: source table too short")); if (dNdx + nelems > p->dLen) return csound->PerfError(csound, p->h.insdshead, Str("copyTabElems: destination table too short")); for (j = 0; j< nelems; j++) p->dTable[dNdx+j] = p->sTable[sNdx+j]; } return OK; } typedef struct { /* GAB 11/Jan/2001 */ OPDS h; MYFLT *idestTab, *idestIndex, *isourceTab, *isourceIndex, *inumElems; } COPYTABELEMS_I; static int copyTabElemsi(CSOUND *csound, COPYTABELEMS_I *p) { FUNC *ftp; int nelems = (int) *p->inumElems, dLen, sLen; MYFLT *sTable, *dTable; if ((ftp = csound->FTnp2Find(csound, p->idestTab)) == NULL) return csound->InitError(csound, Str("copyTabElems: incorrect destination " "table number")); dLen = ftp->flen; if (nelems > dLen) return csound->InitError(csound, Str("copyTabElems: destination table too short " "or number of elements to copy too big")); dTable = ftp->ftable; if ((ftp = csound->FTnp2Find(csound, p->isourceTab)) == NULL) return csound->InitError(csound, Str("copyTabElems: incorrect source table number")); sLen = ftp->flen; if (nelems > sLen) return csound->InitError(csound, Str("copyTabElems: source table size less than " "the number of elements to copy")); sTable = ftp->ftable; { int j, sNdx = (int) *p->isourceIndex * nelems, dNdx = (int) *p->idestIndex * nelems; if (sNdx + nelems > sLen) return csound->PerfError(csound, p->h.insdshead, Str("copyTabElems: source table too short")); if (dNdx + nelems > dLen) return csound->PerfError(csound, p->h.insdshead, Str("copyTabElems: destination table too short")); for (j = 0; j< nelems; j++) { dTable[dNdx+j] = sTable[sNdx+j]; } } return OK; } #endif /* -------------------------------------------------------------------- */ typedef struct { OPDS h; MYFLT *kstartChan, *argums[VARGMAX]; int numChans, narg; } INRANGE; /* extern MYFLT *spin, *spout; */ /* extern int spoutactive, PortaudioNumOfInPorts; gab default, = nchnls */ static int inRange_i(CSOUND *csound, INRANGE *p) { p->narg = p->INOCOUNT-1; /*p->numChans = (PortaudioNumOfInPorts == -1) ? nchnls : PortaudioNumOfInPorts; */ if (UNLIKELY(!csound->oparms->sfread)) return csound->InitError(csound, Str("inrg: audio input is not enabled")); p->numChans = csound->GetNchnls(csound); return OK; } static int inRange(CSOUND *csound, INRANGE *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t j, nsmps = CS_KSMPS; int i; MYFLT *ara[VARGMAX]; int startChan = (int) *p->kstartChan -1; MYFLT *sp = csound->spin + startChan; int narg = p->narg, numchans = p->numChans; if (UNLIKELY(startChan < 0)) return csound->PerfError(csound, p->h.insdshead, Str("inrg: channel number cannot be < 1 " "(1 is the first channel)")); if (UNLIKELY(early)) nsmps -= early; for (i = 0; i < narg; i++) { ara[i] = p->argums[i]; if (UNLIKELY(offset)) memset(ara[i], '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) memset(&ara[i][nsmps], '\0', early*sizeof(MYFLT)); ara[i] += offset; } for (j=offset; jFTnp2Find(csound, p->ift)) == NULL) return csound->InitError(csound, Str("invalid function")); if (UNLIKELY(!(p->fsr=ftp->gen01args.sample_rate))){ csound->Message(csound, Str("lposc: no sample rate stored in function;" " assuming=sr\n")); p->fsr=CS_ESR; } p->ftp = ftp; p->tablen = ftp->flen; /* changed from p->phs = *p->iphs * p->tablen; */ if ((loop = *p->kloop) < 0) loop=FL(0.0); if ((end = *p->kend) > p->tablen || end <=0 ) end = (MYFLT)p->tablen; looplength = end - loop; if (*p->iphs >= 0) p->phs = *p->iphs; while (p->phs >= end) p->phs -= looplength; return OK; } static int lposca(CSOUND *csound, LPOSC *p) { double *phs= &p->phs; double si= *p->freq * (p->fsr/CS_ESR); MYFLT *out = p->out, *amp=p->amp; MYFLT *ft = p->ftp->ftable, *curr_samp; MYFLT fract; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 loop, end, looplength /* = p->looplength */ ; if ((loop = (long) *p->kloop) < 0) loop=0;/* gab */ else if (loop > p->tablen-3) loop = p->tablen-3; if ((end = (long) *p->kend) > p->tablen-1 ) end = p->tablen - 1; else if (end <= 2) end = 2; if (end < loop+2) end = loop + 2; looplength = end - loop; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; n= end) *phs -= looplength; while (*phs < loop) *phs += looplength; } return OK; } /* -------------------------------------------------------------------- */ typedef struct { OPDS h; MYFLT *out1, *out2, *amp, *freq, *kloop, *kend, *ift, *iphs; long tablen; MYFLT fsr; MYFLT *ft; /*table */ double phs, fsrUPsr /* , looplength */; long phs_int; } LPOSC_ST; static int lposc_stereo_set(CSOUND *csound, LPOSC_ST *p) { FUNC *ftp; double loop, end, looplength, fsr; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->ift)) == NULL)) return csound->InitError(csound, Str("invalid function")); if (UNLIKELY(!(fsr = ftp->gen01args.sample_rate))) { csound->Message(csound, Str("lposcil: no sample rate stored in function;" " assuming=sr\n")); p->fsr=CS_ESR; } p->fsrUPsr = fsr/CS_ESR; p->ft = ftp->ftable; p->tablen = ftp->flen/2; /* changed from p->phs = *p->iphs * p->tablen; */ if ((loop = *p->kloop) < 0) loop=0;/* gab */ else if (loop > p->tablen-3) loop = p->tablen-3; if ((end = *p->kend) > p->tablen-1 ) end = p->tablen - 1; else if (end <= 2) end = 2; if (end < loop+2) end = loop + 2; looplength = end - loop; if (*p->iphs >= 0) p->phs_int = (long) (p->phs = *p->iphs); while (p->phs >= end) p->phs_int = (long) (p->phs -= looplength); return OK; } static int lposca_stereo(CSOUND *csound, LPOSC_ST *p) /* stereo lposcinta */ { double *phs= &p->phs, si= *p->freq * p->fsrUPsr; MYFLT *out1 = p->out1, *out2 = p->out2, *amp=p->amp; MYFLT *ft = p->ft; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 loop, end, looplength /* = p->looplength */ ; if ((loop = (long) *p->kloop) < 0) loop=0;/* gab */ else if (loop > p->tablen-3) loop = p->tablen-3; if ((end = (long) *p->kend) > p->tablen-1 ) end = p->tablen - 1; else if (end <= 2) end = 2; if (end < loop+2) end = loop + 2; looplength = end - loop; if (UNLIKELY(offset)) { memset(out1, '\0', offset*sizeof(MYFLT)); memset(out2, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&out1[nsmps], '\0', early*sizeof(MYFLT)); memset(&out2[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; n= end) *phs -= looplength; while (*phs < loop) *phs += looplength; } return OK; } static int lposca_stereo_no_trasp(CSOUND *csound, LPOSC_ST *p) { /* transposition is allowed only */ /*in integer values (twice, three times etc.) so it is faster */ long *phs = &p->phs_int, si = (long) *p->freq; MYFLT *out1 = p->out1, *out2 = p->out2, *amp=p->amp; MYFLT *ft = p->ft; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; long loop, end, looplength /* = p->looplength */ ; if ((loop = (long) *p->kloop) < 0) loop=0;/* gab */ else if (loop > p->tablen-3) loop = p->tablen-3; if ((end = (long) *p->kend) > p->tablen-1 ) end = p->tablen - 1; else if (end <= 2) end = 2; if (end < loop+2) end = loop + 2; looplength = end - loop; if (UNLIKELY(offset)) { memset(out1, '\0', offset*sizeof(MYFLT)); memset(out2, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&out1[nsmps], '\0', early*sizeof(MYFLT)); memset(&out2[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; n= end) *phs -= looplength; while (*phs < loop) *phs += looplength; } return OK; } /* -------------------------------------------------------------------- */ #include "vectorial.h" typedef struct { /* gab d5*/ OPDS h; MYFLT *out, *ktrig, *min, *max; MYFLT lastvalue; } TRANGERAND; static int trRangeRand(CSOUND *csound, TRANGERAND *p) { /* gab d5*/ if (*p->ktrig) *p->out = p->lastvalue = randGab * (*p->max - *p->min) + *p->min; else *p->out = p->lastvalue; return OK; } /* -------------------------------------------------------------------- */ /* Note: this opcode has been left out because it is undocumented */ #if 0 typedef struct { OPDS h; MYFLT *rcar, *rmod; MYFLT *kfreq_max, *kfreq_min, *kband_max, *kband_min; } DSH; static int dashow (CSOUND *csound, DSH *p) { MYFLT range = *p->kband_max - *p->kband_min; if (range != FL(0.0)) *p->rmod = (*p->kfreq_max - *p->kfreq_min) / (*p->kband_max - *p->kband_min); else *p->rmod = FL(0.0); *p->rcar = (*p->kfreq_max - (*p->kband_max * *p->rmod)); if (*p->rmod <= FL(0.0)) *p->rmod = FABS (*p->rmod); if (*p->rcar <= FL(0.0)) *p->rcar = FABS (*p->rcar); return OK; } #endif /* -------------------------------------------------------------------- */ #define S(x) sizeof(x) static OENTRY localops[] = { { "vtable1k", S(MTABLE1), TR, 3, "", "kz", (SUBR)mtable1_set, (SUBR)mtable1_k, (SUBR) NULL }, /* { "schedk", S(SCHEDK), 0, 3, "", "kkz", (SUBR)schedk_i, (SUBR) schedk, (SUBR) NULL }, */ /* { "schedInTime", S(SCHEDINTIME), 0, 3, "", "kz", (SUBR)schedInTime_set, (SUBR)schedInTime , (SUBR) NULL }, */ /* { "copyTabElems", S(COPYTABELEMS),0, 3, "", "kikiki", (SUBR)copyTabElems_set, (SUBR)copyTabElems, (SUBR)NULL }, */ /* { "copyTabElemsi", S(COPYTABELEMS_I), 0, 1, "", "iiiii", (SUBR)copyTabElemsi, (SUBR)NULL, (SUBR)NULL }, */ /* { "Trandom", S(TRANGERAND), 0, 2, "k", "kkk", NULL, (SUBR)trRangeRand }, */ { "trandom", S(TRANGERAND), 0, 2, "k", "kkk", NULL, (SUBR)trRangeRand }, /* { "lposcinta", S(LPOSC), 0, 5, "a", "akkkio", (SUBR)lposc_set, NULL, (SUBR)lposcinta}, */ /* { "lposcintsa", S(LPOSCINT_ST), 0, 5, "aa","akkkio", (SUBR)lposcint_stereo_set,NULL, (SUBR)lposcinta_stereo}, */ /* { "lposcintsa2", S(LPOSCINT_ST), 0, 5, "aa","akkkio", (SUBR)lposcint_stereo_set,NULL, (SUBR)lposcinta_stereo_no_trasp}, */ { "lposcila", S(LPOSC), TR, 5, "a", "akkkio", (SUBR)lposc_set, NULL, (SUBR)lposca}, { "lposcilsa", S(LPOSC_ST), TR, 5, "aa","akkkio", (SUBR)lposc_stereo_set, NULL, (SUBR)lposca_stereo}, { "lposcilsa2", S(LPOSC_ST), TR, 5, "aa","akkkio", (SUBR)lposc_stereo_set, NULL, (SUBR)lposca_stereo_no_trasp}, /* { "dashow.i", S(DSH), 0,1, "ii","iiii", (SUBR)dashow }, */ /* { "dashow.k", S(DSH), 0,2, "kk","kkkk", NULL, (SUBR)dashow }, */ { "inrg", S(INRANGE), 0,5, "", "ky", (SUBR)inRange_i, (SUBR)NULL, (SUBR)inRange } }; int newgabopc_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } int hvs_init_(CSOUND *csound); int slidertable_init_(CSOUND *csound); int tabmorph_init_(CSOUND *csound); int rbatonopc_init_(CSOUND *csound); int newgabopc_ModuleInit(CSOUND *csound) { int err = 0; err |= hvs_init_(csound); err |= newgabopc_init_(csound); err |= slidertable_init_(csound); err |= tabmorph_init_(csound); /* err |= rbatonopc_init_(csound); */ return (err ? CSOUND_ERROR : CSOUND_SUCCESS); } /* PUBLIC int csoundModuleDestroy(CSOUND *csound) { return 0; } */ csound-6.10.0/Opcodes/gab/opcodes.txt000066400000000000000000000110751321653344700174270ustar00rootroot00000000000000 Opcode Name csound5 CsoundAV ------------------------------------------------------------ adsynt2 gab.c newopcodes.c bminfo bmopen bmoscil bmoscili bmscan bmscani bmtable bmtablei call calld callm callmd changed gab.c newopcodes.c dashow exitnow gab.c newopcodes.c fof3 foscili2 ftlen2 img2GLtex imgConvolve imgCreate imgGain imgPoint k gab.c newopcodes.c loscil2 lposc lposcila lposcilsa lposcilsa2 lposcint lposcinta lposcintsa lposcintsa2 lpres lpresx mandel gab.c newopcodes.c max gab.c newopcodes.c metro metro.c newopcodes.c nlalp gab.c newopcodes.c oscfeed parmca parmck parmta parmtk physic1 physic2 posc rbatonPercPad rbatonPot rbatonXYZ resonxk gab.c newopcodes.c rgb2hsvl rtrnca rtrnck rtrnta rtrntk schedk seqtime2 set sliderKawai spec2tab specinfo splitrig metro.c newopcodes.c system tab gab.c newopcodes.c tabk2t tabplay gab.c newopcodes.c tabrec gab.c newopcodes.c tabw gab.c newopcodes.c tb0 gab.c newopcodes.c tb1 gab.c newopcodes.c tb10 gab.c newopcodes.c tb11 gab.c newopcodes.c tb12 gab.c newopcodes.c tb13 gab.c newopcodes.c tb14 gab.c newopcodes.c tb15 gab.c newopcodes.c tb2 gab.c newopcodes.c tb3 gab.c newopcodes.c tb4 gab.c newopcodes.c tb5 gab.c newopcodes.c tb6 gab.c newopcodes.c tb7 gab.c newopcodes.c tb8 gab.c newopcodes.c tb9 gab.c newopcodes.c timedseq metro.c newopcodes.c turnoffk vadd vectorial.c vectorial.c vaddv vectorial.c vectorial.c vcella vectorial.c vectorial.c vcopy vectorial.c vectorial.c vdelayk vectorial.c vectorial.c vdivv vectorial.c vectorial.c vecdelay vectorial.c vectorial.c vexp vectorial.c vectorial.c vexpseg vectorial.c vectorial.c vexpv vectorial.c vectorial.c vlimit vectorial.c vectorial.c vlinseg vectorial.c vectorial.c vlpres vmap vectorial.c vectorial.c vmirror vectorial.c vectorial.c vmult vectorial.c vectorial.c vmultv vectorial.c vectorial.c vphaseseg vport vectorial.c vectorial.c vpow vectorial.c vectorial.c vpowv vectorial.c vectorial.c vrandh vectorial.c vectorial.c vrandi vectorial.c vectorial.c vsubv vectorial.c vectorial.c vtaba vectorial.c newopcodes.c vtabi vectorial.c newopcodes.c vtabk vectorial.c newopcodes.c vtablea vectorial.c newopcodes.c vtablei vectorial.c newopcodes.c vtablek vectorial.c newopcodes.c vtablewa vectorial.c newopcodes.c vtablewi vectorial.c newopcodes.c vtablewk vectorial.c newopcodes.c vtabwa vectorial.c newopcodes.c vtabwi vectorial.c newopcodes.c vtabwk vectorial.c newopcodes.c vwrap vectorial.c vectorial.c xxx zr gab.c newopcodes.c csound-6.10.0/Opcodes/gab/sliderTable.c000066400000000000000000000747101321653344700176350ustar00rootroot00000000000000/* Copyright (C) 2007 Gabriel Maldonado Csound is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ //#include "csdl.h" #include "csoundCore.h" #include "interlocks.h" #include #define f7bit (FL(127.0)) #define oneTOf7bit (MYFLT)(1.0/127.0) #define f14bit (FL(16383.0)) #define oneTOf14bit (MYFLT)(1.0/16383.0) #define f21bit (FL(2097151.0)) #define oneTOf21bit (MYFLT)(1.0/2097151.0) typedef struct { MYFLT *ictlno, *imin, *imax, *initvalue, *ifn; } SLD; typedef struct { MYFLT *ictlno, *imin, *imax, *initvalue, *ifn, *ihp; } SLDf; /*--------------------------------------------------------*/ #define SLIDER_I_TABLE_INIT(p, n) \ { \ unsigned char chan = p->slchan = (unsigned char)((*p->ichan)-1); \ char sbuf[120]; \ if (UNLIKELY(chan > 15)) { \ return csound->InitError(csound, Str("illegal channel")); \ } \ else { \ MYFLT value; \ int j = 0; \ SLD *sld = p->s; \ unsigned char *slnum = p->slnum; \ MYFLT *min = p->min, *max= p->max; \ FUNC *outftp, **ftp = p->ftp; \ MYFLT *chanblock = (MYFLT *) csound->m_chnbp[chan]->ctl_val; \ \ if ((outftp = csound->FTnp2Find(csound, p->ioutfn)) != NULL) \ p->outTable = outftp->ftable; \ while (j < 8) { \ int t = (int) *sld->ifn; \ *slnum = (unsigned char) *sld->ictlno; \ value=*sld->initvalue; \ \ if (UNLIKELY(*slnum > 127)) { \ snprintf(sbuf, 120, \ Str("illegal control number at position n.%d"), \ j); \ return csound->InitError(csound, "%s", sbuf); \ break; \ } \ *min=*sld->imin; \ *max=*sld->imax; \ if (t !=0 && t != -1) { /*table indexing */ \ if (UNLIKELY(value >= 1 || value < 0)) { \ snprintf(sbuf, 120, \ Str("sliderXtable: illegal initvalue at " \ "position %d. When using table " \ "indexing, the init range is 0 to 1"),\ j); \ return csound->InitError(csound, "%s", sbuf); \ break; \ } \ } \ else if (UNLIKELY(value < *min || value > *max )) { \ snprintf(sbuf, 120, \ Str("illegal initvalue at position n.%d"), j); \ return csound->InitError(csound, "%s", sbuf); \ break; \ } \ \ switch (t) { \ case 0: /* LINEAR */ \ value = (*sld->initvalue - *min) / (*max - *min); \ break; \ case -1: /* EXPONENTIAL */ \ if (UNLIKELY(*min == 0 || *max == 0)) { \ return csound->InitError(csound, \ Str("sliderXtable: zero is " \ "illegal in exponential " \ "operations")); \ } \ { \ MYFLT range = *max-*min; \ MYFLT base; \ base= (MYFLT) pow(*max / *min, 1/range); \ value = (MYFLT) (log(value/ *min) / log(base)) ; \ value /= range; \ } \ break; \ default: /* TABLE */ \ value = value; /* unchanged, value must be in the 0 to 1 range, */ \ /* representing the phase of the table */ \ if (*sld->ifn > 0) *ftp = csound->FTnp2Find(csound, sld->ifn); \ } \ chanblock[*slnum++] = (MYFLT)((int)(value * f7bit + FL(0.5))); \ min++; max++; ftp++; j++; sld++; \ } \ } \ } \ return OK; #define SLIDER_TABLE_INIT(p, n) \ { \ int j = 0; \ FUNC **ftp = p->ftp; \ MYFLT *chanblock = (MYFLT *) csound->m_chnbp[p->slchan]->ctl_val; \ unsigned char *slnum = p->slnum; \ MYFLT *min = p->min, *max = p->max; \ MYFLT *outTable = p->outTable + (int) *p->ioffset; \ *p->ktrig = 0; \ while (j < n) { \ int t = (int) *(p->s[j].ifn); \ int val = (int) chanblock[*slnum++]; \ MYFLT value = (MYFLT) val / f7bit; \ if (val != p->oldvalue[j] ) { \ MYFLT base, range = *max - *min; \ *p->ktrig = 1; \ p->oldvalue[j] = val; \ switch (t) { \ case -1: /* EXPONENTIAL */ \ base = (MYFLT) pow((*max / *min), 1/range); \ value = *min * (MYFLT) pow(base, value * range); \ break; \ case 0: /* LINEAR */ \ value = value * range + *min; \ break; \ default: /* TABLE */ \ value = *((*ftp)->ftable + (long)(value * (*ftp)->flen)); \ value = value * range + *min; /* scales the output */ \ break; \ } \ *outTable = value; \ } \ min++; max++; j++; ftp++; outTable++; \ } \ } \ return OK; /*--------------------------------------------------------*/ typedef struct { OPDS h; MYFLT *ktrig; /* output */ MYFLT *ichan, *ioutfn, *ioffset; /* input */ SLD s[8]; MYFLT min[8], max[8], *outTable; unsigned char slchan, slnum[8], oldvalue[8]; FUNC *ftp[8]; } SLIDER8t; /* GAB */ static int sliderTable_i8(CSOUND *csound, SLIDER8t *p) /* GAB */ { SLIDER_I_TABLE_INIT(p,8); } static int sliderTable8(CSOUND *csound, SLIDER8t *p) /* GAB */ { SLIDER_TABLE_INIT(p,8); } /*--------------------------------------------------------*/ typedef struct { OPDS h; MYFLT *ktrig; /* output */ MYFLT *ichan, *ioutfn, *ioffset; /* input */ SLD s[16]; MYFLT min[16], max[16], *outTable; unsigned char slchan, slnum[16], oldvalue[16]; FUNC *ftp[16]; } SLIDER16t; /* GAB */ static int sliderTable_i16(CSOUND *csound, SLIDER16t *p) /* GAB */ { SLIDER_I_TABLE_INIT(p,16); } static int sliderTable16(CSOUND *csound, SLIDER16t *p) /* GAB */ { SLIDER_TABLE_INIT(p,16); } /*--------------------------------------------------------*/ typedef struct { OPDS h; MYFLT *ktrig; /* output */ MYFLT *ichan, *ioutfn, *ioffset; /* input */ SLD s[32]; MYFLT min[32], max[32], *outTable; unsigned char slchan, slnum[32], oldvalue[32]; FUNC *ftp[32]; } SLIDER32t; /* GAB */ static int sliderTable_i32(CSOUND *csound, SLIDER32t *p) /* GAB */ { SLIDER_I_TABLE_INIT(p,32); } static int sliderTable32(CSOUND *csound, SLIDER32t *p) /* GAB */ { SLIDER_TABLE_INIT(p,32); } /*--------------------------------------------------------*/ typedef struct { OPDS h; MYFLT *ktrig; /* output */ MYFLT *ichan, *ioutfn, *ioffset; /* input */ SLD s[64]; MYFLT min[64], max[64], *outTable; unsigned char slchan, slnum[64], oldvalue[64]; FUNC *ftp[64]; } SLIDER64t; /* GAB */ static int sliderTable_i64(CSOUND *csound, SLIDER64t *p) /* GAB */ { SLIDER_I_TABLE_INIT(p,64); } static int sliderTable64(CSOUND *csound, SLIDER64t *p) /* GAB */ { SLIDER_TABLE_INIT(p,64); } /*--------------------------------------------------------*/ #define SLIDER_I_TABLEF_INIT(p,n) \ { \ unsigned char chan = p->slchan = (unsigned char)((*p->ichan)-1); \ char sbuf[120]; \ if (UNLIKELY(chan > 15)) { \ return csound->InitError(csound, Str("illegal channel")); \ } \ { \ MYFLT value; \ int j = 0; \ SLDf *sld = p->s; \ unsigned char *slnum = p->slnum; \ MYFLT *min = p->min, *max= p->max; \ FUNC *outftp, **ftp = p->ftp; \ MYFLT *chanblock = (MYFLT *) csound->m_chnbp[chan]->ctl_val; \ \ MYFLT b; \ MYFLT *yt1 = p->yt1, *c1=p->c1, *c2=p->c2; \ \ \ if((outftp = csound->FTnp2Find(csound, p->ioutfn)) != NULL) \ p->outTable = outftp->ftable; \ while (j < n) { \ int t = (int) *sld->ifn; \ *slnum = (unsigned char) *sld->ictlno; \ value=*sld->initvalue; \ \ if (UNLIKELY(*slnum > 127)) { \ snprintf(sbuf, 120, \ Str("illegal control number at position n.%d"), j); \ return csound->InitError(csound, "%s", sbuf); \ break; \ } \ if (UNLIKELY(value < (*min=*sld->imin) || \ value > (*max=*sld->imax) )) { \ snprintf(sbuf, 120, \ Str("illegal initvalue at position n.%d"), j); \ return csound->InitError(csound, "%s", sbuf); \ break; \ } \ \ switch (t) { \ case 0: /* LINEAR */ \ value = (*sld->initvalue - *min) / (*max - *min); \ break; \ case -1: /* EXPONENTIAL */ \ if (*min == 0 || *max == 0) { \ return csound->InitError(csound, \ Str("sliderXtable: zero is illegal"\ " in exponential operations"));\ } \ { \ MYFLT range = *max-*min; \ MYFLT base; \ base= (MYFLT) pow(*max / *min, 1/range); \ value = (MYFLT) (log(value/ *min) / log(base)) ; \ value /= range; \ } \ break; \ default: /* TABLE */ \ value = value; /* unchanged, value must be in the 0 to 1 range, */ \ /* representing the phase of the table */ \ if (*sld->ifn > 0) *ftp = csound->FTnp2Find(csound, sld->ifn); \ if (UNLIKELY(value >= 1 || value < 0)) { \ snprintf(sbuf, 120, \ Str("sliderXtable: illegal initvalue at " \ "position %d. When using table indexing," \ " the init range is 0 to 1"), j); \ return csound->InitError(csound, "%s", sbuf); \ } \ } \ chanblock[*slnum++] = (MYFLT)((int)(value * f7bit + FL(0.5))); \ /*----- init filtering coeffs*/ \ *yt1++ = FL(0.0); \ b = (MYFLT)(2.0 - cos((double)(*(sld)->ihp * \ csound->tpidsr * CS_KSMPS))); \ *c2 = (MYFLT)(b - sqrt((double)(b * b - FL(1.0)))); \ *c1++ = FL(1.0) - *c2++; \ \ min++; max++; ftp++; j++; sld++; \ } \ } \ } \ return OK; #define SLIDER_TABLEF_INIT(p,n) \ { \ MYFLT value, base; \ int j = 0; \ FUNC **ftp = p->ftp; \ MYFLT *chanblock = (MYFLT *) csound->m_chnbp[p->slchan]->ctl_val; \ unsigned char *slnum = p->slnum; \ MYFLT *min = p->min, *max = p->max; \ MYFLT *outTable = p->outTable + (int) *p->ioffset; \ MYFLT *yt1 = p->yt1, *c1=p->c1, *c2=p->c2; \ \ while (j < n) { \ int t = (int) *(p->s[j].ifn); \ MYFLT range; \ int val = (int) chanblock[*slnum++]; \ value = (MYFLT) val / f7bit; \ if (val != p->oldvalue[j] ) { \ *p->ktrig = 1; \ p->oldvalue[j] = val; \ } \ switch (t) { \ case -1: /* EXPONENTIAL */ \ range = *max - *min; \ base = (MYFLT) pow((*max / *min), 1/range); \ value = *min * (MYFLT) pow(base, value * range); \ break; \ case 0: /* LINEAR */ \ value = value * (*max++ - *min) + *min; \ break; \ default: /* TABLE */ \ value = *((*ftp)->ftable + (long)(value * (*ftp)->flen)); \ value = value * (*max - *min) + *min; /* scales the output */ \ break; \ } \ *outTable++ = \ *yt1 = *c1++ * value + *c2++ * *yt1; /* filters the output */ \ yt1++; min++; max++; j++; ftp++; \ } \ } \ return OK; /*--------------------------------------------------------*/ typedef struct { OPDS h; MYFLT *ktrig; /* output */ MYFLT *ichan, *ioutfn, *ioffset; /* input */ SLDf s[8]; MYFLT min[8], max[8], *outTable; unsigned char slchan, slnum[8], oldvalue[8]; FUNC *ftp[8]; MYFLT c1[8], c2[8]; MYFLT yt1[8]; } SLIDER8tf; static int sliderTable_i8f(CSOUND *csound, SLIDER8tf *p) { SLIDER_I_TABLEF_INIT(p,8) } static int sliderTable8f(CSOUND *csound, SLIDER8tf *p) { SLIDER_TABLEF_INIT(p,8) } /*--------------------------------------------------------*/ typedef struct { OPDS h; MYFLT *ktrig; /* output */ MYFLT *ichan, *ioutfn, *ioffset; /* input */ SLDf s[16]; MYFLT min[16], max[16], *outTable; unsigned char slchan, slnum[16], oldvalue[16]; FUNC *ftp[16]; MYFLT c1[16], c2[16]; MYFLT yt1[6]; } SLIDER16tf; static int sliderTable_i16f(CSOUND *csound, SLIDER16tf *p) { SLIDER_I_TABLEF_INIT(p,16) } static int sliderTable16f(CSOUND *csound, SLIDER16tf *p) { SLIDER_TABLEF_INIT(p,16) } /*--------------------------------------------------------*/ typedef struct { OPDS h; MYFLT *ktrig; /* output */ MYFLT *ichan, *ioutfn, *ioffset; /* input */ SLDf s[32]; MYFLT min[32], max[32], *outTable; unsigned char slchan, slnum[32], oldvalue[32]; FUNC *ftp[32]; MYFLT c1[32], c2[32]; MYFLT yt1[32]; } SLIDER32tf; static int sliderTable_i32f(CSOUND *csound, SLIDER32tf *p) { SLIDER_I_TABLEF_INIT(p,32) } static int sliderTable32f(CSOUND *csound, SLIDER32tf *p) { SLIDER_TABLEF_INIT(p,32) } /*--------------------------------------------------------*/ typedef struct { OPDS h; MYFLT *ktrig; /* output */ MYFLT *ichan, *ioutfn, *ioffset; /* input */ SLDf s[64]; MYFLT min[64], max[64], *outTable; unsigned char slchan, slnum[64], oldvalue[64]; FUNC *ftp[64]; MYFLT c1[6], c2[64]; MYFLT yt1[64]; } SLIDER64tf; static int sliderTable_i64f(CSOUND *csound, SLIDER64tf *p) { SLIDER_I_TABLEF_INIT(p,64) } static int sliderTable64f(CSOUND *csound, SLIDER64tf *p) { SLIDER_TABLEF_INIT(p,64) } /*--------------------------------------------------------*/ /* An opcode to expand the versatility of the KAWAI MM-16 midi mixer. This device doesn't allow to program the midi message associated to each slider. In fact it is only able to output the control 7 for each midi channel. With this opcode it is possible to assign each slider to the 16 output values. Syntax: k1,k2,....k16 sliderKawai \ imin1, imax1, initvalue1, ifn1, imin2, imax2, initvalue2, ifn2, .............................. imin16, imax16, initvalue16, ifn16, */ typedef struct { MYFLT *imin, *imax, *initvalue, *ifn; } SLD2; typedef struct { OPDS h; MYFLT *r[16]; /* output */ SLD2 s[16]; MYFLT min[16], max[16]; FUNC *ftp[16]; } SLIDERKAWAI; static int sliderKawai_i(CSOUND *csound, SLIDERKAWAI *p) { char sbuf[120]; int n = 16; MYFLT value; int j = 0; SLD2 *sld = p->s; MYFLT *min = p->min, *max= p->max; FUNC **ftp = p->ftp; do { if (UNLIKELY((value=*sld->initvalue) < (*min=*sld->imin) || value > (*max=*sld->imax) )) { snprintf(sbuf, 120, Str("illegal initvalue at position n.%d"), j); return csound->InitError(csound, "%s", sbuf); } if (*sld->ifn > 0) *ftp++ = csound->FTnp2Find(csound, sld->ifn); else *ftp++ = NULL; value = (*(sld++)->initvalue - *min) / (*max++ - *min); min++; csound->m_chnbp[j]->ctl_val[7] = (MYFLT)((int)(value * f7bit + FL(0.5))); } while (++j < n); return OK; } static int sliderKawai(CSOUND *csound, SLIDERKAWAI *p) { MYFLT value; int j = 0, n=16; FUNC **ftp = p->ftp-1; MYFLT *min = p->min, *max = p->max; MYFLT **result = p->r; do { value = (MYFLT) csound->m_chnbp[j]->ctl_val[7] * oneTOf7bit; if (*(++ftp)) /* if valid ftable,use value as index */ /* no interpolation */ value = *((*ftp)->ftable + (long)(value * (*ftp)->flen)); **result++ = value * (*max++ - *min) + *min; /* scales the output */ min++;; } while (++j < n); return OK; } /*--------------------------------------------------------*/ #define TOOSMALL 0.0000000000000000000000001f /* to avoid denormalization bug */ typedef struct { OPDS h; MYFLT *r, *ichan, *ictlno, *imin, *imax, *ifn, *icutoff; short flag; FUNC *ftp; long ctlno; MYFLT c1; /* Value to multiply with input value */ MYFLT c2; /* Value to multiply with previous state */ MYFLT yt1; /* Previous state */ MYFLT prev; } CTRL7a; static int ctrl7a_set(CSOUND *csound, CTRL7a *p) { int ctlno, chan; MYFLT cutoff, b; if ((ctlno = (int) *p->ictlno) < 0 || ctlno > 127) return csound->InitError(csound, Str("illegal controller number")); else if ((chan=(int) *p->ichan-1) < 0 || chan > 15) return csound->InitError(csound, Str("illegal midi channel")); else p->ctlno = ctlno; if (*p->ifn > 0) { if (UNLIKELY(((p->ftp = csound->FTnp2Find(csound, p->ifn)) == NULL))) p->flag = 0; /* invalid ftable */ else p->flag= 1; } else p->flag= 0; p->yt1 = FL(0.0); if (*p->icutoff <= 0) cutoff = 5; else cutoff = *p->icutoff; b = FL(2.0) - COS(cutoff * csound->tpidsr * CS_KSMPS); p->c2 = b - SQRT(b * b - 1.0); p->c1 = FL(1.0) - p->c2; p->prev = 0; return OK; } static int ctrl7a(CSOUND *csound, CTRL7a *p) { MYFLT *ar, val, incr; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT value = (MYFLT) (csound->m_chnbp[(int) *p->ichan-1]->ctl_val[p->ctlno] * oneTOf7bit); if (p->flag) { /* if valid ftable,use value as index */ /* no interpolation */ value = *(p->ftp->ftable + (long)(value*(p->ftp->flen-1))); } /* scales the output */ value = value * (*p->imax - *p->imin) + *p->imin + TOOSMALL; value = p->yt1 = p->c1 * value + p->c2 * p->yt1; ar = p->r; val = p->prev; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } incr = (value - val) / (MYFLT)(nsmps-offset); for (n=offset; nprev = val; return OK; } #define S(x) sizeof(x) OENTRY sliderTable_localops[] = { { "slider8table", S(SLIDER8t), 0, 3, "k", "iii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii", (SUBR)sliderTable_i8, (SUBR)sliderTable8, (SUBR)NULL }, { "slider16table", S(SLIDER8t), 0, 3, "k", "iii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii", (SUBR)sliderTable_i16, (SUBR)sliderTable16, (SUBR)NULL }, { "slider32table", S(SLIDER8t), 0, 3, "k", "iii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii", (SUBR)sliderTable_i32, (SUBR)sliderTable32, (SUBR)NULL }, { "slider64table", S(SLIDER8t), 0, 3, "k", "iii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii", (SUBR)sliderTable_i64, (SUBR)sliderTable64, (SUBR)NULL }, { "slider8tablef", S(SLIDER8tf), 0, 3, "k", "iii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii", (SUBR)sliderTable_i8f, (SUBR)sliderTable8f, (SUBR)NULL }, { "slider16tablef",S(SLIDER16tf), 0, 3, "k", "iii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii", (SUBR)sliderTable_i16f, (SUBR)sliderTable16f, (SUBR)NULL }, { "slider32tablef",S(SLIDER32tf), 0, 3, "k", "iii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii", (SUBR)sliderTable_i32f, (SUBR)sliderTable32f, (SUBR)NULL }, { "slider64tablef",S(SLIDER64tf), 0, 3, "k", "iii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii", (SUBR)sliderTable_i64f, (SUBR)sliderTable64f, (SUBR)NULL }, { "sliderKawai", S(SLIDERKAWAI), 0, 3, "kkkkkkkkkkkkkkkk", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii", (SUBR)sliderKawai_i, (SUBR)sliderKawai, NULL }, { "ctrl7.a", S(CTRL7a), 0, 5, "a", "iikkoo", (SUBR) ctrl7a_set, NULL, (SUBR) ctrl7a }, }; int slidertable_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(sliderTable_localops[0]), (int) (sizeof(sliderTable_localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/gab/stdopcod.h000066400000000000000000000076241321653344700172270ustar00rootroot00000000000000/* stdopcod.h: This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef CSOUND_STDOPCOD_H #define CSOUND_STDOPCOD_H //#include "csdl.h" #include "csoundCore.h" #include #include "interlocks.h" /* file structure for fout opcodes */ struct fileinTag { SNDFILE *file; /* Used in audio cases */ FILE *raw; /* Only used if text file */ void *fd; /* file handle returned by CSOUND::FileOpen */ char *name; /* short name */ int do_scale; /* non-zero if 0dBFS scaling should be applied */ uint32 refCount; /* reference count, | 0x80000000 if close reqd */ }; typedef struct VCO2_TABLE_ARRAY_ VCO2_TABLE_ARRAY; typedef struct _atsbufread ATSBUFREAD; typedef struct STDOPCOD_GLOBALS_ { CSOUND *csound; /* fout.c */ struct fileinTag *file_opened; int file_max; int file_num; int32 fout_kreset; /* MYFLT *buf; int buf_size; */ /* VL - now using per instance buffer */ /* oscbnk.c */ uint32 oscbnk_seed; int32 rnd31i_seed; int denorm_seed; int vco2_nr_table_arrays; VCO2_TABLE_ARRAY **vco2_tables; /* ugnorman.c */ ATSBUFREAD *atsbufreadaddr; int swapped_warning; /* locsig.c */ void *locsigaddr; /* space.c */ void *spaceaddr; /* gab/gab.c */ MYFLT *tb_ptrs[16]; /* Left here while the rest is implemented */ MYFLT *tb[16]; /* gab: updated */ int tb_ixmode[16]; /* gab: added */ int32 tb_size[16]; /* gab: added */ } STDOPCOD_GLOBALS; extern int ambicode_init_(CSOUND *); extern int bbcut_init_(CSOUND *); extern int biquad_init_(CSOUND *); extern int butter_init_(CSOUND *); extern int clfilt_init_(CSOUND *); extern int cross2_init_(CSOUND *); extern int dam_init_(CSOUND *); extern int dcblockr_init_(CSOUND *); extern int filter_init_(CSOUND *); extern int flanger_init_(CSOUND *); extern int follow_init_(CSOUND *); extern int fout_init_(CSOUND *); extern int freeverb_init_(CSOUND *); extern int ftconv_init_(CSOUND *); extern int ftgen_init_(CSOUND *); extern int gab_gab_init_(CSOUND *); extern int gab_vectorial_init_(CSOUND *); extern int grain_init_(CSOUND *); extern int locsig_init_(CSOUND *); extern int lowpassr_init_(CSOUND *); extern int metro_init_(CSOUND *); extern int midiops2_init_(CSOUND *); extern int midiops3_init_(CSOUND *); extern int newfils_init_(CSOUND *); extern int nlfilt_init_(CSOUND *); extern int oscbnk_init_(CSOUND *); extern int pluck_init_(CSOUND *); extern int repluck_init_(CSOUND *); extern int reverbsc_init_(CSOUND *); extern int seqtime_init_(CSOUND *); extern int sndloop_init_(CSOUND *); extern int sndwarp_init_(CSOUND *); extern int space_init_(CSOUND *); extern int spat3d_init_(CSOUND *); extern int syncgrain_init_(CSOUND *); extern int ugens7_init_(CSOUND *); extern int ugens9_init_(CSOUND *); extern int ugensa_init_(CSOUND *); extern int uggab_init_(CSOUND *); extern int ugmoss_init_(CSOUND *); extern int ugnorman_init_(CSOUND *); extern int ugsc_init_(CSOUND *); extern int wave_terrain_init_(CSOUND *); #endif /* CSOUND_STDOPCOD_H */ csound-6.10.0/Opcodes/gab/tabmorph.c000066400000000000000000000236171321653344700172170ustar00rootroot00000000000000/* Copyright (C) 2007 Gabriel Maldonado Csound is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ //#include "csdl.h" #include "csoundCore.h" #include "interlocks.h" typedef struct { OPDS h; MYFLT *out, *xindex, *xinterpoint, *xtabndx1, *xtabndx2, *argums[VARGMAX]; MYFLT *table[VARGMAX]; int length; long numOfTabs; } TABMORPH; static int tabmorph_set (CSOUND *csound, TABMORPH *p) /*Gab 13-March-2005 */ { int numOfTabs,j; MYFLT **argp, *first_table = NULL; FUNC *ftp; long flength = 0; numOfTabs = p->numOfTabs =((p->INCOUNT-4)); /* count segs & alloc if nec */ argp = p->argums; for (j=0; j< numOfTabs; j++) { if (UNLIKELY((ftp = csound->FTnp2Find(csound, *argp++)) == NULL)) return csound->InitError(csound, Str("tabmorph: invalid table number")); if (UNLIKELY(ftp->flen != flength && flength != 0)) return csound->InitError(csound, Str("tabmorph: all tables must have the " "same length!")); flength = ftp->flen; if (j==0) first_table = ftp->ftable; p->table[j] = ftp->ftable; } p->table[j] = first_table; /* for interpolation */ p->length = flength; return OK; } static int tabmorph(CSOUND *csound, TABMORPH *p) { MYFLT /* index, index_frac, */ tabndx1, tabndx2, tabndx1frac, tabndx2frac; MYFLT tab1val1,tab1val2, tab2val1, tab2val2, interpoint, val1, val2; long index_int; int tabndx1int, tabndx2int; index_int = (int) *p->xindex % p->length; tabndx1 = *p->xtabndx1; tabndx1int = (int) tabndx1; tabndx1frac = tabndx1 - tabndx1int; tabndx1int %= p->numOfTabs; tab1val1 = (p->table[tabndx1int ])[index_int]; tab1val2 = (p->table[tabndx1int+1])[index_int]; val1 = tab1val1 * (1-tabndx1frac) + tab1val2 * tabndx1frac; tabndx2 = *p->xtabndx2; tabndx2int = (int) tabndx2; tabndx2frac = tabndx2 - tabndx2int; tabndx2int %= p->numOfTabs; tab2val1 = (p->table[tabndx2int ])[index_int]; tab2val2 = (p->table[tabndx2int+1])[index_int]; val2 = tab2val1 * (1-tabndx2frac) + tab2val2 * tabndx2frac; interpoint = *p->xinterpoint; interpoint = (interpoint < 0 ? 0 : (interpoint > 1.0 ? 1.0 : interpoint)); /* interpoint -= (int) interpoint; to limit to zero to 1 range */ *p->out = val1 * (1 - interpoint) + val2 * interpoint; return OK; } static int tabmorphi(CSOUND *csound, TABMORPH *p) /* interpolation */ { MYFLT index, index_frac, tabndx1, tabndx2, tabndx1frac, tabndx2frac; MYFLT tab1val1a,tab1val2a, tab2val1a, tab2val2a, interpoint, val1, val2; MYFLT val1a, val2a, val1b, val2b, tab1val1b,tab1val2b, tab2val1b, tab2val2b; long index_int; int tabndx1int, tabndx2int; index = *p->xindex; index_int = (int) index; index_frac = index - index_int; index_int %= p->length; tabndx1 = *p->xtabndx1; tabndx1int = (int) tabndx1; tabndx1frac = tabndx1 - tabndx1int; tabndx1int %= p->numOfTabs; tab1val1a = (p->table[tabndx1int ])[index_int]; tab1val2a = (p->table[tabndx1int+1])[index_int]; val1a = tab1val1a * (1-tabndx1frac) + tab1val2a * tabndx1frac; tab1val1b = (p->table[tabndx1int ])[index_int+1]; tab1val2b = (p->table[tabndx1int+1])[index_int+1]; val1b = tab1val1b * (1-tabndx1frac) + tab1val2b * tabndx1frac; val1 = val1a + (val1b-val1a) * index_frac; /*--------------*/ tabndx2 = *p->xtabndx2; tabndx2int = (int) tabndx2; tabndx2frac = tabndx2 - tabndx2int; tabndx2int %= p->numOfTabs; tab2val1a = (p->table[tabndx2int ])[index_int]; tab2val2a = (p->table[tabndx2int+1])[index_int]; val2a = tab2val1a * (1-tabndx2frac) + tab2val2a * tabndx2frac; tab2val1b = (p->table[tabndx2int ])[index_int+1]; tab2val2b = (p->table[tabndx2int+1])[index_int+1]; val2b = tab2val1b * (1-tabndx2frac) + tab2val2b * tabndx2frac; val2 = val2a + (val2b-val2a) * index_frac; interpoint = *p->xinterpoint; interpoint -= (int) interpoint; /* to limit to zero to 1 range */ *p->out = val1 * (1 - interpoint) + val2 * interpoint; return OK; } static int atabmorphia(CSOUND *csound, TABMORPH *p) /* all arguments at a-rate */ { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int tablen = p->length; MYFLT *out = p->out; MYFLT *index = p->xindex; MYFLT *interpoint = p->xinterpoint; MYFLT *tabndx1 = p->xtabndx1; MYFLT *tabndx2 = p->xtabndx2; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nnumOfTabs; tab1val1a = (p->table[tabndx1int ])[index_int]; tab1val2a = (p->table[tabndx1int+1])[index_int]; val1a = tab1val1a * (1-tabndx1frac) + tab1val2a * tabndx1frac; tab1val1b = (p->table[tabndx1int ])[index_int+1]; tab1val2b = (p->table[tabndx1int+1])[index_int+1]; val1b = tab1val1b * (1-tabndx1frac) + tab1val2b * tabndx1frac; val1 = val1a + (val1b-val1a) * index_frac; /*--------------*/ tabndx2int = (int) tabndx2[n]; tabndx2frac = tabndx2[n] - tabndx2int; tabndx2int %= p->numOfTabs; tab2val1a = (p->table[tabndx2int ])[index_int]; tab2val2a = (p->table[tabndx2int+1])[index_int]; val2a = tab2val1a * (1-tabndx2frac) + tab2val2a * tabndx2frac; tab2val1b = (p->table[tabndx2int ])[index_int+1]; tab2val2b = (p->table[tabndx2int+1])[index_int+1]; val2b = tab2val1b * (1-tabndx2frac) + tab2val2b * tabndx2frac; val2 = val2a + (val2b-val2a) * index_frac; interpoint[n] -= (int) interpoint[n]; /* to limit to zero to 1 range */ out[n] = val1 * (1 - interpoint[n]) + val2 * interpoint[n]; } return OK; } /* all args k-rate except out and table index */ static int atabmorphi(CSOUND *csound, TABMORPH *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int tablen = p->length; MYFLT *out = p->out; MYFLT *index; MYFLT tabndx1, tabndx2, tabndx1frac, tabndx2frac, interpoint; int tabndx1int, tabndx2int; tabndx1 = *p->xtabndx1; tabndx1int = (int) tabndx1; tabndx1frac = tabndx1 - tabndx1int; tabndx1int %= p->numOfTabs; index = p->xindex; /*--------------*/ tabndx2 = *p->xtabndx2; tabndx2int = (int) tabndx2; tabndx2frac = tabndx2 - tabndx2int; tabndx2int %= p->numOfTabs; interpoint = *p->xinterpoint; interpoint -= (int) interpoint; /* to limit to zero to 1 range */ if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; ntable[tabndx1int ])[index_int]; tab1val2a = (p->table[tabndx1int+1])[index_int]; val1a = tab1val1a * (1-tabndx1frac) + tab1val2a * tabndx1frac; tab1val1b = (p->table[tabndx1int ])[index_int+1]; tab1val2b = (p->table[tabndx1int+1])[index_int+1]; val1b = tab1val1b * (1-tabndx1frac) + tab1val2b * tabndx1frac; val1 = val1a + (val1b-val1a) * index_frac; tab2val1a = (p->table[tabndx2int ])[index_int]; tab2val2a = (p->table[tabndx2int+1])[index_int]; val2a = tab2val1a * (1-tabndx2frac) + tab2val2a * tabndx2frac; tab2val1b = (p->table[tabndx2int ])[index_int+1]; tab2val2b = (p->table[tabndx2int+1])[index_int+1]; val2b = tab2val1b * (1-tabndx2frac) + tab2val2b * tabndx2frac; val2 = val2a + (val2b-val2a) * index_frac; out[n] = val1 * (1 - interpoint) + val2 * interpoint; } return OK; } #define S(x) sizeof(x) OENTRY tabmoroph_localops[] = { { "tabmorph", S(TABMORPH), TR, 3, "k", "kkkkm", (SUBR) tabmorph_set, (SUBR) tabmorph, NULL}, { "tabmorphi", S(TABMORPH), TR, 3, "k", "kkkkm", (SUBR) tabmorph_set, (SUBR) tabmorphi, NULL}, { "tabmorpha", S(TABMORPH), TR, 5, "a", "aaaam", (SUBR) tabmorph_set, NULL, (SUBR) atabmorphia}, { "tabmorphak",S(TABMORPH), TR, 5, "a", "akkkm", (SUBR) tabmorph_set, NULL, (SUBR) atabmorphi } }; int tabmorph_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(tabmoroph_localops[0]), (int) (sizeof(tabmoroph_localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/gab/vectorial.c000066400000000000000000002342451321653344700173740ustar00rootroot00000000000000/* Copyright (C) 2002-2004 Gabriel Maldonado The gab library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The gab library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the gab library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Ported to csound5 by:Andres Cabrera andres@geminiflux.com This file includes the vectorial table opcodes from newopcodes.c Optional arguments to some opcodes and other fixes by Andres Cabrera and Istvan Varga. */ //#include "stdopcod.h" #include "csoundCore.h" #include "interlocks.h" #include "vectorial.h" #include static int mtable_i(CSOUND *csound,MTABLEI *p) { FUNC *ftp; int j, nargs; MYFLT *table, xbmul = FL(0.0), **out = p->outargs; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->xfn)) == NULL)) { return csound->InitError(csound, Str("vtablei: incorrect table number")); } table = ftp->ftable; nargs = p->INOCOUNT-4; if (*p->ixmode) xbmul = (MYFLT) (ftp->flen / nargs); if (*p->kinterp) { MYFLT v1, v2 ; MYFLT fndx = (*p->ixmode) ? *p->xndx * xbmul : *p->xndx; long indx = (long) fndx; MYFLT fract = fndx - indx; for (j=0; j < nargs; j++) { v1 = table[indx * nargs + j]; v2 = table[(indx + 1) * nargs + j]; **out++ = v1 + (v2 - v1) * fract; } } else { long indx = (*p->ixmode) ? (long)(*p->xndx * xbmul) : (long) *p->xndx; for (j=0; j < nargs; j++) **out++ = table[indx * nargs + j]; } return OK; } static int mtable_set(CSOUND *csound,MTABLE *p) /* mtab by G.Maldonado */ { FUNC *ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->xfn)) == NULL)) { return csound->InitError(csound, Str("vtable: incorrect table number")); } p->ftable = ftp->ftable; p->nargs = p->INOCOUNT-4; p->len = ftp->flen / p->nargs; p->pfn = (long) *p->xfn; if (*p->ixmode) p->xbmul = (MYFLT) ftp->flen / p->nargs; return OK; } static int mtable_k(CSOUND *csound,MTABLE *p) { int j, nargs = p->nargs; MYFLT **out = p->outargs; MYFLT *table; long len; if (p->pfn != (long)*p->xfn) { FUNC *ftp; if (UNLIKELY( (ftp = csound->FTnp2Find(csound, p->xfn) ) == NULL)) { return csound->PerfError(csound, p->h.insdshead, Str("vtablek: incorrect table number")); } p->pfn = (long)*p->xfn; p->ftable = ftp->ftable; p->len = ftp->flen / nargs; if (*p->ixmode) p->xbmul = (MYFLT) ftp->flen / nargs; } table= p->ftable; len = p->len; if (*p->kinterp) { MYFLT fndx; long indx; MYFLT fract; long indxp1; MYFLT v1, v2 ; fndx = (*p->ixmode) ? *p->xndx * p->xbmul : *p->xndx; if (fndx >= len) fndx = (MYFLT) fmod(fndx, len); indx = (long) fndx; fract = fndx - indx; indxp1 = (indx < len-1) ? (indx+1) * nargs : 0; indx *=nargs; for (j=0; j < nargs; j++) { v1 = table[indx + j]; v2 = table[indxp1 + j]; **out++ = v1 + (v2 - v1) * fract; } } else { long indx = (*p->ixmode) ? ((long)(*p->xndx * p->xbmul) % len) * nargs : ((long) *p->xndx % len ) * nargs ; for (j=0; j < nargs; j++) **out++ = table[indx + j]; } return OK; } static int mtable_a(CSOUND *csound,MTABLE *p) { int j, nargs = p->nargs; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t k, nsmps = CS_KSMPS; int ixmode = (int) *p->ixmode; MYFLT **out = p->outargs; MYFLT *table; MYFLT *xndx = p->xndx, xbmul; long len; if (p->pfn != (long)*p->xfn) { FUNC *ftp; if (UNLIKELY( (ftp = csound->FTnp2Find(csound, p->xfn) ) == NULL)) { return csound->PerfError(csound, p->h.insdshead, Str("vtablea: incorrect table number")); } p->pfn = (long)*p->xfn; p->ftable = ftp->ftable; p->len = ftp->flen / nargs; if (ixmode) p->xbmul = (MYFLT) ftp->flen / nargs; } table = p->ftable; len = p->len; xbmul = p->xbmul; if (UNLIKELY(offset)) for (j=0; j < nargs; j++) memset(out[j], '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; for (j=0; j < nargs; j++) memset(&out[j][nsmps], '\0', early*sizeof(MYFLT)); } if (*p->kinterp) { MYFLT fndx; long indx; MYFLT fract; long indxp1; for (k=offset; k= len) fndx = (MYFLT) fmod(fndx, len); indx = (long) fndx; fract = fndx - indx; indxp1 = (indx < len-1) ? (indx+1) * nargs : 0L; indx *=nargs; for (j=0; j < nargs; j++) { v1 = table[indx + j]; v2 = table[indxp1 + j]; out[j][k] = v1 + (v2 - v1) * fract; } } } else { for (k=offset; koutargs; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->xfn)) == NULL)) { return csound->InitError(csound, Str("vtabi: incorrect table number")); } table = ftp->ftable; nargs = p->INOCOUNT-2; indx = (long) *p->xndx; for (j=0; j < nargs; j++) **out++ = table[indx * nargs + j]; return OK; } static int mtab_set(CSOUND *csound,MTAB *p) /* mtab by G.Maldonado */ { FUNC *ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->xfn)) == NULL)) { return csound->InitError(csound, Str("vtab: incorrect table number")); } p->ftable = ftp->ftable; p->nargs = p->INOCOUNT-2; p->len = ftp->flen / p->nargs; p->pfn = (long) *p->xfn; return OK; } static int mtab_k(CSOUND *csound,MTAB *p) { int j, nargs = p->nargs; MYFLT **out = p->outargs; MYFLT *table; long len, indx; table= p->ftable; len = p->len; indx = ((long) *p->xndx % len ) * nargs ; for (j=0; j < nargs; j++) **out++ = table[indx + j]; return OK; } static int mtab_a(CSOUND *csound,MTAB *p) { int j, nargs = p->nargs; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t k, nsmps = CS_KSMPS; MYFLT **out = p->outargs; MYFLT *table; MYFLT *xndx = p->xndx; long len; table = p->ftable; len = p->len; if (UNLIKELY(offset)) for (j=0; j < nargs; j++) memset(out[j], '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; for (j=0; j < nargs; j++) memset(&out[j][nsmps], '\0', early*sizeof(MYFLT)); } for (k=offset;kinargs; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->xfn)) == NULL)) { return csound->InitError(csound, Str("vtablewi: incorrect table number")); } table = ftp->ftable; nargs = p->INOCOUNT-3; if (*p->ixmode) xbmul = (MYFLT) (ftp->flen / nargs); indx = (*p->ixmode) ? (long)(*p->xndx * xbmul) : (long) *p->xndx; for (j=0; j < nargs; j++) table[indx * nargs + j] = **in++; return OK; } static int mtablew_set(CSOUND *csound,MTABLEW *p) /* mtabw by G.Maldonado */ { FUNC *ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->xfn)) == NULL)) { return csound->InitError(csound, Str("vtablew: incorrect table number")); } p->ftable = ftp->ftable; p->nargs = p->INOCOUNT-3; p->len = ftp->flen / p->nargs; p->pfn = (long) *p->xfn; if (*p->ixmode) p->xbmul = (MYFLT) ftp->flen / p->nargs; return OK; } static int mtablew_k(CSOUND *csound,MTABLEW *p) { int j, nargs = p->nargs; MYFLT **in = p->inargs; MYFLT *table; long len, indx; if (p->pfn != (long)*p->xfn) { FUNC *ftp; if (UNLIKELY( (ftp = csound->FTnp2Find(csound, p->xfn) ) == NULL)) { return csound->PerfError(csound, p->h.insdshead, Str("vtablewk: incorrect table number")); } p->pfn = (long)*p->xfn; p->ftable = ftp->ftable; p->len = ftp->flen / nargs; if (*p->ixmode) p->xbmul = (MYFLT) ftp->flen / nargs; } table= p->ftable; len = p->len; indx = (*p->ixmode) ? ((long)(*p->xndx * p->xbmul) % len) * nargs : ((long) *p->xndx % len ) * nargs ; for (j=0; j < nargs; j++) table[indx + j] = **in++; return OK; } static int mtablew_a(CSOUND *csound,MTABLEW *p) { int j, nargs = p->nargs; int ixmode = (int) *p->ixmode; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t k, nsmps = CS_KSMPS; uint32_t early = p->h.insdshead->ksmps_no_end; MYFLT **in = p->inargs; MYFLT *table; MYFLT *xndx = p->xndx, xbmul; long len; if (p->pfn != (long)*p->xfn) { FUNC *ftp; if (UNLIKELY( (ftp = csound->FTnp2Find(csound, p->xfn) ) == NULL)) { return csound->PerfError(csound, p->h.insdshead, Str("vtablewa: incorrect table number")); } p->pfn = (long)*p->xfn; p->ftable = ftp->ftable; p->len = ftp->flen / nargs; if (ixmode) p->xbmul = (MYFLT) ftp->flen / nargs; } table = p->ftable; len = p->len; xbmul = p->xbmul; if (UNLIKELY(early)) nsmps -= early; for (k=offset; kinargs; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->xfn)) == NULL)) { return csound->InitError(csound, Str("vtabwi: incorrect table number")); } table = ftp->ftable; nargs = p->INOCOUNT-2; indx = (long) *p->xndx; for (j=0; j < nargs; j++) table[indx * nargs + j] = **in++; return OK; } static int mtabw_set(CSOUND *csound,MTABW *p) /* mtabw by G.Maldonado */ { FUNC *ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->xfn)) == NULL)) { return csound->InitError(csound, Str("vtablew: incorrect table number")); } p->ftable = ftp->ftable; p->nargs = p->INOCOUNT-2; p->len = ftp->flen / p->nargs; p->pfn = (long) *p->xfn; return OK; } static int mtabw_k(CSOUND *csound,MTABW *p) { int j, nargs = p->nargs; MYFLT **in = p->inargs; MYFLT *table; long len, indx; if (p->pfn != (long)*p->xfn) { FUNC *ftp; if (UNLIKELY( (ftp = csound->FTnp2Find(csound, p->xfn) ) == NULL)) { return csound->PerfError(csound, p->h.insdshead, Str("vtablewk: incorrect table number")); } p->pfn = (long)*p->xfn; p->ftable = ftp->ftable; p->len = ftp->flen / nargs; } table= p->ftable; len = p->len; indx = ((long) *p->xndx % len ) * nargs ; for (j=0; j < nargs; j++) table[indx + j] = **in++; return OK; } static int mtabw_a(CSOUND *csound,MTABW *p) { int j, nargs = p->nargs; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t k, nsmps = CS_KSMPS; MYFLT **in = p->inargs; MYFLT *table; MYFLT *xndx = p->xndx; long len; if (p->pfn != (long)*p->xfn) { FUNC *ftp; if (UNLIKELY( (ftp = csound->FTnp2Find(csound, p->xfn) ) == NULL)) { return csound->PerfError(csound, p->h.insdshead, Str("vtabwa: incorrect table number")); } p->pfn = (long)*p->xfn; p->ftable = ftp->ftable; p->len = ftp->flen / nargs; } table = p->ftable; len = p->len; if (UNLIKELY(early)) nsmps -= early; for (k=offset; kFTnp2Find(csound, p->ifn); if (UNLIKELY(ftp == NULL)) return NOTOK; p->vector = ftp->ftable; /* long elements = (long) *p->kelements; */ p->len = (long) ftp->flen; /* p->dstoffset = (long) *p->kdstoffset; if (UNLIKELY((elements | (long)*p->kdstoffset) < 0L || (elements + (long)*p->kdstoffset) > p->len)) { return csound->InitError(csound, Str("vectorop: Destination table length exceeded")); } */ return OK; } static int vadd_i(CSOUND *csound, VECTOROPI *p) { FUNC *ftp; MYFLT *vector; int32 i, elements, dstoffset, len; MYFLT value = *p->kval; ftp = csound->FTnp2Find(csound, p->ifn); if (UNLIKELY(ftp == NULL)) { return csound->InitError(csound, Str("vadd_i: invalid table number %i"), (int) *p->ifn); } vector = ftp->ftable; len = (int32) ftp->flen; elements = MYFLT2LRND(*p->ielements); dstoffset = MYFLT2LRND(*p->idstoffset); if (dstoffset < 0) { elements += dstoffset; } else { len -= dstoffset; vector += dstoffset; } if (UNLIKELY(elements > len)) { elements = len; csound->Warning(csound,Str("vadd_i: ifn length exceeded")); } for (i = 0; i < elements; i++) vector[i] += value; return OK; } static int vaddk(CSOUND *csound, VECTOROP *p) { int i, len; int32 dstoffset, elements = (int32)*p->kelements; MYFLT *vector; MYFLT value; vector = p->vector; value = *p->kval; len = p->len; dstoffset = MYFLT2LRND(*p->kdstoffset); if (dstoffset < 0) { elements += dstoffset; } else { len -= dstoffset; vector += dstoffset; } if (UNLIKELY(elements > len)) { elements = len; if (UNLIKELY((int) *p->kverbose != 0)) csound->Warning(csound,Str("vadd: ifn1 length exceeded")); } for (i = 0; i < elements; i++) vector[i] += value; return OK; } static int vmult_i(CSOUND *csound, VECTOROPI *p) { FUNC *ftp; MYFLT *vector; int32 i, elements, dstoffset, len; MYFLT value = *p->kval; ftp = csound->FTnp2Find(csound, p->ifn); if (UNLIKELY(ftp == NULL)) { return csound->InitError(csound,Str("vadd_i: invalid table number %i"), (int) *p->ifn); } vector = ftp->ftable; len = (int32) ftp->flen; elements = MYFLT2LRND(*p->ielements); dstoffset = MYFLT2LRND(*p->idstoffset); if (dstoffset < 0) { elements += dstoffset; } else { len -= dstoffset; vector += dstoffset; } if (UNLIKELY(elements > len)) { elements = len; csound->Warning(csound,Str("vmult_i: ifn length exceeded")); } for (i = 0; i < elements; i++) vector[i] *= value; return OK; } static int vmultk(CSOUND *csound, VECTOROP *p) { int i, len; int32 dstoffset, elements = (int32)*p->kelements; MYFLT *vector; MYFLT value; vector = p->vector; value = (MYFLT)*p->kval; len = p->len; dstoffset = (int32)*p->kdstoffset; if (dstoffset < 0) { elements += dstoffset; } else { len -= dstoffset; vector += dstoffset; } if (UNLIKELY(elements > len)) { elements = len; if (UNLIKELY((int) *p->kverbose != 0)) csound->Warning(csound,Str("vmult: ifn1 length exceeded")); } for (i = 0; i < elements; i++) vector[i] *= value; return OK; } static int vpow_i(CSOUND *csound, VECTOROPI *p) { FUNC *ftp; MYFLT *vector; int32 i, elements, dstoffset, len; MYFLT value = *p->kval; ftp = csound->FTnp2Find(csound, p->ifn); if (UNLIKELY(ftp == NULL)) { return csound->InitError(csound,Str("vpow_i: invalid table number %i"), (int) *p->ifn); } vector = ftp->ftable; len = (int32) ftp->flen; elements = (int32) *p->ielements; dstoffset = (int32) *p->idstoffset; if (dstoffset < 0) { elements += dstoffset; } else { len -= dstoffset; vector += dstoffset; } if (UNLIKELY(elements > len)) { elements = len; csound->Warning(csound,Str("vpow_i: ifn length exceeded")); } for (i = 0; i < elements; i++) vector[i] = POWER(vector[i], value); return OK; } static int vpowk(CSOUND *csound, VECTOROP *p) { int i, len; int32 dstoffset, elements = (int32)*p->kelements; MYFLT *vector; MYFLT value; vector = p->vector; value = (MYFLT)*p->kval; len = p->len; dstoffset = (int32)*p->kdstoffset; if (dstoffset < 0) { elements += dstoffset; } else { len -= dstoffset; vector += dstoffset; } if (UNLIKELY(elements > len)) { elements = len; if (UNLIKELY((int) *p->kverbose != 0)) csound->Warning(csound,Str("vpow: ifn1 length exceeded")); } for (i = 0; i < elements; i++) vector[i] = POWER(vector[i], value); return OK; } static int vexp_i(CSOUND *csound, VECTOROPI *p) { FUNC *ftp; MYFLT *vector; int32 i, elements, dstoffset, len; MYFLT value = *p->kval; ftp = csound->FTnp2Find(csound, p->ifn); if (UNLIKELY(ftp == NULL)) { return csound->InitError(csound,Str("vexp_i: invalid table number %i"), (int) *p->ifn); } vector = ftp->ftable; len = (int32) ftp->flen; elements = (int32) *p->ielements; dstoffset = (int32) *p->idstoffset; if (dstoffset < 0) { elements += dstoffset; } else { len -= dstoffset; vector += dstoffset; } if (UNLIKELY(elements > len)) { elements = len; csound->Warning(csound,Str("vexp_i: ifn length exceeded")); } for (i = 0; i < elements; i++) vector[i] = POWER(value, vector[i]); return OK; } static int vexpk(CSOUND *csound, VECTOROP *p) { int i, len; int32 dstoffset, elements = (int32)*p->kelements; MYFLT *vector; MYFLT value; vector = p->vector; value = (MYFLT)*p->kval; len = p->len; dstoffset = (int32)*p->kdstoffset; if (dstoffset < 0) { elements += dstoffset; } else { len -= dstoffset; vector += dstoffset; } if (UNLIKELY(elements > len)) { elements = len; if (UNLIKELY((int) *p->kverbose != 0)) csound->Warning(csound,Str("vexp: ifn1 length exceeded")); } for (i = 0; i < elements; i++) vector[i] += POWER(value, vector[i]); return OK; } /* ------------------------- */ static int vectorsOp_set(CSOUND *csound, VECTORSOP *p) { FUNC *ftp1, *ftp2; /* if (*p->ifn1 == *p->ifn2) csound->Warning(csound, Str("vectorsop: ifn1 = ifn2."));*/ ftp1 = csound->FTnp2Find(csound, p->ifn1); ftp2 = csound->FTnp2Find(csound, p->ifn2); if (UNLIKELY(ftp1 == NULL)) { return csound->InitError(csound, Str("vectorsop: ifn1 invalid table number %i"), (int) *p->ifn1); } else if (UNLIKELY(ftp2 == NULL)) { return csound->InitError(csound, Str("vectorsop: ifn2 invalid table number %i"), (int) *p->ifn2); } p->vector1 = ftp1->ftable; p->vector2 = ftp2->ftable; /*int elements = (int) *p->kelements; p->dstoffset = (int32) *p->kdstoffset; p->srcoffset = (int32) *p->ksrcoffset;*/ p->len1 = (int32) ftp1->flen+1; /* Guard point included */ p->len2 = (int32) ftp2->flen+1;/* if ((elements | (int32) *p->kdstoffset) < 0L || (elements + (int32) *p->kdstoffset) > p->len1) { return csound->Warning(csound, Str("vectorops: Destination table length exceeded")); }*/ return OK; } static int vcopy(CSOUND *csound,VECTORSOP *p) { int i, j, n; int32 len1, len2, srcoffset, dstoffset, elements = (int32)*p->kelements; MYFLT *vector1, *vector2; vector1 = p->vector1; vector2 = p->vector2; len1 = p->len1; len2 = p->len2; srcoffset = (int32)*p->ksrcoffset; dstoffset = (int32)*p->kdstoffset; if (dstoffset < 0) { elements += dstoffset; srcoffset -= dstoffset; } else { len1 -= dstoffset; vector1 += dstoffset; } if (UNLIKELY(elements > len1)) { elements = len1; if (UNLIKELY((int) *p->kverbose != 0)) csound->Warning(csound,Str("vcopy: ifn1 length exceeded")); } /*elements = (elements < len1 ? elements : len1);*/ if (srcoffset < 0) { /*int i, */n = -srcoffset; n = (n < elements ? n : elements); for (i = 0; i < n; i++) vector1[i] = 0; elements -= i; vector1 += i; } else { len2 -= srcoffset; vector2 += srcoffset; } /*n = (elements < len2 ? elements : len2);*/ if (UNLIKELY(elements > len2)) { if (UNLIKELY((int) *p->kverbose != 0)) csound->Warning(csound,Str("vcopy: ifn2 length exceeded")); n = len2; } else n = elements; i = 0; if (p->vector1 == p->vector2 && vector1 > vector2) { /* special case: need to reverse direction*/ for (j = n; --j >= 0; i++) vector1[j] = vector2[j]; } for (; i < n; i++) vector1[i] = vector2[i]; for ( ; i < elements; i++) vector1[i] = FL(0.0); return OK; } static int vcopy_i(CSOUND *csound, VECTORSOPI *p) { FUNC *ftp1, *ftp2; MYFLT *vector1, *vector2; int32 i, j, n, elements, srcoffset, dstoffset, len1, len2; ftp1 = csound->FTnp2Find(csound, p->ifn1); ftp2 = csound->FTnp2Find(csound, p->ifn2); if (UNLIKELY(ftp1 == NULL)) { return csound->InitError(csound, Str("vcopy_i: ifn1 invalid table number %i"), (int) *p->ifn1); } else if (UNLIKELY(ftp2 == NULL)) { return csound->InitError(csound, Str("vcopy_i: ifn2 invalid table number %i"), (int) *p->ifn2); } /* if (*p->ifn1 == *p->ifn2) csound->Warning(csound, Str("vcopy_i: ifn1 = ifn2."));*/ vector1 = ftp1->ftable; vector2 = ftp2->ftable; len1 = (int32) ftp1->flen+1; len2 = (int32) ftp2->flen+1; elements = (int32) *p->ielements; srcoffset = (int32) *p->isrcoffset; dstoffset = (int32) *p->idstoffset; if (dstoffset < 0) { elements += dstoffset; srcoffset -= dstoffset; } else { len1 -= dstoffset; vector1 += dstoffset; } if (UNLIKELY(elements > len1)) { elements = len1; csound->Warning(csound,Str("vcopy_i: ifn1 length exceeded")); } /* elements = (elements < len1 ? elements : len1);*/ if (srcoffset < 0) { /*int i, */n = -srcoffset; n = (n < elements ? n : elements); for (i = 0; i < n; i++) vector1[i] = FL(0.0); elements -= i; vector1 += i; } else { len2 -= srcoffset; vector2 += srcoffset; } /* n = (elements < len2 ? elements : len2);*/ if (UNLIKELY(elements > len2)) { csound->Warning(csound,Str("vcopy_i: ifn2 length exceeded")); n = len2; } else n = elements; i = 0; if (p->vector1 == p->vector2 && vector1 > vector2) { /* special case: need to reverse direction*/ for (j = n; --j >= 0; i++) vector1[j] = vector2[j]; } for ( ; i < n; i++) vector1[i] = vector2[i]; for ( ; i < elements; i++) vector1[i] = FL(0.0); return OK; } static int vaddvk(CSOUND *csound,VECTORSOP *p) { int i, j, n; int32 len1, len2, srcoffset, dstoffset, elements = (int32)*p->kelements; MYFLT *vector1, *vector2; vector1 = p->vector1; vector2 = p->vector2; len1 = p->len1; len2 = p->len2; srcoffset = (int32)*p->ksrcoffset; dstoffset = (int32)*p->kdstoffset; if (dstoffset < 0) { elements += dstoffset; srcoffset -= dstoffset; } else { len1 -= dstoffset; vector1 += dstoffset; } if (UNLIKELY(elements > len1)) { elements = len1; if (UNLIKELY((int) *p->kverbose != 0)) csound->Warning(csound,Str("vaddv: ifn1 length exceeded")); } /* elements = (elements < len1 ? elements : len1);*/ if (srcoffset < 0) { /*int i, n = -srcoffset; */ i = -srcoffset; /*n = (n < elements ? n : elements); for (i = 0; i < n; i++) vector1[i] = 0;*/ elements -= i; vector1 += i; } else { len2 -= srcoffset; vector2 += srcoffset; } /*n = (elements < len2 ? elements : len2);*/ if (UNLIKELY(elements > len2)) { if (UNLIKELY((int) *p->kverbose != 0)) csound->Warning(csound,Str("vaddv: ifn2 length exceeded")); n = len2; } else n = elements; i = 0; if (p->vector1 == p->vector2 && vector1 > vector2) { /* special case: need to reverse direction*/ for (j = n; --j >= 0; i++) vector1[j] += vector2[j]; } for (; i < n; i++) vector1[i] += vector2[i]; /*for ( ; i < elements; i++) vector1[i] = 0;*/ return OK; } static int vaddv_i(CSOUND *csound, VECTORSOPI *p) { FUNC *ftp1, *ftp2; MYFLT *vector1, *vector2; int32 i, n, elements, srcoffset, dstoffset, len1, len2; ftp1 = csound->FTnp2Find(csound, p->ifn1); ftp2 = csound->FTnp2Find(csound, p->ifn2); if (UNLIKELY(ftp1 == NULL)) { return csound->InitError(csound, Str("vaddv_i: ifn1 invalid table number %i"), (int) *p->ifn1); } else if (UNLIKELY(ftp2 == NULL)) { return csound->InitError(csound, Str("vaddv_i: ifn2 invalid table number %i"), (int) *p->ifn2); } /* if (*p->ifn1 == *p->ifn2) csound->Warning(csound, Str("vaddv_i: ifn1 = ifn2."));*/ vector1 = ftp1->ftable; vector2 = ftp2->ftable; len1 = (int32) ftp1->flen+1; len2 = (int32) ftp2->flen+1; elements = (int32) *p->ielements; srcoffset = (int32) *p->isrcoffset; dstoffset = (int32) *p->idstoffset; if (dstoffset < 0) { elements += dstoffset; srcoffset -= dstoffset; } else { len1 -= dstoffset; vector1 += dstoffset; } if (UNLIKELY(elements > len1)) { elements = len1; csound->Warning(csound,Str("vaddv_i: ifn1 length exceeded")); } /*elements = (elements < len1 ? elements : len1);*/ if (srcoffset < 0) { /*int i, n = -srcoffset; */ n = -srcoffset; n = (n < elements ? n : elements); for (i = 0; i < n; i++) vector1[i] = FL(0.0); elements -= i; vector1 += i; } else { len2 -= srcoffset; vector2 += srcoffset; } /*n = (elements < len2 ? elements : len2);*/ if (UNLIKELY(elements > len2)) { csound->Warning(csound,Str("vaddv_i: ifn2 length exceeded")); n = len2; } else n = elements; for (i = 0; i < n; i++) vector1[i] += vector2[i]; return OK; } static int vsubvk(CSOUND *csound,VECTORSOP *p) { int i, j, n; int32 len1, len2, srcoffset, dstoffset, elements = (int32)*p->kelements; MYFLT *vector1, *vector2; vector1 = p->vector1; vector2 = p->vector2; len1 = p->len1; len2 = p->len2; srcoffset = (int32)*p->ksrcoffset; dstoffset = (int32)*p->kdstoffset; if (dstoffset < 0) { elements += dstoffset; srcoffset -= dstoffset; } else { len1 -= dstoffset; vector1 += dstoffset; } if (UNLIKELY(elements > len1)) { elements = len1; if (UNLIKELY((int) *p->kverbose != 0)) csound->Warning(csound,Str("vsubv: ifn1 length exceeded")); } /* elements = (elements < len1 ? elements : len1);*/ if (srcoffset < 0) { i = -srcoffset; /*int i, n = -srcoffset; n = (n < elements ? n : elements); for (i = 0; i < n; i++) vector1[i] = 0;*/ elements -= i; vector1 += i; } else { len2 -= srcoffset; vector2 += srcoffset; } /*n = (elements < len2 ? elements : len2);*/ if (UNLIKELY(elements > len2)) { if (UNLIKELY((int) *p->kverbose != 0)) csound->Warning(csound,Str("vsubv: ifn2 length exceeded")); n = len2; } else n = elements; i = 0; if (p->vector1 == p->vector2 && vector1 > vector2) { /* special case: need to reverse direction */ for (j = n; --j >= 0; i++) vector1[j] -= vector2[j]; } for ( ; i < n; i++) vector1[i] -= vector2[i]; /*for ( ; i < elements; i++) vector1[i] = 0;*/ return OK; } static int vsubv_i(CSOUND *csound, VECTORSOPI *p) { FUNC *ftp1, *ftp2; MYFLT *vector1, *vector2; int32 i, j, n, elements, srcoffset, dstoffset, len1, len2; ftp1 = csound->FTnp2Find(csound, p->ifn1); ftp2 = csound->FTnp2Find(csound, p->ifn2); if (UNLIKELY(ftp1 == NULL)) { return csound->InitError(csound, Str("vsubv_i: ifn1 invalid table number %i"), (int) *p->ifn1); } else if (UNLIKELY(ftp2 == NULL)) { return csound->InitError(csound, Str("vsubv_i: ifn2 invalid table number %i"), (int) *p->ifn2); } /* if (*p->ifn1 == *p->ifn2) csound->Warning(csound, Str("vsubv_i: ifn1 = ifn2."));*/ vector1 = ftp1->ftable; vector2 = ftp2->ftable; len1 = (int32) ftp1->flen+1; len2 = (int32) ftp2->flen+1; elements = (int32) *p->ielements; srcoffset = (int32) *p->isrcoffset; dstoffset = (int32) *p->idstoffset; if (dstoffset < 0) { elements += dstoffset; srcoffset -= dstoffset; } else { len1 -= dstoffset; vector1 += dstoffset; } if (UNLIKELY(elements > len1)) { elements = len1; csound->Warning(csound,Str("vsubv_i: ifn1 length exceeded")); } /* elements = (elements < len1 ? elements : len1); */ if (srcoffset < 0) { n = -srcoffset; /*int i, n = -srcoffset; */ n = (n < elements ? n : elements); for (i = 0; i < n; i++) vector1[i] = 0; elements -= i; vector1 += i; } else { len2 -= srcoffset; vector2 += srcoffset; } /* n = (elements < len2 ? elements : len2); */ if (UNLIKELY(elements > len2)) { csound->Warning(csound,Str("vsubv_i: ifn2 length exceeded")); n = len2; } else n = elements; i = 0; if (p->vector1 == p->vector2 && vector1 > vector2) { /* special case: need to reverse direction */ for (j = n; --j >= 0; i++) vector1[j] -= vector2[j]; } for ( ; i < n; i++) vector1[i] -= vector2[i]; return OK; } static int vmultvk(CSOUND *csound,VECTORSOP *p) { int i, j, n; int32 len1, len2, srcoffset, dstoffset, elements = (int32)*p->kelements; MYFLT *vector1, *vector2; vector1 = p->vector1; vector2 = p->vector2; len1 = p->len1; len2 = p->len2; srcoffset = (int32)*p->ksrcoffset; dstoffset = (int32)*p->kdstoffset; if (dstoffset < 0) { elements += dstoffset; srcoffset -= dstoffset; } else { len1 -= dstoffset; vector1 += dstoffset; } if (UNLIKELY(elements > len1)) { elements = len1; if (UNLIKELY((int) *p->kverbose != 0)) csound->Warning(csound,Str("vmultv: ifn1 length exceeded")); } /*elements = (elements < len1 ? elements : len1);*/ if (srcoffset < 0) { i = -srcoffset; /*int i, n = -srcoffset; n = (n < elements ? n : elements); for (i = 0; i < n; i++) vector1[i] = 0;*/ elements -= i; vector1 += i; } else { len2 -= srcoffset; vector2 += srcoffset; } /*n = (elements < len2 ? elements : len2);*/ if (UNLIKELY(elements > len2)) { if (UNLIKELY((int) *p->kverbose != 0)) csound->Warning(csound,Str("vmultv: ifn2 length exceeded")); n = len2; } else n = elements; i = 0; if (p->vector1 == p->vector2 && vector1 > vector2) { /* special case: need to reverse direction */ for (j = n; --j >= 0; i++) vector1[j] *= vector2[j]; } for ( ; i < n; i++) vector1[i] *= vector2[i]; /* for ( ; i < elements; i++) vector1[i] = 0;*/ return OK; } static int vmultv_i(CSOUND *csound, VECTORSOPI *p) { FUNC *ftp1, *ftp2; MYFLT *vector1, *vector2; int32 i, j, n, elements, srcoffset, dstoffset, len1, len2; ftp1 = csound->FTnp2Find(csound, p->ifn1); ftp2 = csound->FTnp2Find(csound, p->ifn2); if (UNLIKELY(ftp1 == NULL)) { return csound->InitError(csound, Str("vmultv_i: ifn1 invalid table number %i"), (int) *p->ifn1); } else if (UNLIKELY(ftp2 == NULL)) { return csound->InitError(csound, Str("vmultv_i: ifn2 invalid table number %i"), (int) *p->ifn2); } /* if (*p->ifn1 == *p->ifn2) csound->Warning(csound, Str("vmultv_i: ifn1 = ifn2."));*/ vector1 = ftp1->ftable; vector2 = ftp2->ftable; len1 = (int32) ftp1->flen+1; len2 = (int32) ftp1->flen+1; elements = (int32) *p->ielements; srcoffset = (int32) *p->isrcoffset; dstoffset = (int32) *p->idstoffset; if (dstoffset < 0) { elements += dstoffset; srcoffset -= dstoffset; } else { len1 -= dstoffset; vector1 += dstoffset; } if (UNLIKELY(elements > len1)) { elements = len1; csound->Warning(csound,Str("vmultv_i: ifn1 length exceeded")); } /* elements = (elements < len1 ? elements : len1);*/ if (srcoffset < 0) { /*int i, */n = -srcoffset; n = (n < elements ? n : elements); for (i = 0; i < n; i++) vector1[i] = FL(0.0); elements -= i; vector1 += i; } else { len2 -= srcoffset; vector2 += srcoffset; } /*n = (elements < len2 ? elements : len2);*/ if (UNLIKELY(elements > len2)) { csound->Warning(csound,Str("vmultv_i: ifn2 length exceeded")); n = len2; } else n = elements; i = 0; if (p->vector1 == p->vector2 && vector1 > vector2) { /* special case: need to reverse direction */ for (j = n; --j >= 0; i++) vector1[j] *= vector2[j]; } for ( ; i < n; i++) vector1[i] *= vector2[i]; return OK; } static int vdivvk(CSOUND *csound,VECTORSOP *p) { int i, j, n; int32 len1, len2, srcoffset, dstoffset, elements = (int32)*p->kelements; MYFLT *vector1, *vector2; vector1 = p->vector1; vector2 = p->vector2; len1 = p->len1; len2 = p->len2; srcoffset = (int32)*p->ksrcoffset; dstoffset = (int32)*p->kdstoffset; if (dstoffset < 0) { elements += dstoffset; srcoffset -= dstoffset; } else { len1 -= dstoffset; vector1 += dstoffset; } if (UNLIKELY(elements > len1)) { elements = len1; if (UNLIKELY((int) *p->kverbose != 0)) csound->Warning(csound,Str("vdivv: ifn1 length exceeded")); } /* elements = (elements < len1 ? elements : len1); */ if (srcoffset < 0) { i = -srcoffset; /*int i, n = -srcoffset; n = (n < elements ? n : elements); for (i = 0; i < n; i++) vector1[i] = 0;*/ elements -= i; vector1 += i; } else { len2 -= srcoffset; vector2 += srcoffset; } /*n = (elements < len2 ? elements : len2);*/ if (UNLIKELY(elements > len2)) { if (UNLIKELY((int) *p->kverbose != 0)) csound->Warning(csound,Str("vdivv: ifn2 length exceeded")); n = len2; } else n = elements; i = 0; if (p->vector1 == p->vector2 && vector1 > vector2) { /* special case: need to reverse direction */ for (j = n; --j >= 0; i++) vector1[j] /= vector2[j]; } for ( ; i < n; i++) vector1[i] /= vector2[i]; /* for ( ; i < elements; i++) vector1[i] = 0;*/ return OK; } static int vdivv_i(CSOUND *csound, VECTORSOPI *p) { FUNC *ftp1, *ftp2; MYFLT *vector1, *vector2; int32 i, j, n, elements, srcoffset, dstoffset, len1, len2; ftp1 = csound->FTnp2Find(csound, p->ifn1); ftp2 = csound->FTnp2Find(csound, p->ifn2); if (UNLIKELY(ftp1 == NULL)) { return csound->InitError(csound, Str("vdivv_i: ifn1 invalid table number %i"), (int) *p->ifn1); } else if (UNLIKELY(ftp2 == NULL)) { return csound->InitError(csound, Str("vdivv_i: ifn2 invalid table number %i"), (int) *p->ifn2); } /*if (*p->ifn1 == *p->ifn2) csound->Warning(csound, Str("vdivv_i: ifn1 = ifn2."));*/ vector1 = ftp1->ftable; vector2 = ftp2->ftable; len1 = (int32) ftp1->flen+1; len2 = (int32) ftp2->flen+1; elements = (int32) *p->ielements; srcoffset = (int32) *p->isrcoffset; dstoffset = (int32) *p->idstoffset; if (dstoffset < 0) { elements += dstoffset; srcoffset -= dstoffset; } else { len1 -= dstoffset; vector1 += dstoffset; } if (UNLIKELY(elements > len1)) { elements = len1; csound->Warning(csound,Str("vdivv_i: ifn1 length exceeded")); } /* elements = (elements < len1 ? elements : len1); */ if (srcoffset < 0) { n = -srcoffset; /*int i, n = -srcoffset; */ n = (n < elements ? n : elements); for (i = 0; i < n; i++) vector1[i] = FL(0.0); elements -= i; vector1 += i; } else { len2 -= srcoffset; vector2 += srcoffset; } /*n = (elements < len2 ? elements : len2);*/ if (UNLIKELY(elements > len2)) { csound->Warning(csound,Str("vdivv_i: ifn2 length exceeded")); n = len2; } else n = elements; i = 0; if (p->vector1 == p->vector2 && vector1 > vector2) { /*special case: need to reverse direction*/ for (j = n; --j >= 0; i++) vector1[j] = vector2[j]; } for ( ; i < n; i++) vector1[i] /= vector2[i]; return OK; } static int vpowvk(CSOUND *csound,VECTORSOP *p) { int i, j, n; int32 len1, len2, srcoffset, dstoffset, elements = (int32)*p->kelements; MYFLT *vector1, *vector2; vector1 = p->vector1; vector2 = p->vector2; len1 = p->len1; len2 = p->len2; srcoffset = (int32)*p->ksrcoffset; dstoffset = (int32)*p->kdstoffset; if (dstoffset < 0) { elements += dstoffset; srcoffset -= dstoffset; } else { len1 -= dstoffset; vector1 += dstoffset; } if (UNLIKELY(elements > len1)) { elements = len1; if (UNLIKELY((int) *p->kverbose != 0)) csound->Warning(csound,Str("vpowv: ifn1 length exceeded")); } /*elements = (elements < len1 ? elements : len1);*/ if (srcoffset < 0) { i = -srcoffset; /*int i, n = -srcoffset; n = (n < elements ? n : elements); for (i = 0; i < n; i++) vector1[i] = 0; */ elements -= i; vector1 += i; } else { len2 -= srcoffset; vector2 += srcoffset; } /* n = (elements < len2 ? elements : len2); */ if (UNLIKELY(elements > len2)) { if (UNLIKELY((int) *p->kverbose != 0)) csound->Warning(csound,Str("vpowv: ifn2 length exceeded")); n = len2; } else n = elements; i = 0; if (p->vector1 == p->vector2 && vector1 > vector2) { /* special case: need to reverse direction */ for (j = n; --j >= 0; i++) vector1[j] = POWER(vector1[j], vector2[j]); } for ( ; i < n; i++) vector1[i] = POWER(vector1[i], vector2[i]); /*for ( ; i < elements; i++) vector1[i] = 0;*/ return OK; } static int vpowv_i(CSOUND *csound, VECTORSOPI *p) { FUNC *ftp1, *ftp2; MYFLT *vector1, *vector2; int32 i, j, n, elements, srcoffset, dstoffset, len1, len2; ftp1 = csound->FTnp2Find(csound, p->ifn1); ftp2 = csound->FTnp2Find(csound, p->ifn2); if (UNLIKELY(ftp1 == NULL)) { return csound->InitError(csound, Str("vpowv_i: ifn1 invalid table number %i"), (int) *p->ifn1); } else if (UNLIKELY(ftp2 == NULL)) { return csound->InitError(csound, Str("vpowv_i: ifn2 invalid table number %i"), (int) *p->ifn2); } /*if (*p->ifn1 == *p->ifn2) csound->Warning(csound, Str("vpowv_i: ifn1 = ifn2."));*/ vector1 = ftp1->ftable; vector2 = ftp2->ftable; len1 = (int32) ftp1->flen+1; len2 = (int32) ftp2->flen+1; elements = (int32) *p->ielements; srcoffset = (int32) *p->isrcoffset; dstoffset = (int32) *p->idstoffset; if (dstoffset < 0) { elements += dstoffset; srcoffset -= dstoffset; } else { len1 -= dstoffset; vector1 += dstoffset; } if (UNLIKELY(elements > len1)) { elements = len1; csound->Warning(csound,Str("vpowv_i: ifn1 length exceeded")); } /*elements = (elements < len1 ? elements : len1);*/ if (srcoffset < 0) { /*int i, */n = -srcoffset; n = (n < elements ? n : elements); for (i = 0; i < n; i++) vector1[i] = FL(0.0); elements -= i; vector1 += i; } else { len2 -= srcoffset; vector2 += srcoffset; } /*n = (elements < len2 ? elements : len2);*/ if (UNLIKELY(elements > len2)) { csound->Warning(csound,Str("vpowv_i: ifn2 length exceeded")); n = len2; } else n = elements; i = 0; if (p->vector1 == p->vector2 && vector1 > vector2) { /*special case: need to reverse direction*/ for (j = n; --j >= 0; i++) vector1[j] = POWER(vector1[j], vector2[j]); } for (i = 0; i < n; i++) vector1[i] = POWER(vector1[i], vector2[i]); return OK; } static int vexpvk(CSOUND *csound,VECTORSOP *p) { int i, j, n; int32 len1, len2, srcoffset, dstoffset, elements = (int32)*p->kelements; MYFLT *vector1, *vector2; vector1 = p->vector1; vector2 = p->vector2; len1 = p->len1; len2 = p->len2; srcoffset = (int32)*p->ksrcoffset; dstoffset = (int32)*p->kdstoffset; if (dstoffset < 0) { elements += dstoffset; srcoffset -= dstoffset; } else { len1 -= dstoffset; vector1 += dstoffset; } if (UNLIKELY(elements > len1)) { elements = len1; if (UNLIKELY((int) *p->kverbose != 0)) csound->Warning(csound,Str("vexpv: ifn1 length exceeded")); } /* elements = (elements < len1 ? elements : len1); */ if (srcoffset < 0) { i = -srcoffset; /*int i, n = -srcoffset; n = (n < elements ? n : elements); for (i = 0; i < n; i++) vector1[i] = 0; */ elements -= i; vector1 += i; } else { len2 -= srcoffset; vector2 += srcoffset; } /*n = (elements < len2 ? elements : len2);*/ if (UNLIKELY(elements > len2)) { if (UNLIKELY((int) *p->kverbose != 0)) csound->Warning(csound,Str("vexpv: ifn2 length exceeded")); n = len2; } else n = elements; i = 0; if (p->vector1 == p->vector2 && vector1 > vector2) { /* special case: need to reverse direction */ for (j = n; --j >= 0; i++) vector1[j] = POWER(vector2[j], vector1[j]); } for ( ; i < n; i++) vector1[i] = POWER(vector2[i], vector1[i]); /* for ( ; i < elements; i++) vector1[i] = 1;*/ return OK; } static int vexpv_i(CSOUND *csound, VECTORSOPI *p) { FUNC *ftp1, *ftp2; MYFLT *vector1, *vector2; int32 i, j, n, elements, srcoffset, dstoffset, len1, len2; ftp1 = csound->FTnp2Find(csound, p->ifn1); ftp2 = csound->FTnp2Find(csound, p->ifn2); if (UNLIKELY(ftp1 == NULL)) { return csound->InitError(csound, Str("vexpv_i: ifn1 invalid table number %i"), (int) *p->ifn1); } else if (UNLIKELY(ftp2 == NULL)) { return csound->InitError(csound, Str("vexpv_i: ifn2 invalid table number %i"), (int) *p->ifn2); } /*if (*p->ifn1 == *p->ifn2) csound->Warning(csound, Str("vexpv_i: ifn1 = ifn2."));*/ vector1 = ftp1->ftable; vector2 = ftp2->ftable; len1 = (int32) ftp1->flen+1; len2 = (int32) ftp2->flen+1; elements = (int32) *p->ielements; srcoffset = (int32) *p->isrcoffset; dstoffset = (int32) *p->idstoffset; if (dstoffset < 0) { elements += dstoffset; srcoffset -= dstoffset; } else { len1 -= dstoffset; vector1 += dstoffset; } if (UNLIKELY(elements > len1)) { elements = len1; csound->Warning(csound,Str("vexpv_i: ifn1 length exceeded")); } /* elements = (elements < len1 ? elements : len1); */ if (srcoffset < 0) { n = -srcoffset; /*int i, n = -srcoffset; */ n = (n < elements ? n : elements); for (i = 0; i < n; i++) vector1[i] = FL(0.0); elements -= i; vector1 += i; } else { len2 -= srcoffset; vector2 += srcoffset; } /*n = (elements < len2 ? elements : len2);*/ if (UNLIKELY(elements > len2)) { csound->Warning(csound,Str("vexpv_i: ifn2 length exceeded")); n = len2; } else n = elements; i = 0; if (p->vector1 == p->vector2 && vector1 > vector2) { /* special case: need to reverse direction */ for (j = n; --j >= 0; i++) vector1[j] = POWER(vector2[j], vector1[j]); } for ( ; i < n; i++) vector1[i] = POWER(vector2[i], vector1[i]); return OK; } /*static int vmap(CSOUND *csound,VECTORSOP *p) { int elements = *p->kelements; MYFLT *vector1 = p->vector1, *vector2 = p->vector2; do { *vector1 = (vector2++)[(int)*vector1]; vector1++; } while (--elements); return OK; }*/ static int vmap_i(CSOUND *csound,VECTORSOPI *p) { FUNC *ftp1, *ftp2; MYFLT *vector1, *vector2; int32 i, n, elements, srcoffset, dstoffset, len1, len2; ftp1 = csound->FTnp2Find(csound, p->ifn1); ftp2 = csound->FTnp2Find(csound, p->ifn2); if (UNLIKELY(*p->ifn1 == *p->ifn2)) { return csound->InitError(csound, Str("vmap: Error: ifn1 and ifn2 can not " "be the same")); } if (UNLIKELY(ftp1 == NULL)) { return csound->InitError(csound, Str("vmap: ifn1 invalid table number %i"), (int) *p->ifn1); } else if (UNLIKELY(ftp2 == NULL)) { return csound->InitError(csound, Str("vmap: ifn2 invalid table number %i"), (int) *p->ifn2); } /* if (*p->ifn1 == *p->ifn2) csound->Warning(csound, Str("vcopy_i: ifn1 = ifn2."));*/ vector1 = ftp1->ftable; vector2 = ftp2->ftable; len1 = (int32) ftp1->flen+1; len2 = (int32) ftp2->flen+1; elements = (int32) *p->ielements; srcoffset = (int32) *p->isrcoffset; dstoffset = (int32) *p->idstoffset; if (dstoffset < 0) { elements += dstoffset; srcoffset -= dstoffset; } else { len1 -= dstoffset; vector1 += dstoffset; } if (UNLIKELY(elements > len1)) { elements = len1; csound->Warning(csound,Str("vmap: ifn1 length exceeded")); } /* elements = (elements < len1 ? elements : len1);*/ if (srcoffset < 0) { /*int i, */n = -srcoffset; n = (n < elements ? n : elements); for (i = 0; i < n; i++) vector1[i] = FL(0.0); elements -= i; vector1 += i; } else { len2 -= srcoffset; vector2 += srcoffset; } /* n = (elements < len2 ? elements : len2);*/ if (UNLIKELY(elements > len2)) { csound->Warning(csound,Str("vmap: ifn2 length exceeded")); n = len2; } else n = elements; i = 0; for ( ; i < n; i++) vector1[i] = vector2[(int)vector1[i]]; for ( ; i < elements; i++) vector1[i] = FL(0.0); return OK; } static int vlimit_set(CSOUND *csound,VLIMIT *p) { FUNC *ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound,p->ifn)) != NULL)) { p->vector = ftp->ftable; p->elements = (int) *p->ielements; } else return NOTOK; if (UNLIKELY(p->elements > (int)ftp->flen )) { return csound->InitError(csound, Str("vectorop: invalid num of elements")); } return OK; } static int vlimit(CSOUND *csound,VLIMIT *p) { int elements = p->elements; MYFLT *vector = p->vector; MYFLT min = *p->kmin, max = *p->kmax; do { *vector = (*vector > min) ? ((*vector < max) ? *vector : max) : min; vector++; } while (--elements); return OK; } /*-----------------------------*/ static int vport_set(CSOUND *csound,VPORT *p) { FUNC *ftp; int elements; MYFLT /* *vector,*/ *yt1,*vecInit = NULL; if (LIKELY((ftp = csound->FTnp2Find(csound,p->ifn)) != NULL)) { p->vector = ftp->ftable; elements = (p->elements = (int) *p->ielements); if (UNLIKELY(elements > (int)ftp->flen) ) return csound->InitError(csound, Str("vport: invalid table length or " "num of elements")); } else return csound->InitError(csound, Str("vport: invalid table")); if (LIKELY(*p->ifnInit)) { if (LIKELY((ftp = csound->FTnp2Find(csound,p->ifnInit)) != NULL)) { vecInit = ftp->ftable; if (UNLIKELY(elements > (int)ftp->flen) ) return csound->InitError(csound, Str("vport: invalid init table length" " or num of elements")); } else return csound->InitError(csound, Str("vport: invalid init table")); } if (p->auxch.auxp == NULL) csound->AuxAlloc(csound, elements * sizeof(MYFLT), &p->auxch); yt1 = (p->yt1 = (MYFLT *) p->auxch.auxp); if (vecInit) { do { *yt1++ = *vecInit++; } while (--elements); } else { do { *yt1++ = FL(0.0); } while (--elements); } p->prvhtim = -FL(100.0); return OK; } static int vport(CSOUND *csound,VPORT *p) { int elements = p->elements; MYFLT *vector = p->vector, *yt1 = p->yt1, c1, c2; if (p->prvhtim != *p->khtim) { p->c2 = (MYFLT)pow(0.5, (double)CS_ONEDKR / *p->khtim); p->c1 = FL(1.0) - p->c2; p->prvhtim = *p->khtim; } c1 = p->c1; c2 = p->c2; do { *vector = (*yt1 = c1 * *vector + c2 * *yt1); vector++; yt1++; } while (--elements); return OK; } /*-------------------------------*/ static int vwrap(CSOUND *csound,VLIMIT *p) { int elements = p->elements; MYFLT *vector = p->vector; MYFLT min = *p->kmin, max = *p->kmax; if (min >= max) { MYFLT average = (min+max)/2; do { *vector++ = average; } while (--elements); } else { do { if (*vector >= max) { *vector = min + FMOD(*vector - min, FABS(min-max)); vector++; } else { *vector = max - FMOD(max - *vector, FABS(min-max)); vector++; } } while (--elements); } return OK; } static int vmirror(CSOUND *csound,VLIMIT *p) { int elements = p->elements; MYFLT *vector = p->vector; MYFLT min = *p->kmin, max = *p->kmax; if (min >= max) { MYFLT average = (min+max)* FL(0.50); do { *vector++ = average; } while (--elements); } else { do { while (!((*vector <= max) && (*vector >=min))) { if (*vector > max) *vector = max + max - *vector; else *vector = min + min - *vector; } vector++; } while (--elements); } return OK; } #define RNDMUL 15625 // #define MASK16 0xFFFF // #define MASK15 0x7FFF #define BIPOLAR 0x7FFFFFFF /* Constant to make bipolar */ #define RIA 16807 /* multiplier */ #define RIM 0x7FFFFFFFL /* 2**31 - 1 */ #define dv2_31 (FL(4.656612873077392578125e-10)) static int32 randint31(int32 seed31) { uint32 rilo, rihi; rilo = RIA * (int32)(seed31 & 0xFFFF); rihi = RIA * (int32)((uint32)seed31 >> 16); rilo += (rihi & 0x7FFF) << 16; if (rilo > RIM) { rilo &= RIM; ++rilo; } rilo += rihi >> 15; if (rilo > RIM) { rilo &= RIM; ++rilo; } return (int32)rilo; } static int vrandh_set(CSOUND *csound,VRANDH *p) { FUNC *ftp; int elements = 0; MYFLT *num1; uint32 seed; int32 r; if (*p->iseed >= FL(0.0)) { /* new seed:*/ if (*p->iseed > FL(1.0)) { /* Seed from current time */ seed = csound->GetRandomSeedFromTime(); if (*p->isize == 0) { p->rand = (int32) (seed & 0xFFFFUL); } else { p->rand = (int32) (seed % 0x7FFFFFFEUL) + 1L; } csound->Message(csound, Str("vrandh: Seeding from current time %u\n"), seed); } else { if (*p->isize == 0) p->rand = 0xffff&(short)(*p->iseed * 32768L); /* init rand integ */ else p->rand = (int32) (*p->iseed * FL(2147483648.0)); } if ((ftp = csound->FTnp2Find(csound,p->ifn)) != NULL) { p->elements = (int) *p->ielements; p->offset = (int) *p->idstoffset; } else return csound->InitError(csound, Str("vrandh: Invalid table.")); if (UNLIKELY(*p->idstoffset >= (int)ftp->flen)) return csound->InitError(csound, Str("vrandh: idstoffset is greater than" " table length.")); p->vector = ftp->ftable + p->offset; if (UNLIKELY(p->elements + p->offset > (int)ftp->flen)) { csound->Warning(csound, Str("randh: Table length exceeded, " "last elements discarded.")); p->elements = p->offset - ftp->flen; } } if (p->auxch.auxp == NULL) csound->AuxAlloc(csound, p->elements * sizeof(MYFLT), &p->auxch); num1 = (p->num1 = (MYFLT *) p->auxch.auxp); r = p->rand; elements = p->elements; do { if (*p->isize == 0) { *num1++ = (MYFLT) ((short) r) * DV32768; r = (int32) (r & 0xFFFFUL); } else { // 31-bit PRNG *num1++ = (MYFLT)((int32)((unsigned)r<<1)-BIPOLAR) * dv2_31; r = randint31( r); } } while (--elements); p->phs = 0; p->rand = r; return OK; } static int vrandh(CSOUND *csound,VRANDH *p) { MYFLT *vector = p->vector, *num1 = p->num1; MYFLT value = *p->krange; int elements = p->elements; int32 r; do { *vector++ = (*num1++ * value) + *p->ioffset; } while (--elements); p->phs += (int32)(*p->kcps * CS_KICVT); if (p->phs >= MAXLEN) { p->phs &= PHMASK; elements = p->elements; vector = p->vector; num1 = p->num1; r = p->rand; do { if (*p->isize == 0) { *num1++ = (MYFLT) ((short) r) * DV32768; r *= RNDMUL; r += 1; } else { // 31-bit PRNG *num1++ = (MYFLT)((int32)((unsigned)r<<1)-BIPOLAR) * dv2_31; r = randint31(r); } } while (--elements); p->rand = r; } return OK; } static int vrandi_set(CSOUND *csound,VRANDI *p) { FUNC *ftp; int elements = 0; MYFLT *dfdmax, *num1, *num2; uint32 seed; int32 r; if (*p->iseed >= FL(0.0)) { /* new seed:*/ if (*p->iseed > FL(1.0)) { /* Seed from current time */ seed = csound->GetRandomSeedFromTime(); if (*p->isize == 0) { p->rand = (int32) (seed & 0xFFFFUL); } else { p->rand = (int32) (seed % 0x7FFFFFFEUL) + 1L; } csound->Message(csound, Str("vrandi: Seeding from current time %u\n"), seed); } else { if (*p->isize == 0) p->rand = 0xffff&(short)(*p->iseed * 32768L); /* init rand integ */ else p->rand = (int32) (*p->iseed * FL(2147483648.0)); } if (LIKELY((ftp = csound->FTnp2Find(csound,p->ifn)) != NULL)) { p->elements = (int) *p->ielements; p->offset = (int) *p->idstoffset; } else return csound->InitError(csound, Str("vrandi: Invalid table.")); if (UNLIKELY(p->offset >= (int)ftp->flen)) return csound->InitError(csound, Str("vrandi: idstoffset is greater than" "table length.")); p->vector = ftp->ftable + p->offset; if (UNLIKELY(p->elements > (int)ftp->flen)) { csound->Warning(csound, Str("vrandi: Table length exceeded, " "last elements discarded.")); p->elements = p->offset - ftp->flen; } } if (p->auxch.auxp == NULL) { csound->AuxAlloc(csound, p->elements * sizeof(MYFLT) * 3, &p->auxch); } elements = p->elements; num1 = (p->num1 = (MYFLT *) p->auxch.auxp); num2 = (p->num2 = &num1[elements]); dfdmax = (p->dfdmax = &num1[elements * 2]); r = p->rand; do { *num1 = FL(0.0); if (*p->isize == 0) { *num2 = (MYFLT) ((short) r) * DV32768; r = (int32) (r & 0xFFFFUL); } else { // 31-bit PRNG *num2 = (MYFLT)((int32)((unsigned)r<<1)-BIPOLAR) * dv2_31; r = randint31(r); } *dfdmax++ = (*num2++ - *num1++) / FMAXLEN; } while (--elements); p->phs = 0; p->rand = r; return OK; } static int vrandi(CSOUND *csound,VRANDI *p) { MYFLT *vector = p->vector, *num1 = p->num1, *num2, *dfdmax = p->dfdmax; MYFLT value = *p->krange; int elements = p->elements; int32 r; do { *vector++ = (((MYFLT)*num1++ + ((MYFLT)p->phs * *dfdmax++)) * value) + *p->ioffset; } while (--elements); p->phs += (int32)(*p->kcps * CS_KICVT); if (p->phs >= MAXLEN) { p->phs &= PHMASK; elements = p->elements; vector = p->vector; num1 = p->num1; num2 = p->num2; dfdmax = p->dfdmax; r = p->rand; do { *num1 = *num2; if (*p->isize == 0) { *num2 = (MYFLT) ((short) r) * DV32768; r *= RNDMUL; /* recalc random */ r += 1; } else { // 31-bit PRNG *num2 = (MYFLT)((int32)((unsigned)r<<1)-BIPOLAR) * dv2_31 ; r = randint31(r); } *dfdmax++ = ((MYFLT)*num2++ - (MYFLT)*num1++) / FMAXLEN; } while (--elements); p->rand = r; } return OK; } static int vecdly_set(CSOUND *csound, VECDEL *p) { FUNC *ftp; int elements = (p->elements = (int) *p->ielements), j; int32 n; if (LIKELY((ftp = csound->FTnp2Find(csound,p->ifnOut)) != NULL)) { p->outvec = ftp->ftable; elements = (p->elements = (int) *p->ielements); if (UNLIKELY( elements > (int)ftp->flen )) return csound->InitError(csound, Str("vecdelay: invalid num of elements")); } else return csound->InitError(csound, Str("vecdly: invalid output table")); if (LIKELY((ftp = csound->FTnp2Find(csound,p->ifnIn)) != NULL)) { p->invec = ftp->ftable; if (UNLIKELY(elements > (int)ftp->flen)) return csound->InitError(csound, Str("vecdelay: invalid num of elements")); } else return csound->InitError(csound, Str("vecdly: invalid input table")); if (LIKELY((ftp = csound->FTnp2Find(csound,p->ifnDel)) != NULL)) { p->dlyvec = ftp->ftable; if (UNLIKELY( elements > (int)ftp->flen )) return csound->InitError(csound, Str("vecdelay: invalid num of elements")); } else return csound->InitError(csound, Str("vecdly: invalid delay table")); n = (p->maxd = (int32) (*p->imaxd * CS_EKR)); if (n == 0) n = (p->maxd = 1); if (!*p->istod) { if (p->aux.auxp == NULL || (unsigned int)(elements * sizeof(MYFLT *) + n * elements * sizeof(MYFLT) + elements * sizeof(int32)) > p->aux.size) { csound->AuxAlloc(csound, elements * sizeof(MYFLT *) + n * elements * sizeof(MYFLT) + elements * sizeof(int32), &p->aux); p->buf= (MYFLT **) p->aux.auxp; for (j = 0; j < elements; j++) { p->buf[j] = (MYFLT*) ((char*) p->aux.auxp + sizeof(MYFLT*) * elements + sizeof(MYFLT) * n * j); } p->left = (int32*) ((char*) p->aux.auxp + sizeof(MYFLT*) * elements + sizeof(MYFLT) * n * elements); } else { MYFLT **buf= p->buf; for (j = 0; j < elements; j++) { MYFLT *temp = buf[j]; int count = n; /* memset(buf[j], 0, sizeof(MYFLT)*n); */ do { *temp++ = FL(0.0); } while (--count); p->left[j] = 0; } } } return OK; } static int vecdly(CSOUND *csound,VECDEL *p) { int32 maxd = p->maxd, *indx=p->left, v1, v2; MYFLT **buf = p->buf, fv1, fv2, *inVec = p->invec; MYFLT *outVec = p->outvec, *dlyVec = p->dlyvec; int elements = p->elements; if (UNLIKELY(buf==NULL)) { return csound->InitError(csound, Str("vecdly: not initialised")); } do { (*buf)[*indx] = *inVec++; fv1 = *indx - *dlyVec++ * CS_EKR; while (fv1 < FL(0.0)) fv1 += (MYFLT)maxd; while (fv1 >= (MYFLT)maxd) fv1 -= (MYFLT)maxd; if (fv1 < maxd - 1) fv2 = fv1 + 1; else fv2 = FL(0.0); v1 = (int32)fv1; v2 = (int32)fv2; *outVec++ = (*buf)[v1] + (fv1 - v1) * ((*buf)[v2]-(*buf)[v1]); ++buf; if (++(*indx) == maxd) *indx = 0; ++indx; } while (--elements); return OK; } static int vseg_set(CSOUND *csound,VSEG *p) { TSEG *segp; int nsegs; MYFLT **argp, dur, *vector; FUNC *nxtfunc, *curfunc, *ftp; int32 flength; if (!(p->INCOUNT & 1)) { return csound->InitError(csound, Str("incomplete number of input arguments")); } nsegs = ((p->INCOUNT-2) >> 1); /* count segs & alloc if nec */ if ((segp = (TSEG *) p->auxch.auxp) == NULL) { csound->AuxAlloc(csound, (int32)(nsegs+1)*sizeof(TSEG), &p->auxch); p->cursegp = segp = (TSEG *) p->auxch.auxp; (segp+nsegs)->cnt = MAXPOS; } argp = p->argums; if (UNLIKELY((nxtfunc = csound->FTnp2Find(csound,*argp++)) == NULL)) return NOTOK; if ((ftp = csound->FTnp2Find(csound,p->ioutfunc)) != NULL) { p->vector = ftp->ftable; p->elements = (int) *p->ielements; } else return NOTOK; if (UNLIKELY( p->elements > (int)ftp->flen )) return csound->InitError(csound, Str("vlinseg/vexpseg: invalid num. of elements")); /* memset(p->vector, 0, sizeof(MYFLT)*p->elements); */ vector = p->vector; flength = p->elements; do { *vector++ = FL(0.0); } while (--flength); if (UNLIKELY(**argp <= FL(0.0))) return NOTOK; /* if idur1 <= 0, skip init */ p->cursegp = segp; /* else proceed from 1st seg */ segp--; do { segp++; /* init each seg .. */ curfunc = nxtfunc; dur = **argp++; if (UNLIKELY((nxtfunc = csound->FTnp2Find(csound,*argp++)) == NULL)) return NOTOK; if (dur > FL(0.0)) { segp->d = dur * CS_EKR; segp->function = curfunc; segp->nxtfunction = nxtfunc; segp->cnt = (int32) MYFLT2LRND(segp->d); } else break; /* .. til 0 dur or done */ } while (--nsegs); segp++; segp->d = FL(0.0); segp->cnt = MAXPOS; /* set last cntr to infin */ segp->function = nxtfunc; segp->nxtfunction = nxtfunc; return OK; } static int vlinseg(CSOUND *csound,VSEG *p) { TSEG *segp; MYFLT *curtab, *nxttab,curval, nxtval, durovercnt=FL(0.0), *vector; int32 flength, upcnt; if (UNLIKELY(p->auxch.auxp==NULL)) { return csound->InitError(csound, Str("tableseg: not initialised")); } segp = p->cursegp; curtab = segp->function->ftable; nxttab = segp->nxtfunction->ftable; upcnt = (int32)segp->d-segp->cnt; if (upcnt > 0) durovercnt = segp->d/upcnt; while (--segp->cnt < 0) p->cursegp = ++segp; flength = p->elements; vector = p->vector; do { curval = *curtab++; nxtval = *nxttab++; if (durovercnt > FL(0.0)) *vector++ = (curval + ((nxtval - curval) / durovercnt)); else *vector++ = curval; } while (--flength); return OK; } static int vexpseg(CSOUND *csound,VSEG *p) { TSEG *segp; MYFLT *curtab, *nxttab,curval, nxtval, cntoverdur=FL(0.0), *vector; int32 flength, upcnt; if (UNLIKELY(p->auxch.auxp==NULL)) { return csound->InitError(csound, Str("tablexseg: not initialised")); } segp = p->cursegp; curtab = segp->function->ftable; nxttab = segp->nxtfunction->ftable; upcnt = (int32)segp->d-segp->cnt; if (upcnt > 0) cntoverdur = upcnt/ segp->d; while (--segp->cnt < 0) p->cursegp = ++segp; flength = p->elements; vector = p->vector; cntoverdur *= cntoverdur; do { curval = *curtab++; nxtval = *nxttab++; *vector++ = (curval + ((nxtval - curval) * cntoverdur)); } while (--flength); return OK; } /* ----------------------------------------------- */ #if 0 static int vphaseseg_set(CSOUND *csound,VPSEG *p) { TSEG2 *segp; int nsegs,j; MYFLT **argp, *vector; double dur, durtot = 0.0, prevphs; FUNC *nxtfunc, *curfunc, *ftp; int32 flength; nsegs = p->nsegs =((p->INCOUNT-3) >> 1); /* count segs & alloc if nec */ if ((segp = (TSEG2 *) p->auxch.auxp) == NULL) { csound->AuxAlloc(csound, (int32)(nsegs+1)*sizeof(TSEG), &p->auxch); p->cursegp = segp = (TSEG2 *) p->auxch.auxp; /* (segp+nsegs)->cnt = MAXPOS; */ } argp = p->argums; if ((nxtfunc = csound->FTnp2Find(csound,*argp++)) == NULL) return NOTOK; if ((ftp = csound->FTnp2Find(csound,p->ioutfunc)) != NULL) { p->vector = ftp->ftable; p->elements = (int) *p->ielements; } if ( p->elements > (int)ftp->flen ) return csound->InitError(csound, Str("vphaseseg: invalid num. of elements")); vector = p->vector; flength = p->elements; do { *vector++ = FL(0.0); } while (--flength); if (**argp <= FL(0.0)) return NOTOK; /* if idur1 <= 0, skip init */ /* p->cursegp = tempsegp =segp; */ /* else proceed from 1st seg */ segp--; do { segp++; /* init each seg .. */ curfunc = nxtfunc; dur = **argp++; if ((nxtfunc = csound->FTnp2Find(csound,*argp++)) == NULL) return NOTOK; if (dur > FL(0.0)) { durtot+=dur; segp->d = dur; /* * CS_EKR; */ segp->function = curfunc; segp->nxtfunction = nxtfunc; /* segp->cnt = (int32) (segp->d + .5); */ } else break; /* .. til 0 dur or done */ } while (--nsegs); segp++; segp->function = nxtfunc; segp->nxtfunction = nxtfunc; nsegs = p->nsegs; segp = p->cursegp; for (j=0; j< nsegs; j++) segp[j].d /= durtot; for (j=nsegs-1; j>= 0; j--) segp[j+1].d = segp[j].d; segp[0].d = prevphs = 0.0; for (j=0; j<= nsegs; j++) { segp[j].d += prevphs; prevphs = segp[j].d; } return OK; } static int vphaseseg(CSOUND *csound,VPSEG *p) { TSEG2 *segp = p->cursegp; double phase = *p->kphase, partialPhase = 0.0; int j, flength; MYFLT *curtab = NULL, *nxttab = NULL, curval, nxtval, *vector; while (phase >= 1.0) phase -= 1.0; while (phase < 0.0) phase = 0.0; for (j = 0; j < p->nsegs; j++) { TSEG2 *seg = &segp[j], *seg1 = &segp[j+1]; if (phase < seg1->d) { curtab = seg->function->ftable; nxttab = seg1->function->ftable; partialPhase = (phase - seg->d) / (seg1->d - seg->d); break; } } flength = p->elements; vector = p->vector; do { curval = *curtab++; nxtval = *nxttab++; *vector++ = (MYFLT) (curval + ((nxtval - curval) * partialPhase)); } while (--flength); return OK; } #endif /* ------------------------- */ static int kdel_set(CSOUND *csound,KDEL *p) { uint32 n; n = (p->maxd = (int32) (*p->imaxd * CS_EKR)); if (n == 0) n = (p->maxd = 1); if (!*p->istod) { if (p->aux.auxp == NULL || (unsigned int)(n*sizeof(MYFLT)) > p->aux.size) csound->AuxAlloc(csound, n * sizeof(MYFLT), &p->aux); else { memset(p->aux.auxp, 0, sizeof(MYFLT)*n); } p->left = 0; } return OK; } static int kdelay(CSOUND *csound,KDEL *p) { int32 maxd = p->maxd, indx, v1, v2; MYFLT *buf = (MYFLT *)p->aux.auxp, fv1, fv2; if (UNLIKELY(buf==NULL)) { return csound->InitError(csound, Str("vdelayk: not initialised")); } indx = p->left; buf[indx] = *p->kin; fv1 = indx - *p->kdel * CS_EKR; while (fv1 < FL(0.0)) fv1 += (MYFLT)maxd; while (fv1 >= (MYFLT)maxd) fv1 -= (MYFLT)maxd; if (*p->interp) { /* no interpolation */ *p->kr = buf[(int32) fv1]; } else { if (fv1 < maxd - 1) fv2 = fv1 + 1; else fv2 = FL(0.0); v1 = (int32)fv1; v2 = (int32)fv2; *p->kr = buf[v1] + (fv1 - v1) * (buf[v2]-buf[v1]); } if (++(p->left) == maxd) p->left = 0; return OK; } /* From fractals.c */ static int ca_set(CSOUND *csound,CELLA *p) { FUNC *ftp; int elements; MYFLT *currLine, *initVec = NULL; if (LIKELY((ftp = csound->FTnp2Find(csound,p->ioutFunc)) != NULL)) { p->outVec = ftp->ftable; elements = (p->elements = (int) *p->ielements); if (UNLIKELY( elements > (int)ftp->flen )) return csound->InitError(csound, Str("cella: invalid num of elements")); } else return csound->InitError(csound, Str("cella: invalid output table")); if (LIKELY((ftp = csound->FTnp2Find(csound,p->initStateFunc)) != NULL)) { initVec = (p->initVec = ftp->ftable); if (UNLIKELY(elements > (int)ftp->flen )) return csound->InitError(csound, Str("cella: invalid num of elements")); } else return csound->InitError(csound, Str("cella: invalid initial state table")); if (LIKELY((ftp = csound->FTnp2Find(csound,p->iRuleFunc)) != NULL)) { p->ruleVec = ftp->ftable; } else return csound->InitError(csound, Str("cella: invalid rule table")); if (p->auxch.auxp == NULL) csound->AuxAlloc(csound, elements * sizeof(MYFLT) * 2, &p->auxch); currLine = (p->currLine = (MYFLT *) p->auxch.auxp); p->NewOld = 0; p->ruleLen = (int) *p->irulelen; /* memcpy(currLine, initVec, sizeof(MYFLT)*elements); */ do { *currLine++ = *initVec++; } while (--elements); return OK; } static int ca(CSOUND *csound,CELLA *p) { if (*p->kreinit) { MYFLT *currLine = p->currLine, *initVec = p->initVec; int elements = p->elements; p->NewOld = 0; /* memcpy(currLine, initVec, sizeof(MYFLT)*elements); */ do { *currLine++ = *initVec++; } while (--elements); } if (*p->ktrig) { int j, elements = p->elements, jm1, ruleLen = p->ruleLen; MYFLT *actual, *previous, *outVec = p->outVec, *ruleVec = p->ruleVec; previous = &(p->currLine[elements * p->NewOld]); p->NewOld += 1; p->NewOld %= 2; actual = &(p->currLine[elements * p->NewOld]); if (*p->iradius == 1) { for (j=0; j < elements; j++) { jm1 = (j < 1) ? elements-1 : j-1; outVec[j] = previous[j]; actual[j] = ruleVec[ (int) (previous[jm1] + previous[j] + previous[(j+1) % elements] ) % ruleLen]; } } else { int jm2; for (j=0; j < elements; j++) { jm1 = (j < 1) ? elements-1 : j-1; jm2 = (j < 2) ? elements-2 : j-2; outVec[j] = previous[j]; actual[j] = ruleVec[ (int) (previous[jm2] + previous[jm1] + previous[j] + previous[(j+1) % elements] + previous[(j+2) % elements]) % ruleLen]; } } } else { int elements = p->elements; MYFLT *actual = &(p->currLine[elements * !(p->NewOld)]), *outVec = p->outVec; do { *outVec++ = *actual++ ; } while (--elements); } return OK; } #define S(x) sizeof(x) OENTRY vectorial_localops[] = { { "vtablei", S(MTABLEI), TR, 1, "", "iiiim", (SUBR)mtable_i, NULL }, { "vtablek", S(MTABLE), TR, 3, "", "kkkiz", (SUBR)mtable_set, (SUBR)mtable_k, NULL }, { "vtablea", S(MTABLE), TR, 5, "", "akkiy", (SUBR)mtable_set, NULL, (SUBR)mtable_a }, { "vtablewi", S(MTABLEIW), TB, 1, "", "iiim", (SUBR)mtablew_i, NULL }, { "vtablewk", S(MTABLEW), TB, 3, "", "kkiz", (SUBR)mtablew_set, (SUBR)mtablew_k, NULL }, { "vtablewa", S(MTABLEW), TB, 5, "", "akiy", (SUBR)mtablew_set, NULL, (SUBR)mtablew_a }, { "vtabi", S(MTABI), TR, 1, "", "iim", (SUBR)mtab_i, NULL }, { "vtabk", S(MTAB), TR, 3, "", "kiz", (SUBR)mtab_set, (SUBR)mtab_k, NULL }, { "vtaba", S(MTAB), TR, 5, "", "aiy", (SUBR)mtab_set, NULL, (SUBR)mtab_a }, { "vtabwi", S(MTABIW), TB, 1, "", "iim", (SUBR)mtabw_i, NULL }, { "vtabwk", S(MTABW), TB, 3, "", "kiz", (SUBR)mtabw_set, (SUBR)mtabw_k, NULL }, { "vtabwa", S(MTABW), TB, 5, "", "aiy", (SUBR)mtabw_set, NULL, (SUBR)mtabw_a }, { "vadd", S(VECTOROP), TB, 3, "", "ikkOO", (SUBR)vectorOp_set, (SUBR) vaddk }, { "vadd_i", S(VECTOROPI), TB, 1, "", "iiio", (SUBR) vadd_i, NULL, NULL }, { "vmult", S(VECTOROP), TB, 3, "", "ikkOO", (SUBR)vectorOp_set, (SUBR) vmultk}, { "vmult_i", S(VECTOROPI), TB, 1, "", "iiio", (SUBR) vmult_i, NULL, NULL }, { "vpow", S(VECTOROP), TB, 3, "", "ikkOO", (SUBR)vectorOp_set, (SUBR) vpowk }, { "vpow_i", S(VECTOROPI), TB, 1, "", "iiio", (SUBR) vpow_i, NULL, NULL }, { "vexp", S(VECTOROP), TB, 3, "", "ikkOO", (SUBR)vectorOp_set, (SUBR) vexpk }, { "vexp_i", S(VECTOROPI), TB, 1, "", "iiio", (SUBR) vexp_i, NULL, NULL }, { "vaddv", S(VECTORSOP), TB, 3, "", "iikOOO", (SUBR)vectorsOp_set, (SUBR) vaddvk }, { "vaddv_i", S(VECTORSOPI), TB, 1, "", "iiioo", (SUBR)vaddv_i, NULL, NULL }, { "vsubv", S(VECTORSOP), TB, 3, "", "iikOOO", (SUBR)vectorsOp_set, (SUBR) vsubvk }, { "vsubv_i", S(VECTORSOPI), TB, 1, "", "iiioo", (SUBR)vsubv_i, NULL, NULL }, { "vmultv", S(VECTORSOP), TB, 3, "", "iikOOO", (SUBR)vectorsOp_set, (SUBR) vmultvk}, { "vmultv_i", S(VECTORSOPI), TB, 1, "", "iiioo", (SUBR)vmultv_i, NULL, NULL }, { "vdivv", S(VECTORSOP), TB, 3, "", "iikOOO", (SUBR)vectorsOp_set, (SUBR) vdivvk }, { "vdivv_i", S(VECTORSOPI), TB, 1, "", "iiioo", (SUBR)vdivv_i, NULL, NULL }, { "vpowv", S(VECTORSOP), TB, 3, "", "iikOOO", (SUBR)vectorsOp_set, (SUBR) vpowvk }, { "vpowv_i", S(VECTORSOPI), TB, 1, "", "iiioo", (SUBR)vpowv_i, NULL, NULL }, { "vexpv", S(VECTORSOP), TB, 3, "", "iikOOO", (SUBR)vectorsOp_set, (SUBR) vexpvk }, { "vexpv_i", S(VECTORSOPI), TB, 1, "", "iiioo", (SUBR)vexpv_i, NULL, NULL }, { "vcopy", S(VECTORSOP), TB, 3, "", "iikOOO", (SUBR)vectorsOp_set, (SUBR) vcopy }, { "vcopy_i", S(VECTORSOP), TB, 1, "", "iiioo", (SUBR) vcopy_i, NULL, NULL}, { "vmap", S(VECTORSOPI), TB, 1, "", "iiioo", (SUBR)vmap_i, NULL, NULL }, { "vlimit", S(VLIMIT), TR, 3, "", "ikki",(SUBR)vlimit_set, (SUBR)vlimit }, { "vwrap", S(VLIMIT), TB, 3, "", "ikki",(SUBR)vlimit_set, (SUBR) vwrap }, { "vmirror", S(VLIMIT), 0, 3, "", "ikki",(SUBR)vlimit_set, (SUBR)vmirror }, { "vlinseg", S(VSEG), TB, 3, "", "iim", (SUBR)vseg_set, (SUBR)vlinseg }, { "vexpseg", S(VSEG), 0, 3, "", "iim", (SUBR)vseg_set, (SUBR)vexpseg }, { "vrandh", S(VRANDH), TB, 3, "", "ikkiovoo",(SUBR)vrandh_set, (SUBR)vrandh}, { "vrandi", S(VRANDI), TB, 3, "", "ikkiovoo",(SUBR)vrandi_set, (SUBR)vrandi }, { "vport", S(VPORT), TB, 3, "", "ikio",(SUBR)vport_set, (SUBR)vport }, { "vecdelay", S(VECDEL),0, 3, "", "iiiiio",(SUBR)vecdly_set, (SUBR)vecdly }, { "vdelayk", S(KDEL), 0, 3, "k", "kkioo",(SUBR)kdel_set, (SUBR)kdelay }, { "vcella", S(CELLA), TR, 3, "", "kkiiiiip",(SUBR)ca_set, (SUBR)ca } }; int gab_vectorial_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(vectorial_localops[0]), (int) (sizeof(vectorial_localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/gab/vectorial.h000066400000000000000000000121601321653344700173670ustar00rootroot00000000000000/* Copyright (C) 2002-2004 Gabriel Maldonado The gab library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The gab library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the gab library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Ported to csound5 by: Andres Cabrera */ #ifndef GAB_VECTORIAL_H #define GAB_VECTORIAL_H /* The follwoing from CsoundAV/newopcodes.h */ typedef struct { OPDS h; MYFLT *xndx, *xfn, *kinterp, *ixmode, *outargs[VARGMAX]; } MTABLEI; typedef struct { OPDS h; MYFLT *xndx, *xfn, *kinterp, *ixmode, *outargs[VARGMAX]; int nargs; MYFLT xbmul; long pfn, len; MYFLT *ftable; } MTABLE; typedef struct { OPDS h; MYFLT *xndx, *xfn, *ixmode, *inargs[VARGMAX]; } MTABLEIW; typedef struct { OPDS h; MYFLT *xndx, *xfn, *ixmode, *inargs[VARGMAX]; int nargs; MYFLT xbmul; long pfn, len; MYFLT *ftable; } MTABLEW; typedef struct { OPDS h; MYFLT *xndx, *xfn, *inargs[VARGMAX]; } MTABIW; typedef struct { OPDS h; MYFLT *xndx, *xfn, *inargs[VARGMAX]; int nargs; /* MYFLT xbmul; */ long pfn, len; MYFLT *ftable; } MTABW; typedef struct { OPDS h; MYFLT *xndx, *xfn, *outargs[VARGMAX]; } MTABI; typedef struct { OPDS h; MYFLT *xndx, *xfn, *outargs[VARGMAX]; int nargs; /* MYFLT xbmul; */ long pfn, len; MYFLT *ftable; } MTAB; /* The following from CSoundAV/vectorial.h */ typedef struct { OPDS h; MYFLT *ifn, *kval, *kelements, *kdstoffset, *kverbose; long /*elements,*/ len/*, dstoffset*/; MYFLT *vector; } VECTOROP; typedef struct { OPDS h; MYFLT *ifn, *kval, *ielements, *idstoffset; long /*elements,*/ len; MYFLT *vector; } VECTOROPI; typedef struct { OPDS h; MYFLT *ifn1, *ifn2, *kelements, *kdstoffset, *ksrcoffset, *kverbose; int /*elements,*/ len1, len2/*, dstoffset, srcoffset*/; MYFLT *vector1, *vector2; } VECTORSOP; typedef struct { OPDS h; MYFLT *ifn1, *ifn2, *ielements, *idstoffset, *isrcoffset; int /*elements,*/ len1, len2; MYFLT *vector1, *vector2; } VECTORSOPI; typedef struct { OPDS h; MYFLT *ifn, *kmin, *kmax, *ielements; int elements; MYFLT *vector; } VLIMIT; typedef struct { OPDS h; MYFLT *ifn, *krange, *kcps, *ielements, *idstoffset, *iseed, *isize, *ioffset; AUXCH auxch; MYFLT *vector; int elements; int offset; long phs; MYFLT *num1; long rand; } VRANDH; typedef struct { OPDS h; MYFLT *ifn, *krange, *kcps, *ielements, *idstoffset, *iseed, *isize, *ioffset; AUXCH auxch; MYFLT *vector; int elements; int offset; long phs; MYFLT *num1, *num2, *dfdmax; long rand; } VRANDI; /* TSEG definition from H/vpvoc.h */ typedef struct { FUNC *function, *nxtfunction; MYFLT d; long cnt; } TSEG; typedef struct { OPDS h; MYFLT *ioutfunc,*ielements,*argums[VARGMAX]; TSEG *cursegp; MYFLT *vector; int elements; long nsegs; AUXCH auxch; } VSEG; typedef struct { OPDS h; MYFLT *ifn, *khtim, *ielements, *ifnInit; MYFLT c1, c2, *yt1, *vector, prvhtim; int elements; AUXCH auxch; } VPORT; typedef struct { OPDS h; MYFLT *ifnOut, *ifnIn, *ifnDel, *ielements, *imaxd, *istod; AUXCH aux; MYFLT **buf, *outvec, *invec, *dlyvec; int32 *left, maxd; int elements; } VECDEL; typedef struct { FUNC *function, *nxtfunction; double d; } TSEG2; typedef struct { OPDS h; MYFLT *kphase, *ioutfunc, *ielements,*argums[VARGMAX]; TSEG2 *cursegp; MYFLT *vector; int elements; long nsegs; AUXCH auxch; } VPSEG; typedef struct { OPDS h; MYFLT *kr, *kin, *kdel, *imaxd, *istod, *interp; AUXCH aux; long left, maxd; } KDEL; typedef struct { OPDS h; MYFLT *ktrig, *kreinit, *ioutFunc, *initStateFunc, *iRuleFunc, *ielements, *irulelen, *iradius; MYFLT *currLine, *outVec, *initVec, *ruleVec; int elements, NewOld, ruleLen; AUXCH auxch; } CELLA; /* from uggab.h for vrandi, vrandh */ /* #define oneUp31Bit (double) (4.656612875245796924105750827168e-10) #define randGab (MYFLT) ((double) \ (((csound->holdrand = csound->holdrand * 214013 + 2531011) >> 1) \ & 0x7fffffff) * oneUp31Bit) #define BiRandGab (MYFLT) ((double) \ (csound->holdrand = csound->holdrand * -214013 + 2531011) * oneUp31Bit)*/ #endif csound-6.10.0/Opcodes/gendy.c000066400000000000000000000462061321653344700157570ustar00rootroot00000000000000/* gendy.c: Implementation of the dynamic stochastic synthesis generator conceived by Iannis Xenakis. Based on Nick Collins's Gendy1 ugen (SuperCollider). (c) Tito Latini, 2012 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" typedef struct { OPDS h; MYFLT *out, *kamp, *ampdist, *durdist, *adpar, *ddpar; MYFLT *minfreq, *maxfreq, *ampscl, *durscl, *initcps, *knum; MYFLT phase, amp, nextamp, dur, speed; int32 index, rand, points; AUXCH memamp, memdur; } GENDY; typedef struct { OPDS h; MYFLT *out, *kamp, *ampdist, *durdist, *adpar, *ddpar; MYFLT *minfreq, *maxfreq, *ampscl, *durscl; MYFLT *kcurveup, *kcurvedown, *initcps, *knum; MYFLT phase, amp, nextamp, dur, speed; int32 index, rand, points; AUXCH memamp, memdur; } GENDYX; typedef struct { OPDS h; MYFLT *out, *kamp, *ampdist, *durdist, *adpar, *ddpar; MYFLT *minfreq, *maxfreq, *ampscl, *durscl, *initcps, *knum; MYFLT amp, nextamp, dur, slope, midpnt, curve; int32 phase, index, rand, points; AUXCH memamp, memdur; } GENDYC; #define BIPOLAR 0x7FFFFFFF /* Constant to make bipolar */ #define dv2_31 (FL(4.656612873077392578125e-10)) #define GENDYMAXCPS 8192 /* Max number of control points */ static MYFLT gendy_distribution(CSOUND *csound, int which, MYFLT a, int32 rnd) { MYFLT c, r; if (a > FL(1.0)) a = FL(1.0); else if (a < FL(0.0001)) a = FL(0.0001); switch (which) { case 0: // linear break; case 1: // cauchy c = ATAN(FL(10.0)*a); r = (MYFLT)((int32)((unsigned)rnd<<1)-BIPOLAR) * dv2_31; r = (FL(1.0)/a) * TAN(c*r) * FL(0.1); return r; case 2: // logist c = FL(0.5)+(FL(0.499)*a); c = LOG((FL(1.0)-c)/c); r = (((MYFLT)rnd*dv2_31 - FL(0.5)) * FL(0.998)*a) + FL(0.5); r = LOG((FL(1.0)-r)/r)/c; return r; case 3: // hyperbcos c = TAN(FL(1.5692255)*a); r = TAN(FL(1.5692255)*a*(MYFLT)rnd*dv2_31)/c; r = (LOG(r*FL(0.999)+FL(0.001)) * FL(-0.1447648))*FL(2.0) - FL(1.0); return r; case 4: // arcsine c = SIN(FL(1.5707963)*a); r = SIN(PI_F * ((MYFLT)rnd*dv2_31 - FL(0.5))*a)/c; return r; case 5: // expon c = LOG(FL(1.0)-(FL(0.999)*a)); r = (MYFLT)rnd*dv2_31*FL(0.999)*a; r = (LOG(FL(1.0)-r)/c)*FL(2.0) - FL(1.0); return r; case 6: // external sig return a*FL(2.0) - FL(1.0); default: break; } r = (MYFLT)((int32)((unsigned)rnd<<1)-BIPOLAR) * dv2_31; return r; } static int gendyset(CSOUND *csound, GENDY *p) { int i; MYFLT *memamp, *memdur; p->amp = FL(0.0); p->nextamp = FL(0.0); p->phase = FL(1.0); p->speed = FL(100.0); p->index = 0; if (UNLIKELY(*p->initcps < FL(1.0))) p->points = 12; else if (UNLIKELY(*p->initcps > GENDYMAXCPS)) p->points = GENDYMAXCPS; else p->points = (int32)*p->initcps; csound->AuxAlloc(csound, p->points*sizeof(MYFLT), &p->memamp); csound->AuxAlloc(csound, p->points*sizeof(MYFLT), &p->memdur); memamp = p->memamp.auxp; memdur = p->memdur.auxp; p->rand = csoundRand31(&csound->randSeed1); for (i=0; i < p->points; i++) { p->rand = csoundRand31(&p->rand); memamp[i] = (MYFLT)((int32)((unsigned)p->rand<<1)-BIPOLAR)*dv2_31; p->rand = csoundRand31(&p->rand); memdur[i] = (MYFLT)p->rand * dv2_31; } return OK; } static int kgendy(CSOUND *csound, GENDY *p) { int knum; MYFLT *memamp, *memdur, minfreq, maxfreq, dist; knum = (int)*p->knum; memamp = p->memamp.auxp; memdur = p->memdur.auxp; minfreq = *p->minfreq; maxfreq = *p->maxfreq; if (p->phase >= FL(1.0)) { int index = p->index; p->phase -= FL(1.0); if (knum > p->points || knum < 1) knum = p->points; p->index = index = (index+1) % knum; p->amp = p->nextamp; p->rand = csoundRand31(&p->rand); dist = gendy_distribution(csound, *p->ampdist, *p->adpar, p->rand); p->nextamp = memamp[index] + *p->ampscl * dist; /* amplitude variations within the boundaries of a mirror */ if (p->nextamp < FL(-1.0) || p->nextamp > FL(1.0)) { if (p->nextamp < FL(0.0)) p->nextamp += FL(4.0); p->nextamp = FMOD(p->nextamp, FL(4.0)); if (p->nextamp > FL(1.0)) { p->nextamp = (p->nextamp < FL(3.0) ? FL(2.0) - p->nextamp : p->nextamp - FL(4.0)); } } memamp[index] = p->nextamp; p->rand = csoundRand31(&p->rand); dist = gendy_distribution(csound, *p->durdist, *p->ddpar, p->rand); p->dur = memdur[index] + *p->durscl * dist; /* time variations within the boundaries of a mirror */ if (p->dur > FL(1.0)) p->dur = FL(2.0) - FMOD(p->dur, FL(2.0)); else if (p->dur < FL(0.0)) p->dur = FL(2.0) - FMOD(p->dur + FL(2.0), FL(2.0)); memdur[index] = p->dur; p->speed = (minfreq + (maxfreq - minfreq) * p->dur) * csound->onedsr * knum; } *p->out = *p->kamp * ((FL(1.0) - p->phase) * p->amp + p->phase * p->nextamp); p->phase += p->speed; return OK; } static int agendy(CSOUND *csound, GENDY *p) { int knum; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *out, *memamp, *memdur, minfreq, maxfreq, dist; out = p->out; knum = (int)*p->knum; memamp = p->memamp.auxp; memdur = p->memdur.auxp; minfreq = *p->minfreq; maxfreq = *p->maxfreq; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nphase >= FL(1.0)) { int index = p->index; p->phase -= FL(1.0); if (knum > p->points || knum < 1) knum = p->points; p->index = index = (index+1) % knum; p->amp = p->nextamp; p->rand = csoundRand31(&p->rand); dist = gendy_distribution(csound, *p->ampdist, *p->adpar, p->rand); p->nextamp = memamp[index] + *p->ampscl * dist; if (p->nextamp < FL(-1.0) || p->nextamp > FL(1.0)) { if (p->nextamp < FL(0.0)) p->nextamp += FL(4.0); p->nextamp = FMOD(p->nextamp, FL(4.0)); if (p->nextamp > FL(1.0)) { p->nextamp = (p->nextamp < FL(3.0) ? FL(2.0) - p->nextamp : p->nextamp - FL(4.0)); } } memamp[index] = p->nextamp; p->rand = csoundRand31(&p->rand); dist = gendy_distribution(csound, *p->durdist, *p->ddpar, p->rand); p->dur = memdur[index] + *p->durscl * dist; if (p->dur > FL(1.0)) p->dur = FL(2.0) - FMOD(p->dur, FL(2.0)); else if (p->dur < FL(0.0)) p->dur = FL(2.0) - FMOD(p->dur + FL(2.0), FL(2.0)); memdur[index] = p->dur; p->speed = (minfreq + (maxfreq - minfreq) * p->dur) * csound->onedsr * knum; } out[n] = *p->kamp * ((FL(1.0) - p->phase) * p->amp + p->phase * p->nextamp); p->phase += p->speed; } return OK; } static int gendyxset(CSOUND *csound, GENDYX *p) { int i; MYFLT *memamp, *memdur; p->amp = FL(0.0); p->nextamp = FL(0.0); p->phase = FL(1.0); p->speed = FL(100.0); p->index = 0; if (UNLIKELY(*p->initcps < FL(1.0))) p->points = 12; else if (UNLIKELY(*p->initcps > GENDYMAXCPS)) p->points = GENDYMAXCPS; else p->points = (int32)*p->initcps; csound->AuxAlloc(csound, p->points*sizeof(MYFLT), &p->memamp); csound->AuxAlloc(csound, p->points*sizeof(MYFLT), &p->memdur); memamp = p->memamp.auxp; memdur = p->memdur.auxp; p->rand = csoundRand31(&csound->randSeed1); for (i=0; i < p->points; i++) { p->rand = (int32)csoundRand31(&p->rand); memamp[i] = (MYFLT)((int32)((unsigned)p->rand<<1)-BIPOLAR)*dv2_31; p->rand = csoundRand31(&p->rand); memdur[i] = (MYFLT)p->rand * dv2_31; } return OK; } static int kgendyx(CSOUND *csound, GENDYX *p) { int knum; MYFLT *memamp, *memdur, minfreq, maxfreq, dist, curve; knum = (int)*p->knum; memamp = p->memamp.auxp; memdur = p->memdur.auxp; minfreq = *p->minfreq; maxfreq = *p->maxfreq; if (p->phase >= FL(1.0)) { int index = p->index; p->phase -= FL(1.0); if (knum > p->points || knum < 1) knum = p->points; p->index = index = (index+1) % knum; p->amp = p->nextamp; p->rand = csoundRand31(&p->rand); dist = gendy_distribution(csound, *p->ampdist, *p->adpar, p->rand); p->nextamp = memamp[index] + *p->ampscl * dist; if (p->nextamp < FL(-1.0) || p->nextamp > FL(1.0)) { if (p->nextamp < FL(0.0)) p->nextamp += FL(4.0); p->nextamp = FMOD(p->nextamp, FL(4.0)); if (p->nextamp > FL(1.0)) { p->nextamp = (p->nextamp < FL(3.0) ? FL(2.0) - p->nextamp : p->nextamp - FL(4.0)); } } memamp[index] = p->nextamp; p->rand = csoundRand31(&p->rand); dist = gendy_distribution(csound, *p->durdist, *p->ddpar, p->rand); p->dur = memdur[index] + *p->durscl * dist; if (p->dur > FL(1.0)) p->dur = FL(2.0) - FMOD(p->dur, FL(2.0)); else if (p->dur < FL(0.0)) p->dur = FL(2.0) - FMOD(p->dur + FL(2.0), FL(2.0)); memdur[index] = p->dur; p->speed = (minfreq + (maxfreq - minfreq) * p->dur) * csound->onedsr * knum; } if (*p->kcurveup < FL(0.0)) *p->kcurveup = FL(0.0); if (*p->kcurvedown < FL(0.0)) *p->kcurvedown = FL(0.0); curve = ((p->nextamp - p->amp) > FL(0.0) ? *p->kcurveup : *p->kcurvedown); *p->out = *p->kamp * (p->amp + POWER(p->phase, curve) * (p->nextamp - p->amp)); p->phase += p->speed; return OK; } static int agendyx(CSOUND *csound, GENDYX *p) { int knum; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *out, *memamp, *memdur, minfreq, maxfreq, dist, curve; out = p->out; knum = (int)*p->knum; memamp = p->memamp.auxp; memdur = p->memdur.auxp; minfreq = *p->minfreq; maxfreq = *p->maxfreq; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nphase >= FL(1.0)) { int index = p->index; p->phase -= FL(1.0); if (knum > p->points || knum < 1) knum = p->points; p->index = index = (index+1) % knum; p->amp = p->nextamp; p->rand = csoundRand31(&p->rand); dist = gendy_distribution(csound, *p->ampdist, *p->adpar, p->rand); p->nextamp = memamp[index] + *p->ampscl * dist; if (p->nextamp < FL(-1.0) || p->nextamp > FL(1.0)) { if (p->nextamp < FL(0.0)) p->nextamp += FL(4.0); p->nextamp = FMOD(p->nextamp, FL(4.0)); if (p->nextamp > FL(1.0)) { p->nextamp = (p->nextamp < FL(3.0) ? FL(2.0) - p->nextamp : p->nextamp - FL(4.0)); } } memamp[index] = p->nextamp; p->rand = csoundRand31(&p->rand); dist = gendy_distribution(csound, *p->durdist, *p->ddpar, p->rand); p->dur = memdur[index] + *p->durscl * dist; if (p->dur > FL(1.0)) p->dur = FL(2.0) - FMOD(p->dur, FL(2.0)); else if (p->dur < FL(0.0)) p->dur = FL(2.0) - FMOD(p->dur + FL(2.0), FL(2.0)); memdur[index] = p->dur; p->speed = (minfreq + (maxfreq - minfreq) * p->dur) * csound->onedsr * knum; } if (*p->kcurveup < FL(0.0)) *p->kcurveup = FL(0.0); if (*p->kcurvedown < FL(0.0)) *p->kcurvedown = FL(0.0); curve = ((p->nextamp - p->amp) > FL(0.0) ? *p->kcurveup : *p->kcurvedown); out[n] = *p->kamp * (p->amp + POWER(p->phase, curve) * (p->nextamp - p->amp)); p->phase += p->speed; } return OK; } /* version with cubic interpolation based from Bhob Rainey's Gendy4 */ static int gendycset(CSOUND *csound, GENDYC *p) { int i; MYFLT *memamp, *memdur; p->amp = FL(0.0); p->nextamp = FL(0.0); p->slope = FL(0.0); p->midpnt = FL(0.0); p->curve = FL(0.0); p->phase = 0; p->index = 0; if (UNLIKELY(*p->initcps < FL(1.0))) p->points = 12; else if (UNLIKELY(*p->initcps > GENDYMAXCPS)) p->points = GENDYMAXCPS; else p->points = (int32)*p->initcps; csound->AuxAlloc(csound, p->points*sizeof(MYFLT), &p->memamp); csound->AuxAlloc(csound, p->points*sizeof(MYFLT), &p->memdur); memamp = p->memamp.auxp; memdur = p->memdur.auxp; p->rand = csoundRand31(&csound->randSeed1); for (i=0; i < p->points; i++) { p->rand = csoundRand31(&p->rand); memamp[i] = (MYFLT)((int32)((unsigned)p->rand<<1)-BIPOLAR)*dv2_31; p->rand = csoundRand31(&p->rand); memdur[i] = (MYFLT)p->rand * dv2_31; } return OK; } static int kgendyc(CSOUND *csound, GENDYC *p) { int knum; MYFLT *memamp, *memdur, minfreq, maxfreq, dist; knum = (int)*p->knum; memamp = p->memamp.auxp; memdur = p->memdur.auxp; minfreq = *p->minfreq; maxfreq = *p->maxfreq; if (p->phase <= 0) { int index = p->index; MYFLT fphase, next_midpnt; if (knum > p->points || knum < 1) knum = p->points; p->index = index = (index+1) % knum; p->amp = p->nextamp; p->rand = csoundRand31(&p->rand); dist = gendy_distribution(csound, *p->ampdist, *p->adpar, p->rand); p->nextamp = memamp[index] + *p->ampscl * dist; if (p->nextamp < FL(-1.0) || p->nextamp > FL(1.0)) { if (p->nextamp < FL(0.0)) p->nextamp += FL(4.0); p->nextamp = FMOD(p->nextamp, FL(4.0)); if (p->nextamp > FL(1.0)) { p->nextamp = (p->nextamp < FL(3.0) ? FL(2.0) - p->nextamp : p->nextamp - FL(4.0)); } } next_midpnt = (p->amp + p->nextamp) * 0.5; memamp[index] = p->nextamp; p->rand = csoundRand31(&p->rand); dist = gendy_distribution(csound, *p->durdist, *p->ddpar, p->rand); p->dur = memdur[index] + *p->durscl * dist; if (p->dur > FL(1.0)) p->dur = FL(2.0) - FMOD(p->dur, FL(2.0)); else if (p->dur < FL(0.0)) p->dur = FL(2.0) - FMOD(p->dur + FL(2.0), FL(2.0)); memdur[index] = p->dur; fphase = (minfreq + (maxfreq - minfreq) * p->dur) * knum; fphase = (fphase > FL(0.001) ? fphase : FL(0.001)); p->phase = (int32)(csound->GetSr(csound) / fphase); if (p->phase < 2) p->phase = 2; p->curve = FL(2.0) * (next_midpnt - p->midpnt - p->phase * p->slope); p->curve = p->curve / (p->phase * p->phase + p->phase); } p->phase--; *p->out = *p->kamp * p->midpnt; p->slope += p->curve; p->midpnt += p->slope; return OK; } static int agendyc(CSOUND *csound, GENDYC *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; int knum; int remain = CS_KSMPS-offset-early; MYFLT *out, *memamp, *memdur, minfreq, maxfreq, dist; out = p->out; knum = (int)*p->knum; memamp = p->memamp.auxp; memdur = p->memdur.auxp; minfreq = *p->minfreq; maxfreq = *p->maxfreq; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { memset(&out[remain+offset], '\0', early*sizeof(MYFLT)); } do { uint32_t n, nsmps = CS_KSMPS; if (p->phase <= 0) { int index = p->index; MYFLT fphase, next_midpnt; if (knum > p->points || knum < 1) knum = p->points; p->index = index = (index+1) % knum; p->amp = p->nextamp; p->rand = csoundRand31(&p->rand); dist = gendy_distribution(csound, *p->ampdist, *p->adpar, p->rand); p->nextamp = memamp[index] + *p->ampscl * dist; if (p->nextamp < FL(-1.0) || p->nextamp > FL(1.0)) { if (p->nextamp < FL(0.0)) p->nextamp += FL(4.0); p->nextamp = FMOD(p->nextamp, FL(4.0)); if (p->nextamp > FL(1.0)) { p->nextamp = (p->nextamp < FL(3.0) ? FL(2.0) - p->nextamp : p->nextamp - FL(4.0)); } } next_midpnt = (p->amp + p->nextamp) * 0.5; memamp[index] = p->nextamp; p->rand = csoundRand31(&p->rand); dist = gendy_distribution(csound, *p->durdist, *p->ddpar, p->rand); p->dur = memdur[index] + *p->durscl * dist; if (p->dur > FL(1.0)) p->dur = FL(2.0) - FMOD(p->dur, FL(2.0)); else if (p->dur < FL(0.0)) p->dur = FL(2.0) - FMOD(p->dur + FL(2.0), FL(2.0)); memdur[index] = p->dur; fphase = (minfreq + (maxfreq - minfreq) * p->dur) * knum; fphase = (fphase > FL(0.001) ? fphase : FL(0.001)); p->phase = (int32)(csound->GetSr(csound) / fphase); if (p->phase < 2) p->phase = 2; p->curve = FL(2.0) * (next_midpnt - p->midpnt - p->phase * p->slope); p->curve = p->curve / (p->phase * p->phase + p->phase); } nsmps = (remain < p->phase ? remain : p->phase); remain -= nsmps; p->phase -= nsmps; for (n=offset; nkamp * p->midpnt; p->slope += p->curve; p->midpnt += p->slope; } } while (remain); return OK; } static OENTRY gendy_localops[] = { { "gendy", 0xffff }, { "gendyx", 0xffff }, { "gendyc", 0xffff }, { "gendy.k", sizeof(GENDY), 0,3, "k", "kkkkkkkkkoO", (SUBR)gendyset, (SUBR)kgendy, (SUBR)NULL }, { "gendy.a", sizeof(GENDY), 0,5, "a", "kkkkkkkkkoO", (SUBR)gendyset, (SUBR)NULL, (SUBR)agendy }, { "gendyx.k", sizeof(GENDYX), 0,3, "k", "kkkkkkkkkkkoO", (SUBR)gendyxset, (SUBR)kgendyx, (SUBR)NULL }, { "gendyx.a", sizeof(GENDYX), 0,5, "a", "kkkkkkkkkkkoO", (SUBR)gendyxset, (SUBR)NULL, (SUBR)agendyx }, { "gendyc.k", sizeof(GENDYC), 0,3, "k", "kkkkkkkkkoO", (SUBR)gendycset, (SUBR)kgendyc, (SUBR)NULL }, { "gendyc.a", sizeof(GENDYC), 0,5, "a", "kkkkkkkkkoO", (SUBR)gendycset, (SUBR)NULL, (SUBR)agendyc } }; LINKAGE_BUILTIN(gendy_localops) csound-6.10.0/Opcodes/getftargs.c000066400000000000000000000052321321653344700166310ustar00rootroot00000000000000/* getftargs.c: Copyright (C) 2016 Guillermo Senna. This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csdl.h" typedef struct { OPDS h; STRINGDAT *Scd; MYFLT *ftable; MYFLT *ktrig; MYFLT prv_ktrig; int status; } FTARGS; static int getftargs(CSOUND *, FTARGS *); /* Inspiration for the implementation of this Opcode was taken from the following Csound Opcodes: "sprintf", "puts" and "pwd". Credit for that goes to their respective authors. */ static int getftargs_init(CSOUND *csound, FTARGS *p) { p->status = OK; if (*p->ktrig > FL(0.0)) p->status = getftargs(csound, p); p->prv_ktrig = *p->ktrig; return p->status; } static int getftargs_process(CSOUND *csound, FTARGS *p) { if (*p->ktrig != p->prv_ktrig && *p->ktrig > FL(0.0)) { p->prv_ktrig = *p->ktrig; p->status = getftargs(csound, p); } return p->status; } static int getftargs(CSOUND *csound, FTARGS *p) { FUNC *src; int32 argcnt, i, strlen = 0; if (UNLIKELY((src = csound->FTnp2Find(csound, p->ftable)) == NULL)) { return csound->PerfError(csound, p->h.insdshead, Str("table: could not find ftable %d"), (int) *p->ftable); } argcnt = src->argcnt; for (i = 1; i != argcnt; i++) strlen += snprintf(NULL, 0, "%g ", src->args[i]); p->Scd->size = strlen; if (p->Scd->data == NULL) { p->Scd->data = (char*) csound->Calloc(csound, strlen); } else p->Scd->data = (char*) csound->ReAlloc(csound, p->Scd->data, strlen); { char* curr = p->Scd->data, *const end = curr + strlen; for (i = 1; curr != end && i != argcnt; i++) { curr += snprintf(curr, end-curr, "%g ", src->args[i]); } } return OK; } static OENTRY localops[] = { { "getftargs", sizeof(FTARGS), 0, 3, "S", "ik", (SUBR)getftargs_init, (SUBR)getftargs_process } }; LINKAGE csound-6.10.0/Opcodes/grain.c000066400000000000000000000122231321653344700157410ustar00rootroot00000000000000/* grain.c: Copyright (C) 1994 Paris Smaragdis, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Granular synthesizer designed and coded by Paris Smaragdis */ /* Berklee College of Music Csound development team */ /* Copyright (c) May 1994. All rights reserved */ /* Some speed hacks added by John Fitch */ #include "stdopcod.h" #include "grain.h" static inline MYFLT Unirand(CSOUND *csound, MYFLT a) { MYFLT x; x = (MYFLT) (csound->Rand31(&(csound->randSeed1)) - 1) / FL(2147483645.0); return (x * a); } static int agsset(CSOUND *csound, PGRA *p) /* Granular U.G. set-up */ { FUNC *gftp, *eftp; int32 bufsize; MYFLT *d; if (LIKELY((gftp = csound->FTFind(csound, p->igfn)) != NULL)) p->gftp = gftp; else return NOTOK; if (LIKELY((eftp = csound->FTFind(csound, p->iefn)) != NULL)) p->eftp = eftp; else return NOTOK; p->gcount = FL(1.0); if (*p->opt == 0) p->pr = (MYFLT)(gftp->flen << gftp->lobits); else p->pr = FL(0.0); bufsize = sizeof(MYFLT) * (2L * (size_t) (CS_ESR * *p->imkglen) + (3L * CS_KSMPS)); if (p->aux.auxp == NULL || (unsigned int)bufsize > p->aux.size) csound->AuxAlloc(csound, bufsize, &p->aux); else memset(p->aux.auxp, '\0', bufsize); /* Clear any old data */ d = p->x = (MYFLT *)p->aux.auxp; d += (int)(CS_ESR * *p->imkglen) + CS_KSMPS; p->y = d; p->ampadv = IS_ASIG_ARG(p->xamp) ? 1 : 0; p->lfradv = IS_ASIG_ARG(p->xlfr) ? 1 : 0; p->dnsadv = IS_ASIG_ARG(p->xdns) ? 1 : 0; return OK; } static int ags(CSOUND *csound, PGRA *p) /* Granular U.G. a-rate main routine */ { FUNC *gtp, *etp; MYFLT *buf, *out, *rem, *gtbl, *etbl; MYFLT *xdns, *xamp, *xlfr, *temp, amp; int32 isc, isc2, inc, inc2, lb, lb2; int32 n, bufsize; int32 ekglen; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT kglen = *p->kglen; MYFLT gcount = p->gcount; /* Pick up common values to locals for speed */ if (UNLIKELY(p->aux.auxp==NULL)) goto err1; if (UNLIKELY(kglen<=FL(0.0))) return csound->PerfError(csound, p->h.insdshead, Str("grain: grain length zero")); gtp = p->gftp; gtbl = gtp->ftable; etp = p->eftp; etbl = etp->ftable; lb = gtp->lobits; lb2 = etp->lobits; buf = p->x; rem = p->y; out = p->sr; if (kglen > *p->imkglen) kglen = *p->imkglen; ekglen = (int32)(CS_ESR * kglen); /* Useful constant */ inc2 = (int32)(csound->sicvt / kglen); /* Constant for each cycle */ bufsize = CS_KSMPS + ekglen; xdns = p->xdns; xamp = p->xamp; xlfr = p->xlfr; memset(buf, '\0', bufsize*sizeof(MYFLT)); if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i = offset ; i < nsmps ; i++) { if (gcount >= FL(1.0)) { /* I wonder..... */ gcount = FL(0.0); amp = *xamp + Unirand(csound, *p->kabnd); isc = (int32) Unirand(csound, p->pr); isc2 = 0; inc = (int32) ((*xlfr + Unirand(csound, *p->kbnd)) * csound->sicvt); temp = buf + i; n = ekglen; do { *temp++ += amp * *(gtbl + (isc >> lb)) * *(etbl + (isc2 >> lb2)); isc = (isc +inc )&PHMASK; isc2 = (isc2+inc2)&PHMASK; } while (--n); } xdns += p->dnsadv; gcount += *xdns * csound->onedsr; xamp += p->ampadv; xlfr += p->lfradv; } n = bufsize; temp = rem; do { *temp = *buf++ + *(temp + CS_KSMPS); temp++; } while (--n); memcpy(&out[offset], rem, (nsmps-offset)*sizeof(MYFLT)); p->gcount = gcount; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("grain: not initialised")); } #define S(x) sizeof(x) static OENTRY localops[] = { { "grain", S(PGRA), TR, 5, "a", "xxxkkkiiio", (SUBR)agsset, NULL, (SUBR)ags } }; int grain_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/grain.h000066400000000000000000000025531321653344700157530ustar00rootroot00000000000000/* grain.h: Copyright (C) 1994 Paris Smaragdis, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Granular synthesizer designed and coded by Paris Smaragdis */ /* Berklee College of Music Csound development team */ /* Copyright (c) May 1994. All rights reserved */ typedef struct { OPDS h; MYFLT *sr, *xamp, *xlfr, *xdns, *kabnd, *kbnd, *kglen; MYFLT *igfn, *iefn, *imkglen, *opt; MYFLT gcount; MYFLT pr; AUXCH aux; MYFLT *x, *y; FUNC *gftp, *eftp; int16 dnsadv, ampadv, lfradv; } PGRA; csound-6.10.0/Opcodes/grain4.c000066400000000000000000000364371321653344700160420ustar00rootroot00000000000000/* grain4.c: Copyright (C) 1994, 1995 Allan S C Lee, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Verson 4.0 - Mar 95 */ /* Verson 4.1 - 10 Mar 95 */ /* Lifted restriction on pitch, now accept */ /* anything greater than zero */ /* Improved code in handling the warp-round */ /* pointer. */ /* Verson 4.2 - 20 Apr 95 */ /* Add optional parameter ifnenv */ /* Function table to be used for the shape of the*/ /* envelop rise and decade curve */ /* Minor changes by John Fitch Dec 1995 */ // #include "csdl.h" #include "csoundCore.h" #include "interlocks.h" #include "grain4.h" #include #define RNDMUL 15625L static MYFLT grand(GRAINV4 *); static int grainsetv4(CSOUND *csound, GRAINV4 *p) { FUNC *ftp, *ftp_env; int nvoice, cnt; int32_t tmplong1, tmplong2; MYFLT tmpfloat1; MYFLT pitch[4]; /* call ftfind() to get the function table...*/ if (LIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) != NULL)) { p->ftp = ftp; } else { return csound->InitError(csound, Str("granule_set: " "Unable to find function table")); } /* call ftfind() to get the function table for the envelop...*/ if (*p->ifnenv > 0) { if (LIKELY((ftp_env = csound->FTnp2Find(csound, p->ifnenv)) != NULL)) { p->ftp_env = ftp_env; } else { return csound->InitError(csound, Str("granule_set: Unable to find " "function table for envelope")); } } if (UNLIKELY(*p->ivoice > MAXVOICE)) { return csound->InitError(csound, Str("granule_set: Too many voices")); } if (UNLIKELY(*p->iratio <= 0)) { return csound->InitError(csound, Str("granule_set: " "iratio must be greater then 0")); } if (UNLIKELY((*p->imode != 0) && ((*p->imode != -1) && (*p->imode != 1)))) { return csound->InitError(csound, Str("granule_set: " "imode must be -1, 0 or +1")); } if (UNLIKELY(*p->ithd < 0)) { return csound->InitError(csound, Str("granule_set: Illegal ithd, " "must be greater than zero")); } if (UNLIKELY((*p->ipshift != 1) && (*p->ipshift!=2) && (*p->ipshift!=3) && (*p->ipshift!=4) && (*p->ipshift!=0) )) { return csound->InitError(csound, Str("granule_set: ipshift must be " "integer between 0 and 4")); } if (UNLIKELY(((*p->ipshift >=1) && (*p->ipshift <=4)) && (*p->ivoice < *p->ipshift))) { return csound->InitError(csound, Str("granule_set: Not enough voices " "for the number of pitches")); } if ( *p->ipshift !=FL(0.0) ) { if (UNLIKELY(*p->ipitch1 < FL(0.0) )) { return csound->InitError(csound, Str("granule_set: ipitch1 must be greater then zero")); } if (UNLIKELY(*p->ipitch2 < FL(0.0) )) { return csound->InitError(csound, Str("granule_set: ipitch2 must be greater then zero")); } if (UNLIKELY(*p->ipitch3 < FL(0.0) )) { return csound->InitError(csound, Str("granule_set: ipitch3 must be greater then zero")); } if (UNLIKELY(*p->ipitch4 < FL(0.0) )) { return csound->InitError(csound, Str("granule_set: ipitch4 must be greater then zero")); } } if (UNLIKELY((*p->igskip < 0) || (*p->igskip * CS_ESR > ftp->flen) )) { return csound->InitError(csound, Str("granule_set: must be positive and " "less than function table length")); } if (UNLIKELY(*p->igskip_os < 0)) { return csound->InitError(csound, Str("granule_set: " "igskip_os must be greater then 0")); } p->gstart = (int32)(*p->igskip * CS_ESR); p->glength = (int32)(*p->ilength * CS_ESR); p->gend = p->gstart + p->glength; if (UNLIKELY(*p->kgap < 0)) { return csound->InitError(csound, Str("granule_set: " "kgap must be greater then 0")); } if (UNLIKELY((*p->igap_os < 0) || (*p->igap_os > 100))) { return csound->InitError(csound, Str("granule_set: " "igap_os must be 0%% to 100%%")); } if (UNLIKELY(*p->kgsize < 0)) { return csound->InitError(csound, Str("granule_set: " "kgsize must be greater then 0")); } if (UNLIKELY((*p->igsize_os < 0) || (*p->igsize_os >100))) { return csound->InitError(csound, Str("granule_set: " "igsize_os must be 0%% to 100%%")); } if (UNLIKELY((*p->iatt < FL(0.0)) || (*p->idec < 0.0) || ((*p->iatt + *p->idec) > FL(100.0)))) { return csound->InitError(csound, Str("granule_set: Illegal value of iatt and/or idec")); } /* end if */ /* Initialize random number generator */ if (*p->iseed >=0) { p->grnd = (int16)(*p->iseed * FL(32768.0)); /* IV - Jul 11 2002 */ } /* Initialize variables....*/ p->gskip_os = (int32)(*p->igskip_os * CS_ESR);/* in number of samples */ p->gap_os = *p->igap_os / FL(100.0); p->gsize_os = *p->igsize_os / FL(100.0); for (nvoice = 0; nvoice < *p->ivoice; nvoice++) { p->fpnt[nvoice] = 0; p->cnt[nvoice] = 0; p->phs[nvoice] = FL(0.0); p->gskip[nvoice] = (int32)(*p->igskip * CS_ESR); p->gap[nvoice] = (int32)(*p->kgap * CS_ESR); } if (*p->igap_os != 0) { for (nvoice = 0; nvoice < *p->ivoice; nvoice++) p->gap[nvoice] += (int32)((MYFLT)p->gap[nvoice] * p->gap_os * grand(p)); } if (*p->imode == 0) { for (nvoice = 0; nvoice < *p->ivoice; nvoice++) p->mode[nvoice] = (grand(p) < 0) ? -1 : 1; } else { for (nvoice = 0; nvoice < *p->ivoice; nvoice++) p->mode[nvoice] = (int32)*p->imode; } if ((*p->ipshift >=1) && (*p->ipshift <=4)) { pitch[0] = *p->ipitch1; pitch[1] = *p->ipitch2; pitch[2] = *p->ipitch3; pitch[3] = *p->ipitch4; cnt = 0; for (nvoice = 0; nvoice < *p->ivoice; nvoice++) { p->pshift[nvoice] = pitch[cnt++]; cnt = (cnt < *p->ipshift) ? cnt : 0; } } if (*p->ipshift == 0) { for (nvoice = 0; nvoice < *p->ivoice; nvoice++) { tmpfloat1 = grand(p); p->pshift[nvoice] = (tmpfloat1 ivoice; nvoice++) p->gsize[nvoice] = (int32)(*p->kgsize * CS_ESR * p->pshift[nvoice]); if (*p->igsize_os != 0) { for (nvoice = 0; nvoice < *p->ivoice; nvoice++) p->gsize[nvoice] += (int32)(p->gsize[nvoice] * p->gsize_os * grand(p)); } for (nvoice = 0; nvoice < *p->ivoice; nvoice++) p->stretch[nvoice] = p->gsize[nvoice] + p->gap[nvoice]; if (*p->igskip_os != 0) for (nvoice = 0; nvoice < *p->ivoice; nvoice++) { tmplong1 = ((p->gskip_os * grand(p)) + (MYFLT)p->gskip[nvoice]); p->gskip[nvoice] = (tmplong1 < p->gstart) ? p->gstart : tmplong1; p->gskip[nvoice]= ((p->gskip[nvoice]+p->stretch[nvoice])>(int32)p->gend) ? (int32)p->gstart : p->gskip[nvoice]; } if (*p->ithd != 0) { /* Do thresholding.... */ tmplong2 = 0; for (tmplong1=0; tmplong1< (int) ftp->flen; tmplong1++) if (fabs(ftp->ftable[tmplong1]) >= *p->ithd ) ftp->ftable[tmplong2++] = ftp->ftable[tmplong1]; ftp->flen = tmplong2; } if (p->gend > (int) ftp->flen) { return csound->InitError(csound, Str("granule_set: Illegal combination " "of igskip and ilength")); } nvoice = (int)*p->ivoice; if (UNLIKELY(*p->ilength < (20 * *p->kgsize))) csound->Warning(csound, Str("granule_set: " "WARNING * ilength may be too short * \n" " ilength should be " "greater than kgsize * max up\n" " pitch shift. Also, igsize_os " "and igskip_os should\n" " be taken into consideration.\n" "ilength is " "%f Sec, kgsize is %f Sec\n"), *p->ilength, *p->kgsize); p->clock = 0; /* init clock */ return OK; } /* end grainsetv4(p) */ static int graingenv4(CSOUND *csound, GRAINV4 *p) { FUNC *ftp, *ftp_env; MYFLT *ar, *ftbl, *ftbl_env=NULL; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int nvoice; int32 tmplong1, tmplong2, tmplong3, tmpfpnt, flen_env=0; MYFLT fract, v1, tmpfloat1; int32 att_len, dec_len, att_sus; MYFLT envlop; /* Optimisations */ int32 gstart = p->gstart; int32 gend = p->gend; int32 glength = p->glength; MYFLT iratio = *p->iratio; /* Recover parameters from previous call.... */ ftp = p->ftp; if (UNLIKELY(p->ftp==NULL)) goto err1; /* RWD fix */ ftbl = ftp->ftable; if (*p->ifnenv > 0) { ftp_env = p->ftp_env; flen_env = ftp_env->flen; ftbl_env = ftp_env->ftable; } /* Recover audio output pointer... */ ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } /* *** Start the loop .... *** */ for (n=offset; nfpnt, *cnt = p->cnt, *gskip = p->gskip; int32 *gap = p->gap, *gsize = p->gsize; int32 *stretch = p->stretch, *mode = p->mode; MYFLT *pshift = p->pshift, *phs = p->phs; ar[n] = FL(0.0); for (nvoice = 0; nvoice < *p->ivoice ; nvoice++) { if (*fpnt >= (*gsize -1)) { ar[n] += 0; /* Is this necessary?? */ *cnt +=1L; } else { fract = *phs - *fpnt; if (*mode < 0) { tmplong1 = *gskip - gstart; if (*fpnt >= tmplong1) { tmplong1= *fpnt - tmplong1; tmplong2= tmplong1/glength; tmplong1 -= tmplong2 * glength; tmpfpnt = gend - tmplong1; } else tmpfpnt = *gskip - *fpnt; } else { tmplong1 = gend - *gskip; if (*fpnt >= tmplong1) { tmplong1= *fpnt - tmplong1; tmplong2= tmplong1/glength; tmplong1 -= tmplong2 * glength; tmpfpnt = gstart + tmplong1; } else tmpfpnt = *gskip + *fpnt; } att_len = (int32)(*gsize * *p->iatt * FL(0.01)); dec_len = (int32)(*gsize * *p->idec * FL(0.01)); att_sus = *gsize - dec_len; if (*fpnt < att_sus) { tmpfloat1 = (FL(1.0) * *fpnt) / att_len; envlop = ((tmpfloat1 >=FL(1.0)) ? FL(1.0) : tmpfloat1); } else envlop = ((MYFLT)(dec_len - (MYFLT)(*fpnt - att_sus)))/((MYFLT)dec_len); v1 = *(ftbl + tmpfpnt); tmpfpnt = tmpfpnt + *mode; if (tmpfpnt < gstart) tmpfpnt = gend - (gstart - tmpfpnt) + 1; if (tmpfpnt > gend) tmpfpnt = gstart + (tmpfpnt - gend) - 1; if (*p->ifnenv > 0) { tmplong3 = (int32)(envlop * flen_env) -1L; envlop = *(ftbl_env + tmplong3); } ar[n] +=(v1 + ( *(ftbl + tmpfpnt) - v1) * fract ) * envlop ; *phs += *pshift; *fpnt = (int32)*phs; *cnt = (int32)*phs; } /* end if (*fpnt >= (*gsize -1)) */ if (*cnt >= *stretch) { *cnt = 0; *fpnt= 0; *phs = FL(0.0); /* pick up new values... */ /* Use the old value of the pshift, gsize and gap */ /* to determine the time advanced */ /* *gskip+= ((*gsize / *pshift) + *gap) * iratio; */ *gskip += (int32)((*gsize / *pshift) * iratio); if (*p->igskip_os != 0) *gskip += (int32)(p->gskip_os * grand(p)); if (*gskip >= gend) { tmplong1 = *gskip - gend; tmplong2 = tmplong1 /glength; tmplong1 -= tmplong2 * glength; *gskip = gstart + tmplong1; } if (*gskip < gstart) *gskip = gstart; if (*p->imode == 0) *mode = (grand(p) < 0) ? -1 : 1; if (*p->ipshift == 0) { tmpfloat1 = grand(p); *pshift = (tmpfloat1 < FL(0.0)) ? (tmpfloat1*FL(0.5))+FL(1.0) : tmpfloat1+FL(1.0); } *gap = (int32)(*p->kgap * CS_ESR); if (*p->igap_os != 0) { *gap += (int32)((*gap * p->gap_os) * grand(p)); } *gsize = (int32)(*p->kgsize * CS_ESR * *pshift); if (*p->igsize_os != 0) *gsize += (int32)((*gsize * p->gsize_os) * grand(p)); *stretch = *gsize + *gap; } fpnt++; cnt++; gskip++; gap++; gsize++; stretch++; mode++; pshift++; phs++; } /* p->clock++; */ ar[n] *= *p->xamp; /* increment audio pointer and multiply the xamp */ } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("grain4: not initialised")); } /* end graingenv4(p) */ /* Function return a float random number between -1 to +1 */ static MYFLT grand( GRAINV4 *p) { p->grnd *= (int)RNDMUL; p->grnd += 1; return ((MYFLT) p->grnd * DV32768); /* IV - Jul 11 2002 */ } /* end grand(p) */ #define S(x) sizeof(x) static OENTRY grain4_localops[] = { { "granule", S(GRAINV4), TR, 5, "a", "xiiiiiiiiikikiiivppppo", (SUBR)grainsetv4, NULL, (SUBR)graingenv4}, }; LINKAGE_BUILTIN(grain4_localops) csound-6.10.0/Opcodes/grain4.h000066400000000000000000000060721321653344700160370ustar00rootroot00000000000000/* grain4.h: Copyright (C) 1994, 1995 Allan S C Lee, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define MAXVOICE 128 typedef struct { OPDS h; MYFLT *ar, *xamp, *ivoice, *iratio; MYFLT *imode, *ithd, *ifn, *ipshift; MYFLT *igskip; MYFLT *igskip_os; MYFLT *ilength, *kgap, *igap_os, *kgsize, *igsize_os, *iatt, *idec; MYFLT *iseed, *ipitch1, *ipitch2, *ipitch3, *ipitch4, *ifnenv; int32 fpnt[MAXVOICE], cnt[MAXVOICE], gskip[MAXVOICE], gap[MAXVOICE]; int32 gsize[MAXVOICE], stretch[MAXVOICE], mode[MAXVOICE]; MYFLT pshift[MAXVOICE], phs[MAXVOICE]; int16 grnd; int32 clock, gskip_os; int32_t gstart, gend, glength; MYFLT gap_os, gsize_os; FUNC *ftp, *ftp_env; } GRAINV4; /* ar - audio results xamp - amplitude ivoice - number of voices iratio - ratio of the speed of the gskip pointer relative to audio sample rate. 0.5 will be half speed. imode - +1 grain pointer move forward (same direction of the gskip pointer), -1 backward (oppose direction fo the gskip pointer) or 0 for random ithd - threshold, if the sample signal is smaller then ithd, it will be skiped ifn - function table number ipshift - pitch shift control. If ipshift set to 0, pitch will be set randomly up and dow an octave. If ipshift set to 1, 2, 3 or 4, up to four different pitches can be set amount all the voices set in ivoice, optional parmaters ipitch1, ipitch2, ipitch3 and ipitch4 will be used. igskip - initial skip from the beginning of the function table in sec. igskip_os - gskip pointer random offset in sec, 0 will be no offset. ilength - length of the table to be used start from igskip in sec. kgap - gap in sec. igap_os - gap random offset in % of the gap size, 0 will be no offset. kgsize - grain size in sec. igsize_os - grain size random offset in % of grain size. iatt - attack in % of grain size. idec - decade in % of grain size. [iseed] - optional, seed for the random number generator, default is 0.5. [ipitch1], [ipitch2], [ipitch3], [ipitch4] - optional, pitch shift parameter if ipshift set to 1, 2, 3 or 4. Range: 0.1 (down 10 octave) to 10 (up 10 octave). Default value is 1, original pitch. [ifnenv] Optional function table number to be used to generate the shape of the rise and decade of envlop. */ csound-6.10.0/Opcodes/harmon.c000066400000000000000000000422001321653344700161230ustar00rootroot00000000000000/* harmon.c: Copyright (C) 1996 Barry Vercoe This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "interlocks.h" #include typedef struct { MYFLT *srcp; int32 cntr; } PULDAT; typedef struct { MYFLT *kfrq; int32 phase, phsinc; } VOCDAT; #define PULMAX 8 #define VOCMAX 4 typedef struct { OPDS h; MYFLT *ar, *asig, *koct, *kfrq1, *kfrq2; MYFLT *kfrq3, *kfrq4, *icpsmode, *ilowest, *ipolarity; //4 // or MYFLT *kfrq3, *icpsmode, *ilowest, *ipolarity, *dummy; //3 // or MYFLT *icpsmode, *ilowest, *ipolarity, *dummy, *dummy1; //2 //Local int16 nbufsmps, n2bufsmps, period, cpsmode, polarity, poslead; MYFLT prvoct, minoct, sicvt; MYFLT *bufp, *midp, *inp1, *inp2; MYFLT *pulsbuf[4], *sigmoid, *curpuls; MYFLT vocamp, vocinc, ampinc; PULDAT puldat[PULMAX], *endp, *limp; VOCDAT vocdat[VOCMAX], *vlim; int16 pbufcnt, maxprd, pulslen, switching; AUXCH auxch; int hmrngflg; } HARM234; /* static void print_data(HARM234* p, int x) */ /* { */ /* printf("DATA %d\n=======\n", x); */ /* printf("nbufsmps, n2bufsmps, period, cpsmode, polarity, poslead " */ /* "= (%d,%d,%d,%d,%d,%d\n", */ /* p->nbufsmps, p->n2bufsmps, p->period, p->cpsmode, p->polarity, */ /* p->poslead); */ /* printf("prvoct, minoct, sicvt = %f, %f, %f\n", */ /* p->prvoct, p->minoct, p->sicvt); */ /* //MYFLT *bufp, *midp, *inp1, *inp2; */ /* //MYFLT *pulsbuf[4], *sigmoid, *curpuls; */ /* printf("vocamp, vocinc, ampinc = %f, %f, %f\n", */ /* p->vocamp, p->vocinc, p->ampinc); */ /* //PULDAT puldat[PULMAX], *endp, *limp; */ /* //VOCDAT vocdat[VOCMAX], *vlim; */ /* printf("pbufcnt, maxprd, pulslen, switching = %d, %d, %d, %d, %d\n", */ /* p->pbufcnt, p->maxprd, p->pulslen, p->switching, p->hmrngflg); */ /* //AUXCH auxch; */ /* //int hmrngflg; */ /* printf("pulse: %p %p %p %p; %d %d %d %d\n", */ /* p->puldat[0].srcp, p->puldat[1].srcp, */ /* p->puldat[2].srcp, p->puldat[3].srcp, */ /* p->puldat[0].cntr, p->puldat[1].cntr, */ /* p->puldat[2].cntr, p->puldat[3].cntr); */ /* printf("voc: (%p %d %d) (%p %d %d) (%p %d %d) (%p %d %d)\n", */ /* p->vocdat[0].kfrq, p->vocdat[0].phase, p->vocdat[0].phsinc, */ /* p->vocdat[1].kfrq, p->vocdat[1].phase, p->vocdat[1].phsinc, */ /* p->vocdat[2].kfrq, p->vocdat[2].phase, p->vocdat[2].phsinc, */ /* p->vocdat[3].kfrq, p->vocdat[3].phase, p->vocdat[3].phsinc); */ /* printf("output: %f %f %f %f ...\n", */ /* p->ar[0], p->ar[1], p->ar[2], p->ar[3]); */ /* } */ #define PBUFS 4 #define PBMSK 0x3 #define SLEN 256 #define LCNT 75 static int hm234set(CSOUND *csound, HARM234 *p) { MYFLT minoct = p->minoct; p->hmrngflg = 0; /*if (p->auxch.auxp == NULL || minoct < p->minoct ) */ { MYFLT minfrq = POWER(FL(2.0), minoct) * ONEPT; int16 nbufs = (int16)(csound->ekr * 3 / minfrq) + 1;/* recalc max pulse prd */ int16 nbufsmps = nbufs * CS_KSMPS; int16 maxprd = (int16)(csound->esr * 2 / minfrq); /* incl sigmoid ends */ int16 cnt; int32 totalsiz = nbufsmps * 2 + maxprd * 4 + (SLEN+1); MYFLT *pulsbuf, *sigp; /* & realloc buffers */ csound->AuxAlloc(csound, totalsiz * sizeof(MYFLT), &p->auxch); p->bufp = (MYFLT *) p->auxch.auxp; p->midp = p->bufp + nbufsmps; /* each >= maxprd * 3 */ pulsbuf = p->midp + nbufsmps; p->pulsbuf[0] = pulsbuf; pulsbuf += maxprd; p->pulsbuf[1] = pulsbuf; pulsbuf += maxprd; p->pulsbuf[2] = pulsbuf; pulsbuf += maxprd; p->pulsbuf[3] = pulsbuf; pulsbuf += maxprd; /* cnt must = PBUFS */ p->sigmoid = sigp = pulsbuf; for (cnt = 0; cnt < SLEN+1; cnt++) /* make sigmoid inplace */ *sigp++ = (FL(1.0) - COS(PI_F * cnt / SLEN)) * FL(0.5); p->maxprd = maxprd; p->nbufsmps = nbufsmps; p->n2bufsmps = nbufsmps * 2; } //p->minoct = minoct; p->sicvt = FL(65536.0) * csound->onedsr; //printf("sicvt = %f\n", p->sicvt); // p->polarity = (int16)*p->ipolarity; p->poslead = 0; p->inp1 = p->bufp; p->inp2 = p->midp; p->endp = p->puldat; /* nothing in PULDAT array */ p->limp = p->puldat + PULMAX; p->prvoct = FL(0.0); p->period = 0; p->curpuls = NULL; p->pbufcnt = 0; p->vocamp = FL(0.0); /* begin unvoiced */ p->ampinc = FL(10.0) * csound->onedsr; /* .1 sec lin ramp for uv to v */ //printf("ampinc = %f\n", p->ampinc); p->switching = 0; return OK; } static int harmon234(CSOUND *csound, HARM234 *p) { MYFLT *outp, *dirp; MYFLT *inp1, *inp2; MYFLT koct, vocamp, diramp; PULDAT *endp; VOCDAT *vdp; int16 nsmps = CS_KSMPS, oflow = 0; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; //print_data(p, 1); if ((koct = *p->koct) != p->prvoct) { /* if new pitch estimate */ if (koct >= p->minoct) { /* above requested low */ MYFLT cps = POWER(FL(2.0), koct) * ONEPT; /* recalc pulse period */ p->period = (int16) (CS_ESR / cps); if (!p->cpsmode) p->sicvt = cps * FL(65536.0) * csound->onedsr; /* k64dsr;*/ } p->prvoct = koct; } inp1 = p->inp1; inp2 = p->inp2; if (UNLIKELY(offset)) { memset(inp1, '\0', offset*sizeof(MYFLT)); memset(inp2, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&inp1[nsmps], '\0', early*sizeof(MYFLT)); memset(&inp2[nsmps], '\0', early*sizeof(MYFLT)); } memcpy(&inp1[offset], &p->asig[offset], sizeof(MYFLT)*(nsmps-offset)); memcpy(&inp2[offset], &p->asig[offset], sizeof(MYFLT)*(nsmps-offset)); inp1 += nsmps-offset; inp2 += nsmps-offset; //for (srcp = q->asig, nsmps = CS_KSMPS; nsmps--; ) // *inp1++ = *inp2++ = *srcp++; /* dbl store the wavform */ //print_data(p, 2); if (koct >= p->minoct) { /* PERIODIC: find the pulse */ MYFLT val0, *buf0, *p0, *plim, *x; int16 period, triprd, xdist; period = p->period; /* set srch range of 2 periods */ triprd = period * 3; p0 = inp2 - triprd; /* btwn 3 prds back & 1 prd back */ plim = inp2 - period; buf0 = p->bufp; if (UNLIKELY(p0 < buf0)) p0 = buf0; x = p0; /* locate first zero crossing */ if ((val0 = *x++) == FL(0.0)) while (*x == FL(0.0) && ++x < plim); /* if no signal in this range */ else if (val0 > FL(0.0)) while (*x > 0. && ++x < plim); /* or unipolar with no z-crossing */ else while (*x < FL(0.0) && ++x < plim); if (x >= plim) goto nonprd; /* then non-periodic */ if (p->polarity > 0) { MYFLT pospk = FL(0.0); /* POSITIVE polarity: */ MYFLT *posp = NULL; for ( ; x < plim; x++) { /* find ensuing max val */ MYFLT val = *x; if (val > pospk) { pospk = val; posp = x; } } if (posp == NULL) goto nonprd; for (x = posp; x >= buf0 && *x > FL(0.0); x--); /* & its preceding z-crossing */ xdist = posp - x; } else if (p->polarity < 0) { MYFLT negpk = FL(0.0); /* NEGATIVE polarity: */ MYFLT *negp = NULL; for ( ; x < plim; x++) { /* find ensuing min val */ MYFLT val = *x; if (val < negpk) { negpk = val; negp = x; } } if (negp == NULL) goto nonprd; for (x = negp; x >= buf0 && *x < FL(0.0); x--); /* & its preceding z-crossing */ xdist = negp - x; } else { MYFLT pospk, negpk, *posp, *negp; /* NOT SURE: */ MYFLT *poscross, *negcross; int16 posdist, negdist; pospk = negpk = FL(0.0); posp = negp = NULL; for ( ; x < plim; x++) { /* find ensuing max & min vals */ MYFLT val = *x; if (val > FL(0.0)) { if (val > pospk) { pospk = val; posp = x; } } else if (val < negpk) { negpk = val; negp = x; } } if (posp == NULL || negp == NULL) goto nonprd; for (x = posp; x >= buf0 && *x > FL(0.0); x--); /* & their preceding z-crossings */ posdist = posp - x; poscross = x; for (x = negp; x >= buf0 && *x < FL(0.0); x--); negdist = negp - x; negcross = x; if (pospk / posdist > -negpk / negdist) { /* find z-cross with grtst slope to peak */ if (UNLIKELY(p->poslead < LCNT)) { /* and consistent polarity */ if (p->poslead == 1) csound->Warning(csound, Str("harm signal has positive lead\n")); p->poslead += 1; } } else { if (UNLIKELY(p->poslead > -LCNT)) { if (p->poslead == -1) csound->Warning(csound, Str("harm signal has negative lead\n")); p->poslead -= 1; } } if (p->poslead >= 0) { /* use this as pulse beginning */ x = poscross; xdist = posdist; } else { x = negcross; xdist = negdist; } } if (x != p->curpuls) { /* if pulse positn is new */ int16 nn, pulslen, sigdist, ndirect; MYFLT *bufp, signdx, siginc; MYFLT *z, zval; p->curpuls = x; /* record this new positn */ z = x + period; /* and from estimated end */ if ((zval = *z) != FL(0.0)) { int16 n, nlim = inp2 - z; for (n = 1; n < nlim; n++) { if (zval * *(z+n) <= FL(0.0)) { /* find nearest zcrossing */ z += n; break; } else if (zval * *(z-n) <= FL(0.0)) { z -= n; break; } /* (true period is now z - x) */ } } x -= xdist; /* now extend for sig ris-dec */ z += xdist; if (x < buf0) x = buf0; /* truncated if necessary */ else if (z > inp2) z = inp2; /* by input limits */ pulslen = z - x; if (pulslen > p->maxprd) pulslen = p->maxprd; /* & storage limits */ sigdist = xdist * 2; ndirect = pulslen - sigdist*2; if (ndirect < 0) goto nostor; p->pbufcnt++; /* select a new puls buffr */ p->pbufcnt &= PBMSK; bufp = p->pulsbuf[p->pbufcnt]; signdx = FL(0.0); /* & store extended pulse */ siginc = (MYFLT)SLEN / sigdist; for (nn = sigdist; nn--; signdx += siginc) { MYFLT *sigp = p->sigmoid + (int)signdx; *bufp++ = *x++ * *sigp; /* w. sigmoid-envlpd ends */ } //memcpy(bufp, x, sizeof(MYFLT)*ndirect); while (ndirect--) *bufp++ = *x++; signdx = (MYFLT)SLEN - siginc; for (nn = sigdist; nn--; signdx -= siginc) { MYFLT *sigp = p->sigmoid + (int)signdx; *bufp++ = *x++ * *sigp; } p->pulslen = pulslen; } nostor: if (p->vocamp < FL(1.0)) { /* if onset */ p->vocinc = p->ampinc; /* set pos voice ramp */ p->switching = 1; } } else { /* NON-PERIODIC: */ nonprd: if (p->vocamp > FL(0.0)) { /* if onset */ p->vocinc = -p->ampinc; /* set neg voice ramp */ p->switching = 1; } p->curpuls = NULL; /* start no new pulses */ } //print_data(p, 3); /* HARMONIZER */ for (vdp=p->vocdat; vdpvlim; vdp++) /* get new frequencies */ vdp->phsinc = (int32)(*vdp->kfrq * p->sicvt); outp = p->ar; //nsmps = csound->ksmps; vocamp = p->vocamp; diramp = FL(1.0) - vocamp; dirp = p->asig; endp = p->endp; do { /* insert pulses into output: */ MYFLT sum = FL(0.0); PULDAT *pdp = p->puldat; while (pdp < endp) { addin: sum += *pdp->srcp++; /* get any ongoing pulsdata */ if (--pdp->cntr <= 0) { /* & phase out if now done */ if (--endp == pdp) break; pdp->srcp = endp->srcp; pdp->cntr = endp->cntr; goto addin; } pdp++; } /* if time to start a new one */ for (vdp=p->vocdat; vdpvlim; vdp++) if (vdp->phsinc && (vdp->phase += vdp->phsinc) & (~0xFFFF)) { vdp->phase &= 0x0000FFFFL; if (p->curpuls != NULL) { /* & pulses are current */ if (endp < p->limp) { /* set one up */ endp->srcp = p->pulsbuf[p->pbufcnt]; endp->cntr = p->pulslen; /* w. extended len */ endp++; } else oflow = 1; } } if (p->switching) { /* if v/uv switching */ vocamp += p->vocinc; /* do linear ramp */ if (vocamp <= FL(0.0)) { vocamp = FL(0.0); p->switching = 0; } else if (vocamp >= FL(1.0)) { vocamp = FL(1.0); p->switching = 0; } diramp = FL(1.0) - vocamp; } *outp++ = sum * vocamp + *dirp++ * diramp; /* output combined */ } while (--nsmps); p->endp = endp; p->vocamp = vocamp; if (UNLIKELY(oflow && ++p->hmrngflg > 10)) { csound->Warning(csound, Str("harmon234: out of range\n")); p->hmrngflg = 0; } if (inp1 >= p->midp) { /* if end of pq bufs */ int32 bsmps = p->nbufsmps; p->inp1 = p->bufp; /* reset all ptrs */ p->inp2 = p->midp; if (p->curpuls != NULL) p->curpuls -= bsmps; } else { p->inp1 = inp1; p->inp2 = inp2; } //print_data(p, 4); return OK; } int harm2set(CSOUND *csound, HARM234 *p) { VOCDAT *vdp = p->vocdat; vdp->kfrq = p->kfrq1; vdp->phase = 0; vdp++; vdp->kfrq = p->kfrq2; vdp->phase = 0; vdp++; p->vlim = vdp; p->polarity = (int16)*p->icpsmode; p->minoct = *p->kfrq4; p->cpsmode = ((*p->kfrq3 != FL(0.0))); return hm234set(csound, p); } int harm3set(CSOUND *csound, HARM234 *p) { VOCDAT *vdp = p->vocdat; vdp->kfrq = p->kfrq1; vdp->phase = 0; vdp++; vdp->kfrq = p->kfrq2; vdp->phase = 0; vdp++; vdp->kfrq = p->kfrq3; vdp->phase = 0; vdp++; p->vlim = vdp; //printf("mode, lowest, polar = %p,%p,%p\n", // p->icpsmode, p->ilowest, p->ipolarity); p->polarity = (int16)*p->ilowest; p->minoct = *p->icpsmode; p->cpsmode = (*p->kfrq4 != FL(0.0)); //printf("mode, lowest, polar = (%d,%f,%d)\n", // p->cpsmode, p->minoct, p->ipolarity); return hm234set(csound, p); } int harm4set(CSOUND *csound, HARM234 *p) { VOCDAT *vdp = p->vocdat; vdp->kfrq = p->kfrq1; vdp->phase = 0; vdp++; vdp->kfrq = p->kfrq2; vdp->phase = 0; vdp++; vdp->kfrq = p->kfrq3; vdp->phase = 0; vdp++; vdp->kfrq = p->kfrq4; vdp->phase = 0; vdp++; p->vlim = vdp; p->polarity = (int16)*p->ipolarity; p->minoct = *p->ilowest; p->cpsmode = (*p->icpsmode != FL(0.0)); return hm234set(csound, p); } #define S(x) sizeof(x) static OENTRY harmon_localops[] = { { "harmon2",S(HARM234),0,5,"a","akkkiip", (SUBR)harm2set,NULL, (SUBR)harmon234 }, { "harmon3",S(HARM234),0,5,"a","akkkkiip", (SUBR)harm3set,NULL, (SUBR)harmon234 }, { "harmon4",S(HARM234),0,5,"a","akkkkkiip",(SUBR)harm4set,NULL, (SUBR)harmon234 }, }; LINKAGE_BUILTIN(harmon_localops) csound-6.10.0/Opcodes/hdf5/000077500000000000000000000000001321653344700153235ustar00rootroot00000000000000csound-6.10.0/Opcodes/hdf5/CMakeLists.txt000066400000000000000000000030541321653344700200650ustar00rootroot00000000000000option(BUILD_HDF5_OPCODES "Build the hdf5 read/write opcodes" ON) if(MSVC) message(STATUS "HDF5_HOME: $ENV{HDF5_HOME}") message(STATUS "Configuring HDF5 for static linkage.") find_library (HDF5_library NAMES libhdf5 PATHS $ENV{HDF5_HOME} PATH_SUFFIXES lib NO_DEFAULT_PATH) find_library (HDF5_szip_library NAMES libszip PATHS $ENV{HDF5_HOME} PATH_SUFFIXES lib NO_DEFAULT_PATH) find_library (HDF5_zlib_library NAMES libzlib PATHS $ENV{HDF5_HOME} PATH_SUFFIXES lib NO_DEFAULT_PATH) find_path(HDF5_H hdf5.h PATHS $ENV{HDF5_HOME} PATH_SUFFIXES include ${EXTRA_PREFIX} NO_DEFAULT_PATH) check_deps(BUILD_HDF5_OPCODES HDF5_library HDF5_H) if(BUILD_HDF5_OPCODES) message(STATUS "HDF5_H: ${HDF5_H}") message(STATUS "HDF5_library: ${HDF5_library}") message(STATUS "HDF5_szip_library: ${HDF5_szip_library}") message(STATUS "HDF5_zlib_library: ${HDF5_zlib_library}") make_plugin(hdf5ops HDF5IO.c) target_include_directories(hdf5ops PRIVATE ${HDF5_H}) target_link_libraries(hdf5ops ${HDF5_library} ${HDF5_szip_library} ${HDF5_zlib_library}) endif() else() find_package(HDF5) check_deps(BUILD_HDF5_OPCODES HDF5_FOUND) if(BUILD_HDF5_OPCODES) message(STATUS "HDF5_INCLUDE_DIRS: ${HDF5_INCLUDE_DIRS}") message(STATUS "HDF5_LIBRARIES: ${HDF5_LIBRARIES}") make_plugin(hdf5ops HDF5IO.c) target_include_directories(hdf5ops PRIVATE ${HDF5_INCLUDE_DIRS}) target_link_libraries(hdf5ops ${HDF5_LIBRARIES}) endif() endif() check_include_file(hdf5.h HDF5_H) csound-6.10.0/Opcodes/hdf5/HDF5IO.c000066400000000000000000001305051321653344700164110ustar00rootroot00000000000000/* * Copyright (C) 2014 Edward Costello * * This software is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "HDF5IO.h" #include #ifdef _MSC_VER #include #else #include #endif #define HDF5ERROR(x) if (UNLIKELY((x) == -1)) \ {csound->Die(csound, #x" error\nExiting\n");} // Type strings to match the enum types static const char typeStrings[8][12] = { "STRING_VAR", "ARATE_VAR", "KRATE_VAR", "IRATE_VAR", "ARATE_ARRAY", "KRATE_ARRAY", "IRATE_ARRAY", "UNKNOWN" }; // Get the argument enum type from the opcode argument pointer // // Get the csound type from the argument // Get the variable type name // Do a string comparison and match the type to the enum type ArgumentType HDF5IO_getArgumentTypeFromArgument(CSOUND *csound, MYFLT *argument) { const CS_TYPE *csoundType = csound->GetTypeForArg((void *)argument); const char *type = csoundType->varTypeName; ArgumentType argumentType = UNKNOWN; if (strcmp("S", type) == 0) { argumentType = STRING_VAR; } else if (strcmp("a", type) == 0) { argumentType = ARATE_VAR; } else if (strcmp("k", type) == 0) { argumentType = KRATE_VAR; } else if (strcmp("i", type) == 0) { argumentType = IRATE_VAR; } else if (strcmp("[", type) == 0) { ARRAYDAT *array = (ARRAYDAT *)argument; if (strcmp("k", array->arrayType->varTypeName) == 0) { argumentType = KRATE_ARRAY; } else if (strcmp("a", array->arrayType->varTypeName) == 0) { argumentType = ARATE_ARRAY; } else if (strcmp("i", array->arrayType->varTypeName) == 0) { argumentType = IRATE_ARRAY; } } return argumentType; } // Get the matching argument enum type from a string // // Do a string comparison and assign the corresponding enum type to the string ArgumentType HDF5IO_getArgumentTypeFromString(CSOUND *csound, const char *string) { ArgumentType type = UNKNOWN; if (strcmp("STRING_VAR", string) == 0) { type = STRING_VAR; } else if (strcmp("ARATE_VAR", string) == 0) { type = ARATE_VAR; } else if (strcmp("KRATE_VAR", string) == 0) { type = KRATE_VAR; } else if (strcmp("IRATE_VAR", string) == 0) { type = IRATE_VAR; } else if (strcmp("ARATE_ARRAY", string) == 0) { type = ARATE_ARRAY; } else if (strcmp("KRATE_ARRAY", string) == 0) { type = KRATE_ARRAY; } else if (strcmp("IRATE_ARRAY", string) == 0) { type = IRATE_ARRAY; } return type; } // Create or open a hdf5 file // // Allocate the memory for a hdf5 file struct // Assign the path string to the file name in the struct // Check if the file exists // If it doesn't and this function is being called by the hdf5 write function, // create the file // If it exists, open the file for appending // Find out what size the MYFLT floating point type is and assign the correct // hdf5 type to it // Return the pointer to the hdf5 file struct HDF5File *HDF5IO_newHDF5File(CSOUND *csound, AUXCH *hdf5FileMemory, STRINGDAT *path, bool openForWriting) { csound->AuxAlloc(csound, sizeof(HDF5File), hdf5FileMemory); HDF5File *hdf5File = hdf5FileMemory->auxp; hdf5File->fileName = path->data; int fileExists = access(hdf5File->fileName, 0); if (UNLIKELY(fileExists == -1)) { if (LIKELY(openForWriting == true)) { hdf5File->fileHandle = H5Fcreate(hdf5File->fileName, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); HDF5ERROR(hdf5File->fileHandle); } else { csound->Die(csound, "hdf5read: Error, file does not exist"); } } else { hdf5File->fileHandle = H5Fopen(hdf5File->fileName, H5F_ACC_RDWR, H5P_DEFAULT); HDF5ERROR(hdf5File->fileHandle); } #ifdef USE_DOUBLE hdf5File->floatSize = H5T_NATIVE_DOUBLE; #else hdf5File->floatSize = H5T_NATIVE_FLOAT; #endif //else { //csound->Die(csound,"HDF5IO: Illegal size for floating point type, exiting"); //} return hdf5File; } // Write a string attribute to a hdf5 file dataset // // Create a new attribute of type C string // Set the size of the string to 11 characters, this is the longest string // length of the argument type strings // Set the string to be null terminated // Create the attribute in the hdf5 file // Write the string to the attribute // Close the open handles void HDF5IO_writeStringAttribute(CSOUND *csound, HDF5File *self, HDF5Dataset *dataset, const char *attributeName, const char *attributeString) { hid_t attributeID = H5Screate(H5S_SCALAR); HDF5ERROR(attributeID); hid_t attributeType = H5Tcopy(H5T_C_S1); HDF5ERROR(attributeType); HDF5ERROR(H5Tset_size(attributeType, 11)); HDF5ERROR(H5Tset_strpad(attributeType,H5T_STR_NULLTERM)); hid_t attributeHandle = H5Acreate2(dataset->datasetID, attributeName, attributeType, attributeID, H5P_DEFAULT, H5P_DEFAULT); HDF5ERROR(attributeHandle); HDF5ERROR(H5Awrite(attributeHandle, attributeType, attributeString)); HDF5ERROR(H5Sclose(attributeID)); HDF5ERROR(H5Tclose(attributeType)); HDF5ERROR(H5Aclose(attributeHandle)); } // Read a string attribute from the hdf5 file // // Open the data set and get the info structure // Get the attribute at index 0, this should probably be more general, needs // more work // Get the type of the attribute // Read the attribute into memory and close all the handles void HDF5IO_readStringAttribute(CSOUND *csound, HDF5File *self, char *datasetName, char *attributeString) { hid_t dataSetID = H5Dopen2(self->fileHandle, datasetName, H5P_DEFAULT); H5O_info_t oinfo; HDF5ERROR(H5Oget_info(dataSetID, &oinfo)); hid_t attributeID = H5Aopen_by_idx(dataSetID, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, 0, H5P_DEFAULT, H5P_DEFAULT); HDF5ERROR(attributeID); hid_t attributeType = H5Aget_type(attributeID); HDF5ERROR(attributeType); hid_t attributeTypeMemory = H5Tget_native_type(attributeType, H5T_DIR_ASCEND); HDF5ERROR(attributeTypeMemory); HDF5ERROR(H5Aread(attributeID, attributeTypeMemory, attributeString)); HDF5ERROR(H5Aclose(attributeID)); HDF5ERROR(H5Tclose(attributeType)); HDF5ERROR(H5Tclose(attributeTypeMemory)); HDF5ERROR(H5Dclose(dataSetID)); } // Find if csound is running in sample accurate mode // // Get the argument parameters passed to run csound // Find the sample accurate parameter and return it bool HDF5IO_getSampleAccurate(CSOUND *csound) { OPARMS parameters = {0}; csound->GetOParms(csound, ¶meters); return parameters.sampleAccurate; } // Set everything up so datasets can be written from the opcodes input variables, // i-rate datasets are written at initialisation all others are written on the // performance pass. // // Get the amount of samples in a control pass // Get the amount of arguments to the opcode, this doesn't include the first // argument which is for the filename. // Check that the first argument is a string for the filename, check others // are not strings // Register the callback to close the hdf5 file when performance finishes // Get the path argument and open a hdf5 file, if it doesn't exist create it // Create the datasets in the file so they can be written int HDF5Write_initialise(CSOUND *csound, HDF5Write *self) { self->ksmps = csound->GetKsmps(csound); self->inputArgumentCount = self->INOCOUNT - 1; HDF5Write_checkArgumentSanity(csound, self); csound->RegisterDeinitCallback(csound, self, HDF5Write_finish); STRINGDAT *path = (STRINGDAT *)self->arguments[0]; self->hdf5File = HDF5IO_newHDF5File(csound, &self->hdf5FileMemory, path, true); HDF5Write_createDatasets(csound, self); return OK; } // Write the input data to the associated dataset // // Enlarge the dataset first then get the file space // Select a hyperslab with the necessary offset and size // Create a memory space where the data is written to // Write the data to the memory space // Close the file space void HDF5Write_writeData(CSOUND *csound, HDF5Write *self, HDF5Dataset *dataset, MYFLT *data) { HDF5ERROR(H5Dset_extent(dataset->datasetID, dataset->datasetSize)); hid_t filespace = H5Dget_space(dataset->datasetID); HDF5ERROR(filespace); HDF5ERROR(H5Sselect_hyperslab(filespace, H5S_SELECT_SET, dataset->offset, NULL, dataset->chunkDimensions, NULL)); hid_t memspace = H5Screate_simple(dataset->rank, dataset->chunkDimensions, NULL); HDF5ERROR(memspace); HDF5ERROR(H5Dwrite(dataset->datasetID, self->hdf5File->floatSize, memspace, filespace, H5P_DEFAULT, data)); HDF5ERROR(H5Sclose(filespace)); } // Write a-rate variables and arrays to the specified data set // // For sample accurate mode, get the offset and early variables // Calculate the size of the incoming vector // If the vector is 0 return, no more data to write // Expand the dataset size by ksmps, because data is written in chunks // For sample accurate mode the exact dataset size is set when writing is finished // Write the data to the dataset // Increment the offset by the size of the vector that was just written void HDF5Write_writeAudioData(CSOUND *csound, HDF5Write *self, HDF5Dataset *dataset, MYFLT *dataPointer) { size_t offset = self->h.insdshead->ksmps_offset; size_t early = self->h.insdshead->ksmps_no_end; int vectorSize = (int)(self->ksmps - offset - early); if (UNLIKELY(vectorSize == 0)) { return; } dataset->datasetSize[0] += self->ksmps; HDF5Write_writeData(csound, self, dataset, &dataPointer[offset]); dataset->offset[0] += vectorSize; } // Write k-rate variables and arrays to the specified data set // // Increment the data set size by 1 // Write the data to the dataset // Increment the offset by 1 void HDF5Write_writeControlData(CSOUND *csound, HDF5Write *self, HDF5Dataset *dataset, MYFLT *dataPointer) { dataset->datasetSize[0]++; HDF5Write_writeData(csound, self, dataset, dataPointer); dataset->offset[0]++; } // Send each input argument to the necessary writing function // // Iterate through the dataset array, select the current // Depending on the dataset type send to the necessary write function int HDF5Write_process(CSOUND *csound, HDF5Write *self) { int i; for (i = 0; i < self->inputArgumentCount; ++i) { HDF5Dataset *currentDataset = &self->datasets[i]; switch (currentDataset->writeType) { case ARATE_ARRAY: { HDF5Write_writeAudioData(csound, self, currentDataset, ((ARRAYDAT *)currentDataset->argumentPointer)->data); break; } case KRATE_ARRAY: { HDF5Write_writeControlData(csound, self, currentDataset, ((ARRAYDAT *)currentDataset->argumentPointer)->data); break; } case ARATE_VAR: { HDF5Write_writeAudioData(csound, self, currentDataset, currentDataset->argumentPointer); break; } case KRATE_VAR: { HDF5Write_writeControlData(csound, self, currentDataset, currentDataset->argumentPointer); break; } default: { break; } } } return OK; } // Close the hdf5 file and set the a-rate dataset extents for sample accurate mode // // Check that the datasets exist // Iterate through the datasets, if a-rate, set the size to be the same as // current offset // Set the set extent of the dataset to the size // Close the datasets, then close the file int HDF5Write_finish(CSOUND *csound, void *inReference) { HDF5Write *self = inReference; if (LIKELY(self->datasets != NULL)) { int i; for (i = 0; i < self->inputArgumentCount; ++i) { HDF5Dataset *dataset = &self->datasets[i]; switch (dataset->writeType) { case ARATE_ARRAY: { dataset->datasetSize[0] = dataset->offset[0]; HDF5ERROR(H5Dset_extent(dataset->datasetID, dataset->datasetSize)); break; } case ARATE_VAR: { dataset->datasetSize[0] = dataset->offset[0]; HDF5ERROR(H5Dset_extent(dataset->datasetID, dataset->datasetSize)); break; } default: { break; } } HDF5ERROR(H5Dclose(dataset->datasetID)); } } HDF5ERROR(H5Fclose(self->hdf5File->fileHandle)); return OK; } // Check that the correct types of inputs have been used in the opcode // // Get the argument type for the first input // If it is not a string stop csound // Iterate over the rest of the input arguments, if any are strings stop csound void HDF5Write_checkArgumentSanity(CSOUND *csound, const HDF5Write *self) { int i; ArgumentType type = HDF5IO_getArgumentTypeFromArgument(csound, self->arguments[0]); if (UNLIKELY(type != STRING_VAR)) { csound->Die(csound, Str("hdf5write: Error, first argument does not " "appear to be a string, exiting")); } for (i = 0; i < self->inputArgumentCount; ++i) { type = HDF5IO_getArgumentTypeFromArgument(csound, self->arguments[i + 1]); if (UNLIKELY(type == STRING_VAR || type == UNKNOWN)) { csound->Die(csound, Str("hdf5write: Error, unable to identify type " "of argument %zd"), i); } } } // Create, or delete and create again a dataset in an hdf5 file // // Check to see if the dataset exists // If it exists delete it // Create the data space, set the writing chunk size and the empty space fill value // Create the data set in the data space and write the argument type as a string // attribute void HDF5Write_initialiseHDF5Dataset(CSOUND *csound, HDF5Write *self, HDF5Dataset *dataset) { htri_t result = H5Lexists(self->hdf5File->fileHandle, dataset->datasetName, H5P_DEFAULT); if (result == 1) { HDF5ERROR(H5Ldelete(self->hdf5File->fileHandle, dataset->datasetName, H5P_DEFAULT)); } hid_t dataspaceID = H5Screate_simple(dataset->rank, dataset->chunkDimensions, dataset->maxDimensions); HDF5ERROR(dataspaceID); hid_t cparams = H5Pcreate(H5P_DATASET_CREATE); HDF5ERROR(cparams); HDF5ERROR(H5Pset_chunk(cparams, dataset->rank, dataset->chunkDimensions)); MYFLT zero = 0; HDF5ERROR(H5Pset_fill_value(cparams, self->hdf5File->floatSize, &zero)); dataset->datasetID = H5Dcreate2(self->hdf5File->fileHandle, dataset->datasetName, self->hdf5File->floatSize, dataspaceID, H5P_DEFAULT, cparams, H5P_DEFAULT); HDF5ERROR(dataset->datasetID); HDF5IO_writeStringAttribute(csound, self->hdf5File, dataset, "Variable Type", typeStrings[dataset->writeType]); } // Set up the variables for writing an array dataset // // Get the array from the argument pointer // If its an i-rate array the rank is copied, if not we add a dimension // Allocate arrays for the chunk sizes, maximum sizes, data set sizes and // offset sizes // Copy the sizes from the input array variables to the allocated size arrays // If it's an a-rate array set the last chunk dimension to ksmps, last max // dimension to unlimited and dataset size to 0 // If it's a k-rate array set the last chunk dimension to 1 and last max // dimension to unlimited // If it's an i-rate array just return void HDF5Write_newArrayDataset(CSOUND *csound, HDF5Write *self, HDF5Dataset *dataset) { ARRAYDAT *array = (ARRAYDAT *)dataset->argumentPointer; int i; if (dataset->writeType == IRATE_ARRAY) { dataset->rank = array->dimensions; } else { dataset->rank = array->dimensions + 1; } csound->AuxAlloc(csound, dataset->rank * sizeof(hsize_t), &dataset->chunkDimensionsMemory); dataset->chunkDimensions = dataset->chunkDimensionsMemory.auxp; csound->AuxAlloc(csound, dataset->rank * sizeof(hsize_t), &dataset->maxDimensionsMemory); dataset->maxDimensions = dataset->maxDimensionsMemory.auxp; csound->AuxAlloc(csound, dataset->rank * sizeof(hsize_t), &dataset->datasetSizeMemory); dataset->datasetSize = dataset->datasetSizeMemory.auxp; csound->AuxAlloc(csound, dataset->rank * sizeof(hsize_t), &dataset->offsetMemory); dataset->offset = dataset->offsetMemory.auxp; for (i = 0; i < array->dimensions; ++i) { dataset->chunkDimensions[i + 1] = array->sizes[i]; dataset->maxDimensions[i + 1] = array->sizes[i]; dataset->datasetSize[i + 1] = array->sizes[i]; } switch (dataset->writeType) { case ARATE_ARRAY: { dataset->chunkDimensions[0] = self->ksmps; dataset->maxDimensions[0] = H5S_UNLIMITED; dataset->datasetSize[0] = 0; break; } case KRATE_ARRAY: { dataset->chunkDimensions[0] = 1; dataset->maxDimensions[0] = H5S_UNLIMITED; break; } case IRATE_ARRAY: { return; } default: { csound->Die(csound, Str("This should not happen, exiting")); break; } } } // Set up variables for writing a scalar dataset // // Set the rank to 1 // Allocate memory for chunk sizes, maximum sizes, dataset sizes and offsets // If the argument is not an i-rate variable: // Set the chunk dimensions to ksmps if a-rate, 1 if k-rate // Set maximum dimensions to unlimited // Set the data size to 0 // If it is an i-rate variable: // Set the data set size to 1 // Set the chunk dimensions to 1 // Set the maximum dimensions to 1 // Set the offset to 0 void HDF5Write_newScalarDataset(CSOUND *csound, HDF5Write *self, HDF5Dataset *dataset) { dataset->rank = 1; csound->AuxAlloc(csound, sizeof(hsize_t), &dataset->chunkDimensionsMemory); dataset->chunkDimensions = dataset->chunkDimensionsMemory.auxp; csound->AuxAlloc(csound, sizeof(hsize_t), &dataset->maxDimensionsMemory); dataset->maxDimensions = dataset->maxDimensionsMemory.auxp; csound->AuxAlloc(csound, sizeof(hsize_t), &dataset->datasetSizeMemory); dataset->datasetSize = dataset->datasetSizeMemory.auxp; csound->AuxAlloc(csound, sizeof(hsize_t), &dataset->offsetMemory); dataset->offset = dataset->offsetMemory.auxp; if (dataset->writeType != IRATE_VAR) { dataset->chunkDimensions[0] = dataset->writeType == ARATE_VAR ? self->ksmps : 1; dataset->maxDimensions[0] = H5S_UNLIMITED; dataset->datasetSize[0] = 0; } else { dataset->datasetSize[0] = 1; dataset->chunkDimensions[0] = 1; dataset->maxDimensions[0] = 1; } dataset->offset[0] = 0; } // Create the datasets for each argument to be written // // Allocate the memory for the datasets array // Get the current empty dataset from the array // Set it's dataset name as the input arguments name + 1 which is after the // file path string // Get the argument pointer from the arguments + 1 after the file path string // Get the enum write type from the argument pointer // Depending on the write type set up the variables in the correct way for // writing during performance // If the variables are i-rate set up the variables and write them void HDF5Write_createDatasets(CSOUND *csound, HDF5Write *self) { int i; csound->AuxAlloc(csound, sizeof(HDF5Dataset) * self->inputArgumentCount, &self->datasetsMemory); self->datasets = self->datasetsMemory.auxp; for (i = 0; i < self->inputArgumentCount; ++i) { HDF5Dataset *currentDataset = &self->datasets[i]; currentDataset->datasetName = csound->GetInputArgName(self, (int)i + 1); currentDataset->argumentPointer = self->arguments[i + 1]; currentDataset->writeType = HDF5IO_getArgumentTypeFromArgument(csound, currentDataset->argumentPointer); switch (currentDataset->writeType) { case ARATE_ARRAY: { HDF5Write_newArrayDataset(csound, self, currentDataset); HDF5Write_initialiseHDF5Dataset(csound, self, currentDataset); break; } case KRATE_ARRAY: { HDF5Write_newArrayDataset(csound, self, currentDataset); HDF5Write_initialiseHDF5Dataset(csound, self, currentDataset); break; } case IRATE_ARRAY: { HDF5Write_newArrayDataset(csound, self, currentDataset); HDF5Write_initialiseHDF5Dataset(csound, self, currentDataset); HDF5Write_writeData(csound, self, currentDataset, ((ARRAYDAT *)currentDataset->argumentPointer)->data); break; } case ARATE_VAR: { HDF5Write_newScalarDataset(csound, self, currentDataset); HDF5Write_initialiseHDF5Dataset(csound, self, currentDataset); break; } case KRATE_VAR: { HDF5Write_newScalarDataset(csound, self, currentDataset); HDF5Write_initialiseHDF5Dataset(csound, self, currentDataset); break; } case IRATE_VAR: { HDF5Write_newScalarDataset(csound, self, currentDataset); HDF5Write_initialiseHDF5Dataset(csound, self, currentDataset); HDF5Write_writeData(csound, self, currentDataset, currentDataset->argumentPointer); break; } default: { break; } } } } // Open datasets in a hdf5 file so they can be read by the opcode // // Get the amount of samples in a control pass // Get the amount of input arguments minus the file path argument // Get the amount of output arguments // Check that input == output arguments and input arguments are strings, // output not strings // Register the finish callback to close the hdf5 file when performance // is finished // Check csound is running in sample accurate mode // Get the path string from the first argument // Open the hdf5 file then open the hdf5 datasets int HDF5Read_initialise(CSOUND *csound, HDF5Read *self) { self->ksmps = csound->GetKsmps(csound); self->inputArgumentCount = self->INOCOUNT - 1; self->outputArgumentCount = self->OUTOCOUNT; HDF5Read_checkArgumentSanity(csound, self); csound->RegisterDeinitCallback(csound, self, HDF5Read_finish); self->isSampleAccurate = HDF5IO_getSampleAccurate(csound); STRINGDAT *path = (STRINGDAT *)self->arguments[self->outputArgumentCount]; self->hdf5File = HDF5IO_newHDF5File(csound, &self->hdf5FileMemory, path, false); HDF5Read_openDatasets(csound, self); return OK; } // Copy data from the a-rate variable read sample buffer to the output array data // // This function is used to copy data from a sample buffer each hdf5 // struct to an array data member, this is because in sample accurate // mode the stride of the data read from the hdf5 file isn't correct // and must be offset properly before it is written to the array data void HDF5Read_copySampleBufferToArray(size_t channelCount, MYFLT *sampleBuffer, MYFLT *arrayData, size_t vectorSize, size_t offset, size_t ksmps) { size_t channel; for (channel = 0; channel < channelCount; ++channel) { memcpy(&arrayData[ksmps * channel + offset], &sampleBuffer[vectorSize * channel], sizeof(MYFLT) * vectorSize); } } // Read data from an hdf5 file dataset // // Get the specified file space // Select the hyperslab at the specified offset and chunk dimension // Create a memory space from where the data is read // Read the data from the memory space // Close the open file and memory spaces void HDF5Read_readData(CSOUND *csound, HDF5Read *self, HDF5Dataset *dataset, hsize_t *offset, hsize_t *chunkDimensions, MYFLT *dataPointer) { unsigned long kCount = csound->GetKcounter(csound); if (kCount > dataset->datasetSize[0]) { return; } hid_t filespace = H5Dget_space(dataset->datasetID); HDF5ERROR(filespace); HDF5ERROR(H5Sselect_hyperslab(filespace, H5S_SELECT_SET, offset, NULL, chunkDimensions, NULL)); hid_t memspace = H5Screate_simple(dataset->rank, chunkDimensions, NULL); HDF5ERROR(memspace); HDF5ERROR(H5Dread(dataset->datasetID, self->hdf5File->floatSize, memspace, filespace, H5P_DEFAULT, dataPointer)); HDF5ERROR(H5Sclose(filespace)); HDF5ERROR(H5Sclose(memspace)); } // Read data at audio rate from a hdf5 file dataset // // If the offset is larger than the size of the dataset there is no more // data to read so return // Get the offset and early variables and work out the size of data to read // If the read vector size plus the offset is larger than the dataset size // reduce the vector size accordingly // If the vector size is less than the ksmps value, use the sample // buffer to store read data so the stride can be corrected before // writing it to the array data, if not just point directly to array // data // Create the chunk dimensions variable, set the required size // Read data from the hdf5 file // If the vector size is not equal to ksmps correct the stride of data // Increment the offset by the vector size void HDF5Read_readAudioData(CSOUND *csound, HDF5Read *self, HDF5Dataset *dataset, MYFLT *inputDataPointer) { if (dataset->offset[0] >= dataset->datasetSize[0]) { return; } size_t offset = self->h.insdshead->ksmps_offset; size_t early = self->h.insdshead->ksmps_no_end; size_t vectorSize = (int)(self->ksmps - offset - early); if (vectorSize + dataset->offset[0] > dataset->datasetSize[0]) { vectorSize = (int)(dataset->datasetSize[0] - dataset->offset[0]); } MYFLT *dataPointer = vectorSize != self->ksmps ? dataset->sampleBuffer : inputDataPointer; // FIXME if this is called frequently or on the audio thread then this won't // work and will need a different solution #ifdef _MSC_VER hsize_t* chunkDimensions = malloc (dataset->rank * sizeof (hsize_t)); #else hsize_t chunkDimensions[dataset->rank]; #endif memcpy(&chunkDimensions[1], &dataset->datasetSize[1], sizeof(hsize_t) * dataset->rank); chunkDimensions[0] = vectorSize; memcpy (chunkDimensions, dataset->datasetSize, sizeof (hsize_t) * dataset->rank); chunkDimensions[dataset->rank - 1] = vectorSize; HDF5Read_readData (csound, self, dataset, dataset->offset, chunkDimensions, dataPointer); if (vectorSize != self->ksmps) { HDF5Read_copySampleBufferToArray(dataset->elementCount, dataset->sampleBuffer, inputDataPointer, vectorSize, offset, self->ksmps); } dataset->offset[0] += vectorSize; #ifdef _MSC_VER free (chunkDimensions); #endif } // Read data at control rate from a hdf5 dataset // // If the offset of the dataset is larger than the data set size, no // more data to read to return // Create chunk dimension variable and set the appropriate size // Read the data from the dataset // Increment the offset variable void HDF5Read_readControlData(CSOUND *csound, HDF5Read *self, HDF5Dataset *dataset, MYFLT *dataPointer) { if (dataset->offset[0] >= dataset->datasetSize[0]) { return; } // FIXME if this is called frequently or on the audio thread then this won't // work and will need a different solution #ifndef _MSC_VER hsize_t chunkDimensions[dataset->rank]; #else hsize_t* chunkDimensions = malloc (dataset->rank * sizeof (hsize_t)); #endif memcpy(&chunkDimensions[1], &dataset->datasetSize[1], sizeof(hsize_t) * (dataset->rank - 1)); chunkDimensions[0] = 1; HDF5Read_readData(csound, self, dataset, dataset->offset, chunkDimensions, dataPointer); dataset->offset[0]++; #ifdef _MSC_VER free (chunkDimensions); #endif } // Read dataset variables during performance time // // Iterate through each of the opened datasets, // Depending on the dataset read type use the appropriate read function // to read the data int HDF5Read_process(CSOUND *csound, HDF5Read *self) { int i; for (i = 0; i < self->inputArgumentCount; ++i) { HDF5Dataset *dataset = &self->datasets[i]; if (dataset->readAll == true) { continue; } switch (dataset->readType) { case ARATE_ARRAY: { HDF5Read_readAudioData(csound, self, dataset, ((ARRAYDAT *)dataset->argumentPointer)->data); break; } case KRATE_ARRAY: { HDF5Read_readControlData(csound, self, dataset, ((ARRAYDAT *)dataset->argumentPointer)->data); break; } case ARATE_VAR: { HDF5Read_readAudioData(csound, self, dataset, dataset->argumentPointer); break; } case KRATE_VAR: { HDF5Read_readControlData(csound, self, dataset, dataset->argumentPointer); break; } default: { break; } } } return OK; } // Close the necessary variables when reading has finished // // Iterate through open datasets closing them in the hdf5 file // Close the hdf5 file int HDF5Read_finish(CSOUND *csound, void *inReference) { HDF5Read *self = inReference; int i; for (i = 0; i < self->inputArgumentCount; ++i) { HDF5Dataset *dataset = &self->datasets[i]; HDF5ERROR(H5Dclose(dataset->datasetID)); } HDF5ERROR(H5Fclose(self->hdf5File->fileHandle)); return OK; } // Check the input and output arguments for validity // // Check to see that if the amount of input arguments matches output arguments // Check that the input arguments are strings, and the output arguments are // not strings void HDF5Read_checkArgumentSanity(CSOUND *csound, const HDF5Read *self) { int i; if (UNLIKELY(self->inputArgumentCount != self->outputArgumentCount)) { if (self->inputArgumentCount > self->outputArgumentCount) { csound->Die(csound, Str("hdf5read: Error, more input arguments than " "output arguments, exiting")); } else { csound->Die(csound, Str("hdf5read: Error, more output arguments than " "input arguments, exiting")); } } for (i = 0; i < self->inputArgumentCount; ++i) { ArgumentType inputType = HDF5IO_getArgumentTypeFromArgument(csound, self->arguments[self->outputArgumentCount + i]); ArgumentType outputType = HDF5IO_getArgumentTypeFromArgument(csound, self->arguments[i]); if (UNLIKELY(inputType != STRING_VAR)) { csound->Die(csound, Str("hdf5read: Error, input argument %zd does not " "appear to be a string, exiting"), i + 1); } else if (UNLIKELY(inputType == UNKNOWN)) { csound->Die(csound, Str("hdf5read: Error, input argument %zd type " "is unknown, exiting"), i + 1); } if (UNLIKELY(outputType == STRING_VAR)) { csound->Die(csound, Str("hdf5read: Error, output argument %zd appears " "to be a string, exiting"), i + 1); } else if (UNLIKELY(outputType == UNKNOWN)) { csound->Die(csound, Str("hdf5read: Error, output argument %zd type " "is unknown, exiting"), i + 1); } } } // Open the specified dataset in the hdf5 file // // Check that the hdf5 dataset exists in the file, if it doesn't stop csound // If it does then open it void HDF5Read_initialiseHDF5Dataset(CSOUND *csound, HDF5Read *self, HDF5Dataset *dataset) { htri_t result = H5Lexists(self->hdf5File->fileHandle, dataset->datasetName, H5P_DEFAULT); if (UNLIKELY(result <= 0)) { csound->Die(csound, Str("hdf5read: Error, dataset does not exist or " "cannot be found in file")); } dataset->datasetID = H5Dopen2(self->hdf5File->fileHandle, dataset->datasetName, H5P_DEFAULT); HDF5ERROR(dataset->datasetID); } // Check opcode read types are compatible with the types written to the hdf5 dataset // // Get the written type from the hdf5 file // If the opcode read type for the dataset is an array and the write type is // an array or a-rate or k-rate variable return // If the opcode read type is an a-rate or k-rate variable and the write type // is an a-rate or k-rate vairable return // If the opcode read type is an i-reate variable and the write type is an // i-rate variable return // Otherwise stop csound void HDF5Read_checkReadTypeSanity(CSOUND *csound, HDF5Read *self, HDF5Dataset *dataset) { char attributeString[12] = {"UNKNOWN\0"}; HDF5IO_readStringAttribute(csound, self->hdf5File, dataset->datasetName, attributeString); dataset->writeType = HDF5IO_getArgumentTypeFromString(csound, attributeString); if (dataset->readType == ARATE_ARRAY || dataset->readType == KRATE_ARRAY || dataset->readType == IRATE_ARRAY) { if (dataset->writeType == ARATE_ARRAY || dataset->writeType == KRATE_ARRAY || dataset->writeType == IRATE_ARRAY || dataset->writeType == ARATE_VAR || dataset->writeType == KRATE_VAR) { return; } } else if (dataset->readType == ARATE_VAR || dataset->readType == KRATE_VAR) { if (dataset->writeType == ARATE_VAR || dataset->writeType == KRATE_VAR) { return; } } else if (dataset->readType == IRATE_VAR) { if (dataset->writeType == IRATE_VAR) { return; } } else { csound->Die(csound, Str("hdf5read: Unable to read saved type of " "dataset, exiting")); } } // Allocate the memory for an output array from the opcode // // Get the pointer to the output argument and cast to array // Get the rank and allocate the dimension sizes memory // Assign first dimension size to array sizes and dataset element count // If the rank is greater than 1, multiply dimensions to get element count // Allocate data space for the array using the element count void HDF5Read_allocateArray(CSOUND *csound, HDF5Dataset *dataset, hsize_t rank, hsize_t *dimensions) { ARRAYDAT *array = dataset->argumentPointer; array->dimensions = (int)rank; array->sizes = csound->Calloc(csound, sizeof(int) * rank); array->sizes[0] = (int)dimensions[0]; dataset->elementCount = dimensions[0]; if (rank > 1) { size_t i; for (i = 1; i < rank; ++i) { array->sizes[i] = (int)dimensions[i]; dataset->elementCount *= array->sizes[i]; } } CS_VARIABLE *arrayVariable = array->arrayType->createVariable(csound, NULL); array->arrayMemberSize = arrayVariable->memBlockSize; array->data = csound->Calloc(csound, arrayVariable->memBlockSize * dataset->elementCount); } // Initialise the dataset and prepare for reading an a-rate, k-rate or i-rate // array during performance time // // Get the data space from the dataset in the hdf5 file // Get the rank from the data space // Allocate the size array for specified rank // Get the dimensions of the dataset and copy to dataset size array // If requested output type for dataset is not an i-rate array: // Create the dimensions variable and copy the dataset size minus the last // dimension to the array // Then allocate the array data for the output argument // Allocate the memory for the offset variable // If it's an a-rate array and sample accurate allocate data for the sample buffer // Else if it's an i-rate array copy the array dimensions including the last one // Then allocate the array data for the output argument // Cast the argument pointer to an array, then read the data into the array from // the hdf5 file void HDF5Read_initialiseArrayOutput(CSOUND *csound, HDF5Read *self, HDF5Dataset *dataset) { hid_t dataspaceID = H5Dget_space(dataset->datasetID); HDF5ERROR(dataspaceID); dataset->rank = H5Sget_simple_extent_ndims(dataspaceID); csound->AuxAlloc(csound, sizeof(hsize_t) * dataset->rank, &dataset->datasetSizeMemory); dataset->datasetSize = dataset->datasetSizeMemory.auxp; H5Sget_simple_extent_dims(dataspaceID, dataset->datasetSize, NULL); HDF5ERROR(H5Sclose(dataspaceID)); if (dataset->readType != IRATE_ARRAY && dataset->readAll == false) { // FIXME if this is called frequently or on the audio thread then this won't // work and will need a different solution #ifdef _MSC_VER hsize_t* arrayDimensions = malloc ((dataset->rank - 1) * sizeof (hsize_t)); #else hsize_t arrayDimensions[dataset->rank - 1]; #endif memcpy(arrayDimensions, &dataset->datasetSize[1], (dataset->rank - 1) * sizeof(hsize_t)); HDF5Read_allocateArray(csound, dataset, (dataset->rank - 1), arrayDimensions); csound->AuxAlloc(csound, sizeof(hsize_t) * dataset->rank, &dataset->offsetMemory); dataset->offset = dataset->offsetMemory.auxp; if (dataset->readType == ARATE_ARRAY || self->isSampleAccurate == true) { csound->AuxAlloc(csound, dataset->elementCount * self->ksmps * sizeof(MYFLT), &dataset->sampleBufferMemory); dataset->sampleBuffer = dataset->sampleBufferMemory.auxp; } #ifdef _MSC_VER free (arrayDimensions); #endif } else { #ifdef _MSC_VER hsize_t* arrayDimensions = malloc ((dataset->rank) * sizeof (hsize_t)); #else hsize_t arrayDimensions[dataset->rank]; #endif memcpy(arrayDimensions, dataset->datasetSize, dataset->rank * sizeof(hsize_t)); HDF5Read_allocateArray(csound, dataset, dataset->rank, arrayDimensions); ARRAYDAT *array = dataset->argumentPointer; #ifdef _MSC_VER hsize_t* offset = malloc ((dataset->rank) * sizeof (hsize_t)); #else hsize_t offset[dataset->rank]; #endif memset(offset, 0, sizeof(hsize_t) * dataset->rank); HDF5Read_readData(csound, self, dataset, offset, arrayDimensions, array->data); #ifdef _MSC_VER free (offset); #endif } } // Initialise the dataset and prepare for reading an a-rate, k-rate or i-rate // variable during performance time // // Get the data space from the dataset in the hdf5 file // Set the rank as 1, the variable is a scalar // If the dataset read type is a-rate or k-rate: // Allocate the dataset size memory, get the size of the dataset and copy to // the size memory // Allocate offset memory and set to 0 // If the dataset is to be read at a-rate and we are running sample accurate // allocate the sample buffer // Otherwise create array dimesions variable, set to 1, create offset variable, // set to 0 and read the i-rate variable void HDF5Read_initialiseScalarOutput(CSOUND *csound, HDF5Read *self, HDF5Dataset *dataset) { hid_t dataspaceID = H5Dget_space(dataset->datasetID); HDF5ERROR(dataspaceID); dataset->rank = 1; if (dataset->readType == ARATE_VAR || dataset->readType == KRATE_VAR || dataset->readType == IRATE_VAR) { csound->AuxAlloc(csound, sizeof(hsize_t) * dataset->rank, &dataset->datasetSizeMemory); dataset->datasetSize = dataset->datasetSizeMemory.auxp; H5Sget_simple_extent_dims(dataspaceID, dataset->datasetSize, NULL); HDF5ERROR(H5Sclose(dataspaceID)); csound->AuxAlloc(csound, sizeof(hsize_t), &dataset->offsetMemory); dataset->offset = dataset->offsetMemory.auxp; memset(dataset->offset, 0, sizeof(hsize_t)); if (dataset->readType == ARATE_VAR && self->isSampleAccurate == true) { csound->AuxAlloc(csound, self->ksmps * sizeof(MYFLT), &dataset->sampleBufferMemory); dataset->sampleBuffer = dataset->sampleBufferMemory.auxp; dataset->elementCount = 1; } if (dataset->readType == IRATE_VAR) { hsize_t arrayDimensions[1] = {1}; hsize_t offset[1] = {0}; HDF5Read_readData(csound, self, dataset, offset, arrayDimensions, dataset->argumentPointer); } } } // Open the datasets in an hdf5 file for reading // // Allocate memory for the datasets array // Iterate through the datasets in the array // Assign the input argument name to the dataset name // Get the read type from the arguments // Assign the argument data pointer // Check that the read type and write type are compatible // Initialise the data set using the corresponding function for read type specified void HDF5Read_openDatasets(CSOUND *csound, HDF5Read *self) { int i; csound->AuxAlloc(csound, sizeof(HDF5Dataset) * self->inputArgumentCount, &self->datasetsMemory); self->datasets = self->datasetsMemory.auxp; for (i = 0; i < self->inputArgumentCount; ++i) { HDF5Dataset *currentDataset = &self->datasets[i]; STRINGDAT *inputArgument = (STRINGDAT *)self->arguments[self->outputArgumentCount + i + 1]; csound->AuxAlloc(csound, sizeof(char) * strlen(inputArgument->data), ¤tDataset->datasetNameMemory); currentDataset->datasetName = currentDataset->datasetNameMemory.auxp; strcpy(currentDataset->datasetName, inputArgument->data); if (currentDataset->datasetName[strlen(inputArgument->data) - 1] == '*') { currentDataset->readAll = true; currentDataset->datasetName[strlen(inputArgument->data) - 1] = '\0'; } currentDataset->readType = HDF5IO_getArgumentTypeFromArgument(csound, self->arguments[i]); currentDataset->argumentPointer = self->arguments[i]; HDF5Read_checkReadTypeSanity(csound, self, currentDataset); HDF5Read_initialiseHDF5Dataset(csound, self, currentDataset); switch (currentDataset->readType) { case ARATE_ARRAY: { HDF5Read_initialiseArrayOutput(csound, self, currentDataset); break; } case KRATE_ARRAY: { HDF5Read_initialiseArrayOutput(csound, self, currentDataset); break; } case IRATE_ARRAY: { HDF5Read_initialiseArrayOutput(csound, self, currentDataset); break; } case ARATE_VAR: { HDF5Read_initialiseScalarOutput(csound, self, currentDataset); break; } case KRATE_VAR: { HDF5Read_initialiseScalarOutput(csound, self, currentDataset); break; } case IRATE_VAR: { HDF5Read_initialiseScalarOutput(csound, self, currentDataset); break; } default: break; } } } static OENTRY localops[] = { { .opname = "hdf5write", .dsblksiz = sizeof(HDF5Write), .thread = 3, .outypes = "", .intypes = "*", .iopadr = (SUBR)HDF5Write_initialise, .kopadr = (SUBR)HDF5Write_process, .aopadr = NULL }, { .opname = "hdf5read", .dsblksiz = sizeof(HDF5Read), .thread = 3, .outypes = "*", .intypes = "*", .iopadr = (SUBR)HDF5Read_initialise, .kopadr = (SUBR)HDF5Read_process, .aopadr = NULL } }; LINKAGE csound-6.10.0/Opcodes/hdf5/HDF5IO.h000066400000000000000000000064221321653344700164160ustar00rootroot00000000000000/* * Copyright (C) 2014 Edward Costello * * This software is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "csdl.h" #include "hdf5.h" #include typedef enum ArgumentType { STRING_VAR, ARATE_VAR, KRATE_VAR, IRATE_VAR, ARATE_ARRAY, KRATE_ARRAY, IRATE_ARRAY, UNKNOWN } ArgumentType; typedef struct _fft { OPDS h; ARRAYDAT *out; ARRAYDAT *in, *in2; MYFLT *f; MYFLT b; int n; void *setup; AUXCH mem; } nFFT; typedef struct HDF5Dataset { char *datasetName; AUXCH datasetNameMemory; void *argumentPointer; ArgumentType writeType; ArgumentType readType; int rank; hsize_t *chunkDimensions; AUXCH chunkDimensionsMemory; hsize_t *maxDimensions; AUXCH maxDimensionsMemory; hsize_t *offset; AUXCH offsetMemory; hsize_t *datasetSize; AUXCH datasetSizeMemory; hid_t datasetID; size_t elementCount; MYFLT *sampleBuffer; AUXCH sampleBufferMemory; bool readAll; } HDF5Dataset; typedef struct HDF5File { hid_t fileHandle; char *fileName; hid_t floatSize; } HDF5File; HDF5File *HDF5IO_newHDF5File(CSOUND *csound, AUXCH *hdf5FileMemory, STRINGDAT *path, bool openForWriting); void HDF5IO_deleteHDF5File(CSOUND *csound, HDF5File *hdf5File); typedef struct HDF5Write { OPDS h; MYFLT *arguments[20]; int inputArgumentCount; size_t ksmps; HDF5File *hdf5File; AUXCH hdf5FileMemory; HDF5Dataset *datasets; AUXCH datasetsMemory; } HDF5Write; int HDF5Write_initialise(CSOUND *csound, HDF5Write *self); int HDF5Write_process(CSOUND *csound, HDF5Write *self); int HDF5Write_finish(CSOUND *csound, void *inReference); void HDF5Write_checkArgumentSanity(CSOUND *csound, const HDF5Write *self); void HDF5Write_createDatasets(CSOUND *csound, HDF5Write *self); void HDF5Write_newArrayDataset(CSOUND *csound, HDF5Write *self, HDF5Dataset *dataset); void HDF5Write_deleteArrayDataset(CSOUND *csound, HDF5Dataset *dataset); typedef struct HDF5Read { OPDS h; MYFLT *arguments[20]; int inputArgumentCount; int outputArgumentCount; size_t ksmps; HDF5File *hdf5File; AUXCH hdf5FileMemory; HDF5Dataset *datasets; AUXCH datasetsMemory; bool isSampleAccurate; } HDF5Read; int HDF5Read_initialise(CSOUND *csound, HDF5Read *self); int HDF5Read_process(CSOUND *csound, HDF5Read *self); int HDF5Read_finish(CSOUND *csound, void *inReference); void HDF5Read_checkArgumentSanity(CSOUND *csound, const HDF5Read *self); void HDF5Read_openDatasets(CSOUND *csound, HDF5Read *self); csound-6.10.0/Opcodes/hrtfearly.c000066400000000000000000002067131321653344700166520ustar00rootroot00000000000000/* Brian Carty PhD Code August 2010 binaural reverb: early reflections This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* #include "csdl.h" */ #include "csoundCore.h" #include "interlocks.h" #define SQUARE(X) ((X)*(X)) /* definitions, from mit */ #define minelev (-40) #define elevincrement (10) static const int elevationarray[14] = {56, 60, 72, 72, 72, 72, 72, 60, 56, 45, 36, 24, 12, 1 }; /* for ppc byte switch */ #ifdef WORDS_BIGENDIAN static int swap4bytes(CSOUND* csound, MEMFIL* mfp) { char c1, c2, c3, c4; char *p = mfp->beginp; int size = mfp->length; while (size >= 4) { c1 = p[0]; c2 = p[1]; c3 = p[2]; c4 = p[3]; p[0] = c4; p[1] = c3; p[2] = c2; p[3] = c1; size -= 4; p +=4; } return OK; } #else static int (*swap4bytes)(CSOUND*, MEMFIL*) = NULL; #endif /* low pass filter for overall surface shape */ MYFLT filter(MYFLT* sig, MYFLT highcoeff, MYFLT lowcoeff, MYFLT *del, int vecsize, MYFLT sr) { MYFLT costh, coef; int i; /* setup filter */ MYFLT T = FL(1.0) / sr; MYFLT twopioversr = FL(2.0 * PI * T); MYFLT freq; MYFLT check; MYFLT scale, nyqresponse, irttwo, highresponse, lowresponse, cosw, a, b, c, x, y; irttwo = FL(1.0) / SQRT(FL(2.0)); /* simple filter deals with difference in low and high */ highresponse = FL(1.0) - highcoeff; lowresponse = FL(1.0) - lowcoeff; /* scale factor: walls assumed to be low pass */ scale = lowresponse; nyqresponse = highresponse + lowcoeff; /* should always be lowpass! */ if (nyqresponse > irttwo) nyqresponse = irttwo; /* calculate cutoff, according to nyqresponse */ /* w = twopioversr * f (= sr / (MYFLT)2.0) (w = pi in the case of nyq...2pi/sr * sr/2) */ /* cosw = (MYFLT)cos(w);... = -1 in case of nyq */ cosw = -FL(1.0); a = c = SQUARE(nyqresponse) - FL(1.0); b = (FL(2.0) * cosw * SQUARE(nyqresponse)) - FL(2.0); /* '+' and '-' sqrt in quadratic equation give equal results in this scenario: working backwards to find cutoff freq of simple tone filter! */ x = (-b + (SQRT(SQUARE(b) - FL(4.0) * a * c))) / (FL(2.0) * a); y = (-SQUARE(x) - FL(1.0)) / (FL(2.0) * x); check = FL(2.0) - y; /* check for legal acos arg */ if (check < -FL(1.0)) check = -FL(1.0); freq = FL(acos(check)); freq /= twopioversr; /* filter */ costh = FL(2.0) - COS(freq * twopioversr); coef = SQRT(costh * costh - 1.0) - costh; for(i = 0; i < vecsize; i++) { /* filter */ sig[i] = (sig[i] * (1 + coef) - *del * coef); /* scale */ sig[i] *= scale; /* store */ *del = sig[i]; } return *sig; } /* band pass for surface detail, from csound eqfil */ MYFLT band(MYFLT* sig, MYFLT cfreq, MYFLT bw, MYFLT g, MYFLT *del, int vecsize, MYFLT sr) { MYFLT T = FL(1.0) / sr; MYFLT pioversr = FL(PI) * T; MYFLT a = (COS(cfreq * pioversr * 2.0)); MYFLT b = (TAN(bw * pioversr)); MYFLT c = (FL(1.0) - b) / (FL(1.0) + b); MYFLT w, y; int i; for(i = 0; i < vecsize; i++) { w = sig[i] + a * (FL(1.0) + c) * del[0] - c * del[1]; y = w * c - a * (FL(1.0) + c) * del[0] + del[1]; sig[i] = FL(0.5) * (y + sig[i] + g * (sig[i] - y)); del[1] = del[0]; del[0] = w; } return *sig; } typedef struct { OPDS h; /* out l/r, low rt60, high rt60, amp, delay for latediffuse */ MYFLT *outsigl, *outsigr, *irt60low, *irt60high, *imfp; /* input, source, listener, hrtf files, default room, [fadelength, sr, order, threed, headrot, roomsize, wall high and low absorb coeffs, gain for 3 band pass, same for floor and ceiling] */ MYFLT *in, *srcx, *srcy, *srcz, *lstnrx, *lstnry, *lstnrz; STRINGDAT *ifilel, *ifiler; MYFLT *idefroom, *ofade, *osr, *porder, *othreed, *Oheadrot, *ormx, *ormy, *ormz, *owlh, *owll, *owlg1, *owlg2, *owlg3, *oflh, *ofll, *oflg1, *oflg2, *oflg3,*oclh, *ocll, *oclg1, *oclg2, *oclg3; /* check if relative source has changed, to avoid recalculations */ MYFLT srcxv, srcyv, srczv, lstnrxv, lstnryv, lstnrzv; MYFLT srcxk, srcyk, srczk, lstnrxk, lstnryk, lstnrzk; MYFLT rotatev; /* processing buffer sizes, depends on sr */ int irlength, irlengthpad, overlapsize; MYFLT sr; int counter; /* crossfade preparation and checks */ int fade, fadebuffer; int initialfade; /* interpolation buffer declaration */ AUXCH lowl1, lowr1, lowl2, lowr2; AUXCH highl1, highr1, highl2, highr2; AUXCH hrtflinterp, hrtfrinterp, hrtflpad, hrtfrpad; AUXCH hrtflpadold, hrtfrpadold; /* convolution and in/output buffers */ AUXCH inbuf,inbufpad; AUXCH outlspec, outrspec; AUXCH outlspecold, outrspecold; AUXCH overlapl, overlapr; AUXCH overlaplold, overlaprold; /* no of impulses based on order */ int impulses, order; int M; /* 3d check*/ int threed; /* speed of sound*/ MYFLT c; /* Image Model*/ MYFLT rmx, rmy, rmz; int maxdelsamps; /* for each reflection*/ AUXCH hrtflpadspec, hrtfrpadspec, hrtflpadspecold, hrtfrpadspecold; AUXCH outl, outr, outlold, outrold; AUXCH currentphasel, currentphaser; AUXCH dell, delr; AUXCH tempsrcx, tempsrcy, tempsrcz; AUXCH dist; AUXCH dtime; AUXCH amp; /* temp o/p buffers */ AUXCH predell, predelr; /* processing values that need to be kept for each reflection*/ /* dynamic values based on no. fo impulses*/ AUXCH oldelevindex, oldangleindex; AUXCH cross, l, delp, skipdel; AUXCH vdt; /* wall details */ MYFLT wallcoeflow, wallcoefhigh, wallg1, wallg2, wallg3; MYFLT floorcoeflow, floorcoefhigh, floorg1, floorg2, floorg3; MYFLT ceilingcoeflow, ceilingcoefhigh, ceilingg1, ceilingg2, ceilingg3; /* wall filter q*/ MYFLT q; /* file pointers*/ float *fpbeginl, *fpbeginr; } early; static int early_init(CSOUND *csound, early *p) { /* iterator */ int i; /* left and right data files: spectral mag, phase format.*/ MEMFIL *fpl=NULL, *fpr=NULL; char filel[MAXNAME],filer[MAXNAME]; /* processing sizes*/ int irlength = 0, irlengthpad = 0, overlapsize = 0; /* walls: surface area*/ MYFLT wallS1, wallS2, cfS; /* rt60 */ MYFLT Salphalow, Salphahigh; MYFLT vol; /* room */ MYFLT rmx, rmy, rmz; /* default room */ int defroom; /* dynamic values, based on number of impulses...*/ int *oldelevindex; int *oldangleindex; int *skipdel; /* order calculation */ int impulses = 1; int temp = 2; /* defs for delay lines */ MYFLT maxdist = FL(0.0); MYFLT maxdtime; int maxdelsamps; /* late tail */ MYFLT meanfreepath; MYFLT surfacearea = FL(0.0); /* setup defaults for optional parameters */ int fade = (int)*p->ofade; MYFLT sr = *p->osr; int threed = (int)*p->othreed; int order = (int)*p->porder; /* fade length: default 8, max 24, min 1 (fade is a local variable)*/ if (fade < 1 || fade > 24) fade = 8; p->fade = fade; /* threed defaults to 2d! */ if (threed < 0 || threed > 1) threed = 0; p->threed = threed; /* order: max 4, default 1 */ if (order < 0 || order > 4) order = 1; p->order = order; /* sr, defualt 44100 */ if (sr != 44100 && sr != 48000 && sr != 96000) sr = 44100; p->sr = sr; if (UNLIKELY(CS_ESR != sr)) csound->Message(csound, Str("\n\nWARNING!!:\nOrchestra SR not compatible " "with HRTF processing SR of: %.0f\n\n"), sr); /* setup as per sr */ if (sr == 44100 || sr == 48000) { irlength = 128; irlengthpad = 256; overlapsize = (irlength - 1); } else if (sr == 96000) { irlength = 256; irlengthpad = 512; overlapsize = (irlength - 1); } /* copy in string name...*/ strncpy(filel, (char*) p->ifilel->data, MAXNAME-1); filel[MAXNAME-1]='\0'; strncpy(filer, (char*) p->ifiler->data, MAXNAME-1); filer[MAXNAME-1]='\0'; /* reading files, with byte swap */ fpl = csound->ldmemfile2withCB(csound, filel, CSFTYPE_FLOATS_BINARY, swap4bytes); if (UNLIKELY(fpl == NULL)) return csound->InitError(csound, Str("\n\n\nCannot load left data file, exiting\n\n")); fpr = csound->ldmemfile2withCB(csound, filer, CSFTYPE_FLOATS_BINARY, swap4bytes); if (UNLIKELY(fpr == NULL)) return csound->InitError(csound, Str("\n\n\nCannot load right data file, exiting\n\n")); /* file handles */ p->fpbeginl = (float *) fpl->beginp; p->fpbeginr = (float *) fpr->beginp; /* setup structure values */ p->irlength = irlength; p->irlengthpad = irlengthpad; p->overlapsize = overlapsize; p->c = 344.0; /* zero structure values */ p->counter = 0; p->initialfade = 0; p->M = 0; /* the amount of buffers to fade over */ p->fadebuffer = (int)fade * irlength; defroom = (int)*p->idefroom; /* 3 default rooms allowed*/ if (defroom > 3) defroom = 1; /* setup wall coeffs: walls: plasterboard, ceiling: painted plaster, floor: carpet if any default room is chosen, default parameters for walls/ceiling/floor */ if (defroom) { p->wallcoefhigh = FL(0.3); p->wallcoeflow = FL(0.1); p->wallg1 = FL(0.75); p->wallg2 = FL(0.95); p->wallg3 = FL(0.9); p->floorcoefhigh = FL(0.6); p->floorcoeflow = FL(0.1); p->floorg1 = FL(0.95); p->floorg2 = FL(0.6); p->floorg3 = FL(0.35); p->ceilingcoefhigh = FL(0.2); p->ceilingcoeflow = FL(0.1); p->ceilingg1 = FL(1.0); p->ceilingg2 = FL(1.0); p->ceilingg3 = FL(1.0); } /* otherwise use values, if valid */ else { p->wallcoefhigh = (*p->owlh > FL(0.0) && *p->owlh < FL(1.0)) ? *p->owlh : FL(0.3); p->wallcoeflow = (*p->owll > FL(0.0) && *p->owll < FL(1.0)) ? *p->owll : FL(0.1); p->wallg1 = (*p->owlg1 > FL(0.0) && *p->owlg1 < FL(10.0)) ? *p->owlg1 : FL(0.75); p->wallg2 = (*p->owlg2 > FL(0.0) && *p->owlg2 < FL(10.0)) ? *p->owlg2 : FL(0.95); p->wallg3 = (*p->owlg3 > FL(0.0) && *p->owlg3 < FL(10.0)) ? *p->owlg3 : FL(0.9); p->floorcoefhigh = (*p->oflh > FL(0.0) && *p->oflh < FL(1.0)) ? *p->oflh : FL(0.6); p->floorcoeflow = (*p->ofll > FL(0.0) && *p->ofll < FL(1.0)) ? *p->ofll : FL(0.1); p->floorg1 = (*p->oflg1 > FL(0.0) && *p->oflg1 < FL(10.0)) ? *p->oflg1 : FL(0.95); p->floorg2 = (*p->oflg2 > FL(0.0) && *p->oflg2 < FL(10.0)) ? *p->oflg2 : FL(0.6); p->floorg3 = (*p->oflg3 > FL(0.0) && *p->oflg3 < FL(10.0)) ? *p->oflg3 : FL(0.35); p->ceilingcoefhigh = (*p->oclh > FL(0.0) && *p->oclh < FL(1.0)) ? *p->oclh : FL(0.2); p->ceilingcoeflow = (*p->ocll > FL(0.0) && *p->ocll < FL(1.0)) ? *p->ocll : FL(0.1); p->ceilingg1 = (*p->oclg1 > FL(0.0) && *p->oclg1 < FL(10.0)) ? *p->oclg1 : FL(1.0); p->ceilingg2 = (*p->oclg2 > FL(0.0) && *p->oclg2 < FL(10.0)) ? *p->oclg2 : FL(1.0); p->ceilingg3 = (*p->oclg3 > FL(0.0) && *p->oclg3 < FL(10.0)) ? *p->oclg3 : FL(1.0); } /* medium room */ if (defroom == 1) { rmx = 10; rmy = 10; rmz = 3; } /* small */ else if (defroom == 2) { rmx = 3; rmy = 4; rmz = 3; } /* large */ else if (defroom == 3) { rmx = 20; rmy = 25; rmz = 7; } /* read values if they exist, use medium if not valid (must be at least a 2*2*2 room! */ else { rmx = *p->ormx >= FL(2.0) ? *p->ormx : 10; rmy = *p->ormy >= FL(2.0) ? *p->ormy : 10; rmz = *p->ormz >= FL(2.0) ? *p->ormz : 4; } /* store */ p->rmx = rmx; p->rmy = rmy; p->rmz = rmz; /* how many sources? */ if (threed) { for(i = 1; i <= order; i++) { impulses += (4 * i); if (i <= (order - 1)) /* sources = 2d impulses for order, plus 2 * each preceding no of impulses eg order 2: 2d = 1 + 4 + 8 = 13, 3d + 2*5 + 2 = 25*/ temp += 2*impulses; else impulses = impulses + temp; } } else { for(i = 1; i <= order; i++) /* there will be 4 * order additional impulses for each order*/ impulses += (4*i); } p->impulses = impulses; /* allocate memory, reuse if possible: interpolation buffers */ if (!p->lowl1.auxp || p->lowl1.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->lowl1); else memset(p->lowl1.auxp, 0, irlength * sizeof(MYFLT)); if (!p->lowr1.auxp || p->lowr1.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->lowr1); else memset(p->lowr1.auxp, 0, irlength * sizeof(MYFLT)); if (!p->lowl2.auxp || p->lowl2.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->lowl2); else memset(p->lowl2.auxp, 0, irlength * sizeof(MYFLT)); if (!p->lowr2.auxp || p->lowr2.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->lowr2); else memset(p->lowr2.auxp, 0, irlength * sizeof(MYFLT)); if (!p->highl1.auxp || p->highl1.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->highl1); else memset(p->highl1.auxp, 0, irlength * sizeof(MYFLT)); if (!p->highr1.auxp || p->highr1.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->highr1); else memset(p->highr1.auxp, 0, irlength * sizeof(MYFLT)); if (!p->highl2.auxp || p->highl2.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->highl2); else memset(p->highl2.auxp, 0, irlength * sizeof(MYFLT)); if (!p->highr2.auxp || p->highr2.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->highr2); else memset(p->highr2.auxp, 0, irlength * sizeof(MYFLT)); if (!p->hrtflinterp.auxp || p->hrtflinterp.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->hrtflinterp); else memset(p->hrtflinterp.auxp, 0, irlength * sizeof(MYFLT)); if (!p->hrtfrinterp.auxp || p->hrtfrinterp.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->hrtfrinterp); else memset(p->hrtfrinterp.auxp, 0, irlength * sizeof(MYFLT)); /* hrtf processing buffers */ if (!p->hrtflpad.auxp || p->hrtflpad.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad * sizeof(MYFLT), &p->hrtflpad); if (!p->hrtfrpad.auxp || p->hrtfrpad.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad * sizeof(MYFLT), &p->hrtfrpad); if (!p->hrtflpadold.auxp || p->hrtflpadold.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad * sizeof(MYFLT), &p->hrtflpadold); if (!p->hrtfrpadold.auxp || p->hrtfrpadold.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad * sizeof(MYFLT), &p->hrtfrpadold); memset(p->hrtflpad.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->hrtfrpad.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->hrtflpadold.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->hrtfrpadold.auxp, 0, irlengthpad * sizeof(MYFLT)); /* convolution & processing */ if (!p->inbuf.auxp || p->inbuf.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->inbuf); if (!p->inbufpad.auxp || p->inbufpad.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad * sizeof(MYFLT), &p-> inbufpad); memset(p->inbuf.auxp, 0, irlength * sizeof(MYFLT)); memset(p->inbufpad.auxp, 0, irlengthpad * sizeof(MYFLT)); if (!p->outlspec.auxp || p->outlspec.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad * sizeof(MYFLT), &p->outlspec); if (!p->outrspec.auxp || p->outrspec.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad * sizeof(MYFLT), &p->outrspec); memset(p->outlspec.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->outrspec.auxp, 0, irlengthpad * sizeof(MYFLT)); if (!p->outlspecold.auxp || p->outlspecold.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad * sizeof(MYFLT), &p->outlspecold); if (!p->outrspecold.auxp || p->outrspecold.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad * sizeof(MYFLT), &p->outrspecold); memset(p->outlspecold.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->outrspecold.auxp, 0, irlengthpad * sizeof(MYFLT)); if (!p->overlapl.auxp || p->overlapl.size < overlapsize * sizeof(MYFLT)) csound->AuxAlloc(csound, overlapsize * sizeof(MYFLT), &p->overlapl); if (!p->overlapr.auxp || p->overlapr.size < overlapsize * sizeof(MYFLT)) csound->AuxAlloc(csound, overlapsize * sizeof(MYFLT), &p->overlapr); memset(p->overlapl.auxp, 0, overlapsize * sizeof(MYFLT)); memset(p->overlapr.auxp, 0, overlapsize * sizeof(MYFLT)); if (!p->overlaplold.auxp || p->overlaplold.size < overlapsize * sizeof(MYFLT)) csound->AuxAlloc(csound, overlapsize * sizeof(MYFLT), &p->overlaplold); if (!p->overlaprold.auxp || p->overlaprold.size < overlapsize * sizeof(MYFLT)) csound->AuxAlloc(csound, overlapsize * sizeof(MYFLT), &p->overlaprold); memset(p->overlaplold.auxp, 0, overlapsize * sizeof(MYFLT)); memset(p->overlaprold.auxp, 0, overlapsize * sizeof(MYFLT)); /* dynamic values, based on no. of impulses*/ if (!p->predell.auxp || p->predell.size < irlength * impulses * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * impulses * sizeof(MYFLT), &p->predell); if (!p->predelr.auxp || p->predelr.size < irlength * impulses * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * impulses * sizeof(MYFLT), &p->predelr); memset(p->predell.auxp, 0, irlength * impulses * sizeof(MYFLT)); memset(p->predelr.auxp, 0, irlength * impulses * sizeof(MYFLT)); if (!p->cross.auxp || p->cross.size < impulses * sizeof(int)) csound->AuxAlloc(csound, impulses * sizeof(int), &p->cross); if (!p->l.auxp || p->l.size < impulses * sizeof(int)) csound->AuxAlloc(csound, impulses * sizeof(int), &p->l); if (!p->delp.auxp || p->delp.size < impulses * sizeof(int)) csound->AuxAlloc(csound, impulses * sizeof(int), &p->delp); if (!p->skipdel.auxp || p->skipdel.size < impulses * sizeof(int)) csound->AuxAlloc(csound, impulses * sizeof(int), &p->skipdel); if (!p->vdt.auxp || p->vdt.size < impulses * sizeof(MYFLT)) csound->AuxAlloc(csound, impulses * sizeof(MYFLT), &p->vdt); memset(p->cross.auxp, 0, impulses * sizeof(int)); memset(p->l.auxp, 0, impulses * sizeof(int)); memset(p->delp.auxp, 0, impulses * sizeof(int)); memset(p->vdt.auxp, 0, impulses * sizeof(MYFLT)); /* skipdel looked after below */ /* values distinct to each reflection*/ if (!p->tempsrcx.auxp || p->tempsrcx.size < impulses * sizeof(MYFLT)) csound->AuxAlloc(csound, impulses * sizeof(MYFLT), &p->tempsrcx); if (!p->tempsrcy.auxp || p->tempsrcy.size < impulses * sizeof(MYFLT)) csound->AuxAlloc(csound, impulses * sizeof(MYFLT), &p->tempsrcy); if (!p->tempsrcz.auxp || p->tempsrcz.size < impulses * sizeof(MYFLT)) csound->AuxAlloc(csound, impulses * sizeof(MYFLT), &p->tempsrcz); if (!p->dist.auxp || p->dist.size < impulses * sizeof(MYFLT)) csound->AuxAlloc(csound, impulses * sizeof(MYFLT), &p->dist); if (!p->dtime.auxp || p->dtime.size < impulses * sizeof(MYFLT)) csound->AuxAlloc(csound, impulses * sizeof(MYFLT), &p->dtime); if (!p->amp.auxp || p->amp.size < impulses * sizeof(MYFLT)) csound->AuxAlloc(csound, impulses * sizeof(MYFLT), &p->amp); memset(p->tempsrcx.auxp, 0, impulses * sizeof(MYFLT)); memset(p->tempsrcy.auxp, 0, impulses * sizeof(MYFLT)); memset(p->tempsrcz.auxp, 0, impulses * sizeof(MYFLT)); memset(p->dist.auxp, 0, impulses * sizeof(MYFLT)); memset(p->dtime.auxp, 0, impulses * sizeof(MYFLT)); memset(p->amp.auxp, 0, impulses * sizeof(MYFLT)); if (!p->oldelevindex.auxp || p->oldelevindex.size < impulses * sizeof(int)) csound->AuxAlloc(csound, impulses * sizeof(int), &p->oldelevindex); if (!p->oldangleindex.auxp || p->oldangleindex.size < impulses * sizeof(int)) csound->AuxAlloc(csound, impulses * sizeof(int), &p->oldangleindex); /* no need to zero above, as filled below...*/ /* -1 for first check */ oldelevindex = (int *)p->oldelevindex.auxp; oldangleindex = (int *)p->oldangleindex.auxp; for(i = 0; i < impulses; i++) oldelevindex[i] = oldangleindex[i] = -1; /* more values distinct to each reflection */ if (!p->hrtflpadspec.auxp || p->hrtflpadspec.size < irlengthpad * impulses * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad * impulses * sizeof(MYFLT), &p->hrtflpadspec); if (!p->hrtfrpadspec.auxp || p->hrtfrpadspec.size < irlengthpad * impulses * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad * impulses * sizeof(MYFLT), &p->hrtfrpadspec); memset(p->hrtflpadspec.auxp, 0, irlengthpad * impulses * sizeof(MYFLT)); memset(p->hrtfrpadspec.auxp, 0, irlengthpad * impulses * sizeof(MYFLT)); if (!p->hrtflpadspecold.auxp || p->hrtflpadspecold.size < irlengthpad * impulses * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad * impulses * sizeof(MYFLT), &p->hrtflpadspecold); if (!p->hrtfrpadspecold.auxp || p->hrtfrpadspecold.size < irlengthpad * impulses * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad * impulses * sizeof(MYFLT), &p->hrtfrpadspecold); memset(p->hrtflpadspecold.auxp, 0, irlengthpad * impulses * sizeof(MYFLT)); memset(p->hrtfrpadspecold.auxp, 0, irlengthpad * impulses * sizeof(MYFLT)); if (!p->outl.auxp || p->outl.size < irlengthpad * impulses * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad * impulses * sizeof(MYFLT), &p->outl); if (!p->outr.auxp || p->outr.size < irlengthpad * impulses * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad * impulses * sizeof(MYFLT), &p->outr); memset(p->outl.auxp, 0, irlengthpad * impulses * sizeof(MYFLT)); memset(p->outr.auxp, 0, irlengthpad * impulses * sizeof(MYFLT)); if (!p->outlold.auxp || p->outlold.size < irlengthpad * impulses * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad * impulses * sizeof(MYFLT), &p->outlold); if (!p->outrold.auxp || p->outrold.size < irlengthpad * impulses * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad * impulses * sizeof(MYFLT), &p->outrold); memset(p->outlold.auxp, 0, irlengthpad * impulses * sizeof(MYFLT)); memset(p->outrold.auxp, 0, irlengthpad * impulses * sizeof(MYFLT)); if (!p->currentphasel.auxp || p->currentphasel.size < irlength * impulses * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * impulses * sizeof(MYFLT), &p->currentphasel); if (!p->currentphaser.auxp || p->currentphaser.size < irlength * impulses * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * impulses * sizeof(MYFLT), &p->currentphaser); memset(p->currentphasel.auxp, 0, irlength * impulses * sizeof(MYFLT)); memset(p->currentphaser.auxp, 0, irlength * impulses * sizeof(MYFLT)); /* setup rt60 calcs...*/ /* rectangular room: surface area of opposite walls, and floor/ceiling */ wallS1 = rmy * rmz; wallS2 = rmx * rmz; cfS = rmx * rmy; /* volume and surface areas, for rt60 calc, for high and low frequencies */ vol = rmx * rmy * rmz; /* add all surfaces, 2 of each wall in shoebox geometry */ Salphalow = wallS1 * (LOG(FL(1.0) - p->wallcoeflow)) * FL(2.0); Salphalow += wallS2 * (LOG(FL(1.0) - p->wallcoeflow)) * FL(2.0); Salphalow += cfS * (LOG(FL(1.0) - p->floorcoeflow)); Salphalow += cfS * (LOG(FL(1.0) - p->ceilingcoeflow)); Salphahigh = wallS1 * (LOG(FL(1.0) - p->wallcoefhigh)) * FL(2.0); Salphahigh += wallS2 * (LOG(FL(1.0) - p->wallcoefhigh)) * FL(2.0); Salphahigh += cfS * (LOG(FL(1.0) - p->floorcoefhigh)); Salphahigh += cfS * (LOG(FL(1.0) - p->ceilingcoefhigh)); /* wall filter quality factor (4 octaves for required spread!: .2666667) (2 octaves = .6667 implies 125 - 500, cf 250, 500 - 2k, cf 1k, 2000 - 8000, cf 4k) (4 octaves = = .2666667 implies 62.5 - 1000, cf 250, 250 - 4000, cf 1k, 1000 - 16k, cf 4k */ p->q = FL(0.2666667); *p->irt60low = (FL(-0.161) * vol)/Salphalow; *p->irt60high = (FL(-0.161) * vol)/Salphahigh; /* calculate max delay according to max dist from order */ /* use hypotenuse rule to get max dist */ /* could calculate per order, but designed for low order use */ maxdist = (SQRT(SQUARE(rmx) + SQUARE(rmy))); if (threed) maxdist = (SQRT(SQUARE(maxdist)+SQUARE(rmz))); maxdist = maxdist * (order + 1); maxdtime = maxdist / p->c; maxdelsamps = (int)(maxdtime * sr); p->maxdelsamps = maxdelsamps; surfacearea = FL(2.0) * wallS1 + FL(2.0) * wallS2 + FL(2.0) * cfS; meanfreepath = FL(4.0) * vol / (surfacearea * p->c); /* set output...*/ *p->imfp = meanfreepath; /* allocate delay memory for each impulse */ if (!p->dell.auxp || p->dell.size < maxdelsamps * sizeof(MYFLT) * impulses) csound->AuxAlloc(csound, maxdelsamps * sizeof(MYFLT) * impulses, &p->dell); if (!p->delr.auxp || p->delr.size < maxdelsamps * sizeof(MYFLT) * impulses) csound->AuxAlloc(csound, maxdelsamps * sizeof(MYFLT) * impulses, &p->delr); memset(p->dell.auxp, 0, maxdelsamps * impulses * sizeof(MYFLT)); memset(p->delr.auxp, 0, maxdelsamps * impulses * sizeof(MYFLT)); /* amount to skip in to each del line */ skipdel = (int *)p->skipdel.auxp; for(i = 0; i < impulses; i++) skipdel[i] = i * maxdelsamps; /* setup values used to check if relative source position has changed, start at illegal value to ensure first process read */ p->srcxv = FL(-1.0); p->srcyv = FL(-1.0); p->srczv = FL(-1.0); p->lstnrxv = FL(-1.0); p->lstnryv = FL(-1.0); p->lstnrzv = FL(-1.0); p->srcxk = FL(-1.0); p->srcyk = FL(-1.0); p->srczk = FL(-1.0); p->lstnrxk = FL(-1.0); p->lstnryk = FL(-1.0); p->lstnrzk = FL(-1.0); p->rotatev = FL(0.0); return OK; } static int early_process(CSOUND *csound, early *p) { /* iterators */ int i; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t j, nsmps = CS_KSMPS; /* local pointers to p */ MYFLT *in = p->in; MYFLT *outsigl = p->outsigl; MYFLT *outsigr = p->outsigr; int irlength = p->irlength; int irlengthpad = p->irlengthpad; int overlapsize = p->overlapsize; int counter = p->counter; /* convolution buffers */ MYFLT *lowl1 = (MYFLT *)p->lowl1.auxp; MYFLT *lowr1 = (MYFLT *)p->lowr1.auxp; MYFLT *lowl2 = (MYFLT *)p->lowl2.auxp; MYFLT *lowr2 = (MYFLT *)p->lowr2.auxp; MYFLT *highl1 = (MYFLT *)p->highl1.auxp; MYFLT *highr1 = (MYFLT *)p->highr1.auxp; MYFLT *highl2 = (MYFLT *)p->highl2.auxp; MYFLT *highr2 = (MYFLT *)p->highr2.auxp; MYFLT *hrtflinterp = (MYFLT *)p->hrtflinterp.auxp; MYFLT *hrtfrinterp = (MYFLT *)p->hrtfrinterp.auxp; /* hrtf processing buffers */ MYFLT *hrtflpad = (MYFLT *)p->hrtflpad.auxp; MYFLT *hrtfrpad = (MYFLT *)p->hrtfrpad.auxp; MYFLT *hrtflpadold = (MYFLT *)p->hrtflpadold.auxp; MYFLT *hrtfrpadold = (MYFLT *)p->hrtfrpadold.auxp; /* pointers into HRTF files: floating point data(even in 64 bit csound) */ float *fpindexl = (float *)p->fpbeginl; float *fpindexr = (float *)p->fpbeginr; /* local copies */ MYFLT srcx = *p->srcx; MYFLT srcy = *p->srcy; MYFLT srcz = *p->srcz; MYFLT lstnrx = *p->lstnrx; MYFLT lstnry = *p->lstnry; MYFLT lstnrz = *p->lstnrz; MYFLT rotate = *p->Oheadrot; MYFLT sr = p->sr; /* local variables, mainly used for simplification */ MYFLT elevindexstore; MYFLT angleindexlowstore; MYFLT angleindexhighstore; /* for reading */ MYFLT angle, elev; int elevindex; int angleindex; int skip = 0; /* crossfade preparation and checks */ int fade = p->fade; int fadebuffer = p->fadebuffer; int initialfade = p->initialfade; int crossfade; int crossout; /* interpolation variable declaration: local */ int elevindexlow, elevindexhigh, angleindex1, angleindex2, angleindex3, angleindex4; MYFLT elevindexhighper, angleindex2per, angleindex4per; MYFLT magllow, magrlow, maglhigh, magrhigh, magl, magr, phasel, phaser; /* convolution and in/output buffers */ MYFLT *inbuf = (MYFLT *)p->inbuf.auxp; MYFLT *inbufpad = (MYFLT *)p->inbufpad.auxp; MYFLT *outlspec = (MYFLT *)p->outlspec.auxp; MYFLT *outrspec = (MYFLT *)p->outrspec.auxp; MYFLT *outlspecold = (MYFLT *)p->outlspecold.auxp; MYFLT *outrspecold = (MYFLT *)p->outrspecold.auxp; MYFLT *overlapl = (MYFLT *)p->overlapl.auxp; MYFLT *overlapr = (MYFLT *)p->overlapr.auxp; MYFLT *overlaplold = (MYFLT *)p->overlaplold.auxp; MYFLT *overlaprold = (MYFLT *)p->overlaprold.auxp; MYFLT *predell = (MYFLT *)p->predell.auxp; MYFLT *predelr = (MYFLT *)p->predelr.auxp; MYFLT outltot, outrtot; /* distinct to each reflection */ MYFLT *hrtflpadspec = (MYFLT *)p->hrtflpadspec.auxp; MYFLT *hrtfrpadspec = (MYFLT *)p->hrtfrpadspec.auxp; MYFLT *hrtflpadspecold = (MYFLT *)p->hrtflpadspecold.auxp; MYFLT *hrtfrpadspecold = (MYFLT *)p->hrtfrpadspecold.auxp; MYFLT *outl = (MYFLT *)p->outl.auxp; MYFLT *outr = (MYFLT *)p->outr.auxp; MYFLT *outlold = (MYFLT *)p->outlold.auxp; MYFLT *outrold = (MYFLT *)p->outrold.auxp; MYFLT *currentphasel = (MYFLT *)p->currentphasel.auxp; MYFLT *currentphaser = (MYFLT *)p->currentphaser.auxp; MYFLT *dell = (MYFLT *)p->dell.auxp; MYFLT *delr = (MYFLT *)p->delr.auxp; /* as above */ int *oldelevindex = (int *)p->oldelevindex.auxp; int *oldangleindex = (int *)p->oldangleindex.auxp; int *cross = (int *)p->cross.auxp; int *l = (int *)p->l.auxp; int *delp = (int *)p->delp.auxp; int *skipdel = (int *)p->skipdel.auxp; MYFLT *vdt = (MYFLT *)p->vdt.auxp; MYFLT *dist = (MYFLT *)p->dist.auxp; MYFLT *dtime = (MYFLT *)p->dtime.auxp; MYFLT *amp = (MYFLT *)p->amp.auxp; MYFLT *tempsrcx = (MYFLT *)p->tempsrcx.auxp; MYFLT *tempsrcy = (MYFLT *)p->tempsrcy.auxp; MYFLT *tempsrcz = (MYFLT *)p->tempsrcz.auxp; MYFLT tempdist; /* from structure */ int impulses = p->impulses; int order = p->order; int M = p->M; int threed = p->threed; /* used in vdel */ int maxdelsamps = p->maxdelsamps; MYFLT c = p->c; int pos; MYFLT rp, frac; /* room size */ MYFLT rmx = p->rmx; MYFLT rmy = p->rmy; MYFLT rmz = p->rmz; /* xc = x coordinate, etc...*/ int xc, yc, zc, lowz, highz; /* to simplify formulae, local */ MYFLT formx, formy, formz; int formxpow, formypow, formzpow; int wallreflections, floorreflections=0, ceilingreflections=0; MYFLT delsinglel, delsingler; MYFLT deldoublel[2], deldoubler[2]; /* temp variables, for efficiency */ MYFLT tempx, tempy; /* angle / elev calc of source location */ MYFLT newpntx, newpnty, newpntz; MYFLT ab,ac,bc; MYFLT coselev; /* processing size! */ //n = CS_KSMPS; /* check for legal src/lstnr locations */ /* restricted to being inside room! */ if (srcx > (rmx - FL(0.1))) srcx = rmx - FL(0.1); if (srcx < FL(0.1)) srcx = FL(0.1); if (srcy > (rmy - FL(0.1))) srcy = rmy - FL(0.1); if (srcy < FL(0.1)) srcy = FL(0.1); if (srcz > (rmz - FL(0.1))) srcz = rmz - FL(0.1); if (srcz < FL(0.1)) srcz = FL(0.1); if (lstnrx > (rmx - FL(0.1))) lstnrx = rmx - FL(0.1); if (lstnrx < FL(0.1)) lstnrx = FL(0.1); if (lstnry > (rmy - FL(0.1))) lstnry = rmy - FL(0.1); if (lstnry < FL(0.1)) lstnry = FL(0.1); if (lstnrz > (rmz - FL(0.1))) lstnrz = rmz - FL(0.1); if (lstnrz < FL(0.1)) lstnrz = FL(0.1); /* k rate computations: sources, distances, delays, amps for each image source. */ /* need minus values for formula... */ /* only update if relative source updates! improves speed in static sources by a factor of 2-3! */ if (srcx != p->srcxk || srcy != p->srcyk || srcz != p->srczk || lstnrx != p->lstnrxk || lstnry != p->lstnryk || lstnrz != p->lstnrzk) { p->srcxk = srcx; p->srcyk = srcy; p->srczk = srcz; p->lstnrxk = lstnrx; p->lstnryk = lstnry; p->lstnrzk = lstnrz; for (xc = -order; xc <= order; xc++) { for (yc = abs(xc) - order; yc <= order - abs(xc); yc++) { /* only scroll through z plane if 3d required...*/ if (threed) { lowz = abs(yc) - (order - abs(xc)); highz = (order - abs(xc)) - abs(yc); } else { lowz = 0; highz = 0; } for (zc = lowz; zc <= highz; zc++) { /* to avoid recalculation, especially at audio rate for delay, later on */ formxpow = (int)pow(-1.0, xc); formypow = (int)pow(-1.0, yc); formzpow = (int)pow(-1.0, zc); formx = (xc + (1 - formxpow)/2) * rmx; formy = (yc + (1 - formypow)/2) * rmy; formz = (zc + (1 - formzpow)/2) * rmz; /* image */ tempsrcx[M] = formxpow * srcx + formx; tempsrcy[M] = formypow * srcy + formy; tempsrcz[M] = formzpow * srcz + formz; /* Calculate delay here using source and listener location */ dist[M] = (SQRT(SQUARE(tempsrcx[M] - lstnrx) + SQUARE(tempsrcy[M] - lstnry) + SQUARE(tempsrcz[M] - lstnrz))); /* in seconds... */ dtime[M] = dist[M] / c; /* furthest allowable distance....max amp = 1. */ tempdist = (dist[M] < FL(0.45) ? FL(0.45) : dist[M]); /* high amp value may cause clipping on early reflections...reduce overall amp if so...*/ /* SPL inverse distance law */ amp[M] = FL(0.45) / tempdist; /* vdels for distance processing: */ vdt[M] = dtime[M] * sr; if (vdt[M] > maxdelsamps) vdt[M] = (MYFLT)maxdelsamps; M++; M = M % impulses; } } } } /* a rate... */ if (UNLIKELY(offset)) { memset(outsigl, '\0', offset*sizeof(MYFLT)); memset(outsigr, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&outsigl[nsmps], '\0', early*sizeof(MYFLT)); memset(&outsigr[nsmps], '\0', early*sizeof(MYFLT)); } for (j=offset;j= 0 ? (rp < maxdelsamps ? rp : rp - maxdelsamps) : rp + maxdelsamps); frac = rp - (int)rp; /* shift into correct part of buffer */ pos = (int)rp + skipdel[M]; /* write to l and r del lines */ dell[delp[M] + skipdel[M]] = predell[counter + M * irlength] * amp[M]; delr[delp[M] + skipdel[M]] = predelr[counter + M * irlength] * amp[M]; /* read, at variable interpolated speed */ outltot += dell[pos] + frac*(dell[(pos + 1 < (maxdelsamps + skipdel[M]) ? pos + 1 : skipdel[M])] - dell[pos]); outrtot += delr[pos] + frac*(delr[(pos + 1 < (maxdelsamps + skipdel[M]) ? pos + 1 : skipdel[M])] - delr[pos]); delp[M] = (delp[M] != maxdelsamps - 1 ? delp[M] + 1 : 0); outsigl[j] = outltot; outsigr[j] = outrtot; } counter++; /* used to ensure fade does not happen on first run */ if (initialfade < (irlength + 2)) initialfade++; /* 'hrtf buffer' rate */ if (counter == irlength) { /* reset */ M = 0; /* run according to formula */ for (xc = -order; xc <= order; xc++) { for (yc = abs(xc) - order; yc <= order - abs(xc); yc++) { /* only scroll through z plane if 3d required... */ if (threed) { lowz = abs(yc) - (order - abs(xc)); highz = (order - abs(xc)) - abs(yc); } else { lowz = 0; highz = 0; } for (zc = lowz; zc <= highz; zc++) { /* zero */ crossout = 0; crossfade = 0; /* avoid unnecessary processing if relative source location has not changed */ if (srcx != p->srcxv || srcy != p->srcyv || srcz != p->srczv || lstnrx != p->lstnrxv || lstnry != p->lstnryv || lstnrz != p->lstnrzv || rotate != p->rotatev) { /* if first process complete (128 samps in) and source is too close to listener: warning, do not process duda and martens range dependence jasa 98: 5 times radius: near field...hrtf changes! */ if (dist[M] < FL(0.45) && initialfade > irlength) ; /* do not process... */ else { /* to avoid case where atan2 is invalid */ tempx = tempsrcx[M] - lstnrx; tempy = tempsrcy[M] - lstnry; if (tempx == 0 && tempy == 0) angle = 0; else { /* - to invert anticlockwise to clockwise */ angle = (-(ATAN2(tempy, tempx)) * 180.0 / PI_F); /* add 90 to go from y axis (front) */ angle = angle + 90.0; } /* xy point will be same as source, z same as listener: a workable triangle */ newpntx = tempsrcx[M]; newpnty = tempsrcy[M]; newpntz = lstnrz; /* ab: source to listener, ac: source to new point under/over source, bc listener to new point */ /* a = source, b = listener, c = new point */ ab = (SQRT(SQUARE(tempsrcx[M] - lstnrx) + SQUARE(tempsrcy[M] - lstnry) + SQUARE(tempsrcz[M] - lstnrz))); ac = (SQRT(SQUARE(tempsrcx[M] - newpntx) + SQUARE(tempsrcy[M] - newpnty) + SQUARE(tempsrcz[M] - newpntz))); bc = (SQRT(SQUARE(lstnrx - newpntx) + SQUARE(lstnry - newpnty) + SQUARE(lstnrz - newpntz))); /* elev: when bc == 0 -> source + listener at same x,y point (may happen in first run, checked after that) angle = 0, elev = 0 if at same point, or source may be directly above/below */ if (bc == FL(0.0)) { /* source at listener */ if (ac == FL(0.0)) elev = FL(0.0); /* source above listener */ else elev = FL(90.0); } else { /* cosine rule */ coselev = ((SQUARE(bc) + SQUARE(ab) - SQUARE(ac)) / (2.0 * ab * bc)); elev = (ACOS(coselev)* 180.0 / PI_F); } /* if z coefficient of source < listener: source below listener...*/ if (tempsrcz[M] < lstnrz) elev *= -1; if (elev > FL(90.0)) elev = FL(90.0); if (elev < FL(-40.0)) elev = FL(-40.0); /* two nearest elev indices to avoid recalculating */ elevindexstore = (elev - minelev) / elevincrement; elevindexlow = (int)elevindexstore; if (elevindexlow < 13) elevindexhigh = elevindexlow + 1; /* highest index reached */ else elevindexhigh = elevindexlow; /* get percentage value for interpolation */ elevindexhighper = elevindexstore - elevindexlow; /* head rotation */ angle -= rotate; while(angle < FL(0.0)) angle += FL(360.0); while(angle >= FL(360.0)) angle -= FL(360.0); /* as above,lookup index, used to check for crossfade */ elevindex = (int)(elevindexstore + 0.5); angleindex = (int)(angle / (360.0 / elevationarray[elevindex]) + 0.5); angleindex = angleindex % elevationarray[elevindex]; /* avoid recalculation */ angleindexlowstore = angle / (FL(360.0) / elevationarray[elevindexlow]); angleindexhighstore = angle / (FL(360.0) / elevationarray[elevindexhigh]); /* 4 closest indices, 2 low and 2 high */ angleindex1 = (int)angleindexlowstore; angleindex2 = angleindex1 + 1; angleindex2 = angleindex2 % elevationarray[elevindexlow]; angleindex3 = (int)angleindexhighstore; angleindex4 = angleindex3 + 1; angleindex4 = angleindex4 % elevationarray[elevindexhigh]; /* angle percentages for interp */ angleindex2per = angleindexlowstore - angleindex1; angleindex4per = angleindexhighstore - angleindex3; /* crossfade happens if index changes:nearest measurement changes, 1st step: store old values */ if (oldelevindex[M] != elevindex || oldangleindex[M] != angleindex) { if (initialfade > irlength) { /* warning on overlapping fades */ if (cross[M]) { printf(Str("\nWARNING: fades are " "overlapping: this could " "lead to noise: reduce " "fade size or change " "trajectory\n\n")); cross[M] = 0; } /* reset l */ l[M] = 0; crossfade = 1; for (i = 0; i < irlengthpad; i++) { hrtflpadspecold[irlengthpad * M + i] = hrtflpadspec[irlengthpad * M + i]; hrtfrpadspecold[irlengthpad * M + i] = hrtfrpadspec[irlengthpad * M + i]; } } skip = 0; /* store current phase */ if (angleindex > elevationarray[elevindex] / 2) { for (i = 0; i < elevindex; i ++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < (elevationarray[elevindex] - angleindex); i++) skip += irlength; for (i = 0; i < irlength; i++) { currentphasel[irlength * M + i] = fpindexr[skip + i]; currentphaser[irlength * M + i] = fpindexl[skip + i]; } } else { for (i = 0; i < elevindex; i ++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < angleindex; i++) skip += irlength; for (i = 0; i < irlength; i++) { currentphasel[irlength * M + i] = fpindexl[skip+i]; currentphaser[irlength * M + i] = fpindexr[skip+i]; } } } /* for next check */ oldelevindex[M] = elevindex; oldangleindex[M] = angleindex; /* read 4 nearest HRTFs */ /* switch l and r */ skip = 0; if (angleindex1 > elevationarray[elevindexlow] / 2) { for (i = 0; i < elevindexlow; i ++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < (elevationarray[elevindexlow] - angleindex1); i++) skip += irlength; for (i = 0; i < irlength; i++) { lowl1[i] = fpindexr[skip+i]; lowr1[i] = fpindexl[skip+i]; } } else { for (i = 0; i < elevindexlow; i ++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < angleindex1; i++) skip += irlength; for (i = 0; i < irlength; i++) { lowl1[i] = fpindexl[skip+i]; lowr1[i] = fpindexr[skip+i]; } } skip = 0; if (angleindex2 > elevationarray[elevindexlow] / 2) { for (i = 0; i < elevindexlow; i ++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < (elevationarray[elevindexlow] - angleindex2); i++) skip += irlength; for (i = 0; i < irlength; i++) { lowl2[i] = fpindexr[skip+i]; lowr2[i] = fpindexl[skip+i]; } } else { for (i = 0; i < elevindexlow; i ++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < angleindex2; i++) skip += irlength; for (i = 0; i < irlength; i++) { lowl2[i] = fpindexl[skip+i]; lowr2[i] = fpindexr[skip+i]; } } skip = 0; if (angleindex3 > elevationarray[elevindexhigh] / 2) { for (i = 0; i < elevindexhigh; i ++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < (elevationarray[elevindexhigh] - angleindex3); i++) skip += irlength; for (i = 0; i < irlength; i++) { highl1[i] = fpindexr[skip+i]; highr1[i] = fpindexl[skip+i]; } } else { for (i = 0; i < elevindexhigh; i ++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < angleindex3; i++) skip += irlength; for (i = 0; i < irlength; i++) { highl1[i] = fpindexl[skip+i]; highr1[i] = fpindexr[skip+i]; } } skip = 0; if (angleindex4 > elevationarray[elevindexhigh] / 2) { for (i = 0; i < elevindexhigh; i ++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < (elevationarray[elevindexhigh] - angleindex4); i++) skip += irlength; for (i = 0; i < irlength; i++) { highl2[i] = fpindexr[skip+i]; highr2[i] = fpindexl[skip+i]; } } else { for (i = 0; i < elevindexhigh; i ++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < angleindex4; i++) skip += irlength; for (i = 0; i < irlength; i++) { highl2[i] = fpindexl[skip+i]; highr2[i] = fpindexr[skip+i]; } } /* magnitude interpolation */ /* 0hz and Nyq */ magllow = (FABS(lowl1[0])) + ((FABS(lowl2[0]) - FABS(lowl1[0]))) * angleindex2per; maglhigh = (FABS(highl1[0])) + ((FABS(highl2[0]) - FABS(highl1[0]))) * angleindex4per; magrlow = (FABS(lowr1[0])) + ((FABS(lowr2[0]) - FABS(lowr1[0]))) * angleindex2per; magrhigh = (FABS(highr1[0])) + ((FABS(highr2[0]) - FABS(highr1[0]))) * angleindex4per; magl = magllow + (maglhigh - magllow) * elevindexhighper; magr = magrlow + (magrhigh - magrlow) * elevindexhighper; if (currentphasel[M * irlength] < FL(0.0)) hrtflinterp[0] = - magl; else hrtflinterp[0] = magl; if (currentphaser[M * irlength] < FL(0.0)) hrtfrinterp[0] = - magr; else hrtfrinterp[0] = magr; magllow = (FABS(lowl1[1])) + ((FABS(lowl2[1]) - FABS(lowl1[1]))) * angleindex2per; maglhigh = (FABS(highl1[1])) + ((FABS(highl2[1]) - FABS(highl1[1]))) * angleindex4per; magrlow = (FABS(lowr1[1])) + ((FABS(lowr2[1]) - FABS(lowr1[1]))) * angleindex2per; magrhigh = (FABS(highr1[1])) + ((FABS(highr2[1]) - FABS(highr1[1]))) * angleindex4per; magl = magllow + (maglhigh - magllow) * elevindexhighper; magr = magrlow + (magrhigh - magrlow) * elevindexhighper; if (currentphasel[M * irlength + 1] < FL(0.0)) hrtflinterp[1] = - magl; else hrtflinterp[1] = magl; if (currentphaser[M * irlength + 1] < FL(0.0)) hrtfrinterp[1] = - magr; else hrtfrinterp[1] = magr; /* other values are complex, in fftw format */ for (i = 2; i < irlength; i += 2) { /* interpolate high and low magnitudes */ magllow = lowl1[i] + (lowl2[i] - lowl1[i]) * angleindex2per; maglhigh = highl1[i] + (highl2[i] - highl1[i]) * angleindex4per; magrlow = lowr1[i] + (lowr2[i] - lowr1[i]) * angleindex2per; magrhigh = highr1[i] + (highr2[i] - highr1[i]) * angleindex4per; /* interpolate high and low results, use current phase */ magl = magllow + (maglhigh - magllow) * elevindexhighper; phasel = currentphasel[M * irlength + i + 1]; /* polar to rectangular */ hrtflinterp[i] = magl * FL(cos(phasel)); hrtflinterp[i + 1] = magl * FL(sin(phasel)); magr = magrlow + (magrhigh - magrlow) * elevindexhighper; phaser = currentphaser[M * irlength + i + 1]; hrtfrinterp[i] = magr * FL(cos(phaser)); hrtfrinterp[i + 1] = magr * FL(sin(phaser)); } csound->InverseRealFFT(csound, hrtflinterp, irlength); csound->InverseRealFFT(csound, hrtfrinterp, irlength); /* wall filters... */ /* all 4 walls are the same! (trivial to make them different...) */ /* x axis, wall1 (left) */ wallreflections = (int)abs((int)(xc * .5 - .25 + (0.25 * pow(-1.0, xc)))); /* wall2, x (right) */ wallreflections += (int)abs((int)(xc * .5 + .25 - (0.25 * pow(-1.0, xc)))); /* yaxis, wall3 (bottom) */ wallreflections += (int)abs((int)(yc * .5 - .25 + (0.25 * pow(-1.0, yc)))); /* yaxis, wall 4 (top) */ wallreflections += (int)abs((int)(yc * .5 + .25 - (0.25 * pow(-1.0, yc)))); if (threed) { /* floor (negative z) */ floorreflections = (int)abs((int)(zc * .5 - .25 + (0.25 * pow(-1.0, zc)))); /* ceiling (positive z) */ ceilingreflections = (int)abs((int)(zc * .5 + .25 - (0.25 * pow(-1.0, zc)))); } /* fixed parameters on bands etc (to limit no of inputs), but these could trivially be variable */ /* note: delay values can be reused: zeroed every time as only used in processing hrtf, once every irlength, so not used continuously...*/ /* if processing was continuous, would need separate mem for each filter, store for next run etc...*/ for (i = 0; i < wallreflections; i++) { delsinglel = delsingler = FL(0.0); filter(hrtflinterp, p->wallcoefhigh, p->wallcoeflow, &delsinglel, irlength, sr); filter(hrtfrinterp, p->wallcoefhigh, p->wallcoeflow, &delsingler, irlength, sr); deldoublel[0] = deldoublel[1] = deldoubler[0] = deldoubler[1] = 0.0; band(hrtflinterp, FL(250.0), FL(250.0) / p->q, p->wallg1, deldoublel, irlength, sr); band(hrtfrinterp, FL(250.0), FL(250.0) / p->q, p->wallg1, deldoubler, irlength, sr); deldoublel[0] = deldoublel[1] = deldoubler[0] = deldoubler[1] = 0.0; band(hrtflinterp, FL(1000.0), FL(1000.0) / p->q, p->wallg2, deldoublel, irlength, sr); band(hrtfrinterp, FL(1000.0), FL(1000.0) / p->q, p->wallg2, deldoubler, irlength, sr); deldoublel[0] = deldoublel[1] = deldoubler[0] = deldoubler[1] = 0.0; band(hrtflinterp, FL(4000.0), FL(4000.0) / p->q, p->wallg3, deldoublel, irlength, sr); band(hrtfrinterp, FL(4000.0), FL(4000.0) / p->q, p->wallg3, deldoubler, irlength, sr); } if (threed) { for (i = 0; i < floorreflections; i++) { delsinglel = delsingler = FL(0.0); filter(hrtflinterp, p->floorcoefhigh, p->floorcoeflow, &delsinglel, irlength, sr); filter(hrtfrinterp, p->floorcoefhigh, p->floorcoeflow, &delsingler, irlength, sr); deldoublel[0] = deldoublel[1] = deldoubler[0] = deldoubler[1] = 0.0; band(hrtflinterp, FL(250.0), FL(250.0) / p->q, p->floorg1, deldoublel, irlength, sr); band(hrtfrinterp, FL(250.0), FL(250.0) / p->q, p->floorg1, deldoubler, irlength, sr); deldoublel[0] = deldoublel[1] = deldoubler[0] = deldoubler[1] = 0.0; band(hrtflinterp, FL(1000.0), FL(1000.0) / p->q, p->floorg2, deldoublel, irlength, sr); band(hrtfrinterp, FL(1000.0), FL(1000.0) / p->q, p->floorg2, deldoubler, irlength, sr); deldoublel[0] = deldoublel[1] = deldoubler[0] = deldoubler[1] = 0.0; band(hrtflinterp, FL(4000.0), FL(4000.0) / p->q, p->floorg3, deldoublel, irlength, sr); band(hrtfrinterp, FL(4000.0), FL(4000.0) / p->q, p->floorg3, deldoubler, irlength, sr); } for (i = 0; i < ceilingreflections; i++) { delsinglel = delsingler = FL(0.0); filter(hrtflinterp, p->ceilingcoefhigh, p->ceilingcoeflow, &delsinglel, irlength, sr); filter(hrtfrinterp, p->ceilingcoefhigh, p->ceilingcoeflow, &delsingler, irlength, sr); deldoublel[0] = deldoublel[1] = deldoubler[0] = deldoubler[1] = 0.0; band(hrtflinterp, FL(250.0), FL(250.0) / p->q, p->ceilingg1, deldoublel, irlength, sr); band(hrtfrinterp, FL(250.0), FL(250.0) / p->q, p->ceilingg1, deldoubler, irlength, sr); deldoublel[0] = deldoublel[1] = deldoubler[0] = deldoubler[1] = 0.0; band(hrtflinterp, FL(1000.0), FL(1000.0) / p->q, p->ceilingg2, deldoublel, irlength, sr); band(hrtfrinterp, FL(1000.0), FL(1000.0) / p->q, p->ceilingg2, deldoubler, irlength, sr); deldoublel[0] = deldoublel[1] = deldoubler[0] = deldoubler[1] = 0.0; band(hrtflinterp, FL(4000.0), FL(4000.0) / p->q, p->ceilingg3, deldoublel, irlength, sr); band(hrtfrinterp, FL(4000.0), FL(4000.0) / p->q, p->ceilingg3, deldoubler, irlength, sr); } } for (i = 0; i < irlength; i++) { hrtflpad[i] = hrtflinterp[i]; hrtfrpad[i] = hrtfrinterp[i]; } for (i = irlength; i < irlengthpad; i++) { hrtflpad[i] = FL(0.0); hrtfrpad[i] = FL(0.0); } /* back to freq domain */ csound->RealFFT(csound, hrtflpad, irlengthpad); csound->RealFFT(csound, hrtfrpad, irlengthpad); /* store */ for (i = 0; i < irlengthpad; i++) { hrtflpadspec[M * irlengthpad + i] = hrtflpad[i]; hrtfrpadspec[M * irlengthpad + i] = hrtfrpad[i]; } } } /* end of source / listener relative change process */ /* look after overlap add */ for (i = 0; i < overlapsize ; i++) { overlapl[i] = outl[M * irlengthpad + i + irlength]; overlapr[i] = outr[M * irlengthpad + i + irlength]; if (crossfade) { overlaplold[i] = outl[M * irlengthpad + i + irlength]; overlaprold[i] = outr[M * irlengthpad + i + irlength]; } /* overlap will be previous fading out signal */ if (cross[M]) { overlaplold[i] = outlold[M * irlengthpad + i + irlength]; overlaprold[i] = outrold[M * irlengthpad + i + irlength]; } } /* insert insig */ for (i = 0; i < irlength; i++) inbufpad[i] = inbuf[i]; for (i = irlength; i < irlengthpad; i++) inbufpad[i] = FL(0.0); csound->RealFFT(csound, inbufpad, irlengthpad); for (i = 0; i < irlengthpad; i ++) { hrtflpad[i] = hrtflpadspec[M * irlengthpad + i]; hrtfrpad[i] = hrtfrpadspec[M * irlengthpad + i]; } /* convolution: spectral multiplication */ csound->RealFFTMult(csound, outlspec, hrtflpad, inbufpad, irlengthpad, FL(1.0)); csound->RealFFTMult(csound, outrspec, hrtfrpad, inbufpad, irlengthpad, FL(1.0)); csound->InverseRealFFT(csound, outlspec, irlengthpad); csound->InverseRealFFT(csound, outrspec, irlengthpad); /* scale */ for (i = 0; i < irlengthpad; i++) { outlspec[i] = outlspec[i]/(sr/FL(38000.0)); outrspec[i] = outrspec[i]/(sr/FL(38000.0)); } /* store */ for (i = 0; i < irlengthpad; i++) { outl[M * irlengthpad + i] = outlspec[i]; outr[M * irlengthpad + i] = outrspec[i]; } /* setup for fades */ if (crossfade || cross[M]) { crossout = 1; /* need to put these values into a buffer for processing */ for (i = 0; i < irlengthpad; i++) { hrtflpadold[i] = hrtflpadspecold[M * irlengthpad + i]; hrtfrpadold[i] = hrtfrpadspecold[M * irlengthpad + i]; } /* convolution */ csound->RealFFTMult(csound, outlspecold, hrtflpadold, inbufpad, irlengthpad, FL(1.0)); csound->RealFFTMult(csound, outrspecold, hrtfrpadold, inbufpad, irlengthpad, FL(1.0)); /* ifft, back to time domain */ csound->InverseRealFFT(csound, outlspecold, irlengthpad); csound->InverseRealFFT(csound, outrspecold, irlengthpad); /* scale */ for (i = 0; i < irlengthpad; i++) { outlspecold[i] = outlspecold[i]/(sr/FL(38000.0)); outrspecold[i] = outrspecold[i]/(sr/FL(38000.0)); } /* o/p real values */ for (i = 0; i < irlengthpad; i++) { outlold[M * irlengthpad + i] = outlspecold[i]; outrold[M * irlengthpad + i] = outrspecold[i]; } cross[M]++; cross[M] = cross[M] % fade; } if (crossout) for (i = 0; i < irlength; i++) { predell[i + M * irlength] = (outlspecold[i] + (i < overlapsize ? overlaplold[i] : FL(0.0))) * FL(1. - (FL(l[M]) / fadebuffer)) + (outlspec[i] + (i < overlapsize ? overlapl[i] : FL(0.0))) * (FL(l[M]) / fadebuffer); predelr[i + M * irlength] = (outrspecold[i] + (i < overlapsize ? overlaprold[i] : FL(0.0))) * FL(1. - (FL(l[M]) / fadebuffer)) + (outrspec[i] + (i < overlapsize ? overlapr[i] : FL(0.0))) * (FL(l[M]) / fadebuffer); l[M]++; } else for (i = 0; i < irlength; i++) { predell[i + M * irlength] = outlspec[i] + (i < overlapsize ? overlapl[i] : FL(0.0)); predelr[i + M * irlength] = outrspec[i] + (i < overlapsize ? overlapr[i] : FL(0.0)); } M++; M = M % impulses; } /* z */ } /* y */ } /* x */ counter = 0; /* need to store these values here, as storing them after check would not allow each impulse to be processed! */ p->srcxv = srcx; p->srcyv = srcy; p->srczv = srcz; p->lstnrxv = lstnrx; p->lstnryv = lstnry; p->lstnrzv = lstnrz; p->rotatev = rotate; } /* end of counter == irlength */ /* update */ p->counter = counter; p->initialfade = initialfade; } /* end of ksmps loop */ return OK; } static OENTRY hrtfearly_localops[] = { { "hrtfearly", sizeof(early), 0,5, "aaiii", "axxxxxxSSioopoOoooooooooooooooooo", (SUBR)early_init, NULL, (SUBR)early_process } }; LINKAGE_BUILTIN(hrtfearly_localops) csound-6.10.0/Opcodes/hrtferX.c000066400000000000000000000375521321653344700162770ustar00rootroot00000000000000/* hrtferX.c: Copyright (C) 1995, 2001 Eli Breder, David McIntyre, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /*********************************************************** * FINAL PROJECT * * * * course: 216-605A * * Digital Sound Synthesis & Audio Processing * * * * * * hrtferxk.c * * ---------- * * * * Eli Breder (9111216) and David McIntyre (9005614) * * * * Dec. 17, 1995 * * * * Code modifications John ffitch January 2001 * * * ***********************************************************/ /*************************************************************** * This version of hrtfer loads the file HRTFcompact into memory. * Offsets into the file are calculated in the a-rate code to * get the requested HRTF measurements. We've implemented * a linear crossfade to deal with the clicks which occur * when the input audio is convolved with new HRTFs. Although this * the clicking, it does not eliminate them. * A better solution would be to implement interpolation between * the old and new HRTFs (probably a project in itself). ***************************************************************/ // #include "csdl.h" #include "csoundCore.h" #include "interlocks.h" #include #include #include #include "hrtferx.h" /* This array transferred here so as to be declared once. Belongs to the structure of the HRTF data really in 3Dug.h */ static const int elevation_data[N_ELEV] = {56, 60, 72, 72, 72, 72, 72, 60, 56, 45, 36, 24, 12, 1 }; #define ROUND(x) ((int)floor((x)+FL(0.5))) #define GET_NFAZ(el_index) ((elevation_data[el_index] / 2) + 1) static int hrtferxkSet(CSOUND *csound, HRTFER *p) { // int i; /* standard loop counter */ char filename[MAXNAME]; int bytrev_test; MEMFIL *mfp; /* first check if orchestra's sampling rate is compatible with HRTF measurement's */ if (UNLIKELY(CS_ESR != SAMP_RATE)) { return csound->InitError(csound, Str("Orchestra sampling rate is not compatible with HRTF.\n" "Should be %d...exiting."), SAMP_RATE); return NOTOK; /* not reached */ } if (!strcmp("HRTFcompact", p->ifilno->data)) { strncpy(filename, p->ifilno->data, MAXNAME-1); filename[MAXNAME-1] = '\0'; } else { csound->Message(csound, Str("\nLast argument must be the string " "'HRTFcompact' ...correcting.\n")); strncpy(filename, "HRTFcompact", MAXNAME); /* for safety */ } if ((mfp = p->mfp) == NULL) mfp = csound->ldmemfile2withCB(csound, filename, CSFTYPE_HRTF, NULL); p->mfp = mfp; p->fpbegin = (int16*) mfp->beginp; bytrev_test = 0x1234; if (*((unsigned char*) &bytrev_test) == (unsigned char) 0x34) { /* Byte reverse on data set if necessary */ int16 *x = p->fpbegin; int32 len = (mfp->length)/sizeof(int16); while (len != 0) { int16 v = *x; v = ((v & 0xFF) << 8) + ((v >> 8) & 0xFF); /* Swap bytes */ *x = v; x++; len--; } } /* initialize counters and indices */ p->outcount = 0; p->incount = 0; p->outfront = p->outend = 0; /* working indices for circ output buffer */ /* initialize oldhrtf_data with zeros */ /* initialize input buffer */ /* initialize left result buffer */ /* initialize right result buffer */ /* initialize left output buffer */ /* initialize right output buffer */ /* for (i=0; ix[i] = FL(0.0); */ /* p->yl[i] = FL(0.0); */ /* p->yr[i] = FL(0.0); */ /* p->outl[i] = FL(0.0); */ /* p->outr[i] = FL(0.0); */ /* } */ memset(p->x, 0, BUF_LEN*sizeof(MYFLT)); memset(p->yl, 0, BUF_LEN*sizeof(MYFLT)); memset(p->yr, 0, BUF_LEN*sizeof(MYFLT)); memset(p->outl, 0, BUF_LEN*sizeof(MYFLT)); memset(p->outr, 0, BUF_LEN*sizeof(MYFLT)); /* initialize left overlap buffer */ /* initialize right overlap buffer */ /* for (i=0; ibl[i] = FL(0.0); */ /* p->br[i] = FL(0.0); */ /* } */ memset(p->bl, 0, FILT_LENm1*sizeof(MYFLT)); memset(p->br, 0, FILT_LENm1*sizeof(MYFLT)); return OK; } /********************** a-rate code ***********************************/ static int hrtferxk(CSOUND *csound, HRTFER *p) { MYFLT *aLeft, *aRight; /* audio output streams */ MYFLT *aIn, *kAz, *kElev; /* audio and control input streams */ int azim, elev, el_index, az_index; int nsmpsi, nsmpso; /* number of samples in/out */ /* input, out-left, out-right */ MYFLT *x, *yl, *yr; /* Local copies of address */ /* overlap left, overlap right */ MYFLT *bl, *br; /* copy of current input convolved with old HRTFs */ MYFLT *outl, *outr; /* output left/right */ int outfront, outend; /* circular output indices */ int incount, outcount; /* number of samples in/out */ uint32_t toread; /* number of samples to read */ int i; /* standard loop counter */ HRTF_DATUM hrtf_data; /* local hrtf instances */ int flip; /* flag - true if we need to flip the channels */ int16 *fpindex; /* pointer into HRTF file */ int16 numskip; /* number of shorts to skip in HRTF file */ /* short arrays into which HRTFs are stored locally */ int16 sl[FILT_LEN], sr[FILT_LEN]; /* float versions of above to be sent to FFT routines */ MYFLT xl[BUF_LEN], xr[BUF_LEN]; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t ii; if (UNLIKELY(p->mfp==NULL)) goto err1; /* RWD fix */ /* update local variables */ kElev = p->kElev; kAz = p->kAz; elev = (int) *kElev; azim = (int) *kAz; //oldel_index = p->oldel_index; fpindex = (int16 *) p->fpbegin; flip = 0; /* Convert elevation in degrees to elevation array index. */ el_index = ROUND((double)(elev - MIN_ELEV) / ELEV_INC); if (el_index < 0) el_index = 0; else if (el_index >= N_ELEV) el_index = N_ELEV-1; /* Convert azimuth in degrees to azimuth array index. */ azim = (int)fmod((double)azim, 360.0); if (azim < 0) azim += 360; if (azim > 180) { azim = 360 - azim; flip = 1; /* set to true */ } /* else */ /* flip = 0; /\* it is still false *\/ */ /* azim should be 0<=azim<=180 so calculate az_index and clip to legal range note - accesses global array elevation_data */ az_index = ROUND((double)azim / (360.0 / elevation_data[el_index])); if (az_index < 0) az_index = 0; else if (az_index >= elevation_data[el_index]) az_index = elevation_data[el_index] - 1; /* calculate offset into HRTFcompact file */ /* first get to the first value of the requested elevation */ if (el_index == 0) fpindex = (int16 *) p->fpbegin; else for (i=0; i<=el_index; i++) { numskip = (int16)(GET_NFAZ(i) * BUF_LEN); fpindex += numskip; } /* fpindex should now point to first azimuth at requested el_index */ /* now get to first value of requested azimuth */ if (az_index == 0) { /* csound->Message(csound, "in az_index == 0\n"); */ numskip = 0; } else { for (i=0, numskip=0; iGetInverseRealFFTScale(csound, BUF_LEN) / FL(256.0); scaleFac /= FL(32768.0); /* copy int16 buffers into float buffers */ for (i=0; iRealFFT(csound, xl, BUF_LEN); csound->RealFFT(csound, xr, BUF_LEN); /* If azimuth called for right side of head, use left side measurements and flip output channels. This is due to the fact that the HRTFs we are using only include left side placements. */ if (flip) { for (i=0; iincount; outcount = p->outcount; outfront = p->outfront; outend = p->outend; /* Get local pointers to structures */ outl = &p->outl[0]; outr = &p->outr[0]; bl = &p->bl[0]; br = &p->br[0]; x = &p->x[0]; yl = &p->yl[0]; yr = &p->yr[0]; aIn = p->aIn; aLeft = p->aLeft; aRight = p->aRight; nsmpsi = nsmpso = CS_KSMPS; /* main loop for a-rate code. Audio read in, processed, and output in this loop. Loop exits when control period (ksmps) is finished. */ while (nsmpsi > 0) { /* determine how much audio may be read in */ if ((incount + nsmpsi) <= FILT_LEN) toread = nsmpsi; else toread = FILT_LEN - incount; /* reading in audio into x */ if (incount == 0) { for (ii = 0; ii < toread; ii++) x[ii] = *aIn++; } else { for (ii = incount; ii<(incount + toread); ii++) x[ii] = *aIn++; } /* update counters for amount of audio read */ nsmpsi -= toread; incount += toread; /* loop for audio processing */ if (incount == FILT_LEN) { /* enough audio for convolution - so do it! */ incount = 0; /* pad x to BUF_LEN with zeros for Moore FFT */ for (i = FILT_LEN; i < BUF_LEN; i++) x[i] = FL(0.0); csound->RealFFT(csound, x, BUF_LEN); /* complex multiplication, y = hrtf_data * x */ csound->RealFFTMult(csound, yl, hrtf_data.left, x, BUF_LEN, FL(1.0)); csound->RealFFTMult(csound, yr, hrtf_data.right, x, BUF_LEN, FL(1.0)); /* convolution is the inverse FFT of above result (yl,yr) */ csound->InverseRealFFT(csound, yl, BUF_LEN); csound->InverseRealFFT(csound, yr, BUF_LEN); /* overlap-add the results */ for (i = 0; i < FILT_LENm1; i++) { yl[i] += bl[i]; yr[i] += br[i]; bl[i] = yl[FILT_LEN+i]; br[i] = yr[FILT_LEN+i]; } /* put convolution ouput into circular output buffer */ if (outend <= FILT_LEN) { /* output will fit in buffer boundaries, therefore no circular reference required */ for (i = outend; i < (outend + FILT_LEN); i++) { outl[i] = yl[i-outend]; outr[i] = yr[i-outend]; } outcount += FILT_LEN; outend += FILT_LEN; } else { /* circular reference required due to buffer boundaries */ for (i = outend; i < BUF_LEN; i++) { outl[i] = yl[i-outend]; outr[i] = yr[i-outend]; } for (i = 0; i < (-FILT_LEN + outend); i++) { outl[i] = yl[(BUF_LEN-outend) + i]; outr[i] = yr[(BUF_LEN-outend) + i]; } outcount += FILT_LEN; outend -= FILT_LEN; } } /* output audio to audio stream. Can only output one control period (ksmps) worth of samples */ if (nsmpso < outcount) { if ((outfront+nsmpso) < BUF_LEN) { for (i = 0; i < nsmpso; i++) { *aLeft++ = outl[outfront + i]; *aRight++ = outr[outfront + i]; } outcount -= nsmpso; outfront += nsmpso; nsmpso = 0; } else { uint32 j = 0; /* account for circular reference */ for (i = outfront; i < BUF_LEN; i++, j++) { *aLeft++ = (jearly) ? FL(0.0) : outl[i]; *aRight++ = (jearly) ? FL(0.0) : outr[i]; } outcount -= nsmpso; nsmpso -= (BUF_LEN - outfront); for (i = 0; i < nsmpso; i++, j++) { *aLeft++ = (jearly) ? FL(0.0) : outl[i]; *aRight++ = (jearly) ? FL(0.0) : outr[i]; } outfront = nsmpso; nsmpso = 0; } } else { uint32 j = 0; if ((outfront+nsmpso) < BUF_LEN) { for (i = 0; i < outcount; i++, j++) { *aLeft++ = (jearly) ? FL(0.0) : outl[outfront + i]; *aRight++ = (jearly) ? FL(0.0) : outr[outfront + i]; } nsmpso -= outcount; outfront += outcount; outcount = 0; } else { /* account for circular reference */ for (i = outfront; i < BUF_LEN; i++, j++) { *aLeft++ = (jearly) ? FL(0.0) : outl[i]; *aRight++ = (jearly) ? FL(0.0) : outr[i]; } nsmpso -= outcount; outcount -= (BUF_LEN - outfront); for (i = 0; i < outcount; i++, j++) { *aLeft++ = (jearly) ? FL(0.0) : outl[i]; *aRight++ = (jearly) ? FL(0.0) : outr[i]; } outfront = outcount; outcount = 0; } } /* end of audio processing loop - "if" */ } /* end of control period loop - "while" */ /* update state in p */ p->outcount = outcount; p->incount = incount; p->outfront = outfront; p->outend = outend; p->oldel_index = el_index; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("hrtfer: not initialised")); } static OENTRY hrtferX_localops[] = { { "hrtfer", sizeof(HRTFER), _QQ, 5, "aa", "akkS", (SUBR)hrtferxkSet, NULL, (SUBR)hrtferxk}, }; LINKAGE_BUILTIN(hrtferX_localops) csound-6.10.0/Opcodes/hrtferx.h000066400000000000000000000030541321653344700163320ustar00rootroot00000000000000/* hrtferx.h: Copyright (C) 1995, 2001 Eli Breder, David McIntyre, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /****************** hrtferxk.h *******************/ #include "3Dug.h" typedef struct { OPDS h; MYFLT *aLeft, *aRight; /* outputs */ MYFLT *aIn, *kAz, *kElev; /* inputs */ STRINGDAT *ifilno; /* and inputs */ MEMFIL *mfp; /* file pointer */ int16 *fpbegin; int oldel_index, oldaz_index; int32 incount, outfront, outend, outcount; AUXCH auxch; /* will point to allocated memory */ HRTF_DATUM hrtf_data, oldhrtf_data; /* matrix to store HRTF data */ MYFLT outl[BUF_LEN], outr[BUF_LEN]; MYFLT x[BUF_LEN], yl[BUF_LEN], yr[BUF_LEN]; MYFLT bl[FILT_LENm1], br[FILT_LENm1]; } HRTFER; csound-6.10.0/Opcodes/hrtfopcodes.c000066400000000000000000003100671321653344700171700ustar00rootroot00000000000000/* hrtfopcodes.c: new HRTF opcodes (c) Brian Carty, 2010 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "interlocks.h" #include /* definitions */ /* from mit */ #define minelev (-40) #define elevincrement (10) /* max delay for min phase: a time value: multiply by sr to get no of samples for memory allocation */ #define maxdeltime (0.0011) /* additional definitions for woodworth models */ #define c (34400.0) /* hrtf data sets were analysed for low frequency phase values, as it is the important part of the spectrum for phase based localisation cues. The values below were extracted and are used to scale the functional phase spectrum. radius: 8.8 cm see nonlinitd.cpp */ static const float nonlinitd[5] = {1.570024f, 1.378733f, 1.155164f, 1.101230f,1.0f}; static const float nonlinitd48k[5] = {1.549748f, 1.305457f, 1.124501f, 1.112852f,1.0f}; static const float nonlinitd96k[5] = {1.550297f, 1.305671f, 1.124456f, 1.112818f,1.0f}; /* number of measurements per elev: mit data const:read only, static:exists for whole process... */ static const int elevationarray[14] = {56, 60, 72, 72, 72, 72, 72, 60, 56, 45, 36, 24, 12, 1 }; /* assumed mit hrtf data will be used here. Otherwise delay data would need to be extracted and replaced here... */ static const float minphasedels[368] = { 0.000000f, 0.000045f, 0.000091f, 0.000136f, 0.000159f, 0.000204f, 0.000249f, 0.000272f, 0.000295f, 0.000317f, 0.000363f, 0.000385f, 0.000272f, 0.000408f, 0.000454f, 0.000454f, 0.000408f, 0.000385f, 0.000363f, 0.000317f, 0.000295f, 0.000295f, 0.000249f, 0.000204f, 0.000159f, 0.000136f, 0.000091f, 0.000045f, 0.000000f, 0.000000f, 0.000045f, 0.000091f, 0.000136f, 0.000181f, 0.000227f, 0.000249f, 0.000272f, 0.000317f, 0.000363f, 0.000385f, 0.000454f, 0.000476f, 0.000454f, 0.000522f, 0.000499f, 0.000499f, 0.000476f, 0.000454f, 0.000408f, 0.000408f, 0.000385f, 0.000340f, 0.000295f, 0.000272f, 0.000227f, 0.000181f, 0.000136f, 0.000091f, 0.000045f, 0.000000f, 0.000000f, 0.000045f, 0.000091f, 0.000113f, 0.000159f, 0.000204f, 0.000227f, 0.000272f, 0.000317f, 0.000317f, 0.000363f, 0.000408f, 0.000363f, 0.000522f, 0.000476f, 0.000499f, 0.000590f, 0.000567f, 0.000567f, 0.000544f, 0.000522f, 0.000499f, 0.000476f, 0.000454f, 0.000431f, 0.000408f, 0.000385f, 0.000363f, 0.000317f, 0.000295f, 0.000249f, 0.000204f, 0.000181f, 0.000136f, 0.000091f, 0.000045f, 0.000000f, 0.000000f, 0.000045f, 0.000091f, 0.000113f, 0.000159f, 0.000204f, 0.000249f, 0.000295f, 0.000317f, 0.000363f, 0.000340f, 0.000385f, 0.000431f, 0.000476f, 0.000522f, 0.000544f, 0.000612f, 0.000658f, 0.000658f, 0.000635f, 0.000658f, 0.000522f, 0.000499f, 0.000476f, 0.000454f, 0.000408f, 0.000385f, 0.000363f, 0.000340f, 0.000295f, 0.000272f, 0.000227f, 0.000181f, 0.000136f, 0.000091f, 0.000045f, 0.000000f, 0.000000f, 0.000045f, 0.000091f, 0.000136f, 0.000159f, 0.000204f, 0.000249f, 0.000295f, 0.000340f, 0.000385f, 0.000431f, 0.000476f, 0.000522f, 0.000567f, 0.000522f, 0.000567f, 0.000567f, 0.000635f, 0.000703f, 0.000748f, 0.000748f, 0.000726f, 0.000703f, 0.000658f, 0.000454f, 0.000431f, 0.000385f, 0.000363f, 0.000317f, 0.000295f, 0.000272f, 0.000227f, 0.000181f, 0.000136f, 0.000091f, 0.000045f, 0.000000f, 0.000000f, 0.000045f, 0.000091f, 0.000113f, 0.000159f, 0.000204f, 0.000249f, 0.000295f, 0.000340f, 0.000385f, 0.000408f, 0.000454f, 0.000499f, 0.000544f, 0.000522f, 0.000590f, 0.000590f, 0.000635f, 0.000658f, 0.000680f, 0.000658f, 0.000544f, 0.000590f, 0.000567f, 0.000454f, 0.000431f, 0.000385f, 0.000363f, 0.000317f, 0.000272f, 0.000272f, 0.000227f, 0.000181f, 0.000136f, 0.000091f, 0.000045f, 0.000000f, 0.000000f, 0.000045f, 0.000068f, 0.000113f, 0.000159f, 0.000204f, 0.000227f, 0.000272f, 0.000317f, 0.000340f, 0.000385f, 0.000431f, 0.000454f, 0.000499f, 0.000499f, 0.000544f, 0.000567f, 0.000590f, 0.000590f, 0.000590f, 0.000590f, 0.000567f, 0.000567f, 0.000476f, 0.000454f, 0.000408f, 0.000385f, 0.000340f, 0.000340f, 0.000295f, 0.000249f, 0.000204f, 0.000159f, 0.000136f, 0.000091f, 0.000045f, 0.000000f, 0.000000f, 0.000045f, 0.000091f, 0.000113f, 0.000159f, 0.000204f, 0.000249f, 0.000295f, 0.000340f, 0.000363f, 0.000385f, 0.000431f, 0.000454f, 0.000499f, 0.000522f, 0.000522f, 0.000522f, 0.000499f, 0.000476f, 0.000454f, 0.000431f, 0.000385f, 0.000340f, 0.000317f, 0.000272f, 0.000227f, 0.000181f, 0.000136f, 0.000091f, 0.000045f, 0.000000f, 0.000000f, 0.000045f, 0.000091f, 0.000136f, 0.000159f, 0.000204f, 0.000227f, 0.000249f, 0.000295f, 0.000340f, 0.000363f, 0.000385f, 0.000408f, 0.000431f, 0.000431f, 0.000431f, 0.000431f, 0.000408f, 0.000385f, 0.000363f, 0.000317f, 0.000317f, 0.000272f, 0.000227f, 0.000181f, 0.000136f, 0.000091f, 0.000045f, 0.000000f, 0.000000f, 0.000045f, 0.000091f, 0.000136f, 0.000181f, 0.000204f, 0.000227f, 0.000272f, 0.000295f, 0.000317f, 0.000340f, 0.000340f, 0.000363f, 0.000363f, 0.000340f, 0.000317f, 0.000295f, 0.000249f, 0.000204f, 0.000159f, 0.000113f, 0.000068f, 0.000023f, 0.000000f, 0.000045f, 0.000068f, 0.000113f, 0.000159f, 0.000181f, 0.000204f, 0.000227f, 0.000249f, 0.000249f, 0.000249f, 0.000227f, 0.000227f, 0.000181f, 0.000159f, 0.000113f, 0.000091f, 0.000045f, 0.000000f, 0.000000f, 0.000045f, 0.000091f, 0.000136f, 0.000159f, 0.000181f, 0.000181f, 0.000181f, 0.000159f, 0.000136f, 0.000091f, 0.000045f, 0.000000f, 0.000000f, 0.000045f, 0.000068f, 0.000091f, 0.000068f, 0.000045f, 0.000000f, 0.000000f }; #ifdef WORDS_BIGENDIAN static int swap4bytes(CSOUND* csound, MEMFIL* mfp) { char c1, c2, c3, c4; char *p = mfp->beginp; int size = mfp->length; while (size >= 4) { c1 = p[0]; c2 = p[1]; c3 = p[2]; c4 = p[3]; p[0] = c4; p[1] = c3; p[2] = c2; p[3] = c1; size -= 4; p +=4; } return OK; } #else static int (*swap4bytes)(CSOUND*, MEMFIL*) = NULL; #endif /* Csound hrtf magnitude interpolation, phase truncation object */ /* aleft,aright hrtfmove asrc, kaz, kel, ifilel->data, ifiler [, imode = 0, ifade = 8, sr = 44100]... */ /* imode: minphase/phase truncation, ifade: no of buffers per fade for phase trunc., sr can be 44.1/48/96k */ typedef struct { OPDS h; /* outputs and inputs */ MYFLT *outsigl, *outsigr; MYFLT *in, *kangle, *kelev; STRINGDAT *ifilel, *ifiler; MYFLT *omode, *ofade, *osr; /* check if relative source has changed! */ MYFLT anglev, elevv; float *fpbeginl,*fpbeginr; /* see definitions in INIT */ int irlength, irlengthpad, overlapsize; MYFLT sr; /* old indices for checking if changes occur in trajectory. */ int oldelevindex, oldangleindex; int counter; /* initialfade used to avoid fade in of data...if not,'old' data faded out with zero hrtf,'new' data faded in. */ int cross,l,initialfade; /* user defined buffer size for fades. */ int fadebuffer, fade; /* flags for process type */ int minphase,phasetrunc; /* hrtf data padded */ AUXCH hrtflpad,hrtfrpad; /* old data for fades */ AUXCH oldhrtflpad,oldhrtfrpad; /* in and output buffers */ AUXCH insig, outl, outr, outlold, outrold; /* memory local to perform method */ /* insig fft */ AUXCH complexinsig; /* hrtf buffers (rectangular complex form) */ AUXCH hrtflfloat, hrtfrfloat; /* spectral data */ AUXCH outspecl, outspecr, outspecoldl, outspecoldr; /* overlap data */ AUXCH overlapl, overlapr; /* old overlap data for longer crossfades */ AUXCH overlapoldl, overlapoldr; /* interpolation buffers */ AUXCH lowl1, lowr1, lowl2, lowr2, highl1, highr1, highl2, highr2; /* current phase buffers */ AUXCH currentphasel, currentphaser; /* min phase buffers */ AUXCH logmagl,logmagr,xhatwinl,xhatwinr,expxhatwinl,expxhatwinr; /* min phase window: a static buffer */ AUXCH win; MYFLT delayfloat; /* delay */ AUXCH delmeml, delmemr; int ptl, ptr, mdtl, mdtr; } hrtfmove; static int hrtfmove_init(CSOUND *csound, hrtfmove *p) { /* left and right data files: spectral mag, phase format. */ MEMFIL *fpl = NULL,*fpr = NULL; int i; char filel[MAXNAME],filer[MAXNAME]; int mode = (int)*p->omode; int fade = (int)*p->ofade; MYFLT sr = *p->osr; MYFLT *win; /* time domain impulse length, padded, overlap add */ int irlength=0, irlengthpad=0, overlapsize=0; /* flag for process type: default phase trunc */ if(mode == 1) { p->minphase = 1; p->phasetrunc = 0; } else { p->phasetrunc = 1; p->minphase = 0; } /* fade length: default 8, max 24, min 1 */ if(fade < 1 || fade > 24) fade = 8; p->fade = fade; /* sr, defualt 44100 */ if(sr != 44100 && sr != 48000 && sr != 96000) sr = 44100; p->sr = sr; if (UNLIKELY(CS_ESR != sr)) csound->Message(csound, Str("\n\nWARNING!!:\nOrchestra SR not compatible" " with HRTF processing SR of: %.0f\n\n"), sr); /* setup as per sr */ if(sr == 44100 || sr == 48000) { irlength = 128; irlengthpad = 256; overlapsize = (irlength - 1); } else if(sr == 96000) { irlength = 256; irlengthpad = 512; overlapsize = (irlength - 1); } /* copy in string name */ strncpy(filel, (char*) p->ifilel->data, MAXNAME-1); filel[MAXNAME-1]='\0'; strncpy(filer, (char*) p->ifiler->data, MAXNAME-1); filel[MAXNAME-1]='\0'; /* reading files, with byte swap */ fpl = csound->ldmemfile2withCB(csound, filel, CSFTYPE_FLOATS_BINARY, swap4bytes); if (UNLIKELY(fpl == NULL)) return csound->InitError(csound, Str("\n\n\nCannot load left data file, exiting\n\n")); fpr = csound->ldmemfile2withCB(csound, filer, CSFTYPE_FLOATS_BINARY, swap4bytes); if (UNLIKELY(fpr == NULL)) return csound->InitError(csound, Str("\n\n\nCannot load right data file, exiting\n\n")); p->irlength = irlength; p->irlengthpad = irlengthpad; p->overlapsize = overlapsize; /* the amount of buffers to fade over. */ p->fadebuffer = (int)fade*irlength; /* file handles */ p->fpbeginl = (float *) fpl->beginp; p->fpbeginr = (float *) fpr->beginp; /* common buffers (used by both min phase and phasetrunc) */ if (!p->insig.auxp || p->insig.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength*sizeof(MYFLT), &p->insig); if (!p->outl.auxp || p->outl.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad*sizeof(MYFLT), &p->outl); if (!p->outr.auxp || p->outr.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad*sizeof(MYFLT), &p->outr); if (!p->hrtflpad.auxp || p->hrtflpad.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad*sizeof(MYFLT), &p->hrtflpad); if (!p->hrtfrpad.auxp || p->hrtfrpad.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad*sizeof(MYFLT), &p->hrtfrpad); if (!p->complexinsig.auxp || p->complexinsig.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad*sizeof(MYFLT), &p->complexinsig); if (!p->hrtflfloat.auxp || p->hrtflfloat.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength*sizeof(MYFLT), &p->hrtflfloat); if (!p->hrtfrfloat.auxp || p->hrtfrfloat.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength*sizeof(MYFLT), &p->hrtfrfloat); if (!p->outspecl.auxp || p->outspecl.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad*sizeof(MYFLT), &p->outspecl); if (!p->outspecr.auxp || p->outspecr.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad*sizeof(MYFLT), &p->outspecr); if (!p->overlapl.auxp || p->overlapl.size < overlapsize * sizeof(MYFLT)) csound->AuxAlloc(csound, overlapsize*sizeof(MYFLT), &p->overlapl); if (!p->overlapr.auxp || p->overlapr.size < overlapsize * sizeof(MYFLT)) csound->AuxAlloc(csound, overlapsize*sizeof(MYFLT), &p->overlapr); memset(p->insig.auxp, 0, irlength * sizeof(MYFLT)); memset(p->outl.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->outr.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->hrtflpad.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->hrtfrpad.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->complexinsig.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->hrtflfloat.auxp, 0, irlength * sizeof(MYFLT)); memset(p->hrtfrfloat.auxp, 0, irlength * sizeof(MYFLT)); memset(p->outspecl.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->outspecr.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->overlapl.auxp, 0, overlapsize * sizeof(MYFLT)); memset(p->overlapr.auxp, 0, overlapsize * sizeof(MYFLT)); /* interpolation values */ if (!p->lowl1.auxp || p->lowl1.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->lowl1); if (!p->lowr1.auxp || p->lowr1.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->lowr1); if (!p->lowl2.auxp || p->lowl2.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->lowl2); if (!p->lowr2.auxp || p->lowr2.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->lowr2); if (!p->highl1.auxp || p->highl1.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->highl1); if (!p->highr1.auxp || p->highr1.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->highr1); if (!p->highl2.auxp || p->highl2.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->highl2); if (!p->highr2.auxp || p->highr2.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->highr2); if (!p->currentphasel.auxp || p->currentphasel.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength*sizeof(MYFLT), &p->currentphasel); if (!p->currentphaser.auxp || p->currentphaser.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength*sizeof(MYFLT), &p->currentphaser); memset(p->lowl1.auxp, 0, irlength * sizeof(MYFLT)); memset(p->lowr1.auxp, 0, irlength * sizeof(MYFLT)); memset(p->lowl2.auxp, 0, irlength * sizeof(MYFLT)); memset(p->lowr2.auxp, 0, irlength * sizeof(MYFLT)); memset(p->highl1.auxp, 0, irlength * sizeof(MYFLT)); memset(p->highl2.auxp, 0, irlength * sizeof(MYFLT)); memset(p->highr1.auxp, 0, irlength * sizeof(MYFLT)); memset(p->highr2.auxp, 0, irlength * sizeof(MYFLT)); memset(p->currentphasel.auxp, 0, irlength * sizeof(MYFLT)); memset(p->currentphaser.auxp, 0, irlength * sizeof(MYFLT)); /* phase truncation buffers and variables */ if (!p->oldhrtflpad.auxp || p->oldhrtflpad.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad*sizeof(MYFLT), &p->oldhrtflpad); if (!p->oldhrtfrpad.auxp || p->oldhrtfrpad.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad*sizeof(MYFLT), &p->oldhrtfrpad); if (!p->outlold.auxp || p->outlold.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad*sizeof(MYFLT), &p->outlold); if (!p->outrold.auxp || p->outrold.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad*sizeof(MYFLT), &p->outrold); if (!p->outspecoldl.auxp || p->outspecoldl.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad*sizeof(MYFLT), &p->outspecoldl); if (!p->outspecoldr.auxp || p->outspecoldr.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad*sizeof(MYFLT), &p->outspecoldr); if (!p->overlapoldl.auxp || p->overlapoldl.size < overlapsize * sizeof(MYFLT)) csound->AuxAlloc(csound, overlapsize*sizeof(MYFLT), &p->overlapoldl); if (!p->overlapoldr.auxp || p->overlapoldr.size < overlapsize * sizeof(MYFLT)) csound->AuxAlloc(csound, overlapsize*sizeof(MYFLT), &p->overlapoldr); memset(p->oldhrtflpad.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->oldhrtfrpad.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->outlold.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->outrold.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->outspecoldl.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->outspecoldr.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->overlapoldl.auxp, 0, overlapsize * sizeof(MYFLT)); memset(p->overlapoldr.auxp, 0, overlapsize * sizeof(MYFLT)); /* initialize counters and indices */ p->counter = 0; p->cross = 0; p->l = 0; p->initialfade = 0; /* need to be a value that is not possible for first check to avoid phase not being read. */ p->oldelevindex = -1; p->oldangleindex = -1; /* buffer declaration for min phase calculations */ if (!p->logmagl.auxp || p->logmagl.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength*sizeof(MYFLT), &p->logmagl); if (!p->logmagr.auxp || p->logmagr.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength*sizeof(MYFLT), &p->logmagr); if (!p->xhatwinl.auxp || p->xhatwinl.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength*sizeof(MYFLT), &p->xhatwinl); if (!p->xhatwinr.auxp || p->xhatwinr.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength*sizeof(MYFLT), &p->xhatwinr); if (!p->expxhatwinl.auxp || p->expxhatwinl.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength*sizeof(MYFLT), &p->expxhatwinl); if (!p->expxhatwinr.auxp || p->expxhatwinr.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength*sizeof(MYFLT), &p->expxhatwinr); memset(p->logmagl.auxp, 0, irlength * sizeof(MYFLT)); memset(p->logmagr.auxp, 0, irlength * sizeof(MYFLT)); memset(p->xhatwinl.auxp, 0, irlength * sizeof(MYFLT)); memset(p->xhatwinr.auxp, 0, irlength * sizeof(MYFLT)); memset(p->expxhatwinl.auxp, 0, irlength * sizeof(MYFLT)); memset(p->expxhatwinr.auxp, 0, irlength * sizeof(MYFLT)); /* delay buffers */ if (!p->delmeml.auxp || p->delmeml.size < (int)(sr * maxdeltime) * sizeof(MYFLT)) csound->AuxAlloc(csound, (int)(sr * maxdeltime) * sizeof(MYFLT), &p->delmeml); if (!p->delmemr.auxp || p->delmemr.size < (int)(sr * maxdeltime) * sizeof(MYFLT)) csound->AuxAlloc(csound, (int)(sr * maxdeltime) * sizeof(MYFLT), &p->delmemr); memset(p->delmeml.auxp, 0, (int)(sr * maxdeltime) * sizeof(MYFLT)); memset(p->delmemr.auxp, 0, (int)(sr * maxdeltime) * sizeof(MYFLT)); if (!p->win.auxp || p->win.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength*sizeof(MYFLT), &p->win); win = (MYFLT *)p->win.auxp; /* min phase win defined for irlength point impulse! */ win[0] = FL(1.0); for(i = 1; i < (irlength / 2); i++) win[i] = FL(2.0); win[(irlength / 2)] = FL(1.0); for(i = ((irlength / 2) + 1); i < irlength; i++) win[i] = FL(0.0); p->mdtl = (int)(FL(0.00095) * sr); p->mdtr = (int)(FL(0.00095) * sr); p->delayfloat = FL(0.0); p->ptl = 0; p->ptr = 0; /* setup values used to check if src has moved, illegal values to start with to ensure first read */ p->anglev = -1; p->elevv = -41; return OK; } static int hrtfmove_process(CSOUND *csound, hrtfmove *p) { /* local pointers to p */ MYFLT *in = p->in; MYFLT *outsigl = p->outsigl; MYFLT *outsigr = p->outsigr; /* common buffers and variables */ MYFLT *insig = (MYFLT *)p->insig.auxp; MYFLT *outl = (MYFLT *)p->outl.auxp; MYFLT *outr = (MYFLT *)p->outr.auxp; MYFLT *hrtflpad = (MYFLT *)p->hrtflpad.auxp; MYFLT *hrtfrpad = (MYFLT *)p->hrtfrpad.auxp; MYFLT *complexinsig = (MYFLT *)p->complexinsig.auxp; MYFLT *hrtflfloat = (MYFLT *)p->hrtflfloat.auxp; MYFLT *hrtfrfloat = (MYFLT *)p->hrtfrfloat.auxp; MYFLT *outspecl = (MYFLT *)p->outspecl.auxp; MYFLT *outspecr = (MYFLT *)p->outspecr.auxp; MYFLT *overlapl = (MYFLT *)p->overlapl.auxp; MYFLT *overlapr = (MYFLT *)p->overlapr.auxp; MYFLT elev = *p->kelev; MYFLT angle = *p->kangle; int counter = p->counter; /* pointers into HRTF files: floating point data (even in 64 bit csound) */ float *fpindexl; float *fpindexr; int i,elevindex, angleindex, skip = 0; int minphase = p->minphase; int phasetrunc = p->phasetrunc; MYFLT sr = p->sr; int irlength = p->irlength; int irlengthpad = p->irlengthpad; int overlapsize = p->overlapsize; /* local variables, mainly used for simplification */ MYFLT elevindexstore; MYFLT angleindexlowstore; MYFLT angleindexhighstore; /* interpolation values */ MYFLT *lowl1 = (MYFLT *)p->lowl1.auxp; MYFLT *lowr1 = (MYFLT *)p->lowr1.auxp; MYFLT *lowl2 = (MYFLT *)p->lowl2.auxp; MYFLT *lowr2 = (MYFLT *)p->lowr2.auxp; MYFLT *highl1 = (MYFLT *)p->highl1.auxp; MYFLT *highr1 = (MYFLT *)p->highr1.auxp; MYFLT *highl2 = (MYFLT *)p->highl2.auxp; MYFLT *highr2 = (MYFLT *)p->highr2.auxp; MYFLT *currentphasel = (MYFLT *)p->currentphasel.auxp; MYFLT *currentphaser = (MYFLT *)p->currentphaser.auxp; /* local interpolation values */ MYFLT elevindexhighper, angleindex2per, angleindex4per; int elevindexlow, elevindexhigh, angleindex1, angleindex2, angleindex3, angleindex4; MYFLT magl,magr,phasel,phaser, magllow, magrlow, maglhigh, magrhigh; /* phase truncation buffers and variables */ MYFLT *oldhrtflpad = (MYFLT *)p->oldhrtflpad.auxp; MYFLT *oldhrtfrpad = (MYFLT *)p->oldhrtfrpad.auxp; MYFLT *outlold = (MYFLT *)p->outlold.auxp; MYFLT *outrold = (MYFLT *)p->outrold.auxp; MYFLT *outspecoldl = (MYFLT *)p->outspecoldl.auxp; MYFLT *outspecoldr = (MYFLT *)p->outspecoldr.auxp; MYFLT *overlapoldl = (MYFLT *)p->overlapoldl.auxp; MYFLT *overlapoldr = (MYFLT *)p->overlapoldr.auxp; int oldelevindex = p ->oldelevindex; int oldangleindex = p ->oldangleindex; int cross = p ->cross; int l = p->l; int initialfade = p->initialfade; int crossfade; int crossout; int fade = p->fade; int fadebuffer = p->fadebuffer; /* minimum phase buffers */ MYFLT *logmagl = (MYFLT *)p->logmagl.auxp; MYFLT *logmagr = (MYFLT *)p->logmagr.auxp; MYFLT *xhatwinl = (MYFLT *)p->xhatwinl.auxp; MYFLT *xhatwinr = (MYFLT *)p->xhatwinr.auxp; MYFLT *expxhatwinl = (MYFLT *)p->expxhatwinl.auxp; MYFLT *expxhatwinr = (MYFLT *)p->expxhatwinr.auxp; /* min phase window */ MYFLT *win = (MYFLT *)p->win.auxp; /* min phase delay variables */ MYFLT *delmeml = (MYFLT *)p->delmeml.auxp; MYFLT *delmemr = (MYFLT *)p->delmemr.auxp; MYFLT delaylow1, delaylow2, delayhigh1, delayhigh2, delaylow, delayhigh; MYFLT delayfloat = p->delayfloat; int ptl = p->ptl; int ptr = p->ptr; int mdtl = p->mdtl; int mdtr = p->mdtr; int posl, posr; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t j, nsmps = CS_KSMPS; MYFLT outvdl, outvdr, vdtl, vdtr, fracl, fracr, rpl, rpr; /* start indices at correct value (start of file)/ zero indices. */ fpindexl = (float *) p->fpbeginl; fpindexr = (float *) p->fpbeginr; if (UNLIKELY(offset)) { memset(outsigl, '\0', offset*sizeof(MYFLT)); memset(outsigr, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&outsigl[nsmps], '\0', early*sizeof(MYFLT)); memset(&outsigr[nsmps], '\0', early*sizeof(MYFLT)); } for(j = offset; j < nsmps; j++) { /* ins and outs */ insig[counter] = in[j]; outsigl[j] = outl[counter]; outsigr[j] = outr[counter]; counter++; if(phasetrunc) { /* used to ensure fade does not happen on first run */ if(initialfade < (irlength + 2)) initialfade++; } if(counter == irlength) { /* process a block */ crossfade = 0; crossout = 0; if(elev > FL(90.0)) elev = FL(90.0); if(elev < FL(-40.0)) elev = FL(-40.0); while(angle < FL(0.0)) angle += FL(360.0); while(angle >= FL(360.0)) angle -= FL(360.0); /* only update if location changes! */ if(angle != p->anglev || elev != p->elevv) { /* two nearest elev indices to avoid recalculating */ elevindexstore = (elev - minelev) / elevincrement; elevindexlow = (int)elevindexstore; if(elevindexlow < 13) elevindexhigh = elevindexlow + 1; /* highest index reached */ else elevindexhigh = elevindexlow; /* get percentage value for interpolation */ elevindexhighper = elevindexstore - elevindexlow; /* read using an index system based on number of points measured per elevation at mit */ /* lookup indices, used to check for crossfade */ elevindex = (int)(elevindexstore + FL(0.5)); angleindex = (int)(angle / (FL(360.0) / elevationarray[elevindex]) + FL(0.5)); angleindex = angleindex % elevationarray[elevindex]; /* avoid recalculation */ angleindexlowstore = angle / (FL(360.0) / elevationarray[elevindexlow]); angleindexhighstore = angle / (FL(360.) / elevationarray[elevindexhigh]); /* 4 closest indices, 2 low and 2 high */ angleindex1 = (int)angleindexlowstore; angleindex2 = angleindex1 + 1; angleindex2 = angleindex2 % elevationarray[elevindexlow]; angleindex3 = (int)angleindexhighstore; angleindex4 = angleindex3 + 1; angleindex4 = angleindex4 % elevationarray[elevindexhigh]; /* angle percentages for interp */ angleindex2per = angleindexlowstore - angleindex1; angleindex4per = angleindexhighstore - angleindex3; if(phasetrunc) { if(angleindex!=oldangleindex || elevindex!=oldelevindex) { /* store last point and turn crossfade on, provided that initialfade value indicates first block processed! */ /* (otherwise,there will be a fade in at the start). */ if(initialfade>irlength) { /* post warning if fades ovelap */ if(cross) { csound->Message(csound, Str("\nWARNING: fades are " "overlapping: this could lead" " to noise: reduce fade size " "or change trajectory\n\n")); cross = 0; } /* reset l, use as index to fade */ l = 0; crossfade = 1; /* store old data */ for(i = 0; i < irlengthpad; i++) { oldhrtflpad[i] = hrtflpad[i]; oldhrtfrpad[i] = hrtfrpad[i]; } } /* store point for current phase as trajectory comes closer to a new index */ skip = 0; /* store current phase */ if(angleindex > elevationarray[elevindex] / 2) { for(i = 0; i < elevindex; i++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < (elevationarray[elevindex] - angleindex); i++) skip += irlength; for(i = 0; i < irlength; i++) { currentphasel[i] = fpindexr[skip + i]; currentphaser[i] = fpindexl[skip + i]; } } else { for(i = 0; i < elevindex; i++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < angleindex; i++) skip += irlength; for(i = 0; i < irlength; i++) { currentphasel[i] = fpindexl[skip+i]; currentphaser[i] = fpindexr[skip+i]; } } } } /* for next check */ p->oldelevindex = elevindex; p->oldangleindex = angleindex; /* read 4 nearest HRTFs */ skip = 0; /* switch l and r */ if(angleindex1 > elevationarray[elevindexlow] / 2) { for(i = 0; i < elevindexlow; i++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < (elevationarray[elevindexlow] - angleindex1); i++) skip += irlength; for(i = 0; i < irlength; i++) { lowl1[i] = fpindexr[skip+i]; lowr1[i] = fpindexl[skip+i]; } } else { for(i = 0; i < elevindexlow; i++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < angleindex1; i++) skip += irlength; for(i = 0; i < irlength; i++) { lowl1[i] = fpindexl[skip+i]; lowr1[i] = fpindexr[skip+i]; } } skip = 0; if(angleindex2 > elevationarray[elevindexlow] / 2) { for(i = 0; i < elevindexlow; i++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < (elevationarray[elevindexlow] - angleindex2); i++) skip += irlength; for(i = 0; i < irlength; i++) { lowl2[i] = fpindexr[skip+i]; lowr2[i] = fpindexl[skip+i]; } } else { for(i = 0; i < elevindexlow; i++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < angleindex2; i++) skip += irlength; for(i = 0; i < irlength; i++) { lowl2[i] = fpindexl[skip+i]; lowr2[i] = fpindexr[skip+i]; } } skip = 0; if(angleindex3 > elevationarray[elevindexhigh] / 2) { for(i = 0; i < elevindexhigh; i++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < (elevationarray[elevindexhigh] - angleindex3); i++) skip += irlength; for(i = 0; i < irlength; i++) { highl1[i] = fpindexr[skip+i]; highr1[i] = fpindexl[skip+i]; } } else { for(i = 0; i < elevindexhigh; i++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < angleindex3; i++) skip += irlength; for(i = 0; i < irlength; i++) { highl1[i] = fpindexl[skip+i]; highr1[i] = fpindexr[skip+i]; } } skip = 0; if(angleindex4 > elevationarray[elevindexhigh] / 2) { for(i = 0; i < elevindexhigh; i++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < (elevationarray[elevindexhigh] - angleindex4); i++) skip += irlength; for(i = 0; i < irlength; i++) { highl2[i] = fpindexr[skip+i]; highr2[i] = fpindexl[skip+i]; } } else { for(i = 0; i < elevindexhigh; i++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < angleindex4; i++) skip += irlength; for(i = 0; i < irlength; i++) { highl2[i] = fpindexl[skip+i]; highr2[i] = fpindexr[skip+i]; } } /* interpolation */ /* 0 Hz and Nyq...absoulute values for mag */ magllow = FABS(lowl1[0]) + (FABS(lowl2[0]) - FABS(lowl1[0])) * angleindex2per; maglhigh = FABS(highl1[0]) + (FABS(highl2[0]) - FABS(highl1[0])) * angleindex4per; magl = magllow + (maglhigh - magllow) * elevindexhighper; if(minphase) { logmagl[0] = LOG((magl == FL(0.0) ? FL(0.00000001) : magl)); } /* this is where real values of 0hz and nyq needed: if neg real, 180 degree phase */ /* if data was complex, mag interp would use fabs() inherently, phase would be 0/pi */ /* if pi, real is negative! */ else { if(currentphasel[0] < FL(0.0)) hrtflfloat[0] = -magl; else hrtflfloat[0] = magl; } magllow = FABS(lowl1[1]) + (FABS(lowl2[1]) - FABS(lowl1[1])) * angleindex2per; maglhigh = FABS(highl1[1]) + (FABS(highl2[1]) - FABS(highl1[1])) * angleindex4per; magl = magllow + (maglhigh-magllow) * elevindexhighper; if(minphase) { logmagl[1] = LOG(magl == FL(0.0) ? FL(0.00000001) : magl); } else { if(currentphasel[1] < FL(0.0)) hrtflfloat[1] = -magl; else hrtflfloat[1] = magl; } magrlow = FABS(lowr1[0]) + (FABS(lowr2[0]) - FABS(lowr1[0])) * angleindex2per; magrhigh = FABS(highr1[0]) + (FABS(highr2[0]) - FABS(highr1[0])) * angleindex4per; magr = magrlow + (magrhigh - magrlow) * elevindexhighper; if(minphase) { logmagr[0] = LOG(magr == FL(0.0) ? FL(0.00000001) : magr); } else { if(currentphaser[0] < FL(0.0)) hrtfrfloat[0] = -magr; else hrtfrfloat[0] = magr; } magrlow = FABS(lowr1[1]) + (FABS(lowr2[1]) - FABS(lowr1[1])) * angleindex2per; magrhigh = FABS(highr1[1]) + (FABS(highr2[1]) - FABS(highr1[1])) * angleindex4per; magr = magrlow + (magrhigh - magrlow) * elevindexhighper; if(minphase) { logmagr[1] = LOG(magr == FL(0.0) ? FL(0.00000001) : magr); } else { if(currentphaser[1] < FL(0.0)) hrtfrfloat[1] = -magr; else hrtfrfloat[1] = magr; } /* remaining values */ for(i = 2; i < irlength; i += 2) { /* interpolate high and low mags */ magllow = lowl1[i] + (lowl2[i] - lowl1[i]) * angleindex2per; maglhigh = highl1[i] + (highl2[i] - highl1[i]) * angleindex4per; magrlow = lowr1[i] + (lowr2[i] - lowr1[i]) * angleindex2per; magrhigh = highr1[i] + (highr2[i] - highr1[i]) * angleindex4per; /* interpolate high and low results */ magl = magllow + (maglhigh - magllow) * elevindexhighper; magr = magrlow + (magrhigh - magrlow) * elevindexhighper; if(phasetrunc) { /* use current phase, back to rectangular */ phasel = currentphasel[i + 1]; phaser = currentphaser[i + 1]; /* polar to rectangular */ hrtflfloat[i] = magl * COS(phasel); hrtflfloat[i+1] = magl * SIN(phasel); hrtfrfloat[i] = magr * COS(phaser); hrtfrfloat[i+1] = magr * SIN(phaser); } if(minphase) { /* store log magnitudes, 0 phases for ifft, do not allow log(0.0) */ logmagl[i] = LOG(magl == FL(0.0) ? FL(0.00000001) : magl); logmagr[i] = LOG(magr == FL(0.0) ? FL(0.00000001) : magr); logmagl[i + 1] = FL(0.0); logmagr[i + 1] = FL(0.0); } } if(minphase) { /* ifft!...see Oppehneim and Schafer for min phase process...based on real cepstrum method */ csound->InverseRealFFT(csound, logmagl, irlength); csound->InverseRealFFT(csound, logmagr, irlength); /* window, note no need to scale on csound iffts... */ for(i = 0; i < irlength; i++) { xhatwinl[i] = logmagl[i] * win[i]; xhatwinr[i] = logmagr[i] * win[i]; } /* fft */ csound->RealFFT(csound, xhatwinl, irlength); csound->RealFFT(csound, xhatwinr, irlength); /* exponential of result */ /* 0 hz and nyq purely real... */ expxhatwinl[0] = EXP(xhatwinl[0]); expxhatwinl[1] = EXP(xhatwinl[1]); expxhatwinr[0] = EXP(xhatwinr[0]); expxhatwinr[1] = EXP(xhatwinr[1]); /* exponential of real, cos/sin of imag */ for(i = 2; i < irlength; i += 2) { expxhatwinl[i] = EXP(xhatwinl[i]) * COS(xhatwinl[i + 1]); expxhatwinl[i+1] = EXP(xhatwinl[i]) * SIN(xhatwinl[i + 1]); expxhatwinr[i] = EXP(xhatwinr[i]) * COS(xhatwinr[i + 1]); expxhatwinr[i+1] = EXP(xhatwinr[i]) * SIN(xhatwinr[i + 1]); } /* ifft for output buffers */ csound->InverseRealFFT(csound, expxhatwinl, irlength); csound->InverseRealFFT(csound, expxhatwinr, irlength); /* output */ for(i= 0; i < irlength; i++) { hrtflpad[i] = expxhatwinl[i]; hrtfrpad[i] = expxhatwinr[i]; } } /* use current phase and interped mag directly */ if(phasetrunc) { /* ifft */ csound->InverseRealFFT(csound, hrtflfloat, irlength); csound->InverseRealFFT(csound, hrtfrfloat, irlength); for (i = 0; i < irlength; i++) { /* scale and pad buffers with zeros to fftbuff */ hrtflpad[i] = hrtflfloat[i]; hrtfrpad[i] = hrtfrfloat[i]; } } /* zero pad impulse */ for(i = irlength; i < irlengthpad; i++) { hrtflpad[i] = FL(0.0); hrtfrpad[i] = FL(0.0); } /* back to freq domain */ csound->RealFFT(csound, hrtflpad, irlengthpad); csound->RealFFT(csound, hrtfrpad, irlengthpad); if(minphase) { /* read delay data: 4 nearest points, as above */ /* point 1 */ skip = 0; if(angleindex1 > elevationarray[elevindexlow] / 2) { for (i = 0; i < elevindexlow; i++) skip += ((int)(elevationarray[i] / 2) + 1); for(i = 0; i < (elevationarray[elevindexlow] - angleindex1); i++) skip++; delaylow1 = minphasedels[skip]; } else { for (i = 0; i < elevindexlow; i++) skip += ((int)(elevationarray[i] / 2) + 1); for(i = 0; i < angleindex1; i++) skip++; delaylow1 = minphasedels[skip]; } /* point 2 */ skip = 0; if(angleindex2 > elevationarray[elevindexlow] / 2) { for (i = 0; i < elevindexlow; i++) skip += ((int)(elevationarray[i] / 2) + 1); for(i = 0; i < (elevationarray[elevindexlow] - angleindex2); i++) skip++; delaylow2 = minphasedels[skip]; } else { for (i = 0; i < elevindexlow; i++) skip += ((int)(elevationarray[i] / 2) + 1); for (i = 0; i < angleindex2; i++) skip++; delaylow2 = minphasedels[skip]; } /* point 3 */ skip = 0; if(angleindex3 > elevationarray[elevindexhigh] / 2) { for (i = 0; i < elevindexhigh; i++) skip += ((int)(elevationarray[i] / 2) + 1); for(i = 0; i < (elevationarray[elevindexhigh] - angleindex3); i++) skip++; delayhigh1 =minphasedels[skip]; } else { for (i = 0; i < elevindexhigh; i++) skip += ((int)(elevationarray[i] / 2) + 1); for (i = 0; i < angleindex3; i++) skip++; delayhigh1 = minphasedels[skip]; } /* point 4 */ skip = 0; if(angleindex4 > elevationarray[elevindexhigh] / 2) { for (i = 0; i < elevindexhigh; i++) skip += ((int)(elevationarray[i] / 2) + 1); for(i = 0; i < (elevationarray[elevindexhigh] - angleindex4); i++) skip++; delayhigh2 = minphasedels[skip]; } else { for (i = 0; i < elevindexhigh; i++) skip += ((int)(elevationarray[i] / 2) + 1); for (i = 0; i < angleindex4; i++) skip++; delayhigh2 = minphasedels[skip]; } /* delay interp */ delaylow = delaylow1 + ((delaylow2 - delaylow1) * angleindex2per); delayhigh = delayhigh1 + ((delayhigh2 - delayhigh1) * angleindex4per); delayfloat = delaylow + ((delayhigh - delaylow) * elevindexhighper); p->delayfloat = delayfloat; } /* end of angle/elev change process */ p->elevv = elev; p->anglev = angle; } /* look after overlap add */ for(i = 0; i < overlapsize ; i++) { overlapl[i] = outl[i + irlength]; overlapr[i] = outr[i + irlength]; /* look after fade */ if(phasetrunc) { if(crossfade) { overlapoldl[i] = outl[i + irlength]; overlapoldr[i] = outr[i + irlength]; } /* overlap will be previous fading out signal */ if(cross) { overlapoldl[i] = outlold[i + irlength]; overlapoldr[i] = outrold[i + irlength]; } } } /* insert insig */ for (i = 0; i < irlength; i++) complexinsig[i] = insig[i]; for (i = irlength; i < irlengthpad; i++) complexinsig[i] = FL(0.0); csound->RealFFT(csound, complexinsig, irlengthpad); /* complex mult function... */ csound->RealFFTMult(csound, outspecl, hrtflpad, complexinsig, irlengthpad, FL(1.0)); csound->RealFFTMult(csound, outspecr, hrtfrpad, complexinsig, irlengthpad, FL(1.0)); /* convolution is the inverse FFT of above result */ csound->InverseRealFFT(csound, outspecl, irlengthpad); csound->InverseRealFFT(csound, outspecr, irlengthpad); /* real values, scaled (by a little more than usual to ensure no clipping) sr related */ for(i = 0; i < irlengthpad; i++) { outl[i] = outspecl[i] / (sr / FL(38000.0)); outr[i] = outspecr[i] / (sr / FL(38000.0)); } if(phasetrunc) { /* setup for fades */ if(crossfade || cross) { crossout = 1; csound->RealFFTMult(csound, outspecoldl, oldhrtflpad, complexinsig, irlengthpad, FL(1.0)); csound->RealFFTMult(csound, outspecoldr, oldhrtfrpad, complexinsig, irlengthpad, FL(1.0)); csound->InverseRealFFT(csound, outspecoldl, irlengthpad); csound->InverseRealFFT(csound, outspecoldr, irlengthpad); /* scaled */ for(i = 0; i < irlengthpad; i++) { outlold[i] = outspecoldl[i] / (sr / FL(38000.0)); outrold[i] = outspecoldr[i] / (sr / FL(38000.0)); } cross++; /* number of processing buffers in a fade */ cross = cross % fade; } if(crossout) { /* do fade */ for(i = 0; i < irlength; i++) { outl[i] = ((outlold[i] + (i FL(180.0)) { vdtr = delayfloat * sr; vdtl = FL(0.0); } else { vdtr = FL(0.0); vdtl = delayfloat * sr; } /* delay right */ if(vdtr > mdtr) vdtr = FL(mdtr); for(i = 0; i < irlength; i++) { rpr = ptr - vdtr; rpr = (rpr >= 0 ? (rpr < mdtr ? rpr : rpr - mdtr) : rpr + mdtr); posr = (int) rpr; fracr = rpr - posr; delmemr[ptr] = outr[i]; outvdr = delmemr[posr] + fracr * (delmemr[(posr + 1 < mdtr ? posr + 1 : 0)] - delmemr[posr]); outr[i] = outvdr; ptr = (ptr != mdtr - 1 ? ptr + 1 : 0); } /* delay left */ if(vdtl > mdtl) vdtl = FL(mdtl); for(i = 0; i < irlength; i++) { rpl = ptl - vdtl; rpl = (rpl >= 0 ? (rpl < mdtl ? rpl : rpl - mdtl) : rpl + mdtl); posl = (int) rpl; fracl = rpl - (int) posl; delmeml[ptl] = outl[i]; outvdl = delmeml[posl] + fracl * (delmeml[(posl + 1 < mdtl ? posl + 1 : 0)] - delmeml[posl]); outl[i] = outvdl; ptl = (ptl != mdtl - 1 ? ptl + 1 : 0); } p->ptl = ptl; p->ptr = ptr; } /* reset counter */ counter = 0; if(phasetrunc) { /* update */ p->cross = cross; p->l = l; } } /* end of irlength == counter */ } /* end of ksmps audio loop */ /* update */ p->counter = counter; if(phasetrunc) p->initialfade = initialfade; return OK; } /* Csound hrtf magnitude interpolation, woodworth phase, static source: January 10 */ /* overlap add convolution */ /* aleft, aright hrtfstat ain, iang, iel, ifilel, ifiler->data [,iradius = 8.8, isr = 44100]...options of 48 and 96k sr */ /* see definitions above */ typedef struct { OPDS h; /* outputs and inputs */ MYFLT *outsigl, *outsigr; MYFLT *in, *iangle, *ielev; STRINGDAT *ifilel, *ifiler; MYFLT *oradius, *osr; /*see definitions in INIT*/ int irlength, irlengthpad, overlapsize; MYFLT sroverN; int counter; MYFLT sr; /* hrtf data padded */ AUXCH hrtflpad,hrtfrpad; /* in and output buffers */ AUXCH insig, outl, outr; /* memory local to perform method */ /* insig fft */ AUXCH complexinsig; /* hrtf buffers (rectangular complex form) */ AUXCH hrtflfloat, hrtfrfloat; /* spectral data */ AUXCH outspecl, outspecr; /* overlap data */ AUXCH overlapl, overlapr; /* interpolation buffers */ AUXCH lowl1, lowr1, lowl2, lowr2, highl1, highr1, highl2, highr2; /* buffers for impulse shift */ AUXCH leftshiftbuffer, rightshiftbuffer; } hrtfstat; static int hrtfstat_init(CSOUND *csound, hrtfstat *p) { /* left and right data files: spectral mag, phase format. */ MEMFIL *fpl = NULL, *fpr = NULL; char filel[MAXNAME], filer[MAXNAME]; /* interpolation values */ MYFLT *lowl1; MYFLT *lowr1; MYFLT *lowl2; MYFLT *lowr2; MYFLT *highl1; MYFLT *highr1; MYFLT *highl2; MYFLT *highr2; MYFLT *hrtflfloat; MYFLT *hrtfrfloat; MYFLT *hrtflpad; MYFLT *hrtfrpad; MYFLT elev = *p->ielev; MYFLT angle = *p->iangle; MYFLT r = *p->oradius; MYFLT sr = *p->osr; /* pointers into HRTF files */ float *fpindexl=NULL; float *fpindexr=NULL; /* time domain impulse length, padded, overlap add */ int irlength=0, irlengthpad=0, overlapsize=0; int i, skip = 0; /* local interpolation values */ MYFLT elevindexhighper, angleindex2per, angleindex4per; int elevindexlow, elevindexhigh, angleindex1, angleindex2, angleindex3, angleindex4; MYFLT magl, magr, phasel, phaser, magllow, magrlow, maglhigh, magrhigh; /* local variables, mainly used for simplification */ MYFLT elevindexstore; MYFLT angleindexlowstore; MYFLT angleindexhighstore; /* woodworth values */ MYFLT radianangle, radianelev, itd=0, itdww, freq; /* shift */ int shift; MYFLT *leftshiftbuffer; MYFLT *rightshiftbuffer; /* sr */ if(sr != FL(44100.0) && sr != FL(48000.0) && sr != FL(96000.0)) sr = FL(44100.0); p->sr = sr; if (UNLIKELY(CS_ESR != sr)) csound->Message(csound, Str("\n\nWARNING!!:\nOrchestra SR not compatible with " "HRTF processing SR of: %.0f\n\n"), sr); /* setup as per sr */ if(sr == 44100 || sr == 48000) { irlength = 128; irlengthpad = 256; overlapsize = (irlength - 1); } else if(sr == 96000) { irlength = 256; irlengthpad = 512; overlapsize = (irlength - 1); } /* copy in string name... */ strncpy(filel, (char*) p->ifilel->data, MAXNAME-1); filel[MAXNAME-1]='\0'; strncpy(filer, (char*) p->ifiler->data, MAXNAME-1); filel[MAXNAME-1]='\0'; /* reading files, with byte swap */ fpl = csound->ldmemfile2withCB(csound, filel, CSFTYPE_FLOATS_BINARY, swap4bytes); if (UNLIKELY(fpl == NULL)) return csound->InitError(csound, Str("\n\n\nCannot load left data file, exiting\n\n")); fpr = csound->ldmemfile2withCB(csound, filer, CSFTYPE_FLOATS_BINARY, swap4bytes); if (UNLIKELY(fpr == NULL)) return csound->InitError(csound, Str("\n\n\nCannot load right data file, exiting\n\n")); p->irlength = irlength; p->irlengthpad = irlengthpad; p->overlapsize = overlapsize; p->sroverN = sr/irlength; /* start indices at correct value (start of file)/ zero indices. (do not need to store here, as only accessing in INIT) */ fpindexl = (float *) fpl->beginp; fpindexr = (float *) fpr->beginp; /* buffers */ if (!p->insig.auxp || p->insig.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength*sizeof(MYFLT), &p->insig); if (!p->outl.auxp || p->outl.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad*sizeof(MYFLT), &p->outl); if (!p->outr.auxp || p->outr.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad*sizeof(MYFLT), &p->outr); if (!p->hrtflpad.auxp || p->hrtflpad.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad*sizeof(MYFLT), &p->hrtflpad); if (!p->hrtfrpad.auxp || p->hrtfrpad.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad*sizeof(MYFLT), &p->hrtfrpad); if (!p->complexinsig.auxp || p->complexinsig.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad*sizeof(MYFLT), &p-> complexinsig); if (!p->hrtflfloat.auxp || p->hrtflfloat.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength*sizeof(MYFLT), &p->hrtflfloat); if (!p->hrtfrfloat.auxp || p->hrtfrfloat.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength*sizeof(MYFLT), &p->hrtfrfloat); if (!p->outspecl.auxp || p->outspecl.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad*sizeof(MYFLT), &p->outspecl); if (!p->outspecr.auxp || p->outspecr.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad*sizeof(MYFLT), &p->outspecr); if (!p->overlapl.auxp || p->overlapl.size < overlapsize * sizeof(MYFLT)) csound->AuxAlloc(csound, overlapsize*sizeof(MYFLT), &p->overlapl); if (!p->overlapr.auxp || p->overlapr.size < overlapsize * sizeof(MYFLT)) csound->AuxAlloc(csound, overlapsize*sizeof(MYFLT), &p->overlapr); memset(p->insig.auxp, 0, irlength * sizeof(MYFLT)); memset(p->outl.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->outr.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->hrtflpad.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->hrtfrpad.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->complexinsig.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->hrtflfloat.auxp, 0, irlength * sizeof(MYFLT)); memset(p->hrtfrfloat.auxp, 0, irlength * sizeof(MYFLT)); memset(p->outspecl.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->outspecr.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->overlapl.auxp, 0, overlapsize * sizeof(MYFLT)); memset(p->overlapr.auxp, 0, overlapsize * sizeof(MYFLT)); /* interpolation values */ if (!p->lowl1.auxp || p->lowl1.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->lowl1); if (!p->lowr1.auxp || p->lowr1.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->lowr1); if (!p->lowl2.auxp || p->lowl2.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->lowl2); if (!p->lowr2.auxp || p->lowr2.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->lowr2); if (!p->highl1.auxp || p->highl1.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->highl1); if (!p->highr1.auxp || p->highr1.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->highr1); if (!p->highl2.auxp || p->highl2.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->highl2); if (!p->highr2.auxp || p->highr2.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->highr2); /* best to zero, for future changes (filled in init) */ memset(p->lowl1.auxp, 0, irlength * sizeof(MYFLT)); memset(p->lowr1.auxp, 0, irlength * sizeof(MYFLT)); memset(p->lowl2.auxp, 0, irlength * sizeof(MYFLT)); memset(p->lowr2.auxp, 0, irlength * sizeof(MYFLT)); memset(p->highl1.auxp, 0, irlength * sizeof(MYFLT)); memset(p->highl2.auxp, 0, irlength * sizeof(MYFLT)); memset(p->highr1.auxp, 0, irlength * sizeof(MYFLT)); memset(p->highr2.auxp, 0, irlength * sizeof(MYFLT)); /* shift buffers */ if (!p->leftshiftbuffer.auxp || p->leftshiftbuffer.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength*sizeof(MYFLT), &p->leftshiftbuffer); if (!p->rightshiftbuffer.auxp || p->rightshiftbuffer.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength*sizeof(MYFLT), &p->rightshiftbuffer); memset(p->leftshiftbuffer.auxp, 0, irlength * sizeof(MYFLT)); memset(p->rightshiftbuffer.auxp, 0, irlength * sizeof(MYFLT)); lowl1 = (MYFLT *)p->lowl1.auxp; lowr1 = (MYFLT *)p->lowr1.auxp; lowl2 = (MYFLT *)p->lowl2.auxp; lowr2 = (MYFLT *)p->lowr2.auxp; highl1 = (MYFLT *)p->highl1.auxp; highr1 = (MYFLT *)p->highr1.auxp; highl2 = (MYFLT *)p->highl2.auxp; highr2 = (MYFLT *)p->highr2.auxp; leftshiftbuffer = (MYFLT *)p->leftshiftbuffer.auxp; rightshiftbuffer = (MYFLT *)p->rightshiftbuffer.auxp; hrtflfloat = (MYFLT *)p->hrtflfloat.auxp; hrtfrfloat = (MYFLT *)p->hrtfrfloat.auxp; hrtflpad = (MYFLT *)p->hrtflpad.auxp; hrtfrpad = (MYFLT *)p->hrtfrpad.auxp; if(r <= 0 || r > 15) r = FL(8.8); if(elev > FL(90.0)) elev = FL(90.0); if(elev < FL(-40.0)) elev = FL(-40.0); while(angle < FL(0.0)) angle += FL(360.0); while(angle >= FL(360.0)) angle -= FL(360.0); /* two nearest elev indices to avoid recalculating */ elevindexstore = (elev - minelev) / elevincrement; elevindexlow = (int)elevindexstore; if(elevindexlow < 13) elevindexhigh = elevindexlow + 1; /* highest index reached */ else elevindexhigh = elevindexlow; /* get percentage value for interpolation */ elevindexhighper = elevindexstore - elevindexlow; /* avoid recalculation */ angleindexlowstore = angle / (FL(360.0) / elevationarray[elevindexlow]); angleindexhighstore = angle / (FL(360.0) / elevationarray[elevindexhigh]); /* 4 closest indices, 2 low and 2 high */ angleindex1 = (int)angleindexlowstore; angleindex2 = angleindex1 + 1; angleindex2 = angleindex2 % elevationarray[elevindexlow]; angleindex3 = (int)angleindexhighstore; angleindex4 = angleindex3 + 1; angleindex4 = angleindex4 % elevationarray[elevindexhigh]; /* angle percentages for interp */ angleindex2per = angleindexlowstore - angleindex1; angleindex4per = angleindexhighstore - angleindex3; /* read 4 nearest HRTFs */ skip = 0; /* switch l and r */ if(angleindex1 > elevationarray[elevindexlow] / 2) { for(i = 0; i < elevindexlow; i++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < (elevationarray[elevindexlow] - angleindex1); i++) skip += irlength; for(i = 0; i < irlength; i++) { lowl1[i] = fpindexr[skip + i]; lowr1[i] = fpindexl[skip + i]; } } else { for(i = 0; i < elevindexlow; i++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < angleindex1; i++) skip += irlength; for(i = 0; i < irlength; i++) { lowl1[i] = fpindexl[skip + i]; lowr1[i] = fpindexr[skip + i]; } } skip = 0; if(angleindex2 > elevationarray[elevindexlow] / 2) { for(i = 0; i < elevindexlow; i++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < (elevationarray[elevindexlow] - angleindex2); i++) skip += irlength; for(i = 0; i < irlength; i++) { lowl2[i] = fpindexr[skip + i]; lowr2[i] = fpindexl[skip + i]; } } else { for(i = 0; i < elevindexlow; i++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < angleindex2; i++) skip += irlength; for(i = 0; i < irlength; i++) { lowl2[i] = fpindexl[skip + i]; lowr2[i] = fpindexr[skip + i]; } } skip = 0; if(angleindex3 > elevationarray[elevindexhigh] / 2) { for(i = 0; i < elevindexhigh; i++) skip += ((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < (elevationarray[elevindexhigh] - angleindex3); i++) skip += irlength; for(i = 0; i < irlength; i++) { highl1[i] = fpindexr[skip + i]; highr1[i] = fpindexl[skip + i]; } } else { for(i = 0; i < elevindexhigh; i++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < angleindex3; i++) skip += irlength; for(i = 0; i < irlength; i++) { highl1[i] = fpindexl[skip + i]; highr1[i] = fpindexr[skip + i]; } } skip = 0; if(angleindex4 > elevationarray[elevindexhigh] / 2) { for(i = 0; i < elevindexhigh; i++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < (elevationarray[elevindexhigh] - angleindex4); i++) skip += irlength; for(i = 0; i < irlength; i++) { highl2[i] = fpindexr[skip + i]; highr2[i] = fpindexl[skip + i]; } } else { for(i = 0; i < elevindexhigh; i++) skip +=((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < angleindex4; i++) skip += irlength; for(i = 0; i < irlength; i++) { highl2[i] = fpindexl[skip + i]; highr2[i] = fpindexr[skip + i]; } } /* woodworth process */ /* ITD formula, check which ear is relevant to calculate angle from */ if(angle > FL(180.0)) radianangle = (angle - FL(180.0)) * PI_F / FL(180.0); else radianangle = angle * PI_F / FL(180.0); /* degrees to radians */ radianelev = elev * PI_F / FL(180.0); /* get in correct range for formula */ if(radianangle > PI_F / FL(2.0)) radianangle = FL(PI) - radianangle; /* woodworth formula for itd */ itdww = (radianangle + SIN(radianangle)) * r * COS(radianelev) / c; /* 0 Hz and Nyq... */ /* these are real values...may be neg (implying phase of pi: in phase truncation), so need fabs... */ magllow = FABS(lowl1[0]) + (FABS(lowl2[0]) - FABS(lowl1[0])) * angleindex2per; maglhigh = FABS(highl1[0]) + (FABS(highl2[0]) - FABS(highl1[0])) * angleindex4per; hrtflfloat[0] = magllow + (maglhigh - magllow) * elevindexhighper; magllow = FABS(lowl1[1]) + (FABS(lowl2[1]) - FABS(lowl1[1])) * angleindex2per; maglhigh = FABS(highl1[1]) + (FABS(highl2[1]) - FABS(highl1[1])) * angleindex4per; hrtflfloat[1] = magllow + (maglhigh - magllow) * elevindexhighper; magrlow = FABS(lowr1[0]) + (FABS(lowr2[0]) - FABS(lowr1[0])) * angleindex2per; magrhigh = FABS(highr1[0]) + (FABS(highr2[0]) - FABS(highr1[0])) * angleindex4per; hrtfrfloat[0] = magrlow + (magrhigh - magrlow) * elevindexhighper; magrlow = FABS(lowr1[1]) + (FABS(lowr2[1]) - FABS(lowr1[1])) * angleindex2per; magrhigh = FABS(highr1[1]) + (FABS(highr2[1]) - FABS(highr1[1])) * angleindex4per; hrtfrfloat[1] = magrlow + (magrhigh - magrlow) * elevindexhighper; /* magnitude interpolation */ for(i = 2; i < irlength; i+=2) { /* interpolate high and low mags */ magllow = lowl1[i] + (lowl2[i] - lowl1[i]) * angleindex2per; maglhigh = highl1[i]+(highl2[i] - highl1[i]) * angleindex4per; magrlow = lowr1[i] + (lowr2[i] - lowr1[i]) * angleindex2per; magrhigh = highr1[i] + (highr2[i] - highr1[i]) * angleindex4per; /* interpolate high and low results */ magl = magllow + (maglhigh - magllow) * elevindexhighper; magr = magrlow + (magrhigh - magrlow) * elevindexhighper; freq = (i / 2) * p->sroverN; /* non linear itd...last value in array = 1.0, so back to itdww */ if(p->sr == 96000) { if ((i / 2) < 6) itd = itdww * nonlinitd96k[(i / 2) - 1]; } else if(p->sr == 48000) { if ((i / 2) < 6) itd = itdww * nonlinitd48k[(i / 2) - 1]; } else if(p->sr == 44100) { if((i / 2) < 6) itd = itdww * nonlinitd[(i / 2) - 1]; } if(angle > FL(180.)) { phasel = TWOPI_F * freq * (itd / 2); phaser = TWOPI_F * freq * -(itd / 2); } else { phasel = TWOPI_F * freq * -(itd / 2); phaser = TWOPI_F * freq * (itd / 2); } /* polar to rectangular */ hrtflfloat[i] = magl * COS(phasel); hrtflfloat[i+1] = magl * SIN(phasel); hrtfrfloat[i] = magr * COS(phaser); hrtfrfloat[i+1] = magr * SIN(phaser); } /* ifft */ csound->InverseRealFFT(csound, hrtflfloat, irlength); csound->InverseRealFFT(csound, hrtfrfloat, irlength); for (i = 0; i < irlength; i++) { /* scale and pad buffers with zeros to fftbuff */ leftshiftbuffer[i] = hrtflfloat[i]; rightshiftbuffer[i] = hrtfrfloat[i]; } /* shift for causality...impulse as is is centred around zero time lag... then phase added. */ /* this step centres impulse around centre tap of filter (then phase moves it for correct itd...) */ shift = irlength / 2; for(i = 0; i < irlength; i++) { hrtflpad[i] = leftshiftbuffer[shift]; hrtfrpad[i] = rightshiftbuffer[shift]; shift++; shift = shift % irlength; } /* zero pad impulse */ for(i = irlength; i < irlengthpad; i++) { hrtflpad[i] = FL(0.0); hrtfrpad[i] = FL(0.0); } /* back to freq domain */ csound->RealFFT(csound, hrtflpad, irlengthpad); csound->RealFFT(csound, hrtfrpad, irlengthpad); /* initialize counter */ p->counter = 0; return OK; } static int hrtfstat_process(CSOUND *csound, hrtfstat *p) { /* local pointers to p */ MYFLT *in = p->in; MYFLT *outsigl = p->outsigl; MYFLT *outsigr = p->outsigr; /* common buffers and variables */ MYFLT *insig = (MYFLT *)p->insig.auxp; MYFLT *outl = (MYFLT *)p->outl.auxp; MYFLT *outr = (MYFLT *)p->outr.auxp; MYFLT *hrtflpad = (MYFLT *)p->hrtflpad.auxp; MYFLT *hrtfrpad = (MYFLT *)p->hrtfrpad.auxp; MYFLT *complexinsig = (MYFLT *)p->complexinsig.auxp; MYFLT *outspecl = (MYFLT *)p->outspecl.auxp; MYFLT *outspecr = (MYFLT *)p->outspecr.auxp; MYFLT *overlapl = (MYFLT *)p->overlapl.auxp; MYFLT *overlapr = (MYFLT *)p->overlapr.auxp; int counter = p->counter; int i; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t j, nsmps = CS_KSMPS; int irlength = p->irlength; int irlengthpad = p->irlengthpad; int overlapsize = p->overlapsize; MYFLT sr = p->sr; if (UNLIKELY(offset)) { memset(outsigl, '\0', offset*sizeof(MYFLT)); memset(outsigr, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&outsigl[nsmps], '\0', early*sizeof(MYFLT)); memset(&outsigr[nsmps], '\0', early*sizeof(MYFLT)); } for(j = offset; j < nsmps; j++) { /* ins and outs */ insig[counter] = in[j]; outsigl[j] = outl[counter]; outsigr[j] = outr[counter]; counter++; if(counter == irlength) { /* process a block */ /* look after overlap add stuff */ for(i = 0; i < overlapsize ; i++) { overlapl[i] = outl[i+irlength]; overlapr[i] = outr[i+irlength]; } /* insert insig for complex real,im fft, zero pad */ for (i = 0; i < irlength; i++) complexinsig[i] = insig[i]; for (i = irlength; i < irlengthpad; i++) complexinsig[i] = FL(0.0); csound->RealFFT(csound, complexinsig, irlengthpad); /* complex multiplication */ csound->RealFFTMult(csound, outspecl, hrtflpad, complexinsig, irlengthpad, FL(1.0)); csound->RealFFTMult(csound, outspecr, hrtfrpad, complexinsig, irlengthpad, FL(1.0)); /* convolution is the inverse FFT of above result */ csound->InverseRealFFT(csound, outspecl, irlengthpad); csound->InverseRealFFT(csound, outspecr, irlengthpad); /* scaled by a factor related to sr...? */ for(i = 0; i < irlengthpad; i++) { outl[i] = outspecl[i] / (sr / FL(38000.0)); outr[i] = outspecr[i] / (sr / FL(38000.0)); } for(i = 0; i < irlength; i++) { outl[i] = outl[i] + (i < overlapsize ? overlapl[i] : FL(0.0)); outr[i] = outr[i] + (i < overlapsize ? overlapr[i] : FL(0.0)); } /* reset counter */ counter = 0; } /* end of irlength == counter */ } /* end of ksmps audio loop */ /* update */ p->counter = counter; return OK; } /* Csound hrtf magnitude interpolation, dynamic woodworth trajectory */ /* stft from fft.cpp in sndobj... */ /* stft based on sndobj implementation...some notes: */ /* using an overlapskip (same as m_counter) for in and out to control seperately for clarity... */ /* aleft, aright hrtfmove2 ain, kang, kel, ifilel, ifiler [, ioverlap = 4, iradius = 8.8, isr = 44100] */ /* ioverlap is stft overlap, iradius is head radius, sr can also be 48000 and 96000 */ typedef struct { OPDS h; /* outputs and inputs */ MYFLT *outsigl, *outsigr; MYFLT *in, *kangle, *kelev; STRINGDAT *ifilel, *ifiler; MYFLT *ooverlap, *oradius, *osr; /* check if relative source has changed! */ MYFLT anglev, elevv; /* see definitions in INIT */ int irlength; MYFLT sroverN; MYFLT sr; /* test inputs in init, get accepted value/default, and store in variables below. */ int overlap; MYFLT radius; int hopsize; float *fpbeginl,*fpbeginr; /* to keep track of process */ int counter, t; /* in and output buffers */ AUXCH inbuf; AUXCH outbufl, outbufr; /* memory local to perform method */ /* insig fft */ AUXCH complexinsig; /* hrtf buffers (rectangular complex form) */ AUXCH hrtflfloat, hrtfrfloat; /* spectral data */ AUXCH outspecl, outspecr; /* interpolation buffers */ AUXCH lowl1,lowr1,lowl2,lowr2,highl1,highr1,highl2,highr2; /* stft window */ AUXCH win; /* used for skipping into next stft array on way in and out */ AUXCH overlapskipin, overlapskipout; } hrtfmove2; static int hrtfmove2_init(CSOUND *csound, hrtfmove2 *p) { /* left and right data files: spectral mag, phase format. */ MEMFIL *fpl = NULL, *fpr = NULL; char filel[MAXNAME], filer[MAXNAME]; /* time domain impulse length */ int irlength=0; /* stft window */ MYFLT *win; /* overlap skip buffers */ int *overlapskipin, *overlapskipout; //MYFLT *inbuf; //MYFLT *outbufl, *outbufr; int overlap = (int)*p->ooverlap; MYFLT r = *p->oradius; MYFLT sr = *p->osr; int i = 0; if(sr != 44100 && sr != 48000 && sr != 96000) sr = 44100; p->sr = sr; if (UNLIKELY(CS_ESR != sr)) csound->Message(csound, Str("\n\nWARNING!!:\nOrchestra SR not compatible" "with HRTF processing SR of: %.0f\n\n"), sr); /* setup as per sr */ if(sr == 44100 || sr == 48000) irlength = 128; else if(sr == 96000) irlength = 256; /* copy in string name... */ strncpy(filel, (char*) p->ifilel->data, MAXNAME-1); filel[MAXNAME-1] = '\0'; strncpy(filer, (char*) p->ifiler->data, MAXNAME-1); filer[MAXNAME-1] = '\0'; /* reading files, with byte swap */ fpl = csound->ldmemfile2withCB(csound, filel, CSFTYPE_FLOATS_BINARY, swap4bytes); if (UNLIKELY(fpl == NULL)) return csound->InitError(csound, Str("\n\n\nCannot load left data file, exiting\n\n")); fpr = csound->ldmemfile2withCB(csound, filer, CSFTYPE_FLOATS_BINARY, swap4bytes); if (UNLIKELY(fpr == NULL)) return csound->InitError(csound, Str("\n\n\nCannot load right data file, exiting\n\n")); p->irlength = irlength; p->sroverN = sr / irlength; /* file handles */ p->fpbeginl = (float *) fpl->beginp; p->fpbeginr = (float *) fpr->beginp; if(overlap != 2 && overlap != 4 && overlap != 8 && overlap != 16) overlap = 4; p->overlap = overlap; if(r <= 0 || r > 15) r = FL(8.8); p->radius = r; p->hopsize = (int)(irlength / overlap); /* buffers */ if (!p->inbuf.auxp || p->inbuf.size < (overlap * irlength) * sizeof(MYFLT)) csound->AuxAlloc(csound, (overlap * irlength) * sizeof(MYFLT), &p->inbuf); /* 2d arrays in 1d! */ if (!p->outbufl.auxp || p->outbufl.size < (overlap * irlength) * sizeof(MYFLT)) csound->AuxAlloc(csound, (overlap * irlength) * sizeof(MYFLT), &p->outbufl); if (!p->outbufr.auxp || p->outbufr.size < (overlap * irlength) * sizeof(MYFLT)) csound->AuxAlloc(csound, (overlap * irlength) * sizeof(MYFLT), &p->outbufr); if (!p->complexinsig.auxp || p->complexinsig.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p-> complexinsig); if (!p->hrtflfloat.auxp || p->hrtflfloat.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->hrtflfloat); if (!p->hrtfrfloat.auxp || p->hrtfrfloat.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->hrtfrfloat); if (!p->outspecl.auxp || p->outspecl.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->outspecl); if (!p->outspecr.auxp || p->outspecr.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->outspecr); memset(p->inbuf.auxp, 0, (overlap*irlength) * sizeof(MYFLT)); memset(p->outbufl.auxp, 0, (overlap*irlength) * sizeof(MYFLT)); memset(p->outbufr.auxp, 0, (overlap*irlength) * sizeof(MYFLT)); memset(p->complexinsig.auxp, 0, irlength * sizeof(MYFLT)); memset(p->hrtflfloat.auxp, 0, irlength * sizeof(MYFLT)); memset(p->hrtfrfloat.auxp, 0, irlength * sizeof(MYFLT)); memset(p->outspecl.auxp, 0, irlength * sizeof(MYFLT)); memset(p->outspecr.auxp, 0, irlength * sizeof(MYFLT)); /* interpolation values */ if (!p->lowl1.auxp || p->lowl1.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->lowl1); if (!p->lowr1.auxp || p->lowr1.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->lowr1); if (!p->lowl2.auxp || p->lowl2.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->lowl2); if (!p->lowr2.auxp || p->lowr2.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->lowr2); if (!p->highl1.auxp || p->highl1.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->highl1); if (!p->highr1.auxp || p->highr1.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->highr1); if (!p->highl2.auxp || p->highl2.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->highl2); if (!p->highr2.auxp || p->highr2.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->highr2); memset(p->lowl1.auxp, 0, irlength * sizeof(MYFLT)); memset(p->lowr1.auxp, 0, irlength * sizeof(MYFLT)); memset(p->lowl2.auxp, 0, irlength * sizeof(MYFLT)); memset(p->lowr2.auxp, 0, irlength * sizeof(MYFLT)); memset(p->highl1.auxp, 0, irlength * sizeof(MYFLT)); memset(p->highl2.auxp, 0, irlength * sizeof(MYFLT)); memset(p->highr1.auxp, 0, irlength * sizeof(MYFLT)); memset(p->highr2.auxp, 0, irlength * sizeof(MYFLT)); if (!p->win.auxp || p->win.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->win); if (!p->overlapskipin.auxp || p->overlapskipin.size < overlap * sizeof(int)) csound->AuxAlloc(csound, overlap * sizeof(int), &p->overlapskipin); if (!p->overlapskipout.auxp || p->overlapskipout.size < overlap * sizeof(int)) csound->AuxAlloc(csound, overlap * sizeof(int), &p->overlapskipout); memset(p->win.auxp, 0, irlength * sizeof(MYFLT)); memset(p->overlapskipin.auxp, 0, overlap * sizeof(int)); memset(p->overlapskipout.auxp, 0, overlap * sizeof(int)); win = (MYFLT *)p->win.auxp; overlapskipin = (int *)p->overlapskipin.auxp; overlapskipout = (int *)p->overlapskipout.auxp; /* window is Hanning */ for(i = 0; i < irlength; i++) win[i] = FL(0.5) - (FL(0.5) * COS(i * TWOPI_F / (MYFLT)(irlength - 1))); for(i = 0; i < overlap; i++) { /* so, for example in overlap 4: will be 0, 32, 64, 96 if ir = 128 */ overlapskipin[i] = p->hopsize * i; overlapskipout[i] = p->hopsize * i; } /* initialise */ p->counter = 0; p->t = 0; /* setup values used to check if src has moved, illegal values to start with to ensure first read */ p->anglev = -1; p->elevv = -41; return OK; } static int hrtfmove2_process(CSOUND *csound, hrtfmove2 *p) { /* local pointers to p */ MYFLT *in = p->in; MYFLT *outsigl = p->outsigl; MYFLT *outsigr = p->outsigr; /* common buffers and variables */ MYFLT *inbuf = (MYFLT *)p->inbuf.auxp; MYFLT *outbufl = (MYFLT *)p->outbufl.auxp; MYFLT *outbufr = (MYFLT *)p->outbufr.auxp; MYFLT outsuml = FL(0.0), outsumr = FL(0.0); MYFLT *complexinsig = (MYFLT *)p->complexinsig.auxp; MYFLT *hrtflfloat = (MYFLT *)p->hrtflfloat.auxp; MYFLT *hrtfrfloat = (MYFLT *)p->hrtfrfloat.auxp; MYFLT *outspecl = (MYFLT *)p->outspecl.auxp; MYFLT *outspecr = (MYFLT *)p->outspecr.auxp; MYFLT elev = *p->kelev; MYFLT angle = *p->kangle; int overlap = p->overlap; MYFLT r = p->radius; MYFLT sr = p->sr; MYFLT sroverN = p->sroverN; int hopsize = p->hopsize; MYFLT *win = (MYFLT *)p->win.auxp; int *overlapskipin = (int *)p->overlapskipin.auxp; int *overlapskipout = (int *)p->overlapskipout.auxp; int counter = p ->counter; int t = p ->t; /* pointers into HRTF files */ float *fpindexl; float *fpindexr; int i, skip = 0; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t j, nsmps = CS_KSMPS; /* interpolation values */ MYFLT *lowl1 = (MYFLT *)p->lowl1.auxp; MYFLT *lowr1 = (MYFLT *)p->lowr1.auxp; MYFLT *lowl2 = (MYFLT *)p->lowl2.auxp; MYFLT *lowr2 = (MYFLT *)p->lowr2.auxp; MYFLT *highl1 = (MYFLT *)p->highl1.auxp; MYFLT *highr1 = (MYFLT *)p->highr1.auxp; MYFLT *highl2 = (MYFLT *)p->highl2.auxp; MYFLT *highr2 = (MYFLT *)p->highr2.auxp; /* local interpolation values */ MYFLT elevindexhighper, angleindex2per, angleindex4per; int elevindexlow, elevindexhigh, angleindex1, angleindex2, angleindex3, angleindex4; MYFLT magl, magr, phasel, phaser, magllow, magrlow, maglhigh, magrhigh; /* woodworth values */ MYFLT radianangle, radianelev, itd=0, itdww, freq; int irlength = p->irlength; /* local variables, mainly used for simplification */ MYFLT elevindexstore; MYFLT angleindexlowstore; MYFLT angleindexhighstore; /* start indices at correct value (start of file)/ zero indices. */ fpindexl = (float *) p->fpbeginl; fpindexr = (float *) p->fpbeginr; if (UNLIKELY(offset)) { memset(outsigl, '\0', offset*sizeof(MYFLT)); memset(outsigr, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&outsigl[nsmps], '\0', early*sizeof(MYFLT)); memset(&outsigr[nsmps], '\0', early*sizeof(MYFLT)); } /* ksmps loop */ for(j = offset; j < nsmps; j++) { /* distribute the signal and apply the window */ /* according to a time pointer (kept by overlapskip[n]) */ for(i = 0; i < overlap; i++) { inbuf[(i * irlength) + overlapskipin[i]] = in[j] * win[overlapskipin[i]]; overlapskipin[i]++; } counter++; if(counter == hopsize) { /* process a block */ if(elev > FL(90.0)) elev = FL(90.0); if(elev < FL(-40.0)) elev = FL(-40.0); while(angle < FL(0.0)) angle += FL(360.0); while(angle >= FL(360.0)) angle -= FL(360.0); if(angle != p->anglev || elev != p->elevv) { /* two nearest elev indices to avoid recalculating */ elevindexstore = (elev - minelev) / elevincrement; elevindexlow = (int)elevindexstore; if(elevindexlow < 13) elevindexhigh = elevindexlow + 1; /* highest index reached */ else elevindexhigh = elevindexlow; /* get percentage value for interpolation */ elevindexhighper = elevindexstore - elevindexlow; /* avoid recalculation */ angleindexlowstore = angle / (FL(360.0) / elevationarray[elevindexlow]); angleindexhighstore = angle / (FL(360.0) / elevationarray[elevindexhigh]); /* 4 closest indices, 2 low and 2 high */ angleindex1 = (int)angleindexlowstore; angleindex2 = angleindex1 + 1; angleindex2 = angleindex2 % elevationarray[elevindexlow]; angleindex3 = (int)angleindexhighstore; angleindex4 = angleindex3 + 1; angleindex4 = angleindex4 % elevationarray[elevindexhigh]; /* angle percentages for interp */ angleindex2per = angleindexlowstore - angleindex1; angleindex4per = angleindexhighstore - angleindex3; /* read 4 nearest HRTFs */ skip = 0; /* switch l and r */ if(angleindex1 > elevationarray[elevindexlow] / 2) { for(i = 0; i < elevindexlow; i++) skip += ((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < (elevationarray[elevindexlow] - angleindex1); i++) skip += irlength; for(i = 0; i < irlength; i++) { lowl1[i] = fpindexr[skip + i]; lowr1[i] = fpindexl[skip + i]; } } else { for(i = 0; i < elevindexlow; i++) skip += ((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < angleindex1; i++) skip += irlength; for(i = 0; i < irlength; i++) { lowl1[i] = fpindexl[skip + i]; lowr1[i] = fpindexr[skip + i]; } } skip = 0; if(angleindex2 > elevationarray[elevindexlow] / 2) { for(i = 0; i < elevindexlow; i++) skip += ((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < (elevationarray[elevindexlow] - angleindex2); i++) skip += irlength; for(i = 0; i < irlength; i++) { lowl2[i] = fpindexr[skip + i]; lowr2[i] = fpindexl[skip + i]; } } else { for(i = 0; i < elevindexlow; i++) skip += ((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < angleindex2; i++) skip += irlength; for(i = 0; i < irlength; i++) { lowl2[i] = fpindexl[skip + i]; lowr2[i] = fpindexr[skip + i]; } } skip = 0; if(angleindex3 > elevationarray[elevindexhigh] / 2) { for(i = 0; i < elevindexhigh; i++) skip += ((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < (elevationarray[elevindexhigh] - angleindex3); i++) skip += irlength; for(i = 0; i < irlength; i++) { highl1[i] = fpindexr[skip + i]; highr1[i] = fpindexl[skip + i]; } } else { for(i = 0; i < elevindexhigh; i++) skip += ((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < angleindex3; i++) skip += irlength; for(i = 0; i < irlength; i++) { highl1[i] = fpindexl[skip + i]; highr1[i] = fpindexr[skip + i]; } } skip = 0; if(angleindex4 > elevationarray[elevindexhigh] / 2) { for(i = 0; i < elevindexhigh; i++) skip += ((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < (elevationarray[elevindexhigh] - angleindex4); i++) skip += irlength; for(i = 0; i < irlength; i++) { highl2[i] = fpindexr[skip + i]; highr2[i] = fpindexl[skip + i]; } } else { for(i = 0; i < elevindexhigh; i++) skip += ((int)(elevationarray[i] / 2) + 1) * irlength; for (i = 0; i < angleindex4; i++) skip += irlength; for(i = 0; i < irlength; i++) { highl2[i] = fpindexl[skip + i]; highr2[i] = fpindexr[skip + i]; } } /* woodworth process */ /* ITD formula, check which ear is relevant to calculate angle from */ if(angle > FL(180.0)) radianangle = (angle - FL(180.0)) * PI_F / FL(180.0); else radianangle = angle * PI_F / FL(180.0); /* degrees to radians */ radianelev = elev * PI_F / FL(180.0); /* get in correct range for formula */ if(radianangle > (PI_F / FL(2.0))) radianangle = FL(PI) - radianangle; /* woodworth formula for itd */ itdww = (radianangle + SIN(radianangle)) * r * COS(radianelev) / c; /* 0 Hz and Nyq... */ /* need fabs() here, to get mag, as 0hz and nyq stored as a real value, to allow for possible negative, implying phase of pi (in phase truncation) */ magllow = FABS(lowl1[0]) + (FABS(lowl2[0]) - FABS(lowl1[0])) * angleindex2per; maglhigh = FABS(highl1[0]) + (FABS(highl2[0]) - FABS(highl1[0])) * angleindex4per; hrtflfloat[0] = magllow + (maglhigh - magllow) * elevindexhighper; magllow = FABS(lowl1[1]) + (FABS(lowl2[1]) - FABS(lowl1[1])) * angleindex2per; maglhigh = FABS(highl1[1]) + (FABS(highl2[1]) - FABS(highl1[1])) * angleindex4per; hrtflfloat[1] = magllow + (maglhigh - magllow) * elevindexhighper; magrlow = FABS(lowr1[0]) + (FABS(lowr2[0]) - FABS(lowr1[0])) * angleindex2per; magrhigh = FABS(highr1[0]) + (FABS(highr2[0]) - FABS(highr1[0])) * angleindex4per; hrtfrfloat[0] = magrlow + (magrhigh - magrlow) * elevindexhighper; magrlow = FABS(lowr1[1]) + (FABS(lowr2[1]) - FABS(lowr1[1])) * angleindex2per; magrhigh = FABS(highr1[1]) + (FABS(highr2[1]) - FABS(highr1[1])) * angleindex4per; hrtfrfloat[1] = magrlow + (magrhigh - magrlow) * elevindexhighper; /* magnitude interpolation */ for(i = 2; i < irlength; i += 2) { /* interpolate high and low mags */ magllow = lowl1[i] + (lowl2[i] - lowl1[i]) * angleindex2per; maglhigh = highl1[i] + (highl2[i] - highl1[i]) * angleindex4per; magrlow = lowr1[i] + (lowr2[i] - lowr1[i]) * angleindex2per; magrhigh = highr1[i] + (highr2[i] - highr1[i]) * angleindex4per; /* interpolate high and low results */ magl = magllow + (maglhigh - magllow) * elevindexhighper; magr = magrlow + (magrhigh - magrlow) * elevindexhighper; freq = (i / 2) * sroverN; /* non linear itd...last value in array = 1.0, so back to itdww */ if(p->sr == 96000) { if ((i / 2) < 6) itd = itdww * nonlinitd96k[(i / 2) - 1]; } else if(p->sr == 48000) { if ((i / 2) < 6) itd = itdww * nonlinitd48k[(i / 2) - 1]; } else if(p->sr == 44100) { if((i / 2) < 6) itd = itdww * nonlinitd[(i / 2) - 1]; } if(angle > FL(180.)) { phasel = TWOPI_F * freq * (itd / 2); phaser = TWOPI_F * freq * -(itd / 2);} else { phasel = TWOPI_F * freq * -(itd / 2); phaser = TWOPI_F * freq * (itd / 2); } /* polar to rectangular */ hrtflfloat[i] = magl * COS(phasel); hrtflfloat[i+1] = magl * SIN(phasel); hrtfrfloat[i] = magr * COS(phaser); hrtfrfloat[i+1] = magr * SIN(phaser); } p->elevv = elev; p->anglev = angle; } /* t used to read inbuf...*/ t--; if(t < 0) t = overlap - 1; /* insert insig for complex real, im fft */ for(i = 0; i < irlength; i++) complexinsig[i] = inbuf[(t * irlength) + i]; /* zero the current input sigframe time pointer */ overlapskipin[t] = 0; csound->RealFFT(csound, complexinsig, irlength); csound->RealFFTMult(csound, outspecl, hrtflfloat, complexinsig, irlength, FL(1.0)); csound->RealFFTMult(csound, outspecr, hrtfrfloat, complexinsig, irlength, FL(1.0)); /* convolution is the inverse FFT of above result */ csound->InverseRealFFT(csound, outspecl, irlength); csound->InverseRealFFT(csound, outspecr, irlength); /* need scaling based on overlap (more overlaps -> louder) and sr... */ for(i = 0; i < irlength; i++) { outbufl[(t * irlength) + i] = outspecl[i] / (overlap * FL(0.5) * (sr / FL(44100.0))); outbufr[(t * irlength) + i] = outspecr[i] / (overlap * FL(0.5) * (sr / FL(44100.0))); } } /* end of !counter % hopsize */ /* output = sum of all relevant outputs: eg if overlap = 4 and counter = 0, */ /* outsigl[j] = outbufl[0] + outbufl[128 + 96] + outbufl[256 + 64] + outbufl[384 + 32]; */ /* * * * * [ ] + */ /* * * * [*] + */ /* * * [*] * + */ /* * [*] * * = */ /* stft! */ outsuml = outsumr = FL(0.0); for(i = 0; i < (int)overlap; i++) { outsuml += outbufl[(i * irlength) + overlapskipout[i]] * win[overlapskipout[i]]; outsumr += outbufr[(i * irlength) + overlapskipout[i]] * win[overlapskipout[i]]; overlapskipout[i]++; } if(counter == hopsize) { /* zero output incrementation... */ /* last buffer will have gone from 96 to 127...then 2nd last will have gone from 64 to 127... */ overlapskipout[t] = 0; counter = 0; } outsigl[j] = outsuml; outsigr[j] = outsumr; } /* end of ksmps audio loop */ /* update */ p->t = t; p->counter = counter; return OK; } /* see csound manual (extending csound) for details of below */ static OENTRY hrtfopcodes_localops[] = { { "hrtfmove", sizeof(hrtfmove),0, 5, "aa", "akkSSooo", (SUBR)hrtfmove_init, NULL, (SUBR)hrtfmove_process }, { "hrtfstat", sizeof(hrtfstat),0, 5, "aa", "aiiSSoo", (SUBR)hrtfstat_init, NULL, (SUBR)hrtfstat_process }, { "hrtfmove2", sizeof(hrtfmove2),0, 5, "aa", "akkSSooo", (SUBR)hrtfmove2_init, NULL, (SUBR)hrtfmove2_process } }; LINKAGE_BUILTIN(hrtfopcodes_localops) csound-6.10.0/Opcodes/hrtfreverb.c000066400000000000000000001434571321653344700170300ustar00rootroot00000000000000/* Brian Carty PhD Code August 2010 binaural reverb: diffuse field This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "interlocks.h" #define SQUARE(X) ((X)*(X)) /* endian issues: swap bytes for ppc */ #ifdef WORDS_BIGENDIAN static int swap4bytes(CSOUND* csound, MEMFIL* mfp) { char c1, c2, c3, c4; char *p = mfp->beginp; int size = mfp->length; while (size >= 4) { c1 = p[0]; c2 = p[1]; c3 = p[2]; c4 = p[3]; p[0] = c4; p[1] = c3; p[2] = c2; p[3] = c1; size -= 4; p +=4; } return OK; } #else static int (*swap4bytes)(CSOUND*, MEMFIL*) = NULL; #endif /* matrices for feedback delay network (fdn) */ #define mthird (-FL(1.0) / 3) #define tthird (FL(2.0) / 3) #define msix (-FL(1.0) / 6) #define fsix (FL(5.0) / 6) #define mtw (-FL(1.0) / 12) #define etw (FL(11.0) / 12) static const MYFLT matrix6[36] = {tthird,mthird,mthird,mthird,mthird,mthird, mthird,tthird,mthird,mthird,mthird,mthird, mthird,mthird,tthird,mthird,mthird,mthird, mthird,mthird,mthird,tthird,mthird,mthird, mthird,mthird,mthird,mthird,tthird,mthird, mthird,mthird,mthird,mthird,mthird,tthird}; static const MYFLT matrix12[144] = {fsix,msix,msix,msix,msix,msix,msix,msix,msix,msix,msix,msix, msix,fsix,msix,msix,msix,msix,msix,msix,msix,msix,msix,msix, msix,msix,fsix,msix,msix,msix,msix,msix,msix,msix,msix,msix, msix,msix,msix,fsix,msix,msix,msix,msix,msix,msix,msix,msix, msix,msix,msix,msix,fsix,msix,msix,msix,msix,msix,msix,msix, msix,msix,msix,msix,msix,fsix,msix,msix,msix,msix,msix,msix, msix,msix,msix,msix,msix,msix,fsix,msix,msix,msix,msix,msix, msix,msix,msix,msix,msix,msix,msix,fsix,msix,msix,msix,msix, msix,msix,msix,msix,msix,msix,msix,msix,fsix,msix,msix,msix, msix,msix,msix,msix,msix,msix,msix,msix,msix,fsix,msix,msix, msix,msix,msix,msix,msix,msix,msix,msix,msix,msix,fsix,msix, msix,msix,msix,msix,msix,msix,msix,msix,msix,msix,msix,fsix}; static const MYFLT matrix24[576] = {etw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,etw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,etw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,etw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,etw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,etw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,etw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,etw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,etw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,etw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,etw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,etw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, etw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,etw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,etw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,etw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,etw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,etw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,etw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,etw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,etw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,etw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,etw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw, mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,mtw,etw}; /* for delay line lengths */ static const int primes[229] = { 17, 23, 59, 71, 113, 127, 163, 191, 211, 229, 271, 283, 313, 337, 359, 373, 409, 461, 541, 587, 631, 691, 709, 773, 829, 863, 919, 971, 1039, 1069, 1123, 1171, 1217, 1259, 1303, 1373, 1423, 1483, 1511, 1597, 1627, 1669, 1733, 1787, 1847, 1867, 1913, 1951, 2027, 2081, 2131, 2179, 2213, 2269, 2333, 2383, 2423, 2467, 2531, 2579, 2617, 2671, 2729, 2789, 2837, 2861, 2917, 2999, 3011, 3083, 3121, 3169, 3209, 3259, 3331, 3389, 3449, 3469, 3533, 3571, 3613, 3671, 3727, 3779, 3821, 3889, 3917, 3989, 4001, 4051, 4111, 4177, 4231, 4271, 4337, 4391, 4447, 4483, 4517, 4567, 4621, 4691, 4733, 4787, 4817, 4861, 4919, 4967, 5023, 5077, 5113, 5167, 5233, 5297, 5309, 5351, 5441, 5483, 5507, 5563, 5641, 5683, 5711, 5783, 5821, 5857, 5927, 5981, 6011, 6067, 6121, 6173, 6217, 6271, 6317, 6361, 6421, 6473, 6529, 6581, 6607, 6661, 6733, 6793, 6841, 6883, 6911, 6961, 7027, 7057, 7109, 7177, 7211, 7297, 7349, 7393, 7417, 7481, 7523, 7561, 7607, 7673, 7717, 7789, 7841, 7879, 7919, 7963, 8017, 8081, 8111, 8167, 8209, 8287, 8317, 8377, 8443, 8467, 8521, 8563, 8623, 8677, 8713, 8761, 8831, 8867, 8923, 8963, 9013, 9059, 9109, 9187, 9221, 9257, 9323, 9371, 9413, 9461, 9511, 9587, 9631, 9679, 9721, 9781, 9803, 9859, 9949, 9973, 10039, 10079, 10111, 10177, 10211, 10259, 10333, 10391, 10429, 10459, 10513, 10589, 10607, 10663, 10711, 10799, 10831, 10859, 10909, 10979, 11003 }; typedef struct { OPDS h; /* in / out */ /* outputs l/r and delay required for late del...*/ MYFLT *outsigl, *outsigr, *idel; /* mean free path and order are optional, meanfp defaults to medium room, opcode can be used as stand alone binaural reverb, or spatially accurate taking meanfp and order from earlies opcode */ MYFLT *insig, *ilowrt60, *ihighrt60; STRINGDAT *ifilel, *ifiler; MYFLT *osr, *omeanfp, *porder; /* internal data / class variables */ MYFLT delaytime; int delaytimeint, basedelay; /* number of delay lines */ int M; /* delay line iterators */ int u, v, w, x, y, z; int ut, vt, wt, xt, yt, zt; int utf1, vtf1, wtf1, xtf1, ytf1, ztf1; int utf2, vtf2, wtf2, xtf2, ytf2, ztf2; /* buffer lengths, change for different sr */ int irlength; int irlengthpad; int overlapsize; /* memory buffers: delays */ AUXCH delays; /* filter coeffs */ AUXCH gi, ai; /* matrix manipulations */ AUXCH inmat, inmatlp, dellp, outmat; /* delays */ AUXCH del1, del2, del3, del4, del5, del6; AUXCH del1t, del2t, del3t, del4t, del5t, del6t; AUXCH del1tf, del2tf, del3tf, del4tf, del5tf, del6tf, del7tf, del8tf, del9tf, del10tf, del11tf, del12tf; /* filter variables, spectral manipulations */ AUXCH power, HRTFave, num, denom, cohermags, coheru, coherv; AUXCH filtout, filtuout, filtvout, filtpad, filtupad, filtvpad; /* output of matrix cycle, with IIRs in combs and FIR tone, then l and r o/p processed with u and v coherence filters */ /* with overlap buffers for overlap add convolution */ AUXCH matrixlu, matrixrv; AUXCH olmatrixlu, olmatrixrv; /* above processed with hrtf l and r filters */ /* with overlap buffers for overlap add convolution */ AUXCH hrtfl, hrtfr; AUXCH olhrtfl, olhrtfr; /* filter coeff */ MYFLT b; /* 1st order FIR mem */ MYFLT inoldl, inoldr; /* for storing hrtf data used to create filters */ AUXCH buffl, buffr; /* counter */ int counter; MYFLT sr; }hrtfreverb; int hrtfreverb_init(CSOUND *csound, hrtfreverb *p) { /* left and right data files: spectral mag, phase format */ MEMFIL *fpl = NULL, *fpr = NULL; char filel[MAXNAME],filer[MAXNAME]; /* files contain floats */ float *fpindexl, *fpindexr; /* processing sizes */ int irlength=0, irlengthpad=0, overlapsize=0; /* pointers used to fill buffers in data structure */ int *delaysp; MYFLT *gip, *aip; MYFLT *powerp, *HRTFavep, *nump, *denomp, *cohermagsp, *coherup, *cohervp; MYFLT *filtoutp, *filtuoutp, *filtvoutp, *filtpadp, *filtupadp, *filtvpadp; MYFLT *bufflp, *buffrp; /* iterators, file skip */ int i, j; int skip = 0; int skipdouble = 0; /* used in choice of delay line lengths */ int basedelay=0; /* local filter variables for spectral manipulations */ MYFLT rel, rer, retemp, iml, imr, imtemp; /* setup filters */ MYFLT T, alpha, aconst, exp; int clipcheck = 0; MYFLT sr = (MYFLT)*p->osr; MYFLT meanfp = (MYFLT)*p->omeanfp; int order = (int)*p->porder; /* delay line variables */ MYFLT delaytime, meanfporder; int delaytimeint; int Msix, Mtwelve, Mtwentyfour; int meanfpsamps, meanfpordersamps; int test; MYFLT rt60low = (MYFLT)*p->ilowrt60; MYFLT rt60high = (MYFLT)*p->ihighrt60; int M; /* sr, defualt 44100 */ if(sr != 44100 && sr != 48000 && sr != 96000) sr = 44100; p->sr = sr; if (UNLIKELY(CS_ESR != sr)) csound->Message(csound, Str("\n\nWARNING!!:\nOrchestra SR not compatible with" " HRTF processing SR of: %.0f\n\n"), sr); /* meanfp: defaults to doom size 10 * 10 * 4 (max of 1: v. large room, min according to min room dimensions in early: 2 * 2 * 2) */ if(meanfp <= 0.003876 || meanfp > 1) meanfp = FL(0.01292); /* order: defaults to 1 (4 is max for earlies) */ if(order < 0 || order > 4) order = 1; /* rt60 values must be positive and non zero */ if(rt60low <= 0) rt60low = FL(0.01); if(rt60high <= 0) rt60high = FL(0.01); /* setup as per sr */ if(sr == 44100 || sr == 48000) { irlength = 128; irlengthpad = 256; overlapsize = (irlength - 1); } else if(sr == 96000) { irlength = 256; irlengthpad = 512; overlapsize = (irlength - 1); } /* copy in string name... */ strncpy(filel, (char*) p->ifilel->data, MAXNAME-1); strncpy(filer, (char*) p->ifiler->data, MAXNAME-1); /* reading files, with byte swap */ fpl = csound->ldmemfile2withCB(csound, filel, CSFTYPE_FLOATS_BINARY, swap4bytes); if (UNLIKELY(fpl == NULL)) return csound->InitError(csound, Str("\n\n\nCannot load left data file, exiting\n\n")); fpr = csound->ldmemfile2withCB(csound, filer, CSFTYPE_FLOATS_BINARY,swap4bytes); if (UNLIKELY(fpr == NULL)) return csound->InitError(csound, Str("\n\n\nCannot load right data file, exiting\n\n")); /* do not need to be in p, as only used in init */ fpindexl = (float *)fpl->beginp; fpindexr = (float *)fpr->beginp; /* setup structure values */ p->irlength = irlength; p->irlengthpad = irlengthpad; p->overlapsize = overlapsize; /* allocate memory */ if (!p->power.auxp || p->power.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->power); if (!p->HRTFave.auxp || p->HRTFave.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->HRTFave); if (!p->num.auxp || p->num.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->num); if (!p->denom.auxp || p->denom.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->denom); if (!p->cohermags.auxp || p->cohermags.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->cohermags); if (!p->coheru.auxp || p->coheru.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->coheru); if (!p->coherv.auxp || p->coherv.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->coherv); if (!p->filtout.auxp || p->filtout.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->filtout); if (!p->filtuout.auxp || p->filtuout.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->filtuout); if (!p->filtvout.auxp || p->filtvout.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->filtvout); if (!p->filtpad.auxp || p->filtpad.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad * sizeof(MYFLT), &p->filtpad); if (!p->filtupad.auxp || p->filtupad.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad * sizeof(MYFLT), &p->filtupad); if (!p->filtvpad.auxp || p->filtvpad.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad * sizeof(MYFLT), &p->filtvpad); /* zero numerator and power buffer, as they accumulate */ memset(p->power.auxp, 0, irlength * sizeof(MYFLT)); memset(p->num.auxp, 0, irlength * sizeof(MYFLT)); /* no need to zero other above mem, as it will be filled in init */ if (!p->matrixlu.auxp || p->matrixlu.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad * sizeof(MYFLT), &p->matrixlu); if (!p->matrixrv.auxp || p->matrixrv.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad * sizeof(MYFLT), &p->matrixrv); if (!p->olmatrixlu.auxp || p->olmatrixlu.size < overlapsize * sizeof(MYFLT)) csound->AuxAlloc(csound, overlapsize * sizeof(MYFLT), &p->olmatrixlu); if (!p->olmatrixrv.auxp || p->olmatrixrv.size < overlapsize * sizeof(MYFLT)) csound->AuxAlloc(csound, overlapsize * sizeof(MYFLT), &p->olmatrixrv); if (!p->hrtfl.auxp || p->hrtfl.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad * sizeof(MYFLT), &p->hrtfl); if (!p->hrtfr.auxp || p->hrtfr.size < irlengthpad * sizeof(MYFLT)) csound->AuxAlloc(csound, irlengthpad * sizeof(MYFLT), &p->hrtfr); if (!p->olhrtfl.auxp || p->olhrtfl.size < overlapsize * sizeof(MYFLT)) csound->AuxAlloc(csound, overlapsize * sizeof(MYFLT), &p->olhrtfl); if (!p->olhrtfr.auxp || p->olhrtfr.size < overlapsize * sizeof(MYFLT)) csound->AuxAlloc(csound, overlapsize * sizeof(MYFLT), &p->olhrtfr); memset(p->matrixlu.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->matrixrv.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->olmatrixlu.auxp, 0, overlapsize * sizeof(MYFLT)); memset(p->olmatrixrv.auxp, 0, overlapsize * sizeof(MYFLT)); memset(p->hrtfl.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->hrtfr.auxp, 0, irlengthpad * sizeof(MYFLT)); memset(p->olhrtfl.auxp, 0, overlapsize * sizeof(MYFLT)); memset(p->olhrtfr.auxp, 0, overlapsize * sizeof(MYFLT)); if (!p->buffl.auxp || p->buffl.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->buffl); if (!p->buffr.auxp || p->buffr.size < irlength * sizeof(MYFLT)) csound->AuxAlloc(csound, irlength * sizeof(MYFLT), &p->buffr); memset(p->buffl.auxp, 0, irlength * sizeof(MYFLT)); memset(p->buffr.auxp, 0, irlength * sizeof(MYFLT)); /* buffers to store hrtf data */ bufflp = (MYFLT *)p->buffl.auxp; buffrp = (MYFLT *)p->buffr.auxp; /* 0 delay iterators */ p->u = p->v = p->w = p->x = p->y = p->z = 0; p->ut = p->vt = p->wt = p->xt = p->yt = p->zt = 0; p->utf1 = p->vtf1 = p->wtf1 = p->xtf1 = p->ytf1 = p->ztf1 = 0; p->utf2 = p->vtf2 = p->wtf2 = p->xtf2 = p->ytf2 = p->ztf2 = 0; /* calculate delayline lengths */ meanfporder = meanfp * (order + 1); meanfpsamps = (int)(meanfp * sr); meanfpordersamps = (int)(meanfporder * sr); /* setup reverb time */ delaytime = rt60low > rt60high ? rt60low : rt60high; /* in samples */ delaytime *= sr; /* schroeder suggests 0.15 modes per Hz, so M should be > 0.15 t60 */ delaytime /= 7; /* which no. of delay lines implies ave delay nearest to mfp(which is an appropriate ave)? */ Msix = abs((int)(delaytime / 6) - meanfpsamps); Mtwelve = abs((int)(delaytime / 12) - meanfpsamps); Mtwentyfour = abs((int)(delaytime / 24) - meanfpsamps); M = Mtwelve < Mtwentyfour ? (Msix < Mtwelve ? 6 : 12) : 24; csound->Message(csound, "%d \n", M); delaytime /= M; delaytimeint = (int)delaytime; if(delaytimeint < meanfpsamps) delaytimeint = meanfpsamps; /*csound->Message(csound, "%d %d %d \n", M, delaytimeint, meanfpsamps);*/ /* maximum value, according to primes array and delay line allocation */ if(delaytimeint > 10112) delaytimeint = 10112; /* minimum values, according to primes array and delay line allocation */ if(M==6) { if(delaytimeint < 164) delaytimeint = 164; } else if(M==12) { if(delaytimeint < 374) delaytimeint = 374; } else if(M==24) { if(delaytimeint < 410) delaytimeint = 410; } /* allocate memory based on M: number of delays */ if (!p->delays.auxp || p->delays.size < M * sizeof(int)) csound->AuxAlloc(csound, M * sizeof(int), &p->delays); if (!p->gi.auxp || p->gi.size < M * sizeof(MYFLT)) csound->AuxAlloc(csound, M * sizeof(MYFLT), &p->gi); if (!p->ai.auxp || p->ai.size < M * sizeof(MYFLT)) csound->AuxAlloc(csound, M * sizeof(MYFLT), &p->ai); if (!p->inmat.auxp || p->inmat.size < M * sizeof(MYFLT)) csound->AuxAlloc(csound, M * sizeof(MYFLT), &p->inmat); if (!p->inmatlp.auxp || p->inmatlp.size < M * sizeof(MYFLT)) csound->AuxAlloc(csound, M * sizeof(MYFLT), &p->inmatlp); if (!p->dellp.auxp || p->dellp.size < M * sizeof(MYFLT)) csound->AuxAlloc(csound, M * sizeof(MYFLT), &p->dellp); if (!p->outmat.auxp || p->outmat.size < M * sizeof(MYFLT)) csound->AuxAlloc(csound, M * sizeof(MYFLT), &p->outmat); memset(p->delays.auxp, 0, M * sizeof(int)); memset(p->gi.auxp, 0, M * sizeof(MYFLT)); memset(p->ai.auxp, 0, M * sizeof(MYFLT)); memset(p->inmat.auxp, 0, M * sizeof(MYFLT)); memset(p->inmatlp.auxp, 0, M * sizeof(MYFLT)); memset(p->dellp.auxp, 0, M * sizeof(MYFLT)); memset(p->outmat.auxp, 0, M * sizeof(MYFLT)); /* choose appropriate base delay times */ for(i = 0; i < 212; i++) { if(M == 6) test = (i > 6 ? i : 6) - 6; else if(M == 12) test = (i > 15 ? i : 15) - 15; else test = (i > 16 ? i : 16) - 16; if(primes[i] > delaytimeint || primes[test] > meanfpordersamps) { basedelay = i - 1; if(primes[test] > meanfpordersamps) csound->Message(csound, Str("\nfdn delay > earlies del..., fixed!")); *p->idel = (meanfpordersamps - primes[test - 1]) / sr; break; } } delaysp = (int *)p->delays.auxp; /* fill delay data, note this data can be filled locally */ delaysp[0] = primes[basedelay]; delaysp[1] = primes[basedelay + 3]; delaysp[2] = primes[basedelay - 3]; delaysp[3] = primes[basedelay + 6]; delaysp[4] = primes[basedelay - 6]; delaysp[5] = primes[basedelay + 9]; if(M ==12 || M==24) { delaysp[6] = primes[basedelay - 9]; delaysp[7] = primes[basedelay + 12]; delaysp[8] = primes[basedelay - 12]; delaysp[9] = primes[basedelay + 15]; delaysp[10] = primes[basedelay - 15]; delaysp[11] = primes[basedelay + 18]; } if(M ==24) { /* fill in gaps... */ delaysp[12] = primes[basedelay + 1]; delaysp[13] = primes[basedelay - 1]; delaysp[14] = primes[basedelay + 4]; delaysp[15] = primes[basedelay - 4]; delaysp[16] = primes[basedelay + 7]; delaysp[17] = primes[basedelay - 7]; delaysp[18] = primes[basedelay + 10]; delaysp[19] = primes[basedelay - 10]; delaysp[20] = primes[basedelay + 13]; delaysp[21] = primes[basedelay - 13]; delaysp[22] = primes[basedelay + 16]; delaysp[23] = primes[basedelay - 16]; } /* setup and zero delay lines */ if (!p->del1.auxp || p->del1.size < delaysp[0] * sizeof(MYFLT)) csound->AuxAlloc(csound, delaysp[0] * sizeof(MYFLT), &p->del1); if (!p->del2.auxp || p->del2.size < delaysp[1] * sizeof(MYFLT)) csound->AuxAlloc(csound, delaysp[1] * sizeof(MYFLT), &p->del2); if (!p->del3.auxp || p->del3.size < delaysp[2] * sizeof(MYFLT)) csound->AuxAlloc(csound, delaysp[2] * sizeof(MYFLT), &p->del3); if (!p->del4.auxp || p->del4.size < delaysp[3] * sizeof(MYFLT)) csound->AuxAlloc(csound, delaysp[3] * sizeof(MYFLT), &p->del4); if (!p->del5.auxp || p->del5.size < delaysp[4] * sizeof(MYFLT)) csound->AuxAlloc(csound, delaysp[4] * sizeof(MYFLT), &p->del5); if (!p->del6.auxp || p->del6.size < delaysp[5] * sizeof(MYFLT)) csound->AuxAlloc(csound, delaysp[5] * sizeof(MYFLT), &p->del6); memset(p->del1.auxp, 0, delaysp[0] * sizeof(MYFLT)); memset(p->del2.auxp, 0, delaysp[1] * sizeof(MYFLT)); memset(p->del3.auxp, 0, delaysp[2] * sizeof(MYFLT)); memset(p->del4.auxp, 0, delaysp[3] * sizeof(MYFLT)); memset(p->del5.auxp, 0, delaysp[4] * sizeof(MYFLT)); memset(p->del6.auxp, 0, delaysp[5] * sizeof(MYFLT)); /* if 12 delay lines required */ if(M == 12 || M==24) { if (!p->del1t.auxp || p->del1t.size < delaysp[6] * sizeof(MYFLT)) csound->AuxAlloc(csound, delaysp[6] * sizeof(MYFLT), &p->del1t); if (!p->del2t.auxp || p->del2t.size < delaysp[7] * sizeof(MYFLT)) csound->AuxAlloc(csound, delaysp[7] * sizeof(MYFLT), &p->del2t); if (!p->del3t.auxp || p->del3t.size < delaysp[8] * sizeof(MYFLT)) csound->AuxAlloc(csound, delaysp[8] * sizeof(MYFLT), &p->del3t); if (!p->del4t.auxp || p->del4t.size < delaysp[9] * sizeof(MYFLT)) csound->AuxAlloc(csound, delaysp[9] * sizeof(MYFLT), &p->del4t); if (!p->del5t.auxp || p->del5t.size < delaysp[10] * sizeof(MYFLT)) csound->AuxAlloc(csound, delaysp[10] * sizeof(MYFLT), &p->del5t); if (!p->del6t.auxp || p->del6t.size < delaysp[11] * sizeof(MYFLT)) csound->AuxAlloc(csound, delaysp[11] * sizeof(MYFLT), &p->del6t); memset(p->del1t.auxp, 0, delaysp[6] * sizeof(MYFLT)); memset(p->del2t.auxp, 0, delaysp[7] * sizeof(MYFLT)); memset(p->del3t.auxp, 0, delaysp[8] * sizeof(MYFLT)); memset(p->del4t.auxp, 0, delaysp[9] * sizeof(MYFLT)); memset(p->del5t.auxp, 0, delaysp[10] * sizeof(MYFLT)); memset(p->del6t.auxp, 0, delaysp[11] * sizeof(MYFLT)); } if(M==24) { if (!p->del1tf.auxp || p->del1tf.size < delaysp[12] * sizeof(MYFLT)) csound->AuxAlloc(csound, delaysp[12] * sizeof(MYFLT), &p->del1tf); if (!p->del2tf.auxp || p->del2tf.size < delaysp[13] * sizeof(MYFLT)) csound->AuxAlloc(csound, delaysp[13] * sizeof(MYFLT), &p->del2tf); if (!p->del3tf.auxp || p->del3tf.size < delaysp[14] * sizeof(MYFLT)) csound->AuxAlloc(csound, delaysp[14] * sizeof(MYFLT), &p->del3tf); if (!p->del4tf.auxp || p->del4tf.size < delaysp[15] * sizeof(MYFLT)) csound->AuxAlloc(csound, delaysp[15] * sizeof(MYFLT), &p->del4tf); if (!p->del5tf.auxp || p->del5tf.size < delaysp[16] * sizeof(MYFLT)) csound->AuxAlloc(csound, delaysp[16] * sizeof(MYFLT), &p->del5tf); if (!p->del6tf.auxp || p->del6tf.size < delaysp[17] * sizeof(MYFLT)) csound->AuxAlloc(csound, delaysp[17] * sizeof(MYFLT), &p->del6tf); if (!p->del7tf.auxp || p->del7tf.size < delaysp[18] * sizeof(MYFLT)) csound->AuxAlloc(csound, delaysp[18] * sizeof(MYFLT), &p->del7tf); if (!p->del8tf.auxp || p->del8tf.size < delaysp[19] * sizeof(MYFLT)) csound->AuxAlloc(csound, delaysp[19] * sizeof(MYFLT), &p->del8tf); if (!p->del9tf.auxp || p->del9tf.size < delaysp[20] * sizeof(MYFLT)) csound->AuxAlloc(csound, delaysp[20] * sizeof(MYFLT), &p->del9tf); if (!p->del10tf.auxp || p->del10tf.size < delaysp[21] * sizeof(MYFLT)) csound->AuxAlloc(csound, delaysp[21] * sizeof(MYFLT), &p->del10tf); if (!p->del11tf.auxp || p->del11tf.size < delaysp[22] * sizeof(MYFLT)) csound->AuxAlloc(csound, delaysp[22] * sizeof(MYFLT), &p->del11tf); if (!p->del12tf.auxp || p->del12tf.size < delaysp[23] * sizeof(MYFLT)) csound->AuxAlloc(csound, delaysp[23] * sizeof(MYFLT), &p->del12tf); memset(p->del1tf.auxp, 0, delaysp[12] * sizeof(MYFLT)); memset(p->del2tf.auxp, 0, delaysp[13] * sizeof(MYFLT)); memset(p->del3tf.auxp, 0, delaysp[14] * sizeof(MYFLT)); memset(p->del4tf.auxp, 0, delaysp[15] * sizeof(MYFLT)); memset(p->del5tf.auxp, 0, delaysp[16] * sizeof(MYFLT)); memset(p->del6tf.auxp, 0, delaysp[17] * sizeof(MYFLT)); memset(p->del7tf.auxp, 0, delaysp[18] * sizeof(MYFLT)); memset(p->del8tf.auxp, 0, delaysp[19] * sizeof(MYFLT)); memset(p->del9tf.auxp, 0, delaysp[20] * sizeof(MYFLT)); memset(p->del10tf.auxp, 0, delaysp[21] * sizeof(MYFLT)); memset(p->del11tf.auxp, 0, delaysp[22] * sizeof(MYFLT)); memset(p->del12tf.auxp, 0, delaysp[23] * sizeof(MYFLT)); } powerp = (MYFLT *)p->power.auxp; HRTFavep = (MYFLT *)p->HRTFave.auxp; nump = (MYFLT *)p->num.auxp; denomp = (MYFLT *)p->denom.auxp; cohermagsp = (MYFLT *)p->cohermags.auxp; coherup = (MYFLT *)p->coheru.auxp; cohervp = (MYFLT *)p->coherv.auxp; /* usually, just go through all files; in this case, just doubled due to symmetry (with exceptions, as below) */ for(i = 0; i < 368; i ++) { /* if at a measurement where no doubling for symmetry necessary... */ if(i == 0 || i == 28 || i == 29 || i == 59 || i == 60 || i == 96 || i == 97 || i == 133 || i == 134 || i == 170 || i == 171 || i == 207 || i == 208 || i == 244 || i == 245 || i == 275 || i == 276 || i == 304 || i == 305 || i == 328 || i == 346 || i == 347 || i == 359 || i == 360 || i == 366 || i == 367) skipdouble = 1; else skipdouble = 0; for(j = 0; j < irlength; j ++) { bufflp[j] = fpindexl[skip + j]; buffrp[j] = fpindexr[skip + j]; } /* deal with 0 hz and nyq: may be a negative real val, no need for fabs() as squaring anyway! */ /* skipdouble: l = r */ if(skipdouble) { powerp[0] = powerp[0] + SQUARE(bufflp[0]); powerp[1] = powerp[1] + SQUARE(bufflp[1]); } /* include both */ else { powerp[0] = powerp[0] + SQUARE(bufflp[0]) + SQUARE(buffrp[0]); powerp[1] = powerp[1] + SQUARE(bufflp[1]) + SQUARE(buffrp[1]); } for(j = 2; j < irlength; j += 2) { if(skipdouble) powerp[j] = powerp[j] + (MYFLT)SQUARE(bufflp[j]); else powerp[j] = powerp[j] + (MYFLT)SQUARE(bufflp[j]) + (MYFLT)SQUARE(buffrp[j]); powerp[j + 1] = FL(0.0); } skip += irlength; } for(i = 0; i < irlength; i++) HRTFavep[i] = SQRT(powerp[i] / FL(710.0)); fpindexl = (float *)fpl->beginp; fpindexr = (float *)fpr->beginp; skip = 0; /* coherence values */ for(i = 0; i< 368; i++) { /* if at a measurement where no doubling for symmetry necessary... */ if(i == 0 || i == 28 || i == 29 || i == 59 || i == 60 || i == 96 || i == 97 || i == 133 || i == 134 || i == 170 || i == 171 || i == 207 || i == 208 || i == 244 || i == 245 || i == 275 || i == 276 || i == 304 || i == 305 || i == 328 || i == 346 || i == 347 || i == 359 || i == 360 || i == 366 || i == 367) skipdouble = 1; else skipdouble = 0; for(j = 0; j < irlength; j ++) { bufflp[j] = fpindexl[skip + j]; buffrp[j] = fpindexr[skip + j]; } /* back to rectangular to find numerator: need complex nos */ /* 0Hz and Nyq ok as real */ if(skipdouble) { nump[0] = nump[0] + (bufflp[0] * buffrp[0]); nump[1] = nump[1] + (bufflp[1] * buffrp[1]); } else { nump[0] = nump[0] + (bufflp[0] * buffrp[0]) + (buffrp[0] * bufflp[0]); nump[1] = nump[1] + (bufflp[1] * buffrp[1]) + (buffrp[1] * bufflp[1]); } /* complex multiplication */ /* (a + i b)(c + i d) */ /* = (a c - b d) + i(a d + b c) */ /* conjugate: d becomes -d -> = (a c + b d) + i(- a d + b c) */ /* doing l * conj r and r * conj l here, as dataset symmetrical... for non symmetrical, just go through all and do l * conj r */ for(j = 2; j < irlength; j += 2) { rel = bufflp[j] * COS(bufflp[j + 1]); iml = bufflp[j] * SIN(bufflp[j + 1]); rer = buffrp[j] * COS(buffrp[j + 1]); imr = buffrp[j] * SIN(buffrp[j + 1]); if(skipdouble) { nump[j] = nump[j] + ((rel * rer) + (iml * imr)); nump[j + 1] = nump[j + 1] + ((rel * -imr) + (iml * rer)); } else { nump[j] = nump[j] + ((rel * rer) + (iml * imr)) + ((rer * rel) + (imr * iml)); nump[j + 1] = nump[j + 1] + ((rel * -imr) + (iml * rer)) + ((rer * -iml) + (imr * rel)); } } skip += irlength; } /* 0 & nyq = fabs() for mag... */ nump[0] = FABS(nump[0]); nump[1] = FABS(nump[1]); /* magnitudes of sum of conjugates */ for(i = 2; i < irlength; i += 2) { retemp = nump[i]; imtemp = nump[i + 1]; nump[i] = SQRT(SQUARE(retemp) + SQUARE(imtemp)); nump[i + 1] = FL(0.0); } /* sqrt (powl * powr) powl = powr in symmetric case, so just power[] needed */ for(i = 0; i < irlength; i++) denomp[i] = powerp[i]; /* coherence values */ cohermagsp[0] = nump[0] / denomp[0]; cohermagsp[1] = nump[1] / denomp[1]; for(i = 2; i < irlength; i += 2) { cohermagsp[i] = nump[i] / denomp[i]; cohermagsp[i+1] = FL(0.0); } /* coherence formula */ coherup[0] = SQRT((FL(1.0) + cohermagsp[0]) / FL(2.0)); coherup[1] = SQRT((FL(1.0) + cohermagsp[1]) / FL(2.0)); cohervp[0] = SQRT((FL(1.0) - cohermagsp[0]) / FL(2.0)); cohervp[1] = SQRT((FL(1.0) - cohermagsp[1]) / FL(2.0)); for(i = 2; i < irlength; i += 2) { coherup[i] = SQRT((FL(1.0) + cohermagsp[i]) / FL(2.0)); cohervp[i] = SQRT((FL(1.0) - cohermagsp[i]) / FL(2.0)); coherup[i + 1] = FL(0.0); cohervp[i + 1] = FL(0.0); } /* no need to go back to rectangular for fft, as phase = 0, so same */ csound->InverseRealFFT(csound, HRTFavep, irlength); csound->InverseRealFFT(csound, coherup, irlength); csound->InverseRealFFT(csound, cohervp, irlength); filtoutp = (MYFLT *)p->filtout.auxp; filtuoutp = (MYFLT *)p->filtuout.auxp; filtvoutp = (MYFLT *)p->filtvout.auxp; filtpadp = (MYFLT *)p->filtpad.auxp; filtupadp = (MYFLT *)p->filtupad.auxp; filtvpadp = (MYFLT *)p->filtvpad.auxp; /* shift */ for(i = 0; i < irlength; i++) { filtoutp[i] = HRTFavep[(i + (irlength / 2)) % irlength]; filtuoutp[i] = coherup[(i + (irlength / 2)) % irlength]; filtvoutp[i] = cohervp[(i + (irlength / 2)) % irlength]; } for(i = 0; i < irlength; i++) { filtpadp[i] = filtoutp[i]; filtupadp[i] = filtuoutp[i]; filtvpadp[i] = filtvoutp[i]; } for(i = irlength; i < irlengthpad; i++) { filtpadp[i] = FL(0.0); filtupadp[i] = FL(0.0); filtvpadp[i] = FL(0.0); } csound->RealFFT(csound, filtpadp, irlengthpad); csound->RealFFT(csound, filtupadp, irlengthpad); csound->RealFFT(csound, filtvpadp, irlengthpad); T = FL(1.0) / sr; gip = (MYFLT *)p->gi.auxp; aip = (MYFLT *)p->ai.auxp; do { double alphsq; alpha = rt60high / rt60low; clipcheck = 0; alphsq = SQUARE(alpha); p->b = (FL(1.0) - alpha) / (FL(1.0) + alpha); aconst = (LOG(FL(10.0)) / FL(4.0)) * (FL(1.0) - (FL(1.0) / alphsq)); for(i = 0; i < M; i++) { exp = (-FL(3.0) * delaysp[i] * T) / rt60low; gip[i] = POWER(FL(10.0), exp); aip[i] = exp * aconst; if(aip[i] > FL(0.99) || aip[i] < -FL(0.99)) { csound->Message(csound, Str("\nwarning, approaching instability, " "fixed with a flat late reverb!")); clipcheck = 1; if(aip[i] > 0.99) rt60high = rt60low; else rt60low = rt60high; break; } } }while(clipcheck); /* initialise counter and filter delays */ p->counter = 0; p->inoldl = 0; p->inoldr = 0; p->M = M; return OK; } int hrtfreverb_process(CSOUND *csound, hrtfreverb *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; int j, k; /* signals in, out */ MYFLT *in = p->insig, sigin; MYFLT *outl = p->outsigl; MYFLT *outr = p->outsigr; /* pointers to delay data */ MYFLT *del1p, *del2p, *del3p, *del4p, *del5p, *del6p; MYFLT *del1tp=NULL, *del2tp=NULL, *del3tp=NULL, *del4tp=NULL, *del5tp=NULL, *del6tp=NULL; MYFLT *del1tfp=NULL, *del2tfp=NULL, *del3tfp=NULL, *del4tfp=NULL, *del5tfp=NULL, *del6tfp=NULL, *del7tfp=NULL, *del8tfp=NULL, *del9tfp=NULL, *del10tfp=NULL, *del11tfp=NULL, *del12tfp=NULL; int *delaysp; /* matrix manipulation */ MYFLT *inmatp, *inmatlpp, *dellpp, *outmatp; /* delay line iterators */ int u, v, w, x, y, z; int ut=0, vt=0, wt=0, xt=0, yt=0, zt=0; int utf1=0, vtf1=0, wtf1=0, xtf1=0, ytf1=0, ztf1=0; int utf2=0, vtf2=0, wtf2=0, xtf2=0, ytf2=0, ztf2=0; /* number of delays */ int M = p->M; /* FIR temp variables */ MYFLT tonall, tonalr; MYFLT b = p->b; /* IIR variables */ MYFLT *gip, *aip; /* counter */ int counter = p->counter; /* matrix/coher and hrtf filter buffers, with overlap add buffers */ MYFLT *matrixlup = (MYFLT *)p->matrixlu.auxp; MYFLT *matrixrvp = (MYFLT *)p->matrixrv.auxp; MYFLT *olmatrixlup = (MYFLT *)p->olmatrixlu.auxp; MYFLT *olmatrixrvp = (MYFLT *)p->olmatrixrv.auxp; MYFLT *hrtflp = (MYFLT *)p->hrtfl.auxp; MYFLT *hrtfrp = (MYFLT *)p->hrtfr.auxp; MYFLT *olhrtflp = (MYFLT *)p->olhrtfl.auxp; MYFLT *olhrtfrp = (MYFLT *)p->olhrtfr.auxp; /* processing lengths */ int irlength = p->irlength; int irlengthpad = p->irlengthpad; int overlapsize = p->overlapsize; /* 1st order FIR mem */ MYFLT inoldl = p->inoldl; MYFLT inoldr = p->inoldr; /* filters, created in INIT */ MYFLT *filtpadp = (MYFLT *)p->filtpad.auxp; MYFLT *filtupadp = (MYFLT *)p->filtupad.auxp; MYFLT *filtvpadp = (MYFLT *)p->filtvpad.auxp; MYFLT sr = p->sr; del1p = (MYFLT *)p->del1.auxp; del2p = (MYFLT *)p->del2.auxp; del3p = (MYFLT *)p->del3.auxp; del4p = (MYFLT *)p->del4.auxp; del5p = (MYFLT *)p->del5.auxp; del6p = (MYFLT *)p->del6.auxp; if(M==12 || M==24) { del1tp = (MYFLT *)p->del1t.auxp; del2tp = (MYFLT *)p->del2t.auxp; del3tp = (MYFLT *)p->del3t.auxp; del4tp = (MYFLT *)p->del4t.auxp; del5tp = (MYFLT *)p->del5t.auxp; del6tp = (MYFLT *)p->del6t.auxp; } if(M==24) { del1tfp = (MYFLT *)p->del1tf.auxp; del2tfp = (MYFLT *)p->del2tf.auxp; del3tfp = (MYFLT *)p->del3tf.auxp; del4tfp = (MYFLT *)p->del4tf.auxp; del5tfp = (MYFLT *)p->del5tf.auxp; del6tfp = (MYFLT *)p->del6tf.auxp; del7tfp = (MYFLT *)p->del7tf.auxp; del8tfp = (MYFLT *)p->del8tf.auxp; del9tfp = (MYFLT *)p->del9tf.auxp; del10tfp = (MYFLT *)p->del10tf.auxp; del11tfp = (MYFLT *)p->del11tf.auxp; del12tfp = (MYFLT *)p->del12tf.auxp; } delaysp = (int *)p->delays.auxp; inmatp = (MYFLT *)p->inmat.auxp; inmatlpp = (MYFLT *)p->inmatlp.auxp; dellpp = (MYFLT *)p->dellp.auxp; outmatp = (MYFLT *)p->outmat.auxp; gip = (MYFLT *)p->gi.auxp; aip = (MYFLT *)p->ai.auxp; /* point to structure */ u = p->u; v = p->v; w = p->w; x = p->x; y = p->y; z = p->z; if(M==12 || M==24) { ut = p->ut; vt = p->vt; wt = p->wt; xt = p->xt; yt = p->yt; zt = p->zt; } /* else { */ /* printf("Should not get here\n"); */ /* ut = vt = wt = xt = yt = zt = 0; */ /* } */ if(M==24) { utf1 = p->utf1; vtf1 = p->vtf1; wtf1 = p->wtf1; xtf1 = p->xtf1; ytf1 = p->ytf1; ztf1 = p->ztf1; utf2 = p->utf2; vtf2 = p->vtf2; wtf2 = p->wtf2; xtf2 = p->xtf2; ytf2 = p->ytf2; ztf2 = p->ztf2; } if (UNLIKELY(offset)) { memset(outl, '\0', offset*sizeof(MYFLT)); memset(outr, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&outl[nsmps], '\0', early*sizeof(MYFLT)); memset(&outr[nsmps], '\0', early*sizeof(MYFLT)); } /* processing loop */ for(i=offset; i < nsmps; i++) { /* tonal filter: 1 - b pow(z,-1) / 1 - b 1/1-b in - b/1-b in(old) */ /* dot product of l and r = 0 for uncorrelated */ tonall = (del1p[u] - del2p[v] + del3p[w] - del4p[x] + del5p[y] - del6p[z]); if(M==12 || M==24) tonall += (del1tp[ut] - del2tp[vt] + del3tp[wt] - del4tp[xt] + del5tp[yt] - del6tp[zt]); if(M==24) tonall += (del1tfp[utf1] - del2tfp[vtf1] + del3tfp[wtf1] - del4tfp[xtf1] + del5tfp[ytf1] - del6tfp[ztf1] + del7tfp[utf2] - del8tfp[vtf2] + del9tfp[wtf2] - del10tfp[xtf2] + del11tfp[ytf2] - del12tfp[ztf2]); matrixlup[counter] = (((FL(1.0) / (FL(1.0) - b)) * tonall) - ((b / (FL(1.0) - b)) * inoldl)); matrixlup[counter] /= M; inoldl = tonall; tonalr = (del1p[u] + del2p[v] + del3p[w] + del4p[x] + del5p[y] + del6p[z]); if(M==12 || M==24) tonalr += (del1tp[ut] + del2tp[vt] + del3tp[wt] + del4tp[xt] + del5tp[yt] + del6tp[zt]); if(M==24) tonalr += (del1tfp[utf1] - del2tfp[vtf1] + del3tfp[wtf1] - del4tfp[xtf1] + del5tfp[ytf1] - del6tfp[ztf1] + del7tfp[utf2] - del8tfp[vtf2] + del9tfp[wtf2] - del10tfp[xtf2] + del11tfp[ytf2] - del12tfp[ztf2]); matrixrvp[counter] = (((FL(1.0) / (FL(1.0) - b)) * tonalr) - ((b / (FL(1.0) - b)) * inoldr)); matrixrvp[counter] /= M; inoldr = tonalr; /* inputs from del lines (need more for larger fdn) */ inmatp[0] = del1p[u]; inmatp[1] = del2p[v]; inmatp[2] = del3p[w]; inmatp[3] = del4p[x]; inmatp[4] = del5p[y]; inmatp[5] = del6p[z]; if(M==12 || M==24) { inmatp[6] = del1tp[ut]; inmatp[7] = del2tp[vt]; inmatp[8] = del3tp[wt]; inmatp[9] = del4tp[xt]; inmatp[10] = del5tp[yt]; inmatp[11] = del6tp[zt]; } if(M==24) { inmatp[12] = del1tfp[utf1]; inmatp[13] = del2tfp[vtf1]; inmatp[14] = del3tfp[wtf1]; inmatp[15] = del4tfp[xtf1]; inmatp[16] = del5tfp[ytf1]; inmatp[17] = del6tfp[ztf1]; inmatp[18] = del7tfp[utf2]; inmatp[19] = del8tfp[vtf2]; inmatp[20] = del9tfp[wtf2]; inmatp[21] = del10tfp[xtf2]; inmatp[22] = del11tfp[ytf2]; inmatp[23] = del12tfp[ztf2]; } /* low pass each filter: gi ( 1 - ai / 1 - ai pow(z,-1) op = gi - gi ai x(n) + ai del del = op */ for(j = 0; j < M; j++) { inmatlpp[j] = (gip[j] * (1 - aip[j]) * inmatp[j]) + (aip[j] * dellpp[j]); dellpp[j] = inmatlpp[j]; } /* matrix mult: multiplying a vector by a matrix: embedded householders cause stability issues, as reported by Murphy...*/ for(j = 0; j < M; j++) { outmatp[j] = FL(0.0); for(k = 0; k < M; k++) { if(M==24) outmatp[j] += (matrix24[j * M + k] * inmatlpp[k]); else if(M==12) outmatp[j] += (matrix12[j * M + k] * inmatlpp[k]); else outmatp[j] += (matrix6[j * M + k] * inmatlpp[k]); } } sigin = in[i] * (FL(32767.0) / csound->e0dbfs); del1p[u] = outmatp[0] + sigin; del2p[v] = outmatp[1] + sigin; del3p[w] = outmatp[2] + sigin; del4p[x] = outmatp[3] + sigin; del5p[y] = outmatp[4] + sigin; del6p[z] = outmatp[5] + sigin; if(M == 12 || M == 24) { del1tp[ut] = outmatp[6] + sigin; del2tp[vt] = outmatp[7] + sigin; del3tp[wt] = outmatp[8] + sigin; del4tp[xt] = outmatp[9] + sigin; del5tp[yt] = outmatp[10] + sigin; del6tp[zt] = outmatp[11] + sigin; } if(M == 24) { del1tfp[utf1] = outmatp[12] + sigin; del2tfp[vtf1] = outmatp[13] + sigin; del3tfp[wtf1] = outmatp[14] + sigin; del4tfp[xtf1] = outmatp[15] + sigin; del5tfp[ytf1] = outmatp[16] + sigin; del6tfp[ztf1] = outmatp[17] + sigin; del7tfp[utf2] = outmatp[18] + sigin; del8tfp[vtf2] = outmatp[19] + sigin; del9tfp[wtf2] = outmatp[20] + sigin; del10tfp[xtf2] = outmatp[21] + sigin; del11tfp[ytf2] = outmatp[22] + sigin; del12tfp[ztf2] = outmatp[23] + sigin; } u = (u != delaysp[0] - 1 ? u + 1 : 0); v = (v != delaysp[1] - 1 ? v + 1 : 0); w = (w != delaysp[2] - 1 ? w + 1 : 0); x = (x != delaysp[3] - 1 ? x + 1 : 0); y = (y != delaysp[4] - 1 ? y + 1 : 0); z = (z != delaysp[5] - 1 ? z + 1 : 0); if(M == 12 || M == 24) { ut = (ut != delaysp[6] - 1 ? ut + 1 : 0); vt = (vt != delaysp[7] - 1 ? vt + 1 : 0); wt = (wt != delaysp[8] - 1 ? wt + 1 : 0); xt = (xt != delaysp[9] - 1 ? xt + 1 : 0); yt = (yt != delaysp[10] - 1 ? yt + 1 : 0); zt = (zt != delaysp[11] - 1 ? zt + 1 : 0); } if(M == 24) { utf1 = (utf1 != delaysp[12] - 1 ? utf1 + 1 : 0); vtf1 = (vtf1 != delaysp[13] - 1 ? vtf1 + 1 : 0); wtf1 = (wtf1 != delaysp[14] - 1 ? wtf1 + 1 : 0); xtf1 = (xtf1 != delaysp[15] - 1 ? xtf1 + 1 : 0); ytf1 = (ytf1 != delaysp[16] - 1 ? ytf1 + 1 : 0); ztf1 = (ztf1 != delaysp[17] - 1 ? ztf1 + 1 : 0); utf2 = (utf2 != delaysp[18] - 1 ? utf2 + 1 : 0); vtf2 = (vtf2 != delaysp[19] - 1 ? vtf2 + 1 : 0); wtf2 = (wtf2 != delaysp[20] - 1 ? wtf2 + 1 : 0); xtf2 = (xtf2 != delaysp[21] - 1 ? xtf2 + 1 : 0); ytf2 = (ytf2 != delaysp[22] - 1 ? ytf2 + 1 : 0); ztf2 = (ztf2 != delaysp[23] - 1 ? ztf2 + 1 : 0); } /* output, increment counter */ // outl[i] = hrtflp[counter]; // outr[i] = hrtfrp[counter]; outl[i] = hrtflp[counter] * (csound->e0dbfs / FL(32767.0)); outr[i] = hrtfrp[counter] * (csound->e0dbfs / FL(32767.0)); counter++; if(counter == irlength) { for(j = irlength; j < irlengthpad; j++) { matrixlup[j] = FL(0.0); matrixrvp[j] = FL(0.0); } /* fft result from matrices */ csound->RealFFT(csound, matrixlup, irlengthpad); csound->RealFFT(csound, matrixrvp, irlengthpad); /* convolution: spectral multiplication */ csound->RealFFTMult(csound, matrixlup, matrixlup, filtupadp, irlengthpad, FL(1.0)); csound->RealFFTMult(csound, matrixrvp, matrixrvp, filtvpadp, irlengthpad, FL(1.0)); /* ifft result */ csound->InverseRealFFT(csound, matrixlup, irlengthpad); csound->InverseRealFFT(csound, matrixrvp, irlengthpad); for(j = 0; j < irlength; j++) { matrixlup[j] = matrixlup[j] + (j < overlapsize ? olmatrixlup[j] : FL(1.0)); matrixrvp[j] = matrixrvp[j] + (j < overlapsize ? olmatrixrvp[j] : FL(1.0)); } /* store overlap for next time */ for(j = 0; j < overlapsize; j++) { olmatrixlup[j] = matrixlup[j + irlength]; olmatrixrvp[j] = matrixrvp[j + irlength]; } /* coherence formula */ for(j = 0; j < irlength; j++) { hrtflp[j] = matrixlup[j] + matrixrvp[j]; hrtfrp[j] = matrixlup[j] - matrixrvp[j]; } for(j = irlength; j < irlengthpad; j++) { hrtflp[j] = FL(0.0); hrtfrp[j] = FL(0.0); } /* fft result from matrices */ csound->RealFFT(csound, hrtflp, irlengthpad); csound->RealFFT(csound, hrtfrp, irlengthpad); /* convolution: spectral multiplication */ csound->RealFFTMult(csound, hrtflp, hrtflp, filtpadp, irlengthpad, FL(1.0)); csound->RealFFTMult(csound, hrtfrp, hrtfrp, filtpadp, irlengthpad, FL(1.0)); /* ifft result */ csound->InverseRealFFT(csound, hrtflp, irlengthpad); csound->InverseRealFFT(csound, hrtfrp, irlengthpad); /* scale */ for(j = 0; j < irlengthpad; j++) { hrtflp[j] = hrtflp[j]/(sr / FL(38000.0)); hrtfrp[j] = hrtfrp[j]/(sr / FL(38000.0)); } for(j = 0; j < irlength; j++) { hrtflp[j] = hrtflp[j] + (j < overlapsize ? olhrtflp[j] : FL(0.0)); hrtfrp[j] = hrtfrp[j] + (j < overlapsize ? olhrtfrp[j] : FL(0.0)); } /* store overlap for next time */ for(j = 0; j < overlapsize; j++) { olhrtflp[j] = hrtflp[j + irlength]; olhrtfrp[j] = hrtfrp[j + irlength]; } counter = 0; } /* end of irlength loop */ } /* end of ksmps loop */ /* keep for next time */ p->counter = counter; p->u = u; p->v = v; p->w = w; p->x = x; p->y = y; p->z = z; if(M == 12 || M == 24) { p->ut = ut; p->vt = vt; p->wt = wt; p->xt = xt; p->yt = yt; p->zt = zt; } if(M == 24) { p->utf1 = utf1; p->vtf1 = vtf1; p->wtf1 = wtf1; p->xtf1 = xtf1; p->ytf1 = ytf1; p->ztf1 = ztf1; p->utf2 = utf2; p->vtf2 = vtf2; p->wtf2 = wtf2; p->xtf2 = xtf2; p->ytf2 = ytf2; p->ztf2 = ztf2; } p->inoldl = inoldl; p->inoldr = inoldr; return OK; } static OENTRY hrtfreverb_localops[] = { { "hrtfreverb", sizeof(hrtfreverb), 0,5, "aai", "aiiSSoop", (SUBR)hrtfreverb_init, NULL, (SUBR)hrtfreverb_process } }; LINKAGE_BUILTIN(hrtfreverb_localops) csound-6.10.0/Opcodes/ifd.c000066400000000000000000000272611321653344700154130ustar00rootroot00000000000000/* ifd.c pvsifd (c) Victor Lazzarini, 2005 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* PVSIFD Instantaneous Frequency Distribution analysis, plus magnitude and phase output. ffrs, fphs pvsifd ain, ifftsize, ihopsize, iwintype[,iscal] ffrs - AMP_FREQ signal fphs - AMP_PHASE signal (unwrapped phase) ain - input ifftsize - fftsize (must be integer multiple of hopsize) ihopsize - hopsize iwintype - O:hamming; 1: hanning, iscal - magnitude scaling (defaults to 0) */ #include "pvs_ops.h" #include "pstream.h" typedef struct _ifd { OPDS h; /* outputs */ PVSDAT *fout1, *fout2; /* inputs */ MYFLT *in, *p2, *p3, *p4, *p5, *p6, *p7; /* data */ AUXCH sigframe, diffsig, win, diffwin; AUXCH counter; int fftsize, hopsize, wintype, frames, cnt; double fund, factor; MYFLT norm, g; void *setup; } IFD; static int ifd_init(CSOUND * csound, IFD * p) { int fftsize, hopsize, frames; int *counter, wintype, i; MYFLT *winf, *dwinf; double alpha = 0.0, fac; //p->cnt = 0; fftsize = p->fftsize = (int) *p->p2; hopsize = p->hopsize = (int) *p->p3; p->g = *p->p5; wintype = p->wintype = (int) *p->p4; frames = fftsize / hopsize; if (UNLIKELY((frames - (float) fftsize / hopsize) != 0.0f)) return csound->InitError(csound, Str("pvsifd: fftsize should " "be an integral multiple of hopsize")); if (UNLIKELY((fftsize & (fftsize - 1)))) return csound->InitError(csound, Str("pvsifd: fftsize should be power-of-two")); p->frames = frames; if (p->sigframe.auxp == NULL || frames * fftsize * sizeof(MYFLT) > (unsigned int) p->sigframe.size) csound->AuxAlloc(csound, frames * fftsize * sizeof(MYFLT), &p->sigframe); else memset(p->sigframe.auxp, 0, sizeof(MYFLT) * fftsize * frames); if (p->diffsig.auxp == NULL || fftsize * sizeof(MYFLT) > (unsigned int) p->diffsig.size) csound->AuxAlloc(csound, fftsize * sizeof(MYFLT), &p->diffsig); else memset(p->diffsig.auxp, 0, sizeof(MYFLT) * fftsize); if (p->diffwin.auxp == NULL || fftsize * sizeof(MYFLT) > (unsigned int) p->diffwin.size) csound->AuxAlloc(csound, fftsize * sizeof(MYFLT), &p->diffwin); if (p->win.auxp == NULL || fftsize * sizeof(MYFLT) > (unsigned int) p->win.size) csound->AuxAlloc(csound, fftsize * sizeof(MYFLT), &p->win); if (p->counter.auxp == NULL || frames * sizeof(int) > (unsigned int) p->counter.size) csound->AuxAlloc(csound, frames * sizeof(int), &p->counter); if (p->fout1->frame.auxp == NULL || (fftsize + 2) * sizeof(MYFLT) > (unsigned int) p->fout1->frame.size) csound->AuxAlloc(csound, (fftsize + 2) * sizeof(float), &p->fout1->frame); else memset(p->fout1->frame.auxp, 0, sizeof(MYFLT) * (fftsize + 2)); if (p->fout2->frame.auxp == NULL || (fftsize + 2) * sizeof(MYFLT) > (unsigned int) p->fout2->frame.size) csound->AuxAlloc(csound, (fftsize + 2) * sizeof(float), &p->fout2->frame); else memset(p->fout2->frame.auxp, 0, sizeof(MYFLT) * (fftsize + 2)); p->fout1->N = fftsize; p->fout1->overlap = hopsize; p->fout1->winsize = fftsize; p->fout1->wintype = wintype; p->fout1->framecount = 1; p->fout1->format = PVS_AMP_FREQ; p->fout2->N = fftsize; p->fout2->overlap = hopsize; p->fout2->winsize = fftsize; p->fout2->wintype = wintype; p->fout2->framecount = 1; p->fout2->format = PVS_AMP_PHASE; counter = (int *) p->counter.auxp; for (i = 0; i < frames; i++) counter[i] = i * hopsize; winf = (MYFLT *) p->win.auxp; dwinf = (MYFLT *) p->diffwin.auxp; switch (wintype) { case PVS_WIN_HAMMING: alpha = 0.54; break; case PVS_WIN_HANN: alpha = 0.5; break; default: return csound->InitError(csound, Str("pvsifd: unsupported value for iwintype\n")); break; } fac = TWOPI / (fftsize - 1.0); for (i = 0; i < fftsize; i++) winf[i] = (MYFLT) (alpha - (1.0 - alpha) * cos(fac * i)); p->norm = 0; for (i = 0; i < fftsize; i++) { dwinf[i] = winf[i] - (i + 1 < fftsize ? winf[i + 1] : FL(0.0)); p->norm += winf[i]; } p->factor = CS_ESR / TWOPI_F; p->fund = CS_ESR / fftsize; p->setup = csound->RealFFT2Setup(csound, fftsize, FFT_FWD); return OK; } static void IFAnalysis(CSOUND * csound, IFD * p, MYFLT * signal) { double powerspec, da, db, a, b, ph, factor = p->factor, fund = p->fund; MYFLT scl = p->g / p->norm; int i2, i, fftsize = p->fftsize, hsize = p->fftsize / 2; MYFLT tmp1, tmp2, *diffwin = (MYFLT *) p->diffwin.auxp; MYFLT *win = (MYFLT *) p->win.auxp; MYFLT *diffsig = (MYFLT *) p->diffsig.auxp; float *output = (float *) p->fout1->frame.auxp; float *outphases = (float *) p->fout2->frame.auxp; for (i = 0; i < fftsize; i++) { diffsig[i] = signal[i] * diffwin[i]; signal[i] = signal[i] * win[i]; } for (i = 0; i < hsize; i++) { tmp1 = diffsig[i + hsize]; tmp2 = diffsig[i]; diffsig[i] = tmp1; diffsig[i + hsize] = tmp2; tmp1 = signal[i + hsize]; tmp2 = signal[i]; signal[i] = tmp1; signal[i + hsize] = tmp2; } csound->RealFFT2(csound, p->setup, signal); csound->RealFFT2(csound, p->setup,diffsig); for (i = 2; i < fftsize; i += 2) { i2 = i / 2; a = signal[i] * scl; b = signal[i + 1] * scl; da = diffsig[i] * scl; db = diffsig[i + 1] * scl; powerspec = a * a + b * b; if ((outphases[i] = output[i] = (float) sqrt(powerspec)) != 0.0f) { output[i + 1] = ((a * db - b * da) / powerspec) * factor + i2 * fund; ph = (float) atan2(b, a); /*double d = ph - outphases[i + 1]; while (d > PI) d -= TWOPI; while (d < -PI) d += TWOPI; */ outphases[i + 1] = (float)ph; } else { output[i + 1] = i2 * fund; outphases[i + 1] = 0.0f; } } output[0] = outphases[0] = signal[0] * scl; output[1] = outphases[1] = outphases[fftsize + 1] = 0.0f; output[fftsize] = outphases[fftsize] = signal[1] * scl; output[fftsize + 1] = CS_ESR * FL(0.5); p->fout1->framecount++; p->fout2->framecount++; } static int ifd_process(CSOUND * csound, IFD * p) { int i; MYFLT *sigin = p->in; MYFLT *sigframe = (MYFLT *) p->sigframe.auxp; int fftsize = p->fftsize; int *counter = (int *) p->counter.auxp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int frames = p->frames; //int cnt = p->cnt; if (UNLIKELY(early)) nsmps -= early; for (n = offset; n < nsmps; n++) { for (i = 0; i < frames; i++) { sigframe[i * fftsize + counter[i]] = sigin[n]; counter[i]++; if (counter[i] == fftsize) { //if (cnt < frames) // cnt++; //else IFAnalysis(csound, p, &sigframe[i * fftsize]); counter[i] = 0; } } } //p->cnt = cnt; return OK; } static int tifd_init(CSOUND * csound, IFD * p) { int fftsize, hopsize; int wintype, i; MYFLT *winf, *dwinf; double alpha = 0.0, fac; fftsize = p->fftsize = (int) *p->p4; hopsize = p->hopsize = (int) *p->p5; wintype = p->wintype = (int) *p->p6; if (UNLIKELY((fftsize & (fftsize - 1)))) return csound->InitError(csound, Str("pvsifd: fftsize should be power-of-two")); if (p->sigframe.auxp == NULL || fftsize * sizeof(MYFLT) > (unsigned int) p->sigframe.size) csound->AuxAlloc(csound, fftsize * sizeof(MYFLT), &p->sigframe); else memset(p->sigframe.auxp, 0, sizeof(MYFLT) * fftsize); if (p->diffsig.auxp == NULL || fftsize * sizeof(MYFLT) > (unsigned int) p->diffsig.size) csound->AuxAlloc(csound, fftsize * sizeof(MYFLT), &p->diffsig); else memset(p->diffsig.auxp, 0, sizeof(MYFLT) * fftsize); if (p->diffwin.auxp == NULL || fftsize * sizeof(MYFLT) > (unsigned int) p->diffwin.size) csound->AuxAlloc(csound, fftsize * sizeof(MYFLT), &p->diffwin); if (p->win.auxp == NULL || fftsize * sizeof(MYFLT) > (unsigned int) p->win.size) csound->AuxAlloc(csound, fftsize * sizeof(MYFLT), &p->win); if (p->fout1->frame.auxp == NULL || (fftsize + 2) * sizeof(MYFLT) > (unsigned int) p->fout1->frame.size) csound->AuxAlloc(csound, (fftsize + 2) * sizeof(float), &p->fout1->frame); else memset(p->fout1->frame.auxp, 0, sizeof(MYFLT) * (fftsize + 2)); if (p->fout2->frame.auxp == NULL || (fftsize + 2) * sizeof(MYFLT) > (unsigned int) p->fout2->frame.size) csound->AuxAlloc(csound, (fftsize + 2) * sizeof(float), &p->fout2->frame); else memset(p->fout2->frame.auxp, 0, sizeof(MYFLT) * (fftsize + 2)); p->fout1->N = fftsize; p->fout1->overlap = hopsize; p->fout1->winsize = fftsize; p->fout1->wintype = wintype; p->fout1->framecount = 1; p->fout1->format = PVS_AMP_FREQ; p->fout2->N = fftsize; p->fout2->overlap = hopsize; p->fout2->winsize = fftsize; p->fout2->wintype = wintype; p->fout2->framecount = 1; p->fout2->format = PVS_AMP_PHASE; winf = (MYFLT *) p->win.auxp; dwinf = (MYFLT *) p->diffwin.auxp; switch (wintype) { case PVS_WIN_HAMMING: alpha = 0.54; break; case PVS_WIN_HANN: alpha = 0.5; break; default: return csound->InitError(csound, Str("pvsifd: unsupported value for iwintype\n")); break; } fac = TWOPI / (fftsize - 1.0); for (i = 0; i < fftsize; i++) winf[i] = (MYFLT) (alpha - (1.0 - alpha) * cos(fac * i)); p->norm = 0; for (i = 0; i < fftsize; i++) { dwinf[i] = winf[i] - (i + 1 < fftsize ? winf[i + 1] : FL(0.0)); p->norm += winf[i]; } p->factor = CS_ESR / TWOPI_F; p->fund = CS_ESR / fftsize; p->cnt = hopsize; return OK; } static int tifd_process(CSOUND * csound, IFD * p) { int hopsize = p->hopsize; uint32_t nsmps = CS_KSMPS; if(p->cnt >= hopsize){ MYFLT pos = *p->in*csound->GetSr(csound); MYFLT *sigframe = (MYFLT *) p->sigframe.auxp; MYFLT pit = *p->p3; int fftsize = p->fftsize; int post; MYFLT frac; FUNC *ft = csound->FTnp2Find(csound,p->p7); if (UNLIKELY(ft == NULL)) { return csound->PerfError(csound, p->h.insdshead, "could not find table number %d\n", (int) *p->p7); } MYFLT *tab = ft->ftable; int i,size = ft->flen; for(i=0; i < fftsize; i++){ MYFLT in; post = (int) pos; frac = pos - post; while (post >= size) post -= size; while (post < 0) post += size; in = tab[post] + frac*(tab[post+1] - tab[post]); sigframe[i] = in; pos += pit; } p->g = *p->p2; IFAnalysis(csound, p, sigframe); p->cnt -= hopsize; } p->cnt += nsmps; return OK; } static OENTRY localops[] = { { "pvsifd", sizeof(IFD), 0, 5, "ff", "aiiip", (SUBR) ifd_init, 0, (SUBR) ifd_process}, { "tabifd", sizeof(IFD), 0, 3, "ff", "kkkiiii", (SUBR) tifd_init, (SUBR) tifd_process} }; int ifd_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/imageOpcodes.c000066400000000000000000000435131321653344700172460ustar00rootroot00000000000000 /** * IMAGE OPCODES * * imageOpcodes.c * * Copyright (c) 2007 by Cesare Marilungo. All rights reserved. * * L I C E N S E * * This software is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * C S O U N D M A N P A G E * * imageload - opens an image (in PNG format) * imagesave - saves an image (in PNG format) * imagecreate - create an empty image * imagesize - gets the size of an image * imagegetpixel - gets the rgb values of a pixel * imagesetpixel - sets the rgb values of a pixel * imagefree - free memory from a previously loaded or created image. * * SYNTAX * * iImageNumber imageload sFilename * * imageSave iImageNumber, sFilename * * iImageNumber imagecreate iWidth, iHeight * * iWidth, iHeight imagesize iImageNumber * * kred, kgreen, kblue imagegetpixel iImageNumber, kX, kY * ared, agreen, ablue imagegetpixel iImageNumber, aX, aY * * imagesetpixel iImageNumber, kX, kY, kred, kgreen, kblue * imagesetpixel iImageNumber, aX, aY, ared, agreen, ablue * * imageFree iImageNumber * */ #define USE_LIBPNG #ifdef USE_LIBPNG #include #else #include #include #endif /* #include */ /* #include */ #include "csdl.h" #include "imageOpcodes.h" /* __doOpenImage and __doSaveImage are the only two functions that deal with the actual image loading saving library. imageData stores the image content as an array of RGB bytes for each row (l->r t->b) so a pixel value in imageData is located at: (w*y+x)*3. */ /* #undef CS_KSMPS */ /* #define CS_KSMPS (csound->GetKsmps(csound)) */ static Image * __doOpenImage(char * filename, CSOUND *csound) { #ifdef USE_LIBPNG #define HS (8) FILE *fp; void *fd; unsigned char header[HS]; png_structp png_ptr; png_infop info_ptr; /* png_infop end_ptr; */ int is_png; png_uint_32 width, height, rowbytes; int bit_depth; int color_type; unsigned char *image_data; png_bytepp row_pointers; unsigned int i; Image *img; fd = csound->FileOpen2(csound, &fp, CSFILE_STD, filename, "rb", "SFDIR;SSDIR", CSFTYPE_IMAGE_PNG, 0); if (UNLIKELY(fd == NULL)) { csound->InitError(csound, Str("imageload: cannot open image %s.\n"), filename); return NULL; } if (UNLIKELY(HS!=fread(header, 1, HS, fp))) csound->InitError(csound, Str("imageload: file %s is not in PNG format.\n"), filename); is_png = !png_sig_cmp(header, 0, HS); if (UNLIKELY(!is_png)) { csound->InitError(csound, Str("imageload: file %s is not in PNG format.\n"), filename); csound->FileClose(csound, fd); return NULL; } png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (UNLIKELY(!png_ptr)) { csound->InitError(csound, Str("imageload: out of memory.\n")); csound->FileClose(csound, fd); return NULL; } info_ptr = png_create_info_struct(png_ptr); if (UNLIKELY(!info_ptr)) { png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); csound->InitError(csound, Str("imageload: out of memory.\n")); csound->FileClose(csound, fd); return NULL; } /* end_ptr = png_create_info_struct(png_ptr); */ /* if (UNLIKELY(!end_ptr)) { */ /* png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); */ /* csound->InitError(csound, Str("imageload: out of memory.\n")); */ /* csound->FileClose(csound, fd); */ /* return NULL; */ /* } */ png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, HS); png_read_info(png_ptr, info_ptr); { png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); } if (color_type & PNG_COLOR_MASK_ALPHA) png_set_strip_alpha(png_ptr); if (bit_depth == 16) png_set_strip_16(png_ptr); if (bit_depth < 8) png_set_packing(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); png_read_update_info(png_ptr, info_ptr); rowbytes = png_get_rowbytes(png_ptr, info_ptr); if (UNLIKELY((image_data = (unsigned char *)csound->Malloc(csound,rowbytes*height))==NULL)) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); csound->InitError(csound, Str("imageload: out of memory.\n")); return NULL; } row_pointers = (png_bytepp) csound->Malloc(csound, height*sizeof(png_bytep)); if (UNLIKELY(row_pointers == NULL)) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); csound->Free(csound,image_data); image_data = NULL; csound->InitError(csound, Str("imageload: out of memory.\n")); return NULL; } for (i = 0; i < height; i++) row_pointers[i] = image_data + i*rowbytes; png_read_image(png_ptr, row_pointers); csound->Free(csound,row_pointers); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); csound->FileClose(csound, fd); img = csound->Malloc(csound, sizeof(Image)); if (UNLIKELY(!img)) { csound->Free(csound,image_data); csound->InitError(csound, Str("imageload: out of memory.\n")); return NULL; } img->w = width; img->h = height; img->imageData = image_data; return img; #else Display *disp; ImlibData *id; ImlibImage *im; Image *img; size_t datasize; disp=XOpenDisplay(NULL); id=Imlib_init(disp); im=Imlib_load_image(id, filename); img = csound->Malloc(csound, sizeof(Image)); img->w = im->rgb_width; img->h = im->rgb_height; datasize = img->w*img->h*3 * sizeof(unsigned char); img->imageData = csound->Malloc(csound, datasize); memcpy(img->imageData, im->rgb_data, datasize); return img; #endif /* SDL */ /* Image *img; size_t datasize; SDL_Surface *srfc; int x,y; int bpp; int indcount = 0; Uint32 *pixel; Uint8 r, g, b; srfc = IMG_Load(filename); if (srfc) { SDL_LockSurface(srfc); img = csound->Malloc(csound, sizeof(Image)); img->w = srfc->w; img->h = srfc->h; bpp = srfc->format->BitsPerPixel; datasize = img->w*img->h*3 * sizeof(unsigned char); img->imageData = csound->Malloc(csound, datasize); for(y = 0; y < img->h; y++) { for(x = 0; x < img->w; x++) { if (bpp<=8) //need to test on other platforms pixel = srfc->pixels + y * srfc->pitch + x * bpp; else pixel = srfc->pixels + y * srfc->pitch + x * bpp / 8; SDL_GetRGB(*pixel,srfc->format, &r, &g, &b); img->imageData[indcount]= r; img->imageData[indcount+1]= g; img->imageData[indcount+2]= b; indcount += 3; } } SDL_UnlockSurface(srfc); SDL_FreeSurface ( srfc ); return img; } return NULL; */ } static int __doSaveImage(Image *image, char *filename, CSOUND *csound) { #ifdef USE_LIBPNG png_structp png_ptr; png_infop info_ptr; png_bytepp row_pointers; unsigned rowbytes; int i; FILE *fp; void *fd; fd = csound->FileOpen2(csound, &fp, CSFILE_STD, filename, "wb", "", CSFTYPE_IMAGE_PNG, 0); if (UNLIKELY(fd == NULL)) { return csound->InitError(csound, Str("imageload: cannot open image %s for writing.\n"), filename); } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (UNLIKELY(!png_ptr)){ csound->FileClose(csound, fd); return csound->InitError(csound, Str("imageload: out of memory.\n")); } info_ptr = png_create_info_struct(png_ptr); if (UNLIKELY(!info_ptr)) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); csound->FileClose(csound, fd); return csound->InitError(csound, Str("imageload: out of memory.\n")); } png_init_io(png_ptr, fp); png_set_IHDR(png_ptr, info_ptr, image->w, image->h, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(png_ptr, info_ptr); row_pointers = (png_bytepp)csound->Malloc(csound, image->h*sizeof(png_bytep)); if (UNLIKELY(row_pointers == NULL)) { png_destroy_write_struct(&png_ptr, &info_ptr); return csound->InitError(csound, Str("imageload: out of memory.\n")); } rowbytes = png_get_rowbytes(png_ptr, info_ptr); for (i = 0; i < image->h; i++) row_pointers[i] = image->imageData + i*rowbytes; png_write_image(png_ptr, row_pointers); png_write_end(png_ptr, info_ptr); csound->Free(csound,row_pointers); png_destroy_write_struct(&png_ptr, &info_ptr); csound->FileClose(csound, fd); return OK; #else Display *disp; ImlibData *id; ImlibImage *im; disp=XOpenDisplay(NULL); id=Imlib_init(disp); im = Imlib_create_image_from_data(id, image->imageData, NULL, image->w, image->h); Imlib_save_image(id, im, filename, NULL); Imlib_kill_image(id, im); return OK; #endif } static Image * createImage(CSOUND *csound, int w, int h) { Image *img; size_t datasize; img = csound->Malloc(csound, sizeof(Image)); img->w = w; img->h = h; datasize = img->w*img->h*3 * sizeof(unsigned char); img->imageData = csound->Malloc(csound, datasize); return img; } static Images * getImages(CSOUND *csound) { Images *pimages; pimages = (Images*)csound->QueryGlobalVariable(csound, "imageOpcodes.images"); if (pimages==NULL) { /* first call */ csound->CreateGlobalVariable(csound, "imageOpcodes.images", sizeof(Images)); pimages = (Images*)csound->QueryGlobalVariable(csound, "imageOpcodes.images"); pimages->images = (Image **) NULL; pimages->cnt = (size_t) 0; } return pimages; } static int imagecreate (CSOUND *csound, IMGCREATE * p) { Images *pimages; Image *img; pimages = getImages(csound); pimages->cnt++; pimages->images = (Image **) csound->ReAlloc(csound, pimages->images, sizeof(Image *) * pimages->cnt); img = createImage(csound, *p->kw, *p->kh); if (UNLIKELY(img==NULL)) { return csound->InitError(csound, Str("Cannot allocate memory.\n")); } else { pimages->images[pimages->cnt-1] = img; *(p->kn) = (MYFLT) pimages->cnt; return OK; } } static int imageload (CSOUND *csound, IMGLOAD * p) { char filename[256]; Images *pimages; Image *img; pimages = getImages(csound); pimages->cnt++; pimages->images = (Image **) csound->ReAlloc(csound, pimages->images, sizeof(Image *) * pimages->cnt); strncpy(filename, (char*) (p->ifilnam->data), 255);filename[255]='\0'; img = __doOpenImage(filename, csound); if (LIKELY(img)) { pimages->images[pimages->cnt-1] = img; *(p->kn) = (MYFLT) pimages->cnt; return OK; } else { return csound->InitError(csound, Str("imageload: cannot open image %s.\n"), filename); } } static int imagesize (CSOUND *csound, IMGSIZE * p) { Images *pimages; Image *img; pimages = (Images *) csound->QueryGlobalVariable(csound, "imageOpcodes.images"); img = pimages->images[(int)(*p->kn)-1]; *(p->kw) = (MYFLT) img->w; *(p->kh) = (MYFLT) img->h; return OK; } static int imagegetpixel (CSOUND *csound, IMGGETPIXEL * p) { Images *pimages; Image *img; int w, h, x, y; pimages = (Images *) csound->QueryGlobalVariable(csound, "imageOpcodes.images"); img = pimages->images[(int)(*p->kn)-1]; w = img->w; h = img->h; x = *p->kx*w; y = *p->ky*h; if (x >= 0 && x < w && y >= 0 && y < h ) { int pixel = (w*y+x)*3; *p->kr = img->imageData[pixel]/FL(255.0); *p->kg = img->imageData[pixel+1]/FL(255.0); *p->kb = img->imageData[pixel+2]/FL(255.0); } else { *p->kr = FL(0.0); *p->kg = FL(0.0); *p->kb = FL(0.0); } return OK; } static int imagegetpixel_a (CSOUND *csound, IMGGETPIXEL * p) { Images *pimages; Image *img; MYFLT *r = p->kr; MYFLT *g = p->kg; MYFLT *b = p->kb; MYFLT *tx = p->kx; MYFLT *ty = p->ky; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; int w, h, x, y, pixel; pimages = (Images *) csound->QueryGlobalVariable(csound, "imageOpcodes.images"); img = pimages->images[(int)(*p->kn)-1]; w = img->w; h = img->h; if (UNLIKELY(offset)) { memset(r, '\0', offset*sizeof(MYFLT)); memset(g, '\0', offset*sizeof(MYFLT)); memset(b, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); memset(&g[nsmps], '\0', early*sizeof(MYFLT)); memset(&b[nsmps], '\0', early*sizeof(MYFLT)); } for (i = 0; i < nsmps; i++) { x = tx[i]*w; y = ty[i]*h; if ( x >= 0 && x < w && y >= 0 && y < h ) { pixel = (w*y+x)*3; r[i] = img->imageData[pixel]/FL(255.0); g[i] = img->imageData[pixel+1]/FL(255.0); b[i] = img->imageData[pixel+2]/FL(255.0); } else { r[i] = FL(0.0); g[i] = FL(0.0); b[i] = FL(0.0); } } return OK; } static int imagesetpixel_a (CSOUND *csound, IMGSETPIXEL * p) { Images *pimages; Image *img; MYFLT *r = p->kr; MYFLT *g = p->kg; MYFLT *b = p->kb; MYFLT *tx = p->kx; MYFLT *ty = p->ky; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; int h,w,x, y, pixel; pimages = (Images *) csound->QueryGlobalVariable(csound, "imageOpcodes.images"); img = pimages->images[(int)(*p->kn)-1]; w = img->w; h = img->h; if (UNLIKELY(early)) nsmps -= early; for (i = offset; i < nsmps; i++) { x = tx[i]*w; y = ty[i]*h; if (x >= 0 && x < w && y >= 0 && y < h ) { pixel = (w*y+x)*3; img->imageData[pixel] = (unsigned char)(r[i]*255) % 256; img->imageData[pixel+1] = (unsigned char)(g[i]*255) % 256; img->imageData[pixel+2] = (unsigned char)(b[i]*255) % 256; } } return OK; } static int imagesetpixel (CSOUND *csound, IMGSETPIXEL * p) { Images *pimages; Image *img; int w, h, x, y, pixel; pimages = (Images *) csound->QueryGlobalVariable(csound, "imageOpcodes.images"); img = pimages->images[(int)(*p->kn)-1]; w = img->w; h = img->h; x = *p->kx*w; y = *p->ky*h; if (x >= 0 && x < w && y >= 0 && y < h ) { pixel = (w*y+x)*3; img->imageData[pixel] = (unsigned char)((*p->kr)*255) % 256; img->imageData[pixel+1] = (unsigned char)((*p->kg)*255) % 256; img->imageData[pixel+2] = (unsigned char)((*p->kb)*255) % 256; } return OK; } static int imagesave (CSOUND *csound, IMGSAVE * p) { Images *pimages; Image *img; char filename[256]; strncpy(filename, (char*) (p->ifilnam->data), 255);filename[255]='\0'; pimages = (Images *) csound->QueryGlobalVariable(csound, "imageOpcodes.images"); img = pimages->images[(int)(*p->kn)-1]; return __doSaveImage(img, filename, csound); } static int imagefree (CSOUND *csound, IMGSAVE * p) { Images *pimages; Image *img; pimages = (Images *) csound->QueryGlobalVariable(csound, "imageOpcodes.images"); img = pimages->images[(int)(*p->kn)-1]; csound->Free(csound,img->imageData); csound->Free(csound,img); return OK; } #define S(x) sizeof(x) static OENTRY image_localops[] = { { "imageload", S(IMGLOAD), 0, 1, "i", "S", (SUBR)imageload, NULL, NULL }, { "imagecreate",S(IMGCREATE),0, 1, "i", "ii", (SUBR)imagecreate, NULL, NULL }, { "imagesize", S(IMGSIZE), 0, 1, "ii", "i", (SUBR)imagesize, NULL, NULL }, { "imagegetpixel", S(IMGGETPIXEL), 0, 7, "sss", "ixx", (SUBR)imagegetpixel, (SUBR)imagegetpixel, (SUBR)imagegetpixel_a }, { "imagesetpixel", S(IMGSETPIXEL), 0, 7, "", "ixxxxx", (SUBR)imagesetpixel, (SUBR)imagesetpixel, (SUBR)imagesetpixel_a }, { "imagesave", S(IMGSAVE), 0, 1, "", "iS", (SUBR)imagesave, NULL, NULL }, { "imagefree", S(IMGFREE), 0, 1, "", "i", (SUBR)imagefree, NULL, NULL }, }; LINKAGE_BUILTIN(image_localops) csound-6.10.0/Opcodes/imageOpcodes.h000066400000000000000000000027151321653344700172520ustar00rootroot00000000000000/** * IMAGE OPCODES * * imageOpcodes.h * * Copyright (c) 2007 by Cesare Marilungo. All rights reserved. * * L I C E N S E * * This software is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ typedef struct { unsigned char *imageData; int w,h; } Image; typedef struct { Image **images; size_t cnt; } Images; typedef struct { OPDS h; MYFLT *kn; STRINGDAT *ifilnam ; } IMGLOAD; typedef struct { OPDS h; MYFLT *kn, *kw, *kh ; } IMGCREATE; typedef struct { OPDS h; MYFLT *kw, *kh, *kn; } IMGSIZE; typedef struct { OPDS h; MYFLT *kr,*kg,*kb, *kn, *kx,*ky; } IMGGETPIXEL; typedef struct { OPDS h; MYFLT *kn,*kx,*ky,*kr,*kg,*kb; } IMGSETPIXEL; typedef struct { OPDS h; MYFLT *kn; STRINGDAT *ifilnam; } IMGSAVE; typedef struct { OPDS h; MYFLT *kn; } IMGFREE; csound-6.10.0/Opcodes/jackTransport.c000066400000000000000000000053131321653344700174700ustar00rootroot00000000000000/** * jack_transport.c * * Copyright (c) 2008 by Cesare Marilungo. All rights reserved. * * L I C E N S E * * This software is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * U S A G E * * jack_transport 1 - to start jack transport * * jack_transport 0 - to stop * * the second optional parameter tells where the transport should be located * */ #include #include #include #include "cs_jack.h" enum { STOP, START }; typedef struct { OPDS h; MYFLT *command; MYFLT *location; } JACKTRANSPORT; static int jack_transport (CSOUND *csound, JACKTRANSPORT * p) { RtJackGlobals *rtjack; jack_client_t *client; rtjack = (RtJackGlobals*) csound->QueryGlobalVariableNoCheck(csound, "_rtjackGlobals"); client = rtjack->client; if (UNLIKELY(client == NULL)) { return csound->InitError(csound, Str("Cannot find Jack client.\n")); } else { //move to specified location (in seconds) if ((int)(*p->location)>=0) { MYFLT loc_sec = *p->location; MYFLT loc_sec_per_sr = loc_sec*csound->GetSr(csound); jack_transport_locate(client, loc_sec_per_sr); csound->Warning(csound, Str("jacktransport: playback head moved " "at %f seconds\n"), loc_sec); } //start or stop switch ((int)(*p->command)) { case START: csound->Warning(csound, Str("jacktransport: playing.\n")); jack_transport_start(client); break; case STOP: csound->Warning(csound, Str("jacktransport: stopped.\n")); jack_transport_stop(client); break; default: csound->Warning(csound, Str("jacktransport: invalid parameter.\n")); break; } } return OK; } #define S(x) sizeof(x) static OENTRY jackTransport_localops[] = { { "jacktransport", S(JACKTRANSPORT), 0, 1, "", "ij", (SUBR)jack_transport, NULL, NULL }, }; LINKAGE_BUILTIN(jackTransport_localops) csound-6.10.0/Opcodes/jacko.cpp000066400000000000000000002004721321653344700162750ustar00rootroot00000000000000/* jacko.cpp: Copyright (C) 2010nby Michael Gogins This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /** * T H E J A C K O P C O D E S * Michael Gogins * * The Jack opcodes can be used to connect any number * of Csound instances, instruments, or user-defined * opcodes to any number of Jack ports * in any number of external Jack servers. * Audio and MIDI signal types are supported. * * Sending MIDI and/or audio to external Jack clients, * such as synthesizers, and receiving audio and/or * MIDI back from them, is supported. * * Receiving MIDI and/or audio from external Jack clients, * such as sequencers, and sending MIDI and/or audio * back to them, is supported. * * Other uses also are supported. * * O P C O D E S * * JackoInit -- Initializes Csound as a Jack client. * * Description * * Initializes this instance of Csound as a Jack client. * * Csound's sr must be equal to the Jack daemon's * frames per second. * * Csound's ksmps must be equal to the Jack daemon's * frames per period. * * Frames per period must not only (a) be a power of 2, * but also (b) go evenly into the frames per second, * e.g. 128 frames per period goes into 48000 * frames per second 375 times, for a latency or * MIDI time granularity of about 2.7 milliseconds * (as good as or better than the absolute best * human performers). * * The order of processing of all signals that pass * from Jack input ports, through Csound processing, * and to Jack output ports, must be properly * determined by sequence of instrument and * opcode definition within the Csound orchestra. * * Syntax * * JackoInit SclientName, ServerName * * Initialization * * SclientName -- The name of the Jack client; * normally, should be "csound". * * ServerName -- The name of the Jack daemon; * normally, will be "default". * * This opcode must be called once and only once in the * orchestra header, and before any other Jack opcodes. * If more than one instance of Csound is using the Jack * opcodes at the same time, then each instance of Csound * must use a different client name. * * * JackoInfo -- Prints information about the Jack system. * * Description * * Prints the Jack daemon and client names, the * sampling rate and frames per period, * and all active Jack port names, * types, states, and connections. * * Syntax * * JackoInfo * * Initialization * * May be called any number of times in the orchestra header, * for example both before and after creating Jack ports * in the Csound orchestra header. * * * JackoFreewheel -- Turns freewheeling mode on or off. * * Description * * Turns Jack's freewheeling mode on or off. * * When freewheeling is on, if supported by the rest * of the Jack system, Csound will run as fast as possible, * which may be either faster or slower than real time. * * This is essential for rendering scores that are too * dense for real-time jacko_is_driving to a soundfile, * without xruns or dropouts. * * Syntax * * JackoFreewheel [ienabled] * * Initialization * * ienabled -- Turns freewheeling on (the default) or off. * * * JackoAudioInConnect -- Creates an audio connection * from a Jack port to Csound. * * Description * * In the orchestra header, creates an audio connection * from an external Jack audio output port to a * Jack audio input port inside this instance of Csound. * * Syntax * * JackoAudioInConnect SexternalPortName, ScsoundPortName * * Initialization * * SexternalPortName -- The full name ("clientname:portname") * of an external Jack audio output port. * * ScsoundPortName -- The short name ("portname") * of the internal Jack audio input port. * * Performance * * The actual audio must be read with the JackoAudioIn opcode. * * * JackoAudioOutConnect -- Creates an audio connection * from Csound to a Jack port. * * Description * * In the orchestra header, creates an audio connection * from a Jack audio output port inside this instance * of Csound to an external Jack audio input port. * * Syntax * * JackoAudioOutConnect ScsoundPortName, SexternalPortName * * Initialization * * ScsoundPortName -- The short name ("portname") * of the internal Jack audio input port. * * SexternalPortName -- The full name ("clientname:portname") * of an external Jack audio output port. * * Performance * * The actual audio must be written with the JackoAudioOut * opcode. * * * JackoMidiInConnect -- Creates a MIDI connection from * Jack to Csound. * * Description * * Creates a MIDI connection from an external Jack MIDI * output port to this instance of Csound. * * Syntax * * JackoMidiInConnect SexternalPortName, ScsoundPortName * * Initialization * * SexternalPortName -- The full name ("clientname:portname") * of an external Jack MIDI output port. * * ScsoundPortName -- The short name ("portname") * of the internal Jack MIDI input port. * * Must be used in conjunction with the * -M0 -+rtmidi=null Csound command-line options. * Can be used in with the MIDI inter-operability * command-line options and/or opcodes to enable the * use of ordinary Csound instrument definitions to * render external scores or MIDI sequences. * * Note that Csound can connect to ALSA ports through Jack, * but in this case you will have to identify the port by * its alias in the JackInfo printout. * * Performance * * The actual MIDI events will be received in the * regular Csound way, i.e. through a MIDI driver * and the sensevents mechanism, rather than through * a Jack input port opcode. * * The granularity of timing is Csound's kperiod. * * * JackoMidiOutConnect -- Creates a MIDI connection from * Csound to Jack. * * Description * * In the orchestra header, creates a connection * from a Jack MIDI output port inside this instance * of Csound to an external Jack MIDI input port. * * Syntax * * JackoMidiOutConnect ScsoundPortName, SexternalPortName * * Initialization * * ScsoundPortName -- The short name ("portname") * of the internal Jack audio input port. * * SexternalPortName -- The full name ("clientname:portname") * of an external Jack audio output port. * * Performance * * The actual MIDI data must be written with the JackoMidiOut * or JackoNoteOut opcodes. * * * JackoOn -- Enables or disables all Jack ports. * * Description * * After all Jack connections have been created, enables * or disables all Jack input and output opcodes * inside this instance of Csound to read or write data. * * Syntax * * JackoOn [iactive] * * Initialization * * iactive -- A flag that turns the ports on (the default) * or off. * * * JackoAudioIn -- Receives an audio signal from a Jack port. * * Description * * Receives an audio signal from a Jack audio input port * inside this instance of Csound, which in turn has * received the signal from its connected external Jack * audio output port. * * Syntax * * asignal JackoAudioIn ScsoundPortName * * Initialization * * ScsoundPortName -- The short name ("portname") * of the internal Jack audio input port. * * Performance * * asignal -- Audio received from the external Jack * output port to which ScsoundPortName is connected. * * * JackoAudioOut -- Sends an audio signal to a Jack port. * * Description * * Sends an audio signal to an internal Jack audio * output port, and in turn to its connected external * Jack audio input port. * * Note that it is possible to send audio out via Jack * to the system audio interface, while at the same time * rendering to a regular Csound output soundfile. * * Syntax * * JackoAudioOut ScsoundPortName, asignal * * Initialization * * ScsoundPortName -- The short name ("portname") * of the internal Jack audio output port. * * Performance * * asignal -- Audio to be sent to the external Jack audio * input port to which CsoundPortName is connected. * * Audio from multiple instances of the opcode sending * to the same Jack port is summed before sending. * * * JackoMidiOut -- Sends a MIDI channel message to a * Jack port. * * Description * * Sends a MIDI channel message to a Jack MIDI output port * inside this instance of Csound, and in turn to its * connected external Jack MIDI input port. * * Syntax * * JackoMidiOut ScsoundPortName, kstatus, kchannel, kdata1[, kdata2] * * Initialization * * ScsoundPortName -- The short name ("portname") * of the internal Jack MIDI input port. * * Performance * * kstatus -- MIDI status byte; must indicate a MIDI channel * message. * * kchannel -- MIDI channel (from 0 through 15). * * kdata1 -- First data byte of a MIDI channel message. * * kdata2 -- Optional second data byte of a MIDI channel message. * * This opcode can be called any number of times * in the same kperiod. Messages from multiple instances * of the opcode sending to the same port are collected * before sending. * * Running status, system exclusive messages, and * real-time messages are not supported. * * The granularity of timing is Csound's kperiod. * * * JackoNoteOut -- Send one note to a Jack MIDI port. * * Description * * Sends one note to a Jack MIDI output port inside this * instance of Csound, and in turn to the connected external * Jack MIDI input port, with a duration * specified by the score instrument statement. * The matching MIDI note off message is generated * and scheduled for later transmission. * * Notes from multiple instances of the opcode * sending to the same output port are collected * before sending. * * The granularity of timing is Csound's kperiod. * * Syntax * * JackoNoteOut ScsoundPortName, ichannel, ikey, ivelocity * * Initialization * * ScsoundPortName -- The short name ("portname") of the * Jack MIDI output port created by jackmidioutconnect. * * ichannel -- The MIDI channel (from 0 through 15) to * receive the note. * * ikey -- The MIDI key number (from 0 through 127, 60 is * middle C) of the note. * * ivelocity -- The MIDI velocity number (from 0 through 127) * of the note. * * * JackoTransport -- Control the Jack transport. * * Description * * Starts, stops, or repositions the Jack transport. * This is useful, e.g., for starting an external sequencer * playing to send MIDI messages to Csound. * * Syntax * * JackoTransport kcommand, [kposition] * * Performance * * kcommand -- 0 means "no action", 1 starts the transport, * 2 stops the transport, and 3 positions the transport * to kposition seconds from the beginning of jacko_is_driving * (i.e. time 0 in the score). * * This opcode can be used at init time or during jacko_is_driving. * * The granularity of timing is Csound's kperiod. * * * I M P L E M E N T A T I O N * * Processing is done according to the callback model: * * 1. The jackinit opcode: * 1.1. Creates a Jack client, * which is associated with the * running instance of Csound. * 1.2. Registers a JackProcessCallback with Jack. * 1.3. Registers a SenseEventCallback with Csound. * 1.4. Installs a MIDI driver callback to consume * MIDI events coming from Jack input ports. * 1.5. Puts the Csound processing thread to sleep. * 1.6. Activates the client. * 2. The ports are created and connected in the orchestra header. * 3. After all ports are connected, they are turned on in the * orchestra header. * 4. Every time the Jack callback fires: * 4.1. Any MIDI events pending in the input ports are enqueued * for dispatch via the MIDI driver callack through * Csound's normal sensevents mechanism. * 4.2. csoundPerformKsmps is called. * 4.3. When the Csound jacko_is_driving is finished: * 4.3.1. The Csound processing thread is re-awakened. * 4.3.2. The Jack processing callback is deactivated. * 4.3.2. The Jack client is closed. * 5. At the end of processing, the module deinitialization * function erases all Jack-related state. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace csound; struct JackoInit; struct JackoInfo; struct JackoFreewheel; struct JackoAudioIn; struct JackoAudioOut; struct JackoMidiOut; struct JackoNoteOut; struct JackoTransport; struct JackoState; /** * There is one and only one JackoState instance per instance of Csound. * It is created by and only by the JackoInit opcode. */ //static JackoState *jackoState = 0; static void SenseEventCallback_(CSOUND *csound, void *data); static int JackProcessCallback_(jack_nframes_t frames, void *data); static int midiDeviceOpen_(CSOUND *csound, void **userData, const char *devName); static int midiRead_(CSOUND *csound, void *userData, unsigned char *midiData, int nbytes); /** * Manages all state relevant to the global * interaction between Jack and Csound for a particular * client and instance of Csound. The actual reading * and writing of data is done by the input and output * opcodes. */ struct JackoState { CSOUND *csound; const char *serverName; const char *clientName; jack_client_t *jackClient; std::atomic jacko_is_driving; std::atomic jackActive; jack_nframes_t csoundFramesPerTick; jack_nframes_t jackFramesPerTick; jack_nframes_t csoundFramesPerSecond; jack_nframes_t jackFramesPerSecond; jack_nframes_t jackFrameTime; std::map audioInPorts; std::map audioOutPorts; std::map midiInPorts; std::map midiOutPorts; std::list midiInputQueue; jack_position_t jack_position; pthread_t closeThread; pthread_mutex_t csoundPerformanceThreadConditionMutex; pthread_mutexattr_t csoundPerformanceThreadConditionMutexAttribute; pthread_cond_t csoundPerformanceThreadCondition; JackoState(CSOUND *csound_, const char *serverName_, const char *clientName_) : csound(csound_), serverName(serverName_), clientName(clientName_), jackActive(false), jacko_is_driving(false) { int result = 0; csound = csound_; csoundFramesPerTick = csound->GetKsmps(csound); csoundFramesPerSecond = csound->GetSr(csound); pthread_mutexattr_init(&csoundPerformanceThreadConditionMutexAttribute); pthread_mutexattr_settype(&csoundPerformanceThreadConditionMutexAttribute, PTHREAD_MUTEX_RECURSIVE); result |= pthread_mutex_init(&csoundPerformanceThreadConditionMutex, &csoundPerformanceThreadConditionMutexAttribute); result |= pthread_cond_init(&csoundPerformanceThreadCondition, 0); std::memset(&jack_position, 0, sizeof(jack_position_t)); jack_options_t jack_options = (jack_options_t)(JackServerName | JackNoStartServer | JackUseExactName); jack_status_t status = jack_status_t(0); jackClient = jack_client_open(clientName, jack_options, &status, serverName); if (!jackClient) { csound->Message(csound, Str("Could not create Jack client \"%s\" -- " "is Jack server \"%s\" running? Status: %d\n"), clientName, serverName, status); csound->LongJmp(csound, 1); } else { csound->Message(csound, Str("Created Jack client \"%s\" for Jack server \"%s\".\n"), clientName, serverName); } jackFramesPerTick = jack_get_buffer_size(jackClient); if (csoundFramesPerTick != jackFramesPerTick) { csound->Message(csound, Str("Jack buffer size %d != Csound ksmps %d, exiting...\n"), jackFramesPerTick, csoundFramesPerTick); csound->LongJmp(csound, 1); } jackFramesPerSecond = jack_get_sample_rate(jackClient); if (csoundFramesPerSecond != jackFramesPerSecond) { csound->Message(csound, Str("Jack sampling rate %d != Csound sr %d, exiting...\n"), jackFramesPerSecond, csoundFramesPerSecond); csound->LongJmp(csound, 1); } csound->SetExternalMidiInOpenCallback(csound, midiDeviceOpen_); csound->SetExternalMidiReadCallback(csound, midiRead_); csound->RegisterSenseEventCallback(csound, SenseEventCallback_, this); result |= jack_set_process_callback(jackClient, JackProcessCallback_, this); result |= jack_activate(jackClient); if (!result) { csound->Message(csound, Str("Activated Jack client \"%s\".\n"), jack_get_client_name(jackClient)); } else { csound->Message(csound, Str("Failed to activate Jack client \"%s\": status %d.\n"), jack_get_client_name(jackClient), result); return; } //jackInitialized = true; } ~JackoState() { //int result = 0; // This does NOTHING! } int SenseEventCallback() { int result = 0; // Here we must wait once and only once, in order to put // the original Csound processing thread to sleep -- // but we must NOT put the Jack processing callback // to sleep when it comes here! if (jacko_is_driving == false) { // While Jack is processing, wait here. // The Jack process callback will then call csoundPerformKsmps // until the Csound jacko_is_driving is complete. csound->Message(csound, Str("Jacko is now driving Csound performance...\n")); result |= pthread_mutex_lock(&csoundPerformanceThreadConditionMutex); jacko_is_driving = true; while (jacko_is_driving == true) { result |= pthread_cond_wait(&csoundPerformanceThreadCondition, &csoundPerformanceThreadConditionMutex); } result |= pthread_mutex_unlock(&csoundPerformanceThreadConditionMutex); csound->Message(csound, Str("Jacko has quit driving Csound performance.\n")); return 1; } return 0; } int JackProcessCallback(jack_nframes_t frames) { if (jacko_is_driving == false) { return 0; } // We must call PerformKsmps here ONLY after the original // Csound jacko_is_driving thread is waiting on its condition. int finished = 0; jackFrameTime = jack_last_frame_time(jackClient); if (jacko_is_driving == true) { // Enqueue any MIDI messages pending in input ports. for (std::map ::iterator it = midiInPorts.begin(); it != midiInPorts.end(); ++it) { jack_port_t *midiinport = it->second; void *portbuffer = jack_port_get_buffer(midiinport, jackFramesPerTick); if (portbuffer) { jack_nframes_t eventN = jack_midi_get_event_count(portbuffer); for (jack_nframes_t eventI = 0; eventI < eventN; ++eventI) { jack_midi_event_t event; int result = jack_midi_event_get(&event, portbuffer, eventI); if (result == 0) { for (size_t i = 0; i < event.size; ++i) { midiInputQueue.push_back(event.buffer[i]); } } } } } // Clear MIDI output buffers. for (std::map ::iterator it = midiOutPorts.begin(); it != midiOutPorts.end(); ++it) { void *buffer = jack_port_get_buffer(it->second, jackFramesPerTick); jack_midi_clear_buffer(buffer); } finished = csound->PerformKsmps(csound); // We break here when the Csound performace is complete, and close // the Jack connection in a separate thread. if (finished /* && jackActive */) { csound->Message(csound, Str("Jacko performance finished.\n")); jacko_is_driving = false; // Create a thread to run the close routine. finished |= pthread_create(&closeThread, 0, &JackoState::closeThreadRoutine_, this); } } return finished; } int close() { csound->Message(csound, Str("BEGAN JackoState::close()...\n")); int result = OK; // Try not to do thread related operations more than once... result = jack_deactivate(jackClient); csound->Message(csound, Str("Jack client deactivated.\n")); // Jack documentation says deactivating the client does the following also: for (std::map ::iterator it = audioInPorts.begin(); it != audioInPorts.end(); ++it) { result = jack_port_unregister(jackClient, it->second); } for (std::map ::iterator it = audioOutPorts.begin(); it != audioOutPorts.end(); ++it) { result = jack_port_unregister(jackClient, it->second); } for (std::map ::iterator it = midiInPorts.begin(); it != midiInPorts.end(); ++it) { result = jack_port_unregister(jackClient, it->second); } for (std::map ::iterator it = midiOutPorts.begin(); it != midiOutPorts.end(); ++it) { result = jack_port_unregister(jackClient, it->second); } csound->Message(csound, Str("Jack ports unregistered.\n")); result |= jack_client_close(jackClient); //csound->Message(csound, Str("Jack client closed.\n")); pthread_cond_signal(&csoundPerformanceThreadCondition); result |= pthread_cond_destroy(&csoundPerformanceThreadCondition); result |= pthread_mutex_unlock(&csoundPerformanceThreadConditionMutex); result |= pthread_mutex_destroy(&csoundPerformanceThreadConditionMutex); audioOutPorts.clear(); audioInPorts.clear(); midiInPorts.clear(); midiOutPorts.clear(); csound->Message(csound, Str("ENDED JackoState::close().\n")); return result; } void *closeThreadRoutine() { int result = 0; close(); void *result_ = 0; memcpy(&result_, &result, std::min(sizeof(result), sizeof(result_))); return result_; } static void *closeThreadRoutine_(void *userdata) { return ((JackoState *)userdata)->closeThreadRoutine(); } void startTransport() { midiInputQueue.clear(); jack_transport_start(jackClient); } void stopTransport() { jack_transport_stop(jackClient); } int positionTransport(double timeSeconds) { int result = OK; jack_position.frame_time = timeSeconds; midiInputQueue.clear(); result = jack_transport_reposition(jackClient, &jack_position); return result; } /** * Return a MIDI output buffer, * clearing it if not yet cleared for this tick. */ jack_midi_data_t *getMidiOutBuffer(jack_port_t *csoundPort) { jack_midi_data_t *buffer = (jack_midi_data_t *)jack_port_get_buffer(csoundPort, csoundFramesPerTick); return buffer; } }; static int JackProcessCallback_(jack_nframes_t frames, void *data) { return ((JackoState *)data)->JackProcessCallback(frames); } static void SenseEventCallback_(CSOUND *csound, void *data) { ((JackoState *)data)->SenseEventCallback(); } static int midiDeviceOpen_(CSOUND *csound, void **userData, const char *devName) { JackoState *jackoState; csound::QueryGlobalPointer(csound, "jackoState", jackoState); *userData = jackoState; return 0; } /** * Dispatch any MIDI channel messages that have * been read from Jack MIDI input ports. */ static int midiRead_(CSOUND *csound, void *userData, unsigned char *midiData, int midiN) { JackoState *jackoState_ = (JackoState *)userData; int midiI = 0; while (!jackoState_->midiInputQueue.empty() && midiI < midiN) { midiData[midiI] = jackoState_->midiInputQueue.front(); jackoState_->midiInputQueue.pop_front(); midiI++; } //if (midiI) { // csound->Message(csound, "midiRead_: %d bytes.\n", midiI); //} return midiI; } struct JackoInit : public OpcodeBase { STRINGDAT *ServerName; STRINGDAT *SclientName; const char *serverName; const char *clientName; int init(CSOUND *csound) { serverName = csound->strarg2name(csound, (char *) 0, ServerName->data, (char *)"default", (int) 1); clientName = csound->strarg2name(csound, (char *) 0, SclientName->data, (char *)"csound", (int) 1); JackoState *jackoState = new JackoState(csound, serverName, clientName); int result = csound::CreateGlobalPointer(csound, "jackoState", jackoState); return OK; } }; struct JackoInfo : public OpcodeBase { int init(CSOUND *csound) { JackoState *jackoState = 0; csound::QueryGlobalPointer(csound, "jackoState", jackoState); log(csound, "Jack information for client: %s\n", jackoState->clientName); log(csound, " Daemon name: %s\n", jackoState->serverName); log(csound, " Frames per second: %d\n", jackoState->jackFramesPerSecond); log(csound, " Frames per period: %d\n", jackoState->jackFramesPerTick); const char **ports = jack_get_ports(jackoState->jackClient, 0, 0, 0); if (ports) { log(csound, " Ports and connections:\n"); for (size_t i = 0; ports[i]; ++i) { const char *PortName = ports[i]; jack_port_t *port = jack_port_by_name(jackoState->jackClient, PortName); int flags = jack_port_flags(port); const char *type = jack_port_type(port); const char *portType = " "; if ((flags & JackPortIsOutput) == JackPortIsOutput) { portType = "Output"; } else if ((flags & JackPortIsInput) == JackPortIsInput) { portType = "Input "; } log(csound, " %3d: %s %-25s %s\n", (i+1), portType, type, (PortName ? PortName : "(no name)")); char alias1[0x100]; char alias2[0x100]; char *const aliases[2] = {alias1, alias2}; size_t aliasN = jack_port_get_aliases(port, aliases); for (size_t aliasI = 0; aliasI < aliasN; ++aliasI) { log(csound, " Alias: %s\n", aliases[aliasI]); } const char **connections = jack_port_get_all_connections(jackoState->jackClient, port); if (connections) { for (size_t j = 0; connections[j]; ++j) { if ((jack_port_flags(port) & JackPortIsOutput) == JackPortIsOutput) { log(csound, " Sends to: >> %s\n", connections[j]); } else { log(csound, " Receives from: << %s\n", connections[j]); } } } std::free(connections); } std::free(ports); } return OK; } }; struct JackoFreewheel : public OpcodeBase { MYFLT *ifreewheel; int init(CSOUND *csound) { JackoState *jackoState = 0; csound::QueryGlobalPointer(csound, "jackoState", jackoState); int freewheel = (int) *ifreewheel; int result = jack_set_freewheel(jackoState->jackClient, freewheel); if (result) { warn(csound, Str("Failed to set Jack freewheeling mode to \"%s\": error %d.\n"), (freewheel ? "on" : "off"), result); } else { log(csound, Str("Set Jack freewheeling mode to \"%s\".\n"), (freewheel ? "on" : "off")); } return result; } }; struct JackoOn : public OpcodeBase { MYFLT *jon; int init(CSOUND *csound) { int result = OK; JackoState *jackoState = 0; csound::QueryGlobalPointer(csound, "jackoState", jackoState); jackoState->jackActive = (char) *jon; log(csound, Str("Turned Jack connections \"%s\".\n"), (jackoState->jackActive ? "on" : "off")); return result; } }; struct JackoAudioInConnect : public OpcodeBase { // Out. // Ins. STRINGDAT *SexternalPortName; STRINGDAT *ScsoundPortName; // State. const char *csoundPortName; char csoundFullPortName[0x100]; const char *externalPortName; const char *clientName; jack_port_t *csoundPort; jack_port_t *externalPort; int init(CSOUND *csound) { JackoState *jackoState = 0; csound::QueryGlobalPointer(csound, "jackoState", jackoState); int result = OK; clientName = jack_get_client_name(jackoState->jackClient); csoundPortName = csound->strarg2name(csound, (char *)0, ScsoundPortName->data, (char *)"", (int) 1); std::sprintf(csoundFullPortName, "%s:%s", clientName, csoundPortName); externalPortName = csound->strarg2name(csound, (char *) 0, SexternalPortName->data, (char *)"csound", (int) 1); csoundPort = jack_port_by_name(jackoState->jackClient, csoundFullPortName); if (!csoundPort) { csoundPort = jack_port_register(jackoState->jackClient, csoundPortName, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); if (csoundPort) { log(csound, "Created Jack port \"%s\".\n", csoundFullPortName); } else { warn(csound, Str("Could not create Jack port \"%s\".\n"), csoundFullPortName); } } externalPort = jack_port_by_name(jackoState->jackClient, externalPortName); result = jack_connect(jackoState->jackClient, jack_port_name(externalPort), jack_port_name(csoundPort)); if (result == EEXIST) { log(csound, "Connection from \"%s\" to \"%s\" already exists.\n", externalPortName, csoundFullPortName); } else if (result) { warn(csound, Str("Could not create Jack connection from \"%s\" to \"%s\": " "status %d.\n"), externalPortName, csoundFullPortName, result); return result; } else { log(csound, "Created Jack connection from \"%s\" to \"%s\".\n", externalPortName, csoundFullPortName); } jackoState->audioInPorts[csoundPortName] = csoundPort; return result; } }; struct JackoAudioIn : public OpcodeBase { // Out. MYFLT *asignal; // Ins. STRINGDAT *ScsoundPortName; // State. const char *csoundPortName; jack_port_t *csoundPort; jack_nframes_t csoundFramesPerTick; JackoState *jackoState; int init(CSOUND *csound) { csound::QueryGlobalPointer(csound, "jackoState", jackoState); int result = OK; csoundFramesPerTick = jackoState->csoundFramesPerTick; csoundPortName = csound->strarg2name(csound, (char *)0, ScsoundPortName->data, (char *)"", (int) 1); csoundPort = jackoState->audioInPorts[csoundPortName]; return result; } int audio(CSOUND *csound) { jack_default_audio_sample_t *buffer = (jack_default_audio_sample_t *)jack_port_get_buffer(csoundPort, csoundFramesPerTick); for (size_t frame = 0; frame < csoundFramesPerTick; ++frame) { asignal[frame] = buffer[frame]; } return OK; } }; struct JackoAudioOutConnect : public OpcodeBase { // No outs. // Ins. STRINGDAT *ScsoundPortName; STRINGDAT *SexternalPortName; // State. const char *csoundPortName; char csoundFullPortName[0x100]; const char *externalPortName; const char *clientName; size_t frames; jack_port_t *csoundPort; jack_port_t *externalPort; JackoState *jackoState; int init(CSOUND *csound) { csound::QueryGlobalPointer(csound, "jackoState", jackoState); int result = OK; frames = opds.insdshead->ksmps; clientName = jack_get_client_name(jackoState->jackClient); csoundPortName = csound->strarg2name(csound, (char *)0, ScsoundPortName->data, (char *)"", (int) 1); std::sprintf(csoundFullPortName, "%s:%s", clientName, csoundPortName); externalPortName = csound->strarg2name(csound, (char *) 0, SexternalPortName->data, (char *)"csound", (int) 1); csoundPort = jack_port_by_name(jackoState->jackClient, csoundFullPortName); if (!csoundPort) { csoundPort = jack_port_register(jackoState->jackClient, csoundPortName, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if (csoundPort) { log(csound, "Created Jack port \"%s\".\n", csoundFullPortName); } else { warn(csound, Str("Could not create Jack port \"%s\".\n"), csoundFullPortName); } } externalPort = jack_port_by_name(jackoState->jackClient, externalPortName); result = jack_connect(jackoState->jackClient, jack_port_name(csoundPort), jack_port_name(externalPort)); if (result == EEXIST) { log(csound, "Connection from \"%s\" to \"%s\" already exists.\n", csoundFullPortName, externalPortName); } else if (result) { warn(csound, Str("Could not create Jack connection from \"%s\" to \"%s\": " "status %d.\n"), csoundFullPortName, externalPortName, result); return result; } else { log(csound, "Created Jack connection from \"%s\" to \"%s\".\n", csoundFullPortName, externalPortName); } jackoState->audioOutPorts[csoundPortName] = csoundPort; return result; } }; struct JackoAudioOut : public OpcodeBase { // No outs. // Ins. STRINGDAT *ScsoundPortName; MYFLT *asignal; // State. const char *csoundPortName; jack_port_t *csoundPort; jack_nframes_t csoundFramesPerTick; JackoState *jackoState; int init(CSOUND *csound) { csound::QueryGlobalPointer(csound, "jackoState", jackoState); int result = OK; csoundFramesPerTick = jackoState->csoundFramesPerTick; csoundPortName = csound->strarg2name(csound, (char *)0, ScsoundPortName->data, (char *)"", (int) 1); csoundPort = jackoState->audioOutPorts[csoundPortName]; return result; } int audio(CSOUND *csound) { jack_default_audio_sample_t *buffer = (jack_default_audio_sample_t *)jack_port_get_buffer(csoundPort, csoundFramesPerTick); for (size_t frame = 0; frame < csoundFramesPerTick; ++frame) { buffer[frame] = asignal[frame]; } return OK; } }; struct JackoMidiInConnect : public OpcodeBase { // No outs. // Ins. STRINGDAT *SexternalPortName; STRINGDAT *ScsoundPortName; // State. const char *csoundPortName; char csoundFullPortName[0x100]; const char *externalPortName; const char *clientName; size_t frames; jack_port_t *csoundPort; jack_port_t *externalPort; JackoState *jackoState; int init(CSOUND *csound) { csound::QueryGlobalPointer(csound, "jackoState", jackoState); int result = OK; frames = opds.insdshead->ksmps; clientName = jack_get_client_name(jackoState->jackClient); csoundPortName = csound->strarg2name(csound, (char *)0, ScsoundPortName->data, (char *)"", (int) 1); std::sprintf(csoundFullPortName, "%s:%s", clientName, csoundPortName); externalPortName = csound->strarg2name(csound, (char *) 0, SexternalPortName->data, (char *)"csound", (int) 1); csoundPort = jack_port_by_name(jackoState->jackClient, csoundFullPortName); if (!csoundPort) { csoundPort = jack_port_register(jackoState->jackClient, csoundPortName, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); if (csoundPort) { log(csound, "Created Jack port \"%s\".\n", csoundFullPortName); } else { warn(csound, Str("Could not create Jack port \"%s\".\n"), csoundFullPortName); } } externalPort = jack_port_by_name(jackoState->jackClient, externalPortName); result = jack_connect(jackoState->jackClient, jack_port_name(externalPort), jack_port_name(csoundPort)); if (result == EEXIST) { log(csound, "Connection from \"%s\" to \"%s\" already exists.\n", externalPortName, csoundFullPortName); } else if (result) { warn(csound, Str("Could not create Jack connection from \"%s\" to \"%s\": " "status %d.\n"), externalPortName, csoundFullPortName, result); return result; } else { log(csound, "Created Jack connection from \"%s\" to \"%s\".\n", externalPortName, csoundFullPortName); } jackoState->midiInPorts[csoundPortName] = csoundPort; return result; } }; struct JackoMidiOutConnect : public OpcodeBase { // No outs. // Ins. STRINGDAT *ScsoundPortName; STRINGDAT *SexternalPortName; // State. const char *csoundPortName; char csoundFullPortName[0x100]; const char *externalPortName; const char *clientName; size_t frames; jack_port_t *csoundPort; jack_port_t *externalPort; JackoState *jackoState; int init(CSOUND *csound) { csound::QueryGlobalPointer(csound, "jackoState", jackoState); int result = OK; frames = opds.insdshead->ksmps; clientName = jack_get_client_name(jackoState->jackClient); csoundPortName = csound->strarg2name(csound, (char *)0, ScsoundPortName->data, (char *)"", (int) 1); std::sprintf(csoundFullPortName, "%s:%s", clientName, csoundPortName); externalPortName = csound->strarg2name(csound, (char *) 0, SexternalPortName->data, (char *)"csound", (int) 1); csoundPort = jack_port_by_name(jackoState->jackClient, csoundFullPortName); if (!csoundPort) { csoundPort = jack_port_register(jackoState->jackClient, csoundPortName, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); if (csoundPort) { log(csound, "Created Jack port \"%s\".\n", csoundFullPortName); } else { warn(csound, Str("Could not create Jack port \"%s\".\n"), csoundFullPortName); } } externalPort = jack_port_by_name(jackoState->jackClient, externalPortName); result = jack_connect(jackoState->jackClient, jack_port_name(csoundPort), jack_port_name(externalPort)); if (result == EEXIST) { log(csound, "Connection from \"%s\" to \"%s\" already exists.\n", csoundFullPortName, externalPortName); } else if (result) { warn(csound, Str("Could not create Jack connection from \"%s\" to \"%s\": " "status %d.\n"), csoundFullPortName, externalPortName, result); return result; } else { log(csound, "Created Jack connection from \"%s\" to \"%s\".\n", csoundFullPortName, externalPortName); } jackoState->midiOutPorts[csoundPortName] = csoundPort; return result; } }; struct JackoMidiOut : public OpcodeBase { // No outs. // Ins. STRINGDAT *ScsoundPortName; MYFLT *kstatus; MYFLT *kchannel; MYFLT *kdata1; MYFLT *kdata2; char status; char channel; char data1; char data2; char priorstatus; char priorchannel; char priordata1; char priordata2; // State. const char *csoundPortName; jack_port_t *csoundPort; jack_nframes_t csoundFramesPerTick; jack_midi_data_t *buffer; JackoState *jackoState; int init(CSOUND *csound) { csound::QueryGlobalPointer(csound, "jackoState", jackoState); int result = OK; csoundFramesPerTick = jackoState->csoundFramesPerTick; csoundPortName = csound->strarg2name(csound, (char *)0, ScsoundPortName->data, (char *)"", (int) 1); csoundPort = jackoState->midiOutPorts[csoundPortName]; priorstatus = -1; priorchannel = -1; priordata1 = -1; priordata2 = -1; return result; } int kontrol(CSOUND *csound) { int result = OK; status = *kstatus; channel = *kchannel; data1 = *kdata1; data2 = *kdata2; if (status != priorstatus || channel != priorchannel || data1 != priordata1 || data2 != priordata2) { size_t dataSize = 0; if (data2 == -1) { dataSize = 2; } else { dataSize = 3; } buffer = jackoState->getMidiOutBuffer(csoundPort); jack_midi_data_t *data = jack_midi_event_reserve(buffer, 0, dataSize); data[0] = (status + channel); data[1] = data1; if (data2 != -1) { data[2] = data2; //log(csound, "MIDI: %3d %3d %3d\n", data[0], data[1], data[2]); } else { //log(csound, "MIDI: %3d %3d\n", data[0], data[1]); } } priorstatus = status; priorchannel = channel; priordata1 = data1; priordata2 = data2; return result; } }; struct JackoNoteOut : public OpcodeNoteoffBase { // No outs. // Ins. STRINGDAT *ScsoundPortName; MYFLT *ichannel; MYFLT *ikey; MYFLT *ivelocity; char status; char channel; char key; char velocity; // State. const char *csoundPortName; jack_port_t *csoundPort; jack_nframes_t csoundFramesPerTick; jack_midi_data_t *buffer; JackoState *jackoState; int init(CSOUND *csound) { csound::QueryGlobalPointer(csound, "jackoState", jackoState); int result = OK; csoundFramesPerTick = jackoState->csoundFramesPerTick; csoundPortName = csound->strarg2name(csound, (char *)0, ScsoundPortName->data, (char *)"", (int) 1); csoundPort = jackoState->midiOutPorts[csoundPortName]; status = 144; channel = (char) *ichannel; key = (char) *ikey; velocity = (char) *ivelocity; buffer = jackoState->getMidiOutBuffer(csoundPort); jack_midi_data_t *data = jack_midi_event_reserve(buffer, 0, 3); data[0] = (status + channel); data[1] = key; data[2] = velocity; //log(csound, "noteon: %3d %3d %3d\n", data[0], data[1], data[2]); return result; } int noteoff(CSOUND *csound) { int result = OK; buffer = jackoState->getMidiOutBuffer(csoundPort); jack_midi_data_t *data = jack_midi_event_reserve(buffer, 0, 3); data[0] = (status + channel); data[1] = key; data[2] = 0; //log(csound, "noteoff: %3d %3d %3d\n", data[0], data[1], data[2]); return result; } }; struct JackoTransport : public OpcodeBase { // Outs. // Ins. MYFLT *kcommand; MYFLT *Oposition; // State. int command; int priorCommand; double positionSeconds; double priorPositionSeconds; JackoState *jackoState; int init(CSOUND *csound) { csound::QueryGlobalPointer(csound, "jackoState", jackoState); priorCommand = -1; priorPositionSeconds = 0.0; return kontrol(csound); } int kontrol(CSOUND *csound) { int result = OK; command = int(*kcommand); positionSeconds = double(*Oposition); if (command) { if (command != priorCommand) { priorCommand = command; switch (command) { case 1: result = jackoState->positionTransport(0.0); jackoState->startTransport(); log(csound, "Started Jack transport.\n"); break; case 2: jackoState->stopTransport(); log(csound, "Stopped Jack transport.\n"); break; case 3: if (positionSeconds != priorPositionSeconds) { priorPositionSeconds = positionSeconds; result = jackoState->positionTransport(positionSeconds); jackoState->startTransport(); if (result) { log(csound, "Failed to start Jack transport at %f seconds with" " result: %d\n", positionSeconds, result); } else { log(csound, "Started Jack transport at %f seconds.\n", positionSeconds); } } break; }; } } return result; } }; extern "C" { static OENTRY oentries[] = { { (char *)"JackoInit", sizeof(JackoInit), 0, 1, (char *)"", (char *)"SS", (SUBR) &JackoInit::init_, 0, 0 }, { (char *)"JackoInfo", sizeof(JackoInfo), 0, 1, (char *)"", (char *)"", (SUBR) &JackoInfo::init_, 0, 0 }, { (char *)"JackoFreewheel", sizeof(JackoFreewheel), 0, 1, (char *)"", (char *)"i", (SUBR) &JackoFreewheel::init_, 0, 0 }, { (char *)"JackoOn", sizeof(JackoOn), 0, 1, (char *)"", (char *)"j", (SUBR) &JackoOn::init_, 0, 0 }, { (char *)"JackoAudioInConnect", sizeof(JackoAudioInConnect), 0, 1, (char *)"", (char *)"SS", (SUBR) &JackoAudioInConnect::init_, 0, 0, }, { (char *)"JackoAudioIn", sizeof(JackoAudioIn), 0, 5, (char *)"a", (char *)"S", (SUBR) &JackoAudioIn::init_, 0, (SUBR) &JackoAudioIn::audio_, }, { (char *)"JackoAudioOutConnect", sizeof(JackoAudioOutConnect), 0, 1, (char *)"", (char *)"SS", (SUBR) &JackoAudioOutConnect::init_, 0, 0, }, { (char *)"JackoAudioOut", sizeof(JackoAudioOut), 0, 5, (char *)"", (char *)"Sa", (SUBR) &JackoAudioOut::init_, 0, (SUBR) &JackoAudioOut::audio_, }, { (char *)"JackoMidiInConnect", sizeof(JackoMidiInConnect), 0, 1, (char *)"", (char *)"SS", (SUBR) &JackoMidiInConnect::init_, 0, 0, }, { (char *)"JackoMidiOutConnect", sizeof(JackoMidiOutConnect), 0, 1, (char *)"", (char *)"SS", (SUBR) &JackoMidiOutConnect::init_, 0, 0, }, { (char *)"JackoMidiOut", sizeof(JackoMidiOut), 0, 3, (char *)"", (char *)"SkkkO", (SUBR) &JackoMidiOut::init_, (SUBR) &JackoMidiOut::kontrol_, 0, }, { (char *)"JackoNoteOut", sizeof(JackoNoteOut), 0, 3, (char *)"", (char *)"Siii", (SUBR) &JackoNoteOut::init_, (SUBR) &JackoNoteOut::kontrol_, 0 }, { (char *)"JackoTransport", sizeof(JackoTransport), 0, 3, (char *)"", (char *)"kO", // O defaults to 0. (SUBR) &JackoTransport::init_, (SUBR) &JackoTransport::kontrol_, 0 }, { 0, 0, 0, 0, 0, 0, (SUBR) 0, (SUBR) 0, (SUBR) 0 } }; PUBLIC int csoundModuleCreate(CSOUND *csound) { return 0; } PUBLIC int csoundModuleInit(CSOUND *csound) { OENTRY *ep = (OENTRY *)&(oentries[0]); int err = 0; while (ep->opname != 0) { err |= csound->AppendOpcode(csound, ep->opname, ep->dsblksiz, ep->flags, ep->thread, ep->outypes, ep->intypes, (int (*)(CSOUND *, void *)) ep->iopadr, (int (*)(CSOUND *, void *)) ep->kopadr, (int (*)(CSOUND *, void *)) ep->aopadr); ep++; } return err; } PUBLIC int csoundModuleDestroy(CSOUND *csound) { int result = OK; JackoState *jackoState = 0; csound::QueryGlobalPointer(csound, "jackoState", jackoState); if (jackoState) { delete jackoState; jackoState = 0; } return result; } } csound-6.10.0/Opcodes/jacko_test.csd000066400000000000000000000056151321653344700173250ustar00rootroot00000000000000 csound -m255 -M0 -+rtmidi=null -RWf --midi-key=4 --midi-velocity=5 -o jacko_test.wav ; Unit tests for the Jack opcodes. ; To do: ; -- Python score generator and client runner. sr = 48000 ksmps = 128 nchnls = 2 0dbfs = 1 JackoInit "default", "csound" ; To use ALSA midi ports, use "jackd -Xseq" ; and use "jack_lsp -A -c" or aliases from JackInfo, ; probably together with information from the sequencer, ; to figure out the damn port names. ; JackoMidiInConnect "alsa_pcm:in-131-0-Master", "midiin" JackoAudioInConnect "aeolus:out.L", "leftin" JackoAudioInConnect "aeolus:out.R", "rightin" JackoMidiOutConnect "midiout", "aeolus:Midi/in" ; Note that Jack enables audio to be output to a regular ; Csound soundfile and, at the same time, to a sound ; card in real time to the system client via Jack. JackoAudioOutConnect "leftout", "system:playback_1" JackoAudioOutConnect "rightout", "system:playback_2" JackoInfo ; Turning freewheeling on seems automatically ; to turn system playback off. This is good! JackoFreewheel 1 JackoOn alwayson "jackin" instr 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ichannel = p1 - 1 itime = p2 iduration = p3 ikey = p4 ivelocity = p5 JackoNoteOut "midiout", ichannel, ikey, ivelocity print itime, iduration, ichannel, ikey, ivelocity endin instr jackin ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; JackoTransport 3, 1.0 aleft JackoAudioIn "leftin" aright JackoAudioIn "rightin" ; Aeolus uses MIDI controller 98 to control stops. ; Only 1 data value byte is used, not the 2 data ; bytes often used with NRPNs. ; The format for control mode is 01mm0ggg: ; mm 10 to set stops, 0, ggg group (or Division, 0 based). ; The format for stop selection is 000bbbbb: ; bbbbb for button number (0 based). ; Mode to enable stops for Divison I: b1100010 (98 ; [this controller VALUE is a pure coincidence]). JackoMidiOut "midiout", 176, 0, 98, 98 ; Stops: Principal 8 (0), Principal 4 (1) , Flote 8 (8) , Flote 2 (10) JackoMidiOut "midiout", 176, 0, 98, 0 JackoMidiOut "midiout", 176, 0, 98, 1 JackoMidiOut "midiout", 176, 0, 98, 8 JackoMidiOut "midiout", 176, 0, 98, 10 ; Sends audio coming in from Aeolus out ; not only to the Jack system out (sound card), ; but also to the output soundfile. ; Note that in freewheeling mode, "leftout" ; and "rightout" simply go silent. JackoAudioOut "leftout", aleft JackoAudioOut "rightout", aright outs aright, aleft endin f 0 30 i 1 1 30 60 60 i 1 2 30 64 60 i 1 3 30 71 60 e 2 csound-6.10.0/Opcodes/linear_algebra.cpp000066400000000000000000005440231321653344700201400ustar00rootroot00000000000000/* linear_algebra.cpp: Copyright (C) 2008 by Michael Gogins This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /** * L I N E A R A L G E B R A O P C O D E S F O R C S O U N D * Michael Gogins * * These opcodes implement many linear algebra operations, * from scalar, vector, and matrix arithmetic up to * and including QR based eigenvalue decompositions. * The opcodes are designed for digital signal processing, * and of course other mathematical operations, * in the Csound orchestra language. * * The numerical implementation uses the gmm++ library * from http://home.gna.org/getfem/gmm_intro. * * NOTE: SDFT must be #defined in order to build and use these opcodes. * * For applications with f-sig variables, array arithmetic must be * performed only when the f-sig is "current," because f-rate * is some fraction of k-rate; currency can be determined with the * la_k_current_f opcode. * * For applications using assignments between real vectors and * a-rate variables, array arithmetic must be performed only when the * vectors are "current", because the size of the vector may be * some integral multiple of ksmps; currency can be determined * by means of the la_k_current_vr opcode. * * Linear Algebra Data Types * ------------------------- * * Mathematical Type Code Corresponding Csound Type or Types * ----------------- ---- ------------------------------------------------- * real scalar r i-rate or k-rate variable * complex scalar c pair of i-rate or k-rate variables, e.g. "kr, ki" * real vector vr i-rate variable holding address of array * a a-rate variable * t function table number * complex vector vc i-rate variable holding address of array * f fsig variable * real matrix mr i-rate variable holding address of array * complex matrix mc i-rate variable holding address of array * * All arrays are 0-based; the first index iterates rows to give columns, * the second index iterates columns to give elements. * * All arrays are general and dense; banded, Hermitian, symmetric * and sparse routines are not implemented. * * An array can be of type code vr, vc, mr, or mc * and is stored in an i-rate object. * In orchestra code, an array is passed as a * MYFLT i-rate variable that contains the address * of the array object, which is actually stored * in the allocator opcode instance. * Although array variables are i-rate, of course * their values and even shapes may change at i-rate or k-rate. * * All operands must be pre-allocated; except for the creation * opcodes, no opcode ever allocates any arrays. * This is true even if the array appears on the * left-hand side of an opcode! However, some operations * may reshape arrays to hold results. * * Arrays are automatically deallocated when their instrument * is deallocated. * * Not only for more efficient performance, * but also to make it easier to remember opcode names, * the performance rate, output value types, operation names, * and input value types are deterministically * encoded into the opcode name: * 1. "la" for "linear algebra opcode family". * 2. "i" or "k" for performance rate. * 3. Type code(s) (see above table) for output value(s), * but only if the type is not implicit from the input values. * 4. Operation name: common mathematical name * (preferred) or abbreviation. * 5. Type code(s) for input values, if not implicit. * * For details, see the gmm++ documentation at * http://download.gna.org/getfem/doc/gmmuser.pdf. * * Array Creation * -------------- * * ivr la_i_vr_create irows * ivc la_i_vc_create irows * imr la_i_mr_create irows, icolumns [, odiagonal] * imc la_i_mc_create irows, icolumns [, odiagonal_r, odiagonal_i] * * Array Introspection * ------------------- * * irows la_i_size_vr ivr * irows la_i_size_vc ivc * irows, icolumns la_i_size_mr imr * irows, icolumns la_i_size_mc imc * * kfiscurrent la_k_current_f fsig * kvriscurrent la_k_current_vr ivr * * la_i_print_vr ivr * la_i_print_vc ivc * la_i_print_mr imr * la_i_print_mc imc * * Array Assignment and Conversion * ------------------------------- * * ivr la_i_assign_vr ivr * ivr la_k_assign_vr ivr * ivc la_i_assign_vc ivc * ivc la_k_assign_vc ivr * imr la_i_assign_mr imr * imr la_k_assign_mr imr * imc la_i_assign_mc imc * imc la_k_assign_mc imr * * NOTE: Assignments from tables or fsigs will resize vectors. * Assignments to or from asigs are incremental -- ksmps * frames are copied each kperiod and the array index * wraps around as required. * * ivr la_k_assign_a asig * ivr la_i_assign_t itablenumber * ivr la_k_assign_t itablenumber * ivc la_k_assign_f fsig * * asig la_k_a_assign ivr * itablenum la_i_t_assign ivr * itablenum la_k_t_assign ivr * fsig la_k_f_assign ivc * * Fill Arrays with Random Elements * -------------------------------- * * ivr la_i_random_vr [ifill_fraction] * ivr la_k_random_vr [kfill_fraction] * ivc la_i_random_vc [ifill_fraction] * ivc la_k_random_vc [kfill_fraction] * imr la_i_random_mr [ifill_fraction] * imr la_k_random_mr [kfill_fraction] * imc la_i_random_mc [ifill_fraction] * imc la_k_random_mc [kfill_fraction] * * Array Element Access * -------------------- * * ivr la_i_vr_set irow, ivalue * kvr la_k_vr_set krow, kvalue * ivc la_i_vc_set irow, ivalue_r, ivalue_i * kvc la_k_vc_set krow, kvalue_r, kvalue_i * imr la_i mr_set irow, icolumn, ivalue * kmr la_k mr_set krow, kcolumn, ivalue * imc la_i_mc_set irow, icolumn, ivalue_r, ivalue_i * kmc la_k_mc_set krow, kcolumn, kvalue_r, kvalue_i * * ivalue la_i_get_vr ivr, irow * kvalue la_k_get_vr ivr, krow, * ivalue_r, ivalue_i la_i_get_vc ivc, irow * kvalue_r, kvalue_i la_k_get_vc ivc, krow * ivalue la_i_get_mr imr, irow, icolumn * kvalue la_k_get_mr imr, krow, kcolumn * ivalue_r, ivalue_i la_i_get_mc imc, irow, icolumn * kvalue_r, kvalue_i la_k_get_mc imc, krow, kcolumn * * Single Array Operations * ----------------------- * * imr la_i_transpose_mr imr * imr la_k_transpose_mr imr * imc la_i_transpose_mc imc * imc la_k_transpose_mc imc * ivr la_i_conjugate_vr ivr * ivr la_k_conjugate_vr ivr * ivc la_i_conjugate_vc ivc * ivc la_k_conjugate_vc ivc * imr la_i_conjugate_mr imr * imr la_k_conjugate_mr imr * imc la_i_conjugate_mc imc * imc la_k_conjugate_mc imc * * Scalar Operations * ----------------- * * ir la_i_norm1_vr ivr * kr la_k_norm1_vr ivc * ir la_i_norm1_vc ivc * kr la_k_norm1_vc ivc * ir la_i_norm1_mr imr * kr la_k_norm1_mr imr * ir la_i_norm1_mc imc * kr la_k_norm1_mc imc * * ir la_i_norm_euclid_vr ivr * kr la_k_norm_euclid_vr ivr * ir la_i_norm_euclid_vc ivc * kr la_k_norm_euclid_vc ivc * ir la_i_norm_euclid_mr mvr * kr la_k_norm_euclid_mr mvr * ir la_i_norm_euclid_mc mvc * kr la_k_norm_euclid_mc mvc * * ir la_i_distance_vr ivr * kr la_k_distance_vr ivr * ir la_i_distance_vc ivc * kr la_k_distance_vc ivc * * ir la_i_norm_max imr * kr la_k_norm_max imc * ir la_i_norm_max imr * kr la_k_norm_max imc * * ir la_i_norm_inf_vr ivr * kr la_k_norm_inf_vr ivr * ir la_i_norm_inf_vc ivc * kr la_k_norm_inf_vc ivc * ir la_i_norm_inf_mr imr * kr la_k_norm_inf_mr imr * ir la_i_norm_inf_mc imc * kr la_k_norm_inf_mc imc * * ir la_i_trace_mr imr * kr la_k_trace_mr imr * ir, ii la_i_trace_mc imc * kr, ki la_k_trace_mc imc * * ir la_i_lu_det imr * kr la_k_lu_det imr * ir la_i_lu_det imc * kr la_k_lu_det imc * * Elementwise Array-Array Operations * ---------------------------------- * * ivr la_i_add_vr ivr_a, ivr_b * ivc la_k_add_vc ivc_a, ivc_b * imr la_i_add_mr imr_a, imr_b * imc la_k_add_mc imc_a, imc_b * * ivr la_i_subtract_vr ivr_a, ivr_b * ivc la_k_subtract_vc ivc_a, ivc_b * imr la_i_subtract_mr imr_a, imr_b * imc la_k_subtract_mc imc_a, imc_b * * ivr la_i_multiply_vr ivr_a, ivr_b * ivc la_k_multiply_vc ivc_a, ivc_b * imr la_i_multiply_mr imr_a, imr_b * imc la_k_multiply_mc imc_a, imc_b * * ivr la_i_divide_vr ivr_a, ivr_b * ivc la_k_divide_vc ivc_a, ivc_b * imr la_i_divide_mr imr_a, imr_b * imc la_k_divide_mc imc_a, imc_b * * Inner Products * -------------- * * ir la_i_dot_vr ivr_a, ivr_b * kr la_k_dot_vr ivr_a, ivr_b * ir, ii la_i_dot_vc ivc_a, ivc_b * kr, ki la_k_dot_vc ivc_a, ivc_b * * imr la_i_dot_mr imr_a, imr_b * imr la_k_dot_mr imr_a, imr_b * imc la_i_dot_mc imc_a, imc_b * imc la_k_dot_mc imc_a, imc_b * * ivr la_i_dot_mr_vr imr_a, ivr_b * ivr la_k_dot_mr_vr imr_a, ivr_b * ivc la_i_dot_mc_vc imc_a, ivc_b * ivc la_k_dot_mc_vc imc_a, ivc_b * * Matrix Inversion * ---------------- * * imr, icondition la_i_invert_mr imr * imr, kcondition la_k_invert_mr imr * imc, icondition la_i_invert_mc imc * imc, kcondition la_k_invert_mc imc * * Matrix Decompositions and Solvers * --------------------------------- * * ivr la_i_upper_solve_mr imr [, j_1_diagonal] * ivr la_k_upper_solve_mr imr [, j_1_diagonal] * ivc la_i_upper_solve_mc imc [, j_1_diagonal] * ivc la_k_upper_solve_mc imc [, j_1_diagonal] * * ivr la_i_lower_solve_mr imr [, j_1_diagonal] * ivr la_k_lower_solve_mr imr [, j_1_diagonal] * ivc la_i_lower_solve_mc imc [, j_1_diagonal] * ivc la_k_lower_solve_mc imc [, j_1_diagonal] * * imr, ivr_pivot, isize la_i_lu_factor_mr imr * imr, ivr_pivot, ksize la_k_lu_factor_mr imr * imc, ivr_pivot, isize la_i_lu_factor_mc imc * imc, ivr_pivot, ksize la_k_lu_factor_mc imc * * ivr_x la_i_lu_solve_mr imr, ivr_b * ivr_x la_k_lu_solve_mr imr, ivr_b * ivc_x la_i_lu_solve_mc imc, ivc_b * ivc_x la_k_lu_solve_mc imc, ivc_b * * imr_q, imr_r la_i_qr_factor_mr imr * imr_q, imr_r la_k_qr_factor_mr imr * imc_q, imc_r la_i_qr_factor_mc imc * imc_q, imc_r la_k_qr_factor_mc imc * * ivr_eig_vals la_i_qr_eigen_mr imr, i_tolerance * ivr_eig_vals la_k_qr_eigen_mr imr, k_tolerance * ivr_eig_vals la_i_qr_eigen_mc imc, i_tolerance * ivr_eig_vals la_k_qr_eigen_mc imc, k_tolerance * * NOTE: Matrix must be Hermitian in order to compute eigenvectors. * * ivr_eig_vals, imr_eig_vecs la_i_qr_sym_eigen_mr imr, i_tolerance * ivr_eig_vals, imr_eig_vecs la_k_qr_sym_eigen_mr imr, k_tolerance * ivc_eig_vals, imc_eig_vecs la_i_qr_sym_eigen_mc imc, i_tolerance * ivc_eig_vals, imc_eig_vecs la_k_qr_sym_eigen_mc imc, k_tolerance * */ extern "C" { // a-rate, k-rate, FUNC, SPECDAT #include // PVSDAT #include } #ifdef ST #undef ST #endif #ifdef WR #undef WR #endif #include #include #include #include #include using namespace csound; static std::ostream &operator <<(std::ostream &o, const std::vector& m) { gmm::write(o,m); return o; } static std::ostream &operator <<(std::ostream &o, const std::vector< std::complex >& m) { gmm::write(o,m); return o; } /** * Template union for safely and efficiently * typecasting the value of a MYFLT variable * to the address of an array, and vice versa. */ template struct ArrayCaster { union { A* a; F f; }; }; /** * Safely and efficiently typecast the address * of an array to the value of a MYFLT variable. */ template void tof(A *a, F *f) { ArrayCaster arrayCaster; arrayCaster.a = a; *f = arrayCaster.f; }; /** * Safely and efficiently typecast the value of a * a MYFLT variable to the address of an array. */ template void toa(F *f, A *&a) { ArrayCaster arrayCaster; arrayCaster.f = *f; a = arrayCaster.a; }; class la_i_vr_create_t : public OpcodeNoteoffBase { public: MYFLT *i_vr; MYFLT *i_rows; std::vector vr; int init(CSOUND *) { vr.resize(size_t(*i_rows)); tof(this, i_vr); return OK; } int noteoff(CSOUND *) { vr.resize(0); return OK; } }; class la_i_vc_create_t : public OpcodeNoteoffBase { public: MYFLT *i_vc; MYFLT *i_rows; std::vector< std::complex > vc; int init(CSOUND *) { vc.resize(size_t(*i_rows)); tof(this, i_vc); return OK; } int noteoff(CSOUND *) { vc.resize(0); return OK; } }; class la_i_mr_create_t : public OpcodeNoteoffBase { public: MYFLT *i_mr; MYFLT *i_rows; MYFLT *i_columns; MYFLT *o_diagonal; gmm::dense_matrix mr; int init(CSOUND *) { gmm::resize(mr, size_t(*i_rows), size_t(*i_columns)); if (*o_diagonal) { for (size_t i = 0, n = size_t(*i_rows); i < n; ++i) { mr(i, i) = *o_diagonal; } } tof(this, i_mr); return OK; } int noteoff(CSOUND *) { mr.resize(0, 0); return OK; } }; class la_i_mc_create_t : public OpcodeNoteoffBase { public: MYFLT *i_mc; MYFLT *i_rows; MYFLT *i_columns; MYFLT *o_diagonal_r; MYFLT *o_diagonal_i; gmm::dense_matrix< std::complex > mc; int init(CSOUND *) { gmm::resize(mc, size_t(*i_rows), size_t(*i_columns)); if (*o_diagonal_r || *o_diagonal_i) { for (size_t i = 0, n = size_t(*i_rows); i < n; ++i) { mc(i, i) = std::complex(*o_diagonal_r, *o_diagonal_i); } } tof(this, i_mc); return OK; } int noteoff(CSOUND *) { mc.resize(0, 0); return OK; } }; class la_i_size_vr_t : public OpcodeBase { public: MYFLT *i_size; MYFLT *i_vr; int init(CSOUND *) { la_i_vr_create_t *array = 0; toa(i_vr, array); *i_size = (MYFLT) gmm::vect_size(array->vr); return OK; } }; class la_i_size_vc_t : public OpcodeBase { public: MYFLT *i_size; MYFLT *i_vc; int init(CSOUND *) { la_i_vc_create_t *array = 0; toa(i_vc, array); *i_size = (MYFLT) gmm::vect_size(array->vc); return OK; } }; class la_i_size_mr_t : public OpcodeBase { public: MYFLT *i_rows; MYFLT *i_columns; MYFLT *i_mr; int init(CSOUND *) { la_i_mr_create_t *array = 0; toa(i_mr, array); *i_rows = (MYFLT) gmm::mat_nrows(array->mr); *i_columns = (MYFLT) gmm::mat_ncols(array->mr); return OK; } }; class la_i_size_mc_t : public OpcodeBase { public: MYFLT *i_rows; MYFLT *i_columns; MYFLT *i_mc; int init(CSOUND *) { la_i_mc_create_t *array = 0; toa(i_mc, array); *i_rows = (MYFLT) gmm::mat_nrows(array->mc); *i_columns = (MYFLT) gmm::mat_ncols(array->mc); return OK; } }; /** * Return 1 if the input f-sig is current * (i.e., if its value might change in the next kperiod); * return 0 if the input f-sig is not current. * * Example: * * kcurrent la_k_current_f fsig * if (kcurrent == 1.0) then * ; arithmetic on fsig here... * endif */ class la_k_current_f_t : public OpcodeBase { public: MYFLT *k_current; PVSDAT *f_sig; size_t last_frame; int init(CSOUND *) { last_frame = f_sig->framecount; return OK; } int kontrol(CSOUND *) { if (last_frame < f_sig->framecount) { last_frame = f_sig->framecount; *k_current = 1.0; } else { *k_current = 0.0; } return OK; } }; /** * Return 1 if the real vector is current (i.e., its * current index equals 0); return 0 if the input * real vector is not current. A real vector is current * in the very first kperiod of performance, * and at each subsequent kperiod where ksmps has * accumulated past the end of the vector and * has wrapped back to index 0. For this to be * possible, the size of the vector must be an integral * multiple of ksmps. * * Example: * * ; FIRST, assignments from a-rate variables to vectors. * kcurrent la_k_current_vr ivr * if (kcurrent == 1.0) then * ; SECOND, arithmetic with current vectors. * endif * ; THIRD, assignments from vectors to a-rate variables. */ class la_k_current_vr_t : public OpcodeBase { public: MYFLT *k_current; MYFLT *rhs_ivr; la_i_vr_create_t *rhs; size_t ksmps; size_t vector_size; int init(CSOUND *csound) { rhs = 0; toa(rhs_ivr, rhs); ksmps = opds.insdshead->ksmps; vector_size = gmm::vect_size(rhs->vr); return OK; } int kontrol(CSOUND *csound) { size_t frame_count = opds.insdshead->kcounter * ksmps; size_t index = frame_count % vector_size; if (index == 0) { *k_current = 1.0; } else { *k_current = 0.0; } return OK; } }; class la_i_print_vr_t : public OpcodeBase { public: MYFLT *i_vr; int init(CSOUND *csound) { la_i_vr_create_t *array = 0; toa(i_vr, array); std::ostringstream stream; stream << array->vr << std::endl; csound->Message(csound, stream.str().c_str()); return OK; } }; class la_i_print_vc_t : public OpcodeBase { public: MYFLT *i_vc; int init(CSOUND *csound) { la_i_vc_create_t *array = 0; toa(i_vc, array); std::ostringstream stream; stream << array->vc << std::endl; csound->Message(csound, stream.str().c_str()); return OK; } }; class la_i_print_mr_t : public OpcodeBase { public: MYFLT *i_mr; int init(CSOUND *csound) { la_i_mr_create_t *array = 0; toa(i_mr, array); std::ostringstream stream; stream << array->mr << std::endl; csound->Message(csound, stream.str().c_str()); return OK; } }; class la_i_print_mc_t : public OpcodeBase { public: MYFLT *i_mc; int init(CSOUND *csound) { la_i_mc_create_t *array = 0; toa(i_mc, array); std::ostringstream stream; stream << array->mc << std::endl; csound->Message(csound, stream.str().c_str()); return OK; } }; class la_i_assign_vr_t : public OpcodeBase { public: MYFLT *i_vr_lhs; MYFLT *i_vr_rhs; la_i_vr_create_t *lhs; la_i_vr_create_t *rhs; int init(CSOUND *csound) { toa(i_vr_lhs, lhs); toa(i_vr_rhs, rhs); gmm::copy(rhs->vr, lhs->vr); return OK; } }; class la_k_assign_vr_t : public OpcodeBase { public: MYFLT *i_vr_lhs; MYFLT *i_vr_rhs; la_i_vr_create_t *lhs; la_i_vr_create_t *rhs; int init(CSOUND *csound) { toa(i_vr_lhs, lhs); toa(i_vr_rhs, rhs); return OK; } int kontrol(CSOUND *csound) { gmm::copy(rhs->vr, lhs->vr); return OK; } }; class la_i_assign_vc_t : public OpcodeBase { public: MYFLT *i_vc_lhs; MYFLT *i_vc_rhs; la_i_vc_create_t *lhs; la_i_vc_create_t *rhs; int init(CSOUND *csound) { toa(i_vc_lhs, lhs); toa(i_vc_rhs, rhs); gmm::copy(rhs->vc, lhs->vc); return OK; } }; class la_k_assign_vc_t : public OpcodeBase { public: MYFLT *i_vc_lhs; MYFLT *i_vc_rhs; la_i_vc_create_t *lhs; la_i_vc_create_t *rhs; int init(CSOUND *csound) { toa(i_vc_lhs, lhs); toa(i_vc_rhs, rhs); return OK; } int kontrol(CSOUND *csound) { gmm::copy(rhs->vc, lhs->vc); return OK; } }; class la_i_assign_mr_t : public OpcodeBase { public: MYFLT *i_mr_lhs; MYFLT *i_mr_rhs; la_i_mr_create_t *lhs; la_i_mr_create_t *rhs; int init(CSOUND *csound) { toa(i_mr_lhs, lhs); toa(i_mr_rhs, rhs); gmm::copy(rhs->mr, lhs->mr); return OK; } }; class la_k_assign_mr_t : public OpcodeBase { public: MYFLT *i_mr_lhs; MYFLT *i_mr_rhs; la_i_mr_create_t *lhs; la_i_mr_create_t *rhs; int init(CSOUND *csound) { toa(i_mr_lhs, lhs); toa(i_mr_rhs, rhs); return OK; } int kontrol(CSOUND *csound) { gmm::copy(rhs->mr, lhs->mr); return OK; } }; class la_i_assign_mc_t : public OpcodeBase { public: MYFLT *i_mc_lhs; MYFLT *i_mc_rhs; la_i_mc_create_t *lhs; la_i_mc_create_t *rhs; int init(CSOUND *csound) { toa(i_mc_lhs, lhs); toa(i_mc_rhs, rhs); gmm::copy(rhs->mc, lhs->mc); return OK; } }; class la_k_assign_mc_t : public OpcodeBase { public: MYFLT *i_mc_lhs; MYFLT *i_mc_rhs; la_i_mc_create_t *lhs; la_i_mc_create_t *rhs; int init(CSOUND *csound) { toa(i_mc_lhs, lhs); toa(i_mc_rhs, rhs); return OK; } int kontrol(CSOUND *csound) { gmm::copy(rhs->mc, lhs->mc); return OK; } }; class la_k_assign_a_t : public OpcodeBase { public: MYFLT *i_vr; MYFLT *a_a; la_i_vr_create_t *lhs; size_t ksmps; size_t vector_size; int init(CSOUND *csound) { toa(i_vr, lhs); ksmps = opds.insdshead->ksmps; vector_size = gmm::vect_size(lhs->vr); return OK; } int kontrol(CSOUND *csound) { uint32_t offset = opds.insdshead->ksmps_offset; uint32_t early = opds.insdshead->ksmps_no_end; size_t frame_count = opds.insdshead->ksmps * ksmps; size_t array_i = frame_count % vector_size; if (UNLIKELY(early)) ksmps -= early; for (size_t i = offset; i < ksmps; ++i, ++array_i) { lhs->vr[array_i] = a_a[i]; } return OK; } }; class la_i_assign_t_t : public OpcodeBase { public: MYFLT *i_vr; MYFLT *i_tablenumber; la_i_vr_create_t *lhs; int tablenumber; int n; int init(CSOUND *csound) { toa(i_vr, lhs); tablenumber = int(std::floor(*i_tablenumber)); n = csound->TableLength(csound, tablenumber); gmm::resize(lhs->vr, n); for (int i = 0; i < n; ++i) { lhs->vr[i] = csound->TableGet(csound, tablenumber, i); } return OK; } }; class la_k_assign_t_t : public OpcodeBase { public: MYFLT *i_vr; MYFLT *i_tablenumber; la_i_vr_create_t *lhs; int tablenumber; int n; int init(CSOUND *csound) { toa(i_vr, lhs); tablenumber = int(std::floor(*i_tablenumber)); n = csound->TableLength(csound, tablenumber); gmm::resize(lhs->vr, n); return OK; } int kontrol(CSOUND *csound) { for (int i = 0; i < n; ++i) { lhs->vr[i] = csound->TableGet(csound, tablenumber, i); } return OK; } }; class la_k_assign_f_t : public OpcodeBase { public: MYFLT *i_vc; PVSDAT *f_fsig; la_i_vc_create_t *lhs; int n; std::complex *f; int init(CSOUND *csound) { toa(i_vc, lhs); n = f_fsig->N; // std::complex has the same layout as CMPLX. f = (std::complex *)f_fsig->frame.auxp; gmm::resize(lhs->vc, n); return OK; } int kontrol(CSOUND *csound) { for (int i = 0; i < n; ++i) { lhs->vc[i] = f[i]; } return OK; } }; class la_k_a_assign_t : public OpcodeBase { public: MYFLT *a_a; MYFLT *i_vr; la_i_vr_create_t *rhs; size_t ksmps; int init(CSOUND *csound) { toa(i_vr, rhs); ksmps = opds.insdshead->ksmps; return OK; } int kontrol(CSOUND *csound) { uint32_t offset = opds.insdshead->ksmps_offset; uint32_t early = opds.insdshead->ksmps_no_end; memset(a_a, '\0', offset*sizeof(MYFLT)); size_t frameCount = opds.insdshead->kcounter * opds.insdshead->ksmps; size_t vectorSize = gmm::vect_size(rhs->vr); size_t array_i = frameCount % vectorSize; if (UNLIKELY(early)) ksmps -= early; for (size_t i = 0; i < ksmps; ++i, ++array_i) { a_a[i] = rhs->vr[array_i]; } return OK; } }; class la_i_t_assign_t : public OpcodeBase { public: MYFLT *i_tablenumber; MYFLT *i_vr; la_i_vr_create_t *rhs; int tablenumber; int n; int init(CSOUND *csound) { toa(i_vr, rhs); tablenumber = int(std::floor(*i_tablenumber)); n = csound->TableLength(csound, tablenumber); gmm::resize(rhs->vr, n); for (int i = 0; i < n; ++i) { csound->TableSet(csound, tablenumber, i, rhs->vr[i]); } return OK; } }; class la_k_t_assign_t : public OpcodeBase { public: MYFLT *i_tablenumber; MYFLT *i_vr; la_i_vr_create_t *rhs; int tablenumber; int n; int init(CSOUND *csound) { toa(i_vr, rhs); tablenumber = int(std::floor(*i_tablenumber)); n = csound->TableLength(csound, tablenumber); gmm::resize(rhs->vr, n); return OK; } int kontrol(CSOUND *csound) { for (int i = 0; i < n; ++i) { csound->TableSet(csound, tablenumber, i, rhs->vr[i]); } return OK; } }; class la_k_f_assign_t : public OpcodeBase { public: PVSDAT *f_fsig; MYFLT *i_vc; la_i_vc_create_t *rhs; int n; std::complex *f; int init(CSOUND *csound) { toa(i_vc, rhs); n = f_fsig->N; // std::complex has the same layout as CMPLX. f = (std::complex *)f_fsig->frame.auxp; gmm::resize(rhs->vc, n); return OK; } int kontrol(CSOUND *csound) { for (int i = 0; i < n; ++i) { f[i] = rhs->vc[i]; } return OK; } }; class la_i_random_vr_t : public OpcodeBase { public: MYFLT *i_vr_lhs; MYFLT *i_fraction; la_i_vr_create_t *lhs; int init(CSOUND *csound) { toa(i_vr_lhs, lhs); gmm::fill_random(lhs->vr, *i_fraction); return OK; } }; class la_k_random_vr_t : public OpcodeBase { public: MYFLT *i_vr_lhs; MYFLT *i_fraction; la_i_vr_create_t *lhs; int init(CSOUND *csound) { toa(i_vr_lhs, lhs); return OK; } int kontrol(CSOUND *csound) { gmm::fill_random(lhs->vr, *i_fraction); return OK; } }; class la_i_random_vc_t : public OpcodeBase { public: MYFLT *i_vc_lhs; MYFLT *i_fraction; la_i_vc_create_t *lhs; int init(CSOUND *csound) { toa(i_vc_lhs, lhs); gmm::fill_random(lhs->vc, *i_fraction); return OK; } }; class la_k_random_vc_t : public OpcodeBase { public: MYFLT *i_vc_lhs; MYFLT *i_fraction; la_i_vc_create_t *lhs; int init(CSOUND *csound) { toa(i_vc_lhs, lhs); return OK; } int kontrol(CSOUND *csound) { gmm::fill_random(lhs->vc, *i_fraction); return OK; } }; class la_i_random_mr_t : public OpcodeBase { public: MYFLT *i_mr_lhs; MYFLT *i_fraction; la_i_mr_create_t *lhs; int init(CSOUND *csound) { toa(i_mr_lhs, lhs); gmm::fill_random(lhs->mr, *i_fraction); return OK; } }; class la_k_random_mr_t : public OpcodeBase { public: MYFLT *i_mr_lhs; MYFLT *i_fraction; la_i_mr_create_t *lhs; int init(CSOUND *csound) { toa(i_mr_lhs, lhs); return OK; } int kontrol(CSOUND *csound) { gmm::fill_random(lhs->mr, *i_fraction); return OK; } }; class la_i_random_mc_t : public OpcodeBase { public: MYFLT *i_mc_lhs; MYFLT *i_fraction; la_i_mc_create_t *lhs; int init(CSOUND *csound) { toa(i_mc_lhs, lhs); gmm::fill_random(lhs->mc, *i_fraction); return OK; } }; class la_k_random_mc_t : public OpcodeBase { public: MYFLT *i_mc_lhs; MYFLT *i_fraction; la_i_mc_create_t *lhs; int init(CSOUND *csound) { toa(i_mc_lhs, lhs); return OK; } int kontrol(CSOUND *csound) { gmm::fill_random(lhs->mc, *i_fraction); return OK; } }; class la_i_vr_set_t : public OpcodeBase { public: MYFLT *i_vr; MYFLT *i_row; MYFLT *i_value; la_i_vr_create_t *vr; int init(CSOUND *) { toa(i_vr, vr); vr->vr[size_t(*i_row)] = *i_value; return OK; } }; class la_k_vr_set_t : public OpcodeBase { public: MYFLT *i_vr; MYFLT *k_row; MYFLT *k_value; la_i_vr_create_t *vr; int init(CSOUND *) { toa(i_vr, vr); return OK; } int kontrol(CSOUND *) { vr->vr[size_t(*k_row)] = *k_value; return OK; } }; class la_i_vc_set_t : public OpcodeBase { public: MYFLT *i_vc; MYFLT *i_row; MYFLT *i_value_r; MYFLT *i_value_i; la_i_vc_create_t *vc; int init(CSOUND *) { toa(i_vc, vc); vc->vc[size_t(*i_row)] = std::complex(*i_value_r, *i_value_i); return OK; } }; class la_k_vc_set_t : public OpcodeBase { public: MYFLT *i_vc; MYFLT *k_row; MYFLT *k_value_r; MYFLT *k_value_i; la_i_vc_create_t *vc; int init(CSOUND *) { toa(i_vc, vc); return OK; } int kontrol(CSOUND *) { vc->vc[size_t(*k_row)] = std::complex(*k_value_r, *k_value_i); return OK; } }; class la_i_mr_set_t : public OpcodeBase { public: MYFLT *i_mr; MYFLT *i_row; MYFLT *i_column; MYFLT *i_value; la_i_mr_create_t *mr; int init(CSOUND *) { toa(i_mr, mr); mr->mr(size_t(*i_row), size_t(*i_column)) = *i_value; return OK; } }; class la_k_mr_set_t : public OpcodeBase { public: MYFLT *i_mr; MYFLT *k_row; MYFLT *k_column; MYFLT *k_value; la_i_mr_create_t *mr; int init(CSOUND *) { toa(i_mr, mr); return OK; } int kontrol(CSOUND *) { mr->mr(size_t(*k_row), size_t(*k_column)) = *k_value; return OK; } }; class la_i_mc_set_t : public OpcodeBase { public: MYFLT *i_mc; MYFLT *i_row; MYFLT *i_column; MYFLT *i_value_r; MYFLT *i_value_i; la_i_mc_create_t *mc; int init(CSOUND *) { toa(i_mc, mc); mc->mc(size_t(*i_row), size_t(*i_column)) = std::complex(*i_value_r, *i_value_i); return OK; } }; class la_k_mc_set_t : public OpcodeBase { public: MYFLT *i_mc; MYFLT *k_row; MYFLT *k_column; MYFLT *k_value_r; MYFLT *k_value_i; la_i_mc_create_t *mc; int init(CSOUND *) { toa(i_mc, mc); return OK; } int kontrol(CSOUND *) { mc->mc(size_t(*k_row), size_t(*k_column)) = std::complex(*k_value_r, *k_value_i); return OK; } }; class la_i_get_vr_t : public OpcodeBase { public: MYFLT *i_value; MYFLT *i_vr; MYFLT *i_row; la_i_vr_create_t *vr; int init(CSOUND *) { toa(i_vr, vr); *i_value = vr->vr[size_t(*i_row)]; return OK; } }; class la_k_get_vr_t : public OpcodeBase { public: MYFLT *k_value; MYFLT *i_vr; MYFLT *k_row; la_i_vr_create_t *vr; int init(CSOUND *) { toa(i_vr, vr); return OK; } int kontrol(CSOUND *) { *k_value = vr->vr[size_t(*k_row)]; return OK; } }; class la_i_get_vc_t : public OpcodeBase { public: MYFLT *i_value_r; MYFLT *i_value_i; MYFLT *i_vc; MYFLT *i_row; la_i_vc_create_t *vc; int init(CSOUND *) { toa(i_vc, vc); const std::complex &lhs = vc->vc[size_t(*i_row)]; *i_value_r = lhs.real(); *i_value_i = lhs.imag(); return OK; } }; class la_k_get_vc_t : public OpcodeBase { public: MYFLT *k_value_r; MYFLT *k_value_i; MYFLT *i_vc; MYFLT *k_row; la_i_vc_create_t *vc; int init(CSOUND *) { toa(i_vc, vc); return OK; } int kontrol(CSOUND *) { const std::complex &lhs = vc->vc[size_t(*k_row)]; *k_value_r = lhs.real(); *k_value_i = lhs.imag(); return OK; } }; class la_i_get_mr_t : public OpcodeBase { public: MYFLT *i_value; MYFLT *i_mr; MYFLT *i_row; MYFLT *i_column; la_i_mr_create_t *mr; int init(CSOUND *) { toa(i_mr, mr); *i_value = mr->mr(size_t(*i_row), size_t(*i_column)); return OK; } }; class la_k_get_mr_t : public OpcodeBase { public: MYFLT *k_value; MYFLT *i_mr; MYFLT *k_row; MYFLT *k_column; la_i_mr_create_t *mr; int init(CSOUND *) { toa(i_mr, mr); return OK; } int kontrol(CSOUND *) { *k_value = mr->mr(size_t(*k_row), size_t(*k_column)); return OK; } }; class la_i_get_mc_t : public OpcodeBase { public: MYFLT *i_value_r; MYFLT *i_value_i; MYFLT *i_mc; MYFLT *i_row; MYFLT *i_column; la_i_mc_create_t *mc; int init(CSOUND *) { toa(i_mc, mc); const std::complex &lhs = mc->mc(size_t(*i_row), size_t(*i_column)); *i_value_r = lhs.real(); *i_value_i = lhs.imag(); return OK; } }; class la_k_get_mc_t : public OpcodeBase { public: MYFLT *k_value_r; MYFLT *k_value_i; MYFLT *i_mc; MYFLT *k_row; MYFLT *k_column; la_i_mc_create_t *mc; int init(CSOUND *) { toa(i_mc, mc); return OK; } int kontrol(CSOUND *) { const std::complex &lhs = mc->mc(size_t(*k_row), size_t(*k_column)); *k_value_r = lhs.real(); *k_value_i = lhs.imag(); return OK; } }; class la_i_transpose_mr_t : public OpcodeBase { public: MYFLT *imr_lhs; MYFLT *imr_rhs; la_i_mr_create_t *lhs; la_i_mr_create_t *rhs; int init(CSOUND *) { toa(imr_lhs, lhs); toa(imr_rhs, rhs); gmm::copy(gmm::transposed(rhs->mr), lhs->mr); return OK; } }; class la_k_transpose_mr_t : public OpcodeBase { public: MYFLT *imr_lhs; MYFLT *imr_rhs; la_i_mr_create_t *lhs; la_i_mr_create_t *rhs; int init(CSOUND *) { toa(imr_lhs, lhs); toa(imr_rhs, rhs); return OK; } int kontrol(CSOUND *) { gmm::copy(gmm::transposed(rhs->mr), lhs->mr); return OK; } }; class la_i_transpose_mc_t : public OpcodeBase { public: MYFLT *imc_lhs; MYFLT *imc_rhs; la_i_mc_create_t *lhs; la_i_mc_create_t *rhs; int init(CSOUND *) { toa(imc_lhs, lhs); toa(imc_rhs, rhs); gmm::copy(gmm::transposed(rhs->mc), lhs->mc); return OK; } }; class la_k_transpose_mc_t : public OpcodeBase { public: MYFLT *imc_lhs; MYFLT *imc_rhs; la_i_mc_create_t *lhs; la_i_mc_create_t *rhs; int init(CSOUND *) { toa(imc_lhs, lhs); toa(imc_rhs, rhs); return OK; } int kontrol(CSOUND *) { gmm::copy(gmm::transposed(rhs->mc), lhs->mc); return OK; } }; class la_i_conjugate_vr_t : public OpcodeBase { public: MYFLT *ivr_lhs; MYFLT *ivr_rhs; la_i_vr_create_t *lhs; la_i_vr_create_t *rhs; int init(CSOUND *) { toa(ivr_lhs, lhs); toa(ivr_rhs, rhs); gmm::copy(gmm::conjugated(rhs->vr), lhs->vr); return OK; } }; class la_k_conjugate_vr_t : public OpcodeBase { public: MYFLT *ivr_lhs; MYFLT *ivr_rhs; la_i_vr_create_t *lhs; la_i_vr_create_t *rhs; int init(CSOUND *) { toa(ivr_lhs, lhs); toa(ivr_rhs, rhs); return OK; } int kontrol(CSOUND *) { gmm::copy(gmm::conjugated(rhs->vr), lhs->vr); return OK; } }; class la_i_conjugate_vc_t : public OpcodeBase { public: MYFLT *ivc_lhs; MYFLT *ivc_rhs; la_i_vc_create_t *lhs; la_i_vc_create_t *rhs; int init(CSOUND *) { toa(ivc_lhs, lhs); toa(ivc_rhs, rhs); gmm::copy(gmm::conjugated(rhs->vc), lhs->vc); return OK; } }; class la_k_conjugate_vc_t : public OpcodeBase { public: MYFLT *ivc_lhs; MYFLT *ivc_rhs; la_i_vc_create_t *lhs; la_i_vc_create_t *rhs; int init(CSOUND *) { toa(ivc_lhs, lhs); toa(ivc_rhs, rhs); return OK; } int kontrol(CSOUND *) { gmm::copy(gmm::conjugated(rhs->vc), lhs->vc); return OK; } }; class la_i_conjugate_mr_t : public OpcodeBase { public: MYFLT *imr_lhs; MYFLT *imr_rhs; la_i_mr_create_t *lhs; la_i_mr_create_t *rhs; int init(CSOUND *) { toa(imr_lhs, lhs); toa(imr_rhs, rhs); gmm::copy(gmm::conjugated(rhs->mr), lhs->mr); return OK; } }; class la_k_conjugate_mr_t : public OpcodeBase { public: MYFLT *imr_lhs; MYFLT *imr_rhs; la_i_mr_create_t *lhs; la_i_mr_create_t *rhs; int init(CSOUND *) { toa(imr_lhs, lhs); toa(imr_rhs, rhs); return OK; } int kontrol(CSOUND *) { gmm::copy(gmm::conjugated(rhs->mr), lhs->mr); return OK; } }; class la_i_conjugate_mc_t : public OpcodeBase { public: MYFLT *imc_lhs; MYFLT *imc_rhs; la_i_mc_create_t *lhs; la_i_mc_create_t *rhs; int init(CSOUND *) { toa(imc_lhs, lhs); toa(imc_rhs, rhs); gmm::copy(gmm::conjugated(rhs->mc), lhs->mc); return OK; } }; class la_k_conjugate_mc_t : public OpcodeBase { public: MYFLT *imc_lhs; MYFLT *imc_rhs; la_i_mc_create_t *lhs; la_i_mc_create_t *rhs; int init(CSOUND *) { toa(imc_lhs, lhs); toa(imc_rhs, rhs); return OK; } int kontrol(CSOUND *) { gmm::copy(gmm::conjugated(rhs->mc), lhs->mc); return OK; } }; class la_i_norm1_vr_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_vr_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::vect_norm1(rhs->vr); return OK; } }; class la_k_norm1_vr_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_vr_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); return OK; } int kontrol(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::vect_norm1(rhs->vr); return OK; } }; class la_i_norm1_vc_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_vc_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::vect_norm1(rhs->vc); return OK; } }; class la_k_norm1_vc_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_vc_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); return OK; } int kontrol(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::vect_norm1(rhs->vc); return OK; } }; class la_i_norm1_mr_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_mr_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::mat_norm1(rhs->mr); return OK; } }; class la_k_norm1_mr_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_mr_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); return OK; } int kontrol(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::mat_norm1(rhs->mr); return OK; } }; class la_i_norm1_mc_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_mc_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::mat_norm1(rhs->mc); return OK; } }; class la_k_norm1_mc_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_mc_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); return OK; } int kontrol(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::mat_norm1(rhs->mc); return OK; } }; class la_i_norm_euclid_vr_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_vr_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::vect_norm2(rhs->vr); return OK; } }; class la_k_norm_euclid_vr_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_vr_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); return OK; } int kontrol(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::vect_norm2(rhs->vr); return OK; } }; class la_i_norm_euclid_vc_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_vc_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::vect_norm2(rhs->vc); return OK; } }; class la_k_norm_euclid_vc_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_vc_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); return OK; } int kontrol(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::vect_norm2(rhs->vc); return OK; } }; class la_i_norm_euclid_mr_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_mr_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::mat_euclidean_norm(rhs->mr); return OK; } }; class la_k_norm_euclid_mr_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_mr_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); return OK; } int kontrol(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::mat_euclidean_norm(rhs->mr); return OK; } }; class la_i_norm_euclid_mc_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_mc_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::mat_euclidean_norm(rhs->mc); return OK; } }; class la_k_norm_euclid_mc_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_mc_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); return OK; } int kontrol(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::mat_euclidean_norm(rhs->mc); return OK; } }; class la_i_distance_vr_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_1_; MYFLT *rhs_2_; la_i_vr_create_t *rhs_1; la_i_vr_create_t *rhs_2; int init(CSOUND *) { toa(rhs_1_, rhs_1); toa(rhs_2_, rhs_2); *lhs = gmm::vect_dist2(rhs_1->vr, rhs_2->vr); return OK; } }; class la_k_distance_vr_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_1_; MYFLT *rhs_2_; la_i_vr_create_t *rhs_1; la_i_vr_create_t *rhs_2; int init(CSOUND *) { toa(rhs_1_, rhs_1); toa(rhs_2_, rhs_2); return OK; } int kontrol(CSOUND *) { *lhs = gmm::vect_dist2(rhs_1->vr, rhs_2->vr); return OK; } }; class la_i_distance_vc_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_1_; MYFLT *rhs_2_; la_i_vc_create_t *rhs_1; la_i_vc_create_t *rhs_2; int init(CSOUND *) { toa(rhs_1_, rhs_1); toa(rhs_2_, rhs_2); *lhs = gmm::vect_dist2(rhs_1->vc, rhs_2->vc); return OK; } }; class la_k_distance_vc_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_1_; MYFLT *rhs_2_; la_i_vc_create_t *rhs_1; la_i_vc_create_t *rhs_2; int init(CSOUND *) { toa(rhs_1_, rhs_1); toa(rhs_2_, rhs_2); return OK; } int kontrol(CSOUND *) { *lhs = gmm::vect_dist2(rhs_1->vc, rhs_2->vc); return OK; } }; class la_i_norm_max_mr_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_mr_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::mat_maxnorm(rhs->mr); return OK; } }; class la_k_norm_max_mr_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_mr_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); return OK; } int kontrol(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::mat_maxnorm(rhs->mr); return OK; } }; class la_i_norm_max_mc_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_mc_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::mat_maxnorm(rhs->mc); return OK; } }; class la_k_norm_max_mc_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_mc_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); return OK; } int kontrol(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::mat_maxnorm(rhs->mc); return OK; } }; class la_i_norm_inf_vr_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_vr_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::vect_norminf(rhs->vr); return OK; } }; class la_k_norm_inf_vr_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_vr_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); return OK; } int kontrol(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::vect_norminf(rhs->vr); return OK; } }; class la_i_norm_inf_vc_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_vc_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::vect_norminf(rhs->vc); return OK; } }; class la_k_norm_inf_vc_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_vc_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); return OK; } int kontrol(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::vect_norminf(rhs->vc); return OK; } }; class la_i_norm_inf_mr_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_mr_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::mat_norminf(rhs->mr); return OK; } }; class la_k_norm_inf_mr_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_mr_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); return OK; } int kontrol(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::mat_norminf(rhs->mr); return OK; } }; class la_i_norm_inf_mc_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_mc_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::mat_norminf(rhs->mc); return OK; } }; class la_k_norm_inf_mc_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_mc_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); return OK; } int kontrol(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::mat_norminf(rhs->mc); return OK; } }; class la_i_trace_mr_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_mr_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::mat_trace(rhs->mr); return OK; } }; class la_k_trace_mr_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_mr_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); return OK; } int kontrol(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::mat_trace(rhs->mr); return OK; } }; class la_i_trace_mc_t : public OpcodeBase { public: MYFLT *lhs_r; MYFLT *lhs_i; MYFLT *rhs_; la_i_mc_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); const std::complex &lhs = gmm::mat_trace(rhs->mc); *lhs_r = lhs.real(); *lhs_i = lhs.imag(); return OK; } }; class la_k_trace_mc_t : public OpcodeBase { public: MYFLT *lhs_r; MYFLT *lhs_i; MYFLT *rhs_; la_i_mc_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); return OK; } int kontrol(CSOUND *) { toa(rhs_, rhs); const std::complex &lhs = gmm::mat_trace(rhs->mc); *lhs_r = lhs.real(); *lhs_i = lhs.imag(); return OK; } }; class la_i_lu_det_mr_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_mr_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::lu_det(rhs->mr); return OK; } }; class la_k_lu_det_mr_t : public OpcodeBase { public: MYFLT *lhs; MYFLT *rhs_; la_i_mr_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); return OK; } int kontrol(CSOUND *) { toa(rhs_, rhs); *lhs = gmm::lu_det(rhs->mr); return OK; } }; class la_i_lu_det_mc_t : public OpcodeBase { public: MYFLT *lhs_r; MYFLT *lhs_i; MYFLT *rhs_; la_i_mc_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); const std::complex &lhs = gmm::lu_det(rhs->mc); *lhs_r = lhs.real(); *lhs_i = lhs.imag(); return OK; } }; class la_k_lu_det_mc_t : public OpcodeBase { public: MYFLT *lhs_r; MYFLT *lhs_i; MYFLT *rhs_; la_i_mc_create_t *rhs; int init(CSOUND *) { toa(rhs_, rhs); return OK; } int kontrol(CSOUND *) { toa(rhs_, rhs); const std::complex &lhs = gmm::lu_det(rhs->mc); *lhs_r = lhs.real(); *lhs_i = lhs.imag(); return OK; } }; /** * Elementwise addition. * The array on the left-hand side can also appear * on the right-hand side in order to perform a += b. */ class la_i_add_vr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_vr_create_t *lhs; la_i_vr_create_t *rhs_a; la_i_vr_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); for (size_t i = 0, n = rhs_a->vr.size(); i < n; ++i) { lhs->vr[i] = rhs_a->vr[i] + rhs_b->vr[i]; } return OK; } }; /** * Elementwise addition. * The array on the left-hand side can also appear * on the right-hand side in order to perform a += b. */ class la_k_add_vr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_vr_create_t *lhs; la_i_vr_create_t *rhs_a; la_i_vr_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); return OK; } int kontrol(CSOUND *) { for (size_t i = 0, n = rhs_a->vr.size(); i < n; ++i) { lhs->vr[i] = rhs_a->vr[i] + rhs_b->vr[i]; } return OK; } }; /** * Elementwise addition. * The array on the left-hand side can also appear * on the right-hand side in order to perform a += b. */ class la_i_add_vc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_vc_create_t *lhs; la_i_vc_create_t *rhs_a; la_i_vc_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); for (size_t i = 0, n = rhs_a->vc.size(); i < n; ++i) { lhs->vc[i] = rhs_a->vc[i] + rhs_b->vc[i]; } return OK; } }; /** * Elementwise addition. * The array on the left-hand side can also appear * on the right-hand side in order to perform a += b. */ class la_k_add_vc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_vc_create_t *lhs; la_i_vc_create_t *rhs_a; la_i_vc_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); return OK; } int kontrol(CSOUND *) { for (size_t i = 0, n = rhs_a->vc.size(); i < n; ++i) { lhs->vc[i] = rhs_a->vc[i] + rhs_b->vc[i]; } return OK; } }; /** * Elementwise addition. * The array on the left-hand side can also appear * on the right-hand side in order to perform A += B. */ class la_i_add_mr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_mr_create_t *lhs; la_i_mr_create_t *rhs_a; la_i_mr_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); size_t rowN = gmm::mat_nrows(rhs_a->mr); size_t columnN = gmm::mat_ncols(rhs_a->mr); for (size_t rowI = 0; rowI < rowN; ++rowI) { for (size_t columnI = 0; columnI < columnN; ++columnI) { lhs->mr(rowI, columnI) = rhs_a->mr(rowI, columnI) + rhs_b->mr(rowI, columnI); } } return OK; } }; /** * Elementwise addition. * The array on the left-hand side can also appear * on the right-hand side in order to perform A += B. */ class la_k_add_mr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_mr_create_t *lhs; la_i_mr_create_t *rhs_a; la_i_mr_create_t *rhs_b; size_t rowN; size_t columnN; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); rowN = gmm::mat_nrows(rhs_a->mr); columnN = gmm::mat_ncols(rhs_a->mr); return OK; } int kontrol(CSOUND *) { for (size_t rowI = 0; rowI < rowN; ++rowI) { for (size_t columnI = 0; columnI < columnN; ++columnI) { lhs->mr(rowI, columnI) = rhs_a->mr(rowI, columnI) + rhs_b->mr(rowI, columnI); } } return OK; } }; /** * Elementwise addition. * The array on the left-hand side can also appear * on the right-hand side in order to perform A += B. */ class la_i_add_mc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_mc_create_t *lhs; la_i_mc_create_t *rhs_a; la_i_mc_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); size_t rowN = gmm::mat_nrows(rhs_a->mc); size_t columnN = gmm::mat_ncols(rhs_a->mc); for (size_t rowI = 0; rowI < rowN; ++rowI) { for (size_t columnI = 0; columnI < columnN; ++columnI) { lhs->mc(rowI, columnI) = rhs_a->mc(rowI, columnI) + rhs_b->mc(rowI, columnI); } } return OK; } }; /** * Elementwise addition. * The array on the left-hand side can also appear * on the right-hand side in order to perform A += B. */ class la_k_add_mc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_mc_create_t *lhs; la_i_mc_create_t *rhs_a; la_i_mc_create_t *rhs_b; size_t rowN; size_t columnN; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); rowN = gmm::mat_nrows(rhs_a->mc); columnN = gmm::mat_ncols(rhs_a->mc); return OK; } int kontrol(CSOUND *) { for (size_t rowI = 0; rowI < rowN; ++rowI) { for (size_t columnI = 0; columnI < columnN; ++columnI) { lhs->mc(rowI, columnI) = rhs_a->mc(rowI, columnI) + rhs_b->mc(rowI, columnI); } } return OK; } }; /** * Elementwise subtraction. * The array on the left-hand side can also appear * on the right-hand side in order to perform a -= b. */ class la_i_subtract_vr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_vr_create_t *lhs; la_i_vr_create_t *rhs_a; la_i_vr_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); for (size_t i = 0, n = rhs_a->vr.size(); i < n; ++i) { lhs->vr[i] = rhs_a->vr[i] - rhs_b->vr[i]; } return OK; } }; /** * Elementwise subtraction. * The array on the left-hand side can also appear * on the right-hand side in order to perform a -= b. */ class la_k_subtract_vr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_vr_create_t *lhs; la_i_vr_create_t *rhs_a; la_i_vr_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); return OK; } int kontrol(CSOUND *) { for (size_t i = 0, n = rhs_a->vr.size(); i < n; ++i) { lhs->vr[i] = rhs_a->vr[i] - rhs_b->vr[i]; } return OK; } }; /** * Elementwise subtraction. * The array on the left-hand side can also appear * on the right-hand side in order to perform a -= b. */ class la_i_subtract_vc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_vc_create_t *lhs; la_i_vc_create_t *rhs_a; la_i_vc_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); for (size_t i = 0, n = rhs_a->vc.size(); i < n; ++i) { lhs->vc[i] = rhs_a->vc[i] - rhs_b->vc[i]; } return OK; } }; /** * Elementwise subtraction. * The array on the left-hand side can also appear * on the right-hand side in order to perform a -= b. */ class la_k_subtract_vc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_vc_create_t *lhs; la_i_vc_create_t *rhs_a; la_i_vc_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); return OK; } int kontrol(CSOUND *) { for (size_t i = 0, n = rhs_a->vc.size(); i < n; ++i) { lhs->vc[i] = rhs_a->vc[i] - rhs_b->vc[i]; } return OK; } }; /** * Elementwise subtraction. * The array on the left-hand side can also appear * on the right-hand side in order to perform A -= B. */ class la_i_subtract_mr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_mr_create_t *lhs; la_i_mr_create_t *rhs_a; la_i_mr_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); size_t rowN = gmm::mat_nrows(rhs_a->mr); size_t columnN = gmm::mat_ncols(rhs_a->mr); for (size_t rowI = 0; rowI < rowN; ++rowI) { for (size_t columnI = 0; columnI < columnN; ++columnI) { lhs->mr(rowI, columnI) = rhs_a->mr(rowI, columnI) - rhs_b->mr(rowI, columnI); } } return OK; } }; /** * Elementwise subtraction. * The array on the left-hand side can also appear * on the right-hand side in order to perform A -= B. */ class la_k_subtract_mr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_mr_create_t *lhs; la_i_mr_create_t *rhs_a; la_i_mr_create_t *rhs_b; size_t rowN; size_t columnN; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); rowN = gmm::mat_nrows(rhs_a->mr); columnN = gmm::mat_ncols(rhs_a->mr); return OK; } int kontrol(CSOUND *) { for (size_t rowI = 0; rowI < rowN; ++rowI) { for (size_t columnI = 0; columnI < columnN; ++columnI) { lhs->mr(rowI, columnI) = rhs_a->mr(rowI, columnI) - rhs_b->mr(rowI, columnI); } } return OK; } }; /** * Elementwise subtraction. * The array on the left-hand side can also appear * on the right-hand side in order to perform A -= B. */ class la_i_subtract_mc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_mc_create_t *lhs; la_i_mc_create_t *rhs_a; la_i_mc_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); size_t rowN = gmm::mat_nrows(rhs_a->mc); size_t columnN = gmm::mat_ncols(rhs_a->mc); for (size_t rowI = 0; rowI < rowN; ++rowI) { for (size_t columnI = 0; columnI < columnN; ++columnI) { lhs->mc(rowI, columnI) = rhs_a->mc(rowI, columnI) - rhs_b->mc(rowI, columnI); } } return OK; } }; /** * Elementwise subtraction. * The array on the left-hand side can also appear * on the right-hand side in order to perform A -= B. */ class la_k_subtract_mc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_mc_create_t *lhs; la_i_mc_create_t *rhs_a; la_i_mc_create_t *rhs_b; size_t rowN; size_t columnN; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); rowN = gmm::mat_nrows(rhs_a->mc); columnN = gmm::mat_ncols(rhs_a->mc); return OK; } int kontrol(CSOUND *) { for (size_t rowI = 0; rowI < rowN; ++rowI) { for (size_t columnI = 0; columnI < columnN; ++columnI) { lhs->mc(rowI, columnI) = rhs_a->mc(rowI, columnI) - rhs_b->mc(rowI, columnI); } } return OK; } }; /** * Elementwise multiplication. * The array on the left-hand side can also appear * on the right-hand side in order to perform a *= b. */ class la_i_multiply_vr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_vr_create_t *lhs; la_i_vr_create_t *rhs_a; la_i_vr_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); for (size_t i = 0, n = rhs_a->vr.size(); i < n; ++i) { lhs->vr[i] = rhs_a->vr[i] * rhs_b->vr[i]; } return OK; } }; /** * Elementwise multiplication. * The array on the left-hand side can also appear * on the right-hand side in order to perform a *= b. */ class la_k_multiply_vr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_vr_create_t *lhs; la_i_vr_create_t *rhs_a; la_i_vr_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); return OK; } int kontrol(CSOUND *) { for (size_t i = 0, n = rhs_a->vr.size(); i < n; ++i) { lhs->vr[i] = rhs_a->vr[i] * rhs_b->vr[i]; } return OK; } }; /** * Elementwise multiplication. * The array on the left-hand side can also appear * on the right-hand side in order to perform a *= b. */ class la_i_multiply_vc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_vc_create_t *lhs; la_i_vc_create_t *rhs_a; la_i_vc_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); for (size_t i = 0, n = rhs_a->vc.size(); i < n; ++i) { lhs->vc[i] = rhs_a->vc[i] * rhs_b->vc[i]; } return OK; } }; /** * Elementwise multiplication. * The array on the left-hand side can also appear * on the right-hand side in order to perform a *= b. */ class la_k_multiply_vc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_vc_create_t *lhs; la_i_vc_create_t *rhs_a; la_i_vc_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); return OK; } int kontrol(CSOUND *) { for (size_t i = 0, n = rhs_a->vc.size(); i < n; ++i) { lhs->vc[i] = rhs_a->vc[i] * rhs_b->vc[i]; } return OK; } }; /** * Elementwise multiplication. * The array on the left-hand side can also appear * on the right-hand side in order to perform A *= B. */ class la_i_multiply_mr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_mr_create_t *lhs; la_i_mr_create_t *rhs_a; la_i_mr_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); size_t rowN = gmm::mat_nrows(rhs_a->mr); size_t columnN = gmm::mat_ncols(rhs_a->mr); for (size_t rowI = 0; rowI < rowN; ++rowI) { for (size_t columnI = 0; columnI < columnN; ++columnI) { lhs->mr(rowI, columnI) = rhs_a->mr(rowI, columnI) * rhs_b->mr(rowI, columnI); } } return OK; } }; /** * Elementwise multiplication. * The array on the left-hand side can also appear * on the right-hand side in order to perform A *= B. */ class la_k_multiply_mr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_mr_create_t *lhs; la_i_mr_create_t *rhs_a; la_i_mr_create_t *rhs_b; size_t rowN; size_t columnN; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); rowN = gmm::mat_nrows(rhs_a->mr); columnN = gmm::mat_ncols(rhs_a->mr); return OK; } int kontrol(CSOUND *) { for (size_t rowI = 0; rowI < rowN; ++rowI) { for (size_t columnI = 0; columnI < columnN; ++columnI) { lhs->mr(rowI, columnI) = rhs_a->mr(rowI, columnI) * rhs_b->mr(rowI, columnI); } } return OK; } }; /** * Elementwise multiplication. * The array on the left-hand side can also appear * on the right-hand side in order to perform A *= B. */ class la_i_multiply_mc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_mc_create_t *lhs; la_i_mc_create_t *rhs_a; la_i_mc_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); size_t rowN = gmm::mat_nrows(rhs_a->mc); size_t columnN = gmm::mat_ncols(rhs_a->mc); for (size_t rowI = 0; rowI < rowN; ++rowI) { for (size_t columnI = 0; columnI < columnN; ++columnI) { lhs->mc(rowI, columnI) = rhs_a->mc(rowI, columnI) * rhs_b->mc(rowI, columnI); } } return OK; } }; /** * Elementwise multiplication. * The array on the left-hand side can also appear * on the right-hand side in order to perform A *= B. */ class la_k_multiply_mc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_mc_create_t *lhs; la_i_mc_create_t *rhs_a; la_i_mc_create_t *rhs_b; size_t rowN; size_t columnN; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); rowN = gmm::mat_nrows(rhs_a->mc); columnN = gmm::mat_ncols(rhs_a->mc); return OK; } int kontrol(CSOUND *) { for (size_t rowI = 0; rowI < rowN; ++rowI) { for (size_t columnI = 0; columnI < columnN; ++columnI) { lhs->mc(rowI, columnI) = rhs_a->mc(rowI, columnI) * rhs_b->mc(rowI, columnI); } } return OK; } }; /** * Elementwise division. * The array on the left-hand side can also appear * on the right-hand side in order to perform a /= b. */ class la_i_divide_vr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_vr_create_t *lhs; la_i_vr_create_t *rhs_a; la_i_vr_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); for (size_t i = 0, n = rhs_a->vr.size(); i < n; ++i) { lhs->vr[i] = rhs_a->vr[i] / rhs_b->vr[i]; } return OK; } }; /** * Elementwise division. * The array on the left-hand side can also appear * on the right-hand side in order to perform a /= b. */ class la_k_divide_vr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_vr_create_t *lhs; la_i_vr_create_t *rhs_a; la_i_vr_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); return OK; } int kontrol(CSOUND *) { for (size_t i = 0, n = rhs_a->vr.size(); i < n; ++i) { lhs->vr[i] = rhs_a->vr[i] / rhs_b->vr[i]; } return OK; } }; /** * Elementwise division. * The array on the left-hand side can also appear * on the right-hand side in order to perform a /= b. */ class la_i_divide_vc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_vc_create_t *lhs; la_i_vc_create_t *rhs_a; la_i_vc_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); for (size_t i = 0, n = rhs_a->vc.size(); i < n; ++i) { lhs->vc[i] = rhs_a->vc[i] / rhs_b->vc[i]; } return OK; } }; /** * Elementwise division. * The array on the left-hand side can also appear * on the right-hand side in order to perform a /= b. */ class la_k_divide_vc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_vc_create_t *lhs; la_i_vc_create_t *rhs_a; la_i_vc_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); return OK; } int kontrol(CSOUND *) { for (size_t i = 0, n = rhs_a->vc.size(); i < n; ++i) { lhs->vc[i] = rhs_a->vc[i] / rhs_b->vc[i]; } return OK; } }; /** * Elementwise division. * The array on the left-hand side can also appear * on the right-hand side in order to perform A /= B. */ class la_i_divide_mr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_mr_create_t *lhs; la_i_mr_create_t *rhs_a; la_i_mr_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); size_t rowN = gmm::mat_nrows(rhs_a->mr); size_t columnN = gmm::mat_ncols(rhs_a->mr); for (size_t rowI = 0; rowI < rowN; ++rowI) { for (size_t columnI = 0; columnI < columnN; ++columnI) { lhs->mr(rowI, columnI) = rhs_a->mr(rowI, columnI) / rhs_b->mr(rowI, columnI); } } return OK; } }; /** * Elementwise division. * The array on the left-hand side can also appear * on the right-hand side in order to perform A /= B. */ class la_k_divide_mr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_mr_create_t *lhs; la_i_mr_create_t *rhs_a; la_i_mr_create_t *rhs_b; size_t rowN; size_t columnN; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); rowN = gmm::mat_nrows(rhs_a->mr); columnN = gmm::mat_ncols(rhs_a->mr); return OK; } int kontrol(CSOUND *) { for (size_t rowI = 0; rowI < rowN; ++rowI) { for (size_t columnI = 0; columnI < columnN; ++columnI) { lhs->mr(rowI, columnI) = rhs_a->mr(rowI, columnI) / rhs_b->mr(rowI, columnI); } } return OK; } }; /** * Elementwise division. * The array on the left-hand side can also appear * on the right-hand side in order to perform A /= B. */ class la_i_divide_mc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_mc_create_t *lhs; la_i_mc_create_t *rhs_a; la_i_mc_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); size_t rowN = gmm::mat_nrows(rhs_a->mc); size_t columnN = gmm::mat_ncols(rhs_a->mc); for (size_t rowI = 0; rowI < rowN; ++rowI) { for (size_t columnI = 0; columnI < columnN; ++columnI) { lhs->mc(rowI, columnI) = rhs_a->mc(rowI, columnI) / rhs_b->mc(rowI, columnI); } } return OK; } }; /** * Elementwise division. * The array on the left-hand side can also appear * on the right-hand side in order to perform A /= B. */ class la_k_divide_mc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_mc_create_t *lhs; la_i_mc_create_t *rhs_a; la_i_mc_create_t *rhs_b; size_t rowN; size_t columnN; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); rowN = gmm::mat_nrows(rhs_a->mc); columnN = gmm::mat_ncols(rhs_a->mc); return OK; } int kontrol(CSOUND *) { for (size_t rowI = 0; rowI < rowN; ++rowI) { for (size_t columnI = 0; columnI < columnN; ++columnI) { lhs->mc(rowI, columnI) = rhs_a->mc(rowI, columnI) / rhs_b->mc(rowI, columnI); } } return OK; } }; /** * Elementwise multiplication. * The array on the left-hand side can also appear * on the right-hand side in order to perform a *= b. */ class la_i_dot_vr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_vr_create_t *rhs_a; la_i_vr_create_t *rhs_b; int init(CSOUND *) { toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); *lhs_ = gmm::vect_sp(rhs_a->vr, rhs_b->vr); return OK; } }; /** * Elementwise multiplication. * The array on the left-hand side can also appear * on the right-hand side in order to perform a *= b. */ class la_k_dot_vr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_vr_create_t *rhs_a; la_i_vr_create_t *rhs_b; int init(CSOUND *) { toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); return OK; } int kontrol(CSOUND *) { *lhs_ = gmm::vect_sp(rhs_a->vr, rhs_b->vr); return OK; } }; /** * Elementwise multiplication. * The array on the left-hand side can also appear * on the right-hand side in order to perform a *= b. */ class la_i_dot_vc_t : public OpcodeBase { public: MYFLT *lhs_r; MYFLT *lhs_i; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_vc_create_t *rhs_a; la_i_vc_create_t *rhs_b; int init(CSOUND *) { toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); std::complex lhs = gmm::vect_sp(rhs_a->vc, rhs_b->vc); *lhs_r = lhs.real(); *lhs_i = lhs.imag(); return OK; } }; /** * Elementwise multiplication. * The array on the left-hand side can also appear * on the right-hand side in order to perform a *= b. */ class la_k_dot_vc_t : public OpcodeBase { public: MYFLT *lhs_r; MYFLT *lhs_i; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_vc_create_t *rhs_a; la_i_vc_create_t *rhs_b; int init(CSOUND *) { toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); return OK; } int kontrol(CSOUND *) { std::complex lhs = gmm::vect_sp(rhs_a->vc, rhs_b->vc); *lhs_r = lhs.real(); *lhs_i = lhs.imag(); return OK; } }; class la_i_dot_mr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_mr_create_t *lhs; la_i_mr_create_t *rhs_a; la_i_mr_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); gmm::mult(rhs_a->mr, rhs_b->mr, lhs->mr); return OK; } }; class la_k_dot_mr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_mr_create_t *lhs; la_i_mr_create_t *rhs_a; la_i_mr_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); gmm::mult(rhs_a->mr, rhs_b->mr, lhs->mr); return OK; } int kontrol(CSOUND *) { gmm::mult(rhs_a->mr, rhs_b->mr, lhs->mr); return OK; } }; class la_i_dot_mc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_mc_create_t *lhs; la_i_mc_create_t *rhs_a; la_i_mc_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); gmm::mult(rhs_a->mc, rhs_b->mc, lhs->mc); return OK; } }; class la_k_dot_mc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_mc_create_t *lhs; la_i_mc_create_t *rhs_a; la_i_mc_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); return OK; } int kontrol(CSOUND *) { gmm::mult(rhs_a->mc, rhs_b->mc, lhs->mc); return OK; } }; class la_i_dot_mr_vr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_vr_create_t *lhs; la_i_mr_create_t *rhs_a; la_i_vr_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); gmm::mult(rhs_a->mr, rhs_b->vr, lhs->vr); return OK; } }; class la_k_dot_mr_vr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_vr_create_t *lhs; la_i_mr_create_t *rhs_a; la_i_vr_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); return OK; } int kontrol(CSOUND *) { gmm::mult(rhs_a->mr, rhs_b->vr, lhs->vr); return OK; } }; class la_i_dot_mc_vc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_vc_create_t *lhs; la_i_mc_create_t *rhs_a; la_i_vc_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); gmm::mult(rhs_a->mc, rhs_b->vc, lhs->vc); return OK; } }; class la_k_dot_mc_vc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_a_; MYFLT *rhs_b_; la_i_vc_create_t *lhs; la_i_mc_create_t *rhs_a; la_i_vc_create_t *rhs_b; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_a_, rhs_a); toa(rhs_b_, rhs_b); return OK; } int kontrol(CSOUND *) { gmm::mult(rhs_a->mc, rhs_b->vc, lhs->vc); return OK; } }; class la_i_invert_mr_t : public OpcodeBase { public: MYFLT *imr_lhs; MYFLT *icondition; MYFLT *imr_rhs; la_i_mr_create_t *lhs; la_i_mr_create_t *rhs; int init(CSOUND *) { toa(imr_lhs, lhs); toa(imr_rhs, rhs); gmm::copy(rhs->mr, lhs->mr); *icondition = gmm::lu_inverse(lhs->mr); return OK; } }; class la_k_invert_mr_t : public OpcodeBase { public: MYFLT *imr_lhs; MYFLT *kcondition; MYFLT *imr_rhs; la_i_mr_create_t *lhs; la_i_mr_create_t *rhs; int init(CSOUND *) { toa(imr_lhs, lhs); toa(imr_rhs, rhs); return OK; } int kontrol(CSOUND *) { gmm::copy(rhs->mr, lhs->mr); *kcondition = gmm::lu_inverse(lhs->mr); return OK; } }; class la_i_invert_mc_t : public OpcodeBase { public: MYFLT *imc_lhs; MYFLT *icondition_r; MYFLT *icondition_i; MYFLT *imc_rhs; la_i_mc_create_t *lhs; la_i_mc_create_t *rhs; int init(CSOUND *) { toa(imc_lhs, lhs); toa(imc_rhs, rhs); gmm::copy(rhs->mc, lhs->mc); std::complex condition = gmm::lu_inverse(lhs->mc); *icondition_r = condition.real(); *icondition_i = condition.imag(); return OK; } }; class la_k_invert_mc_t : public OpcodeBase { public: MYFLT *imc_lhs; MYFLT *kcondition_r; MYFLT *kcondition_i; MYFLT *imc_rhs; la_i_mc_create_t *lhs; la_i_mc_create_t *rhs; int init(CSOUND *) { toa(imc_lhs, lhs); toa(imc_rhs, rhs); return OK; } int kontrol(CSOUND *) { gmm::copy(rhs->mc, lhs->mc); std::complex condition = gmm::lu_inverse(lhs->mc); *kcondition_r = condition.real(); *kcondition_i = condition.imag(); return OK; } }; class la_i_upper_solve_mr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_; MYFLT *is_unit; la_i_vr_create_t *lhs; la_i_mr_create_t *rhs; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_, rhs); gmm::upper_tri_solve(rhs->mr, lhs->vr, bool(*is_unit)); return OK; } }; class la_k_upper_solve_mr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_; MYFLT *is_unit; la_i_vr_create_t *lhs; la_i_mr_create_t *rhs; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_, rhs); return OK; } int kontrol(CSOUND *) { gmm::upper_tri_solve(rhs->mr, lhs->vr, bool(*is_unit)); return OK; } }; class la_i_upper_solve_mc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_; MYFLT *is_unit; la_i_vc_create_t *lhs; la_i_mc_create_t *rhs; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_, rhs); gmm::upper_tri_solve(rhs->mc, lhs->vc, bool(*is_unit)); return OK; } }; class la_k_upper_solve_mc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_; MYFLT *is_unit; la_i_vc_create_t *lhs; la_i_mc_create_t *rhs; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_, rhs); return OK; } int kontrol(CSOUND *) { gmm::upper_tri_solve(rhs->mc, lhs->vc, bool(*is_unit)); return OK; } }; class la_i_lower_solve_mr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_; MYFLT *is_unit; la_i_vr_create_t *lhs; la_i_mr_create_t *rhs; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_, rhs); gmm::lower_tri_solve(rhs->mr, lhs->vr, bool(*is_unit)); return OK; } }; class la_k_lower_solve_mr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_; MYFLT *is_unit; la_i_vr_create_t *lhs; la_i_mr_create_t *rhs; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_, rhs); return OK; } int kontrol(CSOUND *) { gmm::lower_tri_solve(rhs->mr, lhs->vr, bool(*is_unit)); return OK; } }; class la_i_lower_solve_mc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_; MYFLT *is_unit; la_i_vc_create_t *lhs; la_i_mc_create_t *rhs; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_, rhs); gmm::lower_tri_solve(rhs->mc, lhs->vc, bool(*is_unit)); return OK; } }; class la_k_lower_solve_mc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *rhs_; MYFLT *is_unit; la_i_vc_create_t *lhs; la_i_mc_create_t *rhs; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_, rhs); return OK; } int kontrol(CSOUND *) { gmm::lower_tri_solve(rhs->mc, lhs->vc, bool(*is_unit)); return OK; } }; class la_i_lu_factor_mr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *pivot_; MYFLT *isize; MYFLT *rhs_; la_i_mr_create_t *lhs; la_i_vr_create_t *pivot; la_i_mr_create_t *rhs; std::vector pivot__; size_t pivot_size; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_, pivot); toa(rhs_, rhs); pivot_size = gmm::mat_nrows(rhs->mr); pivot__.resize(pivot_size); gmm::copy(rhs->mr, lhs->mr); *isize = gmm::lu_factor(lhs->mr, pivot__); for (size_t i = 0; i < pivot_size; ++i) { pivot->vr[i] = pivot__[i]; } return OK; } }; class la_k_lu_factor_mr_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *pivot_; MYFLT *ksize; MYFLT *rhs_; la_i_mr_create_t *lhs; la_i_vr_create_t *pivot; la_i_mr_create_t *rhs; std::vector pivot__; size_t pivot_size; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_, pivot); toa(rhs_, rhs); return OK; } int kontrol(CSOUND *) { pivot_size = gmm::mat_nrows(rhs->mr); pivot__.resize(pivot_size); gmm::copy(rhs->mr, lhs->mr); *ksize = gmm::lu_factor(lhs->mr, pivot__); for (size_t i = 0; i < pivot_size; ++i) { pivot->vr[i] = pivot__[i]; } return OK; } }; class la_i_lu_factor_mc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *pivot_; MYFLT *isize; MYFLT *rhs_; la_i_mc_create_t *lhs; la_i_vr_create_t *pivot; la_i_mc_create_t *rhs; std::vector pivot__; size_t pivot_size; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_, pivot); toa(rhs_, rhs); pivot_size = gmm::mat_nrows(rhs->mc); pivot__.resize(pivot_size); gmm::copy(rhs->mc, lhs->mc); *isize = gmm::lu_factor(lhs->mc, pivot__); for (size_t i = 0; i < pivot_size; ++i) { pivot->vr[i] = pivot__[i]; } return OK; } }; class la_k_lu_factor_mc_t : public OpcodeBase { public: MYFLT *lhs_; MYFLT *pivot_; MYFLT *ksize; MYFLT *rhs_; la_i_mc_create_t *lhs; la_i_vr_create_t *pivot; la_i_mc_create_t *rhs; std::vector pivot__; size_t pivot_size; int init(CSOUND *) { toa(lhs_, lhs); toa(rhs_, pivot); toa(rhs_, rhs); return OK; } int kontrol(CSOUND *) { pivot_size = gmm::mat_nrows(rhs->mc); pivot__.resize(pivot_size); gmm::copy(rhs->mc, lhs->mc); *ksize = gmm::lu_factor(lhs->mc, pivot__); for (size_t i = 0; i < pivot_size; ++i) { pivot->vr[i] = pivot__[i]; } return OK; } }; class la_i_lu_solve_mr_t : public OpcodeBase { public: MYFLT *lhs_x_; MYFLT *rhs_A_; MYFLT *rhs_b_; la_i_vr_create_t *lhs_x; la_i_mr_create_t *rhs_A; la_i_vr_create_t *rhs_b; int init(CSOUND *) { toa(lhs_x_, lhs_x); toa(rhs_A_, rhs_A); toa(rhs_b_, rhs_b); gmm::lu_solve(rhs_A->mr, lhs_x->vr, rhs_b->vr); return OK; } }; class la_k_lu_solve_mr_t : public OpcodeBase { public: MYFLT *lhs_x_; MYFLT *rhs_A_; MYFLT *rhs_b_; la_i_vr_create_t *lhs_x; la_i_mr_create_t *rhs_A; la_i_vr_create_t *rhs_b; int init(CSOUND *) { toa(lhs_x_, lhs_x); toa(rhs_A_, rhs_A); toa(rhs_b_, rhs_b); return OK; } int kontrol(CSOUND *) { gmm::lu_solve(rhs_A->mr, lhs_x->vr, rhs_b->vr); return OK; } }; class la_i_lu_solve_mc_t : public OpcodeBase { public: MYFLT *lhs_x_; MYFLT *rhs_A_; MYFLT *rhs_b_; la_i_vc_create_t *lhs_x; la_i_mc_create_t *rhs_A; la_i_vc_create_t *rhs_b; int init(CSOUND *) { toa(lhs_x_, lhs_x); toa(rhs_A_, rhs_A); toa(rhs_b_, rhs_b); gmm::lu_solve(rhs_A->mc, lhs_x->vc, rhs_b->vc); return OK; } }; class la_k_lu_solve_mc_t : public OpcodeBase { public: MYFLT *lhs_x_; MYFLT *rhs_A_; MYFLT *rhs_b_; la_i_vc_create_t *lhs_x; la_i_mc_create_t *rhs_A; la_i_vc_create_t *rhs_b; int init(CSOUND *) { toa(lhs_x_, lhs_x); toa(rhs_A_, rhs_A); toa(rhs_b_, rhs_b); return OK; } int kontrol(CSOUND *) { gmm::lu_solve(rhs_A->mc, lhs_x->vc, rhs_b->vc); return OK; } }; class la_i_qr_factor_mr_t : public OpcodeBase { public: MYFLT *lhs_Q_; MYFLT *lhs_R_; MYFLT *rhs_A_; la_i_mr_create_t *lhs_Q; la_i_mr_create_t *lhs_R; la_i_mr_create_t *rhs_A; int init(CSOUND *) { toa(lhs_Q_, lhs_Q); toa(lhs_R_, lhs_R); toa(rhs_A_, rhs_A); gmm::qr_factor(rhs_A->mr, lhs_Q->mr, lhs_R->mr); return OK; } }; class la_k_qr_factor_mr_t : public OpcodeBase { public: MYFLT *lhs_Q_; MYFLT *lhs_R_; MYFLT *rhs_A_; la_i_mr_create_t *lhs_Q; la_i_mr_create_t *lhs_R; la_i_mr_create_t *rhs_A; int init(CSOUND *) { toa(lhs_Q_, lhs_Q); toa(lhs_R_, lhs_R); toa(rhs_A_, rhs_A); return OK; } int kontrol(CSOUND *) { gmm::qr_factor(rhs_A->mr, lhs_Q->mr, lhs_R->mr); return OK; } }; class la_i_qr_factor_mc_t : public OpcodeBase { public: MYFLT *lhs_Q_; MYFLT *lhs_R_; MYFLT *rhs_A_; la_i_mc_create_t *lhs_Q; la_i_mc_create_t *lhs_R; la_i_mc_create_t *rhs_A; int init(CSOUND *) { toa(lhs_Q_, lhs_Q); toa(lhs_R_, lhs_R); toa(rhs_A_, rhs_A); gmm::qr_factor(rhs_A->mc, lhs_Q->mc, lhs_R->mc); return OK; } }; class la_k_qr_factor_mc_t : public OpcodeBase { public: MYFLT *lhs_Q_; MYFLT *lhs_R_; MYFLT *rhs_A_; la_i_mc_create_t *lhs_Q; la_i_mc_create_t *lhs_R; la_i_mc_create_t *rhs_A; int init(CSOUND *) { toa(lhs_Q_, lhs_Q); toa(lhs_R_, lhs_R); toa(rhs_A_, rhs_A); return OK; } int kontrol(CSOUND *) { gmm::qr_factor(rhs_A->mc, lhs_Q->mc, lhs_R->mc); return OK; } }; class la_i_qr_eigen_mr_t : public OpcodeBase { public: MYFLT *lhs_eigenvalues_; MYFLT *rhs_A_; MYFLT *itolerance; la_i_vr_create_t *lhs_eigenvalues; la_i_mr_create_t *rhs_A; int init(CSOUND *) { toa(lhs_eigenvalues_, lhs_eigenvalues); toa(rhs_A_, rhs_A); gmm::implicit_qr_algorithm(rhs_A->mr, lhs_eigenvalues->vr, double(*itolerance)); return OK; } }; class la_k_qr_eigen_mr_t : public OpcodeBase { public: MYFLT *lhs_eigenvalues_; MYFLT *rhs_A_; MYFLT *ktolerance; la_i_vr_create_t *lhs_eigenvalues; la_i_mr_create_t *rhs_A; int init(CSOUND *) { toa(lhs_eigenvalues_, lhs_eigenvalues); toa(rhs_A_, rhs_A); return OK; } int kontrol(CSOUND *) { gmm::implicit_qr_algorithm(rhs_A->mr, lhs_eigenvalues->vr, double(*ktolerance)); return OK; } }; class la_i_qr_eigen_mc_t : public OpcodeBase { public: MYFLT *lhs_eigenvalues_; MYFLT *rhs_A_; MYFLT *itolerance; la_i_vc_create_t *lhs_eigenvalues; la_i_mc_create_t *rhs_A; int init(CSOUND *) { toa(lhs_eigenvalues_, lhs_eigenvalues); toa(rhs_A_, rhs_A); gmm::implicit_qr_algorithm(rhs_A->mc, lhs_eigenvalues->vc, double(*itolerance)); return OK; } }; class la_k_qr_eigen_mc_t : public OpcodeBase { public: MYFLT *lhs_eigenvalues_; MYFLT *rhs_A_; MYFLT *ktolerance; la_i_vc_create_t *lhs_eigenvalues; la_i_mc_create_t *rhs_A; int init(CSOUND *) { toa(lhs_eigenvalues_, lhs_eigenvalues); toa(rhs_A_, rhs_A); return OK; } int kontrol(CSOUND *) { gmm::implicit_qr_algorithm(rhs_A->mc, lhs_eigenvalues->vc, double(*ktolerance)); return OK; } }; class la_i_qr_sym_eigen_mr_t : public OpcodeBase { public: MYFLT *lhs_eigenvalues_; MYFLT *lhs_eigenvectors_; MYFLT *rhs_A_; MYFLT *itolerance; la_i_vr_create_t *lhs_eigenvalues; la_i_mr_create_t *lhs_eigenvectors; la_i_mr_create_t *rhs_A; int init(CSOUND *) { toa(lhs_eigenvalues_, lhs_eigenvalues); toa(lhs_eigenvectors_, lhs_eigenvectors); toa(rhs_A_, rhs_A); gmm::implicit_qr_algorithm(rhs_A->mr, lhs_eigenvalues->vr, lhs_eigenvectors->mr, double(*itolerance)); return OK; } }; class la_k_qr_sym_eigen_mr_t : public OpcodeBase { public: MYFLT *lhs_eigenvalues_; MYFLT *lhs_eigenvectors_; MYFLT *rhs_A_; MYFLT *ktolerance; la_i_vr_create_t *lhs_eigenvalues; la_i_mr_create_t *lhs_eigenvectors; la_i_mr_create_t *rhs_A; int init(CSOUND *) { toa(lhs_eigenvalues_, lhs_eigenvalues); toa(lhs_eigenvectors_, lhs_eigenvectors); toa(rhs_A_, rhs_A); return OK; } int kontrol(CSOUND *) { gmm::implicit_qr_algorithm(rhs_A->mr, lhs_eigenvalues->vr, lhs_eigenvectors->mr, double(*ktolerance)); return OK; } }; class la_i_qr_sym_eigen_mc_t : public OpcodeBase { public: MYFLT *lhs_eigenvalues_; MYFLT *lhs_eigenvectors_; MYFLT *rhs_A_; MYFLT *itolerance; la_i_vc_create_t *lhs_eigenvalues; la_i_mc_create_t *lhs_eigenvectors; la_i_mc_create_t *rhs_A; int init(CSOUND *) { toa(lhs_eigenvalues_, lhs_eigenvalues); toa(lhs_eigenvectors_, lhs_eigenvectors); toa(rhs_A_, rhs_A); gmm::implicit_qr_algorithm(rhs_A->mc, lhs_eigenvalues->vc, lhs_eigenvectors->mc, double(*itolerance)); return OK; } }; class la_k_qr_sym_eigen_mc_t : public OpcodeBase { public: MYFLT *lhs_eigenvalues_; MYFLT *lhs_eigenvectors_; MYFLT *rhs_A_; MYFLT *ktolerance; la_i_vc_create_t *lhs_eigenvalues; la_i_mc_create_t *lhs_eigenvectors; la_i_mc_create_t *rhs_A; int init(CSOUND *) { toa(lhs_eigenvalues_, lhs_eigenvalues); toa(lhs_eigenvectors_, lhs_eigenvectors); toa(rhs_A_, rhs_A); return OK; } int kontrol(CSOUND *) { gmm::implicit_qr_algorithm(rhs_A->mc, lhs_eigenvalues->vc, lhs_eigenvectors->mc, double(*ktolerance)); return OK; } }; extern "C" { PUBLIC int csoundModuleCreate(CSOUND *csound) { return 0; } PUBLIC int csoundModuleInit(CSOUND *csound) { int status = 0; status |= csound->AppendOpcode(csound, "la_i_vr_create", sizeof(la_i_vr_create_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_vr_create_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_vc_create", sizeof(la_i_vr_create_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_vc_create_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_mr_create", sizeof(la_i_mr_create_t), 0, 1, "i", "iio", (int (*)(CSOUND*,void*)) &la_i_mr_create_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_mc_create", sizeof(la_i_mc_create_t), 0, 1, "i", "iioo", (int (*)(CSOUND*,void*)) &la_i_mc_create_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_size_vr", sizeof(la_i_size_vr_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_size_vr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_size_vc", sizeof(la_i_size_vc_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_size_vc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_size_mr", sizeof(la_i_size_mr_t), 0, 1, "ii", "i", (int (*)(CSOUND*,void*)) &la_i_size_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_size_mc", sizeof(la_i_size_mc_t), 0, 1, "ii", "i", (int (*)(CSOUND*,void*)) &la_i_size_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_current_f", sizeof(la_k_current_f_t), 0, 3, "k", "f", (int (*)(CSOUND*,void*)) &la_k_current_f_t::init_, (int (*)(CSOUND*,void*)) &la_k_current_f_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_current_vr", sizeof(la_k_current_vr_t), 0, 3, "k", "i", (int (*)(CSOUND*,void*)) &la_k_current_vr_t::init_, (int (*)(CSOUND*,void*)) &la_k_current_vr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_print_vr", sizeof(la_i_print_vr_t), 0, 1, "", "i", (int (*)(CSOUND*,void*)) &la_i_print_vr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_print_vc", sizeof(la_i_print_vc_t), 0, 1, "", "i", (int (*)(CSOUND*,void*)) &la_i_print_vc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_print_mr", sizeof(la_i_print_mr_t), 0, 1, "", "i", (int (*)(CSOUND*,void*)) &la_i_print_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_print_mc", sizeof(la_i_print_mc_t), 0, 1, "", "i", (int (*)(CSOUND*,void*)) &la_i_print_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_assign_vr", sizeof(la_i_assign_vr_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_assign_vr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_assign_vr", sizeof(la_k_assign_vr_t), 0, 3, "i", "k", (int (*)(CSOUND*,void*)) &la_k_assign_vr_t::init_, (int (*)(CSOUND*,void*)) &la_k_assign_vr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_assign_vc", sizeof(la_i_assign_vc_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_assign_vc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_assign_vc", sizeof(la_k_assign_vc_t), 0, 3, "i", "k", (int (*)(CSOUND*,void*)) &la_k_assign_vc_t::init_, (int (*)(CSOUND*,void*)) &la_k_assign_vc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_assign_mr", sizeof(la_i_assign_mr_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_assign_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_assign_mr", sizeof(la_k_assign_mr_t), 0, 3, "i", "k", (int (*)(CSOUND*,void*)) &la_k_assign_mr_t::init_, (int (*)(CSOUND*,void*)) &la_k_assign_mr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_assign_mc", sizeof(la_i_assign_mc_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_assign_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_assign_mc", sizeof(la_k_assign_mc_t), 0, 3, "i", "k", (int (*)(CSOUND*,void*)) &la_k_assign_mc_t::init_, (int (*)(CSOUND*,void*)) &la_k_assign_mc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_assign_a", sizeof(la_k_assign_a_t), 0, 3, "i", "a", (int (*)(CSOUND*,void*)) &la_k_assign_a_t::init_, (int (*)(CSOUND*,void*)) &la_k_assign_a_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_assign_t", sizeof(la_i_assign_t_t), TR, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_assign_t_t::init_, (int (*)(CSOUND*,void*)) &la_i_assign_t_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_assign_t", sizeof(la_k_assign_t_t), TR, 3, "i", "k", (int (*)(CSOUND*,void*)) &la_k_assign_t_t::init_, (int (*)(CSOUND*,void*)) &la_k_assign_t_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_assign_f", sizeof(la_k_assign_f_t), 0, 3, "i", "f", (int (*)(CSOUND*,void*)) &la_k_assign_f_t::init_, (int (*)(CSOUND*,void*)) &la_k_assign_f_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_a_assign", sizeof(la_k_a_assign_t), 0, 3, "a", "k", (int (*)(CSOUND*,void*)) &la_k_a_assign_t::init_, (int (*)(CSOUND*,void*)) &la_k_a_assign_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_t_assign", sizeof(la_i_t_assign_t), TW, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_t_assign_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_t_assign", sizeof(la_k_t_assign_t), TW, 3, "i", "k", (int (*)(CSOUND*,void*)) &la_k_t_assign_t::init_, (int (*)(CSOUND*,void*)) &la_k_t_assign_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_f_assign", sizeof(la_k_f_assign_t), 0, 3, "f", "p", (int (*)(CSOUND*,void*)) &la_k_f_assign_t::init_, (int (*)(CSOUND*,void*)) &la_k_f_assign_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_random_vr", sizeof(la_i_random_vr_t), 0, 1, "i", "p", (int (*)(CSOUND*,void*)) &la_i_random_vr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_random_vr", sizeof(la_k_random_vr_t), 0, 3, "i", "p", (int (*)(CSOUND*,void*)) &la_k_random_vr_t::init_, (int (*)(CSOUND*,void*)) &la_k_random_vr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_random_vc", sizeof(la_i_random_vc_t), 0, 1, "i", "p", (int (*)(CSOUND*,void*)) &la_i_random_vc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_random_vc", sizeof(la_k_random_vc_t), 0, 3, "i", "p", (int (*)(CSOUND*,void*)) &la_k_random_vc_t::init_, (int (*)(CSOUND*,void*)) &la_k_random_vc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_random_mr", sizeof(la_i_random_mr_t), 0, 1, "i", "p", (int (*)(CSOUND*,void*)) &la_i_random_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_random_mr", sizeof(la_k_random_mr_t), 0, 3, "i", "p", (int (*)(CSOUND*,void*)) &la_k_random_mr_t::init_, (int (*)(CSOUND*,void*)) &la_k_random_mr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_random_mc", sizeof(la_i_random_mc_t), 0, 1, "i", "p", (int (*)(CSOUND*,void*)) &la_i_random_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_random_mc", sizeof(la_k_random_mc_t), 0, 3, "i", "p", (int (*)(CSOUND*,void*)) &la_k_random_mc_t::init_, (int (*)(CSOUND*,void*)) &la_k_random_mc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_vr_set", sizeof(la_i_vr_set_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_vr_set_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_vr_set", sizeof(la_k_vr_set_t), 0, 3, "i", "kk", (int (*)(CSOUND*,void*)) &la_k_vr_set_t::init_, (int (*)(CSOUND*,void*)) &la_k_vr_set_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_vc_set", sizeof(la_i_vc_set_t), 0, 1, "i", "iii", (int (*)(CSOUND*,void*)) &la_i_vc_set_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_vc_set", sizeof(la_k_vc_set_t), 0, 3, "i", "kkk", (int (*)(CSOUND*,void*)) &la_k_vc_set_t::init_, (int (*)(CSOUND*,void*)) &la_k_vc_set_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_mr_set", sizeof(la_i_mr_set_t), 0, 1, "i", "iii", (int (*)(CSOUND*,void*)) &la_i_mr_set_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_mr_set", sizeof(la_k_mr_set_t), 0, 3, "i", "kkk", (int (*)(CSOUND*,void*)) &la_k_mr_set_t::init_, (int (*)(CSOUND*,void*)) &la_k_mr_set_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_mc_set", sizeof(la_i_mc_set_t), 0, 1, "i", "iiii", (int (*)(CSOUND*,void*)) &la_i_mc_set_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_mc_set", sizeof(la_k_mc_set_t), 0, 3, "i", "kkkk", (int (*)(CSOUND*,void*)) &la_k_mc_set_t::init_, (int (*)(CSOUND*,void*)) &la_k_mc_set_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_get_vr", sizeof(la_i_get_vr_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_get_vr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_get_vr", sizeof(la_k_get_vr_t), 0, 3, "k", "ik", (int (*)(CSOUND*,void*)) &la_k_get_vr_t::init_, (int (*)(CSOUND*,void*)) &la_k_get_vr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_get_vc", sizeof(la_i_get_vc_t), 0, 1, "ii", "ii", (int (*)(CSOUND*,void*)) &la_i_get_vc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_get_vc", sizeof(la_k_get_vc_t), 0, 3, "kk", "ik", (int (*)(CSOUND*,void*)) &la_k_get_vc_t::init_, (int (*)(CSOUND*,void*)) &la_k_get_vc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_get_mr", sizeof(la_i_get_mr_t), 0, 1, "i", "iii", (int (*)(CSOUND*,void*)) &la_i_get_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_get_mr", sizeof(la_k_get_mr_t), 0, 3, "k", "ikk", (int (*)(CSOUND*,void*)) &la_k_get_mr_t::init_, (int (*)(CSOUND*,void*)) &la_k_get_mr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_get_mc", sizeof(la_i_get_mc_t), 0, 1, "ii", "iii", (int (*)(CSOUND*,void*)) &la_i_get_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_get_mc", sizeof(la_k_get_mc_t), 0, 3, "kk", "ikk", (int (*)(CSOUND*,void*)) &la_k_get_mc_t::init_, (int (*)(CSOUND*,void*)) &la_k_get_mc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_transpose_mr", sizeof(la_i_transpose_mr_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_transpose_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_transpose_mr", sizeof(la_k_transpose_mr_t), 0, 3, "i", "k", (int (*)(CSOUND*,void*)) &la_k_transpose_mr_t::init_, (int (*)(CSOUND*,void*)) &la_k_transpose_mr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_transpose_mc", sizeof(la_i_transpose_mc_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_transpose_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_transpose_mc", sizeof(la_k_transpose_mc_t), 0, 2, "i", "i", (int (*)(CSOUND*,void*)) &la_k_transpose_mc_t::init_, (int (*)(CSOUND*,void*)) &la_k_transpose_mc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_conjugate_vr", sizeof(la_i_conjugate_vr_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_conjugate_vr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_conjugate_vr", sizeof(la_k_conjugate_vr_t), 0, 3, "i", "i", (int (*)(CSOUND*,void*)) &la_k_conjugate_vr_t::init_, (int (*)(CSOUND*,void*)) &la_k_conjugate_vr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_conjugate_vc", sizeof(la_i_conjugate_vc_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_conjugate_vc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_conjugate_vc", sizeof(la_k_conjugate_vc_t), 0, 3, "i", "i", (int (*)(CSOUND*,void*)) &la_k_conjugate_vc_t::init_, (int (*)(CSOUND*,void*)) &la_k_conjugate_vc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_conjugate_mr", sizeof(la_i_conjugate_mr_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_conjugate_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_conjugate_mr", sizeof(la_k_conjugate_mr_t), 0, 3, "i", "i", (int (*)(CSOUND*,void*)) &la_k_conjugate_mr_t::init_, (int (*)(CSOUND*,void*)) &la_k_conjugate_mr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_conjugate_mc", sizeof(la_i_conjugate_mc_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_conjugate_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_conjugate_mc", sizeof(la_k_conjugate_mc_t), 0, 3, "i", "i", (int (*)(CSOUND*,void*)) &la_k_conjugate_mc_t::init_, (int (*)(CSOUND*,void*)) &la_k_conjugate_mc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_norm1_vr", sizeof(la_i_norm1_vr_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_norm1_vr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_norm1_vr", sizeof(la_k_norm1_vr_t), 0, 3, "k", "i", (int (*)(CSOUND*,void*)) &la_k_norm1_vr_t::init_, (int (*)(CSOUND*,void*)) &la_k_norm1_vr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_norm1_vc", sizeof(la_i_norm1_vc_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_norm1_vc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_norm1_vc", sizeof(la_k_norm1_vc_t), 0, 3, "k", "i", (int (*)(CSOUND*,void*)) &la_k_norm1_vc_t::init_, (int (*)(CSOUND*,void*)) &la_k_norm1_vc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_norm1_mr", sizeof(la_i_norm1_mr_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_norm1_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_norm1_mr", sizeof(la_k_norm1_mr_t), 0, 3, "k", "i", (int (*)(CSOUND*,void*)) &la_k_norm1_mr_t::init_, (int (*)(CSOUND*,void*)) &la_k_norm1_mr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_norm1_mc", sizeof(la_i_norm1_mc_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_norm1_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_norm1_mc", sizeof(la_k_norm1_mc_t), 0, 3, "k", "i", (int (*)(CSOUND*,void*)) &la_k_norm1_mc_t::init_, (int (*)(CSOUND*,void*)) &la_k_norm1_mc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_norm_euclid_vr", sizeof(la_i_norm_euclid_vr_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_norm_euclid_vr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_norm_euclid_vr", sizeof(la_k_norm_euclid_vr_t), 0, 3, "k", "i", (int (*)(CSOUND*,void*)) &la_k_norm_euclid_vr_t::init_, (int (*)(CSOUND*,void*)) &la_k_norm_euclid_vr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_norm_euclid_vc", sizeof(la_i_norm_euclid_vc_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_norm_euclid_vc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_norm_euclid_vc", sizeof(la_k_norm_euclid_vc_t), 0, 3, "k", "i", (int (*)(CSOUND*,void*)) &la_k_norm_euclid_vc_t::init_, (int (*)(CSOUND*,void*)) &la_k_norm_euclid_vc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_norm_euclid_mr", sizeof(la_i_norm_euclid_mr_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_norm_euclid_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_norm_euclid_mr", sizeof(la_k_norm_euclid_mr_t), 0, 3, "k", "i", (int (*)(CSOUND*,void*)) &la_k_norm_euclid_mr_t::init_, (int (*)(CSOUND*,void*)) &la_k_norm_euclid_mr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_norm_euclid_mc", sizeof(la_i_norm_euclid_mc_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_norm_euclid_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_norm_euclid_mc", sizeof(la_k_norm_euclid_mc_t), 0, 3, "k", "i", (int (*)(CSOUND*,void*)) &la_k_norm_euclid_mc_t::init_, (int (*)(CSOUND*,void*))&la_k_norm_euclid_mc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_distance_vr", sizeof(la_i_distance_vr_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_distance_vr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_distance_vr", sizeof(la_k_distance_vr_t), 0, 3, "k", "ii", (int (*)(CSOUND*,void*)) &la_k_distance_vr_t::init_, (int (*)(CSOUND*,void*)) &la_k_distance_vr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_distance_vc", sizeof(la_i_distance_vc_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_distance_vc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_distance_vc", sizeof(la_k_distance_vc_t), 0, 3, "k", "ii", (int (*)(CSOUND*,void*)) &la_k_distance_vc_t::init_, (int (*)(CSOUND*,void*)) &la_k_distance_vc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_norm_max_mr", sizeof(la_i_norm_max_mr_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_norm_max_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_norm_max_mr", sizeof(la_k_norm_max_mr_t), 0, 3, "k", "i", (int (*)(CSOUND*,void*)) &la_k_norm_max_mr_t::init_, (int (*)(CSOUND*,void*)) &la_k_norm_max_mr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_norm_max_mc", sizeof(la_i_norm_max_mc_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_norm_max_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_norm_max_mc", sizeof(la_k_norm_max_mc_t), 0, 3, "k", "i", (int (*)(CSOUND*,void*)) &la_k_norm_max_mc_t::init_, (int (*)(CSOUND*,void*)) &la_k_norm_max_mc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_norm_inf_vr", sizeof(la_i_norm_inf_vr_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_norm_inf_vr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_norm_inf_vr", sizeof(la_k_norm_inf_vr_t), 0, 3, "k", "i", (int (*)(CSOUND*,void*)) &la_k_norm_inf_vr_t::init_, (int (*)(CSOUND*,void*)) &la_k_norm_inf_vr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_norm_inf_vc", sizeof(la_i_norm_inf_vc_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_norm_inf_vc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_norm_inf_vc", sizeof(la_k_norm_inf_vc_t), 0, 3, "k", "i", (int (*)(CSOUND*,void*)) &la_k_norm_inf_vc_t::init_, (int (*)(CSOUND*,void*)) &la_k_norm_inf_vc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_norm_inf_mr", sizeof(la_i_norm_inf_mr_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_norm_inf_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_norm_inf_mr", sizeof(la_k_norm_inf_mr_t), 0, 3, "k", "i", (int (*)(CSOUND*,void*)) &la_k_norm_inf_mr_t::init_, (int (*)(CSOUND*,void*)) &la_k_norm_inf_mr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_norm_inf_mc", sizeof(la_i_norm_inf_mc_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_norm_inf_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_norm_inf_mc", sizeof(la_k_norm_inf_mc_t), 0, 3, "k", "i", (int (*)(CSOUND*,void*)) &la_k_norm_inf_mc_t::init_, (int (*)(CSOUND*,void*)) &la_k_norm_inf_mc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_trace_mr", sizeof(la_i_trace_mr_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_trace_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_trace_mr", sizeof(la_k_trace_mr_t), 0, 3, "k", "i", (int (*)(CSOUND*,void*)) &la_k_trace_mr_t::init_, (int (*)(CSOUND*,void*)) &la_k_trace_mr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_trace_mc", sizeof(la_i_trace_mc_t), 0, 1, "ii", "i", (int (*)(CSOUND*,void*)) &la_i_trace_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_trace_mc", sizeof(la_k_trace_mc_t), 0, 3, "kk", "i", (int (*)(CSOUND*,void*)) &la_k_trace_mc_t::init_, (int (*)(CSOUND*,void*)) &la_k_trace_mc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_lu_det_mr", sizeof(la_i_lu_det_mr_t), 0, 1, "i", "i", (int (*)(CSOUND*,void*)) &la_i_lu_det_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_lu_det_mr", sizeof(la_k_lu_det_mr_t), 0, 3, "k", "i", (int (*)(CSOUND*,void*)) &la_k_lu_det_mr_t::init_, (int (*)(CSOUND*,void*)) &la_k_lu_det_mr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_lu_det_mc", sizeof(la_i_lu_det_mc_t), 0, 1, "ii", "i", (int (*)(CSOUND*,void*)) &la_i_lu_det_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_lu_det_mc", sizeof(la_k_lu_det_mc_t), 0, 3, "kk", "i", (int (*)(CSOUND*,void*)) &la_k_lu_det_mc_t::init_, (int (*)(CSOUND*,void*)) &la_k_lu_det_mc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_add_vr", sizeof(la_i_add_vr_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_add_vr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_add_vr", sizeof(la_k_add_vr_t), 0, 3, "i", "ii", (int (*)(CSOUND*,void*)) &la_k_add_vr_t::init_, (int (*)(CSOUND*,void*)) &la_k_add_vr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_add_vc", sizeof(la_i_add_vc_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_add_vc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_add_vc", sizeof(la_k_add_vc_t), 0, 3, "i", "ii", (int (*)(CSOUND*,void*)) &la_k_add_vc_t::init_, (int (*)(CSOUND*,void*)) &la_k_add_vc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_add_mr", sizeof(la_i_add_mr_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_add_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_add_mr", sizeof(la_k_add_mr_t), 0, 3, "i", "ii", (int (*)(CSOUND*,void*)) &la_k_add_mr_t::init_, (int (*)(CSOUND*,void*)) &la_k_add_mr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_add_mc", sizeof(la_i_add_mc_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_add_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_add_mc", sizeof(la_k_add_mc_t), 0, 3, "i", "ii", (int (*)(CSOUND*,void*)) &la_k_add_mc_t::init_, (int (*)(CSOUND*,void*)) &la_k_add_mc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_subtract_vr", sizeof(la_i_subtract_vr_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_subtract_vr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_subtract_vr", sizeof(la_k_subtract_vr_t), 0, 3, "i", "ii", (int (*)(CSOUND*,void*)) &la_k_subtract_vr_t::init_, (int (*)(CSOUND*,void*)) &la_k_subtract_vr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_subtract_vc", sizeof(la_i_subtract_vc_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_subtract_vc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_subtract_vc", sizeof(la_k_subtract_vc_t), 0, 3, "i", "ii", (int (*)(CSOUND*,void*)) &la_k_subtract_vc_t::init_, (int (*)(CSOUND*,void*)) &la_k_subtract_vc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_subtract_mr", sizeof(la_i_subtract_mr_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_subtract_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_subtract_mr", sizeof(la_k_subtract_mr_t), 0, 3, "i", "ii", (int (*)(CSOUND*,void*)) &la_k_subtract_mr_t::init_, (int (*)(CSOUND*,void*)) &la_k_subtract_mr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_subtract_mc", sizeof(la_i_subtract_mc_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_subtract_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_subtract_mc", sizeof(la_k_subtract_mc_t), 0, 3, "i", "ii", (int (*)(CSOUND*,void*)) &la_k_subtract_mc_t::init_, (int (*)(CSOUND*,void*)) &la_k_subtract_mc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_multiply_vr", sizeof(la_i_multiply_vr_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_multiply_vr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_multiply_vr", sizeof(la_k_multiply_vr_t), 0, 3, "i", "ii", (int (*)(CSOUND*,void*)) &la_k_multiply_vr_t::init_, (int (*)(CSOUND*,void*)) &la_k_multiply_vr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_multiply_vc", sizeof(la_i_multiply_vc_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_multiply_vc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_multiply_vc", sizeof(la_k_multiply_vc_t), 0, 3, "i", "ii", (int (*)(CSOUND*,void*)) &la_k_multiply_vc_t::init_, (int (*)(CSOUND*,void*)) &la_k_multiply_vc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_multiply_mr", sizeof(la_i_multiply_mr_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_multiply_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_multiply_mr", sizeof(la_k_multiply_mr_t), 0, 3, "i", "ii", (int (*)(CSOUND*,void*)) &la_k_multiply_mr_t::init_, (int (*)(CSOUND*,void*)) &la_k_multiply_mr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_multiply_mc", sizeof(la_i_multiply_mc_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_multiply_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_multiply_mc", sizeof(la_k_multiply_mc_t), 0, 3, "i", "ii", (int (*)(CSOUND*,void*)) &la_k_multiply_mc_t::init_, (int (*)(CSOUND*,void*)) &la_k_multiply_mc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_divide_vr", sizeof(la_i_divide_vr_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_divide_vr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_divide_vr", sizeof(la_k_divide_vr_t), 0, 3, "i", "ii", (int (*)(CSOUND*,void*)) &la_k_divide_vr_t::init_, (int (*)(CSOUND*,void*)) &la_k_divide_vr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_divide_vc", sizeof(la_i_divide_vc_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_divide_vc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_divide_vc", sizeof(la_k_divide_vc_t), 0, 3, "i", "kk", (int (*)(CSOUND*,void*)) &la_k_divide_vc_t::init_, (int (*)(CSOUND*,void*)) &la_k_divide_vc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_divide_mr", sizeof(la_i_divide_mr_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_divide_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_divide_mr", sizeof(la_k_divide_mr_t), 0, 3, "i", "ii", (int (*)(CSOUND*,void*)) &la_k_divide_mr_t::init_, (int (*)(CSOUND*,void*)) &la_k_divide_mr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_divide_mc", sizeof(la_i_divide_mc_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_divide_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_divide_mc", sizeof(la_k_divide_mc_t), 0, 3, "i", "ii", (int (*)(CSOUND*,void*)) &la_k_divide_mc_t::init_, (int (*)(CSOUND*,void*)) &la_k_divide_mc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_dot_vr", sizeof(la_i_dot_vr_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_dot_vr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_dot_vr", sizeof(la_k_dot_vr_t), 0, 3, "i", "ii", (int (*)(CSOUND*,void*)) &la_k_dot_vr_t::init_, (int (*)(CSOUND*,void*)) &la_k_dot_vr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_dot_vc", sizeof(la_i_dot_vc_t), 0, 1, "ii", "ii", (int (*)(CSOUND*,void*)) &la_i_dot_vc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_dot_vc", sizeof(la_k_dot_vc_t), 0, 3, "ii", "ii", (int (*)(CSOUND*,void*)) &la_k_dot_vc_t::init_, (int (*)(CSOUND*,void*)) &la_k_dot_vc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_dot_mr", sizeof(la_i_dot_mr_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_dot_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_dot_mr", sizeof(la_k_dot_mr_t), 0, 3, "i", "ii", (int (*)(CSOUND*,void*)) &la_k_dot_mr_t::init_, (int (*)(CSOUND*,void*)) &la_k_dot_mr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_dot_mc", sizeof(la_i_dot_mc_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_dot_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_dot_mc", sizeof(la_k_dot_mc_t), 0, 3, "i", "ii", (int (*)(CSOUND*,void*)) &la_k_dot_mc_t::init_, (int (*)(CSOUND*,void*)) &la_k_dot_mc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_dot_mr_vr", sizeof(la_i_dot_mr_vr_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_dot_mr_vr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_dot_mr_vr", sizeof(la_k_dot_mr_vr_t), 0, 3, "i", "ii", (int (*)(CSOUND*,void*)) &la_k_dot_mr_vr_t::init_, (int (*)(CSOUND*,void*)) &la_k_dot_mr_vr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_dot_mc_vc", sizeof(la_i_dot_mc_vc_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_dot_mc_vc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_dot_mc_vc", sizeof(la_k_dot_mc_vc_t), 0, 3, "i", "ii", (int (*)(CSOUND*,void*)) &la_k_dot_mc_vc_t::init_, (int (*)(CSOUND*,void*)) &la_k_dot_mc_vc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_invert_mr", sizeof(la_i_invert_mr_t), 0, 1, "ii", "i", (int (*)(CSOUND*,void*)) &la_i_invert_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_invert_mr", sizeof(la_k_invert_mr_t), 0, 3, "ik", "i", (int (*)(CSOUND*,void*)) &la_k_invert_mr_t::init_, (int (*)(CSOUND*,void*)) &la_k_invert_mr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_invert_mc", sizeof(la_i_invert_mc_t), 0, 1, "iii", "i", (int (*)(CSOUND*,void*)) &la_i_invert_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_invert_mc", sizeof(la_k_invert_mc_t), 0, 3, "ikk", "i", (int (*)(CSOUND*,void*)) &la_k_invert_mc_t::init_, (int (*)(CSOUND*,void*)) &la_k_invert_mc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_upper_solve_mr", sizeof(la_i_upper_solve_mr_t), 0, 1, "i", "io", (int (*)(CSOUND*,void*)) &la_i_upper_solve_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_upper_solve_mr", sizeof(la_k_upper_solve_mr_t), 0, 3, "i", "iO", (int (*)(CSOUND*,void*)) &la_k_upper_solve_mr_t::init_, (int (*)(CSOUND*,void*)) &la_k_upper_solve_mr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_upper_solve_mc", sizeof(la_i_upper_solve_mc_t), 0, 1, "i", "io", (int (*)(CSOUND*,void*)) &la_i_upper_solve_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_upper_solve_mc", sizeof(la_k_upper_solve_mc_t), 0, 3, "i", "iO", (int (*)(CSOUND*,void*)) &la_k_upper_solve_mc_t::init_, (int (*)(CSOUND*,void*)) &la_k_upper_solve_mc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_lower_solve_mr", sizeof(la_i_lower_solve_mr_t), 0, 1, "i", "io", (int (*)(CSOUND*,void*)) &la_i_lower_solve_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_lower_solve_mr", sizeof(la_k_lower_solve_mr_t), 0, 3, "i", "iO", (int (*)(CSOUND*,void*)) &la_k_lower_solve_mr_t::init_, (int (*)(CSOUND*,void*)) &la_k_lower_solve_mr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_lower_solve_mc", sizeof(la_i_lower_solve_mc_t), 0, 1, "i", "io", (int (*)(CSOUND*,void*)) &la_i_lower_solve_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_lower_solve_mc", sizeof(la_k_lower_solve_mc_t), 0, 3, "i", "iO", (int (*)(CSOUND*,void*)) &la_k_lower_solve_mc_t::init_, (int (*)(CSOUND*,void*)) &la_k_lower_solve_mc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_lu_factor_mr", sizeof(la_i_lu_factor_mr_t), 0, 1, "iii", "i", (int (*)(CSOUND*,void*)) &la_i_lu_factor_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_lu_factor_mr", sizeof(la_k_lu_factor_mr_t), 0, 3, "iik", "i", (int (*)(CSOUND*,void*)) &la_k_lu_factor_mr_t::init_, (int (*)(CSOUND*,void*)) &la_k_lu_factor_mr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_lu_factor_mc", sizeof(la_i_lu_factor_mc_t), 0, 1, "iii", "i", (int (*)(CSOUND*,void*)) &la_i_lu_factor_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_lu_factor_mc", sizeof(la_k_lu_factor_mc_t), 0, 3, "i", "i", (int (*)(CSOUND*,void*)) &la_k_lu_factor_mc_t::init_, (int (*)(CSOUND*,void*)) &la_k_lu_factor_mc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_lu_solve_mr", sizeof(la_i_lu_solve_mr_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_lu_solve_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_lu_solve_mr", sizeof(la_k_lu_solve_mr_t), 0, 3, "i", "ii", (int (*)(CSOUND*,void*)) &la_k_lu_solve_mr_t::init_, (int (*)(CSOUND*,void*)) &la_k_lu_solve_mr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_lu_solve_mc", sizeof(la_i_lu_solve_mc_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_lu_solve_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_lu_solve_mc", sizeof(la_k_lu_solve_mc_t), 0, 3, "i", "ii", (int (*)(CSOUND*,void*)) &la_k_lu_solve_mc_t::init_, (int (*)(CSOUND*,void*)) &la_k_lu_solve_mc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_qr_factor_mr", sizeof(la_i_qr_factor_mr_t), 0, 1, "ii", "i", (int (*)(CSOUND*,void*)) &la_i_qr_factor_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_qr_factor_mr", sizeof(la_k_qr_factor_mr_t), 0, 3, "ii", "i", (int (*)(CSOUND*,void*)) &la_k_qr_factor_mr_t::init_, (int (*)(CSOUND*,void*)) &la_k_qr_factor_mr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_qr_factor_mc", sizeof(la_i_qr_factor_mc_t), 0, 1, "ii", "i", (int (*)(CSOUND*,void*)) &la_i_qr_factor_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_qr_factor_mc", sizeof(la_k_qr_factor_mc_t), 0, 3, "ii", "i", (int (*)(CSOUND*,void*)) &la_k_qr_factor_mc_t::init_, (int (*)(CSOUND*,void*)) &la_k_qr_factor_mc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_qr_eigen_mr", sizeof(la_i_qr_eigen_mr_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_qr_eigen_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_qr_eigen_mr", sizeof(la_k_qr_eigen_mr_t), 0, 3, "i", "ik", (int (*)(CSOUND*,void*)) &la_k_qr_eigen_mr_t::init_, (int (*)(CSOUND*,void*)) &la_k_qr_eigen_mr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_qr_eigen_mc", sizeof(la_i_qr_eigen_mc_t), 0, 1, "i", "ii", (int (*)(CSOUND*,void*)) &la_i_qr_eigen_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_qr_eigen_mc", sizeof(la_k_qr_eigen_mc_t), 0, 3, "i", "ik", (int (*)(CSOUND*,void*)) &la_k_qr_eigen_mc_t::init_, (int (*)(CSOUND*,void*)) &la_k_qr_eigen_mc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_qr_sym_eigen_mr", sizeof(la_i_qr_sym_eigen_mr_t), 0, 1, "ii", "ii", (int (*)(CSOUND*,void*)) &la_i_qr_sym_eigen_mr_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_qr_sym_eigen_mr", sizeof(la_k_qr_sym_eigen_mr_t), 0, 3, "ii", "ik", (int (*)(CSOUND*,void*)) &la_k_qr_sym_eigen_mr_t::init_, (int (*)(CSOUND*,void*)) &la_k_qr_sym_eigen_mr_t::kontrol_, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_i_qr_sym_eigen_mc", sizeof(la_i_qr_sym_eigen_mc_t), 0, 1, "ii", "ii", (int (*)(CSOUND*,void*)) &la_i_qr_sym_eigen_mc_t::init_, (int (*)(CSOUND*,void*)) 0, (int (*)(CSOUND*,void*)) 0); status |= csound->AppendOpcode(csound, "la_k_qr_sym_eigen_mc", sizeof(la_k_qr_sym_eigen_mc_t), 0, 3, "ii", "ik", (int (*)(CSOUND*,void*)) &la_k_qr_sym_eigen_mc_t::init_, (int (*)(CSOUND*,void*)) &la_k_qr_sym_eigen_mc_t::kontrol_, (int (*)(CSOUND*,void*)) 0); return status; } PUBLIC int csoundModuleDestroy(CSOUND *csound) { return 0; } } csound-6.10.0/Opcodes/linuxjoystick.c000066400000000000000000000122161321653344700175620ustar00rootroot00000000000000/* linuxjoystick.c: Copyright (C) 2010 Justin Glenn Smith This Csound plugin is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This plugin is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this plugin; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA USAGE: kresultmask linuxjoystick kdevice ktab kdevice = The index of the joystick device, either /dev/js or /dev/input/js ktab = A table to hold input results, should be at least enough elements to store one value for each stick axis and one for each button + 2. The first two elements of the table are initialized with the number of axes and the number of buttons, respectively, when a joystick is opened. If a joystick is unplugged during performance, the opcode will repeatedly attempt to reopen the device with a delay between attempts. kresultmask: A bitmask, with a 1 bit for each table index with a new input received. */ #include "linuxjoystick.h" #include static int linuxjoystick (CSOUND *csound, LINUXJOYSTICK *stick) { static int read_pos = 0; struct js_event js; int read_size; int getmore; int evtidx; long long evtmask = 0; char device[256]; if (UNLIKELY(stick->initme == 0)) { stick->timeout = 0; stick->devFD = -10; stick->initme = 1; } if (UNLIKELY(*stick->ktable != stick->table)) { if (UNLIKELY((void *)(stick->ftp = csound->FTnp2Find(csound, stick->ktable)) == NULL)) { csound->Warning(csound, Str("linuxjoystick: No such table %f"), *(float*)(stick->ktable)); return OK; } stick->table = *stick->ktable; } if (stick->devFD < 0 || *stick->kdev != stick->dev) { if (stick->timeout > 0 && *stick->kdev == stick->dev) { (stick->timeout)--; return OK; } stick->dev = (int)MYFLT2LRND(*stick->kdev); snprintf(device, 256, "/dev/js%i", stick->dev); if ((stick->devFD = open(device, O_RDONLY, O_NONBLOCK)) < 0) { snprintf(device, 256, "/dev/input/js%i", stick->dev); stick->devFD = open(device, O_RDONLY, O_NONBLOCK); } if (LIKELY(stick->devFD > 0)) { fcntl(stick->devFD, F_SETFL, fcntl(stick->devFD, F_GETFL, 0)|O_NONBLOCK); ioctl(stick->devFD, JSIOCGAXES, &stick->numk); ioctl(stick->devFD, JSIOCGBUTTONS, &stick->numb); if (UNLIKELY(stick->ftp->flen < 2u+(stick->numk)+(stick->numb))) { csound->Warning (csound, Str("linuxjoystick: table %d of size %d too small for data size %d"), (int)stick->table, stick->ftp->flen, 2+stick->numk+stick->numb); return OK; } stick->ftp->ftable[ 0 ] = (MYFLT) stick->numk; stick->ftp->ftable[ 1 ] = (MYFLT) stick->numb; evtmask = 3; } else { stick->timeout = 10000; csound->Warning(csound, Str("linuxjoystick: could not open device " "/dev/input/js%d for reason: %s\n"), stick->dev, strerror(errno)); csound->Warning(csound, Str("linuxjoystick: could not open device " "/dev/js%d for reason: %s\n"), stick->dev, strerror(errno)); return OK; } } getmore = 1; while (getmore) { read_size = read(stick->devFD, (void *) &js+read_pos, sizeof(struct js_event)-read_pos); if (read_size == -1 && errno == EAGAIN ) { getmore = 0; } else if (UNLIKELY(read_size < 1)) { csound->Warning(csound, Str("linuxjoystick: read %d closing joystick"), read_size); close(stick->devFD); stick->devFD = -1; getmore = 0; } else { read_pos += read_size; if (read_pos == sizeof(struct js_event)) { read_pos = 0; if (js.type & JS_EVENT_AXIS) { evtidx = 2 + js.number; } else if (js.type & JS_EVENT_BUTTON) { evtidx = 2 + stick->numk + js.number; } else { csound->Warning(csound, Str("unknown joystick event type %i"), js.type); return OK; } evtmask = evtmask | (1 << evtidx); stick->ftp->ftable[ evtidx ] = (MYFLT) js.value; } } } *stick->kresult = (MYFLT) evtmask; return OK; } static OENTRY localops[] = { { "joystick", sizeof(LINUXJOYSTICK), 0, 2, "k", "kk", NULL, (SUBR) linuxjoystick, NULL }, }; LINKAGE csound-6.10.0/Opcodes/linuxjoystick.h000066400000000000000000000020461321653344700175670ustar00rootroot00000000000000/* linuxjoystick.c: Copyright (C) 2010 Justin Glenn Smith This Csound plugin is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This plugin is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this plugin; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "csdl.h" #include "linux/joystick.h" typedef struct { OPDS h; MYFLT *kresult, *kdev, *ktable; int devFD; unsigned int numk, numb; int timeout, initme; MYFLT table; int dev; FUNC *ftp; } LINUXJOYSTICK; csound-6.10.0/Opcodes/liveconv.c000066400000000000000000000403661321653344700164770ustar00rootroot00000000000000/* liveconv.c: Copyright (C) 2017 Sigurd Saue, Oeyvind Brandtsegg This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* The implementation is indebted to the ftconv opcode by Istvan Varga 2005 */ #include "csdl.h" #include /* ** Data structures holding the load/unload information */ typedef struct { enum { NO_LOAD, LOADING, UNLOADING } status; int pos; } load_t; typedef struct { load_t *begin; load_t *end; load_t *head; int available; } rbload_t; static inline void init_load(rbload_t *buffer, int size) { load_t* iter = buffer->begin; buffer->head = buffer->begin; buffer->end = buffer->begin + size; buffer->available = 1; for (iter = buffer->begin; iter != buffer->end; iter++) { iter->status = NO_LOAD; iter->pos = 0; } } static inline load_t* next_load(const rbload_t *buffer, load_t* const now) { load_t *temp = now + 1; if (UNLIKELY(temp == buffer->end)) { temp = buffer->begin; } return temp; } static inline load_t* previous_load(const rbload_t *buffer, load_t* const now) { return (now == buffer->begin) ? (buffer->end - 1) : (now - 1); } /* ** liveconv - data structure holding the internal state */ typedef struct { /* ** Input parameters given by user */ OPDS h; MYFLT *aOut; // output buffer MYFLT *aIn; // input buffer MYFLT *iFTNum; // impulse respons table MYFLT *iPartLen; // length of impulse response partitions // (latency <-> CPU usage) MYFLT *kUpdate; // Control variable for updating the IR buffer // (+1 is start load, -1 is start unload) MYFLT *kClear; // Clear output buffers /* ** Internal state of opcode maintained outside */ int initDone; /* flag to indicate initialization */ int cnt; /* buffer position, 0 to partSize - 1 */ int nPartitions; /* number of convolve partitions */ int partSize; /* partition length in sample frames (= iPartLen as integer) */ int rbCnt; /* ring buffer index, 0 to nPartitions - 1 */ /* The following pointer point into the auxData buffer */ MYFLT *tmpBuf; /* temporary buffer for accumulating FFTs */ MYFLT *ringBuf; /* ring buffer of FFTs of input partitions - these buffers are now computed during init */ MYFLT *IR_Data; /* impulse responses (scaled) */ MYFLT *outBuf; /* output buffer (size=partSize*2) */ rbload_t loader; /* Bookkeeping of load/unload operations */ void *fwdsetup, *invsetup; AUXCH auxData; /* Aux data buffer allocated in init pass */ } liveconv_t; /* ** Function to multiply the FFT buffers ** outBuf - the output of the operation (called with tmpBuf), single channel only ** ringBuf - the partitions of the single input signal ** IR_data - the impulse response of a particular channel ** partSize - size of partition ** nPartitions - number of partitions ** ringBuf_startPos - the starting position of the ring buffer ** (corresponds to the start of the partition after the ** last filled partition) */ static void multiply_fft_buffers(MYFLT *outBuf, MYFLT *ringBuf, MYFLT *IR_Data, int partSize, int nPartitions, int ringBuf_startPos) { MYFLT re, im, re1, re2, im1, im2; MYFLT *rbPtr, *irPtr, *outBufPtr, *outBufEndPm2, *rbEndP; /* note: partSize must be at least 2 samples */ partSize <<= 1; /* locale partsize is twice the size of the partition size */ /* Finding the index of the last sample pair in the output buffer */ outBufEndPm2 = (MYFLT*) outBuf + (int) (partSize - 2); /* The end of the ring buffer */ rbEndP = (MYFLT*) ringBuf + (int) (partSize * nPartitions); rbPtr = &(ringBuf[ringBuf_startPos]); /* Initialize ring buffer pointer */ irPtr = IR_Data; /* Initialize impulse data pointer */ outBufPtr = outBuf; /* Initialize output buffer pointer */ /* clear output buffer to zero */ memset(outBuf, 0, sizeof(MYFLT)*partSize); /* ** Multiply FFTs for each partition and mix to output buffer ** Note: IRs are stored in reverse partition order */ do { /* wrap ring buffer position */ if (rbPtr >= rbEndP) rbPtr = ringBuf; outBufPtr = outBuf; *(outBufPtr++) += *(rbPtr++) * *(irPtr++); /* convolve DC - real part only */ *(outBufPtr++) += *(rbPtr++) * *(irPtr++); /* convolve Nyquist - real part only */ re1 = *(rbPtr++); im1 = *(rbPtr++); re2 = *(irPtr++); im2 = *(irPtr++); /* ** Status: ** outBuf + 2, ringBuf + 4, irBuf + 4 ** re = buf + 2, im = buf + 3 */ re = re1 * re2 - im1 * im2; im = re1 * im2 + re2 * im1; while (outBufPtr < outBufEndPm2) { /* complex multiply */ re1 = rbPtr[0]; im1 = rbPtr[1]; re2 = irPtr[0]; im2 = irPtr[1]; outBufPtr[0] += re; outBufPtr[1] += im; re = re1 * re2 - im1 * im2; im = re1 * im2 + re2 * im1; re1 = rbPtr[2]; im1 = rbPtr[3]; re2 = irPtr[2]; im2 = irPtr[3]; outBufPtr[2] += re; outBufPtr[3] += im; re = re1 * re2 - im1 * im2; im = re1 * im2 + re2 * im1; outBufPtr += 4; rbPtr += 4; irPtr += 4; /* ** Status: ** outBuf + 2 + 4n, ringBuf + 4 + 4n, irBuf + 4 + 4n ** re = buf + 2 + 4n, im = buf + 3 + 4n */ } outBufPtr[0] += re; outBufPtr[1] += im; } while (--nPartitions); } static inline int buf_bytes_alloc(int partSize, int nPartitions) { int nSmps; nSmps = (partSize << 1); /* tmpBuf */ nSmps += ((partSize << 1) * nPartitions); /* ringBuf */ nSmps += ((partSize << 1) * nPartitions); /* IR_Data */ nSmps += ((partSize << 1)); /* outBuf */ nSmps *= (int) sizeof(MYFLT); /* Buffer type MYFLT */ nSmps += (nPartitions+1) * (int) sizeof(load_t); /* Load/unload structure */ /* One load/unload pr. partitions and an extra for buffering is sufficient */ return nSmps; } static void set_buf_pointers(liveconv_t *p, int partSize, int nPartitions) { MYFLT *ptr; ptr = (MYFLT*) (p->auxData.auxp); p->tmpBuf = ptr; ptr += (partSize << 1); p->ringBuf = ptr; ptr += ((partSize << 1) * nPartitions); p->IR_Data = ptr; ptr += ((partSize << 1) * nPartitions); p->outBuf = ptr; ptr += (partSize << 1); p->loader.begin = (load_t*) ptr; } static int liveconv_init(CSOUND *csound, liveconv_t *p) { FUNC *ftp; // function table int n, nBytes; /* set p->partSize to the initial partition length, iPartLen */ p->partSize = MYFLT2LRND(*(p->iPartLen)); if (UNLIKELY(p->partSize < 4 || (p->partSize & (p->partSize - 1)) != 0)) { // Must be a power of 2 at least as large as 4 return csound->InitError(csound, Str("liveconv: invalid impulse response " "partition length")); } /* Find and assign the function table numbered iFTNum */ ftp = csound->FTnp2Find(csound, p->iFTNum); if (UNLIKELY(ftp == NULL)) return NOTOK; /* ftfind should already have printed the error message */ /* Calculate the total length */ n = (int) ftp->flen; if (UNLIKELY(n <= 0)) { return csound->InitError(csound, Str("liveconv: invalid length, or insufficient" " IR data for convolution")); } // Compute the number of partitions (total length / partition size) p->nPartitions = (n + (p->partSize - 1)) / p->partSize; /* ** Calculate the amount of aux space to allocate (in bytes) and ** allocate if necessary ** Function of partition size and number of partitions */ nBytes = buf_bytes_alloc(p->partSize, p->nPartitions); if (nBytes != (int) p->auxData.size) csound->AuxAlloc(csound, (int32) nBytes, &(p->auxData)); /* ** From here on is initialization of data */ /* initialize buffer pointers */ set_buf_pointers(p, p->partSize, p->nPartitions); /* Initialize load bookkeeping */ init_load(&p->loader, (p->nPartitions + 1)); /* clear ring buffer to zero */ n = (p->partSize << 1) * p->nPartitions; memset(p->ringBuf, 0, n*sizeof(MYFLT)); /* initialize buffer indices */ p->cnt = 0; p->rbCnt = 0; p->fwdsetup = csound->RealFFT2Setup(csound, (p->partSize << 1), FFT_FWD); p->invsetup = csound->RealFFT2Setup(csound, (p->partSize << 1), FFT_INV); /* clear IR buffer to zero */ memset(p->IR_Data, 0, n*sizeof(MYFLT)); /* clear output buffers to zero */ memset(p->outBuf, 0, (p->partSize << 1)*sizeof(MYFLT)); /* ** After initialization: ** Buffer indexes are zero ** tmpBuf is filled with rubish ** ringBuf and outBuf are filled with zero ** IR_Data buffers are filled with zero */ p->initDone = 1; return OK; } static int liveconv_perf(CSOUND *csound, liveconv_t *p) { MYFLT *x, *rBuf; FUNC *ftp; // function table int i, k, n, nSamples, rBufPos, updateIR, clearBuf, nPart, cnt; load_t *load_ptr; // uint32_t numLoad = p->nPartitions + 1; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, nsmps = CS_KSMPS; /* Only continue if initialized */ if (UNLIKELY(p->initDone <= 0)) goto err1; ftp = csound->FTnp2Find(csound, p->iFTNum); nSamples = p->partSize; /* Length of partition */ /* Pointer to a partition of the ring buffer */ rBuf = &(p->ringBuf[p->rbCnt * (nSamples << 1)]); if (UNLIKELY(offset)) memset(p->aOut, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->aOut[nsmps], '\0', early*sizeof(MYFLT)); } /* If clear flag is set: empty buffers and reset indexes */ clearBuf = MYFLT2LRND(*(p->kClear)); if (clearBuf) { /* clear ring buffer to zero */ n = (nSamples << 1) * p->nPartitions; memset(p->ringBuf, 0, n*sizeof(MYFLT)); /* initialize buffer index */ p->cnt = 0; p->rbCnt = 0; /* clear output buffers to zero */ memset(p->outBuf, 0, (nSamples << 1)*sizeof(MYFLT)); } /* ** How to handle the kUpdate input: ** -1: Gradually clear the IR buffer ** 0: Do nothing ** 1: Gradually load the IR buffer */ if (p->loader.available) { // The buffer before the head position is the temporary buffer load_ptr = previous_load(&p->loader, p->loader.head); updateIR = MYFLT2LRND(*(p->kUpdate)); if (updateIR == 1) { load_ptr->status = LOADING; load_ptr->pos = 0; } else if (updateIR == -1) { load_ptr->status = UNLOADING; load_ptr->pos = 0; } if (load_ptr->status != NO_LOAD) { p->loader.available = 0; /* Special case: At a partition border: Make the temporary buffer head position */ if (p->cnt == 0) p->loader.head = load_ptr; } } /* For each sample in the audio input buffer (length = ksmps) */ for (nn = offset; nn < nsmps; nn++) { /* store input signal in buffer */ rBuf[p->cnt] = p->aIn[nn]; /* copy output signals from buffer (contains data from previous convolution pass) */ p->aOut[nn] = p->outBuf[p->cnt]; /* is input buffer full ? */ if (++p->cnt < nSamples) continue; /* no, continue with next sample */ /* Check if there are any IR partitions to load/unload */ load_ptr = p->loader.head; while (load_ptr->status != NO_LOAD) { cnt = load_ptr->pos; if (load_ptr->status == LOADING) { nPart = cnt / nSamples + 1; /* IR write position, starting with the last! */ n = (nSamples << 1) * (p->nPartitions - nPart); /* Iterate over IR partitions in reverse order */ for (k = 0; k < nSamples; k++) { /* Fill IR_Data with scaled IR data, or zero if outside the IR buffer */ p->IR_Data[n + k] = (cnt < (int)ftp->flen) ? ftp->ftable[cnt] : FL(0.0); cnt++; } /* pad second half of IR to zero */ for (k = nSamples; k < (nSamples << 1); k++) p->IR_Data[n + k] = FL(0.0); /* calculate FFT (replace in the same buffer) */ csound->RealFFT2(csound, p->fwdsetup, &(p->IR_Data[n])); } else if (load_ptr->status == UNLOADING) { nPart = cnt / nSamples + 1; /* IR write position, starting with the last! */ n = (nSamples << 1) * (p->nPartitions - nPart); memset(p->IR_Data + n, 0, (nSamples << 1)*sizeof(MYFLT)); } // Update load buffer and move to the next buffer load_ptr->pos += nSamples; if (load_ptr->pos >= p->nPartitions * nSamples) { load_ptr->status = NO_LOAD; } load_ptr = next_load(&p->loader, load_ptr); } p->loader.available = 1; // Check if there is a temporary buffer ready to get loaded with the // next partition load_ptr = previous_load(&p->loader, p->loader.head); if (load_ptr->status != NO_LOAD) p->loader.head = load_ptr; /* Now the partition is filled with input --> start calculate the convolution */ p->cnt = 0; /* reset buffer position */ /* pad input in ring buffer with zeros to double length */ for (i = nSamples; i < (nSamples << 1); i++) rBuf[i] = FL(0.0); /* calculate FFT of input */ csound->RealFFT2(csound, p->fwdsetup, rBuf); /* update ring buffer position */ p->rbCnt++; if (p->rbCnt >= p->nPartitions) p->rbCnt = 0; rBufPos = p->rbCnt * (nSamples << 1); /* Move to next partition in ring buffer (used in next iteration to store the next input sample) */ rBuf = &(p->ringBuf[rBufPos]); /* multiply complex arrays --> multiplication in the frequency domain */ multiply_fft_buffers(p->tmpBuf, p->ringBuf, p->IR_Data, nSamples, p->nPartitions, rBufPos); /* inverse FFT */ csound->RealFFT2(csound, p->invsetup, p->tmpBuf); /* ** Copy IFFT result to output buffer ** The second half is left as "tail" for next iteration ** The first half is overlapped with "tail" of previous block */ x = &(p->outBuf[0]); for (i = 0; i < nSamples; i++) { x[i] = p->tmpBuf[i] + x[i + nSamples]; x[i + nSamples] = p->tmpBuf[i + nSamples]; } } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("liveconv: not initialised")); } /* module interface functions */ static OENTRY localops[] = { { "liveconv", // name of opcode sizeof(liveconv_t), // data size of state block TR, 5, // thread "a", // output arguments "aiikk", // input arguments (SUBR) liveconv_init, // init function (SUBR) NULL, // k-rate function (SUBR) liveconv_perf // a-rate function } }; LINKAGE csound-6.10.0/Opcodes/locsig.c000066400000000000000000000156441321653344700161330ustar00rootroot00000000000000/* locsig.c: Copyright (C) 1998 Richard Karpen This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /*LOCSIG*/ /******************************************/ /* The applications in this file were */ /* designed and coded by Richard Karpen */ /* University of Washington, Seattle 1998 */ /******************************************/ #include "stdopcod.h" #include "locsig.h" #include static int locsigset(CSOUND *csound, LOCSIG *p) { STDOPCOD_GLOBALS *pp; int outcount = p->OUTOCOUNT; if (UNLIKELY(outcount != 2 && outcount != 4)) return csound->InitError(csound, Str("Wrong number of outputs in locsig; " "must be 2 or 4")); if (p->auxch.auxp == NULL || p->auxch.sizeAuxAlloc(csound, (size_t) (CS_KSMPS * 4) * sizeof(MYFLT), &p->auxch); fltp = (MYFLT *) p->auxch.auxp; p->rrev1 = fltp; fltp += CS_KSMPS; p->rrev2 = fltp; fltp += CS_KSMPS; p->rrev3 = fltp; fltp += CS_KSMPS; p->rrev4 = fltp; fltp += CS_KSMPS; } p->prev_degree = -FL(918273645.192837465); p->prev_distance = -FL(918273645.192837465); pp = (STDOPCOD_GLOBALS*) csound->stdOp_Env; pp->locsigaddr = (void*) p; return OK; } static int locsig(CSOUND *csound, LOCSIG *p) { MYFLT *r1, *r2, *r3=NULL, *r4=NULL, degree, *asig; MYFLT direct, *rrev1, *rrev2, *rrev3=NULL, *rrev4=NULL; MYFLT torev, localrev, globalrev; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (*p->distance != p->prev_distance) { p->distr=(FL(1.0) / *p->distance); p->distrsq = FL(1.0)/SQRT(*p->distance); p->prev_distance = *p->distance; } if (*p->degree != p->prev_degree) { degree = *p->degree/FL(360.00); p->ch1 = COS(TWOPI_F * degree); if (p->ch1 < FL(0.0)) p->ch1 = FL(0.0); p->ch2 = SIN(TWOPI_F * degree); if (p->ch2 < FL(0.0)) p->ch2 = FL(0.0); if (p->OUTOCOUNT == 4) { p->ch3 = COS(TWOPI_F * (degree + FL(0.5))); if (p->ch3 < FL(0.0)) p->ch3 = FL(0.0); p->ch4 = SIN(TWOPI_F * (degree + FL(0.5))); if (p->ch4 < FL(0.0)) p->ch4 = FL(0.0); } p->prev_degree = *p->degree; } r1 = p->r1; r2 = p->r2; asig = p->asig; rrev1 = p->rrev1; rrev2 = p->rrev2; if (p->OUTOCOUNT == 4) { r3 = p->r3; r4 = p->r4; rrev3 = p->rrev3; rrev4 = p->rrev4; } if (UNLIKELY(offset)) { memset(r1, '\0', offset*sizeof(MYFLT)); memset(r2, '\0', offset*sizeof(MYFLT)); if (p->OUTOCOUNT == 4) { memset(r3, '\0', offset*sizeof(MYFLT)); memset(r4, '\0', offset*sizeof(MYFLT)); } } if (UNLIKELY(early)) { nsmps -= early; memset(&r1[nsmps], '\0', early*sizeof(MYFLT)); memset(&r2[nsmps], '\0', early*sizeof(MYFLT)); if (p->OUTOCOUNT == 4) { memset(&r3[nsmps], '\0', early*sizeof(MYFLT)); memset(&r4[nsmps], '\0', early*sizeof(MYFLT)); } } for (n=offset; ndistr; torev = asig[n] * p->distrsq * *p->reverbamount; globalrev = torev * p->distr; localrev = torev * (FL(1.0) - p->distr); r1[n] = direct * p->ch1; r2[n] = direct * p->ch2; rrev1[n] = (localrev * p->ch1) + globalrev; rrev2[n] = (localrev * p->ch2) + globalrev; if (p->OUTOCOUNT == 4) { r3[n] = direct * p->ch3; r4[n] = direct * p->ch4; rrev3[n] = (localrev* p->ch3) + globalrev; rrev4[n] = (localrev* p->ch4) + globalrev; } } return OK; } static int locsendset(CSOUND *csound, LOCSEND *p) { STDOPCOD_GLOBALS *pp; LOCSIG *q; pp = (STDOPCOD_GLOBALS*) csound->stdOp_Env; q = (LOCSIG*) pp->locsigaddr; p->locsig = q; if (UNLIKELY(p->OUTOCOUNT != q->OUTOCOUNT)) { return csound->InitError(csound, Str("Number of outputs must be the " "same as the previous locsig")); } return OK; } static int locsend(CSOUND *csound, LOCSEND *p) { /* MYFLT *r1, *r2, *r3=NULL, *r4=NULL; */ /* MYFLT *rrev1, *rrev2, *rrev3=NULL, *rrev4=NULL; */ LOCSIG *q = p->locsig; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; /* r1 = p->r1; */ /* r2 = p->r2; */ /* rrev1 = q->rrev1; */ /* rrev2 = q->rrev2; */ /* if (p->OUTOCOUNT == 4) { */ /* r3 = p->r3; */ /* r4 = p->r4; */ /* rrev3 = q->rrev3; */ /* rrev4 = q->rrev4; */ /* } */ /* for (n=0;nOUTOCOUNT == 4) { */ /* r3[n] = rrev3[n]; */ /* r4[n] = rrev4[n]; */ /* } */ /* } */ /* Quicker form is: */ if (UNLIKELY(offset)) { memset(p->r1, '\0', offset*sizeof(MYFLT)); memset(p->r2, '\0', offset*sizeof(MYFLT)); if (p->OUTOCOUNT == 4) { memset(p->r3, '\0', offset*sizeof(MYFLT)); memset(p->r4, '\0', offset*sizeof(MYFLT)); } } if (UNLIKELY(early)) { nsmps -= early; memset(&p->r1[nsmps], '\0', early*sizeof(MYFLT)); memset(&p->r2[nsmps], '\0', early*sizeof(MYFLT)); if (p->OUTOCOUNT == 4) { memset(&p->r3[nsmps], '\0', early*sizeof(MYFLT)); memset(&p->r4[nsmps], '\0', early*sizeof(MYFLT)); } } n = (nsmps-offset)*sizeof(MYFLT); memcpy(p->r1+offset, q->rrev1, n); memcpy(p->r2+offset, q->rrev2, n); if (p->OUTOCOUNT == 4) { memcpy(p->r3+offset, q->rrev3, n); memcpy(p->r4+offset, q->rrev4, n); } return OK; } #define S(x) sizeof(x) static OENTRY localops[] = { { "locsig", S(LOCSIG), 0, 5, "mmmm", "akkk", (SUBR)locsigset,NULL, (SUBR)locsig }, { "locsend", S(LOCSEND),0, 5, "mmmm", "",(SUBR)locsendset, NULL, (SUBR)locsend } }; int locsig_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/locsig.h000066400000000000000000000026741321653344700161370ustar00rootroot00000000000000/* locsig.h: Copyright (C) 1998 Richard Karpen This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* LOCSIG.H */ /******************************************/ /* The applications in this file were */ /* designed and coded by Richard Karpen */ /* University of Washington, Seattle 1998 */ /******************************************/ #include "stdopcod.h" typedef struct { OPDS h; MYFLT *r1, *r2, *r3, *r4, *asig, *degree, *distance, *reverbamount; MYFLT prev_degree, prev_distance, distr, distrsq; MYFLT ch1, ch2, ch3, ch4; AUXCH auxch; MYFLT *rrev1, *rrev2, *rrev3, *rrev4; } LOCSIG; typedef struct { OPDS h; MYFLT *r1, *r2, *r3, *r4; LOCSIG *locsig; } LOCSEND; csound-6.10.0/Opcodes/loscilx.c000066400000000000000000000574631321653344700163350ustar00rootroot00000000000000/* loscilx.c: Copyright (C) 2006 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // #include "csdl.h" #include "csoundCore.h" #include "interlocks.h" #include "soundio.h" typedef struct SNDLOAD_OPCODE_ { OPDS h; /* -------- */ MYFLT *Sfname, *iFormat, *iChannels, *iSampleRate; MYFLT *iBaseFreq, *iAmpScale; MYFLT *iStartOffset; MYFLT *iLoopMode1, *iLoopStart1, *iLoopEnd1; } SNDLOAD_OPCODE; static int sndload_opcode_init_(CSOUND *csound, SNDLOAD_OPCODE *p, int isstring) { char *fname; SNDMEMFILE *sf; SF_INFO sfinfo; int sampleFormat, loopMode; if (isstring) fname = ((STRINGDAT *)p->Sfname)->data; else { if(csound->ISSTRCOD(*p->Sfname)) fname = csound->Strdup(csound, get_arg_string(csound, *p->Sfname)); else fname = csound->strarg2name(csound, (char*) NULL, p->Sfname, "soundin.", 0); } memset(&sfinfo, 0, sizeof(SF_INFO)); sampleFormat = (int) MYFLT2LRND(*(p->iFormat)); sfinfo.format = (int) TYPE2SF(TYP_RAW); switch (sampleFormat) { case -1: sfinfo.format = 0; break; case 0: sfinfo.format |= (int) FORMAT2SF(csound->oparms->outformat); break; case 1: sfinfo.format |= (int) FORMAT2SF(AE_CHAR); break; case 2: sfinfo.format |= (int) FORMAT2SF(AE_ALAW); break; case 3: sfinfo.format |= (int) FORMAT2SF(AE_ULAW); break; case 4: sfinfo.format |= (int) FORMAT2SF(AE_SHORT); break; case 5: sfinfo.format |= (int) FORMAT2SF(AE_LONG); break; case 6: sfinfo.format |= (int) FORMAT2SF(AE_FLOAT); break; case 7: sfinfo.format |= (int) FORMAT2SF(AE_UNCH); break; case 8: sfinfo.format |= (int) FORMAT2SF(AE_24INT); break; case 9: sfinfo.format |= (int) FORMAT2SF(AE_DOUBLE); break; default: csound->Free(csound, fname); return csound->InitError(csound, Str("invalid sample format: %d"), sampleFormat); } if (sfinfo.format) { int tmp; tmp = (int) MYFLT2LRND(*(p->iChannels)); sfinfo.channels = (tmp > 0 ? tmp : 1); tmp = (int) MYFLT2LRND(*(p->iSampleRate)); sfinfo.samplerate = (tmp > 0 ? tmp : (int) MYFLT2LRND(CS_ESR)); } sf = csound->LoadSoundFile(csound, fname, &sfinfo); if (UNLIKELY(sf == NULL)) { int xx = csound->InitError(csound, Str("could not load '%s'"), fname); csound->Free(csound, fname); return xx; } csound->Free(csound, fname); if (*(p->iBaseFreq) > FL(0.0)) sf->baseFreq = (double) *(p->iBaseFreq); if (*(p->iAmpScale) != FL(0.0)) sf->scaleFac = (double) *(p->iAmpScale); if (*(p->iStartOffset) >= FL(0.0)) sf->startOffs = (double) *(p->iStartOffset); loopMode = (int) MYFLT2LRND(*(p->iLoopMode1)); if (loopMode >= 0) { if (UNLIKELY(loopMode > 3)) return csound->InitError(csound, Str("invalid loop mode: %d"), loopMode); sf->loopMode = loopMode + 1; sf->loopStart = *(p->iLoopStart1); sf->loopEnd = *(p->iLoopEnd1); } if (sf->loopMode < 2 || sf->loopStart == sf->loopEnd) { sf->loopStart = 0.0; sf->loopEnd = (double) ((int32) sf->nFrames); } else if (sf->loopStart > sf->loopEnd) { double tmp = sf->loopStart; sf->loopStart = sf->loopEnd; sf->loopEnd = tmp; } return OK; } static int sndload_opcode_init(CSOUND *csound, SNDLOAD_OPCODE *p) { return sndload_opcode_init_(csound,p,0); } static int sndload_opcode_init_S(CSOUND *csound, SNDLOAD_OPCODE *p) { return sndload_opcode_init_(csound,p,1); /* JPff: surely wrong as 0 */ } /* ------------------------------------------------------------------------ */ #define LOSCILX_MAXOUTS (16) #define LOSCILX_MAX_INTERP_SIZE (256) #define LOSCILX_PHASE_SCALE (4294967296.0) typedef struct LOSCILX_OPCODE_ { OPDS h; /* -------- */ MYFLT *ar[LOSCILX_MAXOUTS]; MYFLT *xamp, *kcps, *ifn, *iwsize, *ibas, *istrt; MYFLT *imod1, *ibeg1, *iend1; /* -------- */ int_least64_t curPos, curPosInc; int curLoopDir, curLoopMode; int_least64_t curLoopStart, curLoopEnd; MYFLT prvKcps, frqScale, ampScale, warpFact, winFact; void *dataPtr; int32 nFrames; int nChannels; int winSize; int enableWarp; /* non-zero when downsampling */ int usingFtable; int arateXamp; int loopingWholeFile; } LOSCILX_OPCODE; static inline int_least64_t loscilx_convert_phase(double phs) { double tmp = phs * LOSCILX_PHASE_SCALE; #ifdef HAVE_C99 return (int_least64_t) llrint(tmp); #else return (int_least64_t) (tmp + (tmp < 0.5 ? -0.5 : 0.5)); #endif } static inline int32 loscilx_phase_int(int_least64_t phs) { int32_t retval = (int32_t) ((uint32_t) ((uint_least64_t) phs >> 32)); #ifndef __i386__ if ((int32_t) 0x80000000U >= (int32_t) 0) /* for safety only */ retval += (-((int32_t) 0x40000000) << 2); #endif return retval; } static inline double loscilx_phase_frac(int_least64_t phs) { return ((double) ((int) (((uint32_t) ((uint_least64_t) phs) & (uint32_t) 0xFFFFFFFFU) >> 1)) * (1.0 / 2147483648.0)); } static int loscilx_opcode_init(CSOUND *csound, LOSCILX_OPCODE *p) { void *dataPtr = NULL; int nChannels, loopMode; double frqScale = 1.0; p->dataPtr = NULL; nChannels = csound->GetOutputArgCnt(p); if (UNLIKELY(nChannels < 1 || nChannels > LOSCILX_MAXOUTS)) return csound->InitError(csound, Str("loscilx: invalid number of output arguments")); p->nChannels = nChannels; if (csound->ISSTRCOD(*p->ifn)) { SNDMEMFILE *sf; p->usingFtable = 0; sf = csound->LoadSoundFile(csound, (char*) get_arg_string(csound, *p->ifn), (SF_INFO *) NULL); if (UNLIKELY(sf == NULL)) return csound->InitError(csound, Str("could not load '%s'"), (char*) p->ifn); if (sf->loopMode < 2 || sf->loopStart == sf->loopEnd) { sf->loopStart = 0.0; sf->loopEnd = (double) ((int32) sf->nFrames); } else if (sf->loopStart > sf->loopEnd) { double tmp = sf->loopStart; sf->loopStart = sf->loopEnd; sf->loopEnd = tmp; } if (UNLIKELY(sf->nChannels != nChannels)) return csound->InitError(csound, Str("number of output arguments " "inconsistent with number of " "sound file channels")); dataPtr = (void*) &(sf->data[0]); p->curPos = loscilx_convert_phase(sf->startOffs); p->curLoopMode = sf->loopMode - 1; if (p->curLoopMode < 1 || p->curLoopMode > 3) p->curLoopMode = 0; else { p->curLoopStart = loscilx_convert_phase(sf->loopStart); p->curLoopEnd = loscilx_convert_phase(sf->loopEnd); } if (*(p->ibas) > FL(0.0)) { frqScale = sf->sampleRate / ((double) CS_ESR * (double) *(p->ibas)); } else frqScale = sf->sampleRate / ((double) CS_ESR * sf->baseFreq); p->ampScale = (MYFLT) sf->scaleFac * csound->e0dbfs; p->nFrames = (int32) sf->nFrames; } else { FUNC *ftp; p->usingFtable = 1; ftp = csound->FTnp2Find(csound, p->ifn); if (ftp == NULL) return NOTOK; if (UNLIKELY((int) ftp->nchanls != nChannels)) return csound->InitError(csound, Str("number of output arguments " "inconsistent with number of " "sound file channels")); dataPtr = (void*) &(ftp->ftable[0]); p->curPos = (int_least64_t) 0; switch ((int) ftp->loopmode1) { case 1: p->curLoopMode = 1; break; case 2: p->curLoopMode = 3; break; default: p->curLoopMode = 0; } p->curLoopStart = (int_least64_t) ftp->begin1 << 32; p->curLoopEnd = (int_least64_t) ftp->end1 << 32; if (*(p->ibas) > FL(0.0)) { if (ftp->gen01args.sample_rate > FL(0.0)) frqScale = (double) ftp->gen01args.sample_rate / ((double) CS_ESR * (double) *(p->ibas)); else frqScale = 1.0 / (double) *(p->ibas); } else if (ftp->cpscvt > FL(0.0)) { frqScale = (double) ftp->cpscvt * (1.0 / (double) LOFACT); } else if (ftp->gen01args.sample_rate > FL(0.0)) frqScale = (double) ftp->gen01args.sample_rate / (double) CS_ESR; p->ampScale = FL(1.0); p->nFrames = ftp->flenfrms + 1L; } if (*(p->istrt) >= FL(0.0)) p->curPos = loscilx_convert_phase((double) *(p->istrt)); p->curPosInc = (int_least64_t) 0; p->curLoopDir = 1; loopMode = (int) MYFLT2LRND(*(p->imod1)); if (loopMode >= 0) { if (UNLIKELY(loopMode > 3)) return csound->InitError(csound, Str("invalid loop mode: %d"), loopMode); p->curLoopMode = loopMode; p->curLoopStart = loscilx_convert_phase((double) *(p->ibeg1)); p->curLoopEnd = loscilx_convert_phase((double) *(p->iend1)); } if (p->curLoopMode <= 0 || p->curLoopStart == p->curLoopEnd) { p->curLoopStart = (int_least64_t) 0; p->curLoopEnd = (int_least64_t) p->nFrames << 32; } else if (p->curLoopStart > p->curLoopEnd) { int_least64_t tmp = p->curLoopStart; p->curLoopStart = p->curLoopEnd; p->curLoopEnd = tmp; } p->prvKcps = FL(0.0); p->frqScale = (MYFLT) (frqScale * LOSCILX_PHASE_SCALE); p->warpFact = FL(1.0); p->winSize = (int) MYFLT2LRND(*(p->iwsize)); if (p->winSize < 1) p->winSize = 4; /* default to cubic interpolation */ else if (p->winSize > 2) { if (p->winSize > LOSCILX_MAX_INTERP_SIZE) p->winSize = LOSCILX_MAX_INTERP_SIZE; else p->winSize = (p->winSize + 2) & (~((int) 3)); if (p->winSize > 4) { /* constant for window calculation */ p->winFact = (FL(1.0) - POWER(p->winSize * FL(0.85172), -FL(0.89624))) / ((p->winSize * p->winSize) >> 2); } } p->enableWarp = 0; if (IS_ASIG_ARG(p->xamp)) p->arateXamp = ~((int) 0); /* used as a bit mask */ else p->arateXamp = 0; p->loopingWholeFile = 0; if (p->curLoopMode == 1) { if (loscilx_phase_int(p->curLoopStart + (int_least64_t) 0x80000000U) == 0L) { if (loscilx_phase_int(p->curLoopEnd + (int_least64_t) 0x80000000U) == p->nFrames) p->loopingWholeFile = 1; } } p->dataPtr = dataPtr; return OK; } /* ------------- set up fast sine generator ------------- */ /* Input args: */ /* a: amplitude */ /* f: frequency (-PI - PI) */ /* p: initial phase (0 - PI/2) */ /* c: 2.0 * cos(f) - 2.0 */ /* Output args: */ /* *x: first output sample */ /* *v: coefficients for calculating next sample as */ /* shown below: */ /* v = v + c * x */ /* x = x + v */ /* These values are calculated as follows: */ /* x = y[0] */ /* v = y[1] - (c + 1.0) * y[0] */ /* where y[0], and y[1] are the first, and */ /* second sample of the sine wave to be */ /* generated, respectively. */ /* -------- written by Istvan Varga, Jan 28 2002 -------- */ static inline void init_sine_gen(double a, double f, double p, double c, double *x, double *v) { double y0, y1; /* these should be doubles */ double xx, vv; y0 = sin(p); y1 = sin(p + f); xx = y0; vv = y1 - (c * y0) - y0; /* amp. scale */ *x = xx*a; *v = vv*a; } static int loscilx_opcode_perf(CSOUND *csound, LOSCILX_OPCODE *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; int j; double frac_d, pidwarp_d = 0.0, c = 0.0; MYFLT frac, ampScale, winFact = p->winFact; int32 ndx; int winSmps; float winBuf[LOSCILX_MAX_INTERP_SIZE]; if (UNLIKELY(p->dataPtr == NULL)) goto err1; if (*(p->kcps) != p->prvKcps) { double f; p->prvKcps = *(p->kcps); f = (double) p->prvKcps * (double) p->frqScale; #ifdef HAVE_C99 p->curPosInc = (int_least64_t) llrint(f); #else p->curPosInc = (int_least64_t) (f + (f < 0.0 ? -0.5 : 0.5)); #endif if (p->winSize > 4) { int_least64_t nn = ((int_least64_t) 0x00010001 << 16); /* calculate window "warp" parameter for sinc interpolation */ if (p->curPosInc > nn || p->curPosInc < (-nn)) { if (p->curPosInc >= (int_least64_t) 0) p->warpFact = (MYFLT) nn / (MYFLT) p->curPosInc; else p->warpFact = (MYFLT) (-nn) / (MYFLT) p->curPosInc; if (p->warpFact < (FL(2.0) / (MYFLT) p->winSize)) p->warpFact = (FL(2.0) / (MYFLT) p->winSize); p->enableWarp = 1; } else p->enableWarp = 0; } } if (p->enableWarp) { double tmp1, tmp2; pidwarp_d = PI * (double) p->warpFact; c = 2.0 * cos(pidwarp_d) - 2.0; /* correct window for kwarp */ tmp1 = tmp2 = (double) (p->winSize >> 1); tmp1 *= tmp1; tmp1 = 1.0 / tmp1; tmp2 *= (double) p->warpFact; tmp2 -= (double) ((int) tmp2) + 0.5; tmp2 *= (4.0 * tmp2); winFact = (MYFLT) (((double) p->winFact - tmp1) * tmp2 + tmp1); } ampScale = *(p->xamp) * p->ampScale; if (UNLIKELY(offset)) memset(p->ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->ar[nsmps], '\0', early*sizeof(MYFLT)); } for (i = offset; icurPos); frac = (MYFLT) frac_d; ndx = loscilx_phase_int(p->curPos); if (i & p->arateXamp) ampScale = p->xamp[i] * p->ampScale; /* calculate interpolation window */ winSmps = p->winSize; switch (p->winSize) { case 1: /* no interpolation */ winBuf[0] = 1.0f; break; case 2: /* linear interpolation */ winBuf[0] = (float) (FL(1.0) - frac); winBuf[1] = (float) frac; break; case 4: /* cubic interpolation */ { MYFLT a0, a1, a2, a3; ndx--; a3 = frac * frac; a3 -= FL(1.0); a3 *= (FL(1.0) / FL(6.0)); a2 = frac; a2 += FL(1.0); a0 = (a2 *= FL(0.5)); a0 -= FL(1.0); a1 = FL(3.0) * a3; a2 -= a1; a0 -= a3; a1 -= frac; winBuf[0] = (float) (a0 * frac); winBuf[1] = (float) (a1 * frac + FL(1.0)); winBuf[2] = (float) (a2 * frac); winBuf[3] = (float) (a3 * frac); } break; default: /* sinc interpolation */ { double d, x, v; MYFLT a0, a1; int wsized2 = winSmps >> 1; ndx += (int32) (1 - wsized2); d = (double) (1 - wsized2) - frac_d; j = 0; if (p->enableWarp) { /* ...with window warp enabled */ init_sine_gen((1.0 / PI), pidwarp_d, (pidwarp_d * d), c, &x, &v); /* samples -(window size / 2 - 1) to -1 */ do { a1 = (MYFLT) d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = (MYFLT) x * a1 * a1 / (MYFLT) d; winBuf[j++] = (float) a1; d += 1.0; v += c * x; x += v; } while (j < (wsized2 - 1)); /* sample 0 */ /* avoid division by zero */ if (frac_d < 0.00003) { a1 = p->warpFact; } else { a1 = (MYFLT) d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = (MYFLT) x * a1 * a1 / (MYFLT) d; } winBuf[j++] = (float) a1; d += 1.0; v += c * x; x += v; /* sample 1 */ /* avoid division by zero */ if (frac_d > 0.99997) { a1 = p->warpFact; } else { a1 = (MYFLT) d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = (MYFLT) x * a1 * a1 / (MYFLT) d; } winBuf[j++] = (float) a1; d += 1.0; v += c * x; x += v; /* samples 2 to (window size / 2) */ do { a1 = (MYFLT) d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = (MYFLT) x * a1 * a1 / (MYFLT) d; winBuf[j++] = (float) a1; d += 1.0; v += c * x; x += v; } while (j < p->winSize); } else { /* ...with window warp disabled */ /* avoid division by zero */ if (frac_d < 0.00001 || frac_d > 0.99999) { ndx += (int32) (wsized2 - (frac_d < 0.5 ? 1 : 0)); winSmps = 1; winBuf[0] = 1.0f; } else { a0 = (MYFLT) (sin(PI * frac_d) / PI); do { a1 = (MYFLT) d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = a0 * a1 * a1 / (MYFLT) d; winBuf[j++] = (float) a1; d += 1.0; a1 = (MYFLT) d; a1 = FL(1.0) - a1 * a1 * winFact; a1 = -(a0 * a1 * a1 / (MYFLT) d); winBuf[j++] = (float) a1; d += 1.0; } while (j < p->winSize); } } } } /* generate sound output */ ndx--; j = 0; if (p->nChannels == 1) { /* mono */ MYFLT ar = FL(0.0); do { ndx++; if ((uint32) ndx >= (uint32) p->nFrames) { if (!p->loopingWholeFile) continue; if (ndx < 0L) { do { ndx += p->nFrames; } while (ndx < 0L); } else { do { ndx -= p->nFrames; } while (ndx >= p->nFrames); } } #ifdef USE_DOUBLE if (p->usingFtable) { ar += (((MYFLT*) p->dataPtr)[ndx] * (MYFLT) winBuf[j]); } else #endif { ar += ((MYFLT) ((float*) p->dataPtr)[ndx] * (MYFLT) winBuf[j]); } } while (++j < winSmps); /* scale output */ p->ar[0][i] = ar * ampScale; } else if (p->nChannels == 2) { /* stereo */ MYFLT ar1 = FL(0.0), ar2 = FL(0.0); do { ndx++; if ((uint32) ndx >= (uint32) p->nFrames) { if (!p->loopingWholeFile) continue; if (ndx < 0L) { do { ndx += p->nFrames; } while (ndx < 0L); } else { do { ndx -= p->nFrames; } while (ndx >= p->nFrames); } } #ifdef USE_DOUBLE if (p->usingFtable) { ar1 += (((MYFLT*) p->dataPtr)[ndx + ndx] * (MYFLT) winBuf[j]); ar2 += (((MYFLT*) p->dataPtr)[ndx + ndx + 1L] * (MYFLT) winBuf[j]); } else #endif { ar1 += ((MYFLT) ((float*) p->dataPtr)[ndx + ndx] * (MYFLT) winBuf[j]); ar2 += ((MYFLT) ((float*) p->dataPtr)[ndx + ndx + 1L] * (MYFLT) winBuf[j]); } } while (++j < winSmps); /* scale output */ p->ar[0][i] = ar1 * ampScale; p->ar[1][i] = ar2 * ampScale; } else { /* generic multichannel code */ int k = 0; do { p->ar[k][i] = FL(0.0); } while (++k < p->nChannels); do { ndx++; if ((uint32) ndx >= (uint32) p->nFrames) { if (!p->loopingWholeFile) continue; if (ndx < 0L) { do { ndx += p->nFrames; } while (ndx < 0L); } else { do { ndx -= p->nFrames; } while (ndx >= p->nFrames); } } #ifdef USE_DOUBLE if (p->usingFtable) { MYFLT *fp = &(((MYFLT*) p->dataPtr)[ndx * (int32) p->nChannels]); k = 0; do { p->ar[k][i] += (fp[k] * (MYFLT) winBuf[j]); } while (++k < p->nChannels); } else #endif { float *fp = &(((float*) p->dataPtr)[ndx * (int32) p->nChannels]); k = 0; do { p->ar[k][i] += ((MYFLT) fp[k] * (MYFLT) winBuf[j]); } while (++k < p->nChannels); } } while (++j < winSmps); /* scale output */ k = 0; do { p->ar[k][i] *= ampScale; } while (++k < p->nChannels); } /* update playback position */ if (p->curLoopMode) { int_least64_t prvPos = p->curPos; if (p->curLoopDir > 0) p->curPos += p->curPosInc; else p->curPos -= p->curPosInc; if (p->curPos < p->curLoopStart) { if (prvPos >= p->curLoopStart) { switch (p->curLoopMode) { case 1: case 2: p->curPos = p->curPos + (p->curLoopEnd - p->curLoopStart); break; case 3: p->curPos = p->curLoopStart + (p->curLoopStart - p->curPos); p->curLoopDir = -(p->curLoopDir); break; } } } else if (p->curPos >= p->curLoopEnd) { if (prvPos < p->curLoopEnd) { switch (p->curLoopMode) { case 1: p->curPos = p->curPos + (p->curLoopStart - p->curLoopEnd); break; case 2: case 3: p->curPos = p->curLoopEnd + (p->curLoopEnd - p->curPos); p->curLoopDir = -(p->curLoopDir); break; } } } } else p->curPos += p->curPosInc; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("loscilx: not initialised")); } /* ------------------------------------------------------------------------ */ static OENTRY loscilx_localops[] = { { "sndload", sizeof(SNDLOAD_OPCODE), _QQ, 1, "", "iooooojjoo", (SUBR) sndload_opcode_init, (SUBR) NULL, (SUBR) NULL }, { "sndload.S", sizeof(SNDLOAD_OPCODE), _QQ, 1, "", "Sooooojjoo", (SUBR) sndload_opcode_init_S, (SUBR) NULL, (SUBR) NULL }, { "loscilx", sizeof(LOSCILX_OPCODE), TR, 5, "mmmmmmmmmmmmmmmm", "xkioojjoo", (SUBR) loscilx_opcode_init, (SUBR) NULL, (SUBR) loscilx_opcode_perf } }; LINKAGE_BUILTIN(loscilx_localops) csound-6.10.0/Opcodes/lowpassr.c000066400000000000000000000305461321653344700165230ustar00rootroot00000000000000/* lowpassr.c: Copyright (C) 1998 Gabriel Maldonado This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Resonant Lowpass filters by G.Maldonado */ #include "stdopcod.h" #include "lowpassr.h" #include static int lowpr_set(CSOUND *csound, LOWPR *p) { if (*p->istor==FL(0.0)) p->ynm1 = p->ynm2 = 0.0; p->okf = 0.0; p->okr = 0.0; p->k = 0.0; return OK; } static int lowpr(CSOUND *csound, LOWPR *p) { double b, k = p->k; MYFLT *ar, *asig; double yn, ynm1, ynm2 ; MYFLT kfco = *p->kfco; MYFLT kres = *p->kres; double coef1 = p->coef1, coef2 = p->coef2; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (p->okf != kfco || p->okr != kres) { /* Only if changed */ if (UNLIKELY(kfco<=FL(0.0))) return csound->PerfError(csound, p->h.insdshead, Str("Cutoff parameter must be positive")); b = 10.0 / (kres * sqrt((double)kfco)) - 1.0; p->k = k = 1000.0 / (double)kfco; p->coef1 = coef1 = (b+2.0 * k); p->coef2 = coef2 = 1.0/(1.0 + b + k); p->okf = kfco; p->okr = kres; /* remember to save recalculation */ } ar = p->ar; asig = p->asig; ynm1 = p->ynm1; ynm2 = p->ynm2; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nynm1 = ynm1; p->ynm2 = ynm2; /* And save */ return OK; } static int lowpraa(CSOUND *csound, LOWPR *p) { double b, k = p->k; MYFLT *ar, *asig; double yn, ynm1, ynm2 ; MYFLT *fco = p->kfco; MYFLT *res = p->kres; MYFLT okf = p->okf, okr = p->okr; double coef1 = p->coef1, coef2 = p->coef2; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (okf!= fco[0] || okr != res[0]) { /* Only if changed */ if (UNLIKELY(fco[0]<=FL(0.0))) return csound->PerfError(csound, p->h.insdshead, Str("Cutoff parameter must be positive")); b = 10.0 / (res[0] * sqrt((double)fco[0])) - 1.0; p->k = k = 1000.0 / (double)fco[0]; p->coef1 = coef1 = (b+2.0 * k); p->coef2 = coef2 = 1.0/(1.0 + b + k); okf = fco[0]; okr = res[0]; /* remember to save recalculation */ } ar = p->ar; asig = p->asig; ynm1 = p->ynm1; ynm2 = p->ynm2; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nPerfError(csound, p->h.insdshead, Str("Cutoff parameter must be positive")); b = 10.0 / (res[n] * sqrt((double)fco[n])) - 1.0; p->k = k = 1000.0 / (double)fco[0]; p->coef1 = coef1 = (b+2.0 * k); p->coef2 = coef2 = 1.0/(1.0 + b + k); okf = fco[n]; okr = res[n]; /* remember to save recalculation */ } ar[n] = (MYFLT)(yn = (coef1 * ynm1 - k * ynm2 + (double)asig[n]) * coef2); ynm2 = ynm1; ynm1 = yn; } p->ynm1 = ynm1; p->ynm2 = ynm2; /* And save */ p->okf = okf; p->okr = okr; return OK; } static int lowprak(CSOUND *csound, LOWPR *p) { double b, k = p->k; MYFLT *ar, *asig; double yn, ynm1, ynm2 ; MYFLT *fco = p->kfco; MYFLT kres = *p->kres; MYFLT okf = p->okf, okr = p->okr; double coef1 = p->coef1, coef2 = p->coef2; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (okf != fco[0] || okr != kres) { /* Only if changed */ if (UNLIKELY(fco[0]<=FL(0.0))) return csound->PerfError(csound, p->h.insdshead, Str("Cutoff parameter must be positive")); b = 10.0 / (kres * sqrt((double)fco[0])) - 1.0; p->k = k = 1000.0 / (double)fco[0]; p->coef1 = coef1 = (b+2.0 * k); p->coef2 = coef2 = 1.0/(1.0 + b + k); okf = fco[0]; okr = kres; /* remember to save recalculation */ } ar = p->ar; asig = p->asig; ynm1 = p->ynm1; ynm2 = p->ynm2; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nPerfError(csound, p->h.insdshead, Str("Cutoff parameter must be positive")); b = 10.0 / (kres * sqrt((double)fco[n])) - 1.0; p->k = k = 1000.0 / (double)fco[n]; p->coef1 = coef1 = (b+2.0 * k); p->coef2 = coef2 = 1.0/(1.0 + b + k); okf = fco[n]; /* remember to save recalculation */ } ar[n] = (MYFLT)(yn = (coef1 * ynm1 - k * ynm2 + (double)asig[n]) * coef2); ynm2 = ynm1; ynm1 = yn; } p->ynm1 = ynm1; p->ynm2 = ynm2; /* And save */ p->okf = okf; p->okr = okr; return OK; } static int lowprka(CSOUND *csound, LOWPR *p) { double b, k = p->k; MYFLT *ar, *asig; double yn, ynm1, ynm2 ; MYFLT fco = *p->kfco; MYFLT *res = p->kres; MYFLT okr = p->okr, okf = p->okf; double coef1 = p->coef1, coef2 = p->coef2; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (okf!= fco || okr != res[0]) { /* Only if changed */ if (UNLIKELY(fco<=FL(0.0))) return csound->PerfError(csound, p->h.insdshead, Str("Cutoff parameter must be positive")); b = 10.0 / (res[0] * sqrt((double)fco)) - 1.0; p->k = k = 1000.0 / (double)fco; p->coef1 = coef1 = (b+2.0 * k); p->coef2 = coef2 = 1.0/(1.0 + b + k); okf = fco; okr = res[0]; /* remember to save recalculation */ } ar = p->ar; asig = p->asig; ynm1 = p->ynm1; ynm2 = p->ynm2; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nk = k = 1000.0 / (double)fco; p->coef1 = coef1 = (b+2.0 * k); p->coef2 = coef2 = 1.0/(1.0 + b + k); okr = res[n]; /* remember to save recalculation */ } ar[n] = (MYFLT)(yn = (coef1 * ynm1 - k * ynm2 + (double)asig[n]) * coef2); ynm2 = ynm1; ynm1 = yn; } p->ynm1 = ynm1; p->ynm2 = ynm2; /* And save */ p->okf = okf; p->okr = okr; return OK; } static int lowpr_setx(CSOUND *csound, LOWPRX *p) { int j; if ((p->loop = (int) MYFLT2LONG(*p->ord)) < 1) p->loop = 4; /*default value*/ else if (UNLIKELY(p->loop > 10)) { return csound->InitError(csound, Str("illegal order num. (min 1, max 10)")); } if (*p->istor == FL(0.0)) for (j=0; j< p->loop; j++) p->ynm1[j] = p->ynm2[j] = FL(0.0); p->k = p->okf = p->okr = -FL(1.0); return OK; } static int lowprx(CSOUND *csound, LOWPRX *p) { MYFLT b, k = p->k; MYFLT *ar, *asig, yn,*ynm1, *ynm2 ; MYFLT coef1 = p->coef1, coef2 = p->coef2; MYFLT *kfco = p->kfco, *kres = p->kres; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int j; int asgf = IS_ASIG_ARG(p->kfco), asgr = IS_ASIG_ARG(p->kres); ynm1 = p->ynm1; ynm2 = p->ynm2; asig = p->asig; if (UNLIKELY(offset)) memset(p->ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->ar[nsmps], '\0', early*sizeof(MYFLT)); } for (j=0; j< p->loop; j++) { ar = p->ar; for (n=offset;nokf != fco || p->okr != res) { /* Only if changed */ b = FL(10.0) / (res * SQRT(fco)) - FL(1.0); k = FL(1000.0) / fco; coef1 = (b+FL(2.0) * k); coef2 = FL(1.0)/(FL(1.0) + b + k); p->okf = fco; p->okr = res; /* remember to save recalculation */ } ar[n] = yn = (coef1 * ynm1[j] - k * ynm2[j] + asig[n]) * coef2; ynm2[j] = ynm1[j]; ynm1[j] = yn; } asig= p->ar; } p->k = k; p->coef1 = coef1; p->coef2 = coef2; return OK; } static int lowpr_w_sep_set(CSOUND *csound, LOWPR_SEP *p) { int j; if ((p->loop = (int) MYFLT2LONG(*p->ord)) < 1) p->loop = 4; /*default value*/ else if (UNLIKELY(p->loop > 10)) { return csound->InitError(csound, Str("illegal order num. (min 1, max 10)")); } for (j=0; j< p->loop; j++) p->ynm1[j] = p->ynm2[j] = FL(0.0); return OK; } static int lowpr_w_sep(CSOUND *csound, LOWPR_SEP *p) { MYFLT b, k; MYFLT *ar, *asig, yn,*ynm1, *ynm2 ; MYFLT coef1, coef2; MYFLT kfcobase = *p->kfco; MYFLT sep = (*p->sep / p->loop); uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int j; MYFLT kres = *p->kres; MYFLT kfco; ynm1 = p->ynm1; ynm2 = p->ynm2; asig = p->asig; if (UNLIKELY(offset)) memset(p->ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->ar[nsmps], '\0', early*sizeof(MYFLT)); } ar = p->ar; for (j=0; j< p->loop; j++) { MYFLT lynm1 = ynm1[j]; MYFLT lynm2 = ynm2[j]; /* linfco=log((double) kfco)*ONEtoLOG2 ; linfco = linfco + (sep / p->loop)*j; kfco = (MYFLT) pow(2.0,linfco); */ kfco = kfcobase * (FL(1.0) + (sep * j)); b = FL(10.0) / ( kres * (MYFLT)sqrt((double)kfco)) - FL(1.0); k = FL(1000.0) / kfco; coef1 = (b+FL(2.0) *k); coef2 = FL(1.0)/(FL(1.0) + b + k); for (n=offset;nar; } return OK; } #define S(x) sizeof(x) static OENTRY localops[] = { { "lowres.kk", S(LOWPR), 0, 5, "a", "akko", (SUBR)lowpr_set, NULL, (SUBR)lowpr }, { "lowres.aa", S(LOWPR), 0, 5, "a", "aaao", (SUBR)lowpr_set, NULL, (SUBR)lowpraa }, { "lowres.ak", S(LOWPR), 0, 5, "a", "aako", (SUBR)lowpr_set, NULL, (SUBR)lowprak }, { "lowres.ka", S(LOWPR), 0, 5, "a", "akao", (SUBR)lowpr_set, NULL, (SUBR)lowprka }, { "lowresx", S(LOWPRX), 0, 5, "a", "axxoo", (SUBR)lowpr_setx, NULL, (SUBR)lowprx }, { "vlowres", S(LOWPR_SEP),0, 5, "a", "akkik", (SUBR)lowpr_w_sep_set, NULL, (SUBR)lowpr_w_sep } }; int lowpassr_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/lowpassr.h000066400000000000000000000025451321653344700165260ustar00rootroot00000000000000/* lowpassr.h: Copyright (C) 1998 Gabriel Maldonado This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ typedef struct { OPDS h; MYFLT *ar, *asig, *kfco, *kres, *istor; double ynm1, ynm2; double coef1, coef2, okf, okr, k; } LOWPR; typedef struct { OPDS h; MYFLT *ar, *asig, *kfco, *kres, *ord, *istor; MYFLT ynm1[10], ynm2[10] ; int loop; MYFLT coef1, coef2, okf, okr, k; } LOWPRX; typedef struct { OPDS h; MYFLT *ar, *asig, *kfco, *kres, *ord, *sep; MYFLT ynm1[10], ynm2[10], cut[10]; int loop; } LOWPR_SEP; csound-6.10.0/Opcodes/mandolin.c000066400000000000000000000203441321653344700164450ustar00rootroot00000000000000/* mandolin.c: code for physical model of mandolin Copyright (C) 1997 John ffitch, Perry Cook This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /********************************************/ /* Commuted Mandolin Subclass of enhanced */ /* dual plucked-string model */ /* by Perry Cook, 1995-96 */ /* Controls: CONTROL1 = bodySize */ /* CONTROL2 = pluckPosition */ /* CONTROL3 = loopGain */ /* MOD_WHEEL= deTuning */ /* */ /* Note: Commuted Synthesis, as with many */ /* other WaveGuide techniques, is covered */ /* by patents, granted, pending, and/or */ /* applied-for. Many are assigned to the */ /* Board of Trustees, Stanford University. */ /* For information, contact the Office of */ /* Technology Licensing, Stanford U. */ /********************************************/ // #include "csdl.h" #include "csoundCore.h" #include "mandolin.h" static inline int infoTick(MANDOL *p) { int32 temp; MYFLT temp_time, alpha; int allDone = 0; p->s_time += *p->s_rate; /* Update current time */ if (p->s_time >= (MYFLT)p->soundfile->flen) { /* Check for end of sound */ p->s_time = (MYFLT)(p->soundfile->flen-1L); /* stick at end */ allDone = 1; /* Information for one-shot use */ } else if (p->s_time < FL(0.0)) /* Check for end of sound */ p->s_time = FL(0.0); /* stick at beg */ temp_time = p->s_time; temp = (int32) temp_time; /* Integer part of time address */ alpha = temp_time - (MYFLT) temp; /* fractional part of time address */ p->s_lastOutput = /* Do linear interpolation */ FL(0.05)*((MYFLT*)(p->soundfile->ftable))[temp]; p->s_lastOutput = p->s_lastOutput + /* same as alpha*data[temp+1] */ (alpha * FL(0.05)*(((MYFLT*)(p->soundfile->ftable))[temp+1] - p->s_lastOutput)); /* + (1-alpha)data[temp] */ /* p->s_lastOutput *= FL(0.51);*/ /* Scaling hack; see below, and changed */ return allDone; } /* Suggested values pluckAmp = 0.3; pluckPos = 0.4; detuning = 0.995; */ int mandolinset(CSOUND *csound, MANDOL *p) { FUNC *ftp; if (LIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) != NULL)) p->soundfile = ftp; else { /* Expect pluck wave */ return csound->InitError(csound, Str("No table for Mandolin")); } if (*p->lowestFreq>=FL(0.0)) { /* Skip initialisation */ if (*p->lowestFreq!=FL(0.0)) { p->length = (int32) (CS_ESR / (*p->lowestFreq * FL(0.9)) + FL(1.0)); } else if (LIKELY(*p->frequency!=FL(0.0))) { p->length = (int32) (CS_ESR / *p->frequency + FL(1.0)); } else { csound->Warning(csound, Str("No base frequency for mandolin")); p->length = (int32) (CS_ESR / FL(50.0) + FL(1.0)); } p->lastFreq = FL(50.0); /* p->baseLoopGain = 0.995; */ /* p->loopGain = 0.999; */ make_DLineA(csound,&p->delayLine1, p->length); make_DLineA(csound,&p->delayLine2, p->length); make_DLineL(csound,&p->combDelay, p->length); make_OneZero(&p->filter1); make_OneZero(&p->filter2); // p->lastLength = p->length * FL(0.5); /* soundfile->normalize(0.05); Empirical hack here transferred to use */ p->lastLength = ( CS_ESR / p->lastFreq); /* length - delays */ /* DLineA_setDelay(&p->delayLine1, (p->lastLength / *p->detuning) - 0.5f); */ /* DLineA_setDelay(&p->delayLine2, (p->lastLength * *p->detuning) - 0.5f); */ /* this function gets interesting here, */ p->s_time = FL(0.0); /* because pluck may be longer than */ /* string length, so we just reset the */ /* soundfile and add in the pluck in */ /* the tick method. */ /* Set Pick Position */ DLineL_setDelay(&p->combDelay, FL(0.5) * *p->pluckPos * p->lastLength); /* which puts zeroes at pos*length */ p->dampTime = (int32) p->lastLength; /* See tick method below */ p->waveDone = 0; { int relestim = (int)(CS_EKR * FL(0.1)); /* 1/10th second decay extention */ if (relestim > p->h.insdshead->xtratim) p->h.insdshead->xtratim = relestim; } p->kloop = (int)(p->h.insdshead->offtim * CS_EKR); /* ??? */ } return OK; } int mandolin(CSOUND *csound, MANDOL *p) { MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT amp = (*p->amp)*AMP_RSCALE; /* Normalise */ MYFLT lastOutput; MYFLT loopGain; loopGain = *p->baseLoopGain + (p->lastFreq * FL(0.000005)); if (loopGain>FL(1.0)) loopGain = FL(0.99999); if (p->kloop>0 && p->h.insdshead->relesing) p->kloop=1; if (p->lastFreq != *p->frequency) { p->lastFreq = *p->frequency; p->lastLength = ( CS_ESR / p->lastFreq); /* length - delays */ DLineA_setDelay(csound, &p->delayLine1, (p->lastLength / *p->detuning) - FL(0.5)); DLineA_setDelay(csound, &p->delayLine2, (p->lastLength * *p->detuning) - FL(0.5)); } if ((--p->kloop) == 0) { loopGain = (FL(1.0) - amp) * FL(0.5); } if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;nwaveDone) { p->waveDone = infoTick(p); /* as long as it goes . . . */ temp = p->s_lastOutput * amp; /* scaled pluck excitation */ temp = temp - DLineL_tick(&p->combDelay, temp);/* with comb filtering */ } if (p->dampTime>=0) { /* Damping hack to help avoid */ p->dampTime -= 1; /* overflow on replucking */ lastOutput = DLineA_tick(&p->delayLine1, /* Calculate 1st delay */ OneZero_tick(&p->filter1, /* filterered reflection */ temp + /* plus pluck excitation */ (p->delayLine1.lastOutput * FL(0.7)))); lastOutput += DLineA_tick(&p->delayLine2, /* and 2nd delay just like the 1st */ OneZero_tick(&p->filter2, temp + (p->delayLine2.lastOutput * FL(0.7)))); /* that's the whole thing!! */ } else { /* No damping hack after 1 period */ lastOutput = DLineA_tick(&p->delayLine1, /* Calculate 1st delay */ OneZero_tick(&p->filter1, /* filtered reflection */ temp + /* plus pluck excitation */ (p->delayLine1.lastOutput * loopGain))); lastOutput += DLineA_tick(&p->delayLine2, /* and 2nd delay */ OneZero_tick(&p->filter2, /* just like the 1st */ temp + (p->delayLine2.lastOutput * loopGain))); } lastOutput *= FL(3.7); ar[n] = lastOutput*AMP_SCALE; } return OK; } csound-6.10.0/Opcodes/mandolin.h000066400000000000000000000046201321653344700164510ustar00rootroot00000000000000/* mandolin.h: mandolin model Copyright (C) 1997 John ffitch, Perry Cook This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /**********************************************************************/ /* Commuted Mandolin Subclass of enhanced dual plucked-string model */ /* by Perry Cook, 1995-96 */ /* Controls: bodySize pluckPosition loopGain deTuning */ /* */ /* Note: Commuted Synthesis, as with many other WaveGuide techniques,*/ /* is covered by patents, granted, pending, and/or applied-for. All */ /* are assigned to the Board of Trustees, Stanford University. */ /* For information, contact the Office of Technology Licensing, */ /* Stanford U. */ /**********************************************************************/ #if !defined(__Mandolin_h) #define __Mandolin_h #include "clarinet.h" #include "brass.h" typedef struct Mandolin { OPDS h; MYFLT *ar; /* Output */ MYFLT *amp; MYFLT *frequency; MYFLT *pluckPos; MYFLT *detuning; MYFLT *baseLoopGain; MYFLT *s_rate; MYFLT *ifn; MYFLT *lowestFreq; FUNC *soundfile; MYFLT s_time; MYFLT s_lastOutput; DLineA delayLine1; DLineA delayLine2; DLineL combDelay; OneZero filter1; OneZero filter2; int32 length; MYFLT lastFreq; MYFLT lastLength; int32 dampTime; int waveDone; int kloop; } MANDOL; #endif csound-6.10.0/Opcodes/marimba.h000066400000000000000000000033721321653344700162630ustar00rootroot00000000000000/* mandolin.c: Copyright (C) 1996, 1997 Perry Cook, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /*******************************************/ /* Marimba SubClass of Modal4 Instrument, */ /* by Perry R. Cook, 1995-96 */ /* */ /* Controls: stickHardness */ /* strikePosition*/ /* vibFreq */ /* vibAmt */ /*******************************************/ #if !defined(__Marimba_h) #define __Marimba_h #include "modal4.h" typedef struct Marimba { OPDS h; MYFLT *ar; /* Output */ MYFLT *amplitude, *frequency; MYFLT *hardness, *spos, *ifn; MYFLT *vibFreq, *vibAmt, *ivfn, *dettack; MYFLT *doubles, *triples; /* Modal4 */ Modal4 m4; int multiStrike; MYFLT strikePosition; MYFLT stickHardness; int first; int kloop; } MARIMBA; #endif csound-6.10.0/Opcodes/metro.c000066400000000000000000000162321321653344700157730ustar00rootroot00000000000000/* metro.c: Copyright (C) 2000 Gabriel Maldonado This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "stdopcod.h" #include typedef struct { OPDS h; MYFLT *sr, *xcps, *iphs; double curphs; int flag; } METRO; typedef struct { OPDS h; MYFLT *trig, *ndx, *maxtics, *ifn, *outargs[VARGMAX]; int numouts, currtic, old_ndx; MYFLT *table; } SPLIT_TRIG; typedef struct { OPDS h; MYFLT *ktrig, *kphs, *ifn, *args[VARGMAX]; MYFLT endSeq, *table, oldPhs; int numParm, endIndex, prevIndex, nextIndex ; MYFLT prevActime, nextActime; int initFlag; } TIMEDSEQ; static int metro_set(CSOUND *csound, METRO *p) { double phs = *p->iphs; int32 longphs; if (phs >= 0.0) { if (UNLIKELY((longphs = (int32)phs))) csound->Warning(csound, Str("metro:init phase truncation")); p->curphs = (MYFLT)phs - (MYFLT)longphs; } p->flag=1; return OK; } static int metro(CSOUND *csound, METRO *p) { double phs= p->curphs; if (phs == 0.0 && p->flag) { *p->sr = FL(1.0); p->flag = 0; } else if ((phs += *p->xcps * CS_ONEDKR) >= 1.0) { *p->sr = FL(1.0); phs -= 1.0; p->flag = 0; } else *p->sr = FL(0.0); p->curphs = phs; return OK; } static int split_trig_set(CSOUND *csound, SPLIT_TRIG *p) { /* syntax of each table element: numtics_elem1, tic1_out1, tic1_out2, ... , tic1_outN, tic2_out1, tic2_out2, ... , tic2_outN, tic3_out1, tic3_out2, ... , tic3_outN, ..... ticN_out1, ticN_out2, ... , ticN_outN, numtics_elem2, tic1_out1, tic1_out2, ... , tic1_outN, tic2_out1, tic2_out2, ... , tic2_outN, tic3_out1, tic3_out2, ... , tic3_outN, ..... ticN_out1, ticN_out2, ... , ticN_outN, */ FUNC *ftp; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) == NULL)) { return csound->InitError(csound, Str("splitrig: incorrect table number")); } p->table = ftp->ftable; p->numouts = p->INOCOUNT-4; p->currtic = 0; return OK; } static int split_trig(CSOUND *csound, SPLIT_TRIG *p) { int j; int numouts = p->numouts; MYFLT **outargs = p->outargs; if (*p->trig) { int ndx = (int) *p->ndx * (numouts * (int) *p->maxtics + 1); int numtics = (int) p->table[ndx]; MYFLT *table = &(p->table[ndx+1]); int kndx = (int) *p->ndx; int currtic; if (kndx != p->old_ndx) { p->currtic = 0; p->old_ndx = kndx; } currtic = p->currtic; for (j = 0; j < numouts; j++) *outargs[j] = table[j + currtic * numouts ]; p->currtic = (currtic +1) % numtics; } else { // Maybe a memset? for(j =0; j< numouts; j++) *outargs[j] = FL(0.0); } return OK; } static int timeseq_set(CSOUND *csound, TIMEDSEQ *p) { FUNC *ftp; MYFLT *table; unsigned int j; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) == NULL)) return NOTOK; table = p->table = ftp->ftable; p->numParm = p->INOCOUNT-2; /* ? */ for (j = 0; j < ftp->flen; j+= p->numParm) { if (table[j] < 0) { p->endSeq = table[j+1]; p->endIndex = j/p->numParm; break; } } p->initFlag = 1; return OK; } static int timeseq(CSOUND *csound, TIMEDSEQ *p) { MYFLT *table = p->table, minDist = CS_ONEDKR; MYFLT phs = *p->kphs, endseq = p->endSeq; int j,k, numParm = p->numParm, endIndex = p->endIndex; while (phs > endseq) phs -=endseq; while (phs < 0 ) phs +=endseq; if (p->initFlag) { prev: for (j=0,k=endIndex; j < endIndex; j++, k--) { if (table[j*numParm + 1] > phs ) { p->nextActime = table[j*numParm + 1]; p->nextIndex = j; p->prevActime = table[(j-1)*numParm + 1]; p->prevIndex = j-1; break; } if (table[k*numParm + 1] < phs ) { p->nextActime = table[(k+1)*numParm + 1]; p->nextIndex = k+1; p->prevActime = table[k*numParm + 1]; p->prevIndex = k; break; } } if (phs == p->prevActime&& p->prevIndex != -1 ) { *p->ktrig = 1; for (j=0; j < numParm; j++) { *p->args[j]=table[p->prevIndex*numParm + j]; } } else if (phs == p->nextActime && p->nextIndex != -1 ) { *p->ktrig = 1; for (j=0; j < numParm; j++) { *p->args[j]=table[p->nextIndex*numParm + j]; } } /*p->oldPhs = phs; */ p->initFlag=0; } else { if (phs > p->nextActime || phs < p->prevActime) { for (j=0; j < numParm; j++) { *p->args[j]=table[p->nextIndex*numParm + j]; } if (table[p->nextIndex*numParm] != -1) /* if it is not end locator */ /**p->ktrig = 1; */ *p->ktrig = table[p->nextIndex*numParm + 3]; if (phs > p->nextActime) { if (p->prevIndex > p->nextIndex && p->oldPhs < phs) { /* there is a phase jump */ *p->ktrig = 0; goto fine; } if (fabs(phs-p->nextActime) > minDist) goto prev; p->prevActime = table[p->nextIndex*numParm + 1]; p->prevIndex = p->nextIndex; p->nextIndex = (p->nextIndex + 1) % endIndex; p->nextActime = table[p->nextIndex*numParm + 1]; } else { if (fabs(phs-p->nextActime) > minDist) goto prev; p->nextActime = table[p->prevIndex*numParm + 1]; /*p->nextActime+1; */ p->nextIndex = p->prevIndex; p->prevIndex = (p->prevIndex - 1); if (p->prevIndex < 0) { p->prevIndex += p->endIndex; } p->prevActime = table[p->prevIndex*numParm + 1]; /*p->nextActime+1; */ } } else *p->ktrig = 0; fine: p->oldPhs = phs; } return OK; } #define S(x) sizeof(x) static OENTRY localops[] = { { "metro", S(METRO), 9, 3, "k", "ko", (SUBR)metro_set, (SUBR)metro }, { "splitrig", S(SPLIT_TRIG), 0, 3, "", "kkiiz", (SUBR)split_trig_set, (SUBR)split_trig }, { "timedseq",S(TIMEDSEQ), TR, 3, "k", "kiz", (SUBR)timeseq_set, (SUBR)timeseq } }; int metro_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/midiops2.c000066400000000000000000000535611321653344700164010ustar00rootroot00000000000000/* midiops2.c: Copyright (C) 1997 Gabriel Maldonado (C) 2006 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /****************************************/ /** midicXX UGs by Gabriel Maldonado **/ /****************************************/ #include "stdopcod.h" #include "midiops2.h" #ifndef TRUE #define TRUE (1) #endif #ifndef FALSE #define FALSE (0) #endif #define f7bit (FL(127.0)) #define f14bit (FL(16383.0)) #define f21bit (FL(2097151.0)) #define oneTOf7bit ((MYFLT)1./127.) #define oneTOf14bit ((MYFLT)1./16383.) #define oneTOf21bit ((MYFLT)1./2097151.) /*------------------------------------------------------------------------*/ /* 7 bit midi control UGs */ static int imidic7(CSOUND *csound, MIDICTL2 *p) { MYFLT value; FUNC *ftp; int32 ctlno; if (!p->h.insdshead->m_chnbp) { return OK; } if (UNLIKELY((ctlno = (int32)*p->ictlno) < 0 || ctlno > 127)) return csound->InitError(csound, Str("illegal controller number")); else { value = (MYFLT)(csound->curip->m_chnbp->ctl_val[ctlno] * oneTOf7bit); if (*p->ifn > 0) { if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) == NULL)) return NOTOK; /* if valid ftable, use value as index */ value = *(ftp->ftable + (int32)(value*ftp->flen)); /* no interpolation */ } *p->r = value * (*p->imax - *p->imin) + *p->imin; /* scales the output*/ } return OK; } static int midic7set(CSOUND *csound, MIDICTL2 *p) { int32 ctlno; if (UNLIKELY((ctlno = (int32)*p->ictlno) < 0 || ctlno > 127)) { return csound->InitError(csound, Str("illegal controller number")); } else p->ctlno = ctlno; if (*p->ifn > 0) { if (((p->ftp = csound->FTnp2Find(csound, p->ifn)) == NULL)) p->flag = FALSE; /* invalid ftable */ else p->flag= TRUE; } else p->flag= FALSE; return OK; } static int midic7(CSOUND *csound, MIDICTL2 *p) { MYFLT value; INSDS *lcurip = p->h.insdshead; if (!p->h.insdshead->m_chnbp) { return OK; } value = (MYFLT) (lcurip->m_chnbp->ctl_val[p->ctlno] * oneTOf7bit); if (p->flag) { /* if valid ftable,use value as index */ value = *(p->ftp->ftable + (int32)(value*p->ftp->flen)); /* no interpolation */ } *p->r = value * (*p->imax - *p->imin) + *p->imin; /* scales the output */ return OK; } /*------------------------------------------------------------------------*/ /* 14 bit midi control UGs */ static int imidic14(CSOUND *csound, MIDICTL3 *p) { MYFLT value; FUNC *ftp; int32 ctlno1; int32 ctlno2; if (!p->h.insdshead->m_chnbp) { return OK; } if (UNLIKELY((ctlno1 = (int32)*p->ictlno1) < 0 || ctlno1 > 127 || (ctlno2 = (int32)*p->ictlno2) < 0 || ctlno2 > 127 )) return csound->InitError(csound, Str("illegal controller number")); else { value = (MYFLT) ((csound->curip->m_chnbp->ctl_val[ctlno1] * 128 + csound->curip->m_chnbp->ctl_val[ctlno2]) * oneTOf14bit); if (*p->ifn > 0) { /* linear interpolation routine */ MYFLT phase; MYFLT *base_address; MYFLT *base; MYFLT *top; MYFLT diff; int32 length; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) == NULL)) return NOTOK; /* if valid ftable,use value as index */ phase = value * (length = ftp->flen); diff = phase - (int32) phase; base = (base_address = ftp->ftable) + (int32)(phase); top = base + 1 ; top = (top - base_address > length) ? base_address : top; value = *base + (*top - *base) * diff; } *p->r = value * (*p->imax - *p->imin) + *p->imin; /* scales the output*/ } return OK; } static int midic14set(CSOUND *csound, MIDICTL3 *p) { int32 ctlno1; int32 ctlno2; if (UNLIKELY((ctlno1 = (int32)*p->ictlno1) < 0 || ctlno1 > 127 || (ctlno2 = (int32)*p->ictlno2) < 0 || ctlno2 > 127 )) { return csound->InitError(csound, Str("illegal controller number")); } p->ctlno1 = ctlno1; p->ctlno2 = ctlno2; if (*p->ifn > 0) { if (UNLIKELY(((p->ftp = csound->FTnp2Find(csound, p->ifn)) == NULL))) p->flag = FALSE; /* invalid ftable */ else p->flag= TRUE; } else p->flag= FALSE; return OK; } static int midic14(CSOUND *csound, MIDICTL3 *p) { MYFLT value; INSDS *lcurip = p->h.insdshead; if (!p->h.insdshead->m_chnbp) { return OK; } value = (MYFLT) ((lcurip->m_chnbp->ctl_val[p->ctlno1] *128 + lcurip->m_chnbp->ctl_val[p->ctlno2] ) * oneTOf14bit); if (p->flag) { /* if valid ftable,use value as index */ MYFLT phase = value * p->ftp->flen; /* gab-A1 */ MYFLT *base = p->ftp->ftable + (int32)(phase); value = *base + (*(base+1) - *base) * (phase - (int32) phase); /* linear interpolation routine */ /* MYFLT phase; MYFLT *base_address; MYFLT *base; MYFLT *top; MYFLT diff; int32 length; phase = value * (length = p->ftp->flen); diff = phase - (int32) phase; base = (base_address = p->ftp->ftable) + (int32)(phase); top = base + 1 ; top = (top - base_address > length) ? base_address : top; value = *base + (*top - *base) * diff; */ } *p->r = value * (*p->imax - *p->imin) + *p->imin; /* scales the output */ return OK; } /*-----------------------------------------------------------------------------*/ /* 21 bit midi control UGs */ static int imidic21(CSOUND *csound, MIDICTL4 *p) { MYFLT value; int32 ctlno1; int32 ctlno2; int32 ctlno3; if (!p->h.insdshead->m_chnbp) { return OK; } if (UNLIKELY((ctlno1 = (int32)*p->ictlno1) < 0 || ctlno1 > 127 || (ctlno2 = (int32)*p->ictlno2) < 0 || ctlno2 > 127 || (ctlno3 = (int32)*p->ictlno3) < 0 || ctlno3 > 127)) return csound->InitError(csound, Str("illegal controller number")); else { value = (MYFLT) ((csound->curip->m_chnbp->ctl_val[ctlno1] * 16384 + csound->curip->m_chnbp->ctl_val[ctlno2] * 128 + csound->curip->m_chnbp->ctl_val[ctlno3]) * oneTOf21bit); if (*p->ifn > 0) { /* linear interpolation routine */ FUNC *ftp = csound->FTnp2Find(csound, p->ifn); /* gab-A1 */ MYFLT phase; MYFLT *base; if (UNLIKELY(ftp == NULL)) return csound->InitError(csound, Str("Invalid ftable no. %f"), *p->ifn); phase = value * ftp->flen; base = ftp->ftable + (int32)(phase); value = *base + (*(base+1) - *base) * (phase - (int32)phase); } *p->r = value * (*p->imax - *p->imin) + *p->imin; /* scales the output*/ } return OK; } static int midic21set(CSOUND *csound, MIDICTL4 *p) { int32 ctlno1; int32 ctlno2; int32 ctlno3; if (UNLIKELY((ctlno1 = (int32)*p->ictlno1) < 0 || ctlno1 > 127 || (ctlno2 = (int32)*p->ictlno2) < 0 || ctlno2 > 127 || (ctlno3 = (int32)*p->ictlno3) < 0 || ctlno3 > 127)) { return csound->InitError(csound, Str("illegal controller number")); } p->ctlno1 = ctlno1; p->ctlno2 = ctlno2; p->ctlno3 = ctlno3; if (*p->ifn > 0) { if (UNLIKELY(((p->ftp = csound->FTnp2Find(csound, p->ifn)) == NULL))) p->flag = FALSE; /* invalid ftable */ else p->flag= TRUE; } else p->flag= FALSE; return OK; } static int midic21(CSOUND *csound, MIDICTL4 *p) { MYFLT value; INSDS *lcurip = p->h.insdshead; if (!p->h.insdshead->m_chnbp) { return OK; } value = (MYFLT)((lcurip->m_chnbp->ctl_val[p->ctlno1] * 16384 + lcurip->m_chnbp->ctl_val[p->ctlno2] * 128 + lcurip->m_chnbp->ctl_val[p->ctlno3] ) * oneTOf21bit); if (p->flag) { /* if valid ftable,use value as index */ /* linear interpolation routine */ MYFLT phase = value * p->ftp->flen; MYFLT *base = p->ftp->ftable + (int32)(phase); value = *base + (*(base+1) - *base) * (phase - (int32) phase); /* MYFLT phase; MYFLT *base_address; MYFLT *base; MYFLT *top; MYFLT diff; int32 length; phase = value * (length = p->ftp->flen); diff = phase - (int32) phase; base = (base_address = p->ftp->ftable) + (int32)(phase); top = base + 1 ; top = (top - base_address > length) ? base_address : top; value = *base + (*top - *base) * diff; */ } *p->r = value * (*p->imax - *p->imin) + *p->imin; /* scales the output */ return OK; } /*-----------------------------------------------------------------*/ /* GLOBAL MIDI IN CONTROLS activable by score-oriented instruments*/ /*-----------------------------------------------------------------*/ static int ictrl7(CSOUND *csound, CTRL7 *p) { MYFLT value; FUNC *ftp; int32 ctlno; if (UNLIKELY((ctlno = (int32)*p->ictlno) < 0 || ctlno > 127)) return csound->InitError(csound, Str("illegal controller number")); else { value = (MYFLT) (csound->m_chnbp[(int) *p->ichan-1]->ctl_val[ctlno] * oneTOf7bit); if (*p->ifn > 0) { if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) == NULL)) return NOTOK; /* if valid ftable,use value as index */ value = *(ftp->ftable + (int32)(value*ftp->flen)); /* no interpolation */ } *p->r = value * (*p->imax - *p->imin) + *p->imin; /* scales the output*/ } return OK; } static int ctrl7set(CSOUND *csound, CTRL7 *p) { int32 ctlno; int chan; if (UNLIKELY((ctlno = (int32) *p->ictlno) < 0 || ctlno > 127)) { return csound->InitError(csound, Str("illegal controller number")); } else if (UNLIKELY((chan=(int) *p->ichan-1) < 0 || chan > 15)) { return csound->InitError(csound, Str("illegal midi channel")); /* gab-A2 (chan number fix)*/ } /*else if (midi_in_p_num < 0) midi_in_error("ctrl7");*/ else p->ctlno = ctlno; if (*p->ifn > 0) { if (UNLIKELY(((p->ftp = csound->FTnp2Find(csound, p->ifn)) == NULL))) p->flag = FALSE; /* invalid ftable */ else p->flag= TRUE; } else p->flag= FALSE; return OK; } static int ctrl7(CSOUND *csound, CTRL7 *p) { MYFLT value = (MYFLT) (csound->m_chnbp[(int) *p->ichan-1]->ctl_val[p->ctlno] * oneTOf7bit); if (p->flag) { /* if valid ftable,use value as index */ value = *(p->ftp->ftable + (int32)(value*p->ftp->flen)); /* no interpolation */ } *p->r = value * (*p->imax - *p->imin) + *p->imin; /* scales the output */ return OK; } /* 14 bit midi control UGs */ static int ictrl14(CSOUND *csound, CTRL14 *p) { MYFLT value; int32 ctlno1; int32 ctlno2; int chan; if (UNLIKELY((ctlno1 = (int32)*p->ictlno1) < 0 || ctlno1 > 127 || (ctlno2 = (int32)*p->ictlno2) < 0 || ctlno2 > 127 )) return csound->InitError(csound, Str("illegal controller number")); else if (UNLIKELY((chan=(int) *p->ichan-1) < 0 || chan > 15)) return csound->InitError(csound, Str("illegal midi channel")); else { value = (MYFLT)((csound->m_chnbp[chan]->ctl_val[ctlno1] * 128 + csound->m_chnbp[chan]->ctl_val[ctlno2]) * oneTOf14bit); if (*p->ifn > 0) { /* linear interpolation routine */ FUNC *ftp = csound->FTnp2Find(csound, p->ifn); MYFLT phase; MYFLT *base; if (UNLIKELY(ftp == NULL)) return csound->InitError(csound, Str("Invalid ftable no. %f"), *p->ifn); phase = value * ftp->flen; base = ftp->ftable + (int32)(phase); value = *base + (*(base+1) - *base) * (phase - (int32)phase); } *p->r = value * (*p->imax - *p->imin) + *p->imin; /* scales the output*/ } return OK; } static int ctrl14set(CSOUND *csound, CTRL14 *p) { int32 ctlno1; int32 ctlno2; int chan; if (UNLIKELY((ctlno1 = (int32)*p->ictlno1) < 0 || ctlno1 > 127 || (ctlno2 = (int32)*p->ictlno2) < 0 || ctlno2 > 127 )) { return csound->InitError(csound, Str("illegal controller number")); } else if (UNLIKELY((chan=(int) *p->ichan-1) < 0 || chan > 15)) { return csound->InitError(csound, Str("illegal midi channel")); } p->ctlno1 = ctlno1; p->ctlno2 = ctlno2; if (*p->ifn > 0) { if (UNLIKELY(((p->ftp = csound->FTnp2Find(csound, p->ifn)) == NULL))) p->flag = FALSE; /* invalid ftable */ else p->flag= TRUE; } else p->flag= FALSE; return OK; } static int ctrl14(CSOUND *csound, CTRL14 *p) { MYFLT value; int chan=(int) *p->ichan-1; value = (MYFLT)((csound->m_chnbp[chan]->ctl_val[p->ctlno1] * 128 + csound->m_chnbp[chan]->ctl_val[p->ctlno2]) * oneTOf14bit); if (p->flag) { /* if valid ftable,use value as index */ /* linear interpolation routine */ MYFLT phase = value * p->ftp->flen; MYFLT *base = p->ftp->ftable + (int32)(phase); value = *base + (*(base+1) - *base) * (phase - (int32) phase); } *p->r = value * (*p->imax - *p->imin) + *p->imin; /* scales the output */ return OK; } /*-----------------------------------------------------------------------------*/ /* 21 bit midi control UGs */ static int ictrl21(CSOUND *csound, CTRL21 *p) { MYFLT value; int32 ctlno1; int32 ctlno2; int32 ctlno3; int chan; if (UNLIKELY((ctlno1 = (int32)*p->ictlno1) < 0 || ctlno1 > 127 || (ctlno2 = (int32)*p->ictlno2) < 0 || ctlno2 > 127 || (ctlno3 = (int32)*p->ictlno3) < 0 || ctlno3 > 127)) return csound->InitError(csound, Str("illegal controller number")); else if (UNLIKELY((chan=(int) *p->ichan-1) < 0 || chan > 15)) return csound->InitError(csound, Str("illegal midi channel")); else { value = (MYFLT)((csound->m_chnbp[chan]->ctl_val[ctlno1] * 16384 + csound->m_chnbp[chan]->ctl_val[ctlno2] * 128 + csound->m_chnbp[chan]->ctl_val[ctlno3]) * oneTOf21bit); if (*p->ifn > 0) { /* linear interpolation routine */ FUNC *ftp = csound->FTnp2Find(csound, p->ifn); MYFLT phase; MYFLT *base; if (UNLIKELY(ftp == NULL)) return csound->InitError(csound, Str("Invalid ftable no. %f"), *p->ifn); phase = value * ftp->flen; base = ftp->ftable + (int32)(phase); value = *base + (*(base+1) - *base) * (phase - (int32)phase); } *p->r = value * (*p->imax - *p->imin) + *p->imin; /* scales the output*/ } return OK; } static int ctrl21set(CSOUND *csound, CTRL21 *p) { int32 ctlno1; int32 ctlno2; int32 ctlno3; int chan; if (UNLIKELY((ctlno1 = (int32)*p->ictlno1) < 0 || ctlno1 > 127 || (ctlno2 = (int32)*p->ictlno2) < 0 || ctlno2 > 127 || (ctlno3 = (int32)*p->ictlno3) < 0 || ctlno3 > 127)) { return csound->InitError(csound, Str("illegal controller number")); } else if (UNLIKELY((chan=(int) *p->ichan-1) < 0 || chan > 15)) { return csound->InitError(csound, Str("illegal midi channel")); } p->ctlno1 = ctlno1; p->ctlno2 = ctlno2; p->ctlno3 = ctlno3; if (*p->ifn > 0) { if (UNLIKELY(((p->ftp = csound->FTnp2Find(csound, p->ifn)) == NULL))) p->flag = FALSE; /* invalid ftable */ else p->flag= TRUE; } else p->flag= FALSE; return OK; } static int ctrl21(CSOUND *csound, CTRL21 *p) { MYFLT value; int chan=(int) *p->ichan-1; value = (csound->m_chnbp[chan]->ctl_val[p->ctlno1] * 16384 + csound->m_chnbp[chan]->ctl_val[p->ctlno2] * 128 + csound->m_chnbp[chan]->ctl_val[p->ctlno3]) / f21bit; if (p->flag) { /* if valid ftable,use value as index */ /* linear interpolation routine */ MYFLT phase = value * p->ftp->flen; MYFLT *base = p->ftp->ftable + (int32)(phase); value = *base + (*(base+1) - *base) * (phase - (int32) phase); } *p->r = value * (*p->imax - *p->imin) + *p->imin; /* scales the output */ return OK; } static int initc7(CSOUND *csound, INITC7 *p) /* for setting a precise value use the following formula:*/ { /* (value - min) / (max - min) */ MYFLT fvalue; int chan; if (UNLIKELY((fvalue = *p->ivalue) < 0. || fvalue > 1. )) return csound->InitError(csound, Str("value out of range")); else if (UNLIKELY((chan = (int) *p->ichan-1) < 0 || chan > 15 || !csound->m_chnbp[chan])) return csound->InitError(csound, Str("illegal midi channel")); else csound->m_chnbp[chan]->ctl_val[(int) *p->ictlno] = fvalue * f7bit + FL(0.5); return OK; } static int initc14(CSOUND *csound, INITC14 *p) { MYFLT fvalue; int value, msb, lsb, chan; if (UNLIKELY((fvalue = *p->ivalue) < FL(0.0) || fvalue > FL(1.0) )) return csound->InitError(csound, Str("value out of range")); else if (UNLIKELY((chan = (int) *p->ichan - 1) < 0 || chan > 15 || !csound->m_chnbp[chan])) return csound->InitError(csound, Str("illegal midi channel")); else { value = (int)MYFLT2LONG(fvalue * f14bit); msb = value >> 7; lsb = value & 0x7F; csound->m_chnbp[chan]->ctl_val[(int) *p->ictlno1] = (MYFLT)msb; csound->m_chnbp[chan]->ctl_val[(int) *p->ictlno2] = (MYFLT)lsb; } return OK; } static int initc21(CSOUND *csound, INITC21 *p) { MYFLT fvalue; int value, msb, xsb, lsb, chan; if (UNLIKELY((fvalue = *p->ivalue) < FL(0.0) || fvalue > FL(1.0) )) return csound->InitError(csound, Str("value out of range")); else if (UNLIKELY((chan = (int) *p->ichan - 1) < 0 || chan > 15 || !csound->m_chnbp[chan])) return csound->InitError(csound, Str("illegal midi channel")); else { value = (int)MYFLT2LONG(fvalue * f21bit); msb = value >> 14; xsb = (value >> 7) & 0x7F; lsb = value & 0x7F; csound->m_chnbp[chan]->ctl_val[(int) *p->ictlno1] = (MYFLT)msb; csound->m_chnbp[chan]->ctl_val[(int) *p->ictlno2] = (MYFLT)xsb; csound->m_chnbp[chan]->ctl_val[(int) *p->ictlno3] = (MYFLT)lsb; } return OK; } /* midipgm by Istvan Varga, 2006 */ typedef struct MIDIPGM_OP_ { OPDS h; MYFLT *ipgm, *ichn; } MIDIPGM_OP; static int midipgm_opcode(CSOUND *csound, MIDIPGM_OP *p) { MCHNBLK *chnp; int channelNum; *(p->ipgm) = FL(0.0); channelNum = (int) MYFLT2LONG(*(p->ichn)); if (channelNum > 0) { if (UNLIKELY(channelNum > 16)) return csound->InitError(csound, Str("invalid channel number: %d"), channelNum); chnp = csound->m_chnbp[channelNum - 1]; } else chnp = p->h.insdshead->m_chnbp; if (chnp != NULL) { if ((int) chnp->pgmno >= 0) *(p->ipgm) = (MYFLT) ((int) chnp->pgmno + 1); } return OK; } #define S(x) sizeof(x) static OENTRY localops[] = { { "ctrl14", 0xffff, }, { "ctrl21", 0xffff, }, { "ctrl7", 0xffff, }, { "midic14", 0xffff, }, { "midic21", 0xffff, }, { "midic7", 0xffff, }, { "midic7.i",S(MIDICTL2),0, 1, "i", "iiio", (SUBR)imidic7, NULL, NULL }, { "midic7.k", S(MIDICTL2),0, 3, "k", "ikko", (SUBR)midic7set, (SUBR)midic7, NULL }, { "midic14.i", S(MIDICTL3), 0, 1,"i", "iiiio",(SUBR)imidic14, NULL, NULL }, { "midic14.k", S(MIDICTL3), 0, 3,"k", "iikko",(SUBR)midic14set, (SUBR)midic14,NULL}, { "midic21.i", S(MIDICTL4),0, 1,"i", "iiiiio",(SUBR)imidic21, NULL, NULL }, { "midic21.k", S(MIDICTL4), 0, 3,"k", "iiikko",(SUBR)midic21set,(SUBR)midic21,NULL}, { "ctrl7.i", S(CTRL7), 0, 1, "i", "iiiio", (SUBR)ictrl7, NULL, NULL }, { "ctrl7.k", S(CTRL7), 0, 3, "k", "iikko", (SUBR)ctrl7set, (SUBR)ctrl7, NULL }, { "ctrl14.i", S(CTRL14),0, 1, "i", "iiiiio",(SUBR)ictrl14, NULL, NULL }, { "ctrl14.k", S(CTRL14), 0, 3, "k", "iiikko",(SUBR)ctrl14set, (SUBR)ctrl14, NULL }, { "ctrl21.i", S(CTRL21),0, 1, "i", "iiiiiio", (SUBR)ictrl21, NULL, NULL }, { "ctrl21.k", S(CTRL21), 0, 3, "k", "iiiikko", (SUBR)ctrl21set,(SUBR)ctrl21,NULL}, { "initc7", S(INITC7), 0, 1, "", "iii", (SUBR)initc7, NULL, NULL }, { "initc14", S(INITC14), 0, 1, "", "iiii", (SUBR)initc14, NULL, NULL }, { "initc21", S(INITC21), 0, 1, "", "iiiii",(SUBR)initc21, NULL, NULL }, { "midipgm", S(MIDIPGM_OP), 0, 1, "i", "o", (SUBR)midipgm_opcode, NULL, NULL } }; int midiops2_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/midiops2.h000066400000000000000000000044711321653344700164020ustar00rootroot00000000000000/* midiops2.h: Copyright (C) 1997 Gabriel Maldonado This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /****************************************/ /** midicXX UGs by Gabriel Maldonado **/ /****************************************/ #ifndef MIDIOPS2_H #define MIDIOPS2_H typedef struct { OPDS h; MYFLT *r, *ictlno, *imin, *imax, *ifn; int16 flag; FUNC *ftp; int32 ctlno; } MIDICTL2; typedef struct { OPDS h; MYFLT *r, *ictlno1, *ictlno2, *imin, *imax, *ifn; int16 flag; FUNC *ftp; int32 ctlno1, ctlno2; } MIDICTL3; typedef struct { OPDS h; MYFLT *r, *ictlno1, *ictlno2, *ictlno3, *imin, *imax, *ifn; int16 flag; FUNC *ftp; int32 ctlno1, ctlno2, ctlno3; } MIDICTL4; /*----------------------------------------*/ /* GLOBAL MIDI IN CONTROLS activable by score-oriented instruments*/ typedef struct { OPDS h; MYFLT *r, *ichan, *ictlno, *imin, *imax, *ifn; int16 flag; FUNC *ftp; int32 ctlno; } CTRL7; typedef struct { OPDS h; MYFLT *r, *ichan, *ictlno1, *ictlno2, *imin, *imax, *ifn; int16 flag; FUNC *ftp; int32 ctlno1, ctlno2; } CTRL14; typedef struct { OPDS h; MYFLT *r, *ichan, *ictlno1, *ictlno2, *ictlno3, *imin, *imax, *ifn; int16 flag; FUNC *ftp; int32 ctlno1, ctlno2, ctlno3; } CTRL21; typedef struct { OPDS h; MYFLT *ichan, *ictlno, *ivalue; } INITC7; typedef struct { OPDS h; MYFLT *ichan, *ictlno1, *ictlno2, *ivalue; } INITC14; typedef struct { OPDS h; MYFLT *ichan, *ictlno1, *ictlno2, *ictlno3, *ivalue; } INITC21; #endif csound-6.10.0/Opcodes/midiops3.c000066400000000000000000000762401321653344700164010ustar00rootroot00000000000000/* midiops3.c: Copyright (C) 1997 Gabriel Maldonado This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* sliders and other MIDI opcodes by Gabriel Maldonado */ #include "stdopcod.h" #include "midiops.h" #include "midiops3.h" #include #define f7bit (FL(127.0)) #define oneTOf7bit (MYFLT)(1.0/127.0) #define f14bit (FL(16383.0)) #define oneTOf14bit (MYFLT)(1.0/16383.0) #define f21bit (FL(2097151.0)) #define oneTOf21bit (MYFLT)(1.0/2097151.0) /* This set of macros is rather a cop-out! */ #define SLIDERI_INIT(p, n) \ { \ unsigned char chan = p->slchan = (unsigned char)((*p->ichan)-1); \ char sbuf[120]; \ if (UNLIKELY(chan > 15)) { \ return csound->InitError(csound, Str("illegal channel")); \ } \ { \ MYFLT value; \ int j = 0; \ SLD *sld = p->s; \ unsigned char *slnum = p->slnum; \ MYFLT *min = p->min, *max= p->max; \ FUNC **ftp = p->ftp; \ MYFLT *chanblock = (MYFLT *) csound->m_chnbp[chan]->ctl_val;\ while (j++ < n) { \ *slnum = (unsigned char) *sld->ictlno; \ if (UNLIKELY(*slnum > 127)) { \ snprintf(sbuf, 120, \ Str("illegal control number at position n.%d"), j); \ return csound->InitError(csound, "%s", sbuf); \ } \ if (UNLIKELY((value=*sld->initvalue) < (*min=*sld->imin) || \ value > (*max=*sld->imax) )) { \ snprintf(sbuf, 120, \ Str("illegal initvalue at position n.%d"), \ j); \ return csound->InitError(csound, "%s", sbuf); \ } \ if (*sld->ifn > 0) *ftp++ = csound->FTnp2Find(csound, sld->ifn); \ else *ftp++ = NULL; \ value = (*(sld++)->initvalue - *min) / (*max++ - *min); \ min++; \ chanblock[*slnum++] = (MYFLT)((int)(value * f7bit + FL(0.5))); \ } \ } \ return OK; \ } #define SLIDER_INIT(p, n) \ { \ MYFLT value; \ int j = 0; \ FUNC **ftp = p->ftp-1; \ MYFLT *chanblock = (MYFLT *) csound->m_chnbp[p->slchan]->ctl_val; \ unsigned char *slnum = p->slnum; \ MYFLT *min = p->min, *max = p->max; \ MYFLT **result = p->r; \ while (j++ < n) { \ value = (MYFLT) (chanblock[*slnum++] * oneTOf7bit); \ if (*(++ftp)) /* if valid ftable,use value as index */ \ value = *((*ftp)->ftable + (int32)(value * (*ftp)->flen)); \ /* no interpolation */ \ **result++ = value * (*max++ - *min) + *min; /* scales the output */ \ min++;; \ } \ return OK; \ } /*--------------------------------------------------------*/ static int slider_i8(CSOUND *csound, SLIDER8 *p) { SLIDERI_INIT(p, 8); } static int slider8(CSOUND *csound, SLIDER8 *p) { SLIDER_INIT(p, 8); } static int slider_i16(CSOUND *csound, SLIDER16 *p) { SLIDERI_INIT(p, 16); } static int slider16(CSOUND *csound, SLIDER16 *p) { SLIDER_INIT(p, 16); } static int slider_i32(CSOUND *csound, SLIDER32 *p) { SLIDERI_INIT(p, 32); } static int slider32(CSOUND *csound, SLIDER32 *p) { SLIDER_INIT(p, 32); } static int slider_i64(CSOUND *csound, SLIDER64 *p) { SLIDERI_INIT(p, 64); } static int slider64(CSOUND *csound, SLIDER64 *p) { SLIDER_INIT(p, 64); } /*==============================*/ #define SLIDERIF(p, n) \ { \ unsigned char chan = p->slchan = (unsigned char)((*p->ichan)-1); \ char sbuf[120]; \ if (UNLIKELY(chan > 15)) { \ return csound->InitError(csound, Str("illegal channel")); \ } \ { \ MYFLT value = FL(0.0); \ int j = 0; \ SLDf *sld = p->s; \ unsigned char *slnum = p->slnum; \ MYFLT *min = p->min, *max= p->max; \ FUNC **ftp = p->ftp; \ MYFLT b; \ MYFLT *yt1 = p->yt1, *c1=p->c1, *c2=p->c2; \ MYFLT *chanblock = (MYFLT *) csound->m_chnbp[chan]->ctl_val;\ while (j++ < 8) { \ *slnum = (unsigned char) *sld->ictlno; \ if (UNLIKELY(*slnum > 127)) { \ snprintf(sbuf, 120, \ Str("illegal control number at position n.%d"), j); \ return csound->InitError(csound, "%s", sbuf); \ } \ if (UNLIKELY((value=*sld->initvalue) < (*min=*sld->imin) || \ value > (*max=*sld->imax) )) { \ snprintf(sbuf, 120, \ Str("illegal initvalue at position n.%d"), j); \ return csound->InitError(csound, "%s", sbuf); \ } \ if (*sld->ifn > 0) *ftp++ = csound->FTnp2Find(csound, sld->ifn); \ else *ftp++ = NULL; \ value = (*sld->initvalue - *min) / (*max++ - *min); \ min++;; \ chanblock[*slnum++] = (MYFLT)(int)(value * f7bit + FL(0.5));\ \ /*----- init filtering coeffs*/ \ *yt1++ = FL(0.0); \ b = (MYFLT)(2.0 - cos((double)(*(sld++)->ihp \ * csound->tpidsr \ * CS_KSMPS))); \ *c2 = (MYFLT)(b - sqrt((double)(b * b - FL(1.0)))); \ *c1++ = FL(1.0) - *c2++; \ } \ } \ return OK; \ } #define SLIDERF(p, n) \ { \ MYFLT value; \ int j = 0; \ FUNC **ftp = p->ftp-1; \ MYFLT *chanblock = (MYFLT *) csound->m_chnbp[p->slchan]->ctl_val; \ unsigned char *slnum = p->slnum; \ MYFLT *min = p->min, *max = p->max; \ MYFLT **result = p->r; \ MYFLT *yt1 = p->yt1, *c1=p->c1, *c2=p->c2; \ while (j++ < n) { \ value = chanblock[*slnum++] * oneTOf7bit; \ if (*(++ftp)) /* if valid ftable,use value as index */ \ value = *( (*ftp)->ftable + (int32)(value * (*ftp)->flen));\ value = value * (*max++ - *min) + *min; /* scales the output */ \ min++; \ **result++ = \ *yt1 = *c1++ * value + *c2++ * *yt1; /* filters the output */ \ yt1++; \ } \ return OK; \ } static int slider_i8f(CSOUND *csound, SLIDER8f *p) { SLIDERIF(p, 8); } static int slider8f(CSOUND *csound, SLIDER8f *p) { SLIDERF(p, 8); } static int slider_i16f(CSOUND *csound, SLIDER16f *p) { SLIDERIF(p, 16); } static int slider16f(CSOUND *csound, SLIDER16f *p) { SLIDERF(p, 16); } static int slider_i32f(CSOUND *csound, SLIDER32f *p) { SLIDERIF(p, 32); } static int slider32f(CSOUND *csound, SLIDER32f *p) { SLIDERF(p, 32); } static int slider_i64f(CSOUND *csound, SLIDER64f *p) { SLIDERIF(p, 64); } static int slider64f(CSOUND *csound, SLIDER64f *p) { SLIDERF(p, 64); } /*===================================*/ #define ISLIDER(p, n) \ { \ unsigned char chan= (unsigned char) ((*p->ichan)-1); \ char sbuf[120]; \ if (UNLIKELY(chan > 15)) { \ return csound->InitError(csound, Str("illegal channel")); \ } \ { \ MYFLT value; \ int j = 0; \ ISLD *sld = p->s; \ unsigned char slnum; \ MYFLT *chanblock = (MYFLT *) csound->m_chnbp[chan]->ctl_val;\ FUNC *ftp; \ MYFLT **result = p->r; \ \ while (j++ < n) { \ slnum=(unsigned char) *sld->ictlno; \ if (UNLIKELY(slnum > 127)) { \ snprintf(sbuf, 120, Str("illegal control number at position n.%d"), j); \ return csound->InitError(csound, "%s", sbuf); \ } \ value = chanblock[slnum] * oneTOf7bit; \ if (*sld->ifn > 0) { \ ftp = csound->FTnp2Find(csound, sld->ifn); \ value = *( ftp->ftable + (int32)(value * ftp->flen)); \ /* no interpolation */ \ } \ **result++ = value * (*sld->imax - *sld->imin) + *sld->imin; \ /* scales the output */ \ sld++; \ } \ } \ return OK; \ } static int islider8(CSOUND *csound, ISLIDER8 *p) { ISLIDER(p, 8); } static int islider16(CSOUND *csound, ISLIDER16 *p) { ISLIDER(p, 16); } static int islider32(CSOUND *csound, ISLIDER32 *p) { ISLIDER(p, 32); } static int islider64(CSOUND *csound, ISLIDER64 *p) { ISLIDER(p, 64); } /*-------------------------------*/ #define SLIDERI14(p, n) \ { \ unsigned char chan= p->slchan = (unsigned char)((*p->ichan)-1); \ char sbuf[120]; \ if (UNLIKELY(chan > 15)) { \ return csound->InitError(csound, Str("illegal channel")); \ } \ { \ MYFLT value; \ int intvalue, j = 0; \ SLD14 *sld = p->s; \ unsigned char *slnum_msb = p->slnum_msb; \ unsigned char *slnum_lsb = p->slnum_lsb; \ MYFLT *min = p->min, *max= p->max; \ FUNC **ftp = p->ftp; \ MYFLT *chanblock = (MYFLT *) csound->m_chnbp[chan]->ctl_val; \ \ while (j++ < n) { \ *slnum_msb = (unsigned char)*sld->ictlno_msb; \ if (UNLIKELY(*slnum_msb > 127)) { \ snprintf(sbuf, 120, \ Str("illegal msb control number at position n.%d"), \ j); \ return csound->InitError(csound, "%s", sbuf); \ } \ *slnum_lsb = (unsigned char)*sld->ictlno_lsb; \ if (UNLIKELY(*slnum_lsb > 127)) { \ snprintf(sbuf, 120, \ Str("illegal lsb control number at position n.%d"), \ j); \ return csound->InitError(csound, "%s", sbuf); \ } \ if (UNLIKELY((value=*sld->initvalue) < (*min=*sld->imin) || \ value > (*max=*sld->imax) )) { \ snprintf(sbuf, 120, \ Str("illegal initvalue at position n.%d"), j); \ return csound->InitError(csound, "%s", sbuf); \ } \ if (*sld->ifn > 0) *ftp++ = csound->FTnp2Find(csound, sld->ifn); \ else *ftp++ = NULL; \ intvalue = (int) (((*(sld++)->initvalue - *min) / (*max++ - *min)) \ * f14bit+FL(0.5)); \ min++; \ chanblock[*slnum_msb++] = (MYFLT) (intvalue >> 7); \ chanblock[*slnum_lsb++] = (MYFLT) (intvalue & 0x7f); \ } \ } \ return OK; \ } #define SLIDER14(p, n) \ { \ MYFLT value = FL(0.0); \ int j = 0; \ FUNC **ftp = p->ftp-1; \ MYFLT *chanblock = (MYFLT *) csound->m_chnbp[p->slchan]->ctl_val; \ unsigned char *slnum_msb = p->slnum_msb; \ unsigned char *slnum_lsb = p->slnum_lsb; \ MYFLT *min = p->min, *max = p->max; \ MYFLT **result = p->r; \ \ while (j++ < n) { \ value = (MYFLT)((chanblock[*slnum_msb++] * 128 \ + chanblock[*slnum_lsb++]) * oneTOf14bit); \ if (*(++ftp)) { /* if valid ftable,use value as index */ \ MYFLT phase = value * (*ftp)->flen; \ MYFLT *base = (*ftp)->ftable + (int32)(phase); \ value = *base + (*(base+1) - *base) * (phase - (int32) phase); \ } \ **result++ = value * (*max++ - *min) + *min; /* scales the output */ \ min++; \ } \ return OK; \ } static int slider_i16bit14(CSOUND *csound, SLIDER16BIT14 *p) { SLIDERI14(p, 16); } static int slider16bit14(CSOUND *csound, SLIDER16BIT14 *p) { SLIDER14(p, 16); } static int slider_i32bit14(CSOUND *csound, SLIDER32BIT14 *p) { SLIDERI14(p, 32); } static int slider32bit14(CSOUND *csound, SLIDER32BIT14 *p) { SLIDER14(p, 32); } /*--------------------------------*/ #define ISLIDER14(p, n) \ { \ unsigned char chan = (unsigned char)((*p->ichan)-1); \ char sbuf[120]; \ if (UNLIKELY(chan > 15)) { \ return csound->InitError(csound, Str("illegal channel")); \ } \ { \ MYFLT value; \ int j = 0; \ ISLD14 *sld = p->s; \ unsigned char slnum_msb; \ unsigned char slnum_lsb; \ MYFLT *chanblock = (MYFLT *) csound->m_chnbp[chan]->ctl_val; \ MYFLT **result = p->r; \ \ while (j++ < n) { \ slnum_msb=(unsigned char)*sld->ictlno_msb; \ if (UNLIKELY(slnum_msb > 127)) { \ snprintf(sbuf, 120, \ Str("illegal msb control number at position n.%d"), \ j); \ return csound->InitError(csound, "%s", sbuf); \ } \ slnum_lsb=(unsigned char)*sld->ictlno_lsb; \ if (UNLIKELY(slnum_lsb > 127)) { \ snprintf(sbuf, 120, \ Str("illegal lsb control number at position n.%d"), \ j); \ return csound->InitError(csound, "%s", sbuf); \ } \ \ value = (MYFLT)((chanblock[slnum_msb] * 128 \ + chanblock[slnum_lsb]) * oneTOf14bit); \ if (*sld->ifn > 0) { /* linear interpolation routine */ \ FUNC *ftp= csound->FTnp2Find(csound, sld->ifn); \ MYFLT phase = value * ftp->flen; \ MYFLT *base = ftp->ftable + (int32)(phase); \ value = *base + (*(base + 1) - *base) * (phase - (int32) phase); \ } \ /* scales the output */ \ **result++ = value * (*sld->imax - *sld->imin) + *sld->imin; \ sld++; \ } \ } \ return OK; \ } static int islider16bit14(CSOUND *csound, ISLIDER16BIT14 *p) { ISLIDER14(p, 16); } static int islider32bit14(CSOUND *csound, ISLIDER32BIT14 *p) { ISLIDER14(p, 32); } #define S(x) sizeof(x) static OENTRY localops[] = { { "s16b14", 0xffff, }, { "s32b14", 0xffff, }, { "slider16", 0xffff, }, { "slider32", 0xffff, }, { "slider64", 0xffff, }, { "slider8", 0xffff, }, { "slider8.k", S(SLIDER8), 0, 3, "kkkkkkkk", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiii", (SUBR)slider_i8, (SUBR)slider8, NULL }, { "slider8f", S(SLIDER8f), 0, 3, "kkkkkkkk","iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiii", (SUBR)slider_i8f, (SUBR)slider8f, NULL }, { "slider8.i", S(SLIDER8), 0, 1, "iiiiiiii", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii", (SUBR)islider8, NULL, NULL }, { "slider16.k", S(SLIDER16), 0, 3, "kkkkkkkkkkkkkkkk", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiii", (SUBR)slider_i16, (SUBR)slider16, NULL }, { "slider16f", S(SLIDER16f), 0, 3, "kkkkkkkkkkkkkkkk", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiii", (SUBR)slider_i16f, (SUBR)slider16f, NULL }, { "slider16.i", S(SLIDER16), 0, 1, "iiiiiiiiiiiiiiii", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiii", (SUBR)islider16, NULL, NULL }, { "slider32.k", S(SLIDER32), 0, 3, "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiii", (SUBR)slider_i32, (SUBR)slider32, NULL }, { "slider32f", S(SLIDER32f), 0, 3, "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiii", (SUBR)slider_i32f, (SUBR)slider32f, NULL }, { "slider32.i", S(SLIDER32), 0, 1, "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii", (SUBR)islider32, NULL, NULL }, { "slider64.k", S(SLIDER64), 0, 3, "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk" "kkkkkkkkkkkkkkkkkkk", "iiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiii", (SUBR)slider_i64, (SUBR)slider64, NULL }, { "slider64f", S(SLIDER64f), 0, 3, "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk" "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk", "iiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii", (SUBR)slider_i64f, (SUBR)slider64f, NULL }, { "slider64.i", S(SLIDER64), 0, 1, "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii", "iiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiii", (SUBR)islider64, NULL, NULL }, { "s16b14.k", S(SLIDER16BIT14), 0, 3, "kkkkkkkkkkkkkkkk", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii", (SUBR)slider_i16bit14, (SUBR)slider16bit14, NULL}, { "s32b14.k", S(SLIDER32BIT14), 0, 3, "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii", (SUBR)slider_i32bit14, (SUBR)slider32bit14, NULL}, { "s16b14.i", S(ISLIDER16BIT14), 0, 1, "iiiiiiiiiiiiiiii", "iiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiii", (SUBR)islider16bit14, NULL, NULL }, { "s32b14.i", S(ISLIDER32BIT14), 0, 1, "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii", (SUBR)islider32bit14, NULL, NULL } }; int midiops3_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/midiops3.h000066400000000000000000000114161321653344700164000ustar00rootroot00000000000000/* midiops3.h: Copyright (C) 1997 Gabriel Maldonado This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ typedef struct { MYFLT *ictlno, *imin, *imax, *initvalue, *ifn; } SLD; typedef struct { OPDS h; MYFLT *r[8]; /* output */ MYFLT *ichan; /* input */ SLD s[8]; MYFLT min[8], max[8]; unsigned char slchan, slnum[8]; FUNC *ftp[8]; } SLIDER8; typedef struct { OPDS h; MYFLT *r[16]; /* output */ MYFLT *ichan; /* input */ SLD s[16]; MYFLT min[16], max[16]; unsigned char slchan, slnum[16]; FUNC *ftp[16]; } SLIDER16; typedef struct { OPDS h; MYFLT *r[32]; /* output */ MYFLT *ichan; /* input */ SLD s[32]; MYFLT min[32], max[32]; unsigned char slchan, slnum[32]; FUNC *ftp[32]; } SLIDER32; typedef struct { OPDS h; MYFLT *r[64]; /* output */ MYFLT *ichan; /* input */ SLD s[64]; MYFLT min[64], max[64]; unsigned char slchan, slnum[64]; FUNC *ftp[64]; } SLIDER64; /*=============================*/ typedef struct { MYFLT *ictlno, *imin, *imax, *initvalue, *ifn, *ihp; } SLDf; typedef struct { OPDS h; MYFLT *r[8]; /* output */ MYFLT *ichan; /* input */ SLDf s[8]; MYFLT min[8], max[8]; unsigned char slchan, slnum[8]; FUNC *ftp[8]; MYFLT c1[8], c2[8]; MYFLT yt1[8]; } SLIDER8f; typedef struct { OPDS h; MYFLT *r[16]; /* output */ MYFLT *ichan; /* input */ SLDf s[16]; MYFLT min[16], max[16]; unsigned char slchan, slnum[16]; FUNC *ftp[16]; MYFLT c1[16], c2[16]; MYFLT yt1[16]; } SLIDER16f; typedef struct { OPDS h; MYFLT *r[32]; /* output */ MYFLT *ichan; /* input */ SLDf s[32]; MYFLT min[32], max[32]; unsigned char slchan, slnum[32]; FUNC *ftp[32]; MYFLT c1[32], c2[32]; MYFLT yt1[32]; } SLIDER32f; typedef struct { OPDS h; MYFLT *r[64]; /* output */ MYFLT *ichan; /* input */ SLDf s[64]; MYFLT min[64], max[64]; unsigned char slchan, slnum[64]; FUNC *ftp[64]; MYFLT c1[64], c2[64]; MYFLT yt1[64]; } SLIDER64f; /*---------------------*/ typedef struct { MYFLT *ictlno, *imin, *imax, *ifn; } ISLD; typedef struct { OPDS h; MYFLT *r[8]; /* output */ MYFLT *ichan; /* input */ ISLD s[8]; } ISLIDER8; typedef struct { OPDS h; MYFLT *r[16]; /* output */ MYFLT *ichan; /* input */ ISLD s[16]; } ISLIDER16; typedef struct { OPDS h; MYFLT *r[32]; /* output */ MYFLT *ichan; /* input */ ISLD s[32]; } ISLIDER32; typedef struct { OPDS h; MYFLT *r[64]; /* output */ MYFLT *ichan; /* input */ ISLD s[64]; } ISLIDER64; /*------------------------------*/ typedef struct { MYFLT *ictlno_msb, *ictlno_lsb, *imin, *imax, *initvalue, *ifn; } SLD14; typedef struct { OPDS h; MYFLT *r[16]; /* output */ MYFLT *ichan; /* input */ SLD14 s[16]; MYFLT min[16], max[16]; unsigned char slchan, slnum_msb[16],slnum_lsb[16]; FUNC *ftp[16]; } SLIDER16BIT14; typedef struct { OPDS h; MYFLT *r[32]; /* output */ MYFLT *ichan; /* input */ SLD14 s[32]; MYFLT min[32], max[32]; unsigned char slchan, slnum_msb[32],slnum_lsb[32]; FUNC *ftp[32]; } SLIDER32BIT14; /*--------------------*/ typedef struct { MYFLT *ictlno_msb, *ictlno_lsb, *imin, *imax, *ifn; } ISLD14; typedef struct { OPDS h; MYFLT *r[16]; /* output */ MYFLT *ichan; /* input */ ISLD14 s[16]; } ISLIDER16BIT14; typedef struct { OPDS h; MYFLT *r[32]; /* output */ MYFLT *ichan; /* input */ ISLD14 s[32]; } ISLIDER32BIT14; csound-6.10.0/Opcodes/minmax.c000066400000000000000000000234061321653344700161370ustar00rootroot00000000000000/* minmax.c A Csound opcode library implementing ugens for finding minimum and maximum values. Anthony Kozar April 5, 2005 Jan 26, 2006: Added non-accumulating and abs value variations. Mar 06, 2006: Converted to Csound 5 API. Copyright (C) 2005-6 Anthony M. Kozar Jr. This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // #include "csdl.h" #include "csoundCore.h" #include "interlocks.h" #include typedef struct { OPDS h; MYFLT *accum, *ain; } MINMAXACCUM; typedef struct { OPDS h; MYFLT *xout, *xin1, *xin2toN[VARGMAX]; } MINMAX; /* Which implementation is faster ?? */ static int MaxAccumulate(CSOUND *csound, MINMAXACCUM *p) { MYFLT cur; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *out = p->accum; MYFLT *in = p->ain; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; n out[n])) out[n] = cur; } return OK; } static int MinAccumulate(CSOUND *csound, MINMAXACCUM *p) { MYFLT cur; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *out = p->accum; MYFLT *in = p->ain; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nh.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *out = p->accum; MYFLT *in = p->ain; MYFLT inabs; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; n out[n])) out[n] = inabs; } return OK; } static int MinAbsAccumulate(CSOUND *csound, MINMAXACCUM *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *out = p->accum; MYFLT *in = p->ain; MYFLT inabs; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nh.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int nargs = ((int) p->INOCOUNT) - 1; MYFLT *out = p->xout; MYFLT *in1 = p->xin1; MYFLT **in2 = p->xin2toN; MYFLT max, temp; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; n max)) max = temp; } out[n] = max; } return OK; } static int Min_arate(CSOUND *csound, MINMAX *p) { int i; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int nargs = ((int) p->INOCOUNT) - 1; MYFLT *out = p->xout; MYFLT *in1 = p->xin1; MYFLT **in2 = p->xin2toN; MYFLT min, temp; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nh.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int nargs = ((int) p->INOCOUNT) - 1; MYFLT *out = p->xout; MYFLT *in1 = p->xin1; MYFLT **in2 = p->xin2toN; MYFLT max, temp; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; n max)) max = temp; } out[n] = max; } return OK; } static int MinAbs_arate(CSOUND *csound, MINMAX *p) { int i; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int nargs = ((int) p->INOCOUNT) - 1; MYFLT *out = p->xout; MYFLT *in1 = p->xin1; MYFLT **in2 = p->xin2toN; MYFLT min, temp; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nINOCOUNT) - 1; MYFLT *out = p->xout; MYFLT *in1 = p->xin1; MYFLT **in2 = p->xin2toN; MYFLT max, temp; max = *in1; for (i = 0; i < nargs; ++i) { temp = in2[i][0]; if (UNLIKELY(temp > max)) max = temp; } *out = max; return OK; } static int Min_krate(CSOUND *csound, MINMAX *p) { int i; int nargs = ((int) p->INOCOUNT) - 1; MYFLT *out = p->xout; MYFLT *in1 = p->xin1; MYFLT **in2 = p->xin2toN; MYFLT min, temp; min = *in1; for (i = 0; i < nargs; ++i) { temp = in2[i][0]; if (UNLIKELY(temp < min)) min = temp; } *out = min; return OK; } /* Absolute value versions of k-rate opcodes */ static int MaxAbs_krate(CSOUND *csound, MINMAX *p) { int i; int nargs = ((int) p->INOCOUNT) - 1; MYFLT *out = p->xout; MYFLT *in1 = p->xin1; MYFLT **in2 = p->xin2toN; MYFLT max, temp; max = FABS(*in1); for (i = 0; i < nargs; ++i) { temp = FABS(in2[i][0]); if (UNLIKELY(temp > max)) max = temp; } *out = max; return OK; } static int MinAbs_krate(CSOUND *csound, MINMAX *p) { int i; int nargs = ((int) p->INOCOUNT) - 1; MYFLT *out = p->xout; MYFLT *in1 = p->xin1; MYFLT **in2 = p->xin2toN; MYFLT min, temp; min = FABS(*in1); for (i = 0; i < nargs; ++i) { temp = FABS(in2[i][0]); if (UNLIKELY(temp < min)) min = temp; } *out = min; return OK; } /* code for linking dynamic libraries under Csound 5 */ #define S(x) sizeof(x) static OENTRY minmax_localops[] = { {"maxaccum", S(MINMAXACCUM), 0, 4, "", "aa", NULL, NULL, (SUBR) MaxAccumulate}, {"minaccum", S(MINMAXACCUM), 0, 4, "", "aa", NULL, NULL, (SUBR) MinAccumulate}, {"maxabsaccum", S(MINMAXACCUM), 0, 4, "", "aa", NULL, NULL, (SUBR) MaxAbsAccumulate}, {"minabsaccum", S(MINMAXACCUM), 0, 4, "", "aa", NULL, NULL, (SUBR) MinAbsAccumulate}, {"max", 0xffff}, {"min", 0xffff}, {"maxabs", 0xffff}, {"minabs", 0xffff}, {"max.a", S(MINMAX), 0, 4, "a", "ay", NULL, NULL, (SUBR) Max_arate}, {"min.a", S(MINMAX), 0, 4, "a", "ay", NULL, NULL, (SUBR) Min_arate}, {"maxabs.a", S(MINMAX), 0, 4, "a", "ay", NULL, NULL, (SUBR) MaxAbs_arate}, {"minabs.a", S(MINMAX), 0, 4, "a", "ay", NULL, NULL, (SUBR) MinAbs_arate}, {"max.k", S(MINMAX), 0, 2, "k", "kz", NULL, (SUBR) Max_krate, NULL}, {"min.k", S(MINMAX), 0, 2, "k", "kz", NULL, (SUBR) Min_krate, NULL}, {"max.i", S(MINMAX), 0, 1, "i", "im", (SUBR) Max_krate, NULL, NULL}, {"min.i", S(MINMAX), 0, 1, "i", "im", (SUBR) Min_krate, NULL, NULL}, {"maxabs.k", S(MINMAX), 0, 2, "k", "kz", NULL, (SUBR) MaxAbs_krate, NULL}, {"minabs.k", S(MINMAX), 0, 2, "k", "kz", NULL, (SUBR) MinAbs_krate, NULL} }; LINKAGE_BUILTIN(minmax_localops) csound-6.10.0/Opcodes/mixer.cpp000066400000000000000000000416721321653344700163370ustar00rootroot00000000000000/* mixer.cpp: Copyright (C) 2005 by Michael Gogins This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "OpcodeBase.hpp" #include #include using namespace csound; // Define ENABLE_MIXER_IDEBUG to enable i-rate debug messages. //#define ENABLE_MIXER_IDEBUG // Define ENABLE_MIXER_KDEBUG to enable -rate and a-rate debug messages. //#define ENABLE_MIXER_KDEBUG /** * The mixer busses are laid out: * busses[csound][bus][channel][frame]. * std::map > > > *busses = 0; * * The mixer send matrix is laid out: * matrix[csound][send][bus]. * std::map > > *matrix = 0; */ /** * Creates the buss if it does not already exist. */ static void createBuss(CSOUND *csound, size_t buss) { #ifdef ENABLE_MIXER_IDEBUG csound->Message(csound, "createBuss: csound %p buss %d...\n", csound, buss); #endif std::map > > > *busses = 0; csound::QueryGlobalPointer(csound, "busses", busses); if ((*busses)[csound].find(buss) == (*busses)[csound].end()) { size_t channels = csound->GetNchnls(csound); size_t frames = csound->GetKsmps(csound); (*busses)[csound][buss].resize(channels); for (size_t channel = 0; channel < channels; channel++) { (*busses)[csound][buss][channel].resize(frames); } #ifdef ENABLE_MIXER_IDEBUG csound->Message(csound, "createBuss: created buss.\n"); #endif } else { #ifdef ENABLE_MIXER_IDEBUG csound->Message(csound, "createBuss: buss already exists.\n"); #endif } } /** * MixerSetLevel isend, ibuss, kgain * * Controls the gain of any signal route from a send to a bus */ struct MixerSetLevel : public OpcodeBase { // No outputs. // Inputs. MYFLT *isend; MYFLT *ibuss; MYFLT *kgain; // State. size_t send; size_t buss; std::map > > *matrix; int init(CSOUND *csound) { #ifdef ENABLE_MIXER_IDEBUG warn(csound, "MixerSetLevel::init...\n"); #endif csound::QueryGlobalPointer(csound, "matrix", matrix); send = static_cast(*isend); buss = static_cast(*ibuss); createBuss(csound, buss); (*matrix)[csound][send][buss] = *kgain; #ifdef ENABLE_MIXER_IDEBUG warn(csound, "MixerSetLevel::init: csound %p send %d buss %d gain %f\n", csound, send, buss, (*matrix)[csound][send][buss]); #endif return OK; } int kontrol(CSOUND *csound) { (*matrix)[csound][send][buss] = *kgain; #ifdef ENABLE_MIXER_KDEBUG warn(csound, "MixerSetLevel::kontrol: csound %p send %d buss " "%d gain %f\n", csound, send, buss, (*matrix)[csound][send][buss]); #endif return OK; } }; /** * kgain MixerGetLevel isend, ibuss * * Returns the gain of any signal route from a send to a bus. */ struct MixerGetLevel : public OpcodeBase { //. MYFLT *kgain; // Inputs. MYFLT *isend; MYFLT *ibuss; // State. size_t send; size_t buss; std::map > > *matrix; int init(CSOUND *csound) { #ifdef ENABLE_MIXER_IDEBUG warn(csound, "MixerGetLevel::init...\n"); #endif csound::QueryGlobalPointer(csound, "matrix", matrix); send = static_cast(*isend); buss = static_cast(*ibuss); createBuss(csound, buss); return OK; } int noteoff(CSOUND *) { return OK; } int kontrol(CSOUND *csound) { #ifdef ENABLE_MIXER_KDEBUG warn(csound, "MixerGetLevel::kontrol...\n"); #endif *kgain = (*matrix)[csound][send][buss]; return OK; } }; /** * MixerSend asignal, isend, ibus, ichannel * * Routes a signal from a send to a channel of a mixer bus. * The gain of the send is controlled by the previously set mixer level. */ struct MixerSend : public OpcodeBase { // No outputs. // Inputs. MYFLT *ainput; MYFLT *isend; MYFLT *ibuss; MYFLT *ichannel; // State. size_t send; size_t buss; size_t channel; size_t frames; MYFLT *busspointer; std::map > > > *busses; std::map > > *matrix; int init(CSOUND *csound) { #ifdef ENABLE_MIXER_IDEBUG warn(csound, "MixerSend::init...\n"); #endif csound::QueryGlobalPointer(csound, "busses", busses); csound::QueryGlobalPointer(csound, "matrix", matrix); send = static_cast(*isend); buss = static_cast(*ibuss); createBuss(csound, buss); channel = static_cast(*ichannel); frames = opds.insdshead->ksmps; busspointer = &(*busses)[csound][buss][channel].front(); #ifdef ENABLE_MIXER_IDEBUG warn(csound, "MixerSend::init: instance %p send %d buss " "%d channel %d frames %d busspointer %p\n", csound, send, buss, channel, frames, busspointer); #endif return OK; } int noteoff(CSOUND *) { return OK; } int audio(CSOUND *csound) { #ifdef ENABLE_MIXER_KDEBUG warn(csound, "MixerSend::audio...\n"); #endif MYFLT gain = (*matrix)[csound][send][buss]; for (size_t i = 0; i < frames; i++) { busspointer[i] += (ainput[i] * gain); } #ifdef ENABLE_MIXER_KDEBUG warn(csound, "MixerSend::audio: instance %d send %d buss " "%d gain %f busspointer %p\n", csound, send, buss, gain, busspointer); #endif return OK; } }; /** * asignal MixerReceive ibuss, ichannel * * Receives a signal from a channel of a bus. * Obviously, instruments receiving signals must be numbered higher * than instruments sending those signals. */ struct MixerReceive : public OpcodeBase { // Output. MYFLT *aoutput; // Inputs. MYFLT *ibuss; MYFLT *ichannel; // State. size_t buss; size_t channel; size_t frames; MYFLT *busspointer; std::map > > > *busses; int init(CSOUND *csound) { csound::QueryGlobalPointer(csound, "busses", busses); buss = static_cast(*ibuss); channel = static_cast(*ichannel); frames = opds.insdshead->ksmps; createBuss(csound, buss); #ifdef ENABLE_MIXER_IDEBUG warn(csound, "MixerReceive::init...\n"); #endif busspointer = &(*busses)[csound][buss][channel].front(); #ifdef ENABLE_MIXER_IDEBUG warn(csound, "MixerReceive::init csound %p buss %d channel " "%d frames %d busspointer %p\n", csound, buss, channel, frames, busspointer); #endif return OK; } int noteoff(CSOUND *) { return OK; } int audio(CSOUND *csound) { #ifdef ENABLE_MIXER_KDEBUG warn(csound, "MixerReceive::audio...\n"); #endif for (size_t i = 0; i < frames; i++) { aoutput[i] = busspointer[i]; } #ifdef ENABLE_MIXER_KDEBUG warn(csound, "MixerReceive::audio aoutput %p busspointer %p\n", aoutput, buss); #endif return OK; } }; /** * MixerClear * * Clears all busses. Must be invoked after last MixerReceive. * You should probably use a highest-numbered instrument * with an indefinite duration that invokes only this opcode. */ struct MixerClear : public OpcodeBase { // No output. // No input. // State. std::map > > > *busses; int init(CSOUND *csound) { csound::QueryGlobalPointer(csound, "busses", busses); return OK; } int audio(CSOUND *csound) { #ifdef ENABLE_MIXER_KDEBUG warn(csound, "MixerClear::audio...\n") #endif for (std::map > >::iterator busi = (*busses)[csound].begin(); busi != (*busses)[csound].end(); ++busi) { for (std::vector< std::vector >::iterator channeli = busi->second.begin(); channeli != busi->second.end(); ++channeli) { for (std::vector::iterator framei = (*channeli).begin(); framei != (*channeli).end(); ++framei) { *framei = 0; } } } #ifdef ENABLE_MIXER_KDEBUG warn(csound, "MixerClear::audio\n") #endif return OK; } }; extern "C" { static OENTRY localops[] = { { (char *)"MixerSetLevel", sizeof(MixerSetLevel), _CW, 3, (char *)"", (char *)"iik", (SUBR) &MixerSetLevel::init_, (SUBR) &MixerSetLevel::kontrol_, 0 }, { (char *)"MixerSetLevel_i", sizeof(MixerSetLevel), _CW, 1, (char *)"", (char *)"iii", (SUBR) &MixerSetLevel::init_, 0, 0 }, { (char *)"MixerGetLevel", sizeof(MixerGetLevel), _CR, 3, (char *)"k", (char *)"ii", (SUBR) &MixerGetLevel::init_, (SUBR) &MixerGetLevel::kontrol_, 0 }, { (char *)"MixerSend", sizeof(MixerSend), _CR, 5, (char *)"", (char *)"aiii", (SUBR) &MixerSend::init_, 0, (SUBR) &MixerSend::audio_ }, { (char *)"MixerReceive", sizeof(MixerReceive), _CW, 5, (char *)"a", (char *)"ii", (SUBR) &MixerReceive::init_, 0, (SUBR) &MixerReceive::audio_ }, { (char *)"MixerClear", sizeof(MixerClear), 0, 5, (char *)"", (char *)"", (SUBR) &MixerClear::init_, 0, (SUBR) &MixerClear::audio_ }, { NULL, 0, 0, 0, NULL, NULL, (SUBR) NULL, (SUBR) NULL, (SUBR) NULL } }; PUBLIC int csoundModuleCreate_mixer(CSOUND *csound) { std::map > > > *busses = 0; busses = new std::map > > >; csound::CreateGlobalPointer(csound, "busses", busses); std::map > > *matrix = 0; matrix = new std::map > >; csound::CreateGlobalPointer(csound, "matrix", matrix); return OK; } PUBLIC int csoundModuleInit_mixer(CSOUND *csound) { OENTRY *ep = (OENTRY *) &(localops[0]); int err = 0; while (ep->opname != NULL) { err |= csound->AppendOpcode(csound, ep->opname, ep->dsblksiz, ep->flags, ep->thread, ep->outypes, ep->intypes, (int (*)(CSOUND *, void *)) ep->iopadr, (int (*)(CSOUND *, void *)) ep->kopadr, (int (*)(CSOUND *, void *)) ep->aopadr); ep++; } return err; } /* * The mixer busses are laid out: * busses[csound][bus][channel][frame]. * std::map > > > *busses = 0; * The mixer send matrix is laid out: * matrix[csound][send][bus]. * std::map > > *matrix = 0; */ PUBLIC int csoundModuleDestroy_mixer(CSOUND *csound) { std::map > > > *busses = 0; csound::QueryGlobalPointer(csound, "busses", busses); if (busses) { for (std::map > >::iterator busi = (*busses)[csound].begin(); busi != (*busses)[csound].end(); ++busi) { for (std::vector< std::vector >::iterator channeli = busi->second.begin(); channeli != busi->second.end(); ++channeli) { channeli->resize(0); } busi->second.clear(); } busses->clear(); csound::DestroyGlobalPointer(csound, "busses", busses); busses = 0; } std::map > > *matrix = 0; csound::QueryGlobalPointer(csound, "matrix", matrix); if (matrix) { // std::map > > for (std::map >::iterator matrixi = (*matrix)[csound].begin(); matrixi != (*matrix)[csound].end(); ++matrixi) { matrixi->second.clear(); } matrix->clear(); csound::DestroyGlobalPointer(csound, "matrix", matrix); matrix = 0; } return OK; } #ifndef INIT_STATIC_MODULES PUBLIC int csoundModuleCreate(CSOUND *csound) { return csoundModuleCreate_mixer(csound); } PUBLIC int csoundModuleInit(CSOUND *csound) { return csoundModuleInit_mixer(csound); } PUBLIC int csoundModuleDestroy(CSOUND *csound) { return csoundModuleDestroy_mixer(csound); } #endif } // END EXTERN C csound-6.10.0/Opcodes/modal4.c000066400000000000000000000472401321653344700160300ustar00rootroot00000000000000/* modal4.c: Copyright (C) 1996, 1997 Perry Cook, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /*******************************************/ /* 4 Resonance Modal Synthesis Instrument */ /* by Perry R. Cook, 1995-96 */ /* This instrument contains an excitation */ /* wavetable, an envelope, and four reso- */ /* nances (Non-Sweeping BiQuad Filters). */ /*******************************************/ // #include "csdl.h" #include "csoundCore.h" #include "modal4.h" #include "marimba.h" #include "vibraphn.h" #include #include "interlocks.h" static int make_Modal4(CSOUND *csound, Modal4 *m, MYFLT *ifn, MYFLT vgain, MYFLT vrate) { FUNC *ftp; if (LIKELY((ftp = csound->FTnp2Find(csound,ifn)) != NULL)) m->vibr = ftp; else { /* Expect sine wave */ csound->ErrorMsg(csound, Str("No table for Modal4 case")); return NOTOK; } make_Envelope(&m->envelope); /* We do not make the excitation wave here yet, */ /* because we do not know what it's going to be. */ make_BiQuad(&m->filters[0]); make_BiQuad(&m->filters[1]); make_BiQuad(&m->filters[2]); make_BiQuad(&m->filters[3]); make_OnePole(&m->onepole); m->v_rate = vrate; /* 6.0; */ m->vibrGain = vgain; /* 0.05; */ /* m->directGain = 0.0; */ m->masterGain = FL(1.0); /* m->baseFreq = 440.0; */ /* Modal4_setRatioAndReson(m, 0, 1.00, 0.9997); */ /* Set some */ /* Modal4_setRatioAndReson(m, 1, 1.30, 0.9997); */ /* silly */ /* Modal4_setRatioAndReson(m, 2, 1.77, 0.9997); */ /* default */ /* Modal4_setRatioAndReson(m, 3, 2.37, 0.9997); */ /* values here */ /* Modal4_setFiltGain(m, 0, 0.01); */ /* Modal4_setFiltGain(m, 1, 0.01); */ /* Modal4_setFiltGain(m, 2, 0.01); */ /* Modal4_setFiltGain(m, 3, 0.01); */ /* OnePole_clear(&m->onepole); */ BiQuad_clear(&m->filters[0]); BiQuad_clear(&m->filters[1]); BiQuad_clear(&m->filters[2]); BiQuad_clear(&m->filters[3]); BiQuad_setEqualGainZeroes(m->filters[0]); BiQuad_setEqualGainZeroes(m->filters[1]); BiQuad_setEqualGainZeroes(m->filters[2]); BiQuad_setEqualGainZeroes(m->filters[3]); /* stickHardness = 0.5; */ /* strikePosition = 0.561; */ return OK; } void Modal4_setFreq(CSOUND *csound, Modal4 *m, MYFLT frequency) { m->baseFreq = frequency; Modal4_setRatioAndReson(csound, m, 0,m->ratios[0],m->resons[0]); Modal4_setRatioAndReson(csound, m, 1,m->ratios[1],m->resons[1]); Modal4_setRatioAndReson(csound, m, 2,m->ratios[2],m->resons[2]); Modal4_setRatioAndReson(csound, m, 3,m->ratios[3],m->resons[3]); } void Modal4_setRatioAndReson(CSOUND *csound, Modal4 *m, int whichOne, MYFLT ratio,MYFLT reson) { MYFLT temp; if (ratio* m->baseFreq < CS_ESR * FL(0.5)) { m->ratios[whichOne] = ratio; } else { temp = ratio; while (temp* m->baseFreq > FL(0.5)*CS_ESR) temp *= FL(0.5); m->ratios[whichOne] = temp; } m->resons[whichOne] = reson; if (ratio<0) temp = -ratio; else temp = ratio * m->baseFreq; BiQuad_setFreqAndReson(m->filters[whichOne], temp,reson); } static void Modal4_strike(CSOUND *csound, Modal4 *m, MYFLT amplitude) { int i; MYFLT temp; Envelope_setRate(csound, &m->envelope, FL(1.0)); Envelope_setTarget(&m->envelope, amplitude); OnePole_setPole(&m->onepole, FL(1.0) - amplitude); Envelope_tick(&m->envelope); m->w_time = FL(0.0); //m->w_lastOutput = FL(0.0); m->w_allDone = 0; /* wave->reset(); */ for (i=0;i<4;i++) { if (m->ratios[i] < 0) temp = - m->ratios[i]; else temp = m->ratios[i] * m->baseFreq; BiQuad_setFreqAndReson(m->filters[i], temp, m->resons[i]); } } static void Modal4_damp(CSOUND *csound, Modal4 *m, MYFLT amplitude) { int i; MYFLT temp; for (i=0;i<4;i++) { if (m->ratios[i] < 0) temp = - m->ratios[i]; else temp = m->ratios[i] * m->baseFreq; BiQuad_setFreqAndReson(m->filters[i], temp, m->resons[i]*amplitude); } } static MYFLT Modal4_tick(Modal4 *m) { MYFLT temp,temp2; int32 itemp; MYFLT temp_time, alpha, lastOutput; int length = (int)m->wave->flen; m->w_time += m->w_rate; /* Update current time */ if (m->w_time >= length) { /* Check for end of sound */ m->w_time = (MYFLT)(length-1); /* stick at end */ m->w_allDone = 1; /* Information for one-shot use */ } else if (m->w_time < FL(0.0)) /* Check for end of sound */ m->w_time = FL(0.0); /* stick at beg */ temp_time = m->w_time; #ifdef phase_offset if (m->w_phaseOffset != FL(0.0)) { temp_time += m->w_phaseOffset; /* Add phase offset */ if (temp_time >= length) /* Check for end of sound */ temp_time = length-1; /* stick at end */ else if (temp_time < FL(0.0)) /* check for end of sound */ temp_time = FL(0.0); /* stick at beg */ } #endif itemp = (int32) temp_time; /* Integer part of time address */ alpha = temp_time - (MYFLT)itemp; /* fractional part of time address */ lastOutput = m->wave->ftable[itemp]; /* Do linear interpolation */ lastOutput = lastOutput + /* same as alpha*data[temp+1] */ (alpha * (m->wave->ftable[itemp+1] - lastOutput)); /* + (1-alpha)data[temp] */ temp = m->masterGain * OnePole_tick(&m->onepole, lastOutput * Envelope_tick(&m->envelope)); temp2 = BiQuad_tick(&m->filters[0], temp); temp2 += BiQuad_tick(&m->filters[1], temp); temp2 += BiQuad_tick(&m->filters[2], temp); temp2 += BiQuad_tick(&m->filters[3], temp); temp2 = temp2 - (temp2 * m->directGain); temp2 += m->directGain * temp; if (m->vibrGain != 0.0) { /* Tick on vibrato table */ m->v_time += m->v_rate; /* Update current time */ while (m->v_time >= m->vibr->flen) /* Check for end of sound */ m->v_time -= m->vibr->flen; /* loop back to beginning */ while (m->v_time < FL(0.0)) /* Check for end of sound */ m->v_time += m->vibr->flen; /* loop back to beginning */ temp_time = m->v_time; #ifdef phase_offset if (m->v_phaseOffset != FL(0.0)) { temp_time += m->v_phaseOffset; /* Add phase offset */ while (temp_time >= m->vibr->flen) /* Check for end of sound */ temp_time -= m->vibr->flen; /* loop back to beginning */ while (temp_time < FL(0.0)) /* Check for end of sound */ temp_time += m->vibr->flen; /* loop back to beginning */ } #endif itemp = (int32) temp_time; /* Integer part of time address */ /* fractional part of time address */ alpha = temp_time - (MYFLT)itemp; lastOutput = m->vibr->ftable[itemp]; /* Do linear interpolation */ /* same as alpha*data[itemp+1] + (1-alpha)data[temp] */ lastOutput = /*m->v)*/lastOutput + (alpha * (m->vibr->ftable[itemp+1] - lastOutput)); /* End of vibrato tick */ temp = FL(1.0) + (lastOutput * m->vibrGain); /* Calculate AM */ temp2 = temp * temp2; /* and apply to master out */ } return (temp2 + temp2); } /*******************************************/ /* Marimba SubClass of Modal4 Instrument, */ /* by Perry R. Cook, 1995-96 */ /* */ /* Controls: stickHardness */ /* strikePosition */ /* vibFreq */ /* vibAmt */ /*******************************************/ int marimbaset(CSOUND *csound, MARIMBA *p) { Modal4 *m = &(p->m4); MYFLT temp,temp2; int itemp; FUNC *ftp; if (LIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) != NULL)) p->m4.wave = ftp; else { /* Expect an impulslything */ return csound->InitError(csound, Str("No table for Marimba strike")); } if (UNLIKELY(make_Modal4(csound, m, p->ivfn, *p->vibAmt, *p->vibFreq)==NOTOK)) return NOTOK; p->m4.w_phaseOffset = FL(0.0); /* p->m4.w_rate = 0.5; */ Modal4_setRatioAndReson(csound,m,0, FL(1.00), FL(0.9996)); /* Set all 132.0 */ Modal4_setRatioAndReson(csound,m,1, FL(3.99), FL(0.9994)); /* of our 523.0 */ Modal4_setRatioAndReson(csound,m,2,FL(10.65), FL(0.9994)); /* default 1405.0 */ Modal4_setRatioAndReson(csound,m,3,-FL(18.50),FL(0.999)); /* resonances 2443 */ Modal4_setFiltGain(m, 0, FL(0.04)); /* and */ Modal4_setFiltGain(m, 1, FL(0.01)); /* gains */ Modal4_setFiltGain(m, 2, FL(0.01)); /* for each */ Modal4_setFiltGain(m, 3, FL(0.008)); /* resonance */ p->m4.directGain = FL(0.1); p->multiStrike = 0; p->strikePosition = *p->spos; /* Set Stick hardness stuff */ p->stickHardness = *p->hardness; p->m4.w_rate = (FL(0.25) * (MYFLT)pow(4.0,(double)p->stickHardness)); p->m4.masterGain = (FL(0.1) + (FL(1.8) * p->stickHardness)); /* Set Strike position */ temp2 = p->strikePosition * PI_F; temp = SIN(temp2); BiQuad_setGain(p->m4.filters[0], FL(0.12)*temp); /* 1st mode function of pos.*/ temp = SIN(FL(0.05) + (FL(3.9) * temp2)); BiQuad_setGain(p->m4.filters[1], -FL(0.03)*temp); /* 2nd mode function of pos.*/ temp = SIN(-FL(0.05) + (FL(11.0) * temp2)); BiQuad_setGain(p->m4.filters[2], FL(0.11)*temp); /* 3rd mode function of pos.*/ /* Strike */ { int triples = (*p->triples<=FL(0.0) ? 20 : (int)*p->triples); int doubles = (*p->doubles<=FL(0.0) ? 40 : triples + (int)*p->doubles); itemp = csound->Rand31(&(csound->randSeed1)) % 100; if (itemp < triples) { p->multiStrike = 2; if (csound->oparms->msglevel & RNGEMSG) csound->Message(csound, Str("striking three times here!!!\n")); } else if (itemp < doubles) { p->multiStrike = 1; if (csound->oparms->msglevel & RNGEMSG) csound->Message(csound, Str("striking twice here!!\n")); } else p->multiStrike = 0; } Modal4_strike(csound, m, *p->amplitude * AMP_RSCALE); Modal4_setFreq(csound, m, *p->frequency); p->first = 1; { int relestim = (int) (CS_EKR * *p->dettack); /* 0.1 second decay extention */ if (relestim > p->h.insdshead->xtratim) p->h.insdshead->xtratim = relestim; } p->kloop = (int) ((int32) (p->h.insdshead->offtim * CS_EKR) - (int32) (CS_EKR * *p->dettack)); return OK; } int marimba(CSOUND *csound, MARIMBA *p) { Modal4 *m = &(p->m4); MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT amp = (*p->amplitude) * AMP_RSCALE; /* Normalise */ if (p->kloop>0 && p->h.insdshead->relesing) p->kloop=1; if ((--p->kloop) == 0) { Modal4_damp(csound, m, FL(1.0) - (amp * FL(0.03))); } p->m4.v_rate = *p->vibFreq; /* 6.0; */ p->m4.vibrGain = *p->vibAmt; /* 0.05; */ if (UNLIKELY(p->first)) { Modal4_strike(csound, m, *p->amplitude * AMP_RSCALE); Modal4_setFreq(csound, m, *p->frequency); p->first = 0; } if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;nmultiStrike>0) if (p->m4.w_allDone) { p->m4.w_time = FL(0.0); //p->m4.w_lastOutput = FL(0.0); p->m4.w_allDone = 0; p->multiStrike -= 1; } lastOutput = Modal4_tick(m); ar[n] = lastOutput*AMP_SCALE*FL(0.5); } return OK; } /*******************************************/ /* Vibraphone SubClass of Modal4 */ /* Instrument, by Perry R. Cook, 1995-96 */ /* */ /* Controls: CONTROL1 = stickHardness */ /* CONTROL2 = strikePosition*/ /* CONTROL3 = vibFreq */ /* MOD_WHEEL= vibAmt */ /*******************************************/ int vibraphnset(CSOUND *csound, VIBRAPHN *p) { Modal4 *m = &(p->m4); MYFLT temp; FUNC *ftp; if (LIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) != NULL)) p->m4.wave = ftp; /* Expect an impulslything */ else { return csound->InitError(csound, Str("No table for Vibraphone strike")); } if (UNLIKELY(make_Modal4(csound, m, p->ivfn, *p->vibAmt, *p->vibFreq)==NOTOK)) return NOTOK; p->m4.w_phaseOffset = FL(0.0); /* p->m4.w_rate = 13.33; */ OnePole_setPole(&p->m4.onepole, FL(0.2)); Modal4_setRatioAndReson(csound, m, 0, FL(1.0), FL(0.99995)); /* Set */ Modal4_setRatioAndReson(csound, m, 1, FL(2.01),FL(0.99991)); /* our */ Modal4_setRatioAndReson(csound, m, 2, FL(3.9), FL(0.99992)); /* resonance */ Modal4_setRatioAndReson(csound, m, 3,FL(14.37),FL(0.99990)); /* values here */ Modal4_setFiltGain(m, 0, FL(0.025)); Modal4_setFiltGain(m, 1, FL(0.015)); Modal4_setFiltGain(m, 2, FL(0.015)); Modal4_setFiltGain(m, 3, FL(0.015)); p->m4.directGain = FL(0.0); /* vibrGain = 0.2; */ p->m4.w_rate = FL(2.0) + (FL(22.66) * *p->hardness); p->m4.masterGain = FL(0.2) + (*p->hardness * FL(1.6)); /* Set Strike position */ temp = (p->strikePosition = *p->spos) * PI_F; BiQuad_setGain(p->m4.filters[0], FL(0.025) * SIN(temp)); BiQuad_setGain(p->m4.filters[1], FL(0.015) * SIN(FL(0.1) + (FL(2.01) * temp))); BiQuad_setGain(p->m4.filters[2], FL(0.015) * SIN(FL(3.95) * temp)); /* Strike */ Modal4_strike(csound, m, *p->amplitude * AMP_RSCALE); Modal4_setFreq(csound, m, *p->frequency); p->first = 1; return OK; } int vibraphn(CSOUND *csound, VIBRAPHN *p) { Modal4 *m = &(p->m4); MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT amp = (*p->amplitude)*AMP_RSCALE; /* Normalise */ if (p->kloop>0 && p->h.insdshead->relesing) p->kloop=1; if ((--p->kloop) == 0) { Modal4_damp(csound, m, FL(1.0) - (amp * FL(0.03))); } if (UNLIKELY(p->first)) { Modal4_strike(csound, m, *p->amplitude * AMP_RSCALE); Modal4_setFreq(csound, m, *p->frequency); p->first = 0; } p->m4.v_rate = *p->vibFreq; p->m4.vibrGain =*p->vibAmt; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;nm4); FUNC *ftp; MYFLT temp; /* Expect an impulslything */ if (LIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) != NULL)) p->m4.wave = ftp; else { return csound->InitError(csound, Str("No table for Agogobell strike")); } if (UNLIKELY(make_Modal4(csound, m, p->ivfn, *p->vibAmt, *p->vibFreq)==NOTOK)) return NOTOK; p->m4.w_phaseOffset = FL(0.0); /* p->m4.w_rate = 7.0; */ OnePole_setPole(&p->m4.onepole, FL(0.2)); Modal4_setRatioAndReson(csound, m, 0, FL(1.00), FL(0.999)); /* Set */ Modal4_setRatioAndReson(csound, m, 1, FL(4.08), FL(0.999)); /* our */ Modal4_setRatioAndReson(csound, m, 2, FL(6.669),FL(0.999)); /* resonance */ Modal4_setRatioAndReson(csound, m, 3,-FL(3725.0), FL(0.999)); /* values here */ Modal4_setFiltGain(m, 0, FL(0.06)); Modal4_setFiltGain(m, 1, FL(0.05)); Modal4_setFiltGain(m, 2, FL(0.03)); Modal4_setFiltGain(m, 3, FL(0.02)); p->m4.directGain = FL(0.25); /* vibrGain = 0.2; */ p->m4.w_rate = FL(3.0) + (FL(8.0) * *p->hardness); p->m4.masterGain = FL(1.0); /* Set Strike position */ temp = (p->strikePosition = *p->spos) * PI_F; BiQuad_setGain(p->m4.filters[0], FL(0.08) * SIN(FL(0.7) * temp)); BiQuad_setGain(p->m4.filters[1], FL(0.07) * SIN(FL(0.1) + (FL(5.0) * temp))); BiQuad_setGain(p->m4.filters[2], FL(0.04) * SIN(FL(0.2) + (FL(7.0) * temp))); /* Strike */ Modal4_strike(csound, m, *p->amplitude*AMP_RSCALE); Modal4_setFreq(csound, m, *p->frequency); return OK; } int agogobel(CSOUND *csound, VIBRAPHN *p) { Modal4 *m = &(p->m4); MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; p->m4.v_rate = *p->vibFreq; p->m4.vibrGain =*p->vibAmt; if (UNLIKELY(p->first)) { Modal4_strike(csound, m, *p->amplitude * AMP_RSCALE); Modal4_setFreq(csound, m, *p->frequency); p->first = 0; } if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;nmasterGain = aGain) #define Modal4_setDirectGain(m,aGain) (m->directGain = aGain) #define Modal4_setFiltGain(m,whichOne,gain) \ (BiQuad_setGain(m->filters[whichOne], gain)) static void Modal4_strike(CSOUND *, Modal4 *m, MYFLT amplitude); static void Modal4_damp(CSOUND *, Modal4 *m, MYFLT amplitude); static MYFLT Modal4_tick(Modal4 *); #endif csound-6.10.0/Opcodes/modmatrix.c000066400000000000000000000210201321653344700166400ustar00rootroot00000000000000/* Modmatrix - modulation matrix Copyright (C) 2009 Øyvind Brandtsegg, Thom Johansen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "modmatrix.h" #define INITERROR(x) csound->InitError(csound, Str("modmatrix: " x)) #if defined(__SSE2__) #include #elif defined(__SSE__) #include #endif static int modmatrix_init(CSOUND *csound, MODMATRIX *m) { unsigned int size; m->restab = csound->FTnp2Find(csound, m->ires); m->modtab = csound->FTnp2Find(csound, m->imod); m->parmtab = csound->FTnp2Find(csound, m->iparm); m->mattab = csound->FTnp2Find(csound, m->imatrix); if (UNLIKELY(!m->restab)) return INITERROR("unable to load result table"); if (UNLIKELY(!m->modtab)) return INITERROR("unable to load modulator table"); if (UNLIKELY(!m->parmtab)) return INITERROR("unable to load parameter value table"); if (UNLIKELY(!m->mattab)) return INITERROR("unable to load routing matrix table"); m->nummod = (int)*m->inummod; m->numparm = (int)*m->inumparm; if (UNLIKELY(m->nummod <= 0)) return INITERROR("number of modulators must be a positive integer"); if (UNLIKELY(m->numparm <= 0)) return INITERROR("number of parameters must be a positive integer"); /* Malloc one big chunk instead of several small ones, we need (worst case): MYFLTs - nummod*numparm, nummod, numparm ints - nummod, numparm */ size = (m->nummod*m->numparm + m->nummod + m->numparm)*sizeof(MYFLT) + (m->nummod + m->numparm)*sizeof(int); if (m->aux.auxp == NULL || m->aux.size < size) csound->AuxAlloc(csound, size, &m->aux); if (UNLIKELY(m->aux.auxp == NULL)) return INITERROR("memory allocation error"); m->proc_mat = (MYFLT *)m->aux.auxp; m->mod_map = (int *)(m->proc_mat + m->nummod*m->numparm); m->parm_map = m->mod_map + m->nummod; m->remap_mod = (MYFLT *)(m->parm_map + m->numparm); m->remap_parm = m->remap_mod + m->nummod; m->scanned = 0; m->doscan = 1; return OK; } static void scan_modulation_matrix(CSOUND *csound, MODMATRIX *m) { int i, j, k; MYFLT *matval; /* Use the still unused process matrix for this temporary array */ int *coltab = (int *)m->proc_mat; memset(coltab, 0, m->numparm*sizeof(int)); m->nummod_scanned = m->numparm_scanned = 0; /* Scan for rows containing only zero */ k = 0; for (i = 0; i < m->nummod; ++i) { MYFLT *cur = &m->mattab->ftable[m->numparm*i]; for (j = 0; j < m->numparm; ++j) { if (*cur++ != FL(0.0)) { m->mod_map[k++] = i; ++m->nummod_scanned; coltab[j] = 1; /* Mark column as non-zero */ break; } } } k = 0; /* Scan for columns containing only zero */ for (i = 0; i < m->numparm; ++i) { MYFLT *cur = &m->mattab->ftable[i]; int nonzero = coltab[i]; if (!nonzero) { /* Columns is not previously marked as being non-zero, scan it */ for (j = 0; j < m->nummod; ++j) { if (*cur != FL(0.0)) { nonzero = 1; break; } cur += m->numparm; } } if (nonzero) { m->parm_map[k++] = i; ++m->numparm_scanned; } } /* TODO Possibly check numparm_scanned and nummod_scanned here to see if it even makes sense to process the matrix, set m->scanned accordingly */ /* Rebuild matrix without zero rows and columns */ matval = m->proc_mat; for (i = 0; i < m->nummod_scanned; ++i) { int mod = m->mod_map[i]; MYFLT *row = &m->mattab->ftable[mod*m->numparm]; for (j = 0; j < m->numparm_scanned; ++j) { int parm = m->parm_map[j]; *matval++ = row[parm]; } } m->scanned = 1; m->doscan = 0; } static void process(CSOUND *csound, MODMATRIX *m) { int col = 0, row; MYFLT *src = &m->modtab->ftable[0]; /* Use unrolled SSE based loops if possible. All loading and storing has to be unaligned since Csound has no alignment guarantees on anything, to the best of my knowledge */ #if defined(__SSE__) && !defined(USE_DOUBLE) for (; col < (m->numparm & ~7); col += 8) { __m128 acc1 = _mm_setzero_ps(); __m128 acc2 = _mm_setzero_ps(); float *curmod = &m->mattab->ftable[col]; for (row = 0; row < m->nummod; ++row) { __m128 srcval = _mm_load1_ps(&src[row]); __m128 modcoef1 = _mm_loadu_ps(curmod); __m128 modcoef2 = _mm_loadu_ps(curmod + 4); acc1 = _mm_add_ps(acc1, _mm_mul_ps(srcval, modcoef1)); acc2 = _mm_add_ps(acc2, _mm_mul_ps(srcval, modcoef2)); curmod += m->numparm; } __m128 params1 = _mm_loadu_ps(&m->parmtab->ftable[col]); __m128 params2 = _mm_loadu_ps(&m->parmtab->ftable[col + 4]); _mm_storeu_ps(&m->restab->ftable[col], _mm_add_ps(params1, acc1)); _mm_storeu_ps(&m->restab->ftable[col + 4], _mm_add_ps(params2, acc2)); } #elif defined(__SSE2__) && defined(USE_DOUBLE) for (; col < (m->numparm & ~3); col += 4) { __m128d acc1 = _mm_setzero_pd(); __m128d acc2 = _mm_setzero_pd(); double *curmod = &m->mattab->ftable[col]; for (row = 0; row < m->nummod; ++row) { __m128d srcval = _mm_load1_pd(&src[row]); __m128d modcoef1 = _mm_loadu_pd(curmod); __m128d modcoef2 = _mm_loadu_pd(curmod + 2); acc1 = _mm_add_pd(acc1, _mm_mul_pd(srcval, modcoef1)); acc2 = _mm_add_pd(acc2, _mm_mul_pd(srcval, modcoef2)); curmod += m->numparm; } __m128d params1 = _mm_loadu_pd(&m->parmtab->ftable[col]); __m128d params2 = _mm_loadu_pd(&m->parmtab->ftable[col + 2]); _mm_storeu_pd(&m->restab->ftable[col], _mm_add_pd(params1, acc1)); _mm_storeu_pd(&m->restab->ftable[col + 2], _mm_add_pd(params2, acc2)); } #endif /* This piece of code will either handle the entire matrix in case neither of the above got compiled, or handle the last columns of a matrix with width not divisible by four */ for (; col < m->numparm; ++col) { MYFLT acc = FL(0.0); MYFLT *curmod = &m->mattab->ftable[col]; for (row = 0; row < m->nummod; ++row) { acc += (*curmod)*src[row]; curmod += m->numparm; } m->restab->ftable[col] = m->parmtab->ftable[col] + acc; } } static void process_scanned(CSOUND *csound, MODMATRIX *m) { int col = 0, row; int i; MYFLT *src = &m->remap_mod[0]; for (i = 0; i < m->nummod_scanned; ++i) m->remap_mod[i] = m->modtab->ftable[m->mod_map[i]]; for (i = 0; i < m->numparm_scanned; ++i) m->remap_parm[i] = m->parmtab->ftable[m->parm_map[i]]; memcpy(m->restab->ftable, m->parmtab->ftable, m->numparm*sizeof(MYFLT)); for (; col < m->numparm_scanned; ++col) { MYFLT acc = FL(0.0); MYFLT *curmod = &m->proc_mat[col]; for (row = 0; row < m->nummod_scanned; ++row) { acc += (*curmod)*src[row]; curmod += m->numparm_scanned; } m->restab->ftable[m->parm_map[col]] += acc; } } static int modmatrix(CSOUND *csound, MODMATRIX *m) { /* We wait until the update signal has gone low again before actually preprocessing a matrix */ if (*m->kupdate > FL(0.0) && !m->doscan) { m->doscan = 1; m->scanned = 0; } else if (*m->kupdate == FL(0.0) && m->doscan) { scan_modulation_matrix(csound, m); } if (!m->scanned) process(csound, m); else process_scanned(csound, m); return OK; } static OENTRY modmatrix_localops[] = { { "modmatrix", sizeof(MODMATRIX), TB, 3, "", "iiiiiik", (SUBR)modmatrix_init, (SUBR)modmatrix, (SUBR)NULL } }; LINKAGE_BUILTIN(modmatrix_localops) csound-6.10.0/Opcodes/modmatrix.h000066400000000000000000000025061321653344700166550ustar00rootroot00000000000000/* Partikkel - a granular synthesis module for Csound 5 Copyright (C) 2009 Øyvind Brandtsegg, Thom Johansen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ //#include "csdl.h" #include "interlocks.h" #include "csoundCore.h" typedef struct { OPDS h; MYFLT *ires; MYFLT *imod; MYFLT *iparm; MYFLT *imatrix; MYFLT *inummod; MYFLT *inumparm; MYFLT *kupdate; FUNC *restab, *modtab, *parmtab, *mattab; int nummod, numparm; /* Variables for the preprocessed matrix */ int doscan, scanned; AUXCH aux; MYFLT *proc_mat; int *mod_map, *parm_map; MYFLT *remap_mod, *remap_parm; int nummod_scanned, numparm_scanned; } MODMATRIX; csound-6.10.0/Opcodes/moog1.c000066400000000000000000000250541321653344700156710ustar00rootroot00000000000000/* moog1.c: Copyright (C) 1996, 1997 Perry Cook, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // #include "csdl.h" #include "csoundCore.h" #include "moog1.h" extern void make_TwoZero(TwoZero *); extern void TwoZero_setZeroCoeffs(TwoZero *, MYFLT*); extern MYFLT TwoZero_tick(TwoZero *, MYFLT); /********************************************/ /* Sweepable Formant (2-pole) */ /* Filter Class, by Perry R. Cook, 1995-96 */ /* See books on filters to understand */ /* more about how this works. This drives */ /* to a target at speed set by rate. */ /********************************************/ static void make_FormSwep(FormSwep *p) { p->poleCoeffs[0] = p->poleCoeffs[1] = FL(0.0); p->gain = FL(1.0); p->freq = p->reson = FL(0.0); p->currentGain = FL(1.0); p->currentFreq = p->currentReson = FL(0.0); p->targetGain = FL(1.0); p->targetFreq = p->targetReson = FL(0.0); p->deltaGain = FL(0.0); p->deltaFreq = p->deltaReson = FL(0.0); p->sweepState = FL(0.0); p->sweepRate = FL(0.002); p->dirty = 0; p->outputs[0] = p->outputs[1] = FL(0.0); } /* void FormSwep_setFreqAndReson(FormSwep *p, MYFLT aFreq, MYFLT aReson) */ /* { */ /* p->dirty = 0; */ /* p->reson = p->currentReson = aReson; */ /* p->freq = p->currentFreq = aFreq; */ /* p->poleCoeffs[1] = - (aReson * aReson); */ /* p->poleCoeffs[0] = 2.0*aReson*(MYFLT)cos((double)(twopi*aFreq/esr)); */ /* } */ void FormSwep_setStates(FormSwep *p, MYFLT aFreq, MYFLT aReson, MYFLT aGain) { p->dirty = 0; p->freq = p->targetFreq = p->currentFreq = aFreq; p->reson = p->targetReson = p->currentReson = aReson; p->gain = p->targetGain = p->currentGain = aGain; } void FormSwep_setTargets(FormSwep *p, MYFLT aFreq, MYFLT aReson, MYFLT aGain) { p->dirty = 1; p->targetFreq = aFreq; p->targetReson = aReson; p->targetGain = aGain; p->deltaFreq = aFreq - p->currentFreq; p->deltaReson = aReson - p->currentReson; p->deltaGain = aGain - p->currentGain; p->sweepState = FL(0.0); } MYFLT FormSwep_tick(CSOUND *csound, FormSwep *p, MYFLT sample) /* Perform Filter Operation */ { MYFLT temp; if (p->dirty) { p->sweepState += p->sweepRate; if (p->sweepState>= FL(1.0)) { p->sweepState = FL(1.0); p->dirty = 0; p->currentReson = p->reson = p->targetReson; p->currentFreq = p->freq = p->targetFreq; p->currentGain = p->gain = p->targetGain; } else { p->currentReson = p->reson + (p->deltaReson * p->sweepState); p->currentFreq = p->freq + (p->deltaFreq * p->sweepState); p->currentGain = p->gain + (p->deltaGain * p->sweepState); } p->poleCoeffs[1] = - (p->currentReson * p->currentReson); p->poleCoeffs[0] = FL(2.0) * p->currentReson * COS(csound->tpidsr * p->currentFreq); } temp = p->currentGain * sample; temp += p->poleCoeffs[0] * p->outputs[0]; temp += p->poleCoeffs[1] * p->outputs[1]; p->outputs[1] = p->outputs[0]; p->outputs[0] = temp; return temp; } static MYFLT Samp_tick(Wave *p) { int32 temp, temp1; MYFLT temp_time, alpha; MYFLT lastOutput; p->time += p->rate; /* Update current time */ while (p->time >= p->wave->flen) /* Check for end of sound */ p->time -= p->wave->flen; /* loop back to beginning */ while (p->time < FL(0.0)) /* Check for end of sound */ p->time += p->wave->flen; /* loop back to beginning */ temp_time = p->time; if (p->phase != FL(0.0)) { temp_time += p->phase; /* Add phase offset */ while (temp_time >= p->wave->flen) /* Check for end of sound */ temp_time -= p->wave->flen; /* loop back to beginning */ while (temp_time < FL(0.0)) /* Check for end of sound */ temp_time += p->wave->flen; /* loop back to beginning */ } temp = (int32) temp_time; /* Integer part of time address */ temp1 = temp + 1; if (UNLIKELY(temp1==(int)p->wave->flen)) temp1 = 0; /* Wrap!! */ /* fractional part of time address */ alpha = temp_time - (MYFLT)temp; lastOutput = p->wave->ftable[temp]; /* Do linear interpolation */ /* same as alpha*data[temp+1] + (1-alpha)data[temp] */ lastOutput += (alpha * (p->wave->ftable[temp1] - lastOutput)); /* End of vibrato tick */ return lastOutput; } int Moog1set(CSOUND *csound, MOOG1 *p) { FUNC *ftp; MYFLT tempCoeffs[2] = {FL(0.0),-FL(1.0)}; make_ADSR(&p->adsr); make_OnePole(&p->filter); make_TwoZero(&p->twozeroes[0]); TwoZero_setZeroCoeffs(&p->twozeroes[0], tempCoeffs); make_TwoZero(&p->twozeroes[1]); TwoZero_setZeroCoeffs(&p->twozeroes[1], tempCoeffs); make_FormSwep(&p->filters[0]); make_FormSwep(&p->filters[1]); if (LIKELY((ftp = csound->FTnp2Find(csound, p->iatt)) != NULL)) p->attk.wave = ftp; /* mandpluk */ else return NOTOK; if (LIKELY((ftp = csound->FTnp2Find(csound, p->ifn )) != NULL)) p->loop.wave = ftp; /* impuls20 */ else return NOTOK; if (LIKELY((ftp = csound->FTnp2Find(csound, p->ivfn)) != NULL)) p->vibr.wave = ftp; /* sinewave */ else return NOTOK; p->attk.time = p->attk.phase = FL(0.0); p->loop.time = p->loop.phase = FL(0.0); p->vibr.time = p->vibr.phase = FL(0.0); p->oldfilterQ = p->oldfilterRate = FL(0.0); ADSR_setAllTimes(csound, &p->adsr, FL(0.001), FL(1.5), FL(0.6), FL(0.250)); ADSR_setAll(csound, &p->adsr, FL(0.05), FL(0.00003), FL(0.6), FL(0.0002)); ADSR_keyOn(&p->adsr); return OK; } int Moog1(CSOUND *csound, MOOG1 *p) { MYFLT amp = *p->amp * AMP_RSCALE; /* Normalised */ MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT temp; MYFLT vib = *p->vibAmt; p->baseFreq = *p->frequency; p->attk.rate = p->baseFreq * FL(0.01) * p->attk.wave->flen * csound->onedsr; p->loop.rate = p->baseFreq * p->loop.wave->flen * csound->onedsr; p->attackGain = amp * FL(0.5); p->loopGain = amp; if (*p->filterQ != p->oldfilterQ) { p->oldfilterQ = *p->filterQ; temp = p->oldfilterQ + FL(0.05); FormSwep_setStates(&p->filters[0], FL(2000.0), temp, FL(2.0) * (FL(1.0) - temp)); FormSwep_setStates(&p->filters[1], FL(2000.0), temp, FL(2.0) * (FL(1.0) - temp)); temp = p->oldfilterQ + FL(0.099); FormSwep_setTargets(&p->filters[0], FL(0.0), temp, FL(2.0) * (FL(1.0) - temp)); FormSwep_setTargets(&p->filters[1], FL(0.0), temp, FL(2.0) * (FL(1.0) - temp)); } if (*p->filterRate != p->oldfilterRate) { p->oldfilterRate = *p->filterRate; p->filters[0].sweepRate = p->oldfilterRate * RATE_NORM; p->filters[1].sweepRate = p->oldfilterRate * RATE_NORM; } p->vibr.rate = *p->vibf * p->vibr.wave->flen * csound->onedsr; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; nvibr); p->loop.rate = p->baseFreq * (FL(1.0) + temp) * (MYFLT)(p->loop.wave->flen) * csound->onedsr; } p->attk.time += p->attk.rate; /* Update current time */ #ifdef DEBUG csound->Message(csound, "Attack_time=%f\tAttack_rate=%f\n", p->attk.time, p->attk.rate); #endif temp_time = p->attk.time; if (p->attk.time >= (MYFLT)p->attk.wave->flen) output = FL(0.0); /* One shot */ else { itemp = (int32) temp_time; /* Integer part of time address */ /* fractional part of time address */ alpha = temp_time - (MYFLT)itemp; #ifdef DEBUG csound->Message(csound, "Attack: (%d, %d), alpha=%f\t", itemp, itemp+1, alpha); #endif output = p->attk.wave->ftable[itemp]; /* Do linear interpolation */ /* same as alpha*data[itemp+1] + (1-alpha)data[itemp] */ #ifdef DEBUG csound->Message(csound, "->%f+\n", output); #endif output += (alpha * (p->attk.wave->ftable[itemp+1] - output)); output *= p->attackGain; /* End of attack tick */ } #ifdef DEBUG csound->Message(csound, "After Attack: %f\n", output); #endif output += p->loopGain * Samp_tick(&p->loop); #ifdef DEBUG csound->Message(csound, "Before OnePole: %f\n", output); #endif output = OnePole_tick(&p->filter, output); #ifdef DEBUG csound->Message(csound, "After OnePole: %f\n", output); #endif output *= ADSR_tick(&p->adsr); #ifdef DEBUG csound->Message(csound, "Sampler_tick: %f\n", output); #endif output = TwoZero_tick(&p->twozeroes[0], output); #ifdef DEBUG csound->Message(csound, "TwoZero0_tick: %f\n", output); #endif output = FormSwep_tick(csound, &p->filters[0], output); #ifdef DEBUG csound->Message(csound, "Filters0_tick: %f\n", output); #endif output = TwoZero_tick(&p->twozeroes[1], output); #ifdef DEBUG csound->Message(csound, "TwoZero1_tick: %f\n", output); #endif output = FormSwep_tick(csound, &p->filters[1], output); #ifdef DEBUG csound->Message(csound, "Filter2_tick: %f\n", output); #endif ar[n] = output*AMP_SCALE*FL(8.0); } return OK; } csound-6.10.0/Opcodes/moog1.h000066400000000000000000000067171321653344700157030ustar00rootroot00000000000000/* moog1.h: Copyright (C) 1996, 1997 Perry Cook, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /******************************************/ /* Moog1 Subclass of */ /* Sampling Synthesizer Class */ /* by Perry R. Cook, 1995-96 */ /* */ /* Controls: CONTROL1 = filterQ */ /* CONTROL2 = filterRate */ /* CONTROL3 = vibFreq */ /* MOD_WHEEL= vibAmt */ /******************************************/ #if !defined(__Moog1_h) #define __Moog1_h #include "fm4op.h" /*******************************************/ /* Sweepable Formant (2-pole) */ /* Filter Class, by Perry R. Cook, 1995-96*/ /* See books on filters to understand */ /* more about how this works. Nothing */ /* out of the ordinary in this version. */ /*******************************************/ typedef struct FormSwep { MYFLT gain; MYFLT outputs[2]; MYFLT poleCoeffs[2]; MYFLT freq; MYFLT reson; int dirty; MYFLT targetFreq; MYFLT targetReson; MYFLT targetGain; MYFLT currentFreq; MYFLT currentReson; MYFLT currentGain; MYFLT deltaFreq; MYFLT deltaReson; MYFLT deltaGain; MYFLT sweepState; MYFLT sweepRate; } FormSwep; #define FormSwep_setSweepRate(p,aRate) (p.sweepRate = aRate) #define FormSwep_clear(p) (p.outputs[0]=p.outputs[1]=FL(0.0)) void FormSwep_setTargets(FormSwep *, MYFLT, MYFLT, MYFLT); MYFLT FormSwep_tick(CSOUND *, FormSwep *, MYFLT); typedef struct Wave { FUNC *wave; MYFLT rate; MYFLT time; MYFLT phase; } Wave; /*******************************************/ /* Master Class for Sampling Synthesizer */ /* by Perry R. Cook, 1995-96 */ /* This instrument contains up to 5 */ /* attack waves, 5 looped waves, and */ /* an ADSR envelope. */ /*******************************************/ typedef struct MOOG1 { OPDS h; MYFLT *ar; /* Output */ MYFLT *amp, *frequency; MYFLT *filterQ, *filterRate, *vibf, *vibAmt; MYFLT *iatt, *ifn, *ivfn; ADSR adsr; Wave attk; /* Not looped */ Wave loop; /* Looped */ Wave vibr; /* Looped */ OnePole filter; MYFLT baseFreq; MYFLT attackRatio; MYFLT loopRatio; MYFLT attackGain; MYFLT loopGain; MYFLT oldfilterQ; MYFLT oldfilterRate; FormSwep filters[2]; TwoZero twozeroes[2]; } MOOG1; #endif csound-6.10.0/Opcodes/mp3in.c000066400000000000000000002157121321653344700156770ustar00rootroot00000000000000/* mp3in.c: Copyright (C) 2009 by John ffitch, V Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* mp3in.c */ /* #include "csdl.h" */ #include "csoundCore.h" #include "mp3dec.h" typedef struct { OPDS h; MYFLT *ar[2]; MYFLT *iFileCode; MYFLT *iSkipTime; MYFLT *iSampleFormat; MYFLT *iSkipInit; MYFLT *ibufsize; /* ------------------------------------- */ mp3dec_t mpa; /* For library */ int r; /* Result field */ int initDone; int bufSize; /* in sample frames, power of two */ uint32_t bufused; int64_t pos; /* type should be defined in sysdep.h */ uint8_t *buf; AUXCH auxch; FDCH fdch; } MP3IN; typedef struct { OPDS h; MYFLT *ir; MYFLT *iFileCode; } MP3LEN; int mp3in_cleanup(CSOUND *csound, MP3IN *p) { if (LIKELY(p->mpa != NULL)) mp3dec_uninit(p->mpa); p->mpa = NULL; return OK; } int mp3ininit_(CSOUND *csound, MP3IN *p, int stringname) { char name[1024]; int fd; mp3dec_t mpa = NULL; mpadec_config_t config = { MPADEC_CONFIG_FULL_QUALITY, MPADEC_CONFIG_STEREO, MPADEC_CONFIG_16BIT, MPADEC_CONFIG_LITTLE_ENDIAN, MPADEC_CONFIG_REPLAYGAIN_NONE, TRUE, TRUE, TRUE, 0.0 }; mpadec_info_t mpainfo; int buffersize = (*p->ibufsize<=0.0 ? /*0x1000*/ 8*1152 : (int)*p->ibufsize); /* uint64_t maxsize; */ int r; int skip; if (p->OUTOCOUNT==1) config.mode = MPADEC_CONFIG_MONO; /* if already open, close old file first */ if (p->fdch.fd != NULL) { /* skip initialisation if requested */ if (*(p->iSkipInit) != FL(0.0)) return OK; csound->FDClose(csound, &(p->fdch)); } /* set default format parameters */ /* open file */ p->mpa = mpa = mp3dec_init(); if (UNLIKELY(!mpa)) { return csound->InitError(csound, Str("Not enough memory\n")); } if (UNLIKELY((r = mp3dec_configure(mpa, &config)) != MP3DEC_RETCODE_OK)) { mp3dec_uninit(mpa); p->mpa = NULL; return csound->InitError(csound, "%s", mp3dec_error(r)); } /* FIXME: name can overflow with very long string */ if (stringname==0){ if (csound->ISSTRCOD(*p->iFileCode)) strncpy(name,get_arg_string(csound, *p->iFileCode), 1023); else csound->strarg2name(csound, name, p->iFileCode, "soundin.",0); } else strncpy(name, ((STRINGDAT *)p->iFileCode)->data, 1023); if (UNLIKELY(csound->FileOpen2(csound, &fd, CSFILE_FD_R, name, "rb", "SFDIR;SSDIR", CSFTYPE_OTHER_BINARY, 0) == NULL)) { mp3dec_uninit(mpa); return csound->InitError(csound, Str("mp3in: %s: failed to open file"), name); } /* HOW TO record file handle so that it will be closed at note-off */ /* memset(&(p->fdch), 0, sizeof(FDCH)); */ /* p->fdch.fd = fd; */ /* fdrecord(csound, &(p->fdch)); */ if (UNLIKELY((r = mp3dec_init_file(mpa, fd, 0, FALSE)) != MP3DEC_RETCODE_OK)) { mp3dec_uninit(mpa); return csound->InitError(csound, "%s", mp3dec_error(r)); } if (UNLIKELY((r = mp3dec_get_info(mpa, &mpainfo, MPADEC_INFO_STREAM)) != MP3DEC_RETCODE_OK)) { mp3dec_uninit(mpa); return csound->InitError(csound, "%s", mp3dec_error(r)); } skip = (int)(*p->iSkipTime*CS_ESR); /* maxsize = mpainfo.decoded_sample_size */ /* *mpainfo.decoded_frame_samples */ /* *mpainfo.frames; */ /* csound->Message(csound, "maxsize = %li\n", maxsize); */ /* print file information */ /* if (UNLIKELY(csound->oparms_.msglevel & WARNMSG)) */ { char temp[80]; if (mpainfo.frequency < 16000) strcpy(temp, "MPEG-2.5 "); else if (mpainfo.frequency < 32000) strcpy(temp, "MPEG-2 "); else strcpy(temp, "MPEG-1 "); if (mpainfo.layer == 1) strcat(temp, "Layer I"); else if (mpainfo.layer == 2) strcat(temp, "Layer II"); else strcat(temp, "Layer III"); csound->Warning(csound, "Input: %s, %s, %d kbps, %d Hz (%d:%02d)\n", temp, ((mpainfo.channels > 1) ? "stereo" : "mono"), mpainfo.bitrate, mpainfo.frequency, mpainfo.duration/60, mpainfo.duration%60); } /* check number of channels in file (must equal the number of outargs) */ /* if (UNLIKELY(sfinfo.channels != p->nChannels && */ /* (csound->oparms_.msglevel & WARNMSG) != 0)) { */ /* mp3dec_uninit(mpa); */ /* return csound->InitError(csound, */ /* Str("mp3in: number of output args " */ /* "inconsistent with number of file channels")); */ /* } */ /* skip initialisation if requested */ if (*(p->iSkipInit) != FL(0.0)) return OK; /* set file parameters from header info */ if ((int) (CS_ESR + FL(0.5)) != mpainfo.frequency) { csound->Warning(csound, Str("mp3in: file sample rate (%d) " "!= orchestra sr (%d)\n"), mpainfo.frequency, (int) (CS_ESR + FL(0.5))); } /* initialise buffer */ mp3dec_seek(mpa,0, MP3DEC_SEEK_SAMPLES); p->bufSize = buffersize; if (p->auxch.auxp == NULL || p->auxch.size < (unsigned int)buffersize) csound->AuxAlloc(csound, buffersize, &p->auxch); p->buf = (uint8_t *) p->auxch.auxp; p->bufused = -1; buffersize /= (mpainfo.decoded_sample_size); //printf("===%d \n", skip); //skip = skip - 528; while (skip > 0) { int xx= skip; // printf("%d \n", skip); if (xx > buffersize) xx = buffersize; skip -= xx; r = mp3dec_decode(mpa, p->buf, mpainfo.decoded_sample_size*xx, &p->bufused); // printf("u %d \n", p->bufused); } //if(!skip) //mp3dec_seek(mpa, skip, MP3DEC_SEEK_SAMPLES); p->r = r; if (p->initDone == 0) csound->RegisterDeinitCallback(csound, p, (int (*)(CSOUND*, void*)) mp3in_cleanup); /* done initialisation */ p->initDone = -1; p->pos = 0; return OK; } int mp3ininit(CSOUND *csound, MP3IN *p){ return mp3ininit_(csound,p,0); } int mp3ininit_S(CSOUND *csound, MP3IN *p){ return mp3ininit_(csound,p,1); } int mp3in(CSOUND *csound, MP3IN *p) { int r = p->r; mp3dec_t mpa = p->mpa; uint8_t *buffer = p->buf; MYFLT *al = p->ar[0]; MYFLT *ar = p->ar[1]; int pos = p->pos; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t i, n, nsmps = CS_KSMPS; if (UNLIKELY(offset)) { memset(al, '\0', offset*sizeof(MYFLT)); memset(ar, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&al[nsmps], '\0', early*sizeof(MYFLT)); memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nOUTOCOUNT; i++) { /* stereo */ MYFLT xx; short *bb = (short*)buffer; while (r != MP3DEC_RETCODE_OK || 2*pos >= (int)p->bufused) { r = mp3dec_decode(mpa, buffer, p->bufSize, &p->bufused); if (UNLIKELY(p->bufused == 0)) { memset(&al[n], 0, (nsmps-n)*sizeof(MYFLT)); memset(&ar[n], 0, (nsmps-n)*sizeof(MYFLT)); goto ending; } pos = 0; } xx = ((MYFLT)bb[pos]/(MYFLT)0x7fff) * csound->e0dbfs; if (i==0) al[n] = xx; else ar[n] = xx; pos++; } } ending: p->pos = pos; p->r = r; if (UNLIKELY(r != MP3DEC_RETCODE_OK)) { mp3dec_uninit(mpa); p->mpa = NULL; return NOTOK; } return OK; } int mp3len_(CSOUND *csound, MP3LEN *p, int stringname) { char name[1024]; int fd; mp3dec_t mpa = NULL; mpadec_config_t config = { MPADEC_CONFIG_FULL_QUALITY, MPADEC_CONFIG_STEREO, MPADEC_CONFIG_16BIT, MPADEC_CONFIG_LITTLE_ENDIAN, MPADEC_CONFIG_REPLAYGAIN_NONE, TRUE, TRUE, TRUE, 0.0 }; mpadec_info_t mpainfo; int r; /* open file */ mpa = mp3dec_init(); if (UNLIKELY(!mpa)) { return csound->InitError(csound, Str("Not enough memory\n")); } if (UNLIKELY((r = mp3dec_configure(mpa, &config)) != MP3DEC_RETCODE_OK)) { mp3dec_uninit(mpa); return csound->InitError(csound, "%s", mp3dec_error(r)); } /* FIXME: name can overflow with very long string */ if(stringname==0){ if(csound->ISSTRCOD(*p->iFileCode)) strncpy(name,get_arg_string(csound, *p->iFileCode), 1023); else csound->strarg2name(csound, name, p->iFileCode, "soundin.",0); } else strncpy(name, ((STRINGDAT *)p->iFileCode)->data, 1023); if (UNLIKELY(csound->FileOpen2(csound, &fd, CSFILE_FD_R, name, "rb", "SFDIR;SSDIR", CSFTYPE_OTHER_BINARY, 0) == NULL)) { mp3dec_uninit(mpa); return csound->InitError(csound, Str("mp3in: %s: failed to open file"), name); } if (UNLIKELY((r = mp3dec_init_file(mpa, fd, 0, FALSE)) != MP3DEC_RETCODE_OK)) { mp3dec_uninit(mpa); return csound->InitError(csound, "%s", mp3dec_error(r)); } if (UNLIKELY((r = mp3dec_get_info(mpa, &mpainfo, MPADEC_INFO_STREAM)) != MP3DEC_RETCODE_OK)) { close(fd); mp3dec_uninit(mpa); return csound->InitError(csound, "%s", mp3dec_error(r)); } close(fd); if(!strcmp(csound->GetOpcodeName(&p->h), "mp3len")) *p->ir = (MYFLT)mpainfo.duration; else if(!strcmp(csound->GetOpcodeName(&p->h), "mp3sr")) *p->ir = (MYFLT) mpainfo.frequency; else if(!strcmp(csound->GetOpcodeName(&p->h), "mp3bitrate")) *p->ir = (MYFLT) mpainfo.bitrate; else if(!strcmp(csound->GetOpcodeName(&p->h), "mp3nchnls")) *p->ir = (MYFLT) mpainfo.channels; mp3dec_uninit(mpa); return OK; } int mp3len(CSOUND *csound, MP3LEN *p){ return mp3len_(csound,p,0); } int mp3len_S(CSOUND *csound, MP3LEN *p){ return mp3len_(csound,p,1); } #define MP3_CHNS 2 typedef struct dats{ OPDS h; MYFLT *out1,*out2,*kstamp, *knum, *time,*kpitch, *kamp, *skip, *iN, *idecim, *klock,*kinterp; int cnt, hsize, curframe, N, decim,tscale; double pos; MYFLT accum; AUXCH outframe[MP3_CHNS], win, bwin[MP3_CHNS], fwin[MP3_CHNS], nwin[MP3_CHNS], prev[MP3_CHNS], framecount[MP3_CHNS], fdata[MP3_CHNS], buffer; MYFLT *indataL[2], *indataR[2]; MYFLT *tab[MP3_CHNS]; char curbuf; mp3dec_t mpa; FDCH fdch; MYFLT resamp; double tstamp, incr; int initDone; uint32_t bufused; int finished; char init; CSOUND *csound; // PTHREAD: change //pthread_t t; void* t; int ti; char filling; void *fwdsetup, *invsetup; } DATASPACE; int mp3scale_cleanup(CSOUND *csound, DATASPACE *p) { if (p->mpa != NULL) mp3dec_uninit(p->mpa); return OK; } #define BUFS 32 static void fillbuf(CSOUND *csound, DATASPACE *p, int nsmps); /* file-reading version of temposcal */ static int sinit(CSOUND *csound, DATASPACE *p) { int N = *p->iN, ui; unsigned int i; unsigned int size; int decim = *p->idecim; /*double dtime; struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); dtime = ts.tv_sec + 1e-9*ts.tv_nsec;*/ if (N) { for (i=0; N; i++) { N >>= 1; } N = (int) pow(2.0, i-1); /* could be a shift? */ } else N = 2048; if (decim == 0) decim = 4; p->hsize = N/decim; p->cnt = p->hsize; p->curframe = 0; p->pos = 0; for (i=0; i < MP3_CHNS; i++){ size = (N+2)*sizeof(MYFLT); if (p->fwin[i].auxp == NULL || p->fwin[i].size < size) csound->AuxAlloc(csound, size, &p->fwin[i]); if (p->bwin[i].auxp == NULL || p->bwin[i].size < size) csound->AuxAlloc(csound, size, &p->bwin[i]); if (p->prev[i].auxp == NULL || p->prev[i].size < size) csound->AuxAlloc(csound, size, &p->prev[i]); size = decim*sizeof(int); if (p->framecount[i].auxp == NULL || p->framecount[i].size < size) csound->AuxAlloc(csound, size, &p->framecount[i]); { int k=0; for (k=0; k < decim; k++) { ((int *)(p->framecount[i].auxp))[k] = k*N; } } size = decim*sizeof(MYFLT)*N; if (p->outframe[i].auxp == NULL || p->outframe[i].size < size) csound->AuxAlloc(csound, size, &p->outframe[i]); else memset(p->outframe[i].auxp,0,size); } size = N*sizeof(MYFLT); if (p->win.auxp == NULL || p->win.size < size) csound->AuxAlloc(csound, size, &p->win); { MYFLT x = FL(2.0)*PI_F/N; for (ui=0; ui < N; ui++) ((MYFLT *)p->win.auxp)[ui] = FL(0.5) - FL(0.5)*COS((MYFLT)ui*x); } p->N = N; p->decim = decim; /*clock_gettime(CLOCK_MONOTONIC, &ts); dtime = ts.tv_sec + 1e-9*ts.tv_nsec - dtime; csound->Message(csound, "SINIT time %f ms", dtime*1000);*/ p->fwdsetup = csound->RealFFT2Setup(csound,N,FFT_FWD); p->invsetup = csound->RealFFT2Setup(csound,N,FFT_INV); return OK; } static int sinit3_(CSOUND *csound, DATASPACE *p) { unsigned int size; char *name; // open file int fd; int r; mp3dec_t mpa = NULL; mpadec_config_t config = { MPADEC_CONFIG_FULL_QUALITY, MPADEC_CONFIG_STEREO, MPADEC_CONFIG_16BIT, MPADEC_CONFIG_LITTLE_ENDIAN, MPADEC_CONFIG_REPLAYGAIN_NONE, TRUE, TRUE, TRUE, 0.0 }; mpadec_info_t mpainfo; /*double dtime; struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); dtime = ts.tv_sec + 1e-9*ts.tv_nsec;*/ name = ((STRINGDAT *)p->knum)->data; p->mpa = mpa = mp3dec_init(); if (UNLIKELY(!mpa)) { return csound->InitError(csound, Str("Not enough memory\n")); } if (UNLIKELY((r = mp3dec_configure(mpa, &config)) != MP3DEC_RETCODE_OK)) { mp3dec_uninit(mpa); p->mpa = NULL; return csound->InitError(csound, "%s", mp3dec_error(r)); } if (UNLIKELY(csound->FileOpen2(csound, &fd, CSFILE_FD_R, name, "rb", "SFDIR;SSDIR", CSFTYPE_OTHER_BINARY, 0) == NULL)) { mp3dec_uninit(mpa); return csound->InitError(csound, Str("mp3scale: %s: failed to open file"), name); }// else // csound->Message(csound, Str("mp3scale: open %s \n"), name); if (UNLIKELY((r = mp3dec_init_file(mpa, fd, 0, FALSE)) != MP3DEC_RETCODE_OK)) { mp3dec_uninit(mpa); return csound->InitError(csound, "%s", mp3dec_error(r)); } // else // csound->Message(csound, Str("mp3scale: init %s \n"), name); if (UNLIKELY((r = mp3dec_get_info(mpa, &mpainfo, MPADEC_INFO_STREAM)) != MP3DEC_RETCODE_OK)) { mp3dec_uninit(mpa); return csound->InitError(csound, "%s", mp3dec_error(r)); } /* { char temp[80]; if (mpainfo.frequency < 16000) strcpy(temp, "MPEG-2.5 "); else if (mpainfo.frequency < 32000) strcpy(temp, "MPEG-2 "); else strcpy(temp, "MPEG-1 "); if (mpainfo.layer == 1) strcat(temp, "Layer I"); else if (mpainfo.layer == 2) strcat(temp, "Layer II"); else strcat(temp, "Layer III"); csound->Warning(csound, "Input: %s, %s, %d kbps, %d Hz (%d:%02d)\n", temp, ((mpainfo.channels > 1) ? "stereo" : "mono"), mpainfo.bitrate, mpainfo.frequency, mpainfo.duration/60, mpainfo.duration%60); }*/ if(mpainfo.frequency != CS_ESR) p->resamp = mpainfo.frequency/CS_ESR; else p->resamp = 1; /*clock_gettime(CLOCK_MONOTONIC, &ts); dtime = ts.tv_sec + 1e-9*ts.tv_nsec - dtime; csound->Message(csound, "MP3 INIT time %f ms", dtime*1000); clock_gettime(CLOCK_MONOTONIC, &ts); dtime = ts.tv_sec + 1e-9*ts.tv_nsec;*/ { char *ps; sinit(csound, p); size = p->N*sizeof(MYFLT)*BUFS; if (p->fdata[0].auxp == NULL || p->fdata[0].size < size) csound->AuxAlloc(csound, size, &p->fdata[0]); ps = (char *) p->fdata[0].auxp; p->indataL[0] = (MYFLT*) ps; p->indataL[1] = (MYFLT*) (ps + size/2); if (p->fdata[1].auxp == NULL || p->fdata[1].size < size) csound->AuxAlloc(csound, size, &p->fdata[1]); ps = (char *) p->fdata[1].auxp; p->indataR[0] = (MYFLT*) ps; p->indataR[1] = (MYFLT*) (ps + size/2); if (p->buffer.auxp == NULL || p->buffer.size < size) csound->AuxAlloc(csound, size, &p->buffer); } /* memset(&(p->fdch), 0, sizeof(FDCH)); p->fdch.fd = fd; fdrecord(csound, &(p->fdch)); */ printf("fftsize = %d \n", p->N); int buffersize = size; buffersize /= mpainfo.decoded_sample_size; int skip = (int)(*p->skip*CS_ESR)*p->resamp; p->bufused = -1; /*while (skip > 0) { int xx= skip; if (xx > buffersize) xx = buffersize; skip -= xx; r = mp3dec_decode(mpa, p->buffer.auxp, mpainfo.decoded_sample_size*xx, &p->bufused); }*/ mp3dec_seek(mpa, skip, MP3DEC_SEEK_SAMPLES); // fill buffers p->curbuf = 0; fillbuf(csound,p,p->N*BUFS/2); p->pos = p->hsize; p->tscale = 0; p->accum = 0; p->tab[0] = (MYFLT *) p->fdata[0].auxp; p->tab[1] = (MYFLT *) p->fdata[1].auxp; p->tstamp = 0; if(p->initDone == -1) csound->RegisterDeinitCallback(csound, p, (int (*)(CSOUND*, void*)) mp3scale_cleanup); p->initDone = -1; p->finished = 0; p->init = 1; /*clock_gettime(CLOCK_MONOTONIC, &ts); dtime = ts.tv_sec + 1e-9*ts.tv_nsec - dtime; csound->Message(csound, "MP3SCAL INIT time %f ms", dtime*1000);*/ return OK; } #ifdef ANDROID void *init_thread(void *p){ DATASPACE *pp = (DATASPACE *) p; sinit3_(pp->csound,pp); return NULL; } static int sinit3(CSOUND *csound, DATASPACE *p){ p->csound = csound; p->init = 0; p->ti = 0; csound->Message(csound, "thread start\n"); pthread_create(&p->t, NULL, init_thread, p); return OK; } #else static int sinit3(CSOUND *csound, DATASPACE *p) { return sinit3_(csound,p); } #endif /* this will read a buffer full of samples from disk position offset samps from the last call to fillbuf */ void fillbuf(CSOUND *csound, DATASPACE *p, int nsmps){ short *buffer= (short *) p->buffer.auxp; MYFLT *data[2]; data[0] = p->indataL[(int)p->curbuf]; data[1] = p->indataR[(int)p->curbuf]; int i,j, end; memset(data[0],0,nsmps*sizeof(MYFLT)); memset(data[1],0,nsmps*sizeof(MYFLT)); if(!p->finished){ mp3dec_decode(p->mpa,p->buffer.auxp, MP3_CHNS*nsmps*sizeof(short), &p->bufused); if(p->bufused == 0) p->finished = 1; else { end = p->bufused/sizeof(short); for(i=j=0; i < end/2; i++, j+=2){ data[0][i] = buffer[j]/32768.0; data[1][i] = buffer[j+1]/32768.0; } } } p->curbuf = p->curbuf ? 0 : 1; } static int sprocess3(CSOUND *csound, DATASPACE *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; MYFLT pitch = *p->kpitch*p->resamp, time = *p->time*p->resamp, lock = *p->klock; MYFLT *out; MYFLT *tab, **table,frac; int N = p->N, hsize = p->hsize, cnt = p->cnt; int nsmps = CS_KSMPS, n; int size = p->fdata[0].size/sizeof(MYFLT), post, i, j; double pos, spos = p->pos; MYFLT *fwin, *bwin; MYFLT in, *prev; MYFLT *win = (MYFLT *) p->win.auxp, *outframe; MYFLT ph_real, ph_im, tmp_real, tmp_im, div; int *framecnt, curframe = p->curframe; int decim = p->decim; int interp = *p->kinterp; double tstamp = p->tstamp, incrt = p->incr; double amp = *p->kamp*csound->Get0dBFS(csound)*(8./decim)/3.; int curbuf = p->curbuf; AUXCH *mfwin = p->fwin, *mbwin = p->bwin, *mprev = p->prev, *moutframe = p->outframe, *mframecount = p->framecount; MYFLT hsizepitch = hsize*pitch; int nbytes = p->N*sizeof(MYFLT); if(time < 0) time = 0.0; table = p->tab; if(!p->init){ for (j=0; j < MP3_CHNS; j++) { out = j == 0 ? p->out1 : p->out2; memset(out, '\0', nsmps*sizeof(MYFLT)); } p->ti++; *p->kstamp = 0; return OK; } if(*p->kstamp == 0) csound->Message(csound, "waited %d cycles\n", p->ti); if (UNLIKELY(early)) { nsmps -= early; for (j=0; j < MP3_CHNS; j++) { out = j == 0 ? p->out1 : p->out2; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } } if (UNLIKELY(offset)) { for (j=0; j < MP3_CHNS; j++) { out = j == 0 ? p->out1 : p->out2; memset(out, '\0', offset*sizeof(MYFLT)); } } for (n=offset; n < nsmps; n++) { if (cnt == hsize){ spos += hsize*time; incrt = time*nsmps; while(spos >= size) { spos -= size; } while(spos < 0){ spos += size; } if (spos > size/2+hsize && curbuf == 0) { fillbuf(csound,p,size/2); } else if (spos < size/2+hsize && curbuf == 1){ fillbuf(csound,p,size/2); } for (j = 0; j < MP3_CHNS; j++) { bwin = (MYFLT *) mbwin[j].auxp; fwin = (MYFLT *) mfwin[j].auxp; prev = (MYFLT *) mprev[j].auxp; framecnt = (int *) mframecount[j].auxp; outframe= (MYFLT *) moutframe[j].auxp; tab = table[j]; if(pitch != 1) { pos = spos; for (i=0; i < N; i++) { post = (int) pos; frac = pos - post; if(post < 0) post += size; if(post >= size) post -= size; if(post+1 < size && interp){ in = tab[post] + frac*(tab[post+1] - tab[post]); } else in = tab[post]; fwin[i] = in * win[i]; post -= hsizepitch; if(post < 0) post += size; if(post >= size) post -= size; if(post+1 < size && interp){ in = tab[post] + frac*(tab[post+1] - tab[post]); } else in = tab[post]; bwin[i] = in * win[i]; pos += pitch; } } else { post = (int) spos; int end = post+N; if(end <= size) memcpy(fwin,&tab[post],nbytes); else { int endbytes; endbytes = (end - size)*sizeof(MYFLT); end = N - (end - size); memcpy(fwin,&tab[post],nbytes-endbytes); memcpy(&fwin[end],tab,endbytes); } post -= hsize; if(post < 0) post += size; end = post+N; if(end < size) memcpy(bwin,&tab[post],nbytes); else { int endbytes; endbytes = (end - size)*sizeof(MYFLT); end = N - (end - size); memcpy(bwin,&tab[post],nbytes-endbytes); memcpy(&bwin[end],tab,endbytes); } for(i=0; i < N; i++) { bwin[i] *= win[i]; fwin[i] *= win[i]; } } csound->RealFFT2(csound, p->fwdsetup, bwin); bwin[N] = bwin[1]; bwin[N+1] = FL(0.0); csound->RealFFT2(csound, p->fwdsetup, fwin); fwin[N] = fwin[1]; fwin[N+1] = FL(0.0); for (i=0; i < N + 2; i+=2) { div = FL(1.0)/(HYPOT(prev[i], prev[i+1]) + 1.0e-20); ph_real = prev[i]*div; ph_im = prev[i+1]*div; tmp_real = bwin[i] * ph_real + bwin[i+1] * ph_im; tmp_im = bwin[i] * ph_im - bwin[i+1] * ph_real; bwin[i] = tmp_real; bwin[i+1] = tmp_im; } for (i=0; i < N + 2; i+=2) { if (lock) { if (i > 0) { if (i < N) { tmp_real = bwin[i] + bwin[i-2] + bwin[i+2]; tmp_im = bwin[i+1] + bwin[i-1] + bwin[i+3]; } else { tmp_real = bwin[i] + bwin[i-2]; tmp_im = FL(0.0); } } else { tmp_real = bwin[i] + bwin[i+2]; tmp_im = FL(0.0); } } else { tmp_real = bwin[i]; tmp_im = bwin[i+1]; } tmp_real += 1e-15; div = FL(1.0)/(HYPOT(tmp_real, tmp_im)); ph_real = tmp_real*div; ph_im = tmp_im*div; tmp_real = fwin[i] * ph_real - fwin[i+1] * ph_im; tmp_im = fwin[i] * ph_im + fwin[i+1] * ph_real; prev[i] = fwin[i] = tmp_real; prev[i+1] = fwin[i+1] = tmp_im; } fwin[1] = fwin[N]; csound->RealFFT2(csound, p->invsetup, fwin); framecnt[curframe] = curframe*N; for (i=0;iout1 : p->out2; framecnt = (int *) p->framecount[j].auxp; outframe = (MYFLT *) p->outframe[j].auxp; out[n] = (MYFLT) 0; for (i = 0; i < decim; i++) { out[n] += outframe[framecnt[i]]; framecnt[i]++; } out[n] *= amp; } cnt++; } p->cnt = cnt; p->curframe = curframe; p->pos = spos; p->tstamp = tstamp + incrt; *p->kstamp = (*p->skip + p->tstamp/csound->GetSr(csound))/p->resamp; p->incr = incrt; return OK; } #ifdef ANDROID typedef struct _mp3scal2_ { int cnt, hsize, curframe, N, decim,tscale; double pos; MYFLT accum; AUXCH outframe[MP3_CHNS], win, bwin[MP3_CHNS], fwin[MP3_CHNS], nwin[MP3_CHNS], prev[MP3_CHNS], framecount[MP3_CHNS], fdata[MP3_CHNS], buffer; MYFLT *indataL[8], *indataR[8]; MYFLT *tab[MP3_CHNS]; char curbuf; mp3dec_t mpa; FDCH fdch; MYFLT resamp; double tstamp, incr; int initDone; uint32_t bufused; int finished; char init; CSOUND *csound; pthread_t t,t1; int ti; MYFLT ilen; MYFLT skip; char playing; int nsmps; char filling; int async; int error; MYFLT orsr; char lock; unsigned long end; } MP3SCAL2; typedef struct _loader { OPDS h; STRINGDAT *res; STRINGDAT *name; MYFLT *skip, *iN, *idecim, *bfs; MP3SCAL2 p; } LOADER; void *buffiller(void *pp){ MP3SCAL2 *p = (MP3SCAL2 *) pp; int nsmps = p->nsmps; short *buffer= (short *) p->buffer.auxp; MYFLT *data[2]; p->lock = 1; if(p->mpa != NULL) { data[0] = p->indataL[(int)p->curbuf]; data[1] = p->indataR[(int)p->curbuf]; int i,j, end; memset(data[0],0,nsmps*sizeof(MYFLT)); memset(data[1],0,nsmps*sizeof(MYFLT)); if(!p->finished){ mp3dec_decode(p->mpa,p->buffer.auxp, MP3_CHNS*nsmps*sizeof(short), &p->bufused); if(p->bufused == 0) p->finished = 1; else { end = (p->bufused/sizeof(short))/MP3_CHNS; for(i=j=0; i < end; i++, j+=2){ data[0][i] = buffer[j]/32768.0; data[1][i] = buffer[j+1]/32768.0; } } } p->curbuf = (p->curbuf+1)%8; } p->lock = 0; return NULL; } void fillbuf2(CSOUND *csound, MP3SCAL2 *p, int nsmps){ p->nsmps = nsmps; if(p->async) { int policy; struct sched_param param; pthread_create(&(p->t1), NULL, buffiller, p); pthread_getschedparam(p->t1, &policy, ¶m); param.sched_priority = 1; //policy = SCHED_OTHER; if(pthread_setschedparam(p->t1, policy, ¶m) != 0) csound->Message(csound, "could not set priority \n"); } else buffiller((void *) p); } static int meminit(CSOUND *csound, LOADER *pp) { MP3SCAL2 *p = &(pp->p); int N = *pp->iN, ui; unsigned int i; unsigned int size; int decim = *pp->idecim; p->N = N; p->error = 0; if (N) { for (i=0; N; i++) { N >>= 1; } N = (int) pow(2.0, i-1); } else N = 2048; if (decim == 0) decim = 4; p->hsize = N/decim; p->cnt = p->hsize; p->curframe = 0; p->pos = 0; for (i=0; i < MP3_CHNS; i++){ size = (N+2)*sizeof(MYFLT); if (p->fwin[i].auxp == NULL || p->fwin[i].size < size) csound->AuxAlloc(csound, size, &p->fwin[i]); if (p->bwin[i].auxp == NULL || p->bwin[i].size < size) csound->AuxAlloc(csound, size, &p->bwin[i]); if (p->prev[i].auxp == NULL || p->prev[i].size < size) csound->AuxAlloc(csound, size, &p->prev[i]); size = decim*sizeof(int); if (p->framecount[i].auxp == NULL || p->framecount[i].size < size) csound->AuxAlloc(csound, size, &p->framecount[i]); { int k=0; for (k=0; k < decim; k++) { ((int *)(p->framecount[i].auxp))[k] = k*N; } } size = decim*sizeof(MYFLT)*N; if (p->outframe[i].auxp == NULL || p->outframe[i].size < size) csound->AuxAlloc(csound, size, &p->outframe[i]); else memset(p->outframe[i].auxp,0,size); } size = N*sizeof(MYFLT); if (p->win.auxp == NULL || p->win.size < size) csound->AuxAlloc(csound, size, &p->win); { MYFLT x = FL(2.0)*PI_F/N; for (ui=0; ui < N; ui++) ((MYFLT *)p->win.auxp)[ui] = FL(0.5) - FL(0.5)*COS((MYFLT)ui*x); } p->N = N; p->decim = decim; return OK; } int mp3dec_cleanup(CSOUND *csound, LOADER *p) { while(p->p.lock) usleep(1000); if (p->p.mpa != NULL) mp3dec_uninit(p->p.mpa); p->p.mpa = NULL; return OK; } void decode_seek(CSOUND *csound, mp3dec_t mpa, int skip){ unsigned char buffer[1152*4]; mp3dec_seek(mpa, 0, MP3DEC_SEEK_SAMPLES); while (skip > 0) { mp3dec_decode(mpa,buffer, 1152*4,NULL); skip -= 1152; } } static int filinit(CSOUND *csound, LOADER *pp) { MP3SCAL2 *p = &(pp->p); unsigned int size; char *name; // open file int fd; int r; mp3dec_t mpa = NULL; mpadec_config_t config = { MPADEC_CONFIG_FULL_QUALITY, MPADEC_CONFIG_STEREO, MPADEC_CONFIG_16BIT, MPADEC_CONFIG_LITTLE_ENDIAN, MPADEC_CONFIG_REPLAYGAIN_NONE, TRUE, TRUE, TRUE, 0.0 }; mpadec_info_t mpainfo; int buffsize = 32768; p->init = 0; if(*pp->bfs) buffsize = *pp->bfs*8; name = pp->name->data; if(p->mpa != NULL) mp3dec_uninit(p->mpa); p->mpa = mpa = mp3dec_init(); if (UNLIKELY(!mpa)) { p->error = MPADEC_RETCODE_NOT_ENOUGH_MEMORY; return NOTOK; } if (UNLIKELY((r = mp3dec_configure(mpa, &config)) != MP3DEC_RETCODE_OK)) { mp3dec_uninit(mpa); p->mpa = NULL; p->error = r; return NOTOK; } if (UNLIKELY(csound->FileOpen2(csound, &fd, CSFILE_FD_R, name, "rb", "SFDIR;SSDIR", CSFTYPE_OTHER_BINARY, 0) == NULL)) { mp3dec_uninit(mpa); p->error = -1; return NOTOK; } if (UNLIKELY((r = mp3dec_init_file(mpa, fd, 0, TRUE)) != MP3DEC_RETCODE_OK)) { mp3dec_uninit(mpa); p->error = r; return NOTOK; } if (UNLIKELY((r = mp3dec_get_info(mpa, &mpainfo, MPADEC_INFO_STREAM)) != MP3DEC_RETCODE_OK)) { mp3dec_uninit(mpa); return NOTOK; } p->ilen = (MYFLT) mpainfo.duration; if(mpainfo.frequency != CS_ESR) p->resamp = mpainfo.frequency/CS_ESR; else p->resamp = 1; meminit(csound, pp); size = buffsize*sizeof(MYFLT); if (p->fdata[0].auxp == NULL || p->fdata[0].size < size) csound->AuxAlloc(csound, size, &p->fdata[0]); p->indataL[0] = p->fdata[0].auxp; p->indataL[1] = p->fdata[0].auxp + size/8; p->indataL[2] = p->fdata[0].auxp + size/4; p->indataL[3] = p->fdata[0].auxp + 3*size/8; p->indataL[4] = p->fdata[0].auxp + size/2; p->indataL[5] = p->fdata[0].auxp + 5*size/8; p->indataL[6] = p->fdata[0].auxp + 3*size/4; p->indataL[7] = p->fdata[0].auxp + 7*size/8; memset(p->indataL[7], 0, size/8); if (p->fdata[1].auxp == NULL || p->fdata[1].size < size) csound->AuxAlloc(csound, size, &p->fdata[1]); p->indataR[0] = p->fdata[1].auxp; p->indataR[1] = p->fdata[1].auxp + size/8; p->indataR[2] = p->fdata[1].auxp + size/4; p->indataR[3] = p->fdata[1].auxp + 3*size/8; p->indataR[4] = p->fdata[1].auxp + size/2; p->indataR[5] = p->fdata[1].auxp + 5*size/8; p->indataR[6] = p->fdata[1].auxp + 3*size/4; p->indataR[7] = p->fdata[1].auxp + 7*size/8; memset(p->indataR[7], 0, size/8); size = buffsize*sizeof(short)/4; if (p->buffer.auxp == NULL || p->buffer.size < size) csound->AuxAlloc(csound, size, &p->buffer); /*double dtime; struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); dtime = ts.tv_sec + 1e-9*ts.tv_nsec; */ int skip = (int)(*pp->skip*mpainfo.frequency); p->bufused = -1; /* mp3_seek operates on multiples of 1152 frames */ int frmsiz = mpainfo.decoded_frame_samples; if(skip > 0) { int ftbr = skip/frmsiz; int skips = ftbr*frmsiz; MYFLT fsize = (FL(125.0)*mpainfo.bitrate*frmsiz)/mpainfo.frequency; if(fsize - (int) fsize > FL(0.0)){ char dat[4]; int byts, pad, i; mp3dec_seek(mpa, 0, MP3DEC_SEEK_SAMPLES); for(i=0; i < ftbr; i++){ byts = read(fd,dat,4); pad = dat[2] & 0x02 ? 1 : 0; lseek(fd,(int)fsize + pad - 4, SEEK_CUR); //printf("skip %d pad %d \n", i, pad); } } else mp3dec_seek(mpa, skips, MP3DEC_SEEK_SAMPLES); skip = skip - skips; } else mp3dec_seek(mpa, 0, MP3DEC_SEEK_SAMPLES); /*clock_gettime(CLOCK_MONOTONIC, &ts); dtime = ts.tv_sec + 1e-9*ts.tv_nsec - dtime; csound->Message(csound, "skip time %f \n", dtime);*/ // fill buffers p->orsr = mpainfo.frequency; p->curbuf = 0; p->finished = 0; p->nsmps = buffsize/8; buffiller((void *)p); buffiller((void *)p); buffiller((void *)p); buffiller((void *)p); buffiller((void *)p); buffiller((void *)p); buffiller((void *)p); buffiller((void *)p); p->pos = skip*csound->GetSr(csound)/p->orsr; p->tscale = 0; p->accum = 0; p->tab[0] = (MYFLT *) p->fdata[0].auxp; p->tab[1] = (MYFLT *) p->fdata[1].auxp; p->tstamp = 0; p->finished = 0; p->skip = *pp->skip; p->filling = 0; p->init = 1; return OK; } void *loader_thread(void *p){ LOADER *pp = (LOADER *) p; if(filinit(pp->p.csound,pp) == NOTOK) { if(pp->p.error > 0) pp->p.csound->Message(pp->p.csound, "mp3scal_load error: %s \n", mp3dec_error(pp->p.error)); else pp->p.csound->Message(pp->p.csound, "mp3scal_load error:" "could not open %s \n", pp->name->data); } return NULL; } static int loader_init(CSOUND *csound, LOADER *pp){ MP3SCAL2 *p = &(pp->p); p->csound = csound; p->init = 0; p->ti = 0; if(p->playing == 0){ if(pthread_create(&(pp->p.t), NULL, loader_thread, pp) != 0) csound->Message(csound, "failed to start thread \n"); struct sched_param param; int policy; pthread_getschedparam((pp->p.t), &policy, ¶m); param.sched_priority = 0; policy = SCHED_OTHER; if(pthread_setschedparam((pp->p.t), policy, ¶m) != 0) csound->Message(csound, "could not set priority \n"); } else return csound->InitError(csound, "cannot load: player still active\n"); pp->res->data = (char *) p; pp->res->size = sizeof(MP3SCAL2); // if(p->initDone == 0) //csound->RegisterDeinitCallback(csound, pp, // (int (*)(CSOUND*, void*)) mp3dec_cleanup); //p->initDone = 1; return OK; } typedef struct _check { OPDS h; MYFLT *res; STRINGDAT *pp; MP3SCAL2 *p; } CHECK; static int check_init(CSOUND *csound, CHECK *p){ if(p->pp->data != NULL && p->pp->size != sizeof(MP3SCAL2)) { p->p = (MP3SCAL2 *) p->pp->data; } else return csound->InitError(csound, "invalid handle \n"); return OK; } static int check_play(CSOUND *csound, CHECK *p){ *p->res = p->p->init; return OK; } #ifdef HAVE_NEON #include #endif typedef struct _player { OPDS h; MYFLT *out1, *out2, *kstamp, *ilen; STRINGDAT *pp; MYFLT *time, *kpitch, *kamp, *klock, *kinterp, *async; MP3SCAL2 *p; char start_flag; #ifdef HAVE_NEON PFFFT_Setup *setup; float *bw,*fw; #else void *fwdsetup, *invsetup; #endif } PLAYER; int mp3dec_cleanup_player(CSOUND *csound, PLAYER *p) { while(p->p->lock) usleep(1000); pthread_join(p->p->t1, NULL); if (p->p->mpa != NULL) mp3dec_uninit(p->p->mpa); p->p->mpa = NULL; #ifdef HAVE_NEON pffft_destroy_setup(p->setup); pffft_aligned_free(p->bw); pffft_aligned_free(p->fw); #endif return OK; } static int player_init(CSOUND *csound, PLAYER *p){ if(p->pp->data != NULL && p->pp->size != sizeof(MP3SCAL2)) { p->p = (MP3SCAL2 *) p->pp->data; } else return csound->InitError(csound, "invalid handle \n"); *p->ilen = p->p->ilen; p->p->async = *p->async; if(p->p->initDone == 0) csound->RegisterDeinitCallback(csound, p, (int (*)(CSOUND*, void*)) mp3dec_cleanup_player); p->p->initDone = 1; int policy; struct sched_param param; pthread_getschedparam(pthread_self(), &policy, ¶m); /*if(policy == SCHED_OTHER) csound->Message(csound, "POLICY: SCHED_OTHER"); struct sched_param param; pthread_getschedparam(pthread_self(), &policy, ¶m); if(policy == SCHED_OTHER) csound->Message(csound, "POLICY: SCHED_OTHER"); else if(policy == SCHED_FIFO) csound->Message(csound, "POLICY: SCHED_FIFO, %d", param.sched_priority);*/ #ifdef HAVE_NEON while(!p->p->N) usleep(1000); p->setup = pffft_new_setup(p->p->N,PFFFT_REAL); p->bw = pffft_aligned_malloc(p->p->N*sizeof(float)); p->fw = pffft_aligned_malloc(p->p->N*sizeof(float)); #else while(!p->p->N) usleep(1000); p->fwdsetup = csound->RealFFT2Setup(csound,p->p->N,FFT_FWD); p->invsetup = csound->RealFFT2Setup(csound,p->p->N,FFT_INV); #endif p->start_flag = 1; return OK; } #include #ifdef HAVE_NEON #include static inline void cmplx_multiply_scal(MYFLT *ans_r, MYFLT *ans_i, MYFLT *in1, MYFLT *in2, MYFLT div, bool neg){ float32x4_t op1, op2, ans; float32x2_t tmp1, tmp2; float32_t vans[4]; tmp1 = vld1_f32(in1); tmp2 = vld1_f32(in2); op1 = vcombine_f32(tmp1,tmp1); op2 = vcombine_f32(tmp2,vrev64_f32(tmp2)); /* ac - bd + i(ad + bc) */ ans = vmulq_n_f32(op2,div); op2 = vmulq_f32(op1,ans); vst1q_f32(vans, op2); *ans_r = vans[0] - (neg ? -vans[1] : vans[1]); *ans_i = vans[2] + (neg ? -vans[3] : vans[3]); } static inline MYFLT invsqrt(MYFLT x) { long i; float x2 = x*0.5f; i = * (long *) &x; i = 0x5f3759df - (i >> 1); x = *(float *) &i; x = x*(1.5f - (x2*x*x)); return x; } static inline MYFLT inv_mag_(MYFLT *a){ float32x2_t ans, op; float32_t vans[2]; op = vld1_f32(a); ans = vmul_f32(op,op); vst1_f32(vans, ans); return invsqrt(vans[0]+vans[1]); } #else static inline void cmplx_multiply_scal(MYFLT *ans_r, MYFLT *ans_i, MYFLT* in1, MYFLT* in2, MYFLT div, bool neg){ MYFLT r = in2[0] * div, i = in2[1] * div; *ans_r = in1[0]*r - (neg ? -in1[1]*i : in1[1]*i); *ans_i = in1[0]*i + (neg ? -in1[1]*r : in1[1]*r); } #endif static inline MYFLT inv_mag(MYFLT *a){ return FL(1.0)/(sqrt(a[0]*a[0]+a[1]*a[1])+1.0e-15); //return invsqrt(a[0]*a[0]+a[1]*a[1]); } static inline MYFLT inv_mag2(MYFLT *a){ a[0] += 1.0e-15; return FL(1.0)/(sqrt(a[0]*a[0]+a[1]*a[1])); //return invsqrt(a[0]*a[0]+a[1]*a[1]); } #define FTOINT(x) ((int)x) static int player_play(CSOUND *csound, PLAYER *pp) { MP3SCAL2 *p = pp->p; uint32_t offset = pp->h.insdshead->ksmps_offset; uint32_t early = pp->h.insdshead->ksmps_no_end; int decim = p->decim; MYFLT pitch = *pp->kpitch*p->resamp, time = *pp->time*p->resamp, lock = *pp->klock; double amp = *pp->kamp*csound->Get0dBFS(csound)*(8./decim)/3.; int interp = *pp->kinterp; #ifdef __clang__ MYFLT *restrict out; MYFLT *restrict fwin; MYFLT *restrict bwin; MYFLT *restrict prev; MYFLT *restrict win = (MYFLT *) p->win.auxp, *restrict outframe; int *restrict framecnt, curframe = p->curframe; MYFLT *restrict tab, **table,frac; MYFLT *restrict phs; #else MYFLT *out; MYFLT *fwin; MYFLT *bwin; MYFLT *prev; MYFLT *win = (MYFLT *) p->win.auxp, *outframe; int *framecnt, curframe = p->curframe; MYFLT *tab, **table,frac; MYFLT *phs; #endif int N = p->N, hsize = p->hsize, cnt = p->cnt; int nsmps = csound->GetKsmps(csound), n; int size = p->fdata[0].size/sizeof(MYFLT), post, i, j; double pos, spos = p->pos; MYFLT in; MYFLT div; double tstamp = p->tstamp, incrt = p->incr; AUXCH *mfwin = p->fwin, *mbwin = p->bwin, *mprev = p->prev, *moutframe = p->outframe, *mframecount = p->framecount; MYFLT hsizepitch = hsize*pitch; int nbytes = p->N*sizeof(MYFLT); int start_flag = pp->start_flag; #ifdef HAVE_NEON float *restrict bw = pp->bw, *restrict fw = pp->fw; #endif p->playing = 1; if(time < 0) time = 0.0; table = p->tab; if(!p->init){ for (j=0; j < MP3_CHNS; j++) { out = j == 0 ? pp->out1 : pp->out2; memset(out, '\0', nsmps*sizeof(MYFLT)); } csound->Message(csound, "not init \n"); p->ti++; *pp->kstamp = 0; return OK; } else *pp->ilen = p->ilen; if (UNLIKELY(early)) { nsmps -= early; for (j=0; j < MP3_CHNS; j++) { out = j == 0 ? pp->out1 : pp->out2; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } } if (UNLIKELY(offset)) { for (j=0; j < MP3_CHNS; j++) { out = j == 0 ? pp->out1 : pp->out2; memset(out, '\0', offset*sizeof(MYFLT)); } } for (n=offset; n < nsmps; n++) { if (cnt == hsize){ while(spos >= size) { spos -= size; } while(spos < 0){ spos += size; } if (spos > size/8+hsize && p->curbuf == 0 && p->filling == 0) { fillbuf2(csound,p,size/8); p->filling = 1; } else if (spos > size/4+hsize && p->curbuf == 1 && p->filling == 1){ fillbuf2(csound,p,size/8); p->filling = 2; } else if (spos > 3*size/8+hsize && p->curbuf == 2 && p->filling == 2){ fillbuf2(csound,p,size/8); p->filling = 3; } else if (spos > size/2+hsize && p->curbuf == 3 && p->filling == 3){ fillbuf2(csound,p,size/8); p->filling = 4; } else if (spos > 5*size/8+hsize && p->curbuf == 4 && p->filling == 4){ fillbuf2(csound,p,size/8); p->filling = 5; } else if (spos > 3*size/4+hsize && p->curbuf == 5 && p->filling == 5){ fillbuf2(csound,p,size/8); p->filling = 6; } else if (spos > 7*size/8+hsize && p->curbuf == 6 && p->filling == 6){ fillbuf2(csound,p,size/8); p->filling = 7; } else if (spos < size/8+hsize && p->curbuf == 7 && p->filling == 7){ fillbuf2(csound,p,size/8); p->filling = 0; } for (j = 0; j < MP3_CHNS; j++) { bwin = (MYFLT *) mbwin[j].auxp; fwin = (MYFLT *) mfwin[j].auxp; prev = (MYFLT *) mprev[j].auxp; framecnt = (int *) mframecount[j].auxp; outframe= (MYFLT *) moutframe[j].auxp; tab = table[j]; if(pitch != 1) { pos = spos; #ifndef HAVE_NEON for (i=0; i < N; i++) { post = (int) pos; frac = pos - post; if(post < 0) post += size; if(post >= size) post -= size; if(post+1 < size && interp){ in = tab[post] + frac*(tab[post+1] - tab[post]); } else in = tab[post]; #ifdef HAVE_NEON fw[i] = in * win[i]; #else fwin[i] = in * win[i]; #endif post -= hsizepitch; if(post < 0) post += size; if(post >= size) post -= size; if(post+1 < size && interp){ in = tab[post] + frac*(tab[post+1] - tab[post]); } else in = tab[post]; #ifdef HAVE_NEON bw[i] = in * win[i]; #else bwin[i] = in * win[i]; #endif pos += pitch; } #else float32x4_t bsm1,bsm2,ans; float tmpf[5],fracv[4]; float tmpos; int tmposi; for (i=0; i < N; i+=4) { tmpos = pos; if(tmpos < 0) tmpos += size; if(tmpos >= size) tmpos -= size; tmposi = FTOINT(tmpos); tmpf[0] = tab[tmposi]; fracv[0] = tmpos - tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); if(tmposi < size){ tmpf[1] = tab[tmposi]; fracv[1] = tmpos -tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); if(tmposi < size){ tmpf[2] = tab[tmposi]; fracv[2] = tmpos - tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); if(tmposi < size){ tmpf[3] = tab[tmposi]; fracv[3] = tmpos - tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); if(tmposi < size) tmpf[4] = tab[tmposi]; else { tmpos -= size; tmposi = FTOINT(tmpos); tmpf[4] = tab[tmposi]; } } else { tmpos -= size; tmposi = FTOINT(tmpos); tmpf[3] = tab[tmposi]; fracv[3] = tmpos -tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); tmpf[4] = tab[tmposi]; } } else { tmpos -= size; tmposi = FTOINT(tmpos); tmpf[2] = tab[tmposi]; fracv[2] = tmpos - tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); tmpf[3] = tab[tmposi]; fracv[3] = tmpos - tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); tmpf[4] = tab[tmposi]; } } else { tmpos -= size; tmposi = FTOINT(tmpos); tmpf[1] = tab[tmposi]; fracv[1] = tmpos -tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); tmpf[2] = tab[tmposi]; fracv[2] = tmpos - tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); tmpf[3] = tab[tmposi]; fracv[3] = tmpos - tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); tmpf[4] = tab[tmposi]; } bsm1 = vld1q_f32(&tmpf[0]); bsm2 = vld1q_f32(&tmpf[1]); ans = vsubq_f32(bsm2,bsm1); bsm2 = vld1q_f32(fracv); bsm2 = vmulq_f32(ans,bsm2); ans = vaddq_f32(bsm1,bsm2); bsm1 = vld1q_f32(&win[i]); bsm2 = vmulq_f32(ans,bsm1); vst1q_f32(&fw[i],bsm2); tmpos = pos - hsize*pitch; if(tmpos < 0) tmpos += size; if(tmpos >= size) tmpos -= size; if(tmpos < 0) tmpos += size; if(tmpos >= size) tmpos -= size; tmposi = FTOINT(tmpos); tmpf[0] = tab[tmposi]; fracv[0] = tmpos - tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); if(tmposi < size){ tmpf[1] = tab[tmposi]; fracv[1] = tmpos -tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); if(tmposi < size){ tmpf[2] = tab[tmposi]; fracv[2] = tmpos - tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); if(tmposi < size){ tmpf[3] = tab[tmposi]; fracv[3] = tmpos - tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); if(tmposi < size) tmpf[4] = tab[tmposi]; else { tmpos -= size; tmposi = FTOINT(tmpos); tmpf[4] = tab[tmposi]; } } else { tmpos -= size; tmposi = FTOINT(tmpos); tmpf[3] = tab[tmposi]; fracv[3] = tmpos -tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); tmpf[4] = tab[tmposi]; } } else { tmpos -= size; tmposi = FTOINT(tmpos); tmpf[2] = tab[tmposi]; fracv[2] = tmpos - tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); tmpf[3] = tab[tmposi]; fracv[3] = tmpos - tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); tmpf[4] = tab[tmposi]; } } else { tmpos -= size; tmposi = FTOINT(tmpos); tmpf[1] = tab[tmposi]; fracv[1] = tmpos -tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); tmpf[2] = tab[tmposi]; fracv[2] = tmpos - tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); tmpf[3] = tab[tmposi]; fracv[3] = tmpos - tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); tmpf[4] = tab[tmposi]; } bsm1 = vld1q_f32(&tmpf[0]); bsm2 = vld1q_f32(&tmpf[1]); ans = vsubq_f32(bsm2,bsm1); bsm2 = vld1q_f32(fracv); bsm2 = vmulq_f32(ans,bsm2); ans = vaddq_f32(bsm1,bsm2); bsm1 = vld1q_f32(&win[i]); bsm2 = vmulq_f32(ans,bsm1); vst1q_f32(&bw[i],bsm2); pos += pitch*4; } #endif } else { post = (int) spos; int end = post+N; if(end <= size) memcpy(fwin,&tab[post],nbytes); else { int endbytes; endbytes = (end - size)*sizeof(MYFLT); end = N - (end - size); memcpy(fwin,&tab[post],nbytes-endbytes); memcpy(&fwin[end],tab,endbytes); } post -= hsize; if(post < 0) post += size; end = post+N; if(end < size) memcpy(bwin,&tab[post],nbytes); else { int endbytes; endbytes = (end - size)*sizeof(MYFLT); end = N - (end - size); memcpy(bwin,&tab[post],nbytes-endbytes); memcpy(&bwin[end],tab,endbytes); } #ifdef HAVE_NEON for(i=0; i < N; i++) { bw[i] = bwin[i]*win[i]; fw[i] = fwin[i]*win[i]; } #else for(i=0; i < N; i++) { bwin[i] *= win[i]; fwin[i] *= win[i]; } #endif } #ifdef HAVE_NEON pffft_transform_ordered(pp->setup,bw,bw,NULL,PFFFT_FORWARD); pffft_transform_ordered(pp->setup,fw,fw,NULL,PFFFT_FORWARD); memcpy(bwin,bw,N*sizeof(float)); memcpy(fwin,fw,N*sizeof(float)); bwin[N] = bw[1]; fwin[N] = fw[1]; #else csound->RealFFT2(csound, pp->fwdsetup, bwin); csound->RealFFT2(csound, pp->fwdsetup, fwin); #endif bwin[N] = bwin[1]; bwin[N+1] = FL(0.0); fwin[N] = fwin[1]; fwin[N+1] = FL(0.0); if(start_flag){ memcpy(prev, bwin, sizeof(MYFLT)*(N+2)); pp->start_flag = 0; } for (i=0; i < N; i+=2) { div = inv_mag(&prev[i]); cmplx_multiply_scal(&prev[i],&prev[i+1], &bwin[i],&prev[i], div, true); } if (lock) { phs = prev; for(i = 2; i < N; i++) bwin[i] = phs[i]; for(i = 2; i < N; i++) bwin[i] += phs[i-2]; for(i = 2; i < N; i++) bwin[i] += phs[i+2]; bwin[0] = prev[i] + prev[i-2]; bwin[N] = prev[i] + prev[i+2]; } else memcpy(bwin,prev,sizeof(MYFLT)*(N+2)); for (i=0; i < N; i+=2) { div = inv_mag2(&bwin[i]); cmplx_multiply_scal(&prev[i],&prev[i+1], &fwin[i], &bwin[i], div, false); } #ifdef HAVE_NEON for(i=0;isetup,fw,fw,NULL,PFFFT_BACKWARD); #else for(i=0; i < N+2; i++) fwin[i] = prev[i]; fwin[1] = fwin[N]; csound->RealFFT2(csound, pp->invsetup, fwin); #endif framecnt[curframe] = curframe*N; for (i=0;iout1 : pp->out2; framecnt = (int *) p->framecount[j].auxp; outframe = (MYFLT *) p->outframe[j].auxp; out[n] = (MYFLT) 0; for (i = 0; i < decim; i++) { out[n] += outframe[framecnt[i]]; framecnt[i]++; } out[n] *= amp; } cnt++; } p->cnt = cnt; p->curframe = curframe; p->pos = spos; *pp->kstamp = (p->skip + p->tstamp/p->orsr); p->tstamp = tstamp + incrt; p->incr = incrt; p->playing = 0; return OK; } #endif #ifdef ONE_FINE_DAY static int meminit2(CSOUND *csound, LOADER *pp) { MP3SCAL2 *p = &(pp->p); int N = *pp->iN, ui; unsigned int i; unsigned int size; int decim = *pp->idecim; p->N = N; p->error = 0; if (N) { for (i=0; N; i++) { N >>= 1; } N = (int) pow(2.0, i-1); } else N = 2048; if (decim == 0) decim = 4; p->hsize = N/decim; p->cnt = p->hsize; p->curframe = 0; p->pos = 0; for (i=0; i < MP3_CHNS; i++){ size = (N+2)*sizeof(MYFLT); if (p->fwin[i].auxp == NULL || p->fwin[i].size < size) csound->AuxAlloc(csound, size, &p->fwin[i]); if (p->bwin[i].auxp == NULL || p->bwin[i].size < size) csound->AuxAlloc(csound, size, &p->bwin[i]); if (p->prev[i].auxp == NULL || p->prev[i].size < size) csound->AuxAlloc(csound, size, &p->prev[i]); size = decim*sizeof(int); if (p->framecount[i].auxp == NULL || p->framecount[i].size < size) csound->AuxAlloc(csound, size, &p->framecount[i]); { int k=0; for (k=0; k < decim; k++) { ((int *)(p->framecount[i].auxp))[k] = k*N; } } size = decim*sizeof(MYFLT)*N; if (p->outframe[i].auxp == NULL || p->outframe[i].size < size) csound->AuxAlloc(csound, size, &p->outframe[i]); else memset(p->outframe[i].auxp,0,size); } size = N*sizeof(MYFLT); if (p->win.auxp == NULL || p->win.size < size) csound->AuxAlloc(csound, size, &p->win); { MYFLT x = FL(2.0)*PI_F/N; for (ui=0; ui < N; ui++) ((MYFLT *)p->win.auxp)[ui] = FL(0.5) - FL(0.5)*COS((MYFLT)ui*x); } p->N = N; p->decim = decim; return OK; } static int filinit2(CSOUND *csound, LOADER *pp) { MP3SCAL2 *p = &(pp->p); unsigned int size; char *name; // open file int fd; int r; mp3dec_t mpa = NULL; mpadec_config_t config = { MPADEC_CONFIG_FULL_QUALITY, MPADEC_CONFIG_STEREO, MPADEC_CONFIG_16BIT, MPADEC_CONFIG_LITTLE_ENDIAN, MPADEC_CONFIG_REPLAYGAIN_NONE, TRUE, TRUE, TRUE, 0.0 }; mpadec_info_t mpainfo; int buffsize = 32768; if(*pp->bfs) buffsize = *pp->bfs*8; name = pp->name->data; if(p->mpa != NULL) mp3dec_uninit(p->mpa); p->mpa = mpa = mp3dec_init(); if (UNLIKELY(!mpa)) { p->error = MPADEC_RETCODE_NOT_ENOUGH_MEMORY; return NOTOK; } if (UNLIKELY((r = mp3dec_configure(mpa, &config)) != MP3DEC_RETCODE_OK)) { mp3dec_uninit(mpa); p->mpa = NULL; p->error = r; return NOTOK; } if (UNLIKELY(csound->FileOpen2(csound, &fd, CSFILE_FD_R, name, "rb", "SFDIR;SSDIR", CSFTYPE_OTHER_BINARY, 0) == NULL)) { mp3dec_uninit(mpa); p->error = -1; return NOTOK; } if (UNLIKELY((r = mp3dec_init_file(mpa, fd, 0, FALSE)) != MP3DEC_RETCODE_OK)) { mp3dec_uninit(mpa); p->error = r; return NOTOK; } if (UNLIKELY((r = mp3dec_get_info(mpa, &mpainfo, MPADEC_INFO_STREAM)) != MP3DEC_RETCODE_OK)) { mp3dec_uninit(mpa); return NOTOK; } p->ilen = (MYFLT) mpainfo.duration; if(mpainfo.frequency != CS_ESR) p->resamp = mpainfo.frequency/CS_ESR; else p->resamp = 1; meminit2(csound, pp); int extrasmps = p->N+p->hsize+528; size = (mpainfo.duration*mpainfo.frequency + extrasmps)*sizeof(MYFLT); if (p->fdata[0].auxp == NULL || p->fdata[0].size < size) csound->AuxAlloc(csound, size, &p->fdata[0]); if (p->fdata[1].auxp == NULL || p->fdata[1].size < size) csound->AuxAlloc(csound, size, &p->fdata[1]); int frmsiz = mpainfo.decoded_frame_samples; int skip = (int)(*pp->skip*mpainfo.frequency); p->bufused = -1; p->orsr = mpainfo.frequency; p->curbuf = 0; p->nsmps = buffsize/8; p->pos = p->hsize + skip - 528; p->tscale = 0; p->accum = 0; p->tab[0] = (MYFLT *) p->fdata[0].auxp; p->tab[1] = (MYFLT *) p->fdata[1].auxp; p->tstamp = 0; p->finished = 0; p->init = 0; p->skip = *pp->skip; p->filling = 7; // fill buffers mp3dec_seek(mpa,0, MP3DEC_SEEK_SAMPLES); int end = mpainfo.duration*mpainfo.frequency; short decbuffer[frmsiz*sizeof(short)*MP3_CHNS]; p->end = end; MYFLT *left = (MYFLT *) p->fdata[0].auxp; MYFLT *right = (MYFLT *) p->fdata[1].auxp; left += p->hsize; right += p->hsize; int i,j,k; uint32_t bufused = 0; for(i=0;i p->pos) { p->init = 1; } } return OK; } void *loader_thread2(void *p){ LOADER *pp = (LOADER *) p; if(filinit2(pp->p.csound,pp) == NOTOK) { if(pp->p.error > 0) pp->p.csound->Message(pp->p.csound, "mp3scal_load error: %s \n", mp3dec_error(pp->p.error)); else pp->p.csound->Message(pp->p.csound, "mp3scal_load error:" "could not open %s \n", pp->name->data); } return NULL; } static int loader_init2(CSOUND *csound, LOADER *pp){ MP3SCAL2 *p = &(pp->p); p->csound = csound; p->init = 0; p->ti = 0; if(p->playing == 0){ pthread_create(&(pp->p.t), NULL, loader_thread2, pp); struct sched_param param; int policy; pthread_getschedparam((pp->p.t), &policy, ¶m); param.sched_priority = 0; policy = SCHED_OTHER; if(pthread_setschedparam((pp->p.t), policy, ¶m) != 0) csound->Message(csound, "could not set priority \n"); } else return csound->InitError(csound, "cannot load: player still active\n"); pp->res->data = (char *) p; pp->res->size = sizeof(MP3SCAL2); return OK; } static int player_init2(CSOUND *csound, PLAYER *p){ if(p->pp->data != NULL && p->pp->size != sizeof(MP3SCAL2)) { p->p = (MP3SCAL2 *) p->pp->data; } else return csound->InitError(csound, "invalid handle \n"); *p->ilen = p->p->ilen; p->p->async = *p->async; if(p->p->initDone == 0) csound->RegisterDeinitCallback(csound, p, (int (*)(CSOUND*, void*)) mp3dec_cleanup_player); p->p->initDone = 1; #ifdef HAVE_NEON while(!p->p->N) usleep(1000); p->setup = pffft_new_setup(p->p->N,PFFFT_REAL); p->bw = pffft_aligned_malloc(p->p->N*sizeof(float)); p->fw = pffft_aligned_malloc(p->p->N*sizeof(float)); #else while(!p->p->N) usleep(1000); p->fwdsetup = csound->RealFFT2Setup(csound,p->p->N,FFT_FWD); p->invsetup = csound->RealFFT2Setup(csound,p->p->N,FFT_INV); #endif p->start_flag = 1; return OK; } static int player_play2(CSOUND *csound, PLAYER *pp) { MP3SCAL2 *p = pp->p; uint32_t offset = pp->h.insdshead->ksmps_offset; uint32_t early = pp->h.insdshead->ksmps_no_end; int decim = p->decim; MYFLT pitch = *pp->kpitch*p->resamp, time = *pp->time*p->resamp, lock = *pp->klock; double amp = *pp->kamp*csound->Get0dBFS(csound)*(8.0/decim)/3.0; int interp = *pp->kinterp; #ifdef __clang__ MYFLT *restrict out; MYFLT *restrict fwin; MYFLT *restrict bwin; MYFLT *restrict prev; MYFLT *restrict win = (MYFLT *) p->win.auxp, *restrict outframe; int *restrict framecnt, curframe = p->curframe; MYFLT *restrict tab; MYFLT frac; MYFLT *restrict phs; #else MYFLT *out; MYFLT *fwin; MYFLT *bwin; MYFLT *prev; MYFLT *win = (MYFLT *) p->win.auxp, *outframe; int *framecnt, curframe = p->curframe; MYFLT *tab; MYFLT frac; MYFLT *phs; #endif int N = p->N, hsize = p->hsize, cnt = p->cnt; int nsmps = csound->GetKsmps(csound), n; int post, i, j; double pos, spos = p->pos; MYFLT in; MYFLT div; double tstamp = p->tstamp, incrt = p->incr; AUXCH *mfwin = p->fwin, *mbwin = p->bwin, *mprev = p->prev, *moutframe = p->outframe, *mframecount = p->framecount; MYFLT hsizepitch = hsize*pitch; int nbytes = p->N*sizeof(MYFLT); int start_flag = pp->start_flag; #ifdef HAVE_NEON float *restrict bw = pp->bw, *restrict fw = pp->fw; #endif if(spos >= p->end) { for (j=0; j < MP3_CHNS; j++) { out = j == 0 ? pp->out1 : pp->out2; memset(out, '\0', nsmps*sizeof(MYFLT)); } return OK; } p->playing = 1; if(time < 0) time = 0.0; if(!p->init){ for (j=0; j < MP3_CHNS; j++) { out = j == 0 ? pp->out1 : pp->out2; memset(out, '\0', nsmps*sizeof(MYFLT)); } p->ti++; *pp->kstamp = 0; return OK; } else *pp->ilen = p->ilen; if (UNLIKELY(early)) { nsmps -= early; for (j=0; j < MP3_CHNS; j++) { out = j == 0 ? pp->out1 : pp->out2; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } } if (UNLIKELY(offset)) { for (j=0; j < MP3_CHNS; j++) { out = j == 0 ? pp->out1 : pp->out2; memset(out, '\0', offset*sizeof(MYFLT)); } } for (n=offset; n < nsmps; n++) { if(cnt == hsize){ for (j = 0; j < MP3_CHNS; j++) { bwin = (MYFLT *) mbwin[j].auxp; fwin = (MYFLT *) mfwin[j].auxp; prev = (MYFLT *) mprev[j].auxp; framecnt = (int *) mframecount[j].auxp; outframe= (MYFLT *) moutframe[j].auxp; tab = (MYFLT *) p->fdata[j].auxp; if(pitch != 1) { pos = spos; #ifndef HAVE_NEON for (i=0; i < N; i++) { post = (int) pos; frac = pos - post; if(interp){ in = tab[post] + frac*(tab[post+1] - tab[post]); } else in = tab[post]; #ifdef HAVE_NEON fw[i] = in * win[i]; #else fwin[i] = in * win[i]; #endif post -= hsizepitch; if(interp){ in = tab[post] + frac*(tab[post+1] - tab[post]); } else in = tab[post]; #ifdef HAVE_NEON bw[i] = in * win[i]; #else bwin[i] = in * win[i]; #endif pos += pitch; } #else float32x4_t bsm1,bsm2,ans; float tmpf[5],fracv[4]; float tmpos; int tmposi; for (i=0; i < N; i+=4) { tmpos = pos; tmposi = FTOINT(tmpos); tmpf[0] = tab[tmposi]; fracv[0] = tmpos - tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); tmpf[1] = tab[tmposi]; fracv[1] = tmpos -tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); tmpf[2] = tab[tmposi]; fracv[2] = tmpos - tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); tmpf[3] = tab[tmposi]; fracv[3] = tmpos - tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); tmpf[4] = tab[tmposi]; bsm1 = vld1q_f32(&tmpf[0]); bsm2 = vld1q_f32(&tmpf[1]); ans = vsubq_f32(bsm2,bsm1); bsm2 = vld1q_f32(fracv); bsm2 = vmulq_f32(ans,bsm2); ans = vaddq_f32(bsm1,bsm2); bsm1 = vld1q_f32(&win[i]); bsm2 = vmulq_f32(ans,bsm1); vst1q_f32(&fw[i],bsm2); tmpos = pos - hsize*pitch; tmposi = FTOINT(tmpos); tmpf[0] = tab[tmposi]; fracv[0] = tmpos - tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); tmpf[1] = tab[tmposi]; fracv[1] = tmpos -tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); tmpf[2] = tab[tmposi]; fracv[2] = tmpos - tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); tmpf[3] = tab[tmposi]; fracv[3] = tmpos - tmposi; tmpos += pitch; tmposi = FTOINT(tmpos); tmpf[4] = tab[tmposi]; bsm1 = vld1q_f32(&tmpf[0]); bsm2 = vld1q_f32(&tmpf[1]); ans = vsubq_f32(bsm2,bsm1); bsm2 = vld1q_f32(fracv); bsm2 = vmulq_f32(ans,bsm2); ans = vaddq_f32(bsm1,bsm2); bsm1 = vld1q_f32(&win[i]); bsm2 = vmulq_f32(ans,bsm1); vst1q_f32(&bw[i],bsm2); pos += pitch*4; } #endif } else { post = (int) spos; memcpy(fwin,&tab[post],nbytes); post -= hsize; memcpy(bwin,&tab[post],nbytes); #ifdef HAVE_NEON for(i=0; i < N; i++) { bw[i] = bwin[i]*win[i]; fw[i] = fwin[i]*win[i]; } #else for(i=0; i < N; i++) { bwin[i] *= win[i]; fwin[i] *= win[i]; } #endif } // if(time != FL(1.0) || pitch != FL(1.0)){ #ifdef HAVE_NEON pffft_transform_ordered(pp->setup,bw,bw,NULL,PFFFT_FORWARD); pffft_transform_ordered(pp->setup,fw,fw,NULL,PFFFT_FORWARD); memcpy(bwin,bw,N*sizeof(float)); memcpy(fwin,fw,N*sizeof(float)); bwin[N] = bw[1]; fwin[N] = fw[1]; #else csound->RealFFT2(csound, pp->fwdsetup, bwin); csound->RealFFT2(csound, pp->fwdsetup, fwin); #endif bwin[N] = bwin[1]; bwin[N+1] = FL(0.0); fwin[N] = fwin[1]; fwin[N+1] = FL(0.0); if(start_flag){ memcpy(prev, bwin, sizeof(MYFLT)*(N+2)); pp->start_flag = 0; } for (i=0; i < N; i+=2) { div = inv_mag(&prev[i]); cmplx_multiply_scal(&prev[i],&prev[i+1], &bwin[i],&prev[i], div, true); } if (lock) { phs = prev; for(i = 2; i < N; i++) bwin[i] = phs[i]; for(i = 2; i < N; i++) bwin[i] += phs[i-2]; for(i = 2; i < N; i++) bwin[i] += phs[i+2]; bwin[0] = prev[i] + prev[i-2]; bwin[N] = prev[i] + prev[i+2]; } else memcpy(bwin,prev,sizeof(MYFLT)*(N+2)); for (i=0; i < N; i+=2) { div = inv_mag(&bwin[i]); cmplx_multiply_scal(&prev[i],&prev[i+1], &fwin[i], &bwin[i], div, false); } #ifdef HAVE_NEON for(i=0;isetup,fw,fw,NULL,PFFFT_BACKWARD); #else #endif //} else pp->start_flag = 1; framecnt[curframe] = curframe*N; for (i=0;iout1 : pp->out2; framecnt = (int *) p->framecount[j].auxp; outframe = (MYFLT *) p->outframe[j].auxp; out[n] = (MYFLT) 0; for (i = 0; i < decim; i++) { out[n] += outframe[framecnt[i]]; framecnt[i]++; } out[n] *= amp; } cnt++; } p->cnt = cnt; p->curframe = curframe; p->pos = spos; *pp->kstamp = (p->skip + p->tstamp/p->orsr); p->tstamp = tstamp + incrt; p->incr = incrt; p->playing = 0; return OK; } #endif #define S(x) sizeof(x) static OENTRY mp3in_localops[] = { {"mp3in", S(MP3IN), 0, 5, "mm", "Soooo", (SUBR) mp3ininit_S, NULL, (SUBR)mp3in}, {"mp3in.i", S(MP3IN), 0, 5, "mm", "ioooo", (SUBR) mp3ininit, NULL, (SUBR)mp3in}, {"mp3len", S(MP3LEN), 0, 1, "i", "S", (SUBR) mp3len_S, NULL, NULL}, {"mp3len.i", S(MP3LEN), 0, 1, "i", "i", (SUBR) mp3len, NULL, NULL}, {"mp3sr", S(MP3LEN), 0, 1, "i", "S", (SUBR) mp3len_S, NULL, NULL}, {"mp3sr.i", S(MP3LEN), 0, 1, "i", "i", (SUBR) mp3len, NULL, NULL}, {"mp3bitrate", S(MP3LEN), 0, 1, "i", "S", (SUBR) mp3len_S, NULL, NULL}, {"mp3bitrate.i", S(MP3LEN), 0, 1, "i", "i", (SUBR) mp3len, NULL, NULL}, {"mp3nchnls", S(MP3LEN), 0, 1, "i", "S", (SUBR) mp3len_S, NULL, NULL}, {"mp3nchnls.i", S(MP3LEN), 0, 1, "i", "i", (SUBR) mp3len, NULL, NULL}, {"mp3scal", sizeof(DATASPACE), 0, 5, "aak", "SkkkoooPP", (SUBR)sinit3, NULL,(SUBR)sprocess3 }, #ifdef ANDROID {"mp3scal_load", sizeof(LOADER), 0, 1, "i", "Soooo", (SUBR)loader_init, NULL,NULL }, {"mp3scal_play", sizeof(PLAYER), 0, 5, "aaki", "ikkkPPo", (SUBR)player_init, NULL,(SUBR)player_play}, {"mp3scal_check", sizeof(CHECK), 0, 5, "k", "i", (SUBR)check_init, NULL,(SUBR)check_play}, #endif /* {"mp3scal_load2", sizeof(LOADER), 0, 1, "i", "Soooo", (SUBR)loader_init2, NULL,NULL }, {"mp3scal_play2", sizeof(PLAYER), 0, 5, "aaki", "ikkkPPo", (SUBR)player_init2, NULL,(SUBR)player_play2} */ }; LINKAGE_BUILTIN(mp3in_localops) csound-6.10.0/Opcodes/newfils.c000066400000000000000000002053301321653344700163130ustar00rootroot00000000000000/* newfils.c: filter opcodes (c) Victor Lazzarini, 2004 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "stdopcod.h" #include "newfils.h" #include static inline double fast_tanh(double x) { double x2 = x * x; double a = x * (135135.0 + x2 * (17325.0 + x2 * (378.0 + x2))); double b = 135135.0 + x2 * (62370.0 + x2 * (3150.0 + x2 * 28.0)); return a / b; } static double TanH(double x) { /* use the fact that tanh(-x) = - tanh(x) and if x>~4 tanh is approx constant 1 and for small x tanh(x) =~ x So giving a cheap approximation */ int sign = 1; if (x<0) sign=-1, x= -x; if (x>=4.0) { return sign; } if (x<0.5) return x*sign; #ifdef JPFF printf("x=%g\n",x, fast_tanh(x),tanh(x)); #endif return sign*fast_tanh(x); } static int moogladder_init(CSOUND *csound, moogladder *p) { /* int i; */ if (LIKELY(*p->istor == FL(0.0))) { /* for (i = 0; i < 6; i++) */ /* p->delay[i] = 0.0; */ memset(p->delay, '\0', 6*sizeof(double)); /* for (i = 0; i < 3; i++) */ /* p->tanhstg[i] = 0.0; */ memset(p->tanhstg, '\0', 3*sizeof(double)); p->oldfreq = FL(0.0); p->oldres = -FL(1.0); /* ensure calculation on first cycle */ } return OK; } static int moogladder_process(CSOUND *csound, moogladder *p) { MYFLT *out = p->out; MYFLT *in = p->in; MYFLT freq = *p->freq; MYFLT res = *p->res; double res4; double *delay = p->delay; double *tanhstg = p->tanhstg; double stg[4], input; double acr, tune; #define THERMAL (0.000025) /* (1.0 / 40000.0) transistor thermal voltage */ int j; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; if (res < 0) res = 0; if (p->oldfreq != freq || p->oldres != res) { double f, fc, fc2, fc3, fcr; p->oldfreq = freq; /* sr is half the actual filter sampling rate */ fc = (double)(freq/CS_ESR); f = 0.5*fc; fc2 = fc*fc; fc3 = fc2*fc; /* frequency & amplitude correction */ fcr = 1.8730*fc3 + 0.4955*fc2 - 0.6490*fc + 0.9988; acr = -3.9364*fc2 + 1.8409*fc + 0.9968; tune = (1.0 - exp(-(TWOPI*f*fcr))) / THERMAL; /* filter tuning */ p->oldres = res; p->oldacr = acr; p->oldtune = tune; } else { res = p->oldres; acr = p->oldacr; tune = p->oldtune; } res4 = 4.0*(double)res*acr; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i = offset; i < nsmps; i++) { /* oversampling */ for (j = 0; j < 2; j++) { /* filter stages */ input = in[i] - res4*delay[5]; delay[0] = stg[0] = delay[0] + tune*(tanh(input*THERMAL) - tanhstg[0]); #if 1 input = stg[0]; stg[1] = delay[1] + tune*((tanhstg[0] = tanh(input*THERMAL)) - tanhstg[1]); input = delay[1] = stg[1]; stg[2] = delay[2] + tune*((tanhstg[1] = tanh(input*THERMAL)) - tanhstg[2]); input = delay[2] = stg[2]; stg[3] = delay[3] + tune*((tanhstg[2] = tanh(input*THERMAL)) - tanh(delay[3]*THERMAL)); delay[3] = stg[3]; #else { int k; for (k = 1; k < 4; k++) { input = stg[k-1]; stg[k] = delay[k] + tune*((tanhstg[k-1] = tanh(input*THERMAL)) - (k != 3 ? tanhstg[k] : tanh(delay[k]*THERMAL))); delay[k] = stg[k]; } } #endif /* 1/2-sample delay for phase compensation */ delay[5] = (stg[3] + delay[4])*0.5; delay[4] = stg[3]; } out[i] = (MYFLT) delay[5]; } return OK; } static int moogladder_process_aa(CSOUND *csound, moogladder *p) { MYFLT *out = p->out; MYFLT *in = p->in; MYFLT *freq = p->freq; MYFLT *res = p->res; MYFLT cfreq = freq[0], cres = res[0]; double res4; double *delay = p->delay; double *tanhstg = p->tanhstg; double stg[4], input; double acr, tune; #define THERMAL (0.000025) /* (1.0 / 40000.0) transistor thermal voltage */ int j; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; if (p->oldfreq != cfreq || p->oldres != cres) { double f, fc, fc2, fc3, fcr; p->oldfreq = cfreq; /* sr is half the actual filter sampling rate */ fc = (double)(cfreq/CS_ESR); f = 0.5*fc; fc2 = fc*fc; fc3 = fc2*fc; /* frequency & amplitude correction */ fcr = 1.8730*fc3 + 0.4955*fc2 - 0.6490*fc + 0.9988; acr = -3.9364*fc2 + 1.8409*fc + 0.9968; tune = (1.0 - exp(-(TWOPI*f*fcr))) / THERMAL; /* filter tuning */ p->oldres = cres; p->oldacr = acr; p->oldtune = tune; } else { cres = p->oldres; acr = p->oldacr; tune = p->oldtune; } res4 = 4.0*(double)cres*acr; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i = offset; i < nsmps; i++) { if (p->oldfreq != freq[i] || p->oldres != res[i]) { double f, fc, fc2, fc3, fcr; p->oldfreq = freq[i]; /* sr is half the actual filter sampling rate */ fc = (double)(freq[i]/CS_ESR); f = 0.5*fc; fc2 = fc*fc; fc3 = fc2*fc; /* frequency & amplitude correction */ fcr = 1.8730*fc3 + 0.4955*fc2 - 0.6490*fc + 0.9988; acr = -3.9364*fc2 + 1.8409*fc + 0.9968; tune = (1.0 - exp(-(TWOPI*f*fcr))) / THERMAL; /* filter tuning */ p->oldres = cres; p->oldacr = acr; p->oldtune = tune; res4 = 4.0*(double)res[i]*acr; } /* oversampling */ for (j = 0; j < 2; j++) { /* filter stages */ input = in[i] - res4 /*4.0*res*acr*/ *delay[5]; delay[0] = stg[0] = delay[0] + tune*(tanh(input*THERMAL) - tanhstg[0]); #if 1 input = stg[0]; stg[1] = delay[1] + tune*((tanhstg[0] = tanh(input*THERMAL)) - tanhstg[1]); input = delay[1] = stg[1]; stg[2] = delay[2] + tune*((tanhstg[1] = tanh(input*THERMAL)) - tanhstg[2]); input = delay[2] = stg[2]; stg[3] = delay[3] + tune*((tanhstg[2] = tanh(input*THERMAL)) - tanh(delay[3]*THERMAL)); delay[3] = stg[3]; #else { int k; for (k = 1; k < 4; k++) { input = stg[k-1]; stg[k] = delay[k] + tune*((tanhstg[k-1] = tanh(input*THERMAL)) - (k != 3 ? tanhstg[k] : tanh(delay[k]*THERMAL))); delay[k] = stg[k]; } } #endif /* 1/2-sample delay for phase compensation */ delay[5] = (stg[3] + delay[4])*0.5; delay[4] = stg[3]; } out[i] = (MYFLT) delay[5]; } return OK; } static int moogladder_process_ak(CSOUND *csound, moogladder *p) { MYFLT *out = p->out; MYFLT *in = p->in; MYFLT *freq = p->freq; MYFLT res = *p->res; double res4; double *delay = p->delay; double *tanhstg = p->tanhstg; double stg[4], input; double acr, tune; #define THERMAL (0.000025) /* (1.0 / 40000.0) transistor thermal voltage */ int j; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; if (res < 0) res = 0; if (p->oldfreq != freq[0] || p->oldres != res) { double f, fc, fc2, fc3, fcr; p->oldfreq = freq[0]; /* sr is half the actual filter sampling rate */ fc = (double)(freq[0]/CS_ESR); f = 0.5*fc; fc2 = fc*fc; fc3 = fc2*fc; /* frequency & amplitude correction */ fcr = 1.8730*fc3 + 0.4955*fc2 - 0.6490*fc + 0.9988; acr = -3.9364*fc2 + 1.8409*fc + 0.9968; tune = (1.0 - exp(-(TWOPI*f*fcr))) / THERMAL; /* filter tuning */ p->oldres = res; p->oldacr = acr; p->oldtune = tune; } else { res = p->oldres; acr = p->oldacr; tune = p->oldtune; } res4 = 4.0*(double)res*acr; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i = offset; i < nsmps; i++) { if (p->oldfreq != freq[i]) { double f, fc, fc2, fc3, fcr; p->oldfreq = freq[i]; /* sr is half the actual filter sampling rate */ fc = (double)(freq[i]/CS_ESR); f = 0.5*fc; fc2 = fc*fc; fc3 = fc2*fc; /* frequency & amplitude correction */ fcr = 1.8730*fc3 + 0.4955*fc2 - 0.6490*fc + 0.9988; acr = -3.9364*fc2 + 1.8409*fc + 0.9968; tune = (1.0 - exp(-(TWOPI*f*fcr))) / THERMAL; /* filter tuning */ p->oldacr = acr; p->oldtune = tune; res4 = 4.0*(double)res*acr; } /* oversampling */ for (j = 0; j < 2; j++) { /* filter stages */ input = in[i] - res4 /*4.0*res*acr*/ *delay[5]; delay[0] = stg[0] = delay[0] + tune*(tanh(input*THERMAL) - tanhstg[0]); #if 1 input = stg[0]; stg[1] = delay[1] + tune*((tanhstg[0] = tanh(input*THERMAL)) - tanhstg[1]); input = delay[1] = stg[1]; stg[2] = delay[2] + tune*((tanhstg[1] = tanh(input*THERMAL)) - tanhstg[2]); input = delay[2] = stg[2]; stg[3] = delay[3] + tune*((tanhstg[2] = tanh(input*THERMAL)) - tanh(delay[3]*THERMAL)); delay[3] = stg[3]; #else { int k; for (k = 1; k < 4; k++) { input = stg[k-1]; stg[k] = delay[k] + tune*((tanhstg[k-1] = tanh(input*THERMAL)) - (k != 3 ? tanhstg[k] : tanh(delay[k]*THERMAL))); delay[k] = stg[k]; } } #endif /* 1/2-sample delay for phase compensation */ delay[5] = (stg[3] + delay[4])*0.5; delay[4] = stg[3]; } out[i] = (MYFLT) delay[5]; } return OK; } static int moogladder_process_ka(CSOUND *csound, moogladder *p) { MYFLT *out = p->out; MYFLT *in = p->in; MYFLT freq = *p->freq; MYFLT *res = p->res; MYFLT cres = res[0]; double res4; double *delay = p->delay; double *tanhstg = p->tanhstg; double stg[4], input; double acr, tune; #define THERMAL (0.000025) /* (1.0 / 40000.0) transistor thermal voltage */ int j; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; if (cres < 0) cres = 0; if (p->oldfreq != freq || p->oldres != cres) { double f, fc, fc2, fc3, fcr; p->oldfreq = freq; /* sr is half the actual filter sampling rate */ fc = (double)(freq/CS_ESR); f = 0.5*fc; fc2 = fc*fc; fc3 = fc2*fc; /* frequency & amplitude correction */ fcr = 1.8730*fc3 + 0.4955*fc2 - 0.6490*fc + 0.9988; acr = -3.9364*fc2 + 1.8409*fc + 0.9968; tune = (1.0 - exp(-(TWOPI*f*fcr))) / THERMAL; /* filter tuning */ p->oldres = cres; p->oldacr = acr; p->oldtune = tune; } else { cres = p->oldres; acr = p->oldacr; tune = p->oldtune; } res4 = 4.0*(double)cres*acr; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i = offset; i < nsmps; i++) { if (cres != res[i]) { double f, fc, fc2, fc3, fcr; /* sr is half the actual filter sampling rate */ fc = (double)(freq/CS_ESR); f = 0.5*fc; fc2 = fc*fc; fc3 = fc2*fc; /* frequency & amplitude correction */ fcr = 1.8730*fc3 + 0.4955*fc2 - 0.6490*fc + 0.9988; acr = -3.9364*fc2 + 1.8409*fc + 0.9968; tune = (1.0 - exp(-(TWOPI*f*fcr))) / THERMAL; /* filter tuning */ p->oldres = cres = res[i]; p->oldacr = acr; p->oldtune = tune; res4 = 4.0*(double)cres*acr; } /* oversampling */ for (j = 0; j < 2; j++) { /* filter stages */ input = in[i] - res4 /*4.0*res*acr*/ *delay[5]; delay[0] = stg[0] = delay[0] + tune*(tanh(input*THERMAL) - tanhstg[0]); #if 1 input = stg[0]; stg[1] = delay[1] + tune*((tanhstg[0] = tanh(input*THERMAL)) - tanhstg[1]); input = delay[1] = stg[1]; stg[2] = delay[2] + tune*((tanhstg[1] = tanh(input*THERMAL)) - tanhstg[2]); input = delay[2] = stg[2]; stg[3] = delay[3] + tune*((tanhstg[2] = tanh(input*THERMAL)) - tanh(delay[3]*THERMAL)); delay[3] = stg[3]; #else { int k; for (k = 1; k < 4; k++) { input = stg[k-1]; stg[k] = delay[k] + tune*((tanhstg[k-1] = tanh(input*THERMAL)) - (k != 3 ? tanhstg[k] : tanh(delay[k]*THERMAL))); delay[k] = stg[k]; } } #endif /* 1/2-sample delay for phase compensation */ delay[5] = (stg[3] + delay[4])*0.5; delay[4] = stg[3]; } out[i] = (MYFLT) delay[5]; } return OK; } static int moogladder2_process(CSOUND *csound, moogladder *p) { MYFLT *out = p->out; MYFLT *in = p->in; MYFLT freq = *p->freq; MYFLT res = *p->res; double res4; double *delay = p->delay; double *tanhstg = p->tanhstg; double stg[4], input; double acr, tune; #define THERMAL (0.000025) /* (1.0 / 40000.0) transistor thermal voltage */ int j; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; if (res < 0) res = 0; if (p->oldfreq != freq || p->oldres != res) { double f, fc, fc2, fc3, fcr; p->oldfreq = freq; /* sr is half the actual filter sampling rate */ fc = (double)(freq/CS_ESR); f = 0.5*fc; fc2 = fc*fc; fc3 = fc2*fc; /* frequency & amplitude correction */ fcr = 1.8730*fc3 + 0.4955*fc2 - 0.6490*fc + 0.9988; acr = -3.9364*fc2 + 1.8409*fc + 0.9968; tune = (1.0 - exp(-(TWOPI*f*fcr))) / THERMAL; /* filter tuning */ p->oldres = res; p->oldacr = acr; p->oldtune = tune; } else { res = p->oldres; acr = p->oldacr; tune = p->oldtune; } res4 = 4.0*(double)res*acr; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i = offset; i < nsmps; i++) { /* oversampling */ for (j = 0; j < 2; j++) { /* filter stages */ input = in[i] - res4*delay[5]; delay[0] = stg[0] = delay[0] + tune*(TanH(input*THERMAL) - tanhstg[0]); #if 1 input = stg[0]; stg[1] = delay[1] + tune*((tanhstg[0] = TanH(input*THERMAL)) - tanhstg[1]); input = delay[1] = stg[1]; stg[2] = delay[2] + tune*((tanhstg[1] = TanH(input*THERMAL)) - tanhstg[2]); input = delay[2] = stg[2]; stg[3] = delay[3] + tune*((tanhstg[2] = TanH(input*THERMAL)) - TanH(delay[3]*THERMAL)); delay[3] = stg[3]; #else { int k; for (k = 1; k < 4; k++) { input = stg[k-1]; stg[k] = delay[k] + tune*((tanhstg[k-1] = TanH(input*THERMAL)) - (k != 3 ? tanhstg[k] : TanH(delay[k]*THERMAL))); delay[k] = stg[k]; } } #endif /* 1/2-sample delay for phase compensation */ delay[5] = (stg[3] + delay[4])*0.5; delay[4] = stg[3]; } out[i] = (MYFLT) delay[5]; } return OK; } static int moogladder2_process_aa(CSOUND *csound, moogladder *p) { MYFLT *out = p->out; MYFLT *in = p->in; MYFLT *freq = p->freq; MYFLT *res = p->res; MYFLT cfreq = freq[0], cres = res[0]; double res4; double *delay = p->delay; double *tanhstg = p->tanhstg; double stg[4], input; double acr, tune; #define THERMAL (0.000025) /* (1.0 / 40000.0) transistor thermal voltage */ int j; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; if (p->oldfreq != cfreq || p->oldres != cres) { double f, fc, fc2, fc3, fcr; p->oldfreq = cfreq; /* sr is half the actual filter sampling rate */ fc = (double)(cfreq/CS_ESR); f = 0.5*fc; fc2 = fc*fc; fc3 = fc2*fc; /* frequency & amplitude correction */ fcr = 1.8730*fc3 + 0.4955*fc2 - 0.6490*fc + 0.9988; acr = -3.9364*fc2 + 1.8409*fc + 0.9968; tune = (1.0 - exp(-(TWOPI*f*fcr))) / THERMAL; /* filter tuning */ p->oldres = cres; p->oldacr = acr; p->oldtune = tune; } else { cres = p->oldres; acr = p->oldacr; tune = p->oldtune; } res4 = 4.0*(double)cres*acr; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i = offset; i < nsmps; i++) { if (p->oldfreq != freq[i] || p->oldres != res[i]) { double f, fc, fc2, fc3, fcr; p->oldfreq = freq[i]; /* sr is half the actual filter sampling rate */ fc = (double)(freq[i]/CS_ESR); f = 0.5*fc; fc2 = fc*fc; fc3 = fc2*fc; /* frequency & amplitude correction */ fcr = 1.8730*fc3 + 0.4955*fc2 - 0.6490*fc + 0.9988; acr = -3.9364*fc2 + 1.8409*fc + 0.9968; tune = (1.0 - exp(-(TWOPI*f*fcr))) / THERMAL; /* filter tuning */ p->oldres = cres; p->oldacr = acr; p->oldtune = tune; res4 = 4.0*(double)res[i]*acr; } /* oversampling */ for (j = 0; j < 2; j++) { /* filter stages */ input = in[i] - res4 /*4.0*res*acr*/ *delay[5]; delay[0] = stg[0] = delay[0] + tune*(TanH(input*THERMAL) - tanhstg[0]); #if 1 input = stg[0]; stg[1] = delay[1] + tune*((tanhstg[0] = TanH(input*THERMAL)) - tanhstg[1]); input = delay[1] = stg[1]; stg[2] = delay[2] + tune*((tanhstg[1] = TanH(input*THERMAL)) - tanhstg[2]); input = delay[2] = stg[2]; stg[3] = delay[3] + tune*((tanhstg[2] = TanH(input*THERMAL)) - TanH(delay[3]*THERMAL)); delay[3] = stg[3]; #else { int k; for (k = 1; k < 4; k++) { input = stg[k-1]; stg[k] = delay[k] + tune*((tanhstg[k-1] = TanH(input*THERMAL)) - (k != 3 ? tanhstg[k] : TanH(delay[k]*THERMAL))); delay[k] = stg[k]; } } #endif /* 1/2-sample delay for phase compensation */ delay[5] = (stg[3] + delay[4])*0.5; delay[4] = stg[3]; } out[i] = (MYFLT) delay[5]; } return OK; } static int moogladder2_process_ak(CSOUND *csound, moogladder *p) { MYFLT *out = p->out; MYFLT *in = p->in; MYFLT *freq = p->freq; MYFLT res = *p->res; double res4; double *delay = p->delay; double *tanhstg = p->tanhstg; double stg[4], input; double acr, tune; #define THERMAL (0.000025) /* (1.0 / 40000.0) transistor thermal voltage */ int j; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; if (res < 0) res = 0; if (p->oldfreq != freq[0] || p->oldres != res) { double f, fc, fc2, fc3, fcr; p->oldfreq = freq[0]; /* sr is half the actual filter sampling rate */ fc = (double)(freq[0]/CS_ESR); f = 0.5*fc; fc2 = fc*fc; fc3 = fc2*fc; /* frequency & amplitude correction */ fcr = 1.8730*fc3 + 0.4955*fc2 - 0.6490*fc + 0.9988; acr = -3.9364*fc2 + 1.8409*fc + 0.9968; tune = (1.0 - exp(-(TWOPI*f*fcr))) / THERMAL; /* filter tuning */ p->oldres = res; p->oldacr = acr; p->oldtune = tune; } else { res = p->oldres; acr = p->oldacr; tune = p->oldtune; } res4 = 4.0*(double)res*acr; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i = offset; i < nsmps; i++) { if (p->oldfreq != freq[i]) { double f, fc, fc2, fc3, fcr; p->oldfreq = freq[i]; /* sr is half the actual filter sampling rate */ fc = (double)(freq[i]/CS_ESR); f = 0.5*fc; fc2 = fc*fc; fc3 = fc2*fc; /* frequency & amplitude correction */ fcr = 1.8730*fc3 + 0.4955*fc2 - 0.6490*fc + 0.9988; acr = -3.9364*fc2 + 1.8409*fc + 0.9968; tune = (1.0 - exp(-(TWOPI*f*fcr))) / THERMAL; /* filter tuning */ p->oldacr = acr; p->oldtune = tune; res4 = 4.0*(double)res*acr; } /* oversampling */ for (j = 0; j < 2; j++) { /* filter stages */ input = in[i] - res4 /*4.0*res*acr*/ *delay[5]; delay[0] = stg[0] = delay[0] + tune*(TanH(input*THERMAL) - tanhstg[0]); #if 1 input = stg[0]; stg[1] = delay[1] + tune*((tanhstg[0] = TanH(input*THERMAL)) - tanhstg[1]); input = delay[1] = stg[1]; stg[2] = delay[2] + tune*((tanhstg[1] = TanH(input*THERMAL)) - tanhstg[2]); input = delay[2] = stg[2]; stg[3] = delay[3] + tune*((tanhstg[2] = TanH(input*THERMAL)) - TanH(delay[3]*THERMAL)); delay[3] = stg[3]; #else { int k; for (k = 1; k < 4; k++) { input = stg[k-1]; stg[k] = delay[k] + tune*((tanhstg[k-1] = TanH(input*THERMAL)) - (k != 3 ? tanhstg[k] : TanH(delay[k]*THERMAL))); delay[k] = stg[k]; } } #endif /* 1/2-sample delay for phase compensation */ delay[5] = (stg[3] + delay[4])*0.5; delay[4] = stg[3]; } out[i] = (MYFLT) delay[5]; } return OK; } static int moogladder2_process_ka(CSOUND *csound, moogladder *p) { MYFLT *out = p->out; MYFLT *in = p->in; MYFLT freq = *p->freq; MYFLT *res = p->res; MYFLT cres = res[0]; double res4; double *delay = p->delay; double *tanhstg = p->tanhstg; double stg[4], input; double acr, tune; #define THERMAL (0.000025) /* (1.0 / 40000.0) transistor thermal voltage */ int j; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; if (cres < 0) cres = 0; if (p->oldfreq != freq || p->oldres != cres) { double f, fc, fc2, fc3, fcr; p->oldfreq = freq; /* sr is half the actual filter sampling rate */ fc = (double)(freq/CS_ESR); f = 0.5*fc; fc2 = fc*fc; fc3 = fc2*fc; /* frequency & amplitude correction */ fcr = 1.8730*fc3 + 0.4955*fc2 - 0.6490*fc + 0.9988; acr = -3.9364*fc2 + 1.8409*fc + 0.9968; tune = (1.0 - exp(-(TWOPI*f*fcr))) / THERMAL; /* filter tuning */ p->oldres = cres; p->oldacr = acr; p->oldtune = tune; } else { cres = p->oldres; acr = p->oldacr; tune = p->oldtune; } res4 = 4.0*(double)cres*acr; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i = offset; i < nsmps; i++) { if (cres != res[i]) { double f, fc, fc2, fc3, fcr; /* sr is half the actual filter sampling rate */ fc = (double)(freq/CS_ESR); f = 0.5*fc; fc2 = fc*fc; fc3 = fc2*fc; /* frequency & amplitude correction */ fcr = 1.8730*fc3 + 0.4955*fc2 - 0.6490*fc + 0.9988; acr = -3.9364*fc2 + 1.8409*fc + 0.9968; tune = (1.0 - exp(-(TWOPI*f*fcr))) / THERMAL; /* filter tuning */ p->oldres = cres = res[i]; p->oldacr = acr; p->oldtune = tune; res4 = 4.0*(double)cres*acr; } /* oversampling */ for (j = 0; j < 2; j++) { /* filter stages */ input = in[i] - res4 /*4.0*res*acr*/ *delay[5]; delay[0] = stg[0] = delay[0] + tune*(TanH(input*THERMAL) - tanhstg[0]); #if 1 input = stg[0]; stg[1] = delay[1] + tune*((tanhstg[0] = TanH(input*THERMAL)) - tanhstg[1]); input = delay[1] = stg[1]; stg[2] = delay[2] + tune*((tanhstg[1] = TanH(input*THERMAL)) - tanhstg[2]); input = delay[2] = stg[2]; stg[3] = delay[3] + tune*((tanhstg[2] = TanH(input*THERMAL)) - TanH(delay[3]*THERMAL)); delay[3] = stg[3]; #else { int k; for (k = 1; k < 4; k++) { input = stg[k-1]; stg[k] = delay[k] + tune*((tanhstg[k-1] = TanH(input*THERMAL)) - (k != 3 ? tanhstg[k] : TanH(delay[k]*THERMAL))); delay[k] = stg[k]; } } #endif /* 1/2-sample delay for phase compensation */ delay[5] = (stg[3] + delay[4])*0.5; delay[4] = stg[3]; } out[i] = (MYFLT) delay[5]; } return OK; } static int statevar_init(CSOUND *csound,statevar *p) { if (*p->istor==FL(0.0)) { p->bpd = p->lpd = p->lp = 0.0; p->oldfreq = FL(0.0); p->oldres = FL(0.0); } if (*p->osamp<=FL(0.0)) p->ostimes = 3; else p->ostimes = (int) *p->osamp; return OK; } static int statevar_process(CSOUND *csound,statevar *p) { MYFLT *outhp = p->outhp; MYFLT *outlp = p->outlp; MYFLT *outbp = p->outbp; MYFLT *outbr = p->outbr; MYFLT *in = p->in; MYFLT *freq = p->freq; MYFLT *res = p->res; double lpd = p->lpd; double bpd = p->bpd; double lp = p->lp, hp = 0.0, bp = 0.0, br = 0.0; double f,q,lim; int ostimes = p->ostimes,j; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; int asgfr = IS_ASIG_ARG(p->freq), asgrs = IS_ASIG_ARG(p->res); if (UNLIKELY(offset)) { memset(outhp, '\0', offset*sizeof(MYFLT)); memset(outlp, '\0', offset*sizeof(MYFLT)); memset(outbp, '\0', offset*sizeof(MYFLT)); memset(outbr, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&outhp[nsmps], '\0', early*sizeof(MYFLT)); memset(&outlp[nsmps], '\0', early*sizeof(MYFLT)); memset(&outbp[nsmps], '\0', early*sizeof(MYFLT)); memset(&outbr[nsmps], '\0', early*sizeof(MYFLT)); } q = p->oldq; f = p->oldf; for (i=offset; ioldfreq != fr|| p->oldres != rs) { f = 2.0*sin(fr*(double)csound->pidsr/ostimes); q = 1.0/rs; lim = ((2.0 - f) *0.05)/ostimes; /* csound->Message(csound, "lim: %f, q: %f \n", lim, q); */ if (q < lim) q = lim; p->oldq = q; p->oldf = f; p->oldfreq = fr; p->oldres = rs; } for (j=0; jbpd = bpd; p->lpd = lpd; p->lp = lp; return OK; } static int fofilter_init(CSOUND *csound,fofilter *p) { int i; if (*p->istor==FL(0.0)) { for (i=0;i<4; i++) p->delay[i] = 0.0; } return OK; } static int fofilter_process(CSOUND *csound,fofilter *p) { MYFLT *out = p->out; MYFLT *in = p->in; MYFLT *freq = p->freq; MYFLT *ris = p->ris; MYFLT *dec = p->dec; double *delay = p->delay,ang=0,fsc,rrad1=0,rrad2=0; double w1,y1,w2,y2; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT lfrq = -FL(1.0), lrs = -FL(1.0), ldc = -FL(1.0); int asgfr = IS_ASIG_ARG(p->freq) , asgrs = IS_ASIG_ARG(p->ris); int asgdc = IS_ASIG_ARG(p->dec); if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset;itpidsr*frq; /* pole angle */ fsc = sin(ang) - 3.0; /* freq scl */ rrad1 = pow(10.0, fsc/(dc*CS_ESR)); /* filter radii */ rrad2 = pow(10.0, fsc/(rs*CS_ESR)); } w1 = in[i] + 2.0*rrad1*cos(ang)*delay[0] - rrad1*rrad1*delay[1]; y1 = w1 - delay[1]; delay[1] = delay[0]; delay[0] = w1; w2 = in[i] + 2.0*rrad2*cos(ang)*delay[2] - rrad2*rrad2*delay[3]; y2 = w2 - delay[3]; delay[3] = delay[2]; delay[2] = w2; out[i] = (MYFLT) (y1 - y2); } return OK; } /* filter designs by Fons Adriaensen */ typedef struct _mvcf { OPDS h; MYFLT *out; MYFLT *in, *freq, *res, *skipinit; double c1, c2, c3, c4, c5; double fr, w; } mvclpf24; double exp2ap(double x) { int i = (int) (floor(x)); x -= i; return ldexp(1 + x * (0.6930 + x * (0.2416 + x * (0.0517 + x * 0.0137))), i); } int mvclpf24_init(CSOUND *csound, mvclpf24 *p){ if (!*p->skipinit){ p->c1 = p->c2 = p->c3 = p->c4 = p->c5 = FL(0.0); p->fr = FL(0.0); } return OK; } #define CBASE 261.62556416 int mvclpf24_perf1(CSOUND *csound, mvclpf24 *p){ MYFLT *out = p->out; MYFLT *in = p->in, res; double c1 = p->c1+1e-6, c2 = p->c2, c3 = p->c3, c4 = p->c4, c5 = p->c5, w, x, t; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT scal = csound->Get0dBFS(csound); if (p->fr != *p->freq) { MYFLT fr = log2(*p->freq/CBASE); p->fr = *p->freq; w = exp2ap(fr + 10.82)/csound->GetSr(csound); if (w < 0.8) w *= 1 - 0.4 * w - 0.125 * w * w; else { w *= 0.6; if (w > 0.92) w = 0.92; } p->w = w; } else w = p->w; res = *p->res; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset; i < nsmps; i++){ x = -4.2*res*c5 + in[i]/scal + 1e-10; t = c1 / (1 + fabs (c1)); c1 += w*(x - t); x = c1 / (1 + fabs (c1)); c2 += w * (x - c2); c3 += w * (c2 - c3); c4 += w * (c3 - c4); out[i] = c4*scal; c5 += 0.5 * (c4 - c5); } p->c1 = c1; p->c2 = c2; p->c3 = c3; p->c4 = c4; p->c5 = c5; return OK; } int mvclpf24_perf1_ak(CSOUND *csound, mvclpf24 *p){ MYFLT *out = p->out; MYFLT *in = p->in, res, *freq = p->freq; double c1 = p->c1+1e-6, c2 = p->c2, c3 = p->c3, c4 = p->c4, c5 = p->c5, w, x, t; int wi; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT scal = csound->Get0dBFS(csound); res = *p->res; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset; i < nsmps; i++){ t = log2(freq[i]/CBASE) + 10.82; wi = (int) (floor(t)); t -= wi; t = ldexp(1 + t * (0.6930 + t * (0.2416 + t * (0.0517 + t * 0.0137))), wi); w = t/csound->GetSr(csound); if (w < 0.8) w *= 1 - 0.4 * w - 0.125 * w * w; else { w *= 0.6; if (w > 0.92) w = 0.92; } x = -4.2*res*c5 + in[i]/scal + 1e-10; t = c1 / (1 + fabs (c1)); c1 += w*(x - t); x = c1 / (1 + fabs (c1)); c2 += w * (x - c2); c3 += w * (c2 - c3); c4 += w * (c3 - c4); out[i] = c4*scal; c5 += 0.5 * (c4 - c5); } p->c1 = c1; p->c2 = c2; p->c3 = c3; p->c4 = c4; p->c5 = c5; return OK; } int mvclpf24_perf1_ka(CSOUND *csound, mvclpf24 *p){ MYFLT *out = p->out; MYFLT *in = p->in, *res = p->res; double c1 = p->c1+1e-6, c2 = p->c2, c3 = p->c3, c4 = p->c4, c5 = p->c5, w, x, t; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT scal = csound->Get0dBFS(csound); if (p->fr != *p->freq) { MYFLT fr = log2(*p->freq/CBASE); p->fr = *p->freq; w = exp2ap(fr + 10.82)/csound->GetSr(csound); if (w < 0.8) w *= 1 - 0.4 * w - 0.125 * w * w; else { w *= 0.6; if (w > 0.92) w = 0.92; } p->w = w; } else w = p->w; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset; i < nsmps; i++){ x = -4.2*c5*res[i] + in[i]/scal + 1e-10; t = c1 / (1 + fabs (c1)); c1 += w*(x - t); x = c1 / (1 + fabs (c1)); c2 += w * (x - c2); c3 += w * (c2 - c3); c4 += w * (c3 - c4); out[i] = c4*scal; c5 += 0.5 * (c4 - c5); } p->c1 = c1; p->c2 = c2; p->c3 = c3; p->c4 = c4; p->c5 = c5; return OK; } int mvclpf24_perf1_aa(CSOUND *csound, mvclpf24 *p){ MYFLT *out = p->out; MYFLT *in = p->in, *res = p->res, *freq = p->freq; double c1 = p->c1+1e-6, c2 = p->c2, c3 = p->c3, c4 = p->c4, c5 = p->c5, w, x, t; int wi; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT scal = csound->Get0dBFS(csound); if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset; i < nsmps; i++){ t = log2(freq[i]/CBASE) + 10.82; wi = (int) (floor(t)); t -= wi; t = ldexp(1 + t * (0.6930 + t * (0.2416 + t * (0.0517 + t * 0.0137))), wi); w = t/csound->GetSr(csound); if (w < 0.8) w *= 1 - 0.4 * w - 0.125 * w * w; else { w *= 0.6; if (w > 0.92) w = 0.92; } x = -4.2*c5*res[i] + in[i]/scal + 1e-10; t = c1 / (1 + fabs (c1)); c1 += w*(x - t); x = c1 / (1 + fabs (c1)); c2 += w * (x - c2); c3 += w * (c2 - c3); c4 += w * (c3 - c4); out[i] = c4*scal; c5 += 0.5 * (c4 - c5); } p->c1 = c1; p->c2 = c2; p->c3 = c3; p->c4 = c4; p->c5 = c5; return OK; } int mvclpf24_perf2(CSOUND *csound, mvclpf24 *p){ MYFLT *out = p->out; MYFLT *in = p->in, res; double c1 = p->c1+1e-6, c2 = p->c2, c3 = p->c3, c4 = p->c4, c5 = p->c5, w, x; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT scal = csound->Get0dBFS(csound); if (p->fr != *p->freq) { MYFLT fr = log2(*p->freq/CBASE); p->fr = *p->freq; w = exp2ap(fr + 10.71)/csound->GetSr(csound); if (w < 0.8) w *= 1 - 0.4 * w - 0.125 * w * w; else { w *= 0.6; if (w > 0.92) w = 0.92; } p->w = w; } else w = p->w; res = *p->res; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset; i < nsmps; i++){ x = -4.5*res*c5 + in[i]/scal + 1e-10; x /= sqrt (1 + x * x); c1 += w * (x - c1) / (1 + c1 * c1); c2 += w * (c1 - c2) / (1 + c2 * c2); c3 += w * (c2 - c3) / (1 + c3 * c3); c4 += w * (c3 - c4) / (1 + c4 * c4); out[i] = c4*scal; c5 += 0.5 * (c4 - c5); } p->c1 = c1; p->c2 = c2; p->c3 = c3; p->c4 = c4; p->c5 = c5; return OK; } int mvclpf24_perf2_ak(CSOUND *csound, mvclpf24 *p){ MYFLT *out = p->out; MYFLT *in = p->in, res, *freq = p->freq ; double c1 = p->c1+1e-6, c2 = p->c2, c3 = p->c3, c4 = p->c4, c5 = p->c5, w, x, t; int wi; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT scal = csound->Get0dBFS(csound); res = *p->res; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset; i < nsmps; i++){ t = log2(freq[i]/CBASE) + 10.71; wi = (int) (floor(t)); t -= wi; t = ldexp(1 + t * (0.6930 + t * (0.2416 + t * (0.0517 + t * 0.0137))), wi); w = t/csound->GetSr(csound); if (w < 0.8) w *= 1 - 0.4 * w - 0.125 * w * w; else { w *= 0.6; if (w > 0.92) w = 0.92; } x = -4.5*res*c5 + in[i]/scal + 1e-10; x /= sqrt (1 + x * x); c1 += w * (x - c1) / (1 + c1 * c1); c2 += w * (c1 - c2) / (1 + c2 * c2); c3 += w * (c2 - c3) / (1 + c3 * c3); c4 += w * (c3 - c4) / (1 + c4 * c4); out[i] = c4*scal; c5 += 0.5 * (c4 - c5); } p->c1 = c1; p->c2 = c2; p->c3 = c3; p->c4 = c4; p->c5 = c5; return OK; } int mvclpf24_perf2_ka(CSOUND *csound, mvclpf24 *p){ MYFLT *out = p->out; MYFLT *in = p->in, *res = p->res; double c1 = p->c1+1e-6, c2 = p->c2, c3 = p->c3, c4 = p->c4, c5 = p->c5, w, x; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT scal = csound->Get0dBFS(csound); if (p->fr != *p->freq) { MYFLT fr = log2(*p->freq/CBASE); p->fr = *p->freq; w = exp2ap(fr + 10.71)/csound->GetSr(csound); if (w < 0.8) w *= 1 - 0.4 * w - 0.125 * w * w; else { w *= 0.6; if (w > 0.92) w = 0.92; } p->w = w; } else w = p->w; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset; i < nsmps; i++){ x = -4.5*c5*res[i] + in[i]/scal + 1e-10; x /= sqrt (1 + x * x); c1 += w * (x - c1) / (1 + c1 * c1); c2 += w * (c1 - c2) / (1 + c2 * c2); c3 += w * (c2 - c3) / (1 + c3 * c3); c4 += w * (c3 - c4) / (1 + c4 * c4); out[i] = c4*scal; c5 += 0.5 * (c4 - c5); } p->c1 = c1; p->c2 = c2; p->c3 = c3; p->c4 = c4; p->c5 = c5; return OK; } int mvclpf24_perf2_aa(CSOUND *csound, mvclpf24 *p){ MYFLT *out = p->out; MYFLT *in = p->in, *res = p->res, *freq = p->freq ; double c1 = p->c1+1e-6, c2 = p->c2, c3 = p->c3, c4 = p->c4, c5 = p->c5, w, x, t; int wi; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT scal = csound->Get0dBFS(csound); if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset; i < nsmps; i++){ t = log2(freq[i]/CBASE) + 10.71; wi = (int) (floor(t)); t -= wi; t = ldexp(1 + t * (0.6930 + t * (0.2416 + t * (0.0517 + t * 0.0137))), wi); w = t/csound->GetSr(csound); if (w < 0.8) w *= 1 - 0.4 * w - 0.125 * w * w; else { w *= 0.6; if (w > 0.92) w = 0.92; } x = -4.5*c5*res[i] + in[i]/scal + 1e-10; x /= sqrt (1 + x * x); c1 += w * (x - c1) / (1 + c1 * c1); c2 += w * (c1 - c2) / (1 + c2 * c2); c3 += w * (c2 - c3) / (1 + c3 * c3); c4 += w * (c3 - c4) / (1 + c4 * c4); out[i] = c4*scal; c5 += 0.5 * (c4 - c5); } p->c1 = c1; p->c2 = c2; p->c3 = c3; p->c4 = c4; p->c5 = c5; return OK; } int mvclpf24_perf3(CSOUND *csound, mvclpf24 *p){ MYFLT *out = p->out; MYFLT *in = p->in, res; double c1 = p->c1+1e-6, c2 = p->c2, c3 = p->c3, c4 = p->c4, c5 = p->c5, w, x, d; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT scal = csound->Get0dBFS(csound); if (p->fr != *p->freq) { MYFLT fr = log2(*p->freq/CBASE); p->fr = *p->freq; w = exp2ap(fr + 9.70)/csound->GetSr(csound); if (w < 0.75) w *= 1.005 - w * (0.624 - w * (0.65 - w * 0.54)); else { w *= 0.6748; if (w > 0.82) w = 0.82; } p->w = w; } else w = p->w; res = *p->res; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset; i < nsmps; i++){ x = in[i]/scal - (4.3 - 0.2 * w) * res * c5 + 1e-10; x /= sqrt (1 + x * x); d = w * (x - c1) / (1 + c1 * c1); x = c1 + 0.77 * d; c1 = x + 0.23 * d; d = w * (x - c2) / (1 + c2 * c2); x = c2 + 0.77 * d; c2 = x + 0.23 * d; d = w * (x - c3) / (1 + c3 * c3); x = c3 + 0.77 * d; c3 = x + 0.23 * d; d = w * (x - c4); x = c4 + 0.77 * d; c4 = x + 0.23 * d; c5 += 0.85 * (c4 - c5); x = in[i]/scal -(4.3 - 0.2 * w) * res * c5; x /= sqrt (1 + x * x); d = w * (x - c1) / (1 + c1 * c1); x = c1 + 0.77 * d; c1 = x + 0.23 * d; d = w * (x - c2) / (1 + c2 * c2); x = c2 + 0.77 * d; c2 = x + 0.23 * d; d = w * (x - c3) / (1 + c3 * c3); x = c3 + 0.77 * d; c3 = x + 0.23 * d; d = w * (x - c4); x = c4 + 0.77 * d; c4 = x + 0.23 * d; c5 += 0.85 * (c4 - c5); out[i] = c4*scal; } p->c1 = c1; p->c2 = c2; p->c3 = c3; p->c4 = c4; p->c5 = c5; return OK; } int mvclpf24_perf3_ak(CSOUND *csound, mvclpf24 *p){ MYFLT *out = p->out; MYFLT *in = p->in, res, *freq = p->freq; double c1 = p->c1+1e-6, c2 = p->c2, c3 = p->c3, c4 = p->c4, c5 = p->c5, w, x, t, d; int wi; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT scal = csound->Get0dBFS(csound); res = *p->res; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset; i < nsmps; i++){ t = log2(freq[i]/CBASE) + 9.70; wi = (int) (floor(t)); t -= wi; t = ldexp(1 + t * (0.6930 + t * (0.2416 + t * (0.0517 + t * 0.0137))), wi); w = t/csound->GetSr(csound); if (w < 0.75) w *= 1.005 - w * (0.624 - w * (0.65 - w * 0.54)); else { w *= 0.6748; if (w > 0.82) w = 0.82; } x = in[i]/scal - (4.3 - 0.2 * w) * res * c5 + 1e-10; x /= sqrt (1 + x * x); d = w * (x - c1) / (1 + c1 * c1); x = c1 + 0.77 * d; c1 = x + 0.23 * d; d = w * (x - c2) / (1 + c2 * c2); x = c2 + 0.77 * d; c2 = x + 0.23 * d; d = w * (x - c3) / (1 + c3 * c3); x = c3 + 0.77 * d; c3 = x + 0.23 * d; d = w * (x - c4); x = c4 + 0.77 * d; c4 = x + 0.23 * d; c5 += 0.85 * (c4 - c5); x = in[i]/scal -(4.3 - 0.2 * w) * res * c5; x /= sqrt (1 + x * x); d = w * (x - c1) / (1 + c1 * c1); x = c1 + 0.77 * d; c1 = x + 0.23 * d; d = w * (x - c2) / (1 + c2 * c2); x = c2 + 0.77 * d; c2 = x + 0.23 * d; d = w * (x - c3) / (1 + c3 * c3); x = c3 + 0.77 * d; c3 = x + 0.23 * d; d = w * (x - c4); x = c4 + 0.77 * d; c4 = x + 0.23 * d; c5 += 0.85 * (c4 - c5); out[i] = c4*scal; } p->c1 = c1; p->c2 = c2; p->c3 = c3; p->c4 = c4; p->c5 = c5; return OK; } int mvclpf24_perf3_ka(CSOUND *csound, mvclpf24 *p){ MYFLT *out = p->out; MYFLT *in = p->in, *res = p->res; double c1 = p->c1+1e-6, c2 = p->c2, c3 = p->c3, c4 = p->c4, c5 = p->c5, w, x, d; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT scal = csound->Get0dBFS(csound); if (p->fr != *p->freq) { MYFLT fr = log2(*p->freq/CBASE); p->fr = *p->freq; w = exp2ap(fr + 9.70)/csound->GetSr(csound); if (w < 0.75) w *= 1.005 - w * (0.624 - w * (0.65 - w * 0.54)); else { w *= 0.6748; if (w > 0.82) w = 0.82; } p->w = w; } else w = p->w; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset; i < nsmps; i++){ x = in[i]/scal - (4.3 - 0.2 * w) * (res[i] > FL(0.0) ? (res[i] < FL(1.0) ? res[i] : FL(1.0)) : FL(0.0)) * c5 + 1e-10; x /= sqrt (1 + x * x); d = w * (x - c1) / (1 + c1 * c1); x = c1 + 0.77 * d; c1 = x + 0.23 * d; d = w * (x - c2) / (1 + c2 * c2); x = c2 + 0.77 * d; c2 = x + 0.23 * d; d = w * (x - c3) / (1 + c3 * c3); x = c3 + 0.77 * d; c3 = x + 0.23 * d; d = w * (x - c4); x = c4 + 0.77 * d; c4 = x + 0.23 * d; c5 += 0.85 * (c4 - c5); x = in[i]/scal - (4.3 - 0.2 * w) * res[i] * c5 + 1e-10; x /= sqrt (1 + x * x); d = w * (x - c1) / (1 + c1 * c1); x = c1 + 0.77 * d; c1 = x + 0.23 * d; d = w * (x - c2) / (1 + c2 * c2); x = c2 + 0.77 * d; c2 = x + 0.23 * d; d = w * (x - c3) / (1 + c3 * c3); x = c3 + 0.77 * d; c3 = x + 0.23 * d; d = w * (x - c4); x = c4 + 0.77 * d; c4 = x + 0.23 * d; c5 += 0.85 * (c4 - c5); out[i] = c4*scal; } p->c1 = c1; p->c2 = c2; p->c3 = c3; p->c4 = c4; p->c5 = c5; return OK; } int mvclpf24_perf3_aa(CSOUND *csound, mvclpf24 *p){ MYFLT *out = p->out; MYFLT *in = p->in, *res = p->res, *freq = p->freq; double c1 = p->c1+1e-6, c2 = p->c2, c3 = p->c3, c4 = p->c4, c5 = p->c5, w, t, x, d; int wi; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT scal = csound->Get0dBFS(csound); if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset; i < nsmps; i++){ t = log2(freq[i]/CBASE) + 9.70; wi = (int) (floor(t)); t -= wi; t = ldexp(1 + t * (0.6930 + t * (0.2416 + t * (0.0517 + t * 0.0137))), wi); w = t/csound->GetSr(csound); if (w < 0.75) w *= 1.005 - w * (0.624 - w * (0.65 - w * 0.54)); else { w *= 0.6748; if (w > 0.82) w = 0.82; } x = in[i]/scal - (4.3 - 0.2 * w) * (res[i] > FL(0.0) ? (res[i] < FL(1.0) ? res[i] : FL(1.0)) : FL(0.0)) * c5 + 1e-10; x /= sqrt (1 + x * x); d = w * (x - c1) / (1 + c1 * c1); x = c1 + 0.77 * d; c1 = x + 0.23 * d; d = w * (x - c2) / (1 + c2 * c2); x = c2 + 0.77 * d; c2 = x + 0.23 * d; d = w * (x - c3) / (1 + c3 * c3); x = c3 + 0.77 * d; c3 = x + 0.23 * d; d = w * (x - c4); x = c4 + 0.77 * d; c4 = x + 0.23 * d; c5 += 0.85 * (c4 - c5); x = in[i]/scal - (4.3 - 0.2 * w) * res[i] * c5 + 1e-10; x /= sqrt (1 + x * x); d = w * (x - c1) / (1 + c1 * c1); x = c1 + 0.77 * d; c1 = x + 0.23 * d; d = w * (x - c2) / (1 + c2 * c2); x = c2 + 0.77 * d; c2 = x + 0.23 * d; d = w * (x - c3) / (1 + c3 * c3); x = c3 + 0.77 * d; c3 = x + 0.23 * d; d = w * (x - c4); x = c4 + 0.77 * d; c4 = x + 0.23 * d; c5 += 0.85 * (c4 - c5); out[i] = c4*scal; } p->c1 = c1; p->c2 = c2; p->c3 = c3; p->c4 = c4; p->c5 = c5; return OK; } typedef struct _mvcf4 { OPDS h; MYFLT *out0, *out1, *out2, *out3; MYFLT *in, *freq, *res, *skipinit; double c1, c2, c3, c4, c5; double fr, w; } mvclpf24_4; int mvclpf24_4_init(CSOUND *csound, mvclpf24_4 *p){ if (!*p->skipinit){ p->c1 = p->c2 = p->c3 = p->c4 = p->c5 = FL(0.0); p->fr = FL(0.0); } return OK; } int mvclpf24_perf4(CSOUND *csound, mvclpf24_4 *p){ MYFLT *out0 = p->out0, *out1 = p->out1, *out2 = p->out2, *out3 = p->out3; MYFLT *in = p->in, res; double c1 = p->c1+1e-6, c2 = p->c2, c3 = p->c3, c4 = p->c4, c5 = p->c5, w, x, d; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT scal = csound->Get0dBFS(csound); if (p->fr != *p->freq) { MYFLT fr = log2(*p->freq/CBASE); p->fr = *p->freq; w = exp2ap(fr + 9.70)/csound->GetSr(csound); if (w < 0.75) w *= 1.005 - w * (0.624 - w * (0.65 - w * 0.54)); else { w *= 0.6748; if (w > 0.82) w = 0.82; } p->w = w; } else w = p->w; res = *p->res > FL(0.0) ? (*p->res < FL(1.0) ? *p->res : FL(1.0)) : FL(0.0); if (UNLIKELY(offset)) { memset(out0, '\0', offset*sizeof(MYFLT)); memset(out1, '\0', offset*sizeof(MYFLT)); memset(out2, '\0', offset*sizeof(MYFLT)); memset(out3, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&out0[nsmps], '\0', early*sizeof(MYFLT)); memset(&out1[nsmps], '\0', early*sizeof(MYFLT)); memset(&out2[nsmps], '\0', early*sizeof(MYFLT)); memset(&out3[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset; i < nsmps; i++){ x = in[i]/scal - (4.3 - 0.2 * w) * res * c5 + 1e-10; x /= sqrt (1 + x * x); d = w * (x - c1) / (1 + c1 * c1); x = c1 + 0.77 * d; c1 = x + 0.23 * d; d = w * (x - c2) / (1 + c2 * c2); x = c2 + 0.77 * d; c2 = x + 0.23 * d; d = w * (x - c3) / (1 + c3 * c3); x = c3 + 0.77 * d; c3 = x + 0.23 * d; d = w * (x - c4); x = c4 + 0.77 * d; c4 = x + 0.23 * d; c5 += 0.85 * (c4 - c5); x = in[i]/scal -(4.3 - 0.2 * w) * res * c5; x /= sqrt (1 + x * x); d = w * (x - c1) / (1 + c1 * c1); x = c1 + 0.77 * d; c1 = x + 0.23 * d; d = w * (x - c2) / (1 + c2 * c2); x = c2 + 0.77 * d; c2 = x + 0.23 * d; d = w * (x - c3) / (1 + c3 * c3); x = c3 + 0.77 * d; c3 = x + 0.23 * d; d = w * (x - c4); x = c4 + 0.77 * d; c4 = x + 0.23 * d; c5 += 0.85 * (c4 - c5); out0[i] = c1*scal; out1[i] = c2*scal; out2[i] = c3*scal; out3[i] = c4*scal; } p->c1 = c1; p->c2 = c2; p->c3 = c3; p->c4 = c4; p->c5 = c5; return OK; } int mvclpf24_perf4_ak(CSOUND *csound, mvclpf24_4 *p){ MYFLT *out0 = p->out0, *out1 = p->out1, *out2 = p->out2, *out3 = p->out3; MYFLT *in = p->in, res, *freq = p->freq; double c1 = p->c1+1e-6, c2 = p->c2, c3 = p->c3, c4 = p->c4, c5 = p->c5, w, x, t, d; int wi; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT scal = csound->Get0dBFS(csound); res = *p->res; if (UNLIKELY(offset)) { memset(out0, '\0', offset*sizeof(MYFLT)); memset(out1, '\0', offset*sizeof(MYFLT)); memset(out2, '\0', offset*sizeof(MYFLT)); memset(out3, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&out0[nsmps], '\0', early*sizeof(MYFLT)); memset(&out1[nsmps], '\0', early*sizeof(MYFLT)); memset(&out2[nsmps], '\0', early*sizeof(MYFLT)); memset(&out3[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset; i < nsmps; i++){ t = log2(freq[i]/CBASE) + 9.70; wi = (int) (floor(t)); t -= wi; t = ldexp(1 + t * (0.6930 + t * (0.2416 + t * (0.0517 + t * 0.0137))), wi); w = t/csound->GetSr(csound); if (w < 0.75) w *= 1.005 - w * (0.624 - w * (0.65 - w * 0.54)); else { w *= 0.6748; if (w > 0.82) w = 0.82; } x = in[i]/scal - (4.3 - 0.2 * w) * res * c5 + 1e-10; x /= sqrt (1 + x * x); d = w * (x - c1) / (1 + c1 * c1); x = c1 + 0.77 * d; c1 = x + 0.23 * d; d = w * (x - c2) / (1 + c2 * c2); x = c2 + 0.77 * d; c2 = x + 0.23 * d; d = w * (x - c3) / (1 + c3 * c3); x = c3 + 0.77 * d; c3 = x + 0.23 * d; d = w * (x - c4); x = c4 + 0.77 * d; c4 = x + 0.23 * d; c5 += 0.85 * (c4 - c5); x = in[i]/scal -(4.3 - 0.2 * w) * res * c5; x /= sqrt (1 + x * x); d = w * (x - c1) / (1 + c1 * c1); x = c1 + 0.77 * d; c1 = x + 0.23 * d; d = w * (x - c2) / (1 + c2 * c2); x = c2 + 0.77 * d; c2 = x + 0.23 * d; d = w * (x - c3) / (1 + c3 * c3); x = c3 + 0.77 * d; c3 = x + 0.23 * d; d = w * (x - c4); x = c4 + 0.77 * d; c4 = x + 0.23 * d; c5 += 0.85 * (c4 - c5); out0[i] = c1*scal; out1[i] = c2*scal; out2[i] = c3*scal; out3[i] = c4*scal; } p->c1 = c1; p->c2 = c2; p->c3 = c3; p->c4 = c4; p->c5 = c5; return OK; } int mvclpf24_perf4_ka(CSOUND *csound, mvclpf24_4 *p){ MYFLT *out0 = p->out0, *out1 = p->out1, *out2 = p->out2, *out3 = p->out3; MYFLT *in = p->in, *res = p->res; double c1 = p->c1+1e-6, c2 = p->c2, c3 = p->c3, c4 = p->c4, c5 = p->c5, w, x, d; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT scal = csound->Get0dBFS(csound); if (p->fr != *p->freq) { MYFLT fr = log2(*p->freq/CBASE); p->fr = *p->freq; w = exp2ap(fr + 9.70)/csound->GetSr(csound); if (w < 0.75) w *= 1.005 - w * (0.624 - w * (0.65 - w * 0.54)); else { w *= 0.6748; if (w > 0.82) w = 0.82; } p->w = w; } else w = p->w; if (UNLIKELY(offset)) { memset(out0, '\0', offset*sizeof(MYFLT)); memset(out1, '\0', offset*sizeof(MYFLT)); memset(out2, '\0', offset*sizeof(MYFLT)); memset(out3, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&out0[nsmps], '\0', early*sizeof(MYFLT)); memset(&out1[nsmps], '\0', early*sizeof(MYFLT)); memset(&out2[nsmps], '\0', early*sizeof(MYFLT)); memset(&out3[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset; i < nsmps; i++){ x = in[i]/scal - (4.3 - 0.2 * w) * res[i] * c5 + 1e-10; x /= sqrt (1 + x * x); d = w * (x - c1) / (1 + c1 * c1); x = c1 + 0.77 * d; c1 = x + 0.23 * d; d = w * (x - c2) / (1 + c2 * c2); x = c2 + 0.77 * d; c2 = x + 0.23 * d; d = w * (x - c3) / (1 + c3 * c3); x = c3 + 0.77 * d; c3 = x + 0.23 * d; d = w * (x - c4); x = c4 + 0.77 * d; c4 = x + 0.23 * d; c5 += 0.85 * (c4 - c5); x = in[i]/scal - (4.3 - 0.2 * w) * (res[i] > FL(0.0) ? (res[i] < FL(1.0) ? res[i] : FL(1.0)) : FL(0.0)) * c5 + 1e-10; x /= sqrt (1 + x * x); d = w * (x - c1) / (1 + c1 * c1); x = c1 + 0.77 * d; c1 = x + 0.23 * d; d = w * (x - c2) / (1 + c2 * c2); x = c2 + 0.77 * d; c2 = x + 0.23 * d; d = w * (x - c3) / (1 + c3 * c3); x = c3 + 0.77 * d; c3 = x + 0.23 * d; d = w * (x - c4); x = c4 + 0.77 * d; c4 = x + 0.23 * d; c5 += 0.85 * (c4 - c5); out0[i] = c1*scal; out1[i] = c2*scal; out2[i] = c3*scal; out3[i] = c4*scal; } p->c1 = c1; p->c2 = c2; p->c3 = c3; p->c4 = c4; p->c5 = c5; return OK; } int mvclpf24_perf4_aa(CSOUND *csound, mvclpf24_4 *p){ MYFLT *out0 = p->out0, *out1 = p->out1, *out2 = p->out2, *out3 = p->out3; MYFLT *in = p->in, *res = p->res, *freq = p->freq; double c1 = p->c1+1e-6, c2 = p->c2, c3 = p->c3, c4 = p->c4, c5 = p->c5, w, x, t, d; int wi; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT scal = csound->Get0dBFS(csound); if (UNLIKELY(offset)) { memset(out0, '\0', offset*sizeof(MYFLT)); memset(out1, '\0', offset*sizeof(MYFLT)); memset(out2, '\0', offset*sizeof(MYFLT)); memset(out3, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&out0[nsmps], '\0', early*sizeof(MYFLT)); memset(&out1[nsmps], '\0', early*sizeof(MYFLT)); memset(&out2[nsmps], '\0', early*sizeof(MYFLT)); memset(&out3[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset; i < nsmps; i++){ t = log2(freq[i]/CBASE) + 9.70; wi = (int) (floor(t)); t -= wi; t = ldexp(1 + t * (0.6930 + t * (0.2416 + t * (0.0517 + t * 0.0137))), wi); w = t/csound->GetSr(csound); if (w < 0.75) w *= 1.005 - w * (0.624 - w * (0.65 - w * 0.54)); else { w *= 0.6748; if (w > 0.82) w = 0.82; } x = in[i]/scal - (4.3 - 0.2 * w) * res[i] * c5 + 1e-10; x /= sqrt (1 + x * x); d = w * (x - c1) / (1 + c1 * c1); x = c1 + 0.77 * d; c1 = x + 0.23 * d; d = w * (x - c2) / (1 + c2 * c2); x = c2 + 0.77 * d; c2 = x + 0.23 * d; d = w * (x - c3) / (1 + c3 * c3); x = c3 + 0.77 * d; c3 = x + 0.23 * d; d = w * (x - c4); x = c4 + 0.77 * d; c4 = x + 0.23 * d; c5 += 0.85 * (c4 - c5); x = in[i]/scal - (4.3 - 0.2 * w) * (res[i] > FL(0.0) ? (res[i] < FL(1.0) ? res[i] : FL(1.0)) : FL(0.0)) * c5 + 1e-10; x /= sqrt (1 + x * x); d = w * (x - c1) / (1 + c1 * c1); x = c1 + 0.77 * d; c1 = x + 0.23 * d; d = w * (x - c2) / (1 + c2 * c2); x = c2 + 0.77 * d; c2 = x + 0.23 * d; d = w * (x - c3) / (1 + c3 * c3); x = c3 + 0.77 * d; c3 = x + 0.23 * d; d = w * (x - c4); x = c4 + 0.77 * d; c4 = x + 0.23 * d; c5 += 0.85 * (c4 - c5); out0[i] = c1*scal; out1[i] = c2*scal; out2[i] = c3*scal; out3[i] = c4*scal; } p->c1 = c1; p->c2 = c2; p->c3 = c3; p->c4 = c4; p->c5 = c5; return OK; } #define PEAKHCF FL(1.4) typedef struct _mvcfh { OPDS h; MYFLT *out; MYFLT *in, *freq, *skipinit; double c1, c2, c3, c4, c5; double fr, w, x; } mvchpf24; int mvchpf24_init(CSOUND *csound, mvchpf24 *p){ if (!*p->skipinit){ p->c1 = p->c2 = p->c3 = p->c4 = p->c5 = p->x = FL(0.0); p->fr = FL(0.0); } return OK; } int mvchpf24_perf(CSOUND *csound, mvchpf24 *p){ MYFLT *out = p->out; MYFLT *in = p->in; double c1 = p->c1+1e-6, c2 = p->c2, c3 = p->c3, c4 = p->c4, c5 = p->c5, w, x = p->x, t, d, y; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT scal = csound->Get0dBFS(csound); if (p->fr != *p->freq) { MYFLT fr = log2(*p->freq/CBASE); p->fr = *p->freq; w = csound->GetSr(csound)/exp2ap(fr+ 9.2); if (w < FL(2.0)) w = FL(2.0); p->w = w; } else w = p->w; if (UNLIKELY(offset)) { memset(out, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset; i < nsmps; i++){ x = y = in[i]/scal - 0.3 * x; d = x - c1 + 1e-10; t = d * d; d *= (1 + t) / (w + t); c1 += d; x -= c1; c1 += d; d = x - c2 + 1e-10; t = d * d; d *= (1 + t) / (w + t); c2 += d; x -= c2; c2 += d; d = x - c3 + 1e-10; t = d * d; d *= (1 + t) / (w + t); c3 += d; x -= c3; c3 += d; d = x - c4 + 1e-10; t = d * d; d *= (1 + t) / (w + t); c4 += d; x -= c4; c4 += d; out[i] = scal*x/PEAKHCF; x -= y; } p->c1 = c1; p->c2 = c2; p->c3 = c3; p->c4 = c4; p->c5 = c5; p->x = x; return OK; } int mvchpf24_perf_a(CSOUND *csound, mvchpf24 *p){ MYFLT *out = p->out; MYFLT *in = p->in, *freq = p->freq; double c1 = p->c1+1e-6, c2 = p->c2, c3 = p->c3, c4 = p->c4, c5 = p->c5, w, x = p->x, t, d, y; int wi; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT scal = csound->Get0dBFS(csound); if (UNLIKELY(offset)) { memset(out, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset; i < nsmps; i++){ t = log2(freq[i]/CBASE) + 9.70; wi = (int) (floor(t)); t -= wi; t = ldexp(1 + t * (0.6930 + t * (0.2416 + t * (0.0517 + t * 0.0137))), wi); w = csound->GetSr(csound)/t; if (w < FL(2.0)) w = FL(2.0); x = y = in[i]/scal - 0.3 * x; d = x - c1 + 1e-10; t = d * d; d *= (1 + t) / (w + t); c1 += d; x -= c1; c1 += d; d = x - c2 + 1e-10; t = d * d; d *= (1 + t) / (w + t); c2 += d; x -= c2; c2 += d; d = x - c3 + 1e-10; t = d * d; d *= (1 + t) / (w + t); c3 += d; x -= c3; c3 += d; d = x - c4 + 1e-10; t = d * d; d *= (1 + t) / (w + t); c4 += d; x -= c4; c4 += d; out[i] = scal*x/PEAKHCF; x -= y; } p->c1 = c1; p->c2 = c2; p->c3 = c3; p->c4 = c4; p->c5 = c5; p->x = x; return OK; } static OENTRY localops[] = { {"mvchpf", sizeof(mvchpf24), 0, 5, "a", "akp", (SUBR) mvchpf24_init, NULL, (SUBR) mvchpf24_perf}, {"mvchpf", sizeof(mvchpf24), 0, 5, "a", "aap", (SUBR) mvchpf24_init, NULL, (SUBR) mvchpf24_perf_a}, {"mvclpf1", sizeof(mvclpf24), 0, 5, "a", "akkp", (SUBR) mvclpf24_init, NULL, (SUBR) mvclpf24_perf1}, {"mvclpf1", sizeof(mvclpf24), 0, 5, "a", "aakp", (SUBR) mvclpf24_init, NULL, (SUBR) mvclpf24_perf1_ak}, {"mvclpf1", sizeof(mvclpf24), 0, 5, "a", "akap", (SUBR) mvclpf24_init, NULL, (SUBR) mvclpf24_perf1_ka}, {"mvclpf1", sizeof(mvclpf24), 0, 5, "a", "aaap", (SUBR) mvclpf24_init, NULL, (SUBR) mvclpf24_perf1_aa}, {"mvclpf2", sizeof(mvclpf24), 0, 5, "a", "akkp", (SUBR) mvclpf24_init, NULL, (SUBR) mvclpf24_perf2}, {"mvclpf2", sizeof(mvclpf24), 0, 5, "a", "aakp", (SUBR) mvclpf24_init, NULL, (SUBR) mvclpf24_perf2_ak}, {"mvclpf2", sizeof(mvclpf24), 0, 5, "a", "akap", (SUBR) mvclpf24_init, NULL, (SUBR) mvclpf24_perf2_ka}, {"mvclpf2", sizeof(mvclpf24), 0, 5, "a", "aaap", (SUBR) mvclpf24_init, NULL, (SUBR) mvclpf24_perf2_aa}, {"mvclpf3", sizeof(mvclpf24), 0, 5, "a", "akkp", (SUBR) mvclpf24_init, NULL, (SUBR) mvclpf24_perf3}, {"mvclpf3", sizeof(mvclpf24), 0, 5, "a", "aakp", (SUBR) mvclpf24_init, NULL, (SUBR) mvclpf24_perf3_ak}, {"mvclpf3", sizeof(mvclpf24), 0, 5, "a", "akap", (SUBR) mvclpf24_init, NULL, (SUBR) mvclpf24_perf3_ka}, {"mvclpf3", sizeof(mvclpf24), 0, 5, "a", "aaap", (SUBR) mvclpf24_init, NULL, (SUBR) mvclpf24_perf3_aa}, {"mvclpf4", sizeof(mvclpf24_4), 0, 5, "aaaa", "akkp", (SUBR) mvclpf24_4_init, NULL, (SUBR) mvclpf24_perf4}, {"mvclpf4", sizeof(mvclpf24), 0, 5, "aaaa", "aakp", (SUBR) mvclpf24_init, NULL, (SUBR) mvclpf24_perf4_ak}, {"mvclpf4", sizeof(mvclpf24), 0, 5, "aaaa", "akap", (SUBR) mvclpf24_init, NULL, (SUBR) mvclpf24_perf4_ka}, {"mvclpf4", sizeof(mvclpf24), 0, 5, "aaaa", "aaap", (SUBR) mvclpf24_init, NULL, (SUBR) mvclpf24_perf4_aa}, {"moogladder.kk", sizeof(moogladder), 0, 5, "a", "akkp", (SUBR) moogladder_init, NULL, (SUBR) moogladder_process }, {"moogladder.aa", sizeof(moogladder), 0, 5, "a", "aaap", (SUBR) moogladder_init, NULL, (SUBR) moogladder_process_aa }, {"moogladder.ak", sizeof(moogladder), 0, 5, "a", "aakp", (SUBR) moogladder_init, NULL, (SUBR) moogladder_process_ak }, {"moogladder.ka", sizeof(moogladder), 0, 5, "a", "akap", (SUBR) moogladder_init, NULL, (SUBR) moogladder_process_ka }, {"moogladder2.kk", sizeof(moogladder), 0, 5, "a", "akkp", (SUBR) moogladder_init, NULL, (SUBR) moogladder2_process }, {"moogladder2.aa", sizeof(moogladder), 0, 5, "a", "aaap", (SUBR) moogladder_init, NULL, (SUBR) moogladder2_process_aa }, {"moogladder2.ak", sizeof(moogladder), 0, 5, "a", "aakp", (SUBR) moogladder_init, NULL, (SUBR) moogladder2_process_ak }, {"moogladder2.ka", sizeof(moogladder), 0, 5, "a", "akap", (SUBR) moogladder_init, NULL, (SUBR) moogladder2_process_ka }, {"statevar", sizeof(statevar), 0, 5, "aaaa", "axxop", (SUBR) statevar_init, NULL, (SUBR) statevar_process }, {"fofilter", sizeof(fofilter), 0, 5, "a", "axxxp", (SUBR) fofilter_init, NULL, (SUBR) fofilter_process } }; int newfils_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/newfils.h000066400000000000000000000103411321653344700163140ustar00rootroot00000000000000/* newfils.h: Filter opcodes (c) Victor Lazzarini, 2004 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* MOOGLADDER: asig moogladder ain, kcf, kres[, istor] A new implementation of the Moog ladder filter, based on Antti Huovilainen's design (Huovilainen, A. "Non-linear Digital Implementation of the Moog Ladder Filter". DAFX 2004, Napoli). ain: input signal. kcf: lowpass cuttoff frequency (Hz). kres: resonance, generally < 1, but not limited to it. Higher than 1 resonance values might cause aliasing, analogue synths generally allow resonances to be above 1. istor: defaults to 1, initialise the internal delay buffers on startup. 0 means no initialisation. STATEVAR: ahp,alp,abp,abr statevar ain, kcf, kq [, iosamps, istor] A digital implementation of the analogue state-variable filter. This filter has four simultaneous outputs: high-pass, low-pass, band-pass and band-reject. ahp: high-pass output alp: low-pass output abp: band-pass output abr: band-reject output ain: input signal kcf: filter frequency (Hz) kq: filter Q. This value is limited internally depending on the frequency and the number of times of oversampling used in the process (3-times oversampling by default). iosamps: number of times of oversampling used in the filtering process. This will determine the maximum sharpness of the filter resonance (Q). More oversampling allows higher Qs, less oversampling will limit the resonance. The default is 3 times (iosamps=0). istor: defaults to 1, initialise the internal delay buffers on startup. 0 means no initialisation. FOFILTER: ar fofilter asig, kcf, kris, kdec[,istor] This filter generates a stream of overlapping sinewave grains, when fed with a pulse train. Each grain is the impulse response of a combination of two BP filters. The grains are defined by their attack time (determining the skirtwidth of the formant region at -60dB) and decay time (-6dB bandwidth). Overlapping will occur when 1/freq < decay, but, unlike FOF, there is no upper limit on the number of overlaps. The original idea for this opcode came from J McCartney's formlet class in SuperCollider, but this is possibly implemented differently(?). asig: input signal kcf: formant center frequency (Hz) kris: impulse response attack time (secs) kdec: impulse response decay time (to -60dB, in secs) istor: defaults to 1, initialise the internal delay buffers on startup. 0 means no initialisation. */ #ifndef _NEWFILS_H #define _NEWFILS_H typedef struct _moogladder { OPDS h; MYFLT *out; MYFLT *in; MYFLT *freq; MYFLT *res; MYFLT *istor; double delay[6]; double tanhstg[3]; MYFLT oldfreq; MYFLT oldres; double oldacr; double oldtune; } moogladder; static int moogladder_init(CSOUND *csound,moogladder *p); static int moogladder_process(CSOUND *csound,moogladder *p); typedef struct _statevar { OPDS h; MYFLT *outhp; MYFLT *outlp; MYFLT *outbp; MYFLT *outbr; MYFLT *in; MYFLT *freq; MYFLT *res; MYFLT *osamp; MYFLT *istor; double bpd; double lpd; double lp; int ostimes; MYFLT oldfreq; MYFLT oldres; double oldq; double oldf; } statevar; static int statevar_init(CSOUND *csound,statevar *p); static int statevar_process(CSOUND *csound,statevar *p); typedef struct _fofilter { OPDS h; MYFLT *out; MYFLT *in; MYFLT *freq; MYFLT *ris; MYFLT *dec; MYFLT *istor; double delay[4]; } fofilter; static int fofilter_init(CSOUND *csound,fofilter *p); static int fofilter_process(CSOUND *csound,fofilter *p); #endif csound-6.10.0/Opcodes/nlfilt.c000066400000000000000000000214441321653344700161360ustar00rootroot00000000000000/* nlfilt.c: Copyright (C) 1996 John ffitch, Richard Dobson This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Y{n} =a Y{n-1} + b Y{n-2} + d Y^2{n-L} + X{n} - C */ /***************************************************************\ * nlfilt.c * * Non-linear filter (Excitable region) * * 5 June 1996 John ffitch * * See paper by Dobson and ffitch, ICMC'96 * \***************************************************************/ #include "stdopcod.h" #include "nlfilt.h" typedef struct { OPDS h; MYFLT *ians; MYFLT *index; } PFIELD; typedef struct { OPDS h; MYFLT *inits[24]; MYFLT *start; } PINIT; #define MAX_DELAY (1024) #define MAXAMP (FL(64000.0)) static int nlfiltset(CSOUND *csound, NLFILT *p) { if (p->delay.auxp == NULL || p->delay.sizeAuxAlloc(csound, MAX_DELAY * sizeof(MYFLT), &p->delay); } else { memset(p->delay.auxp, 0, MAX_DELAY * sizeof(MYFLT)); } p->point = 0; return OK; } /* end nlfset(p) */ static int nlfilt(CSOUND *csound, NLFILT *p) { MYFLT *ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int point = p->point; int nm1 = point; int nm2 = point - 1; int nmL; MYFLT ynm1, ynm2, ynmL; MYFLT a = *p->a, b = *p->b, d = *p->d, C = *p->C; MYFLT *in = p->in; MYFLT *fp = (MYFLT*) p->delay.auxp; MYFLT L = *p->L; MYFLT maxamp, dvmaxamp, maxampd2; if (UNLIKELY(fp == NULL)) goto err1; /* RWD fix */ ar = p->ar; /* L is k-rate so need to check */ if (L < FL(1.0)) L = FL(1.0); else if (L >= MAX_DELAY) { L = (MYFLT) MAX_DELAY; } nmL = point - (int) (L) - 1; if (UNLIKELY(nm1 < 0)) nm1 += MAX_DELAY; /* Deal with the wrapping */ if (UNLIKELY(nm2 < 0)) nm2 += MAX_DELAY; if (UNLIKELY(nmL < 0)) nmL += MAX_DELAY; ynm1 = fp[nm1]; /* Pick up running values */ ynm2 = fp[nm2]; ynmL = fp[nmL]; maxamp = csound->e0dbfs * FL(1.953125); /* 64000 with default 0dBFS */ dvmaxamp = FL(1.0) / maxamp; maxampd2 = maxamp * FL(0.5); if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; n maxamp) out = maxampd2; else if (out < -maxamp) out = -maxampd2; ar[n] = out; if (UNLIKELY(++point == MAX_DELAY)) { point = 0; } fp[point] = yn; /* and delay line */ if (UNLIKELY(++nmL == MAX_DELAY)) { nmL = 0; } ynm2 = ynm1; /* Shuffle along */ ynm1 = yn; ynmL = fp[nmL]; } p->point = point; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("nlfilt: not initialised")); } /* end nlfilt(p) */ /* Y{n} = a Y{n-1} + b Y{n-2} + d Y^2{n-L} + X{n} - C */ /* Revised version due to Risto Holopainen 12 Mar 2004 */ /* Y{n} =tanh(a Y{n-1} + b Y{n-2} + d Y^2{n-L} + X{n} - C) */ static int nlfilt2(CSOUND *csound, NLFILT *p) { MYFLT *ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int point = p->point; int nm1 = point; int nm2 = point - 1; int nmL; MYFLT ynm1, ynm2, ynmL; MYFLT a = *p->a, b = *p->b, d = *p->d, C = *p->C; MYFLT *in = p->in; MYFLT *fp = (MYFLT*) p->delay.auxp; MYFLT L = *p->L; MYFLT maxamp, dvmaxamp, maxampd2; if (UNLIKELY(fp == NULL)) goto err1; /* RWD fix */ ar = p->ar; /* L is k-rate so need to check */ if (L < FL(1.0)) L = FL(1.0); else if (L >= MAX_DELAY) { L = (MYFLT) MAX_DELAY; } nmL = point - (int) (L) - 1; if (UNLIKELY(nm1 < 0)) nm1 += MAX_DELAY; /* Deal with the wrapping */ if (UNLIKELY(nm2 < 0)) nm2 += MAX_DELAY; if (UNLIKELY(nmL < 0)) nmL += MAX_DELAY; ynm1 = fp[nm1]; /* Pick up running values */ ynm2 = fp[nm2]; ynmL = fp[nmL]; nsmps = CS_KSMPS; maxamp = csound->e0dbfs * FL(1.953125); /* 64000 with default 0dBFS */ dvmaxamp = FL(1.0) / maxamp; maxampd2 = maxamp * FL(0.5); if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; n maxamp) out = maxampd2; else if (out < -maxamp) out = -maxampd2; ar[n] = out; if (UNLIKELY(++point == MAX_DELAY)) { point = 0; } yn = TANH(yn); fp[point] = yn; /* and delay line */ if (UNLIKELY(++nmL == MAX_DELAY)) { nmL = 0; } ynm2 = ynm1; /* Shuffle along */ ynm1 = yn; ynmL = fp[nmL]; } p->point = point; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("nlfilt2: not initialised")); } /* end nlfilt2(p) */ /* ***************************************************************** */ /* ***************************************************************** */ /* ***************************************************************** */ /* ***************************************************************** */ /* icnt pcnt */ /* ival pfld indx */ int pcount(CSOUND *csound, PFIELD *p) { *p->ians = (MYFLT) csound->currevent->pcnt; return OK; } int pvalue(CSOUND *csound, PFIELD *p) { int n = (int)(*p->index); if (UNLIKELY(csound->currevent==NULL || n<1 || n>csound->currevent->pcnt)) { *p->ians = FL(0.0); /* For tidyness */ return NOTOK; /* Should this be an error?? */ } *p->ians = csound->currevent->p[n]; return OK; } int pinit(CSOUND *csound, PINIT *p) { int n; int x = 1; int nargs = p->OUTOCOUNT; int pargs = csound->currevent->pcnt; int start = (int)(*p->start); /* Should check that inits exist> */ if (UNLIKELY(nargs>pargs)) csound->Warning(csound, Str("More arguments than p fields")); for (n=0; (nISSTRCOD(csound->currevent->p[n+start])) { ((STRINGDAT *)p->inits[n])->data = cs_strdup(csound, get_arg_string(csound, csound->currevent->p[n+start])); ((STRINGDAT *)p->inits[n])->size = strlen(((STRINGDAT *)p->inits[n])->data)+1; } else *p->inits[n] = csound->currevent->p[n+start]; x <<= 1; } return OK; } #define S(x) sizeof(x) static OENTRY localops[] = { { "pcount", S(PFIELD), 0, 1, "i", "", (SUBR)pcount, NULL, NULL }, { "pindex", S(PFIELD), 0, 1, "i", "i", (SUBR)pvalue, NULL, NULL }, { "passign", S(PINIT), 0, 1, "IIIIIIIIIIIIIIIIIIIIIIII", "p", (SUBR)pinit, NULL, NULL }, { "nlfilt", S(NLFILT), 0, 5, "a", "akkkkk", (SUBR)nlfiltset, NULL, (SUBR)nlfilt }, { "nlfilt2", S(NLFILT), 0, 5, "a", "akkkkk", (SUBR)nlfiltset, NULL, (SUBR)nlfilt2 } }; int nlfilt_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/nlfilt.h000066400000000000000000000022051321653344700161350ustar00rootroot00000000000000/* nlfilt.h: Copyright (C) 1996 John ffitch, Richard Dobson This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Structure for Dobson/Fitch nonlinear filter */ typedef struct { OPDS h; MYFLT *ar, *in, *a, *b, *d, *C, *L; /* The parameter */ AUXCH delay; /* Buffer for old values */ int point; /* Pointer to old values */ } NLFILT; csound-6.10.0/Opcodes/opencl/000077500000000000000000000000001321653344700157555ustar00rootroot00000000000000csound-6.10.0/Opcodes/opencl/CMakeLists.txt000066400000000000000000000021011321653344700205070ustar00rootroot00000000000000option(BUILD_OPENCL_OPCODES "Build the OpenCL parallel opcodes" OFF) if(BUILD_OPENCL_OPCODES) find_library (OpenCL_library NAMES OpenCL) if(BUILD_OPENCL_OPCODES) function(make_opencl_plugin libname srcs) if(APPLE) add_library(${libname} SHARED ${srcs}) else() add_library(${libname} MODULE ${srcs}) endif() set(i 2) while( ${i} LESS ${ARGC} ) if(NOT MSVC OR NOT("${ARGV${i}}" MATCHES "m")) target_link_libraries(${libname} ${ARGV${i}}) endif() math(EXPR i "${i}+1") endwhile() set_target_properties(${libname} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${BUILD_PLUGINS_DIR} LIBRARY_OUTPUT_DIRECTORY ${BUILD_PLUGINS_DIR} ARCHIVE_OUTPUT_DIRECTORY ${BUILD_PLUGINS_DIR}) install(TARGETS ${libname} LIBRARY DESTINATION "${PLUGIN_INSTALL_DIR}" ) endfunction(make_opencl_plugin) include_directories(${CMAKE_HOME_DIRECTORY}/include) include_directories(/usr/local/include) make_opencl_plugin(clop cladsynth.c) target_link_libraries(clop ${OpenCL_library}) endif() endif() csound-6.10.0/Opcodes/opencl/build.sh000066400000000000000000000001651321653344700174120ustar00rootroot00000000000000gcc -O3 -dynamiclib -o libclop1.dylib -DUSE_DOUBLE -D_FORTIFY_SOURCE=0 cladsynth.c -I../../include -framework OpenCL csound-6.10.0/Opcodes/opencl/cladsyn.csd000066400000000000000000000012231321653344700201030ustar00rootroot00000000000000 --opcode-lib=./libclop1.dylib ksmps = 64 0dbfs = 1 instr 1 ifftsize = 2048 ihopsize = 512 ibins = 1024 idev = 0 ; /* device number */ asig1 vco2 0.5, 440 fsig = pvsanal(asig1, ifftsize,ihopsize, ifftsize, 1) asig = cladsynth(fsig,1,1,ibins,idev) asig = linenr(asig,0.001,0.01,0.01) out(asig*0.5) endin instr 2 ifftsize = 2048 ihopsize = 512 ibins = 1024 asig1 vco2 0.5, 440 fsig = pvsanal(asig1, ifftsize,ihopsize, ifftsize, 1) asig = pvsadsyn(fsig,ibins,1) asig = linenr(asig,0.001,0.01,0.01) out(asig*0.5) endin i1 0 60 csound-6.10.0/Opcodes/opencl/cladsynth.c000066400000000000000000000356461321653344700201300ustar00rootroot00000000000000/* cladsynth.c (c) Victor Lazzarini, 2014 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #ifdef __MACH__ #include #else #include #endif const char *code = "#define FMAXLEN ((float)0x40000000) \n" "#define PHMASK 0x3fffffff \n" "#define PI 3.1415926f\n" "inline void AtomicAdd(volatile __global float *source, const float operand) {\n" " union {\n" " unsigned int intVal;\n" " float floatVal;\n" " } newVal;\n" " union {\n" " unsigned int intVal;\n" " float floatVal;\n" " } prevVal;\n" " do {\n" " prevVal.floatVal = *source;\n" " newVal.floatVal = prevVal.floatVal + operand;\n" " } while (atomic_cmpxchg((volatile __global unsigned int *)source, \n" " prevVal.intVal, newVal.intVal) != prevVal.intVal);\n" "}\n" "kernel void sample(global float *out, global float *frame, \n" " global long *ph,\n" " global float *amps, float pitch, int bins, \n" " int vsize, float sr) {\n" " int t = get_global_id(0);\n" " int n = t%vsize; /* sample index */\n" " int h = t/vsize; /* bin index */\n" " int k = h<<1;\n" " long lph;\n" " float a = amps[h], ascl = ((float)n)/vsize;\n" " float fscal = pitch*FMAXLEN/sr;\n" " lph = (ph[h] + (long)(n*round(frame[k+1]*fscal))) & PHMASK;\n" " a += ascl*(frame[k] - a);\n" " AtomicAdd(&out[n], a*sin((2*PI*lph)/FMAXLEN));\n" "}\n" "kernel void update(global float *out, global float *frame,\n" " global long *ph, global float *amps, float pitch, int bins, \n" " int vsize, float sr){\n" " int h = get_global_id(0);\n" " int k = h << 1,i,j;\n" " /* update phases and amps */\n" " ph[h] = (ph[h] + (long)(vsize*round(pitch*frame[k+1]*FMAXLEN/sr))) & PHMASK;\n" " amps[h] = frame[k];\n" " if(h >= vsize) return;\n" " out[h] = 0.f;\n" "}\n" " \n"; typedef struct cladsyn_ { OPDS h; MYFLT *asig; PVSDAT *fsig; MYFLT *kamp, *kfreq; MYFLT *inum, *idev; cl_mem out; cl_mem frame; cl_mem ph; float *fp; cl_mem amps; AUXCH out_; int bins; size_t threads; int count; int vsamps; size_t mthreads; int framecount; cl_context context; cl_command_queue commands; cl_program program; cl_kernel kernel1, kernel2; size_t wgs1, wgs2; float sr; } CLADSYN; char * cl_error_string(int err) { switch (err) { case CL_SUCCESS: return "Success!"; case CL_DEVICE_NOT_FOUND: return "Device not found."; case CL_DEVICE_NOT_AVAILABLE: return "Device not available"; case CL_COMPILER_NOT_AVAILABLE: return "Compiler not available"; case CL_MEM_OBJECT_ALLOCATION_FAILURE: return "Memory object allocation failure"; case CL_OUT_OF_RESOURCES: return "Out of resources"; case CL_OUT_OF_HOST_MEMORY: return "Out of host memory"; case CL_PROFILING_INFO_NOT_AVAILABLE: return "Profiling information not available"; case CL_MEM_COPY_OVERLAP: return "Memory copy overlap"; case CL_IMAGE_FORMAT_MISMATCH: return "Image format mismatch"; case CL_IMAGE_FORMAT_NOT_SUPPORTED: return "Image format not supported"; case CL_BUILD_PROGRAM_FAILURE: return "Program build failure"; case CL_MAP_FAILURE: return "Map failure"; case CL_INVALID_VALUE: return "Invalid value"; case CL_INVALID_DEVICE_TYPE: return "Invalid device type"; case CL_INVALID_PLATFORM: return "Invalid platform"; case CL_INVALID_DEVICE: return "Invalid device"; case CL_INVALID_CONTEXT: return "Invalid context"; case CL_INVALID_QUEUE_PROPERTIES: return "Invalid queue properties"; case CL_INVALID_COMMAND_QUEUE: return "Invalid command queue"; case CL_INVALID_HOST_PTR: return "Invalid host pointer"; case CL_INVALID_MEM_OBJECT: return "Invalid memory object"; case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR: return "Invalid image format descriptor"; case CL_INVALID_IMAGE_SIZE: return "Invalid image size"; case CL_INVALID_SAMPLER: return "Invalid sampler"; case CL_INVALID_BINARY: return "Invalid binary"; case CL_INVALID_BUILD_OPTIONS: return "Invalid build options"; case CL_INVALID_PROGRAM: return "Invalid program"; case CL_INVALID_PROGRAM_EXECUTABLE: return "Invalid program executable"; case CL_INVALID_KERNEL_NAME: return "Invalid kernel name"; case CL_INVALID_KERNEL_DEFINITION: return "Invalid kernel definition"; case CL_INVALID_KERNEL: return "Invalid kernel"; case CL_INVALID_ARG_INDEX: return "Invalid argument index"; case CL_INVALID_ARG_VALUE: return "Invalid argument value"; case CL_INVALID_ARG_SIZE: return "Invalid argument size"; case CL_INVALID_KERNEL_ARGS: return "Invalid kernel arguments"; case CL_INVALID_WORK_DIMENSION: return "Invalid work dimension"; case CL_INVALID_WORK_GROUP_SIZE: return "Invalid work group size"; case CL_INVALID_WORK_ITEM_SIZE: return "Invalid work item size"; case CL_INVALID_GLOBAL_OFFSET: return "Invalid global offset"; case CL_INVALID_EVENT_WAIT_LIST: return "Invalid event wait list"; case CL_INVALID_EVENT: return "Invalid event"; case CL_INVALID_OPERATION: return "Invalid operation"; case CL_INVALID_GL_OBJECT: return "Invalid OpenGL object"; case CL_INVALID_BUFFER_SIZE: return "Invalid buffer size"; case CL_INVALID_MIP_LEVEL: return "Invalid mip-map level"; default: return "Unknown error"; } } static int destroy_cladsyn(CSOUND *csound, void *pp); static int init_cladsyn(CSOUND *csound, CLADSYN *p){ int asize, ipsize, fpsize, err; cl_device_id device_ids[32], device_id; cl_context context; cl_command_queue commands; cl_program program; cl_kernel kernel1, kernel2; cl_uint num = 0, nump = 0; cl_platform_id platforms[16]; uint32_t i; if(p->fsig->overlap > 1024) return csound->InitError(csound, "overlap is too large\n"); err = clGetDeviceIDs(NULL, CL_DEVICE_TYPE_ALL, 32, device_ids, &num); if (err != CL_SUCCESS){ clGetPlatformIDs(16, platforms, &nump); int devs = 0; for(i=0; i < nump && devs < 32; i++){ char name[128]; clGetPlatformInfo(platforms[i], CL_PLATFORM_NAME, 128, name, NULL); csound->Message(csound, "available platform[%d] %s\n",i, name); err = clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_ALL, 32-devs, &device_ids[devs], &num); if (err != CL_SUCCESS) csound->InitError(csound, "failed to find an OpenCL device! %s \n", cl_error_string(err)); } devs += num; } for(i=0; i < num; i++){ char name[128]; cl_device_type type; clGetDeviceInfo(device_ids[i], CL_DEVICE_NAME, 128, name, NULL); clGetDeviceInfo(device_ids[i], CL_DEVICE_TYPE, sizeof(cl_device_type), &type, NULL); if(type & CL_DEVICE_TYPE_CPU) csound->Message(csound, "available CPU[device %d] %s\n",i, name); else if(type & CL_DEVICE_TYPE_GPU) csound->Message(csound, "available GPU[device %d] %s\n",i, name); else if(type & CL_DEVICE_TYPE_ACCELERATOR) csound->Message(csound, "available ACCELLERATOR[device %d] %s\n",i, name); else csound->Message(csound, "available generic [device %d] %s\n",i, name);; } // SELECT THE GPU HERE if(*p->idev < num) device_id = device_ids[(int)*p->idev]; else device_id = device_ids[num-1]; context = clCreateContext(0, 1, &device_id, NULL, NULL, &err); if (!context) return csound->InitError(csound, "Failed to create a compute context! %s\n", cl_error_string(err)); // Create a command commands // commands = clCreateCommandQueue(context, device_id, 0, &err); if (!commands) return csound->InitError(csound, "Failed to create a command commands! %s\n", cl_error_string(err)); // Create the compute program from the source buffer // program = clCreateProgramWithSource(context, 1, (const char **) &code, NULL, &err); if (!program) return csound->InitError(csound, "Failed to create compute program! %s\n", cl_error_string(err)); err = clBuildProgram(program, 0, NULL, NULL, NULL, NULL); if (err != CL_SUCCESS) { size_t len; char buffer[2048]; csound->Message(csound, "Failed to build program executable! %s\n", cl_error_string(err)); clGetProgramBuildInfo(program, device_id, CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, &len); return csound->InitError(csound, "%s\n", buffer); } kernel1 = clCreateKernel(program, "sample", &err); if (!kernel1 || err != CL_SUCCESS) return csound->InitError(csound, "Failed to create sample compute kernel! %s\n", cl_error_string(err)); kernel2 = clCreateKernel(program, "update", &err); if (!kernel2 || err != CL_SUCCESS) return csound->InitError(csound, "Failed to create update compute kernel! %s\n", cl_error_string(err)); char name[128]; clGetDeviceInfo(device_id, CL_DEVICE_NAME, 128, name, NULL); csound->Message(csound, "using device: %s\n",name); p->bins = (p->fsig->N)/2; if(*p->inum > 0 && *p->inum < p->bins) p->bins = *p->inum; p->vsamps = p->fsig->overlap; p->threads = p->bins*p->vsamps; p->mthreads = (p->bins > p->vsamps ? p->bins : p->vsamps); asize = p->vsamps*sizeof(cl_float); ipsize = (p->bins > p->vsamps ? p->bins : p->vsamps)*sizeof(cl_long); fpsize = p->fsig->N*sizeof(cl_float); p->out = clCreateBuffer(context,0, asize, NULL, NULL); p->frame = clCreateBuffer(context, CL_MEM_READ_ONLY, fpsize, NULL, NULL); p->ph = clCreateBuffer(context,0, ipsize, NULL, NULL); p->amps = clCreateBuffer(context,0,(p->bins > p->vsamps ? p->bins : p->vsamps)*sizeof(cl_float), NULL, NULL); // memset needed? asize = p->vsamps*sizeof(float); if(p->out_.auxp == NULL || p->out_.size < (unsigned long) asize) csound->AuxAlloc(csound, asize , &p->out_); csound->RegisterDeinitCallback(csound, p, destroy_cladsyn); p->count = 0; p->context = context; p->program = program; p->commands = commands; p->kernel1 = kernel1; p->kernel2 = kernel2; clGetKernelWorkGroupInfo(p->kernel1, device_id, CL_KERNEL_WORK_GROUP_SIZE, sizeof(p->wgs1), &p->wgs1, NULL); clGetKernelWorkGroupInfo(p->kernel2, device_id, CL_KERNEL_WORK_GROUP_SIZE, sizeof(p->wgs1), &p->wgs2, NULL); p->sr = csound->GetSr(csound); clSetKernelArg(p->kernel1, 0, sizeof(cl_mem), &p->out); clSetKernelArg(p->kernel1, 1, sizeof(cl_mem), &p->frame); clSetKernelArg(p->kernel1, 2, sizeof(cl_mem), &p->ph); clSetKernelArg(p->kernel1, 3, sizeof(cl_mem), &p->amps); clSetKernelArg(p->kernel1, 5, sizeof(cl_int), &p->bins); clSetKernelArg(p->kernel1, 6, sizeof(cl_int), &p->vsamps); clSetKernelArg(p->kernel1, 7, sizeof(cl_float), &p->sr); clSetKernelArg(p->kernel2, 0, sizeof(cl_mem), &p->out); clSetKernelArg(p->kernel2, 1, sizeof(cl_mem), &p->frame); clSetKernelArg(p->kernel2, 2, sizeof(cl_mem), &p->ph); clSetKernelArg(p->kernel2, 3, sizeof(cl_mem), &p->amps); clSetKernelArg(p->kernel2, 5, sizeof(cl_int), &p->bins); clSetKernelArg(p->kernel2, 6, sizeof(cl_int), &p->vsamps); clSetKernelArg(p->kernel2, 7, sizeof(cl_float), &p->sr); return OK; } static int perf_cladsyn(CSOUND *csound, CLADSYN *p){ uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; float *out_ = (float *) p->out_.auxp; MYFLT *asig = p->asig; int count = p->count, vsamps = p->vsamps; p->fp = (float *) (p->fsig->frame.auxp); if (UNLIKELY(offset)) memset(asig, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&asig[nsmps], '\0', early*sizeof(MYFLT)); } for(n=offset; n < nsmps; n++){ if(count == 0) { int err; float freq = *p->kfreq; clSetKernelArg(p->kernel1, 4, sizeof(cl_float), &freq); clSetKernelArg(p->kernel2, 4, sizeof(cl_float), &freq); clEnqueueWriteBuffer(p->commands,p->frame, CL_TRUE, 0, sizeof(cl_float)*p->bins*2, p->fp, 0, NULL, NULL); err = clEnqueueNDRangeKernel(p->commands,p->kernel1, 1, NULL, &p->threads, &p->wgs1, 0, NULL, NULL); if(err) csound->Message(csound,"Error: Failed to compute sample kernel! %s\n", cl_error_string(err)); clFinish(p->commands); clEnqueueReadBuffer(p->commands,p->out, CL_TRUE, 0,vsamps*sizeof(cl_float),out_, 0, NULL, NULL); err = clEnqueueNDRangeKernel(p->commands,p->kernel2, 1, NULL, &p->mthreads, &p->wgs2, 0, NULL, NULL); if(err) csound->Message(csound,"Error: Failed to compute update kernel!%s\n", cl_error_string(err)); count = vsamps; } asig[n] = (MYFLT) out_[vsamps - count]; count--; } p->count = count; return OK; } static int destroy_cladsyn(CSOUND *csound, void *pp){ CLADSYN *p = (CLADSYN *) pp; clReleaseMemObject(p->out); clReleaseMemObject(p->ph); clReleaseMemObject(p->frame); clReleaseMemObject(p->amps); clReleaseProgram(p->program); clReleaseKernel(p->kernel1); clReleaseKernel(p->kernel2); clReleaseCommandQueue(p->commands); clReleaseContext(p->context); return OK; } static OENTRY localops[] = { {"cladsynth", sizeof(CLADSYN),0, 5, "a", "fkkoo", (SUBR) init_cladsyn, NULL, (SUBR) perf_cladsyn} }; LINKAGE csound-6.10.0/Opcodes/oscbnk.c000066400000000000000000002651211321653344700161270ustar00rootroot00000000000000/* oscbnk.c: Copyright (C) 2002, 2005 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "stdopcod.h" #include "oscbnk.h" #include static inline STDOPCOD_GLOBALS *get_oscbnk_globals(CSOUND *csound) { return ((STDOPCOD_GLOBALS*) csound->stdOp_Env); } /* ---- oscbnk, grain2, and grain3 - written by Istvan Varga, 2001 ---- */ /* update random seed */ static CS_PURE int32 oscbnk_rand31(int32 seed) { uint64_t tmp1; uint32_t tmp2; /* x = (16807 * x) % 0x7FFFFFFF */ tmp1 = (uint64_t) ((int32_t) seed * (int64_t) 16807); tmp2 = (uint32_t) tmp1 & (uint32_t) 0x7FFFFFFF; tmp2 += (uint32_t) (tmp1 >> 31); if ((int32_t) tmp2 < (int32_t) 0) tmp2 = (tmp2 + (uint32_t) 1) & (uint32_t) 0x7FFFFFFF; return (int32) tmp2; } /* initialise random seed */ static void oscbnk_seedrand(CSOUND *csound, int32 *seed, MYFLT seedval) { *seed = (int32) ((double) seedval + 0.5); if (*seed < 1L) { /* seed from current time */ STDOPCOD_GLOBALS *pp = get_oscbnk_globals(csound); if (pp->oscbnk_seed > 0UL) pp->oscbnk_seed += 23UL; else pp->oscbnk_seed = (uint32) csound->GetRandomSeedFromTime(); pp->oscbnk_seed = ((pp->oscbnk_seed - 1UL) % 0x7FFFFFFEUL) + 1UL; *seed = (int32) pp->oscbnk_seed; } else { *seed = ((*seed - 1L) % 0x7FFFFFFEL) + 1L; } *seed = oscbnk_rand31(*seed); *seed = oscbnk_rand31(*seed); } /* return a random phase value between 0 and OSCBNK_PHSMAX */ static uint32 oscbnk_rnd_phase(int32 *seed) { /* update random seed */ *seed = oscbnk_rand31(*seed); /* convert seed to phase */ return ((uint32) *seed >> OSCBNK_RNDPHS); } /* return a random value between -1 and 1 */ static MYFLT oscbnk_rnd_bipolar(int32 *seed, MYFLT rpow, int rmode) { double x; MYFLT s; /* update random seed */ *seed = oscbnk_rand31(*seed); /* convert to floating point */ x = (double) (*seed - 0x3FFFFFFFL) * (1.0 / 1073741823.015625); if (!(rmode)) return ((MYFLT) x); /* uniform distribution */ /* change distribution */ s = (x < 0.0 ? FL(-1.0) : FL(1.0)); /* sign */ x = fabs(x); /* absolute value */ if (rmode == 2) x = fabs(1.0 - x); x = pow(x, (double) rpow); if (rmode == 2) x = 1.0 - x; return ((MYFLT) x * s); } /* set ftable parameters (mask etc.) according to table length */ static void oscbnk_flen_setup(int32 flen, uint32 *mask, uint32 *lobits, MYFLT *pfrac); /* Update random seed, and return next value from parameter table (if */ /* enabled) or random value between 0 and 1. If output table is present */ /* store value in table. */ static MYFLT oscbnk_rand(OSCBNK *p) { MYFLT y; /* update random seed */ p->seed = oscbnk_rand31(p->seed); /* convert to float */ y = (MYFLT) (p->seed - 1L) / (MYFLT) 0x7FFFFFFDL; /* read from parameter table (if exists) */ if ((p->tabl_cnt < p->tabl_len) && (p->tabl[p->tabl_cnt] >= FL(0.0))) y = p->tabl[p->tabl_cnt]; switch (p->tabl_cnt % 5) { case 0: /* wrap phase */ case 1: case 3: y -= (MYFLT) ((int32) y); break; default: if (y > FL(1.0)) y = FL(1.0); /* limit frequency */ } /* store in output table */ if (p->tabl_cnt < p->outft_len) p->outft[p->tabl_cnt] = y; p->tabl_cnt++; return y; } /* Read from ft at phase with linear interpolation. flen is the table */ /* length. Phase is limited to the range 0 - 1. */ static MYFLT oscbnk_interp_read_limit(MYFLT phase, MYFLT *ft, int32 flen) { MYFLT x; int32 n; if (phase < FL(0.0)) return ft[0]; else phase *= (MYFLT) flen; n = (int32) phase; phase -= (MYFLT) n; if (n >= flen) return ft[flen]; else x = ft[n]; x += phase * (ft[++n] - x); //printf("**** (%d) x = %f\n", __LINE__, x); return x; } /* LFO / modulation */ static void oscbnk_lfo(OSCBNK *p, OSCBNK_OSC *o) { uint32 n; int eqmode; MYFLT f, l, q, k, kk, vk, vkk, vkdq, sq; MYFLT lfo1val = FL(0.0), lfo2val = FL(0.0); /* lfo1val = LFO1 output, lfo2val = LFO2 output */ if (p->ilfomode & 0xF0) { /* LFO 1 */ n = o->LFO1phs >> p->l1t_lobits; lfo1val = p->l1t[n++]; lfo1val += (p->l1t[n] - lfo1val) * (MYFLT) ((int32) (o->LFO1phs & p->l1t_mask)) * p->l1t_pfrac; /* update phase */ f = o->LFO1frq * p->lf1_scl + p->lf1_ofs; o->LFO1phs = (o->LFO1phs + OSCBNK_PHS2INT(f)) & OSCBNK_PHSMSK; } if (p->ilfomode & 0x0F) { /* LFO 2 */ n = o->LFO2phs >> p->l2t_lobits; lfo2val = p->l2t[n++]; lfo2val += (p->l2t[n] - lfo2val) * (MYFLT) ((int32) (o->LFO2phs & p->l2t_mask)) * p->l2t_pfrac; /* update phase */ f = o->LFO2frq * p->lf2_scl + p->lf2_ofs; o->LFO2phs = (o->LFO2phs + OSCBNK_PHS2INT(f)) & OSCBNK_PHSMSK; } /* modulate phase, frequency, and amplitude */ o->osc_frq = FL(0.0); if (p->ilfomode & 0x88) { /* FM */ if (p->ilfomode & 0x80) o->osc_frq += lfo1val; if (p->ilfomode & 0x08) o->osc_frq += lfo2val; o->osc_frq = o->osc_frq * *(p->args[3]); } if (p->ilfomode & 0x44) { /* AM */ o->osc_amp = FL(0.0); if (p->ilfomode & 0x40) o->osc_amp += lfo1val; if (p->ilfomode & 0x04) o->osc_amp += lfo2val; o->osc_amp--; o->osc_amp *= *(p->args[2]); o->osc_amp++; } else { o->osc_amp = FL(1.0); } o->osc_phm = FL(0.0); /* PM */ if (p->ilfomode & 0x22) { if (p->ilfomode & 0x20) o->osc_phm += lfo1val; if (p->ilfomode & 0x02) o->osc_phm += lfo2val; o->osc_phm *= *(p->args[4]); } if ((eqmode = p->ieqmode) < 0) return; /* EQ disabled */ /* modulate EQ */ f = l = q = FL(0.0); lfo1val = lfo1val * FL(0.5) + FL(0.5); lfo2val = lfo2val * FL(0.5) + FL(0.5); if (p->ilfomode & 0x10) { /* LFO1 to EQ */ f += oscbnk_interp_read_limit(lfo1val, p->eqft, p->eqft_len); l += oscbnk_interp_read_limit(lfo1val, p->eqlt, p->eqlt_len); q += oscbnk_interp_read_limit(lfo1val, p->eqqt, p->eqqt_len); } if (p->ilfomode & 0x01) { /* LFO2 to EQ */ f += oscbnk_interp_read_limit(lfo2val, p->eqft, p->eqft_len); l += oscbnk_interp_read_limit(lfo2val, p->eqlt, p->eqlt_len); q += oscbnk_interp_read_limit(lfo2val, p->eqqt, p->eqqt_len); } /* calculate EQ frequency, level, and Q */ f *= p->eqo_scl; f += p->eqo_ofs; l *= p->eql_scl; l += p->eql_ofs; q *= p->eqq_scl; q += p->eqq_ofs; f = FABS(f); q = FABS(q); /* EQ code taken from biquad.c */ sq = lb0 = FL(1.0) + sq * k + vkk; o->b1 = FL(2.0) * (vkk - FL(1.0)); o->b2 = FL(1.0) - sq * k + vkk; } else { o->b0 = FL(1.0) + vkdq + kk; o->b1 = FL(2.0) * (kk - FL(1.0)); o->b2 = FL(1.0) - vkdq + kk; } l = FL(1.0) + (k / q) + kk; /* l = a0 */ o->a1 = FL(2.0) * (kk - FL(1.0)); o->a2 = FL(1.0) - (k / q) + kk; if (eqmode == 2) { o->a1 = -(o->a1); o->b1 = -(o->b1); } l = FL(1.0) / l; o->a1 *= l; o->a2 *= l; o->b0 *= l; o->b1 *= l; o->b2 *= l; //printf("**** (%d) a1, a2 = %f, %f\n", __LINE__, o->a1, o->a2); } /* ---------------- oscbnk set-up ---------------- */ static int oscbnkset(CSOUND *csound, OSCBNK *p) { uint32_t i; FUNC *ftp; MYFLT x; p->init_k = 1; p->nr_osc = (int) MYFLT2LONG(*(p->args[5])); /* number of oscs */ if (p->nr_osc <= 0) p->nr_osc = -1; /* no output */ oscbnk_seedrand(csound, &(p->seed), *(p->args[6])); /* random seed */ p->ilfomode = (int) MYFLT2LONG(*(p->args[11])) & 0xFF; /* LFO mode */ p->eq_interp = 0; /* EQ mode */ if (*(p->args[18]) < FL(-0.5)) { p->ieqmode = -1; p->ilfomode &= 0xEE; /* disable EQ */ } else { p->ieqmode = (int) MYFLT2LONG(*(p->args[18])); if (p->ieqmode > 2) { p->ieqmode -= 3; } else { p->eq_interp = 1; /* enable interpolation */ } if (p->ieqmode > 2) p->ieqmode = 2; } /* set up ftables */ if (p->ilfomode & 0xF0) { ftp = csound->FTFind(csound, p->args[20]); /* LFO 1 */ if ((ftp == NULL) || ((p->l1t = ftp->ftable) == NULL)) return NOTOK; oscbnk_flen_setup(ftp->flen, &(p->l1t_mask), &(p->l1t_lobits), &(p->l1t_pfrac)); } else { p->l1t = NULL; /* LFO1 not used */ p->l1t_lobits = p->l1t_mask = 0UL; p->l1t_pfrac = FL(0.0); } if (p->ilfomode & 0x0F) { ftp = csound->FTFind(csound, p->args[21]); /* LFO 2 */ if (UNLIKELY((ftp == NULL) || ((p->l2t = ftp->ftable) == NULL))) return NOTOK; oscbnk_flen_setup(ftp->flen, &(p->l2t_mask), &(p->l2t_lobits), &(p->l2t_pfrac)); } else { p->l2t = NULL; /* LFO2 not used */ p->l2t_lobits = p->l2t_mask = 0UL; p->l2t_pfrac = FL(0.0); } if (p->ieqmode >= 0) { ftp = csound->FTFind(csound, p->args[22]); /* EQ frequency */ if (UNLIKELY((ftp == NULL) || ((p->eqft = ftp->ftable) == NULL))) return NOTOK; p->eqft_len = ftp->flen; ftp = csound->FTFind(csound, p->args[23]); /* EQ level */ if (UNLIKELY((ftp == NULL) || ((p->eqlt = ftp->ftable) == NULL))) return NOTOK; p->eqlt_len = ftp->flen; ftp = csound->FTFind(csound, p->args[24]); /* EQ Q */ if (UNLIKELY((ftp == NULL) || ((p->eqqt = ftp->ftable) == NULL))) return NOTOK; p->eqqt_len = ftp->flen; } else { p->eqft = p->eqlt = p->eqqt = NULL; /* EQ disabled */ p->eqft_len = p->eqlt_len = p->eqqt_len = 0L; } if (*(p->args[25]) >= FL(1.0)) { /* parameter table */ ftp = csound->FTFind(csound, p->args[25]); if (UNLIKELY((ftp == NULL) || ((p->tabl = ftp->ftable) == NULL))) return NOTOK; p->tabl_len = ftp->flen; } else { p->tabl = NULL; p->tabl_len = 0L; } p->tabl_cnt = 0L; /* table ptr. */ if (*(p->args[26]) >= FL(1.0)) { /* output table */ ftp = csound->FTFind(csound, p->args[26]); if (UNLIKELY((ftp == NULL) || ((p->outft = ftp->ftable) == NULL))) return NOTOK; p->outft_len = ftp->flen; } else { p->outft = NULL; p->outft_len = 0L; } /* allocate space */ if (p->nr_osc < 1) return OK; i = (uint32_t) p->nr_osc * (int32) sizeof (OSCBNK_OSC); if ((p->auxdata.auxp == NULL) || (p->auxdata.size < i)) csound->AuxAlloc(csound, i, &(p->auxdata)); p->osc = (OSCBNK_OSC *) p->auxdata.auxp; memset(p->outft, 0, p->outft_len*sizeof(MYFLT)); /* initialise oscillators */ for (i = 0; i < (uint32_t)p->nr_osc; i++) { /* oscillator phase */ x = oscbnk_rand(p); p->osc[i].osc_phs = OSCBNK_PHS2INT(x); /* LFO1 phase */ x = oscbnk_rand(p); p->osc[i].LFO1phs = OSCBNK_PHS2INT(x); /* LFO1 frequency */ p->osc[i].LFO1frq = oscbnk_rand(p); /* LFO2 phase */ x = oscbnk_rand(p); p->osc[i].LFO2phs = OSCBNK_PHS2INT(x); /* LFO2 frequency */ p->osc[i].LFO2frq = oscbnk_rand(p); /* EQ data */ p->osc[i].xnm1 = p->osc[i].xnm2 = FL(0.0); p->osc[i].ynm1 = p->osc[i].ynm2 = FL(0.0); p->osc[i].b0 = FL(1.0); p->osc[i].a1 = p->osc[i].b1 = FL(0.0); p->osc[i].a2 = p->osc[i].b2 = FL(0.0); } return OK; } /* ---------------- oscbnk performance ---------------- */ static int oscbnk(CSOUND *csound, OSCBNK *p) { int osc_cnt, pm_enabled, am_enabled; FUNC *ftp; MYFLT *ft; uint32 n, lobits, mask, ph, f_i; MYFLT pfrac, pm, a, f, a1, a2, b0, b1, b2; MYFLT k, a_d = FL(0.0), a1_d = FL(0.0), a2_d = FL(0.0), b0_d = FL(0.0), b1_d = FL(0.0), b2_d = FL(0.0); MYFLT yn, xnm1 = FL(0.0), xnm2 = FL(0.0), ynm1 = FL(0.0), ynm2 = FL(0.0); OSCBNK_OSC *o; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, nsmps = CS_KSMPS; /* clear output signal */ memset(p->args[0], '\0', nsmps*sizeof(MYFLT)); if (p->nr_osc == -1) { return OK; /* nothing to render */ } else if (UNLIKELY((p->seed == 0L) || (p->osc == NULL))) goto err1; /* check oscillator ftable */ ftp = csound->FTFindP(csound, p->args[19]); if (UNLIKELY((ftp == NULL) || ((ft = ftp->ftable) == NULL))) return NOTOK; oscbnk_flen_setup(ftp->flen, &(mask), &(lobits), &(pfrac)); /* some constants */ pm_enabled = (p->ilfomode & 0x22 ? 1 : 0); am_enabled = (p->ilfomode & 0x44 ? 1 : 0); p->frq_scl = csound->onedsr; /* osc. freq. */ p->lf1_scl = (*(p->args[8]) - *(p->args[7])) * CS_ONEDKR; p->lf1_ofs = *(p->args[7]) * CS_ONEDKR; /* LFO1 freq. */ p->lf2_scl = (*(p->args[10]) - *(p->args[9])) * CS_ONEDKR; p->lf2_ofs = *(p->args[9]) * CS_ONEDKR; /* LFO2 freq. */ if (p->ieqmode >= 0) { MYFLT fmax = *(p->args[13]); MYFLT fmin = *(p->args[12]); /* VL: min freq cannot be > max freq */ fmin = fmin < fmax ? fmin : fmax; p->eqo_scl = (fmax - fmin) * csound->tpidsr; p->eqo_ofs = fmin * csound->tpidsr; /* EQ omega */ p->eql_scl = *(p->args[15]) - (p->eql_ofs= *(p->args[14]));/* EQ level */ p->eqq_scl = *(p->args[17]) - (p->eqq_ofs= *(p->args[16]));/* EQ Q */ } if (UNLIKELY(early)) nsmps -= early; for (osc_cnt = 0, o = p->osc; osc_cnt < p->nr_osc; osc_cnt++, o++) { if (p->init_k) oscbnk_lfo(p, o); ph = o->osc_phs; /* phase */ pm = o->osc_phm; /* phase mod. */ if ((p->init_k) && (pm_enabled)) { f = pm - (MYFLT) ((int32) pm); ph = (ph + OSCBNK_PHS2INT(f)) & OSCBNK_PHSMSK; } a = o->osc_amp; /* amplitude */ f = o->osc_frq; /* frequency */ if (p->ieqmode < 0) { /* EQ disabled */ oscbnk_lfo(p, o); /* initialise ramps */ f = ((o->osc_frq + f) * FL(0.5) + *(p->args[1])) * p->frq_scl; if (pm_enabled) { f += (MYFLT) ((double) o->osc_phm - (double) pm) / (nsmps-offset); f -= (MYFLT) ((int32) f); } f_i = OSCBNK_PHS2INT(f); if (am_enabled) a_d = (o->osc_amp - a) / (nsmps-offset); /* oscillator */ for (nn = offset; nn < nsmps; nn++) { /* read from table */ n = ph >> lobits; k = ft[n++]; k += (ft[n] - k) * (MYFLT) ((int32) (ph & mask)) * pfrac; /* amplitude modulation */ if (am_enabled) k *= (a += a_d); /* mix to output */ p->args[0][nn] += k; /* update phase */ ph = (ph + f_i) & OSCBNK_PHSMSK; } } else { /* EQ enabled */ a1 = o->a1; a2 = o->a2; /* EQ coeffs */ b0 = o->b0; b1 = o->b1; b2 = o->b2; xnm1 = o->xnm1; xnm2 = o->xnm2; ynm1 = o->ynm1; ynm2 = o->ynm2; oscbnk_lfo(p, o); /* initialise ramps */ f = ((o->osc_frq + f) * FL(0.5) + *(p->args[1])) * p->frq_scl; if (pm_enabled) { f += (MYFLT) ((double) o->osc_phm - (double) pm) / (nsmps-offset); f -= (MYFLT) ((int32) f); } f_i = OSCBNK_PHS2INT(f); if (am_enabled) a_d = (o->osc_amp - a) / (nsmps-offset); if (p->eq_interp) { /* EQ w/ interpolation */ a1_d = (o->a1 - a1) / (nsmps-offset); a2_d = (o->a2 - a2) / (nsmps-offset); b0_d = (o->b0 - b0) / (nsmps-offset); b1_d = (o->b1 - b1) / (nsmps-offset); b2_d = (o->b2 - b2) / (nsmps-offset); /* oscillator */ for (nn = offset; nn < nsmps; nn++) { /* update ramps */ a1 += a1_d; a2 += a2_d; b0 += b0_d; b1 += b1_d; b2 += b2_d; /* read from table */ n = ph >> lobits; k = ft[n++]; k += (ft[n] - k) * (MYFLT) ((int32) (ph & mask)) * pfrac; /* amplitude modulation */ if (am_enabled) k *= (a += a_d); /* EQ */ yn = b2 * xnm2; yn += b1 * (xnm2 = xnm1); yn += b0 * (xnm1 = k); yn -= a2 * ynm2; yn -= a1 * (ynm2 = ynm1); ynm1 = yn; /* mix to output */ //if (yn>1) { // printf("**** (%d) yn = %f\n", __LINE__, yn); // printf("**** a1 = %f a2 = %f; %f\n", // a1, a2, 0.5*(-a1+ sqrt(a1*a1-4*a2)/a2)); //} p->args[0][nn] += yn; //if (p->args[0][nn]>1) // printf("**** (%d) out%d = %f\n", __LINE__, nn, p->args[0][nn]); /* update phase */ ph = (ph + f_i) & OSCBNK_PHSMSK; } /* save EQ coeffs */ o->a1 = a1; o->a2 = a2; o->b0 = b0; o->b1 = b1; o->b2 = b2; } else { /* EQ w/o interpolation */ /* oscillator */ a1 = o->a1; a2 = o->a2; /* EQ coeffs */ b0 = o->b0; b1 = o->b1; b2 = o->b2; for (nn = offset; nn < nsmps; nn++) { /* read from table */ n = ph >> lobits; k = ft[n++]; k += (ft[n] - k) * (MYFLT) ((int32) (ph & mask)) * pfrac; /* amplitude modulation */ if (am_enabled) k *= (a += a_d); /* EQ */ yn = b2 * xnm2; yn += b1 * (xnm2 = xnm1); yn += b0 * (xnm1 = k); yn -= a2 * ynm2; yn -= a1 * (ynm2 = ynm1); ynm1 = yn; /* mix to output */ p->args[0][nn] += yn; /* update phase */ ph = (ph + f_i) & OSCBNK_PHSMSK; } /* save EQ coeffs */ o->a1 = a1; o->a2 = a2; o->b0 = b0; o->b1 = b1; o->b2 = b2; } } o->xnm1 = xnm1; o->xnm2 = xnm2; /* save EQ state */ o->ynm1 = ynm1; o->ynm2 = ynm2; /* save amplitude and phase */ o->osc_amp = a; o->osc_phs = ph; } p->init_k = 0; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("oscbnk: not initialised")); } /* ---------------- grain2 set-up ---------------- */ static int grain2set(CSOUND *csound, GRAIN2 *p) { int i; FUNC *ftp; uint32_t n; double x, y; /* check opcode params */ i = (int) MYFLT2LONG(*(p->imode)); /* mode */ if (i & 1) return OK; /* skip initialisation */ p->init_k = 1; p->mode = i & 0x0E; p->nr_osc = (int) MYFLT2LONG(*(p->iovrlp)); /* nr of oscillators */ if (p->nr_osc < 1) p->nr_osc = -1; oscbnk_seedrand(csound, &(p->seed), *(p->iseed)); /* initialise seed */ p->rnd_pow = *(p->irpow); /* random distribution */ if ((p->rnd_pow == FL(0.0)) || (p->rnd_pow == FL(-1.0)) || (p->rnd_pow == FL(1.0))) { p->rnd_pow = FL(1.0); p->rnd_mode = 0; } else if (p->rnd_pow < FL(0.0)) { p->rnd_pow = -(p->rnd_pow); p->rnd_mode = 2; } else { p->rnd_mode = 1; } ftp = csound->FTFind(csound, p->iwfn); /* window table */ if (UNLIKELY((ftp == NULL) || ((p->wft = ftp->ftable) == NULL))) return NOTOK; oscbnk_flen_setup(ftp->flen, &(p->wft_mask), &(p->wft_lobits), &(p->wft_pfrac)); /* allocate space */ if (p->nr_osc == -1) return OK; /* no oscillators */ n = (uint32_t) p->nr_osc * (int32) sizeof(GRAIN2_OSC); if ((p->auxdata.auxp == NULL) || (p->auxdata.size < n)) csound->AuxAlloc(csound, n, &(p->auxdata)); p->osc = (GRAIN2_OSC *) p->auxdata.auxp; /* initialise oscillators */ y = (double) OSCBNK_PHSMAX / (double) p->nr_osc; x = (double) OSCBNK_PHSMAX + 0.5; for (i = 0; i < p->nr_osc; i++) { if ((x -= y) < 0.0) x = 0.0; p->osc[i].window_phs = (uint32) x; } return OK; } /* ---------------- grain2 performance ---------------- */ /* set initial phase of grains with start time less than zero */ static void grain2_init_grain_phase(GRAIN2_OSC *o, uint32 frq, uint32 w_frq, MYFLT frq_scl, int f_nolock) { double d; MYFLT f; if (!(w_frq)) return; if (f_nolock) { d = (double) o->grain_frq_flt * (double) frq_scl * (double) OSCBNK_PHSMAX + (double) frq; } else { d = (double) o->grain_frq_int; } d *= (double) o->window_phs / ((double) w_frq * (double) OSCBNK_PHSMAX); d -= (double) ((int32) d); f = (MYFLT) d; o->grain_phs = (o->grain_phs + OSCBNK_PHS2INT(f)) & OSCBNK_PHSMSK; } /* initialise grain */ static void grain2_init_grain(GRAIN2 *p, GRAIN2_OSC *o) { MYFLT f; /* random phase */ o->grain_phs = oscbnk_rnd_phase(&(p->seed)); /* random frequency */ f = oscbnk_rnd_bipolar(&(p->seed), p->rnd_pow, p->rnd_mode); if (p->mode & 2) { o->grain_frq_flt = f; } else { /* lock frequency */ f = p->grain_frq + p->frq_scl * f; o->grain_frq_int = OSCBNK_PHS2INT(f); } } /* ---- grain2 opcode ---- */ static int grain2(CSOUND *csound, GRAIN2 *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, nsmps = CS_KSMPS; int i, w_interp, g_interp, f_nolock; MYFLT *aout, *ft, *w_ft, grain_frq, frq_scl, pfrac, w_pfrac, f, a, k; uint32 n, mask, lobits, w_mask, w_lobits; uint32 g_frq, w_frq; GRAIN2_OSC *o; FUNC *ftp; /* assign object data to local variables */ aout = p->ar; /* audio output */ o = p->osc; /* oscillator array */ w_interp = (p->mode & 8 ? 1 : 0); /* interpolate window */ g_interp = (p->mode & 4 ? 0 : 1); /* interpolate grain */ f_nolock = (p->mode & 2 ? 1 : 0); /* don't lock grain frq */ w_ft = p->wft; /* window ftable */ w_mask = p->wft_mask; w_lobits = p->wft_lobits; w_pfrac = p->wft_pfrac; /* clear output signal */ memset(aout, 0, nsmps*sizeof(MYFLT)); if (UNLIKELY(early)) nsmps -= early; if (p->nr_osc == -1) { return OK; /* nothing to render */ } else if (UNLIKELY((p->seed == 0L) || (p->osc == NULL))) goto err1; /* check grain ftable */ ftp = csound->FTFindP(csound, p->kfn); if (UNLIKELY((ftp == NULL) || ((ft = ftp->ftable) == NULL))) return NOTOK; oscbnk_flen_setup(ftp->flen, &mask, &lobits, &pfrac); p->grain_frq = grain_frq = *(p->kcps) * csound->onedsr; /* grain freq. */ p->frq_scl = frq_scl = *(p->kfmd) * csound->onedsr; f = csound->onedsr / *(p->kgdur); /* window frequency */ w_frq = OSCBNK_PHS2INT(f); /* initialisation */ if (p->init_k) { g_frq = OSCBNK_PHS2INT(grain_frq); for (i = 0; i < p->nr_osc; i++) { grain2_init_grain(p, o + i); grain2_init_grain_phase(o + i, g_frq, w_frq, frq_scl, f_nolock); } p->init_k = 0; } for (i = 0; i < p->nr_osc; i++) { /* calculate grain frequency */ if (f_nolock) { f = grain_frq + frq_scl * o[i].grain_frq_flt; o[i].grain_frq_int = OSCBNK_PHS2INT(f); } } aout = p->ar; /* audio output */ for (nn = offset; nnnr_osc; do { /* grain waveform */ n = o->grain_phs >> lobits; k = ft[n++]; if (g_interp) k += (ft[n] - k) * (MYFLT) ((int32) (o->grain_phs & mask)) * pfrac; o->grain_phs += o->grain_frq_int; o->grain_phs &= OSCBNK_PHSMSK; /* window waveform */ n = o->window_phs >> w_lobits; a = w_ft[n++]; if (w_interp) a += (w_ft[n] - a) * (MYFLT) ((int32) (o->window_phs & w_mask)) * w_pfrac; o->window_phs += w_frq; /* mix to output */ aout[nn] += a * k; if (o->window_phs >= OSCBNK_PHSMAX) { o->window_phs &= OSCBNK_PHSMSK; /* new grain */ grain2_init_grain(p, o); /* grain frequency */ if (f_nolock) { f = grain_frq + frq_scl * o->grain_frq_flt; o->grain_frq_int = OSCBNK_PHS2INT(f); } } o++; /* next grain */ } while (--i); o -= p->nr_osc; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("grain2: not initialised")); } /* ---------------- grain3 set-up ---------------- */ static int grain3set(CSOUND *csound, GRAIN3 *p) { int i; FUNC *ftp; uint32_t n; /* check opcode params */ i = (int) MYFLT2LONG(*(p->imode)); /* mode */ if (i & 1) return OK; /* skip initialisation */ p->init_k = 1; p->mode = i & 0x7E; p->x_phs = OSCBNK_PHSMAX; p->ovrlap = (int) MYFLT2LONG(*(p->imaxovr)); /* max. overlap */ p->ovrlap = (p->ovrlap < 1 ? 1 : p->ovrlap) + 1; oscbnk_seedrand(csound, &(p->seed), *(p->iseed)); /* initialise seed */ ftp = csound->FTFind(csound, p->iwfn); /* window table */ if (UNLIKELY((ftp == NULL) || ((p->wft = ftp->ftable) == NULL))) return NOTOK; oscbnk_flen_setup(ftp->flen, &(p->wft_mask), &(p->wft_lobits), &(p->wft_pfrac)); /* allocate space */ n = ((uint32_t) CS_KSMPS + 1L) * (int32) sizeof(uint32); n += (uint32_t) p->ovrlap * (int32) sizeof(GRAIN2_OSC); if ((p->auxdata.auxp == NULL) || (p->auxdata.size < n)) csound->AuxAlloc(csound, n, &(p->auxdata)); p->phase = (uint32 *) p->auxdata.auxp; p->osc = (GRAIN2_OSC *) ((uint32 *) p->phase + CS_KSMPS + 1); p->osc_start = p->osc; p->osc_end = p->osc; p->osc_max = p->osc + (p->ovrlap - 1); return OK; } /* ---------------- grain3 performance ---------------- */ /* initialise grain */ static void grain3_init_grain(GRAIN3 *p, GRAIN2_OSC *o, uint32 w_ph, uint32 g_ph) { MYFLT f; /* start phase */ f = oscbnk_rnd_bipolar(&(p->seed), p->p_rnd_pow, p->p_rnd_mode); f *= *(p->kpmd); if (p->pm_wrap) f -= (MYFLT) ((int32) f); o->grain_phs = (g_ph + OSCBNK_PHS2INT(f)) & OSCBNK_PHSMSK; o->window_phs = w_ph; /* frequency */ f = oscbnk_rnd_bipolar(&(p->seed), p->f_rnd_pow, p->f_rnd_mode); if (p->mode & 2) { o->grain_frq_flt = f; } else { /* lock frequency */ f *= p->frq_scl; o->grain_frq_int = (p->grain_frq + OSCBNK_PHS2INT(f)) & OSCBNK_PHSMSK; } } /* ---- grain3 opcode ---- */ static int grain3(CSOUND *csound, GRAIN3 *p) { int i, w_interp, g_interp, f_nolock; MYFLT *aout0, *aout, *ft, *w_ft, frq_scl, pfrac, w_pfrac, f, a, k; MYFLT wfdivxf, w_frq_f, x_frq_f; uint32 n, mask, lobits, w_mask, w_lobits; uint32 *phs, frq, x_ph, x_frq, g_ph, g_frq, w_ph, w_frq; GRAIN2_OSC *o; FUNC *ftp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, nsmps = CS_KSMPS; /* clear output */ memset(p->ar, 0, nsmps*sizeof(MYFLT)); if (UNLIKELY(early)) nsmps -= early; if (UNLIKELY((p->seed == 0L) || (p->osc == NULL))) goto err1; /* assign object data to local variables */ aout0 = p->ar; /* audio output */ w_interp = (p->mode & 8 ? 1 : 0); /* interpolate window */ g_interp = (p->mode & 4 ? 0 : 1); /* interpolate grain */ f_nolock = (p->mode & 2 ? 1 : 0); /* do not lock grain frq */ w_ft = p->wft; /* window ftable */ w_mask = p->wft_mask; w_lobits = p->wft_lobits; w_pfrac = p->wft_pfrac; phs = p->phase; /* grain phase offset */ x_ph = p->x_phs; ftp = csound->FTFindP(csound, p->kfn); /* check grain ftable */ if (UNLIKELY((ftp == NULL) || ((ft = ftp->ftable) == NULL))) return NOTOK; oscbnk_flen_setup(ftp->flen, &mask, &lobits, &pfrac); p->f_rnd_pow = *(p->kfrpow); /* random distribution (frequency) */ if ((p->f_rnd_pow == FL(0.0)) || (p->f_rnd_pow == FL(-1.0)) || (p->f_rnd_pow == FL(1.0))) { p->f_rnd_pow = FL(1.0); p->f_rnd_mode = 0; } else if (p->f_rnd_pow < FL(0.0)) { p->f_rnd_pow = -(p->f_rnd_pow); p->f_rnd_mode = 2; } else { p->f_rnd_mode = 1; } p->p_rnd_pow = *(p->kprpow); /* random distribution (phase) */ if ((p->p_rnd_pow == FL(0.0)) || (p->p_rnd_pow == FL(-1.0)) || (p->p_rnd_pow == FL(1.0))) { p->p_rnd_pow = FL(1.0); p->p_rnd_mode = 0; } else if (p->p_rnd_pow < FL(0.0)) { p->p_rnd_pow = -(p->p_rnd_pow); p->p_rnd_mode = 2; } else { p->p_rnd_mode = 1; } if (p->init_k) { /* initial phase */ f = *(p->kphs); g_ph = OSCBNK_PHS2INT(f); } else { f = p->phs0; g_ph = phs[nsmps]; } p->phs0 = *(p->kphs); /* convert phase modulation to frequency modulation */ f = (MYFLT) ((double) p->phs0 - (double) f) / (nsmps-offset); f -= (MYFLT) ((int32) f); g_frq = OSCBNK_PHS2INT(f); f = *(p->kcps) * csound->onedsr; /* grain frequency */ frq = (g_frq + OSCBNK_PHS2INT(f)) & OSCBNK_PHSMSK; if (p->mode & 0x40) g_frq = frq; /* phase sync */ /* calculate phase offset values for this k-cycle */ for (nn = offset; nn <= nsmps; nn++) { phs[nn] = g_ph; g_ph = (g_ph + g_frq) & OSCBNK_PHSMSK; } w_frq_f = csound->onedsr / *(p->kgdur); /* window frequency */ if (UNLIKELY((w_frq_f < (FL(1.0) / (MYFLT) OSCBNK_PHSMAX)) || (w_frq_f >= FL(1.0)))) { return csound->PerfError(csound, p->h.insdshead, Str("grain3: invalid grain duration")); } w_frq = OSCBNK_PHS2INT(w_frq_f); x_frq_f = csound->onedsr * *(p->kdens); /* density */ if (UNLIKELY((x_frq_f < (FL(1.0) / (MYFLT) OSCBNK_PHSMAX)) || (x_frq_f >= FL(1.0)))) { return csound->PerfError(csound, p->h.insdshead, Str("grain3: invalid grain density")); } x_frq = OSCBNK_PHS2INT(x_frq_f); wfdivxf = w_frq_f / ((MYFLT) OSCBNK_PHSMAX * x_frq_f); p->grain_frq = frq; /* grain frequency */ p->frq_scl = frq_scl = *(p->kfmd) * csound->onedsr; p->pm_wrap = (fabs((double) *(p->kpmd)) > 0.9 ? 1 : 0); /* initialise grains (if enabled) */ if ((p->init_k) && (!(p->mode & 0x10))) { f = w_frq_f / x_frq_f; g_frq = (f > FL(0.99999) ? OSCBNK_PHSMAX : OSCBNK_PHS2INT(f)); /* initial window phase */ // COVERITY: g_frq is not zero, as it is derived from 1/sr g_ph = OSCBNK_PHSMAX % g_frq; if (g_ph < (OSCBNK_PHSMAX >> 16)) g_ph += g_frq; g_ph = OSCBNK_PHSMAX - g_ph; while (g_ph) { grain3_init_grain(p, p->osc_end, g_ph, *phs); if (!(p->mode & 0x40)) /* init. grain phase */ grain2_init_grain_phase(p->osc_end, frq, w_frq, frq_scl, f_nolock); if (++(p->osc_end) > p->osc_max) p->osc_end = p->osc; if (UNLIKELY(p->osc_end == p->osc_start)) goto err2; g_ph -= g_frq; } } p->init_k = 0; nn = nsmps; o = p->osc_start; while (nn>offset) { if (x_ph >= OSCBNK_PHSMAX) { /* check for new grain */ x_ph &= OSCBNK_PHSMSK; if (!(p->mode & 0x20)) { f = (MYFLT) x_ph * wfdivxf; w_ph = OSCBNK_PHS2INT(f); } else { w_ph = 0UL; } grain3_init_grain(p, p->osc_end, w_ph, *phs); if (++(p->osc_end) > p->osc_max) p->osc_end = p->osc; if (UNLIKELY(p->osc_end == p->osc_start)) goto err2; } if (o == p->osc_end) { /* no active grains */ x_ph += x_frq; nn--; aout0++; phs++; continue; } g_ph = o->grain_phs; /* grain phase */ if (f_nolock) { /* grain frequency */ f = o->grain_frq_flt * frq_scl; g_frq = OSCBNK_PHS2INT(f); g_frq = (g_frq + frq) & OSCBNK_PHSMSK; } else { /* lock frequency */ g_frq = o->grain_frq_int; } w_ph = o->window_phs; /* window phase */ /* render grain */ aout = aout0; i = nn; while (i--) { /* window waveform */ n = w_ph >> w_lobits; a = w_ft[n++]; if (w_interp) a += (w_ft[n] - a) * w_pfrac * (MYFLT) ((int32) (w_ph & w_mask)); /* grain waveform */ n = g_ph >> lobits; k = ft[n++]; if (g_interp) k += (ft[n] - k) * pfrac * (MYFLT) ((int32) (g_ph & mask)); /* mix to output */ *(aout++) += a * k; /* update phase */ g_ph = (g_ph + g_frq) & OSCBNK_PHSMSK; /* check for end of grain */ if ((w_ph += w_frq) >= OSCBNK_PHSMAX) { if (++(p->osc_start) > p->osc_max) p->osc_start = p->osc; break; } } /* save phase */ o->grain_phs = g_ph; o->window_phs = w_ph; /* next grain */ if (++o > p->osc_max) o = p->osc; } p->x_phs = x_ph; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("grain3: not initialised")); err2: return csound->PerfError(csound, p->h.insdshead, Str("grain3 needs more overlaps")); } /* ----------------------------- rnd31 opcode ------------------------------ */ static int rnd31set(CSOUND *csound, RND31 *p) { /* initialise random seed */ oscbnk_seedrand(csound, &(p->seed), *(p->iseed)); return OK; } /* ---- rnd31 / i-rate ---- */ static int rnd31i(CSOUND *csound, RND31 *p) { MYFLT rpow; int rmode; /* random distribution */ rpow = *(p->rpow); if ((rpow == FL(0.0)) || (rpow == FL(-1.0)) || (rpow == FL(1.0))) { rpow = FL(1.0); rmode = 0; } else if (rpow < FL(0.0)) { rpow = -(rpow); rmode = 2; } else { rmode = 1; } /* initialise seed */ if (p->rnd31i_seed == NULL) { STDOPCOD_GLOBALS *pp = get_oscbnk_globals(csound); p->rnd31i_seed = &(pp->rnd31i_seed); } if (*(p->iseed) < FL(0.5)) { /* seed from current time */ if (*(p->rnd31i_seed) <= 0L) /* check if already initialised */ oscbnk_seedrand(csound, p->rnd31i_seed, FL(0.0)); } else { /* explicit seed value */ oscbnk_seedrand(csound, p->rnd31i_seed, *(p->iseed)); } *(p->out) = *(p->scl) * oscbnk_rnd_bipolar(p->rnd31i_seed, rpow, rmode); return OK; } /* ---- rnd31 / k-rate ---- */ static int rnd31k(CSOUND *csound, RND31 *p) { MYFLT rpow; int rmode; if (UNLIKELY(!p->seed)) goto err1; /* random distribution */ rpow = *(p->rpow); if ((rpow == FL(0.0)) || (rpow == FL(-1.0)) || (rpow == FL(1.0))) { rpow = FL(1.0); rmode = 0; } else if (rpow < FL(0.0)) { rpow = -(rpow); rmode = 2; } else { rmode = 1; } *(p->out) = *(p->scl) * oscbnk_rnd_bipolar(&(p->seed), rpow, rmode); return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("rnd31: not initialised")); } /* ---- rnd31 / a-rate ---- */ static int rnd31a(CSOUND *csound, RND31 *p) { MYFLT scl, *out, rpow; int rmode; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, nsmps = CS_KSMPS; if (UNLIKELY(!p->seed)) goto err1; scl = *(p->scl); out = p->out; /* random distribution */ rpow = *(p->rpow); if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } if ((rpow == FL(0.0)) || (rpow == FL(-1.0)) || (rpow == FL(1.0))) { /* IV - Jan 30 2003: optimised code for uniform distribution */ scl *= (MYFLT) (1.0 / 1073741823.015625); for (nn=offset; nnseed = oscbnk_rand31(p->seed); out[nn] = scl * (MYFLT) (p->seed - 0x3FFFFFFFL); } return OK; } else if (rpow < FL(0.0)) { rpow = -(rpow); rmode = 2; } else { rmode = 1; } for (nn=offset; nnseed), rpow, rmode); } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("rnd31: not initialised")); } /* ---- oscilikt initialisation ---- */ static int oscktset(CSOUND *csound, OSCKT *p) { MYFLT phs; if (*(p->istor) != FL(0.0)) return OK; /* skip initialisation */ /* initialise table parameters */ p->oldfn = FL(-1.0); p->lobits = p->mask = 0UL; p->pfrac = FL(0.0); p->ft = NULL; /* initial phase */ phs = *(p->iphs) - (MYFLT) ((int32) *(p->iphs)); p->phs = OSCBNK_PHS2INT(phs); return OK; } /* ---- oscilikt performance ---- */ static int kosclikt(CSOUND *csound, OSCKT *p) { FUNC *ftp; uint32 n, phs; MYFLT v, *ft; /* check if table number was changed */ if (*(p->kfn) != p->oldfn || p->ft == NULL) { p->oldfn = *(p->kfn); ftp = csound->FTFindP(csound, p->kfn); /* new table parameters */ if (UNLIKELY((ftp == NULL) || ((p->ft = ftp->ftable) == NULL))) return NOTOK; oscbnk_flen_setup(ftp->flen, &(p->mask), &(p->lobits), &(p->pfrac)); } /* copy object data to local variables */ ft = p->ft; phs = p->phs; /* read from table with interpolation */ n = phs >> p->lobits; v = (MYFLT) ((int32) (phs & p->mask)) * p->pfrac; *(p->sr) = (ft[n] + (ft[n + 1] - ft[n]) * v) * *(p->xamp); /* update phase */ v = *(p->xcps) * CS_ONEDKR; p->phs = (phs + OSCBNK_PHS2INT(v)) & OSCBNK_PHSMSK; return OK; } static int osckkikt(CSOUND *csound, OSCKT *p) { FUNC *ftp; uint32 n, phs, lobits, mask, frq; MYFLT pfrac, *ft, v, a, *ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, nsmps = CS_KSMPS; /* check if table number was changed */ if (*(p->kfn) != p->oldfn || p->ft == NULL) { p->oldfn = *(p->kfn); ftp = csound->FTFindP(csound, p->kfn); /* new table parameters */ if (UNLIKELY((ftp == NULL) || ((p->ft = ftp->ftable) == NULL))) return NOTOK; oscbnk_flen_setup(ftp->flen, &(p->mask), &(p->lobits), &(p->pfrac)); } /* copy object data to local variables */ ft = p->ft; phs = p->phs; a = *(p->xamp); ar = p->sr; lobits = p->lobits; mask = p->mask; pfrac = p->pfrac; /* read from table with interpolation */ v = *(p->xcps) * csound->onedsr; frq = OSCBNK_PHS2INT(v); if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (nn=offset; nn> lobits; v = ft[n++]; v += (ft[n] - v) * (MYFLT) ((int32) (phs & mask)) * pfrac; phs = (phs + frq) & OSCBNK_PHSMSK; ar[nn] = v * a; } /* save new phase */ p->phs = phs; return OK; } static int osckaikt(CSOUND *csound, OSCKT *p) { FUNC *ftp; uint32 n, phs, lobits, mask; MYFLT pfrac, *ft, v, a, *ar, *xcps; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, nsmps=CS_KSMPS; /* check if table number was changed */ if (*(p->kfn) != p->oldfn || p->ft == NULL) { p->oldfn = *(p->kfn); ftp = csound->FTFindP(csound, p->kfn); /* new table parameters */ if (UNLIKELY((ftp == NULL) || ((p->ft = ftp->ftable) == NULL))) return NOTOK; oscbnk_flen_setup(ftp->flen, &(p->mask), &(p->lobits), &(p->pfrac)); } /* copy object data to local variables */ ft = p->ft; phs = p->phs; a = *(p->xamp); ar = p->sr; xcps = p->xcps; lobits = p->lobits; mask = p->mask; pfrac = p->pfrac; /* read from table with interpolation */ if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (nn=offset; nn> lobits; v = ft[n++]; v += (ft[n] - v) * (MYFLT) ((int32) (phs & mask)) * pfrac; ar[nn] = v * a; v = *(xcps++) * csound->onedsr; phs = (phs + OSCBNK_PHS2INT(v)) & OSCBNK_PHSMSK; } /* save new phase */ p->phs = phs; return OK; } static void oscbnk_flen_setup(int32 flen, uint32 *mask, uint32 *lobits, MYFLT *pfrac) { uint32 n; n = (uint32) flen; *lobits = 0UL; *mask = 1UL; *pfrac = FL(0.0); if (n < 2UL) return; while (n < OSCBNK_PHSMAX) { n <<= 1; *mask <<= 1; (*lobits)++; } *pfrac = FL(1.0) / (MYFLT) *mask; (*mask)--; } static int oscakikt(CSOUND *csound, OSCKT *p) { FUNC *ftp; uint32 n, phs, lobits, mask, frq; MYFLT pfrac, *ft, v, *ar, *xamp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, nsmps = CS_KSMPS; /* check if table number was changed */ if (*(p->kfn) != p->oldfn || p->ft == NULL) { p->oldfn = *(p->kfn); ftp = csound->FTFindP(csound, p->kfn); /* new table parameters */ if (UNLIKELY((ftp == NULL) || ((p->ft = ftp->ftable) == NULL))) return NOTOK; oscbnk_flen_setup(ftp->flen, &(p->mask), &(p->lobits), &(p->pfrac)); } /* copy object data to local variables */ ft = p->ft; phs = p->phs; xamp = p->xamp; ar = p->sr; lobits = p->lobits; mask = p->mask; pfrac = p->pfrac; /* read from table with interpolation */ v = *(p->xcps) * csound->onedsr; frq = OSCBNK_PHS2INT(v); if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (nn=offset; nn> lobits; v = ft[n++]; v += (ft[n] - v) * (MYFLT) ((int32) (phs & mask)) * pfrac; phs = (phs + frq) & OSCBNK_PHSMSK; ar[nn] = v * *(xamp++); } /* save new phase */ p->phs = phs; return OK; } static int oscaaikt(CSOUND *csound, OSCKT *p) { FUNC *ftp; uint32 n, phs, lobits, mask; MYFLT pfrac, *ft, v, *ar, *xcps, *xamp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, nsmps = CS_KSMPS; /* check if table number was changed */ if (*(p->kfn) != p->oldfn || p->ft == NULL) { p->oldfn = *(p->kfn); ftp = csound->FTFindP(csound, p->kfn); /* new table parameters */ if (UNLIKELY((ftp == NULL) || ((p->ft = ftp->ftable) == NULL))) return NOTOK; oscbnk_flen_setup(ftp->flen, &(p->mask), &(p->lobits), &(p->pfrac)); } /* copy object data to local variables */ ft = p->ft; phs = p->phs; ar = p->sr; xcps = p->xcps; xamp = p->xamp; lobits = p->lobits; mask = p->mask; pfrac = p->pfrac; /* read from table with interpolation */ if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (nn=offset; nn> lobits; v = ft[n++]; v += (ft[n] - v) * (MYFLT) ((int32) (phs & mask)) * pfrac; ar[nn] = v * xamp[nn]; v = xcps[nn] * csound->onedsr; phs = (phs + OSCBNK_PHS2INT(v)) & OSCBNK_PHSMSK; } /* save new phase */ p->phs = phs; return OK; } /* ---- osciliktp initialisation ---- */ static int oscktpset(CSOUND *csound, OSCKTP *p) { if (*(p->istor) != FL(0.0)) return OK; /* skip initialisation */ /* initialise table parameters */ p->oldfn = FL(-1.0); p->lobits = p->mask = 0UL; p->pfrac = FL(0.0); p->ft = NULL; /* initial phase */ p->phs = 0UL; p->old_phs = FL(0.0); p->init_k = 1; return OK; } /* ---- osciliktp performance ---- */ static int oscktp(CSOUND *csound, OSCKTP *p) { FUNC *ftp; uint32_t n, phs, lobits, mask, frq; MYFLT pfrac, *ft, v, *ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, nsmps = CS_KSMPS; /* check if table number was changed */ if (*(p->kfn) != p->oldfn || p->ft == NULL) { p->oldfn = *(p->kfn); ftp = csound->FTFindP(csound, p->kfn); /* new table parameters */ if (UNLIKELY((ftp == NULL) || ((p->ft = ftp->ftable) == NULL))) return NOTOK; oscbnk_flen_setup(ftp->flen, &(p->mask), &(p->lobits), &(p->pfrac)); } /* copy object data to local variables */ ft = p->ft; phs = p->phs; ar = p->ar; lobits = p->lobits; mask = p->mask; pfrac = p->pfrac; v = *(p->kcps) * csound->onedsr; frq = OSCBNK_PHS2INT(v); /* initialise phase if 1st k-cycle */ if (p->init_k) { p->init_k = 0; p->old_phs = *(p->kphs); v = *(p->kphs) - (MYFLT) ((int32) *(p->kphs)); phs = OSCBNK_PHS2INT(v); } /* convert phase modulation to frequency modulation */ /* VL moved the line from below to here */ v = (MYFLT) ((double) *(p->kphs) - (double) p->old_phs) / (nsmps-offset); p->old_phs = *(p->kphs); frq = (frq + OSCBNK_PHS2INT(v)) & OSCBNK_PHSMSK; /* read from table with interpolation */ if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } //v = (MYFLT) ((double) *(p->kphs) - (double) p->old_phs) / (nsmps-offset); /* VL this result is never used */ for (nn=offset; nn> lobits; v = ft[n++]; v += (ft[n] - v) * (MYFLT) ((int32) (phs & mask)) * pfrac; phs = (phs + frq) & OSCBNK_PHSMSK; ar[nn] = v; } /* save new phase */ p->phs = phs; return OK; } /* ---- oscilikts initialisation ---- */ static int oscktsset(CSOUND *csound, OSCKTS *p) { if (*(p->istor) != FL(0.0)) return OK; /* skip initialisation */ /* initialise table parameters */ p->oldfn = FL(-1.0); p->lobits = p->mask = 0UL; p->pfrac = FL(0.0); p->ft = NULL; /* initial phase */ p->phs = 0UL; p->init_k = 1; return OK; } /* ---- oscilikts performance ---- */ static int osckts(CSOUND *csound, OSCKTS *p) { FUNC *ftp; uint32_t n, phs, lobits, mask, frq = 0UL; MYFLT pfrac, *ft, v, *ar, *xcps, *xamp, *async; int a_amp, a_cps; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, nsmps = CS_KSMPS; /* check if table number was changed */ if (*(p->kfn) != p->oldfn || p->ft == NULL) { p->oldfn = *(p->kfn); ftp = csound->FTnp2Find(csound, p->kfn); /* new table parameters */ if (UNLIKELY((ftp == NULL) || ((p->ft = ftp->ftable) == NULL))) return NOTOK; oscbnk_flen_setup(ftp->flen, &(p->mask), &(p->lobits), &(p->pfrac)); } /* copy object data to local variables */ ft = p->ft; a_amp = (IS_ASIG_ARG(p->xamp) ? 1 : 0); a_cps = (IS_ASIG_ARG(p->xcps) ? 1 : 0); phs = p->phs; ar = p->ar; xcps = p->xcps; xamp = p->xamp; async = p->async; lobits = p->lobits; mask = p->mask; pfrac = p->pfrac; if (!a_cps) { v = *xcps * csound->onedsr; frq = OSCBNK_PHS2INT(v); } /* initialise phase if 1st k-cycle */ if (p->init_k) { p->init_k = 0; v = *(p->kphs) - (MYFLT) ((int32) *(p->kphs)); phs = OSCBNK_PHS2INT(v); } /* read from table with interpolation */ if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (nn=offset; nn FL(0.0)) { /* re-initialise phase */ v = *(p->kphs) - (MYFLT) ((int32) *(p->kphs)); phs = OSCBNK_PHS2INT(v); } n = phs >> lobits; v = ft[n++]; v += (ft[n] - v) * (MYFLT) ((int32) (phs & mask)) * pfrac; ar[nn] = v * *xamp; if (a_amp) xamp++; if (a_cps) { v = xcps[nn] * csound->onedsr; frq = OSCBNK_PHS2INT(v); } phs = (phs + frq) & OSCBNK_PHSMSK; } /* save new phase */ p->phs = phs; return OK; } /* ---- vco2init, vco2ft, and vco2 opcodes by Istvan Varga, Sep 2002 ---- */ /* table arrays for vco2 opcode */ /* 0: sawtooth */ /* 1: 4 * x * (1 - x) */ /* 2: pulse (not normalised) */ /* 3: square */ /* 4: triangle */ /* 5 and above: user defined */ #define VCO2_MAX_NPART 4096 /* maximum number of harmonic partials */ typedef struct { int waveform; /* waveform number (< 0: user defined) */ int w_npart; /* nr of partials in user specified waveform */ double npart_mul; /* multiplier for number of partials */ int min_size, max_size; /* minimum and maximum table size */ MYFLT *w_fftbuf; /* FFT of user specified waveform */ } VCO2_TABLE_PARAMS; /* remove table array for the specified waveform */ static void vco2_delete_table_array(CSOUND *csound, int w) { STDOPCOD_GLOBALS *pp = get_oscbnk_globals(csound); int j; /* table array does not exist: nothing to do */ if (pp->vco2_tables == (VCO2_TABLE_ARRAY**) NULL || w >= pp->vco2_nr_table_arrays || pp->vco2_tables[w] == (VCO2_TABLE_ARRAY*) NULL) return; #ifdef VCO2FT_USE_TABLE /* free number of partials -> table list, */ csound->Free(csound, pp->vco2_tables[w]->nparts_tabl); #else /* free number of partials list, */ csound->Free(csound, pp->vco2_tables[w]->nparts); #endif /* table data (only if not shared as standard Csound ftables), */ for (j = 0; j < pp->vco2_tables[w]->ntabl; j++) { if (pp->vco2_tables[w]->base_ftnum < 1) csound->Free(csound, pp->vco2_tables[w]->tables[j].ftable); } /* table list, */ csound->Free(csound, pp->vco2_tables[w]->tables); /* and table array structure */ csound->Free(csound, pp->vco2_tables[w]); pp->vco2_tables[w] = NULL; } /* generate a table using the waveform specified in tp */ static void vco2_calculate_table(CSOUND *csound, VCO2_TABLE *table, VCO2_TABLE_PARAMS *tp) { MYFLT scaleFac; MYFLT *fftbuf; int i, minh; if(table->ftable == NULL) { csound->InitError(csound, "function table is NULL, check that ibasfn is available\n"); return; } /* allocate memory for FFT */ fftbuf = (MYFLT*) csound->Malloc(csound, sizeof(MYFLT) * (table->size + 2)); if (tp->waveform >= 0) { /* no DC offset for */ minh = 1; fftbuf[0] = fftbuf[1] = FL(0.0); /* built-in waveforms */ } else minh = 0; scaleFac = csound->GetInverseRealFFTScale(csound, (int) table->size); scaleFac *= (FL(0.5) * (MYFLT) table->size); switch (tp->waveform) { case 0: scaleFac *= (FL(-2.0) / PI_F); break; case 1: scaleFac *= (FL(-4.0) / (PI_F * PI_F)); break; case 3: scaleFac *= (FL(-4.0) / PI_F); break; case 4: scaleFac *= (FL(8.0) / (PI_F * PI_F)); break; } /* calculate FFT of the requested waveform */ for (i = minh; i <= (table->size >> 1); i++) { fftbuf[i << 1] = fftbuf[(i << 1) + 1] = FL(0.0); if (i > table->npart) continue; switch (tp->waveform) { case 0: /* sawtooth */ fftbuf[(i << 1) + 1] = scaleFac / (MYFLT) i; break; case 1: /* 4 * x * (1 - x) */ fftbuf[i << 1] = scaleFac / ((MYFLT) i * (MYFLT) i); break; case 2: /* pulse */ fftbuf[i << 1] = scaleFac; break; case 3: /* square */ fftbuf[(i << 1) + 1] = (i & 1 ? (scaleFac / (MYFLT) i) : FL(0.0)); break; case 4: /* triangle */ fftbuf[(i << 1) + 1] = (i & 1 ? ((i & 2 ? scaleFac : (-scaleFac)) / ((MYFLT) i * (MYFLT) i)) : FL(0.0)); break; default: /* user defined */ if (i <= tp->w_npart) { fftbuf[i << 1] = scaleFac * tp->w_fftbuf[i << 1]; fftbuf[(i << 1) + 1] = scaleFac * tp->w_fftbuf[(i << 1) + 1]; } } } /* inverse FFT */ fftbuf[1] = fftbuf[table->size]; fftbuf[table->size] = fftbuf[(int) table->size + 1] = FL(0.0); csound->InverseRealFFT(csound, fftbuf, (int) table->size); /* copy to table */ for (i = 0; i < table->size; i++) table->ftable[i] = fftbuf[i]; /* write guard point */ table->ftable[table->size] = fftbuf[0]; /* free memory used by temporary buffers */ csound->Free(csound, fftbuf); } /* set default table parameters depending on waveform */ static void vco2_default_table_params(int w, VCO2_TABLE_PARAMS *tp) { tp->waveform = w; tp->w_npart = -1; tp->npart_mul = 1.05; tp->min_size = (w == 2 ? 256 : 128); tp->max_size = (w == 2 ? 16384 : 8192); tp->w_fftbuf = NULL; } /* return number of partials for next table */ static void vco2_next_npart(double *npart, VCO2_TABLE_PARAMS *tp) { double n; n = *npart * tp->npart_mul; if ((n - *npart) < 1.0) (*npart)++; else *npart = n; } /* return optimal table size for a given number of partials */ static int vco2_table_size(int npart, VCO2_TABLE_PARAMS *tp) { int n; if (npart < 1) return 16; /* empty table, size is always 16 */ else if (npart == 1) n = 1; else if (npart <= 4) n = 2; else if (npart <= 16) n = 4; else if (npart <= 64) n = 8; else if (npart <= 256) n = 16; else if (npart <= 1024) n = 32; else n = 64; /* set table size according to min and max value */ n *= tp->min_size; if (n > tp->max_size) n = tp->max_size; return n; } /* Generate table array for the specified waveform (< 0: user defined). */ /* The tables can be accessed also as standard Csound ftables, starting */ /* from table number "base_ftable" if it is greater than zero. */ /* The return value is the first ftable number that is not allocated. */ static int vco2_tables_create(CSOUND *csound, int waveform, int base_ftable, VCO2_TABLE_PARAMS *tp) { STDOPCOD_GLOBALS *pp = get_oscbnk_globals(csound); int i, npart, ntables; double npart_f; VCO2_TABLE_ARRAY *tables; VCO2_TABLE_PARAMS tp2; /* set default table parameters if not specified in tp */ if (tp == NULL) { if (waveform < 0) return -1; vco2_default_table_params(waveform, &tp2); tp = &tp2; } waveform = (waveform < 0 ? 4 - waveform : waveform); if (waveform >= pp->vco2_nr_table_arrays) { /* extend space for table arrays */ ntables = ((waveform >> 4) + 1) << 4; pp->vco2_tables = (VCO2_TABLE_ARRAY**) csound->ReAlloc(csound, pp->vco2_tables, sizeof(VCO2_TABLE_ARRAY*) * ntables); for (i = pp->vco2_nr_table_arrays; i < ntables; i++) pp->vco2_tables[i] = NULL; pp->vco2_nr_table_arrays = ntables; } /* clear table array if already initialised */ if (pp->vco2_tables[waveform] != NULL) { vco2_delete_table_array(csound, waveform); csound->Warning(csound, Str("redefined table array for waveform %d\n"), (waveform > 4 ? 4 - waveform : waveform)); } /* calculate number of tables */ i = tp->max_size >> 1; if (i > VCO2_MAX_NPART) i = VCO2_MAX_NPART; /* max number of partials */ npart_f = 0.0; ntables = 0; do { ntables++; vco2_next_npart(&npart_f, tp); } while (npart_f <= (double) i); /* allocate memory for the table array ... */ tables = pp->vco2_tables[waveform] = (VCO2_TABLE_ARRAY*) csound->Calloc(csound, sizeof(VCO2_TABLE_ARRAY)); /* ... and all tables */ #ifdef VCO2FT_USE_TABLE tables->nparts_tabl = (VCO2_TABLE**) csound->Malloc(csound, sizeof(VCO2_TABLE*) * (VCO2_MAX_NPART + 1)); #else tables->nparts = (MYFLT*) csound->Malloc(csound, sizeof(MYFLT) * (ntables * 3)); for (i = 0; i < ntables; i++) { tables->nparts[i] = FL(-1.0); /* padding for number of partials */ tables->nparts[(ntables << 1) + i] = FL(1.0e24); /* list */ } #endif tables->tables = (VCO2_TABLE*) csound->Calloc(csound, sizeof(VCO2_TABLE) * ntables); /* generate tables */ tables->ntabl = ntables; /* store number of tables */ tables->base_ftnum = base_ftable; /* and base ftable number */ npart_f = 0.0; i = 0; do { /* store number of partials, */ npart = tables->tables[i].npart = (int) (npart_f + 0.5); #ifndef VCO2FT_USE_TABLE tables->nparts[ntables + i] = (MYFLT) npart; #endif /* table size, */ tables->tables[i].size = vco2_table_size(npart, tp); /* and other parameters */ oscbnk_flen_setup((int32) tables->tables[i].size, &(tables->tables[i].mask), &(tables->tables[i].lobits), &(tables->tables[i].pfrac)); /* if base ftable was specified, generate empty table ... */ if (base_ftable > 0) { csound->FTAlloc(csound, base_ftable, (int) tables->tables[i].size); csoundGetTable(csound, &(tables->tables[i].ftable), base_ftable); base_ftable++; /* next table number */ } else /* ... else allocate memory (cannot be accessed as a */ tables->tables[i].ftable = /* standard Csound ftable) */ (MYFLT*) csound->Malloc(csound, sizeof(MYFLT) * (tables->tables[i].size + 1)); /* now calculate the table */ vco2_calculate_table(csound, &(tables->tables[i]), tp); /* next table */ vco2_next_npart(&npart_f, tp); } while (++i < ntables); #ifdef VCO2FT_USE_TABLE /* build table for number of harmonic partials -> table lookup */ i = npart = 0; do { tables->nparts_tabl[npart++] = &(tables->tables[i]); if (i < (ntables - 1) && npart >= tables->tables[i + 1].npart) i++; } while (npart <= VCO2_MAX_NPART); #endif return base_ftable; } /* ---- vco2init opcode ---- */ static int vco2init(CSOUND *csound, VCO2INIT *p) { int waveforms, base_ftable, ftnum, i, w; VCO2_TABLE_PARAMS tp; FUNC *ftp; uint32_t j; /* check waveform number */ waveforms = (int) MYFLT2LRND(*(p->iwaveforms)); if (UNLIKELY(waveforms < -1000000 || waveforms > 31)) { return csound->InitError(csound, Str("vco2init: invalid waveform number: %f"), *(p->iwaveforms)); } /* base ftable number (required by user defined waveforms except -1) */ ftnum = base_ftable = (int) MYFLT2LONG(*(p->iftnum)); if (ftnum < 1) ftnum = base_ftable = -1; if (UNLIKELY((waveforms < -1 && ftnum < 1) || ftnum > 1000000)) { return csound->InitError(csound, Str("vco2init: invalid base ftable number")); } *(p->ift) = (MYFLT) ftnum; if (!waveforms) return OK; /* nothing to do */ w = (waveforms < 0 ? waveforms : 0); do { /* set default table parameters, */ vco2_default_table_params(w, &tp); /* and override with user specified values (if there are any) */ if (*(p->ipmul) > FL(0.0)) { if (UNLIKELY(*(p->ipmul) < FL(1.00999) || *(p->ipmul) > FL(2.00001))) { return csound->InitError(csound, Str("vco2init: invalid " "partial number multiplier")); } tp.npart_mul = (double) *(p->ipmul); } if (*(p->iminsiz) > FL(0.0)) { i = (int) MYFLT2LONG(*(p->iminsiz)); if (UNLIKELY(i < 16 || i > 262144 || (i & (i - 1)))) { return csound->InitError(csound, Str("vco2init: invalid min table size")); } tp.min_size = i; } if (*(p->imaxsiz) > FL(0.0)) { i = (int) MYFLT2LONG(*(p->imaxsiz)); if (UNLIKELY(i < 16 || i > 16777216 || (i & (i - 1)) || i < tp.min_size)) { return csound->InitError(csound, Str("vco2init: invalid max table size")); } tp.max_size = i; } else { tp.max_size = tp.min_size << 6; /* default max size */ if (tp.max_size > 16384) tp.max_size = 16384; if (tp.max_size < tp.min_size) tp.max_size = tp.min_size; } if (w >= 0) { /* built-in waveforms */ if (waveforms & (1 << w)) { ftnum = vco2_tables_create(csound, w, ftnum, &tp); if (UNLIKELY(base_ftable > 0 && ftnum <= 0)) { return csound->InitError(csound, Str("ftgen error")); } } } else { /* user defined, requires source ftable */ if (UNLIKELY((ftp = csound->FTFind(csound, p->isrcft)) == NULL || ftp->flen < 4)) { return csound->InitError(csound, Str("vco2init: invalid source ftable")); } /* analyze source table, and store results in table params structure */ i = ftp->flen; tp.w_npart = i >> 1; tp.w_fftbuf = (MYFLT*) csound->Malloc(csound, sizeof(MYFLT) * (i + 2)); for (j = 0; j < ftp->flen; j++) tp.w_fftbuf[j] = ftp->ftable[j] / (MYFLT) (ftp->flen >> 1); csound->RealFFT(csound, tp.w_fftbuf, (int) ftp->flen); tp.w_fftbuf[ftp->flen] = tp.w_fftbuf[1]; tp.w_fftbuf[1] = tp.w_fftbuf[(int) ftp->flen + 1] = FL(0.0); /* generate table array */ ftnum = vco2_tables_create(csound,waveforms, ftnum, &tp); /* free memory used by FFT buffer */ csound->Free(csound, tp.w_fftbuf); if (UNLIKELY(base_ftable > 0 && ftnum <= 0)) { return csound->InitError(csound, Str("ftgen error")); } } *(p->ift) = (MYFLT) ftnum; w++; } while (w > 0 && w < 5); return OK; } /* ---- vco2ft / vco2ift opcode (initialisation) ---- */ static int vco2ftp(CSOUND *, VCO2FT *); static int vco2ftset(CSOUND *csound, VCO2FT *p) { int w; if (p->vco2_nr_table_arrays == NULL || p->vco2_tables == NULL) { STDOPCOD_GLOBALS *pp = get_oscbnk_globals(csound); p->vco2_nr_table_arrays = &(pp->vco2_nr_table_arrays); p->vco2_tables = &(pp->vco2_tables); } w = (int) MYFLT2LRND(*(p->iwave)); if (w > 4) w = 0x7FFFFFFF; if (w < 0) w = 4 - w; if (UNLIKELY(w >= *(p->vco2_nr_table_arrays) || (*(p->vco2_tables))[w] == NULL || (*(p->vco2_tables))[w]->base_ftnum < 1)) { return csound->InitError(csound, Str("vco2ft: table array " "not found for this waveform")); } #ifdef VCO2FT_USE_TABLE p->nparts_tabl = (*(p->vco2_tables))[w]->nparts_tabl; p->tab0 = (*(p->vco2_tables))[w]->tables; #else /* address of number of partials list (with offset for padding) */ p->nparts = (*(p->vco2_tables))[w]->nparts + (*(p->vco2_tables))[w]->ntabl; p->npart_old = p->nparts + ((*(p->vco2_tables))[w]->ntabl >> 1); #endif p->base_ftnum = (*(p->vco2_tables))[w]->base_ftnum; if (*(p->inyx) > FL(0.5)) p->p_scl = FL(0.5) * CS_ESR; else if (*(p->inyx) < FL(0.001)) p->p_scl = FL(0.001) * CS_ESR; else p->p_scl = *(p->inyx) * CS_ESR; p->p_min = p->p_scl / (MYFLT) VCO2_MAX_NPART; /* in case of vco2ift opcode, find table number now */ if (!strcmp(p->h.optext->t.opcod, "vco2ift")) vco2ftp(csound, p); else /* else set perf routine to avoid */ p->h.opadr = (SUBR) vco2ftp; /* "not initialised" error */ return OK; } /* ---- vco2ft opcode (performance) ---- */ static int vco2ftp(CSOUND *csound, VCO2FT *p) { #ifdef VCO2FT_USE_TABLE MYFLT npart; int n; #else MYFLT npart, *nparts; int nn; #endif npart = (MYFLT)fabs(*(p->kcps)); if (npart < p->p_min) npart = p->p_min; #ifdef VCO2FT_USE_TABLE n = (int) (p->nparts_tabl[(int) (p->p_scl / npart)] - p->tab0); *(p->kft) = (MYFLT) (n + p->base_ftnum); #else npart = p->p_scl / npart; nparts = p->npart_old; if (npart < *nparts) { do { nparts--; nn = 1; while (npart < *(nparts - nn)) { nparts = nparts - nn; nn <<= 1; } } while (nn > 1); } else if (npart >= *(nparts + 1)) { do { nparts++; nn = 1; while (npart >= *(nparts + nn + 1)) { nparts = nparts + nn; nn <<= 1; } } while (nn > 1); } p->npart_old = nparts; *(p->kft) = (MYFLT) ((int) (nparts - p->nparts) + p->base_ftnum); #endif return OK; } static int vco2ft(CSOUND *csound, VCO2FT *p) { return csound->PerfError(csound, p->h.insdshead, Str("vco2ft: not initialised")); } /* ---- vco2 opcode (initialisation) ---- */ static int vco2set(CSOUND *csound, VCO2 *p) { int mode, tnum; int tnums[8] = { 0, 0, 1, 2, 1, 3, 4, 5 }; int modes[8] = { 0, 1, 2, 0, 0, 0, 0, 0 }; MYFLT x; uint32_t min_args; if (p->vco2_nr_table_arrays == NULL || p->vco2_tables == NULL) { STDOPCOD_GLOBALS *pp = get_oscbnk_globals(csound); p->vco2_nr_table_arrays = &(pp->vco2_nr_table_arrays); p->vco2_tables = &(pp->vco2_tables); } /* check number of args */ if (UNLIKELY(p->INOCOUNT > 6)) { return csound->InitError(csound, Str("vco2: too many input arguments")); } mode = (int) MYFLT2LONG(*(p->imode)) & 0x1F; if (mode & 1) return OK; /* skip initialisation */ /* more checks */ min_args = 2; if ((mode & 14) == 2 || (mode & 14) == 4) min_args = 4; if (mode & 16) min_args = 5; if (UNLIKELY(p->INOCOUNT < min_args)) { return csound->InitError(csound, Str("vco2: insufficient required arguments")); } //FIXME // if (UNLIKELY(p->XINCODE)) { // return csound->InitError(csound, Str("vco2: invalid argument type")); // } /* select table array and algorithm, according to waveform */ tnum = tnums[(mode & 14) >> 1]; p->mode = modes[(mode & 14) >> 1]; /* initialise tables if not done yet */ if (tnum >= *(p->vco2_nr_table_arrays) || (*(p->vco2_tables))[tnum] == NULL) { if (LIKELY(tnum < 5)) vco2_tables_create(csound, tnum, -1, NULL); else { return csound->InitError(csound, Str("vco2: table array not found for " "user defined waveform")); } } #ifdef VCO2FT_USE_TABLE p->nparts_tabl = (*(p->vco2_tables))[tnum]->nparts_tabl; #else /* address of number of partials list (with offset for padding) */ p->nparts = (*(p->vco2_tables))[tnum]->nparts + (*(p->vco2_tables))[tnum]->ntabl; p->npart_old = p->nparts + ((*(p->vco2_tables))[tnum]->ntabl >> 1); p->tables = (*(p->vco2_tables))[tnum]->tables; #endif /* set misc. parameters */ p->init_k = 1; p->pm_enabled = (mode & 16 ? 1 : 0); if ((mode & 16) || (p->INOCOUNT < 5)) p->phs = 0UL; else { x = *(p->kphs); x -= (MYFLT) ((int32) x); p->phs = OSCBNK_PHS2INT(x); } p->f_scl = csound->onedsr; x = (p->INOCOUNT < 6 ? FL(0.5) : *(p->inyx)); if (x < FL(0.001)) x = FL(0.001); if (x > FL(0.5)) x = FL(0.5); p->p_min = x / (MYFLT) VCO2_MAX_NPART; p->p_scl = x; return OK; } /* ---- vco2 opcode (performance) ---- */ static int vco2(CSOUND *csound, VCO2 *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, nsmps = CS_KSMPS; int n; VCO2_TABLE *tabl; uint32 phs, phs2, frq, frq2, lobits, mask; #ifdef VCO2FT_USE_TABLE MYFLT f, f1, npart, pfrac, v, *ftable, kamp, *ar; if (UNLIKELY(p->nparts_tabl == NULL)) { #else MYFLT f, f1, npart, *nparts, pfrac, v, *ftable, kamp, *ar; if (UNLIKELY(p->tables == NULL)) { #endif return csound->PerfError(csound, p->h.insdshead, Str("vco2: not initialised")); } /* if 1st k-cycle, initialise now */ if (p->init_k) { p->init_k = 0; if (p->pm_enabled) { f = p->kphs_old = *(p->kphs); f -= (MYFLT) ((int32) f); p->phs = OSCBNK_PHS2INT(f); } if (p->mode) { p->kphs2_old = -(*(p->kpw)); f = p->kphs2_old; f -= (MYFLT) ((int32) f); p->phs2 = (p->phs + OSCBNK_PHS2INT(f)) & OSCBNK_PHSMSK; } } ar = p->ar; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } /* calculate frequency (including phase modulation) */ f = *(p->kcps) * p->f_scl; frq = OSCBNK_PHS2INT(f); if (p->pm_enabled) { f1 = (MYFLT) ((double) *(p->kphs) - (double) p->kphs_old) / (nsmps-offset); p->kphs_old = *(p->kphs); frq = (frq + OSCBNK_PHS2INT(f1)) & OSCBNK_PHSMSK; f += f1; } /* find best table for current frequency */ npart = (MYFLT)fabs(f); if (npart < p->p_min) npart = p->p_min; #ifdef VCO2FT_USE_TABLE tabl = p->nparts_tabl[(int) (p->p_scl / npart)]; #else npart = p->p_scl / npart; nparts = p->npart_old; if (npart < *nparts) { do { nparts--; nn = 1; while (npart < *(nparts - nn)) { nparts = nparts - nn; nn <<= 1; } } while (nn > 1); } else if (npart >= *(nparts + 1)) { do { nparts++; nn = 1; while (npart >= *(nparts + nn + 1)) { nparts = nparts + nn; nn <<= 1; } } while (nn > 1); } p->npart_old = nparts; tabl = p->tables + (int) (nparts - p->nparts); #endif /* copy object data to local variables */ kamp = *(p->kamp); phs = p->phs; lobits = tabl->lobits; mask = tabl->mask; pfrac = tabl->pfrac; ftable = tabl->ftable; if (!p->mode) { /* - mode 0: simple table playback - */ for (nn=offset; nn> lobits; v = ftable[n++]; v += (ftable[n] - v) * (MYFLT) ((int32) (phs & mask)) * pfrac; phs = (phs + frq) & OSCBNK_PHSMSK; ar[nn] = v * kamp; } } else { v = -(*(p->kpw)); /* pulse width */ f1 = (MYFLT) ((double) v - (double) p->kphs2_old) / (nsmps-offset); f = p->kphs2_old; f -= (MYFLT) ((int32) f); if (f < FL(0.0)) f++; p->kphs2_old = v; phs2 = p->phs2; frq2 = (frq + OSCBNK_PHS2INT(f1)) & OSCBNK_PHSMSK; if (p->mode == 1) { /* - mode 1: PWM - */ /* DC correction offset */ f = FL(1.0) - FL(2.0) * f; f1 *= FL(-2.0); for (nn=offset; nn> lobits; v = ftable[n++]; ar[nn] = v + (ftable[n] - v) * (MYFLT) ((int32) (phs & mask)) * pfrac; n = phs2 >> lobits; v = ftable[n++]; v += (ftable[n] - v) * (MYFLT) ((int32) (phs2 & mask)) * pfrac; ar[nn] = (ar[nn] - v + f) * kamp; phs = (phs + frq) & OSCBNK_PHSMSK; phs2 = (phs2 + frq2) & OSCBNK_PHSMSK; f += f1; } } else { /* - mode 2: saw / triangle ramp - */ for (nn=offset; nn> lobits; v = ftable[n++]; ar[nn] = v + (ftable[n] - v) * (MYFLT) ((int32) (phs & mask)) * pfrac; n = phs2 >> lobits; v = ftable[n++]; v += (ftable[n] - v) * (MYFLT) ((int32) (phs2 & mask)) * pfrac; ar[nn] = (ar[nn] - v) * (FL(0.25) / (f - f * f)) * kamp; phs = (phs + frq) & OSCBNK_PHSMSK; phs2 = (phs2 + frq2) & OSCBNK_PHSMSK; f += f1; } } p->phs2 = phs2; } /* save oscillator phase */ p->phs = phs; return OK; } /* ---- denorm opcode ---- */ #ifndef USE_DOUBLE #define DENORM_RND ((MYFLT) ((*seed = (*seed * 15625 + 1) & 0xFFFF) - 0x8000) \ * FL(1.0e-24)) #else #define DENORM_RND ((MYFLT) ((*seed = (*seed * 15625 + 1) & 0xFFFF) - 0x8000) \ * FL(1.0e-60)) #endif static int denorms(CSOUND *csound, DENORMS *p) { MYFLT r, *ar, **args = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn, nsmps = CS_KSMPS; int n = p->INOCOUNT, *seed; seed = p->seedptr; if (seed == NULL) { STDOPCOD_GLOBALS *pp = get_oscbnk_globals(csound); seed = p->seedptr = &(pp->denorm_seed); } if (UNLIKELY(early)) nsmps -= early; do { r = DENORM_RND; ar = *args++; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); for (nn=offset; nnimode) & 3; if (mode & 1) return OK; /* skip initialisation */ p->mode = mode; /* calculate delay time */ npts = (int) (*p->idel * CS_EKR + FL(1.5)); if (UNLIKELY(npts < 1)) return csound->InitError(csound, Str("delayk: invalid delay time " "(must be >= 0)")); p->readp = 0; p->npts = npts; /* allocate space for delay buffer */ if (p->aux.auxp == NULL || (unsigned int)(npts * sizeof(MYFLT)) > p->aux.size) { csound->AuxAlloc(csound, (int32) (npts * sizeof(MYFLT)), &p->aux); } p->init_k = npts - 1; return OK; } static int delayk(CSOUND *csound, DELAYK *p) { MYFLT *buf = (MYFLT*) p->aux.auxp; if (UNLIKELY(!buf)) return csound->PerfError(csound, p->h.insdshead, Str("delayk: not initialised")); buf[p->readp++] = *(p->ksig); /* write input signal to buffer */ if (p->readp >= p->npts) p->readp = 0; /* wrap index */ if (p->init_k) { *(p->ar) = (p->mode & 2 ? *(p->ksig) : FL(0.0)); /* initial delay */ p->init_k--; } else *(p->ar) = buf[p->readp]; /* read output signal */ return OK; } static int vdelaykset(CSOUND *csound, VDELAYK *p) { int npts, mode = (int) MYFLT2LONG(*p->imode) & 3; if (mode & 1) return OK; /* skip initialisation */ p->mode = mode; /* calculate max. delay time */ npts = (int) (*p->imdel * CS_EKR + FL(1.5)); if (UNLIKELY(npts < 1)) return csound->InitError(csound, Str("vdel_k: invalid max delay time " "(must be >= 0)")); p->wrtp = 0; p->npts = npts; /* allocate space for delay buffer */ if (p->aux.auxp == NULL || (unsigned int)(npts * sizeof(MYFLT)) > p->aux.size) { csound->AuxAlloc(csound, (int32) (npts * sizeof(MYFLT)), &p->aux); } p->init_k = npts; /* not -1 this time ! */ return OK; } static int vdelayk(CSOUND *csound, VDELAYK *p) { MYFLT *buf = (MYFLT*) p->aux.auxp; int n, npts = p->npts; if (UNLIKELY(!buf)) return csound->PerfError(csound, p->h.insdshead, Str("vdel_k: not initialised")); buf[p->wrtp] = *(p->ksig); /* write input signal to buffer */ /* calculate delay time */ n = (int) MYFLT2LONG(*(p->kdel) * CS_EKR); if (UNLIKELY(n < 0)) return csound->PerfError(csound, p->h.insdshead, Str("vdel_k: invalid delay time " "(must be >= 0)")); n = p->wrtp - n; if (++p->wrtp >= npts) p->wrtp = 0; /* wrap index */ if (p->init_k) { if (p->mode & 2) { if (npts == p->init_k) p->frstkval = *(p->ksig); /* save first input value */ *(p->ar) = (n < 0 ? p->frstkval : buf[n]); /* initial delay */ } else { *(p->ar) = (n < 0 ? FL(0.0) : buf[n]); } p->init_k--; } else { while (n < 0) n += npts; *(p->ar) = buf[n]; /* read output signal */ } return OK; } /* ------------ rbjeq opcode ------------ */ /* original algorithm by Robert Bristow-Johnson */ /* Csound orchestra version by Josep M Comajuncosas, Aug 1999 */ /* ported to C (and optimised) by Istvan Varga, Dec 2002 */ /* ar rbjeq asig, kfco, klvl, kQ, kS[, imode] */ /* IV - Dec 28 2002: according to the original version by JMC, the formula */ /* alpha = sin(omega) * sinh(1 / (2 * Q)) */ /* should be used to calculate Q. However, according to my tests, it seems */ /* to be wrong with low Q values, where this simplified code */ /* alpha = sin(omega) / (2 * Q) */ /* was measured to be more accurate. It also makes the Q value for no */ /* resonance exactly sqrt(0.5) (as it would be expected), while the old */ /* version required a Q setting of about 0.7593 for no resonance. */ /* With Q >= 1, there is not much difference. */ /* N.B.: the above apply to the lowpass and highpass filters only. For */ /* bandpass, band-reject, and peaking EQ, the modified formula is */ /* alpha = tan(omega / (2 * Q)) */ /* Defining this macro selects the revised version, while commenting it */ /* out enables the original. */ /* #undef IV_Q_CALC */ #define IV_Q_CALC 1 static int rbjeqset(CSOUND *csound, RBJEQ *p) { int mode = (int) MYFLT2LONG(*p->imode) & 0xF; if (mode & 1) return OK; /* skip initialisation */ /* filter type */ p->ftype = mode >> 1; /* reset filter */ p->old_kcps = p->old_klvl = p->old_kQ = p->old_kS = FL(-1.12123e35); p->b0 = p->b1 = p->b2 = p->a1 = p->a2 = FL(0.0); p->xnm1 = p->xnm2 = p->ynm1 = p->ynm2 = FL(0.0); return OK; } static int rbjeq(CSOUND *csound, RBJEQ *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int new_frq; MYFLT b0, b1, b2, a1, a2, tmp; MYFLT xnm1, xnm2, ynm1, ynm2; MYFLT *ar, *asig; double dva0; if (*(p->kcps) != p->old_kcps) { /* frequency changed */ new_frq = 1; p->old_kcps = *(p->kcps); /* calculate variables that depend on freq., and are used by all modes */ p->omega = (double) p->old_kcps * TWOPI / (double) CS_ESR; p->cs = cos(p->omega); p->sn = sqrt(1.0 - p->cs * p->cs); //printf("**** (%d) p->cs = %f\n", __LINE__, p->cs); } else new_frq = 0; /* copy object data to local variables */ ar = p->ar; asig = p->asig; xnm1 = p->xnm1; xnm2 = p->xnm2; ynm1 = p->ynm1; ynm2 = p->ynm2; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } switch (p->ftype) { case 0: /* lowpass filter */ if (new_frq || *(p->kQ) != p->old_kQ) { double alpha; p->old_kQ = *(p->kQ); #ifdef IV_Q_CALC alpha = p->sn * 0.5 / (double) p->old_kQ; /* IV - Dec 28 2002 */ #else alpha = p->sn * sinh(0.5 / (double) p->old_kQ); #endif /* recalculate all coeffs */ dva0 = 1.0 / (1.0 + alpha); p->b2 = (MYFLT) (0.5 * (dva0 - dva0 * p->cs)); p->a1 = (MYFLT) (-2.0 * dva0 * p->cs); p->a2 = (MYFLT) (dva0 - dva0 * alpha); } b2 = p->b2; a1 = p->a1; a2 = p->a2; for (n=offset; nkQ) != p->old_kQ) { double alpha; p->old_kQ = *(p->kQ); #ifdef IV_Q_CALC alpha = p->sn * 0.5 / (double) p->old_kQ; /* IV - Dec 28 2002 */ #else alpha = p->sn * sinh(0.5 / (double) p->old_kQ); #endif /* recalculate all coeffs */ dva0 = 1.0 / (1.0 + alpha); p->b2 = (MYFLT) (0.5 * (dva0 + dva0 * p->cs)); p->a1 = (MYFLT) (-2.0 * dva0 * p->cs); p->a2 = (MYFLT) (dva0 - dva0 * alpha); } b2 = p->b2; a1 = p->a1; a2 = p->a2; for (n=offset; nkQ) != p->old_kQ) { double alpha; p->old_kQ = *(p->kQ); #ifdef IV_Q_CALC alpha = tan(p->omega * 0.5 / (double) p->old_kQ); /* IV - Dec 28 2002 */ #else alpha = p->sn * sinh(0.5 / (double) p->old_kQ); #endif /* recalculate all coeffs */ dva0 = 1.0 / (1.0 + alpha); p->b2 = (MYFLT) (dva0 * alpha); p->a1 = (MYFLT) (-2.0 * dva0 * p->cs); p->a2 = (MYFLT) (dva0 - dva0 * alpha); } b2 = p->b2; a1 = p->a1; a2 = p->a2; for (n=offset; nkQ) != p->old_kQ) { double alpha; p->old_kQ = *(p->kQ); #ifdef IV_Q_CALC alpha = tan(p->omega * 0.5 / (double) p->old_kQ); /* IV - Dec 28 2002 */ #else alpha = p->sn * sinh(0.5 / (double) p->old_kQ); #endif /* recalculate all coeffs */ dva0 = 1.0 / (1.0 + alpha); p->b2 = (MYFLT) dva0; p->a1 = (MYFLT) (-2.0 * dva0 * p->cs); p->a2 = (MYFLT) (dva0 - dva0 * alpha); } b2 = p->b2; a1 = p->a1; a2 = p->a2; for (n=offset; nkQ) != p->old_kQ || *(p->klvl) != p->old_klvl) { double sq, alpha, tmp1, tmp2; p->old_kQ = *(p->kQ); sq = sqrt((double) (p->old_klvl = *(p->klvl))); //printf("*** (%d) p->old_klvl\n", __LINE__, p->old_klvl); #ifdef IV_Q_CALC alpha = tan(p->omega * 0.5 / (double) p->old_kQ); /* IV - Dec 28 2002 */ #else alpha = p->sn * sinh(0.5 / (double) p->old_kQ); #endif /* recalculate all coeffs */ tmp1 = alpha / sq; dva0 = 1.0 / (1.0 + tmp1); tmp2 = alpha * sq * dva0; p->b0 = (MYFLT) (dva0 + tmp2); p->b2 = (MYFLT) (dva0 - tmp2); p->a1 = (MYFLT) (-2.0 * dva0 * p->cs); p->a2 = (MYFLT) (dva0 - dva0 * tmp1); } b0 = p->b0; b2 = p->b2; a1 = p->a1; a2 = p->a2; for (n=offset; nklvl) != p->old_klvl || *(p->kS) != p->old_kS) { double sq, beta, tmp1, tmp2, tmp3, tmp4; sq = sqrt((double) (p->old_klvl = *(p->klvl))); p->old_kS = *(p->kS); beta = p->sn * sqrt(((double) p->old_klvl + 1.0) / p->old_kS - (double) p->old_klvl + sq + sq - 1.0); /* recalculate all coeffs */ tmp1 = sq + 1.0; tmp2 = sq - 1.0; tmp3 = tmp1 * p->cs; tmp4 = tmp2 * p->cs; dva0 = 1.0 / (tmp1 + tmp4 + beta); p->a1 = (MYFLT) (-2.0 * dva0 * (tmp2 + tmp3)); p->a2 = (MYFLT) (dva0 * (tmp1 + tmp4 - beta)); dva0 *= sq; p->b0 = (MYFLT) (dva0 * (tmp1 - tmp4 + beta)); p->b1 = (MYFLT) ((dva0 + dva0) * (tmp2 - tmp3)); p->b2 = (MYFLT) (dva0 * (tmp1 - tmp4 - beta)); } b0 = p->b0; b1 = p->b1; b2 = p->b2; a1 = p->a1; a2 = p->a2; for (n=offset; nklvl) != p->old_klvl || *(p->kS) != p->old_kS) { double sq, beta, tmp1, tmp2, tmp3, tmp4; sq = sqrt((double) (p->old_klvl = *(p->klvl))); p->old_kS = *(p->kS); beta = p->sn * sqrt(((double) p->old_klvl + 1.0) / p->old_kS - (double) p->old_klvl + sq + sq - 1.0); /* recalculate all coeffs */ tmp1 = sq + 1.0; tmp2 = sq - 1.0; tmp3 = tmp1 * p->cs; tmp4 = tmp2 * p->cs; dva0 = 1.0 / (tmp1 - tmp4 + beta); p->a1 = (MYFLT) ((dva0 + dva0) * (tmp2 - tmp3)); p->a2 = (MYFLT) (dva0 * (tmp1 - tmp4 - beta)); dva0 *= sq; p->b0 = (MYFLT) (dva0 * (tmp1 + tmp4 + beta)); p->b1 = (MYFLT) (-2.0 * dva0 * (tmp2 + tmp3)); p->b2 = (MYFLT) (dva0 * (tmp1 + tmp4 - beta)); } b0 = p->b0; b1 = p->b1; b2 = p->b2; a1 = p->a1; a2 = p->a2; for (n=offset; nPerfError(csound, p->h.insdshead, Str("rbjeq: invalid filter type")); break; } /* save filter state */ p->xnm1 = xnm1; p->xnm2 = xnm2; p->ynm1 = ynm1; p->ynm2 = ynm2; return OK; } /* ------------------------------------------------------------------------- */ static const OENTRY localops[] = { { "oscbnk", sizeof(OSCBNK), TR, 5, "a", "kkkkiikkkkikkkkkkikooooooo", (SUBR) oscbnkset, (SUBR) NULL, (SUBR) oscbnk }, { "grain2", sizeof(GRAIN2), TR, 5, "a", "kkkikiooo", (SUBR) grain2set, (SUBR) NULL, (SUBR) grain2 }, { "grain3", sizeof(GRAIN3), TR, 5, "a", "kkkkkkikikkoo", (SUBR) grain3set, (SUBR) NULL, (SUBR) grain3 }, { "rnd31", 0xFFFF, 0, 0, NULL, NULL, (SUBR) NULL, (SUBR) NULL, (SUBR) NULL }, { "rnd31.i", sizeof(RND31), 0, 1, "i", "iio", (SUBR) rnd31i, (SUBR) NULL, (SUBR) NULL }, { "rnd31.k", sizeof(RND31), 0, 3, "k", "kko", (SUBR) rnd31set, (SUBR) rnd31k, (SUBR) NULL }, { "rnd31.a", sizeof(RND31), 0, 5, "a", "kko", (SUBR) rnd31set, (SUBR) NULL, (SUBR) rnd31a }, { "oscilikt", 0xFFFE, TR }, { "oscilikt.a", sizeof(OSCKT), 0, 5, "a", "kkkoo", (SUBR) oscktset, NULL, (SUBR)osckkikt }, { "oscilikt.kk", sizeof(OSCKT), 0, 3, "k", "kkkoo", (SUBR) oscktset, (SUBR) kosclikt, NULL }, { "oscilikt.ka", sizeof(OSCKT), 0, 5, "a", "kakoo", (SUBR) oscktset, (SUBR) NULL, (SUBR) osckaikt }, { "oscilikt.ak", sizeof(OSCKT), 0, 5, "a", "akkoo", (SUBR) oscktset, (SUBR) NULL, (SUBR) oscakikt }, { "oscilikt.aa", sizeof(OSCKT), 0, 5, "a", "aakoo", (SUBR) oscktset, (SUBR) NULL, (SUBR) oscaaikt }, { "osciliktp", sizeof(OSCKTP), TR, 5, "a", "kkko", (SUBR) oscktpset, (SUBR) NULL, (SUBR) oscktp }, { "oscilikts", sizeof(OSCKTS), TR, 5, "a", "xxkako", (SUBR) oscktsset, (SUBR) NULL, (SUBR) osckts }, { "vco2init", sizeof(VCO2INIT), TW, 1, "i", "ijjjjj", (SUBR) vco2init, (SUBR) NULL, (SUBR) NULL }, { "vco2ift", sizeof(VCO2FT), TW, 1, "i", "iov", (SUBR) vco2ftset, (SUBR) NULL, (SUBR) NULL }, { "vco2ft", sizeof(VCO2FT), TW, 3, "k", "kov", (SUBR) vco2ftset, (SUBR) vco2ft, (SUBR) NULL }, // { "vco2", sizeof(VCO2), TR, 5, "a", "kkoM", { "vco2", sizeof(VCO2), TR, 5, "a", "kkoOOo", (SUBR) vco2set, (SUBR) NULL, (SUBR) vco2 }, { "denorm", sizeof(DENORMS), 0, 4, "", "y", (SUBR) NULL, (SUBR) NULL, (SUBR) denorms }, { "delayk", sizeof(DELAYK), 0, 3, "k", "kio", (SUBR) delaykset, (SUBR) delayk, (SUBR) NULL }, { "vdel_k", sizeof(VDELAYK), 0, 3, "k", "kkio", (SUBR) vdelaykset, (SUBR) vdelayk, (SUBR) NULL }, { "rbjeq", sizeof(RBJEQ), 0, 5, "a", "akkkko", (SUBR) rbjeqset, (SUBR) NULL, (SUBR) rbjeq } }; int oscbnk_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/oscbnk.h000066400000000000000000000270551321653344700161360ustar00rootroot00000000000000/* oscbnk.h: Copyright (C) 2002, 2005 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef CSOUND_OSCBNK_H #define CSOUND_OSCBNK_H #include "stdopcod.h" /* #ifdef B64BIT #define MAXLEN 0x40000000 #define FMAXLEN ((MYFLT)(MAXLEN)) #define PHMASK 0x3fffffff #else #define MAXLEN 0x1000000L #define FMAXLEN ((MYFLT)(MAXLEN)) #define PHMASK 0x0FFFFFFL #endif */ /* ---- oscbnk, grain2, and grain3 - written by Istvan Varga, 2001 ---- */ #define OSCBNK_PHSMAX 0x80000000UL /* max. phase */ #define OSCBNK_PHSMSK 0x7FFFFFFFUL /* phase mask */ #define OSCBNK_RNDPHS 0 /* 31 bit rand -> phase bit shift */ /* convert floating point phase value to integer */ #define OSCBNK_PHS2INT(x) \ ((uint32) MYFLT2LRND((x) * (MYFLT) OSCBNK_PHSMAX) & OSCBNK_PHSMSK) /* oscbnk types */ typedef struct { uint32 LFO1phs; /* LFO 1 phase */ MYFLT LFO1frq; /* LFO 1 frequency (0-1) */ uint32 LFO2phs; /* LFO 2 phase */ MYFLT LFO2frq; /* LFO 2 frequency (0-1) */ uint32 osc_phs; /* main oscillator phase */ MYFLT osc_phm; /* phase mod. */ MYFLT osc_frq, osc_amp; /* osc. freq. / sr, amplitude */ MYFLT xnm1, xnm2, ynm1, ynm2; /* EQ tmp data */ MYFLT a1, a2, b0, b1, b2; /* EQ coeffs saved for interp. */ } OSCBNK_OSC; typedef struct { OPDS h; MYFLT *args[27]; /* opcode args (see manual) */ int init_k; /* 1st k-cycle (0: no, 1: yes) */ int nr_osc; /* number of oscillators */ int32 seed; /* random seed */ int ilfomode, ieqmode; /* LFO and EQ mode */ int eq_interp; /* enable filter coeff. interp. */ MYFLT frq_scl; /* constants for calculating */ MYFLT lf1_scl, lf1_ofs; /* k-rate parameters */ MYFLT lf2_scl, lf2_ofs; MYFLT eqo_scl, eqo_ofs; MYFLT eql_scl, eql_ofs; MYFLT eqq_scl, eqq_ofs; MYFLT *l1t, l1t_pfrac; /* LFO 1 ftable */ uint32 l1t_mask, l1t_lobits; MYFLT *l2t, l2t_pfrac; /* LFO 2 ftable */ uint32 l2t_mask, l2t_lobits; MYFLT *eqft; /* EQ frequency table */ int32 eqft_len; MYFLT *eqlt; /* EQ level table */ int32 eqlt_len; MYFLT *eqqt; /* EQ Q table */ int32 eqqt_len; MYFLT *tabl; /* parameter input table */ int32 tabl_len; /* (optional) */ MYFLT *outft; /* parameter output table */ int32 outft_len; /* (optional) */ int32 tabl_cnt; /* current param in table */ AUXCH auxdata; OSCBNK_OSC *osc; /* oscillator array */ } OSCBNK; /* grain2 types */ typedef struct { uint32 grain_phs; /* grain phase */ uint32 grain_frq_int; /* grain frequency (integer) */ MYFLT grain_frq_flt; /* grain frequency (float) */ uint32 window_phs; /* window phase */ } GRAIN2_OSC; typedef struct { OPDS h; MYFLT *ar, *kcps, *kfmd; /* opcode args */ MYFLT *kgdur, *iovrlp; MYFLT *kfn, *iwfn, *irpow; MYFLT *iseed, *imode; int init_k; /* 1st k-cycle (0: no, 1: yes) */ int mode; /* imode (see manual) */ int nr_osc; /* number of oscillators */ int32 seed; /* random seed */ int rnd_mode; /* random distribution params */ MYFLT rnd_pow; MYFLT grain_frq, frq_scl; /* grain frequency */ MYFLT *wft, wft_pfrac; /* window table */ uint32 wft_lobits, wft_mask; AUXCH auxdata; GRAIN2_OSC *osc; /* oscillator array */ } GRAIN2; /* -------- grain3 types -------- */ typedef struct { OPDS h; MYFLT *ar, *kcps, *kphs; /* opcode args */ MYFLT *kfmd, *kpmd; MYFLT *kgdur, *kdens; MYFLT *imaxovr, *kfn, *iwfn; MYFLT *kfrpow, *kprpow; MYFLT *iseed, *imode; int init_k; /* 1st k-cycle (0: no, 1: yes) */ int mode; /* imode (see manual) */ int ovrlap; /* max. number of oscillators */ int32 seed; /* random seed */ int f_rnd_mode; /* random distribution (freq.) */ MYFLT f_rnd_pow; int p_rnd_mode, pm_wrap; /* random distribution (phase) */ MYFLT p_rnd_pow; uint32 grain_frq; /* grain frequency */ MYFLT frq_scl; MYFLT phs0; /* prev. kphs value for interp. */ uint32 x_phs; MYFLT *wft, wft_pfrac; /* window table */ uint32 wft_lobits, wft_mask; AUXCH auxdata; uint32 *phase; /* grain phase offset */ GRAIN2_OSC *osc; /* oscillator array */ GRAIN2_OSC *osc_start; /* first active grain */ GRAIN2_OSC *osc_end; /* last active grain + 1 */ GRAIN2_OSC *osc_max; /* ptr to last osc in array */ } GRAIN3; /* -------- rnd31 types -------- */ typedef struct { OPDS h; /* opcode args */ MYFLT *out; /* output signal */ MYFLT *scl; /* scale */ MYFLT *rpow; /* distribution */ MYFLT *iseed; /* seed */ /* internal variables */ int32 *rnd31i_seed; /* global seed for rnd31 */ int32 seed; /* random seed */ } RND31; /* -------- oscilikt types -------- */ typedef struct { OPDS h; MYFLT *sr, *xamp, *xcps, *kfn, *iphs, *istor; uint32 phs, lobits, mask; MYFLT pfrac, *ft, oldfn; } OSCKT; typedef struct { OPDS h; MYFLT *ar, *kcps, *kfn, *kphs, *istor; uint32 phs, lobits, mask; MYFLT pfrac, *ft, oldfn, old_phs; int init_k; } OSCKTP; typedef struct { OPDS h; MYFLT *ar, *xamp, *xcps, *kfn, *async, *kphs, *istor; uint32 phs, lobits, mask; MYFLT pfrac, *ft, oldfn; int init_k; } OSCKTS; /* ---- vco2init, vco2ft, and vco2 opcodes by Istvan Varga, Sep 2002 ---- */ /* Select algorithm to be used for finding table numbers */ /* Define this macro to use simple table lookup (slower */ /* at high control rate, due to float->int cast), or */ /* comment it out to use a search algorithm (slower with */ /* very fast changes in frequency) */ #define VCO2FT_USE_TABLE 1 typedef struct { int npart; /* number of harmonic partials (may be zero) */ int size; /* size of the table (not incl. guard point) */ uint32 /* parameters needed for reading the table, */ lobits, mask; /* and interpolation */ MYFLT pfrac; MYFLT *ftable; /* table data (size + 1 floats) */ } VCO2_TABLE; struct VCO2_TABLE_ARRAY_ { int ntabl; /* number of tables */ int base_ftnum; /* base ftable number (-1: none) */ #ifdef VCO2FT_USE_TABLE VCO2_TABLE **nparts_tabl; /* table ptrs for all numbers of partials */ #else MYFLT *nparts; /* number of partials list */ #endif VCO2_TABLE *tables; /* array of table structures */ }; typedef struct { OPDS h; MYFLT *ift, *iwaveforms, *iftnum, *ipmul, *iminsiz, *imaxsiz, *isrcft; } VCO2INIT; typedef struct { OPDS h; MYFLT *ar, *kamp, *kcps, *imode, *kpw, *kphs, *inyx; MYFLT *dummy[9]; #ifdef VCO2FT_USE_TABLE VCO2_TABLE **nparts_tabl; /* table ptrs for all numbers of partials */ #endif int init_k; /* 1 in first k-cycle, 0 otherwise */ int mode; /* algorithm (0, 1, or 2) */ int pm_enabled; /* phase modulation enabled (0: no, 1: yes) */ #ifdef VCO2FT_USE_TABLE MYFLT f_scl, p_min, p_scl, kphs_old, kphs2_old; #else MYFLT f_scl, p_min, p_scl, *npart_old, *nparts, kphs_old, kphs2_old; VCO2_TABLE *tables; /* pointer to array of tables */ #endif uint32 phs, phs2; /* oscillator phase */ VCO2_TABLE_ARRAY ***vco2_tables; int *vco2_nr_table_arrays; } VCO2; typedef struct { OPDS h; MYFLT *kft, *kcps, *iwave, *inyx; MYFLT p_min, p_scl; #ifdef VCO2FT_USE_TABLE VCO2_TABLE **nparts_tabl, *tab0; #else MYFLT *npart_old, *nparts; #endif VCO2_TABLE_ARRAY ***vco2_tables; int *vco2_nr_table_arrays; int base_ftnum; } VCO2FT; typedef struct { /* denorm a1[, a2[, a3[, ... ]]] */ OPDS h; MYFLT *ar[256]; int *seedptr; } DENORMS; typedef struct { /* kr delayk ksig, idel[, imode] */ OPDS h; MYFLT *ar, *ksig, *idel, *imode; int npts, init_k, readp, mode; AUXCH aux; } DELAYK; typedef struct { /* kr vdel_k ksig, kdel, imdel[, imode] */ OPDS h; MYFLT *ar, *ksig, *kdel, *imdel, *imode; int npts, init_k, wrtp, mode; MYFLT frstkval; AUXCH aux; } VDELAYK; typedef struct { /* ar rbjeq asig, kfco, klvl, kQ, kS[, imode] */ OPDS h; MYFLT *ar, *asig, *kcps, *klvl, *kQ, *kS, *imode; /* args */ /* internal variables */ MYFLT old_kcps, old_klvl, old_kQ, old_kS; double omega, cs, sn; MYFLT xnm1, xnm2, ynm1, ynm2; MYFLT b0, b1, b2, a1, a2; int ftype; } RBJEQ; #endif /* CSOUND_OSCBNK_H */ csound-6.10.0/Opcodes/p5g_mac000066400000000000000000000012701321653344700157330ustar00rootroot00000000000000#define P5G_BUTTONS #0# #define P5G_BUTTON_A #1# #define P5G_BUTTON_B #2# #define P5G_BUTTON_C #4# #define P5G_JUSTPUSH #8# #define P5G_JUSTPU_A #9# #define P5G_JUSTPU_B #10# #define P5G_JUSTPU_C #12# #define P5G_RELEASED #16# #define P5G_RELSED_A #17# #define P5G_RELSED_B #18# #define P5G_RELSED_C #20# #define P5G_FINGER_INDEX #32# #define P5G_FINGER_MIDDLE #33# #define P5G_FINGER_RING #34# #define P5G_FINGER_PINKY #35# #define P5G_FINGER_THUMB #36# #define P5G_DELTA_X #37# #define P5G_DELTA_Y #38# #define P5G_DELTA_Z #39# #define P5G_DELTA_XR #40# #define P5G_DELTA_YR #41# #define P5G_DELTA_ZR #42# #define P5G_ANGLES #43# csound-6.10.0/Opcodes/p5glove.c000066400000000000000000000165721321653344700162350ustar00rootroot00000000000000/* p5glove.c: Copyright (C) 2009 by John ffitch, This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* p5glove.c */ #include "csdl.h" #include #include typedef struct { OPDS h; /* ------------------------------------- */ void *thread; int on; } P5GLOVEINIT; typedef struct { OPDS h; MYFLT *res; MYFLT *kControl; MYFLT *num; /* ------------------------------------- */ uint32_t last; } P5GLOVE; typedef struct { OPDS h; MYFLT *iControl; MYFLT *iMin; MYFLT *iMax; MYFLT *num; } P5GRANGE; #define P5G_BUTTONS 0 #define P5G_BUTTON_A 1 #define P5G_BUTTON_B 2 #define P5G_BUTTON_C 4 #define P5G_JUSTPUSH 8 #define P5G_JUSTPU_A 9 #define P5G_JUSTPU_B 10 #define P5G_JUSTPU_C 12 #define P5G_RELEASED 16 #define P5G_RELSED_A 17 #define P5G_RELSED_B 18 #define P5G_RELSED_C 20 #define P5G_FINGER_INDEX 32 #define P5G_FINGER_MIDDLE 33 #define P5G_FINGER_RING 34 #define P5G_FINGER_PINKY 35 #define P5G_FINGER_THUMB 36 #define P5G_DELTA_X 37 #define P5G_DELTA_Y 38 #define P5G_DELTA_Z 39 #define P5G_DELTA_XR 40 #define P5G_DELTA_YR 41 #define P5G_DELTA_ZR 42 #define P5G_ANGLES 43 //P5Glove myGlove; uintptr_t runp5thread(void *g) { P5Glove *glove = (P5Glove *)g; while (*glove) { p5glove_sample(*glove, 0.2); } return 0; } int p5g_deinit(CSOUND *csound, P5GLOVEINIT *p) { p->on = 0; return pthread_cancel((pthread_t)(p->thread)); } int p5glove_find(CSOUND *csound, P5GLOVEINIT *p) { P5Glove *glove = (P5Glove*)csound->QueryGlobalVariable(csound, "p5glove"); if (glove == NULL) { csound->CreateGlobalVariable(csound, "p5glove", sizeof(P5Glove)); glove = (P5Glove*)csound->QueryGlobalVariable(csound, "p5glove"); } *glove = p5glove_open(0); if (UNLIKELY(*glove==NULL)) { return csound->InitError(csound, Str("unable to open p5glove\n")); } p->on = 1; csound->RegisterDeinitCallback(csound, p, (int (*)(CSOUND *, void *)) p5g_deinit); p->thread = csound->CreateThread(runp5thread, glove); return OK; } int p5glove_poll(CSOUND *csound, P5GLOVE *p) { /* P5Glove *glove = (P5Glove*)csound->QueryGlobalVariable(csound,"p5glove"); */ /* int res; */ /* if (glove == NULL) */ /* return csound->PerfError(csound, p->h.insdshead, */ /* Str("No glove open")); */ /* res = p5glove_sample(*glove, -1); */ /* if (res < 0 && errno == EAGAIN) return OK; */ /* //res = p5glove_sample(*glove, -1); */ /* if (UNLIKELY(res < 0)) */ /* return csound->PerfError(csound, p->h.insdshead, */ /* Str("P5Glove failure")); */ return OK; } int p5glove_closer(CSOUND *csound, P5GLOVE *p) { P5Glove *glove = (P5Glove*)csound->QueryGlobalVariable(csound, "p5glove"); if (glove==NULL) return NOTOK; printf("Closer called\n"); p5glove_close(*glove); *glove = NULL; csound->DestroyGlobalVariable(csound, "p5glove"); return OK; } int p5g_data_init(CSOUND *csound, P5GLOVE *p) { /* P5Glove p5g; */ /* p5g = (P5Glove)csound->QueryGlobalVariable(csound, "p5glove"); */ /* if (UNLIKELY(p5g==NULL)) */ /* return csound->InitError(csound, Str("No p5glove open")); */ p->last = 0; return OK; } int p5g_data(CSOUND *csound, P5GLOVE *p) { P5Glove *glove = (P5Glove*)csound->QueryGlobalVariable(csound, "p5glove"); int kontrol = (int)(*p->kControl+FL(0.5)); uint32_t buttons, just, rels; if (glove==NULL) csound->PerfError(csound, p->h.insdshead, Str("No open glove")); p5glove_get_buttons(*glove,&buttons); just = ((!p->last) & buttons); rels = (p->last & !buttons); p->last = buttons; if (kontrol<0) { printf("debug: \n"); *p->res = FL(0.0); return OK; } else if (kontrolres = (MYFLT)(buttons); case P5G_BUTTON_A: *p->res = (MYFLT)(buttons & P5GLOVE_BUTTON_A); return OK; case P5G_BUTTON_B: *p->res = (MYFLT)(buttons & P5GLOVE_BUTTON_B); return OK; case P5G_BUTTON_C: *p->res = (MYFLT)(buttons & P5GLOVE_BUTTON_C); return OK; case P5G_JUSTPUSH: *p->res = (MYFLT)just; return OK; case P5G_JUSTPU_A: *p->res = (MYFLT)(just & P5GLOVE_BUTTON_A); return OK; case P5G_JUSTPU_B: *p->res = (MYFLT)(just & P5GLOVE_BUTTON_B); return OK; case P5G_JUSTPU_C: *p->res = (MYFLT)(just & P5GLOVE_BUTTON_C); return OK; case P5G_RELEASED: *p->res = (MYFLT)rels; return OK; case P5G_RELSED_A: *p->res = (MYFLT)(rels & P5GLOVE_BUTTON_A); return OK; case P5G_RELSED_B: *p->res = (MYFLT)(rels & P5GLOVE_BUTTON_B); return OK; case P5G_RELSED_C: *p->res = (MYFLT)(rels & P5GLOVE_BUTTON_C); return OK; default: *p->res = 0.0; return NOTOK; } } else if (kontrol<=P5G_FINGER_THUMB) { double clench; p5glove_get_finger(*glove,kontrol-P5G_FINGER_INDEX,&clench); *p->res = (MYFLT)clench; /* *p->res = (MYFLT)(p5->data.finger[finger]/63.0); */ return OK; } else { double pos[3], axis[3], angle; p5glove_get_position(*glove, pos); p5glove_get_rotation(*glove, &angle, axis); /* printf("pos: %f %f %f\n", pos[0], pos[1], pos[2]); */ /* printf("axis: %f %f %f\n", axis[0], axis[1], axis[2]); */ /* printf("angle: %f\n", angle); */ switch (kontrol) { case P5G_DELTA_X: *p->res = (MYFLT)pos[0]; return OK; case P5G_DELTA_Y: *p->res = (MYFLT)pos[1]; return OK; case P5G_DELTA_Z: *p->res = (MYFLT)pos[2]; return OK; case P5G_DELTA_XR: *p->res = (MYFLT)axis[0]; return OK; case P5G_DELTA_YR: *p->res = (MYFLT)axis[1]; return OK; case P5G_DELTA_ZR: *p->res = (MYFLT)axis[2]; return OK; case P5G_ANGLES: *p->res = (MYFLT)angle; return OK; default: break; } } return NOTOK; } #define S(x) sizeof(x) static OENTRY p5g_localops[] = { {"p5gconnect", S(P5GLOVEINIT), 0, 3, "", "", (SUBR)p5glove_find, (SUBR)p5glove_poll, NULL, (SUBR)p5glove_closer }, {"p5gdata", S(P5GLOVE), 0, 3, "k", "k", (SUBR)p5g_data_init, (SUBR)p5g_data } }; LINKAGE_BUILTIN(p5g_localops) csound-6.10.0/Opcodes/padsynth_gen.cpp000066400000000000000000000417151321653344700176740ustar00rootroot00000000000000/* padsynt_gen.cpp: Copyright (C) 2015 Michael Gogins after Nasca O Paul This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ extern "C" { #include "csdl.h" } #include #include #include /** Paul Octavian Nasca's "padsynth algorithm" adds bandwidth to each partial of a periodic weaveform. This bandwidth is heard as color, movement, and additional richness of sound. First, the waveform is defined by the user as a series of harmonic partials. Then, bandwidth is added by independently spreading each partial of the original waveform from a single frequency across neighboring frequencies, according to a "profile" function: a Gaussian curve, a square, or a rising and then falling expontential. The partials of the original waveform may be considered to be samples in a discrete Fourier transform of the waveform. Normally there is not an exact one-to-one correspondence between the frequencies of the samples (frequency bins) of the discrete Fourier transform with the frequencies of the partials of the original waveform, because any frequency in the inverse of the discrete Fourier transform might be synthesized by interference between any number of bins. However, the padsynth algorithm uses a simple trick to create this correspondence. The discrete Fourier transform is simply made so large that the frequency of any partial of the original waveform will be very close to the frequency of the corresponding bin in the Fourier transform. Once this correspondence has been created, the bandwidth profile can be applied by centering it over the frequency bin of the original partial, scaling the profile by the bandwidth, and simply multiplying the original partial by each sample of the profile and adding the product to the corresponding bin of the Fourier transform. As the frequencies of the partials increase, their bandwidth may optionally become wider or (less often) narrower. Once each partial has been spread out in this way, the discrete Fourier transform may be given random phases, and is then simply inverted to synthesize the desired waveform, which may be used as the wavetable for a digital oscillator. N.B.: The size of the function table does NOT necessarily reflect one periodic cycle of the waveform that it contains. The fundamental frequency must be used to generate the desired pitch from an oscillator using the function table, e.g. oscillator_hz = desired_hz * (sr / padsynth_size / fundamental_hz) The parameters of the function table statement are: p1 "padsynth" p2 Score time (usually 0). p3 Function table size (must be a power of 2, should be large, e.g. 2^18 == 262144). p4 Function table number (auto-generated if 0). p5 Fundamental frequency of the generated waveform (cycles per second). p6 Bandwidth of the partials (cents). p7 Scaling factor for partial bandwidth (log of increase/decrease with partial frequency, 0 is no stretch or shrink). p8 Harmonic stretch/shrink of the partial (1 is harmonic). p9 Number specifying the shape of the bandwidth profile: 1 Gaussian 2 Square 3 Exponential p10 Profile function parameter. p11-pN The amplitudes of the partials (may be 0). */ static void log(CSOUND *csound, const char *format,...) { va_list args; va_start(args, format); if(csound) { if (csound->GetMessageLevel(csound) & WARNMSG) csound->MessageV(csound, 0, format, args); } else { vfprintf(stdout, format, args); } va_end(args); } static void warn(CSOUND *csound, const char *format,...) { if(csound) { if(csound->GetMessageLevel(csound) & WARNMSG) { va_list args; va_start(args, format); csound->MessageV(csound, CSOUNDMSG_WARNING, format, args); va_end(args); } } else { va_list args; va_start(args, format); vfprintf(stderr, format, args); va_end(args); } } static MYFLT profile_original(MYFLT fi, MYFLT bwi) { MYFLT x=fi/bwi; x*=x; if (x>14.71280603) { return 0.0; //this avoids computing the e^(-x^2) where it's results are very close to zero } return exp(-x)/bwi; }; // profile(p9_profile_shape, profile_sample_index_normalized, bandwidth_samples, p10_profile_parameter); static MYFLT profile(int shape, MYFLT fi, MYFLT bwi, MYFLT a) { MYFLT x = fi / bwi; MYFLT y = 0; switch(shape) { case 1: y = std::exp(-(x * x * a)); break; case 2: // The idea is to take profile 1 and simply say y goes to 0 if below a and to 1 if above a. y = std::exp(-(x * x * a)); if(a < 0.00001) { a = 0.00001; } else if (a > 0.99999) { a = 0.99999; } if (y < a) { y = 0; } else { y = 1; } break; case 3: y = std::exp(-(std::fabs(x) * std::sqrt(a))); break; } return y / bwi; } #if 0 // Keep this stuff around, it might come in handy later. #define FUNC(b) MYFLT base_function_ ## b(MYFLT x, MYFLT a) static MYFLT base_function_pulse(MYFLT x, MYFLT a) { return (std::fmod(x, 1.0) < a) ? -1.0 : 1.0; } FUNC(saw) { if(a < 0.00001f) { a = 0.00001f; } else if(a > 0.99999f) { a = 0.99999f; } x = fmod(x, 1); if(x < a) { return x / a * 2.0f - 1.0f; } else { return (1.0f - x) / (1.0f - a) * 2.0f - 1.0f; } } FUNC(triangle) { x = fmod(x + 0.25f, 1); a = 1 - a; if(a < 0.00001f) { a = 0.00001f; } if(x < 0.5f) { x = x * 4 - 1.0f; } else { x = (1.0f - x) * 4 - 1.0f; } x /= -a; if(x < -1.0f) { x = -1.0f; } if(x > 1.0f) { x = 1.0f; } return x; } FUNC(power) { x = fmod(x, 1); if(a < 0.00001f) { a = 0.00001f; } else if(a > 0.99999f) { a = 0.99999f; } return powf(x, expf((a - 0.5f) * 10.0f)) * 2.0f - 1.0f; } FUNC(gauss) { x = fmod(x, 1) * 2.0f - 1.0f; if(a < 0.00001f) { a = 0.00001f; } return expf(-x * x * (expf(a * 8) + 5.0f)) * 2.0f - 1.0f; } FUNC(diode) { if(a < 0.00001f) { a = 0.00001f; } else if(a > 0.99999f) { a = 0.99999f; } a = a * 2.0f - 1.0f; x = cosf((x + 0.5f) * 2.0f * PI) - a; if(x < 0.0f) { x = 0.0f; } return x / (1.0f - a) * 2 - 1.0f; } FUNC(abssine) { x = fmod(x, 1); if(a < 0.00001f) { a = 0.00001f; } else if(a > 0.99999f) { a = 0.99999f; } return sinf(powf(x, expf((a - 0.5f) * 5.0f)) * PI) * 2.0f - 1.0f; } FUNC(pulsesine) { if(a < 0.00001f) { a = 0.00001f; } x = (fmod(x, 1) - 0.5f) * expf((a - 0.5f) * logf(128)); if(x < -0.5f) { x = -0.5f; } else if(x > 0.5f) { x = 0.5f; } x = sinf(x * PI * 2.0f); return x; } FUNC(stretchsine) { x = fmod(x + 0.5f, 1) * 2.0f - 1.0f; a = (a - 0.5f) * 4; if(a > 0.0f) { a *= 2; } a = powf(3.0f, a); float b = powf(fabs(x), a); if(x < 0) { b = -b; } return -sinf(b * PI); } FUNC(chirp) { x = fmod(x, 1.0f) * 2.0f * PI; a = (a - 0.5f) * 4; if(a < 0.0f) { a *= 2.0f; } a = powf(3.0f, a); return sinf(x / 2.0f) * sinf(a * x * x); } FUNC(absstretchsine) { x = fmod(x + 0.5f, 1) * 2.0f - 1.0f; a = (a - 0.5f) * 9; a = powf(3.0f, a); float b = powf(fabs(x), a); if(x < 0) { b = -b; } return -powf(sinf(b * PI), 2); } FUNC(chebyshev) { a = a * a * a * 30.0f + 1.0f; return cosf(acosf(x * 2.0f - 1.0f) * a); } FUNC(sqr) { a = a * a * a * a * 160.0f + 0.001f; return -atanf(sinf(x * 2.0f * PI) * a); } FUNC(spike) { float b = a * 0.66666; // the width of the range: if a == 0.5, b == 0.33333 if(x < 0.5) { if(x < (0.5 - (b / 2.0))) { return 0.0; } else { x = (x + (b / 2) - 0.5) * (2.0 / b); // shift to zero, and expand to range from 0 to 1 return x * (2.0 / b); // this is the slope: 1 / (b / 2) } } else { if(x > (0.5 + (b / 2.0))) { return 0.0; } else { x = (x - 0.5) * (2.0 / b); return (1 - x) * (2.0 / b); } } } FUNC(circle) { // a is parameter: 0 -> 0.5 -> 1 // O.5 = circle float b, y; b = 2 - (a * 2); // b goes from 2 to 0 x = x * 4; if(x < 2) { x = x - 1; // x goes from -1 to 1 if((x < -b) || (x > b)) { y = 0; } else { y = sqrt(1 - (x*x) / (b*b)); // normally * a^2, but a stays 1 } } else { x = x - 3; // x goes from -1 to 1 as well if((x < -b) || (x > b)) { y = 0; } else { y = -sqrt(1 - (x*x) / (b*b)); } } return y; } typedef MYFLT (*base_function_t)(MYFLT, MYFLT); static base_function_t get_base_function(int index) { if(!index) { return NULL; } if(index == 127) { //should be the custom wave return NULL; } index--; base_function_t functions[] = { base_function_triangle,comment base_function_pulse, base_function_saw, base_function_power, base_function_gauss, base_function_diode, base_function_abssine, base_function_pulsesine, base_function_stretchsine, base_function_chirp, base_function_absstretchsine, base_function_chebyshev, base_function_sqr, base_function_spike, base_function_circle, }; return functions[index]; } #endif extern "C" { /* Original code: MYFLT PADsynth::profile(MYFLT fi, MYFLT bwi) { MYFLT x=fi/bwi; x*=x; if (x>14.71280603) { return 0.0; //this avoids computing the e^(-x^2) where it's results are very close to zero } return exp(-x)/bwi; }; for (nh=1; nhcsound; MYFLT p1_function_table_number = ff->fno; MYFLT p2_score_time = ff->e.p[2]; int N = ff->flen; MYFLT p5_fundamental_frequency = ff->e.p[5]; MYFLT p6_partial_bandwidth = ff->e.p[6]; MYFLT p7_partial_bandwidth_scale_factor = ff->e.p[7]; MYFLT p8_harmonic_stretch = ff->e.p[8]; int p9_profile_shape = (int) ff->e.p[9]; //base_function_t base_function = get_base_function(p9_profile_shape); MYFLT p10_profile_parameter = ff->e.p[10]; MYFLT samplerate = csound->GetSr(csound); log(csound, "samplerate: %12d\n", (int) samplerate); log(csound, "p1_function_table_number: %9.4f\n", p1_function_table_number); log(csound, "p2_score_time: %9.4f\n", p2_score_time); log(csound, "p3_ftable_size %12d\n", N); log(csound, "p4_gen_id: %12d\n", (int)(ff->e.p[4])); log(csound, "p5_fundamental_frequency: %9.4f\n", p5_fundamental_frequency); log(csound, "p6_partial_bandwidth: %9.4f\n", p6_partial_bandwidth); log(csound, "p7_partial_bandwidth_scale_factor: %9.4f\n", p7_partial_bandwidth_scale_factor); log(csound, "p8_harmonic_stretch: %9.4f\n", p8_harmonic_stretch); log(csound, "p9_profile_shape: %12d\n", p9_profile_shape); //log(csound, "profile_function: 0x%16p\n", base_function); log(csound, "p10_profile_parameter: %9.4f\n", p10_profile_parameter); // The amplitudes of each partial are in pfield 11 and higher. // N.B.: The partials are indexed starting from 1. int partialN = ff->e.pcnt - 10; std::vector A(partialN + 1); A[0] = FL(0.0); for (int partialI = 1; partialI <= partialN; ++partialI) { A[partialI] = ff->e.p[11 + partialI - 1]; } for (int i = 0; i < N; ++i) { ftp->ftable[i] = FL(0.0); } // N.B.: An in-place IFFT of N/2 complex to N real samples is used. // ftable[1] contains the real part of the Nyquist frequency; we make it 0. std::complex *spectrum = (std::complex *)ftp->ftable; int complexN = int(N / 2.0); for (int partialI = 1; partialI <= partialN; ++partialI) { MYFLT partial_Hz = p5_fundamental_frequency * p8_harmonic_stretch * ((MYFLT) partialI); MYFLT frequency_sample_index_normalized = partial_Hz / ((MYFLT) samplerate); int partial_frequency_index = frequency_sample_index_normalized * ((MYFLT) N); MYFLT bandwidth_Hz = (std::pow(2.0, p6_partial_bandwidth / 1200.0) - 1.0) * p5_fundamental_frequency * std::pow(p8_harmonic_stretch * ((MYFLT) partialI), p7_partial_bandwidth_scale_factor); MYFLT bandwidth_samples = bandwidth_Hz / (2.0 * samplerate); log(csound, "partial[%3d]: %9.4f\n", partialI, A[partialI]); warn(csound, " partial_Hz: %9.4f\n", partial_Hz); warn(csound, " frequency_sample_index_normalized: %9.4f\n", frequency_sample_index_normalized); warn(csound, " partial_frequency_index: %12d\n", partial_frequency_index); warn(csound, " bandwidth_Hz: %9.4f\n", bandwidth_Hz); warn(csound, " bandwidth_samples: %12.8f\n", bandwidth_samples); for (int fft_sample_index = 0; fft_sample_index < complexN; ++fft_sample_index) { MYFLT fft_sample_index_normalized = ((MYFLT) fft_sample_index) / ((MYFLT) N); MYFLT profile_sample_index_normalized = fft_sample_index_normalized - frequency_sample_index_normalized; MYFLT profile_sample = profile(p9_profile_shape, profile_sample_index_normalized, bandwidth_samples, p10_profile_parameter); //MYFLT profile_sample = profile_original(profile_sample_index_normalized, bandwidth_samples); MYFLT real = profile_sample * A[partialI]; spectrum[fft_sample_index] += real; }; }; std::default_random_engine generator; std::uniform_real_distribution distribution(0.0, 6.28318530718); for (int complexI = 0; complexI < complexN; ++complexI) { MYFLT random_phase = distribution(generator); MYFLT real = spectrum[complexI].real(); spectrum[complexI].real(real * std::cos(random_phase)); spectrum[complexI].imag(real * std::sin(random_phase)); }; spectrum[0].imag(0); csound->InverseRealFFT(csound, ftp->ftable, N); // Normalize, MYFLT maximum = FL(0.0); for (int i = 0; i < N; ++i) { if (std::fabs(ftp->ftable[i]) > maximum) { maximum = std::fabs(ftp->ftable[i]); //warn(csound, "maximum at %d: %f\n", i, maximum); } } for (int i = 0; i < N; ++i) { ftp->ftable[i] /= maximum * ROOT2; } return OK; } static NGFENS padsynth_gens[] = { { (char *)"padsynth", padsynth_gen }, { NULL, NULL } }; PUBLIC NGFENS *csound_fgen_init(CSOUND *csound) \ { return padsynth_gens; } }; csound-6.10.0/Opcodes/padsynth_gen.csd000066400000000000000000000073201321653344700176550ustar00rootroot00000000000000 sr=96000 ksmps=1 nchnls=2 0dbfs=2000 gispec_len init 2^18 instr 1 prints "Plain sine for frequency/amplitude/distortion comparison.\n" gi_padsynth_1 ftgenonce 0, 0, gispec_len, 10, 1 iattack = 0.08 idecay = 0.1 isustain = 0.25 irelease = 0.2 aenv madsr iattack, idecay, isustain, irelease ifreq cpsmidinn p4 iamp ampdb p5 asig poscil iamp, ifreq, gi_padsynth_1 asig = aenv * asig aleft, aright pan2 asig, 0.5 outs aleft, aright endin instr 2 prints "PadSynth with sine tone.\n" ibasehz = 261.625565 ; p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 gi_padsynth_1 ftgenonce 0, 0, gispec_len, "padsynth", ibasehz, p6, 0.0, 1, 1, 1.0, 1 iattack = 0.08 idecay = 0.1 isustain = 0.25 irelease = 0.2 aenv madsr iattack, idecay, isustain, irelease ifreq cpsmidinn p4 iamp ampdb p5 asig poscil iamp, ifreq*(sr/gispec_len/ibasehz), gi_padsynth_1 asig = aenv * asig aleft, aright pan2 asig, 0.5 outs aleft, aright endin instr 3 prints "PadSynth with harmonics.\n" ibasehz = 261.625565 ; p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 gi_padsynth_1 ftgenonce 0, 0, gispec_len, "padsynth", ibasehz, p6, 1, 1, 1, 1, 0.7600046992, 0.6199994683, 0.9399998784, 0.4400023818, 0.0600003302, 0.8499968648, 0.0899999291, 0.8199964762, 0.3199984133, 0.9400014281, 0.3000001907, 0.120003365, 0.1799997687, 0.5200006366, 0.9300042987 iattack = 0.08 idecay = 0.1 isustain = 0.25 irelease = 0.2 aenv madsr iattack, idecay, isustain, irelease ifreq cpsmidinn p4 iamp ampdb p5 asig poscil iamp, ifreq*(sr/gispec_len/ibasehz), gi_padsynth_1 asig = aenv * asig aleft, aright pan2 asig, 0.5 outs aleft, aright endin instr 4 prints "PadSynth with inharmonic partials.\n" ibasehz = 261.625565 ; p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 gi_padsynth_1 ftgenonce 0, 0, gispec_len, "padsynth", ibasehz, p6, 1, 2, 3, 1, 0.7600046992, 0.6199994683, 0.9399998784, 0.4400023818, 0.0600003302, 0.8499968648, 0.0899999291, 0.8199964762, 0.3199984133, 0.9400014281, 0.3000001907, 0.120003365, 0.1799997687, 0.5200006366, 0.9300042987 iattack = 0.08 idecay = 0.1 isustain = 0.25 irelease = 0.2 aenv madsr iattack, idecay, isustain, irelease ifreq cpsmidinn p4 iamp ampdb p5 asig poscil iamp, ifreq*(sr/gispec_len/ibasehz), gi_padsynth_1 asig = aenv * asig aleft, aright pan2 asig, 0.5 outs aleft, aright endin i1 2 8 60.00 60 i1 ^+10 8 72.00 60 i1 ^+10 8 84.00 60 s i2 2 8 60.00 60 0.3 i2 ^+10 8 72.00 60 0.3 i2 ^+10 8 84.00 60 0.3 i2 ^+10 8 60.00 60 25 i2 ^+10 8 72.00 60 25 i2 ^+10 8 84.00 60 25 i2 ^+10 8 60.00 60 55 i2 ^+10 8 72.00 60 55 i2 ^+10 8 84.00 60 55 s i3 2 8 60.00 60 0.3 i3 ^+10 8 72.00 60 0.3 i3 ^+10 8 84.00 60 0.3 i3 ^+10 8 60.00 60 25 i3 ^+10 8 72.00 60 25 i3 ^+10 8 84.00 60 25 i3 ^+10 8 60.00 60 55 i3 ^+10 8 72.00 60 55 i3 ^+10 8 84.00 60 55 s i4 2 8 60.00 60 0.3 i4 ^+10 8 72.00 60 0.3 i4 ^+10 8 84.00 60 0.3 i4 ^+10 8 60.00 60 25 i4 ^+10 8 72.00 60 25 i4 ^+10 8 84.00 60 25 i4 ^+10 8 60.00 60 55 i4 ^+10 8 72.00 60 55 i4 ^+10 8 84.00 60 55 e 100 100 320 240 true 255 255 255 csound-6.10.0/Opcodes/pan2.c000066400000000000000000000064721321653344700155120ustar00rootroot00000000000000/* pan2.c: Copyright (C) 2007 John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // #include "csdl.h" #include "csoundCore.h" #include "interlocks.h" #include typedef struct { OPDS h; MYFLT *aleft; /* Left output */ MYFLT *aright; /* Right output */ MYFLT *asig; MYFLT *pan; /* pan position */ MYFLT *itype; /* type of panning */ int type; } PAN2; #define SQRT2 FL(1.41421356237309504880) static int pan2set(CSOUND *csound, PAN2 *p) { int type = p->type = MYFLT2LRND(*p->itype); if (UNLIKELY(type <0 || type > 3)) return csound->InitError(csound, Str("Unknown panning type")); return OK; } static int pan2run(CSOUND *csound, PAN2 *p) { int type = p->type; MYFLT *ain = p->asig; MYFLT *al = p->aleft, *ar = p->aright; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int asgp = IS_ASIG_ARG(p->pan); if (UNLIKELY(offset)) { memset(ar, '\0', offset*sizeof(MYFLT)); memset(al, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); memset(&al[nsmps], '\0', early*sizeof(MYFLT)); } switch (type) { case 0: { MYFLT kangl = PI_F*FL(0.5) * *p->pan; for (n=offset; npan[n]; ar[n] = ain[n] * SIN(kangl); al[n] = ain[n] * COS(kangl); } break; } case 1: { MYFLT kangl = *p->pan; for (n=offset; npan[n]; ar[n] = ain[n] * SQRT(kangl); al[n] = ain[n] * SQRT(FL(1.0)-kangl); } break; } case 2: { MYFLT kangl = *p->pan; for (n=offset; npan[n]; ar[n] = ain[n] * kangl; al[n] = ain[n] * (FL(1.0)-kangl); } break; } case 3: { MYFLT kangl = *p->pan, cc, ss, l, r; for (n=offset; npan[n]; cc = COS(PI*kangl*FL(0.5)); ss = SIN(PI*kangl*FL(0.5)); l = SQRT2*(cc+ss)*0.5; r = SQRT2*(cc-ss)*0.5; al[n] = ain[n] * l; ar[n] = ain[n] * r; } } } return OK; } static OENTRY pan2_localops[] = { { "pan2", sizeof(PAN2), 0, 5, "aa", "axo", (SUBR) pan2set, 0, (SUBR) pan2run }, }; LINKAGE_BUILTIN(pan2_localops) csound-6.10.0/Opcodes/partials.c000066400000000000000000000405311321653344700164630ustar00rootroot00000000000000/* partials.c (c) Victor Lazzarini, 2005 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* PARTIALS Streaming partial track analysis ftrk partials ffr, fphs, kthresh, kminpts, kmaxgap, imaxtracks ftrk - TRACKS streaming spectral signal ffrs - AMP_FREQ input signal fphs - AMP_PHASE input signal (unwrapped phase expected) kthresh - analysis threshold (0 <= kthresh <= 1) kminpts - minimum number of time-points for a partial track kmaxgap - max gap between detected peaks in a track imaxtracks - max number of tracks (<= number of analysis bins) */ #include "pvs_ops.h" #include "pstream.h" typedef struct _parts { OPDS h; PVSDAT *fout; PVSDAT *fin1, *fin2; MYFLT *kthresh, *pts, *gap, *mtrks; int tracks, numbins, mtracks, prev, cur; unsigned long accum; uint32 lastframe, timecount; AUXCH mags, lmags, index, cflag, trkid, trndx; AUXCH tstart, binex, magex, oldbins, diffs, adthresh; AUXCH pmags, bins, lastpk; int nophase; } _PARTS; static int partials_init(CSOUND * csound, _PARTS * p) { int N = p->fin1->N, maxtracks; int numbins = N / 2 + 1, i; int *trkid; int *trndx; p->tracks = 0; p->mtracks = *p->mtrks; p->timecount = 0; p->accum = 0; p->numbins = numbins; maxtracks = (p->mtracks < numbins ? p->mtracks : numbins); p->prev = 0; p->cur = maxtracks; if (p->mags.auxp == NULL || p->mags.size < sizeof(double) * numbins) csound->AuxAlloc(csound, sizeof(double) * numbins, &p->mags); else memset(p->mags.auxp, 0,sizeof(double) * numbins ); if (p->lmags.auxp == NULL || p->lmags.size < sizeof(double) * numbins) csound->AuxAlloc(csound, sizeof(double) * numbins, &p->lmags); else memset(p->lmags.auxp, 0,sizeof(double) * numbins ); if (p->cflag.auxp == NULL || p->cflag.size < sizeof(int) * maxtracks) csound->AuxAlloc(csound, sizeof(int) * maxtracks, &p->cflag); else memset(p->cflag.auxp, 0, sizeof(int) * maxtracks); if (p->trkid.auxp == NULL || p->trkid.size < sizeof(int) * maxtracks * 2) csound->AuxAlloc(csound, sizeof(int) * maxtracks * 2, &p->trkid); else memset(p->trkid.auxp, 0, sizeof(int) * maxtracks * 2); if (p->trndx.auxp == NULL || p->trndx.size < sizeof(int) * maxtracks) csound->AuxAlloc(csound, sizeof(int) * maxtracks, &p->trndx); else memset(p->trndx.auxp, 0, sizeof(int) * maxtracks ); if (p->index.auxp == NULL || p->index.size < sizeof(int) * numbins) csound->AuxAlloc(csound, sizeof(int) * numbins, &p->index); else memset(p->index.auxp, 0,sizeof(int) * numbins ); if (p->tstart.auxp == NULL || p->tstart.size < sizeof(uint32) * maxtracks * 2) csound->AuxAlloc(csound, sizeof(uint32) * maxtracks * 2, &p->tstart); else memset(p->tstart.auxp, 0, sizeof(uint32) * maxtracks * 2); if (p->lastpk.auxp == NULL || p->lastpk.size < sizeof(uint32) * maxtracks * 2) csound->AuxAlloc(csound, sizeof(uint32) * maxtracks * 2, &p->lastpk); else memset(p->lastpk.auxp, 0, sizeof(uint32) * maxtracks * 2); if (p->binex.auxp == NULL || p->binex.size < sizeof(double) * numbins) csound->AuxAlloc(csound, sizeof(double) * numbins, &p->binex); else memset(p->binex.auxp, 0,sizeof(double) * numbins ); if (p->magex.auxp == NULL || p->magex.size < sizeof(double) * numbins) csound->AuxAlloc(csound, sizeof(double) * numbins, &p->magex); else memset(p->magex.auxp, 0,sizeof(double) * numbins ); if (p->bins.auxp == NULL || p->bins.size < sizeof(double) * maxtracks) csound->AuxAlloc(csound, sizeof(double) * maxtracks, &p->bins); else memset(p->bins.auxp, 0, sizeof(double) * maxtracks ); if (p->oldbins.auxp == NULL || p->oldbins.size < sizeof(double) * maxtracks * 2) csound->AuxAlloc(csound, sizeof(double) * maxtracks * 2, &p->oldbins); else memset(p->oldbins.auxp, 0, sizeof(double) * maxtracks * 2); if (p->diffs.auxp == NULL || p->diffs.size < sizeof(double) * numbins) csound->AuxAlloc(csound, sizeof(double) * numbins, &p->diffs); else memset(p->diffs.auxp, 0, sizeof(double) * numbins ); if (p->pmags.auxp == NULL || p->pmags.size < sizeof(double) * maxtracks * 2) csound->AuxAlloc(csound, sizeof(double) * maxtracks * 2, &p->pmags); else memset(p->pmags.auxp, 0, sizeof(double) * maxtracks * 2); if (p->adthresh.auxp == NULL || p->adthresh.size < sizeof(double) * maxtracks * 2) csound->AuxAlloc(csound, sizeof(double) * maxtracks * 2, &p->adthresh); else memset(p->adthresh.auxp, 0, sizeof(double) * maxtracks * 2); if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(float) * numbins * 4) csound->AuxAlloc(csound, sizeof(float) * numbins * 4, &p->fout->frame); else memset(p->fout->frame.auxp, 0,sizeof(float) * numbins * 4); p->fout->N = N; p->fout->overlap = p->fin1->overlap; p->fout->winsize = p->fin1->winsize; p->fout->wintype = p->fin1->wintype; p->fout->framecount = 1; p->fout->format = PVS_TRACKS; trkid = (int *) p->trkid.auxp; trndx = (int *) p->trndx.auxp; for (i = 0; i < maxtracks; i++) trkid[p->cur + i] = trkid[p->prev + i] = trndx[i] = -1; p->mtracks = maxtracks; if (UNLIKELY(p->fin1->format != PVS_AMP_FREQ)) { return csound->InitError(csound, Str("partials: first input not in AMP_FREQ format \n")); } if (UNLIKELY(p->fin2->format != PVS_AMP_PHASE)) { csound->Warning(csound, Str("partials: no phase input, tracks will contain " "amp & freq only\n")); p->nophase = 1; } else p->nophase = 0; p->lastframe = 0; return OK; } static void Analysis(CSOUND * csound, _PARTS * p) { float absthresh, logthresh; int ndx, count = 0, i = 0, n = 0, j = 0; float dbstep; double y1, y2, a, b, dtmp; float ftmp, ftmp2; int numbins = p->numbins, maxtracks = p->mtracks; int prev = p->prev, cur = p->cur, foundcont; int accum = p->accum, minpoints = (int) (*p->pts > 1 ? *p->pts : 1) - 1; int tracks = p->tracks; double *mags = (double *) p->mags.auxp; double *lmags = (double *) p->lmags.auxp; int *cflag = (int *) p->cflag.auxp; int *trkid = (int *) p->trkid.auxp; int *trndx = (int *) p->trndx.auxp; int *index = (int *) p->index.auxp; uint32 *tstart = (uint32 *) p->tstart.auxp; double *binex = (double *) p->binex.auxp; double *magex = (double *) p->magex.auxp; double *oldbins = (double *) p->oldbins.auxp; double *diffs = (double *) p->diffs.auxp; double *adthresh = (double *) p->adthresh.auxp; double *pmags = (double *) p->pmags.auxp; double *bins = (double *) p->bins.auxp; uint32 *lastpk = (uint32 *) p->lastpk.auxp; unsigned int timecount = p->timecount, maxgap = (unsigned int) (*p->gap > 0 ? *p->gap : 0); int test1 = 1, test2 = 0; if(*p->kthresh >= 0) { float max = 0.0f; for (i = 0; i < numbins; i++) if (max < mags[i]) { max = mags[i]; } absthresh = (float)(*p->kthresh * max); } else absthresh = (float)(-*p->kthresh * csound->Get0dBFS(csound)); logthresh = logf(absthresh / 5.0f); /* Quadratic Interpolation obtains bin indexes and magnitudes binex & magex respectively */ /* take the logarithm of the magnitudes */ for (i = 0; i < numbins; i++) lmags[i] = log((double)mags[i]); for (i = 0; i < numbins - 1; i++) { if (i) test1 = (lmags[i] > lmags[i - 1] ? 1 : 0); else test1 = 0; test2 = (lmags[i] >= lmags[i + 1] ? 1 : 0); if ((lmags[i] > logthresh) && (test1 && test2)) { index[n] = i; n++; } } for (i = 0; i < n; i++) { int rmax; rmax = index[i]; y1 = lmags[rmax] - (dtmp = (rmax ? lmags[rmax - 1] : lmags[rmax + 1])) + 0.000001; y2 = (rmax < numbins - 1 ? lmags[rmax + 1] : lmags[rmax]) - dtmp + 0.000001; a = (y2 - 2.0 * y1) / 2.0; b = 1.0 - y1 / a; binex[i] = (double) (rmax - 1.0 + b / 2.0); magex[i] = (double) exp(dtmp - a * b * b / 4.0); } /* Track allocation */ /* reset continuation flags */ for (i = 0; i < maxtracks; i++) { cflag[i] = 0; } /* loop to the end of tracks (indicate by the 0'd bins) find continuation tracks */ for (j = 0; oldbins[prev + j] != 0.f && j < maxtracks; j++) { foundcont = 0; if (n > 0) { /* check for peaks; n will be > 0 */ ftmp = oldbins[prev + j]; for (i = 0; i < numbins; i++) { diffs[i] = binex[i] - ftmp; /* differences */ diffs[i] = (diffs[i] < 0 ? -diffs[i] : diffs[i]); } ndx = 0; /* best index */ for (i = 0; i < numbins; i++) if (diffs[i] < diffs[ndx]) ndx = i; /* if difference smaller than 1 bin */ ftmp2 = ftmp - binex[ndx]; ftmp2 = (ftmp2 < 0.0f ? -ftmp2 : ftmp2); if (ftmp2 < 1.0f) { /* if amp jump is too great */ if (adthresh[prev + j] < (dbstep = 20.0f * LOG10(magex[ndx] / pmags[prev + j]))) { /* mark for discontinuation */ cflag[j] = 0; } else { oldbins[prev + j] = binex[ndx]; pmags[prev + j] = magex[ndx]; /* track index keeps track history so we know which ones continue */ cflag[j] = 1; binex[ndx] = magex[ndx] = FL(0.0); lastpk[prev + j] = timecount; foundcont = 1; count++; /* update adthresh */ ftmp = dbstep * 1.5f; ftmp2 = adthresh[prev + j] - (adthresh[prev + j] - 1.5f) * 0.048770575f; adthresh[prev + j] = (ftmp > ftmp2 ? ftmp : ftmp2); } /* else */ } } if (foundcont == 0) { if ((mags[(int) (oldbins[prev + j] + 0.5f)]) < (0.2 * pmags[prev + j]) || (timecount - lastpk[prev + j]) > maxgap) cflag[j] = 0; else { cflag[j] = 1; count++; } } } /* for loop */ if (count < maxtracks) { /* if we have not exceeded available tracks. compress the arrays */ for (i = 0, n = 0; i < maxtracks; i++) { if (cflag[i]) { oldbins[cur + n] = oldbins[prev + i]; pmags[cur + n] = pmags[prev + i]; adthresh[cur + n] = adthresh[prev + i]; tstart[cur + n] = tstart[prev + i]; trkid[cur + n] = trkid[prev + i]; lastpk[cur + n] = lastpk[prev + i]; n++; } /* ID == -1 means zeroed track */ else trndx[i] = -1; } /* now current arrays are the compressed previous arrays. Create new tracks */ for (j = 0; j < numbins && count < maxtracks; j++) { if (magex[j] > absthresh) { oldbins[cur + count] = binex[j]; pmags[cur + count] = magex[j]; adthresh[cur + count] = 400.f; /* track ID is a positive number in the range of 0 - maxtracks*4 - 1 it is given when the track starts used to identify and match tracks */ tstart[cur + count] = timecount; trkid[cur + count] = ((accum++));// % (maxtracks * 1000)); lastpk[cur + count] = timecount; count++; } } for (i = count; i < maxtracks; i++) { /* zero the right-hand size of the current arrays */ pmags[cur + i] = oldbins[cur + i] = adthresh[cur + i] = 0.0f; trkid[cur + i] = -1; } } /* if count != maxtracks */ /* count is the number of continuing tracks + new tracks now we check for tracks that have been there for more than minpoints hop periods and output them */ tracks = 0; for (i = 0; i < maxtracks; i++) { if (i < count && tstart[cur + i] <= timecount - minpoints) { bins[i] = oldbins[cur + i]; mags[i] = pmags[cur + i]; trndx[i] = trkid[cur + i]; tracks++; } } /* current arrays become previous */ timecount++; p->timecount = timecount; p->cur = prev; p->prev = cur; p->accum = accum; p->tracks = tracks; } static int partials_process(CSOUND * csound, _PARTS * p) { int pos, ndx, end, fftsize = p->fin1->N; int numbins = fftsize / 2 + 1, i, k; int tracks, nophase = p->nophase; float *fin1 = p->fin1->frame.auxp; float *fin2 = p->fin2->frame.auxp; float *fout = p->fout->frame.auxp; double *mags = p->mags.auxp; double *bins = p->bins.auxp; int *trndx = p->trndx.auxp; double frac, a, b; int maxtracks = (p->mtracks < numbins ? p->mtracks : numbins); end = numbins * 4; if (p->lastframe < p->fin1->framecount) { for (i = k = 0; i < fftsize + 2; i += 2, k++) mags[k] = fin1[i]; Analysis(csound, p); /* fout holds [amp, freq, pha, ID] */ tracks = p->tracks; for (i = k = 0; i < end && k < maxtracks; i += 4, k++) { if (k < tracks) { /* magnitudes */ ndx = (int) bins[k]; fout[i] = (float) mags[k]; /* fractional part of bin indexes */ frac = (bins[k] - ndx); /* freq interpolation */ pos = ndx * 2 + 1; a = fin1[pos]; b = (bins[k] < numbins - 1 ? (fin1[pos + 2] - a) : 0); fout[i + 1] = (float) (a + frac * b); if (!nophase){ float pha = fin2[pos]; /* while (pha >= PI_F) pha -= TWOPI_F; while (pha < -PI_F) pha += TWOPI_F; */ fout[i + 2] = pha; /* phase (truncated) */ } else fout[i + 2] = 0.f; fout[i + 3] = (float) trndx[k]; /* trk IDs */ } else { /* empty tracks */ fout[i + 3] = trndx[k]; } } p->lastframe = p->fout->framecount = p->fin1->framecount; } return OK; } typedef struct _partxt{ OPDS h; STRINGDAT *fname; PVSDAT *tracks; FDCH fdch; FILE *f; uint32 lastframe; } PARTXT; int part2txt_init(CSOUND *csound, PARTXT *p){ if (p->fdch.fd != NULL) fdclose(csound, &(p->fdch)); p->fdch.fd = csound->FileOpen2(csound, &(p->f), CSFILE_STD, p->fname->data, "w", "", CSFTYPE_FLOATS_TEXT, 0); if (UNLIKELY(p->fdch.fd == NULL)) return csound->InitError(csound, Str("Cannot open %s"), p->fname->data); p->lastframe = 0; return OK; } int part2txt_perf(CSOUND *csound, PARTXT *p){ float *tracks = (float *) p->tracks->frame.auxp; int i = 0; if (p->tracks->framecount > p->lastframe){ for (i=0; tracks[i+3] != -1; i+=4){ fprintf(p->f, "%f %f %f %d\n",tracks[i],tracks[i+1], tracks[i+2], (int) tracks[i+3]); } fprintf(p->f, "-1.0 -1.0 -1.0 -1\n"); p->lastframe = p->tracks->framecount; } return OK; } static OENTRY localops[] = { { "partials", sizeof(_PARTS), 0, 3, "f", "ffkkki", (SUBR) partials_init, (SUBR) partials_process }, { "part2txt", sizeof(_PARTS), 0, 3, "", "Sf", (SUBR) part2txt_init, (SUBR) part2txt_perf } }; int partials_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/partikkel.c000066400000000000000000001100121321653344700166220ustar00rootroot00000000000000/* xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Partikkel - a granular synthesis module for Csound 5 Copyright (C) 2006-2016 Oeyvind Brandtsegg, Torgeir Strand Henriksen, Thom Johansen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "partikkel.h" #include #include #define INITERROR(x) csound->InitError(csound, Str("partikkel: " x)) #define PERFERROR(x) csound->PerfError(csound, p->h.insdshead,Str("partikkel: " x)) #define WARNING(x) csound->Warning(csound, Str("partikkel: " x)) /* Assume csound and p pointers are always available */ #define frand() (csound->RandMT(&p->randstate)/(double)(0xffffffff)) /* linear interpolation between x and y by z * NOTE: arguments evaluated more than once, do not pass anything with side * effects */ #define lrp(x, y, z) ((x) + ((y) - (x))*(z)) /* macro used to wrap an index back to start position if it's out of bounds. */ #define clip_index(index, from, to) \ if (index > (unsigned)(to) || index < (unsigned)(from)) \ index = (unsigned)(from); /* here follows routines for maintaining a linked list of grains */ /* initialises a linked list of NODEs */ static void init_pool(GRAINPOOL *s, unsigned max_grains) { unsigned i; NODE **p = &s->grainlist; NODE *grainpool = (NODE *)s->mempool; s->free_nodes = max_grains; /* build list of grains in pool */ for (i = 0; i < max_grains; ++i) { NODE *node; *p = grainpool + i; node = *p; node->next = NULL; p = &(node->next); } } /* returns pointer to new node */ static NODE *get_grain(GRAINPOOL *s) { NODE *ret = s->grainlist; if (s->grainlist) s->grainlist = s->grainlist->next; s->free_nodes--; return ret; } /* returns a NODE to the pool. function returns pointer to next node */ static NODE *return_grain(GRAINPOOL *s, NODE *c) { NODE *oldnext = c->next; c->next = s->grainlist; s->grainlist = c; s->free_nodes++; return oldnext; } /* return oldest grain to the pool, we use this when we're out of grains */ static void kill_oldest_grain(GRAINPOOL *s, NODE *n) { while (n->next->next) n = n->next; return_grain(s, n->next); n->next = NULL; } static int setup_globals(CSOUND *csound, PARTIKKEL *p) { PARTIKKEL_GLOBALS *pg; PARTIKKEL_GLOBALS_ENTRY **pe; pg = csound->QueryGlobalVariable(csound, "partikkel"); if (pg == NULL) { int i; if (UNLIKELY(csound->CreateGlobalVariable(csound, "partikkel", sizeof(PARTIKKEL_GLOBALS)) != 0)) return INITERROR("could not allocate globals"); pg = csound->QueryGlobalVariable(csound, "partikkel"); pg->rootentry = NULL; /* build default tables. allocate enough for three, plus extra for the * ftable data itself */ /* we only fill in the entries in the FUNC struct that we use */ /* table with data [1.0, 1.0, 1.0], used as default by envelopes */ pg->ooo_tab = (FUNC *)csound->Calloc(csound, sizeof(FUNC)); pg->ooo_tab->ftable = (MYFLT*)csound->Calloc(csound, 3*sizeof(MYFLT)); pg->ooo_tab->flen = 2; pg->ooo_tab->lobits = 31; for (i = 0; i <= 2; ++i) pg->ooo_tab->ftable[i] = FL(1.0); /* table with data [0.0, 0.0, 0.0], used as default by grain * distribution table, channel masks and grain waveforms */ pg->zzz_tab = (FUNC *)csound->Calloc(csound, sizeof(FUNC)); pg->zzz_tab->ftable = (MYFLT*)csound->Calloc(csound, 3*sizeof(MYFLT)); pg->zzz_tab->flen = 2; pg->zzz_tab->lobits = 31; /* table with data [0.0, 0.0, 1.0], used as default by gain masks, * fm index table, and wave start and end freq tables */ pg->zzo_tab = (FUNC *)csound->Calloc(csound, sizeof(FUNC)); pg->zzo_tab->ftable = (MYFLT*)csound->Calloc(csound, 4*sizeof(MYFLT)); pg->zzo_tab->ftable[2] = FL(1.0); pg->zzo_tab->flen = 3; /* JPff */ /* table with data [0.0, 0.0, 0.5, 0.5, 0.5, 0.5, 0.0], used as default * by wave gain table */ pg->zzhhhhz_tab = (FUNC *)csound->Calloc(csound, sizeof(FUNC)); pg->zzhhhhz_tab->ftable = (MYFLT*)csound->Calloc(csound, 8*sizeof(MYFLT)); for (i = 2; i <= 5; ++i) pg->zzhhhhz_tab->ftable[i] = FL(0.5); } p->globals = pg; if ((int)*p->opcodeid == 0) { /* opcodeid 0 means we do not bother with the sync opcode */ p->globals_entry = NULL; return OK; } /* try to find entry corresponding to our opcodeid */ pe = &pg->rootentry; while (*pe != NULL && (*pe)->id != *p->opcodeid) pe = &((*pe)->next); /* check if one already existed, if not, create one */ if (*pe == NULL) { *pe = csound->Malloc(csound, sizeof(PARTIKKEL_GLOBALS_ENTRY)); (*pe)->id = *p->opcodeid; (*pe)->partikkel = p; /* allocate table for sync data */ (*pe)->synctab = csound->Calloc(csound, 2*CS_KSMPS*sizeof(MYFLT)); (*pe)->next = NULL; } p->globals_entry = *pe; return OK; } /* look up a sample from a csound table using linear interpolation * tab: csound table pointer * index: fixed point index in the range 0..PHMASK inclusive * zscale: 1/(1 << tab->lobits) * shift: length of phase register in bits minus length of table in bits */ static inline MYFLT lrplookup(FUNC *tab, unsigned phase, MYFLT zscale, unsigned shift) { const unsigned index = phase >> shift; const unsigned mask = (1 << shift) - 1; MYFLT a = tab->ftable[index]; MYFLT b = tab->ftable[index + 1]; MYFLT z = (MYFLT)(phase & mask)*zscale; return lrp(a, b, z); } /* Why not use csound->intpow ? */ static inline double intpow_(MYFLT x, unsigned n) { double ans = 1.0; while (n != 0) { if (n & 1) ans *= x; n >>= 1; x *= x; } return ans; } /* dsf synthesis for trainlets */ static inline MYFLT dsf(FUNC *tab, GRAIN *grain, double beta, MYFLT zscale, unsigned cosineshift) { MYFLT numerator, denominator, cos_beta; MYFLT lastharmonic, result; unsigned fbeta, N = grain->harmonics; const MYFLT a = grain->falloff; const MYFLT a_pow_N = grain->falloff_pow_N; fbeta = (unsigned)(beta*(double)UINT_MAX); cos_beta = lrplookup(tab, fbeta, zscale, cosineshift); denominator = FL(1.0) - FL(2.0)*a*cos_beta + a*a; if (denominator < FL(1e-6) && denominator > FL(-1e-6)) { /* handle this special case to avoid divison by zero */ result = N - FL(1.0); } else { /* this factor can also serve as a last, fadable harmonic, if we in the * future want to fade the number of harmonics smoothly */ lastharmonic = a_pow_N*lrplookup(tab, fbeta*N, zscale, cosineshift); numerator = FL(1.0) - a*cos_beta - lastharmonic + a*a_pow_N*lrplookup(tab, (N - 1)*fbeta, zscale, cosineshift); result = numerator/denominator - FL(1.0); } return result; } static int partikkel_init(CSOUND *csound, PARTIKKEL *p) { uint32_t size; int ret; if ((ret = setup_globals(csound, p)) != OK) return ret; p->grainroot = NULL; /* set grainphase to 1.0 to make grain scheduler create a grain immediately * after starting opcode */ p->grainphase = 1.0; p->num_outputs = csound->GetOutputArgCnt(p); /* save for faster access */ /* resolve tables with no default table handling */ p->costab = csound->FTFind(csound, p->cosine); /* resolve some tables with default table handling */ p->disttab = *p->dist >= FL(0.0) ? csound->FTFind(csound, p->dist) : p->globals->zzz_tab; p->gainmasktab = *p->gainmasks >= FL(0.0) ? csound->FTFind(csound, p->gainmasks) : p->globals->zzo_tab; p->channelmasktab = *p->channelmasks >= FL(0.0) ? csound->FTFind(csound, p->channelmasks) : p->globals->zzz_tab; p->env_attack_tab = *p->env_attack >= FL(0.0) ? csound->FTFind(csound, p->env_attack) : p->globals->ooo_tab; p->env_decay_tab = *p->env_decay >= FL(0.0) ? csound->FTFind(csound, p->env_decay) : p->globals->ooo_tab; p->env2_tab = *p->env2 >= FL(0.0) ? csound->FTFind(csound, p->env2) : p->globals->ooo_tab; p->wavfreqstarttab = *p->wavfreq_startmuls >= FL(0.0) ? csound->FTFind(csound, p->wavfreq_startmuls) : p->globals->zzo_tab; p->wavfreqendtab = *p->wavfreq_endmuls >= FL(0.0) ? csound->FTFind(csound, p->wavfreq_endmuls) : p->globals->zzo_tab; p->fmamptab = *p->fm_indices >= FL(0.0) ? csound->FTFind(csound, p->fm_indices) : p->globals->zzo_tab; p->wavgaintab = *p->waveamps >= FL(0.0) ? csound->FTFind(csound, p->waveamps) : p->globals->zzhhhhz_tab; if (*p->pantable >= FL(0.0)) { p->pantab = csound->FTFind(csound, p->pantable); if (!p->pantab) return INITERROR("unable to load panning function table"); } else { p->pantab = NULL; /* use default linear panning function */ } if (UNLIKELY(!p->disttab)) return INITERROR("unable to load distribution table"); if (UNLIKELY(!p->costab)) return INITERROR("unable to load cosine table"); if (UNLIKELY(!p->gainmasktab)) return INITERROR("unable to load gain mask table"); if (UNLIKELY(!p->channelmasktab)) return INITERROR("unable to load channel mask table"); if (UNLIKELY(!p->env_attack_tab || !p->env_decay_tab || !p->env2_tab)) return INITERROR("unable to load envelope table"); if (UNLIKELY(!p->wavfreqstarttab)) return INITERROR("unable to load start frequency scaler table"); if (UNLIKELY(!p->wavfreqendtab)) return INITERROR("unable to load end frequency scaler table"); if (UNLIKELY(!p->fmamptab)) return INITERROR("unable to load FM index table"); if (UNLIKELY(!p->wavgaintab)) return INITERROR("unable to load wave gain table"); p->disttabshift = sizeof(unsigned)*CHAR_BIT - (unsigned)(log((double)p->disttab->flen)/log(2.0) + 0.5); p->cosineshift = sizeof(unsigned)*CHAR_BIT - (unsigned)(log((double)p->costab->flen)/log(2.0) + 0.5); p->zscale = FL(1.0)/FL(1 << p->cosineshift); p->wavfreqstartindex = p->wavfreqendindex = 0; p->gainmaskindex = p->channelmaskindex = 0; p->wavgainindex = 0; p->fmampindex = 0; p->distindex = 0; p->synced = 0; p->graininc = 0.0; /* allocate memory for the grain mix buffer */ size = CS_KSMPS*sizeof(MYFLT); if (p->aux.auxp == NULL || p->aux.size < size) csound->AuxAlloc(csound, size, &p->aux); else memset(p->aux.auxp, 0, size); /* allocate memory for the grain pool and initialize it*/ if (UNLIKELY(*p->max_grains < FL(1.0))) return INITERROR("maximum number of grains needs to be non-zero " "and positive"); size = ((unsigned)*p->max_grains)*sizeof(NODE); if (p->aux2.auxp == NULL || p->aux2.size < size) csound->AuxAlloc(csound, size, &p->aux2); p->gpool.mempool = p->aux2.auxp; init_pool(&p->gpool, (unsigned)*p->max_grains); /* find out which of the xrate parameters are arate */ p->grainfreq_arate = IS_ASIG_ARG(p->grainfreq) ? 1 : 0; p->out_of_voices_warning = 0; /* reset user warning indicator */ csound->SeedRandMT(&p->randstate, NULL, csound->GetRandomSeedFromTime()); return OK; } /* n is sample number for which the grain is to be scheduled * offset is time offset for grain in seconds, passed separately for hints */ static int schedule_grain(CSOUND *csound, PARTIKKEL *p, NODE *node, int32 n, double offset) { /* make a new grain */ MYFLT startfreqscale, endfreqscale; MYFLT maskgain, maskchannel; GRAIN *grain = &node->grain; unsigned int i; unsigned int chan; MYFLT graingain; MYFLT *gainmasks = p->gainmasktab->ftable; MYFLT *chanmasks = p->channelmasktab->ftable; MYFLT *freqstarts = p->wavfreqstarttab->ftable; MYFLT *freqends = p->wavfreqendtab->ftable; MYFLT *fmamps = p->fmamptab->ftable; MYFLT *wavgains = p->wavgaintab->ftable; unsigned wavgainsindex; /* the table boundary limits might well change at any time, so we do the * boundary clipping before using it to fetch a value */ /* get gain mask */ clip_index(p->gainmaskindex, gainmasks[0], gainmasks[1]); maskgain = gainmasks[p->gainmaskindex + 2]; p->gainmaskindex++; /* get channel mask */ clip_index(p->channelmaskindex, chanmasks[0], chanmasks[1]); maskchannel = chanmasks[p->channelmaskindex + 2]; p->channelmaskindex++; /* get frequency sweep start scaler */ clip_index(p->wavfreqstartindex, freqstarts[0], freqstarts[1]); startfreqscale = freqstarts[p->wavfreqstartindex + 2]; p->wavfreqstartindex++; /* get frequency sweep end scaler */ clip_index(p->wavfreqendindex, freqends[0], freqends[1]); endfreqscale = freqends[p->wavfreqendindex + 2]; p->wavfreqendindex++; /* get fm modulation index */ clip_index(p->fmampindex, fmamps[0], fmamps[1]); grain->fmamp = fmamps[p->fmampindex + 2]; p->fmampindex++; /* calculate waveform gain table index for later use */ clip_index(p->wavgainindex, wavgains[0], wavgains[1]); wavgainsindex = 5*p->wavgainindex++; graingain = *p->amplitude*maskgain; /* check if our mask gain is zero or if stochastic masking takes place */ if ((fabs(graingain) < FL(1e-8)) || (frand() > 1.0 - *p->randommask)) { /* grain is either masked out or has a zero amplitude, so we cancel it * and proceed with scheduling our next grain */ return_grain(&p->gpool, node); return OK; } grain->env2amount = *p->env2_amount; grain->envattacklen = (1.0 - *p->sustain_amount)*(*p->a_d_ratio); grain->envdecaystart = grain->envattacklen + *p->sustain_amount; grain->fmenvtab = p->fmenvtab; /* place a grain in between two channels according to channel mask value */ chan = (unsigned)maskchannel; if (UNLIKELY(chan >= p->num_outputs)) { return_grain(&p->gpool, node); return PERFERROR("channel mask specifies non-existing output channel"); } /* use panning law table if specified */ if (p->pantab != NULL) { const unsigned tabsize = p->pantab->flen/8; /* offset of pan table for current output pair */ const unsigned tab_offset = chan*tabsize; const unsigned offset = (unsigned)((maskchannel - chan)*(tabsize - 1)); const unsigned flip_offset = tabsize - 1 - offset; grain->gain1 = p->pantab->ftable[tab_offset + flip_offset]; grain->gain2 = p->pantab->ftable[tab_offset + offset]; } else { grain->gain1 = FL(1.0) - (maskchannel - chan); grain->gain2 = maskchannel - chan; } grain->chan1 = chan; grain->chan2 = p->num_outputs > chan + 1 ? chan + 1 : 0; /* duration in samples */ const double dur_samples = CS_ESR*(*p->duration)/1000.0; /* if grainlength is below one sample, we'll just cancel it */ if (dur_samples < 1.0) { return_grain(&p->gpool, node); return OK; } /* the grain is supposed to start at grainphase = 0, so calculate how far * we overshot that and correct all relevant wave and envelope phases * for proper sub-sample grain placement. if offset != 0, our grains * are probably not very synchronous, and will not benefit from this. * also only enable it for sufficiently high grain rates. current * threshold corresponds to around 150hz */ const double phase_corr = offset == 0.0 && p->graininc > 0.0032 ? p->grainphase/p->graininc : 0.0; const double rcp_samples = 1.0/dur_samples; grain->start = (unsigned)((double)n + offset*CS_ESR + phase_corr); grain->stop = (unsigned)(grain->start + dur_samples - phase_corr) + 1; /* set up the four wavetables and dsf to use in the grain */ for (i = 0; i < 5; ++i) { WAVEDATA *curwav = &grain->wav[i]; MYFLT freqmult = i != WAV_TRAINLET ? *(*(&p->wavekey1 + i))*(*p->wavfreq) : *p->trainletfreq; MYFLT startfreq = freqmult*startfreqscale; MYFLT endfreq = freqmult*endfreqscale; MYFLT *samplepos = *(&p->samplepos1 + i); MYFLT enddelta; curwav->table = i != WAV_TRAINLET ? p->wavetabs[i] : p->costab; curwav->gain = wavgains[wavgainsindex + i + 2]*graingain; /* drop wavetables with close to zero gain */ if (fabs(curwav->gain) < FL(1e-8)) { curwav->table = NULL; continue; } /* now do some trainlet specific setup */ if (i == WAV_TRAINLET) { double normalize, nh; MYFLT maxfreq = startfreq > endfreq ? startfreq : endfreq; /* limit dsf harmonics to nyquist to avoid aliasing. * minumum number of harmonics is 2, since 1 would yield just dc, * which we remove anyway */ nh = 0.5*CS_ESR/fabs(maxfreq); if (nh > fabs(*p->harmonics)) nh = fabs(*p->harmonics); grain->harmonics = (unsigned)nh + 1; if (grain->harmonics < 2) grain->harmonics = 2; grain->falloff = *p->falloff; grain->falloff_pow_N = intpow_(grain->falloff, grain->harmonics); /* normalize trainlets to uniform peak, using geometric sum */ if (FABS(grain->falloff) > FL(0.9999) && FABS(grain->falloff) < FL(1.0001)) /* limit case for falloff = 1 */ normalize = 1.0/(double)grain->harmonics; else normalize = (1.0 - fabs(grain->falloff)) /(1.0 - fabs(grain->falloff_pow_N)); curwav->gain *= normalize; } curwav->delta = startfreq*csound->onedsr; enddelta = endfreq*csound->onedsr; if (i != WAV_TRAINLET) { /* set wavphase to samplepos parameter */ curwav->phase = samplepos[n]; } else { /* set to 0.5 so the dsf pulse doesn't occur at the very start of * the grain where it'll probably be enveloped away anyway */ curwav->phase = 0.5; } /* place grain between samples. this is especially important to make * high frequency synchronous grain streams sounds right */ curwav->phase += phase_corr*startfreq*csound->onedsr; /* clamp phase in case it's out of bounds */ curwav->phase = curwav->phase > 1.0 ? 1.0 : curwav->phase; curwav->phase = curwav->phase < 0.0 ? 0.0 : curwav->phase; /* phase and delta for wavetable synthesis are scaled by table length */ if (i != WAV_TRAINLET) { double tablen = (double)curwav->table->flen; curwav->phase *= tablen; curwav->delta *= tablen; enddelta *= tablen; } /* the sweep curve generator is a first order iir filter */ if (curwav->delta == enddelta || *p->freqsweepshape == FL(0.5)) { /* special case for linear sweep */ curwav->sweepdecay = 1.0; curwav->sweepoffset = (enddelta - curwav->delta)*rcp_samples; } else { /* handle extreme cases the generic code doesn't handle too well */ if (*p->freqsweepshape < FL(0.001)) { curwav->sweepdecay = 1.0; curwav->sweepoffset = 0.0; } else if (*p->freqsweepshape > FL(0.999)) { curwav->sweepdecay = 0.0; curwav->sweepoffset = enddelta; } else { double start_offset, total_decay, t; t = fabs((*p->freqsweepshape - 1.0)/(*p->freqsweepshape)); curwav->sweepdecay = pow(t, 2.0*rcp_samples); total_decay = t*t; /* pow(curwav->sweepdecay, samples) */ start_offset = (enddelta - curwav->delta*total_decay)/ (1.0 - total_decay); curwav->sweepoffset = start_offset*(1.0 - curwav->sweepdecay); } } } grain->envinc = rcp_samples; grain->envphase = phase_corr*grain->envinc; /* link new grain into the list */ node->next = p->grainroot; p->grainroot = node; return OK; } /* this function schedules the grains that are bound to happen this k-period */ static int schedule_grains(CSOUND *csound, PARTIKKEL *p) { uint32_t koffset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; NODE *node; MYFLT **waveformparams = &p->waveform1; MYFLT grainfreq = fabs(*p->grainfreq); /* krate table lookup, first look up waveform ftables */ for (n = 0; n < 4; ++n) { p->wavetabs[n] = *waveformparams[n] >= FL(0.0) ? csound->FTnp2Find(csound, waveformparams[n]) : p->globals->zzz_tab; if (UNLIKELY(p->wavetabs[n] == NULL)) return PERFERROR("unable to load waveform table"); } /* look up fm envelope table for use in grains scheduled this kperiod */ p->fmenvtab = *p->fm_env >= FL(0.0) ? csound->FTFind(csound, p->fm_env) : p->globals->ooo_tab; if (UNLIKELY(!p->fmenvtab)) return PERFERROR("unable to load FM envelope table"); if (UNLIKELY(early)) nsmps -= early; /* start grain scheduling */ for (n = koffset; n < nsmps; ++n) { if (p->sync[n] >= FL(1.0)) { /* we got a full sync pulse, hardsync grain clock if needed */ if (!p->synced) { p->grainphase = 1.0; p->synced = 1; } else { /* if sync is held high, stop the grain clock until it goes * back to zero or below again */ p->graininc = 0.0; } } else { /* softsync-like functionality where we advance the grain clock by * the amount given by the sync value */ if (p->sync[n]) { p->grainphase += p->sync[n]; p->grainphase = p->grainphase > 1.0 ? 1.0 : p->grainphase; p->grainphase = p->grainphase < 0.0 ? 0.0 : p->grainphase; } p->synced = 0; } if (p->grainphase >= 1.0) { double offset; do p->grainphase -= 1.0; while (UNLIKELY(p->grainphase >= 1.0)); /* schedule new synchronous or synced grain */ /* first determine time offset for grain */ if (*p->distribution >= FL(0.0)) { /* positive distrib, choose random point in table */ unsigned rnd = csound->RandMT(&p->randstate); offset = p->disttab->ftable[rnd >> p->disttabshift]; offset *= *p->distribution; } else { /* negative distrib, choose sequential point in table */ offset = p->disttab->ftable[p->distindex++]; offset *= -*p->distribution; if ((uint32_t)p->distindex >= p->disttab->flen) p->distindex = 0; } /* convert offset to seconds, also limiting it to 10 seconds to * avoid accidentally filling grain pool with grains which will * spawn in half a day */ if (grainfreq < FL(0.001)) { /* avoid div by zero */ offset = 0; } else { offset /= grainfreq; if (offset > 10.0) offset = 10.0; } /* check if there are any grains left in the pool */ if (!p->gpool.free_nodes) { if (!p->out_of_voices_warning) { WARNING("maximum number of grains reached"); p->out_of_voices_warning = 1; /* we only warn once */ } kill_oldest_grain(&p->gpool, p->grainroot); } /* add a new grain */ node = get_grain(&p->gpool); /* check first, in case we'll change the above behaviour of * killing a grain */ if (node) { int ret = schedule_grain(csound, p, node, n, offset); if (ret != OK) return ret; } /* create a sync pulse for use in partikkelsync */ if (p->globals_entry) p->globals_entry->synctab[n] = FL(1.0); } /* store away the scheduler phase for use in partikkelsync */ if (p->globals_entry) p->globals_entry->synctab[CS_KSMPS + n] = p->grainphase; if (p->grainfreq_arate) grainfreq = fabs(p->grainfreq[n]); p->graininc = grainfreq*csound->onedsr; p->grainphase += p->graininc; } return OK; } /* Main synthesis loops */ /* NOTE: the main synthesis loop is duplicated for both wavetable and * trainlet synthesis for speed */ static inline void render_wave(PARTIKKEL *p, GRAIN *grain, WAVEDATA *wav, MYFLT *buf, unsigned stop) { unsigned n; double fmenvphase = grain->envphase; /* wavetable synthesis */ for (n = grain->start; n < stop; ++n) { double tablen = (double)wav->table->flen; unsigned x0; MYFLT frac, fmenv; /* make sure phase accumulator stays within bounds */ while (UNLIKELY(wav->phase >= tablen)) wav->phase -= tablen; while (UNLIKELY(wav->phase < 0.0)) wav->phase += tablen; /* sample table lookup with linear interpolation */ x0 = (unsigned)wav->phase; frac = (MYFLT)(wav->phase - x0); buf[n] += lrp(wav->table->ftable[x0], wav->table->ftable[x0 + 1], frac)*wav->gain; fmenv = grain->fmenvtab->ftable[(size_t)(fmenvphase*FMAXLEN) >> grain->fmenvtab->lobits]; fmenvphase += grain->envinc; wav->phase += wav->delta + wav->delta*p->fm[n]*grain->fmamp*fmenv; /* apply sweep */ wav->delta = wav->delta*wav->sweepdecay + wav->sweepoffset; } } static inline void render_trainlet(PARTIKKEL *p, GRAIN *grain, WAVEDATA *wav, MYFLT *buf, unsigned stop) { unsigned n; double fmenvphase = grain->envphase; /* trainlet synthesis */ for (n = grain->start; n < stop; ++n) { MYFLT fmenv; while (UNLIKELY(wav->phase >= 1.0)) wav->phase -= 1.0; while (UNLIKELY(wav->phase < 0.0)) wav->phase += 1.0; /* dsf/trainlet synthesis */ buf[n] += wav->gain*dsf(p->costab, grain, wav->phase, p->zscale, p->cosineshift); fmenv = grain->fmenvtab->ftable[(size_t)(fmenvphase*FMAXLEN) >> grain->fmenvtab->lobits]; fmenvphase += grain->envinc; wav->phase += wav->delta + wav->delta*p->fm[n]*grain->fmamp*fmenv; wav->delta = wav->delta*wav->sweepdecay + wav->sweepoffset; } } /* do the actual waveform synthesis */ static inline void render_grain(CSOUND *csound, PARTIKKEL *p, GRAIN *grain) { int i; unsigned n; MYFLT *out1 = *(&(p->output1) + grain->chan1); MYFLT *out2 = *(&(p->output1) + grain->chan2); unsigned stop = grain->stop > CS_KSMPS ? CS_KSMPS : grain->stop; MYFLT *buf = (MYFLT *)p->aux.auxp; if (grain->start >= CS_KSMPS) return; /* grain starts at a later kperiod */ for (i = 0; i < 5; ++i) { WAVEDATA *curwav = &grain->wav[i]; /* check if ftable is to be rendered */ if (curwav->table == NULL) continue; if (i != WAV_TRAINLET) render_wave(p, grain, curwav, buf, stop); else render_trainlet(p, grain, curwav, buf, stop); } /* apply envelopes */ for (n = grain->start; n < stop; ++n) { MYFLT env, env2, output; double envphase; FUNC *envtable; /* apply envelopes */ if (grain->envphase < grain->envattacklen) { envtable = p->env_attack_tab; envphase = grain->envphase/grain->envattacklen; } else if (grain->envphase < grain->envdecaystart) { /* for sustain, use last sample in attack table */ envtable = p->env_attack_tab; envphase = 1.0; } else if (grain->envphase < 1.0) { envtable = p->env_decay_tab; envphase = (grain->envphase - grain->envdecaystart)/(1.0 - grain->envdecaystart); } else { /* clamp envelope phase because of round-off errors */ envtable = grain->envdecaystart < 1.0 ? p->env_decay_tab : p->env_attack_tab; envphase = grain->envphase = 1.0; } /* fetch envelope values */ env = envtable->ftable[(size_t)(envphase*FMAXLEN) >> envtable->lobits]; env2 = p->env2_tab->ftable[(size_t)(grain->envphase*FMAXLEN) >> p->env2_tab->lobits]; env2 = FL(1.0) - grain->env2amount + grain->env2amount*env2; grain->envphase += grain->envinc; /* generate grain output sample */ output = buf[n]*env*env2; /* now distribute this grain to the output channels it's supposed to * end up in, as decided by the channel mask */ out1[n] += output*grain->gain1; out2[n] += output*grain->gain2; } /* now clear the area we just worked in */ memset(buf + grain->start, 0, (stop - grain->start)*sizeof(MYFLT)); } static int partikkel(CSOUND *csound, PARTIKKEL *p) { int ret; unsigned int n; NODE **nodeptr; MYFLT **outputs = &p->output1; if (UNLIKELY(p->aux.auxp == NULL || p->aux2.auxp == NULL)) return PERFERROR("not initialised"); if ((ret = schedule_grains(csound, p)) != OK) return ret; /* clear output buffers, we'll be accumulating our outputs */ for (n = 0; n < p->num_outputs; ++n) memset(outputs[n], 0, sizeof(MYFLT)*CS_KSMPS); /* prepare to traverse grain list */ nodeptr = &p->grainroot; while (*nodeptr) { GRAIN *grain = &((*nodeptr)->grain); /* render current grain to outputs */ render_grain(csound, p, grain); /* check if grain is finished */ if (grain->stop <= CS_KSMPS) { /* grain is finished, deactivate it */ *nodeptr = return_grain(&p->gpool, *nodeptr); } else { /* extend grain lifetime with one k-period and find next grain */ if (CS_KSMPS > grain->start) grain->start = 0; /* grain is active */ else grain->start -= CS_KSMPS; /* grain is not yet active */ grain->stop -= CS_KSMPS; nodeptr = &((*nodeptr)->next); } } return OK; } /* partikkelsync stuff */ static int partikkelsync_init(CSOUND *csound, PARTIKKEL_SYNC *p) { PARTIKKEL_GLOBALS *pg; PARTIKKEL_GLOBALS_ENTRY *pe; if (UNLIKELY((int)*p->opcodeid == 0)) return csound->InitError(csound, Str("partikkelsync: opcode id needs to be a non-zero integer")); pg = csound->QueryGlobalVariable(csound, "partikkel"); if (UNLIKELY(pg == NULL || pg->rootentry == NULL)) return csound->InitError(csound, Str("partikkelsync: could not find opcode id")); pe = pg->rootentry; while (pe->id != *p->opcodeid && pe->next != NULL) pe = pe->next; if (UNLIKELY(pe->id != *p->opcodeid)) return csound->InitError(csound, Str("partikkelsync: could not find opcode id")); p->ge = pe; /* find out if we're supposed to output grain scheduler phase too */ p->output_schedphase = csound->GetOutputArgCnt(p) > 1; return OK; } static int partikkelsync(CSOUND *csound, PARTIKKEL_SYNC *p) { /* write sync pulse data */ memcpy(p->syncout, p->ge->synctab, CS_KSMPS*sizeof(MYFLT)); /* write scheduler phase data, if user wanted it */ if (p->output_schedphase) { memcpy(p->schedphaseout, p->ge->synctab + CS_KSMPS, CS_KSMPS*sizeof(MYFLT)); } /* clear first half of sync table to get rid of old sync pulses */ memset(p->ge->synctab, 0, CS_KSMPS*sizeof(MYFLT)); return OK; } static int get_global_entry(CSOUND *csound, PARTIKKEL_GLOBALS_ENTRY **entry, MYFLT opcodeid, const char *prefix) { PARTIKKEL_GLOBALS *pg; PARTIKKEL_GLOBALS_ENTRY *pe; pg = csound->QueryGlobalVariable(csound, "partikkel"); if (UNLIKELY(pg == NULL)) return csound->InitError(csound, Str("%s: partikkel not initialized"), prefix); /* try to find entry corresponding to our opcodeid */ pe = pg->rootentry; while (pe != NULL && pe->id != opcodeid) pe = pe->next; if (UNLIKELY(pe == NULL)) return csound->InitError(csound, Str("%s: could not find opcode id"), prefix); *entry = pe; return OK; } static int partikkelget_init(CSOUND *csound, PARTIKKEL_GET *p) { return get_global_entry(csound, &p->ge, *p->opcodeid, "partikkelget"); } static int partikkelget(CSOUND *csound, PARTIKKEL_GET *p) { PARTIKKEL *partikkel = p->ge->partikkel; switch ((int)*p->index) { case 0: *p->valout = (MYFLT)partikkel->gainmaskindex; break; case 1: *p->valout = (MYFLT)partikkel->wavfreqstartindex; break; case 2: *p->valout = (MYFLT)partikkel->wavfreqendindex; break; case 3: *p->valout = (MYFLT)partikkel->fmampindex; break; case 4: *p->valout = (MYFLT)partikkel->channelmaskindex; break; case 5: *p->valout = (MYFLT)partikkel->wavgainindex; break; } return OK; } static int partikkelset_init(CSOUND *csound, PARTIKKEL_SET *p) { return get_global_entry(csound, &p->ge, *p->opcodeid, "partikkelset"); } static int partikkelset(CSOUND *csound, PARTIKKEL_SET *p) { PARTIKKEL *partikkel = p->ge->partikkel; switch ((int)*p->index) { case 0: partikkel->gainmaskindex = (unsigned)*p->value; break; case 1: partikkel->wavfreqstartindex = (unsigned)*p->value; break; case 2: partikkel->wavfreqendindex = (unsigned)*p->value; break; case 3: partikkel->fmampindex = (unsigned)*p->value; break; case 4: partikkel->channelmaskindex = (unsigned)*p->value; break; case 5: partikkel->wavgainindex = (unsigned)*p->value; break; } return OK; } static OENTRY partikkel_localops[] = { { "partikkel", sizeof(PARTIKKEL), TR, 5, "ammmmmmm", "xkiakiiikkkkikkiiaikikkkikkkkkiaaaakkkkioj", (SUBR)partikkel_init, (SUBR)NULL, (SUBR)partikkel }, { "partikkelsync", sizeof(PARTIKKEL_SYNC), TR, 5, "am", "i", (SUBR)partikkelsync_init, (SUBR)NULL, (SUBR)partikkelsync }, { "partikkelget", sizeof(PARTIKKEL_GET), TR, 3, "k", "ki", (SUBR)partikkelget_init, (SUBR)partikkelget, (SUBR)NULL }, { "partikkelset", sizeof(PARTIKKEL_SET), TR, 3, "", "kki", (SUBR)partikkelset_init, (SUBR)partikkelset, (SUBR)NULL } }; LINKAGE_BUILTIN(partikkel_localops) csound-6.10.0/Opcodes/partikkel.h000066400000000000000000000110251321653344700166330ustar00rootroot00000000000000/* Partikkel - a granular synthesis module for Csound 5 Copyright (C) 2006-2009 yvind Brandtsegg, Torgeir Strand Henriksen, Thom Johansen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "csoundCore.h" #include "interlocks.h" typedef struct { FUNC *table; double phase, delta; double sweepoffset, sweepdecay; MYFLT gain; } WAVEDATA; typedef struct { unsigned start, stop; double envphase, envinc; double envattacklen, envdecaystart; double env2amount; MYFLT fmamp; FUNC *fmenvtab; unsigned harmonics; MYFLT falloff, falloff_pow_N; MYFLT gain1, gain2; unsigned chan1, chan2; WAVEDATA wav[5]; } GRAIN; /* which of the wav[] entries above correspond to the trainlet generator */ #define WAV_TRAINLET 4 /* support structs for the grain pool routines */ typedef struct NODE { GRAIN grain; struct NODE *next; } NODE; typedef struct { NODE *grainlist; char *mempool; unsigned free_nodes; } GRAINPOOL; struct PARTIKKEL; typedef struct PARTIKKEL_GLOBALS_ENTRY { MYFLT id; MYFLT *synctab; struct PARTIKKEL *partikkel; struct PARTIKKEL_GLOBALS_ENTRY *next; } PARTIKKEL_GLOBALS_ENTRY; typedef struct { /* default tables. name describes table contents, 'z' is 0.0, 'o' is 1.0 * and 'h' is 0.5 */ FUNC *ooo_tab; FUNC *zzz_tab; FUNC *zzo_tab; FUNC *zzhhhhz_tab; //char *tablestorage; PARTIKKEL_GLOBALS_ENTRY *rootentry; } PARTIKKEL_GLOBALS; typedef struct PARTIKKEL { OPDS h; /* output arrays */ MYFLT *output1, *output2, *output3, *output4; MYFLT *output5, *output6, *output7, *output8; /* opcode parameters */ MYFLT *grainfreq; MYFLT *distribution; MYFLT *dist; MYFLT *sync; MYFLT *env2_amount; MYFLT *env2; MYFLT *env_attack; MYFLT *env_decay; MYFLT *sustain_amount; MYFLT *a_d_ratio; MYFLT *duration; MYFLT *amplitude; MYFLT *gainmasks; MYFLT *wavfreq; MYFLT *freqsweepshape; MYFLT *wavfreq_startmuls; MYFLT *wavfreq_endmuls; MYFLT *fm; MYFLT *fm_indices; MYFLT *fm_env; MYFLT *cosine; MYFLT *trainletfreq; MYFLT *harmonics; MYFLT *falloff; MYFLT *channelmasks; MYFLT *randommask; MYFLT *waveform1, *waveform2, *waveform3, *waveform4; MYFLT *waveamps; MYFLT *samplepos1, *samplepos2, *samplepos3, *samplepos4; MYFLT *wavekey1, *wavekey2, *wavekey3, *wavekey4; MYFLT *max_grains; MYFLT *opcodeid; MYFLT *pantable; /* internal variables */ PARTIKKEL_GLOBALS *globals; PARTIKKEL_GLOBALS_ENTRY *globals_entry; GRAINPOOL gpool; NODE *grainroot; int out_of_voices_warning; unsigned num_outputs; int grainfreq_arate; int synced; AUXCH aux, aux2; CsoundRandMTState randstate; FUNC *wavetabs[4]; FUNC *costab; unsigned cosineshift; MYFLT zscale; FUNC *disttab; unsigned distindex; unsigned disttabshift; FUNC *env2_tab, *env_attack_tab, *env_decay_tab; FUNC *fmenvtab; FUNC *gainmasktab; unsigned gainmaskindex; FUNC *wavfreqstarttab, *wavfreqendtab; unsigned wavfreqstartindex, wavfreqendindex; FUNC *fmamptab; unsigned fmampindex; FUNC *channelmasktab; unsigned channelmaskindex; FUNC *wavgaintab; unsigned wavgainindex; double grainphase, graininc; FUNC *pantab; } PARTIKKEL; typedef struct { OPDS h; /* output arrays */ MYFLT *syncout; MYFLT *schedphaseout; /* opcode parameters */ MYFLT *opcodeid; /* internal variables */ int output_schedphase; PARTIKKEL_GLOBALS_ENTRY *ge; } PARTIKKEL_SYNC; typedef struct { OPDS h; /* output */ MYFLT *valout; /* inputs */ MYFLT *index; MYFLT *opcodeid; PARTIKKEL_GLOBALS_ENTRY *ge; } PARTIKKEL_GET; typedef struct { OPDS h; /* inputs */ MYFLT *index; MYFLT *value; MYFLT *opcodeid; PARTIKKEL_GLOBALS_ENTRY *ge; } PARTIKKEL_SET; csound-6.10.0/Opcodes/paulstretch.c000066400000000000000000000140401321653344700171760ustar00rootroot00000000000000/* paulstretch.c: This is an implementation of the paulstretch algorithm by Paul Nasca Octavian, based off of the Numpy/Scipy python implementation written by the same author. Copyright (C) 2016 by Paul Batchelor This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #ifdef _MSC_VER #define _USE_MATH_DEFINES #endif #include #include #include "csoundCore.h" #include "interlocks.h" #include "H/fftlib.h" typedef struct { OPDS h; MYFLT *out, *stretch, *winsize, *ifn; MYFLT start_pos, displace_pos; MYFLT *window; MYFLT *old_windowed_buf; MYFLT *hinv_buf; MYFLT *output; FUNC *ft; uint32_t windowsize; uint32_t half_windowsize; MYFLT *tmp; uint32_t counter; AUXCH m_window; AUXCH m_old_windowed_buf; AUXCH m_hinv_buf; AUXCH m_output; AUXCH m_tmp; } PAULSTRETCH; static void compute_block(CSOUND *csound, PAULSTRETCH *p) { uint32_t istart_pos = floor(p->start_pos); uint32_t pos; uint32_t i; uint32_t windowsize = p->windowsize; uint32_t half_windowsize = p->half_windowsize; MYFLT *hinv_buf = p->hinv_buf; MYFLT *old_windowed_buf= p->old_windowed_buf; MYFLT *tbl = p->ft->ftable; MYFLT *window = p->window; MYFLT *output= p->output; MYFLT *tmp = p->tmp; for (i = 0; i < windowsize; i++) { pos = istart_pos + i; if (LIKELY(pos < p->ft->flen)) { tmp[i] = tbl[pos] * window[i]; } else { tmp[i] = FL(0.0); } } /* re-order bins and take FFT */ tmp[p->windowsize] = tmp[1]; tmp[p->windowsize + 1] = FL(0.0); csoundRealFFTnp2(csound, tmp, p->windowsize); /* randomize phase */ for (i = 0; i < windowsize + 2; i += 2) { MYFLT mag = HYPOT(tmp[i], tmp[i + 1]); // Android 5.1 does not seem to have cexpf ... // complex ph = cexpf(I * ((MYFLT)rand() / RAND_MAX) * 2 * M_PI); // so ... MYFLT x = (((MYFLT)rand() / RAND_MAX) * 2 * M_PI); #ifdef MSVC // TODO - Double check this is equivalent to non-windows complex definition _Fcomplex ph = { cos(x), sin(x) }; #else complex double ph = cos(x) + I*sin(x); #endif tmp[i] = mag * (MYFLT)crealf(ph); tmp[i + 1] = mag * (MYFLT)cimagf(ph); } /* re-order bins and take inverse FFT */ tmp[1] = tmp[p->windowsize]; csoundInverseRealFFTnp2(csound, tmp, p->windowsize); /* apply window and overlap */ for (i = 0; i < windowsize; i++) { tmp[i] *= window[i]; if (i < half_windowsize) { output[i] = (MYFLT)(tmp[i] + old_windowed_buf[half_windowsize + i]); output[i] *= hinv_buf[i]; } old_windowed_buf[i] = tmp[i]; } p->start_pos += p->displace_pos; } static int ps_init(CSOUND* csound, PAULSTRETCH *p) { FUNC *ftp = csound->FTnp2Find(csound, p->ifn); uint32_t i = 0; unsigned int size; if (ftp == NULL) return csound->InitError(csound, Str("paulstretch: table not found")); p->ft = ftp; p->windowsize = (uint32_t)FLOOR((CS_ESR * *p->winsize)); if (p->windowsize < 16) { p->windowsize = 16; } p->half_windowsize = p->windowsize / 2; p->displace_pos = (p->windowsize * FL(0.5)) / *p->stretch; size = sizeof(MYFLT) * p->windowsize; csound->AuxAlloc(csound, size, &(p->m_window)); p->window = p->m_window.auxp; csound->AuxAlloc(csound, size, &p->m_old_windowed_buf); p->old_windowed_buf = p->m_old_windowed_buf.auxp; csound->AuxAlloc(csound, (size_t)(sizeof(MYFLT) * p->half_windowsize), &p->m_hinv_buf); p->hinv_buf = p->m_hinv_buf.auxp; csound->AuxAlloc(csound, (size_t)(sizeof(MYFLT) * p->half_windowsize), &p->m_output); p->output = p->m_output.auxp; csound->AuxAlloc(csound, size + 2 * sizeof(MYFLT), &p->m_tmp); p->tmp = p->m_tmp.auxp; /* Create Hann window */ for (i = 0; i < p->windowsize; i++) { p->window[i] = FL(0.5) - COS(i * TWOPI_F / (p->windowsize - 1)) * FL(0.5); } /* create inverse Hann window */ { MYFLT hinv_sqrt2 = (1 + SQRT(FL(0.5))) * FL(0.5); for (i = 0; i < p->half_windowsize; i++) { p->hinv_buf[i] = hinv_sqrt2 - (FL(1.0) - hinv_sqrt2) * COS(i * TWOPI_F / p->half_windowsize); } } p->start_pos = FL(0.0); p->counter = 0; return OK; } static int paulstretch_perf(CSOUND* csound, PAULSTRETCH *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *out = p->out; if (UNLIKELY(offset)) { memset(p->out, '\0', offset*sizeof(MYFLT)); memset(p->out, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&p->out[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { if (p->counter == 0) { compute_block(csound, p); } out[n] = p->output[p->counter]; p->counter = (p->counter + 1) % p->half_windowsize; } return OK; } static OENTRY paulstretch_localops[] = { { "paulstretch", (int) sizeof(PAULSTRETCH), TR, 5, "a", "iii", (int (*)(CSOUND *, void *)) ps_init, (int (*)(CSOUND *, void *)) NULL, (int (*)(CSOUND *, void *)) paulstretch_perf} }; LINKAGE_BUILTIN(paulstretch_localops) csound-6.10.0/Opcodes/phisem.c000066400000000000000000001411171321653344700161330ustar00rootroot00000000000000/* phisem.c: Copyright (C) 1997, 2000 Perry Cook, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General ublic License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /**********************************************************/ /* PhISEM (Physically Informed Stochastic Event Modeling */ /* by Perry R. Cook, Princeton, February 1997 */ /* */ /* Meta-model that simulates all of: */ /* Maraca Simulation by Perry R. Cook, Princeton, 1996-7 */ /* Sekere Simulation by Perry R. Cook, Princeton, 1996-7 */ /* Cabasa Simulation by Perry R. Cook, Princeton, 1996-7 */ /* Bamboo Windchime Simulation, by Perry R. Cook, 1996-7 */ /* Water Drops Simulation, by Perry R. Cook, 1996-7 */ /* Tambourine Simulation, by Perry R. Cook, 1996-7 */ /* Sleighbells Simulation, by Perry R. Cook, 1996-7 */ /* Guiro Simulation, by Perry R. Cook, 1996-7 */ /* */ /**********************************************************/ /* PhOLIES (Physically-Oriented Library of */ /* Imitated Environmental Sounds), Perry Cook, 1997-9 */ /* */ /* Stix1 (walking on brittle sticks) */ /* Crunch1 (like new fallen snow, or not) */ /* Wrench (basic socket wrench, friend of guiro) */ /* Sandpapr (sandpaper) */ /**********************************************************/ // #include "csdl.h" #include "csoundCore.h" #include "interlocks.h" #include "phisem.h" #include /* To do "10: Wrench", "12: CokeCan"}; */ static inline int my_random(CSOUND *csound, int max) { /* Return Random Int Between 0 and max */ return (csound->Rand31(&(csound->randSeed1)) % (max + 1)); } static MYFLT noise_tick(CSOUND *csound) { /* Return random MYFLT float between -1.0 and 1.0 */ MYFLT temp; temp = (MYFLT) csound->Rand31(&(csound->randSeed1)) - FL(1073741823.5); return (temp * (MYFLT) (1.0 / 1073741823.0)); } /************************* MARACA *****************************/ #define MARA_SOUND_DECAY FL(0.95) #define MARA_SYSTEM_DECAY FL(0.999) #define MARA_GAIN FL(20.0) #define MARA_NUM_BEANS 25 #define MARA_CENTER_FREQ FL(3200.0) #define MARA_RESON FL(0.96) /*********************** SEKERE *****************************/ #define SEKE_SOUND_DECAY FL(0.96) #define SEKE_SYSTEM_DECAY FL(0.999) #define SEKE_GAIN FL(20.0) #define SEKE_NUM_BEANS FL(64.0) #define SEKE_CENTER_FREQ FL(5500.0) #define SEKE_RESON FL(0.6) /*********************** SANDPAPER **************************/ #define SANDPAPR_SOUND_DECAY FL(0.999) #define SANDPAPR_SYSTEM_DECAY FL(0.999) #define SANDPAPR_GAIN FL(0.5) #define SANDPAPR_NUM_GRAINS FL(128.0) #define SANDPAPR_CENTER_FREQ FL(4500.0) #define SANDPAPR_RESON FL(0.6) /*(********************** CABASA *****************************/ #define CABA_SOUND_DECAY FL(0.96) #define CABA_SYSTEM_DECAY FL(0.997) #define CABA_GAIN FL(40.0) #define CABA_NUM_BEADS 512 #define CABA_CENTER_FREQ FL(3000.0) #define CABA_RESON FL(0.7) /************************ Bamboo Wind Chimes *****************/ #define BAMB_SOUND_DECAY FL(0.95) #define BAMB_SYSTEM_DECAY FL(0.9999) #define BAMB_GAIN FL(2.0) #define BAMB_NUM_TUBES FL(1.25) #define BAMB_CENTER_FREQ0 FL(2800.0) #define BAMB_CENTER_FREQ1 (FL(0.8) * FL(2800.0)) #define BAMB_CENTER_FREQ2 (FL(1.2) * FL(2800.0)) #define BAMB_RESON FL(0.995) /******************* Water Drops ****************************/ #define WUTR_SOUND_DECAY FL(0.95) #define WUTR_SYSTEM_DECAY FL(0.996) #define WUTR_GAIN FL(1.0) #define WUTR_NUM_SOURCES FL(10.0) #define WUTR_CENTER_FREQ0 FL(450.0) #define WUTR_CENTER_FREQ1 FL(600.0) #define WUTR_CENTER_FREQ2 FL(750.0) #define WUTR_RESON FL(0.9985) #define WUTR_FREQ_SWEEP FL(1.0001) /****************** TAMBOURINE *****************************/ #define TAMB_SOUND_DECAY FL(0.95) #define TAMB_SYSTEM_DECAY FL(0.9985) #define TAMB_GAIN FL(5.0) #define TAMB_NUM_TIMBRELS 32 #define TAMB_SHELL_FREQ FL(2300.0) #define TAMB_SHELL_GAIN FL(0.1) #define TAMB_SHELL_RESON FL(0.96) #define TAMB_CYMB_FREQ1 FL(5600.0) #define TAMB_CYMB_FREQ2 FL(8100.0) #define TAMB_CYMB_RESON FL(0.99) /********************** SLEIGHBELLS *************************/ #define SLEI_SOUND_DECAY FL(0.97) #define SLEI_SYSTEM_DECAY FL(0.9994) #define SLEI_GAIN FL(1.0) #define SLEI_NUM_BELLS 32 #define SLEI_CYMB_FREQ0 FL(2500.0) #define SLEI_CYMB_FREQ1 FL(5300.0) #define SLEI_CYMB_FREQ2 FL(6500.0) #define SLEI_CYMB_FREQ3 FL(8300.0) #define SLEI_CYMB_FREQ4 FL(9800.0) #define SLEI_CYMB_RESON FL(0.99) /*************************** GUIRO ***********************/ #define GUIR_SOUND_DECAY FL(0.95) #define GUIR_GAIN FL(10.0) #define GUIR_NUM_PARTS 128 #define GUIR_GOURD_FREQ FL(2500.0) #define GUIR_GOURD_RESON FL(0.97) #define GUIR_GOURD_FREQ2 FL(4000.0) #define GUIR_GOURD_RESON2 FL(0.97) /************************** WRENCH ***********************/ #define WRENCH_SOUND_DECAY FL(0.95) #define WRENCH_GAIN 5 #define WRENCH_NUM_PARTS FL(128.0) #define WRENCH_FREQ FL(3200.0) #define WRENCH_RESON FL(0.99) #define WRENCH_FREQ2 FL(8000.) #define WRENCH_RESON2 FL(0.992) /************************ COKECAN **************************/ #define COKECAN_SOUND_DECAY FL(0.97) #define COKECAN_SYSTEM_DECAY FL(0.999) #define COKECAN_GAIN FL(0.8) #define COKECAN_NUM_PARTS 48 #define COKECAN_HELMFREQ FL(370.0) #define COKECAN_HELM_RES FL(0.99) #define COKECAN_METLFREQ0 FL(1025.0) #define COKECAN_METLFREQ1 FL(1424.0) #define COKECAN_METLFREQ2 FL(2149.0) #define COKECAN_METLFREQ3 FL(3596.0) #define COKECAN_METL_RES FL(0.992) /************************************************************/ /* PhOLIES (Physically-Oriented Library of */ /* Imitated Environmental Sounds), Perry Cook, 1997-8 */ /************************************************************/ /*********************** STIX1 *****************************/ #define STIX1_SOUND_DECAY FL(0.96) #define STIX1_SYSTEM_DECAY FL(0.998) #define STIX1_GAIN FL(30.0) #define STIX1_NUM_BEANS FL(2.0) #define STIX1_CENTER_FREQ FL(5500.0) #define STIX1_RESON FL(0.6) /************************ Crunch1 ***************************/ #define CRUNCH1_SOUND_DECAY FL(0.95) #define CRUNCH1_SYSTEM_DECAY FL(0.99806) #define CRUNCH1_GAIN FL(20.0) #define CRUNCH1_NUM_BEADS 7 #define CRUNCH1_CENTER_FREQ FL(800.0) #define CRUNCH1_RESON FL(0.95) #define MAX_SHAKE FL(2000.0) #define MIN_ENERGY FL(0.0) /* 0.1 or 0.3?? */ static int cabasaset(CSOUND *csound, CABASA *p) { p->sndLevel = FL(0.0); p->kloop = (int)(p->h.insdshead->offtim * CS_EKR) - (int)(CS_EKR * *p->dettack); p->outputs0 = FL(0.0); p->outputs1 = FL(0.0); p->shake_maxSave = FL(0.0); p->totalEnergy = FL(0.0); p->num_objects = CABA_NUM_BEADS; p->soundDecay = CABA_SOUND_DECAY; p->systemDecay = CABA_SYSTEM_DECAY; p->gain = LOG((MYFLT)CABA_NUM_BEADS)*CABA_GAIN/(MYFLT)CABA_NUM_BEADS; p->resons = CABA_RESON; p->coeffs1 = CABA_RESON * CABA_RESON; p->coeffs0 = - CABA_RESON * FL(2.0) * COS(CABA_CENTER_FREQ * csound->tpidsr); /* Note On */ p->shakeEnergy = *p->amp * MAX_SHAKE * FL(0.1); if (p->shakeEnergy > MAX_SHAKE) p->shakeEnergy = MAX_SHAKE; p->last_num = FL(0.0); return OK; } static int cabasa(CSOUND *csound, CABASA *p) { MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT data; /* Use locals for speed */ MYFLT shakeEnergy = p->shakeEnergy; MYFLT systemDecay = p->systemDecay; MYFLT sndLevel = p->sndLevel; MYFLT soundDecay = p->soundDecay; MYFLT input; MYFLT outputs0 = p->outputs0; MYFLT outputs1 = p->outputs1; MYFLT coeff0 = p->coeffs0; MYFLT coeff1 = p->coeffs1; MYFLT gain = p->gain; if (*p->num_beads != p->last_num) { /* # beans has changed */ p->last_num = *p->num_beads; if ((int32)(*p->num_beads+FL(0.5)) != p->num_objects) { p->num_objects = (int32)(*p->num_beads+FL(0.5)); if (p->num_objects >= 1) { gain = p->gain = LOG((MYFLT)p->num_objects) / FL(1.38629436111989061883) /* (MYFLT)log(4.0)*/ * FL(40.0) / (MYFLT) p->num_objects; } } } if (*p->damp != FL(0.0)) { systemDecay = p->systemDecay = FL(0.998) + (*p->damp * FL(0.002)); } if (*p->shake_max != FL(0.0)) { shakeEnergy = p->shakeEnergy += CS_KSMPS * *p->shake_max * MAX_SHAKE * FL(0.1); if (shakeEnergy > MAX_SHAKE) shakeEnergy = MAX_SHAKE; } if (p->kloop>0 && p->h.insdshead->relesing) p->kloop=1; if ((--p->kloop) == 0) { shakeEnergy = FL(0.0); } if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;n MIN_ENERGY) { */ shakeEnergy *= systemDecay; /* Exponential system decay */ if (my_random(csound, 1024) < p->num_objects) { sndLevel += gain * shakeEnergy; } input = sndLevel * noise_tick(csound); /* Actual Sound is Random */ sndLevel *= soundDecay; /* Exponential Sound decay */ input -= outputs0*coeff0; /* Do */ input -= outputs1*coeff1; /* resonant */ outputs1 = outputs0; /* filter */ outputs0 = input; /* calculations */ data = outputs0 - outputs1; /* if (data > 10000.0f) data = 10000.0f; */ /* if (data < -10000.0f) data = -10000.0f; */ ar[n] = data * FL(0.0005) * csound->e0dbfs ; /* } */ /* else { */ /* *ar++ = 0.0f; */ /* } */ } p->shakeEnergy = shakeEnergy; p->sndLevel = sndLevel; p->outputs0 = outputs0; p->outputs1 = outputs1; return OK; } static int sekereset(CSOUND *csound, SEKERE *p) { p->sndLevel = FL(0.0); p->kloop = (int)(p->h.insdshead->offtim * CS_EKR) - (int)(CS_EKR * *p->dettack); p->outputs0 = FL(0.0); p->outputs1 = FL(0.0); p->finalZ2 = FL(0.0); p->finalZ1 = FL(0.0); p->finalZ0 = FL(0.0); p->shake_maxSave = FL(0.0); p->totalEnergy = FL(0.0); p->num_objects = SEKE_NUM_BEANS; p->soundDecay = SEKE_SOUND_DECAY; p->systemDecay = SEKE_SYSTEM_DECAY; p->gain = LOG(SEKE_NUM_BEANS)*SEKE_GAIN/SEKE_NUM_BEANS; p->resons = SEKE_RESON; p->coeffs1 = SEKE_RESON * SEKE_RESON; p->coeffs0 = - SEKE_RESON * FL(2.0) * COS(SEKE_CENTER_FREQ * csound->tpidsr); /* Note On */ p->shakeEnergy = *p->amp * MAX_SHAKE * FL(0.1); if (p->shakeEnergy > MAX_SHAKE) p->shakeEnergy = MAX_SHAKE; p->last_num = FL(0.0); return OK; } static int sekere(CSOUND *csound, SEKERE *p) { MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT data; /* Use locals for speed */ MYFLT shakeEnergy = p->shakeEnergy; MYFLT systemDecay = p->systemDecay; MYFLT sndLevel = p->sndLevel; MYFLT soundDecay = p->soundDecay; MYFLT input; MYFLT outputs0 = p->outputs0; MYFLT outputs1 = p->outputs1; MYFLT coeff0 = p->coeffs0; MYFLT coeff1 = p->coeffs1; MYFLT gain = p->gain; if (*p->num_beads != p->last_num) { p->last_num = *p->num_beads; if ((int32)(*p->num_beads+FL(0.5)) != p->num_objects) { p->num_objects = *p->num_beads; if (p->num_objects >= 1) { gain = p->gain = LOG((MYFLT)p->num_objects) / FL(1.38629436111989061883) /* (MYFLT)log(4.0)*/ * FL(120.0) / (MYFLT) p->num_objects; } } } if (*p->damp != FL(0.0)) { systemDecay = p->systemDecay = FL(0.998) + (*p->damp * FL(0.002)); } if (*p->shake_max != FL(0.0)) { shakeEnergy = p->shakeEnergy += CS_KSMPS * *p->shake_max * MAX_SHAKE * FL(0.1); if (shakeEnergy > MAX_SHAKE) shakeEnergy = MAX_SHAKE; } if (p->kloop>0 && p->h.insdshead->relesing) p->kloop=1; if ((--p->kloop) == 0) { shakeEnergy = FL(0.0); } if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;n MIN_ENERGY) { */ shakeEnergy *= systemDecay; /* Exponential system decay */ if (my_random(csound, 1024) < p->num_objects) { sndLevel += gain * shakeEnergy; } input = sndLevel * noise_tick(csound); /* Actual Sound is Random */ sndLevel *= soundDecay; /* Exponential Sound decay */ input -= outputs0*coeff0; /* Do */ input -= outputs1*coeff1; /* resonant */ outputs1 = outputs0; /* filter */ outputs0 = input; /* calculations */ p->finalZ2 = p->finalZ1; p->finalZ1 = p->finalZ0; p->finalZ0 = p->outputs1; data = p->finalZ0 - p->finalZ2; /* if (data > 10000.0f) data = 10000.0f; */ /* if (data < -10000.0f) data = -10000.0f; */ ar[n] = data * FL(0.0005) * csound->e0dbfs ; /* } */ /* else { */ /* ar[n] = 0.0f; */ /* } */ } //printf("%d/%d:\n", offset, early); p->shakeEnergy = shakeEnergy; p->sndLevel = sndLevel; p->outputs0 = outputs0; p->outputs1 = outputs1; return OK; } static int sandset(CSOUND *csound, SEKERE *p) { p->sndLevel = FL(0.0); p->kloop = (int)(p->h.insdshead->offtim * CS_EKR) - (int)(CS_EKR * *p->dettack); p->outputs0 = FL(0.0); p->outputs1 = FL(0.0); p->finalZ2 = FL(0.0); p->finalZ1 = FL(0.0); p->finalZ0 = FL(0.0); p->shake_maxSave = FL(0.0); p->totalEnergy = FL(0.0); p->num_objects = SANDPAPR_NUM_GRAINS; p->soundDecay = SANDPAPR_SOUND_DECAY; p->systemDecay = SANDPAPR_SYSTEM_DECAY; p->gain = LOG(SANDPAPR_NUM_GRAINS) * SANDPAPR_GAIN / SANDPAPR_NUM_GRAINS; p->resons = SANDPAPR_RESON; p->coeffs1 = SANDPAPR_RESON * SANDPAPR_RESON; p->coeffs0 = - SANDPAPR_RESON * FL(2.0) * COS(SANDPAPR_CENTER_FREQ * csound->tpidsr); /* Note On */ p->shakeEnergy = *p->amp * csound->dbfs_to_float * MAX_SHAKE * FL(0.1); if (p->shakeEnergy > MAX_SHAKE) p->shakeEnergy = MAX_SHAKE; p->last_num = FL(128.0); return OK; } static int stixset(CSOUND *csound, SEKERE *p) { p->sndLevel = FL(0.0); p->kloop = (int)(p->h.insdshead->offtim * CS_EKR) - (int)(CS_EKR * *p->dettack); p->outputs0 = FL(0.0); p->outputs1 = FL(0.0); p->finalZ2 = FL(0.0); p->finalZ1 = FL(0.0); p->finalZ0 = FL(0.0); p->shake_maxSave = FL(0.0); p->totalEnergy = FL(0.0); p->num_objects = STIX1_NUM_BEANS; p->soundDecay = STIX1_SOUND_DECAY; p->systemDecay = STIX1_SYSTEM_DECAY; p->gain = LOG(STIX1_NUM_BEANS) * STIX1_GAIN / STIX1_NUM_BEANS; p->resons = STIX1_RESON; p->coeffs1 = STIX1_RESON * STIX1_RESON; p->coeffs0 = - STIX1_RESON * FL(2.0) * COS(STIX1_CENTER_FREQ * csound->tpidsr); /* Note On */ p->shakeEnergy = *p->amp * csound->dbfs_to_float * MAX_SHAKE * FL(0.1); if (p->shakeEnergy > MAX_SHAKE) p->shakeEnergy = MAX_SHAKE; p->last_num = FL(30.0); return OK; } static int crunchset(CSOUND *csound, CABASA *p) { p->sndLevel = FL(0.0); p->kloop = (int)(p->h.insdshead->offtim * CS_EKR) - (int)(CS_EKR * *p->dettack); p->outputs0 = FL(0.0); p->outputs1 = FL(0.0); p->shake_maxSave = FL(0.0); p->totalEnergy = FL(0.0); p->num_objects = CRUNCH1_NUM_BEADS; p->soundDecay = CRUNCH1_SOUND_DECAY; p->systemDecay = CRUNCH1_SYSTEM_DECAY; p->gain = LOG((MYFLT)CRUNCH1_NUM_BEADS) * CRUNCH1_GAIN / (MYFLT) CRUNCH1_NUM_BEADS; p->resons = CRUNCH1_RESON; p->coeffs1 = CRUNCH1_RESON * CRUNCH1_RESON; p->coeffs0 = - CRUNCH1_RESON * FL(2.0) * COS(CRUNCH1_CENTER_FREQ * csound->tpidsr); /* Note On */ p->shakeEnergy = *p->amp * csound->dbfs_to_float * MAX_SHAKE * FL(0.1); if (p->shakeEnergy > MAX_SHAKE) p->shakeEnergy = MAX_SHAKE; p->last_num = FL(0.0); return OK; } static int guiroset(CSOUND *csound, GUIRO *p) { MYFLT temp; p->res_freqSave = FL(0.0); p->shake_maxSave = FL(0.0); p->res_freq2 = FL(0.0); p->baseGain = FL(0.0); p->sndLevel = FL(0.0); p->kloop = (int)(p->h.insdshead->offtim * CS_EKR) - (int)(CS_EKR * *p->dettack); p->outputs00 = FL(0.0); p->outputs01 = FL(0.0); p->outputs10 = FL(0.0); p->outputs11 = FL(0.0); p->totalEnergy = FL(0.0); p->ratchetDelta = FL(0.0005); p->finalZ0 = FL(0.0); p->finalZ1 = FL(0.0); p->finalZ2 = FL(0.0); p->num_objects = (MYFLT)GUIR_NUM_PARTS; p->soundDecay = GUIR_SOUND_DECAY; p->systemDecay = FL(1.0); temp = LOG((MYFLT)GUIR_NUM_PARTS) * GUIR_GAIN / (MYFLT) GUIR_NUM_PARTS; p->gains0=temp; p->gains1=temp; p->coeffs01 = GUIR_GOURD_RESON * GUIR_GOURD_RESON; p->coeffs00 = -GUIR_GOURD_RESON * FL(2.0) * COS(GUIR_GOURD_FREQ * csound->tpidsr); p->coeffs11 = GUIR_GOURD_RESON2 * GUIR_GOURD_RESON2; p->coeffs10 = -GUIR_GOURD_RESON2 * FL(2.0) * COS(GUIR_GOURD_FREQ2 * csound->tpidsr); p->ratchet = FL(0.0); p->ratchetPos = 10; /* Note On */ p->shakeEnergy = MAX_SHAKE * FL(0.1); p->shake_damp = FL(0.0); if (p->shakeEnergy > MAX_SHAKE) p->shakeEnergy = MAX_SHAKE; p->ratchetPos += 1; return OK; } static int guiro(CSOUND *csound, GUIRO *p) { MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT lastOutput; if (*p->num_teeth != FL(0.0) && (int32)(*p->num_teeth+FL(0.5)) != p->num_objects) { p->num_objects = *p->num_teeth; if (p->num_objects < FL(1.0)) p->num_objects = FL(1.0); p->gains0 = p->gains1 = LOG((MYFLT)p->num_objects) * GUIR_GAIN / (MYFLT) p->num_objects; } if (*p->damp != FL(0.0) && *p->damp != p->shake_damp) { p->shake_damp = *p->damp; /* p->systemDecay = TAMB_SYSTEM_DECAY + (p->shake_damp * FL(0.002)); */ /* p->scrapeVel = p->shake_damp; */ } if (*p->shake_max != FL(0.0) && *p->shake_max != p->shake_maxSave) { p->shake_maxSave = *p->shake_max; p->shakeEnergy += p->shake_maxSave * MAX_SHAKE * FL(0.1); if (p->shakeEnergy > MAX_SHAKE) p->shakeEnergy = MAX_SHAKE; } if (*p->freq != FL(0.0) && *p->freq != p->res_freqSave) { p->res_freqSave = *p->freq; p->coeffs00 = -GUIR_GOURD_RESON * FL(2.0) * COS(p->res_freqSave * csound->tpidsr); } if (*p->freq2 != p->res_freq2) { p->res_freq2 = *p->freq2; p->coeffs10 = -GUIR_GOURD_RESON2 * FL(2.0) * COS(p->res_freq2 * csound->tpidsr); } if (p->kloop>0 && p->h.insdshead->relesing) p->kloop=1; if ((--p->kloop) == 0) { p->shakeEnergy = FL(0.0); p->ratchetPos = 0; } { MYFLT sndLevel = p->sndLevel; MYFLT ratchet = p->ratchet; int ratchetPos = p->ratchetPos; MYFLT totalEnergy = p->totalEnergy; MYFLT num_objects = p->num_objects; MYFLT soundDecay = p->soundDecay; MYFLT ratchetDelta = p->ratchetDelta; MYFLT inputs0, inputs1; MYFLT outputs00 = p->outputs00; MYFLT outputs01 = p->outputs01; MYFLT outputs10 = p->outputs10; MYFLT outputs11 = p->outputs11; MYFLT coeffs00 = p->coeffs00; MYFLT coeffs01 = p->coeffs01; MYFLT coeffs10 = p->coeffs10; MYFLT coeffs11 = p->coeffs11; MYFLT finalZ0 = p->finalZ0; MYFLT finalZ1 = p->finalZ1; MYFLT finalZ2 = p->finalZ2; MYFLT gains0 = p->gains0; MYFLT gains1 = p->gains1; MYFLT amp = *p->amp*csound->e0dbfs; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;n 0) { ratchet -= (ratchetDelta + (FL(0.002)*totalEnergy)); if (ratchet < FL(0.0)) { ratchet = FL(1.0); ratchetPos -= 1; } totalEnergy = ratchet; if (my_random(csound, 1024) < num_objects) { sndLevel += FL(512.0) * ratchet * totalEnergy; } inputs0 = sndLevel; inputs0 *= noise_tick(csound) * ratchet; sndLevel *= soundDecay; inputs1 = inputs0; inputs0 -= outputs00*coeffs00; inputs0 -= outputs01*coeffs01; outputs01 = outputs00; outputs00 = inputs0; inputs1 -= outputs10*coeffs10; inputs1 -= outputs11*coeffs11; outputs11 = outputs10; outputs10 = inputs1; finalZ2 = finalZ1; finalZ1 = finalZ0; finalZ0 = gains0*outputs01 + gains1*outputs11; lastOutput = finalZ0 - finalZ2; lastOutput *= FL(0.0001); } else lastOutput = FL(0.0); ar[n] = FL(1.33)*lastOutput*amp; } p->sndLevel = sndLevel; p->ratchet = ratchet; p->ratchetPos = ratchetPos; p->totalEnergy = totalEnergy; p->outputs00 = outputs00; p->outputs01 = outputs01; p->outputs10 = outputs10; p->outputs11 = outputs11; p->finalZ0 = finalZ0; p->finalZ1 = finalZ1; p->finalZ2 = finalZ2; } return OK; } static int tambourset(CSOUND *csound, TAMBOURINE *p) { MYFLT temp; p->shake_maxSave = FL(0.0); p->sndLevel = FL(0.0); p->kloop = (int)(p->h.insdshead->offtim * CS_EKR) - (int)(CS_EKR * *p->dettack); p->outputs00 = FL(0.0); p->outputs01 = FL(0.0); p->outputs10 = FL(0.0); p->outputs11 = FL(0.0); p->outputs20 = FL(0.0); p->outputs21 = FL(0.0); p->totalEnergy = FL(0.0); p->finalZ0 = FL(0.0); p->finalZ1 = FL(0.0); p->finalZ2 = FL(0.0); p->num_objectsSave = p->num_objects = (MYFLT)TAMB_NUM_TIMBRELS; p->soundDecay = TAMB_SOUND_DECAY; p->systemDecay = TAMB_SYSTEM_DECAY; p->gain = FL(24.0) / TAMB_NUM_TIMBRELS; p->res_freq1 = TAMB_CYMB_FREQ1; p->res_freq2 = TAMB_CYMB_FREQ2; temp = LOG((MYFLT)TAMB_NUM_TIMBRELS) * TAMB_GAIN / (MYFLT) TAMB_NUM_TIMBRELS; p->gains0 = temp*TAMB_SHELL_GAIN; p->gains1 = temp*FL(0.8); p->gains2 = temp; p->coeffs01 = TAMB_SHELL_RESON * TAMB_SHELL_RESON; p->coeffs00 = -TAMB_SHELL_RESON * FL(2.0) * COS(TAMB_SHELL_FREQ * csound->tpidsr); p->coeffs11 = TAMB_CYMB_RESON * TAMB_CYMB_RESON; p->coeffs10 = -TAMB_CYMB_RESON * FL(2.0) * COS(TAMB_CYMB_FREQ1 * csound->tpidsr); p->coeffs21 = TAMB_CYMB_RESON * TAMB_CYMB_RESON; p->coeffs20 = -TAMB_CYMB_RESON * FL(2.0) * COS(TAMB_CYMB_FREQ2 * csound->tpidsr); /* Note On */ p->shakeEnergy = *p->amp * csound->dbfs_to_float * MAX_SHAKE * FL(0.1); p->shake_damp = FL(0.0); if (p->shakeEnergy > MAX_SHAKE) p->shakeEnergy = MAX_SHAKE; return OK; } static int tambourine(CSOUND *csound, TAMBOURINE *p) { MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT data; MYFLT temp_rand; MYFLT lastOutput; if (*p->num_timbrels != FL(0.0) && *p->num_timbrels != p->num_objects) { p->num_objects = *p->num_timbrels; if (p->num_objects < FL(1.0)) p->num_objects = FL(1.0); p->gain = FL(24.0) / p->num_objects; } if (*p->freq != FL(0.0) && *p->freq != p->res_freq) { p->res_freq = *p->freq; p->coeffs00 = -TAMB_SHELL_RESON * FL(2.0) * COS(p->res_freq * csound->tpidsr); } if (*p->damp != FL(0.0) && *p->damp != p->shake_damp) { p->shake_damp = *p->damp; p->systemDecay = TAMB_SYSTEM_DECAY + (p->shake_damp * FL(0.002)); } if (*p->shake_max != FL(0.0) && *p->shake_max != p->shake_maxSave) { p->shake_maxSave = *p->shake_max; p->shakeEnergy += p->shake_maxSave * MAX_SHAKE * FL(0.1); if (p->shakeEnergy > MAX_SHAKE) p->shakeEnergy = MAX_SHAKE; } if (*p->freq1 != FL(0.0) && *p->freq1 != p->res_freq1) { p->res_freq1 = *p->freq1; p->coeffs10 = -TAMB_CYMB_RESON * FL(2.0) * COS(p->res_freq1 * csound->tpidsr); } if (*p->freq2 != FL(0.0) && *p->freq2 != p->res_freq2) { p->res_freq2 = *p->freq2; p->coeffs20 = -TAMB_CYMB_RESON * FL(2.0) * COS(p->res_freq2 * csound->tpidsr); } if (p->kloop>0 && p->h.insdshead->relesing) p->kloop=1; if ((--p->kloop) == 0) { p->shakeEnergy = FL(0.0); } { MYFLT shakeEnergy = p->shakeEnergy; MYFLT systemDecay = p->systemDecay; MYFLT sndLevel = p->sndLevel; MYFLT soundDecay = p->soundDecay; MYFLT inputs0, inputs1, inputs2; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;nnum_objects) { sndLevel += p->gain * shakeEnergy; temp_rand = p->res_freq1 * (FL(1.0) + (FL(0.05)*noise_tick(csound))); p->coeffs10 = -TAMB_CYMB_RESON * FL(2.0) * COS(temp_rand * csound->tpidsr); temp_rand = p->res_freq2 * (FL(1.0) + (FL(0.05)*noise_tick(csound))); p->coeffs20 = -TAMB_CYMB_RESON * FL(2.0) * COS(temp_rand * csound->tpidsr); } inputs0 = sndLevel * noise_tick(csound); /* Actual Sound is Random */ inputs1 = inputs0; inputs2 = inputs0; sndLevel *= soundDecay; /* Exponential Sound decay */ p->finalZ2 = p->finalZ1; p->finalZ1 = p->finalZ0; p->finalZ0 = FL(0.0); inputs0 -= p->outputs00*p->coeffs00; /* Do */ inputs0 -= p->outputs01*p->coeffs01; /* resonant */ p->outputs01 = p->outputs00; /* filter */ p->outputs00 = inputs0; /* calculations */ p->finalZ0 += p->gains0 * p->outputs01; inputs1 -= p->outputs10*p->coeffs10; /* Do */ inputs1 -= p->outputs11*p->coeffs11; /* resonant */ p->outputs11 = p->outputs10; /* filter */ p->outputs10 = inputs1; /* calculations */ p->finalZ0 += p->gains1 * p->outputs11; inputs2 -= p->outputs20*p->coeffs20; /* Do */ inputs2 -= p->outputs21*p->coeffs21; /* resonant */ p->outputs21 = p->outputs20; /* filter */ p->outputs20 = inputs2; /* calculations */ p->finalZ0 += p->gains2 * p->outputs21; data = p->finalZ0 - p->finalZ2; /* Extra zero(s) for shape */ lastOutput = data * FL(0.0009); ar[n] = lastOutput*csound->e0dbfs; } p->shakeEnergy = shakeEnergy; p->sndLevel = sndLevel; } return OK; } static int bambooset(CSOUND *csound, BAMBOO *p) { MYFLT temp; p->shake_maxSave = FL(0.0); p->sndLevel = FL(0.0); p->kloop = (int)(p->h.insdshead->offtim * CS_EKR) - (int)(CS_EKR * *p->dettack); p->outputs00 = FL(0.0); p->outputs01 = FL(0.0); p->outputs10 = FL(0.0); p->outputs11 = FL(0.0); p->outputs20 = FL(0.0); p->outputs21 = FL(0.0); p->totalEnergy = FL(0.0); p->res_freq0 = BAMB_CENTER_FREQ0; p->res_freq1 = BAMB_CENTER_FREQ1; p->res_freq2 = BAMB_CENTER_FREQ2; p->num_objectsSave = p->num_objects = BAMB_NUM_TUBES; p->soundDecay = BAMB_SOUND_DECAY; p->systemDecay = BAMB_SYSTEM_DECAY; temp = LOG((MYFLT)BAMB_NUM_TUBES) * BAMB_GAIN / (MYFLT) BAMB_NUM_TUBES; p->gain = temp; p->coeffs01 = BAMB_RESON * BAMB_RESON; p->coeffs00 = -BAMB_RESON * FL(2.0) * COS(BAMB_CENTER_FREQ0 * csound->tpidsr); p->coeffs11 = BAMB_RESON * BAMB_RESON; p->coeffs10 = -BAMB_RESON * FL(2.0) * COS(BAMB_CENTER_FREQ1 * csound->tpidsr); p->coeffs21 = BAMB_RESON * BAMB_RESON; p->coeffs20 = -BAMB_RESON * FL(2.0) * COS(BAMB_CENTER_FREQ2 * csound->tpidsr); /* Note On */ p->shakeEnergy = *p->amp * csound->dbfs_to_float * MAX_SHAKE * FL(0.1); p->shake_damp = FL(0.0); if (p->shakeEnergy > MAX_SHAKE) p->shakeEnergy = MAX_SHAKE; return OK; } static int bamboo(CSOUND *csound, BAMBOO *p) { MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT data; MYFLT temp_rand; MYFLT lastOutput; if (*p->num_tubes != FL(0.0) && *p->num_tubes != p->num_objects) { p->num_objects = *p->num_tubes; if (p->num_objects < FL(1.0)) p->num_objects = FL(1.0); } if (*p->freq != FL(0.0) && *p->freq != p->res_freq0) { p->res_freq0 = *p->freq; p->coeffs00 = -BAMB_RESON * FL(2.0) * COS(p->res_freq0 * csound->tpidsr); } if (*p->damp != FL(0.0) && *p->damp != p->shake_damp) { p->shake_damp = *p->damp; p->systemDecay = BAMB_SYSTEM_DECAY + (p->shake_damp * FL(0.002)); } if (*p->shake_max != FL(0.0) && *p->shake_max != p->shake_maxSave) { p->shake_maxSave = *p->shake_max; p->shakeEnergy += p->shake_maxSave * MAX_SHAKE * FL(0.1); if (p->shakeEnergy > MAX_SHAKE) p->shakeEnergy = MAX_SHAKE; } if (*p->freq1 != FL(0.0) && *p->freq1 != p->res_freq1) { p->res_freq1 = *p->freq1; p->coeffs10 = -BAMB_RESON * FL(2.0) * COS(p->res_freq1 * csound->tpidsr); } if (*p->freq2 != FL(0.0) && *p->freq2 != p->res_freq2) { p->res_freq2 = *p->freq2; p->coeffs20 = -BAMB_RESON * FL(2.0) * COS(p->res_freq2 * csound->tpidsr); } if (p->kloop>0 && p->h.insdshead->relesing) p->kloop=1; if ((--p->kloop) == 0) { p->shakeEnergy = FL(0.0); } { MYFLT shakeEnergy = p->shakeEnergy; MYFLT systemDecay = p->systemDecay; MYFLT sndLevel = p->sndLevel; MYFLT soundDecay = p->soundDecay; MYFLT inputs0, inputs1, inputs2; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;nnum_objects) { sndLevel += shakeEnergy; temp_rand = p->res_freq0 * (FL(1.0) + (FL(0.2) * noise_tick(csound))); p->coeffs00 = -BAMB_RESON * FL(2.0) * COS(temp_rand * csound->tpidsr); temp_rand = p->res_freq1 * (FL(1.0) + (FL(0.2) * noise_tick(csound))); p->coeffs10 = -BAMB_RESON * FL(2.0) * COS(temp_rand * csound->tpidsr); temp_rand = p->res_freq2 * (FL(1.0) + (FL(0.2) * noise_tick(csound))); p->coeffs20 = -BAMB_RESON * FL(2.0) * COS(temp_rand * csound->tpidsr); } inputs0 = sndLevel * noise_tick(csound); /* Actual Sound is Random */ inputs1 = inputs0; inputs2 = inputs0; sndLevel *= soundDecay; /* Exponential Sound decay */ inputs0 -= p->outputs00*p->coeffs00; /* Do */ inputs0 -= p->outputs01*p->coeffs01; /* resonant */ p->outputs01 = p->outputs00; /* filter */ p->outputs00 = inputs0; /* calculations */ data = p->gain * p->outputs01; inputs1 -= p->outputs10*p->coeffs10; /* Do */ inputs1 -= p->outputs11*p->coeffs11; /* resonant */ p->outputs11 = p->outputs10; /* filter */ p->outputs10 = inputs1; /* calculations */ data += p->gain * p->outputs11; inputs2 -= p->outputs20*p->coeffs20; /* Do */ inputs2 -= p->outputs21*p->coeffs21; /* resonant */ p->outputs21 = p->outputs20; /* filter */ p->outputs20 = inputs2; /* calculations */ data += p->gain * p->outputs21; /* if (data > 10000.0f) data = 10000.0f; */ /* if (data < -10000.0f) data = -10000.0f; */ lastOutput = data * FL(0.00051); ar[n] = lastOutput*csound->e0dbfs; } p->shakeEnergy = shakeEnergy; p->sndLevel = sndLevel; } return OK; } static int wuterset(CSOUND *csound, WUTER *p) { MYFLT temp; p->sndLevel = FL(0.0); p->kloop = (int)(p->h.insdshead->offtim * CS_EKR) - (int)(CS_EKR * *p->dettack); p->outputs00 = FL(0.0); p->outputs01 = FL(0.0); p->outputs10 = FL(0.0); p->outputs11 = FL(0.0); p->outputs20 = FL(0.0); p->outputs21 = FL(0.0); p->totalEnergy = FL(0.0); p->center_freqs0 = p->res_freq0 = WUTR_CENTER_FREQ0; p->center_freqs1 = p->res_freq1 = WUTR_CENTER_FREQ1; p->center_freqs2 = p->res_freq2 = WUTR_CENTER_FREQ2; p->num_objectsSave = p->num_objects = WUTR_NUM_SOURCES; p->soundDecay = WUTR_SOUND_DECAY; p->systemDecay = WUTR_SYSTEM_DECAY; temp = LOG(WUTR_NUM_SOURCES) * WUTR_GAIN / WUTR_NUM_SOURCES; p->gains0 = p->gains1 = p->gains2 = temp; p->coeffs01 = WUTR_RESON * WUTR_RESON; p->coeffs00 = -WUTR_RESON * FL(2.0) * COS(WUTR_CENTER_FREQ0 * csound->tpidsr); p->coeffs11 = WUTR_RESON * WUTR_RESON; p->coeffs10 = -WUTR_RESON * FL(2.0) * COS(WUTR_CENTER_FREQ1 * csound->tpidsr); p->coeffs21 = WUTR_RESON * WUTR_RESON; p->coeffs20 = -WUTR_RESON * FL(2.0) * COS(WUTR_CENTER_FREQ2 * csound->tpidsr); /* Note On */ p->shakeEnergy = *p->amp * csound->dbfs_to_float * MAX_SHAKE * FL(0.1); p->shake_damp = FL(0.0); if (p->shakeEnergy > MAX_SHAKE) p->shakeEnergy = MAX_SHAKE; p->shake_maxSave = FL(0.0); p->num_objects = 10; /* Bug fix by JPff 2014/08/27 */ p->finalZ0 = p->finalZ1 = p->finalZ2 = FL(0.0); return OK; } static int wuter(CSOUND *csound, WUTER *p) { MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT data; MYFLT lastOutput; if (*p->num_tubes != FL(0.0) && *p->num_tubes != p->num_objects) { p->num_objects = *p->num_tubes; if (p->num_objects < FL(1.0)) p->num_objects = FL(1.0); } if (*p->freq != FL(0.0) && *p->freq != p->res_freq0) { p->res_freq0 = *p->freq; p->coeffs00 = -WUTR_RESON * FL(2.0) * COS(p->res_freq0 * csound->tpidsr); } if (*p->damp != FL(0.0) && *p->damp != p->shake_damp) { p->shake_damp = *p->damp; p->systemDecay = WUTR_SYSTEM_DECAY + (p->shake_damp * FL(0.002)); } if (*p->shake_max != FL(0.0) && *p->shake_max != p->shake_maxSave) { p->shake_maxSave = *p->shake_max; p->shakeEnergy += p->shake_maxSave * MAX_SHAKE * FL(0.1); if (p->shakeEnergy > MAX_SHAKE) p->shakeEnergy = MAX_SHAKE; } if (*p->freq1 != FL(0.0) && *p->freq1 != p->res_freq1) { p->res_freq1 = *p->freq1; p->coeffs10 = -WUTR_RESON * FL(2.0) * COS(p->res_freq1 * csound->tpidsr); } if (*p->freq2 != FL(0.0) && *p->freq2 != p->res_freq2) { p->res_freq2 = *p->freq2; p->coeffs20 = -WUTR_RESON * FL(2.0) * COS(p->res_freq2 * csound->tpidsr); } //if (p->kloop>0 && p->h.insdshead->relesing) p->kloop=1; if ((--p->kloop) == 0) { p->shakeEnergy = FL(0.0); } { MYFLT shakeEnergy = p->shakeEnergy; MYFLT systemDecay = p->systemDecay; MYFLT sndLevel = p->sndLevel; MYFLT num_objects = p->num_objects; MYFLT soundDecay = p->soundDecay; MYFLT inputs0, inputs1, inputs2; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;ncenter_freqs0 = p->res_freq1 * (FL(0.75) + (FL(0.25) * noise_tick(csound))); p->gains0 = FABS(noise_tick(csound)); } else if (j == 1) { p->center_freqs1 = p->res_freq1 * (FL(1.0) + (FL(0.25) * noise_tick(csound))); p->gains1 = FABS(noise_tick(csound)); } else { p->center_freqs2 = p->res_freq1 * (FL(1.25) + (FL(0.25) * noise_tick(csound))); p->gains2 = FABS(noise_tick(csound)); } } p->gains0 *= WUTR_RESON; if (p->gains0 > FL(0.001)) { p->center_freqs0 *= WUTR_FREQ_SWEEP; p->coeffs00 = -WUTR_RESON * FL(2.0) * COS(p->center_freqs0 * csound->tpidsr); } p->gains1 *= WUTR_RESON; if (p->gains1 > FL(0.001)) { p->center_freqs1 *= WUTR_FREQ_SWEEP; p->coeffs10 = -WUTR_RESON * FL(2.0) * COS(p->center_freqs1 * csound->tpidsr); } p->gains2 *= WUTR_RESON; if (p->gains2 > FL(0.001)) { p->center_freqs2 *= WUTR_FREQ_SWEEP; p->coeffs20 = -WUTR_RESON * FL(2.0) * COS(p->center_freqs2 * csound->tpidsr); } sndLevel *= soundDecay; /* Each (all) event(s) */ /* decay(s) exponentially */ inputs0 = sndLevel; inputs0 *= noise_tick(csound); /* Actual Sound is Random */ inputs1 = inputs0 * p->gains1; inputs2 = inputs0 * p->gains2; inputs0 *= p->gains0; inputs0 -= p->outputs00*p->coeffs00; inputs0 -= p->outputs01*p->coeffs01; p->outputs01 = p->outputs00; p->outputs00 = inputs0; data = p->gains0*p->outputs00; inputs1 -= p->outputs10*p->coeffs10; inputs1 -= p->outputs11*p->coeffs11; p->outputs11 = p->outputs10; p->outputs10 = inputs1; data += p->gains1*p->outputs10; inputs2 -= p->outputs20*p->coeffs20; inputs2 -= p->outputs21*p->coeffs21; p->outputs21 = p->outputs20; p->outputs20 = inputs2; data += p->gains2*p->outputs20; p->finalZ2 = p->finalZ1; p->finalZ1 = p->finalZ0; p->finalZ0 = data * FL(4.0); lastOutput = p->finalZ2 - p->finalZ0; lastOutput *= FL(0.005); ar[n] = lastOutput*csound->e0dbfs; } p->shakeEnergy = shakeEnergy; p->sndLevel = sndLevel; } return OK; } static int sleighset(CSOUND *csound, SLEIGHBELLS *p) { MYFLT temp; p->shake_maxSave = FL(0.0); p->sndLevel = FL(0.0); p->kloop = (int)(p->h.insdshead->offtim * CS_EKR) - (int)(CS_EKR * *p->dettack); p->outputs00 = FL(0.0); p->outputs01 = FL(0.0); p->outputs10 = FL(0.0); p->outputs11 = FL(0.0); p->outputs20 = FL(0.0); p->outputs21 = FL(0.0); p->outputs30 = FL(0.0); p->outputs31 = FL(0.0); p->outputs40 = FL(0.0); p->outputs41 = FL(0.0); p->totalEnergy = FL(0.0); p->res_freq0 = SLEI_CYMB_FREQ0; p->res_freq1 = SLEI_CYMB_FREQ1; p->res_freq2 = SLEI_CYMB_FREQ2; p->res_freq3 = SLEI_CYMB_FREQ3; p->res_freq4 = SLEI_CYMB_FREQ4; p->num_objectsSave = p->num_objects = (MYFLT)SLEI_NUM_BELLS; p->soundDecay = SLEI_SOUND_DECAY; p->systemDecay = SLEI_SYSTEM_DECAY; temp = LOG((MYFLT)SLEI_NUM_BELLS)/(MYFLT)SLEI_NUM_BELLS; p->gain = temp; p->coeffs01 = SLEI_CYMB_RESON * SLEI_CYMB_RESON; p->coeffs00 = -SLEI_CYMB_RESON * FL(2.0) * COS(SLEI_CYMB_FREQ0 * csound->tpidsr); p->coeffs11 = SLEI_CYMB_RESON * SLEI_CYMB_RESON; p->coeffs10 = -SLEI_CYMB_RESON * FL(2.0) * COS(SLEI_CYMB_FREQ1 * csound->tpidsr); p->coeffs21 = SLEI_CYMB_RESON * SLEI_CYMB_RESON; p->coeffs20 = -SLEI_CYMB_RESON * FL(2.0) * COS(SLEI_CYMB_FREQ2 * csound->tpidsr); p->coeffs31 = SLEI_CYMB_RESON * SLEI_CYMB_RESON; p->coeffs30 = -SLEI_CYMB_RESON * FL(2.0) * COS(SLEI_CYMB_FREQ3 * csound->tpidsr); p->coeffs41 = SLEI_CYMB_RESON * SLEI_CYMB_RESON; p->coeffs40 = -SLEI_CYMB_RESON * FL(2.0) * COS(SLEI_CYMB_FREQ4 * csound->tpidsr); /* Note On */ p->shakeEnergy = *p->amp * csound->dbfs_to_float * MAX_SHAKE * FL(0.1); p->shake_damp = FL(0.0); if (p->shakeEnergy > MAX_SHAKE) p->shakeEnergy = MAX_SHAKE; return OK; } static int sleighbells(CSOUND *csound, SLEIGHBELLS *p) { MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT data; MYFLT temp_rand; MYFLT lastOutput; if (*p->num_bells != FL(0.0) && *p->num_bells != p->num_objects) { p->num_objects = *p->num_bells; if (p->num_objects < FL(1.0)) p->num_objects = FL(1.0); } if (*p->freq != FL(0.0) && *p->freq != p->res_freq0) { p->res_freq0 = *p->freq; p->coeffs00 = -SLEI_CYMB_RESON * FL(2.0) * COS(p->res_freq0 * csound->tpidsr); } if (*p->damp != FL(0.0) && *p->damp != p->shake_damp) { p->shake_damp = *p->damp; p->systemDecay = SLEI_SYSTEM_DECAY + (p->shake_damp * FL(0.002)); } if (*p->shake_max != FL(0.0) && *p->shake_max != p->shake_maxSave) { p->shake_maxSave = *p->shake_max; p->shakeEnergy += p->shake_maxSave * MAX_SHAKE * FL(0.1); if (p->shakeEnergy > MAX_SHAKE) p->shakeEnergy = MAX_SHAKE; } if (*p->freq1 != FL(0.0) && *p->freq1 != p->res_freq1) { p->res_freq1 = *p->freq1; p->coeffs10 = -SLEI_CYMB_RESON * FL(2.0) * COS(p->res_freq1 * csound->tpidsr); } if (*p->freq2 != FL(0.0) && *p->freq2 != p->res_freq2) { p->res_freq2 = *p->freq2; p->coeffs20 = -SLEI_CYMB_RESON * FL(2.0) * COS(p->res_freq2 * csound->tpidsr); } if (p->kloop>0 && p->h.insdshead->relesing) p->kloop=1; if ((--p->kloop) == 0) { p->shakeEnergy = FL(0.0); } { MYFLT shakeEnergy = p->shakeEnergy; MYFLT systemDecay = p->systemDecay; MYFLT sndLevel = p->sndLevel; MYFLT soundDecay = p->soundDecay; MYFLT inputs0, inputs1, inputs2, inputs3, inputs4; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;nnum_objects) { sndLevel += p->gain * shakeEnergy; temp_rand = p->res_freq0 * (FL(1.0) + (FL(0.03)*noise_tick(csound))); p->coeffs00 = -SLEI_CYMB_RESON * FL(2.0) * COS(temp_rand * csound->tpidsr); temp_rand = p->res_freq1 * (FL(1.0) + (FL(0.03)*noise_tick(csound))); p->coeffs10 = -SLEI_CYMB_RESON * FL(2.0) * COS(temp_rand * csound->tpidsr); temp_rand = p->res_freq2 * (FL(1.0) + (FL(0.03)*noise_tick(csound))); p->coeffs20 = -SLEI_CYMB_RESON * FL(2.0) * COS(temp_rand * csound->tpidsr); temp_rand = p->res_freq3 * (FL(1.0) + (FL(0.03)*noise_tick(csound))); p->coeffs30 = -SLEI_CYMB_RESON * FL(2.0) * COS(temp_rand * csound->tpidsr); temp_rand = p->res_freq4 * (FL(1.0) + (FL(0.03)*noise_tick(csound))); p->coeffs40 = -SLEI_CYMB_RESON * FL(2.0) * COS(temp_rand * csound->tpidsr); } inputs0 = sndLevel * noise_tick(csound); /* Actual Sound is Random */ inputs1 = inputs0; inputs2 = inputs0; inputs3 = inputs0 * FL(0.5); inputs4 = inputs0 * FL(0.3); sndLevel *= soundDecay; /* ExponentialSound decay */ inputs0 -= p->outputs00*p->coeffs00; /* Do */ inputs0 -= p->outputs01*p->coeffs01; /* resonant */ p->outputs01 = p->outputs00; /* filter */ p->outputs00 = inputs0; /* calculations */ data = p->outputs01; inputs1 -= p->outputs10*p->coeffs10; /* Do */ inputs1 -= p->outputs11*p->coeffs11; /* resonant */ p->outputs11 = p->outputs10; /* filter */ p->outputs10 = inputs1; /* calculations */ data += p->outputs11; inputs2 -= p->outputs20*p->coeffs20; /* Do */ inputs2 -= p->outputs21*p->coeffs21; /* resonant */ p->outputs21 = p->outputs20; /* filter */ p->outputs20 = inputs2; /* calculations */ data += p->outputs21; inputs3 -= p->outputs30*p->coeffs30; /* Do */ inputs3 -= p->outputs31*p->coeffs31; /* resonant */ p->outputs31 = p->outputs30; /* filter */ p->outputs30 = inputs3; /* calculations */ data += p->outputs31; inputs4 -= p->outputs40*p->coeffs40; /* Do */ inputs4 -= p->outputs41*p->coeffs41; /* resonant */ p->outputs41 = p->outputs40; /* filter */ p->outputs40 = inputs4; /* calculations */ data += p->outputs41; p->finalZ2 = p->finalZ1; p->finalZ1 = p->finalZ0; p->finalZ0 = data; data = p->finalZ2 - p->finalZ0; lastOutput = data * FL(0.001); ar[n] = lastOutput*csound->e0dbfs; } p->shakeEnergy = shakeEnergy; p->sndLevel = sndLevel; } return OK; } #define S(x) sizeof(x) static OENTRY phisem_localops[] = { { "cabasa", S(CABASA), 0, 5, "a", "iiooo", (SUBR)cabasaset, NULL, (SUBR)cabasa}, { "crunch", S(CABASA), 0, 5, "a", "iiooo", (SUBR)crunchset, NULL, (SUBR)cabasa}, { "sekere", S(SEKERE), 0, 5, "a", "iiooo", (SUBR)sekereset, NULL, (SUBR)sekere}, { "sandpaper", S(SEKERE),0, 5, "a", "iiooo", (SUBR)sandset, NULL, (SUBR)sekere}, { "stix", S(SEKERE), 0, 5, "a", "iiooo", (SUBR)stixset, NULL, (SUBR)sekere}, { "guiro", S(GUIRO), 0, 5, "a", "kiooooo",(SUBR)guiroset, NULL, (SUBR)guiro }, { "tambourine", S(TAMBOURINE),0, 5,"a", "kioooooo", (SUBR)tambourset, NULL, (SUBR)tambourine}, { "bamboo", S(BAMBOO), 0, 5, "a", "kioooooo", (SUBR)bambooset, NULL, (SUBR)bamboo }, { "dripwater", S(WUTER), 0, 5, "a", "kioooooo", (SUBR)wuterset, NULL, (SUBR)wuter }, { "sleighbells", S(SLEIGHBELLS), 0, 5, "a","kioooooo", (SUBR)sleighset, NULL, (SUBR)sleighbells } }; LINKAGE_BUILTIN(phisem_localops) csound-6.10.0/Opcodes/phisem.h000066400000000000000000000231601321653344700161350ustar00rootroot00000000000000/* phisem.h: Copyright (C) 1997, 2000 Perry Cook, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /**********************************************************/ /* PhISEM (Physically Informed Stochastic Event Modeling */ /* by Perry R. Cook, Princeton, February 1997 */ /* */ /* Meta-model that simulates all of: */ /* Maraca Simulation by Perry R. Cook, Princeton, 1996-7 */ /* Sekere Simulation by Perry R. Cook, Princeton, 1996-7 */ /* Cabasa Simulation by Perry R. Cook, Princeton, 1996-7 */ /* Bamboo Windchime Simulation, by Perry R. Cook, 1996-7 */ /* Water Drops Simulation, by Perry R. Cook, 1996-7 */ /* Tambourine Simulation, by Perry R. Cook, 1996-7 */ /* Sleighbells Simulation, by Perry R. Cook, 1996-7 */ /* Guiro Simulation, by Perry R. Cook, 1996-7 */ /* */ /**********************************************************/ /* PhOLIES (Physically-Oriented Library of */ /* Imitated Environmental Sounds), Perry Cook, 1997-9 */ /* Stix1 (walking on brittle sticks) */ /* Crunch1 (like new fallen snow, or not) */ /* Wrench (basic socket wrench, friend of guiro) */ /* Sandpapr (sandpaper) */ /**********************************************************/ #if !defined(__Phisem_h) #define __Phisem_h typedef struct Cabasa { OPDS h; MYFLT *ar; /* Output */ MYFLT *amp; /* How loud */ MYFLT *dettack; /* When to switch off */ MYFLT *num_beads; /* Number of beads */ MYFLT *damp; MYFLT *shake_max; MYFLT shake_maxSave; MYFLT shakeEnergy; MYFLT outputs0; MYFLT outputs1; MYFLT coeffs0; MYFLT coeffs1; MYFLT sndLevel; MYFLT gain; MYFLT resons; MYFLT soundDecay; MYFLT systemDecay; int32 num_objects; MYFLT last_num; MYFLT totalEnergy; int kloop; } CABASA; typedef struct Sekere { OPDS h; MYFLT *ar; /* Output */ MYFLT *amp; /* How loud */ MYFLT *dettack; /* How loud */ MYFLT *num_beads; /* Number of beads */ MYFLT *damp; MYFLT *shake_max; MYFLT shake_maxSave; MYFLT shakeEnergy; MYFLT outputs0; MYFLT outputs1; MYFLT coeffs0; MYFLT coeffs1; MYFLT sndLevel; MYFLT gain; MYFLT resons; MYFLT soundDecay; MYFLT systemDecay; MYFLT num_objects; MYFLT last_num; MYFLT totalEnergy; MYFLT finalZ0; MYFLT finalZ1; MYFLT finalZ2; int kloop; } SEKERE; typedef struct Guiro { OPDS h; MYFLT *ar; /* Output */ MYFLT *amp; MYFLT *dettack; MYFLT *num_teeth; MYFLT *damp; MYFLT *shake_max; MYFLT *freq; MYFLT *freq2; MYFLT res_freqSave; MYFLT shake_damp; MYFLT shake_maxSave; MYFLT res_freq2; MYFLT shakeEnergy; MYFLT outputs00; MYFLT outputs01; MYFLT outputs10; MYFLT outputs11; MYFLT coeffs00; MYFLT coeffs01; MYFLT coeffs10; MYFLT coeffs11; MYFLT sndLevel; MYFLT baseGain; MYFLT gains0; MYFLT gains1; MYFLT soundDecay; MYFLT systemDecay; MYFLT num_objects; MYFLT totalEnergy; MYFLT ratchet,ratchetDelta; int ratchetPos; MYFLT finalZ0; MYFLT finalZ1; MYFLT finalZ2; MYFLT decayScale; int kloop; } GUIRO; typedef struct Tambour { OPDS h; MYFLT *ar; /* Output */ MYFLT *amp; /* How loud */ MYFLT *dettack; /* How loud */ MYFLT *num_timbrels; MYFLT *damp; MYFLT *shake_max; MYFLT *freq; MYFLT *freq1; MYFLT *freq2; MYFLT num_objectsSave; MYFLT shake_maxSave; MYFLT shakeEnergy; MYFLT outputs00; MYFLT outputs01; MYFLT outputs10; MYFLT outputs11; MYFLT outputs20; MYFLT outputs21; MYFLT coeffs00; MYFLT coeffs01; MYFLT coeffs10; MYFLT coeffs11; MYFLT coeffs20; MYFLT coeffs21; MYFLT sndLevel; MYFLT gain; MYFLT gains0; MYFLT gains1; MYFLT gains2; MYFLT resons; MYFLT soundDecay; MYFLT systemDecay; MYFLT num_objects; MYFLT totalEnergy; MYFLT finalZ0; MYFLT finalZ1; MYFLT finalZ2; MYFLT decayScale; MYFLT res_freq; MYFLT res_freq1; MYFLT res_freq2; MYFLT shake_damp; int kloop; } TAMBOURINE; typedef struct Bamboo { OPDS h; MYFLT *ar; /* Output */ MYFLT *amp; /* How loud */ MYFLT *dettack; /* How loud */ MYFLT *num_tubes; MYFLT *damp; MYFLT *shake_max; MYFLT *freq; MYFLT *freq1; MYFLT *freq2; MYFLT num_objectsSave; MYFLT shake_maxSave; MYFLT shakeEnergy; MYFLT outputs00; MYFLT outputs01; MYFLT outputs10; MYFLT outputs11; MYFLT outputs20; MYFLT outputs21; MYFLT coeffs00; MYFLT coeffs01; MYFLT coeffs10; MYFLT coeffs11; MYFLT coeffs20; MYFLT coeffs21; MYFLT sndLevel; MYFLT gain; MYFLT resons; MYFLT soundDecay; MYFLT systemDecay; MYFLT num_objects; MYFLT totalEnergy; MYFLT decayScale; MYFLT res_freq0; MYFLT res_freq1; MYFLT res_freq2; MYFLT shake_damp; int kloop; } BAMBOO; typedef struct Wuter { OPDS h; MYFLT *ar; /* Output */ MYFLT *amp; /* How loud */ MYFLT *dettack; /* How loud */ MYFLT *num_tubes; MYFLT *damp; MYFLT *shake_max; MYFLT *freq; MYFLT *freq1; MYFLT *freq2; MYFLT num_objectsSave; MYFLT shake_maxSave; MYFLT shakeEnergy; MYFLT outputs00; MYFLT outputs01; MYFLT outputs10; MYFLT outputs11; MYFLT outputs20; MYFLT outputs21; MYFLT coeffs00; MYFLT coeffs01; MYFLT coeffs10; MYFLT coeffs11; MYFLT coeffs20; MYFLT coeffs21; MYFLT finalZ0; MYFLT finalZ1; MYFLT finalZ2; MYFLT sndLevel; MYFLT gains0; MYFLT gains1; MYFLT gains2; MYFLT center_freqs0; MYFLT center_freqs1; MYFLT center_freqs2; MYFLT soundDecay; MYFLT systemDecay; MYFLT num_objects; MYFLT totalEnergy; MYFLT decayScale; MYFLT res_freq0; MYFLT res_freq1; MYFLT res_freq2; MYFLT shake_damp; int kloop; } WUTER; typedef struct Sleighbells { OPDS h; MYFLT *ar; /* Output */ MYFLT *amp; /* How loud */ MYFLT *dettack; /* How loud */ MYFLT *num_bells; MYFLT *damp; MYFLT *shake_max; MYFLT *freq; MYFLT *freq1; MYFLT *freq2; MYFLT num_objectsSave; MYFLT shake_maxSave; MYFLT shakeEnergy; MYFLT outputs00; MYFLT outputs01; MYFLT outputs10; MYFLT outputs11; MYFLT outputs20; MYFLT outputs21; MYFLT outputs30; MYFLT outputs31; MYFLT outputs40; MYFLT outputs41; MYFLT coeffs00; MYFLT coeffs01; MYFLT coeffs10; MYFLT coeffs11; MYFLT coeffs20; MYFLT coeffs21; MYFLT coeffs30; MYFLT coeffs31; MYFLT coeffs40; MYFLT coeffs41; MYFLT finalZ0; MYFLT finalZ1; MYFLT finalZ2; MYFLT sndLevel; MYFLT gain; MYFLT soundDecay; MYFLT systemDecay; MYFLT num_objects; MYFLT totalEnergy; MYFLT decayScale; MYFLT res_freq0; MYFLT res_freq1; MYFLT res_freq2; MYFLT res_freq3; MYFLT res_freq4; MYFLT shake_damp; int kloop; } SLEIGHBELLS; #endif csound-6.10.0/Opcodes/physmod.c000066400000000000000000001207521321653344700163330ustar00rootroot00000000000000/* physmod.c: Copyright (C) 1996, 1997 Perry Cook, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Collection of physical modelled instruments */ //#include "csdl.h" #include "csoundCore.h" #include "clarinet.h" #include "flute.h" #include "bowed.h" #include "brass.h" #include #include "interlocks.h" /* ************************************** */ /* Waveguide Clarinet model ala Smith */ /* after McIntyre, Schumacher, Woodhouse */ /* by Perry Cook, 1995-96 */ /* Recoded for Csound by John ffitch */ /* November 1997 */ /* */ /* This is a waveguide model, and thus */ /* relates to various Stanford Univ. */ /* and possibly Yamaha and other patents.*/ /* */ /* ************************************** */ /**********************************************/ /* One break point linear reed table object */ /* by Perry R. Cook, 1995-96 */ /* Consult McIntyre, Schumacher, & Woodhouse */ /* Smith, Hirschman, Cook, Scavone, */ /* more for information. */ /**********************************************/ static inline MYFLT ReedTabl_LookUp(ReedTabl *r, MYFLT deltaP) /* Perform "Table Lookup" by direct clipped */ /* linear function calculation */ { /* deltaP is differential reed pressure */ MYFLT lastOutput = r->offSet + (r->slope * deltaP); /* basic non-lin */ if (lastOutput > FL(1.0)) lastOutput = FL(1.0); /* if other way, reed slams shut */ if (lastOutput < -FL(1.0)) lastOutput = -FL(1.0); /* if all the way open, acts like open end */ return lastOutput; } /*******************************************/ /* One Zero Filter Class, */ /* by Perry R. Cook, 1995-96 */ /* The parameter gain is an additional */ /* gain parameter applied to the filter */ /* on top of the normalization that takes */ /* place automatically. So the net max */ /* gain through the system equals the */ /* value of gain. sgain is the combina- */ /* tion of gain and the normalization */ /* parameter, so if you set the poleCoeff */ /* to alpha, sgain is always set to */ /* gain / (1.0 - fabs(alpha)). */ /*******************************************/ void make_OneZero(OneZero* z) { z->gain = FL(1.0); z->zeroCoeff = FL(1.0); z->sgain = FL(0.5); z->inputs = FL(0.0); } MYFLT OneZero_tick(OneZero* z, MYFLT sample) /* Perform Filter Operation */ { MYFLT temp, lastOutput; temp = z->sgain * sample; lastOutput = (z->inputs * z->zeroCoeff) + temp; z->inputs = temp; return lastOutput; } void OneZero_setCoeff(OneZero* z, MYFLT aValue) { z->zeroCoeff = aValue; if (z->zeroCoeff > FL(0.0)) /* Normalize gain to 1.0 max */ z->sgain = z->gain / (FL(1.0) + z->zeroCoeff); else z->sgain = z->gain / (FL(1.0) - z->zeroCoeff); } /* void OneZero_print(CSOUND *csound, OneZero *p) */ /* { */ /* csound->Message(csound, */ /* "OneZero: gain=%f inputs=%f zeroCoeff=%f sgain=%f\n", */ /* p->gain, p->inputs, p->zeroCoeff, p->sgain); */ /* } */ /* *********************************************************************** */ int clarinset(CSOUND *csound, CLARIN *p) { FUNC *ftp; if (LIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) != NULL)) p->vibr = ftp; else { /* Expect sine wave */ return csound->InitError(csound, Str("No table for Clarinet")); } if (*p->lowestFreq>=FL(0.0)) { /* Skip initialisation */ if (*p->lowestFreq) p->length = (int32) (CS_ESR / *p->lowestFreq + FL(1.0)); else if (LIKELY(*p->frequency)) p->length = (int32) (CS_ESR / *p->frequency + FL(1.0)); else { csound->Warning(csound, Str("No base frequency for clarinet " "-- assuming 50Hz\n")); p->length = (int32) (CS_ESR / FL(50.0) + FL(1.0)); } make_DLineL(csound, &p->delayLine, p->length); p->reedTable.offSet = FL(0.7); p->reedTable.slope = -FL(0.3); make_OneZero(&(p->filter)); make_Envelope(&p->envelope); make_Noise(p->noise); /* p->noiseGain = 0.2f; */ /* Arguemnts; suggested values? */ /* p->vibrGain = 0.1f; */ { int relestim = (int)(CS_EKR * FL(0.1)); /* 1/10th second decay extention */ if (relestim > p->h.insdshead->xtratim) p->h.insdshead->xtratim = relestim; } p->kloop = (int) ((int32) (p->h.insdshead->offtim * CS_EKR) - (int32) (CS_EKR * *p->attack)); #ifdef BETA csound->Message(csound, "offtim=%f kloop=%d\n", p->h.insdshead->offtim, p->kloop); #endif p->envelope.rate = FL(0.0); p->v_time = 0; } return OK; } int clarin(CSOUND *csound, CLARIN *p) { MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT amp = (*p->amp)*AMP_RSCALE; /* Normalise */ MYFLT nGain = *p->noiseGain; int v_len = (int)p->vibr->flen; MYFLT *v_data = p->vibr->ftable; MYFLT vibGain = *p->vibAmt; MYFLT vTime = p->v_time; if (p->envelope.rate==FL(0.0)) { p->envelope.rate = amp /(*p->attack*CS_ESR); p->envelope.value = p->envelope.target = FL(0.55) + amp*FL(0.30); } p->outputGain = amp + FL(0.001); DLineL_setDelay(&p->delayLine, /* length - approx filter delay */ (CS_ESR/ *p->frequency) * FL(0.5) - FL(1.5)); p->v_rate = *p->vibFreq * p->vibr->flen * csound->onedsr; /* Check to see if into decay yet */ if (p->kloop>0 && p->h.insdshead->relesing) p->kloop=1; if ((--p->kloop) == 0) { p->envelope.state = 1; /* Start change */ p->envelope.rate = p->envelope.value / (*p->dettack * CS_ESR); p->envelope.target = FL(0.0); #ifdef BETA csound->Message(csound, "Set off phase time = %f Breath v,r = %f, %f\n", (MYFLT) CS_KCNT * CS_ONEDKR, p->envelope.value, p->envelope.rate); #endif } if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;nenvelope); breathPressure += breathPressure * nGain * Noise_tick(csound,&p->noise); /* Tick on vibrato table */ vTime += p->v_rate; /* Update current time */ while (vTime >= v_len) /* Check for end of sound */ vTime -= v_len; /* loop back to beginning */ while (vTime < FL(0.0)) /* Check for end of sound */ vTime += v_len; /* loop back to beginning */ temp_time = vTime; #ifdef have_phase if (p->v_phaseOffset != FL(0.0)) { temp_time += p->v_phaseOffset; /* Add phase offset */ while (temp_time >= v_len) /* Check for end of sound */ temp_time -= v_len; /* loop back to beginning */ while (temp_time < FL(0.0)) /* Check for end of sound */ temp_time += v_len; /* loop back to beginning */ } #endif temp = (int32) temp_time; /* Integer part of time address */ /* fractional part of time address */ alpha = temp_time - (MYFLT)temp; v_lastOutput = v_data[temp]; /* Do linear interpolation */ /* same as alpha*data[temp+1] + (1-alpha)data[temp] */ v_lastOutput += (alpha * (v_data[temp+1] - v_lastOutput)); /* End of vibrato tick */ breathPressure += breathPressure * vibGain * v_lastOutput; pressureDiff = OneZero_tick(&p->filter, /* differential pressure */ DLineL_lastOut(&p->delayLine)); pressureDiff = (-FL(0.95)*pressureDiff) - breathPressure; /* of reflected and mouth */ nextsamp = pressureDiff * ReedTabl_LookUp(&p->reedTable,pressureDiff); nextsamp = breathPressure + nextsamp; /* perform scattering in economical way */ lastOutput = DLineL_tick(&p->delayLine, nextsamp); lastOutput *= p->outputGain; ar[n] = lastOutput*AMP_SCALE; } p->v_time = vTime; return OK; } /******************************************/ /* WaveGuide Flute ala Karjalainen, */ /* Smith, Waryznyk, etc. */ /* with polynomial Jet ala Cook */ /* by Perry Cook, 1995-96 */ /* Recoded for Csound by John ffitch */ /* November 1997 */ /* */ /* This is a waveguide model, and thus */ /* relates to various Stanford Univ. */ /* and possibly Yamaha and other patents.*/ /* */ /******************************************/ /**********************************************/ /* Jet Table Object by Perry R. Cook, 1995-96 */ /* Consult Fletcher and Rossing, Karjalainen, */ /* Cook, more, for information. */ /* This, as with many other of my "tables", */ /* is not a table, but is computed by poly- */ /* nomial calculation. */ /**********************************************/ static inline MYFLT JetTabl_lookup(MYFLT sample) /* Perform "Table Lookup" */ { /* By Polynomial Calculation */ /* (x^3 - x) approximates sigmoid of jet */ MYFLT j = sample * (sample*sample - FL(1.0)); if (j > FL(1.0)) j = FL(1.0); /* Saturation at +/- 1.0 */ else if (j < -FL(1.0)) j = -FL(1.0); return j; } int fluteset(CSOUND *csound, FLUTE *p) { FUNC *ftp; int32 length; if (LIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) != NULL)) p->vibr = ftp; else { /* Expect sine wave */ return csound->InitError(csound, Str("No table for Flute")); } if (*p->lowestFreq>=FL(0.0)) { /* Skip initialisation?? */ if (*p->lowestFreq!=FL(0.0)) { length = (int32) (CS_ESR / *p->lowestFreq + FL(1.0)); p->limit = *p->lowestFreq; } else if (*p->frequency!=FL(0.0)) { length = (int32) (CS_ESR / *p->frequency + FL(1.0)); p->limit = *p->frequency; } else { csound->Warning(csound, Str("No base frequency for flute " "-- assumed to be 50Hz\n")); length = (int32) (CS_ESR / FL(50.0) + FL(1.0)); p->limit = FL(50.0); } make_DLineL(csound, &p->boreDelay, length); length = length >> 1; /* ??? really; yes from later version */ make_DLineL(csound, &p->jetDelay, length); make_OnePole(&p->filter); make_DCBlock(&p->dcBlock); make_Noise(p->noise); make_ADSR(&p->adsr); /* Clear */ /* OnePole_clear(&p->filter); */ /* DCBlock_clear(&p->dcBlock); */ /* End Clear */ /* DLineL_setDelay(&p->boreDelay, 100.0f); */ /* DLineL_setDelay(&p->jetDelay, 49.0f); */ OnePole_setPole(&p->filter, FL(0.7) - (FL(0.1) * RATE_NORM)); OnePole_setGain(&p->filter, -FL(1.0)); ADSR_setAllTimes(csound, &p->adsr, FL(0.005), FL(0.01), FL(0.8), FL(0.010)); /* ADSR_setAll(&p->adsr, 0.02f, 0.05f, 0.8f, 0.001f); */ /* Suggested values */ /* p->endRefl = 0.5; */ /* p->jetRefl = 0.5; */ /* p->noiseGain = 0.15; */ /* Breath pressure random component */ /* p->vibrGain = 0.05; */ /* breath periodic vibrato component */ /* p->jetRatio = 0.32; */ p->lastamp = FL(1.0); /* Remember */ /* This should be controlled by attack */ ADSR_setAttackRate(csound, &p->adsr, FL(0.02)); p->maxPress = FL(2.3) / FL(0.8); p->outputGain = FL(1.001); ADSR_keyOn(&p->adsr); p->kloop = (MYFLT)((int)(p->h.insdshead->offtim*CS_EKR - CS_EKR*(*p->dettack))); p->lastFreq = FL(0.0); p->lastJet = -FL(1.0); /* freq = (2/3)*p->frequency as we're overblowing here */ /* but 1/(2/3) is 1.5 so multiply for speed */ } return OK; } int flute(CSOUND *csound, FLUTE *p) { MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT amp = (*p->amp)*AMP_RSCALE; /* Normalise */ MYFLT temp; int v_len = (int)p->vibr->flen; MYFLT *v_data = p->vibr->ftable; MYFLT v_time = p->v_time; MYFLT vibGain = *p->vibAmt; MYFLT jetRefl, endRefl, noisegain; if (amp!=p->lastamp) { /* If amplitude has changed */ /* This should be controlled by attack */ ADSR_setAttackRate(csound, &p->adsr, amp * FL(0.02)); p->maxPress = (FL(1.1) + (amp * FL(0.20))) / FL(0.8); p->outputGain = amp + FL(0.001); p->lastamp = amp; } p->v_rate = *p->vibFreq * v_len * csound->onedsr; /* Start SetFreq */ if (p->lastFreq != *p->frequency) { /* It changed */ p->lastFreq = *p->frequency; if (p->limit>p->lastFreq) { p->lastFreq = p->limit; csound->Warning(csound, Str("frequency too low, set to minimum")); } p->lastJet = *p->jetRatio; /* freq = (2/3)*p->frequency as we're overblowing here */ /* but 1/(2/3) is 1.5 so multiply for speed */ /* Length - approx. filter delay */ temp = FL(1.5)* CS_ESR / p->lastFreq - FL(2.0); DLineL_setDelay(&p->boreDelay, temp); /* Length of bore tube */ DLineL_setDelay(&p->jetDelay, temp * p->lastJet); /* jet delay shorter */ } else if (*p->jetRatio != p->lastJet) { /* Freq same but jet changed */ p->lastJet = *p->jetRatio; /* Length - approx. filter delay */ temp = FL(1.5)* CS_ESR / p->lastFreq - FL(2.0); DLineL_setDelay(&p->jetDelay, temp * p->lastJet); /* jet delay shorter */ } /* End SetFreq */ if (p->kloop>FL(0.0) && p->h.insdshead->relesing) p->kloop=FL(1.0); if ((--p->kloop) == 0) { p->adsr.releaseRate = p->adsr.value / (*p->dettack * CS_ESR); p->adsr.target = FL(0.0); p->adsr.rate = p->adsr.releaseRate; p->adsr.state = RELEASE; } noisegain = *p->noiseGain; jetRefl = *p->jetRefl; endRefl = *p->endRefl; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;nmaxPress * ADSR_tick(&p->adsr); /* Breath Pressure */ randPress = noisegain*Noise_tick(csound,&p->noise); /* Random Deviation */ /* Tick on vibrato table */ v_time += p->v_rate; /* Update current time */ while (v_time >= v_len) /* Check for end of sound */ v_time -= v_len; /* loop back to beginning */ while (v_time < FL(0.0)) /* Check for end of sound */ v_time += v_len; /* loop back to beginning */ temp_time = v_time; #ifdef phase_offset if (p->v_phaseOffset != FL(0.0)) { temp_time += p->v_phaseOffset;/* Add phase offset */ while (temp_time >= v_len) /* Check for end of sound */ temp_time -= v_len; /* loop back to beginning */ while (temp_time < FL(0.0)) /* Check for end of sound */ temp_time += v_len; /* loop back to beginning */ } #endif temp = (int32) temp_time; /* Integer part of time address */ /* fractional part of time address */ alpha = temp_time - (MYFLT)temp; v_lastOutput = v_data[temp]; /* Do linear interpolation */ /* same as alpha*data[temp+1] + (1-alpha)data[temp] */ v_lastOutput += (alpha * (v_data[temp+1] - v_lastOutput)); /* End of vibrato tick */ randPress += vibGain * v_lastOutput; /* + breath vibrato */ randPress *= breathPress; /* All scaled by Breath Pressure */ temf = OnePole_tick(&p->filter, DLineL_lastOut(&p->boreDelay)); temf = DCBlock_tick(&p->dcBlock, temf); /* Block DC on reflection */ pressDiff = breathPress + randPress /* Breath Pressure */ - (jetRefl * temf); /* - reflected */ pressDiff = DLineL_tick(&p->jetDelay, pressDiff); /* Jet Delay Line */ pressDiff = JetTabl_lookup(pressDiff) /* Non-Lin Jet + reflected */ + (endRefl * temf); /* Bore Delay and "bell" filter */ lastOutput = FL(0.3) * DLineL_tick(&p->boreDelay, pressDiff); lastOutput *= p->outputGain; ar[n] = lastOutput*AMP_SCALE*FL(1.4); } p->v_time = v_time; return OK; } /******************************************/ /* Bowed String model ala Smith */ /* after McIntyre, Schumacher, Woodhouse */ /* by Perry Cook, 1995-96 */ /* Recoded for Csound by John ffitch */ /* November 1997 */ /* */ /* This is a waveguide model, and thus */ /* relates to various Stanford Univ. */ /* and possibly Yamaha and other patents.*/ /* */ /******************************************/ /******************************************/ /* Simple Bow Table Object, after Smith */ /* by Perry R. Cook, 1995-96 */ /******************************************/ /* Perform Table Lookup */ MYFLT BowTabl_lookup(CSOUND *csound, BowTabl *b, MYFLT sample) { /* sample is differential */ MYFLT lastOutput; /* string vs. bow velocity */ MYFLT input; input = sample /* + b->offSet*/ ; /* add bias to sample */ input *= b->slope; /* scale it */ lastOutput = FABS(input) + FL(0.75); /* below min delta, frict = 1 */ lastOutput = csound->intpow(lastOutput,-4L); /* if (lastOutput < FL(0.0) ) lastOutput = FL(0.0); */ /* minimum frict is 0.0 */ if (lastOutput > FL(1.0)) lastOutput = FL(1.0); /* maximum friction is 1.0 */ return lastOutput; } int bowedset(CSOUND *csound, BOWED *p) { int32 length; FUNC *ftp; MYFLT amp = (*p->amp)*AMP_RSCALE; /* Normalise */ if (LIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) != NULL)) p->vibr = ftp; else { /* Expect sine wave */ return csound->InitError(csound, Str("No table for wgbow vibrato")); } if (*p->lowestFreq>=FL(0.0)) { /* If no init skip */ if (*p->lowestFreq!=FL(0.0)) { length = (int32) (CS_ESR / *p->lowestFreq + FL(1.0)); p->limit = *p->lowestFreq; } else if (*p->frequency!=FL(0.0)) { length = (int32) (CS_ESR / *p->frequency + FL(1.0)); p->limit = *p->frequency; } else { csound->Warning(csound, Str("unknown lowest frequency for bowed string " "-- assuming 50Hz\n")); length = (int32) (CS_ESR / FL(50.0) + FL(1.0)); p->limit = FL(50.0); } make_DLineL(csound, &p->neckDelay, length); length = length >> 1; /* Unsure about this; seems correct in later code */ make_DLineL(csound, &p->bridgeDelay, length); /* p->bowTabl.offSet = FL(0.0);*/ /* offset is a bias, really not needed unless */ /* friction is different in each direction */ /* p->bowTabl.slope contrls width of friction pulse, related to bowForce */ p->bowTabl.slope = FL(3.0); make_OnePole(&p->reflFilt); make_BiQuad(&p->bodyFilt); make_ADSR(&p->adsr); DLineL_setDelay(&p->neckDelay, FL(100.0)); DLineL_setDelay(&p->bridgeDelay, FL(29.0)); OnePole_setPole(&p->reflFilt, FL(0.6) - (FL(0.1) * RATE_NORM)); OnePole_setGain(&p->reflFilt, FL(0.95)); BiQuad_setFreqAndReson(p->bodyFilt, FL(500.0), FL(0.85)); BiQuad_setEqualGainZeroes(p->bodyFilt); BiQuad_setGain(p->bodyFilt, FL(0.2)); ADSR_setAllTimes(csound, &p->adsr, FL(0.02), FL(0.005), FL(0.9), FL(0.01)); /* ADSR_setAll(&p->adsr, 0.002f,0.01f,0.9f,0.01f); */ p->adsr.target = FL(1.0); p->adsr.rate = p->adsr.attackRate; p->adsr.state = ATTACK; p->maxVelocity = FL(0.03) + (FL(0.2) * amp); p->lastpress = FL(0.0); /* Set unknown state */ p->lastfreq = FL(0.0); p->lastbeta = FL(0.0); /* Remember states */ p->lastamp = amp; } return OK; } int bowed(CSOUND *csound, BOWED *p) { MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT amp = (*p->amp)*AMP_RSCALE; /* Normalise */ MYFLT maxVel; int freq_changed = 0; if (amp != p->lastamp) { p->maxVelocity = FL(0.03) + (FL(0.2) * amp); p->lastamp = amp; } maxVel = p->maxVelocity; if (p->lastpress != *p->bowPress) p->bowTabl.slope = p->lastpress = *p->bowPress; /* Set Frequency if changed */ if (p->lastfreq != *p->frequency) { /* delay - approx. filter delay */ if (p->limit<=*p->frequency) p->lastfreq = *p->frequency; else { p->lastfreq = p->limit; csound->Warning(csound, Str("frequency too low, set to minimum")); } p->baseDelay = CS_ESR / p->lastfreq - FL(4.0); freq_changed = 1; } if (p->lastbeta != *p->betaRatio || freq_changed) { /* Reset delays if changed */ p->lastbeta = *p->betaRatio; DLineL_setDelay(&p->bridgeDelay, /* bow to bridge length */ p->baseDelay * p->lastbeta); DLineL_setDelay(&p->neckDelay, /* bow to nut (finger) length */ p->baseDelay *(FL(1.0) - p->lastbeta)); } p->v_rate = *p->vibFreq * p->vibr->flen * csound->onedsr; if (p->kloop>0 && p->h.insdshead->relesing) p->kloop=1; if ((--p->kloop) == 0) { ADSR_setDecayRate(csound, &p->adsr, (FL(1.0) - p->adsr.value) * FL(0.005)); p->adsr.target = FL(0.0); p->adsr.rate = p->adsr.releaseRate; p->adsr.state = RELEASE; } if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;nadsr); /* Bridge Reflection */ bridgeRefl = - OnePole_tick(&p->reflFilt, p->bridgeDelay.lastOutput); nutRefl = - p->neckDelay.lastOutput; /* Nut Reflection */ stringVel = bridgeRefl + nutRefl; /* Sum is String Velocity */ velDiff = bowVelocity - stringVel; /* Differential Velocity */ /* Non-Lin Bow Function */ newVel = velDiff * BowTabl_lookup(csound, &p->bowTabl, velDiff); DLineL_tick(&p->neckDelay, bridgeRefl + newVel); /* Do string */ DLineL_tick(&p->bridgeDelay, nutRefl + newVel); /* propagations */ if (*p->vibAmt > FL(0.0)) { int32 temp; MYFLT temp_time, alpha; /* Tick on vibrato table */ p->v_time += p->v_rate; /* Update current time */ while (p->v_time >= p->vibr->flen) /* Check for end of sound */ p->v_time -= p->vibr->flen; /* loop back to beginning */ while (p->v_time < FL(0.0)) /* Check for end of sound */ p->v_time += p->vibr->flen; /* loop back to beginning */ temp_time = p->v_time; #ifdef phase_offset if (p->v_phaseOffset != FL(0.0)) { temp_time += p->v_phaseOffset; /* Add phase offset */ while (temp_time >= p->vibr->flen) /* Check for end of sound */ temp_time -= p->vibr->flen; /* loop back to beginning */ while (temp_time < FL(0.0)) /* Check for end of sound */ temp_time += p->vibr->flen; /* loop back to beginning */ } #endif temp = (int32) temp_time; /* Integer part of time address */ /* fractional part of time address */ alpha = temp_time - (MYFLT)temp; p->v_lastOutput = p->vibr->ftable[temp]; /* Do linear interpolation */ /* same as alpha*data[temp+1] + (1-alpha)data[temp] */ p->v_lastOutput = p->v_lastOutput + (alpha * (p->vibr->ftable[temp+1] - p->v_lastOutput)); /* End of vibrato tick */ DLineL_setDelay(&p->neckDelay, (p->baseDelay * (FL(1.0) - p->lastbeta)) + (p->baseDelay * *p->vibAmt * p->v_lastOutput)); } else DLineL_setDelay(&p->neckDelay, (p->baseDelay * (FL(1.0) - p->lastbeta))); lastOutput = BiQuad_tick(&p->bodyFilt, p->bridgeDelay.lastOutput); ar[n] = lastOutput*AMP_SCALE * amp *FL(1.8); } return OK; } /******************************************/ /* Waveguide Brass Instrument Model ala */ /* Cook (TBone, HosePlayer) */ /* by Perry R. Cook, 1995-96 */ /* Recoded for Csound by John ffitch */ /* November 1997 */ /* */ /* This is a waveguide model, and thus */ /* relates to various Stanford Univ. */ /* and possibly Yamaha and other patents.*/ /* */ /******************************************/ /****************************************************************************/ /* */ /* AllPass Interpolating Delay Line Object by Perry R. Cook 1995-96 */ /* This one uses a delay line of maximum length specified on creation, */ /* and interpolates fractional length using an all-pass filter. This */ /* version is more efficient for computing static length delay lines */ /* (alpha and coeff are computed only when the length is set, there */ /* probably is a more efficient computational form if alpha is changed */ /* often (each sample)). */ /****************************************************************************/ void make_DLineA(CSOUND *csound, DLineA *p, int32 max_length) { p->length = max_length; csound->AuxAlloc(csound, max_length * sizeof(MYFLT), &p->inputs); p->lastIn = FL(0.0); p->lastOutput = FL(0.0); p->inPoint = 0; p->outPoint = max_length >> 1; } int DLineA_setDelay(CSOUND *csound, DLineA *p, MYFLT lag) { MYFLT outputPointer; /* outPoint chases inpoint + 2 for interp and other */ outputPointer = (MYFLT)p->inPoint - lag + FL(2.0); if (UNLIKELY(p->length<=0)) goto err1; while (outputPointer<0) outputPointer += p->length; /* modulo table length */ p->outPoint = (int32) outputPointer; /* Integer part of delay */ p->alpha = FL(1.0) + p->outPoint - outputPointer;/* fractional part of delay */ if (p->alphaoutPoint++; /* cancellation. Keeps allpass */ p->alpha += FL(1.0); /* delay in range of .1 to 1.1 */ } p->coeff = (FL(1.0)-p->alpha)/(FL(1.0)+p->alpha); /* coefficient for all pass*/ return 0; err1: csound->ErrorMsg(csound, Str("DlineA not initialised")); return NOTOK; } MYFLT DLineA_tick(DLineA *p, MYFLT sample) /* Take sample, yield sample */ { MYFLT temp; ((MYFLT*)p->inputs.auxp)[p->inPoint++] = sample; /* Write input sample */ if (p->inPoint >= p->length) /* Increment input pointer */ p->inPoint -= p->length; /* modulo length */ temp = ((MYFLT*)p->inputs.auxp)[p->outPoint++]; /* filter input */ if (p->outPoint >= p->length) /* Increment output pointer*/ p->outPoint -= p->length; /* modulo length */ p->lastOutput = -p->coeff * p->lastOutput; /* delayed output */ p->lastOutput += p->lastIn + (p->coeff * temp); /* input + delayed Input*/ p->lastIn = temp; return p->lastOutput; /* save output and return */ } /* ====================================================================== */ /****************************************************************************/ /* Lip Filter Object by Perry R. Cook, 1995-96 */ /* The lip of the brass player has dynamics which are controlled by the */ /* mass, spring constant, and damping of the lip. This filter simulates */ /* that behavior and the transmission/reflection properties as well. */ /* See Cook TBone and HosePlayer instruments and articles. */ /****************************************************************************/ #define make_LipFilt(p) make_BiQuad(p) void LipFilt_setFreq(CSOUND *csound, LipFilt *p, MYFLT frequency) { MYFLT coeffs[2]; coeffs[0] = FL(2.0) * FL(0.997) * (MYFLT)cos(csound->tpidsr * (double)frequency); /* damping should */ coeffs[1] = -FL(0.997) * FL(0.997); /* change with lip */ BiQuad_setPoleCoeffs(p, coeffs); /* parameters, but */ BiQuad_setGain(*p, FL(0.03)); /* not yet. */ } /* NOTE: Here we should add lip tension */ /* settings based on Mass/Spring/Damping */ /* Maybe in TookKit97 */ MYFLT LipFilt_tick(LipFilt *p, MYFLT mouthSample, MYFLT boreSample) /* Perform "Table Lookup" By Polynomial Calculation */ { MYFLT temp; MYFLT output; temp = mouthSample - boreSample; /* Differential pressure */ temp = BiQuad_tick(p, temp); /* Force -> position */ temp = temp*temp; /* Simple position to area mapping */ if (temp > FL(1.0)) temp = FL(1.0); /* Saturation at + 1.0 */ output = temp * mouthSample; /* Assume mouth input = area */ output += (FL(1.0)-temp) * boreSample; /* and Bore reflection is compliment */ return output; } /* ====================================================================== */ int brassset(CSOUND *csound, BRASS *p) { FUNC *ftp; MYFLT amp = (*p->amp)*AMP_RSCALE; /* Normalise */ if (LIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) != NULL)) p->vibr = ftp; else { /* Expect sine wave */ return csound->InitError(csound, Str("No table for Brass")); } p->frq = *p->frequency; /* Remember */ if (*p->lowestFreq>=FL(0.0)) { if (*p->lowestFreq!=FL(0.0)) { p->length = (int32) (CS_ESR / *p->lowestFreq + FL(1.0)); p->limit = *p->lowestFreq; } else if (p->frq!=FL(0.0)) { p->length = (int32) (CS_ESR / p->frq + FL(1.0)); p->limit = p->frq; } else { csound->Warning(csound, Str("No base frequency for brass " "-- assumed to be 50Hz\n")); p->length = (int32) (CS_ESR / FL(50.0) + FL(1.0)); p->limit = FL(50.0); } make_DLineA(csound, &p->delayLine, p->length); make_LipFilt(&p->lipFilter); make_DCBlock(&p->dcBlock); make_ADSR(&p->adsr); ADSR_setAllTimes(csound, &p->adsr, FL(0.005), FL(0.001), FL(1.0), FL(0.010)); /* ADSR_setAll(&p->adsr, 0.02f, 0.05f, FL(1.0), 0.001f); */ ADSR_setAttackRate(csound, &p->adsr, amp * FL(0.001)); p->maxPressure = amp; ADSR_keyOn(&p->adsr); /* Set frequency */ /* p->slideTarget = (CS_ESR / p->frq * FL(2.0)) + 3.0f; */ /* fudge correction for filter delays */ /* DLineA_setDelay(&p->delayLine, p->slideTarget);*/ /* we'll play a harmonic */ p->lipTarget = FL(0.0); /* LipFilt_setFreq(csound, &p->lipFilter, p->frq); */ /* End of set frequency */ p->frq = FL(0.0); /* to say we do not know */ p->lipT = FL(0.0); /* LipFilt_setFreq(csound, &p->lipFilter, */ /* p->lipTarget * (MYFLT)pow(4.0, (2.0* p->lipT) -1.0)); */ { int relestim = (int)(CS_EKR * FL(0.1)); /* 1/10th second decay extention */ if (relestim > p->h.insdshead->xtratim) p->h.insdshead->xtratim = relestim; } p->kloop = (int) ((int32) (p->h.insdshead->offtim * CS_EKR) - (int32) (CS_EKR * *p->dettack)); } return OK; } int brass(CSOUND *csound, BRASS *p) { MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT amp = (*p->amp)*AMP_RSCALE; /* Normalise */ MYFLT maxPressure = p->maxPressure = amp; int v_len = (int)p->vibr->flen; MYFLT *v_data = p->vibr->ftable; MYFLT vibGain = *p->vibAmt; MYFLT vTime = p->v_time; p->v_rate = *p->vibFreq * v_len * csound->onedsr; /* vibr->setFreq(6.137); */ /* vibrGain = 0.05; */ /* breath periodic vibrato component */ if (p->kloop>0 && p->h.insdshead->relesing) p->kloop=1; if ((--p->kloop) == 0) { ADSR_setReleaseRate(csound, &p->adsr, amp * FL(0.005)); ADSR_keyOff(&p->adsr); } if (p->frq != *p->frequency) { /* Set frequency if changed */ p->frq = *p->frequency; if (p->limit > p->frq) { p->frq =p->limit; csound->Warning(csound, Str("frequency too low, set to minimum")); } p->slideTarget = (CS_ESR / p->frq * FL(2.0)) + FL(3.0); /* fudge correction for filter delays */ /* we'll play a harmonic */ if (DLineA_setDelay(csound, &p->delayLine, p->slideTarget)) return OK; p->lipTarget = p->frq; p->lipT = FL(0.0); /* So other part is set */ } /* End of set frequency */ if (*p->liptension != p->lipT) { p->lipT = *p->liptension; LipFilt_setFreq(csound, &p->lipFilter, p->lipTarget * (MYFLT)pow(4.0,(2.0* p->lipT) -1.0)); } if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;nadsr); /* Tick on vibrato table */ vTime += p->v_rate; /* Update current time */ while (vTime >= v_len) /* Check for end of sound */ vTime -= v_len; /* loop back to beginning */ while (vTime < FL(0.0)) /* Check for end of sound */ vTime += v_len; /* loop back to beginning */ temp_time = vTime; #ifdef phase_offset if (p->v_phaseOffset != FL(0.0)) { temp_time += p->v_phaseOffset; /* Add phase offset */ while (temp_time >= v_len) /* Check for end of sound */ temp_time -= v_len; /* loop back to beginning */ while (temp_time < FL(0.0)) /* Check for end of sound */ temp_time += v_len; /* loop back to beginning */ } #endif temp = (int) temp_time; /* Integer part of time address */ /* fractional part of time address */ alpha = temp_time - (MYFLT)temp; v_lastOutput = v_data[temp]; /* Do linear interpolation, same as */ v_lastOutput += /*alpha*data[temp+1]+(1-alpha)data[temp] */ (alpha * (v_data[temp+1] - v_lastOutput)); /* End of vibrato tick */ breathPressure += vibGain * v_lastOutput; lastOutput = DLineA_tick(&p->delayLine, /* bore delay */ DCBlock_tick(&p->dcBlock, /* block DC */ LipFilt_tick(&p->lipFilter, FL(0.3) * breathPressure, /* mouth input */ /* and bore reflection */ FL(0.85) * p->delayLine.lastOutput))); ans = lastOutput*AMP_SCALE*FL(3.5); ar[n] = ans; } p->v_time = vTime; return OK; } #define S sizeof #include "mandolin.h" #include "singwave.h" #include "shaker.h" #include "fm4op.h" #include "bowedbar.h" int tubebellset(void*,void*); int tubebell(void*,void*); int rhodeset(void*,void*); int wurleyset(void*,void*); int wurley(void*,void*); int heavymetset(void*,void*); int heavymet(void*,void*); int b3set(void*,void*); int hammondB3(void*,void*); int FMVoiceset(void*,void*); int FMVoice(void*,void*); int percfluteset(void*,void*); int percflute(void*,void*); int Moog1set(void*,void*); int Moog1(void*,void*); int mandolinset(void*,void*); int mandolin(void*,void*); int voicformset(void*,void*); int voicform(void*,void*); int shakerset(void*,void*); int shaker(void*,void*); int bowedbarset(void*,void*); int bowedbar(void*,void*); static OENTRY physmod_localops[] = { { "wgclar", S(CLARIN),TR, 5, "a", "kkkiikkkjo",(SUBR)clarinset,NULL, (SUBR)clarin }, { "wgflute", S(FLUTE), TR, 5, "a", "kkkiikkkjovv",(SUBR)fluteset,NULL, (SUBR)flute }, { "wgbow", S(BOWED), TR, 5, "a", "kkkkkkjo", (SUBR)bowedset, NULL, (SUBR)bowed }, { "wgbrass", S(BRASS), TR, 5, "a", "kkkikkjo", (SUBR)brassset, NULL, (SUBR)brass}, { "mandol", S(MANDOL), TR, 5, "a", "kkkkkkio",(SUBR)mandolinset,NULL,(SUBR)mandolin}, { "voice", S(VOICF), TR, 5, "a", "kkkkkkii",(SUBR)voicformset,NULL,(SUBR)voicform}, { "fmbell", S(FM4OP), TR, 5, "a", "kkkkkkjjjjjo", (SUBR)tubebellset,NULL,(SUBR)tubebell}, { "fmrhode", S(FM4OP), TR, 5, "a", "kkkkkkiiiii",(SUBR)rhodeset,NULL,(SUBR)tubebell}, { "fmwurlie", S(FM4OP),TR, 5, "a", "kkkkkkiiiii",(SUBR)wurleyset,NULL,(SUBR)wurley }, { "fmmetal", S(FM4OP), TR, 5, "a", "kkkkkkiiiii", (SUBR)heavymetset, NULL, (SUBR)heavymet}, { "fmb3", S(FM4OP), TR, 5, "a", "kkkkkkjjjjj", (SUBR)b3set,NULL,(SUBR)hammondB3 }, { "fmvoice", S(FM4OPV),TR, 5, "a", "kkkkkkjjjjj", (SUBR)FMVoiceset,NULL,(SUBR)FMVoice}, { "fmpercfl", S(FM4OP),TR, 5, "a", "kkkkkkjjjjj", (SUBR)percfluteset, NULL, (SUBR)percflute}, { "moog", S(MOOG1), TR, 5, "a", "kkkkkkiii", (SUBR)Moog1set, NULL, (SUBR)Moog1 }, { "shaker", S(SHAKER), 0, 5, "a", "kkkkko", (SUBR)shakerset, NULL, (SUBR)shaker}, { "wgbowedbar", S(BOWEDBAR), 0, 5, "a","kkkkkoooo", (SUBR)bowedbarset, NULL,(SUBR) bowedbar }, }; LINKAGE_BUILTIN(physmod_localops) csound-6.10.0/Opcodes/physutil.c000066400000000000000000000355771321653344700165430ustar00rootroot00000000000000/* physutil.c: Copyright (C) 1996, 1997 Perry Cook, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* This file contains a collection of utilities for the Physical Model opcodes, in no particular order */ // #include "csdl.h" #include "csoundCore.h" #include #include "physutil.h" /*******************************************/ /* Noise Generator Class, */ /* by Perry R. Cook, 1995-96 */ /* White noise as often as you like. */ /*******************************************/ /* Return random MYFLT float between -1.0 and 1.0 */ MYFLT Noise_tick(CSOUND *csound, Noise *n) { MYFLT temp; temp = (MYFLT) csound->Rand31(&(csound->randSeed1)) - FL(1073741823.5); temp *= (MYFLT) (1.0 / 1073741823.0); *n = (Noise) temp; return temp; } /*******************************************/ /* Linearly Interpolating Delay Line */ /* Object by Perry R. Cook 1995-96 */ /* This one uses a delay line of maximum */ /* length specified on creation, and */ /* linearly interpolates fractional */ /* length. It is designed to be more */ /* efficient if the delay length is not */ /* changed very often. */ /*******************************************/ void make_DLineL(CSOUND *csound, DLineL *p, int32 max_length) { p->length = max_length; csound->AuxAlloc(csound, max_length * sizeof(MYFLT), &p->inputs); p->outPoint = 0; p->lastOutput = FL(0.0); p->inPoint = max_length >> 1; } void DLineL_setDelay(DLineL *p, MYFLT lag) { MYFLT outputPointer = p->inPoint - lag; /* read chases write, +1 for interp. */ while (outputPointerlength; /* modulo maximum length */ while (outputPointer>=(MYFLT)p->length) outputPointer -= (MYFLT)p->length; /* modulo maximum length */ p->outPoint = (int32) outputPointer; /* integer part */ p->alpha = outputPointer - (MYFLT)p->outPoint; /* fractional part */ p->omAlpha = FL(1.0) - p->alpha; /* 1.0 - fractional part */ } MYFLT DLineL_tick(DLineL *p, MYFLT sample) /* Take one, yield one */ { MYFLT lastOutput; ((MYFLT*)p->inputs.auxp)[p->inPoint++] = sample; /* Input next sample */ if (UNLIKELY( p->inPoint == p->length)) /* Check for end condition */ p->inPoint -= p->length; /* first 1/2 of interpolation */ lastOutput = ((MYFLT*)p->inputs.auxp)[p->outPoint++] * p->omAlpha; if ( p->outPoint< p->length) { /* Check for end condition */ /* second 1/2 of interpolation */ lastOutput += ((MYFLT*)p->inputs.auxp)[p->outPoint] * p->alpha; } else { /* if at end . . . */ /* second 1/2 of interpolation */ lastOutput += ((MYFLT*)p->inputs.auxp)[0]*p->alpha; p->outPoint -= p->length; } return (p->lastOutput = lastOutput); } /*******************************************/ /* Envelope Class, Perry R. Cook, 1995-96 */ /* This is the base class for envelopes. */ /* This one is capable of ramping state */ /* from where it is to a target value by */ /* a rate. */ /*******************************************/ void make_Envelope(Envelope *e) { e->target = FL(0.0); e->value = FL(0.0); e->rate = FL(0.001); e->state = 1; } void Envelope_keyOn(Envelope *e) { e->target = FL(1.0); if (e->value != e->target) e->state = 1; } void Envelope_keyOff(Envelope *e) { e->target = FL(0.0); if (e->value != e->target) e->state = 1; } void Envelope_setRate(CSOUND *csound, Envelope *e, MYFLT aRate) { if (UNLIKELY(aRate < FL(0.0))) { csound->Warning(csound, Str("negative rates not " "allowed!!, correcting\n")); e->rate = -aRate; } else e->rate = aRate; // printf("Env setRate: %p rate=%f value=%f target=%f\n", e, // e->rate, e->value, e->target); } void Envelope_setTarget(Envelope *e, MYFLT aTarget) { e->target = aTarget; if (e->value != e->target) e->state = 1; } void Envelope_setValue(Envelope *e, MYFLT aValue) { e->state = 0; e->target = aValue; e->value = aValue; } MYFLT Envelope_tick(Envelope *e) { // printf("(Envelope_tick: %p state=%d target=%f, rate=%f, value=%f => ", e, // e->state, e->target, e->rate, e->value); if (e->state) { if (e->target > e->value) { e->value += e->rate; if (e->value >= e->target) { e->value = e->target; e->state = 0; } } else { e->value -= e->rate; if (e->value <= e->target) { e->value = e->target; e->state = 0; } } } // printf("%f) ", e->value); return e->value; } void Envelope_print(CSOUND *csound, Envelope *p) { csound->Message(csound, Str("Envelope: value=%f target=%f" " rate=%f state=%d\n"), p->value, p->target, p->rate, p->state); } /*******************************************/ /* One Pole Filter Class, */ /* by Perry R. Cook, 1995-96 */ /* The parameter gain is an additional */ /* gain parameter applied to the filter */ /* on top of the normalization that takes */ /* place automatically. So the net max */ /* gain through the system equals the */ /* value of gain. sgain is the combina- */ /* tion of gain and the normalization */ /* parameter, so if you set the poleCoeff */ /* to alpha, sgain is always set to */ /* gain * (1.0 - fabs(alpha)). */ /*******************************************/ void make_OnePole(OnePole* p) { p->poleCoeff = FL(0.9); p->gain = FL(1.0); p->sgain = FL(0.1); p->outputs = FL(0.0); } void OnePole_setPole(OnePole* p, MYFLT aValue) { p->poleCoeff = aValue; if (p->poleCoeff > FL(0.0)) /* Normalize gain to 1.0 max */ p->sgain = p->gain * (FL(1.0) - p->poleCoeff); else p->sgain = p->gain * (FL(1.0) + p->poleCoeff); } void OnePole_setGain(OnePole* p, MYFLT aValue) { p->gain = aValue; if (p->poleCoeff > FL(0.0)) p->sgain = p->gain * (FL(1.0) - p->poleCoeff); /* Normalize gain 1.0 max */ else p->sgain = p->gain * (FL(1.0) + p->poleCoeff); } MYFLT OnePole_tick(OnePole* p, MYFLT sample) /* Perform Filter Operation */ { p->outputs = (p->sgain * sample) + (p->poleCoeff * p->outputs); return p->outputs; } #ifdef BETA void OnePole_print(CSOUND *csound, OnePole *p) { csound->Message(csound, "OnePole: gain=%f outputs=%f poleCoeff=%f sgain=%f\n", p->gain, p->outputs, p->poleCoeff, p->sgain); } #endif /*******************************************/ /* DC Blocking Filter */ /* by Perry R. Cook, 1995-96 */ /* This guy is very helpful in, uh, */ /* blocking DC. Needed because a simple */ /* low-pass reflection filter allows DC */ /* to build up inside recursive */ /* structures. */ /*******************************************/ void make_DCBlock(DCBlock* p) { p->outputs = FL(0.0); p->inputs = FL(0.0); } MYFLT DCBlock_tick(DCBlock* p, MYFLT sample) { p->outputs = sample - p->inputs + FL(0.99) * p->outputs; p->inputs = sample; return p->outputs; } /*******************************************/ /* ADSR Subclass of the Envelope Class, */ /* by Perry R. Cook, 1995-96 */ /* This is the traditional ADSR (Attack */ /* Decay, Sustain, Release) ADSR. */ /* It responds to simple KeyOn and KeyOff */ /* messages, keeping track of it's state. */ /* There are two tick (update value) */ /* methods, one returns the value, and */ /* other returns the state (0 = A, 1 = D, */ /* 2 = S, 3 = R) */ /*******************************************/ void make_ADSR(ADSR *a) { make_Envelope((Envelope*)a); a->target = FL(0.0); a->value = FL(0.0); a->attackRate = FL(0.001); a->decayRate = FL(0.001); a->sustainLevel = FL(0.5); a->releaseRate = FL(0.01); a->state = ATTACK; } void ADSR_keyOn(ADSR *a) { a->target = FL(1.0); a->rate = a->attackRate; a->state = ATTACK; } void ADSR_keyOff(ADSR *a) { a->target = FL(0.0); a->rate = a->releaseRate; a->state = RELEASE; } void ADSR_setAttackRate(CSOUND *csound, ADSR *a, MYFLT aRate) { if (UNLIKELY(aRate < FL(0.0))) { csound->Warning(csound, Str("negative rates not allowed!!," " correcting\n")); a->attackRate = -aRate; } else a->attackRate = aRate; a->attackRate *= RATE_NORM; } void ADSR_setDecayRate(CSOUND *csound, ADSR *a, MYFLT aRate) { if (UNLIKELY(aRate < FL(0.0))) { csound->Warning(csound, Str("negative rates not allowed!!, correcting\n")); a->decayRate = -aRate; } else a->decayRate = aRate; a->decayRate *= RATE_NORM; } void ADSR_setSustainLevel(CSOUND *csound, ADSR *a, MYFLT aLevel) { if (UNLIKELY(aLevel < FL(0.0) )) { csound->Warning(csound, Str("Sustain level out of range!!, correcting\n")); a->sustainLevel = FL(0.0); } else a->sustainLevel = aLevel; } void ADSR_setReleaseRate(CSOUND *csound, ADSR *a, MYFLT aRate) { if (UNLIKELY(aRate < FL(0.0))) { csound->Warning(csound, Str("negative rates not allowed!!, correcting\n")); a->releaseRate = -aRate; } else a->releaseRate = aRate; a->releaseRate *= RATE_NORM; } void ADSR_setAttackTime(CSOUND *csound, ADSR *a, MYFLT aTime) { if (UNLIKELY(aTime < FL(0.0))) { csound->Warning(csound, Str("negative times not allowed!!, correcting\n")); a->attackRate = FL(1.0) /(-aTime*CS_ESR); } else a->attackRate = FL(1.0) / (aTime*CS_ESR); } void ADSR_setDecayTime(CSOUND *csound, ADSR *a, MYFLT aTime) { if (UNLIKELY(aTime < FL(0.0))) { csound->Warning(csound, Str("negative times not allowed!!, correcting\n")); a->decayRate = FL(1.0) /(-aTime*CS_ESR); } else a->decayRate = FL(1.0) / (aTime*CS_ESR); } void ADSR_setReleaseTime(CSOUND *csound, ADSR *a, MYFLT aTime) { if (UNLIKELY(aTime < FL(0.0))) { csound->Warning(csound, Str("negative times not allowed!!, correcting\n")); a->releaseRate = FL(1.0) /(-aTime*CS_ESR); } else a->releaseRate = FL(1.0) / (aTime*CS_ESR); } void ADSR_setAllTimes(CSOUND *csound, ADSR *a, MYFLT attTime, MYFLT decTime, MYFLT susLevel, MYFLT relTime) { ADSR_setAttackTime(csound, a, attTime); ADSR_setDecayTime(csound, a, decTime); ADSR_setSustainLevel(csound, a, susLevel); ADSR_setReleaseTime(csound, a, relTime); } void ADSR_setAll(CSOUND *csound, ADSR *a, MYFLT attRate, MYFLT decRate, MYFLT susLevel, MYFLT relRate) { ADSR_setAttackRate(csound, a, attRate); ADSR_setDecayRate(csound, a, decRate); ADSR_setSustainLevel(csound, a, susLevel); ADSR_setReleaseRate(csound, a, relRate); } void ADSR_setTarget(CSOUND *csound, ADSR *a, MYFLT aTarget) { a->target = aTarget; if (a->value target) { a->state = ATTACK; ADSR_setSustainLevel(csound, a, a->target); a->rate = a->attackRate; } if (a->value > a->target) { ADSR_setSustainLevel(csound, a, a->target); a->state = DECAY; a->rate = a->decayRate; } } void ADSR_setValue(CSOUND *csound, ADSR *a, MYFLT aValue) { a->state = SUSTAIN; a->target = aValue; a->value = aValue; ADSR_setSustainLevel(csound, a, aValue); a->rate = FL(0.0); } MYFLT ADSR_tick(ADSR *a) { if (a->state==ATTACK) { a->value += a->rate; if (a->value >= a->target) { a->value = a->target; a->rate = a->decayRate; a->target = a->sustainLevel; a->state = DECAY; } } else if (a->state==DECAY) { a->value -= a->decayRate; if (a->value <= a->sustainLevel) { a->value = a->sustainLevel; a->rate = FL(0.0); a->state = SUSTAIN; } } else if (a->state==RELEASE) { a->value -= a->releaseRate; if (a->value <= FL(0.0)) { a->value = FL(0.0); a->state = CLEAR; } } return a->value; } /*******************************************/ /* BiQuad (2-pole, 2-zero) Filter Class, */ /* by Perry R. Cook, 1995-96 */ /* See books on filters to understand */ /* more about how this works. Nothing */ /* out of the ordinary in this version. */ /*******************************************/ void make_BiQuad(BiQuad *b) { b->zeroCoeffs[0] = FL(0.0); b->zeroCoeffs[1] = FL(0.0); b->poleCoeffs[0] = FL(0.0); b->poleCoeffs[1] = FL(0.0); b->gain = FL(1.0); /* BiQuad_clear(b); */ b->inputs[0] = FL(0.0); b->inputs[1] = FL(0.0); b->lastOutput = FL(0.0); } void BiQuad_clear(BiQuad *b) { b->inputs[0] = FL(0.0); b->inputs[1] = FL(0.0); b->lastOutput = FL(0.0); } void BiQuad_setPoleCoeffs(BiQuad *b, MYFLT *coeffs) { b->poleCoeffs[0] = coeffs[0]; b->poleCoeffs[1] = coeffs[1]; } void BiQuad_setZeroCoeffs(BiQuad *b, MYFLT *coeffs) { b->zeroCoeffs[0] = coeffs[0]; b->zeroCoeffs[1] = coeffs[1]; } MYFLT BiQuad_tick(BiQuad *b, MYFLT sample) /* Perform Filter Operation */ { /* Biquad is two pole, two zero filter */ MYFLT temp; /* Look it up in your favorite DSP text */ temp = sample * b->gain; /* Here's the math for the */ temp += b->inputs[0] * b->poleCoeffs[0]; /* version which implements */ temp += b->inputs[1] * b->poleCoeffs[1]; /* only 2 state variables. */ b->lastOutput = temp; /* This form takes */ b->lastOutput += (b->inputs[0] * b->zeroCoeffs[0]); /* 5 multiplies and */ b->lastOutput += (b->inputs[1] * b->zeroCoeffs[1]); /* 4 adds */ b->inputs[1] = b->inputs[0]; /* and 3 moves */ b->inputs[0] = temp; /* like the 2 state-var form */ return b->lastOutput; } csound-6.10.0/Opcodes/physutil.h000066400000000000000000000167661321653344700165470ustar00rootroot00000000000000/* physutil.h: Copyright (C) 1996, 1997 Perry Cook, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #if !defined(__PhysUtil_h) #define __PhysUtil_h /* Various filters etc for Physical models */ #include #define AMP_SCALE (csound->e0dbfs) #define AMP_RSCALE (csound->dbfs_to_float) /*******************************************/ /* Noise Generator Class, */ /* by Perry R. Cook, 1995-96 */ /* White noise as often as you like. */ /* Recoded by John ffitch 1997 */ /*******************************************/ typedef MYFLT Noise; #define make_Noise(n) n = FL(0.0) MYFLT Noise_tick(CSOUND *, Noise *); #define Noise_lastOut(n) (n) /*******************************************/ /* Linearly Interpolating Delay Line */ /* Object by Perry R. Cook 1995-96 */ /* Recoded by John ffitch 1997 */ /*******************************************/ typedef struct DLineL{ AUXCH inputs; MYFLT lastOutput; int32 inPoint; int32 outPoint; int32 length; MYFLT alpha; MYFLT omAlpha; } DLineL; #define DLineL_lastOut(d) ((d)->lastOutput) void make_DLineL(CSOUND *,DLineL *, int32); void DLineL_setDelay(DLineL *, MYFLT); MYFLT DLineL_tick(DLineL *, MYFLT); /*******************************************/ /* Envelope Class, Perry R. Cook, 1995-96 */ /* This is the base class for envelopes. */ /* This one is capable of ramping state */ /* from where it is to a target value by */ /* a rate. It also responds to simple */ /* KeyOn and KeyOff messages, ramping to */ /* 1.0 on keyon and to 0.0 on keyoff. */ /* There are two tick (update value) */ /* methods, one returns the value, and */ /* other returns 0 if the envelope is at */ /* the target value (the state bit). */ /*******************************************/ #define RATE_NORM (FL(22050.0)/csound->esr) typedef struct Envelope { MYFLT value; MYFLT target; MYFLT rate; int state; } Envelope; void make_Envelope(Envelope*); void Envelope_keyOn(Envelope*); void Envelope_keyOff(Envelope*); void Envelope_setRate(CSOUND *,Envelope*, MYFLT); void Envelope_setTarget(Envelope*, MYFLT); void Envelope_setValue(Envelope*,MYFLT); MYFLT Envelope_tick(Envelope*); void Envelope_print(CSOUND *,Envelope*); /*******************************************/ /* One Pole Filter Class, */ /* by Perry R. Cook, 1995-96 */ /* The parameter gain is an additional */ /* gain parameter applied to the filter */ /* on top of the normalization that takes */ /* place automatically. So the net max */ /* gain through the system equals the */ /* value of gain. sgain is the combina- */ /* tion of gain and the normalization */ /* parameter, so if you set the poleCoeff */ /* to alpha, sgain is always set to */ /* gain * (1.0 - fabs(alpha)). */ /*******************************************/ typedef struct OnePole { MYFLT gain; /* Start Filter subclass */ MYFLT outputs; /* MYFLT *inputs; */ /* MYFLT lastOutput; */ /* End */ MYFLT poleCoeff; MYFLT sgain; } OnePole; void make_OnePole(OnePole*); /* void OnePole_clear(OnePole*); */ void OnePole_setPole(OnePole*, MYFLT aValue); void OnePole_setGain(OnePole*, MYFLT aValue); MYFLT OnePole_tick(OnePole*, MYFLT sample); void OnePole_print(CSOUND*, OnePole*); /*******************************************/ /* DC Blocking Filter */ /* by Perry R. Cook, 1995-96 */ /* This guy is very helpful in, uh, */ /* blocking DC. Needed because a simple */ /* low-pass reflection filter allows DC */ /* to build up inside recursive */ /* structures. */ /*******************************************/ typedef struct DCBlock { MYFLT gain; MYFLT outputs; MYFLT inputs; /* MYFLT lastOutput; */ } DCBlock; void make_DCBlock(DCBlock*); /* void DCBlock_clear(DCBlock*); */ MYFLT DCBlock_tick(DCBlock*, MYFLT); /*******************************************/ /* ADSR Subclass of the Envelope Class, */ /* by Perry R. Cook, 1995-96 */ /* This is the traditional ADSR (Attack */ /* Decay, Sustain, Release) envelope. */ /* It responds to simple KeyOn and KeyOff */ /* messages, keeping track of it's state. */ /* There are two tick (update value) */ /* methods, one returns the value, and */ /* other returns the state (0 = A, 1 = D, */ /* 2 = S, 3 = R) */ /*******************************************/ #define ATTACK (0) #define DECAY (1) #define SUSTAIN (2) #define RELEASE (3) #define CLEAR (4) typedef struct ADSR { MYFLT value; /* Envelope subclass */ MYFLT target; MYFLT rate; int state; /* end */ MYFLT attackRate; MYFLT decayRate; MYFLT sustainLevel; MYFLT releaseRate; } ADSR; void make_ADSR(ADSR*); void dest_ADSR(ADSR*); void ADSR_keyOn(ADSR*); void ADSR_keyOff(ADSR*); void ADSR_setAttackRate(CSOUND *,ADSR*, MYFLT); void ADSR_setDecayRate(CSOUND *,ADSR*, MYFLT); void ADSR_setSustainLevel(CSOUND *,ADSR*, MYFLT); void ADSR_setReleaseRate(CSOUND *,ADSR*, MYFLT); void ADSR_setAll(CSOUND *,ADSR*, MYFLT, MYFLT, MYFLT, MYFLT); void ADSR_setAllTimes(CSOUND *,ADSR*, MYFLT, MYFLT, MYFLT, MYFLT); void ADSR_setTarget(CSOUND *,ADSR*, MYFLT); void ADSR_setValue(CSOUND *,ADSR*, MYFLT); MYFLT ADSR_tick(ADSR*); int ADSR_informTick(ADSR*); MYFLT ADSR_lastOut(ADSR*); /*******************************************/ /* BiQuad (2-pole, 2-zero) Filter Class, */ /* by Perry R. Cook, 1995-96 */ /* See books on filters to understand */ /* more about how this works. Nothing */ /* out of the ordinary in this version. */ /*******************************************/ typedef struct BiQuad { MYFLT gain; /* Start if filter subclass */ MYFLT inputs[2]; MYFLT lastOutput; /* End */ MYFLT poleCoeffs[2]; MYFLT zeroCoeffs[2]; } BiQuad; void make_BiQuad(BiQuad*); void dest_BiQuad(BiQuad*); void BiQuad_clear(BiQuad*); void BiQuad_setPoleCoeffs(BiQuad*, MYFLT *); void BiQuad_setZeroCoeffs(BiQuad*, MYFLT *); #define BiQuad_setGain(b,aValue) ((b).gain = aValue) #define BiQuad_setEqualGainZeroes(b) \ { (b).zeroCoeffs[1] = -FL(1.0); (b).zeroCoeffs[0] = FL(0.0); } #define BiQuad_setFreqAndReson(b,freq,reson) \ { (b).poleCoeffs[1]= -((reson)*(reson)); \ (b).poleCoeffs[0]= FL(2.0)*(reson)*\ (MYFLT)cos((double)(freq)*(double)csound->tpidsr); } MYFLT BiQuad_tick(BiQuad*, MYFLT); #define BiQuad_lastOut(x) (x)->lastOutput #endif csound-6.10.0/Opcodes/pinker.c000066400000000000000000000141501321653344700161320ustar00rootroot00000000000000/* pink.c New Shade of Pink (c) 2014 Stefan Stenzel stefan at waldorfmusic.de Terms of use: Use for any purpose. If used in a commercial product, you should give me one. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - some temporary bias required for hack on floats Implemented in Csound by John ffitch Copyright (C) 2014 Stefan Stenzel, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* PINKER.C */ typedef struct { OPDS h; MYFLT *ar; int inc; int dec; int32 accu; int32 lfsr; unsigned char cnt; int offset; } PINKER; #define PINK_BIAS FL(440.0) static int instance_cnt = 0; /* Is tis thread-safe? */ // Let preprocessor and compiler calculate two lookup tables for 12-tap // FIR filter with these coefficients: // 1.190566,0.162580, 0.002208,0.025475,-0.001522,0.007322, // 0.001774,0.004529,-0.001561,0.000776,-0.000486,0.002017 #define F(cf,m,shift) (0.0625f*cf*(2*((m)>>shift&1)-1)) #define FA(n) F(1.190566,n,0)+F(0.162580,n,1)+F(0.002208,n,2)+ \ F(0.025475,n,3)+F(-0.001522,n,4)+F(0.007322,n,5)-PINK_BIAS #define FB(n) F(0.001774,n,0)+F(0.004529,n,1)+F(-0.001561,n,2)+ \ F(0.000776,n,3)+F(-0.000486,n,4)+F(0.002017,n,5) #define FA8(n) FA(n),FA(n+1),FA(n+2),FA(n+3),FA(n+4),FA(n+5),FA(n+6),FA(n+7) #define FB8(n) FB(n),FB(n+1),FB(n+2),FB(n+3),FB(n+4),FB(n+5),FB(n+6),FB(n+7) // 1st FIR lookup table static const float pfira[64] = {FA8(0) ,FA8(8), FA8(16),FA8(24), FA8(32),FA8(40),FA8(48),FA8(56)}; // 2nd FIR lookup table static const float pfirb[64] = {FB8(0), FB8(8), FB8(16),FB8(24), FB8(32),FB8(40),FB8(48),FB8(56)}; // bitreversed lookup table #define PM16(n) n,0x80,0x40,0x80,0x20,0x80,0x40,0x80, \ 0x10,0x80,0x40,0x80,0x20,0x80,0x40,0x80 static const unsigned char pnmask[256] = { PM16(0x00),PM16(0x08),PM16(0x04),PM16(0x08), PM16(0x02),PM16(0x08),PM16(0x04),PM16(0x08), PM16(0x01),PM16(0x08),PM16(0x04),PM16(0x08), PM16(0x02),PM16(0x08),PM16(0x04),PM16(0x08) }; static const int ind[] = { 0, 0x0800, 0x0400, 0x0800, 0x0200, 0x0800, 0x0400, 0x0800, 0x0100, 0x0800, 0x0400, 0x0800, 0x0200, 0x0800, 0x0400, 0x0800}; /* generate samples of pink noise */ static int pink_perf(CSOUND* csound, PINKER *p) { int inc = p->inc; int dec = p->dec; int32 accu = p->accu; int32 lfsr = p->lfsr; int cnt = p->cnt; int bit; int n, nn, nsmps = csound->ksmps; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; int mask; float yy; MYFLT *out = p->ar; int loffset = p->offset; if (UNLIKELY(early)) { nsmps -= early; } for (n=offset, nn=loffset; n> 31; dec &= ~0x0800; */ /* lfsr <<= 1; dec |= inc & 0x0800; */ /* inc ^= bit & 0x0800; accu -= dec; */ /* lfsr ^= bit & 0x46000001; accu += inc; */ /* leftOut[i+1] = accu * pscale + pflta[lfsr & 0x3F] + pfltb[lfsr >> 6 & 0x3F]; */ if (k==0) mask = pnmask[cnt++]; else mask = ind[k]; bit = lfsr >> 31; /* spill random to all bits */ dec &= ~mask; /* blank old decrement bit */ lfsr <<= 1; /* shift lfsr */ dec |= inc & mask; /* copy increment to decrement bit */ inc ^= bit & mask; /* new random bit */ *((int *)(&yy)) = accu; /* save biased value as float */ //printf("yy = %f ", yy); accu += inc - dec; /* integrate */ lfsr ^= bit & 0x46000001; /* update lfsr */ yy += pfira[lfsr & 0x3F] /* add 1st half precalculated FIR */ + pfirb[lfsr >>6 & 0x3F]; /* add 2nd half, also corrects bias */ //printf("out = %f a,b = %f,%f mask = %.8x dec,inc = %x,%x acc = %x\n", // yy, pfira[lfsr & 0x3F], pfirb[lfsr >>6 & 0x3F], // mask, dec, inc, accu); out[n] = yy*csound->e0dbfs; /* PINK(mask); PINK(0x0800); PINK(0x0400); PINK(0x0800); */ /* PINK(0x0200); PINK(0x0800); PINK(0x0400); PINK(0x0800); */ /* PINK(0x0100); PINK(0x0800); PINK(0x0400); PINK(0x0800); */ /* PINK(0x0200); PINK(0x0800); PINK(0x0400); PINK(0x0800); */ } p->inc = inc; // write back variables p->dec = dec; p->accu = accu; p->lfsr = lfsr; p->cnt = cnt; p->offset = nn%16; return OK; }; static int pink_init(CSOUND *csund, PINKER *p) // constructor { p->lfsr = 0x5EED41F5 + instance_cnt++; // seed for lfsr, // decorrelate multiple instances *((float*)(&p->accu)) = PINK_BIAS; // init float hack p->cnt = 0; // counter from zero p->inc = 0x0CCC; // balance initial states to avoid DC p->dec = 0x0CCC; p->offset = 0; return OK; } static OENTRY pinker_localops[] = { { "pinker", sizeof(PINKER),0,5, "a", "", (SUBR)pink_init, NULL, (SUBR)pink_perf } }; LINKAGE_BUILTIN(pinker_localops) csound-6.10.0/Opcodes/pitch.c000066400000000000000000002312211321653344700157510ustar00rootroot00000000000000 /* pitch.c: Copyright (C) 1999 John ffitch, Istvan Varga, Peter Neubäcker, rasmus ekman, Phil Burk This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // #include "csdl.h" #include "csoundCore.h" /* PITCH.C */ #include #include #include "cwindow.h" #include "spectra.h" #include "pitch.h" #include "uggab.h" #define STARTING 1 #define PLAYING 2 #define LOGTWO (0.69314718055994530942) static inline int32 MYFLOOR(MYFLT x) { if (x >= 0.0) { return (int32) x; } else { return (int32) (x - FL(0.99999999)); } } static const MYFLT bicoefs[] = { -FL(0.2674054), FL(0.7491305), FL(0.7160484), FL(0.0496285), FL(0.7160484), FL(0.0505247), FL(0.3514850), FL(0.5257536), FL(0.3505025), FL(0.5257536), FL(0.3661840), FL(0.0837990), FL(0.3867783), FL(0.6764264), FL(0.3867783) }; #define rand_31(x) (x->Rand31(&(x->randSeed1)) - 1) int pitchset(CSOUND *csound, PITCH *p) /* pitch - uses spectra technology */ { double b; /* For RMS */ int n, nocts, nfreqs, ncoefs; MYFLT Q, *fltp; OCTDAT *octp; DOWNDAT *dwnp = &p->downsig; SPECDAT *specp = &p->wsig; int32 npts, nptls, nn, lobin; int *dstp, ptlmax; MYFLT fnfreqs, rolloff, *oct0p, *flop, *fhip, *fundp, *fendp, *fp; MYFLT weight, weightsum, dbthresh, ampthresh; /* RMS of input signal */ b = 2.0 - cos(10.0*(double)csound->tpidsr); p->c2 = b - sqrt(b * b - 1.0); p->c1 = 1.0 - p->c2; if (!*p->istor) p->prvq = 0.0; /* End of rms */ /* Initialise spectrum */ /* for mac roundoff */ p->timcount = (int)(CS_EKR * *p->iprd + FL(0.001)); nocts = (int)*p->iocts; if (UNLIKELY(nocts<=0)) nocts = 6; nfreqs = (int)*p->ifrqs; if (UNLIKELY(nfreqs<=0)) nfreqs = 12; ncoefs = nocts * nfreqs; Q = *p->iq; if (UNLIKELY(Q<=FL(0.0))) Q = FL(15.0); if (UNLIKELY(p->timcount <= 0)) return csound->InitError(csound, Str("illegal iprd")); if (UNLIKELY(nocts > MAXOCTS)) return csound->InitError(csound, Str("illegal iocts")); if (UNLIKELY(nfreqs > MAXFRQS)) return csound->InitError(csound, Str("illegal ifrqs")); if (nocts != dwnp->nocts || nfreqs != p->nfreqs || /* if anything has changed */ Q != p->curq ) { /* make new tables */ double basfrq, curfrq, frqmlt, Qfactor; double theta, a, windamp, onedws, pidws; MYFLT *sinp, *cosp; int k, sumk, windsiz, halfsiz, *wsizp, *woffp; int32 auxsiz, bufsiz; int32 majr, minr, totsamps; double hicps,locps,oct; /* must alloc anew */ p->nfreqs = nfreqs; p->curq = Q; p->ncoefs = ncoefs; dwnp->srate = CS_ESR; hicps = dwnp->srate * 0.375; /* top freq is 3/4 pi/2 ... */ oct = log(hicps / ONEPT) / LOGTWO; /* octcps() (see aops.c) */ dwnp->looct = (MYFLT)(oct - nocts); /* true oct val of lowest frq */ locps = hicps / (1L << nocts); basfrq = hicps * 0.5; /* oct below retuned top */ frqmlt = pow(2.0,1.0/(double)nfreqs); /* nfreq interval mult */ Qfactor = Q * dwnp->srate; curfrq = basfrq; for (sumk=0,wsizp=p->winlen,woffp=p->offset,n=nfreqs; n--; ) { *wsizp++ = k = (int)(Qfactor/curfrq) | 01; /* calc odd wind sizes */ *woffp++ = (*(p->winlen) - k) / 2; /* & symmetric offsets */ sumk += k; /* and find total */ curfrq *= frqmlt; } windsiz = *(p->winlen); auxsiz = (windsiz + 2*sumk) * sizeof(MYFLT); /* calc lcl space rqd */ csound->AuxAlloc(csound, (size_t)auxsiz, &p->auxch1); /* & alloc auxspace */ fltp = (MYFLT *) p->auxch1.auxp; p->linbufp = fltp; fltp += windsiz; /* linbuf must take nsamps */ p->sinp = sinp = fltp; fltp += sumk; p->cosp = cosp = fltp; /* cos gets rem sumk */ wsizp = p->winlen; curfrq = basfrq * TWOPI / dwnp->srate; for (n = nfreqs; n--; ) { /* now fill tables */ windsiz = *wsizp++; /* (odd win size) */ halfsiz = windsiz >> 1; onedws = 1.0 / (windsiz-1); pidws = PI / (windsiz-1); for (k = -halfsiz; k<=halfsiz; k++) { /* with sines */ a = cos(k * pidws); windamp = 0.08 + 0.92 * a * a; /* times hamming */ windamp *= onedws; /* scaled */ theta = k * curfrq; *sinp++ = (MYFLT)(windamp * sin(theta)); *cosp++ = (MYFLT)(windamp * cos(theta)); } curfrq *= frqmlt; /* step by log freq */ } dwnp->hifrq = (MYFLT)hicps; dwnp->lofrq = (MYFLT)locps; dwnp->nsamps = windsiz = *(p->winlen); dwnp->nocts = nocts; minr = windsiz >> 1; /* sep odd windsiz into maj, min */ majr = windsiz - minr; /* & calc totsamps reqd */ totsamps = (majr*nocts) + (minr<auxch.auxp; /* & distrib to octdata */ for (n=nocts,octp=dwnp->octdata+(nocts-1); n--; octp--) { bufsiz = majr + minr; octp->begp = fltp; fltp += bufsiz; /* (lo oct first) */ octp->endp = fltp; minr *= 2; } SPECset(csound, specp, (int32)ncoefs);/* prep the spec dspace */ specp->downsrcp = dwnp; /* & record its source */ } for (octp=dwnp->octdata; nocts--; octp++) { /* reset all oct params, & */ octp->curp = octp->begp; memset(octp->feedback, '\0', 6*sizeof(MYFLT)); octp->scount = 0; } specp->nfreqs = p->nfreqs; /* save the spec descriptors */ specp->dbout = 0; specp->ktimstamp = 0; /* init specdata to not new */ specp->ktimprd = p->timcount; p->scountdown = p->timcount; /* prime the spect countdown */ /* Start specptrk */ if ((npts = specp->npts) != p->winpts) { /* if size has changed */ SPECset(csound, &p->wfund, (int32)npts); /* realloc for wfund */ p->wfund.downsrcp = specp->downsrcp; p->fundp = (MYFLT *) p->wfund.auxch.auxp; p->winpts = npts; } if (UNLIKELY(*p->inptls<=FL(0.0))) nptls = 4; else nptls = (int32)*p->inptls; if (UNLIKELY(nptls > MAXPTL)) { return csound->InitError(csound, Str("illegal no of partials")); } if (UNLIKELY(*p->irolloff<=FL(0.0))) p->rolloff = FL(0.6); else p->rolloff = *p->irolloff; p->nptls = nptls; /* number, whether all or odd */ ptlmax = nptls; dstp = p->pdist; fnfreqs = (MYFLT)specp->nfreqs; for (nn = 1; nn <= ptlmax; nn++) *dstp++ = (int) ((LOG((MYFLT) nn) / (MYFLT)LOGTWO) * fnfreqs + FL(0.5)); if (UNLIKELY((rolloff = p->rolloff) == FL(0.0) || rolloff == FL(1.0) || nptls == 1)) { p->rolloff = FL(0.0); weightsum = (MYFLT)nptls; } else { MYFLT *fltp = p->pmult; MYFLT octdrop = (FL(1.0) - rolloff) / fnfreqs; weightsum = FL(0.0); for (dstp = p->pdist, nn = nptls; nn--; ) { weight = FL(1.0) - octdrop * *dstp++; /* rolloff * octdistance */ weightsum += weight; *fltp++ = weight; } if (UNLIKELY(*--fltp < FL(0.0))) { return csound->InitError(csound, Str("per octave rolloff too steep")); } p->rolloff = 1; } lobin = (int32)(specp->downsrcp->looct * fnfreqs); oct0p = p->fundp - lobin; /* virtual loc of oct 0 */ flop = oct0p + (int)(*p->ilo * fnfreqs); fhip = oct0p + (int)(*p->ihi * fnfreqs); fundp = p->fundp; fendp = fundp + specp->npts; if (flop < fundp) flop = fundp; if (UNLIKELY(fhip > fendp)) fhip = fendp; if (UNLIKELY(flop >= fhip)) { /* chk hi-lo range valid */ return csound->InitError(csound, Str("illegal lo-hi values")); } for (fp = fundp; fp < flop; ) *fp++ = FL(0.0); /* clear unused lo and hi range */ for (fp = fhip; fp < fendp; ) *fp++ = FL(0.0); dbthresh = *p->idbthresh; /* thresholds: */ ampthresh = (MYFLT)exp((double)dbthresh * LOG10D20); p->threshon = ampthresh; /* mag */ p->threshoff = ampthresh * FL(0.5); p->threshon *= weightsum; p->threshoff *= weightsum; p->oct0p = oct0p; /* virtual loc of oct 0 */ p->confact = *p->iconf; p->flop = flop; p->fhip = fhip; p->playing = 0; p->kvalsav = (*p->istrt>=FL(0.0) ? *p->istrt : (*p->ilo+*p->ihi)*FL(0.5)); p->kval = p->kinc = FL(0.0); p->kavl = p->kanc = FL(0.0); p->jmpcount = 0; return OK; } int pitch(CSOUND *csound, PITCH *p) { MYFLT *asig; double q; double c1 = p->c1, c2 = p->c2; MYFLT a, b, *dftp, SIG, yt1, yt2; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int nocts, winlen; DOWNDAT *downp = &p->downsig; OCTDAT *octp; SPECDAT *specp; MYFLT c; MYFLT kvar; /* RMS */ q = p->prvq; asig = p->asig; if (UNLIKELY(offset)) memset(asig, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&asig[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; ne0dbfs; /* Normalise.... */ q = c1 * as * as + c2 * q; SIG = as; /* for each source sample: */ octp = downp->octdata; /* align onto top octave */ nocts = downp->nocts; do { /* then for each oct: */ const MYFLT *coefp; MYFLT *ytp, *curp; int nfilt; curp = octp->curp; *curp++ = SIG; /* write samp to cur buf */ if (UNLIKELY(curp >= octp->endp)) curp = octp->begp; /* & modulo the pointer */ octp->curp = curp; if (UNLIKELY(!(--nocts))) break; /* if lastoct, break */ coefp = bicoefs; ytp = octp->feedback; for (nfilt = 3; nfilt--; ) { /* apply triple biquad: */ yt2 = *ytp++; yt1 = *ytp--; /* get prev feedback */ SIG -= (*coefp++ * yt1); /* apply recurs filt */ SIG -= (*coefp++ * yt2); *ytp++ = yt1; *ytp++ = SIG; /* stor nxt feedback */ SIG *= *coefp++; SIG += (*coefp++ * yt1); /* apply forwrd filt */ SIG += (*coefp++ * yt2); } } while (!(++octp->scount & 01) && octp++); /* send alt samps to nxtoct */ } p->prvq = q; kvar = SQRT((MYFLT)q); /* End of spectrum part */ specp = &p->wsig; if (LIKELY((--p->scountdown))) goto nxt; /* if not yet time for new spec */ p->scountdown = p->timcount; /* else reset counter & proceed: */ downp = &p->downsig; nocts = downp->nocts; octp = downp->octdata + nocts; dftp = (MYFLT *) specp->auxch.auxp; winlen = *(p->winlen); while (nocts--) { MYFLT *bufp, *sinp, *cosp; int len, *lenp, *offp, nfreqs; MYFLT *begp, *curp, *endp, *linbufp; int len2; octp--; /* for each oct (low to high) */ begp = octp->begp; curp = octp->curp; endp = octp->endp; if (UNLIKELY((len = endp - curp) >= winlen)) /* if no wrap */ linbufp = curp; /* use samples in circbuf */ else { len2 = winlen - len; linbufp = bufp = p->linbufp; /* else cp crcbuf to linbuf */ while (len--) *bufp++ = *curp++; curp = begp; while (len2--) *bufp++ = *curp++; } cosp = p->cosp; /* get start windowed sines */ sinp = p->sinp; lenp = p->winlen; offp = p->offset; for (nfreqs=p->nfreqs; nfreqs--; ) { /* now for ea. frq this oct */ a = FL(0.0); b = FL(0.0); bufp = linbufp + *offp++; for (len = *lenp++; len--; bufp++) { /* apply windowed sine seg */ a += *bufp * *cosp++; b += *bufp * *sinp++; } c = HYPOT(a, b); /* get magnitude */ *dftp++ = c; /* store in out spectrum */ } } specp->ktimstamp = CS_KCNT; /* time-stamp the output */ nxt: /* specptrk */ { MYFLT *inp = (MYFLT *) specp->auxch.auxp; MYFLT *endp = inp + specp->npts; MYFLT *inp2, sum, *fp; int nn, *pdist, confirms; MYFLT kval, fmax, *fmaxp, absdiff, realbin; MYFLT *flop, *fhip, *ilop, *ihip, a, b, c, denom, delta; int32 lobin, hibin; if (UNLIKELY(inp==NULL)) goto err1; /* RWD fix */ kval = p->playing == PLAYING ? p->kval : p->kvalsav; lobin = (int32)((kval - kvar) * specp->nfreqs);/* set lims of frq interest */ hibin = (int32)((kval + kvar) * specp->nfreqs); if ((flop = p->oct0p + lobin) < p->flop) /* as fundp bin pntrs */ flop = p->flop; if ((fhip = p->oct0p + hibin) > p->fhip) /* within hard limits */ fhip = p->fhip; ilop = inp + (flop - p->fundp); /* similar for input bins */ ihip = inp + (fhip - p->fundp); inp = ilop; fp = flop; if (p->rolloff) { MYFLT *pmult; do { sum = *inp; pdist = p->pdist + 1; pmult = p->pmult + 1; for (nn = p->nptls; --nn; ) { if ((inp2 = inp + *pdist++) >= endp) break; sum += *inp2 * *pmult++; } *fp++ = sum; } while (++inp < ihip); } else { do { sum = *inp; pdist = p->pdist + 1; for (nn = p->nptls; --nn; ) { if ((inp2 = inp + *pdist++) >= endp) break; sum += *inp2; } *fp++ = sum; } while (++inp < ihip); } fp = flop; /* now srch fbins for peak */ for (fmaxp = fp, fmax = *fp; ++fp fmax)) { fmax = *fp; fmaxp = fp; } if (!p->playing) { if (fmax > p->threshon) /* not playing & threshon? */ p->playing = STARTING; /* prepare to turn on */ else goto output; } else { if (fmax < p->threshoff) { /* playing & threshoff ? */ if (p->playing == PLAYING) p->kvalsav = p->kval; /* save val & turn off */ p->kval = FL(0.0); p->kavl = FL(0.0); p->kinc = FL(0.0); p->kanc = FL(0.0); p->playing = 0; goto output; } } a = fmaxp>flop ? *(fmaxp-1) : FL(0.0); /* calc a refined bin no */ b = fmax; c = fmaxpoct0p) + delta; /* get modified bin number */ kval = realbin / specp->nfreqs; /* & cvt to true decoct */ if (p->playing == STARTING) { /* STARTING mode: */ absdiff = FABS(kval - p->kvalsav);// < FL(0.0)) absdiff = -absdiff; confirms = (int)(absdiff * p->confact); /* get interval dependency */ if (UNLIKELY(p->jmpcount < confirms)) { p->jmpcount += 1; /* if not enough confirms, */ goto output; /* must wait some more */ } else { p->playing = PLAYING; /* else switch on playing */ p->jmpcount = 0; p->kval = kval; /* but suppress interp */ p->kinc = FL(0.0); } } else { /* PLAYING mode: */ absdiff = FABS(kval - p->kval); confirms = (int)(absdiff * p->confact); /* get interval dependency */ if (p->jmpcount < confirms) { p->jmpcount += 1; /* if not enough confirms, */ p->kinc = FL(0.0); /* must wait some more */ } else { p->jmpcount = 0; /* else OK to jump interval */ p->kval = kval; } } fmax += delta * (c - a) * FL(0.25); /* get modified amp */ p->kavl = fmax; } output: *p->koct = p->kval; /* output true decoct & amp */ *p->kamp = p->kavl * FL(4.0); return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("pitch: not initialised")); } /* Multiply and accumulate opcodes */ int macset(CSOUND *csound, SUM *p) { if (UNLIKELY((((int)p->INOCOUNT)&1)==1)) { return csound->PerfError(csound, p->h.insdshead, Str("Must have even number of arguments in mac\n")); } return OK; } int maca(CSOUND *csound, SUM *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t k, nsmps = CS_KSMPS; int count=(int) p->INOCOUNT, j; MYFLT *ar = p->ar, **args = p->argums; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (k=offset; kh.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t k, nsmps = CS_KSMPS; int count=(int) p->INOCOUNT, j; MYFLT *ar = p->ar, **args = p->argums; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (k=offset; kQueryGlobalVariable(csound, "readClock::counters"); if (UNLIKELY(*p == NULL)) { csound->CreateGlobalVariable(csound, "readClock::counters", sizeof(CPU_CLOCK)); *p = csound->QueryGlobalVariable(csound, "readClock::counters"); csound->InitTimerStruct(&(((CPU_CLOCK*) (*p))->r)); } } static inline CPU_CLOCK *getClockStruct(CSOUND *csound, void **p) { if (UNLIKELY(*p == NULL)) initClockStruct(csound, p); return (CPU_CLOCK*) (*p); } int clockset(CSOUND *csound, CLOCK *p) { p->c = (int)*p->cnt; if (UNLIKELY(p->c < 0 || p->c > 31)) p->c = 32; return OK; } int clockon(CSOUND *csound, CLOCK *p) { CPU_CLOCK *clk = getClockStruct(csound, &(p->clk)); if (LIKELY(!clk->running[p->c])) { clk->running[p->c] = 1; clk->counters[p->c] -= csound->GetCPUTime(&(clk->r)); } return OK; } int clockoff(CSOUND *csound, CLOCK *p) { CPU_CLOCK *clk = getClockStruct(csound, &(p->clk)); if (LIKELY(clk->running[p->c])) { clk->running[p->c] = 0; clk->counters[p->c] += csound->GetCPUTime(&(clk->r)); } return OK; } int clockread(CSOUND *csound, CLKRD *p) { CPU_CLOCK *clk = getClockStruct(csound, &(p->clk)); int cnt = (int) *p->a; if (UNLIKELY(cnt < 0 || cnt > 32)) cnt = 32; if (UNLIKELY(clk->running[cnt])) return csound->InitError(csound, Str("clockread: clock still running, " "call clockoff first")); /* result in ms */ printf("readclock%d: %g\n", cnt, clk->counters[cnt]); *p->r = (MYFLT) (clk->counters[cnt] * 1000.0); return OK; } int scratchread(CSOUND *csound, SCRATCHPAD *p) { int index = MYFLT2LRND(*p->index); if (index<0 || index>3) return csound->PerfError(csound, p->h.insdshead, Str("scratchpad index out of range")); *p->val = p->h.insdshead->scratchpad[index]; return OK; } int scratchwrite(CSOUND *csound, SCRATCHPAD *p) { int index = MYFLT2LRND(*p->index); if (index<0 || index>3) return csound->PerfError(csound, p->h.insdshead, Str("scratchpad index out of range")); p->h.insdshead->scratchpad[index] = *p->val; return OK; } /* ************************************************************ */ /* Opcodes from Peter Neubäcker */ /* ************************************************************ */ int adsyntset(CSOUND *csound, ADSYNT *p) { FUNC *ftp; unsigned int count; int32 *lphs; p->inerr = 0; if (LIKELY((ftp = csound->FTFind(csound, p->ifn)) != NULL)) { p->ftp = ftp; } else { p->inerr = 1; return csound->InitError(csound, Str("adsynt: wavetable not found!")); } count = (unsigned int)*p->icnt; if (UNLIKELY(count < 1)) count = 1; p->count = count; if (LIKELY((ftp = csound->FTnp2Find(csound, p->ifreqtbl)) != NULL)) { p->freqtp = ftp; } else { p->inerr = 1; return csound->InitError(csound, Str("adsynt: freqtable not found!")); } if (UNLIKELY(ftp->flen < count)) { p->inerr = 1; return csound->InitError(csound, Str( "adsynt: partial count is greater than freqtable size!")); } if (LIKELY((ftp = csound->FTnp2Find(csound, p->iamptbl)) != NULL)) { p->amptp = ftp; } else { p->inerr = 1; return csound->InitError(csound, Str("adsynt: amptable not found!")); } if (UNLIKELY(ftp->flen < count)) { p->inerr = 1; return csound->InitError(csound, Str( "adsynt: partial count is greater than amptable size!")); } if (p->lphs.auxp==NULL || p->lphs.size < (size_t)sizeof(int32)*count) csound->AuxAlloc(csound, sizeof(int32)*count, &p->lphs); lphs = (int32*)p->lphs.auxp; if (*p->iphs > 1) { do { *lphs++ = ((int32) ((MYFLT) ((double) rand_31(csound) / 2147483645.0) * FMAXLEN)) & PHMASK; } while (--count); } else if (*p->iphs >= 0) { do { *lphs++ = ((int32) (*p->iphs * FMAXLEN)) & PHMASK; } while (--count); } return OK; } int adsynt(CSOUND *csound, ADSYNT *p) { FUNC *ftp, *freqtp, *amptp; MYFLT *ar, *ftbl, *freqtbl, *amptbl; MYFLT amp0, amp, cps0, cps; int32 phs, inc, lobits; int32 *lphs; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int c, count; if (UNLIKELY(p->inerr)) { return csound->PerfError(csound, p->h.insdshead, Str("adsynt: not initialised")); } ftp = p->ftp; ftbl = ftp->ftable; lobits = ftp->lobits; freqtp = p->freqtp; freqtbl = freqtp->ftable; amptp = p->amptp; amptbl = amptp->ftable; lphs = (int32*)p->lphs.auxp; cps0 = *p->kcps; amp0 = *p->kamp; count = p->count; ar = p->sr; memset(ar, 0, nsmps*sizeof(MYFLT)); if (UNLIKELY(early)) nsmps -= early; for (c=0; csicvt); phs = lphs[c]; for (n=offset; n> lobits)) * amp; phs += inc; phs &= PHMASK; } lphs[c] = phs; } return OK; } int hsboscset(CSOUND *csound, HSBOSC *p) { FUNC *ftp; int octcnt, i; if (LIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) != NULL)) { p->ftp = ftp; if (UNLIKELY(*p->ioctcnt < 2)) octcnt = 3; else octcnt = (int)*p->ioctcnt; if (UNLIKELY(octcnt > 10)) octcnt = 10; p->octcnt = octcnt; if (*p->iphs >= 0) { for (i=0; ilphs[i] = ((int32)(*p->iphs * FMAXLEN)) & PHMASK; } } else p->ftp = NULL; if (LIKELY((ftp = csound->FTnp2Find(csound, p->imixtbl)) != NULL)) { p->mixtp = ftp; } else p->mixtp = NULL; return OK; } int hsboscil(CSOUND *csound, HSBOSC *p) { FUNC *ftp, *mixtp; MYFLT fract, v1, amp0, amp, *ar, *ftab, *mtab; int32 phs, inc, lobits; int32 phases[10]; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT tonal, bright, freq, ampscl; int octcnt = p->octcnt; MYFLT octstart, octoffs, octbase; int octshift, i, mtablen; MYFLT hesr = CS_ESR / FL(2.0); ftp = p->ftp; mixtp = p->mixtp; if (UNLIKELY(ftp==NULL || mixtp==NULL)) { return csound->PerfError(csound, p->h.insdshead, Str("hsboscil: not initialised")); } tonal = *p->ktona; tonal -= MYFLOOR(tonal); bright = *p->kbrite - tonal; octstart = bright - (MYFLT)octcnt * FL(0.5); octbase = MYFLOOR(MYFLOOR(octstart) + FL(1.5)); octoffs = octbase - octstart; mtab = mixtp->ftable; mtablen = mixtp->flen; freq = *p->ibasef * POWER(FL(2.0), tonal + octbase); ampscl = mtab[(int)((1.0 / (MYFLT)octcnt) * mtablen)]; amp = mtab[(int)((octoffs / (MYFLT)octcnt) * mtablen)]; if ((amp - p->prevamp) > (ampscl * FL(0.5))) octshift = 1; else if ((amp - p->prevamp) < (-(ampscl * FL(0.5)))) octshift = -1; else octshift = 0; p->prevamp = amp; ampscl = FL(0.0); for (i=0; ilphs[(i+octshift+100*octcnt) % octcnt]; ampscl += mtab[(int)(((MYFLT)i / (MYFLT)octcnt) * mtablen)]; } amp0 = *p->kamp / ampscl; lobits = ftp->lobits; ar = p->sr; memset(ar, 0, nsmps*sizeof(MYFLT)); if (UNLIKELY(early)) nsmps -= early; for (i=0; i hesr)) amp = FL(0.0); inc = (int32)(freq * csound->sicvt); for (n=offset; nftable + (phs >> lobits); v1 = *ftab++; ar[n] += (v1 + (*ftab - v1) * fract) * amp; phs += inc; phs &= PHMASK; } p->lphs[i] = phs; octoffs += FL(1.0); freq *= FL(2.0); } return OK; } int pitchamdfset(CSOUND *csound, PITCHAMDF *p) { MYFLT srate, downs; int32 size, minperi, maxperi, downsamp, upsamp, msize, bufsize; uint32_t interval; uint32_t nsmps = CS_KSMPS; p->inerr = 0; downs = *p->idowns; if (downs < (-FL(1.9))) { upsamp = (int)MYFLT2LONG((-downs)); downsamp = 0; srate = CS_ESR * (MYFLT)upsamp; } else { downsamp = (int)MYFLT2LONG(downs); if (UNLIKELY(downsamp < 1)) downsamp = 1; srate = CS_ESR / (MYFLT)downsamp; upsamp = 0; } minperi = (int32)(srate / *p->imaxcps); maxperi = (int32)(FL(0.5)+srate / *p->imincps); if (UNLIKELY(maxperi <= minperi)) { p->inerr = 1; return csound->InitError(csound, Str("pitchamdf: maxcps must be > mincps !")); } if (*p->iexcps < 1) interval = maxperi; else interval = (uint32_t)(srate / *p->iexcps); if (interval < nsmps) { if (downsamp) interval = nsmps / downsamp; else interval = nsmps * upsamp; } size = maxperi + interval; bufsize = sizeof(MYFLT)*(size + maxperi + 2); p->srate = srate; p->downsamp = downsamp; p->upsamp = upsamp; p->minperi = minperi; p->maxperi = maxperi; p->size = size; p->readp = 0; p->index = 0; p->lastval = FL(0.0); if (*p->icps < 1) p->peri = (minperi + maxperi) / 2; else p->peri = (int)(srate / *p->icps); if (*p->irmsmedi < 1) p->rmsmedisize = 0; else p->rmsmedisize = ((int)MYFLT2LONG(*p->irmsmedi))*2+1; p->rmsmediptr = 0; if (p->rmsmedisize) { msize = p->rmsmedisize * 3 * sizeof(MYFLT); if (p->rmsmedian.auxp==NULL || p->rmsmedian.size < (size_t)msize) csound->AuxAlloc(csound, msize, &p->rmsmedian); else { memset(p->rmsmedian.auxp, 0, msize); } } if (*p->imedi < 1) p->medisize = 0; else p->medisize = (int)MYFLT2LONG(*p->imedi)*2+1; p->mediptr = 0; if (p->medisize) { msize = p->medisize * 3 * sizeof(MYFLT); if (p->median.auxp==NULL || p->median.size < (size_t)msize) csound->AuxAlloc(csound, (size_t)msize, &p->median); else { memset(p->median.auxp, 0, msize); } } if (p->buffer.auxp==NULL || p->buffer.size < (size_t)bufsize) { csound->AuxAlloc(csound, bufsize, &p->buffer); } else memset(p->buffer.auxp, 0, bufsize); return OK; } #define SWAP(a,b) temp=(a);(a)=(b);(b)=temp MYFLT medianvalue(uint32 n, MYFLT *vals) { /* vals must point to 1 below relevant data! */ uint32 i, ir, j, l, mid; uint32 k = (n + 1) / 2; MYFLT a, temp; l = 1; ir = n; while (1) { if (ir <= l+1) { if (ir == l+1 && vals[ir] < vals[l]) { SWAP(vals[l], vals[ir]); } return vals[k]; } else { mid = (l+ir) >> 1; SWAP(vals[mid], vals[l+1]); if (vals[l+1] > vals[ir]) { SWAP(vals[l+1], vals[ir]); } if (vals[l] > vals[ir]) { SWAP(vals[l], vals[ir]); } if (vals[l+1] > vals[l]) { SWAP(vals[l+1], vals[l]); } i = l + 1; j = ir; a = vals[l]; while (1) { do i++; while (vals[i] < a); do j--; while (vals[j] > a); if (UNLIKELY(j < i)) break; SWAP(vals[i], vals[j]); } vals[l] = vals[j]; vals[j] = a; if (j >= k) ir = j-1; if (j <= k) l = i; } } } #undef SWAP int pitchamdf(CSOUND *csound, PITCHAMDF *p) { MYFLT *buffer = (MYFLT*)p->buffer.auxp; MYFLT *rmsmedian = (MYFLT*)p->rmsmedian.auxp; int32 rmsmedisize = p->rmsmedisize; int32 rmsmediptr = p->rmsmediptr; MYFLT *median = (MYFLT*)p->median.auxp; int32 medisize = p->medisize; int32 mediptr = p->mediptr; int32 size = p->size; int32 index = p->index; int32 minperi = p->minperi; int32 maxperi = p->maxperi; MYFLT *asig = p->asig; MYFLT srate = p->srate; int32 peri = p->peri; int32 upsamp = p->upsamp; MYFLT upsmp = (MYFLT)upsamp; MYFLT lastval = p->lastval; MYFLT newval, delta; int32 readp = p->readp; int32 interval = size - maxperi; int nsmps = CS_KSMPS; int i; int32 i1, i2; MYFLT val, rms; double sum; MYFLT acc, accmin, diff; if (UNLIKELY(p->inerr)) { return csound->PerfError(csound, p->h.insdshead, Str("pitchamdf: not initialised")); } if (upsamp) { while (1) { newval = asig[readp++]; delta = (newval-lastval) / upsmp; lastval = newval; for (i=0; i 0) accmin += diff; else accmin -= diff; } for (i1 = minperi + 1; i1 <= maxperi; ++i1) { acc = FL(0.0); for (i2 = 0; i2 < size; ++i2) { diff = buffer[i1+i2] - buffer[i2]; if (diff > 0) acc += diff; else acc -= diff; } if (acc < accmin) { accmin = acc; peri = i1; } } for (i1 = 0; i1 < interval; i1++) buffer[i1] = buffer[i1+interval]; index = maxperi; if (medisize) { median[mediptr] = (MYFLT)peri; for (i1 = 0; i1 < medisize; i1++) median[medisize+i1] = median[i1]; median[medisize*2+mediptr] = medianvalue(medisize, &median[medisize-1]); peri = (int32)median[medisize*2 + ((mediptr+medisize/2+1) % medisize)]; mediptr = (mediptr + 1) % medisize; p->mediptr = mediptr; } } } if (readp >= nsmps) break; } readp = readp % nsmps; p->lastval = lastval; } else { int32 downsamp = p->downsamp; while (1) { buffer[index++] = asig[readp]; readp += downsamp; if (index == size) { peri = minperi; accmin = FL(0.0); for (i2 = 0; i2 < size; ++i2) { diff = buffer[i2+minperi] - buffer[i2]; if (diff > FL(0.0)) accmin += diff; else accmin -= diff; } for (i1 = minperi + 1; i1 <= maxperi; ++i1) { acc = FL(0.0); for (i2 = 0; i2 < size; ++i2) { diff = buffer[i1+i2] - buffer[i2]; if (diff > FL(0.0)) acc += diff; else acc -= diff; } if (acc < accmin) { accmin = acc; peri = i1; } } for (i1 = 0; i1 < interval; i1++) buffer[i1] = buffer[i1+interval]; index = maxperi; if (medisize) { median[mediptr] = (MYFLT)peri; for (i1 = 0; i1 < medisize; i1++) median[medisize+i1] = median[i1]; median[medisize*2+mediptr] = medianvalue(medisize, &median[medisize-1]); peri = (int32)median[medisize*2 + ((mediptr+medisize/2+1) % medisize)]; mediptr = (mediptr + 1) % medisize; p->mediptr = mediptr; } } if (readp >= nsmps) break; } readp = readp % nsmps; } buffer = &buffer[(index + size - peri) % size]; sum = 0.0; for (i1=0; i1rmsmediptr = rmsmediptr; } if (UNLIKELY(peri==0)) { *p->kcps = FL(0.0); } else *p->kcps = srate / (MYFLT)peri; *p->krms = rms; p->index = index; p->peri = peri; p->readp = readp; return OK; } /*==================================================================*/ /* phasorbnk */ /*==================================================================*/ int phsbnkset(CSOUND *csound, PHSORBNK *p) { double phs; int n, count; double *curphs; count = (int)MYFLT2LONG(*p->icnt); if (UNLIKELY(count < 2)) count = 2; if (p->curphs.auxp==NULL || p->curphs.size < (size_t)sizeof(double)*count) csound->AuxAlloc(csound, (size_t)sizeof(double)*count, &p->curphs); curphs = (double*)p->curphs.auxp; if (*p->iphs > 1) { for (n=0; niphs) >= 0) { for (n=0; ncurphs.auxp; int size = p->curphs.size / sizeof(double); int index = (int)(*p->kindx); if (UNLIKELY(curphs == NULL)) { return csound->PerfError(csound, p->h.insdshead, Str("phasorbnk: not initialised")); } if (UNLIKELY(index<0 || index>=size)) { *p->sr = FL(0.0); return NOTOK; } *p->sr = (MYFLT)(phs = curphs[index]); if (UNLIKELY((phs += *p->xcps * csound->onedkr) >= 1.0)) phs -= 1.0; else if (UNLIKELY(phs < 0.0)) /* patch from Matthew Scala */ phs += 1.0; curphs[index] = phs; return OK; } int phsorbnk(CSOUND *csound, PHSORBNK *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *rs; double phase, incr; double *curphs = (double*)p->curphs.auxp; int size = p->curphs.size / sizeof(double); int index = (int)(*p->kindx); if (UNLIKELY(curphs == NULL)) { return csound->PerfError(csound, p->h.insdshead, Str("phasorbnk: not initialised")); } if (UNLIKELY(index<0 || index>=size)) { *p->sr = FL(0.0); return NOTOK; } rs = p->sr; phase = curphs[index]; if (UNLIKELY(offset)) memset(rs, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rs[nsmps], '\0', early*sizeof(MYFLT)); } if (IS_ASIG_ARG(p->xcps)) { MYFLT *cps = p->xcps; for (n=offset; nonedsr); rs[n] = (MYFLT)phase; phase += incr; if (UNLIKELY(phase >= 1.0)) phase -= 1.0; else if (UNLIKELY(phase < 0.0)) phase += 1.0; } } else { incr = (double)(*p->xcps * csound->onedsr); for (n=offset; n= 1.0)) phase -= 1.0; else if (UNLIKELY(phase < 0.0)) phase += 1.0; } } curphs[index] = phase; return OK; } /* Opcodes from rasmus ekman */ /* pinkish: Two methods for pink-type noise generation The Moore/Gardner method, coded by Phil Burke, optimised by James McCartney; Paul Kellet's -3dB/octave white->pink filter bank, "refined" version; Paul Kellet's -3dB/octave white->pink filter bank, "economy" version The Moore/Gardner method output seems to have bumps in the low-mid and mid-high ranges. The Kellet method (refined) has smooth spectrum, but goes up slightly at the far high end. */ #define GARDNER_PINK FL(0.0) #define KELLET_PINK FL(1.0) #define KELLET_CHEAP_PINK FL(2.0) int GardnerPink_init(CSOUND *csound, PINKISH *p); int GardnerPink_perf(CSOUND *csound, PINKISH *p); int pinkset(CSOUND *csound, PINKISH *p) { /* Check valid method */ if (UNLIKELY(*p->imethod != GARDNER_PINK && *p->imethod != KELLET_PINK && *p->imethod != KELLET_CHEAP_PINK)) { return csound->InitError(csound, Str("pinkish: Invalid method code")); } /* User range scaling can be a- or k-rate for Gardner, a-rate only for filter */ if (IS_ASIG_ARG(p->xin)) { p->ampinc = 1; } else { /* Cannot accept k-rate input with filter method */ if (UNLIKELY(*p->imethod != FL(0.0))) { return csound->InitError(csound, Str( "pinkish: Filter method requires a-rate (noise) input")); } p->ampinc = 0; } /* Unless we're reinitializing a tied note, zero coefs */ if (*p->iskip != FL(1.0)) { if (*p->imethod == GARDNER_PINK) GardnerPink_init(csound,p); else /* Filter method */ p->b0 = p->b1 = p->b2 = p->b3 = p->b4 = p->b5 = p->b6 = FL(0.0); } return OK; } int pinkish(CSOUND *csound, PINKISH *p) { MYFLT *aout, *ain; double c0, c1, c2, c3, c4, c5, c6, nxtin, nxtout; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; aout = p->aout; ain = p->xin; if (UNLIKELY(offset)) memset(aout, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&aout[nsmps], '\0', early*sizeof(MYFLT)); } if (*p->imethod == GARDNER_PINK) { /* Gardner method (default) */ GardnerPink_perf(csound,p); } else if (*p->imethod == KELLET_PINK) { /* Paul Kellet's "refined" pink filter */ /* Get filter states */ c0 = p->b0; c1 = p->b1; c2 = p->b2; c3 = p->b3; c4 = p->b4; c5 = p->b5; c6 = p->b6; for (n=offset;nb0 = c0; p->b1 = c1; p->b2 = c2; p->b3 = c3; p->b4 = c4; p->b5 = c5; p->b6 = c6; } else if (*p->imethod == KELLET_CHEAP_PINK) { /* Get filter states */ c0 = p->b0; c1 = p->b1; c2 = p->b2; for (n=offset;nb0 = c0; p->b1 = c1; p->b2 = c2; } return OK; } /************************************************************/ /* GardnerPink_init() and GardnerPink_perf() Generate Pink Noise using Gardner method. Optimization suggested by James McCartney uses a tree to select which random value to replace. x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x Tree is generated by counting trailing zeros in an increasing index. When the index is zero, no random number is selected. Author: Phil Burk, http://www.softsynth.com Revision History: Csound version by rasmus ekman May 2000 Several changes, some marked "(re)" Copyright 1999 Phil Burk - No rights reserved. */ /************************************************************/ /* Yet another pseudo-random generator. Could probably be changed for any of the other available ones in Csound */ #define PINK_RANDOM_BITS (24) /* Left-shift one bit less 24 to allow negative values (re) */ #define PINK_RANDOM_SHIFT (7) /* Calculate pseudo-random 32 bit number based on linear congruential method. */ static int32 GenerateRandomNumber(uint32 randSeed) { randSeed = ((uint32_t) randSeed * 196314165U) + 907633515UL; return (int32) ((int32_t) ((uint32_t) randSeed)); } /************************************************************/ /* Set up for user-selected number of bands of noise generators. */ int GardnerPink_init(CSOUND *csound, PINKISH *p) { int i; MYFLT pmax; int32 numRows; /* Set number of rows to use (default to 20) */ if (*p->iparam1 >= 4 && *p->iparam1 <= GRD_MAX_RANDOM_ROWS) p->grd_NumRows = (int32)*p->iparam1; else { p->grd_NumRows = 20; /* Warn if user tried but failed to give sensible number */ if (UNLIKELY(*p->iparam1 != FL(0.0))) csound->Warning(csound, Str("pinkish: Gardner method requires 4-%d bands. " "Default %d substituted for %d.\n"), GRD_MAX_RANDOM_ROWS, p->grd_NumRows, (int) *p->iparam1); } /* Seed random generator by user value or by time (default) */ if (*p->iseed != FL(0.0)) { if (*p->iseed > -1.0 && *p->iseed < 1.0) p->randSeed = (uint32) (*p->iseed * (MYFLT)0x80000000); else p->randSeed = (uint32) *p->iseed; } else p->randSeed = (uint32) csound->GetRandomSeedFromTime(); numRows = p->grd_NumRows; p->grd_Index = 0; if (numRows == 32) p->grd_IndexMask = 0xFFFFFFFF; else p->grd_IndexMask = (1<grd_Scalar = FL(1.0) / pmax; /* Warm up by filling all rows (re) (original zeroed all rows, and runningSum) */ { int32 randSeed, newRandom, runningSum = 0; randSeed = p->randSeed; for (i = 0; i < numRows; i++) { randSeed = GenerateRandomNumber(randSeed); newRandom = randSeed >> PINK_RANDOM_SHIFT; runningSum += newRandom; p->grd_Rows[i] = newRandom; } p->grd_RunningSum = runningSum; p->randSeed = randSeed; } return OK; } /* Generate numRows octave-spaced white bands and sum to pink noise. */ int GardnerPink_perf(CSOUND *csound, PINKISH *p) { MYFLT *aout, *amp, scalar; int32 *rows, rowIndex, indexMask, randSeed, newRandom; int32 runningSum, sum, ampinc; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t n, nsmps = CS_KSMPS - p->h.insdshead->ksmps_no_end; aout = p->aout; amp = p->xin; ampinc = p->ampinc; /* Used to increment user amp if a-rate */ scalar = p->grd_Scalar; rowIndex = p->grd_Index; indexMask = p->grd_IndexMask; runningSum = p->grd_RunningSum; rows = &(p->grd_Rows[0]); randSeed = p->randSeed; for (n=offset; n> 1; numZeros++; } /* Replace the indexed ROWS random value. * Subtract and add back to RunningSum instead of adding all * the random values together. Only one changes each time. */ runningSum -= rows[numZeros]; randSeed = GenerateRandomNumber(randSeed); newRandom = randSeed >> PINK_RANDOM_SHIFT; runningSum += newRandom; rows[numZeros] = newRandom; } /* Add extra white noise value. */ randSeed = GenerateRandomNumber(randSeed); newRandom = randSeed >> PINK_RANDOM_SHIFT; sum = runningSum + newRandom; /* Scale to range of +/-p->xin (user-selected amp) */ aout[n] = *amp * sum * scalar; amp += ampinc; /* Increment if amp is a-rate */ } p->grd_RunningSum = runningSum; p->grd_Index = rowIndex; p->randSeed = randSeed; return OK; } /* ************************************************************ */ /* A collection of clipping techniques -- JPff */ /* Method 0: Bram de Jong */ /* x > a: f(x) = a + (x-a)/(1+((x-a)/(1-a))^2) */ /* x > 1: f(x) = (a+1)/2 */ /* JPff scaled this to a limit and a fraction */ /* Method 1: */ /* |x|imethod); p->meth = meth; p->arg = FABS(*p->iarg); p->lim = *p->limit; switch (meth) { case 0: /* Bram de Jong method */ if (p->arg > FL(1.0) || p->arg < FL(0.0)) p->arg = FL(0.999); p->arg = p->lim * p->arg; p->k1 = FL(1.0)/(p->lim - p->arg); p->k1 = p->k1 * p->k1; p->k2 = (p->lim + p->arg)*FL(0.5); break; case 1: p->k1 = PI_F/(FL(2.0) * p->lim); break; case 2: p->k1 = FL(1.0)/TANH(FL(1.0)); break; default: p->meth = 0; } return OK; } int clip(CSOUND *csound, CLIP *p) { MYFLT *aout = p->aout, *ain = p->ain; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT a = p->arg, k1 = p->k1, k2 = p->k2; MYFLT limit = p->lim; MYFLT rlim = FL(1.0)/limit; if (UNLIKELY(offset)) memset(aout, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&aout[nsmps], '\0', early*sizeof(MYFLT)); } switch (p->meth) { case 0: /* Soft clip with division */ for (n=offset;n=FL(0.0)) { if (UNLIKELY(x>limit)) x = k2; else if (x>a) x = a + (x-a)/(FL(1.0)+(x-a)*(x-a)*k1); } else { if (UNLIKELY(x<-limit)) x = -k2; else if (-x>a) x = -a + (x+a)/(FL(1.0)+(x+a)*(x+a)*k1); } aout[n] = x; } return OK; case 1: for (n=offset;n=limit)) x = limit; else if (UNLIKELY(x<= -limit)) x = -limit; else x = limit*SIN(k1*x); aout[n] = x; } return OK; case 2: for (n=offset;n=limit)) x = limit; else if (UNLIKELY(x<= -limit)) x = -limit; else x = limit*k1*TANH(x*rlim); aout[n] = x; } return OK; } return OK; } /* ********************************************************************** */ /* *************** IMPULSE ********************************************** */ /* ********************************************************************** */ int impulse_set(CSOUND *csound, IMPULSE *p) { p->next = (unsigned int)MYFLT2LONG(*p->offset * CS_ESR); return OK; } int impulse(CSOUND *csound, IMPULSE *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int next = p->next; MYFLT *ar = p->ar; if (next<0) next = -next; if (UNLIKELY(next < (int32)nsmps)) { /* Impulse in this frame */ MYFLT frq = *p->freq; /* Freq at k-rate */ int sfreq; /* Converted to samples */ if (frq == FL(0.0)) sfreq = INT_MAX; /* Zero means infinite */ else if (frq < FL(0.0)) sfreq = -(int)frq; /* Negative cnts in sample */ else sfreq = (int)(frq*CS_ESR); /* Normal case */ if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;namp; next = sfreq - 1; /* Note can be less than k-rate */ } else ar[n] = FL(0.0); } } else { /* Nothing this time so just fill */ memset(ar, 0, nsmps*sizeof(MYFLT)); next -= nsmps; } p->next = next; return OK; } /* ********************************************************************** */ /* Version of CMUSIC trans opcode */ /* creates y0 + (y1 - y0) * (1 - exp( t*alpha )) / (1 - exp(alpha)) */ /* or */ /* y0 + (y1 - y0) * t if alpha is zero */ /* ********************************************************************** */ int trnset(CSOUND *csound, TRANSEG *p) { NSEG *segp; int nsegs; MYFLT **argp, val; if (UNLIKELY(p->INOCOUNT%3!=1)) return csound->InitError(csound, Str("Incorrect argument count in transeg")); nsegs = p->INOCOUNT / 3; /* count segs & alloc if nec */ if ((segp = (NSEG *) p->auxch.auxp) == NULL || (unsigned int)p->auxch.size < nsegs*sizeof(NSEG)) { csound->AuxAlloc(csound, (int32)nsegs*sizeof(NSEG), &p->auxch); p->cursegp = segp = (NSEG *) p->auxch.auxp; } segp[nsegs-1].cnt = MAXPOS; /* set endcount for safety */ segp[nsegs-1].acnt = MAXPOS; /* set endcount for safety */ argp = p->argums; val = **argp++; if (**argp <= FL(0.0)) return OK; /* if idur1 <= 0, skip init */ p->curval = val; p->curcnt = 0; p->cursegp = segp - 1; /* else setup null seg0 */ p->segsrem = nsegs + 1; p->curx = FL(0.0); do { /* init each seg .. */ MYFLT dur = **argp++; MYFLT alpha = **argp++; MYFLT nxtval = **argp++; MYFLT d = dur * CS_ESR; if ((segp->acnt = segp->cnt = (int32)MYFLT2LONG(d)) < 0) segp->cnt = 0; else segp->cnt = (int32)(dur * CS_EKR); segp->nxtpt = nxtval; segp->val = val; if (alpha == FL(0.0)) { segp->c1 = (nxtval-val)/d; } else { segp->c1 = (nxtval - val)/(FL(1.0) - EXP(alpha)); } segp->alpha = alpha/d; val = nxtval; segp++; } while (--nsegs); p->xtra = -1; p->alpha = ((NSEG*)p->auxch.auxp)[0].alpha; p->curinc = ((NSEG*)p->auxch.auxp)[0].c1; return OK; } int trnset_bkpt(CSOUND *csound, TRANSEG *p) { NSEG *segp; int nsegs; MYFLT **argp, val; MYFLT totdur = FL(0.0); if (UNLIKELY(p->INOCOUNT%3!=1)) return csound->InitError(csound, Str("Incorrect argument count in transegb")); nsegs = p->INOCOUNT / 3; /* count segs & alloc if nec */ if ((segp = (NSEG *) p->auxch.auxp) == NULL || (unsigned int)p->auxch.size < nsegs*sizeof(NSEG)) { csound->AuxAlloc(csound, (int32)nsegs*sizeof(NSEG), &p->auxch); p->cursegp = segp = (NSEG *) p->auxch.auxp; } segp[nsegs-1].cnt = MAXPOS; /* set endcount for safety */ argp = p->argums; val = **argp++; if (**argp <= FL(0.0)) return OK; /* if idur1 <= 0, skip init */ p->curval = val; p->curcnt = 0; p->cursegp = segp - 1; /* else setup null seg0 */ p->segsrem = nsegs + 1; p->curx = FL(0.0); do { /* init each seg .. */ MYFLT dur = **argp++; MYFLT alpha = **argp++; MYFLT nxtval = **argp++; MYFLT d; dur -= totdur; totdur += dur; d = dur * CS_ESR; if ((segp->cnt = (int32)MYFLT2LONG(d)) < 0) segp->cnt = 0; else segp->cnt = (int32)(dur * CS_EKR); segp->nxtpt = nxtval; segp->val = val; if (alpha == FL(0.0)) { segp->c1 = (nxtval-val)/d; } else { segp->c1 = (nxtval - val)/(FL(1.0) - EXP(alpha)); } segp->alpha = alpha/d; val = nxtval; segp++; } while (--nsegs); p->xtra = -1; p->alpha = ((NSEG*)p->auxch.auxp)[0].alpha; p->curinc = ((NSEG*)p->auxch.auxp)[0].c1; return OK; } int ktrnseg(CSOUND *csound, TRANSEG *p) { *p->rslt = p->curval; /* put the cur value */ if (UNLIKELY(p->auxch.auxp==NULL)) { /* RWD fix */ csound->PerfError(csound,p->h.insdshead, Str("Error: transeg not initialised (krate)\n")); } if (p->segsrem) { /* done if no more segs */ if (--p->curcnt <= 0) { /* if done cur segment */ NSEG *segp = p->cursegp; chk1: if (!(--p->segsrem)) { p->curval = segp->nxtpt; /* advance the cur val */ return OK; } p->cursegp = ++segp; /* find the next */ if (!(p->curcnt = segp->cnt)) { /* nonlen = discontin */ p->curval = segp->nxtpt; /* poslen = new slope */ goto chk1; } p->curinc = segp->c1; p->alpha = segp->alpha; p->curx = FL(0.0); } p->curx += (MYFLT)CS_KSMPS*p->alpha; if (p->alpha == FL(0.0)) p->curval += p->curinc*CS_KSMPS; /* advance the cur val */ else p->curval = p->cursegp->val + p->curinc * (FL(1.0) - EXP(p->curx)); } return OK; } int trnseg(CSOUND *csound, TRANSEG *p) { MYFLT val, *rs = p->rslt; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; NSEG *segp = p->cursegp; if (UNLIKELY(p->auxch.auxp==NULL)) { return csound->PerfError(csound, p->h.insdshead, Str("transeg: not initialised (arate)\n")); } if (UNLIKELY(offset)) memset(rs, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rs[nsmps], '\0', early*sizeof(MYFLT)); } val = p->curval; /* sav the cur value */ for (n=offset; nsegsrem) { /* if no more segs putk */ if (--p->curcnt <= 0) { /* if done cur segment */ segp = p->cursegp; chk1: if (UNLIKELY(!--p->segsrem)) { /* if none left */ val = p->curval = segp->nxtpt; goto putk; /* put endval */ } p->cursegp = ++segp; /* else find the next */ if (!(p->curcnt = segp->acnt)) { val = p->curval = segp->nxtpt; /* nonlen = discontin */ goto chk1; } /* poslen = new slope */ p->curinc = segp->c1; p->alpha = segp->alpha; p->curx = FL(0.0); p->curval = val; } if (p->alpha == FL(0.0)) { rs[n] = val; val += p->curinc; } else { rs[n] = val; p->curx += p->alpha; val = segp->val + p->curinc * (FL(1.0) - EXP(p->curx)); } } else{ putk: rs[n] = val; } } p->curval = val; return OK; } /* MIDI aware version of transeg */ int trnsetr(CSOUND *csound, TRANSEG *p) { int relestim; NSEG *segp; int nsegs; MYFLT **argp; double val; if (UNLIKELY(p->INOCOUNT%3!=1)) return csound->InitError(csound, Str("Incorrect argument count in transegr")); nsegs = p->INOCOUNT / 3; /* count segs & alloc if nec */ if ((segp = (NSEG *) p->auxch.auxp) == NULL || (unsigned int)p->auxch.size < nsegs*sizeof(NSEG)) { csound->AuxAlloc(csound, (int32)nsegs*sizeof(NSEG), &p->auxch); p->cursegp = segp = (NSEG *) p->auxch.auxp; } segp[nsegs-1].cnt = MAXPOS; /* set endcount for safety */ segp[nsegs-1].acnt = MAXPOS; /* set endcount for safety */ argp = p->argums; val = (double)**argp++; if (UNLIKELY(**argp <= FL(0.0))) return OK; /* if idur1 <= 0, skip init */ p->curval = val; p->curcnt = 0; p->cursegp = segp - 1; /* else setup null seg0 */ p->segsrem = nsegs + 1; p->curx = FL(0.0); do { /* init each seg .. */ double dur = (double)**argp++; MYFLT alpha = **argp++; MYFLT nxtval = **argp++; MYFLT d = dur * CS_ESR; if ((segp->acnt = segp->cnt = (int32)(d + FL(0.5))) < 0) segp->cnt = 0; else segp->cnt = (int32)(dur * CS_EKR); segp->nxtpt = nxtval; segp->val = val; if (alpha == FL(0.0)) { segp->c1 = (nxtval-val)/d; //printf("alpha zero val=%f c1=%f\n", segp->val, segp->c1); } else { p->lastalpha = alpha; segp->c1 = (nxtval - val)/(FL(1.0) - EXP(alpha)); } segp->alpha = alpha/d; val = nxtval; segp++; p->finalval = nxtval; } while (--nsegs); //p->xtra = -1; p->alpha = ((NSEG*)p->auxch.auxp)[0].alpha; p->curinc = ((NSEG*)p->auxch.auxp)[0].c1; relestim = (int)(p->cursegp + p->segsrem - 1)->cnt; p->xtra = relestim; if (relestim > p->h.insdshead->xtratim) p->h.insdshead->xtratim = (int)relestim; /* { */ /* int i; */ /* int nseg = p->INOCOUNT / 3; */ /* NSEG *segp = p->cursegp; */ /* for (i=0; irslt = p->curval; /* put the cur value */ if (UNLIKELY(p->auxch.auxp==NULL)) { /* RWD fix */ csound->PerfError(csound,p->h.insdshead, Str("Error: transeg not initialised (krate)\n")); } if (p->segsrem) { /* done if no more segs */ NSEG *segp; if (p->h.insdshead->relesing && p->segsrem > 1) { //printf("releasing\n"); while (p->segsrem > 1) { /* reles flag new: */ segp = ++p->cursegp; /* go to last segment */ p->segsrem--; } /* get univ relestim */ segp->cnt = p->xtra>=0 ? p->xtra : p->h.insdshead->xtratim; if (segp->alpha == FL(0.0)) { segp->c1 = (p->finalval-p->curval)/(segp->cnt*CS_KSMPS); //printf("finalval = %f curval = %f, cnt = %d c1 = %f\n", // p->finalval, p->curval, segp->cnt, segp->c1); } else { segp->c1 = (p->finalval - p->curval)/(FL(1.0) - EXP(p->lastalpha)); segp->alpha = p->lastalpha/(segp->cnt*CS_KSMPS); segp->val = p->curval; } goto newm; /* and set new curmlt */ } if (--p->curcnt <= 0) { /* if done cur segment */ chk1: if (p->segsrem == 2) return OK; /* seg Y rpts lastval */ if (!(--p->segsrem)) return OK; /* seg Z now done all */ segp = ++p->cursegp; /* find the next */ newm: //printf("curcnt = %d seg/cnt = %d\n", p->curcnt, segp->cnt); if (!(p->curcnt = segp->cnt)) { /* nonlen = discontin */ p->curval = segp->nxtpt; /* poslen = new slope */ //printf("curval = %f\n", p->curval); goto chk1; } p->curinc = segp->c1; p->alpha = segp->alpha; p->curx = FL(0.0); } if (p->alpha == FL(0.0)) { p->curval += p->curinc *CS_KSMPS; /* advance the cur val */ //printf("curval = %f\n", p->curval); } else p->curval = p->cursegp->val + (p->curinc) * (FL(1.0) - EXP(p->curx)); p->curx += (MYFLT)CS_KSMPS* p->alpha; } return OK; } int trnsegr(CSOUND *csound, TRANSEG *p) { MYFLT val, *rs = p->rslt; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(p->auxch.auxp==NULL)) { return csound->PerfError(csound, p->h.insdshead, Str("transeg: not initialised (arate)\n")); } if (UNLIKELY(offset)) memset(rs, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rs[nsmps], '\0', early*sizeof(MYFLT)); } val = p->curval; /* sav the cur value */ for (n=offset; nsegsrem)) { /* if no more segs putk */ NSEG *segp; if (p->h.insdshead->relesing && p->segsrem > 1) { while (p->segsrem > 1) { /* if release flag new */ segp = ++p->cursegp; /* go to last segment */ p->segsrem--; } /* get univ relestim */ segp->cnt = p->xtra>=0 ? p->xtra : p->h.insdshead->xtratim; if (segp->alpha == FL(0.0)) { segp->c1 = (p->finalval-val)/segp->acnt; } else { /* this is very wrong */ segp->c1 = (p->finalval - val)/(FL(1.0) - EXP(p->lastalpha)); segp->alpha = p->lastalpha/segp->acnt; segp->val = val; } goto newm; /* and set new curmlt */ } if (--p->curcnt <= 0) { /* if done cur segment */ //segp = p->cursegp; /* overwritten later -- coverity */ chk1: if (p->segsrem == 2) goto putk; /* seg Y rpts lastval */ if (UNLIKELY(!--p->segsrem)) { /* if none left */ //val = p->curval = segp->nxtpt; goto putk; /* put endval */ } segp = ++p->cursegp; /* else find the next */ newm: if (!(p->curcnt = segp->acnt)) { val = p->curval = segp->nxtpt; /* nonlen = discontin */ goto chk1; } /* poslen = new slope */ p->curinc = segp->c1; p->alpha = segp->alpha; p->curx = FL(0.0); p->curval = val; } if (p->alpha == FL(0.0)) { rs[n] = val; val += p->curinc; } else { segp = p->cursegp; rs[n] = val; p->curx += p->alpha; val = segp->val + p->curinc * (FL(1.0) - EXP(p->curx)); } } else { putk: rs[n] = val; } } p->curval = val; return OK; } extern int32 randint31(int32); int varicolset(CSOUND *csound, VARI *p) { p->last = FL(0.0); p->lastbeta = *p->beta; p->sq1mb2 = SQRT(FL(1.0)-p->lastbeta * p->lastbeta); p->ampmod = FL(0.785)/(FL(1.0)+p->lastbeta); p->ampinc = IS_ASIG_ARG(p->kamp) ? 1 : 0; return OK; } int varicol(CSOUND *csound, VARI *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT beta = *p->beta; MYFLT sq1mb2 = p->sq1mb2; MYFLT lastx = p->last; MYFLT ampmod = p->ampmod; MYFLT *kamp = p->kamp; int ampinc = p->ampinc; MYFLT *rslt = p->rslt; if (beta != p->lastbeta) { beta = p->lastbeta = *p->beta; sq1mb2 = p->sq1mb2 = SQRT(FL(1.0)-p->lastbeta * p->lastbeta); ampmod = p->ampmod = FL(0.785)/(FL(1.0)+p->lastbeta); } if (UNLIKELY(offset)) memset(rslt, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&rslt[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nlast = lastx; return OK; } /* ************************************************************************ */ /* ***** Josep Comajuncosas' 18dB/oct resonant 3-pole LPF with tanh dist ** */ /* ***** Coded in C by John ffitch, 2000 Dec 17 *************************** */ /* ************************************************************************ */ #include /* This code is transcribed from a Csound macro, so no real comments */ int lpf18set(CSOUND *csound, LPF18 *p) { /* Initialise delay lines */ if (*p->istor==FL(0.0)) { p->ay1 = FL(0.0); p->ay2 = FL(0.0); p->aout = FL(0.0); p->lastin = FL(0.0); } return OK; } int lpf18db(CSOUND *csound, LPF18 *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT ay1 = p->ay1; MYFLT ay2 = p->ay2; MYFLT aout = p->aout; MYFLT *ain = p->ain; MYFLT *ar = p->ar; MYFLT lastin = p->lastin; double value = 0.0; int flag = 1; MYFLT lfc=0, lrs=0, kres=0, kfcn=0, kp=0, kp1=0, kp1h=0; double lds = 0.0; MYFLT zerodb = csound->e0dbfs; int asgf = IS_ASIG_ARG(p->fco), asgr = IS_ASIG_ARG(p->res), asgd = IS_ASIG_ARG(p->dist); if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;nfco[n] : *p->fco); res = (asgr ? p->res[n] : *p->res); dist = (double)(asgd ? p->dist[n] : *p->dist); if (fco != lfc || flag) { lfc = fco; kfcn = FL(2.0) * fco * csound->onedsr; kp = ((-FL(2.7528)*kfcn + FL(3.0429))*kfcn + FL(1.718))*kfcn - FL(0.9984); kp1 = kp+FL(1.0); kp1h = FL(0.5)*kp1; flag = 1; } if (res != lrs || flag) { lrs = res; kres = res * (((-FL(2.7079)*kp1 + FL(10.963))*kp1 - FL(14.934))*kp1 + FL(8.4974)); flag = 1; } if (dist != lds || flag) { lds = dist; value = 1.0+(dist*(1.5+2.0*(double)kres*(1.0-(double)kfcn))); } flag = 0; lastin = ain[n]/zerodb - TANH(kres*aout); ay1 = kp1h * (lastin + ax1) - kp*ay1; ay2 = kp1h * (ay1 + ay11) - kp*ay2; aout = kp1h * (ay2 + ay31) - kp*aout; ar[n] = TANH(aout*value)*zerodb; } p->ay1 = ay1; p->ay2 = ay2; p->aout = aout; p->lastin = lastin; return OK; } /* ************************************************** */ /* **** Wishart wavesets ************************ */ /* **** from Trevor and CDP ************************ */ /* **** John ffitch Jan 2001 ************************ */ /* ************************************************** */ int wavesetset(CSOUND *csound, BARRI *p) { if (*p->len == FL(0.0)) p->length = 1 + (int)(p->h.insdshead->p3.value * CS_ESR * FL(0.5)); else p->length = 1 + (int)*p->len; if (UNLIKELY(p->length <= 1)) p->length = (int)CS_ESR; csound->AuxAlloc(csound, (int32)p->length*sizeof(MYFLT), &p->auxch); p->cnt = 1; p->start = 0; p->current = 0; p->end = 0; p->direction = 1; p->lastsamp = FL(1.0); p->noinsert = 0; return OK; } int waveset(CSOUND *csound, BARRI *p) { MYFLT *in = p->ain; MYFLT *out = p->ar; int index = p->end; MYFLT *insert = (MYFLT*)(p->auxch.auxp) + index; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } if (p->noinsert) goto output; for (n=offset;nstart) { p->noinsert = 1; break; } if (index==p->length) { /* Input wrapping */ index = 0; insert = (MYFLT*)(p->auxch.auxp); } } output: p->end = index; index = p->current; insert = (MYFLT*)(p->auxch.auxp) + index; for (n=offset;nlength) { index = 0; insert = (MYFLT*)(p->auxch.auxp); } if (samp != FL(0.0) && p->lastsamp*samp < FL(0.0)) { if (p->direction == 1) p->direction = -1; /* First cross */ else { /* Second cross */ p->direction = 1; if (++p->cnt > *p->rep) { p->cnt = 1; p->start = index; p->noinsert = 0; } else { index = p->start; insert = (MYFLT*)(p->auxch.auxp) + index; } } } if (samp != FL(0.0)) p->lastsamp = samp; out[n] = samp; } p->current = index; return OK; } int medfiltset(CSOUND *csound, MEDFILT *p) { int maxwind = (int)MYFLT2LONG(*p->imaxsize); int auxsize = 2*sizeof(MYFLT)*maxwind; p->ind = 0; p->maxwind = maxwind; if (p->b.auxp==NULL || p->b.size < (size_t)auxsize) csound->AuxAlloc(csound, (size_t)auxsize, &p->b); else if (*p->iskip!=FL(0.0)) memset(p->b.auxp, 0, auxsize); p->buff = (MYFLT*)p->b.auxp; p->med = &(p->buff[maxwind]); return OK; } int medfilt(CSOUND *csound, MEDFILT *p) { MYFLT *aout = p->ans; MYFLT *asig = p->asig; MYFLT *buffer = p->buff; MYFLT *med = p->med; int maxwind = p->maxwind; int kwind = MYFLT2LONG(*p->kwind); int index = p->ind; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(p->b.auxp==NULL)) { return csound->PerfError(csound, p->h.insdshead, Str("median: not initialised (arate)\n")); } if (UNLIKELY(kwind > maxwind)) { csound->Warning(csound, Str("median: window (%d)larger than maximum(%d); truncated"), kwind, maxwind); kwind = maxwind; } if (UNLIKELY(offset)) memset(aout, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&aout[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; n %f\n", n, index-1, x, aout[n]); */ if (index>=maxwind) index = 0; } p->ind = index; return OK; } int kmedfilt(CSOUND *csound, MEDFILT *p) { MYFLT *buffer = p->buff; MYFLT *med = p->med; MYFLT x = *p->asig; int maxwind = p->maxwind; int kwind = MYFLT2LONG(*p->kwind); int index = p->ind; if (UNLIKELY(p->b.auxp==NULL)) { return csound->PerfError(csound, p->h.insdshead, Str("median: not initialised (krate)\n")); } if (UNLIKELY(kwind > maxwind)) { csound->Warning(csound, Str("median: window (%d)larger than maximum(%d); truncated"), kwind, maxwind); kwind = maxwind; } buffer[index++] = x; if (kwind<=index) { /* all in centre */ memcpy(&med[0], &buffer[index-kwind], kwind*sizeof(MYFLT)); } else { /* or in two parts */ memcpy(&med[0], &buffer[0], index*sizeof(MYFLT)); memcpy(&med[index], &buffer[maxwind+index-kwind], (kwind-index)*sizeof(MYFLT)); } *p->ans = medianvalue(kwind, med-1); /* -1 as should point below data */ if (index>=maxwind) index = 0; p->ind = index; return OK; } csound-6.10.0/Opcodes/pitch.h000066400000000000000000000217011321653344700157560ustar00rootroot00000000000000#ifndef PITCH_H #define PITCH_H /* pitch.h: Copyright (C) 1999 John ffitch, Istvan Varga, Peter Neubcker, rasmus ekman, Phil Burk This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* PITCH.H */ #include "spectra.h" #include "uggab.h" typedef struct { OPDS h; MYFLT *koct, *kamp; MYFLT *asig; MYFLT *iprd, *ilo, *ihi, *idbthresh; /* Optional */ MYFLT *ifrqs, *iconf, *istrt, *iocts, *iq, *inptls, *irolloff, *istor; double c1, c2, prvq; #define MAXFRQS 120 SPECDAT wsig; int nfreqs, ncoefs, dbout, scountdown, timcount; MYFLT curq, *sinp, *cosp, *linbufp; int winlen[MAXFRQS], offset[MAXFRQS]; DOWNDAT downsig; WINDAT sinwindow, octwindow; AUXCH auxch1, auxch2; int pdist[MAXPTL], nptls, rolloff; MYFLT pmult[MAXPTL], confact, kvalsav, kval, kavl, kinc, kanc; MYFLT *flop, *fhip, *fundp, *oct0p, threshon, threshoff; int winpts, jmpcount, playing; SPECDAT wfund; } PITCH; typedef struct { OPDS h; MYFLT *cnt; void *clk; int c; } CLOCK; typedef struct { OPDS h; MYFLT *r; MYFLT *a; void *clk; } CLKRD; typedef struct { OPDS h; MYFLT *val; MYFLT *index; } SCRATCHPAD; typedef struct { OPDS h; MYFLT *ins; MYFLT *onoff; } MUTE; typedef struct { OPDS h; MYFLT *cnt; MYFLT *ins; MYFLT *opt; MYFLT *norel; } INSTCNT; typedef struct { OPDS h; MYFLT *instrnum, *ipercent, *iopc; /* IV - Oct 31 2002 */ } CPU_PERC; typedef struct { OPDS h; MYFLT *sr, *kamp, *kcps, *ifn, *ifreqtbl, *iamptbl, *icnt, *iphs; FUNC *ftp; FUNC *freqtp; FUNC *amptp; unsigned int count; int inerr; AUXCH lphs; } ADSYNT; typedef struct { OPDS h; MYFLT *sr, *kamp, *ktona, *kbrite, *ibasef, *ifn; MYFLT *imixtbl, *ioctcnt, *iphs; int32 lphs[10]; int octcnt; MYFLT prevamp; FUNC *ftp; FUNC *mixtp; } HSBOSC; typedef struct { OPDS h; MYFLT *kcps, *krms, *asig, *imincps, *imaxcps, *icps, *imedi, *idowns, *iexcps, *irmsmedi; MYFLT srate; MYFLT lastval; int32 downsamp; int32 upsamp; int32 minperi; int32 maxperi; int32 index; int32 readp; int32 size; int32 peri; int32 medisize; int32 mediptr; int32 rmsmedisize; int32 rmsmediptr; int inerr; AUXCH median; AUXCH rmsmedian; AUXCH buffer; } PITCHAMDF; typedef struct { OPDS h; MYFLT *sr, *xcps, *kindx, *icnt, *iphs; AUXCH curphs; } PHSORBNK; /* pinkish opcode... Two methods for generating pink noise */ /* Gardner method space req */ #define GRD_MAX_RANDOM_ROWS (32) typedef struct { OPDS h; MYFLT *aout; MYFLT *xin, *imethod, *iparam1, *iseed, *iskip; int32 ampinc; /* Scale output to range */ uint32 randSeed; /* Used by local random generator */ /* for Paul Kellet's filter bank */ double b0, b1, b2, b3, b4, b5, b6; /* for Gardner method */ int32 grd_Rows[GRD_MAX_RANDOM_ROWS]; int32 grd_NumRows; /* Number of rows (octave bands of noise) */ int32 grd_RunningSum; /* Used to optimize summing of generators. */ int grd_Index; /* Incremented each sample. */ int grd_IndexMask; /* Index wrapped by ANDing with this mask. */ MYFLT grd_Scalar; /* Used to scale to normalize generated noise. */ } PINKISH; typedef struct { OPDS h; MYFLT *aout; MYFLT *ain, *imethod, *limit, *iarg; MYFLT arg, lim, k1, k2; int meth; } CLIP; typedef struct { OPDS h; MYFLT *ar; MYFLT *amp, *freq, *offset; unsigned int next; } IMPULSE; typedef struct { int32 cnt,acnt; MYFLT alpha; MYFLT val, nxtpt; MYFLT c1; } NSEG; typedef struct { OPDS h; MYFLT *rslt, *argums[VARGMAX]; NSEG *cursegp; int32 nsegs; int32 segsrem, curcnt; MYFLT curval, curinc, alpha; MYFLT curx; AUXCH auxch; int32 xtra; MYFLT finalval, lastalpha; } TRANSEG; typedef struct { OPDS h; MYFLT *rslt, *kamp, *beta; MYFLT last, lastbeta, sq1mb2, ampmod; int ampinc; } VARI; typedef struct { OPDS h; MYFLT *ar, *ain, *fco, *res, *dist, *istor; MYFLT ay1, ay2, aout, lastin; } LPF18; typedef struct { OPDS h; MYFLT *ar, *ain, *rep, *len; AUXCH auxch; int length; /* Length of buffer */ int cnt; /* Repetions of current cycle */ int start; /* Start of current cycle */ int current; /* takeout point */ int direction; /* Need to check direction of crossing */ int end; /* Insert point */ MYFLT lastsamp; /* So we can test changes */ int noinsert; /* Flag to say we are losing input */ } BARRI; typedef struct { OPDS h; MYFLT *sr, *xamp, *xcps, *ifn, *iphs; MYFLT lphs; FUNC *ftp; } XOSC; typedef struct { OPDS h; MYFLT *ans; MYFLT *pnum; } PFUN; typedef struct { OPDS h; MYFLT *ans; MYFLT *pnum; AUXCH pfield; } PFUNK; typedef struct { OPDS h; MYFLT *ans; MYFLT *asig; MYFLT *kwind; MYFLT *imaxsize; MYFLT *iskip; AUXCH b; MYFLT *buff; MYFLT *med; int ind; int maxwind; } MEDFILT; int Foscaa(CSOUND *, XOSC *p); int Foscak(CSOUND *, XOSC *p); int Foscka(CSOUND *, XOSC *p); int Fosckk(CSOUND *, XOSC *p); int Foscset(CSOUND *, XOSC *p); int GardnerPink_init(CSOUND *, PINKISH *p); int GardnerPink_perf(CSOUND *, PINKISH *p); int adsynt(CSOUND *, ADSYNT *p); int adsyntset(CSOUND *, ADSYNT *p); int clip(CSOUND *, CLIP *p); int clip_set(CSOUND *, CLIP *p); int clockoff(CSOUND *, CLOCK *p); int clockon(CSOUND *, CLOCK *p); int clockread(CSOUND *, CLKRD *p); int clockset(CSOUND *, CLOCK *p); int scratchread(CSOUND *, SCRATCHPAD *p); int scratchwrite(CSOUND *, SCRATCHPAD *p); int cpuperc(CSOUND *, CPU_PERC *p); int cpuperc_S(CSOUND *, CPU_PERC *p); int hsboscil(CSOUND *, HSBOSC *p); int hsboscset(CSOUND *, HSBOSC *p); int impulse(CSOUND *, IMPULSE *p); int impulse_set(CSOUND *, IMPULSE *p); int instcount(CSOUND *, INSTCNT *p); int instcount_S(CSOUND *, INSTCNT *p); int totalcount(CSOUND *, INSTCNT *p); int kphsorbnk(CSOUND *, PHSORBNK *p); int ktrnseg(CSOUND *, TRANSEG *p); int ktrnsegr(CSOUND *csound, TRANSEG *p); int lpf18db(CSOUND *, LPF18 *p); int lpf18set(CSOUND *, LPF18 *p); int mac(CSOUND *, SUM *p); int maca(CSOUND *, SUM *p); int macset(CSOUND *, SUM *p); int maxalloc(CSOUND *, CPU_PERC *p); int mute_inst(CSOUND *, MUTE *p); int maxalloc_S(CSOUND *, CPU_PERC *p); int mute_inst_S(CSOUND *, MUTE *p); int pfun(CSOUND *, PFUN *p); int pfunk_init(CSOUND *, PFUNK *p); int pfunk(CSOUND *, PFUNK *p); int phsbnkset(CSOUND *, PHSORBNK *p); int phsorbnk(CSOUND *, PHSORBNK *p); int pinkish(CSOUND *, PINKISH *p); int pinkset(CSOUND *, PINKISH *p); int pitch(CSOUND *, PITCH *p); int pitchamdf(CSOUND *, PITCHAMDF *p); int pitchamdfset(CSOUND *, PITCHAMDF *p); int pitchset(CSOUND *, PITCH *p); int trnseg(CSOUND *, TRANSEG *p); int trnsegr(CSOUND *csound, TRANSEG *p); int trnset(CSOUND *, TRANSEG *p); int trnset_bkpt(CSOUND *, TRANSEG *p); int trnsetr(CSOUND *csound, TRANSEG *p); int varicol(CSOUND *, VARI *p); int varicolset(CSOUND *, VARI *p); int waveset(CSOUND *, BARRI *p); int wavesetset(CSOUND *, BARRI *p); int medfiltset(CSOUND *, MEDFILT *p); int medfilt(CSOUND *, MEDFILT *p); int kmedfilt(CSOUND *, MEDFILT *p); #endif /* PITCH_H */ csound-6.10.0/Opcodes/pitch0.c000066400000000000000000000153451321653344700160400ustar00rootroot00000000000000/* pitch0.c: Copyright (C) 1999 John ffitch, Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // #include "csdl.h" #include "csoundCore.h" /* PITCH.C */ #include "cwindow.h" #include #include "spectra.h" #include "pitch.h" #include "uggab.h" int mute_inst(CSOUND *csound, MUTE *p) { int n; int onoff = (*p->onoff == FL(0.0) ? 0 : 1); if (csound->ISSTRCOD(*p->ins)) { char *ss = get_arg_string(csound,*p->ins); n = csound->strarg2insno(csound,ss,1); } else n = *p->ins; if (UNLIKELY(n < 1)) return NOTOK; if (onoff==0) { csound->Warning(csound, Str("Muting new instances of instr %d\n"), n); } else { csound->Warning(csound, Str("Allowing instrument %d to start\n"), n); } csound->engineState.instrtxtp[n]->muted = onoff; return OK; } int mute_inst_S(CSOUND *csound, MUTE *p) { int n; int onoff = (*p->onoff == FL(0.0) ? 0 : 1); n = csound->strarg2insno(csound, ((STRINGDAT *)p->ins)->data, 1); if (UNLIKELY(n < 1)) return NOTOK; if (onoff==0) { csound->Warning(csound, Str("Muting new instances of instr %d\n"), n); } else { csound->Warning(csound, Str("Allowing instrument %d to start\n"), n); } csound->engineState.instrtxtp[n]->muted = onoff; return OK; } int instcount(CSOUND *csound, INSTCNT *p) { int n; if (csound->ISSTRCOD(*p->ins)) { char *ss = get_arg_string(csound,*p->ins); n = csound->strarg2insno(csound,ss,1); } else n = *p->ins; if (n<0 || n > csound->engineState.maxinsno || csound->engineState.instrtxtp[n] == NULL) *p->cnt = FL(0.0); else if (n==0) { /* Count all instruments */ int tot = 1; for (n=1; nengineState.maxinsno; n++) if (csound->engineState.instrtxtp[n]) /* If it exists */ tot += ((*p->opt) ? csound->engineState.instrtxtp[n]->instcnt : csound->engineState.instrtxtp[n]->active); *p->cnt = (MYFLT)tot; } else { //csound->Message(csound, "Instr %p \n", csound->engineState.instrtxtp[n]); *p->cnt = ((*p->opt) ? (MYFLT) csound->engineState.instrtxtp[n]->instcnt : (MYFLT) csound->engineState.instrtxtp[n]->active); if (*p->norel) *p->cnt -= csound->engineState.instrtxtp[n]->pending_release; } return OK; } int instcount_S(CSOUND *csound, INSTCNT *p) { int n = csound->strarg2insno(csound, ((STRINGDAT *)p->ins)->data, 1); if (n<0 || n > csound->engineState.maxinsno || csound->engineState.instrtxtp[n] == NULL) *p->cnt = FL(0.0); else if (n==0) { /* Count all instruments */ int tot = 1; for (n=1; nengineState.maxinsno; n++) if (csound->engineState.instrtxtp[n]) /* If it exists */ tot += ((*p->opt) ? csound->engineState.instrtxtp[n]->instcnt : csound->engineState.instrtxtp[n]->active); *p->cnt = (MYFLT)tot; } else { *p->cnt = ((*p->opt) ? (MYFLT) csound->engineState.instrtxtp[n]->instcnt : (MYFLT) csound->engineState.instrtxtp[n]->active); if (*p->norel) *p->cnt -= csound->engineState.instrtxtp[n]->pending_release; } return OK; } /* After gabriel maldonado */ int cpuperc(CSOUND *csound, CPU_PERC *p) { int n; if (csound->ISSTRCOD(*p->instrnum)) { char *ss = get_arg_string(csound,*p->instrnum); n = csound->strarg2insno(csound,ss,1); } else n = *p->instrnum; if (n > 0 && n <= csound->engineState.maxinsno && csound->engineState.instrtxtp[n] != NULL) /* If instrument exists */ csound->engineState.instrtxtp[n]->cpuload = *p->ipercent; return OK; } int cpuperc_S(CSOUND *csound, CPU_PERC *p) { int n = csound->strarg2insno(csound, ((STRINGDAT *)p->instrnum)->data, 1); if (n > 0 && n <= csound->engineState.maxinsno && csound->engineState.instrtxtp[n] != NULL) /* If instrument exists */ csound->engineState.instrtxtp[n]->cpuload = *p->ipercent; return OK; } int maxalloc(CSOUND *csound, CPU_PERC *p) { int n; if (csound->ISSTRCOD(*p->instrnum)) { char *ss = get_arg_string(csound,*p->instrnum); n = csound->strarg2insno(csound,ss,1); } else n = *p->instrnum; if (n > 0 && n <= csound->engineState.maxinsno && csound->engineState.instrtxtp[n] != NULL) /* If instrument exists */ csound->engineState.instrtxtp[n]->maxalloc = (int)*p->ipercent; return OK; } int maxalloc_S(CSOUND *csound, CPU_PERC *p) { int n = csound->strarg2insno(csound, ((STRINGDAT *)p->instrnum)->data, 1); if (n > 0 && n <= csound->engineState.maxinsno && csound->engineState.instrtxtp[n] != NULL) /* If instrument exists */ csound->engineState.instrtxtp[n]->maxalloc = (int)*p->ipercent; return OK; } int pfun(CSOUND *csound, PFUN *p) { int n = (int)MYFLT2LONG(*p->pnum); MYFLT ans; if (n<1) ans = FL(0.0); else if (ncurrevent->p[n]; else if (csound->currevent->c.extra && ncurrevent->c.extra[0]) ans = csound->currevent->c.extra[n-PMAX+1]; else ans = FL(0.0); /*csound->Message(csound, "p(%d) %f\n", n,ans);*/ *p->ans = ans; return OK; } int pfunk_init(CSOUND *csound, PFUNK *p) { int i, n = (int)MYFLT2LONG(*p->pnum); MYFLT ans, *pfield; if (n<1 || n>PMAX) ans = FL(0.0); else ans = csound->currevent->p[n]; /* save the pfields of the current event */ csound->AuxAlloc(csound, (csound->currevent->pcnt+1)*sizeof(MYFLT), &p->pfield); pfield = p->pfield.auxp; for (i=1; i<=csound->currevent->pcnt; i++) pfield[i] = csound->currevent->p[i]; *p->ans = ans; return OK; } int pfunk(CSOUND *csound, PFUNK *p) { int n = (int)MYFLT2LONG(*p->pnum); MYFLT ans, *pfield; if (n<1 || n>PMAX) { ans = FL(0.0); } else { pfield = p->pfield.auxp; ans = pfield[n]; } *p->ans = ans; return OK; } csound-6.10.0/Opcodes/pitchtrack.c000066400000000000000000000533001321653344700167760ustar00rootroot00000000000000/* pitchtrack.c kcps, kamp ptrack asig, ihopsize [, ipeaks] (c) Victor Lazzarini, 2007 based on M Puckette's pitch tracking algorithm. This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "interlocks.h" #include #define MINFREQINBINS 5 #define MAXHIST 3 #define MAXWINSIZ 8192 #define MINWINSIZ 128 #define DEFAULTWINSIZ 1024 #define NPREV 20 #define MAXPEAKNOS 100 #define DEFAULTPEAKNOS 20 #define MINBW FL(0.03) #define BINPEROCT 48 #define BPEROOVERLOG2 69.24936196 #define FACTORTOBINS FL(4/0.0145453) #define BINGUARD 10 #define PARTIALDEVIANCE FL(0.023) #define DBSCAL 3.333 #define DBOFFSET FL(-92.3) #define MINBIN 3 #define MINAMPS 40 #define MAXAMPS 50 #define THRSH FL(10.) static const MYFLT partialonset[] = { FL(0.0), FL(48.0), FL(76.0782000346154967102), FL(96.0), FL(111.45254855459339269887), FL(124.07820003461549671089), FL(134.75303625876499715823), FL(144.0), FL(152.15640006923099342109), FL(159.45254855459339269887), FL(166.05271769459026829915), FL(172.07820003461549671088), FL(177.62110647077242370064), FL(182.75303625876499715892), FL(187.53074858920888940907), FL(192.0), }; #define NPARTIALONSET ((int)(sizeof(partialonset)/sizeof(MYFLT))) #define COEF1 ((MYFLT)(.5 * 1.227054)) #define COEF2 ((MYFLT)(.5 * -0.302385)) #define COEF3 ((MYFLT)(.5 * 0.095326)) #define COEF4 ((MYFLT)(.5 * -0.022748)) #define COEF5 ((MYFLT)(.5 * 0.002533)) #define FLTLEN 5 typedef struct peak { MYFLT pfreq; MYFLT pwidth; MYFLT ppow; MYFLT ploudness; } PEAK; typedef struct histopeak { MYFLT hpitch; MYFLT hvalue; MYFLT hloud; int hindex; int hused; } HISTOPEAK; typedef struct pitchtrack { OPDS h; MYFLT *freq, *amp; MYFLT *asig,*size,*peak; AUXCH signal, prev, sin, spec1, spec2, peakarray; int numpks; int cnt; int histcnt; int hopsize; MYFLT sr; MYFLT cps; MYFLT dbs[NPREV]; MYFLT amplo; MYFLT amphi; MYFLT npartial; MYFLT dbfs; MYFLT prevf; } PITCHTRACK; void ptrack(CSOUND *csound,PITCHTRACK *p) { MYFLT *spec = (MYFLT *)p->spec1.auxp; MYFLT *spectmp = (MYFLT *)p->spec2.auxp; MYFLT *sig = (MYFLT *)p->signal.auxp; MYFLT *sinus = (MYFLT *)p->sin.auxp; MYFLT *prev = (MYFLT *)p->prev.auxp; PEAK *peaklist = (PEAK *)p->peakarray.auxp; HISTOPEAK histpeak; int i, j, k, hop = p->hopsize, n = 2*hop, npeak, logn = -1, count, tmp; MYFLT totalpower, totalloudness, totaldb; MYFLT maxbin, *histogram = spectmp + BINGUARD; MYFLT hzperbin = p->sr / (n + n); int numpks = p->numpks; int indx, halfhop = hop>>1; MYFLT best; MYFLT cumpow = 0, cumstrength = 0, freqnum = 0, freqden = 0; int npartials = 0, nbelow8 = 0; MYFLT putfreq; count = p->histcnt + 1; if (count == NPREV) count = 0; p->histcnt = count; tmp = n; while (tmp) { tmp >>= 1; logn++; } maxbin = BINPEROCT * (logn-2); for (i = 0, k = 0; i < hop; i++, k += 2) { spec[k] = sig[i] * sinus[k]; spec[k+1] = sig[i] * sinus[k+1]; } csound->ComplexFFT(csound, spec, hop); for (i = 0, k = 2*FLTLEN; i < hop; i+=2, k += 4) { spectmp[k] = spec[i]; spectmp[k+1] = spec[i+1]; } for (i = n - 2, k = 2*FLTLEN+2; i >= 0; i-=2, k += 4) { spectmp[k] = spec[i]; spectmp[k+1] = -spec[i+1]; } for (i = (2*FLTLEN), k = (2*FLTLEN-2);i=0; i-=2, k+=2) { spectmp[k] = spectmp[i]; spectmp[k+1] = -spectmp[k+1]; } for (i = j = 0, k = 2*FLTLEN; i < halfhop; i++, j+=8, k+=2) { MYFLT re, im; re= COEF1 * ( prev[k-2] - prev[k+1] + spectmp[k-2] - prev[k+1]) + COEF2 * ( prev[k-3] - prev[k+2] + spectmp[k-3] - spectmp[ 2]) + COEF3 * (-prev[k-6] +prev[k+5] -spectmp[k-6] +spectmp[k+5]) + COEF4 * (-prev[k-7] +prev[k+6] -spectmp[k-7] +spectmp[k+6]) + COEF5 * ( prev[k-10] -prev[k+9] +spectmp[k-10] -spectmp[k+9]); im= COEF1 * ( prev[k-1] +prev[k] +spectmp[k-1] +spectmp[k]) + COEF2 * (-prev[k-4] -prev[k+3] -spectmp[k-4] -spectmp[k+3]) + COEF3 * (-prev[k-5] -prev[k+4] -spectmp[k-5] -spectmp[k+4]) + COEF4 * ( prev[k-8] +prev[k+7] +spectmp[k-8] +spectmp[k+7]) + COEF5 * ( prev[k-9] +prev[k+8] +spectmp[k-9] +spectmp[k+8]); spec[j] = FL(0.707106781186547524400844362104849) * (re + im); spec[j+1] = FL(0.707106781186547524400844362104849) * (im - re); spec[j+4] = prev[k] + spectmp[k+1]; spec[j+5] = prev[k+1] - spectmp[k]; j += 8; k += 2; re= COEF1 * ( prev[k-2] -prev[k+1] -spectmp[k-2] +spectmp[k+1]) + COEF2 * ( prev[k-3] -prev[k+2] -spectmp[k-3] +spectmp[k+2]) + COEF3 * (-prev[k-6] +prev[k+5] +spectmp[k-6] -spectmp[k+5]) + COEF4 * (-prev[k-7] +prev[k+6] +spectmp[k-7] -spectmp[k+6]) + COEF5 * ( prev[k-10] -prev[k+9] -spectmp[k-10] +spectmp[k+9]); im= COEF1 * ( prev[k-1] +prev[k] -spectmp[k-1] -spectmp[k]) + COEF2 * (-prev[k-4] -prev[k+3] +spectmp[k-4] +spectmp[k+3]) + COEF3 * (-prev[k-5] -prev[k+4] +spectmp[k-5] +spectmp[k+4]) + COEF4 * ( prev[k-8] +prev[k+7] -spectmp[k-8] -spectmp[k+7]) + COEF5 * ( prev[k-9] +prev[k+8] -spectmp[k-9] -spectmp[k+8]); spec[j] = FL(0.707106781186547524400844362104849) * (re + im); spec[j+1] = FL(0.707106781186547524400844362104849) * (im - re); spec[j+4] = prev[k] - spectmp[k+1]; spec[j+5] = prev[k+1] + spectmp[k]; } for (i = 0; i < n + 4*FLTLEN; i++) prev[i] = spectmp[i]; for (i = 0; i < MINBIN; i++) spec[4*i + 2] = spec[4*i + 3] = FL(0.0); for (i = 4*MINBIN, totalpower = 0; i < (n-2)*4; i += 4) { MYFLT re = spec[i] - FL(0.5) * (spec[i-8] + spec[i+8]); MYFLT im = spec[i+1] - FL(0.5) * (spec[i-7] + spec[i+9]); spec[i+3] = (totalpower += (spec[i+2] = re * re + im * im)); } if (totalpower > FL(1.0e-9)) { totaldb = FL(DBSCAL) * LOG(totalpower/n); totalloudness = SQRT(SQRT(totalpower)); if (totaldb < 0) totaldb = 0; } else totaldb = totalloudness = FL(0.0); p->dbs[count] = totaldb + DBOFFSET; if (totaldb >= p->amplo) { npeak = 0; for (i = 4*MINBIN;i < (4*(n-2)) && npeak < numpks; i+=4) { MYFLT height = spec[i+2], h1 = spec[i-2], h2 = spec[i+6]; MYFLT totalfreq, peakfr, tmpfr1, tmpfr2, m, var, stdev; if (height < h1 || height < h2 || h1 < FL(0.00001)*totalpower || h2 < FL(0.00001)*totalpower) continue; peakfr= ((spec[i-8] - spec[i+8]) * (FL(2.0) * spec[i] - spec[i+8] - spec[i-8]) + (spec[i-7] - spec[i+9]) * (FL(2.0) * spec[i+1] - spec[i+9] - spec[i-7])) / (height + height); tmpfr1= ((spec[i-12] - spec[i+4]) * (FL(2.0) * spec[i-4] - spec[i+4] - spec[i-12]) + (spec[i-11] - spec[i+5]) * (FL(2.0) * spec[i-3] - spec[i+5] - spec[i-11])) / (FL(2.0) * h1) - 1; tmpfr2= ((spec[i-4] - spec[i+12]) * (FL(2.0) * spec[i+4] - spec[i+12] - spec[i-4]) + (spec[i-3] - spec[i+13]) * (FL(2.0) * spec[i+5] - spec[i+13] - spec[i-3])) / (FL(2.0) * h2) + 1; m = FL(0.333333333333) * (peakfr + tmpfr1 + tmpfr2); var = FL(0.5) * ((peakfr-m)*(peakfr-m) + (tmpfr1-m)*(tmpfr1-m) + (tmpfr2-m)*(tmpfr2-m)); totalfreq = (i>>2) + m; if (var * totalpower > THRSH * height || var < FL(1.0e-30)) continue; stdev = (MYFLT)sqrt((double)var); if (totalfreq < 4) totalfreq = 4; peaklist[npeak].pwidth = stdev; peaklist[npeak].ppow = height; peaklist[npeak].ploudness = SQRT(SQRT(height)); peaklist[npeak].pfreq = totalfreq; npeak++; } if (npeak > numpks) npeak = numpks; for (i = 0; i < maxbin; i++) histogram[i] = 0; //or memset(histogram, '\0', maxbin*sizeof(MYFLT)); for (i = 0; i < npeak; i++) { MYFLT pit = (MYFLT)(BPEROOVERLOG2 * LOG(peaklist[i].pfreq) - 96.0); MYFLT binbandwidth = FACTORTOBINS * peaklist[i].pwidth/peaklist[i].pfreq; MYFLT putbandwidth = (binbandwidth < FL(2.0) ? FL(2.0) : binbandwidth); MYFLT weightbandwidth = (binbandwidth < FL(1.0) ? FL(1.0) : binbandwidth); MYFLT weightamp = FL(4.0) * peaklist[i].ploudness / totalloudness; for (j = 0; j < NPARTIALONSET; j++) { MYFLT bin = pit - partialonset[j]; if (bin < maxbin) { MYFLT para, pphase, score = FL(30.0) * weightamp / ((j+p->npartial) * weightbandwidth); int firstbin = bin + FL(0.5) - FL(0.5) * putbandwidth; int lastbin = bin + FL(0.5) + FL(0.5) * putbandwidth; int ibw = lastbin - firstbin; if (firstbin < -BINGUARD) break; para = FL(1.0) / (putbandwidth * putbandwidth); for (k = 0, pphase = firstbin-bin; k <= ibw; k++,pphase += FL(1.0)) histogram[k+firstbin] += score * (FL(1.0) - para * pphase * pphase); } } } for (best = 0, indx = -1, j=0; j < maxbin; j++) if (histogram[j] > best) indx = j, best = histogram[j]; histpeak.hvalue = best; histpeak.hindex = indx; putfreq = EXP((FL(1.0) / BPEROOVERLOG2) * (histpeak.hindex + FL(96.0))); for (j = 0; j < npeak; j++) { MYFLT fpnum = peaklist[j].pfreq/putfreq; int pnum = (int)(fpnum + FL(0.5)); MYFLT fipnum = pnum; MYFLT deviation; if (pnum > 16 || pnum < 1) continue; deviation = FL(1.0) - fpnum/fipnum; if (deviation > -PARTIALDEVIANCE && deviation < PARTIALDEVIANCE) { MYFLT stdev, weight; npartials++; if (pnum < 8) nbelow8++; cumpow += peaklist[j].ppow; cumstrength += SQRT(SQRT(peaklist[j].ppow)); stdev = (peaklist[j].pwidth > MINBW ? peaklist[j].pwidth : MINBW); weight = FL(1.0) / ((stdev*fipnum) * (stdev*fipnum)); freqden += weight; freqnum += weight * peaklist[j].pfreq/fipnum; } } if ((nbelow8 < 4 || npartials < 7) && cumpow < FL(0.01) * totalpower) histpeak.hvalue = 0; else { double pitchpow = (cumstrength * cumstrength); MYFLT freqinbins = freqnum/freqden; pitchpow = pitchpow * pitchpow; if (freqinbins < MINFREQINBINS) histpeak.hvalue = 0; else { p->cps = histpeak.hpitch = hzperbin * freqnum/freqden; histpeak.hloud = FL(DBSCAL) * LOG(pitchpow/n); } } } } int pitchtrackinit(CSOUND *csound, PITCHTRACK *p) { int i, winsize = *p->size*2, powtwo, tmp; MYFLT *tmpb; if (UNLIKELY(winsize < MINWINSIZ || winsize > MAXWINSIZ)) { csound->Warning(csound, Str("ptrack: FFT size out of range; using %d\n"), winsize = DEFAULTWINSIZ); } tmp = winsize; powtwo = -1; while (tmp) { tmp >>= 1; powtwo++; } if (UNLIKELY(winsize != (1 << powtwo))) { csound->Warning(csound, Str("ptrack: FFT size not a power of 2; using %d\n"), winsize = (1 << powtwo)); } p->hopsize = *p->size; if (!p->signal.auxp || p->signal.size < p->hopsize*sizeof(MYFLT)) { csound->AuxAlloc(csound, p->hopsize*sizeof(MYFLT), &p->signal); } if (!p->prev.auxp || p->prev.size < (p->hopsize*2 + 4*FLTLEN)*sizeof(MYFLT)) { csound->AuxAlloc(csound, (p->hopsize*2 + 4*FLTLEN)*sizeof(MYFLT), &p->prev); } if (!p->sin.auxp || p->sin.size < (p->hopsize*2)*sizeof(MYFLT)) { csound->AuxAlloc(csound, (p->hopsize*2)*sizeof(MYFLT), &p->sin); } if (!p->spec2.auxp || p->spec2.size < (winsize*4 + 4*FLTLEN)*sizeof(MYFLT)) { csound->AuxAlloc(csound, (winsize*4 + 4*FLTLEN)*sizeof(MYFLT), &p->spec2); } if (!p->spec1.auxp || p->spec1.size < (winsize*4)*sizeof(MYFLT)) { csound->AuxAlloc(csound, (winsize*4)*sizeof(MYFLT), &p->spec1); } for (i = 0, tmpb = (MYFLT *)p->signal.auxp; i < p->hopsize; i++) tmpb[i] = FL(0.0); for (i = 0, tmpb = (MYFLT *)p->prev.auxp; i < winsize + 4 * FLTLEN; i++) tmpb[i] = FL(0.0); for (i = 0, tmpb = (MYFLT *)p->sin.auxp; i < p->hopsize; i++) tmpb[2*i] = (MYFLT) cos((PI*i)/(winsize)), tmpb[2*i+1] = -(MYFLT)sin((PI*i)/(winsize)); p->cnt = 0; if (*p->peak == 0 || *p->peak > MAXPEAKNOS) p->numpks = DEFAULTPEAKNOS; else p->numpks = *p->peak; if (!p->peakarray.auxp || p->peakarray.size < (p->numpks+1)*sizeof(PEAK)) { csound->AuxAlloc(csound, (p->numpks+1)*sizeof(PEAK), &p->peakarray); } p->cnt = 0; p->histcnt = 0; p->sr = CS_ESR; for (i = 0; i < NPREV; i++) p->dbs[i] = FL(-144.0); p->amplo = MINAMPS; p->amphi = MAXAMPS; p->npartial = 7; p->dbfs = FL(32768.0)/csound->e0dbfs; p->prevf = p->cps = 100.0; return (OK); } int pitchtrackprocess(CSOUND *csound, PITCHTRACK *p) { MYFLT *sig = p->asig; int i; MYFLT *buf = (MYFLT *)p->signal.auxp; int pos = p->cnt, h = p->hopsize; MYFLT scale = p->dbfs; int ksmps = CS_KSMPS; for (i=0; icps) *p->freq = p->cps; //else *p->freq = p->prevf; //p->prevf = *p->freq; *p->amp = p->dbs[p->histcnt]; p->cnt = pos; return OK; } typedef struct _pitchaf{ OPDS h; MYFLT *kpitch; MYFLT *asig, *kfmin, *kfmax, *iflow; AUXCH buff1, buff2, cor; int lag; MYFLT pitch; int len,size; } PITCHAF; int pitchafset(CSOUND *csound, PITCHAF *p){ int siz = (int)(CS_ESR/ (*p->iflow)); if (p->buff1.auxp == NULL || p->buff1.size < siz*sizeof(MYFLT)) csound->AuxAlloc(csound, siz*sizeof(MYFLT), &p->buff1); else memset(p->buff1.auxp, 0, p->buff1.size); if (p->buff2.auxp == NULL ||p-> buff2.size < siz*sizeof(MYFLT)) csound->AuxAlloc(csound, siz*sizeof(MYFLT), &p->buff2); else memset(p->buff2.auxp, 0, p->buff2.size); if (p->cor.auxp == NULL || p->cor.size < siz*sizeof(MYFLT)) csound->AuxAlloc(csound, siz*sizeof(MYFLT), &p->cor); else memset(p->cor.auxp, 0, p->cor.size); p->lag = 0; p->pitch = FL(0.0); p->len = siz; p->size = siz; return OK; } int pitchafproc(CSOUND *csound, PITCHAF *p) { int lag = p->lag,n, i, j, imax = 0, len = p->len, ksmps = CS_KSMPS; MYFLT *buff1 = (MYFLT *)p->buff1.auxp; MYFLT *buff2 = (MYFLT *)p->buff2.auxp; MYFLT *cor = (MYFLT *)p->cor.auxp; MYFLT *s = p->asig, pitch; //MYFLT ifmax = *p->kfmax; for (n=0; n < ksmps; n++) { for (i=0,j=lag; i < len; i++) { cor[lag] += buff1[i]*buff2[j]; j = j != len ? j+1 : 0; } buff2[lag++] = s[n]; if (lag == len) { float max = 0.0f; for (i=0; i < len; i++) { if (cor[i] > max) { max = cor[i]; if (i) imax = i; } buff1[i] = buff2[i]; cor[i] = FL(0.0); } len = CS_ESR/(*p->kfmin); if (len > p->size) len = p->size; lag = 0; } } p->lag = lag; p->len = len; if (imax) { pitch = CS_ESR/imax; if (pitch <= *p->kfmax) p->pitch = pitch; } *p->kpitch = p->pitch; return OK; } /* PLL Pitch tracker (Zoelzer et al) V Lazzarini, 2012 */ #define ROOT2 (1.4142135623730950488) enum {LP1=0, LP2, HP}; typedef struct biquad_ { double a0, a1, a2, b1, b2; double del1, del2; } BIQUAD; typedef struct plltrack_ { OPDS h; MYFLT *freq, *lock; MYFLT *asig,*kd,*klpf,*klpfQ,*klf,*khf,*kthresh; BIQUAD fils[6]; double ace, xce; double cos_x, sin_x, x1, x2; MYFLT klpf_o, klpfQ_o, klf_o,khf_o; } PLLTRACK; void update_coefs(CSOUND *csound, double fr, double Q, BIQUAD *biquad, int TYPE) { double k, ksq, div, ksqQ; switch(TYPE){ case LP2: k = tan(fr*csound->pidsr); ksq = k*k; ksqQ = ksq*Q; div = ksqQ+k+Q; biquad->b1 = (2*Q*(ksq-1.))/div; biquad->b2 = (ksqQ-k+Q)/div; biquad->a0 = ksqQ/div; biquad->a1 = 2*biquad->a0; biquad->a2 = biquad->a0; break; case LP1: k = 1.0/tan(csound->pidsr*fr); ksq = k*k; biquad->a0 = 1.0 / ( 1.0 + ROOT2 * k + ksq); biquad->a1 = 2.0*biquad->a0; biquad->a2 = biquad->a0; biquad->b1 = 2.0 * (1.0 - ksq) * biquad->a0; biquad->b2 = ( 1.0 - ROOT2 * k + ksq) * biquad->a0; break; case HP: k = tan(csound->pidsr*fr); ksq = k*k; biquad->a0 = 1.0 / ( 1.0 + ROOT2 * k + ksq); biquad->a1 = -2.*biquad->a0; biquad->a2 = biquad->a0; biquad->b1 = 2.0 * (ksq - 1.0) * biquad->a0; biquad->b2 = ( 1.0 - ROOT2 * k + ksq) * biquad->a0; break; } } int plltrack_set(CSOUND *csound, PLLTRACK *p) { int i; p->x1 = p->cos_x = p->sin_x = 0.0; p->x2 = 1.0; p->klpf_o = p->klpfQ_o = p->klf_o = p->khf_o = 0.0; update_coefs(csound,10.0, 0.0, &p->fils[4], LP1); p->ace = p->xce = 0.0; for (i=0; i < 6; i++) p->fils[i].del1 = p->fils[i].del2 = 0.0; return OK; } int plltrack_perf(CSOUND *csound, PLLTRACK *p) { int ksmps, i, k; MYFLT _0dbfs; double a0[6], a1[6], a2[6], b1[6], b2[6]; double *mem1[6], *mem2[6]; double *ace, *xce; double *cos_x, *sin_x, *x1, *x2; double scal,esr; BIQUAD *biquad = p->fils; MYFLT *asig=p->asig,kd=*p->kd,klpf,klpfQ,klf,khf,kthresh; MYFLT *freq=p->freq, *lock =p->lock, itmp = asig[0]; int itest = 0; _0dbfs = csound->e0dbfs; ksmps = CS_KSMPS; esr = CS_ESR; scal = 2.0*csound->pidsr; /* check for muted input & bypass */ if (ksmps > 1){ for (i=0; i < ksmps; i++) { if (asig[i] != 0.0 && asig[i] != itmp) { itest = 1; break; } itmp = asig[i]; } if (!itest) return OK; } else if (*asig == 0.0) return OK; if (*p->klpf == 0) klpf = 20.0; else klpf = *p->klpf; if (*p->klpfQ == 0) klpfQ = 1./3.; else klpfQ = *p->klpfQ; if (*p->klf == 0) klf = 20.0; else klf = *p->klf; if (*p->khf == 0) khf = 1500.0; else khf = *p->khf; if (*p->kthresh == 0.0) kthresh= 0.001; else kthresh = *p->kthresh; if (p->khf_o != khf) { update_coefs(csound, khf, 0.0, &biquad[0], LP1); update_coefs(csound, khf, 0.0, &biquad[1], LP1); update_coefs(csound, khf, 0.0, &biquad[2], LP1); p->khf_o = khf; } if (p->klf_o != klf) { update_coefs(csound, klf, 0.0, &biquad[3], HP); p->klf_o = klf; } if (p->klpf_o != klpf || p->klpfQ_o != klpfQ ) { update_coefs(csound, klpf, klpfQ, &biquad[5], LP2); p->klpf_o = klpf; p->klpfQ_o = klpfQ; } for (k=0; k < 6; k++) { a0[k] = biquad[k].a0; a1[k] = biquad[k].a1; a2[k] = biquad[k].a2; b1[k] = biquad[k].b1; b2[k] = biquad[k].b2; mem1[k] = &(biquad[k].del1); mem2[k] = &(biquad[k].del2); } cos_x = &p->cos_x; sin_x = &p->sin_x; x1 = &p->x1; x2 = &p->x2; xce = &p->xce; ace = &p->ace; for (i=0; i < ksmps; i++){ double input = (double) (asig[i]/_0dbfs), env; double w, y, icef = 0.99, fosc, xd, c, s, oc; /* input stage filters */ for (k=0; k < 4 ; k++){ w = input - *(mem1[k])*b1[k] - *(mem2[k])*b2[k]; y = w*a0[k] + *(mem1[k])*a1[k] + *(mem2[k])*a2[k]; *(mem2[k]) = *(mem1[k]); *(mem1[k]) = w; input = y; } /* envelope extraction */ w = FABS(input) - *(mem1[k])*b1[k] - *(mem2[k])*b2[k]; y = w*a0[k] + *(mem1[k])*a1[k] + *(mem2[k])*a2[k]; *(mem2[k]) = *(mem1[k]); *(mem1[k]) = w; env = y; k++; /* constant envelope */ if (env > kthresh) input /= env; else input = 0.0; /*post-ce filter */ *ace = (1.-icef)*(input + *xce)/2. + *ace*icef; *xce = input; /* PLL */ xd = *cos_x * (*ace) * kd * esr; w = xd - *(mem1[k])*b1[k] - *(mem2[k])*b2[k]; y = w*a0[k] + *(mem1[k])*a1[k] + *(mem2[k])*a2[k]; *(mem2[k]) = *(mem1[k]); *(mem1[k]) = w; freq[i] = FABS(2*y); lock[i] = *ace * (*sin_x); fosc = y + xd; /* quadrature osc */ *sin_x = *x1; *cos_x = *x2; oc = fosc*scal; c = COS(oc); s = SIN(oc); *x1 = *sin_x*c + *cos_x*s; *x2 = -*sin_x*s + *cos_x*c; } return OK; } #define S(x) sizeof(x) static OENTRY pitchtrack_localops[] = { {"ptrack", S(PITCHTRACK), 0, 5, "kk", "aio", (SUBR)pitchtrackinit, NULL, (SUBR)pitchtrackprocess}, {"pitchac", S(PITCHTRACK), 0, 5, "k", "akki", (SUBR)pitchafset, NULL, (SUBR)pitchafproc}, {"plltrack", S(PLLTRACK), 0, 5, "aa", "akOOOOO", (SUBR)plltrack_set, NULL, (SUBR)plltrack_perf} }; LINKAGE_BUILTIN(pitchtrack_localops) csound-6.10.0/Opcodes/platerev.c000066400000000000000000000212321321653344700164630ustar00rootroot00000000000000/* platerev.c: Copyright (C) 2006 by Stefan Bilbao 2012 John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csdl.h" #include /* #undef CS_KSMPS */ /* #define CS_KSMPS (csound->GetKsmps(csound)) */ typedef struct { OPDS h; MYFLT *aout[40]; MYFLT *tabins; MYFLT *tabout; MYFLT *bndry; MYFLT *asp; MYFLT *stiff; MYFLT *decay; MYFLT *loss; MYFLT *ain[40]; // Internals double s00, s10, s01, s11, s20, s02, t00, t01, t10; uint32_t nin, nout, Nx, Ny; double *u, *u1, *u2; AUXCH auxch; double L, dy, dt; MYFLT *in_param, *out_param; double ci[40], si[40], co[40], so[40]; } PLATE; static int platerev_init(CSOUND *csound, PLATE *p) { FUNC *inp, *outp; double a = *p->asp; double dt = (p->dt = 1.0/csound->GetSr(csound)); /* time step */ double sig = (csound->GetSr(csound)+csound->GetSr(csound))* (POWER(10.0, FL(3.0)*dt/(*p->decay))-FL(1.0)); /* loss constant */ double b2 = *p->loss; double dxmin = 2.0*sqrt(dt*(b2+hypot(*p->loss, *p->stiff))); uint32_t Nx = (p->Nx = (uint32_t)floor(1.0/dxmin)); uint32_t Nx5 = Nx+5; double dx = 1.0/(double)Nx; uint32_t Ny = (p->Ny = (uint32_t)floor(a*Nx)); double dy = (p->dy = *p->asp/Ny); double alf = dx/dy; double mu = dt*(*p->stiff)*Nx*Nx; double mu2 = mu*mu; double eta = 1.0/(1.0+sig*dt); double V = 2.0*b2*dt*Nx*Nx; uint32_t qq; p->nin = (int) (p->INOCOUNT) - 7; p->nout = (int) (p->OUTOCOUNT); if (UNLIKELY((inp = csound->FTnp2Find(csound,p->tabins)) == NULL || inp->flen < (unsigned)3*p->nin)) { return csound->InitError(csound, Str("Missing input table or too short")); } if (UNLIKELY((outp = csound->FTnp2Find(csound,p->tabout)) == NULL || outp->flen < (unsigned int)3*p->nout)) { return csound->InitError(csound, Str("Missing output table or too short")); } p->in_param = inp->ftable; p->out_param = outp->ftable; p->L = (a<1.0 ? a : 1.0); csound->AuxAlloc(csound, 3*Nx5*(Ny+5)*sizeof(double), &p->auxch); p->u = (double*)p->auxch.auxp; p->u1 = p->u+Nx5*(Ny+5); p->u2 = p->u1+Nx5*(Ny+5); p->s00 = 2.0*eta*(1.0-mu2*(3.0+4.0*alf*alf+3.0*alf*alf*alf*alf)- V*(1.0+alf*alf)); p->s10 = (4.0*mu2*(1.0+alf*alf)+V)*eta; p->s01 = alf*alf*(4.0*mu2*(1.0+alf*alf)+V)*eta; p->s11 = -2.0*mu2*eta*alf*alf; p->s02 = (p->s20 = -eta*mu2)*alf*alf*alf*alf; p->t00 = (-(1.0-sig*dt)+2.0*V*(1.0+alf*alf))*eta; p->t10 = -V*eta; p->t01 = -V*eta*alf*alf; for (qq=0; qqnin; qq++) { p->ci[qq] = cos((double)p->in_param[3*qq+2]); p->si[qq] = sin((double)p->in_param[3*qq+2]); } for (qq=0; qqnout; qq++) { p->co[qq] = cos((double)p->out_param[3*qq+2]); p->so[qq] = sin((double)p->out_param[3*qq+2]); } return OK; } static int platerev(CSOUND *csound, PLATE *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, j, nsmps = CS_KSMPS; uint32_t Ny = p->Ny, Nx = p->Nx; uint32_t Nx5 = Nx+5; int bc = (int) MYFLT2LONG(*p->bndry); double *u = p->u, *u1 = p->u1, *u2 = p->u2; double s00 = p->s00, s10 = p->s10, s01 = p->s01, s11 = p->s11, s20 = p->s20, s02 = p->s02, t00 = p->t00, t10 = p->t10, t01 = p->t01; double dt = p->dt, dy = p->dy; uint32_t n, qq; MYFLT *uin; double wi[40], wo[40], sdi[40], cdi[40], sdo[40], cdo[40]; if (UNLIKELY(early)) nsmps -= early; for (qq=0; qq<(uint32_t)p->nin; qq++) { double delta = TWOPI*(double)p->in_param[3*qq]*dt; cdi[qq] = cos(delta); sdi[qq] = sin(delta); wi[qq] = p->L*0.5*(double)p->in_param[3*qq+1]; delta = TWOPI*(double)p->out_param[3*qq]*dt; cdo[qq] = cos(delta); sdo[qq] = sin(delta); wo[qq] = (p->L*0.5)*(double)p->out_param[3*qq+1]; if (UNLIKELY(offset)) memset(p->aout[qq], '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) memset(&p->aout[qq][nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nnin; qq++) { double w = wi[qq]; double cv = p->ci[qq]*cdi[qq] - p->si[qq]*sdi[qq]; double sv = p->ci[qq]*sdi[qq] + p->si[qq]*cdi[qq]; double xid = (0.5+w*cv)*Nx; double yid = ((*p->asp)*0.5+w*sv)/dy; int xi = (int)(floor(xid))+2; int yi = (int)(floor(yid))+2; double xf = xid-(double)(xi-2); double yf = yid-(double)(yi-2); double xyf = xf*yf; uin=p->ain[qq]; p->ci[qq] = cv; p->si[qq] = sv; yi = Nx5*yi + xi; u[yi] += (1.0-xf-yf+xyf)*uin[n]; u[1+yi] += (xf-xyf)*uin[n]; u[1+Nx5+yi] += xyf*uin[n]; u[Nx5+yi] += (yf-xyf)*uin[n]; } /* %%%% readout */ for (qq=0; qqnout; qq++) { double w = wo[qq]; double cv = p->co[qq]*cdo[qq] - p->so[qq]*sdo[qq]; double sv = p->co[qq]*sdo[qq] + p->so[qq]*cdo[qq]; double xod = (0.5+w*cv)*Nx; double yod = (*p->asp*0.5+w*sv)/dy; int xo = (int)(floor(xod))+2; int yo = (int)(floor(yod))+2; double xf = xod-(double)(xo-2); double yf = yod-(double)(yo-2); double xyf = xf*yf; p->co[qq] = cv; p->so[qq] = sv; yo = yo*Nx5 + xo; (p->aout[qq])[n] = (MYFLT)((1.0-xf-yf+xyf)*u[yo]+ (yf-xyf)*u[Nx5+yo]+ (xf-xyf)*u[1+yo]+ xyf*u[1+Nx5+yo])/FL(25.0); } { double *tmp = u2; /* cycle U*/ u2 = u1; u1 = u; u = tmp; } } p->u = u; p->u1 = u1; p->u2 = u2; return OK; } static OENTRY localops[] = { { "platerev", sizeof(PLATE), 0, 5, "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", "iikiiiiy", (SUBR) platerev_init, NULL, (SUBR) platerev }, }; LINKAGE csound-6.10.0/Opcodes/pluck.c000066400000000000000000000271741321653344700157720ustar00rootroot00000000000000/* pluck.c: Copyright (C) 1994, 2000 Michael A. Casey, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* pluck.c -- plucked string class definitions */ /* * Code conversion from C++ to C (October 1994) * Author: Michael A. Casey MIT Media Labs * Language: C * Copyright (c) 1994 MIT Media Lab, All Rights Reserved * Some modifications John ffitch, 2000, simplifying code */ #include "stdopcod.h" #include "wavegde.h" #include "pluck.h" /* external prototypes */ static void pluckSetFilters(CSOUND*, WGPLUCK*, MYFLT, MYFLT); static MYFLT *pluckShape(CSOUND*, WGPLUCK*); /* pluck shape function */ /* ***** class filter3 -- JPff ****** */ /* ::set -- set the coefficients */ static inline void filter3Set(filter3* filt, MYFLT a0, MYFLT a1) { filt->a0 = a0; filt->a1 = a1; filt->x1 = filt->x2 = FL(0.0); #ifdef WG_VERBOSE csound->Message(csound, "c[0]=%f; c[1]=%f; c[2]=\n", a0, a1, a0); csound->Message(csound, "Zeros at %f, %f\n", (-a1-sqrt(a1*a1-4.0*a0*a0))/(2.0*a0), (-a1+sqrt(a1*a1-4.0*a0*a0))/(2.0*a0)); #endif } /* ***** plucked string class member function definitions ***** */ /* pluck::excite -- excitation function for plucked string */ static int pluckExcite(CSOUND *csound, WGPLUCK* p) { MYFLT *shape; int i; int size = p->wg.upperRail.size; /* set the delay element to pick at */ p->pickSamp=(len_t)(size * *p->pickPos); if (UNLIKELY(p->pickSamp<1)) p->pickSamp = 1; /* set the bridge filter coefficients for the correct magnitude response */ pluckSetFilters(csound, p,*p->Aw0,*p->AwPI);/*attenuation in dB at w0 and PI*/ /* add the pick shape to the waveguide rails */ if (UNLIKELY((shape = pluckShape(csound,p))==NULL)) return NOTOK; /* add shape to lower rail */ for (i=0;iwg.lowerRail.data[i] = shape[i]; /* Why add? Starts at zero anyway */ p->wg.upperRail.data[size-i-1] = shape[i]; } /* free the space used by the pluck shape */ csound->Free(csound, shape); /* set excitation flag */ p->wg.excited = 1; return OK; } /* ::pluck -- create the plucked-string instrument */ static int pluckPluck(CSOUND *csound, WGPLUCK* p) { /* ndelay = total required delay - 1.0 */ len_t ndelay = (len_t) (CS_ESR / *p->freq - FL(1.0)); #ifdef WG_VERBOSE csound->Message(csound, "pluckPluck -- allocating memory..."); #endif /* Allocate auxillary memory or reallocate if size has changed */ csound->AuxAlloc(csound, (len_t)(ndelay/2)*sizeof(MYFLT), &p->upperData); csound->AuxAlloc(csound, (len_t)(ndelay/2)*sizeof(MYFLT), &p->lowerData); #ifdef WG_VERBOSE csound->Message(csound, "done.\n"); #endif /* construct waveguide object */ #ifdef WG_VERBOSE csound->Message(csound, "Constructing waveguide..."); #endif waveguideWaveguide(csound, (waveguide*)&p->wg, /* waveguide */ (MYFLT)*p->freq, /* f0 frequency */ (MYFLT*)p->upperData.auxp, /* upper rail data */ (MYFLT*)p->lowerData.auxp); /* lower rail data */ #ifdef WG_VERBOSE csound->Message(csound, "done.\n"); #endif /* Excite the string with the input parameters */ #ifdef WG_VERBOSE csound->Message(csound, "Exciting the string..."); #endif pluckExcite(csound,p); #ifdef WG_VERBOSE csound->Message(csound, "done\n"); #endif return OK; } /* pluck::setFilters -- frequency dependent filter calculations */ static void pluckSetFilters(CSOUND *csound, WGPLUCK* p, MYFLT A_w0, MYFLT A_PI) { /* Define the required magnitude response of H1 at w0 and PI */ /* Constrain attenuation specification to dB per second */ MYFLT NRecip = p->wg.f0 * csound->onedsr; /* N=t*CS_ESR/f0 */ MYFLT H1_w0 = POWER(FL(10.0),-A_w0*FL(0.05)*NRecip); MYFLT H1_PI = POWER(FL(10.0),-A_PI*FL(0.05)*NRecip); { /* The tuning filter is allpass, so no dependency for H1 */ /* therefore solve for the coefficients of the bridge filter directly */ MYFLT cosw0 = COS(p->wg.w0); MYFLT a1=(H1_w0+cosw0*H1_PI)/(1+cosw0); MYFLT a0 = (a1 - H1_PI)*FL(0.5); /* apply constraints on coefficients (see Sullivan)*/ if (UNLIKELY((a0bridge,a0, a1); /* set the new bridge coefficients */ } } /* ::pluckShape -- the pluck function for a string */ static MYFLT *pluckShape(CSOUND *csound, WGPLUCK* p) { MYFLT scale = *p->amp; MYFLT *shape; len_t len=p->wg.lowerRail.size; len_t i; MYFLT M; /* This memory must be freed after use */ shape = (MYFLT *)csound->Malloc(csound, len*sizeof(MYFLT)); if (UNLIKELY(!shape)) { csound->InitError(csound, Str("wgpluck:Could not allocate for initial shape")); return NULL; } scale = FL(0.5) * scale; /* Scale was squared!! */ for (i=0;ipickSamp;i++) shape[i] = scale*i / p->pickSamp; M = (MYFLT)len - p->pickSamp; for (i=0;ipickSamp+i] = scale - (i*scale/M); return shape; } /* ::update -- waveguide rail insert and update routine */ static inline void guideRailUpdate(guideRail *gr,MYFLT samp) { *gr->pointer++ = samp; if (UNLIKELY(gr->pointer > gr->endPoint)) gr->pointer = gr->data; } /* ::getSamps -- the sample generating routine */ static int pluckGetSamps(CSOUND *csound, WGPLUCK* p) { MYFLT yr0,yl0,yrM,ylM; /* Key positions on the waveguide */ MYFLT *ar = p->out; /* The sample output buffer */ len_t M=p->wg.upperRail.size; /* Length of the guide rail */ uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; len_t n,nsmps=CS_KSMPS; /* int i = 0; */ MYFLT *fdbk = p->afdbk; /* set the delay element to pickup at */ len_t pickupSamp=(len_t)(M * *p->pickupPos); if (UNLIKELY(pickupSamp<1)) pickupSamp = 1; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;nwg.upperRail,pickupSamp) +guideRailAccess(&p->wg.lowerRail,M-pickupSamp); yrM = guideRailAccess(&p->wg.upperRail,M-1);/* wave into the nut */ ylM = -yrM; /* reflect the incoming sample at the nut */ yl0 = guideRailAccess(&p->wg.lowerRail,0); /* wave into bridge */ yr0 = -filter3FIR(&p->bridge,yl0); /* bridge reflection filter */ yr0 = filterAllpass(&p->wg,yr0); /* allpass tuning filter */ yr0 += *fdbk++; /* Surely better to inject here */ guideRailUpdate(&p->wg.upperRail,yr0); /* update the upper rail*/ guideRailUpdate(&p->wg.lowerRail,ylM); /* update the lower rail*/ } return OK; } /* * Code conversion from C++ to C (October 1994) * Author: Michael A. Casey MIT Media Labs * Language: C * Copyright (c) 1994 MIT Media Lab, All Rights Reserved */ #define EPSILON (FL(0.25)) /* threshold for small tuning values */ /* prototypes */ static inline int circularBufferCircularBuffer(CSOUND *csound, circularBuffer* cb, len_t N) { MYFLT *data = cb->data; /* if (UNLIKELY(!data)) */ /* return csound->InitError(csound, */ /* Str("wgpluck: Buffer memory not allocated!")); */ /* Initialize pointers and variables */ cb->size = N; cb->inited = 1; cb->pointer = data; cb->endPoint = data+cb->size-1; cb->insertionPoint = data; cb->extractionPoint = data; return OK; } /* ***** class guideRail -- waveguide rail derived class ***** */ /* Guide rail is a circular buffer */ #define guideRailGuideRail(csound,gr,d) circularBufferCircularBuffer(csound, gr,d) /* ::access -- waveguide rail access routine */ static MYFLT guideRailAccess(guideRail* gr, len_t pos) { MYFLT *s = gr->pointer - pos; while (s < gr->data) s += gr->size; while (s > gr->endPoint) s -= gr->size; return *s; } /* ::FIR -- direct convolution filter routine */ static MYFLT filter3FIR(filter3* filt, MYFLT s) { /* y[n] = c1*x[n] + c2*x[n-1] + ... + cM*x[n-M+1] */ MYFLT ans = filt->a0 * (s+filt->x2) + filt->a1 * filt->x1; filt->x2 = filt->x1; filt->x1 = s; return ans; } /* ::allpass -- accurate 1st-order allpass filter routine */ /* c = allpass filter coefficient, input sample */ static MYFLT filterAllpass(waveguide* wg,MYFLT s) { /* p[n] = x[n] + gp[n-1], y[n] = p[n-1] - gp[n] */ MYFLT q = s + wg->c*wg->p; s = - wg->c * q + wg->p; wg->p = q; return s; } /* q = 0.000000 wg->c = -0.047619 wg->p = 0.000000 s = 0.000000 s1 = nan */ /* ***** Waveguide base-class member definitions ***** */ /* ::waveguide -- constructor * sets delay lengths and filter responses for frequency * total delay length = (SR/f0) * also sets tuning filter for fractional delay for exact tuning */ static void waveguideWaveguide(CSOUND *csound, waveguide* wg, MYFLT freq, MYFLT* upperData, MYFLT* lowerData) { MYFLT size, df; wg->excited = 0; wg->p = FL(0.0); /* tuning filter state variable */ wg->f0 = freq; wg->w0 = csound->tpidsr*freq; #ifdef WG_VERBOSE csound->Message(csound, "f0=%f, w0=%f\n", wg->f0, wg->w0); #endif /* Calculate the size of the delay lines and set them */ /* Set pointers to appropriate positions in instrument memory */ size = CS_ESR / freq - FL(1.0); /* construct the fractional part of the delay */ df = (size - (len_t)size); /* fractional delay amount */ if (dfupperRail.data = upperData; wg->lowerRail.data = lowerData; #ifdef WG_VERBOSE csound->Message(csound, "size=%d+1, df=%f\n", (len_t) size, df); #endif size = size*FL(0.5); circularBufferCircularBuffer(csound, &wg->upperRail,(len_t)size); circularBufferCircularBuffer(csound, &wg->lowerRail,(len_t)size); waveguideSetTuning(csound, wg,df); } /* Set the allpass tuning filter coefficient */ static void waveguideSetTuning(CSOUND *csound, waveguide* wg, MYFLT df) { MYFLT k=csound->onedsr * wg->w0; /*c = (1.0-df)/(1.0+df);*/ /* Solve for coefficient from df */ wg->c = -sinf((k-k*df)/FL(2.0))/sinf((k+k*df)/FL(2.0)); #ifdef WG_VERBOSE csound->Message(csound, "tuning :c=%f\n", wg->c); #endif } #define S(x) sizeof(x) static OENTRY localops[] = { { "wgpluck",S(WGPLUCK),0, 5,"a","iikiiia", (SUBR)pluckPluck,NULL,(SUBR)pluckGetSamps} }; int pluck_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/pluck.h000066400000000000000000000036451321653344700157740ustar00rootroot00000000000000/* pluck.h: Copyright (C) 1994, 2000 Michael A. Casey, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* pluck.h -- plucked string class declarations */ /* * Code conversion from C++ to C (October 1994) * Author: Michael A. Casey MIT Media Labs * Language: C * Copyright (c) 1994 MIT Media Lab, All Rights Reserved * Some modifications by John ffitch, 2000, simplifying code */ #ifndef _pluck_h #define _pluck_h #include "wavegde.h" /* pluck -- derived class to implement simple plucked string algorithm */ typedef struct { OPDS h; MYFLT *out; /* plucked string output */ MYFLT *freq,*amp,*pickupPos,*pickPos,*Aw0,*AwPI,*afdbk; /* inputs */ waveguide wg; /* general waveguide model structure */ filter3 bridge; /* lowpass bridge filter */ len_t pickSamp; /* where to pluck the string */ /* Auxillary memory allocation */ AUXCH upperData; /* upper rail data space */ AUXCH lowerData; /* lower rail data space */ AUXCH bridgeCoeffs; /* Bridge filter coefficients */ AUXCH bridgeData; /* Bridge filter lattice data */ } WGPLUCK; #endif csound-6.10.0/Opcodes/psynth.c000066400000000000000000001163051321653344700161740ustar00rootroot00000000000000/* psynth.c (c) Victor Lazzarini, 2005 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* TRADSYN Streaming partial track additive synthesis asig tradsyn fin, kscal, kpitch, kmaxtracks, ifn asig - output signal fin - TRACKS streaming spectral signal kscal - amplitude scaling kpitch - pitch scaling kmaxtracks - max output tracks ifn - function table containing a sinusoid (sine or cosine) SINSYN Streaming partial track additive synthesis with cubic phase interpolation asig sinsyn fin, kscal, kmaxtracks, ifn asig - output signal fin - TRACKS streaming spectral signal kscal - amplitude scaling kmaxtracks - max output tracks ifn - function table containing a sinusoid (generally a cosine) RESYN Streaming partial track additive synthesis with cubic phase interpolation with pitch scaling and support for timescale-modified input signals. asig sinsyn fin, kscal, kpitch, kmaxtracks, ifn asig - output signal fin - TRACKS streaming spectral signal kscal - amplitude scaling kpitch - pitch scaling kmaxtracks - max output tracks ifn - function table containing a sinusoid (generally a cosine) PLUS a number of track processing opcodes. */ #include "pvs_ops.h" #include "pstream.h" typedef struct _psyn { OPDS h; MYFLT *out; PVSDAT *fin; MYFLT *scal, *pitch, *maxtracks, *ftb, *thresh; int tracks, pos, numbins, hopsize; FUNC *func; AUXCH sum, amps, freqs, phases, trackID; double factor, facsqr, min; } _PSYN; typedef struct _psyn2 { OPDS h; MYFLT *out; PVSDAT *fin; MYFLT *scal, *maxtracks, *ftb, *thresh; int tracks, pos, numbins, hopsize; FUNC *func; AUXCH sum, amps, freqs, phases, trackID; double factor, facsqr, min; } _PSYN2; static int psynth_init(CSOUND *csound, _PSYN *p) { int numbins = p->fin->N / 2 + 1; if (UNLIKELY(p->fin->format != PVS_TRACKS)) { return csound->InitError(csound, Str("psynth: first input not in TRACKS format\n")); } p->func = csound->FTnp2Find(p->h.insdshead->csound, p->ftb); if (UNLIKELY(p->func == NULL)) { return csound->InitError(csound, Str("psynth: function table not found\n")); } p->tracks = 0; p->hopsize = p->fin->overlap; p->pos = 0; p->numbins = numbins; p->factor = p->hopsize * csound->onedsr; p->facsqr = p->factor * p->factor; if(*p->thresh == -1) p->min = 0.00002*csound->Get0dBFS(csound); else p->min = *p->thresh*csound->Get0dBFS(csound); if (p->amps.auxp == NULL || (unsigned) p->amps.size < sizeof(double) * numbins) csound->AuxAlloc(csound, sizeof(double) * numbins, &p->amps); else memset(p->amps.auxp, 0, sizeof(double) * numbins ); if (p->freqs.auxp == NULL || (unsigned) p->freqs.size < sizeof(double) * numbins) csound->AuxAlloc(csound, sizeof(double) * numbins, &p->freqs); else memset(p->freqs.auxp, 0, sizeof(double) * numbins ); if (p->phases.auxp == NULL || (unsigned) p->phases.size < sizeof(double) * numbins) csound->AuxAlloc(csound, sizeof(double) * numbins, &p->phases); else memset(p->phases.auxp, 0, sizeof(double) * numbins ); if (p->sum.auxp == NULL || (unsigned) p->sum.size < sizeof(double) * p->hopsize) csound->AuxAlloc(csound, sizeof(double) * p->hopsize, &p->sum); else memset(p->sum.auxp, 0, sizeof(double) * p->hopsize ); if (p->trackID.auxp == NULL || (unsigned) p->trackID.size < sizeof(int) * numbins) csound->AuxAlloc(csound, sizeof(int) * numbins, &p->trackID); else memset(p->trackID.auxp, 0, sizeof(int) * numbins ); return OK; } static int psynth_process(CSOUND *csound, _PSYN *p) { double ampnext, amp, freq, freqnext, phase, ratio; double a, f, frac, incra, incrph, factor; MYFLT scale = *p->scal, pitch = *p->pitch; int ndx, size = p->func->flen; int i, j, k, m, id; int notcontin = 0; int contin = 0; int tracks = p->tracks, maxtracks = (int) *p->maxtracks; MYFLT *tab = p->func->ftable, *out = p->out; float *fin = (float *) p->fin->frame.auxp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int pos = p->pos; double *amps = (double *) p->amps.auxp, *freqs = (double *) p->freqs.auxp; double *phases = (double *) p->phases.auxp; MYFLT *outsum = (MYFLT *) p->sum.auxp; int *trackID = (int *) p->trackID.auxp; int hopsize = p->hopsize; double min = p->min; ratio = size * csound->onedsr; factor = p->factor; maxtracks = p->numbins > maxtracks ? maxtracks : p->numbins; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { out[n] = outsum[pos]; pos++; if (pos == hopsize) { memset(outsum, 0, sizeof(MYFLT) * hopsize); /* for each track */ i = j = k = 0; while (i < maxtracks * 4) { ampnext = (double) fin[i] * scale; freqnext = (double) fin[i + 1] * pitch; if ((id = (int) fin[i + 3]) != -1) { j = k + notcontin; if (k < tracks - notcontin) { if (trackID[j] == id) { /* if this is a continuing track */ contin = 1; freq = freqs[j]; phase = phases[j]; amp = amps[j]; } else { /* if this is a dead track */ contin = 0; freqnext = freq = freqs[j]; phase = phases[j]; amp = amps[j]; ampnext = FL(0.0); } } else { /* new track */ contin = 1; freq = freqnext; phase = -freq * factor; amp = FL(0.0); } if (amp > min) { /* interpolation & track synthesis loop */ a = amp; f = freq; incra = (ampnext - amp) / hopsize; incrph = (freqnext - freq) / hopsize; for (m = 0; m < hopsize; m++) { /* table lookup oscillator */ phase += f * ratio; while (phase < 0) phase += size; while (phase >= size) phase -= size; ndx = (int) phase; frac = phase - ndx; outsum[m] += a * (tab[ndx] + (tab[ndx + 1] - tab[ndx]) * frac); a += incra; f += incrph; } } /* keep amp, freq, and phase values for next time */ if (contin) { amps[k] = ampnext; freqs[k] = freqnext; phases[k] = phase; trackID[k] = id; i += 4; k++; } else notcontin++; } else break; } pos = 0; p->tracks = k; } } p->pos = pos; return OK; } static int psynth2_init(CSOUND *csound, _PSYN2 *p) { int numbins = p->fin->N / 2 + 1; if (UNLIKELY(p->fin->format != PVS_TRACKS)) { return csound->InitError(csound, Str("psynth: first input not in TRACKS format\n")); } p->func = csound->FTnp2Find(p->h.insdshead->csound, p->ftb); if (UNLIKELY(p->func == NULL)) { return csound->InitError(csound, Str("psynth: function table not found\n")); } p->tracks = 0; p->hopsize = p->fin->overlap; p->pos = 0; p->numbins = numbins; p->factor = p->hopsize * csound->onedsr; p->facsqr = p->factor * p->factor; if(*p->thresh == -1) p->min = 0.00002*csound->Get0dBFS(csound); else p->min = *p->thresh*csound->Get0dBFS(csound); if (p->amps.auxp == NULL || (unsigned) p->amps.size < sizeof(double) * numbins) csound->AuxAlloc(csound, sizeof(double) * numbins, &p->amps); else memset(p->amps.auxp, 0, sizeof(double) * numbins ); if (p->freqs.auxp == NULL || (unsigned) p->freqs.size < sizeof(double) * numbins) csound->AuxAlloc(csound, sizeof(double) * numbins, &p->freqs); else memset(p->freqs.auxp, 0, sizeof(double) * numbins ); if (p->phases.auxp == NULL || (unsigned) p->phases.size < sizeof(double) * numbins) csound->AuxAlloc(csound, sizeof(double) * numbins, &p->phases); else memset(p->phases.auxp, 0, sizeof(double) * numbins ); if (p->sum.auxp == NULL || (unsigned) p->sum.size < sizeof(double) * p->hopsize) csound->AuxAlloc(csound, sizeof(double) * p->hopsize, &p->sum); else memset(p->sum.auxp, 0, sizeof(double) * p->hopsize ); if (p->trackID.auxp == NULL || (unsigned) p->trackID.size < sizeof(int) * numbins) csound->AuxAlloc(csound, sizeof(int) * numbins, &p->trackID); else memset(p->trackID.auxp, 0, sizeof(int) * numbins ); return OK; } static int psynth2_process(CSOUND *csound, _PSYN2 *p) { double ampnext, amp, freq, freqnext, phase, phasenext; double a2, a3, cph; double phasediff, facsqr, ph; double a, frac, incra, incrph, factor, lotwopi, cnt; MYFLT scale = *p->scal; int ndx, size = p->func->flen; int i=0, j, k, m, id; int notcontin = 0; int contin = 0; int tracks = p->tracks, maxtracks = (int) *p->maxtracks; MYFLT *tab = p->func->ftable, *out = p->out; float *fin = (float *) p->fin->frame.auxp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int pos = p->pos; double *amps = (double *) p->amps.auxp, *freqs = (double *) p->freqs.auxp; double *phases = (double *) p->phases.auxp; MYFLT *outsum = (MYFLT *) p->sum.auxp; int *trackID = (int *) p->trackID.auxp; int hopsize = p->hopsize; double min = p->min; incrph = csound->onedsr; lotwopi = (double)(size) / TWOPI_F; factor = p->factor; facsqr = p->facsqr; maxtracks = p->numbins > maxtracks ? maxtracks : p->numbins; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { out[n] = outsum[pos]; pos++; if (UNLIKELY(pos == hopsize)) { memset(outsum, 0, sizeof(MYFLT) * hopsize); /* for each track */ i = j = k = 0; while (i < maxtracks * 4) { ampnext = (double) fin[i] * scale; freqnext = (double) fin[i + 1] * TWOPI_F; phasenext = (double) fin[i + 2]; if ((id = (int) fin[i + 3]) != -1) { j = k + notcontin; if (k < tracks - notcontin) { if (trackID[j] == id) { /* if this is a continuing track */ contin = 1; freq = freqs[j]; phase = phases[j]; amp = amps[j]; } else { /* if this is a dead track */ contin = 0; freqnext = freq = freqs[j]; phase = phases[j]; phasenext = phase + freq * factor; amp = amps[j]; ampnext = FL(0.0); } } else { /* new track */ contin = 1; goto cont; #if 0 freq = freqnext; phase = phasenext - freq * factor; amp = FL(0.0); #endif } if (amp > min) { /* phasediff */ phasediff = phasenext - phase; while (phasediff >= PI_F) phasediff -= TWOPI_F; while (phasediff < -PI_F) phasediff += TWOPI_F; /* update phasediff to match the freq */ cph = ((freq + freqnext) * factor * 0.5 - phasediff) / TWOPI; phasediff += TWOPI_F * (int) (cph + 0.5); /* interpolation coefs */ a2 = 3.0 / facsqr * (phasediff - factor / 3.0 * (2.0 * freq + freqnext)); a3 = 1.0 / (3.0 * facsqr) * (freqnext - freq - 2.0 * a2 * factor); /* interpolation & track synthesis loop */ a = amp; ph = phase; cnt = 0; incra = (ampnext - amp) / hopsize; for (m = 0; m < hopsize; m++) { /* table lookup oscillator */ ph *= lotwopi; while (ph < 0) ph += size; while (ph >= size) ph -= size; ndx = (int) ph; frac = ph - ndx; outsum[m] += a * (tab[ndx] + (tab[ndx + 1] - tab[ndx]) * frac); a += incra; cnt += incrph; ph = phase + cnt * (freq + cnt * (a2 + a3 * cnt)); } } /* keep amp, freq, and phase values for next time */ cont: if (contin) { amps[k] = ampnext; freqs[k] = freqnext; phases[k] = phasenext; trackID[k] = id; i += 4; k++; } else notcontin++; } else break; } pos = 0; p->tracks = k; } } p->pos = pos; return OK; } static int psynth3_process(CSOUND *csound, _PSYN *p) { double ampnext, amp, freq, freqnext, phase, phasenext; double a2, a3, cph=0.0; double phasediff, facsqr, ph; double a, frac, incra, incrph, factor, lotwopi, cnt; MYFLT scale = *p->scal, pitch = *p->pitch; int ndx, size = p->func->flen; int i, j, k, m, id; int notcontin = 0; int contin = 0; int tracks = p->tracks, maxtracks = (int) *p->maxtracks; MYFLT *tab = p->func->ftable, *out = p->out; float *fin = (float *) p->fin->frame.auxp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int pos = p->pos; double *amps = (double *) p->amps.auxp, *freqs = (double *) p->freqs.auxp; double *phases = (double *) p->phases.auxp; MYFLT *outsum = (MYFLT *) p->sum.auxp; int *trackID = (int *) p->trackID.auxp; int hopsize = p->hopsize; double min = p->min; incrph = csound->onedsr; lotwopi = (double) (size) / TWOPI_F; factor = p->factor; facsqr = p->facsqr; maxtracks = p->numbins > maxtracks ? maxtracks : p->numbins; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { out[n] = outsum[pos]; pos++; if (UNLIKELY(pos == hopsize)) { memset(outsum, 0, sizeof(MYFLT) * hopsize); /* for each track */ i = j = k = 0; while (i < maxtracks * 4) { ampnext = (double) fin[i] * scale; freqnext = (double) fin[i + 1] * TWOPI_F * pitch; phasenext = (double) fin[i + 2]; if ((id = (int) fin[i + 3]) != -1) { j = k + notcontin; if (k < tracks - notcontin) { if (trackID[j] == id) { /* if this is a continuing track */ contin = 1; freq = freqs[j]; phase = phases[j]; amp = amps[j]; } else { /* if this is a dead track */ contin = 0; freqnext = freq = freqs[j]; phase = phases[j]; phasenext = phase + freq * factor; amp = amps[j]; ampnext = FL(0.0); } } else { /* new track */ contin = 1; freq = freqnext; phase = phasenext - freq * factor; amp = FL(0.0); } if (amp > min) { /* phasediff */ phasediff = phasenext - phase; while (phasediff >= PI_F) phasediff -= TWOPI_F; while (phasediff < -PI_F) phasediff += TWOPI_F; /* update phasediff to match the freq */ cph = ((freq + freqnext) * factor *0.5 - phasediff) / TWOPI; phasediff += TWOPI_F * cph; /* interpolation coefs */ a2 = 3.0 / facsqr * (phasediff - factor / 3.0 * (2.0 * freq + freqnext)); a3 = 1.0 / (3.0 * facsqr) * (freqnext - freq - 2.0 * a2 * factor); /* interpolation & track synthesis loop */ a = amp; ph = phase; cnt = 0; incra = (ampnext - amp) / hopsize; for (m = 0; m < hopsize; m++) { /* table lookup oscillator */ ph *= lotwopi; while (ph < 0) ph += size; while (ph >= size) ph -= size; ndx = (int) ph; frac = ph - ndx; outsum[m] += a * (tab[ndx] + (tab[ndx + 1] - tab[ndx]) * frac); a += incra; cnt += incrph; ph = phase + cnt * (freq + cnt * (a2 + a3 * cnt)); } } /* keep amp, freq, and phase values for next time */ if (contin) { amps[k] = ampnext; freqs[k] = freqnext; phasenext += (cph - (int) cph) * TWOPI; while (phasenext < 0) phasenext += TWOPI_F; while (phasenext >= TWOPI_F) phasenext -= TWOPI_F; phases[k] = phasenext; trackID[k] = id; i += 4; k++; } else notcontin++; } else break; } pos = 0; p->tracks = k; } } p->pos = pos; return OK; } typedef struct _ptrans { OPDS h; PVSDAT *fout; PVSDAT *fin; MYFLT *kpar; MYFLT *kgain; MYFLT *pad1; MYFLT *pad2; unsigned int lastframe; int numbins; } _PTRANS; static int trans_init(CSOUND *csound, _PTRANS *p) { int numbins; if (UNLIKELY(p->fin->format != PVS_TRACKS)) { return csound->InitError(csound, Str("Input not in TRACKS format\n")); } p->numbins = numbins = (p->fout->N = p->fin->N) / 2 + 1; if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(float) * numbins * 4) csound->AuxAlloc(csound, sizeof(float) * numbins * 4, &p->fout->frame); ((float *) p->fout->frame.auxp)[3] = -1.0f; p->fout->overlap = p->fin->overlap; p->fout->winsize = p->fin->winsize; p->fout->wintype = p->fin->wintype; p->fout->framecount = 1; p->fout->format = PVS_TRACKS; p->lastframe = 0; return OK; } static int trscale_process(CSOUND *csound, _PTRANS *p) { MYFLT scale = *p->kpar; MYFLT gain = (p->kgain != NULL ? *p->kgain : FL(1.0)); MYFLT nyq = CS_ESR * FL(0.5); float *framein = (float *) p->fin->frame.auxp; float *frameout = (float *) p->fout->frame.auxp; int i = 0, id = (int) framein[3], end = p->numbins * 4; MYFLT outfr; if (p->lastframe < p->fin->framecount) { do { if (gain != FL(1.0)) frameout[i] = framein[i] * gain; else frameout[i] = framein[i]; outfr = framein[i + 1] * scale; frameout[i + 1] = (float) (outfr < nyq ? outfr : nyq); frameout[i + 2] = framein[i + 2]; id = (int) framein[i + 3]; frameout[i + 3] = (float) id; i += 4; } while (id != -1 && i < end); p->fout->framecount = p->lastframe = p->fin->framecount; } return OK; } static int trshift_process(CSOUND *csound, _PTRANS *p) { MYFLT shift = *p->kpar; MYFLT gain = (p->kgain != NULL ? *p->kgain : FL(1.0)); MYFLT nyq = CS_ESR * FL(0.5); float *framein = (float *) p->fin->frame.auxp; float *frameout = (float *) p->fout->frame.auxp; int i = 0, id = (int) framein[3], end = p->numbins * 4; MYFLT outfr; if (p->lastframe < p->fin->framecount) { do { if (gain != FL(1.0)) frameout[i] = framein[i] * gain; else frameout[i] = framein[i]; outfr = framein[i + 1] + shift; frameout[i + 1] = (float) (outfr < nyq ? outfr : nyq); frameout[i + 2] = framein[i + 2]; id = (int) framein[i + 3]; frameout[i + 3] = (float) id; i += 4; } while (id != -1 && i < end); p->fout->framecount = p->lastframe = p->fin->framecount; } return OK; } typedef struct _plow { OPDS h; PVSDAT *fout; MYFLT *kfr; MYFLT *kamp; PVSDAT *fin; MYFLT *kpar; unsigned int lastframe; int numbins; } _PLOW; static int trlowest_init(CSOUND *csound, _PLOW *p) { int numbins; if (UNLIKELY(p->fin->format != PVS_TRACKS)) { return csound->InitError(csound, Str("Input not in TRACKS format\n")); } p->numbins = numbins = (p->fout->N = p->fin->N) / 2 + 1; if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(float) * numbins * 4) csound->AuxAlloc(csound, sizeof(float) * numbins * 4, &p->fout->frame); ((float *) p->fout->frame.auxp)[3] = -1.0f; p->fout->overlap = p->fin->overlap; p->fout->winsize = p->fin->winsize; p->fout->wintype = p->fin->wintype; p->fout->framecount = 1; p->fout->format = PVS_TRACKS; p->lastframe = 0; return OK; } static int trlowest_process(CSOUND *csound, _PLOW *p) { MYFLT scale = *p->kpar; MYFLT nyq = CS_ESR * FL(0.5); float lowest = (float) nyq, outamp = 0.0f, outph = 0.0f, outid = -1.0f; float *framein = (float *) p->fin->frame.auxp; float *frameout = (float *) p->fout->frame.auxp; int i = 0, id = (int) framein[3], end = p->numbins * 4; if (p->lastframe < p->fin->framecount) { do { if (framein[i + 1] < lowest && framein[i] > 0.0f) { lowest = framein[i + 1]; outamp = framein[i]; outph = framein[i + 2]; outid = framein[i + 3]; } id = (int) framein[i + 3]; i += 4; } while (id != -1 && i < end); frameout[0] = outamp * scale; frameout[1] = lowest; frameout[2] = outph; frameout[3] = outid; frameout[7] = -1.0f; *p->kfr = (MYFLT) lowest; *p->kamp = (MYFLT) frameout[0]; p->fout->framecount = p->lastframe = p->fin->framecount; /*csound->Message(csound, "lowest %f\n", lowest);*/ } return OK; } static int trhighest_process(CSOUND *csound, _PLOW *p) { MYFLT scale = *p->kpar; float highest = 0.0f, outamp = 0.0f, outph = 0.0f, outid = -1.0f; float *framein = (float *) p->fin->frame.auxp; float *frameout = (float *) p->fout->frame.auxp; int i = 0, id = (int) framein[3], end = p->numbins * 4; if (p->lastframe < p->fin->framecount) { do { if (framein[i + 1] > highest && framein[i] > 0.0f) { highest = framein[i + 1]; outamp = framein[i]; outph = framein[i + 2]; outid = framein[i + 3]; } id = (int) framein[i + 3]; i += 4; } while (id != -1 && i < end); frameout[0] = outamp * scale; frameout[1] = highest; frameout[2] = outph; frameout[3] = outid; frameout[7] = -1.0f; *p->kfr = (MYFLT) highest; *p->kamp = (MYFLT) frameout[0]; p->fout->framecount = p->lastframe = p->fin->framecount; /*csound->Message(csound, "lowest %f\n", lowest);*/ } return OK; } typedef struct _psplit { OPDS h; PVSDAT *fsig1; PVSDAT *fsig2; PVSDAT *fsig3; MYFLT *kpar; MYFLT *kgain1; MYFLT *kgain2; MYFLT *pad1; MYFLT *pad2; unsigned int lastframe; int numbins; } _PSPLIT; static int trsplit_init(CSOUND *csound, _PSPLIT *p) { int numbins; if (UNLIKELY(p->fsig3->format != PVS_TRACKS)) { return csound->InitError(csound, Str("trsplit: input not " "in TRACKS format\n")); } p->numbins = numbins = (p->fsig2->N = p->fsig1->N = p->fsig3->N) / 2 + 1; if (p->fsig1->frame.auxp == NULL || p->fsig1->frame.size < sizeof(float) * numbins * 4) csound->AuxAlloc(csound, sizeof(float) * numbins * 4, &p->fsig1->frame); ((float *) p->fsig1->frame.auxp)[3] = -1.0f; p->fsig1->overlap = p->fsig3->overlap; p->fsig1->winsize = p->fsig3->winsize; p->fsig1->wintype = p->fsig3->wintype; p->fsig1->framecount = 1; p->fsig1->format = PVS_TRACKS; if (p->fsig2->frame.auxp == NULL || p->fsig2->frame.size < sizeof(float) * numbins * 4) csound->AuxAlloc(csound, sizeof(float) * numbins * 4, &p->fsig2->frame); ((float *) p->fsig2->frame.auxp)[3] = -1.0f; p->fsig2->overlap = p->fsig3->overlap; p->fsig2->winsize = p->fsig3->winsize; p->fsig2->wintype = p->fsig3->wintype; p->fsig2->framecount = 1; p->fsig2->format = PVS_TRACKS; p->lastframe = 0; return OK; } static int trsplit_process(CSOUND *csound, _PSPLIT *p) { MYFLT split = *p->kpar; MYFLT gain1 = (p->kgain1 != NULL ? *p->kgain1 : FL(1.0)); MYFLT gain2 = (p->kgain2 != NULL ? *p->kgain2 : FL(1.0)); float *framein = (float *) p->fsig3->frame.auxp; float *frameout1 = (float *) p->fsig1->frame.auxp; float *frameout2 = (float *) p->fsig2->frame.auxp; int i = 0, id = (int) framein[3], end = p->numbins * 4; int trkcnt1 = 0, trkcnt2 = 0; if (p->lastframe < p->fsig3->framecount) { do { if (framein[i + 1] < split) { if (gain1 != FL(1.0)) frameout1[trkcnt1] = framein[i] * gain1; else frameout1[trkcnt1] = framein[i]; frameout1[trkcnt1 + 1] = framein[i + 1]; frameout1[trkcnt1 + 2] = framein[i + 2]; id = (int) framein[i + 3]; frameout1[trkcnt1 + 3] = (float) id; trkcnt1 += 4; } else { if (gain2 != FL(1.0)) frameout2[trkcnt2] = framein[i] * gain2; else frameout2[trkcnt2] = framein[i]; frameout2[trkcnt2 + 1] = framein[i + 1]; frameout2[trkcnt2 + 2] = framein[i + 2]; id = (int) framein[i + 3]; frameout2[trkcnt2 + 3] = (float) id; trkcnt2 += 4; } i += 4; } while (id != -1 && i < end); if (trkcnt1) frameout1[trkcnt1 - 1] = -1.0f; if (trkcnt2) frameout2[trkcnt2 - 1] = -1.0f; p->fsig2->framecount = p->fsig1->framecount = p->lastframe = p->fsig3->framecount; /*csound->Message(csound, "split %d : %d\n", trkcnt1/4, trkcnt2/4);*/ } return OK; } typedef struct _psmix { OPDS h; PVSDAT *fsig1; PVSDAT *fsig2; PVSDAT *fsig3; unsigned int lastframe; int numbins; } _PSMIX; static int trmix_init(CSOUND *csound, _PSMIX *p) { int numbins; if (UNLIKELY(p->fsig2->format != PVS_TRACKS)) { return csound->InitError(csound, Str("trmix: first input not in TRACKS format\n")); } if (UNLIKELY(p->fsig3->format != PVS_TRACKS)) { return csound->InitError(csound, Str("trmix: second input not in TRACKS format\n")); } p->numbins = numbins = (p->fsig1->N = p->fsig2->N) / 2 + 1; if (p->fsig1->frame.auxp == NULL || p->fsig1->frame.size < sizeof(float) * numbins * 4) csound->AuxAlloc(csound, sizeof(float) * numbins * 4, &p->fsig1->frame); ((float *) p->fsig1->frame.auxp)[3] = -1.0f; p->fsig1->overlap = p->fsig2->overlap; p->fsig1->winsize = p->fsig2->winsize; p->fsig1->wintype = p->fsig2->wintype; p->fsig1->framecount = 1; p->fsig1->format = PVS_TRACKS; p->lastframe = 0; return OK; } static int trmix_process(CSOUND *csound, _PSMIX *p) { float *framein2 = (float *) p->fsig3->frame.auxp; float *frameout = (float *) p->fsig1->frame.auxp; float *framein1 = (float *) p->fsig2->frame.auxp; int i = 0, j = 0, id = (int) framein1[3], end = p->numbins * 4; if (p->lastframe < p->fsig2->framecount) { while (id != -1 && i < end) { frameout[i] = framein1[i]; frameout[i + 1] = framein1[i + 1]; frameout[i + 2] = framein1[i + 2]; frameout[i + 3] = (float) id; i += 4; id = (int) framein1[i + 3]; } id = (int) framein2[3]; while (id != -1 && i < end && j < end) { frameout[i] = framein2[j]; frameout[i + 1] = framein2[j + 1]; frameout[i + 2] = framein2[j + 2]; frameout[i + 3] = (float) id; i += 4; j += 4; id = (int) framein2[j + 3]; } if (i + 3 < p->numbins * 4) frameout[i + 3] = -1.0f; p->fsig1->framecount = p->lastframe = p->fsig2->framecount; } return OK; } typedef struct _psfil { OPDS h; PVSDAT *fout; PVSDAT *fin; MYFLT *kpar; MYFLT *ifn; FUNC *tab; int len; unsigned int lastframe; int numbins; } _PSFIL; static int trfil_init(CSOUND *csound, _PSFIL *p) { int numbins; if (UNLIKELY(p->fin->format != PVS_TRACKS)) { return csound->InitError(csound, Str("trfil: input not in TRACKS format\n")); } p->tab = csound->FTnp2Find(csound, p->ifn); if (UNLIKELY(p->tab == NULL)) { return csound->InitError(csound, Str("trfil: could not find function table\n")); } p->len = p->tab->flen; p->numbins = numbins = (p->fout->N = p->fin->N) / 2 + 1; if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(float) * numbins * 4) csound->AuxAlloc(csound, sizeof(float) * numbins * 4, &p->fout->frame); ((float *) p->fout->frame.auxp)[3] = -1.0f; p->fout->overlap = p->fin->overlap; p->fout->winsize = p->fin->winsize; p->fout->wintype = p->fin->wintype; p->fout->framecount = 1; p->fout->format = PVS_TRACKS; p->lastframe = 0; return OK; } static int trfil_process(CSOUND *csound, _PSFIL *p) { MYFLT amnt = *p->kpar, gain = FL(1.0); MYFLT nyq = CS_ESR * FL(0.5); MYFLT *fil = p->tab->ftable; float *framein = (float *) p->fin->frame.auxp; float *frameout = (float *) p->fout->frame.auxp; int i = 0, id = (int) framein[3], len = p->len, end = p->numbins * 4; if (p->lastframe < p->fin->framecount) { MYFLT fr, pos = FL(0.0), frac = FL(0.0); int posi = 0; if (UNLIKELY(amnt > 1)) amnt = 1; if (UNLIKELY(amnt < 0)) amnt = 0; do { fr = framein[i + 1]; if (UNLIKELY(fr > nyq)) fr = nyq; //if (fr < 0) fr = FABS(fr); pos = fr * len / nyq; posi = (int) pos; frac = pos - posi; gain = fil[posi] + frac * (fil[posi + 1] - fil[posi]); frameout[i] = (float) (framein[i] * (FL(1.0) - amnt + gain * amnt)); frameout[i + 1] = fr; frameout[i + 2] = framein[i + 2]; id = (int) framein[i + 3]; frameout[i + 3] = (float) id; i += 4; } while (id != -1 && i < end); if (i - 1 < p->numbins * 4) frameout[i - 1] = -1.0f; p->fout->framecount = p->lastframe = p->fin->framecount; } return OK; } typedef struct _pscross { OPDS h; PVSDAT *fsig1; PVSDAT *fsig2; PVSDAT *fsig3; MYFLT *kpar1; MYFLT *kpar2; MYFLT *kpar3; unsigned int lastframe; int numbins; } _PSCROSS; static int trcross_init(CSOUND *csound, _PSCROSS *p) { int numbins; if (UNLIKELY(p->fsig2->format != PVS_TRACKS)) { return csound->InitError(csound, Str("trmix: first input not in TRACKS format\n")); } if (UNLIKELY(p->fsig3->format != PVS_TRACKS)) { return csound->InitError(csound, Str("trmix: second input not in TRACKS format\n")); } p->numbins = numbins = (p->fsig1->N = p->fsig2->N) / 2 + 1; if (p->fsig1->frame.auxp == NULL || p->fsig1->frame.size < sizeof(float) * numbins * 4) csound->AuxAlloc(csound, sizeof(float) * numbins * 4, &p->fsig1->frame); ((float *) p->fsig1->frame.auxp)[3] = -1.0f; p->fsig1->overlap = p->fsig2->overlap; p->fsig1->winsize = p->fsig2->winsize; p->fsig1->wintype = p->fsig2->wintype; p->fsig1->framecount = 1; p->fsig1->format = PVS_TRACKS; p->lastframe = 0; return OK; } static int trcross_process(CSOUND *csound, _PSCROSS *p) { MYFLT interval = *p->kpar1, bal = *p->kpar2; int mode = p->kpar3 != NULL ? (int) *p->kpar3 : 0; float *framein2 = (float *) p->fsig3->frame.auxp; float *frameout = (float *) p->fsig1->frame.auxp; float *framein1 = (float *) p->fsig2->frame.auxp; int i = 0, j = 0, nomatch = 1, id, end = p->numbins * 4; float max = 0; MYFLT boundup, boundown; int maxj = -1; id = (int) framein1[3]; if (p->lastframe < p->fsig2->framecount) { if (bal > 1) bal = FL(1.0); if (bal < 0) bal = FL(0.0); if (mode < 1) for (i = 0; framein2[i + 3] != -1 && i < end; i += 4) max = framein2[i] > max ? framein2[i] : max; for (i = 0; id != -1 && i < end; i += 4, id = (int) framein1[i + 3]) { boundup = framein1[i + 1] * interval; boundown = framein1[i + 1] * (FL(1.0) / interval); for (j = 0; j < end && framein2[j + 3] != -1; j += 4) { if ((framein2[j + 1] > boundown) && (framein2[j + 1] <= boundup)) { if (maxj != -1) maxj = framein2[j] > framein2[maxj] ? j : maxj; else maxj = j; nomatch = 0; } } if (!nomatch) { if (mode < 1) frameout[i] = (float) ((framein1[i] * (max ? framein2[maxj] / max : 1.0f)) * bal + framein1[i] * (FL(1.0) - bal)); else frameout[i] = (float) (framein2[maxj] * bal + framein1[i] * (FL(1.0) - bal)); frameout[i + 1] = framein1[i + 1]; frameout[i + 2] = framein1[i + 2]; frameout[i + 3] = (float) id; } else { frameout[i] = (float) (framein1[i] * (FL(1.0) - bal)); frameout[i + 1] = framein1[i + 1]; frameout[i + 2] = framein1[i + 2]; frameout[i + 3] = (float) id; } nomatch = 1; maxj = -1; } if (i + 3 < p->numbins * 4) frameout[i + 3] = -1.0f; p->fsig1->framecount = p->lastframe = p->fsig2->framecount; /*csound->Message(csound, "mix %d : %d\n", k/4, j/4);*/ } return OK; } typedef struct _psbin { OPDS h; PVSDAT *fsig1; PVSDAT *fsig2; MYFLT *ipar; int N; unsigned int lastframe; int numbins; } _PSBIN; static int binit_init(CSOUND *csound, _PSBIN *p) { int numbins, N; if (UNLIKELY(p->fsig2->format != PVS_TRACKS)) { return csound->InitError(csound, Str("binit: first input not in TRACKS format\n")); } N = p->N = (int) *p->ipar; p->numbins = numbins = p->fsig2->N / 2 + 1; if (p->fsig1->frame.auxp == NULL || p->fsig1->frame.size < sizeof(float) * (N + 2)) csound->AuxAlloc(csound, sizeof(float) * (N + 2), &p->fsig1->frame); p->fsig1->overlap = p->fsig2->overlap; p->fsig1->winsize = p->fsig2->winsize; p->fsig1->wintype = p->fsig2->wintype; p->fsig1->framecount = 1; p->fsig1->format = PVS_AMP_FREQ; p->fsig1->N = N; p->lastframe = 0; return OK; } static int binit_process(CSOUND *csound, _PSBIN *p) { int N = (int) p->N; float *frameout = (float *) p->fsig1->frame.auxp; float *framein = (float *) p->fsig2->frame.auxp; int i = 0, n = 0, id = (int) framein[3], end = p->numbins * 4; int maxi = -1; MYFLT bw = CS_ESR / (MYFLT)N, boundup, boundown; MYFLT nyq = CS_ESR * FL(0.5), centre; if (p->lastframe < p->fsig2->framecount) { for (n = 2; n < N; n += 2) { centre = (n / 2) * bw; boundup = (n == N - 2 ? nyq : centre + (bw / 2)); boundown = (n == 2 ? 0 : centre - (bw / 2)); for (i = 0; id != -1 && i < end; i += 4, id = (int) framein[i + 3]) { if ((framein[i + 1] > boundown) && (framein[i + 1] <= boundup)) { if (maxi != -1) maxi = (framein[i] > framein[maxi] ? i : maxi); else maxi = i; } } if (maxi != -1) { frameout[n] = framein[maxi]; frameout[n + 1] = framein[maxi + 1]; maxi = -1; } else { frameout[n] = 0.f; frameout[n + 1] = 0.f; } id = (int) framein[3]; } frameout[0] = 0.f; frameout[N] = 0.f; p->fsig1->framecount = p->lastframe = p->fsig2->framecount; } return OK; } static OENTRY localops[] = { {"tradsyn", sizeof(_PSYN),0, 5, "a", "fkkkij", (SUBR) psynth_init, NULL, (SUBR) psynth_process} , {"sinsyn", sizeof(_PSYN2), TR, 5, "a", "fkkij", (SUBR) psynth2_init, NULL, (SUBR) psynth2_process} , {"resyn", sizeof(_PSYN), TR, 5, "a", "fkkkij", (SUBR) psynth_init, NULL, (SUBR) psynth3_process} , {"trscale", sizeof(_PTRANS),0, 3, "f", "fz", (SUBR) trans_init, (SUBR) trscale_process} , {"trshift", sizeof(_PTRANS),0, 3, "f", "fz", (SUBR) trans_init, (SUBR) trshift_process} , {"trsplit", sizeof(_PSPLIT),0, 3, "ff", "fz", (SUBR) trsplit_init, (SUBR) trsplit_process} , {"trmix", sizeof(_PSMIX),0, 3, "f", "ff", (SUBR) trmix_init, (SUBR) trmix_process} , {"trlowest", sizeof(_PLOW),0, 3, "fkk", "fk", (SUBR) trlowest_init, (SUBR) trlowest_process} , {"trhighest", sizeof(_PLOW),0, 3, "fkk", "fk", (SUBR) trlowest_init, (SUBR) trhighest_process} , {"trfilter", sizeof(_PSFIL),0, 3, "f", "fki", (SUBR) trfil_init, (SUBR) trfil_process} , {"trcross", sizeof(_PSCROSS),0, 3, "f", "ffkz", (SUBR) trcross_init, (SUBR) trcross_process} , {"binit", sizeof(_PSBIN),0, 3, "f", "fi", (SUBR) binit_init, (SUBR) binit_process} }; int psynth_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/ptrigtbl.h000066400000000000000000000135241321653344700165020ustar00rootroot00000000000000/* ptrigtbl.h: Copyright (C) 1997 Paris Smaragdis, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define GOOD_TRIG #if defined(GOOD_TRIG) #define FHT_SWAP(a,b,t) {(t)=(a);(a)=(b);(b)=(t);} #define TRIG_VARS \ MYFLT coswrk[24], sinwrk[24]; \ int32 t_lam = 0L; \ coswrk[0] = FL(0.0); \ sinwrk[0] = FL(1.0); #define TRIG_INIT(k,c,s) \ { \ int32 i; \ for (i = 1; i <= k; i++) { \ coswrk[i] = costab[i]; \ sinwrk[i] = sintab[i]; \ } \ t_lam = 0; \ c = FL(1.0); \ s = FL(0.0); \ } #define TRIG_NEXT(k,c,s) \ { \ int32 i, j; \ (t_lam)++; \ for (i = 0; !((1L << i) & t_lam); i++); \ i = k - i; \ s = sinwrk[i]; \ c = coswrk[i]; \ if (i > 1) { \ for (j = k - i + 2; (1L << j) & t_lam; j++); \ j = k - j; \ sinwrk[i] = halsec[i] * (sinwrk[i-1] + sinwrk[j]); \ coswrk[i] = halsec[i] * (coswrk[i-1] + coswrk[j]); \ } \ } #endif #if defined(FAST_TRIG) #define TRIG_VARS MYFLT t_c,t_s; #define TRIG_INIT(k,c,s) \ { \ t_c = costab[k]; \ t_s = sintab[k]; \ c = 1; \ s = 0; \ } #define TRIG_NEXT(k,c,s) \ { \ MYFLT t = c; \ c = t*t_c - s*t_s; \ s = t*t_s + s*t_c; \ } #endif #define SQRT2_2 (FL(0.70710678118654752440084436210484)) #define SQRT2 (FL(2.0) * FL(0.70710678118654752440084436210484)) static const MYFLT halsec[20]= { FL(0.0), FL(0.0), FL(.54119610014619698439972320536638942006107206337801), FL(.50979557910415916894193980398784391368261849190893), FL(.50241928618815570551167011928012092247859337193963), FL(.50060299823519630134550410676638239611758632599591), FL(.50015063602065098821477101271097658495974913010340), FL(.50003765191554772296778139077905492847503165398345), FL(.50000941253588775676512870469186533538523133757983), FL(.50000235310628608051401267171204408939326297376426), FL(.50000058827484117879868526730916804925780637276181), FL(.50000014706860214875463798283871198206179118093251), FL(.50000003676714377807315864400643020315103490883972), FL(.50000000919178552207366560348853455333939112569380), FL(.50000000229794635411562887767906868558991922348920), FL(.50000000057448658687873302235147272458812263401372) }; static const MYFLT costab[20]= { FL(.00000000000000000000000000000000000000000000000000), FL(.70710678118654752440084436210484903928483593768847), FL(.92387953251128675612818318939678828682241662586364), FL(.98078528040323044912618223613423903697393373089333), FL(.99518472667219688624483695310947992157547486872985), FL(.99879545620517239271477160475910069444320361470461), FL(.99969881869620422011576564966617219685006108125772), FL(.99992470183914454092164649119638322435060646880221), FL(.99998117528260114265699043772856771617391725094433), FL(.99999529380957617151158012570011989955298763362218), FL(.99999882345170190992902571017152601904826792288976), FL(.99999970586288221916022821773876567711626389934930), FL(.99999992646571785114473148070738785694820115568892), FL(.99999998161642929380834691540290971450507605124278), FL(.99999999540410731289097193313960614895889430318945), FL(.99999999885102682756267330779455410840053741619428) }; static const MYFLT sintab[20]= { FL(1.0000000000000000000000000000000000000000000000000), FL(.70710678118654752440084436210484903928483593768846), FL(.38268343236508977172845998403039886676134456248561), FL(.19509032201612826784828486847702224092769161775195), FL(.09801714032956060199419556388864184586113667316749), FL(.04906767432741801425495497694268265831474536302574), FL(.02454122852291228803173452945928292506546611923944), FL(.01227153828571992607940826195100321214037231959176), FL(.00613588464915447535964023459037258091705788631738), FL(.00306795676296597627014536549091984251894461021344), FL(.00153398018628476561230369715026407907995486457522), FL(.00076699031874270452693856835794857664314091945205), FL(.00038349518757139558907246168118138126339502603495), FL(.00019174759731070330743990956198900093346887403385), FL(.00009587379909597734587051721097647635118706561284), FL(.00004793689960306688454900399049465887274686668768) }; csound-6.10.0/Opcodes/pvadd.c000066400000000000000000000170161321653344700157440ustar00rootroot00000000000000/* pvadd.c: Copyright (C) 1998 Richard Karpen This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /******************************************/ /* The applications in this file were */ /* designed and coded by Richard Karpen */ /* University of Washington, Seattle 1998 */ /******************************************/ /* PVADD.C */ #include "pvoc.h" #include static int pvx_loadfile(CSOUND *csound, const char *fname, PVADD *p); /* This is used in pvadd instead of the Fetch() from dsputil.c */ void FetchInForAdd(float *inp, MYFLT *buf, int32 fsize, MYFLT pos, int binoffset, int maxbin, int binincr) { int32 j; float *frame0, *frame1; int32 base; MYFLT frac; base = (int32)pos; frac = pos - (MYFLT)base; /* & how close to get to next */ frame0 = inp + ((int32)fsize+2L)*base; frame1 = frame0 + ((int32)fsize+2L); if (frac != FL(0.0)) { for (j = binoffset; j < maxbin; j+=binincr) { buf[2L*j] = frame0[2L*j] + frac*(frame1[2L*j]-frame0[2L*j]); buf[2L*j+1L] = frame0[2L*j+1L] + frac*(frame1[2L*j+1L]-frame0[2L*j+1L]); } } else { for (j = binoffset; j < maxbin; j+=binincr) { buf[2L*j] = frame0[2L*j]; buf[2L*j+1] = frame0[2L*j+1L]; } } } int pvaddset_(CSOUND *csound, PVADD *p, int stringname) { int ibins; char pvfilnam[MAXNAME]; int size; FUNC *ftp = NULL, *AmpGateFunc = NULL; int32 memsize; if (*p->ifn > FL(0.0)) if (UNLIKELY((ftp = csound->FTFind(csound, p->ifn)) == NULL)) return NOTOK; p->ftp = ftp; if (*p->igatefun > FL(0.0)) if (UNLIKELY((AmpGateFunc = csound->FTnp2Find(csound, p->igatefun)) == NULL)) return NOTOK; p->AmpGateFunc = AmpGateFunc; if (stringname==0){ if (csound->ISSTRCOD(*p->ifilno)) strncpy(pvfilnam,get_arg_string(csound, *p->ifilno), MAXNAME-1); else csound->strarg2name(csound, pvfilnam, p->ifilno, "pvoc.",0); } else strncpy(pvfilnam, ((STRINGDAT *)p->ifilno)->data, MAXNAME-1); if (UNLIKELY(pvx_loadfile(csound, pvfilnam, p) != OK)) return NOTOK; memsize = (int32) (MAXBINS + PVFFTSIZE + PVFFTSIZE); if (*p->imode == 1 || *p->imode == 2) { int32 n= (int32) ((p->frSiz + 2L) * (p->maxFr + 2L)); #ifdef USE_DOUBLE n = (n + 1L) * (int32) sizeof(float) / (int32) sizeof(double); #endif memsize += n; } if (p->auxch.auxp == NULL || memsize != p->mems) { MYFLT *fltp; csound->AuxAlloc(csound, (memsize * sizeof(MYFLT)), &p->auxch); fltp = (MYFLT *) p->auxch.auxp; p->oscphase = fltp; fltp += MAXBINS; p->buf = fltp; if (*p->imode == 1 || *p->imode == 2) { fltp += PVFFTSIZE * 2; p->pvcopy = (float*) ((void*) fltp); } } p->mems = memsize; size = pvfrsiz(p); p->prFlg = 1; /* true */ if (*p->igatefun > 0) p->PvMaxAmp = PvocMaxAmp(p->frPtr, size, p->maxFr); if (*p->imode == 1 || *p->imode == 2) { SpectralExtract(p->frPtr, p->pvcopy, size, p->maxFr, (int) *p->imode, *p->ifreqlim); p->frPtr = (float*) p->pvcopy; } memset(p->oscphase, 0, MAXBINS*sizeof(MYFLT)); ibins = (*p->ibins <= FL(0.0) ? (size / 2) : (int) *p->ibins); p->maxbin = ibins + (int) *p->ibinoffset; p->maxbin = (p->maxbin > (size / 2) ? (size / 2) : p->maxbin); return OK; } int pvadd(CSOUND *csound, PVADD *p) { MYFLT *ar, *ftab; MYFLT frIndx; int size = pvfrsiz(p); int i, binincr = (int) *p->ibinincr; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT amp, frq, v1, fract, *oscphase; int32 phase, incr; FUNC *ftp; int32 lobits; if (UNLIKELY(p->auxch.auxp == NULL)) goto err1; ftp = p->ftp; if (UNLIKELY((frIndx = *p->ktimpnt * p->frPrtim) < 0)) goto err2; if (frIndx > p->maxFr) { /* not past last one */ frIndx = (MYFLT) p->maxFr; if (p->prFlg) { p->prFlg = 0; /* false */ csound->Warning(csound, Str("PVADD ktimpnt truncated to last frame")); } } FetchInForAdd(p->frPtr, p->buf, size, frIndx, (int) *p->ibinoffset, p->maxbin, binincr); if (*p->igatefun > 0) PvAmpGate(p->buf, p->maxbin*2, p->AmpGateFunc, p->PvMaxAmp); ar = p->rslt; memset(ar, 0, nsmps*sizeof(MYFLT)); if (UNLIKELY(early)) nsmps -= early; oscphase = p->oscphase; for (i = (int) *p->ibinoffset; i < p->maxbin; i += binincr) { lobits = ftp->lobits; phase = (int32) *oscphase; frq = p->buf[i * 2 + 1] * *p->kfmod; if (p->buf[i * 2 + 1] == FL(0.0) || frq >= CS_ESR * FL(0.5)) { incr = 0; /* Hope then does not matter */ amp = FL(0.0); } else { MYFLT tmp = frq * csound->sicvt; incr = (int32) MYFLT2LONG(tmp); amp = p->buf[i * 2]; } for (n=offset;nftable + (phase >> lobits); v1 = *ftab++; ar[n] += (v1 + (*ftab - v1) * fract) * amp; phase += incr; phase &= PHMASK; } *oscphase = (MYFLT) phase; oscphase++; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("pvadd: not initialised")); err2: return csound->PerfError(csound, p->h.insdshead, Str("PVADD timpnt < 0")); } int pvaddset(CSOUND *csound, PVADD *p){ return pvaddset_(csound, p, 0); } int pvaddset_S(CSOUND *csound, PVADD *p){ return pvaddset_(csound, p, 1); } static int pvx_loadfile(CSOUND *csound, const char *fname, PVADD *p) { PVOCEX_MEMFILE pp; if (UNLIKELY(csound->PVOCEX_LoadFile(csound, fname, &pp) != 0)) { return csound->InitError(csound, Str("PVADD cannot load %s"), fname); } /* fft size must be <= PVFRAMSIZE (=8192) for Csound */ if (UNLIKELY(pp.fftsize > PVFRAMSIZE)) { return csound->InitError(csound, Str("pvoc-ex file %s: " "FFT size %d too large for Csound"), fname, (int) pp.fftsize); } if (UNLIKELY(pp.fftsize < 128)) { return csound->InitError(csound, Str("PV frame %d seems too small in %s"), pp.fftsize, fname); } /* have to reject m/c files for now, until opcodes upgraded */ if (UNLIKELY(pp.chans > 1)) { return csound->InitError(csound, Str("pvoc-ex file %s is not mono"), fname); } /* ignore the window spec until we can use it! */ p->frSiz = pp.fftsize; p->frPtr = (float*) pp.data; p->maxFr = pp.nframes - 1; p->asr = pp.srate; /* factor by which to mult expand phase diffs (ratio of samp spacings) */ p->frPrtim = CS_ESR / (MYFLT) pp.overlap; return OK; } csound-6.10.0/Opcodes/pvadd.h000066400000000000000000000027661321653344700157570ustar00rootroot00000000000000/* pvadd.h: Copyright (C) 1998 Richard Karpen This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* PVADD.H */ #define MAXBINS 4096 #ifndef PVFRAMSIZE #define PVFRAMSIZE 8192 /* i.e. max FFT point size */ #endif #define PVFFTSIZE (2*PVFRAMSIZE) /* 2x for real + imag */ #define pvfrsiz(p) (p->frSiz) typedef struct { OPDS h; MYFLT *rslt, *ktimpnt, *kfmod, *ifilno, *ifn, *ibins; MYFLT *ibinoffset, *ibinincr, *imode, *ifreqlim, *igatefun; FUNC *ftp, *AmpGateFunc; AUXCH auxch; MYFLT *oscphase, *buf, PvMaxAmp; MYFLT frPrtim, asr; float *frPtr, *pvcopy; int32 maxFr, frSiz, prFlg, mems; int maxbin; } PVADD; csound-6.10.0/Opcodes/pvinterp.c000066400000000000000000000517621321653344700165230ustar00rootroot00000000000000/* pvinterp.c: Copyright (C) 1996 Richard Karpen This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /*****************************************/ /*********** PVINTERP, PVCROSS ***********/ /******** By Richard Karpen 1996 *********/ /*****************************************/ #include "pvoc.h" #include #define WLN 1 /* time window is WLN*2*ksmps long */ #define OPWLEN (2*WLN*CS_KSMPS) /* manifest used for final time wdw */ /************************************************************/ /*************PVBUFREAD**************************************/ /************************************************************/ int pvbufreadset_(CSOUND *csound, PVBUFREAD *p, int stringname) { char pvfilnam[MAXNAME]; PVOCEX_MEMFILE pp; int frInc, chans; /* THESE SHOULD BE SAVED IN PVOC STRUCT */ { PVOC_GLOBALS *p_ = PVOC_GetGlobals(csound); p_->pvbufreadaddr = p; } if (p->auxch.auxp == NULL) { /* if no buffers yet, alloc now */ /* Assumes PVDATASIZE, PVFFTSIZE, PVWINLEN constant */ MYFLT *fltp; csound->AuxAlloc(csound, (PVDATASIZE + PVFFTSIZE * 3 + PVWINLEN) * sizeof(MYFLT), &p->auxch); fltp = (MYFLT *) p->auxch.auxp; p->lastPhase = fltp; fltp += PVDATASIZE; /* and insert addresses */ p->fftBuf = fltp; /* fltp += PVFFTSIZE; */ /* Not needed */ } if (stringname==0){ if (csound->ISSTRCOD(*p->ifilno)) strncpy(pvfilnam,get_arg_string(csound, *p->ifilno), MAXNAME-1); else csound->strarg2name(csound, pvfilnam, p->ifilno, "pvoc.",0); } else strncpy(pvfilnam, ((STRINGDAT *)p->ifilno)->data, MAXNAME-1); if (UNLIKELY(csound->PVOCEX_LoadFile(csound, pvfilnam, &pp) != 0)) return csound->InitError(csound, Str("PVBUFREAD cannot load %s"), pvfilnam); p->frSiz = pp.fftsize; frInc = pp.overlap; chans = pp.chans; p->asr = pp.srate; if (UNLIKELY(p->asr != CS_ESR)) { /* & chk the data */ csound->Warning(csound, Str("%s's srate = %8.0f, orch's srate = %8.0f"), pvfilnam, p->asr, CS_ESR); } if (UNLIKELY(p->frSiz > PVFRAMSIZE)) { return csound->InitError(csound, Str("PVOC frame %ld bigger than %ld in %s"), (long) p->frSiz, (long) PVFRAMSIZE, pvfilnam); } if (UNLIKELY(p->frSiz < 128)) { return csound->InitError(csound, Str("PVOC frame %ld seems too small in %s"), (long) p->frSiz, pvfilnam); } if (UNLIKELY(chans != 1)) { return csound->InitError(csound, Str("%d chans (not 1) in PVOC file %s"), (int) chans, pvfilnam); } p->frPtr = (float*) pp.data; p->maxFr = pp.nframes - 1; p->frPktim = (MYFLT) CS_KSMPS / (MYFLT) frInc; p->frPrtim = CS_ESR / (MYFLT) frInc; p->prFlg = 1; /* true */ /* amplitude scale for PVOC */ /* p->scale = (MYFLT) pp.fftsize * ((MYFLT) pp.fftsize / (MYFLT) pp.winsize); */ p->scale = (MYFLT) pp.fftsize * FL(0.5); p->scale *= csound->GetInverseRealFFTScale(csound, pp.fftsize); if (UNLIKELY((OPWLEN / 2 + 1) > PVWINLEN )) { return csound->InitError(csound, Str("ksmps of %d needs wdw of %d, " "max is %d for pv %s"), CS_KSMPS, (int) (OPWLEN / 2 + 1), (int) PVWINLEN, pvfilnam); } return OK; } int pvbufreadset(CSOUND *csound, PVBUFREAD *p){ return pvbufreadset_(csound,p,0); } int pvbufreadset_S(CSOUND *csound, PVBUFREAD *p){ return pvbufreadset_(csound,p,1); } int pvbufread(CSOUND *csound, PVBUFREAD *p) { MYFLT frIndx; MYFLT *buf = p->fftBuf; int size = pvfrsiz(p); if (UNLIKELY(p->auxch.auxp == NULL)) goto err1; /* RWD fix */ if (UNLIKELY((frIndx = *p->ktimpnt * p->frPrtim) < 0)) goto err2; if (frIndx > (MYFLT) p->maxFr) { /* not past last one */ frIndx = (MYFLT) p->maxFr; if (UNLIKELY(p->prFlg)) { p->prFlg = 0; /* false */ csound->Warning(csound, Str("PVOC ktimpnt truncated to last frame")); } } FetchIn(p->frPtr, buf, size, frIndx); p->buf = buf; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("pvbufread: not initialised")); err2: return csound->PerfError(csound, p->h.insdshead, Str("PVOC timpnt < 0")); } /************************************************************/ /*************PVINTERP**************************************/ /************************************************************/ int pvinterpset_(CSOUND *csound, PVINTERP *p, int stringname) { unsigned int i; char pvfilnam[MAXNAME]; PVOCEX_MEMFILE pp; int frInc, chans; /* THESE SHOULD BE SAVED IN PVOC STRUCT */ p->pp = PVOC_GetGlobals(csound); p->pvbufread = p->pp->pvbufreadaddr; if (UNLIKELY(p->pvbufread == NULL)) return csound->InitError(csound, Str("pvinterp: associated pvbufread not found")); if (p->auxch.auxp == NULL) { /* if no buffers yet, alloc now */ MYFLT *fltp; csound->AuxAlloc(csound, (PVDATASIZE + PVFFTSIZE * 3 + PVWINLEN) * sizeof(MYFLT), &p->auxch); fltp = (MYFLT *) p->auxch.auxp; p->lastPhase = fltp; fltp += PVDATASIZE; /* and insert addresses */ p->fftBuf = fltp; fltp += PVFFTSIZE; p->dsBuf = fltp; fltp += PVFFTSIZE; p->outBuf = fltp; fltp += PVFFTSIZE; p->window = fltp; } if (stringname==0){ if (csound->ISSTRCOD(*p->ifilno)) strncpy(pvfilnam,get_arg_string(csound, *p->ifilno), MAXNAME-1); else csound->strarg2name(csound, pvfilnam, p->ifilno, "pvoc.",0); } else strncpy(pvfilnam, ((STRINGDAT *)p->ifilno)->data, MAXNAME-1);; if (UNLIKELY(csound->PVOCEX_LoadFile(csound, pvfilnam, &pp) != 0)) return csound->InitError(csound, Str("PVINTERP cannot load %s"), pvfilnam); p->frSiz = pp.fftsize; frInc = pp.overlap; chans = pp.chans; p->asr = pp.srate; if (UNLIKELY(p->asr != CS_ESR)) { /* & chk the data */ csound->Warning(csound, Str("%s's srate = %8.0f, orch's srate = %8.0f"), pvfilnam, p->asr, CS_ESR); } if (UNLIKELY(p->frSiz != p->pvbufread->frSiz)) { return csound->InitError(csound, Str("pvinterp: %s: frame size %d does not " "match pvbufread frame size %d\n"), pvfilnam, (int) p->frSiz, (int) p->pvbufread->frSiz); } if (UNLIKELY(chans != 1)) { return csound->InitError(csound, Str("%d chans (not 1) in PVOC file %s"), (int) chans, pvfilnam); } /* Check that pv->frSiz is a power of two too ? */ p->frPtr = (float*) pp.data; p->baseFr = 0; /* point to first data frame */ p->maxFr = pp.nframes - 1; /* highest possible frame index */ p->frPktim = (MYFLT) CS_KSMPS / (MYFLT) frInc; /* factor by which to mult expand phase diffs (ratio of samp spacings) */ p->frPrtim = CS_ESR / (MYFLT) frInc; /* factor by which to mulitply 'real' time index to get frame index */ /* amplitude scale for PVOC */ /* p->scale = (MYFLT) pp.fftsize * ((MYFLT) pp.fftsize / (MYFLT) pp.winsize); */ p->scale = (MYFLT) pp.fftsize * FL(0.5); p->scale *= csound->GetInverseRealFFTScale(csound, pp.fftsize); /* 2*incr/OPWLEN scales down for win ovlp, windo'd 1ce (but 2ce?) */ /* 1/frSiz is the required scale down before (i)FFT */ p->prFlg = 1; /* true */ p->opBpos = 0; p->lastPex = FL(1.0); /* needs to know last pitchexp to update phase */ /* Set up time window */ memset(p->lastPhase,'\0', pvdasiz(p)*sizeof(MYFLT)); /* for (i = 0; i < pvdasiz(p); ++i) { /\* or maybe pvdasiz(p) *\/ */ /* p->lastPhase[i] = FL(0.0); */ /* } */ if (UNLIKELY((OPWLEN / 2 + 1) > PVWINLEN)) { return csound->InitError(csound, Str("ksmps of %d needs wdw of %d, " "max is %d for pv %s"), CS_KSMPS, (OPWLEN / 2 + 1), PVWINLEN, pvfilnam); } for (i = 0; i < OPWLEN / 2 + 1; ++i) /* time window is OPWLEN long */ p->window[i] = (MYFLT) (0.5 - 0.5 * cos(TWOPI*(double)i/(double)OPWLEN)); /* NB: HANNING */ memset(p->outBuf, 0, pvfrsiz(p)*sizeof(MYFLT)); /* for (i = 0; i< pvfrsiz(p); ++i) */ /* p->outBuf[i] = FL(0.0); */ MakeSinc(p->pp); /* sinctab is same for all instances */ return OK; } int pvinterpset(CSOUND *csound, PVINTERP *p){ return pvinterpset_(csound,p,0); } int pvinterpset_S(CSOUND *csound, PVINTERP *p){ return pvinterpset_(csound,p,1); } int pvinterp(CSOUND *csound, PVINTERP *p) { MYFLT *ar = p->rslt; MYFLT frIndx; MYFLT *buf = p->fftBuf; MYFLT *buf2 = p->dsBuf; int asize = pvdasiz(p); /* fix */ int size = pvfrsiz(p); int buf2Size, outlen; int circBufSize = PVFFTSIZE; MYFLT pex, scaleFac = p->scale; PVBUFREAD *q = p->pvbufread; int32 i, j; if (UNLIKELY(p->auxch.auxp == NULL)) goto err1; /* RWD Fix */ pex = *p->kfmod; outlen = (int) (((MYFLT) size) / pex); /* use outlen to check window/krate/transpose combinations */ if (UNLIKELY(outlen>PVFFTSIZE)) /* Maximum transposition down is one octave */ /* ..so we won't run into buf2Size problems */ goto err2; if (UNLIKELY(outlen<(int)(2*CS_KSMPS))) goto err3; /* minimum post-squeeze windowlength */ buf2Size = OPWLEN; /* always window to same length after DS */ if (UNLIKELY((frIndx = *p->ktimpnt * p->frPrtim) < 0)) goto err4; if (frIndx > (MYFLT)p->maxFr) { /* not past last one */ frIndx = (MYFLT)p->maxFr; if (UNLIKELY(p->prFlg)) { p->prFlg = 0; /* false */ csound->Warning(csound, Str("PVOC ktimpnt truncated to last frame")); } } FetchIn(p->frPtr, buf, size, frIndx); /* Here's where the interpolation happens ***********************/ if (pex > FL(1.0)) scaleFac /= pex; for (i = 0, j = 1; i <= size; i += 2, j += 2) { buf[i] = buf[i] * *p->kampscale2; q->buf[i] = q->buf[i] * *p->kampscale1; buf[j] = buf[j] * *p->kfreqscale2; q->buf[j] = q->buf[j] * *p->kfreqscale1; buf[i] = (buf[i] + ((q->buf[i] - buf[i]) * *p->kampinterp)) * scaleFac; buf[j] = (buf[j] + ((q->buf[j] - buf[j]) * *p->kfreqinterp)); } /*******************************************************************/ FrqToPhase(buf, asize, pex * (MYFLT) CS_KSMPS, p->asr, (MYFLT) (0.5 * ((pex / p->lastPex) - 1))); /* accumulate phase and wrap to range -PI to PI */ RewrapPhase(buf, asize, p->lastPhase); Polar2Real_PVOC(csound, buf, (int) size); if (pex != FL(1.0)) UDSample(p->pp, buf, (FL(0.5) * ((MYFLT) size - pex * (MYFLT) buf2Size)), buf2, size, buf2Size, pex); else memcpy(buf2, buf + (int) ((size - buf2Size) >> 1), sizeof(MYFLT) * buf2Size); ApplyHalfWin(buf2, p->window, buf2Size); addToCircBuf(buf2, p->outBuf, p->opBpos, CS_KSMPS, circBufSize); writeClrFromCircBuf(p->outBuf, ar, p->opBpos, CS_KSMPS, circBufSize); p->opBpos += CS_KSMPS; if (UNLIKELY(p->opBpos > circBufSize)) p->opBpos -= circBufSize; addToCircBuf(buf2 + CS_KSMPS, p->outBuf, p->opBpos, buf2Size - CS_KSMPS, circBufSize); p->lastPex = pex; /* needs to know last pitchexp to update phase */ return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("pvinterp: not initialised")); err2: return csound->PerfError(csound, p->h.insdshead, Str("PVOC transpose too low")); err3: return csound->PerfError(csound, p->h.insdshead, Str("PVOC transpose too high")); err4: return csound->PerfError(csound, p->h.insdshead, Str("PVOC timpnt < 0")); } /************************************************************/ /************* PVCROSS **************************************/ /************************************************************/ int pvcrossset_(CSOUND *csound, PVCROSS *p, int stringname) { uint32_t i; char pvfilnam[MAXNAME]; PVOCEX_MEMFILE pp; int frInc, chans; /* THESE SHOULD BE SAVED IN PVOC STRUCT */ p->pp = PVOC_GetGlobals(csound); p->pvbufread = p->pp->pvbufreadaddr; if (UNLIKELY(p->pvbufread == NULL)) return csound->InitError(csound, Str("pvcross: associated pvbufread not found")); if (p->auxch.auxp == NULL) { /* if no buffers yet, alloc now */ MYFLT *fltp; csound->AuxAlloc(csound, (PVDATASIZE + PVFFTSIZE * 3 + PVWINLEN) * sizeof(MYFLT), &p->auxch); fltp = (MYFLT *) p->auxch.auxp; p->lastPhase = fltp; fltp += PVDATASIZE; /* and insert addresses */ p->fftBuf = fltp; fltp += PVFFTSIZE; p->dsBuf = fltp; fltp += PVFFTSIZE; p->outBuf = fltp; fltp += PVFFTSIZE; p->window = fltp; } if (stringname==0){ if (csound->ISSTRCOD(*p->ifilno)) strncpy(pvfilnam,get_arg_string(csound, *p->ifilno), MAXNAME-1); else csound->strarg2name(csound, pvfilnam, p->ifilno, "pvoc.",0); } else strncpy(pvfilnam, ((STRINGDAT *)p->ifilno)->data, MAXNAME-1); if (UNLIKELY(csound->PVOCEX_LoadFile(csound, pvfilnam, &pp) != 0)) return csound->InitError(csound, Str("PVCROSS cannot load %s"), pvfilnam); p->frSiz = pp.fftsize; frInc = pp.overlap; chans = pp.chans; p->asr = pp.srate; if (UNLIKELY(p->asr != CS_ESR)) { /* & chk the data */ csound->Warning(csound, Str("%s's srate = %8.0f, orch's srate = %8.0f"), pvfilnam, p->asr, CS_ESR); } if (UNLIKELY(p->frSiz != p->pvbufread->frSiz)) { return csound->InitError(csound, Str("pvcross: %s: frame size %d does not " "match pvbufread frame size %d\n"), pvfilnam, (int) p->frSiz, (int) p->pvbufread->frSiz); } if (UNLIKELY(chans != 1)) { return csound->InitError(csound, Str("%d chans (not 1) in PVOC file %s"), (int) chans, pvfilnam); } /* Check that pv->frSiz is a power of two too ? */ p->frPtr = (float*) pp.data; p->baseFr = 0; /* point to first data frame */ p->maxFr = pp.nframes - 1; /* highest possible frame index */ p->frPktim = (MYFLT) CS_KSMPS / (MYFLT) frInc; /* factor by which to mult expand phase diffs (ratio of samp spacings) */ p->frPrtim = CS_ESR / (MYFLT) frInc; /* factor by which to mulitply 'real' time index to get frame index */ /* amplitude scale for PVOC */ /* p->scale = (MYFLT) pp.fftsize * ((MYFLT) pp.fftsize / (MYFLT) pp.winsize); */ p->scale = (MYFLT) pp.fftsize * FL(0.5); p->scale *= csound->GetInverseRealFFTScale(csound, pp.fftsize); p->prFlg = 1; /* true */ p->opBpos = 0; p->lastPex = FL(1.0); /* needs to know last pitchexp to update phase */ /* Set up time window */ memset(p->lastPhase, '\0', pvdasiz(p)*sizeof(MYFLT)); /* for (i = 0; i < pvdasiz(p); ++i) { /\* or maybe pvdasiz(p) *\/ */ /* p->lastPhase[i] = FL(0.0); */ /* } */ if (UNLIKELY((OPWLEN / 2 + 1) > PVWINLEN )) { return csound->InitError(csound, Str("ksmps of %d needs wdw of %d, " "max is %d for pv %s"), CS_KSMPS, (OPWLEN / 2 + 1), PVWINLEN, pvfilnam); } for (i = 0; i < OPWLEN / 2 + 1; ++i) /* time window is OPWLEN long */ p->window[i] = (MYFLT) (0.5 - 0.5 * cos(TWOPI*(double)i/(double)OPWLEN)); /* NB: HANNING */ memset(p->outBuf, 0, pvfrsiz(p)*sizeof(MYFLT)); /* for (i = 0; i < pvfrsiz(p); ++i) */ /* p->outBuf[i] = FL(0.0); */ MakeSinc(p->pp); /* sinctab is same for all instances */ if (p->memenv.auxp == NULL || p->memenv.size < pvdasiz(p)*sizeof(MYFLT)) csound->AuxAlloc(csound, pvdasiz(p) * sizeof(MYFLT), &p->memenv); return OK; } int pvcrossset(CSOUND *csound, PVCROSS *p){ return pvcrossset_(csound,p,0); } int pvcrossset_S(CSOUND *csound, PVCROSS *p) { return pvcrossset_(csound,p,1); } int pvcross(CSOUND *csound, PVCROSS *p) { MYFLT *ar = p->rslt; MYFLT frIndx; MYFLT *buf = p->fftBuf; MYFLT *buf2 = p->dsBuf; int asize = pvdasiz(p); /* fix */ int size = pvfrsiz(p); int buf2Size, outlen; int circBufSize = PVFFTSIZE; int specwp = (int) *p->ispecwp; /* spectral warping flag */ MYFLT pex, scaleFac = p->scale; PVBUFREAD *q = p->pvbufread; int32 i, j; MYFLT ampscale1 = *p->kampscale1; MYFLT ampscale2 = *p->kampscale2; if (UNLIKELY(p->auxch.auxp == NULL)) goto err1; /* RWD Fix */ pex = *p->kfmod; outlen = (int) (((MYFLT) size) / pex); /* use outlen to check window/krate/transpose combinations */ if (UNLIKELY(outlen>PVFFTSIZE)) /* Maximum transposition down is one octave */ /* ..so we won't run into buf2Size problems */ goto err2; if (UNLIKELY(outlen<(int)(2*CS_KSMPS))) /* minimum post-squeeze windowlength */ goto err3; buf2Size = OPWLEN; /* always window to same length after DS */ if (UNLIKELY((frIndx = *p->ktimpnt * p->frPrtim) < 0)) goto err4; if (frIndx > (MYFLT) p->maxFr) { /* not past last one */ frIndx = (MYFLT) p->maxFr; if (p->prFlg) { p->prFlg = 0; /* false */ csound->Warning(csound, Str("PVOC ktimpnt truncated to last frame")); } } FetchIn(p->frPtr, buf, size, frIndx); /**** Apply amplitudes from pvbufread ********/ if (pex > FL(1.0)) scaleFac /= pex; for (i = 0, j = 0; i <= size; i += 2, j++) buf[i] = ((buf[i] * ampscale2) + (q->buf[i] * ampscale1)) * scaleFac; /***************************************************/ FrqToPhase(buf, asize, pex * (MYFLT) CS_KSMPS, p->asr, (MYFLT) (0.5 * ((pex / p->lastPex) - 1))); /* accumulate phase and wrap to range -PI to PI */ RewrapPhase(buf, asize, p->lastPhase); if (specwp == 0 || (p->prFlg)++ == -(int) specwp) { /* ?screws up when prFlg used */ /* specwp=0 => normal; specwp = -n => just nth frame */ #ifdef BETA if (specwp < 0) csound->Message(csound, Str("PVOC debug: one frame gets through\n")); #endif if (specwp > 0) PreWarpSpec(buf, asize, pex, (MYFLT *)p->memenv.auxp); Polar2Real_PVOC(csound, buf, (int) size); if (pex != FL(1.0)) UDSample(p->pp, buf, (FL(0.5) * ((MYFLT) size - pex * (MYFLT) buf2Size)), buf2, size, buf2Size, pex); else memcpy(buf2, buf + (int) ((size - buf2Size) >> 1), sizeof(MYFLT) * buf2Size); if (specwp >= 0) ApplyHalfWin(buf2, p->window, buf2Size); } else { memset(buf2, 0, buf2Size*sizeof(MYFLT)); } addToCircBuf(buf2, p->outBuf, p->opBpos, CS_KSMPS, circBufSize); writeClrFromCircBuf(p->outBuf, ar, p->opBpos, CS_KSMPS, circBufSize); p->opBpos += CS_KSMPS; if (UNLIKELY(p->opBpos > circBufSize)) p->opBpos -= circBufSize; addToCircBuf(buf2 + CS_KSMPS, p->outBuf, p->opBpos, buf2Size - CS_KSMPS, circBufSize); p->lastPex = pex; /* needs to know last pitchexp to update phase */ return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("pvcross: not initialised")); err2: return csound->PerfError(csound, p->h.insdshead, Str("PVOC transpose too low")); err3: return csound->PerfError(csound, p->h.insdshead, Str("PVOC transpose too high")); err4: return csound->PerfError(csound, p->h.insdshead, Str("PVOC timpnt < 0")); } csound-6.10.0/Opcodes/pvinterp.h000066400000000000000000000062421321653344700165210ustar00rootroot00000000000000/* pvinterp.h: Copyright (C) 1996 Richard Karpen This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* PVINTERP.H */ typedef struct { OPDS h; MYFLT *ktimpnt, *ifilno; int32 maxFr, frSiz, prFlg; /* base Frame (in frameData0) and maximum frame on file, ptr to fr, size */ MYFLT frPktim, frPrtim, asr, scale; float *frPtr; AUXCH auxch; MYFLT *lastPhase, *fftBuf; /* [PVFFTSIZE] FFT works on Real & Imag */ MYFLT *buf; } PVBUFREAD; typedef struct { OPDS h; MYFLT *rslt, *ktimpnt, *kfmod, *ifilno, *kfreqscale1, *kfreqscale2, *kampscale1, *kampscale2, *kfreqinterp, *kampinterp; int32 kcnt; int32 baseFr, maxFr, frSiz, prFlg, opBpos; /* base Frame (in frameData0) and maximum frame on file, ptr to fr, size */ MYFLT frPktim, frPrtim, asr, scale, lastPex; float *frPtr; /* asr is analysis sample rate */ /* fft frames per k-time (equals phase change expansion factor) */ AUXCH auxch; /* manage AUXDS for the following 5 buffer spaces */ MYFLT *lastPhase; /* [PVDATASIZE] Keep track of cum. phase */ MYFLT *fftBuf; /* [PVFFTSIZE] FFT works on Real & Imag */ MYFLT *dsBuf; /* [PVFFTSIZE] Output of downsampling may be 2x */ MYFLT *outBuf; /* [PVFFTSIZE] Output buffer over win length */ MYFLT *window; /* [PVWINLEN] Store 1/2 window */ PVBUFREAD *pvbufread; PVOC_GLOBALS *pp; } PVINTERP; typedef struct { OPDS h; MYFLT *rslt, *ktimpnt, *kfmod, *ifilno, *kampscale1, *kampscale2, *ispecwp; int32 kcnt; int32 baseFr, maxFr, frSiz, prFlg, opBpos; /* base Frame (in frameData0) and maximum frame on file, ptr to fr, size */ MYFLT frPktim, frPrtim, asr, scale, lastPex; float *frPtr; /* asr is analysis sample rate */ /* fft frames per k-time (equals phase change expansion factor) */ AUXCH auxch; /* manage AUXDS for the following 5 buffer spaces */ MYFLT *lastPhase; /* [PVDATASIZE] Keep track of cum. phase */ MYFLT *fftBuf; /* [PVFFTSIZE] FFT works on Real & Imag */ MYFLT *dsBuf; /* [PVFFTSIZE] Output of downsampling may be 2x */ MYFLT *outBuf; /* [PVFFTSIZE] Output buffer over win length */ MYFLT *window; /* [PVWINLEN] Store 1/2 window */ PVBUFREAD *pvbufread; PVOC_GLOBALS *pp; AUXCH memenv; } PVCROSS; csound-6.10.0/Opcodes/pvlock.c000066400000000000000000001024171321653344700161440ustar00rootroot00000000000000/* pvlock.c: Copyright (C) 2009 V Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "interlocks.h" #include "pstream.h" #include "soundio.h" #define MAXOUTS 2 typedef struct dats{ OPDS h; MYFLT *out[MAXOUTS], *time, *kamp, *kpitch, *knum, *klock, *iN, *idecim, *konset, *offset, *dbthresh; int cnt, hsize, curframe, N, decim,tscale; unsigned int nchans; double pos; MYFLT accum; AUXCH outframe[MAXOUTS], win, bwin[MAXOUTS], fwin[MAXOUTS], nwin[MAXOUTS], prev[MAXOUTS], framecount[MAXOUTS], fdata; MYFLT *indata[2]; MYFLT *tab; int curbuf; SNDFILE *sf; FDCH fdch; MYFLT resamp; double tstamp, incr; void *fwdsetup, *invsetup; } DATASPACE; static inline int32 intpowint(int32 x, uint32 n) /* Binary +ve power function */ { int32 ans = 1; while (n!=0) { if (n&1) ans = ans * x; n >>= 1; x = x*x; } return ans; } static int sinit(CSOUND *csound, DATASPACE *p) { int N = *p->iN, ui; unsigned int nchans, i; unsigned int size; int decim = *p->idecim; if (N) { for (i=0; N; i++) { N >>= 1; } N = intpowint(2, i-1); /* faster than pow fn */ } else N = 2048; if (decim == 0) decim = 4; p->hsize = N/decim; p->cnt = p->hsize; p->curframe = 0; p->pos = 0; nchans = p->nchans; if (UNLIKELY(nchans < 1 || nchans > MAXOUTS)) return csound->InitError(csound, Str("invalid number of output arguments")); p->nchans = nchans; for (i=0; i < nchans; i++){ size = (N+2)*sizeof(MYFLT); if (p->fwin[i].auxp == NULL || p->fwin[i].size < size) csound->AuxAlloc(csound, size, &p->fwin[i]); if (p->bwin[i].auxp == NULL || p->bwin[i].size < size) csound->AuxAlloc(csound, size, &p->bwin[i]); if (p->prev[i].auxp == NULL || p->prev[i].size < size) csound->AuxAlloc(csound, size, &p->prev[i]); size = decim*sizeof(int); if (p->framecount[i].auxp == NULL || p->framecount[i].size < size) csound->AuxAlloc(csound, size, &p->framecount[i]); { int k=0; for (k=0; k < decim; k++) { ((int *)(p->framecount[i].auxp))[k] = k*N; } } size = decim*sizeof(MYFLT)*N; if (p->outframe[i].auxp == NULL || p->outframe[i].size < size) csound->AuxAlloc(csound, size, &p->outframe[i]); else memset(p->outframe[i].auxp,0,size); } size = N*sizeof(MYFLT); if (p->win.auxp == NULL || p->win.size < size) csound->AuxAlloc(csound, size, &p->win); { MYFLT x = FL(2.0)*PI_F/N; for (ui=0; ui < N; ui++) ((MYFLT *)p->win.auxp)[ui] = FL(0.5) - FL(0.5)*COS((MYFLT)ui*x); } p->N = N; p->decim = decim; p->fwdsetup = csound->RealFFT2Setup(csound, N, FFT_FWD); p->invsetup = csound->RealFFT2Setup(csound, N, FFT_INV); return OK; } static int sinit1(CSOUND *csound, DATASPACE *p){ p->nchans = csound->GetOutputArgCnt(p); return sinit(csound, p); } static int sprocess1(CSOUND *csound, DATASPACE *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; MYFLT pitch = *p->kpitch, *time = p->time, lock = *p->klock, *out, amp =*p->kamp; MYFLT *tab, frac; FUNC *ft; int N = p->N, hsize = p->hsize, cnt = p->cnt, nchans = p->nchans; int nsmps = CS_KSMPS, n; int sizefrs, size, post, i, j; long spos = p->pos; double pos; MYFLT *fwin, *bwin, in, *prev, *win = (MYFLT *) p->win.auxp; MYFLT *outframe; MYFLT ph_real, ph_im, tmp_real, tmp_im, div; int *framecnt; int curframe = p->curframe, decim = p->decim; double scaling = (8./decim)/3.; if (UNLIKELY(early)) { nsmps -= early; for (j=0; j < nchans; j++) { out = p->out[j]; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } } if (UNLIKELY(offset)) { for (j=0; j < nchans; j++) { out = p->out[j]; memset(out, '\0', offset*sizeof(MYFLT)); } } for (n=offset; n < nsmps; n++) { if (cnt == hsize) { /* audio samples are stored in a function table */ ft = csound->FTnp2Find(csound,p->knum); tab = ft->ftable; size = ft->flen; if (UNLIKELY((int) ft->nchanls != nchans)) return csound->PerfError(csound, p->h.insdshead, Str("number of output arguments " "inconsistent with number of " "sound file channels")); /* spos is the reading position in samples, hsize is hopsize, time[n] is current read position in secs esr is sampling rate */ spos = hsize*(long)((time[n])*CS_ESR/hsize); sizefrs = size/nchans; while (spos > sizefrs) spos -= sizefrs; while (spos <= 0) spos += sizefrs; for (j = 0; j < nchans; j++) { pos = spos; bwin = (MYFLT *) p->bwin[j].auxp; fwin = (MYFLT *) p->fwin[j].auxp; prev = (MYFLT *)p->prev[j].auxp; framecnt = (int *)p->framecount[j].auxp; outframe= (MYFLT *) p->outframe[j].auxp; /* this loop fills two frames/windows with samples from table, reading is linearly-interpolated, frames are separated by 1 hopsize */ for (i=0; i < N; i++) { /* front window, fwin */ post = (int) pos; frac = pos - post; post *= nchans; post += j; while (post < 0) post += size; while (post >= size) post -= size; if (post+nchans < size) in = tab[post] + frac*(tab[post+nchans] - tab[post]); else in = tab[post]; fwin[i] = in * win[i]; /* window it */ /* back windo, bwin */ post = (int) (pos - hsize*pitch); post *= nchans; post += j; while (post < 0) post += size; while (post >= size) post -= size; if (post+nchans < size) in = tab[post] + frac*(tab[post+nchans] - tab[post]); else in = tab[post]; bwin[i] = in * win[i]; /* window it */ /* increment read pos according to pitch transposition */ pos += pitch; } /* take the FFT of both frames re-order Nyquist bin from pos 1 to N */ csound->RealFFT2(csound, p->fwdsetup, bwin); bwin[N] = bwin[1]; bwin[N+1] = 0.0; csound->RealFFT2(csound, p->fwdsetup, fwin); fwin[N] = fwin[1]; fwin[N+1] = 0.0; /* phase vocoder processing */ for (i=0; i < N + 2; i+=2) { /* phases of previous output frame in exponential format, obtained by dividing by magnitude */ div = FL(1.0)/(HYPOT(prev[i], prev[i+1]) + 1e-20); ph_real = prev[i]*div; ph_im = prev[i+1]*div; /* back window magnitudes, phase differences between prev and back windows */ tmp_real = bwin[i] * ph_real + bwin[i+1] * ph_im; tmp_im = bwin[i] * ph_im - bwin[i+1] * ph_real; bwin[i] = tmp_real; bwin[i+1] = tmp_im; } for (i=0; i < N + 2; i+=2) { if (lock) { /* phase-locking */ if (i > 0) { if (i < N){ tmp_real = bwin[i] + bwin[i-2] + bwin[i+2]; tmp_im = bwin[i+1] + bwin[i-1] + bwin[i+3]; } else { /* Nyquist */ tmp_real = bwin[i] + bwin[i-2]; tmp_im = FL(0.0); } } else { /* 0 Hz */ tmp_real = bwin[i] + bwin[i+2]; tmp_im = FL(0.0); } } else { /* no locking */ tmp_real = bwin[i]; tmp_im = bwin[i+1]; } tmp_real += 1e-15; div = FL(1.0)/(HYPOT(tmp_real, tmp_im)); /* phases of tmp frame */ ph_real = tmp_real*div; ph_im = tmp_im*div; /* front window mags, phase sum of tmp and front windows */ tmp_real = fwin[i] * ph_real - fwin[i+1] * ph_im; tmp_im = fwin[i] * ph_im + fwin[i+1] * ph_real; /* phase vocoder output */ prev[i] = fwin[i] = tmp_real; prev[i+1] = fwin[i+1] = tmp_im; } /* re-order bins and take inverse FFT */ fwin[1] = fwin[N]; csound->RealFFT2(csound, p->invsetup, fwin); /* frame counter */ framecnt[curframe] = curframe*N; /* write to overlapped output frames */ for (i=0;iframecount[j].auxp; outframe = (MYFLT *) p->outframe[j].auxp; out = p->out[j]; out[n] = (MYFLT)0; /* write output */ for (i = 0; i < decim; i++) { out[n] += outframe[framecnt[i]]; framecnt[i]++; } /* scale output */ out[n] *= amp*scaling; } cnt++; } p->cnt = cnt; p->curframe = curframe; return OK; } static int sinit2(CSOUND *csound, DATASPACE *p) { unsigned int size,i; p->nchans = csound->GetOutputArgCnt(p); sinit(csound, p); size = p->N*sizeof(MYFLT); for (i=0; i < p->nchans; i++) if (p->nwin[i].auxp == NULL || p->nwin[i].size < size) csound->AuxAlloc(csound, size, &p->nwin[i]); p->pos = *p->offset*CS_ESR + p->hsize; p->tscale = 0; p->accum = 0; return OK; } static int sprocess2(CSOUND *csound, DATASPACE *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; MYFLT pitch = *p->kpitch, time = *p->time, lock = *p->klock; MYFLT *out, amp =*p->kamp; MYFLT *tab,frac, dbtresh = *p->dbthresh; FUNC *ft; int N = p->N, hsize = p->hsize, cnt = p->cnt, sizefrs, nchans = p->nchans; int nsmps = CS_KSMPS, n; int size, post, i, j; double pos, spos = p->pos; MYFLT *fwin, *bwin; MYFLT in, *nwin, *prev; MYFLT *win = (MYFLT *) p->win.auxp, *outframe; MYFLT powrat; MYFLT ph_real, ph_im, tmp_real, tmp_im, div; int *framecnt, curframe = p->curframe; int decim = p->decim; double scaling = (8./decim)/3.; if (UNLIKELY(early)) { nsmps -= early; for (j=0; j < nchans; j++) { out = p->out[j]; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } } if (UNLIKELY(offset)) { for (j=0; j < nchans; j++) { out = p->out[j]; memset(out, '\0', offset*sizeof(MYFLT)); } } for (n=offset; n < nsmps; n++) { if (cnt == hsize){ ft = csound->FTnp2Find(csound,p->knum); tab = ft->ftable; size = ft->flen; if (time < 0 || time >= 1 || !*p->konset) { spos += hsize*time; //csound->Message(csound, "position: %f \n", spos); } else if (p->tscale) { spos += hsize*(time/(1+p->accum)); p->accum=0.0; } else { spos += hsize; p->accum++; p->tscale = 1; } if (UNLIKELY((int) ft->nchanls != nchans)) return csound->PerfError(csound, p->h.insdshead, Str("number of output arguments " "inconsistent with number of " "sound file channels")); sizefrs = size/nchans; while (spos > sizefrs) spos -= sizefrs; while (spos <= 0) spos += sizefrs; for (j = 0; j < nchans; j++) { pos = spos; bwin = (MYFLT *) p->bwin[j].auxp; fwin = (MYFLT *) p->fwin[j].auxp; nwin = (MYFLT *) p->nwin[j].auxp; prev = (MYFLT *)p->prev[j].auxp; framecnt = (int *)p->framecount[j].auxp; outframe= (MYFLT *) p->outframe[j].auxp; for (i=0; i < N; i++) { post = (int) pos; frac = pos - post; post *= nchans; post += j; while (post < 0) post += size; while (post >= size) post -= size; if (post+nchans < size) in = tab[post] + frac*(tab[post+nchans] - tab[post]); else in = tab[post]; fwin[i] = in * win[i]; post = (int) (pos - hsize*pitch); post *= nchans; post += j; while (post < 0) post += size; while (post >= size) post -= size; //if (post >= 0 && post < size) if (post+nchans < size) in = tab[post] + frac*(tab[post+nchans] - tab[post]); else in = tab[post]; //else in = (MYFLT) 0; bwin[i] = in * win[i]; post = (int) pos + hsize; post *= nchans; post += j; while (post < 0) post += size; while (post >= size) post -= size; if (post+nchans < size) in = tab[post] + frac*(tab[post+nchans] - tab[post]); else in = tab[post]; nwin[i] = in * win[i]; pos += pitch; } csound->RealFFT2(csound, p->fwdsetup, bwin); bwin[N] = bwin[1]; bwin[N+1] = FL(0.0); csound->RealFFT2(csound, p->fwdsetup, fwin); csound->RealFFT2(csound, p->fwdsetup, nwin); tmp_real = tmp_im = (MYFLT) 1e-20; for (i=2; i < N; i++) { tmp_real += nwin[i]*nwin[i] + nwin[i+1]*nwin[i+1]; tmp_im += fwin[i]*fwin[i] + fwin[i+1]*fwin[i+1]; } powrat = FL(20.0)*LOG10(tmp_real/tmp_im); if (powrat > dbtresh) p->tscale=0; /*else tscale=1;*/ fwin[N] = fwin[1]; fwin[N+1] = FL(0.0); for (i=0; i < N + 2; i+=2) { div = FL(1.0)/(HYPOT(prev[i], prev[i+1]) + 1.0e-20); ph_real = prev[i]*div; ph_im = prev[i+1]*div; tmp_real = bwin[i] * ph_real + bwin[i+1] * ph_im; tmp_im = bwin[i] * ph_im - bwin[i+1] * ph_real; bwin[i] = tmp_real; bwin[i+1] = tmp_im; } for (i=0; i < N + 2; i+=2) { if (lock) { if (i > 0) { if (i < N) { tmp_real = bwin[i] + bwin[i-2] + bwin[i+2]; tmp_im = bwin[i+1] + bwin[i-1] + bwin[i+3]; } else { tmp_real = bwin[i] + bwin[i-2]; tmp_im = FL(0.0); } } else { tmp_real = bwin[i] + bwin[i+2]; tmp_im = FL(0.0); } } else { tmp_real = bwin[i]; tmp_im = bwin[i+1]; } tmp_real += 1e-15; div = FL(1.0)/(HYPOT(tmp_real, tmp_im)); ph_real = tmp_real*div; ph_im = tmp_im*div; tmp_real = fwin[i] * ph_real - fwin[i+1] * ph_im; tmp_im = fwin[i] * ph_im + fwin[i+1] * ph_real; prev[i] = fwin[i] = tmp_real; prev[i+1] = fwin[i+1] = tmp_im; } fwin[1] = fwin[N]; csound->RealFFT2(csound, p->invsetup, fwin); framecnt[curframe] = curframe*N; for (i=0;iout[j]; framecnt = (int *) p->framecount[j].auxp; outframe = (MYFLT *) p->outframe[j].auxp; out[n] = (MYFLT) 0; for (i = 0; i < decim; i++) { out[n] += outframe[framecnt[i]]; framecnt[i]++; } out[n] *= amp*scaling; } cnt++; } p->cnt = cnt; p->curframe = curframe; p->pos = spos; return OK; } #define BUFS 20 static void fillbuf(CSOUND *csound, DATASPACE *p, int nsmps); /* file-reading version of temposcal */ static int sinit3(CSOUND *csound, DATASPACE *p) { unsigned int size,i; char *name; SF_INFO sfinfo; // open file void *fd; name = ((STRINGDAT *)p->knum)->data; fd = csound->FileOpen2(csound, &(p->sf), CSFILE_SND_R, name, &sfinfo, "SFDIR;SSDIR", CSFTYPE_UNKNOWN_AUDIO, 0); if (sfinfo.samplerate != CS_ESR) p->resamp = sfinfo.samplerate/CS_ESR; else p->resamp = 1; p->nchans = sfinfo.channels; if (p->OUTOCOUNT != p->nchans) return csound->InitError(csound, Str("filescal: mismatched channel numbers. " "%d outputs, %d inputs\n"), p->OUTOCOUNT, p->nchans); sinit(csound, p); size = p->N*sizeof(MYFLT); for (i=0; i < p->nchans; i++) if (p->nwin[i].auxp == NULL || p->nwin[i].size < size) csound->AuxAlloc(csound, size, &p->nwin[i]); size = p->N*sizeof(MYFLT)*BUFS; if (p->fdata.auxp == NULL || p->fdata.size < size) csound->AuxAlloc(csound, size, &p->fdata); p->indata[0] = p->fdata.auxp; p->indata[1] = (MYFLT *) (((char*)p->fdata.auxp) + size/2); memset(&(p->fdch), 0, sizeof(FDCH)); p->fdch.fd = fd; fdrecord(csound, &(p->fdch)); // fill buffers p->curbuf = 0; fillbuf(csound, p, p->N*BUFS/2); p->pos = *p->offset*CS_ESR + p->hsize; p->tscale = 0; p->accum = 0; p->tab = (MYFLT *) p->indata[0]; p->tstamp = 0.0; return OK; } /* this will read a buffer full of samples from disk position offset samps from the last call to fillbuf */ void fillbuf(CSOUND *csound, DATASPACE *p, int nsmps){ sf_count_t sampsread; // fill p->curbuf sampsread = sf_read_MYFLT(p->sf, p->indata[p->curbuf], nsmps); if (sampsread < nsmps) memset(p->indata[p->curbuf]+sampsread, 0, sizeof(MYFLT)*(nsmps-sampsread)); // point to the other p->curbuf = p->curbuf ? 0 : 1; } static int sprocess3(CSOUND *csound, DATASPACE *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; MYFLT pitch = *p->kpitch*p->resamp, time = *p->time, lock = *p->klock; MYFLT *out, amp =*p->kamp; MYFLT *tab,frac, dbtresh = *p->dbthresh; //FUNC *ft; int N = p->N, hsize = p->hsize, cnt = p->cnt, sizefrs, nchans = p->nchans; int nsmps = CS_KSMPS, n; int size, post, i, j; double pos, spos = p->pos; MYFLT *fwin, *bwin; MYFLT in, *nwin, *prev; MYFLT *win = (MYFLT *) p->win.auxp, *outframe; MYFLT powrat; MYFLT ph_real, ph_im, tmp_real, tmp_im, div; int *framecnt, curframe = p->curframe; int decim = p->decim; double tstamp = p->tstamp, incrt = p->incr; if (time < 0) /* negative tempo is not possible */ time = 0.0; time *= p->resamp; { int outnum = csound->GetOutputArgCnt(p); double _0dbfs = csound->Get0dBFS(csound); if (UNLIKELY(early)) { nsmps -= early; for (j=0; j < nchans; j++) { out = p->out[j]; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } } if (UNLIKELY(offset)) { for (j=0; j < nchans; j++) { out = p->out[j]; memset(out, '\0', offset*sizeof(MYFLT)); } } for (n=offset; n < nsmps; n++) { if (cnt == hsize){ tab = p->tab; size = p->fdata.size/sizeof(MYFLT); if (time < 0 || time >= 1 || !*p->konset) { spos += hsize*time; incrt = time*nsmps; } else if (p->tscale) { spos += hsize*(time/(1+p->accum)); incrt = (time/(1+p->accum))*nsmps; p->accum=0.0; } else { spos += hsize; incrt = nsmps; p->accum++; p->tscale = 1; } sizefrs = size/nchans; while (spos > sizefrs) { spos -= sizefrs; } while (spos <= 0) { spos += sizefrs; } if (spos > (MYFLT)(sizefrs/2) && p->curbuf == 0) { fillbuf(csound, p, size/2); } else if (spos < (MYFLT)(sizefrs/2) && p->curbuf == 1) { fillbuf(csound, p, size/2); } for (j = 0; j < nchans; j++) { pos = spos; bwin = (MYFLT *) p->bwin[j].auxp; fwin = (MYFLT *) p->fwin[j].auxp; nwin = (MYFLT *) p->nwin[j].auxp; prev = (MYFLT *)p->prev[j].auxp; framecnt = (int *)p->framecount[j].auxp; outframe= (MYFLT *) p->outframe[j].auxp; for (i=0; i < N; i++) { post = (int) pos; frac = pos - post; post *= nchans; post += j; while (post < 0) post += size; while (post >= size) post -= size; if (post+nchans < size) in = tab[post] + frac*(tab[post+nchans] - tab[post]); else { in = tab[post]; } fwin[i] = in * win[i]; post = (int) (pos - hsize*pitch); post *= nchans; post += j; while (post < 0) post += size; while (post >= size) post -= size; if (post+nchans < size) in = tab[post] + frac*(tab[post+nchans] - tab[post]); else in = tab[post]; bwin[i] = in * win[i]; post = (int) pos + hsize; post *= nchans; post += j; while (post < 0) post += size; while (post >= size) post -= size; if (post+nchans < size) in = tab[post] + frac*(tab[post+nchans] - tab[post]); else in = tab[post]; nwin[i] = in * win[i]; pos += pitch; } csound->RealFFT2(csound, p->fwdsetup, bwin); bwin[N] = bwin[1]; bwin[N+1] = FL(0.0); csound->RealFFT2(csound, p->fwdsetup, fwin); csound->RealFFT2(csound, p->fwdsetup, nwin); tmp_real = tmp_im = (MYFLT) 1e-20; for (i=2; i < N; i++) { tmp_real += nwin[i]*nwin[i] + nwin[i+1]*nwin[i+1]; tmp_im += fwin[i]*fwin[i] + fwin[i+1]*fwin[i+1]; } powrat = FL(20.0)*LOG10(tmp_real/tmp_im); if (powrat > dbtresh) p->tscale=0; /*else tscale=1;*/ fwin[N] = fwin[1]; fwin[N+1] = FL(0.0); for (i=0; i < N + 2; i+=2) { div = FL(1.0)/(HYPOT(prev[i], prev[i+1]) + 1.0e-20); ph_real = prev[i]*div; ph_im = prev[i+1]*div; tmp_real = bwin[i] * ph_real + bwin[i+1] * ph_im; tmp_im = bwin[i] * ph_im - bwin[i+1] * ph_real; bwin[i] = tmp_real; bwin[i+1] = tmp_im; } for (i=0; i < N + 2; i+=2) { if (lock) { if (i > 0) { if (i < N) { tmp_real = bwin[i] + bwin[i-2] + bwin[i+2]; tmp_im = bwin[i+1] + bwin[i-1] + bwin[i+3]; } else { tmp_real = bwin[i] + bwin[i-2]; tmp_im = FL(0.0); } } else { tmp_real = bwin[i] + bwin[i+2]; tmp_im = FL(0.0); } } else { tmp_real = bwin[i]; tmp_im = bwin[i+1]; } tmp_real += 1e-15; div = FL(1.0)/(HYPOT(tmp_real, tmp_im)); ph_real = tmp_real*div; ph_im = tmp_im*div; tmp_real = fwin[i] * ph_real - fwin[i+1] * ph_im; tmp_im = fwin[i] * ph_im + fwin[i+1] * ph_real; prev[i] = fwin[i] = tmp_real; prev[i+1] = fwin[i+1] = tmp_im; } fwin[1] = fwin[N]; csound->RealFFT2(csound, p->invsetup, fwin); framecnt[curframe] = curframe*N; for (i=0;iout[j]; framecnt = (int *) p->framecount[j].auxp; outframe = (MYFLT *) p->outframe[j].auxp; out[n] = (MYFLT) 0; for (i = 0; i < decim; i++) { out[n] += outframe[framecnt[i]]; framecnt[i]++; } out[n] *= _0dbfs*amp*(2./3.); } cnt++; } } p->cnt = cnt; p->curframe = curframe; p->pos = spos; //printf("%f s \n", tstamp/csound->GetSr(csound)); p->tstamp = tstamp + incrt; p->incr = incrt; return OK; } typedef struct { OPDS h; PVSDAT *fout; PVSDAT *fin; MYFLT *klock; MYFLT *file; uint32 lastframe; }PVSLOCK; static int pvslockset(CSOUND *csound, PVSLOCK *p) { int32 N = p->fin->N; if (UNLIKELY(p->fin == p->fout)) csound->Warning(csound, Str("Unsafe to have same fsig as in and out")); p->fout->N = N; p->fout->overlap = p->fin->overlap; p->fout->winsize = p->fin->winsize; p->fout->wintype = p->fin->wintype; p->fout->format = p->fin->format; p->fout->framecount = 1; p->lastframe = 0; if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(float) * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame); if (UNLIKELY(!(p->fout->format == PVS_AMP_FREQ) )) return csound->InitError(csound, Str("pvsfreeze: signal format " "must be amp-freq.")); return OK; } static int pvslockproc(CSOUND *csound, PVSLOCK *p) { int i; float *fout = (float *) p->fout->frame.auxp, *fin = (float *) p->fin->frame.auxp; int N = p->fin->N; if (p->lastframe < p->fin->framecount) { memcpy(fout,fin, sizeof(float)*(N+2)); //int l=0; if (*p->klock) { for (i=2; i < N-4; i+=2){ float p2 = fin[i]; float p3 = fin[i+2]; float p1 = fin[i-2]; float p4 = fin[i+4]; float p5 = fin[i+6]; if (p3 > p1 && p3 > p2 && p3 > p4 && p3 > p5) { float freq = fin[i+3], d; d = 0.01*freq; if (FABS(fout[i-1] - freq) < d)fout[i-1] = freq; if (FABS(fout[i+1] - freq) < d)fout[i+1] = freq; if (FABS(fout[i+3] - freq) < d)fout[i+3] = freq; if (FABS(fout[i+5] - freq) < d)fout[i+5] = freq; if (FABS(fout[i+7] - freq) < d)fout[i+7] = freq; //l+=1; } } //printf("%d peak locks\n", l); } p->fout->framecount = p->lastframe = p->fin->framecount; } return OK; } typedef struct hilb { OPDS h; MYFLT *out[2], *in, *ifftsize, *ihopsize; AUXCH fftdata, inframe, outframe; AUXCH win, iframecnt, oframecnt; int off, cnt, decim; int N, hop; } HILB; static int hilbert_init(CSOUND *csound, HILB *p){ int N = (int) *p->ifftsize; int h = (int) *p->ihopsize; unsigned int size; int *p1, *p2, i, decim; if (h > N) h = N; for (i=0; N; i++) { N >>= 1; } N = intpowint(2, i-1); for (i=0; h; i++) { h >>= 1; } h = intpowint(2, i-1); decim = N/h; size = (N*decim)*sizeof(MYFLT); if (p->inframe.auxp == NULL || p->inframe.size < size) csound->AuxAlloc(csound, size, &p->inframe); memset(p->inframe.auxp, 0, size); size *= 2; if (p->outframe.auxp == NULL || p->outframe.size < size) csound->AuxAlloc(csound, size, &p->outframe); memset(p->outframe.auxp, 0, size); size /= decim; if (p->fftdata.auxp == NULL || p->fftdata.size < size) csound->AuxAlloc(csound, size, &p->fftdata); memset(p->fftdata.auxp, 0, size); size = (N/h)*sizeof(int); if (p->iframecnt.auxp == NULL || p->iframecnt.size < size) csound->AuxAlloc(csound, size, &p->iframecnt); if (p->oframecnt.auxp == NULL || p->oframecnt.size < size) csound->AuxAlloc(csound, size, &p->oframecnt); p1 = (int *) p->iframecnt.auxp; p2 = (int *) p->oframecnt.auxp; for(i = 0; i < N/h; i++){ p1[i] = (decim - 1 - i)*h; p2[i] = 2*(decim - 1 - i)*h; } size = N*sizeof(MYFLT); if (p->win.auxp == NULL || p->win.size < size) { MYFLT x = FL(2.0)*PI_F/N; csound->AuxAlloc(csound, size, &p->win); for (i=0; i < N; i++) ((MYFLT *)p->win.auxp)[i] = FL(0.5) - FL(0.5)*COS((MYFLT)i*x); } p->cnt = 0; p->off = 0; p->N = N; p->hop = h; return OK; } static int hilbert_proc(CSOUND *csound, HILB *p){ uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; int n, nsmps = CS_KSMPS, off = p->off, decim = p->N/p->hop; int hopsize = p->hop, fftsize = p->N; int i,k,j, cnt = p->cnt; int *iframecnt = (int *) p->iframecnt.auxp; int *oframecnt = (int *) p->oframecnt.auxp; MYFLT *fftdata = (MYFLT *) p->fftdata.auxp; MYFLT *inframe = (MYFLT *) p->inframe.auxp; MYFLT *outframe = (MYFLT *) p->outframe.auxp; MYFLT *win = (MYFLT *) p->win.auxp; MYFLT **out = p->out; MYFLT *in = p->in; MYFLT scal = decim < 4 ? 1 : 16./(3*decim); if (UNLIKELY(early)) { nsmps -= early; for (j=0; j < 2; j++) { memset(&out[j][nsmps], '\0', early*sizeof(MYFLT)); } } if (UNLIKELY(offset)) { for (j=0; j < 2; j++) { memset(out[j], '\0', offset*sizeof(MYFLT)); } } for (n=offset; n < nsmps; n++, cnt++) { if (cnt == hopsize) { cnt = 0; for(i = j = 0; i < fftsize; i++, j+=2) { fftdata[j] = inframe[i+off]*win[i]; fftdata[j+1] = FL(0.0); } csound->ComplexFFT(csound, fftdata, fftsize); fftdata[0] *= 0.5; fftdata[1] *= 0.5; memset(fftdata+fftsize, 0, fftsize*sizeof(MYFLT)); csound->InverseComplexFFT(csound, fftdata, fftsize); for(i = j = 0; i < fftsize; i++, j+=2) { outframe[j+2*off] = fftdata[j]*win[i]*scal; outframe[j+1+2*off] = fftdata[j+1]*win[i]*scal; } off += fftsize; p->off = off = off%(fftsize*decim); } out[0][n] = out[1][n] = FL(0.0); for (i = 0; i < decim; i++) { inframe[iframecnt[i]+i*fftsize] = in[n]; iframecnt[i] = iframecnt[i] == fftsize-1 ? 0 : iframecnt[i]+1; k = 2*i*fftsize; out[0][n] += outframe[oframecnt[i]+k]; out[1][n] += outframe[oframecnt[i]+k+1]; oframecnt[i] = oframecnt[i] == 2*fftsize-2 ? 0 : oframecnt[i]+2; } } p->cnt = cnt; return OK; } typedef struct amfm { OPDS h; MYFLT *am, *fm; MYFLT *re, *im; double ph; double scal; } AMFM; int am_fm_init(CSOUND *csound, AMFM *p) { p->ph = FL(0.0); p->scal = csound->GetSr(csound)/(2*PI); return OK; } int am_fm(CSOUND *csound, AMFM *p){ uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; int n, nsmps = CS_KSMPS; double oph = p->ph, f, ph; MYFLT *fm = p->fm; MYFLT *am = p->am; MYFLT *re = p->re; MYFLT *im = p->im; MYFLT scal = p->scal; if (UNLIKELY(early)) { nsmps -= early; memset(&am[nsmps], '\0', early*sizeof(MYFLT)); memset(&fm[nsmps], '\0', early*sizeof(MYFLT)); } if (UNLIKELY(offset)) { memset(&am[nsmps], '\0', offset*sizeof(MYFLT)); memset(&fm[nsmps], '\0', offset*sizeof(MYFLT)); } for (n=offset; n < nsmps; n++) { am[n] = SQRT(re[n]*re[n] + im[n]*im[n]); ph = atan2(im[n], re[n]); f = ph - oph; oph = ph; if (f >= PI) f -= 2*PI; else if (f < -PI) f += 2*PI; fm[n] = f*scal; } p->ph = oph; return OK; } static OENTRY pvlock_localops[] = { {"mincer", sizeof(DATASPACE), 0, 5, "mm", "akkkkoo", (SUBR)sinit1, NULL,(SUBR)sprocess1 }, {"temposcal", sizeof(DATASPACE), 0, 5, "mm", "kkkkkooPOP", (SUBR)sinit2, NULL,(SUBR)sprocess2 }, {"filescal", sizeof(DATASPACE), 0, 5, "mm", "kkkSkooPOP", (SUBR)sinit3, NULL,(SUBR)sprocess3 }, {"hilbert2", sizeof(HILB), 0, 5, "aa", "aii", (SUBR) hilbert_init, NULL, (SUBR) hilbert_proc}, {"fmanal", sizeof(AMFM), 0, 5, "aa", "aa", (SUBR) am_fm_init, NULL, (SUBR) am_fm}, {"pvslock", sizeof(PVSLOCK), 0, 3, "f", "fk", (SUBR) pvslockset, (SUBR) pvslockproc}, }; LINKAGE_BUILTIN(pvlock_localops) csound-6.10.0/Opcodes/pvoc.c000066400000000000000000000073001321653344700156100ustar00rootroot00000000000000/* pvoc.c: This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "pvoc.h" int pvset(CSOUND *, void *), pvset_S(CSOUND *, void *), pvoc(CSOUND *, void *); int pvaddset(CSOUND *, void *), pvadd(CSOUND *, void *); int pvaddset_S(CSOUND *, void *); int tblesegset(CSOUND *, void *), ktableseg(CSOUND *, void *); int ktablexseg(CSOUND *, void *); int vpvset(CSOUND *, void *), vpvset_S(CSOUND *, void *), vpvoc(CSOUND *, void *); int pvreadset(CSOUND *, void *), pvread(CSOUND *, void *); int pvcrossset(CSOUND *, void *), pvcross(CSOUND *, void *); int pvbufreadset(CSOUND *, void *), pvbufread(CSOUND *, void *); int pvinterpset(CSOUND *, void *), pvinterp(CSOUND *, void *); int pvreadset_S(CSOUND *, void *); int pvcrossset_S(CSOUND *, void *); int pvbufreadset_S(CSOUND *, void *); int pvinterpset_S(CSOUND *, void *); #define S(x) sizeof(x) static OENTRY pvoc_localops[] = { { "pvoc", S(PVOC), 0, 5, "a", "kkSoooo", pvset_S, NULL, pvoc }, { "pvoc.i", S(PVOC), 0, 5, "a", "kkioooo", pvset, NULL, pvoc }, { "tableseg", S(TABLESEG), TR, 3, "", "iim", tblesegset, ktableseg, NULL }, { "ktableseg", S(TABLESEG), _QQ|TR, 3, "", "iim", tblesegset, ktableseg, NULL }, { "tablexseg", S(TABLESEG), TW, 3, "", "iin", tblesegset, ktablexseg, NULL }, { "vpvoc", S(VPVOC), TR, 5, "a", "kkSoo", vpvset_S, NULL, vpvoc }, { "vpvoc.i", S(VPVOC), TR, 5, "a", "kkioo", vpvset, NULL, vpvoc }, { "pvread", S(PVREAD), 0, 3, "kk", "kSi", pvreadset_S, pvread, NULL }, { "pvread.i", S(PVREAD), 0, 3, "kk", "kii", pvreadset, pvread, NULL }, { "pvcross", S(PVCROSS), 0, 5, "a", "kkSkko", pvcrossset_S, NULL, pvcross }, { "pvbufread", S(PVBUFREAD),0, 3, "", "kS", pvbufreadset_S, pvbufread, NULL}, { "pvinterp", S(PVINTERP), 0, 5, "a", "kkSkkkkkk", pvinterpset_S, NULL, pvinterp}, { "pvcross.i", S(PVCROSS), 0, 5, "a", "kkikko", pvcrossset, NULL, pvcross }, { "pvbufread.i", S(PVBUFREAD),0, 3, "", "ki", pvbufreadset, pvbufread, NULL}, { "pvinterp.i", S(PVINTERP), 0, 5, "a", "kkikkkkkk", pvinterpset, NULL, pvinterp}, { "pvadd", S(PVADD), 0, 5, "a", "kkSiiopooo", pvaddset_S, NULL, pvadd }, { "pvadd.i", S(PVADD), 0, 5, "a", "kkiiiopooo", pvaddset, NULL, pvadd } }; PVOC_GLOBALS *PVOC_AllocGlobals(CSOUND *csound) { PVOC_GLOBALS *p; #ifdef BETA csound->Message(csound, "calling alloc globals"); #endif if (UNLIKELY(csound->CreateGlobalVariable(csound, "pvocGlobals", sizeof(PVOC_GLOBALS)) != 0)){ csound->ErrorMsg(csound, Str("Error allocating PVOC globals")); return NULL; } p = (PVOC_GLOBALS*) csound->QueryGlobalVariable(csound, "pvocGlobals"); p->csound = csound; p->dsputil_sncTab = (MYFLT*) NULL; p->pvbufreadaddr = (PVBUFREAD*) NULL; p->tbladr = (TABLESEG*) NULL; return p; } LINKAGE_BUILTIN(pvoc_localops) csound-6.10.0/Opcodes/pvoc.h000066400000000000000000000030171321653344700156160ustar00rootroot00000000000000/* pvoc.h: This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef CSOUND_PVOC_H #define CSOUND_PVOC_H // #include "csdl.h" #include "csoundCore.h" #include "interlocks.h" typedef struct PVOC_GLOBALS_ PVOC_GLOBALS; #include "dsputil.h" #include "ugens8.h" #include "pvread.h" #include "pvinterp.h" #include "vpvoc.h" #include "pvadd.h" #include "pvocext.h" struct PVOC_GLOBALS_ { CSOUND *csound; MYFLT *dsputil_sncTab; PVBUFREAD *pvbufreadaddr; TABLESEG *tbladr; }; extern PVOC_GLOBALS *PVOC_AllocGlobals(CSOUND *csound); static inline PVOC_GLOBALS *PVOC_GetGlobals(CSOUND *csound) { PVOC_GLOBALS *p; p = (PVOC_GLOBALS*) csound->QueryGlobalVariable(csound, "pvocGlobals"); if (p == NULL) return PVOC_AllocGlobals(csound); return p; } #endif /* CSOUND_PVOC_H */ csound-6.10.0/Opcodes/pvocext.c000066400000000000000000000113361321653344700163350ustar00rootroot00000000000000/* pvocext.c: Copyright (C) 1998 Richard Karpen This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /******************************************/ /* The applications in this file were */ /* designed and coded by Richard Karpen */ /* University of Washington, Seattle 1998 */ /******************************************/ /* PVOCEXT.C */ #include "pvoc.h" #include #define minval(val1, val2) (val1 <= val2 ? val1 : val2) /* Spectral Extraction. Based on ideas from Tom Erbe's SoundHack */ void SpectralExtract( float *inp, /* pointer to input data */ float *pvcopy, int32 fsize, /* frame size we're working with */ int32 MaxFrame, int mode, MYFLT freqlim ) { int32 i, j, k; float *frm_1; int32 ampindex, freqindex; MYFLT freqTemp, freqframes[10]={0.0}, freqdiff=FL(0.0), ampscale; int32 framecurb; memcpy(pvcopy, inp, (fsize+2L)*MaxFrame*sizeof(float)); frm_1 = pvcopy; for (j=0; j<(fsize/2L + 1L); j++) { ampindex = j + j; freqindex = ampindex + 1L; for (i=0; i freqlim && freqdiff < freqlim * 2) { ampscale = (freqdiff - freqlim) / freqlim; frm_1[ampindex+((fsize+2L)*i)] *= ampscale; } else if (freqdiff <= freqlim) frm_1[ampindex+((fsize+2L)*i)] = FL(0.0); } else if (mode==2) { /* lets through just the stable-pitched parts */ if (freqdiff < freqlim) { ampscale = (freqlim - freqdiff) / freqlim; frm_1[ampindex+((fsize+2L)*i)] *= ampscale; } else frm_1[ampindex+((fsize+2L)*i)] = FL(0.0); } } } } MYFLT PvocMaxAmp( float *inp, /* pointer to input data */ int32 fsize, /* frame size we're working with */ int32 MaxFrame ) { int32 j, k; float *frm_0, *frmx; int32 ampindex; MYFLT MaxAmpInData = FL(0.0); frm_0 = inp; /* find max amp in the whole pvoc file */ for (j=0; j<(fsize/2L + 1L); ++j) { ampindex = j + j; for (k=0; k<=MaxFrame; k++) { frmx = frm_0 + ((fsize+2L)*k); MaxAmpInData = (frmx[ampindex] > MaxAmpInData ? frmx[ampindex] : MaxAmpInData); } } return(MaxAmpInData); } /*********************************************************************/ /* Different from Tom Erbe's Amplitude Gating. This one maps */ /* the normalised amplitude values from the analysis bins onto */ /* a user defined function. The amplitude values which are */ /* normalised to be between 0 and 1 are used as indeces into */ /* the table where and amplitude of 0 points at the beginning */ /* of the table and an amplitude of 1 points to the end of the table */ /*********************************************************************/ void PvAmpGate( MYFLT *buf, /* where to get our mag/pha pairs */ int32 fsize, /* frame size we're working with */ FUNC *ampfunc, MYFLT MaxAmpInData ) { int32 j; int32 ampindex, funclen, mapPoint; funclen = ampfunc->flen; for (j=0; j<(fsize/2L + 1L); ++j) { ampindex = j + j; /* use normalised amp as index into table for amp scaling */ mapPoint = (int32)((buf[ampindex] / MaxAmpInData) * funclen); buf[ampindex] *= *(ampfunc->ftable + mapPoint); } } csound-6.10.0/Opcodes/pvocext.h000066400000000000000000000022211321653344700163330ustar00rootroot00000000000000/* pvocext.h: Copyright (C) 1998 Richard Karpen This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Spectral Extraction and Amplitude Gating functions */ /* By Richard Karpen June, 1998 */ /* Based on ideas from Tom Erbe's SoundHack */ /* Predeclare Functions */ void SpectralExtract(float *, float *, int32, int32, int, MYFLT); MYFLT PvocMaxAmp(float *, int32, int32); void PvAmpGate(MYFLT *, int32, FUNC *, MYFLT); csound-6.10.0/Opcodes/pvread.c000066400000000000000000000113741321653344700161300ustar00rootroot00000000000000/* pvread.c: Copyright (C) 1992, 2000 Richard Karpen, Richard Dobson This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /**************************************************************/ /***********pvread ********************************************/ /*** By Richard Karpen - July-October 1992*********************/ /**************************************************************/ #include "pvoc.h" #include /*RWD 10:9:2000 read pvocex file format */ #include "pvfileio.h" static int pvocex_loadfile(CSOUND *, const char *fname, PVREAD *p); #define WLN 1 /* time window is WLN*2*ksmps long */ #define OPWLEN (2*WLN*ksmps) /* manifest used for final time wdw */ static void FetchInOne( float *inp, /* pointer to input data */ MYFLT *buf, /* where to put our nice mag/pha pairs */ int32 fsize, /* frame size we're working with */ MYFLT pos, /* fractional frame we want */ int32 mybin) { float *frame0; float *frame1; int32 base; MYFLT frac; int32 twmybin = mybin+mybin; /* Always used thus */ /***** WITHOUT INFO ON WHERE LAST FRAME IS, MAY 'INTERP' BEYOND IT ****/ base = (int32)pos; /* index of basis frame of interpolation */ frac = ((MYFLT)(pos - (MYFLT)base)); /* & how close to get to next */ frame0 = inp + ((int32) fsize + 2L) * base + twmybin; frame1 = frame0 + ((int32) fsize + 2L); /* addresses of both frames */ if (frac != 0.0) { /* must have 2 cases to avoid possible segmentation */ /* violations and failed computes, else may interp */ /* beyond valid data */ buf[0] = frame0[0] + frac * (frame1[0] - frame0[0]); buf[1] = frame0[1] + frac * (frame1[1] - frame0[1]); } else { /* frac is 0.0 i.e. just copy the source frame */ buf[0] = frame0[0]; buf[1] = frame0[1]; } } int pvreadset_(CSOUND *csound, PVREAD *p, int stringname) { char pvfilnam[256]; if (stringname==0){ if (csound->ISSTRCOD(*p->ifilno)) strncpy(pvfilnam,get_arg_string(csound, *p->ifilno), MAXNAME-1); else csound->strarg2name(csound, pvfilnam, p->ifilno, "pvoc.",0); } else strncpy(pvfilnam, ((STRINGDAT *)p->ifilno)->data, MAXNAME-1); if (pvocex_loadfile(csound, pvfilnam, p) == OK) { p->prFlg = 1; p->mybin = MYFLT2LRND(*p->ibin); return OK; } return NOTOK; } int pvreadset(CSOUND *csound, PVREAD *p){ return pvreadset_(csound,p,0); } int pvreadset_S(CSOUND *csound, PVREAD *p){ return pvreadset_(csound,p,1); } int pvread(CSOUND *csound, PVREAD *p) { MYFLT frIndx; MYFLT buf[2]; int size = pvfrsiz(p); if (UNLIKELY((frIndx = *p->ktimpnt * p->frPrtim) < 0)) goto err1; if (frIndx > p->maxFr) { /* not past last one */ frIndx = (MYFLT)p->maxFr; if (p->prFlg) { p->prFlg = 0; /* false */ csound->Warning(csound, Str("PVOC ktimpnt truncated to last frame")); } } FetchInOne(p->frPtr, &(buf[0]), size, frIndx, p->mybin); *p->kfreq = buf[1]; *p->kamp = buf[0]; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("PVOC timpnt < 0")); } static int pvocex_loadfile(CSOUND *csound, const char *fname, PVREAD *p) { PVOCEX_MEMFILE pp; if (UNLIKELY(csound->PVOCEX_LoadFile(csound, fname, &pp) != 0)) { return csound->InitError(csound, Str("PVREAD cannot load %s"), fname); } /* have to reject m/c files for now, until opcodes upgraded */ if (UNLIKELY(pp.chans > 1)) { return csound->InitError(csound, Str("pvoc-ex file %s is not mono"), fname); } /* ignore the window spec until we can use it! */ p->frSiz = pp.fftsize; p->frPtr = (float*) pp.data; p->baseFr = 0; /* point to first data frame */ p->maxFr = pp.nframes - 1; p->asr = pp.srate; /* highest possible frame index */ /* factor by which to mult expand phase diffs (ratio of samp spacings) */ p->frPrtim = CS_ESR / ((MYFLT) pp.overlap); return OK; } csound-6.10.0/Opcodes/pvread.h000066400000000000000000000022771321653344700161370ustar00rootroot00000000000000/* pvread.h: Copyright (C) 1992 Richard Karpen This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* PVREAD.H */ typedef struct { OPDS h; MYFLT *kfreq, *kamp, *ktimpnt, *ifilno, *ibin; int32 kcnt; int32 baseFr, maxFr, frSiz, prFlg; /* base Frame (in frameData0) and maximum frame on file, ptr to fr, size */ MYFLT frPrtim, asr; float *frPtr; int32 mybin; } PVREAD; csound-6.10.0/Opcodes/pvs_ops.c000066400000000000000000000025511321653344700163350ustar00rootroot00000000000000/* pvs_ops.c: This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "pvs_ops.h" /* PUBLIC int csoundModuleCreate(CSOUND *csound) { (void) csound; return 0; } */ int pvsopc_ModuleInit(CSOUND *csound) { int err = 0; err |= ifd_init_(csound); err |= partials_init_(csound); err |= psynth_init_(csound); err |= pvsbasic_init_(csound); err |= pvscent_init_(csound); err |= pvsdemix_init_(csound); err |= pvsband_init_(csound); return (err ? CSOUND_ERROR : CSOUND_SUCCESS); } /* PUBLIC int csoundModuleInfo(void) { return ((CS_APIVERSION << 16) + (CS_APISUBVER << 8) + (int) sizeof(MYFLT)); } */ csound-6.10.0/Opcodes/pvs_ops.h000066400000000000000000000022651321653344700163440ustar00rootroot00000000000000/* pvs_ops.h: This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef CSOUND_PVS_OPS_H #define CSOUND_PVS_OPS_H /* #include "csdl.h" */ #include "csoundCore.h" #include "interlocks.h" extern int ifd_init_(CSOUND *); extern int partials_init_(CSOUND *); extern int psynth_init_(CSOUND *); extern int pvsbasic_init_(CSOUND *); extern int pvscent_init_(CSOUND *); extern int pvsdemix_init_(CSOUND *); extern int pvsband_init_(CSOUND *); #endif /* CSOUND_PVS_OPS_H */ csound-6.10.0/Opcodes/pvsband.c000066400000000000000000000240551321653344700163040ustar00rootroot00000000000000/* pvsband.c: bandpass filter transformation of streaming PV signals (c) John ffitch, 2007 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "pvs_ops.h" #include "pstream.h" typedef struct { OPDS h; PVSDAT *fout; PVSDAT *fin; MYFLT *klowcut; MYFLT *klowbnd; MYFLT *khigbnd; MYFLT *khigcut; MYFLT *fade; MYFLT lastframe; } PVSBAND; static int pvsbandinit(CSOUND *csound, PVSBAND *p) { int N = p->fin->N; if (UNLIKELY(p->fin == p->fout)) csound->Warning(csound, Str("Unsafe to have same fsig as in and out")); if (p->fin->sliding) { if (p->fout->frame.auxp==NULL || CS_KSMPS*(N+2)*sizeof(MYFLT) > (unsigned int)p->fout->frame.size) csound->AuxAlloc(csound, CS_KSMPS*(N+2)*sizeof(MYFLT),&p->fout->frame); else memset(p->fout->frame.auxp, 0, CS_KSMPS*(N+2)*sizeof(MYFLT)); } else { if (p->fout->frame.auxp == NULL || p->fout->frame.size < (N+2)*sizeof(float)) /* RWD MUST be 32bit */ csound->AuxAlloc(csound, (N+2)*sizeof(float), &p->fout->frame); else memset(p->fout->frame.auxp, 0, (N+2)*sizeof(float)); } p->fout->N = N; p->fout->overlap = p->fin->overlap; p->fout->winsize = p->fin->winsize; p->fout->wintype = p->fin->wintype; p->fout->format = p->fin->format; p->fout->framecount = 1; p->lastframe = 0; p->fout->sliding = p->fin->sliding; p->fout->NB = p->fin->NB; return OK; } static int pvsband(CSOUND *csound, PVSBAND *p) { int i, N = p->fin->N; MYFLT lowcut = *p->klowcut; MYFLT lowbnd = *p->klowbnd; MYFLT higbnd = *p->khigbnd; MYFLT higcut = *p->khigcut; float *fin = (float *) p->fin->frame.auxp; float *fout = (float *) p->fout->frame.auxp; MYFLT fade = *p->fade; MYFLT opef = FL(1.0) - EXP(fade); if (UNLIKELY(fout == NULL)) goto err1; if (lowcutfin->sliding) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int NB = p->fout->NB; if (UNLIKELY(early)) nsmps -= early; for (n=offset; nfin->frame.auxp + n*NB; CMPLX *fout = (CMPLX *) p->fout->frame.auxp + n*NB; if (IS_ASIG_ARG(p->klowcut)) lowcut = p->klowcut[n], change = 1; if (IS_ASIG_ARG(p->klowbnd)) lowbnd = p->klowbnd[n], change = 1; if (IS_ASIG_ARG(p->khigbnd)) higbnd = p->khigbnd[n], change = 1; if (IS_ASIG_ARG(p->khigcut)) higcut = p->khigcut[n], change = 1; if (change) { if (lowcuthigcut) { /* outside band */ fout[i].re = FL(0.0); fout[i].im = -FL(1.0); } else if (afrq > lowbnd && afrq lowcut && afrq < lowbnd) { /* ramp up */ if (fade != FL(0.0)) { fout[i].re = fin[i].re * (FL(1.0) - EXP(fade*(afrq-lowcut)/(lowbnd-lowcut)))/opef; } else fout[i].re = fin[i].re * (afrq - lowcut)/(lowbnd - lowcut); fout[i].im = frq; } else { /* ramp down */ if (fade != FL(0.0)) { fout[i].re = fin[i].re * (FL(1.0) - EXP(fade*(higcut-afrq)/(higcut-higbnd)))/opef; } else fout[i].re = fin[i].re * (higcut - afrq)/(higcut - higbnd); fout[i].im = frq; } } } return OK; } if (p->lastframe < p->fin->framecount) { for (i = 0; i < N; i += 2) { MYFLT frq = fin[i+1]; MYFLT afrq = (frqhigcut) { fout[i] = FL(0.0); fout[i+1] = -FL(1.0); } else if (afrq > lowbnd && afrq lowcut && afrq < lowbnd) { if (fade != FL(0.0)) fout[i] = fin[i] * (1.0f - expf(fade*(afrq-lowcut)/(lowbnd-lowcut)))/opef; else fout[i] = fin[i] * (frq - lowcut)/(lowbnd - lowcut); fout[i+1] = frq; } else { if (fade != FL(0.0)) fout[i] = fin[i] * (1.0f - expf(fade*(higcut-afrq)/(higcut-higbnd)))/opef; else fout[i] = fin[i] * (higcut - frq)/(higcut - higbnd); fout[i+1] = frq; } } p->fout->framecount = p->lastframe = p->fin->framecount; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("pvsband: not initialised")); } static int pvsbrej(CSOUND *csound, PVSBAND *p) { int i, N = p->fin->N; MYFLT lowcut = *p->klowcut; MYFLT lowbnd = *p->klowbnd; MYFLT higbnd = *p->khigbnd; MYFLT higcut = *p->khigcut; float *fin = (float *) p->fin->frame.auxp; float *fout = (float *) p->fout->frame.auxp; MYFLT fade = *p->fade; MYFLT opef = FL(1.0) - EXP(fade); if (UNLIKELY(fout == NULL)) goto err1; if (lowcutfin->sliding) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int NB = p->fout->NB; if (UNLIKELY(early)) nsmps -= early; for (n=offset; nfin->frame.auxp + n*NB; CMPLX *fout = (CMPLX *) p->fout->frame.auxp + n*NB; if (IS_ASIG_ARG(p->klowcut)) lowcut = p->klowcut[n], change = 1; if (IS_ASIG_ARG(p->klowbnd)) lowbnd = p->klowbnd[n], change = 1; if (IS_ASIG_ARG(p->khigbnd)) higbnd = p->khigbnd[n], change = 1; if (IS_ASIG_ARG(p->khigcut)) higcut = p->khigcut[n], change = 1; if (change) { if (lowcuthigcut) { fout[i] = fin[i]; } else if (afrq > lowbnd && afrq lowcut && afrq < lowbnd) { if (fade) fout[i].re = fin[i].re * (FL(1.0) - EXP(fade*(afrq-lowcut)/(lowbnd-lowcut)))/opef; else fout[i].re = fin[i].re * (lowbnd - afrq)/(lowbnd - lowcut); fout[i].im = frq; } else { if (fade) fout[i].re = fin[i].re * (FL(1.0) - EXP(fade*(afrq-higbnd)/(higcut-higbnd)))/opef; else fout[i].re = fin[i].re * (afrq - higbnd)/(higcut - higbnd); fout[i].im = frq; } } } return OK; } if (p->lastframe < p->fin->framecount) { for (i = 0; i < N; i += 2) { MYFLT frq = fin[i+1]; MYFLT afrq = (frqhigcut) { fout[i] = fin[i]; fout[i+1] = fin[i+1]; } else if (afrq > lowbnd && afrq lowcut && afrq < lowbnd) { if (fade != FL(0.0)) fout[i] = fin[i] * (1.0f - expf(fade*(lowbnd - afrq)/(lowbnd - lowcut)))/opef; else fout[i] = fin[i] * (lowbnd - afrq)/(lowbnd - lowcut); fout[i+1] = frq; } else { if (fade != FL(0.0)) fout[i] = fin[i] * (1.0f - expf(fade*(afrq - higbnd)/(higcut - higbnd)))/opef; else fout[i] = fin[i] * (afrq - higbnd)/(higcut - higbnd); fout[i+1] = frq; } } p->fout->framecount = p->lastframe = p->fin->framecount; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("pvsband: not initialised")); } static OENTRY localops[] = { {"pvsbandp", sizeof(PVSBAND), 0, 3, "f", "fxxxxO", (SUBR) pvsbandinit, (SUBR) pvsband, (SUBR) NULL }, {"pvsbandr", sizeof(PVSBAND), 0, 3, "f", "fxxxxO", (SUBR) pvsbandinit, (SUBR) pvsbrej, (SUBR) NULL } }; int pvsband_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/pvsbasic.c000066400000000000000000002333641321653344700164660ustar00rootroot00000000000000/* pvsbasic.c: basic opcodes for transformation of streaming PV signals (c) Victor Lazzarini, 2004 John ffitch, 2007 (slifing form) This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* pvsmix */ #include "pvs_ops.h" #include "pvsbasic.h" #include "pvfileio.h" #include #define MAXOUTS 16 static int fsigs_equal(const PVSDAT *f1, const PVSDAT *f2); typedef struct _pvsgain { OPDS h; PVSDAT *fout; PVSDAT *fa; MYFLT *kgain; uint32 lastframe; } PVSGAIN; static int pvsgainset(CSOUND *csound, PVSGAIN *p){ int32 N = p->fa->N; p->fout->sliding = 0; if (p->fa->sliding) { if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(MYFLT) * CS_KSMPS * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT) * CS_KSMPS, &p->fout->frame); p->fout->NB = p->fa->NB; p->fout->sliding = 1; } else if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(float) * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame); p->fout->N = N; p->fout->overlap = p->fa->overlap; p->fout->winsize = p->fa->winsize; p->fout->wintype = p->fa->wintype; p->fout->format = p->fa->format; p->fout->framecount = 1; p->lastframe = 0; if (UNLIKELY(!(p->fout->format == PVS_AMP_FREQ) || (p->fout->format == PVS_AMP_PHASE))) return csound->InitError(csound, Str("pvsgain: signal format " "must be amp-phase or amp-freq.")); return OK; } static int pvsgain(CSOUND *csound, PVSGAIN *p) { int i; int32 framesize; float *fout, *fa; MYFLT gain = *p->kgain; if (p->fa->sliding) { CMPLX * fout, *fa; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int NB = p->fa->NB; for (n=0; nfout->frame.auxp +NB*n; for (i = 0; i < NB; i++) fout[i].re = fout[i].im = FL(0.0); } for (n=nsmps-early; nfout->frame.auxp +NB*n; for (i = 0; i < NB; i++) fout[i].re = fout[i].im = FL(0.0); } nsmps -= early; for (n=offset; nfout->frame.auxp +NB*n; fa = (CMPLX*) p->fa->frame.auxp +NB*n; for (i = 0; i < NB; i++) { fout[i].re = fa[i].re*gain; fout[i].im = fa[i].im; } } return OK; } fout = (float *) p->fout->frame.auxp; fa = (float *) p->fa->frame.auxp; framesize = p->fa->N + 2; if (p->lastframe < p->fa->framecount) { for (i = 0; i < framesize; i += 2){ fout[i] = fa[i]*gain; fout[i+1] = fa[i+1]; } p->fout->framecount = p->fa->framecount; p->lastframe = p->fout->framecount; } return OK; } static int pvsinit(CSOUND *csound, PVSINI *p) { int i; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; float *bframe; int32 N = (int32) *p->framesize; p->fout->N = N; p->fout->overlap = (int32)(*p->olap ? *p->olap : N/4); p->fout->winsize = (int32)(*p->winsize ? *p->winsize : N); p->fout->wintype = (int32) *p->wintype; p->fout->format = (int32) *p->format; p->fout->framecount = 1; p->fout->sliding = 0; if (p->fout->overlap < (int)nsmps || p->fout->overlap <=10) { int NB = 1+N/2; MYFLT *bframe; p->fout->NB = NB; if (p->fout->frame.auxp == NULL || p->fout->frame.size * CS_KSMPS < sizeof(float) * (N + 2)) csound->AuxAlloc(csound, (N + 2) * nsmps * sizeof(float), &p->fout->frame); p->fout->sliding = 1; bframe = (MYFLT *) p->fout->frame.auxp; for (n=0; nnsmps-early ? FL(0.0) :(i >>1) * N * csound->onedsr); } } else { if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(float) * (N + 2)) { csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame); } bframe = (float *) p->fout->frame.auxp; for (i = 0; i < N + 2; i += 2) { //bframe[i] = 0.0f; bframe[i + 1] = (i >>1) * N * csound->onedsr; } } p->lastframe = 0; return OK; } typedef struct { OPDS h; PVSDAT *fin; MYFLT *file; int pvfile; AUXCH frame; AUXCH buf; AUXCH dframe; CSOUND *csound; void *cb; int async; #ifndef __EMSCRIPTEN__ void* thread; #endif int N; uint32 lastframe; }PVSFWRITE; uintptr_t pvs_io_thread(void *pp); static int pvsfwrite_destroy(CSOUND *csound, void *pp) { PVSFWRITE *p = (PVSFWRITE *) pp; #ifndef __EMSCRIPTEN__ if (p->async){ p->async = 0; // PTHREAD: change //pthread_join(p->thread, NULL); csoundJoinThread (p->thread); csound->DestroyCircularBuffer(csound, p->cb); } #endif csound->PVOC_CloseFile(csound,p->pvfile); return OK; } static int pvsfwriteset_(CSOUND *csound, PVSFWRITE *p, int stringname) { int N; char fname[MAXNAME]; if (stringname==0) { if (csound->ISSTRCOD(*p->file)) strncpy(fname,get_arg_string(csound, *p->file), MAXNAME-1); else csound->strarg2name(csound, fname, p->file, "pvoc.",0); } else strncpy(fname, ((STRINGDAT *)p->file)->data, MAXNAME-1); if (UNLIKELY(p->fin->sliding)) return csound->InitError(csound,Str("SDFT Not implemented in this case yet")); p->pvfile= -1; N = p->N = p->fin->N; if ((p->pvfile = csound->PVOC_CreateFile(csound, fname, p->fin->N, p->fin->overlap, 1, p->fin->format, CS_ESR, STYPE_16, p->fin->wintype, 0.0f, NULL, p->fin->winsize)) == -1) return csound->InitError(csound, Str("pvsfwrite: could not open file %s\n"), fname); #ifndef __EMSCRIPTEN__ if (csound->realtime_audio_flag) { int bufframes = 16; p->csound = csound; if (p->frame.auxp == NULL || p->frame.size < sizeof(MYFLT) * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT), &p->frame); if (p->buf.auxp == NULL || p->buf.size < sizeof(MYFLT) * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT), &p->buf); if (p->dframe.auxp == NULL || p->dframe.size < sizeof(float) * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->dframe); p->cb = csound->CreateCircularBuffer(csound, (N+2)*sizeof(float)*bufframes, sizeof(MYFLT)); // PTHREAD: change //pthread_create(&p->thread, NULL, pvs_io_thread, (void *) p); p->thread = csoundCreateThread (pvs_io_thread, (void*)p); p->async = 1; } else #endif { if (p->frame.auxp == NULL || p->frame.size < sizeof(float) * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->frame); p->async = 0; } csound->RegisterDeinitCallback(csound, p, pvsfwrite_destroy); p->lastframe = 0; return OK; } static int pvsfwriteset(CSOUND *csound, PVSFWRITE *p){ return pvsfwriteset_(csound,p,0); } static int pvsfwriteset_S(CSOUND *csound, PVSFWRITE *p){ return pvsfwriteset_(csound,p,1); } uintptr_t pvs_io_thread(void *pp){ PVSFWRITE *p = (PVSFWRITE *) pp; CSOUND *csound = p->csound; MYFLT *buf = (MYFLT *) p->buf.auxp; float *frame = (float *) p->dframe.auxp; int *on = &p->async; int lc,n, N2=p->N+2; _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); while (*on) { lc = csound->ReadCircularBuffer(csound, p->cb, buf, N2); if (lc) { for (n=0; n < N2; n++) frame[n] = (float) buf[n]; csound->PVOC_PutFrames(csound, p->pvfile, frame, 1); } } return (uintptr_t)0; } static int pvsfwrite(CSOUND *csound, PVSFWRITE *p) { float *fin = p->fin->frame.auxp; if (p->lastframe < p->fin->framecount) { int32 framesize = p->fin->N+2,i; if (p->async == 0) { float _0dbfs = (float) csound->Get0dBFS(csound); float *fout = p->frame.auxp; for (i=0;i < framesize; i+=2) { fout[i] = fin[i]/_0dbfs; fout[i+1] = fin[i+1]; } if (UNLIKELY(!csound->PVOC_PutFrames(csound, p->pvfile, fout, 1))) return csound->PerfError(csound, p->h.insdshead, Str("pvsfwrite: could not write data\n")); } else { MYFLT *fout = p->frame.auxp; MYFLT _0dbfs = csound->Get0dBFS(csound); for (i=0;i < framesize; i+=2){ fout[i] = (MYFLT) fin[i]/_0dbfs; fout[i+1] = (MYFLT) fin[i+1]; } csound->WriteCircularBuffer(csound, p->cb, fout, framesize); } p->lastframe = p->fin->framecount; } return OK; } typedef struct _pvsdiskin { OPDS h; PVSDAT *fout; MYFLT *file; MYFLT *kspeed; MYFLT *kgain; MYFLT *ioff; MYFLT *ichn; MYFLT *interp; double pos; uint32 oldpos; int chans, chn; int pvfile; int scnt; uint32 flen; AUXCH buffer; } pvsdiskin; #define FSIGBUFRAMES 2 static int pvsdiskinset_(CSOUND *csound, pvsdiskin *p, int stringname) { int N; WAVEFORMATEX fmt; PVOCDATA pvdata; char fname[MAXNAME]; if (stringname==0){ if (csound->ISSTRCOD(*p->file)) strncpy(fname,get_arg_string(csound, *p->file), MAXNAME-1); else csound->strarg2name(csound, fname, p->file, "pvoc.",0); } else strncpy(fname, ((STRINGDAT *)p->file)->data, MAXNAME-1); if (UNLIKELY(p->fout->sliding)) return csound->InitError(csound, Str("SDFT Not implemented in this case yet")); if ((p->pvfile = csound->PVOC_OpenFile(csound, fname, &pvdata, &fmt)) < 0) return csound->InitError(csound, Str("pvsdiskin: could not open file %s\n"), fname); N = (pvdata.nAnalysisBins-1)*2; p->chans = fmt.nChannels; if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(float) * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame); if (p->buffer.auxp == NULL || p->buffer.size < sizeof(float) * (N + 2) * FSIGBUFRAMES * p->chans) csound->AuxAlloc(csound, (N + 2) * sizeof(float) * FSIGBUFRAMES * p->chans, &p->buffer); p->flen = csound->PVOC_FrameCount(csound, p->pvfile) - 1; p->fout->N = N; p->fout->overlap = pvdata.dwOverlap; p->fout->winsize = pvdata.dwWinlen; switch ((pv_wtype) pvdata.wWindowType) { case PVOC_HAMMING: p->fout->wintype = PVS_WIN_HAMMING; break; case PVOC_HANN: p->fout->wintype = PVS_WIN_HANN; break; case PVOC_KAISER: p->fout->wintype = PVS_WIN_KAISER; break; default: p->fout->wintype = PVS_WIN_HAMMING; break; } p->fout->format = pvdata.wAnalFormat; p->fout->framecount = 1; p->scnt = p->fout->overlap; p->pos = *p->ioff * CS_ESR/N; p->oldpos = -1; p->chn = (int) (*p->ichn <= p->chans ? *p->ichn : p->chans) -1; if (p->chn < 0) p->chn = 0; return OK; } static int pvsdiskinset(CSOUND *csound, pvsdiskin *p){ return pvsdiskinset_(csound, p, 0); } static int pvsdiskinset_S(CSOUND *csound, pvsdiskin *p){ return pvsdiskinset_(csound, p, 1); } static int pvsdiskinproc(CSOUND *csound, pvsdiskin *p) { int overlap = p->fout->overlap, i; unsigned int posi; double pos = p->pos; int32 N = p->fout->N; MYFLT frac; float *fout = (float *) p->fout->frame.auxp; float *buffer = (float *) p->buffer.auxp; float *frame1 = buffer + (N+2)*p->chn; float *frame2 = buffer + (N+2)*(p->chans + p->chn); float amp = (float) (*p->kgain * csound->e0dbfs); if (p->scnt >= overlap) { posi = (unsigned int) pos; if (posi != p->oldpos) { /* read new frame PVOC_Rewind() is now PVOC_fseek() adapted to work as fseek(), using the last argument as offset */ while(pos >= p->flen) pos -= p->flen; while(pos < 0) pos += p->flen; csound->PVOC_fseek(csound,p->pvfile, pos); (void)csound->PVOC_GetFrames(csound, p->pvfile, buffer, 2*p->chans); p->oldpos = posi = (unsigned int)pos; } if (*p->interp) { /* interpolate */ frac = pos - posi; for (i=0; i < N+2; i+=2) { fout[i] = amp*(frame1[i] + frac*(frame2[i] - frame1[i])); fout[i+1] = frame1[i+1] + frac*(frame2[i+1] - frame1[i+1]); } } else /* do not */ for (i=0; i < N+2; i+=2) { fout[i] = amp*(frame1[i]); fout[i+1] = frame1[i+1]; } p->pos += (*p->kspeed * p->chans); p->scnt -= overlap; p->fout->framecount++; } p->scnt += CS_KSMPS; return OK; } typedef struct _pvst { OPDS h; PVSDAT *fout[MAXOUTS]; MYFLT *ktime; MYFLT *kamp; MYFLT *kpitch; MYFLT *knum; MYFLT *konset; MYFLT *wrap, *offset; MYFLT *fftsize, *hsize, *dbthresh; uint32 scnt; int tscale; MYFLT accum; double pos; float factor, fund, rotfac, scale; AUXCH bwin[MAXOUTS]; AUXCH fwin[MAXOUTS], nwin[MAXOUTS]; AUXCH win; int nchans; int init; void *fwdsetup; } PVST; int pvstanalset(CSOUND *csound, PVST *p) { int i, N, hsize, nChannels; N = (*p->fftsize > 0 ? *p->fftsize : 2048); hsize = (*p->hsize > 0 ? *p->hsize : 512); p->init = 0; nChannels = csound->GetOutputArgCnt(p); if (UNLIKELY(nChannels < 1 || nChannels > MAXOUTS)) return csound->InitError(csound, Str("invalid number of output arguments")); p->nchans = nChannels; for (i=0; i < p->nchans; i++) { p->fout[i]->N = N; p->fout[i]->overlap = hsize; p->fout[i]->wintype = PVS_WIN_HANN; p->fout[i]->winsize = N; p->fout[i]->framecount = 1; if (p->fout[i]->frame.auxp == NULL || p->fout[i]->frame.size < sizeof(float) * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout[i]->frame); else memset(p->fout[i]->frame.auxp, 0, sizeof(float)*(N+2)); if (p->bwin[i].auxp == NULL || p->bwin[i].size < sizeof(MYFLT) * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT), &p->bwin[i]); else memset(p->bwin[i].auxp, 0, p->bwin[i].size); if (p->fwin[i].auxp == NULL || p->fwin[i].size < sizeof(MYFLT) * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT), &p->fwin[i]); else memset(p->fwin[i].auxp, 0, sizeof(MYFLT)*(N+2)); if (p->nwin[i].auxp == NULL || p->nwin[i].size < sizeof(MYFLT) * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT), &p->nwin[i]); else memset(p->nwin[i].auxp, 0, sizeof(MYFLT)*(N+2)); } if (p->win.auxp == NULL || p->win.size < sizeof(MYFLT) * (N)) csound->AuxAlloc(csound, (N) * sizeof(MYFLT), &p->win); p->scale = 0.0f; for (i=0; i < N; i++) p->scale += (((MYFLT *)p->win.auxp)[i] = 0.5 - 0.5*cos(i*2*PI/N)); for (i=0; i < N; i++) ((MYFLT *)p->win.auxp)[i] *= 2./p->scale; p->rotfac = hsize*TWOPI/N; p->factor = CS_ESR/(hsize*TWOPI); p->fund = CS_ESR/N; p->scnt = p->fout[0]->overlap; p->tscale = 1; p->pos = *p->offset*CS_ESR; //printf("off: %f\n", *p->offset); p->accum = 0.0; p->fwdsetup = csound->RealFFT2Setup(csound,N,FFT_FWD); return OK; } int pvstanal(CSOUND *csound, PVST *p) { int hsize = p->fout[0]->overlap, i, k; unsigned int j; uint32_t sizefrs, nchans = p->nchans; int32 N = p->fout[0]->N, post, size; double frac, spos = p->pos, pos; MYFLT *tab, dbtresh = *p->dbthresh; FUNC *ft; float *fout; MYFLT *bwin, *fwin, *nwin, *win = (MYFLT *) p->win.auxp; float amp = (float) (*p->kamp), factor = p->factor, fund = p->fund; float pitch = (float) (*p->kpitch), rotfac = p->rotfac; MYFLT time = *p->ktime; float tmp_real, tmp_im, powrat; if ((int)p->scnt >= hsize) { /* audio samples are stored in a function table */ ft = csound->FTnp2Find(csound,p->knum); if (ft == NULL){ csound->PerfError(csound, p->h.insdshead, Str("could not find table number %d\n"), (int) *p->knum); return NOTOK; } tab = ft->ftable; size = ft->flen; /* nchans = ft->nchanls; */ /* spos is the reading position in samples, hsize is hopsize, time is current read rate esr is sampling rate */ if (UNLIKELY(ft->nchanls != (int32)nchans)) return csound->PerfError(csound, p->h.insdshead, Str("number of output arguments " "inconsistent with number of " "sound file channels")); sizefrs = size/nchans; if (!*p->wrap && spos == 0.0) spos += hsize; if (!*p->wrap && spos >= sizefrs) { for (j=0; j < nchans; j++) { memset(p->fout[j]->frame.auxp, 0, sizeof(float)*(N+2)); p->fout[j]->framecount++; } goto end; } while (spos >= sizefrs) spos -= sizefrs; while (spos < hsize) spos += (sizefrs + hsize); pos = spos; for (j=0; j < nchans; j++) { fout = (float *) p->fout[j]->frame.auxp; bwin = (MYFLT *) p->bwin[j].auxp; fwin = (MYFLT *) p->fwin[j].auxp; nwin = (MYFLT *) p->nwin[j].auxp; /* this loop fills two frames/windows with samples from table, reading is linearly-interpolated, frames are separated by 1 hopsize */ for (i=0; i < N; i++) { /* front window, fwin */ MYFLT in; post = (int) pos; frac = pos - post; post *= nchans; post += j; while (post >= size ) post -= size; while (post < 0) post += size; in = tab[post] + frac*(tab[post+nchans] - tab[post]); fwin[i] = amp * in * win[i]; /* window it */ /* back windo, bwin */ post = (int) (pos - hsize*pitch); post *= nchans; post += j; while (post >= size ) post -= size; while (post < 0) post += size; in = tab[post] + frac*(tab[post+nchans] - tab[post]); bwin[i] = in * win[i]; /* window it */ if (*p->konset){ post = (int) pos + hsize; post *= nchans; post += j; while (post >= size ) post -= size; while (post < 0) post += size; in = tab[post]; nwin[i] = amp * in * win[i]; } /* increment read pos according to pitch transposition */ pos += pitch; } /* take the FFT of both frames re-order Nyquist bin from pos 1 to N */ csound->RealFFT2(csound, p->fwdsetup, bwin); csound->RealFFT2(csound, p->fwdsetup, fwin); if (*p->konset){ csound->RealFFT2(csound,p->fwdsetup, nwin); tmp_real = tmp_im = (MYFLT) 1e-20; for (i=2; i < N; i++) { tmp_real += nwin[i]*nwin[i] + nwin[i+1]*nwin[i+1]; tmp_im += fwin[i]*fwin[i] + fwin[i+1]*fwin[i+1]; } powrat = FL(20.0)*LOG10(tmp_real/tmp_im); if (powrat > dbtresh) p->tscale=0; } else p->tscale=1; fwin[N+1] = fwin[1] = 0.0; for (i=2,k=1; i < N; i+=2, k++) { float bph, fph, dph; /* freqs */ bph = atan2(bwin[i+1],bwin[i]); fph = atan2(fwin[i+1],fwin[i]); /* pdiff, compensate for rotation */ dph = fph - bph - rotfac*k; while(dph > PI) dph -= TWOPI; while(dph < -PI) dph += TWOPI; fout[i+1] = dph*factor + k*fund; /* mags */ fout[i] = sqrt(fwin[i]*fwin[i] + fwin[i+1]*fwin[i+1]); } p->fout[j]->framecount++; } if (time < 0 || time >= 1 || !*p->konset) { spos += hsize*time; } else if (p->tscale) { spos += hsize*(time/(1+p->accum)); p->accum=0.0; } else { spos += hsize; p->accum++; p->tscale = 1; } end: p->scnt -= hsize; p->pos = spos; } p->scnt += CS_KSMPS; return OK; } static int pvsfreezeset(CSOUND *csound, PVSFREEZE *p) { int32 N = p->fin->N; if (UNLIKELY(p->fin == p->fout)) csound->Warning(csound, Str("Unsafe to have same fsig as in and out")); p->fout->N = N; p->fout->overlap = p->fin->overlap; p->fout->winsize = p->fin->winsize; p->fout->wintype = p->fin->wintype; p->fout->format = p->fin->format; p->fout->framecount = 1; p->lastframe = 0; p->fout->NB = (N/2)+1; p->fout->sliding = p->fin->sliding; if (p->fin->sliding) { uint32_t nsmps = CS_KSMPS; if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(MYFLT) * (N + 2) * nsmps) csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT) * nsmps, &p->fout->frame); if (p->freez.auxp == NULL || p->freez.size < sizeof(MYFLT) * (N + 2) * nsmps) csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT) * nsmps, &p->freez); } else { if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(float) * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame); if (p->freez.auxp == NULL || p->freez.size < sizeof(float) * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->freez); if (UNLIKELY(!(p->fout->format == PVS_AMP_FREQ) || (p->fout->format == PVS_AMP_PHASE))) return csound->InitError(csound, Str("pvsfreeze: signal format " "must be amp-phase or amp-freq.")); } return OK; } static int pvssfreezeprocess(CSOUND *csound, PVSFREEZE *p) { int i; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t n, nsmps = CS_KSMPS; int NB = p->fin->NB; MYFLT freeza = *p->kfra, freezf = *p->kfrf; CMPLX *fz = (CMPLX*)p->freez.auxp; for (n=0; nfout->frame.auxp + n*NB; for (i = 0; i < NB; i++) fo[i].re = fo[i].im = FL(0.0); } for (n=offset; nfout->frame.auxp + n*NB; CMPLX *fi = (CMPLX*)p->fin->frame.auxp + n*NB; for (i = 0; i < NB; i++) { if (freeza < 1) fz[i].re = fi[i].re; if (freezf < 1) fz[i].im = fi[i].im; fo[i] = fz[i]; } } return OK; } static int pvsfreezeprocess(CSOUND *csound, PVSFREEZE *p) { int i; int32 framesize; MYFLT freeza, freezf; float *fout, *fin, *freez; if (p->fin->sliding) return pvssfreezeprocess(csound, p); freeza = *p->kfra; freezf = *p->kfrf; fout = (float *) p->fout->frame.auxp; fin = (float *) p->fin->frame.auxp; freez = (float *) p->freez.auxp; framesize = p->fin->N + 2; if (p->lastframe < p->fin->framecount) { for (i = 0; i < framesize; i += 2) { if (freeza < 1) freez[i] = fin[i]; if (freezf < 1) freez[i + 1] = fin[i + 1]; fout[i] = freez[i]; fout[i + 1] = freez[i + 1]; } p->fout->framecount = p->lastframe = p->fin->framecount; } return OK; } static int pvsoscset(CSOUND *csound, PVSOSC *p) { int i; int32 N = (int32) *p->framesize; p->fout->N = N; p->fout->overlap = (int32)(*p->olap ? *p->olap : N/4); p->fout->winsize = (int32)(*p->winsize ? *p->winsize : N); p->fout->wintype = (int32) *p->wintype; p->fout->format = (int32) *p->format; p->fout->framecount = 0; p->fout->sliding = 0; if (p->fout->overlap<(int)CS_KSMPS || p->fout->overlap<=10) { return csound->InitError(csound, Str("pvsosc does not work while sliding")); #ifdef SOME_FINE_DAY CMPLX *bframe; int NB = 1+N/2; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t n, nsmps = CS_KSMPS; p->fout->NB = NB; p->fout->sliding = 1; if (p->fout->frame.auxp == NULL || p->fout->frame.size < CS_KSMPS*sizeof(MYFLT) * (N + 2)) csound->AuxAlloc(csound, (N + 2) * CS_KSMPS* sizeof(MYFLT), &p->fout->frame); else memset(p->fout->frame.auxp, '\0', (N + 2) * CS_KSMPS* sizeof(MYFLT)); bframe = (CMPLX *)p->fout->frame.auxp; for (n=0; nonedsr); } return OK; #endif } else { float *bframe; int j; if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(float) * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame); bframe = (float *) p->fout->frame.auxp; for (i = j = 0; i < N + 2; i += 2, j++) { //bframe[i] = 0.0f; bframe[i + 1] = j * N * csound->onedsr; } p->lastframe = 1; p->incr = (MYFLT)CS_KSMPS/p->fout->overlap; } return OK; } static int pvsoscprocess(CSOUND *csound, PVSOSC *p) { int i, harm, type; int32 framesize; MYFLT famp, ffun,w; float *fout; double cfbin,a; float amp, freq; int cbin, k, n; famp = *p->ka; ffun = *p->kf; type = (int)MYFLT2LRND(*p->type); fout = (float *) p->fout->frame.auxp; framesize = p->fout->N + 2; if (p->fout->sliding) { CMPLX *fout; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t n, nsmps = CS_KSMPS; int NB = p->fout->NB; harm = (int)(CS_ESR/(2*ffun)); if (type==1) famp *= FL(1.456)/POWER((MYFLT)harm, FL(1.0)/FL(2.4)); else if (type==2) famp *= FL(1.456)/POWER((MYFLT)harm, FL(0.25)); else if (type==3) famp *= FL(1.456)/POWER((MYFLT)harm, FL(1.0)/FL(160.0)); else { harm = 1; famp *= FL(1.456); } for (n=0; nfout->frame.auxp + n*NB; w = CS_ESR/p->fout->N; /* harm = (int)(CS_ESR/(2*ffun)); */ memset(fout, '\0', NB*sizeof(CMPLX)); if (nlastframe > p->fout->framecount) { w = CS_ESR/p->fout->N; harm = (int)(CS_ESR/(2*ffun)); if (type==1) famp *= FL(1.456)/pow(harm, FL(1.0)/FL(2.4)); else if (type==2) famp *= FL(1.456)/POWER(harm, FL(0.25)); else if (type==3) famp *= FL(1.456)/POWER(harm, FL(1.0)/FL(160.0)); else { harm = 1; famp *= FL(1.456); } memset(fout, 0, sizeof(float)*framesize); /* for (i = 0; i < framesize; i ++) fout[i] = 0.f; */ for (n=1; n <= harm; n++) { if (type == 3) amp = famp/(harm); else amp = (famp/n); freq = ffun*n; cfbin = freq/w; cbin = (int)MYFLT2LRND(cfbin); if (cbin != 0) { for (i=cbin-1,k = (cbin-1)<<1;i < cbin+3 &&i < framesize/2 ; i++, k+=2) { //k = i<<1; if (i-cfbin == 0) a = 1; else a = sin(i-cfbin)/(i-cfbin); fout[k] = amp*a*a*a; fout[k+1] = freq; } if (type==2) n++; } } p->fout->framecount = p->lastframe; } p->incr += p->incr; if (p->incr > 1) { p->incr = (MYFLT)CS_KSMPS/p->fout->overlap; p->lastframe++; } return OK; } static int pvsbinset(CSOUND *csound, PVSBIN *p) { p->lastframe = 0; return OK; } static int pvsbinprocess(CSOUND *csound, PVSBIN *p) { int32 framesize, pos; if (p->fin->sliding) { CMPLX *fin = (CMPLX *) p->fin->frame.auxp; framesize = p->fin->NB; pos=*p->kbin; if (pos >= 0 && pos < framesize) { *p->kamp = (MYFLT)fin[pos].re; *p->kfreq = (MYFLT)fin[pos].im; } } else { float *fin; fin = (float *) p->fin->frame.auxp; if (p->lastframe < p->fin->framecount) { framesize = p->fin->N + 2; pos=*p->kbin*2; if (pos >= 0 && pos < framesize) { *p->kamp = (MYFLT)fin[pos]; *p->kfreq = (MYFLT)fin[pos+1]; } p->lastframe = p->fin->framecount; } } return OK; } static int pvsbinprocessa(CSOUND *csound, PVSBIN *p) { int32 framesize, pos; if (p->fin->sliding) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t k, nsmps = CS_KSMPS; CMPLX *fin = (CMPLX *) p->fin->frame.auxp; int NB = p->fin->NB; pos = *p->kbin; if (pos >= 0 && pos < NB) { for (k=0; kkamp[k] = p->kfreq[k] = FL(0.0); for (k=offset; kkamp[k] = (MYFLT)fin[pos+NB*k].re; p->kfreq[k] = (MYFLT)fin[pos+NB*k].im; } } } else { float *fin; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t k, nsmps = CS_KSMPS; fin = (float *) p->fin->frame.auxp; if (p->lastframe < p->fin->framecount) { framesize = p->fin->N + 2; pos=*p->kbin*2; if (pos >= 0 && pos < framesize) { memset(p->kamp, '\0', offset*sizeof(MYFLT)); memset(p->kfreq, '\0', offset*sizeof(MYFLT)); for (k=offset; kkamp[k] = (MYFLT)fin[pos]; p->kfreq[k] = (MYFLT)fin[pos+1]; } p->lastframe = p->fin->framecount; } } } return OK; } static int pvsmoothset(CSOUND *csound, PVSMOOTH *p) { int32 N = p->fin->N; if (UNLIKELY(p->fin == p->fout)) csound->Warning(csound, Str("Unsafe to have same fsig as in and out")); p->fout->NB = (N/2)+1; p->fout->sliding = p->fin->sliding; if (p->fin->sliding) { if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(MYFLT) * CS_KSMPS * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT) * CS_KSMPS, &p->fout->frame); if (p->del.auxp == NULL || p->del.size < sizeof(MYFLT) * CS_KSMPS * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT) * CS_KSMPS, &p->del); } else { if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(float) * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame); if (p->del.auxp == NULL || p->del.size < sizeof(float) * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->del); } memset(p->del.auxp, 0, (N + 2) * sizeof(float)); p->fout->N = N; p->fout->overlap = p->fin->overlap; p->fout->winsize = p->fin->winsize; p->fout->wintype = p->fin->wintype; p->fout->format = p->fin->format; p->fout->framecount = 1; p->lastframe = 0; if (UNLIKELY(!(p->fout->format == PVS_AMP_FREQ) || (p->fout->format == PVS_AMP_PHASE))) return csound->InitError(csound, Str("pvsmooth: signal format " "must be amp-phase or amp-freq.")); return OK; } static int pvsmoothprocess(CSOUND *csound, PVSMOOTH *p) { int i; int32 framesize; double ffa, ffr; ffa = (double) *p->kfra; ffr = (double) *p->kfrf; framesize = p->fin->N + 2; if (p->fin->sliding) { CMPLX *fout, *fin, *del; double costh1, costh2, coef1, coef2; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t n, nsmps = CS_KSMPS; int NB = p->fin->NB; ffa = ffa < 0.0 ? 0.0 : (ffa > 1.0 ? 1.0 : ffa); ffr = ffr < 0.0 ? 0.0 : (ffr > 1.0 ? 1.0 : ffr); costh1 = 2.0 - cos(PI * ffa); costh2 = 2.0 - cos(PI * ffr); coef1 = sqrt(costh1 * costh1 - 1.0) - costh1; coef2 = sqrt(costh2 * costh2 - 1.0) - costh2; for (n=0; nfout->frame.auxp +NB*n; del = (CMPLX*) p->del.auxp +NB*n; fout[i].re = fout[i].im = del[i].re = del[i].im = FL(0.0); } for (n=offset; nfout->frame.auxp +NB*n; fin = (CMPLX*) p->fin->frame.auxp +NB*n; del = (CMPLX*) p->del.auxp +NB*n; if (IS_ASIG_ARG(p->kfra)) { ffa = (double) p->kfra[n]; ffa = ffa < 0.0 ? 0.0 : (ffa > 1.0 ? 1.0 : ffa); costh1 = 2.0 - cos(PI * ffa); coef1 = sqrt(costh1 * costh1 - 1.0) - costh1; } if (IS_ASIG_ARG(p->kfrf)) { ffr = (double) p->kfrf[n]; ffr = ffr < 0.0 ? 0.0 : (ffr > 1.0 ? 1.0 : ffr); costh2 = 2.0 - cos(PI * ffr); coef2 = sqrt(costh2 * costh2 - 1.0) - costh2; } for (i=0; ilastframe < p->fin->framecount) { float *fout, *fin, *del; double costh1, costh2, coef1, coef2; fout = (float *) p->fout->frame.auxp; fin = (float *) p->fin->frame.auxp; del = (float *) p->del.auxp; ffa = ffa < FL(0.0) ? FL(0.0) : (ffa > FL(1.0) ? FL(1.0) : ffa); ffr = ffr < FL(0.0) ? FL(0.0) : (ffr > FL(1.0) ? FL(1.0) : ffr); costh1 = 2.0 - cos(PI * ffa); costh2 = 2.0 - cos(PI * ffr); coef1 = sqrt(costh1 * costh1 - 1.0) - costh1; coef2 = sqrt(costh2 * costh2 - 1.0) - costh2; for (i = 0; i < framesize; i += 2) { /* amp smoothing */ fout[i] = (float) (fin[i] * (1.0 + coef1) - del[i] * coef1); /* freq smoothing */ fout[i + 1] = (float) (fin[i + 1] * (1.0 + coef2) - del[i + 1] * coef2); del[i] = fout[i]; del[i + 1] = fout[i + 1]; } p->fout->framecount = p->lastframe = p->fin->framecount; } return OK; } static int pvsmixset(CSOUND *csound, PVSMIX *p) { int32 N = p->fa->N; /* if (UNLIKELY(p->fa == p->fout || p->fb == p->fout)) csound->Warning(csound, Str("Unsafe to have same fsig as in and out"));*/ p->fout->sliding = 0; if (p->fa->sliding) { if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(MYFLT) * CS_KSMPS * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT) * CS_KSMPS, &p->fout->frame); p->fout->NB = p->fa->NB; p->fout->sliding = 1; } else if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(float) * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame); p->fout->N = N; p->fout->overlap = p->fa->overlap; p->fout->winsize = p->fa->winsize; p->fout->wintype = p->fa->wintype; p->fout->format = p->fa->format; p->fout->framecount = 1; p->lastframe = 0; if (UNLIKELY(!(p->fout->format == PVS_AMP_FREQ) || (p->fout->format == PVS_AMP_PHASE))) return csound->InitError(csound, Str("pvsmix: signal format " "must be amp-phase or amp-freq.")); return OK; } static int pvsmix(CSOUND *csound, PVSMIX *p) { int i; int32 framesize; int test; float *fout, *fa, *fb; if (UNLIKELY(!fsigs_equal(p->fa, p->fb))) goto err1; if (p->fa->sliding) { CMPLX * fout, *fa, *fb; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t n, nsmps = CS_KSMPS; int NB = p->fa->NB; for (n=0; nfout->frame.auxp +NB*n; for (i = 0; i < NB; i++) fout[i].re = fout[i].im = FL(0.0); } for (n=offset; nfout->frame.auxp +NB*n; fa = (CMPLX*) p->fa->frame.auxp +NB*n; fb = (CMPLX*) p->fb->frame.auxp +NB*n; for (i = 0; i < NB; i++) { fout[i] = (fa[i].re >= fb[i].re) ? fa[i] : fb[i]; } } return OK; } fout = (float *) p->fout->frame.auxp; fa = (float *) p->fa->frame.auxp; fb = (float *) p->fb->frame.auxp; framesize = p->fa->N + 2; if (p->lastframe < p->fa->framecount) { for (i = 0; i < framesize; i += 2) { test = fa[i] >= fb[i]; if (test) { fout[i] = fa[i]; fout[i + 1] = fa[i + 1]; } else { fout[i] = fb[i]; fout[i + 1] = fb[i + 1]; } } p->fout->framecount = p->fa->framecount; p->lastframe = p->fout->framecount; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("pvsmix: formats are different.")); } /* pvsfilter */ static int pvsfilterset(CSOUND *csound, PVSFILTER *p) { int32 N = p->fin->N; if (UNLIKELY(p->fin == p->fout || p->fil == p->fout)) csound->Warning(csound, Str("Unsafe to have same fsig as in and out")); if (UNLIKELY(!(p->fout->format == PVS_AMP_FREQ) || (p->fout->format == PVS_AMP_PHASE))) return csound->InitError(csound, Str("pvsfilter: signal format " "must be amp-phase or amp-freq.")); p->fout->sliding = 0; if (p->fin->sliding) { if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(MYFLT) * CS_KSMPS * (N + 2)) csound->AuxAlloc(csound, sizeof(MYFLT) * CS_KSMPS * (N + 2), &p->fout->frame); p->fout->NB = p->fin->NB; p->fout->sliding = 1; } else if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(float) * (N + 2)) csound->AuxAlloc(csound, sizeof(float) * (N + 2), &p->fout->frame); p->fout->N = N; p->fout->overlap = p->fin->overlap; p->fout->winsize = p->fin->winsize; p->fout->wintype = p->fin->wintype; p->fout->format = p->fin->format; p->fout->framecount = 1; p->lastframe = 0; return OK; } static int pvsfilter(CSOUND *csound, PVSFILTER *p) { int32 i, N = p->fout->N; float g = (float) *p->gain; MYFLT dirgain, kdepth = *p->kdepth; float *fin = (float *) p->fin->frame.auxp; float *fout = (float *) p->fout->frame.auxp; float *fil = (float *) p->fil->frame.auxp; if (UNLIKELY(fout == NULL)) goto err1; if (UNLIKELY(!fsigs_equal(p->fin, p->fil))) goto err2; if (p->fin->sliding) { int NB = p->fout->NB; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t n, nsmps = CS_KSMPS; CMPLX *fin, *fout, *fil; MYFLT g = *p->gain; kdepth = kdepth >= FL(0.0) ? (kdepth <= FL(1.0) ? kdepth*g : g) : FL(0.0); dirgain = (FL(1.0) - kdepth)*g; for (n=0; nfout->frame.auxp + NB*n; for (i = 0; i < NB; i++) fout[i].re = fout[i].im = FL(0.0); } for (n=offset; nfin->frame.auxp + NB*n; fout = (CMPLX *)p->fout->frame.auxp + NB*n; fil = (CMPLX *)p->fil->frame.auxp + NB*n; if (IS_ASIG_ARG(p->kdepth)) { kdepth = p->kdepth[n] >= FL(0.0) ? (p->kdepth[n] <= FL(1.0) ? p->kdepth[n]*g : g) : FL(0.0); dirgain = (FL(1.0) - kdepth)*g; } for (i = 0; i < NB; i++) { fout[i].re = fin[i].re * (dirgain + fil[i].re * kdepth); fout[i].im = fin[i].im; } } return OK; } if (p->lastframe < p->fin->framecount) { kdepth = kdepth >= 0 ? (kdepth <= 1 ? kdepth : 1) : FL(0.0); dirgain = (1 - kdepth); for (i = 0; i < N + 2; i += 2) { fout[i] = (float) (fin[i] * (dirgain + fil[i] * kdepth))*g; fout[i + 1] = fin[i + 1]; } p->fout->framecount = p->lastframe = p->fin->framecount; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("pvsfilter: not initialised")); err2: return csound->PerfError(csound, p->h.insdshead, Str("pvsfilter: formats are different.")); } /* pvscale */ typedef struct _pvscale { OPDS h; PVSDAT *fout; PVSDAT *fin; MYFLT *kscal; MYFLT *keepform; MYFLT *gain; MYFLT *coefs; AUXCH fenv, ceps, ftmp; void *fwdsetup, *invsetup; uint32 lastframe; } PVSSCALE; static int pvsscaleset(CSOUND *csound, PVSSCALE *p) { int32 N = p->fin->N, tmp; if (UNLIKELY(p->fin == p->fout)) csound->Warning(csound, Str("Unsafe to have same fsig as in and out")); p->fout->NB = p->fin->NB; p->fout->sliding = p->fin->sliding; if (p->fin->sliding) { if (p->fout->frame.auxp == NULL || p->fout->frame.size < CS_KSMPS * sizeof(MYFLT) * (N + 2)) csound->AuxAlloc(csound, CS_KSMPS * sizeof(MYFLT) * (N + 2), &p->fout->frame); } else { if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(float) * (N + 2)) /* RWD MUST be 32bit */ csound->AuxAlloc(csound, sizeof(float) * (N + 2), &p->fout->frame); } if (p->ftmp.auxp == NULL || p->ftmp.size < sizeof(float) * (N+4)) csound->AuxAlloc(csound, sizeof(float) * (N + 2), &p->ftmp); p->fout->N = N; p->fout->overlap = p->fin->overlap; p->fout->winsize = p->fin->winsize; p->fout->wintype = p->fin->wintype; p->fout->format = p->fin->format; p->fout->framecount = 1; p->lastframe = 0; tmp = N + N%2; if (p->ceps.auxp == NULL || p->ceps.size < sizeof(MYFLT) * (tmp+2)) csound->AuxAlloc(csound, sizeof(MYFLT) * (tmp + 2), &p->ceps); memset(p->ceps.auxp, 0, sizeof(MYFLT)*(tmp+2)); if (p->fenv.auxp == NULL || p->fenv.size < sizeof(MYFLT) * (N+2)) csound->AuxAlloc(csound, sizeof(MYFLT) * (N + 2), &p->fenv); memset(p->fenv.auxp, 0, sizeof(MYFLT)*(N+2)); p->fwdsetup = csound->RealFFT2Setup(csound, N/2, FFT_FWD); p->invsetup = csound->RealFFT2Setup(csound, N/2, FFT_INV); return OK; } void csoundInverseComplexFFTnp2(CSOUND *csound, MYFLT *buf, int FFTsize); void csoundComplexFFTnp2(CSOUND *csound, MYFLT *buf, int FFTsize); static int pvsscale(CSOUND *csound, PVSSCALE *p) { int i, chan, N = p->fout->N; float max = 0.0f; MYFLT pscal = FABS(*p->kscal); int keepform = (int) *p->keepform; float g = (float) *p->gain; float *fin = (float *) p->fin->frame.auxp; float *fout = (float *) p->fout->frame.auxp; MYFLT *fenv = (MYFLT *) p->fenv.auxp; float *ftmp = (float *) p->ftmp.auxp; MYFLT *ceps = (MYFLT *) p->ceps.auxp; float sr = CS_ESR, binf; int coefs = (int) *p->coefs; if (UNLIKELY(fout == NULL)) goto err1; if (p->fout->sliding) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t n, nsmps = CS_KSMPS; int NB = p->fout->NB; MYFLT g = *p->gain; for (n=0; nfout->frame.auxp + n*NB; for (i = 0; i < NB; i++) fout[i].re = fout[i].im = FL(0.0); } for (n=offset; nfin->frame.auxp + n*NB; CMPLX *fout = (CMPLX *) p->fout->frame.auxp + n*NB; fout[0] = fin[0]; fout[NB-1] = fin[NB-1]; if (IS_ASIG_ARG(p->kscal)) { pscal = FABS(p->kscal[n]); } if (keepform) for (i = 1; i < NB-1; i++) { max = max < fin[i].re ? fin[i].re : max; } for (i = 1; i < NB-1; i++) { if (keepform == 0 || keepform == 1 || !max) fout[i].re = fin[i].re; else fout[i].re = fin[i].re * (fin[i].re / max); fout[i].im = fin[i].im * pscal; /* Remove aliases */ if (fout[i].im>=CS_ESR*0.5 || fout[i].im<= -CS_ESR*0.5) fout[i].re=0.0; } for (i = 1; i < NB; i++) { fout[i].re *= g; } } return OK; } if (p->lastframe < p->fin->framecount) { int n; fout[0] = fin[0]; fout[N] = fin[N]; memcpy(ftmp,fin,sizeof(float)*(N+2)); for (i = 2, n=1; i < N; i += 2, n++) { fout[i] = 0.0f; fout[i + 1] = -1.0f; fenv[n] = 0.f; } if (keepform) { int cond = 1; int j; for (i=j=0; i < N; i+=2, j++) fenv[j] = LOG(ftmp[i] > 0.0 ? ftmp[i] : 1e-20); if (keepform > 2) { /* experimental mode 3 */ int w = 5, w2 = w*2; for (i=0; i < w; i++) ceps[i] = fenv[i]; for (i=w; i < N/2-w; i++) { ceps[i] = 0.0; for (j=-w; j < w; j++) ceps[i] += fenv[i+j]; ceps[i] /= w2; } for (i=0; iRealFFT2(csound, p->fwdsetup, ceps); else csound->RealFFTnp2(csound, ceps, tmp); for (i=coefs; i < N/2; i++) ceps[i] = 0.0; if (!(N & (N - 1))) csound->RealFFT2(csound, p->invsetup, ceps); else csound->InverseRealFFTnp2(csound, ceps, tmp); for (i=j=0; i < N/2; i++, j+=2) { if (keepform > 1) { if (fenv[i] < ceps[i]) fenv[i] = ceps[i]; if ((LOG(ftmp[j]) - ceps[i]) > FL(0.23)) cond = 1; } else { fenv[i] = EXP(ceps[i]); max = max < fenv[i] ? fenv[i] : max; } } } if (keepform > 1) for (i=0; i 0) { fout[newchan] = ftmp[i]*fenv[newchan>>1]; fout[newchan + 1] = (float) (ftmp[i + 1] * pscal); } } } else { for (i = 2, chan = 1; i < N; chan++, i += 2) { int newchan; newchan = (int) ((chan * pscal)+0.5) << 1; if (newchan < N && newchan > 0) { fout[newchan] = ftmp[i]; fout[newchan + 1] = (float) (ftmp[i + 1] * pscal); } } } for (i = 2; i < N; i += 2) { if (isnan(fout[i])) fout[i] = 0.0f; if (fout[i + 1] == -1.0f) { fout[i] = 0.f; } else fout[i] *= g; } p->fout->framecount = p->lastframe = p->fin->framecount; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("pvscale: not initialised")); } /* pvshift */ typedef struct _pvshift { OPDS h; PVSDAT *fout; PVSDAT *fin; MYFLT *kshift; MYFLT *lowest; MYFLT *keepform; MYFLT *gain; MYFLT *coefs; AUXCH fenv, ceps, ftmp; uint32 lastframe; } PVSSHIFT; static int pvsshiftset(CSOUND *csound, PVSSHIFT *p) { int N = p->fin->N; if (UNLIKELY(p->fin == p->fout)) csound->Warning(csound, Str("Unsafe to have same fsig as in and out")); if (p->fin->sliding) { if (p->fout->frame.auxp==NULL || CS_KSMPS*(N+2)*sizeof(MYFLT) > (unsigned int)p->fout->frame.size) csound->AuxAlloc(csound, CS_KSMPS*(N+2)*sizeof(MYFLT),&p->fout->frame); else memset(p->fout->frame.auxp, 0, CS_KSMPS*(N+2)*sizeof(MYFLT)); } else { if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(float) * (N + 2)) /* RWD MUST be 32bit */ csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame); else memset(p->fout->frame.auxp, 0, (N+2)*sizeof(float)); } p->fout->N = N; p->fout->overlap = p->fin->overlap; p->fout->winsize = p->fin->winsize; p->fout->wintype = p->fin->wintype; p->fout->format = p->fin->format; p->fout->framecount = 1; p->lastframe = 0; p->fout->sliding = p->fin->sliding; p->fout->NB = p->fin->NB; if (p->ceps.auxp == NULL || p->ceps.size < sizeof(MYFLT) * (N+2)) csound->AuxAlloc(csound, sizeof(MYFLT) * (N + 2), &p->ceps); else memset(p->ceps.auxp, 0, sizeof(MYFLT)*(N+2)); if (p->fenv.auxp == NULL || p->fenv.size < sizeof(MYFLT) * (N+2)) csound->AuxAlloc(csound, sizeof(MYFLT) * (N + 2), &p->fenv); else memset(p->fenv.auxp, 0, sizeof(MYFLT)*(N+2)); if (p->ftmp.auxp == NULL || p->ftmp.size < sizeof(float) * (N+4)) csound->AuxAlloc(csound, sizeof(float) * (N + 2), &p->ftmp); return OK; } static int pvsshift(CSOUND *csound, PVSSHIFT *p) { int i, chan, newchan, N = p->fout->N; MYFLT pshift = (MYFLT) *p->kshift; int lowest = abs((int) (*p->lowest * N * csound->onedsr)); float max = 0.0f; int cshift = (int) (pshift * N * csound->onedsr); int keepform = (int) *p->keepform; float g = (float) *p->gain; float *fin = (float *) p->fin->frame.auxp; float *fout = (float *) p->fout->frame.auxp; float *ftmp = (float *) p->ftmp.auxp; MYFLT *fenv = (MYFLT *) p->fenv.auxp; MYFLT *ceps = (MYFLT *) p->ceps.auxp; float sr = CS_ESR, binf; int coefs = (int) *p->coefs; if (UNLIKELY(fout == NULL)) goto err1; if (p->fin->sliding) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t n, nsmps = CS_KSMPS; int NB = p->fout->NB; MYFLT g = *p->gain; lowest = lowest ? (lowest > NB ? NB : lowest) : 1; for (n=0; nfout->frame.auxp + n*NB; for (i = 0; i < NB; i++) fout[i].re = fout[i].im = FL(0.0); } for (n=offset; nfin->frame.auxp + n*NB; CMPLX *fout = (CMPLX *) p->fout->frame.auxp + n*NB; fout[0] = fin[0]; fout[NB-1] = fin[NB-1]; if (IS_ASIG_ARG(p->kshift)) { pshift = (p->kshift)[n]; } for (i = 1; i < NB-1; i++) { if (keepform && (max < fin[i].re)) max = fin[i].re; if (i < lowest) { fout[i] = fin[i]; } } for (i = lowest; i < NB; i++) { if (keepform == 0 || keepform == 1 || !max) fout[i].re = fin[i].re; else fout[i].re = fin[i].re * (fin[i].re / max); fout[i].im = (fin[i].im + pshift); /* Remove aliases */ if (fout[i].im>=CS_ESR*0.5 || fout[i].im<= -CS_ESR*0.5) fout[i].re = 0.0; } if (g!=1.0f) for (i = lowest; i < NB; i++) { fout[i].re *= g; } } return OK; } if (p->lastframe < p->fin->framecount) { int j; lowest = lowest ? (lowest > N / 2 ? N / 2 : lowest << 1) : 2; fout[0] = fin[0]; fout[N] = fin[N]; memcpy(ftmp, fin, sizeof(float)*(N+2)); for (j = i = 2; i < N; i += 2, j++) { fenv[j] = 0.0; if (i < lowest) { fout[i] = fin[i]; fout[i + 1] = fin[i + 1]; } else { fout[i] = 0.0f; fout[i + 1] = -1.0f; } } if (keepform) { /* new modes 1 & 2 */ int cond = 1; int tmp = N/2; tmp = tmp + tmp%2; for (i=j=0; i < N; i+=2, j++) fenv[j] = LOG(fin[i] > FL(0.0) ? fin[i] : FL(1e-20)); if (coefs < 1) coefs = 80; while(cond) { cond = 0; for (j=i=0; i < N; i+=2, j++) { ceps[i] = fenv[j]; ceps[i+1] = FL(0.0); } if (!(N & (N - 1))) csound->InverseComplexFFT(csound, ceps, N/2); else csoundInverseComplexFFTnp2(csound, ceps, tmp); for (i=coefs; i < N-coefs; i++) ceps[i] = 0.0; if (!(N & (N - 1))) csound->ComplexFFT(csound, ceps, N/2); else csoundComplexFFTnp2(csound, ceps, tmp); for (i=j=0; i < N; i+=2, j++) { if (keepform > 1) { if (fenv[j] < ceps[i]) fenv[j] = ceps[i]; if ((LOG(fin[i]) - ceps[i]) > 0.23) cond = 1; } else { fenv[j] = EXP(ceps[i]); max = max < fenv[j] ? fenv[j] : max; } } } if (keepform > 1) for (i=0; i> 1; i < N; chan++, i += 2) { newchan = (chan + cshift) << 1; if (newchan < N && newchan > lowest) { fout[newchan] = ftmp[i] * fenv[newchan>>1]; fout[newchan + 1] = (float) (ftmp[i + 1] + pshift); } } } else { for (i = lowest, chan = lowest >> 1; i < N; chan++, i += 2) { newchan = (chan + cshift) << 1; if (newchan < N && newchan > lowest) { fout[newchan] = ftmp[i]; fout[newchan + 1] = (float) (ftmp[i + 1] + pshift); } } } for (i = lowest; i < N; i += 2) { if (fout[i + 1] == -1.0f) fout[i] = 0.0f; else fout[i] *= g; } p->fout->framecount = p->lastframe = p->fin->framecount; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("pvshift: not initialised")); } /* pvswarp */ typedef struct _pvswarp { OPDS h; PVSDAT *fout; PVSDAT *fin; MYFLT *kscal; MYFLT *kshift; MYFLT *klowest; MYFLT *keepform; MYFLT *gain; MYFLT *coefs; AUXCH fenv, ceps; uint32 lastframe; } PVSWARP; static int pvswarpset(CSOUND *csound, PVSWARP *p) { int32 N = p->fin->N; if (UNLIKELY(p->fin == p->fout)) csound->Warning(csound, Str("Unsafe to have same fsig as in and out")); { if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(float) * (N + 2)) /* RWD MUST be 32bit */ csound->AuxAlloc(csound, sizeof(float) * (N + 2), &p->fout->frame); } p->fout->N = N; p->fout->overlap = p->fin->overlap; p->fout->winsize = p->fin->winsize; p->fout->wintype = p->fin->wintype; p->fout->format = p->fin->format; p->fout->framecount = 1; p->lastframe = 0; if (p->ceps.auxp == NULL || p->ceps.size < sizeof(MYFLT) * (N+2)) csound->AuxAlloc(csound, sizeof(MYFLT) * (N + 2), &p->ceps); else memset(p->ceps.auxp, 0, sizeof(MYFLT)*(N+2)); if (p->fenv.auxp == NULL || p->fenv.size < sizeof(MYFLT) * (N+2)) csound->AuxAlloc(csound, sizeof(MYFLT) * (N + 2), &p->fenv); else memset(p->fenv.auxp, 0, sizeof(MYFLT)*(N+2)); return OK; } static int pvswarp(CSOUND *csound, PVSWARP *p) { int i,j, chan, N = p->fout->N; float max = 0.0f; MYFLT pscal = FABS(*p->kscal); MYFLT pshift = (*p->kshift); int cshift = (int) (pshift * N * csound->onedsr); int keepform = (int) *p->keepform; float g = (float) *p->gain; float *fin = (float *) p->fin->frame.auxp; float *fout = (float *) p->fout->frame.auxp; MYFLT *fenv = (MYFLT *) p->fenv.auxp; MYFLT *ceps = (MYFLT *) p->ceps.auxp; float sr = CS_ESR, binf; int lowest = abs((int) (*p->klowest * N * csound->onedsr));; int coefs = (int) *p->coefs; lowest = lowest ? (lowest > N / 2 ? N / 2 : lowest << 1) : 2; if (UNLIKELY(fout == NULL)) goto err1; if (p->lastframe < p->fin->framecount) { int n; fout[0] = fin[0]; fout[N] = fin[N]; for (i = 2, n=1; i < N; i += 2, n++) { fout[i] = 0.0f; fout[i + 1] = -1.0f; fenv[n] = 0.f; } { int cond = 1; for (j=i=0; i < N; i+=2, j++) { fenv[j] = LOG(fin[i] > 0.0 ? fin[i] : 1e-20); } if (keepform > 2) { /* experimental mode 3 */ int w = 5; for (i=0; i < w; i++) ceps[i] = fenv[i]; for (i=w; i < N/2-w; i++) { ceps[i] = 0.0; for (j=-w; j < w; j++) ceps[i] += fenv[i+j]; ceps[i] /= 2*w; } for (i=0; iInverseComplexFFT(csound, ceps, N/2); else csoundInverseComplexFFTnp2(csound, ceps, tmp); for (i=coefs; i < N-coefs; i++) ceps[i] = 0.0; if (!(N & (N - 1))) csound->ComplexFFT(csound, ceps, N/2); else csoundComplexFFTnp2(csound, ceps, tmp); for (j=i=0; i < N; i+=2, j++) { if (keepform > 1) { if (fenv[j] < ceps[i]) fenv[j] = ceps[i]; if ((LOG(fin[i]) - ceps[i]) > 0.23) cond = 1; } else { fenv[j] = EXP(ceps[i]); max = max < fenv[j] ? fenv[j] : max; } } } if (keepform > 1) for (j=i=0; i= lowest) { if (newchan < N && newchan > 0) fout[newchan] = fin[newchan]*fenv[j]; } else fout[i] = fin[i]; fout[i + 1] = fin[i + 1]; } for (i = j= lowest; i < N; i += 2, j++) { if (isnan(fout[i])) fout[i] = 0.0f; else fout[i] *= g; binf = (j)*sr/N; if (fenv[j] && binf < pscal*sr/2+pshift ) fin[i] *= fenv[i/2]; } p->fout->framecount = p->lastframe = p->fin->framecount; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("pvswarp: not initialised")); } /* pvsblur */ static int pvsblurset(CSOUND *csound, PVSBLUR *p) { float *delay; int32 N = p->fin->N, i, j; int olap = p->fin->overlap; int delayframes, framesize = N + 2; if (UNLIKELY(p->fin == p->fout)) csound->Warning(csound, Str("Unsafe to have same fsig as in and out")); if (p->fin->sliding) { csound->InitError(csound, Str("pvsblur does not work sliding yet")); delayframes = (int) (FL(0.5) + *p->maxdel * CS_ESR); if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(MYFLT) * CS_KSMPS * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT) * CS_KSMPS, &p->fout->frame); if (p->delframes.auxp == NULL || p->delframes.size < (N + 2) * sizeof(MYFLT) * CS_KSMPS * delayframes) csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT) * CS_KSMPS * delayframes, &p->delframes); } else { p->frpsec = CS_ESR / olap; delayframes = (int) (*p->maxdel * p->frpsec); if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(float) * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame); if (p->delframes.auxp == NULL || p->delframes.size < (N + 2) * sizeof(float) * CS_KSMPS * delayframes) csound->AuxAlloc(csound, (N + 2) * sizeof(float) * delayframes, &p->delframes); } delay = (float *) p->delframes.auxp; for (j = 0; j < framesize * delayframes; j += framesize) for (i = 0; i < N + 2; i += 2) { delay[i + j] = 0.0f; delay[i + j + 1] = i * CS_ESR / N; } p->fout->N = N; p->fout->overlap = olap; p->fout->winsize = p->fin->winsize; p->fout->wintype = p->fin->wintype; p->fout->format = p->fin->format; p->fout->framecount = 1; p->lastframe = 0; p->count = 0; p->fout->sliding = p->fin->sliding; p->fout->NB = p->fin->NB; return OK; } static int pvsblur(CSOUND *csound, PVSBLUR *p) { int32 j, i, N = p->fout->N, first, framesize = N + 2; int32 countr = p->count; double amp = 0.0, freq = 0.0; int delayframes = (int) (*p->kdel * p->frpsec); int kdel = delayframes * framesize; int mdel = (int) (*p->maxdel * p->frpsec) * framesize; float *fin = (float *) p->fin->frame.auxp; float *fout = (float *) p->fout->frame.auxp; float *delay = (float *) p->delframes.auxp; if (UNLIKELY(fout == NULL || delay == NULL)) goto err1; if (p->fin->sliding) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t n, nsmps = CS_KSMPS; int NB = p->fin->NB; kdel = kdel >= 0 ? (kdel < mdel ? kdel : mdel - framesize) : 0; for (n=0; nfout->frame.auxp +NB*n; for (i = 0; i < NB; i++) fout[i].re = fout[i].im = FL(0.0); } for (n=offset; nfin->frame.auxp +NB*n; CMPLX *fout = (CMPLX *) p->fout->frame.auxp +NB*n; CMPLX *delay = (CMPLX *) p->delframes.auxp +NB*n; for (i = 0; i < NB; i++) { delay[countr + i] = fin[i]; if (kdel) { if ((first = countr - kdel) < 0) first += mdel; for (j = first; j != countr; j = (j + framesize) % mdel) { amp += delay[j + i].re; freq += delay[j + i].im; } fout[i].re = (MYFLT) (amp / delayframes); fout[i].im = (MYFLT) (freq / delayframes); amp = freq = FL(0.0); } else { fout[i] = fin[i]; } } } countr += (N + 2); p->count = countr < mdel ? countr : 0; return OK; } if (p->lastframe < p->fin->framecount) { kdel = kdel >= 0 ? (kdel < mdel ? kdel : mdel - framesize) : 0; for (i = 0; i < N + 2; i += 2) { delay[countr + i] = fin[i]; delay[countr + i + 1] = fin[i + 1]; if (kdel) { if ((first = countr - kdel) < 0) first += mdel; for (j = first; j != countr; j = (j + framesize) % mdel) { amp += delay[j + i]; freq += delay[j + i + 1]; } fout[i] = (float) (amp / delayframes); fout[i + 1] = (float) (freq / delayframes); amp = freq = 0.; } else { fout[i] = fin[i]; fout[i + 1] = fin[i + 1]; } } p->fout->framecount = p->lastframe = p->fin->framecount; countr += (N + 2); p->count = countr < mdel ? countr : 0; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("pvsblur: not initialised")); } /* pvstencil */ static int pvstencilset(CSOUND *csound, PVSTENCIL *p) { int32 N = p->fin->N; uint32_t i; int32 chans = N / 2 + 1; MYFLT *ftable; p->fout->N = N; p->fout->overlap = p->fin->overlap; p->fout->winsize = p->fin->winsize; p->fout->wintype = p->fin->wintype; p->fout->format = p->fin->format; p->fout->framecount = 1; p->lastframe = 0; p->fout->NB = chans; if (p->fin->sliding) { if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(MYFLT) * (N + 2) * CS_KSMPS) csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT) * CS_KSMPS, &p->fout->frame); p->fout->sliding = 1; } else { if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(float) * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame); if (UNLIKELY(!(p->fout->format == PVS_AMP_FREQ) || (p->fout->format == PVS_AMP_PHASE))) return csound->InitError(csound, Str("pvstencil: signal format " "must be amp-phase or amp-freq.")); } p->func = csound->FTnp2Find(csound, p->ifn); if (p->func == NULL) return OK; if (UNLIKELY(p->func->flen + 1 < (unsigned int)chans)) return csound->InitError(csound, Str("pvstencil: ftable needs to equal " "the number of bins")); ftable = p->func->ftable; for (i = 0; i < p->func->flen + 1; i++) if (ftable[i] < FL(0.0)) ftable[i] = FL(0.0); return OK; } static int pvstencil(CSOUND *csound, PVSTENCIL *p) { MYFLT *ftable; if (p->fin->sliding) { MYFLT g = FABS(*p->kgain); MYFLT masklevel = FABS(*p->klevel); int NB = p->fin->NB, i; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; p->fout->NB = NB; p->fout->N = p->fin->N; p->fout->format = p->fin->format; p->fout->wintype = p->fin->wintype; ftable = p->func->ftable; for (n=0; nfout->frame.auxp + n*NB; for (i = 0; i < NB; i++) fout[i].re = fout[i].im = FL(0.0); } for (n=nsmps-early; nfout->frame.auxp + n*NB; for (i = 0; i < NB; i++) fout[i].re = fout[i].im = FL(0.0); } nsmps -= early; for (n=offset; nfout->frame.auxp + n*NB; CMPLX *fin = (CMPLX *) p->fin->frame.auxp + n*NB; for (i = 0; i < NB; i++) { if (fin[i].re > ftable[i] * masklevel) fout[i].re = fin[i].re; /* Just copy */ else { fout[i].re = fin[i].re * g; /* or apply gain */ } fout[i].im = fin[i].im * g; } } } else { int32 framesize, i, j; int test; float *fout, *fin; float g = fabsf((float)*p->kgain); float masklevel = fabsf((float)*p->klevel); fout = (float *) p->fout->frame.auxp; fin = (float *) p->fin->frame.auxp; ftable = p->func->ftable; framesize = p->fin->N + 2; if (UNLIKELY(fout == NULL)) goto err1; if (p->lastframe < p->fin->framecount) { for (i = 0, j = 0; i < framesize; i += 2, j++) { test = fin[i] > ftable[j] * masklevel; if (test) fout[i] = fin[i]; else fout[i] = fin[i] * g; fout[i + 1] = fin[i + 1]; } p->fout->framecount = p->lastframe = p->fin->framecount; } } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("pvstencil: not initialised")); } static int fsigs_equal(const PVSDAT *f1, const PVSDAT *f2) { if ( (f1->sliding == f2->sliding) && (f1->overlap == f2->overlap) && (f1->winsize == f2->winsize) && (f1->wintype == f2->wintype) && /* harsh, maybe... */ (f1->N == f2->N) && (f1->format == f2->format)) return 1; return 0; } typedef struct _pvsenvw { OPDS h; MYFLT *kflag; PVSDAT *fin; MYFLT *ftab; MYFLT *keepform; MYFLT *gain; MYFLT *coefs; AUXCH fenv, ceps; uint32 lastframe; } PVSENVW; static int pvsenvwset(CSOUND *csound, PVSENVW *p) { int32 N = p->fin->N; p->lastframe = 0; if (p->ceps.auxp == NULL || p->ceps.size < sizeof(MYFLT) * (N+2)) csound->AuxAlloc(csound, sizeof(MYFLT) * (N + 2), &p->ceps); else memset(p->ceps.auxp, 0, sizeof(MYFLT)*(N+2)); if (p->fenv.auxp == NULL || p->fenv.size < sizeof(MYFLT) * (N+2)) csound->AuxAlloc(csound, sizeof(MYFLT) * (N + 2), &p->fenv); else memset(p->fenv.auxp, 0, sizeof(MYFLT)*(N+2)); return OK; } static int pvsenvw(CSOUND *csound, PVSENVW *p) { int i,j, N = p->fin->N; float max = 0.0f; int keepform = (int) *p->keepform; float g = (float) *p->gain; float *fin = (float *) p->fin->frame.auxp; MYFLT *fenv = (MYFLT *) p->fenv.auxp; MYFLT *ceps = (MYFLT *) p->ceps.auxp; int coefs = (int) *p->coefs; FUNC *ft = csound->FTnp2Find(csound, p->ftab); int size; MYFLT *ftab; if (ft == NULL) { csound->PerfError(csound, p->h.insdshead, Str("could not find table number %d\n"), (int) *p->ftab); return NOTOK; } size = ft->flen; ftab = ft->ftable; *p->kflag = 0.0; if (p->lastframe < p->fin->framecount) { { int cond = 1; for (i=j=0; i < N; i+=2, j++) { fenv[j] = LOG(fin[i] > 0.0 ? fin[i] : 1e-20); } if (keepform > 2) { /* experimental mode 3 */ int j; int w = 5; for (i=0; i < w; i++) ceps[i] = fenv[i]; for (i=w; i < N/2-w; i++) { ceps[i] = 0.0; for (j=-w; j < w; j++) ceps[i] += fenv[i+j]; ceps[i] /= 2*w; } for (i=0; iInverseComplexFFT(csound, ceps, N/2); else csoundInverseComplexFFTnp2(csound, ceps, tmp); for (i=coefs; i < N-coefs; i++) ceps[i] = 0.0; if (!(N & (N - 1))) csound->ComplexFFT(csound, ceps, N/2); else csoundComplexFFTnp2(csound, ceps, tmp); for (i=j=0; i < N; i+=2, j++) { if (keepform > 1) { if (fenv[j] < ceps[i]) fenv[j] = ceps[i]; if ((LOG(fin[i]) - ceps[i]) > 0.23) cond = 1; } else { fenv[j] = EXP(ceps[i]); max = max < fenv[j] ? fenv[j] : max; } } } if (keepform > 1) for (j=i=0; ilastframe = p->fin->framecount; *p->kflag = FL(1.0); } return OK; } typedef struct pvs2tab_t { OPDS h; MYFLT *framecount; ARRAYDAT *ans; PVSDAT *fsig; } PVS2TAB_T; int pvs2tab_init(CSOUND *csound, PVS2TAB_T *p) { if (UNLIKELY(!(p->fsig->format == PVS_AMP_FREQ) || (p->fsig->format == PVS_AMP_PHASE))) return csound->InitError(csound, Str("pvs2tab: signal format " "must be amp-phase or amp-freq.")); if (LIKELY(p->ans->data)) return OK; return csound->InitError(csound, Str("array-variable not initialised")); } int pvs2tab(CSOUND *csound, PVS2TAB_T *p){ int size = p->ans->sizes[0], N = p->fsig->N, i; float *fsig = (float *) p->fsig->frame.auxp; for(i = 0; i < size && i < N+2; i++) p->ans->data[i] = (MYFLT) fsig[i]; *p->framecount = (MYFLT) p->fsig->framecount; return OK; } typedef struct pvs2tabsplit_t { OPDS h; MYFLT *framecount; ARRAYDAT *mags; ARRAYDAT *freqs; PVSDAT *fsig; } PVS2TABSPLIT_T; int pvs2tabsplit_init(CSOUND *csound, PVS2TABSPLIT_T *p) { if (UNLIKELY(!(p->fsig->format == PVS_AMP_FREQ) || (p->fsig->format == PVS_AMP_PHASE))) return csound->InitError(csound, Str("pvs2tab: signal format " "must be amp-phase or amp-freq.")); if (LIKELY(p->mags->data) && LIKELY(p->freqs->data)) return OK; return csound->InitError(csound, Str("array-variable not initialised")); } int pvs2tabsplit(CSOUND *csound, PVS2TABSPLIT_T *p){ int mags_size = p->mags->sizes[0], freqs_size = p->freqs->sizes[0], N = p->fsig->N, i, j; float *fsig = (float *) p->fsig->frame.auxp; for(i = 0, j = 0; j < mags_size && i < N+2; i += 2, j++) { p->mags->data[j] = (MYFLT) fsig[i]; } for(i = 1, j = 0; j < freqs_size && i < N+2; i += 2, j++) p->freqs->data[j] = (MYFLT) fsig[i]; *p->framecount = (MYFLT) p->fsig->framecount; return OK; } typedef struct tab2pvs_t { OPDS h; PVSDAT *fout; ARRAYDAT *in; MYFLT *olap, *winsize, *wintype, *format; uint32 ktime; uint32 lastframe; } TAB2PVS_T; int tab2pvs_init(CSOUND *csound, TAB2PVS_T *p) { if (LIKELY(p->in->data)){ int N; p->fout->N = N = p->in->sizes[0] - 2; p->fout->overlap = (int32)(*p->olap ? *p->olap : N/4); p->fout->winsize = (int32)(*p->winsize ? *p->winsize : N); p->fout->wintype = (int32) *p->wintype; p->fout->format = 0; p->fout->framecount = 1; p->lastframe = 0; p->ktime = 0; if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(float) * (N + 2)) { csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame); } else memset(p->fout->frame.auxp, 0, sizeof(float)*(N+2)); return OK; } else return csound->InitError(csound, Str("array-variable not initialised")); } int tab2pvs(CSOUND *csound, TAB2PVS_T *p) { int size = p->in->sizes[0], i; float *fout = (float *) p->fout->frame.auxp; p->ktime += CS_KSMPS; if (p->ktime > (uint32) p->fout->overlap) { p->fout->framecount++; p->ktime -= p->fout->overlap; } if (p->lastframe < p->fout->framecount){ for (i = 0; i < size; i++){ fout[i] = (float) p->in->data[i]; } p->lastframe = p->fout->framecount; } return OK; } typedef struct tab2pvssplit_t { OPDS h; PVSDAT *fout; ARRAYDAT *mags; ARRAYDAT *freqs; MYFLT *olap, *winsize, *wintype, *format; uint32 ktime; uint32 lastframe; } TAB2PVSSPLIT_T; int tab2pvssplit_init(CSOUND *csound, TAB2PVSSPLIT_T *p) { if (LIKELY(p->mags->data) && LIKELY(p->freqs->data) && (p->mags->sizes[0] == p->freqs->sizes[0])) { int N; p->fout->N = N = (p->mags->sizes[0] * 2) - 2; p->fout->overlap = (int32)(*p->olap ? *p->olap : N/4); p->fout->winsize = (int32)(*p->winsize ? *p->winsize : N); p->fout->wintype = (int32) *p->wintype; p->fout->format = 0; p->fout->framecount = 1; p->lastframe = 0; p->ktime = 0; if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(float) * (N + 2)) { csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame); } else memset(p->fout->frame.auxp, 0, sizeof(float)*(N+2)); return OK; } else return csound->InitError(csound, Str("magnitude and frequency arrays not " "initialised, or are not the same size")); } int tab2pvssplit(CSOUND *csound, TAB2PVSSPLIT_T *p) { int size = p->mags->sizes[0], i; float *fout = (float *) p->fout->frame.auxp; p->ktime += CS_KSMPS; if (p->ktime > (uint32) p->fout->overlap) { p->fout->framecount++; p->ktime -= p->fout->overlap; } if (p->lastframe < p->fout->framecount){ for (i = 0; i < size; i++){ fout[i * 2] = (float) p->mags->data[i]; fout[i * 2 + 1] = (float) p->freqs->data[i]; } p->lastframe = p->fout->framecount; } return OK; } static OENTRY localops[] = { {"pvsfwrite", sizeof(PVSFWRITE),0, 3, "", "fS", (SUBR) pvsfwriteset_S, (SUBR) pvsfwrite}, {"pvsfwrite.i", sizeof(PVSFWRITE),0, 3, "", "fi", (SUBR) pvsfwriteset, (SUBR) pvsfwrite}, {"pvsfilter", sizeof(PVSFILTER),0, 3, "f", "ffxp", (SUBR) pvsfilterset, (SUBR) pvsfilter}, {"pvscale", sizeof(PVSSCALE),0, 3, "f", "fxOPO", (SUBR) pvsscaleset, (SUBR) pvsscale}, {"pvshift", sizeof(PVSSHIFT),0, 3, "f", "fxkOPO", (SUBR) pvsshiftset, (SUBR) pvsshift}, {"pvsfilter", sizeof(PVSFILTER),0, 3, "f", "fffp", (SUBR) pvsfilterset, (SUBR) pvsfilter}, {"pvscale", sizeof(PVSSCALE),0, 3, "f", "fkOPO", (SUBR) pvsscaleset, (SUBR) pvsscale}, {"pvshift", sizeof(PVSSHIFT),0, 3, "f", "fkkOPO", (SUBR) pvsshiftset, (SUBR) pvsshift}, {"pvsmix", sizeof(PVSMIX),0, 3, "f", "ff", (SUBR) pvsmixset, (SUBR)pvsmix, NULL}, {"pvsfilter", sizeof(PVSFILTER),0, 3, "f", "ffxp", (SUBR) pvsfilterset, (SUBR) pvsfilter}, {"pvsblur", sizeof(PVSBLUR),0, 3, "f", "fki", (SUBR) pvsblurset, (SUBR) pvsblur, NULL}, {"pvstencil", sizeof(PVSTENCIL), TR, 3, "f", "fkki", (SUBR) pvstencilset, (SUBR) pvstencil}, {"pvsinit", sizeof(PVSINI),0, 1, "f", "ioopo", (SUBR) pvsinit, NULL, NULL}, {"pvsbin", sizeof(PVSBIN),0, 3, "ss", "fk", (SUBR) pvsbinset, (SUBR) pvsbinprocess, (SUBR) pvsbinprocessa}, {"pvsfreeze", sizeof(PVSFREEZE),0, 3, "f", "fkk", (SUBR) pvsfreezeset, (SUBR) pvsfreezeprocess, NULL}, {"pvsmooth", sizeof(PVSFREEZE),0, 3, "f", "fxx", (SUBR) pvsmoothset, (SUBR) pvsmoothprocess, NULL}, {"pvsosc", sizeof(PVSOSC),0, 3, "f", "kkkioopo", (SUBR) pvsoscset, (SUBR) pvsoscprocess, NULL}, {"pvsdiskin", sizeof(pvsdiskin),0, 3, "f", "SkkopP",(SUBR) pvsdiskinset_S, (SUBR) pvsdiskinproc, NULL}, {"pvsdiskin.i", sizeof(pvsdiskin),0, 3, "f", "ikkopP",(SUBR) pvsdiskinset, (SUBR) pvsdiskinproc, NULL}, {"pvstanal", sizeof(PVST),0, 3, "FFFFFFFFFFFFFFFF", "kkkkPPoooP", (SUBR) pvstanalset, (SUBR) pvstanal, NULL}, {"pvswarp", sizeof(PVSWARP),0, 3, "f", "fkkOPPO", (SUBR) pvswarpset, (SUBR) pvswarp}, {"pvsenvftw", sizeof(PVSENVW),0, 3, "k", "fkPPO", (SUBR) pvsenvwset, (SUBR) pvsenvw}, {"pvsgain", sizeof(PVSGAIN), 0,3, "f", "fk", (SUBR) pvsgainset, (SUBR) pvsgain, NULL}, {"pvs2tab", sizeof(PVS2TAB_T), 0,3, "k", "k[]f", (SUBR) pvs2tab_init, (SUBR) pvs2tab, NULL}, {"pvs2tab", sizeof(PVS2TABSPLIT_T), 0,3, "k", "k[]k[]f", (SUBR) pvs2tabsplit_init, (SUBR) pvs2tabsplit, NULL}, {"tab2pvs", sizeof(TAB2PVS_T), 0, 3, "f", "k[]oop", (SUBR) tab2pvs_init, (SUBR) tab2pvs, NULL}, {"tab2pvs", sizeof(TAB2PVSSPLIT_T), 0, 3, "f", "k[]k[]oop", (SUBR) tab2pvssplit_init, (SUBR) tab2pvssplit, NULL}, {"pvs2array", sizeof(PVS2TAB_T), 0,3, "k", "k[]f", (SUBR) pvs2tab_init, (SUBR) pvs2tab, NULL}, {"pvs2array", sizeof(PVS2TABSPLIT_T), 0,3, "k", "k[]k[]f", (SUBR) pvs2tabsplit_init, (SUBR) pvs2tabsplit, NULL}, {"pvsfromarray", sizeof(TAB2PVS_T), 0, 3, "f", "k[]oop", (SUBR) tab2pvs_init, (SUBR) tab2pvs, NULL}, {"pvsfromarray", sizeof(TAB2PVSSPLIT_T), 0, 3, "f", "k[]k[]oop", (SUBR) tab2pvssplit_init, (SUBR) tab2pvssplit, NULL} }; int pvsbasic_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/pvsbasic.h000066400000000000000000000136041321653344700164640ustar00rootroot00000000000000/* pvsbasic.h: basic opcodes for transformation of streaming PV signals (c) Victor Lazzarini, 2004 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* PVSMOOTH: fsig pvsmooth fsigin, kcfa, kcff Smooths the spectral functions of a pvs signal. fsigin: input signal kcfa: cutoff frequency amount of LP filter applied to amplitudes (0 - 1) kcff: cutoff frequency amount of LP filter applied to frequencies (0 - 1) PVSFREEZE: fsig pvsfreeze fsigin, kfreeza, freezf Freeze a spectral frame. fsigin: input kfreeza: amplitude freezing (1=on, 0=off) kfreezf: frequency freezing (1=on, 0=off) PVSMIX: fsig pvsmix fsigin1, fsigin2 Mix 'seamlessly' two pv signals. fsigin1, fsigin2: input signals. PVSFILTER: fsig pvsfilter fsigin, fsigfil, kdepth[, igain] Multiply amplitudes of fsigin by those of fsigfil, according to kdepth fsigin: input signal fsigfil: filtering signal kdepth: depth of filtering igain: amplitude scaling PVSCALE: fsig pvscale fsigin, kscal[, ikeepform, igain] Scale the frequency components of a pv signal, resulting in pitch shift. fsigin: input signal kscal: scaling ratio ikeepform: attempt to keep input signal formants; 0: do not keep formants; 1: keep formants by imposing original amps; 2: keep formants by filtering using the original spec envelope (defaults to 0) igain: amplitude scaling (defaults to 1) PVSHIFT: fsig pvshift fsigin, kshift, klowest [,ikeepform, igain] Shift the frequency components of a pv signal. fsigin: input signal kshift: shift amount (in Hz) klowest: lowest freq affected by the process. ikeepform: attempt to keep input signal formants; 0: do not keep formants; 1: keep formants by imposing original amps; 2: keep formants by filtering using the original spec envelope (defaults to 0) igain: amplitude scaling (defaults to 1) PVBLUR: fsig pvsblur fsigin, kblurtime, imaxdel Average the amp/freq time functions of each analysis channel for a specified time (truncated to number of frames). The input signal will be delayed by that amount. fsigin: input signal kblurtime: time in secs during which windows will be averaged. imaxdel: max delay time, used for allocating memory for the averaging operation. PVSTENCIL: fsig pvstencil fsigin, kgain, klevel, iftable Transforms a signal according to a masking function table; if the signal normalised amplitude is below the value of the function for a specific PV channel, it applies a gain to that channel. fsigin: input signal kgain: 'stencil' gain klevel: mask function level (ftable is scaled by this value prior to 'stenciling') iftable: masking function table opcode table entries: {"pvscale", S(PVSSCALE), 3,"f", "fkop", pvsscaleset, pvsscale, NULL }, {"pvshift", S(PVSSHIFT), 3,"f", "fkopo", pvsshiftset, pvsshift, NULL }, {"pvsmix", S(PVSMIX), 3, "f", "ff", pvsmixset, pvsmix, NULL}, {"pvsfilter", S(PVSFILTER), 3, "f", "ffkp", pvsfilterset, pvsfilter, NULL}, {"pvsblur", S(PVSBLUR), 3, "f", "fki", pvsblurset, pvsblur, NULL}, {"pvstencil", S(PVSTENCIL), 3, "f", "fkki", pvstencilset, pvstencil, NULL} {"pvsinit", S(PVSINI), 3, "f", "", pvsinit, NULL, NULL} */ #ifndef _PVSBASIC_H #define _PVSBASIC_H #include "pstream.h" typedef struct _pvsini { OPDS h; PVSDAT *fout; MYFLT *framesize, *olap, *winsize, *wintype, *format; uint32 lastframe; } PVSINI; typedef struct _pvsosc { OPDS h; PVSDAT *fout; MYFLT *ka, *kf, *type; MYFLT *framesize, *olap, *winsize, *wintype, *format; MYFLT incr; uint32 lastframe; } PVSOSC; typedef struct _pvsbin { OPDS h; MYFLT *kamp, *kfreq; PVSDAT *fin; MYFLT *kbin; uint32 lastframe; } PVSBIN; typedef struct _pvsfreez { OPDS h; PVSDAT *fout; PVSDAT *fin; MYFLT *kfra, *kfrf; AUXCH freez; uint32 lastframe; } PVSFREEZE; typedef struct _pvsmooth { OPDS h; PVSDAT *fout; PVSDAT *fin; MYFLT *kfra, *kfrf; AUXCH del; uint32 lastframe; } PVSMOOTH; typedef struct _pvsmix { OPDS h; PVSDAT *fout; PVSDAT *fa; PVSDAT *fb; uint32 lastframe; } PVSMIX; static int pvsmixset(CSOUND *, PVSMIX *p); static int pvsmix(CSOUND *, PVSMIX *p); typedef struct _pvsfilter { OPDS h; PVSDAT *fout; PVSDAT *fin; PVSDAT *fil; MYFLT *kdepth; MYFLT *gain; uint32 lastframe; } PVSFILTER; static int pvsfilterset(CSOUND *, PVSFILTER *p); static int pvsfilter(CSOUND *, PVSFILTER *p); typedef struct _pvsblur { OPDS h; PVSDAT *fout; PVSDAT *fin; MYFLT *kdel; MYFLT *maxdel; AUXCH delframes; MYFLT frpsec; int32 count; uint32 lastframe; } PVSBLUR; static int pvsblurset(CSOUND *, PVSBLUR *p); static int pvsblur(CSOUND *, PVSBLUR *p); typedef struct _pvstencil { OPDS h; PVSDAT *fout; PVSDAT *fin; MYFLT *kgain; MYFLT *klevel; MYFLT *ifn; FUNC *func; uint32 lastframe; } PVSTENCIL; static int pvstencilset(CSOUND *, PVSTENCIL *p); static int pvstencil(CSOUND *, PVSTENCIL *p); #endif csound-6.10.0/Opcodes/pvsbuffer.c000066400000000000000000000242071321653344700166500ustar00rootroot00000000000000/* (c) Victor Lazzarini, 2007 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // #include "csdl.h" #include "csoundCore.h" #include "interlocks.h" #include "pstream.h" typedef struct { PVSDAT header; float *data; uint32 frames; } FSIG_HANDLE; typedef struct { OPDS h; MYFLT *hptr; MYFLT *ktime; PVSDAT *fin; MYFLT *len; MYFLT pos; uint32 nframes; uint32 cframes; AUXCH handmem; FSIG_HANDLE *handle; AUXCH buffer; uint32 lastframe; } PVSBUFFER; static int pvsbufferset(CSOUND *csound, PVSBUFFER *p) { int N, hop, i=0; char varname[32] = "::buffer0"; FSIG_HANDLE **phandle = NULL; if (UNLIKELY(p->fin->sliding)) return csound->InitError(csound, Str("SDFT case not implemented yet")); if (p->handmem.auxp == NULL) csound->AuxAlloc(csound, sizeof(FSIG_HANDLE), &p->handmem); p->handle = (FSIG_HANDLE *) p->handmem.auxp; p->handle->header.N = N = p->fin->N; p->handle->header.overlap = hop = p->fin->overlap; p->handle->header.winsize = p->fin->winsize; p->handle->header.wintype = p->fin->wintype; p->handle->header.format = p->fin->format; p->handle->header.framecount = p->fin->framecount; p->nframes = p->handle->frames = (*p->len) * CS_ESR/hop; if (p->buffer.auxp == NULL || p->buffer.size < sizeof(float) * (N + 2) * p->nframes) csound->AuxAlloc(csound, (N + 2) * sizeof(float) * p->nframes, &p->buffer); else memset(p->buffer.auxp, 0, (N + 2) * sizeof(float) * p->nframes); p->handle->header.frame.auxp = p->buffer.auxp; p->handle->header.frame.size = p->buffer.size; p->handle->data = (float *) p->buffer.auxp; while ((phandle = (FSIG_HANDLE **)csound->QueryGlobalVariable(csound,varname)) != NULL) if (p->handle == *phandle) break; else snprintf(varname, 32, "::buffer%d", ++i); if (phandle == NULL) { csound->CreateGlobalVariable(csound, varname, sizeof(FSIG_HANDLE *)); phandle = (FSIG_HANDLE **) csound->QueryGlobalVariable(csound,varname); /*csound->Message(csound, "%p -> %p \n", p->handle, phandle); */ if (phandle == NULL) return csound->InitError(csound, Str("error... could not create global var for handle\n")); else *phandle = p->handle; } *p->hptr = (MYFLT) i; p->lastframe = 0; p->cframes = 0; *p->ktime = p->pos = FL(0.0); return OK; } static int pvsbufferproc(CSOUND *csound, PVSBUFFER *p) { float *fin = p->fin->frame.auxp; if (p->lastframe < p->fin->framecount) { int32 framesize = p->fin->N + 2, i; float *fout = (float *) p->buffer.auxp; fout += framesize*p->cframes; for (i=0;i < framesize; i+=2) { fout[i] = fin[i]; fout[i+1] = fin[i+1]; } p->handle->header.framecount = p->lastframe = p->fin->framecount; p->pos = p->cframes/(CS_ESR/p->fin->overlap); p->cframes++; if (p->cframes == p->nframes)p->cframes = 0; } *p->ktime = p->pos; return OK; } typedef struct { OPDS h; PVSDAT *fout; MYFLT *ktime; MYFLT *hptr; MYFLT *strt; MYFLT *end; MYFLT *clear; MYFLT iclear, optr; FSIG_HANDLE *handle; unsigned int scnt; } PVSBUFFERREAD; static int pvsbufreadset(CSOUND *csound, PVSBUFFERREAD *p) { int N; FSIG_HANDLE *handle=NULL, **phandle; char varname[32]; snprintf(varname, 32, "::buffer%d", (int)(*p->hptr)); /* csound->Message(csound, "%s:\n", varname); */ phandle = (FSIG_HANDLE **) csound->QueryGlobalVariable(csound,varname); if (phandle == NULL) return csound->InitError(csound, Str("error... could not read handle from " "global variable\n")); else handle = *phandle; p->optr = *p->hptr; if (handle != NULL) { p->fout->N = N = handle->header.N; p->fout->overlap = handle->header.overlap; p->fout->winsize = handle->header.winsize; p->fout->wintype = handle->header.wintype; p->fout->format = handle->header.format; p->fout->framecount = 1; } else { p->fout->N = N = 1024; p->fout->overlap = 256; p->fout->winsize = 1024; p->fout->wintype = 1; p->fout->format = PVS_AMP_FREQ; p->fout->framecount = 1; } if (p->fout->frame.auxp == NULL || p->fout->frame.size < sizeof(float) * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame); p->fout->sliding = 0; p->scnt = p->fout->overlap; p->handle = handle; return OK; } static int pvsbufreadproc(CSOUND *csound, PVSBUFFERREAD *p){ unsigned int posi, frames; MYFLT pos, sr = CS_ESR, frac; FSIG_HANDLE *handle = p->handle, **phandle; float *fout, *buffer; int strt = *p->strt, end = *p->end, i, N; unsigned int overlap; p->iclear = *p->clear; if (*p->hptr != p->optr) { char varname[32]; snprintf(varname, 32, "::buffer%d", (int)(*p->hptr)); phandle = (FSIG_HANDLE **) csound->QueryGlobalVariable(csound,varname); if (phandle == NULL) csound->PerfError(csound, p->h.insdshead, Str("error... could not read handle " "from global variable\n")); else handle = *phandle; } if (handle == NULL) goto err1; fout = (float *) p->fout->frame.auxp, buffer = handle->data; N = p->fout->N; overlap = p->fout->overlap; if (p->scnt >= overlap){ float *frame1, *frame2; strt /= (sr/N); end /= (sr/N); strt = (int)(strt < 0 ? 0 : strt > N/2 ? N/2 : strt); end = (int)(end <= strt ? N/2 + 2 : end > N/2 + 2 ? N/2 + 2 : end); frames = handle->frames-1; pos = *p->ktime*(sr/overlap); if (p->iclear) memset(fout, 0, sizeof(float)*(N+2)); while (pos >= frames) pos -= frames; while (pos < 0) pos += frames; posi = (int) pos; if (N == handle->header.N && overlap == (unsigned int)handle->header.overlap){ frame1 = buffer + (N + 2) * posi; frame2 = buffer + (N + 2)*(posi != frames-1 ? posi+1 : 0); frac = pos - posi; for (i=strt; i < end; i+=2){ fout[i] = frame1[i] + frac*(frame2[i] - frame1[i]); fout[i+1] = frame1[i+1] + frac*(frame2[i+1] - frame1[i+1]); } } else for (i=0; i < N+2; i+=2){ fout[i] = 0.0f; fout[i+1] = 0.0f; } p->scnt -= overlap; p->fout->framecount++; } p->scnt += CS_KSMPS; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("Invalid buffer handle")); } static int pvsbufreadproc2(CSOUND *csound, PVSBUFFERREAD *p) { unsigned int posi, frames; MYFLT pos, sr = CS_ESR; FSIG_HANDLE *handle = p->handle, **phandle; MYFLT frac, *tab1, *tab2, *tab; FUNC *ftab; float *fout, *buffer; uint32_t overlap, i; int N; if (*p->hptr != p->optr){ char varname[32]; snprintf(varname, 32, "::buffer%d", (int)(*p->hptr)); phandle = (FSIG_HANDLE **) csound->QueryGlobalVariable(csound,varname); if (phandle == NULL) csound->PerfError(csound, p->h.insdshead, Str("error... could not read handle from " "global variable\n")); else handle = *phandle; } if (UNLIKELY(handle == NULL)) goto err1; fout = (float *) p->fout->frame.auxp, buffer = handle->data; N = p->fout->N; overlap = p->fout->overlap; if (p->scnt >= overlap) { float *frame1, *frame2; frames = handle->frames-1; ftab = csound->FTnp2Find(csound, p->strt); if (UNLIKELY((int)ftab->flen < N/2+1)) csound->PerfError(csound, p->h.insdshead, Str("table length too small: needed %d, got %d\n"), N/2+1, ftab->flen); tab = tab1 = ftab->ftable; ftab = csound->FTnp2Find(csound, p->end); if (UNLIKELY((int)ftab->flen < N/2+1)) csound->PerfError(csound, p->h.insdshead, Str("table length too small: needed %d, got %d\n"), N/2+1, ftab->flen); tab2 = ftab->ftable; for (i=0; i < (unsigned int)N+2; i++){ pos = (*p->ktime - tab[i/2])*(sr/overlap); while(pos >= frames) { pos -= frames; } while(pos < 0){ pos += frames; } posi = (int) pos; if (N == handle->header.N && overlap == (unsigned int)handle->header.overlap) { frame1 = buffer + (N + 2) * posi; frame2 = buffer + (N + 2)*(posi != frames-1 ? posi+1 : 0); frac = pos - posi; fout[i] = frame1[i] + frac*(frame2[i] - frame1[i]); } else fout[i] = 0.0f; if (tab == tab1) tab = tab2; else tab = tab1; } p->scnt -= overlap; p->fout->framecount++; } p->scnt += CS_KSMPS; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("Invalid buffer handle")); } #define S(x) sizeof(x) /* static */ static OENTRY pvsbuffer_localops[] = { {"pvsbuffer", S(PVSBUFFER), 0, 3, "ik", "fi", (SUBR)pvsbufferset, (SUBR)pvsbufferproc, NULL}, {"pvsbufread", S(PVSBUFFERREAD), 0, 3, "f", "kkOOo", (SUBR)pvsbufreadset, (SUBR)pvsbufreadproc, NULL}, {"pvsbufread2", S(PVSBUFFERREAD), 0, 3, "f", "kkkk", (SUBR)pvsbufreadset, (SUBR)pvsbufreadproc2, NULL} }; LINKAGE_BUILTIN(pvsbuffer_localops) /* LINKAGE */ csound-6.10.0/Opcodes/pvscent.c000066400000000000000000000300571321653344700163300ustar00rootroot00000000000000/* pvscent.c: Calculation of spectral centroid as Beauchamp (c) John ffitch, 2005 (c) Alan OCinneide, 2005 (c) V Lazzarin, 2012 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "pvs_ops.h" #include "pstream.h" typedef struct { OPDS h; MYFLT *ans; PVSDAT *fin; uint32 lastframe; MYFLT old; } PVSCENT; static int pvscentset(CSOUND *csound, PVSCENT *p) { *p->ans = FL(0.0); p->lastframe = 0; if (UNLIKELY(!(p->fin->format==PVS_AMP_FREQ) || (p->fin->format==PVS_AMP_PHASE))) return csound->InitError(csound, Str("pvscent: format must be amp-phase" " or amp-freq.\n")); return OK; } static int pvscent(CSOUND *csound, PVSCENT *p) { int32 i,N = p->fin->N; MYFLT c = FL(0.0); MYFLT d = FL(0.0); MYFLT j, binsize = CS_ESR/(MYFLT)N; if (p->fin->sliding) { CMPLX *fin = (CMPLX*) p->fin->frame.auxp; int NB = p->fin->NB; for (i=0, j=FL(0.5)*binsize; ifin->frame.auxp; if (p->lastframe < p->fin->framecount) { //printf("N=%d binsize=%f\n", N, binsize); for (i=0,j=FL(0.5)*binsize; ilastframe = p->fin->framecount; } } *p->ans = (d==FL(0.0) ? FL(0.0) : c/d); return OK; } static int pvsscent(CSOUND *csound, PVSCENT *p) { MYFLT *a = p->ans; if (p->fin->sliding) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 i,N = p->fin->N; MYFLT c = FL(0.0); MYFLT d = FL(0.0); MYFLT j, binsize = CS_ESR/(MYFLT)N; int NB = p->fin->NB; if (UNLIKELY(offset)) memset(a, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&a[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nfin->frame.auxp + n*NB; for (i=0,j=FL(0.5)*binsize; ih.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT old = p->old; int32 i,N = p->fin->N; MYFLT c = FL(0.0); MYFLT d = FL(0.0); MYFLT j, binsize = CS_ESR/(MYFLT)N; float *fin = (float *) p->fin->frame.auxp; nsmps -= early; for (n=offset; nlastframe < p->fin->framecount) { for (i=0,j=FL(0.5)*binsize; ilastframe = p->fin->framecount; } else { a[n] = old; } } p->old = old; } return OK; } typedef struct _cent { OPDS h; MYFLT *ans; MYFLT *asig, *ktrig, *ifftsize; uint32_t fsize, count; MYFLT old; void *setup; AUXCH frame, windowed, win; } CENT; static int cent_i(CSOUND *csound, CENT *p) { int fftsize = *p->ifftsize; p->count = 0; p->fsize = 1; while(fftsize >>= 1) p->fsize <<= 1; if (p->fsize < *p->ifftsize) { p->fsize <<= 1; csound->Warning(csound, Str("centroid requested fftsize = %.0f, actual = %d\n"), *p->ifftsize, p->fsize); } if (p->frame.auxp == NULL || p->frame.size < p->fsize*sizeof(MYFLT)) csound->AuxAlloc(csound, p->fsize*sizeof(MYFLT), &p->frame); if (p->windowed.auxp == NULL || p->windowed.size < p->fsize*sizeof(MYFLT)) csound->AuxAlloc(csound, p->fsize*sizeof(MYFLT), &p->windowed); if (p->win.auxp == NULL || p->win.size < p->fsize*sizeof(MYFLT)) { unsigned int i; MYFLT *win; csound->AuxAlloc(csound, p->fsize*sizeof(MYFLT), &p->win); win = (MYFLT *) p->win.auxp; for (i=0; i < p->fsize; i++) win[i] = 0.5 - 0.5*cos(i*TWOPI/p->fsize); } p->old = 0; memset(p->frame.auxp, 0, p->fsize*sizeof(MYFLT)); memset(p->windowed.auxp, 0, p->fsize*sizeof(MYFLT)); p->setup = csound->RealFFT2Setup(csound,p->fsize,FFT_FWD); return OK; } static int cent_k(CSOUND *csound, CENT *p) { unsigned int n = p->count, k; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT *frame = (MYFLT *) p->frame.auxp, *asig = p->asig; uint32_t fsize = (uint32_t)p->fsize; if (UNLIKELY(early)) nsmps -= early; for (i=offset; i < nsmps; i++){ frame[n] = asig[i]; if (n == fsize-1) { n=0; } else n++; } if (*p->ktrig) { MYFLT c = FL(0.0); MYFLT d = FL(0.0); MYFLT *windowed = (MYFLT *) p->windowed.auxp; MYFLT *win = (MYFLT *) p->win.auxp; MYFLT mag, cf, binsize = CS_ESR/(MYFLT)fsize; for (i=0,k=n; i < fsize; i++){ windowed[i] = frame[k]*win[i]; if (k == fsize-1) k=0; else k++; } csound->RealFFT2(csound, p->setup, windowed); cf=FL(0.5)*binsize; mag = fabs(windowed[0])/fsize; c += mag*cf; d += mag; cf += binsize; for (i=2; i < fsize; i+=2, cf += binsize) { windowed[i] /= fsize; windowed[i+1] /= fsize; mag = sqrt(windowed[i]*windowed[i] + windowed[i+1]*windowed[i+1]); c += mag*cf; d += mag; } p->old = *p->ans = (d==FL(0.0) ? FL(0.0) : c/d); } else *p->ans = p->old; p->count = n; return OK; } /* PVSPITCH opcode by Ala OCinneide */ typedef struct _pvspitch { /* OPDS data structure */ OPDS h; /* Output */ MYFLT *kfreq; MYFLT *kamp; /* Inputs */ PVSDAT *fin; MYFLT *ithreshold; /* Internal arrays */ AUXCH peakfreq; AUXCH inharmonic; uint32 lastframe; } PVSPITCH; #if !defined(FALSE) #define FALSE (0) #endif #if !defined(TRUE) #define TRUE (!FALSE) #endif #define RoundNum(Number) (int)MYFLT2LRND(Number) /* Should one use remainder or drem ?? */ #define Remainder(Numerator, Denominator) \ Numerator/Denominator - (int) (Numerator/Denominator) int pvspitch_init(CSOUND *csound, PVSPITCH *p) { /* Initialise frame count to zero. */ unsigned int size; p->lastframe = 0; if (UNLIKELY(p->fin->sliding)) return csound->InitError(csound, Str("SDFT case not implemented yet")); size = sizeof(MYFLT)*(p->fin->N+2); if (p->peakfreq.auxp == NULL || p->peakfreq.size < size) csound->AuxAlloc(csound, size, &p->peakfreq); if (p->inharmonic.auxp == NULL || p->inharmonic.size < size) csound->AuxAlloc(csound, size, &p->inharmonic); if (UNLIKELY(p->fin->format!=PVS_AMP_FREQ)) { return csound->InitError(csound, Str("PV Frames must be in AMP_FREQ format!\n")); } return OK; } int pvspitch_process(CSOUND *csound, PVSPITCH *p) { /* Initialised inputs */ float *Frame = (float *) p->fin->frame.auxp; MYFLT *PeakFreq = (MYFLT *) p->peakfreq.auxp; MYFLT *inharmonic = (MYFLT *) p->inharmonic.auxp; MYFLT Threshold = (MYFLT) *p->ithreshold; int fftsize = (int) p->fin->N; int numBins = fftsize/2 + 1; MYFLT f0Cand, Frac, Freq = FL(0.0); int i, j, P1, P2, maxPartial; MYFLT lowHearThreshold = FL(20.0); MYFLT Amp = FL(0.0); int Partial = 0; int numPeaks = 0; int maxAdj = 3; int Adj = FALSE; int PrevNotAdj = FALSE; /* Un-normalise the threshold value */ Threshold *= csound->e0dbfs; /* If a new frame is ready... */ if (p->lastframe < p->fin->framecount) { /* Finds the peaks in the frame. */ for (i=1; i<(numBins-1) && numPeaks Threshold && Frame[2*i] > Frame[2*(i-1)] && Frame[2*i] > Frame[2*(i+1)]) { PeakFreq[numPeaks]=Frame[2*i+1]; numPeaks++; i++; /* Impossible to have two peaks in a row, skip over the next. */ } Amp += Frame[2*i]; } Amp += Frame[0]; Amp += Frame[2*numBins]; Amp *= FL(0.5); if (UNLIKELY(numPeaks==0)) { /* If no peaks found return 0. */ Partial = 0; } else { /* Threshold of hearing is 20 Hz, so no need to look beyond there for the fundamental. */ maxPartial = (int) (PeakFreq[0]/lowHearThreshold); /* Calculates the inharmonicity for each fundamental candidate */ for (i=0; i FL(0.5)) Frac = FL(1.0) - Frac; Frac /= PeakFreq[j]; inharmonic[i]+=Frac; } /* Test for the adjacency of partials... */ for (j=0; j0 && inharmonic[i]0 && PrevNotAdj && Adj)) { /* The best candidate so far... */ if (Adj) { Partial = i+1; PrevNotAdj = FALSE; } else if (i==0) { Partial = i+1; PrevNotAdj = TRUE; } else PrevNotAdj = TRUE; } } } /* Output the appropriate frequency values. */ if (LIKELY(Partial!=0)) { f0Cand = PeakFreq[0]/Partial; /* Average frequency between partials */ for (i=0; ikfreq = Freq; } else { *p->kfreq = FL(0.0); } *p->kamp = Amp; /* Update the frame count */ p->lastframe = p->fin->framecount; } return OK; } static OENTRY localops[] = { { "pvscent", sizeof(PVSCENT), 0, 3, "s", "f", (SUBR)pvscentset, (SUBR)pvscent, (SUBR)pvsscent }, { "centroid", sizeof(CENT), 0, 3, "k", "aki", (SUBR)cent_i, (SUBR)cent_k, NULL}, { "pvspitch", sizeof(PVSPITCH), 0, 3, "kk", "fk", (SUBR)pvspitch_init, (SUBR)pvspitch_process, NULL} }; int pvscent_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/pvsdemix.c000066400000000000000000000144241321653344700165050ustar00rootroot00000000000000/* pvsdemix.c: De-mixing of stereo sources. (c) Victor Lazzarini, 2005 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "pvs_ops.h" #include "pvsdemix.h" static int fsigs_equal(const PVSDAT *f1, const PVSDAT *f2) { if ((f1->overlap == f2->overlap) && (f1->winsize == f2->winsize) && (f1->wintype == f2->wintype) /* harsh, maybe... */ && (f1->N == f2->N) && (f1->format == f2->format) ) return 1; return 0; } #define FLOATMAX_ 3.402823466e+38f static int pvsdemix_init(CSOUND *csound, PVSDEMIX *p) { uint32_t N = p->finleft->N; int olap = p->finleft->overlap; uint32_t M; p->beta = (int)(*p->slices); if (UNLIKELY(p->finleft->sliding)) return csound->InitError(csound, Str("SDFT case not implemented yet")); M = (N+2)*sizeof(float); if (p->fout->frame.auxp==NULL || p->fout->frame.sizeAuxAlloc(csound, M,&p->fout->frame); M = M*p->beta; if (p->left.auxp==NULL || p->left.sizeAuxAlloc(csound, M, &p->left); if (p->right.auxp==NULL || p->right.sizeAuxAlloc(csound, M, &p->right); M = (N/2+1)*sizeof(float); if (p->maxl.auxp==NULL || p->maxl.sizeAuxAlloc(csound, M, &p->maxl); if (p->maxr.auxp==NULL || p->maxr.sizeAuxAlloc(csound, M, &p->maxr); if (p->minl.auxp==NULL || p->minl.sizeAuxAlloc(csound, M, &p->minl); if (p->minr.auxp==NULL || p->minr.sizeAuxAlloc(csound, M, &p->minr); p->fout->N = N; p->fout->overlap = olap; p->fout->winsize = p->finleft->winsize; p->fout->wintype = p->finleft->wintype; p->fout->format = p->finleft->format; p->fout->framecount = 1; p->lastframe = 0; if (!(p->fout->format==PVS_AMP_FREQ) || (p->fout->format==PVS_AMP_PHASE)) return csound->InitError(csound, "pvsdemix: signal format must be amp-phase or amp-freq.\n"); return OK; } static int pvsdemix_process(CSOUND *csound, PVSDEMIX *p) { int n, i, n2, N = p->fout->N, imax; int framesize = N+2; float sum = 0.0f,sig,g; int beta = (int) p->beta, pos; float *sigl = (float *) p->finleft->frame.auxp; float *sigr = (float *) p->finright->frame.auxp; float *out = (float *) p->fout->frame.auxp; float *left = (float *) p->left.auxp; float *right = (float *) p->right.auxp; float *minl = (float *) p->minl.auxp; float *maxr = (float *) p->maxr.auxp; float *minr = (float *) p->minr.auxp; float *maxl = (float *) p->maxl.auxp; MYFLT azimuth = *p->pos; MYFLT width = *p->width; MYFLT range; if (UNLIKELY(!fsigs_equal(p->finleft,p->finright))) goto err1; if (UNLIKELY(out==NULL)) goto err2; if (p->lastframe < p->finleft->framecount) { if (width > beta) width = (MYFLT) beta; else if (width < 1) width = FL(1.0); if (azimuth < -1) azimuth = -FL(1.0); else if (azimuth > 1) azimuth = FL(1.0); imax = beta*framesize; range = width/FL(2.0); pos = (int)((azimuth >= 0 ? azimuth : -azimuth)*beta); /* create the azimuth amplitude vectors & find the max/min values for channels, per bin */ for (n=0; n < N/2+1; n++) { maxl[n] = maxr[n] = 0.0f; minl[n] = minr[n] = FLOATMAX_; n2 = n << 1; for (i=framesize; i <= imax; i+=framesize){ g = (float)i/imax; sig = sigl[n2] - g*sigr[n2]; left[n+(imax - i)] = sig < 0 ? -sig : sig; maxl[n] = (maxl[n] > left[n+(imax - i)] ? maxl[n] : left[n+(imax - i)]); minl[n] = (minl[n] < left[n+(imax - i)] ? minl[n] : left[n+(imax - i)]); sig = sigr[n2] - g*sigl[n2]; right[n+(imax - i)] = sig < 0 ? -sig : sig; maxr[n] = (maxr[n] > right[n+(imax - i)] ? maxr[n] : right[n+(imax - i)]); minr[n] = (minr[n] < right[n+(imax - i)] ? minr[n] : right[n+(imax - i)]); } /* reverse the nulls into peaks */ for (i=0; i < imax; i+=framesize) { left[n+i] = (left[n+i] == minl[n] ? maxl[n] - minl[n] : 0.f); right[n+i] = (right[n+i] == minr[n] ? maxr[n] - minr[n] : 0.f); } /* resynthesise the signal azimuth <= 0 => pos incrs right to left azimuth > 0 => pos incrs left to right */ for (i = (int) (pos-range); i < pos+range; i++) { if (i < 0) sum += (azimuth <= 0 ? right[n+(beta+i)*framesize] : left[n+(beta+i)*framesize]); else if (i < beta) sum +=(azimuth <= 0 ? right[n+i*framesize] : left[n+i*framesize]); } out[n2] = sum; out[n2+1] = (azimuth < 0 ? sigl[n2+1] : sigr[n2+1]); sum=0.f; } p->fout->framecount = p->lastframe = p->finleft->framecount; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("pvsdemix : formats are different.\n")); err2: return csound->PerfError(csound, p->h.insdshead, Str("pvsdemix : not initialised \n")); } static OENTRY localops[] = { {"pvsdemix", sizeof(PVSDEMIX), 0, 3, "f", "ffkki", (SUBR) pvsdemix_init, (SUBR) pvsdemix_process, (SUBR) NULL } }; int pvsdemix_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/pvsdemix.h000066400000000000000000000042011321653344700165020ustar00rootroot00000000000000/* pvsdemix.h: (c) Victor Lazzarini, 2005 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA PVSDEMIX: De-mixing of stereo sources. fsig pvsdemix fleft,fright,kpos,kwidth,ipoints INITIALIZATION: ipoints - total number of discrete points, which will divide each pan side of the stereo image. This ultimately affects the resolution of the process. PERFORMANCE fleft - fsig containing the PVS analysis signal of the left channel fright - fsig containing the PVS analysis signal of the right channel kpos - the azimuth target centre position, which will be de-mixed, from left to right (-1 <= kpos <= 1). This is the reverse pan-pot control. kwidth - the azimuth subspace width, which will determine the number of points around kpos which will be used in the de-mixing process. (1 <= kwidth <= ipoints). */ #ifndef _PVSDEMIX_H #define _PVSDEMIX_H #include "pstream.h" typedef struct _pvsdemix { OPDS h; PVSDAT *fout; PVSDAT *finleft; PVSDAT *finright; MYFLT *pos; MYFLT *width; MYFLT *slices; AUXCH left; AUXCH right; AUXCH maxl; AUXCH maxr; AUXCH minl; AUXCH minr; int beta; uint32 lastframe; } PVSDEMIX; static int pvsdemix_init(CSOUND *csound, PVSDEMIX *p); static int pvsdemix_process(CSOUND *csound, PVSDEMIX *p); #endif csound-6.10.0/Opcodes/pvsgendy.c000066400000000000000000000077311321653344700165100ustar00rootroot00000000000000/* pvsgendy.c: gendy style transformation in frequency domain (c) John ffitch, 2009 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "pstream.h" typedef struct { OPDS h; PVSDAT *fout; PVSDAT *fin; MYFLT *kmrate; MYFLT *kfrate; unsigned int lastframe; } PVSGENDY; static int pvsgendyinit(CSOUND *csound, PVSGENDY *p) { int N = p->fin->N; if (UNLIKELY(p->fin == p->fout)) csound->Warning(csound, Str("Unsafe to have same fsig as in and out")); if (UNLIKELY(p->fin->sliding)) { if (p->fout->frame.auxp==NULL || CS_KSMPS*(N+2)*sizeof(MYFLT) > (unsigned int)p->fout->frame.size) csound->AuxAlloc(csound, CS_KSMPS*(N+2)*sizeof(MYFLT),&p->fout->frame); else memset(p->fout->frame.auxp, 0, CS_KSMPS*(N+2)*sizeof(MYFLT)); } else { if (p->fout->frame.auxp == NULL || p->fout->frame.size < (N+2)*sizeof(float)) /* RWD MUST be 32bit */ csound->AuxAlloc(csound, (N+2)*sizeof(float), &p->fout->frame); else memset(p->fout->frame.auxp, 0, (N+2)*sizeof(MYFLT)); } p->fout->N = N; p->fout->overlap = p->fin->overlap; p->fout->winsize = p->fin->winsize; p->fout->wintype = p->fin->wintype; p->fout->format = p->fin->format; p->fout->framecount = 1; p->lastframe = 0; p->fout->sliding = p->fin->sliding; p->fout->NB = p->fin->NB; return OK; } static int pvsgendy(CSOUND *csound, PVSGENDY *p) { int i, N = p->fin->N; MYFLT mrate = *p->kmrate; MYFLT frate = *p->kfrate; float *finf = (float *) p->fin->frame.auxp; float *foutf = (float *) p->fout->frame.auxp; if (UNLIKELY(foutf == NULL)) goto err1; if (p->fin->sliding) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int NB = p->fout->NB; for (n=0; nfin->frame.auxp + n*NB; CMPLX *fout = (CMPLX *) p->fout->frame.auxp + n*NB; for (i = 0; i < NB-1; i++) { MYFLT x = (MYFLT)(rand()-RAND_MAX/2)/(MYFLT)RAND_MAX; // printf("%f\n", x); fout[i].re = fin[i].re + mrate * x; fout[i].im = fin[i].im + frate * (MYFLT)(rand()-RAND_MAX/2)/(MYFLT)RAND_MAX/(MYFLT)(i+1); } } return OK; } if (p->lastframe < p->fin->framecount) { for (i = 0; i < N; i += 2) { MYFLT x = frate * (MYFLT)(rand()-RAND_MAX/2)/(MYFLT)RAND_MAX/(MYFLT)(i+1); foutf[i+1] = finf[i+1] + x; foutf[i] = finf[i] + mrate * (MYFLT)(rand()-RAND_MAX/2)/(MYFLT)RAND_MAX; } p->fout->framecount = p->lastframe = p->fin->framecount; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("pvsgendy: not initialised")); } static OENTRY pvsgendy_localops[] = { { "pvsgendy", sizeof(PVSGENDY), 0, 3, "f", "fkk", (SUBR) pvsgendyinit, (SUBR) pvsgendy, (SUBR) NULL } }; LINKAGE_BUILTIN(pvsgendy_localops) csound-6.10.0/Opcodes/pvsops.cpp000066400000000000000000000171311321653344700165360ustar00rootroot00000000000000/* pvsops.c: pvs and other spectral-based opcodes Copyright (C) 2017 Victor Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include struct PVTrace : csnd::FPlugin<1, 2> { csnd::AuxMem amps; static constexpr char const *otypes = "f"; static constexpr char const *itypes = "fk"; int init() { if (inargs.fsig_data(0).isSliding()) return csound->init_error(Str("sliding not supported")); if (inargs.fsig_data(0).fsig_format() != csnd::fsig_format::pvs && inargs.fsig_data(0).fsig_format() != csnd::fsig_format::polar) return csound->init_error(Str("fsig format not supported")); amps.allocate(csound, inargs.fsig_data(0).nbins()); csnd::Fsig &fout = outargs.fsig_data(0); fout.init(csound, inargs.fsig_data(0)); framecount = 0; return OK; } int kperf() { csnd::pv_frame &fin = inargs.fsig_data(0); csnd::pv_frame &fout = outargs.fsig_data(0); if (framecount < fin.count()) { int n = fin.len() - (int)inargs[1]; float thrsh; std::transform(fin.begin(), fin.end(), amps.begin(), [](csnd::pv_bin f) { return f.amp(); }); std::nth_element(amps.begin(), amps.begin() + n, amps.end()); thrsh = amps[n]; std::transform(fin.begin(), fin.end(), fout.begin(), [thrsh](csnd::pv_bin f) { return f.amp() >= thrsh ? f : csnd::pv_bin(); }); framecount = fout.count(fin.count()); } return OK; } }; struct TVConv : csnd::Plugin<1, 6> { csnd::AuxMem ir; csnd::AuxMem in; csnd::AuxMem insp; csnd::AuxMem irsp; csnd::AuxMem out; csnd::AuxMem saved; csnd::AuxMem::iterator itn; csnd::AuxMem::iterator itr; csnd::AuxMem::iterator itnsp; csnd::AuxMem::iterator itrsp; uint32_t n; uint32_t fils; uint32_t pars; uint32_t ffts; csnd::fftp fwd, inv; typedef std::complex cmplx; uint32_t rpow2(uint32_t n) { uint32_t v = 2; while (v <= n) v <<= 1; if ((n - (v >> 1)) < (v - n)) return v >> 1; else return v; } cmplx *to_cmplx(MYFLT *f) { return reinterpret_cast(f); } cmplx real_prod(cmplx &a, cmplx &b) { return cmplx(a.real() * b.real(), a.imag() * b.imag()); } int init() { pars = inargs[4]; fils = inargs[5]; if (pars > fils) std::swap(pars, fils); if (pars > 1) { pars = rpow2(pars); fils = rpow2(fils) * 2; ffts = pars * 2; fwd = csound->fft_setup(ffts, FFT_FWD); inv = csound->fft_setup(ffts, FFT_INV); out.allocate(csound, ffts); insp.allocate(csound, fils); irsp.allocate(csound, fils); saved.allocate(csound, pars); ir.allocate(csound, fils); in.allocate(csound, fils); itnsp = insp.begin(); itrsp = insp.begin(); n = 0; } else { ir.allocate(csound, fils); in.allocate(csound, fils); } itn = in.begin(); itr = ir.begin(); return OK; } int pconv() { csnd::AudioSig insig(this, inargs(0)); csnd::AudioSig irsig(this, inargs(1)); csnd::AudioSig outsig(this, outargs(0)); auto irp = irsig.begin(); auto inp = insig.begin(); auto *frz1 = inargs(2); auto *frz2 = inargs(3); auto inc1 = csound->is_asig(frz1); auto inc2 = csound->is_asig(frz2); for (auto &s : outsig) { if(*frz1 > 0) itn[n] = *inp; if(*frz2 > 0) itr[n] = *irp; s = out[n] + saved[n]; saved[n] = out[n + pars]; if (++n == pars) { cmplx *ins, *irs, *ous = to_cmplx(out.data()); std::copy(itn, itn + ffts, itnsp); std::copy(itr, itr + ffts, itrsp); std::fill(out.begin(), out.end(), 0.); // FFT csound->rfft(fwd, itnsp); csound->rfft(fwd, itrsp); // increment iterators itnsp += ffts, itrsp += ffts; itn += ffts, itr += ffts; if (itnsp == insp.end()) { itnsp = insp.begin(); itrsp = irsp.begin(); itn = in.begin(); itr = ir.begin(); } // spectral delay line for (csnd::AuxMem::iterator it1 = itnsp, it2 = irsp.end() - ffts; it2 >= irsp.begin(); it1 += ffts, it2 -= ffts) { if (it1 == insp.end()) it1 = insp.begin(); ins = to_cmplx(it1); irs = to_cmplx(it2); // spectral product for (uint32_t i = 1; i < pars; i++) ous[i] += ins[i] * irs[i]; ous[0] += real_prod(ins[0], irs[0]); } // IFFT csound->rfft(inv, out.data()); n = 0; } frz1 += inc1, frz2 += inc2; irp++, inp++; } return OK; } int dconv() { csnd::AudioSig insig(this, inargs(0)); csnd::AudioSig irsig(this, inargs(1)); csnd::AudioSig outsig(this, outargs(0)); auto irp = irsig.begin(); auto inp = insig.begin(); auto frz1 = inargs(2); auto frz2 = inargs(3); auto inc1 = csound->is_asig(frz1); auto inc2 = csound->is_asig(frz2); for (auto &s : outsig) { if(*frz1 > 0) *itn = *inp; if(*frz2 > 0) *itr = *irp; itn++, itr++; if(itn == in.end()) { itn = in.begin(); itr = ir.begin(); } s = 0.; for (csnd::AuxMem::iterator it1 = itn, it2 = ir.end() - 1; it2 >= ir.begin(); it1++, it2--) { if(it1 == in.end()) it1 = in.begin(); s += *it1 * *it2; } frz1 += inc1, frz2 += inc2; inp++, irp++; } return OK; } int aperf() { if (pars > 1) return pconv(); else return dconv(); } }; /* class PrintThread : public csnd::Thread { std::atomic_bool splock; std::atomic_bool on; std::string message; void lock() { bool tmp = false; while(!splock.compare_exchange_weak(tmp,true)) tmp = false; } void unlock() { splock = false; } uintptr_t run() { std::string old; while(on) { lock(); if(old.compare(message)) { csound->message(message.c_str()); old = message; } unlock(); } return 0; } public: PrintThread(csnd::Csound *csound) : Thread(csound), splock(false), on(true), message("") {}; ~PrintThread(){ on = false; join(); } void set_message(const char *m) { lock(); message = m; unlock(); } }; struct TPrint : csnd::Plugin<0, 1> { static constexpr char const *otypes = ""; static constexpr char const *itypes = "S"; PrintThread t; int init() { csound->plugin_deinit(this); csnd::constr(&t, csound); return OK; } int deinit() { csnd::destr(&t); return OK; } int kperf() { t.set_message(inargs.str_data(0).data); return OK; } }; */ #include void csnd::on_load(Csound *csound) { csnd::plugin(csound, "pvstrace", csnd::thread::ik); csnd::plugin(csound, "tvconv", "a", "aaxxii", csnd::thread::ia); } csound-6.10.0/Opcodes/py/000077500000000000000000000000001321653344700151255ustar00rootroot00000000000000csound-6.10.0/Opcodes/py/README000066400000000000000000000012631321653344700160070ustar00rootroot00000000000000PYTHON OPCODES FOR CSOUND By Maurizio Umberto Puxeddu Modified by Michael Gogins for Csound 5 2004 July 24 BEFORE COMPILING To generate the source code for the Python opcodes just run the pycall-gen.py and pyx-gen.py scripts in this directory. NOTES These opcodes require the Python virtual machine to be initialized, which can be done by putting the "pyinit" opcode in the orchestra header. If you write your composition as a Python script in CsoundVST, you can write classes for your composition in that script and embed your Csound orchestras and scores in the script using Python triple quotes ('''). Therefore, the {{ and }} directives are not necessary if you use CsoundVST. csound-6.10.0/Opcodes/py/examples/000077500000000000000000000000001321653344700167435ustar00rootroot00000000000000csound-6.10.0/Opcodes/py/examples/ftedit.orc000066400000000000000000000010131321653344700207220ustar00rootroot00000000000000sr=44100 kr=4410 ksmps=10 nchnls=1 pyinit pyruni {{ from music.gui import ftedit table = csound.ftable(10, 8192, 10, 1) ftedit.edit(table) csound.ievent(1, 0, 5, 8.0, 60, table) }} instr 1 iDuration = p3 iFrequency = cpsoct(p4) iAmplitude = ampdb(p5) iTable = p6 kAmplitude linen iAmplitude, 1, iDuration, 1 aSignal oscil kAmplitude, iFrequency, iTable out aSignal endin csound-6.10.0/Opcodes/py/examples/ftedit.sco000066400000000000000000000000061321653344700207240ustar00rootroot00000000000000f0 10 csound-6.10.0/Opcodes/py/examples/heredoc.orc000066400000000000000000000015151321653344700210630ustar00rootroot00000000000000sr=44100 kr=44100 ksmps=1 nchnls=1 instr 1 k1 line 0, p3, 10 printks {{ Hello there! This should be in a second line. Anyway I didn't mean to write so much useless things. I just want to say that k1 is %f at the moment. Ok now let's not waste more time and resume the performance, ok? Hey!? Oh, one last thing. This #include "dontincludeme.orc" is not a real inclusion directive. This #define M1 #hahahahah# is not a real macro definition. And this $M1 is not a real macro expansion directive. Notice this is also a quite long text. }}, 1, k1 endin instr 2 ; This is not {{ heredoc }} ; The is not a {{ ; multiline ; heredoc }} k1 line 0, p3, 10 printks "This is not {{heredoc}}: %f\\n", 1, k1 endin csound-6.10.0/Opcodes/py/examples/heredoc.sco000066400000000000000000000000201321653344700210520ustar00rootroot00000000000000i1 0 10 i2 0 10 csound-6.10.0/Opcodes/py/examples/ievent.orc000066400000000000000000000012401321653344700207370ustar00rootroot00000000000000sr=44100 kr=4410 ksmps=10 nchnls=2 giSinusoid ftgen 0, 0, 8192, 10, 1 pyinit pyruni {{ import csound from random import random for i in range(800): csound.ievent(1, i * .2, 0.05, 6.8 + random() * 3, 70.0) csound.ievent(1, i * .2, 0.05, 8.8 + random() * 3, 70.0) }} instr 1 iDuration = p3 iFrequency = cpsoct(p4) iAmplitude = ampdb(p5) aAmplitude linseg iAmplitude, iDuration - 0.01, iAmplitude, 0.002 ,0, 1,0 aOutput oscili aAmplitude, iFrequency, giSinusoid outs aOutput, aOutput endin csound-6.10.0/Opcodes/py/examples/ievent.sco000066400000000000000000000000061321653344700207370ustar00rootroot00000000000000f0 60 csound-6.10.0/Opcodes/py/examples/pyassign.orc000066400000000000000000000002621321653344700213050ustar00rootroot00000000000000sr=44100 kr=4410 ksmps=10 nchnls=1 pyinit instr 1 k1 rand 1000 pyassign "a", k1 pyrun "print a" endin csound-6.10.0/Opcodes/py/examples/pyassign.sco000066400000000000000000000000121321653344700212770ustar00rootroot00000000000000i1 0 0.01 csound-6.10.0/Opcodes/py/examples/pycall1.orc000066400000000000000000000007421321653344700210200ustar00rootroot00000000000000sr=44100 kr=4410 ksmps=10 nchnls=1 giSinusoid ftgen 0, 0, 8192, 10, 1 pyinit pyruni {{ import random pool = [(1 + i/10.0) ** 1.2 for i in range(100)] def get_number_from_pool(n, p): if random.random() < p: i = int(random.random() * len(pool)) pool[i] = n return random.choice(pool) }} instr 1 k1 oscil 1, 3, giSinusoid k2 pycall1 "get_number_from_pool", k1 + 2, p4 printk 0.01, k2 endin csound-6.10.0/Opcodes/py/examples/pycall1.sco000066400000000000000000000000151321653344700210120ustar00rootroot00000000000000i1 0 10 0.01 csound-6.10.0/Opcodes/py/examples/pycall2.orc000066400000000000000000000011761321653344700210230ustar00rootroot00000000000000sr=44100 kr=4410 ksmps=10 nchnls=1 giSinusoid ftgen 0, 0, 8192, 10, 1 pyinit pyruni {{ import random class GetNumberFromPool: def __init__(self, e=1.2, a=1.0, f=0.1, N=100): self.pool = [(a + i*f) ** e for i in range(N)] def __call__(self, n, p): if random.random() < p: i = int(random.random() * len(self.pool)) self.pool[i] = n return random.choice(self.pool) get_number_from_pool = GetNumberFromPool() }} instr 1 k1 oscil 1, 3, giSinusoid k2 pycall1 "get_number_from_pool", k1 + 2, p4 printk 0.01, k2 endin csound-6.10.0/Opcodes/py/examples/pycall2.sco000066400000000000000000000000151321653344700210130ustar00rootroot00000000000000i1 0 10 0.01 csound-6.10.0/Opcodes/py/examples/pycall3.orc000066400000000000000000000030061321653344700210160ustar00rootroot00000000000000sr=44100 kr=4410 ksmps=10 nchnls=1 pyinit pyruni {{ def f0(a, b, c, d, e, f, g, h): pass def f1(a, b, c, d, e, f, g, h): return a def f2(a, b, c, d, e, f, g, h): return a, b def f3(a, b, c, d, e, f, g, h): return a, b, c def f4(a, b, c, d, e, f, g, h): return a, b, c, d def f5(a, b, c, d, e, f, g, h): return a, b, c, d, e def f6(a, b, c, d, e, f, g, h): return a, b, c, d, e, f def f7(a, b, c, d, e, f, g, h): return a, b, c, d, e, f, g def f8(a, b, c, d, e, f, g, h): return a, b, c, d, e, f, g, h }} instr 1 pycall "f0", 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8 k1 pycall1 "f1", 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8 k1, k2 pycall2 "f2", 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8 k1, k2, k3 pycall3 "f3", 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8 k1, k2, k3, k4 pycall4 "f4", 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8 k1, k2, k3, k4, k5 pycall5 "f5", 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8 k1, k2, k3, k4, k5, k6 pycall6 "f6", 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8 k1, k2, k3, k4, k5, k6, k7 pycall7 "f7", 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8 k1, k2, k3, k4, k5, k6, k7, k8 pycall8 "f8", 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8 printk 0.01, k1 printk 0.01, k2 printk 0.01, k3 printk 0.01, k4 printk 0.01, k5 printk 0.01, k6 printk 0.01, k7 printk 0.01, k8 endin csound-6.10.0/Opcodes/py/examples/pycall3.sco000066400000000000000000000000111321653344700210100ustar00rootroot00000000000000i1 0 0.1 csound-6.10.0/Opcodes/py/examples/pycallt.orc000066400000000000000000000041231321653344700211200ustar00rootroot00000000000000sr=44100 kr=4410 ksmps=10 nchnls=1 pyinit pyruni {{ def f0(a, b, c, d, e, f, g, h): print 'f0 got', a, b, c, d, e, f, g, h print 'f0 returning None' def f1(a, b, c, d, e, f, g, h): print 'f1 got', a, b, c, d, e, f, g, h print 'f1 returning', a return a def f2(a, b, c, d, e, f, g, h): print 'f2 got', a, b, c, d, e, f, g, h print 'f2 returning', a, b return a, b def f3(a, b, c, d, e, f, g, h): print 'f3 got', a, b, c, d, e, f, g, h print 'f3 returning', a, b, c return a, b, c def f4(a, b, c, d, e, f, g, h): print 'f4 got', a, b, c, d, e, f, g, h print 'f4 returning', a, b, c, d return a, b, c, d def f5(a, b, c, d, e, f, g, h): print 'f5 got', a, b, c, d, e, f, g, h print 'f5 returning', a, b, c, d, e return a, b, c, d, e def f6(a, b, c, d, e, f, g, h): print 'f6 got', a, b, c, d, e, f, g, h print 'f6 returning', a, b, c, d, e, f return a, b, c, d, e, f def f7(a, b, c, d, e, f, g, h): print 'f7 got', a, b, c, d, e, f, g, h print 'f7 returning', a, b, c, d, e, f, g return a, b, c, d, e, f, g def f8(a, b, c, d, e, f, g, h): print 'f8 got', a, b, c, d, e, f, g, h print 'f8 returning', a, b, c, d, e, f, g, h return a, b, c, d, e, f, g, h }} instr 1 kt metro 1.5 pycallt kt, "f0", 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8 k1 pycall1t kt, "f1", 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8 k1, k2 pycall2t kt, "f2", 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8 k1, k2, k3 pycall3t kt, "f3", 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8 k1, k2, k3, k4 pycall4t kt, "f4", 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8 k1, k2, k3, k4, k5 pycall5t kt, "f5", 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8 k1, k2, k3, k4, k5, k6 pycall6t kt, "f6", 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8 k1, k2, k3, k4, k5, k6, k7 pycall7t kt, "f7", 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8 k1, k2, k3, k4, k5, k6, k7, k8 pycall8t kt, "f8", 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8 endin csound-6.10.0/Opcodes/py/examples/pycallt.sco000066400000000000000000000000101321653344700211100ustar00rootroot00000000000000i1 0 10 csound-6.10.0/Opcodes/py/examples/pyeval.orc000066400000000000000000000003231321653344700207460ustar00rootroot00000000000000sr=44100 kr=4410 ksmps=10 nchnls=1 pyinit pyruni "from random import random" instr 1 pyrun "a = random()" k1 pyeval "a" printk 0.1, k1 endin csound-6.10.0/Opcodes/py/examples/pyeval.sco000066400000000000000000000000111321653344700207410ustar00rootroot00000000000000i1 0 0.5 csound-6.10.0/Opcodes/py/examples/pyexec.orc000066400000000000000000000003621321653344700207460ustar00rootroot00000000000000sr=44100 kr=4410 ksmps=10 nchnls=1 pyinit pyruni "import random" pyexeci "pyexec1.py" instr 1 pyexec "pyexec2.py" pylexeci "pyexec3.py" pylexec "pyexec4.py" endin csound-6.10.0/Opcodes/py/examples/pyexec.sco000066400000000000000000000000241321653344700207420ustar00rootroot00000000000000i1 0 0.01 i1 0 0.01 csound-6.10.0/Opcodes/py/examples/pyexec1.py000066400000000000000000000002711321653344700206730ustar00rootroot00000000000000import time, os print print "Welcome to Csound!" try: s = ', %s?' % os.getenv('USER') except: s = '?' print 'What sound do you want to hear today%s' % s answer = raw_input() csound-6.10.0/Opcodes/py/examples/pyexec2.py000066400000000000000000000000451321653344700206730ustar00rootroot00000000000000print 'your answer is "%s"' % answer csound-6.10.0/Opcodes/py/examples/pyexec3.py000066400000000000000000000000721321653344700206740ustar00rootroot00000000000000message = 'a private random number: %f' % random.random() csound-6.10.0/Opcodes/py/examples/pyexec4.py000066400000000000000000000000161321653344700206730ustar00rootroot00000000000000print message csound-6.10.0/Opcodes/py/examples/pyexect.orc000066400000000000000000000010231321653344700211250ustar00rootroot00000000000000sr=44100 kr=4410 ksmps=10 nchnls=1 pyinit instr 1 ktrigger1 metro 3 ktrigger2 metro 6 ktrigger3 metro 10 ktrigger4 metro 0.5 pyexect ktrigger1, "pyexect1.py" pyexect ktrigger2, "pyexect2.py" pyexect ktrigger3, "pyexect3.py" pylexect ktrigger3 + ktrigger1, "pyexect4.py" a1 rand 5000 out a1 endin csound-6.10.0/Opcodes/py/examples/pyexect.sco000066400000000000000000000000161321653344700211270ustar00rootroot00000000000000i1 0 5 i1 0 5 csound-6.10.0/Opcodes/py/examples/pyexect1.py000066400000000000000000000000141321653344700210520ustar00rootroot00000000000000print 'zum' csound-6.10.0/Opcodes/py/examples/pyexect2.py000066400000000000000000000000131321653344700210520ustar00rootroot00000000000000print 'pa' csound-6.10.0/Opcodes/py/examples/pyexect3.py000066400000000000000000000000131321653344700210530ustar00rootroot00000000000000print 'zi' csound-6.10.0/Opcodes/py/examples/pyexect4.py000066400000000000000000000000141321653344700210550ustar00rootroot00000000000000print 'zut' csound-6.10.0/Opcodes/py/examples/pyrun.csd000066400000000000000000000012431321653344700206130ustar00rootroot00000000000000 csound -opyrun.wav temp.orc temp.sco sr=44100 kr=4410 ksmps=10 nchnls=1 pyinit pyruni "import random" instr 1 ; This message is stored in the main namespace ; and is the same for every instance pyruni "message = 'a global random number: %f' % random.random()" pyrun "print message" ; This message is stored in the private namespace ; and is different for different instances pylruni "message = 'a private random number: %f' % random.random()" pylrun "print message" endin i1 0 0.1 csound-6.10.0/Opcodes/py/examples/pyrun.orc000066400000000000000000000007741321653344700206350ustar00rootroot00000000000000sr=44100 kr=4410 ksmps=10 nchnls=1 pyinit pyruni "import random" instr 1 ; This message is stored in the main namespace ; and is the same for every instance pyruni "message = 'a global random number: %f' % random.random()" pyrun "print message" ; This message is stored in the private namespace ; and is different for different instances pylruni "message = 'a private random number: %f' % random.random()" pylrun "print message" endin csound-6.10.0/Opcodes/py/examples/pyrun.sco000066400000000000000000000000111321653344700206160ustar00rootroot00000000000000i1 0 0.1 csound-6.10.0/Opcodes/py/examples/pyrunt.orc000066400000000000000000000007451321653344700210170ustar00rootroot00000000000000sr=44100 kr=4410 ksmps=10 nchnls=1 pyinit instr 1 ktrigger1 metro 3 ktrigger2 metro 6 ktrigger3 metro 10 pyrunt ktrigger1, "print 'zum'" pyrunt ktrigger2, "print 'pa'" pyrunt ktrigger3, "print 'zi'" pylrunt ktrigger3 + ktrigger1, "print 'zut'" a1 rand 5000 out a1 endin csound-6.10.0/Opcodes/py/examples/pyrunt.sco000066400000000000000000000000161321653344700210070ustar00rootroot00000000000000i1 0 5 i1 0 5 csound-6.10.0/Opcodes/py/index.html000066400000000000000000000545641321653344700171400ustar00rootroot00000000000000 PyCsound Manual [DRAFT]

Python Opcodes for Csound

Copyright © 2002 by Maurizio Umberto Puxeddu. All rights reserved.

Portions copyright © 2004 by Michael Gogins

This document has been updated Sunday 25 July 2004 by Michael Gogins.

Table of Contents

Opcodes

This section describes the Csound opcodes related to Python.

Using the Python opcode family, you can interact with a Python interpreter embedded in Csound in five ways:

  1. Run a statement (run).

  2. Execute a script (exec).

  3. Invoke a callable and pass arguments (call).

  4. Evaluate an expression (eval).

  5. Change the value of a Python object, possibly creating a new Python object (assign).

Since you can do these things...

  • At i-time or at k-time,

  • In the global Python namespace, or in a namespace specific to an individual instance of a Csound instrument,

  • And can you can retrieve from 0 to 8 return values from callables that accept N parameters...

...this means that there are many Python-related opcodes. But all of these opcodes share the same py prefix, and have a regular naming scheme:

"py" + [optional context prefix] + [action name] + [optional x-time prefix]    

Orchestra Syntax

Blocks of Python code, and indeed entire scripts, can be embedded in Csound orchestras using the {{ and }} directives to enclose the script, as follows:

sr=44100
kr=4410
ksmps=10
nchnls=1
pyinit

giSinusoid	ftgen	0,	0, 8192, 10,	1

pyruni {{
import random

pool = [(1 + i/10.0) ** 1.2 for i in range(100)]

def get_number_from_pool(n, p):
    if random.random() < p:
        i = int(random.random() * len(pool))
        pool[i] = n
    return random.choice(pool)
}}

instr 1
	k1	oscil	1, 3, giSinusoid	
	k2	pycall1	"get_number_from_pool", k1 + 2, p4
		printk	0.01, k2
endin



pyinit Opcode

pyinit

In the command-line version of Csound, you must first invoke the pyinit opcode in the orchestra header to initialize the Python interpreter, before using any of the other Python opcodes.

But if you use the Python opcodes in the CsoundVST version of Csound, you should not invoke pyinit, because CsoundVST automatically initializes the Python interpreter for you. In addition, CsoundVST automatically creates a Python interface to the Csound API, in the form a global instance of the CsoundVST.CppSound class named csound. Therefore, Python code written in the Csound orchestra has access to the global csound object.

Run Opcodes

pyrun   "statement"
pyruni  "statement"

pylrun  "statememt"
pylruni "statement"      

Execute the specified Python statement at k-time (pyrun and pylrun) or i-time (pyruni and pylruni).

The statement is executed in the global environment for pyrun and pyruni or the local environment for pylrun and pylruni..

These opcodes perform no message passing. However, since the statement have access to the main namespace and the private namespace, it can interact with objects previously created in that environment.

The "local" version of the "run" opcodes are useful when the code ran by different instances of an instrument should not interact.

Example 1. Example of the RUN opcode group

Orchestra:

sr=44100
kr=4410
ksmps=10
nchnls=1

pyruni "import random"

instr 1
        ; This message is stored in the main namespace
        ; and is the same for every instance
        pyruni  "message = 'a global random number: %f' % random.random()"
        pyrun   "print message"

        ; This message is stored in the private namespace
        ; and is different for different instances
        pylruni "message = 'a private random number: %f' % random.random()"
        pylrun  "print message"

endin

Score:

i1 0 0.1

Running this score you should get intermixed pairs of messages from the two instances of instrument 1.

The first message of each pair is stored into the main namespace and so the second instance overwrites the message of the first instance. The result is that first message will be the same for both instances.

The second message is different for the two instances, being stored in the private namespace.

Exec Opcodes

pyexec    "filename"
pyexeci   "filename"
pylexec   "filename"
pylexeci  "filename"
pyexect   ktrigger, "filename"
pylexec   ktrigger, "filename"      

Execute a script from a file at k-time or i-time (i suffix).

This is not the same as calling the script with the system() call, since the code is executed by the embedded interpreter.

The code contained in the specified file is executed in the global environment for opcodes pyexec and pyexeci and in the private environment for the opcodes pylexec and pylexeci.

These opcodes perform no message passing. However, since the statement have access to the main namespace and the private namespace, it can interact with objects previously created in that environment.

The "local" version of the "exec" opcodes are useful when the code ran by different instances of an instrument should not interact.

Example 2. Example of the EXEC opcode group

Orchestra (pyexec.orc):

sr=44100
kr=4410
ksmps=10
nchnls=1

        pyruni "import random"

        pyexeci "pyexec1.py"

instr 1

        pyexec          "pyexec2.py"

        pylexeci        "pyexec3.py"
        pylexec         "pyexec4.py"

endin

Score (pyexec.sco):

i1 0 0.01
i1 0 0.01

The pyexec1.py script:

import time, os

print
print "Welcome to Csound!"

try:
    s = ', %s?' % os.getenv('USER')
except:
    s = '?'

print 'What sound do you want to hear today%s' % s
answer = raw_input()

The pyexec2.py script:

print 'your answer is "%s"' % answer

The pyexec3.py script:

message = 'a private random number: %f' % random.random()

The pyexec4.py script:

print message

If I run this example on my machine I get something like:

Using ../../csound.xmg
Csound Version 4.19 (Mar 23 2002)
Embedded Python interpreter version 2.2
orchname:  pyexec.orc
scorename: pyexec.sco
sorting score ...
        ... done
orch compiler:
11 lines read
        instr   1       
Csound Version 4.19 (Mar 23 2002)
displays suppressed

Welcome to Csound!
What sound do you want to hear today, maurizio?

then I answer

damn you

then Csound continues with the normal performance

your answer is "damn you"
a private random number: 0.884006
new alloc for instr 1:
your answer is "damn you"
a private random number: 0.884006
your answer is "damn you"
a private random number: 0.889868
your answer is "damn you"
a private random number: 0.884006
your answer is "damn you"
a private random number: 0.889868
your answer is "damn you"
a private random number: 0.884006
your answer is "damn you"
...

Embarassing.

In the same instrument a message is created in the private namespace and printed, appearing different for each instance.

Call Opcodes

                                        pycall   "callable", karg1, ...
kresult                                 pycall1  "callable", karg1, ...
kresult1, kresult2                      pycall2  "callable", karg1, ...
kr1, kr2, kr3                           pycall3  "callable", karg1, ...
kr1, kr2, kr3, kr4                      pycall4  "callable", karg1, ...
kr1, kr2, kr3, kr4, kr5                 pycall5  "callable", karg1, ...
kr1, kr2, kr3, kr4, kr5, kr6            pycall6  "callable", karg1, ...
kr1, kr2, kr3, kr4, kr5, kr6, kr7       pycall7  "callable", karg1, ...
kr1, kr2, kr3, kr4, kr5, kr6, kr7, kr8  pycall8  "callable", karg1, ...

                                        pycallt   ktrigger, "callable", karg1, ...
kresult                                 pycall1t  ktrigger, "callable", karg1, ...
kresult1, kresult2                      pycall2t  ktrigger, "callable", karg1, ...
kr1, kr2, kr3                           pycall3t  ktrigger, "callable", karg1, ...
kr1, kr2, kr3, kr4                      pycall4t  ktrigger, "callable", karg1, ...
kr1, kr2, kr3, kr4, kr5                 pycall5t  ktrigger, "callable", karg1, ...
kr1, kr2, kr3, kr4, kr5, kr6            pycall6t  ktrigger, "callable", karg1, ...
kr1, kr2, kr3, kr4, kr5, kr6, kr7       pycall7t  ktrigger, "callable", karg1, ...
kr1, kr2, kr3, kr4, kr5, kr6, kr7, kr8  pycall8t  ktrigger, "callable", karg1, ...

                                        pycalli   "callable", karg1, ...
iresult                                 pycall1i  "callable", iarg1, ...
iresult1, iresult2                      pycall2i  "callable", iarg1, ...
ir1, ir2, ir3                           pycall3i  "callable", iarg1, ...
ir1, ir2, ir3, ir4                      pycall4i  "callable", iarg1, ...
ir1, ir2, ir3, ir4, ir5                 pycall5i  "callable", iarg1, ...
ir1, ir2, ir3, ir4, ir5, ir6            pycall6i  "callable", iarg1, ...
ir1, ir2, ir3, ir4, ir5, ir6, ir7       pycall7i  "callable", iarg1, ...
ir1, ir2, ir3, ir4, ir5, ir6, ir7, ir8  pycall8i  "callable", iarg1, ...

pycalln   "callable", nresults, kresult1, ..., kresultn, karg1, ...
pycallni  "callable", nresults, iresult1, ..., iresultn, iarg1,  ...

                                        pylcall   "callable", karg1, ...
kresult                                 pylcall1  "callable", karg1, ...
kresult1, kresult2                      pylcall2  "callable", karg1, ...
kr1, kr2, kr3                           pylcall3  "callable", karg1, ...
kr1, kr2, kr3, kr4                      pylcall4  "callable", karg1, ...
kr1, kr2, kr3, kr4, kr5                 pylcall5  "callable", karg1, ...
kr1, kr2, kr3, kr4, kr5, kr6            pylcall6  "callable", karg1, ...
kr1, kr2, kr3, kr4, kr5, kr6, kr7       pylcall7  "callable", karg1, ...
kr1, kr2, kr3, kr4, kr5, kr6, kr7, kr8  pylcall8   "callable", karg1, ...

                                        pylcallt   ktrigger, "callable", karg1, ...
kresult                                 pylcall1t  ktrigger, "callable", karg1, ...
kresult1, kresult2                      pylcall2t  ktrigger, "callable", karg1, ...
kr1, kr2, kr3                           pylcall3t  ktrigger, "callable", karg1, ...
kr1, kr2, kr3, kr4                      pylcall4t  ktrigger, "callable", karg1, ...
kr1, kr2, kr3, kr4, kr5                 pylcall5t  ktrigger, "callable", karg1, ...
kr1, kr2, kr3, kr4, kr5, kr6            pylcall6t  ktrigger, "callable", karg1, ...
kr1, kr2, kr3, kr4, kr5, kr6, kr7       pylcall7t  ktrigger, "callable", karg1, ...
kr1, kr2, kr3, kr4, kr5, kr6, kr7, kr8  pylcall8t  ktrigger, "callable", karg1, ...

                                        pylcalli   "callable", karg1, ...
iresult                                 pylcall1i  "callable", iarg1, ...
iresult1, iresult2                      pylcall2i  "callable", iarg1, ...
ir1, ir2, ir3                           pylcall3i  "callable", iarg1, ...
ir1, ir2, ir3, ir4                      pylcall4i  "callable", iarg1, ...
ir1, ir2, ir3, ir4, ir5                 pylcall5i  "callable", iarg1, ...
ir1, ir2, ir3, ir4, ir5, ir6            pylcall6i  "callable", iarg1, ...
ir1, ir2, ir3, ir4, ir5, ir6, ir7       pylcall7i  "callable", iarg1, ...
ir1, ir2, ir3, ir4, ir5, ir6, ir7, ir8  pylcall8i  "callable", iarg1, ...

pylcalln   "callable", nresults, kresult1, ..., kresultn, karg1, ...
pylcallni  "callable", nresults, iresult1, ..., iresultn, iarg1, ...      

This family of opcodes call the specified Python callable at k-time and i-time (i suffix), passing the given arguments. The call is perfomed in the global environment and the result (the returning value) is copied into the Csound output variables specified.

They pass any number of parameters which are cast to float inside the Python interpreter.

The pycall/pycalli, pycall1/pycall1i ... pycall8/pycall8i opcodes can accomodate for a number of results ranging from 0 to 8 according to their numerical prefix (0 is omitted).

The pycalln/pycallni opcodes can accomodate for any number of results: the callable name is followed by the number of output arguments, then come the list of Csound output variable and the list of parameters to be passed.

The returning value of the callable must be None for pycall or pycalli, a float for pycall1i or pycall1i and a tuple (with proper size) of floats for the pycall2/pycall2i ... pycall8/pycall8i and pycalln/pycallni opcodes.

Example 3. Calling a C or Python function

Supposing we have previously defined or imported a function named effe as

from random import random, choice

# a pool of 100 numbers
pool = [i ** 1.3 for i in range(100)]

def get_number_from_pool(n, p):
    # substitute an old number with the new number?
    if random() < p:
        i = choice(range(len(pool)))
        pool[i] = n

    # return a random number from the pool
    return choice(pool)        

then the following orchestra code

k2   pycall1 "get_number_from_pool", k1, p6        

would set k2 randomly from a pool of numbers changing in time. You can pass new pools elements and control the change rate from the orchestra.

Example 4. Calling a function-object

A more generic implementation of the previous example makes use of a simple function object.

from random import random, choice

class GetNumberFromPool:
    def __init__(self, e, begin=0, end=100, step=1):
        self.pool = [i ** e for i in range(begin, end, step)]

    def __call__(self, n, p):
        # substitute an old number with the new number?
        if random() < p:
            i = choice(range(len(pool)))
            pool[i] = n

        # return a random number from the pool
        return choice(pool)

get_number_from_pool1 = GetNumberFromPool(1.3)
get_number_from_pool2 = GetNumberFromPool(1.5, 50, 250, 2)        

then the following orchestra code

k2   pycall1 "get_number_from_pool1", k1, p6
k4   pycall1 "get_number_from_pool2", k3, p7        

would set k2 and k3 randomly from a pool of numbers changing in time. You can pass new pools elements (here k1 and k3) and control the change rate (here p6 and p7) from the orchestra.

As you can see in the first snippet, you can customize the initialization of the pool as well as create several pool.

Eval Opcodes

kresult  pyeval    "expression"
iresult  pyevali   "expression"
kresult  pyleval   "expression"
iresult  pylevali  "expression"
kresult  pyevalt   ktrigger, "expression"
kresult  pylevalt  ktrigger, "expression"      

These opcodes evaluate a generic Python expression and store the result in a Csound variable at k-time or i-time (i suffix).

The expression must evaluate in a float or an object that can be cast to a float.

They can be used effectively to trasfer data from a Python object into a Csound variable.

Example 5. Retrieving a Python variable value

The code

k1           pyeval      "v1"        

will copy the content of the Python variable v1 into the Csound variable k1 at each k-time.

Assign Opcodes

pyassign    "variable", kvalue
pyassigni   "variable", ivalue
pylassign   "variable", kvalue
pylassigni  "variable", ivalue
pyassignt   ktrigger, "variable", kvalue
pylassignt  ktrigger, "variable", kvalue      

Assign the value of the given Csound variable to a Python variable possibly destroying its previous content.

The resulting Python object will be a float.

To Do

  1. Debug memory leaks.

  2. Optimize for speed.

Bibliography

Guido van Rossum, Python Tutorial.

Guido van Rossum, Python Library Reference.

Guido van Rossum, Extending and Embedding the Python Interpreter.

Guido van Rossum, Python/C API Reference Manual.


csound-6.10.0/Opcodes/py/pycall-gen.py000066400000000000000000000156651321653344700175470ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (C) 2002 Maurizio Umberto Puxeddu # This file is part of Csound. # The Csound Library is free software; you can redistribute it # and/or modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # Csound is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with Csound; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # 02111-1307 USA '''Automatically generate opcode structures, methods [and table entries]. Just run it.''' def generate_pycall_common_init_code(f, n, pre, post, rate, triggered=0): if triggered: t, T = 't', 'T' else: t, T = '', '' name = 'py%scall%d%s%s_%srate' % (pre, n, post, t, rate) print >> f, 'static int %s(CSOUND *csound, PYCALL%d%s *p)' % (name, n, T) print >> f, '{' print >> f, ' char command[1024];' print >> f, ' PyObject *result;' print >> f, ' int *py_initialize_done;' print >> f, ' if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL ||*py_initialize_done == 0)' print >> f, ' return NOTOK;' print >> f if triggered: print >> f, ' if (!*p->trigger) {' if n == 0: pass if n == 1: print >> f, ' *p->result = p->oresult;' elif n > 1: for i in range(n): print >> f, ' *p->result%d = p->oresult%d;' % (i+1, i+1) print >> f, ' return OK;' print >> f, ' }' print >> f def generate_pycall_common_call_code(f, context, withinit, triggered): if triggered: skip = 2 else: skip = 1 print >> f, ' format_call_statement(command, (char*) p->function->data,' print >> f, ' p->INOCOUNT, p->args, %d);' % skip print >> f if context == 'private': print >> f, ' result = eval_string_in_given_context(command, 0);' else: if withinit: print >> f, ' create_private_namespace_if_needed(&p->h);' print >> f print >> f, ' result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead));' print >> f def generate_pycall_exception_handling_code(f, n, pre, post, rate, triggered=0): print >> f, ' if (result == NULL)' print >> f, ' return pyErrMsg(p, "python exception");' print >> f def generate_pycall_result_conversion_code(f, n, pre, post, rate, triggered=0): if triggered: t, T = 't', 'T' else: t, T = '', '' if n == 0: print >> f, ' if (result != Py_None)' print >> f, ' return errMsg(p, "callable must return None");' elif n == 1: print >> f, ' if (!PyFloat_Check(result)) {' print >> f, ' return errMsg(p, "callable must return a float");' print >> f, ' }' print >> f, ' else {' print >> f, ' *p->result = PyFloat_AsDouble(result);' if triggered: print >> f, ' p->oresult = *p->result;' print >> f, ' }' print >> f, ' return OK;' else: name = 'py%scall%d%s%s_%srate' % (pre, n, post, t, rate) print >> f, ' if (!PyTuple_Check(result) || PyTuple_Size(result) != %d) {' % n print >> f, ' return errMsg(p, "callable must return %d values");' % n print >> f, ' }' print >> f, ' else {' for i in range(n): print >> f, ' *p->result%d = PyFloat_AsDouble(PyTuple_GET_ITEM(result, %d));' % (i+1, i) if triggered: print >> f, ' p->oresult%d = *p->result%d;' % (i+1, i+1) print >> f, ' }' print >> f print >> f, ' Py_DECREF(result);' print >> f, ' return OK;' print >> f, '}' print >> f def generate_pycall_krate_method(f, n, triggered=0): generate_pycall_common_init_code(f, n, '', '', 'k', triggered) generate_pycall_common_call_code(f, 'private', 1, triggered) generate_pycall_exception_handling_code(f, n, '', '', 'k', triggered) generate_pycall_result_conversion_code(f, n, '', '', 'k', triggered) def generate_pylcall_irate_method(f, n, triggered=0): if triggered: t, T = 't', 'T' else: t, T = '', '' name = 'pylcall%d%s_irate' % (n, t) print >> f, 'static int %s(CSOUND *csound, PYCALL%d%s *p)' % (name, n, T) print >> f, '{' print >> f, ' int *py_initialize_done;' print >> f, ' if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL ||*py_initialize_done == 0)' print >> f, ' return NOTOK;' print >> f, ' create_private_namespace_if_needed(&p->h);' print >> f, ' return OK;' print >> f, '}' print >> f def generate_pylcall_krate_method(f, n, triggered=0): generate_pycall_common_init_code(f, n, 'l', '', 'k', triggered) generate_pycall_common_call_code(f, 'global', 0, triggered) generate_pycall_exception_handling_code(f, n, 'l', '', 'k', triggered) generate_pycall_result_conversion_code(f, n, 'l', '', 'k', triggered) def generate_pylcalli_irate_method(f, n): generate_pycall_common_init_code(f, n, 'l', 'i', 'i') generate_pycall_common_call_code(f, 'global', 1, 0) generate_pycall_exception_handling_code(f, n, 'l', 'i', 'i') generate_pycall_result_conversion_code(f, n, 'l', 'i', 'i') # ---------- def generate_pycall_opcode_struct(f, n, triggered=0): if triggered: T = 'T' else: T = '' print >> f, 'typedef struct {' print >> f, ' OPDS h;' if n == 1: print >> f, ' MYFLT *result;' else: for i in range(n): print >> f, ' MYFLT *result%d;' % (i+1) if triggered: print >> f, ' MYFLT *trigger;' print >> f, ' STRINGDAT *function;' print >> f, ' MYFLT *args[VARGMAX-3];' if triggered: if n == 1: print >> f, ' MYFLT oresult;' else: for i in range(n): print >> f, ' MYFLT oresult%d;' % (i+1) print >> f, '} PYCALL%d%s;' % (n, T) print >> f # -------- f = open('pycall.auto.c', 'w') print >> f for n in range(9): generate_pycall_krate_method(f, n) generate_pylcall_irate_method(f, n) generate_pylcall_krate_method(f, n) generate_pylcalli_irate_method(f, n) generate_pycall_krate_method(f, n, 1) generate_pylcall_irate_method(f, n, 1) generate_pylcall_krate_method(f, n, 1) f.close() f = open('pycall.auto.h', 'w') print >> f for n in range(9): generate_pycall_opcode_struct(f, n) generate_pycall_opcode_struct(f, n, 1) f.close() csound-6.10.0/Opcodes/py/pycall.auto.c000066400000000000000000001642401321653344700175330ustar00rootroot00000000000000/* * pycall.auto.c * * Copyright (C) 2002 Maurizio Umberto Puxeddu, Michael Gogins * * This software is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ static int pycall0_krate(CSOUND *csound, PYCALL0 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); result = eval_string_in_given_context(command, 0); if (result == NULL) return pyErrMsg(p, "python exception"); if (result != Py_None) return errMsg(p, "callable must return None"); Py_DECREF(result); return OK; } static int pylcall0_irate(CSOUND *csound, PYCALL0 *p) { int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pylcall0_krate(CSOUND *csound, PYCALL0 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(result != Py_None)) return errMsg(p, "callable must return None"); Py_DECREF(result); return OK; } static int pylcall0i_irate(CSOUND *csound, PYCALL0 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); create_private_namespace_if_needed(&p->h); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(result != Py_None)) return errMsg(p, "callable must return None"); Py_DECREF(result); return OK; } static int pycall0t_krate(CSOUND *csound, PYCALL0T *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; if (!*p->trigger) { return OK; } format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 2); result = eval_string_in_given_context(command, 0); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(result != Py_None)) return errMsg(p, "callable must return None"); Py_DECREF(result); return OK; } static int pylcall0t_irate(CSOUND *csound, PYCALL0T *p) { int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pylcall0t_krate(CSOUND *csound, PYCALL0T *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; if (!*p->trigger) { return OK; } format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 2); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(result != Py_None)) return errMsg(p, "callable must return None"); Py_DECREF(result); return OK; } static int pycall1_krate(CSOUND *csound, PYCALL1 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); result = eval_string_in_given_context(command, 0); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyFloat_Check(result))) { return errMsg(p, "callable must return a float"); } else { *p->result = PyFloat_AsDouble(result); } return OK; Py_DECREF(result); return OK; } static int pylcall1_irate(CSOUND *csound, PYCALL1 *p) { create_private_namespace_if_needed(&p->h); return OK; } static int pylcall1_krate(CSOUND *csound, PYCALL1 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyFloat_Check(result))) { return errMsg(p, "callable must return a float"); } else { *p->result = PyFloat_AsDouble(result); } return OK; Py_DECREF(result); return OK; } static int pylcall1i_irate(CSOUND *csound, PYCALL1 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); create_private_namespace_if_needed(&p->h); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyFloat_Check(result))) { return errMsg(p, "callable must return a float"); } else { *p->result = PyFloat_AsDouble(result); } return OK; Py_DECREF(result); return OK; } static int pycall1t_krate(CSOUND *csound, PYCALL1T *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; if (!*p->trigger) { *p->result = p->oresult; return OK; } format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 2); result = eval_string_in_given_context(command, 0); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyFloat_Check(result))) { return errMsg(p, "callable must return a float"); } else { *p->result = PyFloat_AsDouble(result); p->oresult = *p->result; } return OK; Py_DECREF(result); return OK; } static int pylcall1t_irate(CSOUND *csound, PYCALL1T *p) { int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pylcall1t_krate(CSOUND *csound, PYCALL1T *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; if (!*p->trigger) { *p->result = p->oresult; return OK; } format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 2); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyFloat_Check(result))) { return errMsg(p, "callable must return a float"); } else { *p->result = PyFloat_AsDouble(result); p->oresult = *p->result; } return OK; Py_DECREF(result); return OK; } static int pycall2_krate(CSOUND *csound, PYCALL2 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); result = eval_string_in_given_context(command, 0); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 2)) { return errMsg(p, "callable must return 2 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); } Py_DECREF(result); return OK; } static int pylcall2_irate(CSOUND *csound, PYCALL2 *p) { int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pylcall2_krate(CSOUND *csound, PYCALL2 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 2)) { return errMsg(p, "callable must return 2 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); } Py_DECREF(result); return OK; } static int pylcall2i_irate(CSOUND *csound, PYCALL2 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); create_private_namespace_if_needed(&p->h); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 2)) { return errMsg(p, "callable must return 2 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); } Py_DECREF(result); return OK; } static int pycall2t_krate(CSOUND *csound, PYCALL2T *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; if (!*p->trigger) { *p->result1 = p->oresult1; *p->result2 = p->oresult2; return OK; } format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 2); result = eval_string_in_given_context(command, 0); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 2)) { return errMsg(p, "callable must return 2 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); p->oresult1 = *p->result1; *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); p->oresult2 = *p->result2; } Py_DECREF(result); return OK; } static int pylcall2t_irate(CSOUND *csound, PYCALL2T *p) { int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pylcall2t_krate(CSOUND *csound, PYCALL2T *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; if (!*p->trigger) { *p->result1 = p->oresult1; *p->result2 = p->oresult2; return OK; } format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 2); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 2)) { return errMsg(p, "callable must return 2 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); p->oresult1 = *p->result1; *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); p->oresult2 = *p->result2; } Py_DECREF(result); return OK; } static int pycall3_krate(CSOUND *csound, PYCALL3 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); result = eval_string_in_given_context(command, 0); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 3)) { return errMsg(p, "callable must return 3 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); } Py_DECREF(result); return OK; } static int pylcall3_irate(CSOUND *csound, PYCALL3 *p) { int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pylcall3_krate(CSOUND *csound, PYCALL3 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 3)) { return errMsg(p, "callable must return 3 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); } Py_DECREF(result); return OK; } static int pylcall3i_irate(CSOUND *csound, PYCALL3 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); create_private_namespace_if_needed(&p->h); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 3)) { return errMsg(p, "callable must return 3 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); } Py_DECREF(result); return OK; } static int pycall3t_krate(CSOUND *csound, PYCALL3T *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; if (!*p->trigger) { *p->result1 = p->oresult1; *p->result2 = p->oresult2; *p->result3 = p->oresult3; return OK; } format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 2); result = eval_string_in_given_context(command, 0); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 3)) { return errMsg(p, "callable must return 3 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); p->oresult1 = *p->result1; *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); p->oresult2 = *p->result2; *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); p->oresult3 = *p->result3; } Py_DECREF(result); return OK; } static int pylcall3t_irate(CSOUND *csound, PYCALL3T *p) { int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pylcall3t_krate(CSOUND *csound, PYCALL3T *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; if (!*p->trigger) { *p->result1 = p->oresult1; *p->result2 = p->oresult2; *p->result3 = p->oresult3; return OK; } format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 2); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 3)) { return errMsg(p, "callable must return 3 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); p->oresult1 = *p->result1; *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); p->oresult2 = *p->result2; *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); p->oresult3 = *p->result3; } Py_DECREF(result); return OK; } static int pycall4_krate(CSOUND *csound, PYCALL4 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); result = eval_string_in_given_context(command, 0); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 4)) { return errMsg(p, "callable must return 4 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); } Py_DECREF(result); return OK; } static int pylcall4_irate(CSOUND *csound, PYCALL4 *p) { int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pylcall4_krate(CSOUND *csound, PYCALL4 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 4)) { return errMsg(p, "callable must return 4 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); } Py_DECREF(result); return OK; } static int pylcall4i_irate(CSOUND *csound, PYCALL4 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); create_private_namespace_if_needed(&p->h); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 4)) { return errMsg(p, "callable must return 4 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); } Py_DECREF(result); return OK; } static int pycall4t_krate(CSOUND *csound, PYCALL4T *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; if (!*p->trigger) { *p->result1 = p->oresult1; *p->result2 = p->oresult2; *p->result3 = p->oresult3; *p->result4 = p->oresult4; return OK; } format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 2); result = eval_string_in_given_context(command, 0); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 4)) { return errMsg(p, "callable must return 4 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); p->oresult1 = *p->result1; *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); p->oresult2 = *p->result2; *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); p->oresult3 = *p->result3; *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); p->oresult4 = *p->result4; } Py_DECREF(result); return OK; } static int pylcall4t_irate(CSOUND *csound, PYCALL4T *p) { int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pylcall4t_krate(CSOUND *csound, PYCALL4T *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; if (!*p->trigger) { *p->result1 = p->oresult1; *p->result2 = p->oresult2; *p->result3 = p->oresult3; *p->result4 = p->oresult4; return OK; } format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 2); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 4)) { return errMsg(p, "callable must return 4 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); p->oresult1 = *p->result1; *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); p->oresult2 = *p->result2; *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); p->oresult3 = *p->result3; *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); p->oresult4 = *p->result4; } Py_DECREF(result); return OK; } static int pycall5_krate(CSOUND *csound, PYCALL5 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); result = eval_string_in_given_context(command, 0); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 5)) { return errMsg(p, "callable must return 5 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); *p->result5 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 4)); } Py_DECREF(result); return OK; } static int pylcall5_irate(CSOUND *csound, PYCALL5 *p) { int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pylcall5_krate(CSOUND *csound, PYCALL5 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 5)) { return errMsg(p, "callable must return 5 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); *p->result5 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 4)); } Py_DECREF(result); return OK; } static int pylcall5i_irate(CSOUND *csound, PYCALL5 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); create_private_namespace_if_needed(&p->h); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 5)) { return errMsg(p, "callable must return 5 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); *p->result5 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 4)); } Py_DECREF(result); return OK; } static int pycall5t_krate(CSOUND *csound, PYCALL5T *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; if (!*p->trigger) { *p->result1 = p->oresult1; *p->result2 = p->oresult2; *p->result3 = p->oresult3; *p->result4 = p->oresult4; *p->result5 = p->oresult5; return OK; } format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 2); result = eval_string_in_given_context(command, 0); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 5)) { return errMsg(p, "callable must return 5 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); p->oresult1 = *p->result1; *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); p->oresult2 = *p->result2; *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); p->oresult3 = *p->result3; *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); p->oresult4 = *p->result4; *p->result5 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 4)); p->oresult5 = *p->result5; } Py_DECREF(result); return OK; } static int pylcall5t_irate(CSOUND *csound, PYCALL5T *p) { int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pylcall5t_krate(CSOUND *csound, PYCALL5T *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; if (!*p->trigger) { *p->result1 = p->oresult1; *p->result2 = p->oresult2; *p->result3 = p->oresult3; *p->result4 = p->oresult4; *p->result5 = p->oresult5; return OK; } format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 2); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 5)) { return errMsg(p, "callable must return 5 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); p->oresult1 = *p->result1; *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); p->oresult2 = *p->result2; *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); p->oresult3 = *p->result3; *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); p->oresult4 = *p->result4; *p->result5 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 4)); p->oresult5 = *p->result5; } Py_DECREF(result); return OK; } static int pycall6_krate(CSOUND *csound, PYCALL6 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); result = eval_string_in_given_context(command, 0); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 6)) { return errMsg(p, "callable must return 6 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); *p->result5 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 4)); *p->result6 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 5)); } Py_DECREF(result); return OK; } static int pylcall6_irate(CSOUND *csound, PYCALL6 *p) { int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pylcall6_krate(CSOUND *csound, PYCALL6 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 6)) { return errMsg(p, "callable must return 6 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); *p->result5 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 4)); *p->result6 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 5)); } Py_DECREF(result); return OK; } static int pylcall6i_irate(CSOUND *csound, PYCALL6 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); create_private_namespace_if_needed(&p->h); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 6)) { return errMsg(p, "callable must return 6 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); *p->result5 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 4)); *p->result6 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 5)); } Py_DECREF(result); return OK; } static int pycall6t_krate(CSOUND *csound, PYCALL6T *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; if (!*p->trigger) { *p->result1 = p->oresult1; *p->result2 = p->oresult2; *p->result3 = p->oresult3; *p->result4 = p->oresult4; *p->result5 = p->oresult5; *p->result6 = p->oresult6; return OK; } format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 2); result = eval_string_in_given_context(command, 0); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 6)) { return errMsg(p, "callable must return 6 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); p->oresult1 = *p->result1; *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); p->oresult2 = *p->result2; *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); p->oresult3 = *p->result3; *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); p->oresult4 = *p->result4; *p->result5 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 4)); p->oresult5 = *p->result5; *p->result6 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 5)); p->oresult6 = *p->result6; } Py_DECREF(result); return OK; } static int pylcall6t_irate(CSOUND *csound, PYCALL6T *p) { int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pylcall6t_krate(CSOUND *csound, PYCALL6T *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; if (!*p->trigger) { *p->result1 = p->oresult1; *p->result2 = p->oresult2; *p->result3 = p->oresult3; *p->result4 = p->oresult4; *p->result5 = p->oresult5; *p->result6 = p->oresult6; return OK; } format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 2); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 6)) { return errMsg(p, "callable must return 6 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); p->oresult1 = *p->result1; *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); p->oresult2 = *p->result2; *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); p->oresult3 = *p->result3; *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); p->oresult4 = *p->result4; *p->result5 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 4)); p->oresult5 = *p->result5; *p->result6 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 5)); p->oresult6 = *p->result6; } Py_DECREF(result); return OK; } static int pycall7_krate(CSOUND *csound, PYCALL7 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); result = eval_string_in_given_context(command, 0); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 7)) { return errMsg(p, "callable must return 7 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); *p->result5 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 4)); *p->result6 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 5)); *p->result7 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 6)); } Py_DECREF(result); return OK; } static int pylcall7_irate(CSOUND *csound, PYCALL7 *p) { int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pylcall7_krate(CSOUND *csound, PYCALL7 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 7)) { return errMsg(p, "callable must return 7 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); *p->result5 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 4)); *p->result6 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 5)); *p->result7 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 6)); } Py_DECREF(result); return OK; } static int pylcall7i_irate(CSOUND *csound, PYCALL7 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); create_private_namespace_if_needed(&p->h); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 7)) { return errMsg(p, "callable must return 7 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); *p->result5 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 4)); *p->result6 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 5)); *p->result7 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 6)); } Py_DECREF(result); return OK; } static int pycall7t_krate(CSOUND *csound, PYCALL7T *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; if (!*p->trigger) { *p->result1 = p->oresult1; *p->result2 = p->oresult2; *p->result3 = p->oresult3; *p->result4 = p->oresult4; *p->result5 = p->oresult5; *p->result6 = p->oresult6; *p->result7 = p->oresult7; return OK; } format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 2); result = eval_string_in_given_context(command, 0); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 7)) { return errMsg(p, "callable must return 7 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); p->oresult1 = *p->result1; *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); p->oresult2 = *p->result2; *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); p->oresult3 = *p->result3; *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); p->oresult4 = *p->result4; *p->result5 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 4)); p->oresult5 = *p->result5; *p->result6 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 5)); p->oresult6 = *p->result6; *p->result7 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 6)); p->oresult7 = *p->result7; } Py_DECREF(result); return OK; } static int pylcall7t_irate(CSOUND *csound, PYCALL7T *p) { int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pylcall7t_krate(CSOUND *csound, PYCALL7T *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; if (!*p->trigger) { *p->result1 = p->oresult1; *p->result2 = p->oresult2; *p->result3 = p->oresult3; *p->result4 = p->oresult4; *p->result5 = p->oresult5; *p->result6 = p->oresult6; *p->result7 = p->oresult7; return OK; } format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 2); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 7)) { return errMsg(p, "callable must return 7 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); p->oresult1 = *p->result1; *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); p->oresult2 = *p->result2; *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); p->oresult3 = *p->result3; *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); p->oresult4 = *p->result4; *p->result5 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 4)); p->oresult5 = *p->result5; *p->result6 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 5)); p->oresult6 = *p->result6; *p->result7 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 6)); p->oresult7 = *p->result7; } Py_DECREF(result); return OK; } static int pycall8_krate(CSOUND *csound, PYCALL8 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); result = eval_string_in_given_context(command, 0); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 8)) { return errMsg(p, "callable must return 8 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); *p->result5 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 4)); *p->result6 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 5)); *p->result7 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 6)); *p->result8 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 7)); } Py_DECREF(result); return OK; } static int pylcall8_irate(CSOUND *csound, PYCALL8 *p) { int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pylcall8_krate(CSOUND *csound, PYCALL8 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 8)) { return errMsg(p, "callable must return 8 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); *p->result5 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 4)); *p->result6 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 5)); *p->result7 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 6)); *p->result8 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 7)); } Py_DECREF(result); return OK; } static int pylcall8i_irate(CSOUND *csound, PYCALL8 *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 1); create_private_namespace_if_needed(&p->h); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 8)) { return errMsg(p, "callable must return 8 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); *p->result5 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 4)); *p->result6 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 5)); *p->result7 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 6)); *p->result8 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 7)); } Py_DECREF(result); return OK; } static int pycall8t_krate(CSOUND *csound, PYCALL8T *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; if (!*p->trigger) { *p->result1 = p->oresult1; *p->result2 = p->oresult2; *p->result3 = p->oresult3; *p->result4 = p->oresult4; *p->result5 = p->oresult5; *p->result6 = p->oresult6; *p->result7 = p->oresult7; *p->result8 = p->oresult8; return OK; } format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 2); result = eval_string_in_given_context(command, 0); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 8)) { return errMsg(p, "callable must return 8 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); p->oresult1 = *p->result1; *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); p->oresult2 = *p->result2; *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); p->oresult3 = *p->result3; *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); p->oresult4 = *p->result4; *p->result5 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 4)); p->oresult5 = *p->result5; *p->result6 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 5)); p->oresult6 = *p->result6; *p->result7 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 6)); p->oresult7 = *p->result7; *p->result8 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 7)); p->oresult8 = *p->result8; } Py_DECREF(result); return OK; } static int pylcall8t_irate(CSOUND *csound, PYCALL8T *p) { int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pylcall8t_krate(CSOUND *csound, PYCALL8T *p) { char command[1024]; PyObject *result; int *py_initialize_done; if (UNLIKELY((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0)) return NOTOK; if (!*p->trigger) { *p->result1 = p->oresult1; *p->result2 = p->oresult2; *p->result3 = p->oresult3; *p->result4 = p->oresult4; *p->result5 = p->oresult5; *p->result6 = p->oresult6; *p->result7 = p->oresult7; *p->result8 = p->oresult8; return OK; } format_call_statement(command, (char*) p->function->data, p->INOCOUNT, p->args, 2); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (UNLIKELY(result == NULL)) return pyErrMsg(p, "python exception"); if (UNLIKELY(!PyTuple_Check(result) || PyTuple_Size(result) != 8)) { return errMsg(p, "callable must return 8 values"); } else { *p->result1 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 0)); p->oresult1 = *p->result1; *p->result2 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 1)); p->oresult2 = *p->result2; *p->result3 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 2)); p->oresult3 = *p->result3; *p->result4 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 3)); p->oresult4 = *p->result4; *p->result5 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 4)); p->oresult5 = *p->result5; *p->result6 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 5)); p->oresult6 = *p->result6; *p->result7 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 6)); p->oresult7 = *p->result7; *p->result8 = PyFloat_AsDouble(PyTuple_GET_ITEM(result, 7)); p->oresult8 = *p->result8; } Py_DECREF(result); return OK; } csound-6.10.0/Opcodes/py/pycall.auto.h000066400000000000000000000121121321653344700175260ustar00rootroot00000000000000/* * pycall.auto.h * * Copyright (C) 2002 Maurizio Umberto Puxeddu, Michael Gogins * * This software is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ typedef struct { OPDS h; STRINGDAT *function; MYFLT *args[VARGMAX-3]; } PYCALL0; typedef struct { OPDS h; MYFLT *trigger; STRINGDAT *function; MYFLT *args[VARGMAX-3]; } PYCALL0T; typedef struct { OPDS h; MYFLT *result; STRINGDAT *function; MYFLT *args[VARGMAX-3]; } PYCALL1; typedef struct { OPDS h; MYFLT *result; MYFLT *trigger; STRINGDAT *function; MYFLT *args[VARGMAX-3]; MYFLT oresult; } PYCALL1T; typedef struct { OPDS h; MYFLT *result1; MYFLT *result2; STRINGDAT *function; MYFLT *args[VARGMAX-3]; } PYCALL2; typedef struct { OPDS h; MYFLT *result1; MYFLT *result2; MYFLT *trigger; STRINGDAT *function; MYFLT *args[VARGMAX-3]; MYFLT oresult1; MYFLT oresult2; } PYCALL2T; typedef struct { OPDS h; MYFLT *result1; MYFLT *result2; MYFLT *result3; STRINGDAT *function; MYFLT *args[VARGMAX-3]; } PYCALL3; typedef struct { OPDS h; MYFLT *result1; MYFLT *result2; MYFLT *result3; MYFLT *trigger; STRINGDAT *function; MYFLT *args[VARGMAX-3]; MYFLT oresult1; MYFLT oresult2; MYFLT oresult3; } PYCALL3T; typedef struct { OPDS h; MYFLT *result1; MYFLT *result2; MYFLT *result3; MYFLT *result4; STRINGDAT *function; MYFLT *args[VARGMAX-3]; } PYCALL4; typedef struct { OPDS h; MYFLT *result1; MYFLT *result2; MYFLT *result3; MYFLT *result4; MYFLT *trigger; STRINGDAT *function; MYFLT *args[VARGMAX-3]; MYFLT oresult1; MYFLT oresult2; MYFLT oresult3; MYFLT oresult4; } PYCALL4T; typedef struct { OPDS h; MYFLT *result1; MYFLT *result2; MYFLT *result3; MYFLT *result4; MYFLT *result5; STRINGDAT *function; MYFLT *args[VARGMAX-3]; } PYCALL5; typedef struct { OPDS h; MYFLT *result1; MYFLT *result2; MYFLT *result3; MYFLT *result4; MYFLT *result5; MYFLT *trigger; STRINGDAT *function; MYFLT *args[VARGMAX-3]; MYFLT oresult1; MYFLT oresult2; MYFLT oresult3; MYFLT oresult4; MYFLT oresult5; } PYCALL5T; typedef struct { OPDS h; MYFLT *result1; MYFLT *result2; MYFLT *result3; MYFLT *result4; MYFLT *result5; MYFLT *result6; STRINGDAT *function; MYFLT *args[VARGMAX-3]; } PYCALL6; typedef struct { OPDS h; MYFLT *result1; MYFLT *result2; MYFLT *result3; MYFLT *result4; MYFLT *result5; MYFLT *result6; MYFLT *trigger; STRINGDAT *function; MYFLT *args[VARGMAX-3]; MYFLT oresult1; MYFLT oresult2; MYFLT oresult3; MYFLT oresult4; MYFLT oresult5; MYFLT oresult6; } PYCALL6T; typedef struct { OPDS h; MYFLT *result1; MYFLT *result2; MYFLT *result3; MYFLT *result4; MYFLT *result5; MYFLT *result6; MYFLT *result7; STRINGDAT *function; MYFLT *args[VARGMAX-3]; } PYCALL7; typedef struct { OPDS h; MYFLT *result1; MYFLT *result2; MYFLT *result3; MYFLT *result4; MYFLT *result5; MYFLT *result6; MYFLT *result7; MYFLT *trigger; STRINGDAT *function; MYFLT *args[VARGMAX-3]; MYFLT oresult1; MYFLT oresult2; MYFLT oresult3; MYFLT oresult4; MYFLT oresult5; MYFLT oresult6; MYFLT oresult7; } PYCALL7T; typedef struct { OPDS h; MYFLT *result1; MYFLT *result2; MYFLT *result3; MYFLT *result4; MYFLT *result5; MYFLT *result6; MYFLT *result7; MYFLT *result8; STRINGDAT *function; MYFLT *args[VARGMAX-3]; } PYCALL8; typedef struct { OPDS h; MYFLT *result1; MYFLT *result2; MYFLT *result3; MYFLT *result4; MYFLT *result5; MYFLT *result6; MYFLT *result7; MYFLT *result8; MYFLT *trigger; STRINGDAT *function; MYFLT *args[VARGMAX-3]; MYFLT oresult1; MYFLT oresult2; MYFLT oresult3; MYFLT oresult4; MYFLT oresult5; MYFLT oresult6; MYFLT oresult7; MYFLT oresult8; } PYCALL8T; csound-6.10.0/Opcodes/py/pythonhelper.h000066400000000000000000000022511321653344700200170ustar00rootroot00000000000000/* * pythonhelper.h * * Copyright (C) 2002 Maurizio Umberto Puxeddu * * This software is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _pycsound_pythonhelper_h_ #define _pycsound_pythonhelper_h_ #ifdef _DEBUG # undef _DEBUG # include # define _DEBUG #else # include #endif /* I do it because I can't #include in "csoundCore.h". */ #define GETPYLOCAL(ids) ((PyObject *)ids->pylocal) #define SETPYLOCAL(ids, p) { ids->pylocal = (void *)p; } #endif csound-6.10.0/Opcodes/py/pythonopcodes.c000066400000000000000000000400741321653344700201740ustar00rootroot00000000000000/* * pythonopcodes.c * * Copyright (C) 2002 Maurizio Umberto Puxeddu * * This software is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef _DEBUG # undef _DEBUG # include # define _DEBUG #else # include #endif #include #include "csdl.h" #include "pythonopcodes.h" #include "pythonhelper.h" /* HELPERS */ static CS_NOINLINE void create_private_namespace_if_needed(OPDS *o) { if (GETPYLOCAL(o->insdshead) == 0) { SETPYLOCAL(o->insdshead, PyDict_New()); #ifdef DEBUG_PY_NAMESPACES printf("Creating private namespace %p for %p\n", (void*) GETPYLOCAL(o->insdshead), (void*) o->insdshead); #endif } #ifdef DEBUG_PY_NAMESPACES else { printf("Private namespace for %p already allocated at %p\n", (void*) o->insdshead, (void*) GETPYLOCAL(o->insdshead)); } #endif } static void format_call_statement2(char *statement, char *callable, int argc, MYFLT *argv[], long skip) { int i; statement[0] = '\0'; if (argc-skip > 0) { snprintf(statement, 1024, "%s(%0.6f", callable, *(argv[skip])); for (i = skip+1; i < argc; ++i) { snprintf(statement + strlen(statement), 1024 - strlen(statement), ", %f", *(argv[i])); } // MKG 2014 Jan 29: No linkage for strlcat in py.dll on MinGW. //strlcat(statement, ")", 1024); strncat(statement, ")", 1023 - strlen(statement)); statement[1023] = '\0'; } else { snprintf(statement, 1024, "%s()", callable); } } static void format_call_statement(char *statement, char *callable, int argc, MYFLT *argv[], int skip) { int i; statement[0] = '\0'; if (argc > 0) { snprintf(statement, 1024, "%s(%0.6f", callable, *(argv[0])); for (i = 1; i < argc - skip; ++i) { snprintf(statement + strlen(statement), 1024-strlen(statement), ", %f", *(argv[i])); } // MKG 2014 Jan 29: No linkage for strlcat in py.dll on MinGW. //strlcat(statement, ")", 1024); strncat(statement, ")", 1023-strlen(statement)); statement[1023] = '\0'; } else { snprintf(statement, 1024, "%s()", callable); } } static PyObject * run_statement_in_given_context(char *string, PyObject *private) { PyObject *module, *public; module = PyImport_AddModule("__main__"); if (module == NULL) { PyErr_SetString(PyExc_RuntimeError, "couldn't find module __main__"); return NULL; } public = PyModule_GetDict(module); return PyRun_String(string, Py_file_input, public, private ? private : public); } static PyObject * eval_string_in_given_context(char *string, PyObject *private) { PyObject *module, *public; module = PyImport_AddModule("__main__"); if (module == NULL) { PyErr_SetString(PyExc_RuntimeError, "couldn't find module __main__"); return NULL; } public = PyModule_GetDict(module); return PyRun_String(string, Py_eval_input, public, private ? private : public); } static PyObject * exec_file_in_given_context(CSOUND* cs, char *filename, PyObject *private) { PyObject *result, *module, *public, *pyFileObj; char *fullpath; fullpath = cs->FindInputFile(cs, filename, NULL); module = PyImport_AddModule("__main__"); if (module == NULL) { PyErr_SetString(PyExc_RuntimeError, "couldn't find module __main__"); return NULL; } public = PyModule_GetDict(module); pyFileObj = PyFile_FromString(fullpath, "r"); if (pyFileObj == NULL) { PyErr_Format(PyExc_RuntimeError, "couldn't open script file %s", filename); return NULL; } result = PyRun_File(PyFile_AsFile(pyFileObj), fullpath, Py_file_input, public, private ? private : public); return result; } /* ------ OPCODES ------ */ static CS_NOINLINE int errMsg(void *p, const char *msg) { CSOUND *csound = ((OPDS*) p)->insdshead->csound; const char *opname = csound->GetOpcodeName(p); csound->ErrorMsg(csound, "%s: %s", opname, msg); return NOTOK; } static CS_NOINLINE int pyErrMsg(void *p, const char *msg) { CSOUND *csound = ((OPDS*) p)->insdshead->csound; const char *opname = csound->GetOpcodeName(p); csound->ErrorMsg(csound, "%s: %s", opname, msg); PyErr_Print(); return NOTOK; } static int pyinit(CSOUND *csound, PYINIT *p) { (void) csound; (void) p; int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound, "PY_INITIALIZE")) == NULL){ csound->CreateGlobalVariable(csound, "PY_INITIALIZE", sizeof(int)); py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE"); *py_initialize_done = 0; } if (*py_initialize_done == 0) { Py_Initialize(); *py_initialize_done = 1; } PyObject *module = PyImport_AddModule("__main__"); if (module == NULL) { PyErr_SetString(PyExc_RuntimeError, "couldn't find module __main__"); return NOTOK; } PyObject *public = PyModule_GetDict(module); PyObject *csobj = Py_BuildValue("l", (long) csound); PyDict_SetItemString(public, "_CSOUND_", csobj); return OK; } #include "pyx.auto.c" #include "pycall.auto.c" static int pycalln_krate(CSOUND *csound, PYCALLN *p) { int i; char command[1024]; PyObject *result; format_call_statement2(command, p->function->data, p->INOCOUNT-2, p->args, *p->nresult); result = eval_string_in_given_context(command, 0); if (result != NULL && PyTuple_Check(result) && PyTuple_Size(result) == (int) *p->nresult) { for (i = 0; i < *p->nresult; ++i) *p->args[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(result, i)); Py_DECREF(result); } else { return pyErrMsg(p, "ERROR"); } return OK; } static int pylcalln_irate(CSOUND *csound, PYCALLN *p) { create_private_namespace_if_needed(&p->h); return OK; } static int pylcalln_krate(CSOUND *csound, PYCALLN *p) { int i; char command[1024]; PyObject *result; format_call_statement2(command, p->function->data, p->INOCOUNT-2, p->args, *p->nresult); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (result != NULL && PyTuple_Check(result) && PyTuple_Size(result) == (int) *p->nresult) { for (i = 0; i < *p->nresult; ++i) *p->args[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(result, i)); Py_DECREF(result); } else { return pyErrMsg(p, "ERROR"); } return OK; } static int pylcallni_irate(CSOUND *csound, PYCALLN *p) { int i; char command[1024]; PyObject *result; create_private_namespace_if_needed(&p->h); format_call_statement2(command, p->function->data, p->INOCOUNT-2, p->args, *p->nresult); result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead)); if (result != NULL && PyTuple_Check(result) && PyTuple_Size(result) == (int) *p->nresult) { for (i = 0; i < *p->nresult; ++i) *p->args[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(result, i)); Py_DECREF(result); } else { return pyErrMsg(p, "ERROR"); } return OK; } /* PYTHON OPCODES */ OENTRY python_localops[] = { /* INITIALIZATION */ { "pyinit", sizeof(PYINIT), 0, 1, "", "", (SUBR)pyinit, NULL }, /* RUN GROUP */ { "pyrun", sizeof(PYRUN), 0, 2, "", "S", NULL, (SUBR)pyrun_krate }, { "pyruni", sizeof(PYRUN), 0, 1, "", "S", (SUBR)pyruni_irate }, { "pylrun", sizeof(PYRUN), 0, 3, "", "S", (SUBR)pylrun_irate, (SUBR)pylrun_krate }, { "pylruni", sizeof(PYRUN), 0, 1, "", "S", (SUBR)pylruni_irate }, { "pyrunt", sizeof(PYRUNT), 0, 2, "", "kS", NULL, (SUBR)pyrunt_krate }, { "pylrunt", sizeof(PYRUNT), 0, 3, "", "kS", (SUBR)pylrunt_irate, (SUBR)pylrunt_krate }, /* EXEC GROUP */ { "pyexec", sizeof(PYEXEC), 0, 2, "", "S", NULL, (SUBR)pyexec_krate }, { "pyexeci", sizeof(PYEXEC), 0, 1, "", "S", (SUBR)pyexec_krate }, { "pylexec", sizeof(PYEXEC), 0, 3, "", "S", (SUBR)pylexec_irate, (SUBR)pylexec_krate }, { "pylexeci", sizeof(PYEXEC), 0, 1, "", "S", (SUBR)pylexeci_irate }, { "pyexect", sizeof(PYEXECT), 0, 2, "", "kS", NULL, (SUBR)pyexect_krate }, { "pylexect", sizeof(PYEXECT), 0, 3, "", "kS", (SUBR)pylexect_irate, (SUBR)pylexect_krate }, /* CALL GROUP */ { "pycall", sizeof(PYCALL0), 0, 2, "" , "Sz", NULL, (SUBR)pycall0_krate }, { "pycall1", sizeof(PYCALL1), 0, 2, "k", "Sz", NULL, (SUBR)pycall1_krate }, { "pycall2", sizeof(PYCALL2), 0, 2, "kk", "Sz", NULL, (SUBR)pycall2_krate }, { "pycall3", sizeof(PYCALL3), 0, 2, "kkk", "Sz", NULL, (SUBR)pycall3_krate }, { "pycall4", sizeof(PYCALL4), 0, 2, "kkkk", "Sz", NULL, (SUBR)pycall4_krate }, { "pycall5", sizeof(PYCALL5), 0, 2, "kkkkk", "Sz", NULL, (SUBR)pycall5_krate }, { "pycall6", sizeof(PYCALL6), 0, 2, "kkkkkk", "Sz", NULL, (SUBR)pycall6_krate }, { "pycall7", sizeof(PYCALL7), 0, 2, "kkkkkkk", "Sz", NULL, (SUBR)pycall7_krate }, { "pycall8", sizeof(PYCALL8), 0, 2, "kkkkkkkk", "Sz", NULL,(SUBR)pycall8_krate }, { "pycalln", sizeof(PYCALLN), 0, 2, "", "Siz", NULL, (SUBR)pycalln_krate }, { "pycallt", sizeof(PYCALL0T), 0, 2, "" , "kSz", NULL, (SUBR)pycall0t_krate }, { "pycall1t", sizeof(PYCALL1T), 0, 2, "k", "kSz", NULL, (SUBR)pycall1t_krate }, { "pycall2t", sizeof(PYCALL2T), 0, 2, "kk", "kSz", NULL, (SUBR)pycall2t_krate }, { "pycall3t", sizeof(PYCALL3T),0, 2, "kkk", "kSz", NULL, (SUBR)pycall3t_krate }, { "pycall4t", sizeof(PYCALL4T), 0, 2, "kkkk", "kSz", NULL, (SUBR)pycall4t_krate }, { "pycall5t", sizeof(PYCALL5T), 0, 2, "kkkkk", "kSz", NULL, (SUBR)pycall5t_krate }, { "pycall6t", sizeof(PYCALL6T), 0, 2, "kkkkkk", "kSz", NULL,(SUBR)pycall6t_krate }, { "pycall7t", sizeof(PYCALL7T), 0, 2, "kkkkkkk","kSz", NULL,(SUBR)pycall7t_krate }, { "pycall8t", sizeof(PYCALL8T), 0, 2, "kkkkkkkk","kSz",NULL,(SUBR)pycall8t_krate }, #if 0 { "pycallnt", sizeof(PYCALLNT), 0, 2, "", "Siz", NULL, (SUBR)pycallnt_krate }, #endif { "pycalli", sizeof(PYCALL0), 0, 1, "", "Sm", (SUBR)pycall0_krate }, { "pycall1i", sizeof(PYCALL1), 0, 1, "i", "Sm", (SUBR)pycall1_krate }, { "pycall2i", sizeof(PYCALL2), 0, 1, "ii", "Sm", (SUBR)pycall2_krate }, { "pycall3i", sizeof(PYCALL3), 0, 1, "iii", "Sm", (SUBR)pycall3_krate }, { "pycall4i", sizeof(PYCALL4), 0, 1, "iiii", "Sm", (SUBR)pycall4_krate }, { "pycall5i", sizeof(PYCALL5), 0, 1, "iiiii", "Sm", (SUBR)pycall5_krate }, { "pycall6i", sizeof(PYCALL6), 0, 1, "iiiiii", "Sm", (SUBR)pycall6_krate }, { "pycall7i", sizeof(PYCALL7), 0, 1, "iiiiiii", "Sm", (SUBR)pycall7_krate }, { "pycall8i", sizeof(PYCALL8), 0, 1, "iiiiiiii", "Sm", (SUBR)pycall8_krate }, { "pycallni", sizeof(PYCALLN), 0, 1, "", "Sim", (SUBR)pycalln_krate }, { "pylcall", sizeof(PYCALL0), 0, 3, "" , "Sz", (SUBR)pylcall0_irate, (SUBR)pylcall0_krate }, { "pylcall1", sizeof(PYCALL1), 0, 3, "k", "Sz", (SUBR)pylcall1_irate, (SUBR)pylcall1_krate }, { "pylcall2", sizeof(PYCALL2), 0, 3, "kk", "Sz", (SUBR)pylcall2_irate, (SUBR)pylcall2_krate }, { "pylcall3", sizeof(PYCALL3), 0, 3, "kkk", "Sz", (SUBR)pylcall3_irate, (SUBR)pylcall3_krate }, { "pylcall4", sizeof(PYCALL4), 0, 3, "kkkk", "Sz", (SUBR)pylcall4_irate, (SUBR)pylcall4_krate }, { "pylcall5", sizeof(PYCALL5), 0, 3, "kkkkk", "Sz", (SUBR)pylcall5_irate, (SUBR)pylcall5_krate }, { "pylcall6", sizeof(PYCALL6), 0, 3, "kkkkkk", "Sz", (SUBR)pylcall6_irate, (SUBR)pylcall6_krate }, { "pylcall7", sizeof(PYCALL7), 0, 3, "kkkkkkk", "Sz", (SUBR)pylcall7_irate, (SUBR)pylcall7_krate }, { "pylcall8", sizeof(PYCALL8), 0, 3, "kkkkkkkk", "Sz", (SUBR)pylcall8_irate, (SUBR)pylcall8_krate }, { "pylcalln", sizeof(PYCALLN), 0, 3, "", "Siz", (SUBR)pylcalln_irate, (SUBR)pylcalln_krate }, { "pylcallt", sizeof(PYCALL0T), 0, 3, "" , "kSz", (SUBR)pylcall0t_irate, (SUBR)pylcall0t_krate }, { "pylcall1t", sizeof(PYCALL1T), 0, 3, "k", "kSz", (SUBR)pylcall1t_irate, (SUBR)pylcall1t_krate }, { "pylcall2t", sizeof(PYCALL2T), 0, 3, "kk", "kSz", (SUBR)pylcall2t_irate, (SUBR)pylcall2t_krate }, { "pylcall3t", sizeof(PYCALL3T), 0, 3, "kkk", "kSz", (SUBR)pylcall3t_irate, (SUBR)pylcall3t_krate }, { "pylcall4t", sizeof(PYCALL4T), 0, 3, "kkkk", "kSz", (SUBR)pylcall4t_irate, (SUBR)pylcall4t_krate }, { "pylcall5t", sizeof(PYCALL5T), 0, 3, "kkkkk", "kSz", (SUBR)pylcall5t_irate, (SUBR)pylcall5t_krate }, { "pylcall6t", sizeof(PYCALL6T), 0, 3, "kkkkkk", "kSz", (SUBR)pylcall6t_irate, (SUBR)pylcall6t_krate }, { "pylcall7t", sizeof(PYCALL7T), 0, 3, "kkkkkkk", "kSz", (SUBR)pylcall7t_irate, (SUBR)pylcall7t_krate }, { "pylcall8t", sizeof(PYCALL8T), 0, 3, "kkkkkkkk", "kSz", (SUBR)pylcall8t_irate, (SUBR)pylcall8t_krate }, #if 0 { "pylcallnt", sizeof(PYCALLNT), 0, 3, "", "Siz", (SUBR)pylcalln_irate, (SUBR)pylcallnt_krate }, #endif { "pylcalli", sizeof(PYCALL0), 0, 1, "", "Sm", (SUBR)pylcall0i_irate }, { "pylcall1i", sizeof(PYCALL1), 0, 1, "i", "Sm", (SUBR)pylcall1i_irate }, { "pylcall2i", sizeof(PYCALL2), 0, 1, "ii", "Sm", (SUBR)pylcall2i_irate }, { "pylcall3i", sizeof(PYCALL3), 0, 1, "iii", "Sm", (SUBR)pylcall3i_irate }, { "pylcall4i", sizeof(PYCALL4), 0, 1, "iiii", "Sm", (SUBR)pylcall4i_irate }, { "pylcall5i", sizeof(PYCALL5), 0, 1, "iiiii", "Sm", (SUBR)pylcall5i_irate }, { "pylcall6i", sizeof(PYCALL6), 0, 1, "iiiiii", "Sm", (SUBR)pylcall6i_irate }, { "pylcall7i", sizeof(PYCALL7), 0, 1, "iiiiiii", "Sm", (SUBR)pylcall7i_irate }, { "pylcall8i", sizeof(PYCALL8), 0, 1, "iiiiiiii", "Sm", (SUBR)pylcall8i_irate }, { "pylcallni", sizeof(PYCALLN), 0, 1, "", "Sim", (SUBR)pylcallni_irate }, /* EVAL GROUP */ { "pyeval", sizeof(PYEVAL), 0, 2, "k", "S", NULL, (SUBR)pyeval_krate }, { "pyevali", sizeof(PYEVAL), 0, 1, "i", "S", (SUBR)pyeval_krate }, { "pyleval", sizeof(PYEVAL), 0, 3, "k", "S", (SUBR)pyleval_irate, (SUBR)pyleval_krate }, { "pylevali", sizeof(PYEVAL), 0, 1, "i", "S", (SUBR)pylevali_irate }, { "pyevalt", sizeof(PYEVALT), 0, 2, "k", "S", NULL, (SUBR)pyevalt_krate }, { "pylevalt", sizeof(PYEVALT), 0, 3, "k", "S", (SUBR)pylevalt_irate, (SUBR)pylevalt_krate }, /* ASSIGN GROUP */ { "pyassign", sizeof(PYASSIGN), 0, 2, "", "Sz", NULL, (SUBR)pyassign_krate }, { "pyassigni", sizeof(PYASSIGN), 0, 1, "", "Sz", (SUBR)pyassign_krate }, { "pylassign", sizeof(PYASSIGN), 0, 3, "", "Sz", (SUBR)pylassign_irate, (SUBR)pylassign_krate }, { "pylassigni", sizeof(PYASSIGN), 0, 1, "", "Sz", (SUBR)pylassigni_irate }, { "pyassignt", sizeof(PYASSIGNT), 0, 2, "", "Sz", NULL, (SUBR)pyassignt_krate }, { "pylassignt", sizeof(PYASSIGNT), 0, 3, "", "Sz", (SUBR)pylassignt_irate, (SUBR)pylassignt_krate }, }; LINKAGE_BUILTIN(python_localops) csound-6.10.0/Opcodes/py/pythonopcodes.h000066400000000000000000000023471321653344700202020ustar00rootroot00000000000000/* * pythonopcodes.h * * Copyright (C) 2002 Maurizio Umberto Puxeddu * * This software is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _pycsound_pythonopcodes_h_ #define _pycsound_pythonopcodes_h_ #ifdef _DEBUG # undef _DEBUG # include # define _DEBUG #else # include #endif #include "csdl.h" #include "pyx.auto.h" #include "pycall.auto.h" typedef struct { OPDS h; } PYINIT; typedef struct { OPDS h; STRINGDAT *function; MYFLT *nresult; MYFLT *args[VARGMAX]; } PYCALLN; #endif /* _pycsound_pythonopcodes_h_ */ csound-6.10.0/Opcodes/py/pyx-gen.py000066400000000000000000000115661321653344700170770ustar00rootroot00000000000000#!/usr/bin/env python def generate_x_method(f, action, context, rate0, triggered): if rate0 != 'k': rate = rate0 else: rate = '' if action in ('exec', 'assign', 'eval'): size = 1024 elif action == 'run': size = 40960 else: raise 'undefined action %s' % action if action in ('run', 'assign'): helper = 'run_statement' elif action == 'exec': helper = 'exec_file' elif action == 'eval': helper = 'eval_string' else: raise 'undefined action %s' % action if context == 'private': prefix = 'l' ns = 'GETPYLOCAL(p->h.insdshead)' elif context == 'global': prefix = '' ns = '0' prepare = '' else: raise 'undefined context %s' % context if triggered: if rate == 'i': raise 'cannot be triggered at i-rate' t, T = 't', 'T' else: t, T = '', '' ACTION = action.upper() RATE = rate.upper() name = 'py%(prefix)s%(action)s%(rate)s%(t)s_%(rate0)srate' % locals() print >> f, 'static int %(name)s(CSOUND *csound, PY%(ACTION)s%(T)s *p)' % locals() print >> f, '{' print >> f, ' char source[%d];' % size print >> f, ' PyObject *result;' print >> f, ' int *py_initialize_done;' print >> f, ' if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL ||*py_initialize_done == 0)' print >> f, ' return NOTOK;' print >> f if triggered: if action == 'eval': print >> f, ' if (!*p->trigger) {' print >> f, ' *p->result = p->oresult;' print >> f, ' return OK;' print >> f, ' }' else: print >> f, ' if (!*p->trigger)' print >> f, ' return OK;' print >> f if context == 'private' and rate0 == 'i': print >> f, ' create_private_namespace_if_needed(&p->h);' print >> f if action == 'assign': print >> f, ' sprintf(source, "%s = %f", (char*) p->string->data, *p->value);' else: print >> f, ' strcpy(source, (char*) p->string->data);' print >> f if action == 'exec': print >> f, ' result = %(helper)s_in_given_context(csound, source, %(ns)s);' % locals() else: print >> f, ' result = %(helper)s_in_given_context(source, %(ns)s);' % locals() print >> f, ' if (result == NULL) {' print >> f, ' return pyErrMsg(p, "python exception");' print >> f, ' }' if action == 'eval': print >> f, ' else if (!PyFloat_Check(result)) {' print >> f, ' errMsg(p, "expression must evaluate in a float");' print >> f, ' }' print >> f, ' else {' print >> f, ' *p->result = PyFloat_AsDouble(result);' if triggered: print >> f, ' p->oresult = *p->result;' print >> f, ' }' print >> f, ' Py_DECREF(result);' print >> f, ' return OK;' print >> f, '}' print >> f def generate_init_method(f, action, triggered): ACTION = action.upper() if triggered: t, T = 't', 'T' else: t, T = '', '' print >> f, 'static int pyl%(action)s%(t)s_irate(CSOUND *csound, PY%(ACTION)s%(T)s *p)' % locals() print >> f, '{' print >> f, ' int *py_initialize_done;' print >> f, ' if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL ||*py_initialize_done == 0)' print >> f, ' return NOTOK;' print >> f, ' create_private_namespace_if_needed(&p->h);' print >> f, ' return OK;' print >> f, '}' print >> f # ---------------- def generate_pycall_opcode_struct(f, action, triggered): ACTION = action.upper() if triggered: T = 'T' else: T = '' print >> f, 'typedef struct {' print >> f, ' OPDS h;' if action == 'eval': print >> f, ' MYFLT *result;' if triggered: print >> f, ' MYFLT *trigger;' print >> f, ' MYFLT *string;' if action == 'assign': print >> f, ' MYFLT *value;' if action == 'eval' and triggered: print >> f, ' MYFLT oresult;' print >> f, '} PY%(ACTION)s%(T)s;' % locals() print >> f f = open('pyx.auto.c', 'w') print >> f for action in ['exec', 'run', 'eval', 'assign']: generate_x_method(f, action, 'global', 'k', 0) generate_x_method(f, action, 'global', 'i', 0) generate_init_method(f, action, 0) generate_x_method(f, action, 'private', 'k', 0) generate_x_method(f, action, 'private', 'i', 0) generate_x_method(f, action, 'global', 'k', 1) generate_init_method(f, action, 1) generate_x_method(f, action, 'private', 'k', 1) f.close() f = open('pyx.auto.h', 'w') print >> f for action in ['exec', 'run', 'eval', 'assign']: for triggered in [0, 1]: generate_pycall_opcode_struct(f, action, triggered) f.close() csound-6.10.0/Opcodes/py/pyx.auto.c000066400000000000000000000433471321653344700170730ustar00rootroot00000000000000/* * pyx.auto.c * * Copyright (C) 2002 Maurizio Umberto Puxeddu, Michael Gogins * * This software is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ static int pyexec_krate(CSOUND *csound, PYEXEC *p) { char source[1024]; PyObject *result; int *py_initialize_done; if ((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; strncpy(source, (char*) p->string->data,1023); source[1023] = '\0'; result = exec_file_in_given_context(csound, source, 0); if (result == NULL) { return pyErrMsg(p, "python exception"); } Py_DECREF(result); return OK; } #if 0 static int pyexeci_irate(CSOUND *csound, PYEXEC *p) { char source[1024]; PyObject *result; int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; strncpy(source, (char*) p->string->data, 1023); source[1023] = '\0'; result = exec_file_in_given_context(csound, source, 0); if (result == NULL) { return pyErrMsg(p, "python exception"); } Py_DECREF(result); return OK; } #endif static int pylexec_irate(CSOUND *csound, PYEXEC *p) { int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pylexec_krate(CSOUND *csound, PYEXEC *p) { char source[1024]; PyObject *result; int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; strncpy(source, (char*) p->string->data, 1023); source[1023]='\0'; result = exec_file_in_given_context(csound, source, GETPYLOCAL(p->h.insdshead)); if (result == NULL) { return pyErrMsg(p, "python exception"); } Py_DECREF(result); return OK; } static int pylexeci_irate(CSOUND *csound, PYEXEC *p) { char source[1024]; PyObject *result; int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; create_private_namespace_if_needed(&p->h); strncpy(source, (char*) p->string->data, 1023); source[1023]='\0'; result = exec_file_in_given_context(csound, source, GETPYLOCAL(p->h.insdshead)); if (result == NULL) { return pyErrMsg(p, "python exception"); } Py_DECREF(result); return OK; } static int pyexect_krate(CSOUND *csound, PYEXECT *p) { char source[1024]; PyObject *result; int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; if (!*p->trigger) return OK; strncpy(source, (char*) p->string->data, 1023);source[1023]='\0'; result = exec_file_in_given_context(csound, source, 0); if (result == NULL) { return pyErrMsg(p, "python exception"); } Py_DECREF(result); return OK; } static int pylexect_irate(CSOUND *csound, PYEXECT *p) { int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pylexect_krate(CSOUND *csound, PYEXECT *p) { char source[1024]; PyObject *result; int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; if (!*p->trigger) return OK; strncpy(source, (char*) p->string->data, 1023); source[1023]='\0'; result = exec_file_in_given_context(csound, source, GETPYLOCAL(p->h.insdshead)); if (result == NULL) { return pyErrMsg(p, "python exception"); } Py_DECREF(result); return OK; } static int pyrun_krate(CSOUND *csound, PYRUN *p) { char source[40960]; PyObject *result; int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; strncpy(source, (char*) p->string->data, 40959);source[40959]='\0'; result = run_statement_in_given_context(source, 0); if (result == NULL) { return pyErrMsg(p, "python exception"); } Py_DECREF(result); return OK; } static int pyruni_irate(CSOUND *csound, PYRUN *p) { char source[40960]; PyObject *result; int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; strncpy(source, (char*) p->string->data, 40959);source[40959]='\0'; result = run_statement_in_given_context(source, 0); if (result == NULL) { return pyErrMsg(p, "python exception"); } Py_DECREF(result); return OK; } static int pylrun_irate(CSOUND *csound, PYRUN *p) { int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pylrun_krate(CSOUND *csound, PYRUN *p) { char source[40960]; PyObject *result; int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; strncpy(source, (char*) p->string->data, 40959); source[40959]='\0'; result = run_statement_in_given_context(source, GETPYLOCAL(p->h.insdshead)); if (result == NULL) { return pyErrMsg(p, "python exception"); } Py_DECREF(result); return OK; } static int pylruni_irate(CSOUND *csound, PYRUN *p) { char source[40960]; PyObject *result; int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; create_private_namespace_if_needed(&p->h); strncpy(source, (char*) p->string->data, 40959); source[40959]='\0'; result = run_statement_in_given_context(source, GETPYLOCAL(p->h.insdshead)); if (result == NULL) { return pyErrMsg(p, "python exception"); } Py_DECREF(result); return OK; } static int pyrunt_krate(CSOUND *csound, PYRUNT *p) { char source[40960]; PyObject *result; int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; if (!*p->trigger) return OK; strncpy(source, (char*) p->string->data, 40959); source[40959]='\0'; result = run_statement_in_given_context(source, 0); if (result == NULL) { return pyErrMsg(p, "python exception"); } Py_DECREF(result); return OK; } static int pylrunt_irate(CSOUND *csound, PYRUNT *p) { int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pylrunt_krate(CSOUND *csound, PYRUNT *p) { char source[40960]; PyObject *result; int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; if (!*p->trigger) return OK; strncpy(source, (char*) p->string->data, 40959); source[40959]='\0'; result = run_statement_in_given_context(source, GETPYLOCAL(p->h.insdshead)); if (result == NULL) { return pyErrMsg(p, "python exception"); } Py_DECREF(result); return OK; } static int pyeval_krate(CSOUND *csound, PYEVAL *p) { char source[1024]; PyObject *result; int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; strncpy(source, (char*) p->string->data, 1023);source[1023]='\0'; result = eval_string_in_given_context(source, 0); if (result == NULL) { return pyErrMsg(p, "python exception"); } else if (!PyFloat_Check(result)) { errMsg(p, "expression must evaluate in a float"); } else { *p->result = PyFloat_AsDouble(result); } Py_DECREF(result); return OK; } #if 0 static int pyevali_irate(CSOUND *csound, PYEVAL *p) { char source[1024]; PyObject *result; int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; strncpy(source, (char*) p->string->data, 1023);source[1023]='\0'; result = eval_string_in_given_context(source, 0); if (result == NULL) { return pyErrMsg(p, "python exception"); } else if (!PyFloat_Check(result)) { errMsg(p, "expression must evaluate in a float"); } else { *p->result = PyFloat_AsDouble(result); } Py_DECREF(result); return OK; } #endif static int pyleval_irate(CSOUND *csound, PYEVAL *p) { int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pyleval_krate(CSOUND *csound, PYEVAL *p) { char source[1024]; PyObject *result; int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; strncpy(source, (char*) p->string->data, 1023);source[1023]='\0'; result = eval_string_in_given_context(source, GETPYLOCAL(p->h.insdshead)); if (result == NULL) { return pyErrMsg(p, "python exception"); } else if (!PyFloat_Check(result)) { errMsg(p, "expression must evaluate in a float"); } else { *p->result = PyFloat_AsDouble(result); } Py_DECREF(result); return OK; } static int pylevali_irate(CSOUND *csound, PYEVAL *p) { char source[1024]; PyObject *result; int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; create_private_namespace_if_needed(&p->h); strncpy(source, (char*) p->string->data, 1023);source[1023]='\0'; result = eval_string_in_given_context(source, GETPYLOCAL(p->h.insdshead)); if (result == NULL) { return pyErrMsg(p, "python exception"); } else if (!PyFloat_Check(result)) { errMsg(p, "expression must evaluate in a float"); } else { *p->result = PyFloat_AsDouble(result); } Py_DECREF(result); return OK; } static int pyevalt_krate(CSOUND *csound, PYEVALT *p) { char source[1024]; PyObject *result; int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; if (!*p->trigger) { *p->result = p->oresult; return OK; } strncpy(source, (char*) p->string->data, 1023);source[1023]='\0'; result = eval_string_in_given_context(source, 0); if (result == NULL) { return pyErrMsg(p, "python exception"); } else if (!PyFloat_Check(result)) { errMsg(p, "expression must evaluate in a float"); } else { *p->result = PyFloat_AsDouble(result); p->oresult = *p->result; } Py_DECREF(result); return OK; } static int pylevalt_irate(CSOUND *csound, PYEVALT *p) { int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pylevalt_krate(CSOUND *csound, PYEVALT *p) { char source[1024]; PyObject *result; int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; if (!*p->trigger) { *p->result = p->oresult; return OK; } strncpy(source, (char*) p->string->data, 1023);source[1023]='\0'; result = eval_string_in_given_context(source, GETPYLOCAL(p->h.insdshead)); if (result == NULL) { return pyErrMsg(p, "python exception"); } else if (!PyFloat_Check(result)) { errMsg(p, "expression must evaluate in a float"); } else { *p->result = PyFloat_AsDouble(result); p->oresult = *p->result; } Py_DECREF(result); return OK; } static int pyassign_krate(CSOUND *csound, PYASSIGN *p) { char source[1024]; PyObject *result; int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; snprintf(source, 1024, "%s = %f", (char*) p->string->data, *p->value); result = run_statement_in_given_context(source, 0); if (result == NULL) { return pyErrMsg(p, "python exception"); } Py_DECREF(result); return OK; } #if 0 static int pyassigni_irate(CSOUND *csound, PYASSIGN *p) { char source[1024]; PyObject *result; int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; snprintf(source, 1024, "%s = %f", (char*) p->string->data, *p->value); result = run_statement_in_given_context(source, 0); if (result == NULL) { return pyErrMsg(p, "python exception"); } Py_DECREF(result); return OK; } #endif static int pylassign_irate(CSOUND *csound, PYASSIGN *p) { int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pylassign_krate(CSOUND *csound, PYASSIGN *p) { char source[1024]; PyObject *result; int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; snprintf(source, 1024, "%s = %f", (char*) p->string->data, *p->value); result = run_statement_in_given_context(source, GETPYLOCAL(p->h.insdshead)); if (result == NULL) { return pyErrMsg(p, "python exception"); } Py_DECREF(result); return OK; } static int pylassigni_irate(CSOUND *csound, PYASSIGN *p) { char source[1024]; PyObject *result; int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; create_private_namespace_if_needed(&p->h); snprintf(source, 1024, "%s = %f", (char*) p->string->data, *p->value); result = run_statement_in_given_context(source, GETPYLOCAL(p->h.insdshead)); if (result == NULL) { return pyErrMsg(p, "python exception"); } Py_DECREF(result); return OK; } static int pyassignt_krate(CSOUND *csound, PYASSIGNT *p) { char source[1024]; PyObject *result; int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; if (!*p->trigger) return OK; snprintf(source, 1024, "%s = %f", (char*) p->string->data, *p->value); result = run_statement_in_given_context(source, 0); if (result == NULL) { return pyErrMsg(p, "python exception"); } Py_DECREF(result); return OK; } static int pylassignt_irate(CSOUND *csound, PYASSIGNT *p) { int *py_initialize_done; if((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; create_private_namespace_if_needed(&p->h); return OK; } static int pylassignt_krate(CSOUND *csound, PYASSIGNT *p) { char source[1024]; PyObject *result; int *py_initialize_done; if ((py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE")) == NULL || *py_initialize_done == 0) return NOTOK; if (!*p->trigger) return OK; snprintf(source, 1024, "%s = %f", (char*) p->string->data, *p->value); result = run_statement_in_given_context(source, GETPYLOCAL(p->h.insdshead)); if (result == NULL) { return pyErrMsg(p, "python exception"); } Py_DECREF(result); return OK; } csound-6.10.0/Opcodes/py/pyx.auto.h000066400000000000000000000030211321653344700170610ustar00rootroot00000000000000/* * pyx.auto. * * Copyright (C) 2002 Maurizio Umberto Puxeddu, Michael Gogins * * This software is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ typedef struct { OPDS h; STRINGDAT *string; } PYEXEC; typedef struct { OPDS h; MYFLT *trigger; STRINGDAT *string; } PYEXECT; typedef struct { OPDS h; STRINGDAT *string; } PYRUN; typedef struct { OPDS h; MYFLT *trigger; STRINGDAT *string; } PYRUNT; typedef struct { OPDS h; MYFLT *result; STRINGDAT *string; } PYEVAL; typedef struct { OPDS h; MYFLT *result; MYFLT *trigger; STRINGDAT *string; MYFLT oresult; } PYEVALT; typedef struct { OPDS h; STRINGDAT *string; MYFLT *value; } PYASSIGN; typedef struct { OPDS h; MYFLT *trigger; STRINGDAT *string; MYFLT *value; } PYASSIGNT; csound-6.10.0/Opcodes/quadbezier.c000066400000000000000000000065361321653344700170060ustar00rootroot00000000000000/* quadbezier.c: Copyright (C) 2016 Guillermo Senna. This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csdl.h" #include static MYFLT SolveQuadratic(MYFLT a, MYFLT b, MYFLT c); static MYFLT FindTforX(MYFLT x1, MYFLT x2, MYFLT x3, int x); /* This Gen routine fills a table with the values produced by applying the quadratic B??zier function. It is aimed at frontend developers and will draw the correct paths as long as it is treated like a regular function. This means that, for example, you won't be able to create a circle and store it inside an f-table. References: https://pomax.github.io/bezierinfo/ -> A very concise summary on the matter. http://stackoverflow.com/questions/5634460/quadratic-bezier-curve-calculate-point http://stackoverflow.com/questions/27791915/quadratic-bezier-curve-calculate-t-given-x https://github.com/vikman90/bezier https://en.wikipedia.org/wiki/B??zier_curve Implementation: It is assumed that x1 equals 0 and that x[n] can't never be equal or greater than x[n+1]. On the other hand, cx[n] can be equal to x[n] or x[n+1]. For the coding part, I've recycled code from some of the numbered GEN routines and specially from the "fareygen" and other named routines. Credit for that goes to the respective authors of those routines. */ static int quadbeziertable (FGDATA *ff, FUNC *ftp) { int nvals, nargs, n; MYFLT *fp = ftp->ftable; CSOUND *csound = ff->csound; nvals = ff->flen; nargs = ff->e.pcnt - 4; if (UNLIKELY(nargs < 5)) { return csound->ftError(ff, Str("insufficient arguments")); } ff->e.p[4] *= -1; for (n = 4; n < nargs; n += 4) { int j, x1; j = (n < 8) ? 0 : ff->e.p[n]; x1 = j; while (j <= ff->e.p[n+4]) { MYFLT t; t = FindTforX(x1, ff->e.p[n+2], ff->e.p[n+4], j); if (j <= nvals) fp[j++] = (FL(1.0) - t) * (FL(1.0) - t) * ff->e.p[n+1] + FL(2.0) * (FL(1.0) - t) * t * ff->e.p[n+3] + t * t * ff->e.p[n+5]; } } return OK; } /* utility functions */ inline static MYFLT SolveQuadratic(MYFLT a, MYFLT b, MYFLT c) { MYFLT determinant; determinant = b*b - 4*a*c; if (determinant >= 0) return (-b + SQRT(determinant)) / (FL(2.0)*a); else return 0; } static MYFLT FindTforX(MYFLT x1, MYFLT x2, MYFLT x3, int x) { MYFLT a = (x1 - FL(2.0)*x2 + x3), b = FL(2.0)* (-x1 + x2), c = x1 - x; if (a) return SolveQuadratic(a, b, c); else return (x-x1)/b; } static NGFENS quadbezier_fgens[] = { { "quadbezier", quadbeziertable }, { NULL, NULL } }; FLINKAGE_BUILTIN(quadbezier_fgens) csound-6.10.0/Opcodes/repluck.c000066400000000000000000000257711321653344700163220ustar00rootroot00000000000000/* repluck.c: Copyright (C) 1996 John ffitch 1998 Victor Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /***************************************************************\ * repluck.c * * Various waveguide instruments * * 3 March 1996 John ffitch * \***************************************************************/ #include "stdopcod.h" #include "repluck.h" static int wgpsetin(CSOUND *, WGPLUCK2 *); static int wgpset(CSOUND *csound, WGPLUCK2 *p) { p->ain = NULL; wgpsetin(csound,p); return OK; } static int wgpsetin(CSOUND *csound, WGPLUCK2 *p) { int npts; int pickpt; int rail_len; MYFLT upslope; MYFLT downslope; MYFLT *initial_shape; int i; int scale = 1; DelayLine *upper_rail; DelayLine *lower_rail; MYFLT plk = *p->plk; /* Initialize variables....*/ npts = (int)(CS_ESR / *p->icps);/* Length of full delay */ while (npts < 512) { /* Minimum rail length is 256 */ npts += (int)(CS_ESR / *p->icps); scale++; } rail_len = npts/2/* + 1*/; /* but only need half length */ if (UNLIKELY(plk >= FL(1.0) || plk <= FL(0.0))) { plk = (p->ain ? FL(0.0) : FL(0.5)); } pickpt = (int)(rail_len * plk); /* Create upper rail */ if (p->upper.auxp == NULL) {/* get newspace */ csound->AuxAlloc(csound, sizeof(DelayLine),&p->upper); } upper_rail = (DelayLine*)p->upper.auxp; upper_rail->length = rail_len; if (rail_len > 0) { csound->AuxAlloc(csound, rail_len*sizeof(MYFLT),&p->up_data); upper_rail->data = (MYFLT*)p->up_data.auxp; } // else upper_rail->data = NULL; upper_rail->pointer = upper_rail->data; upper_rail->end = upper_rail->data + rail_len - 1; /* Create lower rail */ if (p->lower.auxp == NULL) {/* get newspace */ csound->AuxAlloc(csound, sizeof(DelayLine),&p->lower); } lower_rail = (DelayLine*)p->lower.auxp; lower_rail->length = rail_len; //if (rail_len > 0) { Always true csound->AuxAlloc(csound, rail_len*sizeof(MYFLT),&p->down_data); lower_rail->data = (MYFLT*)p->down_data.auxp; //} //else lower_rail->data = NULL; lower_rail->pointer = lower_rail->data; lower_rail->end = lower_rail->data + rail_len - 1; /* Set initial shape */ if (LIKELY(plk != FL(0.0))) { initial_shape = (MYFLT*) csound->Malloc(csound, rail_len*sizeof(MYFLT)); if (UNLIKELY(pickpt < 1)) pickpt = 1; /* Place for pluck, in range (0,1.0) */ upslope = FL(1.0)/(MYFLT)pickpt; /* Slightly faster to precalculate */ downslope = FL(1.0)/(MYFLT)(rail_len - pickpt - 1); for (i = 0; i < pickpt; i++) initial_shape[i] = upslope * i; for (i = pickpt; i < rail_len; i++) initial_shape[i] = downslope * (rail_len - 1 - i); for (i=0; idata[i] = FL(0.5) * initial_shape[i]; for (i=0; idata[i] = FL(0.5) * initial_shape[i]; csound->Free(csound,initial_shape); } else { memset(upper_rail->data, 0, rail_len*sizeof(MYFLT)); memset(lower_rail->data, 0, rail_len*sizeof(MYFLT)); } /* Copy data into structure */ p->state = FL(0.0); /* filter memory */ p->rail_len = rail_len; p->scale = scale; return OK; } /* end wgpset(p) */ /* Access a delay line with wrapping */ static MYFLT* locate(DelayLine *dl, int position) { MYFLT *outloc = dl->pointer + position; while (outloc < dl->data) outloc += dl->length; while (outloc > dl->end) outloc -= dl->length; return outloc; } static MYFLT getvalue(DelayLine *dl, int position) { MYFLT *outloc = dl->pointer + position; while (outloc < dl->data) outloc += dl->length; while (outloc > dl->end) outloc -= dl->length; return *outloc; } #define OVERCNT (256) #define OVERSHT (8) #define OVERMSK (0xFF) static int wgpluck(CSOUND *csound, WGPLUCK2 *p) { MYFLT *ar, *ain; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT yp0,ym0,ypM,ymM; DelayLine *upper_rail; DelayLine *lower_rail; int pickup, pickfrac; int i; int scale; MYFLT state = p->state; MYFLT reflect = *p->reflect; if (UNLIKELY(reflect <= FL(0.0) || reflect >= FL(1.0))) { csound->Warning(csound, Str("Reflection invalid (%f)\n"), reflect); reflect = FL(0.5); } ar = p->ar; ain = p->ain; scale = p->scale; reflect = FL(1.0) - (FL(1.0) - reflect)/(MYFLT)scale; /* For over sapling */ upper_rail = (DelayLine*)p->upper.auxp; lower_rail = (DelayLine*)p->lower.auxp; /* fractional delays */ pickup = (int)((MYFLT)OVERCNT * *(p->pickup) * p->rail_len); pickfrac = pickup & OVERMSK; pickup = pickup>>OVERSHT; if (UNLIKELY(pickup<0 || pickup > p->rail_len)) { csound->Warning(csound, Str("Pickup out of range (%f)\n"), *p->pickup); pickup = p->rail_len * (OVERCNT/2); pickfrac = pickup & OVERMSK; pickup = pickup>>OVERSHT; } if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;nxamp); loc = locate(upper_rail,1); *loc += (FL(0.5)* *ain++)/(*p->xamp); } ar[n] *= *p->xamp; /* and scale */ for (i=0; ilength - 2); /* Sample to "nut" */ ymM = -ypM; /* Inverting reflection at rigid nut */ /* reflection at yielding bridge */ /* Implement a one-pole lowpass with feedback coefficient from input */ state = (state * reflect) + ym0 * (FL(1.0) - reflect); yp0 = - state; /* String state update */ /* Decrement pointer and then update */ { MYFLT *ptr = upper_rail->pointer; ptr--; if (UNLIKELY(ptr < upper_rail->data)) ptr = upper_rail->end; *ptr = yp0; upper_rail->pointer = ptr; } /* Update and then increment pointer */ { MYFLT *ptr = lower_rail->pointer; *ptr = ymM; ptr++; if (UNLIKELY(ptr > lower_rail->end)) ptr = lower_rail->data; lower_rail->pointer = ptr; } } }; p->state = state; /* Remember last state sample */ return OK; } /* end wgpluck(p) */ /*******************************************************/ /* streson.c : string resonator opcode */ /* takes one input and passes it through */ /* emulates the resonance */ /* of a string tuned to a kfun fundamental */ /* Victor Lazzarini, 1998 */ /*******************************************************/ static int stresonset(CSOUND *csound, STRES *p) { p->size = (int) (CS_ESR/20); /* size of delay line */ csound->AuxAlloc(csound, p->size*sizeof(MYFLT), &p->aux); p->Cdelay = (MYFLT*) p->aux.auxp; /* delay line */ p->LPdelay = p->APdelay = FL(0.0); /* reset the All-pass and Low-pass delays */ p->wpointer = p->rpointer = 0; /* reset the read/write pointers */ memset(p->Cdelay, '\0', p->size*sizeof(MYFLT)); return OK; } static int streson(CSOUND *csound, STRES *p) { MYFLT *out = p->result; MYFLT *in = p->ainput; MYFLT g = *p->ifdbgain; MYFLT freq; double a, s, w, sample, tdelay, fracdelay; int delay; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int rp = p->rpointer, wp = p->wpointer; int size = p->size; MYFLT APdelay = p->APdelay; MYFLT LPdelay = p->LPdelay; int vdt; freq = *p->afr; if (UNLIKELY(freq < FL(20.0))) freq = FL(20.0); /* lowest freq is 20 Hz */ tdelay = CS_ESR/freq; delay = (int) (tdelay - 0.5); /* comb delay */ fracdelay = tdelay - (delay + 0.5); /* fractional delay */ vdt = size - delay; /* set the var delay */ a = (1.0-fracdelay)/(1.0+fracdelay); /* set the all-pass gain */ if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;n= size)) rp -= size; tmpo = p->Cdelay[rp]; w = in[n] + tmpo; s = (LPdelay + w)*0.5; LPdelay = w; out[n] = sample = APdelay + s*a; APdelay = s - (sample*a); p->Cdelay[wp] = sample*g; wp++; if (UNLIKELY(wp == size)) wp=0; } p->rpointer = rp; p->wpointer = wp; p->LPdelay = LPdelay; p->APdelay = APdelay; return OK; } #define S(x) sizeof(x) static OENTRY localops[] = { { "repluck", S(WGPLUCK2), 0, 5, "a", "ikikka",(SUBR)wgpsetin, NULL, (SUBR)wgpluck}, { "wgpluck2",S(WGPLUCK2), 0, 5, "a", "ikikk", (SUBR)wgpset, NULL, (SUBR)wgpluck}, { "streson", S(STRES), 0, 5, "a", "akk", (SUBR)stresonset, NULL, (SUBR)streson} }; int repluck_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/repluck.h000066400000000000000000000034051321653344700163150ustar00rootroot00000000000000/* repluck.h: Copyright (C) 1996, 1998 John ffitch, Victor Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* repluck.h */ typedef struct _DelayLine { MYFLT *data; int length; MYFLT *pointer; MYFLT *end; } DelayLine; typedef struct { OPDS h; MYFLT *ar, *plk, *xamp, *icps, *pickup, *reflect; MYFLT *ain; AUXCH upper; AUXCH lower; AUXCH up_data; AUXCH down_data; MYFLT state; int scale; int rail_len; } WGPLUCK2; /****************************************************/ /* streson.h : string resonator header file */ /* */ /* Victor Lazzarini, 1998 */ /****************************************************/ typedef struct{ OPDS h; MYFLT *result, *ainput, *afr, *ifdbgain; double LPdelay, APdelay; MYFLT *Cdelay; AUXCH aux; int wpointer, rpointer, size; } STRES; csound-6.10.0/Opcodes/reverbsc.c000066400000000000000000000270361321653344700164640ustar00rootroot00000000000000/* reverbsc.c: 8 delay line FDN reverb, with feedback matrix based upon physical modeling scattering junction of 8 lossless waveguides of equal characteristic impedance. Based on Julius O. Smith III, "A New Approach to Digital Reverberation using Closed Waveguide Networks," Proceedings of the International Computer Music Conference 1985, p. 47-53 (also available as a seperate publication from CCRMA), as well as some more recent papers by Smith and others. Csound orchestra version coded by Sean Costello, October 1999 C implementation (C) 2005 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "stdopcod.h" #include #define DEFAULT_SRATE 44100.0 #define MIN_SRATE 5000.0 #define MAX_SRATE 1000000.0 #define MAX_PITCHMOD 20.0 #define DELAYPOS_SHIFT 28 #define DELAYPOS_SCALE 0x10000000 #define DELAYPOS_MASK 0x0FFFFFFF /* reverbParams[n][0] = delay time (in seconds) */ /* reverbParams[n][1] = random variation in delay time (in seconds) */ /* reverbParams[n][2] = random variation frequency (in 1/sec) */ /* reverbParams[n][3] = random seed (0 - 32767) */ static const double reverbParams[8][4] = { { (2473.0 / DEFAULT_SRATE), 0.0010, 3.100, 1966.0 }, { (2767.0 / DEFAULT_SRATE), 0.0011, 3.500, 29491.0 }, { (3217.0 / DEFAULT_SRATE), 0.0017, 1.110, 22937.0 }, { (3557.0 / DEFAULT_SRATE), 0.0006, 3.973, 9830.0 }, { (3907.0 / DEFAULT_SRATE), 0.0010, 2.341, 20643.0 }, { (4127.0 / DEFAULT_SRATE), 0.0011, 1.897, 22937.0 }, { (2143.0 / DEFAULT_SRATE), 0.0017, 0.891, 29491.0 }, { (1933.0 / DEFAULT_SRATE), 0.0006, 3.221, 14417.0 } }; static const double outputGain = 0.35; static const double jpScale = 0.25; typedef struct { int writePos; int bufferSize; int readPos; int readPosFrac; int readPosFrac_inc; int dummy; int seedVal; int randLine_cnt; double filterState; MYFLT buf[1]; } delayLine; typedef struct { OPDS h; MYFLT *aoutL, *aoutR, *ainL, *ainR, *kFeedBack, *kLPFreq; MYFLT *iSampleRate, *iPitchMod, *iSkipInit; double sampleRate; double dampFact; MYFLT prv_LPFreq; int initDone; delayLine *delayLines[8]; AUXCH auxData; } SC_REVERB; static int delay_line_max_samples(SC_REVERB *p, int n) { double maxDel; maxDel = reverbParams[n][0]; maxDel += (reverbParams[n][1] * (double) *(p->iPitchMod) * 1.125); return (int) (maxDel * p->sampleRate + 16.5); } static int delay_line_bytes_alloc(SC_REVERB *p, int n) { int nBytes; nBytes = (int) sizeof(delayLine) - (int) sizeof(MYFLT); nBytes += (delay_line_max_samples(p, n) * (int) sizeof(MYFLT)); nBytes = (nBytes + 15) & (~15); return nBytes; } static void next_random_lineseg(SC_REVERB *p, delayLine *lp, int n) { double prvDel, nxtDel, phs_incVal; /* update random seed */ if (lp->seedVal < 0) lp->seedVal += 0x10000; lp->seedVal = (lp->seedVal * 15625 + 1) & 0xFFFF; if (lp->seedVal >= 0x8000) lp->seedVal -= 0x10000; /* length of next segment in samples */ lp->randLine_cnt = (int) ((p->sampleRate / reverbParams[n][2]) + 0.5); prvDel = (double) lp->writePos; prvDel -= ((double) lp->readPos + ((double) lp->readPosFrac / (double) DELAYPOS_SCALE)); while (prvDel < 0.0) prvDel += (double) lp->bufferSize; prvDel = prvDel / p->sampleRate; /* previous delay time in seconds */ nxtDel = (double) lp->seedVal * reverbParams[n][1] / 32768.0; /* next delay time in seconds */ nxtDel = reverbParams[n][0] + (nxtDel * (double) *(p->iPitchMod)); /* calculate phase increment per sample */ phs_incVal = (prvDel - nxtDel) / (double) lp->randLine_cnt; phs_incVal = phs_incVal * p->sampleRate + 1.0; lp->readPosFrac_inc = (int) (phs_incVal * DELAYPOS_SCALE + 0.5); } static void init_delay_line(SC_REVERB *p, delayLine *lp, int n) { double readPos; /* int i; */ /* calculate length of delay line */ lp->bufferSize = delay_line_max_samples(p, n); lp->dummy = 0; lp->writePos = 0; /* set random seed */ lp->seedVal = (int) (reverbParams[n][3] + 0.5); /* set initial delay time */ readPos = (double) lp->seedVal * reverbParams[n][1] / 32768; readPos = reverbParams[n][0] + (readPos * (double) *(p->iPitchMod)); readPos = (double) lp->bufferSize - (readPos * p->sampleRate); lp->readPos = (int) readPos; readPos = (readPos - (double) lp->readPos) * (double) DELAYPOS_SCALE; lp->readPosFrac = (int) (readPos + 0.5); /* initialise first random line segment */ next_random_lineseg(p, lp, n); /* clear delay line to zero */ lp->filterState = 0.0; memset(lp->buf, 0, sizeof(MYFLT)*lp->bufferSize); /* for (i = 0; i < lp->bufferSize; i++) */ /* lp->buf[i] = FL(0.0); */ } static int sc_reverb_init(CSOUND *csound, SC_REVERB *p) { int i; int nBytes; /* check for valid parameters */ if (UNLIKELY(*(p->iSampleRate) <= FL(0.0))) p->sampleRate = (double) CS_ESR; else p->sampleRate = (double) *(p->iSampleRate); if (UNLIKELY(p->sampleRate < MIN_SRATE || p->sampleRate > MAX_SRATE)) { return csound->InitError(csound, Str("reverbsc: sample rate is out of range")); } if (UNLIKELY(*(p->iPitchMod) < FL(0.0) || *(p->iPitchMod) > (MYFLT) MAX_PITCHMOD)) { return csound->InitError(csound, Str("reverbsc: invalid pitch modulation factor")); } /* calculate the number of bytes to allocate */ nBytes = 0; for (i = 0; i < 8; i++) nBytes += delay_line_bytes_alloc(p, i); if (nBytes != (int)p->auxData.size) csound->AuxAlloc(csound, (size_t) nBytes, &(p->auxData)); else if (p->initDone && *(p->iSkipInit) != FL(0.0)) return OK; /* skip initialisation if requested */ /* set up delay lines */ nBytes = 0; for (i = 0; i < 8; i++) { p->delayLines[i] = (delayLine*) ((unsigned char*) (p->auxData.auxp) + (int) nBytes); init_delay_line(p, p->delayLines[i], i); nBytes += delay_line_bytes_alloc(p, i); } p->dampFact = 1.0; p->prv_LPFreq = FL(0.0); p->initDone = 1; return OK; } static int sc_reverb_perf(CSOUND *csound, SC_REVERB *p) { double ainL, ainR, aoutL, aoutR; double vm1, v0, v1, v2, am1, a0, a1, a2, frac; delayLine *lp; int readPos; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, n, nsmps = CS_KSMPS; int bufferSize; /* Local copy */ double dampFact = p->dampFact; if (UNLIKELY(p->initDone <= 0)) goto err1; /* calculate tone filter coefficient if frequency changed */ if (*(p->kLPFreq) != p->prv_LPFreq) { p->prv_LPFreq = *(p->kLPFreq); dampFact = 2.0 - cos(p->prv_LPFreq * TWOPI / p->sampleRate); dampFact = p->dampFact = dampFact - sqrt(dampFact * dampFact - 1.0); } if (UNLIKELY(offset)) { memset(p->aoutL, '\0', offset*sizeof(MYFLT)); memset(p->aoutR, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&p->aoutL[nsmps], '\0', early*sizeof(MYFLT)); memset(&p->aoutR[nsmps], '\0', early*sizeof(MYFLT)); } /* update delay lines */ for (i = offset; i < nsmps; i++) { /* calculate "resultant junction pressure" and mix to input signals */ ainL = aoutL = aoutR = 0.0; for (n = 0; n < 8; n++) ainL += p->delayLines[n]->filterState; ainL *= jpScale; ainR = ainL + (double) p->ainR[i]; ainL = ainL + (double) p->ainL[i]; /* loop through all delay lines */ for (n = 0; n < 8; n++) { lp = p->delayLines[n]; bufferSize = lp->bufferSize; /* send input signal and feedback to delay line */ lp->buf[lp->writePos] = (MYFLT) ((n & 1 ? ainR : ainL) - lp->filterState); if (UNLIKELY(++lp->writePos >= bufferSize)) lp->writePos -= bufferSize; /* read from delay line with cubic interpolation */ if (lp->readPosFrac >= DELAYPOS_SCALE) { lp->readPos += (lp->readPosFrac >> DELAYPOS_SHIFT); lp->readPosFrac &= DELAYPOS_MASK; } if (UNLIKELY(lp->readPos >= bufferSize)) lp->readPos -= bufferSize; readPos = lp->readPos; frac = (double) lp->readPosFrac * (1.0 / (double) DELAYPOS_SCALE); /* calculate interpolation coefficients */ a2 = frac * frac; a2 -= 1.0; a2 *= (1.0 / 6.0); a1 = frac; a1 += 1.0; a1 *= 0.5; am1 = a1 - 1.0; a0 = 3.0 * a2; a1 -= a0; am1 -= a2; a0 -= frac; /* read four samples for interpolation */ if (LIKELY(readPos > 0 && readPos < (bufferSize - 2))) { vm1 = (double) (lp->buf[readPos - 1]); v0 = (double) (lp->buf[readPos]); v1 = (double) (lp->buf[readPos + 1]); v2 = (double) (lp->buf[readPos + 2]); } else { /* at buffer wrap-around, need to check index */ if (--readPos < 0) readPos += bufferSize; vm1 = (double) lp->buf[readPos]; if (++readPos >= bufferSize) readPos -= bufferSize; v0 = (double) lp->buf[readPos]; if (++readPos >= bufferSize) readPos -= bufferSize; v1 = (double) lp->buf[readPos]; if (++readPos >= bufferSize) readPos -= bufferSize; v2 = (double) lp->buf[readPos]; } v0 = (am1 * vm1 + a0 * v0 + a1 * v1 + a2 * v2) * frac + v0; /* update buffer read position */ lp->readPosFrac += lp->readPosFrac_inc; /* apply feedback gain and lowpass filter */ v0 *= (double) *(p->kFeedBack); v0 = (lp->filterState - v0) * dampFact + v0; lp->filterState = v0; /* mix to output */ if (n & 1) aoutR += v0; else aoutL += v0; /* start next random line segment if current one has reached endpoint */ if (--(lp->randLine_cnt) <= 0) next_random_lineseg(p, lp, n); } p->aoutL[i] = (MYFLT) (aoutL * outputGain); p->aoutR[i] = (MYFLT) (aoutR * outputGain); } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("reverbsc: not initialised")); } /* module interface functions */ int reverbsc_init_(CSOUND *csound) { return csound->AppendOpcode(csound, "reverbsc", (int) sizeof(SC_REVERB), 0, 5, "aa", "aakkjpo", (int (*)(CSOUND *, void *)) sc_reverb_init, (int (*)(CSOUND *, void *)) NULL, (int (*)(CSOUND *, void *)) sc_reverb_perf); } csound-6.10.0/Opcodes/scoreline.c000066400000000000000000000036311321653344700166270ustar00rootroot00000000000000/* scoreline.c: (c) Victor Lazzarini, 2004,2008 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ //#include "csdl.h" #include "csoundCore.h" //extern void csoundInputMessageInternal(CSOUND *, const char *); typedef struct _inmess { OPDS h; STRINGDAT *SMess; MYFLT *ktrig; } INMESS; typedef struct _scorepos { OPDS h; MYFLT *spos; } SCOREPOS; int messi(CSOUND *csound, INMESS *p) { csound->InputMessage(csound, (char *)p->SMess->data); return OK; } int messk(CSOUND *csound, INMESS *p){ if (*p->ktrig) csound->InputMessage(csound, (char *)p->SMess->data); return OK; } int setscorepos(CSOUND *csound, SCOREPOS *p){ csound->SetScoreOffsetSeconds(csound, *p->spos); return OK; } int rewindscore(CSOUND *csound, SCOREPOS *p){ csound->RewindScore(csound); return OK; } static OENTRY scoreline_localops[] = { {"scoreline_i", sizeof(INMESS), 0, 1, "", "S", (SUBR)messi, NULL, NULL}, {"scoreline", sizeof(INMESS), 0, 2, "", "Sk", NULL, (SUBR)messk, NULL}, {"setscorepos", sizeof(SCOREPOS), 0, 1, "", "i", (SUBR)setscorepos, NULL, NULL}, {"rewindscore", sizeof(SCOREPOS), 0, 1, "", "", (SUBR)rewindscore, NULL, NULL} }; LINKAGE_BUILTIN(scoreline_localops) csound-6.10.0/Opcodes/select.c000066400000000000000000000033231321653344700161210ustar00rootroot00000000000000/* select.c: Copyright (C) 2016 John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csdl.h" typedef struct Select { OPDS h; MYFLT *ar, *in1, *in2, *less, *equal, *more; } Selecter; static int selecter(CSOUND *csound, Selecter* p) { MYFLT *ar = p->ar; MYFLT *a1=p->in1, *a2=p->in2, *al=p->less, *ae=p->equal, *am=p->more; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nndx; p->pfn = (int32) *p->kfn; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->kfn)) == NULL)) { return csound->InitError(csound, Str("seqtime: incorrect table number")); } *ndx = (int32) *p->initndx; p->done = 0; p->table = ftp->ftable; if (p->ndx > 0) p->newtime = p->table[p->ndx-1]; else p->newtime = 0; p->start = (double)CS_KCNT * CS_ONEDKR; start = (int32) *p->kstart; loop = (int32) *p->kloop; if (loop > 0) { *ndx %= loop; if (*ndx == 0) { *ndx += start; } } else if (loop < 0) { (*ndx)--; while (*ndx < start) { *ndx -= loop + start; } } p->curr_unit_time = *p->unit_time; p->first_flag= 1; return OK; } static int seqtim(CSOUND *csound, SEQTIM *p) { if (p->done) *p->ktrig=FL(0.0); else { int32 start = (int32) *p->kstart, loop = (int32) *p->kloop; int32 *ndx = &p->ndx; if (p->pfn != (int32)*p->kfn) { FUNC *ftp; if (UNLIKELY((ftp = csound->FTFindP(csound, p->kfn)) == NULL)) goto err1; p->pfn = (int32)*p->kfn; p->table = ftp->ftable; } if (p->curr_unit_time != *p->unit_time) { double constant = p->start - (double)CS_KCNT * CS_ONEDKR; double difference_new = p->newtime * p->curr_unit_time + constant; double difference_old = p->newtime * *p->unit_time + constant; double difference = difference_new - difference_old; p->start = p->start + difference; p->curr_unit_time = *p->unit_time; } if (CS_KCNT * CS_ONEDKR > p->newtime * *p->unit_time + p->start) { MYFLT curr_val = p->table[p->ndx]; p->first_flag = 0; p->newtime += (double)curr_val; if (loop > 0) { (*ndx)++; *ndx %= loop; if (*ndx == 0){ if (start == loop) { p->done = 1; return OK; } *ndx += start; } } else if (loop < 0 ){ (*ndx)--; while (p->ndx < 0) { if (start == loop) { p->done = 1; return OK; } *ndx -= loop + start; } } *p->ktrig = curr_val * p->curr_unit_time; } else { if (UNLIKELY(p->first_flag)) { *p->ktrig = p->table[p->ndx]; p->first_flag=0; } else { *p->ktrig=FL(0.0); } } } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("seqtime: incorrect table number")); } /**---------------------------------------**/ static int seqtim2_set(CSOUND *csound, SEQTIM2 *p) { FUNC *ftp; int32 start, loop; int32 *ndx = &p->ndx; p->pfn = (int32) *p->kfn; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->kfn)) == NULL)) { return csound->InitError(csound, Str("seqtim: incorrect table number")); } *ndx = (int32) *p->kinitndx; p->done=0; p->table = ftp->ftable; p->newtime = p->table[p->ndx]; p->start = CS_KCNT * CS_ONEDKR; start = (int32) *p->kstart; loop = (int32) *p->kloop; if (loop > 0 ) { (*ndx)++; *ndx %= loop; if (*ndx == 0) { *ndx += start; } } else if (loop < 0 ){ (*ndx)--; while (*ndx < start) { *ndx -= loop + start; } } p->curr_unit_time = *p->unit_time; p->first_flag = 1; return OK; } static int seqtim2(CSOUND *csound, SEQTIM2 *p) { if (*p->ktrigin) { p->ndx = (int32) *p->kinitndx; } if (p->done) goto end; else { int32 start = (int32) *p->kstart, loop = (int32) *p->kloop; int32 *ndx = &p->ndx; if (p->pfn != (int32)*p->kfn) { FUNC *ftp; if (UNLIKELY( (ftp = csound->FTFindP(csound, p->kfn) ) == NULL)) goto err1; p->pfn = (int32)*p->kfn; p->table = ftp->ftable; } if (p->curr_unit_time != *p->unit_time) { double constant = p->start - CS_KCNT * CS_ONEDKR; double difference_new = p->newtime * p->curr_unit_time + constant; double difference_old = p->newtime * *p->unit_time + constant; double difference = difference_new - difference_old; p->start = p->start + difference; p->curr_unit_time = *p->unit_time; } if (CS_KCNT * CS_ONEDKR > p->newtime * *p->unit_time + p->start) { float curr_val = p->table[p->ndx]; p->newtime += p->table[p->ndx]; if (loop > 0 ) { (*ndx)++; *ndx %= loop; if (*ndx == 0){ if (start == loop) { p->done =1; return OK; } *ndx += start; } } else if (loop < 0 ){ (*ndx)--; while (p->ndx < 0) { if (start == loop) { p->done = 1; return OK; } *ndx -= loop + start; } } *p->ktrig = curr_val * p->curr_unit_time; } else { if (UNLIKELY(p->first_flag)) { *p->ktrig = p->table[p->ndx]; p->first_flag = 0; } else { end: *p->ktrig = FL(0.0); } } } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("seqtim: incorrect table number")); } #define S(x) sizeof(x) static OENTRY localops[] = { { "seqtime", S(SEQTIM), TR, 3, "k", "kkkkk", (SUBR)seqtim_set, (SUBR)seqtim }, { "seqtime2", S(SEQTIM2),TR, 3, "k", "kkkkkk", (SUBR)seqtim2_set, (SUBR)seqtim2} }; int seqtime_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/serial.c000066400000000000000000000346511321653344700161310ustar00rootroot00000000000000/***************************************************** 251 CSOUND SERIAL PORT OPCODES ma++ ingalls, 2011/9/4 modified for WIndows John ffitch * based on "Arduino-serial" * Copyright (c) 2006, Tod E. Kurt, tod@todbot.com * http://todbot.com/blog/ Copyright (C) 2011 matt ingalls based on "Arduino-serial", Copyright (c) 2006, Tod E. Kurt, tod@todbot.com http://todbot.com/blog/ and licenced LGPL to csound This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include /* Standard types */ #include /* String function definitions */ #ifndef WIN32 #include /* UNIX standard function definitions */ #include /* File control definitions */ #include /* POSIX terminal control definitions */ #include #else #include "windows.h" #endif #include "csdl.h" /* ************************************************** As far as I can tell his should work on Windows as well using "COM1" etc ************************************************** */ /***************************************************** open a port. baudRate defaults to 9600 iPort serialBegin SPortName [, baudRate ] close a port serialEnd iPort write byte(s) to the port, at i or k rate serialWrite_i iPort, iByte serialWrite_i iPort, kByte serialWrite_i iPort, Sbytes serialWrite iPort, iByte serialWrite iPort, kByte serialWrite iPort, Sbytes read the next byte from the input buffer returned value will be in the range of 0-255 kByte serialRead iPort print to screen any bytes (up to 32k) in input buffer note that these bytes will be cleared from the buffer. use this opcode mainly for debugging messages. if you want to mix debugging and other communication messages over the same port, you will need to manually parse the data with the serialRead opcode. serialPrint iPort clear the input buffer serialFlush iPort TODO: (might need some kind of threaded buffer-read?) kNum serialAvailable iPort returns number of bytes available to read kByte serialPeekByte iPort returns the next byte in the input buffer does not remove the byte from the buffer *****************************************************/ #ifdef WIN32 typedef struct SERIAL_GLOBALS_ { CSOUND *csound; int maxind; HANDLE handles[10]; } SERIAL_GLOBALS; static HANDLE get_port(CSOUND *csound, int port) { HANDLE hport; SERIAL_GLOBALS *q; q = (SERIAL_GLOBALS*) csound->QueryGlobalVariable(csound, "serialGlobals_"); if (q == NULL) { csound->ErrorMsg(csound, Str("No ports available")); return NULL; } hport = (HANDLE)q->handles[port]; return hport; } #endif typedef struct { OPDS h; MYFLT *returnedPort; STRINGDAT *portName; MYFLT *baudRate; } SERIALBEGIN; int serialBegin(CSOUND *csound, SERIALBEGIN *p); typedef struct { OPDS h; MYFLT *port; } SERIALEND; int serialEnd(CSOUND *csound, SERIALEND *p); typedef struct { OPDS h; MYFLT *port, *toWrite; } SERIALWRITE; int serialWrite(CSOUND *csound, SERIALWRITE *p); typedef struct { OPDS h; MYFLT *rChar, *port; } SERIALREAD; int serialRead(CSOUND *csound, SERIALREAD *p); typedef struct { OPDS h; MYFLT *port; } SERIALPRINT; int serialPrint(CSOUND *csound, SERIALPRINT *p); typedef struct { OPDS h; MYFLT *port; } SERIALFLUSH; int serialFlush(CSOUND *csound, SERIALFLUSH *p); ///-----------TODO typedef struct { OPDS h; MYFLT *retVal, *port; } SERIALAVAIL; int serialAvailable(CSOUND *csound, SERIALAVAIL *p); typedef struct { OPDS h; MYFLT *retChar, *port; } SERIALPEEK; int serialPeekByte(CSOUND *csound, SERIALPEEK *p); //------------------ #ifndef WIN32 // takes the string name of the serial port (e.g. "/dev/tty.usbserial","COM1") // and a baud rate (bps) and connects to that port at that speed and 8N1. // opens the port in fully raw mode so you can send binary data. // returns valid fd, or -1 on error int serialport_init(CSOUND *csound, const char* serialport, int baud) { struct termios toptions; int fd; speed_t brate; //csound = NULL; /* Not used */ fprintf(stderr,"init_serialport: opening port %s @ %d bps\n", serialport,baud); fd = open(serialport, O_RDWR | O_NOCTTY | O_NDELAY); if (fd == -1) { perror("init_serialport: Unable to open port "); return -1; } if (tcgetattr(fd, &toptions) < 0) { perror("init_serialport: Couldn't get term attributes"); close(fd); return -1; } switch(baud) { default: brate = B9600; break; case 4800: brate = B4800; break; case 9600: brate = B9600; break; #ifdef B14400 case 14400: brate = B14400; break; #endif case 19200: brate = B19200; break; #ifdef B28800 case 28800: brate = B28800; break; #endif case 38400: brate = B38400; break; case 57600: brate = B57600; break; case 115200: brate = B115200; break; } cfsetispeed(&toptions, brate); cfsetospeed(&toptions, brate); // 8N1 toptions.c_cflag &= ~PARENB; toptions.c_cflag &= ~CSTOPB; toptions.c_cflag &= ~CSIZE; toptions.c_cflag |= CS8; // no flow control toptions.c_cflag &= ~CRTSCTS; toptions.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw toptions.c_oflag &= ~OPOST; // make raw // see: http://unixwiz.net/techtips/termios-vmin-vtime.html toptions.c_cc[VMIN] = 0; toptions.c_cc[VTIME] = 20; if ( tcsetattr(fd, TCSANOW, &toptions) < 0) { close(fd); perror("init_serialport: Couldn't set term attributes"); return -1; } return fd; } #else int serialport_init(CSOUND *csound, const char* serialport, int baud) { HANDLE hSerial; DCB dcbSerialParams = {0}; int i; /* NEED TO CREATE A GLOBAL FOR HANDLE */ SERIAL_GLOBALS *q; q = (SERIAL_GLOBALS*) csound->QueryGlobalVariable(csound, "serialGlobals_"); if (q == NULL) { if (csound->CreateGlobalVariable(csound, "serialGlobals_", sizeof(SERIAL_GLOBALS)) != 0){ csound->ErrorMsg(csound, Str("serial: failed to allocate globals")); return 0; } q = (SERIAL_GLOBALS*) csound->QueryGlobalVariable(csound, "serialGlobals_"); q->csound = csound; q->maxind = 0; } /* WCHAR wport[256]; */ /* MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED, serialport, */ /* strlen(serialport)+1, */ /* (LPCSTR)wport, 256); */ /* hSerial = CreateFile(serialport, GENERIC_READ | GENERIC_WRITE, 0, */ /* 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); */ hSerial = CreateFileA(serialport, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); //Check if the connection was successfull if (hSerial==INVALID_HANDLE_VALUE) { //If not success full display an Error return csound->InitError(csound, Str("%s not available.\n"), serialport); } memset(&dcbSerialParams, 0, sizeof(dcbSerialParams)); dcbSerialParams.DCBlength=sizeof(dcbSerialParams); switch (baud) { case 1200: dcbSerialParams.BaudRate = CBR_1200; break; case 2400: dcbSerialParams.BaudRate = CBR_2400; break; case 4800: dcbSerialParams.BaudRate = CBR_4800; break; default: case 9600: dcbSerialParams.BaudRate = CBR_9600; break; case 14400: dcbSerialParams.BaudRate = CBR_14400; break; case 19200: dcbSerialParams.BaudRate = CBR_19200; break; case 38400: dcbSerialParams.BaudRate = CBR_38400; break; case 56000: dcbSerialParams.BaudRate = CBR_56000; break; case 57600: dcbSerialParams.BaudRate = CBR_57600; break; case 115200: dcbSerialParams.BaudRate = CBR_115200; break; case 128000: dcbSerialParams.BaudRate = CBR_128000; break; case 256000: dcbSerialParams.BaudRate = CBR_256000; break; } dcbSerialParams.ByteSize=8; dcbSerialParams.StopBits=ONESTOPBIT; dcbSerialParams.Parity=NOPARITY; SetCommState(hSerial, &dcbSerialParams); for(i=0; i>q->maxind; i++) { if (q->handles[i]==NULL) { q->handles[i] = hSerial; return i; } } if (q->maxind>=10) return csound->InitError(csound, Str("Number of serial handles exhausted")); q->handles[q->maxind++] = hSerial; return q->maxind-1; } /* Also #define BAUD_075 1 #define BAUD_110 2 #define BAUD_134_5 4 #define BAUD_150 8 #define BAUD_300 16 #define BAUD_600 32 #define BAUD_1200 64 #define BAUD_1800 128 #define BAUD_2400 256 #define BAUD_4800 512 #define BAUD_7200 1024 #define BAUD_9600 2048 #define BAUD_14400 4096 #define BAUD_19200 8192 #define BAUD_38400 16384 #define BAUD_56K 32768 #define BAUD_128K 65536 #define BAUD_115200 131072 #define BAUD_57600 262144 */ #endif int serialBegin(CSOUND *csound, SERIALBEGIN *p) { *p->returnedPort = (MYFLT)serialport_init(csound, (char *)p->portName->data, *p->baudRate); return OK; } int serialEnd(CSOUND *csound, SERIALEND *p) { #ifdef WN32 SERIAL_GLOBALS *q; q = (SERIAL_GLOBALS*) csound->QueryGlobalVariable(csound, "serialGlobals_"); if (q = NULL) return csound->PerfError(csound, Str("Nothing to close")); CloseHandle((HANDLE)q->handles[(int)p->port]); q->handles[(int)*p->port] = NULL; #else close((int)*p->port); #endif return OK; } int serialWrite(CSOUND *csound, SERIALWRITE *p) { #ifdef WIN32 HANDLE port = get_port(csound, (int)*p->port); if (port==NULL) return NOTOK; #endif { unsigned char b = *p->toWrite; #ifndef WIN32 if (UNLIKELY(write((int)*p->port, &b, 1)<0)) return NOTOK; #else int nbytes; WriteFile(port, &b, 1, (PDWORD)&nbytes, NULL); #endif } return OK; } int serialWrite_S(CSOUND *csound, SERIALWRITE *p) { #ifdef WIN32 HANDLE port = get_port(csound, (int)*p->port); if (port==NULL) return NOTOK; #endif #ifndef WIN32 if (UNLIKELY(write((int)*p->port, ((STRINGDAT*)p->toWrite)->data, ((STRINGDAT*)p->toWrite)->size))!= ((STRINGDAT*)p->toWrite)->size) /* Does Windows write behave correctly? */ return NOTOK; #else int nbytes; WriteFile(port,p->toWrite, strlen((char *)p->toWrite), (PDWORD)&nbytes, NULL); #endif return OK; } int serialRead(CSOUND *csound, SERIALREAD *p) { unsigned char b = 0; #ifdef WIN32 size_t bytes; HANDLE port = get_port(csound, (int)*p->port); if (port==NULL) return NOTOK; ReadFile(port, &b, 1, (PDWORD)&bytes, NULL); #else ssize_t bytes; bytes = read((int)*p->port, &b, 1); #endif if (bytes > 0) *p->rChar = b; else *p->rChar = -1; return OK; } int serialPrint(CSOUND *csound, SERIALPRINT *p) { char str[32769]; #ifdef WIN32 size_t bytes; HANDLE port = get_port(csound, (int)*p->port); if (port==NULL) return NOTOK; ReadFile(port, str, 32768, (PDWORD)&bytes, NULL); #else ssize_t bytes; bytes = read((int)*p->port, str, 32768); #endif if (bytes > 0) { str[bytes] = '\0'; // terminate csound->MessageS(csound, CSOUNDMSG_ORCH, "%s", str); } return OK; } int serialFlush(CSOUND *csound, SERIALFLUSH *p) { #ifndef WIN32 tcflush(*p->port, TCIFLUSH); // who knows if this works... #endif return OK; } int serialAvailable(CSOUND *csound, SERIALAVAIL *p) { //TODO return OK; } int serialPeekByte(CSOUND *csound, SERIALPEEK *p) { //TODO return OK; } #define S(x) sizeof(x) static OENTRY serial_localops[] = { { (char *)"serialBegin", S(SERIALBEGIN), 0, 1, (char *)"i", (char *)"So", (SUBR)serialBegin, (SUBR)NULL, (SUBR)NULL }, { (char *)"serialEnd", S(SERIALEND), 0, 2, (char *)"", (char *)"i", (SUBR)NULL, (SUBR)serialEnd, (SUBR)NULL }, { (char *)"serialWrite_i", S(SERIALWRITE), 0, 1, (char *)"", (char *)"ii", (SUBR)serialWrite, (SUBR)NULL, (SUBR)NULL }, { (char *)"serialWrite_i.S", S(SERIALWRITE), 0, 1, (char *)"", (char *)"iS", (SUBR)serialWrite_S, (SUBR)NULL, (SUBR)NULL }, { (char *)"serialWrite", S(SERIALWRITE), WR, 2, (char *)"", (char *)"ik", (SUBR)NULL, (SUBR)serialWrite, (SUBR)NULL }, { (char *)"serialWrite.S", S(SERIALWRITE), WR, 2, (char *)"", (char *)"iS", (SUBR)NULL, (SUBR)serialWrite_S, (SUBR)NULL }, { (char *)"serialRead", S(SERIALREAD), 0, 2, (char *)"k", (char *)"i", (SUBR)NULL, (SUBR)serialRead, (SUBR)NULL }, { (char *)"serialPrint", S(SERIALPRINT), WR,2, (char *)"", (char *)"i", (SUBR)NULL, (SUBR)serialPrint, (SUBR)NULL }, { (char *)"serialFlush", S(SERIALFLUSH), 0, 2, (char *)"", (char *)"i", (SUBR)NULL, (SUBR)serialFlush, (SUBR)NULL }, /* { (char *)"serialAvailable", S(SERIALAVAIL), 0, 2, (char *)"k", (char *)"i", */ /* (SUBR)NULL, (SUBR)serialAvailable, (SUBR)NULL }, */ /* { (char *)"serialPeekByte", S(SERIALPEEK),0, 2, (char *)"k", (char *)"i", */ /* (SUBR)NULL, (SUBR)serialPeekByte, (SUBR)NULL } */ }; LINKAGE_BUILTIN(serial_localops) csound-6.10.0/Opcodes/sf.h000066400000000000000000000067261321653344700152710ustar00rootroot00000000000000/* sf.h: Copyright (C) 2000 Gabriel Maldonado, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #if !defined(_SF_H) #include "sftype.h" #ifdef __GNUC__ # ifndef PACKED # define PACKED __attribute__((packed)) # endif /* PACKED */ #else # define PACKED #endif #ifdef MSVC # pragma pack(push, before, 1) #endif struct _splitType { int num; sfSample *sample; BYTE sampleModes; BYTE minNoteRange; BYTE maxNoteRange; BYTE minVelRange; BYTE maxVelRange; long startOffset; long endOffset; long startLoopOffset; long endLoopOffset; char overridingRootKey; char coarseTune; char fineTune; SHORT scaleTuning; SHORT initialAttenuation; SHORT pan; MYFLT attack; MYFLT decay; MYFLT sustain; MYFLT release; } PACKED; typedef struct _splitType splitType; struct _instrType { int num; char *name; BYTE splits_num; splitType *split; } PACKED; typedef struct _instrType instrType; struct _layerType { int num; char *name; BYTE splits_num; splitType *split; BYTE minNoteRange; BYTE maxNoteRange; BYTE minVelRange; BYTE maxVelRange; char coarseTune; char fineTune; SHORT scaleTuning; SHORT initialAttenuation; SHORT pan; } PACKED; typedef struct _layerType layerType; struct _presetType { char *name; int num; WORD prog; WORD bank; int layers_num; layerType *layer; } PACKED; typedef struct _presetType presetType; struct _CHUNK { BYTE ckID[4]; /* A chunk ID identifies the type of data within the chunk. */ DWORD ckSize; /* The size of the chunk data in bytes, excluding any pad byte. */ BYTE *ckDATA; /* The actual data plus a pad byte if reqd to word align. */ } PACKED; typedef struct _CHUNK CHUNK; struct _CHUNKS { CHUNK main_chunk; CHUNK *phdrChunk, *pbagChunk, *pmodChunk, *pgenChunk, *instChunk, *ibagChunk, *imodChunk, *igenChunk, *shdrChunk, *smplChunk; sfPresetHeader *phdr; sfInst *inst; sfSample *shdr; sfPresetBag *pbag; sfModList *pmod; sfGenList *pgen; sfInstBag *ibag; sfInstModList *imod; sfInstGenList *igen; } PACKED; typedef struct _CHUNKS CHUNKS; struct _SFBANK { char name[256]; int presets_num; presetType *preset; int instrs_num; instrType *instr; SHORT *sampleData; CHUNKS chunk; } PACKED; typedef struct _SFBANK SFBANK; #ifdef MSVC # pragma pack(pop, before) #endif #define _SF_H #endif csound-6.10.0/Opcodes/sfenum.h000066400000000000000000000133671321653344700161550ustar00rootroot00000000000000/* sfenum.h: Copyright (C) 1995-1998 Creative Technology Ltd. / E-mu Systems, Inc. This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* ////////////////////////////////////////////////////////////////////////// // // // SFENUM.H // // // // Description : Header file for acccesing the SoundFont Edit Engine // // // // Copyright (c) Creative Technology Ltd. / E-mu Systems, Inc. // // 1995-1998. All rights reserved. // // // // Revision: 1.00 // // // ////////////////////////////////////////////////////////////////////////// */ #ifndef _SFENUM_H #define _SFENUM_H typedef enum { /* Oscillator */ startAddrsOffset, /*sample start address -4 (0 to 0xffffff) 0 */ endAddrsOffset, startloopAddrsOffset, /*loop start address -4 (0 to 0xffffff) */ endloopAddrsOffset, /*loop end address -3 (0 to 0xffffff) */ /* Pitch */ startAddrsCoarseOffset, /*CHANGED FOR SF2 */ modLfoToPitch, /*main fm: lfo1-> pitch 5 */ vibLfoToPitch, /*aux fm: lfo2-> pitch */ modEnvToPitch, /*pitch env: env1(aux)-> pitch */ /* Filter */ initialFilterFc, /*initial filter cutoff */ initialFilterQ, /*filter Q */ modLfoToFilterFc, /*filter modulation: lfo1 -> filter cutoff 10 */ modEnvToFilterFc, /*filter env: env1(aux)-> filter cutoff */ /* Amplifier */ endAddrsCoarseOffset, /*CHANGED FOR SF2 */ modLfoToVolume, /*tremolo: lfo1-> volume */ unused1, /* Effects */ chorusEffectsSend, /*chorus 15 */ reverbEffectsSend, /*reverb */ pan, unused2, unused3, unused4, /* 20 */ /* Main lfo1 */ delayModLFO, /*delay 0x8000-n*(725us) */ freqModLFO, /*frequency */ /* Aux lfo2 */ delayVibLFO, /*delay 0x8000-n*(725us) */ freqVibLFO, /*frequency */ /* Env1(aux/value) */ delayModEnv, /*delay 0x8000 - n(725us) 25 */ attackModEnv, /*attack */ holdModEnv, /*hold */ decayModEnv, /*decay */ sustainModEnv, /*sustain */ releaseModEnv, /*release 30 */ keynumToModEnvHold, keynumToModEnvDecay, /* Env2(ampl/vol) */ delayVolEnv, /*delay 0x8000 - n(725us) */ attackVolEnv, /*attack */ holdVolEnv, /*hold 35 */ decayVolEnv, /*decay */ sustainVolEnv, /*sustain */ releaseVolEnv, /*release */ keynumToVolEnvHold, keynumToVolEnvDecay, /* 40 */ /* Preset */ instrument, reserved1, keyRange, velRange, startloopAddrCoarseOffset, /*CHANGED FOR SF2 45 */ keynum, velocity, initialAttenuation, /*CHANGED FOR SF2 */ reserved2, endloopAddrsCoarseOffset, /*CHANGED FOR SF2 50 */ coarseTune, fineTune, sampleID, sampleModes, /*CHANGED FOR SF2 */ reserved3, /* 55 */ scaleTuning, exclusiveClass, overridingRootKey, unused5, endOper /* 60 */ } SFGenerator; typedef enum { /* Start of MIDI modulation operators */ cc1_Mod, cc7_Vol, cc10_Pan, cc64_Sustain, cc91_Reverb, cc93_Chorus, ccPitchBend, ccIndirectModX, ccIndirectModY, endMod } SFModulator; #ifdef never #define monoSample 0x0001 #define rightSample 0x0002 #define leftSample 0x0004 #define linkedSample 0x0008 #define ROMSample 0x8000 /* 32768 */ #define ROMMonoSample 0x8001 /* 32769 */ #define ROMRightSample 0x8002 /* 32770 */ #define ROMLeftSample 0x8004 /* 32772 */ #define ROMLinkedSample 0x8008 /* 32776 */ #endif enum scaleTuning { equalTemp, fiftyCents }; enum SFSampleField /*used by Sample Read Module */ { NAME_FIELD = 1, START_FIELD, END_FIELD, START_LOOP_FIELD, END_LOOP_FIELD, SMPL_RATE_FIELD, ORG_KEY_FIELD, CORRECTION_FIELD, SMPL_LINK_FIELD, SMPL_TYPE_FIELD }; enum SFInfoChunkField /*used by Bank Read Module */ { IFIL_FIELD = 1, IROM_FIELD, IVER_FIELD, ISNG_FIELD, INAM_FIELD, IPRD_FIELD, IENG_FIELD, ISFT_FIELD, ICRD_FIELD, ICMT_FIELD, ICOP_FIELD }; #endif /*_SFENUM_H */ csound-6.10.0/Opcodes/sfont.c000066400000000000000000002760771321653344700160150ustar00rootroot00000000000000/* sfont.c: Copyright (C) 2000-7 Gabriel Maldonado, John ffitch, Victor Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* WARNING! This file MUST be compiled by setting the structure member alignment (compiler option) to 1 byte. That is: no padding bytes should be present between a structure data member and another. This code will cause memory access faults and crash Csound if compiled with structure member alignment different than 1. See the documentation of your C compiler to choose the appropriate compiler directive switch. */ // #include "csdl.h" #include "csoundCore.h" #include "interlocks.h" #include #include #include #include #include #include "sfenum.h" #include "sfont.h" #define s2d(x) *((DWORD *) (x)) static int chunk_read(CSOUND *, FILE *f, CHUNK *chunk); static void fill_SfPointers(CSOUND *); static int fill_SfStruct(CSOUND *); static void layerDefaults(layerType *layer); static void splitDefaults(splitType *split); #define MAX_SFONT (10) #define MAX_SFPRESET (16384) #define GLOBAL_ATTENUATION (FL(0.3)) #define ONETWELTH (0.08333333333333333333333333333) #define TWOTOTWELTH (1.05946309435929526456182529495) typedef struct _sfontg { SFBANK *soundFont; SFBANK *sfArray; int currSFndx; int maxSFndx; presetType **presetp; SHORT **sampleBase; MYFLT pitches[128]; } sfontg; int sfont_ModuleDestroy(CSOUND *csound) { int j,k,l; SFBANK *sfArray; sfontg *globals; globals = (sfontg *) (csound->QueryGlobalVariable(csound, "::sfontg")); if (globals == NULL) return 0; sfArray = globals->sfArray; for (j=0; jcurrSFndx; j++) { for (k=0; k< sfArray[j].presets_num; k++) { for (l=0; lFree(csound, sfArray[j].preset[k].layer[l].split); } csound->Free(csound, sfArray[j].preset[k].layer); } csound->Free(csound, sfArray[j].preset); for (l=0; l< sfArray[j].instrs_num; l++) { csound->Free(csound, sfArray[j].instr[l].split); } csound->Free(csound, sfArray[j].instr); csound->Free(csound, sfArray[j].chunk.main_chunk.ckDATA); } csound->Free(csound, sfArray); globals->currSFndx = 0; csound->Free(csound, globals->presetp); csound->Free(csound, globals->sampleBase); csound->DestroyGlobalVariable(csound, "::sfontg"); return 0; } static void SoundFontLoad(CSOUND *csound, char *fname) { FILE *fil; void *fd; SFBANK *soundFont; sfontg *globals; globals = (sfontg *) (csound->QueryGlobalVariable(csound, "::sfontg")); soundFont = globals->soundFont; fd = csound->FileOpen2(csound, &fil, CSFILE_STD, fname, "rb", "SFDIR;SSDIR", CSFTYPE_SOUNDFONT, 0); if (UNLIKELY(fd == NULL)) { csound->ErrorMsg(csound, Str("sfload: cannot open SoundFont file \"%s\" (error %s)"), fname, strerror(errno)); return; } soundFont = &globals->sfArray[globals->currSFndx]; /* if (UNLIKELY(soundFont==NULL)){ */ /* csound->ErrorMsg(csound, Str("Sfload: cannot use globals")); */ /* return; */ /* } */ strncpy(soundFont->name, csound->GetFileName(fd), 255); soundFont->name[255]='\0'; if (UNLIKELY(chunk_read(csound, fil, &soundFont->chunk.main_chunk)<0)) csound->Message(csound, Str("sfont: failed to read file\n")); csound->FileClose(csound, fd); globals->soundFont = soundFont; fill_SfPointers(csound); fill_SfStruct(csound); } static int compare(presetType * elem1, presetType *elem2) { if (elem1->bank * 128 + elem1->prog > elem2->bank * 128 + elem2->prog) return 1; else return -1; } /* syntax: ihandle SfLoad "filename" */ static char *Gfname; /* NOT THREAD SAFE */ static int SfLoad_(CSOUND *csound, SFLOAD *p, int istring) /* open a file and return its handle */ { /* the handle is simply a stack index */ char *fname; SFBANK *sf; sfontg *globals; globals = (sfontg *) (csound->QueryGlobalVariable(csound, "::sfontg")); if (UNLIKELY(globals==NULL)) { return csound->InitError(csound, Str("sfload: could not open globals\n")); } if (istring) fname = csound->Strdup(csound, ((STRINGDAT *)p->fname)->data); else { if (csound->ISSTRCOD(*p->fname)) fname = csound->Strdup(csound, get_arg_string(csound,*p->fname)); else fname = csound->strarg2name(csound, NULL, p->fname, "sfont.", 0); } /* strcpy(fname, (char*) p->fname); */ Gfname = fname; SoundFontLoad(csound, fname); *p->ihandle = (float) globals->currSFndx; sf = &globals->sfArray[globals->currSFndx]; qsort(sf->preset, sf->presets_num, sizeof(presetType), (int (*)(const void *, const void * )) compare); csound->Free(csound,fname); if (UNLIKELY(++globals->currSFndx>=globals->maxSFndx)) { globals->maxSFndx += 5; globals->sfArray = (SFBANK *)csound->ReAlloc(csound, globals->sfArray, /* JPff fix */ globals->maxSFndx*sizeof(SFBANK)); csound->Warning(csound, Str("Extending soundfonts")); if (globals->sfArray == NULL) return NOTOK; } return OK; } static int SfLoad(CSOUND *csound, SFLOAD *p){ return SfLoad_(csound,p,0); } static int SfLoad_S(CSOUND *csound, SFLOAD *p){ return SfLoad_(csound,p,1); } static char *filter_string(char *s, char temp_string[24]) { int i=0, j=0; int c; for (i=0; i<22; i++, j++) { c = s[j]; if (c=='\0') break; if (isprint(c)) temp_string[i]=c; else if (c<32) { temp_string[i++]='^'; temp_string[i] = '@'+c; } else temp_string[i]='?'; } temp_string[i] = '\0'; return temp_string; } static int Sfplist(CSOUND *csound, SFPLIST *p) { sfontg *globals; SFBANK *sf; char temp_string[24]; int j; globals = (sfontg *) (csound->QueryGlobalVariable(csound, "::sfontg")); sf = &globals->sfArray[(int) *p->ihandle]; csound->Message(csound, Str("\nPreset list of \"%s\"\n"), sf->name); for (j =0; j < sf->presets_num; j++) { presetType *prs = &sf->preset[j]; csound->Message(csound, Str("%3d) %-20s\tprog:%-3d bank:%d\n"), j, filter_string(prs->name, temp_string), prs->prog, prs->bank); } csound->Message(csound, "\n"); return OK; } static int SfAssignAllPresets(CSOUND *csound, SFPASSIGN *p) { sfontg *globals; SFBANK *sf; int pHandle, pnum; int j, enableMsgs; globals = (sfontg *) (csound->QueryGlobalVariable(csound, "::sfontg")); sf = &globals->sfArray[(int) *p->ihandle]; pHandle = (int) *p->startNum; pnum = sf->presets_num; enableMsgs = (*p->msgs==FL(0.0)); if (enableMsgs) csound->Message(csound, Str("\nAssigning all Presets of \"%s\" starting from" " %d (preset handle number)\n"), sf->name, pHandle); for (j = 0; j < pnum; j++) { presetType *prs = &sf->preset[j]; if (enableMsgs) csound->Message(csound, Str("%3d<--%-20s\t(prog:%-3d bank:%d)\n"), j, prs->name, prs->prog, prs->bank); globals->presetp[pHandle] = &sf->preset[j]; globals->sampleBase[pHandle] = sf->sampleData; pHandle++; } if (enableMsgs) csound->Message(csound, Str("\nAll presets have been assigned to preset" " handles from %d to %d \n\n"), (int) *p->startNum, pHandle - 1); return OK; } static int Sfilist(CSOUND *csound, SFPLIST *p) { sfontg *globals; SFBANK *sf; int j; globals = (sfontg *) (csound->QueryGlobalVariable(csound, "::sfontg")); sf = &globals->sfArray[(int) *p->ihandle]; csound->Message(csound, Str("\nInstrument list of \"%s\"\n"), sf->name); for (j =0; j < sf->instrs_num; j++) { instrType *inst = &sf->instr[j]; csound->Message(csound, "%3d) %-20s\n", j, inst->name); } csound->Message(csound, "\n"); return OK; } static int SfPreset(CSOUND *csound, SFPRESET *p) { sfontg *globals; SFBANK *sf; int j, presetHandle = (int) *p->iPresetHandle; globals = (sfontg *) (csound->QueryGlobalVariable(csound, "::sfontg")); sf = &globals->sfArray[(DWORD) *p->isfhandle]; if (presetHandle >= MAX_SFPRESET) { return csound->InitError(csound, Str("sfpreset: preset handle too big (%d), max: %d"), presetHandle, (int) MAX_SFPRESET - 1); } for (j=0; j< sf->presets_num; j++) { if (sf->preset[j].prog == (WORD) *p->iprog && sf->preset[j].bank == (WORD) *p->ibank ) { globals->presetp[presetHandle] = &sf->preset[j]; globals->sampleBase[presetHandle] = sf->sampleData; break; } } *p->ipresethandle = (MYFLT) presetHandle; if (UNLIKELY(globals->presetp[presetHandle] == NULL)) { return csound->InitError(csound, Str("sfpreset: cannot find any preset having prog " "number %d and bank number %d in SoundFont file" " \"%s\""), (int) *p->iprog, (int) *p->ibank, globals->sfArray[(DWORD) *p->isfhandle].name); } return OK; } static int SfPlay_set(CSOUND *csound, SFPLAY *p) { DWORD index = (DWORD) *p->ipresethandle; presetType *preset; SHORT *sBase; int layersNum, j, spltNum = 0, flag = (int) *p->iflag; sfontg *globals; globals = (sfontg *) (csound->QueryGlobalVariable(csound, "::sfontg")); preset = globals->presetp[index]; sBase = globals->sampleBase[index]; if (!UNLIKELY(preset!=NULL)) { return csound->InitError(csound, Str("sfplay: invalid or " "out-of-range preset number")); } layersNum = preset->layers_num; for (j =0; j < layersNum; j++) { layerType *layer = &preset->layer[j]; int vel= (int) *p->ivel, notnum= (int) *p->inotnum; if (notnum >= layer->minNoteRange && notnum <= layer->maxNoteRange && vel >= layer->minVelRange && vel <= layer->maxVelRange) { int splitsNum = layer->splits_num, k; for (k = 0; k < splitsNum; k++) { splitType *split = &layer->split[k]; if (notnum >= split->minNoteRange && notnum <= split->maxNoteRange && vel >= split->minVelRange && vel <= split->maxVelRange) { sfSample *sample = split->sample; DWORD start=sample->dwStart; MYFLT attenuation; double pan; double freq, orgfreq; double tuneCorrection = split->coarseTune + layer->coarseTune + (split->fineTune + layer->fineTune)*0.01; int orgkey = split->overridingRootKey; if (orgkey == -1) orgkey = sample->byOriginalKey; orgfreq = globals->pitches[orgkey]; if (flag) { freq = orgfreq * pow(2.0, ONETWELTH * tuneCorrection); p->si[spltNum]= (freq/(orgfreq*orgfreq))* sample->dwSampleRate*csound->onedsr; } else { freq = orgfreq * pow(2.0, ONETWELTH * tuneCorrection) * pow(2.0, ONETWELTH * (split->scaleTuning*0.01) * (notnum-orgkey)); p->si[spltNum]= (freq/orgfreq) * sample->dwSampleRate*csound->onedsr; } attenuation = (MYFLT) (layer->initialAttenuation + split->initialAttenuation); attenuation = POWER(FL(2.0), (-FL(1.0)/FL(60.0)) * attenuation ) * GLOBAL_ATTENUATION; pan = (double)(split->pan + layer->pan) / 1000.0 + 0.5; if (pan > 1.0) pan = 1.0; else if (pan < 0.0) pan = 0.0; /* Suggested fix from steven yi Oct 2002 */ p->base[spltNum] = sBase + start; p->phs[spltNum] = (double) split->startOffset + *p->ioffset; p->end[spltNum] = sample->dwEnd + split->endOffset - start; p->startloop[spltNum] = sample->dwStartloop + split->startLoopOffset - start; p->endloop[spltNum] = sample->dwEndloop + split->endLoopOffset - start; p->leftlevel[spltNum] = (MYFLT) sqrt(1.0-pan) * attenuation; p->rightlevel[spltNum] = (MYFLT) sqrt(pan) * attenuation; p->mode[spltNum]= split->sampleModes; p->attack[spltNum] = split->attack*CS_EKR; p->decay[spltNum] = split->decay*CS_EKR; p->sustain[spltNum] = split->sustain; p->release[spltNum] = split->release*CS_EKR; if (*p->ienv > 1) { p->attr[spltNum] = 1.0/(CS_EKR*split->attack); p->decr[spltNum] = pow((split->sustain+0.0001), 1.0/(CS_EKR* split->decay+0.0001)); if (split->attack != 0.0) p->env[spltNum] = 0.0; else p->env[spltNum] = 1.0; } else if (*p->ienv > 0) { p->attr[spltNum] = 1.0/(CS_EKR*split->attack); p->decr[spltNum] = (split->sustain-1.0)/(CS_EKR* split->decay); if (split->attack != 0.0) p->env[spltNum] = 0.0; else p->env[spltNum] = 1.0; } else { p->env[spltNum] = 1.0; } p->ti[spltNum] = 0; spltNum++; } } } } p->spltNum = spltNum; return OK; } #define Linear_interpolation \ SHORT *curr_samp = *base + (int32) *phs;\ MYFLT fract = (MYFLT) *phs - (MYFLT)((int32)*phs);\ MYFLT out = (*curr_samp + (*(curr_samp+1) - *curr_samp)*fract); #define Cubic_interpolation \ MYFLT phs1 = (MYFLT) *phs -FL(1.0);\ int x0 = (int32)phs1 ;\ MYFLT fract = (MYFLT)(phs1 - x0);\ SHORT *ftab = *base + x0;\ MYFLT ym1= *ftab++;\ MYFLT y0 = *ftab++;\ MYFLT y1 = *ftab++;\ MYFLT y2 = *ftab;\ MYFLT frsq = fract*fract;\ MYFLT frcu = frsq*ym1;\ MYFLT t1 = y2 + FL(3.0)*y0;\ MYFLT out = y0 + FL(0.5)*frcu + \ fract*(y1 - frcu/FL(6.0) - t1/FL(6.0) - ym1/FL(3.0)) + \ frsq*fract*(t1/FL(6.0) - FL(0.5)*y1) + frsq*(FL(0.5)* y1 - y0); #define Looped \ if (*phs >= *startloop) flag = 1; \ if (flag) { \ while (*phs >= *endloop) *phs -= looplength; \ while (*phs < *startloop) *phs += looplength; \ } #define ExpEnvelope \ if (*tinc < *attack) *env += *attr; \ else if (*tinc < *decay + *attack) *env *= *decr; \ else *env = *sustain; \ (*tinc)++; \ #define LinEnvelope \ if (*tinc < *attack) *env += *attr; \ else if (*tinc < *decay + *attack) *env += *decr; \ else *env = *sustain; \ (*tinc)++; \ #define Unlooped \ if (*phs > *end) break; \ if (*phs < FL(0.0)) *phs = FL(0.0); \ #define Mono_out \ out1[n] += *attenuation * out * (*env); \ *phs += si; #define Stereo_out \ out1[n] += *left * out * (*env);\ out2[n] += *right * out * (*env);\ *phs += si; static int SfPlay(CSOUND *csound, SFPLAY *p) { MYFLT *out1 = p->out1, *out2 = p->out2, *env = p->env; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int j = p->spltNum; SHORT **base = p->base; DWORD *end = p->end, *startloop= p->startloop, *endloop= p->endloop, *tinc = p->ti; SHORT *mode = p->mode; double *sampinc = p->si, *phs = p->phs; MYFLT *left= p->leftlevel, *right= p->rightlevel, *attack = p->attack, *decr = p->decr, *decay = p->decay, *sustain= p->sustain, *release = p->release, *attr = p->attr; memset(out1, 0, nsmps*sizeof(MYFLT)); memset(out2, 0, nsmps*sizeof(MYFLT)); if (UNLIKELY(early)) nsmps -= early; if (IS_ASIG_ARG(p->xfreq)) { while (j--) { double looplength = *endloop - *startloop; MYFLT *freq = p->xfreq; if (*mode == 1 || *mode ==3) { int flag =0; if (*p->ienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nxfreq; while (j--) { double looplength = *endloop - *startloop; double si = *sampinc * freq; if (*mode == 1 || *mode ==3) { int flag =0; if (*p->ienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nxamp)) { MYFLT *amp = p->xamp; for (n=offset;nxamp; for (n=offset;nout1, *out2 = p->out2, *env = p->env; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int j = p->spltNum; SHORT **base = p->base; DWORD *end = p->end, *startloop = p->startloop, *endloop = p->endloop, *tinc = p->ti; SHORT *mode = p->mode; double *sampinc = p->si, *phs = p->phs; MYFLT *left= p->leftlevel, *right= p->rightlevel, *attack = p->attack, *decr = p->decr, *decay = p->decay, *sustain= p->sustain, *release = p->release, *attr = p->attr; memset(out1, 0, nsmps*sizeof(MYFLT)); memset(out2, 0, nsmps*sizeof(MYFLT)); if (UNLIKELY(early)) nsmps -= early; if (IS_ASIG_ARG(p->xfreq)) { while (j--) { double looplength = *endloop - *startloop; MYFLT *freq = p->xfreq; /* nsmps = CS_KSMPS; */ if (*mode == 1 || *mode ==3) { int flag =0; if (*p->ienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nxfreq; while(j--) { double looplength = *endloop - *startloop, si = *sampinc * freq; if (*mode == 1 || *mode ==3) { int flag =0; if (*p->ienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nxamp)) { MYFLT *amp = p->xamp; for (n=offset;nxamp; for (n=offset;nipresethandle; presetType *preset; SHORT *sBase; /* int layersNum= preset->layers_num, j, spltNum = 0, flag=(int) *p->iflag; */ int layersNum, j, spltNum = 0, flag=(int) *p->iflag; sfontg *globals; globals = (sfontg *) (csound->QueryGlobalVariable(csound, "::sfontg")); preset = globals->presetp[index]; sBase = globals->sampleBase[index]; if (UNLIKELY(!preset)) { return csound->InitError(csound, Str("sfplaym: invalid or " "out-of-range preset number")); } layersNum= preset->layers_num; for (j =0; j < layersNum; j++) { layerType *layer = &preset->layer[j]; int vel= (int) *p->ivel, notnum= (int) *p->inotnum; if (notnum >= layer->minNoteRange && notnum <= layer->maxNoteRange && vel >= layer->minVelRange && vel <= layer->maxVelRange) { int splitsNum = layer->splits_num, k; for (k = 0; k < splitsNum; k++) { splitType *split = &layer->split[k]; if (notnum >= split->minNoteRange && notnum <= split->maxNoteRange && vel >= split->minVelRange && vel <= split->maxVelRange) { sfSample *sample = split->sample; DWORD start=sample->dwStart; double freq, orgfreq; double tuneCorrection = split->coarseTune + layer->coarseTune + (split->fineTune + layer->fineTune)*0.01; int orgkey = split->overridingRootKey; if (orgkey == -1) orgkey = sample->byOriginalKey; orgfreq = globals->pitches[orgkey] ; if (flag) { freq = orgfreq * pow(2.0, ONETWELTH * tuneCorrection); p->si[spltNum]= (freq/(orgfreq*orgfreq))* sample->dwSampleRate*csound->onedsr; } else { freq = orgfreq * pow(2.0, ONETWELTH * tuneCorrection) * pow( 2.0, ONETWELTH* (split->scaleTuning*0.01) * (notnum-orgkey)); p->si[spltNum]= (freq/orgfreq) * sample->dwSampleRate*csound->onedsr; } p->attenuation[spltNum] = POWER(FL(2.0), (-FL(1.0)/FL(60.0)) * (layer->initialAttenuation + split->initialAttenuation)) * GLOBAL_ATTENUATION; p->base[spltNum] = sBase+ start; p->phs[spltNum] = (double) split->startOffset + *p->ioffset; p->end[spltNum] = sample->dwEnd + split->endOffset - start; p->startloop[spltNum] = sample->dwStartloop + split->startLoopOffset - start; p->endloop[spltNum] = sample->dwEndloop + split->endLoopOffset - start; p->mode[spltNum]= split->sampleModes; p->attack[spltNum] = split->attack*CS_EKR; p->decay[spltNum] = split->decay*CS_EKR; p->sustain[spltNum] = split->sustain; p->release[spltNum] = split->release*CS_EKR; if (*p->ienv > 1) { p->attr[spltNum] = 1.0/(CS_EKR*split->attack); p->decr[spltNum] = pow((split->sustain+0.0001), 1.0/(CS_EKR* split->decay+0.0001)); if (split->attack != 0.0) p->env[spltNum] = 0.0; else p->env[spltNum] = 1.0; } else if (*p->ienv > 0) { p->attr[spltNum] = 1.0/(CS_EKR*split->attack); p->decr[spltNum] = (split->sustain-1.0)/(CS_EKR* split->decay); if (split->attack != 0.0) p->env[spltNum] = 0.0; else p->env[spltNum] = 1.0; } else { p->env[spltNum] = 1.0; } p->ti[spltNum] = 0; spltNum++; } } } } p->spltNum = spltNum; return OK; } static int SfPlayMono(CSOUND *csound, SFPLAYMONO *p) { MYFLT *out1 = p->out1 , *env = p->env; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int j = p->spltNum; SHORT **base = p->base; DWORD *end= p->end, *startloop= p->startloop, *endloop= p->endloop, *tinc = p->ti; SHORT *mode = p->mode; double *sampinc = p->si, *phs = p->phs; MYFLT *attenuation = p->attenuation, *attack = p->attack, *decr = p->decr, *decay = p->decay, *sustain= p->sustain, *release = p->release, *attr = p->attr; memset(out1, 0, nsmps*sizeof(MYFLT)); if (UNLIKELY(early)) nsmps -= early; if (IS_ASIG_ARG(p->xfreq)) { while (j--) { double looplength = *endloop - *startloop; MYFLT *freq = p->xfreq; if (*mode == 1 || *mode ==3) { int flag =0; for (n=offset;nienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } { Linear_interpolation Mono_out Looped } } } else if (*phs < *end) { for (n=offset;nienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } { Linear_interpolation Mono_out Unlooped } } } phs++; base++; sampinc++; endloop++; startloop++; attenuation++, mode++, end++; attack++; decay++; sustain++; release++; tinc++; env++; attr++; decr++; } } else { MYFLT freq = *p->xfreq; while (j--) { double looplength = *endloop - *startloop; double si = *sampinc * freq; if (*mode == 1 || *mode ==3) { int flag =0; for (n=offset;nienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } { Linear_interpolation Mono_out Looped } } } else if (*phs < *end) { for (n=offset;nienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } { Linear_interpolation Mono_out Unlooped } } } phs++; base++; sampinc++; endloop++; startloop++; attenuation++, mode++, end++; attack++; decay++; sustain++; release++; tinc++; env++; attr++; decr++; } } if (IS_ASIG_ARG(p->xamp)) { MYFLT *amp = p->xamp; for (n=offset;nxamp; for (n=offset;nout1, *env = p->env; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int j = p->spltNum; SHORT **base = p->base; DWORD *end = p->end, *startloop = p->startloop, *endloop = p->endloop, *tinc = p->ti; SHORT *mode = p->mode; double *sampinc = p->si, *phs = p->phs; MYFLT *attenuation = p->attenuation,*attack = p->attack, *decr = p->decr, *decay = p->decay, *sustain= p->sustain, *release = p->release, *attr = p->attr; memset(out1, 0, nsmps*sizeof(MYFLT)); if (UNLIKELY(early)) nsmps -= early; if (IS_ASIG_ARG(p->xfreq)) { while (j--) { double looplength = *endloop - *startloop; MYFLT *freq = p->xfreq; if (*mode == 1 || *mode ==3) { int flag =0; if (*p->ienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nxfreq; while (j--) { double looplength = *endloop - *startloop; double si = *sampinc * freq; if (*mode == 1 || *mode ==3) { int flag =0; if (*p->ienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nxamp)) { MYFLT *amp = p->xamp; for (n=offset;nxamp; for (n=offset;nsfBank; globals = (sfontg *) (csound->QueryGlobalVariable(csound, "::sfontg")); sf = &globals->sfArray[index]; if (UNLIKELY(index > globals->currSFndx || *p->instrNum > sf->instrs_num)) { return csound->InitError(csound, Str("sfinstr: instrument out of range")); } else { instrType *layer = &sf->instr[(int) *p->instrNum]; SHORT *sBase = sf->sampleData; int spltNum = 0, flag=(int) *p->iflag; int vel= (int) *p->ivel, notnum= (int) *p->inotnum; int splitsNum = layer->splits_num, k; for (k = 0; k < splitsNum; k++) { splitType *split = &layer->split[k]; if (notnum >= split->minNoteRange && notnum <= split->maxNoteRange && vel >= split->minVelRange && vel <= split->maxVelRange) { sfSample *sample = split->sample; DWORD start=sample->dwStart; MYFLT attenuation, pan; double freq, orgfreq; double tuneCorrection = split->coarseTune + split->fineTune*0.01; int orgkey = split->overridingRootKey; if (orgkey == -1) orgkey = sample->byOriginalKey; orgfreq = globals->pitches[orgkey] ; if (flag) { freq = orgfreq * pow(2.0, ONETWELTH * tuneCorrection); p->si[spltNum] = (freq/(orgfreq*orgfreq))* sample->dwSampleRate*csound->onedsr; } else { freq = orgfreq * pow(2.0, ONETWELTH * tuneCorrection) * pow( 2.0, ONETWELTH* (split->scaleTuning*0.01)*(notnum - orgkey)); p->si[spltNum] = (freq/orgfreq)*(sample->dwSampleRate*csound->onedsr); } attenuation = (MYFLT) (split->initialAttenuation); attenuation = POWER(FL(2.0), (-FL(1.0)/FL(60.0)) * attenuation) * GLOBAL_ATTENUATION; pan = (MYFLT) split->pan / FL(1000.0) + FL(0.5); if (pan > FL(1.0)) pan =FL(1.0); else if (pan < FL(0.0)) pan = FL(0.0); p->base[spltNum] = sBase + start; p->phs[spltNum] = (double) split->startOffset + *p->ioffset; p->end[spltNum] = sample->dwEnd + split->endOffset - start; p->startloop[spltNum] = sample->dwStartloop + split->startLoopOffset - start; p->endloop[spltNum] = sample->dwEndloop + split->endLoopOffset - start; p->leftlevel[spltNum] = (FL(1.0)-pan) * attenuation; p->rightlevel[spltNum] = pan * attenuation; p->mode[spltNum]= split->sampleModes; p->attack[spltNum] = split->attack*CS_EKR; p->decay[spltNum] = split->decay*CS_EKR; p->sustain[spltNum] = split->sustain; p->release[spltNum] = split->release*CS_EKR; if (*p->ienv > 1) { p->attr[spltNum] = 1.0/(CS_EKR*split->attack); p->decr[spltNum] = pow((split->sustain+0.0001), 1.0/(CS_EKR*split->decay+0.0001)); if (split->attack != 0.0) p->env[spltNum] = 0.0; else p->env[spltNum] = 1.0; } else if (*p->ienv > 0) { p->attr[spltNum] = 1.0/(CS_EKR*split->attack); p->decr[spltNum] = (split->sustain-1.0)/(CS_EKR* split->decay); if (split->attack != 0.0) p->env[spltNum] = 0.0; else p->env[spltNum] = 1.0; } else { p->env[spltNum] = 1.0; } p->ti[spltNum] = 0; spltNum++; } } p->spltNum = spltNum; } return OK; } static int SfInstrPlay(CSOUND *csound, SFIPLAY *p) { MYFLT *out1= p->out1, *out2= p->out2, *env = p->env; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int j = p->spltNum; SHORT **base = p->base; DWORD *end= p->end, *startloop= p->startloop, *endloop= p->endloop, *tinc = p->ti; SHORT *mode = p->mode; double *sampinc = p->si, *phs = p->phs; MYFLT *left= p->leftlevel, *right= p->rightlevel, *attack = p->attack, *decr = p->decr, *decay = p->decay, *sustain= p->sustain, *release = p->release, *attr = p->attr; memset(out1, 0, nsmps*sizeof(MYFLT)); memset(out2, 0, nsmps*sizeof(MYFLT)); if (UNLIKELY(early)) nsmps -= early; if (IS_ASIG_ARG(p->xfreq)) { while (j--) { double looplength = *endloop - *startloop; MYFLT *freq = p->xfreq; if (*mode == 1 || *mode ==3) { int flag =0; if (*p->ienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nxfreq; while (j--) { double looplength = *endloop - *startloop; double si = *sampinc * freq; if (*mode == 1 || *mode ==3) { int flag =0; if (*p->ienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nxamp)) { MYFLT *amp = p->xamp; for (n=offset;nxamp; for (n=offset;nout1, *out2= p->out2,*env =p->env; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int j = p->spltNum; SHORT **base = p->base; DWORD *end= p->end, *startloop= p->startloop, *endloop= p->endloop, *tinc = p->ti; SHORT *mode = p->mode; double *sampinc = p->si, *phs = p->phs; MYFLT *left= p->leftlevel, *right= p->rightlevel, *attack = p->attack, *decr = p->decr, *decay = p->decay, *sustain= p->sustain, *release = p->release, *attr = p->attr; memset(out1, 0, nsmps*sizeof(MYFLT)); memset(out2, 0, nsmps*sizeof(MYFLT)); if (UNLIKELY(early)) nsmps -= early; if (IS_ASIG_ARG(p->xfreq)) { while (j--) { double looplength = *endloop - *startloop; MYFLT *freq = p->xfreq; if (*mode == 1 || *mode ==3) { int flag =0; if (*p->ienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nxfreq; while (j--) { double looplength = *endloop - *startloop; double si = *sampinc * freq; if (*mode == 1 || *mode ==3) { int flag =0; if (*p->ienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nxamp)) { MYFLT *amp = p->xamp; for (n=offset;nxamp; for (n=offset;nsfBank; sfontg *globals; SFBANK *sf; globals = (sfontg *) (csound->QueryGlobalVariable(csound, "::sfontg")); sf = &globals->sfArray[index]; if (UNLIKELY(index > globals->currSFndx || *p->instrNum > sf->instrs_num)) { return csound->InitError(csound, Str("sfinstr: instrument out of range")); } else { instrType *layer = &sf->instr[(int) *p->instrNum]; SHORT *sBase = sf->sampleData; int spltNum = 0, flag=(int) *p->iflag; int vel= (int) *p->ivel, notnum= (int) *p->inotnum; int splitsNum = layer->splits_num, k; for (k = 0; k < splitsNum; k++) { splitType *split = &layer->split[k]; if (notnum >= split->minNoteRange && notnum <= split->maxNoteRange && vel >= split->minVelRange && vel <= split->maxVelRange) { sfSample *sample = split->sample; DWORD start=sample->dwStart; double freq, orgfreq; double tuneCorrection = split->coarseTune + split->fineTune/100.0; int orgkey = split->overridingRootKey; if (orgkey == -1) orgkey = sample->byOriginalKey; orgfreq = globals->pitches[orgkey]; if (flag) { freq = orgfreq * pow(2.0, ONETWELTH * tuneCorrection); p->si[spltNum] = (freq/(orgfreq*orgfreq))* sample->dwSampleRate*csound->onedsr; } else { freq = orgfreq * pow(2.0, ONETWELTH * tuneCorrection) * pow( 2.0, ONETWELTH* (split->scaleTuning*0.01) * (notnum-orgkey)); p->si[spltNum] = (freq/orgfreq)*(sample->dwSampleRate*csound->onedsr); } p->attenuation[spltNum] = (MYFLT) pow(2.0, (-1.0/60.0)* split->initialAttenuation) * GLOBAL_ATTENUATION; p->base[spltNum] = sBase+ start; p->phs[spltNum] = (double) split->startOffset + *p->ioffset; p->end[spltNum] = sample->dwEnd + split->endOffset - start; p->startloop[spltNum] = sample->dwStartloop + split->startLoopOffset - start; p->endloop[spltNum] = sample->dwEndloop + split->endLoopOffset - start; p->mode[spltNum]= split->sampleModes; p->attack[spltNum] = split->attack*CS_EKR; p->decay[spltNum] = split->decay*CS_EKR; p->sustain[spltNum] = split->sustain; p->release[spltNum] = split->release*CS_EKR; if (*p->ienv > 1) { p->attr[spltNum] = 1.0/(CS_EKR*split->attack); p->decr[spltNum] = pow((split->sustain+0.0001), 1.0/(CS_EKR* split->decay+0.0001)); if (split->attack != 0.0) p->env[spltNum] = 0.0; else p->env[spltNum] = 1.0; } else if (*p->ienv > 0) { p->attr[spltNum] = 1.0/(CS_EKR*split->attack); p->decr[spltNum] = (split->sustain-1.0)/(CS_EKR* split->decay); if (split->attack != 0.0) p->env[spltNum] = 0.0; else p->env[spltNum] = 1.0; } else { p->env[spltNum] = 1.0; } p->ti[spltNum] = 0; spltNum++; } } p->spltNum = spltNum; } return OK; } static int SfInstrPlayMono(CSOUND *csound, SFIPLAYMONO *p) { MYFLT *out1= p->out1, *env = p->env; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int j = p->spltNum; SHORT **base = p->base; DWORD *end= p->end, *startloop= p->startloop, *endloop= p->endloop, *tinc = p->ti; SHORT *mode = p->mode; double *sampinc = p->si, *phs = p->phs; MYFLT *attenuation = p->attenuation, *attack = p->attack, *decr = p->decr, *decay = p->decay, *sustain= p->sustain, *release = p->release, *attr = p->attr; memset(out1, 0, nsmps*sizeof(MYFLT)); if (UNLIKELY(early)) nsmps -= early; if (IS_ASIG_ARG(p->xfreq)) { while (j--) { double looplength = *endloop - *startloop; MYFLT *freq = p->xfreq; if (*mode == 1 || *mode ==3) { int flag =0; if (*p->ienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nxfreq; while (j--) { double looplength = *endloop - *startloop; double si = *sampinc * freq; if (*mode == 1 || *mode ==3) { int flag =0; if (*p->ienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nxamp)) { MYFLT *amp = p->xamp; for (n=offset;nxamp; for (n=offset;nout1, *env = p->env ; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int j = p->spltNum; SHORT **base = p->base; DWORD *end= p->end, *startloop= p->startloop, *endloop= p->endloop, *tinc = p->ti; SHORT *mode = p->mode; double *sampinc = p->si, *phs = p->phs; MYFLT *attenuation = p->attenuation,*attack = p->attack, *decr = p->decr, *decay = p->decay, *sustain= p->sustain, *release = p->release, *attr = p->attr; memset(out1, 0, nsmps*sizeof(MYFLT)); if (UNLIKELY(early)) nsmps -= early; if (IS_ASIG_ARG(p->xfreq)) { while (j--) { double looplength = *endloop - *startloop; MYFLT *freq = p->xfreq; if (*mode == 1 || *mode ==3) { int flag =0; if (*p->ienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nxfreq; while (j--) { double looplength = *endloop - *startloop; double si = *sampinc * freq; if (*mode == 1 || *mode ==3) { int flag =0; if (*p->ienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nienv > 1) { ExpEnvelope } else if (*p->ienv > 0) { LinEnvelope } for (n=offset;nxamp)) { MYFLT *amp = p->xamp; for (n=offset;nxamp; for (n=offset;n Little-endian (for Big-endian machines only) * fmt: ((b|w|d)[0-9]*)+ * b:byte (no conversion), w:word, d:double word, digits(optional):repeat n times */ #ifdef WORDS_BIGENDIAN static void ChangeByteOrder(char *fmt, char *p, int32 size) { char c, c1, c2, c3, c4; char *fmt_org = fmt; int32 i, times; while (size > 0) { fmt = fmt_org; while (*fmt) { c = *fmt++; if (isdigit(*fmt)) { times = strtol(fmt, &fmt, 10); } else { times = 1; } for (i = 0; i < times; i++) { switch(c) { case 'b': case 'B': p++; size--; break; case 'w': case 'W': c1 = p[0]; c2 = p[1]; *p++ = c2; *p++ = c1; size -= 2; break; case 'd': case 'D': c1 = p[0]; c2 = p[1]; c3 = p[2]; c4 = p[3]; *p++ = c4; *p++ = c3; *p++ = c2; *p++ = c1; size -= 4; break; } } } } } #else #define ChangeByteOrder(fmt, p, size) /* nothing */ #endif static int fill_SfStruct(CSOUND *csound) { int j, k, i, l, m, size, iStart, iEnd, kk, ll, mStart, mEnd; int pbag_num,first_pbag,layer_num; int ibag_num,first_ibag,split_num; CHUNK *phdrChunk; presetType *preset; sfPresetHeader *phdr; sfPresetBag *pbag; sfGenList *pgen; sfInst *inst; sfInstBag *ibag; /* sfInstModList *imod; */ sfInstGenList *igen; sfSample *shdr; SFBANK *soundFont; sfontg *globals; globals = (sfontg *) (csound->QueryGlobalVariable(csound, "::sfontg")); soundFont = globals->soundFont; /* imod = soundFont->chunk.imod; */ igen = soundFont->chunk.igen; shdr = soundFont->chunk.shdr; phdrChunk= soundFont->chunk.phdrChunk; phdr = soundFont->chunk.phdr; pbag = soundFont->chunk.pbag; pgen = soundFont->chunk.pgen; inst = soundFont->chunk.inst; ibag = soundFont->chunk.ibag; size = phdrChunk->ckSize / sizeof(sfPresetHeader); soundFont->presets_num = size; preset = (presetType *) csound->Malloc(csound, size * sizeof(presetType)); for (j=0; j < size; j++) { preset[j].name = phdr[j].achPresetName; if (strcmp(preset[j].name,"EOP")==0) { soundFont->presets_num = j; goto end_fill_presets; } preset[j].num = j; preset[j].prog = phdr[j].wPreset; preset[j].bank = phdr[j].wBank; first_pbag = phdr[j].wPresetBagNdx; pbag_num = phdr[j+1].wPresetBagNdx - first_pbag; layer_num = 0; for (k = 0 ; k < pbag_num ; k++) { iStart = pbag[k+first_pbag].wGenNdx; iEnd = pbag[k+first_pbag+1].wGenNdx; for (i = iStart; i < iEnd; i++) { if (pgen[i].sfGenOper == instrument ) { layer_num++; } } } preset[j].layers_num = layer_num; preset[j].layer = (layerType *) csound->Malloc(csound, layer_num * sizeof(layerType)); for (k=0; k num = pgen[i].genAmount.wAmount; layer->name = inst[layer->num].achInstName; first_ibag = inst[layer->num].wInstBagNdx; ibag_num = inst[layer->num +1].wInstBagNdx - first_ibag; split_num = 0; for (l=0; l < ibag_num; l++) { mStart = ibag[l+first_ibag].wInstGenNdx; mEnd = ibag[l+first_ibag+1].wInstGenNdx; for (m=mStart; m < mEnd; m++) { if (igen[m].sfGenOper == sampleID) { split_num++; } } } layer->splits_num = split_num; layer->split = (splitType *) csound->Malloc(csound, split_num * sizeof(splitType)); for (l=0; lsplit[l]); } for (l=0, ll=0; l < ibag_num; l++) { int sglobal_zone = 1; mStart = ibag[l+first_ibag].wInstGenNdx; mEnd = ibag[l+first_ibag+1].wInstGenNdx; for (m=mStart; m < mEnd; m++) { if (igen[m].sfGenOper == sampleID) sglobal_zone=0; } if (sglobal_zone) { for (m=mStart; m < mEnd; m++) { switch (igen[m].sfGenOper) { case sampleID: break; case overridingRootKey: GoverridingRootKey = igen[m].genAmount.wAmount; break; case coarseTune: GcoarseTune = igen[m].genAmount.shAmount; break; case fineTune: GfineTune = igen[m].genAmount.shAmount; break; case scaleTuning: GscaleTuning = igen[m].genAmount.shAmount; break; case pan: Gpan = igen[m].genAmount.shAmount; break; case sampleModes: GsampleModes = igen[m].genAmount.wAmount; break; case initialAttenuation: GinitialAttenuation = igen[m].genAmount.shAmount; break; case keyRange: break; case velRange: break; } } } else { splitType *split; split = &layer->split[ll]; split->attack = split->decay = split->sustain = split->release = FL(0.0); if (GoverridingRootKey != UNUSE) split->overridingRootKey = (BYTE) GoverridingRootKey; if (GcoarseTune != UNUSE) split->coarseTune = (BYTE) GcoarseTune; if (GfineTune != UNUSE) split->fineTune = (BYTE) GfineTune; if (GscaleTuning != UNUSE) split->scaleTuning = (BYTE) GscaleTuning; if (Gpan != UNUSE) split->pan = (BYTE) Gpan; if (GsampleModes != UNUSE) split->sampleModes = (BYTE) GsampleModes; if (GinitialAttenuation != UNUSE) split->initialAttenuation = (BYTE) GinitialAttenuation; for (m=mStart; m < mEnd; m++) { switch (igen[m].sfGenOper) { case sampleID: { int num = igen[m].genAmount.wAmount; split->num= num; split->sample = &shdr[num]; if (UNLIKELY(split->sample->sfSampleType & 0x8000)) { csound->Free(csound, preset); csound->ErrorMsg(csound, Str("SoundFont file \"%s\" " "contains ROM samples !\n" "At present time only RAM " "samples are allowed " "by sfload.\n" "Session aborted !"), Gfname); return NOTOK; } sglobal_zone = 0; ll++; } break; case overridingRootKey: split->overridingRootKey = (BYTE) igen[m].genAmount.wAmount; break; case coarseTune: split->coarseTune = (char) igen[m].genAmount.shAmount; break; case fineTune: split->fineTune = (char) igen[m].genAmount.shAmount; break; case scaleTuning: split->scaleTuning = igen[m].genAmount.shAmount; break; case pan: split->pan = igen[m].genAmount.shAmount; break; case sampleModes: split->sampleModes = (BYTE) igen[m].genAmount.wAmount; break; case initialAttenuation: split->initialAttenuation = igen[m].genAmount.shAmount; break; case keyRange: split->minNoteRange = igen[m].genAmount.ranges.byLo; split->maxNoteRange = igen[m].genAmount.ranges.byHi; break; case velRange: split->minVelRange = igen[m].genAmount.ranges.byLo; split->maxVelRange = igen[m].genAmount.ranges.byHi; break; case startAddrsOffset: split->startOffset += igen[m].genAmount.shAmount; break; case endAddrsOffset: split->endOffset += igen[m].genAmount.shAmount; break; case startloopAddrsOffset: split->startLoopOffset += igen[m].genAmount.shAmount; break; case endloopAddrsOffset: split->endLoopOffset += igen[m].genAmount.shAmount; break; case startAddrsCoarseOffset: split->startOffset += igen[m].genAmount.shAmount * 32768; break; case endAddrsCoarseOffset: split->endOffset += igen[m].genAmount.shAmount * 32768; break; case startloopAddrCoarseOffset: split->startLoopOffset += igen[m].genAmount.shAmount * 32768; break; case endloopAddrsCoarseOffset: split->endLoopOffset += igen[m].genAmount.shAmount * 32768; break; case delayVolEnv: csound->Message(csound, "del: %f\n", (double) igen[m].genAmount.shAmount); break; case attackVolEnv: /*attack */ split->attack = POWER(FL(2.0), igen[m].genAmount.shAmount/FL(1200.0)); /* csound->Message(csound, "att: %f\n", split->attack ); */ break; /* case holdVolEnv: */ /*hold 35 */ case decayVolEnv: /*decay */ split->decay = POWER(FL(2.0), igen[m].genAmount.shAmount/FL(1200.0)); /* csound->Message(csound, "dec: %f\n", split->decay); */ break; case sustainVolEnv: /*sustain */ split->sustain = POWER(FL(10.0), -igen[m].genAmount.shAmount/FL(20.0)); /* csound->Message(csound, "sus: %f\n", split->sustain); */ break; case releaseVolEnv: /*release */ split->release = POWER(FL(2.0), igen[m].genAmount.shAmount/FL(1200.0)); /* csound->Message(csound, "rel: %f\n", split->release); */ break; case keynum: /*csound->Message(csound, "");*/ break; case velocity: /*csound->Message(csound, "");*/ break; case exclusiveClass: /*csound->Message(csound, "");*/ break; } } } } kk++; } break; case coarseTune: layer->coarseTune = (char) pgen[i].genAmount.shAmount; break; case fineTune: layer->fineTune = (char) pgen[i].genAmount.shAmount; break; case scaleTuning: layer->scaleTuning = pgen[i].genAmount.shAmount; break; case initialAttenuation: layer->initialAttenuation = pgen[i].genAmount.shAmount; break; case pan: layer->pan = pgen[i].genAmount.shAmount; break; case keyRange: layer->minNoteRange = pgen[i].genAmount.ranges.byLo; layer->maxNoteRange = pgen[i].genAmount.ranges.byHi; break; case velRange: layer->minVelRange = pgen[i].genAmount.ranges.byLo; layer->maxVelRange = pgen[i].genAmount.ranges.byHi; break; } } } } end_fill_presets: soundFont->preset = preset; /* fill layer list */ { instrType *instru; size = soundFont->chunk.instChunk->ckSize / sizeof(sfInst); soundFont->instrs_num = size; instru = (instrType *) csound->Malloc(csound, size * sizeof(layerType)); for (j=0; j < size; j++) { #define UNUSE 0x7fffffff int GsampleModes=UNUSE, GcoarseTune=UNUSE, GfineTune=UNUSE; int Gpan=UNUSE, GinitialAttenuation=UNUSE,GscaleTuning=UNUSE; int GoverridingRootKey = UNUSE; instru[j].name = inst[j].achInstName; if (strcmp(instru[j].name,"EOI")==0) { soundFont->instrs_num = j; goto end_fill_layers; } instru[j].num = j; first_ibag = inst[j].wInstBagNdx; ibag_num = inst[j+1].wInstBagNdx - first_ibag; split_num=0; for (l=0; l < ibag_num; l++) { mStart = ibag[l+first_ibag].wInstGenNdx; mEnd = ibag[l+first_ibag+1].wInstGenNdx; for (m=mStart; m < mEnd; m++) { if (igen[m].sfGenOper == sampleID) { split_num++; } } } instru[j].splits_num = split_num; instru[j].split = (splitType *) csound->Malloc(csound, split_num * sizeof(splitType)); for (l=0; loverridingRootKey = (BYTE) GoverridingRootKey; if (GcoarseTune != UNUSE) split->coarseTune = (BYTE) GcoarseTune; if (GfineTune != UNUSE) split->fineTune = (BYTE) GfineTune; if (GscaleTuning != UNUSE) split->scaleTuning = (BYTE) GscaleTuning; if (Gpan != UNUSE) split->pan = (BYTE) Gpan; if (GsampleModes != UNUSE) split->sampleModes = (BYTE) GsampleModes; if (GinitialAttenuation != UNUSE) split->initialAttenuation = (BYTE) GinitialAttenuation; for (m=mStart; m < mEnd; m++) { switch (igen[m].sfGenOper) { case sampleID: { int num = igen[m].genAmount.wAmount; split->num= num; split->sample = &shdr[num]; if (UNLIKELY(split->sample->sfSampleType & 0x8000)) { csound->Free(csound, instru); csound->ErrorMsg(csound, Str("SoundFont file \"%s\" contains " "ROM samples !\n" "At present time only RAM samples " "are allowed by sfload.\n" "Session aborted !"), Gfname); return NOTOK; } sglobal_zone = 0; ll++; } break; case overridingRootKey: split->overridingRootKey = (BYTE) igen[m].genAmount.wAmount; break; case coarseTune: split->coarseTune = (char) igen[m].genAmount.shAmount; break; case fineTune: split->fineTune = (char) igen[m].genAmount.shAmount; break; case scaleTuning: split->scaleTuning = igen[m].genAmount.shAmount; break; case pan: split->pan = igen[m].genAmount.shAmount; break; case sampleModes: split->sampleModes = (BYTE) igen[m].genAmount.wAmount; break; case initialAttenuation: split->initialAttenuation = igen[m].genAmount.shAmount; break; case keyRange: split->minNoteRange = igen[m].genAmount.ranges.byLo; split->maxNoteRange = igen[m].genAmount.ranges.byHi; break; case velRange: split->minVelRange = igen[m].genAmount.ranges.byLo; split->maxVelRange = igen[m].genAmount.ranges.byHi; break; case startAddrsOffset: split->startOffset += igen[m].genAmount.shAmount; break; case endAddrsOffset: split->endOffset += igen[m].genAmount.shAmount; break; case startloopAddrsOffset: split->startLoopOffset += igen[m].genAmount.shAmount; break; case endloopAddrsOffset: split->endLoopOffset += igen[m].genAmount.shAmount; break; case startAddrsCoarseOffset: split->startOffset += igen[m].genAmount.shAmount * 32768; break; case endAddrsCoarseOffset: split->endOffset += igen[m].genAmount.shAmount * 32768; break; case startloopAddrCoarseOffset: split->startLoopOffset += igen[m].genAmount.shAmount * 32768; break; case endloopAddrsCoarseOffset: split->endLoopOffset += igen[m].genAmount.shAmount * 32768; break; case keynum: /*csound->Message(csound, "");*/ break; case velocity: /*csound->Message(csound, "");*/ break; case exclusiveClass: /*csound->Message(csound, "");*/ break; } } } } } end_fill_layers: soundFont->instr = instru; } return OK; } static void layerDefaults(layerType *layer) { layer->splits_num = 0; layer->minNoteRange = 0; layer->maxNoteRange = 127; layer->minVelRange = 0; layer->maxVelRange = 127; layer->coarseTune = 0; layer->fineTune = 0; layer->scaleTuning = 0; layer->initialAttenuation = 0; layer->pan = 0; } static void splitDefaults(splitType *split) { split->sampleModes = 0; split->minNoteRange = 0; split->maxNoteRange = 127; split->minVelRange = 0; split->maxVelRange = 127; split->startOffset = 0; split->endOffset = 0; split->startLoopOffset = 0; split->endLoopOffset = 0; split->overridingRootKey = -1; split->coarseTune = 0; split->fineTune = 0; split->scaleTuning = 100; split->initialAttenuation = 0; split->pan = 0; } static int chunk_read(CSOUND *csound, FILE *fil, CHUNK *chunk) { if (UNLIKELY(4 != fread(chunk->ckID,1,4, fil))) return 0; if (UNLIKELY(1 != fread(&chunk->ckSize,4,1,fil))) { chunk->ckSize = 0; return 0; } //if (UNLIKELY(chunk->ckSize>0x8fffff00)) return 0; ChangeByteOrder("d", (char *)&chunk->ckSize, 4); chunk->ckDATA = (BYTE *) csound->Malloc(csound, chunk->ckSize); if (chunk->ckDATA==NULL) return 0; if (chunk->ckSize>0x8fffff00) return 0; return fread(chunk->ckDATA,1,chunk->ckSize,fil); } static DWORD dword(char *p) { union cheat { DWORD i; char c[4]; } x; x.c[0] = *p++; x.c[1] = *p++; x.c[2] = *p++; x.c[3] = *p++; return x.i; } static void fill_SfPointers(CSOUND *csound) { char *chkp; DWORD chkid, j, size; CHUNK *main_chunk; CHUNK *smplChunk=NULL, *phdrChunk=NULL, *pbagChunk=NULL, *pmodChunk=NULL; CHUNK *pgenChunk=NULL, *instChunk=NULL, *ibagChunk=NULL, *imodChunk=NULL; CHUNK *igenChunk=NULL, *shdrChunk=NULL; SFBANK *soundFont; sfontg *globals; globals = (sfontg *) (csound->QueryGlobalVariable(csound, "::sfontg")); if (UNLIKELY(globals == NULL)) { csound->ErrorMsg(csound, Str("Sfont: cannot use globals/")); return; } soundFont = globals->soundFont; if (LIKELY(soundFont != NULL)) main_chunk=&(soundFont->chunk.main_chunk); else { csound->ErrorMsg(csound, Str("Sfont: cannot use globals/")); return; } if (UNLIKELY(main_chunk->ckDATA == NULL)) { csound->ErrorMsg(csound, Str("Sfont format not compatible")); return; } chkp = (char *) main_chunk->ckDATA+4; for (j=4; j< main_chunk->ckSize;) { chkid = /* (DWORD *) chkp*/ dword(chkp); /* #ifdef BETA */ /* csound->Message(csound, "Looking at %.4s\n", (char*) &chkid); */ /* #endif */ if (chkid == s2d("LIST")) { /* #ifdef BETA */ /* csound->Message(csound, "LIST "); */ /* #endif */ j += 4; chkp += 4; ChangeByteOrder("d", chkp, 4); size = /* (DWORD *) chkp */ dword(chkp); j += 4; chkp += 4; chkid = /* (DWORD *) chkp */ dword(chkp); /* #ifdef BETA */ /* csound->Message(csound, "**chkid %p %p\n", */ /* (void*) chkid, (void*) (*((DWORD *) chkp))); */ /* csound->Message(csound, ":Looking at %.4s (%u)\n", */ /* (char*) &chkid, (unsigned int) size); */ /* #endif */ if (chkid == s2d("INFO")) { chkp += size; j += size; } else if (chkid == s2d("sdta")) { j +=4; chkp += 4; smplChunk = (CHUNK *) chkp; soundFont->sampleData = (void *) &(smplChunk->ckDATA); ChangeByteOrder("d", chkp + 4, 4); ChangeByteOrder("w", chkp + 8, size - 12); /* #ifdef BETA */ /* { */ /* DWORD i; */ /* for (i=size-12; i< size+4; i++) */ /* csound->Message(csound, "%c(%.2x)", chkp[i], chkp[i]); */ /* csound->Message(csound, "\n"); */ /* } */ /* #endif */ chkp += size-4; j += size-4; } else if (chkid == s2d("pdta")) { j += 4; chkp += 4; do { chkid = /* (DWORD *) chkp */ dword(chkp); /* csound->Message(csound, "::Looking at %.4s (%d)\n",&chkid,size); */ if (chkid == s2d("phdr")) { phdrChunk = (CHUNK *) chkp; soundFont->chunk.phdr= (sfPresetHeader *) &phdrChunk->ckDATA; ChangeByteOrder("d", chkp + 4, 4); ChangeByteOrder("b20w3d3", chkp + 8, phdrChunk->ckSize); chkp += phdrChunk->ckSize+8; j += phdrChunk->ckSize+8; } else if (chkid == s2d("pbag")) { pbagChunk = (CHUNK *) chkp; soundFont->chunk.pbag= (void *) &pbagChunk->ckDATA; ChangeByteOrder("d", chkp + 4, 4); ChangeByteOrder("w2", chkp + 8, pbagChunk->ckSize); chkp += pbagChunk->ckSize+8; j += pbagChunk->ckSize+8; } else if (chkid == s2d("pmod")) { pmodChunk = (CHUNK *) chkp; soundFont->chunk.pmod= (void *) &pmodChunk->ckDATA; ChangeByteOrder("d", chkp + 4, 4); ChangeByteOrder("w5", chkp + 8, pmodChunk->ckSize); chkp += pmodChunk->ckSize+8; j += pmodChunk->ckSize+8; } else if (chkid == s2d("pgen")) { pgenChunk = (CHUNK *) chkp; soundFont->chunk.pgen= (void *) &pgenChunk->ckDATA; ChangeByteOrder("d", chkp + 4, 4); ChangeByteOrder("w2", chkp + 8, pgenChunk->ckSize); chkp += pgenChunk->ckSize+8; j += pgenChunk->ckSize+8; } else if (chkid == s2d("inst")) { instChunk = (CHUNK *) chkp; soundFont->chunk.inst= (sfInst *) &instChunk->ckDATA; ChangeByteOrder("d", chkp + 4, 4); ChangeByteOrder("b20w", chkp + 8, instChunk->ckSize); chkp += instChunk->ckSize+8; j += instChunk->ckSize+8; } else if (chkid == s2d("ibag")) { ibagChunk = (CHUNK *) chkp; soundFont->chunk.ibag= (void *) &ibagChunk->ckDATA; ChangeByteOrder("d", chkp + 4, 4); ChangeByteOrder("w2", chkp + 8, ibagChunk->ckSize); chkp += ibagChunk->ckSize+8; j += ibagChunk->ckSize+8; } else if (chkid == s2d("imod")) { imodChunk = (CHUNK *) chkp; soundFont->chunk.imod= (void *) &imodChunk->ckDATA; ChangeByteOrder("d", chkp + 4, 4); ChangeByteOrder("w5", chkp + 8, imodChunk->ckSize); chkp += imodChunk->ckSize+8; j += imodChunk->ckSize+8; } else if (chkid == s2d("igen")) { igenChunk = (CHUNK *) chkp; soundFont->chunk.igen= (sfInstGenList *) &igenChunk->ckDATA; ChangeByteOrder("d", chkp + 4, 4); ChangeByteOrder("w2", chkp + 8, igenChunk->ckSize); chkp += igenChunk->ckSize+8; j += igenChunk->ckSize+8; } else if (chkid == s2d("shdr")) { shdrChunk = (CHUNK *) chkp; soundFont->chunk.shdr= (sfSample *) &shdrChunk->ckDATA; ChangeByteOrder("d", chkp + 4, 4); ChangeByteOrder("b20d5b2w2", chkp + 8, shdrChunk->ckSize); chkp += shdrChunk->ckSize+8; j += shdrChunk->ckSize+8; } else { /* #ifdef BETA */ /* csound->Message(csound, "Unknown sfont %.4s(%.8x)\n", */ /* (char*) &chkid, (unsigned int) chkid); */ /* #endif */ shdrChunk = (CHUNK *) chkp; chkp += shdrChunk->ckSize+8; j += shdrChunk->ckSize+8; } } while (j < main_chunk->ckSize); } else { /* #ifdef BETA */ /* csound->Message(csound, "Unknown sfont %.4s(%.8x)\n", */ /* (char*) &chkid, (unsigned int) chkid); */ /* #endif */ shdrChunk = (CHUNK *) chkp; chkp += shdrChunk->ckSize+8; j += shdrChunk->ckSize+8; } } else { /* #ifdef BETA */ /* csound->Message(csound, "Unknown sfont %.4s(%.8x)\n", */ /* (char*) &chkid, (unsigned int) chkid); */ /* #endif */ shdrChunk = (CHUNK *) chkp; chkp += shdrChunk->ckSize+8; j += shdrChunk->ckSize+8; } } soundFont->chunk.smplChunk = smplChunk; soundFont->chunk.phdrChunk = phdrChunk; soundFont->chunk.pbagChunk = pbagChunk; soundFont->chunk.pmodChunk = pmodChunk; soundFont->chunk.pgenChunk = pgenChunk; soundFont->chunk.instChunk = instChunk; soundFont->chunk.ibagChunk = ibagChunk; soundFont->chunk.imodChunk = imodChunk; soundFont->chunk.igenChunk = igenChunk; soundFont->chunk.shdrChunk = shdrChunk; } typedef struct _sflooper { OPDS h; MYFLT *outL, *outR; /* output */ MYFLT *ivel, *inotnum, *amp, *pitch, *ipresethandle, *loop_start, *loop_end, *crossfade, *start, *imode, *ifn2, *iskip; int spltNum; SHORT *sBase[MAXSPLT]; FUNC *efunc; MYFLT count; int lstart[MAXSPLT], lend[MAXSPLT], cfade, mode; double ndx[MAXSPLT][2]; /* table lookup ndx */ double freq[MAXSPLT]; int firsttime, init, end[MAXSPLT], sstart[MAXSPLT]; MYFLT leftlevel[MAXSPLT], rightlevel[MAXSPLT]; } sflooper; static int sflooper_init(CSOUND *csound, sflooper *p) { DWORD index = (DWORD) *p->ipresethandle; presetType *preset; SHORT *sBase; int layersNum, j, spltNum = 0; sfontg *globals; globals = (sfontg *) (csound->QueryGlobalVariable(csound, "::sfontg")); preset = globals->presetp[index]; sBase = globals->sampleBase[index]; if (!preset) { return csound->InitError(csound, Str("sfplay: invalid or " "out-of-range preset number")); } layersNum = preset->layers_num; for (j =0; j < layersNum; j++) { layerType *layer = &preset->layer[j]; int vel= (int) *p->ivel, notnum= (int) *p->inotnum; if (notnum >= layer->minNoteRange && notnum <= layer->maxNoteRange && vel >= layer->minVelRange && vel <= layer->maxVelRange) { int splitsNum = layer->splits_num, k; for (k = 0; k < splitsNum; k++) { splitType *split = &layer->split[k]; if (notnum >= split->minNoteRange && notnum <= split->maxNoteRange && vel >= split->minVelRange && vel <= split->maxVelRange) { sfSample *sample = split->sample; DWORD start=sample->dwStart; MYFLT attenuation; double pan; double freq, orgfreq; double tuneCorrection = split->coarseTune + layer->coarseTune + (split->fineTune + layer->fineTune)*0.01; int orgkey = split->overridingRootKey; if (orgkey == -1) orgkey = sample->byOriginalKey; orgfreq = globals->pitches[orgkey]; freq = orgfreq * pow(2.0, ONETWELTH * tuneCorrection) * pow(2.0, ONETWELTH * (split->scaleTuning*0.01) * (notnum-orgkey)); p->freq[spltNum]= (freq/orgfreq) * sample->dwSampleRate*csound->onedsr; attenuation = (MYFLT) (layer->initialAttenuation + split->initialAttenuation); attenuation = POWER(FL(2.0), (-FL(1.0)/FL(60.0)) * attenuation ) * GLOBAL_ATTENUATION; pan = (double)(split->pan + layer->pan) / 1000.0 + 0.5; if (pan > 1.0) pan = 1.0; else if (pan < 0.0) pan = 0.0; p->sBase[spltNum] = sBase; p->sstart[spltNum] = start; p->end[spltNum] = sample->dwEnd + split->endOffset; p->leftlevel[spltNum] = (MYFLT) sqrt(1.0-pan) * attenuation; p->rightlevel[spltNum] = (MYFLT) sqrt(pan) * attenuation; spltNum++; } } } } p->spltNum = spltNum; if (*p->ifn2 != 0) p->efunc = csound->FTnp2Find(csound, p->ifn2); else p->efunc = NULL; if (*p->iskip == 0){ p->mode = (int) *p->imode; for(j=0; j < spltNum; j++){ if (p->mode == 0 || p->mode == 2){ if ((p->ndx[j][0] = *p->start*CS_ESR+p->sstart[j]) < 0) p->ndx[j][0] = 0; if (p->ndx[j][0] >= p->end[j]) p->ndx[j][0] = (double) p->end[j] - 1.0; p->count = 0; } } p->init = 1; p->firsttime = 1; } return OK; } static int sflooper_process(CSOUND *csound, sflooper *p) { int k; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT *outL = p->outL, *outR = p->outR, out, sr = CS_ESR; MYFLT amp = *(p->amp), pit = *(p->pitch); SHORT **base = p->sBase, *tab; double *ndx; MYFLT frac0, frac1, *etab, left, right; int *nend = p->end, *loop_end = p->lend, *loop_start = p->lstart, crossfade = p->cfade, len, spltNum = p->spltNum; MYFLT count = p->count,fadein, fadeout, pitch; int *firsttime = &p->firsttime, elen, mode=p->mode, init = p->init; uint32 tndx0, tndx1; if (p->efunc != NULL) { etab = p->efunc->ftable; elen = p->efunc->flen; } else { etab = NULL; elen = 0; } /* loop parameters & check */ if (pit < FL(0.0)) pit = FL(0.0); memset(outL, 0, nsmps*sizeof(MYFLT)); memset(outR, 0, nsmps*sizeof(MYFLT)); if (UNLIKELY(early)) nsmps -= early; for(k=0; k < spltNum; k++){ tab = base[k]; len = nend[k]; ndx = p->ndx[k]; left = p->leftlevel[k]; right = p->rightlevel[k]; pitch = pit*p->freq[k]; if (*firsttime) { int loopsize; loop_start[k] = (int) (*p->loop_start*sr) + p->sstart[k]; loop_end[k] = (int) (*p->loop_end*sr) + p->sstart[k]; loop_start[k] = loop_start[k] < 0 ? 0 : loop_start[k]; loop_end[k] = loop_end[k] > len ? len : (loop_end[k] < loop_start[k] ? loop_start[k] : loop_end[k]); loopsize = loop_end[k] - loop_start[k]; crossfade = (int) (*p->crossfade*sr); if (mode == 1) { ndx[0] = (double) loop_end[k]; ndx[1] = (double) loop_end[k]; count = (MYFLT) crossfade; p->cfade = crossfade = crossfade > loopsize ? loopsize : crossfade; } else if (mode == 2) { ndx[1] = (double) loop_start[k] - 1.0; p->cfade = crossfade = crossfade > loopsize/2 ? loopsize/2-1 : crossfade; } else { ndx[1] = (double) loop_start[k]; p->cfade = crossfade = crossfade > loopsize ? loopsize : crossfade; } *firsttime = 0; } for (i=offset; i < nsmps; i++) { if (mode == 1){ /* backwards */ tndx0 = (int) ndx[0]; frac0 = ndx[0] - tndx0; if (ndx[0] > crossfade + loop_start[k]) out = amp*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0])); else { tndx1 = (int) ndx[1]; frac1 = ndx[1] - tndx1; if (etab==NULL){ fadeout = count/crossfade; fadein = FL(1.0) - fadeout; } else { fadeout = elen*count/crossfade; fadein = etab[elen - (int)fadeout]; fadeout = etab[(int)fadeout]; } out = amp*(fadeout*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0])) + fadein*(tab[tndx1] + frac1*(tab[tndx1+1] - tab[tndx1]))); ndx[1] -= pitch; count -= pitch; } ndx[0] -= pitch; if (ndx[0] <= loop_start[k]) { int loopsize; loop_start[k] = (int) (*p->loop_start*sr) + p->sstart[k]; loop_end[k] = (int) (*p->loop_end*sr) + p->sstart[k]; loop_start[k] = loop_start[k] < 0 ? 0 : loop_start[k]; loop_end[k] = loop_end[k] > len ? len : (loop_end[k] < loop_start[k] ? loop_start[k] : loop_end[k]); loopsize = loop_end[k] - loop_start[k]; crossfade = (int) (*p->crossfade*sr); p->cfade = crossfade = crossfade > loopsize ? loopsize : crossfade; ndx[0] = ndx[1]; ndx[1] = (double)loop_end[k]; count=(MYFLT)crossfade; } outR[i] += out*right; outL[i] += out*left; } else if (mode==2) { /* back and forth */ out = 0; /* this is the forward reader */ if (init && ndx[0] < loop_start[k] + crossfade) { tndx0 = (int) ndx[0]; frac0 = ndx[0] - tndx0; out = amp*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0])); ndx[0] += pitch; } else if (ndx[0] < loop_start[k] + crossfade) { if (etab==NULL) fadein = count/crossfade; else fadein = etab[(int)(elen*count/crossfade)]; tndx0 = (int) ndx[0]; frac0 = ndx[0] - tndx0; out += amp*fadein*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0])); ndx[0] += pitch; count += pitch; } else if (ndx[0] < loop_end[k] - crossfade) { tndx0 = (int) ndx[0]; frac0 = ndx[0] - tndx0; out = amp*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0])); ndx[0] += pitch; init = 0; if (ndx[0] >= loop_end[k] - crossfade) { ndx[1] = (double) loop_end[k]; count = 0; } } else if (ndx[0] < loop_end[k]) { if (etab==NULL) fadeout = FL(1.0) - count/crossfade; else fadeout = etab[(int)(elen*(FL(1.0) - count/crossfade))]; tndx0 = (int) ndx[0]; frac0 = ndx[0] - tndx0; out += amp*fadeout*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0])); ndx[0] += pitch; count += pitch; } /* this is the backward reader */ if (ndx[1] > loop_end[k] - crossfade) { if (etab==NULL) fadein = count/crossfade; else fadein = etab[(int)(elen*count/crossfade)]; tndx1 = (int) ndx[1]; frac1 = ndx[1] - tndx1; out += amp*fadein*(tab[tndx1] + frac1*(tab[tndx1+1] - tab[tndx1])); ndx[1] -= pitch; } else if (ndx[1] > loop_start[k] + crossfade) { tndx1 = (int) ndx[1]; frac1 = ndx[1] - tndx1; out = amp*(tab[tndx1] + frac1*(tab[tndx1+1] - tab[tndx1])); ndx[1] -= pitch; if (ndx[1] <= loop_start[k] + crossfade) { ndx[0] = (double) loop_start[k]; count = 0; } } else if (ndx[1] > loop_start[k]) { if (etab==NULL) fadeout = FL(1.0) - count/crossfade; else fadeout = etab[(int)(elen*(FL(1.0) - count/crossfade))]; tndx1 = (int) ndx[1]; frac1 = ndx[1] - tndx1; out += amp*fadeout*(tab[tndx1] + frac1*(tab[tndx1+1] - tab[tndx1])); ndx[1] -= pitch; if (ndx[1] <= loop_start[k]) { int loopsize; loop_start[k] = (int) (*p->loop_start*sr) + p->sstart[k]; loop_end[k] = (int) (*p->loop_end*sr) + p->sstart[k]; loop_start[k] = loop_start[k] < 0 ? 0 : loop_start[k]; loop_end[k] = loop_end[k] > len ? len : (loop_end[k] < loop_start[k] ? loop_start[k] : loop_end[k]); loopsize = loop_end[k] - loop_start[k]; crossfade = (int) (*p->crossfade*sr); p->cfade = crossfade = crossfade > loopsize/2 ? loopsize/2-1 : crossfade; } } outR[i] += out*right; outL[i] += out*left; } else { /* normal */ out = 0; tndx0 = (uint32) ndx[0]; frac0 = ndx[0] - tndx0; if (ndx[0] < loop_end[k]-crossfade) out = amp*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0])); else { tndx1 = (int) ndx[1]; frac1 = ndx[1] - tndx1; if (etab==NULL) { fadein = count/crossfade; fadeout = FL(1.0) - fadein; } else { fadein = elen*count/crossfade; fadeout = etab[elen - (int)fadein]; fadein = etab[(int)fadein]; } out = amp*(fadeout*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0])) + fadein*(tab[tndx1] + frac1*(tab[tndx1+1] - tab[tndx1]))); ndx[1]+=pitch; count+=pitch; } ndx[0]+=pitch; if (ndx[0] >= loop_end[k]) { int loopsize; loop_start[k] = (int) (*p->loop_start*sr) + p->sstart[k]; loop_end[k] = (int) (*p->loop_end*sr) + p->sstart[k]; loop_start[k] = loop_start[k] < 0 ? 0 : loop_start[k]; loop_end[k] = loop_end[k] > len ? len : (loop_end[k] < loop_start[k] ? loop_start[k] : loop_end[k]); loopsize = loop_end[k] - loop_start[k]; crossfade = (int) (*p->crossfade*sr); p->cfade = crossfade = crossfade > loopsize ? loopsize-1 : crossfade; ndx[0] = ndx[1]; ndx[1] = (double)loop_start[k]; count=0; } outR[i] += out*right; outL[i] += out*left; } } } p->count = count; p->cfade = crossfade; p->init = init; return OK; } #define S sizeof static OENTRY localops[] = { { "sfload",S(SFLOAD), 0, 1, "i", "S", (SUBR)SfLoad_S, NULL, NULL }, { "sfload.i",S(SFLOAD), 0, 1, "i", "i", (SUBR)SfLoad, NULL, NULL }, { "sfpreset",S(SFPRESET), 0, 1, "i", "iiii", (SUBR)SfPreset }, { "sfplay", S(SFPLAY), 0, 5, "aa", "iixxiooo", (SUBR)SfPlay_set, NULL, (SUBR)SfPlay }, { "sfplaym", S(SFPLAYMONO), 0, 5, "a", "iixxiooo", (SUBR)SfPlayMono_set, NULL, (SUBR)SfPlayMono }, { "sfplist",S(SFPLIST), 0, 1, "", "i", (SUBR)Sfplist }, { "sfilist",S(SFPLIST), 0, 1, "", "i", (SUBR)Sfilist }, { "sfpassign",S(SFPASSIGN), 0, 1, "", "iip", (SUBR)SfAssignAllPresets }, { "sfinstrm", S(SFIPLAYMONO),0, 5, "a", "iixxiiooo", (SUBR)SfInstrPlayMono_set, NULL, (SUBR)SfInstrPlayMono }, { "sfinstr", S(SFIPLAY), 0, 5, "aa", "iixxiiooo", (SUBR)SfInstrPlay_set, NULL,(SUBR)SfInstrPlay }, { "sfplay3", S(SFPLAY), 0, 5, "aa", "iixxiooo", (SUBR)SfPlay_set, NULL, (SUBR)SfPlay3 }, { "sfplay3m", S(SFPLAYMONO), 0, 5, "a", "iixxiooo", (SUBR)SfPlayMono_set, NULL,(SUBR)SfPlayMono3 }, { "sfinstr3", S(SFIPLAY), 0, 5, "aa", "iixxiiooo", (SUBR)SfInstrPlay_set, NULL, (SUBR)SfInstrPlay3 }, { "sfinstr3m", S(SFIPLAYMONO), 0, 5, "a", "iixxiiooo",(SUBR)SfInstrPlayMono_set, NULL, (SUBR)SfInstrPlayMono3 }, { "sflooper", S(sflooper), 0, 5, "aa", "iikkikkkoooo", (SUBR)sflooper_init, NULL, (SUBR)sflooper_process }, { NULL, 0, 0, 0, NULL, NULL, (SUBR) NULL, (SUBR) NULL, (SUBR) NULL } }; int sfont_ModuleCreate(CSOUND *csound) { int j; sfontg *globals; csound->CreateGlobalVariable(csound, "::sfontg", sizeof(sfontg)); globals = (sfontg *) (csound->QueryGlobalVariable(csound, "::sfontg")); if (globals == NULL) return csound->InitError(csound, Str("error... could not create sfont globals\n")); globals->sfArray = (SFBANK *) csound->Malloc(csound, MAX_SFONT*sizeof(SFBANK)); globals->presetp = (presetType **) csound->Malloc(csound, MAX_SFPRESET *sizeof(presetType *)); globals->sampleBase = (SHORT **) csound->Malloc(csound, MAX_SFPRESET*sizeof(SHORT *)); globals->currSFndx = 0; globals->maxSFndx = MAX_SFONT; for (j=0; j<128; j++) { globals->pitches[j] = (MYFLT) (csound->A4 * pow(2.0, (double)(j- 69)/12.0)); } return OK; } int sfont_ModuleInit(CSOUND *csound) { OENTRY *ep = (OENTRY*) &(localops[0]); int err = 0; while (ep->opname != NULL) { err |= csound->AppendOpcode(csound, ep->opname, ep->dsblksiz, ep->flags, ep->thread, ep->outypes, ep->intypes, (int (*)(CSOUND *, void*)) ep->iopadr, (int (*)(CSOUND *, void*)) ep->kopadr, (int (*)(CSOUND *, void*)) ep->aopadr); ep++; } return err; } csound-6.10.0/Opcodes/sfont.h000066400000000000000000000067201321653344700160040ustar00rootroot00000000000000/* sfont.h: Copyright (C) 2000 Gabriel Maldonado This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "sftype.h" #include "sf.h" typedef struct { OPDS h; MYFLT *ihandle, *fname; } SFLOAD; typedef struct { OPDS h; MYFLT *ihandle; } SFPLIST; typedef struct { OPDS h; MYFLT *startNum,*ihandle, *msgs; } SFPASSIGN; typedef struct { OPDS h; MYFLT *ipresethandle, *iprog, *ibank, *isfhandle, *iPresetHandle; } SFPRESET; #define MAXSPLT 10 typedef struct { OPDS h; MYFLT *out1, *out2, *ivel, *inotnum,*xamp, *xfreq; MYFLT *ipresethandle, *iflag, *ioffset, *ienv; int spltNum; SHORT *base[MAXSPLT], mode[MAXSPLT]; DWORD end[MAXSPLT], startloop[MAXSPLT], endloop[MAXSPLT], ti[MAXSPLT]; double si[MAXSPLT],phs[MAXSPLT]; MYFLT leftlevel[MAXSPLT], rightlevel[MAXSPLT], attack[MAXSPLT], decay[MAXSPLT], sustain[MAXSPLT], release[MAXSPLT]; MYFLT attr[MAXSPLT], decr[MAXSPLT]; MYFLT env[MAXSPLT]; } SFPLAY; typedef struct { OPDS h; MYFLT *out1, *ivel, *inotnum,*xamp, *xfreq, *ipresethandle, *iflag, *ioffset, *ienv; int spltNum; SHORT *base[MAXSPLT], mode[MAXSPLT]; DWORD end[MAXSPLT], startloop[MAXSPLT], endloop[MAXSPLT], ti[MAXSPLT]; double si[MAXSPLT],phs[MAXSPLT]; MYFLT attenuation[MAXSPLT],attack[MAXSPLT], decay[MAXSPLT], sustain[MAXSPLT], release[MAXSPLT]; MYFLT attr[MAXSPLT], decr[MAXSPLT]; MYFLT env[MAXSPLT]; } SFPLAYMONO; typedef struct { OPDS h; MYFLT *out1, *ivel, *inotnum, *xamp, *xfreq, *instrNum; MYFLT *sfBank, *iflag, *ioffset, *ienv; int spltNum; SHORT *base[MAXSPLT], mode[MAXSPLT]; DWORD end[MAXSPLT], startloop[MAXSPLT], endloop[MAXSPLT], ti[MAXSPLT]; double si[MAXSPLT],phs[MAXSPLT]; MYFLT attenuation[MAXSPLT],attack[MAXSPLT], decay[MAXSPLT], sustain[MAXSPLT], release[MAXSPLT]; MYFLT attr[MAXSPLT], decr[MAXSPLT]; MYFLT env[MAXSPLT]; } SFIPLAYMONO; typedef struct { OPDS h; MYFLT *out1, *out2, *ivel, *inotnum, *xamp, *xfreq; MYFLT *instrNum, *sfBank, *iflag, *ioffset, *ienv; int spltNum; SHORT *base[MAXSPLT], mode[MAXSPLT]; DWORD end[MAXSPLT], startloop[MAXSPLT], endloop[MAXSPLT], ti[MAXSPLT]; double si[MAXSPLT],phs[MAXSPLT]; MYFLT leftlevel[MAXSPLT], rightlevel[MAXSPLT],attack[MAXSPLT], decay[MAXSPLT], sustain[MAXSPLT], release[MAXSPLT]; MYFLT attr[MAXSPLT], decr[MAXSPLT]; MYFLT env[MAXSPLT]; } SFIPLAY; csound-6.10.0/Opcodes/sftype.h000066400000000000000000000124061321653344700161630ustar00rootroot00000000000000/* sftype.h: Copyright (C) 2000 Gabriel Maldonado This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #if !defined(_SFTYPE_H) #define _SFTYPE_H #ifdef __GNUC__ # ifndef PACKED # define PACKED __attribute__((packed)) # endif /* PACKED */ #elif defined MSVC # pragma pack(push, before, 1) # define PACKED #else # error "No pack defined." #endif #ifndef WORDS_BIGENDIAN # if defined(__POWERPC__) || defined(__PPC__) || defined(__ppc__) # define WORDS_BIGENDIAN 1 # endif #endif #if defined(WORDS_BIGENDIAN) && defined(__i386__) # undef WORDS_BIGENDIAN #endif #if !defined(WIN32) || defined(__CYGWIN__) typedef uint32_t DWORD; #endif /* typedef int BOOL; */ typedef uint8_t BYTE; typedef uint16_t WORD; typedef short SHORT; typedef char CHAR; typedef unsigned short SFTransform; typedef struct { #ifdef WORDS_BIGENDIAN /* bigendian m/c like Mac and SGI */ BYTE byHi; BYTE byLo; #else BYTE byLo; BYTE byHi; #endif } PACKED rangesType; typedef union { rangesType ranges; SHORT shAmount; WORD wAmount; } PACKED genAmountType; /* The SFSampleLink is an enumeration type which describes both the type of sample (mono, stereo left, etc.) and the whether the sample is located in RAM or ROM memory: */ typedef enum { monoSample = 1, rightSample = 2, leftSample = 4, linkedSample = 8, ROMSample = 0x8000, /*32768 */ RomMonoSample = 0x8001, /*32769 */ RomRightSample = 0x8002, /*32770 */ RomLeftSample = 0x8004, /*32772 */ RomLinkedSample = 0x8008 /*32776 */ } SFSampleLink; /* The INFO-list chunk in a SoundFont 2 compatible file contains three mandatory and a variety of optional subchunks as defined below. The INFO-list chunk gives basic information about the SoundFont compatible bank contained in the file. */ /* The ifil subchunk is a mandatory subchunk identifying the SoundFont specification version level to which the file complies. It is always four bytes in length, and contains data according to the structure: */ /* -> */ typedef struct { WORD wMajor; WORD wMinor; } PACKED sfVersionTag; /* -> */ typedef struct { CHAR achPresetName[20]; WORD wPreset; WORD wBank; WORD wPresetBagNdx; DWORD dwLibrary; DWORD dwGenre; DWORD dwMorphology; } PACKED sfPresetHeader; /* -> */ typedef struct { WORD wGenNdx; WORD wModNdx; } PACKED sfPresetBag; /* -> */ typedef struct { /* SFModulator sfModSrcOper; SFGenerator sfModDestOper; SHORT modAmount; SFModulator sfModAmtSrcOper; SFTransform sfModTransOper; */ /* SFModulator sfModSrcOper; */ WORD sfModSrcOper; /* SFGenerator sfModDestOper; */ WORD sfModDestOper; SHORT modAmount; /* SFModulator sfModAmtSrcOper; */ WORD sfModAmtSrcOper; SFTransform sfModTransOper; } PACKED sfModList; /* -> */ typedef struct { /*SFGenerator sfGenOper; */ WORD sfGenOper; genAmountType genAmount; } PACKED sfGenList; /* -> */ typedef struct { CHAR achInstName[20]; WORD wInstBagNdx; } PACKED sfInst; /* -> */ typedef struct { WORD wInstGenNdx; WORD wInstModNdx; } PACKED sfInstBag; /* -> */ typedef struct { /* SFModulator sfModSrcOper; SFGenerator sfModDestOper; SHORT modAmount; SFModulator sfModAmtSrcOper; SFTransform sfModTransOper; */ /* SFModulator sfModSrcOper; */ WORD sfModSrcOper; /* SFGenerator sfModDestOper; */ WORD sfModDestOper; SHORT modAmount; /* SFModulator sfModAmtSrcOper; */ WORD sfModAmtSrcOper; SFTransform sfModTransOper; } PACKED sfInstModList; /* -> */ typedef struct { /* SFGenerator sfGenOper; */ WORD sfGenOper; genAmountType genAmount; } PACKED sfInstGenList; /* -> */ typedef struct { CHAR achSampleName[20]; DWORD dwStart; DWORD dwEnd; DWORD dwStartloop; DWORD dwEndloop; DWORD dwSampleRate; BYTE byOriginalKey; CHAR chCorrection; WORD wSampleLink; /*SFSampleLink sfSampleType; */ WORD sfSampleType; } PACKED sfSample; #ifdef MSVC # pragma pack(pop, before) #endif #endif csound-6.10.0/Opcodes/shaker.c000066400000000000000000000131471321653344700161240ustar00rootroot00000000000000/* shaker.c: Copyright (C) 1996, 1997 Perry Cook, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /********************************************************/ /* Maracha SImulation by Perry R. Cook, 1996 */ /********************************************************/ /********************************************************/ /* In real life, each grain has an individual sound and envelope, but if you buy the notion that each sound is independent noise, the sum of a bunch of independent exponentially decaying enveloped noises is a single exponentially decaying enveloped noise. shakeEnergy is an exponentially decaying, but reexcitable by shaking, energy expressing how loud a single collision will be. This code would implement individual grain envelopes if (random(8) < 1) { noises[which] = 1024 * shakeEnergy; which += 1; if (which==MAX) which = 0; } input = 0.0; for (i=0;iamp)*AMP_RSCALE; /* Normalise */ p->shake_speed = FL(0.0008) + (amp * FL(0.0004)); make_BiQuad(&p->filter); make_ADSR(&p->envelope); p->res_freq = FL(3200.0); BiQuad_setFreqAndReson(p->filter, p->res_freq, FL(0.96)); BiQuad_setEqualGainZeroes(p->filter); BiQuad_setGain(p->filter, FL(1.0)); p->shakeEnergy = FL(0.0); p->noiseGain = FL(0.0); p->coll_damp = FL(0.95); /* p->shake_damp = 0.999f; */ /* p->num_beans = 8; */ ADSR_setAll(csound, &p->envelope, p->shake_speed, p->shake_speed, FL(0.0), p->shake_speed); p->num_beans = (int)*p->beancount; if (p->num_beans<1) p->num_beans = 1; p->wait_time = 0x7FFFFFFE / p->num_beans; p->gain_norm = FL(0.0005); p->shake_num = (int)*p->times; ADSR_keyOn(&p->envelope); p->kloop = (int)(p->h.insdshead->offtim * CS_EKR) - (int)(CS_EKR * *p->dettack); p->freq = -FL(1.0); /* So will get changed */ return OK; } int shaker(CSOUND *csound, SHAKER *p) { MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT amp = (*p->amp)*AMP_RSCALE; /* Normalise */ MYFLT shake = amp + amp; MYFLT damp = *p->shake_damp; MYFLT gain = p->gain_norm; MYFLT ngain = p->noiseGain; MYFLT sEnergy = p->shakeEnergy; MYFLT shake_speed = FL(0.0008) + amp * FL(0.0004); if (p->freq != *p->kfreq) BiQuad_setFreqAndReson(p->filter, p->freq = *p->kfreq, FL(0.96)); if (p->num_beans != (int)*p->beancount) { /* Bean Count */ p->num_beans = (int)*p->beancount; p->wait_time = 0x7FFFFFFE / p->num_beans; } if (shake_speed != p->shake_speed) { p->shake_speed = shake_speed; ADSR_setAll(csound, &p->envelope, shake_speed, shake_speed, FL(0.0), shake_speed); } if (p->kloop>0 && p->h.insdshead->relesing) p->kloop=1; if ((--p->kloop) == 0) { p->shake_num = 0; } if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } gain *= p->num_beans; /* Save work in loop */ for (n=offset; nenvelope); temp = p->envelope.value * shake; if (p->shake_num>0) { if (p->envelope.state==SUSTAIN) { if (p->shake_num < 64) p->shake_num -= 1; ADSR_keyOn(&p->envelope); } } if (temp > sEnergy) sEnergy = temp; sEnergy *= damp; /* Exponential System Decay */ /* There's Roughly Constant Probablity of a Collision, and */ /* Energy of Each Collision is Weighted by Exponentially */ /* Decaying System Energy. All add together for total */ /* exponentially decaying sound energy. */ if (csound->Rand31(&(csound->randSeed1)) <= p->wait_time) { ngain += gain * sEnergy; } /* Actual Sound is Random */ lastOutput = ngain * ((MYFLT) csound->Rand31(&(csound->randSeed1)) - FL(1073741823.5)) * (MYFLT) (1.0 / 1073741823.0); /* Each (all) event(s) decay(s) exponentially */ ngain *= p->coll_damp; lastOutput = BiQuad_tick(&p->filter, lastOutput); ar[n] = lastOutput * AMP_SCALE * FL(7.0); /* As too quiet */ } p->noiseGain = ngain; p->shakeEnergy = sEnergy; return OK; } csound-6.10.0/Opcodes/shaker.h000066400000000000000000000035311321653344700161250ustar00rootroot00000000000000/* shaker.h: Copyright (C) 1996, 1997 Perry Cook, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /******************************************/ /* Maracha (& other shakers) Simulation */ /* by Perry R. Cook, 1996 */ /* by Perry Cook, 1995-96 */ /* */ /* See ICMC96 paper "PhISM: Percussive */ /* Synthesis." for more exciting details */ /******************************************/ #if !defined(__Shaker_h) #define __Shaker_h #include "physutil.h" typedef struct Shaker { OPDS h; MYFLT *ar; /* Output */ MYFLT *amp, *kfreq; MYFLT *beancount, *shake_damp; MYFLT *times, *dettack; BiQuad filter; ADSR envelope; int num_beans; int wait_time; int shake_num; MYFLT shake_speed; /* A + amp*N -- hides two parameters */ MYFLT res_freq; MYFLT coll_damp; MYFLT shakeEnergy; MYFLT noiseGain; MYFLT gain_norm; int kloop; MYFLT freq; } SHAKER; #endif csound-6.10.0/Opcodes/shape.c000066400000000000000000000445671321653344700157610ustar00rootroot00000000000000/* shape.c A Csound opcode library implementing ugens for various waveshaping methods. Anthony Kozar January 5, 2004 November 2, 2007: Ported to Csound 5. Copyright (C) 2004,2007 Anthony M. Kozar Jr. Code for syncphasor based on phasor from ugens2.c. Copyright (C) 1991-2007 Barry Vercoe, John ffitch, Robin Whittle This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "interlocks.h" #include typedef struct { OPDS h; MYFLT *aout, *ain, *kshapeamount, *ifullscale; MYFLT maxamplitude, one_over_maxamp; } POWER_SHAPE; static int PowerShapeInit(CSOUND* csound, POWER_SHAPE* p) { p->maxamplitude = *p->ifullscale; if (UNLIKELY(p->maxamplitude<= 0.0)) return csound->InitError(csound, Str("powershape: ifullscale must be strictly positive")); p->one_over_maxamp = FL(1.0) / p->maxamplitude; return OK; } static int PowerShape(CSOUND* csound, POWER_SHAPE* p) { MYFLT cur, amt, maxampl, invmaxampl; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT* out = p->aout; MYFLT* in = p->ain; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } amt = *(p->kshapeamount); invmaxampl = p->one_over_maxamp; if (amt == FL(0.0)) { /* treat zero-power with care */ for (n=offset; nmaxamplitude; for (n=offset; nh.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int ncoeff = /* index of the last coefficient */ csound->GetInputArgCnt(p) - 2; MYFLT *out = p->aout; MYFLT *in = p->ain; MYFLT **coeff = p->kcoefficients; MYFLT sum, x; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; n= 0; --i) { sum *= x; sum += *coeff[i]; } out[n] = sum; } return OK; } typedef struct { OPDS h; MYFLT *aout, *ain, *kcoefficients[VARGMAX]; MYFLT *chebn; AUXCH coeff; } CHEBPOLY; static int ChebyshevPolyInit(CSOUND* csound, CHEBPOLY* p) { int ncoeff = csound->GetInputArgCnt(p) - 1; /* Need two MYFLT arrays of length ncoeff: first for the coefficients of the sum of polynomials, and the second for the coefficients of the individual chebyshev polynomials as we are adding them up. */ csound->AuxAlloc(csound, (2*ncoeff + 1)*sizeof(MYFLT), &(p->coeff)); p->chebn = ((MYFLT*)p->coeff.auxp) + ncoeff; return OK; } /* Efficiently evaluates a sum of Chebyshev polynomials of arbitrary order. Coefficients (k0, k1, k2, ... ) are k-rate multipliers of each Chebyshev polynomial starting with the zero-order polynomial T0(x) = 1, then T1(x) = x, T2(x) = 2x^2 - 1, etc. */ static int ChebyshevPolynomial(CSOUND* csound, CHEBPOLY* p) { int i, j; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int ncoeff = /* index of the last coefficient */ csound->GetInputArgCnt(p) - 2; MYFLT *out = p->aout; MYFLT *in = p->ain; MYFLT **chebcoeff = p->kcoefficients; MYFLT *chebn = p->chebn; MYFLT *coeff = (MYFLT*)p->coeff.auxp; MYFLT sum, x; /* Every other coefficient in a Cheb. poly. is 0, and these zero coeff. alternate positions in successive polynomials. So we store two consecutive Cheb. poly. in the same array with the odd coeff. making up one, and the even coeff. the other. */ /* Initialize the Cheb. poly. array with first two C.P. */ chebn[0] = chebn[1] = FL(1.0); for (i = 2; i <= ncoeff; ++i) chebn[i] = FL(0.0); /* Calculate the final coefficients array */ coeff[0] = chebcoeff[0][0]; if (ncoeff > 0) coeff[1] = chebcoeff[1][0]; if (ncoeff > 1) { for (i = 2; i <= ncoeff; ++i) coeff[i] = FL(0.0); /* Calculate successive Cheb. poly. while accumulating our final poly. coefficients based on input Cheb. coeff. */ for (i = 2; i <= ncoeff; i+=2) { /* do the next even Cheb. poly. */ chebn[0] = -chebn[0]; coeff[0] += chebn[0] * chebcoeff[i][0]; for (j = 2; j <= ncoeff; j+=2) { chebn[j] = 2*chebn[j-1] - chebn[j]; coeff[j] += chebn[j] * chebcoeff[i][0]; } /* do the next odd Cheb. poly. if needed */ if (ncoeff > i) { for (j = 1; j <= ncoeff; j+=2) { chebn[j] = 2*chebn[j-1] - chebn[j]; coeff[j] += chebn[j] * chebcoeff[i+1][0]; } } } } /* Use our final coeff. to evaluate the poly. for each input sample */ if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; n= 0 ; --i) { sum *= x; sum += coeff[i]; } out[n] = sum; } return OK; } /* Phase distortion opcodes */ typedef struct { OPDS h; MYFLT *aout, *ain, *kwidth, *kcenter, *ibipolar, *ifullscale; } PD_CLIP; static int PDClip(CSOUND* csound, PD_CLIP* p) { MYFLT cur, low, high, maxampl, width, unwidth, center, outscalar; int bipolarMode; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT* out = p->aout; MYFLT* in = p->ain; bipolarMode = (int) *(p->ibipolar); maxampl = *(p->ifullscale); width = (*(p->kwidth) > FL(1.0) ? FL(1.0) : (*(p->kwidth) < FL(0.0) ? FL(0.0) : *(p->kwidth))); unwidth = FL(1.0) - width; /* width of 1/2 unclipped region */ if (bipolarMode) { /* the unclipped region can only shift left or right by up to width */ if (*(p->kcenter) < - width) center = - width * maxampl; else if (*(p->kcenter) > width) center = width * maxampl; else center = *(p->kcenter) * maxampl; } else { width = FL(0.5) * width; /* range reduced by 1/2 in unipolar mode */ unwidth = FL(0.5) * unwidth; center = *(p->kcenter) * FL(0.5) + FL(0.5); /* make unipolar */ if (center < (FL(0.5) - width)) center = (FL(0.5) - width) * maxampl; else if (center > (FL(0.5) + width)) center = (FL(0.5) + width) * maxampl; else center = center * maxampl; } low = center - unwidth*maxampl; /* min value of unclipped input */ high = unwidth*maxampl + center; /* max value of unclipped input */ if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } if (bipolarMode) { outscalar = (unwidth == FL(0.0)) ? FL(0.0) : (FL(1.0) / unwidth); for (n=offset; n= high ? maxampl : (outscalar * (cur-center)))); } } else { outscalar = (unwidth == FL(0.0)) ? FL(0.0) : (FL(0.5) / unwidth); for (n=offset; n= high ? maxampl : (outscalar * (cur-low)))); } } return OK; } typedef struct { OPDS h; MYFLT *aout, *ain, *kamount, *ibipolar, *ifullscale; } PD_HALF; /* Casio-style phase distortion with "pivot point" on the X axis */ static int PDHalfX(CSOUND* csound, PD_HALF* p) { MYFLT cur, maxampl, midpoint, leftslope, rightslope; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT* out = p->aout; MYFLT* in = p->ain; maxampl = *(p->ifullscale); if (maxampl == FL(0.0)) maxampl = FL(1.0); if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } if (*(p->ibipolar) != FL(0.0)) { /* bipolar mode */ /* clamp kamount in range [-1,1] */ midpoint = (*(p->kamount) >= FL(1.0) ? maxampl : (*(p->kamount) <= FL(-1.0) ? -maxampl : (*(p->kamount) * maxampl))); if (midpoint != -maxampl) leftslope = maxampl / (midpoint + maxampl); else leftslope = FL(0.0); if (midpoint != maxampl) rightslope = maxampl / (maxampl - midpoint); else rightslope = FL(0.0); for (n=offset; nkamount) >= FL(1.0) ? maxampl : (*(p->kamount) <= FL(-1.0) ? FL(0.0) : ((*(p->kamount) + FL(1.0)) * halfmaxampl))); if (midpoint != FL(0.0)) leftslope = halfmaxampl / midpoint; else leftslope = FL(0.0); if (midpoint != maxampl) rightslope = halfmaxampl / (maxampl - midpoint); else rightslope = FL(0.0); for (n=offset; nh.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT* out = p->aout; MYFLT* in = p->ain; maxampl = *(p->ifullscale); if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } if (maxampl == FL(0.0)) maxampl = FL(1.0); if (*(p->ibipolar) != FL(0.0)) { /* bipolar mode */ /* clamp kamount in range [-1,1] */ midpoint = (*(p->kamount) > FL(1.0) ? maxampl : (*(p->kamount) < FL(-1.0) ? -maxampl : (*(p->kamount) * maxampl))); leftslope = (midpoint + maxampl) / maxampl; rightslope = (maxampl - midpoint) / maxampl; for (n=offset; nkamount) >= FL(1.0) ? maxampl : (*(p->kamount) <= FL(-1.0) ? FL(0.0) : ((*(p->kamount) + FL(1.0)) * halfmaxampl))); leftslope = midpoint / halfmaxampl; rightslope = (maxampl - midpoint) / halfmaxampl; for (n=offset; ninitphase) >= FL(0.0)) { if (UNLIKELY((longphs = (int32)phs))) { csound->Warning(csound, Str("init phase truncation\n")); } p->curphase = phs - (MYFLT)longphs; } return OK; } int SyncPhasor(CSOUND *csound, SYNCPHASOR *p) { double phase; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *out, *syncout, *syncin; double incr; int cpsIsARate; out = p->aphase; syncout = p->asyncout; syncin = p->asyncin; phase = p->curphase; cpsIsARate = IS_ASIG_ARG(p->xcps); /* check first input arg rate */ if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } if (cpsIsARate) { MYFLT *cps = p->xcps; for (n=offset; nonedsr); out[n] = (MYFLT)phase; phase += incr; if (phase >= 1.0) { phase -= 1.0; syncout[n] = FL(1.0); /* send sync when phase wraps */ } else if (phase < 0.0) { phase += 1.0; syncout[n] = FL(1.0); } else syncout[n] = FL(0.0); } } } else { incr = (double)(*p->xcps * csound->onedsr); for (n=offset; n= 1.0) { phase -= 1.0; syncout[n] = FL(1.0); /* send sync when phase wraps */ } else if (phase < 0.0) { phase += 1.0; syncout[n] = FL(1.0); } else syncout[n] = FL(0.0); } } } p->curphase = phase; return OK; } /* phasine is an experimental opcode that needs to be reconceptualized because it produces many discontinuities. */ #if 0 typedef struct { OPDS h; MYFLT *aout, *ain, *kphaseadjust, *ifullscale; MYFLT lastin, maxamplitude; } PHASINE; static int PhasineInit(CSOUND* csound, PHASINE* p) { p->lastin = FL(0.0); p->maxamplitude = *p->ifullscale; return OK; } static int Phasine(CSOUND* csound, PHASINE* p) { MYFLT last, cur, phase, adjust, maxampl; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT* out = p->aout; MYFLT* in = p->ain; adjust = *(p->kphaseadjust); last = p->lastin; maxampl = p->maxamplitude; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nlastin = last; return OK; } #endif /* code for linking dynamic libraries under Csound 5 */ #define S(x) sizeof(x) static OENTRY shape_localops[] = { /* { "phasine", S(PHASINE), 0, 5, "a", "akp", (SUBR)PhasineInit, NULL, (SUBR)Phasine }, */ { "powershape", S(POWER_SHAPE), 0, 5, "a", "akp", (SUBR)PowerShapeInit, NULL, (SUBR)PowerShape }, { "polynomial", S(POLYNOMIAL), 0, 4, "a", "az", NULL, NULL, (SUBR)Polynomial }, { "chebyshevpoly", S(CHEBPOLY), 0, 5, "a", "az", (SUBR)ChebyshevPolyInit, NULL, (SUBR)ChebyshevPolynomial }, { "pdclip", S(PD_CLIP), 0, 4, "a", "akkop", NULL, NULL, (SUBR)PDClip }, { "pdhalf", S(PD_HALF), 0, 4, "a", "akop", NULL, NULL, (SUBR)PDHalfX }, { "pdhalfy", S(PD_HALF), 0, 4, "a", "akop", NULL, NULL, (SUBR)PDHalfY }, { "syncphasor", S(SYNCPHASOR), 0, 5, "aa", "xao", (SUBR)SyncPhasorInit, NULL, (SUBR)SyncPhasor }, }; LINKAGE_BUILTIN(shape_localops) csound-6.10.0/Opcodes/signalflowgraph.cpp000066400000000000000000002402541321653344700203770ustar00rootroot00000000000000/* signalflowgrap.cpp: Copyright (C) 2016 by Michael Gogins This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /** * T H E S I G N A L F L O W G R A P H O P C O D E S * * Michael Gogins * * These opcodes enable the use of signal flow graphs * (AKA asynchronous data flow graphs) in Csound orchestras. * Signals flow from the outlets of source instruments * and are summed in the inlets of sink instruments. * Signals may be k-rate, a-rate, or f-rate. * Any number of outlets may be connected to any number of inlets. * When a new instance of an instrument is instantiated during performance, * the declared connections also are automatically instantiated. * * Signal flow graphs simplify the construction of complex mixers, * signal processing chains, and the like. They also simplify the re-use * of "plug and play" instrument definitions and even entire sub-orchestras, * which can simply be #included and then "plugged in" to existing orchestras. * * Note that inlets and outlets are defined in instruments without reference * to how they are connected. Connections are defined in the orchestra header. * It is this separation that enables plug-in instruments. * * Inlets must be named. Instruments may be named or numbered, but in * either case each source instrument must be defined * in the orchestra before any of its sinks. Naming instruments makes * it easier to connect outlets and inlets in any higher-level orchestra * to inlets and outlets in any lower-level #included orchestra. * * O P C O D E S * * outleta Sname, asignal * outletk Sname, ksignal * outletf Sname, fsignal * outletv Sname, xsignal[] * * Outlets send a, k, or f-rate signals out from an instrument. * A- and k-rate signals may be arrays. * * The name of the outlet is implicitly qualified by the instrument name * or number,`so it is valid to use the same outlet name in more than one * instrument (but not to use the same outlet name twice in one instrument). * * asignal inleta Sname * ksignal inletk Sname * fsignal inletf Sname * xsignal[] inletv SName * * Inlets receive a, k, or f-rate signals from outlets in * other instruments. A- and k-rate signals may be arrays. * * Outlets are connected to inlets of the same type using the connect * opcode. If arrays are used, the inlets and outlets must be a-rate * and the same shape. * * The name of the inlet is implicitly qualified by the instrument name, * or number, so it is valid to use the same inlet name in more than one * instrument (but not to use the same inlet name twice in one instrument). * * connect Tsource1, Soutlet1, Tsink1, Sinlet1 * * The connect opcode, valid only in orchestra headers, sends the signals * from the indicated outlet in all instances of the indicated source * instrument to the indicated inlet in all instances of the indicated sink * instrument. Each inlet instance receives the sum of the signals in all * outlet instances. Thus multiple instances of an outlet may fan in to one * instance of an inlet, or one instance of an outlet may fan out to * multiple instances of an inlet. * * alwayson Tinstrument [p4, ..., pn] * * Activates the indicated instrument in the orchestra header, * without need for an i statement. Instruments must be * activated in the same order as they are defined. * * The alwayson opcode is designed to simplify * the definition of re-usable orchestras with * signal processing or effects chains and networks. * * When the instrument is activated, p1 is the insno, p2 is 0, and p3 is -1. * Pfields from p4 on may optionally be sent to the instrument. * * ifno ftgenonce ip1, ip2dummy, isize, igen, iarga, iargb [, ...] * * Enables the creation of function tables entirely inside * instrument definitions, without any duplication of data. * * The ftgenonce opcode is designed to simplify writing instrument definitions * that can be re-used in different orchestras simply by #including them * and plugging them into some output instrument. There is no need to define * function tables either in the score, or in the orchestra header. * * The ftgenonce opcode is similar to ftgentmp, and has identical arguments. * However, function tables are neither duplicated nor deleted. Instead, * all of the arguments to the opcode are concatenated to form the key to a * dictionary that points to the function table number. Thus, every request * to ftgenonce with the same arguments receives the same instance of the * function table data. Every change in the value of any ftgenonce argument * causes the creation of a new function table. */ #include #include #include #include #include #include #include #include #include #include "OpcodeBase.hpp" #include #include "text.h" #include "sysdep.h" #define SIGNALFLOWGRAPH_DEBUG 0 namespace csound { struct SignalFlowGraph; struct Outleta; struct Outletk; struct Outletf; struct Outletkid; struct Outletv; struct Inleta; struct Inletk; struct Inletf; struct Inletkid; struct Inletv; struct Connect; struct AlwaysOn; struct FtGenOnce; std::ostream &operator << (std::ostream &stream, const EVTBLK &a) { stream << a.opcod; for (int i = 0; i < a.pcnt; i++) { stream << " " << a.p[i]; } return stream; } /** * A wrapper to get proper C++ value * semantics for a map key. */ struct EventBlock { EVTBLK evtblk; EventBlock() { std::memset(&evtblk, 0, sizeof(EVTBLK)); } EventBlock(const EVTBLK &other) { std::memcpy(&evtblk, &other, sizeof(EVTBLK)); } EventBlock(const EventBlock &other) { std::memcpy(&evtblk, &other.evtblk, sizeof(EVTBLK)); } virtual ~EventBlock() { } EventBlock &operator = (const EVTBLK &other) { std::memcpy(&evtblk, &other, sizeof(EVTBLK)); return *this; } EventBlock &operator = (const EventBlock &other) { std::memcpy(&evtblk, &other.evtblk, sizeof(EVTBLK)); return *this; } }; bool operator < (const EventBlock &a, const EventBlock &b) { int n = std::max(a.evtblk.pcnt, b.evtblk.pcnt); for (int i = 0; i < n; ++i) { //std::fprintf(stderr, "0x%p[%3d/%3d]: %9.4f 0x%p[%3d/%3d]: %9.4f\n", &a, i, a.evtblk.pcnt, a.evtblk.p[i], &b, i, b.evtblk.pcnt, b.evtblk.p[i]); if ((std::isnan(a.evtblk.p[i]) == true) || (std::isnan(b.evtblk.p[i]) == true)) { if ((std::isnan(a.evtblk.p[i]) == true) && (std::isnan(b.evtblk.p[i]) == false)) { //std::fprintf(stderr, "<\n\n"); return true; } if ((std::isnan(a.evtblk.p[i]) == false) && (std::isnan(b.evtblk.p[i]) == true)) { //std::fprintf(stderr, ">=\n\n"); return false; } if ((std::isnan(a.evtblk.p[i]) == true) && (std::isnan(b.evtblk.p[i]) == true)) { if (std::strcmp(a.evtblk.strarg, b.evtblk.strarg) < 0) { //std::fprintf(stderr, "<\n\n"); return true; } } } if (a.evtblk.p[i] < b.evtblk.p[i]) { //std::fprintf(stderr, "<\n\n"); return true; } if (a.evtblk.p[i] > b.evtblk.p[i]) { //std::fprintf(stderr, ">=\n\n"); return false; } } //if (a.evtblk.pcnt < b.evtblk.pcnt) { // std::fprintf(stderr, "<\n\n"); // return true; //} //std::fprintf(stderr, ">=\n\n"); return false; } // Identifiers are always "sourcename:outletname" and "sinkname:inletname", // or "sourcename:idname:outletname" and "sinkname:inletname." struct SignalFlowGraphState { CSOUND *csound; void *signal_flow_ports_lock; void *signal_flow_ftables_lock; std::map< std::string, std::vector< Outleta * > > aoutletsForSourceOutletIds; std::map< std::string, std::vector< Outletk * > > koutletsForSourceOutletIds; std::map< std::string, std::vector< Outletf * > > foutletsForSourceOutletIds; std::map< std::string, std::vector< Outletv * > > voutletsForSourceOutletIds; std::map< std::string, std::vector< Outletkid * > > kidoutletsForSourceOutletIds; std::map< std::string, std::vector< Inleta * > > ainletsForSinkInletIds; std::map< std::string, std::vector< Inletk * > > kinletsForSinkInletIds; std::map< std::string, std::vector< Inletf * > > finletsForSinkInletIds; std::map< std::string, std::vector< Inletv * > > vinletsForSinkInletIds; std::map< std::string, std::vector< Inletkid * > > kidinletsForSinkInletIds; std::map< std::string, std::vector< std::string > > connections; std::map< EventBlock, int > functionTablesForEvtblks; std::vector< std::vector< std::vector *> * > aoutletVectors; std::vector< std::vector< std::vector *> * > koutletVectors; std::vector< std::vector< std::vector *> * > foutletVectors; std::vector< std::vector< std::vector *> * > voutletVectors; std::vector< std::vector< std::vector *> * > kidoutletVectors; SignalFlowGraphState(CSOUND *csound_) { csound = csound_; signal_flow_ports_lock = csound->Create_Mutex(0); signal_flow_ftables_lock = csound->Create_Mutex(0); } ~SignalFlowGraphState() { } void clear() { LockGuard guard(csound, signal_flow_ports_lock); aoutletsForSourceOutletIds.clear(); ainletsForSinkInletIds.clear(); aoutletVectors.clear(); koutletsForSourceOutletIds.clear(); kinletsForSinkInletIds.clear(); koutletVectors.clear(); foutletsForSourceOutletIds.clear(); voutletsForSourceOutletIds.clear(); kidoutletsForSourceOutletIds.clear(); vinletsForSinkInletIds.clear(); kidinletsForSinkInletIds.clear(); finletsForSinkInletIds.clear(); foutletVectors.clear(); voutletVectors.clear(); kidoutletVectors.clear(); connections.clear(); } }; // For true thread-safety, access to shared data must be protected. // We will use one critical section for each logically independent // potential data race here: ports and ftables. /** * All it does is clear the data structures for the current instance of Csound, * in case they are full from a previous performance. */ struct SignalFlowGraph : public OpcodeBase { int init(CSOUND *csound) { warn(csound, "signalflowgraph::init(0x%p)\n", csound); SignalFlowGraphState *sfg_globals = 0; csound::QueryGlobalPointer(csound, "sfg_globals", sfg_globals); sfg_globals->clear(); return OK; }; }; struct Outleta : public OpcodeNoteoffBase { /** * Inputs. */ STRINGDAT *Sname; MYFLT *asignal; /** * State. */ char sourceOutletId[0x100]; SignalFlowGraphState *sfg_globals; int init(CSOUND *csound) { //warn(csound, "BEGAN Outleta::init()...\n"); csound::QueryGlobalPointer(csound, "sfg_globals", sfg_globals); LockGuard guard(csound, sfg_globals->signal_flow_ports_lock); sourceOutletId[0] = 0; const char *insname = csound->GetInstrumentList(csound)[opds.insdshead->insno]->insname; if (insname) { std::sprintf(sourceOutletId, "%s:%s", insname, (char *)Sname->data); } else { std::sprintf(sourceOutletId, "%d:%s", opds.insdshead->insno, (char *)Sname->data); } std::vector &aoutlets = sfg_globals->aoutletsForSourceOutletIds[sourceOutletId]; if (std::find(aoutlets.begin(), aoutlets.end(), this) == aoutlets.end()) { aoutlets.push_back(this); warn(csound, Str("Created instance 0x%x of %d instances of outlet %s\n"), this, aoutlets.size(), sourceOutletId); } //warn(csound, "ENDED Outleta::init()...\n"); return OK; } int noteoff(CSOUND *csound) { LockGuard guard(csound, sfg_globals->signal_flow_ports_lock); std::vector &aoutlets = sfg_globals->aoutletsForSourceOutletIds[sourceOutletId]; std::vector::iterator thisoutlet = std::find(aoutlets.begin(), aoutlets.end(), this); aoutlets.erase(thisoutlet); warn(csound, Str("Removed instance 0x%x of %d instances of outleta %s\n"), this, aoutlets.size(), sourceOutletId); return OK; } }; struct Inleta : public OpcodeBase { /** * Output. */ MYFLT *asignal; /** * Inputs. */ STRINGDAT *Sname; /** * State. */ char sinkInletId[0x100]; std::vector< std::vector *> *sourceOutlets; int sampleN; SignalFlowGraphState *sfg_globals; int init(CSOUND *csound) { csound::QueryGlobalPointer(csound, "sfg_globals", sfg_globals); LockGuard guard(csound, sfg_globals->signal_flow_ports_lock); warn(csound, "BEGAN Inleta::init()...\n"); sampleN = opds.insdshead->ksmps; warn(csound, "sourceOutlets: 0x%x\n", sourceOutlets); //think problem is here //should always create if (std::find(sfg_globals->aoutletVectors.begin(), sfg_globals->aoutletVectors.end(), sourceOutlets) == sfg_globals->aoutletVectors.end()) { sourceOutlets = new std::vector< std::vector *>; sfg_globals->aoutletVectors.push_back(sourceOutlets); } else { sourceOutlets->clear(); } warn(csound, "sourceOutlets: 0x%x\n", sourceOutlets); sinkInletId[0] = 0; const char *insname = csound->GetInstrumentList(csound)[opds.insdshead->insno]->insname; if (insname) { std::sprintf(sinkInletId, "%s:%s", insname, (char *)Sname->data); } else { std::sprintf(sinkInletId, "%d:%s", opds.insdshead->insno, (char *)Sname->data); } std::vector &ainlets = sfg_globals->ainletsForSinkInletIds[sinkInletId]; if (std::find(ainlets.begin(), ainlets.end(), this) == ainlets.end()) { ainlets.push_back(this); warn(csound, Str("Created instance 0x%x of inlet %s\n"), this, sinkInletId); } // Find source outlets connecting to this. // Any number of sources may connect to any number of sinks. std::vector &sourceOutletIds = sfg_globals->connections[sinkInletId]; for (size_t i = 0, n = sourceOutletIds.size(); i < n; i++) { const std::string &sourceOutletId = sourceOutletIds[i]; std::vector &aoutlets = sfg_globals->aoutletsForSourceOutletIds[sourceOutletId]; if (std::find(sourceOutlets->begin(), sourceOutlets->end(), &aoutlets) == sourceOutlets->end()) { sourceOutlets->push_back(&aoutlets); warn(csound, Str("Connected instances of outlet %s to instance 0x%x of " "inlet %s.\n"), sourceOutletId.c_str(), this, sinkInletId); } } warn(csound, "ENDED Inleta::init().\n"); return OK; } /** * Sum arate values from active outlets feeding this inlet. */ int audio(CSOUND *csound) { LockGuard guard(csound, sfg_globals->signal_flow_ports_lock); //warn(csound, "BEGAN Inleta::audio()...\n"); // Zero the inlet buffer. for (int sampleI = 0; sampleI < sampleN; sampleI++) { asignal[sampleI] = FL(0.0); } // Loop over the source connections... for (size_t sourceI = 0, sourceN = sourceOutlets->size(); sourceI < sourceN; sourceI++) { // Loop over the source connection instances... std::vector *instances = sourceOutlets->at(sourceI); for (size_t instanceI = 0, instanceN = instances->size(); instanceI < instanceN; instanceI++) { Outleta *sourceOutlet = instances->at(instanceI); // Skip inactive instances. if (sourceOutlet->opds.insdshead->actflg) { for (int sampleI = 0, sampleN = ksmps(); sampleI < sampleN; ++sampleI) { asignal[sampleI] += sourceOutlet->asignal[sampleI]; } } } } //warn(csound, "ENDED Inleta::audio().\n"); return OK; } }; struct Outletk : public OpcodeNoteoffBase { /** * Inputs. */ STRINGDAT *Sname; MYFLT *ksignal; /** * State. */ char sourceOutletId[0x100]; SignalFlowGraphState *sfg_globals; int init(CSOUND *csound) { csound::QueryGlobalPointer(csound, "sfg_globals", sfg_globals); LockGuard guard(csound, sfg_globals->signal_flow_ports_lock); const char *insname = csound->GetInstrumentList(csound)[opds.insdshead->insno]->insname; if (insname) { std::sprintf(sourceOutletId, "%s:%s", insname, (char *)Sname->data); } else { std::sprintf(sourceOutletId, "%d:%s", opds.insdshead->insno, (char *)Sname->data); } std::vector &koutlets = sfg_globals->koutletsForSourceOutletIds[sourceOutletId]; if (std::find(koutlets.begin(), koutlets.end(), this) == koutlets.end()) { koutlets.push_back(this); warn(csound, Str("Created instance 0x%x of %d instances of outlet %s\n"), this, koutlets.size(), sourceOutletId); } return OK; } int noteoff(CSOUND *csound) { LockGuard guard(csound, sfg_globals->signal_flow_ports_lock); std::vector &koutlets = sfg_globals->koutletsForSourceOutletIds[sourceOutletId]; std::vector::iterator thisoutlet = std::find(koutlets.begin(), koutlets.end(), this); koutlets.erase(thisoutlet); warn(csound, Str("Removed 0x%x of %d instances of outletk %s\n"), this, koutlets.size(), sourceOutletId); return OK; } }; struct Inletk : public OpcodeBase { /** * Output. */ MYFLT *ksignal; /** * Inputs. */ STRINGDAT *Sname; /** * State. */ char sinkInletId[0x100]; std::vector< std::vector *> *sourceOutlets; int ksmps; SignalFlowGraphState *sfg_globals; int init(CSOUND *csound) { csound::QueryGlobalPointer(csound, "sfg_globals", sfg_globals); LockGuard guard(csound, sfg_globals->signal_flow_ports_lock); ksmps = opds.insdshead->ksmps; if (std::find(sfg_globals->koutletVectors.begin(), sfg_globals->koutletVectors.end(), sourceOutlets) == sfg_globals->koutletVectors.end()) { sourceOutlets = new std::vector< std::vector *>; sfg_globals->koutletVectors.push_back(sourceOutlets); } else { sourceOutlets->clear(); } sinkInletId[0] = 0; const char *insname = csound->GetInstrumentList(csound)[opds.insdshead->insno]->insname; if (insname) { std::sprintf(sinkInletId, "%s:%s", insname, (char *)Sname->data); } else { std::sprintf(sinkInletId, "%d:%s", opds.insdshead->insno, (char *)Sname->data); } std::vector &kinlets = sfg_globals->kinletsForSinkInletIds[sinkInletId]; if (std::find(kinlets.begin(), kinlets.end(), this) == kinlets.end()) { kinlets.push_back(this); warn(csound, Str("Created instance 0x%x of inlet %s\n"), this, sinkInletId); } // Find source outlets connecting to this. // Any number of sources may connect to any number of sinks. std::vector &sourceOutletIds = sfg_globals->connections[sinkInletId]; for (size_t i = 0, n = sourceOutletIds.size(); i < n; i++) { const std::string &sourceOutletId = sourceOutletIds[i]; std::vector &koutlets = sfg_globals->koutletsForSourceOutletIds[sourceOutletId]; if (std::find(sourceOutlets->begin(), sourceOutlets->end(), &koutlets) == sourceOutlets->end()) { sourceOutlets->push_back(&koutlets); warn(csound, Str("Connected instances of outlet %s to instance 0x%x" "of inlet %s.\n"), sourceOutletId.c_str(), this, sinkInletId); } } return OK; } /** * Sum krate values from active outlets feeding this inlet. */ int kontrol(CSOUND *csound) { LockGuard guard(csound, sfg_globals->signal_flow_ports_lock); // Zero the inlet buffer. *ksignal = FL(0.0); // Loop over the source connections... for (size_t sourceI = 0, sourceN = sourceOutlets->size(); sourceI < sourceN; sourceI++) { // Loop over the source connection instances... const std::vector *instances = sourceOutlets->at(sourceI); for (size_t instanceI = 0, instanceN = instances->size(); instanceI < instanceN; instanceI++) { const Outletk *sourceOutlet = instances->at(instanceI); // Skip inactive instances. if (sourceOutlet->opds.insdshead->actflg) { *ksignal += *sourceOutlet->ksignal; } } } return OK; } }; struct Outletf : public OpcodeNoteoffBase { /** * Inputs. */ STRINGDAT *Sname; PVSDAT *fsignal; /** * State. */ char sourceOutletId[0x100]; SignalFlowGraphState *sfg_globals; int init(CSOUND *csound) { csound::QueryGlobalPointer(csound, "sfg_globals", sfg_globals); LockGuard guard(csound, sfg_globals->signal_flow_ports_lock); const char *insname = csound->GetInstrumentList(csound)[opds.insdshead->insno]->insname; if (insname) { std::sprintf(sourceOutletId, "%s:%s", insname, (char *)Sname->data); } else { std::sprintf(sourceOutletId, "%d:%s", opds.insdshead->insno, (char *)Sname->data); } std::vector &foutlets = sfg_globals->foutletsForSourceOutletIds[sourceOutletId]; if (std::find(foutlets.begin(), foutlets.end(), this) == foutlets.end()) { foutlets.push_back(this); warn(csound, Str("Created instance 0x%x of outlet %s\n"), this, sourceOutletId); } return OK; } int noteoff(CSOUND *csound) { std::vector &foutlets = sfg_globals->foutletsForSourceOutletIds[sourceOutletId]; std::vector::iterator thisoutlet = std::find(foutlets.begin(), foutlets.end(), this); foutlets.erase(thisoutlet); warn(csound, Str("Removed 0x%x of %d instances of outletf %s\n"), this, foutlets.size(), sourceOutletId); return OK; } }; struct Inletf : public OpcodeBase { /** * Output. */ PVSDAT *fsignal; /** * Inputs. */ STRINGDAT *Sname; /** * State. */ char sinkInletId[0x100]; std::vector< std::vector *> *sourceOutlets; int ksmps; int lastframe; bool fsignalInitialized; SignalFlowGraphState *sfg_globals; int init(CSOUND *csound) { csound::QueryGlobalPointer(csound, "sfg_globals", sfg_globals); LockGuard guard(csound, sfg_globals->signal_flow_ports_lock); ksmps = opds.insdshead->ksmps; lastframe = 0; fsignalInitialized = false; if (std::find(sfg_globals->foutletVectors.begin(), sfg_globals->foutletVectors.end(), sourceOutlets) == sfg_globals->foutletVectors.end()) { sourceOutlets = new std::vector< std::vector *>; sfg_globals->foutletVectors.push_back(sourceOutlets); } else { sourceOutlets->clear(); } sinkInletId[0] = 0; const char *insname = csound->GetInstrumentList(csound)[opds.insdshead->insno]->insname; if (insname) { std::sprintf(sinkInletId, "%s:%s", insname, (char *)Sname->data); } else { std::sprintf(sinkInletId, "%d:%s", opds.insdshead->insno, (char *)Sname->data); } std::vector &finlets = sfg_globals->finletsForSinkInletIds[sinkInletId]; if (std::find(finlets.begin(), finlets.end(), this) == finlets.end()) { finlets.push_back(this); warn(csound, Str("Created instance 0x%x of inlet %s\n"), this, sinkInletId); } // Find source outlets connecting to this. // Any number of sources may connect to any number of sinks. std::vector &sourceOutletIds = sfg_globals->connections[sinkInletId]; for (size_t i = 0, n = sourceOutletIds.size(); i < n; i++) { const std::string &sourceOutletId = sourceOutletIds[i]; std::vector &foutlets = sfg_globals->foutletsForSourceOutletIds[sourceOutletId]; if (std::find(sourceOutlets->begin(), sourceOutlets->end(), &foutlets) == sourceOutlets->end()) { sourceOutlets->push_back(&foutlets); warn(csound, Str("Connected instances of outlet %s to instance 0x%x of inlet %s.\n"), sourceOutletId.c_str(), this, sinkInletId); } } return OK; } /** * Mix fsig values from active outlets feeding this inlet. */ int audio(CSOUND *csound) { LockGuard guard(csound, sfg_globals->signal_flow_ports_lock); int result = OK; float *sink = 0; float *source = 0; CMPLX *sinkFrame = 0; CMPLX *sourceFrame = 0; // Loop over the source connections... for (size_t sourceI = 0, sourceN = sourceOutlets->size(); sourceI < sourceN; sourceI++) { // Loop over the source connection instances... const std::vector *instances = sourceOutlets->at(sourceI); for (size_t instanceI = 0, instanceN = instances->size(); instanceI < instanceN; instanceI++) { const Outletf *sourceOutlet = instances->at(instanceI); // Skip inactive instances. if (sourceOutlet->opds.insdshead->actflg) { if (!fsignalInitialized) { int32 N = sourceOutlet->fsignal->N; if (UNLIKELY(sourceOutlet->fsignal == fsignal)) { csound->Warning(csound, Str("Unsafe to have same fsig as in and out")); } fsignal->sliding = 0; if (sourceOutlet->fsignal->sliding) { if (fsignal->frame.auxp == 0 || fsignal->frame.size < sizeof(MYFLT) * opds.insdshead->ksmps * (N + 2)) csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT) * opds.insdshead->ksmps, &fsignal->frame); fsignal->NB = sourceOutlet->fsignal->NB; fsignal->sliding = 1; } else if (fsignal->frame.auxp == 0 || fsignal->frame.size < sizeof(float) * (N + 2)) { csound->AuxAlloc(csound, (N + 2) * sizeof(float), &fsignal->frame); } fsignal->N = N; fsignal->overlap = sourceOutlet->fsignal->overlap; fsignal->winsize = sourceOutlet->fsignal->winsize; fsignal->wintype = sourceOutlet->fsignal->wintype; fsignal->format = sourceOutlet->fsignal->format; fsignal->framecount = 1; lastframe = 0; if (UNLIKELY(!(fsignal->format == PVS_AMP_FREQ) || (fsignal->format == PVS_AMP_PHASE))) result = csound->InitError(csound, Str("inletf: signal format " "must be amp-phase or amp-freq.")); fsignalInitialized = true; } if (fsignal->sliding) { for (int frameI = 0; frameI < ksmps; frameI++) { sinkFrame = (CMPLX *) fsignal->frame.auxp + (fsignal->NB * frameI); sourceFrame = (CMPLX *) sourceOutlet->fsignal->frame.auxp + (fsignal->NB * frameI); for (size_t binI = 0, binN = fsignal->NB; binI < binN; binI++) { if (sourceFrame[binI].re > sinkFrame[binI].re) { sinkFrame[binI] = sourceFrame[binI]; } } } } } else { sink = (float *)fsignal->frame.auxp; source = (float *)sourceOutlet->fsignal->frame.auxp; if (lastframe < int(fsignal->framecount)) { for (size_t binI = 0, binN = fsignal->N + 2; binI < binN; binI += 2) { if (source[binI] > sink[binI]) { source[binI] = sink[binI]; source[binI + 1] = sink[binI + 1]; } } fsignal->framecount = lastframe = sourceOutlet->fsignal->framecount; } } } } return result; } }; struct Outletv : public OpcodeNoteoffBase { /** * Inputs. */ STRINGDAT *Sname; ARRAYDAT *vsignal; /** * State. */ char sourceOutletId[0x100]; SignalFlowGraphState *sfg_globals; int init(CSOUND *csound) { warn(csound, "BEGAN Outletv::init()...\n"); csound::QueryGlobalPointer(csound, "sfg_globals", sfg_globals); LockGuard guard(csound, sfg_globals->signal_flow_ports_lock); sourceOutletId[0] = 0; const char *insname = csound->GetInstrumentList(csound)[opds.insdshead->insno]->insname; if (insname) { std::sprintf(sourceOutletId, "%s:%s", insname, (char *)Sname->data); } else { std::sprintf(sourceOutletId, "%d:%s", opds.insdshead->insno, (char *)Sname->data); } std::vector &voutlets = sfg_globals->voutletsForSourceOutletIds[sourceOutletId]; if (std::find(voutlets.begin(), voutlets.end(), this) == voutlets.end()) { voutlets.push_back(this); warn(csound, Str("Created instance 0x%x of %d instances of outlet %s (out arraydat: 0x%x dims: %2d size: %4d [%4d] data: 0x%x (0x%x))\n"), this, voutlets.size(), sourceOutletId, vsignal, vsignal->dimensions, vsignal->sizes[0], vsignal->arrayMemberSize, vsignal->data, &vsignal->data); } warn(csound, "ENDED Outletv::init()...\n"); return OK; } int noteoff(CSOUND *csound) { LockGuard guard(csound, sfg_globals->signal_flow_ports_lock); std::vector &voutlets = sfg_globals->voutletsForSourceOutletIds[sourceOutletId]; std::vector::iterator thisoutlet = std::find(voutlets.begin(), voutlets.end(), this); voutlets.erase(thisoutlet); warn(csound, Str("Removed 0x%x of %d instances of outletv %s\n"), this, voutlets.size(), sourceOutletId); return OK; } }; struct Inletv : public OpcodeBase { /** * Output. */ ARRAYDAT *vsignal; /** * Inputs. */ STRINGDAT *Sname; /** * State. */ char sinkInletId[0x100]; std::vector< std::vector *> *sourceOutlets; size_t arraySize; size_t myFltsPerArrayElement; int sampleN; SignalFlowGraphState *sfg_globals; int init(CSOUND *csound) { warn(csound, "BEGAN Inletv::init()...\n"); csound::QueryGlobalPointer(csound, "sfg_globals", sfg_globals); LockGuard guard(csound, sfg_globals->signal_flow_ports_lock); sampleN = opds.insdshead->ksmps; // The array elements may be krate (1 MYFLT) or arate (ksmps MYFLT). myFltsPerArrayElement = vsignal->arrayMemberSize / sizeof(MYFLT); warn(csound, "myFltsPerArrayElement: %d\n", myFltsPerArrayElement); arraySize = myFltsPerArrayElement; for (size_t dimension = 0; dimension < (size_t) vsignal->dimensions; ++dimension) { arraySize *= vsignal->sizes[dimension]; } warn(csound, "arraySize: %d\n", arraySize); warn(csound, "sourceOutlets: 0x%x\n", sourceOutlets); if (std::find(sfg_globals->voutletVectors.begin(), sfg_globals->voutletVectors.end(), sourceOutlets) == sfg_globals->voutletVectors.end()) { sourceOutlets = new std::vector< std::vector *>; sfg_globals->voutletVectors.push_back(sourceOutlets); } else { sourceOutlets->clear(); } warn(csound, "sourceOutlets: 0x%x\n", sourceOutlets); sinkInletId[0] = 0; const char *insname = csound->GetInstrumentList(csound)[opds.insdshead->insno]->insname; if (insname) { std::sprintf(sinkInletId, "%s:%s", insname, (char *)Sname->data); } else { std::sprintf(sinkInletId, "%d:%s", opds.insdshead->insno, (char *)Sname->data); } std::vector &vinlets = sfg_globals->vinletsForSinkInletIds[sinkInletId]; if (std::find(vinlets.begin(), vinlets.end(), this) == vinlets.end()) { vinlets.push_back(this); warn(csound, Str("Created instance 0x%x of inlet %s (in arraydat: 0x%x dims: %2d size: %4d [%4d] data: 0x%x (0x%x))\n"), this, sinkInletId, vsignal, vsignal->dimensions, vsignal->sizes[0], vsignal->arrayMemberSize, vsignal->data, &vsignal->data); } // Find source outlets connecting to this. // Any number of sources may connect to any number of sinks. std::vector &sourceOutletIds = sfg_globals->connections[sinkInletId]; for (size_t i = 0, n = sourceOutletIds.size(); i < n; i++) { const std::string &sourceOutletId = sourceOutletIds[i]; std::vector &voutlets = sfg_globals->voutletsForSourceOutletIds[sourceOutletId]; if (std::find(sourceOutlets->begin(), sourceOutlets->end(), &voutlets) == sourceOutlets->end()) { sourceOutlets->push_back(&voutlets); warn(csound, Str("Connected instances of outlet %s to instance 0x%x of " "inlet %s\n"), sourceOutletId.c_str(), this, sinkInletId); } } warn(csound, "ENDED Inletv::init().\n"); return OK; } /** * Sum values from active outlets feeding this inlet. */ int audio(CSOUND *csound) { //warn(csound, "BEGAN Inletv::audio()...\n"); LockGuard guard(csound, sfg_globals->signal_flow_ports_lock); for (uint32_t signalI = 0; signalI < arraySize; ++signalI) { vsignal->data[signalI] = FL(0.0); } // Loop over the source connections... for (size_t sourceI = 0, sourceN = sourceOutlets->size(); sourceI < sourceN; sourceI++) { // Loop over the source connection instances... std::vector *instances = sourceOutlets->at(sourceI); for (size_t instanceI = 0, instanceN = instances->size(); instanceI < instanceN; instanceI++) { Outletv *sourceOutlet = instances->at(instanceI); // Skip inactive instances. if (sourceOutlet->opds.insdshead->actflg) { for (uint32_t signalI = 0; signalI < arraySize; ++signalI) { ARRAYDAT *insignal = sourceOutlet->vsignal; MYFLT *indata = insignal->data; //warn(csound, "Inletv::audio: sourceOutlet: 0%x in arraydat: 0x%x data: 0x%x (0x%x)\n", sourceOutlet, insignal, indata, &insignal->data); vsignal->data[signalI] += indata[signalI]; } } } } //warn(csound, "ENDED Inletv::audio().\n"); return OK; } }; struct Outletkid : public OpcodeNoteoffBase { /** * Inputs. */ STRINGDAT *Sname; STRINGDAT *SinstanceId; MYFLT *ksignal; /** * State. */ char sourceOutletId[0x100]; char *instanceId; SignalFlowGraphState *sfg_globals; int init(CSOUND *csound) { csound::QueryGlobalPointer(csound, "sfg_globals", sfg_globals); LockGuard guard(csound, sfg_globals->signal_flow_ports_lock); const char *insname = csound->GetInstrumentList(csound)[opds.insdshead->insno]->insname; instanceId = csound->strarg2name(csound, (char *) 0, SinstanceId->data, (char *)"", 1); if (insname && instanceId) { std::sprintf(sourceOutletId, "%s:%s", insname, (char *)Sname->data); } else { std::sprintf(sourceOutletId, "%d:%s", opds.insdshead->insno, (char *)Sname->data); } if (insname) { std::sprintf(sourceOutletId, "%s:%s", insname, (char *)Sname->data); } else { std::sprintf(sourceOutletId, "%d:%s", opds.insdshead->insno, (char *)Sname->data); } std::vector &koutlets = sfg_globals->kidoutletsForSourceOutletIds[sourceOutletId]; if (std::find(koutlets.begin(), koutlets.end(), this) == koutlets.end()) { koutlets.push_back(this); warn(csound, Str("Created instance 0x%x of %d instances of outlet %s\n"), this, koutlets.size(), sourceOutletId); } return OK; } int noteoff(CSOUND *csound) { LockGuard guard(csound, sfg_globals->signal_flow_ports_lock); std::vector &koutlets = sfg_globals->kidoutletsForSourceOutletIds[sourceOutletId]; std::vector::iterator thisoutlet = std::find(koutlets.begin(), koutlets.end(), this); koutlets.erase(thisoutlet); warn(csound, Str("Removed 0x%x of %d instances of outletkid %s\n"), this, koutlets.size(), sourceOutletId); return OK; } }; struct Inletkid : public OpcodeBase { /** * Output. */ MYFLT *ksignal; /** * Inputs. */ STRINGDAT *Sname; STRINGDAT *SinstanceId; /** * State. */ char sinkInletId[0x100]; char *instanceId; std::vector< std::vector *> *sourceOutlets; int ksmps; SignalFlowGraphState *sfg_globals; int init(CSOUND *csound) { csound::QueryGlobalPointer(csound, "sfg_globals", sfg_globals); LockGuard guard(csound, sfg_globals->signal_flow_ports_lock); ksmps = opds.insdshead->ksmps; if (std::find(sfg_globals->kidoutletVectors.begin(), sfg_globals->kidoutletVectors.end(), sourceOutlets) == sfg_globals->kidoutletVectors.end()) { sourceOutlets = new std::vector< std::vector *>; sfg_globals->kidoutletVectors.push_back(sourceOutlets); } else { sourceOutlets->clear(); } sinkInletId[0] = 0; instanceId = csound->strarg2name(csound, (char *) 0, SinstanceId->data, (char *)"", 1); const char *insname = csound->GetInstrumentList(csound)[opds.insdshead->insno]->insname; if (insname) { std::sprintf(sinkInletId, "%s:%s", insname, (char *)Sname->data); } else { std::sprintf(sinkInletId, "%d:%s", opds.insdshead->insno, (char *)Sname->data); } std::vector &kinlets = sfg_globals->kidinletsForSinkInletIds[sinkInletId]; if (std::find(kinlets.begin(), kinlets.end(), this) == kinlets.end()) { kinlets.push_back(this); warn(csound, Str("Created instance 0x%x of inlet %s\n"), this, sinkInletId); } // Find source outlets connecting to this. // Any number of sources may connect to any number of sinks. std::vector &sourceOutletIds = sfg_globals->connections[sinkInletId]; for (size_t i = 0, n = sourceOutletIds.size(); i < n; i++) { const std::string &sourceOutletId = sourceOutletIds[i]; std::vector &koutlets = sfg_globals->kidoutletsForSourceOutletIds[sourceOutletId]; if (std::find(sourceOutlets->begin(), sourceOutlets->end(), &koutlets) == sourceOutlets->end()) { sourceOutlets->push_back(&koutlets); warn(csound, Str("Connected instances of outlet %s to instance 0x%x of inlet %s.\n"), sourceOutletId.c_str(), this, sinkInletId); } } return OK; } /** * Replay instance signal. */ int kontrol(CSOUND *csound) { LockGuard guard(csound, sfg_globals->signal_flow_ports_lock); // Zero the / buffer. *ksignal = FL(0.0); // Loop over the source connections... for (size_t sourceI = 0, sourceN = sourceOutlets->size(); sourceI < sourceN; sourceI++) { // Loop over the source connection instances... const std::vector *instances = sourceOutlets->at(sourceI); for (size_t instanceI = 0, instanceN = instances->size(); instanceI < instanceN; instanceI++) { const Outletkid *sourceOutlet = instances->at(instanceI); // Skip inactive instances and also all non-matching instances. if (sourceOutlet->opds.insdshead->actflg) { if (std::strcmp(sourceOutlet->instanceId, instanceId) == 0) { *ksignal += *sourceOutlet->ksignal; } } } } return OK; } }; struct Connect : public OpcodeBase { /** * Inputs. */ MYFLT *Source; STRINGDAT *Soutlet; MYFLT *Sink; STRINGDAT *Sinlet; MYFLT *gain; SignalFlowGraphState *sfg_globals; int init(CSOUND *csound) { csound::QueryGlobalPointer(csound, "sfg_globals", sfg_globals); LockGuard guard(csound, sfg_globals->signal_flow_ports_lock); std::string sourceOutletId = csound->strarg2name(csound, (char *) 0, ((std::isnan(*Source)) ? csound->GetString(csound,*Source) : (char *)Source), (char *)"", std::isnan(*Source)); sourceOutletId += ":"; sourceOutletId += csound->strarg2name(csound, (char *) 0, Soutlet->data, (char *)"", 1); std::string sinkInletId = csound->strarg2name(csound, (char *) 0, ((std::isnan(*Sink)) ? csound->GetString(csound,*Sink) : (char *)Sink), (char *)"", std::isnan(*Sink)); sinkInletId += ":"; sinkInletId += csound->strarg2name(csound, (char *) 0, Sinlet->data, (char *)"", 1); warn(csound, Str("Connected outlet %s to inlet %s.\n"), sourceOutletId.c_str(), sinkInletId.c_str()); sfg_globals->connections[sinkInletId].push_back(sourceOutletId); return OK; } }; struct Connecti : public OpcodeBase { /** * Inputs. */ MYFLT *Source; STRINGDAT *Soutlet; STRINGDAT *Sink; STRINGDAT *Sinlet; MYFLT *gain; SignalFlowGraphState *sfg_globals; int init(CSOUND *csound) { csound::QueryGlobalPointer(csound, "sfg_globals", sfg_globals); LockGuard guard(csound, sfg_globals->signal_flow_ports_lock); std::string sourceOutletId = csound->strarg2name(csound, (char *) 0, ((std::isnan(*Source)) ? csound->GetString(csound,*Source) : (char *)Source), (char *)"", std::isnan(*Source)); sourceOutletId += ":"; sourceOutletId += csound->strarg2name(csound, (char *) 0, Soutlet->data, (char *)"", 1); std::string sinkInletId = csound->strarg2name(csound, (char *) 0, Sink->data, (char *)"", 1); sinkInletId += ":"; sinkInletId += csound->strarg2name(csound, (char *) 0, Sinlet->data, (char *)"", 1); warn(csound, Str("Connected outlet %s to inlet %s.\n"), sourceOutletId.c_str(), sinkInletId.c_str()); sfg_globals->connections[sinkInletId].push_back(sourceOutletId); return OK; } }; struct Connectii : public OpcodeBase { /** * Inputs. */ STRINGDAT *Source; STRINGDAT *Soutlet; MYFLT *Sink; STRINGDAT *Sinlet; MYFLT *gain; SignalFlowGraphState *sfg_globals; int init(CSOUND *csound) { csound::QueryGlobalPointer(csound, "sfg_globals", sfg_globals); LockGuard guard(csound, sfg_globals->signal_flow_ports_lock); std::string sourceOutletId = csound->strarg2name(csound, (char *) 0, Source->data, (char *)"", 1); sourceOutletId += ":"; sourceOutletId += csound->strarg2name(csound, (char *) 0, Soutlet->data, (char *)"", 1); std::string sinkInletId = csound->strarg2name(csound, (char *) 0, ((std::isnan(*Sink)) ? csound->GetString(csound,*Sink) : (char *)Sink), (char *)"", std::isnan(*Sink));; sinkInletId += ":"; sinkInletId += csound->strarg2name(csound, (char *) 0, Sinlet->data, (char *)"", 1); warn(csound, Str("Connected outlet %s to inlet %s.\n"), sourceOutletId.c_str(), sinkInletId.c_str()); sfg_globals->connections[sinkInletId].push_back(sourceOutletId); return OK; } }; struct ConnectS : public OpcodeBase { /** * Inputs. */ STRINGDAT *Source; STRINGDAT *Soutlet; STRINGDAT *Sink; STRINGDAT *Sinlet; MYFLT *gain; SignalFlowGraphState *sfg_globals; int init(CSOUND *csound) { csound::QueryGlobalPointer(csound, "sfg_globals", sfg_globals); LockGuard guard(csound, sfg_globals->signal_flow_ports_lock); std::string sourceOutletId = csound->strarg2name(csound, (char *) 0, Source->data, (char *)"", 1); sourceOutletId += ":"; sourceOutletId += csound->strarg2name(csound, (char *) 0, Soutlet->data, (char *)"", 1); std::string sinkInletId = csound->strarg2name(csound, (char *) 0, Sink->data, (char *)"", 1); sinkInletId += ":"; sinkInletId += csound->strarg2name(csound, (char *) 0, Sinlet->data, (char *)"", 1); warn(csound, Str("Connected outlet %s to inlet %s.\n"), sourceOutletId.c_str(), sinkInletId.c_str()); sfg_globals->connections[sinkInletId].push_back(sourceOutletId); return OK; } }; struct AlwaysOnS : public OpcodeBase { /** * Inputs. */ STRINGDAT *Sinstrument; MYFLT *argums[VARGMAX]; /** * State. */ EVTBLK evtblk; int init(CSOUND *csound) { MYFLT offset = csound->GetScoreOffsetSeconds(csound); evtblk.opcod = 'i'; evtblk.strarg = 0; evtblk.p[0] = FL(0.0); evtblk.p[1] = csound->strarg2insno(csound, Sinstrument->data, 1); evtblk.p[2] = evtblk.p2orig = offset; evtblk.p[3] = evtblk.p3orig = FL(-1.0); size_t inArgCount = csound->GetInputArgCnt(this); // Add 2, for hard-coded p2 and p3. evtblk.pcnt = (int16) inArgCount + 2; // Subtract 1, for only required inarg p1. size_t argumN = inArgCount - 1; // Start evtblk at 4, argums at 0. for (size_t pfieldI = 4, argumI = 0; argumI < argumN; pfieldI++, argumI++) { evtblk.p[pfieldI] = *argums[argumI]; } csound->insert_score_event_at_sample(csound, &evtblk, 0); return OK; } }; struct AlwaysOn : public OpcodeBase { /** * Inputs. */ MYFLT *Sinstrument; MYFLT *argums[VARGMAX]; /** * State. */ EVTBLK evtblk; int init(CSOUND *csound) { std::string source = csound->strarg2name(csound, (char *) 0, Sinstrument, (char *)"", (int) 0); MYFLT offset = csound->GetScoreOffsetSeconds(csound); evtblk.opcod = 'i'; evtblk.strarg = 0; evtblk.p[0] = FL(0.0); evtblk.p[1] = *Sinstrument; evtblk.p[2] = evtblk.p2orig = offset; evtblk.p[3] = evtblk.p3orig = FL(-1.0); size_t inArgCount = csound->GetInputArgCnt(this); // Add 2, for hard-coded p2 and p3. evtblk.pcnt = (int16) inArgCount + 2; // Subtract 1, for only required inarg p1. size_t argumN = inArgCount - 1; // Start evtblk at 4, argums at 0. for (size_t pfieldI = 4, argumI = 0; argumI < argumN; pfieldI++, argumI++) { evtblk.p[pfieldI] = *argums[argumI]; } csound->insert_score_event_at_sample(csound, &evtblk, 0); return OK; } }; typedef struct { OPDS h; MYFLT *ifno, *p1, *p2, *p3, *p4, *p5, *argums[VARGMAX]; } FTGEN; typedef struct namedgen { char *name; int genum; struct namedgen *next; } NAMEDGEN; static void log(CSOUND *csound, const char *format,...) { va_list args; va_start(args, format); if (csound) { csound->MessageV(csound, 0, format, args); } else { vfprintf(stdout, format, args); } va_end(args); } static void warn(CSOUND *csound, const char *format,...) { if (csound) { if (csound->GetMessageLevel(csound) & WARNMSG) { va_list args; va_start(args, format); csound->MessageV(csound, CSOUNDMSG_WARNING, format, args); va_end(args); } } else { va_list args; va_start(args, format); vfprintf(stderr, format, args); va_end(args); } } /** * Copy all event parameters to a structure that will be used as a key to * a dictionary for pre-allocated function tables. If the key is in the * dictionary, the function table number is returned; if the key is not in * the dictionary, the function table is created, its number is stored in * the dictionary, and the number is returned. */ static int ftgenonce_(CSOUND *csound, FTGEN *p, bool isNamedGenerator, bool hasStringParameter) { SignalFlowGraphState *sfg_globals; csound::QueryGlobalPointer(csound, "sfg_globals", sfg_globals); LockGuard guard(csound, sfg_globals->signal_flow_ftables_lock); int result = OK; EventBlock eventBlock; EVTBLK *ftevt = &eventBlock.evtblk; *p->ifno = FL(0.0); std::memset(ftevt, 0, sizeof(EVTBLK)); // ifno ftgenonce ipfno, ip2dummy, ip4size, ip5gen, ip6arga, ip7argb,... ftevt->opcod = 'f'; ftevt->strarg = 0; MYFLT *fp = &ftevt->p[0]; ftevt->p[0] = FL(0.0); ftevt->p[1] = *p->p1; ftevt->p[2] = ftevt->p2orig = FL(0.0); ftevt->p[3] = ftevt->p3orig = *p->p3; if (isNamedGenerator) { NAMEDGEN *named = (NAMEDGEN *) csound->GetNamedGens(csound); while (named) { if (strcmp(named->name, ((STRINGDAT *) p->p4)->data) == 0) { /* Look up by name */ break; } named = named->next; /* and round again */ } if (UNLIKELY(named == 0)) { if (sfg_globals->signal_flow_ftables_lock != 0) { csound->UnlockMutex(sfg_globals->signal_flow_ftables_lock); } return csound->InitError(csound, Str("Named gen \"%s\" not defined"), (char *)p->p4); } else { ftevt->p[4] = named->genum; } } else { ftevt->p[4] = *p->p4; } if (hasStringParameter) { int n = (int) fp[4]; ftevt->p[5] = SSTRCOD; if (n < 0) { n = -n; } switch (n) { /* must be Gen01, 23, 28, or 43 */ case 1: case 23: case 28: case 43: ftevt->strarg = ((STRINGDAT *) p->p5)->data; break; default: if (sfg_globals->signal_flow_ftables_lock != 0) { csound->UnlockMutex(sfg_globals->signal_flow_ftables_lock); } return csound->InitError(csound, Str("ftgen string arg not allowed")); } } else { ftevt->p[5] = *p->p5; } // Copy the remaining parameters. ftevt->pcnt = (int16) csound->GetInputArgCnt(p); int n = ftevt->pcnt - 5; if (n > 0) { MYFLT **argp = p->argums; MYFLT *fp = &ftevt->p[0] + 6; do { *fp++ = **argp++; } while (--n); } if (sfg_globals->functionTablesForEvtblks.find(eventBlock) != sfg_globals->functionTablesForEvtblks.end()) { *p->ifno = sfg_globals->functionTablesForEvtblks[eventBlock]; warn(csound, Str("ftgenonce: re-using existing func: %f\n"), *p->ifno); } else { if (sfg_globals->functionTablesForEvtblks.find(eventBlock) != sfg_globals->functionTablesForEvtblks.end()) { *p->ifno = sfg_globals->functionTablesForEvtblks[eventBlock]; warn(csound, Str("ftgenonce: re-using existing func: %f\n"), *p->ifno); } else { FUNC *func = 0; int status = csound->hfgens(csound, &func, ftevt, 1); if (UNLIKELY(status != 0)) { result = csound->InitError(csound, Str("ftgenonce error")); } if (func) { sfg_globals->functionTablesForEvtblks[eventBlock] = func->fno; *p->ifno = (MYFLT) func->fno; warn(csound, Str("ftgenonce: created new func: %d\n"), func->fno); if (sfg_globals->functionTablesForEvtblks.find(eventBlock) == sfg_globals->functionTablesForEvtblks.end()) { #if (SIGNALFLOWGRAPH_DEBUG == 1) std::fprintf(stderr, "Oops! inserted but not found.\n"); #endif } } else { #if (SIGNALFLOWGRAPH_DEBUG == 1) std::fprintf(stderr, "Oops! New but not created.\n"); #endif } } } return result; } static int ftgenonce(CSOUND *csound, FTGEN *p) { return ftgenonce_(csound, p, false, false); } static int ftgenonce_S(CSOUND *csound, FTGEN *p) { return ftgenonce_(csound, p, true, false); } static int ftgenonce_iS(CSOUND *csound, FTGEN *p) { return ftgenonce_(csound, p, false, true); } static int ftgenonce_SS(CSOUND *csound, FTGEN *p) { return ftgenonce_(csound, p, true, true); } extern "C" { static OENTRY oentries[] = { { (char *)"signalflowgraph", sizeof(SignalFlowGraph), 0, 1, (char *)"", (char *)"", (SUBR) &SignalFlowGraph::init_, 0, 0, }, { (char *)"outleta", sizeof(Outleta), _CW, 5, (char *)"", (char *)"Sa", (SUBR) &Outleta::init_, 0, (SUBR) &Outleta::audio_ }, { (char *)"inleta", sizeof(Inleta), _CR, 5, (char *)"a", (char *)"S", (SUBR) &Inleta::init_, 0, (SUBR) &Inleta::audio_ }, { (char *)"outletk", sizeof(Outletk), _CW, 3, (char *)"", (char *)"Sk", (SUBR) &Outletk::init_, (SUBR) &Outletk::kontrol_, 0 }, { (char *)"inletk", sizeof(Inletk), _CR, 3, (char *)"k", (char *)"S", (SUBR) &Inletk::init_, (SUBR) &Inletk::kontrol_, 0 }, { (char *)"outletkid", sizeof(Outletkid), _CW, 3, (char *)"", (char *)"SSk", (SUBR) &Outletk::init_, (SUBR) &Outletk::kontrol_, 0 }, { (char *)"inletkid", sizeof(Inletkid), _CR, 3, (char *)"k", (char *)"SS", (SUBR) &Inletk::init_, (SUBR) &Inletk::kontrol_, 0 }, { (char *)"outletf", sizeof(Outletf), _CW, 5, (char *)"", (char *)"Sf", (SUBR) &Outletf::init_, 0, (SUBR) &Outletf::audio_ }, { (char *)"inletf", sizeof(Inletf), _CR, 5, (char *)"f", (char *)"S", (SUBR) &Inletf::init_, 0, (SUBR) &Inletf::audio_ }, { (char *)"outletv", sizeof(Outletv), _CW, 5, (char *)"", (char *)"Sa[]", (SUBR) &Outletv::init_, 0, (SUBR) &Outletv::audio_ }, { (char *)"inletv", sizeof(Inletv), _CR, 5, (char *)"a[]", (char *)"S", (SUBR) &Inletv::init_, 0, (SUBR) &Inletv::audio_ }, { (char *)"connect", sizeof(Connect), 0, 1, (char *)"", (char *)"iSiSp", (SUBR) &Connect::init_, 0, 0 }, { (char *)"connect.i", sizeof(Connecti), 0, 1, (char *)"", (char *)"iSSSp", (SUBR) &Connecti::init_, 0, 0 }, { (char *)"connect.ii", sizeof(Connectii), 0, 1, (char *)"", (char *)"SSiSp", (SUBR) &Connectii::init_, 0, 0 }, { (char *)"connect.S", sizeof(ConnectS), 0, 1, (char *)"", (char *)"SSSSp", (SUBR) &ConnectS::init_, 0, 0 }, { (char *)"alwayson", sizeof(AlwaysOn), 0, 1, (char *)"", (char *)"im", (SUBR) &AlwaysOn::init_, 0, 0 }, { (char *)"alwayson.S", sizeof(AlwaysOnS), 0, 1, (char *)"", (char *)"Sm", (SUBR) &AlwaysOnS::init_, 0, 0 }, { (char *)"ftgenonce", sizeof(FTGEN), TW, 1, (char *)"i", (char *)"iiiiim", (SUBR) &ftgenonce, 0, 0 }, { (char *)"ftgenonce.S", sizeof(FTGEN), TW, 1, (char *)"i", (char *)"iiiSim", (SUBR) &ftgenonce_S, 0, 0 }, { (char *)"ftgenonce.iS", sizeof(FTGEN), TW, 1, (char *)"i", (char *)"iiiiSm", (SUBR) &ftgenonce_iS, 0, 0 }, { (char *)"ftgenonce.SS", sizeof(FTGEN), TW, 1, (char *)"i", (char *)"iiiSSm", (SUBR) &ftgenonce_SS, 0, 0 }, { 0, 0, 0, 0, 0, 0, (SUBR) 0, (SUBR) 0, (SUBR) 0 } }; PUBLIC int csoundModuleCreate_signalflowgraph(CSOUND *csound) { if (csound->GetDebug(csound)) { csound->Message(csound, "signalflowgraph: csoundModuleCreate(%p)\n", csound); } SignalFlowGraphState *sfg_globals = new SignalFlowGraphState(csound); csound::CreateGlobalPointer(csound, "sfg_globals", sfg_globals); return 0; } PUBLIC int csoundModuleInit_signalflowgraph(CSOUND *csound) { if (csound->GetDebug(csound)) { csound->Message(csound, "signalflowgraph: csoundModuleInit(%p)\n", csound); } OENTRY *ep = (OENTRY *)&(oentries[0]); int err = 0; while (ep->opname != 0) { err |= csound->AppendOpcode(csound, ep->opname, ep->dsblksiz, ep->flags, ep->thread, ep->outypes, ep->intypes, (int (*)(CSOUND *, void *)) ep->iopadr, (int (*)(CSOUND *, void *)) ep->kopadr, (int (*)(CSOUND *, void *)) ep->aopadr); ep++; } return err; } #ifndef INIT_STATIC_MODULES PUBLIC int csoundModuleCreate(CSOUND *csound) { return csoundModuleCreate_signalflowgraph(csound); } PUBLIC int csoundModuleInit(CSOUND *csound) { return csoundModuleInit_signalflowgraph(csound); } PUBLIC int csoundModuleDestroy(CSOUND *csound) { if (csound->GetDebug(csound)) { csound->Message(csound, "signalflowgraph: csoundModuleDestroy(%p)\n", csound); } SignalFlowGraphState *sfg_globals = 0; csound::QueryGlobalPointer(csound, "sfg_globals", sfg_globals); if (sfg_globals != 0) { sfg_globals->clear(); if (sfg_globals->signal_flow_ports_lock != 0) { csound->UnlockMutex(sfg_globals->signal_flow_ports_lock); csound->DestroyMutex(sfg_globals->signal_flow_ports_lock); } if (sfg_globals->signal_flow_ftables_lock != 0) { csound->LockMutex(sfg_globals->signal_flow_ftables_lock); sfg_globals->functionTablesForEvtblks.clear(); csound->UnlockMutex(sfg_globals->signal_flow_ftables_lock); csound->DestroyMutex(sfg_globals->signal_flow_ftables_lock); } csound::DestroyGlobalPointer(csound, "sfg_globals", sfg_globals); } return 0; } #endif } } csound-6.10.0/Opcodes/signalflowgraphtest.csd000066400000000000000000000065131321653344700212640ustar00rootroot00000000000000 ; Select audio/midi flags here according to platform ; Audio out Audio in No messages -odac ; For Non-realtime ouput leave only the line below: ; -o madsr.wav -W ;;; for file output any platform /* Written by Michael Gogins */ ; Initialize the global variables. sr = 48000 ksmps = 100 nchnls = 2 ; Connect up the instruments to create a signal flow graph. connect "SimpleSine", "leftout", "Reverberator", "leftin" connect "SimpleSine", "rightout", "Reverberator", "rightin" connect "Moogy", "leftout", "Reverberator", "leftin" connect "Moogy", "rightout", "Reverberator", "rightin" connect "Reverberator", "leftout", "Compressor", "leftin" connect "Reverberator", "rightout", "Compressor", "rightin" connect "Compressor", "out", "Soundfile", "in" ; Turn on the "effect" units in the signal flow graph. alwayson "Reverberator", 0.91, 12000 alwayson "Compressor" alwayson "Soundfile" instr SimpleSine ihz = cpsmidinn(p4) iamplitude = ampdb(p5) print ihz, iamplitude ; Use ftgenonce instead of ftgen, ftgentmp, or f statement. isine ftgenonce 0, 0, 4096, 10, 1 a1 oscili iamplitude, ihz, isine aenv madsr 0.05, 0.1, 0.5, 0.2 asignal = a1 * aenv ; Stereo audio outlet to be routed in the orchestra header. outleta "leftout", asignal * 0.25 outleta "rightout", asignal * 0.75 endin instr Moogy ihz = cpsmidinn(p4) iamplitude = ampdb(p5) ; Use ftgenonce instead of ftgen, ftgentmp, or f statement. isine ftgenonce 0, 0, 4096, 10, 1 asignal vco iamplitude, ihz, 1, 0.5, isine kfco line 200, p3, 2000 krez init 0.9 asignal moogvcf asignal, kfco, krez, 100000 ; Stereo audio outlet to be routed in the orchestra header. outleta "leftout", asignal * 0.75 outleta "rightout", asignal * 0.25 endin instr Reverberator ; Stereo input. aleftin inleta "leftin" arightin inleta "rightin" idelay = p4 icutoff = p5 aleftout, arightout reverbsc aleftin, arightin, idelay, icutoff ; Stereo output. outleta "leftout", aleftout outleta "rightout", arightout endin instr Compressor ; Stereo input. aleftin inleta "leftin" arightin inleta "rightin" kthreshold = 25000 icomp1 = 0.5 icomp2 = 0.763 irtime = 0.1 iftime = 0.1 prints "init Compressor" asignal[] init 2 aleftout dam aleftin, kthreshold, icomp1, icomp2, irtime, iftime arightout dam arightin, kthreshold, icomp1, icomp2, irtime, iftime ; Stereo output. asignal[0] = aleftout asignal[1] = arightout outletv "out", asignal endin instr Soundfile ; Stereo input. asignal[] init 2 asignal inletv "in" out asignal endin ; Not necessary to activate "effects" or create f-tables in the score! ; Overlapping notes to create new instances of instruments. i "SimpleSine" 1 5 60 85 i "SimpleSine" 2 5 64 80 i "Moogy" 3 5 67 75 i "Moogy" 4 5 71 70 e 1 100 100 320 240 true 255 255 255 csound-6.10.0/Opcodes/singwave.c000066400000000000000000000362671321653344700165020ustar00rootroot00000000000000/* singwave.c: Copyright (C) 1996, 1997 Perry Cook, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /*******************************************/ /* "Singing" Looped Soundfile Class, */ /* by Perry R. Cook, 1995-96 */ /* This Object contains all that's needed */ /* to make a pitched musical sound, like */ /* a simple voice or violin. In general, */ /* it will not be used alone (because of */ /* of munchinification effects from pitch */ /* shifting. It will be used as an */ /* excitation source for other instruments*/ /*******************************************/ // #include "csdl.h" #include "csoundCore.h" #include "singwave.h" #include "moog1.h" void OneZero_setCoeff(OneZero*, MYFLT); MYFLT Wave_tick(MYFLT *, int len, MYFLT *, MYFLT, MYFLT); static void SingWave_setFreq(CSOUND *csound, SingWave *p, MYFLT aFreq); static MYFLT SingWave_tick(CSOUND *csound, SingWave *p); static void VoicForm_setVoicedUnVoiced(VOICF *p, MYFLT vGain, MYFLT nGain); static inline void make_SubNoise(SubNoise *p, int subSample) { p->lastOutput = FL(0.0); p->howOften = p->counter = subSample-1; } static MYFLT SubNoise_tick(CSOUND *csound, SubNoise *p) { MYFLT last; if (p->counter==0) { last = p->lastOutput = Noise_tick(csound, &p->lastOutput); p->counter = p->howOften; } else { (p->counter)--; last = p->lastOutput; } return last; } /*******************************************/ /* Modulator Class, Perry R. Cook, 1995-96*/ /* This Object combines random and */ /* periodic modulations to give a nice */ /* natural human modulation function. */ /*******************************************/ #define POLE_POS (FL(0.999)) #define RND_SCALE (FL(10.0)) static int make_Modulatr(CSOUND *csound,Modulatr *p, MYFLT *i) { FUNC *ftp; if (LIKELY((ftp = csound->FTnp2Find(csound,i)) != NULL)) p->wave = ftp; else { /* Expect sine wave */ return csound->InitError(csound, Str("No table for Modulatr")); } p->v_time = FL(0.0); /* p->v_rate = 6.0; */ /* p->vibAmt = 0.04; */ make_SubNoise(&p->noise, 330);/* Surely this should be scaled to esr?? */ /* p->rndAmt = 0.005; */ make_OnePole(&p->onepole); OnePole_setPole(&p->onepole, POLE_POS); OnePole_setGain(&p->onepole, RND_SCALE * FL(0.005) /* p->rndAmt */); return 0; } #define Modulatr_setVibFreq(p,vibFreq) \ (p.v_rate = vibFreq * (MYFLT)p.wave->flen*csound->onedsr) #define Modulatr_setVibAmt(p,vibAmount) (p.vibAmt = vibAmount) static MYFLT Modulatr_tick(CSOUND *csound, Modulatr *p) { MYFLT lastOutput; lastOutput = Wave_tick(&p->v_time, p->wave->flen, p->wave->ftable, p->v_rate, FL(0.0)); lastOutput *= p->vibAmt; /* Compute periodic and */ /* random modulations */ lastOutput += OnePole_tick(&p->onepole, SubNoise_tick(csound, &p->noise)); return lastOutput; } #if 0 static void Modulatr_print(CSOUND *csound, Modulatr *p) { csound->Message(csound, "Modulatr: v_rate=%f v_time=%f vibAmt=%f\n", p->v_rate, p->v_time, p->vibAmt); } #endif static int make_SingWave(CSOUND *csound, SingWave *p, MYFLT *ifn, MYFLT *ivfn) { FUNC *ftp; if (LIKELY((ftp = csound->FTnp2Find(csound,ifn)) != NULL)) p->wave = ftp; else { return csound->InitError(csound, Str("No table for Singwave")); } p->mytime = FL(0.0); p->rate = FL(1.0); p->sweepRate = FL(0.001); if (UNLIKELY(make_Modulatr(csound, &p->modulator, ivfn))) return NOTOK; Modulatr_setVibFreq(p->modulator, FL(6.0)); Modulatr_setVibAmt(p->modulator, FL(0.04)); make_Envelope(&p->envelope); // printf("Singwave envelope=%p\n", &p->envelope); /* Envelope_setTarget(&p->envelope, FL(1.0)); */ /* Envelope_setRate(csound, &p->envelope, FL(0.1)); */ make_Envelope(&p->pitchEnvelope); // printf("Singwave pitchenvelope=%p\n", &p->pitchEnvelope); SingWave_setFreq(csound, p, FL(75.0)); Envelope_setRate(csound, &p->pitchEnvelope, FL(1.0)); /* SingWave_print(csound, p); */ SingWave_tick(csound, p); SingWave_tick(csound, p); Envelope_setRate(csound, &p->pitchEnvelope, p->sweepRate * p->rate); /* Envelope_print(&p->pitchEnvelope); */ return OK; } static void SingWave_setFreq(CSOUND *csound, SingWave *p, MYFLT aFreq) { MYFLT temp = p->rate; p->rate = (MYFLT)p->wave->flen * aFreq * csound->onedsr; temp -= p->rate; temp = FABS(temp); Envelope_setTarget(&p->pitchEnvelope, p->rate); Envelope_setRate(csound, &p->pitchEnvelope, p->sweepRate * temp); // Envelope_print(csound, &p->pitchEnvelope); } #define SingWave_setVibFreq(p, vibFreq) \ Modulatr_setVibFreq(p.modulator, vibFreq) #define SingWave_setVibAmt(p, vibAmount) \ Modulatr_setVibAmt(p.modulator, vibAmount) static MYFLT SingWave_tick(CSOUND *csound, SingWave *p) { MYFLT lastOutput; int32 temp, temp1; MYFLT alpha, temp_rate; MYFLT mytime = p->mytime; temp_rate = Envelope_tick(&p->pitchEnvelope); // printf("SingWave_tick: %f\n", temp_rate); mytime += temp_rate; /* Update current time */ mytime += temp_rate*Modulatr_tick(csound,&p->modulator); /* Add vibratos */ //printf(" : %f %d\n", mytime, p->wave->flen); while (mytime >= (MYFLT)p->wave->flen) { /* Check for end of sound */ mytime -= p->wave->flen; /* loop back to beginning */ } while (mytime < FL(0.0)) { /* Check for end of sound */ mytime += p->wave->flen; /* loop back to beginning */ } temp = (int32) mytime; /* Integer part of time address */ alpha = mytime - (MYFLT) temp; /* fractional part of time address */ temp1 = temp + 1; if (temp1==(int)p->wave->flen) temp1 = temp; /* Wrap!! */ lastOutput = alpha * p->wave->ftable[temp1]; /* Do linear */ // printf(" : (%d %d) %f %f ", temp, temp1, alpha, lastOutput); lastOutput += (FL(1.0)-alpha) * p->wave->ftable[temp]; /* interpolation */ // printf("%f ", lastOutput); lastOutput *= Envelope_tick(&p->envelope); // printf("%f\n", lastOutput); p->mytime = mytime; return lastOutput; } #if 0 static void SingWave_print(CSOUND *csound, SingWave *p) { csound->Message(csound, Str("SingWave: rate=%f sweepRate=%f mytime=%f\n"), p->rate, p->sweepRate, p->mytime); Modulatr_print(csound, &p->modulator); // Envelope_print(csound, &p->envelope); // Envelope_print(csound, &p->pitchEnvelope); } #endif /*******************************************/ /* 4 Formant Synthesis Instrument */ /* by Perry R. Cook, 1995-96 */ /* This instrument contains an excitation */ /* singing wavetable (looping wave with */ /* random and periodic vibrato, smoothing */ /* on frequency, etc.), excitation noise, */ /* and four sweepable complex resonances. */ /* */ /* Measured Formant data (from me) is */ /* included, and enough data is there to */ /* support either parallel or cascade */ /* synthesis. In the floating point case */ /* cascade synthesis is the most natural */ /* so that's what you'll find here. */ /* */ /* For right now, there's a simple command*/ /* line score interface consisting of 3 */ /* letter symbols for the phonemes, =xx */ /* sets the pitch to x, + and - add and */ /* subtract a half step, and ... makes it */ /* keep doing what it's doing for longer. */ /*******************************************/ char phonemes[32][4] = {"eee","ihh","ehh","aaa", "ahh","aww","ohh","uhh", "uuu","ooo","rrr","lll", "mmm","nnn","nng","ngg", "fff","sss","thh","shh", "xxx","hee","hoo","hah", "bbb","ddd","jjj","ggg", "vvv","zzz","thz","zhh"}; /* #define VoicForm_setFreq(p, frequency) \ */ /* SingWave_setFreq(csound, (p).voiced, frequency) */ /* #define VoicForm_setPitchSweepRate(p, rate) \ */ /* SingWave_setSweepRate((p).voiced, rate) */ /* #define VoicForm_speak(p) SingWave_noteOn(p->voiced) */ #define VoicForm_setFormantAll(p,w,f,r,g) \ FormSwep_setTargets(& p->filters[w],f,r,g) static void VoicForm_setPhoneme(CSOUND *csound, VOICF *p, int i, MYFLT sc) { if (i>16) i = i%16; VoicForm_setFormantAll(p, 0,sc*phonParams[i][0][0], phonParams[i][0][1], (MYFLT)pow(10.0,phonParams[i][0][2] / FL(20.0))); VoicForm_setFormantAll(p, 1,sc*phonParams[i][0][0], phonParams[i][1][1], (MYFLT)pow(10.0,phonParams[i][1][2] / FL(20.0))); VoicForm_setFormantAll(p, 2,sc*phonParams[i][0][0], phonParams[i][2][1], (MYFLT)pow(10.0,phonParams[i][2][2] / FL(20.0))); VoicForm_setFormantAll(p, 3,sc*phonParams[i][0][0], phonParams[i][3][1], (MYFLT)pow(10.0,phonParams[i][3][2] / FL(20.0))); /* VoicForm_setFormantAll(p, 1,sc*phonParams[i][1][0], */ /* phonParams[i][1][1], FL(1.0)); */ /* VoicForm_setFormantAll(p, 2,sc*phonParams[i][2][0], */ /* phonParams[i][2][1], FL(1.0)); */ /* VoicForm_setFormantAll(p, 3,sc*phonParams[i][3][0], */ /* phonParams[i][3][1], FL(1.0)); */ VoicForm_setVoicedUnVoiced(p,phonGains[i][0], phonGains[i][1]); csound->Message(csound, Str("Found Formant: %s (number %i)\n"), phonemes[i], i); } static void VoicForm_setVoicedUnVoiced(VOICF *p, MYFLT vGain, MYFLT nGain) { Envelope_setTarget(&(p->voiced.envelope), vGain); Envelope_setTarget(&p->noiseEnv, nGain); } #if 0 static void VoicForm_quiet(VOICF *p) { Envelope_keyOff(&(p->voiced.envelope)); Envelope_setTarget(&p->noiseEnv, FL(0.0)); } static void VoicForm_noteOff(VOICF *p) { Envelope_keyOff(&p->voiced.envelope); } static void voicprint(CSOUND *csound, VOICF *p) { SingWave_print(csound, &p->voiced); OneZero_print(csound, &p->onezero); OnePole_print(csound, &p->onepole); } #endif static void make_FormSwep(FormSwep *p) { p->poleCoeffs[0] = p->poleCoeffs[1] = FL(0.0); p->gain = FL(1.0); p->freq = p->reson = FL(0.0); p->currentGain = FL(1.0); p->currentFreq = p->currentReson = FL(0.0); p->targetGain = FL(1.0); p->targetFreq = p->targetReson = FL(0.0); p->deltaGain = FL(0.0); p->deltaFreq = p->deltaReson = FL(0.0); p->sweepState = FL(0.0); p->sweepRate = FL(0.002); p->dirty = 0; p->outputs[0] = p->outputs[1] = FL(0.0); } int voicformset(CSOUND *csound, VOICF *p) { MYFLT amp = (*p->amp)*AMP_RSCALE; /* Normalise */ int i; if (UNLIKELY(make_SingWave(csound, &p->voiced, p->ifn, p->ivfn)==NOTOK)) return NOTOK; Envelope_setRate(csound, &(p->voiced.envelope), FL(0.001)); Envelope_setTarget(&(p->voiced.envelope), FL(0.0)); make_Noise(p->noise); for (i=0; i<4; i++) { make_FormSwep(&p->filters[i]); FormSwep_setSweepRate(p->filters[i], FL(0.001)); } make_OneZero(&p->onezero); OneZero_setCoeff(&p->onezero, - FL(0.9)); make_OnePole(&p->onepole); OnePole_setPole(&p->onepole, FL(0.9)); make_Envelope(&p->noiseEnv); Envelope_setRate(csound, &p->noiseEnv, FL(0.001)); Envelope_setTarget(&p->noiseEnv, FL(0.0)); p->oldform = *p->formant; p->ph = (int)(FL(0.5)+ *p->phoneme); VoicForm_setPhoneme(csound, p, p->ph, p->oldform); /* Clear */ /* OnePole_clear(&p->onepole); */ /* Included in make */ FormSwep_clear(p->filters[0]); FormSwep_clear(p->filters[1]); FormSwep_clear(p->filters[2]); FormSwep_clear(p->filters[3]); { MYFLT temp, freq = *p->frequency; if ((freq * FL(22.0)) > CS_ESR) { csound->Warning(csound, Str("This note is too high!!\n")); freq = CS_ESR / FL(22.0); } p->basef = freq; temp = FABS(FL(1500.0) - freq) + FL(200.0); p->lastGain = FL(10000.0) / temp / temp; SingWave_setFreq(csound, &p->voiced, freq); } Envelope_setTarget(&(p->voiced.envelope), amp); OnePole_setPole(&p->onepole, FL(0.95) - (amp * FL(0.2))/FL(128.0)); /* voicprint(csound, p); */ return OK; } int voicform(CSOUND *csound, VOICF *p) { MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (p->basef != *p->frequency) { p->basef = *p->frequency; SingWave_setFreq(csound, &p->voiced, p->basef); } /* OnePole_setPole(&p->onepole, 0.95 - (amp * 0.1)); */ /* Envelope_setTarget(&(p->voiced.envelope), amp); */ /* Envelope_setTarget(&p->noiseEnv, 0.95 - (amp * 0.1)); */ SingWave_setVibFreq(p->voiced, *p->vibf); Modulatr_setVibAmt(p->voiced.modulator, *p->vibAmt); /* Set phoneme */ if (p->oldform != *p->formant || p->ph != (int)(0.5+*p->phoneme)) { p->oldform = *p->formant; p->ph = (int)(0.5 + *p->phoneme); csound->Warning(csound, Str("Setting Phoneme: %d %f\n"), p->ph, p->oldform); VoicForm_setPhoneme(csound, p, (int) *p->phoneme, p->oldform); } /* voicprint(csound, p); */ if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nonepole, OneZero_tick(&p->onezero, SingWave_tick(csound, &p->voiced))); // printf("%d: temp=%f ", n, temp); temp += Envelope_tick(&p->noiseEnv) * Noise_tick(csound, &p->noise); // printf("%f\n", temp); lastOutput = FormSwep_tick(csound, &p->filters[0], temp); // printf("%d: output=%f ", lastOutput); lastOutput = FormSwep_tick(csound, &p->filters[1], lastOutput); // printf("%f ", lastOutput); lastOutput = FormSwep_tick(csound, &p->filters[2], lastOutput); // printf("%f ", lastOutput); lastOutput = FormSwep_tick(csound, &p->filters[3], lastOutput); // printf("%f ", lastOutput); lastOutput *= p->lastGain; // printf("%f ", lastOutput); // printf("->%f\n", lastOutput* AMP_SCALE); ar[n] = lastOutput * FL(0.22) * AMP_SCALE * *p->amp; } return OK; } csound-6.10.0/Opcodes/singwave.h000066400000000000000000000076351321653344700165040ustar00rootroot00000000000000/* singwave.h: Copyright (C) 1996, 1997 Perry Cook, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /*******************************************/ /* "Singing" Looped Soundfile Class, */ /* by Perry R. Cook, 1995-96 */ /* This Object contains all that's needed */ /* to make a pitched musical sound, like */ /* a simple voice or violin. In general, */ /* it will not be used alone (because of */ /* of munchinification effects from pitch */ /* shifting. It will be used as an */ /* excitation source for other instruments*/ /*******************************************/ #if !defined(__SingWave_h) #define __SingWave_h extern MYFLT phonGains[32][2]; extern MYFLT phonParams[32][4][3]; extern char phonemes[32][4]; /*******************************************/ /* Modulator Class, Perry R. Cook, 1995-96*/ /* This Object combines random and */ /* periodic modulations to give a nice */ /* natural human modulation function. */ /*******************************************/ #include "physutil.h" #include "clarinet.h" #include "moog1.h" typedef struct SubNoise { Noise lastOutput; int counter; int howOften; } SubNoise; typedef struct Modulatr { FUNC *wave; MYFLT v_rate; MYFLT v_time; MYFLT v_phase; MYFLT v_lastOutput; SubNoise noise; OnePole onepole; MYFLT vibAmt; MYFLT lastOutput; } Modulatr; typedef struct SingWave { Modulatr modulator; Envelope envelope; Envelope pitchEnvelope; FUNC *wave; MYFLT rate; MYFLT sweepRate; MYFLT mytime; MYFLT lastOutput; } SingWave; /*******************************************/ /* 4 Formant Synthesis Instrument */ /* by Perry R. Cook, 1995-96 */ /* This instrument contains an excitation */ /* singing wavetable (looping wave with */ /* random and periodic vibrato, smoothing */ /* on frequency, etc.), excitation noise, */ /* and four sweepable complex resonances. */ /* */ /* Measured Formant data (from me) is */ /* included, and enough data is there to */ /* support either parallel or cascade */ /* synthesis. In the floating point case */ /* cascade synthesis is the most natural */ /* so that's what you'll find here. */ /* */ /* For right now, there's a simple command*/ /* line score interface consisting of 3 */ /* letter symbols for the phonemes, =xx */ /* sets the pitch to x, + and - add and */ /* subtract a half step, and ... makes it */ /* keep doing what it's doing for longer. */ /*******************************************/ typedef struct VOICF { OPDS h; MYFLT *ar; /* Output */ MYFLT *amp, *frequency; MYFLT *phoneme, *formant; MYFLT *vibf, *vibAmt; MYFLT *ifn, *ivfn; MYFLT oldform; int ph; MYFLT basef; MYFLT lastGain; SingWave voiced; Noise noise; Envelope noiseEnv; FormSwep filters[4]; OnePole onepole; OneZero onezero; } VOICF; #endif csound-6.10.0/Opcodes/sndloop.c000066400000000000000000001266131321653344700163300ustar00rootroot00000000000000/* sndloop.c sndloop flooper pvsarp pvsvoc (c) Victor Lazzarini, 2004 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA SNDLOOP asig, krec sndloop ain, kpitch, ktrig, idur, ifad A sound looper with pitch control. INIT idur - loop duration in seconds ifad - crossfade duration in seconds PERFORMANCE asig - output signal krec - 'rec on' signal, 1 when recording, 0 otherwise kpitch - pitch control (transposition ratio) kon - on signal: when 0, processing is bypassed. When switched on (kon >= 1), the opcode starts recording until the loop memory is full. It then plays the looped sound until it is switched off again (kon = 0). Another recording can start again with kon >= 1. FLOOPER asig flooper kamp, kpitch, istart, idur, ifad, ifn Function-table crossfading looper. INIT istart - starting point of loop (in secs) idur - loop duration (secs) ifad - crossfade duration (secs) PERFORMANCE asig - output signal kamp - amplitude scaling kpitch - pitch control (transposition ratio) FLOOPER2 asig flooper2 kamp, kpitch, kloopstart, kloopend, kcrossfade, ifn [, istart, imode, ifenv] Function-table crossfading looper with variable loop parameters and different looping modes. INIT ifn - sound source function table. Non-power-of-two and deferred allocation tables are allowed. istart - playback starting point in secs, only applicable to loop modes 0 & 2 [def:0] imode - loop modes: 0 forward, 1 backward, 2 back-and-forth [def: 0] ifenv - if non-zero, crossfade envelope shape table number. 0, the default, sets the crossfade to linear. PERFORMANCE kamp - amplitude scaling kpitch - playback pitch ratio (1 - normal, > 1 faster, < 1 slower). Negative ratios are not allowed. kloopstart - loop start point (secs). Note that although k-rate, loop parameters such as this are only updated once per loop cycle. kloopend - loop end point (secs), updated once per loop cycle. kcrossfade - crossfade length (secs), updated once per loop cycle and limited to loop length. PVSARP fsig pvsarp fin, kcf, kdepth, kgain Spectral arpeggiator PERFORMANCE fin - input pv streaming signal kcf - centre freq of arpeggiation (normalised 0 - 1.0, corresponding to 0 - Nyquist) kdepth - depth of attenuation of surrounding frequency bins kgain - gain applied to the bin at the centre frequency PVSVOC fsig pvsvoc fenv,fexc,kdepth, kgain Applies the spectral envelope of one sound to the frequencies (excitation) of another. PERFORMANCE fenv - spectral envelope signal fexc - excitation signal kdepth - depth of effect (0-1) kgain - signal gain */ #include "stdopcod.h" #include "pstream.h" typedef struct _sndloop { OPDS h; MYFLT *out, *recon; /* output,record on */ MYFLT *sig, *pitch, *on; /* in, pitch, sound on */ MYFLT *dur, *cfd; /* duration, crossfade */ AUXCH buffer; /* loop memory */ int32 wp; /* writer pointer */ double rp; /* read pointer */ int32 cfds; /* crossfade in samples */ int32 durs; /* duration in samples */ int rst; /* reset indicator */ MYFLT inc; /* fade in/out increment/decrement */ MYFLT a; /* fade amp */ } sndloop; typedef struct _flooper { OPDS h; MYFLT *out[2]; /* output */ MYFLT *amp, *pitch, *start, *dur, *cfd, *ifn; AUXCH buffer; /* loop memory */ FUNC *sfunc; /* function table */ int32 strts; /* start in samples */ int32 durs; /* duration in samples */ double ndx; /* table lookup ndx */ int nchnls; int loop_off; } flooper; typedef struct _flooper2 { OPDS h; MYFLT *out[2]; /* output */ MYFLT *amp, *pitch, *loop_start, *loop_end, *crossfade, *ifn, *start, *imode, *ifn2, *iskip, *ijump; FUNC *sfunc; /* function table */ FUNC *efunc; MYFLT count; int lstart, lend,cfade, mode; double ndx[2]; /* table lookup ndx */ int firsttime, init; MYFLT ostart, oend; int nchnls; } flooper2; typedef struct _flooper3 { OPDS h; MYFLT *out; /* output */ MYFLT *amp, *pitch, *loop_start, *loop_end, *crossfade, *ifn, *start, *imode, *ifn2, *iskip; FUNC *sfunc; /* function table */ FUNC *efunc; int32 count; int lstart, lend,cfade, mode; int32 ndx[2]; /* table lookup ndx */ int firsttime, init; int lobits,lomask; MYFLT lodiv; } flooper3; typedef struct _pvsarp { OPDS h; PVSDAT *fout; PVSDAT *fin; MYFLT *cf; MYFLT *kdepth; MYFLT *gain; uint32 lastframe; } pvsarp; typedef struct _pvsvoc { OPDS h; PVSDAT *fout; PVSDAT *fin; PVSDAT *ffr; MYFLT *kdepth; MYFLT *gain; MYFLT *kcoefs; AUXCH fenv, ceps, fexc; uint32 lastframe; } pvsvoc; typedef struct _pvsmorph { OPDS h; PVSDAT *fout; PVSDAT *fin; PVSDAT *ffr; MYFLT *kdepth; MYFLT *gain; uint32 lastframe; } pvsmorph; static int sndloop_init(CSOUND *csound, sndloop *p) { p->durs = (int32) (*(p->dur)*CS_ESR); /* dur in samps */ p->cfds = (int32) (*(p->cfd)*CS_ESR); /* fade in samps */ if (UNLIKELY(p->durs < p->cfds)) return csound->InitError(csound, Str("crossfade cannot be longer than loop\n")); p->inc = FL(1.0)/p->cfds; /* inc/dec */ p->a = FL(0.0); p->wp = 0; /* intialise write pointer */ p->rst = 1; /* reset the rec control */ if (p->buffer.auxp==NULL || p->buffer.sizedurs*sizeof(MYFLT)) /* allocate memory if necessary */ csound->AuxAlloc(csound, p->durs*sizeof(MYFLT), &p->buffer); return OK; } static int sndloop_process(CSOUND *csound, sndloop *p) { int on = (int) *(p->on), recon; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; int32 durs = p->durs, cfds = p->cfds, wp = p->wp; double rp = p->rp; MYFLT a = p->a, inc = p->inc; MYFLT *out = p->out, *sig = p->sig, *buffer = p->buffer.auxp; MYFLT pitch = *(p->pitch); if (on) recon = p->rst; /* restart recording if switched on again */ else recon = 0; /* else do not record */ if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset; i < nsmps; i++) { if (recon) { /* if the recording is ON */ /* fade in portion */ if (wp < cfds) { buffer[wp] = sig[i]*a; a += inc; } else { if (wp >= durs) { /* fade out portion */ buffer[wp-durs] += sig[i]*a; a -= inc; } else buffer[wp] = sig[i]; /* middle of loop */ } /* while recording connect input to output directly */ out[i] = sig[i]; wp++; /* increment writer pointer */ if (wp == durs+cfds) { /* end of recording */ recon = 0; /* OFF */ p->rst = 0; /* reset to 0 */ p->rp = (MYFLT) wp; /* rp pointer to start from here */ } } else { if (on) { /* if opcode is ON */ out[i] = buffer[(int)rp]; /* output the looped sound */ rp += pitch; /* read pointer increment */ while (rp >= durs) rp -= durs; /* wrap-around */ while (rp < 0) rp += durs; } else { /* if opocde is OFF */ out[i] = sig[i]; /* copy input to the output */ p->rst = 1; /* reset: ready for new recording */ wp = 0; /* zero write pointer */ } } } p->rp = rp; /* keep the values */ p->wp = wp; p->a = a; *(p->recon) = (MYFLT) recon; /* output 'rec on light' */ return OK; } static int flooper_init(CSOUND *csound, flooper *p) { MYFLT *tab, *buffer, a = FL(0.0), inc; int32 cfds = (int32) (*(p->cfd)*CS_ESR); /* fade in samps */ int32 starts = (int32) (*(p->start)*CS_ESR); /* start in samps */ int32 durs = (int32) (*(p->dur)*CS_ESR); /* dur in samps */ int32 len, i, nchnls; if (UNLIKELY(cfds > durs)) return csound->InitError(csound, Str("crossfade longer than loop duration\n")); inc = FL(1.0)/cfds; /* inc/dec */ p->sfunc = csound->FTnp2Find(csound, p->ifn) ; /* function table */ if (UNLIKELY(p->sfunc==NULL)) { return csound->InitError(csound,Str("function table not found\n")); } tab = p->sfunc->ftable, /* func table pointer */ len = p->sfunc->flen; /* function table length */ nchnls = p->sfunc->nchanls; if (UNLIKELY(nchnls != p->OUTCOUNT)) { return csound->InitError(csound, Str("function table channel count does not match output")); } if (UNLIKELY(starts > len)) { return csound->InitError(csound,Str("start time beyond end of table\n")); } if (UNLIKELY(starts+durs+cfds > len)) { return csound->InitError(csound,Str("table not long enough for loop\n")); } if (p->buffer.auxp==NULL || /* allocate memory if necessary */ p->buffer.size<(durs+1)*sizeof(MYFLT)*nchnls) csound->AuxAlloc(csound,(durs+1)*sizeof(MYFLT)*nchnls, &p->buffer); inc = (MYFLT)1/cfds; /* fade envelope incr/decr */ buffer = p->buffer.auxp; /* loop memory */ /* we now write the loop into memory */ durs *= nchnls; starts *= nchnls; cfds *= nchnls; for (i=0; i < durs; i+=nchnls) { if (i < cfds) { buffer[i] = a*tab[i+starts]; if(nchnls == 2) buffer[i+1] = a*tab[i+starts+1]; a += inc; } else { buffer[i] = tab[i+starts]; if(nchnls == 2) buffer[i+1] = tab[i+starts+1]; } } /* crossfade section */ for (i=0; i < cfds; i+=nchnls) { buffer[i] += a*tab[i+starts+durs]; if(nchnls == 2) buffer[i+1] += a*tab[i+starts+durs+1]; a -= inc; } buffer[durs] = buffer[0]; /* for wrap-around interpolation */ p->strts = starts/nchnls; p->durs = durs/nchnls; p->ndx = FL(0.0); /* lookup index */ p->loop_off = 1; p->nchnls = nchnls; return OK; } static int flooper_process(CSOUND *csound, flooper *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; int32 end = p->strts+p->durs, durs = p->durs; MYFLT **aout = p->out, *buffer = p->buffer.auxp; MYFLT amp = *(p->amp), pitch = *(p->pitch); MYFLT *tab = p->sfunc->ftable; double ndx = p->ndx; MYFLT frac; int tndx, loop_off = p->loop_off, nchnls = p->nchnls; if (UNLIKELY(offset)) memset(aout[0], '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&aout[0][nsmps], '\0', early*sizeof(MYFLT)); if(nchnls == 2) { if (UNLIKELY(offset)) memset(aout[1], '\0', offset*sizeof(MYFLT)); memset(&aout[1][nsmps], '\0', early*sizeof(MYFLT)); } } for (i=offset; i < nsmps; i++) { tndx = (int) ndx; frac = ndx - tndx; /* this is the start portion of the sound */ if (ndx >= 0 && ndx < end && loop_off) { tndx *= nchnls; aout[0][i] = amp*(tab[tndx] + frac*(tab[tndx+nchnls] - tab[tndx])); if(nchnls == 2){ tndx += 1; aout[1][i] = amp*(tab[tndx] + frac*(tab[tndx+nchnls] - tab[tndx])); } ndx += pitch; } /* this is the loop section */ else { if (loop_off) { while(ndx >= end) ndx -= end; /* wrap-around, if reading backwards */ while (tndx < 0) tndx += durs; tndx = (int) ndx; } loop_off = 0; tndx *= nchnls; aout[0][i] = amp*(buffer[tndx] + frac*(buffer[tndx+nchnls] - buffer[tndx])); if(nchnls == 2){ tndx += 1; aout[1][i] = amp*(buffer[tndx] + frac*(buffer[tndx+nchnls] - buffer[tndx])); } ndx += pitch; while (ndx < 0) ndx += durs; while (ndx >= durs) ndx -= durs; } } p->ndx = ndx; p->loop_off = loop_off; return OK; } static int flooper2_init(CSOUND *csound, flooper2 *p) { p->sfunc = csound->FTnp2Find(csound, p->ifn); /* function table */ if (UNLIKELY(p->sfunc==NULL)) { return csound->InitError(csound,Str("function table not found\n")); } if (*p->ifn2 != 0) p->efunc = csound->FTnp2Find(csound, p->ifn2); else p->efunc = NULL; if (*p->iskip == 0){ p->mode = (int) *p->imode; if (p->mode == 0 || p->mode == 2){ if ((p->ndx[0] = *p->start*CS_ESR) < 0) p->ndx[0] = 0; if (p->ndx[0] >= p->sfunc->flen) p->ndx[0] = (double) p->sfunc->flen - 1.0; p->count = 0; } p->init = 1; p->firsttime = 1; p->cfade = 1; } p->nchnls = (int)(p->OUTOCOUNT); if(p->nchnls != p->sfunc->nchanls){ csound->Warning(csound, Str("function table channels do not match opcode outputs")); } return OK; } static int flooper2_process(CSOUND *csound, flooper2 *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT out[2], **aout = p->out, sr = CS_ESR; MYFLT amp = *(p->amp), pitch = *(p->pitch); MYFLT *tab; double *ndx = p->ndx; MYFLT frac0, frac1, *etab; int loop_end = p->lend, loop_start = p->lstart, crossfade = p->cfade, len; MYFLT count = p->count, fadein, fadeout; int *firsttime = &p->firsttime, elen, mode=p->mode, init = p->init, ijump = *p->ijump; uint32 tndx0, tndx1, nchnls, onchnls = p->nchnls; FUNC *func; func = csound->FTnp2Find(csound, p->ifn); if(p->sfunc != func) { p->sfunc = func; if (UNLIKELY(func == NULL)) return csound->PerfError(csound, p->h.insdshead, Str("table %d invalid\n"), (int) *p->ifn); if (p->ndx[0] >= p->sfunc->flen) p->ndx[0] = (double) p->sfunc->flen - 1.0; if(p->nchnls != p->sfunc->nchanls){ csound->Warning(csound, Str("function table channels do not match opcode outputs")); } } tab = p->sfunc->ftable; len = p->sfunc->flen; if (p->efunc != NULL) { etab = p->efunc->ftable; elen = p->efunc->flen; } else { etab = NULL; elen = 0; } /* loop parameters & check */ if (pitch < FL(0.0)) pitch = FL(0.0); if (UNLIKELY(offset)) memset(aout[0], '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&aout[0][nsmps], '\0', early*sizeof(MYFLT)); if(onchnls == 2) { if (UNLIKELY(offset)) memset(aout[1], '\0', offset*sizeof(MYFLT)); memset(&aout[1][nsmps], '\0', early*sizeof(MYFLT)); } } if (*firsttime) { int loopsize; /* offset non zero only if firsttime */ if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); loop_start = (int) (*p->loop_start*sr); loop_end = (int) (*p->loop_end*sr); p->lstart = loop_start = loop_start < 0 ? 0 : loop_start; p->lend = loop_end = loop_end > len ? len : (loop_end < loop_start ? loop_start : loop_end); loopsize = loop_end - loop_start; if (*p->crossfade > 0.0) crossfade = (int) (*p->crossfade*sr); p->ostart = *p->loop_start; p->oend = *p->loop_end; if (mode == 1) { ndx[0] = (double) loop_end; ndx[1] = (double) loop_end; count = (MYFLT) crossfade; p->cfade = crossfade = crossfade > loopsize ? loopsize : crossfade; } else if (mode == 2) { ndx[1] = (double) loop_start - FL(1.0); p->cfade = crossfade = crossfade > loopsize/2 ? loopsize/2-1 : crossfade; } else { ndx[1] = (double) loop_start; p->cfade = crossfade = crossfade > loopsize ? loopsize : crossfade; } *firsttime = 0; } else { if (*p->ijump && (mode == 0) && (p->ostart != *p->loop_start || p->oend != *p->loop_end)) { if (*p->ijump > 1) loop_end = (int)(ndx[0] + crossfade); loop_start = *p->loop_start*sr; p->ostart = *p->loop_start; p->oend = *p->loop_end; } } onchnls = p->nchnls; nchnls = p->sfunc->nchanls; for (i=offset; i < nsmps; i++) { if (mode == 1){ /* backwards */ tndx0 = (int) ndx[0]; frac0 = ndx[0] - tndx0; if (ndx[0] > crossfade + loop_start) { tndx0 *= nchnls; out[0] = amp*(tab[tndx0] + frac0*(tab[tndx0+nchnls] - tab[tndx0])); if(onchnls == 2) { tndx0 += 1; out[1] = amp*(tab[tndx0] + frac0*(tab[tndx0+nchnls] - tab[tndx0])); } } else { tndx1 = (int) ndx[1]; frac1 = ndx[1] - tndx1; if (etab==NULL){ if(crossfade > 0) //27292 fadeout = count/crossfade; else fadeout = 0.0; fadein = FL(1.0) - fadeout; } else { if(crossfade > 0) //27292 fadeout = elen*count/crossfade; else fadeout = 0.0; fadein = etab[elen - (int)fadeout]; fadeout = etab[(int)fadeout]; } tndx1 *= nchnls; tndx0 *= nchnls; out[0] = amp*(fadeout*(tab[tndx0] + frac0*(tab[tndx0+nchnls] - tab[tndx0])) + fadein*(tab[tndx1] + frac1*(tab[tndx1+nchnls] - tab[tndx1]))); if(onchnls == 2) { tndx1 += 1; tndx0 += 1; out[1] = amp*(fadeout*(tab[tndx0] + frac0*(tab[tndx0+nchnls] - tab[tndx0])) + fadein*(tab[tndx1] + frac1*(tab[tndx1+nchnls] - tab[tndx1]))); } ndx[1]-=pitch; count-=pitch; } ndx[0]-=pitch; if (ndx[0] <= loop_start) { int loopsize; loop_start = (int) (*p->loop_start*sr); loop_end = (int) (*p->loop_end*sr); p->lstart = loop_start = loop_start < 0 ? 0 : loop_start; p->lend = loop_end = loop_end > len ? len : (loop_end < loop_start ? loop_start : loop_end); loopsize = loop_end - loop_start; if(*p->crossfade > 0.0) crossfade = (int) (*p->crossfade*sr); p->cfade = crossfade = crossfade > loopsize ? loopsize : crossfade; ndx[0] = ndx[1]; ndx[1] = (double)loop_end; count=(MYFLT)crossfade; p->oend = *p->loop_end; p->ostart = *p->loop_start; } } else if (mode==2) { /* back and forth */ out[0] = 0.0; if(onchnls == 2) out[1] = 0.0; /* this is the forward reader */ if (init && ndx[0] < loop_start + crossfade) { tndx0 = (int) ndx[0]; frac0 = ndx[0] - tndx0; tndx0 *= nchnls; out[0] = amp*(tab[tndx0] + frac0*(tab[tndx0+nchnls] - tab[tndx0])); if(onchnls == 2){ tndx0 *= nchnls; out[1] = amp*(tab[tndx0] + frac0*(tab[tndx0+nchnls] - tab[tndx0])); } ndx[0] += pitch; } else if (ndx[0] < loop_start + crossfade) { if (etab==NULL) fadein = count/crossfade; else fadein = etab[(int)(elen*count/crossfade)]; tndx0 = (int) ndx[0]; frac0 = ndx[0] - tndx0; tndx0 *= nchnls; out[0] += amp*fadein*(tab[tndx0] + frac0*(tab[tndx0+nchnls] - tab[tndx0])); if(onchnls == 2){ tndx0 += 1; out[1] += amp*fadein*(tab[tndx0] + frac0*(tab[tndx0+nchnls] - tab[tndx0])); } ndx[0] += pitch; count += pitch; } else if (ndx[0] < loop_end - crossfade) { tndx0 = (int) ndx[0]; frac0 = ndx[0] - tndx0; tndx0 *= nchnls; out[0] = amp*(tab[tndx0] + frac0*(tab[tndx0+nchnls] - tab[tndx0])); if(onchnls == 2){ tndx0 += 1; out[1] = amp*(tab[tndx0] + frac0*(tab[tndx0+nchnls] - tab[tndx0])); } ndx[0] += pitch; init = 0; if (ndx[0] >= loop_end - crossfade) { ndx[1] = (double) loop_end; count = 0; } } else if (ndx[0] < loop_end) { if (etab==NULL) fadeout = FL(1.0) - count/crossfade; else fadeout = etab[(int)(elen*(1.0 - count/crossfade))]; tndx0 = (int) ndx[0]; frac0 = ndx[0] - tndx0; tndx0 *= nchnls; out[0] += amp*fadeout*(tab[tndx0] + frac0*(tab[tndx0+nchnls] - tab[tndx0])); if(onchnls == 2){ tndx0 += 1; out[1] += amp*fadeout*(tab[tndx0] + frac0*(tab[tndx0+nchnls] - tab[tndx0])); } ndx[0] += pitch; count += pitch; } /* this is the backward reader */ if (ndx[1] > loop_end - crossfade) { if (etab==NULL) fadein = count/crossfade; else fadein = etab[(int)(elen*count/crossfade)]; tndx1 = (int) ndx[1]; frac1 = ndx[1] - tndx1; tndx1 *= nchnls; out[0] += amp*fadein*(tab[tndx1] + frac1*(tab[tndx1+nchnls] - tab[tndx1])); if(onchnls == 2){ tndx1 += 1; out[1] += amp*fadein*(tab[tndx1] + frac1*(tab[tndx1+nchnls] - tab[tndx1])); } ndx[1] -= pitch; } else if (ndx[1] > loop_start + crossfade) { tndx1 = (int) ndx[1]; frac1 = ndx[1] - tndx1; tndx1 *= nchnls; out[0] = amp*(tab[tndx1] + frac1*(tab[tndx1+nchnls] - tab[tndx1])); if(onchnls == 2){ tndx1 += 1; out[1] += amp*(tab[tndx1] + frac1*(tab[tndx1+nchnls] - tab[tndx1])); } ndx[1] -= pitch; if (ndx[1] <= loop_start + crossfade) { ndx[0] = (double) loop_start; count = 0; } } else if (ndx[1] > loop_start) { if (etab==NULL) fadeout = FL(1.0) - count/crossfade; else fadeout = etab[(int)(elen*(1.0 - count/crossfade))]; tndx1 = (int) ndx[1]; frac1 = ndx[1] - tndx1; tndx1 *= nchnls; out[0] += amp*fadeout*(tab[tndx1] + frac1*(tab[tndx1+nchnls] - tab[tndx1])); if(onchnls == 2){ tndx1 += 1; out[1] += amp*fadeout*(tab[tndx1] + frac1*(tab[tndx1+nchnls] - tab[tndx1])); } ndx[1] -= pitch; if (ndx[1] <= loop_start) { int loopsize; loop_start = (int) (*p->loop_start*sr); loop_end = (int) (*p->loop_end*sr); p->lstart = loop_start = loop_start < 0 ? 0 : loop_start; p->lend = loop_end = loop_end > len ? len : (loop_end < loop_start ? loop_start : loop_end); loopsize = loop_end - loop_start; if(*p->crossfade > 0.0) crossfade = (int) (*p->crossfade*sr); p->cfade = crossfade = crossfade > loopsize/2 ? loopsize/2-1 : crossfade; p->oend = *p->loop_end; p->ostart = *p->loop_start; ndx[0] = (double) loop_start; count = 0; } } } else { /* normal */ out[0] = 0; tndx0 = (uint32) ndx[0]; frac0 = ndx[0] - tndx0; if (ndx[0] < loop_end-crossfade) { tndx0 *= nchnls; out[0] = amp*(tab[tndx0] + frac0*(tab[tndx0+nchnls] - tab[tndx0])); if(onchnls == 2){ tndx0 += 1; out[1] = amp*(tab[tndx0] + frac0*(tab[tndx0+nchnls] - tab[tndx0])); } if (ijump) ndx[1] = loop_start; } else { tndx1 = (int) ndx[1]; frac1 = ndx[1] - tndx1; if (etab==NULL) { fadein = count/crossfade; fadeout = FL(1.0) - fadein; } else { fadein = elen*count/crossfade; fadeout = etab[elen - (int)fadein]; fadein = etab[(int)fadein]; } tndx1 *= nchnls; tndx0 *= nchnls; out[0] = amp*(fadeout*(tab[tndx0] + frac0*(tab[tndx0+nchnls] - tab[tndx0])) + fadein*(tab[tndx1] + frac1*(tab[tndx1+nchnls] - tab[tndx1]))); if(onchnls == 2){ tndx1 += 1; tndx0 += 1; out[1] = amp*(fadeout*(tab[tndx0] + frac0*(tab[tndx0+nchnls] - tab[tndx0])) + fadein*(tab[tndx1] + frac1*(tab[tndx1+nchnls] - tab[tndx1]))); } ndx[1]+=pitch; count+=pitch; } ndx[0]+=pitch; if (ndx[0] >= loop_end) { int loopsize; loop_start = (int) (*p->loop_start*sr); loop_end = (int) (*p->loop_end*sr); p->lstart = loop_start = loop_start < 0 ? 0 : loop_start; p->lend = loop_end = loop_end > len ? len : (loop_end < loop_start ? loop_start : loop_end); loopsize = loop_end - loop_start; if(*p->crossfade > 0.0) crossfade = (int) (*p->crossfade*sr); p->cfade = crossfade = crossfade > loopsize ? loopsize-1 : crossfade; ndx[0] = ndx[1]; ndx[1] = (double)loop_start; p->oend = *p->loop_end; p->ostart = *p->loop_start; count=0; } } aout[0][i] = out[0]; if(onchnls == 2) aout[1][i] = out[1]; } p->count = count; p->cfade = crossfade; p->lend = loop_end; p->lstart = loop_start; p->init = init; return OK; } /* static int flooper3_init(CSOUND *csound, flooper3 *p) { int len,i,p2s,lomod; p->sfunc = csound->FTnp2Find(csound, p->ifn); if (UNLIKELY(p->sfunc==NULL)) { return csound->InitError(csound,Str("function table not found\n")); } if (*p->ifn2 != 0) p->efunc = csound->FTFind(csound, p->ifn2); else p->efunc = NULL; len = p->sfunc->flen; p->lobits = 0; for(i=1; i < len; i<<=1); p2s = i; for(;(i & MAXLEN)==0; p->lobits++, i<<=1); lomod = MAXLEN/p2s; p->lomask = lomod - 1; p->lodiv = 1.0/lomod; if (*p->iskip == 0){ p->mode = (int) *p->imode; if (p->mode == 0 || p->mode == 2){ if ((p->ndx[0] = *p->start*CS_ESR) < 0) p->ndx[0] = 0; if (p->ndx[0] >= p->sfunc->flen) p->ndx[0] = p->sfunc->flen - 1.0; p->count = 0; } p->init = 1; p->firsttime = 1; p->ndx[0] <<= p->lobits; } return OK; } static int flooper3_process(CSOUND *csound, flooper3 *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; int lobits = p->lobits,si,ei; MYFLT *out = p->out, sr = CS_ESR; MYFLT amp = *(p->amp), pitch = *(p->pitch); MYFLT *tab = p->sfunc->ftable, cvt; int32 *ndx = p->ndx, lomask = p->lomask, pos; MYFLT frac0, frac1, *etab, lodiv = p->lodiv; int loop_end = p->lend, loop_start = p->lstart, mode = p->mode, crossfade = p->cfade, len = p->sfunc->flen, count = p->count; MYFLT fadein, fadeout; int *firsttime = &p->firsttime, elen, init = p->init; uint32 tndx0, tndx1; if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } if (pitch < FL(0.0)) pitch = FL(0.0); if (*firsttime) { int loopsize; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); loop_start = MYFLT2LRND(*p->loop_start*sr); loop_end = MYFLT2LRND (*p->loop_end*sr); p->lstart = loop_start = (loop_start < 0 ? 0 : loop_start); p->lend = loop_end = (loop_end > len ? len : (loop_end < loop_start ? loop_start : loop_end)); loopsize = loop_end - loop_start; crossfade = MYFLT2LRND(*p->crossfade*sr); if (mode == 1) { ndx[0] = loop_end<cfade = crossfade = crossfade > loopsize ? loopsize : crossfade; } else if (mode == 2) { ndx[1] = (loop_start-1)<cfade = crossfade = crossfade > loopsize/2 ? loopsize/2-1 : crossfade; } else { ndx[1] = loop_start<cfade = crossfade = crossfade > loopsize ? loopsize : crossfade; } *firsttime = 0; } if (p->efunc != NULL) { etab = p->efunc->ftable; elen = p->efunc->flen; } else { etab = NULL; elen = 1; } cvt = (MYFLT )elen/p->cfade; si = MYFLT2LRND(pitch*(lomask)); ei = MYFLT2LRND(pitch*(lomask)); for (i=offset; i < nsmps; i++) { if (mode == 0){ tndx0 = ndx[0]>>lobits; frac0 = (ndx[0] & lomask)*lodiv; if (tndx0 < loop_end-crossfade) out[i] = amp*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0])); else { tndx1 = ndx[1]>>lobits; frac1 = (ndx[1] & lomask)*lodiv; if (etab==NULL) { fadein = (count>>lobits)*cvt; fadeout = FL(1.0) - fadein; } else { pos = MYFLT2LRND((count>>lobits)*cvt); fadein = etab[pos]; fadeout = etab[elen - pos]; } out[i] = amp*(fadeout*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0])) + fadein*(tab[tndx1] + frac1*(tab[tndx1+1] - tab[tndx1]))); ndx[1]+=si; count+=ei; } ndx[0]+=si; if (tndx0 >= loop_end) { int loopsize; loop_start = MYFLT2LRND(*p->loop_start*sr); loop_end = MYFLT2LRND(*p->loop_end*sr); p->lstart = loop_start = (loop_start < 0 ? 0 : loop_start); p->lend = loop_end = (loop_end > len ? len : (loop_end < loop_start ? loop_start : loop_end)); loopsize = (loop_end - loop_start); crossfade = MYFLT2LRND(*p->crossfade*sr); p->cfade = crossfade = crossfade > loopsize ? loopsize : crossfade; ndx[0] = ndx[1]; ndx[1] = loop_start<cfade; } } else if (mode == 1) { tndx0 = ndx[0]>>lobits; frac0 = (ndx[0] & lomask)*lodiv; if (tndx0 > crossfade + loop_start) out[i] = amp*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0])); else { tndx1 = ndx[1]>>lobits; frac1 = (ndx[1] & lomask)*lodiv; if (etab==NULL) { fadeout = (count>>lobits)*cvt; fadein = FL(1.0) - fadeout; } else { pos = MYFLT2LRND((count>>lobits)*cvt); fadeout = etab[pos]; fadein = etab[elen - pos]; } out[i] = amp*(fadeout*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0])) + fadein*(tab[tndx1] + frac1*(tab[tndx1+1] - tab[tndx1]))); ndx[1]-=si; count-=ei; } ndx[0]-=si; if (tndx0 <= loop_start) { int loopsize; loop_start = MYFLT2LRND(*p->loop_start*sr); loop_end = MYFLT2LRND(*p->loop_end*sr); p->lstart = loop_start = (loop_start < 0 ? 0 : loop_start); p->lend = loop_end = (loop_end > len ? len : (loop_end < loop_start ? loop_start : loop_end)); loopsize = (loop_end - loop_start); crossfade = MYFLT2LRND(*p->crossfade*sr); p->cfade = crossfade = crossfade > loopsize ? loopsize : crossfade; ndx[0] = ndx[1]; ndx[1] = loop_end<cfade; } } else if (mode == 2){ out[i] = 0; tndx0 = ndx[0]>>lobits; frac0 = (ndx[0] & lomask)*lodiv; if (init && tndx0 < loop_start + crossfade) { out[i] = amp*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0])); ndx[0] += si; } else if (tndx0 < loop_start + crossfade) { if (etab==NULL) fadein = (count>>lobits)*cvt; else { pos = MYFLT2LRND((count>>lobits)*cvt); fadein = etab[pos]; } out[i] += amp*fadein*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0])); ndx[0] += si; count += ei; } else if (tndx0 < loop_end - crossfade) { out[i] = amp*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0])); ndx[0] += si; init = 0; tndx0 = ndx[0]>>lobits; if (tndx0 >= loop_end - crossfade) { ndx[1] = loop_end<>lobits)*cvt; else { pos = MYFLT2LRND((count>>lobits)*cvt); fadeout = etab[elen - pos]; } out[i] += amp*fadeout*(tab[tndx0] + frac0*(tab[tndx0+1] - tab[tndx0])); ndx[0] += si; count += ei; } tndx1 = ndx[1]>>lobits; frac1 = (ndx[1] & lomask)*lodiv; if (tndx1 > loop_end - crossfade) { if (etab==NULL) fadein = (count>>lobits)*cvt; else { pos = MYFLT2LRND((count>>lobits)*cvt); fadein = etab[pos]; } out[i] += amp*fadein*(tab[tndx1] + frac1*(tab[tndx1+1] - tab[tndx1])); ndx[1] -= si; } else if (tndx1 > loop_start + crossfade) { out[i] = amp*(tab[tndx1] + frac1*(tab[tndx1+1] - tab[tndx1])); ndx[1] -= si; tndx1 = ndx[1]>>lobits; if (tndx1 <= loop_start + crossfade) { ndx[0] = loop_start< loop_start) { if (etab==NULL) fadeout = FL(1.0) - (count>>lobits)*cvt; else { pos = MYFLT2LRND((count>>lobits)*cvt); fadeout = etab[elen - pos]; } out[i] += amp*fadeout*(tab[tndx1] + frac1*(tab[tndx1+1] - tab[tndx1])); ndx[1] -= si; tndx1 = ndx[1]>>lobits; if (tndx1 <= loop_start) { int loopsize; loop_start = MYFLT2LRND(*p->loop_start*sr); loop_end = MYFLT2LRND(*p->loop_end*sr); p->lstart = loop_start = (loop_start < 0 ? 0 : loop_start); p->lend = loop_end = (loop_end > len ? len : (loop_end < loop_start ? loop_start : loop_end)); loopsize = (loop_end - loop_start); crossfade = MYFLT2LRND(*p->crossfade*sr); p->cfade = crossfade = crossfade > loopsize/2 ? loopsize/2-1 : crossfade; cvt = (MYFLT)elen/p->cfade; } } } } p->count = count; p->cfade = crossfade; p->lend = loop_end; p->lstart = loop_start; p->init = init; return OK; } */ static int pvsarp_init(CSOUND *csound, pvsarp *p) { int32 N = p->fin->N; if (p->fout->frame.auxp==NULL || p->fout->frame.size<(N+2)*sizeof(float)) csound->AuxAlloc(csound,(N+2)*sizeof(float),&p->fout->frame); p->fout->N = N; p->fout->overlap = p->fin->overlap; p->fout->winsize = p->fin->winsize; p->fout->wintype = p->fin->wintype; p->fout->format = p->fin->format; p->fout->framecount = 1; p->lastframe = 0; if (UNLIKELY(!(p->fout->format==PVS_AMP_FREQ) || (p->fout->format==PVS_AMP_PHASE))){ return csound->InitError(csound, Str("pvsarp: signal format must be amp-phase " "or amp-freq.\n")); } return OK; } static int pvsarp_process(CSOUND *csound, pvsarp *p) { int32 i,j,N = p->fout->N, bins = N/2 + 1; float g = (float) *p->gain; MYFLT kdepth = (MYFLT) *(p->kdepth), cf = (MYFLT) *(p->cf); float *fin = (float *) p->fin->frame.auxp; float *fout = (float *) p->fout->frame.auxp; if (UNLIKELY(fout==NULL)) goto err1; if (p->lastframe < p->fin->framecount) { cf = cf >= 0 ? (cf < bins ? cf*bins : bins-1) : 0; kdepth = kdepth >= 0 ? (kdepth <= 1 ? kdepth : FL(1.0)): FL(0.0); for (i=j=0;i < N+2;i+=2, j++) { if (j == (int) cf) fout[i] = fin[i]*g; else fout[i] = (float)(fin[i]*(1-kdepth)); fout[i+1] = fin[i+1]; } p->fout->framecount = p->lastframe = p->fin->framecount; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("pvsarp: not initialised\n")); } static int pvsvoc_init(CSOUND *csound, pvsvoc *p) { int32 N = p->fin->N; if (p->fout->frame.auxp==NULL || p->fout->frame.size<(N+2)*sizeof(float)) csound->AuxAlloc(csound,(N+2)*sizeof(float),&p->fout->frame); p->fout->N = N; p->fout->overlap = p->fin->overlap; p->fout->winsize = p->fin->winsize; p->fout->wintype = p->fin->wintype; p->fout->format = p->fin->format; p->fout->framecount = 1; p->lastframe = 0; if (UNLIKELY(!(p->fout->format==PVS_AMP_FREQ) || (p->fout->format==PVS_AMP_PHASE))){ return csound->InitError(csound, Str("signal format must be amp-phase " "or amp-freq.\n")); } if (p->ceps.auxp == NULL || p->ceps.size < sizeof(MYFLT) * (N+2)) csound->AuxAlloc(csound, sizeof(MYFLT) * (N + 2), &p->ceps); else memset(p->ceps.auxp, 0, sizeof(MYFLT)*(N+2)); if (p->fenv.auxp == NULL || p->fenv.size < sizeof(MYFLT) * (N+2)) csound->AuxAlloc(csound, sizeof(MYFLT) * (N + 2), &p->fenv); if (p->fexc.auxp == NULL || p->fexc.size < sizeof(MYFLT) * (N+2)) csound->AuxAlloc(csound, sizeof(MYFLT) * (N + 2), &p->fexc); return OK; } void csoundComplexFFTnp2(CSOUND *csound, MYFLT *buf, int FFTsize); void csoundInverseComplexFFTnp2(CSOUND *csound, MYFLT *buf, int FFTsize); static int pvsvoc_process(CSOUND *csound, pvsvoc *p) { int32 i,N = p->fout->N; float gain = (float) *p->gain; MYFLT kdepth = (MYFLT) *(p->kdepth); float *fin = (float *) p->fin->frame.auxp; float *ffr = (float *) p->ffr->frame.auxp; float *fexc = (float *) p->fexc.auxp; float *fout = (float *) p->fout->frame.auxp; int coefs = (int) *(p->kcoefs), j; MYFLT *fenv = (MYFLT *) p->fenv.auxp; MYFLT *ceps = (MYFLT *) p->ceps.auxp; float maxe=0.f, maxa=0.f; if (UNLIKELY(fout==NULL)) goto err1; if (p->lastframe < p->fin->framecount) { int tmp = N/2; tmp = tmp + tmp%2; for (j=0; j < 2; j++) { MYFLT a; maxe = 0.f; maxa = 0.f; for (i=0; i < N; i+=2) { a = (j ? fin[i] : (fexc[i] = ffr[i])); maxa = maxa < a ? a : maxa; if (a <= 0) a = 1e-20; fenv[i/2] = log(a); } if (coefs < 1) coefs = 80; for (i=0; i < N; i+=2){ ceps[i] = fenv[i/2]; ceps[i+1] = 0.0; } if (!(N & (N - 1))) csound->InverseComplexFFT(csound, ceps, N/2); else csoundInverseComplexFFTnp2(csound, ceps, tmp); for (i=coefs; i < N-coefs; i++) ceps[i] = 0.0; if (!(N & (N - 1))) csound->ComplexFFT(csound, ceps, N/2); else csoundComplexFFTnp2(csound, ceps, tmp); for (i=0; i < N; i+=2) { fenv[i/2] = exp(ceps[i]); maxe = maxe < fenv[i/2] ? fenv[i/2] : maxe; } if (maxe) for (i=0; i= 0 ? (kdepth <= 1 ? kdepth : FL(1.0)): FL(0.0); for (i=0;i < N+2;i+=2) { fout[i] = fenv[i/2]*(fexc[i]*kdepth + fin[i]*(FL(1.0)-kdepth))*gain; fout[i+1] = ffr[i+1]*(kdepth) + fin[i+1]*(FL(1.0)-kdepth); } p->fout->framecount = p->lastframe = p->fin->framecount; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("pvsvoc: not initialised\n")); } static int pvsmorph_init(CSOUND *csound, pvsmorph *p) { int32 N = p->fin->N; if (p->fout->frame.auxp==NULL || p->fout->frame.size<(N+2)*sizeof(float)) csound->AuxAlloc(csound,(N+2)*sizeof(float),&p->fout->frame); p->fout->N = N; p->fout->overlap = p->fin->overlap; p->fout->winsize = p->fin->winsize; p->fout->wintype = p->fin->wintype; p->fout->format = p->fin->format; p->fout->framecount = 1; p->lastframe = 0; if (UNLIKELY(!(p->fout->format==PVS_AMP_FREQ) || (p->fout->format==PVS_AMP_PHASE))){ return csound->InitError(csound, Str("signal format must be amp-phase " "or amp-freq.\n")); } return OK; } static int pvsmorph_process(CSOUND *csound, pvsmorph *p) { int32 i,N = p->fout->N; float frint = (float) *p->gain; float amint = (float) *(p->kdepth); float *fi1 = (float *) p->fin->frame.auxp; float *fi2 = (float *) p->ffr->frame.auxp; float *fout = (float *) p->fout->frame.auxp; if (UNLIKELY(fout==NULL)) goto err1; if (p->lastframe < p->fin->framecount) { amint = amint > 0 ? (amint <= 1 ? amint : FL(1.0)): FL(0.0); frint = frint > 0 ? (frint <= 1 ? frint : FL(1.0)): FL(0.0); for(i=0;i < N+2;i+=2) { fout[i] = fi1[i]*(1.0-amint) + fi2[i]*(amint); fout[i+1] = fi1[i+1]*(1.0-frint) + fi2[i+1]*(frint); } p->fout->framecount = p->lastframe = p->fin->framecount; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("pvsmorph: not initialised\n")); } static OENTRY localops[] = { {"sndloop", sizeof(sndloop),0, 5, "ak", "akkii", (SUBR)sndloop_init, NULL, (SUBR)sndloop_process}, {"flooper", sizeof(flooper), TR, 5, "mm", "kkiiii", (SUBR)flooper_init, NULL, (SUBR)flooper_process}, {"pvsarp", sizeof(pvsarp), 0,3, "f", "fkkk", (SUBR)pvsarp_init, (SUBR)pvsarp_process}, {"pvsvoc", sizeof(pvsvoc), 0,3, "f", "ffkkO", (SUBR)pvsvoc_init, (SUBR)pvsvoc_process}, {"flooper2", sizeof(flooper2), TR, 5, "mm", "kkkkkiooooO", (SUBR)flooper2_init, NULL, (SUBR)flooper2_process}, /* {"flooper3", sizeof(flooper3), TR, 5, "a", "kkkkkioooo", (SUBR)flooper3_init, NULL, (SUBR)flooper3_process},*/ {"pvsmorph", sizeof(pvsvoc), 0,3, "f", "ffkk", (SUBR)pvsmorph_init, (SUBR)pvsmorph_process} }; int sndloop_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/sndwarp.c000066400000000000000000000312361321653344700163240ustar00rootroot00000000000000/* sndwarp.c: Copyright (C) 1997 Richard Karpen, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /**************************************************************/ /*************sndwarp******************************************/ /*** By Richard Karpen - 1992, 1995, 1997 *********************/ /**************************************************************/ /*This is a version that uses table lookup instead of reading */ /*from soundfiles. */ /**************************************************************/ #include "stdopcod.h" #include "sndwarp.h" #define unirand(x) ((MYFLT) (x->Rand31(&(x->randSeed1)) - 1) / FL(2147483645.0)) static int sndwarpgetset(CSOUND *csound, SNDWARP *p) { int i; int nsections; FUNC *ftpWind, *ftpSamp; WARPSECTION *exp; char *auxp; MYFLT iwsize; nsections = (int)*p->ioverlap; if ((auxp = p->auxch.auxp) == NULL || nsections != p->nsections) { if (nsections != p->nsections) auxp = p->auxch.auxp=NULL; csound->AuxAlloc(csound, (size_t)nsections*sizeof(WARPSECTION), &p->auxch); auxp = p->auxch.auxp; p->nsections = nsections; } p->exp = (WARPSECTION *)auxp; if (UNLIKELY((ftpSamp = csound->FTnp2Find(csound, p->isampfun)) == NULL)) return NOTOK; p->ftpSamp = ftpSamp; p->sampflen = ftpSamp->flen; if (UNLIKELY((ftpWind = csound->FTnp2Find(csound, p->ifn)) == NULL)) return NOTOK; p->ftpWind = ftpWind; p->flen = ftpWind->flen; p->maxFr = -1 + ftpSamp->flen; p->prFlg = 1; /* true */ p->begin = (int)(*p->ibegin * CS_ESR); exp = p->exp; iwsize = *p->iwsize; for (i=0; i< *p->ioverlap; i++) { if (i==0) { exp[i].wsize = (int)iwsize; exp[i].cnt = 0; exp[i].ampphs = FL(0.0); } else { exp[i].wsize = (int) (iwsize + (unirand(csound) * (*p->irandw))); exp[i].cnt=(int)(exp[i].wsize*((MYFLT)i/(*p->ioverlap))); exp[i].ampphs = p->flen*((MYFLT)i/(*p->ioverlap)); } exp[i].offset = (MYFLT)p->begin; exp[i].ampincr = (MYFLT)p->flen/(exp[i].wsize-1); /* exp[i].section = i+1; *//* section number just used for debugging! */ } p->ampcode = IS_ASIG_ARG(p->xamp) ? 1 : 0; p->timewarpcode = IS_ASIG_ARG(p->xtimewarp) ? 1 : 0; p->resamplecode = IS_ASIG_ARG(p->xresample) ? 1 : 0; return OK; } static int sndwarp(CSOUND *csound, SNDWARP *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT frm_0,frm_1; int32 base, longphase; MYFLT frac, frIndx; MYFLT *r1, *r2, *amp, *timewarpby, *resample; WARPSECTION *exp; FUNC *ftpWind, *ftpSamp; int i; MYFLT v1, v2, windowamp, fract; MYFLT flen = (MYFLT)p->flen; MYFLT iwsize = *p->iwsize; int overlap = *p->ioverlap; if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; r1 = p->r1; r2 = p->r2; memset(r1, 0, nsmps*sizeof(MYFLT)); if (p->OUTOCOUNT >1) memset(r2, 0, nsmps*sizeof(MYFLT)); /* for (i=0; iOUTOCOUNT >1) *r2++ = FL(0.0); */ /* } */ exp = p->exp; ftpWind = p->ftpWind; ftpSamp = p->ftpSamp; for (i=0; ir1; */ /* if (p->OUTOCOUNT >1) r2 = p->r2; */ resample = p->xresample; timewarpby = p->xtimewarp; amp = p->xamp; if (UNLIKELY(offset)) { memset(r1, '\0', offset*sizeof(MYFLT)); if (p->OUTOCOUNT >1) memset(r2, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&r1[nsmps], '\0', early*sizeof(MYFLT)); if (p->OUTOCOUNT >1) memset(&r2[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nitimemode!=0) exp[i].offset=(CS_ESR * *timewarpby)+p->begin; else exp[i].offset += (MYFLT)exp[i].wsize/(*timewarpby); exp[i].cnt=0; exp[i].wsize = (int) (iwsize + (unirand(csound) * (*p->irandw))); exp[i].ampphs = FL(0.0); exp[i].ampincr = flen/(exp[i].wsize-1); skipover: frIndx =(MYFLT)((exp[i].cnt * *resample) + exp[i].offset); exp[i].cnt += 1; if (frIndx > (MYFLT)p->maxFr) { /* not past last one */ frIndx = (MYFLT)p->maxFr; if (p->prFlg) { p->prFlg = 0; /* false */ csound->Warning(csound, Str("SNDWARP at last sample frame")); } } longphase = (int32)exp[i].ampphs; if (longphase > p->flen-1) longphase = p->flen-1; v1 = *(ftpWind->ftable + longphase); v2 = *(ftpWind->ftable + longphase + 1); fract = (MYFLT)(exp[i].ampphs - (int32)exp[i].ampphs); windowamp = v1 + (v2 - v1)*fract; exp[i].ampphs += exp[i].ampincr; base = (int32)frIndx; /* index of basis frame of interpolation */ frac = ((MYFLT)(frIndx - (MYFLT)base)); frm_0 = *(ftpSamp->ftable + base); frm_1 = *(ftpSamp->ftable + (base+1)); if (frac != FL(0.0)) { r1[n] += ((frm_0 + frac*(frm_1-frm_0)) * windowamp) * *amp; if (i==0) if (p->OUTOCOUNT > 1) r2[n] += (frm_0 + frac*(frm_1-frm_0)) * *amp; } else { r1[n] += (frm_0 * windowamp) * *amp; if (i==0) if (p->OUTOCOUNT > 1) r2[n] += frm_0 * *amp; } if (p->ampcode) amp++; if (p->timewarpcode) timewarpby++; if (p->resamplecode) resample++; } } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("sndwarp: not initialised")); } /****************************************************************/ /**************STEREO VERSION OF SNDWARP*************************/ /****************************************************************/ static int sndwarpstgetset(CSOUND *csound, SNDWARPST *p) { int i; int nsections; FUNC *ftpWind, *ftpSamp; WARPSECTION *exp; char *auxp; MYFLT iwsize; if (UNLIKELY(p->OUTOCOUNT > 2 && p->OUTOCOUNT < 4)) { return csound->InitError(csound, Str("Wrong number of outputs " "in sndwarpst; must be 2 or 4")); } nsections = (int)*p->ioverlap; if ((auxp = p->auxch.auxp) == NULL || nsections != p->nsections) { if (nsections != p->nsections) auxp=p->auxch.auxp=NULL; csound->AuxAlloc(csound, (size_t)nsections*sizeof(WARPSECTION), &p->auxch); auxp = p->auxch.auxp; p->nsections = nsections; } p->exp = (WARPSECTION *)auxp; if (UNLIKELY((ftpSamp = csound->FTnp2Find(csound, p->isampfun)) == NULL)) return NOTOK; p->ftpSamp = ftpSamp; p->sampflen=ftpSamp->flen; if (UNLIKELY((ftpWind = csound->FTnp2Find(csound, p->ifn)) == NULL)) return NOTOK; p->ftpWind = ftpWind; p->flen=ftpWind->flen; p->maxFr = -1L + (int32)(ftpSamp->flen*FL(0.5)); p->prFlg = 1; /* true */ p->begin = (int)(*p->ibegin * CS_ESR); iwsize = *p->iwsize; exp = p->exp; for (i=0; i< nsections; i++) { if (i==0) { exp[i].wsize = (int)iwsize; exp[i].cnt=0; exp[i].ampphs = FL(0.0); } else { exp[i].wsize = (int) (iwsize + (unirand(csound) * (*p->irandw))); exp[i].cnt=(int)(exp[i].wsize*((MYFLT)i/(*p->ioverlap))); exp[i].ampphs = p->flen*(i/(*p->ioverlap)); } exp[i].offset = (MYFLT)p->begin; exp[i].ampincr = (MYFLT)p->flen/(exp[i].wsize-1); /* exp[i].section = i+1; *//* section number just used for debugging! */ } p->ampcode = IS_ASIG_ARG(p->xamp) ? 1 : 0; p->timewarpcode = IS_ASIG_ARG(p->xtimewarp) ? 1 : 0; p->resamplecode = IS_ASIG_ARG(p->xresample) ? 1 : 0; return OK; } static int sndwarpstset(CSOUND *csound, SNDWARPST *p) { return sndwarpstgetset(csound,p); } static int sndwarpst(CSOUND *csound, SNDWARPST *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT frm10,frm11, frm20, frm21; int32 base, longphase; MYFLT frac, frIndx; MYFLT *r1, *r2,*r3, *r4, *amp, *timewarpby, *resample; WARPSECTION *exp; FUNC *ftpWind, *ftpSamp; int i; MYFLT v1, v2, windowamp, fract; MYFLT flen = (MYFLT)p->flen; MYFLT iwsize = *p->iwsize; if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; /* RWD fix */ r1 = p->r1; r2 = p->r2; r3 = p->r3; r4 = p->r4; memset(r1, 0,nsmps*sizeof(MYFLT)); memset(r2, 0,nsmps*sizeof(MYFLT)); if (p->OUTOCOUNT >2) { memset(r3, 0,nsmps*sizeof(MYFLT)); memset(r4, 0,nsmps*sizeof(MYFLT)); } exp = p->exp; ftpWind = p->ftpWind; ftpSamp = p->ftpSamp; if (UNLIKELY(early)) nsmps -= early; for (i=0; i<*p->ioverlap; i++) { resample = p->xresample; timewarpby = p->xtimewarp; amp = p->xamp; for (n=offset; nitimemode!=0) exp[i].offset=(CS_ESR * *timewarpby)+p->begin; else exp[i].offset += (MYFLT)exp[i].wsize/(*timewarpby); exp[i].cnt=0; exp[i].wsize = (int) (iwsize + (unirand(csound) * (*p->irandw))); exp[i].ampphs = FL(0.0); exp[i].ampincr = flen/(exp[i].wsize-1); skipover: frIndx =(MYFLT)(exp[i].cnt * *resample) + (MYFLT)exp[i].offset; exp[i].cnt += 1; if (frIndx > (MYFLT)p->maxFr) { /* not past last one */ frIndx = (MYFLT)p->maxFr; if (p->prFlg) { p->prFlg = 0; /* false */ csound->Warning(csound, Str("SNDWARP at last sample frame")); } } longphase = (int32)exp[i].ampphs; if (longphase > p->flen-1) longphase = p->flen-1; v1 = *(ftpWind->ftable + longphase); v2 = *(ftpWind->ftable + longphase + 1); fract = (MYFLT)(exp[i].ampphs - (int32)exp[i].ampphs); windowamp = v1 + (v2 - v1)*fract; exp[i].ampphs += exp[i].ampincr; base = (int32)frIndx; /* index of basis frame of interpolation */ frac = ((MYFLT)(frIndx - (MYFLT)base)); frm10 = *(ftpSamp->ftable + (base * 2)); frm11 = *(ftpSamp->ftable + ((base+1)*2)); frm20 = *(ftpSamp->ftable + (base*2)+1); frm21 = *(ftpSamp->ftable + (((base+1)*2)+1)); if (frac != FL(0.0)) { r1[n] += ((frm10 + frac*(frm11-frm10)) * windowamp) * *amp; r2[n] += ((frm20 + frac*(frm21-frm20)) * windowamp) * *amp; if (i==0) if (p->OUTOCOUNT > 2) { r3[n] += (frm10 + frac*(frm11-frm10)) * *amp; r4[n] += (frm20 + frac*(frm21-frm20)) * *amp; } } else { r1[n] += (frm10 * windowamp) * *amp; r2[n] += (frm20 * windowamp) * *amp; if (i==0) if (p->OUTOCOUNT > 2) { r3[n] += frm10 * *amp; r4[n] += frm20 * *amp; } } if (p->ampcode) amp++; if (p->timewarpcode) timewarpby++; if (p->resamplecode) resample++; } } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("sndwarpst: not initialised")); } #define S(x) sizeof(x) static OENTRY localops[] = { { "sndwarp", S(SNDWARP), TR, 5, "mm", "xxxiiiiiii", (SUBR)sndwarpgetset, NULL, (SUBR)sndwarp}, { "sndwarpst", S(SNDWARPST), TR, 5, "mmmm","xxxiiiiiii", (SUBR)sndwarpstset,NULL,(SUBR)sndwarpst} }; int sndwarp_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/sndwarp.h000066400000000000000000000033071321653344700163270ustar00rootroot00000000000000/* sndwarp.h: Copyright (C) 1997 Richard Karpen This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ typedef struct { int cnt, wsize, flag; /* , section; */ MYFLT ampincr, ampphs, offset; } WARPSECTION; typedef struct { OPDS h; MYFLT *r1, *r2, *xamp, *xtimewarp, *xresample, *isampfun, *ibegin, *iwsize, *irandw, *ioverlap, *ifn, *itimemode; FUNC *ftpWind, *ftpSamp; int32 maxFr, prFlg, flen, sampflen, nsections; int chans, *frPtr, begin; WARPSECTION *exp; AUXCH auxch; int16 ampcode, timewarpcode, resamplecode; } SNDWARP; typedef struct { OPDS h; MYFLT *r1, *r2, *r3, *r4, *xamp, *xtimewarp, *xresample, *isampfun, *ibegin, *iwsize, *irandw, *ioverlap, *ifn, *itimemode; FUNC *ftpWind, *ftpSamp; int32 maxFr, prFlg, flen, sampflen, nsections; int chans, *frPtr, begin; WARPSECTION *exp; AUXCH auxch; int16 ampcode, timewarpcode, resamplecode; } SNDWARPST; csound-6.10.0/Opcodes/sockrecv.c000066400000000000000000000553261321653344700164730ustar00rootroot00000000000000/* sockrecv.c: Copyright (C) 2006 by John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include #include #if defined(WIN32) && !defined(__CYGWIN__) #include #include #else #include #include #include #include #endif #include #include #define MAXBUFS 32 #define MTU (1456) #ifndef WIN32 extern int inet_aton(const char *cp, struct in_addr *inp); #endif static uintptr_t udpRecv(void *data); static int deinit_udpRecv(CSOUND *csound, void *pdata); typedef struct { OPDS h; MYFLT *asig; STRINGDAT *ipaddress; MYFLT *port; AUXCH aux, tmp; int sock, conn; struct sockaddr_in server_addr; } SOCKRECVT; typedef struct { OPDS h; STRINGDAT *kstr; STRINGDAT *ipaddress; MYFLT *port; AUXCH aux, tmp; int sock, conn; struct sockaddr_in server_addr; } SOCKRECVS; typedef struct { OPDS h; /* 1 channel: ptr1=asig, ptr2=port, ptr3=buffnos */ /* 2 channel: ptr1=asigl, ptr2=asigr, ptr3=port, ptr4=buffnos */ MYFLT *ptr1, *ptr2, *ptr3, *ptr4; AUXCH buffer, tmp; MYFLT *buf; int sock; volatile int threadon; int buffsize; int outsamps, rcvsamps; CSOUND *cs; void *thrid; void *cb; struct sockaddr_in server_addr; } SOCKRECV; typedef struct { OPDS h; /* 1 channel: ptr1=asig, ptr2=port, ptr3=buffnos */ /* 2 channel: ptr1=asigl, ptr2=asigr, ptr3=port, ptr4=buffnos */ STRINGDAT *ptr1; MYFLT *ptr2, *ptr3, *ptr4; AUXCH buffer, tmp; char *buf; int sock; volatile int threadon; int buffsize; int outsamps, rcvsamps; CSOUND *cs; void *thrid; void *cb; struct sockaddr_in server_addr; } SOCKRECVSTR; static int deinit_udpRecv(CSOUND *csound, void *pdata) { SOCKRECV *p = (SOCKRECV *) pdata; p->threadon = 0; csound->JoinThread(p->thrid); return OK; } static uintptr_t udpRecv(void *pdata) { struct sockaddr from; socklen_t clilen = sizeof(from); SOCKRECV *p = (SOCKRECV *) pdata; MYFLT *tmp = (MYFLT *) p->tmp.auxp; int bytes; CSOUND *csound = p->cs; while (p->threadon) { /* get the data from the socket and store it in a tmp buffer */ if ((bytes = recvfrom(p->sock, (void *)tmp, MTU, 0, &from, &clilen)) > 0) { csound->WriteCircularBuffer(csound, p->cb, tmp, bytes/sizeof(MYFLT)); } } return (uintptr_t) 0; } static int deinit_udpRecv_S(CSOUND *csound, void *pdata) { SOCKRECV *p = (SOCKRECV *) pdata; p->threadon = 0; csound->JoinThread(p->thrid); #ifndef WIN32 close(p->sock); csound->Message(csound, Str("OSCraw: Closing socket\n")); #else closesocket(p->sock); csound->Message(csound, Str("OSCraw: Closing socket\n")); #endif return OK; } static uintptr_t udpRecv_S(void *pdata) { struct sockaddr from; socklen_t clilen = sizeof(from); SOCKRECVSTR *p = (SOCKRECVSTR*) pdata; char *tmp = (char *) p->tmp.auxp; int bytes; CSOUND *csound = p->cs; while (p->threadon) { /* get the data from the socket and store it in a tmp buffer */ if ((bytes = recvfrom(p->sock, (void *)tmp, MTU, 0, &from, &clilen)) > 0) { bytes = (bytes+sizeof(MYFLT)-1)/sizeof(MYFLT); csound->WriteCircularBuffer(csound, p->cb, tmp, bytes); } } return (uintptr_t) 0; } /* UDP version one channel */ static int init_recv(CSOUND *csound, SOCKRECV *p) { MYFLT *buf; #if defined(WIN32) && !defined(__CYGWIN__) WSADATA wsaData = {0}; int err; if (UNLIKELY((err=WSAStartup(MAKEWORD(2,2), &wsaData))!= 0)) return csound->InitError(csound, Str("Winsock2 failed to start: %d"), err); #endif p->cs = csound; p->sock = socket(AF_INET, SOCK_DGRAM, 0); #ifndef WIN32 if (UNLIKELY(fcntl(p->sock, F_SETFL, O_NONBLOCK)<0)) return csound->InitError(csound, Str("Cannot set nonblock")); #else { u_long argp = 1; err = ioctlsocket(p->sock, FIONBIO, &argp); if (UNLIKELY(err != NO_ERROR)) return csound->InitError(csound, Str("Cannot set nonblock")); } #endif if (UNLIKELY(p->sock < 0)) { return csound->InitError(csound, Str("creating socket")); } /* create server address: where we want to send to and clear it out */ memset(&p->server_addr, 0, sizeof(p->server_addr)); p->server_addr.sin_family = AF_INET; /* it is an INET address */ p->server_addr.sin_addr.s_addr = htonl(INADDR_ANY); p->server_addr.sin_port = htons((int) *p->ptr2); /* the port */ /* associate the socket with the address and port */ if (UNLIKELY(bind(p->sock, (struct sockaddr *) &p->server_addr, sizeof(p->server_addr)) < 0)) return csound->InitError(csound, Str("bind failed")); if (p->buffer.auxp == NULL || (unsigned long) (MTU) > p->buffer.size) /* allocate space for the buffer */ csound->AuxAlloc(csound, MTU, &p->buffer); else { buf = (MYFLT *) p->buffer.auxp; /* make sure buffer is empty */ memset(buf, 0, MTU); } /* create a buffer to store the received interleaved audio data */ if (p->tmp.auxp == NULL || (long) p->tmp.size < MTU) /* allocate space for the buffer */ csound->AuxAlloc(csound, MTU, &p->tmp); else { buf = (MYFLT *) p->tmp.auxp; /* make sure buffer is empty */ memset(buf, 0, MTU); } p->buffsize = p->buffer.size/sizeof(MYFLT); p->cb = csound->CreateCircularBuffer(csound, *p->ptr3, sizeof(MYFLT)); /* create thread */ p->threadon = 1; p->thrid = csound->CreateThread(udpRecv, (void *) p); csound->RegisterDeinitCallback(csound, (void *) p, deinit_udpRecv); p->buf = p->buffer.auxp; p->outsamps = p->rcvsamps = 0; return OK; } /* UDP version for strings */ static int init_recv_S(CSOUND *csound, SOCKRECVSTR *p) { MYFLT *buf; #if defined(WIN32) && !defined(__CYGWIN__) WSADATA wsaData = {0}; int err; if (UNLIKELY((err=WSAStartup(MAKEWORD(2,2), &wsaData))!= 0)) return csound->InitError(csound, Str("Winsock2 failed to start: %d"), err); #endif p->cs = csound; p->sock = socket(AF_INET, SOCK_DGRAM, 0); #ifndef WIN32 if (UNLIKELY(fcntl(p->sock, F_SETFL, O_NONBLOCK)<0)) return csound->InitError(csound, Str("Cannot set nonblock")); #endif if (UNLIKELY(p->sock < 0)) { return csound->InitError(csound, Str("creating socket")); } /* create server address: where we want to send to and clear it out */ memset(&p->server_addr, 0, sizeof(p->server_addr)); p->server_addr.sin_family = AF_INET; /* it is an INET address */ p->server_addr.sin_addr.s_addr = htonl(INADDR_ANY); p->server_addr.sin_port = htons((int) *p->ptr2); /* the port */ /* associate the socket with the address and port */ if (UNLIKELY(bind(p->sock, (struct sockaddr *) &p->server_addr, sizeof(p->server_addr)) < 0)) return csound->InitError(csound, Str("bind failed")); if (p->buffer.auxp == NULL || (unsigned long) (MTU) > p->buffer.size) /* allocate space for the buffer */ csound->AuxAlloc(csound, MTU, &p->buffer); else { buf = (MYFLT *) p->buffer.auxp; /* make sure buffer is empty */ memset(buf, 0, MTU); } /* create a buffer to store the received string data */ if (p->tmp.auxp == NULL || (long) p->tmp.size < MTU) /* allocate space for the buffer */ csound->AuxAlloc(csound, MTU, &p->tmp); else { buf = (MYFLT *) p->tmp.auxp; /* make sure buffer is empty */ memset(buf, 0, MTU); } p->buffsize = p->buffer.size/sizeof(MYFLT); p->cb = csound->CreateCircularBuffer(csound, *p->ptr3, sizeof(MYFLT)); /* create thread */ p->threadon = 1; p->thrid = csound->CreateThread(udpRecv_S, (void *) p); csound->RegisterDeinitCallback(csound, (void *) p, deinit_udpRecv_S); p->buf = p->buffer.auxp; p->outsamps = p->rcvsamps = 0; return OK; } static int send_recv_k(CSOUND *csound, SOCKRECV *p) { MYFLT *ksig = p->ptr1; *ksig = FL(0.0); if (p->outsamps >= p->rcvsamps){ p->outsamps = 0; p->rcvsamps = csound->ReadCircularBuffer(csound, p->cb, p->buf, p->buffsize); } *ksig = p->buf[p->outsamps++]; return OK; } static int send_recv_S(CSOUND *csound, SOCKRECVSTR *p) { STRINGDAT *str = p->ptr1; int len; if (p->outsamps >= p->rcvsamps) { p->outsamps = 0; p->rcvsamps = csound->ReadCircularBuffer(csound, p->cb, p->buf, p->buffsize); } len = strlen(&p->buf[p->outsamps]); //printf("len %d ans %s\n", len, &p->buf[p->outsamps]); if (len>str->size) { /* ensure enough space for result */ str->data = csound->ReAlloc(csound, str->data, len+1); str->size = len; } strncpy(str->data, &p->buf[p->outsamps], len+1); p->outsamps += len+1; /* Move bffer on */ return OK; } static int send_recv(CSOUND *csound, SOCKRECV *p) { MYFLT *asig = p->ptr1; MYFLT *buf = p->buf; int i, nsmps = CS_KSMPS; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; int outsamps = p->outsamps, rcvsamps = p->rcvsamps; memset(asig, 0, sizeof(MYFLT)*nsmps); if (UNLIKELY(early)) nsmps -= early; for(i=offset; i < nsmps ; i++){ if (outsamps >= rcvsamps){ outsamps = 0; rcvsamps = csound->ReadCircularBuffer(csound, p->cb, buf, p->buffsize); } asig[i] = buf[outsamps]; outsamps++; } p->rcvsamps = rcvsamps; p->outsamps = outsamps; return OK; } /* UDP version two channel */ static int init_recvS(CSOUND *csound, SOCKRECV *p) { MYFLT *buf; #if defined(WIN32) && !defined(__CYGWIN__) WSADATA wsaData = {0}; int err; if ((err=WSAStartup(MAKEWORD(2,2), &wsaData))!= 0) return csound->InitError(csound, Str("Winsock2 failed to start: %d"), err); #endif p->cs = csound; p->sock = socket(AF_INET, SOCK_DGRAM, 0); #ifndef WIN32 if (UNLIKELY(fcntl(p->sock, F_SETFL, O_NONBLOCK)<0)) return csound->InitError(csound, Str("Cannot set nonblock")); #endif if (UNLIKELY(p->sock < 0)) { return csound->InitError(csound, Str("creating socket")); } /* create server address: where we want to send to and clear it out */ memset(&p->server_addr, 0, sizeof(p->server_addr)); p->server_addr.sin_family = AF_INET; /* it is an INET address */ p->server_addr.sin_addr.s_addr = htonl(INADDR_ANY); p->server_addr.sin_port = htons((int) *p->ptr3); /* the port */ /* associate the socket with the address and port */ if (UNLIKELY(bind(p->sock, (struct sockaddr *) &p->server_addr, sizeof(p->server_addr)) < 0)) return csound->InitError(csound, Str("bind failed")); if (p->buffer.auxp == NULL || (unsigned long) (MTU) > p->buffer.size) /* allocate space for the buffer */ csound->AuxAlloc(csound, MTU, &p->buffer); else { buf = (MYFLT *) p->buffer.auxp; /* make sure buffer is empty */ memset(buf, 0, MTU); } /* create a buffer to store the received interleaved audio data */ if (p->tmp.auxp == NULL || (long) p->tmp.size < MTU) /* allocate space for the buffer */ csound->AuxAlloc(csound, MTU, &p->tmp); else { buf = (MYFLT *) p->tmp.auxp; /* make sure buffer is empty */ memset(buf, 0, MTU); } p->cb = csound->CreateCircularBuffer(csound, *p->ptr4, sizeof(MYFLT)); /* create thread */ p->threadon = 1; p->thrid = csound->CreateThread(udpRecv, (void *) p); csound->RegisterDeinitCallback(csound, (void *) p, deinit_udpRecv); p->buf = p->buffer.auxp; p->outsamps = p->rcvsamps = 0; p->buffsize = p->buffer.size/sizeof(MYFLT); return OK; } static int send_recvS(CSOUND *csound, SOCKRECV *p) { MYFLT *asigl = p->ptr1; MYFLT *asigr = p->ptr2; MYFLT *buf = p->buf; int i, nsmps = CS_KSMPS; int outsamps = p->outsamps, rcvsamps = p->rcvsamps; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; memset(asigl, 0, sizeof(MYFLT)*nsmps); memset(asigr, 0, sizeof(MYFLT)*nsmps); if (UNLIKELY(early)) nsmps -= early; for(i=offset; i < nsmps ; i++){ if (outsamps >= rcvsamps){ outsamps = 0; rcvsamps = csound->ReadCircularBuffer(csound, p->cb, buf, p->buffsize); } asigl[i] = buf[outsamps++]; asigr[i] = buf[outsamps++]; } p->rcvsamps = rcvsamps; p->outsamps = outsamps; return OK; } /* TCP version */ static int init_srecv(CSOUND *csound, SOCKRECVT *p) { socklen_t clilen; #if defined(WIN32) && !defined(__CYGWIN__) WSADATA wsaData = {0}; int err; if ((err=WSAStartup(MAKEWORD(2,2), &wsaData))!= 0) return csound->InitError(csound, Str("Winsock2 failed to start: %d"), err); #endif /* create a STREAM (TCP) socket in the INET (IP) protocol */ p->sock = socket(PF_INET, SOCK_STREAM, 0); if (UNLIKELY(p->sock < 0)) { return csound->InitError(csound, Str("creating socket")); } /* create server address: where we want to connect to */ /* clear it out */ memset(&(p->server_addr), 0, sizeof(p->server_addr)); /* it is an INET address */ p->server_addr.sin_family = AF_INET; /* the server IP address, in network byte order */ #if defined(WIN32) && !defined(__CYGWIN__) p->server_addr.sin_addr.S_un.S_addr = inet_addr((const char *) p->ipaddress->data); #else inet_aton((const char *) p->ipaddress->data, &(p->server_addr.sin_addr)); #endif /* the port we are going to listen on, in network byte order */ p->server_addr.sin_port = htons((int) *p->port); /* associate the socket with the address and port */ if (UNLIKELY(bind (p->sock, (struct sockaddr *) &p->server_addr, sizeof(p->server_addr)) < 0)) { return csound->InitError(csound, Str("bind failed")); } /* start the socket listening for new connections -- may wait */ if (UNLIKELY(listen(p->sock, 5) < 0)) { return csound->InitError(csound, Str("listen failed")); } clilen = sizeof(p->server_addr); p->conn = accept(p->sock, (struct sockaddr *) &p->server_addr, &clilen); if (UNLIKELY(p->conn < 0)) { return csound->InitError(csound, Str("accept failed")); } return OK; } static int send_srecv(CSOUND *csound, SOCKRECVT *p) { int n = sizeof(MYFLT) * CS_KSMPS; if (UNLIKELY(n != read(p->conn, p->asig, sizeof(MYFLT) * CS_KSMPS))) { return csound->PerfError(csound, p->h.insdshead, Str("read from socket failed")); } return OK; } typedef struct _rawosc { OPDS h; ARRAYDAT *sout; MYFLT *kflag; MYFLT *port; AUXCH buffer; int sock; /* AUXCH tmp; volatile int threadon; CSOUND *cs; void *thrid; void *cb; */ struct sockaddr_in server_addr; } RAWOSC; static inline void tabensure(CSOUND *csound, ARRAYDAT *p, int size) { if (p->data==NULL || p->dimensions == 0 || (p->dimensions==1 && p->sizes[0] < size)) { size_t ss; if (p->data == NULL) { CS_VARIABLE* var = p->arrayType->createVariable(csound, NULL); p->arrayMemberSize = var->memBlockSize; } ss = p->arrayMemberSize*size; if (p->data==NULL) p->data = (MYFLT*)csound->Calloc(csound, ss); else p->data = (MYFLT*) csound->ReAlloc(csound, p->data, ss); p->dimensions = 1; p->sizes = (int*)csound->Malloc(csound, sizeof(int)); p->sizes[0] = size; } } static int destroy_raw_osc(CSOUND *csound, void *pp) { RAWOSC *p = (RAWOSC *) pp; #ifndef WIN32 close(p->sock); csound->Message(csound, Str("OSCraw: Closing socket\n")); #else closesocket(p->sock); csound->Message(csound, Str("OSCraw: Closing socket\n")); #endif return OK; } static int init_raw_osc(CSOUND *csound, RAWOSC *p) { MYFLT *buf; #if defined(WIN32) && !defined(__CYGWIN__) WSADATA wsaData = {0}; int err; if ((err=WSAStartup(MAKEWORD(2,2), &wsaData))!= 0) return csound->InitError(csound, Str("Winsock2 failed to start: %d"), err); #endif p->sock = socket(AF_INET, SOCK_DGRAM, 0); #ifndef WIN32 if (UNLIKELY(fcntl(p->sock, F_SETFL, O_NONBLOCK)<0)) return csound->InitError(csound, Str("Cannot set nonblock")); #else u_long nMode = 1; // 1: NON-BLOCKING if (ioctlsocket (p->sock, FIONBIO, &nMode) == SOCKET_ERROR) return csound->InitError(csound, Str("Cannot set nonblock")); #endif if (UNLIKELY(p->sock < 0)) { return csound->InitError(csound, Str("creating socket")); } /* create server address: where we want to send to and clear it out */ memset(&p->server_addr, 0, sizeof(p->server_addr)); p->server_addr.sin_family = AF_INET; /* it is an INET address */ p->server_addr.sin_addr.s_addr = htonl(INADDR_ANY); p->server_addr.sin_port = htons((int) *p->port); /* the port */ /* associate the socket with the address and port */ if (UNLIKELY(bind(p->sock, (struct sockaddr *) &p->server_addr, sizeof(p->server_addr)) < 0)) return csound->InitError(csound, Str("bind failed")); if (p->buffer.auxp == NULL || (unsigned long) (MTU) > p->buffer.size) /* allocate space for the buffer */ csound->AuxAlloc(csound, MTU, &p->buffer); else { buf = (MYFLT *) p->buffer.auxp; /* make sure buffer is empty */ memset(buf, 0, MTU); } csound->RegisterDeinitCallback(csound, (void *) p, destroy_raw_osc); tabensure(csound, p->sout,2); return OK; } static inline char le_test(){ union _le { char c[2]; short s; } le = {{0x0001}}; return le.c[0]; } static inline char *byteswap(char *p, int N){ if (le_test()) { char tmp; int j ; for(j = 0; j < N/2; j++) { tmp = p[j]; p[j] = p[N - j - 1]; p[N - j - 1] = tmp; } } return p; } static int perf_raw_osc(CSOUND *csound, RAWOSC *p) { ARRAYDAT *sout = p->sout; if (sout->sizes[0] < 2 || sout->dimensions > 1) return csound->PerfError(csound, p->h.insdshead, Str("output array too small\n")); STRINGDAT *str = (STRINGDAT *) p->sout->data; char *buf = (char *) p->buffer.auxp; int len = 0, n = 0, j = 1; char c; memset(buf, 0, p->buffer.size); uint32_t size = 0; char *types = NULL; struct sockaddr from; socklen_t clilen = sizeof(from); int bytes = recvfrom(p->sock, (void *)buf, MTU-1, 0, &from, &clilen); if (bytes < 0) bytes = 0; // terminating string to satisfy coverity buf[p->buffer.size-1] = '\0'; if (bytes) { if (strncmp(buf,"#bundle",7) == 0) { // bundle buf += 8; buf += 8; size = *((uint32_t *) buf); byteswap((char *)&size, 4); buf += 4; } else size = bytes; while(size > 0 && size < MTU) { /* get address & types */ if (n < sout->sizes[0]) { len = strlen(buf); // printf("len %d size %d incr %d\n", // len, str[n].size, ((size_t) ceil((len+1)/4.)*4)); if (len >= str[n].size) { str[n].data = csound->ReAlloc(csound, str[n].data, len+1); memset(str[n].data,0,len+1); str[n].size = len+1; } strncpy(str[n].data, buf, len); str[n].data[len] = '\0'; // explicitly terminate it. n++; buf += ((size_t) ceil((len+1)/4.)*4); } if (n < sout->sizes[0]) { len = strlen(buf); if (len >= str[n].size) { str[n].data = csound->ReAlloc(csound, str[n].data, len+1); str[n].size = len+1; } strncpy(str[n].data, buf, len); str[n].data[str[n].size-1] = '\0'; // explicitly terminate it. types = str[n].data; n++; buf += ((size_t) ceil((len+1)/4.)*4); } j = 1; // parse data while((c = types[j++]) != '\0' && n < sout->sizes[0]){ if (c == 'f') { float f = *((float *) buf); byteswap((char*)&f,4); if (str[n].size < 32) { str[n].data = csound->ReAlloc(csound, str[n].data, 32); str[n].size = 32; } snprintf(str[n].data, str[n].size, "%f", f); buf += 4; } else if (c == 'i') { int d = *((int32_t *) buf); byteswap((char*) &d,4); if (str[n].size < 32) { str[n].data = csound->ReAlloc(csound, str[n].data, 32); str[n].size = 32; } snprintf(str[n].data, str[n].size, "%d", d); buf += 4; } else if (c == 's') { len = strlen(buf); if (len > str[n].size) { str[n].data = csound->ReAlloc(csound, str[n].data, len+1); str[n].size = len+1; } strncpy(str[n].data, buf, len); str[n].data[len] = '\0'; len = ceil((len+1)/4.)*4; buf += len; } else if (c == 'b') { len = *((uint32_t *) buf); byteswap((char*)&len,4); len = ceil((len)/4.)*4; if (len > str[n].size) { str[n].data = csound->ReAlloc(csound, str[n].data, len+1); str[n].size = len+1; } strncpy(str[n].data, buf, len); str[n].data[len] = '\0'; buf += len; } n++; } size = *((uint32_t *) buf); byteswap((char *)&size, 4); buf += 4; } } *p->kflag = n; return OK; } #define S(x) sizeof(x) static OENTRY sockrecv_localops[] = { { "sockrecv", S(SOCKRECV), 0, 7, "s", "ii", (SUBR) init_recv, (SUBR) send_recv_k, (SUBR) send_recv, NULL }, { "sockrecv", S(SOCKRECVSTR), 0, 3, "S", "ii", (SUBR) init_recv_S, (SUBR) send_recv_S, NULL }, { "sockrecvs", S(SOCKRECV), 0, 5, "aa", "ii", (SUBR) init_recvS, NULL, (SUBR) send_recvS, NULL }, { "strecv", S(SOCKRECVT), 0, 5, "a", "Si", (SUBR) init_srecv, NULL, (SUBR) send_srecv, NULL }, { "OSCraw", S(RAWOSC), 0, 3, "S[]k", "i", (SUBR) init_raw_osc, (SUBR) perf_raw_osc, NULL, NULL} }; LINKAGE_BUILTIN(sockrecv_localops) csound-6.10.0/Opcodes/socksend.c000066400000000000000000000605401321653344700164570ustar00rootroot00000000000000/* socksend.c: Copyright (C) 2006 by John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include #if defined(WIN32) && !defined(__CYGWIN__) #include #else #include #include #include #include #endif #include #include #include extern int inet_aton(const char *cp, struct in_addr *inp); typedef struct { OPDS h; MYFLT *asig; STRINGDAT *ipaddress; MYFLT *port, *buffersize; MYFLT *format; AUXCH aux; int sock; int bsize, wp; int ff, bwidth; struct sockaddr_in server_addr; } SOCKSEND; typedef struct { OPDS h; STRINGDAT *str; STRINGDAT *ipaddress; MYFLT *port, *buffersize; MYFLT *format; AUXCH aux; int sock; int bsize, wp; int ff, bwidth; struct sockaddr_in server_addr; } SOCKSENDT; typedef struct { OPDS h; MYFLT *asigl, *asigr; STRINGDAT *ipaddress; MYFLT *port, *buffersize; MYFLT *format; AUXCH aux; int sock; int bsize, wp; int ff, bwidth; struct sockaddr_in server_addr; } SOCKSENDS; #define MTU (1456) /* UDP version one channel */ static int init_send(CSOUND *csound, SOCKSEND *p) { int bsize; int bwidth = sizeof(MYFLT); #if defined(WIN32) && !defined(__CYGWIN__) WSADATA wsaData = {0}; int err; if (UNLIKELY((err=WSAStartup(MAKEWORD(2,2), &wsaData))!= 0)) return csound->InitError(csound, Str("Winsock2 failed to start: %d"), err); #endif p->ff = (int)(*p->format); p->bsize = bsize = (int) *p->buffersize; /* if (UNLIKELY((sizeof(MYFLT) * bsize) > MTU)) { */ /* return csound->InitError(csound, Str("The buffersize must be <= %d samples " */ /* "to fit in a udp-packet."), */ /* (int) (MTU / sizeof(MYFLT))); */ /* } */ p->wp = 0; p->sock = socket(AF_INET, SOCK_DGRAM, 0); if (UNLIKELY(p->sock < 0)) { return csound->InitError(csound, Str("creating socket")); } /* create server address: where we want to send to and clear it out */ memset(&p->server_addr, 0, sizeof(p->server_addr)); p->server_addr.sin_family = AF_INET; /* it is an INET address */ #if defined(WIN32) && !defined(__CYGWIN__) p->server_addr.sin_addr.S_un.S_addr = inet_addr((const char *) p->ipaddress->data); #else inet_aton((const char *) p->ipaddress->data, &p->server_addr.sin_addr); /* the server IP address */ #endif p->server_addr.sin_port = htons((int) *p->port); /* the port */ if (p->ff) bwidth = sizeof(int16); /* create a buffer to write the interleaved audio to */ if (p->aux.auxp == NULL || (uint32_t) (bsize * bwidth) > p->aux.size) /* allocate space for the buffer */ csound->AuxAlloc(csound, (bsize * bwidth), &p->aux); else { memset(p->aux.auxp, 0, bwidth * bsize); } p->bwidth = bwidth; return OK; } static int send_send(CSOUND *csound, SOCKSEND *p) { const struct sockaddr *to = (const struct sockaddr *) (&p->server_addr); uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; int wp; int buffersize = p->bsize; MYFLT *asig = p->asig; MYFLT *out = (MYFLT *) p->aux.auxp; int16 *outs = (int16 *) p->aux.auxp; int ff = p->ff; if (UNLIKELY(early)) nsmps -= early; for (i = offset, wp = p->wp; i < nsmps; i++, wp++) { if (wp == buffersize) { /* send the package when we have a full buffer */ if (UNLIKELY(sendto(p->sock, (void*)out, buffersize * p->bwidth, 0, to, sizeof(p->server_addr)) < 0)) { return csound->PerfError(csound, p->h.insdshead, Str("sendto failed")); } wp = 0; } if (ff) { // Scale for 0dbfs and make LE int16 val = (int16)((32768.0*asig[i])/csound->e0dbfs); union cheat { char benchar[2]; int16 bensht; } ch; ch.benchar[0] = 0xFF & val; ch.benchar[1] = 0xFF & (val >> 8); outs[wp] = ch.bensht; } else out[wp] = asig[i]; } p->wp = wp; return OK; } static int send_send_k(CSOUND *csound, SOCKSEND *p) { const struct sockaddr *to = (const struct sockaddr *) (&p->server_addr); int buffersize = p->bsize; MYFLT *ksig = p->asig; MYFLT *out = (MYFLT *) p->aux.auxp; int16 *outs = (int16 *) p->aux.auxp; int ff = p->ff; if (p->wp == buffersize) { /* send the package when we have a full buffer */ if (UNLIKELY(sendto(p->sock, (void*)out, buffersize * p->bwidth, 0, to, sizeof(p->server_addr)) < 0)) { return csound->PerfError(csound, p->h.insdshead, Str("sendto failed")); } p->wp = 0; } if (ff) { // Scale for 0dbfs and make LE int16 val = (int16)((32768.0* (*ksig))/csound->e0dbfs); union cheat { char benchar[2]; int16 bensht; } ch; ch.benchar[0] = 0xFF & val; ch.benchar[1] = 0xFF & (val >> 8); outs[p->wp] = ch.bensht; } else out[p->wp++] = *ksig; return OK; } static int send_send_Str(CSOUND *csound, SOCKSENDT *p) { const struct sockaddr *to = (const struct sockaddr *) (&p->server_addr); int buffersize = p->bsize; char *out = (char *) p->aux.auxp; char *q = p->str->data; int len = p->str->size; if (UNLIKELY(len>=buffersize)) { csound->Warning(csound, Str("string truncated in socksend")); len = buffersize-1; } memcpy(out, q, len); memset(out+len, 0, buffersize-len); /* send the package with the string each time */ if (UNLIKELY(sendto(p->sock, (void*)out, buffersize, 0, to, sizeof(p->server_addr)) < 0)) { return csound->PerfError(csound, p->h.insdshead, Str("sendto failed")); } return OK; } /* UDP version 2 channels */ static int init_sendS(CSOUND *csound, SOCKSENDS *p) { int bsize; int bwidth = sizeof(MYFLT); #if defined(WIN32) && !defined(__CYGWIN__) WSADATA wsaData = {0}; int err; if (UNLIKELY((err=WSAStartup(MAKEWORD(2,2), &wsaData))!= 0)) return csound->InitError(csound, Str("Winsock2 failed to start: %d"), err); #endif p->ff = (int)(*p->format); p->bsize = bsize = (int) *p->buffersize; /* if (UNLIKELY((sizeof(MYFLT) * bsize) > MTU)) { */ /* return csound->InitError(csound, Str("The buffersize must be <= %d samples " */ /* "to fit in a udp-packet."), */ /* (int) (MTU / sizeof(MYFLT))); */ /* } */ p->wp = 0; p->sock = socket(AF_INET, SOCK_DGRAM, 0); if (UNLIKELY(p->sock < 0)) { return csound->InitError(csound, Str("creating socket")); } /* create server address: where we want to send to and clear it out */ memset(&p->server_addr, 0, sizeof(p->server_addr)); p->server_addr.sin_family = AF_INET; /* it is an INET address */ #if defined(WIN32) && !defined(__CYGWIN__) p->server_addr.sin_addr.S_un.S_addr = inet_addr((const char *) p->ipaddress->data); #else inet_aton((const char *) p->ipaddress->data, &p->server_addr.sin_addr); /* the server IP address */ #endif p->server_addr.sin_port = htons((int) *p->port); /* the port */ if (p->ff) bwidth = sizeof(int16); /* create a buffer to write the interleaved audio to */ if (p->aux.auxp == NULL || (uint32_t) (bsize * bwidth) > p->aux.size) /* allocate space for the buffer */ csound->AuxAlloc(csound, (bsize * bwidth), &p->aux); else { memset(p->aux.auxp, 0, bwidth * bsize); } p->bwidth = bwidth; return OK; } static int send_sendS(CSOUND *csound, SOCKSENDS *p) { const struct sockaddr *to = (const struct sockaddr *) (&p->server_addr); MYFLT *asigl = p->asigl; MYFLT *asigr = p->asigr; MYFLT *out = (MYFLT *) p->aux.auxp; int16 *outs = (int16 *) p->aux.auxp; int wp; int buffersize = p->bsize; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; int ff = p->ff; if (UNLIKELY(early)) nsmps -= early; /* store the samples of the channels interleaved in the packet */ /* (left, right) */ for (i = offset, wp = p->wp; i < nsmps; i++, wp += 2) { if (wp == buffersize) { /* send the package when we have a full buffer */ if (UNLIKELY(sendto(p->sock, (void*)out, buffersize * p->bwidth, 0, to, sizeof(p->server_addr)) < 0)) { return csound->PerfError(csound, p->h.insdshead, Str("sendto failed")); } wp = 0; } if (ff) { // Scale for 0dbfs and make LE int16 val = 0x8000*(asigl[i]/csound->e0dbfs); union { char benchar[2]; int16 bensht; } ch; ch.benchar[0] = 0xFF & val; ch.benchar[1] = 0xFF & (val >> 8); outs[wp] = ch.bensht; val = 0x8000*(asigl[i+1]/csound->e0dbfs); ch.benchar[0] = 0xFF & val; ch.benchar[1] = 0xFF & (val >> 8); outs[wp + 1] = ch.bensht; } else { out[wp] = asigl[i]; out[wp + 1] = asigr[i]; } } p->wp = wp; return OK; } /* TCP version */ static int init_ssend(CSOUND *csound, SOCKSEND *p) { #if defined(WIN32) && !defined(__CYGWIN__) WSADATA wsaData = {0}; int err; if (UNLIKELY((err=WSAStartup(MAKEWORD(2,2), &wsaData))!= 0)) return csound->InitError(csound, Str("Winsock2 failed to start: %d"), err); #endif /* create a STREAM (TCP) socket in the INET (IP) protocol */ p->sock = socket(PF_INET, SOCK_STREAM, 0); if (UNLIKELY(p->sock < 0)) { return csound->InitError(csound, Str("creating socket")); } /* create server address: where we want to connect to */ /* clear it out */ memset(&(p->server_addr), 0, sizeof(p->server_addr)); /* it is an INET address */ p->server_addr.sin_family = AF_INET; /* the server IP address, in network byte order */ #if defined(WIN32) && !defined(__CYGWIN__) p->server_addr.sin_addr.S_un.S_addr = inet_addr((const char *) p->ipaddress->data); #else inet_aton((const char *) p->ipaddress->data, &(p->server_addr.sin_addr)); #endif /* the port we are going to listen on, in network byte order */ p->server_addr.sin_port = htons((int) *p->port); again: if (UNLIKELY(connect(p->sock, (struct sockaddr *) &p->server_addr, sizeof(p->server_addr)) < 0)) { #ifdef ECONNREFUSED if (errno == ECONNREFUSED) goto again; #endif return csound->InitError(csound, Str("connect failed (%d)"), errno); } return OK; } static int send_ssend(CSOUND *csound, SOCKSEND *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; int32_t n = sizeof(MYFLT) * (CS_KSMPS-offset-early); if (UNLIKELY(n != write(p->sock, &p->asig[offset], n))) { csound->Message(csound, Str("Expected %d got %d\n"), (int) (sizeof(MYFLT) * CS_KSMPS), n); return csound->PerfError(csound, p->h.insdshead, Str("write to socket failed")); } return OK; } typedef struct { OPDS h; MYFLT *kwhen; STRINGDAT *ipaddress; MYFLT *port; /* UDP port */ STRINGDAT *dest; STRINGDAT *type; MYFLT *arg[32]; /* only 26 can be used, but add a few more for safety */ AUXCH aux; AUXCH types; int sock, iargs; MYFLT last; struct sockaddr_in server_addr; } OSCSEND2; static int osc_send2_init(CSOUND *csound, OSCSEND2 *p) { unsigned int bsize; if (UNLIKELY(p->INOCOUNT > 4 && p->INOCOUNT < (unsigned int) p->type->size + 4)) return csound->InitError(csound, Str("insufficient number of arguments for " "OSC message types\n")); #if defined(WIN32) && !defined(__CYGWIN__) WSADATA wsaData = {0}; int err; if (UNLIKELY((err=WSAStartup(MAKEWORD(2,2), &wsaData))!= 0)) return csound->InitError(csound, Str("Winsock2 failed to start: %d"), err); #endif p->sock = socket(AF_INET, SOCK_DGRAM, 0); if (UNLIKELY(p->sock < 0)) { return csound->InitError(csound, Str("creating socket")); } /* create server address: where we want to send to and clear it out */ memset(&p->server_addr, 0, sizeof(p->server_addr)); p->server_addr.sin_family = AF_INET; /* it is an INET address */ #if defined(WIN32) && !defined(__CYGWIN__) p->server_addr.sin_addr.S_un.S_addr = inet_addr((const char *) p->ipaddress->data); #else inet_aton((const char *) p->ipaddress->data, &p->server_addr.sin_addr); /* the server IP address */ #endif p->server_addr.sin_port = htons((int) *p->port); /* the port */ if(p->INCOUNT > 4) { if (p->types.auxp == NULL || strlen(p->type->data) > p->types.size) /* allocate space for the types buffer */ csound->AuxAlloc(csound, strlen(p->type->data), &p->types); memcpy(p->types.auxp, p->type->data, strlen(p->type->data)); // todo: parse type to allocate memory int i, iarg = 0; STRINGDAT *s; ARRAYDAT *ar; FUNC *ft; int j; bsize = 0; for(i=0; i < p->type->size-1; i++) { switch(p->type->data[i]){ case 't': if (UNLIKELY(p->INOCOUNT < (unsigned int) p->type->size + 5)) return csound->InitError(csound, "extra argument needed for type t\n"); bsize += 8; iarg+=2; break; case 'f': case 'i': case 'c': case 'm': bsize += 4; iarg++; break; case 's': if (UNLIKELY(!IS_STR_ARG(p->arg[i]))) return csound->InitError(csound, Str("expecting a string argument\n")); s = (STRINGDAT *)p->arg[i]; bsize += strlen(s->data) + 64; iarg++; break; case 'l': case 'h': /* OSC-accepted type name for 64bit int */ p->type->data[i] = 'h'; /* fall through */ case 'd': bsize += 8; iarg++; break; case 'b': case 'T': case 'F': case 'I': case 'N': iarg++; break; case 'a': bsize += (sizeof(MYFLT)*CS_KSMPS); iarg++; break; case 'G': ft = csound->FTnp2Find(csound, p->arg[i]); bsize += (sizeof(MYFLT)*ft->flen); iarg++; break; case 'A': case 'D': ar = (ARRAYDAT *) p->arg[i]; for(j=0; j < ar->dimensions; j++) bsize += (sizeof(MYFLT)*ar->sizes[j]); bsize += 12; iarg++; break; default: return csound->InitError(csound, Str("%c: data type not supported\n"), p->type->data[i]); } } bsize += (strlen(p->dest->data) + strlen(p->type->data) + 11); bsize *= 2; if (p->aux.auxp == NULL || bsize > p->aux.size) /* allocate space for the buffer */ csound->AuxAlloc(csound, bsize, &p->aux); else { memset(p->aux.auxp, 0, bsize); } p->iargs = iarg; } else { bsize = strlen(p->dest->data)+1; bsize = ceil(bsize/4.)*4;; if (p->aux.auxp == NULL || bsize > p->aux.size) /* allocate space for the buffer */ csound->AuxAlloc(csound, bsize, &p->aux); else { memset(p->aux.auxp, 0, bsize); } } p->last = FL(0.0); return OK; } static inline char le_test(){ union _le { char c[2]; short s; } le = {{0x0001}}; return le.c[0]; } static inline char *byteswap(char *p, int N){ if(le_test()) { char tmp; int j ; for(j = 0; j < N/2; j++) { tmp = p[j]; p[j] = p[N - j - 1]; p[N - j - 1] = tmp; } } return p; } static inline int aux_realloc(CSOUND *csound, size_t size, AUXCH *aux) { char *p = aux->auxp; aux->auxp = csound->ReAlloc(csound, p, size); aux->size = size; aux->endp = (char*)aux->auxp + size; return size; } static int osc_send2(CSOUND *csound, OSCSEND2 *p) { if(*p->kwhen != p->last) { const struct sockaddr *to = (const struct sockaddr *) (&p->server_addr); int buffersize = 0, size, i, bsize = p->aux.size; char *out = (char *) p->aux.auxp; memset(out,0,bsize); /* package destination in 4-byte zero-padded block */ size = strlen(p->dest->data)+1; memcpy(out,p->dest->data,size); size = ceil(size/4.)*4; buffersize += size; if(p->INCOUNT > 4) { /* package type in a 4-byte zero-padded block; add a comma to the beginning of the type string. */ out[buffersize] = ','; size = strlen(p->type->data)+1; /* check for b type before copying */ for(i = 0; i < p->iargs; i++) { if(p->type->data[i] == 'b') { if(*p->arg[i] == FL(0.0)) ((char *)p->types.auxp)[i] = 'F'; else ((char *)p->types.auxp)[i] = 'T'; } else if(p->type->data[i] == 'D' || p->type->data[i] == 'A' || p->type->data[i] == 'G' || p->type->data[i] == 'a') ((char *)p->types.auxp)[i] = 'b'; } memcpy(out+buffersize+1,p->types.auxp,size-1); size = ceil((size+1)/4.)*4; buffersize += size; /* add data to message */ float fdata; double ddata; MYFLT mdata; int data; int64_t ldata; uint64_t udata; STRINGDAT *s; ARRAYDAT *ar; FUNC *ft; int j; for(i = 0; i < p->iargs; i++) { switch(p->type->data[i]){ case 'f': /* realloc if necessary */ if(buffersize + 4 > bsize) { aux_realloc(csound, buffersize + 128, &p->aux); out = (char *) p->aux.auxp; bsize = p->aux.size; } fdata = (float) *p->arg[i]; byteswap((char *) &fdata, 4); memcpy(out+buffersize,&fdata, 4); buffersize += 4; break; case 'd': /* realloc if necessary */ if(buffersize + 8 > bsize) { aux_realloc(csound, buffersize + 128, &p->aux); out = (char *) p->aux.auxp; bsize = p->aux.size; } ddata = *p->arg[i]; byteswap((char *) &ddata, 8); memcpy(out+buffersize,&ddata, 8); buffersize += 8; break; case 't': /* realloc if necessary */ if(buffersize + 4 > bsize) { aux_realloc(csound, buffersize + 128, &p->aux); out = (char *) p->aux.auxp; bsize = p->aux.size; } udata = (uint64_t) MYFLT2LRND(*p->arg[i++]); udata <<= 4; udata |= (uint64_t) MYFLT2LRND(*p->arg[i++]); byteswap((char *) &udata, 8); memcpy(out+buffersize,&udata, 8); buffersize += 8; break; case 'i': case 'm': case 'c': /* realloc if necessary */ if(buffersize + 4 > bsize) { aux_realloc(csound, buffersize + 128, &p->aux); out = (char *) p->aux.auxp; bsize = p->aux.size; } data = MYFLT2LRND(*p->arg[i]); byteswap((char *) &data, 4); memcpy(out+buffersize,&data, 4); buffersize += 4; break; case 'h': /* realloc if necessary */ if(buffersize + 8 > bsize) { aux_realloc(csound, buffersize + 128, &p->aux); out = (char *) p->aux.auxp; bsize = p->aux.size; } ldata = (int64_t) (*p->arg[i]+0.5); byteswap((char *) &ldata, 8); memcpy(out+buffersize,&ldata, 8); buffersize += 8; break; case 's': s = (STRINGDAT *)p->arg[i]; size = strlen(s->data)+1; size = ceil(size/4.)*4; /* realloc if necessary */ if(buffersize + size > bsize) { aux_realloc(csound, buffersize + size + 128, &p->aux); out = (char *) p->aux.auxp; bsize = p->aux.size; } memcpy(out+buffersize, s->data, s->size); buffersize += size; break; case 'G': ft = csound->FTnp2Find(csound, p->arg[i]); size = (int32_t)(sizeof(MYFLT)*ft->flen); if(buffersize + size + 4 > bsize) { aux_realloc(csound, buffersize + size + 128, &p->aux); out = (char *) p->aux.auxp; bsize = p->aux.size; } data = size; byteswap((char *)&data,4); memcpy(out+buffersize,&data,4); buffersize += 4; memcpy(out+buffersize,ft->ftable,size); buffersize += size; break; case 'A': ar = (ARRAYDAT *) p->arg[i]; size = 0; for(j=0; j < ar->dimensions; j++) { size += (int32_t)ar->sizes[j]*sizeof(MYFLT); } if(buffersize + size + 12 > bsize) { aux_realloc(csound, buffersize + size + 128, &p->aux); out = (char *) p->aux.auxp; bsize = p->aux.size; } data = size + 8; byteswap((char *)&data,4); memcpy(out+buffersize,&data,4); buffersize += 4; memcpy(out+buffersize,&(ar->dimensions),4); buffersize += 4; memcpy(out+buffersize,&ar->sizes[0],ar->dimensions*4); buffersize += ar->dimensions*4; memcpy(out+buffersize,ar->data,size); buffersize += size; break; case 'D': ar = (ARRAYDAT *) p->arg[i]; size = 0; for(j=0; j < ar->dimensions; j++) { size += (int32_t)ar->sizes[j]*sizeof(MYFLT); } if(buffersize + size + 12 > bsize) { aux_realloc(csound, buffersize + size + 128, &p->aux); out = (char *) p->aux.auxp; bsize = p->aux.size; } data = size; byteswap((char *)&data,4); memcpy(out+buffersize,&data,4); buffersize += 4; memcpy(out+buffersize,ar->data,size); buffersize += size; break; case 'a': size = (int32_t) (CS_KSMPS+1)*sizeof(MYFLT); if(buffersize + size + 4 > bsize) { aux_realloc(csound, buffersize + size + 128, &p->aux); out = (char *) p->aux.auxp; bsize = p->aux.size; } data = size; byteswap((char *)&data,4); memcpy(out+buffersize,&data,4); buffersize += 4; mdata = CS_KSMPS; memcpy(out+buffersize,&mdata,sizeof(MYFLT)); memcpy(out+buffersize+sizeof(MYFLT),p->arg[i],CS_KSMPS*sizeof(MYFLT)); buffersize += size; break; case 'T': case 'F': case 'I': case 'N': default: break; } } } if (UNLIKELY(sendto(p->sock, (void*)out, buffersize, 0, to, sizeof(p->server_addr)) < 0)) { return csound->PerfError(csound, p->h.insdshead, Str("OSCsend2 failed")); } p->last = *p->kwhen; } return OK; } #define S(x) sizeof(x) static OENTRY socksend_localops[] = { { "socksend.a", S(SOCKSEND), 0, 5, "", "aSiio", (SUBR) init_send, NULL, (SUBR) send_send }, { "socksend.k", S(SOCKSEND), 0, 3, "", "kSiio", (SUBR) init_send, (SUBR) send_send_k, NULL }, { "socksend.S", S(SOCKSENDT), 0, 3, "", "SSiio", (SUBR) init_send, (SUBR) send_send_Str, NULL }, { "socksends", S(SOCKSENDS), 0, 5, "", "aaSiio", (SUBR) init_sendS, NULL, (SUBR) send_sendS }, { "stsend", S(SOCKSEND), 0, 5, "", "aSi", (SUBR) init_ssend, NULL, (SUBR) send_ssend }, { "OSCsend", S(OSCSEND2), 0, 3, "", "kSk*", (SUBR)osc_send2_init, (SUBR)osc_send2 } }; LINKAGE_BUILTIN(socksend_localops) csound-6.10.0/Opcodes/space.c000066400000000000000000000174631321653344700157470ustar00rootroot00000000000000/* space.c: Copyright (C) 1998 Richard Karpen This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /******************************************/ /* The applications in this file were */ /* designed and coded by Richard Karpen */ /* University of Washington, Seattle 1998 */ /******************************************/ #include "stdopcod.h" #include "space.h" #include #define RESOLUTION 100 static int spaceset(CSOUND *csound, SPACE *p) { STDOPCOD_GLOBALS *pp; FUNC *ftp = NULL; if (*p->ifn > 0) { if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) == NULL)) return NOTOK; p->ftp = ftp; } if (p->auxch.auxp == NULL || p->auxch.sizeAuxAlloc(csound, (size_t) (CS_KSMPS * 4) * sizeof(MYFLT), &p->auxch); fltp = (MYFLT *) p->auxch.auxp; p->rrev1 = fltp; fltp += CS_KSMPS; p->rrev2 = fltp; fltp += CS_KSMPS; p->rrev3 = fltp; fltp += CS_KSMPS; p->rrev4 = fltp; fltp += CS_KSMPS; } pp = (STDOPCOD_GLOBALS*) csound->stdOp_Env; pp->spaceaddr = (void*) p; return OK; } static int space(CSOUND *csound, SPACE *p) { MYFLT *r1, *r2, *r3, *r4, *sigp, ch1, ch2, ch3, ch4; MYFLT distance=FL(1.0), distr, distrsq, direct; MYFLT *rrev1, *rrev2, *rrev3, *rrev4; MYFLT torev, localrev, globalrev; MYFLT xndx, yndx; MYFLT half_pi = FL(0.5)*PI_F; MYFLT sqrt2 = SQRT(FL(2.0)); MYFLT fabxndx, fabyndx; FUNC *ftp; int32 indx, length, halflen; MYFLT v1, v2, fract, ndx; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT revb = *p->reverbamount; if (*p->ifn > 0) { /* get xy vals from function table */ if (UNLIKELY((ftp = p->ftp) == NULL)) goto err1; ndx = *p->time * RESOLUTION; /* when data is res. frames/second */ length = ftp->flen; halflen = (int32)(length * FL(0.5)); indx = (int32) floor(ndx); fract = ndx - indx; if (ndx > (halflen-1)) { indx = halflen - 1; fract = FL(0.0); } else if (ndx < 0) { indx = 0L; fract = FL(0.0); } v1 = *(ftp->ftable + (indx*2)); v2 = *(ftp->ftable + (indx*2) + 2); xndx = v1 + (v2 - v1) * fract; v1 = *(ftp->ftable + (indx*2) + 1); v2 = *(ftp->ftable + (indx*2) + 3); yndx = v1 + (v2 - v1) * fract; } else { /* get xy vals from input arguments */ xndx = *p->kx; yndx = *p->ky; } distance = HYPOT(xndx, yndx); fabxndx = FABS(xndx); fabyndx = FABS(yndx); if ((fabxndx > FL(1.0)) || (fabyndx > FL(1.0))) { if (fabxndx > fabyndx) { xndx = xndx/fabxndx; yndx = yndx/fabxndx; /* distance = fabxndx; */ } else { xndx = xndx/fabyndx; yndx = yndx/fabyndx; /* distance = fabyndx; */ } } if (UNLIKELY(distance < FL(1.0))) distance = FL(1.0); distr=(FL(1.0) / distance); distrsq = FL(1.0)/SQRT(distance); xndx = (xndx+FL(1.0))*FL(0.5); yndx = (yndx+FL(1.0))*FL(0.5); ch2 = SIN(half_pi * xndx) * SIN(half_pi * yndx) * sqrt2; ch4 = SIN(half_pi * xndx) * SIN(half_pi * (FL(1.0)-yndx)) * sqrt2; ch1 = SIN(half_pi * (FL(1.0)-xndx)) * SIN(half_pi * yndx) * sqrt2; ch3 = SIN(half_pi * (FL(1.0)-xndx)) * SIN(half_pi * (FL(1.0)-yndx)) * sqrt2; r1 = p->r1; r2 = p->r2; r3 = p->r3; r4 = p->r4; rrev1 = p->rrev1; rrev2 = p->rrev2; rrev3 = p->rrev3; rrev4 = p->rrev4; sigp = p->asig; if (UNLIKELY(offset)) { memset(r1, '\0', offset*sizeof(MYFLT)); memset(r2, '\0', offset*sizeof(MYFLT)); memset(r3, '\0', offset*sizeof(MYFLT)); memset(r4, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&r1[nsmps], '\0', early*sizeof(MYFLT)); memset(&r2[nsmps], '\0', early*sizeof(MYFLT)); memset(&r3[nsmps], '\0', early*sizeof(MYFLT)); memset(&r4[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nPerfError(csound, p->h.insdshead, Str("space: not initialised")); } static int spsendset(CSOUND *csound, SPSEND *p) { STDOPCOD_GLOBALS *pp; pp = (STDOPCOD_GLOBALS*) csound->stdOp_Env; p->space = (SPACE*) pp->spaceaddr; return OK; } static int spsend(CSOUND *csound, SPSEND *p) { SPACE *q = p->space; int nbytes = CS_KSMPS*sizeof(MYFLT); memmove(p->r1, q->rrev1, nbytes); memmove(p->r2, q->rrev2, nbytes); memmove(p->r3, q->rrev3, nbytes); memmove(p->r4, q->rrev4, nbytes); return OK; } static int spdistset(CSOUND *csound, SPDIST *p) { FUNC *ftp; if (*p->ifn > 0) { if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) == NULL)) return NOTOK; p->ftp = ftp; } return OK; } static int spdist(CSOUND *csound, SPDIST *p) { MYFLT *r; MYFLT distance, xndx, yndx; FUNC *ftp; int32 indx, length, halflen; MYFLT v1, v2, fract, ndx; r = p->r; if (*p->ifn > 0) { if (UNLIKELY((ftp = p->ftp)==NULL)) goto err1; ndx = *p->time * RESOLUTION; /* when data is 10 frames/second */ length = ftp->flen; halflen = (int32)(length * FL(0.5)); indx = (int32) floor(ndx); fract = ndx - indx; if (ndx > (halflen-1)) { indx = halflen - 1; fract = FL(0.0); } else if (ndx < 0) { indx = 0L; fract = FL(0.0); } v1 = *(ftp->ftable + (indx+indx)); v2 = *(ftp->ftable + (indx+indx) + 2); xndx = v1 + (v2 - v1) * fract; v1 = *(ftp->ftable + (indx+indx) + 1); v2 = *(ftp->ftable + (indx+indx) + 3); yndx = v1 + (v2 - v1) * fract; } else { /* get xy vals from input arguments */ xndx = *p->kx; yndx = *p->ky; } distance = HYPOT(xndx,yndx); if (distance < FL(1.0)) distance = FL(1.0); *r=distance; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("spdist: not initialised")); } #define S(x) sizeof(x) static OENTRY localops[] = { { "space", S(SPACE), TR,5, "aaaa", "aikkkk",(SUBR)spaceset, NULL, (SUBR)space }, { "spsend", S(SPSEND), 0,5, "aaaa", "", (SUBR)spsendset, NULL, (SUBR)spsend }, { "spdist", S(SPDIST), 0,3, "k", "ikkk", (SUBR)spdistset, (SUBR)spdist, NULL } }; int space_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/space.h000066400000000000000000000027451321653344700157510ustar00rootroot00000000000000/* space.h: Copyright (C) 1998 Richard Karpen This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /******************************************/ /* The applications in this file were */ /* designed and coded by Richard Karpen */ /* University of Washington, Seattle 1998 */ /******************************************/ #include "stdopcod.h" typedef struct { OPDS h; MYFLT *r1, *r2, *r3, *r4, *asig, *ifn, *time, *reverbamount, *kx, *ky; MYFLT ch1, ch2, ch3, ch4; FUNC *ftp; AUXCH auxch; MYFLT *rrev1, *rrev2, *rrev3, *rrev4; } SPACE; typedef struct { OPDS h; MYFLT *r1, *r2, *r3, *r4; SPACE *space; } SPSEND; typedef struct { OPDS h; MYFLT *r, *ifn, *time, *kx, *ky; FUNC *ftp; } SPDIST; csound-6.10.0/Opcodes/spat3d.c000066400000000000000000000775301321653344700160530ustar00rootroot00000000000000/* spat3d.c: Copyright (C) 2001 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* ----- spat3d, spat3di, and spat3dt -- written by Istvan Varga, 2001 ----- */ #include "stdopcod.h" #include #include #include #include #define CSOUND_SPAT3D_C 1 #include "spat3d.h" /* ----------------------- initialisation functions ------------------------ */ /* initialise FIR filter for downsampling */ static int spat3d_init_window(CSOUND *csound, SPAT3D *p) { int i, j, o; double d, w; o = p->oversamp << 5; /* window size = 32 * oversample */ i = ((o + 1) * (sizeof(int) + sizeof(MYFLT))); /* allocate */ if ((p->fltr.auxp == NULL) || (p->fltr.size < (unsigned int)i)) /* space */ csound->AuxAlloc(csound, i, &(p->fltr)); p->sample = (int *) p->fltr.auxp; /* sample number */ p->window = (MYFLT *) (p->sample + o + 1); /* window value */ for (i = -(o >> 1), j = 0; i < (o >> 1); i++) { if (i == 0) { d = 1.0; } else { w = cos(PI * (d = (double) i) / (double) o); d *= PI / (double) (p->oversamp); d = w * w * sin(d) / d; } if (fabs(d) > 0.00000001) { /* skip zero samples */ p->window[j] = (MYFLT) d; /* window value */ p->sample[j++] = i; /* sample number */ } } p->sample[j] = -10000; /* end of window */ return OK; } /* initialise parameric equalizer (code taken from pareq opcode) */ static int spat3d_init_eq(CSOUND *csound, SPAT3D_WALL *wstruct, MYFLT *ftable) { int eqmode; double omega, k, kk, vk, vkk, vkdq, sq, a0, a1, a2, b0, b1, b2; /* EQ code taken from biquad.c */ eqmode = (int) ((double) ftable[3] + 0.5); /* mode */ omega = (double) ftable[0] * (double) csound->tpidsr; /* frequency */ sq = sqrt(2.0 * (double) ftable[1]); /* level */ k = tan((eqmode > 1 ? (PI - omega) : omega) * 0.5); kk = k * k; vk = (double) ftable[1] * k; vkk = (double) ftable[1] * kk; vkdq = vk / (double) ftable[2]; /* Q */ if (eqmode >= 1) { b0 = 1.0 + sq * k + vkk; b1 = 2.0 * (vkk - 1.0); b2 = 1.0 - sq * k + vkk; } else { b0 = 1.0 + vkdq + kk; b1 = 2.0 * (kk - 1.0); b2 = 1.0 - vkdq + kk; } a0 = 1.0 + (k / (double) ftable[2]) + kk; a1 = 2.0 * (kk - 1.0); a2 = 1.0 - (k / (double) ftable[2]) + kk; if (eqmode > 1) { a1 = -a1; b1 = -b1; } a0 = 1.0 / a0; wstruct->a1 = (MYFLT) (a0 * a1); wstruct->a2 = (MYFLT) (a0 * a2); wstruct->b0 = (MYFLT) (a0 * b0); wstruct->b1 = (MYFLT) (a0 * b1); wstruct->b2 = (MYFLT) (a0 * b2); return OK; } /* initialise wall structures */ static SPAT3D_WALL* spat3d_init_wall(SPAT3D *p, /* opcode struct */ int wallno, /* wall number */ int dep, /* recursion depth */ int32 *wmax, /* wall structure number */ MYFLT X, MYFLT Y, MYFLT Z) /* coordinates (spat3di/spat3dt) */ { int i; SPAT3D_WALL *ws; MYFLT *ft, a, d, w, x, y, z; double d0, d1; CSOUND *csound = p->h.insdshead->csound; /* update random seed */ p->rseed = (15625L * p->rseed + 1L) & 0xFFFFL; /* select wall structure and output buffer */ ws = (SPAT3D_WALL *) p->ws.auxp + (*wmax)++; ws->yn = (MYFLT *) p->y.auxp + (p->bs * dep++); /* ftable */ if ((wallno == 0) || (p->ftable == NULL)) { ft = NULL; } else { ft = p->ftable + (wallno << 3) - 2; } /* initialise wall structure */ for (i = 0; i < 6; i++) ws->nextRefl[i] = NULL; ws->xnm1 = ws->xnm2 = ws->ynm1 = ws->ynm2 = FL(0.0); ws->a1 = ws->b1 = ws->a2 = ws->b2 = FL(0.0); ws->b0 = FL(1.0); ws->Xc = ws->W0 = ws->X0 = ws->Y0 = ws->Z0 = FL(0.0); ws->D0 = ws->D1 = 0.0; /* D0 and D1 are doubles */ ws->init = 1; ws->cnum = -1; /* read wall parameters from ftable */ if (ft != NULL) { spat3d_init_eq(csound, ws, ft + 4); /* EQ */ a = -ft[3]; /* scale */ ws->b0 *= a; ws->b1 *= a; ws->b2 *= a; /* apply scale to EQ */ ws->cnum = (6 - wallno) >> 1; /* select wall */ w = ft[1]; /* wall distance */ x = ft[2]; /* randomize */ x *= ((MYFLT) p->rseed - FL(32767.5)) / FL(32767.5); w *= (x + FL(1.0)) * (wallno & 1 ? FL(2.0) : FL(-2.0)); ws->Xc = w; /* coord. offset */ } /* convert coordinates (spat3di, and spat3dt) */ if (p->o_num != 1) { switch (ws->cnum) { /* new coordinates */ case 0: X = ws->Xc - X; break; case 1: Y = ws->Xc - Y; break; case 2: Z = ws->Xc - Z; break; } if (p->zout < 4) { /* convert coord. */ d = SPAT3D_XYZ2DIST(X, Y, Z); /* distance */ d0 = d1 = (double) SPAT3D_DIST2DEL(d); /* delay */ a = SPAT3D_DIST2AMP(d); /* amp. */ d = FL(1.0) / (d > p->mdist ? d : p->mdist); w = x = y = z = FL(0.0); switch (p->zout) { case 3: z = Z * d; w += z*z; z *= a; /* Z */ case 2: x = Y * d; w += x*x; x *= a; /* X */ case 1: y = -X * d; w += y*y; y *= a; /* Y */ } w = a - FL(0.293) * w * a; /* W */ } else { x = X - p->mdist * FL(0.5); /* right channel */ d = SPAT3D_XYZ2DIST(x, Y, Z); /* distance */ d1 = (double) SPAT3D_DIST2DEL(d); /* delay */ a = SPAT3D_DIST2AMP(d); /* amp. */ z = (MYFLT) sqrt(1.0 + (double) (x / (d + FL(0.0001)))); z *= a; y = a - z; /* Rh, Rl */ x += p->mdist; /* left channel */ d = SPAT3D_XYZ2DIST(x, Y, Z); /* distance */ d0 = (double) SPAT3D_DIST2DEL(d); /* delay */ a = SPAT3D_DIST2AMP(d); /* amp. */ x = (MYFLT) sqrt(1.0 - (double) (x / (d + FL(0.0001)))); x *= a; w = a - x; /* Lh, Ll */ } if (dep <= p->mindep) { w = x = y = z = FL(0.0); d0 = d1 = 0.0; } /* extend delay buffer */ if ((MYFLT) d0 > p->mdel) p->mdel = (MYFLT) d0; if ((MYFLT) d1 > p->mdel) p->mdel = (MYFLT) d1; ws->D0 = d0 * (double) CS_ESR + 0.5; ws->D1 = d1 * (double) CS_ESR + 0.5; ws->W0 = w; ws->X0 = x; ws->Y0 = y; ws->Z0 = z; } /* return if there are no more reflections */ if ((dep > p->maxdep) || (p->ftable == NULL)) return ws; /* next reflections */ for (i = 1; i <= 6; i++) if ((p->ftable[(i << 3) - 2] > FL(0.5)) && ((i > wallno) || ((i == (wallno - 1)) && (i & 1)))) ws->nextRefl[i - 1] = spat3d_init_wall(p, i, dep, wmax, X, Y, Z); return ws; /* return pointer to new wall structure */ } /* allocate space for delay buffers */ static int spat3d_init_delay(CSOUND *csound, SPAT3D *p) { int32 i, j; i = ((int32) (p->mdel * CS_ESR) + (int32) CS_KSMPS + 34L) * (int32) p->oversamp; p->mdel_s = i; if (p->o_num == 1) i += 4; /* extra samples for spat3d */ j = i * (int32) sizeof(MYFLT) * (int32) (p->zout > 3 ? 4 : p->zout + 1); if ((p->del.auxp == NULL) || (p->del.size < (unsigned int)j)) /* allocate */ csound->AuxAlloc(csound, j, &(p->del)); /* space */ p->Wb = (MYFLT *) p->del.auxp; /* W */ if (p->zout > 0) p->Yb = p->Wb + i; /* Y */ if (p->zout > 1) p->Xb = p->Yb + i; /* X */ if (p->zout > 2) p->Zb = p->Xb + i; /* Z */ for (j = 0; j < i; j++) { switch (p->zout) { /* clear buffers */ case 4: case 3: p->Zb[j] = FL(0.0); case 2: p->Xb[j] = FL(0.0); case 1: p->Yb[j] = FL(0.0); case 0: p->Wb[j] = FL(0.0); } } if (p->o_num == 1) { switch (p->zout) { case 4: case 3: (p->Zb)++; /* spat3d requires 1 */ case 2: (p->Xb)++; /* extra sample before */ case 1: (p->Yb)++; /* and 3 samples after */ case 0: (p->Wb)++; /* the delay buffer */ } } return OK; } /* count reflections */ static void spat3d_count_refl(int32 *cnt, int *md, int d, int mdep, int w, int wm) { int j; (*cnt)++; /* update count */ if (++d > *md) *md = d; /* md is the max. depth reached + 1 */ if (d > mdep) return; /* mdep is the max. depth allowed */ for (j = 32; j; j >>= 1) /* new reflections */ if ((wm & j) && ((j > w) || ((j == (w >> 1)) && (j & 21)))) spat3d_count_refl(cnt, md, d, mdep, j, wm); } /* initialise opcode structure */ static int spat3d_set_opcode_params(CSOUND *csound, SPAT3D *p) { int xidist, xift, ximode, ximdel, xiovr, xirlen, xioutft; int d, wmask; int32 i; /* default settings */ p->ftable = p->outft = NULL; /* no ftables */ p->zout = p->rseed = p->mindep = p->maxdep = p->outftlnth = wmask = 0; p->oversamp = 1; /* oversample */ p->bs = (int) CS_KSMPS; /* block size */ p->irlen = 2; /* IR length */ p->mdist = p->mdel = FL(0.001); /* unit circle dist., max. delay */ p->mdel_s = p->del_p = 0L; p->Wb = p->Xb = p->Yb = p->Zb = NULL; /* select opcode */ xidist = xift = ximode = ximdel = xiovr = xirlen = xioutft = -1; switch (p->o_num) { case 1: ximdel = 11; xiovr = 12; /* spat3d */ case 0: xidist = 8; xift = 9; ximode = 10; /* spat3di */ break; case 2: xidist = 4; xift = 5; ximode = 6; /* spat3dt */ xirlen = 7; xioutft = 0; break; } /* read opcode args */ if (ximode >= 0) /* output mode */ p->zout = (int) MYFLT2LRND(*(p->args[ximode])); if (xidist >= 0) /* unit circle dist. */ p->mdist = *(p->args[xidist]); if (xift >= 0) { /* ftable */ int fLen; fLen = csoundGetTable(csound, &(p->ftable), (int) *(p->args[xift])); if (fLen < 53) p->ftable = NULL; } if (ximdel >= 0) /* max. delay */ p->mdel = *(p->args[ximdel]); if (xiovr >= 0) /* oversample */ p->oversamp = (int) MYFLT2LRND(*(p->args[xiovr])); if (xirlen >= 0) /* IR length */ p->irlen = (int) MYFLT2LRND(*(p->args[xirlen]) * CS_ESR); if (xioutft >= 0) { /* output table */ int fLen; fLen = csoundGetTable(csound, &(p->outft), (int) *(p->args[xioutft])); if (fLen < 1) { p->outft = NULL; p->outftlnth = 0; } else p->outftlnth = fLen; } /* get parameters from ftable */ if (p->ftable != NULL) { if (p->o_num == 2) { /* min, max depth */ p->mindep = (int) MYFLT2LRND(p->ftable[0]) + 1; p->maxdep = (int) MYFLT2LRND(p->ftable[1]); } else { p->mindep = 0; p->maxdep = (int) MYFLT2LRND(p->ftable[0]); } if (p->ftable[2] >= FL(0.0)) /* max. delay */ p->mdel = p->ftable[2]; if (p->ftable[3] >= FL(0.0)) /* IR length */ p->irlen = (int) MYFLT2LRND(p->ftable[3] * CS_ESR); if (p->ftable[4] >= FL(0.0)) /* unit circle dist. */ p->mdist = p->ftable[4]; p->rseed = (int32) MYFLT2LRND(p->ftable[5]); /* seed */ if (p->rseed < 0L) p->rseed = (int32) csound->GetRandomSeedFromTime() & 0xFFFFL; for (i = 6; i; i--) { /* wall mask */ wmask <<= 1; if (p->ftable[i*8 - 2] > FL(0.5)) wmask++; } } /* limit parameters to useful range */ p->oversamp = SPAT3D_LIMIT(p->oversamp, 1, 8); p->zout = SPAT3D_LIMIT(p->zout, 0, 4); p->mdist = SPAT3D_LIMIT(p->mdist, FL(0.001), FL(1000.0)); p->rseed = SPAT3D_LIMIT(p->rseed, 0L, 65535L); p->mindep = SPAT3D_LIMIT(p->mindep, -1, 256); p->maxdep = SPAT3D_LIMIT(p->maxdep, -1, 256); p->irlen = SPAT3D_LIMIT(p->irlen, 2, 32000); p->mdel = SPAT3D_LIMIT(p->mdel, FL(0.001), FL(1000.0)); if (p->o_num == 2) p->bs = p->irlen; /* block size */ /* allocate space */ if (p->maxdep >= 0) { i = d = 0; spat3d_count_refl(&i, &d, 0, p->maxdep, 0, wmask); i *= (int32) sizeof(SPAT3D_WALL); if ((p->ws.auxp == NULL) || (p->ws.size < (unsigned int)i)) csound->AuxAlloc(csound, i, &(p->ws)); i = (int32) p->bs * (int32) d; i *= (int32) sizeof(MYFLT); if ((p->y.auxp == NULL) || (p->y.size < (unsigned int)i)) csound->AuxAlloc(csound, i, &(p->y)); } return OK; } /* -------------- initialisation functions for spat3d opcode --------------- */ /* spat3d set-up */ static int spat3dset(CSOUND *csound, SPAT3D *p) { int32 wmax; if (*(p->args[13]) != FL(0.0)) return OK; /* skip init */ p->o_num = 1; /* opcode number */ spat3d_set_opcode_params(csound, p); /* set parameters */ if (p->maxdep < 0) return OK; /* nothing to render */ wmax = 0L; /* init. wall structures */ spat3d_init_wall(p, 0, 0, &wmax, FL(0.0), FL(0.0), FL(0.0)); spat3d_init_delay(csound, p); /* alloc delay buffers */ spat3d_init_window(csound, p); /* init. FIR filter */ return OK; } /* -------------- initialisation functions for spat3di opcode -------------- */ /* spat3di set-up */ static int spat3diset(CSOUND *csound, SPAT3D *p) { int32 wmax; if (*(p->args[11]) != FL(0.0)) return OK; /* skip init */ p->o_num = 0; /* opcode number */ spat3d_set_opcode_params(csound, p); /* set parameters */ if (p->maxdep < 0) return OK; /* nothing to render */ wmax = 0L; p->mdel = FL(0.0); /* init. wall structures */ spat3d_init_wall(p, 0, 0, &wmax, *(p->args[5]), *(p->args[6]), *(p->args[7])); spat3d_init_delay(csound, p); /* alloc delay buffers */ return OK; } /* -------------------------- spat3d performance --------------------------- */ /* spat3d wall perf */ static void spat3d_wall_perf(CSOUND *csound, /* General environment */ SPAT3D *p, /* opcode struct */ MYFLT *xn, /* input signal */ SPAT3D_WALL *ws, /* wall parameters structure */ MYFLT X, /* sound source X coordinate */ MYFLT Y, /* sound source Y coordinate */ MYFLT Z) /* sound source Z coordinate */ { MYFLT *yn, W0, X0, Y0, Z0, *Wb, *Xb, *Yb, *Zb; MYFLT a, d, w, x, y, z, wd, xd, yd, zd, x1; double d0, d1, d0d, d1d, D0, D1; int32 xpos, nn, pos; yn = ws->yn; D0 = ws->D0; D1 = ws->D1; pos = p->del_p; W0 = ws->W0; X0 = ws->X0; Y0 = ws->Y0; Z0 = ws->Z0; Wb = Xb = Yb = Zb = NULL; /* calculate coordinates of reflection */ switch (ws->cnum) { case 0: X = ws->Xc - X; break; case 1: Y = ws->Xc - Y; break; case 2: Z = ws->Xc - Z; break; } /* convert coordinates */ if (p->zout < 4) { d = SPAT3D_XYZ2DIST(X, Y, Z); /* distance */ d0 = d1 = (double) SPAT3D_DIST2DEL(d); /* delay */ a = SPAT3D_DIST2AMP(d); /* amp. */ d = FL(1.0) / (d > p->mdist ? d : p->mdist); w = x = y = z = FL(0.0); switch (p->zout) { case 3: z = Z * d; w += z*z; z *= a; /* Z */ case 2: x = Y * d; w += x*x; x *= a; /* X */ case 1: y = -X * d; w += y*y; y *= a; /* Y */ } w = a - FL(0.293) * w * a; /* W */ } else { x = X - p->mdist * FL(0.5); /* right channel */ d = SPAT3D_XYZ2DIST(x, Y, Z); /* distance */ d1 = (double) SPAT3D_DIST2DEL(d); /* delay */ a = SPAT3D_DIST2AMP(d); /* amp. */ z = SQRT(FL(1.0) + (x / (d + FL(0.0001)))); z *= a; y = a - z; /* Rh, Rl */ x += p->mdist; /* left channel */ d = SPAT3D_XYZ2DIST(x, Y, Z); /* distance */ d0 = (double) SPAT3D_DIST2DEL(d); /* delay */ a = SPAT3D_DIST2AMP(d); /* amp. */ x = SQRT(FL(1.0) - (x / (d + FL(0.0001)))); x *= a; w = a - x; /* Lh, Ll */ d1 *= (double) p->oversamp * (double) CS_ESR;/* convert */ } /* delay to */ d0 *= (double) p->oversamp * (double) CS_ESR; /* samples */ /* interpolate W, X, Y, Z, and delay */ if (ws->init) { /* first k-cycle */ D0 = d0; D1 = d1; W0 = w; X0 = x; Y0 = y; Z0 = z; ws->init = 0; } d0d = d1d = 1.0 / (double) p->bs; wd = xd = yd = zd = (MYFLT) d0d; a = (MYFLT) p->oversamp; switch (p->zout) { case 4: d1d *= (d1 - D1); D1 -= d1d * 0.5; d = (a + (MYFLT) d1d) / a; /* correct amplitude */ case 3: zd *= (z - Z0); case 2: xd *= (x - X0); case 1: yd *= (y - Y0); case 0: wd *= (w - W0); d0d *= (d0 - D0); D0 -= d0d * 0.5; a = (a + (MYFLT) d0d) / a; } nn = p->bs; while (nn--) { /* EQ */ *yn = ws->b2 * ws->xnm2; *yn += ws->b1 * (ws->xnm2 = ws->xnm1); *yn += ws->b0 * (ws->xnm1 = *(xn++)); *yn -= ws->a2 * ws->ynm2; *yn -= ws->a1 * (ws->ynm2 = ws->ynm1); ws->ynm1 = *yn; /* write to delay buffer with cubic interpolation */ xpos = (int32) (D0 += d0d); x1 = (MYFLT) (D0 - (double) (xpos--)); z = x1 * x1; z--; z *= FL(0.1666666667); y = x1; y++; w = (y *= FL(0.5)); w--; x = FL(3.0) * z; y -= x; w -= z; x -= x1; x1 *= *yn * a; /* correct amplitude */ w *= x1; /* sample -1 */ x *= x1; x += *yn * a; /* sample 0 */ y *= x1; /* sample +1 */ z *= x1; /* sample +2 */ xpos += pos; while (xpos >= p->mdel_s) xpos -= p->mdel_s; Wb = p->Wb + xpos; W0 += wd; /* W / Ll */ *(Wb++) += w * W0; *(Wb++) += x * W0; *(Wb++) += y * W0; *Wb += z * W0; switch (p->zout) { case 3: Zb = p->Zb + xpos; Z0 += zd; /* Z */ *(Zb++) += w * Z0; *(Zb++) += x * Z0; *(Zb++) += y * Z0; *Zb += z * Z0; case 2: Xb = p->Xb + xpos; X0 += xd; /* X */ *(Xb++) += w * X0; *(Xb++) += x * X0; *(Xb++) += y * X0; *Xb += z * X0; case 1: Yb = p->Yb + xpos; Y0 += yd; /* Y */ *(Yb++) += w * Y0; *(Yb++) += x * Y0; *(Yb++) += y * Y0; *Yb += z * Y0; case 0: break; case 4: Xb = p->Xb + xpos; X0 += xd; /* Lh */ *(Xb++) += w * X0; *(Xb++) += x * X0; *(Xb++) += y * X0; *Xb += z * X0; xpos = (int32) (D1 += d1d); x1 = (MYFLT) (D1 - (double) (xpos--)); z = x1 * x1; z--; z *= FL(0.1666666667); y = x1; y++; w = (y *= FL(0.5)); w--; x = FL(3.0) * z; y -= x; w -= z; x -= x1; x1 *= *yn * d; /* correct amplitude */ w *= x1; /* sample -1 */ x *= x1; x += *yn * d; /* sample 0 */ y *= x1; /* sample +1 */ z *= x1; /* sample +2 */ xpos += pos; while (xpos >= p->mdel_s) xpos -= p->mdel_s; Yb = p->Yb + xpos; Y0 += yd; /* Rl */ *(Yb++) += w * Y0; *(Yb++) += x * Y0; *(Yb++) += y * Y0; *Yb += z * Y0; Zb = p->Zb + xpos; Z0 += zd; /* Rh */ *(Zb++) += w * Z0; *(Zb++) += x * Z0; *(Zb++) += y * Z0; *Zb += z * Z0; } pos += p->oversamp; yn++; /* next sample */ } ws->D0 = D0 + d0d * 0.5; if (p->zout == 4) ws->D1 = D1 + d1d * 0.5; ws->W0 = W0; ws->X0 = X0; ws->Y0 = Y0; ws->Z0 = Z0; /* next reflection(s) */ for (nn = 0; nn < 6; nn++) if (ws->nextRefl[nn] != NULL) spat3d_wall_perf(csound, p, ws->yn, (SPAT3D_WALL *) ws->nextRefl[nn], X, Y, Z); } /* spat3d routine */ static int spat3d(CSOUND *csound, SPAT3D *p) { int32 nn, i, j; MYFLT *aoutW, *aoutX, *aoutY, *aoutZ, w; /* assign object data to local variables */ aoutW = p->args[0]; aoutX = p->args[1]; aoutY = p->args[2]; aoutZ = p->args[3]; /* clear output variables */ nn = -1; while (++nn < p->bs) aoutW[nn] = aoutX[nn] = aoutY[nn] = aoutZ[nn] = FL(0.0); if (p->maxdep < 0) return OK; /* depth < 0 : nothing to render */ if (UNLIKELY((p->ws.auxp == NULL) || (p->y.auxp == NULL))) goto err1; /* spatialize and send to delay line */ j = p->mdel_s; switch (p->zout) { /* clear extra samples at beginning and */ case 4: /* end of delay line */ case 3: *(p->Zb - 1) = p->Zb[j] = p->Zb[j + 1] = p->Zb[j + 2] = FL(0.0); case 2: *(p->Xb - 1) = p->Xb[j] = p->Xb[j + 1] = p->Xb[j + 2] = FL(0.0); case 1: *(p->Yb - 1) = p->Yb[j] = p->Yb[j + 1] = p->Yb[j + 2] = FL(0.0); case 0: *(p->Wb - 1) = p->Wb[j] = p->Wb[j + 1] = p->Wb[j + 2] = FL(0.0); } spat3d_wall_perf(csound, p, p->args[4], (SPAT3D_WALL *) p->ws.auxp, *(p->args[5]), *(p->args[6]), *(p->args[7])); switch (p->zout) { /* copy extra samples from beginning and */ case 4: /* end of delay line */ case 3: p->Zb[j - 1] += *(p->Zb - 1); p->Zb[0] += p->Zb[j]; p->Zb[1] += p->Zb[j + 1]; p->Zb[2] += p->Zb[j + 2]; case 2: p->Xb[j - 1] += *(p->Xb - 1); p->Xb[0] += p->Xb[j]; p->Xb[1] += p->Xb[j + 1]; p->Xb[2] += p->Xb[j + 2]; case 1: p->Yb[j - 1] += *(p->Yb - 1); p->Yb[0] += p->Yb[j]; p->Yb[1] += p->Yb[j + 1]; p->Yb[2] += p->Yb[j + 2]; case 0: p->Wb[j - 1] += *(p->Wb - 1); p->Wb[0] += p->Wb[j]; p->Wb[1] += p->Wb[j + 1]; p->Wb[2] += p->Wb[j + 2]; } nn = p->bs; while (nn--) { /* read from delay line */ /* with interpolation */ i = 0; while ((j = p->sample[i]) > -10000) { w = p->window[i++]; j += p->del_p; if (j < 0) j += p->mdel_s; if (j >= p->mdel_s) j -= p->mdel_s; switch (p->zout) { case 4: case 3: *aoutZ += p->Zb[j] * w; case 2: *aoutX += p->Xb[j] * w; case 1: *aoutY += p->Yb[j] * w; case 0: *aoutW += p->Wb[j] * w; } } j = p->del_p - (p->oversamp << 4); if (j < 0) j += p->mdel_s; for (i = 0; i < p->oversamp; i++, j++) { switch (p->zout) { case 4: case 3: p->Zb[j] = FL(0.0); case 2: p->Xb[j] = FL(0.0); case 1: p->Yb[j] = FL(0.0); case 0: p->Wb[j] = FL(0.0); } } aoutW++; aoutX++; aoutY++; aoutZ++; /* next */ if ((p->del_p += p->oversamp) >= p->mdel_s) /* sample */ p->del_p -= p->mdel_s; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("spat3d: not initialised")); } /* -------------------------- spat3di performance -------------------------- */ /* spat3di wall perf */ static void spat3di_wall_perf(SPAT3D *p, /* opcode struct */ MYFLT *xn, /* input signal */ SPAT3D_WALL *ws) /* wall params */ { MYFLT *yn, *Wb, *Xb, *Yb, *Zb, w, x, y, z; int32 xpos0, xpos1, nn, bs; yn = ws->yn; bs = p->mdel_s; xpos0 = (int32) ws->D0 + p->del_p; while (xpos0 >= bs) xpos0 -= bs; xpos1 = xpos0; Wb = Xb = Yb = Zb = NULL; w = ws->W0; x = ws->X0; y = ws->Y0; z = ws->Z0; switch (p->zout) { case 4: xpos1 = (int32) ws->D1 + p->del_p; while (xpos1 >= bs) xpos1 -= bs; case 3: Zb = p->Zb + xpos1; /* Z / Rh */ case 2: Xb = p->Xb + xpos0; /* X / Lh */ case 1: Yb = p->Yb + xpos1; /* Y / Rl */ case 0: Wb = p->Wb + xpos0; /* W / Ll */ } nn = p->bs; while (nn--) { /* EQ */ *yn = ws->b2 * ws->xnm2; *yn += ws->b1 * (ws->xnm2 = ws->xnm1); *yn += ws->b0 * (ws->xnm1 = *(xn++)); *yn -= ws->a2 * ws->ynm2; *yn -= ws->a1 * (ws->ynm2 = ws->ynm1); ws->ynm1 = *yn; /* write to delay buffer */ switch (p->zout) { case 3: *(Zb++) += *yn * z; /* Z */ case 2: *(Xb++) += *yn * x; /* X */ case 1: *(Yb++) += *yn * y; /* Y */ case 0: *(Wb++) += *yn * w; /* W */ if (++xpos0 >= bs) { xpos0 -= bs; switch (p->zout) { case 3: Zb -= bs; case 2: Xb -= bs; case 1: Yb -= bs; case 0: Wb -= bs; } } break; case 4: *(Wb++) += *yn * w; /* Ll */ *(Xb++) += *yn * x; /* Lh */ *(Yb++) += *yn * y; /* Rl */ *(Zb++) += *yn * z; /* Rh */ if (++xpos0 >= bs) { xpos0 -= bs; Wb -= bs; Xb -= bs; } if (++xpos1 >= bs) { xpos1 -= bs; Yb -= bs; Zb -= bs; } } yn++; } /* next reflection(s) */ for (nn = 0; nn < 6; nn++) if (ws->nextRefl[nn] != NULL) spat3di_wall_perf(p, ws->yn, (SPAT3D_WALL *) ws->nextRefl[nn]); } /* spat3di routine */ static int spat3di(CSOUND *csound, SPAT3D *p) { int32 nn; MYFLT *a_outW, *a_outX, *a_outY, *a_outZ; /* assign object data to local variables */ a_outW = p->args[0]; a_outX = p->args[1]; a_outY = p->args[2]; a_outZ = p->args[3]; /* clear output variables */ nn = 0; do { a_outW[nn] = a_outX[nn] = a_outY[nn] = a_outZ[nn] = FL(0.0); } while (++nn < p->bs); if (p->maxdep < 0) return OK; /* depth < 0 : nothing to render */ if (UNLIKELY((p->ws.auxp == NULL) || (p->y.auxp == NULL))) goto err1; /* spatialize and send to delay line */ spat3di_wall_perf(p, p->args[4], (SPAT3D_WALL *) p->ws.auxp); nn = p->bs; do { /* read from delay line */ switch (p->zout) { case 4: case 3: *(a_outZ++) = p->Zb[p->del_p]; /* Z */ p->Zb[p->del_p] = FL(0.0); case 2: *(a_outX++) = p->Xb[p->del_p]; /* X */ p->Xb[p->del_p] = FL(0.0); case 1: *(a_outY++) = p->Yb[p->del_p]; /* Y */ p->Yb[p->del_p] = FL(0.0); case 0: *(a_outW++) = p->Wb[p->del_p]; /* W */ p->Wb[p->del_p] = FL(0.0); } /* next sample */ if (++(p->del_p) >= p->mdel_s) p->del_p -= p->mdel_s; } while (--nn); return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("spat3di: not initialised")); } /* ---------------------------- spat3dt opcode ----------------------------- */ /* spat3dt wall perf */ static void spat3dt_wall_perf(SPAT3D *p, /* opcode struct */ MYFLT *xn, /* input signal */ SPAT3D_WALL *ws) /* wall params */ { MYFLT *yn, *Wb, *Yb, *endp, w, x, y, z, a, d, ad, yw; int32 nn; yn = ws->yn; endp = p->outft; /* write to ftable */ Wb = endp + ((int32) ws->D0 << 2); Yb = (p->zout < 4 ? Wb : endp + ((int32) ws->D1 << 2)) + 2; endp += p->outftlnth; /* end of table */ w = ws->W0; x = ws->X0; y = ws->Y0; z = ws->Z0; a = FL(1.0) / (MYFLT) p->bs; ad = FL(2.0) * (a *= -a); d = FL(1.0); nn = p->bs; while (nn--) { /* EQ */ *yn = ws->b2 * ws->xnm2; *yn += ws->b1 * (ws->xnm2 = ws->xnm1); *yn += ws->b0 * (ws->xnm1 = *(xn++)); *yn -= ws->a2 * ws->ynm2; *yn -= ws->a1 * (ws->ynm2 = ws->ynm1); ws->ynm1 = *yn; yw = *yn * d; /* yw: windowed signal */ /* write to delay buffer */ if (p->zout < 4) { if (Wb < endp) { *(Wb++) += yw * w; *(Wb++) += yw * x; /* W, X */ *(Wb++) += yw * y; *(Wb++) += yw * z; /* Y, Z */ } } else { if (Wb < endp) { /* Ll, Lh */ *(Wb++) += yw * w; *Wb += yw * x; Wb += 3; } if (Yb < endp) { /* Rl, Rh */ *(Yb++) += yw * y; *Yb += yw * z; Yb += 3; } } d += a; a += ad; yn++; } /* next reflection(s) */ for (nn = 0; nn < 6; nn++) if (ws->nextRefl[nn] != NULL) spat3dt_wall_perf(p, ws->yn, (SPAT3D_WALL *) ws->nextRefl[nn]); } /* spat3dt opcode (i-time only) */ static int spat3dt(CSOUND *csound, SPAT3D *p) { int32 wmax; MYFLT *ir; p->o_num = 2; /* opcode number */ spat3d_set_opcode_params(csound, p); /* set parameters */ if (p->maxdep < 0) return OK; /* nothing to render */ wmax = 0L; p->mdel = FL(0.0); /* init. wall structures */ spat3d_init_wall(p, 0, 0, &wmax, *(p->args[1]), *(p->args[2]), *(p->args[3])); p->outftlnth = ((p->outftlnth) >> 2) << 2; /* table length */ if (UNLIKELY((p->outft == NULL) || (p->outftlnth < 4))) return NOTOK; /* no table */ /* initialise IR */ ir = (MYFLT *) csound->Malloc(csound, sizeof(MYFLT) * (int32) p->bs); ir[0] = FL(1.0); wmax = 0; while (++wmax < (int32) p->bs) ir[wmax] = (sizeof(MYFLT) < 8 ? FL(1.0e-24) : FL(1.0e-48)); if (*(p->args[8]) == FL(0.0)) { /* clear ftable (if enabled) */ wmax = -1; while (++wmax < p->outftlnth) p->outft[wmax] = FL(0.0); } /* braces added by JPff -- REVIEW */ /* render IR */ spat3dt_wall_perf(p, ir, (SPAT3D_WALL *) p->ws.auxp); csound->Free(csound, ir); /* free tmp memory */ return OK; } #define S(x) sizeof(x) static OENTRY localops[] = { { "spat3d", S(SPAT3D), 0, 5, "aaaa", "akkkiiiiio", (SUBR) spat3dset, NULL, (SUBR) spat3d }, { "spat3di",S(SPAT3D), 0, 5, "aaaa", "aiiiiiio", (SUBR) spat3diset, NULL, (SUBR) spat3di }, { "spat3dt",S(SPAT3D), 0, 1, "", "iiiiiiiio", (SUBR) spat3dt, NULL, NULL } }; int spat3d_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/spat3d.h000066400000000000000000000155471321653344700160600ustar00rootroot00000000000000/* spat3d.h: Copyright (C) 2001 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* spat3d, spat3di, and spat3dt - written by Istvan Varga, 2001 */ #ifndef CSOUND_SPAT3D_H #define CSOUND_SPAT3D_H #include "csdl.h" #ifdef CSOUND_SPAT3D_C /* define these only when included from spat3d.c */ #define SPAT3D_SNDSPEED FL(340.0) /* sound speed */ #define SPAT3D_MAXAMP FL(10.0) /* amplitude at dist=0 */ /* convert distance to delay */ #define SPAT3D_DIST2DEL(x) ((x) / SPAT3D_SNDSPEED) /* convert distance to amplitude */ #define SPAT3D_DIST2AMP(x) (FL(1.0) / ((FL(1.0) / SPAT3D_MAXAMP) + (x))) /* calculate distance */ #define SPAT3D_XYZ2DIST(x,y,z) \ ((MYFLT) sqrt ((double) ((x) * (x) + (y) * (y) + (z) * (z)))) /* limit a number to a specified range */ #define SPAT3D_LIMIT(x, a, b) ((x) > (b) ? (b) : ((x) < (a) ? (a) : (x))) typedef struct { void *nextRefl[6]; /* pointers to next reflections */ /* (NULL: no reflection) */ int init; /* 1 at first k-cycle */ int cnum; /* select coord. to transform: */ /* -1: none, 0: X, 1: Y, 2: Z */ MYFLT Xc; /* coord. offset */ MYFLT W0, X0, Y0, Z0; /* W, X, Y, Z (Ll, Lh, Rl, Rh) */ double D0, D1; /* delay */ MYFLT *yn; /* output sound */ MYFLT a0, a1, a2, b0, b1, b2; /* EQ parameters */ MYFLT xnm1, xnm2, ynm1, ynm2; /* EQ tmp data */ } SPAT3D_WALL; /* ftable data: */ /* 0: early refl. recursion depth (for spat3d and spat3di) */ /* 1: late refl. recursion depth (for spat3dt) */ /* 2: max. delay (spat3d) */ /* 3: echo IR length (spat3dt) */ /* 4: unit circle / microphone distance */ /* 5: random seed (0 - 65535) */ /* 6-13: ceil reflection parameters */ /* 6: enable reflection (any non-zero value) */ /* 7: wall distance in meters */ /* 8: randomization of wall distance (1 / (wall dist.)) */ /* 9: reflection level */ /* 10: EQ frequency (see pareq opcode) */ /* 11: EQ level */ /* 12: EQ Q */ /* 13: EQ mode */ /* 14-21: floor parameters */ /* 22-29: front wall parameters */ /* 30-37: back wall parameters */ /* 38-45: right wall parameters */ /* 46-53: left wall parameters */ #endif /* CSOUND_SPAT3D_C */ /* opcode struct for spat3d, spat3di, and spat3dt */ typedef struct { /* opcode args */ OPDS h; MYFLT *args[14]; /* opcode arguments */ /* (see spat3d.README) */ /* spat3di spat3d spat3dt */ /* */ /* 0 aW aW ioutft */ /* 1 aX aX iX */ /* 2 aY aY iY */ /* 3 aZ aZ iZ */ /* 4 ain ain idist */ /* 5 iX kX ift */ /* 6 iY kY imode */ /* 7 iZ kZ irlen */ /* 8 idist idist [iftnocl] */ /* 9 ift ift - */ /* 10 imode imode - */ /* 11 [istor] imdel - */ /* 12 - iovr - */ /* 13 - [istor] - */ /* internal variables */ int o_num; /* opcode (0: spat3di, 1: spat3d, 2: spat3dt */ int oversamp; /* oversample ratio (spat3d) */ int zout; /* output mode */ MYFLT mdist; /* unit circle distance */ MYFLT *ftable; /* ptr. to ftable */ int32 rseed; /* random seed */ int mindep; /* min. recursion depth */ int maxdep; /* max. recursion depth */ MYFLT *outft; /* ptr to output ftable (spat3dt) */ int32 outftlnth; /* output ftable length (spat3dt) */ int irlen; /* IR length (spat3dt) */ int bs; /* block size (ksmps or irlen) */ MYFLT mdel; /* max. delay (in seconds) */ int32 mdel_s; /* max. delay (in samples) */ int32 del_p; /* read position in delay buffers */ MYFLT *Wb, *Xb, *Yb, *Zb; /* delay buffers */ int *sample; /* FIR filter data (spat3d) */ MYFLT *window; AUXCH fltr; AUXCH ws; /* wall structure array */ AUXCH y; /* tmp data */ AUXCH del; /* delay buffer */ } SPAT3D; #endif /* CSOUND_SPAT3D_H */ csound-6.10.0/Opcodes/spectra.c000066400000000000000000001475201321653344700163130ustar00rootroot00000000000000/* spectra.c: Copyright (C) 1995 Barry Vercoe This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // #include "csdl.h" #include "csoundCore.h" #include "interlocks.h" #include #include "cwindow.h" #include "spectra.h" #include "pitch.h" #include "uggab.h" #define LOGTWO (0.69314718056) void DOWNset(CSOUND *p, DOWNDAT *downdp, int32 npts) { int32 nbytes = npts * sizeof(MYFLT); if (downdp->auxch.auxp == NULL || downdp->auxch.size != (uint32_t)nbytes) p->AuxAlloc(p, nbytes, &downdp->auxch); downdp->npts = npts; } void SPECset(CSOUND *p, SPECDAT *specdp, int32 npts) { int32 nbytes = npts * sizeof(MYFLT); if (specdp->auxch.auxp == NULL || (uint32_t)nbytes != specdp->auxch.size) p->AuxAlloc(p, nbytes, &specdp->auxch); specdp->npts = npts; } static const char *outstring[] = {"mag", "db", "mag sqrd", "root mag"}; int spectset(CSOUND *csound, SPECTRUM *p) /* spectrum - calcs disc Fourier transform of */ /* oct-downsampled data outputs coefs (mag, */ /* db or mag2) of log freq within each octave */ { int n, nocts, nfreqs, ncoefs, hanning; MYFLT Q, *fltp; OCTDAT *octp; DOWNDAT *dwnp = &p->downsig; SPECDAT *specp = p->wsig; /* for mac roundoff */ p->timcount = (int)(CS_EKR * *p->iprd + FL(0.001)); nocts = (int)*p->iocts; nfreqs = (int)*p->ifrqs; ncoefs = nocts * nfreqs; Q = *p->iq; hanning = (*p->ihann) ? 1 : 0; p->dbout = (int)*p->idbout; if (UNLIKELY((p->disprd = (int)(CS_EKR * *p->idisprd)) < 0)) p->disprd = 0; if (UNLIKELY(p->timcount <= 0)) return csound->InitError(csound, Str("illegal iprd")); if (UNLIKELY(nocts <= 0 || nocts > MAXOCTS)) return csound->InitError(csound, Str("illegal iocts")); if (UNLIKELY(nfreqs <= 0 || nfreqs > MAXFRQS)) return csound->InitError(csound, Str("illegal ifrqs")); if (UNLIKELY(Q <= FL(0.0))) return csound->InitError(csound, Str("illegal Q value")); if (UNLIKELY(p->dbout < 0 || p->dbout > 3)) return csound->InitError(csound, Str("unknown dbout code")); if (nocts != dwnp->nocts || nfreqs != p->nfreqs || /* if anything has changed */ Q != p->curq || (p->disprd && !p->octwindow.windid) || hanning != p->hanning) { /* make new tables */ double basfrq, curfrq, frqmlt, Qfactor; double theta, a, windamp, onedws, pidws; MYFLT *sinp, *cosp; int k, sumk, windsiz, halfsiz, *wsizp, *woffp; int32 auxsiz, bufsiz = 0; int32 majr, minr, totsamps, totsize; double hicps,locps,oct; /* must alloc anew */ p->nfreqs = nfreqs; p->curq = Q; p->hanning = hanning; p->ncoefs = ncoefs; csound->Warning(csound, Str("spectrum: %s window, %s out, making tables ...\n"), (hanning) ? "hanning":"hamming", outstring[p->dbout]); if (p->h.optext->t.intype == 'k') { dwnp->srate = CS_EKR; /* define the srate */ p->nsmps = 1; } else { dwnp->srate = CS_ESR; p->nsmps = CS_KSMPS; } hicps = dwnp->srate * 0.375; /* top freq is 3/4 pi/2 ... */ oct = log(hicps / ONEPT) / LOGTWO; /* octcps() (see aops.c) */ if (p->h.optext->t.intype != 'k') { /* for sr sampling: */ oct = ((int)(oct*12.0 + 0.5)) / 12.0; /* semitone round to A440 */ hicps = pow(2.0, oct) * ONEPT; /* cpsoct() */ } dwnp->looct = (MYFLT)(oct - nocts); /* true oct val of lowest frq */ locps = hicps / (1L << nocts); csound->Warning(csound, Str("\thigh cps %7.1f\n\t low cps %7.1f\n"), hicps, locps); basfrq = hicps/2.0; /* oct below retuned top */ frqmlt = pow(2.0,(double)1.0/nfreqs); /* nfreq interval mult */ Qfactor = Q * dwnp->srate; curfrq = basfrq; for (sumk=0,wsizp=p->winlen,woffp=p->offset,n=nfreqs; n--; ) { *wsizp++ = k = (int)(Qfactor/curfrq) | 01; /* calc odd wind sizes */ *woffp++ = (*(p->winlen) - k) / 2; /* & symmetric offsets */ sumk += k; /* and find total */ curfrq *= frqmlt; } windsiz = *(p->winlen); csound->Warning(csound, Str("\tQ %4.1f uses a %d sample window each octdown\n"), Q, windsiz); auxsiz = (windsiz + 2*sumk) * sizeof(MYFLT); /* calc lcl space rqd */ csound->AuxAlloc(csound, (size_t)auxsiz, &p->auxch1); /* & alloc auxspace */ fltp = (MYFLT *) p->auxch1.auxp; p->linbufp = fltp; fltp += windsiz; /* linbuf must take nsamps */ p->sinp = sinp = fltp; fltp += sumk; p->cosp = cosp = fltp; /* cos gets rem sumk */ wsizp = p->winlen; curfrq = basfrq * TWOPI / dwnp->srate; for (n = nfreqs; n--; ) { /* now fill tables */ windsiz = *wsizp++; /* (odd win size) */ halfsiz = windsiz >> 1; onedws = 1.0 / (windsiz-1); pidws = PI / (windsiz-1); for (k = -halfsiz; k<=halfsiz; k++) { /* with sines */ a = cos(k * pidws); windamp = a * a; /* times hanning */ if (!hanning) windamp = 0.08 + 0.92 * windamp; /* or hamming */ windamp *= onedws; /* scaled */ theta = k * curfrq; *sinp++ = (MYFLT)(windamp * sin(theta)); *cosp++ = (MYFLT)(windamp * cos(theta)); } curfrq *= frqmlt; /* step by log freq */ } if (*p->idsines != FL(0.0)) { /* if reqd, dsply windowed sines now! */ csound->dispset(csound, &p->sinwindow, p->sinp, (int32) sumk, Str("spectrum windowed sines:"), 0, "spectrum"); csound->display(csound, &p->sinwindow); } dwnp->hifrq = (MYFLT)hicps; dwnp->lofrq = (MYFLT)locps; dwnp->nsamps = windsiz = *(p->winlen); dwnp->nocts = nocts; minr = windsiz >> 1; /* sep odd windsiz into maj, min */ majr = windsiz - minr; /* & calc totsamps reqd */ totsamps = (majr*nocts) + (minr<auxch.auxp; /* & distrib to octdata */ for (n=nocts,octp=dwnp->octdata+(nocts-1); n--; octp--) { bufsiz = majr + minr; octp->begp = fltp; fltp += bufsiz; /* (lo oct first) */ octp->endp = fltp; minr *= 2; } csound->Warning(csound, Str("\t%d oct analysis window " "delay = %d samples (%d msecs)\n"), nocts, bufsiz, (int)(bufsiz*1000/dwnp->srate)); if (p->disprd) { /* if display requested, */ totsize = totsamps * sizeof(MYFLT); /* alloc an equiv local */ csound->AuxAlloc(csound, (size_t)totsize, &p->auxch2);/* linear output window */ csound->dispset(csound, &p->octwindow, (MYFLT *)p->auxch2.auxp, (int32)totsamps, Str("octdown buffers:"), 0, "spectrum"); } SPECset(csound, specp, (int32)ncoefs); /* prep the spec dspace */ specp->downsrcp = dwnp; /* & record its source */ } for (octp=dwnp->octdata; nocts--; octp++) { /* reset all oct params, & */ octp->curp = octp->begp; for (fltp=octp->feedback,n=6; n--; ) *fltp++ = FL(0.0); octp->scount = 0; } specp->nfreqs = p->nfreqs; /* save the spec descriptors */ specp->dbout = p->dbout; specp->ktimstamp = 0; /* init specdata to not new */ specp->ktimprd = p->timcount; p->scountdown = p->timcount; /* prime the spect countdown */ p->dcountdown = p->disprd; /* & the display countdown */ return OK; } static void linocts(DOWNDAT *dwnp, MYFLT *bufp) /* linearize octdown dat to 1 buf */ { /* presumes correct buffer alloc'd in set */ MYFLT *curp, *endp; int wrap; OCTDAT *octp; int nocts; MYFLT *begp; nocts = dwnp->nocts; octp = dwnp->octdata + nocts; while (nocts--) { octp--; /* for each octave (low to high) */ begp = octp->begp; curp = octp->curp; endp = octp->endp; wrap = curp - begp; while (curp < endp) /* copy circbuf to linbuf */ *bufp++ = *curp++; for (curp=begp; wrap--; ) *bufp++ = *curp++; } } static const MYFLT bicoefs[] = { -FL(0.2674054), FL(0.7491305), FL(0.7160484), FL(0.0496285), FL(0.7160484), FL(0.0505247), FL(0.3514850), FL(0.5257536), FL(0.3505025), FL(0.5257536), FL(0.3661840), FL(0.0837990), FL(0.3867783), FL(0.6764264), FL(0.3867783) }; int spectrum(CSOUND *csound, SPECTRUM *p) { MYFLT a, b, *dftp, *sigp = p->signal, SIG, yt1, yt2; int nocts, nsmps = p->nsmps, winlen; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; DOWNDAT *downp = &p->downsig; OCTDAT *octp; SPECDAT *specp; double c; if (UNLIKELY(early)) nsmps -= early; do { SIG = *sigp++; /* for each source sample: */ if (offset--) SIG = FL(0.0); /* for sample accuracy */ octp = downp->octdata; /* align onto top octave */ nocts = downp->nocts; do { /* then for each oct: */ const MYFLT *coefp; MYFLT *ytp, *curp; int nfilt; curp = octp->curp; *curp++ = SIG; /* write samp to cur buf */ if (curp >= octp->endp) curp = octp->begp; /* & modulo the pointer */ octp->curp = curp; if (!(--nocts)) break; /* if lastoct, break */ coefp = bicoefs; ytp = octp->feedback; for (nfilt = 3; nfilt--; ) { /* apply triple biquad: */ yt2 = *ytp++; yt1 = *ytp--; /* get prev feedback */ SIG -= (*coefp++ * yt1); /* apply recurs filt */ SIG -= (*coefp++ * yt2); *ytp++ = yt1; *ytp++ = SIG; /* stor nxt feedback */ SIG *= *coefp++; SIG += (*coefp++ * yt1); /* apply forwrd filt */ SIG += (*coefp++ * yt2); } } while (!(++octp->scount & 01) && octp++); /* send alt samps to nxtoct */ } while (--nsmps); if (p->disprd) /* if displays requested, */ if (!(--p->dcountdown)) { /* on countdown */ linocts(downp, (MYFLT *)p->auxch2.auxp); /* linearize the oct bufs */ csound->display(csound, &p->octwindow); /* & display */ p->dcountdown = p->disprd; } if ((--p->scountdown)) return OK;/* if not yet time for new spec, return */ p->scountdown = p->timcount; /* else reset counter & proceed: */ downp = &p->downsig; specp = p->wsig; nocts = downp->nocts; octp = downp->octdata + nocts; dftp = (MYFLT *) specp->auxch.auxp; winlen = *(p->winlen); while (nocts--) { MYFLT *bufp, *sinp, *cosp; int len, *lenp, *offp, nfreqs; MYFLT *begp, *curp, *endp, *linbufp; int len2; octp--; /* for each oct (low to high) */ begp = octp->begp; curp = octp->curp; endp = octp->endp; if ((len = endp - curp) >= winlen) /* if no wrap */ linbufp = curp; /* use samples in circbuf */ else { len2 = winlen - len; linbufp = bufp = p->linbufp; /* else cp crcbuf to linbuf */ while (len--) *bufp++ = *curp++; curp = begp; while (len2--) *bufp++ = *curp++; } cosp = p->cosp; /* get start windowed sines */ sinp = p->sinp; lenp = p->winlen; offp = p->offset; for (nfreqs=p->nfreqs; nfreqs--; ) { /* now for ea. frq this oct */ a = FL(0.0); b = FL(0.0); bufp = linbufp + *offp++; for (len = *lenp++; len--; bufp++) { /* apply windowed sine seg */ a += *bufp * *cosp++; b += *bufp * *sinp++; } c = a*a + b*b; /* get magnitude squared */ switch (p->dbout) { case 1: if (c < .001) c = .001; /* and convert to db */ c = 10.0 * log10(c); break; case 3: c = sqrt(c); /* or root mag */ case 0 : c = sqrt(c); /* or mag */ case 2: break; /* or leave mag sqrd */ } *dftp++ = (MYFLT)c; /* store in out spectrum */ } } specp->ktimstamp = CS_KCNT; /* time-stamp the output */ return OK; } /* int nocdfset(CSOUND *csound, NOCTDFT *p) */ /* /\* noctdft - calcs disc Fourier transform of oct-downsampled data *\/ */ /* /\* outputs coefs (mag, db or mag2) of log freq within each octave *\/ */ /* { */ /* int nfreqs, hanning, nocts, ncoefs; */ /* MYFLT Q, *fltp; */ /* DOWNDAT *downp = p->dsig; */ /* SPECDAT *specp = p->wsig; */ /* p->timcount = CS_EKR * *p->iprd; */ /* nfreqs = *p->ifrqs; */ /* Q = *p->iq; */ /* hanning = (*p->ihann) ? 1 : 0; */ /* if ((p->dbout = *p->idbout) && p->dbout != 1 && p->dbout != 2) { */ /* return csound->InitError(csound, Str("noctdft: unknown dbout code of %d"), */ /* p->dbout); */ /* } */ /* nocts = downp->nocts; */ /* ncoefs = nocts * nfreqs; */ /* if (nfreqs != p->nfreqs || Q != p->curq /\* if anything changed *\/ */ /* || p->timcount <= 0 || Q <= 0. */ /* || hanning != p->hanning */ /* || ncoefs != p->ncoefs) { /\* make new tables *\/ */ /* double basfrq, curfrq, frqmlt, Qfactor; */ /* double theta, a, windamp, onedws, pidws; */ /* MYFLT *sinp, *cosp; */ /* int n, k, sumk, windsiz, *wsizp, nsamps; */ /* long auxsiz; */ /* csound->Message(csound, */ /* Str("noctdft: %s window, %s out, making tables ...\n"), */ /* (hanning) ? "hanning":"hamming", outstring[p->dbout]); */ /* if (p->timcount <= 0) */ /* return csound->InitError(csound, Str("illegal iprd")); */ /* if (nfreqs <= 0 || nfreqs > MAXFRQS) */ /* return csound->InitError(csound, Str("illegal ifrqs")); */ /* if (Q <= FL(0.0)) */ /* return csound->InitError(csound, Str("illegal Q value")); */ /* nsamps = downp->nsamps; */ /* p->nfreqs = nfreqs; */ /* p->curq = Q; */ /* p->hanning = hanning; */ /* p->ncoefs = ncoefs; */ /* basfrq = downp->hifrq/2.0 * TWOPI/downp->srate; /\* oct below retuned top *\/ */ /* frqmlt = pow(2.0,1.0/(double)nfreqs); /\* nfreq interval mult *\/ */ /* Qfactor = TWOPI * Q; /\* Was incorrect value for 2pi?? *\/ */ /* curfrq = basfrq; */ /* for (sumk=0,wsizp=p->winlen,n=nfreqs; n--; ) { */ /* *wsizp++ = k = Qfactor/curfrq + 0.5; /\* calc window sizes *\/ */ /* sumk += k; /\* and find total *\/ */ /* curfrq *= frqmlt; */ /* } */ /* if ((windsiz = *(p->winlen)) > nsamps) {/\* chk longest windsiz *\/ */ /* return csound->InitError(csound, Str("Q %4.1f needs %d samples, " */ /* "octdown has just %d"), */ /* Q, windsiz, nsamps); */ /* } */ /* else csound->Message(csound, Str("noctdft: Q %4.1f uses %d of " */ /* "%d samps per octdown\n"), */ /* Q, windsiz, nsamps); */ /* auxsiz = (nsamps + 2*sumk) * sizeof(MYFLT);/\* calc local space reqd *\/ */ /* csound->AuxAlloc(csound, (size_t)auxsiz, &p->auxch); /\* & alloc auxspace *\/ */ /* fltp = (MYFLT *) p->auxch.auxp; */ /* p->linbufp = fltp; fltp += nsamps; /\* linbuf must handle nsamps *\/ */ /* p->sinp = sinp = fltp; fltp += sumk; */ /* p->cosp = cosp = fltp; /\* cos gets rem sumk *\/ */ /* wsizp = p->winlen; */ /* for (curfrq=basfrq,n=nfreqs; n--; ) { /\* now fill tables *\/ */ /* windsiz = *wsizp++; */ /* onedws = 1.0 / windsiz; */ /* pidws = PI / windsiz; */ /* for (k=0; kidsines != FL(0.0)) { */ /* /\* if reqd, display windowed sines immediately *\/ */ /* csound->dispset(csound, &p->dwindow, p->sinp, (int32) sumk, */ /* Str("octdft windowed sines:"), 0, "octdft"); */ /* csound->display(csound, &p->dwindow); */ /* } */ /* SPECset(csound, */ /* specp, (long)ncoefs); /\* prep the spec dspace *\/ */ /* specp->downsrcp = downp; /\* & record its source *\/ */ /* } */ /* specp->nfreqs = p->nfreqs; \* save the spec descriptors *\/ */ /* specp->dbout = p->dbout; */ /* specp->ktimstamp = 0; \* init specdata to not new *\/ */ /* specp->ktimprd = p->timcount; */ /* p->countdown = p->timcount; \* & prime the countdown *\/ */ /* return OK; */ /* } */ /* int noctdft(CSOUND *csound, NOCTDFT *p) */ /* { */ /* DOWNDAT *downp; */ /* SPECDAT *specp; */ /* OCTDAT *octp; */ /* MYFLT *dftp; */ /* int nocts, wrap; */ /* MYFLT a, b; */ /* double c; */ /* if ((--p->countdown)) return; /\* if not yet time for new spec, return *\/ */ /* if (p->auxch.auxp==NULL) { /\* RWD fix *\/ */ /* return csound->PerfError(csound, p->h.insdshead, */ /* Str("noctdft: not initialised")); */ /* } */ /* p->countdown = p->timcount; /\* else reset counter & proceed: *\/ */ /* downp = p->dsig; */ /* specp = p->wsig; */ /* nocts = downp->nocts; */ /* octp = downp->octdata + nocts; */ /* dftp = (MYFLT *) specp->auxch.auxp; */ /* while (nocts--) { */ /* MYFLT *bufp, *sinp, *cosp; */ /* int len, *lenp, nfreqs; */ /* MYFLT *begp, *curp, *endp; */ /* octp--; /\* for each octave (low to high) *\/ */ /* begp = octp->begp; */ /* curp = octp->curp; */ /* endp = octp->endp; */ /* wrap = curp - begp; */ /* bufp = p->linbufp; */ /* while (curp < endp) /\* copy circbuf to linbuf *\/ */ /* *bufp++ = *curp++; */ /* for (curp=begp,len=wrap; len--; ) */ /* *bufp++ = *curp++; */ /* cosp = p->cosp; /\* get start windowed sines *\/ */ /* sinp = p->sinp; */ /* lenp = p->winlen; */ /* for (nfreqs=p->nfreqs; nfreqs--; ) { /\* now for each freq this oct: *\/ */ /* a = 0.0; */ /* b = 0.0; */ /* bufp = p->linbufp; */ /* for (len = *lenp++; len--; bufp++) {/\* apply windowed sine seg *\/ */ /* a += *bufp * *cosp++; */ /* b += *bufp * *sinp++; */ /* } */ /* c = a*a + b*b; /\* get magnitude squared *\/ */ /* if (!(p->dbout)) /\* & optionally convert *\/ */ /* c = sqrt(c); /\* to mag or db *\/ */ /* else if (p->dbout == 1) { */ /* if (c < .001) c = .001; */ /* c = 10. * log10(c); */ /* } */ /* *dftp++ = c; /\* store in out spectrum *\/ */ /* } */ /* } */ /* specp->ktimstamp = CS_KCNT; /\* time-stamp the output *\/ */ /* return OK; */ /* } */ int spdspset(CSOUND *csound, SPECDISP *p) { char strmsg[256]; /* RWD is this enough? */ if (UNLIKELY(p->wsig->auxch.auxp==NULL)) { return csound->InitError(csound, Str("specdisp: not initialised")); } if (UNLIKELY((p->timcount = (int)(CS_EKR * *p->iprd)) <= 0)) { return csound->InitError(csound, Str("illegal iperiod")); } if (!(p->dwindow.windid)) { SPECDAT *specp = p->wsig; DOWNDAT *downp = specp->downsrcp; if (downp->lofrq > FL(5.0)) { snprintf(strmsg, 256, Str("instr %d %s, dft (%s), %d octaves (%d - %d Hz):"), (int) p->h.insdshead->p1.value, p->h.optext->t.inlist->arg[0], outstring[specp->dbout], downp->nocts, (int)downp->lofrq, (int)downp->hifrq); } else { /* more detail if low frequency */ snprintf(strmsg, 256, Str("instr %d %s, dft (%s), %d octaves (%3.1f - %3.1f Hz):"), (int) p->h.insdshead->p1.value, p->h.optext->t.inlist->arg[0], outstring[specp->dbout], downp->nocts, downp->lofrq, downp->hifrq); } csound->dispset(csound, &p->dwindow, (MYFLT*) specp->auxch.auxp, (int32)specp->npts, strmsg, (int)*p->iwtflg, "specdisp"); } p->countdown = p->timcount; /* prime the countdown */ return OK; } int specdisp(CSOUND *csound, SPECDISP *p) { /* RWD is this enough? */ if (UNLIKELY(p->wsig->auxch.auxp==NULL)) goto err1; if (!(--p->countdown)) { /* on countdown */ csound->display(csound, &p->dwindow); /* display spect */ p->countdown = p->timcount; /* & reset count */ } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("specdisp: not initialised")); } int sptrkset(CSOUND *csound, SPECPTRK *p) { SPECDAT *inspecp = p->wsig; int32 npts, nptls, nn, lobin; int *dstp, ptlmax, inc; MYFLT nfreqs, rolloff, *oct0p, *flop, *fhip, *fundp, *fendp, *fp; MYFLT weight, weightsum, dbthresh, ampthresh; if ((npts = inspecp->npts) != p->winpts) { /* if size has changed */ SPECset(csound, &p->wfund, (int32)npts); /* realloc for wfund */ p->wfund.downsrcp = inspecp->downsrcp; p->fundp = (MYFLT *) p->wfund.auxch.auxp; p->winpts = npts; } if ((p->ftimcnt = (int)(CS_EKR**p->ifprd)) > 0) { /* if displaying wfund */ SPECDISP *fdp = &p->fdisplay; fdp->h = p->h; fdp->wsig = &p->wfund; /* pass the param pntrs */ fdp->iprd = p->ifprd; fdp->iwtflg = p->iwtflg; /* fdp->altname = "specptrk"; */ /* fdp->altarg = "X-corr"; */ p->wfund.dbout = inspecp->dbout; spdspset(csound,fdp); /* & call specdisp init */ } else p->ftimcnt = 0; if (UNLIKELY((nptls = (int32)*p->inptls) <= 0 || nptls > MAXPTL)) { return csound->InitError(csound, Str("illegal no of partials")); } p->nptls = nptls; /* number, whether all or odd */ if (*p->iodd == FL(0.0)) { ptlmax = nptls; inc = 1; } else { ptlmax = nptls * 2 - 1; inc = 2; } dstp = p->pdist; nfreqs = (MYFLT)inspecp->nfreqs; for (nn = 1; nn <= ptlmax; nn += inc) *dstp++ = (int) ((log((double) nn) / LOGTWO) * nfreqs + 0.5); if ((rolloff = *p->irolloff) == 0.0 || rolloff == 1.0 || nptls == 1) { p->rolloff = 0; weightsum = (MYFLT)nptls; } else { MYFLT *fltp = p->pmult; MYFLT octdrop = (FL(1.0) - rolloff) / nfreqs; weightsum = FL(0.0); for (dstp = p->pdist, nn = nptls; nn--; ) { weight = FL(1.0) - octdrop * *dstp++; /* rolloff * octdistance */ weightsum += weight; *fltp++ = weight; } if (UNLIKELY(*--fltp < FL(0.0))) { return csound->InitError(csound, Str("per oct rolloff too steep")); } p->rolloff = 1; } lobin = (int32)(inspecp->downsrcp->looct * nfreqs); oct0p = p->fundp - lobin; /* virtual loc of oct 0 */ flop = oct0p + (int)(*p->ilo * nfreqs); fhip = oct0p + (int)(*p->ihi * nfreqs); fundp = p->fundp; fendp = fundp + inspecp->npts; if (flop < fundp) flop = fundp; if (fhip > fendp) fhip = fendp; if (UNLIKELY(flop >= fhip)) { /* chk hi-lo range valid */ return csound->InitError(csound, Str("illegal lo-hi values")); } for (fp = fundp; fp < flop; ) *fp++ = FL(0.0); /* clear unused lo and hi range */ for (fp = fhip; fp < fendp; ) *fp++ = FL(0.0); csound->Warning(csound, Str("specptrk: %d freqs, %d%s ptls at "), (int)nfreqs, (int)nptls, inc==2 ? Str(" odd") : ""); for (nn = 0; nn < nptls; nn++) csound->Warning(csound, "\t%d", p->pdist[nn]); if (p->rolloff) { csound->Warning(csound, Str("\n\t\trolloff vals:")); for (nn = 0; nn < nptls; nn++) csound->Warning(csound, "\t%4.2f", p->pmult[nn]); } dbthresh = *p->idbthresh; /* thresholds: */ ampthresh = (MYFLT)exp((double)dbthresh * LOG10D20); switch(inspecp->dbout) { case 0: p->threshon = ampthresh; /* mag */ p->threshoff = ampthresh / FL(2.0); break; case 1: p->threshon = dbthresh; /* db */ p->threshoff = dbthresh - FL(6.0); break; case 2: p->threshon = ampthresh * ampthresh; /* mag sqrd */ p->threshoff = p->threshon / FL(4.0); break; case 3: p->threshon = (MYFLT)sqrt(ampthresh); /* root mag */ p->threshoff = p->threshon / FL(1.414); break; } p->threshon *= weightsum; p->threshoff *= weightsum; csound->Warning(csound, Str("\n\tdbthresh %4.1f: X-corr %s " "threshon %4.1f, threshoff %4.1f\n"), dbthresh, outstring[inspecp->dbout], p->threshon, p->threshoff); p->oct0p = oct0p; /* virtual loc of oct 0 */ p->confact = *p->iconf; p->flop = flop; p->fhip = fhip; p->kinterp = (*p->interp == FL(0.0)) ? 0 : 1; p->playing = 0; p->kvalsav = *p->istrt; p->kval = p->kinc = FL(0.0); p->kavl = p->kanc = FL(0.0); p->jmpcount = 0; return OK; } #define STARTING 1 #define PLAYING 2 int specptrk(CSOUND *csound, SPECPTRK *p) { SPECDAT *inspecp = p->wsig; if (inspecp->ktimstamp == CS_KCNT) { /* if inspectrum is new: */ MYFLT *inp = (MYFLT *) inspecp->auxch.auxp; MYFLT *endp = inp + inspecp->npts; MYFLT *inp2, sum, *fp; int nn, *pdist, confirms; MYFLT kval, kvar, fmax, *fmaxp, absdiff, realbin; MYFLT *flop, *fhip, *ilop, *ihip, a, b, c, denom, delta; int32 lobin, hibin; if (UNLIKELY(inp==NULL)) goto err1; /* RWD fix */ kvar = FABS(*p->kvar); kval = p->playing == PLAYING ? p->kval : p->kvalsav; lobin = (int32)((kval-kvar) * inspecp->nfreqs); /* set lims of frq interest */ hibin = (int32)((kval+kvar) * inspecp->nfreqs); if ((flop = p->oct0p + lobin) < p->flop) /* as fundp bin pntrs */ flop = p->flop; if ((fhip = p->oct0p + hibin) > p->fhip) /* within hard limits */ fhip = p->fhip; ilop = inp + (flop - p->fundp); /* similar for input bins */ ihip = inp + (fhip - p->fundp); if (p->ftimcnt) { /* if displaying, */ for (fp = p->flop; fp < flop; ) /* clr to limits */ *fp++ = FL(0.0); for (fp = p->fhip; fp > fhip; ) *--fp = FL(0.0); } inp = ilop; fp = flop; if (p->rolloff) { MYFLT *pmult; do { sum = *inp; pdist = p->pdist + 1; pmult = p->pmult + 1; for (nn = p->nptls; --nn; ) { if ((inp2 = inp + *pdist++) >= endp) break; sum += *inp2 * *pmult++; } *fp++ = sum; } while (++inp < ihip); } else { do { sum = *inp; pdist = p->pdist + 1; for (nn = p->nptls; --nn; ) { if ((inp2 = inp + *pdist++) >= endp) break; sum += *inp2; } *fp++ = sum; } while (++inp < ihip); } fp = flop; /* now srch fbins for peak */ for (fmaxp = fp, fmax = *fp; ++fp fmax) { fmax = *fp; fmaxp = fp; } if (!p->playing) { if (fmax > p->threshon) /* not playing & threshon? */ p->playing = STARTING; /* prepare to turn on */ else goto output; } else { if (fmax < p->threshoff) { /* playing & threshoff ? */ if (p->playing == PLAYING) p->kvalsav = p->kval; /* save val & turn off */ p->kval = FL(0.0); p->kavl = FL(0.0); p->kinc = FL(0.0); p->kanc = FL(0.0); p->playing = 0; goto output; } } a = fmaxp>flop ? *(fmaxp-1) : FL(0.0); /* calc a refined bin no */ b = fmax; c = fmaxpoct0p) + delta; /* get modified bin number */ kval = realbin / inspecp->nfreqs; /* & cvt to true decoct */ if (p->playing == STARTING) { /* STARTING mode: */ absdiff = FABS(kval - p->kvalsav); confirms = (int)(absdiff * p->confact); /* get interval dependency */ if (p->jmpcount < confirms) { p->jmpcount += 1; /* if not enough confirms, */ goto output; /* must wait some more */ } else { p->playing = PLAYING; /* else switch on playing */ p->jmpcount = 0; p->kval = kval; /* but suppress interp */ p->kinc = FL(0.0); } } else { /* PLAYING mode: */ absdiff = FABS(kval - p->kval); confirms = (int)(absdiff * p->confact); /* get interval dependency */ if (p->jmpcount < confirms) { p->jmpcount += 1; /* if not enough confirms, */ p->kinc = FL(0.0); /* must wait some more */ } else { p->jmpcount = 0; /* else OK to jump interval */ if (p->kinterp) /* with optional interp */ p->kinc = (kval - p->kval) / inspecp->ktimprd; else p->kval = kval; } } fmax += delta * (c - a) / FL(4.0); /* get modified amp */ if (p->kinterp) /* & new kanc if interp */ p->kanc = (fmax - p->kavl) / inspecp->ktimprd; else p->kavl = fmax; } output: *p->koct = p->kval; /* output true decoct & amp */ *p->kamp = p->kavl; if (p->kinterp) { /* interp if reqd */ p->kval += p->kinc; p->kavl += p->kanc; } if (p->ftimcnt) specdisp(csound,&p->fdisplay); return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("specptrk: not initialised")); } int spsumset(CSOUND *csound, SPECSUM *p) { p->kinterp = (*p->interp == FL(0.0)) ? 0 : 1; p->kinc = p->kval = FL(0.0); return OK; } int specsum(CSOUND *csound, SPECSUM *p) /* sum all vals of a spectrum and put as ksig */ /* optionally interpolate the output */ { SPECDAT *specp = p->wsig; if (UNLIKELY(specp->auxch.auxp==NULL)) goto err1; /* RWD fix */ if (specp->ktimstamp == CS_KCNT) { /* if spectrum is new */ MYFLT *valp = (MYFLT *) specp->auxch.auxp; MYFLT sum = FL(0.0); int32 n,npts = specp->npts; /* sum all the values */ for (n=0;nkinterp) /* new kinc if interp */ p->kinc = (sum - p->kval) / specp->ktimprd; else p->kval = sum; } *p->ksum = p->kval; /* output current kval */ if (p->kinterp) /* & interp if reqd */ p->kval += p->kinc; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("specsum: not initialised")); } int spadmset(CSOUND *csound, SPECADDM *p) { SPECDAT *inspec1p = p->wsig1; SPECDAT *inspec2p = p->wsig2; int npts; if (UNLIKELY((npts = inspec1p->npts) != inspec2p->npts)) /* inspecs must agree in size */ return csound->InitError(csound, Str("inputs have different sizes")); if (UNLIKELY(inspec1p->ktimprd != inspec2p->ktimprd)) /* time period */ return csound->InitError(csound, Str("inputs have diff. time periods")); if (UNLIKELY(inspec1p->nfreqs != inspec2p->nfreqs)) /* frq resoltn */ return csound->InitError(csound, Str("inputs have different freq resolution")); if (UNLIKELY(inspec1p->dbout != inspec2p->dbout)) /* and db type */ return csound->InitError(csound, Str("inputs have different amptypes")); if (npts != p->waddm->npts) { /* if out does not match ins */ SPECset(csound, p->waddm, (int32)npts); /* reinit the out spec */ p->waddm->downsrcp = inspec1p->downsrcp; } p->waddm->ktimprd = inspec1p->ktimprd; /* pass the other specinfo */ p->waddm->nfreqs = inspec1p->nfreqs; p->waddm->dbout = inspec1p->dbout; p->waddm->ktimstamp = 0; /* mark the outspec not new */ return OK; } int specaddm(CSOUND *csound, SPECADDM *p) { if (UNLIKELY((p->wsig1->auxch.auxp==NULL) || /* RWD fix */ (p->wsig2->auxch.auxp==NULL) || (p->waddm->auxch.auxp==NULL))) goto err1; if (p->wsig1->ktimstamp == CS_KCNT) { /* if inspec1 is new: */ MYFLT *in1p = (MYFLT *) p->wsig1->auxch.auxp; MYFLT *in2p = (MYFLT *) p->wsig2->auxch.auxp; MYFLT *outp = (MYFLT *) p->waddm->auxch.auxp; MYFLT mul2 = p->mul2; int n,npts = p->wsig1->npts; for (n=0;nwaddm->ktimstamp = CS_KCNT; /* mark the output spec as new */ } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("specaddm: not initialised")); } int spdifset(CSOUND *csound, SPECDIFF *p) { SPECDAT *inspecp = p->wsig; MYFLT *lclp; MYFLT *outp; int npts; if ((npts = inspecp->npts) != p->specsave.npts) { /* if inspec not matched */ SPECset(csound, &p->specsave, (int32)npts); /* reinit the save spec */ SPECset(csound, p->wdiff, (int32)npts); /* & the out diff spec */ p->wdiff->downsrcp = inspecp->downsrcp; } p->wdiff->ktimprd = inspecp->ktimprd; /* pass the other specinfo */ p->wdiff->nfreqs = inspecp->nfreqs; p->wdiff->dbout = inspecp->dbout; lclp = (MYFLT *) p->specsave.auxch.auxp; outp = (MYFLT *) p->wdiff->auxch.auxp; if (UNLIKELY(lclp==NULL || outp==NULL)) { /* RWD */ return csound->InitError(csound, Str("specdiff: local buffers not initialised")); } memset(lclp, 0, npts*sizeof(MYFLT)); /* clr local & out spec bufs */ memset(outp, 0, npts*sizeof(MYFLT)); p->wdiff->ktimstamp = 0; /* mark the out spec not new */ return OK; } int specdiff(CSOUND *csound, SPECDIFF *p) { SPECDAT *inspecp = p->wsig; if (UNLIKELY((inspecp->auxch.auxp==NULL) /* RWD fix */ || (p->specsave.auxch.auxp==NULL) || (p->wdiff->auxch.auxp==NULL))) goto err1; if (inspecp->ktimstamp == CS_KCNT) { /* if inspectrum is new: */ MYFLT *newp = (MYFLT *) inspecp->auxch.auxp; MYFLT *prvp = (MYFLT *) p->specsave.auxch.auxp; MYFLT *difp = (MYFLT *) p->wdiff->auxch.auxp; MYFLT newval, prvval, diff, possum = FL(0.0); /* possum not used! */ int n,npts = inspecp->npts; for (n=0; n FL(0.0)) { /* if new coef > prv coef */ difp[n] = diff; possum += diff; /* enter & accum diff */ } else difp[n] = FL(0.0); /* else enter zero */ prvp[n] = newval; /* sav newval for nxt time */ } p->wdiff->ktimstamp = CS_KCNT; /* mark the output spec as new */ } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("specdiff: not initialised")); } int spsclset(CSOUND *csound, SPECSCAL *p) { SPECDAT *inspecp = p->wsig; SPECDAT *outspecp = p->wscaled; FUNC *ftp; int32 npts; if ((npts = inspecp->npts) != outspecp->npts) { /* if size has changed, */ SPECset(csound, outspecp, (int32)npts); /* realloc */ outspecp->downsrcp = inspecp->downsrcp; csound->AuxAlloc(csound, (int32)npts * 2 * sizeof(MYFLT), &p->auxch); } outspecp->ktimprd = inspecp->ktimprd; /* pass the source spec info */ outspecp->nfreqs = inspecp->nfreqs; outspecp->dbout = inspecp->dbout; p->fscale = (MYFLT *) p->auxch.auxp; /* setup scale & thresh fn areas */ if (UNLIKELY(p->fscale==NULL)) { /* RWD fix */ return csound->InitError(csound, Str("specscal: local buffer not initialised")); } p->fthresh = p->fscale + npts; if (UNLIKELY((ftp=csound->FTFind(csound, p->ifscale)) == NULL)) { /* if fscale given, */ return csound->InitError(csound, Str("missing fscale table")); } else { int32 nn = npts; int32 phs = 0; int32 inc = (int32)PHMASK / npts; int32 lobits = ftp->lobits; MYFLT *ftable = ftp->ftable; MYFLT *flp = p->fscale; for (nn=0;nn> lobits)); /* sample into scale area */ phs += inc; } } if ((p->thresh = (int)*p->ifthresh) && (ftp=csound->FTFind(csound, p->ifthresh)) != NULL) { /* if fthresh given, */ int32 nn = npts; int32 phs = 0; int32 inc = (int32)PHMASK / npts; int32 lobits = ftp->lobits; MYFLT *ftable = ftp->ftable; MYFLT *flp = p->fthresh; for (nn=0;nn> lobits)); /* sample into thresh area */ phs += inc; } } else p->thresh = 0; outspecp->ktimstamp = 0; /* mark the out spec not new */ return OK; } int specscal(CSOUND *csound, SPECSCAL *p) { SPECDAT *inspecp = p->wsig; if ((inspecp->auxch.auxp==NULL) /* RWD fix */ || (p->wscaled->auxch.auxp==NULL) || (p->fscale==NULL)) goto err1; if (inspecp->ktimstamp == CS_KCNT) { /* if inspectrum is new: */ SPECDAT *outspecp = p->wscaled; MYFLT *inp = (MYFLT *) inspecp->auxch.auxp; MYFLT *outp = (MYFLT *) outspecp->auxch.auxp; MYFLT *sclp = p->fscale; int32 n,npts = inspecp->npts; if (p->thresh) { /* if thresh requested, */ MYFLT *threshp = p->fthresh; MYFLT val; for (n=0; n FL(0.0)) /* for vals above thresh */ outp[n] = val * sclp[n]; /* scale & write out */ else outp[n] = FL(0.0); /* else output is 0. */ } } else { for (n=0; nktimstamp = CS_KCNT; /* mark the outspec as new */ } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("specscal: not initialised")); } int sphstset(CSOUND *csound, SPECHIST *p) { SPECDAT *inspecp = p->wsig; MYFLT *lclp; MYFLT *outp; int npts; if ((npts = inspecp->npts) != p->accumer.npts) { /* if inspec not matched */ SPECset(csound, &p->accumer, (int32)npts); /* reinit the accum spec */ SPECset(csound, p->wacout, (int32)npts); /* & the output spec */ p->wacout->downsrcp = inspecp->downsrcp; } p->wacout->ktimprd = inspecp->ktimprd; /* pass the other specinfo */ p->wacout->nfreqs = inspecp->nfreqs; p->wacout->dbout = inspecp->dbout; lclp = (MYFLT *) p->accumer.auxch.auxp; outp = (MYFLT *) p->wacout->auxch.auxp; if (UNLIKELY(lclp==NULL || outp==NULL)) { /* RWD fix */ return csound->InitError(csound, Str("spechist: local buffers not initialised")); } memset(lclp,0,npts*sizeof(MYFLT)); /* clr local & out spec bufs */ memset(outp,0,npts*sizeof(MYFLT)); p->wacout->ktimstamp = 0; /* mark the out spec not new */ return OK; } int spechist(CSOUND *csound, SPECHIST *p) { SPECDAT *inspecp = p->wsig; if (UNLIKELY((inspecp->auxch.auxp==NULL) /* RWD fix */ || (p->accumer.auxch.auxp==NULL) || (p->wacout->auxch.auxp==NULL))) goto err1; if (inspecp->ktimstamp == CS_KCNT) { /* if inspectrum is new: */ MYFLT *newp = (MYFLT *) inspecp->auxch.auxp; MYFLT *acup = (MYFLT *) p->accumer.auxch.auxp; MYFLT *outp = (MYFLT *) p->wacout->auxch.auxp; MYFLT newval; int n,npts = inspecp->npts; for (n=0;nwacout->ktimstamp = CS_KCNT; /* mark the output spec as new */ } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("spechist: not initialised")); } int spfilset(CSOUND *csound, SPECFILT *p) { SPECDAT *inspecp = p->wsig; SPECDAT *outspecp = p->wfil; FUNC *ftp; int32 npts; if ((npts = inspecp->npts) != outspecp->npts) { /* if inspec not matched */ SPECset(csound, outspecp, (int32)npts); /* reinit the out spec */ csound->AuxAlloc(csound, (size_t)npts*2* sizeof(MYFLT), &p->auxch); /* & local auxspace */ p->coefs = (MYFLT *) p->auxch.auxp; /* reassign filt tbls */ p->states = p->coefs + npts; } if (UNLIKELY(p->coefs==NULL || p->states==NULL)) { /* RWD fix */ return csound->InitError(csound, Str("specfilt: local buffers not initialised")); } outspecp->ktimprd = inspecp->ktimprd; /* pass other spect info */ outspecp->nfreqs = inspecp->nfreqs; outspecp->dbout = inspecp->dbout; outspecp->downsrcp = inspecp->downsrcp; if (UNLIKELY((ftp=csound->FTFind(csound, p->ifhtim)) == NULL)) { /* if fhtim table given, */ return csound->InitError(csound, Str("missing htim ftable")); } { int32 nn; int32 phs = 0; int32 inc = (int32)PHMASK / npts; int32 lobits = ftp->lobits; MYFLT *ftable = ftp->ftable; MYFLT *flp = p->coefs; for (nn=0;nn> lobits)); /* sample into coefs area */ phs += inc; } } { int32 nn; MYFLT *flp = p->coefs; double halftim, reittim = inspecp->ktimprd * CS_ONEDKR; for (nn=0;nn 0.) flp[nn] = (MYFLT)pow(0.5, reittim/halftim); else { return csound->InitError(csound, Str("htim ftable must be all-positive")); } } } csound->Warning(csound, Str("coef range: %6.3f - %6.3f\n"), *p->coefs, *(p->coefs+npts-1)); { MYFLT *flp = (MYFLT *) p->states; memset(flp,0,npts*sizeof(MYFLT)); /* clr the persist buf state mem */ } outspecp->ktimstamp = 0; /* mark the output spec as not new */ return OK; } int specfilt(CSOUND *csound, SPECFILT *p) { if (p->wsig->ktimstamp == CS_KCNT) { /* if input spec is new, */ SPECDAT *inspecp = p->wsig; SPECDAT *outspecp = p->wfil; MYFLT *newp = (MYFLT *) inspecp->auxch.auxp; MYFLT *outp = (MYFLT *) outspecp->auxch.auxp; MYFLT curval, *coefp = p->coefs; MYFLT *persp = p->states; int n,npts = inspecp->npts; if (UNLIKELY(newp==NULL || outp==NULL || coefp==NULL || persp==NULL)) /* RWD */ goto err1; for (n=0; nktimstamp = CS_KCNT; /* mark output spec as new */ } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("specfilt: not initialised")); } #define S sizeof static OENTRY spectra_localops[] = { { "spectrum", S(SPECTRUM),_QQ, 7, "w", "xiiiqoooo", (SUBR)spectset,(SUBR)spectrum,(SUBR)spectrum}, { "specaddm", S(SPECADDM),_QQ, 5, "w", "wwp", (SUBR)spadmset,NULL, (SUBR)specaddm}, { "specdiff", S(SPECDIFF),_QQ, 5, "w", "w", (SUBR)spdifset,NULL, (SUBR)specdiff}, { "specscal", S(SPECSCAL),_QQ, 5, "w", "wii", (SUBR)spsclset,NULL, (SUBR)specscal}, { "spechist", S(SPECHIST),_QQ, 5, "w", "w", (SUBR)sphstset,NULL, (SUBR)spechist}, { "specfilt", S(SPECFILT),_QQ, 5, "w", "wi", (SUBR)spfilset,NULL, (SUBR)specfilt}, { "specptrk", S(SPECPTRK),_QQ, 5, "kk", "wkiiiiiioqooo", (SUBR)sptrkset,NULL,(SUBR)specptrk}, { "specsum", S(SPECSUM), _QQ, 5, "k", "wo", (SUBR)spsumset,NULL, (SUBR)specsum }, { "specdisp", S(SPECDISP),_QQ, 5, "", "wio", (SUBR)spdspset,NULL, (SUBR)specdisp}, { "pitch", S(PITCH), 0, 5, "kk", "aiiiiqooooojo", (SUBR)pitchset, NULL, (SUBR)pitch }, { "maca", S(SUM), 0, 5, "a", "y", (SUBR)macset, NULL, (SUBR)maca }, { "mac", S(SUM), 0, 5, "a", "Z", (SUBR)macset, NULL, (SUBR)mac }, { "clockon", S(CLOCK), 0, 3, "", "i", (SUBR)clockset, (SUBR)clockon, NULL }, { "clockoff", S(CLOCK),0, 3, "", "i", (SUBR)clockset, (SUBR)clockoff, NULL }, { "readclock", S(CLKRD),0, 1, "i", "i", (SUBR)clockread, NULL, NULL }, { "readscratch", S(SCRATCHPAD),0, 1, "i", "o", (SUBR)scratchread, NULL, NULL }, { "writescratch", S(SCRATCHPAD),0, 1, "", "io", (SUBR)scratchwrite, NULL, NULL }, { "pitchamdf",S(PITCHAMDF),0,5,"kk","aiioppoo", (SUBR)pitchamdfset, NULL, (SUBR)pitchamdf }, { "hsboscil",S(HSBOSC), TR, 5, "a", "kkkiiioo", (SUBR)hsboscset,NULL,(SUBR)hsboscil }, { "phasorbnk", S(PHSORBNK),0,5,"a", "xkio", (SUBR)phsbnkset, (SUBR)NULL, (SUBR)phsorbnk }, { "phasorbnk.k", S(PHSORBNK),0,3,"k", "xkio", (SUBR)phsbnkset, (SUBR)kphsorbnk, NULL}, { "adsynt",S(HSBOSC), TR, 5, "a", "kkiiiio", (SUBR)adsyntset, NULL, (SUBR)adsynt }, { "mpulse", S(IMPULSE), 0, 5, "a", "kko", (SUBR)impulse_set, NULL, (SUBR)impulse }, { "lpf18", S(LPF18), 0, 5, "a", "axxxo", (SUBR)lpf18set, NULL, (SUBR)lpf18db }, { "waveset", S(BARRI), 0, 5, "a", "ako", (SUBR)wavesetset, NULL, (SUBR)waveset}, { "pinkish", S(PINKISH), 0, 5, "a", "xoooo", (SUBR)pinkset, NULL, (SUBR)pinkish }, { "noise", S(VARI), 0, 5, "a", "xk", (SUBR)varicolset, NULL, (SUBR)varicol }, { "transeg", S(TRANSEG),0, 3, "k", "iiim", (SUBR)trnset,(SUBR)ktrnseg, NULL}, { "transeg.a", S(TRANSEG),0, 5, "a", "iiim", (SUBR)trnset,NULL,(SUBR)trnseg}, { "transegb", S(TRANSEG),0, 3, "k", "iiim", (SUBR)trnset_bkpt,(SUBR)ktrnseg,(SUBR)NULL}, { "transegb.a", S(TRANSEG),0, 5, "a", "iiim", (SUBR)trnset_bkpt,NULL,(SUBR)trnseg }, { "transegr", S(TRANSEG),0, 3, "k", "iiim", (SUBR)trnsetr,(SUBR)ktrnsegr,(SUBR)NULL }, { "transegr.a", S(TRANSEG),0, 5, "a", "iiim", (SUBR)trnsetr,NULL,(SUBR)trnsegr }, { "clip", S(CLIP), 0, 5, "a", "aiiv", (SUBR)clip_set, NULL, (SUBR)clip }, { "cpuprc", S(CPU_PERC),0, 1, "", "Si", (SUBR)cpuperc_S, NULL, NULL }, { "maxalloc", S(CPU_PERC),0, 1, "", "Si", (SUBR)maxalloc_S, NULL, NULL }, { "cpuprc", S(CPU_PERC),0, 1, "", "ii", (SUBR)cpuperc, NULL, NULL }, { "maxalloc", S(CPU_PERC),0, 1, "", "ii", (SUBR)maxalloc, NULL, NULL }, { "active", 0xffff }, { "active.iS", S(INSTCNT),0,1, "i", "Soo", (SUBR)instcount_S, NULL, NULL }, { "active.kS", S(INSTCNT),0,2, "k", "Soo", NULL, (SUBR)instcount_S, NULL }, { "active.i", S(INSTCNT),0,1, "i", "ioo", (SUBR)instcount, NULL, NULL }, { "active.k", S(INSTCNT),0,2, "k", "koo", NULL, (SUBR)instcount, NULL }, { "p.i", S(PFUN), 0,1, "i", "i", (SUBR)pfun, NULL, NULL }, { "p.k", S(PFUNK), 0,3, "k", "k", (SUBR)pfunk_init, (SUBR)pfunk, NULL }, { "mute", S(MUTE), 0,1, "", "So", (SUBR)mute_inst_S }, { "mute.i", S(MUTE), 0,1, "", "io", (SUBR)mute_inst }, { "median", S(MEDFILT), 0, 5, "a", "akio", (SUBR)medfiltset, NULL, (SUBR)medfilt }, { "mediank", S(MEDFILT), 0,5, "k", "kkio", (SUBR)medfiltset, (SUBR)kmedfilt}, }; LINKAGE_BUILTIN(spectra_localops) csound-6.10.0/Opcodes/spectra.h000066400000000000000000000070131321653344700163100ustar00rootroot00000000000000/* spectra.h: Copyright (C) 1995 Barry Vercoe This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* SPECTRA.H */ #ifndef __SPECTRA_H #define __SPECTRA_H #define MAXFRQS 120 typedef struct { OPDS h; SPECDAT *wsig; MYFLT *signal,*iprd,*iocts,*ifrqs,*iq,*ihann; MYFLT *idbout,*idisprd,*idsines; int nfreqs, hanning, ncoefs, dbout, nsmps, scountdown; uint32_t timcount; MYFLT curq, *sinp, *cosp, *linbufp; int disprd, dcountdown, winlen[MAXFRQS], offset[MAXFRQS]; DOWNDAT downsig; WINDAT sinwindow, octwindow; AUXCH auxch1, auxch2; } SPECTRUM; #if 0 typedef struct { OPDS h; SPECDAT *wsig; DOWNDAT *dsig; MYFLT *iprd, *ifrqs, *iq, *ihann, *idbout, *idsines; int nfreqs, hanning, ncoefs, dbout; MYFLT curq, *sinp, *cosp, *linbufp; int countdown, timcount, winlen[MAXFRQS]; WINDAT dwindow; AUXCH auxch; } NOCTDFT; #endif typedef struct { OPDS h; SPECDAT *wsig; MYFLT *iprd, *iwtflg; int countdown, timcount; WINDAT dwindow; } SPECDISP; #define MAXPTL 10 typedef struct { OPDS h; MYFLT *koct, *kamp; SPECDAT *wsig; MYFLT *kvar, *ilo, *ihi, *istrt, *idbthresh, *inptls, *irolloff; MYFLT *iodd, *iconf, *interp, *ifprd, *iwtflg; int pdist[MAXPTL], nptls, rolloff, kinterp, ftimcnt; MYFLT pmult[MAXPTL], confact, kvalsav, kval, kavl, kinc, kanc; MYFLT *flop, *fhip, *fundp, *oct0p, threshon, threshoff; int winpts, jmpcount, playing; SPECDAT wfund; SPECDISP fdisplay; } SPECPTRK; typedef struct { OPDS h; MYFLT *ksum; SPECDAT *wsig; MYFLT *interp; int kinterp; MYFLT kval, kinc; } SPECSUM; typedef struct { OPDS h; SPECDAT *waddm; SPECDAT *wsig1, *wsig2; MYFLT *imul2; MYFLT mul2; } SPECADDM; typedef struct { OPDS h; SPECDAT *wdiff; SPECDAT *wsig; SPECDAT specsave; } SPECDIFF; typedef struct { OPDS h; SPECDAT *wscaled; SPECDAT *wsig; MYFLT *ifscale, *ifthresh; int thresh; MYFLT *fscale, *fthresh; AUXCH auxch; } SPECSCAL; typedef struct { OPDS h; SPECDAT *wacout; SPECDAT *wsig; SPECDAT accumer; } SPECHIST; typedef struct { OPDS h; SPECDAT *wfil; SPECDAT *wsig; MYFLT *ifhtim; MYFLT *coefs, *states; AUXCH auxch; } SPECFILT; extern void DOWNset(CSOUND *, DOWNDAT *, int32); extern void SPECset(CSOUND *, SPECDAT *, int32); #endif csound-6.10.0/Opcodes/squinewave.c000066400000000000000000000316751321653344700170440ustar00rootroot00000000000000/* SQUINEWAVE.C: Sine-Square-Pulse-Saw oscillator * by rasmus ekman 2017, for Csound. * This code is released under the Csound license, * GNU Lesser General Public License version 2.1. */ /* Copyright (C) 2017 rasmus ekman 2017 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "csoundCore.h" /* ================================================================== */ typedef struct { OPDS h; MYFLT *aout, *async_out, *acps, *aclip, *askew, *async_in, *iminsweep, *iphase; // phase and warped_phase range 0-2. //This makes skew/clip into simple proportions double phase; double warped_phase; double hardsync_phase; double hardsync_inc; // Const inited from environment double Min_Sweep; double Maxphase_By_sr; double Max_Warp_Freq; MYFLT *sync_sig; // holds async_in if a-rate int32_t init_phase; } SQUINEWAVE; /* ================================================================== */ static inline int32_t find_sync(const MYFLT* sync_sig, const uint32_t first, const uint32_t last) { uint32_t i; if (sync_sig == 0) return -1; for (i = first; i < last; ++i) { if (sync_sig[i] >= (MYFLT)1) return i; } return -1; } /* ================================================================== */ static void hardsync_init(SQUINEWAVE *p, const double freq, const double warped_phase) { if (p->hardsync_phase) return; // If we're in last flat part, we're just done now if (warped_phase == 2.0) { p->phase = 2.0; return; } if (freq > p->Max_Warp_Freq) return; p->hardsync_inc = (PI / p->Min_Sweep); p->hardsync_phase = p->hardsync_inc * 0.5; } /* ================================================================== */ static inline MYFLT Clamp(const MYFLT x, const MYFLT minval, const MYFLT maxval) { return (x < minval) ? minval : (x > maxval) ? maxval : x; } /* ================================================================== */ int squinewave_init(CSOUND* csound, SQUINEWAVE *p) { const double sr = csound->GetSr(csound); // Skip setting phase only if we have been inited at least once p->init_phase = (*p->iphase < 0 && p->Min_Sweep > 1.0) ? 0 : 1; p->Min_Sweep = *p->iminsweep; // Allow range 4-sr/100 if (p->Min_Sweep < 4.0 || p->Min_Sweep > sr * 0.01) { const int32_t minsweep_default = (int32_t)Clamp(sr / 3000.0, 8.0, sr * 0.01); if (p->Min_Sweep != 0.0) { csound->Warning(csound, Str("squinewave iminsweep range 4 to sr/100. " "Set to default %d"), minsweep_default); } p->Min_Sweep = minsweep_default; } p->Maxphase_By_sr = 2.0 / sr; p->Max_Warp_Freq = sr / (2.0 * p->Min_Sweep); p->sync_sig = IS_ASIG_ARG(p->async_in) ? p->async_in : 0; return OK; } /* ================================================================== */ int squinewave_gen(CSOUND* csound, SQUINEWAVE *p) { const uint32_t nsmps = CS_KSMPS; uint32_t n; // Clear parts of output outside event const uint32_t ksmps_offset = p->h.insdshead->ksmps_offset; const uint32_t ksmps_end = nsmps - p->h.insdshead->ksmps_no_end; if (UNLIKELY(ksmps_offset)) memset(p->aout, 0, ksmps_offset * sizeof(MYFLT)); if (UNLIKELY(ksmps_end < nsmps)) { memset(&p->aout[ksmps_end], 0, p->h.insdshead->ksmps_no_end * sizeof(MYFLT)); } const double Maxphase_By_sr = p->Maxphase_By_sr; const double Max_Warp_Freq = p->Max_Warp_Freq; const double Max_Warp = 1.0 / p->Min_Sweep; const double Min_Sweep = p->Min_Sweep; MYFLT *aout = &p->aout[0]; const MYFLT * const freq_sig = p->acps; const MYFLT * const clip_sig = p->aclip; const MYFLT * const skew_sig = p->askew; double phase = p->phase; double warped_phase = p->warped_phase; double hardsync_phase = p->hardsync_phase; double hardsync_inc = p->hardsync_inc; int32_t sync = find_sync(p->sync_sig, ksmps_offset, ksmps_end); // Set main phase so it matches warp if (p->init_phase) { const double freq = fmax(freq_sig[0], 0.0); const double phase_inc = Maxphase_By_sr * freq; const double min_sweep = phase_inc * Min_Sweep; const double skew = 1.0 - Clamp(skew_sig[0], -1.0, 1.0); const double clip = 1.0 - Clamp(clip_sig[0], 0.0, 1.0); const double midpoint = Clamp(skew, min_sweep, 2.0 - min_sweep); // Init phase range 0-2, has 4 segment parts (sweep down, // flat -1, sweep up, flat +1) warped_phase = *p->iphase; if (warped_phase < 0.0) { // "up" 0-crossing warped_phase = 1.25; } if (warped_phase > 2.0) warped_phase = fmod(warped_phase, 2.0); // Select segment and scale within if (warped_phase < 1.0) { const double sweep_length = fmax(clip * midpoint, min_sweep); if (warped_phase < 0.5) { phase = sweep_length * (warped_phase * 2.0); warped_phase *= 2.0; } else { const double flat_length = midpoint - sweep_length; phase = sweep_length + flat_length * ((warped_phase - 0.5) * 2.0); warped_phase = 1.0; } } else { const double sweep_length = fmax(clip * (2.0 - midpoint), min_sweep); if (warped_phase < 1.5) { phase = midpoint + sweep_length * ((warped_phase - 1.0) * 2.0); warped_phase = 1.0 + (warped_phase - 1.0) * 2.0; } else { const double flat_length = 2.0 - (midpoint + sweep_length); phase = midpoint + sweep_length + flat_length * ((warped_phase - 1.5) * 2.0); warped_phase = 2.0; } } p->init_phase = 0; } if (p->async_out) memset(p->async_out, 0, nsmps * sizeof(MYFLT)); for (n = ksmps_offset; n < ksmps_end; ++n) { double freq = fmax(freq_sig[n], 0.0); if (sync == (int32_t)n) { p->phase = phase; p->hardsync_phase = hardsync_phase; p->hardsync_inc = hardsync_inc; hardsync_init(p, freq, warped_phase); phase = p->phase; hardsync_phase = p->hardsync_phase; hardsync_inc = p->hardsync_inc; } if (hardsync_phase) { const double syncsweep = 0.5 * (1.0 - cos(hardsync_phase)); freq += syncsweep * ((2.0 * Max_Warp_Freq) - freq); hardsync_phase += hardsync_inc; if (hardsync_phase > PI) { hardsync_phase = PI; hardsync_inc = 0.0; } } const double phase_inc = Maxphase_By_sr * freq; // Pure sine if freq > sr/(2*Min_Sweep) if (freq >= Max_Warp_Freq) { // Continue from warped *aout++ = cos(PI * warped_phase); phase = warped_phase; warped_phase += phase_inc; } else { const double min_sweep = phase_inc * Min_Sweep; const double skew = 1.0 - Clamp(skew_sig[n], -1.0, 1.0); const double clip = 1.0 - Clamp(clip_sig[n], 0.0, 1.0); const double midpoint = Clamp(skew, min_sweep, 2.0 - min_sweep); // 1st half: Sweep down to cos(warped_phase <= Pi) then // flat -1 until phase >= midpoint if (warped_phase < 1.0 || (warped_phase == 1.0 && phase < midpoint)) { if (warped_phase < 1.0) { const double sweep_length = fmax(clip * midpoint, min_sweep); *aout++ = cos(PI * warped_phase); warped_phase += fmin(phase_inc / sweep_length, Max_Warp); // Handle fractional warped_phase overshoot after sweep ends if (warped_phase > 1.0) { /* Tricky here: phase and warped may disagree where * we are in waveform (due to FM + skew/clip * changes). Warped dominates to keep waveform * stable, waveform (flat part) decides where we * are. */ const double flat_length = midpoint - sweep_length; // warp overshoot scaled to main phase rate const double phase_overshoot = (warped_phase - 1.0) * sweep_length; // phase matches shape phase = midpoint - flat_length + phase_overshoot - phase_inc; // Flat if next samp still not at midpoint if (flat_length >= phase_overshoot) { warped_phase = 1.0; // phase may be > midpoint here (which means // actually no flat part), if so it will be // corrected in 2nd half (since warped == 1.0) } else { const double next_sweep_length = fmax(clip * (2.0 - midpoint), min_sweep); warped_phase = 1.0 + (phase_overshoot - flat_length) / next_sweep_length; } } } else { // flat up to midpoint *aout++ = -1.0; warped_phase = 1.0; } } // 2nd half: Sweep up to cos(warped_phase <= 2.Pi) then // flat +1 until phase >= 2 else { if (warped_phase < 2.0) { const double sweep_length = fmax(clip * (2.0 - midpoint), min_sweep); if (warped_phase == 1.0) { // warped_phase overshoot after flat part warped_phase = 1.0 + fmin( fmin(phase - midpoint, phase_inc) / sweep_length, Max_Warp); } *aout++ = cos(PI * warped_phase); warped_phase += fmin(phase_inc / sweep_length, Max_Warp); if (warped_phase > 2.0) { const double flat_length = 2.0 - (midpoint + sweep_length); const double phase_overshoot = (warped_phase - 2.0) * sweep_length; phase = 2.0 - flat_length + phase_overshoot - phase_inc; if (flat_length >= phase_overshoot) { warped_phase = 2.0; } else { const double next_sweep_length = fmax(clip * midpoint, min_sweep); warped_phase = 2.0 + (phase_overshoot - flat_length) / next_sweep_length; } } } else { *aout++ = 1.0; warped_phase = 2.0; } } } phase += phase_inc; if (warped_phase >= 2.0 && phase >= 2.0) { if (hardsync_phase) { warped_phase = phase = 0.0; hardsync_phase = hardsync_inc = 0.0; sync = find_sync(p->sync_sig, n + 1, ksmps_end); } else { phase -= 2.0; if (phase > phase_inc) { // wild aliasing freq - just reset phase = phase_inc * 0.5; } if (freq < Max_Warp_Freq) { const double min_sweep = phase_inc * Min_Sweep; const double skew = 1.0 - Clamp(skew_sig[n], -1.0, 1.0); const double clip = 1.0 - Clamp(clip_sig[n], 0.0, 1.0); const double midpoint = Clamp(skew, min_sweep, 2.0 - min_sweep); const double next_sweep_length = fmax(clip * midpoint, min_sweep); warped_phase = fmin(phase / next_sweep_length, Max_Warp); } else warped_phase = phase; } if (p->async_out) p->async_out[n] = 1.0; } } p->phase = phase; p->warped_phase = warped_phase; p->hardsync_phase = hardsync_phase; p->hardsync_inc = hardsync_inc; return OK; } /* ================================================================== */ /* ar[, aSyncOut] squinewave aFreq, aClip, aSkew [, aSyncIn, aMinSweep, iphase] */ static OENTRY squinewave_localops[] = { { "squinewave", sizeof(SQUINEWAVE), 0, 5, "am", "aaaxoj", (SUBR)squinewave_init, NULL, (SUBR)squinewave_gen }, }; LINKAGE_BUILTIN(squinewave_localops) csound-6.10.0/Opcodes/stackops.c000066400000000000000000000532241321653344700164760ustar00rootroot00000000000000/* stackops.c: Copyright (C) 2006 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csdl.h" #include "interlocks.h" #include "pstream.h" static int STR_ARG_P(CSOUND *csound, void* arg) { CS_TYPE *cs_type = csound->GetTypeForArg(arg); if (strcmp("S", cs_type->varTypeName) == 0) { return 1; } else { return 0; } } static int ASIG_ARG_P(CSOUND *csound, void* arg) { CS_TYPE *cs_type = csound->GetTypeForArg(arg); if (strcmp("a", cs_type->varTypeName) == 0) { return 1; } else { return 0; } } typedef struct CsoundArgStack_s CsoundArgStack_t; #define CS_STACK_ALIGN 8 #define CS_STACK_END 0 #define CS_STACK_I (1 << 24) #define CS_STACK_K (2 << 24) #define CS_STACK_A (3 << 24) #define CS_STACK_S (4 << 24) #define CS_STACK_F (5 << 24) struct CsoundArgStack_s { void *curBundle; void *dataSpace; int freeSpaceOffset; int freeSpaceEndOffset; }; typedef struct STACK_OPCODE_ { OPDS h; MYFLT *iStackSize; } STACK_OPCODE; typedef struct PUSH_OPCODE_ { OPDS h; MYFLT *args[32]; /* argMap[0]: bit mask of init (0) or perf (1) time arg type */ /* argMap[1]: number of stack bytes required at i-time */ /* argMap[2]: number of stack bytes required at performace time */ /* argMap[3] to argMap[35]: 0 terminated type/offset list */ int argMap[36]; CsoundArgStack_t *pp; int initDone; } PUSH_OPCODE; typedef struct POP_OPCODE_ { OPDS h; MYFLT *args[32]; /* argMap[0]: bit mask of init (0) or perf (1) time arg type */ /* argMap[1]: number of stack bytes required at i-time */ /* argMap[2]: number of stack bytes required at performace time */ /* argMap[3] to argMap[35]: 0 terminated type/offset list */ int argMap[36]; CsoundArgStack_t *pp; int initDone; } POP_OPCODE; /* fsg_assign() was taken from pstream.c, written by Richard Dobson */ static CS_NOINLINE void fsg_assign(CSOUND *csound, PVSDAT *fdst, const PVSDAT *fsrc) { if (UNLIKELY(fsrc->frame.auxp == NULL)) { csound->ErrorMsg(csound, Str("fsig = : source signal is not initialised")); return; } fdst->N = fsrc->N; fdst->overlap = fsrc->overlap; fdst->winsize = fsrc->winsize; fdst->wintype = fsrc->wintype; fdst->format = fsrc->format; if (fdst->frame.auxp == NULL || fdst->frame.size != (uint32_t)((fdst->N + 2L) * sizeof(float))) csound->AuxAlloc(csound, (fdst->N + 2L) * (long) sizeof(float), &(fdst->frame)); if (fdst->framecount != fsrc->framecount) { memcpy((float*) fdst->frame.auxp, (float*) fsrc->frame.auxp, ((size_t) fdst->N + (size_t) 2) * sizeof(float)); fdst->framecount = fsrc->framecount; } } static inline int csoundStack_Align(int n) { return ((n + (CS_STACK_ALIGN - 1)) & (~(CS_STACK_ALIGN - 1))); } static CS_NOINLINE int csoundStack_Error(void *p, const char *msg) { CSOUND *csound; csound = ((OPDS*) p)->insdshead->csound; csound->ErrorMsg(csound, "%s: %s", csound->GetOpcodeName(p), msg); return NOTOK; } static CS_NOINLINE int csoundStack_OverflowError(void *p) { /* CSOUND *csound= ((OPDS*) p)->insdshead->csound; */ return csoundStack_Error(p, Str("stack overflow")); } static CS_NOINLINE int csoundStack_EmptyError(void *p) { /* CSOUND *csound((OPDS*) p)->insdshead->csound; */ return csoundStack_Error(p, Str("cannot pop from empty stack")); } static CS_NOINLINE int csoundStack_TypeError(void *p) { /* CSOUND *csound = ((OPDS*) p)->insdshead->csound; */ return csoundStack_Error(p, Str("argument number or type mismatch")); } /* static CS_NOINLINE int csoundStack_LengthError(void *p) */ /* { */ /* /\* CSOUND *csound = ((OPDS*) p)->insdshead->csound; *\/ */ /* return csoundStack_Error(p, Str("string argument is too long")); */ /* } */ static CS_NOINLINE CsoundArgStack_t *csoundStack_AllocGlobals(CSOUND *csound, int stackSize) { CsoundArgStack_t *pp; int nBytes; if (UNLIKELY(stackSize < 1024)) stackSize = 1024; else if (UNLIKELY(stackSize > 16777200)) stackSize = 16777200; nBytes = csoundStack_Align((int) sizeof(CsoundArgStack_t)); nBytes += stackSize; if (UNLIKELY(csound->CreateGlobalVariable(csound, "csArgStack", (size_t) nBytes) != 0)) { csound->ErrorMsg(csound, Str("Error allocating argument stack")); return NULL; } pp = (CsoundArgStack_t*) csound->QueryGlobalVariable(csound, "csArgStack"); pp->curBundle = (CsoundArgStack_t*) NULL; pp->dataSpace = (void*) ((char*) pp + (int) csoundStack_Align((int) sizeof(CsoundArgStack_t))); pp->freeSpaceOffset = 0; pp->freeSpaceEndOffset = stackSize; return pp; } static CS_NOINLINE CsoundArgStack_t *csoundStack_GetGlobals(CSOUND *csound) { CsoundArgStack_t *pp; pp = (CsoundArgStack_t*) csound->QueryGlobalVariable(csound, "csArgStack"); if (pp == NULL) pp = csoundStack_AllocGlobals(csound, 32768); return pp; } static CS_NOINLINE int csoundStack_CreateArgMap(PUSH_OPCODE *p, int *argMap, int isOutput) { CSOUND *csound; int i, argCnt, argCnt_i, argCnt_p, curOffs_i, curOffs_p; MYFLT** args = p->args; csound = ((OPDS*) p)->insdshead->csound; if (!isOutput) { argCnt = csound->GetInputArgCnt(p); } else { argCnt = csound->GetOutputArgCnt(p); } if (UNLIKELY(argCnt > 31)) return csoundStack_Error(p, Str("too many arguments")); argMap[0] = 0; argCnt_i = 0; argCnt_p = 0; for (i = 0; i < argCnt; i++) { int maskVal = (1 << i); if (ASIG_ARG_P(csound, args[i])) { argMap[0] |= maskVal; argCnt_p++; } else if (STR_ARG_P(csound, args[i])) { argCnt_i++; } else { const char *argName; if (!isOutput) argName = csound->GetInputArgName(p, i); else argName = csound->GetOutputArgName(p, i); if (argName != (char*) 0 && (argName[0] == (char) 'k' || (argName[0] == (char) 'g' && argName[1] == (char) 'k') || (argName[0] == (char) '#' && argName[1] == (char) 'k'))) { argMap[0] |= maskVal; argCnt_p++; } else argCnt_i++; } } curOffs_i = (int) sizeof(void*); curOffs_i = csoundStack_Align(curOffs_i); curOffs_p = curOffs_i; curOffs_i += ((int) sizeof(int) * (argCnt_i + 1)); curOffs_i = csoundStack_Align(curOffs_i); curOffs_p += ((int) sizeof(int) * (argCnt_p + 1)); curOffs_p = csoundStack_Align(curOffs_p); for (i = 0; i < argCnt; i++) { int maskVal = (1 << i); if (argMap[0] & maskVal) { /* performance time types */ if (ASIG_ARG_P(csound, args[i])) { argMap[i + 3] = (curOffs_p | CS_STACK_A); curOffs_p += ((int) sizeof(MYFLT) * CS_KSMPS); } else { argMap[i + 3] = (curOffs_p | CS_STACK_K); curOffs_p += (int) sizeof(MYFLT); } } else { /* init time types */ if (STR_ARG_P(csound, args[i])) { argMap[i + 3] = (curOffs_i | CS_STACK_S); curOffs_i += (int) sizeof(STRINGDAT); /* curOffs_i = csoundStack_Align(curOffs_i);*/ } else { argMap[i + 3] = (curOffs_i | CS_STACK_I); curOffs_i += (int) sizeof(MYFLT); } } } argMap[i + 3] = CS_STACK_END; if (argCnt_i > 0) argMap[1] = csoundStack_Align(curOffs_i); else argMap[1] = 0; if (argCnt_p > 0) argMap[2] = csoundStack_Align(curOffs_p); else argMap[2] = 0; return OK; } static int stack_opcode_init(CSOUND *csound, STACK_OPCODE *p) { if (UNLIKELY(csound->QueryGlobalVariable(csound, "csArgStack") != NULL)) return csound->InitError(csound, Str("the stack is already allocated")); csoundStack_AllocGlobals(csound, (int) (*(p->iStackSize) + 0.5)); return OK; } static int notinit_opcode_stub_perf(CSOUND *csound, void *p) { return csound->PerfError(csound, ((OPDS*)p)->insdshead, Str("%s: not initialised"), csound->GetOpcodeName(p)); } static int push_opcode_perf(CSOUND *csound, PUSH_OPCODE *p) { if (p->argMap[2] != 0) { void *bp; int i, *ofsp; if (p->pp->freeSpaceOffset + p->argMap[2] > p->pp->freeSpaceEndOffset) return csoundStack_OverflowError(p); bp = (void*) ((char*) p->pp->dataSpace + (int) p->pp->freeSpaceOffset); p->pp->freeSpaceOffset += p->argMap[2]; *((void**) bp) = p->pp->curBundle; p->pp->curBundle = bp; ofsp = (int*) ((char*) bp + (int) csoundStack_Align((int) sizeof(void*))); for (i = 0; p->argMap[i + 3] != CS_STACK_END; i++) { if (p->argMap[0] & (1 << i)) { int curOffs = p->argMap[i + 3]; *(ofsp++) = curOffs; switch (curOffs & (int) 0x7F000000) { case CS_STACK_K: *((MYFLT*) ((char*) bp + (int) (curOffs & (int) 0x00FFFFFF))) = *(p->args[i]); break; case CS_STACK_A: { MYFLT *src, *dst; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nsmps = CS_KSMPS; src = p->args[i]; dst = (MYFLT*) ((char*) bp + (int) (curOffs & (int) 0x00FFFFFF)); if (UNLIKELY(offset)) memset(dst, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&dst[nsmps], '\0', early*sizeof(MYFLT)); } memcpy(&dst[offset], &src[offset], sizeof(MYFLT)*(nsmps-offset)); //for (j = 0; j < nsmps; j++) //dst[j] = src[j]; } } } } *ofsp = CS_STACK_END; } return OK; } static int push_opcode_init(CSOUND *csound, PUSH_OPCODE *p) { if (!p->initDone) { p->pp = csoundStack_GetGlobals(csound); if (UNLIKELY(csoundStack_CreateArgMap(p, (int*)&(p->argMap[0]), 0) != OK)) return NOTOK; p->h.opadr = (int (*)(CSOUND *, void *)) push_opcode_perf; p->initDone = 1; } if (p->argMap[1] != 0) { void *bp; int i, *ofsp; if (UNLIKELY(p->pp->freeSpaceOffset + p->argMap[1] > p->pp->freeSpaceEndOffset)) return csoundStack_OverflowError(p); bp = (void*) ((char*) p->pp->dataSpace + (int) p->pp->freeSpaceOffset); p->pp->freeSpaceOffset += p->argMap[1]; *((void**) bp) = p->pp->curBundle; p->pp->curBundle = bp; ofsp = (int*) ((char*) bp + (int) csoundStack_Align((int) sizeof(void*))); for (i = 0; p->argMap[i + 3] != CS_STACK_END; i++) { if (!(p->argMap[0] & (1 << i))) { int curOffs = p->argMap[i + 3]; *(ofsp++) = curOffs; switch (curOffs & (int) 0x7F000000) { case CS_STACK_I: *((MYFLT*) ((char*) bp + (int) (curOffs & (int) 0x00FFFFFF))) = *(p->args[i]); break; case CS_STACK_S: { char *src; STRINGDAT **ans, *dst; /* int j, maxLen; */ src = ((STRINGDAT*) p->args[i])->data; ans = ((STRINGDAT**)(char*) bp + (int) (curOffs & (int) 0x00FFFFFF)); dst = (STRINGDAT*) csound->Malloc(csound, sizeof(STRINGDAT)); dst->data = csound->Strdup(csound, src); dst->size = strlen(src) + 1; *ans = dst; /* printf("***dst = %p %p %d, \"%s\"\n", */ /* ans, dst, dst->size, dst->data); */ } } } } *ofsp = CS_STACK_END; } return OK; } static int pop_opcode_perf(CSOUND *csound, POP_OPCODE *p) { if (p->argMap[2] != 0) { void *bp; int i, *ofsp; if (UNLIKELY(p->pp->curBundle == NULL)) return csoundStack_EmptyError(p); bp = p->pp->curBundle; ofsp = (int*) ((char*) bp + (int) csoundStack_Align((int) sizeof(void*))); for (i = 0; *ofsp != CS_STACK_END; i++) { if (p->argMap[0] & (1 << i)) { int curOffs = p->argMap[i + 3]; if (curOffs != *ofsp) csoundStack_TypeError(p); ofsp++; switch (curOffs & (int) 0x7F000000) { case CS_STACK_K: *(p->args[i]) = *((MYFLT*) ((char*) bp + (int) (curOffs & (int) 0x00FFFFFF))); break; case CS_STACK_A: { MYFLT *src, *dst; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nsmps = CS_KSMPS; src = (MYFLT*) ((char*) bp + (int) (curOffs & (int) 0x00FFFFFF)); dst = p->args[i]; if (UNLIKELY(offset)) memset(dst, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&dst[nsmps], '\0', early*sizeof(MYFLT)); } memcpy(&dst[offset], &src[offset], (nsmps-offset)*sizeof(MYFLT)); //for (j = 0; j < CS_KSMPS; j++) // dst[j] = src[j]; } break; } } } p->pp->curBundle = *((void**) bp); p->pp->freeSpaceOffset = (int) ((char*) bp - (char*) p->pp->dataSpace); } return OK; } static int pop_opcode_init(CSOUND *csound, POP_OPCODE *p) { if (!p->initDone) { p->pp = csoundStack_GetGlobals(csound); if (UNLIKELY(csoundStack_CreateArgMap((PUSH_OPCODE*)p, &(p->argMap[0]), 1) != OK)) return NOTOK; p->h.opadr = (int (*)(CSOUND *, void *)) pop_opcode_perf; p->initDone = 1; } if (p->argMap[1] != 0) { void *bp; int i, *ofsp; if (p->pp->curBundle == NULL) return csoundStack_EmptyError(p); bp = p->pp->curBundle; ofsp = (int*) ((char*) bp + (int) csoundStack_Align((int) sizeof(void*))); for (i = 0; *ofsp != CS_STACK_END; i++) { if (!(p->argMap[0] & (1 << i))) { int curOffs = p->argMap[i + 3]; if (curOffs != *ofsp) csoundStack_TypeError(p); ofsp++; switch (curOffs & (int) 0x7F000000) { case CS_STACK_I: *(p->args[i]) = *((MYFLT*) ((char*) bp + (int) (curOffs & (int) 0x00FFFFFF))); break; case CS_STACK_S: { STRINGDAT **ans = ((STRINGDAT**)(char*) bp + (int) (curOffs & (int) 0x00FFFFFF)); STRINGDAT *str = *ans; STRINGDAT *dst = (STRINGDAT*)p->args[i]; /* printf("***string: %p\nbp=%p Off = %x\n", ans, bp, curOffs); */ /* printf("***string: %p->%s\n", str, dst->data); */ if (str==NULL) return csound->InitError(csound, "pop of strings broken"); if (str->size>dst->size) { csound->Free(csound,dst->data); dst->data = csound->Strdup(csound, str->data); dst->size = strlen(dst->data)+1; } else { strcpy((char*) dst->data, str->data); } csound->Free(csound,str->data); csound->Free(csound,str); *ans = NULL; } break; } } } p->pp->curBundle = *((void**) bp); p->pp->freeSpaceOffset = (int) ((char*) bp - (char*) p->pp->dataSpace); } return OK; } static int push_f_opcode_perf(CSOUND *csound, PUSH_OPCODE *p) { void *bp; int *ofsp; int offs; if (UNLIKELY(p->pp->freeSpaceOffset + p->argMap[2] > p->pp->freeSpaceEndOffset)) return csoundStack_OverflowError(p); bp = (void*) ((char*) p->pp->dataSpace + (int) p->pp->freeSpaceOffset); p->pp->freeSpaceOffset += p->argMap[2]; *((void**) bp) = p->pp->curBundle; p->pp->curBundle = bp; ofsp = (int*) ((char*) bp + (int) csoundStack_Align((int) sizeof(void*))); offs = p->argMap[3]; *(ofsp++) = offs; *((PVSDAT**) ((char*) bp + (int) (offs & (int) 0x00FFFFFF))) = (PVSDAT*) ((char*) p->args[0]); *ofsp = CS_STACK_END; return OK; } static int push_f_opcode_init(CSOUND *csound, PUSH_OPCODE *p) { void *bp; int *ofsp; int offs; if (!p->initDone) { p->pp = csoundStack_GetGlobals(csound); offs = (int) sizeof(void*); offs = csoundStack_Align(offs); offs += ((int) sizeof(int) * 2); offs = csoundStack_Align(offs); /* the 'f' type is special: */ /* it is copied at both init and performance time */ p->argMap[0] = 1; p->argMap[3] = (CS_STACK_F | offs); p->argMap[4] = CS_STACK_END; /* FIXME: store only the address of the f-signal on the stack */ /* this may be dangerous... */ offs += (int) sizeof(PVSDAT*); offs = csoundStack_Align(offs); p->argMap[1] = offs; p->argMap[2] = offs; p->h.opadr = (int (*)(CSOUND *, void *)) push_f_opcode_perf; p->initDone = 1; } if (UNLIKELY(p->pp->freeSpaceOffset + p->argMap[1] > p->pp->freeSpaceEndOffset)) return csoundStack_OverflowError(p); bp = (void*) ((char*) p->pp->dataSpace + (int) p->pp->freeSpaceOffset); p->pp->freeSpaceOffset += p->argMap[1]; *((void**) bp) = p->pp->curBundle; p->pp->curBundle = bp; ofsp = (int*) ((char*) bp + (int) csoundStack_Align((int) sizeof(void*))); offs = p->argMap[3]; *(ofsp++) = offs; *((PVSDAT**) ((char*) bp + (int) (offs & (int) 0x00FFFFFF))) = (PVSDAT*) ((char*) p->args[0]); *ofsp = CS_STACK_END; return OK; } static int pop_f_opcode_perf(CSOUND *csound, POP_OPCODE *p) { void *bp; int *ofsp; int offs; if (UNLIKELY(p->pp->curBundle == NULL)) return csoundStack_EmptyError(p); bp = p->pp->curBundle; ofsp = (int*) ((char*) bp + (int) csoundStack_Align((int) sizeof(void*))); offs = p->argMap[3]; if (UNLIKELY(offs != *ofsp)) csoundStack_TypeError(p); ofsp++; if (UNLIKELY(*ofsp != CS_STACK_END)) csoundStack_TypeError(p); fsg_assign(csound, (PVSDAT*) p->args[0], *((PVSDAT**) ((char*) bp + (int) (offs & (int) 0x00FFFFFF)))); p->pp->curBundle = *((void**) bp); p->pp->freeSpaceOffset = (int) ((char*) bp - (char*) p->pp->dataSpace); return OK; } static int pop_f_opcode_init(CSOUND *csound, POP_OPCODE *p) { void *bp; int *ofsp; int offs; if (!p->initDone) { p->pp = csoundStack_GetGlobals(csound); offs = (int) sizeof(void*); offs = csoundStack_Align(offs); offs += ((int) sizeof(int) * 2); offs = csoundStack_Align(offs); /* the 'f' type is special: */ /* it is copied at both init and performance time */ p->argMap[0] = 1; p->argMap[3] = (CS_STACK_F | offs); p->argMap[4] = CS_STACK_END; /* FIXME: only the address of the f-signal is stored on the stack */ /* this may be dangerous... */ offs += (int) sizeof(PVSDAT*); offs = csoundStack_Align(offs); p->argMap[1] = offs; p->argMap[2] = offs; p->h.opadr = (int (*)(CSOUND *, void *)) pop_f_opcode_perf; p->initDone = 1; } if (UNLIKELY(p->pp->curBundle == NULL)) return csoundStack_EmptyError(p); bp = p->pp->curBundle; ofsp = (int*) ((char*) bp + (int) csoundStack_Align((int) sizeof(void*))); offs = p->argMap[3]; if (UNLIKELY(offs != *ofsp)) csoundStack_TypeError(p); ofsp++; if (UNLIKELY(*ofsp != CS_STACK_END)) csoundStack_TypeError(p); fsg_assign(csound, (PVSDAT*) p->args[0], *((PVSDAT**) ((char*) bp + (int) (offs & (int) 0x00FFFFFF)))); p->pp->curBundle = *((void**) bp); p->pp->freeSpaceOffset = (int) ((char*) bp - (char*) p->pp->dataSpace); return OK; } /* ------------------------------------------------------------------------ */ static OENTRY localops[] = { { "stack", sizeof(STACK_OPCODE), SK|_QQ, 1, "", "i", (SUBR) stack_opcode_init, (SUBR) NULL, (SUBR) NULL }, { "push", sizeof(PUSH_OPCODE), SK|_QQ, 3, "", "N", (SUBR) push_opcode_init, (SUBR) notinit_opcode_stub_perf, (SUBR) NULL }, { "pop", sizeof(POP_OPCODE), SK|_QQ, 3, "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN", "", (SUBR) pop_opcode_init, (SUBR) notinit_opcode_stub_perf, (SUBR) NULL }, { "push_f", sizeof(PUSH_OPCODE), SK|_QQ, 3, "", "f", (SUBR) push_f_opcode_init, (SUBR) notinit_opcode_stub_perf, (SUBR) NULL }, { "pop_f", sizeof(POP_OPCODE), SK|_QQ, 3, "f", "", (SUBR) pop_f_opcode_init, (SUBR) notinit_opcode_stub_perf, (SUBR) NULL } }; LINKAGE csound-6.10.0/Opcodes/stdopcod.c000066400000000000000000000060471321653344700164670ustar00rootroot00000000000000/* stdopcod.c: This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "stdopcod.h" /* PUBLIC int csoundModuleCreate(CSOUND *csound) { (void) csound; return 0; } */ int stdopc_ModuleInit(CSOUND *csound) { STDOPCOD_GLOBALS *p; int err = 0; if (UNLIKELY(csound->stdOp_Env != NULL)) { csound->ErrorMsg(csound, Str("stdopcod.c: error: globals already allocated")); return CSOUND_ERROR; } csound->stdOp_Env = csound->Calloc(csound, sizeof(STDOPCOD_GLOBALS)); p = (STDOPCOD_GLOBALS*) csound->stdOp_Env; p->csound = csound; /* fout.c */ p->file_opened = (struct fileinTag*) NULL; p->file_num = -1; /*p->buf = (MYFLT*) NULL;*/ /* ugnorman.c */ p->atsbufreadaddr = NULL; err |= ambicode_init_(csound); err |= bbcut_init_(csound); err |= biquad_init_(csound); err |= butter_init_(csound); err |= clfilt_init_(csound); err |= cross2_init_(csound); err |= dam_init_(csound); err |= dcblockr_init_(csound); err |= filter_init_(csound); err |= flanger_init_(csound); err |= follow_init_(csound); err |= fout_init_(csound); err |= freeverb_init_(csound); err |= ftconv_init_(csound); err |= ftgen_init_(csound); err |= gab_gab_init_(csound); err |= gab_vectorial_init_(csound); err |= grain_init_(csound); err |= locsig_init_(csound); err |= lowpassr_init_(csound); err |= metro_init_(csound); err |= midiops2_init_(csound); err |= midiops3_init_(csound); err |= newfils_init_(csound); err |= nlfilt_init_(csound); err |= oscbnk_init_(csound); err |= pluck_init_(csound); err |= repluck_init_(csound); err |= reverbsc_init_(csound); err |= seqtime_init_(csound); err |= sndloop_init_(csound); err |= sndwarp_init_(csound); err |= space_init_(csound); err |= spat3d_init_(csound); err |= syncgrain_init_(csound); err |= ugens7_init_(csound); err |= ugens9_init_(csound); err |= ugensa_init_(csound); err |= uggab_init_(csound); err |= ugmoss_init_(csound); err |= ugnorman_init_(csound); err |= ugsc_init_(csound); err |= wave_terrain_init_(csound); return (err ? CSOUND_ERROR : CSOUND_SUCCESS); } /* PUBLIC int csoundModuleInfo(void) { return ((CS_APIVERSION << 16) + (CS_APISUBVER << 8) + (int) sizeof(MYFLT)); } */ csound-6.10.0/Opcodes/stdopcod.h000066400000000000000000000076221321653344700164740ustar00rootroot00000000000000/* stdopcod.h: This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef CSOUND_STDOPCOD_H #define CSOUND_STDOPCOD_H //#include "csdl.h" #include "csoundCore.h" #include #include "interlocks.h" /* file structure for fout opcodes */ struct fileinTag { SNDFILE *file; /* Used in audio cases */ FILE *raw; /* Only used if text file */ void *fd; /* file handle returned by CSOUND::FileOpen */ char *name; /* short name */ int do_scale; /* non-zero if 0dBFS scaling should be applied */ uint32 refCount; /* reference count, | 0x80000000 if close reqd */ }; typedef struct VCO2_TABLE_ARRAY_ VCO2_TABLE_ARRAY; typedef struct _atsbufread ATSBUFREAD; typedef struct STDOPCOD_GLOBALS_ { CSOUND *csound; /* fout.c */ struct fileinTag *file_opened; int file_max; int file_num; int32 fout_kreset; /* MYFLT *buf; int buf_size; */ /* VL - now using per instance buffer */ /* oscbnk.c */ uint32 oscbnk_seed; int32 rnd31i_seed; int denorm_seed; int vco2_nr_table_arrays; VCO2_TABLE_ARRAY **vco2_tables; /* ugnorman.c */ ATSBUFREAD *atsbufreadaddr; int swapped_warning; /* locsig.c */ void *locsigaddr; /* space.c */ void *spaceaddr; /* gab/gab.c */ MYFLT *tb_ptrs[16]; /* Left here while the rest is implemented */ MYFLT *tb[16]; /* gab: updated */ int tb_ixmode[16]; /* gab: added */ int32 tb_size[16]; /* gab: added */ } STDOPCOD_GLOBALS; extern int ambicode_init_(CSOUND *); extern int bbcut_init_(CSOUND *); extern int biquad_init_(CSOUND *); extern int butter_init_(CSOUND *); extern int clfilt_init_(CSOUND *); extern int cross2_init_(CSOUND *); extern int dam_init_(CSOUND *); extern int dcblockr_init_(CSOUND *); extern int filter_init_(CSOUND *); extern int flanger_init_(CSOUND *); extern int follow_init_(CSOUND *); extern int fout_init_(CSOUND *); extern int freeverb_init_(CSOUND *); extern int ftconv_init_(CSOUND *); extern int ftgen_init_(CSOUND *); extern int gab_gab_init_(CSOUND *); extern int gab_vectorial_init_(CSOUND *); extern int grain_init_(CSOUND *); extern int locsig_init_(CSOUND *); extern int lowpassr_init_(CSOUND *); extern int metro_init_(CSOUND *); extern int midiops2_init_(CSOUND *); extern int midiops3_init_(CSOUND *); extern int newfils_init_(CSOUND *); extern int nlfilt_init_(CSOUND *); extern int oscbnk_init_(CSOUND *); extern int pluck_init_(CSOUND *); extern int repluck_init_(CSOUND *); extern int reverbsc_init_(CSOUND *); extern int seqtime_init_(CSOUND *); extern int sndloop_init_(CSOUND *); extern int sndwarp_init_(CSOUND *); extern int space_init_(CSOUND *); extern int spat3d_init_(CSOUND *); extern int syncgrain_init_(CSOUND *); extern int ugens7_init_(CSOUND *); extern int ugens9_init_(CSOUND *); extern int ugensa_init_(CSOUND *); extern int uggab_init_(CSOUND *); extern int ugmoss_init_(CSOUND *); extern int ugnorman_init_(CSOUND *); extern int ugsc_init_(CSOUND *); extern int wave_terrain_init_(CSOUND *); #endif /* CSOUND_STDOPCOD_H */ csound-6.10.0/Opcodes/stk/000077500000000000000000000000001321653344700152765ustar00rootroot00000000000000csound-6.10.0/Opcodes/stk/CMakeLists.txt000066400000000000000000000063451321653344700200460ustar00rootroot00000000000000option(BUILD_STK_OPCODES "Build the stk opcodes" ON) if(WIN32) cmake_policy(SET CMP0060 NEW) endif() if(NOT STK_LOCAL) find_package(STK) endif() if(BUILD_STK_OPCODES) if(DEFAULT_STK_RAWWAVE_PATH) set(rawwave_path "-DDEFAULT_RAWWAVE_PATH=\\\"${DEFAULT_STK_RAWWAVE_PATH}\\\"") endif() #find_library(STK_LIBRARY stk) if(STK_LIBRARY) find_path(STK_INCLUDE_DIR Stk.h /usr/include/stk /usr/local/include/stk) check_deps(BUILD_STK_OPCODES STK_INCLUDE_DIR) if(STK_INCLUDE_DIR) make_plugin(stkops stkOpcodes.cpp) target_include_directories(stkops PRIVATE ${STK_INCLUDE_DIR}) message(STATUS "Building STK opcodes.") if(BUILD_STATIC_LIBRARY) if(WIN32) add_library(stk STATIC IMPORTED) set_target_properties(stk PROPERTIES IMPORTED_LOCATION ${STK_LIBRARY}) target_link_libraries(stkops stk) else() target_link_libraries(stkops ${STK_LIBRARY}) endif() else() target_link_libraries(stkops ${STK_LIBRARIES}) target_link_libraries(stkops ${PTHREAD_LIBRARY}) endif() target_compile_definitions(stkops PRIVATE ${rawwave_path}) endif() else() set(stk_remove_srcs src/InetWvIn.cpp src/InetWvOut.cpp src/Mutex.cpp src/RtAudio.cpp src/RtMidi.cpp src/Messager.cpp src/RtWvIn.cpp src/RtWvOut.cpp src/Socket.cpp src/TcpClient.cpp src/TcpServer.cpp src/Thread.cpp src/UdpSocket.cpp) file(GLOB stk_srcs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} src/*) list(REMOVE_ITEM stk_srcs ${stk_remove_srcs}) list(APPEND stk_srcs stkOpcodes.cpp) # Assume that if this file exists, then we have the sources find_file(STK_FOUND NAMES src/InetWvIn.cpp HINTS ${CMAKE_CURRENT_SOURCE_DIR}) find_path(STK_INCLUDE_DIR Stk.h ./include) check_deps(BUILD_STK_OPCODES STK_FOUND STK_INCLUDE_DIR) if(BUILD_STK_OPCODES) make_plugin(stkops "${stk_srcs}") target_include_directories(stkops PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) target_include_directories(stkops PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include/stk) target_include_directories(stkops PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) set(stkdefs "-D__STK_REALTIME__") if(APPLE) list(APPEND stkdefs "-D__OS_MACOSX__") list(REMOVE_ITEM stkdefs "-D__STK_REALTIME__") elseif(LINUX) list(APPEND stkdefs "-D__OS_LINUX__") list(APPEND stkdefs "-D__LINUX_ALSA__") elseif(WIN32) list(APPEND stkdefs "-D__OS_WINDOWS__") endif() if(BIG_ENDIAN) list(APPEND stkdefs "-D__BIG_ENDIAN__") else() list(APPEND stkdefs "-D__LITTLE_ENDIAN__") endif() target_compile_definitions(stkops PRIVATE ${stkdefs}) target_compile_definitions(stkops PRIVATE ${rawwave_path}) endif() endif() endif() csound-6.10.0/Opcodes/stk/stkOpcodes.cpp000066400000000000000000000536021321653344700201260ustar00rootroot00000000000000/* This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * CSOUND 5/6 OPCODES FOR PERRY COOK'S SYNTHESIS TOOLKIT IN C++ (STK) INSTRUMENT * * This code is copyright (C) 2005 by Michael Gogins. It is licensed under the * same terms as the Synthesis Tookit in C++ by Perry R. Cook and Gary P. Scavone. * * To compile these opcodes, copy the STK include, src, and rawwaves directories * to the csound6/Opcodes/stk directory as follows: * * csound6/Opcodes/stk/include * csound6/Opcodes/stk/src * csound6/Opcodes/stk/rawwaves * * To use these opcodes, define a RAWWAVE_PATH environment variable that points * to your rawwaves directory, which contains raw soundfiles with function table * data. * * All these opcodes are named "STK" + the STK classname, * e.g. "STKBowed" for the Bowed instrument. * * All the STK opcodes have the same signature: * * aout STKName ifrequency igain {kcontroller0, kvalue1,...,kcontroller3, kvalue3} * * They take a frequency in Hertz and a gain parameter in the range [0, 1], * plus up to four optional krate controller-value pairs, and return an arate * signal that should be more or less in the range [-1, +1]. * See the STK class documentation to determine the controller numbers * used by each instrument. */ #ifndef JPFF #include #include #include #include #include #include #include #include #include #include #include #include #include //#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #else #include "include/Stk.h" #include "include/BandedWG.h" #include "include/BeeThree.h" #include "include/BlowBotl.h" #include "include/BlowHole.h" #include "include/Bowed.h" #include "include/Brass.h" #include "include/Clarinet.h" #include "include/Drummer.h" #include "include/Flute.h" #include "include/FMVoices.h" #include "include/HevyMetl.h" #include "include/Mandolin.h" //#include "include/Mesh2D.h" #include "include/ModalBar.h" #include "include/Moog.h" #include "include/PercFlut.h" #include "include/Plucked.h" #include "include/Resonate.h" #include "include/Rhodey.h" #include "include/Saxofony.h" #include "include/Shakers.h" #include "include/Simple.h" #include "include/Sitar.h" #include "include/StifKarp.h" #include "include/TubeBell.h" #include "include/VoicForm.h" #include "include/Whistle.h" #include "include/Wurley.h" #endif using namespace stk; #define __BUILDING_LIBCSOUND #include #include using namespace csound; #include #include #include #include #include #include using namespace std; using namespace csound; template class STKInstrumentAdapter : public OpcodeBase< STKInstrumentAdapter > { public: // Outputs. MYFLT *aoutput; // Inputs. MYFLT *ifrequency; MYFLT *igain; MYFLT *kcontroller0; MYFLT *kvalue0; MYFLT *kcontroller1; MYFLT *kvalue1; MYFLT *kcontroller2; MYFLT *kvalue2; MYFLT *kcontroller3; MYFLT *kvalue3; MYFLT *kcontroller4; MYFLT *kvalue4; MYFLT *kcontroller5; MYFLT *kvalue5; MYFLT *kcontroller6; MYFLT *kvalue6; MYFLT *kcontroller7; MYFLT *kvalue7; // State. T *instrument; size_t ksmps; bool released; MYFLT oldkcontroller0; MYFLT oldkvalue0; MYFLT oldkcontroller1; MYFLT oldkvalue1; MYFLT oldkcontroller2; MYFLT oldkvalue2; MYFLT oldkcontroller3; MYFLT oldkvalue3; MYFLT oldkcontroller4; MYFLT oldkvalue4; MYFLT oldkcontroller5; MYFLT oldkvalue5; MYFLT oldkcontroller6; MYFLT oldkvalue6; MYFLT oldkcontroller7; MYFLT oldkvalue7; STKInstrumentAdapter() : instrument(0) {} int init(CSOUND *csound) { if(!instrument) { Stk::setSampleRate(csound->GetSr(csound)); instrument = new T(); } ksmps = OpcodeBase< STKInstrumentAdapter >::opds.insdshead->ksmps; instrument->noteOn(*ifrequency, *igain); released = false; oldkcontroller0 = -1.0; oldkvalue0 = -1.0; oldkcontroller1 = -1.0; oldkvalue1 = -1.0; oldkcontroller2 = -1.0; oldkvalue2 = -1.0; oldkcontroller3 = -1.0; oldkvalue3 = -1.0; oldkcontroller4 = -1.0; oldkvalue4 = -1.0; oldkcontroller5 = -1.0; oldkvalue5 = -1.0; oldkcontroller6 = -1.0; oldkvalue6 = -1.0; oldkcontroller7 = -1.0; oldkvalue7 = -1.0; return OK; } int kontrol(CSOUND *csound) { uint32_t offset = OpcodeBase< STKInstrumentAdapter >::opds.insdshead->ksmps_offset; if(!released) { if(*kcontroller0 != oldkcontroller0 || *kvalue0 != oldkvalue0) { instrument->controlChange(static_cast(*kcontroller0), *kvalue0); oldkcontroller0 = *kcontroller0; oldkvalue0 = *kvalue0; } if(*kcontroller1 != oldkcontroller1 || *kvalue1 != oldkvalue1) { instrument->controlChange(static_cast(*kcontroller1), *kvalue1); oldkcontroller1 = *kcontroller1; oldkvalue1 = *kvalue1; } if(*kcontroller2 != oldkcontroller2 || *kvalue2 != oldkvalue2) { instrument->controlChange(static_cast(*kcontroller2), *kvalue2); oldkcontroller2 = *kcontroller2; oldkvalue2 = *kvalue2; } if(*kcontroller3 != oldkcontroller3 || *kvalue3 != oldkvalue3) { instrument->controlChange(static_cast(*kcontroller3), *kvalue3); oldkcontroller3 = *kcontroller3; oldkvalue3 = *kvalue3; } if(*kcontroller4 != oldkcontroller4 || *kvalue4 != oldkvalue4) { instrument->controlChange(static_cast(*kcontroller4), *kvalue4); oldkcontroller4 = *kcontroller4; oldkvalue4 = *kvalue4; } if(*kcontroller5 != oldkcontroller5 || *kvalue5 != oldkvalue5) { instrument->controlChange(static_cast(*kcontroller5), *kvalue5); oldkcontroller5 = *kcontroller5; oldkvalue5 = *kvalue5; } if(*kcontroller6 != oldkcontroller6 || *kvalue6 != oldkvalue6) { instrument->controlChange(static_cast(*kcontroller6), *kvalue6); oldkcontroller6 = *kcontroller6; oldkvalue6 = *kvalue6; } if(*kcontroller7 != oldkcontroller7 || *kvalue7 != oldkvalue7) { instrument->controlChange(static_cast(*kcontroller7), *kvalue7); oldkcontroller7 = *kcontroller7; oldkvalue7 = *kvalue7; } memset(aoutput, '\0', offset*sizeof(MYFLT)); for(size_t i = offset; i < ksmps; i++) { aoutput[i] = instrument->tick(); } } else { //memset(aoutput, 0, ksmps*sizeof(MYFLT)); for(size_t i = 0; i < ksmps; i++) { aoutput[i] = 0; } } return OK; } }; template class STKInstrumentAdapter1 : public OpcodeBase< STKInstrumentAdapter1 > { public: // Outputs. MYFLT *aoutput; // Inputs. MYFLT *ifrequency; MYFLT *igain; MYFLT *kcontroller0; MYFLT *kvalue0; MYFLT *kcontroller1; MYFLT *kvalue1; MYFLT *kcontroller2; MYFLT *kvalue2; MYFLT *kcontroller3; MYFLT *kvalue3; MYFLT *kcontroller4; MYFLT *kvalue4; MYFLT *kcontroller5; MYFLT *kvalue5; MYFLT *kcontroller6; MYFLT *kvalue6; MYFLT *kcontroller7; MYFLT *kvalue7; // State. T *instrument; size_t ksmps; bool released; MYFLT oldkcontroller0; MYFLT oldkvalue0; MYFLT oldkcontroller1; MYFLT oldkvalue1; MYFLT oldkcontroller2; MYFLT oldkvalue2; MYFLT oldkcontroller3; MYFLT oldkvalue3; MYFLT oldkcontroller4; MYFLT oldkvalue4; MYFLT oldkcontroller5; MYFLT oldkvalue5; MYFLT oldkcontroller6; MYFLT oldkvalue6; MYFLT oldkcontroller7; MYFLT oldkvalue7; STKInstrumentAdapter1() : instrument(0) {} int init(CSOUND *csound) { if(!instrument) { Stk::setSampleRate(csound->GetSr(csound)); instrument = new T((StkFloat) 10.0); } ksmps = OpcodeBase< STKInstrumentAdapter1 >::opds.insdshead->ksmps; instrument->noteOn(*ifrequency, *igain); released = false; oldkcontroller0 = -1.0; oldkvalue0 = -1.0; oldkcontroller1 = -1.0; oldkvalue1 = -1.0; oldkcontroller2 = -1.0; oldkvalue2 = -1.0; oldkcontroller3 = -1.0; oldkvalue3 = -1.0; oldkcontroller4 = -1.0; oldkvalue4 = -1.0; oldkcontroller5 = -1.0; oldkvalue5 = -1.0; oldkcontroller6 = -1.0; oldkvalue6 = -1.0; oldkcontroller7 = -1.0; oldkvalue7 = -1.0; return OK; } int kontrol(CSOUND *csound) { uint32_t offset = OpcodeBase< STKInstrumentAdapter1 >::opds.insdshead->ksmps_offset; if(!released) { if(*kcontroller0 != oldkcontroller0 || *kvalue0 != oldkvalue0) { instrument->controlChange(static_cast(*kcontroller0), *kvalue0); oldkcontroller0 = *kcontroller0; oldkvalue0 = *kvalue0; } if(*kcontroller1 != oldkcontroller1 || *kvalue1 != oldkvalue1) { instrument->controlChange(static_cast(*kcontroller1), *kvalue1); oldkcontroller1 = *kcontroller1; oldkvalue1 = *kvalue1; } if(*kcontroller2 != oldkcontroller2 || *kvalue2 != oldkvalue2) { instrument->controlChange(static_cast(*kcontroller2), *kvalue2); oldkcontroller2 = *kcontroller2; oldkvalue2 = *kvalue2; } if(*kcontroller3 != oldkcontroller3 || *kvalue3 != oldkvalue3) { instrument->controlChange(static_cast(*kcontroller3), *kvalue3); oldkcontroller3 = *kcontroller3; oldkvalue3 = *kvalue3; } if(*kcontroller4 != oldkcontroller4 || *kvalue4 != oldkvalue4) { instrument->controlChange(static_cast(*kcontroller4), *kvalue4); oldkcontroller4 = *kcontroller4; oldkvalue4 = *kvalue4; } if(*kcontroller5 != oldkcontroller5 || *kvalue5 != oldkvalue5) { instrument->controlChange(static_cast(*kcontroller5), *kvalue5); oldkcontroller5 = *kcontroller5; oldkvalue5 = *kvalue5; } if(*kcontroller6 != oldkcontroller6 || *kvalue6 != oldkvalue6) { instrument->controlChange(static_cast(*kcontroller6), *kvalue6); oldkcontroller6 = *kcontroller6; oldkvalue6 = *kvalue6; } if(*kcontroller7 != oldkcontroller7 || *kvalue7 != oldkvalue7) { instrument->controlChange(static_cast(*kcontroller7), *kvalue7); oldkcontroller7 = *kcontroller7; oldkvalue7 = *kvalue7; } memset(aoutput, '\0', offset*sizeof(MYFLT)); for(size_t i = offset; i < ksmps; i++) { aoutput[i] = instrument->tick(); } } else { // memset(aoutput, 0, ksmps*sizef(MYFLT)); for(size_t i = 0; i < ksmps; i++) { aoutput[i] = 0; } } return OK; } }; extern "C" { OENTRY oentries[] = { { (char*)"STKBandedWG", sizeof(STKInstrumentAdapter), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter::init_, (SUBR) STKInstrumentAdapter::kontrol_, 0, }, { (char*)"STKBeeThree", sizeof(STKInstrumentAdapter), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter::init_, (SUBR) STKInstrumentAdapter::kontrol_, 0, }, { (char*)"STKBlowBotl", sizeof(STKInstrumentAdapter), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter::init_, (SUBR) STKInstrumentAdapter::kontrol_, 0, }, { (char*)"STKBlowHole", sizeof(STKInstrumentAdapter1), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter1::init_, (SUBR) STKInstrumentAdapter1::kontrol_, 0, }, { (char*)"STKBowed", sizeof(STKInstrumentAdapter1), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter1::init_, (SUBR) STKInstrumentAdapter1::kontrol_, 0, }, { (char*)"STKBrass", sizeof(STKInstrumentAdapter1), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter1::init_, (SUBR) STKInstrumentAdapter1::kontrol_, 0, }, { (char*)"STKClarinet", sizeof(STKInstrumentAdapter1), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter1::init_, (SUBR) STKInstrumentAdapter1::kontrol_, 0, }, { (char*)"STKDrummer", sizeof(STKInstrumentAdapter), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter::init_, (SUBR) STKInstrumentAdapter::kontrol_, 0, }, { (char*)"STKFlute", sizeof(STKInstrumentAdapter1), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter1::init_, (SUBR) STKInstrumentAdapter1::kontrol_, 0, }, { (char*)"STKFMVoices", sizeof(STKInstrumentAdapter), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter::init_, (SUBR) STKInstrumentAdapter::kontrol_, 0, }, { (char*)"STKHevyMetl", sizeof(STKInstrumentAdapter), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter::init_, (SUBR) STKInstrumentAdapter::kontrol_, 0, }, { (char*)"STKMandolin", sizeof(STKInstrumentAdapter1), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter1::init_, (SUBR) STKInstrumentAdapter1::kontrol_, 0, }, { (char*)"STKModalBar", sizeof(STKInstrumentAdapter), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter::init_, (SUBR) STKInstrumentAdapter::kontrol_, 0, }, { (char*)"STKMoog", sizeof(STKInstrumentAdapter), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter::init_, (SUBR) STKInstrumentAdapter::kontrol_, 0, }, { (char*)"STKPercFlut", sizeof(STKInstrumentAdapter), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter::init_, (SUBR) STKInstrumentAdapter::kontrol_, 0, }, { (char*)"STKPlucked", sizeof(STKInstrumentAdapter1), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter1::init_, (SUBR) STKInstrumentAdapter1::kontrol_, 0, }, { (char*)"STKResonate", sizeof(STKInstrumentAdapter), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter::init_, (SUBR) STKInstrumentAdapter::kontrol_, 0, }, { (char*)"STKRhodey", sizeof(STKInstrumentAdapter), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter::init_, (SUBR) STKInstrumentAdapter::kontrol_, 0, }, { (char*)"STKSaxofony", sizeof(STKInstrumentAdapter1), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter1::init_, (SUBR) STKInstrumentAdapter1::kontrol_, 0, }, { (char*)"STKShakers", sizeof(STKInstrumentAdapter), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter::init_, (SUBR) STKInstrumentAdapter::kontrol_, 0, }, { (char*)"STKSimple", sizeof(STKInstrumentAdapter), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter::init_, (SUBR) STKInstrumentAdapter::kontrol_, 0, }, { (char*)"STKSitar", sizeof(STKInstrumentAdapter), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter::init_, (SUBR) STKInstrumentAdapter::kontrol_, 0, }, { (char*)"STKStifKarp", sizeof(STKInstrumentAdapter1), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter1::init_, (SUBR) STKInstrumentAdapter1::kontrol_, 0, }, { (char*)"STKTubeBell", sizeof(STKInstrumentAdapter), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter::init_, (SUBR) STKInstrumentAdapter::kontrol_, 0, }, { (char*)"STKVoicForm", sizeof(STKInstrumentAdapter), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter::init_, (SUBR) STKInstrumentAdapter::kontrol_, 0, }, { (char*)"STKWhistle", sizeof(STKInstrumentAdapter), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter::init_, (SUBR) STKInstrumentAdapter::kontrol_, 0, }, { (char*)"STKWurley", sizeof(STKInstrumentAdapter), 0, 3, (char*)"a", (char*)"iiJJJJJJJJJJJJJJJJ", (SUBR) STKInstrumentAdapter::init_, (SUBR) STKInstrumentAdapter::kontrol_, 0, }, { 0, 0, 0, 0, 0, 0, 0, 0, } }; PUBLIC int csoundModuleCreate(CSOUND *csound) { return 0; } PUBLIC int csoundModuleInit(CSOUND *csound) { const char* path = csound->GetEnv(csound, "RAWWAVE_PATH"); #ifdef DEFAULT_RAWWAVE_PATH if (!path) path = DEFAULT_RAWWAVE_PATH; #endif if (path == NULL) { if (UNLIKELY(csound->GetDebug(csound))) csound->Warning(csound, Str("STK opcodes not available: define environment " "variable RAWWAVE_PATH\n(points " "to rawwaves directory) to use STK opcodes.")); return 0; } else { #if !defined(MACOSX) if (path) { path = std::getenv("RAWWAVE_PATH"); } #endif if (path != NULL && strlen(path) != 0) { Stk::setRawwavePath(path); } //csound->DebugMsg(csound, // Str("RAWWAVE_PATH: %s\n"), Stk::rawwavePath().c_str()); } int status = 0; for(OENTRY *oentry = &oentries[0]; oentry->opname; oentry++) { status |= csound->AppendOpcode(csound, oentry->opname, oentry->dsblksiz, oentry->flags, oentry->thread, oentry->outypes, oentry->intypes, (int (*)(CSOUND*,void*)) oentry->iopadr, (int (*)(CSOUND*,void*)) oentry->kopadr, (int (*)(CSOUND*,void*)) oentry->aopadr); } return status; } PUBLIC int csoundModuleDestroy(CSOUND *csound) { return 0; } } csound-6.10.0/Opcodes/syncgrain.c000066400000000000000000000566701321653344700166540ustar00rootroot00000000000000/* syncgrain.c: Synchronous granular synthesis (c) Victor Lazzarini, 2004 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "stdopcod.h" #include "syncgrain.h" #include "soundio.h" #include "interlocks.h" /* #ifdef HAVE_VALUES_H #include #endif #ifndef MAXINT #include #define MAXINT INT_MAX #endif */ static int syncgrain_init(CSOUND *csound, syncgrain *p) { int size; p->efunc = csound->FTnp2Find(csound, p->ifn2); if (UNLIKELY(p->efunc == NULL)) return NOTOK; p->sfunc = csound->FTnp2Find(csound, p->ifn1); if (UNLIKELY(p->sfunc == NULL)) return NOTOK; p->olaps = (int) *p->ols+2; if (UNLIKELY(p->olaps < 2)) p->olaps = 2; size = (p->olaps) * sizeof(double); if (p->index.auxp == NULL || p->index.size < (unsigned int)size) csound->AuxAlloc(csound, size, &p->index); if (p->envindex.auxp == NULL || p->envindex.size < (unsigned int)size) csound->AuxAlloc(csound, size, &p->envindex); if (p->envincr.auxp == NULL || p->envincr.size < (unsigned int)size) csound->AuxAlloc(csound, size, &p->envincr); size = (p->olaps) * sizeof(int); if (p->streamon.auxp == NULL || p->streamon.size < (unsigned int)size) csound->AuxAlloc(csound, size, &p->streamon); p->count = 0; /* sampling period counter */ p->numstreams = 0; /* curr num of streams */ p->firststream = 0; /* streams index (first stream) */ p->datasize = p->sfunc->flen; p->envtablesize = p->efunc->flen; /* size of envtable */ p->start = 0.0f; p->frac = 0.0f; return OK; } static int syncgrain_process(CSOUND *csound, syncgrain *p) { MYFLT sig, pitch, amp, grsize, envincr, period, fperiod, prate; MYFLT *output = p->output; MYFLT *datap = p->sfunc->ftable; MYFLT *ftable = p->efunc->ftable; int *streamon = (int *) p->streamon.auxp; float start = p->start, frac = p->frac; double *index = (double *) p->index.auxp; double *envindex = (double *) p->envindex.auxp; double *envincrn = (double *) p->envincr.auxp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t vecpos, vecsize=CS_KSMPS; int firststream = p->firststream; int numstreams = p->numstreams, olaps = p->olaps; int count = p->count, j, newstream; int datasize = p->datasize, envtablesize = p->envtablesize; pitch = *p->pitch; fperiod = FABS(CS_ESR/(*p->fr)); //if (UNLIKELY(fperiod < 0)) fperiod = -fperiod; amp = *p->amp; grsize = CS_ESR * *p->grsize; if (UNLIKELY(grsize<1)) goto err1; envincr = envtablesize/grsize; prate = *p->prate; if (UNLIKELY(offset)) memset(output, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { vecsize -= early; memset(&output[vecsize], '\0', early*sizeof(MYFLT)); } for (vecpos = offset; vecpos < vecsize; vecpos++) { sig = FL(0.0); /* if a grain has finished, clean up */ if (UNLIKELY((!streamon[firststream]) && (numstreams) )) { //numstreams--; /* decrease the no of streams */ firststream=(firststream+1)%olaps; /* first stream is the next */ } /* if a fund period has elapsed */ /* start a new grain */ period = fperiod - frac; if (count == 0 || count >= period) { if (count) frac = count - period; /* frac part to be accummulated */ newstream =(firststream+numstreams)%olaps; streamon[newstream] = 1; /* turn the stream on */ envindex[newstream] = 0.0; envincrn[newstream] = envtablesize/grsize; index[newstream] = start; numstreams++; /* increase the stream count */ count = 0; start += prate*grsize; while (UNLIKELY(start >= datasize)) start-=datasize; while (UNLIKELY(start < 0)) start+=datasize; } //for (i=numstreams, // j=firststream; i; i--, j=(j+1)%olaps) { for(j=0; j < olaps; j++){ if(!streamon[j]) continue; /* modulus */ while (UNLIKELY(index[j] >= datasize)) index[j] -= datasize; while (UNLIKELY(index[j] < 0)) index[j] += datasize; if (UNLIKELY(envindex[j] < envtablesize)){ /* sum all the grain streams */ sig += ((datap[(int)index[j]] + (index[j] - (int)index[j])* (datap[(int)index[j]+1] - datap[(int)index[j]]) ) * (ftable[(int)envindex[j]] + (envindex[j] - (int)envindex[j])* (ftable[(int)envindex[j]+1] - ftable[(int)envindex[j]]) ) ); } /* increment the indexes */ /* for each grain */ index[j] += pitch; envindex[j] += envincr; /* if the envelope is finished */ /* the grain is also finished */ if (UNLIKELY(envindex[j] >= envtablesize)) { streamon[j] = 0; numstreams--; } } /* increment the period counter */ count++; /* scale the output */ output[vecpos] = sig*amp; } p->firststream = firststream; p->numstreams = numstreams; p->count = count; p->start = start; p->frac = frac; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("grain size smaller than 1 sample\n")); } static int syncgrainloop_init(CSOUND *csound, syncgrainloop *p) { p->efunc = csound->FTnp2Find(csound, p->ifn2); if (UNLIKELY(p->efunc == NULL)) return NOTOK; p->sfunc = csound->FTnp2Find(csound, p->ifn1); if (UNLIKELY(p->sfunc == NULL)) return NOTOK; p->datasize = p->sfunc->flen; p->envtablesize = p->efunc->flen; /* size of envtable */ p->olaps = (int) *p->ols+1; if (UNLIKELY(p->olaps <2)) p->olaps = 2; if (*p->iskip == 0) { int size = (p->olaps) * sizeof(double); if (p->index.auxp == NULL || p->index.size < (unsigned int)size) csound->AuxAlloc(csound, size, &p->index); if (p->envindex.auxp == NULL || p->envindex.size < (unsigned int)size) csound->AuxAlloc(csound, size, &p->envindex); size = (p->olaps) * sizeof(int); if (p->streamon.auxp == NULL || p->streamon.size > (unsigned int)size) csound->AuxAlloc(csound, size, &p->streamon); p->count = 0; /* sampling period counter */ p->numstreams = 0; /* curr num of streams */ p->firststream = 0; /* streams index (first stream) */ p->start = *p->startpos*(CS_ESR); p->frac = 0.0f; p->firsttime = 1; } return OK; } static int syncgrainloop_process(CSOUND *csound, syncgrainloop *p) { MYFLT sig, pitch, amp, grsize, envincr, period, fperiod, prate; MYFLT *output = p->output; MYFLT *datap = p->sfunc->ftable; MYFLT *ftable = p->efunc->ftable; int *streamon = (int *) p->streamon.auxp; float start = p->start, frac = p->frac; double *index = (double *) p->index.auxp; double *envindex = (double *) p->envindex.auxp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t vecpos, vecsize=CS_KSMPS; int firststream = p->firststream; int numstreams = p->numstreams, olaps = p->olaps; int count = p->count, i,j, newstream; int datasize = p->datasize, envtablesize = p->envtablesize; int loop_start; int loop_end; int loopsize; int firsttime = p->firsttime; MYFLT sr = CS_ESR; /* loop points & checks */ loop_start = (int) (*p->loop_start*sr); loop_end = (int) (*p->loop_end*sr); if (UNLIKELY(loop_start < 0)) loop_start = 0; if (UNLIKELY(loop_start >= datasize)) loop_start = datasize-1; loop_end = (loop_start > loop_end ? loop_start : loop_end); loopsize = loop_end - loop_start; /*csound->Message(csound, "st:%d, end:%d, loopsize=%d\n", loop_start, loop_end, loopsize); */ pitch = *p->pitch; fperiod = FABS(CS_ESR/(*p->fr)); //if (UNLIKELY(fperiod < 0)) fperiod = -fperiod; amp = *p->amp; grsize = CS_ESR * *p->grsize; if (UNLIKELY(grsize<1)) goto err1; if (loopsize <= 0) loopsize = grsize; envincr = envtablesize/grsize; prate = *p->prate; if (UNLIKELY(offset)) memset(output, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { vecsize -= early; memset(&output[vecsize], '\0', early*sizeof(MYFLT)); } for (vecpos = offset; vecpos < vecsize; vecpos++) { sig = FL(0.0); /* if a grain has finished, clean up */ if (UNLIKELY((!streamon[firststream]) && (numstreams) )) { numstreams--; /* decrease the no of streams */ firststream=(firststream+1)%olaps; /* first stream is the next */ } /* if a fund period has elapsed */ /* start a new grain */ period = fperiod - frac; if (UNLIKELY(count == 0 || count >= period)) { if (count) frac = count - period; /* frac part to be accummulated */ newstream =(firststream+numstreams)%olaps; streamon[newstream] = 1; /* turn the stream on */ envindex[newstream] = 0.0; index[newstream] = start; numstreams++; /* increase the stream count */ count = 0; start += prate*grsize; /* this will keep syncgrain looping within the loop boundaries */ while (UNLIKELY(start >= loop_end)) { firsttime = 0; start -= loopsize; /*csound->Message(csound, "st:%d, end:%d, loopsize=%d\n", loop_start, loop_end, loopsize); */ } while (UNLIKELY(start < loop_start && !firsttime)) start += loopsize; } /* depending on pitch transpsition a grain can extend beyond the loop points. it will be wrapped up at the ends of the table. */ for (i=numstreams, j=firststream; i; i--, j=(j+1)%olaps) { /* modulus */ while (index[j] >= datasize) index[j] -= datasize; while(index[j] < 0) index[j] += datasize; if (UNLIKELY(envindex[j] < envtablesize)){ /* sum all the grain streams */ sig += ((datap[(int)index[j]] + (index[j] - (int)index[j])* (datap[(int)index[j]+1] - datap[(int)index[j]]) ) * (ftable[(int)envindex[j]] + (envindex[j] - (int)envindex[j])* (ftable[(int)envindex[j]+1] - ftable[(int)envindex[j]]) ) ); /* increment the indexes */ /* for each grain */ index[j] += pitch; envindex[j] += envincr; } /* if the envelope is finished */ /* the grain is also finished */ if (UNLIKELY(envindex[j] > envtablesize)) streamon[j] = 0; } /* increment the period counter */ count++; /* scale the output */ output[vecpos] = sig*amp; } p->firststream = firststream; p->numstreams = numstreams; p->count = count; p->start = start; p->frac = frac; p->firsttime = firsttime; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("grain size smaller than 1 sample\n")); } #define DGRAIN_MAXCHAN 4 #define DGRAIN_OUTTYPES "mmmm" typedef struct _filegrain { OPDS h; MYFLT *output[DGRAIN_MAXCHAN]; STRINGDAT *fname; MYFLT *amp; MYFLT *fr; MYFLT *pitch; MYFLT *grsize; MYFLT *prate; MYFLT *ifn2; MYFLT *ols; MYFLT *max; MYFLT *ioff; FUNC *efunc; SNDFILE *sf; AUXCH buffer; int count, numstreams, firststream; int dataframes, envtablesize, olaps; AUXCH streamon; AUXCH index; AUXCH envindex; float start,frac; int read1,read2; uint32 pos; float trigger; int nChannels; int32 flen; } filegrain; #define MINFBUFSIZE 88200 static int filegrain_init(CSOUND *csound, filegrain *p) { int size; void *fd; MYFLT *buffer; SF_INFO sfinfo; char *fname = p->fname->data; p->nChannels = (int) (p->OUTOCOUNT); if (UNLIKELY(p->nChannels < 1 || p->nChannels > DGRAIN_MAXCHAN)) { return csound->InitError(csound, Str("diskgrain: invalid number of channels")); } p->efunc = csound->FTnp2Find(csound, p->ifn2); if (UNLIKELY(p->efunc == NULL)) return NOTOK; p->olaps = (int) *p->ols + 1; p->dataframes = (int)(*p->max*CS_ESR*4); if (p->dataframes < MINFBUFSIZE) p->dataframes = MINFBUFSIZE; if (UNLIKELY(p->olaps < 2)) p->olaps = 2; size = (p->olaps) * sizeof(double); if (p->index.auxp == NULL || p->index.size < (unsigned int)size) csound->AuxAlloc(csound, size, &p->index); if (p->envindex.auxp == NULL || p->envindex.size < (unsigned int)size) csound->AuxAlloc(csound, size, &p->envindex); size = (p->olaps) * sizeof(int); if (p->streamon.auxp == NULL || p->streamon.size < (unsigned int)size) csound->AuxAlloc(csound, size, &p->streamon); if (p->buffer.auxp == NULL || p->buffer.size < (p->dataframes+1)*sizeof(MYFLT)*p->nChannels) csound->AuxAlloc(csound, (p->dataframes+1)*sizeof(MYFLT)*p->nChannels, &p->buffer); buffer = (MYFLT *) p->buffer.auxp; /* open file and read the first block using *p->ioff */ fd = csound->FileOpen2(csound, &(p->sf), CSFILE_SND_R, fname, &sfinfo, "SFDIR;SSDIR", CSFTYPE_UNKNOWN_AUDIO, 0); memset(buffer, 0,p->buffer.size); if (UNLIKELY(fd == NULL)) { return csound->InitError(csound, Str("diskgrain: could not open file\n")); } if (UNLIKELY(sfinfo.channels != p->nChannels)) { return csound->InitError(csound, Str("diskgrain: soundfile channel numbers " "do not match the number of outputs \n")); } if (*p->ioff >= 0) sf_seek(p->sf,*p->ioff * CS_ESR, SEEK_SET); if (LIKELY(sf_read_MYFLT(p->sf,buffer,p->dataframes*p->nChannels/2) != 0)) { p->read1 = 1; p->read2 = 0; } else { return csound->InitError(csound, Str("diskgrain: could not read file \n")); } /* -===- */ p->count = 0; /* sampling period counter */ p->numstreams = 0; /* curr num of streams */ p->firststream = 0; /* streams index (first stream) */ p->envtablesize = p->efunc->flen; /* size of envtable */ p->start = 0.0f; p->frac = 0.0f; p->pos = *p->ioff*CS_ESR; p->trigger = 0.0f; p->flen = sfinfo.frames; return OK; } static int filegrain_process(CSOUND *csound, filegrain *p) { MYFLT sig[DGRAIN_MAXCHAN], pitch, amp, grsize, envincr, period, fperiod, prate; MYFLT **output = p->output; MYFLT *datap = (MYFLT *) p->buffer.auxp; MYFLT *ftable = p->efunc->ftable; int *streamon = (int *) p->streamon.auxp; float start = p->start, frac = p->frac, jump; double *index = (double *) p->index.auxp; double *envindex = (double *) p->envindex.auxp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t vecpos, vecsize=CS_KSMPS; int firststream = p->firststream; int numstreams = p->numstreams, olaps = p->olaps; int count = p->count, i,j, newstream; int datasize, hdatasize, envtablesize = p->envtablesize; int dataframes = p->dataframes, hdataframes = p->dataframes/2; int read1 = p->read1, read2 = p->read2; int items, chans = p->nChannels, tndx,endx,n; uint32 pos = p->pos; int32 negpos, flen = p->flen; float trigger = p->trigger, incr; memset(sig, 0, DGRAIN_MAXCHAN*sizeof(MYFLT)); datasize = dataframes*chans; hdatasize = hdataframes*chans; pitch = *p->pitch; fperiod = FABS(CS_ESR/(*p->fr)); //if (UNLIKELY(fperiod < FL(0.0))) fperiod = -fperiod; amp = *p->amp; grsize = CS_ESR * *p->grsize; if (UNLIKELY(grsize<1)) goto err1; if (grsize > hdataframes) grsize = hdataframes; envincr = envtablesize/grsize; prate = *p->prate; if (UNLIKELY(offset)) memset(output, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { vecsize -= early; memset(&output[vecsize], '\0', early*sizeof(MYFLT)); } for (vecpos = offset; vecpos < vecsize; vecpos++) { /* sig = (MYFLT) 0; */ /* if a grain has finished, clean up */ if (UNLIKELY((!streamon[firststream]) && (numstreams) )) { numstreams--; /* decrease the no of streams */ firststream=(firststream+1)%olaps; /* first stream is the next */ } /* if a fund period has elapsed */ /* start a new grain */ period = fperiod - frac; if (count ==0 || count >= period) { if (count) frac = count - period; newstream =(firststream+numstreams)%olaps; streamon[newstream] = 1; envindex[newstream] = 0.0; index[newstream] = start; numstreams++; count = 0; incr = prate*grsize; start += (incr); trigger += (incr); jump = grsize*(pitch > 0 ? pitch : -pitch); if (incr >= 0) { if (trigger >= (dataframes - jump)) { trigger -= (dataframes); if (!read1) { pos += hdataframes; sf_seek(p->sf,pos,SEEK_SET); items = sf_read_MYFLT(p->sf,datap,hdatasize); if (items < hdatasize) { sf_seek(p->sf, 0, 0); sf_read_MYFLT(p->sf,datap+items, hdatasize-items); } for (n=0; n < chans; n++) datap[hdatasize+n] = datap[hdatasize-chans+n]; read1 = 1; read2 = 0; } } else if (trigger >= (hdataframes - jump)) { if (!read2) { pos += hdataframes; sf_seek(p->sf,pos,SEEK_SET); items = sf_read_MYFLT(p->sf,datap+hdatasize, hdatasize); if (items < hdatasize) { sf_seek(p->sf, 0, SEEK_SET); sf_read_MYFLT(p->sf,datap+items+hdatasize, hdatasize-items); } for (n=0; n < chans; n++) datap[datasize+n] = datap[datasize-chans+n]; read2 = 1; read1 = 0; } } } else { if (trigger < jump) { trigger += (dataframes); if (!read1) { /*this roundabout code is to allow us to use an unsigned long to hold the file position whilst allowing for pos to go negative */ negpos = pos; negpos -= hdataframes; if (negpos < 0) { while(negpos < 0) negpos += flen; pos = negpos; } else pos -= hdataframes; /* pos -= hdataframes; if (pos < 0) pos += flen; */ sf_seek(p->sf,pos,SEEK_SET); items = sf_read_MYFLT(p->sf,datap+hdatasize,hdatasize); if (items < hdatasize) { sf_seek(p->sf,items-hdatasize,SEEK_END); sf_read_MYFLT(p->sf,datap+hdatasize+items, hdatasize-items); } for (n=0; n < chans; n++) datap[datasize+n] = datap[datasize-chans+n]; read1 = 1; read2 = 0; } } else if (trigger <= (hdataframes + jump)) { if (!read2) { negpos = pos; negpos -= hdataframes; if (negpos < 0) { while(negpos < 0) negpos += flen; pos = negpos; } else pos -= hdataframes; /* pos -= hdataframes; if (pos < 0) pos += flen; */ sf_seek(p->sf,pos,SEEK_SET); items = sf_read_MYFLT(p->sf,datap,hdatasize); if (items < hdatasize) { sf_seek(p->sf,items-hdatasize,SEEK_END); (void) sf_read_MYFLT(p->sf,datap+items,hdatasize-items); } for (n=0; n < chans; n++) datap[hdatasize+n] = datap[hdatasize-chans+n]; read2 = 1; read1 = 0; } } } if (start >= dataframes) start -= dataframes; if (start < 0) start += dataframes; } for (i=numstreams, j=firststream; i; i--, j=(j+1)%olaps) { /* modulus */ if (index[j] >= dataframes) index[j] -= dataframes; if (index[j] < 0) index[j] += dataframes; /* sum all the grain streams */ tndx = (int)index[j]*chans; endx = (int) envindex[j]; /* sig[0] = sig[1] = sig[2] = sig[3] = 0.0; */ for (n=0; n < chans; n++) { sig[n] += ((datap[tndx+n] + (index[j] - (int)index[j])* (datap[tndx+n+chans] - datap[tndx+n]) ) * (ftable[endx] + (envindex[j] - endx)* (ftable[endx+1] - ftable[endx]) ) ); } /* increment the indexes */ /* for each grain */ index[j] += (pitch); envindex[j] += envincr; /* if the envelope is finished */ /* the grain is also finished */ if (envindex[j] > envtablesize) streamon[j] = 0; } /* increment the period counter */ count++; /* scale the output */ for (n=0; n < chans; n++) { output[n][vecpos] = sig[n]*amp; sig[n] = 0; } } p->firststream = firststream; p->numstreams = numstreams; p->count = count; p->start = start; p->frac = frac; p->trigger = trigger; p->read1 = read1; p->read2 = read2; p->pos = pos; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("grain size smaller than 1 sample\n")); } static OENTRY localops[] = { {"syncgrain", sizeof(syncgrain), TR, 5, "a", "kkkkkiii", (SUBR)syncgrain_init, NULL,(SUBR)syncgrain_process }, {"syncloop", sizeof(syncgrainloop), TR, 5, "a", "kkkkkkkiiioo", (SUBR)syncgrainloop_init, NULL,(SUBR)syncgrainloop_process }, {"diskgrain", sizeof(filegrain), TR, 5, DGRAIN_OUTTYPES, "Skkkkkiipo", (SUBR)filegrain_init, NULL,(SUBR)filegrain_process } }; int syncgrain_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/syncgrain.h000066400000000000000000000123371321653344700166510ustar00rootroot00000000000000/* syncgrain.h: Synchronous granular synthesis (c) Victor Lazzarini, 2004 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* SYNCGRAIN: Syncgrain implements synchronous granular synthesis. The source sound for the grains is obtained by reading a function table containing the samples of the source waveform. For sampled-sound sources, GEN01 is used. Syncgrain will accept deferred allocation tables (with aif files). The grain generator has full control of frequency (grains/sec), overall amplitude, grain pitch (a sampling increment) and grain size (in secs), both as fixed or time-varying (signal) parameters. An extra parameter is the grain pointer speed (or rate), which controls which position the generator will start reading samples in the table for each successive grain. It is measured in fractions of grain size, so a value of 1 (the default) will make each successive grain read from where the previous grain should finish. A value of 0.5 will make the next grain start at the midway position from the previous grain start and finish, etc.. A value of 0 will make the generator read always from a fixed position of the table (wherever the pointer was last at). A negative value will decrement pointer positions. This control gives extra flexibility for creating timescale modifications in the resynthesis. Syncgrain will generate any number of parallel grain streams (which will depend on grain density/frequency), up to the olaps value (default 100). The number of streams (overlapped grains) is determined by grainsize*grain_freq. More grain overlaps will demand more calculations and the synthesis might not run in realtime (depending on processor power). Syncgrain can simulate FOF-like formant synthesis, provided that a suitable shape is used as grain envelope and a sinewave as the grain wave. For this use, grain sizes of around 0.04 secs can be used. The formant centre frequency is determined by the grain pitch. Since this is a sampling increment, in order to use a frequency in Hz, that value has to be scaled by tablesize/sr. Grain frequency will determine the fundamental. Syncgrain uses floating-point indexing, so its precision is not affected by large-size tables. asig syncgrain kamp, kfreq, kpitch, kgrsize, kprate, ifun1, ifun2, iolaps kamp: amplitude scaling kfreq: frequency of grain generation, or density, in grains/sec. kpitch: grain pitch scaling (1=normal pitch, < 1 lower, > 1 higher; negative, backwards) kgrsize: grain size in secs. kprate: grain pointer rate, in relation to grainsize. The value of 1 will advance the reading pointer 1 grain ahead in the source table. Larger values will time-compress and smaller values will time-expand the source signal. Negative values will cause the pointer to run backwards and zero will freeze it. ifun1: source signal function table. Deferred-allocation tables are accepted. ifun2: grain envelope function table. iolaps: maximum number of overlaps, max(kfreq)*max(kgrsize). The syncgrain opcode is based on an improved version of the original SndObj library SyncGrain class. SYNCLOOP: A variation on syncgrain allowing for loop points to be set, as well as sound start position asig syncloop kamp, kfreq, kpitch, kgrsize, kprate,kloopstart, kloopend, \ ifun1, ifun2, iolaps [, istart] parameters are as above, with the following additions: kloopstart - loop start point (in secs) kloopend - loop end point (in secs) istart - start position (in secs), defaults to 0. */ #ifndef _SYNCGRAIN_H #define _SYNCGRAIN_H typedef struct _syncgrain { OPDS h; MYFLT *output; MYFLT *amp; MYFLT *fr; MYFLT *pitch; MYFLT *grsize; MYFLT *prate; MYFLT *ifn1; MYFLT *ifn2; MYFLT *ols; FUNC *sfunc; FUNC *efunc; int count, numstreams, firststream; int datasize, envtablesize, olaps; AUXCH streamon; AUXCH index; AUXCH envindex; AUXCH envincr; float start,frac; } syncgrain; typedef struct _syncgrainl { OPDS h; MYFLT *output; MYFLT *amp; MYFLT *fr; MYFLT *pitch; MYFLT *grsize; MYFLT *prate; MYFLT *loop_start; MYFLT *loop_end; MYFLT *ifn1; MYFLT *ifn2; MYFLT *ols; MYFLT *startpos; MYFLT *iskip; FUNC *sfunc; FUNC *efunc; int count, numstreams, firststream; int datasize, envtablesize, olaps; AUXCH streamon; AUXCH index; AUXCH envindex; float start,frac; int firsttime; } syncgrainloop; static int syncgrain_process(CSOUND *csound, syncgrain *p); static int syncgrain_init(CSOUND *csound, syncgrain *p); #endif csound-6.10.0/Opcodes/system_call.c000066400000000000000000000052021321653344700171570ustar00rootroot00000000000000/* system_call.c: Copyright (C) 2007 John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csdl.h" typedef struct { OPDS h; MYFLT *res; MYFLT *ktrig; STRINGDAT *commandLine; MYFLT *nowait; char *command; MYFLT prv_ktrig; CSOUND *csound; } SYSTEM; #if defined(WIN32) static void threadroutine(void *p) { SYSTEM *pp = (SYSTEM *) p; system(pp->command); pp->csound->Free(pp->csound,pp->command); } static int call_system(CSOUND *csound, SYSTEM *p) { _flushall(); if ( (int)*p->nowait != 0 ) { p->command = csound->Strdup(csound, p->commandLine->data); p->csound = csound; _beginthread( threadroutine, 0, p); *p->res = OK; } else { *p->res = (MYFLT) system( (char *)p->commandLine->data ); } return OK; } #else #include static int call_system(CSOUND *csound, SYSTEM *p) { IGN(csound); if ((int)*p->nowait!=0) { if ((*p->res = fork())) return OK; else { if (UNLIKELY(system((char*)p->commandLine->data)<0)) exit(1); exit(0); } } else { *p->res = (MYFLT)system((char*)p->commandLine->data); return OK; } } #endif int call_system_i(CSOUND *csound, SYSTEM *p) { if (*p->ktrig <= FL(0.0)) { *p->res=FL(0.0); return OK; } else return call_system(csound, p); } int call_system_set(CSOUND *csound, SYSTEM *p) { IGN(csound); p->prv_ktrig = FL(0.0); return OK; } int call_system_k(CSOUND *csound, SYSTEM *p) { if (*p->ktrig == p->prv_ktrig) return OK; p->prv_ktrig = *p->ktrig; if (p->prv_ktrig > FL(0.0)) return (call_system(csound, p)); return OK; } #define S(x) sizeof(x) static OENTRY system_localops[] = { { "system", S(SYSTEM), 0, 3, "k", "kSO", (SUBR)call_system_set,(SUBR)call_system_k}, { "system_i", S(SYSTEM), 0, 1, "i", "iSo", (SUBR)call_system_i} }; LINKAGE_BUILTIN(system_localops) csound-6.10.0/Opcodes/tabsum.c000066400000000000000000000040561321653344700161410ustar00rootroot00000000000000/* tabsum.c: Copyright (C) 2009 John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "interlocks.h" typedef struct { OPDS h; MYFLT *kans; MYFLT *itab; MYFLT *kmin, *kmax; /* Local */ FUNC *ftp; } TABSUM; static int tabsuminit(CSOUND *csound, TABSUM *p) { if (UNLIKELY((p->ftp = csound->FTnp2Find(csound, p->itab)) == NULL)) { return csound->InitError(csound, Str("tabsum: No table")); } return OK; } static int tabsum(CSOUND *csound, TABSUM *p) { int i, min, max; MYFLT ans = FL(0.0); FUNC *ftp = p->ftp; MYFLT *t; if (UNLIKELY(ftp==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("tabsum: Not initialised")); t = p->ftp->ftable; min = MYFLT2LRND(*p->kmin); max = MYFLT2LRND(*p->kmax); if (UNLIKELY(min == 0 && max == 0)) max = ftp->flen-1; else if (UNLIKELY(min > max)) { int k = min; min = max; max = k; } /* printf("tabsum: min, max = %d, %d\n", min, max); */ for (i=min; i<=max; i++) ans += t[i]; *p->kans = ans; return OK; } #define S(x) sizeof(x) static OENTRY tabsum_localops[] = { { "tabsum", S(TABSUM), 0, 3, "k", "iOO", (SUBR)tabsuminit, (SUBR)tabsum }, }; LINKAGE_BUILTIN(tabsum_localops) csound-6.10.0/Opcodes/tl/000077500000000000000000000000001321653344700151145ustar00rootroot00000000000000csound-6.10.0/Opcodes/tl/fractalnoise.cpp000066400000000000000000000413231321653344700202750ustar00rootroot00000000000000/* fractalnoise.cpp: Code generated with Faust 0.9.43 (c) Tito Latini, 2012 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #define max(x,y) (((x)>(y)) ? (x) : (y)) #define min(x,y) (((x)<(y)) ? (x) : (y)) #define dv2_31 (FL(4.656612873077392578125e-10)) typedef struct opdata{ OPDS h; } OPDATA; inline int lsr (int x, int n) { return int(((unsigned int)x) >> n); } /* VECTOR INTRINSICS */ //inline void *aligned_calloc(size_t nmemb, size_t size) //{ // return (void*)(((unsigned long)(calloc((nmemb*size)+15, // (sizeof(char))))+15) & 0xfffffff0); //} /* ABSTRACT USER INTERFACE */ struct Meta { void declare (const char* key, const char* value) { } }; class UserInterface { bool fStopped; public: UserInterface() : fStopped(false) {} virtual ~UserInterface() {} virtual void addButton(char* label, MYFLT* zone) = 0; virtual void addToggleButton(char* label, MYFLT* zone) = 0; virtual void addCheckButton(char* label, MYFLT* zone) = 0; virtual void addVerticalSlider(char* label, MYFLT* zone, MYFLT init, MYFLT min, MYFLT max, MYFLT step) = 0; virtual void addHorizontalSlider(char* label, MYFLT* zone, MYFLT init, MYFLT min, MYFLT max, MYFLT step) = 0; virtual void addNumEntry(char* label, MYFLT* zone, MYFLT init, MYFLT min, MYFLT max, MYFLT step) = 0; virtual void openFrameBox(char* label) = 0; virtual void openTabBox(char* label) = 0; virtual void openHorizontalBox(char* label) = 0; virtual void openVerticalBox(char* label) = 0; virtual void closeBox() = 0; virtual void run() = 0; void stop() { fStopped = true; } bool stopped() { return fStopped; } }; class csUI : public UserInterface { private: MYFLT* args[2]; int ctrlCount; void addZone(MYFLT* zone) { args[ctrlCount++] = zone; } public: csUI() : UserInterface(), ctrlCount(0) { args[0] = args[1] = NULL; }; virtual ~csUI() {}; virtual void addButton(char* label, MYFLT* zone) { addZone(zone); } virtual void addToggleButton(char* label, MYFLT* zone) { addZone(zone); } virtual void addCheckButton(char* label, MYFLT* zone) { addZone(zone); } virtual void addVerticalSlider(char* label, MYFLT* zone, MYFLT init, MYFLT min, MYFLT max, MYFLT step) { addZone(zone); } virtual void addHorizontalSlider(char* label, MYFLT* zone, MYFLT init, MYFLT min, MYFLT max, MYFLT step) { addZone(zone); } virtual void addNumEntry(char* label, MYFLT* zone, MYFLT init, MYFLT min, MYFLT max, MYFLT step) { addZone(zone); } virtual void openFrameBox(char*) {} virtual void openTabBox(char*) {} virtual void openHorizontalBox(char*) {} virtual void openVerticalBox(char*) {} virtual void closeBox() {} virtual void show() {} virtual void run() {} void updateCtrlZones(MYFLT* cs_amp, MYFLT* cs_beta) { *args[0] = *cs_amp; *args[1] = *cs_beta; } }; /* FAUST DSP */ /* abstract definition of a signal processor */ class dsp { protected: int fSamplingFreq; public: dsp() { fSamplingFreq = -1; } virtual ~dsp() {} virtual int getNumInputs() = 0; virtual int getNumOutputs() = 0; virtual void buildUserInterface(UserInterface* userInterface) = 0; virtual void init(int samplingRate) = 0; virtual void compute(CSOUND* csound, MYFLT* output, void *p) = 0; }; /* FAUST generated code */ class mydsp : public dsp { private: int iConst0; MYFLT fConst1; MYFLT fConst2; int iRec8[2]; MYFLT fConst3; MYFLT fConst4; MYFLT fConst5; MYFLT fConst6; MYFLT fConst7; MYFLT fConst8; MYFLT fRec7[3]; MYFLT fslider0; MYFLT fConst9; MYFLT fConst10; MYFLT fConst11; MYFLT fConst12; MYFLT fConst13; MYFLT fConst14; MYFLT fRec6[3]; MYFLT fConst15; MYFLT fConst16; MYFLT fConst17; MYFLT fConst18; MYFLT fConst19; MYFLT fConst20; MYFLT fRec5[3]; MYFLT fConst21; MYFLT fConst22; MYFLT fConst23; MYFLT fConst24; MYFLT fConst25; MYFLT fConst26; MYFLT fRec4[3]; MYFLT fConst27; MYFLT fConst28; MYFLT fConst29; MYFLT fConst30; MYFLT fConst31; MYFLT fConst32; MYFLT fRec3[3]; MYFLT fConst33; MYFLT fConst34; MYFLT fConst35; MYFLT fConst36; MYFLT fConst37; MYFLT fConst38; MYFLT fRec2[3]; MYFLT fConst39; MYFLT fConst40; MYFLT fConst41; MYFLT fConst42; MYFLT fConst43; MYFLT fConst44; MYFLT fRec1[3]; MYFLT fRec0[2]; MYFLT fslider1; public: static void metadata(Meta* m) { m->declare("name", "Fractal Noise"); m->declare("author", "Tito Latini"); m->declare("license", "GNU LGPL"); m->declare("copyright", "Tito Latini"); m->declare("version", "1.0"); m->declare("music.lib/name", "Music Library"); m->declare("music.lib/author", "GRAME"); m->declare("music.lib/copyright", "GRAME"); m->declare("music.lib/version", "1.0"); m->declare("music.lib/license", "LGPL"); m->declare("math.lib/name", "Math Library"); m->declare("math.lib/author", "GRAME"); m->declare("math.lib/copyright", "GRAME"); m->declare("math.lib/version", "1.0"); m->declare("math.lib/license", "LGPL"); } virtual int getNumInputs() { return 0; } virtual int getNumOutputs() { return 1; } static void classInit(int samplingFreq) { } virtual void instanceInit(int samplingFreq) { fSamplingFreq = samplingFreq; iConst0 = min(192000, max(1, fSamplingFreq)); fConst1 = FL(67683.56194843161) / iConst0; fConst2 = (- EXP(-fConst1)); for (int i=0; i<2; i++) iRec8[i] = 0; fConst3 = FL(314.1592653589793) / iConst0; fConst4 = EXP(-fConst3); fConst5 = FL(461.1227396105972) / iConst0; fConst6 = EXP(-fConst5); fConst7 = -fConst6 - fConst4; fConst8 = -fConst6 * -fConst4; for (int i=0; i<3; i++) fRec7[i] = 0; fslider0 = FL(1.75); fConst9 = FL(676.8356194843168) / iConst0; fConst10 = EXP(-fConst9); fConst11 = FL(993.4588265796098) / iConst0; fConst12 = EXP(-fConst11); fConst13 = -fConst12 - fConst10; fConst14 = -fConst12 * -fConst10; for (int i=0; i<3; i++) fRec6[i] = 0; fConst15 = FL(1458.1981380662319) / iConst0; fConst16 = EXP(-fConst15); fConst17 = FL(2140.3421591014803) / iConst0; fConst18 = EXP(-fConst17); fConst19 = -fConst18 - fConst16; fConst20 = -fConst18 * -fConst16; for (int i=0; i<3; i++) fRec5[i] = 0; fConst21 = FL(3141.5926535897916) / iConst0; fConst22 = EXP(-fConst21); fConst23 = FL(4611.22739610597) / iConst0; fConst24 = EXP(-fConst23); fConst25 = -fConst24 - fConst22; fConst26 = -fConst24 * -fConst22; for (int i=0; i<3; i++) fRec4[i] = 0; fConst27 = FL(6768.356194843165) / iConst0; fConst28 = EXP(-fConst27); fConst29 = FL(9934.588265796094) / iConst0; fConst30 = EXP(-fConst29); fConst31 = -fConst30 - fConst28; fConst32 = -fConst30 * -fConst28; for (int i=0; i<3; i++) fRec3[i] = 0; fConst33 = FL(14581.981380662311) / iConst0; fConst34 = EXP(-fConst33); fConst35 = FL(21403.421591014794) / iConst0; fConst36 = EXP(-fConst35); fConst37 = -fConst36 - fConst34; fConst38 = -fConst36 * -fConst34; for (int i=0; i<3; i++) fRec2[i] = 0; fConst39 = FL(31415.926535897903) / iConst0; fConst40 = EXP(-fConst39); fConst41 = FL(46112.27396105968f) / iConst0; fConst42 = EXP(-fConst41); fConst43 = -fConst42 - fConst40; fConst44 = -fConst42 * -fConst40; for (int i=0; i<3; i++) fRec1[i] = 0; for (int i=0; i<2; i++) fRec0[i] = 0; fslider1 = FL(1.0); } virtual void init(int samplingFreq) { classInit(samplingFreq); instanceInit(samplingFreq); } virtual void buildUserInterface(UserInterface* userInterface) { userInterface->openVerticalBox((char*)"fractalnoise"); userInterface->addVerticalSlider((char*)"amp", &fslider1, FL(1.0), FL(0.0), FL(20.0), FL(0.01)); userInterface->addVerticalSlider((char*)"beta", &fslider0, FL(1.75), FL(0.0), FL(10.0), FL(0.01)); userInterface->closeBox(); } virtual void compute (CSOUND* csound, MYFLT* output, void *p) { int nn = ((OPDATA*)p)->h.insdshead->ksmps; uint32_t offset = ((OPDATA *) p)->h.insdshead->ksmps_offset; uint32_t early = ((OPDATA *) p)->h.insdshead->ksmps_no_end; MYFLT fSlow0 = POWER(FL(10.0),(FL(0.08333333333333333) * fslider0)); MYFLT fSlow1 = EXP(-(fConst3 * fSlow0)); MYFLT fSlow2 = EXP(-(fConst5 * fSlow0)); MYFLT fSlow3 = -fSlow2 * -fSlow1; MYFLT fSlow4 = -fSlow2 - fSlow1; MYFLT fSlow5 = EXP(-(fConst9 * fSlow0)); MYFLT fSlow6 = EXP(-(fConst11 * fSlow0)); MYFLT fSlow7 = -fSlow6 * -fSlow5; MYFLT fSlow8 = -fSlow6 - fSlow5; MYFLT fSlow9 = EXP(-(fConst15 * fSlow0)); MYFLT fSlow10 = EXP(-(fConst17 * fSlow0)); MYFLT fSlow11 = -fSlow10 * -fSlow9; MYFLT fSlow12 = -fSlow10 - fSlow9; MYFLT fSlow13 = EXP(-(fConst21 * fSlow0)); MYFLT fSlow14 = EXP(-(fConst23 * fSlow0)); MYFLT fSlow15 = -fSlow14 * -fSlow13; MYFLT fSlow16 = (FL(0.0) - (fSlow14 + fSlow13)); MYFLT fSlow17 = EXP(-(fConst27 * fSlow0)); MYFLT fSlow18 = EXP(-(fConst29 * fSlow0)); MYFLT fSlow19 = -fSlow18 * -fSlow17; MYFLT fSlow20 = -fSlow18 - fSlow17; MYFLT fSlow21 = EXP(-(fConst33 * fSlow0)); MYFLT fSlow22 = EXP(-(fConst35 * fSlow0)); MYFLT fSlow23 = -fSlow22 * -fSlow21; MYFLT fSlow24 = -fSlow22 - fSlow21; MYFLT fSlow25 = EXP(-(fConst39 * fSlow0)); MYFLT fSlow26 = EXP(-(fConst41 * fSlow0)); MYFLT fSlow27 = -fSlow26 * -fSlow25; MYFLT fSlow28 = -fSlow26 - fSlow25; MYFLT fSlow29 = (- EXP(-(fConst1 * fSlow0))); MYFLT fSlow30 = fslider1; MYFLT* output0 = output; if (UNLIKELY(offset)) memset(output0, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nn -= early; memset(&output0[nn], '\0', early*sizeof(MYFLT)); } for (int i=offset; iGetRandSeed(csound, 1) + (1103515245 * iRec8[1])); fRec7[0] = -((fConst8 * fRec7[2]) + (fConst7 * fRec7[1])) + (iRec8[0] * dv2_31); fRec6[0] = (0 - (((fConst14 * fRec6[2]) + (fConst13 * fRec6[1])) - ((fSlow4 * fRec7[1]) + (fRec7[0] + (fSlow3 * fRec7[2]))))); fRec5[0] = (0 - (((fConst20 * fRec5[2]) + (fConst19 * fRec5[1])) - ((fSlow8 * fRec6[1]) + (fRec6[0] + (fSlow7 * fRec6[2]))))); fRec4[0] = (0 - (((fConst26 * fRec4[2]) + (fConst25 * fRec4[1])) - ((fSlow12 * fRec5[1]) + (fRec5[0] + (fSlow11 * fRec5[2]))))); fRec3[0] = (0 - (((fConst32 * fRec3[2]) + (fConst31 * fRec3[1])) - ((fSlow16 * fRec4[1]) + (fRec4[0] + (fSlow15 * fRec4[2]))))); fRec2[0] = (0 - (((fConst38 * fRec2[2]) + (fConst37 * fRec2[1])) - ((fSlow20 * fRec3[1]) + (fRec3[0] + (fSlow19 * fRec3[2]))))); fRec1[0] = (0 - (((fConst44 * fRec1[2]) + (fConst43 * fRec1[1])) - ((fSlow24 * fRec2[1]) + (fRec2[0] + (fSlow23 * fRec2[2]))))); fRec0[0] = (((fSlow28 * fRec1[1]) + (fRec1[0] + (fSlow27 * fRec1[2]))) - (fConst2 * fRec0[1])); output0[i] = (MYFLT)(fSlow30 * (fRec0[0] + (fSlow29 * fRec0[1]))); // post processing fRec0[1] = fRec0[0]; fRec1[2] = fRec1[1]; fRec1[1] = fRec1[0]; fRec2[2] = fRec2[1]; fRec2[1] = fRec2[0]; fRec3[2] = fRec3[1]; fRec3[1] = fRec3[0]; fRec4[2] = fRec4[1]; fRec4[1] = fRec4[0]; fRec5[2] = fRec5[1]; fRec5[1] = fRec5[0]; fRec6[2] = fRec6[1]; fRec6[1] = fRec6[0]; fRec7[2] = fRec7[1]; fRec7[1] = fRec7[0]; iRec8[1] = iRec8[0]; } } }; //typedef struct mydsp FaustCode; typedef struct { OPDS h; MYFLT *out, *kamp, *kbeta; mydsp *faust; csUI *cs_interface; } FRACTALNOISE; extern "C" { int fractalnoise_cleanup(CSOUND *csound, FRACTALNOISE *p) { delete p->faust; delete p->cs_interface; p->faust = 0; p->cs_interface = 0; return OK; } int fractalnoise_init(CSOUND *csound, FRACTALNOISE *p) { p->faust = new mydsp; p->cs_interface = new csUI; p->faust->init((int)csound->GetSr(csound)); p->faust->buildUserInterface(p->cs_interface); csound->RegisterDeinitCallback(csound, p, (int (*)(CSOUND*, void*)) fractalnoise_cleanup); return OK; } int fractalnoise_process(CSOUND *csound, FRACTALNOISE *p) { p->cs_interface->updateCtrlZones(p->kamp, p->kbeta); p->faust->compute(csound, p->out, p); return OK; } static OENTRY localops[] = { { (char*)"fractalnoise", sizeof(FRACTALNOISE), 0, 5, (char*)"a", (char*)"kk", (SUBR)fractalnoise_init, NULL, (SUBR)fractalnoise_process }, { 0, 0, 0, 0, 0, 0, 0, 0, 0} }; #ifndef INIT_STATIC_MODULES PUBLIC int csoundModuleCreate(CSOUND *csound) { return OK; } #endif PUBLIC int csoundModuleInit_fractalnoise(CSOUND *csound) { int status = 0; for(OENTRY *oentry = &localops[0]; oentry->opname; oentry++) { status |= csound->AppendOpcode(csound, oentry->opname, oentry->dsblksiz, oentry->flags, oentry->thread, oentry->outypes, oentry->intypes, (int (*)(CSOUND*,void*)) oentry->iopadr, (int (*)(CSOUND*,void*)) oentry->kopadr, (int (*)(CSOUND*,void*)) oentry->aopadr); } return status; } #ifndef INIT_STATIC_MODULES PUBLIC int csoundModuleInit(CSOUND *csound) { return csoundModuleInit_fractalnoise(csound); } PUBLIC int csoundModuleDestroy(CSOUND *csound) { return OK; } #endif } csound-6.10.0/Opcodes/tl/fractalnoise.dsp000066400000000000000000000042131321653344700202760ustar00rootroot00000000000000declare name "Fractal Noise"; declare author "Tito Latini"; declare license "GNU LGPL"; declare copyright "Tito Latini"; declare version "1.0"; import("music.lib"); /* density of the poles */ h = 6.0; amp = vslider("amp", 1.0, 0.0, 20.0, 0.01); /* * beta = 0, white noise * beta = 1, pink noise * beta = 2, brownian noise */ beta = vslider("beta", 1.75, 0.0, 10.0, 0.01); c1 = pow(10.0, 1 / h); c2 = pow(10.0, beta / (2.0 * h)); T = 1.0 / SR ; /* poles */ p1 = 50; /* pole with lowest frequency */ p2 = p1 * c1; p3 = p2 * c1; p4 = p3 * c1; p5 = p4 * c1; p6 = p5 * c1; p7 = p6 * c1; p8 = p7 * c1; p9 = p8 * c1; p10 = p9 * c1; p11 = p10 * c1; p12 = p11 * c1; p13 = p12 * c1; p14 = p13 * c1; p15 = p14 * c1; coeffCalc(frq) = 0.0 - exp(0.0 - (2.0 * PI * frq * T)); /* coeff a */ a1 = coeffCalc(p1); a2 = coeffCalc(p2); a3 = coeffCalc(p3); a4 = coeffCalc(p4); a5 = coeffCalc(p5); a6 = coeffCalc(p6); a7 = coeffCalc(p7); a8 = coeffCalc(p8); a9 = coeffCalc(p9); a10 = coeffCalc(p10); a11 = coeffCalc(p11); a12 = coeffCalc(p12); a13 = coeffCalc(p13); a14 = coeffCalc(p14); a15 = coeffCalc(p15); /* zeros */ z1 = p1 * c2; z2 = p2 * c2; z3 = p3 * c2; z4 = p4 * c2; z5 = p5 * c2; z6 = p6 * c2; z7 = p7 * c2; z8 = p8 * c2; z9 = p9 * c2; z10 = p10 * c2; z11 = p11 * c2; z12 = p12 * c2; z13 = p13 * c2; z14 = p14 * c2; z15 = p15 * c2; /* coeff b */ b1 = coeffCalc(z1); b2 = coeffCalc(z2); b3 = coeffCalc(z3); b4 = coeffCalc(z4); b5 = coeffCalc(z5); b6 = coeffCalc(z6); b7 = coeffCalc(z7); b8 = coeffCalc(z8); b9 = coeffCalc(z9); b10 = coeffCalc(z10); b11 = coeffCalc(z11); b12 = coeffCalc(z12); b13 = coeffCalc(z13); b14 = coeffCalc(z14); b15 = coeffCalc(z15); sezioni = TF2(1, b1+b2, b1*b2, a1+a2, a1*a2) : TF2(1, b3+b4, b3*b4, a3+a4, a3*a4) : TF2(1, b5+b6, b5*b6, a5+a6, a5*a6) : TF2(1, b7+b8, b7*b8, a7+a8, a7*a8) : TF2(1, b9+b10, b9*b10, a9+a10, a9*a10) : TF2(1, b11+b12, b11*b12, a11+a12, a11*a12) : TF2(1, b13+b14, b13*b14, a13+a14, a13*a14) : TF2(1, b15 , 0, a15, 0) * amp; fractalNoise = noise : sezioni; process = fractalNoise; csound-6.10.0/Opcodes/tl/sc_noise.c000066400000000000000000000247201321653344700170670ustar00rootroot00000000000000/* sc_noise.c: Based on the noise ugens of SuperCollider. (c) Tito Latini, 2012 This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* 08.03.2015 gausstrig was fixed to properly work at k-time. Also I added an optional feature related to the behavior of very first impulse. -- Gleb Rogozinsky */ #include "csoundCore.h" typedef struct { OPDS h; MYFLT *out, *kamp, *kdensity, density0, thresh, scale; int32 rand; } DUST; typedef struct { OPDS h; /* 8.03.15 Added new option ifrst1 --Gleb R */ MYFLT *out, *kamp, *kfrq, *kdev, *imode, *ifrst1, frq0; int32 count, rand, mmode; } GAUSSTRIG; #define BIPOLAR 0x7FFFFFFF /* Constant to make bipolar */ #define dv2_31 (FL(4.656612873077392578125e-10)) static int dust_init(CSOUND *csound, DUST *p) { p->density0 = FL(0.0); p->thresh = FL(0.0); p->scale = FL(0.0); p->rand = csoundRand31(&csound->randSeed1); return OK; } static int dust_process_krate(CSOUND *csound, DUST *p) { MYFLT density, thresh, scale, r; density = *p->kdensity; if (density != p->density0) { thresh = p->thresh = density * csound->onedsr*csound->ksmps; scale = p->scale = (thresh > FL(0.0) ? FL(1.0) / thresh : FL(0.0)); p->density0 = density; } else { thresh = p->thresh; scale = p->scale; } p->rand = csoundRand31(&p->rand); r = (MYFLT)p->rand * dv2_31; *p->out = *p->kamp * (r < thresh ? r*scale : FL(0.0)); return OK; } static int dust_process_arate(CSOUND *csound, DUST *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t n, nsmps = CS_KSMPS; MYFLT *out, density, thresh, scale; out = p->out; density = *p->kdensity; if (density != p->density0) { thresh = p->thresh = density * csound->onedsr; scale = p->scale = (thresh > FL(0.0) ? FL(1.0) / thresh : FL(0.0)); p->density0 = density; } else { thresh = p->thresh; scale = p->scale; } memset(out, '\0', offset*sizeof(MYFLT)); for (n=offset; nrand = csoundRand31(&p->rand); r = (MYFLT)p->rand * dv2_31; out[n] = *p->kamp * (r < thresh ? r*scale : FL(0.0)); } return OK; } static int dust2_process_krate(CSOUND *csound, DUST *p) { MYFLT density, thresh, scale, r; density = *p->kdensity; if (density != p->density0) { thresh = p->thresh = density * csound->onedsr*csound->ksmps; scale = p->scale = (thresh > FL(0.0) ? FL(2.0) / thresh : FL(0.0)); p->density0 = density; } else { thresh = p->thresh; scale = p->scale; } p->rand = csoundRand31(&p->rand); r = (MYFLT)p->rand * dv2_31; *p->out = *p->kamp * (r < thresh ? r*scale - FL(1.0) : FL(0.0)); return OK; } static int dust2_process_arate(CSOUND *csound, DUST *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t n, nsmps = CS_KSMPS; MYFLT *out, density, thresh, scale; out = p->out; density = *p->kdensity; if (density != p->density0) { thresh = p->thresh = density * csound->onedsr; scale = p->scale = (thresh > FL(0.0) ? FL(2.0) / thresh : FL(0.0)); p->density0 = density; } else { thresh = p->thresh; scale = p->scale; } memset(out, '\0', offset*sizeof(MYFLT)); for (n=offset; nrand = csoundRand31(&p->rand); r = (MYFLT)p->rand * dv2_31; out[n] = *p->kamp * (r < thresh ? r*scale - FL(1.0) : FL(0.0)); } return OK; } /* gausstrig opcode based on Bhob Rainey's GaussTrig ugen */ static int gausstrig_init(CSOUND* csound, GAUSSTRIG *p) { p->rand = csoundRand31(&csound->randSeed1); if (*p->ifrst1 > FL(0.0)) { /* values less than FL(0.0) could be used in later versions as an offset in samples */ int nextsamps; MYFLT nextcount, frq, dev, r1, r2; p->frq0 = *p->kfrq; frq = (*p->kfrq > FL(0.001) ? *p->kfrq : FL(0.001)); dev = *p->kdev; nextsamps = (int)(csound->GetSr(csound) / frq); p->rand = csoundRand31(&p->rand); r1 = (MYFLT)p->rand * dv2_31; p->rand = csoundRand31(&p->rand); r2 = (MYFLT)p->rand * dv2_31; nextcount = SQRT(FL(-2.0) * LOG(r1)) * SIN(r2 * TWOPI_F); if (nextcount < FL(-1.0)) { MYFLT diff = FL(-1.0) - nextcount; nextcount = (FL(1.0) < FL(-1.0) + diff ? FL(1.0) : FL(-1.0) + diff); } else if (nextcount > FL(1.0)) { MYFLT diff = nextcount - FL(1.0); nextcount = (FL(-1.0) > FL(1.0) - diff ? FL(-1.0) : FL(1.0) - diff); } p->count = (int)(nextsamps + nextcount * dev * nextsamps); } else { /* GaussTrig UGen behavior */ p->count = 0; } /* * imode > 0 means better frequency modulation. If the frequency * changes, the delay before the next impulse is calculed again. * With the default imode value we have the classic behavior of * the GaussTrig ugen, where the freq modulation is bypassed * during the delay time that precedes the next impulse. */ p->mmode = (*p->imode <= FL(0.0) ? 0 : 1); return OK; } /* a separate k-time init for proper work of gausstrig */ static int gausstrig_initk(CSOUND* csound, GAUSSTRIG *p) { p->rand = csoundRand31(&csound->randSeed1); if (*p->ifrst1 > FL(0.0)) { /* values less than FL(0.0) could be used in later versions as an offset in samples */ int nextsamps; MYFLT nextcount, frq, dev, r1, r2; p->frq0 = *p->kfrq; frq = (*p->kfrq > FL(0.001) ? *p->kfrq : FL(0.001)); dev = *p->kdev; /* this very line of k-time fix. Changed GetSt to GetKr */ nextsamps = (int)(csound->GetKr(csound) / frq); p->rand = csoundRand31(&p->rand); r1 = (MYFLT)p->rand * dv2_31; p->rand = csoundRand31(&p->rand); r2 = (MYFLT)p->rand * dv2_31; nextcount = SQRT(FL(-2.0) * LOG(r1)) * SIN(r2 * TWOPI_F); if (nextcount < FL(-1.0)) { MYFLT diff = FL(-1.0) - nextcount; nextcount = (FL(1.0) < FL(-1.0) + diff ? FL(1.0) : FL(-1.0) + diff); } else if (nextcount > FL(1.0)) { MYFLT diff = nextcount - FL(1.0); nextcount = (FL(-1.0) > FL(1.0) - diff ? FL(-1.0) : FL(1.0) - diff); } p->count = (int)(nextsamps + nextcount * dev * nextsamps); } else { /* GaussTrig UGen behavior */ p->count = 0; } p->mmode = (*p->imode <= FL(0.0) ? 0 : 1); return OK; } static int gausstrig_process_krate(CSOUND* csound, GAUSSTRIG *p) { if (p->count <= 0) { int nextsamps; MYFLT nextcount, frq, dev, r1, r2; p->frq0 = *p->kfrq; frq = (*p->kfrq > FL(0.001) ? *p->kfrq : FL(0.001)); dev = *p->kdev; /* this very line of k-time fix. Changed GetSt to GetKr */ nextsamps = (int)(csound->GetKr(csound) / frq); p->rand = csoundRand31(&p->rand); r1 = (MYFLT)p->rand * dv2_31; p->rand = csoundRand31(&p->rand); r2 = (MYFLT)p->rand * dv2_31; nextcount = SQRT(FL(-2.0) * LOG(r1)) * SIN(r2 * TWOPI_F); if (nextcount < FL(-1.0)) { MYFLT diff = FL(-1.0) - nextcount; nextcount = (FL(1.0) < FL(-1.0) + diff ? FL(1.0) : FL(-1.0) + diff); } else if (nextcount > FL(1.0)) { MYFLT diff = nextcount - FL(1.0); nextcount = (FL(-1.0) > FL(1.0) - diff ? FL(-1.0) : FL(1.0) - diff); } p->count = (int)(nextsamps + nextcount * dev * nextsamps); *p->out = *p->kamp; } else { if (p->mmode && *p->kfrq != p->frq0) p->count = 0; *p->out = FL(0.0); } p->count--; return OK; } static int gausstrig_process_arate(CSOUND* csound, GAUSSTRIG *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t n, nsmps = CS_KSMPS; MYFLT *out = p->out; memset(out, '\0', offset*sizeof(MYFLT)); for (n=offset; ncount <= 0) { int nextsamps; MYFLT nextcount, frq, dev, r1, r2; p->frq0 = *p->kfrq; frq = (*p->kfrq > FL(0.001) ? *p->kfrq : FL(0.001)); dev = *p->kdev; nextsamps = (int)(csound->GetSr(csound) / frq); p->rand = csoundRand31(&p->rand); r1 = (MYFLT)p->rand * dv2_31; p->rand = csoundRand31(&p->rand); r2 = (MYFLT)p->rand * dv2_31; nextcount = SQRT(FL(-2.0) * LOG(r1)) * SIN(r2 * TWOPI_F); if (nextcount < FL(-1.0)) { MYFLT diff = FL(-1.0) - nextcount; nextcount = (FL(1.0) < FL(-1.0) + diff ? FL(1.0) : FL(-1.0) + diff); } else if (nextcount > FL(1.0)) { MYFLT diff = nextcount - FL(1.0); nextcount = (FL(-1.0) > FL(1.0) - diff ? FL(-1.0) : FL(1.0) - diff); } p->count = (int)(nextsamps + nextcount * dev * nextsamps); out[n] = *p->kamp; } else { if (p->mmode && *p->kfrq != p->frq0) p->count = 0; out[n] = FL(0.0); } p->count--; } return OK; } static OENTRY scnoise_localops[] = { { "dust.k", sizeof(DUST), 0,3, "k", "kk", (SUBR)dust_init, (SUBR)dust_process_krate, NULL }, { "dust.k", sizeof(DUST), 0,3, "k", "kk", (SUBR)dust_init, (SUBR)dust_process_krate, NULL }, { "dust.a", sizeof(DUST), 0,5, "a", "kk", (SUBR)dust_init, NULL, (SUBR)dust_process_arate }, { "dust2.k", sizeof(DUST), 0,3, "k", "kk", (SUBR)dust_init, (SUBR)dust2_process_krate, NULL }, { "dust2.a", sizeof(DUST), 0,5, "a", "kk", (SUBR)dust_init, NULL, (SUBR)dust2_process_arate }, { "gausstrig.k", sizeof(GAUSSTRIG), 0,3, "k", "kkkoo", (SUBR)gausstrig_initk, (SUBR)gausstrig_process_krate, NULL }, { "gausstrig.a", sizeof(GAUSSTRIG), 0,5, "a", "kkkoo", (SUBR)gausstrig_init, NULL, (SUBR)gausstrig_process_arate } }; LINKAGE_BUILTIN(scnoise_localops) csound-6.10.0/Opcodes/ugakbari.c000066400000000000000000000052571321653344700164370ustar00rootroot00000000000000/* ugakbari.c: Copyright (C) 2006 by David Akbari This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "interlocks.h" #include #define LOGCURVE(x,y) ((LOG(x * (y-FL(1.0))+FL(1.0)))/(LOG(y))) #define EXPCURVE(x,y) ((EXP(x * LOG(y))-FL(1.0))/(y-FL(1.0))) #define GAINSLIDER(x) (FL(0.000145) * EXP(x * FL(0.06907))) typedef struct _scale { OPDS h; MYFLT *koutval; MYFLT *kinval, *kmax, *kmin; } scale; typedef struct _expcurve { OPDS h; MYFLT *kout; MYFLT *kin, *ksteepness; } expcurve; typedef struct _logcurve { OPDS h; MYFLT *kout; MYFLT *kin, *ksteepness; } logcurve; typedef struct _gainslider { OPDS h; MYFLT *koutsig; MYFLT *kindex; } gainslider; /* scale opcode */ static int scale_process(CSOUND *csound, scale *p) { if (*p->kmin != *p->kmax) { *p->koutval = (*p->kinval * (*p->kmax - *p->kmin) + *p->kmin); } return OK; } /* expcurve opcode */ static int expcurve_perf(CSOUND *csound, expcurve *p) { MYFLT ki = *p->kin; MYFLT ks = *p->ksteepness; *p->kout = EXPCURVE(ki, ks); return OK; } /* logcurve opcode */ static int logcurve_perf(CSOUND *csound, logcurve *p) { MYFLT ki = *p->kin; MYFLT ks = *p->ksteepness; *p->kout = LOGCURVE(ki, ks); return OK; } /* gainslider opcode */ static int gainslider_perf(CSOUND *csound, gainslider *p) { if (*p->kindex <= FL(0.0)) { *p->koutsig = FL(0.0); } else { *p->koutsig = GAINSLIDER(*p->kindex); } return OK; } /* opcode library entries */ static OENTRY ugakbari_localops[] = { { "scale", sizeof(scale), 0, 2, "k", "kkk", NULL, (SUBR)scale_process, NULL }, { "expcurve", sizeof(expcurve), 0, 2, "k", "kk", NULL, (SUBR)expcurve_perf, NULL }, { "logcurve", sizeof(logcurve), 0, 2, "k", "kk", NULL, (SUBR)logcurve_perf, NULL }, { "gainslider", sizeof(gainslider), 0, 2, "k", "k", NULL, (SUBR)gainslider_perf, NULL } }; LINKAGE_BUILTIN(ugakbari_localops) csound-6.10.0/Opcodes/ugens7.c000066400000000000000000000515571321653344700160660ustar00rootroot00000000000000/* ugens7.c: Copyright (C) 1995 J. Michael Clarke, based on ideas from CHANT (IRCAM), Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "stdopcod.h" /* UGENS7.C */ #include "ugens7.h" #include /* loosely based on code of Michael Clarke, University of Huddersfield */ static int newpulse(CSOUND *, FOFS *, OVRLAP *, MYFLT *, MYFLT *, MYFLT *); static int fofset0(CSOUND *csound, FOFS *p, int flag) { int skip = (*p->iskip != FL(0.0) && p->auxch.auxp != 0); if (LIKELY((p->ftp1 = csound->FTFind(csound, p->ifna)) != NULL && (p->ftp2 = csound->FTFind(csound, p->ifnb)) != NULL)) { OVRLAP *ovp, *nxtovp; int32 olaps; p->durtogo = (int32)(*p->itotdur * CS_ESR); if (!skip) { /* legato: skip all memory management */ if (*p->iphs == FL(0.0)) /* if fundphs zero, */ p->fundphs = MAXLEN; /* trigger new FOF */ else p->fundphs = (int32)(*p->iphs * FMAXLEN) & PHMASK; if (UNLIKELY((olaps = (int32)*p->iolaps) <= 0)) { return csound->InitError(csound, Str("illegal value for iolaps")); } if (*p->iphs >= FL(0.0)) csound->AuxAlloc(csound, (size_t)olaps * sizeof(OVRLAP), &p->auxch); ovp = &p->basovrlap; nxtovp = (OVRLAP *) p->auxch.auxp; do { ovp->nxtact = NULL; ovp->nxtfree = nxtovp; /* link the ovlap spaces */ ovp = nxtovp++; } while (--olaps); ovp->nxtact = NULL; ovp->nxtfree = NULL; p->fofcount = -1; p->prvband = FL(0.0); p->expamp = FL(1.0); p->prvsmps = (int32)0; p->preamp = FL(1.0); } /* end of legato code */ p->ampcod = IS_ASIG_ARG(p->xamp) ? 1 : 0; p->fundcod = IS_ASIG_ARG(p->xfund) ? 1 : 0; p->formcod = IS_ASIG_ARG(p->xform) ? 1 : 0; p->xincod = p->ampcod || p->fundcod || p->formcod; if (flag) p->fmtmod = (*p->ifmode == FL(0.0)) ? 0 : 1; } else return NOTOK; p->foftype = flag; return OK; } static int fofset(CSOUND *csound, FOFS *p) { return fofset0(csound, p, 1); } static int fofset2(CSOUND *csound, FOFS *p) { return fofset0(csound, p, 0); } static int fof(CSOUND *csound, FOFS *p) { OVRLAP *ovp; FUNC *ftp1, *ftp2; MYFLT *ar, *amp, *fund, *form; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 fund_inc, form_inc; MYFLT v1, fract ,*ftab; if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; /* RWD fix */ ar = p->ar; amp = p->xamp; fund = p->xfund; form = p->xform; ftp1 = p->ftp1; ftp2 = p->ftp2; fund_inc = (int32)(*fund * csound->sicvt); if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } form_inc = (int32)(*form * csound->sicvt); for (n=offset; nfundphs & MAXLEN) { /* if phs has wrapped */ p->fundphs &= PHMASK; if ((ovp = p->basovrlap.nxtfree) == NULL) goto err2; if (newpulse(csound, p, ovp, amp, fund, form)) { /* init new fof */ ovp->nxtact = p->basovrlap.nxtact; /* & link into */ p->basovrlap.nxtact = ovp; /* actlist */ p->basovrlap.nxtfree = ovp->nxtfree; } } ar[n] = FL(0.0); ovp = &p->basovrlap; while (ovp->nxtact != NULL) { /* perform cur actlist: */ MYFLT result; OVRLAP *prvact = ovp; ovp = ovp->nxtact; /* formant waveform */ fract = PFRAC1(ovp->formphs); /* from JMC Fog*/ ftab = ftp1->ftable + (ovp->formphs >> ftp1->lobits);/*JMC Fog*/ v1 = *ftab++; /*JMC Fog*/ result = v1 + (*ftab - v1) * fract; /*JMC Fog*/ /* result = *(ftp1->ftable + (ovp->formphs >> ftp1->lobits) ); */ if (p->foftype) { if (p->fmtmod) ovp->formphs += form_inc; /* inc phs on mode */ else ovp->formphs += ovp->forminc; } else { #define kgliss ifmode /* MYFLT ovp->glissbas = kgliss / grain length. ovp->sampct is incremented each sample. We add glissbas * sampct to the pitch of grain at each a-rate pass (ovp->formphs is the index into ifna; ovp->forminc is the stepping factor that decides pitch) */ ovp->formphs += (int32)(ovp->forminc + ovp->glissbas * ovp->sampct++); } ovp->formphs &= PHMASK; if (ovp->risphs < MAXLEN) { /* formant ris envlp */ result *= *(ftp2->ftable + (ovp->risphs >> ftp2->lobits) ); ovp->risphs += ovp->risinc; } if (ovp->timrem <= ovp->dectim) { /* formant dec envlp */ result *= *(ftp2->ftable + (ovp->decphs >> ftp2->lobits) ); if ((ovp->decphs -= ovp->decinc) < 0) ovp->decphs = 0; } ar[n] += (result * ovp->curamp); /* add wavfrm to out */ if (--ovp->timrem) /* if fof not expird */ ovp->curamp *= ovp->expamp; /* apply bw exp dec */ else { prvact->nxtact = ovp->nxtact; /* else rm frm activ */ ovp->nxtfree = p->basovrlap.nxtfree; /* & ret spc to free */ p->basovrlap.nxtfree = ovp; ovp = prvact; } } p->fundphs += fund_inc; if (p->xincod) { if (p->ampcod) amp++; if (p->fundcod) fund_inc = (int32)(*++fund * csound->sicvt); if (p->formcod) form_inc = (int32)(*++form * csound->sicvt); } p->durtogo--; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("fof: not initialised")); err2: return csound->PerfError(csound, p->h.insdshead, Str("FOF needs more overlaps")); } static int newpulse(CSOUND *csound, FOFS *p, OVRLAP *ovp, MYFLT *amp, MYFLT *fund, MYFLT *form) { MYFLT octamp = *amp, oct; int32 rismps, newexp = 0; if ((ovp->timrem = (int32)(*p->kdur * CS_ESR)) > p->durtogo && (*p->iskip==FL(0.0))) /* ringtime */ return(0); if ((oct = *p->koct) > FL(0.0)) { /* octaviation */ int32 ioct = (int32)oct, bitpat = ~(-1L << ioct); if (bitpat & ++p->fofcount) return(0); if ((bitpat += 1) & p->fofcount) octamp *= (FL(1.0) + ioct - oct); } if (*fund == FL(0.0)) /* formant phs */ ovp->formphs = 0; else ovp->formphs = (int32)(p->fundphs * *form / *fund) & PHMASK; ovp->forminc = (int32)(*form * csound->sicvt); if (*p->kband != p->prvband) { /* bw: exp dec */ p->prvband = *p->kband; p->expamp = EXP(*p->kband * csound->mpidsr); newexp = 1; } /* Init grain rise ftable phase. Negative kform values make the kris (ifnb) initial index go negative and crash csound. So insert another if-test with compensating code. */ if (*p->kris >= csound->onedsr && *form != FL(0.0)) { /* init fnb ris */ if (*form < FL(0.0) && ovp->formphs != 0) ovp->risphs = (int32)((MAXLEN - ovp->formphs) / -*form / *p->kris); else ovp->risphs = (int32)(ovp->formphs / *form / *p->kris); ovp->risinc = (int32)(csound->sicvt / *p->kris); rismps = MAXLEN / ovp->risinc; } else { ovp->risphs = MAXLEN; rismps = 0; } if (newexp || rismps != p->prvsmps) { /* if new params */ if ((p->prvsmps = rismps)) /* redo preamp */ p->preamp = csound->intpow(p->expamp, -rismps); else p->preamp = FL(1.0); } ovp->curamp = octamp * p->preamp; /* set startamp */ ovp->expamp = p->expamp; if ((ovp->dectim = (int32)(*p->kdec * CS_ESR)) > 0) /* fnb dec */ ovp->decinc = (int32)(csound->sicvt / *p->kdec); ovp->decphs = PHMASK; if (!p->foftype) { /* Make fof take k-rate phase increment: Add current iphs to initial form phase */ ovp->formphs += (int32)(*p->iphs * FMAXLEN); /* krate phs */ ovp->formphs &= PHMASK; /* Set up grain gliss increment: ovp->glissbas will be added to ovp->forminc at each pass in fof2. Thus glissbas must be equal to kgliss / grain playing time. Also make it harmonic, so integer kgliss can represent octaves (ie pow() call). */ ovp->glissbas = ovp->forminc * (MYFLT)pow(2.0, (double)*p->kgliss); /* glissbas should be diff of start & end pitch*/ ovp->glissbas -= ovp->forminc; ovp->glissbas /= ovp->timrem; ovp->sampct = 0; /* Must be reset in case ovp was used before */ } return(1); } #if 0 static int hrngflg=0; #endif static int harmset(CSOUND *csound, HARMON *p) { MYFLT minfrq = *p->ilowest; if (UNLIKELY(minfrq < FL(64.0))) { return csound->InitError(csound, Str("Minimum frequency too low")); } if (p->auxch.auxp == NULL || minfrq < p->minfrq) { int32 nbufs = (int32)(CS_EKR * FL(3.0) / minfrq) + 1; int32 nbufsmps = nbufs * CS_KSMPS; int32 maxprd = (int32)(CS_ESR / minfrq); int32 totalsiz = nbufsmps * 5 + maxprd; /* Surely 5! not 4 */ /* printf("init: nbufs = %d; nbufsmps = %d; maxprd = %d; totalsiz = %d\n", */ /* nbufs, nbufsmps, maxprd, totalsiz); */ csound->AuxAlloc(csound, (size_t)totalsiz * sizeof(MYFLT), &p->auxch); p->bufp = (MYFLT *) p->auxch.auxp; p->midp = p->bufp + nbufsmps; /* each >= maxprd * 3 */ p->bufq = p->midp + nbufsmps; p->midq = p->bufq + nbufsmps; p->autobuf = p->midq + nbufsmps; /* size of maxprd */ p->nbufsmps = nbufsmps; p->n2bufsmps = nbufsmps * 2; p->lomaxdist = maxprd; p->minfrq = minfrq; } if ((p->autoktim = (int)/*MYFLT2LONG*/(*p->iptrkprd * CS_EKR)) < 1) p->autoktim = 1; p->autokcnt = 1; /* init for immediate autocorr attempt */ printf("ekr = %f iptrk = %f, autocnt = %d; autotim = %d\n", CS_EKR, *p->iptrkprd, p->autokcnt, p->autoktim); p->lsicvt = FL(65536.0) * csound->onedsr; p->cpsmode = ((*p->icpsmode != FL(0.0))); p->inp1 = p->bufp; p->inp2 = p->midp; p->inq1 = p->bufq; p->inq2 = p->midq; p->puls1 = NULL; p->puls2 = NULL; p->puls3 = NULL; p->prvest = FL(0.0); p->prvq = FL(0.0); p->phase1 = 0; p->phase2 = 0; #if 0 hrngflg = 0; p->period = -1; #endif return OK; } #if 0 static int cycle = 0; #endif static int harmon(CSOUND *csound, HARMON *p) { MYFLT *src1, *src2, *src3, *inp1, *inp2, *outp; MYFLT c1, c2, qval, *inq1, *inq2; MYFLT sum, minval, *minqp = NULL, *minq1, *minq2, *endp; MYFLT *pulstrt, lin1, lin2, lin3; int32 cnt1, cnt2, cnt3; int32 nn, phase1, phase2, phsinc1, phsinc2, period; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; outp = p->ar; #if 0 if (early || offset) printf("early=%d, offet=%d\n", early, offset); #endif if (UNLIKELY(offset)) memset(outp, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&outp[nsmps], '\0', early*sizeof(MYFLT)); } inp1 = p->inp1; inp2 = p->inp2; inq1 = p->inq1; inq2 = p->inq2; qval = p->prvq; if (*p->kest != p->prvest && *p->kest != FL(0.0)) { /* if new pitch estimate */ MYFLT estperiod = CS_ESR / *p->kest; double b = 2.0 - cos((double)(*p->kest * csound->tpidsr)); p->c2 = (MYFLT)(b - sqrt(b*b - 1.0)); /* recalc lopass coefs */ p->c1 = FL(1.0) - p->c2; p->prvest = *p->kest; p->estprd = estperiod; p->prvar = FL(0.0); } if (*p->kvar != p->prvar) { MYFLT oneplusvar = FL(1.0) + *p->kvar; /* prd window is prd +/- var int */ p->mindist = (int32)(p->estprd/oneplusvar); /* if (p->mindist==0) p->mindist=1; */ p->maxdist = (int32)(p->estprd*oneplusvar); if (p->maxdist > p->lomaxdist) p->maxdist = p->lomaxdist; p->max2dist = p->maxdist * 2; p->prvar = *p->kvar; } c1 = p->c1; c2 = p->c2; //printf("cycle %d\n", ++cycle); for (src1 = p->asig, n = offset; n FL(0.0)) qval = c1 * src1[n] + c2 * qval; /* & its half-wave rect */ else qval = c2 * qval; *inq1++ = *inq2++ = qval; } if (!(--p->autokcnt)) { /* if time for new autocorr */ MYFLT *mid1, *mid2, *src4; MYFLT *autop, *maxp; MYFLT dsum, dinv, win, windec, maxval; int32 dist; //printf("AUTOCORRELATE min/max = %d,%d\n",p->mindist, p->maxdist); p->autokcnt = p->autoktim; mid2 = inp2 - p->max2dist; mid1 = mid2 - 1; autop = p->autobuf; for (dist = p->mindist; dist <= p->maxdist; dist++) { dsum = FL(0.0); dinv = FL(1.0) / dist; src1 = mid1; src3 = mid1 + dist; src2 = mid2; src4 = mid2 + dist; for (win = FL(1.0), windec = dinv, nn = dist; nn--; ) { dsum += win * (*src1 * *src3 + *src2 * *src4); //printf("dsum = %f from %f %f %f %f\n", dsum, *src1, *src2, *src3, *src4); src1--; src2++; src3--; src4++; win -= windec; } *autop++ = dsum * dinv; } maxval = FL(0.0); maxp = autop = p->autobuf; endp = autop + p->maxdist - p->mindist; while (autop < endp) { //printf("newval, maxval = %f, %f\n", *autop, maxval); if (*autop > maxval) { /* max autocorr gives new period */ maxval = *autop; maxp = autop; #if 0 csound->Message(csound, "new maxval %f at %p\n", maxval, (long)maxp); #endif } autop++; } //printf("**** maxval = %f ****\n", maxval); period = p->mindist + maxp - p->autobuf; if (period != p->period) { #if 0 csound->Message(csound, "New period %d %d\n", period, p->period); #endif p->period = period; if (!p->cpsmode) p->lsicvt = FL(65536.0) / period; p->pnt1 = (int32)((MYFLT)period * FL(0.2)); p->pnt2 = (int32)((MYFLT)period * FL(0.8)); p->pnt3 = period; p->inc1 = FL(1.0) / p->pnt1; p->inc2 = FL(1.0) / (period - p->pnt2); } } else period = p->period; minval = (MYFLT)HUGE_VAL; /* Suitably large ! */ minq2 = inq2 - period; /* srch the qbuf for minima */ minq1 = minq2 - period; /* which are 1 period apart */ endp = inq2; /* move srch over 1 period */ while (minq2 < endp) { if ((sum = *minq1 + *minq2) < minval) { minval = sum; minqp = minq1; } minq1++; minq2++; } src1 = minqp - p->n2bufsmps; /* get src equiv of 1st min */ if (period==0) { csound->Warning(csound, Str("Period zero\n")); outp = p->ar; memset(outp, 0, sizeof(MYFLT)*CS_KSMPS); return OK; } while (src1 + CS_KSMPS > inp2) /* if not enough smps presnt */ src1 -= period; /* back up 1 prd */ pulstrt = src1; /* curr available pulse beg */ src1 = p->puls1; /* insert pulses into output */ src2 = p->puls2; src3 = p->puls3; lin1 = p->lin1; lin2 = p->lin2; lin3 = p->lin3; cnt1 = p->cnt1; cnt2 = p->cnt2; cnt3 = p->cnt3; phase1 = p->phase1; phase2 = p->phase2; phsinc1 = (int32)(*p->kfrq1 * p->lsicvt); phsinc2 = (int32)(*p->kfrq2 * p->lsicvt); for (n=offset; npnt11) { sum = *src1++ * lin1; lin1 += p->inc11; } else if (cnt1 <= p->pnt12) sum = *src1++; else if (cnt1 <= p->pnt13) { sum = *src1++ * lin1; lin1 -= p->inc12; } else { sum = FL(0.0); src1 = NULL; } } else sum = FL(0.0); if (src2 != NULL) { if (++cnt2 < p->pnt21) { sum += *src2++ * lin2; lin2 += p->inc21; } else if (cnt2 <= p->pnt22) sum += *src2++; else if (cnt2 <= p->pnt23) { sum += *src2++ * lin2; lin2 -= p->inc22; } else src2 = NULL; } if (src3 != NULL) { if (++cnt3 < p->pnt31) { sum += *src3++ * lin3; lin3 += p->inc31; } else if (cnt3 <= p->pnt32) sum += *src3++; else if (cnt3 <= p->pnt33) { sum += *src3++ * lin3; lin3 -= p->inc32; } else src3 = NULL; } if ((phase1 += phsinc1) & (~0xFFFFL)) { /* 64bit safe! */ phase1 &= 0x0000FFFFL; if (src1 == NULL) { src1 = pulstrt; cnt1 = 0; lin1 = p->inc1; p->inc11 = p->inc1; p->inc12 = p->inc2; p->pnt11 = p->pnt1; p->pnt12 = p->pnt2; p->pnt13 = p->pnt3; } else if (src2 == NULL) { src2 = pulstrt; cnt2 = 0; lin2 = p->inc1; p->inc21 = p->inc1; p->inc22 = p->inc2; p->pnt21 = p->pnt1; p->pnt22 = p->pnt2; p->pnt23 = p->pnt3; } else if (src3 == NULL) { src3 = pulstrt; cnt3 = 0; lin3 = p->inc1; p->inc31 = p->inc1; p->inc32 = p->inc2; p->pnt31 = p->pnt1; p->pnt32 = p->pnt2; p->pnt33 = p->pnt3; } #if 0 else if (UNLIKELY(++hrngflg > 200)) { csound->Message(csound, Str("harmon out of range...\n")); hrngflg = 0; } #endif } if ((phase2 += phsinc2) & (~0xFFFFL)) { phase2 &= 0x0000FFFFL; if (src1 == NULL) { src1 = pulstrt; cnt1 = 0; lin1 = p->inc1; p->inc11 = p->inc1; p->inc12 = p->inc2; p->pnt11 = p->pnt1; p->pnt12 = p->pnt2; p->pnt13 = p->pnt3; } else if (src2 == NULL) { src2 = pulstrt; cnt2 = 0; lin2 = p->inc1; p->inc21 = p->inc1; p->inc22 = p->inc2; p->pnt21 = p->pnt1; p->pnt22 = p->pnt2; p->pnt23 = p->pnt3; } else if (src3 == NULL) { src3 = pulstrt; cnt3 = 0; lin3 = p->inc1; p->inc31 = p->inc1; p->inc32 = p->inc2; p->pnt31 = p->pnt1; p->pnt32 = p->pnt2; p->pnt33 = p->pnt3; } #if 0 else if (UNLIKELY(++hrngflg > 200)) { csound->Message(csound, Str("harmon out of range\n")); hrngflg = 0; } #endif } outp[n] = sum; } if (inp1 >= p->midp) { p->inp1 = p->bufp; p->inp2 = p->midp; p->inq1 = p->bufq; p->inq2 = p->midq; if (src1 != NULL) src1 -= p->nbufsmps; if (src2 != NULL) src2 -= p->nbufsmps; if (src3 != NULL) src3 -= p->nbufsmps; } else { p->inp1 = inp1; p->inp2 = inp2; p->inq1 = inq1; p->inq2 = inq2; } p->puls1 = src1; p->puls2 = src2; p->puls3 = src3; p->lin1 = lin1; p->lin2 = lin2; p->lin3 = lin3; p->cnt1 = cnt1; p->cnt2 = cnt2; p->cnt3 = cnt3; p->phase1 = phase1; p->phase2 = phase2; p->prvq = qval; return OK; } #define S(x) sizeof(x) static OENTRY localops[] = { { "fof", S(FOFS), TR, 5, "a","xxxkkkkkiiiiooo",(SUBR)fofset,NULL,(SUBR)fof }, { "fof2", S(FOFS), TR, 5, "a","xxxkkkkkiiiikko",(SUBR)fofset2,NULL,(SUBR)fof }, { "harmon", S(HARMON), 0,5, "a", "akkkkiii",(SUBR)harmset,NULL, (SUBR)harmon } }; int ugens7_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/ugens8.c000066400000000000000000000237131321653344700160600ustar00rootroot00000000000000/* ugens8.c: Copyright (C) 1991, 1998, 2000 Dan Ellis, Richard Karpen, Richard Dobson This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "pvoc.h" /* UGENS8.C */ #include /* RWD 10:9:2000 read pvocex file format */ #include "pvfileio.h" static int pvx_loadfile(CSOUND *, const char *, PVOC *); /********************************************/ /* Originated by Dan Ellis, MIT */ /* Spectral Extraction and Amplitude Gating */ /* added by Richard Karpen, University */ /* of Washington, Seattle 1998 */ /********************************************/ #define WLN 1 /* time window is WLN*2*ksmps long */ #define OPWLEN (2*WLN*CS_KSMPS) /* manifest used for final time wdw */ int pvset_(CSOUND *csound, PVOC *p, int stringname) { unsigned int i; int32 memsize; char pvfilnam[MAXNAME]; int size; /* THESE SHOULD BE SAVED IN PVOC STRUCT */ FUNC *AmpGateFunc = NULL; p->pp = PVOC_GetGlobals(csound); if (stringname==0){ if (csound->ISSTRCOD(*p->ifilno)) strncpy(pvfilnam,get_arg_string(csound, *p->ifilno), MAXNAME-1); else csound->strarg2name(csound, pvfilnam, p->ifilno, "pvoc.",0); } else strncpy(pvfilnam, ((STRINGDAT *)p->ifilno)->data, MAXNAME-1); if (UNLIKELY(pvx_loadfile(csound, pvfilnam, p) != OK)) return NOTOK; memsize = (int32) (PVDATASIZE + PVFFTSIZE * 3 + PVWINLEN); if (*p->imode == 1 || *p->imode == 2) { int32 n = (int32) ((p->frSiz + 2L) * (p->maxFr + 2L)); #ifdef USE_DOUBLE n = (n + 1L) * (int32) sizeof(float) / (int32) sizeof(double); #endif memsize += n; } if (p->auxch.auxp == NULL || memsize != p->mems) { MYFLT *fltp; csound->AuxAlloc(csound, (memsize * sizeof(MYFLT)), &p->auxch); fltp = (MYFLT *) p->auxch.auxp; p->lastPhase = fltp; fltp += PVDATASIZE; /* and insert addresses */ p->fftBuf = fltp; fltp += PVFFTSIZE; p->dsBuf = fltp; fltp += PVFFTSIZE; p->outBuf = fltp; fltp += PVFFTSIZE; p->window = fltp; if (*p->imode == 1 || *p->imode == 2) { fltp += PVWINLEN; p->pvcopy = (float*) ((void*) fltp); } } p->mems = memsize; p->frPktim = ((MYFLT)CS_KSMPS)/((MYFLT) p->frInc); /* factor by which to mult expand phase diffs (ratio of samp spacings) */ p->frPrtim = CS_ESR/((MYFLT) p->frInc); /* factor by which to mulitply 'real' time index to get frame index */ size = pvfrsiz(p); /* size used in def of OPWLEN ? */ /* 2*incr/OPWLEN scales down for win ovlp, windo'd 1ce (but 2ce?) */ /* 1/frSiz is the required scale down before (i)FFT */ p->prFlg = 1; /* true */ p->opBpos = 0; p->lastPex = FL(1.0); /* needs to know last pitchexp to update phase */ /* Set up time window */ memset(p->lastPhase, 0, sizeof(MYFLT)*pvdasiz(p)); /* for (i=0; i < pvdasiz(p); ++i) { /\* or maybe pvdasiz(p) *\/ */ /* p->lastPhase[i] = FL(0.0); */ /* } */ if (UNLIKELY((OPWLEN/2 + 1)>PVWINLEN )) { return csound->InitError(csound, Str("ksmps of %d needs wdw of %d, " "max is %d for pv %s"), CS_KSMPS, (OPWLEN/2 + 1), PVWINLEN, pvfilnam); } if (*p->igatefun > 0) if (UNLIKELY((AmpGateFunc = csound->FTnp2Find(csound, p->igatefun)) == NULL)) return NOTOK; p->AmpGateFunc = AmpGateFunc; if (*p->igatefun > 0) p->PvMaxAmp = PvocMaxAmp(p->frPtr, size, p->maxFr); if (*p->imode == 1 || *p->imode == 2) { SpectralExtract(p->frPtr, p->pvcopy, size, p->maxFr, (int) *p->imode, *p->ifreqlim); p->frPtr = p->pvcopy; } for (i=0; i < OPWLEN / 2 + 1; ++i) /* time window is OPWLEN long */ p->window[i] = (FL(0.5) - FL(0.5) * COS(TWOPI_F*(MYFLT)i/(MYFLT)OPWLEN)); /* NB: HANNING */ memset(p->outBuf, 0, sizeof(MYFLT)*pvfrsiz(p)); /* for (i=0; i< pvfrsiz(p); ++i) */ /* p->outBuf[i] = FL(0.0); */ MakeSinc(p->pp); /* sinctab is same for all instances */ if (p->memenv.auxp == NULL || p->memenv.size < pvdasiz(p)*sizeof(MYFLT)) csound->AuxAlloc(csound, pvdasiz(p) * sizeof(MYFLT), &p->memenv); return OK; } int pvset(CSOUND *csound, PVOC *p){ return pvset_(csound,p,0); } int pvset_S(CSOUND *csound, PVOC *p){ return pvset_(csound,p,1); } int pvoc(CSOUND *csound, PVOC *p) { MYFLT *ar = p->rslt; MYFLT frIndx; MYFLT *buf = p->fftBuf; MYFLT *buf2 = p->dsBuf; int asize = pvdasiz(p); /* new */ int size = pvfrsiz(p); int buf2Size, outlen; int circBufSize = PVFFTSIZE; int specwp = (int)*p->ispecwp; /* spectral warping flag */ MYFLT pex, scaleFac; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; if (UNLIKELY(p->auxch.auxp == NULL)) goto err1; pex = *p->kfmod; outlen = (int) (((MYFLT) size) / pex); /* use outlen to check window/krate/transpose combinations */ if (UNLIKELY(outlen>PVFFTSIZE)) /* Maximum transposition down is one octave */ goto err2; /* ..so we won't run into buf2Size problems */ if (UNLIKELY(outlen<(int)(2*nsmps))) /* minimum post-squeeze windowlength */ goto err3; buf2Size = OPWLEN; /* always window to same length after DS */ if (UNLIKELY((frIndx = *p->ktimpnt * p->frPrtim) < 0)) goto err4; if (frIndx > p->maxFr) { /* not past last one */ frIndx = (MYFLT)p->maxFr; if (UNLIKELY(p->prFlg)) { p->prFlg = 0; /* false */ csound->Warning(csound, Str("PVOC ktimpnt truncated to last frame")); } } FetchIn(p->frPtr, buf, size, frIndx); if (*p->igatefun > 0) PvAmpGate(buf,size, p->AmpGateFunc, p->PvMaxAmp); FrqToPhase(buf, asize, pex * (MYFLT) nsmps, p->asr, FL(0.5) * ((pex / p->lastPex) - FL(1.0))); /* accumulate phase and wrap to range -PI to PI */ RewrapPhase(buf, asize, p->lastPhase); if (specwp > 0){ /* RWD: THIS CAUSED MASSIVE MEMORY ERROR, BUT DOESN'T WORK ANYWAY */ PreWarpSpec(buf, asize, pex, (MYFLT *)p->memenv.auxp); } Polar2Real_PVOC(csound, buf, size); if (pex != FL(1.0)) UDSample(p->pp, buf, (FL(0.5) * ((MYFLT) size - pex * (MYFLT) buf2Size)), buf2, size, buf2Size, pex); else memcpy(buf2, buf + (int) ((size - buf2Size) >> 1), sizeof(MYFLT) * buf2Size); ApplyHalfWin(buf2, p->window, buf2Size); addToCircBuf(buf2, p->outBuf, p->opBpos, nsmps, circBufSize); writeClrFromCircBuf(p->outBuf, ar, p->opBpos, nsmps, circBufSize); p->opBpos += nsmps; if (UNLIKELY(p->opBpos > circBufSize)) p->opBpos -= circBufSize; addToCircBuf(buf2 + nsmps, p->outBuf, p->opBpos, buf2Size - nsmps, circBufSize); p->lastPex = pex; /* needs to know last pitchexp to update phase */ /* scale output */ scaleFac = p->scale; if (pex > FL(1.0)) scaleFac /= pex; if (UNLIKELY(offset)) memset(p->rslt, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->rslt[nsmps], '\0', early*sizeof(MYFLT)); } for (i = offset; i < nsmps; i++) p->rslt[i] *= scaleFac; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("pvoc: not initialised")); err2: return csound->PerfError(csound, p->h.insdshead, Str("PVOC transpose too low")); err3: return csound->PerfError(csound, p->h.insdshead, Str("PVOC transpose too high")); err4: return csound->PerfError(csound, p->h.insdshead, Str("PVOC timpnt < 0")); } /* RWD 8:2001: custom version of ldmemfile(); enables pvfileio funcs to apply byte-reversal if needed. this version applies scaling to match existing pvanal format */ static int pvx_loadfile(CSOUND *csound, const char *fname, PVOC *p) { PVOCEX_MEMFILE pp; if (UNLIKELY(csound->PVOCEX_LoadFile(csound, fname, &pp) != 0)) { return csound->InitError(csound, Str("PVOC cannot load %s"), fname); } /* fft size must be <= PVFRAMSIZE (=8192) for Csound */ if (UNLIKELY(pp.fftsize > PVFRAMSIZE)) { return csound->InitError(csound, Str("pvoc-ex file %s: " "FFT size %d too large for Csound"), fname, (int) pp.fftsize); } /* have to reject m/c files for now, until opcodes upgraded */ if (UNLIKELY(pp.chans > 1)) { return csound->InitError(csound, Str("pvoc-ex file %s is not mono"), fname); } /* ignore the window spec until we can use it! */ p->frSiz = pp.fftsize; p->frPtr = (float*) pp.data; p->baseFr = 0; /* point to first data frame */ /* highest possible frame index */ p->maxFr = pp.nframes - 1; p->frInc = pp.overlap; p->chans = pp.chans; p->asr = pp.srate; /* amplitude scale for PVOC */ /* p->scale = (MYFLT) pp.fftsize * ((MYFLT) pp.fftsize / (MYFLT) pp.winsize); */ p->scale = (MYFLT) pp.fftsize * FL(0.5); p->scale *= csound->GetInverseRealFFTScale(csound, pp.fftsize); return OK; } csound-6.10.0/Opcodes/ugens8.h000066400000000000000000000066221321653344700160650ustar00rootroot00000000000000/* ugens8.h: Copyright (C) 1991, 1998, 2000 Dan Ellis, Richard Karpen, Richard Dobson This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* UGENS8.H */ #ifndef _UGENS8_H_ #define _UGENS8_H_ #define PVFRAMSIZE 8192 /* i.e. max FFT point size */ #define PVFFTSIZE (2*PVFRAMSIZE) /* 2x for real + imag */ #define PVDATASIZE (1+PVFRAMSIZE/2) /* Need 1/2 channels + mid */ #define PVWINLEN (4097) /* time window 1st half */ /* PVDATASIZE reflects the fact that for n point _real_ time data, the fourier * transform will only have n degrees of freedom, although it has 2n values * (n bins x {re,im} or {mag,phase}). This constraint is reflected by the top * n/2-1 bins (bins n/2+1 .. n-1) being complex conjugates of bins 1..n/2-1. * Bins 0 and n/2 do not have conjugate images, but they ARE always real, * so only contribute one degree of freedom each. So the number of degrees of * freedom in the complex FFT is {re,im}*(n/2 - 1) +2 = n , as expected. * Thus we only need to store and process these independent values. However, * for convenience, and because our analysis system records the phase of * bins 0 and n/2 as 0 or pi rather than making the magnitude negative, we * allow these 2 bins to have imaginary components too, so that FFT frames are * stored as Magnitude & phase for bins 0..n/2 = 2*(n/2 + 1) or n+2 values. * These are the n+2 channels interleaved in the PVOC analysis file, and * then stored and processed wherever you see PVDATA/FRDA (frame data) */ #define pvfrsiz(p) (p->frSiz) #define pvffsiz(p) (2* p->frSiz) #define pvdasiz(p) ((uint32_t)(1 + (p->frSiz)/2)) /* as above, based on */ #define pvfdsiz(p) (2 + p->frSiz) /* ACTUAL frameSize in use */ typedef struct { OPDS h; MYFLT *rslt, *ktimpnt, *kfmod, *ifilno, *ispecwp, *imode; MYFLT *ifreqlim, *igatefun; int32 mems; int32 kcnt, baseFr, maxFr, frSiz, prFlg, opBpos; /* RWD 8:2001 for pvocex: need these too */ int32 frInc, chans; MYFLT frPktim, frPrtim, scale, asr, lastPex; MYFLT PvMaxAmp; float *frPtr, *pvcopy; FUNC *AmpGateFunc; AUXCH auxch; MYFLT *lastPhase; /* [PVDATASIZE] Keep track of cum. phase */ MYFLT *fftBuf; /* [PVFFTSIZE] FFT works on Real & Imag */ MYFLT *dsBuf; /* [PVFFTSIZE] Output of downsampling may be 2x */ MYFLT *outBuf; /* [PVFFTSIZE] Output buffer over win length */ MYFLT *window; /* [PVWINLEN] Store 1/2 window */ MYFLT *dsputil_env; AUXCH memenv; PVOC_GLOBALS *pp; } PVOC; #endif csound-6.10.0/Opcodes/ugens9.c000066400000000000000000000574751321653344700160750ustar00rootroot00000000000000/* ugens9.c: Copyright (C) 1996 Greg Sullivan, 2004 ma++ ingalls This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "stdopcod.h" /* UGENS9.C */ #include #include "convolve.h" #include "ugens9.h" #include "soundio.h" static int cvset_(CSOUND *csound, CONVOLVE *p, int stringname) { char cvfilnam[MAXNAME]; MEMFIL *mfp; MYFLT *fltp; CVSTRUCT *cvh; int siz; int32 Hlenpadded = 1, obufsiz, Hlen; uint32_t nchanls; uint32_t nsmps = CS_KSMPS; if (UNLIKELY(csound->oparms->odebug)) csound->Message(csound, CONVOLVE_VERSION_STRING); if (stringname==0){ if (csound->ISSTRCOD(*p->ifilno)) strncpy(cvfilnam,get_arg_string(csound, *p->ifilno), MAXNAME-1); else csound->strarg2name(csound, cvfilnam,p->ifilno, "convolve.",0); } else strncpy(cvfilnam, ((STRINGDAT *)p->ifilno)->data, MAXNAME-1); if ((mfp = p->mfp) == NULL || strcmp(mfp->filename, cvfilnam) != 0) { /* if file not already readin */ if (UNLIKELY((mfp = csound->ldmemfile2withCB(csound, cvfilnam, CSFTYPE_CVANAL,NULL)) == NULL)) { return csound->InitError(csound, Str("CONVOLVE cannot load %s"), cvfilnam); } } cvh = (CVSTRUCT *)mfp->beginp; if (UNLIKELY(cvh->magic != CVMAGIC)) { return csound->InitError(csound, Str("%s not a CONVOLVE file (magic %d)"), cvfilnam, cvh->magic); } nchanls = (cvh->channel == ALLCHNLS ? cvh->src_chnls : 1); if (*p->channel == FL(0.0)) { if (LIKELY(p->OUTOCOUNT == nchanls)) p->nchanls = nchanls; else { return csound->InitError(csound, Str("CONVOLVE: output channels not equal " "to number of channels in source")); } } else { if (*p->channel <= nchanls) { if (UNLIKELY(p->OUTOCOUNT != 1)) { return csound->InitError(csound, Str("CONVOLVE: output channels not equal " "to number of channels in source")); } else p->nchanls = 1; } else { return csound->InitError(csound, Str("CONVOLVE: channel number greater than " "number of channels in source")); } } Hlen = p->Hlen = cvh->Hlen; while (Hlenpadded < 2*Hlen-1) Hlenpadded <<= 1; p->Hlenpadded = Hlenpadded; p->H = (MYFLT *) ((char *)cvh+cvh->headBsize); if ((p->nchanls == 1) && (*p->channel > 0)) p->H += (Hlenpadded + 2) * (int)(*p->channel - 1); if (UNLIKELY(cvh->samplingRate != CS_ESR)) { /* & chk the data */ csound->Warning(csound, Str("%s's srate = %8.0f, orch's srate = %8.0f"), cvfilnam, cvh->samplingRate, CS_ESR); } if (UNLIKELY(cvh->dataFormat != CVMYFLT)) { return csound->InitError(csound, Str("unsupported CONVOLVE data " "format %d in %s"), cvh->dataFormat, cvfilnam); } /* Determine size of circular output buffer */ if (Hlen >= (int32)nsmps) obufsiz = (int32) CEIL((MYFLT) Hlen / nsmps) * nsmps; else obufsiz = (int32) CEIL(CS_KSMPS / (MYFLT) Hlen) * Hlen; siz = ((Hlenpadded + 2) + p->nchanls * ((Hlen - 1) + obufsiz) + (p->nchanls > 1 ? (Hlenpadded + 2) : 0)); if (p->auxch.auxp == NULL || p->auxch.size < siz*sizeof(MYFLT)) { /* if no buffers yet, alloc now */ csound->AuxAlloc(csound, (size_t) siz*sizeof(MYFLT), &p->auxch); fltp = (MYFLT *) p->auxch.auxp; p->fftbuf = fltp; fltp += (Hlenpadded + 2); /* and insert addresses */ p->olap = fltp; fltp += p->nchanls*(Hlen - 1); p->outbuf = fltp; fltp += p->nchanls*obufsiz; p->X = fltp; } else { fltp = (MYFLT *) p->auxch.auxp; memset(fltp, 0, sizeof(MYFLT)*siz); /* for(i=0; i < siz; i++) fltp[i] = FL(0.0); */ } p->obufsiz = obufsiz; p->outcnt = obufsiz; p->incount = 0; p->obufend = p->outbuf + obufsiz - 1; p->outhead = p->outail = p->outbuf; p->fwdsetup = csound->RealFFT2Setup(csound, Hlenpadded, FFT_FWD); p->invsetup = csound->RealFFT2Setup(csound, Hlenpadded, FFT_INV); return OK; } static int cvset(CSOUND *csound, CONVOLVE *p){ return cvset_(csound,p,0); } static int cvset_S(CSOUND *csound, CONVOLVE *p){ return cvset_(csound,p,1); } /* Write from a circular buffer into a linear output buffer without clearing data UPDATES SOURCE & DESTINATION POINTERS TO REFLECT NEW POSITIONS */ static void writeFromCircBuf( MYFLT **sce, MYFLT **dst, /* Circular source and linear destination */ MYFLT *sceStart, MYFLT *sceEnd, /* Address of start & end of source buffer */ int32 numToDo) /* How many points to write (<= circBufSize) */ { MYFLT *srcindex = *sce; MYFLT *dstindex = *dst; int32 breakPoint; /* how many points to add before having to wrap */ breakPoint = sceEnd - srcindex + 1; if (numToDo >= breakPoint) { /* we will do 2 in 1st loop, rest in 2nd. */ numToDo -= breakPoint; for (; breakPoint > 0; --breakPoint) { *dstindex++ = *srcindex++; } srcindex = sceStart; } for (; numToDo > 0; --numToDo) { *dstindex++ = *srcindex++; } *sce = srcindex; *dst = dstindex; return; } static int convolve(CSOUND *csound, CONVOLVE *p) { int nsmpso=CS_KSMPS,nsmpsi=CS_KSMPS,outcnt_sav; int nchm1 = p->nchanls - 1,chn; int32 i,j; MYFLT *ar[4]; MYFLT *ai = p->ain; MYFLT *fftbufind; int32 outcnt = p->outcnt; int32 incount=p->incount; int32 Hlen = p->Hlen; int32 Hlenm1 = Hlen - 1; int32 obufsiz = p->obufsiz; MYFLT *outhead = NULL; MYFLT *outail = p->outail; MYFLT *olap; MYFLT *X; int32 Hlenpadded = p->Hlenpadded; MYFLT scaleFac; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nn,nsmpso_sav; scaleFac = csound->GetInverseRealFFTScale(csound, (int) Hlenpadded); ar[0] = p->ar1; ar[1] = p->ar2; ar[2] = p->ar3; ar[3] = p->ar4; if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; /* First dump as much pre-existing audio in output buffer as possible */ if (outcnt > 0) { if (outcnt <= (int)CS_KSMPS) i = outcnt; else i = CS_KSMPS; nsmpso -= i; outcnt -= i; for (chn = nchm1;chn >= 0;chn--) { outhead = p->outhead + chn*obufsiz; writeFromCircBuf(&outhead,&ar[chn],p->outbuf+chn*obufsiz, p->obufend+chn*obufsiz,i); } p->outhead = outhead; } while (nsmpsi > 0) { /* Read input audio and place into work buffer. */ fftbufind = p->fftbuf + incount; if ((incount + nsmpsi) <= Hlen) i = nsmpsi; else i = Hlen - incount; nsmpsi -= i; incount += i; nsmpso_sav = CS_KSMPS-early; for (nn=0; i>0; nn++, i--) { if (nn(uint32_t)nsmpso_sav) *fftbufind++ = FL(0.0); else *fftbufind++ = scaleFac * ai[nn]; } if (incount == Hlen) { /* We have enough audio for a convolution. */ incount = 0; /* FFT the input (to create X) */ /*csound->Message(csound, "CONVOLVE: ABOUT TO FFT\n"); */ csound->RealFFT2(csound, p->fwdsetup, p->fftbuf); p->fftbuf[Hlenpadded] = p->fftbuf[1]; p->fftbuf[1] = p->fftbuf[Hlenpadded + 1L] = FL(0.0); /* save the result if multi-channel */ if (nchm1) { fftbufind = p->fftbuf; X = p->X; for (i = Hlenpadded + 2;i > 0;i--) *X++ = *fftbufind++; } nsmpso_sav = nsmpso; outcnt_sav = outcnt; for (chn = nchm1;chn >= 0;chn--) { outhead = p->outhead + chn*obufsiz; outail = p->outail + chn*obufsiz; olap = p->olap + chn*Hlenm1; if (chn < nchm1) { fftbufind = p->fftbuf; X = p->X; for (i = Hlenpadded + 2;i> 0;i--) *fftbufind++ = *X++; } /*csound->Message(csound, "CONVOLVE: ABOUT TO MULTIPLY\n"); */ /* Multiply H * X, point for point */ { MYFLT *a, *b, re, im; int i; a = (MYFLT*) p->H + (int) (chn * (Hlenpadded + 2)); b = (MYFLT*) p->fftbuf; for (i = 0; i <= (int) Hlenpadded; i += 2) { re = a[i + 0] * b[i + 0] - a[i + 1] * b[i + 1]; im = a[i + 0] * b[i + 1] + a[i + 1] * b[i + 0]; b[i + 0] = re; b[i + 1] = im; } } /*csound->Message(csound, "CONVOLVE: ABOUT TO IFFT\n"); */ /* Perform inverse FFT on X */ p->fftbuf[1] = p->fftbuf[Hlenpadded]; p->fftbuf[Hlenpadded] = p->fftbuf[Hlenpadded + 1L] = FL(0.0); csound->RealFFT2(csound, p->invsetup, p->fftbuf); /* Take the first Hlen output samples and output them to either the real audio output buffer or the local circular buffer */ nsmpso = nsmpso_sav; outcnt = outcnt_sav; fftbufind = p->fftbuf; if ( (nsmpso > 0)&&(outcnt == 0) ) { /* csound->Message(csound, "Outputting to audio buffer proper\n");*/ /* space left in output buffer, and nothing currently in circular buffer, so write as much as possible to output buffer first */ if (nsmpso >= Hlenm1) { nsmpso -= Hlenm1; for (i=Hlenm1;i > 0;--i) *ar[chn]++ = *fftbufind++ + *olap++; if (nsmpso > 0) { *ar[chn]++ = *fftbufind++; --nsmpso; } } else { for (;nsmpso > 0;--nsmpso) *ar[chn]++ = *fftbufind++ + *olap++; } } /* Any remaining output must go into circular buffer */ /*csound->Message(csound, "Outputting to circ. buffer\n");*/ i = Hlen - (fftbufind - p->fftbuf); outcnt += i; i--; /* do first Hlen -1 samples with overlap */ j = p->obufend+chn*obufsiz - outail + 1; if (i >= j) { i -= j; for (;j > 0;--j) *outail++ = *fftbufind++ + *olap++; outail = p->outbuf+chn*obufsiz; } for (;i > 0;--i) *outail++ = *fftbufind++ + *olap++; /* just need to do sample at Hlen now */ *outail++ = *fftbufind++; if (outail > p->obufend+chn*obufsiz) outail = p->outbuf+chn*obufsiz; /* Pad the rest to zero, and save first remaining (Hlen - 1) to overlap buffer */ olap = p->olap+chn*Hlenm1; for (i = Hlenm1;i > 0;--i) { *olap++ = *fftbufind; *fftbufind++ = FL(0.0); } olap = p->olap+chn*Hlenm1; /* Now pad the rest to zero as well. In theory, this shouldn't be necessary, however it's conceivable that rounding errors may creep in, and these cells won't be exactly zero. So, let's make absolutely sure */ for (i = Hlenpadded - (Hlen+Hlenm1);i > 0;--i) *fftbufind++ = FL(0.0); } /* end main for loop */ p->outhead = outhead; p->outail = outail; } } /* end while */ /* update state in p */ p->incount = incount; p->outcnt = outcnt; p->outhead = outhead; p->outail = outail; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("convolve: not initialised")); } /* partitioned (low latency) overlap-save convolution. we break up the IR into separate blocks, then perform an FFT on each partition. For this reason we ONLY accept soundfiles as input, and do all of the traditional 'cvanal' processing at i-time. it would be nice to eventually have cvanal create a partitioned format, which in turn would allow this opcode to accept .con files. -ma++ april 2004 */ static int pconvset_(CSOUND *csound, PCONVOLVE *p, int stringname) { int channel = (*(p->channel) <= 0 ? ALLCHNLS : (int) *(p->channel)); SNDFILE *infd; SOUNDIN IRfile; MYFLT *inbuf, *fp1,*fp2; int32 i, j, read_in, part; MYFLT *IRblock; MYFLT ainput_dur, scaleFac; MYFLT partitionSize; /* IV - 2005-04-06: fixed bug: was uninitialised */ memset(&IRfile, 0, sizeof(SOUNDIN)); /* open impulse response soundfile [code derived from SAsndgetset()] */ IRfile.skiptime = FL(0.0); if (stringname==0){ if (csound->ISSTRCOD(*p->ifilno)) strncpy(IRfile.sfname,get_arg_string(csound, *p->ifilno), 511); else csound->strarg2name(csound, IRfile.sfname, p->ifilno, "soundin.",0); } else strncpy(IRfile.sfname, ((STRINGDAT *)p->ifilno)->data, 511); IRfile.sr = 0; if (UNLIKELY(channel < 1 || ((channel > 4) && (channel != ALLCHNLS)))) { return csound->InitError(csound, Str("channel request %d illegal"), channel); } IRfile.channel = channel; IRfile.analonly = 1; if (UNLIKELY((infd = csound->sndgetset(csound, &IRfile)) == NULL)) { return csound->InitError(csound, Str("pconvolve: error while impulse file")); } if (UNLIKELY(IRfile.framesrem < 0)) { csound->Warning(csound, Str("undetermined file length, " "will attempt requested duration")); ainput_dur = FL(0.0); /* This is probably wrong -- JPff */ } else { IRfile.getframes = IRfile.framesrem; if (UNLIKELY(IRfile.sr==0)) return csound->InitError(csound, Str("SR zero")); ainput_dur = (MYFLT) IRfile.getframes / IRfile.sr; } csound->Warning(csound, Str("analyzing %ld sample frames (%3.1f secs)\n"), (long) IRfile.getframes, ainput_dur); p->nchanls = (channel != ALLCHNLS ? 1 : IRfile.nchanls); if (UNLIKELY(p->nchanls != (int)p->OUTOCOUNT)) { return csound->InitError(csound, Str("PCONVOLVE: number of output channels " "not equal to input channels")); } if (UNLIKELY(IRfile.sr != CS_ESR)) { /* ## RWD suggests performing sr conversion here! */ csound->Warning(csound, Str("IR srate != orch's srate")); } /* make sure the partition size is nonzero and a power of 2 */ if (*p->partitionSize <= 0) partitionSize = csound->oparms->outbufsamps / csound->GetNchnls(csound); else partitionSize = *p->partitionSize; p->Hlen = 1; while (p->Hlen < partitionSize) p->Hlen <<= 1; p->Hlenpadded = 2*p->Hlen; /* determine the number of partitions */ p->numPartitions = CEIL((MYFLT)(IRfile.getframes) / (MYFLT)p->Hlen); /* set up FFT tables */ inbuf = (MYFLT *) csound->Malloc(csound, p->Hlen * p->nchanls * sizeof(MYFLT)); csound->AuxAlloc(csound, p->numPartitions * (p->Hlenpadded + 2) * sizeof(MYFLT) * p->nchanls, &p->H); IRblock = (MYFLT *)p->H.auxp; p->fwdsetup = csound->RealFFT2Setup(csound,p->Hlenpadded, FFT_FWD); p->invsetup = csound->RealFFT2Setup(csound,p->Hlenpadded, FFT_INV); /* form each partition and take its FFT */ for (part = 0; part < p->numPartitions; part++) { /* get the block of input samples and normalize -- soundin code handles finding the right channel */ if (UNLIKELY((read_in = csound->getsndin(csound, infd, inbuf, p->Hlen*p->nchanls, &IRfile)) <= 0)) return csound->InitError(csound, Str("PCONVOLVE: less sound than expected!")); /* take FFT of each channel */ scaleFac = csound->dbfs_to_float * csound->GetInverseRealFFTScale(csound, (int) p->Hlenpadded); for (i = 0; i < p->nchanls; i++) { fp1 = inbuf + i; fp2 = IRblock; for (j = 0; j < read_in/p->nchanls; j++) { *fp2++ = *fp1 * scaleFac; fp1 += p->nchanls; } csound->RealFFT2(csound, p->fwdsetup, IRblock); IRblock[p->Hlenpadded] = IRblock[1]; IRblock[1] = IRblock[p->Hlenpadded + 1L] = FL(0.0); IRblock += (p->Hlenpadded + 2); } } csound->Free(csound, inbuf); csound->FileClose(csound, IRfile.fd); /* allocate the buffer saving recent input samples */ csound->AuxAlloc(csound, p->Hlen * sizeof(MYFLT), &p->savedInput); p->inCount = 0; /* allocate the convolution work buffer */ csound->AuxAlloc(csound, (p->Hlenpadded+2) * sizeof(MYFLT), &p->workBuf); p->workWrite = (MYFLT *)p->workBuf.auxp + p->Hlen; /* allocate the buffer holding recent past convolutions */ csound->AuxAlloc(csound, (p->Hlenpadded+2) * p->numPartitions * p->nchanls * sizeof(MYFLT), &p->convBuf); p->curPart = 0; /* allocate circular output sample buffer */ p->outBufSiz = sizeof(MYFLT) * p->nchanls * (p->Hlen >= (int)CS_KSMPS ? p->Hlenpadded : 2*(int)CS_KSMPS); csound->AuxAlloc(csound, p->outBufSiz, &p->output); p->outRead = (MYFLT *)p->output.auxp; /* if ksmps < hlen, we have to pad initial output to prevent a possible empty ksmps pass after a few initial generated buffers. There is probably an equation to figure this out to reduce the delay, but I can't seem to figure it out */ if (p->Hlen > (int)CS_KSMPS) { p->outCount = p->Hlen + CS_KSMPS; p->outWrite = p->outRead + (p->nchanls * p->outCount); } else { p->outCount = 0; p->outWrite = p->outRead; } return OK; } static int pconvset(CSOUND *csound, PCONVOLVE *p){ return pconvset_(csound,p,0); } static int pconvset_S(CSOUND *csound, PCONVOLVE *p){ return pconvset_(csound,p,1); } static int pconvolve(CSOUND *csound, PCONVOLVE *p) { uint32_t nn, nsmps = CS_KSMPS; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = nsmps - p->h.insdshead->ksmps_no_end; MYFLT *ai = p->ain; MYFLT *buf; MYFLT *input = (MYFLT*) p->savedInput.auxp, *workWrite = p->workWrite; MYFLT *a1 = p->ar1, *a2 = p->ar2, *a3 = p->ar3, *a4 = p->ar4; int32 i, j, count = p->inCount; int32 hlenpaddedplus2 = p->Hlenpadded+2; for (nn=0; nnearly? FL(0.0) : ai[nn]); /* We have enough audio for a convolution. */ if (count == p->Hlen) { MYFLT *dest = (MYFLT*) p->convBuf.auxp + p->curPart * (p->Hlenpadded + 2) * p->nchanls; MYFLT *h = (MYFLT*) p->H.auxp; MYFLT *workBuf = (MYFLT*) p->workBuf.auxp; /* FFT the input (to create X) */ *workWrite = FL(0.0); /* zero out nyquist bin from last fft result - maybe is ignored for input(?) but just in case.. */ csound->RealFFT2(csound, p->fwdsetup, workBuf); workBuf[p->Hlenpadded] = workBuf[1]; workBuf[1] = workBuf[p->Hlenpadded + 1L] = FL(0.0); /* for every IR partition convolve and add to previous convolves */ for (i = 0; i < p->numPartitions*p->nchanls; i++) { MYFLT *src = workBuf; int n; for (n = 0; n <= (int) p->Hlenpadded; n += 2) { dest[n + 0] += (h[n + 0] * src[n + 0]) - (h[n + 1] * src[n + 1]); dest[n + 1] += (h[n + 1] * src[n + 0]) + (h[n + 0] * src[n + 1]); } h += n; dest += n; if (UNLIKELY(dest == (MYFLT*)p->convBuf.endp)) dest = (MYFLT*)p->convBuf.auxp; } /* Perform inverse FFT of the ondeck partion block */ buf = (MYFLT*) p->convBuf.auxp + p->curPart * p->nchanls * hlenpaddedplus2; for (i = 0; i < p->nchanls; i++) { MYFLT *bufp; bufp = buf + i * hlenpaddedplus2; bufp[1] = bufp[p->Hlenpadded]; bufp[p->Hlenpadded] = bufp[p->Hlenpadded + 1L] = FL(0.0); csound->RealFFT2(csound, p->invsetup, bufp); } /* We only take only the last Hlen output samples so we first zero out the first half for next time, then we copy the rest to output buffer */ for (j = 0; j < p->nchanls; j++) { MYFLT *outp = p->outWrite + j; for (i = 0; i < p->Hlen; i++) *buf++ = FL(0.0); for (i = 0; i < p->Hlen; i++) { *outp = *buf; *buf++ = FL(0.0); outp += p->nchanls; if (outp >= (MYFLT *)p->output.endp) outp = (MYFLT *)p->output.auxp + j; } buf += 2; } p->outWrite += p->Hlen*p->nchanls; if (p->outWrite >= (MYFLT *)p->output.endp) p->outWrite -= p->outBufSiz/sizeof(MYFLT); p->outCount += p->Hlen; if (++p->curPart == p->numPartitions) /* advance to the next partition */ p->curPart = 0; /* copy the saved input into the work buffer for next time around */ memcpy(p->workBuf.auxp, input, p->Hlen * sizeof(MYFLT)); count = 0; workWrite = (MYFLT *)p->workBuf.auxp + p->Hlen; } } /* end while */ /* copy to output if we have enough samples [we always should except the first Hlen samples] */ if (p->outCount >= (int)CS_KSMPS) { unsigned int n; p->outCount -= CS_KSMPS; for (n=0; n < CS_KSMPS; n++) { switch (p->nchanls) { case 1: *a1++ = *p->outRead++; break; case 2: *a1++ = *p->outRead++; *a2++ = *p->outRead++; break; case 3: *a1++ = *p->outRead++; *a2++ = *p->outRead++; *a3++ = *p->outRead++; break; case 4: *a1++ = *p->outRead++; *a2++ = *p->outRead++; *a3++ = *p->outRead++; *a4++ = *p->outRead++; break; } if (p->outRead == p->output.endp) p->outRead = p->output.auxp; } } /* update struct */ p->inCount = count; p->workWrite = workWrite; return OK; } static OENTRY localops[] = { { "convolve", sizeof(CONVOLVE), 0, 5, "mmmm", "aSo", (SUBR) cvset_S, (SUBR) NULL, (SUBR) convolve }, { "convle", sizeof(CONVOLVE), 0, 5, "mmmm", "aSo", (SUBR) cvset_S, (SUBR) NULL, (SUBR) convolve }, { "pconvolve",sizeof(PCONVOLVE), 0, 5, "mmmm", "aSoo", (SUBR) pconvset_S, (SUBR) NULL, (SUBR) pconvolve }, { "convolve.i", sizeof(CONVOLVE), 0, 5, "mmmm", "aio", (SUBR) cvset, (SUBR) NULL, (SUBR) convolve }, { "convle.i", sizeof(CONVOLVE), 0, 5, "mmmm", "aio", (SUBR) cvset, (SUBR) NULL, (SUBR) convolve }, { "pconvolve.i",sizeof(PCONVOLVE), 0, 5, "mmmm", "aioo", (SUBR) pconvset, (SUBR) NULL, (SUBR) pconvolve } }; int ugens9_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/ugens9.h000066400000000000000000000055531321653344700160700ustar00rootroot00000000000000/* ugens9.h: Copyright (C) 1996 Greg Sullivan This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* UGENS9.H */ typedef struct { OPDS h; MYFLT *ar1,*ar2,*ar3,*ar4,*ain,*ifilno,*channel; MEMFIL *mfp; int32 Hlen, Hlenpadded,incount,outcnt,obufsiz; int nchanls; /* number of channels we are actually processing */ MYFLT *H,*cvlut,*outhead,*outail,*obufend; AUXCH auxch; /* use AUXDS to manage the following buffer spaces */ MYFLT *fftbuf; /* [Hlenpadded + 2] (general FFT working buffer) */ MYFLT *olap; /* [(Hlen - 1) * nchnls] (samples to overlap on next run) */ MYFLT *outbuf; /* (to store output audio if ((Hlen > ksmps) && !(multiple of ksmps)), or ((Hlen < ksmps) && !(submultiple of ksmps)) */ MYFLT *X; /* [Hlenpadded + 2] (holds transform of input audio - only required for multi-channel output) */ void *fwdsetup, *invsetup; /* setup for FFT */ } CONVOLVE; typedef struct { OPDS h; MYFLT *ar1, *ar2, *ar3, *ar4, *ain,*ifilno,*partitionSize,*channel; int32 numPartitions; int32 Hlen, Hlenpadded; int nchanls; /* number of channels we are actually processing */ AUXCH H; /* array of Impulse Responses */ AUXCH savedInput; /* the last Hlen input samps for overlap-save method */ int32 inCount; /* index to write to savedInput */ AUXCH workBuf; /* work buf for current partion convolution */ MYFLT *workWrite; /* current index for writing input samps */ AUXCH convBuf; /* circular buf accumulating partitioned convolutions */ int32 curPart; /* "current" segment in convBuf */ AUXCH output; /* circular buf accumulating output samples */ int32 outBufSiz; /* hlenpadded or 2*ksmps, whichever is greater */ MYFLT *outWrite, *outRead; /* i/o pointers to the output buf */ int32 outCount; /* number of valid samples in the outbuf */ void *fwdsetup, *invsetup; /* setup for FFT */ } PCONVOLVE; csound-6.10.0/Opcodes/ugensa.c000066400000000000000000000222661321653344700161330ustar00rootroot00000000000000/* ugensa.c: Copyright (C) 1997 J. Michael Clarke, based on ideas from CHANT (IRCAM) This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "stdopcod.h" /* UGENSA.C */ #include "ugensa.h" #include "ugens7.h" #include /* FOG generator */ static int newpulse(CSOUND *, FOGS *, OVERLAP *, MYFLT *, MYFLT *, MYFLT *); static int fogset(CSOUND *csound, FOGS *p) { /* legato test, not sure if the last bit (auxch) is correct? */ int skip = (*p->iskip != FL(0.0) && p->auxch.auxp != 0); if (LIKELY((p->ftp1 = csound->FTFind(csound, p->ifna)) != NULL && (p->ftp2 = csound->FTFind(csound, p->ifnb)) != NULL)) { OVERLAP *ovp, *nxtovp; int32 olaps; p->fogcvt = FMAXLEN/(p->ftp1)->flen; /*JMC for FOG*/ p->durtogo = (int32)(*p->itotdur * CS_ESR); if (!skip) { /* legato: skip all memory management */ p->spdphs = 0L; /*JMC for FOG*/ if (*p->iphs == FL(0.0)) /* if fundphs zero, */ p->fundphs = MAXLEN; /* trigger new FOF */ else p->fundphs = (int32)(*p->iphs * FMAXLEN) & PHMASK; if (UNLIKELY((olaps = (int32)*p->iolaps) <= 0)) { return csound->InitError(csound, Str("illegal value for iolaps")); } if (*p->iphs>=FL(0.0)) csound->AuxAlloc(csound, (size_t)olaps * sizeof(OVERLAP), &p->auxch); ovp = &p->basovrlap; nxtovp = (OVERLAP *) p->auxch.auxp; do { ovp->nxtact = NULL; ovp->nxtfree = nxtovp; /* link the ovlap spaces */ ovp = nxtovp++; } while (--olaps); ovp->nxtact = NULL; ovp->nxtfree = NULL; p->fofcount = -1; p->prvband = FL(0.0); p->expamp = FL(1.0); p->prvsmps = 0; p->preamp = FL(1.0); } p->ampcod = IS_ASIG_ARG(p->xamp) ? 1 : 0; p->fundcod = IS_ASIG_ARG(p->xdens) ? 1 : 0; p->formcod = IS_ASIG_ARG(p->xtrans) ? 1 : 0; p->xincod = p->ampcod || p->fundcod || p->formcod; /* p->speedcod = (p->XINCODE & 0x8) ? 1 : 0; */ /*out for phs version of fog*/ p->fmtmod = (*p->itmode == 0.0) ? 0 : 1; } else return NOTOK; return OK; } static int fog(CSOUND *csound, FOGS *p) { OVERLAP *ovp; FUNC *ftp1, *ftp2; MYFLT *ar, *amp, *fund, *ptch, *speed; MYFLT v1, fract ,*ftab, fogcvt = p->fogcvt; /*JMC added for FOG*/ uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 fund_inc, form_inc; /* long speed_inc; */ /*JMC added last--out for phs version*/ ar = p->ar; amp = p->xamp; fund = p->xdens; ptch = p->xtrans; speed = p->xspd; ftp1 = p->ftp1; ftp2 = p->ftp2; fund_inc = (int32)(*fund * csound->sicvt); form_inc = (int32)(*ptch * fogcvt); /*form_inc = *form * csound->sicvt;*/ /* speed_inc = *speed * fogcvt; */ /*JMC for FOG--out for phs version*/ if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset;nfundphs & MAXLEN) { /* if phs has wrapped */ p->fundphs &= PHMASK; if (UNLIKELY((ovp = p->basovrlap.nxtfree) == NULL)) goto err1; if (newpulse(csound, p, ovp, amp, fund, ptch)) { /* init new fof */ ovp->nxtact = p->basovrlap.nxtact; /* & link into */ p->basovrlap.nxtact = ovp; /* actlist */ p->basovrlap.nxtfree = ovp->nxtfree; } } ar[n] = FL(0.0); ovp = &p->basovrlap; while (ovp->nxtact != NULL) { /* perform cur actlist: */ MYFLT result; OVERLAP *prvact = ovp; ovp = ovp->nxtact; /* formant waveform */ fract = PFRAC1(ovp->formphs); /*JMC Fog*/ ftab = ftp1->ftable + (ovp->formphs >> ftp1->lobits);/*JMC Fog*/ v1 = *ftab++; /*JMC Fog*/ result = v1 + (*ftab - v1) * fract; /*JMC Fog*/ /* result = *(ftp1->ftable + (ovp->formphs >> ftp1->lobits) ); FOF version*/ if (p->fmtmod) ovp->formphs += form_inc; /* inc phs on mode */ else ovp->formphs += ovp->forminc; ovp->formphs &= PHMASK; if (ovp->risphs < MAXLEN) { /* formant ris envlp */ result *= *(ftp2->ftable + (ovp->risphs >> ftp2->lobits) ); ovp->risphs += ovp->risinc; } if (ovp->timrem <= ovp->dectim) { /* formant dec envlp */ result *= *(ftp2->ftable + (ovp->decphs >> ftp2->lobits) ); if ((ovp->decphs -= ovp->decinc) < 0) ovp->decphs = 0; } ar[n] += (result * ovp->curamp); /* add wavfrm to out */ if (--ovp->timrem) /* if fof not expird */ ovp->curamp *= ovp->expamp; /* apply bw exp dec */ else { prvact->nxtact = ovp->nxtact; /* else rm frm activ */ ovp->nxtfree = p->basovrlap.nxtfree;/* & ret spc to free */ p->basovrlap.nxtfree = ovp; ovp = prvact; } } p->fundphs += fund_inc; /* p->spdphs += speed_inc; */ /*JMC for FOG*/ p->spdphs = (int32)(speed[n] * FMAXLEN); /*for phs version of FOG*/ p->spdphs &= PHMASK; /*JMC for FOG*/ if (p->xincod) { if (p->ampcod) amp++; if (p->fundcod) fund_inc = (int32)(*++fund * csound->sicvt); if (p->formcod) form_inc = (int32)(*++ptch * fogcvt); /*form_inc = *++form * csound->sicvt;*/ /* if (p->speedcod) speed_inc = *++speed * fogcvt; */ /*JMC for FOG*/ } p->durtogo--; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("FOF needs more overlaps")); } static int newpulse(CSOUND *csound, FOGS *p, OVERLAP *ovp, MYFLT *amp, MYFLT *fund, MYFLT *ptch) { MYFLT octamp = *amp, oct; MYFLT form = *ptch / csound->sicvt, fogcvt = p->fogcvt; int32 rismps, newexp = 0; if ((ovp->timrem = (int32)(*p->kdur * CS_ESR)) > p->durtogo && (*p->iskip==FL(0.0))) /* ringtime */ return(0); if ((oct = *p->koct) > 0.0) { /* octaviation */ int32 ioct = (int32)oct, bitpat = ~(-1L << ioct); if (bitpat & ++p->fofcount) return(0); if ((bitpat += 1) & p->fofcount) octamp *= (FL(1.0) + ioct - oct); } if (*fund == 0.0) /* formant phs */ ovp->formphs = 0; /* else ovp->formphs = (int32)((p->fundphs * form / *fund) + p->spdphs) & PHMASK; */ else ovp->formphs = (int32)(p->fundphs * form / *fund) & PHMASK; ovp->forminc = (int32)(*ptch * fogcvt);/*JMC for FOG*/ /*ovp->forminc = *form * csound->sicvt;*/ if (*p->kband != p->prvband) { /* bw: exp dec */ p->prvband = *p->kband; p->expamp = EXP(*p->kband * csound->mpidsr); newexp = 1; } if (*p->kris >= csound->onedsr && form != 0.0) { /* init fnb ris */ ovp->risphs = (uint32)(ovp->formphs / (fabs(form)) / *p->kris); /* JPff fix */ ovp->risinc = (int32)(csound->sicvt / *p->kris); rismps = MAXLEN / ovp->risinc; } else { ovp->risphs = MAXLEN; rismps = 0; } /* p->spdphs (soundfile ftable index) must be added to ovp->formphs (sound ftable reading rate) AFTER ovp-risphs is calculated */ ovp->formphs = (ovp->formphs + p->spdphs) & PHMASK; if (newexp || rismps != p->prvsmps) { /* if new params */ if ((p->prvsmps = rismps)) /* redo preamp */ p->preamp = csound->intpow(p->expamp, -rismps); else p->preamp = FL(1.0); } ovp->curamp = octamp * p->preamp; /* set startamp */ ovp->expamp = p->expamp; if ((ovp->dectim = (int32)(*p->kdec * CS_ESR)) > 0) /* fnb dec */ ovp->decinc = (int32)(csound->sicvt / *p->kdec); ovp->decphs = PHMASK; return(1); } /* JMC test additional UG */ #define S(x) sizeof(x) static OENTRY localops[] = { { "fog", S(FOGS), TR, 5, "a","xxxakkkkkiiiiooo",(SUBR)fogset,NULL,(SUBR)fog} }; int ugensa_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/ugensa.h000066400000000000000000000035241321653344700161340ustar00rootroot00000000000000/* ugensa.h: Copyright (C) 1997 J. Michael Clarke, based on ideas from CHANT (IRCAM) This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* UGENSM.H */ #define PFRAC1(x) ((MYFLT)((x) & ftp1->lomask) * ftp1->lodiv) typedef struct overlap { struct overlap *nxtact; struct overlap *nxtfree; int32 timrem, dectim, formphs, forminc; uint32 risphs; int32 risinc, decphs, decinc; MYFLT curamp, expamp; } OVERLAP; typedef struct { OPDS h; MYFLT *ar, *xamp, *xdens, *xtrans, *xspd, *koct, *kband, *kris, *kdur, *kdec; MYFLT *iolaps, *ifna, *ifnb, *itotdur, *iphs, *itmode, *iskip; OVERLAP basovrlap; int32 durtogo, fundphs, fofcount, prvsmps, spdphs; /*last added JMC for FOG*/ MYFLT prvband, expamp, preamp, fogcvt; /*last added JMC for FOG*/ int16 xincod, ampcod, fundcod; int16 formcod, fmtmod, speedcod; /*last added JMC for FOG*/ AUXCH auxch; FUNC *ftp1, *ftp2; } FOGS; /*typedef struct { OPDS h; MYFLT *sr, *xamp, *xcps, *ifn, *iphs; int32 lphs; FUNC *ftp; } JMC; */ csound-6.10.0/Opcodes/uggab.c000066400000000000000000002003241321653344700157270ustar00rootroot00000000000000/* uggab.c: Copyright (C) 1998 Gabriel Maldonado, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /********************************************/ /* wrap and mirror UGs by Gabriel Maldonado */ /* and others by same author */ /* Code adapted by JPff 1998 Sep 19 */ /********************************************/ #include "stdopcod.h" #include "uggab.h" #include static int wrap(CSOUND *csound, WRAP *p) { MYFLT *adest= p->xdest; MYFLT *asig = p->xsig; MYFLT xlow, xhigh, xsig; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(offset)) memset(adest, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&adest[nsmps], '\0', early*sizeof(MYFLT)); } if ((xlow=*p->xlow) >= (xhigh=*p->xhigh)) { MYFLT xaverage; xaverage = (xlow + xhigh) * FL(0.5); for (n=offset; n= xlow ) adest[n] = xlow + FMOD(xsig - xlow, FABS(xlow-xhigh)); else adest[n] = xhigh- FMOD(xhigh- xsig, FABS(xlow-xhigh)); } return OK; } static int kwrap(CSOUND *csound, WRAP *p) { MYFLT xsig, xlow, xhigh; if ((xlow=*p->xlow) >= (xhigh=*p->xhigh)) *p->xdest = (xlow + xhigh)*FL(0.5); else { if ((xsig=*p->xsig) >= xlow ) *p->xdest = xlow + FMOD(xsig - xlow, FABS(xlow-xhigh)); else *p->xdest = xhigh- FMOD(xhigh- xsig, FABS(xlow-xhigh)); } return OK; } /*---------------------------------------------------------------------*/ static int kmirror(CSOUND *csound, WRAP *p) { MYFLT xsig, xlow, xhigh; xsig = *p->xsig; xhigh= *p->xhigh; xlow = *p->xlow; if (xlow >= xhigh) *p->xdest = (xlow + xhigh)*FL(0.5); else { while ((xsig > xhigh) || (xsig < xlow)) { if (xsig > xhigh) xsig = xhigh + xhigh - xsig; else xsig = xlow + xlow - xsig; } *p->xdest = xsig; } return OK; } static int mirror(CSOUND *csound, WRAP *p) { MYFLT *adest, *asig; MYFLT xlow, xhigh, xaverage, xsig; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; adest = p->xdest; asig = p->xsig; xlow = *p->xlow; xhigh = *p->xhigh; if (UNLIKELY(offset)) memset(adest, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&adest[nsmps], '\0', early*sizeof(MYFLT)); } if (xlow >= xhigh) { xaverage = (xlow + xhigh)*FL(0.5); for (n=offset;n xhigh) || ( xsig < xlow )) { if (xsig > xhigh) xsig = xhigh + xhigh - xsig; else xsig = xlow + xlow - xsig; } adest[n] = xsig; } return OK; } static int trig_set(CSOUND *csound, TRIG *p) { p->old_sig = FL(0.0); return OK; } static int trig(CSOUND *csound, TRIG *p) { MYFLT sig = *p->ksig; MYFLT threshold = *p->kthreshold; switch ((int) MYFLT2LONG(*p->kmode)) { case 0: /* down-up */ if (p->old_sig <= threshold && sig > threshold) *p->kout = FL(1.0); else *p->kout = FL(0.0); break; case 1: /* up-down */ if (p->old_sig >= threshold && sig < threshold) *p->kout = FL(1.0); else *p->kout = FL(0.0); break; case 2: /* both */ if ((p->old_sig <= threshold && sig > threshold) || (p->old_sig >= threshold && sig < threshold ) ) *p->kout = FL(1.0); else *p->kout = FL(0.0); break; default: return csound->PerfError(csound, p->h.insdshead, Str(" bad imode value")); } p->old_sig = sig; return OK; } /*-------------------------------*/ static int interpol(CSOUND *csound, INTERPOL *p) { MYFLT point_value = (*p->point - *p->imin) / (*p->imax - *p->imin); *p->r = point_value * (*p->val2 - *p->val1) + *p->val1; return OK; } static int nterpol_init(CSOUND *csound, INTERPOL *p) { if (LIKELY(*p->imax != *p->imin)) p->point_factor = FL(1.0)/(*p->imax - *p->imin); else return csound->InitError(csound, Str("Min and max the same")); return OK; } static int knterpol(CSOUND *csound, INTERPOL *p) { MYFLT point_value = (*p->point - *p->imin ) * p->point_factor; *p->r = point_value * (*p->val2 - *p->val1) + *p->val1; return OK; } static int anterpol(CSOUND *csound, INTERPOL *p) { MYFLT point_value = (*p->point - *p->imin ) * p->point_factor; MYFLT *out = p->r, *val1 = p->val1, *val2 = p->val2; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nFTnp2Find(csound, p->ift)) == NULL)) return csound->InitError(csound, Str("table not found in poscil")); p->ftp = ftp; p->tablen = ftp->flen; p->tablenUPsr = p->tablen * csound->onedsr; if (*p->iphs>=FL(0.0)) p->phs = *p->iphs * p->tablen; while (UNLIKELY(p->phs >= p->tablen)) p->phs -= p->tablen; return OK; } static int posckk(CSOUND *csound, POSC *p) { FUNC *ftp = p->ftp; MYFLT *out = p->out, *ft; MYFLT *curr_samp, fract; double phs = p->phs; double si = *p->freq * p->tablenUPsr; /* gab c3 */ uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT amp = *p->amp; if (UNLIKELY(ftp==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("poscil: not initialised")); ft = p->ftp->ftable; if (UNLIKELY(early)) nsmps -= early; for (n=offset; n= p->tablen)) phs -= p->tablen; while (UNLIKELY(phs < 0.0 )) phs += p->tablen; } p->phs = phs; return OK; } static int poscaa(CSOUND *csound, POSC *p) { FUNC *ftp = p->ftp; MYFLT *out = p->out, *ft = p->ftp->ftable; MYFLT *curr_samp, fract; double phs = p->phs; MYFLT *freq = p->freq; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *amp = p->amp; /*gab c3*/ if (UNLIKELY(ftp==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("poscil: not initialised")); ft = p->ftp->ftable; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; ntablenUPsr;/* gab c3 */ while (UNLIKELY(phs >= p->tablen)) phs -= p->tablen; while (UNLIKELY(phs < 0.0) ) phs += p->tablen; } p->phs = phs; return OK; } static int poscka(CSOUND *csound, POSC *p) { FUNC *ftp = p->ftp; MYFLT *out = p->out, *ft; MYFLT *curr_samp, fract; double phs = p->phs; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT amp = *p->amp; MYFLT *freq = p->freq; if (UNLIKELY(ftp==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("poscil: not initialised")); ft = p->ftp->ftable; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; ntablenUPsr;/* gab c3 */ while (UNLIKELY(phs >= p->tablen)) phs -= p->tablen; while (UNLIKELY(phs < 0.0 )) phs += p->tablen; } p->phs = phs; return OK; } static int poscak(CSOUND *csound, POSC *p) { FUNC *ftp = p->ftp; MYFLT *out = p->out, *ft; MYFLT *curr_samp, fract; double phs = p->phs; double si = *p->freq * p->tablenUPsr; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *amp = p->amp; /*gab c3*/ if (UNLIKELY(ftp==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("poscil: not initialised")); ft = p->ftp->ftable; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; n= p->tablen)) phs -= p->tablen; while (UNLIKELY(phs < 0.0) ) phs += p->tablen; } p->phs = phs; return OK; } static int kposc(CSOUND *csound, POSC *p) { double phs = p->phs; double si = *p->freq * p->tablen * CS_ONEDKR; MYFLT *curr_samp = p->ftp->ftable + (int32)phs; MYFLT fract = (MYFLT)(phs - (double)((int32)phs)); *p->out = *p->amp * (*curr_samp +(*(curr_samp+1)-*curr_samp)*fract); phs += si; while (UNLIKELY(phs >= p->tablen)) phs -= p->tablen; while (UNLIKELY(phs < 0.0)) phs += p->tablen; p->phs = phs; return OK; } static int posc3kk(CSOUND *csound, POSC *p) { FUNC *ftp = p->ftp; MYFLT *out = p->out, *ftab; MYFLT fract; double phs = p->phs; double si = *p->freq * p->tablen * csound->onedsr; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT amp = *p->amp; int x0; MYFLT y0, y1, ym1, y2; if (UNLIKELY(ftp==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("poscil3: not initialised")); ftab = p->ftp->ftable; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; ntablen-1]; x0 = 0; } else ym1 = ftab[x0++]; y0 = ftab[x0++]; y1 = ftab[x0++]; if (UNLIKELY(x0>p->tablen)) y2 = ftab[1]; else y2 = ftab[x0]; { MYFLT frsq = fract*fract; MYFLT frcu = frsq*ym1; MYFLT t1 = y2 + y0+y0+y0; out[n] = amp * (y0 + FL(0.5)*frcu + fract*(y1 - frcu/FL(6.0) - t1/FL(6.0) - ym1/FL(3.0)) + frsq*fract*(t1/FL(6.0) - FL(0.5)*y1) + frsq*(FL(0.5)* y1 - y0)); } phs += si; while (UNLIKELY(phs >= p->tablen)) phs -= p->tablen; while (UNLIKELY(phs < 0.0) ) phs += p->tablen; } p->phs = phs; return OK; } static int posc3ak(CSOUND *csound, POSC *p) { FUNC *ftp = p->ftp; MYFLT *out = p->out, *ftab; MYFLT fract; double phs = p->phs; double si = *p->freq * p->tablen * csound->onedsr; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *ampp = p->amp; int x0; MYFLT y0, y1, ym1, y2; if (UNLIKELY(ftp==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("poscil3: not initialised")); ftab = p->ftp->ftable; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; ntablen-1]; x0 = 0; } else ym1 = ftab[x0++]; y0 = ftab[x0++]; y1 = ftab[x0++]; if (UNLIKELY(x0>p->tablen)) y2 = ftab[1]; else y2 = ftab[x0]; { MYFLT frsq = fract*fract; MYFLT frcu = frsq*ym1; MYFLT t1 = y2 + y0+y0+y0; out[n] = ampp[n] * (y0 + FL(0.5)*frcu + fract*(y1 - frcu/FL(6.0) - t1/FL(6.0) - ym1/FL(3.0)) + frsq*fract*(t1/FL(6.0) - FL(0.5)*y1) + frsq*(FL(0.5)* y1 - y0)); } phs += si; while (UNLIKELY(phs >= p->tablen)) phs -= p->tablen; while (UNLIKELY(phs < 0.0) ) phs += p->tablen; } p->phs = phs; return OK; } static int posc3ka(CSOUND *csound, POSC *p) { FUNC *ftp = p->ftp; MYFLT *out = p->out, *ftab; MYFLT fract; double phs = p->phs; /*double si = *p->freq * p->tablen * csound->onedsr;*/ MYFLT *freq = p->freq; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT amp = *p->amp; int x0; MYFLT y0, y1, ym1, y2; if (UNLIKELY(ftp==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("poscil3: not initialised")); ftab = p->ftp->ftable; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; ntablen-1]; x0 = 0; } else ym1 = ftab[x0++]; y0 = ftab[x0++]; y1 = ftab[x0++]; if (UNLIKELY(x0>p->tablen)) y2 = ftab[1]; else y2 = ftab[x0]; { MYFLT frsq = fract*fract; MYFLT frcu = frsq*ym1; MYFLT t1 = y2 + y0+y0+y0; out[n] = amp * (y0 + FL(0.5)*frcu + fract*(y1 - frcu/FL(6.0) - t1/FL(6.0) - ym1/FL(3.0)) + frsq*fract*(t1/FL(6.0) - FL(0.5)*y1) + frsq*(FL(0.5)* y1 - y0)); } phs += ff * p->tablenUPsr; while (UNLIKELY(phs >= p->tablen)) phs -= p->tablen; while (UNLIKELY(phs < 0.0) ) phs += p->tablen; } p->phs = phs; return OK; } static int posc3aa(CSOUND *csound, POSC *p) { FUNC *ftp = p->ftp; MYFLT *out = p->out, *ftab; MYFLT fract; double phs = p->phs; /*double si = *p->freq * p->tablen * csound->onedsr;*/ MYFLT *freq = p->freq; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *ampp = p->amp; int x0; MYFLT y0, y1, ym1, y2; if (UNLIKELY(ftp==NULL)) return csound->PerfError(csound, p->h.insdshead, Str("poscil3: not initialised")); ftab = p->ftp->ftable; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; ntablen-1]; x0 = 0; } else ym1 = ftab[x0++]; y0 = ftab[x0++]; y1 = ftab[x0++]; if (UNLIKELY(x0>p->tablen)) y2 = ftab[1]; else y2 = ftab[x0]; { MYFLT frsq = fract*fract; MYFLT frcu = frsq*ym1; MYFLT t1 = y2 + y0+y0+y0; out[n] = ampp[n] * (y0 + FL(0.5)*frcu + fract*(y1 - frcu/FL(6.0) - t1/FL(6.0) - ym1/FL(3.0)) + frsq*fract*(t1/FL(6.0) - FL(0.5)*y1) + frsq*(FL(0.5)* y1 - y0)); phs += ff * p->tablenUPsr; } while (UNLIKELY(phs >= p->tablen)) phs -= p->tablen; while (UNLIKELY(phs < 0.0) ) phs += p->tablen; } p->phs = phs; return OK; } static int kposc3(CSOUND *csound, POSC *p) { double phs = p->phs; double si = *p->freq * p->tablen * CS_ONEDKR; MYFLT *ftab = p->ftp->ftable; int x0 = (int32)phs; MYFLT fract = (MYFLT)(phs - (double)x0); MYFLT y0, y1, ym1, y2; MYFLT amp = *p->amp; x0--; if (UNLIKELY(x0<0)) { ym1 = ftab[p->tablen-1]; x0 = 0; } else ym1 = ftab[x0++]; y0 = ftab[x0++]; y1 = ftab[x0++]; if (UNLIKELY(x0>p->tablen)) y2 = ftab[1]; else y2 = ftab[x0]; { MYFLT frsq = fract*fract; MYFLT frcu = frsq*ym1; MYFLT t1 = y2 + y0+y0+y0; *p->out = amp * (y0 + FL(0.5)*frcu + fract*(y1 - frcu/FL(6.0) - t1/FL(6.0) - ym1/FL(3.0)) + frsq*fract*(t1/FL(6.0) - FL(0.5)*y1) + frsq*(FL(0.5)* y1 - y0)); } phs += si; while (UNLIKELY(phs >= p->tablen)) phs -= p->tablen; while (UNLIKELY(phs < 0.0)) phs += p->tablen; p->phs = phs; return OK; } static int lposc_set(CSOUND *csound, LPOSC *p) { FUNC *ftp; MYFLT loop, end, looplength; if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->ift)) == NULL)) return NOTOK; if (UNLIKELY(!(p->fsr=ftp->gen01args.sample_rate))) { csound->Warning(csound, Str("losc: no sample rate stored in function " "assuming=sr\n")); p->fsr=CS_ESR; } p->ftp = ftp; p->tablen = ftp->flen; /* changed from p->phs = *p->iphs * p->tablen; */ if (UNLIKELY((loop = *p->kloop) < 0)) loop=FL(0.0); if ((end = *p->kend) > p->tablen || end <=0 ) end = (MYFLT)p->tablen; looplength = end - loop; if (*p->iphs >= 0) p->phs = *p->iphs; while (UNLIKELY(p->phs >= end)) p->phs -= looplength; return OK; } static int lposc(CSOUND *csound, LPOSC *p) { MYFLT *out = p->out, *ft = p->ftp->ftable; MYFLT *curr_samp, fract; double phs= p->phs, si= *p->freq * (p->fsr*csound->onedsr); uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; double loop, end, looplength = p->looplength; MYFLT amp = *p->amp; if ((loop = *p->kloop) < 0) loop=0; if ((end = *p->kend) > p->tablen || end <=0 ) end = p->tablen; looplength = end - loop; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; n= end) phs -= looplength; } p->phs = phs; return OK; } static int lposc3(CSOUND *csound, LPOSC *p) { MYFLT *out = p->out, *ftab = p->ftp->ftable; MYFLT fract; double phs = p->phs, si= *p->freq * (p->fsr*csound->onedsr); uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; double loop, end, looplength = p->looplength; MYFLT amp = *p->amp; int x0; MYFLT y0, y1, ym1, y2; if (UNLIKELY((loop = *p->kloop) < 0)) loop=0; if ((end = *p->kend) > p->tablen || end <=0 ) end = p->tablen; looplength = end - loop; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; ntablen-1]; x0 = 0; } else ym1 = ftab[x0++]; y0 = ftab[x0++]; y1 = ftab[x0++]; if (x0>p->tablen) y2 = ftab[1]; else y2 = ftab[x0]; { MYFLT frsq = fract*fract; MYFLT frcu = frsq*ym1; MYFLT t1 = y2 + y0+y0+y0; out[n] = amp * (y0 + FL(0.5)*frcu + fract*(y1 - frcu/FL(6.0) - t1/FL(6.0) - ym1/FL(3.0)) + frsq*fract*(t1/FL(6.0) - FL(0.5)*y1) + frsq*(FL(0.5)* y1 - y0)); } phs += si; while (phs >= end) phs -= looplength; } p->phs = phs; return OK; } static int sum(CSOUND *csound, SUM *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t k, nsmps = CS_KSMPS; int count = (int) p->INOCOUNT; MYFLT *ar = p->ar, **args = p->argums; MYFLT *ag = *args; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } memcpy(&ar[offset], &ag[offset], sizeof(MYFLT)*(nsmps-offset)); while (--count) { ag = *(++args); /* over all arguments */ for (k=offset; kINOCOUNT; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t k, nsmps = CS_KSMPS; MYFLT *ar = p->ar, **args = p->argums; MYFLT *ag = *args; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } memcpy(&ar[offset], &ag[offset], sizeof(MYFLT)*(nsmps-offset)); while (--count) { ag = *(++args); /* over all arguments */ for (k=offset; kscale = scale = (int) *p->iscl; if ((p->loop = (int) MYFLT2LONG(*p->ord)) < 1) p->loop = 4; /* default value */ if (!*p->istor && (p->aux.auxp == NULL || (uint32_t) (p->loop * 2 * sizeof(MYFLT)) > p->aux.size)) csound->AuxAlloc(csound, (size_t) (p->loop * 2 * sizeof(MYFLT)), &p->aux); p->yt1 = (MYFLT*)p->aux.auxp; p->yt2 = (MYFLT*)p->aux.auxp + p->loop; if (UNLIKELY(scale && scale != 1 && scale != 2)) { return csound->InitError(csound, Str("illegal reson iscl value: %f"), *p->iscl); } if (!(*p->istor)) { memset(p->yt1, 0, p->loop*sizeof(MYFLT)); memset(p->yt2, 0, p->loop*sizeof(MYFLT)); /* for (j = 0; j < p->loop; j++) */ /* p->yt1[j] = p->yt2[j] = FL(0.0); */ } if (p->buffer.auxp == NULL || p->buffer.sizeAuxAlloc(csound, (size_t)(nsmps*sizeof(MYFLT)), &p->buffer); return OK; } static int resony(CSOUND *csound, RESONY *p) { int j; MYFLT *ar = p->ar, *asig; MYFLT c3p1, c3t4, omc3, c2sqr; MYFLT *yt1, *yt2, c1, c2, c3, cosf; double cf; int loop = p->loop; if (UNLIKELY(loop==0)) return csound->InitError(csound, Str("loop cannot be zero")); { MYFLT sep = (*p->sep / (MYFLT) loop); int flag = (int) *p->iflag; MYFLT *buffer = (MYFLT*) (p->buffer.auxp); uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; asig = p->asig; memset(buffer, 0, nsmps*sizeof(MYFLT)); if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } yt1 = p->yt1; yt2 = p->yt2; for (j = 0; j < loop; j++) { if (flag) /* linear separation in hertz */ cosf = (MYFLT) cos((cf = (double) (*p->kcf * sep * j)) * (double) csound->tpidsr); else /* logarithmic separation in octaves */ cosf = (MYFLT) cos((cf = (double) (*p->kcf * pow(2.0, sep * j))) * (double) csound->tpidsr); c3 = EXP(*p->kbw * (cf / *p->kcf) * csound->mtpdsr); c3p1 = c3 + FL(1.0); c3t4 = c3 * FL(4.0); c2 = c3t4 * cosf / c3p1; c2sqr = c2 * c2; omc3 = FL(1.0) - c3; if (p->scale == 1) c1 = omc3 * SQRT(FL(1.0) - c2sqr / c3t4); else if (p->scale == 2) c1 = SQRT((c3p1*c3p1-c2sqr) * omc3/c3p1); else c1 = FL(1.0); for (n = offset; n < nsmps; n++) { MYFLT temp = c1 * asig[n] + c2 * *yt1 - c3 * *yt2; buffer[n] += temp; *yt2 = *yt1; *yt1 = temp; } yt1++; yt2++; } memcpy(&ar[offset], &buffer[offset], sizeof(MYFLT)*(nsmps-offset)); return OK; } } static int fold_set(CSOUND *csound, FOLD *p) { p->sample_index = 0; p->index = 0.0; p->value = FL(0.0); /* This was not initialised -- JPff */ return OK; } static int fold(CSOUND *csound, FOLD *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *ar = p->ar; MYFLT *asig = p->asig; MYFLT kincr = *p->kincr; double index = p->index; int32 sample_index = p->sample_index; MYFLT value = p->value; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nindex = index; p->sample_index = sample_index; p->value = value; return OK; } /* by Gab Maldonado. Under GNU license with a special exception for Canonical Csound addition */ static int loopseg_set(CSOUND *csound, LOOPSEG *p) { p->nsegs = p->INOCOUNT-3; // Should check this is even if (UNLIKELY((p->nsegs&1)!=0)) csound->Warning(csound, Str("loop opcode: wrong argument count")); p->args[0] = FL(0.0); p->phs = *p->iphase; return OK; } static int loopseg(CSOUND *csound, LOOPSEG *p) { MYFLT *argp=p->args; MYFLT beg_seg=FL(0.0), end_seg, durtot=FL(0.0); double phs, si=*p->freq*CS_ONEDKR; int nsegs=p->nsegs+1; int j; if (*p->retrig) phs=p->phs=*p->iphase; else phs=p->phs; for (j=1; jargums[j-1]; argp[nsegs] = *p->argums[0]; for ( j=0; j phs) { MYFLT diff = end_seg - beg_seg; MYFLT fract = ((MYFLT)phs-beg_seg)/diff; MYFLT v1 = argp[j+1]; MYFLT v2 = argp[j+3]; *p->out = v1 + (v2-v1) * fract; break; } } phs += si; while (phs >= 1.0) phs -= 1.0; while (phs < 0.0 ) phs += 1.0; p->phs = phs; return OK; } static int loopxseg(CSOUND *csound, LOOPSEG *p) { MYFLT exp1 = FL(1.0)/(FL(1.0)-EXP(FL(1.0))); MYFLT *argp=p->args; MYFLT beg_seg=FL(0.0), end_seg, durtot=FL(0.0); double phs, si=*p->freq*CS_ONEDKR; int nsegs=p->nsegs+1; int j; if (*p->retrig) phs=p->phs=*p->iphase; else phs=p->phs; for (j=1; jargums[j-1]; argp[nsegs] = *p->argums[0]; for ( j=0; j phs) { MYFLT diff = end_seg - beg_seg; MYFLT fract = ((MYFLT)phs-beg_seg)/diff; MYFLT v1 = argp[j+1]; MYFLT v2 = argp[j+3]; *p->out = v1 + (v2 - v1) * (1 - EXP(fract)) * exp1; break; } } phs += si; while (phs >= 1.0) phs -= 1.0; while (phs < 0.0 ) phs += 1.0; p->phs = phs; return OK; } static int looptseg_set(CSOUND *csound, LOOPTSEG *p) { p->nsegs = (p->INOCOUNT-2)/3; p->phs = *p->iphase; return OK; } static int looptseg(CSOUND *csound, LOOPTSEG *p) { MYFLT beg_seg=FL(0.0), end_seg=FL(0.0), durtot=FL(0.0); double phs, si=*p->freq*CS_ONEDKR; int nsegs=p->nsegs; int j; if (*p->retrig) phs=p->phs=*p->iphase; else phs=p->phs; for ( j=0; jargums[j].time); for ( j=0; j < nsegs; j++) { beg_seg = end_seg; end_seg = beg_seg + *(p->argums[j].time) / durtot; if (beg_seg <= phs && end_seg > phs) { MYFLT alpha = *(p->argums[j].type); MYFLT diff = end_seg - beg_seg; MYFLT fract = ((MYFLT)phs-beg_seg)/diff; MYFLT v1 = *(p->argums[j].start); MYFLT v2 = (j!=nsegs-1)?*(p->argums[j+1].start):*(p->argums[0].start); if (alpha==FL(0.0)) *p->out = v1 + (v2 - v1) * fract; else *p->out = v1 + (v2 - v1) * (FL(1.0)-EXP(alpha*fract))/(FL(1.0)-EXP(alpha)); break; } } phs += si; while (UNLIKELY(phs >= 1.0)) phs -= 1.0; while (UNLIKELY(phs < 0.0 )) phs += 1.0; p->phs = phs; return OK; } static int lpshold(CSOUND *csound, LOOPSEG *p) { MYFLT *argp=p->args; MYFLT beg_seg=0, end_seg, durtot=FL(0.0); double phs, si=*p->freq*CS_ONEDKR; int nsegs=p->nsegs+1; int j; if (*p->retrig) phs=p->phs=*p->iphase; else phs=p->phs; for (j=1; jargums[j-1]; argp[nsegs] = *p->argums[0]; for ( j=0; j phs) { if (beg_seg <= phs && end_seg > phs) { *p->out = argp[j+1]; break; } } } phs += si; while (phs >= 1.0) phs -= 1.0; while (phs < 0.0 ) phs += 1.0; p->phs = phs; return OK; } static int loopsegp_set(CSOUND *csound, LOOPSEGP *p) { p->nsegs = p->INOCOUNT-1; p->args[0] = FL(0.0); return OK; } static int loopsegp(CSOUND *csound, LOOPSEGP *p) { MYFLT *argp = p->args; MYFLT beg_seg=0, end_seg, durtot=FL(0.0); MYFLT phs; int nsegs=p->nsegs+1; int j; phs = *p->kphase; while (phs >= FL(1.0)) phs -= FL(1.0); while (phs < FL(0.0)) phs += FL(1.0); for (j=1; jargums[j-1]; argp[nsegs] = *p->argums[0]; for ( j=0; j phs) { MYFLT diff = end_seg - beg_seg; MYFLT fract = ((MYFLT)phs-beg_seg)/diff; MYFLT v1 = argp[j+1]; MYFLT v2 = argp[j+3]; *p->out = v1 + (v2-v1) * fract; break; } } return OK; } static int lpsholdp(CSOUND *csound, LOOPSEGP *p) { MYFLT *argp=p->args; MYFLT beg_seg=FL(0.0), end_seg, durtot=FL(0.0); MYFLT phs; int nsegs=p->nsegs+1; int j; phs = *p->kphase; while (phs >= FL(1.0)) phs -= FL(1.0); while (phs < FL(0.0)) phs += FL(1.0); for (j=1; jargums[j-1]; argp[nsegs] = *p->argums[0]; for ( j=0; j phs) { if (beg_seg <= phs && end_seg > phs) { *p->out = argp[j+1]; break; } } } return OK; } /* by Gab Maldonado. Under GNU license with a special exception for Canonical Csound addition */ static int lineto_set(CSOUND *csound, LINETO *p) { p->current_time = FL(0.0); p->incr=FL(0.0); p->old_time=FL(0.0); p->flag = 1; return OK; } static int lineto(CSOUND *csound, LINETO *p) { if (UNLIKELY(p->flag)) { p->val_incremented = p->current_val = *p->ksig; p->flag=0; } /* printf("lineto: ktime=%lf ksig=%lf\n " */ /* "old_time=%lf val_inc=%lf incr=%lf val=%lf\n", */ /* *p->ktime, *p->ksig, p->old_time, p->val_incremented, p->incr, */ /* p->current_val); */ if (*p->ksig != p->current_val && p->current_time > p->old_time) { p->old_time = *p->ktime; p->val_incremented = p->current_val; p->current_time = FL(0.0); p->incr = (*p->ksig - p->current_val) / ((int32) (CS_EKR * p->old_time) -1); /* by experiment */ p->current_val = *p->ksig; } else if (p->current_time < p->old_time) { p->val_incremented += p->incr; } p->current_time += 1/CS_EKR; *p->kr = p->val_incremented; return OK; } static int tlineto_set(CSOUND *csound, LINETO2 *p) { p->current_time = FL(0.0); p->incr=FL(0.0); p->old_time=FL(1.0); p->flag = 1; return OK; } static int tlineto(CSOUND *csound, LINETO2 *p) { if (UNLIKELY(p->flag)) { p->val_incremented = p->current_val = *p->ksig; p->flag=0; } if (*p->ktrig) { p->old_time = *p->ktime; /* p->val_incremented = p->current_val; */ p->current_time = FL(0.0); p->incr = (*p->ksig - p->current_val) / ((int32) (CS_EKR * p->old_time) + 1); p->current_val = *p->ksig; } else if (p->current_time < p->old_time) { p->current_time += CS_ONEDKR; p->val_incremented += p->incr; } *p->kr = p->val_incremented; return OK; } /* by Gabriel Maldonado. Under GNU license with a special exception for Canonical Csound addition */ static int vibrato_set(CSOUND *csound, VIBRATO *p) { FUNC *ftp; if (LIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) != NULL)) { p->ftp = ftp; if (*p->iphs >= 0 && *p->iphs<1.0) p->lphs = (((long)(*p->iphs * FMAXLEN)) & PHMASK) >> ftp->lobits; else if (UNLIKELY(*p->iphs>=1.0)) return csound->InitError(csound, Str("vibrato@ Phase out of range")); } else return NOTOK; p->xcpsAmpRate = randGab *(*p->cpsMaxRate - *p->cpsMinRate) + *p->cpsMinRate; p->xcpsFreqRate = randGab *(*p->ampMaxRate - *p->ampMinRate) + *p->ampMinRate; p->tablen = ftp->flen; p->tablenUPkr = p->tablen * CS_ONEDKR; return OK; } static int vibrato(CSOUND *csound, VIBRATO *p) { FUNC *ftp; double phs, inc; MYFLT *ftab, fract, v1; MYFLT RandAmountAmp,RandAmountFreq; RandAmountAmp = (p->num1amp + (MYFLT)p->phsAmpRate * p->dfdmaxAmp) * *p->randAmountAmp ; RandAmountFreq = (p->num1freq + (MYFLT)p->phsFreqRate * p->dfdmaxFreq) * *p->randAmountFreq ; phs = p->lphs; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) goto err1; fract = (MYFLT) (phs - (int32)phs); ftab = ftp->ftable + (int32)phs; v1 = *ftab++; *p->out = (v1 + (*ftab - v1) * fract) * (*p->AverageAmp * POWER(FL(2.0),RandAmountAmp)); inc = ( *p->AverageFreq * POWER(FL(2.0),RandAmountFreq)) * p->tablenUPkr; phs += inc; while (phs >= p->tablen) phs -= p->tablen; while (phs < 0.0 ) phs += p->tablen; p->lphs = phs; p->phsAmpRate += (int32)(p->xcpsAmpRate * CS_KICVT); if (p->phsAmpRate >= MAXLEN) { p->xcpsAmpRate = randGab * (*p->ampMaxRate - *p->ampMinRate) + *p->ampMinRate; p->phsAmpRate &= PHMASK; p->num1amp = p->num2amp; p->num2amp = BiRandGab ; p->dfdmaxAmp = (p->num2amp - p->num1amp) / FMAXLEN; } p->phsFreqRate += (int32)(p->xcpsFreqRate * CS_KICVT); if (p->phsFreqRate >= MAXLEN) { p->xcpsFreqRate = randGab * (*p->cpsMaxRate - *p->cpsMinRate) + *p->cpsMinRate; p->phsFreqRate &= PHMASK; p->num1freq = p->num2freq; p->num2freq = BiRandGab ; p->dfdmaxFreq = (p->num2freq - p->num1freq) / FMAXLEN; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("vibrato(krate): not initialised")); } static int vibr_set(CSOUND *csound, VIBR *p) /* faster and easier to use than vibrato, but less flexible */ { FUNC *ftp; #define randAmountAmp FL(1.59055) /* these default values are far from */ #define randAmountFreq FL(0.629921) /* being the best. If you think you */ #define ampMinRate FL(1.0) /* found better ones, please tell me */ #define ampMaxRate FL(3.0) /* by posting a message to g.maldonado@agora.stm.it */ #define cpsMinRate FL(1.19377) #define cpsMaxRate FL(2.28100) #define iphs FL(0.0) if (LIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) != NULL)) { p->ftp = ftp; p->lphs = (((int32)(iphs * FMAXLEN)) & PHMASK) >> ftp->lobits; } else return NOTOK; p->xcpsAmpRate = randGab * (cpsMaxRate - cpsMinRate) + cpsMinRate; p->xcpsFreqRate = randGab * (ampMaxRate - ampMinRate) + ampMinRate; p->tablen = ftp->flen; p->tablenUPkr = p->tablen * CS_ONEDKR; return OK; } static int vibr(CSOUND *csound, VIBR *p) { FUNC *ftp; double phs, inc; MYFLT *ftab, fract, v1; MYFLT rAmountAmp,rAmountFreq; rAmountAmp = (p->num1amp+(MYFLT)p->phsAmpRate * p->dfdmaxAmp)*randAmountAmp; rAmountFreq = (p->num1freq+(MYFLT)p->phsFreqRate*p->dfdmaxFreq)*randAmountFreq; phs = p->lphs; ftp = p->ftp; if (UNLIKELY(ftp==NULL)) { return csound->PerfError(csound, p->h.insdshead, Str("vibrato(krate): not initialised")); } fract = (MYFLT) (phs - (int32)phs); /*PFRAC(phs);*/ ftab = ftp->ftable + (int32)phs; /*(phs >> ftp->lobits);*/ v1 = *ftab++; *p->out = (v1 + (*ftab - v1) * fract) * (*p->AverageAmp * POWER(FL(2.0),rAmountAmp)); inc = ( *p->AverageFreq * POWER(FL(2.0),rAmountFreq) ) * p->tablenUPkr; phs += inc; while (phs >= p->tablen) phs -= p->tablen; while (phs < 0.0 ) phs += p->tablen; p->lphs = phs; p->phsAmpRate += (int32)(p->xcpsAmpRate * CS_KICVT); if (p->phsAmpRate >= MAXLEN) { p->xcpsAmpRate = randGab * (ampMaxRate - ampMinRate) + ampMinRate; p->phsAmpRate &= PHMASK; p->num1amp = p->num2amp; p->num2amp = BiRandGab; p->dfdmaxAmp = (p->num2amp - p->num1amp) / FMAXLEN; } p->phsFreqRate += (int32)(p->xcpsFreqRate * CS_KICVT); if (p->phsFreqRate >= MAXLEN) { p->xcpsFreqRate = randGab * (cpsMaxRate - cpsMinRate) + cpsMinRate; p->phsFreqRate &= PHMASK; p->num1freq = p->num2freq; p->num2freq = BiRandGab; p->dfdmaxFreq = (p->num2freq - p->num1freq) / FMAXLEN; } #undef randAmountAmp #undef randAmountFreq #undef ampMinRate #undef ampMaxRate #undef cpsMinRate #undef cpsMaxRate #undef iphs return OK; } static int jitter2_set(CSOUND *csound, JITTER2 *p) { if (*p->cps1==FL(0.0) && *p->cps2==FL(0.0) && /* accept default values */ *p->cps2==FL(0.0) && *p->amp1==FL(0.0) && *p->amp2==FL(0.0) && *p->amp3==FL(0.0)) p->flag = 1; else p->flag = 0; p->dfdmax1 = p->dfdmax2 = p->dfdmax3 = FL(0.0); p->phs1 = p->phs2 = p->phs3 = 0; p->num1a = p->num1b = p->num1c = FL(0.0); /* JPff Jul 2016 */ if (*p->option != FL(0.0)) { p->num1a = p->num2a; p->num2a = BiRandGab; p->dfdmax1 = (p->num2a - p->num1a) / FMAXLEN; p->num1b = p->num2b; p->num2b = BiRandGab; p->dfdmax2 = (p->num2b- p->num1b) / FMAXLEN; p->num1c = p->num2c; p->num2c = BiRandGab; p->dfdmax3 = (p->num2c- p->num1c) / FMAXLEN; } return OK; } static int jitter2(CSOUND *csound, JITTER2 *p) { MYFLT out1,out2,out3; out1 = (p->num1a + (MYFLT)p->phs1 * p->dfdmax1); out2 = (p->num1b + (MYFLT)p->phs2 * p->dfdmax2); out3 = (p->num1c + (MYFLT)p->phs3 * p->dfdmax3); if (p->flag) { /* accept default values */ *p->out = (out1* FL(0.5) + out2 * FL(0.3) + out3* FL(0.2)) * *p->gamp; p->phs1 += (int32) (FL(0.82071231913) * CS_KICVT); p->phs2 += (int32) (FL(7.009019029039107) * CS_KICVT); p->phs3 += (int32) (FL(10.0) * CS_KICVT); } else { *p->out = (out1* *p->amp1 + out2* *p->amp2 +out3* *p->amp3) * *p->gamp; p->phs1 += (int32)( *p->cps1 * CS_KICVT); p->phs2 += (int32)( *p->cps2 * CS_KICVT); p->phs3 += (int32)( *p->cps3 * CS_KICVT); } if (p->phs1 >= MAXLEN) { p->phs1 &= PHMASK; p->num1a = p->num2a; p->num2a = BiRandGab; p->dfdmax1 = (p->num2a - p->num1a) / FMAXLEN; } if (p->phs2 >= MAXLEN) { p->phs2 &= PHMASK; p->num1b = p->num2b; p->num2b = BiRandGab; p->dfdmax2 = (p->num2b - p->num1b) / FMAXLEN; } if (p->phs3 >= MAXLEN) { p->phs3 &= PHMASK; p->num1c = p->num2c; p->num2c = BiRandGab; p->dfdmax3 = (p->num2c - p->num1c) / FMAXLEN; } return OK; } static int jitter_set(CSOUND *csound, JITTER *p) { p->num2 = BiRandGab; p->initflag = 1; p->phs=0; return OK; } static int jitter(CSOUND *csound, JITTER *p) { if (p->initflag) { p->initflag = 0; *p->ar = p->num2 * *p->amp; goto next; } *p->ar = (p->num1 + (MYFLT)p->phs * p->dfdmax) * *p->amp; p->phs += (int32)(p->xcps * CS_KICVT); if (p->phs >= MAXLEN) { next: p->xcps = randGab * (*p->cpsMax - *p->cpsMin) + *p->cpsMin; p->phs &= PHMASK; p->num1 = p->num2; p->num2 = BiRandGab; p->dfdmax = (p->num2 - p->num1) / FMAXLEN; } return OK; } static int jitters_set(CSOUND *csound, JITTERS *p) { p->num1 = BiRandGab; p->num2 = BiRandGab; p->df1 = FL(0.0); p->initflag = 1; p->cod = IS_ASIG_ARG(p->amp) ? 1 : 0; p->phs = 0; return OK; } static int jitters(CSOUND *csound, JITTERS *p) { MYFLT x, c3= p->c3, c2= p->c2; MYFLT f0 = p->num0, df0= p->df0; if (p->initflag == 1) { p->initflag = 0; goto next; } p->phs += p->si; if (p->phs >= 1.0) { MYFLT slope, resd1, resd0, f2, f1; next: p->si = (randGab * (*p->cpsMax-*p->cpsMin) + *p->cpsMin)*CS_ONEDKR; if (p->si == 0) p->si = 1; /* Is this necessary? */ while (p->phs > 1.0) p->phs -= 1.0; f0 = p->num0 = p->num1; f1 = p->num1 = p->num2; f2 = p->num2 = BiRandGab; df0 = p->df0 = p->df1; p->df1 = ( f2 - f0 ) * FL(0.5); slope = f1 - f0; resd0 = df0 - slope; resd1 = p->df1 - slope; c3 = p->c3 = resd0 + resd1; c2 = p->c2 = - (resd1 + FL(2.0)* resd0); } x= (MYFLT) p->phs; *p->ar = (((c3 * x + c2) * x + df0) * x + f0) * *p->amp; return OK; } static int jittersa(CSOUND *csound, JITTERS *p) { MYFLT x, c3=p->c3, c2=p->c2; MYFLT f0= p->num0, df0 = p->df0; MYFLT *ar = p->ar, *amp = p->amp; MYFLT cpsMax = *p->cpsMax, cpsMin = *p->cpsMin; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int cod = p->cod; double phs = p->phs, si = p->si; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } if (p->initflag) { p->initflag = 0; n = offset; goto next; } for (n=offset; n= 1.0) { MYFLT slope, resd1, resd0, f2, f1; next: si = (randGab * (cpsMax - cpsMin) + cpsMin)*csound->onedsr; if (si == 0) si = 1; /* Is this necessary? */ while (phs > 1.0) phs -= 1.0; f0 = p->num0 = p->num1; f1 = p->num1 = p->num2; f2 = p->num2 = BiRandGab; df0 = p->df0 = p->df1; p->df1 = ( f2 - f0 ) * FL(0.5); slope = f1 - f0; resd0 = df0 - slope; resd1 = p->df1 - slope; c3 = p->c3 = resd0 + resd1; c2 = p->c2 = - (resd1 + FL(2.0)* resd0); } x = (MYFLT) phs; ar[n] = (((c3 * x + c2) * x + df0) * x + f0) * *amp; if (cod) amp++; } p->phs = phs; p->si =si; return OK; } static int kDiscreteUserRand(CSOUND *csound, DURAND *p) { /* gab d5*/ if (p->pfn != (int32)*p->tableNum) { if (UNLIKELY( (p->ftp = csound->FTFindP(csound, p->tableNum) ) == NULL)) goto err1; p->pfn = (int32)*p->tableNum; } *p->out = p->ftp->ftable[(int32)(randGab * p->ftp->flen)]; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("Invalid ftable no. %f"), *p->tableNum); } static int iDiscreteUserRand(CSOUND *csound, DURAND *p) { p->pfn = 0L; kDiscreteUserRand(csound,p); return OK; } static int aDiscreteUserRand(CSOUND *csound, DURAND *p) { /* gab d5*/ MYFLT *out = p->out, *table; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS, flen; if (p->pfn != (int32)*p->tableNum) { if (UNLIKELY( (p->ftp = csound->FTFindP(csound, p->tableNum) ) == NULL)) goto err1; p->pfn = (int32)*p->tableNum; } table = p->ftp->ftable; flen = p->ftp->flen; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nPerfError(csound, p->h.insdshead, Str("Invalid ftable no. %f"), *p->tableNum); } static int kContinuousUserRand(CSOUND *csound, CURAND *p) { /* gab d5*/ int32 indx; MYFLT findx, fract, v1, v2; if (p->pfn != (int32)*p->tableNum) { if (UNLIKELY( (p->ftp = csound->FTFindP(csound, p->tableNum) ) == NULL)) goto err1; p->pfn = (int32)*p->tableNum; } findx = (MYFLT) (randGab * p->ftp->flen); indx = (int32) findx; fract = findx - indx; v1 = *(p->ftp->ftable + indx); v2 = *(p->ftp->ftable + indx + 1); *p->out = (v1 + (v2 - v1) * fract) * (*p->max - *p->min) + *p->min; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("Invalid ftable no. %f"), *p->tableNum); } static int iContinuousUserRand(CSOUND *csound, CURAND *p) { p->pfn = 0; kContinuousUserRand(csound,p); return OK; } static int Cuserrnd_set(CSOUND *csound, CURAND *p) { p->pfn = 0; return OK; } static int aContinuousUserRand(CSOUND *csound, CURAND *p) { /* gab d5*/ MYFLT min = *p->min, rge = *p->max; MYFLT *out = p->out, *table; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS, flen; int indx; MYFLT findx, fract,v1,v2; if (p->pfn != (int32)*p->tableNum) { if (UNLIKELY( (p->ftp = csound->FTFindP(csound, p->tableNum) ) == NULL)) goto err1; p->pfn = (int32)*p->tableNum; } table = p->ftp->ftable; flen = p->ftp->flen; rge -= min; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nPerfError(csound, p->h.insdshead, Str("Invalid ftable no. %f"), *p->tableNum); } static int ikRangeRand(CSOUND *csound, RANGERAND *p) { /* gab d5*/ *p->out = randGab * (*p->max - *p->min) + *p->min; return OK; } static int aRangeRand(CSOUND *csound, RANGERAND *p) { /* gab d5*/ MYFLT min = *p->min, max = *p->max, *out = p->out; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT rge = max - min; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nphs = 0; int mode = (int)(*p->mode); switch (mode) { case 1: /* immediate interpolation between kmin and 1st random number */ p->num1 = FL(0.0); p->num2 = randGab; p->dfdmax = (p->num2 - p->num1) / FMAXLEN; break; case 2: /* immediate interpolation between ifirstval and 1st random number */ p->num1 = (*p->max - *p->min) ? (*p->fstval - *p->min) / (*p->max - *p->min) : FL(0.0); p->num2 = randGab; p->dfdmax = (p->num2 - p->num1) / FMAXLEN; break; case 3: /* immediate interpolation between 1st and 2nd random number */ p->num1 = randGab; p->num2 = randGab; p->dfdmax = (p->num2 - p->num1) / FMAXLEN; break; default: /* old behaviour as developped by Gabriel */ p->num1 = p->num2 = FL(0.0); p->dfdmax = FL(0.0); } p->cpscod = IS_ASIG_ARG(p->xcps) ? 1 : 0; return OK; } static int krandomi(CSOUND *csound, RANDOMI *p) { *p->ar = (p->num1 + (MYFLT)p->phs * p->dfdmax) * (*p->max - *p->min) + *p->min; p->phs += (int32)(*p->xcps * CS_KICVT); if (p->phs >= MAXLEN) { p->phs &= PHMASK; p->num1 = p->num2; p->num2 = randGab; p->dfdmax = (p->num2 - p->num1) / FMAXLEN; } return OK; } static int randomi(CSOUND *csound, RANDOMI *p) { int32 phs = p->phs, inc; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *ar, *cpsp; MYFLT amp, min; cpsp = p->xcps; min = *p->min; amp = (*p->max - min); ar = p->ar; inc = (int32)(*cpsp++ * csound->sicvt); if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nnum1 + (MYFLT)phs * p->dfdmax) * amp + min; phs += inc; if (p->cpscod) inc = (int32)(*cpsp++ * csound->sicvt); if (phs >= MAXLEN) { phs &= PHMASK; p->num1 = p->num2; p->num2 = randGab; p->dfdmax = (p->num2 - p->num1) / FMAXLEN; } } p->phs = phs; return OK; } /* mode and fstval arguments added */ /* by Francois Pinot, jan. 2011 */ static int randomh_set(CSOUND *csound, RANDOMH *p) { p->phs = 0; int mode = (int)(*p->mode); switch (mode) { case 2: /* the first output value is ifirstval */ p->num1 = (*p->max - *p->min) ? (*p->fstval - *p->min) / (*p->max - *p->min) : FL(0.0); break; case 3: /* the first output value is a random number within the defined range */ p->num1 = randGab; break; default: /* old behaviour as developped by Gabriel */ p->num1 = FL(0.0); } p->cpscod = IS_ASIG_ARG(p->xcps) ? 1 : 0; return OK; } static int krandomh(CSOUND *csound, RANDOMH *p) { *p->ar = p->num1 * (*p->max - *p->min) + *p->min; p->phs += (int32)(*p->xcps * CS_KICVT); if (p->phs >= MAXLEN) { p->phs &= PHMASK; p->num1 = randGab; } return OK; } static int randomh(CSOUND *csound, RANDOMH *p) { int32 phs = p->phs, inc; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *ar, *cpsp; MYFLT amp, min; cpsp = p->xcps; min = *p->min; amp = (*p->max - min); ar = p->ar; inc = (int32)(*cpsp++ * csound->sicvt); if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nnum1 * amp + min; phs += inc; if (p->cpscod) inc = (int32)(*cpsp++ * csound->sicvt); if (phs >= MAXLEN) { phs &= PHMASK; p->num1 = randGab; } } p->phs = phs; return OK; } static int random3_set(CSOUND *csound, RANDOM3 *p) { p->num1 = randGab; p->num2 = randGab; p->df1 = FL(0.0); p->initflag = 1; p->rangeMin_cod = IS_ASIG_ARG(p->rangeMin); p->rangeMax_cod = IS_ASIG_ARG(p->rangeMin); p->phs = 0.0; return OK; } static int random3(CSOUND *csound, RANDOM3 *p) { MYFLT x, c3= p->c3, c2= p->c2; MYFLT f0 = p->num0, df0= p->df0; if (p->initflag) { p->initflag = 0; goto next; } p->phs += p->si; if (p->phs >= 1.0) { MYFLT slope, resd1, resd0, f2, f1; next: p->si = (randGab * (*p->cpsMax-*p->cpsMin) + *p->cpsMin)*CS_ONEDKR; while (p->phs > 1.0) p->phs -= 1.0; f0 = p->num0 = p->num1; f1 = p->num1 = p->num2; f2 = p->num2 = randGab; df0 = p->df0 = p->df1; p->df1 = ( f2 - f0 ) * FL(0.5); slope = f1 - f0; resd0 = df0 - slope; resd1 = p->df1 - slope; c3 = p->c3 = resd0 + resd1; c2 = p->c2 = - (resd1 + FL(2.0)* resd0); } x = (MYFLT) p->phs; *p->ar = (((c3 * x + c2) * x + df0) * x + f0) * (*p->rangeMax - *p->rangeMin) + *p->rangeMin; return OK; } static int random3a(CSOUND *csound, RANDOM3 *p) { int rangeMin_cod = p->rangeMin_cod, rangeMax_cod = p->rangeMax_cod; MYFLT x, c3=p->c3, c2=p->c2; MYFLT f0 = p->num0, df0 = p->df0; MYFLT *ar = p->ar, *rangeMin = p->rangeMin; MYFLT *rangeMax = p->rangeMax; MYFLT cpsMin = *p->cpsMin, cpsMax = *p->cpsMax; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; double phs = p->phs, si = p->si; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } if (p->initflag) { p->initflag = 0; n = offset; goto next; } for (n=offset; n= 1.0) { MYFLT slope, resd1, resd0, f2, f1; next: si = (randGab * (cpsMax - cpsMin) + cpsMin)*csound->onedsr; while (phs > 1.0) phs -= 1.0; f0 = p->num0 = p->num1; f1 = p->num1 = p->num2; f2 = p->num2 = BiRandGab; df0 = p->df0 = p->df1; p->df1 = ( f2 - f0 ) * FL(0.5); slope = f1 - f0; resd0 = df0 - slope; resd1 = p->df1 - slope; c3 = p->c3 = resd0 + resd1; c2 = p->c2 = - (resd1 + FL(2.0)* resd0); } x = (MYFLT) phs; ar[n] = (((c3 * x + c2) * x + df0) * x + f0) * (*rangeMax - *rangeMin) + *rangeMin; if (rangeMin_cod) rangeMin++; if (rangeMax_cod) rangeMax++; } p->phs = phs; p->si = si; return OK; } #define S(x) sizeof(x) static OENTRY localops[] = { { "wrap", 0xffff }, { "wrap.i", S(WRAP), 0,1, "i", "iii", (SUBR)kwrap, NULL, NULL }, { "wrap.k", S(WRAP), 0,2, "k", "kkk", NULL, (SUBR)kwrap, NULL }, { "wrap.a", S(WRAP), 0,4, "a", "akk", NULL, NULL, (SUBR)wrap }, { "mirror", 0xffff }, { "mirror.i", S(WRAP), 0,1, "i", "iii", (SUBR)kmirror, NULL, NULL }, { "mirror.k", S(WRAP), 0,2, "k", "kkk", NULL, (SUBR)kmirror, NULL }, { "mirror.a", S(WRAP), 0,4, "a", "akk", NULL, NULL, (SUBR)mirror }, { "ntrpol.i",S(INTERPOL), 0,1, "i", "iiiop",(SUBR)interpol }, { "ntrpol.k",S(INTERPOL), 0,3, "k", "kkkop",(SUBR)nterpol_init, (SUBR)knterpol }, { "ntrpol.a",S(INTERPOL), 0,5, "a", "aakop",(SUBR)nterpol_init,NULL,(SUBR)anterpol}, { "fold", S(FOLD), 0,5, "a", "ak", (SUBR)fold_set, NULL, (SUBR)fold }, { "lineto", S(LINETO), 0,3, "k", "kk", (SUBR)lineto_set, (SUBR)lineto, NULL }, { "tlineto", S(LINETO2), 0,3, "k", "kkk", (SUBR)tlineto_set, (SUBR)tlineto, NULL}, { "vibrato", S(VIBRATO), TR, 3, "k", "kkkkkkkkio", (SUBR)vibrato_set, (SUBR)vibrato, NULL }, { "vibr", S(VIBRATO), TR, 3, "k", "kki", (SUBR)vibr_set, (SUBR)vibr, NULL }, { "jitter2", S(JITTER2), 0,3, "k", "kkkkkkko", (SUBR)jitter2_set, (SUBR)jitter2 }, { "jitter", S(JITTER), 0,3, "k", "kkk", (SUBR)jitter_set, (SUBR)jitter, NULL }, { "jspline", S(JITTERS), 0,3, "k", "xkk", (SUBR)jitters_set, (SUBR)jitters, NULL }, { "jspline.a", S(JITTERS), 0,5, "a", "xkk", (SUBR)jitters_set, NULL, (SUBR)jittersa }, { "loopseg", S(LOOPSEG), 0,3, "k", "kkiz", (SUBR)loopseg_set, (SUBR)loopseg, NULL}, { "loopxseg", S(LOOPSEG), 0,3, "k", "kkiz", (SUBR)loopseg_set,(SUBR)loopxseg, NULL}, { "looptseg", S(LOOPSEG), 0,3, "k", "kkiz",(SUBR)looptseg_set,(SUBR)looptseg, NULL}, { "lpshold", S(LOOPSEG), 0,3, "k", "kkiz",(SUBR)loopseg_set, (SUBR)lpshold, NULL }, { "loopsegp", S(LOOPSEGP), 0,3,"k", "kz", (SUBR)loopsegp_set,(SUBR)loopsegp, NULL}, { "lpsholdp", S(LOOPSEGP), 0,3,"k", "kz", (SUBR)loopsegp_set,(SUBR)lpsholdp, NULL}, { "cuserrnd", 0xffff, TR }, { "duserrnd", 0xffff, TR }, { "random", 0xffff }, { "cuserrnd.i", S(CURAND),0,1,"i", "iii", (SUBR)iContinuousUserRand, NULL, NULL }, { "cuserrnd.k", S(CURAND),0,2,"k", "kkk", (SUBR)Cuserrnd_set, (SUBR)kContinuousUserRand, NULL }, { "cuserrnd.a",S(CURAND),0,4, "a", "kkk", (SUBR)Cuserrnd_set, NULL, (SUBR)aContinuousUserRand }, { "random.i", S(RANGERAND), 0,1, "i", "ii", (SUBR)ikRangeRand, NULL, NULL }, { "random.k", S(RANGERAND), 0,2, "k", "kk", NULL, (SUBR)ikRangeRand, NULL }, { "random.a", S(RANGERAND), 0,4, "a", "kk", NULL, NULL, (SUBR)aRangeRand }, { "rspline", S(RANDOM3), 0,3, "k", "xxkk", (SUBR)random3_set, (SUBR)random3, NULL }, { "rspline.a", S(RANDOM3), 0,5, "a", "xxkk", (SUBR)random3_set, NULL, (SUBR)random3a }, { "randomi", S(RANDOMI), 0,5, "a", "kkxoo", (SUBR)randomi_set, (SUBR)NULL, (SUBR)randomi }, { "randomi.k", S(RANDOMI), 0,3, "k", "kkkoo", (SUBR)randomi_set, (SUBR)krandomi,NULL }, { "randomh", S(RANDOMH), 0,5, "a", "kkxoo", (SUBR)randomh_set,(SUBR)NULL,(SUBR)randomh }, { "randomh.k", S(RANDOMH), 0,3, "k", "kkkoo", (SUBR)randomh_set,(SUBR)krandomh,NULL}, { "urd.i", S(DURAND), 0,1, "i", "i", (SUBR)iDiscreteUserRand, NULL, NULL }, { "urd.k", S(DURAND), 0,2, "k", "k", (SUBR)Cuserrnd_set,(SUBR)kDiscreteUserRand }, { "urd.a", S(DURAND), 0,4, "a", "k", (SUBR)Cuserrnd_set, NULL, (SUBR)aDiscreteUserRand }, { "duserrnd.i", S(DURAND),0,1, "i", "i", (SUBR)iDiscreteUserRand, NULL, NULL }, { "duserrnd.k", S(DURAND),0,2, "k", "k", (SUBR)Cuserrnd_set,(SUBR)kDiscreteUserRand,NULL }, { "duserrnd.a", S(DURAND),0,4, "a", "k", (SUBR)Cuserrnd_set,NULL,(SUBR)aDiscreteUserRand }, { "poscil", 0xfffe, TR }, { "poscil.a", S(POSC), 0,5, "a", "kkjo", (SUBR)posc_set,(SUBR)NULL,(SUBR)posckk }, { "poscil.kk", S(POSC), 0,3, "k", "kkjo", (SUBR)posc_set,(SUBR)kposc,NULL }, { "poscil.ka", S(POSC), 0,5, "a", "kajo", (SUBR)posc_set, NULL, (SUBR)poscka }, { "poscil.ak", S(POSC), 0,5, "a", "akjo", (SUBR)posc_set, NULL, (SUBR)poscak }, { "poscil.aa", S(POSC), 0,5, "a", "aajo", (SUBR)posc_set, NULL, (SUBR)poscaa }, { "lposcil", S(LPOSC), TR, 5, "a", "kkkkjo", (SUBR)lposc_set, NULL, (SUBR)lposc}, { "poscil3", 0xfffe, TR }, { "poscil3.a",S(POSC), 0,5, "a", "kkjo", (SUBR)posc_set,(SUBR)NULL,(SUBR)posc3kk }, { "poscil3.kk",S(POSC), 0,7, "k", "kkjo", (SUBR)posc_set,(SUBR)kposc3,NULL}, { "poscil3.ak", S(POSC), 0,5, "a", "akjo", (SUBR)posc_set, NULL, (SUBR)posc3ak }, { "poscil3.ka", S(POSC), 0,5, "a", "kajo", (SUBR)posc_set, NULL, (SUBR)posc3ka }, { "poscil3.aa", S(POSC), 0,5, "a", "aajo", (SUBR)posc_set, NULL, (SUBR)posc3aa }, { "lposcil3", S(LPOSC), TR, 5, "a", "kkkkjo", (SUBR)lposc_set, NULL,(SUBR)lposc3}, { "trigger", S(TRIG), 0,3, "k", "kkk", (SUBR)trig_set, (SUBR)trig, NULL }, { "sum", S(SUM), 0,4, "a", "y", NULL, NULL, (SUBR)sum }, { "product", S(SUM), 0,4, "a", "y", NULL, NULL, (SUBR)product }, { "resony", S(RESONY), 0,5, "a", "akkikooo", (SUBR)rsnsety, NULL, (SUBR)resony } }; int uggab_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/uggab.h000066400000000000000000000137441321653344700157440ustar00rootroot00000000000000#ifndef UGGAB_H #define UGGAB_H /* uggab.h: Copyright (C) 1998 Gabriel Maldonado, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /********************************************/ /* wrap and mirror UGs by Gabriel Maldonado */ /********************************************/ typedef struct { OPDS h; MYFLT *xdest, *xsig, *xlow, *xhigh; } WRAP; typedef struct { OPDS h; MYFLT *kout, *ksig, *kthreshold, *kmode; MYFLT old_sig; } TRIG; typedef struct { OPDS h; MYFLT *r, *val1, *val2, *point, *imin, *imax; MYFLT point_factor; } INTERPOL; typedef struct { OPDS h; MYFLT *out, *amp, *freq, *ift, *iphs; FUNC *ftp; int32 tablen; double tablenUPsr; double phs; } POSC; typedef struct { OPDS h; MYFLT *out, *amp, *freq, *kloop, *kend, *ift, *iphs; FUNC *ftp; int32 tablen; MYFLT fsr; double phs, looplength; } LPOSC; typedef struct { OPDS h; MYFLT *ar, *argums[VARGMAX]; } SUM; typedef struct { OPDS h; MYFLT *ar, *asig, *kcf, *kbw, *ord, *sep, *iflag, *iscl, *istor; int scale, loop; AUXCH aux; AUXCH buffer; MYFLT *yt1, *yt2; } RESONY; typedef struct { OPDS h; MYFLT *ar, *asig, *kincr ; double index; int32 sample_index; MYFLT value; } FOLD; typedef struct { OPDS h; MYFLT *out, *freq, *retrig, *iphase, *argums[VARGMAX]; MYFLT args[VARGMAX]; double phs; int nsegs; } LOOPSEG; /* Complexity of args leads to confusion */ typedef struct { MYFLT *start; MYFLT *type; MYFLT *time; } T3SEG; typedef struct { OPDS h; MYFLT *out, *freq, *retrig, *iphase; T3SEG argums[VARGMAX/3]; double phs; int nsegs; } LOOPTSEG; typedef struct { OPDS h; MYFLT *out, *kphase, *argums[VARGMAX]; MYFLT args[VARGMAX]; int nsegs; } LOOPSEGP; typedef struct { /* gab f1 */ OPDS h; MYFLT *kr, *ksig, *ktime; MYFLT current_val, current_time, incr, val_incremented, old_time; int flag; } LINETO; typedef struct { /* gab f1 */ OPDS h; MYFLT *kr, *ksig, *ktime, *ktrig; MYFLT current_val, current_time, incr, val_incremented, old_time; int flag; } LINETO2; typedef struct { OPDS h; MYFLT *out, *AverageAmp,*AverageFreq, *randAmountAmp, *randAmountFreq; MYFLT *ampMinRate, *ampMaxRate, *cpsMinRate, *cpsMaxRate, *ifn, *iphs; MYFLT xcpsAmpRate, xcpsFreqRate; double lphs, tablenUPkr; int32 tablen, phsAmpRate, phsFreqRate; MYFLT num1amp, num2amp, num1freq, num2freq, dfdmaxAmp, dfdmaxFreq; FUNC *ftp; } VIBRATO; typedef struct { OPDS h; MYFLT *out, *AverageAmp,*AverageFreq,*ifn; MYFLT xcpsAmpRate, xcpsFreqRate; double lphs, tablenUPkr; int32 tablen, phsAmpRate, phsFreqRate; MYFLT num1amp, num2amp, num1freq, num2freq, dfdmaxAmp, dfdmaxFreq; FUNC *ftp; } VIBR; typedef struct { OPDS h; MYFLT *out, *gamp, *amp1, *cps1, *amp2, *cps2, *amp3, *cps3, *option; int flag; int32 phs1,phs2,phs3; MYFLT num1a,num2a, dfdmax1, num1b,num2b, dfdmax2, num1c,num2c, dfdmax3; } JITTER2; typedef struct { OPDS h; MYFLT *ar, *amp, *cpsMin, *cpsMax; MYFLT xcps; int32 phs; int initflag; MYFLT num1, num2, dfdmax; } JITTER; typedef struct { OPDS h; MYFLT *ar, *amp, *cpsMin, *cpsMax; double si; double phs; int initflag, cod; MYFLT num0, num1, num2, df0, df1,c3, c2; } JITTERS; #define oneUp31Bit (4.656612875245796924105750827168e-10) #define randGab (MYFLT) ((double) \ (((csound->holdrand = csound->holdrand * 214013 + 2531011) >> 1) \ & 0x7fffffff) * oneUp31Bit) #define BiRandGab (MYFLT) ((double) \ (csound->holdrand = csound->holdrand * -214013 + 2531011) * oneUp31Bit) typedef struct { OPDS h; MYFLT *out, *tableNum; int pfn; FUNC *ftp; } DURAND; typedef struct { OPDS h; MYFLT *out, *min, *max, *tableNum; int pfn; FUNC *ftp; } CURAND; typedef struct { OPDS h; MYFLT *out, *min, *max; } RANGERAND; /* mode and fstval arguments added */ /* by Francois Pinot, jan. 2011 */ typedef struct { OPDS h; MYFLT *ar, *min, *max, *xcps, *mode, *fstval; int16 cpscod; int32 phs; MYFLT num1, num2, dfdmax; } RANDOMI; /* mode and fstval arguments added */ /* by Francois Pinot, jan. 2011 */ typedef struct { OPDS h; MYFLT *ar, *min, *max, *xcps, *mode, *fstval; int16 cpscod; int32 phs; MYFLT num1; } RANDOMH; typedef struct { OPDS h; MYFLT *ar, *rangeMin, *rangeMax, *cpsMin, *cpsMax; double si; double phs; int initflag, rangeMin_cod, rangeMax_cod; MYFLT num0, num1, num2, df0, df1,c3, c2; } RANDOM3; #endif /* UGGAB_H */ csound-6.10.0/Opcodes/ugmoss.c000066400000000000000000000566361321653344700161760ustar00rootroot00000000000000/* ugmoss.c: Copyright (C) 2001 William 'Pete' Moss This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* ugmoss.c */ #include "stdopcod.h" #include "ugmoss.h" #include "aops.h" #include /****************************************************************************** all this code was written by william 'pete' moss. no copyright, since it seems silly to copyright algorithms. do what you want with the code, and credit me if you get the chance ******************************************************************************/ /* rewritten code for dconv, includes speedup tip from Moore: Elements of Computer Music */ static int dconvset(CSOUND *csound, DCONV *p) { FUNC *ftp; p->len = (int)*p->isize; if (LIKELY((ftp = csound->FTnp2Find(csound, p->ifn)) != NULL)) { /* find table */ p->ftp = ftp; if ((unsigned)ftp->flen < p->len) p->len = ftp->flen; /* correct len if flen shorter */ } else { return csound->InitError(csound, Str("No table for dconv")); } if (p->sigbuf.auxp == NULL || p->sigbuf.size < (unsigned int)(p->len*sizeof(MYFLT))) csound->AuxAlloc(csound, p->len*sizeof(MYFLT), &p->sigbuf); else memset(p->sigbuf.auxp, '\0', p->len*sizeof(MYFLT)); p->curp = (MYFLT *)p->sigbuf.auxp; return OK; } static int dconv(CSOUND *csound, DCONV *p) { int32 i = 0; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 len = p->len; MYFLT *ar, *ain, *ftp, *startp, *endp, *curp; MYFLT sum; ain = p->ain; /* read saved values */ ar = p->ar; ftp = p->ftp->ftable; startp = (MYFLT *) p->sigbuf.auxp; endp = startp + len; curp = p->curp; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; ncurp = curp; /* save state */ return OK; } static int and_kk(CSOUND *csound, AOP *p) { int32 input1 = MYFLT2LRND(*p->a); int32 input2 = MYFLT2LRND(*p->b); *p->r = (MYFLT)(input1 & input2); return OK; } static int and_aa(CSOUND *csound, AOP *p) { MYFLT *r = p->r; MYFLT *in1 = p->a; MYFLT *in2 = p->b; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; int n, nsmps = CS_KSMPS; int32 input1, input2; if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { input1 = MYFLT2LRND(in1[n]); input2 = MYFLT2LRND(in2[n]); r[n] = (MYFLT) (input1 & input2); } return OK; } static int and_ak(CSOUND *csound, AOP *p) { MYFLT *r = p->r; MYFLT *in1 = p->a; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 input2 = MYFLT2LRND(*p->b), input1; if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { input1 = MYFLT2LRND(in1[n]); r[n] = (MYFLT)(input1 & input2); } return OK; } static int and_ka(CSOUND *csound, AOP *p) { MYFLT *r = p->r; MYFLT *in2 = p->b; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 input2, input1 = MYFLT2LRND(*p->a); if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { input2 = MYFLT2LRND(in2[n]); r[n] = (MYFLT)(input1 & input2); } return OK; } static int or_kk(CSOUND *csound, AOP *p) { int32 input1 = MYFLT2LRND(*p->a); int32 input2 = MYFLT2LRND(*p->b); *p->r = (MYFLT)(input1 | input2); return OK; } static int or_aa(CSOUND *csound, AOP *p) { MYFLT *r = p->r; MYFLT *in1 = p->a; MYFLT *in2 = p->b; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 input2, input1; if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { input1 = MYFLT2LRND(in1[n]); input2 = MYFLT2LRND(in2[n]); r[n] = (MYFLT)(input1 | input2); } return OK; } static int or_ak(CSOUND *csound, AOP *p) { MYFLT *r = p->r; MYFLT *in1 = p->a; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 input2 = MYFLT2LRND(*p->b), input1; if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { input1 = MYFLT2LRND(in1[n]); r[n] = (MYFLT)(input1 | input2); } return OK; } static int or_ka(CSOUND *csound, AOP *p) { MYFLT *r = p->r; MYFLT *in2 = p->b; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 input2, input1 = MYFLT2LRND(*p->a); if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { input2 = MYFLT2LRND(in2[n]); r[n] = (MYFLT)(input1 | input2); } return OK; } static int xor_kk(CSOUND *csound, AOP *p) { int32 input1 = MYFLT2LRND(*p->a); int32 input2 = MYFLT2LRND(*p->b); *p->r = (MYFLT)(input1 ^ input2); return OK; } static int xor_aa(CSOUND *csound, AOP *p) { MYFLT *r = p->r; MYFLT *in1 = p->a; MYFLT *in2 = p->b; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 input2, input1; if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = 0; n < nsmps; n++) { input1 = MYFLT2LRND(in1[n]); input2 = MYFLT2LRND(in2[n]); r[n] = (MYFLT)(input1 ^ input2); } return OK; } static int xor_ak(CSOUND *csound, AOP *p) { MYFLT *r = p->r; MYFLT *in1 = p->a; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 input2 = MYFLT2LRND(*p->b), input1; if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { input1 = MYFLT2LRND(in1[n]); r[n] = (MYFLT)(input1 ^ input2); } return OK; } static int xor_ka(CSOUND *csound, AOP *p) { MYFLT *r = p->r; MYFLT *in2 = p->b; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 input2, input1 = MYFLT2LRND(*p->a); if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { input2 = MYFLT2LRND(in2[n]); r[n] = (MYFLT)(input1 ^ input2); } return OK; } static int shift_left_kk(CSOUND *csound, AOP *p) { int32 input1 = MYFLT2LRND(*p->a); int input2 = (int) MYFLT2LRND(*p->b); *p->r = (MYFLT) (input1 << input2); return OK; } static int shift_left_aa(CSOUND *csound, AOP *p) { int32 input1, input2; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(offset)) memset(p->r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { input1 = MYFLT2LRND(p->a[n]); input2 = (int32) MYFLT2LRND(p->b[n]); p->r[n] = (MYFLT) (input1 << input2); } return OK; } static int shift_left_ak(CSOUND *csound, AOP *p) { int32 input1; int input2 = MYFLT2LRND(*p->b); uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(offset)) memset(p->r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { input1 = MYFLT2LRND(p->a[n]); p->r[n] = (MYFLT) (input1 << input2); } return OK; } static int shift_left_ka(CSOUND *csound, AOP *p) { int32 input1 = MYFLT2LRND(*p->a), input2; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(offset)) memset(p->r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { input2 = MYFLT2LRND(p->b[n]); p->r[n] = (MYFLT) (input1 << input2); } return OK; } static int shift_right_kk(CSOUND *csound, AOP *p) { int32 input1 = MYFLT2LRND(*p->a); int input2 = (int) MYFLT2LRND(*p->b); *p->r = (MYFLT) (input1 >> input2); return OK; } static int shift_right_aa(CSOUND *csound, AOP *p) { int32 input1, input2; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(offset)) memset(p->r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { input1 = MYFLT2LRND(p->a[n]); input2 = (int) MYFLT2LRND(p->b[n]); p->r[n] = (MYFLT) (input1 >> input2); } return OK; } static int shift_right_ak(CSOUND *csound, AOP *p) { int32 input1; int32 input2 = MYFLT2LRND(*p->b); uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(offset)) memset(p->r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { input1 = MYFLT2LRND(p->a[n]); p->r[n] = (MYFLT) (input1 >> input2); } return OK; } static int shift_right_ka(CSOUND *csound, AOP *p) { int32 input1 = MYFLT2LRND(*p->a), input2; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(offset)) memset(p->r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { input2 = MYFLT2LRND(p->b[n]); p->r[n] = (MYFLT) (input1 >> input2); } return OK; } static int not_k(CSOUND *csound, AOP *p) /* Added for completeness by JPff */ { int32 input1 = MYFLT2LRND(*p->a); *p->r = (MYFLT)(~input1); return OK; } static int not_a(CSOUND *csound, AOP *p) { MYFLT *r = p->r; MYFLT *in1 = p->a; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int32 input1; if (UNLIKELY(offset)) memset(r, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&r[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { input1 = MYFLT2LRND(in1[n]); r[n] = (MYFLT)(~input1); } return OK; } /* all the vcomb and valpass stuff adapted from comb() and alpass() with additional insight from me (petemoss@petemoss.org) */ static int vcombset(CSOUND *csound, VCOMB *p) { int32 lpsiz, nbytes; if (*p->insmps != FL(0.0)) { if (UNLIKELY((lpsiz = MYFLT2LONG(*p->imaxlpt)) <= 0)) { return csound->InitError(csound, Str("illegal loop time")); } } else if (UNLIKELY((lpsiz = (int32)(*p->imaxlpt * CS_ESR)) <= 0)) { return csound->InitError(csound, Str("illegal loop time")); } nbytes = lpsiz * sizeof(MYFLT); if (p->auxch.auxp == NULL || nbytes != (int)p->auxch.size) { csound->AuxAlloc(csound, (size_t)nbytes, &p->auxch); p->pntr = (MYFLT *) p->auxch.auxp; if (UNLIKELY(p->pntr==NULL)) { return csound->InitError(csound, Str("could not allocate memory")); } } else if (!(*p->istor)) { int32 *fp = (int32 *) p->auxch.auxp; p->pntr = (MYFLT *) fp; memset(p->pntr, 0, nbytes); /* do /\* Seems to assume sizeof(int32)=sizeof(MYFLT) *\/ */ /* *fp++ = 0; */ /* while (--lpsiz); */ } p->rvt = FL(0.0); p->lpt = FL(0.0); p->g = FL(0.0); p->lpta = IS_ASIG_ARG(p->xlpt) ? 1 : 0; if (*p->insmps == 0) p->maxlpt = *p->imaxlpt * CS_ESR; else p->maxlpt = *p->imaxlpt; return OK; } static int vcomb(CSOUND *csound, VCOMB *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; uint32 xlpt, maxlpt = (uint32)p->maxlpt; MYFLT *ar, *asig, *rp, *endp, *startp, *wp, *lpt; MYFLT g = p->g; if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; ar = p->ar; asig = p->asig; endp = (MYFLT *) p->auxch.endp; startp = (MYFLT *) p->auxch.auxp; wp = p->pntr; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } if (p->lpta) { /* if xlpt is a-rate */ lpt = p->xlpt; for (n=offset; ninsmps != 0) ? *lpt : *lpt * CS_ESR); if (xlpt > maxlpt) xlpt = maxlpt; if ((rp = wp - xlpt) < startp) rp += maxlpt; if ((p->rvt != *p->krvt) || (p->lpt != *lpt)) { p->rvt = *p->krvt, p->lpt = *lpt; g = p->g = POWER(FL(0.001), (p->lpt / p->rvt)); } lpt++; ar[n] = *rp++; *wp++ = (ar[n] * g) + asig[n]; if (wp >= endp) wp = startp; if (rp >= endp) rp = startp; } } else { /* if xlpt is k-rate */ xlpt = (uint32) ((*p->insmps != 0) ? *p->xlpt : *p->xlpt * CS_ESR); if (xlpt > maxlpt) xlpt = maxlpt; if ((rp = wp - xlpt) < startp) rp += maxlpt; if ((p->rvt != *p->krvt) || (p->lpt != *p->xlpt)) { p->rvt = *p->krvt, p->lpt = *p->xlpt; g = p->g = POWER(FL(0.001), (p->lpt / p->rvt)); } for (n=offset; n= endp) wp = startp; if (rp >= endp) rp = startp; } } p->pntr = wp; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("vcomb: not initialised")); } static int valpass(CSOUND *csound, VCOMB *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; uint32 xlpt, maxlpt = (uint32)p->maxlpt; MYFLT *ar, *asig, *rp, *startp, *endp, *wp, *lpt; MYFLT y, z, g = p->g; if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; ar = p->ar; asig = p->asig; endp = (MYFLT *) p->auxch.endp; startp = (MYFLT *) p->auxch.auxp; wp = p->pntr; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } if (p->lpta) { /* if xlpt is a-rate */ lpt = p->xlpt; for (n=offset; ninsmps != 0) ? lpt[n] : lpt[n] * CS_ESR); if (xlpt > maxlpt) xlpt = maxlpt; if ((rp = wp - xlpt) < startp) rp += maxlpt; if ((p->rvt != *p->krvt) || (p->lpt != lpt[n])) { p->rvt = *p->krvt, p->lpt = lpt[n]; g = p->g = POWER(FL(0.001), (p->lpt / p->rvt)); } y = *rp++; *wp++ = z = y * g + asig[n]; ar[n] = y - g * z; if (wp >= endp) wp = startp; if (rp >= endp) rp = startp; } } else { /* if xlpt is k-rate */ xlpt = (uint32) ((*p->insmps != 0) ? *p->xlpt : *p->xlpt * CS_ESR); if (xlpt > maxlpt) xlpt = maxlpt; if ((rp = wp - xlpt) < startp) rp += maxlpt; if ((p->rvt != *p->krvt) || (p->lpt != *p->xlpt)) { p->rvt = *p->krvt, p->lpt = *p->xlpt; g = p->g = POWER(FL(0.001), (p->lpt / p->rvt)); } for (n=offset; n= endp) wp = startp; if (rp >= endp) rp = startp; } } p->pntr = wp; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("valpass: not initialised")); } static int ftmorfset(CSOUND *csound, FTMORF *p) { FUNC *ftp; int j = 0; unsigned int len; /* make sure resfn exists and set it up */ if (LIKELY((ftp = csound->FTnp2Find(csound, p->iresfn)) != NULL)) { p->resfn = ftp, len = p->resfn->flen; } else { return csound->InitError(csound, Str("iresfn for ftmorf does not exist")); } /* make sure ftfn exists and set it up */ if (LIKELY((ftp = csound->FTnp2Find(csound, p->iftfn)) != NULL)) { p->ftfn = ftp; } else { return csound->InitError(csound, Str("iftfn for ftmorf does not exist")); } do { /* make sure tables in ftfn exist and are right size*/ if (LIKELY((ftp = csound->FTnp2Find(csound, p->ftfn->ftable + j)) != NULL)) { if (UNLIKELY((unsigned int)ftp->flen != len)) { return csound->InitError(csound, Str("table in iftfn for ftmorf wrong size")); } } else { return csound->InitError(csound, Str("table in iftfn for ftmorf " "does not exist")); } } while (++j < (int)p->ftfn->flen); p->len = len; p->ftndx = -FL(1.0); return OK; } static int ftmorf(CSOUND *csound, FTMORF *p) { unsigned int j = 0; int i; MYFLT f; FUNC *ftp1, *ftp2; if (*p->kftndx >= p->ftfn->flen) *p->kftndx = (MYFLT)(p->ftfn->flen - 1); i = (int)*p->kftndx; f = *p->kftndx - i; if (p->ftndx != *p->kftndx) { p->ftndx = *p->kftndx; ftp1 = csound->FTnp2Find(csound, p->ftfn->ftable + i++); ftp2 = csound->FTnp2Find(csound, p->ftfn->ftable + i--); do { *(p->resfn->ftable + j) = (*(ftp1->ftable + j) * (1-f)) + (*(ftp2->ftable + j) * f); } while (++j < p->len); } return OK; } /* end of ugmoss.c */ #define S(x) sizeof(x) static OENTRY localops[] = { { "dconv", S(DCONV), TR, 5, "a", "aii", (SUBR)dconvset, NULL, (SUBR)dconv }, { "vcomb", S(VCOMB), 0,5, "a", "akxioo", (SUBR)vcombset, NULL, (SUBR)vcomb }, { "valpass", S(VCOMB),0,5, "a", "akxioo", (SUBR)vcombset, NULL, (SUBR)valpass }, { "ftmorf", S(FTMORF),TR, 3, "", "kii", (SUBR)ftmorfset, (SUBR)ftmorf, }, { "##and.ii", S(AOP), 0,1, "i", "ii", (SUBR)and_kk }, { "##and.kk", S(AOP), 0,2, "k", "kk", NULL, (SUBR)and_kk }, { "##and.ka", S(AOP), 0,4, "a", "ka", NULL, NULL, (SUBR)and_ka }, { "##and.ak", S(AOP), 0,4, "a", "ak", NULL, NULL, (SUBR)and_ak }, { "##and.aa", S(AOP), 0,4, "a", "aa", NULL, NULL, (SUBR)and_aa }, { "##or.ii", S(AOP), 0,1, "i", "ii", (SUBR)or_kk }, { "##or.kk", S(AOP), 0,2, "k", "kk", NULL, (SUBR)or_kk }, { "##or.ka", S(AOP), 0,4, "a", "ka", NULL, NULL, (SUBR)or_ka }, { "##or.ak", S(AOP), 0,4, "a", "ak", NULL, NULL, (SUBR)or_ak }, { "##or.aa", S(AOP), 0,4, "a", "aa", NULL, NULL, (SUBR)or_aa }, { "##xor.ii", S(AOP), 0,1, "i", "ii", (SUBR)xor_kk }, { "##xor.kk", S(AOP), 0,2, "k", "kk", NULL, (SUBR)xor_kk }, { "##xor.ka", S(AOP), 0,4, "a", "ka", NULL, NULL, (SUBR)xor_ka }, { "##xor.ak", S(AOP), 0,4, "a", "ak", NULL, NULL, (SUBR)xor_ak }, { "##xor.aa", S(AOP), 0,4, "a", "aa", NULL, NULL, (SUBR)xor_aa }, { "##not.i", S(AOP), 0,1, "i", "i", (SUBR)not_k }, { "##not.k", S(AOP), 0,2, "k", "k", NULL, (SUBR)not_k }, { "##not.a", S(AOP), 0,4, "a", "a", NULL, NULL, (SUBR)not_a }, { "##shl.ii", S(AOP), 0,1, "i", "ii", (SUBR) shift_left_kk }, { "##shl.kk", S(AOP), 0,2, "k", "kk", NULL, (SUBR) shift_left_kk }, { "##shl.ka", S(AOP), 0,4, "a", "ka", NULL, NULL, (SUBR) shift_left_ka }, { "##shl.ak", S(AOP), 0,4, "a", "ak", NULL, NULL, (SUBR) shift_left_ak }, { "##shl.aa", S(AOP), 0,4, "a", "aa", NULL, NULL, (SUBR) shift_left_aa }, { "##shr.ii", S(AOP), 0,1, "i", "ii", (SUBR) shift_right_kk }, { "##shr.kk", S(AOP), 0,2, "k", "kk", NULL, (SUBR) shift_right_kk }, { "##shr.ka", S(AOP), 0,4, "a", "ka", NULL, NULL, (SUBR) shift_right_ka }, { "##shr.ak", S(AOP), 0,4, "a", "ak", NULL, NULL, (SUBR) shift_right_ak }, { "##shr.aa", S(AOP), 0,4, "a", "aa", NULL, NULL, (SUBR) shift_right_aa } }; int ugmoss_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/ugmoss.h000066400000000000000000000030741321653344700161670ustar00rootroot00000000000000/* ugmoss.h: Copyright (C) 2001 Willian 'Pete' Moss This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* ugmoss.h */ typedef struct { OPDS h; MYFLT *ar, *ain, *isize, *ifn; MYFLT *curp; FUNC *ftp; AUXCH sigbuf; unsigned int len; } DCONV; typedef struct { OPDS h; MYFLT *ar, *asig, *krvt, *xlpt, *imaxlpt, *istor, *insmps; MYFLT g, rvt, lpt, *pntr, maxlpt; AUXCH auxch; int16 lpta; } VCOMB; typedef struct { OPDS h; MYFLT *kftndx, *iftfn, *iresfn; FUNC *ftfn, *resfn; MYFLT ftndx; unsigned int len; } FTMORF; /* end ugmoss.h */ csound-6.10.0/Opcodes/ugnorman.c000066400000000000000000003106031321653344700164720ustar00rootroot00000000000000/* ugnorman.c: This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* ats-csound version 0.1 * Mon May 10 19:44:46 PDT 2004 * ATScsound Ugens, adapted by Alex Norman (2003) * from the phase vocoder csound code by Richard Karpen * If you find bugs contact me at alexnorman@users.sourceforge.net Some basic info: ATSinfo: idata ATSinfo iatsfile, idataloc read functions: kfreq, kamp ATSread ktimepnt, ifile, ipartial kenergy ATSreadnz ktimepnt, ifile, iband add functions: ar ATSadd ktimepnt, kfmod, iatsfile, ifn, ipartials \ [, ipartialoffset, ipartialincr, igatefn] ar ATSaddnz ktimepnt, iatsfile, ibands \ [, ibandoffset, ibandincr] sinnoi function: ar ATSsinnoi ktimepnt, ksinlev, knzlev, kfreqscale, \ iatsfile, ipartials[, ipartialoffset, ipartialincr] buf/cross functions: ATSbufread ktimepnt, kfmod, iatsfile, ipartials \ [, ipartialoffset, ipartialincr] ar ATScross ktimepnt, kfmod, iatsfile, ifn, kmyamp, \ kbufamp, ipartials[, ipartialoffset, ipartialincr] kfreq, kamp ATSpartialtap ipartialnum kamp ATSinterpread kfreq */ //was frIndx > p->maxFr #define OUT_OF_FRAMES (frIndx >= p->maxFr+1) #include "ugnorman.h" #include #include "interlocks.h" #define ATSA_NOISE_VARIANCE 0.04 #define ATSA_CRITICAL_BAND_EDGES \ { 0.0, 100.0, 200.0, 300.0, 400.0, 510.0, 630.0, 770.0, 920.0, 1080.0, \ 1270.0, 1480.0, 1720.0, 2000.0, 2320.0, 2700.0, 3150.0, 3700.0, \ 4400.0, 5300.0, 6400.0, 7700.0, 9500.0, 12000.0, 15500.0, 20000.0 } /* static variables used for atsbufread and atsbufreadnz */ static inline ATSBUFREAD **get_atsbufreadaddrp(CSOUND *csound) { return &(((STDOPCOD_GLOBALS*) csound->stdOp_Env)->atsbufreadaddr); } /* byte swaps a double */ static CS_PURE double bswap(const double *swap_me) { double d; const unsigned char *p1 = (const unsigned char *) swap_me; unsigned char *p2 = (unsigned char *) &d; p2[0] = p1[7]; p2[1] = p1[6]; p2[2] = p1[5]; p2[3] = p1[4]; p2[4] = p1[3]; p2[5] = p1[2]; p2[6] = p1[1]; p2[7] = p1[0]; return d; } /* load ATS file into memory; returns "is swapped" boolean, or -1 on error */ static int load_atsfile(CSOUND *csound, void *p, MEMFIL **mfp, char *fname, void *name_arg, int istring) { char opname[64]; STDOPCOD_GLOBALS *pp; ATSSTRUCT *atsh; int i; strncpy(opname, csound->GetOpcodeName(p), 63); /* opcode name */ opname[63]='\0'; for (i = 0; opname[i] != '\0'; i++) opname[i] = toupper(opname[i]); /* converted to upper case */ /* copy in ats file name */ if (istring) strncpy(fname, ((STRINGDAT*)name_arg)->data,MAXNAME-1) ; else { if (csound->ISSTRCOD(*((MYFLT*)name_arg))) strncpy(fname,get_arg_string(csound, *((MYFLT*)name_arg)),MAXNAME-1); else csound->strarg2name(csound, fname, name_arg, "ats.",0); } /* load memfile */ if (UNLIKELY((*mfp = csound->ldmemfile2withCB(csound, fname, CSFTYPE_ATS, NULL)) == NULL)) { return csound->InitError(csound, Str("%s: Ats file %s not read (does it exist?)"), opname, fname); } atsh = (ATSSTRUCT*) (*mfp)->beginp; /* make sure that this is an ats file */ if (atsh->magic == 123.0) return 0; /* check to see if it is byteswapped */ if (UNLIKELY((int) bswap(&(atsh->magic)) != 123)) { return csound->InitError(csound, Str("%s: either %s is not an ATS file " "or the byte endianness is wrong"), opname, fname); } pp = (STDOPCOD_GLOBALS*) csound->stdOp_Env; if (pp->swapped_warning) return 1; csound->Warning(csound, Str("%s: %s is byte-swapped\n" "\tno future byte-swapping warnings will be given, " "byte-swapped files\n\twill not result in different " "audio, but they may slow down processing."), opname, fname); pp->swapped_warning = 1; return 1; } /* ats info simply reads data out of the header of an atsfile. (i-rate) */ static int atsinfo_S(CSOUND *csound, ATSINFO *p) { char atsfilname[MAXNAME]; ATSSTRUCT *atsh; MEMFIL *memfile = NULL; double *ret_data; /* data to return */ int swapped = 0; /* flag to indicate if data needs to be swapped */ /* load memfile */ swapped = load_atsfile(csound, p, &memfile, atsfilname, p->ifileno, 1); if (UNLIKELY(swapped < 0)) return NOTOK; atsh = (ATSSTRUCT*) memfile->beginp; switch ((int) MYFLT2LRND(*p->ilocation)) { case 0: ret_data = &(atsh->sampr); break; case 1: ret_data = &(atsh->frmsz); break; case 2: ret_data = &(atsh->winsz); break; case 3: ret_data = &(atsh->npartials); break; case 4: ret_data = &(atsh->nfrms); break; case 5: ret_data = &(atsh->ampmax); break; case 6: ret_data = &(atsh->freqmax); break; case 7: ret_data = &(atsh->dur); break; case 8: ret_data = &(atsh->type); break; default: return csound->InitError(csound, Str("ATSINFO: location is out of bounds: " "0-8 are the only possible selections")); } /* if not swapped then just return the data */ if (!swapped) { *p->ireturn = (MYFLT) *ret_data; return OK; } /* otherwise do byteswapping */ *p->ireturn = (MYFLT) bswap(ret_data); return OK; } static int atsinfo(CSOUND *csound, ATSINFO *p) { char atsfilname[MAXNAME]; ATSSTRUCT *atsh; MEMFIL *memfile = NULL; double *ret_data; /* data to return */ int swapped = 0; /* flag to indicate if data needs to be swapped */ /* load memfile */ swapped = load_atsfile(csound, p, &memfile, atsfilname, p->ifileno, 0); if (UNLIKELY(swapped < 0)) return NOTOK; atsh = (ATSSTRUCT*) memfile->beginp; switch ((int) MYFLT2LRND(*p->ilocation)) { case 0: ret_data = &(atsh->sampr); break; case 1: ret_data = &(atsh->frmsz); break; case 2: ret_data = &(atsh->winsz); break; case 3: ret_data = &(atsh->npartials); break; case 4: ret_data = &(atsh->nfrms); break; case 5: ret_data = &(atsh->ampmax); break; case 6: ret_data = &(atsh->freqmax); break; case 7: ret_data = &(atsh->dur); break; case 8: ret_data = &(atsh->type); break; default: return csound->InitError(csound, Str("ATSINFO: location is out of bounds: " "0-8 are the only possible selections")); } /* if not swapped then just return the data */ if (!swapped) { *p->ireturn = (MYFLT) *ret_data; return OK; } /* otherwise do byteswapping */ *p->ireturn = (MYFLT) bswap(ret_data); return OK; } /************************************************************/ /********* ATSREAD ***********************************/ /************************************************************/ static void FetchPartial(ATSREAD *p, MYFLT *buf, MYFLT position) { MYFLT frac; /* the distance in time we are between frames */ int frame; /* the number of the first frame */ double *frm_1, *frm_2; /* a pointer to frame 1 and frame 2 */ double frm1amp, frm1freq, frm2amp, frm2freq; frame = (int) position; frm_1 = p->datastart + p->frmInc * frame + p->partialloc; /* if we are using the data from the last frame */ /* we should not try to interpolate */ if (frame == p->maxFr) { if (p->swapped == 1) { buf[0] = (MYFLT) bswap(frm_1); /* calc amplitude */ buf[1] = (MYFLT) bswap(frm_1 + 1); /* calc freq */ } else { buf[0] = (MYFLT) *frm_1; /* calc amplitude */ buf[1] = (MYFLT) *(frm_1 + 1); /* calc freq */ } return; } frm_2 = frm_1 + p->frmInc; frac = position - frame; /* byte swap if needed */ if (p->swapped == 1) { frm1amp = bswap(frm_1); frm2amp = bswap(frm_2); frm1freq = bswap(frm_1 + 1); frm2freq = bswap(frm_2 + 1); } else { frm1amp = *frm_1; frm2amp = *frm_2; frm1freq = *(frm_1 + 1); frm2freq = *(frm_2 + 1); } buf[0] = (MYFLT) (frm1amp + frac * (frm2amp - frm1amp)); /* calc amp. */ buf[1] = (MYFLT) (frm1freq + frac * (frm2freq - frm1freq)); /* calc freq */ } static int atsreadset(CSOUND *csound, ATSREAD *p) { char atsfilname[MAXNAME]; ATSSTRUCT *atsh; int n_partials; int type; /* load memfile */ p->swapped = load_atsfile(csound, p, &(p->atsmemfile), atsfilname, p->ifileno, 0); if (UNLIKELY(p->swapped < 0)) return NOTOK; atsh = (ATSSTRUCT*) p->atsmemfile->beginp; /* byte swap if necessary */ if (p->swapped == 1) { p->maxFr = (int) bswap(&atsh->nfrms) - 1; p->timefrmInc = bswap(&atsh->nfrms) / bswap(&atsh->dur); n_partials = (int) bswap(&atsh->npartials); type = (int) bswap(&atsh->type); } else { p->maxFr = (int) atsh->nfrms - 1; p->timefrmInc = atsh->nfrms / atsh->dur; n_partials = (int) atsh->npartials; type = (int) atsh->type; } /* check to see if partial is valid */ if (UNLIKELY((int) (*p->ipartial) > n_partials || (int) (*p->ipartial) <= 0)) { return csound->InitError(csound, Str("ATSREAD: partial %i out of range, " "max allowed is %i"), (int) (*p->ipartial), n_partials); } /* point the data pointer to the correct partial */ p->datastart = (double *) (p->atsmemfile->beginp + sizeof(ATSSTRUCT)); switch (type) { case 1: p->partialloc = 1 + 2 * (*p->ipartial - 1); p->frmInc = n_partials * 2 + 1; break; case 2: p->partialloc = 1 + 3 * (*p->ipartial - 1); p->frmInc = n_partials * 3 + 1; break; case 3: p->partialloc = 1 + 2 * (*p->ipartial - 1); p->frmInc = n_partials * 2 + 26; break; case 4: p->partialloc = 1 + 3 * (*p->ipartial - 1); p->frmInc = n_partials * 3 + 26; break; default: return csound->InitError(csound, Str("Type not implemented")); } /* flag set to reduce the amount of warnings sent out */ /* for time pointer out of range */ p->prFlg = 1; /* true */ return OK; } static int atsreadset_S(CSOUND *csound, ATSREAD *p) { char atsfilname[MAXNAME]; ATSSTRUCT *atsh; int n_partials; int type; /* load memfile */ p->swapped = load_atsfile(csound, p, &(p->atsmemfile), atsfilname, p->ifileno, 1); if (UNLIKELY(p->swapped < 0)) return NOTOK; atsh = (ATSSTRUCT*) p->atsmemfile->beginp; /* byte swap if necessary */ if (p->swapped == 1) { p->maxFr = (int) bswap(&atsh->nfrms) - 1; p->timefrmInc = bswap(&atsh->nfrms) / bswap(&atsh->dur); n_partials = (int) bswap(&atsh->npartials); type = (int) bswap(&atsh->type); } else { p->maxFr = (int) atsh->nfrms - 1; p->timefrmInc = atsh->nfrms / atsh->dur; n_partials = (int) atsh->npartials; type = (int) atsh->type; } /* check to see if partial is valid */ if (UNLIKELY((int) (*p->ipartial) > n_partials || (int) (*p->ipartial) <= 0)) { return csound->InitError(csound, Str("ATSREAD: partial %i out of range, " "max allowed is %i"), (int) (*p->ipartial), n_partials); } /* point the data pointer to the correct partial */ p->datastart = (double *) (p->atsmemfile->beginp + sizeof(ATSSTRUCT)); switch (type) { case 1: p->partialloc = 1 + 2 * (*p->ipartial - 1); p->frmInc = n_partials * 2 + 1; break; case 2: p->partialloc = 1 + 3 * (*p->ipartial - 1); p->frmInc = n_partials * 3 + 1; break; case 3: p->partialloc = 1 + 2 * (*p->ipartial - 1); p->frmInc = n_partials * 2 + 26; break; case 4: p->partialloc = 1 + 3 * (*p->ipartial - 1); p->frmInc = n_partials * 3 + 26; break; default: return csound->InitError(csound, Str("Type not implemented")); } /* flag set to reduce the amount of warnings sent out */ /* for time pointer out of range */ p->prFlg = 1; /* true */ return OK; } static int atsread(CSOUND *csound, ATSREAD *p) { MYFLT frIndx; MYFLT buf[2]; if (UNLIKELY(p->atsmemfile == NULL)) goto err1; if ((frIndx = *(p->ktimpnt) * p->timefrmInc) < FL(0.0)) { frIndx = FL(0.0); if (UNLIKELY(p->prFlg)) { p->prFlg = 0; /* set to false */ csound->Warning(csound, Str("ATSREAD: only positive time pointer " "values allowed, setting to zero\n")); } } else if (OUT_OF_FRAMES) { /* if we are trying to get frames past where we have data */ frIndx = (MYFLT) p->maxFr; if (UNLIKELY(p->prFlg)) { p->prFlg = 0; /* set to false */ csound->Warning(csound, Str("ATSREAD: timepointer out of range, " "truncated to last frame\n")); } } else p->prFlg = 1; FetchPartial(p, buf, frIndx); *p->kamp = buf[0]; *p->kfreq = buf[1]; return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("ATSREAD: not initialised")); } /* * ATSREADNOISE */ static MYFLT FetchNzBand(ATSREADNZ *p, MYFLT position) { MYFLT frac; /* the distance in time we are between frames */ int frame; /* the time of the first frame */ double *frm_1, *frm_2; double frm1val, frm2val; frame = (int) position; frm_1 = p->datastart + p->frmInc * frame + p->nzbandloc; frm1val = (p->swapped == 1) ? bswap(frm_1) : *frm_1; /* if we are using the data from the last frame */ /* we should not try to interpolate */ if (UNLIKELY(frame == p->maxFr)) return (MYFLT) frm1val; frm_2 = frm_1 + p->frmInc; frac = position - frame; frm2val = (p->swapped == 1) ? bswap(frm_2) : *frm_2; return (MYFLT) (frm1val + frac * (frm2val - frm1val)); /* calc energy */ } static int atsreadnzset(CSOUND *csound, ATSREADNZ *p) { char atsfilname[MAXNAME]; ATSSTRUCT *atsh; int n_partials; int type; /* load memfile */ p->swapped = load_atsfile(csound, p, &(p->atsmemfile), atsfilname, p->ifileno, 0); if (UNLIKELY(p->swapped < 0)) return NOTOK; atsh = (ATSSTRUCT*) p->atsmemfile->beginp; /* byte swap if necessary */ if (p->swapped == 1) { p->maxFr = (int) bswap(&atsh->nfrms) - 1; p->timefrmInc = bswap(&atsh->nfrms) / bswap(&atsh->dur); n_partials = (int) bswap(&atsh->npartials); type = (int) bswap(&atsh->type); } else { p->maxFr = (int) atsh->nfrms - 1; p->timefrmInc = atsh->nfrms / atsh->dur; n_partials = (int) atsh->npartials; type = (int) atsh->type; } /* point the data pointer to the correct partial */ p->datastart = (double *) (p->atsmemfile->beginp + sizeof(ATSSTRUCT)); /* check to see if band is valid */ if (UNLIKELY((int) (*p->inzbin) > 25 || (int) (*p->inzbin) <= 0)) { return csound->InitError(csound, Str("ATSREADNZ: band %i out of range, " "1-25 are the valid band values"), (int) (*p->inzbin)); } switch (type) { case 3: /* get past the partial data to the noise */ p->nzbandloc = (int) (2 * n_partials + *p->inzbin); p->frmInc = n_partials * 2 + 26; break; case 4: p->nzbandloc = (int) (3 * n_partials + *p->inzbin); p->frmInc = n_partials * 3 + 26; break; default: return csound->InitError(csound, Str("ATSREADNZ: Type either not implemented " "or does not contain noise")); } /* flag set to reduce the amount of warnings sent out */ /* for time pointer out of range */ p->prFlg = 1; /* true */ return OK; } static int atsreadnzset_S(CSOUND *csound, ATSREADNZ *p) { char atsfilname[MAXNAME]; ATSSTRUCT *atsh; int n_partials; int type; /* load memfile */ p->swapped = load_atsfile(csound, p, &(p->atsmemfile), atsfilname, p->ifileno, 1); if (UNLIKELY(p->swapped < 0)) return NOTOK; atsh = (ATSSTRUCT*) p->atsmemfile->beginp; /* byte swap if necessary */ if (p->swapped == 1) { p->maxFr = (int) bswap(&atsh->nfrms) - 1; p->timefrmInc = bswap(&atsh->nfrms) / bswap(&atsh->dur); n_partials = (int) bswap(&atsh->npartials); type = (int) bswap(&atsh->type); } else { p->maxFr = (int) atsh->nfrms - 1; p->timefrmInc = atsh->nfrms / atsh->dur; n_partials = (int) atsh->npartials; type = (int) atsh->type; } /* point the data pointer to the correct partial */ p->datastart = (double *) (p->atsmemfile->beginp + sizeof(ATSSTRUCT)); /* check to see if band is valid */ if (UNLIKELY((int) (*p->inzbin) > 25 || (int) (*p->inzbin) <= 0)) { return csound->InitError(csound, Str("ATSREADNZ: band %i out of range, " "1-25 are the valid band values"), (int) (*p->inzbin)); } switch (type) { case 3: /* get past the partial data to the noise */ p->nzbandloc = (int) (2 * n_partials + *p->inzbin); p->frmInc = n_partials * 2 + 26; break; case 4: p->nzbandloc = (int) (3 * n_partials + *p->inzbin); p->frmInc = n_partials * 3 + 26; break; default: return csound->InitError(csound, Str("ATSREADNZ: Type either not implemented " "or does not contain noise")); } /* flag set to reduce the amount of warnings sent out */ /* for time pointer out of range */ p->prFlg = 1; /* true */ return OK; } static int atsreadnz(CSOUND *csound, ATSREADNZ *p) { MYFLT frIndx; if (UNLIKELY(p->atsmemfile == NULL)) goto err1; /* make sure we have not over steped the bounds of the data */ if ((frIndx = *(p->ktimpnt) * p->timefrmInc) < FL(0.0)) { frIndx = FL(0.0); if (UNLIKELY(p->prFlg)) { p->prFlg = 0; /* set to false */ csound->Warning(csound, Str("ATSREADNZ: only positive time pointer " "values allowed, setting to zero\n")); } } else if (OUT_OF_FRAMES) { /* if we are trying to get frames past where we have data */ frIndx = (MYFLT) p->maxFr; if (UNLIKELY(p->prFlg)) { p->prFlg = 0; /* set to false */ csound->Warning(csound, Str("ATSREADNZ: timepointer out of range, " "truncated to last frame\n")); } } else p->prFlg = 1; *p->kenergy = FetchNzBand(p, frIndx); return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("ATSREADNZ: not initialised")); } /* * ATSADD */ static void FetchADDPartials(ATSADD *, ATS_DATA_LOC *, MYFLT); static void AtsAmpGate(ATS_DATA_LOC *, int, FUNC *, double); static int atsaddset(CSOUND *csound, ATSADD *p) { char atsfilname[MAXNAME]; ATSSTRUCT *atsh; FUNC *ftp, *AmpGateFunc; int memsize, n_partials, type; /* set up function table for synthesis */ if (UNLIKELY((ftp = csound->FTFind(csound, p->ifn)) == NULL)) { return csound->InitError(csound, Str("ATSADD: Function table number " "for synthesis waveform not valid")); } p->ftp = ftp; /* set up gate function table */ if (*p->igatefun > FL(0.0)) { if (UNLIKELY((AmpGateFunc = csound->FTFind(csound, p->igatefun)) == NULL)) { return csound->InitError(csound, Str("ATSADD: Gate Function table " "number not valid")); } else p->AmpGateFunc = AmpGateFunc; } /* load memfile */ p->swapped = load_atsfile(csound, p, &(p->atsmemfile), atsfilname, p->ifileno, 0); if (UNLIKELY(p->swapped < 0)) return NOTOK; atsh = (ATSSTRUCT*) p->atsmemfile->beginp; /* calculate how much memory we have to allocate for this */ memsize = (int) (*p->iptls) * sizeof(ATS_DATA_LOC) + (int) (*p->iptls) * sizeof(double) + (int) (*p->iptls) * sizeof(MYFLT); /* allocate space if we need it */ /* need room for a buffer and an array of oscillator phase increments */ if (p->auxch.auxp == NULL || p->auxch.size < (unsigned int)memsize) csound->AuxAlloc(csound, (size_t) memsize, &p->auxch); /* set up the buffer, phase, etc. */ p->buf = (ATS_DATA_LOC *) (p->auxch.auxp); p->oscphase = (double *) (p->buf + (int) (*p->iptls)); p->oldamps = (MYFLT *) (p->oscphase + (int) (*p->iptls)); /* byte swap if necessary */ if (p->swapped == 1) { p->maxFr = (int) bswap(&atsh->nfrms) - 1; p->timefrmInc = bswap(&atsh->nfrms) / bswap(&atsh->dur); n_partials = (int) bswap(&atsh->npartials); p->MaxAmp = bswap(&atsh->ampmax); /* store the maxium amplitude */ type = (int) bswap(&atsh->type); } else { p->maxFr = (int) atsh->nfrms - 1; p->timefrmInc = atsh->nfrms / atsh->dur; n_partials = (int) atsh->npartials; p->MaxAmp = atsh->ampmax; /* store the maxium amplitude */ type = (int) atsh->type; } /* make sure partials are in range */ if (UNLIKELY((int) (*p->iptloffset + *p->iptls * *p->iptlincr) > n_partials || (int) (*p->iptloffset) < 0)) { return csound->InitError(csound, Str("ATSADD: Partial(s) out of range, " "max partial allowed is %i"), n_partials); } /* get a pointer to the beginning of the data */ p->datastart = (double *) (p->atsmemfile->beginp + sizeof(ATSSTRUCT)); /* get increments for the partials */ switch (type) { case 1: p->firstpartial = 1 + 2 * (int)(*p->iptloffset); p->partialinc = 2 * (int) (*p->iptlincr); p->frmInc = n_partials * 2 + 1; break; case 2: p->firstpartial = 1 + 3 * (int)(*p->iptloffset); p->partialinc = 3 * (int) (*p->iptlincr); p->frmInc = n_partials * 3 + 1; break; case 3: p->firstpartial = 1 + 2 * (int)(*p->iptloffset); p->partialinc = 2 * (int) (*p->iptlincr); p->frmInc = n_partials * 2 + 26; break; case 4: p->firstpartial = 1 + 3 * (int)(*p->iptloffset); p->partialinc = 3 * (int) (*p->iptlincr); p->frmInc = n_partials * 3 + 26; break; default: return csound->InitError(csound, Str("ATSADD: Type not implemented")); } /* flag set to reduce the amount of warnings sent out */ /* for time pointer out of range */ p->prFlg = 1; /* true */ return OK; } static int atsaddset_S(CSOUND *csound, ATSADD *p) { char atsfilname[MAXNAME]; ATSSTRUCT *atsh; FUNC *ftp, *AmpGateFunc; int memsize, n_partials, type; /* set up function table for synthesis */ if (UNLIKELY((ftp = csound->FTFind(csound, p->ifn)) == NULL)) { return csound->InitError(csound, Str("ATSADD: Function table number " "for synthesis waveform not valid")); } p->ftp = ftp; /* set up gate function table */ if (*p->igatefun > FL(0.0)) { if (UNLIKELY((AmpGateFunc = csound->FTFind(csound, p->igatefun)) == NULL)) { return csound->InitError(csound, Str("ATSADD: Gate Function table " "number not valid")); } else p->AmpGateFunc = AmpGateFunc; } /* load memfile */ p->swapped = load_atsfile(csound, p, &(p->atsmemfile), atsfilname, p->ifileno, 1); if (UNLIKELY(p->swapped < 0)) return NOTOK; atsh = (ATSSTRUCT*) p->atsmemfile->beginp; /* calculate how much memory we have to allocate for this */ memsize = (int) (*p->iptls) * sizeof(ATS_DATA_LOC) + (int) (*p->iptls) * sizeof(double) + (int) (*p->iptls) * sizeof(MYFLT); /* allocate space if we need it */ /* need room for a buffer and an array of oscillator phase increments */ if (p->auxch.auxp == NULL || p->auxch.size < (unsigned int)memsize) csound->AuxAlloc(csound, (size_t) memsize, &p->auxch); /* set up the buffer, phase, etc. */ p->buf = (ATS_DATA_LOC *) (p->auxch.auxp); p->oscphase = (double *) (p->buf + (int) (*p->iptls)); p->oldamps = (MYFLT *) (p->oscphase + (int) (*p->iptls)); /* byte swap if necessary */ if (p->swapped == 1) { p->maxFr = (int) bswap(&atsh->nfrms) - 1; p->timefrmInc = bswap(&atsh->nfrms) / bswap(&atsh->dur); n_partials = (int) bswap(&atsh->npartials); p->MaxAmp = bswap(&atsh->ampmax); /* store the maxium amplitude */ type = (int) bswap(&atsh->type); } else { p->maxFr = (int) atsh->nfrms - 1; p->timefrmInc = atsh->nfrms / atsh->dur; n_partials = (int) atsh->npartials; p->MaxAmp = atsh->ampmax; /* store the maxium amplitude */ type = (int) atsh->type; } /* make sure partials are in range */ if (UNLIKELY((int) (*p->iptloffset + *p->iptls * *p->iptlincr) > n_partials || (int) (*p->iptloffset) < 0)) { return csound->InitError(csound, Str("ATSADD: Partial(s) out of range, " "max partial allowed is %i"), n_partials); } /* get a pointer to the beginning of the data */ p->datastart = (double *) (p->atsmemfile->beginp + sizeof(ATSSTRUCT)); /* get increments for the partials */ switch (type) { case 1: p->firstpartial = 1 + 2 * (int)(*p->iptloffset); p->partialinc = 2 * (int) (*p->iptlincr); p->frmInc = n_partials * 2 + 1; break; case 2: p->firstpartial = 1 + 3 * (int)(*p->iptloffset); p->partialinc = 3 * (int) (*p->iptlincr); p->frmInc = n_partials * 3 + 1; break; case 3: p->firstpartial = 1 + 2 * (int)(*p->iptloffset); p->partialinc = 2 * (int) (*p->iptlincr); p->frmInc = n_partials * 2 + 26; break; case 4: p->firstpartial = 1 + 3 * (int)(*p->iptloffset); p->partialinc = 3 * (int) (*p->iptlincr); p->frmInc = n_partials * 3 + 26; break; default: return csound->InitError(csound, Str("ATSADD: Type not implemented")); } /* flag set to reduce the amount of warnings sent out */ /* for time pointer out of range */ p->prFlg = 1; /* true */ return OK; } static int atsadd(CSOUND *csound, ATSADD *p) { MYFLT frIndx; MYFLT *ar, amp, fract, v1, *ftab,a,inca, *oldamps = p->oldamps; FUNC *ftp; int32 lobits, phase, inc; double *oscphase; int i; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int numpartials = (int) *p->iptls; ATS_DATA_LOC *buf; buf = p->buf; /* ftp is a poiter to the ftable */ if (UNLIKELY(p->auxch.auxp == NULL || (ftp = p->ftp) == NULL)) goto err1; /* make sure time pointer is within range */ if ((frIndx = *(p->ktimpnt) * p->timefrmInc) < FL(0.0)) { frIndx = FL(0.0); if (UNLIKELY(p->prFlg)) { p->prFlg = 0; csound->Warning(csound, Str("ATSADD: only positive time pointer " "values are allowed, setting to zero\n")); } } else if (OUT_OF_FRAMES) { /* if we are trying to get frames past where we have data */ frIndx = (MYFLT) p->maxFr; if (UNLIKELY(p->prFlg)) { p->prFlg = 0; /* set to false */ csound->Warning(csound, Str("ATSADD: time pointer out of range, " "truncating to last frame\n")); } } else p->prFlg = 1; FetchADDPartials(p, buf, frIndx); oscphase = p->oscphase; /* initialise output to zero */ ar = p->aoutput; memset(ar, 0, nsmps*sizeof(MYFLT)); if (UNLIKELY(early)) nsmps -= early; if (*p->igatefun > FL(0.0)) AtsAmpGate(buf, *p->iptls, p->AmpGateFunc, p->MaxAmp); for (i = 0; i < numpartials; i++) { lobits = ftp->lobits; amp = csound->e0dbfs * (MYFLT) p->buf[i].amp; phase = MYFLT2LONG(*oscphase); ar = p->aoutput; /* ar is a pointer to the audio output */ inca = (amp-oldamps[i])/nsmps; a = oldamps[i]; /* put in * kfmod */ inc = MYFLT2LONG(p->buf[i].freq * csound->sicvt * *p->kfmod); for (n=offset; nftable + (phase >> lobits); v1 = *ftab++; fract = (MYFLT) PFRAC(phase); ar[n] += (v1 + fract * (*ftab - v1)) * a; phase += inc; phase &= PHMASK; a+=inca; } *oscphase = (double) phase; oldamps[i] = amp; oscphase++; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("ATSADD: not initialised")); } static void FetchADDPartials(ATSADD *p, ATS_DATA_LOC *buf, MYFLT position) { MYFLT frac; /* the distance in time we are between frames */ double *frm_0, *frm_1; double temp0amp, temp1amp; double temp0freq, temp1freq; int frame; int i; /* for the for loop */ int partialloc = p->firstpartial; int npartials = (int) *p->iptls; frame = (int) position; frm_0 = p->datastart + frame * p->frmInc; /* if we are using the data from the last frame */ /* we should not try to interpolate */ if (UNLIKELY(frame == p->maxFr)) { for (i = 0; i < npartials; i++) { if (p->swapped == 1) { buf[i].amp = bswap(&frm_0[partialloc]); /* calc amplitude */ buf[i].freq = bswap(&frm_0[partialloc + 1]); /* freq */ } else { buf[i].amp = frm_0[partialloc]; /* calc amplitude */ buf[i].freq = frm_0[partialloc + 1]; /* freq */ } partialloc += p->partialinc; } return; } frac = position - frame; frm_1 = frm_0 + p->frmInc; for (i = 0; i < npartials; i++) { if (p->swapped == 1) { temp0amp = bswap(&frm_0[partialloc]); temp1amp = bswap(&frm_1[partialloc]); temp0freq = bswap(&frm_0[partialloc + 1]); temp1freq = bswap(&frm_1[partialloc + 1]); } else { temp0amp = frm_0[partialloc]; temp1amp = frm_1[partialloc]; temp0freq = frm_0[partialloc + 1]; temp1freq = frm_1[partialloc + 1]; } buf[i].amp = temp0amp + frac * (temp1amp - temp0amp); /* calc amplitude */ buf[i].freq = temp0freq + frac * (temp1freq - temp0freq); /* calc freq */ partialloc += p->partialinc; /* get to the next partial */ } } static void AtsAmpGate( /* adaption of PvAmpGate by Richard Karpen */ ATS_DATA_LOC *buf, /* where to get our mag/freq pairs */ int npartials, /* number of partials we are working with */ FUNC *ampfunc, double MaxAmpInData) { int j; int32 funclen, mapPoint; funclen = ampfunc->flen; for (j = 0; j < npartials; ++j) { /* use normalised amp as index into table for amp scaling */ mapPoint = (int32) ((buf[j].amp / MaxAmpInData) * funclen); buf[j].amp *= (double) *(ampfunc->ftable + mapPoint); } } /************************************************************/ /********* ATSADDNZ ***********************************/ /************************************************************/ /* copied directly from atsh synth-funcs.c * with names changed so as not to conflict with csound * -------------------------------------------------------- * randi output random numbers in the range of 1,-1 * getting a new number at frequency freq and interpolating * the intermediate values. */ static void randiats_setup(CSOUND *csound, MYFLT freq, RANDIATS *radat) { radat->size = (int) MYFLT2LRND(CS_ESR / freq); radat->cnt = 0; radat->a1 = (int32) csound->Rand31(&(csound->randSeed1)); radat->a2 = (int32) csound->Rand31(&(csound->randSeed1)); } /* ------------------------------------------------------------------ */ static MYFLT randiats(CSOUND *csound, RANDIATS *radat) { MYFLT output; if (radat->cnt == radat->size) { /* get a new random value */ radat->a1 = radat->a2; radat->a2 = (int32) csound->Rand31(&(csound->randSeed1)); radat->cnt = 0; } output = (((MYFLT) (radat->a2 - radat->a1) / (MYFLT) radat->size) * (MYFLT) radat->cnt) + (MYFLT) radat->a1; radat->cnt++; return (FL(1.0) - ((MYFLT) output * (FL(2.0) / (MYFLT) 0x7FFFFFFF))); } /* ------------------------------------------------------------------ */ static void FetchADDNZbands(int ptls, int firstband, double *datastart, int frmInc, int maxFr, int swapped, double *buf, MYFLT position) { double frac; /* the distance in time we are between frames */ double *frm_0, *frm_1; double frm0val, frm1val; int frame; int i; /* for the for loop */ /*int firstband = p->firstband;*/ #ifdef BETA printf("FetchADDNZbands: position %f\n", (double)position); #endif frame = (int) position; frm_0 = datastart + frame * frmInc; /* if we are using the data from the last frame */ /* we should not try to interpolate */ if (UNLIKELY(frame == maxFr)) { for (i = 0; i < ptls; i++) { buf[i] = (swapped == 1 ? bswap(&frm_0[firstband + i]) : frm_0[firstband + i]); /* output value */ } return; } frm_1 = frm_0 + frmInc; frac = (double) (position - frame); for (i = 0; i < ptls; i++) { if (swapped == 1) { frm0val = bswap(&(frm_0[firstband + i])); frm1val = bswap(&(frm_1[firstband + i])); } else { frm0val = frm_0[firstband + i]; frm1val = frm_1[firstband + i]; } buf[i] = frm0val + frac * (frm1val - frm0val); /* calc energy */ } } static const double freqs[25]= { 100.0, 100.0, 100.0, 100.0, 110.0, 120.0, 140.0, 150.0, 160.0, 190.0, 210.0, 240.0, 280.0, 320.0, 380.0, 450.0, 550.0, 700.0, 900.0, 1100.0, 1300.0, 1800.0, 2500.0, 3500.0, 4500.0}; static int atsaddnzset(CSOUND *csound, ATSADDNZ *p) { char atsfilname[MAXNAME]; ATSSTRUCT *atsh; int i, type, n_partials; /* load memfile */ p->swapped = load_atsfile(csound, p, &(p->atsmemfile), atsfilname, p->ifileno, 0); if (UNLIKELY(p->swapped < 0)) return NOTOK; p->bands = (int)(*p->ibands); p->bandoffset = (int) (*p->ibandoffset); p->bandincr = (int) (*p->ibandincr); atsh = (ATSSTRUCT*) p->atsmemfile->beginp; /* make sure that this file contains noise */ type = (p->swapped == 1) ? (int) bswap(&atsh->type) : (int) atsh->type; if (UNLIKELY(type != 4 && type != 3)) { if (type < 5) return csound->InitError(csound, Str("ATSADDNZ: " "This file type contains no noise")); else return csound->InitError(csound, Str("ATSADDNZ: This file type has not been " "implemented in this code yet.")); } p->datastart = (double *) (p->atsmemfile->beginp + sizeof(ATSSTRUCT)); /* byte swap if necessary */ if (p->swapped == 1) { p->maxFr = (int) bswap(&atsh->nfrms) - 1; p->timefrmInc = bswap(&atsh->nfrms) / bswap(&atsh->dur); n_partials = (int) bswap(&atsh->npartials); p->winsize = (MYFLT) bswap(&atsh->winsz); } else { p->maxFr = (int) atsh->nfrms - 1; p->timefrmInc = atsh->nfrms / atsh->dur; n_partials = (int) atsh->npartials; p->winsize = (MYFLT) atsh->winsz; } /* make sure partials are in range */ if (UNLIKELY((p->bandoffset + p->bands * p->bandincr) > 25 || p->bands <0 || /* Allow zero bands for no good reason */ p->bandoffset < 0)) { return csound->InitError(csound, Str("ATSADDNZ: Band(s) out of range, " "max band allowed is 25")); } /* point the data pointer to the correct partials */ switch (type) { case 3: p->firstband = 1 + 2 * n_partials; p->frmInc = n_partials * 2 + 26; break; case 4: p->firstband = 1 + 3 * n_partials; p->frmInc = n_partials * 3 + 26; break; /* default: // Cannot happen */ /* return csound->InitError(csound, */ /* Str("ATSADDNZ: Type either has no noise " */ /* "or is not implemented " */ /* "(only type 3 and 4 work now)")); */ } /* save bandwidths for creating noise bands */ memcpy(p->nfreq, freqs, 25*sizeof(double)); /* p->nfreq[0] = 100.0; */ /* p->nfreq[1] = 100.0; */ /* p->nfreq[2] = 100.0; */ /* p->nfreq[3] = 100.0; */ /* p->nfreq[4] = 110.0; */ /* p->nfreq[5] = 120.0; */ /* p->nfreq[6] = 140.0; */ /* p->nfreq[7] = 150.0; */ /* p->nfreq[8] = 160.0; */ /* p->nfreq[9] = 190.0; */ /* p->nfreq[10] = 210.0; */ /* p->nfreq[11] = 240.0; */ /* p->nfreq[12] = 280.0; */ /* p->nfreq[13] = 320.0; */ /* p->nfreq[14] = 380.0; */ /* p->nfreq[15] = 450.0; */ /* p->nfreq[16] = 550.0; */ /* p->nfreq[17] = 700.0; */ /* p->nfreq[18] = 900.0; */ /* p->nfreq[19] = 1100.0; */ /* p->nfreq[20] = 1300.0; */ /* p->nfreq[21] = 1800.0; */ /* p->nfreq[22] = 2500.0; */ /* p->nfreq[23] = 3500.0; */ /* p->nfreq[24] = 4500.0; */ { double tmp = TWOPI * csound->onedsr; /* initialise frequencies to modulate noise by */ p->phaseinc[0] = 50.0 * tmp; p->phaseinc[1] = 150.0 * tmp; p->phaseinc[2] = 250.0 * tmp; p->phaseinc[3] = 350.0 * tmp; p->phaseinc[4] = 455.0 * tmp; p->phaseinc[5] = 570.0 * tmp; p->phaseinc[6] = 700.0 * tmp; p->phaseinc[7] = 845.0 * tmp; p->phaseinc[8] = 1000.0 * tmp; p->phaseinc[9] = 1175.0 * tmp; p->phaseinc[10] = 1375.0 * tmp; p->phaseinc[11] = 1600.0 * tmp; p->phaseinc[12] = 1860.0 * tmp; p->phaseinc[13] = 2160.0 * tmp; p->phaseinc[14] = 2510.0 * tmp; p->phaseinc[15] = 2925.0 * tmp; p->phaseinc[16] = 3425.0 * tmp; p->phaseinc[17] = 4050.0 * tmp; p->phaseinc[18] = 4850.0 * tmp; p->phaseinc[19] = 5850.0 * tmp; p->phaseinc[20] = 7050.0 * tmp; p->phaseinc[21] = 8600.0 * tmp; p->phaseinc[22] = 10750.0 * tmp; p->phaseinc[23] = 13750.0 * tmp; p->phaseinc[24] = 17750.0 * tmp; } /* initialise phase */ memset(p->oscphase, '\0', 25*sizeof(double)); /* p->oscphase[0] = 0.0; */ /* p->oscphase[1] = 0.0; */ /* p->oscphase[2] = 0.0; */ /* p->oscphase[3] = 0.0; */ /* p->oscphase[4] = 0.0; */ /* p->oscphase[5] = 0.0; */ /* p->oscphase[6] = 0.0; */ /* p->oscphase[7] = 0.0; */ /* p->oscphase[8] = 0.0; */ /* p->oscphase[9] = 0.0; */ /* p->oscphase[10] = 0.0; */ /* p->oscphase[11] = 0.0; */ /* p->oscphase[12] = 0.0; */ /* p->oscphase[13] = 0.0; */ /* p->oscphase[14] = 0.0; */ /* p->oscphase[15] = 0.0; */ /* p->oscphase[16] = 0.0; */ /* p->oscphase[17] = 0.0; */ /* p->oscphase[18] = 0.0; */ /* p->oscphase[19] = 0.0; */ /* p->oscphase[20] = 0.0; */ /* p->oscphase[21] = 0.0; */ /* p->oscphase[22] = 0.0; */ /* p->oscphase[23] = 0.0; */ /* p->oscphase[24] = 0.0; */ /* initialise band limited noise parameters */ for (i = 0; i < 25; i++) { randiats_setup(csound, p->nfreq[i], &(p->randinoise[i])); } /* flag set to reduce the amount of warnings sent out */ /* for time pointer out of range */ p->prFlg = 1; /* true */ return OK; } static int atsaddnzset_S(CSOUND *csound, ATSADDNZ *p) { char atsfilname[MAXNAME]; ATSSTRUCT *atsh; int i, type, n_partials; /* load memfile */ p->swapped = load_atsfile(csound, p, &(p->atsmemfile), atsfilname, p->ifileno, 1); if (UNLIKELY(p->swapped < 0)) return NOTOK; p->bands = (int)(*p->ibands); p->bandoffset = (int) (*p->ibandoffset); p->bandincr = (int) (*p->ibandincr); atsh = (ATSSTRUCT*) p->atsmemfile->beginp; /* make sure that this file contains noise */ type = (p->swapped == 1) ? (int) bswap(&atsh->type) : (int) atsh->type; if (UNLIKELY(type != 4 && type != 3)) { if (type < 5) return csound->InitError(csound, Str("ATSADDNZ: " "This file type contains no noise")); else return csound->InitError(csound, Str("ATSADDNZ: This file type has not been " "implemented in this code yet.")); } p->datastart = (double *) (p->atsmemfile->beginp + sizeof(ATSSTRUCT)); /* byte swap if necessary */ if (p->swapped == 1) { p->maxFr = (int) bswap(&atsh->nfrms) - 1; p->timefrmInc = bswap(&atsh->nfrms) / bswap(&atsh->dur); n_partials = (int) bswap(&atsh->npartials); p->winsize = (MYFLT) bswap(&atsh->winsz); } else { p->maxFr = (int) atsh->nfrms - 1; p->timefrmInc = atsh->nfrms / atsh->dur; n_partials = (int) atsh->npartials; p->winsize = (MYFLT) atsh->winsz; } /* make sure partials are in range */ if (UNLIKELY((p->bandoffset + p->bands * p->bandincr) > 25 || p->bands <0 || /* Allow zero bands for no good reason */ p->bandoffset < 0)) { return csound->InitError(csound, Str("ATSADDNZ: Band(s) out of range, " "max band allowed is 25")); } /* point the data pointer to the correct partials */ switch (type) { case 3: p->firstband = 1 + 2 * n_partials; p->frmInc = n_partials * 2 + 26; break; case 4: p->firstband = 1 + 3 * n_partials; p->frmInc = n_partials * 3 + 26; break; /* default: */ // Cannot happen as tested earlier /* return csound->InitError(csound, */ /* Str("ATSADDNZ: Type either has no noise " */ /* "or is not implemented " */ /* "(only type 3 and 4 work now)")); */ } /* save bandwidths for creating noise bands */ memcpy(p->nfreq, freqs, 25*sizeof(double)); /* p->nfreq[0] = 100.0; */ /* p->nfreq[1] = 100.0; */ /* p->nfreq[2] = 100.0; */ /* p->nfreq[3] = 100.0; */ /* p->nfreq[4] = 110.0; */ /* p->nfreq[5] = 120.0; */ /* p->nfreq[6] = 140.0; */ /* p->nfreq[7] = 150.0; */ /* p->nfreq[8] = 160.0; */ /* p->nfreq[9] = 190.0; */ /* p->nfreq[10] = 210.0; */ /* p->nfreq[11] = 240.0; */ /* p->nfreq[12] = 280.0; */ /* p->nfreq[13] = 320.0; */ /* p->nfreq[14] = 380.0; */ /* p->nfreq[15] = 450.0; */ /* p->nfreq[16] = 550.0; */ /* p->nfreq[17] = 700.0; */ /* p->nfreq[18] = 900.0; */ /* p->nfreq[19] = 1100.0; */ /* p->nfreq[20] = 1300.0; */ /* p->nfreq[21] = 1800.0; */ /* p->nfreq[22] = 2500.0; */ /* p->nfreq[23] = 3500.0; */ /* p->nfreq[24] = 4500.0; */ { double tmp = TWOPI * csound->onedsr; /* initialise frequencies to modulate noise by */ p->phaseinc[0] = 50.0 * tmp; p->phaseinc[1] = 150.0 * tmp; p->phaseinc[2] = 250.0 * tmp; p->phaseinc[3] = 350.0 * tmp; p->phaseinc[4] = 455.0 * tmp; p->phaseinc[5] = 570.0 * tmp; p->phaseinc[6] = 700.0 * tmp; p->phaseinc[7] = 845.0 * tmp; p->phaseinc[8] = 1000.0 * tmp; p->phaseinc[9] = 1175.0 * tmp; p->phaseinc[10] = 1375.0 * tmp; p->phaseinc[11] = 1600.0 * tmp; p->phaseinc[12] = 1860.0 * tmp; p->phaseinc[13] = 2160.0 * tmp; p->phaseinc[14] = 2510.0 * tmp; p->phaseinc[15] = 2925.0 * tmp; p->phaseinc[16] = 3425.0 * tmp; p->phaseinc[17] = 4050.0 * tmp; p->phaseinc[18] = 4850.0 * tmp; p->phaseinc[19] = 5850.0 * tmp; p->phaseinc[20] = 7050.0 * tmp; p->phaseinc[21] = 8600.0 * tmp; p->phaseinc[22] = 10750.0 * tmp; p->phaseinc[23] = 13750.0 * tmp; p->phaseinc[24] = 17750.0 * tmp; } /* initialise phase */ memset(p->oscphase, '\0', 25*sizeof(double)); /* p->oscphase[0] = 0.0; */ /* p->oscphase[1] = 0.0; */ /* p->oscphase[2] = 0.0; */ /* p->oscphase[3] = 0.0; */ /* p->oscphase[4] = 0.0; */ /* p->oscphase[5] = 0.0; */ /* p->oscphase[6] = 0.0; */ /* p->oscphase[7] = 0.0; */ /* p->oscphase[8] = 0.0; */ /* p->oscphase[9] = 0.0; */ /* p->oscphase[10] = 0.0; */ /* p->oscphase[11] = 0.0; */ /* p->oscphase[12] = 0.0; */ /* p->oscphase[13] = 0.0; */ /* p->oscphase[14] = 0.0; */ /* p->oscphase[15] = 0.0; */ /* p->oscphase[16] = 0.0; */ /* p->oscphase[17] = 0.0; */ /* p->oscphase[18] = 0.0; */ /* p->oscphase[19] = 0.0; */ /* p->oscphase[20] = 0.0; */ /* p->oscphase[21] = 0.0; */ /* p->oscphase[22] = 0.0; */ /* p->oscphase[23] = 0.0; */ /* p->oscphase[24] = 0.0; */ /* initialise band limited noise parameters */ for (i = 0; i < 25; i++) { randiats_setup(csound, p->nfreq[i], &(p->randinoise[i])); } /* flag set to reduce the amount of warnings sent out */ /* for time pointer out of range */ p->prFlg = 1; /* true */ return OK; } static int atsaddnz(CSOUND *csound, ATSADDNZ *p) { MYFLT frIndx; MYFLT *ar, amp; int i; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int synthme; int nsynthed; /* make sure time pointer is within range */ if ((frIndx = *(p->ktimpnt) * p->timefrmInc) < FL(0.0)) { frIndx = FL(0.0); if (UNLIKELY(p->prFlg)) { p->prFlg = 0; csound->Warning(csound, Str("ATSADDNZ: only positive time pointer " "values are allowed, setting to zero\n")); } } else if (OUT_OF_FRAMES) { /* if we are trying to get frames past where we have data */ frIndx = (MYFLT) p->maxFr; if (UNLIKELY(p->prFlg)) { p->prFlg = 0; /* set to false */ csound->Warning(csound, Str("ATSADDNZ: time pointer out of range, " "truncating to last frame\n")); } } else p->prFlg = 1; FetchADDNZbands(25, p->firstband, p->datastart, p->frmInc, p->maxFr, p->swapped, p->buf, frIndx); /* set local pointer to output and initialise output to zero */ ar = p->aoutput; memset(ar, 0, CS_KSMPS*sizeof(MYFLT)); if (UNLIKELY(early)) nsmps -= early; synthme = p->bandoffset; nsynthed = 0; ar = p->aoutput; for (i = 0; i < 25; i++) { /* do we even have to synthesize it? */ if (i == synthme && nsynthed < p->bands) { /* synthesize cosine */ amp = csound->e0dbfs* SQRT((p->buf[i] / (p->winsize*(MYFLT)ATSA_NOISE_VARIANCE))); for (n=offset; noscphase[i]) * amp * randiats(csound, &(p->randinoise[i]))); p->oscphase[i] += p->phaseinc[i]; } /* make sure that the phase does not overflow */ /* while (phase >= costabsz) phase = phase - costabsz; */ nsynthed++; synthme += p->bandincr; } } return OK; } static void band_energy_to_res(CSOUND *csound, ATSSINNOI *p) { int i, j, k; MYFLT edges[] = ATSA_CRITICAL_BAND_EDGES; double *curframe = p->datastart; double bandsum[25]; double partialfreq; double partialamp; double **partialband; int *bandnum; partialband = (double **) csound->Malloc(csound, sizeof(double*) * (int) p->atshead->npartials); bandnum = (int *) csound->Malloc(csound, sizeof(int) * (int) p->atshead->npartials); for (i = 0; i < (int) p->atshead->nfrms; i++) { /* init sums */ memset(bandsum, 0, 25*sizeof(double)); /* find sums per band */ for (j = 0; j < (int) p->atshead->npartials; j++) { partialfreq = *(curframe + 2 + j * (int) p->partialinc); partialamp = *(curframe + 1 + j * (int) p->partialinc); for (k = 0; k < 25; k++) { if ((partialfreq < edges[k + 1]) && (partialfreq >= edges[k])) { bandsum[k] += partialamp; bandnum[j] = k; partialband[j] = (curframe + (int) p->firstband + k); break; } } } /* compute energy per partial */ for (j = 0; j < (int) p->atshead->npartials; j++) { if (bandsum[bandnum[j]] > 0.0) *(p->nzdata + i * (int) p->atshead->npartials + j) = (*(curframe + 1 + j * (int) p->partialinc) * *(partialband[j])) / bandsum[bandnum[j]]; else *(p->nzdata + i * (int) p->atshead->npartials + j) = 0.0; } curframe += p->frmInc; } csound->Free(csound,partialband); csound->Free(csound,bandnum); } static void fetchSINNOIpartials(ATSSINNOI *, MYFLT); static int atssinnoiset(CSOUND *csound, ATSSINNOI *p) { char atsfilname[MAXNAME]; ATSSTRUCT *atsh; int i, memsize, nzmemsize, type; /* load memfile */ p->swapped = load_atsfile(csound, p, &(p->atsmemfile), atsfilname, p->ifileno, 0); if (UNLIKELY(p->swapped < 0)){ return NOTOK; } atsh = (ATSSTRUCT*) p->atsmemfile->beginp; p->atshead = atsh; /* calculate how much memory we have to allocate for this */ /* need room for a buffer and the noise data and the noise info */ /* per partial for synthesizing noise */ memsize = (int) (*p->iptls) * (sizeof(ATS_DATA_LOC) + 2 * sizeof(double) + sizeof(RANDIATS)); /* allocate space if we need it */ /* need room for a buffer and an array of oscillator phase increments */ if (p->auxch.auxp != NULL || memsize > (int)p->auxch.size) csound->AuxAlloc(csound, (size_t) memsize, &p->auxch); /* set up the buffer, phase, etc. */ p->oscbuf = (ATS_DATA_LOC *) (p->auxch.auxp); p->randinoise = (RANDIATS *) (p->oscbuf + (int) (*p->iptls)); p->oscphase = (double *) (p->randinoise + (int) (*p->iptls)); p->nzbuf = (double *) (p->oscphase + (int) (*p->iptls)); if (p->swapped == 1) { p->maxFr = (int) bswap(&atsh->nfrms) - 1; p->timefrmInc = bswap(&atsh->nfrms) / bswap(&atsh->dur); p->npartials = (int) bswap(&atsh->npartials); nzmemsize = (int) (p->npartials * bswap(&atsh->nfrms)); type = (int) bswap(&atsh->type); } else { p->maxFr = (int) atsh->nfrms - 1; p->timefrmInc = atsh->nfrms / atsh->dur; p->npartials = (int) atsh->npartials; nzmemsize = (int) (p->npartials * atsh->nfrms); type = (int) atsh->type; } /* see if we have to allocate memory for the nzdata */ if (nzmemsize != p->nzmemsize) { if (p->nzdata != NULL) csound->Free(csound, p->nzdata); p->nzdata = (double *) csound->Malloc(csound, sizeof(double) * nzmemsize); } /* make sure partials are in range */ if (UNLIKELY((int) (*p->iptloffset + *p->iptls * *p->iptlincr) > p->npartials || (int) (*p->iptloffset) < 0)) { return csound->InitError(csound, Str("ATSSINNOI: Partial(s) out of range, " "max partial allowed is %i"), p->npartials); } /* get a pointer to the beginning of the data */ p->datastart = (double *) (p->atsmemfile->beginp + sizeof(ATSSTRUCT)); /* get increments for the partials */ switch (type) { case 1: p->firstpartial = 1 + 2 * (int)(*p->iptloffset); p->partialinc = 2 * (int) (*p->iptlincr); p->frmInc = p->npartials * 2 + 1; p->firstband = -1; break; case 2: p->firstpartial = 1 + 3 * (int)(*p->iptloffset); p->partialinc = 3 * (int) (*p->iptlincr); p->frmInc = p->npartials * 3 + 1; p->firstband = -1; break; case 3: p->firstpartial = 1 + 2 * (int)(*p->iptloffset); p->partialinc = 2 * (int) (*p->iptlincr); p->frmInc = p->npartials * 2 + 26; p->firstband = 1 + 2 * p->npartials; break; case 4: p->firstpartial = 1 + 3 * (int)(*p->iptloffset); p->partialinc = 3 * (int) (*p->iptlincr); p->frmInc = p->npartials * 3 + 26; p->firstband = 1 + 3 * p->npartials; break; default: return csound->InitError(csound, Str("ATSSINNOI: Type not implemented")); } /* convert noise per band to noise per partial */ /* make sure we do not do this if we have done it already. */ if ((p->firstband != -1) && ((p->filename == NULL) || (strcmp(atsfilname, p->filename) != 0) || (p->nzmemsize != nzmemsize))) { if (p->filename != NULL) csound->Free(csound, p->filename); p->filename = (char *) csound->Malloc(csound, sizeof(char) * strlen(atsfilname)); strcpy(p->filename, atsfilname); /* csound->Message(csound, "\n band to energy res calculation %s \n", p->filename); */ /* calculate the band energys */ band_energy_to_res(csound, p); } /* save the memory size of the noise */ p->nzmemsize = nzmemsize; /* flag set to reduce the amount of warnings sent out */ /* for time pointer out of range */ p->prFlg = 1; /* true */ { double tmp = TWOPI * csound->onedsr; p->phaseinc[0] = 50.0 * tmp; p->phaseinc[1] = 150.0 * tmp; p->phaseinc[2] = 250.0 * tmp; p->phaseinc[3] = 350.0 * tmp; p->phaseinc[4] = 455.0 * tmp; p->phaseinc[5] = 570.0 * tmp; p->phaseinc[6] = 700.0 * tmp; p->phaseinc[7] = 845.0 * tmp; p->phaseinc[8] = 1000.0 * tmp; p->phaseinc[9] = 1175.0 * tmp; p->phaseinc[10] = 1375.0 * tmp; p->phaseinc[11] = 1600.0 * tmp; p->phaseinc[12] = 1860.0 * tmp; p->phaseinc[13] = 2160.0 * tmp; p->phaseinc[14] = 2510.0 * tmp; p->phaseinc[15] = 2925.0 * tmp; p->phaseinc[16] = 3425.0 * tmp; p->phaseinc[17] = 4050.0 * tmp; p->phaseinc[18] = 4850.0 * tmp; p->phaseinc[19] = 5850.0 * tmp; p->phaseinc[20] = 7050.0 * tmp; p->phaseinc[21] = 8600.0 * tmp; p->phaseinc[22] = 10750.0 * tmp; p->phaseinc[23] = 13750.0 * tmp; p->phaseinc[24] = 17750.0 * tmp; } /* initialise phase */ memset(p->noiphase, 0, 25*sizeof(double)); /* p->noiphase[0] = 0.0; */ /* p->noiphase[1] = 0.0; */ /* p->noiphase[2] = 0.0; */ /* p->noiphase[3] = 0.0; */ /* p->noiphase[4] = 0.0; */ /* p->noiphase[5] = 0.0; */ /* p->noiphase[6] = 0.0; */ /* p->noiphase[7] = 0.0; */ /* p->noiphase[8] = 0.0; */ /* p->noiphase[9] = 0.0; */ /* p->noiphase[10] = 0.0; */ /* p->noiphase[11] = 0.0; */ /* p->noiphase[12] = 0.0; */ /* p->noiphase[13] = 0.0; */ /* p->noiphase[14] = 0.0; */ /* p->noiphase[15] = 0.0; */ /* p->noiphase[16] = 0.0; */ /* p->noiphase[17] = 0.0; */ /* p->noiphase[18] = 0.0; */ /* p->noiphase[19] = 0.0; */ /* p->noiphase[20] = 0.0; */ /* p->noiphase[21] = 0.0; */ /* p->noiphase[22] = 0.0; */ /* p->noiphase[23] = 0.0; */ /* p->oscphase[24] = 0.0; */ /* initialise band limited noise parameters */ for (i = 0; i < (int) *p->iptls; i++) { randiats_setup(csound, freqs[i], &(p->randinoise[i])); } return OK; } static int atssinnoiset_S(CSOUND *csound, ATSSINNOI *p) { char atsfilname[MAXNAME]; ATSSTRUCT *atsh; int i, memsize, nzmemsize, type; /* load memfile */ p->swapped = load_atsfile(csound, p, &(p->atsmemfile), atsfilname, p->ifileno, 1); if (UNLIKELY(p->swapped < 0)){ return NOTOK; } atsh = (ATSSTRUCT*) p->atsmemfile->beginp; p->atshead = atsh; /* calculate how much memory we have to allocate for this */ /* need room for a buffer and the noise data and the noise info */ /* per partial for synthesizing noise */ memsize = (int) (*p->iptls) * (sizeof(ATS_DATA_LOC) + 2 * sizeof(double) + sizeof(RANDIATS)); /* allocate space if we need it */ /* need room for a buffer and an array of oscillator phase increments */ if (p->auxch.auxp != NULL || memsize > (int)p->auxch.size) csound->AuxAlloc(csound, (size_t) memsize, &p->auxch); /* set up the buffer, phase, etc. */ p->oscbuf = (ATS_DATA_LOC *) (p->auxch.auxp); p->randinoise = (RANDIATS *) (p->oscbuf + (int) (*p->iptls)); p->oscphase = (double *) (p->randinoise + (int) (*p->iptls)); p->nzbuf = (double *) (p->oscphase + (int) (*p->iptls)); if (p->swapped == 1) { p->maxFr = (int) bswap(&atsh->nfrms) - 1; p->timefrmInc = bswap(&atsh->nfrms) / bswap(&atsh->dur); p->npartials = (int) bswap(&atsh->npartials); nzmemsize = (int) (p->npartials * bswap(&atsh->nfrms)); type = (int) bswap(&atsh->type); } else { p->maxFr = (int) atsh->nfrms - 1; p->timefrmInc = atsh->nfrms / atsh->dur; p->npartials = (int) atsh->npartials; nzmemsize = (int) (p->npartials * atsh->nfrms); type = (int) atsh->type; } /* see if we have to allocate memory for the nzdata */ if (nzmemsize != p->nzmemsize) { if (p->nzdata != NULL) csound->Free(csound, p->nzdata); p->nzdata = (double *) csound->Malloc(csound, sizeof(double) * nzmemsize); } /* make sure partials are in range */ if (UNLIKELY((int) (*p->iptloffset + *p->iptls * *p->iptlincr) > p->npartials || (int) (*p->iptloffset) < 0)) { return csound->InitError(csound, Str("ATSSINNOI: Partial(s) out of range, " "max partial allowed is %i"), p->npartials); } /* get a pointer to the beginning of the data */ p->datastart = (double *) (p->atsmemfile->beginp + sizeof(ATSSTRUCT)); /* get increments for the partials */ switch (type) { case 1: p->firstpartial = 1 + 2 * (int)(*p->iptloffset); p->partialinc = 2 * (int)(*p->iptlincr); p->frmInc = p->npartials * 2 + 1; p->firstband = -1; break; case 2: p->firstpartial = 1 + 3 * (int)(*p->iptloffset); p->partialinc = 3 * (int)(*p->iptlincr); p->frmInc = p->npartials * 3 + 1; p->firstband = -1; break; case 3: p->firstpartial = 1 + 2 * (int)(*p->iptloffset); p->partialinc = 2 * (int)(*p->iptlincr); p->frmInc = p->npartials * 2 + 26; p->firstband = 1 + 2 * p->npartials; break; case 4: p->firstpartial = 1 + 3 * (int)(*p->iptloffset); p->partialinc = 3 * (int)(*p->iptlincr); p->frmInc = p->npartials * 3 + 26; p->firstband = 1 + 3 * p->npartials; break; default: return csound->InitError(csound, Str("ATSSINNOI: Type not implemented")); } /* convert noise per band to noise per partial */ /* make sure we do not do this if we have done it already. */ if ((p->firstband != -1) && ((p->filename == NULL) || (strcmp(atsfilname, p->filename) != 0) || (p->nzmemsize != nzmemsize))) { if (p->filename != NULL) csound->Free(csound, p->filename); p->filename = (char *) csound->Malloc(csound, sizeof(char) * strlen(atsfilname)); strcpy(p->filename, atsfilname); /* csound->Message(csound, "\n band to energy res calculation %s \n", p->filename); */ /* calculate the band energys */ band_energy_to_res(csound, p); } /* save the memory size of the noise */ p->nzmemsize = nzmemsize; /* flag set to reduce the amount of warnings sent out */ /* for time pointer out of range */ p->prFlg = 1; /* true */ { double tmp = TWOPI * csound->onedsr; p->phaseinc[0] = 50.0 * tmp; p->phaseinc[1] = 150.0 * tmp; p->phaseinc[2] = 250.0 * tmp; p->phaseinc[3] = 350.0 * tmp; p->phaseinc[4] = 455.0 * tmp; p->phaseinc[5] = 570.0 * tmp; p->phaseinc[6] = 700.0 * tmp; p->phaseinc[7] = 845.0 * tmp; p->phaseinc[8] = 1000.0 * tmp; p->phaseinc[9] = 1175.0 * tmp; p->phaseinc[10] = 1375.0 * tmp; p->phaseinc[11] = 1600.0 * tmp; p->phaseinc[12] = 1860.0 * tmp; p->phaseinc[13] = 2160.0 * tmp; p->phaseinc[14] = 2510.0 * tmp; p->phaseinc[15] = 2925.0 * tmp; p->phaseinc[16] = 3425.0 * tmp; p->phaseinc[17] = 4050.0 * tmp; p->phaseinc[18] = 4850.0 * tmp; p->phaseinc[19] = 5850.0 * tmp; p->phaseinc[20] = 7050.0 * tmp; p->phaseinc[21] = 8600.0 * tmp; p->phaseinc[22] = 10750.0 * tmp; p->phaseinc[23] = 13750.0 * tmp; p->phaseinc[24] = 17750.0 * tmp; } /* initialise phase */ memset(p->noiphase, 0, 25*sizeof(double)); /* initialise band limited noise parameters */ for (i = 0; i < (int) *p->iptls; i++) { randiats_setup(csound, freqs[i], &(p->randinoise[i])); } return OK; } static int atssinnoi(CSOUND *csound, ATSSINNOI *p) { MYFLT frIndx; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; MYFLT *ar; double noise; double inc; int i; double phase; double amp; double nzamp; /* noize amp */ double sinewave; MYFLT freq; ATS_DATA_LOC *oscbuf; //csound->Message(csound , "start \n"); /* make sure time pointer is within range */ if ((frIndx = *(p->ktimpnt) * p->timefrmInc) < FL(0.0)) { frIndx = FL(0.0); if (UNLIKELY(p->prFlg)) { p->prFlg = 0; csound->Warning(csound, Str("ATSSINNOI: only positive time pointer " "values are allowed, setting to zero\n")); } } else if (OUT_OF_FRAMES) { /* if we are trying to get frames past where we have data */ if (UNLIKELY(p->prFlg)) { p->prFlg = 0; /* set to false */ csound->Warning(csound, Str("ATSSINNOI: time pointer out of range, " // "frIndx=%g maxFr=%g (%g %g) " "truncating to last frame\n") //frIndx, (MYFLT)p->maxFr, *(p->ktimpnt), p->timefrmInc ); } frIndx = (MYFLT) p->maxFr; } else p->prFlg = 1; fetchSINNOIpartials(p, frIndx); FetchADDNZbands(*p->iptls, p->firstband, p->datastart, p->frmInc, p->maxFr, p->swapped, p->nzbuf, frIndx); /* set local pointer to output and initialise output to zero */ ar = p->aoutput; memset(ar, 0, CS_KSMPS*sizeof(MYFLT)); if (UNLIKELY(early)) nsmps -= early; oscbuf = p->oscbuf; /* do synthesis */ if (p->firstband != -1) { for (i = 0; i < (int) *p->iptls; i++) { phase = p->oscphase[i]; ar = p->aoutput; amp = oscbuf[i].amp; freq = (MYFLT) oscbuf[i].freq * *p->kfreq; inc = TWOPI * freq * csound->onedsr; nzamp = sqrt(*(p->nzbuf + i) / (p->atshead->winsz * ATSA_NOISE_VARIANCE)); for (n=offset; nnoiphase[i]) * randiats(csound, &(p->randinoise[i])); p->noiphase[i] += p->phaseinc[i]; } else noise = FL(0.0); /* calc output */ ar[n] += csound->e0dbfs * (MYFLT)(amp * sinewave * *p->ksinamp + noise **p->knzamp); } p->oscphase[i] = phase; } } else { for (i = 0; i < (int) *p->iptls; i++) { phase = p->oscphase[i]; ar = p->aoutput; amp = oscbuf[i].amp; freq = (MYFLT) oscbuf[i].freq * *p->kfreq; inc = TWOPI * freq * csound->onedsr; for (n=offset; ne0dbfs * (MYFLT)sinewave * *p->ksinamp; } p->oscphase[i] = phase; } } return OK; } static void fetchSINNOIpartials(ATSSINNOI *p, MYFLT position) { double frac; /* the distance in time we are between frames */ double *frm_0, *frm_1; double frm0amp, frm0freq, frm1amp, frm1freq; double nz0, nz1; ATS_DATA_LOC *oscbuf; double *nzbuf; int frame; int i; /* for the for loop */ int npartials = p->npartials; frame = (int) position; frm_0 = p->datastart + frame * p->frmInc; oscbuf = p->oscbuf; nzbuf = p->nzbuf; /* if we are using the data from the last frame */ /* we should not try to interpolate */ if (UNLIKELY(frame == p->maxFr)) { if (p->firstband == -1) { /* there is no noise data */ if (p->swapped == 1) { for (i = (int) *p->iptloffset; i < (int) *p->iptls+*p->iptloffset; i += (int) *p->iptlincr) { oscbuf->amp = bswap(frm_0 + 1 + i * (int) p->partialinc); /* amp */ oscbuf->freq = bswap(frm_0 + 2 + i * (int) p->partialinc); /* freq */ oscbuf++; } } else { for (i = (int) *p->iptloffset; i < (int) *p->iptls+*p->iptloffset; i += (int) *p->iptlincr) { oscbuf->amp = *(frm_0 + 1 + i * (int) p->partialinc); /* amp */ oscbuf->freq = *(frm_0 + 2 + i * (int) p->partialinc); /* freq */ oscbuf++; } } } else { if (p->swapped == 1) { for (i = (int) *p->iptloffset; i < (int) *p->iptls+*p->iptloffset; i += (int) *p->iptlincr) { oscbuf->amp = bswap(frm_0 + 1 + i * (int) p->partialinc); /* amp */ oscbuf->freq = bswap(frm_0 + 2 + i * (int) p->partialinc); /* freq */ *nzbuf = bswap(p->nzdata + frame * npartials + i); nzbuf++; oscbuf++; } } else { for (i = (int) *p->iptloffset; i < (int) *p->iptls+*p->iptloffset; i += (int) *p->iptlincr) { oscbuf->amp = *(frm_0 + 1 + i * (int) p->partialinc); /* amp */ oscbuf->freq = *(frm_0 + 2 + i * (int) p->partialinc); /* freq */ *nzbuf = *(p->nzdata + frame * npartials + i); nzbuf++; oscbuf++; } } } return; } frm_1 = frm_0 + p->frmInc; frac = (double) (position - frame); if (p->firstband == -1) { /* there is no noise data */ if (p->swapped == 1) { for (i = (int) *p->iptloffset; i < (int) *p->iptls+*p->iptloffset; i += (int) *p->iptlincr) { frm0amp = bswap(frm_0 + 1 + i * (int) p->partialinc); frm1amp = bswap(frm_1 + 1 + i * (int) p->partialinc); frm0freq = bswap(frm_0 + 2 + i * (int) p->partialinc); frm1freq = bswap(frm_1 + 2 + i * (int) p->partialinc); oscbuf->amp = frm0amp + frac * (frm1amp - frm0amp); /* amp */ oscbuf->freq = frm0freq + frac * (frm1freq - frm0freq); /* freq */ oscbuf++; } } else { for (i = (int) *p->iptloffset; i < (int) *p->iptls+*p->iptloffset; i += (int) *p->iptlincr) { frm0amp = *(frm_0 + 1 + i * (int) p->partialinc); frm1amp = *(frm_1 + 1 + i * (int) p->partialinc); frm0freq = *(frm_0 + 2 + i * (int) p->partialinc); frm1freq = *(frm_1 + 2 + i * (int) p->partialinc); oscbuf->amp = frm0amp + frac * (frm1amp - frm0amp); /* amp */ oscbuf->freq = frm0freq + frac * (frm1freq - frm0freq); /* freq */ oscbuf++; } } } else { if (p->swapped == 1) { for (i = (int) *p->iptloffset; i < (int) *p->iptls+*p->iptloffset; i += (int) *p->iptlincr) { frm0amp = bswap(frm_0 + 1 + i * (int) p->partialinc); frm1amp = bswap(frm_1 + 1 + i * (int) p->partialinc); frm0freq = bswap(frm_0 + 2 + i * (int) p->partialinc); frm1freq = bswap(frm_1 + 2 + i * (int) p->partialinc); nz0 = bswap(p->nzdata + frame * npartials + i); nz1 = bswap(p->nzdata + (frame + 1) * npartials + i); oscbuf->amp = frm0amp + frac * (frm1amp - frm0amp); /* amp */ oscbuf->freq = frm0freq + frac * (frm1freq - frm0freq); /* freq */ /* noise */ *nzbuf = nz0 + frac * (nz1 - nz0); nzbuf++; oscbuf++; } } else { for (i = (int) *p->iptloffset; i < (int) *p->iptls+*p->iptloffset; i += (int) *p->iptlincr) { frm0amp = *(frm_0 + 1 + i * (int) p->partialinc); frm1amp = *(frm_1 + 1 + i * (int) p->partialinc); frm0freq = *(frm_0 + 2 + i * (int) p->partialinc); frm1freq = *(frm_1 + 2 + i * (int) p->partialinc); nz0 = *(p->nzdata + frame * npartials + i); nz1 = *(p->nzdata + (frame + 1) * npartials + i); oscbuf->amp = frm0amp + frac * (frm1amp - frm0amp); /* amp */ oscbuf->freq = frm0freq + frac * (frm1freq - frm0freq); /* freq */ /* noise */ *nzbuf = nz0 + frac * (nz1 - nz0); nzbuf++; oscbuf++; } } } } /************************************************************/ /*********** ATSBUFREAD *************************************/ /************************************************************/ static int atsbufreadset(CSOUND *csound, ATSBUFREAD *p) { char atsfilname[MAXNAME]; MEMFIL *mfp; ATS_DATA_LOC *fltp; ATSSTRUCT *atsh; int type, n_partials; int memsize; /* the size of the memory to request for AUX */ /* load memfile */ p->swapped = load_atsfile(csound, p, &mfp, atsfilname, p->ifileno, 0); if (UNLIKELY(p->swapped < 0)) return NOTOK; atsh = (ATSSTRUCT*) mfp->beginp; /* get past the header to the data, point frptr at time 0 */ p->datastart = (double *) atsh + 10; p->prFlg = 1; /* true */ /* is swapped? */ if (p->swapped == 1) { p->maxFr = (int) bswap(&atsh->nfrms) - 1; p->timefrmInc = bswap(&atsh->nfrms) / bswap(&atsh->dur); type = (int) bswap(&atsh->type); n_partials = (int) bswap(&atsh->npartials); } else { p->maxFr = (int) atsh->nfrms - 1; p->timefrmInc = atsh->nfrms / atsh->dur; type = (int) atsh->type; n_partials = (int) atsh->npartials; } /* we need room for 2 * (1 table + 2 for 20 and 20,000 hz) */ /* (one sorted one unsorted) */ memsize = 2 * ((int) *(p->iptls) + 2); csound->AuxAlloc(csound, (size_t)memsize * sizeof(ATS_DATA_LOC), &p->auxch); fltp = (ATS_DATA_LOC *) p->auxch.auxp; p->table = fltp; p->utable = fltp + ((int) *(p->iptls) + 2); /* check to see if partial is valid */ if (UNLIKELY((int)(*p->iptloffset + *p->iptls * *p->iptlincr) > n_partials || (int)(*p->iptloffset) < 0)) { return csound->InitError(csound, Str("ATSBUFREAD: Partial out of range, " "max partial is %i"), n_partials); } /* set up partial locations and frame increments */ switch (type) { case 1: p->firstpartial = 1 + 2 * (*p->iptloffset); p->partialinc = 2; p->frmInc = n_partials * 2 + 1; break; case 2: p->firstpartial = 1 + 3 * (*p->iptloffset); p->partialinc = 3; p->frmInc = n_partials * 3 + 1; break; case 3: p->firstpartial = 1 + 2 * (*p->iptloffset); p->partialinc = 2; p->frmInc = n_partials * 2 + 26; break; case 4: p->firstpartial = 1 + 3 * (*p->iptloffset); p->partialinc = 3; p->frmInc = n_partials * 3 + 26; break; default: return csound->InitError(csound, Str("ATSBUFREAD: Type not implemented")); } /* put 20 hertz = 0amp and 20000 hz = 0amp */ /* to make interpolation easier later */ p->table[0].freq = p->utable[0].freq = 20; p->table[0].amp = p->utable[0].amp = 0; p->table[(int) *p->iptls + 1].freq = p->utable[(int) *p->iptls + 1].freq = 20000; p->table[(int) *p->iptls + 1].amp = p->utable[(int) *p->iptls + 1].amp = 0; *(get_atsbufreadaddrp(csound)) = p; return OK; } static int atsbufreadset_S(CSOUND *csound, ATSBUFREAD *p) { char atsfilname[MAXNAME]; MEMFIL *mfp; ATS_DATA_LOC *fltp; ATSSTRUCT *atsh; int type, n_partials; int memsize; /* the size of the memory to request for AUX */ /* load memfile */ p->swapped = load_atsfile(csound, p, &mfp, atsfilname, p->ifileno, 1); if (UNLIKELY(p->swapped < 0)) return NOTOK; atsh = (ATSSTRUCT*) mfp->beginp; /* get past the header to the data, point frptr at time 0 */ p->datastart = (double *) atsh + 10; p->prFlg = 1; /* true */ /* is swapped? */ if (p->swapped == 1) { p->maxFr = (int) bswap(&atsh->nfrms) - 1; p->timefrmInc = bswap(&atsh->nfrms) / bswap(&atsh->dur); type = (int) bswap(&atsh->type); n_partials = (int) bswap(&atsh->npartials); } else { p->maxFr = (int) atsh->nfrms - 1; p->timefrmInc = atsh->nfrms / atsh->dur; type = (int) atsh->type; n_partials = (int) atsh->npartials; } /* we need room for 2 * (1 table + 2 for 20 and 20,000 hz) */ /* (one sorted one unsorted) */ memsize = 2 * ((int) *(p->iptls) + 2); csound->AuxAlloc(csound, (size_t)memsize * sizeof(ATS_DATA_LOC), &p->auxch); fltp = (ATS_DATA_LOC *) p->auxch.auxp; p->table = fltp; p->utable = fltp + ((int) *(p->iptls) + 2); /* check to see if partial is valid */ if (UNLIKELY((int)(*p->iptloffset + *p->iptls * *p->iptlincr) > n_partials || (int)(*p->iptloffset) < 0)) { return csound->InitError(csound, Str("ATSBUFREAD: Partial out of range, " "max partial is %i"), n_partials); } /* set up partial locations and frame increments */ switch (type) { case 1: p->firstpartial = 1 + 2 * (*p->iptloffset); p->partialinc = 2; p->frmInc = n_partials * 2 + 1; break; case 2: p->firstpartial = 1 + 3 * (*p->iptloffset); p->partialinc = 3; p->frmInc = n_partials * 3 + 1; break; case 3: p->firstpartial = 1 + 2 * (*p->iptloffset); p->partialinc = 2; p->frmInc = n_partials * 2 + 26; break; case 4: p->firstpartial = 1 + 3 * (*p->iptloffset); p->partialinc = 3; p->frmInc = n_partials * 3 + 26; break; default: return csound->InitError(csound, Str("ATSBUFREAD: Type not implemented")); } /* put 20 hertz = 0amp and 20000 hz = 0amp */ /* to make interpolation easier later */ p->table[0].freq = p->utable[0].freq = 20; p->table[0].amp = p->utable[0].amp = 0; p->table[(int) *p->iptls + 1].freq = p->utable[(int) *p->iptls + 1].freq = 20000; p->table[(int) *p->iptls + 1].amp = p->utable[(int) *p->iptls + 1].amp = 0; *(get_atsbufreadaddrp(csound)) = p; return OK; } static int mycomp(const void *p1, const void *p2) { const ATS_DATA_LOC *a1 = p1; const ATS_DATA_LOC *a2 = p2; double a1f = a1->freq; double a2f = a2->freq; if (a1f < a2f) return -1; else if (a1f == a2f) return 0; else return 1; } static void FetchBUFPartials(ATSBUFREAD *p, ATS_DATA_LOC *buf, ATS_DATA_LOC *buf2, MYFLT position) { MYFLT frac; /* the distance in time we are between frames */ double *frm_0, *frm_1; double frm0amp, frm0freq, frm1amp, frm1freq; int frame; int i; /* for the for loop */ int partialloc = p->firstpartial; int npartials = (int) *p->iptls; frame = (int) position; frm_0 = p->datastart + frame * p->frmInc; /* if we are using the data from the last frame */ /* we should not try to interpolate */ if (UNLIKELY(frame == p->maxFr)) { if (p->swapped == 1) { for (i = 0; i < npartials; i++) { /* calc amplitude */ buf[i].amp = buf2[i].amp = bswap(&frm_0[partialloc]); buf[i].freq = buf2[i].freq = bswap(&frm_0[partialloc + 1]); partialloc += p->partialinc; } } else { for (i = 0; i < npartials; i++) { buf[i].amp = buf2[i].amp = frm_0[partialloc]; /* calc amplitude */ buf[i].freq = buf2[i].freq = frm_0[partialloc + 1]; partialloc += p->partialinc; } } return; } frac = position - frame; frm_1 = frm_0 + p->frmInc; if (p->swapped == 1) { for (i = 0; i < npartials; i++) { frm0amp = bswap(&frm_0[partialloc]); frm0freq = bswap(&frm_0[partialloc + 1]); frm1amp = bswap(&frm_1[partialloc]); frm1freq = bswap(&frm_1[partialloc + 1]); /* calc amplitude */ buf[i].amp = buf2[i].amp = frm0amp + frac * (frm1amp - frm0amp); /* calc freq */ buf[i].freq = buf2[i].freq = *p->kfmod * (frm0freq + frac * (frm1freq - frm0freq)); partialloc += p->partialinc; /* get to the next partial */ } } else { for (i = 0; i < npartials; i++) { /* calc amplitude */ buf[i].amp = buf2[i].amp = frm_0[partialloc] + frac * (frm_1[partialloc] - frm_0[partialloc]); /* calc freq */ buf[i].freq = buf2[i].freq = *p->kfmod * (frm_0[partialloc + 1] + frac * (frm_1[partialloc + 1] - frm_0[partialloc + 1])); partialloc += p->partialinc; /* get to the next partial */ } } } static int atsbufread(CSOUND *csound, ATSBUFREAD *p) { MYFLT frIndx; ATS_DATA_LOC *buf; ATS_DATA_LOC *buf2; if (UNLIKELY(p->table == NULL)) goto err1; /* RWD fix */ *(get_atsbufreadaddrp(csound)) = p; /* make sure time pointer is within range */ if ((frIndx = *(p->ktimpnt) * p->timefrmInc) < FL(0.0)) { frIndx = FL(0.0); if (UNLIKELY(p->prFlg)) { p->prFlg = 0; csound->Warning(csound, Str("ATSBUFREAD: only positive time pointer " "values are allowed, setting to zero\n")); } } else if (OUT_OF_FRAMES) { /* if we are trying to get frames past where we have data */ frIndx = (MYFLT) p->maxFr; if (UNLIKELY(p->prFlg)) { p->prFlg = 0; /* set to false */ csound->Warning(csound, Str("ATSBUFREAD: time pointer out of range, " "truncating to last frame\n")); } } else p->prFlg = 1; /* skip the first value in the table because */ /* we will never have to change it as it is 20hz with amp 0 */ buf = p->table + 1; buf2 = p->utable + 1; FetchBUFPartials(p, buf, buf2, frIndx); /* must sort the buffered values */ qsort(buf, (int) *p->iptls, sizeof(ATS_DATA_LOC), mycomp); return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("ATSBUFREAD: not initialised")); } /* ATS partial tap */ static int atspartialtapset(CSOUND *csound, ATSPARTIALTAP *p) { ATSBUFREAD *atsbufreadaddr; atsbufreadaddr = *(get_atsbufreadaddrp(csound)); if (UNLIKELY(atsbufreadaddr == NULL)) { return csound->InitError(csound, Str("ATSPARTIALTAP: you must have an " "atsbufread before an atspartialtap")); } if (UNLIKELY((int) *p->iparnum > (int) *(atsbufreadaddr->iptls))) { return csound->InitError(csound, Str("ATSPARTIALTAP: exceeded " "max partial %i"), (int) *(atsbufreadaddr->iptls)); } if (UNLIKELY((int) *p->iparnum <= 0)) { return csound->InitError(csound, Str("ATSPARTIALTAP: partial must be " "positive and nonzero")); } return OK; } static int atspartialtap(CSOUND *csound, ATSPARTIALTAP *p) { ATSBUFREAD *atsbufreadaddr; atsbufreadaddr = *(get_atsbufreadaddrp(csound)); if (UNLIKELY(atsbufreadaddr == NULL)) goto err1; *p->kfreq = (MYFLT) ((atsbufreadaddr->utable)[(int)(*p->iparnum)].freq); *p->kamp = (MYFLT) ((atsbufreadaddr->utable)[(int)(*p->iparnum)].amp); return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("ATSPARTIALTAP: you must have an " "atsbufread before an atspartialtap")); } /* ATS interpread */ static int atsinterpreadset(CSOUND *csound, ATSINTERPREAD *p) { if (UNLIKELY(*(get_atsbufreadaddrp(csound)) == NULL)) return csound->InitError(csound, Str("ATSINTERPREAD: you must have an " "atsbufread before an atsinterpread")); p->overflowflag = 1; /* true */ return OK; } static int atsinterpread(CSOUND *csound, ATSINTERPREAD *p) { ATSBUFREAD *atsbufreadaddr; int i; MYFLT frac; /* make sure we have data to read from */ atsbufreadaddr = *(get_atsbufreadaddrp(csound)); if (UNLIKELY(atsbufreadaddr == NULL)) goto err1; /* make sure we are not asking for unreasonble frequencies */ if (UNLIKELY(*p->kfreq <= FL(20.0) || *p->kfreq >= FL(20000.0))) { if (UNLIKELY(p->overflowflag)) { csound->Warning(csound, Str("ATSINTERPREAD: frequency must be greater " "than 20 and less than 20000 Hz")); p->overflowflag = 0; } *p->kamp = FL(0.0); return OK; } /* find the location in the table */ for (i = 0; i < (int) *(atsbufreadaddr->iptls); i++) { /* find i such that table i+1 is greater than the specified frequency */ if ((MYFLT) ((atsbufreadaddr->table[i + 1]).freq) > *p->kfreq) break; } if (i == 0) { *p->kamp = FL(0.0); return OK; } /* linear interpolation */ frac = (*p->kfreq - (atsbufreadaddr->table[i]).freq) / ((atsbufreadaddr->table[i + 1]).freq - (atsbufreadaddr->table[i]).freq); *p->kamp = (MYFLT) ((atsbufreadaddr->table[i]).amp + frac * ((atsbufreadaddr->table[i + 1]).amp - (atsbufreadaddr->table[i]).amp)); /* *p->kamp = (MYFLT) (atsbufreadaddr->table[i]).amp; */ return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("ATSINTERPREAD: you must have an " "atsbufread before an atsinterpread")); } /* ATS cross */ static int atscrossset(CSOUND *csound, ATSCROSS *p) { char atsfilname[MAXNAME]; ATSSTRUCT *atsh; FUNC *ftp; int memsize; int type, n_partials; /* set up function table for synthesis */ if (UNLIKELY((ftp = csound->FTFind(csound, p->ifn)) == NULL)) { return csound->InitError(csound, Str("ATSCROSS: Function table number for " "synthesis waveform not valid")); } p->ftp = ftp; /* load memfile */ p->swapped = load_atsfile(csound, p, &(p->atsmemfile), atsfilname, p->ifileno, 0); if (UNLIKELY(p->swapped < 0)) return NOTOK; atsh = (ATSSTRUCT*) p->atsmemfile->beginp; /* calculate how much memory we have to allocate for this */ memsize = (int)(*p->iptls) * (sizeof(ATS_DATA_LOC) + sizeof(double) + sizeof(MYFLT)) ; /* allocate space if we need it */ /* need room for a buffer and an array of oscillator phase increments */ if (p->auxch.auxp == NULL || p->auxch.size >= (unsigned int)memsize) csound->AuxAlloc(csound, (size_t) memsize, &p->auxch); /* set up the buffer, phase, etc. */ p->buf = (ATS_DATA_LOC *) (p->auxch.auxp); p->oscphase = (double *) (p->buf + (int)(*p->iptls)); p->oldamps = (MYFLT *) (p->oscphase + (int)(*p->iptls)); if (p->swapped == 1) { p->maxFr = (int) bswap(&atsh->nfrms) - 1; p->timefrmInc = bswap(&atsh->nfrms) / bswap(&atsh->dur); type = (int) bswap(&atsh->type); n_partials = (int) bswap(&atsh->npartials); } else { p->maxFr = (int) atsh->nfrms - 1; p->timefrmInc = atsh->nfrms / atsh->dur; type = (int) atsh->type; n_partials = (int) atsh->npartials; } /* make sure partials are in range */ if ((int)(*p->iptloffset + *p->iptls * *p->iptlincr) > n_partials || (int)(*p->iptloffset) < 0) { return csound->InitError(csound, Str("ATSCROSS: Partial(s) out of range, " "max partial allowed is %i"), n_partials); } /* get a pointer to the beginning of the data */ p->datastart = (double *) (p->atsmemfile->beginp + sizeof(ATSSTRUCT)); /* get increments for the partials */ switch (type) { case 1: p->firstpartial = (int) (1 + 2 * (*p->iptloffset)); p->partialinc = 2 * (int)(*p->iptlincr); p->frmInc = n_partials * 2 + 1; break; case 2: p->firstpartial = (int) (1 + 3 * (*p->iptloffset)); p->partialinc = 3 * (int)(*p->iptlincr); p->frmInc = n_partials * 3 + 1; break; case 3: p->firstpartial = (int) (1 + 2 * (*p->iptloffset)); p->partialinc = 2 * (int)(*p->iptlincr); p->frmInc = n_partials * 2 + 26; break; case 4: p->firstpartial = (int) (1 + 3 * (*p->iptloffset)); p->partialinc = 3 * (int)(*p->iptlincr); p->frmInc = n_partials * 3 + 26; break; default: return csound->InitError(csound, Str("ATSCROSS: Type not implemented")); } /* flag set to reduce the amount of warnings sent out */ /* for time pointer out of range */ p->prFlg = 1; /* true */ return OK; } static int atscrossset_S(CSOUND *csound, ATSCROSS *p) { char atsfilname[MAXNAME]; ATSSTRUCT *atsh; FUNC *ftp; int memsize; int type, n_partials; /* set up function table for synthesis */ if (UNLIKELY((ftp = csound->FTFind(csound, p->ifn)) == NULL)) { return csound->InitError(csound, Str("ATSCROSS: Function table number for " "synthesis waveform not valid")); } p->ftp = ftp; /* load memfile */ p->swapped = load_atsfile(csound, p, &(p->atsmemfile), atsfilname, p->ifileno, 1); if (UNLIKELY(p->swapped < 0)) return NOTOK; atsh = (ATSSTRUCT*) p->atsmemfile->beginp; /* calculate how much memory we have to allocate for this */ memsize = (int)(*p->iptls) * (sizeof(ATS_DATA_LOC) + sizeof(double) + sizeof(MYFLT)) ; /* allocate space if we need it */ /* need room for a buffer and an array of oscillator phase increments */ if (p->auxch.auxp == NULL || p->auxch.size >= (unsigned int)memsize) csound->AuxAlloc(csound, (size_t) memsize, &p->auxch); /* set up the buffer, phase, etc. */ p->buf = (ATS_DATA_LOC *) (p->auxch.auxp); p->oscphase = (double *) (p->buf + (int)(*p->iptls)); p->oldamps = (MYFLT *) (p->oscphase + (int)(*p->iptls)); if (p->swapped == 1) { p->maxFr = (int) bswap(&atsh->nfrms) - 1; p->timefrmInc = bswap(&atsh->nfrms) / bswap(&atsh->dur); type = (int) bswap(&atsh->type); n_partials = (int) bswap(&atsh->npartials); } else { p->maxFr = (int) atsh->nfrms - 1; p->timefrmInc = atsh->nfrms / atsh->dur; type = (int) atsh->type; n_partials = (int) atsh->npartials; } /* make sure partials are in range */ if (UNLIKELY((int)(*p->iptloffset + *p->iptls * *p->iptlincr) > n_partials || (int)(*p->iptloffset) < 0)) { return csound->InitError(csound, Str("ATSCROSS: Partial(s) out of range, " "max partial allowed is %i"), n_partials); } /* get a pointer to the beginning of the data */ p->datastart = (double *) (p->atsmemfile->beginp + sizeof(ATSSTRUCT)); /* get increments for the partials */ switch (type) { case 1: p->firstpartial = (int) (1 + 2 * (*p->iptloffset)); p->partialinc = 2 * (int)(*p->iptlincr); p->frmInc = n_partials * 2 + 1; break; case 2: p->firstpartial = (int) (1 + 3 * (*p->iptloffset)); p->partialinc = 3 * (int)(*p->iptlincr); p->frmInc = n_partials * 3 + 1; break; case 3: p->firstpartial = (int) (1 + 2 * (*p->iptloffset)); p->partialinc = 2 * (int)(*p->iptlincr); p->frmInc = n_partials * 2 + 26; break; case 4: p->firstpartial = (int) (1 + 3 * (*p->iptloffset)); p->partialinc = 3 * (int)(*p->iptlincr); p->frmInc = n_partials * 3 + 26; break; default: return csound->InitError(csound, Str("ATSCROSS: Type not implemented")); } /* flag set to reduce the amount of warnings sent out */ /* for time pointer out of range */ p->prFlg = 1; /* true */ return OK; } static void FetchCROSSPartials(ATSCROSS *p, ATS_DATA_LOC *buf, MYFLT position) { MYFLT frac; /* the distance in time we are between frames */ double *frm_0, *frm_1; double frm0amp, frm0freq, frm1amp, frm1freq; int frame; int i; /* for the for loop */ int partialloc = p->firstpartial; int npartials = (int) *p->iptls; frame = (int) position; frm_0 = p->datastart + frame * p->frmInc; /* if we are using the data from the last frame */ /* we should not try to interpolate */ if (UNLIKELY(frame == p->maxFr)) { if (p->swapped == 1) { for (i = 0; i < npartials; i++) { buf[i].amp = bswap(&frm_0[partialloc]); /* calc amplitude */ buf[i].freq = bswap(&frm_0[partialloc + 1]); partialloc += p->partialinc; } } else { for (i = 0; i < npartials; i++) { buf[i].amp = frm_0[partialloc]; /* calc amplitude */ buf[i].freq = frm_0[partialloc + 1]; partialloc += p->partialinc; } } return; } frac = position - frame; frm_1 = frm_0 + p->frmInc; if (p->swapped == 1) { for (i = 0; i < npartials; i++) { frm0amp = frm_0[partialloc]; frm0freq = frm_0[partialloc + 1]; frm1amp = frm_1[partialloc]; frm1freq = frm_1[partialloc + 1]; buf[i].amp = frm0amp + frac * (frm1amp - frm0amp); /* calc amplitude */ buf[i].freq = frm0freq + frac * (frm1freq - frm0freq); /* calc freq */ partialloc += p->partialinc; /* get to the next partial */ } } else { for (i = 0; i < npartials; i++) { /* calc amplitude */ buf[i].amp = frm_0[partialloc] + frac * (frm_1[partialloc] - frm_0[partialloc]); /* calc freq */ buf[i].freq = frm_0[partialloc + 1] + frac * (frm_1[partialloc + 1] - frm_0[partialloc + 1]); partialloc += p->partialinc; /* get to the next partial */ } } } static void ScalePartials( CSOUND *csound, ATS_DATA_LOC *cbuf, /* the current buffer */ int cbufnp, /* the current buffer's number of partials */ MYFLT cbufamp, /* the amplitude for the current buffer */ ATS_DATA_LOC *tbuf, /* the table buffer */ int tbufnp, /* the table buffer's n partials */ MYFLT tbufamp, /* the amp of the table buffer */ MYFLT kthresh ) { MYFLT tempamp; /* hold the cbufn amp for a bit */ MYFLT frac; /* for interpilation */ int i, j=0; /* for the for loop */ for (i = 0; i < cbufnp; i++) { /* look for closest frequency in buffer */ for(j=0;j < tbufnp; j++) { if (tbuf[j].freq > cbuf[i].freq) break; } tempamp = FL(0.0); /* make sure we are not going to overstep our array */ if (LIKELY(j < tbufnp && j > 0)) { /* interp amplitude from table */ frac = (cbuf[i].freq - tbuf[j - 1].freq) / (tbuf[j].freq - tbuf[j - 1].freq); tempamp = tbuf[j - 1].amp + frac * (tbuf[j].amp - tbuf[j - 1].amp); } else if (j == tbufnp) { /* this means the last value in the table */ /* is equal to a value in the current buffer */ if (cbuf[i + 1].freq == tbuf[tbufnp - 1].freq) tempamp = tbuf[tbufnp - 1].amp; } /* do the actual scaling */ if (i kthresh) cbuf[i].amp = cbuf[i].amp * cbufamp + tempamp*tbufamp; else cbuf[i].amp *= cbufamp; } } static int atscross(CSOUND *csound, ATSCROSS *p) { ATSBUFREAD *atsbufreadaddr; MYFLT frIndx, *oldamps = p->oldamps, a, inca; MYFLT *ar, amp, fract, v1, *ftab; FUNC *ftp; int32 lobits, phase, inc; double *oscphase; int i; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int numpartials = (int) *p->iptls; ATS_DATA_LOC *buf; atsbufreadaddr = *(get_atsbufreadaddrp(csound)); if (UNLIKELY(atsbufreadaddr == NULL)) goto err1; buf = p->buf; /* ftp is a pointer to the ftable */ ftp = p->ftp; /* make sure time pointer is within range */ if (UNLIKELY((frIndx = *(p->ktimpnt) * p->timefrmInc) < FL(0.0))) { frIndx = FL(0.0); if (UNLIKELY(p->prFlg)) { p->prFlg = 0; csound->Warning(csound, Str("ATSCROSS: only positive time pointer " "values are allowed, setting to zero\n")); } } else if (OUT_OF_FRAMES) { /* if we are trying to get frames past where we have data */ frIndx = (MYFLT) p->maxFr; if (UNLIKELY(p->prFlg)) { p->prFlg = 0; /* set to false */ csound->Warning(csound, Str("ATSCROSS: time pointer out of range, " "truncating to last frame\n")); } } else p->prFlg = 1; FetchCROSSPartials(p, buf, frIndx); ScalePartials(csound, buf, /* the current buffer */ (int) *(p->iptls), /* the current buffer's number of partials */ *(p->kmyamp), /* the amplitude for the current buffer */ atsbufreadaddr->table, /* the table buffer */ (int) *(atsbufreadaddr->iptls), /* the table buffer's n partials */ *p->katsbufamp, *p->kthresh); /* the amp of the table buffer */ oscphase = p->oscphase; /* initialise output to zero */ ar = p->aoutput; memset(ar, 0, nsmps*sizeof(MYFLT)); if (UNLIKELY(early)) nsmps -= early; for (i = 0; i < numpartials; i++) { lobits = ftp->lobits; amp = csound->e0dbfs * (MYFLT) p->buf[i].amp; phase = MYFLT2LONG (oscphase[i]); ar = p->aoutput; /* ar is a pointer to the audio output */ inca = (amp-oldamps[i])/nsmps; /* put in * kfmod */ inc = MYFLT2LONG(p->buf[i].freq * csound->sicvt * *p->kfmod); a = oldamps[i]; for (n=offset; nftable + (phase >> lobits); v1 = ftab[0]; fract = (MYFLT) PFRAC(phase); ar[n] += (v1 + fract * (ftab[1] - v1)) * a; phase += inc; phase &= PHMASK; a += inca; } oscphase[i] = (double) phase; oldamps[i] = amp; //oscphase++; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("ATSCROSS: you must have an " "atsbufread before an atsinterpread")); } /* end of ugnorman.c */ #define S(x) sizeof(x) static OENTRY localops[] = { { "ATSread", S(ATSREAD), 0, 3, "kk", "kSi", (SUBR) atsreadset_S, (SUBR) atsread, (SUBR) NULL }, { "ATSread.i", S(ATSREAD), 0, 3, "kk", "kii", (SUBR) atsreadset, (SUBR) atsread, (SUBR) NULL }, { "ATSreadnz", S(ATSREADNZ), 0, 3, "k", "kSi", (SUBR) atsreadnzset_S, (SUBR) atsreadnz, (SUBR) NULL }, { "ATSreadnz.i", S(ATSREADNZ), 0, 3, "k", "kii", (SUBR) atsreadnzset, (SUBR) atsreadnz, (SUBR) NULL }, { "ATSadd", S(ATSADD), TR, 5, "a", "kkSiiopo", (SUBR) atsaddset_S, (SUBR) NULL, (SUBR) atsadd }, { "ATSadd.i", S(ATSADD), TR, 5, "a", "kkiiiopo", (SUBR) atsaddset, (SUBR) NULL, (SUBR) atsadd }, { "ATSaddnz", S(ATSADDNZ), 0, 5, "a", "kSiop", (SUBR) atsaddnzset_S, (SUBR) NULL, (SUBR) atsaddnz }, { "ATSaddnz.i", S(ATSADDNZ), 0, 5, "a", "kiiop", (SUBR) atsaddnzset, (SUBR) NULL, (SUBR) atsaddnz }, { "ATSsinnoi", S(ATSSINNOI), 0,5, "a", "kkkkSiop", (SUBR) atssinnoiset_S, (SUBR) NULL, (SUBR) atssinnoi }, { "ATSsinnoi.i", S(ATSSINNOI), 0,5, "a", "kkkkiiop", (SUBR) atssinnoiset, (SUBR) NULL, (SUBR) atssinnoi }, { "ATSbufread", S(ATSBUFREAD), 0,3, "", "kkSiop", (SUBR) atsbufreadset_S, (SUBR) atsbufread, (SUBR) NULL }, { "ATSbufread.i", S(ATSBUFREAD), 0,3, "", "kkiiop", (SUBR) atsbufreadset, (SUBR) atsbufread, (SUBR) NULL }, { "ATSpartialtap", S(ATSPARTIALTAP), 0,3, "kk", "i", (SUBR) atspartialtapset, (SUBR) atspartialtap, (SUBR) NULL }, { "ATSinterpread", S(ATSINTERPREAD), 0,3, "k", "k", (SUBR) atsinterpreadset, (SUBR) atsinterpread, (SUBR) NULL }, { "ATScross", S(ATSCROSS), TR, 5, "a", "kkSikkiopoo", (SUBR) atscrossset_S, (SUBR) NULL, (SUBR) atscross }, { "ATSinfo", S(ATSINFO), 0,1, "i", "Si", (SUBR) atsinfo_S, (SUBR) NULL, (SUBR) NULL }, { "ATScross.i", S(ATSCROSS), TR, 5, "a", "kkiikkiopoo", (SUBR) atscrossset, (SUBR) NULL, (SUBR) atscross }, { "ATSinfo.i", S(ATSINFO), 0,1, "i", "ii", (SUBR) atsinfo, (SUBR) NULL, (SUBR) NULL } }; int ugnorman_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/ugnorman.h000066400000000000000000000213631321653344700165010ustar00rootroot00000000000000/* ugnorman.h: This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* ats-csound version 0.1 * Mon May 10 19:44:46 PDT 2004 * header file for all of the ATScsound functions by Alex Norman */ #include "stdopcod.h" #include #include #include #include typedef struct atsdataloc { double amp; double freq; } ATS_DATA_LOC; typedef struct _randiats { /* the data for the randi UG */ int size; /* size of the frame in samples this should be sr/freq. */ int cnt; /* sample position counter */ int32 a1; /* first amplitude value */ int32 a2; /* next amplitude value */ } RANDIATS; typedef struct _atsnzaux { double buf[25]; MYFLT phaseinc[25]; MYFLT nfreq[25]; RANDIATS randinoise[25]; } atsnzAUX; typedef struct atsstruct { double magic; /* ats magic number */ double sampr; /* sampling rate */ double frmsz; /* frame size in samples */ double winsz; /* window size in samples */ double npartials; /* number of partials */ double nfrms; /* number of frames */ double ampmax; /* max amplitude */ double freqmax; /* max frequency */ double dur; /* duration seconds */ double type; /* Ats Frame type 1-4 */ } ATSSTRUCT; typedef struct _atsinfo { OPDS h; /* the return value, the ats file and a location selection */ MYFLT *ireturn, *ifileno, *ilocation; } ATSINFO; /* structures to pass data to the opcodes */ typedef struct _atsread { OPDS h; /* outputs (2) and inputs */ MYFLT *kfreq, *kamp, *ktimpnt, *ifileno, *ipartial; /* indicates the maximun frame */ int maxFr; /* a flag used to indicate if we've steped out of the time range */ /* of the data, so we do not print too many warnings */ int prFlg; /* points to the start of the data */ double *datastart; /* tells the location of the partal to output */ /* and the number of doubles to increment to get to the next frame */ int partialloc, frmInc; MEMFIL *atsmemfile; double timefrmInc; /* indicates if the data file is byte swapped or not */ int swapped; } ATSREAD; typedef struct _atsreadnz { OPDS h; MYFLT *kenergy, *ktimpnt, *ifileno, *inzbin; /* outputs (1) and inputs */ int maxFr; /* a flag used to indicate if we've steped out of the time range */ /* of the data, so we do not print too many warnings */ int prFlg; double *datastart; /* points to the start of the data */ int nzbandloc, frmInc; MEMFIL *atsmemfile; double timefrmInc; int swapped; /* indicates if the data file is byte swapped or not */ } ATSREADNZ; typedef struct _atsadd { OPDS h; /* audio output and k & i inputs */ MYFLT *aoutput, *ktimpnt, *kfmod, *ifileno, *ifn, *iptls; /* optional arguments */ MYFLT *iptloffset, *iptlincr, *igatefun; /* pointer to table with wave to synthesize sound */ FUNC *ftp, *AmpGateFunc; AUXCH auxch; MEMFIL *atsmemfile; double maxFr; /* a flag used to indicate if we've steped out of the time range */ /* of the data, so we do not print too many warnings */ int prFlg; double timefrmInc; double MaxAmp; /* maximum amplitude in anaylsis file */ int firstpartial, partialinc, frmInc; double *datastart; double *oscphase; /* oscillator phase */ ATS_DATA_LOC *buf; int swapped; /* indicates if the data file is byte swapped or not */ MYFLT *oldamps; } ATSADD; typedef struct _atsaddnz { OPDS h; /* audio output and k & i inputs */ MYFLT *aoutput, *ktimpnt, *ifileno, *ibands; /* optional arguments */ MYFLT *ibandoffset, *ibandincr; MEMFIL *atsmemfile; /* a pointer into the ATS file */ double maxFr; int prFlg; int frmInc; /* amount to increment frame pointer to get to next frame */ double timefrmInc; double winsize; /* size of windows in analysis file, used to */ /* compute RMS amplitude from energy in noise band */ double *datastart; double buf[25]; /* stores band information for passing data */ double phaseinc[25]; /* to create an array of noise */ double oscphase[25]; /* the phase of all the oscilators */ RANDIATS randinoise[25]; /* pointer to the interpolated random noise info */ double nfreq[25]; int firstband; int swapped; /* indicates if the data file is byte swapped or not */ int bands, bandoffset, bandincr; ATSSTRUCT atshead; } ATSADDNZ; struct _atsbufread { OPDS h; MYFLT *ktimpnt, *kfmod, *ifileno, *iptls; MYFLT *iptloffset, *iptlincr; /* optional arguments */ MEMFIL *mfp; int maxFr, prFlg; /* base Frame (in frameData0) and maximum frame on file, ptr to fr, size */ AUXCH auxch; ATS_DATA_LOC *table; /* store freq and amp info for later use */ ATS_DATA_LOC *utable; /* store freq and amp info for later use (unsorted) */ int frmInc; /* amount to increment frame pointer to get to next frame */ int firstpartial; /* location of first wanted partial in the frame */ int partialinc; /* amount to increment pointer by */ /* to get at the next partial in a frame */ double timefrmInc; MYFLT MaxAmp; /* maximum amplitude in anaylsis file */ double *datastart; /* pointer to the data (past the header) */ ATSSTRUCT atshead; int swapped; /* indicates if the data file is byte swapped or not */ }; typedef struct _atscross { OPDS h; /* audio output and k & i inputs */ MYFLT *aoutput, *ktimpnt, *kfmod, *ifileno, *ifn; MYFLT *kmyamp, *katsbufamp, *iptls; /* optional arguments */ MYFLT *iptloffset, *iptlincr, *igatefun, *kthresh; /* pointer to table with wave to synthesize sound */ FUNC *ftp, *AmpGateFunc; AUXCH auxch; MEMFIL *atsmemfile; double maxFr; /* a flag used to indicate if we've steped out of the time range */ /* of the data, so we do not print too many warnings */ int prFlg; double timefrmInc; double MaxAmp; /* maximum amplitude in anaylsis file */ int firstpartial, partialinc, frmInc; double *datastart; double *oscphase; /* oscillator phase */ ATS_DATA_LOC *buf; int swapped; /* indicates if the data file is byte swapped or not */ MYFLT *oldamps; } ATSCROSS; /* modified from atsadd */ typedef struct _atssinnoi { OPDS h; /* audio output and k & i inputs */ MYFLT *aoutput, *ktimpnt, *ksinamp, *knzamp, *kfreq, *ifileno, *iptls; /* optional arguments */ MYFLT *iptloffset, *iptlincr, *igatefun; MEMFIL *atsmemfile; /* a pointer into the ATS file */ AUXCH auxch; double maxFr; int prFlg; int nzmemsize; /* double winsize; */ /* size of windows in analysis file, used to */ /* compute RMS amplitude from energy in noise band */ double *datastart; double *nzdata; int firstpartial; int partialinc; int firstband; int frmInc; /* amount to increment frame pointer to get to next frame */ double timefrmInc; int npartials; ATS_DATA_LOC *oscbuf; /* stores band information for passing data */ double *nzbuf; /* stores band information for passing data */ double *oscphase; /* the phase of all the oscilators */ RANDIATS *randinoise; /* a pointer to the interpolated random noise info */ ATSSTRUCT *atshead; char *filename; int swapped; /* indicates if the data file is byte swapped or not */ double noiphase[25]; double phaseinc[25]; } ATSSINNOI; typedef struct _atspartialtap { OPDS h; MYFLT *kfreq, *kamp, *iparnum; /* out: freq, amp, in: partialnumber */ } ATSPARTIALTAP; typedef struct _atsinterpread { OPDS h; MYFLT *kamp, *kfreq; /* output amp, input: frequency */ int overflowflag; } ATSINTERPREAD; csound-6.10.0/Opcodes/ugsc.c000066400000000000000000000547151321653344700156160ustar00rootroot00000000000000/* ugsc.c: Copyright (C) 1999 Sean Costello This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* ugsc.c -- Opcodes from Sean Costello */ #include "stdopcod.h" #include "ugsc.h" /* svfilter.c * * Copyright 1999, by Sean M. Costello * * svfilter is an implementation of Hal Chamberlin's state variable filter * algorithm, from "Musical Applications of Microprocessors" (Hayden Books, * Indianapolis, Indiana, 1985), 2nd. edition, pp. 489-492. It implements * a second-order resonant filter, with lowpass, highpass and bandpass * outputs. * */ static int svfset(CSOUND *csound, SVF *p) { if (*p->iskip) { /* set initial delay states to 0 */ p->ynm1 = p->ynm2 = FL(0.0); } return OK; } static int svf(CSOUND *csound, SVF *p) { MYFLT f1 = FL(0.0), q1 = FL(1.0), scale = FL(1.0), lfco = -FL(1.0), lq = -FL(1.0); MYFLT *low, *high, *band, *in, ynm1, ynm2; MYFLT low2, high2, band2; MYFLT *kfco = p->kfco, *kq = p->kq; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int asgf = IS_ASIG_ARG(p->kfco), asgq = IS_ASIG_ARG(p->kq); in = p->in; low = p->low; band = p->band; high = p->high; ynm1 = p->ynm1; ynm2 = p->ynm2; /* equations derived from Hal Chamberlin, "Musical Applications * of Microprocessors. */ if (UNLIKELY(offset)) { memset(low, '\0', offset*sizeof(MYFLT)); memset(high, '\0', offset*sizeof(MYFLT)); memset(band, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&low[nsmps], '\0', early*sizeof(MYFLT)); memset(&high[nsmps], '\0', early*sizeof(MYFLT)); memset(&band[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; npidsr)); /* Protect against division by zero */ if (UNLIKELY(qiscl) scale = q1; } low[n] = low2 = ynm2 + f1 * ynm1; high[n] = high2 = scale * in[n] - low2 - q1 * ynm1; band[n] = band2 = f1 * high2 + ynm1; ynm1 = band2; ynm2 = low2; } p->ynm1 = ynm1; p->ynm2 = ynm2; return OK; } /* hilbert.c * * Copyright 1999, by Sean M. Costello * * hilbert is an implementation of an IIR Hilbert transformer. * The structure is based on two 6th-order allpass filters in * parallel, with a constant phase difference of 90 degrees * (+- some small amount of error) between the two outputs. * Allpass coefficients are calculated at i-time. */ static int hilbertset(CSOUND *csound, HILBERT *p) { int j; /* used to increment for loop */ /* pole values taken from Bernie Hutchins, "Musical Engineer's Handbook" */ double poles[12] = {0.3609, 2.7412, 11.1573, 44.7581, 179.6242, 798.4578, 1.2524, 5.5671, 22.3423, 89.6271, 364.7914, 2770.1114}; double polefreq, rc, alpha, beta; /* calculate coefficients for allpass filters, based on sampling rate */ for (j=0; j<12; j++) { /* p->coef[j] = (1 - (15 * PI * pole[j]) / CS_ESR) / (1 + (15 * PI * pole[j]) / CS_ESR); */ polefreq = poles[j] * 15.0; rc = 1.0 / (2.0 * PI * polefreq); alpha = 1.0 / rc; alpha = alpha * 0.5 * (double)csound->onedsr; beta = (1.0 - alpha) / (1.0 + alpha); p->xnm1[j] = p->ynm1[j] = FL(0.0); p->coef[j] = -(MYFLT)beta; } return OK; } static int hilbert(CSOUND *csound, HILBERT *p) { MYFLT xn1, yn1, xn2, yn2; MYFLT *out1, *out2, *in; MYFLT *coef; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int j; coef = p->coef; out1 = p->out1; out2 = p->out2; in = p->in; if (UNLIKELY(offset)) { memset(out1, '\0', offset*sizeof(MYFLT)); memset(out2, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&out1[nsmps], '\0', early*sizeof(MYFLT)); memset(&out2[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nynm1[j]) + p->xnm1[j]; p->xnm1[j] = xn1; p->ynm1[j] = yn1; xn1 = yn1; } xn2 = in[n]; /* 6th order allpass filter for cosine output. Structure is * 6 first-order allpass sections in series. Coefficients * taken from arrays calculated at i-time. */ for (j=6; j < 12; j++) { yn2 = coef[j] * (xn2 - p->ynm1[j]) + p->xnm1[j]; p->xnm1[j] = xn2; p->ynm1[j] = yn2; xn2 = yn2; } out1[n] = yn2; out2[n] = yn1; } return OK; } /* resonrz.c * * Copyright 1999, by Sean M. Costello * * resonr and resonz are implementations of second-order * bandpass resonators, with added zeroes in the transfer function. * The algorithms are based upon the work of Julius O. Smith and * John Stautner at Stanford, and Ken Steiglitz at Princeton. * */ static int resonzset(CSOUND *csound, RESONZ *p) { /* error message code derived from code for reson in ugens5.c */ int scaletype; p->scaletype = scaletype = (int)*p->iscl; if (UNLIKELY(UNLIKELY(scaletype && scaletype != 1 && scaletype != 2))) { return csound->InitError(csound, Str("illegal reson iscl value, %f"), (float)*p->iscl); } if (!(*p->istor)) p->xnm1 = p->xnm2 = p->ynm1 = p->ynm2 = 0.0; return OK; } static int resonr(CSOUND *csound, RESONZ *p) { /* * * An implementation of the 2-pole, 2-zero reson filter * described by Julius O. Smith and James B. Angell in * "A Constant Gain Digital Resonator Tuned by a Single * Coefficient," Computer Music Journal, Vol. 6, No. 4, * Winter 1982, p.36-39. resonr implements the version * where the zeros are located at + and - the square root * of r, where r is the pole radius of the reson filter. * */ double r = 0.0, scale = 1.0; /* radius & scaling factor */ double c1=0.0, c2=0.0; /* filter coefficients */ MYFLT *out, *in; double xn, yn, xnm1, xnm2, ynm1, ynm2; MYFLT *kcf = p->kcf, *kbw = p->kbw; MYFLT lcf = -FL(1.0), lbw = -FL(1.0); uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int asgf = IS_ASIG_ARG(p->kcf), asgw = IS_ASIG_ARG(p->kbw); out = p->out; in = p->in; xnm1 = p->xnm1; xnm2 = p->xnm2; ynm1 = p->ynm1; ynm2 = p->ynm2; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nmpidsr)); c1 = 2.0 * r * cos((double)(cf * csound->tpidsr)); c2 = r * r; if (p->scaletype == 1) scale = 1.0 - r; else if (p->scaletype == 2) scale = sqrt(1.0 - r); } xn = (double)in[n]; out[n] = (MYFLT)(yn = scale * (xn - r * xnm2) + c1 * ynm1 - c2 * ynm2); xnm2 = xnm1; xnm1 = xn; ynm2 = ynm1; ynm1 = yn; } p->xnm1 = xnm1; p->xnm2 = xnm2; p->ynm1 = ynm1; p->ynm2 = ynm2; return OK; } static int resonz(CSOUND *csound, RESONZ *p) { /* * * An implementation of the 2-pole, 2-zero reson filter * described by Julius O. Smith and James B. Angell in * "A Constant Gain Digital Resonator Tuned by a Single * Coefficient," Computer Music Journal, Vol. 6, No. 4, * Winter 1982, p.36-39. resonr implements the version * where the zeros are located at z = 1 and z = -1. * */ double r = 0.0, scale = 1.0; /* radius & scaling factor */ double c1=0.0, c2=0.0; /* filter coefficients */ MYFLT *out, *in; double xn, yn, xnm1, xnm2, ynm1, ynm2; MYFLT *kcf = p->kcf, *kbw = p->kbw; MYFLT lcf = -FL(1.0), lbw = -FL(1.0); uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int asgf = IS_ASIG_ARG(p->kcf), asgw = IS_ASIG_ARG(p->kbw); /* Normalizing factors derived from equations in Ken Steiglitz, * "A Note on Constant-Gain Digital Resonators," Computer * Music Journal, vol. 18, no. 4, pp. 8-10, Winter 1982. */ out = p->out; in = p->in; xnm1 = p->xnm1; xnm2 = p->xnm2; ynm1 = p->ynm1; ynm2 = p->ynm2; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; npidsr)); c1 = 2.0 * r * cos((double)(csound->tpidsr*cf)); c2 = r * r; if (p->scaletype == 1) scale = (1.0 - c2) * 0.5; else if (p->scaletype == 2) scale = sqrt((1.0 - c2) * 0.5); } xn = (double)in[n]; out[n] = (MYFLT)(yn = scale * (xn - xnm2) + c1 * ynm1 - c2 * ynm2); xnm2 = xnm1; xnm1 = xn; ynm2 = ynm1; ynm1 = yn; } p->xnm1 = xnm1; p->xnm2 = xnm2; p->ynm1 = ynm1; p->ynm2 = ynm2; return OK; } static int phaser1set(CSOUND *csound, PHASER1 *p) { int loop = (int) MYFLT2LONG(*p->iorder); int32 nBytes = (int32) loop * (int32) sizeof(MYFLT); if (*p->istor == FL(0.0) || p->auxx.auxp == NULL || (int)p->auxx.sizeauxy.auxp == NULL || (int)p->auxy.sizeAuxAlloc(csound, nBytes, &p->auxx); csound->AuxAlloc(csound, nBytes, &p->auxy); p->xnm1 = (MYFLT *) p->auxx.auxp; p->ynm1 = (MYFLT *) p->auxy.auxp; } else if ((int32) p->auxx.size < nBytes || (int32) p->auxy.size < nBytes) { /* Existing arrays too small so copy */ void *tmp1, *tmp2; size_t oldSize1 = (size_t) p->auxx.size; size_t oldSize2 = (size_t) p->auxy.size; tmp1 = csound->Malloc(csound, oldSize1 + oldSize2); tmp2 = (char*) tmp1 + (int) oldSize1; memcpy(tmp1, p->auxx.auxp, oldSize1); memcpy(tmp2, p->auxy.auxp, oldSize2); csound->AuxAlloc(csound, nBytes, &p->auxx); csound->AuxAlloc(csound, nBytes, &p->auxy); memcpy(p->auxx.auxp, tmp1, oldSize1); memcpy(p->auxy.auxp, tmp2, oldSize2); csound->Free(csound, tmp1); p->xnm1 = (MYFLT *) p->auxx.auxp; p->ynm1 = (MYFLT *) p->auxy.auxp; } p->loop = loop; return OK; } static int phaser1(CSOUND *csound, PHASER1 *p) { MYFLT xn = FL(0.0), yn = FL(0.0); MYFLT *out, *in; MYFLT feedback; MYFLT coef = FABS(*p->kcoef), fbgain = *p->fbgain; MYFLT beta, wp; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; int j; feedback = p->feedback; out = p->out; in = p->in; //if (coef<=FL(0.0)) coef = -coef; /* frequency will "fold over" if <= 0 Hz */ /* next two lines implement bilinear z-transform, to convert * frequency value into a useable coefficient for the * allpass filters. */ wp = csound->pidsr * coef; beta = (FL(1.0) - wp)/(FL(1.0) + wp); if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset; iloop; j++) { /* Difference equation for 1st order * allpass filter */ yn = beta * (xn + p->ynm1[j]) - p->xnm1[j]; /* Stores state values in arrays */ p->xnm1[j] = xn; p->ynm1[j] = yn; xn = yn; } out[i] = yn; feedback = yn; } p->feedback = feedback; return OK; } static int phaser2set(CSOUND *csound, PHASER2 *p) { int modetype; int loop; p->modetype = modetype = (int)*p->mode; if (UNLIKELY(UNLIKELY(modetype && modetype != 1 && modetype != 2))) { return csound->InitError(csound, Str("Phaser mode must be either 1 or 2")); } loop = p->loop = (int) MYFLT2LONG(*p->order); csound->AuxAlloc(csound, (size_t)loop*sizeof(MYFLT), &p->aux1); csound->AuxAlloc(csound, (size_t)loop*sizeof(MYFLT), &p->aux2); p->nm1 = (MYFLT *) p->aux1.auxp; p->nm2 = (MYFLT *) p->aux2.auxp; /* *** This is unnecessary as AuxAlloc zeros *** */ /* for (j=0; j< loop; j++) */ /* p->nm1[j] = p->nm2[j] = FL(0.0); */ return OK; } static int phaser2(CSOUND *csound, PHASER2 *p) { MYFLT xn = FL(0.0), yn = FL(0.0); MYFLT *out, *in; MYFLT kbf = *p->kbf, kq = *p->kbw; MYFLT ksep = *p->ksep, fbgain = *p->fbgain; MYFLT b, a, r, freq; MYFLT temp; MYFLT *nm1, *nm2, feedback; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; int j; nm1 = p->nm1; nm2 = p->nm2; feedback = p->feedback; out = p->out; in = p->in; /* frequency of first notch will "fold over" if <= 0 Hz */ if (kbf <=0) kbf = -kbf; /* keeps ksep at a positive value. Otherwise, blow ups are * almost certain to happen. */ if (ksep <= FL(0.0)) ksep = -ksep; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nloop; j++) { if (p->modetype == 1) freq = kbf + (kbf * ksep * j); else { freq = kbf * kk; kk *= ksep; //freq = kbf * csound->intpow(ksep,(int32)j); } /* Note similarities of following equations to * equations in resonr/resonz. The 2nd-order * allpass filter used here is similar to the * typical reson filter, with the addition of zeros. * The pole angle determines the frequency of the * notch, while the pole radius determines the q of * the notch. */ r = EXP(-(freq * csound->pidsr / kq)); b = -FL(2.0) * r * COS(freq * csound->tpidsr); a = r * r; /* Difference equations for implementing canonical * 2nd order section. (Direct Form II) */ temp = xn - b * nm1[j] - a * nm2[j]; yn = a * temp + b * nm1[j] + nm2[j]; nm2[j] = nm1[j]; nm1[j] = temp; xn = yn; } out[n] = yn; feedback = yn; } p->feedback = feedback; return OK; } /* initialization for 2nd-order lowpass filter */ static int lp2_set(CSOUND *csound, LP2 *p) { if (!(*p->istor)) p->ynm1 = p->ynm2 = 0.0; return OK; } /* k-time code for 2nd-order lowpass filter. Derived from code in Hal Chamberlin's "Musical Applications of Microprocessors." */ static int lp2(CSOUND *csound, LP2 *p) { double a, b, c, temp; MYFLT *out, *in; double yn, ynm1, ynm2; MYFLT kfco = *p->kfco, kres = *p->kres; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; temp = (double)(csound->mpidsr * kfco / kres); /* (-PI_F * kfco / (kres * CS_ESR)); */ a = 2.0 * cos((double) (kfco * csound->tpidsr)) * exp(temp); b = exp(temp+temp); c = 1.0 - a + b; out = p->out; in = p->in; ynm1 = p->ynm1; ynm2 = p->ynm2; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nynm1 = ynm1; p->ynm2 = ynm2; return OK; } static int lp2aa(CSOUND *csound, LP2 *p) { double a, b, c, temp; MYFLT *out, *in; double yn, ynm1, ynm2; MYFLT *fcop = p->kfco, *resp = p->kres; MYFLT fco = fcop[0], res = resp[0]; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; temp = (double)(csound->mpidsr * fco / res); /* (-PI_F * kfco / (kres * CS_ESR)); */ a = 2.0 * cos((double) (fco * csound->tpidsr)) * exp(temp); b = exp(temp+temp); c = 1.0 - a + b; out = p->out; in = p->in; ynm1 = p->ynm1; ynm2 = p->ynm2; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nmpidsr * fco / res); /* (-PI_F * kfco / (kres * CS_ESR)); */ a = 2.0 * cos((double) (fco * csound->tpidsr)) * exp(temp); b = exp(temp+temp); c = 1.0 - a + b; } out[n] = (MYFLT)(yn = a * ynm1 - b * ynm2 + c * (double)in[n]); ynm2 = ynm1; ynm1 = yn; } p->ynm1 = ynm1; p->ynm2 = ynm2; return OK; } static int lp2ka(CSOUND *csound, LP2 *p) { double a, b, c, temp; MYFLT *out, *in; double yn, ynm1, ynm2; MYFLT *resp = p->kres; MYFLT fco = *p->kfco, res = resp[0]; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; temp = (double)(csound->mpidsr * fco / res); /* (-PI_F * kfco / (kres * CS_ESR)); */ a = 2.0 * cos((double) (fco * csound->tpidsr)) * exp(temp); b = exp(temp+temp); c = 1.0 - a + b; out = p->out; in = p->in; ynm1 = p->ynm1; ynm2 = p->ynm2; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nmpidsr * fco / res); /* (-PI_F * kfco / (kres * CS_ESR)); */ a = 2.0 * cos((double) (fco * csound->tpidsr)) * exp(temp); b = exp(temp+temp); c = 1.0 - a + b; } out[n] = (MYFLT)(yn = a * ynm1 - b * ynm2 + c * (double)in[n]); ynm2 = ynm1; ynm1 = yn; } p->ynm1 = ynm1; p->ynm2 = ynm2; return OK; } static int lp2ak(CSOUND *csound, LP2 *p) { double a, b, c, temp; MYFLT *out, *in; double yn, ynm1, ynm2; MYFLT *fcop = p->kfco; MYFLT fco = fcop[0], res = *p->kres; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; temp = (double)(csound->mpidsr * fco / res); /* (-PI_F * kfco / (kres * CS_ESR)); */ a = 2.0 * cos((double) (fco * csound->tpidsr)) * exp(temp); b = exp(temp+temp); c = 1.0 - a + b; out = p->out; in = p->in; ynm1 = p->ynm1; ynm2 = p->ynm2; if (UNLIKELY(offset)) memset(out, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&out[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nmpidsr * fco / res); /* (-PI_F * kfco / (kres * CS_ESR)); */ a = 2.0 * cos((double) (fco * csound->tpidsr)) * exp(temp); b = exp(temp+temp); c = 1.0 - a + b; } out[n] = (MYFLT)(yn = a * ynm1 - b * ynm2 + c * (double)in[n]); ynm2 = ynm1; ynm1 = yn; } p->ynm1 = ynm1; p->ynm2 = ynm2; return OK; } #define S(x) sizeof(x) static OENTRY localops[] = { { "svfilter", S(SVF), 0, 5, "aaa", "axxoo", (SUBR)svfset, NULL, (SUBR)svf }, { "hilbert", S(HILBERT), 0,5, "aa", "a", (SUBR)hilbertset, NULL, (SUBR)hilbert }, { "resonr", S(RESONZ), 0,5, "a", "axxoo", (SUBR)resonzset, NULL, (SUBR)resonr}, { "resonz", S(RESONZ), 0,5, "a", "axxoo", (SUBR)resonzset, NULL, (SUBR)resonz}, { "lowpass2.kk", S(LP2), 0,5, "a", "akko", (SUBR)lp2_set, NULL, (SUBR)lp2 }, { "lowpass2.aa", S(LP2), 0,5, "a", "aaao", (SUBR)lp2_set, NULL, (SUBR)lp2aa }, { "lowpass2.ak", S(LP2), 0,5, "a", "aakao", (SUBR)lp2_set, NULL, (SUBR)lp2ak }, { "lowpass2.ka", S(LP2), 0,5, "a", "akao", (SUBR)lp2_set, NULL, (SUBR)lp2ka }, { "phaser2", S(PHASER2), 0,5, "a", "akkkkkk",(SUBR)phaser2set,NULL,(SUBR)phaser2}, { "phaser1", S(PHASER1), 0,5, "a", "akkko", (SUBR)phaser1set, NULL,(SUBR)phaser1} }; int ugsc_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/ugsc.h000066400000000000000000000056111321653344700156120ustar00rootroot00000000000000/* ugsc.h: Copyright (C) 1999 Sean M. Costello This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* svfilter.h * * Copyright 1999, by Sean M. Costello * * svfilter is an implementation of Hal Chamberlin's state variable filter * algorithm, from "Musical Applications of Microprocessors" (Hayden Books, * Indianapolis, Indiana, 1985), 2nd. edition, pp. 489-492. It implements * a second-order resonant filter, with lowpass, highpass and bandpass * outputs. * */ typedef struct { OPDS h; MYFLT *low, *high, *band, *in, *kfco, *kq, *iscl, *iskip; MYFLT ynm1, ynm2; } SVF; /* hilbert.h * * Copyright 1999, by Sean M. Costello * * hilbert is an implementation of an IIR Hilbert transformer. * The structure is based on two 6th-order allpass filters in * parallel, with a constant phase difference of 90 degrees * (+- some small amount of error) between the two outputs. * Allpass coefficients are calculated at i-time. */ typedef struct { OPDS h; MYFLT *out1, *out2, *in; MYFLT xnm1[12], ynm1[12], coef[12]; } HILBERT; /* resonrz.h * * Copyright 1999, by Sean M. Costello * * resonr and resonz are implementations of second-order * bandpass resonators, with added zeroes in the transfer function. * The algorithms are based upon the work of Julius O. Smith and * John Stautner at Stanford, and Ken Steiglitz at Princeton. * */ typedef struct { OPDS h; MYFLT *out, *in, *kcf, *kbw, *iscl, *istor; double xnm1, xnm2, ynm1, ynm2; int scaletype, aratemod; } RESONZ; /* Structure for cascade of 2nd order allpass filters */ typedef struct { OPDS h; MYFLT *out, *in, *kbf, *kbw, *order, *mode, *ksep, *fbgain; int loop, modetype; MYFLT *nm1, *nm2, feedback; AUXCH aux1, aux2; } PHASER2; /* Structure for cascade of 1st order allpass filters*/ typedef struct { OPDS h; MYFLT *out, *in, *kcoef, *iorder, *fbgain, *istor; int loop; MYFLT *xnm1, *ynm1, feedback; AUXCH auxx, auxy; } PHASER1; /* Structure for lowpass filter */ typedef struct { OPDS h; MYFLT *out, *in, *kfco, *kres, *istor; double ynm1, ynm2; } LP2; csound-6.10.0/Opcodes/urandom.c000066400000000000000000000063661321653344700163210ustar00rootroot00000000000000/* urandom.c: Copyright (C) 2010 by John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csdl.h" //#include #ifdef MACOSX #include #endif typedef struct { OPDS h; MYFLT *ar; /* Output */ MYFLT *imin; MYFLT *imax; int ur; MYFLT mul; MYFLT add; } URANDOM; static int urand_deinit(CSOUND *csound, URANDOM *p) { close(p->ur); return OK; } static int urand_init(CSOUND *csound, URANDOM *p) { int ur = open("/dev/urandom", O_RDONLY); if (UNLIKELY(ur<0)) return NOTOK; p->ur = ur; csound->RegisterDeinitCallback(csound, p, (int (*)(CSOUND *, void *)) urand_deinit); p->mul = FL(0.5)*(*p->imax - *p->imin); p->add = FL(0.5)*(*p->imax + *p->imin); return OK; } static int urand_run(CSOUND *csound, URANDOM *p) { int ur = p->ur; /* union ieee754_double x; */ int64_t x; if (UNLIKELY(read(ur, &x, sizeof(int64_t))!=sizeof(int64_t))) return NOTOK; /* x.ieee.exponent = x.ieee.exponent& 0x377; */ /* printf("Debug: %s(%d): %g %d %03x %05x %08x\n", __FILE__, __LINE__, x.d, */ /* x.ieee.negative, x.ieee.exponent, x.ieee.mantissa0, x.ieee.mantissa1); */ *p->ar = p->mul *((MYFLT)x/(MYFLT)INT64_MAX) + p->add; return OK; } static int urand_irate(CSOUND *csound, URANDOM *p) { if (LIKELY(urand_init(csound,p)==OK)) return urand_run(csound,p); else return NOTOK; } static int urand_arun(CSOUND *csound, URANDOM *p) { int ur = p->ur; /* union ieee754_double x; */ int64_t x; MYFLT *ar = p->ar; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; if (UNLIKELY(offset)) memset(ar, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&ar[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nmul *((MYFLT)x/(MYFLT)INT64_MAX) + p->add; } return OK; } #define S(x) sizeof(x) static OENTRY urandom_localops[] = { { "urandom", 0xFFFF, 0, 0, NULL, NULL, NULL}, { "urandom.i", S(URANDOM), 0, 1, "i", "jp", (SUBR) urand_irate }, { "urandom.k", S(URANDOM), 0, 3, "k", "jp", (SUBR) urand_init, (SUBR) urand_run}, { "urandom.a", S(URANDOM), 0, 5, "a", "jp", (SUBR) urand_init, NULL, (SUBR) urand_arun} }; LINKAGE_BUILTIN(urandom_localops) csound-6.10.0/Opcodes/vaops.c000066400000000000000000000066601321653344700160010ustar00rootroot00000000000000/* vaops.c: Copyright (C) 2006 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "interlocks.h" #define MYFLOOR(x) (x >= FL(0.0) ? (int32)x : (int32)((double)x - 0.99999999)) typedef struct { OPDS h; MYFLT *kout, *kindx, *avar; } VA_GET; typedef struct { OPDS h; MYFLT *kval, *kindx, *avar; } VA_SET; typedef struct { OPDS h; MYFLT *kout, *avar, *kindx; } VASIG_GET; typedef struct { OPDS h; MYFLT *avar, *kval, *kindx; } VASIG_SET; static int vaget(CSOUND *csound, VA_GET *p) { int32 ndx = (int32) MYFLOOR((double)*p->kindx); uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; if (UNLIKELY(ndx<(int32)offset || ndx>=(int32)(CS_KSMPS-early))) return csound->PerfError(csound, p->h.insdshead, Str("Out of range in vaget (%d)"), ndx); *p->kout = p->avar[ndx]; return OK; } static int vaset(CSOUND *csound, VA_SET *p) { int32 ndx = (int32) MYFLOOR((double)*p->kindx); uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; if (UNLIKELY(ndx<(int32)offset || ndx>=(int32)(CS_KSMPS-early))) return csound->PerfError(csound, p->h.insdshead, Str("Out of range in vaset (%d)"), ndx); p->avar[ndx] = *p->kval; return OK; } static int vasigget(CSOUND *csound, VASIG_GET *p) { int32 ndx = (int32) MYFLOOR((double)*p->kindx); uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; if (UNLIKELY(ndx<(int32)offset || ndx>=(int32)(CS_KSMPS-early))) return csound->PerfError(csound, p->h.insdshead, Str("Out of range in vaget (%d)"), ndx); *p->kout = p->avar[ndx]; return OK; } static int vasigset(CSOUND *csound, VASIG_SET *p) { int32 ndx = (int32) MYFLOOR((double)*p->kindx); uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; if (UNLIKELY(ndx<(int32)offset || ndx>=(int32)(CS_KSMPS-early))) return csound->PerfError(csound, p->h.insdshead, Str("Out of range in vaset (%d)"), ndx); p->avar[ndx] = *p->kval; return OK; } #define S(x) sizeof(x) static OENTRY vaops_localops[] = { { "vaget", S(VA_GET), 0, 2, "k", "ka", NULL, (SUBR)vaget }, { "vaset", S(VA_SET), 0, 2, "", "kka", NULL, (SUBR)vaset }, { "##array_get", S(VASIG_GET), 0, 2, "k", "ak", NULL, (SUBR)vasigget }, { "##array_set", S(VASIG_SET), 0, 2, "", "akk", NULL, (SUBR)vasigset } }; LINKAGE_BUILTIN(vaops_localops) csound-6.10.0/Opcodes/vbap.c000066400000000000000000001046241321653344700156000ustar00rootroot00000000000000/* vbap.c: Copyright (C) 2000 Ville Pulkki This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* vbap.c assisting functions for VBAP functions for loudspeaker table initialization Re-written to take flexible number of outputs by JPff 2012 */ #include "csoundCore.h" #include "interlocks.h" #include "vbap.h" #include #include #include #include "interlocks.h" #define MATSIZE (4) #define ATORAD (TWOPI_F / FL(360.0)) /* static void choose_ls_triplets(CSOUND *csound, ls *lss, */ /* ls_triplet_chain **ls_triplets, */ /* int ls_amount, int channels); */ static int any_ls_inside_triplet(int, int, int, ls[], int); static void add_ldsp_triplet(CSOUND *csound, int i, int j, int k, ls_triplet_chain **ls_triplets, ls *lss); static void calculate_3x3_matrixes(CSOUND *csound, ls_triplet_chain *ls_triplets, ls lss[], int ls_amount, int ind); static void choose_ls_tuplets(CSOUND *csound, ls lss[], ls_triplet_chain **ls_triplets, int ls_amount, int ind); static void sort_2D_lss(ls lss[], int sorted_lss[], int ls_amount); static inline MYFLT vec_prod(CART_VEC v1, CART_VEC v2) { return (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z); } static inline MYFLT vec_length(CART_VEC v1) { return SQRT(v1.x*v1.x + v1.y*v1.y + v1.z*v1.z); } static MYFLT *create_ls_table(CSOUND *csound, size_t cnt, int ind) { char name[24]; snprintf(name, 24, "vbap_ls_table_%d", ind); csound->DestroyGlobalVariable(csound, name); if (UNLIKELY(csound->CreateGlobalVariable(csound, name, cnt * sizeof(MYFLT)) != 0)) { csound->ErrorMsg(csound, Str("vbap: error allocating loudspeaker table")); return NULL; } return (MYFLT*) (csound->QueryGlobalVariableNoCheck(csound, name)); } void calc_vbap_gns(int ls_set_am, int dim, LS_SET *sets, MYFLT *gains, int ls_amount, CART_VEC cart_dir) /* Selects a vector base of a virtual source. Calculates gain factors in that base. */ { int i,j,k, tmp2; MYFLT vec[3], tmp; /* direction of the virtual source in cartesian coordinates*/ vec[0] = cart_dir.x; vec[1] = cart_dir.y; vec[2] = cart_dir.z; for (i=0; i< ls_set_am; i++) { sets[i].set_gains[0] = FL(0.0); sets[i].set_gains[1] = FL(0.0); sets[i].set_gains[2] = FL(0.0); sets[i].smallest_wt = FL(1000.0); sets[i].neg_g_am = 0; } for (i=0; i< ls_set_am; i++) { for (j=0; j< dim; j++) { for (k=0; k< dim; k++) { sets[i].set_gains[j] += vec[k] * sets[i].ls_mx[((dim * j )+ k)]; } if (sets[i].smallest_wt > sets[i].set_gains[j]) sets[i].smallest_wt = sets[i].set_gains[j]; if (sets[i].set_gains[j] < -FL(0.05)) sets[i].neg_g_am++; } } j=0; tmp = sets[0].smallest_wt; tmp2=sets[0].neg_g_am; for (i=1; i< ls_set_am; i++) { if (sets[i].neg_g_am < tmp2) { tmp = sets[i].smallest_wt; tmp2=sets[i].neg_g_am; j=i; } else if (sets[i].neg_g_am == tmp2) { if (sets[i].smallest_wt > tmp) { tmp = sets[i].smallest_wt; tmp2=sets[i].neg_g_am; j=i; } } } if (sets[j].set_gains[0]<=FL(0.0) && sets[j].set_gains[1]<=FL(0.0) && sets[j].set_gains[2]<=FL(0.0)) { sets[j].set_gains[0] = FL(1.0); sets[j].set_gains[1] = FL(1.0); sets[j].set_gains[2] = FL(1.0); } memset(gains, 0, ls_amount*sizeof(MYFLT)); gains[sets[j].ls_nos[0]-1] = sets[j].set_gains[0]; gains[sets[j].ls_nos[1]-1] = sets[j].set_gains[1]; if (dim==3) gains[sets[j].ls_nos[2]-1] = sets[j].set_gains[2]; for (i=0;iazi > FL(180.0)) avec->azi -= FL(360.0); while (avec->azi < -FL(180.0)) avec->azi += FL(360.0); if (avec->ele > FL(90.0)) avec->ele = FL(90.0); if (avec->ele < -FL(90.0)) avec->ele = -FL(90.0); } void normalize_wts(OUT_WTS *wts) /* performs equal-power normalization to gain factors*/ { double tmp; MYFLT tmp1; if (wts->wt1 < 0) wts->wt1 = FL(0.0); if (wts->wt2 < 0) wts->wt2 = FL(0.0); if (wts->wt3 < 0) wts->wt3 = FL(0.0); tmp = (double)wts->wt1 * wts->wt1; tmp += (double)wts->wt2 * wts->wt2; tmp += (double)wts->wt3 * wts->wt3; tmp = sqrt(tmp); tmp1 = (MYFLT)(1.0 / tmp); wts->wt1 *= tmp1; wts->wt2 *= tmp1; wts->wt3 *= tmp1; } void angle_to_cart(ANG_VEC avec, CART_VEC *cvec) /* conversion */ { /* length unattended */ //MYFLT atorad = (TWOPI_F / FL(360.0)); cvec->x = (MYFLT) (cos((double) (avec.azi * ATORAD)) * cos((double) (avec.ele * ATORAD))); cvec->y = (MYFLT) (sin((double) (avec.azi * ATORAD)) * cos((double) (avec.ele * ATORAD))); cvec->z = (MYFLT) (sin((double) (avec.ele * ATORAD))); } void cart_to_angle(CART_VEC cvec, ANG_VEC *avec) /* conversion */ { MYFLT tmp, tmp2, tmp3, tmp4; //MYFLT atorad = (TWOPI_F / FL(360.0)); tmp3 = SQRT(FL(1.0) - cvec.z*cvec.z); if (FABS(tmp3) > FL(0.001)) { tmp4 = (cvec.x / tmp3); if (tmp4 > FL(1.0)) tmp4 = FL(1.0); if (tmp4 < -FL(1.0)) tmp4 = -FL(1.0); tmp = ACOS(tmp4 ); } else { tmp = FL(10000.0); } if (FABS(cvec.y) <= FL(0.001)) tmp2 = FL(1.0); else tmp2 = cvec.y / FABS(cvec.y); tmp *= tmp2; if (FABS(tmp) <= PI_F) { avec->azi = tmp; avec->azi /= ATORAD; } avec->ele = ASIN(cvec.z); avec->length = SQRT(cvec.x * cvec.x + cvec.y * cvec.y + cvec.z * cvec.z); avec->ele /= ATORAD; } void angle_to_cart_II(ANG_VEC *from, CART_VEC *to) /* conversion, double*/ { MYFLT ang2rad = TWOPI_F / FL(360.0); to->x= COS(from->azi * ang2rad) * COS(from->ele * ang2rad); to->y= SIN(from->azi * ang2rad) * COS(from->ele * ang2rad); to->z= SIN(from->ele * ang2rad); } MYFLT vol_p_side_lgth(int i, int j,int k, ls lss[] ) { /* calculate volume of the parallelepiped defined by the loudspeaker direction vectors and divide it with total length of the triangle sides. This is used when removing too narrow triangles. */ MYFLT volper, lgth; CART_VEC xprod; cross_prod(lss[i].coords, lss[j].coords, &xprod); volper = FABS(vec_prod(xprod, lss[k].coords)); lgth = FABS(vec_angle(lss[i].coords,lss[j].coords)) + FABS(vec_angle(lss[i].coords,lss[k].coords)) + FABS(vec_angle(lss[j].coords,lss[k].coords)); if (LIKELY(lgth>FL(0.00001))) return volper / lgth; else return FL(0.0); } static void choose_ls_triplets(CSOUND *csound, ls *lss, struct ls_triplet_chain **ls_triplets, int ls_amount) /* Selects the loudspeaker triplets, and calculates the inversion matrices for each selected triplet. A line (connection) is drawn between each loudspeaker. The lines denote the sides of the triangles. The triangles should not be intersecting. All crossing connections are searched and the longer connection is erased. This yields non-intesecting triangles, which can be used in panning.*/ { int i, j, k, l, table_size; int *connections; /* int *i_ptr; */ MYFLT *distance_table; int *distance_table_i; int *distance_table_j; MYFLT distance; struct ls_triplet_chain *trip_ptr, *prev, *tmp_ptr; if (UNLIKELY(ls_amount == 0)) { csound->ErrorMsg(csound, Str("Number of loudspeakers is zero\nExiting")); return; } connections = csound->Calloc(csound, ls_amount * ls_amount * sizeof(int)); distance_table = csound->Calloc(csound, ((ls_amount * (ls_amount - 1)) / 2)* sizeof(MYFLT)); distance_table_i = csound->Calloc(csound, ((ls_amount * (ls_amount - 1)) / 2)* sizeof(int)); distance_table_j = csound->Calloc(csound, ((ls_amount * (ls_amount - 1)) / 2)* sizeof(int)); /* i_ptr = (int *) connections; */ /* for (i=0;i< ((CHANNELS) * (CHANNELS )); i++) */ /* *(i_ptr++) = 0; */ for (i=0;i MIN_VOL_P_SIDE_LGTH) { connections[i+ls_amount*j]=1; connections[j+ls_amount*i]=1; connections[i+ls_amount*k]=1; connections[k+ls_amount*i]=1; connections[j+ls_amount*k]=1; connections[k+ls_amount*j]=1; add_ldsp_triplet(csound, i, j, k, ls_triplets, lss); } } /*calculate distancies between all lss and sorting them*/ table_size =(((ls_amount - 1) * (ls_amount)) / 2); for (i=0;i k;l--) { distance_table[l] = distance_table[l-1]; distance_table_i[l] = distance_table_i[l-1]; distance_table_j[l] = distance_table_j[l-1]; } distance_table[k] = distance; distance_table_i[k] = i; distance_table_j[k] = j; } else table_size--; } } /* disconnecting connections which are crossing shorter ones, starting from shortest one and removing all that cross it, and proceeding to next shortest */ for (i=0; i<(table_size); i++) { int fst_ls = distance_table_i[i]; int sec_ls = distance_table_j[i]; if (connections[fst_ls+ls_amount*sec_ls] == 1) for (j=0; jls_nos[0]; j = trip_ptr->ls_nos[1]; k = trip_ptr->ls_nos[2]; if (connections[i+ls_amount*j] == 0 || connections[i+ls_amount*k] == 0 || connections[j+ls_amount*k] == 0 || any_ls_inside_triplet(i,j,k,lss,ls_amount) == 1) { if (prev != NULL) { prev->next = trip_ptr->next; tmp_ptr = trip_ptr; trip_ptr = trip_ptr->next; csound->Free(csound, tmp_ptr); } else { *ls_triplets = trip_ptr->next; tmp_ptr = trip_ptr; trip_ptr = trip_ptr->next; csound->Free(csound, tmp_ptr); } } else { prev = trip_ptr; trip_ptr = trip_ptr->next; } } csound->Free(csound,connections); csound->Free(csound,distance_table); csound->Free(csound,distance_table_i); csound->Free(csound,distance_table_j); } /* returns 1 if there is loudspeaker(s) inside given ls triplet */ static int any_ls_inside_triplet(int a, int b, int c, ls lss[], int ls_amount) { MYFLT invdet; CART_VEC *lp1, *lp2, *lp3; MYFLT invmx[9]; int i,j; MYFLT tmp; int any_ls_inside, this_inside; lp1 = &(lss[a].coords); lp2 = &(lss[b].coords); lp3 = &(lss[c].coords); /* matrix inversion */ invdet = FL(1.0) / ( lp1->x * ((lp2->y * lp3->z) - (lp2->z * lp3->y)) - lp1->y * ((lp2->x * lp3->z) - (lp2->z * lp3->x)) + lp1->z * ((lp2->x * lp3->y) - (lp2->y * lp3->x))); invmx[0] = ((lp2->y * lp3->z) - (lp2->z * lp3->y)) * invdet; invmx[3] = ((lp1->y * lp3->z) - (lp1->z * lp3->y)) * -invdet; invmx[6] = ((lp1->y * lp2->z) - (lp1->z * lp2->y)) * invdet; invmx[1] = ((lp2->x * lp3->z) - (lp2->z * lp3->x)) * -invdet; invmx[4] = ((lp1->x * lp3->z) - (lp1->z * lp3->x)) * invdet; invmx[7] = ((lp1->x * lp2->z) - (lp1->z * lp2->x)) * -invdet; invmx[2] = ((lp2->x * lp3->y) - (lp2->y * lp3->x)) * invdet; invmx[5] = ((lp1->x * lp3->y) - (lp1->y * lp3->x)) * -invdet; invmx[8] = ((lp1->x * lp2->y) - (lp1->y * lp2->x)) * invdet; any_ls_inside = 0; for (i=0; i< ls_amount; i++) { if (i != a && i!=b && i != c) { this_inside = 1; for (j=0; j< 3; j++) { tmp = lss[i].coords.x * invmx[0 + j*3]; tmp += lss[i].coords.y * invmx[1 + j*3]; tmp += lss[i].coords.z * invmx[2 + j*3]; if (tmp < -FL(0.001)) this_inside = 0; } if (this_inside == 1) any_ls_inside=1; } } return any_ls_inside; } static void add_ldsp_triplet(CSOUND *csound, int i, int j, int k, struct ls_triplet_chain **ls_triplets, ls lss[]) { struct ls_triplet_chain *ls_ptr, *prev; ls_ptr = *ls_triplets; prev = NULL; /*printf("Adding triangle %d %d %d %x... \n",i,j,k,ls_ptr);*/ while (ls_ptr != NULL) { /*printf("ls_ptr %x %x\n",ls_ptr,ls_ptr->next);*/ prev = ls_ptr; ls_ptr = ls_ptr->next; } ls_ptr = (struct ls_triplet_chain*) csound->Malloc(csound, sizeof(struct ls_triplet_chain)); if (prev == NULL) *ls_triplets = ls_ptr; else prev->next = ls_ptr; ls_ptr->next = NULL; ls_ptr->ls_nos[0] = i; ls_ptr->ls_nos[1] = j; ls_ptr->ls_nos[2] = k; /*printf("added.\n");*/ } MYFLT angle_in_base(CART_VEC vb1,CART_VEC vb2,CART_VEC vec) { MYFLT tmp1,tmp2; tmp1 = vec_prod(vec,vb2); if (FABS(tmp1) <= FL(0.001)) tmp2 = FL(1.0); else tmp2 = tmp1 / FABS(tmp1); return (vec_angle(vb1,vec) * tmp2); } MYFLT vec_angle(CART_VEC v1, CART_VEC v2) { MYFLT inner= ((v1.x*v2.x + v1.y*v2.y + v1.z*v2.z)/ (vec_length(v1) * vec_length(v2))); if (inner > FL(1.0)) inner= FL(1.0); if (inner < -FL(1.0)) inner = -FL(1.0); return ACOS(inner); } void vec_mean(CART_VEC v1, CART_VEC v2, CART_VEC *v3) { v3->x=(v1.x+v2.x)*FL(0.5); v3->y=(v1.y+v2.y)*FL(0.5); v3->z=(v1.z+v2.z)*FL(0.5); } void cross_prod(CART_VEC v1,CART_VEC v2, CART_VEC *res) { MYFLT length; res->x = (v1.y * v2.z ) - (v1.z * v2.y); res->y = (v1.z * v2.x ) - (v1.x * v2.z); res->z = (v1.x * v2.y ) - (v1.y * v2.x); length= vec_length(*res); res->x /= length; res->y /= length; res->z /= length; } void vec_print(CSOUND *csound, CART_VEC v) { csound->Message(csound, "vec_print %f %f %f\n", v.x, v.y,v.z); } int lines_intersect(int i,int j,int k,int l,ls lss[]) /* checks if two lines intersect on 3D sphere see theory in paper Pulkki, V. Lokki, T. "Creating Auditory Displays with Multiple Loudspeakers Using VBAP: A Case Study with DIVA Project" in International Conference on Auditory Displays -98. E-mail Ville.Pulkki@hut.fi if you want to have that paper.*/ { CART_VEC v1; CART_VEC v2; CART_VEC v3, neg_v3; MYFLT dist_ij,dist_kl,dist_iv3,dist_jv3,dist_inv3,dist_jnv3; MYFLT dist_kv3,dist_lv3,dist_knv3,dist_lnv3; cross_prod(lss[i].coords,lss[j].coords,&v1); cross_prod(lss[k].coords,lss[l].coords,&v2); cross_prod(v1,v2,&v3); neg_v3.x= FL(0.0) - v3.x; neg_v3.y= FL(0.0) - v3.y; neg_v3.z= FL(0.0) - v3.z; dist_ij = (vec_angle(lss[i].coords,lss[j].coords)); dist_kl = (vec_angle(lss[k].coords,lss[l].coords)); dist_iv3 = (vec_angle(lss[i].coords,v3)); dist_jv3 = (vec_angle(v3,lss[j].coords)); dist_inv3 = (vec_angle(lss[i].coords,neg_v3)); dist_jnv3 = (vec_angle(neg_v3,lss[j].coords)); dist_kv3 = (vec_angle(lss[k].coords,v3)); dist_lv3 = (vec_angle(v3,lss[l].coords)); dist_knv3 = (vec_angle(lss[k].coords,neg_v3)); dist_lnv3 = (vec_angle(neg_v3,lss[l].coords)); /* if one of loudspeakers is close to crossing point, don't do anything*/ if (FABS(dist_iv3) <= FL(0.01) || FABS(dist_jv3) <= FL(0.01) || FABS(dist_kv3) <= FL(0.01) || FABS(dist_lv3) <= FL(0.01) || FABS(dist_inv3) <= FL(0.01) || FABS(dist_jnv3) <= FL(0.01) || FABS(dist_knv3) <= FL(0.01) || FABS(dist_lnv3) <= FL(0.01) ) return(0); if (((FABS(dist_ij - (dist_iv3 + dist_jv3)) <= FL(0.01) ) && (FABS(dist_kl - (dist_kv3 + dist_lv3)) <= FL(0.01))) || ((FABS(dist_ij - (dist_inv3 + dist_jnv3)) <= FL(0.01)) && (FABS(dist_kl - (dist_knv3 + dist_lnv3)) <= FL(0.01) ))) { return (1); } else { return (0); } } static inline int vbap_ls_init_sr (CSOUND *csound, int dim, int count, MYFLT **f, int layout) /* Inits the loudspeaker data. Calls choose_ls_tuplets or _triplets according to current dimension. The inversion matrices are stored in transposed form to ease calculation at run time.*/ { struct ls_triplet_chain *ls_triplets = NULL; ls *lss = malloc(sizeof(ls)*count); ANG_VEC a_vector; CART_VEC c_vector; int i=0,j; //dim = (int) *p->dim; csound->Message(csound, "dim : %d\n",dim); if (UNLIKELY(!((dim==2) || (dim == 3)))) { csound->ErrorMsg(csound, Str("Error in loudspeaker dimension. %d not permitted"), dim); return NOTOK; } //count = (int) *p->ls_amount; for (j=1;j<=count;j++) { if (dim == 3) { a_vector.azi= (MYFLT) *f[2*j-2]; a_vector.ele= (MYFLT) *f[2*j-1]; } else if (dim == 2) { a_vector.azi= (MYFLT) *f[j-1]; a_vector.ele=FL(0.0); } angle_to_cart_II(&a_vector,&c_vector); lss[i].coords.x = c_vector.x; lss[i].coords.y = c_vector.y; lss[i].coords.z = c_vector.z; lss[i].angles.azi = a_vector.azi; lss[i].angles.ele = a_vector.ele; lss[i].angles.length = FL(1.0); /* printf("**** lss[%d]: (%g %g %g) %g %g\n", i, lss[i].coords.x, */ /* lss[i].coords.y, lss[i].coords.z, a_vector.azi, a_vector.ele); */ i++; } //ls_amount = (int)*p->ls_amount; if (UNLIKELY(count < dim)) { free(lss); csound->ErrorMsg(csound, Str("Too few loudspeakers")); return NOTOK; } if (dim == 3) { choose_ls_triplets(csound, lss, &ls_triplets, count); calculate_3x3_matrixes(csound, ls_triplets, lss, count, layout); } else if (dim ==2) { choose_ls_tuplets(csound, lss, &ls_triplets, count, layout); } free(lss); return OK; } int vbap_ls_init (CSOUND *csound, VBAP_LS_INIT *p) { int dim = (int) *p->dim; MYFLT layout = (*p->dim-dim)*100; return vbap_ls_init_sr(csound, dim, (int) *p->ls_amount, p->f, round(layout)); } int vbap_ls_inita (CSOUND *csound, VBAP_LS_INITA *p) { int dim = (int) *p->dim; MYFLT layout = (*p->dim-dim)*100; int i, n = (int)*p->ls_amount; /* if (n>CHANNELS) */ /* return csound->InitError(csound, Str("Too many speakers (%n)\n"), n); */ if (UNLIKELY(n>p->a->sizes[0])) return csound->InitError(csound, Str("Too little data speakers (%d)\n"), n>p->a->sizes[0]); MYFLT **f = csound->Malloc(csound, 2*sizeof(MYFLT*)*n); // Transfer values to pointers for (i=0; i<2*n; i++) f[i] = &(p->a->data[i]); n = vbap_ls_init_sr(csound, dim, n, f, round(layout)); csound->Free(csound, f); return n; } static void calculate_3x3_matrixes(CSOUND *csound, struct ls_triplet_chain *ls_triplets, ls lss[], int ls_amount, int ind) /* Calculates the inverse matrices for 3D */ { MYFLT invdet; CART_VEC *lp1, *lp2, *lp3; MYFLT *ls_table, *invmx; MYFLT *ptr; struct ls_triplet_chain *tr_ptr = ls_triplets; int triplet_amount = 0, i,j,k; if (UNLIKELY(tr_ptr == NULL)) { csound->ErrorMsg(csound, Str("Not valid 3-D configuration")); return; } /* counting triplet amount */ while (tr_ptr != NULL) { triplet_amount++; tr_ptr = tr_ptr->next; } /* calculations and data storage to a global array */ ls_table = create_ls_table(csound, triplet_amount * 12 + 3, ind); ls_table[0] = FL(3.0); /* dimension */ ls_table[1] = (MYFLT) ls_amount; ls_table[2] = (MYFLT) triplet_amount; tr_ptr = ls_triplets; ptr = (MYFLT *) &(ls_table[3]); while (tr_ptr != NULL) { lp1 = &(lss[tr_ptr->ls_nos[0]].coords); lp2 = &(lss[tr_ptr->ls_nos[1]].coords); lp3 = &(lss[tr_ptr->ls_nos[2]].coords); /* matrix inversion */ invmx = tr_ptr->inv_mx; invdet = FL(1.0) / ( lp1->x * ((lp2->y * lp3->z) - (lp2->z * lp3->y)) - lp1->y * ((lp2->x * lp3->z) - (lp2->z * lp3->x)) + lp1->z * ((lp2->x * lp3->y) - (lp2->y * lp3->x))); invmx[0] = ((lp2->y * lp3->z) - (lp2->z * lp3->y)) * invdet; invmx[3] = ((lp1->y * lp3->z) - (lp1->z * lp3->y)) * -invdet; invmx[6] = ((lp1->y * lp2->z) - (lp1->z * lp2->y)) * invdet; invmx[1] = ((lp2->x * lp3->z) - (lp2->z * lp3->x)) * -invdet; invmx[4] = ((lp1->x * lp3->z) - (lp1->z * lp3->x)) * invdet; invmx[7] = ((lp1->x * lp2->z) - (lp1->z * lp2->x)) * -invdet; invmx[2] = ((lp2->x * lp3->y) - (lp2->y * lp3->x)) * invdet; invmx[5] = ((lp1->x * lp3->y) - (lp1->y * lp3->x)) * -invdet; invmx[8] = ((lp1->x * lp2->y) - (lp1->y * lp2->x)) * invdet; for (i=0;i<3;i++) { *(ptr++) = (MYFLT) tr_ptr->ls_nos[i]+1; } for (i=0;i<9;i++) { *(ptr++) = (MYFLT) invmx[i]; } tr_ptr = tr_ptr->next; } k = 3; csound->Warning(csound, Str("\nConfigured loudspeakers\n")); for (i = 0; i < triplet_amount; i++) { csound->Warning(csound, Str("Triplet %d Loudspeakers: "), i); for (j = 0; j < 3; j++) { csound->Warning(csound, "%d ", (int) ls_table[k++]); } csound->Warning(csound, "\n"); /* printf("\nMatrix "); */ /* for (j = 0; j < 9; j++) { */ /* printf("%f ", ls_table[k]); */ /* k++; */ /* } */ /* printf("\n\n"); */ } } static void choose_ls_tuplets(CSOUND *csound, ls lss[], ls_triplet_chain **ls_triplets, int ls_amount, int ind) /* selects the loudspeaker pairs, calculates the inversion matrices and stores the data to a global array */ { int i, j, k; int *sorted_lss = (int*)malloc(sizeof(int)*ls_amount); int *exist = (int*)calloc(1,sizeof(int)*ls_amount); int amount = 0; MYFLT *inv_mat = (MYFLT*)malloc(MATSIZE*sizeof(MYFLT)*ls_amount), *ls_table, *ptr; //int ftable_size; /* sort loudspeakers according their aximuth angle */ sort_2D_lss(lss,sorted_lss,ls_amount); /* adjacent loudspeakers are the loudspeaker pairs to be used.*/ for (i=0;i<(ls_amount-1);i++) { csound->Message(csound, "***%d %d %f %f\n",sorted_lss[i],sorted_lss[i+1], lss[sorted_lss[i]].angles.azi, lss[sorted_lss[i+1]].angles.azi); if (LIKELY((lss[sorted_lss[i+1]].angles.azi - lss[sorted_lss[i]].angles.azi) <= (PI - 0.0175))) { if (LIKELY(calc_2D_inv_tmatrix( lss[sorted_lss[i]].angles.azi, lss[sorted_lss[i+1]].angles.azi, &inv_mat[MATSIZE*i]) != 0)) { exist[i]=1; amount++; } } else csound->Warning(csound, Str("Pair of speakers at %f and %f ignored\n"), lss[sorted_lss[i]].angles.azi*FL(180.0)/PI_F, lss[sorted_lss[i+1]].angles.azi*FL(180.0)/PI_F); } if (LIKELY(((TWOPI_F - lss[sorted_lss[ls_amount-1]].angles.azi) +lss[sorted_lss[0]].angles.azi) < (PI - 0.0175))) { //printf("**less than PI type 2- 0.175\n"); if (LIKELY(calc_2D_inv_tmatrix(lss[sorted_lss[ls_amount-1]].angles.azi, lss[sorted_lss[0]].angles.azi, &inv_mat[MATSIZE*(ls_amount-1)]) != 0)) { exist[ls_amount-1]=1; amount++; } } else csound->Warning(csound, Str("Pair of speakers at %f and %f ignored\n"), lss[sorted_lss[ls_amount-1]].angles.azi*FL(180.0)/PI_F, lss[sorted_lss[0]].angles.azi*FL(180.0)/PI_F); if (UNLIKELY(amount==0)) { csound->InitError(csound, Str("insufficient valid speakers")); free(sorted_lss); free(exist); free(inv_mat); return; } #if 0 if ( amount*6 + 6 <= 16) ftable_size = 16; else if ( amount*6 + 6 <= 32) ftable_size = 32; else if ( amount*6 + 6 <= 64) ftable_size = 64; else if ( amount*6 + 6 <= 128) ftable_size = 128; else if ( amount*6 + 6 <= 256) ftable_size = 256; else if ( amount*6 + 6 <= 1024) ftable_size = 1024; csound->Message(csound, "Loudspeaker matrices calculated with configuration : "); for (i=0; i< ls_amount; i++) csound->Message(csound, "%.1f ", lss[i].angles.azi / ATORAD); csound->Message(csound, "\n"); #endif ls_table = create_ls_table(csound, amount * 6 + 3 + 100, ind); ls_table[0] = FL(2.0); /* dimension */ ls_table[1] = (MYFLT) ls_amount; ls_table[2] = (MYFLT) amount; ptr = &(ls_table[3]); for (i=0;iMessage(csound, Str("\nConfigured loudspeakers\n")); for (i=0; i < amount; i++) { csound->Message(csound, Str("Pair %d Loudspeakers: "), i); for (j=0; j < 2; j++) { csound->Message(csound, "%d ", (int) ls_table[k++]); } csound->Message(csound, "\nMatrix "); for (j=0; j < MATSIZE; j++) { csound->Message(csound, "%f ", ls_table[k]); k++; } csound->Message(csound, "\n\n"); } free(sorted_lss); free(exist); free(inv_mat); } static void sort_2D_lss(ls lss[], int sorted_lss[], int ls_amount) { int i,j,index=-1; MYFLT tmp, tmp_azi; /* Transforming angles between -180 and 180 */ for (i=0; ix = a * vscartdir.x + b * spread_base.x; spreaddir->y = a * vscartdir.y + b * spread_base.y; spreaddir->z = a * vscartdir.z + b * spread_base.z; power=SQRT(spreaddir->x*spreaddir->x + spreaddir->y*spreaddir->y + spreaddir->z*spreaddir->z); spreaddir->x /= power; spreaddir->y /= power; spreaddir->z /= power; } void new_spread_base(CART_VEC spreaddir, CART_VEC vscartdir, MYFLT spread, CART_VEC *spread_base) { MYFLT d; MYFLT power; d = COS(spread/FL(180.0)*PI_F); spread_base->x = spreaddir.x - d * vscartdir.x; spread_base->y = spreaddir.y - d * vscartdir.y; spread_base->z = spreaddir.z - d * vscartdir.z; power=SQRT(spread_base->x*spread_base->x + spread_base->y*spread_base->y + spread_base->z*spread_base->z); spread_base->x /= power; spread_base->y /= power; spread_base->z /= power; } #define S(x) sizeof(x) /* static */ static OENTRY vbap_localops[] = { { "vbap.a", S(VBAP), TR, 5, "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm" "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", "akOOo", (SUBR) vbap_init, (SUBR) NULL, (SUBR) vbap }, { "vbap.A", S(VBAPA), TR, 5, "a[]", "akOOo", (SUBR) vbap_init_a, (SUBR) NULL, (SUBR) vbap_a }, { "vbap4", S(VBAP), TR|_QQ, 5, "aaaammmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm" "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", "akOOo", (SUBR) vbap_init, (SUBR) NULL, (SUBR) vbap }, { "vbap8", S(VBAP), TR|_QQ, 5, "aaaaaaaammmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm" "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", "akOOo", (SUBR) vbap_init, (SUBR) NULL, (SUBR) vbap }, { "vbap16", S(VBAP), TR|_QQ, 5, "aaaaaaaaaaaaaaaammmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm" "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", "akOOo", (SUBR) vbap_init, (SUBR) NULL, (SUBR) vbap }, { "vbapg.a", S(VBAP1), TR, 3, "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", "kOOo", (SUBR) vbap1_init, (SUBR) vbap1 }, { "vbapg.A", S(VBAPA1), TR, 3, "k[]", "kOOo", (SUBR) vbap1_init_a, (SUBR) vbap1a }, { "vbapz", S(VBAP_ZAK), ZW|TR, 5, "", "iiakOOo", (SUBR) vbap_zak_init, (SUBR) NULL, (SUBR) vbap_zak }, { "vbaplsinit",S(VBAP_LS_INIT),TR,1, "", "ii" "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", (SUBR) vbap_ls_init, (SUBR) NULL, (SUBR) NULL, (SUBR) NULL }, { "vbaplsinit",S(VBAP_LS_INIT),TR,1, "", "iii[]", (SUBR) vbap_ls_inita, (SUBR) NULL, (SUBR) NULL, (SUBR) NULL }, { "vbapmove.a", S(VBAP_MOVING), TR, 5, "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm" "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", "aiiim", (SUBR) vbap_moving_init, (SUBR) NULL, (SUBR) vbap_moving }, { "vbapgmove.a", S(VBAP1_MOVING), TR, 5, "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", "iiim", (SUBR) vbap1_moving_init, (SUBR) NULL, (SUBR) vbap1_moving }, { "vbapmove.A", S(VBAPA_MOVING), TR, 5, "a[]", "aiiim", (SUBR) vbap_moving_init_a, (SUBR) NULL, (SUBR) vbap_moving_a }, { "vbapgmove.A", S(VBAPA1_MOVING), TR, 5, "k[]", "iiim", (SUBR) vbap1_moving_init_a, (SUBR) NULL, (SUBR) vbap1_moving_a }, { "vbapzmove", S(VBAP_ZAK_MOVING), ZW|TR, 5, "", "iiaiiim", (SUBR) vbap_zak_moving_init, (SUBR) NULL, (SUBR) vbap_zak_moving }, { "vbap4move", S(VBAP_MOVING), TR|_QQ, 5, "aaaa", "aiiim", (SUBR) vbap_moving_init, (SUBR) NULL, (SUBR) vbap_moving }, { "vbap8move", S(VBAP_MOVING), TR|_QQ, 5, "aaaaaaaa", "aiiim", (SUBR) vbap_moving_init, (SUBR) NULL, (SUBR) vbap_moving } }; LINKAGE_BUILTIN(vbap_localops) csound-6.10.0/Opcodes/vbap.h000066400000000000000000000217161321653344700156050ustar00rootroot00000000000000/* vbap.h: Copyright (C) 2000 Ville Pulkki This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define LOWEST_ACCEPTABLE_WT FL(0.0) #define CHANNELS 128 #define MIN_VOL_P_SIDE_LGTH FL(0.01) typedef struct { MYFLT x; MYFLT y; MYFLT z; } CART_VEC; typedef struct { MYFLT azi; MYFLT ele; MYFLT length; } ANG_VEC; /* A struct for gain factors */ typedef struct { MYFLT wt1, wt2, wt3; MYFLT *out_ptr1, *out_ptr2, *out_ptr3; } OUT_WTS; /* A struct for a loudspeaker triplet or pair (set) */ typedef struct { int ls_nos[3]; MYFLT ls_mx[9]; MYFLT set_gains[3]; MYFLT smallest_wt; int neg_g_am; } LS_SET; /* VBAP structure of n loudspeaker panning */ typedef struct { int number; MYFLT beg_gains[CHANNELS]; MYFLT curr_gains[CHANNELS]; MYFLT end_gains[CHANNELS]; MYFLT updated_gains[CHANNELS]; int dim; AUXCH aux; LS_SET *ls_sets; int ls_am; int ls_set_am; CART_VEC cart_dir; CART_VEC spread_base; ANG_VEC ang_dir; } VBAP_DATA; typedef struct { OPDS h; /* required header */ MYFLT *out_array[CHANNELS]; MYFLT *audio, *azi, *ele, *spread, *layout; VBAP_DATA q; } VBAP; typedef struct { OPDS h; /* required header */ ARRAYDAT *tabout; MYFLT *audio, *azi, *ele, *spread, *layout; VBAP_DATA q; } VBAPA; typedef struct { int number; MYFLT gains[CHANNELS]; int dim; AUXCH aux; LS_SET *ls_sets; int ls_am; int ls_set_am; CART_VEC cart_dir; CART_VEC spread_base; ANG_VEC ang_dir; } VBAP1_DATA; typedef struct { OPDS h; /* required header */ MYFLT *out_array[CHANNELS]; MYFLT *azi, *ele, *spread, *layout; VBAP1_DATA q; } VBAP1; typedef struct { OPDS h; /* required header */ ARRAYDAT *tabout; MYFLT *azi, *ele, *spread, *layout; VBAP1_DATA q; } VBAPA1; /* VBAP structure of loudspeaker moving panning */ typedef struct { MYFLT gains[CHANNELS]; int number; int upd_interval; int dim; AUXCH aux; LS_SET *ls_sets; int ls_am; int ls_set_am; CART_VEC cart_dir; CART_VEC spread_base; ANG_VEC ang_dir, prev_ang_dir, next_ang_dir; int point_change_interval, point_change_counter, curr_fld, next_fld; MYFLT ele_vel; MYFLT end_gains[CHANNELS]; } VBAP1_MOVE_DATA; typedef struct { OPDS h; /* required header */ MYFLT *out_array[CHANNELS]; MYFLT *dur, *spread, *field_am, *fld[VARGMAX]; /* field_am positive: point to point negative: angle velocities */ VBAP1_MOVE_DATA q; } VBAP1_MOVING; typedef struct { OPDS h; /* required header */ ARRAYDAT *tabout; MYFLT *dur, *spread, *field_am, *fld[VARGMAX]; /* field_am positive: point to point negative: angle velocities */ VBAP1_MOVE_DATA q; } VBAPA1_MOVING; /* VBAP structure of loudspeaker moving panning */ typedef struct { MYFLT beg_gains[CHANNELS]; MYFLT curr_gains[CHANNELS]; MYFLT updated_gains[CHANNELS]; int number; int upd_interval; int dim; AUXCH aux; LS_SET *ls_sets; int ls_am; int ls_set_am; CART_VEC cart_dir; CART_VEC spread_base; ANG_VEC ang_dir, prev_ang_dir, next_ang_dir; int point_change_interval, point_change_counter, curr_fld, next_fld; MYFLT ele_vel; MYFLT end_gains[CHANNELS]; } VBAP_MOVE_DATA; typedef struct { OPDS h; /* required header */ MYFLT *out_array[CHANNELS]; MYFLT *audio, *dur, *spread, *field_am, *fld[VARGMAX]; /* field_am positive: point to point negative: angle velocities */ VBAP_MOVE_DATA q; } VBAP_MOVING; typedef struct { OPDS h; /* required header */ ARRAYDAT *tabout; MYFLT *audio, *dur, *spread, *field_am, *fld[VARGMAX]; /* field_am positive: point to point negative: angle velocities */ VBAP_MOVE_DATA q; } VBAPA_MOVING; typedef struct { OPDS h; /* required header */ MYFLT *dim, *ls_amount; MYFLT *f[2*CHANNELS]; } VBAP_LS_INIT; typedef struct { OPDS h; /* required header */ MYFLT *dim, *ls_amount; ARRAYDAT *a; } VBAP_LS_INITA; /* A struct for a loudspeaker instance */ typedef struct { CART_VEC coords; ANG_VEC angles; int channel_nbr; } ls; /* A struct for all loudspeakers */ typedef struct ls_triplet_chain { int ls_nos[3]; MYFLT inv_mx[9]; struct ls_triplet_chain *next; } ls_triplet_chain; /* functions */ void angle_to_cart_II( ANG_VEC *from, CART_VEC *to); int lines_intersect(int i,int j,int k,int l, ls lss[]); MYFLT vec_angle(CART_VEC v1, CART_VEC v2); void vec_mean(CART_VEC v1, CART_VEC v2, CART_VEC *v3); MYFLT angle_in_base(CART_VEC vb1,CART_VEC vb2,CART_VEC vec); void cross_prod(CART_VEC v1,CART_VEC v2, CART_VEC *res) ; /* void sort_angles(MYFLT angles[], int sorted_angles[], */ /* int ls_amount); */ /* void remove_connections_in_planey(int i,int j,int k,int l, */ /* ls lss[CHANNELS], */ /* int connections[CHANNELS][CHANNELS]); */ int calc_2D_inv_tmatrix(MYFLT azi1,MYFLT azi2, MYFLT inv_mat[4]); extern void cart_to_angle(CART_VEC cvec, ANG_VEC *avec); extern void angle_to_cart(ANG_VEC avec, CART_VEC *cvec); extern void normalize_wts(OUT_WTS *wts); extern int vbap_control(CSOUND*, VBAP_DATA *p, MYFLT*, MYFLT*, MYFLT*); void calc_vbap_gns(int ls_set_am, int dim, LS_SET *sets, MYFLT *gains, int ls_amount, CART_VEC cart_dir); void scale_angles(ANG_VEC *avec); MYFLT vol_p_side_lgth(int i, int j, int k, ls lss[]); void new_spread_dir(CART_VEC *spreaddir, CART_VEC vscartdir, CART_VEC spread_base, MYFLT azi, MYFLT spread); void new_spread_base(CART_VEC spreaddir, CART_VEC vscartdir, MYFLT spread, CART_VEC *spread_base); /* VBAP structure for ZAK loudspeaker panning */ typedef struct { OPDS h; /* required header */ MYFLT *numb, *ndx, *audio, *azi, *ele, *spread, *layout; int n; MYFLT *out_array; AUXCH auxch; AUXCH aux; MYFLT *curr_gains; MYFLT *beg_gains; MYFLT *end_gains; MYFLT *updated_gains; int dim; LS_SET *ls_sets; int ls_am; int ls_set_am; CART_VEC cart_dir; CART_VEC spread_base; ANG_VEC ang_dir; } VBAP_ZAK; /* VBAP structure of ZAK loudspeaker moving panning */ typedef struct { OPDS h; /* required header */ MYFLT *numb, *ndx, *audio, *dur, *spread, *field_am, *fld[VARGMAX]; /* field_am positive: point to point negative: angle velocities */ int n; MYFLT *out_array; AUXCH auxch; AUXCH aux; MYFLT *curr_gains; MYFLT *beg_gains; MYFLT *end_gains; MYFLT *updated_gains; int dim; LS_SET *ls_sets; int ls_am; int ls_set_am; CART_VEC cart_dir; CART_VEC spread_base; ANG_VEC ang_dir, prev_ang_dir, next_ang_dir; int point_change_interval, point_change_counter, curr_fld, next_fld; MYFLT ele_vel; } VBAP_ZAK_MOVING; int vbap_init(CSOUND *, VBAP *); int vbap_init_a(CSOUND *, VBAPA *); int vbap(CSOUND *, VBAP *); int vbap_a(CSOUND *, VBAPA *); int vbap_zak_init(CSOUND *, VBAP_ZAK *); int vbap_zak(CSOUND *, VBAP_ZAK *); int vbap_ls_init(CSOUND *, VBAP_LS_INIT *); int vbap_moving_init(CSOUND *, VBAP_MOVING *); int vbap_moving(CSOUND *, VBAP_MOVING *); int vbap_moving_init_a(CSOUND *, VBAPA_MOVING *); int vbap_moving_a(CSOUND *, VBAPA_MOVING *); int vbap_zak_moving_init(CSOUND *, VBAP_ZAK_MOVING *); int vbap_zak_moving(CSOUND *, VBAP_ZAK_MOVING *); int vbap1_init(CSOUND *, VBAP1 *); int vbap1(CSOUND *, VBAP1 *); int vbap1_init_a(CSOUND *, VBAPA1 *); int vbap1a(CSOUND *, VBAPA1 *); int vbap1_moving_init(CSOUND *, VBAP1_MOVING *); int vbap1_moving(CSOUND *, VBAP1_MOVING *); int vbap1_moving_init_a(CSOUND *, VBAPA1_MOVING *); int vbap1_moving_a(CSOUND *, VBAPA1_MOVING *); csound-6.10.0/Opcodes/vbap1.c000066400000000000000000000573531321653344700156670ustar00rootroot00000000000000/* vbap1.c: Copyright (C) 2000 Ville Pulkki 2012 John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* vbap1.c functions specific gains for loudspeaker VBAP Ville Pulkki heavily modified by John ffitch 2012 */ #include "csoundCore.h" #include "vbap.h" #include #include #include static int vbap1_moving_control(CSOUND *, VBAP1_MOVE_DATA *, INSDS *, MYFLT, MYFLT, MYFLT, MYFLT**); static int vbap1_control(CSOUND *, VBAP1_DATA *, MYFLT*, MYFLT*, MYFLT*); int vbap1(CSOUND *csound, VBAP1 *p) /* during note performance: */ { int j; int cnt = p->q.number; vbap1_control(csound,&p->q, p->azi, p->ele, p->spread); /* write gains */ for (j=0; jout_array[j] = p->q.gains[j]; } return OK; } static int vbap1_control(CSOUND *csound, VBAP1_DATA *p, MYFLT* azi, MYFLT* ele, MYFLT* spread) { CART_VEC spreaddir[16]; CART_VEC spreadbase[16]; ANG_VEC atmp; int32 i,j, spreaddirnum; int cnt = p->number; MYFLT *tmp_gains=malloc(sizeof(MYFLT)*cnt),sum=FL(0.0); if (UNLIKELY(p->dim == 2 && fabs(*ele) > 0.0)) { csound->Warning(csound, Str("Warning: truncating elevation to 2-D plane\n")); *ele = FL(0.0); } if (*spread FL(100.0)) *spread = FL(100.0); /* Current panning angles */ p->ang_dir.azi = *azi; p->ang_dir.ele = *ele; p->ang_dir.length = FL(1.0); angle_to_cart(p->ang_dir, &(p->cart_dir)); calc_vbap_gns(p->ls_set_am, p->dim, p->ls_sets, p->gains, cnt, p->cart_dir); /* Calculated gain factors of a spreaded virtual source*/ if (*spread > FL(0.0)) { if (p->dim == 3) { spreaddirnum = 16; /* four orthogonal dirs*/ new_spread_dir(&spreaddir[0], p->cart_dir, p->spread_base, *azi, *spread); new_spread_base(spreaddir[0], p->cart_dir, *spread, &p->spread_base); cross_prod(p->spread_base, p->cart_dir, &spreadbase[1]); cross_prod(spreadbase[1], p->cart_dir, &spreadbase[2]); cross_prod(spreadbase[2], p->cart_dir, &spreadbase[3]); /* four between them*/ vec_mean(p->spread_base, spreadbase[1], &spreadbase[4]); vec_mean(spreadbase[1], spreadbase[2], &spreadbase[5]); vec_mean(spreadbase[2], spreadbase[3], &spreadbase[6]); vec_mean(spreadbase[3], p->spread_base, &spreadbase[7]); /* four at half spreadangle*/ vec_mean(p->cart_dir, p->spread_base, &spreadbase[8]); vec_mean(p->cart_dir, spreadbase[1], &spreadbase[9]); vec_mean(p->cart_dir, spreadbase[2], &spreadbase[10]); vec_mean(p->cart_dir, spreadbase[3], &spreadbase[11]); /* four at quarter spreadangle*/ vec_mean(p->cart_dir, spreadbase[8], &spreadbase[12]); vec_mean(p->cart_dir, spreadbase[9], &spreadbase[13]); vec_mean(p->cart_dir, spreadbase[10], &spreadbase[14]); vec_mean(p->cart_dir, spreadbase[11], &spreadbase[15]); for (i=1;icart_dir, spreadbase[i],*azi,*spread); calc_vbap_gns(p->ls_set_am, p->dim, p->ls_sets, tmp_gains, cnt, spreaddir[i]); for (j=0;jgains[j] += tmp_gains[j]; } } } else if (p->dim == 2) { spreaddirnum = 6; atmp.ele = FL(0.0); atmp.azi = *azi - *spread; angle_to_cart(atmp, &spreaddir[0]); atmp.azi = *azi - *spread/2; angle_to_cart(atmp, &spreaddir[1]); atmp.azi = *azi - *spread/4; angle_to_cart(atmp, &spreaddir[2]); atmp.azi = *azi + *spread/4; angle_to_cart(atmp, &spreaddir[3]); atmp.azi = *azi + *spread/2; angle_to_cart(atmp, &spreaddir[4]); atmp.azi = *azi + *spread; angle_to_cart(atmp, &spreaddir[5]); for (i=0;ils_set_am, p->dim, p->ls_sets, tmp_gains, cnt, spreaddir[i]); for (j=0;jgains[j] += tmp_gains[j]; } } } } if (*spread > FL(70.0)) for (i=0;igains[i] +=(*spread - FL(70.0))/FL(30.0) * (*spread - FL(70.0))/FL(30.0)*FL(20.0); } /*normalization*/ for (i=0;igains[i]*p->gains[i]); } sum=SQRT(sum); for (i=0;igains[i] /= sum; } free(tmp_gains); return OK; } int vbap1_init(CSOUND *csound, VBAP1 *p) { /* Initializations before run time*/ int i, j; MYFLT *ls_table, *ptr; LS_SET *ls_set_ptr; char name[24]; snprintf(name, 24, "vbap_ls_table_%d", (int)*p->layout); ls_table = (MYFLT*) (csound->QueryGlobalVariableNoCheck(csound, name)); if (ls_table==NULL) return csound->InitError(csound, Str("could not find layout table no.%d"), (int)*p->layout ); p->q.number = p->OUTOCOUNT; p->q.dim = (int)ls_table[0]; /* reading in loudspeaker info */ p->q.ls_am = (int)ls_table[1]; p->q.ls_set_am = (int)ls_table[2]; ptr = &(ls_table[3]); if (!p->q.ls_set_am) return csound->InitError(csound, Str("vbap system NOT configured. \nMissing" " vbaplsinit opcode in orchestra?")); csound->AuxAlloc(csound, p->q.ls_set_am * sizeof (LS_SET), &p->q.aux); if (UNLIKELY(p->q.aux.auxp == NULL)) { return csound->InitError(csound, Str("could not allocate memory")); } p->q.ls_sets = (LS_SET*) p->q.aux.auxp; ls_set_ptr = p->q.ls_sets; for (i=0; i < p->q.ls_set_am; i++) { ls_set_ptr[i].ls_nos[2] = 0; /* initial setting */ for (j=0 ; j < p->q.dim ; j++) { ls_set_ptr[i].ls_nos[j] = (int)*(ptr++); } memset(ls_set_ptr[i].ls_mx, '\0', 9*sizeof(MYFLT)); // initial setting /* for (j=0 ; j < 9; j++) */ /* ls_set_ptr[i].ls_mx[j] = FL(0.0); /\*initial setting*\/ */ for (j=0 ; j < (p->q.dim) * (p->q.dim); j++) { ls_set_ptr[i].ls_mx[j] = (MYFLT)*(ptr++); } } /* other initialization */ if (UNLIKELY(p->q.dim == 2 && fabs(*p->ele) > 0.0)) { csound->Warning(csound, Str("Warning: truncating elevation to 2-D plane\n")); *p->ele = FL(0.0); } p->q.ang_dir.azi = (MYFLT)*p->azi; p->q.ang_dir.ele = (MYFLT)*p->ele; p->q.ang_dir.length = FL(1.0); angle_to_cart(p->q.ang_dir, &(p->q.cart_dir)); p->q.spread_base.x = p->q.cart_dir.y; p->q.spread_base.y = p->q.cart_dir.z; p->q.spread_base.z = -p->q.cart_dir.x; vbap1_control(csound,&p->q, p->azi, p->ele, p->spread); return OK; } int vbap1a(CSOUND *csound, VBAPA1 *p) /* during note performance: */ { int j; int cnt = p->q.number; vbap1_control(csound,&p->q, p->azi, p->ele, p->spread); /* write gains */ for (j=0; jtabout->data[j] = p->q.gains[j]; } return OK; } int vbap1_init_a(CSOUND *csound, VBAPA1 *p) { /* Initializations before run time*/ int i, j; MYFLT *ls_table, *ptr; LS_SET *ls_set_ptr; char name[24]; snprintf(name, 24, "vbap_ls_table_%d", (int)*p->layout); ls_table = (MYFLT*) (csound->QueryGlobalVariableNoCheck(csound, name)); if (ls_table==NULL) return csound->InitError(csound, Str("could not find layout table no.%d"), (int)*p->layout ); p->q.number = p->tabout->sizes[0]; p->q.dim = (int)ls_table[0]; /* reading in loudspeaker info */ p->q.ls_am = (int)ls_table[1]; p->q.ls_set_am = (int)ls_table[2]; ptr = &(ls_table[3]); if (!p->q.ls_set_am) return csound->InitError(csound, Str("vbap system NOT configured. \nMissing" " vbaplsinit opcode in orchestra?")); csound->AuxAlloc(csound, p->q.ls_set_am * sizeof (LS_SET), &p->q.aux); if (UNLIKELY(p->q.aux.auxp == NULL)) { return csound->InitError(csound, Str("could not allocate memory")); } p->q.ls_sets = (LS_SET*) p->q.aux.auxp; ls_set_ptr = p->q.ls_sets; for (i=0; i < p->q.ls_set_am; i++) { ls_set_ptr[i].ls_nos[2] = 0; /* initial setting */ for (j=0 ; j < p->q.dim ; j++) { ls_set_ptr[i].ls_nos[j] = (int)*(ptr++); } memset(ls_set_ptr[i].ls_mx, '\0', 9*sizeof(MYFLT)); /*initial setting*/ for (j=0 ; j < (p->q.dim) * (p->q.dim); j++) { ls_set_ptr[i].ls_mx[j] = (MYFLT)*(ptr++); } } /* other initialization */ if (UNLIKELY(p->q.dim == 2 && fabs(*p->ele) > 0.0)) { csound->Warning(csound, Str("Warning: truncating elevation to 2-D plane\n")); *p->ele = FL(0.0); } p->q.ang_dir.azi = (MYFLT)*p->azi; p->q.ang_dir.ele = (MYFLT)*p->ele; p->q.ang_dir.length = FL(1.0); angle_to_cart(p->q.ang_dir, &(p->q.cart_dir)); p->q.spread_base.x = p->q.cart_dir.y; p->q.spread_base.y = p->q.cart_dir.z; p->q.spread_base.z = -p->q.cart_dir.x; vbap1_control(csound,&p->q, p->azi, p->ele, p->spread); return OK; } int vbap1_moving(CSOUND *csound, VBAP1_MOVING *p) { /* during note performance: */ int j; int cnt = p->q.number; vbap1_moving_control(csound,&p->q, p->h.insdshead, CS_ONEDKR, *p->spread, *p->field_am, p->fld); /* write audio to resulting audio streams weighted with gain factors*/ for (j=0; jout_array[j] = p->q.gains[j]; } return OK; } int vbap1_moving_a(CSOUND *csound, VBAPA1_MOVING *p) { /* during note performance: */ // int j; int cnt = p->q.number; vbap1_moving_control(csound,&p->q, p->h.insdshead, CS_ONEDKR, *p->spread, *p->field_am, p->fld); /* write audio to resulting audio streams weighted with gain factors*/ memcpy(p->tabout->data, p->q.gains, cnt*sizeof(MYFLT)); /* for (j=0; jtabout->data[j] = p->q.gains[j]; */ /* } */ return OK; } static int vbap1_moving_control(CSOUND *csound, VBAP1_MOVE_DATA *p, INSDS *insdshead, MYFLT ONEDKR, MYFLT spread, MYFLT field_am, MYFLT **fld) { CART_VEC spreaddir[16]; CART_VEC spreadbase[16]; ANG_VEC atmp; int32 i,j, spreaddirnum; CART_VEC tmp1, tmp2, tmp3; MYFLT coeff, angle; int cnt = p->number; MYFLT *tmp_gains=malloc(sizeof(MYFLT)*cnt),sum=FL(0.0); #ifdef JPFF printf("cnt=%d dim=%d\n", cnt, p->dim); #endif if (UNLIKELY(p->dim == 2 && fabs(p->ang_dir.ele) > 0.0)) { csound->Warning(csound, Str("Warning: truncating elevation to 2-D plane\n")); p->ang_dir.ele = FL(0.0); } if (spread FL(100.0)) spread = FL(100.0); if (p->point_change_counter++ >= p->point_change_interval) { p->point_change_counter = 0; p->curr_fld = p->next_fld; if (++p->next_fld >= (int) fabs(field_am)) { if (field_am >= FL(0.0)) /* point-to-point */ p->next_fld = 0; else p->next_fld = 1; } if (p->dim == 3) { /*jumping over second field */ p->curr_fld = p->next_fld; if (++p->next_fld >= ((int) fabs(field_am))) { if (field_am >= FL(0.0)) /* point-to-point */ p->next_fld = 0; else p->next_fld = 1; } } if (UNLIKELY((fld[abs(p->next_fld)]==NULL))) return csound->PerfError(csound, insdshead, Str("Missing fields in vbapmove\n")); if (field_am >= FL(0.0) && p->dim == 2) /* point-to-point */ if (UNLIKELY(fabs(fabs(*fld[p->next_fld] - *fld[p->curr_fld]) - 180.0) < 1.0)) csound->Warning(csound, Str("Warning: Ambiguous transition 180 degrees.\n")); } if (field_am >= FL(0.0)) { /* point-to-point */ if (p->dim == 3) { /* 3-D*/ p->prev_ang_dir.azi = *fld[p->curr_fld-1]; p->next_ang_dir.azi = *fld[p->next_fld]; p->prev_ang_dir.ele = *fld[p->curr_fld]; p->next_ang_dir.ele = *fld[p->next_fld+1]; coeff = ((MYFLT) p->point_change_counter) / ((MYFLT) p->point_change_interval); angle_to_cart( p->prev_ang_dir,&tmp1); angle_to_cart( p->next_ang_dir,&tmp2); tmp3.x = (FL(1.0)-coeff) * tmp1.x + coeff * tmp2.x; tmp3.y = (FL(1.0)-coeff) * tmp1.y + coeff * tmp2.y; tmp3.z = (FL(1.0)-coeff) * tmp1.z + coeff * tmp2.z; coeff = (MYFLT)sqrt((double)(tmp3.x * tmp3.x + tmp3.y * tmp3.y + tmp3.z * tmp3.z)); tmp3.x /= coeff; tmp3.y /= coeff; tmp3.z /= coeff; cart_to_angle(tmp3,&(p->ang_dir)); } else if (p->dim == 2) { /* 2-D */ p->prev_ang_dir.azi = *fld[p->curr_fld]; p->next_ang_dir.azi = *fld[p->next_fld ]; p->prev_ang_dir.ele = p->next_ang_dir.ele = FL(0.0); scale_angles(&(p->prev_ang_dir)); scale_angles(&(p->next_ang_dir)); angle = (p->prev_ang_dir.azi - p->next_ang_dir.azi); while (angle > FL(180.0)) angle -= FL(360.0); while (angle < -FL(180.0)) angle += FL(360.0); coeff = ((MYFLT) p->point_change_counter) / ((MYFLT) p->point_change_interval); angle *= (coeff); p->ang_dir.azi = p->prev_ang_dir.azi - angle; p->ang_dir.ele = FL(0.0); } else { free(tmp_gains); return csound->PerfError(csound, insdshead, Str("Missing fields in vbapmove\n")); } } else { /* angular velocities */ if (p->dim == 2) { p->ang_dir.azi = p->ang_dir.azi + (*fld[p->next_fld] * ONEDKR); scale_angles(&(p->ang_dir)); } else { /* 3D angular*/ p->ang_dir.azi = p->ang_dir.azi + (*fld[p->next_fld] * ONEDKR); p->ang_dir.ele = p->ang_dir.ele + p->ele_vel * (*fld[p->next_fld+1] * ONEDKR); if (p->ang_dir.ele > FL(90.0)) { p->ang_dir.ele = FL(90.0); p->ele_vel = -p->ele_vel; } if (p->ang_dir.ele < FL(0.0)) { p->ang_dir.ele = FL(0.0); p->ele_vel = -p->ele_vel; } scale_angles(&(p->ang_dir)); } } angle_to_cart(p->ang_dir, &(p->cart_dir)); calc_vbap_gns(p->ls_set_am, p->dim, p->ls_sets, p->gains, cnt, p->cart_dir); if (spread > FL(0.0)) { if (p->dim == 3) { spreaddirnum=16; /* four orthogonal dirs*/ new_spread_dir(&spreaddir[0], p->cart_dir, p->spread_base, p->ang_dir.azi, spread); new_spread_base(spreaddir[0], p->cart_dir, spread, &p->spread_base); cross_prod(p->spread_base, p->cart_dir, &spreadbase[1]); cross_prod(spreadbase[1], p->cart_dir, &spreadbase[2]); cross_prod(spreadbase[2], p->cart_dir, &spreadbase[3]); /* four between them*/ vec_mean(p->spread_base, spreadbase[1], &spreadbase[4]); vec_mean(spreadbase[1], spreadbase[2], &spreadbase[5]); vec_mean(spreadbase[2], spreadbase[3], &spreadbase[6]); vec_mean(spreadbase[3], p->spread_base, &spreadbase[7]); /* four at half spreadangle*/ vec_mean(p->cart_dir, p->spread_base, &spreadbase[8]); vec_mean(p->cart_dir, spreadbase[1], &spreadbase[9]); vec_mean(p->cart_dir, spreadbase[2], &spreadbase[10]); vec_mean(p->cart_dir, spreadbase[3], &spreadbase[11]); /* four at quarter spreadangle*/ vec_mean(p->cart_dir, spreadbase[8], &spreadbase[12]); vec_mean(p->cart_dir, spreadbase[9], &spreadbase[13]); vec_mean(p->cart_dir, spreadbase[10], &spreadbase[14]); vec_mean(p->cart_dir, spreadbase[11], &spreadbase[15]); for (i=1;icart_dir, spreadbase[i],p->ang_dir.azi,spread); calc_vbap_gns(p->ls_set_am, p->dim, p->ls_sets, tmp_gains, cnt, spreaddir[i]); for (j=0;jgains[j] += tmp_gains[j]; } } } else if (p->dim == 2) { spreaddirnum=6; atmp.ele = FL(0.0); atmp.azi = p->ang_dir.azi - spread; angle_to_cart(atmp, &spreaddir[0]); atmp.azi = p->ang_dir.azi - spread/2; angle_to_cart(atmp, &spreaddir[1]); atmp.azi = p->ang_dir.azi - spread/4; angle_to_cart(atmp, &spreaddir[2]); atmp.azi = p->ang_dir.azi + spread/4; angle_to_cart(atmp, &spreaddir[3]); atmp.azi = p->ang_dir.azi + spread/2; angle_to_cart(atmp, &spreaddir[4]); atmp.azi = p->ang_dir.azi + spread; angle_to_cart(atmp, &spreaddir[5]); for (i=0;ils_set_am, p->dim, p->ls_sets, tmp_gains, cnt, spreaddir[i]); for (j=0;jgains[j] += tmp_gains[j]; } } } } if (spread > FL(70.0)) for (i=0;igains[i] +=(spread - FL(70.0))/FL(30.0) * (spread - FL(70.0))/FL(30.0)*FL(10.0); } /*normalization*/ for (i=0;igains[i]*p->gains[i]); } sum=SQRT(sum); for (i=0;igains[i] /= sum; } free(tmp_gains); return OK; } int vbap1_moving_init(CSOUND *csound, VBAP1_MOVING *p) { int i, j; MYFLT *ls_table, *ptr; LS_SET *ls_set_ptr; p->q.number = p->OUTCOUNT; ls_table = (MYFLT*) (csound->QueryGlobalVariableNoCheck(csound, "vbap_ls_table_0")); /* reading in loudspeaker info */ p->q.dim = (int)ls_table[0]; p->q.ls_am = (int)ls_table[1]; p->q.ls_set_am = (int)ls_table[2]; ptr = &(ls_table[3]); if (!p->q.ls_set_am) return csound->InitError(csound, Str("vbap system NOT configured. \n" "Missing vbaplsinit opcode" " in orchestra?")); csound->AuxAlloc(csound, p->q.ls_set_am * sizeof(LS_SET), &p->q.aux); if (UNLIKELY(p->q.aux.auxp == NULL)) { return csound->InitError(csound, Str("could not allocate memory")); } p->q.ls_sets = (LS_SET*) p->q.aux.auxp; ls_set_ptr = p->q.ls_sets; for (i=0 ; i < p->q.ls_set_am ; i++) { ls_set_ptr[i].ls_nos[2] = 0; /* initial setting */ for (j=0 ; j < p->q.dim ; j++) { ls_set_ptr[i].ls_nos[j] = (int)*(ptr++); } for (j=0 ; j < 9; j++) ls_set_ptr[i].ls_mx[j] = FL(0.0); /*initial setting*/ for (j=0 ; j < (p->q.dim) * (p->q.dim); j++) { ls_set_ptr[i].ls_mx[j] = (MYFLT)*(ptr++); } } /* other initialization */ p->q.ele_vel = FL(1.0); /* functions specific to movement */ if (UNLIKELY(fabs(*p->field_am) < (2+ (p->q.dim - 2)*2))) { return csound->InitError(csound, Str("Have to have at least %d directions in vbapmove"), 2 + (p->q.dim - 2) * 2); } if (p->q.dim == 2) p->q.point_change_interval = (int)(CS_EKR * *p->dur /(fabs(*p->field_am) - 1.0)); else if (LIKELY(p->q.dim == 3)) p->q.point_change_interval = (int)(CS_EKR * *p->dur /(fabs(*p->field_am)*0.5 - 1.0)); else return csound->InitError(csound, Str("Wrong dimension")); p->q.point_change_counter = 0; p->q.curr_fld = 0; p->q.next_fld = 1; p->q.ang_dir.azi = *p->fld[0]; if (p->q.dim == 3) { p->q.ang_dir.ele = *p->fld[1]; } else { p->q.ang_dir.ele = FL(0.0); } if (p->q.dim == 3) { p->q.curr_fld = 1; p->q.next_fld = 2; } angle_to_cart(p->q.ang_dir, &(p->q.cart_dir)); p->q.spread_base.x = p->q.cart_dir.y; p->q.spread_base.y = p->q.cart_dir.z; p->q.spread_base.z = -p->q.cart_dir.x; vbap1_moving_control(csound,&p->q, p->h.insdshead, CS_ONEDKR, *p->spread, *p->field_am, p->fld); return OK; } int vbap1_moving_init_a(CSOUND *csound, VBAPA1_MOVING *p) { int i, j; MYFLT *ls_table, *ptr; LS_SET *ls_set_ptr; if (UNLIKELY(p->tabout->data == NULL || p->tabout->dimensions!=1)) return csound->InitError(csound, Str("Output array not initialised")); p->q.number = p->tabout->sizes[0]; ls_table = (MYFLT*) (csound->QueryGlobalVariableNoCheck(csound, "vbap_ls_table_0")); /* reading in loudspeaker info */ p->q.dim = (int)ls_table[0]; p->q.ls_am = (int)ls_table[1]; p->q.ls_set_am = (int)ls_table[2]; ptr = &(ls_table[3]); if (UNLIKELY(!p->q.ls_set_am)) return csound->InitError(csound, Str("vbap system NOT configured. \n" "Missing vbaplsinit opcode" " in orchestra?")); csound->AuxAlloc(csound, p->q.ls_set_am * sizeof(LS_SET), &p->q.aux); if (UNLIKELY(p->q.aux.auxp == NULL)) { return csound->InitError(csound, Str("could not allocate memory")); } p->q.ls_sets = (LS_SET*) p->q.aux.auxp; ls_set_ptr = p->q.ls_sets; for (i=0 ; i < p->q.ls_set_am ; i++) { ls_set_ptr[i].ls_nos[2] = 0; /* initial setting */ for (j=0 ; j < p->q.dim ; j++) { ls_set_ptr[i].ls_nos[j] = (int)*(ptr++); } for (j=0 ; j < 9; j++) ls_set_ptr[i].ls_mx[j] = FL(0.0); /*initial setting*/ for (j=0 ; j < (p->q.dim) * (p->q.dim); j++) { ls_set_ptr[i].ls_mx[j] = (MYFLT)*(ptr++); } } /* other initialization */ p->q.ele_vel = FL(1.0); /* functions specific to movement */ if (UNLIKELY(fabs(*p->field_am) < (2+ (p->q.dim - 2)*2))) { return csound->InitError(csound, Str("Have to have at least %d directions in vbapmove"), 2 + (p->q.dim - 2) * 2); } if (p->q.dim == 2) p->q.point_change_interval = (int)(CS_EKR * *p->dur /(fabs(*p->field_am) - 1.0)); else if (LIKELY(p->q.dim == 3)) p->q.point_change_interval = (int)(CS_EKR * *p->dur /(fabs(*p->field_am)*0.5 - 1.0)); else return csound->InitError(csound, Str("Wrong dimension")); p->q.point_change_counter = 0; p->q.curr_fld = 0; p->q.next_fld = 1; p->q.ang_dir.azi = *p->fld[0]; if (p->q.dim == 3) { p->q.ang_dir.ele = *p->fld[1]; } else { p->q.ang_dir.ele = FL(0.0); } if (p->q.dim == 3) { p->q.curr_fld = 1; p->q.next_fld = 2; } angle_to_cart(p->q.ang_dir, &(p->q.cart_dir)); p->q.spread_base.x = p->q.cart_dir.y; p->q.spread_base.y = p->q.cart_dir.z; p->q.spread_base.z = -p->q.cart_dir.x; vbap1_moving_control(csound,&p->q, p->h.insdshead, CS_ONEDKR, *p->spread, *p->field_am, p->fld); return OK; } csound-6.10.0/Opcodes/vbap_n.c000066400000000000000000000744551321653344700161250ustar00rootroot00000000000000/* vbap_n.c: Copyright (C) 2000 Ville Pulkki This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* vbap_n.c functions specific to four loudspeaker VBAP Ville Pulkki heavily modified by John ffitch 2012 */ #include "csoundCore.h" #include "vbap.h" #include #include #include int vbap_moving_control(CSOUND *, VBAP_MOVE_DATA *, INSDS*, MYFLT, MYFLT *, MYFLT*,MYFLT**); int vbap(CSOUND *csound, VBAP *p) /* during note performance: */ { MYFLT *outptr, *inptr; MYFLT ogain, ngain, gainsubstr; MYFLT invfloatn; int j; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; int cnt = p->q.number; vbap_control(csound,&p->q, p->azi, p->ele, p->spread); for (j=0; jq.beg_gains[j] = p->q.end_gains[j]; p->q.end_gains[j] = p->q.updated_gains[j]; } /* write audio to result audio streams weighted with gain factors*/ if (UNLIKELY(early)) nsmps -= early; invfloatn = FL(1.0)/(nsmps-offset); for (j=0; jaudio; outptr = p->out_array[j]; ogain = p->q.beg_gains[j]; ngain = p->q.end_gains[j]; gainsubstr = ngain - ogain; if (UNLIKELY(offset)) memset(outptr, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) memset(&outptr[nsmps], '\0', early*sizeof(MYFLT)); //printf("cnt%d: ngain=%lf ogain=%f\n", j, ngain, ogain); if (ngain != FL(0.0) || ogain != FL(0.0)) { if (ngain != ogain) { for (i = offset; i < nsmps; i++) { outptr[i] = inptr[i] * (ogain + (MYFLT)(i+1) * invfloatn * gainsubstr); } p->q.curr_gains[j]= ogain + (MYFLT)(i) * invfloatn * gainsubstr; } else { for (i=offset; ih.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; uint32_t ksmps = nsmps; int cnt = p->q.number; vbap_control(csound,&p->q, p->azi, p->ele, p->spread); for (j=0; jq.beg_gains[j] = p->q.end_gains[j]; p->q.end_gains[j] = p->q.updated_gains[j]; } /* write audio to result audio streams weighted with gain factors*/ if (UNLIKELY(early)) nsmps -= early; invfloatn = FL(1.0)/(nsmps-offset); for (j=0; jtabout->data[j*ksmps]; inptr = p->audio; ogain = p->q.beg_gains[j]; ngain = p->q.end_gains[j]; gainsubstr = ngain - ogain; if (UNLIKELY(offset)) memset(outptr, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) memset(&outptr[nsmps], '\0', early*sizeof(MYFLT)); if (ngain != FL(0.0) || ogain != FL(0.0)) { if (ngain != ogain) { for (i = offset; i < nsmps; i++) { outptr[i] = inptr[i] * (ogain + (MYFLT)(i+1) * invfloatn * gainsubstr); } p->q.curr_gains[j]= ogain + (MYFLT)(i) * invfloatn * gainsubstr; } else { for (i=offset; inumber; MYFLT *tmp_gains = malloc(sizeof(MYFLT)*cnt),sum=FL(0.0); if (UNLIKELY(p->dim == 2 && fabs(*ele) > 0.0)) { csound->Warning(csound, Str("Warning: truncating elevation to 2-D plane\n")); *ele = FL(0.0); } if (*spread FL(100.0)) *spread = FL(100.0); /* Current panning angles */ p->ang_dir.azi = (MYFLT) *azi; p->ang_dir.ele = (MYFLT) *ele; p->ang_dir.length = FL(1.0); angle_to_cart(p->ang_dir, &(p->cart_dir)); calc_vbap_gns(p->ls_set_am, p->dim, p->ls_sets, p->updated_gains, cnt, p->cart_dir); /* Calculated gain factors of a spreaded virtual source*/ if (*spread > FL(0.0)) { if (p->dim == 3) { spreaddirnum = 16; /* four orthogonal dirs*/ new_spread_dir(&spreaddir[0], p->cart_dir, p->spread_base, *azi, *spread); new_spread_base(spreaddir[0], p->cart_dir, *spread, &p->spread_base); cross_prod(p->spread_base, p->cart_dir, &spreadbase[1]); cross_prod(spreadbase[1], p->cart_dir, &spreadbase[2]); cross_prod(spreadbase[2], p->cart_dir, &spreadbase[3]); /* four between them*/ vec_mean(p->spread_base, spreadbase[1], &spreadbase[4]); vec_mean(spreadbase[1], spreadbase[2], &spreadbase[5]); vec_mean(spreadbase[2], spreadbase[3], &spreadbase[6]); vec_mean(spreadbase[3], p->spread_base, &spreadbase[7]); /* four at half spreadangle*/ vec_mean(p->cart_dir, p->spread_base, &spreadbase[8]); vec_mean(p->cart_dir, spreadbase[1], &spreadbase[9]); vec_mean(p->cart_dir, spreadbase[2], &spreadbase[10]); vec_mean(p->cart_dir, spreadbase[3], &spreadbase[11]); /* four at quarter spreadangle*/ vec_mean(p->cart_dir, spreadbase[8], &spreadbase[12]); vec_mean(p->cart_dir, spreadbase[9], &spreadbase[13]); vec_mean(p->cart_dir, spreadbase[10], &spreadbase[14]); vec_mean(p->cart_dir, spreadbase[11], &spreadbase[15]); for (i=1;icart_dir, spreadbase[i],*azi,*spread); calc_vbap_gns(p->ls_set_am, p->dim, p->ls_sets, tmp_gains, cnt, spreaddir[i]); for (j=0;jupdated_gains[j] += tmp_gains[j]; } } } else if (p->dim == 2) { spreaddirnum = 6; atmp.ele = FL(0.0); atmp.azi = *azi - *spread; angle_to_cart(atmp, &spreaddir[0]); atmp.azi = *azi - *spread/2; angle_to_cart(atmp, &spreaddir[1]); atmp.azi = *azi - *spread/4; angle_to_cart(atmp, &spreaddir[2]); atmp.azi = *azi + *spread/4; angle_to_cart(atmp, &spreaddir[3]); atmp.azi = *azi + *spread/2; angle_to_cart(atmp, &spreaddir[4]); atmp.azi = *azi + *spread; angle_to_cart(atmp, &spreaddir[5]); for (i=0;ils_set_am, p->dim, p->ls_sets, tmp_gains, cnt, spreaddir[i]); for (j=0;jupdated_gains[j] += tmp_gains[j]; } } } } if (*spread > FL(70.0)) for (i=0;iupdated_gains[i] +=(*spread - FL(70.0))/FL(30.0) * (*spread - FL(70.0))/FL(30.0)*FL(20.0); } /*normalization*/ for (i=0;iupdated_gains[i]*p->updated_gains[i]; } sum=SQRT(sum); for (i=0;iupdated_gains[i] /= sum; } free(tmp_gains); return OK; } int vbap_init(CSOUND *csound, VBAP *p) { /* Initializations before run time*/ int i, j; MYFLT *ls_table, *ptr; LS_SET *ls_set_ptr; int cnt = p->q.number = (int)(p->OUTOCOUNT); char name[24]; if ((!strcmp(p->h.optext->t.opcod, "vbap.a")) == 0) { p->audio = p->out_array[cnt]; p->azi = p->out_array[cnt+1]; p->ele = p->out_array[cnt+2]; p->spread = p->out_array[cnt+3]; p->layout = p->out_array[cnt+4]; } snprintf(name, 24, "vbap_ls_table_%d", (p->layout==NULL?0:(int)*p->layout)); ls_table = (MYFLT*) (csound->QueryGlobalVariable(csound, name)); if (UNLIKELY(ls_table==NULL)) return csound->InitError(csound, Str("could not find layout table no.%d"), (int)*p->layout ); p->q.dim = (int)ls_table[0]; /* reading in loudspeaker info */ p->q.ls_am = (int)ls_table[1]; p->q.ls_set_am = (int)ls_table[2]; ptr = &(ls_table[3]); if (UNLIKELY(!p->q.ls_set_am)) return csound->InitError(csound, Str("vbap system NOT configured. \nMissing" " vbaplsinit opcode in orchestra?")); csound->AuxAlloc(csound, p->q.ls_set_am * sizeof (LS_SET), &p->q.aux); if (UNLIKELY(p->q.aux.auxp == NULL)) { return csound->InitError(csound, Str("could not allocate memory")); } p->q.ls_sets = (LS_SET*) p->q.aux.auxp; ls_set_ptr = p->q.ls_sets; for (i=0; i < p->q.ls_set_am; i++) { ls_set_ptr[i].ls_nos[2] = 0; /* initial setting */ for (j=0 ; j < p->q.dim ; j++) { ls_set_ptr[i].ls_nos[j] = (int)*(ptr++); } memset(ls_set_ptr[i].ls_mx, '\0', 9*sizeof(MYFLT)); // initial setting /* for (j=0 ; j < 9; j++) */ /* ls_set_ptr[i].ls_mx[j] = FL(0.0); /\*initial setting*\/ */ for (j=0 ; j < (p->q.dim) * (p->q.dim); j++) { ls_set_ptr[i].ls_mx[j] = (MYFLT)*(ptr++); } } /* other initialization */ if (UNLIKELY(p->q.dim == 2 && fabs(p->ele==NULL?0:*p->ele) > 0.0)) { csound->Warning(csound, Str("Warning: truncating elevation to 2-D plane\n")); *p->ele = FL(0.0); } p->q.ang_dir.azi = (MYFLT)*p->azi; p->q.ang_dir.ele = (MYFLT)*p->ele; p->q.ang_dir.length = FL(1.0); angle_to_cart(p->q.ang_dir, &(p->q.cart_dir)); p->q.spread_base.x = p->q.cart_dir.y; p->q.spread_base.y = p->q.cart_dir.z; p->q.spread_base.z = -p->q.cart_dir.x; vbap_control(csound,&(p->q), p->azi, p->ele, p->spread); for (i=0;iq.beg_gains[i] = p->q.updated_gains[i]; p->q.end_gains[i] = p->q.updated_gains[i]; } return OK; } int vbap_init_a(CSOUND *csound, VBAPA *p) { /* Initializations before run time*/ int i, j; MYFLT *ls_table, *ptr; LS_SET *ls_set_ptr; int cnt; char name[24]; cnt = p->q.number = p->tabout->sizes[0]; snprintf(name, 24, "vbap_ls_table_%d", (int)*p->layout); ls_table = (MYFLT*) (csound->QueryGlobalVariable(csound, name)); if (UNLIKELY(ls_table==NULL)) return csound->InitError(csound, Str("could not find layout table no.%d"), (int)*p->layout ); p->q.dim = (int)ls_table[0]; /* reading in loudspeaker info */ p->q.ls_am = (int)ls_table[1]; p->q.ls_set_am = (int)ls_table[2]; ptr = &(ls_table[3]); if (UNLIKELY(!p->q.ls_set_am)) return csound->InitError(csound, Str("vbap system NOT configured.\nMissing" " vbaplsinit opcode in orchestra?")); csound->AuxAlloc(csound, p->q.ls_set_am * sizeof(LS_SET), &p->q.aux); if (UNLIKELY(p->q.aux.auxp == NULL)) { return csound->InitError(csound, Str("could not allocate memory")); } p->q.ls_sets = (LS_SET*) p->q.aux.auxp; ls_set_ptr = p->q.ls_sets; for (i=0; i < p->q.ls_set_am; i++) { ls_set_ptr[i].ls_nos[2] = 0; /* initial setting */ for (j=0 ; j < p->q.dim ; j++) { ls_set_ptr[i].ls_nos[j] = (int)*(ptr++); } memset(ls_set_ptr[i].ls_mx, '\0', 9*sizeof(MYFLT)); /* for (j=0 ; j < 9; j++) */ /* ls_set_ptr[i].ls_mx[j] = FL(0.0); /\*initial setting*\/ */ for (j=0 ; j < (p->q.dim) * (p->q.dim); j++) { ls_set_ptr[i].ls_mx[j] = (MYFLT)*(ptr++); } } /* other initialization */ if (UNLIKELY(p->q.dim == 2 && fabs(*p->ele) > 0.0)) { csound->Warning(csound, Str("Warning: truncating elevation to 2-D plane\n")); *p->ele = FL(0.0); } p->q.ang_dir.azi = *p->azi; p->q.ang_dir.ele = *p->ele; p->q.ang_dir.length = FL(1.0); angle_to_cart(p->q.ang_dir, &(p->q.cart_dir)); p->q.spread_base.x = p->q.cart_dir.y; p->q.spread_base.y = p->q.cart_dir.z; p->q.spread_base.z = -p->q.cart_dir.x; vbap_control(csound,&(p->q), p->azi, p->ele, p->spread); for (i=0;iq.beg_gains[i] = p->q.updated_gains[i]; p->q.end_gains[i] = p->q.updated_gains[i]; } return OK; } int vbap_moving(CSOUND *csound, VBAP_MOVING *p) { /* during note performance: */ MYFLT *outptr, *inptr; MYFLT ogain, ngain, gainsubstr; MYFLT invfloatn; int j; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; int cnt = p->q.number; vbap_moving_control(csound,&p->q, p->h.insdshead, CS_ONEDKR, p->spread, p->field_am, p->fld); // vbap_moving_control(csound,p); for (j=0;jq.beg_gains[j] = p->q.end_gains[j]; p->q.end_gains[j] = p->q.updated_gains[j]; } /* write audio to resulting audio streams weighted with gain factors*/ if (UNLIKELY(early)) nsmps -= early; invfloatn = FL(1.0)/(nsmps-offset); for (j=0; jaudio; outptr = p->out_array[j]; if (UNLIKELY(offset)) memset(outptr, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) memset(&outptr[nsmps], '\0', early*sizeof(MYFLT)); ogain = p->q.beg_gains[j]; ngain = p->q.end_gains[j]; gainsubstr = ngain - ogain; if (ngain != FL(0.0) || ogain != FL(0.0)) if (ngain != ogain) { for (i = offset; i < nsmps; i++) { outptr[i] = inptr[i] * (ogain + (MYFLT)(i+1) * invfloatn * gainsubstr); } p->q.curr_gains[j]= ogain + (MYFLT)(i) * invfloatn * gainsubstr; } else for (i=offset; inumber; MYFLT *tmp_gains=malloc(sizeof(MYFLT)*cnt),sum=FL(0.0); if (UNLIKELY(p->dim == 2 && fabs(p->ang_dir.ele) > 0.0)) { csound->Warning(csound, Str("Warning: truncating elevation to 2-D plane\n")); p->ang_dir.ele = FL(0.0); } if (*spread FL(100.0)) *spread = FL(100.0); if (p->point_change_counter++ >= p->point_change_interval) { p->point_change_counter = 0; p->curr_fld = p->next_fld; if (++p->next_fld >= (int) fabs(*field_am)) { if (*field_am >= FL(0.0)) /* point-to-point */ p->next_fld = 0; else p->next_fld = 1; } if (p->dim == 3) { /*jumping over second field */ p->curr_fld = p->next_fld; if (++p->next_fld >= ((int) fabs(*field_am))) { if (*field_am >= FL(0.0)) /* point-to-point */ p->next_fld = 0; else p->next_fld = 1; } } if (UNLIKELY((fld[abs(p->next_fld)]==NULL))) return csound->PerfError(csound, insdshead, Str("Missing fields in vbapmove\n")); if (*field_am >= FL(0.0) && p->dim == 2) /* point-to-point */ if (UNLIKELY(fabs(fabs(*fld[p->next_fld] - *fld[p->curr_fld]) - 180.0) < 1.0)) csound->Warning(csound, Str("Warning: Ambiguous transition 180 degrees.\n")); } if (*field_am >= FL(0.0)) { /* point-to-point */ if (p->dim == 3) { /* 3-D*/ p->prev_ang_dir.azi = *fld[p->curr_fld-1]; p->next_ang_dir.azi = *fld[p->next_fld]; p->prev_ang_dir.ele = *fld[p->curr_fld]; p->next_ang_dir.ele = *fld[p->next_fld+1]; coeff = ((MYFLT) p->point_change_counter) / ((MYFLT) p->point_change_interval); angle_to_cart( p->prev_ang_dir,&tmp1); angle_to_cart( p->next_ang_dir,&tmp2); tmp3.x = (FL(1.0)-coeff) * tmp1.x + coeff * tmp2.x; tmp3.y = (FL(1.0)-coeff) * tmp1.y + coeff * tmp2.y; tmp3.z = (FL(1.0)-coeff) * tmp1.z + coeff * tmp2.z; coeff = (MYFLT)sqrt((double)(tmp3.x * tmp3.x + tmp3.y * tmp3.y + tmp3.z * tmp3.z)); tmp3.x /= coeff; tmp3.y /= coeff; tmp3.z /= coeff; cart_to_angle(tmp3,&(p->ang_dir)); } else if (LIKELY(p->dim == 2)) { /* 2-D */ p->prev_ang_dir.azi = *fld[p->curr_fld]; p->next_ang_dir.azi = *fld[p->next_fld ]; p->prev_ang_dir.ele = p->next_ang_dir.ele = FL(0.0); scale_angles(&(p->prev_ang_dir)); scale_angles(&(p->next_ang_dir)); angle = (p->prev_ang_dir.azi - p->next_ang_dir.azi); while(angle > FL(180.0)) angle -= FL(360.0); while(angle < -FL(180.0)) angle += FL(360.0); coeff = ((MYFLT) p->point_change_counter) / ((MYFLT) p->point_change_interval); angle *= (coeff); p->ang_dir.azi = p->prev_ang_dir.azi - angle; p->ang_dir.ele = FL(0.0); } else { return csound->PerfError(csound, insdshead, Str("Missing fields in vbapmove\n")); } } else { /* angular velocities */ if (p->dim == 2) { p->ang_dir.azi = p->ang_dir.azi + (*fld[p->next_fld] * ONEDKR); scale_angles(&(p->ang_dir)); } else { /* 3D angular*/ p->ang_dir.azi = p->ang_dir.azi + (*fld[p->next_fld] * ONEDKR); p->ang_dir.ele = p->ang_dir.ele + p->ele_vel * (*fld[p->next_fld+1] * ONEDKR); if (p->ang_dir.ele > FL(90.0)) { p->ang_dir.ele = FL(90.0); p->ele_vel = -p->ele_vel; } if (p->ang_dir.ele < FL(0.0)) { p->ang_dir.ele = FL(0.0); p->ele_vel = -p->ele_vel; } scale_angles(&(p->ang_dir)); } } angle_to_cart(p->ang_dir, &(p->cart_dir)); calc_vbap_gns(p->ls_set_am, p->dim, p->ls_sets, p->updated_gains, cnt, p->cart_dir); if (*spread > FL(0.0)) { if (p->dim == 3) { spreaddirnum=16; /* four orthogonal dirs*/ new_spread_dir(&spreaddir[0], p->cart_dir, p->spread_base, p->ang_dir.azi, *spread); new_spread_base(spreaddir[0], p->cart_dir,*spread, &p->spread_base); cross_prod(p->spread_base, p->cart_dir, &spreadbase[1]); cross_prod(spreadbase[1], p->cart_dir, &spreadbase[2]); cross_prod(spreadbase[2], p->cart_dir, &spreadbase[3]); /* four between them*/ vec_mean(p->spread_base, spreadbase[1], &spreadbase[4]); vec_mean(spreadbase[1], spreadbase[2], &spreadbase[5]); vec_mean(spreadbase[2], spreadbase[3], &spreadbase[6]); vec_mean(spreadbase[3], p->spread_base, &spreadbase[7]); /* four at half spreadangle*/ vec_mean(p->cart_dir, p->spread_base, &spreadbase[8]); vec_mean(p->cart_dir, spreadbase[1], &spreadbase[9]); vec_mean(p->cart_dir, spreadbase[2], &spreadbase[10]); vec_mean(p->cart_dir, spreadbase[3], &spreadbase[11]); /* four at quarter spreadangle*/ vec_mean(p->cart_dir, spreadbase[8], &spreadbase[12]); vec_mean(p->cart_dir, spreadbase[9], &spreadbase[13]); vec_mean(p->cart_dir, spreadbase[10], &spreadbase[14]); vec_mean(p->cart_dir, spreadbase[11], &spreadbase[15]); for (i=1;icart_dir, spreadbase[i],p->ang_dir.azi,*spread); calc_vbap_gns(p->ls_set_am, p->dim, p->ls_sets, tmp_gains, cnt, spreaddir[i]); for (j=0;jupdated_gains[j] += tmp_gains[j]; } } } else if (p->dim == 2) { spreaddirnum=6; atmp.ele = FL(0.0); atmp.azi = p->ang_dir.azi - *spread; angle_to_cart(atmp, &spreaddir[0]); atmp.azi = p->ang_dir.azi - *spread/2; angle_to_cart(atmp, &spreaddir[1]); atmp.azi = p->ang_dir.azi - *spread/4; angle_to_cart(atmp, &spreaddir[2]); atmp.azi = p->ang_dir.azi + *spread/4; angle_to_cart(atmp, &spreaddir[3]); atmp.azi = p->ang_dir.azi + *spread/2; angle_to_cart(atmp, &spreaddir[4]); atmp.azi = p->ang_dir.azi + *spread; angle_to_cart(atmp, &spreaddir[5]); for (i=0;ils_set_am, p->dim, p->ls_sets, tmp_gains, cnt, spreaddir[i]); for (j=0;jupdated_gains[j] += tmp_gains[j]; } } } } if (*spread > FL(70.0)) for (i=0;iupdated_gains[i] +=(*spread - FL(70.0))/FL(30.0) * (*spread - FL(70.0))/FL(30.0)*FL(10.0); } /*normalization*/ for (i=0;iupdated_gains[i]*p->updated_gains[i]); } sum=SQRT(sum); for (i=0;iupdated_gains[i] /= sum; } free(tmp_gains); return OK; } int vbap_moving_init(CSOUND *csound, VBAP_MOVING *p) { int i, j; MYFLT *ls_table, *ptr; LS_SET *ls_set_ptr; int cnt = (int)p->h.optext->t.outArgCount; if ((!strncmp(p->h.optext->t.opcod, "vbapmove", 8)) == 0) { p->audio = p->out_array[cnt]; p->dur = p->out_array[cnt+1]; p->spread = p->out_array[cnt+2]; p->field_am = p->out_array[cnt+3]; memcpy(p->fld, &(p->out_array[cnt+4]), sizeof(MYFLT *)*(p->h.optext->t.inArgCount-4)); } ls_table = (MYFLT*) (csound->QueryGlobalVariableNoCheck(csound, "vbap_ls_table_0")); if (UNLIKELY(ls_table==NULL)) return csound->InitError(csound, Str("could not find layout table no.0")); p->q.number = cnt; /* reading in loudspeaker info */ p->q.dim = (int)ls_table[0]; p->q.ls_am = (int)ls_table[1]; p->q.ls_set_am = (int)ls_table[2]; ptr = &(ls_table[3]); if (UNLIKELY(!p->q.ls_set_am)) return csound->InitError(csound, Str("vbap system NOT configured. \nMissing" " vbaplsinit opcode in orchestra?")); csound->AuxAlloc(csound, p->q.ls_set_am * sizeof(LS_SET), &p->q.aux); if (UNLIKELY(p->q.aux.auxp == NULL)) { return csound->InitError(csound, Str("could not allocate memory")); } p->q.ls_sets = (LS_SET*) p->q.aux.auxp; ls_set_ptr = p->q.ls_sets; for (i=0 ; i < p->q.ls_set_am ; i++) { ls_set_ptr[i].ls_nos[2] = 0; /* initial setting */ for (j=0 ; j < p->q.dim ; j++) { ls_set_ptr[i].ls_nos[j] = (int)*(ptr++); } for (j=0 ; j < 9; j++) ls_set_ptr[i].ls_mx[j] = FL(0.0); /*initial setting*/ for (j=0 ; j < (p->q.dim) * (p->q.dim); j++) { ls_set_ptr[i].ls_mx[j] = (MYFLT)*(ptr++); } } /* other initialization */ p->q.ele_vel = FL(1.0); /* functions specific to movement */ if (UNLIKELY(fabs(*p->field_am) < (2+ (p->q.dim - 2)*2))) { return csound->InitError(csound, Str("Have to have at least %d directions in vbapmove"), 2 + (p->q.dim - 2) * 2); } if (p->q.dim == 2) p->q.point_change_interval = (int)(CS_EKR * *p->dur /(fabs(*p->field_am) - 1.0)); else if (LIKELY(p->q.dim == 3)) p->q.point_change_interval = (int)(CS_EKR * *p->dur /(fabs(*p->field_am)*0.5 - 1.0)); else return csound->InitError(csound, Str("Wrong dimension")); p->q.point_change_counter = 0; p->q.curr_fld = 0; p->q.next_fld = 1; p->q.ang_dir.azi = *p->fld[0]; if (p->q.dim == 3) { p->q.ang_dir.ele = *p->fld[1]; } else { p->q.ang_dir.ele = FL(0.0); } if (p->q.dim == 3) { p->q.curr_fld = 1; p->q.next_fld = 2; } angle_to_cart(p->q.ang_dir, &(p->q.cart_dir)); p->q.spread_base.x = p->q.cart_dir.y; p->q.spread_base.y = p->q.cart_dir.z; p->q.spread_base.z = -p->q.cart_dir.x; vbap_moving_control(csound,&p->q, p->h.insdshead, CS_ONEDKR, p->spread, p->field_am, p->fld); for (i = 0; iq.beg_gains[i] = p->q.updated_gains[i]; p->q.end_gains[i] = p->q.updated_gains[i]; } return OK; } int vbap_moving_a(CSOUND *csound, VBAPA_MOVING *p) { /* during note performance: */ MYFLT *outptr, *inptr; MYFLT ogain, ngain, gainsubstr; MYFLT invfloatn; int j; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; uint32_t ksmps = nsmps; int cnt = p->q.number; vbap_moving_control(csound,&p->q, p->h.insdshead, CS_ONEDKR, p->spread, p->field_am, p->fld); // vbap_moving_control(csound,p); for (j=0;jq.beg_gains[j] = p->q.end_gains[j]; p->q.end_gains[j] = p->q.updated_gains[j]; } /* write audio to resulting audio streams weighted with gain factors*/ if (UNLIKELY(early)) nsmps -= early; invfloatn = FL(1.0)/(nsmps-offset); outptr = p->tabout->data; for (j=0; jaudio; outptr = &p->tabout->data[j*ksmps]; if (UNLIKELY(offset)) memset(outptr, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) memset(&outptr[nsmps], '\0', early*sizeof(MYFLT)); ogain = p->q.beg_gains[j]; ngain = p->q.end_gains[j]; gainsubstr = ngain - ogain; if (ngain != FL(0.0) || ogain != FL(0.0)) if (ngain != ogain) { for (i = offset; i < nsmps; i++) { outptr[i] = inptr[i] * (ogain + (MYFLT)(i+1) * invfloatn * gainsubstr); } p->q.curr_gains[j]= ogain + (MYFLT)(i) * invfloatn * gainsubstr; } else for (i=offset; itabout->data==NULL)) { return csound->InitError(csound, Str("Output array in vpabmove not initalised")); } cnt = p->tabout->sizes[0]; ls_table = (MYFLT*) (csound->QueryGlobalVariableNoCheck(csound, "vbap_ls_table_0")); if (UNLIKELY(ls_table==NULL)) return csound->InitError(csound, Str("could not find layout table no.0")); p->q.number = cnt; /* reading in loudspeaker info */ p->q.dim = (int)ls_table[0]; p->q.ls_am = (int)ls_table[1]; p->q.ls_set_am = (int)ls_table[2]; ptr = &(ls_table[3]); if (UNLIKELY(!p->q.ls_set_am)) return csound->InitError(csound, Str("vbap system NOT configured.\nMissing" " vbaplsinit opcode in orchestra?")); csound->AuxAlloc(csound, p->q.ls_set_am * sizeof(LS_SET), &p->q.aux); if (UNLIKELY(p->q.aux.auxp == NULL)) { return csound->InitError(csound, Str("could not allocate memory")); } p->q.ls_sets = (LS_SET*) p->q.aux.auxp; ls_set_ptr = p->q.ls_sets; for (i=0 ; i < p->q.ls_set_am ; i++) { ls_set_ptr[i].ls_nos[2] = 0; /* initial setting */ for (j=0 ; j < p->q.dim ; j++) { ls_set_ptr[i].ls_nos[j] = (int)*(ptr++); } memset(ls_set_ptr[i].ls_mx, '\0', 9*sizeof(MYFLT)); /* for (j=0 ; j < 9; j++) */ /* ls_set_ptr[i].ls_mx[j] = FL(0.0); /\*initial setting*\/ */ for (j=0 ; j < (p->q.dim) * (p->q.dim); j++) { ls_set_ptr[i].ls_mx[j] = (MYFLT)*(ptr++); } } /* other initialization */ p->q.ele_vel = FL(1.0); /* functions specific to movement */ if (UNLIKELY(fabs(*p->field_am) < (2+ (p->q.dim - 2)*2))) { return csound->InitError(csound, Str("Have to have at least %d directions in vbapmove"), 2 + (p->q.dim - 2) * 2); } if (p->q.dim == 2) p->q.point_change_interval = (int)(CS_EKR * *p->dur /(fabs(*p->field_am) - 1.0)); else if (LIKELY(p->q.dim == 3)) p->q.point_change_interval = (int)(CS_EKR * *p->dur /(fabs(*p->field_am)*0.5 - 1.0)); else return csound->InitError(csound, Str("Wrong dimension")); p->q.point_change_counter = 0; p->q.curr_fld = 0; p->q.next_fld = 1; p->q.ang_dir.azi = *p->fld[0]; if (p->q.dim == 3) { p->q.ang_dir.ele = *p->fld[1]; } else { p->q.ang_dir.ele = FL(0.0); } if (p->q.dim == 3) { p->q.curr_fld = 1; p->q.next_fld = 2; } angle_to_cart(p->q.ang_dir, &(p->q.cart_dir)); p->q.spread_base.x = p->q.cart_dir.y; p->q.spread_base.y = p->q.cart_dir.z; p->q.spread_base.z = -p->q.cart_dir.x; vbap_moving_control(csound,&p->q, p->h.insdshead, CS_ONEDKR, p->spread, p->field_am, p->fld); for (i = 0; iq.beg_gains[i] = p->q.updated_gains[i]; p->q.end_gains[i] = p->q.updated_gains[i]; } return OK; } csound-6.10.0/Opcodes/vbap_zak.c000066400000000000000000000525601321653344700164460ustar00rootroot00000000000000/* vbap_zak.c: Copyright (C) 2000 Ville Pulkki This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* vbap_zak.c functions specific to n loudspeaker VBAP Ville Pulkki & John ffitch */ #include "csoundCore.h" #include "vbap.h" #include #include #include int vbap_zak_moving_control(CSOUND *, VBAP_ZAK_MOVING *); int vbap_zak_control(CSOUND *,VBAP_ZAK *); int vbap_zak(CSOUND *csound, VBAP_ZAK *p) /* during note performance: */ { MYFLT *outptr, *inptr; MYFLT ogain, ngain, gainsubstr; MYFLT invfloatn; int j; int n = p->n; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; vbap_zak_control(csound,p); for (j=0; jbeg_gains[j] = p->end_gains[j]; p->end_gains[j] = p->updated_gains[j]; } /* write audio to result audio streams weighted with gain factors */ outptr = p->out_array; if (UNLIKELY(early)) nsmps -= early; invfloatn = FL(1.0)/(nsmps-offset); for (j=0; jaudio; ogain = p->beg_gains[j]; ngain = p->end_gains[j]; gainsubstr = ngain - ogain; if (UNLIKELY(offset)) memset(outptr, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) memset(&outptr[nsmps], '\0', early*sizeof(MYFLT)); if (ngain != FL(0.0) || ogain != FL(0.0)) if (ngain != ogain) { for (i = offset; i < nsmps; i++) { outptr[i] = inptr[i] * (ogain + (MYFLT) (i+1) * invfloatn * gainsubstr); } p->curr_gains[j]= ogain + (MYFLT) (i) * invfloatn * gainsubstr; } else { for (i=offset; in; MYFLT tmp_gains[MAXCHNLS],sum = FL(0.0); if (UNLIKELY(p->dim == 2 && fabs(*p->ele) > 0.0)) { csound->Warning(csound, Str("Warning: truncating elevation to 2-D plane\n")); *p->ele = FL(0.0); } if (*p->spread spread=FL(0.0); else if (*p->spread >FL(100.0)) *p->spread=FL(100.0); /* Current panning angles */ p->ang_dir.azi = (MYFLT) *p->azi; p->ang_dir.ele = (MYFLT) *p->ele; p->ang_dir.length = FL(1.0); angle_to_cart(p->ang_dir, &(p->cart_dir)); calc_vbap_gns(p->ls_set_am, p->dim, p->ls_sets, p->updated_gains, n, p->cart_dir); /* Calculated gain factors of a spreaded virtual source */ if (*p->spread > FL(0.0)) { if (p->dim == 3) { spreaddirnum=16; /* four orthogonal dirs */ new_spread_dir(&spreaddir[0], p->cart_dir, p->spread_base, *p->azi, *p->spread); new_spread_base(spreaddir[0], p->cart_dir,*p->spread, &p->spread_base); cross_prod(p->spread_base, p->cart_dir, &spreadbase[1]); cross_prod(spreadbase[1], p->cart_dir, &spreadbase[2]); cross_prod(spreadbase[2], p->cart_dir, &spreadbase[3]); /* four between them */ vec_mean(p->spread_base, spreadbase[1], &spreadbase[4]); vec_mean(spreadbase[1], spreadbase[2], &spreadbase[5]); vec_mean(spreadbase[2], spreadbase[3], &spreadbase[6]); vec_mean(spreadbase[3], p->spread_base, &spreadbase[7]); /* four at half spreadangle */ vec_mean(p->cart_dir, p->spread_base, &spreadbase[8]); vec_mean(p->cart_dir, spreadbase[1], &spreadbase[9]); vec_mean(p->cart_dir, spreadbase[2], &spreadbase[10]); vec_mean(p->cart_dir, spreadbase[3], &spreadbase[11]); /* four at quarter spreadangle */ vec_mean(p->cart_dir, spreadbase[8], &spreadbase[12]); vec_mean(p->cart_dir, spreadbase[9], &spreadbase[13]); vec_mean(p->cart_dir, spreadbase[10], &spreadbase[14]); vec_mean(p->cart_dir, spreadbase[11], &spreadbase[15]); for (i=1;icart_dir, spreadbase[i],*p->azi,*p->spread); calc_vbap_gns(p->ls_set_am, p->dim, p->ls_sets, tmp_gains, n, spreaddir[i]); for (j=0;jupdated_gains[j] += tmp_gains[j]; } } } else if (p->dim == 2) { spreaddirnum = 6; atmp.ele = FL(0.0); atmp.azi = *p->azi - *p->spread; angle_to_cart(atmp, &spreaddir[0]); atmp.azi = *p->azi - *p->spread/2; angle_to_cart(atmp, &spreaddir[1]); atmp.azi = *p->azi - *p->spread/4; angle_to_cart(atmp, &spreaddir[2]); atmp.azi = *p->azi + *p->spread/4; angle_to_cart(atmp, &spreaddir[3]); atmp.azi = *p->azi + *p->spread/2; angle_to_cart(atmp, &spreaddir[4]); atmp.azi = *p->azi + *p->spread; angle_to_cart(atmp, &spreaddir[5]); for (i=0;ils_set_am, p->dim, p->ls_sets, tmp_gains, n, spreaddir[i]); for (j=0;jupdated_gains[j] += tmp_gains[j]; } } } } if (*p->spread > FL(70.0)) for (i=0;iupdated_gains[i] +=(*p->spread - FL(70.0))/FL(30.0) * (*p->spread - FL(70.0))/FL(30.0)*FL(20.0); } /* normalization */ for (i=0;iupdated_gains[i]*p->updated_gains[i]); } sum = SQRT(sum); for (i=0;iupdated_gains[i] /= sum; } return OK; } int vbap_zak_init(CSOUND *csound, VBAP_ZAK *p) { /* Initializations before run time */ int i, j, indx; MYFLT *ls_table, *ptr; /* , *gains; */ LS_SET *ls_set_ptr; int n = p->n = (int)MYFLT2LONG(*p->numb); /* Set size */ char name[24]; /* Check to see this index is within the limits of za space. */ indx = (int32) *p->ndx; if (UNLIKELY(indx > csound->zalast)) { return csound->PerfError(csound, p->h.insdshead, Str("outz index > isizea. No output")); } else if (UNLIKELY(indx < 0)) { return csound->PerfError(csound, p->h.insdshead, Str("outz index < 0. No output.")); } if ((int)*p->layout==0) strcpy(name, "vbap_ls_table"); else snprintf(name, 24, "vbap_ls_table_%d", (int)*p->layout==0); /* Now read from the array in za space and write to the output. */ p->out_array = csound->zastart + (indx * CS_KSMPS);/* outputs */ csound->AuxAlloc(csound, p->n*sizeof(MYFLT)*4, &p->auxch); p->curr_gains = (MYFLT*)p->auxch.auxp; p->beg_gains = p->curr_gains + p->n; p->end_gains = p->beg_gains + p->n; p->updated_gains = p->end_gains + p->n; ls_table = (MYFLT*) (csound->QueryGlobalVariableNoCheck(csound, name)); p->dim = (int) ls_table[0]; /* reading in loudspeaker info */ p->ls_am = (int) ls_table[1]; p->ls_set_am = (int) ls_table[2]; ptr = &(ls_table[3]); csound->AuxAlloc(csound, p->ls_set_am * sizeof (LS_SET), &p->aux); if (UNLIKELY(p->aux.auxp == NULL)) { return csound->InitError(csound, Str("could not allocate memory")); } p->ls_sets = (LS_SET*) p->aux.auxp; ls_set_ptr = p->ls_sets; for (i=0 ; i < p->ls_set_am ; i++) { ls_set_ptr[i].ls_nos[2] = 0; /* initial setting */ for (j=0 ; j < p->dim ; j++) { ls_set_ptr[i].ls_nos[j] = (int) *(ptr++); } for (j=0 ; j < 9; j++) ls_set_ptr[i].ls_mx[j] = FL(0.0); /* initial setting */ for (j=0 ; j < (p->dim) * (p->dim); j++) { ls_set_ptr[i].ls_mx[j] = (MYFLT) *(ptr++); } } /* other initialization */ if (UNLIKELY(p->dim == 2 && fabs(*p->ele) > 0.0)) { csound->Warning(csound, Str("Warning: truncating elevation to 2-D plane\n")); *p->ele = FL(0.0); } p->ang_dir.azi = (MYFLT) *p->azi; p->ang_dir.ele = (MYFLT) *p->ele; p->ang_dir.length = FL(1.0); angle_to_cart(p->ang_dir, &(p->cart_dir)); p->spread_base.x = p->cart_dir.y; p->spread_base.y = p->cart_dir.z; p->spread_base.z = -p->cart_dir.x; vbap_zak_control(csound,p); for (i=0;ibeg_gains[i] = p->updated_gains[i]; p->end_gains[i] = p->updated_gains[i]; } return OK; } int vbap_zak_moving(CSOUND *csound, VBAP_ZAK_MOVING *p) { /* during note performance: */ MYFLT *outptr, *inptr; MYFLT ogain, ngain, gainsubstr; MYFLT invfloatn; int j; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; vbap_zak_moving_control(csound,p); for (j=0;j< p->n; j++) { p->beg_gains[j] = p->end_gains[j]; p->end_gains[j] = p->updated_gains[j]; } /* write audio to resulting audio streams weighted with gain factors */ invfloatn = FL(1.0)/(nsmps-offset); outptr = p->out_array; if (UNLIKELY(offset)) memset(outptr, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&outptr[nsmps], '\0', early*sizeof(MYFLT)); } for (j=0; jn ;j++) { inptr = p->audio; ogain = p->beg_gains[j]; ngain = p->end_gains[j]; gainsubstr = ngain - ogain; if (ngain != FL(0.0) || ogain != FL(0.0)) if (ngain != ogain) { for (i = offset; i < nsmps; i++) { outptr[i] = inptr[i] * (ogain + (MYFLT) (i+1) * invfloatn * gainsubstr); } p->curr_gains[j] = ogain + (MYFLT) (i) * invfloatn * gainsubstr; } else for (i=offset; in; CART_VEC tmp1, tmp2, tmp3; MYFLT coeff, angle; MYFLT tmp_gains[MAXCHNLS],sum = FL(0.0); /* Array long enough */ if (UNLIKELY(p->dim == 2 && fabs(p->ang_dir.ele) > 0.0)) { csound->Warning(csound, Str("Warning: truncating elevation to 2-D plane\n")); p->ang_dir.ele = FL(0.0); } if (*p->spread spread = FL(0.0); else if (*p->spread >FL(100.0)) *p->spread = FL(100.0); if (p->point_change_counter++ >= p->point_change_interval) { p->point_change_counter = 0; p->curr_fld = p->next_fld; if (++p->next_fld >= (int) fabs(*p->field_am)) { if (*p->field_am >= FL(0.0)) /* point-to-point */ p->next_fld = 0; else p->next_fld = 1; } if (p->dim == 3) { /* jumping over second field */ p->curr_fld = p->next_fld; if (++p->next_fld >= ((int) fabs(*p->field_am))) { if (*p->field_am >= FL(0.0)) /* point-to-point */ p->next_fld = 0; else p->next_fld = 1; } } if (UNLIKELY((p->fld[abs(p->next_fld)]==NULL))) return csound->PerfError(csound, p->h.insdshead, Str("Missing fields in vbapzmove\n")); if (*p->field_am >= FL(0.0) && p->dim == 2) /* point-to-point */ if (UNLIKELY(fabs(fabs(*p->fld[p->next_fld] - *p->fld[p->curr_fld]) - 180.0) < 1.0)) csound->Warning(csound, Str("Warning: Ambiguous transition 180 degrees.\n")); } if (*p->field_am >= FL(0.0)) { /* point-to-point */ if (p->dim == 3) { /* 3-D */ p->prev_ang_dir.azi = *p->fld[p->curr_fld-1]; p->next_ang_dir.azi = *p->fld[p->next_fld]; p->prev_ang_dir.ele = *p->fld[p->curr_fld]; p->next_ang_dir.ele = *p->fld[p->next_fld+1]; coeff = ((MYFLT) p->point_change_counter) / ((MYFLT) p->point_change_interval); angle_to_cart( p->prev_ang_dir,&tmp1); angle_to_cart( p->next_ang_dir,&tmp2); tmp3.x = (FL(1.0)-coeff) * tmp1.x + coeff * tmp2.x; tmp3.y = (FL(1.0)-coeff) * tmp1.y + coeff * tmp2.y; tmp3.z = (FL(1.0)-coeff) * tmp1.z + coeff * tmp2.z; coeff = (MYFLT)sqrt((double)(tmp3.x * tmp3.x + tmp3.y * tmp3.y + tmp3.z * tmp3.z)); tmp3.x /= coeff; tmp3.y /= coeff; tmp3.z /= coeff; cart_to_angle(tmp3,&(p->ang_dir)); } else if (p->dim == 2) { /* 2-D */ p->prev_ang_dir.azi = *p->fld[p->curr_fld]; p->next_ang_dir.azi = *p->fld[p->next_fld ]; p->prev_ang_dir.ele = p->next_ang_dir.ele = FL(0.0); scale_angles(&(p->prev_ang_dir)); scale_angles(&(p->next_ang_dir)); angle = (p->prev_ang_dir.azi - p->next_ang_dir.azi); while(angle > FL(180.0)) angle -= FL(360.0); while(angle < -FL(180.0)) angle += FL(360.0); coeff = ((MYFLT) p->point_change_counter) / ((MYFLT) p->point_change_interval); angle *= (coeff); p->ang_dir.azi = p->prev_ang_dir.azi - angle; p->ang_dir.ele = FL(0.0); } else { return csound->PerfError(csound, p->h.insdshead, Str("Missing fields in vbapzmove\n")); } } else { /* angular velocities */ if (p->dim == 2) { p->ang_dir.azi = p->ang_dir.azi + (*p->fld[p->next_fld] * CS_ONEDKR); scale_angles(&(p->ang_dir)); } else { /* 3D angular */ p->ang_dir.azi = p->ang_dir.azi + (*p->fld[p->next_fld] * CS_ONEDKR); p->ang_dir.ele = p->ang_dir.ele + p->ele_vel * (*p->fld[p->next_fld+1] * CS_ONEDKR); if (p->ang_dir.ele > FL(90.0)) { p->ang_dir.ele = FL(90.0); p->ele_vel = -p->ele_vel; } if (p->ang_dir.ele < FL(0.0)) { p->ang_dir.ele = FL(0.0); p->ele_vel = -p->ele_vel; } scale_angles(&(p->ang_dir)); } } angle_to_cart(p->ang_dir, &(p->cart_dir)); calc_vbap_gns(p->ls_set_am, p->dim, p->ls_sets, p->updated_gains, n, p->cart_dir); if (*p->spread > FL(0.0)) { if (p->dim == 3) { spreaddirnum=16; /* four orthogonal dirs */ new_spread_dir(&spreaddir[0], p->cart_dir, p->spread_base, p->ang_dir.azi, *p->spread); new_spread_base(spreaddir[0], p->cart_dir,*p->spread, &p->spread_base); cross_prod(p->spread_base, p->cart_dir, &spreadbase[1]); cross_prod(spreadbase[1], p->cart_dir, &spreadbase[2]); cross_prod(spreadbase[2], p->cart_dir, &spreadbase[3]); /* four between them */ vec_mean(p->spread_base, spreadbase[1], &spreadbase[4]); vec_mean(spreadbase[1], spreadbase[2], &spreadbase[5]); vec_mean(spreadbase[2], spreadbase[3], &spreadbase[6]); vec_mean(spreadbase[3], p->spread_base, &spreadbase[7]); /* four at half spreadangle */ vec_mean(p->cart_dir, p->spread_base, &spreadbase[8]); vec_mean(p->cart_dir, spreadbase[1], &spreadbase[9]); vec_mean(p->cart_dir, spreadbase[2], &spreadbase[10]); vec_mean(p->cart_dir, spreadbase[3], &spreadbase[11]); /* four at quarter spreadangle */ vec_mean(p->cart_dir, spreadbase[8], &spreadbase[12]); vec_mean(p->cart_dir, spreadbase[9], &spreadbase[13]); vec_mean(p->cart_dir, spreadbase[10], &spreadbase[14]); vec_mean(p->cart_dir, spreadbase[11], &spreadbase[15]); for (i=1;icart_dir, spreadbase[i],p->ang_dir.azi,*p->spread); calc_vbap_gns(p->ls_set_am, p->dim, p->ls_sets, tmp_gains, n, spreaddir[i]); for (j=0;jupdated_gains[j] += tmp_gains[j]; } } } else if (p->dim == 2) { spreaddirnum=6; atmp.ele=FL(0.0); atmp.azi=p->ang_dir.azi - *p->spread; angle_to_cart(atmp, &spreaddir[0]); atmp.azi=p->ang_dir.azi - *p->spread/2; angle_to_cart(atmp, &spreaddir[1]); atmp.azi=p->ang_dir.azi - *p->spread/4; angle_to_cart(atmp, &spreaddir[2]); atmp.azi=p->ang_dir.azi + *p->spread/4; angle_to_cart(atmp, &spreaddir[3]); atmp.azi=p->ang_dir.azi + *p->spread/2; angle_to_cart(atmp, &spreaddir[4]); atmp.azi=p->ang_dir.azi + *p->spread; angle_to_cart(atmp, &spreaddir[5]); for (i=0;ils_set_am, p->dim, p->ls_sets, tmp_gains, n, spreaddir[i]); for (j=0;jupdated_gains[j] += tmp_gains[j]; } } } } if (*p->spread > FL(70.0)) for (i=0;iupdated_gains[i] += (*p->spread - FL(70.0))/FL(30.0) * (*p->spread - FL(70.0))/FL(30.0)*FL(10.0); } /* normalization */ for (i=0;iupdated_gains[i]*p->updated_gains[i]); } sum = SQRT(sum); for (i=0;iupdated_gains[i] /= sum; } return OK; } int vbap_zak_moving_init(CSOUND *csound, VBAP_ZAK_MOVING *p) { int i, j, indx; MYFLT *ls_table, *ptr; LS_SET *ls_set_ptr; int n = p->n; p->n = (int)MYFLT2LONG(*p->numb); /* Set size */ /* Check to see this index is within the limits of za space. */ indx = (int32) *p->ndx; if (UNLIKELY(indx > csound->zalast)) { return csound->PerfError(csound, p->h.insdshead, Str("outz index > isizea. No output")); } else if (UNLIKELY(indx < 0)) { return csound->PerfError(csound, p->h.insdshead, Str("outz index < 0. No output.")); } /* Now read from the array in za space and write to the output. */ p->out_array = csound->zastart + (indx * CS_KSMPS);/* outputs */ csound->AuxAlloc(csound, p->n*sizeof(MYFLT)*4, &p->auxch); p->curr_gains = (MYFLT*)p->auxch.auxp; p->beg_gains = p->curr_gains + p->n; p->end_gains = p->beg_gains + p->n; p->updated_gains = p->end_gains + p->n; /* reading in loudspeaker info */ ls_table = (MYFLT*) (csound->QueryGlobalVariableNoCheck(csound, "vbap_ls_table_0")); p->dim = (int) ls_table[0]; p->ls_am = (int) ls_table[1]; p->ls_set_am = (int) ls_table[2]; ptr = &(ls_table[3]); csound->AuxAlloc(csound, p->ls_set_am * sizeof (LS_SET), &p->aux); if (UNLIKELY(p->aux.auxp == NULL)) { return csound->InitError(csound, Str("could not allocate memory")); } p->ls_sets = (LS_SET*) p->aux.auxp; ls_set_ptr = p->ls_sets; for (i=0 ; i < p->ls_set_am ; i++) { ls_set_ptr[i].ls_nos[2] = 0; /* initial setting */ for (j=0 ; j < p->dim ; j++) { ls_set_ptr[i].ls_nos[j] = (int) *(ptr++); } memset(ls_set_ptr[i].ls_mx, '\0', 9*sizeof(MYFLT)); /* for (j=0 ; j < 9; j++) */ /* ls_set_ptr[i].ls_mx[j] = FL(0.0); /\* initial setting *\/ */ for (j=0 ; j < (p->dim) * (p->dim); j++) { ls_set_ptr[i].ls_mx[j] = (MYFLT) *(ptr++); } } /* other initialization */ p->ele_vel = FL(1.0); /* functions specific to movement */ if (UNLIKELY(fabs(*p->field_am) < (2+ (p->dim - 2)*2))) { return csound->InitError(csound, Str("Have to have at least %d directions in vbapzmove"), 2 + (p->dim - 2) * 2); } if (p->dim == 2) p->point_change_interval = (int) (CS_EKR * *p->dur / (fabs(*p->field_am) - 1.0)); else if (LIKELY(p->dim == 3)) p->point_change_interval = (int) (CS_EKR * *p->dur / (fabs(*p->field_am) * 0.5 - 1.0)); else return csound->InitError(csound, Str("Wrong dimension")); p->point_change_counter = 0; p->curr_fld = 0; p->next_fld = 1; p->ang_dir.azi = *p->fld[0]; if (p->dim == 3) { p->ang_dir.ele = *p->fld[1]; } else { p->ang_dir.ele = FL(0.0); } if (p->dim == 3) { p->curr_fld = 1; p->next_fld = 2; } angle_to_cart(p->ang_dir, &(p->cart_dir)); p->spread_base.x = p->cart_dir.y; p->spread_base.y = p->cart_dir.z; p->spread_base.z = -p->cart_dir.x; vbap_zak_moving_control(csound,p); for (i=0;ibeg_gains[i] = p->updated_gains[i]; p->end_gains[i] = p->updated_gains[i]; } return OK; } csound-6.10.0/Opcodes/vibraphn.h000066400000000000000000000032351321653344700164620ustar00rootroot00000000000000/* vibraphn.h: Copyright (C) 1996, 1997 Perry Cook, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /*******************************************/ /* Vibraphone SubClass of Modal4 */ /* Instrument, by Perry R. Cook, 1995-96 */ /* */ /* Controls: stickHardness */ /* strikePosition */ /* vibFreq */ /* vibAmt */ /*******************************************/ #if !defined(__Vibraphn_h) #define __Vibraphn_h typedef struct Vibraphn { OPDS h; MYFLT *ar; /* Output */ MYFLT *amplitude, *frequency; MYFLT *hardness, *spos, *ifn; MYFLT *vibFreq, *vibAmt, *ivfn, *dettack; Modal4 m4; MYFLT strikePosition; MYFLT stickHardness; int first; int kloop; } VIBRAPHN; #endif csound-6.10.0/Opcodes/vpvoc.c000066400000000000000000000336241321653344700160060ustar00rootroot00000000000000/* vpvoc.c: Copyright (C) 1992 Richard Karpen This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /**************************************************************/ /***********tableseg, tablexseg, voscili, vpvoc************/ /*** By Richard Karpen - July-October 1992************/ /************************************************************/ #include "pvoc.h" #include int tblesegset(CSOUND *csound, TABLESEG *p) { TSEG *segp; int nsegs; MYFLT **argp, dur; FUNC *nxtfunc, *curfunc; int32 flength; if (UNLIKELY(!(p->INCOUNT & 1))) { return csound->InitError(csound, Str("incomplete number of input arguments")); } { PVOC_GLOBALS *p_ = PVOC_GetGlobals(csound); p_->tbladr = p; } nsegs = (p->INCOUNT >> 1); /* count segs & alloc if nec */ if ((segp = (TSEG *) p->auxch.auxp) == NULL || p->auxch.size<(nsegs+1)*sizeof(TSEG)) { csound->AuxAlloc(csound, (size_t)(nsegs+1)*sizeof(TSEG), &p->auxch); p->cursegp = segp = (TSEG *) p->auxch.auxp; (segp+nsegs)->cnt = MAXPOS; } argp = p->argums; if (UNLIKELY((nxtfunc = csound->FTnp2Find(csound, *argp++)) == NULL)) return NOTOK; flength = nxtfunc->flen; p->outfunc = (FUNC*) csound->Calloc(csound, sizeof(FUNC)); p->outfunc->ftable = (MYFLT*)csound->Calloc(csound, (1 + flength) * sizeof(MYFLT)); p->outfunc->flen = nxtfunc->flen; p->outfunc->lenmask = nxtfunc->lenmask; p->outfunc->lobits = nxtfunc->lobits; p->outfunc->lomask = nxtfunc->lomask; p->outfunc->lodiv = nxtfunc->lodiv; //memset(p->outfunc->ftable, 0, sizeof(MYFLT)*(flength+1)); not needed -- calloc if (**argp <= 0.0) return OK; /* if idur1 <= 0, skip init */ p->cursegp = segp; /* else proceed from 1st seg */ segp--; do { segp++; /* init each seg .. */ curfunc = nxtfunc; dur = **argp++; if (UNLIKELY((nxtfunc = csound->FTnp2Find(csound, *argp++)) == NULL)) return OK; if (LIKELY(dur > FL(0.0))) { segp->d = dur * CS_EKR; segp->function = curfunc; segp->nxtfunction = nxtfunc; segp->cnt = (int32) (segp->d + FL(0.5)); } else break; /* .. til 0 dur or done */ } while (--nsegs); segp++; segp->d = FL(0.0); segp->cnt = MAXPOS; /* set last cntr to infin */ segp->function = nxtfunc; segp->nxtfunction = nxtfunc; return OK; } int ktableseg(CSOUND *csound, TABLESEG *p) { TSEG *segp; MYFLT *curtab, *nxttab,curval, nxtval, durovercnt=FL(0.0); int i; int32 flength, upcnt; /* RWD fix */ if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; segp = p->cursegp; curtab = segp->function->ftable; nxttab = segp->nxtfunction->ftable; upcnt = (int32)segp->d-segp->cnt; if (upcnt > 0) durovercnt = segp->d/upcnt; while (--segp->cnt < 0) p->cursegp = ++segp; flength = segp->function->flen; for (i=0; i FL(0.0)) p->outfunc->ftable[i] = (curval + ((nxtval - curval) / durovercnt)); else p->outfunc->ftable[i] = curval; } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("tableseg: not initialised")); } int ktablexseg(CSOUND *csound, TABLESEG *p) { TSEG *segp; MYFLT *curtab, *nxttab,curval, nxtval, cntoverdur=FL(0.0); int i; int32 flength, upcnt; /* RWD fix */ if (UNLIKELY(p->auxch.auxp==NULL)) goto err1; segp = p->cursegp; curtab = segp->function->ftable; nxttab = segp->nxtfunction->ftable; upcnt = (int32)segp->d-segp->cnt; if (upcnt > 0) cntoverdur = upcnt/ segp->d; while(--segp->cnt < 0) p->cursegp = ++segp; flength = segp->function->flen; for (i=0; ioutfunc->ftable[i] = (curval + ((nxtval - curval) * (cntoverdur*cntoverdur))); } return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("tablexseg: not initialised")); } /************************************************************/ /*****************VPVOC**************************************/ /************************************************************/ #define WLN 1 /* time window is WLN*2*ksmps long */ #define OPWLEN (2*WLN*CS_KSMPS) /* manifest used for final time wdw */ int vpvset_(CSOUND *csound, VPVOC *p, int stringname) { unsigned int i; char pvfilnam[MAXNAME]; PVOCEX_MEMFILE pp; int frInc, chans; /* THESE SHOULD BE SAVED IN PVOC STRUCT */ p->pp = PVOC_GetGlobals(csound); /* If optional table given, fake it up -- JPff */ if (*p->isegtab == FL(0.0)) p->tableseg = p->pp->tbladr; else { csound->AuxAlloc(csound, sizeof(TABLESEG), &p->auxtab); p->tableseg = (TABLESEG*) p->auxtab.auxp; if (UNLIKELY((p->tableseg->outfunc = csound->FTnp2Find(csound, p->isegtab)) == NULL)) { return csound->InitError(csound, Str("vpvoc: Could not find ifnmagctrl table %f"), *p->isegtab); } } if (UNLIKELY(p->tableseg == NULL)) return csound->InitError(csound, Str("vpvoc: associated tableseg not found")); if (p->auxch.auxp == NULL) { /* if no buffers yet, alloc now */ MYFLT *fltp; csound->AuxAlloc(csound, (PVDATASIZE + PVFFTSIZE * 3 + PVWINLEN) * sizeof(MYFLT), &p->auxch); fltp = (MYFLT *) p->auxch.auxp; p->lastPhase = fltp; fltp += PVDATASIZE; /* and insert addresses */ p->fftBuf = fltp; fltp += PVFFTSIZE; p->dsBuf = fltp; fltp += PVFFTSIZE; p->outBuf = fltp; fltp += PVFFTSIZE; p->window = fltp; } if (stringname==0){ if (csound->ISSTRCOD(*p->ifilno)) strncpy(pvfilnam,get_arg_string(csound, *p->ifilno), MAXNAME-1); else csound->strarg2name(csound, pvfilnam, p->ifilno, "pvoc.",0); } else strncpy(pvfilnam, ((STRINGDAT *)p->ifilno)->data, MAXNAME-1); if (UNLIKELY(csound->PVOCEX_LoadFile(csound, pvfilnam, &pp) != 0)) return csound->InitError(csound, Str("VPVOC cannot load %s"), pvfilnam); p->frSiz = pp.fftsize; frInc = pp.overlap; chans = pp.chans; p->asr = pp.srate; if (UNLIKELY(p->asr != CS_ESR)) { /* & chk the data */ csound->Warning(csound, Str("%s's srate = %8.0f, orch's srate = %8.0f"), pvfilnam, p->asr, CS_ESR); } if (UNLIKELY(p->frSiz > PVFRAMSIZE)) { return csound->InitError(csound, Str("PVOC frame %ld bigger than %ld in %s"), (long) p->frSiz, (long) PVFRAMSIZE, pvfilnam); } if (UNLIKELY(p->frSiz < 128)) { return csound->InitError(csound, Str("PVOC frame %ld seems too small in %s"), (long) p->frSiz, pvfilnam); } if (UNLIKELY(chans != 1)) { return csound->InitError(csound, Str("%d chans (not 1) in PVOC file %s"), (int) chans, pvfilnam); } /* Check that pv->frSiz is a power of two too ? */ p->frPtr = (float*) pp.data; p->baseFr = 0; /* point to first data frame */ p->maxFr = pp.nframes - 1; /* highest possible frame index */ p->frPktim = (MYFLT) CS_KSMPS / (MYFLT) frInc; /* factor by which to mult expand phase diffs (ratio of samp spacings) */ p->frPrtim = CS_ESR / (MYFLT) frInc; /* factor by which to mulitply 'real' time index to get frame index */ /* amplitude scale for PVOC */ /* p->scale = (MYFLT) pp.fftsize * ((MYFLT) pp.fftsize / (MYFLT) pp.winsize); */ p->scale = (MYFLT) pp.fftsize * FL(0.5); p->scale *= csound->GetInverseRealFFTScale(csound, pp.fftsize); /* 2*incr/OPWLEN scales down for win ovlp, windo'd 1ce (but 2ce?) */ /* 1/frSiz is the required scale down before (i)FFT */ p->prFlg = 1; /* true */ p->opBpos = 0; p->lastPex = FL(1.0); /* needs to know last pitchexp to update phase */ /* Set up time window */ memset(p->lastPhase, 0, sizeof(MYFLT)*pvdasiz(p)); /* for (i = 0; i < pvdasiz(p); ++i) { /\* or maybe pvdasiz(p) *\/ */ /* p->lastPhase[i] = FL(0.0); */ /* } */ if (UNLIKELY((OPWLEN / 2 + 1) > PVWINLEN)) { return csound->InitError(csound, Str("ksmps of %d needs wdw of %d, " "max is %d for pv %s"), CS_KSMPS, (OPWLEN / 2 + 1), PVWINLEN, pvfilnam); } for (i = 0; i < OPWLEN / 2 + 1; ++i) /* time window is OPWLEN long */ p->window[i] = (FL(0.5) - FL(0.5) * COS(TWOPI_F*(MYFLT)i/(MYFLT)OPWLEN)); /* NB: HANNING */ memset(p->outBuf, 0, sizeof(MYFLT)*pvfrsiz(p)); /* for (i = 0; i < pvfrsiz(p); ++i) */ /* p->outBuf[i] = FL(0.0); */ MakeSinc(p->pp); /* sinctab is same for all instances */ if (p->memenv.auxp == NULL || p->memenv.size < pvdasiz(p)*sizeof(MYFLT)) csound->AuxAlloc(csound, pvdasiz(p) * sizeof(MYFLT), &p->memenv); return OK; } int vpvset(CSOUND *csound, VPVOC *p){ return vpvset_(csound,p,0); } int vpvset_S(CSOUND *csound, VPVOC *p){ return vpvset_(csound,p,1); } int vpvoc(CSOUND *csound, VPVOC *p) { MYFLT *ar = p->rslt; MYFLT frIndx; MYFLT *buf = p->fftBuf; MYFLT *buf2 = p->dsBuf; int asize = pvdasiz(p); /* fix */ int size = pvfrsiz(p); int buf2Size, outlen; int circBufSize = PVFFTSIZE; int specwp = (int) *p->ispecwp; /* spectral warping flag */ MYFLT pex, scaleFac = p->scale; TABLESEG *q = p->tableseg; int32 i, j; /* RWD fix */ if (UNLIKELY(p->auxch.auxp == NULL)) goto err1; pex = *p->kfmod; outlen = (int) (((MYFLT) size) / pex); /* use outlen to check window/krate/transpose combinations */ if (UNLIKELY(outlen>PVFFTSIZE)) { /* Maximum transposition down is one octave */ /* ..so we won't run into buf2Size problems */ goto err2; } if (UNLIKELY(outlen<(int)(2*CS_KSMPS))) { /* minimum post-squeeze windowlength */ goto err3; } buf2Size = OPWLEN; /* always window to same length after DS */ if (UNLIKELY((frIndx = *p->ktimpnt * p->frPrtim) < 0)) { goto err4; } if (frIndx > (MYFLT)p->maxFr) { /* not past last one */ frIndx = (MYFLT)p->maxFr; if (UNLIKELY(p->prFlg)) { p->prFlg = 0; /* false */ csound->Warning(csound, Str("PVOC ktimpnt truncated to last frame")); } } FetchIn(p->frPtr, buf, size, frIndx); /**** Apply "spectral envelope" to magnitudes ********/ if (pex > FL(1.0)) scaleFac /= pex; { MYFLT *ftable = q->outfunc->ftable; for (i = 0, j = 0; i <= size; i += 2, j++) buf[i] *= ftable[j] * scaleFac; } /***************************************************/ FrqToPhase(buf, asize, pex * (MYFLT) CS_KSMPS, p->asr, (MYFLT) (0.5 * ((pex / p->lastPex) - 1))); /* accumulate phase and wrap to range -PI to PI */ RewrapPhase(buf, asize, p->lastPhase); if (specwp == 0 || (p->prFlg)++ == -(int)specwp) { /* ?screws up when prFlg used */ /* specwp=0 => normal; specwp = -n => just nth frame */ if (UNLIKELY(specwp < 0)) csound->Warning(csound, Str("PVOC debug: one frame gets through\n")); if (specwp > 0) PreWarpSpec(buf, asize, pex, (MYFLT *)p->memenv.auxp); Polar2Real_PVOC(csound, buf, size); if (pex != FL(1.0)) UDSample(p->pp, buf, (FL(0.5) * ((MYFLT) size - pex * (MYFLT) buf2Size)), buf2, size, buf2Size, pex); else memcpy(buf2, buf + (int) ((size - buf2Size) >> 1), sizeof(MYFLT) * buf2Size); if (specwp >= 0) ApplyHalfWin(buf2, p->window, buf2Size); } else { memset(buf2, 0, sizeof(MYFLT)*buf2Size); /* for (n = 0; n < buf2Size; ++n) */ /* buf2[n] = FL(0.0); */ } addToCircBuf(buf2, p->outBuf, p->opBpos, CS_KSMPS, circBufSize); writeClrFromCircBuf(p->outBuf, ar, p->opBpos, CS_KSMPS, circBufSize); p->opBpos += CS_KSMPS; if (p->opBpos > circBufSize) p->opBpos -= circBufSize; addToCircBuf(buf2 + CS_KSMPS, p->outBuf, p->opBpos, buf2Size - CS_KSMPS, circBufSize); p->lastPex = pex; /* needs to know last pitchexp to update phase */ return OK; err1: return csound->PerfError(csound, p->h.insdshead, Str("vpvoc: not initialised")); err2: return csound->PerfError(csound, p->h.insdshead, Str("PVOC transpose too low")); err3: return csound->PerfError(csound, p->h.insdshead, Str("PVOC transpose too high")); err4: return csound->PerfError(csound, p->h.insdshead, Str("PVOC timpnt < 0")); } csound-6.10.0/Opcodes/vpvoc.h000066400000000000000000000041021321653344700160000ustar00rootroot00000000000000/* vpvoc.h: Copyright (C) 1992 Richard Karpen This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ typedef struct { FUNC *function, *nxtfunction; MYFLT d; int32 cnt; } TSEG; typedef struct { OPDS h; MYFLT *argums[VARGMAX]; TSEG *cursegp; FUNC *outfunc; int32 nsegs; AUXCH auxch; } TABLESEG; typedef struct { OPDS h; MYFLT *rslt, *ktimpnt, *kfmod, *ifilno, *ispecwp, *isegtab; char *strarg; int32 kcnt; int32 baseFr, maxFr, frSiz, prFlg, opBpos; /* base Frame (in frameData0) and maximum frame on file, ptr to fr, size */ MYFLT frPktim, frPrtim, asr, scale, lastPex; float *frPtr; /* asr is analysis sample rate */ /* fft frames per k-time (equals phase change expansion factor) */ AUXCH auxch; /* manage AUXDS for the following 5 buffer spaces */ MYFLT *lastPhase; /* [PVDATASIZE] Keep track of cum. phase */ MYFLT *fftBuf; /* [PVFFTSIZE] FFT works on Real & Imag */ MYFLT *dsBuf; /* [PVFFTSIZE] Output of downsampling may be 2x */ MYFLT *outBuf; /* [PVFFTSIZE] Output buffer over win length */ MYFLT *window; /* [PVWINLEN] Store 1/2 window */ TABLESEG *tableseg; AUXCH auxtab; /* For table is all else fails */ PVOC_GLOBALS *pp; AUXCH memenv; } VPVOC; csound-6.10.0/Opcodes/vst4cs/000077500000000000000000000000001321653344700157235ustar00rootroot00000000000000csound-6.10.0/Opcodes/vst4cs/doc/000077500000000000000000000000001321653344700164705ustar00rootroot00000000000000csound-6.10.0/Opcodes/vst4cs/doc/Compatibilty.doc000066400000000000000000000740001321653344700216200ustar00rootroot00000000000000ࡱ; 9  !"#$%&'()*+,-./012345678:Root Entry  !"#$%&'()*+,-./0123456789:;<=>?@ACDEF  FMicrosoft Word-Dokument MSWordDocWord.Document.89q [ffDefault$a$A$1$ *$/B*OJQJCJmH sH PJnH^JaJ_HtHBA@BAbsatz-StandardschriftartHHWW-Absatz-Standardschriftart.B. Text body x / List^J@"@Caption xx $CJ6^JaJ]&2&Index $^J4B4Table Contents $DARD Table Heading  $$a$ 65]\gX R,,^NT , H 2  d  ^ J  !"#$%&'()*+)8?DJPQ[_c|  *.1?@AMQUnopz}  &'(/25JMNW[_bcdmqu    !"#$%/6;ABCQUX[\]gko  #123=AD\]^knqwxy9:;CFIJKLPSVopqz~#(,OPQg""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""gPGTimes New Roman5Symbol3&ArialOLucida Sans Unicode5Tahoma5TahomaBhiEiE'0Oh+'0 p x 2@3z@)@@n@6snM 0Caolan70,Xg  "l\\\p4 - r  T Current compatibility with CVS version. VST InstrumentWorks?GUI?NotesFree?Absynth 2YesYesMust run csound with -m0NoGanymedYesYesOK.Cheeze MachineYesYesOK.CrystalYesYesMust run csound with -m0RepublicaYesYesOK-dll must be renamedENSIDESAYesYesOK.muniellosNo.NoError on initSuperwaveP8YesYesMust run csound with -m0polyiblitNoNoCan load but crashesborderlinerYesYesOKjx220YesYesOKmellowsoundYesYesOKclawNoNoCan load but crashessynth1YesYesMust run csound with -m0DR-008NoNoCan load but crashesNoRainbow2YesYesOKmysteronYesYesOK-Sound is OK but GUI is not updatedGalactiXYesYesOKCrazy DiamondsYesYesOKEnigmatronYes*YesOK-but audio breaks up with polyphonyOddityYesYesOKVSTPluginWorks?GUI?Notesambience-2003YesNoOKCyanide 2YesYesMust run csound with -m0supaphaserYesYesMust run csound with -m0northpoleYesYesOKSIRYesCutThe window shows an incomplete GUIfreeverb2YesNoOKbouncyNoNoError on initMda plugsYesNoSome tested and workingDfx geometerNoNoErrorvreorderYesYesOKmadshiftaYesYesOKFFTYes*YesLoads and opens but there's no displayC_FFTYes*YesOK-but audio stuttersC_SuperstereoYesYesOK-Cool phase meter for Csound!C_TunerNoNoWTFNoNoJust hangs without crashZ-CutterYesYesAll other Z- plugins are working.RANON VocoderYesYesOK-dll must be renamedSplonkiYes*YesOpens, but I can't figure out how to use it.DeconstructorYes*YesAppears to work, but I'm not sure. Last checked 20/7/04 H ^ l v  65]\Rp~$s$$4r* !%47474747 2$  (*,JRVR$$4r* !%47474747$R$$4r* !%47474747 RZbdfv~R$$4r* !%47474747$ $,VR$$4r* !%47474747$R$$4r* !%47474747 ,4<>@T\b~R$$4r* !%47474747$ $s$$4r* !%47474747 2*,$R$$4r* !%47474747,.FNV\^$s$$4r* !%47474747 2^`lt|VR$$4r* !%47474747$R$$4r* !%47474747 R$$4r* !%47474747$  LN$s$$4r* !%47474747 2NP^dj$R$$4r* !%47474747$s$$4r* !%47474747 26 8 : L T VR$$4r* !%47474747$R$$4r* !%47474747 T \ b d f R$$4r* !%47474747$    $ , VR$$4r* !%47474747$R$$4r* !%47474747 , 4 : < > @ B D F H R$$4r* !%47474747$ H J ^ l v $R$$4r* !%47474747 $s$$4r* !%47474747 hhhhh25^5^5^5^5^    * 2 VR$$4r* !%47474747$R$$4r* !%47474747 2 : l n p R$$4r* !%47474747$   VR$$4r* !%47474747$R$$4r* !%47474747  " ( * , : @ F b d R$$4r* !%47474747$ d f z $s$$4r* !%47474747 2 $R$$4r* !%47474747     $s$$4r* !%47474747 2  2 : B H J L T ^ VR$$4r* !%47474747$R$$4r* !%47474747 ^ f R$$4r* !%47474747$ "*2rtvVR$$4r* !%47474747$R$$4r* !%47474747 s$$4r* !%47474747 2$ HJ$s$$4r* !%47474747 2JLhpxVR$$4r* !%47474747$R$$4r* !%47474747 &(*FPXR$$4r* !%47474747$ R$$4r* !%47474747*. A!n"n#n$n2P1h3P(20Root Entry FCompObjjOle 1TableSummaryInformation(B8WordDocument ,Xcsound-6.10.0/Opcodes/vst4cs/doc/compatibilty.html000066400000000000000000000603271321653344700220660ustar00rootroot00000000000000

VST4CS Current compatibility:

VST Instrument

Works?

GUI?

Notes

Free?

Absynth 2

Yes

Yes

Must run csound with -m0

No

Ganymed

Yes

Yes

OK.


Cheeze Machine

Yes

Yes

OK.


Crystal

Yes

Yes

Must run csound with -m0


Republica

Yes

Yes

OK-dll must be renamed


ENSIDESA

Yes

Yes

OK.


muniellos

No.

No

Error on init


SuperwaveP8

Yes

Yes

Must run csound with -m0


polyiblit

Yes

Yes

OK. Needs a vstprogset before any notes.


borderliner

Yes

Yes

OK


jx220

Yes

Yes

OK


mellowsound

Yes

Yes

OK


claw

Yes

Yes

OK. Needs a vstprogset before any notes.


synth1

Yes

Yes

Must run csound with -m0


DR-008

No

No

Can load but crashes

No

Rainbow2

Yes

Yes

OK


mysteron

Yes

Yes

OK-Sound is OK but GUI is not updated


GalactiX

Yes

Yes

OK


Crazy Diamonds

Yes

Yes

OK


Enigmatron

Yes*

Yes

OK-but audio breaks up with polyphony


Oddity

Yes

Yes

OK







VSTPlugin

Works?

GUI?

Notes


ambience-2003

Yes

No

OK


Cyanide 2

Yes

Yes

Must run csound with -m0


supaphaser

Yes

Yes

Must run csound with -m0


northpole

Yes

Yes

OK


SIR

Yes

Cut

The window shows an incomplete GUI


freeverb2

Yes

No

OK


bouncy

No

No

Error on init


Mda plugs

Yes

No

Some tested and working


Dfx geometer

No

No

Error


vreorder

Yes

Yes

OK


madshifta

Yes

Yes

OK


FFT

Yes*

Yes

Loads and opens but there's no display


C_FFT

Yes*

Yes

OK-but audio stutters


C_Superstereo

Yes

Yes

OK-Cool phase meter for Csound!


C_Tuner

No

No



WTF

No

No

Just hangs without crash


Z-Cutter

Yes

Yes

All other Z- plugins are working.


RANON Vocoder

Yes

Yes

OK-dll must be renamed


Splonki

Yes*

Yes

Opens, but I cannot figure out how to use it.


Deconstructor

Yes*

Yes

Appears to work, but I'm not sure.



Last checked 20/7/04

csound-6.10.0/Opcodes/vst4cs/doc/index.html000066400000000000000000000072621321653344700204740ustar00rootroot00000000000000 vst4cs


vst4cs -- VST for Csound


vst4cs enables the use of VST plugin effects and synthesizers within Csound. The following opcodes are available:

vstinit -- Loads a plugin
vstaudio, vstaudiog -- Returns a plugin's output
vstmidiout -- Sends MIDI data to a plugin
vstparamset, vstparamget -- Send automation data to and from the plugin
vstnote -- Sends a MIDI note with definite duration
vstinfo -- Outputs the Parameter and Program names for a plugin
vstbankload-- Loads an .fxb Bank
vstprogset-- Sets a Program in an .fxb Bank.
vstedit -- Opens the GUI editor for the plugin, when available.

The followin freeware or shareware plugins have been partially tested with vst4cs:

VST Instruments

Synth1 -- http://www.geocities.co.jp/SiliconValley-SanJose/5005/softsynth/index.html
Crazy Diamonds -- http://www.kvr-vst.com/get/193.html
Cheeze Machine (and others -- http://bigtick.pastnotecut.org/index.php
Crystal -- http://www.greenoak.com/crystal/
Republica, Ensidesa -- http://www.trubialabs.tk/  (You need to copy and rename the republica dll to get rid of the weird character)
Superwave P8 -- http://home.btconnect.com/christopherg/main.htm
Ganymed -- http://www.stefan-kuhn.net/
Borderliner -- http://www.tobybear.de/
Polyiblit -- http://www.bostreammail.net/ers/polyiblit.html

VST Effects

Ambience VST -- http://www.sharewaremusicmachine.com/smm/programs/AmbienceWin/
Cyanide2, Bouncy -- http://bram.smartelectronix.com/
Freeverb -- http://www.sonicspot.com/freeverb/freeverb.html
North Pole -- http://www.prosoniq.com/

Current plugin compatibility list

Note: Be careful if paths, plugin or bank names contain strange characters. Try renaming if having problems.

By: Andrs Cabrera and Michael Gogins
Uses code from Hermann Seib's VSTHost and Thomas Grill's vst~ object.
VST is a trademark of Steinberg Media Technologies GmbH
VST Plug-In Technology by Steinberg.

csound-6.10.0/Opcodes/vst4cs/doc/vstaudio.html000066400000000000000000000107131321653344700212160ustar00rootroot00000000000000 vst4cs

Warning: Specifications are still subject to change!





vstaudio, vstaudiog

vst4cs -- VST plugin hosting in Csound on Windows.

Description

vstaudio and vstaudiog are used for sending and receiving audio from a VST plugin.

vstaudio is used within an instrument definition that contains a vstmidiout or vstnote opcode. It outputs audio for only that one instrument. Any audio remaining in the plugin after the end of the note, for example a reverb tail, will be cut off and should be dealt with using a damping envelope.

vstaudiog (vstaudio global) is used in a separate instrument to process audio from any number of VST notes or MIDI events that share the same VST plugin instance (instance). The vstaudiog instrument must be numbered higher than all the instruments receiving notes or MIDI data, and the note controlling the vstplugg instrument must have an indefinite duration, or at least a duration as long as the VST plugin is active.

Syntax

aout1,aout2 vstaudio instance, ain1, ain2

aout1,aout2 vstaudiog instance, ain1, ain2

Initialization

instance -- the number which identifies the plugin, returned previously by the vstinit opcode.

Performance

aout1, aout2 -- the audio output given by the plugin.

ain1, ain2 -- the audio sent to the plug in for processing. For vst instruments, input is usually ignored.

Examples

See vstmidiout or vstparamset for examples.


Credits

Authors:

Cabrera, Andres

Bogota, Colombia

2004

Gogins, Michael

New York, USA

2004











csound-6.10.0/Opcodes/vst4cs/doc/vstbankload.html000066400000000000000000000063371321653344700216770ustar00rootroot00000000000000 vst4cs

Warning: Specifications are still subject to change!





vstbankload

vst4cs -- VST plugin hosting in Csound on Windows.

Description

vstbankload is used for loading parameter banks to a VST plugin.

Syntax

vstbankload instance, ipath

Initialization

instance -- the number which identifies the plugin, returned previously by the vstinit opcode.

ipath -- the full pathname of the parameter bank (.fxb file).

Performance

Examples

/* orc */
sr = 44100
kr = 4410
ksmps = 10
nchnls = 2
giHandle1 vstinit "c:/vstplugins/cheeze/cheeze machine.dll",1
instr 4
vstbankload gihandle1,"c:/vstplugins/cheeze/chengo'scheese.fxb"
vstinfo gihandle1
endin
/* sco */
i 3 0 21
i4 1 1 57 32
e

Credits

Authors:

Cabrera, Andres

Bogota, Colombia

2004

Gogins, Michael

New York, USA

2004











csound-6.10.0/Opcodes/vst4cs/doc/vstedit.html000066400000000000000000000054371321653344700210510ustar00rootroot00000000000000 vst4cs

Warning: Specifications are still subject to change!





vstedit

vst4cs -- VST plugin hosting in Csound on Windows.

Description

vstedit opens the GUI editor widow for a VST plugin.

Syntax

vstedit instance

Initialization

instance -- the number which identifies the plugin, returned previously by the vstinit opcode.

Performance

Credits

Authors:

Cabrera, Andres

Bogota, Colombia

2004

Gogins, Michael

New York, USA

2004











csound-6.10.0/Opcodes/vst4cs/doc/vstinfo.html000066400000000000000000000065061321653344700210550ustar00rootroot00000000000000 vst4cs

Warning: Specifications are still subject to change!





vstinfo

vst4cs -- VST plugin hosting in Csound on Windows.

Description

vstinfo displays the parameters and the programs of a VST plugin.

Syntax

vstinfo instance

Initialization

instance -- the number which identifies the plugin, returned previously by the vstinit opcode.

The verbose flag in vstinit gives the same information as vstinfo. vstinfo is useful after loading parameter banks, or when plugin changes paramters dynamically.

Performance

Examples

/* orc */
sr = 44100
kr = 4410
ksmps = 10
nchnls = 2
giHandle1 vstinit "c:/vstplugins/cheeze/cheeze machine.dll",1
instr 4
vstbankload gihandle1,"c:/vstplugins/cheeze/chengo'scheese.fxb"
vstinfo gihandle1
endin
/* sco */
i 3 0 21
i4 1 1 57 32
e

Credits

Authors:

Cabrera, Andres

Bogota, Colombia

2004

Gogins, Michael

New York, USA

2004











csound-6.10.0/Opcodes/vst4cs/doc/vstinit.html000066400000000000000000000070051321653344700210600ustar00rootroot00000000000000 vst4cs

Warning: Specifications are still subject to change!





vstinit

vst4cs -- VST plugin hosting in Csound on Windows.

Description

vstinit is used to load a VST plugin into memory for use with the other vst4cs opcodes. Both VST effects and instruments (synthesizers) can be used.

Syntax

instance vstinit ilibrarypath [,iverbose]

Initialization

instance -- the number which identifies the plugin, to be passed to other vst4cs opcodes.

ilibrarypath -- the full path to the vst plugin shared library (dll, on Windows). Remember to use '/' instead of '\' as separator.

iverbose -- show plugin information and parameters when loading.

Examples

Example 1. loading a vst plugin

/* orc */
sr = 44100
kr = 4410
ksmps = 10
nchnls = 2
giHandle1 vstinit "c:/vstplugins/cheeze/cheeze machine.dll",1
instr 1
      giHandle2 vstinit "c:/vstplugins/crazy diamonds.dll",1
endin
/* sco */
i 1 0 1
e
/* babo.sco */

Credits

Authors:

Cabrera, Andres

Bogota, Colombia

2004

Gogins, Michael

New York, USA

2004











csound-6.10.0/Opcodes/vst4cs/doc/vstmidiout.html000066400000000000000000000074061321653344700215740ustar00rootroot00000000000000 vst4cs

Warning: Specifications are still subject to change!





vstmidiout

vst4cs -- VST plugin hosting in Csound on Windows.

Description

vstmidiout is used for sending MIDI information to a vst plugin..

Syntax

vstmidiout instance, kstatus, kchan, kdata1, kdata2

Initialization

instance -- the number which identifies the plugin, returned previously by the vstinit opcode.

Performance

kstatus -- the type of midi message to be sent. Currently noteon (144), note off (128), Control Change (176),  Program change (192), Aftertouch (208) and Pitch Bend (224) are supported.

kchan -- the MIDI channel transmitted on.

kdata1, kdata2 -- the MIDI data pair, which varies depending on kstatus. e.g. note/velocity for note on and note off, Controller number/value for control change.

Examples

/* orc */
sr = 44100
kr = 4410
ksmps = 10
nchnls = 2
giHandle1 vstinit "c:/vstplugins/cheeze/cheeze machine.dll",1
instr 3
ain1 = 0
ab1, ab2 vstaudio gihandle1, ain1, ain1
outs ab1, ab2
endin
instr 4
vstmidiout gihandle1,144,1,p4,p5
endin
/* sco */
i 3 0 21
i4 1 1 57 32
i4 3 1 60 100
i4 5 1 62 100
i4 7 1 64 100
i4 9 1 65 100
i4 11 1 67 100
i4 13 1 69 100
i4 15 3 71 100
i4 18 3 72 100
e

Credits

Authors:

Cabrera, Andres

Bogota, Colombia

2004

Gogins, Michael

New York, USA

2004










csound-6.10.0/Opcodes/vst4cs/doc/vstnote.html000066400000000000000000000066411321653344700210670ustar00rootroot00000000000000 vst4cs

Warning: Specifications are still subject to change!





vstnote

vst4cs -- VST plugin hosting in Csound on Windows.

Description

vstnote sends a MIDI note with definite duration to a VST plugin.

Syntax

vstnote instance, kchan, knote, kveloc, kdur

Initialization

instance -- the number which identifies the plugin, returned previously by the vstinit opcode.

Performance

kchan -- The midi channel to trasnmit the note on.

knote -- The midi note number to send.

kveloc -- The midi note's velocity.

kdur -- The midi note's duration in seconds.



Note: Be sure the instrument containing vstnote is not finished before the duration of the note, otherwise you'll have a 'hung' note.

Examples

/* orc */
sr = 44100
kr = 4410
ksmps = 10
nchnls = 2
giHandle5 vstinit "c:/vstplugins/cheeze/cheeze machine.dll",1
instr 3
ain1 = 0
ga1, ga2 vstplugg gihandle5, ain1, ain1
endin
instr 4
vstnote giHandle5, 1, p4, p5, p3
endin
instr 10
outs ga1, ga2
endin
/* sco */
i 3 0 21
i 10 0 21
i4 1 3 57 55
i4 3 3 60 100
i4 5 3 62 100
i4 7 3 64 100
i4 9 2 65 100
i4 11 1 67 100
i4 13 1 69 100
i4 15 3 71 100
i4 18 3 72 100

Credits

Author: Cabrera,Andres; Goggins, Michael

Bogota, Colombia

2004











csound-6.10.0/Opcodes/vst4cs/doc/vstparamset.html000066400000000000000000000073551321653344700217410ustar00rootroot00000000000000 vst4cs

Warning: Specifications are still subject to change!





vstparamset, vstparamget

vst4cs -- VST plugin hosting in Csound on Windows.

Description

vstparamset and vstparamget are used for parameter comunication to and from a VST plugin.

Syntax

vstparamset instance, kparam, kvalue
kvalue vstparamget instance, kparam


Initialization

instance -- the number which identifies the plugin, returned previously by the vstinit opcode.

Performance

kparam -- The number of the parameter to set or get.

kvalue -- the value to set, or the the value returned by the plugin.

Parameters vary according to the plugin. To find out what parameters are available, use the verbose option when loading the plugin with vstinit.

Examples

/* orc */
sr = 44100
kr = 4410
ksmps = 10
nchnls = 2
giHandle1 vstinit "c:/vstplugins/cheeze/cheeze machine.dll",1
instr 3
ain1 = 0
ab1, ab2 vstaudio gihandle1, ain1, ain1
outs ab1, ab2
endin
instr 4
vstmidiout gihandle1,144,1,p4,p5
kline line 0,p3,1
vstparamset gihandle1, 3, kline
endin
/* sco */
i 3 0 21
i4 1 1 57 32
i4 3 1 60 100
i4 5 1 62 100
i4 7 1 64 100
i4 9 1 65 100
i4 11 1 67 100
i4 13 1 69 100
i4 15 3 71 100
i4 18 3 72 100
e

Credits

Authors:

Cabrera, Andres

Bogota, Colombia

2004

Gogins, Michael

New York, USA

2004










csound-6.10.0/Opcodes/vst4cs/doc/vstprogset.html000066400000000000000000000066011321653344700216010ustar00rootroot00000000000000 vst4cs

Warning: Specifications are still subject to change!





vstprogset

vst4cs -- VST plugin hosting in Csound on Windows.

Description

vstprogset sets one of the programs in an .fxb bank.

Syntax

vstprogset instance, kprogram

Initialization

instance -- the number which identifies the plugin, returned previously by the vstinit opcode.

Performance

kprogram -- The number of the program to set

Programs vary according to the plugin and bank. To find out what programs are available, use the verbose option when loading the plugin with vstinit.

Examples

Examples

/* orc */
sr = 44100
kr = 4410
ksmps = 10
nchnls = 2
giHandle1 vstinit "c:/vstplugins/cheeze/cheeze machine.dll",1
instr 4
vstbankload gihandle1,"c:/vstplugins/cheeze/chengo'scheese.fxb"
vstprogset gihandle1, 4
vstinfo gihandle1
endin
/* sco */
i 3 0 21
i4 1 1 57 32
e

Credits

Authors:

Cabrera, Andres

Bogota, Colombia

2004

Gogins, Michael

New York, USA

2004










csound-6.10.0/Opcodes/vst4cs/licensing_considerations_for_csoundvst_and_vst4cs.md000066400000000000000000000623341321653344700304420ustar00rootroot00000000000000#LICENSING AND HOSTING CSOUNDVST AND VST4CS# Michael Gogins 22 September 2017 This is complicated and tedious, so please read carefully and pay attention. I have read all the licenses and agreements from Steinberg, AppVeyor, and GitHub as well as the LGPL v2.1, several times. Please note, I am not a lawyer; so if you think you need legal advice, get it from a lawyer. I welcome comments and corrections. ##SUMMARY## If you're going to go to sleep, here's the tl;dr: -- Hosting source code for CsoundVST and the vst4cs opcodes on GitHub does not violate Steinberg's VST SDK 2.4 license, which is the only one we need to comply with, because we don't host the VST SDK code. -- Hosting source code for CsoundVST and the vst4cs opcodes on GitHub does not violate Csound's GPL v2.1 license. -- Hosting binaries for Csound, CsoundVST, and the vst4cs opcodes on AppVeyor does not violate Steinberg's VST SDK 2.4 license, which is the only one we need to comply with, again because we don't redistribute the VST SDK code. - The question whether hosting binaries for CsoundVST and the vst4cs opcodes violates Csound's LGPL v2.1 license is more complex. However, it is permitted by clause 6 of the LGPL v2.1 and as indicated by https://www.gnu.org/licenses/gpl-faq.en.html#GPLIncompatibleLibs. ###Required Modification### We should however modify the wording of our LGPL v2.1 license for CsoundVST and vst4cs to include an exception for using the VST2 SDK. It would also be possible to use the VST3 SDK's GPL v3 license, but that would require porting both CsoundVST and the vst4cs opcodes to use VST SDK3 instead of the current VST2 SDK. In that case, it is clear that the Csound library could load the vst4cs opcodes, but it is not as clear that non-GPL hosts could load CsoundVST, although this situation is common in the wild. Assuming that we continue to use the LGPL v2.1 license, the licenses for all Csound source code in the `frontends/CsoundVST` and `Opcodes/vst4cs` directories should be changed to read (text is worded for vst4cs): ``` // The vst4cs library is free software; you can redistribute it // and/or modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // The vst4cs library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with The vst4cs library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA // 02111-1307 USA // // Linking vst4cs statically or dynamically with other modules is making a // combined work based on vst4cs. Thus, the terms and conditions of the GNU // Lesser General Public License cover the whole combination. // // In addition, as a special exception, the copyright holders of vst4cs give // you permission to combine vst4cs with free software programs or libraries // that are released under the GNU LGPL and with code included in the // standard release of the VST SDK version 2 under the terms of the license // stated in the VST SDK version 2 files. You may copy and distribute such a // system following the terms of the GNU LGPL for vst4cs and the licenses of // the other code concerned. The source code for the VST SDK version 2 is // available in the VST SDK hosted at https://github.com/steinbergmedia/vst3sdk. // // Note that people who make modified versions of vst4cs are not obligated to // grant this special exception for their modified versions; it is their // choice whether to do so. The GNU Lesser General Public License gives // permission to release a modified version without this exception; this // exception also makes it possible to release a modified version which // carries forward this exception. ``` ##DETAILED EXPLANATION## OK, here are the grisly details. The licenses and agreements that we need to comply with are: 1. GitHub's terms of use. 2. AppVeyor's terms of use. 3. The license used by the Steinberg VST2 SDK (not the VST3 SDK, I will explain this). 4. Csound's LGPL v2.1 license, which specifically includes the clause "or (at your option) any later version." I will now explain these in more detail. Regarding AppVeyor, its terms of service require only that we truthfully convey to AppVeyor the copyrights and licenses to all code built on AppVeyor. This automatically happens when AppVeyor clones Csound's Git repository. So, we do this. Regarding GitHub, its terms of service similarly make no requirements as to licensing of hosted code, but recommends that hosted projects use an open source license. We do that. Csound does not use the GPLv3 license, but rather the LGPL v2.1 license. GPL is "free software," LGPL is "open source." The GPL license is compatible with the LGPL v2.1 license if and and only if the LGPL license includes the wording "or (at your option) any later version." Our license does include this wording. So Csound itself is compatible with the GPL v3 -- if we convey the Csound code under GPL v3. The LGPL allows LGPL or proprietary software to use the Csound library. The situation might be different if CsoundVST and the vst4cs opcodes were GPL. The language for dynamic linking in the GPL is imprecise and contested. Both CsoundVST and vst4cs are not shared libraries that are linked at compile time, they are dynamically loaded and linked at run time. Opinions differ on whether this is permitted. If not, then CsoundVST under GPL 3 could not be loaded by GPL-incompatible hosts. NOTE: We have to worry not only about Csound -- but also about a lot of third party dependencies such as libsndfile! Steinberg's license for the VST SDK is different for different files in the SDK. The VST SDK distribution comes in two directories: VST2_SDK and VST3_SDK. EACH OF THESE HAS ITS OWN LICENSE! Specifically, the VST2_SDK files are licensed thus: //----------------------------------------------------------------------------- // LICENSE // (c) 2017, Steinberg Media Technologies GmbH, All Rights Reserved //----------------------------------------------------------------------------- // This Software Development Kit may not be distributed in parts or its entirety // without prior written agreement by Steinberg Media Technologies GmbH. // This SDK must not be used to re-engineer or manipulate any technology used // in any Steinberg or Third-party application or software module, // unless permitted by law. // Neither the name of the Steinberg Media Technologies nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // // THIS SDK IS PROVIDED BY STEINBERG MEDIA TECHNOLOGIES GMBH "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. // IN NO EVENT SHALL STEINBERG MEDIA TECHNOLOGIES GMBH 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. //---------------------------------------------------------------------------------- The VST3_SDK files are licensed thus: //----------------------------------------------------------------------------- // LICENSE // (c) 2017, Steinberg Media Technologies GmbH, All Rights Reserved //----------------------------------------------------------------------------- This license applies only to files referencing this license, for other files of the Software Development Kit the respective embedded license text is applicable. The license can be found at: www.steinberg.net/sdklicenses_vst3 This Software Development Kit is licensed under the terms of the Steinberg VST3 License, or alternatively under the terms of the General Public License (GPL) Version 3. You may use the Software Development Kit according to either of these licenses as it is most appropriate for your project on a case-by-case basis (commercial or not). a) Proprietary Steinberg VST3 License The Software Development Kit may not be distributed in parts or its entirety without prior written agreement by Steinberg Media Technologies GmbH. The SDK must not be used to re-engineer or manipulate any technology used in any Steinberg or Third-party application or software module, unless permitted by law. Neither the name of the Steinberg Media Technologies GmbH nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. Before publishing a software under the proprietary license, you need to obtain a copy of the License Agreement signed by Steinberg Media Technologies GmbH. The Steinberg VST SDK License Agreement can be found at: www.steinberg.net/en/company/developers.html THE SDK IS PROVIDED BY STEINBERG MEDIA TECHNOLOGIES GMBH "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL STEINBERG MEDIA TECHNOLOGIES GMBH 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. b) General Public License (GPL) Version 3 Details of these licenses can be found at: www.gnu.org/licenses/gpl-3.0.html //---------------------------------------------------------------------------------- Csound's VST features do not use any files in VST3_SDK, but only files in VST2_SDK. I did not sign the agreement for VST SDK 3, because I do not use it. I do adhere to the terms of the VST SDK 2.4, which I registered for and downloaded from Steinberg a long time ago. Please note, we COULD license CsoundVST and the vst4cs opcodes as GPL v3 because of the "any later version" clause of our LPGL v2.1 license, thus complying with the VST3 SDK GPL v3 license, but that would require porting both CsoundVST and the vst4cs opcodes to use the VST3 SDK. So the main question is whether Csound's LGPL v2.1 license permits us to host and distribute the existing CsoundVST and vst4cs binaries. The issue is complex, and the law does not appear to be completely settled. As background, be aware that CsoundVST is a "derivative work" of both the csnd6 library and the VST2 SDK, because it incorporates source code from both. CsoundVST is NOT a derivative work of the csound64 library, because it does not incorporate source code from it, but only uses the csound64 library by dynamic linking. Opinions differ as to dynamic linking, but a strong argument can be made that a program that uses a LGPL v2.1 library by dynamic linking is not a derivative work. Case law leans in that direction, but has so far not squarely focused on this issue. The vst4cs opcodes are NOT a derivative work of any part of Csound, but ARE a derivative work of the VST2 SDK. The vst4cs source code, however, like Csound, is LGPL v2.1. The question then is whether the LGPL v2.1 permits us to host the binaries for CsoundVST and the vst4cs opcodes on AppVeyor and/or GitHub. At first sight, the fact that CsoundVST is a derivative work of the csnd6 library but incorporates proprietary code, and the fact that the vst4cs opcodes are themselves LGPL v2.1 but incorporate proprietary code, would seem to mean "no." However, NOT SO FAST, the LGPL v2.1 license includes a clause to deal with this kind of situation. My comments are enclosed in ***. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. *** THIS IS THE KEY. We do this. *** You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. *** This is true of Csound, CsoundVST, and vst4cs. *** c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. *** We do this for everything but the VST2 SDK; and we also instruct users how to copy the VST2 SDK from Steinberg. There are a number of other VST plugins on GitHub, with both open source licenses and free software licenses, that do just this, including the widely used JUCE audio application framework, which is GPL v3. *** e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. *** We are not in this kind of contradiction, because we DO comply with the VST2 SDK license. *** The AppVeyor.yml file is set up to download the VST SDK 3. I believe that we may download the VST SDK 3, not use any of the SDK 3 specific files, use only the SDK 2.4 files, and thus be bound only by the terms of the SDK 2.4 license. So I think we are OK to build VST features for Csound on AppVeyor using only the VST SDK 2.4 files, and distribute the resulting binaries, without violating Steinberg's license. I don't think Steinberg is being very clear about this situation, because they want everyone to ask permission and thus explicitly give up liability claims against Steinberg. I would be fine with doing that, I just don't think it's necessary. As far as Csound's LGPL v2.1 license is concerned, I believe we are OK under clause 6 of the license, but we could also license CsoundVST and the vst4cs opcodes under GPL v3 and then port them to use VST SDK3. ##OTHER PROJECTS## To gain more understanding of the licensing issues, I have looked over a variety of other free software and open source projects for VST plugins and hosts. Hermann Seib's VSTHOST http://www.hermannseib.com/english/vsthost.htm is LGPL v2.1 with the "later version" option and thus is completely compatible with Csound. That's good, because vst4cs is based on vsthost. It is ditributed both as source (without the VST2 SDK) and as a compiled program from Seib's Web site. However, according to the GPL, we need to get permission from Seib to modify our license as I have proposed. Update: Seib just gave his permission; I have appended his email below. The Pure Data extension `vst~`, which serves the same purpose as vst4cs, hosted at https://sourceforge.net/p/pure-data/svn/HEAD/tree/trunk/, simply incorporates minimal VST2 SDK files attributed to Steinberg, but without license or explanation. Pure Data itself uses the BSD license which is less restrictive than LGPL v2.1. Psycle at https://sourceforge.net/projects/psycle/ is GPL v2 but uses a later version of Seib's VSTHost that is GPL v2.1. Some of the `vst~` external is based on code from http://iem.kug.ac.at/~jams/, but currently this page is inaccessible. Qtractor at https://sourceforge.net/projects/qtractor/ contains the VeSTige aeffect.h header which appears to reverse engineer the VST2 SDK. However, the Qtractor README says it uses Steinberg's VST2 SDK. The JUCE framework, which contains features similar to both CsoundVST and vst4cs, appears to use the Steinberg VST3 SDK which appears to be consistent with the JUCE license, especially if GPL v3. The LMMS sequencer is GPL v2. It appears to contain the VeSTige emulation of the VST2 SDK which is GPL v2. Paul Nasca's http://zynaddsubfx.sourceforge.net/ now provides VST support via something called DPF, which I think stands for Distrho Plugin Framework or something like that. The DPF directory in the ZynAddSubFX repository is empty. The DPF uses VeSTige from Ardour. The DPF uses the ISC license, which is very permissive open source. But it can also use the VST2 SDK. Ardour at https://github.com/Ardour/ardour uses the GPL v2. Ardour also uses VeSTige from LMMS which is GPL v2. WDL-OL at https://github.com/olilarkin/wdl-ol is an audio plugin development framework that uses, among other libraries, the VST SDK. WDL-OS uses the Cockos WDL License which is a very permissive open source license. The programmer must download the VST SDK from Steinberg and also copy the most basic VST2 SDK files. NOTE: It might make sense to use this for Csound and gain interoperability with a number of plugin formats. Dexed at https://github.com/asb2m10/dexed uses the JUCE plugin wrapper and also is GPL v3. vst2413 at https://github.com/keijiro/vst2413 has no license information. It appears to use the VST2 SDK. By the way, it sounds great. Releases include binaries. rust-vst2 at https://github.com/overdrivenpotato/rust-vst2 is a "VST 2.4 API implementation in rust. Create plugins or hosts." Uses the MIT license. The implication is that overdrivepotato has either ported or reverse engineered the VST2 SDK. amsynth at https://github.com/amsynth/amsynth. It uses GPL v2 and also uses VeSTige. VOSIMSynth at https://github.com/austensatterlee/VOSIMSynth uses GPL v3. The programmer must download the VST SDK from Steinberg and copy some VST2 SDK files. ###TRENDS### VeSTige is getting a lot of use, but is GPL v2. JUCE is getting even more use, but makes projects GPL v3. There are a number of projects that require the programmer to download and install VST2 SDK sources before compiling, as I propose. ##APPENDIX## Here is the full text of my email to, and response from, Hermann Seib: 9:58 AM (24 minutes ago) to me Legal considerations always give me a headache. Originally, my open-source VSTHost code contained no license at all - a "do what the fuck you want with it" license, so to speak. Which was taken advantage of, so I added a license; the sole intention of that was to add an explicit "... but don't pretend it's your code and make others pay for it!". So ... your license below looks good to me. I had no problem when Psycle included parts of VSTHost, I don't have a problem with CSound including parts of it. As long as it's understood that this license doesn't cover my own VSTHost code, i.e., it only covers your version and everything that's derived from it, you have my expressed permission. I hope you don't need that in hand-written form, signed with blood :-) Bye, Hermann Am 23.09.2017 um 03:59 schrieb Michael Gogins: I am a developer and maintainer of Csound, a widely used programmable software synthesizer, see http://csound.github.io/ and https://github.com/csound/csound. I am writing this to ask your permission to add an exception to our licensing tems for code that we have borrowed from your VSTHost code. Currently, Csound contains vst4cs, a set of opcodes for csound, that enable Csound to host VST instruments and effects. The sources for vst4cs, in https://github.com/csound/csound/tree/develop/Opcodes/vst4cs, are based in part on your VSTHost sources. The Csound license is LGPL v2.1 with the "either version 2.1 of the License, or (at your option) any later version" clause. I am currently the maintainer of vst4cs. By the way, thank you for creating this excellent project, which we use not only as the basis for vst4cs, but also for testing the VST plugin version of Csound, CsoundVST. Of course, we do not redistribute the VST2 SDK. To build vst4cs requires the developer also to download the VST2 SDK from Steinberg. The licensing situation then becomes a little tricky. According to the GPL, we are permitted to modify the LGPL v2.1 text to permit other users of vst2cs to also use the VST2 SDK and still keep the LGPL v2.1 license. However, we need the permission of the "original author" in order to make this change. Our license notice would then read: // vst4cs: VST HOST OPCODES FOR CSOUND // // Uses code by Hermann Seib from his Vst Host program // and from the vst~ object by Thomas Grill, // which in turn borrows from the Psycle tracker. // VST is a trademark of Steinberg Media Technologies GmbH. // VST Plug-In Technology by Steinberg. // // Copyright (C) 2004 Andres Cabrera, Michael Gogins // // The vst4cs library is free software; you can redistribute it // and/or modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // The vst4cs library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with The vst4cs library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA // 02111-1307 USA // // Linking vst4cs statically or dynamically with other modules is making a // combined work based on vst4cs. Thus, the terms and conditions of the GNU // Lesser General Public License cover the whole combination. // // In addition, as a special exception, the copyright holders of vst4cs, // including the Csound developers and Hermann Seib, the original author of // VSTHost, give you permission to combine vst4cs with free software programs // or libraries that are released under the GNU LGPL and with code included // in the standard release of the VST SDK version 2 under the terms of the // license stated in the VST SDK version 2 files. You may copy and distribute // such a system following the terms of the GNU LGPL for vst4cs and the // licenses of the other code concerned. The source code for the VST SDK // version 2 is available in the VST SDK hosted at // https://github.com/steinbergmedia/vst3sdk. // // Note that people who make modified versions of vst4cs are not obligated to // grant this special exception for their modified versions; it is their // choice whether to do so. The GNU Lesser General Public License gives // permission to release a modified version without this exception; this // exception also makes it possible to release a modified version which // carries forward this exception. May we have your permission to make this our license for our code which is based on your code? Thank you for your consideration, Michael Gogins ----------------------------------------------------- Michael Gogins Irreducible Productions http://michaelgogins.tumblr.com Michael dot Gogins at gmail dot com csound-6.10.0/Opcodes/vst4cs/readme.txt000066400000000000000000000077571321653344700177410ustar00rootroot00000000000000vst4cs ------ VST HOST OPCODES FOR CSOUND vst4cs: VST HOST OPCODES FOR CSOUND Uses code by Hermann Seib from his VSTHost program and from the vst~ object by Thomas Grill (no license), which in turn borrows from the Psycle tracker (also based on VSTHost). VST is a trademark of Steinberg Media Technologies GmbH. VST Plug-In Technology by Steinberg. Copyright (C) 2004 Andres Cabrera, Michael Gogins The vst4cs library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The vst4cs library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with The vst4cs library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Linking vst4cs statically or dynamically with other modules is making a combined work based on vst4cs. Thus, the terms and conditions of the GNU Lesser General Public License cover the whole combination. In addition, as a special exception, the copyright holders of vst4cs, including the Csound developers and Hermann Seib, the original author of VSTHost, give you permission to combine vst4cs with free software programs or libraries that are released under the GNU LGPL and with code included in the standard release of the VST SDK version 2 under the terms of the license stated in the VST SDK version 2 files. You may copy and distribute such a system following the terms of the GNU LGPL for vst4cs and the licenses of the other code concerned. The source code for the VST SDK version 2 is available in the VST SDK hosted at https://github.com/steinbergmedia/vst3sdk. Note that people who make modified versions of vst4cs are not obligated to grant this special exception for their modified versions; it is their choice whether to do so. The GNU Lesser General Public License gives permission to release a modified version without this exception; this exception also makes it possible to release a modified version which carries forward this exception. Current version: 1.0 Installing: Copy vst4cs.dll into your plugin opcodes directory. Copy documentation and source where it suits you. See the HTML documentation for new opcodes. Changes ------- Add to Csound 5 CVS and SConstruct (mkg). Use MYFLT for compiling with either single or double precision (mkg). Change many parameters and non-in/out fields from MYFLT* to MYFLT or other type (mkg). Add virtual destructor to VSTHost class (mkg). Remove Windows-specific header files and data types to enable building on Linux and OS X (mkg). Use cross-platform Csound API functions for loading shared libraries and getting function addresses (mkg). Use std collections throughout -- no explicit heap memory management at all (mkg). Use Csound message printing functions throughout (mkg). Remove all redundant comments (mkg). Simplify turnoff code in vstnote (mkg). Enable fractional pitches (mkg). Cleanup plugin memory allocated on the heap (by using std::vector) (mkg). Write audio only on last instance of vstplug (mkg). Move all VSTPlugin function implementations to vsthost.cpp except for some functions kept inline for speed (mkg). Make all static members of VSTPlugin non-static (mkg). Add the ability to load programs and program banks (ac), and to set programs (mkg). Implement plugin edit windows (mkg). Complete and refine message levels (log and debug) (mkg). Add vstplugg opcode to collect audio from multiple vstnote or vstout instruments (ac and mkg). Renamed opcodes -- vstaudio for vstplug, vstmidiout for vstout, vstparamset for vstpsend, vstparamget for vstpret (mkg). Implemented (supposedly) sample-accurate timing for note on and note off (mkg). csound-6.10.0/Opcodes/vst4cs/src/000077500000000000000000000000001321653344700165125ustar00rootroot00000000000000csound-6.10.0/Opcodes/vst4cs/src/fxbank.cpp000066400000000000000000000423651321653344700205010ustar00rootroot00000000000000// vst4cs: VST HOST OPCODES FOR CSOUND // // Uses code by Hermann Seib from his VSTHost program and from the vst~ // object by Thomas Grill (no license), which in turn borrows from the Psycle // tracker (also based on VSTHost). // // VST is a trademark of Steinberg Media Technologies GmbH. // VST Plug-In Technology by Steinberg. // // Copyright (C) 2004 Andres Cabrera, Michael Gogins // // The vst4cs library is free software; you can redistribute it // and/or modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // The vst4cs library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with The vst4cs library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA // 02111-1307 USA // // Linking vst4cs statically or dynamically with other modules is making a // combined work based on vst4cs. Thus, the terms and conditions of the GNU // Lesser General Public License cover the whole combination. // // In addition, as a special exception, the copyright holders of vst4cs, // including the Csound developers and Hermann Seib, the original author of // VSTHost, give you permission to combine vst4cs with free software programs // or libraries that are released under the GNU LGPL and with code included // in the standard release of the VST SDK version 2 under the terms of the // license stated in the VST SDK version 2 files. You may copy and distribute // such a system following the terms of the GNU LGPL for vst4cs and the // licenses of the other code concerned. The source code for the VST SDK // version 2 is available in the VST SDK hosted at // https://github.com/steinbergmedia/vst3sdk. // // Note that people who make modified versions of vst4cs are not obligated to // grant this special exception for their modified versions; it is their // choice whether to do so. The GNU Lesser General Public License gives // permission to release a modified version without this exception; this // exception also makes it possible to release a modified version which // carries forward this exception. #ifdef _WIN32 #pragma warning(disable:4786) //gab #endif #include "fxbank.h" #include const int MyVersion = 1; /* highest known VST FX version */ CFxBank::CFxBank(char *pszFile) { Init(); /* initialize data areas */ if (pszFile) /* if a file name has been passed */ LoadBank(pszFile); /* load the corresponding bank */ } CFxBank::CFxBank(int nPrograms, int nParams) { Init(); /* initialize data areas */ SetSize(nPrograms, nParams); /* set new size */ } CFxBank::CFxBank(int nChunkSize) { Init(); /* initialize data areas */ SetSize(nChunkSize); /* set new size */ } /*****************************************************************************/ /* Init : initializes all data areas */ /*****************************************************************************/ void CFxBank::Init() { static char szChnk[] = "CcnK"; /* set up swapping flag */ static long lChnk = 'CcnK'; NeedsBSwap = !!memcmp(szChnk, &lChnk, 4); bBank = NULL; /* no bank data loaded */ Unload(); /* reset all parameters */ } CFxBank::~CFxBank() { Unload(); /* unload all data */ } /*****************************************************************************/ /* DoCopy : combined for copy constructor and assignment operator */ /*****************************************************************************/ CFxBank& CFxBank::DoCopy(const CFxBank& org) { unsigned char *nBank = NULL; if (org.nBankLen) { unsigned char *nBank = new unsigned char[org.nBankLen]; if (!nBank) throw (int) 1; memcpy(nBank, org.bBank, org.nBankLen); } Unload(); /* remove previous data */ bBank = nBank; /* and copy in the other one's */ bChunk = org.bChunk; nBankLen = org.nBankLen; strcpy(szFileName, org.szFileName); return *this; } /*****************************************************************************/ /* SetSize : sets new size */ /*****************************************************************************/ bool CFxBank::SetSize(int nPrograms, int nParams) { int nTotLen = sizeof(fxSet) - sizeof(fxProgram); int nProgLen = sizeof(fxProgram) + (nParams - 1) * sizeof(float); nTotLen += nPrograms * nProgLen; unsigned char *nBank = new unsigned char[nTotLen]; if (!nBank) return false; Unload(); bBank = nBank; nBankLen = nTotLen; bChunk = false; memset(nBank, 0, nTotLen); /* initialize new bank */ fxSet *pSet = (fxSet *) bBank; pSet->chunkMagic = cMagic; pSet->byteSize = 0; pSet->fxMagic = bankMagic; pSet->version = MyVersion; pSet->numPrograms = nPrograms; unsigned char *bProg = (unsigned char *) pSet->programs; for (int i = 0; i < nPrograms; i++) { fxProgram *pProg = (fxProgram *) (bProg + i * nProgLen); pProg->chunkMagic = cMagic; pProg->byteSize = 0; pProg->fxMagic = fMagic; pProg->version = 1; pProg->numParams = nParams; for (int j = 0; j < nParams; j++) pProg->params[j] = 0.0; } return true; } bool CFxBank::SetSize(int nChunkSize) { int nTotLen = sizeof(fxChunkSet) + nChunkSize - 8; unsigned char *nBank = new unsigned char[nTotLen]; if (!nBank) return false; Unload(); bBank = nBank; nBankLen = nTotLen; bChunk = true; memset(nBank, 0, nTotLen); /* initialize new bank */ fxChunkSet *pSet = (fxChunkSet *)bBank; pSet->chunkMagic = cMagic; pSet->byteSize = 0; pSet->fxMagic = chunkBankMagic; pSet->version = MyVersion; pSet->numPrograms = 1; pSet->chunkSize = nChunkSize; return true; } /*****************************************************************************/ /* SwapBytes : swaps bytes for big/little-endian difference */ /*****************************************************************************/ void CFxBank::SwapBytes(long &l) { unsigned char *b = (unsigned char *)&l; long intermediate = ((long)b[0] << 24) | ((long)b[1] << 16) | ((long)b[2] << 8) | (long)b[3]; l = intermediate; } void CFxBank::SwapBytes(float &f) { long *pl = (long *)&f; SwapBytes(*pl); } /*****************************************************************************/ /* LoadBank : loads a bank file */ /*****************************************************************************/ bool CFxBank::LoadBank(char *pszFile) { FILE *fp = fopen(pszFile, "rb"); /* try to open the file */ if (!fp) { /* upon error */ printf("Error loading bank: %s \n", pszFile); return false; /* return an error */ } bool brc = true; /* default to OK */ unsigned char *nBank = NULL; //printf("Bank Loaded\n"); //try { fseek(fp, 0, SEEK_END); /* get file size */ size_t tLen = (size_t)ftell(fp); //printf("File Size = %f\n", (float) tLen); rewind(fp); nBank = new unsigned char[tLen]; /* allocate storage */ //if (!nBank) // throw (int)1; /* read chunk set to determine cnt. */ if (fread(nBank, 1, tLen, fp) != tLen) return false; // throw (int)1; fxSet *pSet = (fxSet *)nBank; /* position on set */ //printf("pSet created"); if (NeedsBSwap) /* eventually swap necessary bytes */ { //printf("Swap Needed\n"); SwapBytes(pSet->chunkMagic); SwapBytes(pSet->byteSize); SwapBytes(pSet->fxMagic); SwapBytes(pSet->version); SwapBytes(pSet->fxID); SwapBytes(pSet->fxVersion); SwapBytes(pSet->numPrograms); } if ((pSet->chunkMagic != cMagic) || /* if erroneous data in there */ (pSet->version > MyVersion) || ((pSet->fxMagic != bankMagic) && (pSet->fxMagic != chunkBankMagic))) { printf("Erroneous data.\n"); return 0; } /* get out */ //printf ("Swap OK\n"); if (pSet->fxMagic == bankMagic) { //printf("bankMagic\n"); fxProgram * pProg = pSet->programs; /* position on 1st program */ //printf ("Number of programs = %i",numPrograms); int nProg = 0; while (nProg < pSet->numPrograms) /* walk program list */ { if (NeedsBSwap) /* eventually swap necessary bytes */ { SwapBytes(pProg->chunkMagic); SwapBytes(pProg->byteSize); SwapBytes(pProg->fxMagic); SwapBytes(pProg->version); SwapBytes(pProg->fxID); SwapBytes(pProg->fxVersion); SwapBytes(pProg->numParams); } //printf("bankMagic-Swapped\n"); if ((pProg->chunkMagic != cMagic)|| (pProg->fxMagic != fMagic)) { /* if erroneous data */ printf("Erroneous data.\n"); return 0; /* get out */ }; if (NeedsBSwap) /* if necessary */ { /* swap all parameter bytes */ int j; for (j = 0; j < pProg->numParams; j++) SwapBytes(pProg->params[j]); } //printf("bankMagic-swap parameter\n"); unsigned char *pNext = (unsigned char *)(pProg + 1); pNext += (sizeof(float) * (pProg->numParams - 1)); //if (pNext > nBank + tLen) /* VERY simple fuse */ // throw (int)1; pProg = (fxProgram *)pNext; nProg++; } printf("bankMagic-swap parameter\n"); } /* if it's a chunk file */ else if (pSet->fxMagic == chunkBankMagic) { //printf("chunkBankMagic\n"); fxChunkSet * pCSet = (fxChunkSet *)nBank; if (NeedsBSwap) /* eventually swap necessary bytes */ { SwapBytes(pCSet->chunkSize); /* size check - must not be too large*/ //if (pCSet->chunkSize + sizeof(*pCSet) - 8 > tLen) //throw (int)1; //printf("Chunk OK\n"); } } else printf ("No Magic match\n"); Unload(); /* otherwise remove eventual old data*/ //printf("Unloaded"); bBank = nBank; /* and put in new data */ nBankLen = (int)tLen; bChunk = (pSet->fxMagic == chunkBankMagic); } //catch(...) // { // brc = false; /* if any error occured, say NOPE */ // if (nBank) /* and remove loaded data */ // delete[] nBank; // } fclose(fp); /* close the file */ //printf("File closed\n"); return brc; /* and return */ } /*****************************************************************************/ /* SaveBank : save bank to file */ /*****************************************************************************/ bool CFxBank::SaveBank(char *pszFile) { if (!IsLoaded()) return false; /* create internal copy for mod */ unsigned char *nBank = new unsigned char[nBankLen]; if (!nBank) /* if impossible */ return false; memcpy(nBank, bBank, nBankLen); fxSet *pSet = (fxSet *) nBank; /* position on set */ int numPrograms = pSet->numPrograms; if (NeedsBSwap) { /* if byte-swapping needed */ SwapBytes(pSet->chunkMagic); SwapBytes(pSet->byteSize); SwapBytes(pSet->fxMagic); SwapBytes(pSet->version); SwapBytes(pSet->fxID); SwapBytes(pSet->fxVersion); SwapBytes(pSet->numPrograms); } if (bChunk) { fxChunkSet *pCSet = (fxChunkSet *) nBank; if (NeedsBSwap) /* if byte-swapping needed */ SwapBytes(pCSet->chunkSize); } else { fxProgram *pProg = pSet->programs; /* position on 1st program */ int numParams = pProg->numParams; int nProg = 0; while (nProg < numPrograms) { /* walk program list */ if (NeedsBSwap) { /* eventually swap all necessary */ SwapBytes(pProg->chunkMagic); SwapBytes(pProg->byteSize); SwapBytes(pProg->fxMagic); SwapBytes(pProg->version); SwapBytes(pProg->fxID); SwapBytes(pProg->fxVersion); SwapBytes(pProg->numParams); for (int j = 0; j < numParams; j++) SwapBytes(pProg->params[j]); } unsigned char *pNext = (unsigned char *)(pProg + 1); pNext += (sizeof(float) * (numParams - 1)); if (pNext > nBank + nBankLen) /* VERY simple fuse */ break; pProg = (fxProgram *)pNext; nProg++; } } bool brc = true; /* default to OK */ FILE *fp = NULL; try { fp = fopen(pszFile, "wb"); /* try to open the file */ if (!fp) /* upon error */ throw (int)1; /* return an error */ if (fwrite(nBank, 1, nBankLen, fp) != (size_t)nBankLen) throw (int)1; } catch (...) { brc = false; } if (fp) fclose(fp); delete[] nBank; return brc; } /*****************************************************************************/ /* Unload : removes a loaded bank from memory */ /*****************************************************************************/ void CFxBank::Unload() { if (bBank) delete[] bBank; *szFileName = '\0'; /* reset file name */ bBank = NULL; /* reset bank pointer */ nBankLen = 0; /* reset bank length */ bChunk = false; /* and of course it's no chunk. */ } /*****************************************************************************/ /* GetProgram : returns pointer to one of the loaded programs */ /*****************************************************************************/ fxProgram * CFxBank::GetProgram(int nProgNum) { if ((!IsLoaded()) || (bChunk)) /* if nothing loaded or chunk file */ return NULL; /* return OUCH */ fxSet *pSet = (fxSet *) bBank; /* position on set */ fxProgram *pProg = pSet->programs; /* position on 1st program */ #if 1 int nProgLen = sizeof(fxProgram) + (pProg->numParams - 1) * sizeof(float); unsigned char *pThatProg = ((unsigned char *)pProg) + (nProgNum * nProgLen); pProg = (fxProgram *)pThatProg; #else /*---------------------------------------------------------------------------*/ /* presumably, the following logic is overkill; if all programs have the */ /* same number of parameters, a simple multiplication would do. */ /* But that's not stated anywhere in the VST SDK... */ /*---------------------------------------------------------------------------*/ int i; for (i = 0; i < nProgNum; i++) { unsigned char *pNext = (unsigned char *)(pProg + 1); pNext += (sizeof(float) * (pProg->numParams - 1)); if (pNext > bBank + nBankLen) /* VERY simple fuse */ return NULL; pProg = (fxProgram *)pNext; } #endif return pProg; } csound-6.10.0/Opcodes/vst4cs/src/fxbank.h000066400000000000000000001075511321653344700201450ustar00rootroot00000000000000// vst4cs: VST HOST OPCODES FOR CSOUND // // Uses code by Hermann Seib from his VSTHost program and from the vst~ // object by Thomas Grill (no license), which in turn borrows from the Psycle // tracker (also based on VSTHost). // // VST is a trademark of Steinberg Media Technologies GmbH. // VST Plug-In Technology by Steinberg. // // Copyright (C) 2004 Andres Cabrera, Michael Gogins // // The vst4cs library is free software; you can redistribute it // and/or modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // The vst4cs library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with The vst4cs library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA // 02111-1307 USA // // Linking vst4cs statically or dynamically with other modules is making a // combined work based on vst4cs. Thus, the terms and conditions of the GNU // Lesser General Public License cover the whole combination. // // In addition, as a special exception, the copyright holders of vst4cs, // including the Csound developers and Hermann Seib, the original author of // VSTHost, give you permission to combine vst4cs with free software programs // or libraries that are released under the GNU LGPL and with code included // in the standard release of the VST SDK version 2 under the terms of the // license stated in the VST SDK version 2 files. You may copy and distribute // such a system following the terms of the GNU LGPL for vst4cs and the // licenses of the other code concerned. The source code for the VST SDK // version 2 is available in the VST SDK hosted at // https://github.com/steinbergmedia/vst3sdk. // // Note that people who make modified versions of vst4cs are not obligated to // grant this special exception for their modified versions; it is their // choice whether to do so. The GNU Lesser General Public License gives // permission to release a modified version without this exception; this // exception also makes it possible to release a modified version which // carries forward this exception. #ifndef FXBANK_H #define FXBANK_H #if !defined(VST_2_1_EXTENSIONS) struct VstFileSelect; struct MidiProgramName; struct MidiProgramCategory; struct MidiKeyName; #endif /*****************************************************************************/ /* this is a copy of vstfxstore.h! */ /*****************************************************************************/ #define cMagic 'CcnK' #define fMagic 'FxCk' #define bankMagic 'FxBk' #define chunkGlobalMagic 'FxCh' #define chunkPresetMagic 'FPCh' #define chunkBankMagic 'FBCh' //-------------------------------------------------------------------- struct fxProgram { long chunkMagic; // 'CcnK' long byteSize; // of this chunk, excl. magic + byteSize long fxMagic; // 'FxCk' long version; long fxID; // fx unique id long fxVersion; long numParams; char prgName[28]; float params[1]; // variable no. of parameters }; //-------------------------------------------------------------------- struct fxSet { long chunkMagic; // 'CcnK' long byteSize; // of this chunk, excl. magic + byteSize long fxMagic; // 'FxBk' long version; long fxID; // fx unique id long fxVersion; long numPrograms; char future[128]; fxProgram programs[1]; // variable no. of programs }; //-------------------------------------------------------------------- struct fxChunkSet { long chunkMagic; // 'CcnK' long byteSize; // of this chunk, excl. magic + byteSize long fxMagic; // 'FxCh', 'FPCh', or 'FBCh' long version; long fxID; // fx unique id long fxVersion; long numPrograms; char future[128]; long chunkSize; char chunk[8]; // variable }; //#endif #if !defined(VST_2_3_EXTENSIONS) struct VstSpeakerArrangement; struct VstPatchChunkInfo; #endif #include "public.sdk/source/vst2.x/aeffeditor.h" #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 /*****************************************************************************/ /* CFxBank : class for an Fx Bank */ /*****************************************************************************/ class CFxBank { public: CFxBank(char *pszFile = 0); CFxBank(int nPrograms, int nParams); CFxBank(int nChunkSize); CFxBank(CFxBank const &org) { DoCopy(org); } virtual ~CFxBank(); CFxBank & operator=(CFxBank const &org) { return DoCopy(org); } public: bool SetSize(int nPrograms, int nParams); bool SetSize(int nChunkSize); bool LoadBank(char *pszFile); bool SaveBank(char *pszFile); void Unload(); bool IsLoaded() { return !!bBank; } bool IsChunk() { return bChunk; } // access functions public: long GetVersion() { if (!bBank) return 0; return ((fxSet*)bBank)->version; } long GetFxID() { if (!bBank) return 0; return ((fxSet*)bBank)->fxID; } void SetFxID(long id) { if (bBank) ((fxSet*)bBank)->fxID = id; if (!bChunk) for (int i = GetNumPrograms() -1; i >= 0; i--) GetProgram(i)->fxID = id; } long GetFxVersion() { if (!bBank) return 0; return ((fxSet*)bBank)->fxVersion; } void SetFxVersion(long v) { if (bBank) ((fxSet*)bBank)->fxVersion = v; if (!bChunk) for (int i = GetNumPrograms() -1; i >= 0; i--) GetProgram(i)->fxVersion = v; } long GetNumPrograms() { if (!bBank) return 0; return ((fxSet*)bBank)->numPrograms; } long GetNumParams() { if (bChunk) return 0; return GetProgram(0)->numParams; } long GetChunkSize() { if (!bChunk) return 0; return ((fxChunkSet *)bBank)->chunkSize; } void *GetChunk() { if (!bChunk) return 0; return ((fxChunkSet *)bBank)->chunk; } bool SetChunk(void *chunk) { if (!bChunk) return false; memcpy(((fxChunkSet *)bBank)->chunk, chunk, ((fxChunkSet *)bBank)->chunkSize); return true; } fxProgram * GetProgram(int nProgNum); char * GetProgramName(int nProgram) { fxProgram *p = GetProgram(nProgram); if (!p) return NULL; return p->prgName; } void SetProgramName(int nProgram, const char *name = "") { fxProgram *p = GetProgram(nProgram); if (!p) return; strncpy(p->prgName, name, sizeof(p->prgName)); p->prgName[sizeof(p->prgName)-1] = '\0'; } float GetProgParm(int nProgram, int nParm) { fxProgram *p = GetProgram(nProgram); if (!p || nParm > p->numParams) return 0; return p->params[nParm]; } bool SetProgParm(int nProgram, int nParm, float val = 0.0) { fxProgram *p = GetProgram(nProgram); if (!p || nParm > p->numParams) return false; if (val < 0.0) val = 0.0; if (val > 1.0) val = 1.0; p->params[nParm] = val; return true; } protected: char szFileName[256]; unsigned char * bBank; int nBankLen; bool bChunk; bool NeedsBSwap; protected: void Init(); CFxBank & DoCopy(CFxBank const &org); static void SwapBytes(float &f); static void SwapBytes(long &l); }; /*****************************************************************************/ /* CEffect : class definition for audio effect objects */ /*****************************************************************************/ /* class CVSTHost; class CEffect { public: CEffect(CVSTHost *pHost); virtual ~CEffect(); public: CVSTHost *pHost; AEffect *pEffect; char *sName; bool bEditOpen; bool bNeedIdle; bool bWantMidi; #ifdef WIN32 HMODULE hModule; char *sDir; #elif MAC // yet to do // no idea how things look here... #endif virtual bool Load(const char *name); virtual bool Unload(); virtual bool LoadBank(char *name); virtual bool SaveBank(char *name); virtual long EffDispatch(long opCode, long index=0, long value=0, void *ptr=0, float opt=0.); virtual void EffProcess(float **inputs, float **outputs, long sampleframes); virtual void EffProcessReplacing(float **inputs, float **outputs, long sampleframes); virtual void EffSetParameter(long index, float parameter); virtual float EffGetParameter(long index); void EffOpen() { EffDispatch(effOpen); } void EffClose() { EffDispatch(effClose); } void EffSetProgram(long lValue) { EffDispatch(effSetProgram, 0, lValue); } long EffGetProgram() { return EffDispatch(effGetProgram); } void EffSetProgramName(char *ptr) { EffDispatch(effSetProgramName, 0, 0, ptr); } void EffGetProgramName(char *ptr) { EffDispatch(effGetProgramName, 0, 0, ptr); } void EffGetParamLabel(long index, char *ptr) { EffDispatch(effGetParamLabel, index, 0, ptr); } void EffGetParamDisplay(long index, char *ptr) { EffDispatch(effGetParamDisplay, index, 0, ptr); } void EffGetParamName(long index, char *ptr) { EffDispatch(effGetParamName, index, 0, ptr); } void EffSetSampleRate(float fSampleRate) { EffDispatch(effSetSampleRate, 0, 0, 0, fSampleRate); } void EffSetBlockSize(long value) { EffDispatch(effSetBlockSize, 0, value); } void EffMainsChanged(bool bOn) { EffDispatch(effMainsChanged, 0, bOn); } float EffGetVu() { return (float)EffDispatch(effGetVu) / (float)32767.; } long EffEditGetRect(ERect **ptr) { return EffDispatch(effEditGetRect, 0, 0, ptr); } long EffEditOpen(void *ptr) { long l = EffDispatch(effEditOpen, 0, 0, ptr); if (l > 0) bEditOpen = true; return l; } void EffEditClose() { EffDispatch(effEditClose); bEditOpen = false; } void EffEditIdle() { if (bEditOpen) EffDispatch(effEditIdle); } #if MAC void EffEditDraw(void *ptr) { EffDispatch(nEffect, effEditDraw, 0, 0, ptr); } long EffEditMouse(long index, long value) { return EffDispatch(nEffect, effEditMouse, index, value); } long EffEditKey(long value) { return EffDispatch(effEditKey, 0, value); } void EffEditTop() { EffDispatch(effEditTop); } void EffEditSleep() { EffDispatch(effEditSleep); } #endif long EffIdentify() { return EffDispatch(effIdentify); } long EffGetChunk(void **ptr, bool isPreset = false) { return EffDispatch(effGetChunk, isPreset, 0, ptr); } long EffSetChunk(void *data, long byteSize, bool isPreset = false) { return EffDispatch(effSetChunk, isPreset, byteSize, data); } //VST 2.0 long EffProcessEvents(VstEvents* ptr) { return EffDispatch(effProcessEvents, 0, 0, ptr); } long EffCanBeAutomated(long index) { return EffDispatch(effCanBeAutomated, index); } long EffString2Parameter(long index, char *ptr) { return EffDispatch(effString2Parameter, index, 0, ptr); } long EffGetNumProgramCategories() { return EffDispatch(effGetNumProgramCategories); } long EffGetProgramNameIndexed(long category, long index, char* text) { return EffDispatch(effGetProgramNameIndexed, index, category, text); } long EffCopyProgram(long index) { return EffDispatch(effCopyProgram, index); } long EffConnectInput(long index, bool state) { return EffDispatch(effConnectInput, index, state); } long EffConnectOutput(long index, bool state) { return EffDispatch(effConnectOutput, index, state); } long EffGetInputProperties(long index, VstPinProperties *ptr) { return EffDispatch(effGetInputProperties, index, 0, ptr); } long EffGetOutputProperties(long index, VstPinProperties *ptr) { return EffDispatch(effGetOutputProperties, index, 0, ptr); } long EffGetPlugCategory() { return EffDispatch(effGetPlugCategory); } long EffGetCurrentPosition() { return EffDispatch(effGetCurrentPosition); } long EffGetDestinationBuffer() { return EffDispatch(effGetDestinationBuffer); } long EffOfflineNotify(VstAudioFile* ptr, long numAudioFiles, bool start) { return EffDispatch(effOfflineNotify, start, numAudioFiles, ptr); } long EffOfflinePrepare(VstOfflineTask *ptr, long count) { return EffDispatch(effOfflinePrepare, 0, count, ptr); } long EffOfflineRun(VstOfflineTask *ptr, long count) { return EffDispatch(effOfflineRun, 0, count, ptr); } long EffProcessVarIo(VstVariableIo* varIo) { return EffDispatch(effProcessVarIo, 0, 0, varIo); } long EffSetSpeakerArrangement(VstSpeakerArrangement* pluginInput, VstSpeakerArrangement* pluginOutput) { return EffDispatch(effSetSpeakerArrangement, 0, (long)pluginInput, pluginOutput); } long EffSetBlockSizeAndSampleRate(long blockSize, float sampleRate) { return EffDispatch(effSetBlockSizeAndSampleRate, 0, blockSize, 0, sampleRate); } long EffSetBypass(bool onOff) { return EffDispatch(effSetBypass, 0, onOff); } long EffGetEffectName(char *ptr) { return EffDispatch(effGetEffectName, 0, 0, ptr); } long EffGetErrorText(char *ptr) { return EffDispatch(effGetErrorText, 0, 0, ptr); } long EffGetVendorString(char *ptr) { return EffDispatch(effGetVendorString, 0, 0, ptr); } long EffGetProductString(char *ptr) { return EffDispatch(effGetProductString, 0, 0, ptr); } long EffGetVendorVersion() { return EffDispatch(effGetVendorVersion); } long EffVendorSpecific(long index, long value, void *ptr, float opt) { return EffDispatch(effVendorSpecific, index, value, ptr, opt); } long EffCanDo(const char *ptr) { return EffDispatch(effCanDo, 0, 0, (void *)ptr); } long EffGetTailSize() { return EffDispatch(effGetTailSize); } long EffIdle() { if (bNeedIdle) return EffDispatch(effIdle); else return 0; } long EffGetIcon() { return EffDispatch(effGetIcon); } long EffSetViewPosition(long x, long y) { return EffDispatch(effSetViewPosition, x, y); } long EffGetParameterProperties(long index, VstParameterProperties* ptr) { return EffDispatch(effGetParameterProperties, index, 0, ptr); } long EffKeysRequired() { return EffDispatch(effKeysRequired); } long EffGetVstVersion() { return EffDispatch(effGetVstVersion); } //VST 2.1 extensions long EffKeyDown(VstKeyCode &keyCode) { return EffDispatch(effEditKeyDown, keyCode.character, keyCode.virt, 0, keyCode.modifier); } long EffKeyUp(VstKeyCode &keyCode) { return EffDispatch(effEditKeyUp, keyCode.character, keyCode.virt, 0, keyCode.modifier); } void EffSetKnobMode(long value) { EffDispatch(effSetEditKnobMode, 0, value); } long EffGetMidiProgramName(long channel, MidiProgramName* midiProgramName) { return EffDispatch(effGetMidiProgramName, channel, 0, midiProgramName); } long EffGetCurrentMidiProgram (long channel, MidiProgramName* currentProgram) { return EffDispatch(effGetCurrentMidiProgram, channel, 0, currentProgram); } long EffGetMidiProgramCategory (long channel, MidiProgramCategory* category) { return EffDispatch(effGetMidiProgramCategory, channel, 0, category); } long EffHasMidiProgramsChanged (long channel) { return EffDispatch(effHasMidiProgramsChanged, channel); } long EffGetMidiKeyName(long channel, MidiKeyName* keyName) { return EffDispatch(effGetMidiKeyName, channel, 0, keyName); } long EffBeginSetProgram() { return EffDispatch(effBeginSetProgram); } long EffEndSetProgram() { return EffDispatch(effEndSetProgram); } // VST 2.3 Extensions long EffGetSpeakerArrangement(VstSpeakerArrangement** pluginInput, VstSpeakerArrangement** pluginOutput) { EffDispatch(effGetSpeakerArrangement, 0, (long)pluginInput, pluginOutput); } long EffSetTotalSampleToProcess (long value) { return EffDispatch(effSetTotalSampleToProcess, 0, value); } long EffGetNextShellPlugin(char *name) { return EffDispatch(effShellGetNextPlugin, 0, 0, name); } long EffStartProcess() { return EffDispatch(effStartProcess); } long EffStopProcess() { return EffDispatch(effStopProcess); } long EffSetPanLaw(long type, float val) { return EffDispatch(effSetPanLaw, 0, type, 0, val); } long EffBeginLoadBank(VstPatchChunkInfo* ptr) { return EffDispatch(effBeginLoadBank, 0, 0, ptr); } long EffBeginLoadProgram(VstPatchChunkInfo* ptr) { return EffDispatch(effBeginLoadProgram, 0, 0, ptr); } // overridables public: virtual void * OnGetDirectory(); virtual void OnSizeEditorWindow(long width, long height) { } virtual bool OnUpdateDisplay() { return false; } }; */ /*****************************************************************************/ /* CVSTHost class declaration */ /*****************************************************************************/ /* class CVSTHost { friend class CEffect; public: CVSTHost(); virtual ~CVSTHost(); protected: VstTimeInfo vstTimeInfo; float fSampleRate; long lBlockSize; int naEffects; int nmaEffects; void **aEffects; static CVSTHost * pHost; static long VSTCALLBACK AudioMasterCallback(AEffect *effect, long opcode, long index, long value, void *ptr, float opt); int Search(AEffect *pEffect); int GetPreviousPlugIn(int nEffect); int GetNextPlugIn(int nEffect); long EffDispatch(int nEffect, long opCode, long index=0, long value=0, void *ptr=0, float opt=0.); public: int LoadPlugin(const char * lpszName); int GetSize() { return naEffects; } CEffect *GetAt(int nIndex) { if ((nIndex >= 0) && (nIndex < naEffects)) return (CEffect *)aEffects[nIndex]; else return 0; } void RemoveAt(int nIndex); void RemoveAll(); void EffProcess(int nEffect, float **inputs, float **outputs, long sampleframes); void EffProcessReplacing(int nEffect, float **inputs, float **outputs, long sampleframes); void EffSetParameter(int nEffect, long index, float parameter); float EffGetParameter(int nEffect, long index); void EffOpen(int nEffect) { if (GetAt(nEffect)) GetAt(nEffect)->EffOpen(); } void EffClose(int nEffect) { if (GetAt(nEffect)) GetAt(nEffect)->EffClose(); } void EffSetProgram(int nEffect, long lValue) { if (GetAt(nEffect)) GetAt(nEffect)->EffSetProgram(lValue); } long EffGetProgram(int nEffect) { if (GetAt(nEffect)) return (GetAt(nEffect))->EffGetProgram(); else return 0; } void EffSetProgramName(int nEffect, char *ptr) { if (GetAt(nEffect)) GetAt(nEffect)->EffSetProgramName(ptr); } void EffGetProgramName(int nEffect, char *ptr) { if (GetAt(nEffect)) GetAt(nEffect)->EffGetProgramName(ptr); } void EffGetParamLabel(int nEffect, long index, char *ptr) { if (GetAt(nEffect)) GetAt(nEffect)->EffGetParamLabel(index, ptr); } void EffGetParamDisplay(int nEffect, long index, char *ptr) { if (GetAt(nEffect)) GetAt(nEffect)->EffGetParamDisplay(index, ptr); } void EffGetParamName(int nEffect, long index, char *ptr) { if (GetAt(nEffect)) GetAt(nEffect)->EffGetParamName(index, ptr); } void EffSetSampleRate(int nEffect, float fSampleRate) { if (GetAt(nEffect)) GetAt(nEffect)->EffSetSampleRate(fSampleRate); } void EffSetBlockSize(int nEffect, long value) { if (GetAt(nEffect)) GetAt(nEffect)->EffSetBlockSize(value); } void EffMainsChanged(int nEffect, bool bOn) { if (GetAt(nEffect)) GetAt(nEffect)->EffMainsChanged(bOn); } float EffGetVu(int nEffect) { if (GetAt(nEffect)) return GetAt(nEffect)->EffGetVu(); else return 0.f; } long EffEditGetRect(int nEffect, ERect **ptr) { if (GetAt(nEffect)) return GetAt(nEffect)->EffEditGetRect(ptr); else return 0; } long EffEditOpen(int nEffect, void *ptr) { if (GetAt(nEffect)) return GetAt(nEffect)->EffEditOpen(ptr); else return 0; } void EffEditClose(int nEffect) { if (GetAt(nEffect)) GetAt(nEffect)->EffEditClose(); } void EffEditIdle(int nEffect) { if (GetAt(nEffect)) GetAt(nEffect)->EffEditIdle(); } #if MAC void EffEditDraw(int nEffect, void *ptr) { if (GetAt(nEffect)) GetAt(nEffect)->EffEditDraw(ptr); } long EffEditMouse(int nEffect, long index, long value) { if (GetAt(nEffect)) return GetAt(nEffect)->EffEditMouse(index, value); else return 0; } long EffEditKey(int nEffect, long value) { if (GetAt(nEffect)) return GetAt(nEffect)->EffEditKey(value); else return 0; } void EffEditTop(int nEffect) { if (GetAt(nEffect)) GetAt(nEffect)->EffEditTop(); } void EffEditSleep(int nEffect) { if (GetAt(nEffect)) GetAt(nEffect)->EffEditSleep(); } #endif long EffIdentify(int nEffect) { if (GetAt(nEffect)) return GetAt(nEffect)->EffIdentify(); else return 0; } long EffGetChunk(int nEffect, void **ptr, bool isPreset = false) { if (GetAt(nEffect)) return GetAt(nEffect)->EffGetChunk(ptr, isPreset); else return 0; } long EffSetChunk(int nEffect, void *data, long byteSize, bool isPreset = false) { if (GetAt(nEffect)) return GetAt(nEffect)->EffSetChunk(data, byteSize, isPreset); else return 0; } // VST 2.0 long EffProcessEvents(int nEffect, VstEvents* ptr) { if (GetAt(nEffect)) return GetAt(nEffect)->EffProcessEvents(ptr); else return 0; } long EffCanBeAutomated(int nEffect, long index) { if (GetAt(nEffect)) return GetAt(nEffect)->EffCanBeAutomated(index); else return 0; } long EffString2Parameter(int nEffect, long index, char *ptr) { if (GetAt(nEffect)) return GetAt(nEffect)->EffString2Parameter(index, ptr); else return 0; } long EffGetNumProgramCategories(int nEffect) { if (GetAt(nEffect)) return GetAt(nEffect)->EffGetNumProgramCategories(); else return 0; } long EffGetProgramNameIndexed(int nEffect, long category, long index, char* text) { if (GetAt(nEffect)) return GetAt(nEffect)->EffGetProgramNameIndexed(category, index, text); else return 0; } long EffCopyProgram(int nEffect, long index) { if (GetAt(nEffect)) return GetAt(nEffect)->EffCopyProgram(index); else return 0; } long EffConnectInput(int nEffect, long index, bool state) { if (GetAt(nEffect)) return GetAt(nEffect)->EffConnectInput(index, state); else return 0; } long EffConnectOutput(int nEffect, long index, bool state) { if (GetAt(nEffect)) return GetAt(nEffect)->EffConnectOutput(index, state); else return 0; } long EffGetInputProperties(int nEffect, long index, VstPinProperties *ptr) { if (GetAt(nEffect)) return GetAt(nEffect)->EffGetInputProperties(index, ptr); else return 0; } long EffGetOutputProperties(int nEffect, long index, VstPinProperties *ptr) { if (GetAt(nEffect)) return GetAt(nEffect)->EffGetOutputProperties(index, ptr); else return 0; } long EffGetPlugCategory(int nEffect) { if (GetAt(nEffect)) return GetAt(nEffect)->EffGetPlugCategory(); else return 0; } long EffGetCurrentPosition(int nEffect) { if (GetAt(nEffect)) return GetAt(nEffect)->EffGetCurrentPosition(); else return 0; } long EffGetDestinationBuffer(int nEffect) { if (GetAt(nEffect)) return GetAt(nEffect)->EffGetDestinationBuffer(); else return 0; } long EffOfflineNotify(int nEffect, VstAudioFile* ptr, long numAudioFiles, bool start) { if (GetAt(nEffect)) return GetAt(nEffect)->EffOfflineNotify(ptr, numAudioFiles, start); else return 0; } long EffOfflinePrepare(int nEffect, VstOfflineTask *ptr, long count) { if (GetAt(nEffect)) return GetAt(nEffect)->EffOfflinePrepare(ptr, count); else return 0; } long EffOfflineRun(int nEffect, VstOfflineTask *ptr, long count) { if (GetAt(nEffect)) return GetAt(nEffect)->EffOfflineRun(ptr, count); else return 0; } long EffProcessVarIo(int nEffect, VstVariableIo* varIo) { if (GetAt(nEffect)) return GetAt(nEffect)->EffProcessVarIo(varIo); else return 0; } long EffSetSpeakerArrangement(int nEffect, VstSpeakerArrangement* pluginInput, VstSpeakerArrangement* pluginOutput) { if (GetAt(nEffect)) return GetAt(nEffect)->EffSetSpeakerArrangement(pluginInput, pluginOutput); else return 0; } long EffSetBlockSizeAndSampleRate(int nEffect, long blockSize, float sampleRate) { if (GetAt(nEffect)) return GetAt(nEffect)->EffSetBlockSizeAndSampleRate(blockSize, sampleRate); else return 0; } long EffSetBypass(int nEffect, bool onOff) { if (GetAt(nEffect)) return GetAt(nEffect)->EffSetBypass(onOff); else return 0; } long EffGetEffectName(int nEffect, char *ptr) { if (GetAt(nEffect)) return GetAt(nEffect)->EffGetEffectName(ptr); else return 0; } long EffGetErrorText(int nEffect, char *ptr) { if (GetAt(nEffect)) return GetAt(nEffect)->EffGetErrorText(ptr); else return 0; } long EffGetVendorString(int nEffect, char *ptr) { if (GetAt(nEffect)) return GetAt(nEffect)->EffGetVendorString(ptr); else return 0; } long EffGetProductString(int nEffect, char *ptr) { if (GetAt(nEffect)) return GetAt(nEffect)->EffGetProductString(ptr); else return 0; } long EffGetVendorVersion(int nEffect) { if (GetAt(nEffect)) return GetAt(nEffect)->EffGetVendorVersion(); else return 0; } long EffVendorSpecific(int nEffect, long index, long value, void *ptr, float opt) { if (GetAt(nEffect)) return GetAt(nEffect)->EffVendorSpecific(index, value, ptr, opt); else return 0; } long EffCanDo(int nEffect, const char *ptr) { if (GetAt(nEffect)) return GetAt(nEffect)->EffCanDo(ptr); else return 0; } long EffGetTailSize(int nEffect) { if (GetAt(nEffect)) return GetAt(nEffect)->EffGetTailSize(); else return 0; } long EffIdle(int nEffect) { if (GetAt(nEffect)) return GetAt(nEffect)->EffIdle(); else return 0; } long EffGetIcon(int nEffect) { if (GetAt(nEffect)) return GetAt(nEffect)->EffGetIcon(); else return 0; } long EffSetViewPosition(int nEffect, long x, long y) { if (GetAt(nEffect)) return GetAt(nEffect)->EffSetViewPosition(x, y); else return 0; } long EffGetParameterProperties(int nEffect, long index, VstParameterProperties* ptr) { if (GetAt(nEffect)) return GetAt(nEffect)->EffGetParameterProperties(index, ptr); else return 0; } long EffKeysRequired(int nEffect) { if (GetAt(nEffect)) return GetAt(nEffect)->EffKeysRequired(); else return 0; } long EffGetVstVersion(int nEffect) { if (GetAt(nEffect)) return GetAt(nEffect)->EffGetVstVersion(); else return 0; } // VST 2.1 extensions long EffKeyDown(int nEffect, VstKeyCode &keyCode) { if (GetAt(nEffect)) return GetAt(nEffect)->EffKeyDown(keyCode); else return 0; } long EffKeyUp(int nEffect, VstKeyCode &keyCode) { if (GetAt(nEffect)) return GetAt(nEffect)->EffKeyUp(keyCode); else return 0; } void EffSetKnobMode(int nEffect, long value) { if (GetAt(nEffect)) GetAt(nEffect)->EffSetKnobMode(value); } long EffGetMidiProgramName(int nEffect, long channel, MidiProgramName* midiProgramName) { if (GetAt(nEffect)) return GetAt(nEffect)->EffGetMidiProgramName(channel, midiProgramName); else return 0; } long EffGetCurrentMidiProgram(int nEffect, long channel, MidiProgramName* currentProgram) { if (GetAt(nEffect)) return GetAt(nEffect)->EffGetCurrentMidiProgram(channel, currentProgram); else return 0; } long EffGetMidiProgramCategory(int nEffect, long channel, MidiProgramCategory* category) { if (GetAt(nEffect)) return GetAt(nEffect)->EffGetMidiProgramCategory(channel, category); else return 0; } long EffHasMidiProgramsChanged(int nEffect, long channel) { if (GetAt(nEffect)) return GetAt(nEffect)->EffHasMidiProgramsChanged(channel); else return 0; } long EffGetMidiKeyName(int nEffect, long channel, MidiKeyName* keyName) { if (GetAt(nEffect)) return GetAt(nEffect)->EffGetMidiKeyName(channel, keyName); else return 0; } long EffBeginSetProgram(int nEffect) { if (GetAt(nEffect)) return GetAt(nEffect)->EffBeginSetProgram(); else return 0; } long EffEndSetProgram(int nEffect) { if (GetAt(nEffect)) return GetAt(nEffect)->EffBeginSetProgram(); else return 0; } // VST 2.3 Extensions long EffGetSpeakerArrangement(int nEffect, VstSpeakerArrangement** pluginInput, VstSpeakerArrangement** pluginOutput) { if (GetAt(nEffect)) return GetAt(nEffect)->EffGetSpeakerArrangement(pluginInput, pluginOutput); else return 0; } long EffSetTotalSampleToProcess(int nEffect, long value) { if (GetAt(nEffect)) return GetAt(nEffect)->EffSetTotalSampleToProcess(value); else return 0; } long EffGetNextShellPlugin(int nEffect, char *name) { if (GetAt(nEffect)) return GetAt(nEffect)->EffGetNextShellPlugin(name); else return 0; } long EffStartProcess(int nEffect) { if (GetAt(nEffect)) return GetAt(nEffect)->EffStartProcess(); else return 0; } long EffStopProcess(int nEffect) { if (GetAt(nEffect)) return GetAt(nEffect)->EffStopProcess(); else return 0; } long EffSetPanLaw(int nEffect, long type, float val) { if (GetAt(nEffect)) return GetAt(nEffect)->EffSetPanLaw(type, val); else return 0; } long EffBeginLoadBank(int nEffect, VstPatchChunkInfo* ptr) { if (GetAt(nEffect)) return GetAt(nEffect)->EffBeginLoadBank(ptr); else return 0; } long EffBeginLoadProgram(int nEffect, VstPatchChunkInfo* ptr) { if (GetAt(nEffect)) return GetAt(nEffect)->EffBeginLoadProgram(ptr); else return 0; } // overridable functions public: virtual CEffect * CreateEffect() { return new CEffect(this); } virtual void SetSampleRate(float fSampleRate=44100.); virtual void SetBlockSize(long lSize=1024); virtual void Process(float **inputs, float **outputs, long sampleframes); virtual void ProcessReplacing(float **inputs, float **outputs, long sampleframes); virtual bool OnGetVendorString(char *text) { strcpy(text, "Seib"); return true; } // forgive this little vanity :-) virtual long OnGetHostVendorVersion() { return 1; } virtual bool OnGetProductString(char *text) { strcpy(text, "Default CVSTHost"); return true; } virtual bool OnGetSpeakerArrangement(int nEffect, VstSpeakerArrangement* pluginInput, VstSpeakerArrangement* pluginOutput) { return false; } virtual void OnSetOutputSampleRate(int nEffect, float sampleRate) { } virtual bool OnOfflineStart(int nEffect, VstAudioFile* audioFiles, long numAudioFiles, long numNewAudioFiles) { return false; } virtual bool OnOfflineRead(int nEffect, VstOfflineTask* offline, VstOfflineOption option, bool readSource) { return false; } virtual bool OnOfflineWrite(int nEffect, VstOfflineTask* offline, VstOfflineOption option) { return false; } virtual long OnOfflineGetCurrentPass(int nEffect) { return 0; } virtual long OnOfflineGetCurrentMetaPass(int nEffect) { return 0; } virtual long OnGetAutomationState(int nEffect) { return 0; } virtual long OnGetCurrentProcessLevel(int nEffect) { return 0; } virtual bool OnWillProcessReplacing(int nEffect) { return false; } virtual long OnGetOutputLatency(int nEffect) { return 0; } virtual long OnGetInputLatency(int nEffect) { return 0; } virtual void OnUpdateBlockSize(int nEffect); virtual long OnTempoAt(int nEffect, long pos) { return 0; } virtual void OnUpdateSampleRate(int nEffect); virtual bool OnSizeWindow(int nEffect, long width, long height); virtual bool OnNeedIdle(int nEffect); virtual long OnAudioMasterCallback(int nEffect, long opcode, long index, long value, void *ptr, float opt); virtual long OnGetVersion(int nEffect); virtual bool OnCanDo(const char *ptr); virtual bool OnWantEvents(int nEffect, long filter); virtual long OnIdle(int nEffect=-1); virtual bool OnInputConnected(int nEffect, long input) { return true; } virtual bool OnOutputConnected(int nEffect, long output) { return true; } virtual bool OnSetParameterAutomated(int nEffect, long index, float value) { return false; } virtual bool OnProcessEvents(int nEffect, VstEvents* events) { return false; } virtual VstTimeInfo *OnGetTime(int nEffect) { return &vstTimeInfo; } virtual bool OnSetTime(int nEffect, long filter, VstTimeInfo *timeInfo) { return false; } virtual long OnGetNumAutomatableParameters(int nEffect) { return 0; } virtual long OnGetParameterQuantization(int nEffect) { return 0x40000000; } virtual bool OnIoChanged(int nEffect) { return false; } virtual long OnHostVendorSpecific(int nEffect, long lArg1, long lArg2, void* ptrArg, float floatArg) { return 0; } virtual long OnGetHostLanguage() { return 0; } virtual void * OnOpenWindow(int nEffect, VstWindow* window) { return 0; } virtual bool OnCloseWindow(int nEffect, VstWindow* window) { return false; } virtual void * OnGetDirectory(int nEffect); virtual bool OnUpdateDisplay(int nEffect); // VST 2.1 Extensions virtual bool OnBeginEdit(int nEffect) { return false; } virtual bool OnEndEdit(int nEffect) { return false; } virtual bool OnOpenFileSelector (int nEffect, VstFileSelect *ptr) { return false; } // VST 2.2 Extensions virtual bool OnCloseFileSelector (int nEffect, VstFileSelect *ptr) { return false; } virtual bool OnEditFile(int nEffect, char *ptr) { return false; } virtual bool OnGetChunkFile(int nEffect, void * nativePath) { return false; } // VST 2.3 Extensions virtual VstSpeakerArrangement *OnGetInputSpeakerArrangement(int nEffect) { return 0; } }; */ #endif csound-6.10.0/Opcodes/vst4cs/src/vst4cs.cpp000066400000000000000000000670501321653344700204540ustar00rootroot00000000000000// vst4cs: VST HOST OPCODES FOR CSOUND // // Uses code by Hermann Seib from his VSTHost program and from the vst~ // object by Thomas Grill (no license), which in turn borrows from the Psycle // tracker (also based on VSTHost). // // VST is a trademark of Steinberg Media Technologies GmbH. // VST Plug-In Technology by Steinberg. // // Copyright (C) 2004 Andres Cabrera, Michael Gogins // // The vst4cs library is free software; you can redistribute it // and/or modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // The vst4cs library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with The vst4cs library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA // 02111-1307 USA // // Linking vst4cs statically or dynamically with other modules is making a // combined work based on vst4cs. Thus, the terms and conditions of the GNU // Lesser General Public License cover the whole combination. // // In addition, as a special exception, the copyright holders of vst4cs, // including the Csound developers and Hermann Seib, the original author of // VSTHost, give you permission to combine vst4cs with free software programs // or libraries that are released under the GNU LGPL and with code included // in the standard release of the VST SDK version 2 under the terms of the // license stated in the VST SDK version 2 files. You may copy and distribute // such a system following the terms of the GNU LGPL for vst4cs and the // licenses of the other code concerned. The source code for the VST SDK // version 2 is available in the VST SDK hosted at // https://github.com/steinbergmedia/vst3sdk. // // Note that people who make modified versions of vst4cs are not obligated to // grant this special exception for their modified versions; it is their // choice whether to do so. The GNU Lesser General Public License gives // permission to release a modified version without this exception; this // exception also makes it possible to release a modified version which // carries forward this exception. // Linux only: #define CSOUND_LIFECYCLE_DEBUG #ifdef _WIN32 #pragma warning(disable:4786) //gab #endif #include #include #include #include #include "vst4cs.h" #include #include "vsthost.h" #include "fxbank.h" #if defined(CSOUND_LIFECYCLE_DEBUG) #include #include #include #endif // These two collections replace similar ones that used to be in widglobals.h. //typedef std::vector vstPlugEditors_t; typedef std::vector vstPlugins_t; extern "C" { std::string version = "0.2"; #ifdef WIN32 static void path_convert(char *in); #endif static MYFLT getCurrentTime(CSOUND *csound) { return csound->GetCurrentTimeSamples(csound) / csound->GetSr(csound); } static int vstinit(CSOUND *csound, void *data) { VSTINIT *p = (VSTINIT *) data; VSTPlugin *plugin = new VSTPlugin(csound); vstPlugins_t *vstPlugins = 0; csound::QueryGlobalPointer(csound, "vstPlugins", vstPlugins); *p->iVSThandle = (MYFLT) vstPlugins->size(); vstPlugins->push_back(plugin); if ((int) vstPlugins->size() == 1) { plugin->Log("============================================================\n"); plugin->Log("vst4cs version %s by Andres Cabrera and Michael Gogins\n", version.c_str()); plugin->Log("Using code from H. Seib's VstHost and T. Grill's vst~ object\n"); plugin->Log("VST is a trademark of Steinberg Media Technologies GmbH\n"); plugin->Log("VST Plug-In Technology by Steinberg\n"); plugin->Log("============================================================\n"); } char vstplugname[0x100]; strncpy(vstplugname,((STRINGDAT *)p->iplugin)->data, MAXNAME-1); #if WIN32 path_convert(vstplugname); #endif if (plugin->Instantiate(vstplugname)) { return csound->InitError(csound, Str("vstinit: Error loading effect.")); csound->LongJmp(csound, 1); } plugin->Init(); if (*p->iverbose) { plugin->Info(); } return OK; } static int vstinfo(CSOUND *csound, void *data) { VSTINFO *p = (VSTINFO *) data; vstPlugins_t *vstPlugins = 0; csound::QueryGlobalPointer(csound, "vstPlugins", vstPlugins); VSTPlugin *plugin = (*vstPlugins)[(size_t) *p->iVSThandle]; plugin->Info(); return OK; } static int vstaudio_init(CSOUND *csound, void *data) { VSTAUDIO *p = (VSTAUDIO *) data; p->opcodeInChannels = (size_t) (csound->GetInputArgCnt(data) - 1); if (p->opcodeInChannels > 32) { return csound->InitError(csound, Str("vstaudio: too many input args")); } vstPlugins_t *vstPlugins = 0; csound::QueryGlobalPointer(csound, "vstPlugins", vstPlugins); VSTPlugin *plugin = (*vstPlugins)[(size_t) *p->iVSThandle]; p->vstplugin = plugin; plugin->Debug("vstaudio_init.\n"); p->framesPerBlock = csound->GetKsmps(csound); p->pluginInChannels = (size_t) plugin->getNumInputs(); p->pluginOutChannels = (size_t) plugin->getNumOutputs(); p->opcodeOutChannels = (size_t) csound->GetOutputArgCnt(data); return OK; } static int vstaudio(CSOUND *csound, void *data) { VSTAUDIO *p = (VSTAUDIO *) data; size_t i, j; VSTPlugin *plugin = p->vstplugin; uint32_t offset = p->h.insdshead->ksmps_offset; for(j=0; j < p->pluginOutChannels; j++) { memset(p->aouts[j], '\0', offset*sizeof(MYFLT)); } // plugin->Debug("vstaudio: plugin %x.\n", plugin); if (!p->h.insdshead->nxtact) { for (j = 0; j < p->pluginInChannels && j < p->opcodeInChannels; j++) for (i = offset; i < p->framesPerBlock; i++) plugin->inputs_[j][i] = (float) (p->ains[j][i] / csound->Get0dBFS(csound)); for ( ; j < p->pluginInChannels; j++) for (i = 0; i < p->framesPerBlock; i++) { plugin->inputs_[j][i] = 0.0f; } for (j = 0; j < p->pluginOutChannels; j++) for (i = offset; i < p->framesPerBlock; i++) { plugin->outputs_[j][i] = 0.0f; } plugin->process(&plugin->inputs.front(), &plugin->outputs.front(), p->framesPerBlock); for (j = 0; j < p->pluginOutChannels && j < p->opcodeOutChannels; j++) for (i = offset; i < p->framesPerBlock; i++) { p->aouts[j][i] = (MYFLT) plugin->outputs_[j][i] * csound->Get0dBFS(csound); } for ( ; j < p->opcodeOutChannels; j++) for (i = 0; i < p->framesPerBlock; i++) { p->aouts[j][i] = FL(0.0); } } else { for (j = 0; j < p->opcodeInChannels && j < p->opcodeOutChannels; j++) for (i = offset; i < p->framesPerBlock; i++) { p->aouts[j][i] = p->ains[j][i]; } for ( ; j < p->opcodeOutChannels; j++) for (i = 0; i < p->framesPerBlock; i++) { p->aouts[j][i] = FL(0.0); } } return OK; } static int vstaudiog(CSOUND *csound, void *data) { VSTAUDIO *p = (VSTAUDIO *) data; VSTPlugin *plugin = p->vstplugin; size_t i, j; uint32_t offset = p->h.insdshead->ksmps_offset; for(j=0; j < p->pluginOutChannels; j++) { memset(p->aouts[j], '\0', offset*sizeof(MYFLT)); } for (j = 0; j < p->pluginInChannels && j < p->opcodeInChannels; j++) for (i = offset; i < p->framesPerBlock; i++) plugin->inputs_[j][i] = (float) (p->ains[j][i] / csound->Get0dBFS(csound)); for ( ; j < p->pluginInChannels; j++) for (i = 0; i < p->framesPerBlock; i++) { plugin->inputs_[j][i] = 0.0f; } for (j = 0; j < p->pluginOutChannels; j++) for (i = offset; i < p->framesPerBlock; i++) { plugin->outputs_[j][i] = 0.0f; } plugin->process(&plugin->inputs.front(), &plugin->outputs.front(), p->framesPerBlock); for (j = 0; j < p->pluginOutChannels && j < p->opcodeOutChannels; j++) for (i = offset; i < p->framesPerBlock; i++) { p->aouts[j][i] = (MYFLT) plugin->outputs_[j][i] * csound->Get0dBFS(csound); } for ( ; j < p->opcodeOutChannels; j++) for (i = 0; i < p->framesPerBlock; i++) { p->aouts[j][i] = FL(0.0); } return OK; } static int vstmidiout_init(CSOUND *csound, void *data) { VSTMIDIOUT *p = (VSTMIDIOUT *) data; vstPlugins_t *vstPlugins = 0; csound::QueryGlobalPointer(csound, "vstPlugins", vstPlugins); VSTPlugin *plugin = (*vstPlugins)[(size_t) *p->iVSThandle]; p->vstplugin = plugin; plugin->Debug("vstmidiout_init.\n"); p->prvMidiData = 0; return OK; } static int vstmidiout(CSOUND *csound, void *data) { VSTMIDIOUT *p = (VSTMIDIOUT *) data; VSTPlugin *plugin = p->vstplugin; int st, ch, d1, d2, midiData; st = (int) *(p->kstatus); if (st < 128 || st >= 240) { p->prvMidiData = 0; return OK; } ch = (int) *(p->kchan) & 15; if ((st & 15) > ch) { ch = st & 15; } st &= 240; d1 = (int) *(p->kdata1); if (st != 192 && st != 208) { d2 = (int) *(p->kdata2); if (st == 224) { d2 += ((d1 >> 7) & 127); d1 &= 127; } d2 = (d2 >= 0 ? (d2 < 128 ? d2 : 127) : 0); } else { d2 = 0; } d1 = (d1 >= 0 ? (d1 < 128 ? d1 : 127) : 0); midiData = st | ch | (d1 << 8) | (d2 << 16); if (midiData == p->prvMidiData) { return OK; } p->prvMidiData = midiData; plugin->Debug("vstmidiout. kstatus = %i kdata1 = %i kdata2 = %i" "--- mididata = %i\n", (int) *(p->kstatus), (int) *(p->kdata1), (int) *(p->kdata2), midiData); plugin->AddMIDI(midiData, 0, 0); return OK; } static int vstparamget_init(CSOUND *csound, void *data) { VSTPARAMGET *p = (VSTPARAMGET *) data; vstPlugins_t *vstPlugins = 0; csound::QueryGlobalPointer(csound, "vstPlugins", vstPlugins); VSTPlugin *plugin = (*vstPlugins)[(size_t) *p->iVSThandle]; p->vstplugin = plugin; return OK; } static int vstparamget(CSOUND *csound, void *data) { VSTPARAMGET *p = (VSTPARAMGET *) data; VSTPlugin *plugin = p->vstplugin; plugin->Debug("vstparamset(%d).\n", int(*p->kparam)); *p->kvalue = plugin->GetParamValue(int(*p->kparam)); if (*(p->kvalue) == FL(-1.0)) { plugin->Log("Invalid parameter number %d.\n", int(*p->kparam)); } return OK; } static int vstparamset_init(CSOUND *csound, void *data) { VSTPARAMSET *p = (VSTPARAMSET *) data; vstPlugins_t *vstPlugins = 0; csound::QueryGlobalPointer(csound, "vstPlugins", vstPlugins); VSTPlugin *plugin = (*vstPlugins)[(size_t) *p->iVSThandle]; p->vstplugin = plugin; plugin->Debug("vstparamset_init.\n"); p->oldkparam = 0; p->oldkvalue = 0; return OK; } static int vstparamset(CSOUND *csound, void *data) { VSTPARAMSET *p = (VSTPARAMSET *) data; VSTPlugin *plugin = p->vstplugin; if (*p->kparam == p->oldkparam && *p->kvalue == p->oldkvalue) { return OK; } p->oldkparam = *p->kparam; p->oldkvalue = *p->kvalue; plugin->Debug("vstsend(%d, %f).\n", int(*p->kparam), *p->kvalue); plugin->SetParameter(int(*p->kparam), float(*p->kvalue)); return OK; } static int vstbankload(CSOUND *csound, void *data) { VSTBANKLOAD *p = (VSTBANKLOAD *) data; vstPlugins_t *vstPlugins = 0; csound::QueryGlobalPointer(csound, "vstPlugins", vstPlugins); VSTPlugin *plugin = (*vstPlugins)[(size_t) *p->iVSThandle]; p->vstplugin = plugin; void *dummyPointer = 0; CFxBank fxBank((char *) p->ibank); /* load the bank */ plugin->Dispatch(effBeginLoadBank, 0, 0, (VstPatchChunkInfo *) fxBank.GetChunk(), 0); if (plugin->Dispatch(effBeginLoadBank, 0, 0, (VstPatchChunkInfo *) fxBank.GetChunk(), 0)) { return csound->InitError(csound, Str("Error: BeginLoadBank.")); } if (fxBank.IsLoaded()) { if (plugin->aeffect->uniqueID != fxBank.GetFxID()) { return csound->InitError(csound, Str("Loaded bank ID doesn't match plug-in ID.")); } if (fxBank.IsChunk()) { if (!(plugin->aeffect->flags & effFlagsProgramChunks)) { return csound->InitError(csound, Str("Loaded bank contains a chunk format " "that the effect cannot handle.")); } plugin->Dispatch(effSetChunk, 0, fxBank.GetChunkSize(), fxBank.GetChunk(), 0); // isPreset = 0 plugin->Log("Chunks loaded OK.\n"); } else { int cProg = plugin->Dispatch(effGetProgram, 0, 0, dummyPointer, 0); int i, j; int nParms = fxBank.GetNumParams(); for (i = 0; i < fxBank.GetNumPrograms(); i++) { plugin->Dispatch(effSetProgram, 0, i, dummyPointer, 0); plugin->Dispatch(effSetProgramName, 0, 0, fxBank.GetProgramName(i), 0); for (j = 0; j < nParms; j++) { plugin->SetParameter(j, fxBank.GetProgParm(i, j)); } } plugin->Dispatch(effSetProgram, 0, cProg, dummyPointer, 0); } } else { return csound->InitError(csound, Str("Problem loading bank.")); /* check if error loading */ } plugin->Log("Bank loaded OK.\n"); return OK; } static int vstprogset(CSOUND *csound, void *data) { // The changes here are part of an attempt to map 0 to 1 and others VSTPROGSET *p = (VSTPROGSET *) data; vstPlugins_t *vstPlugins = 0; csound::QueryGlobalPointer(csound, "vstPlugins", vstPlugins); VSTPlugin *plugin = (*vstPlugins)[(size_t) *p->iVSThandle]; p->vstplugin = plugin; int program = (int)*p->iprogram; if (program<=0) { csound->Message(csound, Str("VSTprogset: Program %d treated as 1\n"), program); program = 1; } plugin->SetCurrentProgram(program); return OK; } static int vstedit_init(CSOUND *csound, void *data) { VSTEDIT *p = (VSTEDIT *) data; vstPlugins_t *vstPlugins = 0; csound::QueryGlobalPointer(csound, "vstPlugins", vstPlugins); VSTPlugin *plugin = (*vstPlugins)[(size_t) *p->iVSThandle]; p->vstplugin = plugin; plugin->OpenEditor(); //~ vstPlugEditors->push_back(plugin); //gab return OK; } static int vstSetTempo(CSOUND *csound, void *data) { VSTTEMPO *p = (VSTTEMPO *)data; vstPlugins_t *vstPlugins = 0; csound::QueryGlobalPointer(csound, "vstPlugins", vstPlugins); VSTPlugin *plugin = (*vstPlugins)[(size_t) *p->iVSThandle]; p->vstplugin = plugin; plugin->vstTimeInfo.tempo = *p->tempo; return OK; } int vstbanksave(CSOUND *csound, void *data) { VSTBANKLOAD *p = (VSTBANKLOAD *)data; vstPlugins_t *vstPlugins = 0; csound::QueryGlobalPointer(csound, "vstPlugins", vstPlugins); VSTPlugin *plugin = (*vstPlugins)[(size_t) *p->iVSThandle]; p->vstplugin = plugin; char bankname[512]; //gab strcpy(bankname, (char *) p->ibank); /* use that */ if (!plugin) { return NOTOK; } CFxBank b; if (plugin->aeffect->flags & effFlagsProgramChunks) { void * pChunk; int lSize = plugin->EffGetChunk(&pChunk); if (lSize) { b.SetSize(lSize); } if (b.IsLoaded()) { b.SetChunk(pChunk); } } else { b.SetSize(plugin->aeffect->numPrograms, plugin->aeffect->numParams); if (b.IsLoaded()) { int i, j; int cProg = plugin->EffGetProgram(); int nParms = b.GetNumParams(); for (i = 0; i < b.GetNumPrograms(); i++) { plugin->EffSetProgram(i); char szName[128]; plugin->EffGetProgramName(szName); b.SetProgramName(i, szName); for (j = 0; j < nParms; j++) b.SetProgParm(i, j, plugin->aeffect->getParameter(plugin->aeffect,j)); } plugin->EffSetProgram(cProg); } } if (!b.IsLoaded()) { plugin->Log("Error: Memory Allocation Error.\n"); return NOTOK; } b.SetFxID(plugin->aeffect->uniqueID); b.SetFxVersion(plugin->aeffect->version); if (b.SaveBank(bankname)) { plugin->Log("%s Bank saved OK.\n",bankname); } else { plugin->Log("Error: Error saving file\n"); return NOTOK; } return OK; } #ifdef WIN32 static void path_convert(char *in) { for (int i = 0; in[i] != '\0'; i++) { if (in[i] == '/') { in[i] = '\\'; } } } #endif typedef struct VSTNOTEOUT_ { OPDS h; MYFLT *iVSThandle; MYFLT *iChannel; MYFLT *iKey; MYFLT *iVelocity; MYFLT *iDuration; MYFLT startTime; MYFLT offTime; int channel; int key; int velocity; int on; VSTPlugin *vstplugin; } VSTNOTEOUT; static int vstnote_init(CSOUND *csound, void *data) { VSTNOTEOUT *p = (VSTNOTEOUT *)data; vstPlugins_t *vstPlugins = 0; csound::QueryGlobalPointer(csound, "vstPlugins", vstPlugins); VSTPlugin *plugin = (*vstPlugins)[(size_t) *p->iVSThandle]; p->vstplugin = plugin; p->startTime = getCurrentTime(csound); double onTime = double(p->h.insdshead->p2.value); double deltaTime = onTime - getCurrentTime(csound); int deltaFrames = 0; if (deltaTime > 0) { deltaFrames = int(deltaTime / csound->GetSr(csound)); } // Use the warped p3 to schedule the note off message. if (*p->iDuration > FL(0.0)) { p->offTime = p->startTime + double(p->h.insdshead->p3.value); // In case of real-time performance with indefinite p3... } else if (*p->iDuration == FL(0.0)) { if (csound->GetDebug(csound)) { csound->Message(csound, Str("vstnote_init: not scheduling 0 duration note.\n")); } return OK; } else { p->offTime = p->startTime + FL(1000000.0); } p->channel = int(*p->iChannel) & 0xf; // Split the real-valued MIDI key number // into an integer key number and an integer number of cents (plus or // minus 50 cents). p->key = int(double(*p->iKey) + 0.5); int cents = int( ( ( double(*p->iKey) - double(p->key) ) * double(100.0) ) + double(0.5) ); p->velocity = int(*p->iVelocity) & 0x7f; p->vstplugin->AddMIDI(144 | p->channel | (p->key << 8) | (p->velocity << 16), deltaFrames, cents); // Ensure that the opcode instance is still active when we are scheduled // to turn the note off! p->h.insdshead->xtratim = p->h.insdshead->xtratim + 2; p->on = true; if (csound->GetDebug(csound)) { csound->Message(csound, "vstnote_init: on time: %f\n", onTime); csound->Message(csound, " csound time: %f\n", getCurrentTime(csound)); csound->Message(csound, " delta time: %f\n", deltaTime); csound->Message(csound, " delta frames: %d\n", deltaFrames); csound->Message(csound, " off time: %f\n", p->offTime); csound->Message(csound, " channel: %d\n", p->channel); csound->Message(csound, " key: %d\n", p->key); csound->Message(csound, " cents: %d\n", cents); csound->Message(csound, " velocity: %d\n", p->velocity); } return OK; } static int vstnote_perf(CSOUND *csound, void *data) { VSTNOTEOUT *p = (VSTNOTEOUT *)data; if (p->on) { if (getCurrentTime(csound) >= p->offTime || p->h.insdshead->relesing) { // The note may be scheduled to turn off // some frames after the actual start of this kperiod. double deltaTime = p->offTime - getCurrentTime(csound); int deltaFrames = 0; if (deltaTime > 0) { deltaFrames = int(deltaTime / csound->GetSr(csound)); } p->vstplugin->AddMIDI(128 | p->channel | (p->key << 8) | (0 << 16), deltaFrames, 0); p->on = false; if (csound->GetDebug(csound)) { csound->Message(csound, "vstnote_perf: csound time: %f\n", getCurrentTime(csound)); csound->Message(csound, " off time: %f\n", p->offTime); csound->Message(csound, " delta time: %f\n", deltaTime); csound->Message(csound, " delta frames: %d\n", deltaFrames); csound->Message(csound, " channel: %d\n", p->channel); csound->Message(csound, " key: %d\n", p->key); } } } return OK; } static OENTRY localops[] = { { "vstinit", sizeof(VSTINIT), 0, 1, "i", "To", &vstinit, 0, 0 }, { "vstinfo", sizeof(VSTINFO), 0, 1, "", "i", &vstinfo, 0, 0 }, { "vstaudio", sizeof(VSTAUDIO), 0, 5, "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", "iy", &vstaudio_init, 0, &vstaudio }, { "vstaudiog", sizeof(VSTAUDIO), 0, 5, "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", "iy", &vstaudio_init, 0, &vstaudiog }, { "vstmidiout", sizeof(VSTMIDIOUT), 0, 3, "", "ikkkk", &vstmidiout_init, &vstmidiout, 0 }, { "vstparamget", sizeof(VSTPARAMGET),0, 3, "k", "ik", &vstparamget_init, &vstparamget, 0 }, { "vstparamset", sizeof(VSTPARAMSET),0, 3, "", "ikk", &vstparamset_init, &vstparamset, 0 }, { "vstbankload", sizeof(VSTBANKLOAD),0, 1, "", "iT", &vstbankload, 0, 0 }, { "vstprogset", sizeof(VSTPROGSET), 0, 1, "", "ii", &vstprogset, 0, 0 }, { "vstedit", sizeof(VSTEDIT), 0, 1, "", "i", &vstedit_init, 0, 0 }, { "vsttempo", sizeof(VSTTEMPO), 0, 2, "", "ki", 0, &vstSetTempo, 0/*, &vstedit_deinit*/ }, { "vstnote", sizeof(VSTNOTEOUT), 0, 3, "", "iiiii", &vstnote_init, &vstnote_perf, 0 }, { "vstbanksave", sizeof(VSTBANKLOAD),0, 1, "", "iT", &vstbanksave, 0, 0 }, { 0, 0, 0, 0, 0, 0, (SUBR) 0, (SUBR) 0, (SUBR) 0 } }; PUBLIC int csoundModuleCreate(CSOUND *csound) { // It is necessary to store global references to plugins and editors from Seib's code // so that their memory can be freed when the opcode module is destroyed. #if defined(CSOUND_LIFECYCLE_DEBUG) csound->Message(csound, "csoundModuleCreate: csound: %p thread: %d\n", csound, syscall(SYS_gettid)); #endif int result = 0; vstPlugins_t *vstPlugins = new vstPlugins_t; result = csound::CreateGlobalPointer (csound, "vstPlugins", vstPlugins); return 0; } PUBLIC int csoundModuleInit(CSOUND *csound) { #if defined(CSOUND_LIFECYCLE_DEBUG) csound->Message(csound, "csoundModuleInit: csound: %p thread: %d\n", csound, syscall(SYS_gettid)); #endif OENTRY *ep = (OENTRY *) &(localops[0]); int err = 0; while (ep->opname != NULL) { err |= csound->AppendOpcode(csound, ep->opname, ep->dsblksiz, ep->flags, ep->thread, ep->outypes, ep->intypes, (int (*)(CSOUND *, void *)) ep->iopadr, (int (*)(CSOUND *, void *)) ep->kopadr, (int (*)(CSOUND *, void *)) ep->aopadr); ep++; } return err; } PUBLIC int csoundModuleDestroy(CSOUND *csound) { #if defined(CSOUND_LIFECYCLE_DEBUG) csound->Message(csound, "csoundModuleDestroy: csound: %p thread: %d\n", csound, syscall(SYS_gettid)); #endif vstPlugins_t *vstPlugins = 0; csound::QueryGlobalPointer(csound, "vstPlugins", vstPlugins); for (size_t i = 0, n = vstPlugins->size(); i < n; ++i) { if ((*vstPlugins)[i]) { delete (*vstPlugins)[i]; } vstPlugins->clear(); } delete vstPlugins; vstPlugins = 0; //~ vstPlugins_t *vstPlugEditors = 0; //~ csound::QueryGlobalPointer(csound, "vstPlugEditors", vstPlugEditors); //~ for (size_t i = 0, n = vstPlugEditors->size(); i < n; ++i) { //~ if ((*vstPlugEditors)[i]) { //~ delete (*vstPlugEditors)[i]; //~ } //~ vstPlugEditors->clear(); //~ } //~ delete vstPlugEditors; //~ vstPlugEditors = 0; return 0; } } // extern "C" csound-6.10.0/Opcodes/vst4cs/src/vst4cs.h000066400000000000000000000116511321653344700201150ustar00rootroot00000000000000// vst4cs: VST HOST OPCODES FOR CSOUND // // Uses code by Hermann Seib from his VSTHost program and from the vst~ // object by Thomas Grill (no license), which in turn borrows from the Psycle // tracker (also based on VSTHost). // // VST is a trademark of Steinberg Media Technologies GmbH. // VST Plug-In Technology by Steinberg. // // Copyright (C) 2004 Andres Cabrera, Michael Gogins // // The vst4cs library is free software; you can redistribute it // and/or modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // The vst4cs library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with The vst4cs library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA // 02111-1307 USA // // Linking vst4cs statically or dynamically with other modules is making a // combined work based on vst4cs. Thus, the terms and conditions of the GNU // Lesser General Public License cover the whole combination. // // In addition, as a special exception, the copyright holders of vst4cs, // including the Csound developers and Hermann Seib, the original author of // VSTHost, give you permission to combine vst4cs with free software programs // or libraries that are released under the GNU LGPL and with code included // in the standard release of the VST SDK version 2 under the terms of the // license stated in the VST SDK version 2 files. You may copy and distribute // such a system following the terms of the GNU LGPL for vst4cs and the // licenses of the other code concerned. The source code for the VST SDK // version 2 is available in the VST SDK hosted at // https://github.com/steinbergmedia/vst3sdk. // // Note that people who make modified versions of vst4cs are not obligated to // grant this special exception for their modified versions; it is their // choice whether to do so. The GNU Lesser General Public License gives // permission to release a modified version without this exception; this // exception also makes it possible to release a modified version which // carries forward this exception. #ifndef VST4CS_H #define VST4CS_H #include "csdl.h" class VSTPlugin; // In all of these, sizeof(MYFLT) is not necessarily equal to or greater than // sizeof(VSTPlugin *), hence type casting can not be used and a table of // handles must be used. typedef struct VSTINIT_ { OPDS h; // Inputs. MYFLT *iVSThandle; MYFLT *iplugin; MYFLT *iverbose; // State. VSTPlugin *vstplugin; } VSTINIT; typedef struct VSTINFO_ { OPDS h; // Inputs. MYFLT *iVSThandle; // State. VSTPlugin *vstplugin; } VSTINFO; typedef struct VSTAUDIO_ { OPDS h; // Outputs. MYFLT *aouts[32]; // Inputs. MYFLT *iVSThandle; MYFLT *ains[32]; // State. size_t framesPerBlock; size_t pluginInChannels; size_t pluginOutChannels; size_t opcodeInChannels; size_t opcodeOutChannels; VSTPlugin *vstplugin; } VSTAUDIO; typedef struct VSTNOTE_ { OPDS h; // Inputs. MYFLT *iVSThandle; MYFLT *kchan; MYFLT *knote; MYFLT *kveloc; MYFLT *kdur; // State. size_t vstHandle; int chn; int note; size_t framesRemaining; VSTPlugin *vstplugin; } VSTNOTE; typedef struct VSTMIDIOUT_ { OPDS h; // Inputs. MYFLT *iVSThandle; MYFLT *kstatus; MYFLT *kchan; MYFLT *kdata1; MYFLT *kdata2; // State. size_t vstHandle; int prvMidiData; VSTPlugin *vstplugin; } VSTMIDIOUT; typedef struct VSTPARAMGET_ { OPDS h; // Outputs. MYFLT *kvalue; // Intputs. MYFLT *iVSThandle; MYFLT *kparam; // State. VSTPlugin *vstplugin; } VSTPARAMGET; typedef struct VSTPARAMSET_ { OPDS h; // Inputs. MYFLT *iVSThandle; MYFLT *kparam; MYFLT *kvalue; // State. MYFLT oldkparam; MYFLT oldkvalue; VSTPlugin *vstplugin; } VSTPARAMSET; typedef struct VSTBANKLOAD_ { OPDS h; // Inputs. MYFLT *iVSThandle; MYFLT *ibank; // State. VSTPlugin *vstplugin; } VSTBANKLOAD; typedef struct VSTPROGSET_ { OPDS h; // Inputs. MYFLT *iVSThandle; MYFLT *iprogram; // State. VSTPlugin *vstplugin; } VSTPROGSET; typedef struct VSTEDIT_ { OPDS h; // Inputs. MYFLT *iVSThandle; // State. VSTPlugin *vstplugin; } VSTEDIT; typedef struct VSTTEMPO_ { //gab OPDS h; // Inputs. MYFLT *tempo; MYFLT *iVSThandle; // State. VSTPlugin *vstplugin; } VSTTEMPO; #endif csound-6.10.0/Opcodes/vst4cs/src/vsthost.cpp000066400000000000000000001245751321653344700207460ustar00rootroot00000000000000// vst4cs: VST HOST OPCODES FOR CSOUND // // Uses code by Hermann Seib from his VSTHost program and from the vst~ // object by Thomas Grill (no license), which in turn borrows from the Psycle // tracker (also based on VSTHost). // // VST is a trademark of Steinberg Media Technologies GmbH. // VST Plug-In Technology by Steinberg. // // Copyright (C) 2004 Andres Cabrera, Michael Gogins // // The vst4cs library is free software; you can redistribute it // and/or modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // The vst4cs library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with The vst4cs library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA // 02111-1307 USA // // Linking vst4cs statically or dynamically with other modules is making a // combined work based on vst4cs. Thus, the terms and conditions of the GNU // Lesser General Public License cover the whole combination. // // In addition, as a special exception, the copyright holders of vst4cs, // including the Csound developers and Hermann Seib, the original author of // VSTHost, give you permission to combine vst4cs with free software programs // or libraries that are released under the GNU LGPL and with code included // in the standard release of the VST SDK version 2 under the terms of the // license stated in the VST SDK version 2 files. You may copy and distribute // such a system following the terms of the GNU LGPL for vst4cs and the // licenses of the other code concerned. The source code for the VST SDK // version 2 is available in the VST SDK hosted at // https://github.com/steinbergmedia/vst3sdk. // // Note that people who make modified versions of vst4cs are not obligated to // grant this special exception for their modified versions; it is their // choice whether to do so. The GNU Lesser General Public License gives // permission to release a modified version without this exception; this // exception also makes it possible to release a modified version which // carries forward this exception. #include "vsthost.h" #include #include #include #include #ifdef WIN32 #pragma GCC diagnostic ignored "-fpermissive" #endif #ifdef __MACH__ #include #include #include #endif #ifdef MSVC #pragma warning(disable:4786) //gab #define round int #endif void VSTPlugin::initializeOpcodes() { static bool opcodes_initialized = false; if (opcodes_initialized) { return; } opcodes_initialized = true; dispatchOpcodes().insert(std::pair((long) effOpen, "effOpen")); dispatchOpcodes().insert(std::pair((long) effClose, "effClose")); dispatchOpcodes().insert(std::pair((long) effSetProgram, "effSetProgram")); dispatchOpcodes().insert(std::pair((long) effGetProgram, "effGetProgram")); dispatchOpcodes().insert(std::pair((long) effSetProgramName, "effSetProgramName")); dispatchOpcodes().insert(std::pair((long) effGetProgramName, "effGetProgramName")); dispatchOpcodes().insert(std::pair((long) effGetParamLabel, "effGetParamLabel")); dispatchOpcodes().insert(std::pair((long) effGetParamDisplay, "effGetParamDisplay")); dispatchOpcodes().insert(std::pair((long) effGetParamName, "effGetParamName")); dispatchOpcodes().insert(std::pair((long) effGetVu, "effGetVu")); dispatchOpcodes().insert(std::pair((long) effSetSampleRate, "effSetSampleRate")); dispatchOpcodes().insert(std::pair((long) effSetBlockSize, "effSetBlockSize")); dispatchOpcodes().insert(std::pair((long) effMainsChanged, "effMainsChanged")); dispatchOpcodes().insert(std::pair((long) effEditGetRect, "effEditGetRect")); dispatchOpcodes().insert(std::pair((long) effEditOpen, "effEditOpen")); dispatchOpcodes().insert(std::pair((long) effEditClose, "effEditClose")); dispatchOpcodes().insert(std::pair((long) effEditDraw, "effEditDraw")); dispatchOpcodes().insert(std::pair((long) effEditMouse, "effEditMouse")); dispatchOpcodes().insert(std::pair((long) effEditKey, "effEditKey")); dispatchOpcodes().insert(std::pair((long) effEditIdle, "effEditIdle")); dispatchOpcodes().insert(std::pair((long) effEditTop, "effEditTop")); dispatchOpcodes().insert(std::pair((long) effEditSleep, "effEditSleep")); dispatchOpcodes().insert(std::pair((long) effIdentify, "effIdentify")); dispatchOpcodes().insert(std::pair((long) effGetChunk, "effGetChunk")); dispatchOpcodes().insert(std::pair((long) effSetChunk, "effSetChunk")); dispatchOpcodes().insert(std::pair((long) effProcessEvents, "effProcessEvents")); dispatchOpcodes().insert(std::pair((long) effCanBeAutomated, "effCanBeAutomated")); dispatchOpcodes().insert(std::pair((long) effString2Parameter, "effString2Parameter")); dispatchOpcodes().insert(std::pair((long) effGetNumProgramCategories, "effGetNumProgramCategories")); dispatchOpcodes().insert(std::pair((long) effGetProgramNameIndexed, "effGetProgramNameIndexed")); dispatchOpcodes().insert(std::pair((long) effCopyProgram, "effCopyProgram")); dispatchOpcodes().insert(std::pair((long) effConnectInput, "effConnectInput")); dispatchOpcodes().insert(std::pair((long) effConnectOutput, "effConnectOutput")); dispatchOpcodes().insert(std::pair((long) effGetInputProperties, "effGetInputProperties")); dispatchOpcodes().insert(std::pair((long) effGetOutputProperties, "effGetOutputProperties")); dispatchOpcodes().insert(std::pair((long) effGetPlugCategory, "effGetPlugCategory")); dispatchOpcodes().insert(std::pair((long) effGetCurrentPosition, "effGetCurrentPosition")); dispatchOpcodes().insert(std::pair((long) effGetDestinationBuffer, "effGetDestinationBuffer")); dispatchOpcodes().insert(std::pair((long) effOfflineNotify, "effOfflineNotify")); dispatchOpcodes().insert(std::pair((long) effOfflinePrepare, "effOfflinePrepare")); dispatchOpcodes().insert(std::pair((long) effOfflineRun, "effOfflineRun")); dispatchOpcodes().insert(std::pair((long) effProcessVarIo, "effProcessVarIo")); dispatchOpcodes().insert(std::pair((long) effSetSpeakerArrangement, "effSetSpeakerArrangement")); dispatchOpcodes().insert(std::pair((long) effSetBlockSizeAndSampleRate, "effSetBlockSizeAndSampleRate")); dispatchOpcodes().insert(std::pair((long) effSetBypass, "effSetBypass")); dispatchOpcodes().insert(std::pair((long) effGetEffectName, "effGetEffectName")); dispatchOpcodes().insert(std::pair((long) effGetErrorText, "effGetErrorText")); dispatchOpcodes().insert(std::pair((long) effGetVendorString, "effGetVendorString")); dispatchOpcodes().insert(std::pair((long) effGetProductString, "effGetProductString")); dispatchOpcodes().insert(std::pair((long) effGetVendorVersion, "effGetVendorVersion")); dispatchOpcodes().insert(std::pair((long) effVendorSpecific, "effVendorSpecific")); dispatchOpcodes().insert(std::pair((long) effCanDo, "effCanDo")); dispatchOpcodes().insert(std::pair((long) effGetTailSize, "effGetTailSize")); dispatchOpcodes().insert(std::pair((long) effIdle, "effIdle")); dispatchOpcodes().insert(std::pair((long) effGetIcon, "effGetIcon")); dispatchOpcodes().insert(std::pair((long) effSetViewPosition, "effSetViewPosition")); dispatchOpcodes().insert(std::pair((long) effGetParameterProperties, "effGetParameterProperties")); dispatchOpcodes().insert(std::pair((long) effKeysRequired, "effKeysRequired")); dispatchOpcodes().insert(std::pair((long) effGetVstVersion, "effGetVstVersion")); dispatchOpcodes().insert(std::pair((long) effEditKeyDown, "effEditKeyDown")); dispatchOpcodes().insert(std::pair((long) effEditKeyUp, "effEditKeyUp")); dispatchOpcodes().insert(std::pair((long) effSetEditKnobMode, "effSetEditKnobMode")); dispatchOpcodes().insert(std::pair((long) effGetMidiProgramName, "effGetMidiProgramName")); dispatchOpcodes().insert(std::pair((long) effGetCurrentMidiProgram, "effGetCurrentMidiProgram")); dispatchOpcodes().insert(std::pair((long) effGetMidiProgramCategory, "effGetMidiProgramCategory")); dispatchOpcodes().insert(std::pair((long) effHasMidiProgramsChanged, "effHasMidiProgramsChanged")); dispatchOpcodes().insert(std::pair((long) effGetMidiKeyName, "effGetMidiKeyName")); dispatchOpcodes().insert(std::pair((long) effBeginSetProgram, "effBeginSetProgram")); dispatchOpcodes().insert(std::pair((long) effEndSetProgram, "effEndSetProgram")); dispatchOpcodes().insert(std::pair((long) effGetSpeakerArrangement, "effGetSpeakerArrangement")); dispatchOpcodes().insert(std::pair((long) effShellGetNextPlugin, "effShellGetNextPlugin")); dispatchOpcodes().insert(std::pair((long) effStartProcess, "effStartProcess")); dispatchOpcodes().insert(std::pair((long) effStopProcess, "effStopProcess")); dispatchOpcodes().insert(std::pair((long) effSetTotalSampleToProcess, "effSetTotalSampleToProcess")); dispatchOpcodes().insert(std::pair((long) effSetPanLaw, "effSetPanLaw")); dispatchOpcodes().insert(std::pair((long) effBeginLoadBank, "effBeginLoadBank")); dispatchOpcodes().insert(std::pair((long) effBeginLoadProgram, "effBeginLoadProgram")); masterOpcodes().insert(std::pair((long) audioMasterAutomate, "audioMasterAutomate")); masterOpcodes().insert(std::pair((long) audioMasterVersion, "audioMasterVersion")); masterOpcodes().insert(std::pair((long) audioMasterCurrentId, "audioMasterCurrentId")); masterOpcodes().insert(std::pair((long) audioMasterIdle, "audioMasterIdle")); masterOpcodes().insert(std::pair((long) audioMasterPinConnected, "audioMasterPinConnected")); masterOpcodes().insert(std::pair((long) audioMasterWantMidi, "audioMasterWantMidi")); masterOpcodes().insert(std::pair((long) audioMasterGetTime, "audioMasterGetTime")); masterOpcodes().insert(std::pair((long) audioMasterProcessEvents, "audioMasterProcessEvents")); masterOpcodes().insert(std::pair((long) audioMasterSetTime, "audioMasterSetTime")); masterOpcodes().insert(std::pair((long) audioMasterTempoAt, "audioMasterTempoAt")); masterOpcodes().insert(std::pair( (long)audioMasterGetNumAutomatableParameters, "audioMasterGetNumAutomatableParameters")); masterOpcodes().insert(std::pair((long) audioMasterGetParameterQuantization, "audioMasterGetParameterQuantization")); masterOpcodes().insert(std::pair((long) audioMasterIOChanged, "audioMasterIOChanged")); masterOpcodes().insert(std::pair((long) audioMasterNeedIdle, "audioMasterNeedIdle")); masterOpcodes().insert(std::pair((long) audioMasterSizeWindow, "audioMasterSizeWindow")); masterOpcodes().insert(std::pair((long) audioMasterGetSampleRate, "audioMasterGetSampleRate")); masterOpcodes().insert(std::pair((long) audioMasterGetBlockSize, "audioMasterGetBlockSize")); masterOpcodes().insert(std::pair((long) audioMasterGetInputLatency, "audioMasterGetInputLatency")); masterOpcodes().insert(std::pair((long) audioMasterGetOutputLatency, "audioMasterGetOutputLatency")); masterOpcodes().insert(std::pair((long) audioMasterGetPreviousPlug, "audioMasterGetPreviousPlug")); masterOpcodes().insert(std::pair((long) audioMasterGetNextPlug, "audioMasterGetNextPlug")); masterOpcodes().insert(std::pair((long) audioMasterWillReplaceOrAccumulate, "audioMasterWillReplaceOrAccumulate")); masterOpcodes().insert(std::pair((long) audioMasterGetCurrentProcessLevel, "audioMasterGetCurrentProcessLevel")); masterOpcodes().insert(std::pair((long) audioMasterGetAutomationState, "audioMasterGetAutomationState")); masterOpcodes().insert(std::pair((long) audioMasterOfflineStart, "audioMasterOfflineStart")); masterOpcodes().insert(std::pair((long) audioMasterOfflineRead, "audioMasterOfflineRead")); masterOpcodes().insert(std::pair((long) audioMasterOfflineWrite, "audioMasterOfflineWrite")); masterOpcodes().insert(std::pair((long) audioMasterOfflineGetCurrentPass, "audioMasterOfflineGetCurrentPass")); masterOpcodes().insert(std::pair((long) audioMasterOfflineGetCurrentMetaPass, "audioMasterOfflineGetCurrentMetaPass")); masterOpcodes().insert(std::pair((long) audioMasterSetOutputSampleRate, "audioMasterSetOutputSampleRate")); // masterOpcodes().insert(std::pair( // (long) audioMasterGetSpeakerArrangement, // // "audioMasterGetSpeakerArrangement")); masterOpcodes().insert(std::pair( (long) audioMasterGetOutputSpeakerArrangement, "audioMasterGetOutputSpeakerArrangement")); masterOpcodes().insert(std::pair((long) audioMasterGetVendorString, "audioMasterGetVendorString")); masterOpcodes().insert(std::pair((long) audioMasterGetProductString, "audioMasterGetProductString")); masterOpcodes().insert(std::pair((long) audioMasterGetVendorVersion, "audioMasterGetVendorVersion")); masterOpcodes().insert(std::pair((long) audioMasterVendorSpecific, "audioMasterVendorSpecific")); masterOpcodes().insert(std::pair((long) audioMasterSetIcon, "audioMasterSetIcon")); masterOpcodes().insert(std::pair((long) audioMasterCanDo, "audioMasterCanDo")); masterOpcodes().insert(std::pair((long) audioMasterGetLanguage, "audioMasterGetLanguage")); masterOpcodes().insert(std::pair((long) audioMasterOpenWindow, "audioMasterOpenWindow")); masterOpcodes().insert(std::pair((long) audioMasterCloseWindow, "audioMasterCloseWindow")); masterOpcodes().insert(std::pair((long) audioMasterGetDirectory, "audioMasterGetDirectory")); masterOpcodes().insert(std::pair((long) audioMasterUpdateDisplay, "audioMasterUpdateDisplay")); masterOpcodes().insert(std::pair((long) audioMasterBeginEdit, "audioMasterBeginEdit")); masterOpcodes().insert(std::pair((long) audioMasterEndEdit, "audioMasterEndEdit")); masterOpcodes().insert(std::pair((long) audioMasterOpenFileSelector, "audioMasterOpenFileSelector")); masterOpcodes().insert(std::pair((long) audioMasterCloseFileSelector, "audioMasterCloseFileSelector")); masterOpcodes().insert(std::pair((long) audioMasterEditFile, "audioMasterEditFile")); masterOpcodes().insert(std::pair((long) audioMasterGetChunkFile, "audioMasterGetChunkFile")); masterOpcodes().insert(std::pair((long)audioMasterGetInputSpeakerArrangement, "audioMasterGetInputSpeakerArrangement")); } VSTPlugin::VSTPlugin(CSOUND *csound_) : csound(csound_), libraryHandle(0), aeffect(0), hasEditor(false), editor(0), window(0), windowHandle(0), pluginIsSynth(true), overwrite(false), edited(false), showParameters(false), framesPerSecond(0), framesPerBlock(0) { memset(&vstTimeInfo, 0, sizeof(VstTimeInfo)); framesPerSecond = (float) csound->GetSr(csound); initializeOpcodes(); } VSTPlugin::~VSTPlugin() { Free(); } bool VSTPlugin::AddMIDI(int data, int deltaFrames, int detune) { if (!aeffect) return false; vstMidiEvents.resize(vstMidiEvents.size() + 1); VstMidiEvent &vstMidiEvent = vstMidiEvents.back(); vstMidiEvent.type = kVstMidiType; vstMidiEvent.byteSize = 24; vstMidiEvent.deltaFrames = deltaFrames; vstMidiEvent.flags = 0; vstMidiEvent.detune = detune; vstMidiEvent.noteLength = 0; vstMidiEvent.noteOffset = 0; vstMidiEvent.reserved1 = 0; vstMidiEvent.reserved2 = 0; vstMidiEvent.noteOffVelocity = 0; vstMidiEvent.midiData[0] = data & 255; if ((data & 240) == 144) { if (!(data & (int) 0x7F0000)) { vstMidiEvent.midiData[0] -= 16; data |= (int) 0x400000; } } vstMidiEvent.midiData[1] = (data >> 8) & 127; vstMidiEvent.midiData[2] = (data >> 16) & 127; vstMidiEvent.midiData[3] = 0; return true; } void VSTPlugin::SendMidi() { if (aeffect && vstMidiEvents.size() > 0) { vstEventsBuffer.resize(sizeof(VstEvents) + (sizeof(VstEvent *) * vstMidiEvents.size())); VstEvents *vstEvents = (VstEvents *) &vstEventsBuffer.front(); vstEvents->numEvents = vstMidiEvents.size(); vstEvents->reserved = 0; for (size_t i = 0, n = vstEvents->numEvents; i < n; i++) { vstEvents->events[i] = (VstEvent *) &vstMidiEvents[i]; Debug("VSTPlugin::SendMidi(queue size %d status %d data1 %d " "data2 %d detune %d delta %d\n", vstEvents->numEvents, ((VstMidiEvent *)vstEvents->events[i])->midiData[0], ((VstMidiEvent *)vstEvents->events[i])->midiData[1], ((VstMidiEvent *)vstEvents->events[i])->midiData[2], ((VstMidiEvent *)vstEvents->events[i])->detune, ((VstMidiEvent *)vstEvents->events[i])->deltaFrames); } Dispatch(effProcessEvents, 0, 0, vstEvents, 0.0f); vstMidiEvents.resize(0); } } bool VSTPlugin::DescribeValue(int parameter, char *value) { Debug("VSTPlugin::DescribeValue.\n"); if (aeffect) { if (parameter < aeffect->numParams) { char par_display[0x100]; char par_label[0x100]; Dispatch(effGetParamDisplay,parameter,0,par_display,0.0f); Dispatch(effGetParamLabel,parameter,0,par_label,0.0f); strcpy(value, par_display); return true; } } return false; } int VSTPlugin::Instantiate(const char *libraryName_) { Debug("VSTPlugin::Instance...\n"); #ifdef __MACH__ CFStringRef vstBundlePath = CFStringCreateWithCString(kCFAllocatorDefault, libraryName_, kCFStringEncodingMacRoman ); CFURLRef vstBundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, vstBundlePath, kCFURLPOSIXPathStyle, true); CFBundleRef vstBundle = CFBundleCreate(kCFAllocatorDefault, vstBundleURL); CFRelease(vstBundlePath); CFRelease(vstBundleURL); if (vstBundle == NULL) #else if (csound->OpenLibrary(&libraryHandle, libraryName_) != 0) #endif { Log("WARNING! '%s' was not found or is invalid.\n", libraryName_); return VSTINSTANCE_ERR_NO_VALID_FILE; } Debug("Loaded plugin library '%s'.\n", libraryName_); #ifdef __MACH__ short bundleRes = CFBundleOpenBundleResourceMap(vstBundle); /* For VST SDK 2.4 and later. */ PVSTMAIN main = (PVSTMAIN) CFBundleGetFunctionPointerForName(vstBundle, CFSTR("VSTPluginMain")); /* For VST SDK 2.3 and earlier. */ if (!main) { main = (PVSTMAIN) CFBundleGetFunctionPointerForName(vstBundle, CFSTR("main_macho")); } #else /* For VST SDK 2.4 and later. */ PVSTMAIN main = (PVSTMAIN) csound->GetLibrarySymbol(libraryHandle, "VSTPluginMain"); if (!main) { /* For VST SDK 2.3 and earlier. */ main = (PVSTMAIN) csound->GetLibrarySymbol(libraryHandle, "main"); } #endif if (!main) { Log("Failed to find 'main' function.\n"); csound->CloseLibrary(libraryHandle); aeffect = NULL; return VSTINSTANCE_ERR_NO_VST_PLUGIN; } Debug("Found 'main' function at 0x%x.\n", main); aeffect = main((audioMasterCallback) VSTPlugin::Master); if (!aeffect) { Log("VST plugin: unable to create effect.\n"); csound->CloseLibrary(libraryHandle); return VSTINSTANCE_ERR_REJECTED; } aeffect->user = this; Debug("Created effect '%x'.\n", aeffect); if (aeffect->magic != kEffectMagic) { Log("VST plugin: Instance query rejected by 0x%x\n", aeffect); csound->CloseLibrary(libraryHandle); aeffect = NULL; return VSTINSTANCE_ERR_REJECTED; } if (!Dispatch(effGetProductString, 0, 0, &productName, 0.0f)) { strcpy(productName, libraryName); } return VSTINSTANCE_NO_ERROR; } void VSTPlugin::Info() { int i =0; Log("====================================================\n"); Log("Loaded plugin: %s\n", productName); if (!aeffect->dispatcher(aeffect, effGetVendorString, 0, 0, &vendorName, 0.0f)) { strcpy(vendorName, "Unknown vendor"); } Log("Vendor name: %s \n", vendorName); pluginVersion = aeffect->version; Log("Version: %d \n", pluginVersion); pluginIsSynth = (aeffect->flags & effFlagsIsSynth)?true:false; Log("Is synthesizer? %s\n",(pluginIsSynth==true?"Yes":"No")); overwrite = (aeffect->flags & effFlagsCanReplacing)?true:false; hasEditor = (aeffect->flags & effFlagsHasEditor)?true:false; Log("Number of inputs: %i\n", getNumInputs()); Log("Number of outputs: %i\n", getNumOutputs()); long nparams=NumParameters(); Log("Number of parameters: %d\n",nparams); char buffer[256]; for (i = 0; i < nparams; i++) { strcpy(buffer, "No parameter"); GetParamName(i, buffer); if (strcmp("unused",buffer)==1) Log(" Parameter%5i: %s\n",i, buffer); } csound->Message(csound, "Number of programs: %d\n", (int) aeffect->numPrograms); for (i = 0; i < aeffect->numPrograms; i++) { strcpy(buffer, "No program"); GetProgramName(0, i, buffer); if (strcmp("default",buffer)==1) Log(" Program%7i: %s\n", i, buffer); } csound->Message(csound, "----------------------------------------------------\n"); } int VSTPlugin::getNumInputs(void) { Debug("VSTPlugin::getNumInputs.\n"); return aeffect->numInputs; } int VSTPlugin::getNumOutputs(void) { Debug("VSTPlugin::getNumOutputs.\n"); return aeffect->numOutputs; } void VSTPlugin::Free() // Called also in destruction { Debug("VSTPlugin::Free.\n"); CloseEditor(); if (aeffect) { Dispatch(effMainsChanged, 0, 0, NULL, 0.0f); Dispatch(effClose, 0, 0, NULL, 0.0f); aeffect->user = 0; aeffect = 0; #ifndef __MACH__ csound->CloseLibrary(libraryHandle); #endif libraryHandle = 0; } } void VSTPlugin::Init() { size_t i; Debug("VSTPlugin::Init.\n"); framesPerSecond = (float) csound->GetSr(csound); framesPerBlock = csound->GetKsmps(csound); Log("VSTPlugin::Init framesPerSecond %f framesPerBlock %d " "channels %d in / %d out.\n", framesPerSecond, framesPerBlock, getNumInputs(), getNumOutputs()); inputs_.resize((size_t) getNumInputs()); outputs_.resize((size_t) getNumOutputs()); for (i = 0; i < inputs_.size(); i++) { inputs_[i].resize(framesPerBlock); inputs.push_back(&inputs_[i].front()); } for (i = 0; i < outputs_.size(); i++) { outputs_[i].resize(framesPerBlock); outputs.push_back(&outputs_[i].front()); } Dispatch(effOpen , 0, 0, NULL, 0.0f); Dispatch(effSetProgram , 0, 0, NULL, 0.0f); Dispatch(effSetSampleRate, 0, 0, NULL, framesPerSecond); Dispatch(effSetBlockSize, 0, framesPerBlock, NULL, 0.0f); Dispatch(effMainsChanged, 0, 1, NULL, 0.0f); //Dispatch(effSetBlockSizeAndSampleRate, 0, framesPerBlock, NULL, (float) framesPerSecond); } bool VSTPlugin::SetParameter(int parameter, float value) { Debug("VSTPlugin::SetParameter(%d, %f).\n", parameter, value); if (aeffect) { if ((parameter >= 0) && (parameter <= aeffect->numParams)) { aeffect->setParameter(aeffect, parameter, value); return true; } else return false; } return false; } bool VSTPlugin::SetParameter(int parameter, int value) { Debug("VSTPlugin::SetParameter(%d, %d).\n", parameter, value); return SetParameter(parameter,value/65535.0f); } int VSTPlugin::GetCurrentProgram() { Debug("VSTPlugin::GetCurrentProgram.\n"); if (aeffect) return Dispatch(effGetProgram, 0, 0, NULL, 0.0f); else return 0; } void VSTPlugin::SetCurrentProgram(int prg) { Debug("VSTPlugin::SetCurrentProgram((%d).\n", prg); if (aeffect) Dispatch(effSetProgram, 0, prg, NULL, 0.0f); } bool VSTPlugin::replace() { return overwrite; } void VSTPlugin::EditorIdle() { Dispatch(effEditIdle, 0, 0, windowHandle, 0.0f); } ERect VSTPlugin::GetEditorRect() { ERect *rect_ = 0; Dispatch(effEditGetRect,0,0, &rect_,0.0f); if (rect_) rect = *rect_; else { rect.right = 600; rect.bottom = 400; } return rect; } void VSTPlugin::OpenEditor() { if (windowHandle) return; if (aeffect->flags & effFlagsHasEditor == 1) { GetEditorRect(); Debug("ERect top %d left %d right %d bottom %d.\n", rect.top, rect.left, rect.right, rect.bottom); window = new Fl_Window(rect.right, rect.bottom, GetName()); Debug("Window 0x%x.\n", window); window->show(); #ifdef WIN32 windowHandle = fl_xid(window); Debug("windowHandle 0x%x.\n", windowHandle); SetEditWindow(windowHandle); #elif defined (LINUX) //TODO: Fill appropriate code here // windowHandle = (void *) fl_find(fl_xid(ST(fl_windows)[panelNum].panel)); Log("vstedit not implemented on Linux yet.\n"); #elif defined (MACOSX) //TODO: Fill appropriate code here Log("vstedit not implemented on Mac yet.\n"); #endif } else Log("Plugin:%s has no GUI.\n", productName); } void VSTPlugin::CloseEditor() { if (!windowHandle) return; OnEditorClose(); if (aeffect->flags & effFlagsHasEditor == 1) { OnEditorClose(); //window->hide(); //delete window; //window = 0; windowHandle = 0; } } void VSTPlugin::SetEditWindow(void *h) { windowHandle = h; Dispatch(effEditOpen,0,0, windowHandle,0.0f); } void VSTPlugin::OnEditorClose() { Dispatch(effEditClose,0,0, windowHandle,0.0f); } void VSTPlugin::SetShowParameters(bool s) { showParameters = s; } bool VSTPlugin::ShowParams() { return showParameters; } bool VSTPlugin::GetProgramName(int cat, int parameter, char *buf) { if (aeffect) { if (parameter < NumPrograms()) { Dispatch(effGetProgramNameIndexed, parameter, cat, buf, 0.0f); return true; } } return false; } int VSTPlugin::GetNumCategories() { if (aeffect) return Dispatch(effGetNumProgramCategories, 0, 0, NULL, 0.0f); else return 0; } void VSTPlugin::StopEditing() { edited = false; } void VSTPlugin::Log(const char *format, ...) { va_list args; va_start(args, format); if (csound) { csound->MessageV(csound, 0, format, args); } else { vfprintf(stdout, format, args); } va_end(args); } void VSTPlugin::Debug(const char *format, ...) { va_list args; va_start(args, format); if (csound) { if ((csound->GetMessageLevel(csound) & 7) == 7 || csound->GetDebug(csound)) { csound->MessageV(csound, 0, format, args); } } //else { // vfprintf(stdout, format, args); //} va_end(args); } long VSTPlugin::OnGetVersion(AEffect *effect) { #if defined(VST_2_3_EXTENSIONS) return 2300L; #elif defined(VST_2_2_EXTENSIONS) return 2200L; #elif defined(VST_2_1_EXTENSIONS) return 2100L; #else return 2L; #endif } int VSTPlugin::GetNumParams(void) { return aeffect->numParams; } void VSTPlugin::GetParamName(int numparam, char *name) { if (numparam < aeffect->numParams) Dispatch(effGetParamName, numparam, 0, name, 0.0f); else strcpy(name, "Parameter out of range."); } float VSTPlugin::GetParamValue(int numparam) { if (numparam < aeffect->numParams) return (aeffect->getParameter(aeffect, numparam)); else return -1.0; } char* VSTPlugin::GetName(void) { return productName; } unsigned long VSTPlugin::GetVersion(void) { return pluginVersion; } char* VSTPlugin::GetVendorName(void) { return vendorName; } char* VSTPlugin::GetDllName(void) { return libraryName; } long VSTPlugin::NumParameters(void) { return aeffect->numParams; } float VSTPlugin::GetParameter(long parameter) { return aeffect->getParameter(aeffect, parameter); } int VSTPlugin::NumPrograms(void) { return aeffect->numPrograms; } VstTimeInfo *VSTPlugin::GetTime(void) { Debug("VSGPlugin::GetTime().\n"); if (csound) vstTimeInfo.samplePos = csound->GetCurrentTimeSamples(csound); else vstTimeInfo.samplePos = 0; vstTimeInfo.sampleRate = framesPerSecond; Debug("&vstTimeInfo 0x%x sampleRate %f samplePos %f.\n", &vstTimeInfo, vstTimeInfo.sampleRate, vstTimeInfo.samplePos); return &vstTimeInfo; } bool VSTPlugin::IsSynth() { return pluginIsSynth; } bool VSTPlugin::OnCanDo(const char *ptr) { // printf("Can do call: %s.\n", ptr); if ((!strcmp(ptr, "sendVstMidiEvent")) || (!strcmp(ptr, "receiveVstMidiEvent")) || (!strcmp(ptr, "sendVstEvents")) || (!strcmp(ptr, "receiveVstEvents")) || (!strcmp(ptr, "sendVstTimeInfo")) /*|| (!strcmp(ptr, "sizeWindow"))*/) return true; return false; } bool VSTPlugin::OnInputConnected(AEffect *effect, long input) { return true; } bool VSTPlugin::OnOutputConnected(AEffect *effect, long output) { return true; } VstIntPtr VSTPlugin::Master(AEffect *effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void *ptr, float opt) { VSTPlugin *plugin = 0; CSOUND *csound = 0; if (effect) { plugin = (VSTPlugin *) effect->user; if (plugin) { csound = plugin->csound; } } std::string opcodeName; if (masterOpcodes().find(opcode) != masterOpcodes().end()) { opcodeName = masterOpcodes()[opcode]; } // These messages are to tell Csound what the plugin wants it to do. if (plugin) { plugin->Debug("VSTPlugin::Master(AEffect 0x%p, opcode %ld %s, index %ld, " "value %dl, ptr 0x%p, opt %f)\n", effect, opcode, opcodeName.c_str(), index, value, ptr, opt); } // else { // fprintf(stdout, "VSTPlugin::Master(AEffect 0x%p, opcode %ld %s, index %ld, " // "value %ld, ptr 0x%p, opt %f)\n", // effect, opcode, opcodeName.c_str(), index, value, ptr, opt); // } switch (opcode) { case audioMasterAutomate: return true; case audioMasterVersion: if (effect) return OnGetVersion(effect); case audioMasterCurrentId: if (effect) return effect->uniqueID; else return -1; case audioMasterIdle: if (plugin) { plugin->Dispatch(effEditIdle, 0, 0, NULL, 0.0f); } return 0; case audioMasterPinConnected: if (effect) { return !((value) ? OnOutputConnected(effect, index) : OnInputConnected(effect, index)); } case audioMasterWantMidi: return false; case audioMasterProcessEvents: return false; case audioMasterGetTime: if (plugin) { return (VstIntPtr) plugin->GetTime(); } else { //static VstTimeInfo vstTimeInfo; //memset(&vstTimeInfo, 0, sizeof(VstTimeInfo)); //return (long) &vstTimeInfo; } return 0; case audioMasterTempoAt: return 0; case audioMasterNeedIdle: if (plugin) return plugin->Dispatch(effIdle, 0, 0, NULL, 0.0f); return false; case audioMasterGetSampleRate: if (plugin) return plugin->framesPerSecond; else return ((size_t) (csound->GetSr(csound) + FL(0.5))); case audioMasterGetVendorString: strcpy((char *)ptr, "vst4cs"); return 0; case audioMasterGetVendorVersion: return 5000; case audioMasterGetProductString: strcpy((char*)ptr,"vst4cs"); return 0; case audioMasterGetLanguage: return kVstLangEnglish; case audioMasterUpdateDisplay: if (plugin) { plugin->Dispatch(effEditIdle, 0, 0, NULL, 0.0f); //return 0; } else return 1; case audioMasterGetNextPlug: return 1; case audioMasterWillReplaceOrAccumulate: return 1; case audioMasterGetCurrentProcessLevel: return 0; case audioMasterCanDo: //if(plugin) return OnCanDo((char *)ptr); //else printf("No instance"); default: break; } return 0; } csound-6.10.0/Opcodes/vst4cs/src/vsthost.h000066400000000000000000000206041321653344700203770ustar00rootroot00000000000000// vst4cs: VST HOST OPCODES FOR CSOUND // // Uses code by Hermann Seib from his VSTHost program and from the vst~ // object by Thomas Grill (no license), which in turn borrows from the Psycle // tracker (also based on VSTHost). // // VST is a trademark of Steinberg Media Technologies GmbH. // VST Plug-In Technology by Steinberg. // // Copyright (C) 2004 Andres Cabrera, Michael Gogins // // The vst4cs library is free software; you can redistribute it // and/or modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // The vst4cs library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with The vst4cs library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA // 02111-1307 USA // // Linking vst4cs statically or dynamically with other modules is making a // combined work based on vst4cs. Thus, the terms and conditions of the GNU // Lesser General Public License cover the whole combination. // // In addition, as a special exception, the copyright holders of vst4cs, // including the Csound developers and Hermann Seib, the original author of // VSTHost, give you permission to combine vst4cs with free software programs // or libraries that are released under the GNU LGPL and with code included // in the standard release of the VST SDK version 2 under the terms of the // license stated in the VST SDK version 2 files. You may copy and distribute // such a system following the terms of the GNU LGPL for vst4cs and the // licenses of the other code concerned. The source code for the VST SDK // version 2 is available in the VST SDK hosted at // https://github.com/steinbergmedia/vst3sdk. // // Note that people who make modified versions of vst4cs are not obligated to // grant this special exception for their modified versions; it is their // choice whether to do so. The GNU Lesser General Public License gives // permission to release a modified version without this exception; this // exception also makes it possible to release a modified version which // carries forward this exception. #ifndef VSTPLUGIN_HOST_H #define VSTPLUGIN_HOST_H #include "csdl.h" #if !defined(SWIG) && defined(CS_VSTHOST) #include #endif #include #include #include /** * THE REAL VST INTERFACE IS JUST THIS, USE THE EXACT SAME TYPES: * * typedef VstIntPtr (VSTCALLBACK *audioMasterCallback) (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt); * typedef VstIntPtr (VSTCALLBACK *AEffectDispatcherProc) (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt); * typedef void (VSTCALLBACK *AEffectProcessProc) (AEffect* effect, float** inputs, float** outputs, VstInt32 sampleFrames); * typedef void (VSTCALLBACK *AEffectProcessDoubleProc) (AEffect* effect, double** inputs, double** outputs, VstInt32 sampleFrames); * typedef void (VSTCALLBACK *AEffectSetParameterProc) (AEffect* effect, VstInt32 index, float parameter); * typedef float (VSTCALLBACK *AEffectGetParameterProc) (AEffect* effect, VstInt32 index); */ typedef enum { MAX_EVENTS = 64, MAX_INOUTS = 8, VSTINSTANCE_ERR_NO_VALID_FILE = -1, VSTINSTANCE_ERR_NO_VST_PLUGIN = -2, VSTINSTANCE_ERR_REJECTED = -3, VSTINSTANCE_NO_ERROR = 0 } VST4CS_ENUM; typedef AEffect * (*PVSTMAIN)(audioMasterCallback audioMaster); class Fl_Window; class VSTPlugin { public: CSOUND *csound; void *libraryHandle; AEffect *aeffect; bool hasEditor; AEffEditor *editor; ERect rect; Fl_Window *window; void *windowHandle; char productName[64]; char vendorName[64]; char libraryName[0x100]; unsigned long pluginVersion; bool pluginIsSynth; std::vector inputs; std::vector outputs; std::vector< std::vector > inputs_; std::vector< std::vector > outputs_; std::vector vstMidiEvents; std::vector vstEventsBuffer; bool overwrite; bool edited; bool showParameters; VstTimeInfo vstTimeInfo; float framesPerSecond; size_t framesPerBlock; int targetFLpanel; //GAB VSTPlugin(CSOUND *csound); virtual ~VSTPlugin(); virtual void StopEditing(); virtual int GetNumCategories(); virtual bool GetProgramName(int cat, int p, char *buf); virtual bool ShowParams(); virtual void SetShowParameters(bool s); virtual void OnEditorClose(); virtual void SetEditWindow(void *h); virtual ERect GetEditorRect(); virtual void EditorIdle(); virtual bool replace(); virtual void Free(); virtual int Instantiate(const char *libraryPathname); virtual void Info(); virtual void Init(); virtual int GetNumParams(void); virtual void GetParamName(int param, char *name); virtual float GetParamValue(int param); virtual int getNumInputs(void); virtual int getNumOutputs(void); virtual char* GetName(void); virtual unsigned long GetVersion(); virtual char* GetVendorName(void); virtual char* GetDllName(void); virtual long NumParameters(void); virtual float GetParameter(long parameter); virtual bool DescribeValue(int parameter,char* psTxt); virtual bool SetParameter(int parameter, float value); virtual bool SetParameter(int parameter, int value); virtual void SetCurrentProgram(int prg); virtual int GetCurrentProgram(); virtual int NumPrograms(); virtual bool IsSynth(); virtual bool AddMIDI(int data, int deltaFrames, int detune); virtual void SendMidi(); virtual void processReplacing(float **inputs, float **outputs, long sampleframes); virtual void process(float **inputs, float **outputs, long sampleframes); // typedef VstIntPtr (VSTCALLBACK *AEffectDispatcherProc) (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt); virtual VstIntPtr Dispatch(VstInt32 opCode, VstInt32 index=0, VstIntPtr value=0, void *ptr=0, float opt=0); virtual void Log(const char *format, ...); virtual void Debug(const char *format, ...); virtual void OpenEditor(); virtual void CloseEditor(); virtual VstTimeInfo *GetTime(); static bool OnInputConnected(AEffect *effect, long input); static bool OnOutputConnected(AEffect *effect, long output); static long OnGetVersion(AEffect *effect); static bool OnCanDo(const char *ptr); // typedef VstIntPtr (VSTCALLBACK *audioMasterCallback) (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt); static VstIntPtr Master(AEffect *effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void *ptr, float opt); static void initializeOpcodes(); long EffGetChunk(void **ptr, bool isPreset = false) // GAB { return Dispatch(effGetChunk, isPreset, 0, ptr); } long EffGetProgram() { return Dispatch(effGetProgram); } void EffSetProgram(long lValue) { Dispatch(effSetProgram, 0, lValue); } void EffGetProgramName(char *ptr) { Dispatch(effGetProgramName, 0, 0, ptr); } static std::map &masterOpcodes() { static std::map masterOpcodes_; return masterOpcodes_; } static std::map &dispatchOpcodes() { static std::map dispatchOpcodes_; return dispatchOpcodes_; } }; inline VstIntPtr VSTPlugin::Dispatch(VstInt32 opCode, VstInt32 index, VstIntPtr value, void *ptr, float opt) { if (aeffect) return aeffect->dispatcher(aeffect, opCode, index, value, ptr, opt); else return 0; } inline void VSTPlugin::processReplacing(float **ins, float **outs, long frames) { if (aeffect) { SendMidi(); aeffect->processReplacing(aeffect, ins, outs, frames); } } inline void VSTPlugin::process(float **ins, float **outs, long frames) { if (aeffect) { SendMidi(); aeffect->processReplacing(aeffect, ins, outs, frames); } } #endif csound-6.10.0/Opcodes/wave-terrain.c000066400000000000000000000215731321653344700172550ustar00rootroot00000000000000/* wave-terrain.c: Copyright (C) 2002 Matt Gilliard, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "stdopcod.h" #include "wave-terrain.h" #include /* Wave-terrain synthesis opcode * * author: m gilliard * en6mjg@bath.ac.uk */ static int wtinit(CSOUND *csound, WAVETER *p) { /* DECLARE */ FUNC *ftpx = csound->FTnp2Find(csound, p->i_tabx); FUNC *ftpy = csound->FTnp2Find(csound, p->i_taby); /* CHECK */ if (UNLIKELY((ftpx == NULL)||(ftpy == NULL))) { return csound->InitError(csound, Str("wterrain: ftable not found")); } /* POINT xarr AND yarr AT THE TABLES */ p->xarr = ftpx->ftable; p->yarr = ftpy->ftable; /* PUT SIZES INTO STRUCT FOR REFERENCE AT PERF TIME */ p->sizx = (MYFLT)ftpx->flen; p->sizy = (MYFLT)ftpy->flen; p->theta = 0.0; return OK; } static int wtPerf(CSOUND *csound, WAVETER *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; int xloc, yloc; MYFLT xc, yc; MYFLT amp = *p->kamp; MYFLT pch = *p->kpch; MYFLT kcx = *(p->kcx), kcy = *(p->kcy); MYFLT krx = *(p->krx), kry = *(p->kry); MYFLT sizx = p->sizx, sizy = p->sizy; MYFLT theta = p->theta; MYFLT dtpidsr = csound->tpidsr; MYFLT *aout = p->aout; if (UNLIKELY(offset)) memset(aout, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&aout[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset; ixarr[xloc] * p->yarr[yloc] * amp; /* MOVE SCANNING POINT ROUND THE ELLIPSE */ theta += pch * dtpidsr; } p->theta = FMOD(theta,TWOPI_F); return OK; } /* ------------------------------------------------------------ */ /* Simple scanned synthesis hammer hit opcode * * Like tablecopy, except the src may be smaller, and hitting position * and force given. * * author: m gilliard * en6mjg@bath.ac.uk */ static int scanhinit(CSOUND *csound, SCANHAMMER *p) { unsigned int srcpos = 0; unsigned int dstpos = (unsigned int)MYFLT2LONG(*p->ipos); FUNC *fsrc = csound->FTnp2Find(csound, p->isrc); /* Source table */ FUNC *fdst = csound->FTnp2Find(csound, p->idst); /* Destination table */ if (UNLIKELY(fsrc->flen > fdst->flen)) { return csound->InitError(csound, Str("Source table must be same size or " "smaller than dest table\n")); } for (srcpos=0; srcposflen; srcpos++) { fdst->ftable[dstpos] = fsrc->ftable[srcpos] * *p->imode; if (++dstpos > fdst->flen) { dstpos = 0; } } return OK; } /* ------------------------------------------------------------ */ /* Simple scanned synthesis opcode * * makes a table update at k-rate for the duration of the note. * also scans the system at a k-rate pitch, and k-rate amplitude. * * author: m gilliard * en6mjg@bath.ac.uk */ static int scantinit(CSOUND *csound, SCANTABLE *p) { /* DECLARE */ FUNC *fpoint = csound->FTnp2Find(csound, p->i_point); FUNC *fmass = csound->FTnp2Find(csound, p->i_mass); FUNC *fstiff = csound->FTnp2Find(csound, p->i_stiff); FUNC *fdamp = csound->FTnp2Find(csound, p->i_damp); FUNC *fvel = csound->FTnp2Find(csound, p->i_vel); /* CHECK */ if (UNLIKELY(fpoint == NULL)) { return csound->InitError(csound, Str("Scantable: point table not found")); } if (UNLIKELY(fmass == NULL)) { return csound->InitError(csound, Str("Scantable: mass table not found")); } if (UNLIKELY(fstiff == NULL)) { return csound->InitError(csound, Str("Scantable: stiffness table not found")); } if (UNLIKELY(fdamp == NULL)) { return csound->InitError(csound, Str("Scantable: damping table not found")); } if (UNLIKELY(fvel == NULL)) { return csound->InitError(csound, Str("Scantable: velocity table not found")); } /* CHECK ALL TABLES SAME LENGTH */ if (UNLIKELY(!((fpoint->flen==fmass->flen) && (fdamp->flen==fstiff->flen) && (fvel->flen==fstiff->flen) && (fpoint->flen==fdamp->flen)))) { return csound->InitError(csound, Str("Table lengths do not agree!!")); } p->fpoint = fpoint; p->fmass = fmass; p->fstiff = fstiff; p->fdamp = fdamp; p->fvel = fvel; p->size = (MYFLT)fpoint->flen; /* ALLOCATE SPACE FOR NEW POINTS AND VELOCITIES */ csound->AuxAlloc(csound, fpoint->flen * sizeof(MYFLT), &p->newloca); csound->AuxAlloc(csound, fvel->flen * sizeof(MYFLT), &p->newvela); /* POINT newloc AND newvel AT THE ALLOCATED SPACE */ p->newloc = (MYFLT*)p->newloca.auxp; p->newvel = (MYFLT*)p->newvela.auxp; /* SET SCANNING POSITION */ p->pos = 0; return OK; } static int scantPerf(CSOUND *csound, SCANTABLE *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t i, nsmps = CS_KSMPS; MYFLT force, fc1, fc2; int next, last; /* DECLARE */ FUNC *fpoint = p->fpoint; FUNC *fmass = p->fmass; FUNC *fstiff = p->fstiff; FUNC *fdamp = p->fdamp; FUNC *fvel = p->fvel; MYFLT inc = p->size * *(p->kpch) * csound->onedsr; MYFLT amp = *(p->kamp); MYFLT pos = p->pos; MYFLT *aout = p->aout; /* CALCULATE NEW POSITIONS * * fill in newloc and newvel arrays with calculated values * this is the string updating function * * a mass of zero means immovable, so as to allow fixed points */ /* For all except end points */ for (i=0; i!=p->size; i++) { /* set up conditions for end-points */ last = i - 1; next = i + 1; if (UNLIKELY(i == p->size - 1)) { next = 0; } else if (UNLIKELY(i == 0)) { last = (int)p->size - 1; } if (UNLIKELY(fmass->ftable[i] == 0)) { /* if the mass is zero... */ p->newloc[i] = fpoint->ftable[i]; p->newvel[i] = 0; } else { /* update point according to scheme */ fc1 = (fpoint->ftable[i] - fpoint->ftable[last]) * fstiff->ftable[last]; fc2 = (fpoint->ftable[i] - fpoint->ftable[next]) * fstiff->ftable[i]; force = fc1 + fc2; p->newvel[i] = (fvel->ftable[i] - force / (fmass->ftable[i] * CS_EKR)) * fdamp->ftable[i]; p->newloc[i] = fpoint->ftable[i] + p->newvel[i] * CS_ONEDKR; } } if (UNLIKELY(offset)) memset(aout, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&aout[nsmps], '\0', early*sizeof(MYFLT)); } for (i=offset; iftable[(int)pos] * amp; pos += inc /* p->size * *(p->kpch) * csound->onedsr */; if (UNLIKELY(pos > p->size)) { pos -= p->size; } } p->pos = pos; /* COPY NEW VALUES TO FTABLE * * replace current values with new ones */ memcpy(fpoint->ftable, p->newloc, p->size*sizeof(MYFLT)); memcpy(fvel->ftable, p->newvel, p->size*sizeof(MYFLT)); return OK; } #define S(x) sizeof(x) static OENTRY localops[] = { { "wterrain", S(WAVETER), TR, 5, "a", "kkkkkkii", (SUBR)wtinit, NULL, (SUBR)wtPerf }, { "scantable", S(SCANTABLE),TR, 5,"a", "kkiiiii", (SUBR)scantinit,NULL,(SUBR)scantPerf}, { "scanhammer",S(SCANHAMMER),TB, 1,"", "iiii", (SUBR)scanhinit, NULL, NULL } }; int wave_terrain_init_(CSOUND *csound) { return csound->AppendOpcodes(csound, &(localops[0]), (int) (sizeof(localops) / sizeof(OENTRY))); } csound-6.10.0/Opcodes/wave-terrain.h000066400000000000000000000032421321653344700172530ustar00rootroot00000000000000/* wave-terrain.h: Copyright (C) 2002 Matt Gilliard, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csdl.h" typedef struct { OPDS h; MYFLT *aout; MYFLT *kamp; MYFLT *kpch; MYFLT *kcx, *kcy; MYFLT *krx, *kry; MYFLT *i_tabx, *i_taby; /* Table numbers */ /* Internals */ MYFLT *xarr, *yarr; /* Actual tables */ MYFLT sizx, sizy; double theta; } WAVETER; typedef struct { OPDS h; MYFLT *isrc; MYFLT *idst; MYFLT *ipos; MYFLT *imode; /* imode: 0 : dest = src 1 : dest = dest + src/imode */ } SCANHAMMER; typedef struct { OPDS h; MYFLT *aout; MYFLT *kamp; MYFLT *kpch; MYFLT *i_point; MYFLT *i_mass; MYFLT *i_stiff; MYFLT *i_damp; MYFLT *i_vel; /* End of arguments */ AUXCH newloca; AUXCH newvela; MYFLT *newloc, *newvel; MYFLT size; MYFLT pos; FUNC *fpoint; FUNC *fmass; FUNC *fstiff; FUNC *fdamp; FUNC *fvel; } SCANTABLE; csound-6.10.0/Opcodes/wavegde.h000066400000000000000000000071741321653344700163010ustar00rootroot00000000000000/* wavegde.h: Copyright (C) 1994 Michael A. Casey, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* waveguide.h -- primitive data types and declarations for waveguides */ /* * Code conversion from C++ to C (October 1994) * Author: Michael A. Casey MIT Media Labs * Language: C * Copyright (c) 1994 MIT Media Lab, All Rights Reserved */ #ifndef _waveguide_h #define _waveguide_h #include #ifndef sinf #define sinf(a) (MYFLT)sin((double)(a)) #define cosf(a) (MYFLT)cos((double)(a)) #define sqrtf(a) (MYFLT)sqrt((double)(a)) #define atan2f(a,b) (MYFLT)atan2((double)(a),(double)(b)) #define powf(a,b) (MYFLT)pow((double)(a),(double)(b)) #endif /* TYPEDEFS */ typedef long len_t; /* length type */ /* CLASS DEFINITIONS */ /* circularBuffer -- circular buffer class */ /* serves as base class for waveguides and lattice filters */ typedef struct { int inited; /* Data initialization flag */ len_t size; /* Size of the digital filter lattice */ MYFLT* insertionPoint; /* Position in queue to place new data */ MYFLT* extractionPoint; /* Position to read data from */ MYFLT* data; /* The lattice data */ MYFLT* endPoint; /* The end of the data */ MYFLT* pointer; /* pointer to current position in data */ } circularBuffer; /* class filter -- recursive filter implementation class */ typedef struct { circularBuffer buffer; /* The filter's delay line */ MYFLT* coeffs; /* The filter's coefficients */ } filter; /* class filter3-- JPff */ typedef struct { MYFLT x1, x2; /* Delay line */ MYFLT a0, a1; /* The filter's coefficients */ } filter3; /* filter member functions */ static void filter3Set(filter3*,MYFLT,MYFLT); /* set the coefficients */ static MYFLT filter3FIR(filter3*,MYFLT); /* convolution filter routine */ /* waveguide rail implementation class */ typedef circularBuffer guideRail; /* It's just a circular buffer really */ /* guideRail member functions */ static MYFLT guideRailAccess(guideRail*,len_t); /* delay line access routine */ static void guideRailUpdate(guideRail*,MYFLT); /* delay line update routine */ /* waveguide -- abstract base class definition for waveguide classes */ typedef struct{ int excited; /* excitation flag */ guideRail upperRail; /* the right-going wave */ guideRail lowerRail; /* the left-going wave */ MYFLT c; /* The tuning filter coefficient */ MYFLT p; /* The tuning fitler state */ MYFLT w0; /* The fundamental frequency (PI normalized) */ MYFLT f0; /* The fundamental frequency (Hertz) */ } waveguide; static MYFLT filterAllpass(waveguide*,MYFLT);/* 1st-order allpass filtering*/ /* waveguide member functions */ static void waveguideWaveguide(CSOUND *, waveguide*, MYFLT, MYFLT*, MYFLT*); static void waveguideSetTuning(CSOUND *,waveguide*, MYFLT); /* Set tuning filters */ #endif csound-6.10.0/Opcodes/websockets/000077500000000000000000000000001321653344700166465ustar00rootroot00000000000000csound-6.10.0/Opcodes/websockets/CMakeLists.txt000066400000000000000000000024211321653344700214050ustar00rootroot00000000000000option(BUILD_WEBSOCKET_OPCODE "Build the websocket opcode" ON) FIND_PATH ( WEBSOCKETS_H libwebsockets.h /usr/local/include /usr/include ) if(WIN32 AND NOT MSVC) find_library (websockets_library NAMES websockets_static) else() FIND_LIBRARY ( websockets_library websockets /usr/local/lib /usr/lib ) find_library (websockets_library NAMES websockets) if(APPLE) FIND_LIBRARY (ssl_library NAMES ssl.a /usr/local/lib /usr/lib ) #find_library (crypto_library NAMES crypto.a FIND_LIBRARY ( crypto_library NAMES crypto.a /usr/local/lib /usr/lib ) #find_library (crypto_library NAMES crypto) endif() endif() check_include_file(libwebsockets.h WEBSOCKETS_H) if(WEBSOCKETS_H AND websockets_library) set(CMAKE_REQUIRED_INCLUDES libwebsockets.h) set(CMAKE_REQUIRED_LIBRARIES ${websockets_library}) endif() check_deps(BUILD_WEBSOCKET_OPCODE websockets_library) if(BUILD_WEBSOCKET_OPCODE) make_plugin(websocketIO WebSocketOpcode.c) target_link_libraries(websocketIO ${websockets_library} ${CSOUNDLIB}) if(APPLE) target_link_libraries(websocketIO /usr/local/lib/libssl.a /usr/local/lib/libcrypto.a z) endif() if(WIN32 AND NOT MSVC) target_link_libraries(websocketIO ssl crypto z ws2_32 wsock32) endif() endif() csound-6.10.0/Opcodes/websockets/WebSocketOpcode.c000066400000000000000000000535441321653344700220450ustar00rootroot00000000000000/* WebSocketOpcode.c WebSocketOpcode Copyright (C) 2015, 2016 Edward Costello This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "WebSocketOpcode.h" #include #include #include #include typedef enum ArgumentType { STRING_VAR, ARATE_VAR, KRATE_VAR, IRATE_VAR, ARATE_ARRAY, KRATE_ARRAY, IRATE_ARRAY, UNKNOWN } ArgumentType; struct OpcodeArgument{ void *dataPointer; MYFLT *argumentPointer; bool receivedData; ArgumentType argumentType; AUXCH auxillaryMemory; void *circularBuffer; char *name; void *readBuffer; int itemsCount; unsigned int bytesCount; unsigned int bytesWritten; bool iRateVarSent; }; struct WebSocket{ struct lws_context *context; struct lws *websocket; struct lws_protocols *protocols; void *processThread; unsigned char *messageBuffer; struct lws_context_creation_info info; }; typedef enum ArgumentOffset { OUTPUT_OFFSET = 1000, INPUT_OFFSET = 2000 } ArgumentOffset; static const size_t writeBufferBytesCount = 2048; static const size_t stringVarMaximumBytesCount = 4096; static const size_t ringBufferItemsCount = 2048 * 16; void WebSocketOpcode_initialiseWebSocket(WebSocketOpcode *self, CSOUND *csound); int WebSocketOpcode_finish(CSOUND *csound, void *opaqueReference); void WebSocketOpcode_initialiseArguments(WebSocketOpcode *self, CSOUND *csound); ArgumentType WebSocketOpcode_getArgumentType(CSOUND *csound, MYFLT *argument); int WebSocketOpcode_initialise(CSOUND *csound, WebSocketOpcode *self) { self->inputArgumentCount = self->INOCOUNT - 1; self->outputArgumentCount = self->OUTOCOUNT; self->csound = csound; WebSocketOpcode_initialiseArguments(self, csound); WebSocketOpcode_initialiseWebSocket(self, csound); csound->RegisterDeinitCallback(csound, self, WebSocketOpcode_finish); return OK; } void WebSocketOpcode_sendInputArgumentData(CSOUND *csound, WebSocketOpcode *self) { int i; for (i = 0; i < self->inputArgumentCount; ++i) { OpcodeArgument *currentArgument = &self->inputArguments[i]; if (currentArgument->iRateVarSent == true) { continue; } int itemsWritten = csoundWriteCircularBuffer(csound, currentArgument->circularBuffer, currentArgument->dataPointer, currentArgument->itemsCount); if (UNLIKELY(itemsWritten != currentArgument->itemsCount)) { csound->Message(csound, Str("websocket: variable %s data not sent, " "buffer overrrun\n"), currentArgument->name); } } } void WebSocketOpcode_receiveOutputArgumentData(CSOUND *csound, WebSocketOpcode *self) { int i; for (i = 0; i < self->outputArgumentCount; ++i) { OpcodeArgument *currentArgument = &self->outputArguments[i]; if (currentArgument->receivedData == true) { if (currentArgument->iRateVarSent == true) { continue; } csoundReadCircularBuffer(csound, currentArgument->circularBuffer, currentArgument->dataPointer, currentArgument->itemsCount); if (currentArgument->argumentType == STRING_VAR) { STRINGDAT *string = (STRINGDAT *)currentArgument->argumentPointer; string->size = (int)strlen(currentArgument->dataPointer); } currentArgument->receivedData = false; } } } int WebSocketOpcode_process(CSOUND *csound, WebSocketOpcode *self) { WebSocketOpcode_sendInputArgumentData(csound, self); WebSocketOpcode_receiveOutputArgumentData(csound, self); return OK; } int WebSocketOpcode_finish(CSOUND *csound, void *opaqueReference) { int i; WebSocketOpcode *self = opaqueReference; self->isRunning = false; csound->JoinThread(self->webSocket->processThread); lws_cancel_service(self->webSocket->context); lws_context_destroy(self->webSocket->context); for (i = 0; i < self->outputArgumentCount; ++i) { csoundDestroyCircularBuffer(csound, self->outputArguments[i].circularBuffer); } for (i = 0; i < self->inputArgumentCount; ++i) { csoundDestroyCircularBuffer(csound, self->inputArguments[i].circularBuffer); } csound->Free(csound, self->webSocket->protocols); csound->Free(csound, self->webSocket->messageBuffer); csound->Free(csound, self->webSocket); if (self->inputArgumentCount > 0) { csound->Free(csound, self->inputArguments); } if (self->outputArgumentCount > 0) { csound->Free(csound, self->outputArguments); } return OK; } int WebSocketOpcode_getArrayElementCount(ARRAYDAT *array) { int elementCount = array->sizes[0]; int i; for (i = 1; i < array->dimensions; ++i) { elementCount *= array->sizes[i]; } return elementCount; } void WebSocketOpcode_allocateStringArgument(MYFLT *argument, OpcodeArgument *argumentArrayItem, CSOUND *csound, bool isInputArgument) { STRINGDAT *string = (STRINGDAT *)argument; if (UNLIKELY(isInputArgument == true)) { csound->Die(csound, Str("websocket: this opcode does not send strings, only " "receiving them is supported\nExiting")); } else { if (UNLIKELY(string->size != 0)) { csound->Die(csound, Str("websocket: error output string variable %s must not " "be initialised\nExiting"), argumentArrayItem->name); } else { argumentArrayItem->itemsCount = stringVarMaximumBytesCount; string->data = csound->ReAlloc(csound, string->data, stringVarMaximumBytesCount); memset(string->data, 0, stringVarMaximumBytesCount); } } argumentArrayItem->dataPointer = string->data; argumentArrayItem->bytesCount = sizeof(char) * stringVarMaximumBytesCount; argumentArrayItem->circularBuffer = csoundCreateCircularBuffer(csound, argumentArrayItem->itemsCount * ringBufferItemsCount + 1, sizeof(char)); csound->AuxAlloc(csound, argumentArrayItem->bytesCount, &argumentArrayItem->auxillaryMemory); argumentArrayItem->readBuffer = argumentArrayItem->auxillaryMemory.auxp; } void WebSocketOpcode_allocateArrayArgument(MYFLT *argument, OpcodeArgument *argumentArrayItem, CSOUND *csound) { ARRAYDAT *array = (ARRAYDAT *)argument; if (UNLIKELY(array->dimensions == 0)) { csound->Die(csound, Str("websocket: error array variable %s has not been " "initialised\nExiting"), argumentArrayItem->name); } argumentArrayItem->dataPointer = array->data; argumentArrayItem->itemsCount = WebSocketOpcode_getArrayElementCount(array); argumentArrayItem->bytesCount = array->arrayMemberSize * argumentArrayItem->itemsCount; argumentArrayItem->circularBuffer = csoundCreateCircularBuffer(csound, argumentArrayItem->itemsCount * ringBufferItemsCount + 1, array->arrayMemberSize); csound->AuxAlloc(csound, argumentArrayItem->bytesCount, &argumentArrayItem->auxillaryMemory); argumentArrayItem->readBuffer = argumentArrayItem->auxillaryMemory.auxp; } void WebSocketOpcode_allocateVariableArgument(MYFLT *argument, OpcodeArgument *argumentArrayItem, CSOUND *csound, int bytesCount) { argumentArrayItem->dataPointer = argument; argumentArrayItem->itemsCount = 1; argumentArrayItem->bytesCount = bytesCount; argumentArrayItem->circularBuffer = csoundCreateCircularBuffer(csound, ringBufferItemsCount + 1, argumentArrayItem->bytesCount); csound->AuxAlloc(csound, argumentArrayItem->bytesCount, &argumentArrayItem->auxillaryMemory); argumentArrayItem->readBuffer = argumentArrayItem->auxillaryMemory.auxp; } void WebSocketOpcode_initialiseArgumentsArray(CSOUND *csound, WebSocketOpcode *self, OpcodeArgument *argumentsArray, size_t argumentsCount, MYFLT **arguments, bool areInputArguments) { unsigned int i; for (i = 0; i < argumentsCount; ++i) { OpcodeArgument *argumentArrayItem = &argumentsArray[i]; argumentArrayItem->argumentPointer = arguments[i]; argumentArrayItem->argumentType = WebSocketOpcode_getArgumentType(csound, arguments[i]); argumentArrayItem->name = areInputArguments ? csound->GetInputArgName((void *)self, i + 1) : csound->GetOutputArgName((void *)self, i); switch (argumentsArray[i].argumentType) { case IRATE_ARRAY: case ARATE_ARRAY: case KRATE_ARRAY: { WebSocketOpcode_allocateArrayArgument(arguments[i], argumentArrayItem, csound); break; } case STRING_VAR: { WebSocketOpcode_allocateStringArgument(arguments[i], argumentArrayItem, csound, areInputArguments); break; } case ARATE_VAR: { WebSocketOpcode_allocateVariableArgument(arguments[i], argumentArrayItem, csound, sizeof(MYFLT) * csound->GetKsmps(csound)); break; } case IRATE_VAR: case KRATE_VAR: { WebSocketOpcode_allocateVariableArgument(arguments[i], argumentArrayItem, csound, sizeof(MYFLT)); break; } default: { csound->Die(csound, Str("websocket: error, incompatible argument " "detected\nExiting")); break; } } } } void WebSocketOpcode_initialiseArguments(WebSocketOpcode *self, CSOUND *csound) { self->inputArguments = csound->Calloc(csound, sizeof(OpcodeArgument) * self->inputArgumentCount); self->outputArguments = csound->Calloc(csound, sizeof(OpcodeArgument) * self->outputArgumentCount); WebSocketOpcode_initialiseArgumentsArray(csound, self, self->inputArguments, self->inputArgumentCount, &self->arguments[self->outputArgumentCount + 1], true); WebSocketOpcode_initialiseArgumentsArray(csound, self, self->outputArguments, self->outputArgumentCount, self->arguments, false); } void WebSocketOpcode_writeOnce(WebSocketOpcode *self, OpcodeArgument *inputArgument, void *messageBuffer, struct lws *websocket) { unsigned char *inputData = (unsigned char *)inputArgument->readBuffer; memcpy(messageBuffer, inputData, inputArgument->bytesCount); lws_write(websocket, messageBuffer, inputArgument->bytesCount, LWS_WRITE_BINARY); } void WebSocketOpcode_writeFragments(WebSocketOpcode *self, OpcodeArgument *inputArgument, void *messageBuffer, struct lws *websocket) { unsigned char *inputData = &((unsigned char *)inputArgument->readBuffer)[inputArgument->bytesWritten]; // *** FIXME *** signed/usigned comparison if (inputArgument->bytesWritten + writeBufferBytesCount < inputArgument->bytesCount) { int writeFlags = LWS_WRITE_NO_FIN; writeFlags |= inputArgument->bytesWritten==0 ? LWS_WRITE_BINARY : LWS_WRITE_CONTINUATION; memcpy(messageBuffer, inputData, writeBufferBytesCount); inputArgument->bytesWritten += lws_write(websocket, messageBuffer, writeBufferBytesCount, writeFlags); } else { size_t fragmentBytesCount = inputArgument->bytesCount - inputArgument->bytesWritten; memcpy(messageBuffer, inputData, fragmentBytesCount); lws_write(websocket, messageBuffer, fragmentBytesCount, LWS_WRITE_CONTINUATION); inputArgument->bytesWritten = 0; } } void WebSocketOpcode_writeMessage(WebSocketOpcode *self, OpcodeArgument *inputArgument, void *messageBuffer, struct lws *websocket) { if (inputArgument->bytesCount <= writeBufferBytesCount) { WebSocketOpcode_writeOnce(self, inputArgument, messageBuffer, websocket); } else { WebSocketOpcode_writeFragments(self, inputArgument, messageBuffer, websocket); } } void WebSocketOpcode_handleServerWritable(struct lws *websocket, WebSocketOpcode *self, CSOUND *csound, void *messageBuffer) { const struct lws_protocols *protocol = lws_get_protocol(websocket); if (protocol->id / OUTPUT_OFFSET == 1) { // If it's an output argument usleep(100); return; } int inputIndex = 0; OpcodeArgument *argument = &self->inputArguments[inputIndex]; int readItems = 0; if (argument->bytesWritten == 0) { readItems = csoundReadCircularBuffer(csound, argument->circularBuffer, argument->readBuffer, argument->itemsCount); } if (readItems != 0 || argument->bytesWritten != 0) { WebSocketOpcode_writeMessage(self, argument, messageBuffer, websocket); if (argument->argumentType == IRATE_VAR || argument->argumentType == IRATE_ARRAY) { argument->iRateVarSent = true; } } usleep(100); if (argument->iRateVarSent == false) { lws_callback_on_writable(websocket); } } void WebSocketOpcode_handleReceive(struct lws *websocket, WebSocketOpcode *self, CSOUND *csound, size_t inputDataSize, void *inputData) { const struct lws_protocols *protocol = lws_get_protocol(websocket); if (protocol->id / OUTPUT_OFFSET != 1) { return; } OpcodeArgument *argument = &self->outputArguments[protocol->id - OUTPUT_OFFSET]; if (argument->iRateVarSent == true) { return; } // *** FIXME *** signed/unsigned comparison if (UNLIKELY(argument->bytesCount != inputDataSize && argument->argumentType != STRING_VAR)) { csound->Message(csound, Str("websocket: received message from is not " "correct size for variable %s, message dumped"), protocol->name); return; } if (UNLIKELY(argument->argumentType == STRING_VAR && argument->bytesCount > stringVarMaximumBytesCount)) { csound->Message(csound, Str("websocket: received string message from " "%s is too large, message dumped"), protocol->name); return; } int writtenItems = csoundWriteCircularBuffer(csound, argument->circularBuffer, inputData, argument->itemsCount); argument->receivedData = true; if (UNLIKELY(writtenItems == 0)) { csound->Message(csound, Str("websocket: received message from %s " "dumped, buffer overrrun"), argument->name); } else { if (argument->argumentType == IRATE_VAR || argument->argumentType == IRATE_ARRAY) { argument->iRateVarSent = true; } } } static int Websocket_callback(struct lws *websocket, enum lws_callback_reasons reason, void *user, void *inputData, size_t inputDataSize) { if (reason != LWS_CALLBACK_ESTABLISHED && reason != LWS_CALLBACK_SERVER_WRITEABLE && reason != LWS_CALLBACK_RECEIVE) { return OK; } const struct lws_protocols *protocol = lws_get_protocol(websocket); WebSocketOpcode *self = lws_get_protocol(websocket)->user; CSOUND *csound = self->csound; switch (reason) { case LWS_CALLBACK_ESTABLISHED: { csound->Message(csound, Str("websocket: connection established for %s\n"), protocol->name); break; } case LWS_CALLBACK_SERVER_WRITEABLE: { void *messageBuffer = (void *)&self->webSocket->messageBuffer[LWS_SEND_BUFFER_PRE_PADDING]; WebSocketOpcode_handleServerWritable(websocket, self, csound, messageBuffer); break; } case LWS_CALLBACK_RECEIVE: { WebSocketOpcode_handleReceive(websocket, self, csound, inputDataSize, inputData); break; } case LWS_CALLBACK_CLOSED: { printf("closed\n"); /* Why not sound->Message ? */ } default: { break; } } return OK; } uintptr_t WebSocketOpcode_processThread(void *opaquePointer) { WebSocketOpcode *self = opaquePointer; while (self->isRunning == 1) { lws_service(self->webSocket->context, 10); lws_callback_on_writable_all_protocol(self->webSocket->context, &self->webSocket->protocols[0]); } return 0; } void WebSocketOpcode_initialiseWebSocket(WebSocketOpcode *self, CSOUND *csound) { int i; size_t argumentsCount = self->inputArgumentCount + self->outputArgumentCount; self->webSocket = csound->Calloc(csound, sizeof(WebSocket)); self->webSocket->protocols = //Last protocol is null csound->Calloc(csound, sizeof(struct lws_protocols) * (argumentsCount + 1)); size_t argumentIndex = 0; for (i = 0; i < self->inputArgumentCount; ++i, argumentIndex++) { self->webSocket->protocols[argumentIndex].name = self->inputArguments[i].name; self->webSocket->protocols[argumentIndex].callback = Websocket_callback; self->webSocket->protocols[argumentIndex].id = INPUT_OFFSET + i; self->webSocket->protocols[argumentIndex].user = self; self->webSocket->protocols[argumentIndex].per_session_data_size = sizeof(WebSocketOpcode *); } for (i = 0; i < self->outputArgumentCount; ++i, ++argumentIndex) { self->webSocket->protocols[argumentIndex].name = self->outputArguments[i].name; self->webSocket->protocols[argumentIndex].callback = Websocket_callback; self->webSocket->protocols[argumentIndex].id = OUTPUT_OFFSET + i; self->webSocket->protocols[argumentIndex].user = self; self->webSocket->protocols[argumentIndex].per_session_data_size = sizeof(WebSocketOpcode *); } self->webSocket->info.port = *self->arguments[self->outputArgumentCount]; self->webSocket->info.protocols = self->webSocket->protocols; self->webSocket->info.gid = -1; self->webSocket->info.uid = -1; lws_set_log_level(LLL_DEBUG, NULL); self->webSocket->context = lws_create_context(&self->webSocket->info); self->webSocket->messageBuffer = csound->Calloc(csound, LWS_SEND_BUFFER_PRE_PADDING + (sizeof(char) * writeBufferBytesCount) + LWS_SEND_BUFFER_POST_PADDING); if (UNLIKELY(self->webSocket->context == NULL)) { csound->Die(csound, Str("websocket: could not initialise websocket, Exiting")); } self->isRunning = true; self->webSocket->processThread = csound->CreateThread(WebSocketOpcode_processThread, self); } ArgumentType WebSocketOpcode_getArgumentType(CSOUND *csound, MYFLT *argument) { const CS_TYPE *csoundType = csound->GetTypeForArg((void *)argument); const char *type = csoundType->varTypeName; ArgumentType argumentType = UNKNOWN; if (strcmp("S", type) == 0) { argumentType = STRING_VAR; } else if (strcmp("a", type) == 0) { argumentType = ARATE_VAR; } else if (strcmp("k", type) == 0) { argumentType = KRATE_VAR; } else if (strcmp("i", type) == 0) { argumentType = IRATE_VAR; } else if (strcmp("[", type) == 0) { ARRAYDAT *array = (ARRAYDAT *)argument; if (strcmp("k", array->arrayType->varTypeName) == 0) { argumentType = KRATE_ARRAY; } else if (strcmp("a", array->arrayType->varTypeName) == 0) { argumentType = ARATE_ARRAY; } else if (strcmp("i", array->arrayType->varTypeName) == 0) { argumentType = IRATE_ARRAY; } } return argumentType; } static OENTRY localops[] = { { .opname = "websocket", .dsblksiz = sizeof(WebSocketOpcode), .thread = 3, .outypes = "*", .intypes = "i.", .iopadr = (SUBR)WebSocketOpcode_initialise, .kopadr = (SUBR)WebSocketOpcode_process, .aopadr = NULL } }; LINKAGE csound-6.10.0/Opcodes/websockets/WebSocketOpcode.h000066400000000000000000000030261321653344700220400ustar00rootroot00000000000000/* WebSocketOpcode.h WebSockets Created by Edward Costello on 10/06/2015. Copyright (c) 2015 Edward Costello. This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "csdl.h" #include "csound.h" #ifdef __cplusplus extern "C" { #endif typedef struct OpcodeArgument OpcodeArgument; typedef struct WebSocket WebSocket; typedef struct WebSocketOpcode { OPDS h; MYFLT *arguments[20]; int inputArgumentCount; int outputArgumentCount; WebSocket *webSocket; OpcodeArgument *inputArguments; OpcodeArgument *outputArguments; bool isRunning; CSOUND *csound; } WebSocketOpcode; int WebSocketOpcode_initialise(CSOUND *csound, WebSocketOpcode *self); int WebSocketOpcode_process(CSOUND *csound, WebSocketOpcode *self); #ifdef __cplusplus } #endif csound-6.10.0/Opcodes/wii_mac000066400000000000000000000040101321653344700160230ustar00rootroot00000000000000#define WII_BUTTONS #0# #define WII_TWO #1# #define WII_ONE #2# #define WII_B #3# #define WII_A #4# #define WII_MINUS #5# #define WII_HOME #8# #define WII_LEFT #9# #define WII_RIGHT #10# #define WII_DOWN #11# #define WII_UP #12# #define WII_PLUS #13# #define WII_AXIS_X #17# #define WII_AXIS_Y #18# #define WII_AXIS_Z #19# #define WII_PITCH #20# #define WII_ROLL #21# #define WII_YAW #22# #define WII_FORCE_X #23# #define WII_FORCE_Y #24# #define WII_FORCE_Z #25# #define WII_FORCE_TOTAL #26# #define WII_BATTERY #27# #define WII_NUNCHUK_ANG #28# #define WII_NUNCHUK_MAG #29# #define WII_NUNCHUK_PITCH #30# #define WII_NUNCHUK_ROLL #31# #define WII_NUNCHUK_YAW #32# #define WII_NUNCHUK_Z #33# #define WII_NUNCHUK_C #34# #define WII_IR1_X #35# #define WII_IR1_Y #36# #define WII_IR1_Z #37# ;; State of buttons #define WII_S_TWO #101# #define WII_S_ONE #102# #define WII_S_B #103# #define WII_S_A #104# #define WII_S_MINUS #105# #define WII_S_HOME #108# #define WII_S_LEFT #109# #define WII_S_RIGHT #110# #define WII_S_DOWN #111# #define WII_S_UP #112# #define WII_S_PLUS #113# ;; Held #define WII_H_TWO #201# #define WII_H_ONE #202# #define WII_H_B #203# #define WII_H_A #204# #define WII_H_MINUS #205# #define WII_H_HOME #208# #define WII_H_LEFT #209# #define WII_H_RIGHT #210# #define WII_H_DOWN #211# #define WII_H_UP #212# #define WII_H_PLUS #213# ;; Released #define WII_R_TWO #301# #define WII_R_ONE #302# #define WII_R_B #303# #define WII_R_A #304# #define WII_R_MINUS #305# #define WII_R_HOME #308# #define WII_R_LEFT #309# #define WII_R_RIGHT #310# #define WII_R_DOWN #311# #define WII_R_UP #312# #define WII_R_PLUS #313# ;; Send Data #define WII_RUMBLE #3# #define WII_SET_LEDS #4# csound-6.10.0/Opcodes/wii_mac.h000066400000000000000000000017621321653344700162640ustar00rootroot00000000000000#define WII_BUTTONS (0) #define WII_TWO (1) #define WII_ONE (2) #define WII_B (3) #define WII_A (4) #define WII_MINUS (5) #define WII_HOME (8) #define WII_LEFT (9) #define WII_RIGHT (10) #define WII_DOWN (11) #define WII_UP (12) #define WII_PLUS (13) #define WII_AXIS_X (17) #define WII_AXIS_Y (18) #define WII_AXIS_Z (19) #define WII_PITCH (20) #define WII_ROLL (21) #define WII_YAW (22) #define WII_FORCE_X (23) #define WII_FORCE_Y (24) #define WII_FORCE_Z (25) #define WII_FORCE_TOTAL (26) #define WII_BATTERY (27) #define WII_NUNCHUK_ANG (28) #define WII_NUNCHUK_MAG (29) #define WII_NUNCHUK_PITCH (30) #define WII_NUNCHUK_ROLL (31) #define WII_NUNCHUK_YAW (32) #define WII_NUNCHUK_Z (33) #define WII_NUNCHUK_C (34) #define WII_IR1_X (35) #define WII_IR1_Y (36) #define WII_IR1_Z (37) #define WII_RUMBLE (3) #define WII_SET_LEDS (4) csound-6.10.0/Opcodes/wiimote.c000066400000000000000000000334601321653344700163240ustar00rootroot00000000000000/* wiimote.c: Copyright (C) 2009 by John ffitch, This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* wiimote.c */ #include "csdl.h" #include "wiiuse.h" /* Uses WIIUSE library which is LGPL */ #define MAX_WIIMOTES 4 #include "wii_mac.h" typedef struct { MYFLT axis_x_min; /* 0 -> 255 */ MYFLT axis_x_scale; /* 1 */ MYFLT axis_y_min; MYFLT axis_y_scale; MYFLT axis_z_min; MYFLT axis_z_scale; MYFLT pitch_min; /* -90 -> +90 */ MYFLT pitch_scale; /* 1 */ MYFLT roll_min; MYFLT roll_scale; /* MYFLT tilt_z_min; */ /* MYFLT tilt_z_scale; */ MYFLT joy_min; MYFLT joy_scale; MYFLT nunchuk_pitch_min; MYFLT nunchuk_pitch_scale; MYFLT nunchuk_roll_min; MYFLT nunchuk_roll_scale; /* MYFLT naxis_z_min; */ /* MYFLT naxis_z_max; */ } wiirange_t; typedef struct { OPDS h; MYFLT *res; MYFLT *kControl; MYFLT *num; /* ------------------------------------- */ wiimote **wii; wiirange_t *wiir; int max_wiimotes; } WIIMOTE; typedef struct { OPDS h; MYFLT *kControl; MYFLT *kValue; MYFLT *num; /* ------------------------------------- */ wiimote **wii; wiirange_t *wiir; } WIIMOTES; typedef struct { OPDS h; MYFLT *iControl; MYFLT *iMin; MYFLT *iMax; MYFLT *num; } WIIRANGE; #ifndef WIIMOTE_STATE_CONNECTED # if defined(WIIUSE_0_13) # define WIIMOTE_STATE_CONNECTED (0x0010) # else # define WIIMOTE_STATE_CONNECTED (0x0008) # endif #endif int wiimote_find(CSOUND *csound, WIIMOTE *p) { int n, i; wiimote **wiimotes; wiirange_t *wiirange; int max_wiimotes; wiimotes = (wiimote**)csound->QueryGlobalVariable(csound, "wiiMote"); if (wiimotes == NULL) { csound->CreateGlobalVariable(csound, "wiiMote", MAX_WIIMOTES*sizeof(wiimote*)); wiimotes = (wiimote**)csound->QueryGlobalVariable(csound, "wiiMote"); } wiirange = (wiirange_t *)csound->QueryGlobalVariable(csound, "wiiRange"); if (wiirange == NULL) { csound->CreateGlobalVariable(csound, "wiiRange", MAX_WIIMOTES*sizeof(wiirange_t)); wiirange = (wiirange_t *)csound->QueryGlobalVariable(csound, "wiiRange"); } { /* Use our copy not his */ wiimote** ww = wiiuse_init(MAX_WIIMOTES); memcpy(wiimotes, ww, MAX_WIIMOTES*sizeof(wiimote*)); free(ww); } i = (int)*p->kControl; if (i<=0) i = 10; /* default timeout */ max_wiimotes = (int)*p->num; if (max_wiimotes<=0 || max_wiimotes>MAX_WIIMOTES) max_wiimotes = MAX_WIIMOTES; n = wiiuse_find(wiimotes, max_wiimotes, i); if (LIKELY(n!=0)) n = wiiuse_connect(wiimotes, max_wiimotes); if (UNLIKELY(n==0)) { return csound->InitError(csound, Str("unable to open wiimote\n")); } /* Initialise ranges */ for (i=0; iwii = wiimotes; p->max_wiimotes = n; *p->res = FL(1.0); return OK; } int wiimote_poll(CSOUND *csound, WIIMOTE *p) { wiimote **wiimotes = p->wii; int i; int max_wiimotes = p->max_wiimotes; wiiuse_poll(wiimotes, max_wiimotes); for (i=0; i < max_wiimotes; ++i) { switch (wiimotes[i]->event) { case WIIUSE_EVENT: case WIIUSE_STATUS: case WIIUSE_READ_DATA: break; case WIIUSE_DISCONNECT: case WIIUSE_UNEXPECTED_DISCONNECT: /* the wiimote disconnected */ csound->Warning(csound, Str("wiimote %i disconnected\n"), wiimotes[i]->unid); *p->res = FL(0.0); return OK; case WIIUSE_NUNCHUK_INSERTED: /* * This is a good place to set any nunchuk specific * threshold values. By default they are the same * as the wiimote. */ /* wiiuse_set_nunchuk_orient_threshold((struct nunchuk_t*)&wiimotes[i]-> */ /* exp.nunchuk, 90.0f); */ /* wiiuse_set_nunchuk_accel_threshold((struct nunchuk_t*)&wiimotes[i]-> */ /* exp.nunchuk, 100); */ csound->Warning(csound, Str("Nunchuk inserted.\n")); break; case WIIUSE_NUNCHUK_REMOVED: /* some expansion was removed */ csound->Warning(csound, Str("Nunchuk for wiimote %i was removed.\n"), i); break; default: break; } } *p->res = FL(1.0); return OK; } int wii_data_init(CSOUND *csound, WIIMOTE *p) { wiimote **wiimotes; wiirange_t *wiirange; wiimotes = (wiimote**)csound->QueryGlobalVariable(csound, "wiiMote"); if (UNLIKELY(wiimotes==NULL)) return csound->InitError(csound, Str("No wii open")); wiirange = (wiirange_t *)csound->QueryGlobalVariable(csound, "wiiRange"); if (UNLIKELY(wiirange==NULL)) return csound->InitError(csound, Str("No wii open")); p->wii = wiimotes; p->wiir = wiirange; return OK; } int wii_data(CSOUND *csound, WIIMOTE *p) { wiimote **wii = p->wii; wiirange_t *wiir = p->wiir; int n = (int)*p->num; int kontrol = (int)(*p->kControl+FL(0.5)); if (UNLIKELY(n>=MAX_WIIMOTES || !(wii[n]->state & WIIMOTE_STATE_CONNECTED))) { printf("state of wii %d is %x\n", n, wii[n]->state); return csound->PerfError(csound, p->h.insdshead, Str("wiimote %d does not exist"), n); } if (kontrol<0) { printf("%f -- %.4x: " "tilt=[%f %f];\nforce=(%f %f %f)\n", 100.0*wii[n]->battery_level, wii[n]->btns, wiir[n].pitch_min+wiir[n].pitch_scale*(FL(90.0)+ (MYFLT)wii[n]->orient.pitch), wiir[n].roll_min+wiir[n].roll_scale*(FL(90.0)- (MYFLT)wii[n]->orient.roll), wii[n]->gforce.x, wii[n]->gforce.y, wii[n]->gforce.z); *p->res = FL(0.0); return OK; } if (kontrol>0 && kontrol<17) { *p->res = (MYFLT)IS_JUST_PRESSED(wii[n], 1<<(kontrol-1)); } if (kontrol>100 && kontrol<117) { *p->res = (MYFLT)IS_PRESSED(wii[n], 1<<(kontrol-101)); return OK; } if (kontrol>200 && kontrol<217) { *p->res = (MYFLT)IS_HELD(wii[n], 1<<(kontrol-201)); return OK; } if (kontrol>300 && kontrol<317) { *p->res = (MYFLT)IS_RELEASED(wii[n], 1<<(kontrol-301)); return OK; } else switch (kontrol) { case WII_BUTTONS: *p->res = (MYFLT)(wii[n]->btns&WIIMOTE_BUTTON_ALL); return OK; /* case 17: */ /* *p->res = wiir[n].axis_x_min+wiir[n].axis_x_scale*(MYFLT)wii[n]->axis.x; */ /* return OK; */ /* case 18: */ /* *p->res = wiir[n].axis_y_min+wiir[n].axis_y_scale*(MYFLT)wii[n]->axis.y; */ /* return OK; */ /* case 19: */ /* *p->res = wiir[n].axis_z_min+wiir[n].axis_z_scale*(MYFLT)wii[n]->axis.z; */ /* return OK; */ case WII_PITCH: /* I think the sign is wrong so negated; inplies negative is down */ *p->res = wiir[n].pitch_min+ wiir[n].pitch_scale*(FL(90.0)-(MYFLT)wii[n]->orient.pitch); return OK; case WII_ROLL: *p->res = wiir[n].roll_min+ wiir[n].roll_scale*(FL(90.0)+(MYFLT)wii[n]->orient.roll); return OK; /* case 22: */ /* *p->res = wiir[n].tilt_z_min+ wiir[n].tilt_z_scale*(FL(90.0)-(MYFLT)wii[n]->tilt.z); */ /* return OK; */ case WII_FORCE_X: *p->res = (MYFLT)wii[n]->gforce.x; return OK; case WII_FORCE_Y: *p->res = (MYFLT)wii[n]->gforce.y; return OK; case WII_FORCE_Z: *p->res = (MYFLT)wii[n]->gforce.z; return OK; case WII_FORCE_TOTAL: *p->res = SQRT(wii[n]->gforce.x*wii[n]->gforce.x+ wii[n]->gforce.y*wii[n]->gforce.y+ wii[n]->gforce.z*wii[n]->gforce.z); return OK; case WII_BATTERY: *p->res = FL(100.0)*(MYFLT)wii[n]->battery_level; return OK; case WII_NUNCHUK_ANG: *p->res = (MYFLT)wii[n]->exp.nunchuk.js.ang; return OK; case WII_NUNCHUK_MAG: *p->res = (MYFLT)wii[n]->exp.nunchuk.js.mag; return OK; case WII_NUNCHUK_PITCH: *p->res = wiir[n].nunchuk_pitch_min+ wiir[n].nunchuk_pitch_scale*(FL(90.0)- (MYFLT)wii[n]->exp.nunchuk.orient.pitch); return OK; case WII_NUNCHUK_ROLL: *p->res = wiir[n].nunchuk_roll_min+ wiir[n].nunchuk_roll_scale*(FL(90.0)- (MYFLT)wii[n]->exp.nunchuk.orient.roll); return OK; /* case 32: */ /* *p->res = (MYFLT)wii[n]->exp.nunchuk.axis.z; */ /* return OK; */ case WII_NUNCHUK_Z: *p->res = (MYFLT)((wii[n]->exp.nunchuk.btns & NUNCHUK_BUTTON_Z)== NUNCHUK_BUTTON_Z); return OK; case WII_NUNCHUK_C: *p->res = (MYFLT)((wii[n]->exp.nunchuk.btns & NUNCHUK_BUTTON_C)== NUNCHUK_BUTTON_C); return OK; case WII_IR1_X: *p->res = (MYFLT)wii[n]->ir.x; return OK; case WII_IR1_Y: *p->res = (MYFLT)wii[n]->ir.y; return OK; case WII_IR1_Z: *p->res = (MYFLT)wii[n]->ir.z; return OK; } return NOTOK; } int wii_data_inits(CSOUND *csound, WIIMOTES *p) { wiimote **wiimotes; wiirange_t *wiirange; wiimotes = (wiimote**)csound->QueryGlobalVariable(csound, "wiiMote"); if (UNLIKELY(wiimotes==NULL)) return csound->InitError(csound, Str("No wii open")); wiirange = (wiirange_t *)csound->QueryGlobalVariable(csound, "wiiRange"); if (UNLIKELY(wiirange==NULL)) return csound->InitError(csound, Str("No wii open")); p->wii = wiimotes; p->wiir = wiirange; return OK; } int wii_send(CSOUND *csound, WIIMOTES *p) { wiimote **wii = p->wii; int num = (int)*p->num; if (UNLIKELY(!(wii[num]->state & WIIMOTE_STATE_CONNECTED))) return csound->PerfError(csound, p->h.insdshead, Str("Not open")); switch ((int)(*p->kControl+FL(0.5))) { /* case 1: */ /* wii->mode.acc = (int)*p->kValue; */ /* break; */ /* case 2: */ /* wii->mode.ir = (int)*p->kValue; */ /* break; */ case WII_RUMBLE: wiiuse_rumble(wii[num], (int)*p->kValue); break; case WII_SET_LEDS: wiiuse_set_leds(wii[num], ((uint16)*p->kValue)<<4); break; } return OK; } int wiimote_range(CSOUND *csound, WIIRANGE *p) { wiirange_t *wiirange = (wiirange_t *)csound->QueryGlobalVariable(csound, "wiiRange"); if (UNLIKELY(wiirange==NULL)) return csound->InitError(csound, Str("No wii range")); switch ((int)(*p->iControl+FL(0.5))) { /* case 17: */ /* wiirange->axis_x_min = *p->iMin; */ /* wiirange->axis_x_scale = (*p->iMax-*p->iMin)/FL(255.0); */ /* return OK; */ /* case 18: */ /* wiirange->axis_y_min = *p->iMin; */ /* wiirange->axis_y_scale = (*p->iMax-*p->iMin)/FL(255.0); */ /* return OK; */ /* case 19: */ /* wiirange->axis_z_min = *p->iMin; */ /* wiirange->axis_z_scale = (*p->iMax-*p->iMin)/FL(255.0); */ /* return OK; */ case WII_PITCH: wiirange->pitch_min = *p->iMin; wiirange->pitch_scale = (*p->iMax-*p->iMin)/FL(180.0); return OK; case WII_ROLL: wiirange->roll_min = *p->iMin; wiirange->roll_scale = (*p->iMax-*p->iMin)/FL(180.0); return OK; /* case 22: */ /* wiirange->tilt_z_min = *p->iMin; */ /* wiirange->tilt_z_scale = (*p->iMax-*p->iMin)/FL(180.0); */ /* return OK; */ case WII_NUNCHUK_PITCH: wiirange->nunchuk_pitch_min = *p->iMin; wiirange->nunchuk_pitch_scale = (*p->iMax-*p->iMin)/FL(180.0); return OK; case WII_NUNCHUK_ROLL: wiirange->nunchuk_roll_min = *p->iMin; wiirange->nunchuk_roll_scale = (*p->iMax-*p->iMin)/FL(180.0); return OK; default: return NOTOK; } } #define S(x) sizeof(x) static OENTRY wiimote_localops[] = { {"wiiconnect", S(WIIMOTE), 0, 3, "i", "oo", (SUBR)wiimote_find, (SUBR)wiimote_poll }, {"wiidata", S(WIIMOTE), 0, 3, "k", "ko", (SUBR)wii_data_init, (SUBR)wii_data }, {"wiisend", S(WIIMOTES), 0, 3, "", "kko", (SUBR)wii_data_inits, (SUBR)wii_send }, {"wiirange", S(WIIRANGE), 0, 1, "", "iiio", (SUBR)wiimote_range, NULL, NULL } }; LINKAGE_BUILTIN(wiimote_localops) csound-6.10.0/Opcodes/wpfilters.c000066400000000000000000000614511321653344700166670ustar00rootroot00000000000000/* wpfilters.c: Copyright (C) 2017 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Zero Delay Feedback Filters Based on code by Will Pirkle, presented in: http://www.willpirkle.com/Downloads/AN-4VirtualAnalogFilters.2.0.pdf http://www.willpirkle.com/Downloads/AN-5Korg35_V3.pdf http://www.willpirkle.com/Downloads/AN-6DiodeLadderFilter.pdf http://www.willpirkle.com/Downloads/AN-7Korg35HPF_V2.pdf and in his book "Designing software synthesizer plug-ins in C++ : for RackAFX, VST3, and Audio Units" ZDF using Trapezoidal integrator by Vadim Zavalishin, presented in "The Art of VA Filter Design" (https://www.native-instruments.com/fileadmin/ni_media/ downloads/pdf/VAFilterDesign_1.1.1.pdf) Csound C versions by Steven Yi */ #include "wpfilters.h" static int zdf_1pole_mode_init(CSOUND* csound, ZDF_1POLE_MODE* p) { if (*p->skip == 0) { p->z1 = 0.0; p->last_cut = -1.0; } return OK; } static int zdf_1pole_mode_perf(CSOUND* csound, ZDF_1POLE_MODE* p) { double z1 = p->z1; double last_cut = p->last_cut; double G = p->G; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; double T = csound->onedsr; double Tdiv2 = T / 2.0; double two_div_T = 2.0 / T; int cutoff_arate = IS_ASIG_ARG(p->cutoff); MYFLT cutoff = cutoff_arate ? 0.0 : *p->cutoff; if (UNLIKELY(offset)) { memset(p->outlp, '\0', offset*sizeof(MYFLT)); memset(p->outhp, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&p->outlp[nsmps], '\0', early*sizeof(MYFLT)); memset(&p->outhp[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { if (cutoff_arate) { cutoff = p->cutoff[n]; } if (cutoff != last_cut) { last_cut = cutoff; double wd = TWOPI * cutoff; double wa = two_div_T * tan(wd * Tdiv2); double g = wa * Tdiv2; G = g / (1.0 + g); } // do the filter, see VA book p. 46 // form sub-node value v(n) double in = p->in[n]; double v = (in - z1) * G; // form output of node + register double lp = v + z1; double hp = in - lp; // z1 register update z1 = lp + v; p->outlp[n] = lp; p->outhp[n] = hp; } p->z1 = z1; p->last_cut = last_cut; p->G = G; return OK; } static int zdf_1pole_init(CSOUND* csound, ZDF_1POLE* p) { if (*p->skip == 0) { p->z1 = 0.0; p->last_cut = -1.0; } return OK; } static int zdf_1pole_perf(CSOUND* csound, ZDF_1POLE* p) { double z1 = p->z1; double last_cut = p->last_cut; double G = p->G; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; double T = csound->onedsr; double Tdiv2 = T / 2.0; double two_div_T = 2.0 / T; int mode = MYFLT2LONG(*p->mode); int cutoff_arate = IS_ASIG_ARG(p->cutoff); MYFLT cutoff = cutoff_arate ? 0.0 : *p->cutoff; if (UNLIKELY(offset)) { memset(p->out, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&p->out[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { if (cutoff_arate) { cutoff = p->cutoff[n]; } if (cutoff != last_cut) { last_cut = cutoff; double wd = TWOPI * cutoff; double wa = two_div_T * tan(wd * Tdiv2); double g = wa * Tdiv2; G = g / (1.0 + g); } // do the filter, see VA book p. 46 // form sub-node value v(n) double in = p->in[n]; double v = (in - z1) * G; // form output of node + register double lp = v + z1; if (mode == 0) { // low-pass p->out[n] = lp; } else if (mode == 1) { // high-pass double hp = in - lp; p->out[n] = hp; } else if (mode == 2) { // allpass double hp = in - lp; p->out[n] = lp - hp; } // TODO Implement low-shelf and high-shelf //else if (mode == 3) { // low-shelf //} //else if (mode == 4) { // high-shelf //} // z1 register update z1 = lp + v; } p->z1 = z1; p->last_cut = last_cut; p->G = G; return OK; } static int zdf_2pole_mode_init(CSOUND* csound, ZDF_2POLE_MODE* p) { if (*p->skip == 0) { p->z1 = 0.0; p->z2 = 0.0; p->last_cut = -1.0; p->last_q = -1.0; p->g = 0.0; p->R = 0.0; } return OK; } static int zdf_2pole_mode_perf(CSOUND* csound, ZDF_2POLE_MODE* p) { double z1 = p->z1; double z2 = p->z2; double last_cut = p->last_cut; double last_q = p->last_q; double g = p->g; double R = p->R; double g2 = g * g; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; double T = csound->onedsr; double Tdiv2 = T / 2.0; double two_div_T = 2.0 / T; int cutoff_arate = IS_ASIG_ARG(p->cutoff); int q_arate = IS_ASIG_ARG(p->q); MYFLT cutoff = *p->cutoff; MYFLT q = *p->q; if (UNLIKELY(offset)) { memset(p->outlp, '\0', offset*sizeof(MYFLT)); memset(p->outhp, '\0', offset*sizeof(MYFLT)); memset(p->outbp, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&p->outlp[nsmps], '\0', early*sizeof(MYFLT)); memset(&p->outhp[nsmps], '\0', early*sizeof(MYFLT)); memset(&p->outbp[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { if (cutoff_arate) { cutoff = p->cutoff[n]; } if (q_arate) { q = p->q[n]; } if (cutoff != last_cut) { last_cut = cutoff; double wd = TWOPI * cutoff; double wa = two_div_T * tan(wd * Tdiv2); g = wa * Tdiv2; g2 = g * g; } if (q != last_q) { last_q = q; R = 1.0 / (2.0 * q); } double in = p->in[n]; double hp = (in - (2.0 * R + g) * z1 - z2) / (1.0 + (2.0 * R * g) + g2); double bp = g * hp + z1; double lp = g * bp + z2; // double notch = in - (2.0 * R * bp); // register updates z1 = g * hp + bp; z2 = g * bp + lp; p->outlp[n] = lp; p->outhp[n] = hp; p->outbp[n] = bp; // p->outnotch[n] = notch; } p->z1 = z1; p->z2 = z2; p->last_cut = last_cut; p->last_q = last_q; p->g = g; p->R = R; return OK; } static int zdf_2pole_init(CSOUND* csound, ZDF_2POLE* p) { if (*p->skip == 0) { p->z1 = 0.0; p->z2 = 0.0; p->last_cut = -1.0; p->last_q = -1.0; p->g = 0.0; p->R = 0.0; } return OK; } static int zdf_2pole_perf(CSOUND* csound, ZDF_2POLE* p) { double z1 = p->z1; double z2 = p->z2; double last_cut = p->last_cut; double last_q = p->last_q; int mode = MYFLT2LONG(*p->mode); double g = p->g; double R = p->R; double g2 = g * g; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; double T = csound->onedsr; double Tdiv2 = T / 2.0; double two_div_T = 2.0 / T; int cutoff_arate = IS_ASIG_ARG(p->cutoff); int q_arate = IS_ASIG_ARG(p->q); MYFLT cutoff = *p->cutoff; MYFLT q = *p->q; if (UNLIKELY(offset)) { memset(p->out, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&p->out[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { if (cutoff_arate) { cutoff = p->cutoff[n]; } if (q_arate) { q = p->q[n]; } if (cutoff != last_cut) { last_cut = cutoff; double wd = TWOPI * cutoff; double wa = two_div_T * tan(wd * Tdiv2); g = wa * Tdiv2; g2 = g * g; } if (q != last_q) { last_q = q; R = 1.0 / (2.0 * q); } double in = p->in[n]; double hp = (in - (2.0 * R + g) * z1 - z2) / (1.0 + (2.0 * R * g) + g2); double bp = g * hp + z1; double lp = g * bp + z2; if (mode == 0) { // low-pass p->out[n] = lp; } else if (mode == 1) { // high-pass p->out[n] = hp; } else if (mode == 2) { // band-pass p->out[n] = bp; } else if (mode == 3) { // unity-gain band-pass p->out[n] = 2.0 * R * bp; } else if (mode == 4) { // notch p->out[n] = in - 2.0 * R * bp; } else if (mode == 5) { // all-pass filter p->out[n] = in - 4.0 * R * bp; } else if (mode == 6) { // peak filter p->out[n] = lp - hp; } //else if (mode == 7) { // band shelf - not implemented // p->out[n] = in + 2.0 * K * R * bp; //} // register updates z1 = g * hp + bp; z2 = g * bp + lp; } p->z1 = z1; p->z2 = z2; p->last_cut = last_cut; p->last_q = last_q; p->g = g; p->R = R; return OK; } static int zdf_ladder_init(CSOUND* csound, ZDF_LADDER* p) { if (*p->skip == 0) { p->z1 = 0.0; p->z2 = 0.0; p->z3 = 0.0; p->z4 = 0.0; p->last_cut = -1.0; p->last_q = -1.0; p->last_k = 0.0; p->last_g = 0.0; p->last_G = 0.0; p->last_G2 = 0.0; p->last_G3 = 0.0; p->last_GAMMA = 0.0; } return OK; } static int zdf_ladder_perf(CSOUND* csound, ZDF_LADDER* p) { double z1 = p->z1; double z2 = p->z2; double z3 = p->z3; double z4 = p->z4; double last_cut = p->last_cut; double last_q = p->last_q; double k = p->last_k; double g = p->last_g; double G = p->last_G; double G2 = p->last_G2; double G3 = p->last_G3; double GAMMA = p->last_GAMMA; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; double T = csound->onedsr; double Tdiv2 = T / 2.0; double two_div_T = 2.0 / T; int cutoff_arate = IS_ASIG_ARG(p->cutoff); int q_arate = IS_ASIG_ARG(p->q); MYFLT cutoff = cutoff_arate ? 0.0 : *p->cutoff; MYFLT q = q_arate ? 0.0 : *p->q; if (UNLIKELY(offset)) { memset(p->out, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&p->out[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { if (cutoff_arate) { cutoff = p->cutoff[n]; } if (q_arate) { q = p->q[n]; q = (q < 0.5) ? 0.5 : (q > 25.0) ? 25.0 : q; } if (q != last_q) { last_q = q; // Q [0.5,25] = k [0,4.0] k = (4.0 * (q - 0.5)) / (25.0 - 0.5); } if (cutoff != last_cut) { last_cut = cutoff; double wd = TWOPI * cutoff; double wa = two_div_T * tan(wd * Tdiv2); g = wa * Tdiv2; G = g / (1.0 + g); G2 = G * G; G3 = G2 * G; GAMMA = G2 * G2; } double g_plus_1 = g + 1.0; double S1 = z1 / g_plus_1; double S2 = z2 / g_plus_1; double S3 = z3 / g_plus_1; double S4 = z4 / g_plus_1; double S = (G3 * S1) + (G2 * S2) + (G * S3) + S4; double u = (p->in[n] - k * S) / (1 + k * GAMMA); // 1st stage double v = (u - z1) * G; double lp = v + z1; z1 = lp + v; // 2nd stage v = (lp - z2) * G; lp = v + z2; z2 = lp + v; // 3rd stage v = (lp - z3) * G; lp = v + z3; z3 = lp + v; // 4th stage v = (lp - z4) * G; lp = v + z4; z4 = lp + v; p->out[n] = lp; } p->z1 = z1; p->z2 = z2; p->z3 = z3; p->z4 = z4; p->last_cut = last_cut; p->last_q = last_q; p->last_k = k; p->last_g = g; p->last_G = G; p->last_G2 = G2; p->last_G3 = G3; p->last_GAMMA = GAMMA; return OK; } static int diode_ladder_init(CSOUND* csound, DIODE_LADDER* p) { if (*p->skip == 0) { int i; p->a[0] = 1.0; p->a[1] = 0.5; p->a[2] = 0.5; p->a[3] = 0.5; for (i = 0; i < 4; i++) { p->z[i] = 0.0; p->G[i] = 0.0; p->beta[i] = 0.0; p->SG[i] = 0.0; } for (i = 0; i < 3; i++) { p->delta[i] = 0.0; p->epsilon[i] = 0.0; p->gamma[i] = 0.0; } p->GAMMA = 0.0; p->SIGMA = 0.0; p->last_cut = -1.0; } return OK; } static int diode_ladder_perf(CSOUND* csound, DIODE_LADDER* p) { double a1 = p->a[0]; double a2 = p->a[1]; double a3 = p->a[2]; double a4 = p->a[3]; double z1 = p->z[0]; double z2 = p->z[1]; double z3 = p->z[2]; double z4 = p->z[3]; double G1 = p->G[0]; double G2 = p->G[1]; double G3 = p->G[2]; double G4 = p->G[3]; double beta1 = p->beta[0]; double beta2 = p->beta[1]; double beta3 = p->beta[2]; double beta4 = p->beta[3]; double delta1 = p->delta[0]; double delta2 = p->delta[1]; double delta3 = p->delta[2]; double epsilon1 = p->epsilon[0]; double epsilon2 = p->epsilon[1]; double epsilon3 = p->epsilon[2]; double gamma1 = p->gamma[0]; double gamma2 = p->gamma[1]; double gamma3 = p->gamma[2]; double SG1 = p->SG[0]; double SG2 = p->SG[1]; double SG3 = p->SG[2]; double SG4 = p->SG[3]; double GAMMA = p->GAMMA; double SIGMA = p->SIGMA; double alpha = p->last_alpha; double last_cut = p->last_cut; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; double T = csound->onedsr; double Tdiv2 = T / 2.0; double two_div_T = 2.0 / T; int cutoff_arate = IS_ASIG_ARG(p->cutoff); int k_arate = IS_ASIG_ARG(p->kval); MYFLT cutoff = cutoff_arate ? 0.0 : *p->cutoff; MYFLT k = k_arate ? 0.0 : *p->kval; if (UNLIKELY(offset)) { memset(p->out, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&p->out[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { MYFLT in = p->in[n]; if (cutoff_arate) { cutoff = p->cutoff[n]; } if (k_arate) { k = p->kval[n]; } if (cutoff != last_cut) { last_cut = cutoff; double wd = TWOPI * cutoff; double wa = two_div_T * tan(wd * Tdiv2); double g = wa * Tdiv2; double gp1 = 1.0 + g; G4 = 0.5 * g / gp1; G3 = 0.5 * g / (gp1 - 0.5 * g * G4); G2 = 0.5 * g / (gp1 - 0.5 * g * G3); G1 = g / (gp1 - g * G2); GAMMA = G4 * G3 * G2 * G1; SG1 = G4 * G3 * G2; SG2 = G4 * G3; SG3 = G4; SG4 = 1.0; alpha = g / gp1; beta1 = 1.0 / (gp1 - g * G2); beta2 = 1.0 / (gp1 - 0.5 * g * G3); beta3 = 1.0 / (gp1 - 0.5 * g * G4); beta4 = 1.0 / gp1; gamma1 = 1.0 + G1 * G2; gamma2 = 1.0 + G2 * G3; gamma3 = 1.0 + G3 * G4; delta1 = g; delta2 = delta3 = 0.5 * g; epsilon1 = G2; epsilon2 = G3; epsilon3 = G4; } //feedback inputs double fb4 = beta4 * z4; double fb3 = beta3 * (z3 + fb4 * delta3); double fb2 = beta2 * (z2 + fb3 * delta2); //feedback process double fbo1 = (beta1 * (z1 + fb2 * delta1)); double fbo2 = (beta2 * (z2 + fb3 * delta2)); double fbo3 = (beta3 * (z3 + fb4 * delta3)); SIGMA = (SG1 * fbo1) + (SG2 * fbo2) + (SG3 * fbo3) + (SG4 * fb4); // non-linear processing if (*p->nlp == 1.0) { in = (1.0 / tanh(*p->saturation)) * tanh(*p->saturation * in); } else if (*p->nlp == 2.0) { in = tanh(*p->saturation * in); } // form input to loop double un = (in - k * SIGMA) / (1.0 + k * GAMMA); // 1st stage double xin = un * gamma1 + fb2 + epsilon1 * fbo1; double v = (a1 * xin - z1) * alpha; double lp = v + z1; z1 = lp + v; // 2nd stage xin = lp * gamma2 + fb3 + epsilon2 * fbo2; v = (a2 * xin - z2) * alpha; lp = v + z2; z2 = lp + v; // 3rd stage xin = lp * gamma3 + fb4 + epsilon3 * fbo3; v = (a3 * xin - z3) * alpha; lp = v + z3; z3 = lp + v; // 4th stage v = (a4 * lp - z4) * alpha; lp = v + z4; z4 = lp + v; p->out[n] = lp; } p->a[0] = a1; p->a[1] = a2; p->a[2] = a3; p->a[3] = a4; p->z[0] = z1; p->z[1] = z2; p->z[2] = z3; p->z[3] = z4; p->G[0] = G1; p->G[1] = G2; p->G[2] = G3; p->G[3] = G4; p->beta[0] = beta1; p->beta[1] = beta2; p->beta[2] = beta3; p->beta[3] = beta4; p->delta[0] = delta1; p->delta[1] = delta2; p->delta[2] = delta3; p->epsilon[0] = epsilon1; p->epsilon[1] = epsilon2; p->epsilon[2] = epsilon3; p->gamma[0] = gamma1; p->gamma[1] = gamma2; p->gamma[2] = gamma3; p->SG[0] = SG1; p->SG[1] = SG2; p->SG[2] = SG3; p->SG[3] = SG4; p->GAMMA = GAMMA; p->SIGMA = SIGMA; p->last_alpha = alpha; p->last_cut = last_cut; return OK; } static int k35_lpf_init(CSOUND* csound, K35_LPF* p) { if (*p->skip == 0.0) { p->z1 = 0.0; p->z2 = 0.0; p->z3 = 0.0; p->last_cut = -1.0; p->last_q = -1.0; p->g = 0.0; p->G = 0.0; p->S35 = 0.0; p->alpha = 0.0; p->lpf2_beta = 0.0; p->hpf1_beta = 0.0; } return OK; } static int k35_lpf_perf(CSOUND* csound, K35_LPF* p) { double z1 = p->z1; double z2 = p->z2; double z3 = p->z3; double last_cut = p->last_cut; double last_q = p->last_q; double g = p->g; double G = p->G; double K = p->K; double S35 = p->S35; double alpha = p->alpha; double lpf2_beta = p->lpf2_beta; double hpf1_beta = p->hpf1_beta; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; double T = csound->onedsr; double Tdiv2 = T / 2.0; double two_div_T = 2.0 / T; int cutoff_arate = IS_ASIG_ARG(p->cutoff); int q_arate = IS_ASIG_ARG(p->q); MYFLT cutoff = cutoff_arate ? 0.0 : *p->cutoff; MYFLT q = q_arate ? 0.0 : *p->q; int nonlinear = MYFLT2LONG(*p->nonlinear); double saturation = *p->saturation; if (UNLIKELY(offset)) { memset(p->out, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&p->out[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { MYFLT in = p->in[n]; if (cutoff_arate) { cutoff = p->cutoff[n]; } if (q_arate) { q = p->q[n]; // clamp from 1.0 to 10.0 q = (q > 10.0) ? 10.0 : (q < 1.0) ? 1.0 : q; } if (cutoff != last_cut) { double wd = TWOPI * cutoff; double wa = two_div_T * tan(wd * Tdiv2); g = wa * Tdiv2; G = g / (1.0 + g); } if (q != last_q) { K = 0.01 + ((2.0 - 0.01) * (q / 10.0)); } if ((cutoff != last_cut) || (q != last_q)) { lpf2_beta = (K - (K * G)) / (1.0 + g); hpf1_beta = -1.0 / (1.0 + g); alpha = 1.0 / (1.0 - (K * G) + (K * G * G)); } last_cut = cutoff; last_q = q; // LPF1 double v1 = (in - z1) * G; double lp1 = v1 + z1; z1 = lp1 + v1; double u = alpha * (lp1 + S35); if (nonlinear) { u = tanh(u * saturation); } // LPF2 double v2 = (u - z2) * G; double lp2 = v2 + z2; z2 = lp2 + v2; double y = K * lp2; // HPF1 double v3 = (y - z3) * G; double lp3 = v3 + z3; z3 = lp3 + v3; // double hp1 = y - lp3; /* FIXME: not used */ S35 = (lpf2_beta * z2) + (hpf1_beta * z3); double out = (K > 0) ? (y / K) : y; p->out[n] = out; } p->z1 = z1; p->z2 = z2; p->z3 = z3; p->last_cut = last_cut; p->last_q = last_q; p->g = g; p->G = G; p->K = K; p->S35 = S35; p->alpha = alpha; p->lpf2_beta = lpf2_beta; p->hpf1_beta = hpf1_beta; return OK; } static int k35_hpf_init(CSOUND* csound, K35_HPF* p) { if (*p->skip == 0.0) { p->z1 = 0.0; p->z2 = 0.0; p->z3 = 0.0; p->last_cut = -1.0; p->last_q = -1.0; p->g = 0.0; p->G = 0.0; p->S35 = 0.0; p->alpha = 0.0; p->hpf2_beta = 0.0; p->lpf1_beta = 0.0; } return OK; } static int k35_hpf_perf(CSOUND* csound, K35_HPF* p) { double z1 = p->z1; double z2 = p->z2; double z3 = p->z3; double last_cut = p->last_cut; double last_q = p->last_q; double g = p->g; double G = p->G; double K = p->K; double S35 = p->S35; double alpha = p->alpha; double hpf2_beta = p->hpf2_beta; double lpf1_beta = p->lpf1_beta; uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t n, nsmps = CS_KSMPS; double T = csound->onedsr; double Tdiv2 = T / 2.0; double two_div_T = 2.0 / T; int cutoff_arate = IS_ASIG_ARG(p->cutoff); int q_arate = IS_ASIG_ARG(p->q); MYFLT cutoff = cutoff_arate ? 0.0 : *p->cutoff; MYFLT q = q_arate ? 0.0 : *p->q; int nonlinear = MYFLT2LONG(*p->nonlinear); double saturation = *p->saturation; if (UNLIKELY(offset)) { memset(p->out, '\0', offset*sizeof(MYFLT)); } if (UNLIKELY(early)) { nsmps -= early; memset(&p->out[nsmps], '\0', early*sizeof(MYFLT)); } for (n = offset; n < nsmps; n++) { MYFLT in = p->in[n]; if (cutoff_arate) { cutoff = p->cutoff[n]; } if (q_arate) { q = p->q[n]; // clamp from 1.0 to 10.0 q = (q > 10.0) ? 10.0 : (q < 1.0) ? 1.0 : q; } if (cutoff != last_cut) { double wd = TWOPI * cutoff; double wa = two_div_T * tan(wd * Tdiv2); g = wa * Tdiv2; G = g / (1.0 + g); } if (q != last_q) { K = 0.01 + ((2.0 - 0.01) * (q / 10.0)); } if ((cutoff != last_cut) || (q != last_q)) { hpf2_beta = -G / (1.0 + g); lpf1_beta = 1.0 / (1.0 + g); alpha = 1.0 / (1.0 - (K * G) + (K * G * G)); } last_cut = cutoff; last_q = q; // HPF1 double v1 = (in - z1) * G; double lp1 = v1 + z1; z1 = lp1 + v1; double y1 = in - lp1; double u = alpha * (y1 + S35); double y = K * u; if (nonlinear) { y = tanh(y * saturation); } // HPF2 double v2 = (y - z2) * G; double lp2 = v2 + z2; z2 = lp2 + v2; double hp2 = y - lp2; // LPF1 double v3 = (hp2 - z3) * G; double lp3 = v3 + z3; z3 = lp3 + v3; S35 = (hpf2_beta * z2) + (lpf1_beta * z3); double out = (K > 0) ? (y / K) : y; p->out[n] = out; } p->z1 = z1; p->z2 = z2; p->z3 = z3; p->last_cut = last_cut; p->last_q = last_q; p->g = g; p->G = G; p->K = K; p->S35 = S35; p->alpha = alpha; p->hpf2_beta = hpf2_beta; p->lpf1_beta = lpf1_beta; return OK; } static OENTRY wpfilters_localops[] = { { "zdf_1pole", sizeof(ZDF_1POLE), 0,5,"a","axOo", (SUBR)zdf_1pole_init,NULL,(SUBR)zdf_1pole_perf}, { "zdf_1pole_mode", sizeof(ZDF_1POLE_MODE), 0,5,"aa","axo", (SUBR)zdf_1pole_mode_init,NULL,(SUBR)zdf_1pole_mode_perf}, { "zdf_2pole", sizeof(ZDF_2POLE), 0,5,"a","axxOo", (SUBR)zdf_2pole_init,NULL,(SUBR)zdf_2pole_perf}, { "zdf_2pole_mode", sizeof(ZDF_2POLE_MODE), 0,5,"aaa","axxo", (SUBR)zdf_2pole_mode_init,NULL,(SUBR)zdf_2pole_mode_perf}, { "zdf_ladder", sizeof(ZDF_LADDER), 0,5,"a","axxo", (SUBR)zdf_ladder_init,NULL,(SUBR)zdf_ladder_perf}, { "diode_ladder", sizeof(DIODE_LADDER), 0,5,"a","axxOPo", (SUBR)diode_ladder_init,NULL,(SUBR)diode_ladder_perf}, { "K35_lpf", sizeof(K35_LPF), 0,5,"a","axxOPo", (SUBR)k35_lpf_init,NULL,(SUBR)k35_lpf_perf}, { "K35_hpf", sizeof(K35_LPF), 0,5,"a","axxOPo",(SUBR) k35_hpf_init,NULL,(SUBR)k35_hpf_perf}, }; LINKAGE_BUILTIN(wpfilters_localops) csound-6.10.0/Opcodes/wpfilters.h000066400000000000000000000053741321653344700166760ustar00rootroot00000000000000/* wpfilters.h: Copyright (C) 2017 Steven Yi This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Zero Delay Feedback Filters Based on code by Will Pirkle, presented in: http://www.willpirkle.com/Downloads/AN-4VirtualAnalogFilters.2.0.pdf and in his book "Designing software synthesizer plug-ins in C++ : for RackAFX, VST3, and Audio Units" ZDF using Trapezoidal integrator by Vadim Zavalishin, presented in "The Art of VA Filter Design" (https://www.native-instruments.com/fileadmin/ni_media/ downloads/pdf/VAFilterDesign_1.1.1.pdf) Csound C versions by Steven Yi */ #include "csoundCore.h" typedef struct { OPDS h; MYFLT *out; MYFLT *in, *cutoff, *mode, *skip; MYFLT last_cut, G; double z1; } ZDF_1POLE; typedef struct { OPDS h; MYFLT *outlp, *outhp; MYFLT *in, *cutoff, *skip; MYFLT last_cut, G; double z1; } ZDF_1POLE_MODE; typedef struct { OPDS h; MYFLT *out; MYFLT *in, *cutoff, *q, *mode, *skip; double last_cut, last_q, g, R; double z1, z2; } ZDF_2POLE; typedef struct { OPDS h; MYFLT *outlp,*outbp, *outhp; MYFLT *in, *cutoff, *q, *skip; double last_cut, last_q, g, R; double z1, z2; } ZDF_2POLE_MODE; typedef struct { OPDS h; MYFLT *out; MYFLT *in, *cutoff, *q, *skip; double last_cut, last_q, last_k, last_g, last_G, last_G2, last_G3, last_GAMMA; double z1, z2, z3, z4; } ZDF_LADDER; typedef struct { OPDS h; MYFLT *out; MYFLT *in, *cutoff, *kval, *nlp, *saturation, *skip; double a[4], z[4], G[4], beta[4], delta[3], epsilon[3], gamma[3], SG[4]; double SIGMA, GAMMA, last_alpha, last_cut; } DIODE_LADDER; typedef struct { OPDS h; MYFLT *out; MYFLT *in, *cutoff, *q, *nonlinear, *saturation, *skip; double z1, z2, z3, last_cut, last_q, g, G, K, S35, alpha, lpf2_beta, hpf1_beta; } K35_LPF; typedef struct { OPDS h; MYFLT *out; MYFLT *in, *cutoff, *q, *nonlinear, *saturation, *skip; double z1, z2, z3, last_cut, last_q, g, G, K, S35, alpha, hpf2_beta, lpf1_beta; } K35_HPF; //typedef struct { // //} K35HPF; static int zdf_ladder_perf(CSOUND * csound, ZDF_LADDER * p); csound-6.10.0/README.md000066400000000000000000000064231321653344700143650ustar00rootroot00000000000000# CSOUND Version 6.09 beta [![Build Status](https://travis-ci.org/csound/csound.svg?branch=develop)](https://travis-ci.org/csound/csound) ![Coverity Status](https://scan.coverity.com/projects/1822/badge.svg) [![Build status](https://ci.appveyor.com/api/projects/status/1qamc986774rsbjq/branch/develop?svg=true)](https://ci.appveyor.com/project/csound/csound/branch/develop) A user-programmable and user-extensible sound processing language and software synthesizer. Csound is copyright (c) 1991 Barry Vercoe, John ffitch, and other contributors. Csound is free software; you can redistribute them and/or modify them under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that they will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this software; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # GETTING STARTED CsoundQt, a graphical shell for Csound, is an excellent place to begin the exploration of Csound, especially as CsoundQt has an extensive menu of built-in examples that show off Csound's capabilities. Many musicians make CsoundQt their main Csound environment, although there are other excellent environments. CsoundQt runs not only Csound code, but also Python scripts and, in the latest version, HTML5 code. The examples directory and its subdirectories contain numerous working Csound orchestras, and even complete pieces. The Csound Reference Manual may be found online at http://csound.github.io/docs/manual/indexframes.html, or it may be installed with Csound in a location that varies by operating system. This version of Csound is programmable in C, C++, JavaScript, Python, Java, Lua, and Common Lisp, and scores can be generated in these languages. The Csound API application programming interface reference may be found online at http://csound.github.io/docs/api/index.html, or it may be installed with Csound in a location that varies by operating system. The API reference is generated from and for the C and C++ API, but it is also helpful when programming Csound in other languages. # CONTRIBUTORS Csound contains contributions from musicians, scientists, and programmers from around the world. They include (but are not limited to): * Allan Lee * Andres Cabrera * Anthony Kozar * Bill Gardner * Bill Verplank * Dan Ellis * David Macintyre * Ed Costello * Eli Breder * Fabio P. Bertolotti * Felipe Sataler * Gabriel Maldonado * Greg Sullivan * Hans Mikelson * Henri Manson * Ian McCurdy * Istvan Varga * Jean Piché * Joachim Heintz * John Ramsdell * John ffitch * Marc Resibois * Mark Dolson * Matt Ingalls * Max Mathews * Michael Casey * Michael Clark * Michael Gogins * Mike Berry * Nate Whetsell * Paris Smaragdis * Perry Cook * Peter Neubäcker * Peter Nix * Rasmus Ekman * Richard Dobson * Richard Karpen * Rob Shaw * Robin Whittle * Rory Walsh * Sean Costello * Stephen Kyne * Steven Yi * Tito Latini * Tom Erbe * Victor Lazzarini * Ville Pulkki csound-6.10.0/Release_Notes/000077500000000000000000000000001321653344700156315ustar00rootroot00000000000000csound-6.10.0/Release_Notes/Version_6.00000066400000000000000000000423471321653344700176560ustar00rootroot00000000000000============================ CSOUND VERSION 6.00 RELEASE NOTES ============================ Csound version 6 provides significant advances in functionality over version 5, not only for the Csound application, but also for the Csound library and application programming interface (API). Complete backward compatibility has been retained for all orc/sco/csd based works, but changes in the API are not backwardly compatible. The major changes for Csound 6 are: o A --sample-accurate option provides sample-accurate timing of score events. This breaks backward compatibility for plugin opcodes, which require code changes for tracking current sample frame position in audio type variables (see below for an example). o A --realtime option, which can also be enabled by setting the CSOUND_PARAMS field realtime_mode to 1, provides asynchronous execution of file reading and writing, and of init-time orchestra code. This should make real-time operation of Csound more resistant to dropouts. o New opcodes and syntax support arrays of arbitrary dimensionality. Arrays are created (usually) with the init opcode or with fillarray: k1[] init 4 generates a k-rate 1-dimensional array of length 4. Similarly, a2[][] init 4, 4 creates a square, 4 x 4 a-rate array. Or, k2[] fillarray 1, 2, 3, 4 creates a 4-element vector filled with {1, 2, 3, 4}, and implicitly defines a length. Array elements are indexed with brackets [] such as k1[2] or a2[2][3]. One dimensional arrays replace tvars, and can be used in opcodes like maxtab/maxarray, mintab/minarray and sumtab/sumarray (see below). Array setting can also be done on the left-hand side of opcodes, e.g.: aSigs[0] vco2 .1, 440 aSigs[1] vco2 .1, 880 o Multicore support has been completely rewritten using an improved algorithm for task dispatching, which should use less memory and fewer locks. Multicore benchmarks are now much faster than before. Multithreading often provides significant speedups over single-threaded rendering. o Compilation of instruments and orchestra code can be done at any stage; new instruments can be added or can replace old instruments with the same name/number even while Csound is running. o The Csound API has been cleaned up and extended to support new functionality. ================== USER-LEVEL CHANGES ================== New opcodes: o faustgen o array -- many new or revised opcodes -- see below under orchestra. o compileorc -- takes a filename containing a collection if instrument definitions and compiles them, replacing existing versions. It returns 0 on success. o compilestr -- like compileorc, but takes a string of orchestra code. o readscore -- runs the score preprocessor on a string and then schedules new events via the RT event mechanism, returning 0 if successful. New Gen and Macros: Orchestra: o Note events can start and end in mid-kcycle. As this is an incompatible change it is only invoked with the command-line option --sample-accurate is specified. Note that this does not work for tied notes, and skipping initialisation is probably not useful. o Instruments can run at local values of ksmps using setksmps iksmps as in Csound 5 UDOs. o Compilation can be done at any stage; new instruments can be added or can replace old instruments with the same name/number. Running instances of old instrument definitions are not affected. The only limitation is that header constants in instr 0 are read only once at the time of the first compilation. Init-time code can be placed outside instruments in the global space, but this also will be executed only once following the compilation. In this way, score event generation can be completely replaced by orchestra code. See also the new opcodes compileorc and compilestr. o New syntax operators +=, -=, *= and /=. These are more than syntactic sugar; please use += and -= for accumulating reverbs as it gives better multicore behaviour. o The opcodes add, sub, mul and div have been deleted; use the forms + - * /. Not many people were aware of these opcodes. o Any opcode with zero outputs or one output can be used as a function. Some opcodes might require type annotation to resolve ambiguities; see the the new syntax page in the Csound 6.00 manual. o A statement can be broken across lines after a , = or any arithmetic operation. o There are a range of new or recoded operations on k-valued arrays, most restricted to 1 dimensional arrays (vectors): kans minarray ktab returns the smallest value in the (possibly) multidimensional array kans maxarray ktab returns its largest value kabs sumarray ktab returns sum of all values in the array ktab genarray imin, imax[, inc] generates vector of values from imin to imax by increments of inc (default 1) ktab2 maparray ktab1, "sin" maps the k-rate 1-arg function in the string to every element of the vector ktab2 maparray_i ktab1, "sin" maps the i-rate 1-arg function in the string to every element of the vector ktab2 slicearray ktab1, istart, iend returns a slice of ktab1 from ktab1[istart] to ktab1[iend] copyf2array ktab, kfn copies data from an ftable to a vector copya2ftab ktab, kfn copies data from a vector to an ftable. o Arithmetic on arrays is allowed. In particular addition, subtraction, multiplication, and division are provided in arithmetic syntax on vectors. Similar operations between arrays and scalars are also allowed. o Each instance of every instrument has a scratchpad of 4 values that persists after turnoff; this allows values to carry to next use of the instrument; this may be useful for legato etc. o If a table number is given as -1 then an internal sine wave equivalent to "f. 0 16384 10 1" is used. Attempts to write to this table will give unpredictable results, but is not policed. The 16384 can be change by command line option --sine-size=# where the # is rounded up to a power of two. o A number of oscil opcodes now have the f-table parameter as optional, defaulting to the internal sine wave. (oscil1, oscil1i, oscil, oscil3, oscili, foscil, foscil1, loscil, loscil3, poscil, poscil3) Score: o Score lines can have multiple strings. o Change to escape characters in score strings -- they do not happen. o Also see readscore opcode Modified Opcodes and Gens: o The k() function can take an a-rate argument, in which case it invokes a call to the downsamp opcode. Utilities: o Hetro/adsyn analysis files can be machine byte-order independent if created with -X. The down side is a longer file and a little slower loading. The het_export utility will create the independent format from the old, and het_import is no longer necessary. o cvanal and lpanal will produce machine independent files if the -X option is used. The convolve and lpread etc. opcodes will accept either format. You are encouraged to use the machine independent form. Analysis files produced with -X can be used on other systems. Frontends: o CsoundQt has been ported to Csound 6. o CsoundVST has been ported to Csound 6. o A new Csound6 app for Android has been developed, extending the Csound 5 app with: (1) An improved user interface, including text editing, scrolling performance messages, a built-in User Guide, and links to the Csound manual and Web site. (2) Plugin opcodes, including the signal flow graph opcodes, the FluidSynth opcodes, and the Lua opcodes, which enable executing arbitrary Lua coded in Csound using the very fast LuaJIT engine, even writing opcodes in Lua, and calling any public C function from Csound using LuaJIT's FFI. General usage: o The environment variables for module directories have been renamed OPCODE6DIR64 or OPCODE6DIR (note the 6) so they can co-exist with directories for Csound 5 modules. o Similarly, .csoundrc has been renamed .csound6rc. Bugs fixed: o Too many to record! =========== API CHANGES =========== New configuration/parameter setting functions: PUBLIC int csoundSetOption(CSOUND *csound, char *option); PUBLIC void csoundSetParams(CSOUND *csound, CSOUND_PARAMS *p); PUBLIC void csoundGetParams(CSOUND *csound, CSOUND_PARAMS *p); PUBLIC void csoundSetOutput(CSOUND *csound, char *name, char *type, char *format); PUBLIC void csoundSetInput(CSOUND *csound, char *name); PUBLIC void csoundSetMIDIInput(CSOUND *csound, char *name); PUBLIC void csoundSetMIDIFileInput(CSOUND *csound, char *name); PUBLIC void csoundSetMIDIOutput(CSOUND *csound, char *name); PUBLIC void csoundSetMIDIFileOutput(CSOUND *csound, char *name); New parsing/compilation functions: PUBLIC TREE *csoundParseOrc(CSOUND *csound, char *str); PUBLIC int csoundCompileTree(CSOUND *csound, TREE *root); PUBLIC int csoundCompileOrc(CSOUND *csound, const char *str); PUBLIC int csoundReadScore(CSOUND *csound, char *str); PUBLIC int csoundCompileArgs(CSOUND *, int argc, char **argv); New function for starting csound after the first compilation: PUBLIC int csoundStart(CSOUND *csound); New threadsafe getters/setters for the software bus: PUBLIC MYFLT csoundGetControlChannel(CSOUND *csound, const char *name); PUBLIC void csoundSetControlChannel(CSOUND *csound, const char *name, MYFLT val); PUBLIC void csoundGetAudioChannel(CSOUND *csound, const char *name, MYFLT *samples); PUBLIC void csoundSetAudioChannel(CSOUND *csound, const char *name, MYFLT *samples); PUBLIC void csoundSetStringChannel(CSOUND *csound, const char *name, char *string); PUBLIC void csoundGetStringChannel(CSOUND *csound, const char *name, char *string); New threadsafe copy functions for tables: PUBLIC void csoundTableCopyOut(CSOUND *csound, int table, MYFLT *dest); PUBLIC void csoundTableCopyIn(CSOUND *csound, int table, MYFLT *src); The entire Csound API has been made threadsafe so that performance and control can occur in separate threads (after a call to csoundStart() or csoundCompile()). Thread safety has been implemented by: o Using atomic operations for reading and writing in control channels, o Using spinlocks in audio and string channels, o Using mutexes to protect compilation, score events, and table access. The Csound API and SDK for iOS has been changed to use Automatic Resource Counting (ARC). All projects using Csound 6 for iOS will require the use of ARC. The Csound for iOS Examples project shows how to use ARC compliant code with Csound. Users with existing Csound 5-based iOS projects can use the "Edit->Refactor->Convert to Objective-C ARC..." wizard to help with updating their projects to use ARC. For more information about ARC, consult the "Transitioning to ARC Release Notes" on Apple's Developer website at https://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/ The Csound API and SDK for Android has been changed to use the new Csound API. ==================== SYSTEM LEVEL CHANGES ==================== System changes: o in Linux and OSX, locales are now thread-safe and local. Internal changes: o The build system now uses CMake (instead of SCons as in Csound 5). o A number of table access opcodes have been rewritten, but should behave the same. o Similarly diskin and diskin2 now use the same code, so that diskin should be more stable o The old parser has been completely removed. o New internal functions in CSOUND: void (*FlushCircularBuffer)(CSOUND *, void *); void *(*FileOpenAsync)(CSOUND *, void *, int, const char *, void *, const char *, int, int, int); unsigned int (*ReadAsync)(CSOUND *, void *, MYFLT *, int); unsigned int (*WriteAsync)(CSOUND *, void *, MYFLT *, int); int (*FSeekAsync)(CSOUND *, void *, int, int); char *(*GetString)(CSOUND *, MYFLT); Extract a string originating from a score-event argument. o Functions removed from CSOUND: void *(*FileOpen)(CSOUND *, void*, int, const char*, void*, const char*); o The "private" parts of the API have been changed considerably. Also structures like EVTBLK have been changed. o The LINKAGE1/FLINKAGE1 macros have been renamed to LINKAGE_BUILTIN/FLINKAGE_BUILTIN The template for arate perf-pass opcodes is: int perf_myopcode(CSOUND *csound, MYOPCODE *p) { uint32_t offset = p->h.insdshead->ksmps_offset; uint32_t early = p->h.insdshead->ksmps_no_end; uint32_t nsmps = CS_KSMPS; ... if (UNLIKELY(offset)) memset(p->res, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->res[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nres[n] = .... } return OK; } Csound's string variable type has been re-implemented. The OENTRY structure has been changed. It has a new dependency field. This field is now required for multicore semantics. Setting this field to -1 safely disables parallel execution, but it is recommended to enable parallel execution by using the flags defined in include/interlocks.h If your opcode reads or writes to zak space, use ZR or ZW, or ZB for both. Similarly, if it reads or writes tables, use TR, TW or TB. If it reads or writes to channels, use CR, CW and CB. If it uses the stack, use SK. If it outputs text, then use WR to stop mixing of output. The _QQ flag marks an opcode as deprecated. Other flags may be added later. All opcodes that touch audio should take note of sample-accurate code. A number of previous API functions have been removed. OpenFile and OpenFile2 have both been replaced by new OpenFile2 with an additional argument. Additions have been made for arg type specifications for opcodes. o Any-types have been added, as follows: * '.' signifies a required arg of any-type * '?' signifies an optional arg of any-type * '*' signifies a var-arg list of any-type o Arrays are now specified using "[x]" where x is a type-specifier. The type-specifier can be any of the of the current specifiers, including any-types. See Opcodes/arrays.c for examples of usage. New Type System =============== A new type system has been added to Csound6, and significant changes have been made to the compiler. The previous system for handling types involved reading the first letter of a variable's name every time the variable was used to determine its type. This meant there was much re-checking of types. Also, adding new types was difficult, because much custom code had to be updated to check for new type letters. In Csound6, a separate system of types has been added. Types are defined as CS_TYPEs. The creation of variables from types and the initialisation of memory has been encapsulated within the CS_TYPEs. This change allows easier addition of new types, as well as generic calculations of memory pools, amongst other things. The compiler has been changed to use the new type system in its semantic checking phase. Variables are now registered into a CS_VAR_POOL when they are first defined, with the CS_VARIABLE having a reference to its CS_TYPE. After first time definition within the pool, the type information is looked up in consequent variable uses, rather than re-calculated from the variable name. This opens up possibilities for new variable naming and typing strategies, i.e. using "myVar:K" to denote a k-rate arg. It also opens up possibilities for user-defined types, such as "data myType kval, aval", then using "myVar:myType" to define a var of that type. (The previous is speculative, and is not an active proposal at this time.) The addition of the type system has formalised the static type system that has existed in Csound prior to Csound6. It has, arguably, simplified the code-base in terms of type handling, as well as laid groundwork for future type-related research to be integrated into Csound. ======================================================================== csound-6.10.0/Release_Notes/Version_6.01000066400000000000000000000104071321653344700176470ustar00rootroot00000000000000============================ CSOUND VERSION 6.01 RELEASE NOTES ============================ This new version has a large number of bug fixes (including clearing all tickets on SourceForge) as well internal changes to improve performance. Perhaps the biggest changes however is in the use of arrays. Many opcodes can now use array inputs or outputs, and the previous array opcodes have been widened to all rates as appropriate. USER-LEVEL CHANGES ================== New opcodes: o midifilestatus (UNDOCUMENTED) o signum function New Gen and Macros: None Orchestra: o A number of small fixes have been made to the parser, such as to then in i-rate, the boolean in until loop (#40), ... Score: None Modified Opcodes and Gens: o Fault opcode runs in its own thread o Many extensions to array opcodes, more flexible regarding i , k or a type o Opcodes in, fin, diskin, diskin2, vbap, vbap_move, vbapg, vbapgmove,... now accept array output argument o Opcodes out, fout accepts an array for input o pvs2tab now works with arrays as well (#52, #54) Utilities: None Frontends: o fixes to PD class and csound~ General usage: o Length of strings arbitrary o made tieflag and reinitflag per instance o Using an undefined variable no longer causes a crash o in lists of directories in environment values ; and : are both allowed, with preference based on the operating system Bugs fixed: o Issues in Multidimension arrays fixed o Some parser bugs fixed o Fixed bug in realtime-mode initialisation pass o rtjack reworked o ftload fixed o crashes in pset fixed o fixes in use of strings o fix arrays in UDOs o fix to strlen o fix bug in strsub o fix overwriting of arrays in assignment o fix subinstr o fix chnexport initialisation o fixed bug in setting system constants o stupid error in cell fixed o fixed ksmps inconsistency check o fix bug in string assignment o fixed strcat opcode o fixed sprintf bug o ftconv fix o fix bug in loscil and related opcodes o fixed issues on failure to compile Faust code o fixed framecounting in pvsfromarray ==================== SYSTEM LEVEL CHANGES ==================== System changes: o Fixed issues with error value for csoundGetControlChannel and added new checks in channel tests to evidence channel registration error. o pvs channels made threadsafe o A potential danger in calling csoundDestroy has been removed (#6) o integration of CSOUND_PARAMS to oparms(#23) Internal changes: o improving cpu consumption of diskin2 in async mode o minor improvements in moogladder and statevar to avoid recalculation o urandom.i faster o Some memory issues fixed o implemented a workable (but not ideal) fix that allows using array syntax with a-sigs (#43) o API === o csoundStart() is now called if it has not been already o fixed moduleDestroy to only destroy engine instances for CSOUND that is passed in; fixes Android crashing bug o ReadSco fixed to process f-statements correctly(#56) Platform Specific ================= iOS --- o fixed MIDI Input Windows ------- o better handling of locales o CsoundObj: modified getInputChannelPtr to require passing in the channelType (i.e. CSOUND_CONTROL_CHANNEL, CSOUND_AUDIO_CHANNEL); previously getInputChannelPtr was hardcoded for only control channels. This is a non-backwards compatible change. To update previous project, add "controlChannelType.CSOUND_CONTROL_CHANNEL" when calling getInputChannelPtr(#26) o added -source and -target settings when compiling java interface wrapper; set to 1.6 for both source and target (#44) OSX --- o better handling of locales o set the -mmacosx-version-min=10.6 flag when compiling to allow running the build artifacts on 10.6 and up (note: also required support libs to be compiled with -mmacosx-version-min flag) Linux ----- o thread-unsafe code to handle locales better ======================================================================== csound-6.10.0/Release_Notes/Version_6.03000066400000000000000000000137161321653344700176570ustar00rootroot00000000000000 ============================ CSOUND VERSION 6.03 RELEASE NOTES ============================ This new version has a large number of bug fixes (including clearing many tickets on SourceForge and GitHub) as well internal changes to improve performance. USER-LEVEL CHANGES ================== New opcodes: o printks2: Prints a new value every time a control variable changes using a printf() style syntax. o mp3sr mp3bitrate and mp3nchnls to get information on mp3 files o EXPERIMENTAL: CUDA opcodes for partitioned convolution direct convolution and sliding phase vocoding; OpenCL opcode for additive synthesis o compilecsd to compile instruments from a standard CSD file New Gen and Macros: Orchestra: o The argument for i() is supposed to be a variable not an expression. This is now enforced. (bug #90) Score: o New score opcode y sets the random seed (for ~) at read time Options: This was a bug in CsOptions; the last argument was missed being read (issue #296) As command-line options expression-opt and no-expression-opt do nothing in Csound6 a warning is printed. Modified Opcodes and Gens: o For ogg output it is possible to specify a VBR (variable bit rate) quality. o dssi4cs code has been extensively reworked to avoid potential memory faults. o Many array operations now available for i-arrays as well as k-arrays. o fillarray will work for string arrays o Displays of FFT (via dispfft) improved with scaling/zooming options o Signal flow graph opcodes are now working with a-rate array signals. o In alsa rt code the sample rate is taken from the device o Faust opcode system updated to latest Faust API. Utilities: o fixed bug in lpanal Frontends: csound~: o OSX - fix for running with 32-bit cpu architecture o Windows - csound~ now available for Windows Emscripten: This is now generally merged in to the code-base General usage: o --displays now switches graphs on, as expected o New command-line option --get-system-sr added to obtain the machine's sample rate. o New command-line option --devices[=in|out] gives a list of available audio devices and then exit Bugs fixed: o fixed the bug when tables were replaced but the size did not change o A number of bugs in --sample-accurate have been detected and fixed. This includes opcodes out, outn, and line. o A number of bugs in grain3 were fixed# o Bug in str_chanel could cause a crash; fixed o Small bug in rtjack fixed o Error in resize opcode corrected o Fixed an unlikely bug in atsa o Fixed rtauhal pause issue o Fixed bug in rtjack o A number of bugs/untidiness fixed in GEN23 o Array bound checks fixed o strings channels were not correctly set for dynamic-size strings, now fixed o memory allocation for string formatting in printfsk was fixed, stopping string truncation. o strcat safe against overflow o error in compilation of arrays fixed (issue #293) o GetPvsChannel fixed against a crash ==================== SYSTEM LEVEL CHANGES ==================== System changes: o turnoff opcode now checks that the instrument being affected is active o lenarray can accept any array type o the way of rounding a table number to an integer was changed and is now more as expected. o there is a new possible section in a csd file called which is like csFileB but with unencoded text. o UDO compilation now uses the type system. This means that UDOs now allow any array type to be used. o Improved orchestra parsing speeds with better algorithms Internal changes: The whole system has been checked by the Coverity static checker which identified a number of (mainly minor) problems. These have been reviewed and checked. In particular better use of printing and string copying should prevent overflows. The type and variable system has been extensively rewritten; this allows better array and UDO support. Alignment of variables got right in all cases array copying is now using the type system to copy values; fixes issues with copying string arrays, f-sigs, etc. Always reset Csound when stopping to ensure state is clean; was not being reset when there was a compile error, so that next successful run would start with an invalid Csound engine (issue #305) API === All opcodes etc now use the API memory allocation operations, so it is possible to replace the whole memory allocator. Added csoundCompileCsd to API and associated new compilecsd opcode Protected csoundGetStringChannel against null and short strings and added a check for string size A number of API functions have had char* changed to const char* which reflect the usage The performance engine now includes debugging capabilities to allow interrupting rendering and providing introspection into the engine's state and instrument variables. The following new functions are available by including the csdebug.h header: void csoundDebuggerInit (CSOUND *csound) void csoundDebuggerClean (CSOUND *csound) void csoundSetInstrumentBreakpoint (CSOUND *csound, MYFLT instr, int skip) void csoundRemoveInstrumentBreakpoint (CSOUND *csound, MYFLT instr) void csoundClearBreakpoints (CSOUND *csound) void csoundSetBreakpointCallback (CSOUND *csound, breakpoint_cb_t bkpt_cb, void *userdata) void csoundDebugContinue (CSOUND *csound) void csoundDebugStop (CSOUND *csound) INSDS * csoundDebugGetInstrument (CSOUND *csound) Platform Specific ================= iOS --- Windows ------- Soundfonts in Windows had an internal alignment problem which is fixed. OSX --- Linux ----- ======================================================================== csound-6.10.0/Release_Notes/Version_6.04000066400000000000000000000143051321653344700176530ustar00rootroot00000000000000 ============================ CSOUND VERSION 6.04 RELEASE NOTES VERSION 6.04 ============================ This new version has many extensions and fixes; many new opcodes and significant numbers of internal reworking. There is a new frontend and iOS and Android version have seen many improvements. As ever we track bugs and requests for enhancements via the github issues system. Already proposals for the next release are being made but the volume of changes require a release now. The Developers USER-LEVEL CHANGES ================== New opcodes: o pinker generates high quality pink noise o power opcode ^ now works with array arguments o exciter opcode, modelled on the calf plugin , o vactrol opcode simulate an analog envelope follower o family of hdf5 opcodes to handle hdf5 format files o (experimental undocumented) buchla opcode models the lowgate filter of Buchla o New k-rate opcodes acting on arrays: - transforms: rfft, rifft, fft, fftinv - complex product: complxprod - polar - rectangular conversion: rect2pol, pol2rect, mags, phs, - real - complex: r2c, c2r - windowing: window - cepstrum: pvsceps, iceps, ceps - column / row access: getrow, getcol, setrow, setcol - a-rate data - k-array copy: shiftin, shiftout - phase unwraping: unwrap New Gen and Macros: Orchestra: o Line numbers corrected in instr statements o New control operation, while, for looping o A long-standing bug with macros which use the same name for an argument has been corrected o Redefinition of an instrument in a single call to compile is flagged as an error o ID3 header skip for mp3 files now properly implemented. o Errors induced by not defining the location of STK's raw wave files has been removed o bug fixed where UDO's could not read strings from pfields o bug fixed which hid tb opcodesat i-rate o Attempts to use two OSClisteners with the same port is now trapped rather than give a segmenttion fault Score: Options: Modified Opcodes and Gens: o stackops opcodes deprecated o lenarray extended to handle multi-dimensional arrays o ftgenonce accepts string arguments correctly and multiple string arguments o max and min now have initialisation-time versions o gen23 improved regarding comments and reporting problems o in OSCsend the port is now a k-rate value o socksend now works at k-rate o a number of envelope-generating opcodes are now correct in sample-accurate mode o faust compilation is now lock-protected o mp3 fixed to allow reinit to be used with it. o In remote opcode the name of the network can be set via the environment variable CS_NETWORK. Defaults to en0 (OSX) or eth0. o invalue, outvalue are available at i-rate as well as k-rate Utilities: Frontends: icsound: New frontend icsound is now ready for general use. icsound is a python interface for interactive work in the ipython notebook. csound~: Emscripten: csdebugger: A number of changes and improvements have been made, like stepping through active instruments, better line number use General usage: Jack module now does not stop Csound if autoconnect fails Bugs fixed: o atsinnoi fixed o ftsavek fixed o sprintf fixed o gen27 fixed, especially with extended arguments, as well as fixed a number of errors in extended score arguments. o Physem opcodes (guiro cabasa, sekere) fixed so second call works o flooper fixed in mode 2 o OSCsend multiple fixes o UDO fix for case of local ksmps of 1 o More changes/fixes to dssi code o xscanu and scanu fixed o temposcal and mincer fixed o crash in ftload fixed ==================== SYSTEM LEVEL CHANGES ==================== System changes: o In server mode exit is now clean o Fixes to rtalsa module o Pulseaudio rt module fixes o Fix to remove fluidEngine entries for csound instance (prevents crash on moduleDestroy) o Opcodes called through function calls that returned arrays did not correctly synthesize args as array types due to not converting the arg specifier to the internal format o fixed crashing issue during note initialization for tied notes due to goto skipping over code o fixed incorrect initialization of pfields when note's pfields length were less than instrument expected (off-by-one) Internal changes: * Added Runtime Type Identification for instrument variables; removed use of XINCODE/XOUTCO * fix malloc length in negative number parsing, and improved handling of negative numbers * writing to circularBuffer is now atomic * a number of memory leaks and potential dangerous code have been fixed * type-inference has been extensively reworked, as have a few parsing areas API === * Added API function for retrieving GEN parameters used for creating a table Platform Specific ================= iOS --- * API Refactored for clearer method names and abstraction names (i.e. CsoundBinding instead of CsoundValueCacheable) * Updated to remove deprecated code * A significant amount of reworking has been done on the code Android ------- * API Refactored for clearer method names and abstraction names (i.e. CsoundBinding instead of CsoundValueCacheable) * Changes to enable HTML 5 with JavaScript and it is to be hoped WebGL in the Csound6 Android app. * Enabled change of screen orientation in the Csound6 app without forcing a restart of the app. * Enabled local storage (useful for saving and restoring widget values, etc.). Windows ------- * fixed pointer arithmetic that caused crashing on Windows * pyexec changed to use python's file opening functions to prevent crash on Windows OSX --- * CsoundAC now compiles Linux ----- * threadlocks bug fix on linux. ======================================================================== csound-6.10.0/Release_Notes/Version_6.05000066400000000000000000000121071321653344700176520ustar00rootroot00000000000000 ============================ CSOUND VERSION 6.05 RELEASE NOTES VERSION 6.05 ============================ As ever there are new facilities and numerous bug-fixes. A major part of this release is the removal of a number of memory leaks and over use of memory. Naturally these changes are all but invisible, just a smaller memory foot-print. Note that we track bugs and requests for enhancements via the github issues system,, and these had a significant affect on this release. The Developers USER-LEVEL CHANGES ================== New opcodes: o **None** o Thre opcode sndload is now deprecated New Gen and Macros: o Paul Octavian Nasca's padsynth algorithm implemented as a gen. Orchestra: Score: o Fixed string location calculation bug when processing score lines [fixes #443] Options: o A short-format copyright option is available, with a fixed number of well-known licences (CC, etc) o New command-line option to report MIDI devices in simple format o New command-line option to set ksmps Modified Opcodes and Gens: o adsynt handles amplitude changes better o sfont has better checking for corruptions o better checking in physical models for out-of-range frequencies o ftgenonce and others allows string parameters o gausstrig reworked and extended with new features 0 use of p() function no longer complains overrides the pcnt warning o fix to midirecv o OSCsend cleans up after use improved o fillarray is limited to 1 or 2 dimensional arrays; in fact it failed silently previously for 3D and higher. o oscbnk now works when the equaliser is used. o mp3in now works with both mono and stereo input files o flooper & flooper2 now allow stereo tables o Release phase of expsegr fixed o f-tables created by a large number of arguments could overwrite memory, now fixed o performance of plltrack improved o init of arrays clarified and checked o gen23 corrected to stop an infinite loop o alwayson now starts from score offset; this is part of a fix to the long-standing problem with alwayson in CsoundVST o invalue now checks for output string size and reallocates memory if smaller than default string size (set at 256 bytes for backwards compatibility) Utilities: o The srconv utilityy has been improved but it does not work well, with groups of noise in otherwise good output. We recomment the use of Erik de Castro Lopo's Secret Rabbit Code (aka libsamplerate) as providing sanmplrate conversion at high quailty. srconv wuill be removed shortly possibly to be replaced by an SESRC-based utility. Frontends: pnacl: added interface to allow the use of Csound's MIDI input system. fixed audio input to conform to the latest Pepper API spec. icsound: csound~: Emscripten: csdebugger: General usage: Bugs fixed: o bugs in fastabi, oscktp, phasorbnk, adsr, xadsr, hrtfer fixed o bugs in the harmon. harmon2, harmon3 and harmon4 fixed o Csound could crash after a parsing error, a case now removed ==================== SYSTEM LEVEL CHANGES ==================== System changes: o There are now checks that xin/xout types match those defined as part of UDO definition. o jack now has a timeout Internal changes: * Many defects indicated by coverity fixed or code changed. Should make csound more robust in edge cases. * Parser-related changes simplifies allocation of temporary variables, with some new optimisations. * code for multi-thread rendering improved and stablised vis-a-vis redefinition of instruments. API === * Platform Specific ================= iOS --- * fixed audio callback to work correctly with lightning output and Apple TV. Android ------- * New experimental audio IO mode: csoundPerformKsmps() is called from the OpenSL ES output callback. This mode can be optionally enabled by passing a value of "false" to a new second parameter to the CsoundObj constructor (bool isAsync). The default constructor and the one-parameter sets this to "true" (keeping backwards compatibility with existing code). * The OSC and exciter opcodes are included in distribution. * There are new file open and save dialogs that permit the user to access the SD card on the device, if there is one, in addition to internal storage. * There is a new "Save as..." button that permits the user to save the csd as a new file with a new name. * Many of the examples in the archive of Android examples are now built into the app and can be run from the app's menu. Windows ------- OSX --- Installation now places csladspa.so rather than csladspa.dylib on disk. Linux ----- Linux is now build without FLTK threads, This removes system hangs and is in line with other builds ======================================================================== csound-6.10.0/Release_Notes/Version_6.06000066400000000000000000000076231321653344700176620ustar00rootroot00000000000000 ============================ CSOUND VERSION 6.06 RELEASE NOTES VERSION 6.06 ============================ A number of bug fixes, some quite major, are included, as well as some new facilities and extensions The Developers USER-LEVEL CHANGES ================== New opcodes: o getseed reads the state of the PRN generator; opposite of seed opcode. o tabifd — Instantaneous Frequency Distribution, magnitude and phase analysis. o websocket — Read and write signals and arrays using a websocket connection. o framebuffer — Read audio signals into 1 dimensional k-rate arrays and vice-versa with a specified buffer size. o olabuffer — Sum overlapping frames of audio as k-rate arrays and read as an audio signal New Gen and Macros: o Orchestra: o Labels are allowed in instrument 0 Score: o Maximum string length in scores increased to 1024 Options: o Modified Opcodes and Gens: o diskin2 array version uses array size to give number of channels in raw file form o diskin2 now has the kpitch parameter defaulting to 1 for simple use o Vibrato f-table in wgflute and wgcar optional, defaulting to sine wave o schedule now accept string arguments o urandom now available on OSX platforms o GEN18 had fencepost problem; largely rewritten o In poscil family of opcodes it is possible to skip initialisation of phase o svfilter now can skip initialisation o When opening an input file nchncls_i is used rather than nchnls This ia a change that should have followed the existence of nchnls_i o rtjack module now reports the sampling rate o The opcodes rfft, rifft, fft, fftinv, r2c and c2r now have i-rate array versions o New optional threshhold parameter in opcodes tradsyn, sinsyn and resyn o New thresholding option for partials Utilities: o extract fixed o src_conv improved and integrated with -U options o fixes in atsa, and heti Frontends: pnacl: Support for 48000 sample rate fixed icsound: csound~: Changes to the threading system String channel initialisation fixed A number of other bugs were fixed Emscripten: Csound Javascript object can now receive data from the outvalue opcode. csdebugger: HTML5: Integrate HTML, JavaScript, and other features of HTML5 with Csound, either by embedding a Web page as an element in the CSD file for CsoundQt or Csound for Android, or by hosting Csound in the JavaScript context of a standalone Web browser (Emscripten, PNaCl) or embedded Web browser (csound.node). General usage: o Ill-formatted macros in the orchestra now trapped Bugs fixed: o Use of Windows-style environments for INCDIR etc now works with device numbers. o vibrato opcode fixed o clicking in real-time sample accurate case fixed o Copying of strings now correct; did confuse memory sometimes o Bug in pvstanal fixed o Rounding error in cpspch fixed o Removed crash on recompiling a named instrument o Fix interpolation bug in tablexkt 0 Fix to plltrack when ksmps is 1 ==================== SYSTEM LEVEL CHANGES ==================== System changes: o The "error" message from STK plugin is now a warning o Internal changes: * API === * Redefinition of opcodes and UDOs fixed Platform Specific ================= iOS --- * Android ------- * Windows ------- OSX --- - csnd6.jar link installed in the correct location. - Java JNI linking issues solved. - fixed link name for libpng in libfltk_image Linux ----- ======================================================================== csound-6.10.0/Release_Notes/Version_6.07000066400000000000000000000204021321653344700176510ustar00rootroot00000000000000 ============================ CSOUND VERSION 6.07 RELEASE NOTES VERSION 6.07 ============================ A large number of bug fixes, some quite major, some internal are included, as well as some new facilities and extensions. As ever there are coding improvements as well. -- The Developers USER-LEVEL CHANGES ================== New opcodes: o compress2: like compress but using a more normal use of dB (0.0 for full scale). o (Experimental, source code-only) New cuda opcodes cudasynth2 and cudanal2 o directory opcode: Reads a directory and outputs to a string array a list of file names. o ftsamplebank:to load a sample library from a directory. o mvclpf1, mvclpf2, mvclpf3, mvclpf4, mvchpf: Moog voltage-controlled filter emulations from Fons Andriaensen. o S() converter from k-rate and i-time number to a string. o cepsinv opcode to calculate the inverse cepstrum of an array. o moogladder2 is a faster, less accurate implementation of moogladder. o paulstretch opcode is a lightweight implementation of the PaulStretch time-stretching algorithm by Nasca Octavian Paul. It is ideal for timestretching a signal by very large amounts. o mp3scal implements phase-locked vocoder processing from mp3-format disk files, resampling if necessary. o filescal implements phase-locked vocoder processing from disk files, resampling if necessary. New Gen and Macros: o NONE Orchestra: o The boolean ?..:.. construction can now have string results, while previously it only allowed numbers. o The line number reported when an error is detected at the end of a line is now correct. Also more improvements in line numbers for complex syntax o While loop improved/fixed. o Better and consistent reading of comments. o Continuation lines handled better, especially respecting line numbers. o opcode:S(.) syntax now allowed. Score: o The list of tempo points in score opcode t is now arbitrarily long. o A stupidity in r and { opcodes fixed. Options: o The -z option now suppresses deprecated opcodes, unless given a 2 or 3 argument. o The new option --fftlib controls which real fft library to use internally (FFTLIB = 0, PFFFT = 1, vDSP = 2) Modified Opcodes and Gens: o In OSC opcodes it is now possible to send and receive arrays, tables and audio. o Better diagnostic if diskin2 fails. o Rezzy now checks for unstable filter and modifies to close stable version. o adsr rewritten so it gives an error if the segments are longer than p3. o Use of diskin to an array ow resizes the output array if necessary. o chnget now checks for a change in chanel name as well as data. o interp can take an optional extra argument to give an initial value. o oscilikts uses a more liberal table lookup. o opcode in can read mono or stereo, obviating the in/ins distinction. o sensekey rewritten to provide better diagnostics and fixes a minor bug. o Fix to a case of defining a macro with arguments. o sockrecv now works at a and k rate. o GEN49 now works from ftgen calls. o GEN34 liberalised in tables it accepts. o chnget now allows channel names to be changed at perf time. o iceps has been renamed cepsinv to avoid name clashes. o mp3 support improved in a number of minor ways. o a minor fix to allow a ladspa plugin to be re-loaded by the host. o better checking in inch Utilities: o Frontends: pnacl: icsound: csound~: Emscripten: csdebugger: * Some memory issues fixed. HTML5: CsoundQT has its own notes at https://github.com/CsoundQt/CsoundQt/blob/develop/release_notes/Release%20N otes%200.9.2.1.md General usage: o The multicore options somewhat improved. o When replacing instruments the new version inherits maxalloc and active flags. o Multicore code now works with midi instruments. o MIDI operations now available via a new rtmidi jack module (-+rtmidi=jack) Bugs fixed: o Fix to trigseq. o Major error in rezzy fixed. o p() fixed for high numbers of p-arguments. o p() now works from MIDI events. o The 31-bit random number generator could give a very short loop if seeded with zero; fixed. o Macros in .orc files now work. o A long-standing bug in display of graphs fixed. o Fixes to the envelope opcodes linen, expsegr, linsegr, cossegr, transegr, envlpx, including new warnings. o Many fixes in string opcodes (strsub, strcpy and others). o Fixed bugs in print formats (sprintf printf prints). o pvsmooth had a missing initialisation. o Array initialisation now robust. o Bug in copya2ftab fixed. o Fix in cudapvsanal (EXPERIMENTAL). o partikkel fix to subsample grain placement. o Opcodes that require an odd number of arguments are now properly checked. o pvswrite now takes proper notice of 0dbfs. o GEN34 now allowing non-power-of-two source tables. o vst4cs will now work on 64bit architecture. o strcat mended. o nstance mended. o fixed small issues in rtauhal module. o Windows installer for 64 bit CPU architecture now sets environment variables on system level as it should. o transeg at k-rate with itype non-zero had an initial delay if one cycle o log function on arrays fixed o Rescaling of named GENs fixed o A fencepost error in reading ATS files believed fixed; it generated spurious errors about file finishing early. o Initialisation error in pvbandp fixed. o readfi string allocation fixed ==================== SYSTEM LEVEL CHANGES ==================== System changes: o Extensive use made of in-memory files. Orc and sco are always thus, as are .csound6rc. This simplifies much internally. o Nested longjmps fixed which affected some API use. o If a non-existent .csd file is presented Csound no longer crashes. o The kcounter value is now consistently an unsigned 64bit value, allowing for long performances. API === * csoundCompileCsdText: New function to compile a CSD from a string of text. * The function call csound->GetKcounter(csound) now returns an unsigned 64 bit integer. Previously it returned a long which is unclear. * ctcsound.py is a new wrapper file to the Csound API for the Python language. It is a pure Python file using the FFI (Foreign Function Interface) module ctypes. It does not depend on Swig, and it works with Python2 and Python3 as well. It uses numpy for its data structures, numpy being the fundamental package for scientific computing with Python. Platform Specific ================= iOS --- * Android ------- * Windows ------- * The Windows installer for Csound now contains all executables built for 64 bit CPU architecture. * The Windows installer for 64 bit CPU architecture now provides NW.js "out of the box." It runs all features of Csound, as well as all features of HTML5, in a browser-like runtime with JavaScript scripting, and includes a Csound editor implemented in HTML. The editor will run pieces either as .csd files with embedded or as .html files calling the csound object, and includes JavaScript debugging. * A new simplified build system has been implemented in the csound/mingw64 directory for building Csound using the MSYS2/mingw64 toolchain. * Linking to pthreads and other libraries now static. * Some limited support for non-ASCII characters in file names. OSX --- * Installer fixed for link names for _csnd6 and _CsoundAC. GNU/Linux --------- * date opcode more accurate. ======================================================================== ======================================================================== Date: Tue May 10 14:49:44 2016 +0100 csound-6.10.0/Release_Notes/Version_6.08.md000066400000000000000000000135161321653344700202610ustar00rootroot00000000000000 # CSOUND VERSION 6.08 RELEASE NOTES As usual there are a number of opcode fixes and improvements, but the major changes are in the language structures. First the score language has all-new treatment of macros and preprocessing, bringing it in line with those of the orchestra. The parsing of the orchestra has had a number of fixes as outlined below. A major, and not totally compatible change as been made in reading and writing array elements. The rate of the index now often determines the time of processing; check the entry below under *Orchestra*. This simplifies much code and seems to capture expectations; the earlier ad hoc code had many anomalies. Also as usual there are a number of new opcodes and internal fixes to memory leaks and more robust code. -- The Developers ## USER-LEVEL CHANGES ### New opcodes - dct -- Discrete Cosine Transform of a sample array (type-II DCT) - getftargs -- copy arguments of a gen to an S-variable - mfb -- implements a mel-frequency filter-bank for an array of input magnitudes ### New Gen and Macros - quadbezier -- generating Bezier curves in a table ### Orchestra - The character ¬ is now correctly treated as a variant of ~ for bitwise not - Lexing bug which could corrupt strings fixed - Ensure no newlines in string-lexing - Small improvement in reported line numbers - Better checking of macro syntax - Improved parsing of setting of labels - Added error handling for unmatched brackets for UDO arg specification - Check that `#included` file is not a directory - Deeply nested macro calls better policed - For years Csound has fixed the pitch of A4 at 440Hz. Now this can be set in the header using the new r-variable A4, and also read with that variable - Floating point values can use e or E for exponent - Array access semantics have been clarified: - i[i] => reading at i-time and perf-time, writing at i-time only. - i[k] => reading at perf-time, writing yields a runtime error - k[i], k[k] => reading at perf-time, writing at perf-time - a[i], a[k] => reading at perf-time, writing at perf-time - other (S[], f[]) => reading and writing according to index type (i,k). In particular, i(k[i]) will continue not to work, as before, but the new operator i(k[],i) is provided to cover this case. - xout validation no longer fails when constants are given ### Score - New code to handle macros and other preprocessor commands. Brings it into line with orchestra code - New score opcode C introduced as a way of switching automatic carry off (`C 0`) or on (default) (`C 1`) ### Options - The tempo setting can now be a floating point value (previously fixed to integer) - New option --version prints version information and exits ### Modified Opcodes and Gens - Problems in centroid fixed. - Better treatment of rounding in printks - OSC extended to include multicast - Faust opcodes brought up to date with faust - oscil1 and oscili can take a negative duration - fout opcode documentation clarified - Release time in mxadsr fixed - centroid opcode extended to take array inputs in addition - ptable opcodes are now identical to table family - ftgen now as array input option - subinstr can now have string arguments - the i() format is extended to work on k-rate arrays with the first argument being an array, followed by the indices - monitor opcode can now write to an array ### Utilities - pvlook now always prints explicit analysis window name ### Frontends - icsound: - csound~: - csdebugger: - HTML5 - csound.node: Implemented for Linux, minor API fix. - pnacl: Added compileCsdText method to csound object - Emscripten: - CsoundQT: ### General Usage - Checking of valid macro names improved - ```#undef``` fixed ## Bugs Fixed - Fixes to prints in format use - jitter2 reworked to make it more like the manual. - oscbank has had multiple fixes and now works as advertised - bformdec1 with arrays and type 4 fixed - Bug in pvsceps fixed - In various formatted print opcodes extra trash characters might appear -- fixed - Assigning variables with --sample-accurate could give unexpected results; this is believed fixed now - padsynth square profile fix, and opcode prints less depending on warn level - gen31 fixed - gen41 fixed - Bug in sensekey fixed - A number of issues in centroid fixed - An internal miscalculation of variable sizes that only affected 32bit architectures fixed ## SYSTEM LEVEL CHANGES ### System Changes - New score lexing and preprocessor - MAC line endings now work again - System information messages (system sampling rate, etc) are now directed to stdout - rtjack reworked to deal with names and numbers - The version printing now includes the commit as so the developers know which patches have been applied ### API - API version now 4.0 - Now supports named gens - fterror now in API - API functions SetOutput and GetOutputFormat fixed - Many API functions now use const where appropriate - Messages can now be directed to stdout from the API by using CSOUNDMSG_STDOUT attribute - New Lisp CFFI and FFI interfaces tested with Steel Bank Common Lisp (64 bit CPU architecture), runs in separate thread - ctcsound.py, a new FFI interface for Python was introduced in version 6.07. It is now the recommended interface for Python, csnd6.py being deprecated. ### Platform Specific - iOS - Android - Multichannel input and output allowed - Windows - csound64.lib import library added to Windows installer - OSX - Minor issues with installer fixed - GNU/Linux ==END== csound-6.10.0/Release_Notes/Version_6.09.md000066400000000000000000000167121321653344700202630ustar00rootroot00000000000000!--- To maintain this document use the following markdown: # First level heading ## Second level heading ### Third level heading - First level bullet point - Second level bullet point - Third level bullet point `inline code` ``` preformatted text etc. ``` [hyperlink](url for the hyperlink) Any valid HTML can also be used. ---> # CSOUND VERSION 6.09.1 RELEASE NOTES This is mostly a bugfix release of version 6.09 addressing a number of issues, including a bug in multicore performance. The Web Assembly platform is introduced in this release, as well as support for Swift development on iOS. Some DLLs that were missing from the Windows installer also have been added to it. Following Google's deprecation of PNaCl, this platform has been dropped from the release and will not be further developed. These notes include the changes in 6.09 (for completeness) and 6.09.1 -- The Developers ### (For 6.09) A mixed bag of new opcodes and many fixes and improvements. Also as usual there are a number of internal changes, including many memory leaks fixed and more robust code. -- The Developers ## USER-LEVEL CHANGES ### New opcodes - select -- sample-by-sample comparison of audio selecting the output. - midiarp opcode -- generates arpeggios based on currently held MIDI notes. - hilbert2 -- a DFT-based implementation of a Hilbert transformer. - Ableton Link opcodes -- for synchronizing tempo and beat across local area networks. - pvstrace -- retain only the N loudest bins. - several new unary functions/opcodes for k-rate and i-time numeric arrays: ceil, floor, round, int, frac, powoftwo, abs, log2, log10, log, exp, sqrt, cos, sin, tan, acos, asin, atan, sinh, cosh, tanh, cbrt, limit1. - several new binary functions/opcodes for k-rate and i-time numeric arrays: atan2, pow, hypot, fmod, fmax, fmin. - limit -- numeric limiting within a given range (for arrays). - tvconv -- a time-varying convolution (FIR filter) opcode. - liveconv -- partitioned convolution with dynamically reloadable impulse response - bpf, xyscale, ntom, mton -- (from SuperCollider?). - OSCsendA -- asynchronous version of OSCsend, - OSCsend -- now implemented directly using system sockets. Old version using liblo has been kept as OSCsend_lo. - OSCraw -- to listen for all OSC messages at a given port. - New implementation of OSCsend not using liblo, with previous version now called OSCsend_lo, - sorta and sortd -- sort elements of an array. - dot -- calculates the dot product of two arrays. - zero delay filters -- zdf_1pole_mode, zdf_2pole_mode, zdf_ladder, zdf_1pole and zdf_2pole.xml, diode_ladder, z35_hpf and K35_lpf. - product -- takes a numeric array (k or i-rate) and calculates its product. - supercollider ugens -- sc_phasor, sc_lag, sc_lagud, sc_trig ### New Gen and Macros - ### Orchestra - Including a directory of UDO files no longer fails if more than about 20 entries. - It was possible for kr, sr, and ksmps to be inconsistent in one case, no more. - Macro names better policed and bracket matching. - Octal values as \000 can be in strings - (from 6.09.1) In a UDO the out* opcodes now work, where before it was working only sometimes. ### Score - Improved line number reporting in r opcode and case with no macro implemented. - m and n opcodes fixed. - Expansion of [...] corrected and improved. - Strings in scores improved - The ) character can be in a macro argument if it is escaped with \. - Use of the characters e or s could lead to errors; now fixed. - Macro names better policed, and bracket matching. - p2 and p3 are now at higher precision, no longer truncated to 6 decimal places. - new opcode d to switch off infinite notes (denote); same as i with negative p1. - named instruments can be turned off with i if a - follows the ". - (from 6.09.1) if an r-opcode section eded in e-opcode it used to sop early. ### Options - jack midi module now can report available devices under --midi-devices. - (from 6.09.1) defining smacros and omacros on command line only happens once. - (from 6.09.1) defining smacros from command line now works. ### Modified Opcodes and Gens - ftgentmp improved string arguments. - hdf5read opcode now reads entire data sets when dataset name string is suffixed with an asterisk. - use of non power-of-two lengths in gens now acceptable where before it was inconsistent. - ampmidid optionally can be aware of 0dbfs. - dust and dust2 at k-rate now conform to the manual (NOTE: this is an incompatible change). - In prints the format %% now prints one %. - OSClisten can be used with no data outputs. - GEN18 corrected to write to requested range. - sockrev now can read strings. - vbap system can in some cases allow arbitrary number of speakers via arrays (work in progress). - Websocket server can only accept one protocol output, so limiting intype to just a single argument. - sum opcode will also sum elements of an array. - Overloaded pvs2tab and tab2pvs now can create and use split magnitude and phase arrays. ### Utilities - dnoise fixed. ### Frontends - icsound: - csound~: - csdebugger: - HTML5 - Removed HTML5 Csound editor which has quit working. - Emscripten: Emscripten Csound (asm.js) now requires sourcing in CsoundObj.js and FileList.js separately from libcsound.js. This is to accommodate using the same JS API with either asm.js or wasm backends. - CsoundQT: CsoundQt 0.9.4 is announced: https://github.com/CsoundQt/CsoundQt/blob/develop/release_notes/Release%20notes%200.9.4.md. - (from 6.09.1) Windows installer with CsoundQt does not include PythonQt. ### General Usage ## Bugs Fixed - pwd works on OSX. - Fencepost error in sensLine fixed. - OSCsend corrected for caching of host name. - Bug in push/pop opcodes fixed (this opcode is now a plugin and deprecated). - Bug in sprintf removed. - Bug in soundin removed. - losci/losci3 fixed in case of long tables. - inrg was broken for a while. - Partikkel channelmask panning laws had an indexing error, now fixed. - jack audio module now allows for independent numbers of in and out channels. - Bug in string copying fixed. - Bug in hdf5read where if two hdf5read opcodes were placed in series in an instrument, the argument names of the second opcode instance would be incorrect due to directly changing the last string character of the first when reading an entire dataset. - Memory leaks fixed in some plugin opcodes. ## SYSTEM LEVEL CHANGES ### System Changes - soundin now uses the diskin2 code. - out family of opcodes reworked to reduce interleaving costs and to take proper regard if nchnls value. - (from 6.09.1) a crash on Linux i386 removed relating to server mode. ### API - New `csound_threaded.hpp' header-only facility, obviating need for `csPerfThread.cpp' object in some projects. - Added GetA4 function. - New framework for plugin opcode development in C++ using Csound's allocator. - Added StrDup function. - Boost dependencies removed from Csound interfaces, CsoundAC, and CsoundVST. - (from 6.09.1) Two new API functions, csoundSetSpinSample and csoundClearSpin. ### Platform Specific - iOS - iPad portrait SplitView fix+animation, info popover resizing, stop button fix in Soundfile Pitch Shifter. - Csound-iOS API updates; Examples cleaned up, enhanced/expanded, and reordered. Manual revised, expanded, updated. Updates to API and examples support iOS 10 and Xcode 8. - Android - Multichannel input and output allowed. - Windows - csound64.lib import library added to Windows installer. - OSX - GNU/Linux ==END== csound-6.10.0/Release_Notes/Version_6.10.md000066400000000000000000000170231321653344700202470ustar00rootroot00000000000000 # CSOUND VERSION 6.10 RELEASE NOTES This is mostly a bugfix release, including a major bug recently introduced in loscil. New and improved opcodes and a long orphaned gen (53) are here, as well as many small internal improvements. Internal changes have removed a number of memory leaks. -- The Developers ## USER-LEVEL CHANGES ### New opcodes - midiout_i which is like midiout, but works at i-rate. - chngetks and chnsetks -- versions of chnget and chnset for string channels that **only** run at perf-time. - squinewave is a mostly bandlimited shape-shifting square-pulse-saw-sinewave oscillator with hardsync. - The experimental opcode OSCsendA has been removed; use OSCsend instead. ### New Gen and Macros - gen53 (which has been in the code but not documented for years) is now acknowledged. It creates a linear-phase or minimum-phase impulse response table from a source table containing a frequency response or an impulse response. ### Orchestra - Incorrect use of k-rate if..then.. in instrument 0 is now treated as i-rate. - Incorrect use of k-rate operations in instrument 0 are no longer treated as an error but a warning. - In a csd file commented-out tags were acted upon in some cases, leading to truncated orchestras. This is now fixed. - Arrays can be assigned from i-rate and k-rate to krate and i-rate; previously rates had to match. - The use of ! as a Boolean operation (meaning negation) is now supported, where previously the parser accepted it but did not use it. - Constant folding now implemented on a wide range of arithmetic. - Attempts to use an undefined macro produce a syntax error now. - Missing " (or other terminator) in #include is noticed and the #include is ignored. ### Score - In a csd file commented-out tags were acted upon in some cases, leading to truncated scores. This is now fixed. - The evaluation form [..] can now be nested. - The extract feature (-x from command line) now works. - Use of the score opcode x could case spurious error messages which are now suppressed. - After calling a undefined macro the rest of the line is ignored. - A couple of bugs in repeated sections (r opcode) have been removed. - Missing " (or other terminator) in #include is noticed and the #include is ignored. ### Options - the --tempo (and -t) option now can be fractional; was previously limited to an integer. - new option: --udp-console=address:port redirects console to a remote address:port. - new option: --udp-mirror-console=address:port mirrors the console to a remote address:port. - new option: --udp-echo echoes messages sent to the UDP server - new option: --aft-zero sets initial after-touch value to zero rather than 127. ### Modified Opcodes and Gens - loscil/loscil3 accept floating point increment. - OSCraw closes socket after use. - fout can now generate ogg format, as well as accepting -1 to mean the same format as -o uses. - bitwise and opcode (&) at a-rate corrected for sample-accurate mode. - slicearray has an optional additional argument to give a stride to the slice. - chnset now can have variable channel names. - a-rate arrays may be added, subtracted, multiplied and scaled. This is a start on a-rate array arithmetic. - dssiinit improved removing some crashes. - partials improved to remove a fencepost issue. - vco2ift fixed when an existing table is used. - The formatted printing opcodes now check for insufficient provided arguments. - FLbox and FLsetText again accept an ivar as first argument to give a string via strset (as a alternative to a string). - Better checking in prints should stop some crashes. ### Utilities - ### Frontends - icsound: - csound~: - csdebugger: - Emscripten: Now compiled as WebAssembly (runs in all major browsers). API now somewhat more conformed to other HTML5 APIs. - CsoundQt: Now built from master branch for improved stability. ### General Usage ## Bugs Fixed - The optionality of the last argument in sc_phasor now works. - Freezing in dconv fixed. - looptseg no longer crashes if presented with too few arguments. - schedule etc now work correctly with double-quoted strings within {{ }} strings. - problem with CLI frontend interrupt handler fixed. - outs2 was broken (always wrote to channel 1 like outs1). - Various errors in the DSSI/ladspa system fixed. - vbap was broken in all cases except 4-speakers, now corrected. - Live evaluation of Csound Orchestra code code could result in hard to diagnose, odd errors (e.g., crashes, division by zeros, NaNs). This was due to a bug in merging of newly found constants into the global constant pool. ## SYSTEM LEVEL CHANGES ### System Changes - The GNU Lesser General Public License, version 2.1, for CsoundVST and the vst4cs opcodes has been modified to grant an exception for compiling and linking with the VST2 SDK, which is available from [https://github.com/steinbergmedia/vst3sdk]. For more information, see [https://github.com/csound/csound/blob/develop/Opcodes/vst4cs/licensing_considerations_for_csoundvst_and_vst4cs.md]. - UDP Server now accepts some new commands, which are prefixed by an opcode. These include support for events (&) and scores ($); setting control channels (@ ); setting string channels (% )); getting control channel values via UDP (:@ ) and string channel contents (:% ). ### Translations - As ever the French translations are complete. - The Italian translations of messages are greatly improved in scope; about a half of error and warning messages are now done. - Some progress as been made in German translations. ### API - CompileCsdText now always returns a value indicating success/failure. - Eight new asynchronous versions of API functions now available: csoundCompileTreeAsync(), csoundCompileOrcAsync(), csoundReadScoreAsync(), csoundInputMessageAsync(), csoundScoreEventAsync(), csoundScoreEventAbsoluteAsync(), csoundTableCopyOutAsync(), and csoundTableCopyInAsync(). - For server use, three new API functions: csoundUDPServerStart, csoundUDPServerStatus and csoundUDPServerClose. ### Platform Specific - iOS - - Android - - Windows - Now compiles with Microsoft Visual Studio 2015 or later. - Continuous integration for Windows with AppVeyor (Visual Studio 2017). - OSX - GNU/Linux ALSA MIDI backend now ignores some spurious -ENOENT error codes. ==END== ======================================================================== Author: jpff Date: Thu Nov 9 12:27:38 2017 +0000 Author: Steven Yi Date: Mon Nov 6 16:53:08 2017 -0500 added NULL check for prints opcode to prevent crash when number given as initial arg Author: Steven Yi Date: Mon Nov 6 15:55:40 2017 -0500 added test for prints to not crash if number given (should just report error) csound-6.10.0/SDIF/000077500000000000000000000000001321653344700136265ustar00rootroot00000000000000csound-6.10.0/SDIF/CMakeLists.txt000066400000000000000000000001721321653344700163660ustar00rootroot00000000000000# SDIF2AD Utility set(sdif2ad_SRCS sdif2adsyn.c sdif.c sdif-mem.c) make_executable(sdif2ad "${sdif2ad_SRCS}" "") csound-6.10.0/SDIF/sdif-mem.c000066400000000000000000000200641321653344700154750ustar00rootroot00000000000000/* Copyright (c) 1999. The Regents of the University of California (Regents). All Rights Reserved. Permission to use, copy, modify, and distribute this software and its documentation, without fee and without a signed licensing agreement, is hereby granted, provided that the above copyright notice, this paragraph and the following two paragraphs appear in all copies, modifications, and distributions. Contact The Office of Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, CA 94720-1620, (510) 643-7201, for commercial licensing opportunities. Written by Sami Khoury and Matt Wright, The Center for New Music and Audio Technologies, University of California, Berkeley. IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ /* sdif-mem.c Implementation of routines for representing SDIF data in memory by Sami Khoury and Matt Wright Split from sdif.c 9/22/99 by Matt Wright Updated 10/13/99 by Matt for new SDIF library 4:8:2000 RWD: func calls test explicitly for ESDIF_SUCCESS */ #include "sysdep.h" #include #include #include "sdif-mem.h" /* Global variables local to this file */ static void *(*my_malloc)(int numBytes); static void (*my_free)(void *memory, int numBytes); SDIFresult SDIFmem_Init(void *(*MemoryAllocator)(int numBytes), void (*MemoryFreer)(void *memory, int numBytes)) { my_malloc = MemoryAllocator; my_free = MemoryFreer; return ESDIF_SUCCESS; } SDIFmem_Frame SDIFmem_CreateEmptyFrame(void) { SDIFmem_Frame f; f = (*my_malloc)(sizeof(*f)); if (f == NULL) { return NULL; } f->header.frameType[0] = '\0'; f->header.frameType[1] = '\0'; f->header.frameType[2] = '\0'; f->header.frameType[3] = '\0'; f->header.size = 16; f->header.time = 0; f->header.streamID = 0; f->header.matrixCount = 0; f->matrices = NULL; f->prev = NULL; f->next = NULL; return f; } void SDIFmem_FreeFrame(SDIFmem_Frame f) { SDIFmem_Matrix m, next; if (f == 0) return; m = f->matrices; while (m != NULL) { next = m->next; SDIFmem_FreeMatrix(m); m = next; } (*my_free)(f, sizeof(*f)); } SDIFmem_Matrix SDIFmem_CreateEmptyMatrix(void) { SDIFmem_Matrix result; result = (*my_malloc)(sizeof(*result)); if (result == NULL) { return NULL; } SDIF_Copy4Bytes(result->header.matrixType, "\0\0\0\0"); result->header.matrixDataType = SDIF_NO_TYPE; result->header.rowCount = result->header.columnCount = 0; result->data = 0; return result; } void SDIFmem_FreeMatrix(SDIFmem_Matrix m) { if (m->data != 0) { (*my_free)(m->data, SDIF_GetMatrixDataSize(&(m->header))); } (*my_free)(m, sizeof(*m)); } void SDIFmem_RepairFrameHeader(SDIFmem_Frame f) { sdif_int32 numBytes; sdif_int32 numMatrices; SDIFmem_Matrix m; /* The rest of the frame header: */ numBytes = sizeof(SDIF_FrameHeader) - 8; numMatrices = 0; for (m = f->matrices; m != 0; m=m->next) { ++numMatrices; numBytes += sizeof(SDIF_MatrixHeader); numBytes += SDIF_GetMatrixDataSize(&(m->header)); } f->header.size = numBytes; f->header.matrixCount = numMatrices; } SDIFresult SDIFmem_ReadFrameContents(SDIF_FrameHeader *head, FILE *f, SDIFmem_Frame *putithere) { /* The user has just read the header for this frame; now we have to read all the frame's matrices, put them in an SDIFmem_Matrix linked list, and then stuff everything into an SDIFmem_Frame. */ SDIFresult r; SDIFmem_Frame result; SDIFmem_Matrix matrix; int i, sz; SDIFmem_Matrix *prevNextPtr; result = (SDIFmem_Frame) (*my_malloc)(sizeof(*result)); if (result == 0) { return ESDIF_OUT_OF_MEMORY; } result->header = *head; result->prev = 0; result->next = 0; result->matrices = 0; prevNextPtr = &(result->matrices); for (i = 0; i < head->matrixCount; ++i) { matrix = SDIFmem_CreateEmptyMatrix(); if (matrix == 0) { SDIFmem_FreeFrame(result); return ESDIF_OUT_OF_MEMORY; } /* Get the linked list pointers right. Now if we bomb out and call SDIFmem_FreeFrame(result) it will free the matrix we just allocated */ *(prevNextPtr) = matrix; prevNextPtr = &(matrix->next); matrix->next = 0; if ((r = SDIF_ReadMatrixHeader(&(matrix->header), f))!=ESDIF_SUCCESS) { SDIFmem_FreeFrame(result); return r; } sz = SDIF_GetMatrixDataSize(&(matrix->header)); if (sz == 0) { matrix->data = NULL; } else { matrix->data = (*my_malloc)(sz); if (matrix->data == NULL) { SDIFmem_FreeFrame(result); return ESDIF_OUT_OF_MEMORY; } } /* COVERITY: what if sz=0? dereferences null */ if (sz != 0) if ((r = SDIF_ReadMatrixData(matrix->data, f, &(matrix->header)))!=ESDIF_SUCCESS) { SDIFmem_FreeFrame(result); return r; } } *putithere = result; return ESDIF_SUCCESS; } SDIFresult SDIFmem_ReadFrame(FILE *f, SDIFmem_Frame *putithere) { SDIFresult r; SDIF_FrameHeader fh; if ((r = SDIF_ReadFrameHeader(&fh, f))!=ESDIF_SUCCESS) { return r; } return SDIFmem_ReadFrameContents(&fh, f, putithere); } SDIFresult SDIFmem_AddMatrix(SDIFmem_Frame f, SDIFmem_Matrix m) { int sz; SDIFmem_Matrix p, last; assert(f != NULL); assert(m != NULL); m->next = NULL; p = f->matrices; if (p == NULL) { f->matrices = m; } else { while (p != NULL) { if (SDIF_Char4Eq(p->header.matrixType, m->header.matrixType)) { return ESDIF_DUPLICATE_MATRIX_TYPE_IN_FRAME; } last = p; p = p->next; } last->next = m; } sz = SDIF_GetMatrixDataSize(&(m->header)); f->header.size += sz + sizeof(SDIF_MatrixHeader); f->header.matrixCount++; return ESDIF_SUCCESS; } SDIFresult SDIFmem_WriteMatrix(FILE *sdif_handle, SDIFmem_Matrix m) { SDIFresult r; sdif_int32 sz, numElements; int paddingNeeded; if ((r = SDIF_WriteMatrixHeader(&(m->header), sdif_handle))!=ESDIF_SUCCESS) { return r; } sz = SDIF_GetMatrixDataTypeSize(m->header.matrixDataType); numElements = (m->header.rowCount * m->header.columnCount); switch (sz) { case 1: r = SDIF_Write1(m->data, numElements, sdif_handle); break; case 2: r = SDIF_Write2(m->data, numElements, sdif_handle); break; case 4: r = SDIF_Write4(m->data, numElements, sdif_handle); break; case 8: r = SDIF_Write8(m->data, numElements, sdif_handle); break; default: return ESDIF_BAD_MATRIX_DATA_TYPE; } if (r !=ESDIF_SUCCESS) return r; paddingNeeded = SDIF_PaddingRequired(&(m->header)); if (paddingNeeded) { char pad[8] = "\0\0\0\0\0\0\0\0"; if ((r = SDIF_Write1(pad, paddingNeeded, sdif_handle))!=ESDIF_SUCCESS) return r; } return ESDIF_SUCCESS; } SDIFresult SDIFmem_WriteFrame(FILE *sdif_handle, SDIFmem_Frame f) { SDIFresult r; SDIFmem_Matrix p; assert(f != NULL); assert(sdif_handle != NULL); if ((r = SDIF_WriteFrameHeader(&f->header, sdif_handle))!=ESDIF_SUCCESS) { return r; } for (p = f->matrices; p != NULL; p = p->next) { if ((r = SDIFmem_WriteMatrix(sdif_handle, p))!=ESDIF_SUCCESS) return r; } return ESDIF_SUCCESS; } csound-6.10.0/SDIF/sdif-mem.h000066400000000000000000000126711321653344700155070ustar00rootroot00000000000000/* Copyright (c) 1996, 1997, 1998, 1999. The Regents of the University of California (Regents). All Rights Reserved. Permission to use, copy, modify, and distribute this software and its documentation, without fee and without a signed licensing agreement, is hereby granted, provided that the above copyright notice, this paragraph and the following two paragraphs appear in all copies, modifications, and distributions. Contact The Office of Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, CA 94720-1620, (510) 643-7201, for commercial licensing opportunities. Written by Matt Wright and Sami Khoury, The Center for New Music and Audio Technologies, University of California, Berkeley. IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ /* sdif-mem.h Recommended data structures for storing SDIF data in memory. It stores frame and matrix headers with the standard byte encoding, and it stores the matrices themselves just as they appear in the file, but everything else is done with linked lists rather than counting the sizes of things and knowing that the next one must appear right after this one. Version 1.0, 9/21/99 */ /* Return value/error message conventions: same as sdif.[ch], except for the constructor procedures, which return a pointer to the new object or zero if out of memory. */ /* Structs defining our data structures. Note that they contain the frame and matrix header structs from sdif.h */ /*RWD TODO: declare objects, no pounters */ #ifndef CSOUND_SDIF_MEM_H #define CSOUND_SDIF_MEM_H #include "sdif.h" typedef struct SDIFmemMatrixStruct { SDIF_MatrixHeader header; void *data; struct SDIFmemMatrixStruct *next; } *SDIFmem_Matrix; typedef struct SDIFmemFrameStruct { SDIF_FrameHeader header; SDIFmem_Matrix matrices; /* linked list of matrices. */ struct SDIFmemFrameStruct *prev; struct SDIFmemFrameStruct *next; } *SDIFmem_Frame; /* SDIFmem_Init -- You must call this before any of the other procedures in this library. You pass in the procedures that will be used for malloc() and free(). */ SDIFresult SDIFmem_Init(void *(*MemoryAllocator)(int numBytes), void (*MemoryFreer)(void *memory, int numBytes)); /* Constructors */ /* SDIFmem_CreateEmptyFrame -- Returns 0 if out of memory. */ SDIFmem_Frame SDIFmem_CreateEmptyFrame(void); /* SDIFmem_CreateEmptyMatrix -- Note that the data pointer will be a null pointer; you must allocate the memory to hold the matrix data itself. Returns 0 if out of memory.*/ SDIFmem_Matrix SDIFmem_CreateEmptyMatrix(void); /* SDIFmem_FreeFrame -- Frees the given frame and all of its matrices. It's your job to repair any next and prev pointers pointing to this frame */ void SDIFmem_FreeFrame(SDIFmem_Frame f); /* SDIFmem_FreeMatrix -- Frees the given matrix. It's your job to repair any next pointers pointing to this matrix. If (m->data != 0) it calls MemoryFreer on m->data too. */ void SDIFmem_FreeMatrix(SDIFmem_Matrix m); /* SDIFmem_RepairFrameHeader --- If you've been playing with the matrices in an SDIFmem_Frame, call this to recompute the size of the frame and the number of matrices. */ void SDIFmem_RepairFrameHeader(SDIFmem_Frame f); /* SDIFmem_ReadFrameContents -- Assuming that you just read an SDIF_FrameHeader and decided that you want to read this frame into memory, call this procedure. It will allocate a new SDIFmem_Frame, copy the contents of your SDIF_FrameHeader into it, initialize the prev and next pointers to 0, read all of the frame's matrices from the file and store them in newly allocated SDIFmem_Matrix structures, and put the result in the supplied pointer argument. */ SDIFresult SDIFmem_ReadFrameContents(SDIF_FrameHeader *head, FILE *f, SDIFmem_Frame *putithere); /* SDIFmem_ReadFrame -- Just like SDIFmem_ReadFrameContents, but it also reads the frame header for you. (For use when you know you want to read the next frame into memory even without peeking at the header.) */ SDIFresult SDIFmem_ReadFrame(FILE *f, SDIFmem_Frame *putithere); /* SDIFmem_AddMatrix -- Add a new matrix to an existing frame. Checks to make sure this matrix doesn't have the same MatrixType as any other matrix already in the frame. Updates the size and numMatrices fields in the frame header. */ SDIFresult SDIFmem_AddMatrix(SDIFmem_Frame f, SDIFmem_Matrix m); /* Write the given SDIFmem_Frame, including the frame header and all the matrices, to the given file handle. */ SDIFresult SDIFmem_WriteFrame(FILE *sdif_handle, SDIFmem_Frame f); /* Write the given SDIFmem_Matrix, including the matrix header, matrix data, and possible padding bytes, to the given file handle. Usually you want to call SDIFmem_WriteFrame() instead. */ SDIFresult SDIFmem_WriteMatrix(FILE *sdif_handle, SDIFmem_Matrix m); #endif csound-6.10.0/SDIF/sdif.c000066400000000000000000000437361321653344700147340ustar00rootroot00000000000000/* Copyright (c) 1996. 1997, 1998, 1999. The Regents of the University of California (Regents). All Rights Reserved. Permission to use, copy, modify, and distribute this software and its documentation, without fee and without a signed licensing agreement, is hereby granted, provided that the above copyright notice, this paragraph and the following two paragraphs appear in all copies, modifications, and distributions. Contact The Office of Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, CA 94720-1620, (510) 643-7201, for commercial licensing opportunities. Written by Matt Wright, Amar Chaudhary, and Sami Khoury, The Center for New Music and Audio Technologies, University of California, Berkeley. IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. sdif.c Utilities for formatting data into SDIF SDIF spec: http://www.cnmat.berkeley.edu/SDIF/ Matt Wright, 12/4/96 5/12/97 version 1.1 by Matt and Amar, incorporating little-endian issues 1/12/98 version 1.2 by Amar, conforms to revised SDIF spec 11/5/1998 version 1.3 by Sami, changed error reporting, included stdio.h, and added SDIF_BeginRead(). 11/13/1998 version 2.0 by Sami, renamed functions and types to use "sdif" and "SDIF" prefixes, changed internal error reporting, added documentation in sdif.h, and incremented major version because programs which included sdif.h will no longer compile without changes. 11/16/1998 version 2.0.1 by Sami, added sdif_int32, sdif_uint32, and sdif_unicode typedefs. Added SDIF_GetMatrixDataTypeSize(). 12/1/1998 version 2.0.2 by Sami, created SDIF_Matrix, SDIF_Frame, and SDIF_Stream types and a set of functions for creating and manipulating them. This was done as the foundation for continued work on SDIF streaming. 1/25/99 version 2.1 by Matt: added SDIF_Init() to allow memory allocation in Max/MSP; lots of other little fixes. 9/20/99 version 2.2 by Matt: Incorporating changes to the format from my 6/99 visit to IRCAM. Moved memory stuff to sdif-mem.[ch]. 10/1/99 version 2.3 by Matt: minor fixes for public release. 10/12/99 Version 2.4 by Matt: changed return value convention 18:2:2000 RWD: added old version structs and functions for use with sdif2mp4. NB struct defs are now as plain struct, pointers declared explicitly 4:8:2000 RWD: made all func calls test explicitly against ESDIF_SUCCESS */ #define REALASSERT #ifdef REALASSERT #include #else #define assert(x) /* Do nothing */ #endif #include "sysdep.h" #include #include "sdif.h" /* prototypes for functions used only in this file. */ static int SizeofSanityCheck(void); static SDIFresult SkipBytes(FILE *f, int numBytes); /* error handling stuff. */ static char *error_string_array[] = { "Everything's cool", "This program should display strerror(errno) instead of this string", "Bad SDIF header", "Frame header's size is too low for time tag and stream ID", "fseek() failed while skipping over data", "Unknown matrix data type encountered in SDIF_WriteFrame().", (char *) NULL, /* this will be set by SizeofSanityCheck() */ "End of data", "Bad SDIF matrix header", "Obsolete SDIF file from an old version of SDIF", "Obsolete version of the standard SDIF frame and matrix types", "I/O error: couldn't write", "I/O error: couldn't read", "Out of memory", "Frame has two matrices with the same MatrixType" }; char *SDIF_GetErrorString(SDIFresult error_code) { return error_string_array[error_code]; } SDIFresult SDIF_Init(void) { if (!SizeofSanityCheck()) { return ESDIF_BAD_SIZEOF; } return ESDIF_SUCCESS; } SDIFresult SDIF_OpenWrite(const char *filename, FILE **resultp) { FILE *result; SDIFresult r; if ((result = fopen(filename, "wb")) == NULL) { return ESDIF_SEE_ERRNO; } if ((r = SDIF_BeginWrite(result))!= ESDIF_SUCCESS) { fclose(result); return r; } *resultp = result; return ESDIF_SUCCESS; } SDIFresult SDIF_BeginWrite(FILE *output) { SDIF_GlobalHeader h; SDIF_FillGlobalHeader(&h); return SDIF_WriteGlobalHeader(&h, output); } SDIFresult SDIF_CloseWrite(FILE *f) { fflush(f); if (fclose(f) == 0) { return ESDIF_SUCCESS; } else { return ESDIF_SEE_ERRNO; } } SDIFresult SDIF_OpenRead(const char *filename, FILE **resultp) { FILE *result = NULL; SDIFresult r; if ((result = fopen(filename, "rb")) == NULL) { return ESDIF_SEE_ERRNO; } if ((r = SDIF_BeginRead(result))!=ESDIF_SUCCESS) { fclose(result); return r; } *resultp = result; return ESDIF_SUCCESS; } SDIFresult SDIF_BeginRead(FILE *input) { SDIF_GlobalHeader sgh; SDIFresult r; /* make sure the header is OK. */ if ((r = SDIF_Read1(sgh.SDIF, 4, input))!=ESDIF_SUCCESS) return r; if (!SDIF_Char4Eq(sgh.SDIF, "SDIF")) return ESDIF_BAD_SDIF_HEADER; if ((r = SDIF_Read4(&sgh.size, 1, input))!=ESDIF_SUCCESS) return r; if (sgh.size % 8 != 0) return ESDIF_BAD_SDIF_HEADER; if (sgh.size < 8) return ESDIF_BAD_SDIF_HEADER; if ((r = SDIF_Read4(&sgh.SDIFversion, 1, input))!=ESDIF_SUCCESS) return r; if ((r = SDIF_Read4(&sgh.SDIFStandardTypesVersion, 1, input))!=ESDIF_SUCCESS) return r; if (sgh.SDIFversion != 3) { /*RWD was < 3 */ return ESDIF_OBSOLETE_FILE_VERSION; } if (sgh.SDIFStandardTypesVersion < 1) { return ESDIF_OBSOLETE_TYPES_VERSION; } /* skip size-8 bytes. (We already read the first two version numbers, but maybe there's more data in the header frame.) */ if (sgh.size == 8) { return ESDIF_SUCCESS; } if (SkipBytes(input, sgh.size-8)!=ESDIF_SUCCESS) { return ESDIF_BAD_SDIF_HEADER; } return ESDIF_SUCCESS; } SDIFresult SDIF_CloseRead(FILE *f) { if (fclose(f) == 0) { return ESDIF_SUCCESS; } else { return ESDIF_SEE_ERRNO; } } void SDIF_FillGlobalHeader(SDIF_GlobalHeader *h) { assert(h != NULL); SDIF_Copy4Bytes(h->SDIF, "SDIF"); h->size = 8; h->SDIFversion = SDIF_SPEC_VERSION; h->SDIFStandardTypesVersion = SDIF_LIBRARY_VERSION; } SDIFresult SDIF_WriteGlobalHeader(const SDIF_GlobalHeader *h, FILE *f) { SDIFresult r; assert(h != NULL); assert(f != NULL); #ifdef LITTLE_ENDIAN if ((r = SDIF_Write1(&(h->SDIF), 4, f))!=ESDIF_SUCCESS) return r; if ((r = SDIF_Write4(&(h->size), 1, f))!=ESDIF_SUCCESS) return r; if ((r = SDIF_Write4(&(h->SDIFversion), 1, f))!=ESDIF_SUCCESS) return r; if ((r = SDIF_Write4(&(h->SDIFStandardTypesVersion), 1, f))!=ESDIF_SUCCESS) return r; return ESDIF_SUCCESS; #else return (fwrite(h, sizeof(*h), 1, f) == 1) ?ESDIF_SUCCESS:ESDIF_WRITE_FAILED; #endif } SDIFresult SDIF_ReadFrameHeader(SDIF_FrameHeader *fh, FILE *f) { #ifdef LITTLE_ENDIAN SDIFresult r; if (SDIF_Read1(&(fh->frameType),4,f) != ESDIF_SUCCESS) { /*RWD*/ if (feof(f)) { return ESDIF_END_OF_DATA; } return ESDIF_READ_FAILED; } if ((r = SDIF_Read4(&(fh->size),1,f))!=ESDIF_SUCCESS) return r; if ((r = SDIF_Read8(&(fh->time),1,f))!=ESDIF_SUCCESS) return r; if ((r = SDIF_Read4(&(fh->streamID),1,f))!=ESDIF_SUCCESS) return r; if ((r = SDIF_Read4(&(fh->matrixCount),1,f))!=ESDIF_SUCCESS) return r; return ESDIF_SUCCESS; #else size_t amount_read; amount_read = fread(fh, sizeof(*fh), 1, f); if (amount_read == 1) return ESDIF_SUCCESS; if (amount_read == 0) { /* Now that fread failed, maybe we're at EOF. */ if (feof(f)) { return ESDIF_END_OF_DATA; } } return ESDIF_READ_FAILED; #endif /* LITTLE_ENDIAN */ } SDIFresult SDIF_WriteFrameHeader(const SDIF_FrameHeader *fh, FILE *f) { #ifdef LITTLE_ENDIAN SDIFresult r; if ((r = SDIF_Write1(&(fh->frameType),4,f))!=ESDIF_SUCCESS) return r; if ((r = SDIF_Write4(&(fh->size),1,f))!=ESDIF_SUCCESS) return r; if ((r = SDIF_Write8(&(fh->time),1,f))!=ESDIF_SUCCESS) return r; if ((r = SDIF_Write4(&(fh->streamID),1,f))!=ESDIF_SUCCESS) return r; if ((r = SDIF_Write4(&(fh->matrixCount),1,f))!=ESDIF_SUCCESS) return r; #ifdef _WIN32 fflush(f); #endif return ESDIF_SUCCESS; #else return (fwrite(fh, sizeof(*fh), 1, f) == 1)?ESDIF_SUCCESS:ESDIF_WRITE_FAILED; #endif } SDIFresult SDIF_SkipFrame(const SDIF_FrameHeader *head, FILE *f) { /* The header's size count includes the 8-byte time tag, 4-byte stream ID and 4-byte matrix count that we already read. */ int bytesToSkip = head->size - 16; if (bytesToSkip < 0) { return ESDIF_BAD_FRAME_HEADER; } return SkipBytes(f, bytesToSkip); } SDIFresult SDIF_ReadMatrixHeader(SDIF_MatrixHeader *m, FILE *f) { #ifdef LITTLE_ENDIAN SDIFresult r; if ((r = SDIF_Read1(&(m->matrixType),4,f))!=ESDIF_SUCCESS) return r; if ((r = SDIF_Read4(&(m->matrixDataType),1,f))!=ESDIF_SUCCESS) return r; if ((r = SDIF_Read4(&(m->rowCount),1,f))!=ESDIF_SUCCESS) return r; if ((r = SDIF_Read4(&(m->columnCount),1,f))!=ESDIF_SUCCESS) return r; return ESDIF_SUCCESS; #else if (fread(m, sizeof(*m), 1, f) == 1) { return ESDIF_SUCCESS; } else { return ESDIF_READ_FAILED; } #endif } SDIFresult SDIF_WriteMatrixHeader(const SDIF_MatrixHeader *m, FILE *f) { #ifdef LITTLE_ENDIAN SDIFresult r; if ((r = SDIF_Write1(&(m->matrixType),4,f))!=ESDIF_SUCCESS) return r; if ((r = SDIF_Write4(&(m->matrixDataType),1,f))!=ESDIF_SUCCESS) return r; if ((r = SDIF_Write4(&(m->rowCount),1,f))!=ESDIF_SUCCESS) return r; if ((r = SDIF_Write4(&(m->columnCount),1,f))!=ESDIF_SUCCESS) return r; return ESDIF_SUCCESS; #else return (fwrite(m, sizeof(*m), 1, f) == 1) ? ESDIF_SUCCESS:ESDIF_READ_FAILED; #endif } int SDIF_GetMatrixDataSize(const SDIF_MatrixHeader *m) { int size; size = SDIF_GetMatrixDataTypeSize(m->matrixDataType) * m->rowCount * m->columnCount; if ((size % 8) != 0) { size += (8 - (size % 8)); } return size; } int SDIF_PaddingRequired(const SDIF_MatrixHeader *m) { int size; size = SDIF_GetMatrixDataTypeSize(m->matrixDataType) * m->rowCount * m->columnCount; if ((size % 8) != 0) { return (8 - (size % 8)); } else { return 0; } } SDIFresult SDIF_SkipMatrix(const SDIF_MatrixHeader *head, FILE *f) { int size = SDIF_GetMatrixDataSize(head); if (size < 0) { return ESDIF_BAD_MATRIX_HEADER; } return SkipBytes(f, size); } SDIFresult SDIF_ReadMatrixData(void *putItHere, FILE *f, const SDIF_MatrixHeader *head) { size_t datumSize = (size_t) SDIF_GetMatrixDataTypeSize(head->matrixDataType); size_t numItems = (size_t) (head->rowCount * head->columnCount); #ifdef LITTLE_ENDIAN switch (datumSize) { case 1: return SDIF_Read1(putItHere, numItems, f); case 2: return SDIF_Read2(putItHere, numItems, f); case 4: return SDIF_Read4(putItHere, numItems, f); case 8: return SDIF_Read8(putItHere, numItems, f); default: return ESDIF_BAD_MATRIX_DATA_TYPE; } /* This is never reached */ return ESDIF_SUCCESS; #else if (fread(putItHere, datumSize, numItems, f) == numItems) { return ESDIF_SUCCESS; } else { return ESDIF_READ_FAILED; } #endif } sdif_int32 SDIF_UniqueStreamID(void) { static int id; return ++id; } int SDIF_Char4Eq(const char *ths, const char *that) { return ths[0] == that[0] && ths[1] == that[1] && ths[2] == that[2] && ths[3] == that[3]; } void SDIF_Copy4Bytes(char *target, const char *string) { target[0] = string[0]; target[1] = string[1]; target[2] = string[2]; target[3] = string[3]; } #ifdef LITTLE_ENDIAN #define BUFSIZE 4096 static char p[BUFSIZE]; #endif SDIFresult SDIF_Write1(const void *block, size_t n, FILE *f) { return (fwrite (block,1,n,f) == n) ? ESDIF_SUCCESS : ESDIF_WRITE_FAILED; } SDIFresult SDIF_Write2(const void *block, size_t n, FILE *f) { #ifdef LITTLE_ENDIAN SDIFresult r; const char *q = block; int i, m = 2*n; if ((n << 1) > BUFSIZE) { /* Too big for buffer */ int num = BUFSIZE >> 1; if ((r = SDIF_Write2(block, num, f))!=ESDIF_SUCCESS) return r; return SDIF_Write2(((char *) block) + num, n-num, f); } for (i = 0; i < m; i += 2) { p[i] = q[i+1]; p[i+1] = q[i]; } return (fwrite(p,2,n,f)==n) ? ESDIF_SUCCESS : ESDIF_WRITE_FAILED; #else return (fwrite (block,2,n,f) == n) ? ESDIF_SUCCESS : ESDIF_WRITE_FAILED; #endif } SDIFresult SDIF_Write4(const void *block, size_t n, FILE *f) { #ifdef LITTLE_ENDIAN SDIFresult r; const char *q = block; int i, m = 4*n; if ((n << 2) > BUFSIZE) { int num = BUFSIZE >> 2; if ((r = SDIF_Write4(block, num, f))!=ESDIF_SUCCESS) return r; return SDIF_Write4(((char *) block) + num, n-num, f); } for (i = 0; i < m; i += 4) { p[i] = q[i+3]; p[i+3] = q[i]; p[i+1] = q[i+2]; p[i+2] = q[i+1]; } return (fwrite(p,4,n,f) == n) ? ESDIF_SUCCESS : ESDIF_WRITE_FAILED; #else return (fwrite(block,4,n,f) == n) ? ESDIF_SUCCESS : ESDIF_WRITE_FAILED; #endif } SDIFresult SDIF_Write8(const void *block, size_t n, FILE *f) { #ifdef LITTLE_ENDIAN SDIFresult r; const char *q = block; int i, m = 8*n; if ((n << 3) > BUFSIZE) { int num = BUFSIZE >> 3; if ((r = SDIF_Write8(block, num, f))!=ESDIF_SUCCESS) return r; return SDIF_Write8(((char *) block) + num, n-num, f); } for (i = 0; i < m; i += 8) { p[i] = q[i+7]; p[i+7] = q[i]; p[i+1] = q[i+6]; p[i+6] = q[i+1]; p[i+2] = q[i+5]; p[i+5] = q[i+2]; p[i+3] = q[i+4]; p[i+4] = q[i+3]; } return (fwrite(p,8,n,f) == n) ? ESDIF_SUCCESS : ESDIF_WRITE_FAILED; #else return (fwrite(block,8,n,f) == n) ? ESDIF_SUCCESS : ESDIF_WRITE_FAILED; #endif } SDIFresult SDIF_Read1(void *block, size_t n, FILE *f) { return (fread (block,1,n,f) == n) ? ESDIF_SUCCESS : ESDIF_READ_FAILED; } SDIFresult SDIF_Read2(void *block, size_t n, FILE *f) { #ifdef LITTLE_ENDIAN SDIFresult r; char *q = block; int i, m = 2*n; if ((n << 1) > BUFSIZE) { int num = BUFSIZE >> 1; if ((r = SDIF_Read2(block, num, f))!=ESDIF_SUCCESS) return r; return SDIF_Read2(((char *) block) + num, n-num, f); } if (fread(p,2,n,f) != n) return ESDIF_READ_FAILED; for (i = 0; i < m; i += 2) { q[i] = p[i+1]; q[i+1] = p[i]; } return ESDIF_SUCCESS; #else return (fread(block,2,n,f) == n) ? ESDIF_SUCCESS : ESDIF_READ_FAILED; #endif } SDIFresult SDIF_Read4(void *block, size_t n, FILE *f) { #ifdef LITTLE_ENDIAN SDIFresult r; char *q = block; int i, m = 4*n; if ((n << 2) > BUFSIZE) { int num = BUFSIZE >> 2; if ((r = SDIF_Read4(block, num, f))!=ESDIF_SUCCESS) return r; return SDIF_Read4(((char *) block) + num, n-num, f); } if (fread(p,4,n,f) != n) return ESDIF_READ_FAILED; for (i = 0; i < m; i += 4) { q[i] = p[i+3]; q[i+3] = p[i]; q[i+1] = p[i+2]; q[i+2] = p[i+1]; } return ESDIF_SUCCESS; #else return (fread(block,4,n,f) == n) ? ESDIF_SUCCESS : ESDIF_READ_FAILED; #endif } SDIFresult SDIF_Read8(void *block, size_t n, FILE *f) { #ifdef LITTLE_ENDIAN SDIFresult r; char *q = block; int i, m = 8*n; if ((n << 3) > BUFSIZE) { int num = BUFSIZE >> 3; if ((r = SDIF_Read8(block, num, f))!=ESDIF_SUCCESS) return r; return SDIF_Read8(((char *) block) + num, n-num, f); } if (fread(p,8,n,f) != n) return ESDIF_READ_FAILED; for (i = 0; i < m; i += 8) { q[i] = p[i+7]; q[i+7] = p[i]; q[i+1] = p[i+6]; q[i+6] = p[i+1]; q[i+2] = p[i+5]; q[i+5] = p[i+2]; q[i+3] = p[i+4]; q[i+4] = p[i+3]; } return ESDIF_SUCCESS; #else return (fread(block,8,n,f) == n) ? ESDIF_SUCCESS : ESDIF_READ_FAILED; #endif } /* static function definitions follow. */ static int SizeofSanityCheck(void) { int OOK = 1; static char errorMessage[sizeof("sizeof(sdif_float64) is 999!!!")]; if (sizeof(sdif_int32) != 4) { sprintf(errorMessage, "sizeof(sdif_int32) is %d!", (int)sizeof(sdif_int32)); OOK = 0; } if (sizeof(sdif_float32) != 4) { sprintf(errorMessage, "sizeof(sdif_float32) is %d!", (int)sizeof(sdif_float32)); OOK = 0; } if (sizeof(sdif_float64) != 8) { sprintf(errorMessage, "sizeof(sdif_float64) is %d!", (int)sizeof(sdif_float64)); OOK = 0; } if (!OOK) { error_string_array[ESDIF_BAD_SIZEOF] = errorMessage; } return OOK; } static SDIFresult SkipBytes(FILE *f, int bytesToSkip) { #ifdef STREAMING /* Can't fseek in a stream, so waste some time needlessly copying some bytes in memory */ { #define BLOCK_SIZE 1024 char buf[BLOCK_SIZE]; while (bytesToSkip > BLOCK_SIZE) { if (fread (buf, BLOCK_SIZE, 1, f) != 1) { return ESDIF_READ_FAILED; } bytesToSkip -= BLOCK_SIZE; } if (fread (buf, bytesToSkip, 1, f) != 1) { return ESDIF_READ_FAILED; } } #else /* More efficient implementation */ if (fseek(f, bytesToSkip, SEEK_CUR) != 0) { return ESDIF_SKIP_FAILED; } #endif return ESDIF_SUCCESS; } csound-6.10.0/SDIF/sdif.h000066400000000000000000000265451321653344700147400ustar00rootroot00000000000000/* Copyright (c) 1996. 1997, 1998, 1999. The Regents of the University of California (Regents). All Rights Reserved. Permission to use, copy, modify, and distribute this software and its documentation, without fee and without a signed licensing agreement, is hereby granted, provided that the above copyright notice, this paragraph and the following two paragraphs appear in all copies, modifications, and distributions. Contact The Office of Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, CA 94720-1620, (510) 643-7201, for commercial licensing opportunities. Written by Matt Wright, Amar Chaudhary, and Sami Khoury, The Center for New Music and Audio Technologies, University of California, Berkeley. IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. sdif.h API for working with SDIF. SDIF spec: http://www.cnmat.berkeley.edu/SDIF/ See sdif.c for revision history. version 2.3 #include before this file for FILE *. (A forthcoming C++ version of this libraray will not require stdio to be included.) This part of the SDIF library never allocates any memory; the memory required for all procedures must be passed in by the user of the library. See sdif-mem.h for our "officially recommended" data structures for SDIF in memory and procedures for dealing with them. This SDIF library is at the moment neither reentrant nor thread-safe. */ #ifndef CSOUND_SDIF_H #define CSOUND_SDIF_H #include "sysdep.h" /****************************************************/ /* Create 32-bit and 64-bit int and float typedefs. */ /****************************************************/ typedef uint16_t sdif_unicode; typedef int32_t sdif_int32; typedef uint32_t sdif_uint32; typedef float sdif_float32; typedef double sdif_float64; #if defined(_WIN32) || defined(_WINDOWS) #ifndef _WINDOWS_ #include #endif #endif #ifdef __cplusplus extern "C" { #endif /* Return value convention: Most of the procedures in this library return a value of type SDIFresult, with 0 for success and nonzero for various error conditions. Exceptions are noted in the comment describing each procedure. All errors encountered by the library produce an informative error message, but the library never prints these error messages (because the best way to display an error to a user is platform-specific). Instead, the function SDIF_GetErrorString returns the string corresponding to any given error code. */ /* update sdif.c to reflect any changes made to these error values. */ typedef enum { ESDIF_SUCCESS=0, ESDIF_SEE_ERRNO=1, ESDIF_BAD_SDIF_HEADER=2, ESDIF_BAD_FRAME_HEADER=3, ESDIF_SKIP_FAILED=4, ESDIF_BAD_MATRIX_DATA_TYPE=5, ESDIF_BAD_SIZEOF=6, ESDIF_END_OF_DATA=7, /* Not necessarily an error */ ESDIF_BAD_MATRIX_HEADER=8, ESDIF_OBSOLETE_FILE_VERSION=9, ESDIF_OBSOLETE_TYPES_VERSION=10, ESDIF_WRITE_FAILED=11, ESDIF_READ_FAILED=12, ESDIF_OUT_OF_MEMORY=13, /* Used only by sdif-mem.c */ ESDIF_DUPLICATE_MATRIX_TYPE_IN_FRAME=14 } SDIFresult; /****************************************************/ /***** These data structures match the SDIF spec ****/ /****************************************************/ /* the header for the entire SDIF data. */ typedef struct { char SDIF[4]; /* must be 'S', 'D', 'I', 'F' */ sdif_int32 size; /* size of header frame, not including SDIF or size. */ sdif_int32 SDIFversion; sdif_int32 SDIFStandardTypesVersion; } SDIF_GlobalHeader; /* the header for each frame of SDIF data. */ typedef struct { char frameType[4]; /* should be a registered frame type */ sdif_int32 size; /* # bytes in this frame, not including frameType or size */ sdif_float64 time; /* time corresponding to frame */ sdif_int32 streamID; /* frames that go together have the same ID */ sdif_int32 matrixCount; /* number of matrices in frame */ } SDIF_FrameHeader; /* the header for each matrix of SDIF data. */ typedef struct { char matrixType[4]; sdif_int32 matrixDataType; sdif_int32 rowCount; sdif_int32 columnCount; } SDIF_MatrixHeader; /* Version numbers for SDIF_GlobalHeader associated with this library */ #define SDIF_SPEC_VERSION 3 #define SDIF_LIBRARY_VERSION 1 /* codes for data types used in matrices. these must be kept in sync with the array in sdif.c. */ typedef enum { SDIF_FLOAT32 = 0x0004, SDIF_FLOAT64 = 0x0008, SDIF_INT32 = 0x0104, SDIF_UINT32 = 0x0204, SDIF_UTF8 = 0x0301, SDIF_BYTE = 0x0401, SDIF_NO_TYPE = -1 } SDIF_MatrixDataType; typedef enum { SDIF_FLOAT = 0, SDIF_INT = 1, SDIF_UINT = 2, SDIF_TEXT = 3, SDIF_ARBITRARY = 4 } SDIF_MatrixDataTypeHighOrder; /****************************************************/ /***** Procedures in the library ****/ /****************************************************/ /* SDIF_Init -- You must call this before any of the other SDIF procedures. */ SDIFresult SDIF_Init(void); /* SDIF_GetErrorString -- Returns the string representation of the given error code. */ char *SDIF_GetErrorString(SDIFresult errorcode); /************* Opening and closing files *************/ /* SDIF_OpenWrite -- Opens "filename" for writing and writes the global SDIF header (but does not flush). The resulting FILE* is written into *resultp. */ SDIFresult SDIF_OpenWrite(const char *filename, FILE **resultp); /* SDIF_BeginWrite -- Same as SDIF_OpenWrite() except that it takes a FILE * already opened for binary writing. */ SDIFresult SDIF_BeginWrite(FILE *output); /* SDIF_CloseWrite -- */ SDIFresult SDIF_CloseWrite(FILE *f); /* SDIF_OpenRead -- Opens "filename" for reading and reads and parses the header. The return value will indicate any problem in the header. After calling this the file pointer will be advanced to the beginning of the first frame. */ SDIFresult SDIF_OpenRead(const char *filename, FILE **resultp); /* SDIF_BeginRead -- Same as SDIF_OpenRead() except that it takes a FILE * already opened for binary reading. */ SDIFresult SDIF_BeginRead(FILE *input); /* SDIF_CloseRead -- */ SDIFresult SDIF_CloseRead(FILE *f); /************* Global Header *************/ /* SDIF_FillGlobalHeader -- Writes "SDIF" into "h" and initializes the size and version members. */ void SDIF_FillGlobalHeader(SDIF_GlobalHeader *h); /* SDIF_WriteGlobalHeader -- Writes "h" to "f". */ SDIFresult SDIF_WriteGlobalHeader(const SDIF_GlobalHeader *h, FILE *f); /************* Frames *************/ /* SDIF_ReadFrameHeader -- Reads a frame header from "f" and writes it to "fh". If you've reached the end of the file or stream (which is not an error), this will return ESDIF_END_OF_DATA. */ SDIFresult SDIF_ReadFrameHeader(SDIF_FrameHeader *fh, FILE *f); /* SDIF_WriteFrameHeader -- Writes "fh" to "f". */ SDIFresult SDIF_WriteFrameHeader(const SDIF_FrameHeader *fh, FILE *f); /* SDIF_SkipFrame -- Assuming that you just read an SDIF_FrameHeader and want to ignore the contents of the frame (e.g., because your program doesn't recognize its frameType), call this procedure to skip over the frame data, so you'll be ready to read the next SDIF_FrameHeader from the input. The arguments are a pointer to the SDIF_FrameHeader you just read (which includes the size count) and the open FILE *. */ SDIFresult SDIF_SkipFrame(const SDIF_FrameHeader *fh, FILE *f); /************* Matrices *************/ /* SDIF_ReadMatrixHeader -- Fills "m" with the matrix header read from "f". */ SDIFresult SDIF_ReadMatrixHeader(SDIF_MatrixHeader *m, FILE *f); /* SDIF_WriteMatrixHeader -- Writes "m" to "f". */ SDIFresult SDIF_WriteMatrixHeader(const SDIF_MatrixHeader *m, FILE *f); /* SDIF_GetMatrixDataTypeSize -- Find the size in bytes of the data type indicated by "d" */ #define SDIF_GetMatrixDataTypeSize(d) ((d) & 0xff) /* SDIF_GetMatrixDataSize -- Returns the size in bytes of the matrix described by the given SDIF_MatrixHeader, including possible byte padding. */ int SDIF_GetMatrixDataSize(const SDIF_MatrixHeader *m); /* SDIF_PaddingRequired -- Returns the number of padding bytes required after the matrix data according to the given SDIF_MatrixHeader. */ int SDIF_PaddingRequired(const SDIF_MatrixHeader *m); /* SDIF_SkipMatrix -- Assuming that you just read an SDIF_MatrixHeader and want to ignore the contents of this matrix (e.g., because your program doesn't recognize its matrixType), call this procedure to skip over the matrix data. It will leave the file pointer pointing at the next matrix after the one you skipped, or pointing at the next frame header if the one we skipped was the last one in the frame. */ SDIFresult SDIF_SkipMatrix(const SDIF_MatrixHeader *head, FILE *f); /* SDIF_ReadMatrixData -- Assuming that you just read an SDIF_MatrixHeader and want to read the matrix data itself into a block of memory that you've allocated, call this procedure to do so. Handles big/little endian issues. */ SDIFresult SDIF_ReadMatrixData(void *putItHere, FILE *f, const SDIF_MatrixHeader *head); /************* Stream IDs *************/ /* SDIF_UniqueStreamID -- Each call to this procedure returns a locally unique stream ID: 1, 2, 3... This procedure is not thread-safe. */ sdif_int32 SDIF_UniqueStreamID(void); /************* 4-byte character arrays *************/ /* SDIF_Char4Eq -- Checks two 4-byte character arrays for equality. Returns zero if they differ, nonzero if they're the same. */ int SDIF_Char4Eq(const char *thisone, const char *thatone); /* SDIF_Copy4Bytes -- Copies 4 bytes (e.g., "SDIF") into a 4-byte char array. */ void SDIF_Copy4Bytes(char *target, const char *string); /* SDIF_Read and SDIF_Write -- Abstract away big endian/little endian in reading/writing 1, 2, 4, and 8 byte data. These procedures all take arguments just like fwrite() and fread(), except that the size of the objects you're writing is determined by which function you call instead of an explicit argument. Also, they do little-endian conversion when necessary. */ #ifndef LITTLE_ENDIAN # define LITTLE_ENDIAN 1 #endif #if defined(__POWERPC__) || defined(__PPC__) || defined(__ppc__) # undef LITTLE_ENDIAN #endif SDIFresult SDIF_Write1(const void *block, size_t n, FILE *f); SDIFresult SDIF_Write2(const void *block, size_t n, FILE *f); SDIFresult SDIF_Write4(const void *block, size_t n, FILE *f); SDIFresult SDIF_Write8(const void *block, size_t n, FILE *f); SDIFresult SDIF_Read1(void *block, size_t n, FILE *f); SDIFresult SDIF_Read2(void *block, size_t n, FILE *f); SDIFresult SDIF_Read4(void *block, size_t n, FILE *f); SDIFresult SDIF_Read8(void *block, size_t n, FILE *f); #ifdef __cplusplus } #endif #endif /* __SDIF_H */ csound-6.10.0/SDIF/sdif2adsyn.c000066400000000000000000000326111321653344700160430ustar00rootroot00000000000000/* sdif2adsyn.c: convert SDIF 1TRC additive synthesis data to Csound adsyn format * v1.0 Richard W Dobson August 4 2000 */ #include #include #include #include #include "sdif.h" #include "sdif-mem.h" #ifndef max #define max(x,y) ((x)>(y) ? (x) : (y)) #endif #ifndef min #define min(x,y) ((x)>(y) ? (y) : (x)) #endif /* SDIF indices start from 1 */ #define MAXPARTIALS (1025) /* some old but worthy CNMAT functions */ typedef struct { sdif_float32 index, freq, amp, phase; } SDIF_RowOf1TRC; int SDIF_Read1TRCVals(FILE *f, sdif_float32 *indexp, sdif_float32 *freqp, sdif_float32 *ampp, sdif_float32 *phasep) { SDIF_RowOf1TRC data; #ifdef LITTLE_ENDIAN if (SDIF_Read4(&data, 4, f) != ESDIF_SUCCESS) return -1; #else if (fread(&data, sizeof(data), 1, f) != 1) return -1; #endif *indexp = data.index; *freqp = data.freq; *ampp = data.amp; *phasep = data.phase; return 0; } void usage(void) { printf("SDIF2ADS v1.0: convert sdif 1TRC data to Csound hetro data file.\n" "usage: [-sN][-pN] sdif2adsyn infile.sdif outfile.ads\n" " -s : apply amplitude scale factor N\n" " -p : keep only the first N partials.\n" " (limit: 1024 partials)\n" " NB: the source partial track indices are used directly\n" " to select internal storage.\n" " As these can be arbitrary values, the maximum\n" " of 1024 partials may not be realized in all cases.\n"); } typedef struct partial_point{ float amp; float freq; float pos; struct partial_point *next; } P_POINT; typedef struct partial_props { long numpoints; float maxamp; float maxfreq; float minfreq; P_POINT *head; } PPROPS; int write_partial(FILE *fp,const P_POINT *partial,float sfac,int do_scale) ; P_POINT *new_ppoint(float amp,float freq,float pos) { P_POINT *point; point = (P_POINT *) malloc(sizeof(P_POINT)); if (point) { point->amp = amp; point->freq = freq; point->pos = pos; point->next = NULL; } return point; } /* if anyone wants it, there is enough information to select a frequency range to output.*/ PPROPS *new_pprops(void) { PPROPS *prop; prop = (PPROPS *) malloc(sizeof(PPROPS)); if (prop) { prop->numpoints = 0; prop->maxamp = 0.0f; prop->maxfreq = 0.0f; prop->minfreq = 0.0f; prop->head = NULL; /* will point to head of partial[n] */ } return prop; } int main(int argc, char **argv) { int i,framecount, partials_written = 0; int result, iindex; int max_partials = MAXPARTIALS; int n_partials = 0, maxpoints = 0; sdif_int32 frame_id = -1; SDIF_FrameHeader fh; SDIF_MatrixHeader mh; FILE *infile,*outfile; P_POINT **partials; PPROPS **pprops; sdif_float32 index,amp,freq,phase; float thistime = 0.0f; float maxfreq = 0.0f, minfreq = 100000.0f, maxamp = 0.0f; float scalefac = 1.0; int doscale = 0; short stemp; /* to write partial count to adsyn file */ if (argc < 2) { usage(); exit(1); } printf("SDIF2ADS v1.1\n"); if (SDIF_Init() != ESDIF_SUCCESS) { fprintf(stderr,"OOPS: SDIF does not work on this machine!\n"); exit(1); } while (argv[1][0]=='-') { switch (argv[1][1]) { case('s'): if (argv[1][2] == '\0') { fprintf(stderr,"-s flag requires parameter.\n"); usage(); exit(1); } scalefac = (float) atof(&(argv[1][2])); if (scalefac==0.0f) { fprintf(stderr,"silly value for scalefac!\n"); exit(1); } doscale = 1; break; case('p'): if (argv[1][2] == '\0') { fprintf(stderr,"-p flag requires parameter.\n"); usage(); exit(1); } max_partials = atoi(&(argv[1][2])); if (max_partials < 1) { fprintf(stderr, "-p value too low: need at least one partial!\n"); usage(); exit(1); } if (max_partials > (MAXPARTIALS-1)) { printf("Warning: -p value too high: setting to %d\n", MAXPARTIALS-1); } break; default: fprintf(stderr,"\nunrecognized flag option %s",argv[1]); usage(); exit(1); } argc--; argv++; } if (argc < 2) { fprintf(stderr,"\nSDIF2ADSYN: insufficient arguments"); usage(); exit(1); } result = SDIF_OpenRead(argv[1],&infile); if (result != ESDIF_SUCCESS) { fprintf(stderr,"Couldn't open %s: %s\n", argv[1], SDIF_GetErrorString(result)); exit(1); } if ((outfile = fopen(argv[2],"wb"))==NULL) { fprintf(stderr,"\nunable to open outfile %s",argv[3]); fclose(infile); exit(1); } /* initialize partials array */ /* NB index value 0 NOT USED */ /* allocate for 1024 partials; use user limit on writing outfile */ partials = (P_POINT **) malloc(MAXPARTIALS * sizeof(P_POINT *)); if (partials==NULL) { puts("No memory for partial data!\n"); exit(1); } pprops = (PPROPS **) malloc (MAXPARTIALS * sizeof(PPROPS *)); if (pprops==NULL) { puts("No memory for partial data!\n"); free(partials); exit(1); } for (i=0;i < MAXPARTIALS; i++) { partials[i] = NULL; pprops[i] = NULL; } /* STRATEGY: a very straight conversion from a frame structure to * a breakpoint structure. for each new partial in the SDIF file, * we start a new partial in the array, at the given index. when * a partial dies, the amplitude is (presumed to be) zero, but the * list is not terminated. if an SDIF frame with that index * starts a new partial, the partial with that index continues * accordingly. * * Though in most cases, track indices will small and sequential, * this cannot be presumed. If most or all indices are above * MAXPARTIALS, we are b******d. * Of course, the SDIF file will not tell us what the index range is. * That would be too easy. */ /* main loop to read sdif frames */ framecount = 0; /* assume the frame is kosher for now...*/ while ((result = SDIF_ReadFrameHeader(&fh, infile))==ESDIF_SUCCESS) { if (strncmp(fh.frameType,"1TRC",4)) continue; /*we can only copy one stream - use the first one! */ if (frame_id==-1) frame_id = fh.streamID; else if (frame_id != fh.streamID) { fprintf(stderr,"\nWARNING: multiple stream IDs found - skipping"); continue; } #ifdef _DEBUG /*printf("\nReading SDIF Frame %d, time = %.4f",framecount,fh.time); */ #endif thistime = (float) fh.time; /* Csound adsyn counts time in msecs, in shorts, so can only have 32.767 seconds! */ if (thistime > 32.76f) { printf("Sorry! Reached ADSYN limit of 32.76 seconds.\n"); break; } framecount++; for (i = 0; i < fh.matrixCount; ++i) { int j; if (SDIF_ReadMatrixHeader(&mh,infile) != ESDIF_SUCCESS) { fprintf(stderr,"\nerror reading infile"); exit(1); } /* for now, only accept floats */ if (mh.matrixDataType != SDIF_FLOAT32) { fprintf(stderr,"\nsorry - data not floats"); exit(1); } n_partials = mh.rowCount; #ifdef _DEBUG /*printf("\nReading Matrix %ld: %ld rows",i+1,n_partials); */ #endif for (j=0;j < n_partials; j++) { if (SDIF_Read1TRCVals(infile,&index,&freq,&, &phase)) { fprintf(stderr,"\nerror reading tracks"); exit(1); } if (index < 1.0f) { fprintf(stderr,"Illegal partial index %.2f found in frame %d.\n", index,framecount); exit(1); } iindex = (int) index; /* a small (unlikely) sacrifice for the sake of a simple algorithm! */ if (iindex >= MAXPARTIALS) { printf("Warning: high partial index %d in frame %d; skipping.\n", iindex,framecount); continue; } /* make a new list if we need it */ if (partials[iindex]==NULL) { partials[iindex] = new_ppoint(amp,freq,thistime); if (partials[iindex]==NULL) { puts("No memory for partial data!\n"); exit(1); } pprops[iindex] = new_pprops(); if (pprops[iindex]==NULL) { puts("No memory for partial data!\n"); exit(1); } pprops[iindex]->head = partials[iindex]; pprops[iindex]->maxamp = amp; pprops[iindex]->maxfreq = pprops[iindex]->minfreq = freq; pprops[iindex]->numpoints = 1; } else { /*attach new point to existing list, and update props */ partials[iindex]->next = new_ppoint(amp,freq,thistime); if (partials[iindex]->next==NULL) { puts("No memory for partial data!\n"); exit(1); } partials[iindex] = partials[iindex]->next; pprops[iindex]->maxamp = max(pprops[iindex]->maxamp,amp); pprops[iindex]->maxfreq = max(pprops[iindex]->maxfreq,freq); pprops[iindex]->minfreq = min(pprops[iindex]->minfreq,freq); pprops[iindex]->numpoints++; } } } } /* maybe a single frame is legit? */ if (framecount < 2) { if (framecount==1) fprintf(stderr,"Only one frame found: at least two required.\n"); else fprintf(stderr,"No 1TRC frames found in this sdif file.\n"); SDIF_CloseRead(infile); fclose(outfile); free(partials); free(pprops); exit(0); } /* now we have to write it all out for Csound */ /* how many partials do we have, and what might a good srate be?*/ n_partials = 0; for (i=0;i < MAXPARTIALS;i++) { if (partials[i] != NULL) { maxfreq = max(maxfreq,pprops[i]->maxfreq); minfreq = min(minfreq,pprops[i]->minfreq); maxamp = max(maxamp,pprops[i]->maxamp); maxpoints = max(maxpoints,pprops[i]->numpoints); n_partials++; } } printf("total partials read = %d\n",n_partials); printf("maximum breakpoints = %d\n",maxpoints); printf("max frequency found = %.4f\n",maxfreq); printf("min frequency found = %.4f\n",minfreq); printf("max partial amp found = %.4f\n",maxamp); printf("last frame time = %.4f\n",thistime); /* OK, write this all to adsyn file as shorts (for now....) */ stemp = (short) n_partials; stemp = min(stemp,max_partials); /* set user limit, if any */ /* write number of partial tracks */ if (fwrite((short *) &stemp,sizeof(short),1,outfile) < 1) { fprintf(stderr,"Error writing to outfile.\n"); exit(1); } /* now write each set of amp,freq sets */ for (i=0;i < MAXPARTIALS;i++) { if (partials[i]==NULL) continue; if (write_partial(outfile,pprops[i]->head,scalefac,doscale) < 0) { fprintf(stderr,"Error writing partial %d.\n",i); exit(1); } partials_written++; if (partials_written == (int) stemp) break; } /* release linked lists */ for (i=0;i < MAXPARTIALS;i++) { P_POINT *tthis,*next; if (partials[i]==NULL) continue; tthis = pprops[i]->head; free(pprops[i]); next = tthis->next; while(next) { free(tthis); tthis = next; next = next->next; } free(tthis); } free(partials); free(pprops); fclose(outfile); printf("File conversion completed.\n"); printf("%d partials written to %s\n",(int)stemp,argv[2]); SDIF_CloseRead(infile); return 0; } /* pass props->head */ /* NB does not check for over-range times */ /* it also trusts that there is a freq element matching each amp element */ int write_partial(FILE *fp,const P_POINT *partial,float sfac,int do_scale) { int length = 0; const P_POINT *head; float scalefac = 32767.0f; short amp,freq,time; short amptag = -1, freqtag = -2; short trackend = 32767; if (fp==NULL) return -1; if (partial==NULL) return -1; if (do_scale) scalefac *= sfac; head = partial; if ((fwrite((char *)&tag,sizeof(short),1,fp)) < 1) return -1; /* nothing clever, just go through each list twice */ /*write amps, scaled to 32767 (oh for a f/p adsyn format...) */ while (head) { time = (short)(1000.0f * head->pos); if ((fwrite((char *) &time,sizeof(short),1,fp)) < 1) return -1; amp = (short) (scalefac * head->amp); if ((fwrite((char *)&,sizeof(short),1,fp)) < 1) return -1; length++; head = head->next; } if ((fwrite(&trackend,sizeof(short),1,fp)) < 1) return -1; head = partial; if ((fwrite(&freqtag,sizeof(short),1,fp)) < 1) return -1; while(head) { time = (short)(1000.0f * head->pos); if ((fwrite((char *) &time,sizeof(short),1,fp)) < 1) return -1; freq = (short)(head->freq); if ((fwrite(&freq,sizeof(short),1,fp)) < 1) return -1; head = head->next; } if ((fwrite(&trackend,sizeof(short),1,fp)) < 1) return -1; return length; } csound-6.10.0/SDIF/sdif_rdm.txt000066400000000000000000000030271321653344700161600ustar00rootroot00000000000000SDIF support in Csound. For detailed information on the Sound Description Interchange Format, refer to the CNMAT website: http://cnmat.CNMAT.Berkeley.EDU/SDIF If the filename passed to HETRO has the extension .sdif, data will be written in SDIF format as 1TRC frames of additive synthesis data. The accompanying utility program "sdif2ads" can be used to convert any SDIF file containing a stream of 1TRC data to the Csound 'adsyn' format. 'sdif2ads' allows the user to limit the number of partials retained, and to apply an amplitude scaling factor. This is often necessary, as the SDIF specification does not, to date, require amplitudes to be within a particular range. 'sdif2ads' reports information about the file to the console, including the frequency range. The main advantages of SDIF over the adsyn format, for Csound users, is that SDIF files are fully portable across platforms (data is 'big-endian'), and do not have the duration limit of 32.76 seconds imposed by the 16bit adsyn format.This limit is necessarily imposed by 'sdif2ads'. It is planned to incorporate sdif reading directly into adsyn, thus enabling files of any length (currently memory-permitting) to be analysed and processed. It is important to note that the SDIF formats are still under development, and that while the 1TRC format is now fairly well established, it can still change. Some other SDIF resources (including a viewer) are available via the NC_DREAM website: http://www.bath.ac.uk/~masjpf/NCD/dreamhome.html Richard Dobson 5th August 2000 rwd@cableinet.co.uk csound-6.10.0/SuSE/000077500000000000000000000000001321653344700137205ustar00rootroot00000000000000csound-6.10.0/SuSE/README.SuSE000066400000000000000000000010241321653344700154130ustar00rootroot00000000000000Plugin Directories ================== The plugin binaries are installed under /usr/lib/csound/plugins (/usr/lib64/csound/plugins in x86_64). Please set the environment variable "OPCODE6DIR" to this directory before starting csound. in bash style, export OPCODE6DIR64=/usr/lib/csound/plugins in tcsh style, setenv OPCODE6DIR64 /usr/lib/csound/plugins Binary Renaming =============== sndinfo is renamed to csndinfo in this package due to the name confliction with snd package. Simiarly, extract was renamed to csound-extract. csound-6.10.0/SuSE/csound-python-2.6-fix.diff000066400000000000000000000157761321653344700204730ustar00rootroot00000000000000--- SConstruct-dist 2008-10-01 14:46:05.000000000 +0200 +++ SConstruct 2008-10-01 15:25:35.000000000 +0200 @@ -266,19 +266,19 @@ Tool('mingw')(commonEnvironment) customCPPPATH = commonEnvironment['customCPPPATH'] -commonEnvironment.Prepend(CPPPATH = customCPPPATH) +commonEnvironment.Prepend(CPPPATH = Split(customCPPPATH)) customCCFLAGS = commonEnvironment['customCCFLAGS'] -commonEnvironment.Prepend(CCFLAGS = customCCFLAGS) +commonEnvironment.Prepend(CCFLAGS = Split(customCCFLAGS)) customCXXFLAGS = commonEnvironment['customCXXFLAGS'] -commonEnvironment.Prepend(CXXFLAGS = customCXXFLAGS) +commonEnvironment.Prepend(CXXFLAGS = Split(customCXXFLAGS)) customLIBS = commonEnvironment['customLIBS'] -commonEnvironment.Prepend(LIBS = customLIBS) +commonEnvironment.Prepend(LIBS = Split(customLIBS)) customLIBPATH = commonEnvironment['customLIBPATH'] -commonEnvironment.Prepend(LIBPATH = customLIBPATH) +commonEnvironment.Prepend(LIBPATH = Split(customLIBPATH)) customSHLINKFLAGS = commonEnvironment['customSHLINKFLAGS'] -commonEnvironment.Prepend(SHLINKFLAGS = customSHLINKFLAGS) +commonEnvironment.Prepend(SHLINKFLAGS = Split(customSHLINKFLAGS)) customSWIGFLAGS = commonEnvironment['customSWIGFLAGS'] -commonEnvironment.Prepend(SWIGFLAGS = customSWIGFLAGS) +commonEnvironment.Prepend(SWIGFLAGS = Split(customSWIGFLAGS)) # Define options for different platforms. if getPlatform() != 'win32': @@ -339,15 +339,15 @@ # Define different build environments for different types of targets. if not withMSVC(): - commonEnvironment.Prepend(CCFLAGS = "-Wall") + commonEnvironment.Prepend(CCFLAGS = ["-Wall"]) if getPlatform() == 'linux': - commonEnvironment.Append(CCFLAGS = "-DLINUX") - commonEnvironment.Append(CPPFLAGS = '-DHAVE_SOCKETS') - commonEnvironment.Append(CPPPATH = '/usr/local/include') - commonEnvironment.Append(CPPPATH = '/usr/include') - commonEnvironment.Append(CPPPATH = '/usr/X11R6/include') - commonEnvironment.Append(CCFLAGS = "-DPIPES") + commonEnvironment.Append(CCFLAGS = ["-DLINUX"]) + commonEnvironment.Append(CPPFLAGS = ['-DHAVE_SOCKETS']) + commonEnvironment.Append(CPPPATH = ['/usr/local/include']) + commonEnvironment.Append(CPPPATH = ['/usr/include']) + commonEnvironment.Append(CPPPATH = ['/usr/X11R6/include']) + commonEnvironment.Append(CCFLAGS = ["-DPIPES"]) commonEnvironment.Append(LINKFLAGS = ['-Wl,-Bdynamic']) elif getPlatform() == 'darwin': commonEnvironment.Append(CCFLAGS = "-DMACOSX") @@ -519,9 +519,9 @@ if getPlatform() == 'win32': if configure.CheckHeader("winsock.h", language = "C"): - commonEnvironment.Append(CPPFLAGS = '-DHAVE_SOCKETS') + commonEnvironment.Append(CPPFLAGS = ['-DHAVE_SOCKETS']) elif configure.CheckHeader("sys/socket.h", language = "C"): - commonEnvironment.Append(CPPFLAGS = '-DHAVE_SOCKETS') + commonEnvironment.Append(CPPFLAGS = ['-DHAVE_SOCKETS']) if getPlatform() == 'darwin': commonEnvironment.Append(CPPFLAGS = '-DHAVE_DIRENT_H') @@ -954,7 +954,7 @@ pyModule_ = env.Program('_%s.so' % targetName, srcs) else: if getPlatform() == 'linux': - pyModule_ = env.SharedLibrary('%s' % targetName, srcs, SHLIBPREFIX="_", SHLIBSUFFIX = '.so') + pyModule_ = env.SharedLibrary('%s' % targetName, srcs, SHLIBPREFIX="_", SHLIBSUFFIX = ['.so']) else: pyModule_ = env.SharedLibrary('_%s' % targetName, srcs, SHLIBSUFFIX = '.pyd') if getPlatform() == 'win32' and pythonLibs[0] < 'python24': @@ -992,7 +992,7 @@ ''')) csoundWrapperEnvironment = csoundInterfacesEnvironment.Copy() fixCFlagsForSwig(csoundWrapperEnvironment) - csoundWrapperEnvironment.Append(CPPFLAGS = '-D__BUILDING_CSOUND_INTERFACES') + csoundWrapperEnvironment.Append(CPPFLAGS = ['-D__BUILDING_CSOUND_INTERFACES']) for option in csoundWrapperEnvironment['CCFLAGS']: if string.find(option, '-D') == 0: csoundWrapperEnvironment.Append(SWIGFLAGS = [option]) @@ -1407,11 +1407,11 @@ # distribution into the csound5/Opcodes/Loris directory, e.g. # csound5/Opcodes/Loris/src/*, etc. lorisEnvironment = pluginEnvironment.Copy() - lorisEnvironment.Append(CCFLAGS = '-DHAVE_FFTW3_H') + lorisEnvironment.Append(CCFLAGS = ['-DHAVE_FFTW3_H']) if commonEnvironment['buildRelease'] == '0': - lorisEnvironment.Append(CCFLAGS = '-DDEBUG_LORISGENS') + lorisEnvironment.Append(CCFLAGS = ['-DDEBUG_LORISGENS']) if getPlatform() == 'win32': - lorisEnvironment.Append(CCFLAGS = '-D_MSC_VER') + lorisEnvironment.Append(CCFLAGS = ['-D_MSC_VER']) if not withMSVC(): lorisEnvironment.Append(CCFLAGS = Split(''' -Wno-comment -Wno-unknown-pragmas -Wno-sign-compare @@ -1474,15 +1474,15 @@ ''') stkEnvironment = pluginEnvironment.Copy() if getPlatform() == 'win32': - stkEnvironment.Append(CCFLAGS = '-D__OS_WINDOWS__') + stkEnvironment.Append(CCFLAGS = ['-D__OS_WINDOWS__']) elif getPlatform() == 'linux': - stkEnvironment.Append(CCFLAGS = '-D__OS_LINUX__') + stkEnvironment.Append(CCFLAGS = ['-D__OS_LINUX__']) elif getPlatform() == 'darwin': - stkEnvironment.Append(CCFLAGS = '-D__OS_MACOSX__') + stkEnvironment.Append(CCFLAGS = ['-D__OS_MACOSX__']) if sys.byteorder == 'big': - stkEnvironment.Append(CCFLAGS = '-D__BIG_ENDIAN__') + stkEnvironment.Append(CCFLAGS = ['-D__BIG_ENDIAN__']) else: - stkEnvironment.Append(CCFLAGS = '-D__LITTLE_ENDIAN__') + stkEnvironment.Append(CCFLAGS = ['-D__LITTLE_ENDIAN__']) stkEnvironment.Prepend(CPPPATH = Split(''' Opcodes/stk/include Opcodes/stk/src ./ ./../include ''')) @@ -1523,7 +1523,7 @@ pyEnvironment.Append(LIBS = ['dl', 'm']) elif getPlatform() == 'win32': pyEnvironment['ENV']['PATH'] = os.environ['PATH'] - pyEnvironment.Append(SHLINKFLAGS = '--no-export-all-symbols') + pyEnvironment.Append(SHLINKFLAGS = ['--no-export-all-symbols']) pythonOpcodes = makePlugin(pyEnvironment, 'py', ['Opcodes/py/pythonopcodes.c']) if getPlatform() == 'win32' and pythonLibs[0] < 'python24': @@ -1713,7 +1713,7 @@ vstEnvironment.Append(SWIGFLAGS = Split('-c++ -includeall -verbose -outdir .')) if getPlatform() == 'linux': vstEnvironment.Append(LIBS = ['util', 'dl', 'm']) - vstEnvironment.Append(SHLINKFLAGS = '--no-export-all-symbols') + vstEnvironment.Append(SHLINKFLAGS = ['--no-export-all-symbols']) vstEnvironment.Append(LINKFLAGS = ['-Wl,-rpath-link,.']) guiProgramEnvironment.Prepend(LINKFLAGS = ['-Wl,-rpath-link,.']) os.spawnvp(os.P_WAIT, 'rm', ['rm', '-f', '_CsoundVST.so']) @@ -2029,7 +2029,7 @@ print "...Building csLadspa" csLadspaEnv = commonEnvironment.Copy() csLadspaEnv.Append(LIBS=libCsoundLibs) -csLadspaEnv.Append(CCFLAGS='-I./frontends/csladspa') +csLadspaEnv.Append(CCFLAGS=['-I./frontends/csladspa']) csladspa = csLadspaEnv.SharedLibrary('frontends/csladspa/csladspa.cpp', PREFIX="") Depends(csladspa, csoundLibrary) libs.append(csladspa) csound-6.10.0/SuSE/csound.changes000066400000000000000000000061451321653344700165530ustar00rootroot00000000000000------------------------------------------------------------------- Thu Dec 22 -- John ffitch - Brought into line with csound 5.15 ------------------------------------------------------------------- Sun Sep 18 00:04:38 UTC 2011 - jengelh@medozas.de - Remove redundant tags/sections from specfile ------------------------------------------------------------------- Thu Jul 16 18:04:52 CEST 2009 - tiwai@suse.de - fix scons argument to build for 64bit archs (bnc#521979) ------------------------------------------------------------------- Wed Jan 28 14:40:46 CET 2009 - tiwai@suse.de - Fix python module search path insecure issue (bnc#470095) This package is unaffected; the patch is included just for any possible cases in future. ------------------------------------------------------------------- Wed Oct 1 15:28:52 CEST 2008 - tiwai@suse.de - fix build with python-2.6 ------------------------------------------------------------------- Wed Jun 20 15:44:26 CEST 2007 - tiwai@suse.de - fix fdupes usage ------------------------------------------------------------------- Mon Jun 11 17:57:22 CEST 2007 - tiwai@suse.de - updated to version 5.06: * fix k-rate, vrandh and vrandi scaling problems, mod fix * new opcodes: partikkel, partikkelsync ------------------------------------------------------------------- Tue Mar 27 18:08:43 CEST 2007 - tiwai@suse.de - update to version 5.05: * fixes/improvements on FLTK support * fix heap overflow * clean up old codes ------------------------------------------------------------------- Mon Jan 22 13:11:02 CET 2007 - tiwai@suse.de - major update to version 5.04 (not built with fltk due to lack of threading support) ------------------------------------------------------------------- Mon Mar 27 18:54:23 CEST 2006 - pth@suse.de - Add missing parameter in printf call (bug #129676). ------------------------------------------------------------------- Wed Jan 25 21:35:15 CET 2006 - mls@suse.de - converted neededforbuild to BuildRequires ------------------------------------------------------------------- Fri Oct 15 10:54:27 CEST 2004 - tiwai@suse.de - renamed extract to csound-extract to avoid name confliction (bug #45347). ------------------------------------------------------------------- Wed Jun 2 17:05:41 CEST 2004 - tiwai@suse.de - fixed the ALSA RT plugin with the new API. ------------------------------------------------------------------- Sat Jan 10 18:11:42 CET 2004 - adrian@suse.de - add %run_ldconfig and %defattr ------------------------------------------------------------------- Tue Aug 5 12:48:27 CEST 2003 - tiwai@suse.de - renamed sndinfo to csndinfo to avoid name confliction with snd. ------------------------------------------------------------------- Wed Jul 30 12:48:59 CEST 2003 - tiwai@suse.de - fixed the build on x86-64. ------------------------------------------------------------------- Mon Jul 28 16:11:55 CEST 2003 - tiwai@suse.de - updated to 4.24.1. - fixed tmpnam with mkstemp. ------------------------------------------------------------------- Thu Feb 1 19:18:36 CET 2001 - tiwai@suse.de - Initial vesrion: unofficial-4.10.0.0c csound-6.10.0/SuSE/csound.spec000066400000000000000000000055171321653344700160770ustar00rootroot00000000000000# # spec file for package csound # # Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany. # (c) 2012 Csound Developers # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed # upon. The license for this file, and modifications and additions to the # file, is the same license as for the pristine package itself (unless the # license for the pristine package is not an Open Source License, in which # case the license is the MIT License). An "Open Source License" is a # license that conforms to the Open Source Definition (Version 1.9) # published by the Open Source Initiative. # Please submit bugfixes or comments via http://bugs.opensuse.org/ # Name: csound %define support_fltk 0 BuildRequires: alsa-devel fdupes fluidsynth-devel gcc-c++ jack-devel liblo-devel portaudio-devel python-devel cmake swig %if %support_fltk BuildRequires: fltk-devel libjpeg-devel libpng-devel xorg-x11-devel %endif Summary: Computer Sound Synthesis and Composition Program Version: 6.00 Release: 141 License: GFDL-1.2 ; LGPL-2.1+ ; MIT Group: Productivity/Multimedia/Sound/Utilities Source: Csound%{version}.tar.bz2 Source1: README.SuSE Url: http://www.csounds.com AutoReq: on Autoprov: off BuildRoot: %{_tmppath}/%{name}-%{version}-build %description Csound is a software synthesis program. It is fully modular and supports an unlimited amount of oscillators and filters. For detailed information, refer to http://www.csounds.com. %prep %setup -q -n Csound%{version} cp %{SOURCE1} . # fix encoding iconv -f latin1 -t utf8 readme-csound6.txt > readme-csound6.txt.utf8 %build %if %_lib == "lib64" args="Word64=1 Lib64=1" %else args="" %endif cmake -DCMAKE_INSTALL_PREFIX=$RPM_BUILD_ROOT%{_prefix} -DUSE_LIB64=1 . make prefix=%{_prefix} buildRelease=1 useDouble=1 useOSC=1 \ buildVirtual=1 buildBeats=1 $args \ customCCFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing" \ customCXXFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing" %install %if %_lib == "lib64" args="--word64" %else args="" %endif mkdir -pv $RPM_BUILD_ROOT%{_datadir}/csound make install rm -f $RPM_BUILD_ROOT%{_prefix}/csound6-*.md5sums rm -rf $RPM_BUILD_ROOT%{_datadir}/doc/csound # rename conflicting binary names mv $RPM_BUILD_ROOT%{_bindir}/sndinfo $RPM_BUILD_ROOT%{_bindir}/csndinfo mv $RPM_BUILD_ROOT%{_bindir}/extract $RPM_BUILD_ROOT%{_bindir}/csound-extract # remove devel files rm -f $RPM_BUILD_ROOT%{_libdir}/*.a rm -rf $RPM_BUILD_ROOT%{_includedir} %fdupes -s $RPM_BUILD_ROOT %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %files %defattr(-,root,root) %doc COPYING readme-csound6.txt README.SuSE %{_bindir}/* %{_libdir}/csound %{_datadir}/csound %{_datadir}/locale # %{_includedir}/* # %{_libdir}/lib* %changelog csound-6.10.0/Submitting_opcodes000066400000000000000000000062451321653344700166740ustar00rootroot00000000000000Protocol for submitting new opcodes =================================== The developers are happy to accept code for new opcodes (and other parts) but in order to make the process simple and clear we have drawn up this protocol in the hope that it will avoid embarrassing delays and discussions. Licence ------- In general Csound is licenced with LGPL so submissions need to have that licence or a compatible one. Note that GPL is a problem. Examples of suitable copyright and licence text can be found at the start of most opcode files. Names ----- New opcodes should not have names that start with the letters i, k, f or a. This is to avoid name clashes with existing orchestras; and yes it has happened in the past. Coding ------ Please follow the general style; it is important not to have any static variables which are not constant, while static fuctions are encouraged. Any use of external libraries which introduces new dependencies is a potential problem and may be best discussed with the core team. Formatting/Indentation ---------------------- Ideally C code should not have any tab characters in it, and be limitted to 85 characters wide. Format should be similar to existing code. Also wrap any error strings with a call to Str to assist with language translations. Sample-accurate --------------- If an opcode returns a audio-rate value or uses audio-rate input it must include support for sample-accurate mode. Again looking at existing opcodes shows a template for this. The template for arate perf-pass opcodes is: int perf_myopcode(CSOUND *csound, MYOPCODE *p) { uint32_t offset = p->h.insdshead->ksmps_offset; // delayed onset uint32_t early = p->h.insdshead->ksmps_no_end; // early end of event uint32_t nsmps = CS_KSMPS; ... // Clear parts of the output outside event if (UNLIKELY(offset)) memset(p->res, '\0', offset*sizeof(MYFLT)); if (UNLIKELY(early)) { nsmps -= early; memset(&p->res[nsmps], '\0', early*sizeof(MYFLT)); } for (n=offset; nres[n] = .... } return OK; } Core or Plugin? --------------- New opcodes can be either in the core library, or available as plugins. Which is used depends on a number of factors. If an opcode has external dependencies it can ONLY be added to the Csound standard codebase as a plugin. For platforms where plugins are not available, special packages can be prepared to include an opcode and its dependencies within the core library. if the opcode is only useful on one platform (like the Linux joystick opcode) then a plugin is to be preferred. For others it is a balance between code growth and utility. Documentation ------------- All new opcodes or gens need a manual page, if only a minimal one. Even better if it includes an example .csd file. There is a template in the manual tree opcodes/template.xml, and example files in the examples directory. Submission ---------- Probably easiest as a pull request on github, but direct mail to the developers' mailing list or direct contact with a core developer are OK. ==JPff 2017 Dec 14 csound-6.10.0/Top/000077500000000000000000000000001321653344700136435ustar00rootroot00000000000000csound-6.10.0/Top/README.md000066400000000000000000000014421321653344700151230ustar00rootroot00000000000000Top: files for main software operation ============================ * argdecode.c: argument decoding and parameter setting * cscore_internal.c: cscore score processing main routine * cscorfns.c: cscore score processing functions * csdebug.c: csound runtime debugger * csmodule.c: dynamic module loading (for plugins) * csound.c: CSOUND object initialisation, API functions, performance routines. * getstring.c: string localisation. * init_static_modules: initialisation of some opcode modules. * main.c: compilation and startup routines. * new_opts.c: configuration variable system * one_file.c: CSD file reading. * opcode.c: opcode listing. * server.c: UDP server. * threads.c: threading and locks. * threadsafe.c: threadsafe API implementation. * utility.c: functions for running Csound utilities. csound-6.10.0/Top/argdecode.c000066400000000000000000001713521321653344700157350ustar00rootroot00000000000000/* argdecode.c: Copyright (C) 1998-2013 John ffitch, Victor Lazzarini This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* ARGDECODE.C */ #include "soundio.h" #include "new_opts.h" #include "csmodule.h" #include "corfile.h" #include static void list_audio_devices(CSOUND *csound, int output); static void list_midi_devices(CSOUND *csound, int output); extern void strset_option(CSOUND *csound, char *s); /* from str_ops.c */ extern void print_csound_version(CSOUND* csound); #define FIND(MSG) if (*s == '\0') \ if (UNLIKELY(!(--argc) || (((s = *++argv) != NULL) && *s == '-'))) \ dieu(csound, MSG); #define STDINASSIGN_SNDFILE 1 #define STDINASSIGN_LINEIN 2 #define STDINASSIGN_MIDIFILE 4 #define STDINASSIGN_MIDIDEV 8 #define STDOUTASSIGN_SNDFILE 1 #define STDOUTASSIGN_MIDIOUT 2 /* IV - Feb 19 2005 */ #ifdef EXPERIMENTAL static FILE *logFile = NULL; /* NOT THREAD SAFE */ void msg_callback(CSOUND *csound, int attr, const char *format, va_list args) { (void) csound; if ((attr & CSOUNDMSG_TYPE_MASK) != CSOUNDMSG_REALTIME) { vfprintf(logFile, format, args); fflush(logFile); return; } #if defined(WIN32) || defined(MAC) switch (attr & CSOUNDMSG_TYPE_MASK) { case CSOUNDMSG_ERROR: case CSOUNDMSG_WARNING: case CSOUNDMSG_REALTIME: break; default: vfprintf(logFile, format, args); return; } #endif vfprintf(stderr, format, args); } void nomsg_callback(CSOUND *csound, int attr, const char *format, va_list args){ return; } void do_logging(char *s) { int nomessages = 0; if (logFile) return; if (!strcmp(s, "NULL") || !strcmp(s, "null")) nomessages = 1; else if ((logFile = fopen(s, "w")) == NULL) { fprintf(stderr, Str("Error opening log file '%s': %s\n"), s, strerror(errno)); exit(1); } /* if logging to file, set message callback */ if (logFile != NULL) csoundSetDefaultMessageCallback(msg_callback); else if (nomessages) csoundSetDefaultMessageCallback(nomsg_callback); } void end_logging(void) { if (logFile != NULL) fclose(logFile); } #else #define do_logging(x) {} #endif static inline void set_stdin_assign(CSOUND *csound, int type, int state) { if (state) csound->stdin_assign_flg |= type; else csound->stdin_assign_flg &= (~type); } static inline void set_stdout_assign(CSOUND *csound, int type, int state) { if (state) csound->stdout_assign_flg |= type; else csound->stdout_assign_flg &= (~type); } /* IV - Feb 19 2005 */ static const char *shortUsageList[] = { Str_noop("--help print long usage options"), Str_noop("--version print version details"), Str_noop("-U unam run utility program unam"), Str_noop("-C use Cscore processing of scorefile"), Str_noop("-j N use N threads in performance"), Str_noop("-I I-time only orch run"), Str_noop("-n no sound onto disk"), Str_noop("-i fnam sound input filename"), Str_noop("-o fnam sound output filename"), Str_noop("-b N sample frames (or -kprds) per software sound I/O buffer"), Str_noop("-B N samples per hardware sound I/O buffer"), Str_noop("-A create an AIFF format output soundfile"), Str_noop("-W create a WAV format output soundfile"), Str_noop("-J create an IRCAM format output soundfile"), Str_noop("-h no header on output soundfile"), Str_noop("-c 8-bit signed_char sound samples"), #ifdef never Str_noop("-a alaw sound samples"), #endif Str_noop("-8 8-bit unsigned_char sound samples"), Str_noop("-u ulaw sound samples"), Str_noop("-s short_int sound samples"), Str_noop("-l long_int sound samples"), Str_noop("-f float sound samples"), Str_noop("-3 24bit sound samples"), Str_noop("-r N orchestra srate override"), Str_noop("-k N orchestra krate override"), Str_noop("-K do not generate PEAK chunks"), Str_noop("-v verbose orch translation"), Str_noop("-m N tty message level. Sum of:"), Str_noop(" 1=note amps, 2=out-of-range msg, 4=warnings"), Str_noop(" 0/32/64/96=note amp format (raw,dB,colors)"), Str_noop(" 128=print benchmark information"), Str_noop("-d suppress all displays"), Str_noop("-g suppress graphics, use ascii displays"), Str_noop("-G suppress graphics, use Postscript displays"), Str_noop("-x fnam extract from score.srt using extract file 'fnam'"), Str_noop("-t N use uninterpreted beats of the score, " "initially at tempo N"), Str_noop("-t 0 use score.srt for sorted score rather than a temporary"), Str_noop("-L dnam read Line-oriented realtime score events from " "device 'dnam'"), Str_noop("-M dnam read MIDI realtime events from device 'dnam'"), Str_noop("-F fnam read MIDIfile event stream from file 'fnam'"), /* Str_noop("-P N MIDI sustain pedal threshold (0 - 128)"), */ Str_noop("-R continually rewrite header while writing soundfile " "(WAV/AIFF)"), Str_noop("-H# print heartbeat style 1, 2 or 3 at each soundfile write"), Str_noop("-N notify (ring the bell) when score or miditrack is done"), Str_noop("-T terminate the performance when miditrack is done"), Str_noop("-D defer GEN01 soundfile loads until performance time"), Str_noop("-Q dnam select MIDI output device"), Str_noop("-z list opcodes in this version"), Str_noop("-Z dither output"), #if defined(LINUX) Str_noop("--sched set real-time priority and lock memory"), Str_noop(" (requires -d and real time audio (-iadc/-odac))"), Str_noop("--sched=N set specified scheduling priority, and lock memory"), Str_noop(" (requires -d and real time audio (-iadc/-odac))"), #endif NULL }; static const char *longUsageList[] = { "--format={wav,aiff,au,raw,paf,svx,nist,voc,ircam,w64,mat4,mat5", " pvf,xi,htk,sds,avr,wavex,sd2,flac,caf,wve,ogg,mpc2k,rf64}", "--format={alaw,ulaw,schar,uchar,float,double,short,long,24bit,vorbis}", Str_noop(" Set output file format"), Str_noop("--aiff set AIFF format"), Str_noop("--au set AU format"), Str_noop("--wave set WAV format"), Str_noop("--ircam set IRCAM format"), Str_noop("--ogg set OGG/VORBIS format"), Str_noop("--noheader raw format"), Str_noop("--nopeaks do not write peak information"), " ", Str_noop("--displays use graphic displays"), Str_noop("--nodisplays suppress all displays"), Str_noop("--asciidisplay suppress graphics, use ascii displays"), Str_noop("--postscriptdisplay suppress graphics, use Postscript displays"), " ", Str_noop("--defer-gen1 defer GEN01 soundfile loads until " "performance time"), Str_noop("--iobufsamps=N sample frames (or -kprds) per software " "sound I/O buffer"), Str_noop("--hardwarebufsamps=N samples per hardware sound I/O buffer"), Str_noop("--cscore use Cscore processing of scorefile"), Str_noop("--orc use orchfile without scorefile"), " ", Str_noop("--midifile=FNAME read MIDIfile event stream from file"), Str_noop("--midioutfile=FNAME write MIDI output to file FNAME"), Str_noop("--midi-device=FNAME read MIDI realtime events from device"), Str_noop("--terminate-on-midi terminate the performance when miditrack " "is done"), " ", Str_noop("--heartbeat=N print a heartbeat style 1, 2 or 3 at " "each soundfile write"), Str_noop("--notify notify (ring the bell) when score or " "miditrack is done"), Str_noop("--rewrite continually rewrite header while writing " "soundfile (WAV/AIFF)"), " ", Str_noop("--input=FNAME sound input filename"), Str_noop("--output=FNAME sound output filename"), Str_noop("--logfile=FNAME log output to file"), " ", Str_noop("--nosound no sound onto disk or device"), Str_noop("--tempo=N use uninterpreted beats of the score, " "initially at tempo N"), Str_noop("--i-only I-time only orch run"), Str_noop("--syntax-check-only stop after checking orchestra and " "score syntax"), Str_noop("--control-rate=N orchestra krate override"), Str_noop("--sample-rate=N orchestra srate override"), Str_noop("--score-in=FNAME read line-oriented realtime score events " "from device"), Str_noop("--messagelevel=N tty message level, sum of:"), Str_noop("--messageolevel=O tty message level in octal, of:"), Str_noop(" 1=note amps, 2=out-of-range msg, 4=warnings,"), Str_noop(" 0/32/64/96=note amp format (raw,dB,colors),"), Str_noop(" 128=print benchmark information"), " ", Str_noop("--m-amps=[01] messages on note amps"), Str_noop("--m-range=[01] messages on range errors"), Str_noop("--m-warnings=[01] mesage on warnings"), Str_noop("--m-raw=[01] raw amp messages"), Str_noop("--m-dB=[01] amp messages in dB"), Str_noop("--m-colours=[01] colour amp messages"), Str_noop("--m-benchmarks=[01] print benchmark information"), Str_noop("--csd-line-nums=[01] controls how error line numbers are printed:"), Str_noop(" 1=use CSD line #s (default), 0=use " "ORC/SCO-relative line #s"), Str_noop("--extract-score=FNAME extract from score.srt using extract file"), Str_noop("--keep-sorted-score"), Str_noop("--env:NAME=VALUE set environment variable NAME to VALUE"), Str_noop("--env:NAME+=VALUE append VALUE to environment variable NAME"), Str_noop("--strsetN=VALUE set strset table at index N to VALUE"), Str_noop("--utility=NAME run utility program"), Str_noop("--verbose verbose orch translation"), Str_noop("--list-opcodes list opcodes in this version"), Str_noop("--list-opcodesN list opcodes in style N in this version"), Str_noop("--dither dither output"), Str_noop("--dither-triangular dither output with triangular distribution"), Str_noop("--dither-uniform dither output with rectanular distribution"), Str_noop("--sched set real-time scheduling priority and " "lock memory"), Str_noop("--sched=N set priority to N and lock memory"), Str_noop("--opcode-lib=NAMES dynamic libraries to load"), Str_noop("--opcode-omit=NAMES dynamic libraries not to load"), Str_noop("--omacro:XXX=YYY set orchestra macro XXX to value YYY"), Str_noop("--smacro:XXX=YYY set score macro XXX to value YYY"), Str_noop("--midi-key=N route MIDI note on message"), Str_noop(" key number to pfield N as " "MIDI value [0-127]"), Str_noop("--midi-key-cps=N route MIDI note on message"), Str_noop(" key number to pfield N as cycles per second"), Str_noop("--midi-key-oct=N route MIDI note on message"), Str_noop(" key number to pfield N as linear octave"), Str_noop("--midi-key-pch=N route MIDI note on message"), Str_noop(" key number to pfield N as oct.pch"), Str_noop("--midi-velocity=N route MIDI note on message"), Str_noop(" velocity number to pfield N as MIDI " "value [0-127]"), Str_noop("--midi-velocity-amp=N route MIDI note on message"), Str_noop(" velocity number to pfield N as amplitude"), Str_noop("--no-default-paths turn off relative paths from CSD/ORC/SCO"), Str_noop("--sample-accurate use sample-accurate timing of score events"), Str_noop("--realtime realtime priority mode"), Str_noop("--nchnls=N override number of audio channels"), Str_noop("--nchnls_i=N override number of input audio channels"), Str_noop("--0dbfs=N override 0dbfs (max positive signal amplitude)"), Str_noop("--sinesize length of internal sine table"), Str_noop("--daemon daemon mode: do not exit if CSD/orchestra is " "not given, is empty or does not compile"), Str_noop("--port=N listen to UDP port N for instruments/orchestra " "code (implies --daemon)"), Str_noop("--vbr-quality=Ft set quality of variable bit-rate compression"), Str_noop("--devices[=in|out] list available MIDI devices and exit"), Str_noop("--midi-devices[=in|out] list available audio devices and exit"), Str_noop("--get-system-sr print system sr and exit"), Str_noop("--ksmps=N override ksmps"), Str_noop("--fftlib=N actual FFT lib to use (FFTLIB=0, " "PFFFT = 1, vDSP =2)"), Str_noop("--udp-echo echo UDP commands on terminal"), Str_noop("--aft-zero set aftertouch to zero, not 127 (default)"), " ", Str_noop("--help long help"), NULL }; /* IV - Feb 19 2005 */ void print_short_usage(CSOUND *csound) { char buf[256]; int i; i = -1; while (shortUsageList[++i] != NULL) { snprintf(buf, 256, "%s\n", shortUsageList[i]); csound->Message(csound, "%s", Str(buf)); } csound->Message(csound, Str("flag defaults: csound -s -otest -b%d -B%d -m%d\n\n"), IOBUFSAMPS, IODACSAMPS, csound->oparms->msglevel); } static void longusage(CSOUND *p) { const char **sp; p->Message(p, Str("Usage: csound [-flags] orchfile scorefile\n")); p->Message(p, Str("Legal flags are:\n")); p->Message(p, Str("Long format:\n\n")); for (sp = &(longUsageList[0]); *sp != NULL; sp++) p->Message(p, "%s\n", Str(*sp)); dump_cfg_variables(p); p->Message(p, Str("\nShort format:\n\n")); print_short_usage(p); } CS_NORETURN void dieu(CSOUND *csound, char *s, ...) { va_list args; csound->Message(csound,Str("Usage: csound [-flags] orchfile scorefile\n")); csound->Message(csound,Str("Legal flags are:\n")); print_short_usage(csound); va_start(args, s); csound->ErrMsgV(csound, Str("Csound Command ERROR: "), s, args); va_end(args); //***FIXME This code makes no sense if (csound->info_message_request == 0) { csound->info_message_request = 0; csound->LongJmp(csound, 1); } //Added longjump -- JPff csound->LongJmp(csound, 1); } void set_output_format(OPARMS *O, char c) { switch (c) { case 'a': O->outformat = AE_ALAW; /* a-law soundfile */ break; case 'c': O->outformat = AE_CHAR; /* signed 8-bit soundfile */ break; case '8': O->outformat = AE_UNCH; /* unsigned 8-bit soundfile */ break; case 'f': O->outformat = AE_FLOAT; /* float soundfile */ break; case 'd': O->outformat = AE_DOUBLE; /* double soundfile */ break; case 's': O->outformat = AE_SHORT; /* short_int soundfile*/ break; case 'l': O->outformat = AE_LONG; /* long_int soundfile */ break; case 'u': O->outformat = AE_ULAW; /* mu-law soundfile */ break; case '3': O->outformat = AE_24INT; /* 24bit packed soundfile*/ break; case 'e': O->outformat = AE_FLOAT; /* float soundfile (for rescaling) */ break; case 'v': O->outformat = AE_VORBIS; /* Xiph Vorbis encoding */ break; default: return; /* do nothing */ }; } typedef struct { char *longformat; char shortformat; } SAMPLE_FORMAT_ENTRY; static const SAMPLE_FORMAT_ENTRY sample_format_map[] = { { "alaw", 'a' }, { "schar", 'c' }, { "uchar", '8' }, { "float", 'f' }, { "double", 'd' }, { "long", 'l' }, { "short", 's' }, { "ulaw", 'u' }, { "24bit", '3' }, { "vorbis", 'v' }, { NULL, '\0' } }; const char* get_output_format(OPARMS *O) { int i = 0; char c; switch (O->outformat) { case AE_ALAW: c = 'a'; break; case AE_CHAR: c = 'c'; break; case AE_UNCH: c = '8'; break; case AE_FLOAT: c = 'f'; break; case AE_DOUBLE: c = 'd'; break; case AE_SHORT: c = 's'; break; case AE_LONG: c = 'l'; break; case AE_ULAW: c = 'u'; break; case AE_24INT: c = '3'; break; case AE_VORBIS: c = 'v'; break; default: c = '\0'; }; while(c != sample_format_map[i].shortformat && sample_format_map[i].longformat != NULL) { i++; } return sample_format_map[i].longformat; } typedef struct { char *format; int type; } SOUNDFILE_TYPE_ENTRY; static const SOUNDFILE_TYPE_ENTRY file_type_map[] = { { "wav", TYP_WAV }, { "aiff", TYP_AIFF }, { "au", TYP_AU }, { "raw", TYP_RAW }, { "paf", TYP_PAF }, { "svx", TYP_SVX }, { "nist", TYP_NIST }, { "voc", TYP_VOC }, { "ircam", TYP_IRCAM }, { "w64", TYP_W64 }, { "mat4", TYP_MAT4 }, { "mat5", TYP_MAT5 }, { "pvf", TYP_PVF }, { "xi", TYP_XI }, { "htk", TYP_HTK }, { "sds", TYP_SDS }, { "avr", TYP_AVR }, { "wavex", TYP_WAVEX }, { "sd2", TYP_SD2 }, { "flac", TYP_FLAC }, { "caf", TYP_CAF }, { "wve", TYP_WVE }, { "ogg", TYP_OGG }, { "mpc2k", TYP_MPC2K }, { "rf64", TYP_RF64 }, { NULL , -1 } }; extern void sfopenout(CSOUND *csound); extern void sfcloseout(CSOUND *csound); static int decode_long(CSOUND *csound, char *s, int argc, char **argv) { OPARMS *O = csound->oparms; /* Add other long options here */ if (UNLIKELY(O->odebug)) csound->Message(csound, "decode_long %s\n", s); if (!(strncmp(s, "omacro:", 7))) { if (csound->orcname_mode) return 1; NAMES *nn = (NAMES*) csound->Malloc(csound, sizeof(NAMES)); nn->mac = s; nn->next = csound->omacros; csound->omacros = nn; return 1; } else if (!(strncmp(s, "smacro:", 7))) { if (csound->orcname_mode) return 1; NAMES *nn = (NAMES*) csound->Malloc(csound, sizeof(NAMES)); nn->mac = s; nn->next = csound->smacros; csound->smacros = nn; return 1; } else if (!(strncmp(s, "format=", 7))) { const SAMPLE_FORMAT_ENTRY *sfe; const SOUNDFILE_TYPE_ENTRY *ff; s += 7; do { char *t; t = strchr(s, ':'); if (t != NULL) *(t++) = '\0'; for (ff = &(file_type_map[0]); ff->format != NULL; ff++) { if (strcmp(ff->format, s) == 0) { O->filetyp = ff->type; goto nxtToken; } } for (sfe = &(sample_format_map[0]); sfe->longformat != NULL; sfe++) { if (strcmp(s, sfe->longformat) == 0) { set_output_format(O, sfe->shortformat); goto nxtToken; } } csoundErrorMsg(csound, Str("unknown output format: '%s'"), s); return 0; nxtToken: s = t; } while (s != NULL); return 1; } /* -A */ else if (!(strcmp (s, "aiff"))) { O->filetyp = TYP_AIFF; /* AIFF output request */ return 1; } else if (!(strcmp (s, "au"))) { O->filetyp = TYP_AU; /* AU output request */ return 1; } else if (!(strncmp (s, "iobufsamps=", 11))) { s += 11; if (UNLIKELY(*s=='\0')) dieu(csound, Str("no iobufsamps")); /* defaults in musmon.c */ O->inbufsamps = O->outbufsamps = atoi(s); return 1; } else if (!(strncmp (s, "hardwarebufsamps=", 17))) { s += 17; if (UNLIKELY(*s=='\0')) dieu(csound, Str("no hardware bufsamps")); O->inbufsamps = O->outbufsamps = atoi(s); return 1; } else if (!(strcmp (s, "orc"))) { csound->use_only_orchfile = 1; /* orchfile without scorefile */ return 1; } else if (!(strcmp (s, "cscore"))) { O->usingcscore = 1; /* use cscore processing */ return 1; } else if (!(strcmp (s, "nodisplays"))) { O->displays = 0; /* no func displays */ return 1; } else if (!(strcmp (s, "displays"))) { O->displays = 1; /* func displays */ O->graphsoff = 0; return 1; } else if (!(strcmp (s, "defer-gen1"))) { O->gen01defer = 1; /* defer GEN01 sample loads */ return 1; /* until performance time */ } else if (!(strncmp (s, "midifile=", 9))) { s += 9; if (*s==3) s++; /* skip ETX */ if (UNLIKELY(*s == '\0')) dieu(csound, Str("no midifile name")); O->FMidiname = s; /* Midifile name */ if (!strcmp(O->FMidiname, "stdin")) { #if defined(WIN32) csoundDie(csound, Str("-F: stdin not supported on this platform")); #else set_stdin_assign(csound, STDINASSIGN_MIDIFILE, 1); #endif } else set_stdin_assign(csound, STDINASSIGN_MIDIFILE, 0); O->FMidiin = 1; /***************/ return 1; } else if (!(strncmp (s, "midioutfile=", 12))) { s += 12; if (*s==3) s++; /* skip ETX */ if (UNLIKELY(*s == '\0')) dieu(csound, Str("no midi output file name")); O->FMidioutname = s; return 1; } /* -g */ else if (!(strcmp (s, "asciidisplay"))) { O->graphsoff = 1; /* don't use graphics but ASCII */ return 1; } /* -G */ else if (!(strcmp (s, "postscriptdisplay"))) { O->postscript = 1; /* don't use graphics but PostScript */ return 1; } /* -h */ else if (!(strcmp (s, "noheader"))) { O->filetyp = TYP_RAW; /* RAW output request */ return 1; } else if (!(strncmp (s, "heartbeat=", 10))) { s += 10; if (*s == '\0') O->heartbeat = 1; else O->heartbeat = atoi(s); return 1; } #ifdef EMBEDDED_PYTHON else if (strncmp(s, "pyvar=", 6) == 0) { s += 6; if (*s==3) s++; /* skip ETX */ if (UNLIKELY(python_add_cmdline_definition(s))) dieu(csound, Str("invalid python variable definition syntax")); return 1; } #endif else if (!(strncmp (s, "input=", 6))) { s += 6; if (*s==3) s++; /* skip ETX */ if (UNLIKELY(*s == '\0')) dieu(csound, Str("no infilename")); O->infilename = s; /* soundin name */ if (UNLIKELY(strcmp(O->infilename, "stdout") == 0)) csoundDie(csound, Str("input cannot be stdout")); if (strcmp(O->infilename, "stdin") == 0) { set_stdin_assign(csound, STDINASSIGN_SNDFILE, 1); #if defined(WIN32) csoundDie(csound, Str("stdin audio not supported")); #endif } else set_stdin_assign(csound, STDINASSIGN_SNDFILE, 0); O->sfread = 1; return 1; } /* -I I-time only orch run */ else if (!(strcmp (s, "i-only"))) { csound->initonly = 1; O->syntaxCheckOnly = 0; /* overrides --syntax-check-only */ O->sfwrite = 0; /* and implies nosound */ return 1; } else if (!(strcmp (s, "ircam"))) { O->filetyp = TYP_IRCAM; /* IRCAM output request */ return 1; } else if (!(strcmp (s, "ogg"))) { O->filetyp = TYP_OGG; /* OGG output request */ O->outformat = AE_VORBIS; /* Xiph Vorbis encoding */ return 1; } /* -k N orchestra krate override */ else if (!(strncmp(s, "control-rate=", 13))) { s += 13; if (UNLIKELY(*s=='\0')) dieu(csound, Str("no control rate")); O->kr_override = (float)atof(s); return 1; } else if (!(strncmp(s, "ksmps=", 6))) { s += 6; if (UNLIKELY(*s=='\0')) dieu(csound, Str("no ksmps")); O->ksmps_override = atoi(s); return 1; } /* -K */ else if (!(strcmp (s, "nopeaks"))) { csound->peakchunks = 0; /* Do not write peak information */ return 1; } /* -L dnam read Line-oriented realtime score events from device 'dnam' */ else if (!(strncmp (s, "score-in=", 9))) { s += 9; if (*s==3) s++; /* skip ETX */ if (UNLIKELY(*s=='\0')) dieu(csound, Str("no Linein score device_name")); O->Linename = s; if (!strcmp(O->Linename, "stdin")) { set_stdin_assign(csound, STDINASSIGN_LINEIN, 1); } else set_stdin_assign(csound, STDINASSIGN_LINEIN, 0); O->Linein = 1; return 1; } /* -m N tty message level. Sum of: 1=note amps, 2=out-of-range msg, 4=warnings */ else if (!(strncmp (s, "messagelevel=", 13))) { s += 13; if (UNLIKELY(*s=='\0')) dieu(csound, Str("no message level")); O->msglevel = atoi(s); return 1; } else if (!(strncmp (s, "messageolevel=", 14))) { s += 14; if (UNLIKELY(*s=='\0')) dieu(csound, Str("no message level")); sscanf(s, "%o", &(O->msglevel)); return 1; } else if (!(strncmp (s, "m-amps=", 7))) { int n; s += 7; if (UNLIKELY(*s=='\0')) dieu(csound, Str("no message amps")); sscanf(s, "%d", &n); if (n) O->msglevel |= AMPLMSG; else O->msglevel &= ~AMPLMSG; return 1; } else if (!(strncmp (s, "m-range=",8))) { int n; s += 8; if (UNLIKELY(*s=='\0')) dieu(csound, Str("no message range")); sscanf(s, "%d", &n); if (n) O->msglevel |= RNGEMSG; else O->msglevel &= ~RNGEMSG; return 1; } else if (!(strncmp (s, "m-warnings=",11))) { int n; s += 11; if (UNLIKELY(*s=='\0')) dieu(csound, Str("no message warnings")); sscanf(s, "%d", &n); if (n) O->msglevel |= WARNMSG; else O->msglevel &= ~WARNMSG; return 1; } else if (!(strncmp (s, "m-raw=",6))) { int n; s += 6; if (UNLIKELY(*s=='\0')) dieu(csound, Str("no message raw")); sscanf(s, "%d", &n); if (n) O->msglevel |= 32; else O->msglevel &= ~32; return 1; } else if (!(strncmp (s, "m-dB=",5))) { int n; s += 5; if (UNLIKELY(*s=='\0')) dieu(csound, Str("no message dB")); sscanf(s, "%d", &n); if (n) O->msglevel |= RAWMSG; else O->msglevel &= ~RAWMSG; return 1; } else if (!(strncmp (s, "m-colours=",10)) || !(strncmp (s, "m-colors=",9))) { int n; s += 10; if (*s=='\0') dieu(csound, Str("no message colours")); sscanf(s, "%d", &n); if (n) O->msglevel |= 96; else O->msglevel &= ~96; return 1; } else if (!(strncmp (s, "m-benchmarks=",13))) { int n; s += 13; if (UNLIKELY(*s=='\0')) dieu(csound, Str("no benchmark level")); sscanf(s, "%d", &n); if (n) O->msglevel |= TIMEMSG; else O->msglevel &= ~TIMEMSG; return 1; } else if (!(strncmp (s, "csd-line-nums=",14))) { s += 14; if (UNLIKELY(*s=='\0')) dieu(csound, Str("no value for --csd-line-nums")); O->useCsdLineCounts = (atoi(s) != 0); return 1; } /* -M dnam read MIDI realtime events from device 'dnam' */ else if (!(strncmp (s, "midi-device=", 12))) { s += 12; if (*s==3) s++; /* skip ETX */ if (UNLIKELY(*s=='\0')) dieu(csound, Str("no midi device_name")); O->Midiname = s; if (!strcmp(O->Midiname, "stdin")) { set_stdin_assign(csound, STDINASSIGN_MIDIDEV, 1); #if defined(WIN32) csoundDie(csound, Str("-M: stdin not supported on this platform")); #endif } else set_stdin_assign(csound, STDINASSIGN_MIDIDEV, 0); O->Midiin = 1; return 1; } /* -n no sound */ else if (!(strcmp (s, "nosound"))) { O->sfwrite = 0; /* nosound */ return 1; } /* -N */ else if (!(strcmp (s, "notify"))) { O->ringbell = 1; /* notify on completion */ return 1; } else if (!(strncmp (s, "output=", 7))) { s += 7; if (*s==3) s++; /* skip ETX */ if (UNLIKELY(*s == '\0')) dieu(csound, Str("no outfilename")); O->outfilename = s; /* soundout name */ if (UNLIKELY(strcmp(O->outfilename, "stdin")) == 0) dieu(csound, Str("-o cannot be stdin")); if (strcmp(O->outfilename, "stdout") == 0) { set_stdout_assign(csound, STDOUTASSIGN_SNDFILE, 1); #if defined(WIN32) csoundDie(csound, Str("stdout audio not supported")); #endif } else set_stdout_assign(csound, STDOUTASSIGN_SNDFILE, 0); O->sfwrite = 1; return 1; } else if (!(strncmp (s, "logfile=", 8))) { s += 8; if (UNLIKELY(*s=='\0')) dieu(csound, Str("no log file")); do_logging(s); return 1; } /* -r N */ else if (!(strncmp (s, "sample-rate=", 12))) { s += 12; if (*s==3) s++; /* skip ETX */ O->sr_override = (float)atof(s); return 1; } /* R */ else if (!(strcmp (s, "rewrite"))) { O->rewrt_hdr = 1; return 1; } /* -S */ /* tempo=N use uninterpreted beats of the score, initially at tempo N */ else if (UNLIKELY(!(strncmp (s, "tempo=", 6)))) { s += 6; O->cmdTempo = atof(s); O->Beatmode = 1; /* on uninterpreted Beats */ return 1; } /* -t0 */ else if (!(strcmp (s, "keep-sorted-score"))) { csound->keep_tmp = 1; return 1; } /* IV - Jan 27 2005: --expression-opt */ /* NOTE these do nothing */ else if (!(strcmp (s, "expression-opt"))) { //O->expr_opt = 1; csound->Warning(csound, Str("option expresson-opt has no affect\n")); return 1; } else if (!(strcmp (s, "no-expression-opt"))) { //O->expr_opt = 0; csound->Warning(csound, Str("option no-expresson-opt has no affect\n")); return 1; } else if (!(strncmp (s, "env:", 4))) { if (csoundParseEnv(csound, s + 4) == CSOUND_SUCCESS) return 1; else return 0; } else if (!(strncmp (s, "strset", 6))) { strset_option(csound, s + 6); return 1; } /* -T terminate the performance when miditrack is done */ else if (!(strcmp (s, "terminate-on-midi"))) { O->termifend = 1; /* terminate on midifile end */ return 1; } else if (!(strncmp (s, "utility=", 8))) { int retval; s += 8; if (*s==3) s++; /* skip ETX */ if (*s=='\0') dieu(csound, Str("no utility name")); retval = csoundRunUtility(csound, s, argc, argv); if (retval) { csound->info_message_request = 1; csound->orchname = NULL; return 0; } else csound->LongJmp(csound, retval); return 1; } /* -v */ else if (!(strcmp (s, "verbose"))) { O->odebug = 1; /* verbose otran */ return 1; } /* -x fnam extract from score.srt using extract file 'fnam' */ else if (!(strncmp(s, "extract-score=", 14))) { s += 14; if (UNLIKELY(*s=='\0')) dieu(csound, Str("no xfilename")); csound->xfilename = s; return 1; } else if (!(strcmp(s, "wave"))) { O->filetyp = TYP_WAV; /* WAV output request */ return 1; } else if (!(strncmp (s, "list-opcodes", 12))) { int full = 0; s += 12; if (*s != '\0') { if (isdigit(*s)) full = *s++ - '0'; } list_opcodes(csound, full); return 1; //csound->LongJmp(csound, 0); } /* -Z */ else if (!(strcmp (s, "dither"))) { csound->dither_output = 1; return 1; } else if (!(strcmp (s, "dither-uniform"))) { csound->dither_output = 2; return 1; } else if (!(strcmp (s, "dither-triangular"))) { csound->dither_output = 1; return 1; } else if (!(strncmp (s, "midi-key=", 9))) { s += 9; O->midiKey = atoi(s); return 1; } else if (!(strncmp (s, "midi-key-cps=", 13))) { s += 13 ; O->midiKeyCps = atoi(s); return 1; } else if (!(strncmp (s, "midi-key-oct=", 13))) { s += 13 ; O->midiKeyOct = atoi(s); return 1; } else if (!(strncmp (s, "midi-key-pch=", 13))) { s += 13 ; O->midiKeyPch = atoi(s); return 1; } else if (!(strncmp (s, "midi-velocity=", 14))) { s += 14; O->midiVelocity = atoi(s); return 1; } else if (!(strncmp (s, "midi-velocity-amp=", 18))) { s += 18; O->midiVelocityAmp = atoi(s); return 1; } else if (!(strncmp (s, "opcode-lib=", 11))) { int nbytes; s += 11; if (*s==3) s++; /* skip ETX */ nbytes = (int) strlen(s) + 1; if (csound->dl_opcodes_oplibs == NULL) { /* start new library list */ csound->dl_opcodes_oplibs = (char*) csound->Malloc(csound, (size_t) nbytes); strcpy(csound->dl_opcodes_oplibs, s); } else { /* append to existing list */ nbytes += ((int) strlen(csound->dl_opcodes_oplibs) + 1); csound->dl_opcodes_oplibs = (char*) csound->ReAlloc(csound, csound->dl_opcodes_oplibs, (size_t) nbytes); strcat(csound->dl_opcodes_oplibs, ","); strcat(csound->dl_opcodes_oplibs, s); } return 1; } else if (!(strcmp(s, "default-paths"))) { O->noDefaultPaths = 0; return 1; } else if (!(strcmp(s, "no-default-paths"))) { O->noDefaultPaths = 1; return 1; } else if (!(strncmp (s, "num-threads=", 12))) { s += 12 ; O->numThreads = atoi(s); return 1; } else if (!(strcmp (s, "syntax-check-only"))) { O->syntaxCheckOnly = 1; return 1; } else if (!(strcmp(s, "version"))) { //print_csound_version(csound); // as already printed! csound->LongJmp(csound, 0); } else if (!(strcmp(s, "help"))) { longusage(csound); csound->info_message_request = 1; return 1; //csound->LongJmp(csound, 0); } else if (!(strcmp(s, "sample-accurate"))) { O->sampleAccurate = 1; return 1; } else if (!(strcmp(s, "realtime"))) { csound->Message(csound, Str("realtime mode enabled\n")); O->realtime = 1; return 1; } else if (!(strncmp(s, "nchnls=", 7))) { s += 7; O->nchnls_override = atoi(s); return 1; } else if (!(strncmp(s, "0dbfs=", 6))) { s += 6; O->e0dbfs_override = atoi(s); return 1; } else if (!(strncmp(s, "nchnls_i=", 9))) { s += 9; O->nchnls_i_override = atoi(s); return 1; } else if (!(strncmp(s, "sinesize=", 9))) { { int i = 1, n; s += 9; n = atoi(s); while (i<=n && i< MAXLEN) i <<= 1; csound->sinelength = i; return 1; } } else if (!(strcmp(s, "new-parser")) || !(strcmp(s, "old-parser"))) { return 1; /* ignore flag, this is here for backwards compatibility */ } else if (!(strcmp(s, "sco-parser"))) { csound->score_parser = 1; return 1; /* Try new parser */ } else if (!(strcmp(s, "daemon"))) { O->daemon = 1; return 1; } else if (!(strncmp(s, "port=",5))) { s += 5; O->daemon = atoi(s); return 1; } else if (!(strncmp(s, "udp-echo",8))) { s += 8; O->echo = 1; return 1; } else if (!(strncmp(s, "udp-console=",12))) { char *ports; s += 12; ports = strchr(s, ':'); if(*s != '\0' && ports != NULL) { *ports = '\0'; csoundUDPConsole(csound, s, atoi(ports+1),0); } else csound->Warning(csound, "UDP console: needs address and port\n"); return 1; } else if (!(strncmp(s, "udp-mirror-console=",19))) { char *ports; s += 19; ports = strchr(s, ':'); if(*s != '\0' && ports != NULL) { *ports = '\0'; csoundUDPConsole(csound, s, atoi(ports+1),1); } else csound->Warning(csound, "UDP console: needs address and port\n"); return 1; } else if (!(strncmp(s, "fftlib=",7))) { s += 7; O->fft_lib = atoi(s); return 1; } else if (!(strncmp(s, "vbr-quality=",12))) { s += 12; O->quality = atof(s); return 1; } else if (!(strncmp(s, "devices",7))) { csoundLoadExternals(csound); if (csoundInitModules(csound) != 0) csound->LongJmp(csound, 1); if (*(s+7) == '='){ if (!strncmp(s+8,"in", 2)) { list_audio_devices(csound, 0); } else if (!strncmp(s+8,"out", 2)) list_audio_devices(csound,1); } else { list_audio_devices(csound,0); list_audio_devices(csound,1); } csound->info_message_request = 1; return 1; } else if (!(strncmp(s, "midi-devices",12))) { csoundLoadExternals(csound); if (csoundInitModules(csound) != 0) csound->LongJmp(csound, 1); if (*(s+12) == '='){ if (!strncmp(s+13,"in", 2)) { list_midi_devices(csound, 0); } else if (!strncmp(s+13,"out", 2)) list_midi_devices(csound,1); } else { list_midi_devices(csound,0); list_midi_devices(csound,1); } csound->info_message_request = 1; return 1; } else if (!(strncmp(s, "get-system-sr",13))){ if (O->outfilename && !(strncmp(O->outfilename, "dac",3))) { /* these are default values to get the backend to open successfully */ set_output_format(O, 'f'); O->inbufsamps = O->outbufsamps = 256; O->oMaxLag = 1024; csoundLoadExternals(csound); if (csoundInitModules(csound) != 0) csound->LongJmp(csound, 1); sfopenout(csound); csound->MessageS(csound,CSOUNDMSG_STDOUT, "system sr: %f\n", csound->system_sr(csound,0)); sfcloseout(csound); } csound->info_message_request = 1; return 1; } else if (!(strcmp(s, "aft-zero"))){ csound->aftouch = 0; return 1; } csoundErrorMsg(csound, Str("unknown long option: '--%s'"), s); return 0; } PUBLIC int argdecode(CSOUND *csound, int argc, const char **argv_) { OPARMS *O = csound->oparms; char *s, **argv; int n; char c; /* make a copy of the option list */ char *p1, *p2; int nbytes, i; /* calculate the number of bytes to allocate */ /* N.B. the argc value passed to argdecode is decremented by one */ nbytes = (argc + 1) * (int) sizeof(char*); for (i = 0; i <= argc; i++) nbytes += ((int) strlen(argv_[i]) + 1); p1 = (char*) csound->Malloc(csound, nbytes); /* will be freed by memRESET() */ p2 = (char*) p1 + ((int) sizeof(char*) * (argc + 1)); argv = (char**) p1; for (i = 0; i <= argc; i++) { argv[i] = p2; strcpy(p2, argv_[i]); p2 = (char*) p2 + ((int) strlen(argv_[i]) + 1); } csound->keep_tmp = 0; do { s = *++argv; if (*s++ == '-') { /* read all flags: */ while ((c = *s++) != '\0') { switch (c) { case 'U': FIND(Str("no utility name")); { int retval = csoundRunUtility(csound, s, argc, argv); if (retval) { csound->info_message_request = 1; csound->orchname = NULL; goto end; } else csound->LongJmp(csound, retval); } break; case 'C': O->usingcscore = 1; /* use cscore processing */ break; case 'I': csound->initonly = 1; /* I-only overrides */ O->syntaxCheckOnly = 0; /* --syntax-check-only and implies */ case 'n': O->sfwrite = 0; /* nosound */ break; case 'i': FIND(Str("no infilename")); O->infilename = s; /* soundin name */ s += (int) strlen(s); if (UNLIKELY(strcmp(O->infilename, "stdout")) == 0) csoundDie(csound, Str("input cannot be stdout")); if (strcmp(O->infilename, "stdin") == 0) { set_stdin_assign(csound, STDINASSIGN_SNDFILE, 1); #if defined(WIN32) csoundDie(csound, Str("stdin audio not supported")); #endif } else set_stdin_assign(csound, STDINASSIGN_SNDFILE, 0); O->sfread = 1; break; case 'o': FIND(Str("no outfilename")); O->outfilename = s; /* soundout name */ s += (int) strlen(s); if (UNLIKELY(strcmp(O->outfilename, "stdin") == 0)) dieu(csound, Str("-o cannot be stdin")); if (strcmp(O->outfilename, "stdout") == 0) { set_stdout_assign(csound, STDOUTASSIGN_SNDFILE, 1); #if defined(WIN32) csoundDie(csound, Str("stdout audio not supported")); #endif } else set_stdout_assign(csound, STDOUTASSIGN_SNDFILE, 0); O->sfwrite = 1; break; case 'b': FIND(Str("no iobufsamps")); sscanf(s, "%d%n", &(O->outbufsamps), &n); /* defaults in musmon.c */ O->inbufsamps = O->outbufsamps; s += n; break; case 'B': FIND(Str("no hardware bufsamps")); sscanf(s, "%d%n", &(O->oMaxLag), &n); /* defaults in rtaudio.c */ s += n; break; case 'A': O->filetyp = TYP_AIFF; /* AIFF output request*/ break; case 'J': O->filetyp = TYP_IRCAM; /* IRCAM output request */ break; case 'W': O->filetyp = TYP_WAV; /* WAV output request */ break; case 'h': O->filetyp = TYP_RAW; /* RAW output request */ break; case 'c': case 'a': case 'u': case '8': case 's': case '3': case 'l': case 'f': set_output_format(O, c); break; case 'r': FIND(Str("no sample rate")); O->sr_override = (float)atof(s); while (*++s); break; case 'k': FIND(Str("no control rate")); O->kr_override = (float)atof(s); while (*++s); break; case 'v': O->odebug = 1; /* verbose otran */ break; case 'm': FIND(Str("no message level")); sscanf(s, "%d%n", &(O->msglevel), &n); s += n; break; case 'd': O->displays = 0; /* no func displays */ break; case 'g': O->graphsoff = 1; /* don't use graphics */ break; case 'G': O->postscript = 1; /* Postscript graphics*/ break; case 'x': FIND(Str("no xfilename")); csound->xfilename = s; /* extractfile name */ while (*++s); break; case 't': FIND(Str("no tempo value")); { double val; sscanf(s, "%lg%n", &val, &n); /* use this tempo .. */ s += n; if (UNLIKELY(val < 0.0)) dieu(csound, Str("illegal tempo")); else if (val == 0.0) { csound->keep_tmp = 1; break; } O->cmdTempo = val; O->Beatmode = 1; /* on uninterpreted Beats */ } break; case 'L': FIND(Str("no Linein score device_name")); O->Linename = s; /* Linein device name */ s += (int) strlen(s); if (!strcmp(O->Linename, "stdin")) { set_stdin_assign(csound, STDINASSIGN_LINEIN, 1); } else set_stdin_assign(csound, STDINASSIGN_LINEIN, 0); O->Linein = 1; break; case 'M': FIND(Str("no midi device_name")); O->Midiname = s; /* Midi device name */ s += (int) strlen(s); if (strcmp(O->Midiname, "stdin")==0) { #if defined(WIN32) csoundDie(csound, Str("-M: stdin not supported on this platform")); #else set_stdin_assign(csound, STDINASSIGN_MIDIDEV, 1); #endif } else set_stdin_assign(csound, STDINASSIGN_MIDIDEV, 0); O->Midiin = 1; break; case 'F': FIND(Str("no midifile name")); O->FMidiname = s; /* Midifile name */ s += (int) strlen(s); if (strcmp(O->FMidiname, "stdin")==0) { #if defined(WIN32) csoundDie(csound, Str("-F: stdin not supported on this platform")); #else set_stdin_assign(csound, STDINASSIGN_MIDIFILE, 1); #endif } else set_stdin_assign(csound, STDINASSIGN_MIDIFILE, 0); O->FMidiin = 1; /*****************/ break; case 'Q': FIND(Str("no MIDI output device")); O->Midioutname = s; s += (int) strlen(s); break; case 'R': O->rewrt_hdr = 1; break; case 'H': if (isdigit(*s)) { sscanf(s, "%d%n", &(O->heartbeat), &n); s += n; } else O->heartbeat = 1; break; case 'N': O->ringbell = 1; /* notify on completion */ break; case 'T': O->termifend = 1; /* terminate on midifile end */ break; case 'D': O->gen01defer = 1; /* defer GEN01 sample loads until performance time */ break; case 'K': csound->peakchunks = 0; /* Do not write peak information */ break; case 'z': { int full = 0; if (*s != '\0') { if (isdigit(*s)) full = *s++ - '0'; } list_opcodes(csound, full); } csound->info_message_request = 1; // csound->LongJmp(csound, 0); break; case 'Z': { int full = 1; if (*s != '\0') { if (isdigit(*s)) full = *s++ - '0'; } csound->dither_output = full; } break; case '@': FIND(Str("No indirection file")); { FILE *ind; void *fd; fd = csound->FileOpen2(csound, &ind, CSFILE_STD, s, "r", NULL, CSFTYPE_OPTIONS, 0); if (UNLIKELY(fd == NULL)) { dieu(csound, Str("Cannot open indirection file %s\n"), s); } else { CORFIL *cf = copy_to_corefile(csound, s, NULL, 0); readOptions(csound, cf, 0); corfile_rm(csound, &cf); csound->FileClose(csound, fd); } while (*s++) {}; s--; /* semicolon on separate line to silence warning */ } break; case 'O': FIND(Str("no log file")); do_logging(s); while (*s++) {}; s--; /* semicolon on separate line to silence warning */ break; case '-': #if defined(LINUX) if (!(strcmp (s, "sched"))) { /* ignore --sched */ while (*(++s)); break; } if (!(strncmp(s, "sched=", 6))) { while (*(++s)); break; } #endif if (!decode_long(csound, s, argc, argv)) csound->LongJmp(csound, 1); while (*(++s)); break; case 'j': FIND(Str("no number of threads")); sscanf(s, "%d%n", &(O->numThreads), &n); s += n; break; case '+': /* IV - Feb 01 2005 */ if (parse_option_as_cfgvar(csound, (char*) s - 2) != 0) csound->LongJmp(csound, 1); while (*(++s)); break; default: if (csound->info_message_request == 0) dieu(csound, Str("unknown flag -%c"), c); } } } else { /* 0: normal, 1: ignore, 2: fail */ if (csound->orcname_mode == 2) { csound->Die(csound, Str("error: orchestra and score name not " "allowed in .csound6rc")); } else if (csound->orcname_mode == 0) { if (csound->orchname == NULL) /* VL dec 2016: better duplicate these */ csound->orchname = cs_strdup(csound, --s); else if (LIKELY(csound->scorename == NULL)) csound->scorename = cs_strdup(csound, --s); else { csound->Message(csound,"argc=%d Additional string \"%s\"\n",argc,--s); dieu(csound, Str("too many arguments")); } } } } while (--argc); end: return 1; } PUBLIC int csoundSetOption(CSOUND *csound, const char *option){ /* if already compiled and running, return */ if (csound->engineStatus & CS_STATE_COMP) return 1; else { const char *args[2] = {"csound", option}; csound->info_message_request = 1; return (argdecode(csound, 1, args) ? 0 : 1); } } PUBLIC void csoundSetParams(CSOUND *csound, CSOUND_PARAMS *p){ OPARMS *oparms = csound->oparms; /* if already compiled and running, return */ if (csound->engineStatus & CS_STATE_COMP) return; /* simple ON/OFF switches */ oparms->odebug = p->debug_mode; oparms->displays = p->displays; oparms->graphsoff = p->ascii_graphs; oparms->postscript = p->postscript_graphs; oparms->usingcscore = p->use_cscore; oparms->ringbell = p->ring_bell; oparms->gen01defer = p->defer_gen01_load; oparms->termifend = p->terminate_on_midi; oparms->noDefaultPaths = p->no_default_paths; oparms->syntaxCheckOnly = p->syntax_check_only; oparms->sampleAccurate = p->sample_accurate; oparms->realtime = p->realtime_mode; oparms->useCsdLineCounts = p->csd_line_counts; oparms->heartbeat = p->heartbeat; oparms->ringbell = p->ring_bell; oparms->daemon = p->daemon; /* message level */ if (p->message_level > 0) oparms->msglevel = p->message_level; /* tempo / beatmode */ if (p->tempo > 0) { oparms->cmdTempo = p->tempo; oparms->Beatmode = 1; } /* buffer frames */ if (p->buffer_frames > 0) oparms->inbufsamps = oparms->outbufsamps = p->buffer_frames; /* hardware buffer frames */ if (p->hardware_buffer_frames > 0) oparms->oMaxLag = p->hardware_buffer_frames; /* multicore threads */ if (p->number_of_threads > 1) oparms->numThreads = p->number_of_threads; /* MIDI interop */ if (p->midi_key > 0) oparms->midiKey = p->midi_key; else if (p->midi_key_cps > 0) oparms->midiKeyCps = p->midi_key_cps; else if (p->midi_key_pch > 0) oparms->midiKeyPch = p->midi_key_pch; else if (p->midi_key_oct > 0) oparms->midiKeyOct = p->midi_key_oct; if (p->midi_velocity > 0) oparms->midiVelocity = p->midi_velocity; else if (p->midi_velocity_amp > 0) oparms->midiVelocityAmp = p->midi_velocity_amp; /* CSD line counts */ if (p->csd_line_counts > 0) oparms->useCsdLineCounts = p->csd_line_counts; /* kr override */ if (p->control_rate_override > 0) oparms->kr_override = p->control_rate_override; /* sr override */ if (p->sample_rate_override > 0) oparms->sr_override = p->sample_rate_override; oparms->nchnls_override = p->nchnls_override; oparms->nchnls_i_override = p->nchnls_i_override; oparms->e0dbfs_override = p->e0dbfs_override; if (p->ksmps_override > 0) oparms->ksmps_override = p->ksmps_override; } PUBLIC void csoundGetParams(CSOUND *csound, CSOUND_PARAMS *p){ OPARMS *oparms = csound->oparms; p->debug_mode = oparms->odebug; p->displays = oparms->displays; p->ascii_graphs = oparms->graphsoff; p->postscript_graphs = oparms->postscript; p->use_cscore = oparms->usingcscore; p->ring_bell = oparms->ringbell; p->defer_gen01_load = oparms->gen01defer; p->terminate_on_midi = oparms->termifend; p->no_default_paths = oparms->noDefaultPaths; p->syntax_check_only = oparms->syntaxCheckOnly; p->sample_accurate = oparms->sampleAccurate; p->realtime_mode = oparms->realtime; p->message_level = oparms->msglevel; p->tempo = oparms->cmdTempo; p->buffer_frames = oparms->outbufsamps; p->hardware_buffer_frames = oparms->oMaxLag; p->number_of_threads = oparms->numThreads; p->midi_key = oparms->midiKey; p->midi_key_cps = oparms->midiKeyCps; p->midi_key_pch = oparms->midiKeyPch; p->midi_key_oct = oparms->midiKeyOct; p->midi_velocity = oparms->midiVelocity; p->midi_velocity_amp = oparms->midiVelocityAmp; p->csd_line_counts = oparms->useCsdLineCounts; p->control_rate_override = oparms->kr_override; p->sample_rate_override = oparms->sr_override; p->nchnls_override = oparms->nchnls_override; p->nchnls_i_override = oparms->nchnls_i_override; p->e0dbfs_override = oparms->e0dbfs_override; p->heartbeat = oparms->heartbeat; p->ring_bell = oparms->ringbell; p->daemon = oparms->daemon; p->ksmps_override = oparms->ksmps_override; p->FFT_library = oparms->fft_lib; } PUBLIC void csoundSetOutput(CSOUND *csound, const char *name, const char *type, const char *format) { OPARMS *oparms = csound->oparms; char *typename; /* if already compiled and running, return */ if (csound->engineStatus & CS_STATE_COMP) return; oparms->outfilename = csound->Malloc(csound, strlen(name) + 1); /* will be freed by memRESET */ strcpy(oparms->outfilename, name); /* unsafe -- REVIEW */ if (strcmp(oparms->outfilename, "stdout") == 0) { set_stdout_assign(csound, STDOUTASSIGN_SNDFILE, 1); #if defined(WIN32) csound->Warning(csound, Str("stdout not supported on this platform")); #endif } else set_stdout_assign(csound, STDOUTASSIGN_SNDFILE, 0); oparms->sfwrite = 1; if (type != NULL) { int i=0; while ((typename = file_type_map[i].format) != NULL) { if (!strcmp(type,typename)) break; i++; } if (typename != NULL) { oparms->filetyp = file_type_map[i].type; } } if (format != NULL) { int i=0; while ((typename = sample_format_map[i].longformat) != NULL) { if (!strcmp(format,typename)) break; i++; } if (format != NULL) { set_output_format(oparms, sample_format_map[i].shortformat); } } } PUBLIC void csoundGetOutputFormat(CSOUND *csound, char *type, char *format) { OPARMS *oparms = csound->oparms; int i = 0; const char* fmt = get_output_format(oparms); while (file_type_map[i].type != oparms->filetyp && file_type_map[i].format != NULL) i++; if(file_type_map[i].format != NULL) strcpy(type,file_type_map[i].format); else strcpy(type,""); if(fmt != NULL) strcpy(format, fmt); else strcpy(format,""); } PUBLIC void csoundSetInput(CSOUND *csound, const char *name) { OPARMS *oparms = csound->oparms; /* if already compiled and running, return */ if (csound->engineStatus & CS_STATE_COMP) return; oparms->infilename = csound->Malloc(csound, strlen(name)); /* will be freed by memRESET */ strcpy(oparms->infilename, name); if (strcmp(oparms->infilename, "stdin") == 0) { set_stdin_assign(csound, STDINASSIGN_SNDFILE, 1); #if defined(WIN32) csound->Warning(csound, Str("stdin not supported on this platform")); #endif } else set_stdin_assign(csound, STDINASSIGN_SNDFILE, 0); oparms->sfread = 1; } PUBLIC void csoundSetMIDIInput(CSOUND *csound, const char *name) { OPARMS *oparms = csound->oparms; /* if already compiled and running, return */ if (csound->engineStatus & CS_STATE_COMP) return; oparms->Midiname = csound->Malloc(csound, strlen(name)); /* will be freed by memRESET */ strcpy(oparms->Midiname, name); if (!strcmp(oparms->Midiname, "stdin")) { set_stdin_assign(csound, STDINASSIGN_MIDIDEV, 1); #if defined(WIN32) csound->Warning(csound, Str("stdin not supported on this platform")); #endif } else set_stdin_assign(csound, STDINASSIGN_MIDIDEV, 0); oparms->Midiin = 1; } PUBLIC void csoundSetMIDIFileInput(CSOUND *csound, const char *name) { OPARMS *oparms = csound->oparms; /* if already compiled and running, return */ if (csound->engineStatus & CS_STATE_COMP) return; oparms->FMidiname = csound->Malloc(csound, strlen(name)); /* will be freed by memRESET */ strcpy(oparms->FMidiname, name); if (!strcmp(oparms->FMidiname, "stdin")) { set_stdin_assign(csound, STDINASSIGN_MIDIFILE, 1); #if defined(WIN32) csound->Warning(csound, Str("stdin not supported on this platform")); #endif } else set_stdin_assign(csound, STDINASSIGN_MIDIFILE, 0); oparms->FMidiin = 1; } PUBLIC void csoundSetMIDIFileOutput(CSOUND *csound, const char *name) { OPARMS *oparms = csound->oparms; /* if already compiled and running, return */ if (csound->engineStatus & CS_STATE_COMP) return; oparms->FMidioutname = csound->Malloc(csound, strlen(name)); /* will be freed by memRESET */ strcpy(oparms->FMidioutname, name); } PUBLIC void csoundSetMIDIOutput(CSOUND *csound, const char *name) { OPARMS *oparms = csound->oparms; /* if already compiled and running, return */ if (csound->engineStatus & CS_STATE_COMP) return; oparms->Midioutname = csound->Malloc(csound, strlen(name)); /* will be freed by memRESET */ strcpy(oparms->Midioutname, name); } static void list_audio_devices(CSOUND *csound, int output){ int i,n = csoundGetAudioDevList(csound,NULL, output); CS_AUDIODEVICE *devs = (CS_AUDIODEVICE *) csound->Malloc(csound, n*sizeof(CS_AUDIODEVICE)); if (output) csound->MessageS(csound,CSOUNDMSG_STDOUT, Str("%d audio output devices \n"), n); else csound->MessageS(csound, CSOUNDMSG_STDOUT, Str("%d audio input devices \n"), n); csoundGetAudioDevList(csound,devs,output); for (i=0; i < n; i++) csound->Message(csound, " %d: %s (%s)\n", i, devs[i].device_id, devs[i].device_name); csound->Free(csound, devs); } static void list_midi_devices(CSOUND *csound, int output){ int i,n = csoundGetMIDIDevList(csound,NULL, output); CS_MIDIDEVICE *devs = (CS_MIDIDEVICE *) csound->Malloc(csound, n*sizeof(CS_MIDIDEVICE)); if (output) csound->MessageS(csound, CSOUNDMSG_STDOUT, Str("%d MIDI output devices \n"), n); else csound->MessageS(csound, CSOUNDMSG_STDOUT, Str("%d MIDI input devices \n"), n); csoundGetMIDIDevList(csound,devs,output); for (i=0; i < n; i++) csound->Message(csound, " %d: %s (%s)\n", i, devs[i].device_id, devs[i].device_name); csound->Free(csound, devs); } csound-6.10.0/Top/cscore_internal.c000066400000000000000000000033471321653344700171700ustar00rootroot00000000000000/* cscore_internal.c: Copyright (C) 1991 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "cscore.h" /* CSCORE_DEFAULT.C */ void cscore_(CSOUND *cs) /* callable from Csound or standalone cscore */ /* csound -C will run Csound scores as normal */ { EVLIST *a; while ((a = cscoreListGetSection(cs)) != NULL && a->nevents > 0) { /* read each sect from score */ a = cscoreListAppendStringEvent(cs, a,"s"); /* re-append the s statement */ cscoreListPlay(cs, a); /* play this section */ cscoreListFreeEvents(cs, a); /* reclaim the space */ } if (a) cscoreListFreeEvents(cs, a); /* reclaim space from lget() */ a = cscoreListCreate(cs, 1); a = cscoreListAppendStringEvent(cs, a,"e"); cscoreListPlay(cs, a); /* end-of-score for summaries */ cscoreListFreeEvents(cs, a); return; } csound-6.10.0/Top/cscorfns.c000066400000000000000000000603231321653344700156330ustar00rootroot00000000000000/* cscorfns.c: Copyright (C) 1991 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" /* CSCORFNS.C */ #include "cscore.h" #include "corfile.h" #define TYP_FREE 0 #define TYP_EVENT 1 #define TYP_EVLIST 2 #define TYP_SPACE 3 #define NSLOTS 100 /* default slots in cscoreListCreate list */ #define MAXALLOC 32768L extern int lplay(CSOUND *, EVLIST *); typedef struct space { CSHDR h; struct space *nxtspace; } SPACE; /* RWD: moved from below for use in reset */ typedef struct { FILE *iscfp; EVENT *next; MYFLT until; int wasend, warped, atEOF; } INFILE; static INFILE *infiles = NULL; /* array of infile status blks */ /* next two from cscoreDefineEvent() really */ static EVENT *evtmp = NULL; static EVTBLK *evtmpblk; static SPACE spaceanchor = { { NULL, NULL, TYP_SPACE, 0 }, NULL }; static CSHDR *nxtfree = NULL; /* fast pointer to yet unused free space */ static EVENT *nxtevt = NULL; /* to hold nxt infil event, PMAX pfields */ static EVTBLK *nxtevtblk; /* cs.h EVTBLK subset of EVENT nxtevt */ static int warpout = 0; static MYFLT curuntil; /* initialised to zero by cscoreFileOpen */ static int wasend; /* ditto */ static int atEOF; /* zero when file opened; stays one once rdscor returns 0 */ void cscoreRESET(CSOUND *csound) { nxtfree = NULL; nxtevt = NULL; nxtevtblk = NULL; infiles = NULL; /* FIXME: leak? (any others here?) */ csound->warped = warpout = 0; evtmp = NULL; evtmpblk = NULL; if (spaceanchor.nxtspace != NULL) { SPACE *p = spaceanchor.nxtspace; SPACE *n; do { n = p->nxtspace; csound->Free(csound, p); p = n; } while (p != NULL); } spaceanchor.nxtspace = NULL; spaceanchor.h.prvblk = NULL; spaceanchor.h.nxtblk = NULL; spaceanchor.h.type = TYP_SPACE; spaceanchor.h.size = 0; return; } static SPACE *morespace(CSOUND *csound) { /* alloc large amount of memory, keep in a */ SPACE *space, *prvspace; /* chain. Put SPACE blk at top & init rem as */ CSHDR *free; /* a FREE blk */ prvspace = &spaceanchor; while ((space = prvspace->nxtspace) != NULL) prvspace = space; space = (SPACE *) csound->Malloc(csound, (long) MAXALLOC); prvspace->nxtspace = space; space->nxtspace = NULL; space->h.prvblk = NULL; space->h.nxtblk = (CSHDR *) ((char *) space + sizeof(SPACE)); space->h.type = TYP_SPACE; space->h.size = sizeof(SPACE); free = space->h.nxtblk; free->prvblk = (CSHDR *) space; /* init rem as a TYP_FREE blk */ free->nxtblk = NULL; free->type = TYP_FREE; free->size = MAXALLOC - sizeof(SPACE); return(space); } /* search space chains for min size free blk */ /* else alloc new space blk & reset fast free */ static CSHDR *getfree(CSOUND *csound, int minfreesiz) { SPACE *curspace; CSHDR *blkp; curspace = &spaceanchor; while ((curspace = curspace->nxtspace) != NULL) { blkp = curspace->h.nxtblk; do { if (blkp->type == TYP_FREE && blkp->size >= minfreesiz) return(blkp); } while ((blkp = blkp->nxtblk) != NULL); } curspace = morespace(csound); /* else alloc more space, and */ nxtfree = curspace->h.nxtblk; /* reset the fast free pointer */ return(nxtfree); } /* return a TYP_EVENT or TYP_EVLIST to free space */ /* consolidate with any prev or follow free space */ static void csfree(CSHDR *bp) { CSHDR *prvp, *nxtp; if ((prvp = bp->prvblk) != NULL && prvp->type == TYP_FREE) { if ((nxtp = bp->nxtblk) != NULL && nxtp->type == TYP_FREE) { if ((prvp->nxtblk = nxtp->nxtblk) != NULL) nxtp->nxtblk->prvblk = prvp; prvp->size += bp->size + nxtp->size; } else { if ((prvp->nxtblk = bp->nxtblk) != NULL) bp->nxtblk->prvblk = prvp; prvp->size += bp->size; } } else { if ((nxtp = bp->nxtblk) != NULL && nxtp->type == TYP_FREE) { if ((bp->nxtblk = nxtp->nxtblk) != NULL) nxtp->nxtblk->prvblk = bp; bp->size += nxtp->size; } bp->type = TYP_FREE; } } /* create an array of event pointer slots */ PUBLIC EVLIST * cscoreListCreate(CSOUND *csound, int nslots) { CSHDR *newblk, *newfree; EVLIST *a; int needsiz = sizeof(EVLIST) + nslots * sizeof(EVENT *); int minfreesiz = needsiz + sizeof(CSHDR); if (UNLIKELY(minfreesiz > MAXALLOC)) { csound->Message(csound, Str("Not enough memory\n")); exit(1); } if (nxtfree != NULL && nxtfree->size >= minfreesiz) newblk = nxtfree; else newblk = getfree(csound, minfreesiz); newfree = (CSHDR *) ((char *)newblk + needsiz); newfree->prvblk = newblk; newfree->nxtblk = newblk->nxtblk; newfree->type = TYP_FREE; newfree->size = newblk->size - needsiz; newblk->nxtblk = newfree; newblk->type = TYP_EVLIST; newblk->size = needsiz; if (newblk == nxtfree) nxtfree = newfree; a = (EVLIST *) newblk; a->nslots = nslots; a->nevents= 0; return(a); } /* creat a new event space */ PUBLIC EVENT * cscoreCreateEvent(CSOUND *csound, int pcnt) { CSHDR *newblk, *newfree; EVENT *e; int needsiz = sizeof(EVENT) + pcnt * sizeof(MYFLT); int minfreesiz = needsiz + sizeof(CSHDR); if (UNLIKELY(minfreesiz > MAXALLOC)) { csound->Message(csound, Str("Not enough memory\n")); exit(1); } if (nxtfree != NULL && nxtfree->size >= minfreesiz) newblk = nxtfree; else newblk = getfree(csound, minfreesiz); newfree = (CSHDR *) ((char *)newblk + needsiz); newfree->prvblk = newblk; newfree->nxtblk = newblk->nxtblk; newfree->type = TYP_FREE; newfree->size = newblk->size - needsiz; newblk->nxtblk = newfree; newblk->type = TYP_EVENT; newblk->size = needsiz; if (newblk == nxtfree) nxtfree = newfree; e = (EVENT *) newblk; e->pcnt = pcnt; return(e); } /* make a new copy of an event */ PUBLIC EVENT * cscoreCopyEvent(CSOUND *csound, EVENT *e) { EVENT *f; int n; MYFLT *p, *q; n = e->pcnt; f = cscoreCreateEvent(csound, n); f->op = e->op; f->strarg = e->strarg; /* f->pcnt was set by cscoreCreateEvent */ /* previous method of copying these was dangerous! - akozar */ f->p2orig = e->p2orig; f->p3orig = e->p3orig; p = &e->p[0]; q = &f->p[0]; n += 1; /* p[] is one larger than pcnt b/c p[0] unused */ while (n--) *q++ = *p++; return(f); } /* RWD: cannot addd init arg as this is a std public func */ /* Can only do reentry by moving statics outside: fortunately, */ /* names are unique */ /* define an event from string arg */ PUBLIC EVENT * cscoreDefineEvent(CSOUND *csound, char *s) { MYFLT *p, *q; if (evtmp == NULL) { evtmp = cscoreCreateEvent(csound, PMAX); evtmpblk = (EVTBLK *) &evtmp->strarg; } while (*s == ' ') s++; evtmp->op = *s++; /* read opcode */ while (*s == ' ') s++; p = &evtmp->p[1]; q = &evtmp->p[PMAX]; #ifdef USE_DOUBLE while (CS_SSCANF(s,"%lf",p++) > 0) /* read pfields */ #else while (CS_SSCANF(s,"%f",p++) > 0) /* read pfields */ #endif { while ((*s >= '0' && *s <= '9') || *s == '.' || *s == '-') s++; while (*s == ' ') s++; if (UNLIKELY(p > q && *s != '\0')) { /* too many ? */ p++; csound->Message(csound, Str("PMAX exceeded, string event truncated.\n")); break; } } evtmp->pcnt = p - &evtmp->p[1] - 1; /* set count of params recvd */ evtmp->p2orig = evtmp->p[2]; evtmp->p3orig = evtmp->p[3]; return (cscoreCopyEvent(csound, evtmp)); /* copy event to a new space */ } /* get nxt event from input score buf */ /* and refill the buf */ PUBLIC EVENT * cscoreGetEvent(CSOUND *csound) { EVENT *e; if (!atEOF && nxtevt->op != '\0') e = cscoreCopyEvent(csound, nxtevt); else e = NULL; if (!(rdscor(csound, nxtevtblk))) { nxtevt->op = '\0'; atEOF = 1; } return(e); } /* put an event to cscore outfile */ PUBLIC void cscorePutEvent(CSOUND *csound, EVENT *e) { int pcnt; MYFLT *q; int c = e->op; if (c == 's') warpout = 0; /* new section: init to non-warped */ putc(c, csound->oscfp); q = &e->p[1]; if ((pcnt = e->pcnt)) { if (pcnt--) fprintf(csound->oscfp," %g",*q++); //else goto termin; /* cannot happen */ if (pcnt--) { if (warpout) fprintf(csound->oscfp," %g", e->p2orig); fprintf(csound->oscfp," %g",*q++); } else goto termin; if (pcnt--) { if (warpout) fprintf(csound->oscfp," %g", e->p3orig); fprintf(csound->oscfp," %g",*q++); } else goto termin; while (pcnt--) fprintf(csound->oscfp," %g",*q++); } termin: putc((int)'\n', csound->oscfp); if (c == 'w') warpout = 1; /* was warp statement: sect now warped */ } PUBLIC void cscorePutString(CSOUND *csound, char *s) { fprintf(csound->oscfp,"%s\n", s); if (*s == 's') warpout = 0; else if (*s == 'w') warpout = 1; } /* expand an event list by NSLOTS more slots */ /* copy the previous list, free up the old */ static EVLIST * lexpand(CSOUND *csound, EVLIST *a) { EVLIST *b; EVENT **p, **q; int n; b = cscoreListCreate(csound, a->nslots + NSLOTS); b->nevents = n = a->nevents; p = &a->e[1]; q = &b->e[1]; while (n--) *q++ = *p++; csfree((CSHDR *) a); return(b); } /* append an event to a list */ PUBLIC EVLIST * cscoreListAppendEvent(CSOUND *csound, EVLIST *a, EVENT *e) { int n; if ((n = a->nevents) == a->nslots) a = lexpand(csound, a); a->e[n+1] = e; a->nevents++; return(a); } /* append a string event to a list */ PUBLIC EVLIST * cscoreListAppendStringEvent(CSOUND *csound, EVLIST *a, char *s) { EVENT *e = cscoreDefineEvent(csound, s); return(cscoreListAppendEvent(csound,a,e)); } /* get section events from the scorefile */ PUBLIC EVLIST * cscoreListGetSection(CSOUND *csound) { EVLIST *a; EVENT *e, **p; int nevents = 0; a = cscoreListCreate(csound, NSLOTS); p = &a->e[1]; if (UNLIKELY(csound->scstr == NULL || csound->scstr->body[0] == '\0')) return a; while ((e = cscoreGetEvent(csound)) != NULL) { if (e->op == 's' || e->op == 'e') break; if (nevents == a->nslots) { a->nevents = nevents; a = lexpand(csound, a); p = &a->e[nevents+1]; } *p++ = e; nevents++; } a->nevents = nevents; return(a); } /* get section events from the scorefile */ PUBLIC EVLIST * cscoreListGetUntil(CSOUND *csound, MYFLT beatno) { EVLIST *a; EVENT *e, **p; int nevents = 0; char op; a = cscoreListCreate(csound, NSLOTS); p = &a->e[1]; while ((op = nxtevt->op) == 't' || op == 'w' || op == 's' || op == 'e' || (op != '\0' && nxtevt->p2orig < beatno)) { e = cscoreGetEvent(csound); if (e->op == 's') { wasend = 1; break; } if (e->op == 'e') break; if (nevents == a->nslots) { a->nevents = nevents; a = lexpand(csound,a); p = &a->e[nevents+1]; } *p++ = e; nevents++; } a->nevents = nevents; return(a); } /* get section events from the scorefile */ PUBLIC EVLIST * cscoreListGetNext(CSOUND *csound, MYFLT nbeats) { if (wasend) { wasend = 0; curuntil = nbeats; } else curuntil += nbeats; return(cscoreListGetUntil(csound,curuntil)); } /* put listed events to cscore output */ PUBLIC void cscoreListPut(CSOUND *csound, EVLIST *a) { EVENT **p; int n; n = a->nevents; p = &a->e[1]; while (n--) cscorePutEvent(csound, *p++); } PUBLIC int cscoreListPlay(CSOUND *csound, EVLIST *a) { return lplay(csound, a); } PUBLIC EVLIST * cscoreListCopy(CSOUND *csound, EVLIST *a) { EVLIST *b; EVENT **p, **q; int n = a->nevents; b = cscoreListCreate(csound, n); b->nevents = n; p = &a->e[1]; q = &b->e[1]; while (n--) *q++ = *p++; return(b); } PUBLIC EVLIST * cscoreListCopyEvents(CSOUND *csound, EVLIST *a) { EVLIST *b; EVENT **p, **q; int n = a->nevents; b = cscoreListCreate(csound, n); b->nevents = n; p = &a->e[1]; q = &b->e[1]; while (n--) *q++ = cscoreCopyEvent(csound, *p++); return(b); } PUBLIC EVLIST * cscoreListAppendList(CSOUND *csound, EVLIST *a, EVLIST *b) { EVENT **p, **q; int i, j; i = a->nevents; j = b->nevents; if (i + j >= a->nslots) { EVLIST *c; int n = i; c = cscoreListCreate(csound, i+j); p = &a->e[1]; q = &c->e[1]; while (n--) *q++ = *p++; csfree((CSHDR *) a); a = c; } a->nevents = i+j; p = &a->e[i+1]; q = &b->e[1]; while (j--) *p++ = *q++; return(a); } PUBLIC EVLIST * cscoreListConcatenate(CSOUND *csound, EVLIST *a, EVLIST *b) { return cscoreListAppendList(csound, a, b); } /* put evlist pointers into chronological order */ PUBLIC void cscoreListSort(CSOUND *csound, EVLIST *a) { EVENT **p, **q; EVENT *e, *f; int n, gap, i, j; n = a->nevents; e = a->e[n]; if (e->op == 's' || e->op == 'e') --n; for (gap = n/2; gap > 0; gap /=2) for (i = gap; i < n; i++) for (j = i-gap; j >= 0; j -= gap) { p = &a->e[j+1]; e = *p; q = &a->e[j+1+gap]; f = *q; if (e->op == 'w') break; if (e->p[2] < f->p[2]) break; if (e->p[2] == f->p[2]) { if (e->op == f->op) { if (e->op == 'f') break; if (e->p[1] < f->p[1]) break; if (e->p[1] == f->p[1]) if (e->p[3] <= f->p[3]) break; } else if (e->op < f->op) break; } *p = f; *q = e; } } PUBLIC EVLIST * cscoreListExtractInstruments(CSOUND *csound, EVLIST *a, char *s) /* list extract by instr numbers */ { int x[5], xcnt; int xn, *xp, insno, n; EVENT **p, **q, *e; EVLIST *b, *c; xcnt = sscanf(s,"%d%d%d%d%d",&x[0],&x[1],&x[2],&x[3],&x[4]); n = a->nevents; b = cscoreListCreate(csound, n); p = &a->e[1]; q = &b->e[1]; while ((n--) && (e = *p++) != NULL) { if (e->op != 'i') *q++ = e; else { insno = (int)e->p[1]; xn = xcnt; xp = x; while (xn--) if (*xp++ == insno) { *q++ = e; break; } } } c = cscoreListCopy(csound,b); csfree((CSHDR *) b); return(c); } PUBLIC EVLIST * cscoreListExtractTime(CSOUND *csound, EVLIST *a, MYFLT from, MYFLT to) /* list extract by time */ { EVENT **p, **q, *e; EVLIST *b, *c; MYFLT maxp3; int n; n = a->nevents; b = cscoreListCreate(csound,n); p = &a->e[1]; q = &b->e[1]; maxp3 = to - from; while ((n--) && (e = *p++) != NULL) switch (e->op) { case 'f': if (e->p[2] < to) { *q++ = e = cscoreCopyEvent(csound,e); b->nevents++; if (e->p[2] <= from) e->p[2] = FL(0.0); else e->p[2] -= from; } break; case 'i': if (e->p[2] < from) { if (e->p[2] + e->p[3] > from) { *q++ = e = cscoreCopyEvent(csound,e); b->nevents++; e->p[3] -= from - e->p[2]; e->p[2] = FL(0.0); if (e->p[3] > maxp3) e->p[3] = maxp3; } } else if ((e->p[2] >= from) && (e->p[2] < to)) { *q++ = e = cscoreCopyEvent(csound, e); b->nevents++; if (e->p[2] + e->p[3] > to) e->p[3] = to - e->p[2]; e->p[2] -= from; } break; default: *q++ = cscoreCopyEvent(csound,e); b->nevents++; break; } c = cscoreListCopy(csound,b); csfree((CSHDR *) b); return(c); } /* look for f statements with non-0 p[2] */ static void fp2chk(CSOUND *csound, EVLIST *a, char *s) { EVENT *e, **ep = &a->e[1]; int n = a->nevents, count = 0; while (n--) if ((e = *ep++) && e->op == 'f' && e->p[2] != 0.) count++; if (count) csound->Message(csound, Str("%s found %d f event%s with non-zero p2\n"), s, count, count==1 ? "" : Str("s")); } /* separate f events from evlist */ PUBLIC EVLIST * cscoreListSeparateF(CSOUND *csound, EVLIST *a) { EVLIST *b, *c; EVENT **p, **q, **r; int n; n = a->nevents; b = cscoreListCreate(csound, n); p = q = &a->e[1]; r = &b->e[1]; while (n--) { if ((*p)->op == 'f') *r++ = *p++; else *q++ = *p++; } a->nevents = q - &a->e[1]; b->nevents = r - &b->e[1]; c = cscoreListCopy(csound,b); csfree((CSHDR *) b); fp2chk(csound, c, "cscoreListSeparateF"); return(c); } /* separate t,w,f events from evlist */ PUBLIC EVLIST * cscoreListSeparateTWF(CSOUND *csound, EVLIST *a) { EVLIST *b, *c; EVENT **p, **q, **r; int n, op; n = a->nevents; b = cscoreListCreate(csound,n); p = q = &a->e[1]; r = &b->e[1]; while (n--) { if ((op = (*p)->op) == 't' || op == 'w' || op == 'f') *r++ = *p++; else *q++ = *p++; } a->nevents = q - &a->e[1]; b->nevents = r - &b->e[1]; c = cscoreListCopy(csound,b); csfree((CSHDR *) b); fp2chk(csound, c, "cscoreListSeparateTWF"); return(c); } /* give back event space */ PUBLIC void cscoreFreeEvent(CSOUND *csound, EVENT *e) { csfree((CSHDR *) e); } /* give back list space */ PUBLIC void cscoreListFree(CSOUND *csound, EVLIST *a) { csfree((CSHDR *) a); } /* give back list and its event spaces */ PUBLIC void cscoreListFreeEvents(CSOUND *csound, EVLIST *a) { EVENT **p = &a->e[1]; int n = a->nevents; while (n--) csfree((CSHDR *) *p++); csfree((CSHDR *) a); } #define MAXOPEN 5 static void savinfdata( /* store input file data */ CSOUND *csound, FILE *fp, EVENT *next, MYFLT until, int wasend, int warp, int eof) { INFILE *infp; int n; if ((infp = infiles) == NULL) { infp = infiles = (INFILE *) csound->Calloc(csound, MAXOPEN * sizeof(INFILE)); goto save; } for (n = MAXOPEN; n--; infp++) if (infp->iscfp == fp) goto save; for (infp = infiles, n = MAXOPEN; n--; infp++) if (infp->iscfp == NULL) goto save; csound->ErrorMsg(csound, Str("cscore: too many input files open")); exit(0); /* FIXME: should not call exit */ save: infp->iscfp = fp; infp->next = next; infp->until = until; infp->wasend = wasend; infp->warped = warp; infp->atEOF = eof; } /* make fp the cur scfp & retreive other data */ /* set nxtevtblk to subset cs.h EVTBLK struct */ /* if nxtevt buffer is empty, read one event */ static void makecurrent(CSOUND *csound, FILE *fp) { INFILE *infp; int n; if ((infp = infiles) != NULL) for (n = MAXOPEN; n--; infp++) if (infp->iscfp == fp) { csound->scfp = fp; nxtevt = infp->next; nxtevtblk = (EVTBLK *) &nxtevt->strarg; curuntil = infp->until; wasend = infp->wasend; atEOF = infp->atEOF; csound->warped = infp->warped; if (nxtevt->op == '\0') if (csound->scstr == NULL || csound->scstr->body[0] == '\0' || !(rdscor(csound, nxtevtblk))) { nxtevt->op = '\0'; atEOF = 1; } return; } csound->ErrorMsg(csound, Str("cscore: tried to set an unknown file pointer" " as the current file")); exit(0); /* FIXME: should not call exit */ } /* verify initial scfp, init other data */ /* record & make all this current */ PUBLIC int csoundInitializeCscore(CSOUND *csound, FILE* insco, FILE* outsco) { EVENT *next; if (insco != NULL) { CORFIL *inf = corfile_create_w(csound); int c; while ((c=getc(insco))!=EOF) corfile_putc(csound, c, inf); corfile_rewind(inf); csound->scstr = inf; } if (outsco == NULL) { csound->ErrorMsg(csound, Str("csoundInitializeCscore: no output score given.")); return CSOUND_INITIALIZATION; } csound->scfp = insco; csound->oscfp = outsco; next = cscoreCreateEvent(csound, PMAX); /* creat EVENT blk receiving buf */ next->op = '\0'; savinfdata(csound, csound->scfp, next, FL(0.0), 1, 0, 0);/* curuntil 0, wasend, non-warp, not eof */ makecurrent(csound, csound->scfp); /* make all this current */ return CSOUND_SUCCESS; } /* open new cscore input file, init data */ /* & save; no rdscor until made current */ PUBLIC FILE *cscoreFileOpen(CSOUND *csound, char *name) { FILE *fp; EVENT *next; char *pathname; /* keeping fopen() because the FILE* is returned to the user control program and who knows what they will do with it ... */ pathname = csoundFindInputFile(csound, name, "INCDIR"); if (pathname == NULL || (fp = fopen(pathname, "r")) == NULL) { csound->ErrorMsg(csound, Str("cscoreFileOpen: error opening %s"), name); exit(0); /* FIXME: should not call exit */ } csoundNotifyFileOpened(csound, pathname, CSFTYPE_SCORE, 0, 0); csound->Free(csound, pathname); /* alloc a receiving evtblk */ next = cscoreCreateEvent(csound,PMAX); /* FIXME: need next->op = '\0' ?? */ /* save all, wasend, non-warped, not eof */ savinfdata(csound, fp, next, FL(0.0), 1, 0, 0); return(fp); } PUBLIC void cscoreFileClose(CSOUND *csound, FILE *fp) { INFILE *infp; int n; if (fp == NULL) { csound->Message(csound, Str("cscoreFileClose: NULL file pointer\n")); return; } if ((infp = infiles) != NULL) for (n = MAXOPEN; n--; infp++) if (infp->iscfp == fp) { infp->iscfp = NULL; csound->Free(csound, (char *)infp->next); fclose(fp); if (csound->scfp == fp) csound->scfp = NULL; return; } csound->Message(csound, Str("cscoreFileClose: fp not recorded\n")); } PUBLIC FILE *cscoreFileGetCurrent(CSOUND *csound) { if (csound->scfp == NULL) { csound->ErrorMsg(csound, Str("cscoreFileGetCurrent: no fp current")); exit(0); /* FIXME: should not call exit */ } return(csound->scfp); } /* save the current infil states */ /* make fp & its states current */ PUBLIC void cscoreFileSetCurrent(CSOUND *csound, FILE *fp) { if (fp != NULL) { CORFIL *inf = corfile_create_w(csound); int c; fseek(fp, 0, SEEK_SET); while ((c=getc(fp))!=EOF) corfile_putc(csound, c, inf); corfile_rewind(inf); corfile_rm(csound, &csound->scstr); csound->scstr = inf; nxtevt->op = '\0'; atEOF = 0; } if (csound->scfp != NULL) savinfdata(csound, csound->scfp, nxtevt, curuntil, wasend, csound->warped, atEOF); makecurrent(csound, fp); } /* count entries in event list */ PUBLIC int cscoreListCount(CSOUND *csound, EVLIST *a) { EVENT **p; int n, nrem; n = 0; nrem = a->nslots; p = &a->e[1]; while ((nrem--) && *p++ != NULL) n++; return(n); } csound-6.10.0/Top/csdebug.c000066400000000000000000000305001321653344700154210ustar00rootroot00000000000000/* csdebug.c: Copyright (C) 2013 Andres Cabrera This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "csdebug.h" debug_instr_t *csoundDebugGetCurrentInstrInstance(CSOUND *csound); debug_opcode_t *csoundDebugGetCurrentOpcodeList(CSOUND *csound); void csoundDebugFreeOpcodeList(CSOUND *csound, debug_opcode_t *opcode_list); void csoundDebuggerBreakpointReached(CSOUND *csound) { csdebug_data_t *data = (csdebug_data_t *) csound->csdebug_data; debug_bkpt_info_t bkpt_info; bkpt_info.breakpointInstr = csoundDebugGetCurrentInstrInstance(csound); bkpt_info.instrListHead = csoundDebugGetInstrInstances(csound); bkpt_info.currentOpcode = csoundDebugGetCurrentOpcodeList(csound); bkpt_info.instrVarList = csoundDebugGetVariables(csound, bkpt_info.breakpointInstr); if (data->bkpt_cb) { data->bkpt_cb(csound, &bkpt_info, data->cb_data); } else { csoundMessage(csound, Str("Breakpoint callback not set. Breakpoint Reached.")); } // TODO: These free operations could be moved to a low priority context csoundDebugFreeInstrInstances(csound, bkpt_info.breakpointInstr); csoundDebugFreeInstrInstances(csound, bkpt_info.instrListHead); if (bkpt_info.currentOpcode) { csoundDebugFreeOpcodeList(csound, bkpt_info.currentOpcode); } csoundDebugFreeVariables(csound, bkpt_info.instrVarList); } PUBLIC void csoundDebuggerInit(CSOUND *csound) { csdebug_data_t *data = (csdebug_data_t *) csound->Malloc(csound, sizeof(csdebug_data_t)); data->bkpt_anchor = (bkpt_node_t *) csound->Malloc(csound, sizeof(bkpt_node_t)); data->bkpt_anchor->line = -1; data->bkpt_anchor->next = NULL; data->debug_instr_ptr = NULL; data->debug_opcode_ptr = NULL; data->bkpt_cb = NULL; data->status = CSDEBUG_STATUS_RUNNING; data->bkpt_buffer = csoundCreateCircularBuffer(csound, 64, sizeof(bkpt_node_t **)); data->cmd_buffer = csoundCreateCircularBuffer(csound, 64, sizeof(debug_command_t)); csound->csdebug_data = data; csound->kperf = kperf_debug; } PUBLIC void csoundDebuggerClean(CSOUND *csound) { csdebug_data_t *data = (csdebug_data_t *) csound->csdebug_data; assert(data); bkpt_node_t *node = data->bkpt_anchor; csoundDestroyCircularBuffer(csound, data->bkpt_buffer); csoundDestroyCircularBuffer(csound, data->cmd_buffer); while (node) { bkpt_node_t *oldnode = node; node = node->next; csound->Free(csound, oldnode); } csound->Free(csound, data); csound->csdebug_data = NULL; csound->kperf = kperf_nodebug; } PUBLIC void csoundDebugStart(CSOUND *csound) { csdebug_data_t *data = (csdebug_data_t *) csound->csdebug_data; data->status = CSDEBUG_STATUS_RUNNING; } PUBLIC void csoundSetBreakpoint(CSOUND *csound, int line, int instr, int skip) { csdebug_data_t *data = (csdebug_data_t *) csound->csdebug_data; if (!data) { csound->Warning(csound, Str("csoundSetBreakpoint: cannot set breakpoint. " "Debugger is not initialised.")); return; } if (line <= 0) { csound->Warning(csound, Str("csoundSetBreakpoint: line > 0 for breakpoint.")); return; } bkpt_node_t *newpoint = (bkpt_node_t *) csound->Malloc(csound, sizeof(bkpt_node_t)); newpoint->line = line; newpoint->instr = instr; newpoint->skip = skip; newpoint->count = skip; newpoint->mode = CSDEBUG_BKPT_LINE; csoundWriteCircularBuffer(csound, data->bkpt_buffer, &newpoint, 1); } PUBLIC void csoundRemoveBreakpoint(CSOUND *csound, int line, int instr) { csdebug_data_t *data = (csdebug_data_t *) csound->csdebug_data; if (!data) { csound->Warning(csound, Str("csoundRemoveBreakpoint: cannot remove breakpoint. " "Debugger is not initialised.")); return; } if (line < 0) { csound->Warning(csound, Str ("Negative line for breakpoint invalid.")); } bkpt_node_t *newpoint = (bkpt_node_t *) csound->Malloc(csound, sizeof(bkpt_node_t)); newpoint->line = line; newpoint->instr = instr; newpoint->mode = CSDEBUG_BKPT_DELETE; csoundWriteCircularBuffer(csound, data->bkpt_buffer, &newpoint, 1); } PUBLIC void csoundSetInstrumentBreakpoint(CSOUND *csound, MYFLT instr, int skip) { csdebug_data_t *data = (csdebug_data_t *) csound->csdebug_data; if (!data) { csound->Warning(csound, Str("csoundRemoveBreakpoint: cannot remove breakpoint. " "Debugger is not initialised.")); return; } assert(data); bkpt_node_t *newpoint = (bkpt_node_t *) csound->Malloc(csound, sizeof(bkpt_node_t)); newpoint->line = -1; newpoint->instr = instr; newpoint->skip = skip; newpoint->count = skip; newpoint->mode = CSDEBUG_BKPT_INSTR; csoundWriteCircularBuffer(csound, data->bkpt_buffer, &newpoint, 1); } PUBLIC void csoundRemoveInstrumentBreakpoint(CSOUND *csound, MYFLT instr) { csdebug_data_t *data = (csdebug_data_t *) csound->csdebug_data; assert(data); bkpt_node_t *newpoint = (bkpt_node_t *) csound->Malloc(csound, sizeof(bkpt_node_t)); newpoint->line = -1; newpoint->instr = instr; newpoint->mode = CSDEBUG_BKPT_DELETE; csoundWriteCircularBuffer(csound, data->bkpt_buffer, &newpoint, 1); } PUBLIC void csoundClearBreakpoints(CSOUND *csound) { csdebug_data_t *data = (csdebug_data_t *) csound->csdebug_data; assert(data); bkpt_node_t *newpoint = (bkpt_node_t *) csound->Malloc(csound, sizeof(bkpt_node_t)); newpoint->line = -1; newpoint->instr = -1; newpoint->mode = CSDEBUG_BKPT_CLEAR_ALL; csoundWriteCircularBuffer(csound, data->bkpt_buffer, &newpoint, 1); } PUBLIC void csoundSetBreakpointCallback(CSOUND *csound, breakpoint_cb_t bkpt_cb, void *userdata) { csdebug_data_t *data = (csdebug_data_t *) csound->csdebug_data; assert(data); data->bkpt_cb = bkpt_cb; data->cb_data = userdata; } PUBLIC void csoundDebugStepOver(CSOUND *csound) { csdebug_data_t *data = (csdebug_data_t *) csound->csdebug_data; assert(data); debug_command_t command = CSDEBUG_CMD_STEPOVER; csoundWriteCircularBuffer(csound, data->cmd_buffer, &command, 1); } PUBLIC void csoundDebugStepInto(CSOUND *csound) { csdebug_data_t *data = (csdebug_data_t *) csound->csdebug_data; assert(data); debug_command_t command = CSDEBUG_CMD_STEPINTO; csoundWriteCircularBuffer(csound, data->cmd_buffer, &command, 1); } PUBLIC void csoundDebugNext(CSOUND *csound) { csdebug_data_t *data = (csdebug_data_t *) csound->csdebug_data; assert(data); debug_command_t command = CSDEBUG_CMD_NEXT; csoundWriteCircularBuffer(csound, data->cmd_buffer, &command, 1); } PUBLIC void csoundDebugContinue(CSOUND *csound) { csdebug_data_t *data = (csdebug_data_t *) csound->csdebug_data; assert(data); debug_command_t command = CSDEBUG_CMD_CONTINUE; csoundWriteCircularBuffer(csound, data->cmd_buffer, &command, 1); } PUBLIC void csoundDebugStop(CSOUND *csound) { csdebug_data_t *data = (csdebug_data_t *) csound->csdebug_data; assert(data); debug_command_t command = CSDEBUG_CMD_STOP; csoundWriteCircularBuffer(csound, data->cmd_buffer, &command, 1); } PUBLIC debug_instr_t *csoundDebugGetInstrInstances(CSOUND *csound) { debug_instr_t *instrhead = NULL; debug_instr_t *debug_instr = NULL; INSDS *insds = csound->actanchor.nxtact; while (insds) { if (!instrhead) { instrhead = csound->Malloc(csound, sizeof(debug_instr_t)); debug_instr = instrhead; } else { debug_instr->next = csound->Malloc(csound, sizeof(debug_instr_t)); debug_instr = debug_instr->next; } debug_instr->lclbas = insds->lclbas; debug_instr->varPoolHead = insds->instr->varPool->head; debug_instr->instrptr = (void *) insds; debug_instr->p1 = insds->p1.value; debug_instr->p2 = insds->p2.value; debug_instr->p3 = insds->p3.value; debug_instr->kcounter = insds->kcounter; debug_instr->next = NULL; insds = insds->nxtact; } return instrhead; } debug_instr_t *csoundDebugGetCurrentInstrInstance(CSOUND *csound) { csdebug_data_t *data = (csdebug_data_t *) csound->csdebug_data; assert(data); if (!data->debug_instr_ptr) { return NULL; } debug_instr_t *debug_instr = csound->Malloc(csound, sizeof(debug_instr_t)); INSDS *insds = (INSDS *)data->debug_instr_ptr; debug_instr->lclbas = insds->lclbas; debug_instr->varPoolHead = insds->instr->varPool->head; debug_instr->instrptr = data->debug_instr_ptr; debug_instr->p1 = insds->p1.value; debug_instr->p2 = insds->p2.value; debug_instr->p3 = insds->p3.value; debug_instr->kcounter = insds->kcounter; debug_instr->next = NULL; OPDS* opstart = (OPDS*) data->debug_instr_ptr; if (opstart->nxtp) { debug_instr->line = opstart->nxtp->optext->t.linenum; } else { debug_instr->line = 0; } return debug_instr; } debug_opcode_t *csoundDebugGetCurrentOpcodeList(CSOUND *csound) { csdebug_data_t *data = (csdebug_data_t *) csound->csdebug_data; assert(data); if (!data->debug_instr_ptr) { return NULL; } OPDS *op = (OPDS *)data->debug_opcode_ptr; if (!op) { return NULL; } debug_opcode_t *opcode_list = csound->Malloc(csound, sizeof(debug_opcode_t)); strncpy(opcode_list->opname, op->optext->t.opcod, 15); opcode_list->opname[15] = '\0'; opcode_list->line = op->optext->t.linenum; return opcode_list; } void csoundDebugFreeOpcodeList(CSOUND *csound, debug_opcode_t *opcode_list) { csound->Free(csound, opcode_list); } PUBLIC void csoundDebugFreeInstrInstances(CSOUND *csound, debug_instr_t *instr) { while (instr) { debug_instr_t *oldinstr = instr; instr = instr->next; csound->Free(csound, oldinstr); } } PUBLIC debug_variable_t *csoundDebugGetVariables(CSOUND *csound, debug_instr_t *instr) { debug_variable_t *head = NULL; debug_variable_t *debug_var = head; CS_VARIABLE * var = instr->varPoolHead; while (var) { void * varmem = NULL; if (!head) { head = csound->Malloc(csound, sizeof(debug_variable_t)); debug_var = head; } else { debug_var->next = csound->Malloc(csound, sizeof(debug_variable_t)); debug_var = debug_var->next; } debug_var->next = NULL; debug_var->name = var->varName; debug_var->typeName = var->varType->varTypeName; if (strcmp(debug_var->typeName, "i") == 0 || strcmp(debug_var->typeName, "k") == 0 || strcmp(debug_var->typeName, "a") == 0 || strcmp(debug_var->typeName, "r") == 0 ) { varmem = instr->lclbas + var->memBlockIndex; } else if (strcmp(debug_var->typeName, "S") == 0) { STRINGDAT *strdata = (STRINGDAT *) (instr->lclbas + var->memBlockIndex); varmem = &strdata->data[0]; } else { csound->Message(csound, "csoundDebugGetVarData() unknown data type.\n"); } debug_var->data = varmem; var = var->next; } return head; } PUBLIC void csoundDebugFreeVariables(CSOUND *csound, debug_variable_t *varHead) { while (varHead) { debug_variable_t *oldvar = varHead; varHead = varHead->next; csound->Free(csound, oldvar); } } csound-6.10.0/Top/csmodule.c000066400000000000000000001030061321653344700156220ustar00rootroot00000000000000/* csmodule.c: Copyright (C) 2005 Istvan Varga based on dl_opcodes.c, Copyright (C) 2002 John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /****************************************************************************** * NEW PLUGIN INTERFACE * * ==================== * * * * Plugin libraries are loaded from the directory defined by the environment * * variable OPCODE6DIR (or the current directory if OPCODE6DIR is unset) by * * csoundPreCompile() while initialising a Csound instance, and are unloaded * * at the end of performance by csoundReset(). * * A library may export any of the following five interface functions, * * however, the presence of csoundModuleCreate() is required for identifying * * the file as a Csound plugin module. * * * * int csoundModuleCreate(CSOUND *csound) (required) * * -------------------------------------- * * * * Pre-initialisation function, called by csoundPreCompile(). * * * * int csoundModuleInit(CSOUND *csound) (optional) * * ------------------------------------ * * * * Called by Csound instances before orchestra translation. One possible use * * of csoundModuleInit() is adding new opcodes with csoundAppendOpcode(). * * * * int csoundModuleDestroy(CSOUND *csound) (optional) * * --------------------------------------- * * * * Destructor function for Csound instance 'csound', called at the end of * * performance, after closing audio output. * * * * const char *csoundModuleErrorCodeToString(int errcode) (optional) * * ------------------------------------------------------ * * * * Converts error codes returned by any of the initialisation or destructor * * functions to a string message. * * * * int csoundModuleInfo(void) (optional) * * -------------------------- * * * * Returns information that can be used to determine if the plugin was built * * for a compatible version of libcsound. The return value may be the sum of * * any of the following two values: * * * * ((CS_APIVERSION << 16) + (CS_APISUBVER << 8)) API version * * (int) sizeof(MYFLT) MYFLT type * * * ******************************************************************************/ #include #include #include #include #include #include "csoundCore.h" #include "csmodule.h" #if defined(__MACH__) #include #if (TARGET_OS_IPHONE == 0) && (TARGET_IPHONE_SIMULATOR == 0) #if defined(MAC_OS_X_VERSION_10_6) && \ (MAC_OS_X_VERSION_MIN_REQUIRED>=MAC_OS_X_VERSION_10_6) #define NEW_MACH_CODE #endif #endif #endif #if !(defined (NACL)) #if defined(LINUX) || defined(NEW_MACH_CODE) #include #elif defined(WIN32) #include #endif #endif #if defined(HAVE_DIRENT_H) # include # if 0 && defined(__MACH__) typedef void* DIR; DIR opendir(const char *); struct dirent *readdir(DIR*); int closedir(DIR*); # endif #endif #if defined(WIN32) && !defined(__CYGWIN__) # include # include #endif extern int allocgen(CSOUND *, char *, int (*)(FGDATA *, FUNC *)); #if defined(INIT_STATIC_MODULES) extern int init_static_modules(CSOUND *); #endif /* module interface function names */ static const char *opcode_init_Name = "csound_opcode_init"; static const char *fgen_init_Name = "csound_fgen_init"; static const char *PreInitFunc_Name = "csoundModuleCreate"; static const char *InitFunc_Name = "csoundModuleInit"; static const char *DestFunc_Name = "csoundModuleDestroy"; static const char *ErrCodeToStr_Name = "csoundModuleErrorCodeToString"; static const char *InfoFunc_Name = "csoundModuleInfo"; /* environment variable storing path to plugin libraries */ static const char *plugindir_envvar = "OPCODE6DIR"; static const char *plugindir64_envvar = "OPCODE6DIR64"; /* default directory to load plugins from if environment variable is not set */ #if !(defined (NACL)) #if !(defined(_CSOUND_RELEASE_) && (defined(LINUX) || defined(__MACH__))) # define ENABLE_OPCODEDIR_WARNINGS 1 # ifdef CS_DEFAULT_PLUGINDIR # undef CS_DEFAULT_PLUGINDIR # endif # define CS_DEFAULT_PLUGINDIR "." #else # define ENABLE_OPCODEDIR_WARNINGS 0 # ifndef CS_DEFAULT_PLUGINDIR # ifndef USE_DOUBLE # define CS_DEFAULT_PLUGINDIR "/usr/local/lib/csound/plugins" # else # define CS_DEFAULT_PLUGINDIR "/usr/local/lib/csound/plugins64" # endif # endif #endif #endif #if (TARGET_OS_IPHONE != 0) && (TARGET_IPHONE_SIMULATOR != 0) # define ENABLE_OPCODEDIR_WARNINGS 0 #endif typedef struct opcodeLibFunc_s { long (*opcode_init)(CSOUND *, OENTRY **); /* list of opcode entries */ NGFENS *(*fgen_init)(CSOUND *); /* list of named GEN routines */ void (*dummy)(void); /* unused */ } opcodeLibFunc_t; typedef struct pluginLibFunc_s { int (*InitFunc)(CSOUND *); /* initialisation routine */ int (*DestFunc)(CSOUND *); /* destructor routine */ const char *(*ErrCodeToStr)(int); /* convert error code to string */ } pluginLibFunc_t; typedef struct csoundModule_s { struct csoundModule_s *nxt; /* pointer to next link in chain */ void *h; /* library handle */ int (*PreInitFunc)(CSOUND *); /* pre-initialisation routine */ /* (always NULL if opcode lib) */ union { pluginLibFunc_t p; /* generic plugin interface */ opcodeLibFunc_t o; /* opcode library interface */ } fn; char name[1]; /* name of the module */ } csoundModule_t; static CS_NOINLINE void print_module_error(CSOUND *csound, const char *fmt, const char *fname, const csoundModule_t *m, int err) { csoundMessageS(csound, CSOUNDMSG_ERROR, Str(fmt), fname); if (m != NULL && m->fn.p.ErrCodeToStr != NULL) csoundMessageS(csound, CSOUNDMSG_ERROR, ": %s\n", Str(m->fn.p.ErrCodeToStr(err))); else csoundMessageS(csound, CSOUNDMSG_ERROR, "\n"); } static int check_plugin_compatibility(CSOUND *csound, const char *fname, int n) { int myfltSize, minorVersion, majorVersion; myfltSize = n & 0xFF; if (UNLIKELY(myfltSize != 0 && myfltSize != (int) sizeof(MYFLT))) { csoundWarning(csound, Str("not loading '%s' (uses incompatible " "floating point type)"), fname); return -1; } if (UNLIKELY(n & (~0xFF))) { minorVersion = (n & 0xFF00) >> 8; majorVersion = (n & (~0xFFFF)) >> 16; if (majorVersion != (int) CS_APIVERSION || (minorVersion > (int) CS_APISUBVER)) { /* NOTE **** REFACTOR *** */ csoundWarning(csound, Str("not loading '%s' (incompatible " "with this version of Csound (%d.%d/%d.%d)"), fname, majorVersion,minorVersion, CS_APIVERSION,CS_APISUBVER); return -1; } } return 0; } /* load a single plugin library, and run csoundModuleCreate() if present */ /* returns zero on success */ static CS_NOINLINE int csoundLoadExternal(CSOUND *csound, const char *libraryPath) { csoundModule_t m; volatile jmp_buf tmpExitJmp; csoundModule_t *mp; char *fname; void *h, *p; int (*infoFunc)(void); int err; /* check for a valid name */ if (UNLIKELY(libraryPath == NULL || libraryPath[0] == '\0')) return CSOUND_ERROR; /* remove leading directory components from name */ fname = (char*) libraryPath + (int) strlen(libraryPath); for ( ; fname[0] != DIRSEP && fname != (char*) libraryPath; fname--) ; if (fname[0] == DIRSEP) fname++; if (UNLIKELY(fname[0] == '\0')) return CSOUND_ERROR; /* load library */ /* #if defined(LINUX) */ //printf("About to open library '%s'\n", libraryPath); /* #endif */ err = csoundOpenLibrary(&h, libraryPath); if (UNLIKELY(err)) { char ERRSTR[256]; #if !(defined(NACL)) && defined(LINUX) snprintf(ERRSTR, 256, Str("could not open library '%s' (%s)"), libraryPath, dlerror()); #else snprintf(ERRSTR, 256, Str("could not open library '%s' (%d)"), libraryPath, err); #endif if (csound->delayederrormessages == NULL) { csound->delayederrormessages = csound->Malloc(csound, strlen(ERRSTR)+1); strcpy(csound->delayederrormessages, ERRSTR); } else { char *new = csound->ReAlloc(csound, csound->delayederrormessages, strlen(csound->delayederrormessages)+strlen(ERRSTR)+11); if (UNLIKELY(new==NULL)) { csound->Free(csound, csound->delayederrormessages); return CSOUND_ERROR; } csound->delayederrormessages = new; strcat(csound->delayederrormessages, "\nWARNING: "); strcat(csound->delayederrormessages, ERRSTR); } return CSOUND_ERROR; } /* check if the library is compatible with this version of Csound */ infoFunc = (int (*)(void)) csoundGetLibrarySymbol(h, InfoFunc_Name); if (infoFunc != NULL) { if (UNLIKELY(check_plugin_compatibility(csound, fname, infoFunc()) != 0)) { csoundCloseLibrary(h); return CSOUND_ERROR; } } /* was this plugin already loaded ? */ for (mp = (csoundModule_t*) csound->csmodule_db; mp != NULL; mp = mp->nxt) { if (UNLIKELY(mp->h == h)) { csoundCloseLibrary(h); return CSOUND_SUCCESS; } } /* find out if it is a Csound plugin */ memset(&m, 0, sizeof(csoundModule_t)); m.h = h; m.PreInitFunc = (int (*)(CSOUND *)) csoundGetLibrarySymbol(h, PreInitFunc_Name); if (m.PreInitFunc != NULL) { /* generic plugin library */ m.fn.p.InitFunc = (int (*)(CSOUND *)) csoundGetLibrarySymbol(h, InitFunc_Name); m.fn.p.DestFunc = (int (*)(CSOUND *)) csoundGetLibrarySymbol(h, DestFunc_Name); m.fn.p.ErrCodeToStr = (const char *(*)(int)) csoundGetLibrarySymbol(h, ErrCodeToStr_Name); } else { /* opcode library */ m.fn.o.opcode_init = (long (*)(CSOUND *, OENTRY **)) csoundGetLibrarySymbol(h, opcode_init_Name); m.fn.o.fgen_init = (NGFENS *(*)(CSOUND *)) csoundGetLibrarySymbol(h, fgen_init_Name); if (UNLIKELY(m.fn.o.opcode_init == NULL && m.fn.o.fgen_init == NULL)) { /* must have csound_opcode_init() or csound_fgen_init() */ csoundCloseLibrary(h); if (UNLIKELY(csound->oparms->msglevel & 0x400)) csound->Warning(csound, Str("'%s' is not a Csound plugin library"), libraryPath); return CSOUND_ERROR; } } /* set up module info structure */ /* (note: space for NUL character is already included in size of struct) */ p = (void*) csound->Malloc(csound, sizeof(csoundModule_t) + (size_t) strlen(fname)); if (UNLIKELY(p == NULL)) { csoundCloseLibrary(h); csound->ErrorMsg(csound, Str("csoundLoadExternal(): memory allocation failure")); return CSOUND_MEMORY; } mp = (csoundModule_t*) p; memcpy(mp, &m, sizeof(csoundModule_t)); strcpy(&(mp->name[0]), fname); /* link into database */ mp->nxt = (csoundModule_t*) csound->csmodule_db; csound->csmodule_db = (void*) mp; /* call csoundModuleCreate() if available */ if (m.PreInitFunc != NULL) { memcpy((void*) &tmpExitJmp, (void*) &csound->exitjmp, sizeof(jmp_buf)); if ((err = setjmp(csound->exitjmp)) != 0) { memcpy((void*) &csound->exitjmp, (void*) &tmpExitJmp, sizeof(jmp_buf)); print_module_error(csound, Str("Error in pre-initialisation function " "of module '%s'"), fname, NULL, 0); return (err == (CSOUND_EXITJMP_SUCCESS + CSOUND_MEMORY) ? CSOUND_MEMORY : CSOUND_INITIALIZATION); } err = m.PreInitFunc(csound); memcpy((void*) &csound->exitjmp, (void*) &tmpExitJmp, sizeof(jmp_buf)); if (UNLIKELY(err != 0)) { print_module_error(csound, Str("Error in pre-initialisation function " "of module '%s'"), fname, &m, err); return CSOUND_INITIALIZATION; } } /* plugin was loaded successfully */ return CSOUND_SUCCESS; } static int csoundCheckOpcodeDeny(CSOUND * csound, const char *fname) { /* Check to see if the fname is on the do-not-load list */ char buff[256]; char *th; char *p, *deny; char *list = getenv("CS_OMIT_LIBS"); /* printf("DEBUG %s(%d): check fname=%s\n", __FILE__, __LINE__, fname); */ /* printf("DEBUG %s(%d): list %s\n", __FILE__, __LINE__, list); */ if (list==NULL) return 0; strncpy(buff, fname, 255); buff[255]='\0'; strrchr(buff, '.')[0] = '\0'; /* Remove .so etc */ p = cs_strdup(csound, list); deny = cs_strtok_r(p, ",", &th); /* printf("DEBUG %s(%d): check buff=%s\n", __FILE__, __LINE__, deny); */ while (deny) { /* printf("DEBUG %s(%d): deny=%s\n", __FILE__, __LINE__, deny); */ if (strcmp(deny, buff)==0) { csound->Free(csound, p); /* printf("DEBUG %s(%d): found\n", __FILE__, __LINE__); */ return 1; } deny = cs_strtok_r(NULL, ",", &th); } csound->Free(csound, p); /* printf("DEBUG %s(%d): not found\n", __FILE__, __LINE__); */ return 0; } /** * Load plugin libraries for Csound instance 'csound', and call * pre-initialisation functions. * Return value is CSOUND_SUCCESS if there was no error, CSOUND_ERROR if * some modules could not be loaded or initialised, and CSOUND_MEMORY * if a memory allocation failure has occured. */ int csoundLoadModules(CSOUND *csound) { #if (defined(HAVE_DIRENT_H) && (TARGET_OS_IPHONE == 0)) DIR *dir; struct dirent *f; const char *dname, *fname; char buf[1024]; int i, n, len, err = CSOUND_SUCCESS; if (UNLIKELY(csound->csmodule_db != NULL)) return CSOUND_ERROR; /* open plugin directory */ dname = csoundGetEnv(csound, (sizeof(MYFLT) == sizeof(float) ? plugindir_envvar : plugindir64_envvar)); if (dname == NULL) { #if ENABLE_OPCODEDIR_WARNINGS csound->opcodedirWasOK = 0; # ifdef USE_DOUBLE dname = csoundGetEnv(csound, plugindir_envvar); if (dname == NULL) # endif #endif #ifdef CS_DEFAULT_PLUGINDIR dname = CS_DEFAULT_PLUGINDIR; #else dname = ""; #endif } dir = opendir(dname); if (UNLIKELY(dir == (DIR*) NULL)) { //if (dname != NULL) /* cannot be other */ csound->Warning(csound, Str("Error opening plugin directory '%s': %s"), dname, strerror(errno)); //else //csound->Warning(csound, Str("Error opening plugin directory: %s"), // strerror(errno)); return CSOUND_SUCCESS; } /* load database for deferred plugin loading */ /* n = csoundLoadOpcodeDB(csound, dname); */ /* if (n != 0) */ /* return n; */ /* scan all files in directory */ while ((f = readdir(dir)) != NULL) { fname = &(f->d_name[0]); if (UNLIKELY(fname[0]=='_')) continue; n = len = (int) strlen(fname); if (UNLIKELY(fname[0]=='_')) continue; #if defined(WIN32) strcpy(buf, "dll"); n -= 4; #elif defined(__MACH__) strcpy(buf, "dylib"); n -= 6; #else strcpy(buf, "so"); n -= 3; #endif if (n <= 0 || fname[n] != '.') continue; i = 0; do { if (UNLIKELY((fname[++n] | (char) 0x20) != buf[i])) break; } while (buf[++i] != '\0'); if (buf[i] != '\0') continue; /* found a dynamic library, attempt to open it */ if (UNLIKELY(((int) strlen(dname) + len + 2) > 1024)) { csound->Warning(csound, Str("path name too long, skipping '%s'"), fname); continue; } /* printf("DEBUG %s(%d): possibly deny %s\n", __FILE__, __LINE__,fname); */ if (UNLIKELY(csoundCheckOpcodeDeny(csound, fname))) { csoundWarning(csound, Str("Library %s omitted\n"), fname); continue; } snprintf(buf, 1024, "%s%c%s", dname, DIRSEP, fname); if (UNLIKELY(csound->oparms->odebug)) { csoundMessage(csound, Str("Loading '%s'\n"), buf); } n = csoundLoadExternal(csound, buf); if (UNLIKELY(UNLIKELY(n == CSOUND_ERROR))) continue; /* ignore non-plugin files */ if (UNLIKELY(n < err)) err = n; /* record serious errors */ } closedir(dir); return (err == CSOUND_INITIALIZATION ? CSOUND_ERROR : err); #else return CSOUND_SUCCESS; #endif /* HAVE_DIRENT_H */ } static int cmp_func(const void *p1, const void *p2) { return (strcmp(*((const char**) p1), *((const char**) p2))); } int csoundLoadExternals(CSOUND *csound) { char *s, **lst; int i, cnt, err; s = csound->dl_opcodes_oplibs; if (UNLIKELY(s == NULL || s[0] == '\0')) return 0; /* IV - Feb 19 2005 */ csound->dl_opcodes_oplibs = NULL; csoundMessage(csound, Str("Loading command-line libraries:\n")); cnt = 1; i = 0; do { if (s[i] == ',') cnt++; } while (s[++i] != '\0'); lst = (char**) csound->Malloc(csound, sizeof(char*) * cnt); i = cnt = 0; lst[cnt++] = s; do { if (s[i] == ',') { lst[cnt++] = &(s[i + 1]); s[i] = '\0'; } } while (s[++i] != '\0'); qsort((void*) lst, (size_t) cnt, sizeof(char*), cmp_func); i = 0; do { char *fname = lst[i]; if (fname[0] != '\0' && !(i && strcmp(fname, lst[i - 1]) == 0)) { err = csoundLoadExternal(csound, fname); if (UNLIKELY(err == CSOUND_INITIALIZATION || err == CSOUND_MEMORY)) csoundDie(csound, Str(" *** error loading '%s'"), fname); else if (!err) csoundMessage(csound, " %s\n", fname); } } while (++i < cnt); /* file list is no longer needed */ csound->Free(csound, lst); csound->Free(csound, s); return 0; } /** * Initialise a single module. * Return value is CSOUND_SUCCESS if there was no error. */ static CS_NOINLINE int csoundInitModule(CSOUND *csound, csoundModule_t *m) { int i; if (m->PreInitFunc != NULL) { if (m->fn.p.InitFunc != NULL) { i = m->fn.p.InitFunc(csound); if (UNLIKELY(i != 0)) { print_module_error(csound, Str("Error starting module '%s'"), &(m->name[0]), m, i); return CSOUND_ERROR; } } } else { /* deal with fgens if there are any */ if (m->fn.o.fgen_init != NULL) { NGFENS *names = m->fn.o.fgen_init(csound); for (i = 0; names[i].name != NULL; i++) allocgen(csound, names[i].name, names[i].fn); } if (m->fn.o.opcode_init != NULL) { OENTRY *opcodlst_n; long length; /* load opcodes */ if (UNLIKELY((length = m->fn.o.opcode_init(csound, &opcodlst_n)) < 0L)) return CSOUND_ERROR; else { length /= (long) sizeof(OENTRY); if (length) { if (UNLIKELY(csoundAppendOpcodes(csound, opcodlst_n, (int) length) != 0)) return CSOUND_ERROR; } } } } return CSOUND_SUCCESS; } /** * Call initialisation functions of all loaded modules that have a * csoundModuleInit symbol, for Csound instance 'csound'. * Return value is CSOUND_SUCCESS if there was no error, and CSOUND_ERROR if * some modules could not be initialised. */ int csoundInitModules(CSOUND *csound) { csoundModule_t *m; int i, retval = CSOUND_SUCCESS; /* For regular Csound, init_static_modules is not compiled or called. * For some builds of Csound, e.g. for PNaCl, init_static_modules is * compiled and called to initialize statically linked opcodes and other * plugins that are dynamically loaded on other platforms. */ #if defined(INIT_STATIC_MODULES) retval = init_static_modules(csound); #endif /* call init functions */ for (m = (csoundModule_t*) csound->csmodule_db; m != NULL; m = m->nxt) { i = csoundInitModule(csound, m); if (UNLIKELY(i != CSOUND_SUCCESS && i < retval)) retval = i; } /* return with error code */ return retval; } /* load a plugin library and also initialise it */ /* called on deferred loading of opcode plugins */ int csoundLoadAndInitModule(CSOUND *csound, const char *fname) { volatile jmp_buf tmpExitJmp; volatile int err; err = csoundLoadExternal(csound, fname); if (UNLIKELY(err != 0)) return err; memcpy((void*) &tmpExitJmp, (void*) &csound->exitjmp, sizeof(jmp_buf)); if (UNLIKELY((err = setjmp(csound->exitjmp)) != 0)) { memcpy((void*) &csound->exitjmp, (void*) &tmpExitJmp, sizeof(jmp_buf)); return (err == (CSOUND_EXITJMP_SUCCESS + CSOUND_MEMORY) ? CSOUND_MEMORY : CSOUND_INITIALIZATION); } /* NOTE: this depends on csound->csmodule_db being the most recently */ /* loaded plugin library */ err = csoundInitModule(csound, (csoundModule_t*) csound->csmodule_db); memcpy((void*) &csound->exitjmp, (void*) &tmpExitJmp, sizeof(jmp_buf)); return err; } /** * Call destructor functions of all loaded modules that have a * csoundModuleDestroy symbol, for Csound instance 'csound'. * Return value is CSOUND_SUCCESS if there was no error, and * CSOUND_ERROR if some modules could not be de-initialised. */ extern int sfont_ModuleDestroy(CSOUND *csound); int csoundDestroyModules(CSOUND *csound) { csoundModule_t *m; int i, retval; retval = CSOUND_SUCCESS; while (csound->csmodule_db != NULL) { m = (csoundModule_t*) csound->csmodule_db; /* call destructor functions */ if (m->PreInitFunc != NULL && m->fn.p.DestFunc != NULL) { i = m->fn.p.DestFunc(csound); if (UNLIKELY(i != 0)) { print_module_error(csound, Str("Error de-initialising module '%s'"), &(m->name[0]), m, i); retval = CSOUND_ERROR; } } /* unload library */ csoundCloseLibrary(m->h); csound->csmodule_db = (void*) m->nxt; /* free memory used by database */ csound->Free(csound, (void*) m); } sfont_ModuleDestroy(csound); /* return with error code */ return retval; } /* ------------------------------------------------------------------------ */ #if defined(WIN32) PUBLIC int csoundOpenLibrary(void **library, const char *libraryPath) { *library = (void*) LoadLibrary(libraryPath); return (*library != NULL ? 0 : -1); } PUBLIC int csoundCloseLibrary(void *library) { return (int) (FreeLibrary((HMODULE) library) == FALSE ? -1 : 0); } PUBLIC void *csoundGetLibrarySymbol(void *library, const char *procedureName) { return (void*) GetProcAddress((HMODULE) library, procedureName); } #elif !(defined(NACL)) && (defined(LINUX) || defined (NEW_MACH_CODE)) PUBLIC int csoundOpenLibrary(void **library, const char *libraryPath) { int flg = RTLD_NOW; if (libraryPath != NULL) { int len = (int) strlen(libraryPath); /* ugly hack to fix importing modules in Python opcodes */ if (len >= 9 && strcmp(&(libraryPath[len - 9]), "/libpy.so") == 0) flg |= RTLD_GLOBAL; if (len >= 12 && strcmp(&(libraryPath[len - 12]), "/libpy.dylib") == 0) flg |= RTLD_GLOBAL; } *library = (void*) dlopen(libraryPath, flg); return (*library != NULL ? 0 : -1); } PUBLIC int csoundCloseLibrary(void *library) { return (int) dlclose(library); } PUBLIC void *csoundGetLibrarySymbol(void *library, const char *procedureName) { return (void*) dlsym(library, procedureName); } #else /* case for platforms without shared libraries -- added 062404, akozar */ int csoundOpenLibrary(void **library, const char *libraryPath) { *library = NULL; return -1; } int csoundCloseLibrary(void *library) { return 0; } void *csoundGetLibrarySymbol(void *library, const char *procedureName) { return NULL; } #endif #if ENABLE_OPCODEDIR_WARNINGS static const char *opcodedirWarnMsg[] = { "################################################################", #ifndef USE_DOUBLE "# WARNING: OPCODE6DIR IS NOT SET ! #", #else "# WARNING: OPCODE6DIR64 IS NOT SET ! #", #endif "# Csound requires this environment variable to be set to find #", "# its plugin libraries. If it is not set, you may experience #", "# missing opcodes, audio/MIDI drivers, or utilities. #", "################################################################", NULL }; #endif void print_opcodedir_warning(CSOUND *p) { #if ENABLE_OPCODEDIR_WARNINGS if (!p->opcodedirWasOK) { const char **sp; for (sp = &(opcodedirWarnMsg[0]); *sp != NULL; sp++) p->MessageS(p, CSOUNDMSG_WARNING, " %s\n", Str(*sp)); } #else (void) p; #endif } typedef long (*INITFN)(CSOUND *, void *); extern long babo_localops_init(CSOUND *, void *); extern long bilbar_localops_init(CSOUND *, void *); extern long compress_localops_init(CSOUND *, void *); extern long pvsbuffer_localops_init(CSOUND *, void *); extern long pvsgendy_localops_init(CSOUND *, void *); extern long vosim_localops_init(CSOUND *, void *); extern long eqfil_localops_init(CSOUND *, void *); extern long modal4_localops_init(CSOUND *, void *); extern long scoreline_localops_init(CSOUND *, void *); extern long physmod_localops_init(CSOUND *, void *); extern long modmatrix_localops_init(CSOUND *, void *); extern long spectra_localops_init(CSOUND *, void *); extern long ambicode1_localops_init(CSOUND *, void *); extern long grain4_localops_init(CSOUND *, void *); extern long hrtferX_localops_init(CSOUND *, void *); extern long loscilx_localops_init(CSOUND *, void *); extern long pan2_localops_init(CSOUND *, void *); extern long arrayvars_localops_init(CSOUND *, void *); extern long phisem_localops_init(CSOUND *, void *); extern long pvoc_localops_init(CSOUND *, void *); extern long hrtfopcodes_localops_init(CSOUND *, void *); extern long hrtfreverb_localops_init(CSOUND *, void *); extern long hrtfearly_localops_init(CSOUND *, void *); extern long minmax_localops_init(CSOUND *, void *); //extern long stackops_localops_init(CSOUND *, void *); extern long vbap_localops_init(CSOUND *, void *); extern long vaops_localops_init(CSOUND *, void*); extern long ugakbari_localops_init(CSOUND *, void *); extern long harmon_localops_init(CSOUND *, void *); extern long pitchtrack_localops_init(CSOUND *, void *); extern long squinewave_localops_init(CSOUND *, void *); extern long partikkel_localops_init(CSOUND *, void *); extern long shape_localops_init(CSOUND *, void *); extern long tabsum_localops_init(CSOUND *, void *); extern long crossfm_localops_init(CSOUND *, void *); extern long pvlock_localops_init(CSOUND *, void *); extern long fareyseq_localops_init(CSOUND *, void *); extern long cpumeter_localops_init(CSOUND *, void *); extern long gendy_localops_init(CSOUND *, void *); extern long scnoise_localops_init(CSOUND *, void *); #ifndef NACL extern long socksend_localops_init(CSOUND *, void *); extern long mp3in_localops_init(CSOUND *, void *); extern long sockrecv_localops_init(CSOUND *, void *); #endif extern long afilts_localops_init(CSOUND *, void *); extern long pinker_localops_init(CSOUND *, void *); extern long paulstretch_localops_init(CSOUND *, void *); extern long wpfilters_localops_init(CSOUND *, void *); extern int stdopc_ModuleInit(CSOUND *csound); extern int pvsopc_ModuleInit(CSOUND *csound); extern int sfont_ModuleInit(CSOUND *csound); extern int sfont_ModuleCreate(CSOUND *csound); extern int newgabopc_ModuleInit(CSOUND *csound); const INITFN staticmodules[] = { hrtfopcodes_localops_init, babo_localops_init, bilbar_localops_init, vosim_localops_init, compress_localops_init, pvsbuffer_localops_init, eqfil_localops_init, modal4_localops_init, scoreline_localops_init, physmod_localops_init, modmatrix_localops_init, spectra_localops_init, ambicode1_localops_init, grain4_localops_init, hrtferX_localops_init, loscilx_localops_init, pan2_localops_init, arrayvars_localops_init, phisem_localops_init, pvoc_localops_init, /*stackops_localops_init,*/ vbap_localops_init, ugakbari_localops_init, harmon_localops_init, pitchtrack_localops_init, partikkel_localops_init, shape_localops_init, tabsum_localops_init, crossfm_localops_init, pvlock_localops_init, fareyseq_localops_init, hrtfearly_localops_init, hrtfreverb_localops_init, minmax_localops_init, vaops_localops_init, pvsgendy_localops_init, paulstretch_localops_init, squinewave_localops_init, #ifdef LINUX cpumeter_localops_init, #endif #ifndef NACL mp3in_localops_init, sockrecv_localops_init, socksend_localops_init, #endif gendy_localops_init, scnoise_localops_init, afilts_localops_init, pinker_localops_init, wpfilters_localops_init, NULL }; typedef NGFENS* (*FGINITFN)(CSOUND *); NGFENS *ftest_fgens_init(CSOUND *); const FGINITFN fgentab[] = { ftest_fgens_init, NULL }; CS_NOINLINE int csoundInitStaticModules(CSOUND *csound) { int i; OENTRY *opcodlst_n; long length; for (i=0; staticmodules[i]!=NULL; i++) { length = (staticmodules[i])(csound, &opcodlst_n); if (UNLIKELY(length <= 0L)) return CSOUND_ERROR; length /= (long) sizeof(OENTRY); if (length) { if (UNLIKELY(csoundAppendOpcodes(csound, opcodlst_n, (int) length) != 0)) return CSOUND_ERROR; } } /* stdopc module */ if (UNLIKELY(stdopc_ModuleInit(csound))) return CSOUND_ERROR; /* pvs module */ if (UNLIKELY(pvsopc_ModuleInit(csound))) return CSOUND_ERROR; /* sfont module */ sfont_ModuleCreate(csound); if (UNLIKELY(sfont_ModuleInit(csound))) return CSOUND_ERROR; /* newgabopc */ if (UNLIKELY(newgabopc_ModuleInit(csound))) return CSOUND_ERROR; /* modules were initialised successfully */ /* Now fgens */ for (i = 0; fgentab[i]!=NULL; i++) { int j; NGFENS *names = (fgentab[i])(csound); for (j = 0; names[j].name != NULL; j++) allocgen(csound, names[j].name, names[j].fn); } return CSOUND_SUCCESS; } csound-6.10.0/Top/csound.c000066400000000000000000004205311321653344700153070ustar00rootroot00000000000000/* * C S O U N D * * An auto-extensible system for making music on computers * by means of software alone. * * Copyright (C) 2001-2006 Michael Gogins, Matt Ingalls, John D. Ramsdell, * John P. ffitch, Istvan Varga, Victor Lazzarini, * Steven Yi * * L I C E N S E * * This software is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ //#ifdef __cplusplus //extern "C" { //#endif #if defined(HAVE_UNISTD_H) || defined (__unix) || defined(__unix__) #include #endif #include "csoundCore.h" #include "csmodule.h" #include "corfile.h" #include "csGblMtx.h" #include #include #include #include #include #ifdef HAVE_SYS_TYPES_H # include #endif #if defined(WIN32) && !defined(__CYGWIN__) # include # include #endif #include #include "oload.h" #include "fgens.h" #include "namedins.h" #include "pvfileio.h" #include "fftlib.h" #include "cs_par_base.h" #include "cs_par_orc_semantics.h" //#include "cs_par_dispatch.h" #include "find_opcode.h" #if defined(linux)||defined(__HAIKU__)|| defined(__EMSCRIPTEN__)||defined(__CYGWIN__) #define PTHREAD_SPINLOCK_INITIALIZER 0 #endif #include "csound_standard_types.h" #include "csdebug.h" #include extern void allocate_message_queue(CSOUND *csound); static void SetInternalYieldCallback(CSOUND *, int (*yieldCallback)(CSOUND *)); int playopen_dummy(CSOUND *, const csRtAudioParams *parm); void rtplay_dummy(CSOUND *, const MYFLT *outBuf, int nbytes); int recopen_dummy(CSOUND *, const csRtAudioParams *parm); int rtrecord_dummy(CSOUND *, MYFLT *inBuf, int nbytes); void rtclose_dummy(CSOUND *); int audio_dev_list_dummy(CSOUND *, CS_AUDIODEVICE *, int); int midi_dev_list_dummy(CSOUND *, CS_MIDIDEVICE *, int); static void csoundDefaultMessageCallback(CSOUND *, int, const char *, va_list); static int defaultCsoundYield(CSOUND *); static int csoundDoCallback_(CSOUND *, void *, unsigned int); static void reset(CSOUND *); static int csoundPerformKsmpsInternal(CSOUND *csound); void csoundTableSetInternal(CSOUND *csound, int table, int index, MYFLT value); static INSTRTXT **csoundGetInstrumentList(CSOUND *csound); uint64_t csoundGetKcounter(CSOUND *csound); static void set_util_sr(CSOUND *csound, MYFLT sr); static void set_util_nchnls(CSOUND *csound, int nchnls); extern void cscoreRESET(CSOUND *); extern void memRESET(CSOUND *); extern MYFLT csoundPow2(CSOUND *csound, MYFLT a); extern int csoundInitStaticModules(CSOUND *); extern void close_all_files(CSOUND *); extern void csoundInputMessageInternal(CSOUND *csound, const char *message); extern int isstrcod(MYFLT ); extern int fterror(const FGDATA *ff, const char *s, ...); void (*msgcallback_)(CSOUND *, int, const char *, va_list) = NULL; void csoundDebuggerBreakpointReached(CSOUND *csound); void message_dequeue(CSOUND *csound); extern OENTRY opcodlst_1[]; #define STRING_HASH(arg) STRSH(arg) #define STRSH(arg) #arg void print_csound_version(CSOUND* csound) { #ifdef USE_DOUBLE #ifdef BETA csound->Message(csound, Str("--Csound version %s beta (double samples) %s \n" "[commit: %s]\n"), CS_PACKAGE_VERSION, CS_PACKAGE_DATE, STRING_HASH(GIT_HASH_VALUE)); #else csound->Message(csound, Str("--Csound version %s (double samples) %s \n" "[commit: %s]\n"), CS_PACKAGE_VERSION, CS_PACKAGE_DATE , STRING_HASH(GIT_HASH_VALUE)); #endif #else #ifdef BETA csound->Message(csound, Str("--Csound version %s beta (float samples) %s \n" "[commit: %s]\n"), CS_PACKAGE_VERSION, CS_PACKAGE_DATE, STRING_HASH(GIT_HASH_VALUE)); #else csound->Message(csound, Str("--Csound version %s (float samples) %s \n" "[commit: %s]\n"), CS_PACKAGE_VERSION, CS_PACKAGE_DATE, STRING_HASH(GIT_HASH_VALUE)); #endif #endif } static void free_opcode_table(CSOUND* csound) { int i; CS_HASH_TABLE_ITEM* bucket; CONS_CELL* head; for (i = 0; i < HASH_SIZE; i++) { bucket = csound->opcodes->buckets[i]; while (bucket != NULL) { head = bucket->value; cs_cons_free_complete(csound, head); bucket = bucket->next; } } cs_hash_table_free(csound, csound->opcodes); } static void create_opcode_table(CSOUND *csound) { int err; if (csound->opcodes != NULL) { free_opcode_table(csound); } csound->opcodes = cs_hash_table_create(csound); /* Basic Entry1 stuff */ err = csoundAppendOpcodes(csound, &(opcodlst_1[0]), -1); if (UNLIKELY(err)) csoundDie(csound, Str("Error allocating opcode list")); } #define MAX_MODULES 64 static void module_list_add(CSOUND *csound, char *drv, char *type){ MODULE_INFO **modules = (MODULE_INFO **) csoundQueryGlobalVariable(csound, "_MODULES"); if (modules != NULL){ int i = 0; while (modules[i] != NULL && i < MAX_MODULES) { if (!strcmp(modules[i]->module, drv)) return; i++; } modules[i] = (MODULE_INFO *) csound->Malloc(csound, sizeof(MODULE_INFO)); strncpy(modules[i]->module, drv, 11); strncpy(modules[i]->type, type, 11); } } static int csoundGetRandSeed(CSOUND *csound, int which){ if (which > 1) return csound->randSeed1; else return csound->randSeed2; } static char *csoundGetStrsets(CSOUND *csound, long p){ if (csound->strsets == NULL) return NULL; else return csound->strsets[p]; } static int csoundGetStrsmax(CSOUND *csound){ return csound->strsmax; } static void csoundGetOParms(CSOUND *csound, OPARMS *p){ memcpy(p, csound->oparms, sizeof(OPARMS)); } static int csoundGetDitherMode(CSOUND *csound){ return csound->dither_output; } static int csoundGetZakBounds(CSOUND *csound, MYFLT **zkstart){ *zkstart = csound->zkstart; return csound->zklast; } static int csoundGetReinitFlag(CSOUND *csound){ return csound->reinitflag; } static int csoundGetTieFlag(CSOUND *csound){ return csound->tieflag; } static MYFLT csoundSystemSr(CSOUND *csound, MYFLT val) { if (val > 0) csound->_system_sr = val; return csound->_system_sr; } static const CSOUND cenviron_ = { /* attributes */ csoundGetSr, csoundGetKr, csoundGetKsmps, csoundGetNchnls, csoundGetNchnlsInput, csoundGet0dBFS, csoundGetKcounter, csoundGetCurrentTimeSamples, csoundGetInputBufferSize, csoundGetOutputBufferSize, csoundGetInputBuffer, csoundGetOutputBuffer, csoundSetDebug, csoundGetDebug, csoundGetSizeOfMYFLT, csoundGetOParms, csoundGetEnv, /* message printout */ csoundMessage, csoundMessageS, csoundMessageV, csoundGetMessageLevel, csoundSetMessageLevel, csoundSetMessageCallback, /* Event and MIDI functionality for opcodes */ csoundSetReleaseLength, csoundSetReleaseLengthSeconds, csoundGetMidiChannelNumber, csoundGetMidiChannel, csoundGetMidiNoteNumber, csoundGetMidiVelocity, csoundGetReleaseFlag, csoundGetOffTime, csoundGetPFields, csoundGetInstrumentNumber, csoundGetZakBounds, csoundGetTieFlag, csoundGetReinitFlag, csoundGetStrsmax, csoundGetStrsets, csoundPow2, intpow, type2string, /* arguments to opcodes */ csoundGetTypeForArg, csoundGetInputArgCnt, csoundGetInputArgName, csoundGetOutputArgCnt, csoundGetOutputArgName, get_arg_string, strarg2insno, strarg2name, /* memory allocation */ csoundAuxAlloc, mmalloc, mcalloc, mrealloc, cs_strdup, mfree, /* function tables */ hfgens, csoundFTAlloc, csoundFTDelete, csoundFTFind, csoundFTFindP, csoundFTnp2Find, csoundGetTable, csoundTableLength, csoundTableGet, csoundTableSetInternal, csoundGetNamedGens, /* global and config variable manipulation */ csoundCreateGlobalVariable, csoundQueryGlobalVariable, csoundQueryGlobalVariableNoCheck, csoundDestroyGlobalVariable, csoundCreateConfigurationVariable, csoundSetConfigurationVariable, csoundParseConfigurationVariable, csoundQueryConfigurationVariable, csoundListConfigurationVariables, csoundDeleteConfigurationVariable, csoundCfgErrorCodeToString, /* FFT support */ csoundGetInverseComplexFFTScale, csoundGetInverseRealFFTScale, csoundComplexFFT, csoundInverseComplexFFT, csoundRealFFT, csoundInverseRealFFT, csoundRealFFTMult, csoundRealFFTnp2, csoundInverseRealFFTnp2, /* PVOC-EX system */ pvoc_createfile, pvoc_openfile, pvoc_closefile, pvoc_putframes, pvoc_getframes, pvoc_framecount, pvoc_fseek, pvoc_errorstr, PVOCEX_LoadFile, /* error messages */ csoundDie, csoundInitError, csoundPerfError, csoundWarning, csoundDebugMsg, csoundLongJmp, csoundErrorMsg, csoundErrMsgV, /* random numbers */ csoundGetRandomSeedFromTime, csoundSeedRandMT, csoundRandMT, csoundRand31, csoundGetRandSeed, /* threads and locks */ csoundCreateThread, csoundJoinThread, csoundCreateThreadLock, csoundDestroyThreadLock, csoundWaitThreadLock, csoundNotifyThreadLock, csoundWaitThreadLockNoTimeout, csoundCreateMutex, csoundLockMutexNoWait, csoundLockMutex, csoundUnlockMutex, csoundDestroyMutex, csoundCreateBarrier, csoundDestroyBarrier, csoundWaitBarrier, csoundGetCurrentThreadId, csoundSleep, csoundInitTimerStruct, csoundGetRealTime, csoundGetCPUTime, /* circular buffer */ csoundCreateCircularBuffer, csoundReadCircularBuffer, csoundWriteCircularBuffer, csoundFlushCircularBuffer, csoundDestroyCircularBuffer, /* File access */ csoundFindInputFile, csoundFindOutputFile, SAsndgetset, sndgetset, getsndin, rewriteheader, csoundLoadSoundFile, fdrecord, fdclose, csoundCreateFileHandle, csoundGetFileName, csoundFileClose, csoundFileOpenWithType, type2csfiletype, csoundNotifyFileOpened, sftype2csfiletype, ldmemfile2withCB, csoundFileOpenWithType_Async, csoundReadAsync, csoundWriteAsync, csoundFSeekAsync, getstrformat, sfsampsize, /* RT audio IO and callbacks */ csoundSetPlayopenCallback, csoundSetRtplayCallback, csoundSetRecopenCallback, csoundSetRtrecordCallback, csoundSetRtcloseCallback, csoundSetAudioDeviceListCallback, csoundGetRtRecordUserData, csoundGetRtPlayUserData, csoundGetDitherMode, /* MIDI and callbacks */ csoundSetExternalMidiInOpenCallback, csoundSetExternalMidiReadCallback, csoundSetExternalMidiInCloseCallback, csoundSetExternalMidiOutOpenCallback, csoundSetExternalMidiWriteCallback, csoundSetExternalMidiOutCloseCallback, csoundSetExternalMidiErrorStringCallback, csoundSetMIDIDeviceListCallback, module_list_add, /* displays & graphs */ dispset, display, dispexit, dispinit, csoundSetIsGraphable, csoundSetMakeGraphCallback, csoundSetDrawGraphCallback, csoundSetKillGraphCallback, csoundSetExitGraphCallback, /* generic callbacks */ csoundSetYieldCallback, csoundRegisterKeyboardCallback, csoundRemoveKeyboardCallback, csoundRegisterSenseEventCallback, csoundRegisterDeinitCallback, csoundRegisterResetCallback, SetInternalYieldCallback, /* opcodes and instruments */ csoundAppendOpcode, csoundAppendOpcodes, csoundGetOpcodeName, csoundGetInstrumentList, /* events and performance */ csoundYield, insert_score_event, insert_score_event_at_sample, csoundPerformKsmpsInternal, /* utilities */ csoundAddUtility, csoundRunUtility, csoundListUtilities, csoundSetUtilityDescription, csoundGetUtilityDescription, set_util_sr, set_util_nchnls, /* miscellaneous */ csoundRunCommand, csoundOpenLibrary, csoundCloseLibrary, csoundGetLibrarySymbol, csoundLocalizeString, cs_strtok_r, cs_strtod, cs_sprintf, cs_sscanf, csoundSystemSr, csoundGetScoreOffsetSeconds, csoundSetScoreOffsetSeconds, csoundRewindScore, csoundInputMessageInternal, isstrcod, csoundRealFFT2Setup, csoundRealFFT2, fterror, csoundGetA4, csoundAuxAllocAsync, { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, /* ------- private data (not to be used by hosts or externals) ------- */ /* callback function pointers */ (SUBR) NULL, /* first_callback_ */ (channelCallback_t) NULL, (channelCallback_t) NULL, csoundDefaultMessageCallback, (int (*)(CSOUND *)) NULL, (void (*)(CSOUND *, WINDAT *, const char *)) NULL, /* was: MakeAscii,*/ (void (*)(CSOUND *, WINDAT *windat)) NULL, /* was: DrawAscii,*/ (void (*)(CSOUND *, WINDAT *windat)) NULL, /* was: KillAscii,*/ (int (*)(CSOUND *)) NULL, /* was: defaultCsoundExitGraph, */ defaultCsoundYield, cscore_, /* cscoreCallback_ */ (void(*)(CSOUND*, const char*, int, int, int)) NULL, /* FileOpenCallback_ */ (SUBR) NULL, /* last_callback_ */ /* these are not saved on RESET */ playopen_dummy, rtplay_dummy, recopen_dummy, rtrecord_dummy, rtclose_dummy, audio_dev_list_dummy, midi_dev_list_dummy, csoundDoCallback_, /* doCsoundCallback */ defaultCsoundYield, /* csoundInternalYieldCallback_*/ /* end of callbacks */ (void (*)(CSOUND *)) NULL, /* spinrecv */ (void (*)(CSOUND *)) NULL, /* spoutran */ (int (*)(CSOUND *, MYFLT *, int)) NULL, /* audrecv */ (void (*)(CSOUND *, const MYFLT *, int)) NULL, /* audtran */ NULL, /* hostdata */ NULL, NULL, /* orchname, scorename */ NULL, NULL, /* orchstr, *scorestr */ (OPDS*) NULL, /* ids */ { (CS_VAR_POOL*)NULL, (CS_HASH_TABLE *) NULL, (CS_HASH_TABLE *) NULL, -1, (INSTRTXT**)NULL, { NULL, { 0,0, NULL, NULL, NULL, NULL, 0, NULL, 0,0,0}, 0,0,0, 0, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, FL(0.0), NULL, NULL, 0, 0, 0 }, NULL, MAXINSNO, /* engineState */ }, (INSTRTXT *) NULL, /* instr0 */ (INSTRTXT**)NULL, /* dead_instr_pool */ 0, /* dead_instr_no */ (TYPE_POOL*)NULL, DFLT_KSMPS, /* ksmps */ DFLT_NCHNLS, /* nchnls */ -1, /* inchns */ 0, /* spoutactive */ 0L, /* kcounter */ 0L, /* global_kcounter */ DFLT_SR, /* esr */ DFLT_KR, /* ekr */ 0l, /* curTime */ 0l, /* curTime_inc */ 0.0, /* timeOffs */ 0.0, /* beatOffs */ 0.0, /* curBeat */ 0.0, /* curBeat_inc */ 0L, /* beatTime */ (EVTBLK*) NULL, /* currevent */ (INSDS*) NULL, /* curip */ FL(0.0), /* cpu_power_busy */ (char*) NULL, /* xfilename */ 1, /* peakchunks */ 0, /* keep_tmp */ (CS_HASH_TABLE*)NULL, /* Opcode hash table */ 0, /* nrecs */ NULL, /* Linepipe */ 0, /* Linefd */ NULL, /* csoundCallbacks_ */ (FILE*)NULL, /* scfp */ (CORFIL*)NULL, /* scstr */ NULL, /* oscfp */ { FL(0.0) }, /* maxamp */ { FL(0.0) }, /* smaxamp */ { FL(0.0) }, /* omaxamp */ {0}, {0}, {0}, /* maxpos, smaxpos, omaxpos */ NULL, NULL, /* scorein, scoreout */ NULL, /* argoffspace */ NULL, /* frstoff */ NULL, /* zkstart */ 0L, /* zklast */ NULL, /* zastart */ 0L, /* zalast */ NULL, /* stdOp_Env */ 2345678, /* holdrand */ 0, /* randSeed1 */ 0, /* randSeed2 */ NULL, /* csRandState */ NULL, /* csRtClock */ // 16384, /* strVarMaxLen */ 0, /* strsmax */ (char**) NULL, /* strsets */ NULL, /* spin */ NULL, /* spout */ NULL, /* spraw */ 0, /* nspin */ 0, /* nspout */ NULL, /* auxspin */ (OPARMS*) NULL, /* oparms */ { NULL }, /* m_chnbp */ 0, /* dither_output */ FL(0.0), /* onedsr */ FL(0.0), /* sicvt */ FL(-1.0), /* tpidsr */ FL(-1.0), /* pidsr */ FL(-1.0), /* mpidsr */ FL(-1.0), /* mtpdsr */ FL(0.0), /* onedksmps */ FL(0.0), /* onedkr */ FL(0.0), /* kicvt */ 0, /* reinitflag */ 0, /* tieflag */ DFLT_DBFS, /* e0dbfs */ FL(1.0) / DFLT_DBFS, /* dbfs_to_float ( = 1.0 / e0dbfs) */ 440.0, /* A4 base frequency */ NULL, /* rtRecord_userdata */ NULL, /* rtPlay_userdata */ #if defined(MSVC) ||defined(__POWERPC__) || defined(MACOSX) || \ (defined(_WIN32) && defined(__GNUC__)) {0}, #else {{{0}}}, /* exitjmp of type jmp_buf */ #endif NULL, /* frstbp */ 0, /* sectcnt */ 0, 0, 0, /* inerrcnt, synterrcnt, perferrcnt */ /* {NULL}, */ /* instxtanchor in engineState */ { /* actanchor */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, 0, NULL, 0, 0, 0, 0, 0, 0.0, 0.0, NULL, NULL, 0, 0, FL(0.0), FL(0.0), FL(0.0), FL(0.0), NULL, {FL(0.0), FL(0.0), FL(0.0), FL(0.0)}, NULL, NULL,NULL, NULL, 0, 0, 0, NULL, NULL, 0, 0, 0, FL(0.0), NULL, NULL, {NULL, FL(0.0)}, {NULL, FL(0.0)}, {NULL, FL(0.0)}, {NULL, FL(0.0)} }, {0L }, /* rngcnt */ 0, 0, /* rngflg, multichan */ NULL, /* evtFuncChain */ NULL, /* OrcTrigEvts */ NULL, /* freeEvtNodes */ 1, /* csoundIsScorePending_ */ 0, /* advanceCnt */ 0, /* initonly */ 0, /* evt_poll_cnt */ 0, /* evt_poll_maxcnt */ 0, 0, 0, /* Mforcdecs, Mxtroffs, MTrkend */ NULL, /* opcodeInfo */ NULL, /* flist */ 0, /* maxfnum */ NULL, /* gensub */ GENMAX+1, /* genmax */ NULL, /* namedGlobals */ NULL, /* cfgVariableDB */ FL(0.0), FL(0.0), FL(0.0), /* prvbt, curbt, nxtbt */ FL(0.0), FL(0.0), /* curp2, nxtim */ 0, /* cyclesRemaining */ { 0, NULL, NULL, '\0', 0, FL(0.0), FL(0.0), { FL(0.0) }, {NULL}}, /* evt */ NULL, /* memalloc_db */ (MGLOBAL*) NULL, /* midiGlobals */ NULL, /* envVarDB */ (MEMFIL*) NULL, /* memfiles */ NULL, /* pvx_memfiles */ 0, /* FFT_max_size */ NULL, /* FFT_table_1 */ NULL, /* FFT_table_2 */ NULL, NULL, NULL, /* tseg, tpsave, tplim */ (MYFLT*) NULL, /* gbloffbas */ NULL, /* file_io_thread */ 0, /* file_io_start */ NULL, /* file_io_threadlock */ 0, /* realtime_audio_flag */ NULL, /* init pass thread */ 0, /* init pass loop */ NULL, /* init pass threadlock */ NULL, /* API_lock */ #if defined(HAVE_PTHREAD_SPIN_LOCK) PTHREAD_SPINLOCK_INITIALIZER, /* spoutlock */ PTHREAD_SPINLOCK_INITIALIZER, /* spinlock */ #else 0, /* spoutlock */ 0, /* spinlock */ #endif #if defined(HAVE_PTHREAD_SPIN_LOCK) PTHREAD_SPINLOCK_INITIALIZER, /* memlock */ PTHREAD_SPINLOCK_INITIALIZER, /* spinlock1 */ #else 0, 0, /* memlock, spinlock1 */ #endif NULL, NULL, /* Delayed messages */ { NULL, NULL, NULL, NULL, /* bp, prvibp, sp, nx */ 0, 0, 0, 0, /* op warpin linpos lincnt */ -FL(1.0), FL(0.0), FL(1.0), /* prvp2 clock_base warp_factor */ NULL, /* curmem */ NULL, /* memend */ NULL, /* macros */ -1, /* next_name */ NULL, NULL, /* inputs, str */ 0,0,0, /* input_size, input_cnt, pop */ 1, /* ingappop */ -1, /* linepos */ {{NULL, 0, 0}}, /* names */ {""}, /* repeat_name_n[RPTDEPTH][NAMELEN] */ {0}, /* repeat_cnt_n[RPTDEPTH] */ {0}, /* repeat_point_n[RPTDEPTH] */ 1, {NULL}, 0, /* repeat_inc_n,repeat_mm_n repeat_index */ "", /* repeat_name[NAMELEN] */ 0,0,1, /* repeat_cnt, repeat_point, repeat_inc */ NULL, /* repeat_mm */ 0 }, { NULL, NULL, NULL, NULL, /* orcname, sconame, midname */ 0, 0 /* midiSet, csdlinecount */ }, { NULL, NULL, /* Linep, Linebufend */ 0, /* stdmode */ { 0, NULL, NULL, 0, 0, FL(0.0), FL(0.0), { FL(0.0) }, {NULL}, }, /* EVTBLK prve */ NULL, /* Linebuf */ 0, /* linebufsiz */ NULL, NULL, 0 }, { {0,0}, {0,0}, /* srngcnt, orngcnt */ 0, 0, 0, 0, 0, /* srngflg, sectno, lplayed, segamps, sormsg */ NULL, NULL, /* ep, epend */ NULL /* lsect */ }, //NULL, /* musmonGlobals */ { NULL, /* outfile */ NULL, /* infile */ NULL, /* sfoutname; */ NULL, /* inbuf */ NULL, /* outbuf */ NULL, /* outbufp */ 0, /* inbufrem */ 0, /* outbufrem */ 0,0, /* inbufsiz, outbufsiz */ 0, /* isfopen */ 0, /* osfopen */ 0,0, /* pipdevin, pipdevout */ 1U, /* nframes */ NULL, NULL, /* pin, pout */ 0, /*dither */ }, 0, /* warped */ 0, /* sstrlen */ (char*) NULL, /* sstrbuf */ 1, /* enableMsgAttr */ 0, /* sampsNeeded */ FL(0.0), /* csoundScoreOffsetSeconds_ */ -1, /* inChar_ */ 0, /* isGraphable_ */ 0, /* delayr_stack_depth */ NULL, /* first_delayr */ NULL, /* last_delayr */ { 0L, 0L, 0L, 0L, 0L, 0L }, /* revlpsiz */ 0L, /* revlpsum */ 0.5, /* rndfrac */ NULL, /* logbase2 */ NULL, NULL, /* omacros, smacros */ NULL, /* namedgen */ NULL, /* open_files */ NULL, /* searchPathCache */ NULL, /* sndmemfiles */ NULL, /* reset_list */ NULL, /* pvFileTable */ 0, /* pvNumFiles */ 0, /* pvErrorCode */ // NULL, /* pluginOpcodeFiles */ 0, /* enableHostImplementedAudioIO */ 0, /* MIDI IO */ 0, /* hostRequestedBufferSize */ 0, /* engineStatus */ 0, /* stdin_assign_flg */ 0, /* stdout_assign_flg */ 0, /* orcname_mode */ 0, /* use_only_orchfile */ NULL, /* csmodule_db */ (char*) NULL, /* dl_opcodes_oplibs */ (char*) NULL, /* SF_csd_licence */ (char*) NULL, /* SF_id_title */ (char*) NULL, /* SF_id_copyright */ -1, /* SF_id_scopyright */ (char*) NULL, /* SF_id_software */ (char*) NULL, /* SF_id_artist */ (char*) NULL, /* SF_id_comment */ (char*) NULL, /* SF_id_date */ NULL, /* utility_db */ (int16*) NULL, /* isintab */ NULL, /* lprdaddr */ 0, /* currentLPCSlot */ 0, /* max_lpc_slot */ NULL, /* chn_db */ 1, /* opcodedirWasOK */ 0, /* disable_csd_options */ { 0, { 0U } }, /* randState_ */ 0, /* performState */ 1000, /* ugens4_rand_16 */ 1000, /* ugens4_rand_15 */ NULL, /* schedule_kicked */ (MYFLT*) NULL, /* disprep_fftcoefs */ NULL, /* winEPS_globals */ { /* oparms_ */ 0, /* odebug */ 0, 1, 1, 0, /* sfread, ... */ 0, 0, 0, 0, /* inbufsamps, ... */ 0, /* sfsampsize */ 1, /* displays */ 1, 0, 135, /* graphsoff ... */ 0, 0, /* Beatmode, ... */ 0, 0, /* usingcscore, ... */ 0, 0, 0, 0, /* RTevents, ... */ 0, 0, /* ringbell, ... */ 0, 0, 0, /* rewrt_hdr, ... */ 0.0, /* cmdTempo */ 0.0f, 0.0f, /* sr_override ... */ 0, 0, /* nchnls_override ... */ (char*) NULL, (char*) NULL, NULL, (char*) NULL, (char*) NULL, (char*) NULL, (char*) NULL, (char*) NULL, 0, /* midiKey */ 0, /* midiKeyCps */ 0, /* midiKeyOct */ 0, /* midiKeyPch */ 0, /* midiVelocity */ 0, /* midiVelocityAmp */ 0, /* noDefaultPaths */ 1, /* numThreads */ 0, /* syntaxCheckOnly */ 1, /* useCsdLineCounts */ 0, /* samp acc */ 0, /* realtime */ 0.0, /* 0dbfs override */ 0, /* no exit on compile error */ 0.4, /* vbr quality */ 0, /* ksmps_override */ 0, /* fft_lib */ 0 }, {0, 0, {0}}, /* REMOT_BUF */ NULL, /* remoteGlobals */ 0, 0, /* nchanof, nchanif */ NULL, NULL, /* chanif, chanof */ 0, /* multiThreadedComplete */ NULL, /* multiThreadedThreadInfo */ NULL, /* multiThreadedDag */ NULL, /* barrier1 */ NULL, /* barrier2 */ NULL, /* global_var_lock_root */ NULL, /* global_var_lock_cache */ 0, /* global_var_lock_count */ /* statics from cs_par_orc_semantic_analysis */ NULL, /* instCurr */ NULL, /* instRoot */ 0, /* inInstr */ /* new dag model statics */ 1, /* dag_changed */ 0, /* dag_num_active */ NULL, /* dag_task_map */ NULL, /* dag_task_status */ NULL, /* dag_task_watch */ NULL, /* dag_wlmm */ NULL, /* dag_task_dep */ 100, /* dag_task_max_size */ 0, /* tempStatus */ 1, /* orcLineOffset */ 0, /* scoLineOffset */ NULL, /* csdname */ -1, /* parserUdoflag */ 0, /* parserNamedInstrFlag */ 0, /* tran_nchnlsi */ 0, /* Count of score strings */ 0, /* length of current strings space */ NULL, /* sinetable */ 16384, /* sinesize */ NULL, /* pow2 table */ NULL, /* cps conv table */ NULL, /* output of preprocessor */ NULL, /* output of preprocessor */ {NULL}, /* filedir */ NULL, /* message buffer struct */ 0, /* jumpset */ 0, /* info_message_request */ 0, /* modules loaded */ -1, /* audio system sr */ 0, /* csdebug_data */ kperf_nodebug, /* current kperf function - nodebug by default */ 0, /* which score parser */ NULL, /* symbtab */ 0, /* tseglen */ 1, /* inZero */ NULL, /* msg_queue */ 0, /* msg_queue_wget */ 0, /* msg_queue_wput */ 0, /* msg_queue_rstart */ 0, /* msg_queue_items */ NULL, /* directory for corfiles */ 127, /* aftouch */ /*, NULL */ /* self-reference */ }; void csound_aops_init_tables(CSOUND *cs); typedef struct csInstance_s { CSOUND *csound; struct csInstance_s *nxt; } csInstance_t; /* initialisation state: */ /* 0: not done yet, 1: complete, 2: in progress, -1: failed */ static volatile int init_done = 0; /* chain of allocated Csound instances */ static volatile csInstance_t *instance_list = NULL; /* non-zero if performance should be terminated now */ static volatile int exitNow_ = 0; static void destroy_all_instances(void) { volatile csInstance_t *p; csoundLock(); init_done = -1; /* prevent the creation of any new instances */ if (instance_list == NULL) { csoundUnLock(); return; } csoundUnLock(); csoundSleep(250); while (1) { csoundLock(); p = instance_list; csoundUnLock(); if (p == NULL) { break; } csoundDestroy(p->csound); } } #if defined(ANDROID) || (!defined(LINUX) && !defined(SGI) && \ !defined(__HAIKU__) && !defined(__BEOS__) && \ !defined(__MACH__) && !defined(__EMSCRIPTEN__)) static char *signal_to_string(int sig) { switch(sig) { #ifdef SIGHUP case SIGHUP: return "Hangup"; #endif #ifdef SIGINT case SIGINT: return "Interrupt"; #endif #ifdef SIGQUIT case SIGQUIT: return "Quit"; #endif #ifdef SIGILL case SIGILL: return "Illegal instruction"; #endif #ifdef SIGTRAP case SIGTRAP: return "Trace trap"; #endif #ifdef SIGABRT case SIGABRT: return "Abort"; #endif #ifdef SIGBUS case SIGBUS: return "BUS error"; #endif #ifdef SIGFPE case SIGFPE: return "Floating-point exception"; #endif #ifdef SIGUSR1 case SIGUSR1: return "User-defined signal 1"; #endif #ifdef SIGSEGV case SIGSEGV: return "Segmentation violation"; #endif #ifdef SIGUSR2 case SIGUSR2: return "User-defined signal 2"; #endif #ifdef SIGPIPE case SIGPIPE: return "Broken pipe"; #endif #ifdef SIGALRM case SIGALRM: return "Alarm clock"; #endif #ifdef SIGTERM case SIGTERM: return "Termination"; #endif #ifdef SIGSTKFLT case SIGSTKFLT: return "???"; #endif #ifdef SIGCHLD case SIGCHLD: return "Child status has changed"; #endif #ifdef SIGCONT case SIGCONT: return "Continue"; #endif #ifdef SIGSTOP case SIGSTOP: return "Stop, unblockable"; #endif #ifdef SIGTSTP case SIGTSTP: return "Keyboard stop"; #endif #ifdef SIGTTIN case SIGTTIN: return "Background read from tty"; #endif #ifdef SIGTTOU case SIGTTOU: return "Background write to tty"; #endif #ifdef SIGURG case SIGURG: return "Urgent condition on socket "; #endif #ifdef SIGXCPU case SIGXCPU: return "CPU limit exceeded"; #endif #ifdef SIGXFSZ case SIGXFSZ: return "File size limit exceeded "; #endif #ifdef SIGVTALRM case SIGVTALRM: return "Virtual alarm clock "; #endif #ifdef SIGPROF case SIGPROF: return "Profiling alarm clock"; #endif #ifdef SIGWINCH case SIGWINCH: return "Window size change "; #endif #ifdef SIGIO case SIGIO: return "I/O now possible"; #endif #ifdef SIGPWR case SIGPWR: return "Power failure restart"; #endif default: return "???"; } } #ifdef ANDROID static void psignal_(int sig, char *str) { fprintf(stderr, "%s: %s\n", str, signal_to_string(sig)); } #else # if !defined(__CYGWIN__) static void psignal(int sig, char *str) { fprintf(stderr, "%s: %s\n", str, signal_to_string(sig)); } # endif #endif #elif defined(__BEOS__) static void psignal_(int sig, char *str) { fprintf(stderr, "%s: %s\n", str, strsignal(sig)); } #endif static void signal_handler(int sig) { #if defined(LINUX) && !defined(ANDROID) && !defined(NACL) #include { int j, nptrs; #define SIZE 100 void *buffer[SIZE]; char **strings; nptrs = backtrace(buffer, SIZE); printf("backtrace() returned %d addresses\n", nptrs); /* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO) would produce similar output to the following: */ strings = backtrace_symbols(buffer, nptrs); if (UNLIKELY(strings == NULL)) { perror("backtrace_symbols"); exit(EXIT_FAILURE); } for (j = 0; j < nptrs; j++) printf("%s\n", strings[j]); free(strings); } #endif #if defined(SIGPIPE) if (sig == (int) SIGPIPE) { #ifdef ANDROID psignal_(sig, "Csound ignoring SIGPIPE"); #else psignal(sig, "Csound ignoring SIGPIPE"); #endif return; } #endif #ifdef ANDROID psignal_(sig, "Csound tidy up"); #else psignal(sig, "Csound tidy up"); #endif if ((sig == (int) SIGINT || sig == (int) SIGTERM) && !exitNow_) { exitNow_ = -1; return; } exit(1); } static const int sigs[] = { #if defined(LINUX) || defined(SGI) || defined(sol) || defined(__MACH__) SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGIOT, SIGBUS, SIGFPE, SIGSEGV, SIGPIPE, SIGTERM, SIGXCPU, SIGXFSZ, #elif defined(WIN32) SIGINT, SIGILL, SIGABRT, SIGFPE, SIGSEGV, SIGTERM, #elif defined(__EMX__) SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGTERM, SIGCHLD, #endif -1 }; static void install_signal_handler(void) { unsigned int i; for (i = 0; sigs[i] >= 0; i++) { signal(sigs[i], signal_handler); } } static int getTimeResolution(void); PUBLIC int csoundInitialize(int flags) { int n; do { csoundLock(); n = init_done; switch (n) { case 2: csoundUnLock(); csoundSleep(1); case 0: break; default: csoundUnLock(); return n; } } while (n); init_done = 2; csoundUnLock(); if (getTimeResolution() != 0) { csoundLock(); init_done = -1; csoundUnLock(); return -1; } if (!(flags & CSOUNDINIT_NO_SIGNAL_HANDLER)) { install_signal_handler(); } #if !defined(WIN32) if (!(flags & CSOUNDINIT_NO_ATEXIT)) atexit(destroy_all_instances); #endif csoundLock(); init_done = 1; csoundUnLock(); return 0; } PUBLIC CSOUND *csoundCreate(void *hostdata) { CSOUND *csound; csInstance_t *p; _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); if (init_done != 1) { if (csoundInitialize(0) < 0) return NULL; } csound = (CSOUND*) malloc(sizeof(CSOUND)); if (UNLIKELY(csound == NULL)) return NULL; memcpy(csound, &cenviron_, sizeof(CSOUND)); init_getstring(csound); csound->oparms = &(csound->oparms_); csound->hostdata = hostdata; p = (csInstance_t*) malloc(sizeof(csInstance_t)); if (UNLIKELY(p == NULL)) { free(csound); return NULL; } csoundLock(); p->csound = csound; p->nxt = (csInstance_t*) instance_list; instance_list = p; csoundUnLock(); csoundReset(csound); csound->API_lock = csoundCreateMutex(1); allocate_message_queue(csound); /* NB: as suggested by F Pinot, keep the address of the pointer to CSOUND inside the struct, so it can be cleared later */ //csound->self = &csound; return csound; } /* dummy real time MIDI functions */ int DummyMidiInOpen(CSOUND *csound, void **userData, const char *devName); int DummyMidiRead(CSOUND *csound, void *userData, unsigned char *buf, int nbytes); int DummyMidiOutOpen(CSOUND *csound, void **userData, const char *devName); int DummyMidiWrite(CSOUND *csound, void *userData, const unsigned char *buf, int nbytes); /* random.c */ extern void csound_init_rand(CSOUND *); /* PUBLIC int csoundQueryInterface(const char *name, void **iface, int *version) { if (strcmp(name, "CSOUND") != 0) return 1; *iface = csoundCreate(NULL); *version = csoundGetAPIVersion(); return 0; } */ typedef struct CsoundCallbackEntry_s CsoundCallbackEntry_t; struct CsoundCallbackEntry_s { unsigned int typeMask; CsoundCallbackEntry_t *nxt; void *userData; int (*func)(void *, void *, unsigned int); }; PUBLIC void csoundDestroy(CSOUND *csound) { csInstance_t *p, *prv = NULL; csoundLock(); p = (csInstance_t*) instance_list; while (p != NULL && p->csound != csound) { prv = p; p = p->nxt; } if (p == NULL) { csoundUnLock(); return; } if (prv == NULL) instance_list = p->nxt; else prv->nxt = p->nxt; csoundUnLock(); free(p); reset(csound); if (csound->csoundCallbacks_ != NULL) { CsoundCallbackEntry_t *pp, *nxt; pp = (CsoundCallbackEntry_t*) csound->csoundCallbacks_; do { nxt = pp->nxt; free((void*) pp); pp = nxt; } while (pp != (CsoundCallbackEntry_t*) NULL); } if (csound->API_lock != NULL) { //csoundLockMutex(csound->API_lock); csoundDestroyMutex(csound->API_lock); } /* clear the pointer */ //*(csound->self) = NULL; free((void*) csound); } PUBLIC int csoundGetVersion(void) { return (int) (CS_VERSION * 1000 + CS_SUBVER * 10 + CS_PATCHLEVEL); } PUBLIC int csoundGetAPIVersion(void) { return CS_APIVERSION * 100 + CS_APISUBVER; } PUBLIC void *csoundGetHostData(CSOUND *csound) { return csound->hostdata; } PUBLIC void csoundSetHostData(CSOUND *csound, void *hostData) { csound->hostdata = hostData; } /* * PERFORMANCE */ extern int sensevents(CSOUND *); /** * perform currently active instrs for one kperiod * & send audio result to output buffer * returns non-zero if this kperiod was skipped */ static int getThreadIndex(CSOUND *csound, void *threadId) { int index = 0; THREADINFO *current = csound->multiThreadedThreadInfo; if (current == NULL) { return -1; } while (current != NULL) { #ifdef HAVE_PTHREAD if (pthread_equal(*(pthread_t *)threadId, *(pthread_t *)current->threadId)) #elif defined(WIN32) DWORD* d = (DWORD*)threadId; if (*d == GetThreadId((HANDLE)current->threadId)) #else // FIXME - need to verify this works... if (threadId == current->threadId) #endif return index; index++; current = current->next; } return -1; } #if 0 static int getNumActive(INSDS *start, INSDS *end) { INSDS *current = start; int counter = 1; while (((current = current->nxtact) != NULL) && current != end) { counter++; } return counter; } #endif inline void advanceINSDSPointer(INSDS ***start, int num) { int i; INSDS *s = **start; if (s == NULL) return; for (i = 0; i < num; i++) { s = s->nxtact; if (s == NULL) { **start = NULL; return; } } **start = s; } int dag_get_task(CSOUND *csound, int index, int numThreads, int next_task); int dag_end_task(CSOUND *csound, int task); void dag_build(CSOUND *csound, INSDS *chain); void dag_reinit(CSOUND *csound); inline static int nodePerf(CSOUND *csound, int index, int numThreads) { INSDS *insds = NULL; OPDS *opstart = NULL; int played_count = 0; int which_task; INSDS **task_map = (INSDS**)csound->dag_task_map; double time_end; #define INVALID (-1) #define WAIT (-2) int next_task = INVALID; IGN(index); while (1) { int done; which_task = dag_get_task(csound, index, numThreads, next_task); //printf("******** Select task %d\n", which_task); if (which_task==WAIT) continue; if (which_task==INVALID) return played_count; /* VL: the validity of icurTime needs to be checked */ time_end = (csound->ksmps+csound->icurTime)/csound->esr; insds = task_map[which_task]; if (insds->offtim > 0 && time_end > insds->offtim){ /* this is the last cycle of performance */ insds->ksmps_no_end = insds->no_end; } #ifdef HAVE_ATOMIC_BUILTIN done = __sync_fetch_and_add((int *) &insds->init_done, 0); #else done = insds->init_done; #endif if (done) { opstart = (OPDS*)task_map[which_task]; if (insds->ksmps == csound->ksmps) { insds->spin = csound->spin; insds->spout = csound->spraw; insds->kcounter = csound->kcounter; while ((opstart = opstart->nxtp) != NULL) { /* In case of jumping need this repeat of opstart */ opstart->insdshead->pds = opstart; (*opstart->opadr)(csound, opstart); /* run each opcode */ opstart = opstart->insdshead->pds; } } else { int i, n = csound->nspout, start = 0; int lksmps = insds->ksmps; int incr = csound->nchnls*lksmps; int offset = insds->ksmps_offset; int early = insds->ksmps_no_end; OPDS *opstart; insds->spin = csound->spin; insds->spout = csound->spraw; insds->kcounter = csound->kcounter*csound->ksmps; /* we have to deal with sample-accurate code whole CS_KSMPS blocks are offset here, the remainder is left to each opcode to deal with. */ while (offset >= lksmps) { offset -= lksmps; start += csound->nchnls; } insds->ksmps_offset = offset; if (UNLIKELY(early)) { n -= (early*csound->nchnls); insds->ksmps_no_end = early % lksmps; } for (i=start; i < n; i+=incr, insds->spin+=incr, insds->spout+=incr) { opstart = (OPDS*) insds; while ((opstart = opstart->nxtp) != NULL) { opstart->insdshead->pds = opstart; (*opstart->opadr)(csound, opstart); /* run each opcode */ opstart = opstart->insdshead->pds; } insds->kcounter++; } } insds->ksmps_offset = 0; /* reset sample-accuracy offset */ insds->ksmps_no_end = 0; /* reset end of loop samples */ played_count++; } //printf("******** finished task %d\n", which_task); next_task = dag_end_task(csound, which_task); } return played_count; } inline static void make_interleave(CSOUND *csound) { uint32_t nsmps = csound->ksmps, i, j, k=0; MYFLT *spout = csound->spout; if (!csound->spoutactive) { memset(spout, '\0', csound->nspout*sizeof(MYFLT)); } else { for (j=0; jnchnls; i++) { // Will be copy t ad when complette spout[k + i] = csound->spraw[i*nsmps+j]; } k += csound->nchnls; } } } unsigned long kperfThread(void * cs) { //INSDS *start; CSOUND *csound = (CSOUND *)cs; void *threadId; int index; int numThreads; _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); csound->WaitBarrier(csound->barrier2); threadId = csound->GetCurrentThreadID(); index = getThreadIndex(csound, threadId); numThreads = csound->oparms->numThreads; //start = NULL; csound->Message(csound, Str("Multithread performance:thread %d of " "%d starting.\n"), /* start ? start->insno : */ index+1, numThreads); if (UNLIKELY(index < 0)) { csound->Die(csound, Str("Bad ThreadId")); return ULONG_MAX; } index++; while (1) { csound->WaitBarrier(csound->barrier1); // FIXME:PTHREAD_WORK - need to check if this is necessary and, if so, // use some other kind of locking mechanism as it isn't clear why a //global mutex would be necessary versus a per-CSOUND instance mutex /*csound_global_mutex_lock();*/ if (csound->multiThreadedComplete == 1) { /*csound_global_mutex_unlock();*/ free(threadId); return 0UL; } /*csound_global_mutex_unlock();*/ nodePerf(csound, index, numThreads); csound->WaitBarrier(csound->barrier2); } } int kperf_nodebug(CSOUND *csound) { INSDS *ip; /* update orchestra time */ csound->kcounter = ++(csound->global_kcounter); csound->icurTime += csound->ksmps; csound->curBeat += csound->curBeat_inc; /* call message_dequeue to run API calls */ message_dequeue(csound); /* if skipping time on request by 'a' score statement: */ if (UNLIKELY(UNLIKELY(csound->advanceCnt))) { csound->advanceCnt--; return 1; } /* if i-time only, return now */ if (UNLIKELY(csound->initonly)) return 1; /* PC GUI needs attention, but avoid excessively frequent */ /* calls of csoundYield() */ if (UNLIKELY(--(csound->evt_poll_cnt) < 0)) { csound->evt_poll_cnt = csound->evt_poll_maxcnt; if (UNLIKELY(!csoundYield(csound))) csound->LongJmp(csound, 1); } /* for one kcnt: */ if (csound->oparms_.sfread) /* if audio_infile open */ csound->spinrecv(csound); /* fill the spin buf */ csound->spoutactive = 0; /* make spout inactive */ /* clear spout */ memset(csound->spout, 0, csound->nspout*sizeof(MYFLT)); memset(csound->spraw, 0, csound->nspout*sizeof(MYFLT)); ip = csound->actanchor.nxtact; if (ip != NULL) { /* There are 2 partitions of work: 1st by inso, 2nd by inso count / thread count. */ if (csound->multiThreadedThreadInfo != NULL) { if (csound->dag_changed) dag_build(csound, ip); else dag_reinit(csound); /* set to initial state */ /* process this partition */ csound->WaitBarrier(csound->barrier1); (void) nodePerf(csound, 0, 1); /* wait until partition is complete */ csound->WaitBarrier(csound->barrier2); csound->multiThreadedDag = NULL; } else { int done; double time_end = (csound->ksmps+csound->icurTime)/csound->esr; while (ip != NULL) { /* for each instr active: */ INSDS *nxt = ip->nxtact; if (UNLIKELY(csound->oparms->sampleAccurate && ip->offtim > 0 && time_end > ip->offtim)) { /* this is the last cycle of performance */ // csound->Message(csound, "last cycle %d: %f %f %d\n", // ip->insno, csound->icurTime/csound->esr, // ip->offtim, ip->no_end); ip->ksmps_no_end = ip->no_end; } #ifdef HAVE_ATOMIC_BUILTIN done = __sync_fetch_and_add((int *) &ip->init_done, 0); #else done = ip->init_done; #endif if (done == 1) {/* if init-pass has been done */ OPDS *opstart = (OPDS*) ip; ip->spin = csound->spin; ip->spout = csound->spraw; ip->kcounter = csound->kcounter; if (ip->ksmps == csound->ksmps) { while ((opstart = opstart->nxtp) != NULL && ip->actflg) { opstart->insdshead->pds = opstart; (*opstart->opadr)(csound, opstart); /* run each opcode */ opstart = opstart->insdshead->pds; } } else { int i, n = csound->nspout, start = 0; int lksmps = ip->ksmps; int incr = csound->nchnls*lksmps; int offset = ip->ksmps_offset; int early = ip->ksmps_no_end; OPDS *opstart; ip->spin = csound->spin; ip->spout = csound->spraw; ip->kcounter = csound->kcounter*csound->ksmps/lksmps; /* we have to deal with sample-accurate code whole CS_KSMPS blocks are offset here, the remainder is left to each opcode to deal with. */ while (offset >= lksmps) { offset -= lksmps; start += csound->nchnls; } ip->ksmps_offset = offset; if (UNLIKELY(early)) { n -= (early*csound->nchnls); ip->ksmps_no_end = early % lksmps; } for (i=start; i < n; i+=incr, ip->spin+=incr, ip->spout+=incr) { opstart = (OPDS*) ip; while ((opstart = opstart->nxtp) != NULL && ip->actflg) { opstart->insdshead->pds = opstart; (*opstart->opadr)(csound, opstart); /* run each opcode */ opstart = opstart->insdshead->pds; } ip->kcounter++; } } } /*else csound->Message(csound, "time %f \n", csound->kcounter/csound->ekr);*/ ip->ksmps_offset = 0; /* reset sample-accuracy offset */ ip->ksmps_no_end = 0; /* reset end of loop samples */ ip = nxt; /* but this does not allow for all deletions */ } } } if (!csound->spoutactive) { /* results now in spout? */ memset(csound->spout, 0, csound->nspout * sizeof(MYFLT)); memset(csound->spraw, 0, csound->nspout * sizeof(MYFLT)); } make_interleave(csound); csound->spoutran(csound); /* send to audio_out */ //#ifdef ANDROID //struct timespec ts; //clock_gettime(CLOCK_MONOTONIC, &ts); //csound->Message(csound, "kperf kcount, %d,%d.%06d\n", // csound->kcounter, ts.tv_sec, ts.tv_nsec/1000); //#endif return 0; } static inline void opcode_perf_debug(CSOUND *csound, csdebug_data_t *data, INSDS *ip) { OPDS *opstart = (OPDS*) ip; while ((opstart = opstart->nxtp) != NULL) { /* check if we have arrived at a line breakpoint */ bkpt_node_t *bp_node = data->bkpt_anchor->next; if (data->debug_opcode_ptr) { opstart = data->debug_opcode_ptr; data->debug_opcode_ptr = NULL; } int linenum = opstart->optext->t.linenum; while (bp_node) { if (bp_node->instr == ip->p1.value || (bp_node->instr == 0)) { if ((bp_node->line) == linenum) { /* line matches */ if (bp_node->count < 2) { /* skip of 0 or 1 has the same effect */ if (data->debug_opcode_ptr != opstart) { /* did we just stop here */ data->debug_instr_ptr = ip; data->debug_opcode_ptr = opstart; data->status = CSDEBUG_STATUS_STOPPED; data->cur_bkpt = bp_node; csoundDebuggerBreakpointReached(csound); bp_node->count = bp_node->skip; return; } else { data->debug_opcode_ptr = NULL; /* if just stopped here-continue */ } } else { bp_node->count--; } } } bp_node = bp_node->next; } opstart->insdshead->pds = opstart; (*opstart->opadr)(csound, opstart); /* run each opcode */ opstart = opstart->insdshead->pds; } } static inline void process_debug_buffers(CSOUND *csound, csdebug_data_t *data) { bkpt_node_t *bkpt_node; while (csoundReadCircularBuffer(csound, data->bkpt_buffer, &bkpt_node, 1) == 1) { if (bkpt_node->mode == CSDEBUG_BKPT_CLEAR_ALL) { bkpt_node_t *n; while (data->bkpt_anchor->next) { n = data->bkpt_anchor->next; data->bkpt_anchor->next = n->next; csound->Free(csound, n); /* TODO this should be moved from kperf to a non-realtime context */ } csound->Free(csound, bkpt_node); } else if (bkpt_node->mode == CSDEBUG_BKPT_DELETE) { bkpt_node_t *n = data->bkpt_anchor->next; bkpt_node_t *prev = data->bkpt_anchor; while (n) { if (n->line == bkpt_node->line && n->instr == bkpt_node->instr) { prev->next = n->next; csound->Free(csound, n); /* TODO this should be moved from kperf to a non-realtime context */ n = prev->next; continue; } prev = n; n = n->next; } // csound->Free(csound, bkpt_node); /* TODO move to non rt context */ } else { // FIXME sort list to optimize bkpt_node->next = data->bkpt_anchor->next; data->bkpt_anchor->next = bkpt_node; } } } int kperf_debug(CSOUND *csound) { INSDS *ip; csdebug_data_t *data = (csdebug_data_t *) csound->csdebug_data; /* call message_dequeue to run API calls */ message_dequeue(csound); if (!data || data->status != CSDEBUG_STATUS_STOPPED) { /* update orchestra time */ csound->kcounter = ++(csound->global_kcounter); csound->icurTime += csound->ksmps; csound->curBeat += csound->curBeat_inc; } /* if skipping time on request by 'a' score statement: */ if (UNLIKELY(csound->advanceCnt)) { csound->advanceCnt--; return 1; } /* if i-time only, return now */ if (UNLIKELY(csound->initonly)) return 1; /* PC GUI needs attention, but avoid excessively frequent */ /* calls of csoundYield() */ if (UNLIKELY(--(csound->evt_poll_cnt) < 0)) { csound->evt_poll_cnt = csound->evt_poll_maxcnt; if (UNLIKELY(!csoundYield(csound))) csound->LongJmp(csound, 1); } if (data) { /* process debug commands*/ process_debug_buffers(csound, data); } if (!data || data->status == CSDEBUG_STATUS_RUNNING) { /* for one kcnt: */ if (csound->oparms_.sfread) /* if audio_infile open */ csound->spinrecv(csound); /* fill the spin buf */ csound->spoutactive = 0; /* make spout inactive */ /* clear spout */ memset(csound->spout, 0, csound->nspout*sizeof(MYFLT)); memset(csound->spraw, 0, csound->nspout*sizeof(MYFLT)); } ip = csound->actanchor.nxtact; /* Process debugger commands */ debug_command_t command = CSDEBUG_CMD_NONE; if (data) { csoundReadCircularBuffer(csound, data->cmd_buffer, &command, 1); if (command == CSDEBUG_CMD_STOP && data->status != CSDEBUG_STATUS_STOPPED) { data->debug_instr_ptr = ip; data->status = CSDEBUG_STATUS_STOPPED; csoundDebuggerBreakpointReached(csound); } if (command == CSDEBUG_CMD_CONTINUE && data->status == CSDEBUG_STATUS_STOPPED) { if (data->cur_bkpt->skip <= 2) data->cur_bkpt->count = 2; data->status = CSDEBUG_STATUS_RUNNING; if (data->debug_instr_ptr) { /* if not NULL, resume from last active */ ip = data->debug_instr_ptr; data->debug_instr_ptr = NULL; } } if (command == CSDEBUG_CMD_NEXT && data->status == CSDEBUG_STATUS_STOPPED) { data->status = CSDEBUG_STATUS_NEXT; } } if (ip != NULL && data != NULL && (data->status != CSDEBUG_STATUS_STOPPED) ) { /* There are 2 partitions of work: 1st by inso, 2nd by inso count / thread count. */ if (csound->multiThreadedThreadInfo != NULL) { if (csound->dag_changed) dag_build(csound, ip); else dag_reinit(csound); /* set to initial state */ /* process this partition */ csound->WaitBarrier(csound->barrier1); (void) nodePerf(csound, 0, 1); /* wait until partition is complete */ csound->WaitBarrier(csound->barrier2); csound->multiThreadedDag = NULL; } else { int done; double time_end = (csound->ksmps+csound->icurTime)/csound->esr; while (ip != NULL) { /* for each instr active: */ if (UNLIKELY(csound->oparms->sampleAccurate && ip->offtim > 0 && time_end > ip->offtim)) { /* this is the last cycle of performance */ // csound->Message(csound, "last cycle %d: %f %f %d\n", // ip->insno, csound->icurTime/csound->esr, // ip->offtim, ip->no_end); ip->ksmps_no_end = ip->no_end; } #ifdef HAVE_ATOMIC_BUILTIN done = __sync_fetch_and_add((int *) &ip->init_done, 0); #else done = ip->init_done; #endif if (done == 1) {/* if init-pass has been done */ /* check if next command pending and we are on the first instrument in the chain */ /* coverity says data already dereferenced by here */ if (/*data &&*/ data->status == CSDEBUG_STATUS_NEXT) { if (data->debug_instr_ptr == NULL) { data->debug_instr_ptr = ip; data->debug_opcode_ptr = NULL; data->status = CSDEBUG_STATUS_STOPPED; csoundDebuggerBreakpointReached(csound); return 0; } else { ip = data->debug_instr_ptr; data->debug_instr_ptr = NULL; } } /* check if we have arrived at an instrument breakpoint */ bkpt_node_t *bp_node = data->bkpt_anchor->next; while (bp_node && data->status != CSDEBUG_STATUS_NEXT) { if (bp_node->instr == ip->p1.value && (bp_node->line == -1) ) { if (bp_node->count < 2) { /* skip of 0 or 1 has the same effect */ data->debug_instr_ptr = ip; data->debug_opcode_ptr = NULL; data->cur_bkpt = bp_node; data->status = CSDEBUG_STATUS_STOPPED; csoundDebuggerBreakpointReached(csound); bp_node->count = bp_node->skip; return 0; } else { bp_node->count--; } } bp_node = bp_node->next; } ip->spin = csound->spin; ip->spout = csound->spraw; ip->kcounter = csound->kcounter; if (ip->ksmps == csound->ksmps) { opcode_perf_debug(csound, data, ip); } else { /* when instrument has local ksmps */ int i, n = csound->nspout, start = 0; int lksmps = ip->ksmps; int incr = csound->nchnls*lksmps; int offset = ip->ksmps_offset; int early = ip->ksmps_no_end; ip->spin = csound->spin; ip->spout = csound->spraw; ip->kcounter = csound->kcounter*csound->ksmps/lksmps; /* we have to deal with sample-accurate code whole CS_KSMPS blocks are offset here, the remainder is left to each opcode to deal with. */ while (offset >= lksmps) { offset -= lksmps; start += csound->nchnls; } ip->ksmps_offset = offset; if (UNLIKELY(early)) { n -= (early*csound->nchnls); ip->ksmps_no_end = early % lksmps; } for (i=start; i < n; i+=incr, ip->spin+=incr, ip->spout+=incr) { opcode_perf_debug(csound, data, ip); ip->kcounter++; } } } ip->ksmps_offset = 0; /* reset sample-accuracy offset */ ip->ksmps_no_end = 0; /* reset end of loop samples */ ip = ip->nxtact; /* but this does not allow for all deletions */ if (/*data &&*/ data->status == CSDEBUG_STATUS_NEXT) { data->debug_instr_ptr = ip; /* we have reached the next instrument. Break */ data->debug_opcode_ptr = NULL; if (ip != NULL) { /* must defer break until next kperf */ data->status = CSDEBUG_STATUS_STOPPED; csoundDebuggerBreakpointReached(csound); return 0; } } } } } if (!data || data->status != CSDEBUG_STATUS_STOPPED) { if (!csound->spoutactive) { /* results now in spout? */ memset(csound->spout, 0, csound->nspout * sizeof(MYFLT)); memset(csound->spraw, 0, csound->nspout * sizeof(MYFLT)); } else make_interleave(csound); csound->spoutran(csound); /* send to audio_out */ } return 0; } int csoundReadScoreInternal(CSOUND *csound, const char *str) { OPARMS *O = csound->oparms; /* protect resource */ if (csound->scorestr != NULL && csound->scorestr->body != NULL) corfile_rewind(csound->scorestr); csound->scorestr = corfile_create_w(csound); corfile_puts(csound, (char *)str, csound->scorestr); //#ifdef SCORE_PARSER corfile_puts(csound, "\n#exit\n", csound->scorestr); //#endif corfile_flush(csound, csound->scorestr); /* copy sorted score name */ if (csound->scstr == NULL && (csound->engineStatus & CS_STATE_COMP) == 0) { scsortstr(csound, csound->scorestr); O->playscore = csound->scstr; //corfile_rm(csound, &(csound->scorestr)); //printf("%s\n", O->playscore->body); } else { char *sc = scsortstr(csound, csound->scorestr); //printf("%s \n", sc); csoundInputMessageInternal(csound, (const char *) sc); csound->Free(csound, sc); corfile_rm(csound, &(csound->scorestr)); } return CSOUND_SUCCESS; } PUBLIC int csoundPerformKsmps(CSOUND *csound) { int done; /* VL: 1.1.13 if not compiled (csoundStart() not called) */ if (UNLIKELY(!(csound->engineStatus & CS_STATE_COMP))) { csound->Warning(csound, Str("Csound not ready for performance: csoundStart() " "has not been called \n")); return CSOUND_ERROR; } if (csound->jumpset == 0) { int returnValue; csound->jumpset = 1; /* setup jmp for return after an exit() */ if (UNLIKELY((returnValue = setjmp(csound->exitjmp)))) return ((returnValue - CSOUND_EXITJMP_SUCCESS) | CSOUND_EXITJMP_SUCCESS); } csoundLockMutex(csound->API_lock); do { done = sensevents(csound); if (UNLIKELY(done)) { csoundUnlockMutex(csound->API_lock); csoundMessage(csound, Str("Score finished in csoundPerformKsmps() with %d.\n"), done); return done; } } while (csound->kperf(csound)); csoundUnlockMutex(csound->API_lock); return 0; } static int csoundPerformKsmpsInternal(CSOUND *csound) { int done; int returnValue; /* VL: 1.1.13 if not compiled (csoundStart() not called) */ if (UNLIKELY(!(csound->engineStatus & CS_STATE_COMP))) { csound->Warning(csound, Str("Csound not ready for performance: csoundStart() " "has not been called \n")); return CSOUND_ERROR; } /* setup jmp for return after an exit() */ if (UNLIKELY((returnValue = setjmp(csound->exitjmp)))) { #ifndef MACOSX csoundMessage(csound, Str("Early return from csoundPerformKsmps().\n")); #endif return ((returnValue - CSOUND_EXITJMP_SUCCESS) | CSOUND_EXITJMP_SUCCESS); } do { if (UNLIKELY((done = sensevents(csound)))) { csoundMessage(csound, Str("Score finished in csoundPerformKsmpsInternal().\n")); return done; } } while (csound->kperf(csound)); return 0; } /* external host's outbuffer passed in csoundPerformBuffer() */ PUBLIC int csoundPerformBuffer(CSOUND *csound) { int returnValue; int done; /* VL: 1.1.13 if not compiled (csoundStart() not called) */ if (UNLIKELY(!(csound->engineStatus & CS_STATE_COMP))) { csound->Warning(csound, Str("Csound not ready for performance: csoundStart() " "has not been called \n")); return CSOUND_ERROR; } /* Setup jmp for return after an exit(). */ if (UNLIKELY((returnValue = setjmp(csound->exitjmp)))) { #ifndef MACOSX csoundMessage(csound, Str("Early return from csoundPerformBuffer().\n")); #endif return ((returnValue - CSOUND_EXITJMP_SUCCESS) | CSOUND_EXITJMP_SUCCESS); } csound->sampsNeeded += csound->oparms_.outbufsamps; while (csound->sampsNeeded > 0) { csoundLockMutex(csound->API_lock); do { if (UNLIKELY((done = sensevents(csound)))){ csoundUnlockMutex(csound->API_lock); return done; } } while (csound->kperf(csound)); csoundUnlockMutex(csound->API_lock); csound->sampsNeeded -= csound->nspout; } return 0; } /* perform an entire score */ PUBLIC int csoundPerform(CSOUND *csound) { int done; int returnValue; /* VL: 1.1.13 if not compiled (csoundStart() not called) */ if (UNLIKELY(!(csound->engineStatus & CS_STATE_COMP))) { csound->Warning(csound, Str("Csound not ready for performance: csoundStart() " "has not been called \n")); return CSOUND_ERROR; } csound->performState = 0; /* setup jmp for return after an exit() */ if (UNLIKELY((returnValue = setjmp(csound->exitjmp)))) { #ifndef MACOSX csoundMessage(csound, Str("Early return from csoundPerform().\n")); #endif return ((returnValue - CSOUND_EXITJMP_SUCCESS) | CSOUND_EXITJMP_SUCCESS); } do { csoundLockMutex(csound->API_lock); do { if (UNLIKELY((done = sensevents(csound)))) { csoundMessage(csound, Str("Score finished in csoundPerform().\n")); csoundUnlockMutex(csound->API_lock); if (csound->oparms->numThreads > 1) { csound->multiThreadedComplete = 1; csound->WaitBarrier(csound->barrier1); } return done; } } while (csound->kperf(csound)); csoundUnlockMutex(csound->API_lock); } while ((unsigned char) csound->performState == (unsigned char) '\0'); csoundMessage(csound, Str("csoundPerform(): stopped.\n")); csound->performState = 0; return 0; } /* stop a csoundPerform() running in another thread */ PUBLIC void *csoundGetNamedGens(CSOUND *csound) { return csound->namedgen; } PUBLIC void csoundStop(CSOUND *csound) { csound->performState = -1; } /* * ATTRIBUTES */ PUBLIC int64_t csoundGetCurrentTimeSamples(CSOUND *csound){ return csound->icurTime; } PUBLIC MYFLT csoundGetSr(CSOUND *csound) { return csound->esr; } PUBLIC MYFLT csoundGetKr(CSOUND *csound) { return csound->ekr; } PUBLIC uint32_t csoundGetKsmps(CSOUND *csound) { return csound->ksmps; } PUBLIC uint32_t csoundGetNchnls(CSOUND *csound) { return csound->nchnls; } PUBLIC uint32_t csoundGetNchnlsInput(CSOUND *csound) { if (csound->inchnls > 0) return (uint32_t) csound->inchnls; else return csound->nchnls; } PUBLIC MYFLT csoundGet0dBFS(CSOUND *csound) { return csound->e0dbfs; } PUBLIC long csoundGetInputBufferSize(CSOUND *csound) { return csound->oparms_.inbufsamps; } PUBLIC long csoundGetOutputBufferSize(CSOUND *csound) { return csound->oparms_.outbufsamps; } PUBLIC MYFLT *csoundGetSpin(CSOUND *csound) { return csound->spin; } PUBLIC void csoundSetSpinSample(CSOUND *csound, int frame, int channel, MYFLT sample) { int index = (frame * csound->inchnls) + channel; csound->spin[index] = sample; } PUBLIC void csoundClearSpin(CSOUND *csound) { memset(csound->spin, 0, sizeof(MYFLT)*csound->ksmps*csound->nchnls); } PUBLIC void csoundAddSpinSample(CSOUND *csound, int frame, int channel, MYFLT sample) { int index = (frame * csound->inchnls) + channel; csound->spin[index] += sample; } PUBLIC MYFLT *csoundGetSpout(CSOUND *csound) { return csound->spout; } PUBLIC MYFLT csoundGetSpoutSample(CSOUND *csound, int frame, int channel) { int index = (frame * csound->nchnls) + channel; return csound->spout[index]; } PUBLIC const char *csoundGetOutputName(CSOUND *csound) { return (const char*) csound->oparms_.outfilename; } /** * Calling this function with a non-zero will disable all default * handling of sound I/O by the Csound library, allowing the host * application to use the spin/enableHostImplementedAudioIO = state; csound->hostRequestedBufferSize = (bufSize > 0 ? bufSize : 0); } PUBLIC void csoundSetHostImplementedMIDIIO(CSOUND *csound, int state) { csound->enableHostImplementedMIDIIO = state; } PUBLIC double csoundGetScoreTime(CSOUND *csound) { double curtime = csound->icurTime; double esr = csound->esr; return curtime/esr; } /* * SCORE HANDLING */ PUBLIC int csoundIsScorePending(CSOUND *csound) { return csound->csoundIsScorePending_; } PUBLIC void csoundSetScorePending(CSOUND *csound, int pending) { csound->csoundIsScorePending_ = pending; } PUBLIC void csoundSetScoreOffsetSeconds(CSOUND *csound, MYFLT offset) { double aTime; MYFLT prv = (MYFLT) csound->csoundScoreOffsetSeconds_; csound->csoundScoreOffsetSeconds_ = offset; if (offset < FL(0.0)) return; /* if csoundCompile() was not called yet, just store the offset */ if (!(csound->engineStatus & CS_STATE_COMP)) return; /* otherwise seek to the requested time now */ aTime = (double) offset - (csound->icurTime/csound->esr); if (aTime < 0.0 || offset < prv) { csoundRewindScore(csound); /* will call csoundSetScoreOffsetSeconds */ return; } if (aTime > 0.0) { EVTBLK evt; memset(&evt, 0, sizeof(EVTBLK)); evt.strarg = NULL; evt.scnt = 0; evt.opcod = 'a'; evt.pcnt = 3; evt.p[2] = evt.p[1] = FL(0.0); evt.p[3] = (MYFLT) aTime; insert_score_event_at_sample(csound, &evt, csound->icurTime); } } PUBLIC MYFLT csoundGetScoreOffsetSeconds(CSOUND *csound) { return csound->csoundScoreOffsetSeconds_; } extern void musmon_rewind_score(CSOUND *csound); /* musmon.c */ extern void midifile_rewind_score(CSOUND *csound); /* midifile.c */ PUBLIC void csoundRewindScore(CSOUND *csound) { musmon_rewind_score(csound); if (csound->oparms->FMidiname != NULL) midifile_rewind_score(csound); } PUBLIC void csoundSetCscoreCallback(CSOUND *p, void (*cscoreCallback)(CSOUND *)) { p->cscoreCallback_ = (cscoreCallback != NULL ? cscoreCallback : cscore_); } static void csoundDefaultMessageCallback(CSOUND *csound, int attr, const char *format, va_list args) { #if defined(WIN32) switch (attr & CSOUNDMSG_TYPE_MASK) { case CSOUNDMSG_ERROR: case CSOUNDMSG_WARNING: case CSOUNDMSG_REALTIME: vfprintf(stderr, format, args); break; default: vfprintf(stdout, format, args); } #else FILE *fp = stderr; if ((attr & CSOUNDMSG_TYPE_MASK) == CSOUNDMSG_STDOUT) fp = stdout; if (!attr || !csound->enableMsgAttr) { vfprintf(fp, format, args); return; } if ((attr & CSOUNDMSG_TYPE_MASK) == CSOUNDMSG_ORCH) if (attr & CSOUNDMSG_BG_COLOR_MASK) fprintf(fp, "\033[4%cm", ((attr & 0x70) >> 4) + '0'); if (attr & CSOUNDMSG_FG_ATTR_MASK) { if (attr & CSOUNDMSG_FG_BOLD) fprintf(fp, "\033[1m"); if (attr & CSOUNDMSG_FG_UNDERLINE) fprintf(fp, "\033[4m"); } if (attr & CSOUNDMSG_FG_COLOR_MASK) fprintf(fp, "\033[3%cm", (attr & 7) + '0'); vfprintf(fp, format, args); fprintf(fp, "\033[m"); #endif } PUBLIC void csoundSetDefaultMessageCallback( void (*csoundMessageCallback)(CSOUND *csound, int attr, const char *format, va_list args)) { if (csoundMessageCallback) { msgcallback_ = csoundMessageCallback; } else { msgcallback_ = csoundDefaultMessageCallback; } } PUBLIC void csoundSetMessageCallback(CSOUND *csound, void (*csoundMessageCallback)(CSOUND *csound, int attr, const char *format, va_list args)) { /* Protect against a null callback. */ if (csoundMessageCallback) { csound->csoundMessageCallback_ = csoundMessageCallback; } else { csound->csoundMessageCallback_ = csoundDefaultMessageCallback; } } PUBLIC void csoundMessageV(CSOUND *csound, int attr, const char *format, va_list args) { csound->csoundMessageCallback_(csound, attr, format, args); } PUBLIC void csoundMessage(CSOUND *csound, const char *format, ...) { va_list args; va_start(args, format); csound->csoundMessageCallback_(csound, 0, format, args); va_end(args); } PUBLIC void csoundMessageS(CSOUND *csound, int attr, const char *format, ...) { va_list args; va_start(args, format); csound->csoundMessageCallback_(csound, attr, format, args); va_end(args); } void csoundDie(CSOUND *csound, const char *msg, ...) { va_list args; va_start(args, msg); csound->ErrMsgV(csound, (char*) 0, msg, args); va_end(args); csound->perferrcnt++; csound->LongJmp(csound, 1); } void csoundWarning(CSOUND *csound, const char *msg, ...) { va_list args; if (!(csound->oparms_.msglevel & WARNMSG)) return; csoundMessageS(csound, CSOUNDMSG_WARNING, Str("WARNING: ")); va_start(args, msg); csound->csoundMessageCallback_(csound, CSOUNDMSG_WARNING, msg, args); va_end(args); csoundMessageS(csound, CSOUNDMSG_WARNING, "\n"); } void csoundDebugMsg(CSOUND *csound, const char *msg, ...) { va_list args; if (!(csound->oparms_.odebug)) return; va_start(args, msg); csound->csoundMessageCallback_(csound, 0, msg, args); va_end(args); csoundMessage(csound, "\n"); } void csoundErrorMsg(CSOUND *csound, const char *msg, ...) { va_list args; va_start(args, msg); csound->csoundMessageCallback_(csound, CSOUNDMSG_ERROR, msg, args); va_end(args); csound->MessageS(csound, CSOUNDMSG_ERROR, "\n"); } void csoundErrMsgV(CSOUND *csound, const char *hdr, const char *msg, va_list args) { if (hdr != NULL) csound->MessageS(csound, CSOUNDMSG_ERROR, "%s", hdr); csound->csoundMessageCallback_(csound, CSOUNDMSG_ERROR, msg, args); csound->MessageS(csound, CSOUNDMSG_ERROR, "\n"); } void csoundLongJmp(CSOUND *csound, int retval) { int n = CSOUND_EXITJMP_SUCCESS; n = (retval < 0 ? n + retval : n - retval) & (CSOUND_EXITJMP_SUCCESS - 1); if (!n) n = CSOUND_EXITJMP_SUCCESS; csound->curip = NULL; csound->ids = NULL; csound->reinitflag = 0; csound->tieflag = 0; csound->perferrcnt += csound->inerrcnt; csound->inerrcnt = 0; csound->engineStatus |= CS_STATE_JMP; longjmp(csound->exitjmp, n); } PUBLIC void csoundSetMessageLevel(CSOUND *csound, int messageLevel) { csound->oparms_.msglevel = messageLevel; } PUBLIC int csoundGetMessageLevel(CSOUND *csound) { return csound->oparms_.msglevel; } PUBLIC void csoundKeyPress(CSOUND *csound, char c) { csound->inChar_ = (int) ((unsigned char) c); } /* * CONTROL AND EVENTS */ PUBLIC void csoundSetInputChannelCallback(CSOUND *csound, channelCallback_t inputChannelCalback) { csound->InputChannelCallback_ = inputChannelCalback; } PUBLIC void csoundSetOutputChannelCallback(CSOUND *csound, channelCallback_t outputChannelCalback) { csound->OutputChannelCallback_ = outputChannelCalback; } int csoundScoreEventInternal(CSOUND *csound, char type, const MYFLT *pfields, long numFields) { EVTBLK evt; int i; int ret; memset(&evt, 0, sizeof(EVTBLK)); evt.strarg = NULL; evt.scnt = 0; evt.opcod = type; evt.pcnt = (int16) numFields; for (i = 0; i < (int) numFields; i++) evt.p[i + 1] = pfields[i]; ret = insert_score_event_at_sample(csound, &evt, csound->icurTime); return ret; } int csoundScoreEventAbsoluteInternal(CSOUND *csound, char type, const MYFLT *pfields, long numFields, double time_ofs) { EVTBLK evt; int i; int ret; memset(&evt, 0, sizeof(EVTBLK)); evt.strarg = NULL; evt.scnt = 0; evt.opcod = type; evt.pcnt = (int16) numFields; for (i = 0; i < (int) numFields; i++) evt.p[i + 1] = pfields[i]; ret = insert_score_event(csound, &evt, time_ofs); return ret; } /* * REAL-TIME AUDIO */ /* dummy functions for the case when no real-time audio module is available */ static double *get_dummy_rtaudio_globals(CSOUND *csound) { double *p; p = (double*) csound->QueryGlobalVariable(csound, "__rtaudio_null_state"); if (p == NULL) { if (UNLIKELY(csound->CreateGlobalVariable(csound, "__rtaudio_null_state", sizeof(double) * 4) != 0)) csound->Die(csound, Str("rtdummy: failed to allocate globals")); csound->Message(csound, Str("rtaudio: dummy module enabled\n")); p = (double*) csound->QueryGlobalVariable(csound, "__rtaudio_null_state"); } return p; } static void dummy_rtaudio_timer(CSOUND *csound, double *p) { double timeWait; int i; timeWait = p[0] - csoundGetRealTime(csound->csRtClock); i = (int) (timeWait * 1000.0 + 0.5); if (i > 0) csoundSleep((size_t) i); } int playopen_dummy(CSOUND *csound, const csRtAudioParams *parm) { double *p; char *s; /* find out if the use of dummy real-time audio functions was requested, */ /* or an unknown plugin name was specified; the latter case is an error */ s = (char*) csoundQueryGlobalVariable(csound, "_RTAUDIO"); if (s != NULL && !(strcmp(s, "null") == 0 || strcmp(s, "Null") == 0 || strcmp(s, "NULL") == 0)) { if (s[0] == '\0') csoundErrorMsg(csound, Str(" *** error: rtaudio module set to empty string")); else { // print_opcodedir_warning(csound); csoundErrorMsg(csound, Str(" unknown rtaudio module: '%s', using dummy module"), s); } // return CSOUND_ERROR; } p = get_dummy_rtaudio_globals(csound); csound->rtPlay_userdata = (void*) p; p[0] = csound->GetRealTime(csound->csRtClock); p[1] = 1.0 / ((double) ((int) sizeof(MYFLT) * parm->nChannels) * (double) parm->sampleRate); return CSOUND_SUCCESS; } void rtplay_dummy(CSOUND *csound, const MYFLT *outBuf, int nbytes) { double *p = (double*) csound->rtPlay_userdata; (void) outBuf; p[0] += ((double) nbytes * p[1]); dummy_rtaudio_timer(csound, p); } int recopen_dummy(CSOUND *csound, const csRtAudioParams *parm) { double *p; char *s; /* find out if the use of dummy real-time audio functions was requested, */ /* or an unknown plugin name was specified; the latter case is an error */ s = (char*) csoundQueryGlobalVariable(csound, "_RTAUDIO"); if (s != NULL && !(strcmp(s, "null") == 0 || strcmp(s, "Null") == 0 || strcmp(s, "NULL") == 0)) { if (s[0] == '\0') csoundErrorMsg(csound, Str(" *** error: rtaudio module set to empty string")); else { // print_opcodedir_warning(csound); csoundErrorMsg(csound, Str(" unknown rtaudio module: '%s', using dummy module"), s); } // return CSOUND_ERROR; } p = (double*) get_dummy_rtaudio_globals(csound) + 2; csound->rtRecord_userdata = (void*) p; p[0] = csound->GetRealTime(csound->csRtClock); p[1] = 1.0 / ((double) ((int) sizeof(MYFLT) * parm->nChannels) * (double) parm->sampleRate); return CSOUND_SUCCESS; } int rtrecord_dummy(CSOUND *csound, MYFLT *inBuf, int nbytes) { double *p = (double*) csound->rtRecord_userdata; /* for (i = 0; i < (nbytes / (int) sizeof(MYFLT)); i++) */ /* ((MYFLT*) inBuf)[i] = FL(0.0); */ memset(inBuf, 0, nbytes); p[0] += ((double) nbytes * p[1]); dummy_rtaudio_timer(csound, p); return nbytes; } void rtclose_dummy(CSOUND *csound) { csound->rtPlay_userdata = NULL; csound->rtRecord_userdata = NULL; } int audio_dev_list_dummy(CSOUND *csound, CS_AUDIODEVICE *list, int isOutput) { IGN(csound); IGN(list); IGN(isOutput); return 0; } int midi_dev_list_dummy(CSOUND *csound, CS_MIDIDEVICE *list, int isOutput){ IGN(csound); IGN(list); IGN(isOutput); return 0; } PUBLIC void csoundSetPlayopenCallback(CSOUND *csound, int (*playopen__)(CSOUND *, const csRtAudioParams *parm)) { csound->playopen_callback = playopen__; } PUBLIC void csoundSetRtplayCallback(CSOUND *csound, void (*rtplay__)(CSOUND *, const MYFLT *outBuf, int nbytes)) { csound->rtplay_callback = rtplay__; } PUBLIC void csoundSetRecopenCallback(CSOUND *csound, int (*recopen__)(CSOUND *, const csRtAudioParams *parm)) { csound->recopen_callback = recopen__; } PUBLIC void csoundSetRtrecordCallback(CSOUND *csound, int (*rtrecord__)(CSOUND *, MYFLT *inBuf, int nbytes)) { csound->rtrecord_callback = rtrecord__; } PUBLIC void csoundSetRtcloseCallback(CSOUND *csound, void (*rtclose__)(CSOUND *)) { csound->rtclose_callback = rtclose__; } PUBLIC void csoundSetAudioDeviceListCallback(CSOUND *csound, int (*audiodevlist__)(CSOUND *, CS_AUDIODEVICE *list, int isOutput)) { csound->audio_dev_list_callback = audiodevlist__; } PUBLIC void csoundSetMIDIDeviceListCallback(CSOUND *csound, int (*mididevlist__)(CSOUND *, CS_MIDIDEVICE *list, int isOutput)) { csound->midi_dev_list_callback = mididevlist__; } PUBLIC int csoundGetAudioDevList(CSOUND *csound, CS_AUDIODEVICE *list, int isOutput){ return csound->audio_dev_list_callback(csound,list,isOutput); } PUBLIC int csoundGetMIDIDevList(CSOUND *csound, CS_MIDIDEVICE *list, int isOutput) { return csound->midi_dev_list_callback(csound,list,isOutput); } /* dummy real time MIDI functions */ int DummyMidiInOpen(CSOUND *csound, void **userData, const char *devName) { char *s; (void) devName; *userData = NULL; s = (char*) csoundQueryGlobalVariable(csound, "_RTMIDI"); if (UNLIKELY(s == NULL || (strcmp(s, "null") == 0 || strcmp(s, "Null") == 0 || strcmp(s, "NULL") == 0))) { csoundMessage(csound, Str("WARNING: real time midi input disabled, " "using dummy functions\n")); return 0; } if (s[0] == '\0') csoundErrorMsg(csound, Str("error: -+rtmidi set to empty string")); else { print_opcodedir_warning(csound); csoundErrorMsg(csound, Str("error: -+rtmidi='%s': unknown module"), s); } return -1; } int DummyMidiRead(CSOUND *csound, void *userData, unsigned char *buf, int nbytes) { (void) csound; (void) userData; (void) buf; (void) nbytes; return 0; } int DummyMidiOutOpen(CSOUND *csound, void **userData, const char *devName) { char *s; (void) devName; *userData = NULL; s = (char*) csoundQueryGlobalVariable(csound, "_RTMIDI"); if (s == NULL || (strcmp(s, "null") == 0 || strcmp(s, "Null") == 0 || strcmp(s, "NULL") == 0)) { csoundMessage(csound, Str("WARNING: real time midi output disabled, " "using dummy functions\n")); return 0; } if (s[0] == '\0') csoundErrorMsg(csound, Str("error: -+rtmidi set to empty string")); else { print_opcodedir_warning(csound); csoundErrorMsg(csound, Str("error: -+rtmidi='%s': unknown module"), s); } return -1; } int DummyMidiWrite(CSOUND *csound, void *userData, const unsigned char *buf, int nbytes) { (void) csound; (void) userData; (void) buf; return nbytes; } static const char *midi_err_msg = Str_noop("Unknown MIDI error"); /** * Returns pointer to a string constant storing an error massage * for error code 'errcode'. */ const char *csoundExternalMidiErrorString(CSOUND *csound, int errcode) { if (csound->midiGlobals->MidiErrorStringCallback == NULL) return midi_err_msg; return (csound->midiGlobals->MidiErrorStringCallback(errcode)); } /* Set real time MIDI function pointers. */ PUBLIC void csoundSetExternalMidiInOpenCallback(CSOUND *csound, int (*func)(CSOUND *, void **, const char *)) { csound->midiGlobals->MidiInOpenCallback = func; } PUBLIC void csoundSetExternalMidiReadCallback(CSOUND *csound, int (*func)(CSOUND *, void *, unsigned char *, int)) { csound->midiGlobals->MidiReadCallback = func; } PUBLIC void csoundSetExternalMidiInCloseCallback(CSOUND *csound, int (*func)(CSOUND *, void *)) { csound->midiGlobals->MidiInCloseCallback = func; } PUBLIC void csoundSetExternalMidiOutOpenCallback(CSOUND *csound, int (*func)(CSOUND *, void **, const char *)) { csound->midiGlobals->MidiOutOpenCallback = func; } PUBLIC void csoundSetExternalMidiWriteCallback(CSOUND *csound, int (*func)(CSOUND *, void *, const unsigned char *, int)) { csound->midiGlobals->MidiWriteCallback = func; } PUBLIC void csoundSetExternalMidiOutCloseCallback(CSOUND *csound, int (*func)(CSOUND *, void *)) { csound->midiGlobals->MidiOutCloseCallback = func; } PUBLIC void csoundSetExternalMidiErrorStringCallback(CSOUND *csound, const char *(*func)(int)) { csound->midiGlobals->MidiErrorStringCallback = func; } /* * FUNCTION TABLE DISPLAY. */ PUBLIC int csoundSetIsGraphable(CSOUND *csound, int isGraphable) { int prv = csound->isGraphable_; csound->isGraphable_ = isGraphable; return prv; } PUBLIC void csoundSetMakeGraphCallback(CSOUND *csound, void (*makeGraphCB)(CSOUND *csound, WINDAT *windat, const char *name)) { csound->csoundMakeGraphCallback_ = makeGraphCB; } PUBLIC void csoundSetDrawGraphCallback(CSOUND *csound, void (*drawGraphCallback)(CSOUND *csound, WINDAT *windat)) { csound->csoundDrawGraphCallback_ = drawGraphCallback; } PUBLIC void csoundSetKillGraphCallback(CSOUND *csound, void (*killGraphCallback)(CSOUND *csound, WINDAT *windat)) { csound->csoundKillGraphCallback_ = killGraphCallback; } PUBLIC void csoundSetExitGraphCallback(CSOUND *csound, int (*exitGraphCallback)(CSOUND *)) { csound->csoundExitGraphCallback_ = exitGraphCallback; } /* * OPCODES */ static CS_NOINLINE int opcode_list_new_oentry(CSOUND *csound, const OENTRY *ep) { CONS_CELL *head; OENTRY *entryCopy; char *shortName; if (UNLIKELY(ep->opname == NULL || csound->opcodes == NULL)) return CSOUND_ERROR; shortName = get_opcode_short_name(csound, ep->opname); head = cs_hash_table_get(csound, csound->opcodes, shortName); entryCopy = csound->Malloc(csound, sizeof(OENTRY)); //printf("%p \n", entryCopy); memcpy(entryCopy, ep, sizeof(OENTRY)); entryCopy->useropinfo = NULL; if (head != NULL) { cs_cons_append(head, cs_cons(csound, entryCopy, NULL)); } else { head = cs_cons(csound, entryCopy, NULL); cs_hash_table_put(csound, csound->opcodes, shortName, head); } if (shortName != ep->opname) { csound->Free(csound, shortName); } return 0; } PUBLIC int csoundAppendOpcode(CSOUND *csound, const char *opname, int dsblksiz, int flags, int thread, const char *outypes, const char *intypes, int (*iopadr)(CSOUND *, void *), int (*kopadr)(CSOUND *, void *), int (*aopadr)(CSOUND *, void *)) { OENTRY tmpEntry; int err; tmpEntry.opname = (char*) opname; tmpEntry.dsblksiz = (uint16) dsblksiz; tmpEntry.flags = (uint16) flags; tmpEntry.thread = (uint8_t) thread; tmpEntry.outypes = (char*) outypes; tmpEntry.intypes = (char*) intypes; tmpEntry.iopadr = iopadr; tmpEntry.kopadr = kopadr; tmpEntry.aopadr = aopadr; err = opcode_list_new_oentry(csound, &tmpEntry); if (UNLIKELY(err)) csoundErrorMsg(csound, Str("Failed to allocate new opcode entry.")); return err; } /** * Appends a list of opcodes implemented by external software to Csound's * internal opcode list. The list should either be terminated with an entry * that has a NULL opname, or the number of entries (> 0) should be specified * in 'n'. Returns zero on success. */ int csoundAppendOpcodes(CSOUND *csound, const OENTRY *opcodeList, int n) { OENTRY *ep = (OENTRY*) opcodeList; int err, retval = 0; if (UNLIKELY(opcodeList == NULL)) return -1; if (UNLIKELY(n <= 0)) n = 0x7FFFFFFF; while (n && ep->opname != NULL) { if (UNLIKELY((err = opcode_list_new_oentry(csound, ep)) != 0)) { csoundErrorMsg(csound, Str("Failed to allocate opcode entry for %s."), ep->opname); retval = err; } n--, ep++; } return retval; } /* * MISC FUNCTIONS */ int defaultCsoundYield(CSOUND *csound) { (void) csound; return 1; } PUBLIC void csoundSetYieldCallback(CSOUND *csound, int (*yieldCallback)(CSOUND *)) { csound->csoundYieldCallback_ = yieldCallback; } void SetInternalYieldCallback(CSOUND *csound, int (*yieldCallback)(CSOUND *)) { csound->csoundInternalYieldCallback_ = yieldCallback; } int csoundYield(CSOUND *csound) { if (exitNow_) csound->LongJmp(csound, CSOUND_SIGNAL); csound->csoundInternalYieldCallback_(csound); return csound->csoundYieldCallback_(csound); } extern void csoundDeleteAllGlobalVariables(CSOUND *csound); typedef struct resetCallback_s { void *userData; int (*func)(CSOUND *, void *); struct resetCallback_s *nxt; } resetCallback_t; static void reset(CSOUND *csound) { CSOUND *saved_env; void *p1, *p2; uintptr_t length; uintptr_t end, start; int n = 0; csoundCleanup(csound); /* call registered reset callbacks */ while (csound->reset_list != NULL) { resetCallback_t *p = (resetCallback_t*) csound->reset_list; p->func(csound, p->userData); csound->reset_list = (void*) p->nxt; free(p); } /* call local destructor routines of external modules */ /* should check return value... */ csoundDestroyModules(csound); /* IV - Feb 01 2005: clean up configuration variables and */ /* named dynamic "global" variables of Csound instance */ csoundDeleteAllConfigurationVariables(csound); csoundDeleteAllGlobalVariables(csound); #ifdef CSCORE cscoreRESET(csound); #endif if (csound->opcodes != NULL) { free_opcode_table(csound); csound->opcodes = NULL; } csound->oparms_.odebug = 0; /* RWD 9:2000 not terribly vital, but good to do this somewhere... */ pvsys_release(csound); close_all_files(csound); /* delete temporary files created by this Csound instance */ remove_tmpfiles(csound); rlsmemfiles(csound); while (csound->filedir[n]) /* Clear source directory */ csound->Free(csound,csound->filedir[n++]); memRESET(csound); /** * Copy everything EXCEPT the function pointers. * We do it by saving them and copying them back again... * hope that this does not fail... */ /* VL 07.06.2013 - check if the status is COMP before resetting. */ //CSOUND **self = csound->self; saved_env = (CSOUND*) malloc(sizeof(CSOUND)); memcpy(saved_env, csound, sizeof(CSOUND)); memcpy(csound, &cenviron_, sizeof(CSOUND)); end = (uintptr_t) &(csound->first_callback_); /* used to be &(csound->ids) */ start =(uintptr_t) csound; length = end - start; memcpy((void*) csound, (void*) saved_env, (size_t) length); csound->oparms = &(csound->oparms_); csound->hostdata = saved_env->hostdata; p1 = (void*) &(csound->first_callback_); p2 = (void*) &(csound->last_callback_); length = (uintptr_t) p2 - (uintptr_t) p1; memcpy(p1, (void*) &(saved_env->first_callback_), (size_t) length); csound->csoundCallbacks_ = saved_env->csoundCallbacks_; csound->API_lock = saved_env->API_lock; #ifdef HAVE_PTHREAD_SPIN_LOCK csound->memlock = saved_env->memlock; csound->spinlock = saved_env->spinlock; csound->spoutlock = saved_env->spoutlock; csound->spinlock1= saved_env->spinlock1; #endif csound->enableHostImplementedMIDIIO = saved_env->enableHostImplementedMIDIIO; memcpy(&(csound->exitjmp), &(saved_env->exitjmp), sizeof(jmp_buf)); csound->memalloc_db = saved_env->memalloc_db; //csound->self = self; free(saved_env); } PUBLIC void csoundSetRTAudioModule(CSOUND *csound, const char *module){ char *s; if ((s = csoundQueryGlobalVariable(csound, "_RTAUDIO")) != NULL) strncpy(s, module, 20); if (UNLIKELY(s==NULL)) return; /* Should not happen */ if (strcmp(s, "null") == 0 || strcmp(s, "Null") == 0 || strcmp(s, "NULL") == 0) { csound->Message(csound, Str("setting dummy interface\n")); csound->SetPlayopenCallback(csound, playopen_dummy); csound->SetRecopenCallback(csound, recopen_dummy); csound->SetRtplayCallback(csound, rtplay_dummy); csound->SetRtrecordCallback(csound, rtrecord_dummy); csound->SetRtcloseCallback(csound, rtclose_dummy); csound->SetAudioDeviceListCallback(csound, audio_dev_list_dummy); return; } if (csoundInitModules(csound) != 0) csound->LongJmp(csound, 1); } PUBLIC void csoundSetMIDIModule(CSOUND *csound, const char *module){ char *s; if ((s = csoundQueryGlobalVariable(csound, "_RTMIDI")) != NULL) strncpy(s, module, 20); if (UNLIKELY(s==NULL)) return; /* Should not happen */ if (strcmp(s, "null") == 0 || strcmp(s, "Null") == 0 || strcmp(s, "NULL") == 0) { csound->SetMIDIDeviceListCallback(csound, midi_dev_list_dummy); csound->SetExternalMidiInOpenCallback(csound, DummyMidiInOpen); csound->SetExternalMidiReadCallback(csound, DummyMidiRead); csound->SetExternalMidiInCloseCallback(csound, NULL); csound->SetExternalMidiOutOpenCallback(csound, DummyMidiOutOpen); csound->SetExternalMidiWriteCallback(csound, DummyMidiWrite); csound->SetExternalMidiOutCloseCallback(csound, NULL); return; } if (csoundInitModules(csound) != 0) csound->LongJmp(csound, 1); } PUBLIC int csoundGetModule(CSOUND *csound, int no, char **module, char **type){ MODULE_INFO **modules = (MODULE_INFO **) csoundQueryGlobalVariable(csound, "_MODULES"); if (UNLIKELY(modules[no] == NULL || no >= MAX_MODULES)) return CSOUND_ERROR; *module = modules[no]->module; *type = modules[no]->type; return CSOUND_SUCCESS; } PUBLIC void csoundReset(CSOUND *csound) { char *s; int i, max_len; OPARMS *O = csound->oparms; if (csound->engineStatus & CS_STATE_COMP || csound->engineStatus & CS_STATE_PRE) { /* and reset */ csound->Message(csound, "resetting Csound instance\n"); reset(csound); /* clear compiled flag */ csound->engineStatus |= ~(CS_STATE_COMP); } else { #ifdef HAVE_PTHREAD_SPIN_LOCK pthread_spin_init((pthread_spinlock_t*)&csound->spoutlock, PTHREAD_PROCESS_PRIVATE); pthread_spin_init((pthread_spinlock_t*)&csound->spinlock, PTHREAD_PROCESS_PRIVATE); pthread_spin_init((pthread_spinlock_t*)&csound->memlock, PTHREAD_PROCESS_PRIVATE); pthread_spin_init((pthread_spinlock_t*)&csound->spinlock1, PTHREAD_PROCESS_PRIVATE); #endif if (UNLIKELY(O->odebug)) csound->Message(csound,"init spinlocks\n"); } if (msgcallback_ != NULL) { csoundSetMessageCallback(csound, msgcallback_); } csound->printerrormessagesflag = (void*)1234; /* copysystem environment variables */ i = csoundInitEnv(csound); if (UNLIKELY(i != CSOUND_SUCCESS)) { csound->engineStatus |= CS_STATE_JMP; csound->Die(csound, Str("Failed during csoundInitEnv")); } csound_init_rand(csound); csound->engineState.stringPool = cs_hash_table_create(csound); csound->engineState.constantsPool = cs_hash_table_create(csound); if (csound->symbtab != NULL) cs_hash_table_mfree_complete(csound, csound->symbtab); csound->symbtab = NULL; csound->engineStatus |= CS_STATE_PRE; csound_aops_init_tables(csound); create_opcode_table(csound); /* now load and pre-initialise external modules for this instance */ /* this function returns an error value that may be worth checking */ { int err = csoundInitStaticModules(csound); if (csound->delayederrormessages && csound->printerrormessagesflag==NULL) { csound->Warning(csound, "%s",csound->delayederrormessages); csound->Free(csound, csound->delayederrormessages); csound->delayederrormessages = NULL; } if (UNLIKELY(err==CSOUND_ERROR)) csound->Die(csound, Str("Failed during csoundInitStaticModules")); csoundCreateGlobalVariable(csound, "_MODULES", (size_t) MAX_MODULES*sizeof(MODULE_INFO *)); char *modules = (char *) csoundQueryGlobalVariable(csound, "_MODULES"); memset(modules, 0, sizeof(MODULE_INFO *)*MAX_MODULES); err = csoundLoadModules(csound); if (csound->delayederrormessages && csound->printerrormessagesflag==NULL) { csound->Warning(csound, "%s", csound->delayederrormessages); csound->Free(csound, csound->delayederrormessages); csound->delayederrormessages = NULL; } if (UNLIKELY(err != CSOUND_SUCCESS)) csound->Die(csound, Str("Failed during csoundLoadModules")); /* VL: moved here from main.c */ if (csoundInitModules(csound) != 0) csound->LongJmp(csound, 1); init_pvsys(csound); /* utilities depend on this as well as orchs; may get changed by an orch */ dbfs_init(csound, DFLT_DBFS); csound->csRtClock = (RTCLOCK*) csound->Calloc(csound, sizeof(RTCLOCK)); csoundInitTimerStruct(csound->csRtClock); csound->engineStatus |= /*CS_STATE_COMP |*/ CS_STATE_CLN; print_csound_version(csound); { char buffer[128]; sf_command(NULL, SFC_GET_LIB_VERSION, buffer, 128); csound->Message(csound, "%s\n", buffer); } /* do not know file type yet */ O->filetyp = -1; O->sfheader = 0; csound->peakchunks = 1; csound->typePool = csound->Calloc(csound, sizeof(TYPE_POOL)); csound->engineState.varPool = csoundCreateVarPool(csound); csoundAddStandardTypes(csound, csound->typePool); /* csoundLoadExternals(csound); */ } /* allow selecting real time audio module */ max_len = 21; csoundCreateGlobalVariable(csound, "_RTAUDIO", (size_t) max_len); s = csoundQueryGlobalVariable(csound, "_RTAUDIO"); #ifndef LINUX strcpy(s, "PortAudio"); #else strcpy(s, "alsa"); #endif csoundCreateConfigurationVariable(csound, "rtaudio", s, CSOUNDCFG_STRING, 0, NULL, &max_len, Str("Real time audio module name"), NULL); /* initialise real time MIDI */ csound->midiGlobals = (MGLOBAL*) csound->Calloc(csound, sizeof(MGLOBAL)); csound->midiGlobals->bufp = &(csound->midiGlobals->mbuf[0]); csound->midiGlobals->endatp = csound->midiGlobals->bufp; csoundCreateGlobalVariable(csound, "_RTMIDI", (size_t) max_len); csound->SetMIDIDeviceListCallback(csound, midi_dev_list_dummy); csound->SetExternalMidiInOpenCallback(csound, DummyMidiInOpen); csound->SetExternalMidiReadCallback(csound, DummyMidiRead); csound->SetExternalMidiOutOpenCallback(csound, DummyMidiOutOpen); csound->SetExternalMidiWriteCallback(csound, DummyMidiWrite); s = csoundQueryGlobalVariable(csound, "_RTMIDI"); strcpy(s, "null"); if (csound->enableHostImplementedMIDIIO == 0) #ifndef LINUX strcpy(s, "portmidi"); #else strcpy(s, "alsa"); #endif else strcpy(s, "hostbased"); csoundCreateConfigurationVariable(csound, "rtmidi", s, CSOUNDCFG_STRING, 0, NULL, &max_len, Str("Real time MIDI module name"), NULL); max_len = 256; /* should be the same as in csoundCore.h */ csoundCreateConfigurationVariable(csound, "mute_tracks", &(csound->midiGlobals->muteTrackList[0]), CSOUNDCFG_STRING, 0, NULL, &max_len, Str("Ignore events (other than tempo " "changes) in tracks defined by pattern"), NULL); csoundCreateConfigurationVariable(csound, "raw_controller_mode", &(csound->midiGlobals->rawControllerMode), CSOUNDCFG_BOOLEAN, 0, NULL, NULL, Str("Do not handle special MIDI controllers" " (sustain pedal etc.)"), NULL); /* sound file tag options */ max_len = 201; i = (max_len + 7) & (~7); csound->SF_id_title = (char*) csound->Calloc(csound, (size_t) i * (size_t) 6); csoundCreateConfigurationVariable(csound, "id_title", csound->SF_id_title, CSOUNDCFG_STRING, 0, NULL, &max_len, Str("Title tag in output soundfile " "(no spaces)"), NULL); csound->SF_id_copyright = (char*) csound->SF_id_title + (int) i; csoundCreateConfigurationVariable(csound, "id_copyright", csound->SF_id_copyright, CSOUNDCFG_STRING, 0, NULL, &max_len, Str("Copyright tag in output soundfile" " (no spaces)"), NULL); csoundCreateConfigurationVariable(csound, "id_scopyright", &csound->SF_id_scopyright, CSOUNDCFG_INTEGER, 0, NULL, &max_len, Str("Short Copyright tag in" " output soundfile"), NULL); csound->SF_id_software = (char*) csound->SF_id_copyright + (int) i; csoundCreateConfigurationVariable(csound, "id_software", csound->SF_id_software, CSOUNDCFG_STRING, 0, NULL, &max_len, Str("Software tag in output soundfile" " (no spaces)"), NULL); csound->SF_id_artist = (char*) csound->SF_id_software + (int) i; csoundCreateConfigurationVariable(csound, "id_artist", csound->SF_id_artist, CSOUNDCFG_STRING, 0, NULL, &max_len, Str("Artist tag in output soundfile " "(no spaces)"), NULL); csound->SF_id_comment = (char*) csound->SF_id_artist + (int) i; csoundCreateConfigurationVariable(csound, "id_comment", csound->SF_id_comment, CSOUNDCFG_STRING, 0, NULL, &max_len, Str("Comment tag in output soundfile" " (no spaces)"), NULL); csound->SF_id_date = (char*) csound->SF_id_comment + (int) i; csoundCreateConfigurationVariable(csound, "id_date", csound->SF_id_date, CSOUNDCFG_STRING, 0, NULL, &max_len, Str("Date tag in output soundfile " "(no spaces)"), NULL); { MYFLT minValF = FL(0.0); csoundCreateConfigurationVariable(csound, "msg_color", &(csound->enableMsgAttr), CSOUNDCFG_BOOLEAN, 0, NULL, NULL, Str("Enable message attributes " "(colors etc.)"), NULL); csoundCreateConfigurationVariable(csound, "skip_seconds", &(csound->csoundScoreOffsetSeconds_), CSOUNDCFG_MYFLT, 0, &minValF, NULL, Str("Start score playback at the specified" " time, skipping earlier events"), NULL); } csoundCreateConfigurationVariable(csound, "ignore_csopts", &(csound->disable_csd_options), CSOUNDCFG_BOOLEAN, 0, NULL, NULL, Str("Ignore in CSD files" " (default: no)"), NULL); } PUBLIC int csoundGetDebug(CSOUND *csound) { return csound->oparms_.odebug; } PUBLIC void csoundSetDebug(CSOUND *csound, int debug) { csound->oparms_.odebug = debug; } PUBLIC int csoundTableLength(CSOUND *csound, int table) { MYFLT *tablePtr; return csoundGetTable(csound, &tablePtr, table); } PUBLIC MYFLT csoundTableGet(CSOUND *csound, int table, int index) { return csound->flist[table]->ftable[index]; } void csoundTableSetInternal(CSOUND *csound, int table, int index, MYFLT value) { if (csound->oparms->realtime) csoundLockMutex(csound->init_pass_threadlock); csound->flist[table]->ftable[index] = value; if (csound->oparms->realtime) csoundUnlockMutex(csound->init_pass_threadlock); } void csoundTableCopyOutInternal(CSOUND *csound, int table, MYFLT *ptable){ int len; MYFLT *ftab; /* in realtime mode init pass is executed in a separate thread, so we need to protect it */ if (csound->oparms->realtime) csoundLockMutex(csound->init_pass_threadlock); len = csoundGetTable(csound, &ftab, table); if (UNLIKELY(len>0x00ffffff)) len = 0x00ffffff; // As coverity is unhappy memcpy(ptable, ftab, (size_t) (len*sizeof(MYFLT))); if (csound->oparms->realtime) csoundUnlockMutex(csound->init_pass_threadlock); } void csoundTableCopyInInternal(CSOUND *csound, int table, MYFLT *ptable){ int len; MYFLT *ftab; /* in realtime mode init pass is executed in a separate thread, so we need to protect it */ if (csound->oparms->realtime) csoundLockMutex(csound->init_pass_threadlock); len = csoundGetTable(csound, &ftab, table); if (UNLIKELY(len>0x00ffffff)) len = 0x00ffffff; // As coverity is unhappy memcpy(ftab, ptable, (size_t) (len*sizeof(MYFLT))); if (csound->oparms->realtime) csoundUnlockMutex(csound->init_pass_threadlock); } static int csoundDoCallback_(CSOUND *csound, void *p, unsigned int type) { if (csound->csoundCallbacks_ != NULL) { CsoundCallbackEntry_t *pp; pp = (CsoundCallbackEntry_t*) csound->csoundCallbacks_; do { if (pp->typeMask & type) { int retval = pp->func(pp->userData, p, type); if (retval != CSOUND_SUCCESS) return retval; } pp = pp->nxt; } while (pp != (CsoundCallbackEntry_t*) NULL); } return 1; } /** * Sets a callback function that will be called on keyboard * events. The callback is preserved on csoundReset(), and multiple * callbacks may be set and will be called in reverse order of * registration. If the same function is set again, it is only moved * in the list of callbacks so that it will be called first, and the * user data and type mask parameters are updated. 'typeMask' can be the * bitwise OR of callback types for which the function should be called, * or zero for all types. * Returns zero on success, CSOUND_ERROR if the specified function * pointer or type mask is invalid, and CSOUND_MEMORY if there is not * enough memory. * * The callback function takes the following arguments: * void *userData * the "user data" pointer, as specified when setting the callback * void *p * data pointer, depending on the callback type * unsigned int type * callback type, can be one of the following (more may be added in * future versions of Csound): * CSOUND_CALLBACK_KBD_EVENT * CSOUND_CALLBACK_KBD_TEXT * called by the sensekey opcode to fetch key codes. The data * pointer is a pointer to a single value of type 'int', for * returning the key code, which can be in the range 1 to 65535, * or 0 if there is no keyboard event. * For CSOUND_CALLBACK_KBD_EVENT, both key press and release * events should be returned (with 65536 (0x10000) added to the * key code in the latter case) as unshifted ASCII codes. * CSOUND_CALLBACK_KBD_TEXT expects key press events only as the * actual text that is typed. * The return value should be zero on success, negative on error, and * positive if the callback was ignored (for example because the type is * not known). */ PUBLIC int csoundRegisterKeyboardCallback(CSOUND *csound, int (*func)(void *userData, void *p, unsigned int type), void *userData, unsigned int typeMask) { CsoundCallbackEntry_t *pp; if (UNLIKELY(func == (int (*)(void *, void *, unsigned int)) NULL || (typeMask & (~(CSOUND_CALLBACK_KBD_EVENT | CSOUND_CALLBACK_KBD_TEXT))) != 0U)) return CSOUND_ERROR; csoundRemoveKeyboardCallback(csound, func); pp = (CsoundCallbackEntry_t*) malloc(sizeof(CsoundCallbackEntry_t)); if (UNLIKELY(pp == (CsoundCallbackEntry_t*) NULL)) return CSOUND_MEMORY; pp->typeMask = (typeMask ? typeMask : 0xFFFFFFFFU); pp->nxt = (CsoundCallbackEntry_t*) csound->csoundCallbacks_; pp->userData = userData; pp->func = func; csound->csoundCallbacks_ = (void*) pp; return CSOUND_SUCCESS; } /** * Removes a callback previously set with csoundSetCallback(). */ PUBLIC void csoundRemoveKeyboardCallback(CSOUND *csound, int (*func)(void *, void *, unsigned int)) { CsoundCallbackEntry_t *pp, *prv; pp = (CsoundCallbackEntry_t*) csound->csoundCallbacks_; prv = (CsoundCallbackEntry_t*) NULL; while (pp != (CsoundCallbackEntry_t*) NULL) { if (pp->func == func) { if (prv != (CsoundCallbackEntry_t*) NULL) prv->nxt = pp->nxt; else csound->csoundCallbacks_ = (void*) pp->nxt; free((void*) pp); return; } prv = pp; pp = pp->nxt; } } PUBLIC void csoundSetFileOpenCallback(CSOUND *p, void (*fileOpenCallback)(CSOUND*, const char*, int, int, int)) { p->FileOpenCallback_ = fileOpenCallback; } /* csoundNotifyFileOpened() should be called by plugins via csound->NotifyFileOpened() to let Csound know that they opened a file without using one of the standard mechanisms (csound->FileOpen2() or ldmemfile2withCB()). The notification is passed on to the host if it has set the FileOpen callback. */ void csoundNotifyFileOpened(CSOUND* csound, const char* pathname, int csFileType, int writing, int temporary) { if (csound->FileOpenCallback_ != NULL) csound->FileOpenCallback_(csound, pathname, csFileType, writing, temporary); return; } /* -------- IV - Jan 27 2005: timer functions -------- */ #ifdef HAVE_GETTIMEOFDAY #undef HAVE_GETTIMEOFDAY #endif #if defined(LINUX) || defined(__unix) || defined(__unix__) || defined(__MACH__) #define HAVE_GETTIMEOFDAY 1 #include #endif /* enable use of high resolution timer (Linux/i586/GCC only) */ /* could in fact work under any x86/GCC system, but do not */ /* know how to query the actual CPU frequency ... */ //#define HAVE_RDTSC 1 /* ------------------------------------ */ #if defined(HAVE_RDTSC) #if !(defined(LINUX) && defined(__GNUC__) && defined(__i386__)) #undef HAVE_RDTSC #endif #endif /* hopefully cannot change during performance */ static double timeResolutionSeconds = -1.0; /* find out CPU frequency based on /proc/cpuinfo */ static int getTimeResolution(void) { #if defined(HAVE_RDTSC) FILE *f; char buf[256]; /* if frequency is not known yet */ f = fopen("/proc/cpuinfo", "r"); if (UNLIKELY(f == NULL)) { fprintf(stderr, Str("Cannot open /proc/cpuinfo. " "Support for RDTSC is not available.\n")); return -1; } /* find CPU frequency */ while (fgets(buf, 256, f) != NULL) { int i; char *s = (char*) buf - 1; buf[255] = '\0'; /* safety */ if (strlen(buf) < 9) continue; /* too short, skip */ while (*++s != '\0') if (isupper(*s)) *s = tolower(*s); /* convert to lower case */ if (strncmp(buf, "cpu mhz", 7) != 0) continue; /* check key name */ s = strchr(buf, ':'); /* find frequency value */ if (s == NULL) continue; /* invalid entry */ do { s++; } while (isblank(*s)); /* skip white space */ i = CS_SSCANF(s, "%lf", &timeResolutionSeconds); if (i < 1 || timeResolutionSeconds < 1.0) { timeResolutionSeconds = -1.0; /* invalid entry */ continue; } } fclose(f); if (UNLIKELY(timeResolutionSeconds <= 0.0)) { fprintf(stderr, Str("No valid CPU frequency entry " "was found in /proc/cpuinfo.\n")); return -1; } /* MHz -> seconds */ timeResolutionSeconds = 0.000001 / timeResolutionSeconds; #elif defined(WIN32) LARGE_INTEGER tmp1; int_least64_t tmp2; QueryPerformanceFrequency(&tmp1); tmp2 = (int_least64_t) tmp1.LowPart + ((int_least64_t) tmp1.HighPart << 32); timeResolutionSeconds = 1.0 / (double) tmp2; #elif defined(HAVE_GETTIMEOFDAY) timeResolutionSeconds = 0.000001; #else timeResolutionSeconds = 1.0; #endif #ifdef BETA fprintf(stderr, "time resolution is %.3f ns\n", 1.0e9 * timeResolutionSeconds); #endif return 0; } /* function for getting real time */ static inline int_least64_t get_real_time(void) { #if defined(HAVE_RDTSC) /* optimised high resolution timer for Linux/i586/GCC only */ uint32_t l, h; #ifndef __STRICT_ANSI__ asm volatile ("rdtsc" : "=a" (l), "=d" (h)); #else __asm__ volatile ("rdtsc" : "=a" (l), "=d" (h)); #endif return ((int_least64_t) l + ((int_least64_t) h << 32)); #elif defined(WIN32) /* Win32: use QueryPerformanceCounter - resolution depends on system, */ /* but is expected to be better than 1 us. GetSystemTimeAsFileTime */ /* seems to have much worse resolution under Win95. */ LARGE_INTEGER tmp; QueryPerformanceCounter(&tmp); return ((int_least64_t) tmp.LowPart + ((int_least64_t) tmp.HighPart <<32)); #elif defined(HAVE_GETTIMEOFDAY) /* UNIX: use gettimeofday() - allows 1 us resolution */ struct timeval tv; gettimeofday(&tv, NULL); return ((int_least64_t) tv.tv_usec + (int_least64_t) ((uint32_t) tv.tv_sec * (uint64_t) 1000000)); #else /* other systems: use time() - allows 1 second resolution */ return ((int_least64_t) time(NULL)); #endif } /* function for getting CPU time */ static inline int_least64_t get_CPU_time(void) { return ((int_least64_t) ((uint32_t) clock())); } /* initialise a timer structure */ PUBLIC void csoundInitTimerStruct(RTCLOCK *p) { p->starttime_real = get_real_time(); p->starttime_CPU = get_CPU_time(); } /** * return the elapsed real time (in seconds) since the specified timer * structure was initialised */ PUBLIC double csoundGetRealTime(RTCLOCK *p) { return ((double) (get_real_time() - p->starttime_real) * (double) timeResolutionSeconds); } /** * return the elapsed CPU time (in seconds) since the specified timer * structure was initialised */ PUBLIC double csoundGetCPUTime(RTCLOCK *p) { return ((double) ((uint32_t) get_CPU_time() - (uint32_t) p->starttime_CPU) * (1.0 / (double) CLOCKS_PER_SEC)); } /* return a 32-bit unsigned integer to be used as seed from current time */ PUBLIC uint32_t csoundGetRandomSeedFromTime(void) { return (uint32_t) get_real_time(); } /** * Return the size of MYFLT in bytes. */ PUBLIC int csoundGetSizeOfMYFLT(void) { return (int) sizeof(MYFLT); } /** * Return pointer to user data pointer for real time audio input. */ PUBLIC void **csoundGetRtRecordUserData(CSOUND *csound) { return &(csound->rtRecord_userdata); } /** * Return pointer to user data pointer for real time audio output. */ PUBLIC void **csoundGetRtPlayUserData(CSOUND *csound) { return &(csound->rtPlay_userdata); } typedef struct opcodeDeinit_s { void *p; int (*func)(CSOUND *, void *); void *nxt; } opcodeDeinit_t; /** * Register a function to be called at note deactivation. * Should be called from the initialisation routine of an opcode. * 'p' is a pointer to the OPDS structure of the opcode, and 'func' * is the function to be called, with the same arguments and return * value as in the case of opcode init/perf functions. * The functions are called in reverse order of registration. * Returns zero on success. */ int csoundRegisterDeinitCallback(CSOUND *csound, void *p, int (*func)(CSOUND *, void *)) { INSDS *ip = ((OPDS*) p)->insdshead; opcodeDeinit_t *dp = (opcodeDeinit_t*) malloc(sizeof(opcodeDeinit_t)); (void) csound; if (UNLIKELY(dp == NULL)) return CSOUND_MEMORY; dp->p = p; dp->func = func; dp->nxt = ip->nxtd; ip->nxtd = dp; return CSOUND_SUCCESS; } /** * Register a function to be called by csoundReset(), in reverse order * of registration, before unloading external modules. The function takes * the Csound instance pointer as the first argument, and the pointer * passed here as 'userData' as the second, and is expected to return zero * on success. * The return value of csoundRegisterResetCallback() is zero on success. */ int csoundRegisterResetCallback(CSOUND *csound, void *userData, int (*func)(CSOUND *, void *)) { resetCallback_t *dp = (resetCallback_t*) malloc(sizeof(resetCallback_t)); if (UNLIKELY(dp == NULL)) return CSOUND_MEMORY; dp->userData = userData; dp->func = func; dp->nxt = csound->reset_list; csound->reset_list = (void*) dp; return CSOUND_SUCCESS; } /* call the opcode deinitialisation routines of an instrument instance */ /* called from deact() in insert.c */ int csoundDeinitialiseOpcodes(CSOUND *csound, INSDS *ip) { int err = 0; while (ip->nxtd != NULL) { opcodeDeinit_t *dp = (opcodeDeinit_t*) ip->nxtd; err |= dp->func(csound, dp->p); ip->nxtd = (void*) dp->nxt; free(dp); } return err; } /** * Returns the name of the opcode of which the data structure * is pointed to by 'p'. */ char *csoundGetOpcodeName(void *p) { return ((OPDS*) p)->optext->t.oentry->opname; } /** Returns the CS_TYPE for an opcode's arg pointer */ CS_TYPE* csoundGetTypeForArg(void* argPtr) { char* ptr = (char*)argPtr; CS_TYPE* varType = *(CS_TYPE**)(ptr - CS_VAR_TYPE_OFFSET); return varType; } /** * Returns the number of input arguments for opcode 'p'. */ int csoundGetInputArgCnt(void *p) { return (int) ((OPDS*) p)->optext->t.inArgCount; } /** * Returns the name of input argument 'n' (counting from 0) for opcode 'p'. */ char *csoundGetInputArgName(void *p, int n) { if ((unsigned int) n >= (unsigned int) ((OPDS*) p)->optext->t.inArgCount) return (char*) NULL; return (char*) ((OPDS*) p)->optext->t.inlist->arg[n]; } /** * Returns the number of output arguments for opcode 'p'. */ int csoundGetOutputArgCnt(void *p) { return (int) ((OPDS*) p)->optext->t.outArgCount; } /** * Returns the name of output argument 'n' (counting from 0) for opcode 'p'. */ char *csoundGetOutputArgName(void *p, int n) { if ((unsigned int) n >= (unsigned int) ((OPDS*) p)->optext->t.outArgCount) return (char*) NULL; return (char*) ((OPDS*) p)->optext->t.outlist->arg[n]; } /** * Set release time in control periods (1 / csound->ekr second units) * for opcode 'p' to 'n'. If the current release time is longer than * the specified value, it is not changed. * Returns the new release time. */ int csoundSetReleaseLength(void *p, int n) { if (n > (int) ((OPDS*) p)->insdshead->xtratim) ((OPDS*) p)->insdshead->xtratim = n; return (int) ((OPDS*) p)->insdshead->xtratim; } /** * Set release time in seconds for opcode 'p' to 'n'. * If the current release time is longer than the specified value, * it is not changed. * Returns the new release time in seconds. */ MYFLT csoundSetReleaseLengthSeconds(void *p, MYFLT n) { int kcnt = (int) (n * ((OPDS*) p)->insdshead->csound->ekr + FL(0.5)); if (kcnt > (int) ((OPDS*) p)->insdshead->xtratim) ((OPDS*) p)->insdshead->xtratim = kcnt; return ((MYFLT) ((OPDS*) p)->insdshead->xtratim * ((OPDS*) p)->insdshead->csound->onedkr); } /** * Returns MIDI channel number (0 to 15) for the instrument instance * that called opcode 'p'. * In the case of score notes, -1 is returned. */ int csoundGetMidiChannelNumber(void *p) { MCHNBLK *chn = ((OPDS*) p)->insdshead->m_chnbp; int i; if (chn == NULL) return -1; for (i = 0; i < 16; i++) { if (chn == ((OPDS*) p)->insdshead->csound->m_chnbp[i]) return i; } return -1; } /** * Returns a pointer to the MIDI channel structure for the instrument * instance that called opcode 'p'. * In the case of score notes, NULL is returned. */ MCHNBLK *csoundGetMidiChannel(void *p) { return ((OPDS*) p)->insdshead->m_chnbp; } /** * Returns MIDI note number (in the range 0 to 127) for opcode 'p'. * If the opcode was not called from a MIDI activated instrument * instance, the return value is undefined. */ int csoundGetMidiNoteNumber(void *p) { return (int) ((OPDS*) p)->insdshead->m_pitch; } /** * Returns MIDI velocity (in the range 0 to 127) for opcode 'p'. * If the opcode was not called from a MIDI activated instrument * instance, the return value is undefined. */ int csoundGetMidiVelocity(void *p) { return (int) ((OPDS*) p)->insdshead->m_veloc; } /** * Returns non-zero if the current note (owning opcode 'p') is releasing. */ int csoundGetReleaseFlag(void *p) { return (int) ((OPDS*) p)->insdshead->relesing; } /** * Returns the note-off time in seconds (measured from the beginning of * performance) of the current instrument instance, from which opcode 'p' * was called. The return value may be negative if the note has indefinite * duration. */ double csoundGetOffTime(void *p) { return (double) ((OPDS*) p)->insdshead->offtim; } /** * Returns the array of p-fields passed to the instrument instance * that owns opcode 'p', starting from p0. Only p1, p2, and p3 are * guaranteed to be available. p2 is measured in seconds from the * beginning of the current section. */ MYFLT *csoundGetPFields(void *p) { /* FIXME - this is no longer valid, should return CS_VAR_MEM* and use ->p0_type */ return (MYFLT*) &(((OPDS*) p)->insdshead->p0); } /** * Returns the instrument number (p1) for opcode 'p'. */ int csoundGetInstrumentNumber(void *p) { return (int) ((OPDS*) p)->insdshead->p1.value; } typedef struct csMsgStruct_ { struct csMsgStruct_ *nxt; int attr; char s[1]; } csMsgStruct; typedef struct csMsgBuffer_ { void *mutex_; csMsgStruct *firstMsg; csMsgStruct *lastMsg; int msgCnt; char *buf; } csMsgBuffer; // callback for storing messages in the buffer only static void csoundMessageBufferCallback_1_(CSOUND *csound, int attr, const char *fmt, va_list args); // callback for writing messages to the buffer, and also stdout/stderr static void csoundMessageBufferCallback_2_(CSOUND *csound, int attr, const char *fmt, va_list args); /** * Creates a buffer for storing messages printed by Csound. * Should be called after creating a Csound instance; note that * the message buffer uses the host data pointer, and the buffer * should be freed by calling csoundDestroyMessageBuffer() before * deleting the Csound instance. * If 'toStdOut' is non-zero, the messages are also printed to * stdout and stderr (depending on the type of the message), * in addition to being stored in the buffer. */ void PUBLIC csoundCreateMessageBuffer(CSOUND *csound, int toStdOut) { csMsgBuffer *pp; size_t nBytes; pp = (csMsgBuffer*) csound->message_buffer; if (pp) { csoundDestroyMessageBuffer(csound); } nBytes = sizeof(csMsgBuffer); if (!toStdOut) { nBytes += (size_t) 16384; } pp = (csMsgBuffer*) malloc(nBytes); pp->mutex_ = csoundCreateMutex(0); pp->firstMsg = (csMsgStruct*) NULL; pp->lastMsg = (csMsgStruct*) NULL; pp->msgCnt = 0; if (!toStdOut) { pp->buf = (char*) pp + (int) sizeof(csMsgBuffer); pp->buf[0] = (char) '\0'; } else { pp->buf = (char*) NULL; } csound->message_buffer = (void*) pp; if (toStdOut) { csoundSetMessageCallback(csound, csoundMessageBufferCallback_2_); } else { csoundSetMessageCallback(csound, csoundMessageBufferCallback_1_); } } /** * Returns the first message from the buffer. */ #ifdef MSVC const char PUBLIC *csoundGetFirstMessage(CSOUND *csound) #else const char */*PUBLIC*/ csoundGetFirstMessage(CSOUND *csound) #endif { csMsgBuffer *pp = (csMsgBuffer*) csound->message_buffer; char *msg = NULL; if (pp && pp->msgCnt) { csoundLockMutex(pp->mutex_); if (pp->firstMsg) msg = &(pp->firstMsg->s[0]); csoundUnlockMutex(pp->mutex_); } return msg; } /** * Returns the attribute parameter (see msg_attr.h) of the first message * in the buffer. */ int PUBLIC csoundGetFirstMessageAttr(CSOUND *csound) { csMsgBuffer *pp = (csMsgBuffer*) csound->message_buffer; int attr = 0; if (pp && pp->msgCnt) { csoundLockMutex(pp->mutex_); if (pp->firstMsg) { attr = pp->firstMsg->attr; } csoundUnlockMutex(pp->mutex_); } return attr; } /** * Removes the first message from the buffer. */ void PUBLIC csoundPopFirstMessage(CSOUND *csound) { csMsgBuffer *pp = (csMsgBuffer*) csound->message_buffer; if (pp) { csMsgStruct *tmp; csoundLockMutex(pp->mutex_); tmp = pp->firstMsg; if (tmp) { pp->firstMsg = tmp->nxt; pp->msgCnt--; if (!pp->firstMsg) pp->lastMsg = (csMsgStruct*) 0; } csoundUnlockMutex(pp->mutex_); if (tmp) free((void*) tmp); } } /** * Returns the number of pending messages in the buffer. */ int PUBLIC csoundGetMessageCnt(CSOUND *csound) { csMsgBuffer *pp = (csMsgBuffer*) csound->message_buffer; int cnt = -1; if (pp) { csoundLockMutex(pp->mutex_); cnt = pp->msgCnt; csoundUnlockMutex(pp->mutex_); } return cnt; } /** * Releases all memory used by the message buffer. */ void PUBLIC csoundDestroyMessageBuffer(CSOUND *csound) { csMsgBuffer *pp = (csMsgBuffer*) csound->message_buffer; if (!pp) { csound->Warning(csound, Str("csoundDestroyMessageBuffer: " "Message buffer not allocated.")); return; } csMsgStruct *msg = pp->firstMsg; while (msg) { csMsgStruct *tmp = msg; msg = tmp->nxt; free(tmp); } csound->message_buffer = NULL; csoundSetMessageCallback(csound, NULL); while (csoundGetMessageCnt(csound) > 0) { csoundPopFirstMessage(csound); } csoundSetHostData(csound, NULL); csoundDestroyMutex(pp->mutex_); free((void*) pp); } static void csoundMessageBufferCallback_1_(CSOUND *csound, int attr, const char *fmt, va_list args) { csMsgBuffer *pp = (csMsgBuffer*) csound->message_buffer; csMsgStruct *p; int len; csoundLockMutex(pp->mutex_); len = vsnprintf(pp->buf, 16384, fmt, args); // FIXEDME: this can overflow va_end(args); if (UNLIKELY((unsigned int) len >= (unsigned int) 16384)) { csoundUnlockMutex(pp->mutex_); fprintf(stderr, Str("csound: internal error: message buffer overflow\n")); exit(-1); } p = (csMsgStruct*) malloc(sizeof(csMsgStruct) + (size_t) len); p->nxt = (csMsgStruct*) NULL; p->attr = attr; strcpy(&(p->s[0]), pp->buf); if (pp->firstMsg == (csMsgStruct*) 0) { pp->firstMsg = p; } else { pp->lastMsg->nxt = p; } pp->lastMsg = p; pp->msgCnt++; csoundUnlockMutex(pp->mutex_); } static void csoundMessageBufferCallback_2_(CSOUND *csound, int attr, const char *fmt, va_list args) { csMsgBuffer *pp = (csMsgBuffer*) csound->message_buffer; csMsgStruct *p; int len = 0; va_list args_save; va_copy(args_save, args); switch (attr & CSOUNDMSG_TYPE_MASK) { case CSOUNDMSG_ERROR: case CSOUNDMSG_REALTIME: case CSOUNDMSG_WARNING: len = vfprintf(stderr, fmt, args); break; default: len = vfprintf(stdout, fmt, args); } va_end(args); p = (csMsgStruct*) malloc(sizeof(csMsgStruct) + (size_t) len); p->nxt = (csMsgStruct*) NULL; p->attr = attr; vsnprintf(&(p->s[0]), len, fmt, args_save); va_end(args_save); csoundLockMutex(pp->mutex_); if (pp->firstMsg == (csMsgStruct*) NULL) pp->firstMsg = p; else pp->lastMsg->nxt = p; pp->lastMsg = p; pp->msgCnt++; csoundUnlockMutex(pp->mutex_); } static INSTRTXT **csoundGetInstrumentList(CSOUND *csound){ return csound->engineState.instrtxtp; } uint64_t csoundGetKcounter(CSOUND *csound){ return csound->kcounter; } static void set_util_sr(CSOUND *csound, MYFLT sr){ csound->esr = sr; } static void set_util_nchnls(CSOUND *csound, int nchnls){ csound->nchnls = nchnls; } MYFLT csoundGetA4(CSOUND *csound) { return (MYFLT) csound->A4; } #if 0 PUBLIC int csoundPerformKsmpsAbsolute(CSOUND *csound) { int done = 0; int returnValue; /* VL: 1.1.13 if not compiled (csoundStart() not called) */ if (UNLIKELY(!(csound->engineStatus & CS_STATE_COMP))) { csound->Warning(csound, Str("Csound not ready for performance: csoundStart() " "has not been called \n")); return CSOUND_ERROR; } /* setup jmp for return after an exit() */ if (UNLIKELY((returnValue = setjmp(csound->exitjmp)))) { #ifndef MACOSX csoundMessage(csound, Str("Early return from csoundPerformKsmps().\n")); #endif return ((returnValue - CSOUND_EXITJMP_SUCCESS) | CSOUND_EXITJMP_SUCCESS); } csoundLockMutex(csound->API_lock); do { done |= sensevents(csound); } while (csound->kperf(csound)); csoundUnlockMutex(csound->API_lock); return done; } #endif //#ifdef __cplusplus //} //#endif csound-6.10.0/Top/getstring.c000066400000000000000000000236311321653344700160220ustar00rootroot00000000000000/* getstring.c: Copyright (C) 1999 John ffitch Jan 27 2005: replaced with new implementation by Istvan Varga Dec 25 2007: added GNU gettext implementation as alternative -- John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #ifdef HAVE_STRTOD_L static locale_t csound_c_locale = NULL; #else static char *csound_c_locale = NULL; #endif #ifdef HAVE_DIRENT_H # include # include # if 0 && defined(__MACH__) typedef void* DIR; DIR opendir(const char *); struct dirent *readdir(DIR*); int closedir(DIR*); # endif #endif #include "namedins.h" #define CSSTRNGS_VERSION 0x2000 #include #ifdef GNU_GETTEXT #include #endif #ifndef GNU_GETTEXT void init_getstring(void *cs) { #ifndef HAVE_STRTOD_L setlocale(LC_NUMERIC, "C"); /* Ensure C syntax */ csound_c_locale = setlocale(LC_NUMERIC, "C"); /* and remwmber */ #else if (csound_c_locale == NULL) { csound_c_locale = newlocale (0, "C", NULL); } #endif } PUBLIC char *csoundLocalizeString(const char *s) { return (char*)s; } /* This stub is needed for backwards compatibility */ PUBLIC void csoundSetLanguage(cslanguage_t lang_code) { return; } #else void init_getstring(void *cs) { /* s = csoundGetEnv(NULL, "CS_LANG"); */ /* if (s == NULL) /\* Default locale *\/ */ /* setlocale (LC_MESSAGES, ""); */ /* else */ /* setlocale (LC_MESSAGES, s); /\* Set to particular value *\/ */ /* textdomain("csound6"); */ /* This is not needed when using dgettext */ /* bind_textdomain_codeset("csound6", "UTF-8"); */ #if defined(CSOUND_TEXTDOMAIN) bindtextdomain("csound6", CSOUND_TEXTDOMAIN); #endif #ifndef HAVE_STRTOD_L setlocale(LC_NUMERIC, "C"); /* Ensure C syntax */ #else if (csound_c_locale == NULL) { csound_c_locale = newlocale (0, "C", NULL); } #endif } PUBLIC char *csoundLocalizeString(const char *s) { return dgettext("csound6", s); } static const char *language_names[] = {"", /* Default */ "af", /* CSLANGUAGE_AFRIKAANS */ "sq", /* CSLANGUAGE_ALBANIAN */ "ar", /* CSLANGUAGE_ARABIC */ "hy", /* CSLANGUAGE_ARMENIAN */ "as", /* CSLANGUAGE_ASSAMESE */ "az", /* CSLANGUAGE_AZERI */ "eu", /* CSLANGUAGE_BASQUE */ "be", /* CSLANGUAGE_BELARUSIAN */ "bn", /* CSLANGUAGE_BENGALI */ "bg", /* CSLANGUAGE_BULGARIAN */ "ca", /* CSLANGUAGE_CATALAN */ "zh", /* CSLANGUAGE_CHINESE */ "hr", /* CSLANGUAGE_CROATIAN */ "cs", /* CSLANGUAGE_CZECH */ "da", /* CSLANGUAGE_DANISH */ "nl", /* CSLANGUAGE_DUTCH */ "en_GB", "en_US", "et", /* CSLANGUAGE_ESTONIAN */ "fo", /* CSLANGUAGE_FAEROESE */ "fa", /* CSLANGUAGE_FARSI */ "fi", /* CSLANGUAGE_FINNISH */ "fr", "ka", /* CSLANGUAGE_GEORGIAN */ "de", "el", /* CSLANGUAGE_GREEK */ "gu", /* CSLANGUAGE_GUJARATI */ "he", /* CSLANGUAGE_HEBREW */ "hi", /* CSLANGUAGE_HINDI */ "hu", /* CSLANGUAGE_HUNGARIAN */ "is", /* CSLANGUAGE_ICELANDIC */ "id", /* CSLANGUAGE_INDONESIAN */ "it", /* CSLANGUAGE_ITALIAN */ "ja", /* CSLANGUAGE_JAPANESE */ "kn", /* CSLANGUAGE_KANNADA */ "ks", /* CSLANGUAGE_KASHMIRI */ "kk", /* CSLANGUAGE_KAZAK */ "kok", /* CSLANGUAGE_KONKANI */ "ko", /* CSLANGUAGE_KOREAN */ "lv", /* CSLANGUAGE_LATVIAN */ "lt", /* CSLANGUAGE_LITHUANIAN */ "mk", /* CSLANGUAGE_MACEDONIAN */ "ms", /* CSLANGUAGE_MALAY */ "ml", /* CSLANGUAGE_MALAYALAM */ "mni", /* CSLANGUAGE_MANIPURI */ "mr", /* CSLANGUAGE_MARATHI */ "ne", /* CSLANGUAGE_NEPALI */ "no", /* CSLANGUAGE_NORWEGIAN */ "or", /* CSLANGUAGE_ORIYA */ "pl", /* CSLANGUAGE_POLISH */ "pt", /* CSLANGUAGE_PORTUGUESE */ "pa", /* CSLANGUAGE_PUNJABI */ "ro", "ru", /* CSLANGUAGE_RUSSIAN */ "sa", /* CSLANGUAGE_SANSKRIT */ "sr", /* CSLANGUAGE_SERBIAN */ "sd", /* CSLANGUAGE_SINDHI */ "sk", /* CSLANGUAGE_SLOVAK */ "sl", /* CSLANGUAGE_SLOVENIAN */ "es", "sw", /* CSLANGUAGE_SWAHILI */ "sv", /* CSLANGUAGE_SWEDISH */ "ta", /* CSLANGUAGE_TAMIL */ "tt", /* CSLANGUAGE_TATAR */ "te", /* CSLANGUAGE_TELUGU */ "th", /* CSLANGUAGE_THAI */ "tr", /* CSLANGUAGE_TURKISH */ "uk", /* CSLANGUAGE_UKRAINIAN */ "ur", /* CSLANGUAGE_URDU */ "uz", /* CSLANGUAGE_UZBEK */ "vi", /* CSLANGUAGE_VIETNAMES */ "es_CO", /* COLUMBIAN */ }; PUBLIC void csoundSetLanguage(cslanguage_t lang_code) { const char *name; if (lang_code == CSLANGUAGE_DEFAULT) fprintf(stderr, "Localisation of messages is disabled, using " "default language.\n"); else { fprintf(stderr, "Setting language of messages to %s ...\n", name=language_names[(int) lang_code]); setlocale(LC_MESSAGES, name); } return; } #endif PUBLIC char* cs_strtok_r(char* str, char* delim, char** nextp) { #ifdef HAVE_STRTOK_R return strtok_r(str, delim, nextp); #else /* * public domain strtok_r() by Charlie Gordon * * from comp.lang.c 9/14/2007 * * http://groups.google.com/group/comp.lang.c/msg/2ab1ecbb86646684 * * (Declaration that it's public domain): * http://groups.google.com/group/comp.lang.c/msg/7c7b39328fefab9c */ char *ret; if (str == NULL) { str = *nextp; } str += strspn(str, delim); if (*str == '\0') { return NULL; } ret = str; str += strcspn(str, delim); if (*str) { *str++ = '\0'; } *nextp = str; return ret; #endif } PUBLIC double cs_strtod(char* nptr, char** endptr) { #ifdef HAVE_STRTOD_L return strtod_l(nptr, endptr, csound_c_locale); #else return strtod(nptr, endptr); #endif } #if defined(HAVE_SPRINTF_L) PUBLIC int cs_sprintf(char *str, const char *format, ...) { // This is not thread-safe but no idea how to fix va_list args; int retVal; va_start(args, format); retVal = vsprintf_l(str,csound_c_locale,format,args); va_end(args); return retVal; } PUBLIC int cs_sscanf(char *str, const char *format, ...) { // This is not thread-safe but no idea how to fix va_list args; int retVal; va_start(args, format); retVal = vsscanf_l(str,csound_c_locale,format,args); va_end(args); return retVal; } #else #if defined(HAVE__SPRINT_L) PUBLIC int cs_sprintf(char *str, const char *format, ...) { // This is not thread-safe but no idea how to fix va_list args; int retVal; va_start(args, format); retVal = __vsprintf_l(str,csound_c_locale,format,args); va_end(args); return retVal; } PUBLIC int cs_sscanf(char *str, const char *format, ...) { // This is not thread-safe but no idea how to fix va_list args; int retVal; va_start(args, format); retVal = __vsscanf_l(str,csound_c_locale,format,args); va_end(args); return retVal; } #else PUBLIC int cs_sprintf(char *str, const char *format, ...) { // This is not thread-safe but no idea how to fix va_list args; int retVal; char *curlocale = setlocale(LC_NUMERIC, "C"); va_start(args, format); retVal = vsprintf(str,format,args); va_end(args); setlocale(LC_NUMERIC, curlocale); return retVal; } PUBLIC int cs_sscanf(char *str, const char *format, ...) { // This is not thread-safe but no idea how to fix va_list args; int retVal; char *curlocale = setlocale(LC_NUMERIC, "C"); va_start(args, format); retVal = vsscanf(str,format,args); va_end(args); setlocale(LC_NUMERIC, curlocale); return retVal; } #endif #endif csound-6.10.0/Top/init_static_modules.c000066400000000000000000000053201321653344700200510ustar00rootroot00000000000000/* init_static_modules.c: Copyright (C) 2016 Michael Gogins This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "csmodule.h" /* Do not declare these in header files; just define them in the module file * as extern "C", and declare them here as extern. */ extern int csoundModuleCreate_mixer(CSOUND *csound); extern int csoundModuleCreate_signalflowgraph(CSOUND *csound); extern int csoundModuleInit_ampmidid(CSOUND *); extern int csoundModuleInit_doppler(CSOUND *); extern int csoundModuleInit_fractalnoise(CSOUND *); extern int csoundModuleInit_ftsamplebank(CSOUND *); extern int csoundModuleInit_mixer(CSOUND *); extern int csoundModuleInit_signalflowgraph(CSOUND *); //# extern int csoundModuleInit_ableton_link_opcodes(CSOUND *); /** * Called from the beginning of csoundInitModules to initialize opcodes and * other modules that normally are dynamically loaded (e.g., C++ opcodes), * but that on other platforms (e.g. PNaCl) are statically linked. * * The pattern here is to define in the module source code a * "csoundModuleInit_XXX" function, where XXX is the basename of the * module file, and to call that function here. * * PLEASE NOTE: csoundModuleInit MUST call csoundModuleInit_XXX; * csoundModuleInit_XXX MUST NOT call csoundModuleInit. * * A similar pattern must be used if it is necessary to call * csoundModuleCreate, etc. */ int init_static_modules(CSOUND *csound) { int result = 0; csoundMessage(csound, "init_static_modules...\n"); result |= csoundModuleInit_ampmidid(csound); result |= csoundModuleInit_doppler(csound); result |= csoundModuleInit_fractalnoise(csound); result |= csoundModuleInit_ftsamplebank(csound); result |= csoundModuleCreate_mixer(csound); result |= csoundModuleInit_mixer(csound); result |= csoundModuleCreate_signalflowgraph(csound); result |= csoundModuleInit_signalflowgraph(csound); //# result |= csoundModuleInit_ableton_link_opcodes(csound); return result; } csound-6.10.0/Top/main.c000066400000000000000000000520631321653344700147410ustar00rootroot00000000000000/* main.c: Copyright (C) 1991-2002 Barry Vercoe, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "csoundCore.h" /* MAIN.C */ #include "soundio.h" #include "csmodule.h" #include "corfile.h" #include "csound_orc.h" #include "cs_par_base.h" #include "cs_par_orc_semantics.h" //#include "cs_par_dispatch.h" extern void allocate_message_queue(CSOUND *csound); CS_NORETURN void dieu(CSOUND *, char *, ...); int argdecode(CSOUND *, int, const char **); int init_pvsys(CSOUND *); // char *get_sconame(CSOUND *); void print_benchmark_info(CSOUND *, const char *); void openMIDIout(CSOUND *); int read_unified_file(CSOUND *, char **, char **); int read_unified_file2(CSOUND *csound, char *csd); int read_unified_file4(CSOUND *csound, CORFIL *csd); uintptr_t kperfThread(void * cs); void cs_init_math_constants_macros(CSOUND *csound, PRE_PARM *yyscanner); void cs_init_omacros(CSOUND *csound, PRE_PARM*, NAMES *nn); void csoundInputMessageInternal(CSOUND *csound, const char *message); int csoundCompileOrcInternal(CSOUND *csound, const char *str, int async); static void checkOptions(CSOUND *csound) { const char *csrcname; const char *home_dir; FILE *csrc = NULL; void *fd = NULL; char *s = NULL; /* IV - Feb 17 2005 */ csrcname = csoundGetEnv(csound, "CSOUND6RC"); if (csrcname != NULL && csrcname[0] != '\0') { fd = csound->FileOpen2(csound, &csrc, CSFILE_STD, csrcname, "r", NULL, CSFTYPE_OPTIONS, 0); if (UNLIKELY(fd == NULL)) csoundMessage(csound, Str("WARNING: cannot open csound6rc file %s\n"), csrcname); else csound->Message(csound, Str("Reading options from $CSOUND6RC: %s \n"), csrcname); } if (fd == NULL && ((home_dir = csoundGetEnv(csound, "HOME")) != NULL && home_dir[0] != '\0')) { s = csoundConcatenatePaths(csound, home_dir, ".csound6rc"); fd = csound->FileOpen2(csound, &csrc, CSFILE_STD, s, "r", NULL, CSFTYPE_OPTIONS, 0); if (fd != NULL) csound->Message(csound, Str("Reading options from $HOME/.csound6rc\n")); //csound->Free(csound, s); } /* read global .csound6rc file (if exists) */ if (fd != NULL) { CORFIL *cf = copy_to_corefile(csound, s, NULL, 0); corfile_rewind(cf); readOptions(csound, cf, 0); corfile_rm(csound, &cf); csound->FileClose(csound, fd); csound->Free(csound, s); } /* check for .csound6rc in current directory */ fd = csound->FileOpen2(csound, &csrc, CSFILE_STD, ".csound6rc", "r", NULL, CSFTYPE_OPTIONS, 0); if (fd != NULL) { CORFIL *cf = copy_to_corefile(csound, ".csound6rc", NULL, 0); corfile_rewind(cf); readOptions(csound, cf, 0); csound->Message(csound, Str("Reading options from local directory .csound6rc \n")); corfile_rm(csound, &cf); csound->FileClose(csound, fd); } } PUBLIC int csoundCompileArgs(CSOUND *csound, int argc, const char **argv) { OPARMS *O = csound->oparms; char *s; FILE *xfile = NULL; int n; int csdFound = 0; char *fileDir; if ((n = setjmp(csound->exitjmp)) != 0) { return ((n - CSOUND_EXITJMP_SUCCESS) | CSOUND_EXITJMP_SUCCESS); } if (UNLIKELY(csound->engineStatus & CS_STATE_COMP)) { csound->Message(csound, Str("Csound is already started, call csoundReset()\n" "before starting again.\n")); return CSOUND_ERROR; } if (UNLIKELY(--argc <= 0)) { dieu(csound, Str("insufficient arguments")); } /* command line: allow orc/sco/csd name */ csound->orcname_mode = 0; /* 0: normal, 1: ignore, 2: fail */ if (UNLIKELY(argdecode(csound, argc, argv) == 0)) csound->LongJmp(csound, 1); /* do not allow orc/sco/csd name in .csound6rc */ csound->orcname_mode = 2; checkOptions(csound); if (csound->delayederrormessages) { if (O->msglevel>8) csound->Warning(csound, "%s", csound->delayederrormessages); csound->Free(csound, csound->delayederrormessages); csound->delayederrormessages = NULL; } /* check for CSD file */ if (csound->orchname == NULL) { if (csound->info_message_request) { csound->info_message_request = 0; csound->LongJmp(csound, 1); } else if (UNLIKELY(csound->oparms->daemon == 0)) dieu(csound, Str("no orchestra name")); } else if (csound->use_only_orchfile == 0 && (csound->scorename == NULL || csound->scorename[0] == (char) 0) && csound->orchname[0] != '\0') { /* FIXME: allow orc/sco/csd name in CSD file: does this work ? */ csound->orcname_mode = 0; csound->Message(csound, "UnifiedCSD: %s\n", csound->orchname); /* Add directory of CSD file to search paths before orchname gets * replaced with temp orch name if default paths is enabled */ if (!O->noDefaultPaths) { fileDir = csoundGetDirectoryForPath(csound, csound->orchname); csoundAppendEnv(csound, "SADIR", fileDir); csoundAppendEnv(csound, "SSDIR", fileDir); csoundAppendEnv(csound, "INCDIR", fileDir); csoundAppendEnv(csound, "MFDIR", fileDir); csound->Free(csound, fileDir); } if (csound->orchname != NULL) { csound->csdname = csound->orchname; /* save original CSD name */ { CORFIL *cf = copy_to_corefile(csound, csound->csdname, NULL, 0); if (UNLIKELY(cf == NULL)) { csound->Die(csound, Str("Reading CSD failed ... stopping")); } corfile_rewind(cf); if (UNLIKELY(!read_unified_file4(csound, cf))) { csound->Die(csound, Str("Reading CSD failed ... stopping")); } /* cf is deleted in read_unified_file4 */ } csdFound = 1; } } /* IV - Feb 19 2005: run a second pass of argdecode so that */ /* command line options override CSD options */ /* this assumes that argdecode is safe to run multiple times */ csound->orcname_mode = 1; /* ignore orc/sco name */ argdecode(csound, argc, argv); /* should not fail this time */ /* some error checking */ if (UNLIKELY(csound->stdin_assign_flg && (csound->stdin_assign_flg & (csound->stdin_assign_flg - 1)) != 0)) { csound->Die(csound, Str("error: multiple uses of stdin")); } if (UNLIKELY(csound->stdout_assign_flg && (csound->stdout_assign_flg & (csound->stdout_assign_flg - 1)) != 0)) { csound->Die(csound, Str("error: multiple uses of stdout")); } /* done parsing csound6rc, CSD, and command line options */ if (csound->scorename == NULL && csound->scorestr==NULL) { /* No scorename yet */ csound->Message(csound, "scoreless operation\n"); // csound->scorestr = corfile_create_r("f0 800000000000.0 \n"); // VL 21-09-2016: it looks like #exit is needed for the // new score parser to work. csound->scorestr = corfile_create_r(csound, "\n#exit\n"); corfile_flush(csound, csound->scorestr); if (O->RTevents) csound->Message(csound, Str("realtime performance using dummy " "numeric scorefile\n")); } else if (!csdFound && !O->noDefaultPaths){ /* Add directory of SCO file to search paths*/ fileDir = csoundGetDirectoryForPath(csound, csound->scorename); csoundAppendEnv(csound, "SADIR", fileDir); csoundAppendEnv(csound, "SSDIR", fileDir); csoundAppendEnv(csound, "MFDIR", fileDir); csound->Free(csound, fileDir); } /* Add directory of ORC file to search paths*/ if (!csdFound && !O->noDefaultPaths) { fileDir = csoundGetDirectoryForPath(csound, csound->orchname); csoundAppendEnv(csound, "SADIR", fileDir); csoundAppendEnv(csound, "SSDIR", fileDir); csoundAppendEnv(csound, "MFDIR", fileDir); csound->Free(csound, fileDir); } if (csound->orchstr==NULL && csound->orchname) { /* does not deal with search paths */ csound->Message(csound, Str("orchname: %s\n"), csound->orchname); csound->orcLineOffset = 1; /* Guess -- JPff */ csound->orchstr = copy_to_corefile(csound, csound->orchname, NULL, 0); if (UNLIKELY(csound->orchstr==NULL)) csound->Die(csound, Str("main: failed to open input file - %s\n"), csound->orchname); corfile_puts(csound, "\n#exit\n", csound->orchstr); corfile_putc(csound, '\0', csound->orchstr); corfile_putc(csound, '\0', csound->orchstr); corfile_rewind(csound->orchstr); //csound->orchname = NULL; } if (csound->xfilename != NULL) csound->Message(csound, "xfilename: %s\n", csound->xfilename); csoundLoadExternals(csound); /* load plugin opcodes */ /* VL: added this also to csoundReset() in csound.c */ if (csoundInitModules(csound) != 0) csound->LongJmp(csound, 1); if (UNLIKELY(csoundCompileOrcInternal(csound, NULL, 0) != 0)){ if (csound->oparms->daemon == 0) csoundDie(csound, Str("cannot compile orchestra")); else { /* VL -- 21-10-13 Csound does not need to die on failure to compile. It can carry on, because new instruments can be compiled again */ if (csound->oparms->daemon == 0) csound->Warning(csound, Str("cannot compile orchestra.\n" "Csound will start with no instruments")); } } csound->modules_loaded = 1; s = csoundQueryGlobalVariable(csound, "_RTMIDI"); if (csound->enableHostImplementedMIDIIO == 1) { if (s) { strcpy(s, "hostbased"); } csoundSetConfigurationVariable(csound,"rtmidi", "hostbased"); } /* IV - Jan 28 2005 */ print_benchmark_info(csound, Str("end of orchestra compile")); if (UNLIKELY(!csoundYield(csound))) return -1; /* IV - Oct 31 2002: now we can read and sort the score */ if (csound->scorename != NULL && (n = strlen(csound->scorename)) > 4 && /* if score ?.srt or ?.xtr */ (!strcmp(csound->scorename + (n - 4), ".srt") || !strcmp(csound->scorename + (n - 4), ".xtr"))) { csound->Message(csound, Str("using previous %s\n"), csound->scorename); //playscore = sortedscore = csound->scorename; /* use that one */ csound->scorestr = NULL; csound->scorestr = copy_to_corefile(csound, csound->scorename, NULL, 1); } else { //sortedscore = NULL; if (csound->scorestr==NULL) { csound->scorestr = copy_to_corefile(csound, csound->scorename, NULL, 1); if (UNLIKELY(csound->scorestr==NULL)) csoundDie(csound, Str("cannot open scorefile %s"), csound->scorename); } csound->Message(csound, Str("sorting score ...\n")); //printf("score:\n%s", corfile_current(csound->scorestr)); scsortstr(csound, csound->scorestr); if (csound->keep_tmp) { FILE *ff = fopen("score.srt", "w"); fputs(corfile_body(csound->scstr), ff); fclose(ff); } } if (csound->xfilename != NULL) { /* optionally extract */ if (UNLIKELY(!(xfile = fopen(csound->xfilename, "r")))) csoundDie(csound, Str("cannot open extract file %s"),csound->xfilename); csoundNotifyFileOpened(csound, csound->xfilename, CSFTYPE_EXTRACT_PARMS, 0, 0); csound->Message(csound, Str(" ... extracting ...\n")); scxtract(csound, csound->scstr, xfile); fclose(xfile); csound->tempStatus &= ~csPlayScoMask; } csound->Message(csound, Str("\t... done\n")); /* copy sorted score name */ O->playscore = csound->scstr; /* IV - Jan 28 2005 */ print_benchmark_info(csound, Str("end of score sort")); if (O->syntaxCheckOnly) { csound->Message(csound, Str("Syntax check completed.\n")); return CSOUND_EXITJMP_SUCCESS; } /* open MIDI output (moved here from argdecode) */ if (O->Midioutname != NULL && O->Midioutname[0] == (char) '\0') O->Midioutname = NULL; if (O->FMidioutname != NULL && O->FMidioutname[0] == (char) '\0') O->FMidioutname = NULL; if (O->Midioutname != NULL || O->FMidioutname != NULL) openMIDIout(csound); return CSOUND_SUCCESS; } extern int playopen_dummy(CSOUND *, const csRtAudioParams *parm); extern void rtplay_dummy(CSOUND *, const MYFLT *outBuf, int nbytes); extern int recopen_dummy(CSOUND *, const csRtAudioParams *parm); extern int rtrecord_dummy(CSOUND *, MYFLT *inBuf, int nbytes); extern void rtclose_dummy(CSOUND *); extern int audio_dev_list_dummy(CSOUND *, CS_AUDIODEVICE *, int); extern int midi_dev_list_dummy(CSOUND *csound, CS_MIDIDEVICE *list, int isOutput); extern int DummyMidiInOpen(CSOUND *csound, void **userData, const char *devName); extern int DummyMidiRead(CSOUND *csound, void *userData, unsigned char *buf, int nbytes); extern int DummyMidiOutOpen(CSOUND *csound, void **userData, const char *devName); extern int DummyMidiWrite(CSOUND *csound, void *userData, const unsigned char *buf, int nbytes); PUBLIC int csoundStart(CSOUND *csound) // DEBUG { OPARMS *O = csound->oparms; int n; /* if a CSD was not used, check options */ if (csound->csdname == NULL) checkOptions(csound); if (UNLIKELY(csound->engineStatus & CS_STATE_COMP)){ csound->Message(csound, Str("Csound is already started, call csoundReset()\n" "before starting again.\n")); return CSOUND_ERROR; } { /* test for dummy module request */ char *s; if ((s = csoundQueryGlobalVariable(csound, "_RTAUDIO")) != NULL) if (strcmp(s, "null") == 0 || strcmp(s, "Null") == 0 || strcmp(s, "NULL") == 0) { csound->Message(csound, Str("setting dummy interface\n")); csound->SetPlayopenCallback(csound, playopen_dummy); csound->SetRecopenCallback(csound, recopen_dummy); csound->SetRtplayCallback(csound, rtplay_dummy); csound->SetRtrecordCallback(csound, rtrecord_dummy); csound->SetRtcloseCallback(csound, rtclose_dummy); csound->SetAudioDeviceListCallback(csound, audio_dev_list_dummy); } /* and midi */ if (csound->enableHostImplementedMIDIIO == 0){ if ((s = csoundQueryGlobalVariable(csound, "_RTMIDI")) != NULL) if (strcmp(s, "null") == 0 || strcmp(s, "Null") == 0 || strcmp(s, "NULL") == 0) { csound->SetMIDIDeviceListCallback(csound, midi_dev_list_dummy); csound->SetExternalMidiInOpenCallback(csound, DummyMidiInOpen); csound->SetExternalMidiReadCallback(csound, DummyMidiRead); csound->SetExternalMidiInCloseCallback(csound, NULL); csound->SetExternalMidiOutOpenCallback(csound, DummyMidiOutOpen); csound->SetExternalMidiWriteCallback(csound, DummyMidiWrite); csound->SetExternalMidiOutCloseCallback(csound, NULL); } } else { s = csoundQueryGlobalVariable(csound, "_RTMIDI"); if (s) strcpy(s, "hostbased"); csoundSetConfigurationVariable(csound,"rtmidi", "hostbased"); } } /* VL 30-12-12 csoundInitModules is always called here now to enable Csound to start without calling csoundCompile, but directly from csoundCompileOrc() and csoundReadSco() */ if (csound->modules_loaded == 0){ csoundLoadExternals(csound); /* load plugin opcodes */ if (csoundInitModules(csound) != 0) csound->LongJmp(csound, 1); csound->modules_loaded = 1; } if (csound->instr0 == NULL) { /* compile dummy instr0 to allow csound to start with no orchestra */ csoundCompileOrcInternal(csound, "idummy = 0 \n", 0); } if ((n = setjmp(csound->exitjmp)) != 0) { return ((n - CSOUND_EXITJMP_SUCCESS) | CSOUND_EXITJMP_SUCCESS); } /* if sound file type is still not known, check SFOUTYP */ if (O->filetyp <= 0) { const char *envoutyp; envoutyp = csoundGetEnv(csound, "SFOUTYP"); if (envoutyp != NULL && envoutyp[0] != '\0') { if (strcmp(envoutyp, "AIFF") == 0) O->filetyp = TYP_AIFF; else if (strcmp(envoutyp, "WAV") == 0 || strcmp(envoutyp, "WAVE") == 0) O->filetyp = TYP_WAV; else if (strcmp(envoutyp, "IRCAM") == 0) O->filetyp = TYP_IRCAM; else if (strcmp(envoutyp, "RAW") == 0) O->filetyp = TYP_RAW; else { dieu(csound, Str("%s not a recognised SFOUTYP env setting"), envoutyp); } } else #if !defined(__MACH__) O->filetyp = TYP_WAV; /* default to WAV if even SFOUTYP is unset */ #else O->filetyp = TYP_AIFF; /* ... or AIFF on the Mac */ #endif } /* everything other than a raw sound file has a header */ O->sfheader = (O->filetyp == TYP_RAW ? 0 : 1); if (O->Linein || O->Midiin || O->FMidiin) O->RTevents = 1; if (!O->sfheader) O->rewrt_hdr = 0; /* cannot rewrite header of headerless file */ /* VL 9 04 15: these not need occur jointly anymore */ /* if (O->sr_override || O->kr_override) { if (!O->sr_override || !O->kr_override) dieu(csound, Str("srate and krate overrides must occur jointly")); } */ if (!O->outformat) /* if no audioformat yet */ O->outformat = AE_SHORT; /* default to short_ints */ O->sfsampsize = sfsampsize(FORMAT2SF(O->outformat)); O->informat = O->outformat; /* informat default */ if (O->numThreads > 1) { void csp_barrier_alloc(CSOUND *, void **, int); int i; THREADINFO *current = NULL; csp_barrier_alloc(csound, &(csound->barrier1), O->numThreads); csp_barrier_alloc(csound, &(csound->barrier2), O->numThreads); csound->multiThreadedComplete = 0; for (i = 1; i < O->numThreads; i++) { THREADINFO *t = csound->Malloc(csound, sizeof(THREADINFO)); t->threadId = csound->CreateThread(&kperfThread, (void *)csound); t->next = NULL; if (current == NULL) { csound->multiThreadedThreadInfo = t; } else { current->next = t; } current = t; } csound->WaitBarrier(csound->barrier2); } csound->engineStatus |= CS_STATE_COMP; if (csound->oparms->daemon > 1) csoundUDPServerStart(csound,csound->oparms->daemon); allocate_message_queue(csound); /* if de-alloc by reset */ return musmon(csound); } PUBLIC int csoundCompile(CSOUND *csound, int argc, const char **argv){ int result = csoundCompileArgs(csound,argc,argv); if (result == CSOUND_SUCCESS) return csoundStart(csound); else return result; } PUBLIC int csoundCompileCsd(CSOUND *csound, const char *str) { CORFIL *tt = copy_to_corefile(csound, str, NULL, 0); if (LIKELY(tt != NULL)) { int res = csoundCompileCsdText(csound, tt->body); corfile_rm(csound, &tt); return res; } return CSOUND_ERROR; } PUBLIC int csoundCompileCsdText(CSOUND *csound, const char *csd_text) { //csound->oparms->odebug = 1; /* *** SWITCH ON EXTRA DEBUGGING *** */ int res = read_unified_file4(csound, corfile_create_r(csound, csd_text)); if (LIKELY(res)) { if (csound->csdname != NULL) csound->Free(csound, csound->csdname); csound->csdname = cs_strdup(csound, "*string*"); /* Mark as from text. */ res = csoundCompileOrcInternal(csound, NULL, 0); if (res == CSOUND_SUCCESS){ if ((csound->engineStatus & CS_STATE_COMP) != 0) { char *sc = scsortstr(csound, csound->scorestr); if (sc) { if(csound->oparms->odebug) csound->Message(csound, Str("Real-time score events (engineStatus: %d).\n"), csound->engineStatus); csoundInputMessage(csound, (const char *) sc); } } else { scsortstr(csound, csound->scorestr); if(csound->oparms->odebug) csound->Message(csound, Str("Compiled score " "(engineStatus: %d).\n"), csound->engineStatus); } } return res; } else return CSOUND_ERROR; } csound-6.10.0/Top/new_opts.c000066400000000000000000000175201321653344700156520ustar00rootroot00000000000000/* new_opts.c: Copyright (C) 2005 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /** * Assignment to configuration variables from the command line can be done * with '-+NAME=VALUE'. Boolean variables can be set to true with any of * '-+NAME', '-+NAME=1', '-+NAME=yes', '-+NAME=on', and '-+NAME=true', * while setting to false is possible with any of '-+no-NAME', '-+NAME=0', * '-+NAME=no', '-+NAME=off', and '-+NAME=false'. */ #include #include #include #include "csoundCore.h" #include "csound.h" #include "new_opts.h" /* list command line usage of all registered configuration variables */ void dump_cfg_variables(CSOUND *csound) { csCfgVariable_t **p; int i; p = csoundListConfigurationVariables(csound); if (p == NULL) return; if (p[0] == NULL) return; csound->Message(csound, "\n"); i = 0; do { csound->Message(csound, "-+%s=", (char*) ((p[i])->h.name)); switch ((p[i])->h.type) { case CSOUNDCFG_INTEGER: csound->Message(csound, Str("")); if ((p[i])->i.min > -0x7FFFFFFF) csound->Message(csound, ", %s%d", Str("min: "), (p[i])->i.min); if ((p[i])->i.max < 0x7FFFFFFF) csound->Message(csound, ", %s%d", Str("max: "), (p[i])->i.max); if ((p[i])->i.flags & CSOUNDCFG_POWOFTWO) csound->Message(csound, ", %s", Str("must be power of two")); break; case CSOUNDCFG_BOOLEAN: csound->Message(csound, Str("")); break; case CSOUNDCFG_FLOAT: csound->Message(csound, Str("")); if ((p[i])->f.min > -1.0e24f) csound->Message(csound, ", %s%g", Str("min: "), (double) (p[i])->f.min); if ((p[i])->f.max < 1.0e24f) csound->Message(csound, ", %s%g", Str("max: "), (double) (p[i])->f.max); break; case CSOUNDCFG_DOUBLE: csound->Message(csound, Str("")); if ((p[i])->d.min > -1.0e24) csound->Message(csound, ", %s%g", Str("min: "), (double) (p[i])->d.min); if ((p[i])->d.max < 1.0e24) csound->Message(csound, ", %s%g", Str("max: "), (double) (p[i])->d.max); break; case CSOUNDCFG_MYFLT: csound->Message(csound, Str("")); if ((p[i])->m.min > ((MYFLT) -1.0e24)) csound->Message(csound, ", %s%g", Str("min: "), (double) (p[i])->m.min); if ((p[i])->m.max < ((MYFLT) 1.0e24)) csound->Message(csound, ", %s%g", Str("max: "), (double) (p[i])->m.max); break; case CSOUNDCFG_STRING: csound->Message(csound, Str(" (max. length = %d characters)"), (p[i])->s.maxlen - 1); break; default: csound->Message(csound, Str("")); } csound->Message(csound, "\n"); if ((p[i])->h.longDesc != NULL) csound->Message(csound, "\t%s\n", Str((char*) p[i]->h.longDesc)); else if ((p[i])->h.shortDesc != NULL) csound->Message(csound, "\t%s\n", Str((char*) p[i]->h.shortDesc)); } while (p[++i] != NULL); } /* Parse 's' as an assignment to a configuration variable in the format */ /* '-+NAME=VALUE'. In the case of boolean variables, the format may also */ /* be '-+NAME' for true, and '-+no-NAME' for false. */ /* Return value is zero on success. */ int parse_option_as_cfgvar(CSOUND *csound, const char *s) { csCfgVariable_t *p; if (UNLIKELY((int) strlen(s) < 3)) { csound->Warning(csound, Str(" *** '%s' is not a valid " "Csound command line option."), s); csound->Warning(csound, Str(" *** Type 'csound --help' for the list of " "available options")); return 0; } if (UNLIKELY(strncmp(s, "-+", 2) != 0)) { csound->Warning(csound, Str(" *** '%s' is not a valid " "Csound command line option."), s); csound->Warning(csound, Str(" *** Type 'csound --help' for the list of " "available options")); return 0; } if (strchr(s, '=') == NULL) { /* there is no '=' character, must be a boolean */ p = csoundQueryConfigurationVariable(csound, s + 2); if (p != NULL) { if (UNLIKELY(p->h.type != CSOUNDCFG_BOOLEAN)) { csound->Warning(csound, Str(" *** type of option '%s' " "is not boolean"), s + 2); return 0; } *(p->b.p) = 1; } else if (LIKELY((int) strlen(s) > 5)) { if (UNLIKELY(strncmp(s, "-+no-", 5) != 0)) { csound->Warning(csound, Str(" *** '%s': invalid option name"), s + 2); return 0; } p = csoundQueryConfigurationVariable(csound, s + 5); if (UNLIKELY(p == NULL)) { csound->Warning(csound, Str(" *** '%s': invalid option name"), s + 2); return -1; } if (UNLIKELY(p->h.type != CSOUNDCFG_BOOLEAN)) { csound->Warning(csound, Str(" *** type of option '%s' " "is not boolean"), s + 2); return 0; } *(p->b.p) = 0; } else { csound->Warning(csound, Str(" *** '%s': invalid option name"), s + 2); return 0; } } else if (LIKELY((int) strlen(s) > 3)) { char *buf, *val, *tmp; int retval; buf = (char*) csound->Malloc(csound, sizeof(char) * (size_t) ((int) strlen(s) - 1)); if (UNLIKELY(buf == NULL)) { csound->Warning(csound, Str(" *** memory allocation failure")); return -1; } /* strcpy(buf, s + 2); */ val = (char*) s+2; tmp = buf; while (*val!='\0') { /* * CAN char used during the parsing in CsOptions to mark * the removable characters '\'. ETX char used to mark * the limits of a string. */ if (*val != 0x18 && *val != 3) *tmp++ = *val; val++; } *tmp='\0'; val = strchr(buf, '='); *(val++) = '\0'; /* 'buf' is now the name, 'val' is the value string */ retval = csoundParseConfigurationVariable(csound, buf, val); if (UNLIKELY(retval != CSOUNDCFG_SUCCESS)) { csound->Warning(csound, Str(" *** error setting option '%s' to '%s': %s"), buf, val, csoundCfgErrorCodeToString(retval)); csound->Free(csound, (void*) buf); return 0; } csound->Free(csound, (void*) buf); } else { csound->Warning(csound, Str(" *** '%s' is not a valid " "Csound command line option."), s); csound->Warning(csound, Str(" *** Type 'csound --help' for the list of " "available options.")); return 0; } return 0; } csound-6.10.0/Top/one_file.c000066400000000000000000001137271321653344700156020ustar00rootroot00000000000000/* one_file.c: Copyright (C) 1998 John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include int mkstemp(char *); #include #include #include #include "corfile.h" #if defined(LINUX) || defined(__MACH__) || defined(WIN32) # include # include #endif #define CSD_MAX_LINE_LEN 4096 #define CSD_MAX_ARGS 100 # undef L_tmpnam # define L_tmpnam (200) #ifndef TRUE # define TRUE (1) #endif #ifndef FALSE # define FALSE (0) #endif //#define _DEBUG /* These are used to set/clear bits in csound->tempStatus. If the bit is set, it indicates that the given file is a temporary. */ const uint32_t csOrcMask = 1; const uint32_t csScoInMask = 2; const uint32_t csScoSortMask = 4; const uint32_t csMidiScoMask = 8; const uint32_t csPlayScoMask = 16; #define STA(x) (csound->onefileStatics.x) CS_NOINLINE char *csoundTmpFileName(CSOUND *csound, const char *ext) { #define nBytes (256) char lbuf[256]; #if defined(WIN32) && !defined(__CYGWIN__) struct _stat tmp; #else struct stat tmp; #endif do { #ifndef WIN32 int fd; char *tmpdir = getenv("TMPDIR"); if (tmpdir != NULL && tmpdir[0] != '\0') snprintf(lbuf, nBytes, "%s/csound-XXXXXX", tmpdir); else strcpy(lbuf, "/tmp/csound-XXXXXX"); umask(0077); /* ensure exclusive access on buggy implementations of mkstemp */ if (UNLIKELY((fd = mkstemp(lbuf)) < 0)) csound->Die(csound, Str(" *** cannot create temporary file")); close(fd); //unlink(lbuf); #else { char *s = (char*) csoundGetEnv(csound, "SFDIR"); if (s == NULL) s = (char*) csoundGetEnv(csound, "HOME"); s = _tempnam(s, "cs"); if (UNLIKELY(s == NULL)) csound->Die(csound, Str(" *** cannot create temporary file")); strncpy(lbuf, s, nBytes); free(s); } #endif if (ext != NULL && ext[0] != (char) 0) { #if !defined(LINUX) && !defined(__MACH__) && !defined(WIN32) char *p; /* remove original extension (does not work on OS X */ /* and may be a bad idea) */ if ((p = strrchr(lbuf, '.')) != NULL) *p = '\0'; #endif strlcat(lbuf, ext, nBytes); } #ifdef __MACH__ /* on MacOS X, store temporary files in /tmp instead of /var/tmp */ /* (suggested by Matt Ingalls) */ if (strncmp(lbuf, "/var/tmp/", 9) == 0) { int i = 3; do { i++; lbuf[i - 4] = lbuf[i]; } while (lbuf[i] != '\0'); } #endif #if defined(WIN32) } while (_stat(lbuf, &tmp) == 0); #else /* if the file already exists, try again */ } while (stat(lbuf, &tmp) == 0); #endif return cs_strdup(csound, lbuf); } static inline void alloc_globals(CSOUND *csound) { /* count lines from 0 so that it adds OK to orc/sco counts */ STA(csdlinecount) = 0; } static char *my_fgets(CSOUND *csound, char *s, int n, FILE *stream) { char *a = s; if (UNLIKELY(n <= 1)) return NULL; /* best of a bad deal */ do { int ch = getc(stream); if (UNLIKELY(ch == EOF)) { /* error or EOF */ if (s == a) return NULL; /* no chars -> leave */ if (ferror(stream)) a = NULL; break; /* add NULL even if ferror(), spec says 'indeterminate' */ } if (ch == '\n' || ch == '\r') { /* end of line ? */ ++(STA(csdlinecount)); /* count the lines */ *(s++) = '\n'; /* convert */ if (ch == '\r') { ch = getc(stream); if (ch != '\n') /* Mac format */ ungetc(ch, stream); } break; } *(s++) = ch; } while (--n > 1); *s = '\0'; return a; } void remove_tmpfiles(CSOUND *csound) /* IV - Feb 03 2005 */ { /* use one fn to delete all temporary files */ alloc_globals(csound); while (STA(toremove) != NULL) { NAMELST *nxt = STA(toremove)->next; #ifdef BETA csoundMessage(csound, Str("Removing temporary file %s ...\n"), STA(toremove)->name); #endif if (UNLIKELY(remove(STA(toremove)->name))) csoundMessage(csound, Str("WARNING: could not remove %s\n"), STA(toremove)->name); csound->Free(csound, STA(toremove)->name); csound->Free(csound, STA(toremove)); STA(toremove) = nxt; } } void add_tmpfile(CSOUND *csound, char *name) /* IV - Feb 03 2005 */ { /* add temporary file to delete list */ NAMELST *tmp; alloc_globals(csound); tmp = (NAMELST*) csound->Malloc(csound, sizeof(NAMELST)); tmp->name = (char*) csound->Malloc(csound, strlen(name) + 1); strcpy(tmp->name, name); tmp->next = STA(toremove); STA(toremove) = tmp; } static int blank_buffer(/*CSOUND *csound,*/ char *buffer) { const char *s; for (s = &(buffer[0]); *s != '\0' && *s != '\n'; s++) { if (*s == ';') return TRUE; if (!isblank(*s)) return FALSE; } return TRUE; } /* Consider wrapping corfile_fgets for this function */ static char *my_fgets_cf(CSOUND *csound, char *s, int n, CORFIL *stream) { char *a = s; if (UNLIKELY(n <= 1)) return NULL; /* best of a bad deal */ do { int ch = corfile_getc(stream); if (UNLIKELY(ch == EOF)) { /* error or EOF */ if (s == a) return NULL; /* no chars -> leave */ break; } if (ch == '\n' || ch == '\r') { /* end of line ? */ ++(STA(csdlinecount)); /* count the lines */ *(s++) = '\n'; /* convert */ if (ch == '\r') { ch = corfile_getc(stream); if (ch != '\n') /* Mac format */ corfile_ungetc(stream); } break; } *(s++) = ch; } while (--n > 1); *s = '\0'; return a; } /* readingCsOptions should be non-zero when readOptions() is called while reading the tag, but zero in other cases. */ int readOptions(CSOUND *csound, CORFIL *cf, int readingCsOptions) { char *p; int argc = 0; const char *argv[CSD_MAX_ARGS]; char buffer[CSD_MAX_LINE_LEN]; //alloc_globals(csound); while (my_fgets_cf(csound, buffer, CSD_MAX_LINE_LEN, cf) != NULL) { p = buffer; /* Remove trailing spaces; rather heavy handed */ { int len = strlen(p)-2; while (len>0 && (isblank(p[len]))) len--; p[len+1] = '\n'; p[len+2] = '\0'; } while (isblank(*p)) p++; if (readingCsOptions && strstr(p, "") == p) { return TRUE; } /** * Allow command options in unified CSD files * to begin with the Csound command, so that * the command line arguments can be exactly the same in unified files * as for regular command line invocation. */ if (*p==';' || *p=='#' || *p=='\n') continue; /* empty or comment line? */ argc = 0; argv[0] = p; while (isblank(*p)) p++; /* Ignore leading space */ if (*p=='-') { /* Deal with case where no command name is given */ argv[0] = "csound"; argv[1] = p; argc++; } while (*p != '\0') { if (isblank(*p)) { *p++ = '\0'; #ifdef _DEBUG csoundMessage(csound, "argc=%d argv[%d]=%s\n", argc, argc, argv[argc]); #endif while (isblank(*p)) p++; if (*p== '"') { if (UNLIKELY(argc == CSD_MAX_ARGS)) csoundDie(csound, Str("More than %d arguments in "), CSD_MAX_ARGS); argv[++argc] = ++p; while (*p != '"' && *p != '\0') { if (*p == '\\' && *(p+1) != '\0') p++; p++; } if (*p == '"') { /* ETX char used to mark the limits of a string */ *p = (isspace(*(p+1)) ? '\0' : 3); } // break; } if (*p==';' || *p=='#' || (*p == '/' && *(p+1) == '/')) { /* Comment line? */ *p = '\0'; break; } if (*p == '/' && *(p+1) == '*') { /* Comment line? */ p += 2; top: while (*p != '*' && *p != '\0') p++; if (*p == '*' && *(p+1)== '/') { p += 2; break; } if (*p=='*') { p++; goto top; } my_fgets_cf(csound, buffer, CSD_MAX_LINE_LEN, cf); p = buffer; goto top; } if (UNLIKELY(argc == CSD_MAX_ARGS)) csoundDie(csound, Str("More than %d arguments in "), CSD_MAX_ARGS); argv[++argc] = p; } else if (*p=='\n') { *p = '\0'; break; } else if (*p=='"') { int is_escape = 0; char *old = NULL; *p=3; /* ETX char used to mark the limits of a string */ while ((*p != '"' || is_escape) && *p != '\0') { if (is_escape) *old = 0x18; /* CAN char used to mark a removable character */ is_escape = (*p == '\\' ? !is_escape : 0); old = p; p++; } if (*p == '"') { if (isspace(*(p+1))) { *p = '\0'; break; } else { *p = 3; } } } p++; } //argc++; /* according to Nicola but wrong */ #ifdef _DEBUG { int i; for (i=0; i<=argc; i++) printf("%d: %s\n", i, argv[i]); } #endif /* Read an argv thing */ if (UNLIKELY(argc == 0)) { if (readingCsOptions) csoundErrorMsg(csound, Str("Invalid arguments in : %s"), buffer); else csoundErrorMsg(csound, Str("Invalid arguments in .csoundrc or -@ file: %s"), buffer); } else argdecode(csound, argc, argv); } if (UNLIKELY(readingCsOptions)) csoundErrorMsg(csound, Str("Missing end tag ")); return FALSE; } #if 1 static int all_blank(char* start, char* end) { while (start != end) { if (!isblank(*start)) return 0; start++; } return 1; } static int createOrchestra(CSOUND *csound, CORFIL *cf) { char *p, *q; CORFIL *incore = corfile_create_w(csound); char buffer[CSD_MAX_LINE_LEN]; int state = 0; csound->orcLineOffset = STA(csdlinecount)+1; nxt: while (my_fgets_cf(csound, buffer, CSD_MAX_LINE_LEN, cf)!= NULL) { int c; p = buffer; if (state == 0 && (q = strstr(p, "")) && all_blank(buffer,q)) { csound->Message(csound, "closing tag\n"); //corfile_flush(incore); corfile_puts(csound, "\n#exit\n", incore); corfile_putc(csound, '\0', incore); corfile_putc(csound, '\0', incore); csound->orchstr = incore; return TRUE; } top: if (*p == '\0') continue; if (state==0) { while ((c = *p++)) { if (c=='"') { corfile_putc(csound, c,incore); state = 1; goto top;} else if (c=='/' && *p=='*') { corfile_putc(csound, c,incore); corfile_putc(csound, *p++,incore); state = 2; goto top; } else if (c == ';'|| (c=='/' && *p=='/')) { corfile_puts(csound, p-1, incore); goto nxt; } else if (c=='{' && *p=='{') { corfile_putc(csound, c,incore); corfile_putc(csound, *p++,incore); state = 3; goto top; } corfile_putc(csound, c, incore); } } else if (state == 1) { /* string */ while (((c=*p++))) { corfile_putc(csound, c, incore); if (c=='\\') { corfile_putc(csound, *p++, incore); if (*p=='\0') goto top; } else if (c=='"') { state = 0; goto top;} } csoundErrorMsg(csound, Str("missing \" to terminate string")); corfile_rm(csound, &incore); return FALSE; } else if (state == 2) { /* multiline comment */ while ( (c = *p++)) { if (c=='*' && *p=='/') { corfile_putc(csound, c,incore); corfile_putc(csound, *p++,incore); state = 0; goto top; } corfile_putc(csound, c, incore); } goto nxt; } else if (state == 3) { /* extended string */ while ( (c = *p++)) { if (c=='}' && *p=='}') { corfile_putc(csound, c,incore); corfile_putc(csound, *p++,incore); state = 0; goto top; } corfile_putc(csound, c, incore); } goto nxt; } } csoundErrorMsg(csound, Str("Missing end tag ")); corfile_rm(csound, &incore); return FALSE; } #else static int createOrchestra(CSOUND *csound, CORFIL *cf) { char *p; CORFIL *incore = corfile_create_w(csound); char buffer[CSD_MAX_LINE_LEN]; int comm = 0; csound->orcLineOffset = STA(csdlinecount)+1; while (my_fgets_cf(csound, buffer, CSD_MAX_LINE_LEN, cf)!= NULL) { p = buffer; while (isblank(*p)) p++; if(*p == '/' && *(p+1) == '*') { //csound->Message(csound, "comment start\n"); comm = 1; p += 2; } if (comm == 0 && strstr(p, "") == p) { //csound->Message(csound, "closing tag\n"); //corfile_flush(incore); corfile_puts(csound, "\n#exit\n", incore); corfile_putc(csound, '\0', incore); corfile_putc(csound, '\0', incore); csound->orchstr = incore; return TRUE; } else if (comm) { while (p < buffer + CSD_MAX_LINE_LEN){ if(*p == '*' && *(p+1) == '/') { comm = 0; // csound->Message(csound, "comment end\n"); break; } else p++; } corfile_puts(csound, buffer, incore); } else corfile_puts(csound, buffer, incore); } csoundErrorMsg(csound, Str("Missing end tag ")); corfile_rm(csound, &incore); return FALSE; } #endif #if 1 static int createScore(CSOUND *csound, CORFIL *cf) { char *p, *q; int state = 0; char buffer[CSD_MAX_LINE_LEN]; if (csound->scorestr == NULL) csound->scorestr = corfile_create_w(csound); csound->scoLineOffset = STA(csdlinecount); nxt: while (my_fgets_cf(csound, buffer, CSD_MAX_LINE_LEN, cf)!= NULL) { int c; p = buffer; if (state == 0 && (q = strstr(p, "")) && all_blank(buffer,q)) { corfile_puts(csound, "\n#exit\n", csound->scorestr); corfile_putc(csound, '\0', csound->scorestr); /* For use in bison/flex */ corfile_putc(csound, '\0', csound->scorestr); /* For use in bison/flex */ return TRUE; } top: if (*p == '\0') continue; if (state==0) { while ((c = *p++)) { if (c=='"') { corfile_putc(csound, c,csound->scorestr); state = 1; goto top;} else if (c=='/' && *p=='*') { corfile_putc(csound, c,csound->scorestr); corfile_putc(csound, *p++,csound->scorestr); state = 2; goto top; } else if (c == ';'|| (c=='/' && *p=='/')) { corfile_puts(csound, p-1, csound->scorestr); goto nxt; } corfile_putc(csound, c, csound->scorestr); } } else if (state == 1) { /* string */ while (((c=*p++))) { corfile_putc(csound, c, csound->scorestr); if (c=='\\') { corfile_putc(csound, *p++, csound->scorestr); if (*p=='\0') goto top; } else if (c=='"') { state = 0; goto top;} } csoundErrorMsg(csound, Str("missing \" to terminate string")); corfile_rm(csound, &csound->scorestr); return FALSE; } else if (state == 2) { /* multiline comment */ while ( (c = *p++)) { if (c=='*' && *p=='/') { corfile_putc(csound, c,csound->scorestr); corfile_putc(csound, *p++,csound->scorestr); state = 0; goto top; } corfile_putc(csound, c, csound->scorestr); } goto nxt; } } csoundErrorMsg(csound, Str("Missing end tag ")); return FALSE; } #else static int createScore(CSOUND *csound, CORFIL *cf) { char *p; char buffer[CSD_MAX_LINE_LEN]; if (csound->scorestr == NULL) csound->scorestr = corfile_create_w(csound); csound->scoLineOffset = STA(csdlinecount); while (my_fgets_cf(csound, buffer, CSD_MAX_LINE_LEN, cf)!= NULL) { p = buffer; while (isblank(*p)) p++; if (strstr(p, "") == p) { //#ifdef SCORE_PARSER corfile_puts(csound, "\n#exit\n", csound->scorestr); corfile_putc(csound, '\0', csound->scorestr); /* For use in bison/flex */ corfile_putc(csound, '\0', csound->scorestr); /* For use in bison/flex */ //#endif return TRUE; } else corfile_puts(csound, buffer, csound->scorestr); } csoundErrorMsg(csound, Str("Missing end tag ")); return FALSE; } #endif static int createExScore(CSOUND *csound, char *p, CORFIL *cf) { #ifdef IOS csoundErrorMsg(csound, "External scores not supported on iOS"); return FALSE; #else char *extname; char *q; char prog[256]; void *fd; FILE *scof; char buffer[CSD_MAX_LINE_LEN]; p = strstr(p, "bin=\""); if (UNLIKELY(p==NULL)) { csoundErrorMsg(csound, Str("Missing program in tag ")); return FALSE; } q = strchr(p+5, '"'); if (UNLIKELY(q==NULL)) { /* No program given */ csoundErrorMsg(csound, Str("Missing program in tag ")); return FALSE; } *q = '\0'; strncpy(prog, p+5, 255); prog[255]='\0';/* after "tempStatus |= csScoInMask; #ifdef _DEBUG csoundMessage(csound, Str("Creating %s (%p)\n"), extname, scof); #endif if (UNLIKELY(fd == NULL)) { csound->Free(csound, extname); return FALSE; } csound->scoLineOffset = STA(csdlinecount); while (my_fgets_cf(csound, buffer, CSD_MAX_LINE_LEN, cf)!= NULL) { p = buffer; if (strstr(p, "") == p) { char sys[1024]; csoundFileClose(csound, fd); snprintf(sys, 1024, "%s %s %s", prog, extname, STA(sconame)); if (UNLIKELY(system(sys) != 0)) { csoundErrorMsg(csound, Str("External generation failed")); if (UNLIKELY(remove(extname) || remove(STA(sconame)))) csoundErrorMsg(csound, Str("and cannot remove")); csound->Free(csound, extname); return FALSE; } if (UNLIKELY(remove(extname))) csoundErrorMsg(csound, Str("and cannot remove %s"), extname); if (csound->scorestr == NULL) csound->scorestr = corfile_create_w(csound); fd = csoundFileOpenWithType(csound, &scof, CSFILE_STD, STA(sconame), "r", NULL, CSFTYPE_SCORE, 0); if (UNLIKELY(fd == NULL)) { csoundErrorMsg(csound, Str("cannot open %s"), STA(sconame)); if (UNLIKELY(remove(STA(sconame)))) csoundErrorMsg(csound, Str("and cannot remove %s"), STA(sconame)); csound->Free(csound, extname); return FALSE; } csoundMessage(csound, Str("opened %s\n"), STA(sconame)); while (my_fgets(csound, buffer, CSD_MAX_LINE_LEN, scof)!= NULL) corfile_puts(csound, buffer, csound->scorestr); csoundMessage(csound, Str("closing %s\n"), STA(sconame)); csoundFileClose(csound, fd); if (UNLIKELY(remove(STA(sconame)))) csoundErrorMsg(csound, Str("and cannot remove %s\n"), STA(sconame)); corfile_puts(csound, "\n#exit\n", csound->scorestr); corfile_putc(csound, '\0', csound->scorestr); corfile_putc(csound, '\0', csound->scorestr); //corfile_rewind(csound->scorestr); /* necessary? */ csound->Free(csound, extname); //27363 return TRUE; } else fputs(buffer, scof); } csoundErrorMsg(csound, Str("Missing end tag ")); csound->Free(csound, extname); return FALSE; #endif } static void read_base64(CSOUND *csound, CORFIL *in, FILE *out) { int c; int n, nbits; n = nbits = 0; while ((c = corfile_getc(in)) != '=' && c != '<') { while (isspace(c)) { if (c == '\n') { /* count lines */ ++(STA(csdlinecount)); c = corfile_getc(in); } else if (c == '\r') { ++(STA(csdlinecount)); c = corfile_getc(in); if (c == '\n') c = corfile_getc(in); /* DOS format */ } else c = corfile_getc(in); } if (c == '=' || c == '<' || c == EOF) break; n <<= 6; nbits += 6; if (isupper(c)) c -= 'A'; else if (islower(c)) c -= ((int) 'a' - 26); else if (isdigit(c)) c -= ((int) '0' - 52); else if (c == '+') c = 62; else if (c == '/') c = 63; else { csoundDie(csound, Str("Non base64 character %c(%2x)"), c, c); } n |= (c & 0x3F); if (nbits >= 8) { nbits -= 8; c = (n >> nbits) & 0xFF; n &= ((1 << nbits) - 1); putc(c, out); } } if (c == '<') corfile_ungetc(in); if (nbits >= 8) { nbits -= 8; c = (n >> nbits) & 0xFF; n &= ((1 << nbits) - 1); putc(c, out); } if (UNLIKELY(nbits > 0 && n != 0)) { csoundDie(csound, Str("Truncated byte at end of base64 stream")); } } #ifdef JPFF static void read_base64_2cor(CSOUND *csound, CORFIL *in, CORFIL *out) { int c; int n, nbits; n = nbits = 0; while ((c = corfile_getc(in)) != '=' && c != '<') { while (isspace(c)) { if (c == '\n') { /* count lines */ ++(STA(csdlinecount)); c = corfile_getc(in); } else if (c == '\r') { ++(STA(csdlinecount)); c = corfile_getc(in); if (c == '\n') c = corfile_getc(in); /* DOS format */ } else c = corfile_getc(in); } if (c == '=' || c == '<' || c == EOF) break; n <<= 6; nbits += 6; if (isupper(c)) c -= 'A'; else if (islower(c)) c -= ((int) 'a' - 26); else if (isdigit(c)) c -= ((int) '0' - 52); else if (c == '+') c = 62; else if (c == '/') c = 63; else { csoundDie(csound, Str("Non base64 character %c(%2x)"), c, c); } n |= (c & 0x3F); if (nbits >= 8) { nbits -= 8; c = (n >> nbits) & 0xFF; n &= ((1 << nbits) - 1); corfile_putc(csound, c, out); } } if (c == '<') corfile_ungetc(in); if (nbits >= 8) { nbits -= 8; c = (n >> nbits) & 0xFF; n &= ((1 << nbits) - 1); corfile_putc(csound, c, out); } if (UNLIKELY(nbits > 0 && n != 0)) { csoundDie(csound, Str("Truncated byte at end of base64 stream")); } } #endif static int createMIDI2(CSOUND *csound, CORFIL *cf) { char *p; FILE *midf; void *fd; char buffer[CSD_MAX_LINE_LEN]; /* Generate MIDI file name */ if (STA(midname)) free(STA(midname)); STA(midname) = csoundTmpFileName(csound, ".mid"); fd = csoundFileOpenWithType(csound, &midf, CSFILE_STD, STA(midname), "wb", NULL, CSFTYPE_STD_MIDI, 1); if (UNLIKELY(fd == NULL)) { csoundDie(csound, Str("Cannot open temporary file (%s) for MIDI subfile"), STA(midname)); } csound->tempStatus |= csMidiScoMask; read_base64(csound, cf, midf); csoundFileClose(csound, fd); add_tmpfile(csound, STA(midname)); /* IV - Feb 03 2005 */ STA(midiSet) = TRUE; while (TRUE) { if (my_fgets_cf(csound, buffer, CSD_MAX_LINE_LEN, cf)!= NULL) { p = buffer; while (isblank(*p)) p++; if (strstr(p, "") == p) { return TRUE; } } } csoundErrorMsg(csound, Str("Missing end tag ")); return FALSE; } static int createSample(CSOUND *csound, char *buffer, CORFIL *cf) { int num; FILE *smpf; void *fd; char sampname[256]; /* char buffer[CSD_MAX_LINE_LEN]; */ sscanf(buffer, "", &num); snprintf(sampname, 256, "soundin.%d", num); if (UNLIKELY((smpf = fopen(sampname, "rb")) != NULL)) { fclose(smpf); csoundDie(csound, Str("File %s already exists"), sampname); } fd = csoundFileOpenWithType(csound, &smpf, CSFILE_STD, sampname, "wb", NULL, CSFTYPE_UNKNOWN_AUDIO, 1); if (UNLIKELY(fd == NULL)) { csoundDie(csound, Str("Cannot open sample file (%s) subfile"), sampname); } read_base64(csound, cf, smpf); csoundFileClose(csound, fd); add_tmpfile(csound, sampname); /* IV - Feb 03 2005 */ while (TRUE) { if (my_fgets_cf(csound, buffer, CSD_MAX_LINE_LEN, cf)!= NULL) { char *p = buffer; while (isblank(*p)) p++; if (strstr(p, "") == p) { return TRUE; } } } csoundErrorMsg(csound, Str("Missing end tag ")); return FALSE; } static int createFile(CSOUND *csound, char *buffer, CORFIL *cf) { FILE *smpf; void *fd; char filename[256]; char *p = buffer, *q; filename[0] = '\0'; p += 18; /* 18== strlen("'); if (q) *q='\0'; // printf("p=>>%s<<\n", p); strncpy(filename, p, 255); filename[255]='\0'; //sscanf(buffer, "", filename); // if (filename[0] != '\0' && // filename[strlen(filename) - 1] == '>' && // filename[strlen(filename) - 2] == '"') // filename[strlen(filename) - 2] = '\0'; if (UNLIKELY((smpf = fopen(filename, "rb")) != NULL)) { fclose(smpf); csoundDie(csound, Str("File %s already exists"), filename); } fd = csoundFileOpenWithType(csound, &smpf, CSFILE_STD, filename, "wb", NULL, CSFTYPE_UNKNOWN, 1); if (UNLIKELY(fd == NULL)) { csoundDie(csound, Str("Cannot open file (%s) subfile"), filename); } read_base64(csound, cf, smpf); csoundFileClose(csound, fd); add_tmpfile(csound, filename); /* IV - Feb 03 2005 */ while (TRUE) { if (my_fgets_cf(csound, buffer, CSD_MAX_LINE_LEN, cf)!= NULL) { char *p = buffer; while (isblank(*p)) p++; if (strstr(p, "") == p) { return TRUE; } } } csoundErrorMsg(csound, Str("Missing end tag ")); return FALSE; } #ifdef JPFF static int createCorfile(CSOUND *csound, char *buffer, CORFIL *cf) { CORFIL *smpf; char filename[256]; char *p = buffer, *q; filename[0] = '\0'; p += 18; /* 18== strlen("'); if (q) *q='\0'; // printf("p=>>%s<<\n", p); strncpy(filename, p, 255); filename[255]='\0'; //sscanf(buffer, "", filename); // if (filename[0] != '\0' && // filename[strlen(filename) - 1] == '>' && // filename[strlen(filename) - 2] == '"') // filename[strlen(filename) - 2] = '\0'; smpf = corfile_create_w(csound); read_base64_2cor(csound, cf, smpf); corfile_rewind(smpf); add_corfile(csound, smpf, filename); while (TRUE) { if (my_fgets_cf(csound, buffer, CSD_MAX_LINE_LEN, cf)!= NULL) { char *p = buffer; while (isblank(*p)) p++; if (strstr(p, "") == p) { return TRUE; } } } csoundErrorMsg(csound, Str("Missing end tag ")); return FALSE; } #endif static int createFilea(CSOUND *csound, char *buffer, CORFIL *cf) { FILE *smpf; void *fd; char filename[256]; char buff[1024]; char *p = buffer, *q; int res=FALSE; filename[0] = '\0'; p += 17; /* 17== strlen("'); if (q) *q='\0'; // printf("p=>>%s<<\n", p); strncpy(filename, p, 255); filename[255]='\0'; if (UNLIKELY((smpf = fopen(filename, "r")) != NULL)) { fclose(smpf); csoundDie(csound, Str("File %s already exists"), filename); } fd = csoundFileOpenWithType(csound, &smpf, CSFILE_STD, filename, "w", NULL, CSFTYPE_UNKNOWN, 1); if (UNLIKELY(fd == NULL)) { csoundDie(csound, Str("Cannot open file (%s) subfile"), filename); } while (corfile_fgets(buff, 1024, cf)!=NULL) { char *p = buff; while (isblank(*p)) p++; if (!strncmp(p, "", 9)) { /* stop on antitag at start of line */ res = TRUE; break; } fputs(buff, smpf); } if (UNLIKELY(res==FALSE)) csoundErrorMsg(csound, Str("Missing end tag ")); csoundFileClose(csound, fd); add_tmpfile(csound, filename); /* IV - Feb 03 2005 */ return res; } static int checkVersion(CSOUND *csound, CORFIL *cf) { char *p; int major = 0, minor = 0; int result = TRUE; int version = csoundGetVersion(); char buffer[CSD_MAX_LINE_LEN]; while (my_fgets_cf(csound, buffer, CSD_MAX_LINE_LEN, cf) != NULL) { p = buffer; while (isblank(*p)) p++; if (strstr(p, "") != NULL) return result; if (strstr(p, "Before") != NULL) { sscanf(p, "Before %d.%d", &major, &minor); if (UNLIKELY(version >= ((major * 1000) + (minor*10)))) { csoundDie(csound, Str("This CSD file requires a version of " "Csound before %d.%02d"), major, minor); result = FALSE; } } else if (strstr(p, "After") != NULL) { sscanf(p, "After %d.%d", &major, &minor); if (UNLIKELY(version <= ((major * 1000) + (minor*10)))) { csoundDie(csound, Str("This CSD file requires a version of " "Csound after %d.%02d"), major, minor); result = FALSE; } } else if (strstr(p, "Later") != NULL) { sscanf(p, "Later %d.%d", &major, &minor); if (UNLIKELY(version < ((major * 1000) + (minor*10)))) { csoundDie(csound, Str("This CSD file requires version " "Csound %d.%02d or later"), major, minor); result = FALSE; } } else if (sscanf(p, "%d.%d", &major, &minor) == 2) { if (UNLIKELY(version <= ((major * 1000) + (minor*10)))) { csoundDie(csound, Str("This CSD file requires version " "%d.%02d of Csound"), major, minor); result = FALSE; } } } csoundErrorMsg(csound, Str("Missing end tag ")); return FALSE; } static int checkLicence(CSOUND *csound, CORFIL *cf) { char *p, *licence; int len = 1; char buffer[CSD_MAX_LINE_LEN]; csoundMessage(csound, Str("**** Licence Information ****\n")); licence = (char*) csound->Calloc(csound, len); while (my_fgets_cf(csound, buffer, CSD_MAX_LINE_LEN, cf) != NULL) { p = buffer; if (strstr(p, "") != NULL || strstr(p, "") != NULL) { csoundMessage(csound, Str("**** End of Licence Information ****\n")); csound->Free(csound, csound->SF_csd_licence); csound->SF_csd_licence = licence; return TRUE; } csoundMessage(csound, "%s", p); len += strlen(p); licence = csound->ReAlloc(csound, licence, len); strlcat(licence, p, len); } csound->Free(csound, licence); csoundErrorMsg(csound, Str("Missing end tag ")); return FALSE; } static int checkShortLicence(CSOUND *csound, CORFIL *cf) { int type = 0; char buff[CSD_MAX_LINE_LEN]; csoundMessage(csound, Str("**** Licence Information ****\n")); while (my_fgets_cf(csound, buff, CSD_MAX_LINE_LEN, cf) != NULL) { if (strstr(buff, "") != NULL || strstr(buff, "") != NULL) { csound->SF_id_scopyright = type; return TRUE; } type = atoi(buff); } csoundErrorMsg(csound, Str("Missing end tag ")); return FALSE; } int read_unified_file4(CSOUND *csound, CORFIL *cf) { int result = TRUE; int r; int started = FALSE; int notrunning = csound->engineStatus & CS_STATE_COMP; char buffer[CSD_MAX_LINE_LEN]; #ifdef _DEBUG //csoundMessage(csound, "Calling unified file system4\n"); #endif if (notrunning==0) { alloc_globals(csound); STA(orcname) = STA(sconame) = STA(midname) = NULL; STA(midiSet) = FALSE; } while (my_fgets_cf(csound, buffer, CSD_MAX_LINE_LEN, cf)) { char *p = buffer; while (isblank(*p)) p++; if (strstr(p, "") == p || strstr(p, "") == p) { csoundMessage(csound, Str("STARTING FILE\n")); started = TRUE; } else if (strstr(p, "") == p || strstr(p, "") == p) { if (csound->scorestr != NULL) corfile_flush(csound, csound->scorestr); corfile_rm(csound, &cf); if (notrunning && STA(midiSet)) { csound->oparms->FMidiname = STA(midname); csound->oparms->FMidiin = 1; } return result; } else if (strstr(p, "") == p) { if (!notrunning) { csoundMessage(csound, Str("Creating options\n")); csound->orchname = NULL; /* allow orchestra/score name in CSD file */ r = readOptions(csound, cf, 1); result = r && result; } else { csoundMessage(csound, Str("Skipping \n")); do { if (UNLIKELY(my_fgets_cf(csound, buffer, CSD_MAX_LINE_LEN, cf) == NULL)) { csoundErrorMsg(csound, Str("Missing end tag ")); result = FALSE; break; } p = buffer; while (isblank(*p)) p++; } while (strstr(p, "") != p); } } else if (strstr(p, "") == p) { csoundMessage(csound, Str("Creating orchestra\n")); r = createOrchestra(csound, cf); result = r && result; } else if (strstr(p, "") == p) r = createScore(csound, cf); else r = createExScore(csound, p, cf); result = r && result; } else if (strstr(p, "") == p) { if (notrunning) { r = createMIDI2(csound, cf); result = r && result; } else { csoundMessage(csound, Str("Skipping \n")); do { if (UNLIKELY(my_fgets_cf(csound, buffer, CSD_MAX_LINE_LEN, cf) == NULL)) { csoundErrorMsg(csound, Str("Missing end tag ")); result = FALSE; break; } p = buffer; while (isblank(*p)) p++; } while (strstr(p, "") != p); } } else if (strstr(p, "") == p) { r = checkVersion(csound, cf); result = r && result; } else if (strstr(p, "") == p || strstr(p, "") == p) { r = checkLicence(csound, cf); result = r && result; } else if (strstr(p, "") == p || strstr(p, "") == p) { r = checkShortLicence(csound, cf); result = r && result; } else if (blank_buffer(/*csound,*/ buffer)) continue; else if (started && strchr(p, '<') == buffer){ csoundMessage(csound, Str("unknown CSD tag: %s\n"), buffer); } } if (UNLIKELY(!started)) { csoundMessage(csound, Str("Could not find tag in CSD file.\n")); result = FALSE; } corfile_rm(csound, &cf); return result; } csound-6.10.0/Top/opcode.c000066400000000000000000000161701321653344700152650ustar00rootroot00000000000000/* opcode.c: Copyright (C) 1997 John ffitch (C) 2005 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* OPCODE.C */ /* Print opcodes in system */ /* John ffitch -- 26 Jan 97 */ /* 4 april 02 -- ma++ */ /* restructure to retrieve externally */ /* And suppressing deprecated Oct 2015 -- JPff */ #include "csoundCore.h" #include #include "interlocks.h" static int opcode_cmp_func(const void *a, const void *b) { opcodeListEntry *ep1 = (opcodeListEntry*) a; opcodeListEntry *ep2 = (opcodeListEntry*) b; int retval; if ((retval = strcmp(ep1->opname, ep2->opname)) != 0) return retval; if ((retval = strcmp(ep1->outypes, ep2->outypes)) != 0) return retval; if ((retval = strcmp(ep1->intypes, ep2->intypes)) != 0) return retval; if (ep1 < ep2) return -1; if (ep1 > ep2) return 1; return 0; } /** * Gets an alphabetically sorted list of all opcodes. * Should be called after externals are loaded by csoundCompile(). * Returns the number of opcodes, or a negative error code on failure. * Make sure to call csoundDisposeOpcodeList() when done with the list. */ PUBLIC int csoundNewOpcodeList(CSOUND *csound, opcodeListEntry **lstp) { void *lst = NULL; OENTRY *ep; char *s; size_t nBytes = (size_t) 0; int i, cnt = 0; CONS_CELL *head, *items, *temp; (*lstp) = NULL; if (UNLIKELY(csound->opcodes == NULL)) return -1; head = items = cs_hash_table_values(csound, csound->opcodes); /* count the number of opcodes, and bytes to allocate */ while (items != NULL) { temp = items->value; while (temp != NULL) { ep = temp->value; if (ep->opname != NULL && ep->opname[0] != '\0' && isalpha(ep->opname[0]) && ep->outypes != NULL && ep->intypes != NULL) { cnt++; nBytes += sizeof(opcodeListEntry); for (i = 0; ep->opname[i] != '\0' && ep->opname[i] != '.'; i++); nBytes += (size_t) i; nBytes += strlen(ep->outypes); nBytes += strlen(ep->intypes); nBytes += 3; /* for null characters */ } temp = temp->next; } items = items->next; } nBytes += sizeof(opcodeListEntry); /* allocate memory for opcode list */ lst = csound->Malloc(csound, nBytes); if (UNLIKELY(lst == NULL)) return CSOUND_MEMORY; (*lstp) = (opcodeListEntry*) lst; /* store opcodes in list */ items = head; s = (char*) lst + ((int) sizeof(opcodeListEntry) * (cnt + 1)); cnt = 0; while (items != NULL) { temp = items->value; while (temp != NULL) { ep = temp->value; if (ep->opname != NULL && ep->opname[0] != '\0' && isalpha(ep->opname[0]) && ep->outypes != NULL && ep->intypes != NULL) { for (i = 0; ep->opname[i] != '\0' && ep->opname[i] != '.'; i++) s[i] = ep->opname[i]; s[i++] = '\0'; ((opcodeListEntry*) lst)[cnt].opname = s; s += i; strcpy(s, ep->outypes); ((opcodeListEntry*) lst)[cnt].outypes = s; s += ((int) strlen(ep->outypes) + 1); strcpy(s, ep->intypes); ((opcodeListEntry*) lst)[cnt].intypes = s; s += ((int) strlen(ep->intypes) + 1); ((opcodeListEntry*) lst)[cnt].flags = ep->flags; //if (ep->flags&_QQ) printf("DEPRICATED: %s\n", ep->opname); //if (ep->flags&_QQ) *deprec++; cnt++; } temp = temp->next; } items = items->next; } ((opcodeListEntry*) lst)[cnt].opname = NULL; ((opcodeListEntry*) lst)[cnt].outypes = NULL; ((opcodeListEntry*) lst)[cnt].intypes = NULL; ((opcodeListEntry*) lst)[cnt].flags = 0; cs_cons_free(csound, head); /* sort list */ qsort(lst, (size_t) cnt, sizeof(opcodeListEntry), opcode_cmp_func); /* return the number of opcodes */ return cnt; } PUBLIC void csoundDisposeOpcodeList(CSOUND *csound, opcodeListEntry *lst) { csound->Free(csound, lst); } void list_opcodes(CSOUND *csound, int level) { opcodeListEntry *lst; const char *sp = " "; /* length should be 20 */ int j, k; int cnt, deprec = 0, len = 0, xlen = 0; cnt = csoundNewOpcodeList(csound, &lst); if (UNLIKELY(cnt <= 0)) { csound->ErrorMsg(csound, Str("Error creating opcode list")); csoundDisposeOpcodeList(csound, lst); return; } if ((level&2)==0) for (j=0; jMessage(csound, Str("%d opcodes\n"), cnt-deprec); for (j = 0, k = -1; j < cnt; j++) { if ((level&1) == 0) { /* Print in 4 columns */ if (j > 0 && strcmp(lst[j - 1].opname, lst[j].opname) == 0) continue; if ((level&2)==0 && ((lst[j].flags&_QQ) !=0)) { //printf("dropping %s\n", lst[j].opname); continue; } k++; xlen = 0; if (!(k & 3)) csound->Message(csound, "\n"); else { if (len > 19) { xlen = len - 19; len = 19; } csound->Message(csound, "%s", sp + len); } csound->Message(csound, "%s", lst[j].opname); len = (int) strlen(lst[j].opname) + xlen; } else { char *ans = lst[j].outypes, *arg = lst[j].intypes; if ((level&2)==0 && ((lst[j].flags&_QQ) !=0)) { //printf("dropping %s\n", lst[j].opname); continue; } csound->Message(csound, "%s", lst[j].opname); len = (int) strlen(lst[j].opname); if (len > 11) { xlen = len - 11; len = 11; } csound->Message(csound, "%s", sp + (len + 8)); if (ans == NULL || *ans == '\0') ans = "(null)"; if (arg == NULL || *arg == '\0') arg = "(null)"; csound->Message(csound, "%s", ans); len = (int) strlen(ans) + xlen; len = (len < 11 ? len : 11); xlen = 0; csound->Message(csound, "%s", sp + (len + 8)); csound->Message(csound, "%s\n", arg); } } csound->Message(csound, "\n"); csoundDisposeOpcodeList(csound, lst); } csound-6.10.0/Top/server.c000066400000000000000000000275251321653344700153300ustar00rootroot00000000000000/* server.c: Copyright (C) 2013 V Lazzarini, John ffitch This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef NACL typedef unsigned int u_int32_t; #endif #include "csoundCore.h" #if defined(WIN32) && !defined(__CYGWIN__) #include #include #else #include #include #include #endif typedef struct { int port; int sock; CSOUND *cs; void *thrid; void *cb; struct sockaddr_in server_addr; unsigned char status; } UDPCOM; #define MAXSTR 1048576 /* 1MB */ static void udp_socksend(CSOUND *csound, int *sock, const char *addr, int port, const char *msg) { struct sockaddr_in server_addr; if(*sock <= 0) { #if defined(WIN32) && !defined(__CYGWIN__) WSADATA wsaData = {0}; int err; if (UNLIKELY((err=WSAStartup(MAKEWORD(2,2), &wsaData))!= 0)) csound->Warning(csound, Str("UDP: Winsock2 failed to start: %d"), err); return; #endif *sock = socket(AF_INET, SOCK_DGRAM, 0); if (UNLIKELY(*sock < 0)) { csound->Warning(csound, Str("UDP: error creating socket")); return; } #ifndef WIN32 if (UNLIKELY(fcntl(*sock, F_SETFL, O_NONBLOCK)<0)) { csound->Warning(csound, Str("UDP Server: Cannot set nonblock")); if (*sock>=0) close(*sock); return; } #else { u_long argp = 1; err = ioctlsocket(*sock, FIONBIO, &argp); if (UNLIKELY(err != NO_ERROR)) { csound->Warning(csound, Str("UDP Server: Cannot set nonblock")); closesocket(*sock); return; } } #endif } server_addr.sin_family = AF_INET; /* it is an INET address */ #if defined(WIN32) && !defined(__CYGWIN__) server_addr.sin_addr.S_un.S_addr = inet_addr(addr); #else inet_aton(addr, &server_addr.sin_addr); /* the server IP address */ #endif server_addr.sin_port = htons((int) port); /* the port */ if (UNLIKELY(sendto(*sock, (void*) msg, strlen(msg)+1, 0, (const struct sockaddr *) &server_addr, sizeof(server_addr)) < 0)) { csound->Warning(csound, Str("UDP: sock end failed")); } } static uintptr_t udp_recv(void *pdata){ struct sockaddr from; socklen_t clilen = sizeof(from); UDPCOM *p = (UDPCOM *) pdata; CSOUND *csound = p->cs; int port = p->port; char *orchestra = csound->Calloc(csound, MAXSTR); int sock = 0; int received, cont = 0; char *start = orchestra; size_t timout = (size_t) lround(1000/csound->GetKr(csound)); csound->Message(csound, Str("UDP server started on port %d \n"),port); while (p->status) { if ((received = recvfrom(p->sock, (void *)orchestra, MAXSTR, 0, &from, &clilen)) <= 0) { csoundSleep(timout ? timout : 1); continue; } else { orchestra[received] = '\0'; // terminate string if(strlen(orchestra) < 2) continue; if (csound->oparms->echo) csound->Message(csound, "%s", orchestra); if (strncmp("!!close!!",orchestra,9)==0 || strncmp("##close##",orchestra,9)==0) { csoundInputMessageAsync(csound, "e 0 0"); break; } if(*orchestra == '&') { csoundInputMessageAsync(csound, orchestra+1); } else if(*orchestra == '$') { csoundReadScoreAsync(csound, orchestra+1); } else if(*orchestra == '@') { char chn[128]; MYFLT val; sscanf(orchestra+1, "%s", chn); val = atof(orchestra+1+strlen(chn)); csoundSetControlChannel(csound, chn, val); } else if(*orchestra == '%') { char chn[128]; char *str; sscanf(orchestra+1, "%s", chn); str = cs_strdup(csound, orchestra+1+strlen(chn)); csoundSetStringChannel(csound, chn, str); csound->Free(csound, str); } else if(*orchestra == ':') { char addr[128], chn[128], *msg; int sport, err = 0; MYFLT val; sscanf(orchestra+2, "%s", chn); sscanf(orchestra+2+strlen(chn), "%s", addr); sport = atoi(orchestra+3+strlen(addr)+strlen(chn)); if(*(orchestra+1) == '@') { val = csoundGetControlChannel(csound, chn, &err); msg = (char *) csound->Calloc(csound, strlen(chn) + 32); sprintf(msg, "%s::%f", chn, val); } else if (*(orchestra+1) == '%') { MYFLT *pstring; if (csoundGetChannelPtr(csound, &pstring, chn, CSOUND_STRING_CHANNEL | CSOUND_OUTPUT_CHANNEL) == CSOUND_SUCCESS) { STRINGDAT* stringdat = (STRINGDAT*) pstring; int size = stringdat->size; int *lock = csoundGetChannelLock(csound, (char*) chn); msg = (char *) csound->Calloc(csound, strlen(chn) + size); if (lock != NULL) csoundSpinLock(lock); sprintf(msg, "%s::%s", chn, stringdat->data); if (lock != NULL) csoundSpinUnLock(lock); } else err = -1; } else err = -1; if(!err) { udp_socksend(csound, &sock, addr, sport,msg); csound->Free(csound, msg); } else csound->Warning(csound, Str("could not retrieve channel %s"), chn); } else if(*orchestra == '{' || cont) { char *cp; if((cp = strrchr(orchestra, '}')) != NULL) { if(*(cp-1) != '}') { *cp = '\0'; cont = 0; } else { orchestra += received; cont = 1; } } else { orchestra += received; cont = 1; } if(!cont) { orchestra = start; //csound->Message(csound, "%s \n", orchestra+1); csoundCompileOrcAsync(csound, orchestra+1); } } else { //csound->Message(csound, "%s \n", orchestra); csoundCompileOrcAsync(csound, orchestra); } } } csound->Message(csound, Str("UDP server on port %d stopped\n"),port); csound->Free(csound, start); // csound->Message(csound, "orchestra dealloc\n"); if(sock > 0) #ifndef WIN32 close(sock); #else closesocket(sock); #endif return (uintptr_t) 0; } static int udp_start(CSOUND *csound, UDPCOM *p) { #if defined(WIN32) && !defined(__CYGWIN__) WSADATA wsaData = {0}; int err; if (UNLIKELY((err=WSAStartup(MAKEWORD(2,2), &wsaData))!= 0)){ csound->Warning(csound, Str("Winsock2 failed to start: %d"), err); return CSOUND_ERROR; } #endif p->cs = csound; p->sock = socket(AF_INET, SOCK_DGRAM, 0); #ifndef WIN32 if (UNLIKELY(fcntl(p->sock, F_SETFL, O_NONBLOCK)<0)) { csound->Warning(csound, Str("UDP Server: Cannot set nonblock")); if (p->sock>=0) close(p->sock); return CSOUND_ERROR; } #else { u_long argp = 1; err = ioctlsocket(p->sock, FIONBIO, &argp); if (UNLIKELY(err != NO_ERROR)) { csound->Warning(csound, Str("UDP Server: Cannot set nonblock")); closesocket(p->sock); return CSOUND_ERROR; } } #endif if (UNLIKELY(p->sock < 0)) { csound->Warning(csound, Str("error creating socket")); return CSOUND_ERROR; } /* create server address: where we want to send to and clear it out */ memset(&p->server_addr, 0, sizeof(p->server_addr)); p->server_addr.sin_family = AF_INET; /* it is an INET address */ p->server_addr.sin_addr.s_addr = htonl(INADDR_ANY); p->server_addr.sin_port = htons((int) p->port); /* the port */ /* associate the socket with the address and port */ if (UNLIKELY(bind(p->sock, (struct sockaddr *) &p->server_addr, sizeof(p->server_addr)) < 0)) { csound->Warning(csound, Str("bind failed")); p->thrid = NULL; #ifndef WIN32 close(p->sock); #else closesocket(p->sock); #endif return CSOUND_ERROR; } /* set status flag */ p->status = 1; /* create thread */ p->thrid = csoundCreateThread(udp_recv, (void *) p); return CSOUND_SUCCESS; } int csoundUDPServerClose(CSOUND *csound) { UDPCOM *p = (UDPCOM *) csound->QueryGlobalVariable(csound,"::UDPCOM"); if (p != NULL) { /* unset status flag */ p->status = 0; /* wait for server thread to close */ csoundJoinThread(p->thrid); /* close socket */ #ifndef WIN32 close(p->sock); #else closesocket(p->sock); #endif csound->DestroyGlobalVariable(csound,"::UDPCOM"); return CSOUND_SUCCESS; } else return CSOUND_ERROR; } int csoundUDPServerStart(CSOUND *csound, unsigned int port){ UDPCOM *connection; csound->CreateGlobalVariable(csound, "::UDPCOM", sizeof(UDPCOM)); connection = (UDPCOM *) csound->QueryGlobalVariable(csound, "::UDPCOM"); if (connection != NULL){ connection->port = port; if(connection->status) { csound->Warning(csound, Str("UDP Server: already running")); return CSOUND_ERROR; } else { int res = udp_start(csound, connection); if (res != CSOUND_SUCCESS) { csound->Warning(csound, Str("UDP Server: could not start")); csound->DestroyGlobalVariable(csound,"::UDPCOM"); return CSOUND_ERROR; } else return CSOUND_SUCCESS; } } else { csound->Warning(csound, Str("UDP Server: failed to allocate memory")); return CSOUND_ERROR; } } int csoundUDPServerStatus(CSOUND *csound) { UDPCOM *p = (UDPCOM *) csound->QueryGlobalVariable(csound,"::UDPCOM"); if (p != NULL) { return p->port; } else return CSOUND_ERROR; } #define UDPMSG 1024 typedef struct { int port; const char *addr; int sock; void (*cb)(CSOUND *csound,int attr, const char *format, va_list args); } UDPCONS; static void udp_msg_callback(CSOUND *csound, int attr, const char *format, va_list args) { UDPCONS *p; p = (UDPCONS *) csound->QueryGlobalVariable(csound, "::UDPCONS"); if(p) { char string[UDPMSG]; va_list nargs; va_copy(nargs, args); vsnprintf(string, UDPMSG, format, args); udp_socksend(csound, &(p->sock), p->addr, p->port, string); if(p->cb) p->cb(csound, attr, format, nargs); va_end(nargs); } } static int udp_console_stop(CSOUND *csound, void *pp) { UDPCONS *p = (UDPCONS *) pp; if(p) { csoundSetMessageCallback(csound, p->cb); #ifndef WIN32 close(p->sock); #else closesocket(p->sock); #endif csound->DestroyGlobalVariable(csound,"::UDPCONS"); } return CSOUND_SUCCESS; } int csoundUDPConsole(CSOUND *csound, const char *addr, int port, int mirror) { UDPCONS *p = (UDPCONS *) csound->QueryGlobalVariable(csound, "::UDPCONS"); if(p == NULL) { csound->CreateGlobalVariable(csound, "::UDPCONS", sizeof(UDPCONS)); p = (UDPCONS *) csound->QueryGlobalVariable(csound, "::UDPCONS"); if(p) { p->port = port; p->addr = cs_strdup(csound, (char *) addr); p->sock = 0; if(mirror) p->cb = csound->csoundMessageCallback_; csound->SetMessageCallback(csound, udp_msg_callback); csound->RegisterResetCallback(csound, p, udp_console_stop); } else { csound->Warning(csound, "Could not set UDP console \n"); return CSOUND_ERROR; } return CSOUND_SUCCESS; } return CSOUND_ERROR; } void csoundStopUDPConsole(CSOUND *csound) { UDPCONS *p; csound->CreateGlobalVariable(csound, "::UDPCONS", sizeof(UDPCONS)); p = (UDPCONS *) csound->QueryGlobalVariable(csound, "::UDPCONS"); udp_console_stop(csound, p); } csound-6.10.0/Top/threads.c000066400000000000000000000627561321653344700154610ustar00rootroot00000000000000/* threads.c: This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #if defined(__linux) || defined(__linux__) /* for pthread_mutex_timedlock() */ #define _XOPEN_SOURCE 600 #endif #ifndef HAVE_GETTIMEOFDAY #if defined(LINUX) || defined(__unix) || defined(__unix__) || \ defined(__MACH__) || defined(__HAIKU__) #define HAVE_GETTIMEOFDAY 1 #endif #endif #include "csoundCore.h" #if 0 static CS_NOINLINE void notImplementedWarning_(const char *name) { #ifndef __EMSCRIPTEN__ fprintf(stderr, Str("%s() is not implemented on this platform.\n"), name); #endif } #endif #if defined(HAVE_PTHREAD) #if defined(WIN32) #include #include void gettimeofday_(struct timeval* p, void* tz /* IGNORED */) { union { long long ns100; /*time since 1 Jan 1601 in 100ns units */ FILETIME ft; } now; GetSystemTimeAsFileTime( &(now.ft) ); p->tv_usec=(long)((now.ns100 / 10LL) % 1000000LL ); p->tv_sec= (long)((now.ns100-(116444736000000000LL))/10000000LL); } /** * Runs an external command with the arguments specified in 'argv'. * argv[0] is the name of the program to execute (if not a full path * file name, it is searched in the directories defined by the PATH * environment variable). The list of arguments should be terminated * by a NULL pointer. * If 'noWait' is zero, the function waits until the external program * finishes, otherwise it returns immediately. In the first case, a * non-negative return value is the exit status of the command (0 to * 255), otherwise it is the PID of the newly created process. * On error, a negative value is returned. */ PUBLIC long csoundRunCommand(const char * const *argv, int noWait) { long retval; if (argv == NULL || argv[0] == NULL) return -1L; retval = (long) _spawnvp((noWait ? (int) _P_NOWAIT : (int) _P_WAIT), argv[0], argv); if (!noWait && retval >= 0L) retval &= 255L; return retval; } PUBLIC void csoundSleep(size_t milliseconds) { Sleep((DWORD) milliseconds); } #else #include /** * Runs an external command with the arguments specified in 'argv'. * argv[0] is the name of the program to execute (if not a full path * file name, it is searched in the directories defined by the PATH * environment variable). The list of arguments should be terminated * by a NULL pointer. * If 'noWait' is zero, the function waits until the external program * finishes, otherwise it returns immediately. In the first case, a * non-negative return value is the exit status of the command (0 to * 255), otherwise it is the PID of the newly created process. * On error, a negative value is returned. */ PUBLIC long csoundRunCommand(const char * const *argv, int noWait) { long retval; if (argv == NULL || argv[0] == NULL) return -1L; retval = (long) fork(); if (retval == 0L) { /* child process */ if (execvp(argv[0], (char**) argv) != 0) exit(-1); /* this is not actually reached */ exit(0); } else if (retval > 0L && noWait == 0) { int status = 0; while (waitpid((pid_t) retval, &status, 0) != (pid_t) ECHILD) { if (WIFEXITED(status) != 0) { retval = (long) (WEXITSTATUS(status)) & 255L; return retval; } if (WIFSIGNALED(status) != 0) { retval = 255L; return retval; } } retval = 255L; } return retval; } PUBLIC void csoundSleep(size_t milliseconds) { struct timespec ts; register size_t n, s; s = milliseconds / (size_t) 1000; n = milliseconds - (s * (size_t) 1000); n = (size_t) ((int) n * 1000000); ts.tv_sec = (time_t) s; ts.tv_nsec = (long) n; while (nanosleep(&ts, &ts) != 0) ; } #endif #include #include #include #include #include #define BARRIER_SERIAL_THREAD (-1) #if !defined(HAVE_PTHREAD_BARRIER_INIT) #if !defined( __MACH__)&&!defined(__HAIKU__)&&!defined(ANDROID)&& \ !defined(NACL)&&!defined(__CYGWIN__) typedef struct barrier { pthread_mutex_t mut; pthread_cond_t cond; unsigned int count, max, iteration; } barrier_t; #endif #endif PUBLIC void *csoundCreateThread(uintptr_t (*threadRoutine)(void *), void *userdata) { pthread_t *pthread = (pthread_t *) malloc(sizeof(pthread_t)); if (!pthread_create(pthread, (pthread_attr_t*) NULL, (void *(*)(void *)) threadRoutine, userdata)) { return (void*) pthread; } free(pthread); return NULL; } PUBLIC void *csoundGetCurrentThreadId(void) { pthread_t *ppthread = (pthread_t *)malloc(sizeof(pthread_t)); *ppthread = pthread_self(); /* This version wastes space but works */ return ppthread; } PUBLIC uintptr_t csoundJoinThread(void *thread) { void *threadRoutineReturnValue = NULL; int pthreadReturnValue; pthread_t *pthread = (pthread_t *)thread; if(thread == NULL) return 0; pthreadReturnValue = pthread_join(*pthread, &threadRoutineReturnValue); if (pthreadReturnValue) { return (uintptr_t) ((intptr_t) pthreadReturnValue); } else { return (uintptr_t) threadRoutineReturnValue; } } #if !defined(ANDROID) && (/*defined(LINUX) ||*/ defined(__HAIKU__) || defined(WIN32)) PUBLIC void *csoundCreateThreadLock(void) { pthread_mutex_t *pthread_mutex; pthread_mutex = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t)); if (pthread_mutex == NULL) return NULL; if (pthread_mutex_init(pthread_mutex, NULL) != 0) { free(pthread_mutex); return NULL; } return (void*) pthread_mutex; } PUBLIC int csoundWaitThreadLock(void *lock, size_t milliseconds) { { register int retval = pthread_mutex_trylock((pthread_mutex_t*) lock); if (!retval) return retval; if (!milliseconds) return retval; } { struct timeval tv; struct timespec ts; register size_t n, s; #ifndef HAVE_GETTIMEOFDAY gettimeofday_(&tv, NULL); #else gettimeofday(&tv, NULL); #endif s = milliseconds / (size_t) 1000; n = milliseconds - (s * (size_t) 1000); s += (size_t) tv.tv_sec; n = (size_t) (((int) n * 1000 + (int) tv.tv_usec) * 1000); ts.tv_nsec = (long) (n < (size_t) 1000000000 ? n : n - 1000000000); ts.tv_sec = (time_t) (n < (size_t) 1000000000 ? s : s + 1); return pthread_mutex_timedlock((pthread_mutex_t*) lock, &ts); } } PUBLIC void csoundWaitThreadLockNoTimeout(void *lock) { pthread_mutex_lock((pthread_mutex_t*) lock); } PUBLIC void csoundNotifyThreadLock(void *lock) { pthread_mutex_unlock((pthread_mutex_t*) lock); } PUBLIC void csoundDestroyThreadLock(void *lock) { if (0==pthread_mutex_destroy((pthread_mutex_t*) lock)) free(lock); else perror("csoundDestroyThreadLock: "); } #else /* LINUX */ typedef struct CsoundThreadLock_s { pthread_mutex_t m; pthread_cond_t c; unsigned char s; } CsoundThreadLock_t; PUBLIC void *csoundCreateThreadLock(void) { CsoundThreadLock_t *p; p = (CsoundThreadLock_t*) malloc(sizeof(CsoundThreadLock_t)); if (p == NULL) return NULL; memset(p, 0, sizeof(CsoundThreadLock_t)); if (pthread_mutex_init(&(p->m), (pthread_mutexattr_t*) NULL) != 0) { free((void*) p); return NULL; } if (pthread_cond_init(&(p->c), (pthread_condattr_t*) NULL) != 0) { pthread_mutex_destroy(&(p->m)); free((void*) p); return NULL; } p->s = (unsigned char) 1; return (void*) p; } PUBLIC int csoundWaitThreadLock(void *threadLock, size_t milliseconds) { CsoundThreadLock_t *p; int retval = 0; p = (CsoundThreadLock_t*) threadLock; pthread_mutex_lock(&(p->m)); if (!p->s) { if (milliseconds) { struct timeval tv; struct timespec ts; register size_t n, s; #ifndef HAVE_GETTIMEOFDAY gettimeofday_(&tv, NULL); #else gettimeofday(&tv, NULL); #endif s = milliseconds / (size_t) 1000; n = milliseconds - (s * (size_t) 1000); s += (size_t) tv.tv_sec; n = (size_t) (((int) n * 1000 + (int) tv.tv_usec) * 1000); ts.tv_nsec = (long) (n < (size_t) 1000000000 ? n : n - 1000000000); ts.tv_sec = (time_t) (n < (size_t) 1000000000 ? s : s + 1); do { retval = pthread_cond_timedwait(&(p->c), &(p->m), &ts); } while (!p->s && !retval); } else retval = ETIMEDOUT; } p->s = (unsigned char) 0; pthread_mutex_unlock(&(p->m)); return retval; } PUBLIC void csoundWaitThreadLockNoTimeout(void *threadLock) { CsoundThreadLock_t *p; p = (CsoundThreadLock_t*) threadLock; pthread_mutex_lock(&(p->m)); while (!p->s) { pthread_cond_wait(&(p->c), &(p->m)); } p->s = (unsigned char) 0; pthread_mutex_unlock(&(p->m)); } PUBLIC void csoundNotifyThreadLock(void *threadLock) { CsoundThreadLock_t *p; p = (CsoundThreadLock_t*) threadLock; pthread_mutex_lock(&(p->m)); p->s = (unsigned char) 1; pthread_cond_signal(&(p->c)); pthread_mutex_unlock(&(p->m)); } PUBLIC void csoundDestroyThreadLock(void *threadLock) { CsoundThreadLock_t *p; if (threadLock == NULL) return; csoundNotifyThreadLock(threadLock); p = (CsoundThreadLock_t*) threadLock; pthread_cond_destroy(&(p->c)); pthread_mutex_destroy(&(p->m)); free(threadLock); } #endif /* !LINUX */ PUBLIC void *csoundCreateBarrier(unsigned int max) { #if !defined(HAVE_PTHREAD_BARRIER_INIT) /* iteration needed to distinguish between separate sets of max threads */ /* where a thread enters the barrier before others have had a chance to leave */ /* this limits us to 2^32 barrier synchronisations, but only if one thread */ /* gets stuck and doesn't leave for 2^32 other synchronisations */ barrier_t *b; if (max == 0) return (void*)EINVAL; b = (barrier_t *)malloc(sizeof(barrier_t)); pthread_mutex_init(&b->mut, NULL); pthread_cond_init(&b->cond, NULL); b->count = 0; b->iteration = 0; b->max = max; return b; #else pthread_barrier_t *barrier = (pthread_barrier_t *) malloc(sizeof(pthread_barrier_t)); int status = pthread_barrier_init(barrier, 0, max); fprintf(stderr, "Create barrier %d => %p (%d)\n", max, barrier, status); if (status) return 0; return barrier; #endif } PUBLIC int csoundDestroyBarrier(void *barrier) { #if !defined(HAVE_PTHREAD_BARRIER_INIT) barrier_t *b = (barrier_t *)barrier; if (b->count > 0) return EBUSY; pthread_cond_destroy(&b->cond); pthread_mutex_destroy(&b->mut); #else pthread_barrier_destroy(barrier); #endif free(barrier); return 0; } /* when barrier is passed, all threads except one return 0 */ PUBLIC int csoundWaitBarrier(void *barrier) { #if !defined(HAVE_PTHREAD_BARRIER_INIT) int ret; unsigned int it; barrier_t *b = (barrier_t *)barrier; pthread_mutex_lock(&b->mut); b->count++; it = b->iteration; if (b->count >= b->max) { b->count = 0; b->iteration++; pthread_cond_broadcast(&b->cond); ret = BARRIER_SERIAL_THREAD; } else { while (it == b->iteration) pthread_cond_wait(&b->cond, &b->mut); ret = 0; } pthread_mutex_unlock(&b->mut); return ret; #else return pthread_barrier_wait((pthread_barrier_t *)barrier); #endif } /** * Creates and returns a mutex object, or NULL if not successful. * Mutexes can be faster than the more general purpose monitor objects * returned by csoundCreateThreadLock() on some platforms, and can also * be recursive, but the result of unlocking a mutex that is owned by * another thread or is not locked is undefined. * If 'isRecursive' is non-zero, the mutex can be re-locked multiple * times by the same thread, requiring an equal number of unlock calls; * otherwise, attempting to re-lock the mutex results in undefined * behavior. * Note: the handles returned by csoundCreateThreadLock() and * csoundCreateMutex() are not compatible. */ PUBLIC void *csoundCreateMutex(int isRecursive) { pthread_mutex_t *mutex_ = (pthread_mutex_t*) NULL; pthread_mutexattr_t attr; if (pthread_mutexattr_init(&attr) == 0) { if (pthread_mutexattr_settype(&attr, (isRecursive ? (int) PTHREAD_MUTEX_RECURSIVE : (int) PTHREAD_MUTEX_DEFAULT)) == 0) { mutex_ = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t)); if (mutex_ != NULL) { if (pthread_mutex_init(mutex_, &attr) != 0) { free((void*) mutex_); mutex_ = (pthread_mutex_t*) NULL; } } } pthread_mutexattr_destroy(&attr); } return (void*) mutex_; } /** * Acquires the indicated mutex object; if it is already in use by * another thread, the function waits until the mutex is released by * the other thread. */ PUBLIC void csoundLockMutex(void *mutex_) { pthread_mutex_lock((pthread_mutex_t*) mutex_); } /** * Acquires the indicated mutex object and returns zero, unless it is * already in use by another thread, in which case a non-zero value is * returned immediately, rather than waiting until the mutex becomes * available. * Note: this function may be unimplemented on Windows. */ PUBLIC int csoundLockMutexNoWait(void *mutex_) { return pthread_mutex_trylock((pthread_mutex_t*) mutex_); } /** * Releases the indicated mutex object, which should be owned by * the current thread, otherwise the operation of this function is * undefined. A recursive mutex needs to be unlocked as many times * as it was locked previously. */ PUBLIC void csoundUnlockMutex(void *mutex_) { pthread_mutex_unlock((pthread_mutex_t*) mutex_); } /** * Destroys the indicated mutex object. Destroying a mutex that * is currently owned by a thread results in undefined behavior. */ PUBLIC void csoundDestroyMutex(void *mutex_) { if (mutex_ != NULL) { pthread_mutex_destroy((pthread_mutex_t*) mutex_); free(mutex_); } } /* ------------------------------------------------------------------------ */ PUBLIC void* csoundCreateCondVar() { pthread_cond_t* condVar = (pthread_cond_t*)malloc(sizeof(pthread_cond_t)); if (condVar != NULL) pthread_cond_init(condVar, NULL); return (void*) condVar; } PUBLIC void csoundCondWait(void* condVar, void* mutex) { pthread_cond_wait(condVar, mutex); } PUBLIC void csoundCondSignal(void* condVar) { pthread_cond_signal(condVar); } /* ------------------------------------------------------------------------ */ #elif defined(WIN32) #include #if !defined(_USING_V110_SDK71_) #include #endif #include /* #undef NO_WIN9X_COMPATIBILITY */ typedef struct { uintptr_t (*func)(void *); void *userdata; HANDLE threadLock; } threadParams; static unsigned int __stdcall threadRoutineWrapper(void *p) { uintptr_t (*threadRoutine)(void *); void *userData; threadRoutine = ((threadParams*) p)->func; userData = ((threadParams*) p)->userdata; SetEvent(((threadParams*) p)->threadLock); return (unsigned int) threadRoutine(userData); } PUBLIC void *csoundCreateThread(uintptr_t (*threadRoutine)(void *), void *userdata) { threadParams p; void *h; unsigned int threadID; p.func = threadRoutine; p.userdata = userdata; p.threadLock = CreateEvent(0, 0, 0, 0); if (p.threadLock == (HANDLE) 0) return NULL; h = (void*) _beginthreadex(NULL, (unsigned) 0, threadRoutineWrapper, (void*) &p, (unsigned) 0, &threadID); if (h != NULL) WaitForSingleObject(p.threadLock, INFINITE); CloseHandle(p.threadLock); return h; } PUBLIC void *csoundGetCurrentThreadId(void) { DWORD* d = malloc(sizeof(DWORD)); *d = GetCurrentThreadId(); return (void*) d; } PUBLIC uintptr_t csoundJoinThread(void *thread) { DWORD retval = (DWORD) 0; WaitForSingleObject((HANDLE) thread, INFINITE); GetExitCodeThread((HANDLE) thread, &retval); CloseHandle((HANDLE) thread); return (uintptr_t) retval; } PUBLIC void *csoundCreateThreadLock(void) { HANDLE threadLock = CreateEvent(0, 0, TRUE, 0); return (void*) threadLock; } PUBLIC int csoundWaitThreadLock(void *lock, size_t milliseconds) { return (int) WaitForSingleObject((HANDLE) lock, milliseconds); } PUBLIC void csoundWaitThreadLockNoTimeout(void *lock) { WaitForSingleObject((HANDLE) lock, INFINITE); } PUBLIC void csoundNotifyThreadLock(void *lock) { SetEvent((HANDLE) lock); } PUBLIC void csoundDestroyThreadLock(void *lock) { CloseHandle((HANDLE) lock); } PUBLIC void csoundSleep(size_t milliseconds) { Sleep((DWORD) milliseconds); } /** * Creates and returns a mutex object, or NULL if not successful. * Mutexes can be faster than the more general purpose monitor objects * returned by csoundCreateThreadLock() on some platforms, and can also * be recursive, but the result of unlocking a mutex that is owned by * another thread or is not locked is undefined. * If 'isRecursive' is non-zero, the mutex can be re-locked multiple * times by the same thread, requiring an equal number of unlock calls; * otherwise, attempting to re-lock the mutex results in undefined * behavior. * Note: the handles returned by csoundCreateThreadLock() and * csoundCreateMutex() are not compatible. */ PUBLIC void *csoundCreateMutex(int isRecursive) { CRITICAL_SECTION *cs; (void) isRecursive; cs = (CRITICAL_SECTION*) malloc(sizeof(CRITICAL_SECTION)); if (cs != NULL) InitializeCriticalSection((LPCRITICAL_SECTION) cs); return (void*) cs; } /** * Acquires the indicated mutex object; if it is already in use by * another thread, the function waits until the mutex is released by * the other thread. */ PUBLIC void csoundLockMutex(void *mutex_) { EnterCriticalSection((LPCRITICAL_SECTION) mutex_); } /** * Acquires the indicated mutex object and returns zero, unless it is * already in use by another thread, in which case a non-zero value is * returned immediately, rather than waiting until the mutex becomes * available. * Note: this function may be unimplemented on Windows. */ PUBLIC int csoundLockMutexNoWait(void *mutex_) { #ifdef NO_WIN9X_COMPATIBILITY BOOL retval; /* FIXME: may need to define _WIN32_WINNT before including windows.h */ retval = TryEnterCriticalSection((LPCRITICAL_SECTION) mutex_); return (retval == FALSE ? 1 : 0); #else /* stub for compatibility with Windows 9x */ EnterCriticalSection((LPCRITICAL_SECTION) mutex_); return 0; #endif } /** * Releases the indicated mutex object, which should be owned by * the current thread, otherwise the operation of this function is * undefined. A recursive mutex needs to be unlocked as many times * as it was locked previously. */ PUBLIC void csoundUnlockMutex(void *mutex_) { LeaveCriticalSection((LPCRITICAL_SECTION) mutex_); } /** * Destroys the indicated mutex object. Destroying a mutex that * is currently owned by a thread results in undefined behavior. */ PUBLIC void csoundDestroyMutex(void *mutex_) { if (mutex_ != NULL) { DeleteCriticalSection((LPCRITICAL_SECTION) mutex_); free(mutex_); } } /** * Runs an external command with the arguments specified in 'argv'. * argv[0] is the name of the program to execute (if not a full path * file name, it is searched in the directories defined by the PATH * environment variable). The list of arguments should be terminated * by a NULL pointer. * If 'noWait' is zero, the function waits until the external program * finishes, otherwise it returns immediately. In the first case, a * non-negative return value is the exit status of the command (0 to * 255), otherwise it is the PID of the newly created process. * On error, a negative value is returned. */ PUBLIC long csoundRunCommand(const char * const *argv, int noWait) { long retval; if (argv == NULL || argv[0] == NULL) return -1L; retval = (long) _spawnvp((noWait ? (int) _P_NOWAIT : (int) _P_WAIT), argv[0], argv); if (!noWait && retval >= 0L) retval &= 255L; return retval; } PUBLIC void* csoundCreateCondVar() { CONDITION_VARIABLE* condVar = (CONDITION_VARIABLE*)malloc(sizeof(CONDITION_VARIABLE)); if (condVar != NULL) InitializeConditionVariable(condVar); return (void*) condVar; } PUBLIC void csoundCondWait(void* condVar, void* mutex) { CONDITION_VARIABLE* cv = (CONDITION_VARIABLE*)condVar; CRITICAL_SECTION* cs = (CRITICAL_SECTION*)mutex; SleepConditionVariableCS(cv, cs, INFINITE); } PUBLIC void csoundCondSignal(void* condVar) { CONDITION_VARIABLE* cv = (CONDITION_VARIABLE*)condVar; WakeConditionVariable(cv); } // REMOVE FOLLOWING BARRIER DEFINITION WINDOWS SUPPORT LIMITED to WIN 8.1+ typedef struct barrier { CRITICAL_SECTION* mut; CONDITION_VARIABLE* cond; unsigned int count, max, iteration; } win_barrier_t; PUBLIC void *csoundCreateBarrier(unsigned int max) { win_barrier_t *barrier = (win_barrier_t*)malloc(sizeof(win_barrier_t)); barrier->cond = (CONDITION_VARIABLE*)csoundCreateCondVar(); barrier->mut = (CRITICAL_SECTION*)csoundCreateMutex(0); barrier->count = 0; barrier->iteration = 0; barrier->max = max; return (void*) barrier; // REPLACE ABOVE WITH FOLLOWING ONCE WINDOWS SUPPORT LIMITED to WIN 8.1+ //SYNCHRONIZATION_BARRIER *barrier = // (SYNCHRONIZATION_BARRIER*)malloc(sizeof(SYNCHRONIZATION_BARRIER)); //if (barrier != NULL) // InitializeSynchronizationBarrier(barrier, max, -1); //return (void*) barrier; } PUBLIC int csoundDestroyBarrier(void *barrier) { win_barrier_t *winb = (win_barrier_t*)barrier; free(winb->cond); csoundDestroyMutex(winb->mut); free(winb); return 0; // REPLACE ABOVE WITH FOLLOWING ONCE WINDOWS SUPPORT LIMITED to WIN 8.1+ //DeleteSynchronizationBarrier(barrier); //return 0; } PUBLIC int csoundWaitBarrier(void *barrier) { int ret; unsigned int it; win_barrier_t *winb = (win_barrier_t*)barrier; csoundLockMutex(winb->mut); winb->count++; it = winb->iteration; if (winb->count >= winb->max) { winb->count = 0; winb->iteration++; WakeAllConditionVariable(winb->cond); ret = 1; } else { while(it == winb->iteration) { csoundCondWait(winb->cond, winb->mut); } ret = 0; } csoundUnlockMutex(winb->mut); return ret; // REPLACE ABOVE WITH FOLLOWING ONCE WINDOWS SUPPORT LIMITED to WIN 8.1+ //EnterSynchronizationBarrier(barrier, 0); //return 0; } /* ------------------------------------------------------------------------ */ #else PUBLIC void *csoundCreateThread(uintptr_t (*threadRoutine)(void *), void *userdata) { //notImplementedWarning_("csoundCreateThread"); return NULL; } PUBLIC void *csoundGetCurrentThreadId(void) { //notImplementedWarning_("csoundGetCurrentThreadId"); return NULL; } PUBLIC uintptr_t csoundJoinThread(void *thread) { //notImplementedWarning_("csoundJoinThread"); return (uintptr_t) 0; } PUBLIC void *csoundCreateThreadLock(void) { //notImplementedWarning_("csoundCreateThreadLock"); return NULL; } PUBLIC int csoundWaitThreadLock(void *lock, size_t milliseconds) { //notImplementedWarning_("csoundWaitThreadLock"); return 0; } PUBLIC void csoundWaitThreadLockNoTimeout(void *lock) { //notImplementedWarning_("csoundWaitThreadLockNoTimeout"); } PUBLIC void csoundNotifyThreadLock(void *lock) { //notImplementedWarning_("csoundNotifyThreadLock"); } PUBLIC void csoundDestroyThreadLock(void *lock) { //notImplementedWarning_("csoundDestroyThreadLock"); } PUBLIC void *csoundCreateMutex(int isRecursive) { //notImplementedWarning_("csoundCreateMutex"); return NULL; } PUBLIC void csoundLockMutex(void *mutex_) { //notImplementedWarning_("csoundLockMutex"); } PUBLIC int csoundLockMutexNoWait(void *mutex_) { //notImplementedWarning_("csoundLockMutexNoWait"); return 0; } PUBLIC void csoundUnlockMutex(void *mutex_) { //notImplementedWarning_("csoundUnlockMutex"); } PUBLIC void csoundDestroyMutex(void *mutex_) { //notImplementedWarning_("csoundDestroyMutex"); } PUBLIC void *csoundCreateBarrier(unsigned int max) { //notImplementedWarning_("csoundDestroyBarrier"); return NULL; } PUBLIC int csoundDestroyBarrier(void *barrier) { //notImplementedWarning_("csoundDestroyBarrier"); return 0; } PUBLIC int csoundWaitBarrier(void *barrier) { //notImplementedWarning_("csoundWaitBarrier"); return 0; } PUBLIC void* csoundCreateCondVar() { //notImplementedWarning_("csoundCreateCondVar"); return NULL; } PUBLIC void csoundCondWait(void* condVar, void* mutex) { //notImplementedWarning_("csoundCreateCondWait"); } PUBLIC void csoundCondSignal(void* condVar) { // notImplementedWarning_("csoundCreateCondSignal"); } PUBLIC long csoundRunCommand(const char * const *argv, int noWait) { //notImplementedWarning_("csoundRunCommand"); return 0; } PUBLIC void csoundSleep(size_t milliseconds) { //notImplementedWarning_("csoundSleep"); } #endif csound-6.10.0/Top/threadsafe.c000066400000000000000000000540571321653344700161300ustar00rootroot00000000000000/* * threadsafe.c: threadsafe API functions * (c) V Lazzarini, 2013 * * L I C E N S E * * This software is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include "csound_orc.h" #include #ifdef USE_DOUBLE # define MYFLT_INT_TYPE int64_t #else # define MYFLT_INT_TYPE int32_t #endif int csoundKillInstanceInternal(CSOUND *csound, MYFLT instr, char *instrName, int mode, int allow_release, int async); int csoundCompileTreeInternal(CSOUND *csound, TREE *root, int async); int csoundCompileOrcInternal(CSOUND *csound, const char *str, int async); void merge_state(CSOUND *csound, ENGINE_STATE *engineState, TYPE_TABLE* typetable, OPDS *ids); void killInstance(CSOUND *csound, MYFLT instr, int insno, INSDS *ip, int mode, int allow_release); void csoundInputMessageInternal(CSOUND *csound, const char *message); int csoundReadScoreInternal(CSOUND *csound, const char *message); void csoundTableCopyOutInternal(CSOUND *csound, int table, MYFLT *ptable); void csoundTableCopyInInternal(CSOUND *csound, int table, MYFLT *ptable); void csoundTableSetInternal(CSOUND *csound, int table, int index, MYFLT value); int csoundScoreEventInternal(CSOUND *csound, char type, const MYFLT *pfields, long numFields); int csoundScoreEventAbsoluteInternal(CSOUND *csound, char type, const MYFLT *pfields, long numFields, double time_ofs); void set_channel_data_ptr(CSOUND *csound, const char *name, void *ptr, int newSize); enum {INPUT_MESSAGE=1, READ_SCORE, SCORE_EVENT, SCORE_EVENT_ABS, TABLE_COPY_OUT, TABLE_COPY_IN, TABLE_SET, MERGE_STATE, KILL_INSTANCE}; /* MAX QUEUE SIZE */ #define API_MAX_QUEUE 1024 /* ARG LIST ALIGNMENT */ #define ARG_ALIGN 8 /* Message queue structure */ typedef struct _message_queue { int64_t message; /* message id */ char *args; /* args, arg pointers */ int64_t rtn; /* return value */ } message_queue_t; /* atomicGetAndIncrementWithModulus */ static long atomicGet_Incr_Mod(volatile long* val, long mod) { volatile long oldVal, newVal; do { oldVal = *val; newVal = (oldVal + 1) % mod; #if defined(MSVC) } while (InterlockedCompareExchange(val, newVal, oldVal) != oldVal); #elif defined(HAVE_ATOMIC_BUILTIN) } while (!__atomic_compare_exchange(val, (long *) &oldVal, &newVal, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)); #else /* FIXME: no atomics, what to do? */ } while ((*val = newVal) != newVal); #endif return oldVal; } /* called by csoundCreate() at the start and also by csoundStart() to cover de-allocation by reset */ void allocate_message_queue(CSOUND *csound) { if (csound->msg_queue == NULL) { int i; csound->msg_queue = (message_queue_t **) csound->Calloc(csound, sizeof(message_queue_t*)*API_MAX_QUEUE); for (i = 0; i < API_MAX_QUEUE; i++) { csound->msg_queue[i] = (message_queue_t*) csound->Calloc(csound, sizeof(message_queue_t)); } } } /* enqueue should be called by the relevant API function */ void *message_enqueue(CSOUND *csound, int32_t message, char *args, int argsiz) { if(csound->msg_queue != NULL) { int64_t *rtn; volatile long items; /* block if queue is full */ do { #if defined(MSVC) items = InterlockedExchangeAdd(&csound->msg_queue_items, 0); #elif defined(HAVE_ATOMIC_BUILTIN) items = __atomic_load_n (&csound->msg_queue_items, __ATOMIC_SEQ_CST); #else items = csound->msg_queue_items; #endif } while(items >= API_MAX_QUEUE); message_queue_t* msg = csound->msg_queue[atomicGet_Incr_Mod(&csound->msg_queue_wget, API_MAX_QUEUE)]; msg->message = message; if(msg->args != NULL) csound->Free(csound, msg->args); msg->args = (char *)csound->Calloc(csound, argsiz); memcpy(msg->args, args, argsiz); rtn = &msg->rtn; csound->msg_queue[atomicGet_Incr_Mod(&csound->msg_queue_wput, API_MAX_QUEUE)] = msg; #ifdef MSVC InterlockedIncrement(&csound->msg_queue_items); #elif defined(HAVE_ATOMIC_BUILTIN) __atomic_add_fetch(&csound->msg_queue_items, 1, __ATOMIC_SEQ_CST); #else csound->msg_queue_items++; #endif return (void *) rtn; } else return NULL; } /* dequeue should be called by kperf_*() NB: these calls are already in place */ void message_dequeue(CSOUND *csound) { if(csound->msg_queue != NULL) { long rp = csound->msg_queue_rstart; long items = csound->msg_queue_items; long rend = rp + items; int64_t rtn = 0; /* This value is not used */ while(rp < rend) { message_queue_t* msg = csound->msg_queue[rp % API_MAX_QUEUE]; switch(msg->message) { case INPUT_MESSAGE: { const char *str = msg->args; csoundInputMessageInternal(csound, str); } break; case READ_SCORE: { const char *str = msg->args; rtn = csoundReadScoreInternal(csound, str); } break; case SCORE_EVENT: { char type; const MYFLT *pfields; long numFields; type = msg->args[0]; memcpy(&pfields, msg->args + ARG_ALIGN, sizeof(MYFLT *)); memcpy(&numFields, msg->args + ARG_ALIGN*2, sizeof(long)); rtn = csoundScoreEventInternal(csound, type, pfields, numFields); } break; case SCORE_EVENT_ABS: { char type; const MYFLT *pfields; long numFields; double ofs; type = msg->args[0]; memcpy(&pfields, msg->args + ARG_ALIGN, sizeof(MYFLT *)); memcpy(&numFields, msg->args + ARG_ALIGN*2, sizeof(long)); memcpy(&ofs, msg->args + ARG_ALIGN*3, sizeof(double)); rtn = csoundScoreEventAbsoluteInternal(csound, type, pfields, numFields, ofs); } break; case TABLE_COPY_OUT: { int table; MYFLT *ptable; memcpy(&table, msg->args, sizeof(int)); memcpy(&ptable, msg->args + ARG_ALIGN, sizeof(MYFLT *)); csoundTableCopyOutInternal(csound, table, ptable); } break; case TABLE_COPY_IN: { int table; MYFLT *ptable; memcpy(&table, msg->args, sizeof(int)); memcpy(&ptable, msg->args + ARG_ALIGN, sizeof(MYFLT *)); csoundTableCopyInInternal(csound, table, ptable); } break; case TABLE_SET: { int table, index; MYFLT value; memcpy(&table, msg->args, sizeof(int)); memcpy(&index, msg->args + ARG_ALIGN, sizeof(int)); memcpy(&value, msg->args + 2*ARG_ALIGN, sizeof(MYFLT)); csoundTableSetInternal(csound, table, index, value); } break; case MERGE_STATE: { ENGINE_STATE *e; TYPE_TABLE *t; OPDS *ids; memcpy(&e, msg->args, sizeof(ENGINE_STATE *)); memcpy(&t, msg->args + ARG_ALIGN, sizeof(TYPE_TABLE *)); memcpy(&ids, msg->args + 2*ARG_ALIGN, sizeof(OPDS *)); merge_state(csound, e, t, ids); } break; case KILL_INSTANCE: { MYFLT instr; int mode, insno, rls; INSDS *ip; memcpy(&instr, msg->args, sizeof(MYFLT)); memcpy(&insno, msg->args + ARG_ALIGN, sizeof(int)); memcpy(&ip, msg->args + ARG_ALIGN*2, sizeof(INSDS *)); memcpy(&mode, msg->args + ARG_ALIGN*3, sizeof(int)); memcpy(&rls, msg->args + ARG_ALIGN*4, sizeof(int)); killInstance(csound, instr, insno, ip, mode, rls); } break; } msg->message = 0; rp += 1; } #ifdef MSVC InterlockedExchangeAdd(&csound->msg_queue_items, -items); #elif defined(HAVE_ATOMIC_BUILTIN) __atomic_sub_fetch(&csound->msg_queue_items, items, __ATOMIC_SEQ_CST); #else csound->msg_queue_items -= items; #endif csound->msg_queue_rstart = rp % API_MAX_QUEUE; } } /* these are the message enqueueing functions for each relevant API function */ static inline void csoundInputMessage_enqueue(CSOUND *csound, const char *str){ message_enqueue(csound,INPUT_MESSAGE, (char *) str, strlen(str)+1); } static inline int64_t *csoundReadScore_enqueue(CSOUND *csound, const char *str){ return message_enqueue(csound, READ_SCORE, (char *) str, strlen(str)+1); } static inline void csoundTableCopyOut_enqueue(CSOUND *csound, int table, MYFLT *ptable){ const int argsize = ARG_ALIGN*2; char args[ARG_ALIGN*2]; memcpy(args, &table, sizeof(int)); memcpy(args+ARG_ALIGN, &ptable, sizeof(MYFLT *)); message_enqueue(csound,TABLE_COPY_OUT, args, argsize); } static inline void csoundTableCopyIn_enqueue(CSOUND *csound, int table, MYFLT *ptable){ const int argsize = ARG_ALIGN*2; char args[ARG_ALIGN*2]; memcpy(args, &table, sizeof(int)); memcpy(args+ARG_ALIGN, &ptable, sizeof(MYFLT *)); message_enqueue(csound,TABLE_COPY_IN, args, argsize); } static inline void csoundTableSet_enqueue(CSOUND *csound, int table, int index, MYFLT value) { const int argsize = ARG_ALIGN*3; char args[ARG_ALIGN*3]; memcpy(args, &table, sizeof(int)); memcpy(args+ARG_ALIGN, &index, sizeof(int)); memcpy(args+2*ARG_ALIGN, &value, sizeof(MYFLT)); message_enqueue(csound,TABLE_SET, args, argsize); } static inline int64_t *csoundScoreEvent_enqueue(CSOUND *csound, char type, const MYFLT *pfields, long numFields) { const int argsize = ARG_ALIGN*3; char args[ARG_ALIGN*3]; args[0] = type; memcpy(args+ARG_ALIGN, &pfields, sizeof(MYFLT *)); memcpy(args+2*ARG_ALIGN, &numFields, sizeof(long)); return message_enqueue(csound,SCORE_EVENT, args, argsize); } static inline int64_t *csoundScoreEventAbsolute_enqueue(CSOUND *csound, char type, const MYFLT *pfields, long numFields, double time_ofs) { const int argsize = ARG_ALIGN*4; char args[ARG_ALIGN*4]; args[0] = type; memcpy(args+ARG_ALIGN, &pfields, sizeof(MYFLT *)); memcpy(args+2*ARG_ALIGN, &numFields, sizeof(long)); memcpy(args+3*ARG_ALIGN, &time_ofs, sizeof(double)); return message_enqueue(csound,SCORE_EVENT_ABS, args, argsize); } /* this is to be called from csoundKillInstanceInternal() in insert.c */ void killInstance_enqueue(CSOUND *csound, MYFLT instr, int insno, INSDS *ip, int mode, int allow_release) { const int argsize = ARG_ALIGN*5; char args[ARG_ALIGN*5]; memcpy(args, &instr, sizeof(int)); memcpy(args+ARG_ALIGN, &insno, sizeof(int)); memcpy(args+ARG_ALIGN*2, &ip, sizeof(INSDS *)); memcpy(args+ARG_ALIGN*3, &mode, sizeof(int)); memcpy(args+ARG_ALIGN*4, &allow_release, sizeof(int)); message_enqueue(csound,KILL_INSTANCE,args,argsize); } /* this is to be called from csoundCompileTreeInternal() in csound_orc_compile.c */ void mergeState_enqueue(CSOUND *csound, ENGINE_STATE *e, TYPE_TABLE* t, OPDS *ids) { const int argsize = ARG_ALIGN*3; char args[ARG_ALIGN*3]; memcpy(args, &e, sizeof(ENGINE_STATE *)); memcpy(args+ARG_ALIGN, &t, sizeof(TYPE_TABLE *)); memcpy(args+2*ARG_ALIGN, &ids, sizeof(OPDS *)); message_enqueue(csound,MERGE_STATE, args, argsize); } /* VL: These functions are slated to be converted to message enqueueing in the next API revision. */ void csoundInputMessage(CSOUND *csound, const char *message){ csoundLockMutex(csound->API_lock); csoundInputMessageInternal(csound, message); csoundUnlockMutex(csound->API_lock); } int csoundReadScore(CSOUND *csound, const char *message){ int res; csoundLockMutex(csound->API_lock); res = csoundReadScoreInternal(csound, message); csoundUnlockMutex(csound->API_lock); return res; } void csoundTableCopyOut(CSOUND *csound, int table, MYFLT *ptable){ csoundLockMutex(csound->API_lock); csoundTableCopyOutInternal(csound, table, ptable); csoundUnlockMutex(csound->API_lock); } void csoundTableCopyIn(CSOUND *csound, int table, MYFLT *ptable){ csoundLockMutex(csound->API_lock); csoundTableCopyInInternal(csound, table, ptable); csoundUnlockMutex(csound->API_lock); } void csoundTableSet(CSOUND *csound, int table, int index, MYFLT value) { csoundLockMutex(csound->API_lock); csoundTableSetInternal(csound, table, index, value); csoundUnlockMutex(csound->API_lock); } int csoundScoreEvent(CSOUND *csound, char type, const MYFLT *pfields, long numFields) { csoundLockMutex(csound->API_lock); csoundScoreEventInternal(csound, type, pfields, numFields); csoundUnlockMutex(csound->API_lock); return OK; } int csoundScoreEventAbsolute(CSOUND *csound, char type, const MYFLT *pfields, long numFields, double time_ofs) { csoundLockMutex(csound->API_lock); csoundScoreEventAbsoluteInternal(csound, type, pfields, numFields, time_ofs); csoundUnlockMutex(csound->API_lock); return OK; } int csoundKillInstance(CSOUND *csound, MYFLT instr, char *instrName, int mode, int allow_release){ int async = 0; return csoundKillInstanceInternal(csound, instr, instrName, mode, allow_release, async); } int csoundCompileTree(CSOUND *csound, TREE *root) { int async = 0; return csoundCompileTreeInternal(csound, root, async); } int csoundCompileOrc(CSOUND *csound, const char *str) { int async = 0; return csoundCompileOrcInternal(csound, str, async); } MYFLT csoundEvalCode(CSOUND *csound, const char *str) { int async = 0; if (str && csoundCompileOrcInternal(csound,str,async) == CSOUND_SUCCESS) return csound->instr0->instance[0].retval; #ifdef NAN else return NAN; #else else return 0; #endif } /** Async versions of the functions above To be removed once everything is made async */ void csoundInputMessageAsync(CSOUND *csound, const char *message){ csoundInputMessage_enqueue(csound, message); } void csoundReadScoreAsync(CSOUND *csound, const char *message){ csoundReadScore_enqueue(csound, message); } void csoundTableCopyOutAsync(CSOUND *csound, int table, MYFLT *ptable){ csoundTableCopyOut_enqueue(csound, table, ptable); } void csoundTableCopyInAsync(CSOUND *csound, int table, MYFLT *ptable){ csoundTableCopyIn_enqueue(csound, table, ptable); } void csoundTableSetAsync(CSOUND *csound, int table, int index, MYFLT value) { csoundTableSet_enqueue(csound, table, index, value); } void csoundScoreEventAsync(CSOUND *csound, char type, const MYFLT *pfields, long numFields) { csoundScoreEvent_enqueue(csound, type, pfields, numFields); } void csoundScoreEventAbsoluteAsync(CSOUND *csound, char type, const MYFLT *pfields, long numFields, double time_ofs) { csoundScoreEventAbsolute_enqueue(csound, type, pfields, numFields, time_ofs); } int csoundCompileTreeAsync(CSOUND *csound, TREE *root) { int async = 1; return csoundCompileTreeInternal(csound, root, async); } int csoundCompileOrcAsync(CSOUND *csound, const char *str) { int async = 1; return csoundCompileOrcInternal(csound, str, async); } int csoundKillInstanceAsync(CSOUND *csound, MYFLT instr, char *instrName, int mode, int allow_release){ int async = 1; return csoundKillInstanceInternal(csound, instr, instrName, mode, allow_release, async); } /* VL: the following do not depend on API_lock therefore do not need to be in the message queue */ MYFLT csoundGetControlChannel(CSOUND *csound, const char *name, int *err) { MYFLT *pval; int err_; union { MYFLT d; MYFLT_INT_TYPE i; } x; x.d = FL(0.0); if (UNLIKELY(strlen(name) == 0)) return FL(.0); if ((err_ = csoundGetChannelPtr(csound, &pval, name, CSOUND_CONTROL_CHANNEL | CSOUND_OUTPUT_CHANNEL)) == CSOUND_SUCCESS) { #if defined(MSVC) x.i = InterlockedExchangeAdd64((MYFLT_INT_TYPE *)pval, 0); #elif defined(HAVE_ATOMIC_BUILTIN) x.i = __sync_fetch_and_add((MYFLT_INT_TYPE *)pval, 0); #else x.d = *pval; #endif } if (err) { *err = err_; } return x.d; } void csoundSetControlChannel(CSOUND *csound, const char *name, MYFLT val){ MYFLT *pval; union { MYFLT d; MYFLT_INT_TYPE i; } x; x.d = val; if (csoundGetChannelPtr(csound, &pval, name, CSOUND_CONTROL_CHANNEL | CSOUND_INPUT_CHANNEL) == CSOUND_SUCCESS) #if defined(MSVC) InterlockedExchange64((MYFLT_INT_TYPE *)pval, x.i); #elif defined(HAVE_ATOMIC_BUILTIN) __sync_lock_test_and_set((MYFLT_INT_TYPE *)pval,x.i); #else { int *lock = csoundGetChannelLock(csound, (char*) name); csoundSpinLock(lock); *pval = val; csoundSpinUnLock(lock); } #endif } void csoundGetAudioChannel(CSOUND *csound, const char *name, MYFLT *samples) { MYFLT *psamples; if (strlen(name) == 0) return; if (csoundGetChannelPtr(csound, &psamples, name, CSOUND_AUDIO_CHANNEL | CSOUND_OUTPUT_CHANNEL) == CSOUND_SUCCESS) { int *lock = csoundGetChannelLock(csound, (char*) name); csoundSpinLock(lock); memcpy(samples, psamples, csoundGetKsmps(csound)*sizeof(MYFLT)); csoundSpinUnLock(lock); } } void csoundSetAudioChannel(CSOUND *csound, const char *name, MYFLT *samples) { MYFLT *psamples; if (csoundGetChannelPtr(csound, &psamples, name, CSOUND_AUDIO_CHANNEL | CSOUND_INPUT_CHANNEL) == CSOUND_SUCCESS){ int *lock = csoundGetChannelLock(csound, (char*) name); csoundSpinLock(lock); memcpy(psamples, samples, csoundGetKsmps(csound)*sizeof(MYFLT)); csoundSpinUnLock(lock); } } void csoundSetStringChannel(CSOUND *csound, const char *name, char *string) { MYFLT *pstring; if (csoundGetChannelPtr(csound, &pstring, name, CSOUND_STRING_CHANNEL | CSOUND_INPUT_CHANNEL) == CSOUND_SUCCESS){ STRINGDAT* stringdat = (STRINGDAT*) pstring; int size = stringdat->size; //csoundGetChannelDatasize(csound, name); int *lock = csoundGetChannelLock(csound, (char*) name); if (lock != NULL) { csoundSpinLock(lock); } if (strlen(string) + 1 > (unsigned int) size) { if (stringdat->data!=NULL) csound->Free(csound,stringdat->data); stringdat->data = cs_strdup(csound, string); stringdat->size = strlen(string) + 1; //set_channel_data_ptr(csound,name,(void*)pstring, strlen(string)+1); } else { strcpy((char *) stringdat->data, string); } if (lock != NULL) { csoundSpinUnLock(lock); } } } void csoundGetStringChannel(CSOUND *csound, const char *name, char *string) { MYFLT *pstring; char *chstring; int n2; if (strlen(name) == 0) return; if (csoundGetChannelPtr(csound, &pstring, name, CSOUND_STRING_CHANNEL | CSOUND_OUTPUT_CHANNEL) == CSOUND_SUCCESS){ int *lock = csoundGetChannelLock(csound, (char*) name); chstring = ((STRINGDAT *) pstring)->data; if (lock != NULL) csoundSpinLock(lock); if (string != NULL && chstring != NULL) { n2 = strlen(chstring); strncpy(string,chstring, n2); string[n2] = 0; } if (lock != NULL) csoundSpinUnLock(lock); } } PUBLIC int csoundSetPvsChannel(CSOUND *csound, const PVSDATEXT *fin, const char *name) { MYFLT *pp; PVSDATEXT *f; if (LIKELY(csoundGetChannelPtr(csound, &pp, name, CSOUND_PVS_CHANNEL | CSOUND_INPUT_CHANNEL) == CSOUND_SUCCESS)){ int *lock = csoundGetChannelLock(csound, name); f = (PVSDATEXT *) pp; csoundSpinLock(lock); if (f->frame == NULL) { f->frame = csound->Calloc(csound, sizeof(float)*(fin->N+2)); } else if (f->N < fin->N) { f->frame = csound->ReAlloc(csound, f->frame, sizeof(float)*(fin->N+2)); } memcpy(f, fin, sizeof(PVSDATEXT)-sizeof(float *)); if (fin->frame != NULL) memcpy(f->frame, fin->frame, (f->N+2)*sizeof(float)); csoundSpinUnLock(lock); } else { return CSOUND_ERROR; } return CSOUND_SUCCESS; } PUBLIC int csoundGetPvsChannel(CSOUND *csound, PVSDATEXT *fout, const char *name) { MYFLT *pp; PVSDATEXT *f; if (UNLIKELY(csoundGetChannelPtr(csound, &pp, name, CSOUND_PVS_CHANNEL | CSOUND_OUTPUT_CHANNEL) == CSOUND_SUCCESS)){ int *lock = csoundGetChannelLock(csound, name); f = (PVSDATEXT *) pp; if (UNLIKELY(pp == NULL)) return CSOUND_ERROR; csoundSpinLock(lock); memcpy(fout, f, sizeof(PVSDATEXT)-sizeof(float *)); if (fout->frame != NULL && f->frame != NULL) memcpy(fout->frame, f->frame, sizeof(float)*(fout->N)); csoundSpinUnLock(lock); } else { return CSOUND_ERROR; } return CSOUND_SUCCESS; } csound-6.10.0/Top/utility.c000066400000000000000000000215131321653344700155140ustar00rootroot00000000000000/* utility.c: Copyright (C) 2005 Istvan Varga This file is part of Csound. The Csound Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Csound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Csound; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "csoundCore.h" #include #include "corfile.h" typedef struct csUtility_s { char *name; struct csUtility_s *nxt; int (*UtilFunc)(CSOUND*, int, char**); char *desc; } csUtility_t; int csoundAddUtility(CSOUND *csound, const char *name, int (*UtilFunc)(CSOUND*, int, char**)) { csUtility_t *p; /* csound->Message(csound, "csoundAddUtility: name: %s function: 0x%p\n", name, UtilFunc); */ if (UNLIKELY(csound == NULL || name == NULL || name[0] == '\0' || UtilFunc == NULL)) return -1; p = (csUtility_t*) csound->utility_db; if (LIKELY(p != NULL)) { do { if (UNLIKELY(strcmp(p->name, name) == 0)) return -1; /* name is already in use */ if (p->nxt == NULL) break; p = p->nxt; } while (1); p->nxt = csound->Malloc(csound, sizeof(csUtility_t)); p = p->nxt; } else { csound->utility_db = csound->Calloc(csound, sizeof(csUtility_t)); p = (csUtility_t*) csound->utility_db; } p->name = csound->Malloc(csound, strlen(name) + 1); strcpy(p->name, name); p->nxt = NULL; p->UtilFunc = UtilFunc; p->desc = NULL; return 0; } PUBLIC int csoundRunUtility(CSOUND *csound, const char *name, int argc, char **argv) { csUtility_t *p; char **lst; volatile void *saved_exitjmp; volatile int n; if (UNLIKELY(csound == NULL)) return -1; saved_exitjmp = (void*) csound->Malloc(csound, sizeof(jmp_buf)); if (UNLIKELY(saved_exitjmp == NULL)) return -1; memcpy((void*) saved_exitjmp, (void*) &(csound->exitjmp), sizeof(jmp_buf)); if (UNLIKELY((n = setjmp(csound->exitjmp)) != 0)) { n = (n - CSOUND_EXITJMP_SUCCESS) | CSOUND_EXITJMP_SUCCESS; goto err_return; } if (UNLIKELY(name == NULL || name[0] == '\0')) goto notFound; p = (csUtility_t*) csound->utility_db; while (1) { if (UNLIKELY(p == NULL)) goto notFound; if (strcmp(p->name, name) == 0) break; p = p->nxt; } csound->engineStatus |= CS_STATE_UTIL; csound->scorename = csound->orchname = (char*) name; /* needed ? */ csound->Message(csound, Str("util %s:\n"), name); n = p->UtilFunc(csound, argc, argv); goto err_return; notFound: if (name != NULL && name[0] != '\0') { print_opcodedir_warning(csound); csound->ErrorMsg(csound, Str("Error: utility '%s' not found"), name); } else csound->ErrorMsg(csound, Str("Error: utility not found")); lst = csound->ListUtilities(csound); if (lst != NULL && lst[0] != NULL) { int i; csound->Message(csound, Str("The available utilities are:\n")); for (i = 0; lst[i] != NULL; i++) { const char *desc = csound->GetUtilityDescription(csound, lst[i]); if (desc != NULL) csound->Message(csound, " %s\t%s\n", lst[i], Str(desc)); else csound->Message(csound, " %s\n", lst[i]); } } csoundDeleteUtilityList(csound, lst); n = -1; err_return: memcpy((void*) &(csound->exitjmp), (void*) saved_exitjmp, sizeof(jmp_buf)); csound->Free(csound, (void*) saved_exitjmp); return n; } static int cmp_func(const void *a, const void *b) { return strcmp(*((char**) a), *((char**) b)); } /** * Returns a NULL terminated list of registered utility names. * The caller is responsible for freeing the returned array with * csoundDeleteUtilityList(), however, the names should not be * changed or freed. * The return value may be NULL in case of an error. */ PUBLIC char **csoundListUtilities(CSOUND *csound) { csUtility_t *p = (csUtility_t*) csound->utility_db; char **lst; int utilCnt = 0; /* find out the number of utilities */ while (p != NULL) p = p->nxt, utilCnt++; /* allocate list */ lst = (char**) csound->Malloc(csound, sizeof(char*) * (utilCnt + 1)); if (UNLIKELY(lst == NULL)) return NULL; /* store pointers to utility names */ utilCnt = 0; p = (csUtility_t*) csound->utility_db; while (p != NULL) { lst[utilCnt++] = (char*) p->name; p = p->nxt; } lst[utilCnt] = NULL; qsort(lst, utilCnt, sizeof(char*), cmp_func); /* return with pointer to list */ return lst; } /** * Releases an utility list previously returned by csoundListUtilities(). */ PUBLIC void csoundDeleteUtilityList(CSOUND *csound, char **lst) { if (lst != NULL) csound->Free(csound, lst); } /** * Set description text for the specified utility. * Returns zero on success. */ int csoundSetUtilityDescription(CSOUND *csound, const char *utilName, const char *utilDesc) { csUtility_t *p = (csUtility_t*) csound->utility_db; char *desc = NULL; /* check for valid parameters */ if (UNLIKELY(utilName == NULL)) return CSOUND_ERROR; /* find utility in database */ while (p != NULL && strcmp(p->name, utilName) != 0) p = p->nxt; if (UNLIKELY(p == NULL)) return CSOUND_ERROR; /* not found */ /* copy description text */ if (utilDesc != NULL && utilDesc[0] != '\0') { desc = (char*) csound->Malloc(csound, strlen(utilDesc) + 1); if (UNLIKELY(desc == NULL)) return CSOUND_MEMORY; strcpy(desc, utilDesc); } if (p->desc != NULL) csound->Free(csound, p->desc); p->desc = desc; /* report success */ return CSOUND_SUCCESS; } /** * Get utility description. * Returns NULL if the utility was not found, or it has no description, * or an error occured. */ PUBLIC const char *csoundGetUtilityDescription(CSOUND *csound, const char *utilName) { csUtility_t *p = (csUtility_t*) csound->utility_db; /* check for valid parameters */ if (UNLIKELY(utilName == NULL)) return NULL; /* find utility in database */ while (p != NULL && strcmp(p->name, utilName) != 0) p = p->nxt; if (UNLIKELY(p == NULL)) return NULL; /* not found */ /* return with utility description (if any) */ return (const char*) p->desc; } /* ------------------------------------------------------------------------ */ /** * Sorts score file 'inFile' and writes the result to 'outFile'. * The Csound instance should be initialised with csoundPreCompile() * before calling this function, and csoundReset() should be called * after sorting the score to clean up. On success, zero is returned. */ PUBLIC int csoundScoreSort(CSOUND *csound, FILE *inFile, FILE *outFile) { int err; CORFIL *inf = corfile_create_w(csound); int c; if ((err = setjmp(csound->exitjmp)) != 0) { return ((err - CSOUND_EXITJMP_SUCCESS) | CSOUND_EXITJMP_SUCCESS); } while ((c=getc(inFile))!=EOF) corfile_putc(csound, c, inf); corfile_rewind(inf); /* scsortstr() ignores the second arg - Jan 5 2012 */ csound->scorestr = inf; scsortstr(csound, inf); while ((c=corfile_getc(csound->scstr))!=EOF) putc(c, outFile); corfile_rm(csound, &csound->scstr); return 0; } /** * Extracts from 'inFile', controlled by 'extractFile', and writes * the result to 'outFile'. The Csound instance should be initialised * with csoundPreCompile() before calling this function, and csoundReset() * should be called after score extraction to clean up. * The return value is zero on success. */ PUBLIC int csoundScoreExtract(CSOUND *csound, FILE *inFile, FILE *outFile, FILE *extractFile) { int err; CORFIL *inf = corfile_create_w(csound); int c; if ((err = setjmp(csound->exitjmp)) != 0) { return ((err - CSOUND_EXITJMP_SUCCESS) | CSOUND_EXITJMP_SUCCESS); } while ((c=getc(inFile))!=EOF) corfile_putc(csound, c, inf); corfile_rewind(inf); scxtract(csound, inf, extractFile); while ((c=corfile_getc(csound->scstr))!=EOF) putc(c, outFile); corfile_rm(csound, &csound->scstr); return 0; } csound-6.10.0/all_string_files000066400000000000000000000365651321653344700163630ustar00rootroot00000000000000./Engine/auxfd.c ./Engine/cfgvar.c ./Engine/corfiles.c ./Engine/cs_new_dispatch.c ./Engine/cs_par_base.c ./Engine/cs_par_dispatch.c ./Engine/cs_par_orc_semantic_analysis.c ./Engine/csound_data_structures.c ./Engine/csound_orc_compile.c ./Engine/csound_orc_expressions.c ./Engine/csound_orc_optimize.c ./Engine/csound_orc_semantics.c ./Engine/csound_standard_types.c ./Engine/csound_type_system.c ./Engine/csound_orc.lex ./Engine/csound_orc.y ./Engine/csound_pre.lex ./Engine/csound_prs.lex ./Engine/entry1.c ./Engine/envvar.c ./Engine/extract.c ./Engine/fgens.c ./Engine/insert.c ./Engine/linevent.c ./Engine/memalloc.c ./Engine/memfiles.c ./Engine/musmon.c ./Engine/namedins.c ./Engine/new_orc_parser.c ./Engine/parse_param.h ./Engine/pools.c ./Engine/rdscor.c ./Engine/scope.c ./Engine/score_param.h ./Engine/scsort.c ./Engine/scxtract.c ./Engine/sort.c ./Engine/sread.c ./Engine/swritestr.c ./Engine/symbtab.c ./Engine/twarp.c ./H/aops.h ./H/bus.h ./H/cmath.h ./H/compile_ops.h ./H/convolve.h ./H/corfile.h ./H/csGblMtx.h ./H/cs_jack.h ./H/csmodule.h ./H/csound_orc_expressions.h ./H/csound_orc.h ./H/csound_orc_semantics.h ./H/cs_par_base.h ./H/cs_par_dispatch.h ./H/cs_par_ops.h ./H/cs_par_orc_semantics.h ./H/diskin2.h ./H/disprep.h ./H/dumpf.h ./H/entry1.h ./H/envvar.h ./H/extract.h ./H/fftlib.h ./H/fgens.h ./H/find_opcode.h ./H/insert.h ./H/linevent.h ./H/lpc.h ./H/midifile.h ./H/midiinterop.h ./H/midioops.h ./H/midiops.h ./H/midiout.h ./H/mp3dec.h ./H/mp3dec_internal.h ./H/mpadec.h ./H/mpadec_internal.h ./H/namedins.h ./H/new_opts.h ./H/oload.h ./H/oscils.h ./H/pffft.h ./H/prototyp.h ./H/remote.h ./H/resize.h ./H/schedule.h ./H/sndinfUG.h ./H/sort.h ./H/str_ops.h ./H/tok.h ./H/ugens1.h ./H/ugens2.h ./H/ugens3.h ./H/ugens4.h ./H/ugens5.h ./H/ugens6.h ./H/ugens7.h ./H/ugrw1.h ./H/ugtabs.h ./H/vdelay.h ./H/windin.h ./H/winEPS.h ./InOut/FL_graph.cpp ./InOut/circularbuffer.c ./InOut/cmidi.c ./InOut/ipmidi.c ./InOut/libmpadec/layer1.c ./InOut/libmpadec/layer2.c ./InOut/libmpadec/layer3.c ./InOut/libmpadec/mp3dec.c ./InOut/libmpadec/mp3dec_internal.h ./InOut/libmpadec/mpadec.c ./InOut/libmpadec/mpadec_config.h ./InOut/libmpadec/mpadec_internal.h ./InOut/libmpadec/synth.c ./InOut/libmpadec/tables.c ./InOut/libsnd.c ./InOut/libsnd_u.c ./InOut/midifile.c ./InOut/midirecv.c ./InOut/midisend.c ./InOut/pmidi.c ./InOut/rtalsa.c ./InOut/rtauhal.c ./InOut/rtjack.c ./InOut/rtpa.c ./InOut/rtpulse.c ./InOut/rtwinmm.c ./InOut/virtual_keyboard/Bank.cpp ./InOut/virtual_keyboard/Bank.hpp ./InOut/virtual_keyboard/FLTKKeyboard.cpp ./InOut/virtual_keyboard/FLTKKeyboard.hpp ./InOut/virtual_keyboard/FLTKKeyboardWidget.cpp ./InOut/virtual_keyboard/FLTKKeyboardWidget.hpp ./InOut/virtual_keyboard/FLTKKeyboardWindow.cpp ./InOut/virtual_keyboard/FLTKKeyboardWindow.hpp ./InOut/virtual_keyboard/KeyboardMapping.cpp ./InOut/virtual_keyboard/KeyboardMapping.hpp ./InOut/virtual_keyboard/Program.cpp ./InOut/virtual_keyboard/Program.hpp ./InOut/virtual_keyboard/SliderBank.cpp ./InOut/virtual_keyboard/SliderBank.hpp ./InOut/virtual_keyboard/SliderData.cpp ./InOut/virtual_keyboard/SliderData.hpp ./InOut/virtual_keyboard/virtual_keyboard.cpp ./InOut/widgets.cpp ./InOut/widgets.h ./InOut/widglobals.h ./InOut/winEPS.c ./InOut/winFLTK.c ./InOut/winFLTK.h ./InOut/winascii.c ./InOut/windin.c ./InOut/window.c ./OOps/aops.c ./OOps/bus.c ./OOps/cmath.c ./OOps/compile_ops.c ./OOps/diskin2.c ./OOps/disprep.c ./OOps/dumpf.c ./OOps/fftlib.c ./OOps/goto_ops.c ./OOps/midiinterop.c ./OOps/midiops.c ./OOps/midiout.c ./OOps/mxfft.c ./OOps/oscils.c ./OOps/pstream.c ./OOps/pvfileio.c ./OOps/pvsanal.c ./OOps/random.c ./OOps/remote.c ./OOps/schedule.c ./OOps/sndinfUG.c ./OOps/str_ops.c ./OOps/ugens1.c ./OOps/ugens2.c ./OOps/ugens3.c ./OOps/ugens4.c ./OOps/ugens5.c ./OOps/ugens6.c ./OOps/ugrw1.c ./OOps/ugtabs.c ./OOps/vdelay.c ./Opcodes/3Dug.h ./Opcodes/LuaCsound.cpp ./Opcodes/OSC.c ./Opcodes/Vosim.c ./Opcodes/ableton_link_opcodes.cpp ./Opcodes/afilters.c ./Opcodes/ambicode.c ./Opcodes/ambicode1.c ./Opcodes/ampmidid.cpp ./Opcodes/arrayops.cpp ./Opcodes/arrays.c ./Opcodes/babo.c ./Opcodes/babo.h ./Opcodes/bbcut.c ./Opcodes/bbcut.h ./Opcodes/bilbar.c ./Opcodes/biquad.c ./Opcodes/biquad.h ./Opcodes/bowed.h ./Opcodes/bowedbar.c ./Opcodes/bowedbar.h ./Opcodes/brass.h ./Opcodes/buchla.c ./Opcodes/butter.c ./Opcodes/cellular.c ./Opcodes/chua/ChuaOscillator.cpp ./Opcodes/clarinet.h ./Opcodes/clfilt.c ./Opcodes/clfilt.h ./Opcodes/compress.c ./Opcodes/control.c ./Opcodes/control.h ./Opcodes/cpumeter.c ./Opcodes/cross2.c ./Opcodes/crossfm.c ./Opcodes/crossfm.h ./Opcodes/cuda/adsyn.cu ./Opcodes/cuda/pvsops.cu ./Opcodes/dam.c ./Opcodes/dam.h ./Opcodes/date.c ./Opcodes/dcblockr.c ./Opcodes/dcblockr.h ./Opcodes/doppler.cpp ./Opcodes/dsputil.c ./Opcodes/dsputil.h ./Opcodes/dssi4cs/src/dssi.h ./Opcodes/dssi4cs/src/dssi4cs.c ./Opcodes/dssi4cs/src/dssi4cs.h ./Opcodes/dssi4cs/src/ladspa.h ./Opcodes/dssi4cs/src/load.c ./Opcodes/dssi4cs/src/utils.h ./Opcodes/emugens/emugens.c ./Opcodes/emugens/scugens.c ./Opcodes/eqfil.c ./Opcodes/exciter.c ./Opcodes/fareygen.c ./Opcodes/fareyseq.c ./Opcodes/faustgen.cpp ./Opcodes/fhtfun.h ./Opcodes/filter.c ./Opcodes/filter.h ./Opcodes/flanger.c ./Opcodes/flanger.h ./Opcodes/fluidOpcodes/fluidOpcodes.cpp ./Opcodes/fluidOpcodes/fluidOpcodes.h ./Opcodes/flute.h ./Opcodes/fm4op.c ./Opcodes/fm4op.h ./Opcodes/follow.c ./Opcodes/follow.h ./Opcodes/fout.c ./Opcodes/fout.h ./Opcodes/framebuffer/Framebuffer.c ./Opcodes/framebuffer/Framebuffer.h ./Opcodes/framebuffer/OLABuffer.c ./Opcodes/framebuffer/OLABuffer.h ./Opcodes/framebuffer/OpcodeEntries.c ./Opcodes/freeverb.c ./Opcodes/ftconv.c ./Opcodes/ftest.c ./Opcodes/ftgen.c ./Opcodes/ftsamplebank.cpp ./Opcodes/gab/gab.c ./Opcodes/gab/gab.h ./Opcodes/gab/hvs.c ./Opcodes/gab/newgabopc.c ./Opcodes/gab/sliderTable.c ./Opcodes/gab/stdopcod.h ./Opcodes/gab/tabmorph.c ./Opcodes/gab/vectorial.c ./Opcodes/gab/vectorial.h ./Opcodes/gendy.c ./Opcodes/getftargs.c ./Opcodes/grain.c ./Opcodes/grain.h ./Opcodes/grain4.c ./Opcodes/grain4.h ./Opcodes/harmon.c ./Opcodes/hdf5/HDF5IO.c ./Opcodes/hdf5/HDF5IO.h ./Opcodes/hrtfearly.c ./Opcodes/hrtferX.c ./Opcodes/hrtferx.h ./Opcodes/hrtfopcodes.c ./Opcodes/hrtfreverb.c ./Opcodes/ifd.c ./Opcodes/imageOpcodes.c ./Opcodes/imageOpcodes.h ./Opcodes/jackTransport.c ./Opcodes/jacko.cpp ./Opcodes/linear_algebra.cpp ./Opcodes/linuxjoystick.c ./Opcodes/linuxjoystick.h ./Opcodes/liveconv.c ./Opcodes/locsig.c ./Opcodes/locsig.h ./Opcodes/loscilx.c ./Opcodes/lowpassr.c ./Opcodes/lowpassr.h ./Opcodes/mandolin.c ./Opcodes/mandolin.h ./Opcodes/marimba.h ./Opcodes/metro.c ./Opcodes/midiops2.c ./Opcodes/midiops2.h ./Opcodes/midiops3.c ./Opcodes/midiops3.h ./Opcodes/minmax.c ./Opcodes/mixer.cpp ./Opcodes/modal4.c ./Opcodes/modal4.h ./Opcodes/modmatrix.c ./Opcodes/modmatrix.h ./Opcodes/moog1.c ./Opcodes/moog1.h ./Opcodes/mp3in.c ./Opcodes/newfils.c ./Opcodes/newfils.h ./Opcodes/nlfilt.c ./Opcodes/nlfilt.h ./Opcodes/opencl/cladsynth.c ./Opcodes/oscbnk.c ./Opcodes/oscbnk.h ./Opcodes/p5glove.c ./Opcodes/padsynth_gen.cpp ./Opcodes/pan2.c ./Opcodes/partials.c ./Opcodes/partikkel.c ./Opcodes/partikkel.h ./Opcodes/paulstretch.c ./Opcodes/phisem.c ./Opcodes/phisem.h ./Opcodes/physmod.c ./Opcodes/physutil.c ./Opcodes/physutil.h ./Opcodes/pinker.c ./Opcodes/pitch.c ./Opcodes/pitch.h ./Opcodes/pitch0.c ./Opcodes/pitchtrack.c ./Opcodes/platerev.c ./Opcodes/pluck.c ./Opcodes/pluck.h ./Opcodes/psynth.c ./Opcodes/ptrigtbl.h ./Opcodes/pvadd.c ./Opcodes/pvadd.h ./Opcodes/pvinterp.c ./Opcodes/pvinterp.h ./Opcodes/pvlock.c ./Opcodes/pvoc.c ./Opcodes/pvoc.h ./Opcodes/pvocext.c ./Opcodes/pvocext.h ./Opcodes/pvread.c ./Opcodes/pvread.h ./Opcodes/pvs_ops.c ./Opcodes/pvs_ops.h ./Opcodes/pvsband.c ./Opcodes/pvsbasic.c ./Opcodes/pvsbasic.h ./Opcodes/pvsbuffer.c ./Opcodes/pvscent.c ./Opcodes/pvsdemix.c ./Opcodes/pvsdemix.h ./Opcodes/pvsgendy.c ./Opcodes/pvsops.cpp ./Opcodes/py/pycall.auto.c ./Opcodes/py/pycall.auto.h ./Opcodes/py/pythonhelper.h ./Opcodes/py/pythonopcodes.c ./Opcodes/py/pythonopcodes.h ./Opcodes/py/pyx.auto.c ./Opcodes/py/pyx.auto.h ./Opcodes/quadbezier.c ./Opcodes/repluck.c ./Opcodes/repluck.h ./Opcodes/reverbsc.c ./Opcodes/scansyn.c ./Opcodes/scansyn.h ./Opcodes/scansynx.c ./Opcodes/scoreline.c ./Opcodes/seqtime.c ./Opcodes/select.c ./Opcodes/serial.c ./Opcodes/sf.h ./Opcodes/sfenum.h ./Opcodes/sfont.c ./Opcodes/sfont.h ./Opcodes/sftype.h ./Opcodes/shaker.c ./Opcodes/shaker.h ./Opcodes/shape.c ./Opcodes/signalflowgraph.cpp ./Opcodes/singwave.c ./Opcodes/singwave.h ./Opcodes/sndloop.c ./Opcodes/sndwarp.c ./Opcodes/sndwarp.h ./Opcodes/sockrecv.c ./Opcodes/socksend.c ./Opcodes/space.c ./Opcodes/space.h ./Opcodes/spat3d.c ./Opcodes/spat3d.h ./Opcodes/spectra.c ./Opcodes/spectra.h ./Opcodes/squinewave.c ./Opcodes/stackops.c ./Opcodes/stdopcod.c ./Opcodes/stdopcod.h ./Opcodes/stk/stkOpcodes.cpp ./Opcodes/syncgrain.c ./Opcodes/syncgrain.h ./Opcodes/system_call.c ./Opcodes/tabsum.c ./Opcodes/tl/fractalnoise.cpp ./Opcodes/tl/sc_noise.c ./Opcodes/ugakbari.c ./Opcodes/ugens7.c ./Opcodes/ugens8.c ./Opcodes/ugens8.h ./Opcodes/ugens9.c ./Opcodes/ugens9.h ./Opcodes/ugensa.c ./Opcodes/ugensa.h ./Opcodes/uggab.c ./Opcodes/uggab.h ./Opcodes/ugmoss.c ./Opcodes/ugmoss.h ./Opcodes/ugnorman.c ./Opcodes/ugnorman.h ./Opcodes/ugsc.c ./Opcodes/ugsc.h ./Opcodes/urandom.c ./Opcodes/vaops.c ./Opcodes/vbap.c ./Opcodes/vbap.h ./Opcodes/vbap1.c ./Opcodes/vbap_n.c ./Opcodes/vbap_zak.c ./Opcodes/vibraphn.h ./Opcodes/vpvoc.c ./Opcodes/vpvoc.h ./Opcodes/vst4cs/src/fxbank.cpp ./Opcodes/vst4cs/src/fxbank.h ./Opcodes/vst4cs/src/vst4cs.cpp ./Opcodes/vst4cs/src/vst4cs.h ./Opcodes/vst4cs/src/vsthost.cpp ./Opcodes/vst4cs/src/vsthost.h ./Opcodes/wave-terrain.c ./Opcodes/wave-terrain.h ./Opcodes/wavegde.h ./Opcodes/websockets/WebSocketOpcode.c ./Opcodes/websockets/WebSocketOpcode.h ./Opcodes/wii_mac.h ./Opcodes/wiimote.c ./Opcodes/wpfilters.c ./Opcodes/wpfilters.h ./SDIF/sdif-mem.c ./SDIF/sdif-mem.h ./SDIF/sdif.c ./SDIF/sdif.h ./SDIF/sdif2adsyn.c ./Top/argdecode.c ./Top/cscore_internal.c ./Top/cscorfns.c ./Top/csdebug.c ./Top/csmodule.c ./Top/csound.c ./Top/getstring.c ./Top/main.c ./Top/new_opts.c ./Top/one_file.c ./Top/opcode.c ./Top/server.c ./Top/threads.c ./Top/threadsafe.c ./Top/utility.c ./frontends/CsoundAC/Cell.cpp ./frontends/CsoundAC/Cell.hpp ./frontends/CsoundAC/ChordLindenmayer.cpp ./frontends/CsoundAC/ChordLindenmayer.hpp ./frontends/CsoundAC/Composition.cpp ./frontends/CsoundAC/Composition.hpp ./frontends/CsoundAC/Conversions.cpp ./frontends/CsoundAC/Conversions.hpp ./frontends/CsoundAC/Counterpoint.cpp ./frontends/CsoundAC/Counterpoint.hpp ./frontends/CsoundAC/CounterpointMain.cpp ./frontends/CsoundAC/CounterpointNode.cpp ./frontends/CsoundAC/CounterpointNode.hpp ./frontends/CsoundAC/Event.cpp ./frontends/CsoundAC/Event.hpp ./frontends/CsoundAC/Exception.hpp ./frontends/CsoundAC/Hocket.cpp ./frontends/CsoundAC/Hocket.hpp ./frontends/CsoundAC/ImageToScore.cpp ./frontends/CsoundAC/ImageToScore.hpp ./frontends/CsoundAC/Lindenmayer.cpp ./frontends/CsoundAC/Lindenmayer.hpp ./frontends/CsoundAC/MCRM.cpp ./frontends/CsoundAC/MCRM.hpp ./frontends/CsoundAC/Midifile.cpp ./frontends/CsoundAC/Midifile.hpp ./frontends/CsoundAC/MusicModel.cpp ./frontends/CsoundAC/MusicModel.hpp ./frontends/CsoundAC/Node.cpp ./frontends/CsoundAC/Node.hpp ./frontends/CsoundAC/OrchestraNode.hpp ./frontends/CsoundAC/Platform.hpp ./frontends/CsoundAC/Random.cpp ./frontends/CsoundAC/Random.hpp ./frontends/CsoundAC/Rescale.cpp ./frontends/CsoundAC/Rescale.hpp ./frontends/CsoundAC/Score.cpp ./frontends/CsoundAC/Score.hpp ./frontends/CsoundAC/ScoreModel.cpp ./frontends/CsoundAC/ScoreModel.hpp ./frontends/CsoundAC/ScoreNode.cpp ./frontends/CsoundAC/ScoreNode.hpp ./frontends/CsoundAC/Sequence.cpp ./frontends/CsoundAC/Sequence.hpp ./frontends/CsoundAC/Shell.cpp ./frontends/CsoundAC/Shell.hpp ./frontends/CsoundAC/Silence.hpp ./frontends/CsoundAC/Soundfile.cpp ./frontends/CsoundAC/Soundfile.hpp ./frontends/CsoundAC/StrangeAttractor.cpp ./frontends/CsoundAC/StrangeAttractor.hpp ./frontends/CsoundAC/System.cpp ./frontends/CsoundAC/System.hpp ./frontends/CsoundAC/Voicelead.cpp ./frontends/CsoundAC/Voicelead.hpp ./frontends/CsoundAC/VoiceleadingNode.cpp ./frontends/CsoundAC/VoiceleadingNode.hpp ./frontends/CsoundAC/algrd_internal.h ./frontends/CsoundAC/algsmfrd_internal.h ./frontends/CsoundAC/allegro.cpp ./frontends/CsoundAC/allegro.h ./frontends/CsoundAC/allegrord.cpp ./frontends/CsoundAC/allegroserial.cpp ./frontends/CsoundAC/allegrosmfrd.cpp ./frontends/CsoundAC/allegrosmfwr.cpp ./frontends/CsoundAC/allegrowr.cpp ./frontends/CsoundAC/mfmidi.cpp ./frontends/CsoundAC/mfmidi.h ./frontends/CsoundAC/strparse.cpp ./frontends/CsoundAC/strparse.h ./frontends/CsoundAC/trace.cpp ./frontends/CsoundAC/trace.h ./frontends/CsoundVST/CsoundVST.cpp ./frontends/CsoundVST/CsoundVST.hpp ./frontends/CsoundVST/CsoundVSTMain.cpp ./frontends/CsoundVST/CsoundVstFltk.cpp ./frontends/CsoundVST/CsoundVstFltk.hpp ./frontends/CsoundVST/CsoundVstUi.cpp ./frontends/CsoundVST/CsoundVstUi.h ./frontends/CsoundVST/Platform.hpp ./frontends/CsoundVST/ScoreGenerator.cpp ./frontends/CsoundVST/ScoreGenerator.hpp ./frontends/CsoundVST/ScoreGeneratorVst.cpp ./frontends/CsoundVST/ScoreGeneratorVst.hpp ./frontends/CsoundVST/ScoreGeneratorVstFltk.cpp ./frontends/CsoundVST/ScoreGeneratorVstFltk.hpp ./frontends/CsoundVST/ScoreGeneratorVstMain.cpp ./frontends/CsoundVST/ScoreGeneratorVstUi.cpp ./frontends/CsoundVST/ScoreGeneratorVstUi.h ./frontends/CsoundVST/csoundvst_main.cpp ./frontends/CsoundVST/pyrun.c ./frontends/csladspa/csladspa.cpp ./frontends/csladspa/ladspa.h ./frontends/csound/csound_main.c ./frontends/csound/sched.c ./frontends/csoundapi_tilde/csoundapi_tilde.c ./frontends/debugger/csdebugger.cpp ./frontends/winsound/main.cxx ./frontends/winsound/winsound.fl ./include/OpcodeBase.hpp ./include/cfgvar.h ./include/cs_par_structs.h ./include/cscore.h ./include/csdebug.h ./include/csdl.h ./include/csound.h ./include/csound.hpp ./include/csoundCore.h ./include/csound_data_structures.h ./include/csound_standard_types.h ./include/csound_type_system.h ./include/cwindow.h ./include/float-version.h ./include/interlocks.h ./include/msg_attr.h ./include/OpcodeBase.hpp ./include/plugin.h ./include/pools.h ./include/pstream.h ./include/pvfileio.h ./include/soundio.h ./include/sysdep.h ./include/text.h ./include/version.h ./interfaces/CppSound.cpp ./interfaces/CppSound.hpp ./interfaces/CsoundFile.cpp ./interfaces/CsoundFile.hpp ./interfaces/Soundfile.cpp ./interfaces/Soundfile.hpp ./interfaces/csPerfThread.cpp ./interfaces/csPerfThread.hpp ./interfaces/cs_glue.cpp ./interfaces/cs_glue.hpp ./interfaces/filebuilding.cpp ./interfaces/filebuilding.h ./interfaces/pyMsgCb.cpp ./interfaces/pyMsgCb_stub.cpp ./pluginSDK/examplePlugin.c ./util/atsa.c ./util/atsa_main.c ./util/csanalyze.c ./util/cvanal.c ./util/cvl_main.c ./util/dnoise.c ./util/dnoise_main.c ./util/env_main.c ./util/envext.c ./util/het_export.c ./util/het_import.c ./util/het_main.c ./util/heti_main.c ./util/hetro.c ./util/hetx_main.c ./util/lpanal.c ./util/lpc_export.c ./util/lpc_import.c ./util/lpc_main.c ./util/lpci_main.c ./util/lpcx_main.c ./util/mixer.c ./util/mixer_main.c ./util/pv_export.c ./util/pv_import.c ./util/pvanal.c ./util/pvc_main.c ./util/pvi_main.c ./util/pvl_main.c ./util/pvlook.c ./util/pvx_main.c ./util/scale.c ./util/scale_main.c ./util/sndinfo.c ./util/sndinfo_main.c ./util/srconv.c ./util/srconv_main.c ./util/std_util.c ./util/std_util.h ./util/utilmain.h ./util/xtrc_main.c ./util/xtrct.c ./util1/csd_util/base64.c ./util1/csd_util/cs.c ./util1/csd_util/csb64enc.c ./util1/csd_util/makecsd.c ./util1/scot/scot.c ./util1/scot/scot.h ./util1/scot/scot_main.c ./util1/sortex/smain.c ./util1/sortex/xmain.c csound-6.10.0/appveyor.yml000066400000000000000000000126111321653344700154720ustar00rootroot00000000000000image: Visual Studio 2017 environment: ABLETON_LINK_HOME: C:\projects\csound\msvc\deps\link APPVEYOR_SAVE_CACHE_ON_ERROR: "true" APPVEYOR_RDP_PASSWORD: Vercoe123 CsoundDepsDir: C:\projects\csound\msvc\deps\bin CSOUND_VERSION: 6.10.0-rc2 HDF5_HOME: C:\Program Files\HDF_Group\HDF5\1.8.19 QTDIR: C:\Qt\5.9.2\msvc2017_64 VCPKGDir: C:\Tools\vcpkg VSGENERATOR: Visual Studio 15 2017 Win64 VSTOOLSET: v141 VST_SDK2_HOME: C:\projects\csound\msvc\deps\VST_SDK\VST2_SDK platform: x64 configuration: RelWithDebInfo init: - set CSOUND_HOME=%APPVEYOR_BUILD_FOLDER% - set PYTHON=C:\Python27-x64\python.exe - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) - if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2017" call "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat" - if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2015" call "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin\\amd64\\vcvars64.bat" # C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Redist\MSVC\14.12.25810\x64\Microsoft.VC141.CRT # C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Redist\MSVC\14.12.25810\x64\Microsoft.VC141.CXXAMP # C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Redist\MSVC\14.12.25810\x64\Microsoft.VC141.MFC # C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Redist\MSVC\14.12.25810\x64\Microsoft.VC141.MFCLOC # C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Redist\MSVC\14.12.25810\x64\Microsoft.VC141.OpenMP - set VCREDIST_CRT_DIR=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Redist\MSVC\14.12.25810\x64\Microsoft.VC141.CRT - set VCREDIST_CXXAMP_DIR=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Redist\MSVC\14.12.25810\x64\Microsoft.VC141.CXXAMP - set VCREDIST_OPENMP_DIR=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Redist\MSVC\14.12.25810\x64\Microsoft.VC141.OpenMP - set - echo "Qt SDK configuration files:" - dir "%QTDIR%\\mkspecs" - echo "Redistributable runtime libraries:" - dir /B /S "%VCToolsRedistDir%" - dir /B /S "%VCREDIST_CRT_DIR%" - dir /B /S "%VCREDIST_CXXAMP_DIR%" - dir /B /S "%VCREDIST_OPENMP_DIR%" - set PATH=%PATH%;%CsoundDepsDir% install: - cd msvc # This is so nw-gyp can build csound.node. - ps: Install-Product node 6.2.1 x64 - npm install -g nw-gyp - nodevars.bat - powershell -ExecutionPolicy ByPass -File downloadDependencies.ps1 -vsGenerator "%VSGENERATOR%" -vsToolset "%VSTOOLSET%" - powershell -ExecutionPolicy ByPass -File generateProject.ps1 -vsGenerator "%VSGENERATOR%" -vsToolset "%VSTOOLSET%" -vstSdkHome "%VST_SDK2_HOME% - cd .. build: parallel: true project: msvc\csound-vs\Csound.sln after_build: - dir "%VCPKGDir%\installed\x64-windows-static\include" - cd frontends\nwjs - npm config set msvs_version 2017 --global #- set PYTHON=C:\Python27-x64\python.exe - set npm_config_target=0.23.5 - set npm_config_arch=x64 - set npm_config_runtime=node-webkit - set npm_config_build_from_source=true - set npm_config_node_gyp=C:\Users\appveyor\AppData\Roaming\npm\node_modules\nw-gyp\bin\nw-gyp.js - npm configure --version=0.23.5 - nw-gyp rebuild --target=0.23.5 --arch=x64 && exit=0 - cd ..\.. - set PATH=%QTDIR%\bin;%PATH% - cd msvc # Report qmake version to make sure we are using the Qt libraries we need. - qmake -v - build-csoundqt.bat - cd .. - set PATH=%PATH%;"C:\\Program Files (x86)\\Inno Setup 5" - iscc /dVcpkgInstalledBinDir=%VCPKGDir%\\installed\\x64-windows\\bin\\ /dQtSdkBinDir=%QTDIR%\\bin\\ /dInstallCsoundVst /omsvc installer\\windows\\csound6_x64_appveyor.iss - 7z a csound-windows-x64-%CSOUND_VERSION%-%APPVEYOR_BUILD_NUMBER%.zip %APPVEYOR_BUILD_FOLDER%\msvc\csound-vs\RelWithDebInfo\*.exe %APPVEYOR_BUILD_FOLDER%\msvc\csound-vs\RelWithDebInfo\csound64.lib %APPVEYOR_BUILD_FOLDER%\include\ %APPVEYOR_BUILD_FOLDER%\msvc\csound-vs\RelWithDebInfo\*.dll %APPVEYOR_BUILD_FOLDER%\msvc\csound-vs\RelWithDebInfo\*.pyd %APPVEYOR_BUILD_FOLDER%\msvc\csound-vs\*.jar %APPVEYOR_BUILD_FOLDER%\msvc\csound-vs\*.py %APPVEYOR_BUILD_FOLDER%\msvc\staging\CsoundQt\bin\*.exe - 7z l csound-windows-x64-%CSOUND_VERSION%-%APPVEYOR_BUILD_NUMBER%.zip # Tests test_script: - cmake --build msvc\csound-vs --config RelWithDebInfo --target csdtests artifacts: - path: csound-windows-x64-*.zip name: Csound Binaries type: zip - path: msvc/csound-windows-x64-*.exe name: Csound Installer type: exe cache: - C:\Tools\vcpkg\ -> C:\projects\csound\msvc\downloadDependencies.ps1 - C:\projects\csound\msvc\cache deploy: release: csound-$(csound_version) description: 'Csound Windows installer.' provider: GitHub auth_token: secure: puEAPJVkwT2mZwhobSNpk5LhUEP+61K9j6T66qIXKFk= artifact: msvc/csound-windows-x64*.exe draft: true prerelease: true on: branch: develop appveyor_repo_tag: true # deploy on tag push only notifications: - provider: Email to: - CSOUND-DEV@listserv.heanet.ie subject: 'Build {{status}}' # optional on_build_success: false on_build_failure: true on_build_status_changed: false # - provider: Slack # auth_token: # secure: kBl9BlxvRMr9liHmnBs14A== # channel: development # template: "{{template_variable_1}}, {{template_variable_2}}, ..." csound-6.10.0/brkpt000077500000000000000000000263011321653344700141530ustar00rootroot00000000000000#!/usr/bin/perl # Linseg helper perltk script. # written april 2002 by Matthew Gilliard # Adjusted to produce breakpoint files # September 2002 John ffitch # Mainly names on screen and output format use Tk; use strict; use vars qw($main); my $scale = 500; my $i; my $olt; my $folt; my $pc = 0; my $max_x = 1; my $min_y = 0; my $max_y = 1; my $main = new MainWindow; my @xlist; my @ylist; my @point; my %iinfo; my $fname; if (@ARGV){ $fname = $ARGV[0]; }else{ $fname = "bkptfi"; } open(FF,'>',$fname) or die "Cannot open output"; # First of all, put everything on the screen: $main->Label(-text => 'breakpoint file creator')->pack; # Frames for arranging things in my $bf = $main->Frame->pack; my $bft = $bf->Frame->pack(qw/-side top/); my $bfb = $bf->Frame->pack(qw/-side bottom -fill x/); my $ftl = $bft->Frame->pack(qw/-side left -fill y/); my $ftr = $bft->Frame->pack(qw/-side right/); # X-axis max entry. There is no x-min (see help file). $bfb->Entry(-relief => 'sunken', -textvariable => \$max_x, -width => 4)->pack(qw/-side right/); # Y-axis entries $ftl->Entry(-relief => 'sunken', -textvariable => \$min_y, -width => 4)->pack(qw/-side bottom/); $ftl->Entry(-relief => 'sunken', -textvariable => \$max_y, -width => 4)->pack(qw/-side top/); #Drawing canvs (the graph area) my $c = $ftr->Canvas(relief => 'raised', width => $scale+8, height => $scale+11, cursor => 'top_left_arrow'); $c->pack(qw/-side right/); # Background square (new dot if right-clicked) my $rect = $c->createRectangle(4,4,$scale+4,$scale+4, -fill => 'white'); $c->addtag("background", 'withtag', $rect); $c->bind("background", '<3>' => [sub{new_dot(shift, $Tk::event->x, $Tk::event->y)}]); # Start point of graph my $leftpoint = $c->createOval(1,$scale+7,7,$scale+1, -width => 1, -outline => 'black', -fill => 'darkred'); $c->addtag("left_point", 'withtag', $leftpoint); $c->bind("left_point", '' => [sub{shift->itemconfigure(@_)}, 'current', -fill => 'Skyblue2']); $c->bind("left_point", '' => [sub{shift->itemconfigure(@_)}, 'current', -fill => 'darkred']); $c->bind("left_point", '' => [sub{drag_edge(shift, $Tk::event->x, $Tk::event->y, \%iinfo)}]); $c->bind("left_point", '<1>' => [sub{start_drag_point(shift, $Tk::event->x, $Tk::event->y, \%iinfo)}]); # End point of graph my $rightpoint = $c->createOval($scale+1,1,$scale+7,7, -width => 1, -outline => 'black', -fill => 'darkred'); $c->addtag("right_point", 'withtag', $rightpoint); $c->bind("right_point", '' => [sub{shift->itemconfigure(@_)}, 'current', -fill => 'Skyblue2']); $c->bind("right_point", '' => [sub{shift->itemconfigure(@_)}, 'current', -fill => 'darkred']); $c->bind("right_point", '' => [sub{drag_edge(shift, $Tk::event->x, $Tk::event->y, \%iinfo)}]); $c->bind("right_point", '<1>' => [sub{start_drag_point(shift, $Tk::event->x, $Tk::event->y, \%iinfo)}]); # output line ("brkpt ...) my $outline = $main->Entry(-textvariable => \$olt)->pack(qw/-fill x/); # Row of buttons (Print, Refresh, Exit) my $f = $main->Frame->pack; $f->Button(-relief => 'raised', -text => 'Exit', -command => sub{print "$olt\n"; print FF "$folt"; exit;})->pack(qw/-side right/); $f->Button(-relief => 'raised', -text => 'Show', -command => sub{print "$olt\n";})->pack(qw/-side left/); $f->Button(-relief => 'raised', -text => 'Abort', -command => sub{exit;})->pack(qw/-side left/); $f->Button(-relief => 'raised', -text => 'Refresh', -command => sub{draw_lines($c)} )->pack(qw/-side left/); # Initialise screen draw_lines($c); # Start responding to user input MainLoop; # #Start of subroutines # sub new_dot(){ # This is called by a right-click on the background # It adds the dot, and redraws the lines to include the new dot. my ($c, $x, $y) = @_; $x = $c->canvasx($x); $y = $c->canvasy($y); draw_dot($x, $y, ++$pc); draw_lines($c); } sub draw_dot(){ # This is called (only) by new_dot() # It draws the new dot in the right place and sets its behaviour my ($xpos, $ypos) = @_; $point[$pc] = $c->createOval($xpos-3,$ypos-3,$xpos+3,$ypos+3, -width => 1, -outline => 'black', -fill => 'red'); $c->addtag("p$pc", 'withtag', $point[$pc]); $c->bind("p$pc", '' => [sub{shift->itemconfigure(@_)}, 'current', -fill => 'Skyblue2']); $c->bind("p$pc", '' => [sub{shift->itemconfigure(@_)}, 'current', -fill => 'Red']); $c->bind("p$pc", '' => [sub{drag_point(shift, $Tk::event->x, $Tk::event->y, \%iinfo)}]); $c->bind("p$pc", '<1>' => [sub{start_drag_point(shift, $Tk::event->x, $Tk::event->y, \%iinfo)}]); $c->bind("p$pc", '<3>' => [sub{remove_dot(shift)}]); } sub remove_dot(){ # This is called when a dot is right-clicked on # It deletes the dot in question, resorts the array of coords and redraws the lines my ($c) = @_; $c->delete('current'); getsort(); draw_lines($c); } sub getsort(){ # This is called whenever a dot is moved, added or removed. # It finds all the dots' coordinates, sticks them in 2 arrays, and sorts them my $i; my $j = 0; my $tx; my $ty; my $temp; # clear old arrays @xlist = (); @ylist = (); # find dots, and populate arrays for ($i=0; $i<=100; $i++){ ($tx,,$ty,) = $c->coords("p$i"); if ($tx && $ty){ $xlist[$j] = int $tx - 1; $ylist[$j++] = int $ty - 1; } } $pc = $j; # Sort arrays in order of increasing x value. for ($j=0; $j<$pc; $j++){ for ($i=0; $i<$pc; $i++){ if ($xlist[$i] > $xlist[$i+1]){ $temp = $xlist[$i]; $xlist[$i] = $xlist[$i+1]; $xlist[$i+1] = $temp; $temp = $ylist[$i]; $ylist[$i] = $ylist[$i+1]; $ylist[$i+1] = $temp; } } } } sub start_drag_point(){ # Called when a dot is clicked on # Gets the dot's coords, ready for it to be dragged my ($c, $x, $y, $iinfo) = @_; $iinfo->{lastx} = $c->canvasx($x); $iinfo->{lasty} = $c->canvasy($y); } sub drag_point(){ # Called when a dot is dragged my ($c, $x, $y, $iinfo) = @_; my $cx; my $cy; $x = $c->canvasx($x); $y = $c->canvasy($y); ($cx,,$cy,) = $c->coords('current'); my $xamount = $x - $iinfo->{lastx}; my $yamount = $y - $iinfo->{lasty}; # Keep the dot inside the square, not just the canvas if (($cx + $x - $iinfo->{lastx} < 3) || ($cx + $x - $iinfo->{lastx} > $scale)){ $xamount = 0; } if (($cy + $y - $iinfo->{lasty} > $scale) || ($cy + $y - $iinfo->{lasty} < 1)){ $yamount = 0; } $c->move('current', $xamount, $yamount); $iinfo->{lastx} = $x; $iinfo->{lasty} = $y; # Redraw lines draw_lines($c); } sub drag_edge(){ # The same as drag_point, but for the end dots, only up and down. my ($c, $x, $y, $iinfo) = @_; my $cx; my $cy; $x = $c->canvasx($x); $y = $c->canvasy($y); ($cx,,$cy,) = $c->coords('current'); # Not off the top or bottom, please if (($cy + $y - $iinfo->{lasty} > 0) && ($cy + $y - $iinfo->{lasty} <= $scale)){ $c->move('current', 0, $y-$iinfo->{lasty}); $iinfo->{lastx} = $x; $iinfo->{lasty} = $y; } # Redraw lines draw_lines($c); } sub draw_lines(){ # Called whenever the lines need redrawing (all the time) my ($c) = @_; my $i; # Refresh array of points getsort(); # Delete all lines for ($i=0; $i<=100; $i++){ $c->delete("line$i"); } # Use end points my ($i,$starty,,) = $c->coords('left_point'); my ($i,$endy,,) = $c->coords('right_point'); $starty -= 1; $endy -= 1; if ($pc == 0){ # Line only has 2 points my $line = $c->createLine(4, $starty+4, $scale+4, $endy+4); $c->addtag('line0', 'withtag', $line); $c->lower('line0', 'left_point'); }else{ # First section my $line = $c->createLine(4, $starty+4, $xlist[1]+4, $ylist[1]+4); $c->addtag('line0', 'withtag', $line); $c->lower('line0', 'left_point'); # Middle sections for ($i=1; $i<$pc; $i++){ my $line = $c->createLine($xlist[$i]+4, $ylist[$i]+4, $xlist[$i+1]+4, $ylist[$i+1]+4); $c->addtag("line$i", 'withtag', $line); $c->lower("line$i", 'left_point'); } # Last section my $line = $c->createLine($xlist[$pc]+4, $ylist[$pc]+4, $scale+4, $endy+4); $c->addtag("line$pc", 'withtag', $line); $c->lower("line$pc", 'left_point'); } # Generate the new "brkpt ..." line gen_brkpt($c); print_coords($c); } sub gen_brkpt(){ # Updates the "brkpt ..." line my ($c) = @_; my $i; my $x; my $y; my $tx; my $brkpt = "(0, "; my ($i,$starty,,) = $c->coords('left_point'); my ($i,$endy,,) = $c->coords('right_point'); $starty -= 1; $endy -= 1; # First section $y = int (($scale - $starty)/($scale/100.0))/100; $brkpt .= $y*($max_y-$min_y) + $min_y . ") "; # Middle sections for ($i=1; $i<=$pc; $i++){ $x = int(($xlist[$i])/($scale/100.0))/100.0; $tx = $x; $tx *= $max_x; $y = int(($scale - $ylist[$i])/($scale/100.0))/100 * ($max_y-$min_y) + $min_y; $brkpt .= "($tx, $y) "; } # Last section $tx = 1; $y = int(($scale - $endy)/($scale/100.0))/100 * ($max_y-$min_y) + $min_y; $tx *= $max_x; $brkpt .= "($tx, $y)"; # Display the line $olt = $brkpt; } sub print_coords(){ my ($c) = @_; my $i; my $x; my $y; my $tx; my $fbrkpt = "0\t"; my ($i,$starty,,) = $c->coords('left_point'); my ($i,$endy,,) = $c->coords('right_point'); $starty -= 1; $endy -= 1; # First section $y = int (($scale - $starty)/($scale/100.0))/100; $fbrkpt .= $y*($max_y-$min_y) + $min_y . "\n"; # Middle sections for ($i=1; $i<=$pc; $i++){ $x = int(($xlist[$i])/($scale/100.0))/100.0; $tx = $x; $tx *= $max_x; $y = int(($scale - $ylist[$i])/($scale/100.0))/100 * ($max_y-$min_y) + $min_y; $fbrkpt .= "$tx\t$y\n"; } # Last section $tx = 1; $y = int(($scale - $endy)/($scale/100.0))/100 * ($max_y-$min_y) + $min_y; $tx *= $max_x; $fbrkpt .= "$tx\t$y\n"; $folt = $fbrkpt; } csound-6.10.0/cleanup.sh000077500000000000000000000070251321653344700150730ustar00rootroot00000000000000#!/bin/sh if [ "$#" = "2" ] ; then if [ "$1" = "remove" ] ; then if ( test -e "$2" ) ; then echo "Removing '$2'" rm -Rf "$2" ; fi ; exit 0 ; fi ; exit -1 ; elif [ "$#" != "0" ] ; then exit 0 ; fi "$0" remove ".sconf_temp" "$0" remove "config.log" patterns='*.xmg *.o *.os *.so *.a *.wav *.aif* *.sf *.pcm *.exe *.dll *.obj *.lib *.class' findexpr='-iname .scons*' for pat in $patterns; do findexpr="$findexpr -o -iname $pat" done findexpr="( $findexpr )" find . -type f $findexpr -exec "$0" remove '{}' \; #find . -type f -iname ".scons*" -exec "$0" remove '{}' \; #find . -type f -iname "*.xmg" -exec "$0" remove '{}' \; #find . -type f -iname "*.o" -exec "$0" remove '{}' \; #find . -type f -iname "*.os" -exec "$0" remove '{}' \; #find . -type f -iname "*.so" -exec "$0" remove '{}' \; #find . -type f -iname "*.a" -exec "$0" remove '{}' \; #find . -type f -iname "*.wav" -exec "$0" remove '{}' \; #find . -type f -iname "*.aif*" -exec "$0" remove '{}' \; #find . -type f -iname "*.sf" -exec "$0" remove '{}' \; #find . -type f -iname "*.pcm" -exec "$0" remove '{}' \; #find . -type f -iname "*.exe" -exec "$0" remove '{}' \; #find . -type f -iname "*.dll" -exec "$0" remove '{}' \; #find . -type f -iname "*.obj" -exec "$0" remove '{}' \; #find . -type f -iname "*.lib" -exec "$0" remove '{}' \; find "./interfaces" -type f -iname "*.java" -exec "$0" remove '{}' \; #find "./interfaces" -type f -iname "*.class" -exec "$0" remove '{}' \; notexecpatterns="*.cpp *.cxx *.h *.hpp *.fl *.i *.csd *.py *.sh *.sco *.orc *.txt *.tcl" notexecexpr="-iname *.c" for pat in $notexecpatterns; do notexecexpr="$notexecexpr -o -iname $pat" done notexecexpr="( $notexecexpr )" find . -type f \! $notexecexpr -exec file '{}' \; | grep -E -e ':.*\<(ELF|80386|PE)\>' | cut -d ':' -f 1 | xargs -n 1 "$0" remove #find . -type f \! $notexecexpr -exec file '{}' \; | grep -G -e ':.*\<80386\>' | cut -d ':' -f 1 | xargs -n 1 "$0" remove #find . -type f \! $notexecexpr -exec file '{}' \; | grep -G -e ':.*\' | cut -d ':' -f 1 | xargs -n 1 "$0" remove "$0" remove "./frontends/CsoundVST/CsoundVST_wrap.cc" "$0" remove "./frontends/CsoundVST/CsoundVST_wrap.h" "$0" remove "./CsoundVST.py" "$0" remove "./CsoundVST.pyc" "$0" remove "./CsoundVST.pyo" "$0" remove "./frontends/CsoundAC/CsoundAC_wrap.cc" "$0" remove "./frontends/CsoundAC/CsoundAC_wrap.h" "$0" remove "./CsoundAC.py" "$0" remove "./CsoundAC.pyc" "$0" remove "./CsoundAC.pyo" "$0" remove "./interfaces/python_interface_wrap.cc" "$0" remove "./interfaces/python_interface_wrap.h" "$0" remove "./interfaces/java_interface_wrap.cc" "$0" remove "./interfaces/java_interface_wrap.h" "$0" remove "./interfaces/lua_interface_wrap.cc" "$0" remove "./csnd.py" "$0" remove "./csnd.pyc" "$0" remove "./csnd.pyo" "$0" remove "./interfaces/csnd.py" "$0" remove "./interfaces/csnd.pyc" "$0" remove "./interfaces/csnd.pyo" "$0" remove "./csnd.jar" "$0" remove "./interfaces/csnd" "$0" remove "./Opcodes/Loris/scripting/loris_wrap.cc" "$0" remove "./loris.py" "$0" remove "./loris.pyc" "$0" remove "./loris.pyo" "$0" remove "./frontends/winsound/winsound.cxx" "$0" remove "./frontends/winsound/winsound.h" "$0" remove "./frontends/winsound/winsound.cpp" "$0" remove "./frontends/CsoundVST/ScoreGeneratorVST_wrap.cc" "$0" remove "./frontends/CsoundVST/ScoreGeneratorVST_wrap.h" "$0" remove "./scoregen.py" "$0" remove "./scoregen.pyc" "$0" remove "./scoregen.pyo" rm -f "./libcsound.so" rm -f "./libcsound64.so" rm -f "./_csnd.so" rm -f "./_CsoundVST.so" rm -f "./_CsoundAC.so" rm -f "./libcsnd.so" csound-6.10.0/cmake/000077500000000000000000000000001321653344700141615ustar00rootroot00000000000000csound-6.10.0/cmake/CheckAtomic.cmake000066400000000000000000000005421321653344700173360ustar00rootroot00000000000000 include(CheckCSourceCompiles) if(USE_DOUBLE) set(type "int64_t") else() set(type "int32_t") endif() check_c_source_compiles(" #include #include int main() { static volatile ${type} val = 0; ${type} u = __sync_add_and_fetch(&val, 1); if(u - 1 == 0) { return 0; } return 1; } " HAVE_ATOMIC_BUILTIN) csound-6.10.0/cmake/CompilerOptimizations.cmake000066400000000000000000000031701321653344700215300ustar00rootroot00000000000000 check_c_compiler_flag(-ftree-vectorize HAS_TREE_VECTORIZE) check_cxx_compiler_flag(-ftree-vectorize HAS_CXX_TREE_VECTORIZE) if (HAS_TREE_VECTORISE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftree-vectorize") endif() if (HAS_CXX_TREE_VECTORISE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftree-vectorize") endif() check_c_compiler_flag(-ffast-math HAS_FAST_MATH) check_cxx_compiler_flag(-ffast-math HAS_CXX_FAST_MATH) if (HAS_FAST_MATH AND NOT MINGW) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffast-math") endif() if (HAS_CXX_FAST_MATH AND NOT MINGW) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math") endif() if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") check_c_compiler_flag(-mfpmath=sse HAS_FPMATH_SSE) check_cxx_compiler_flag(-mfpmath=sse HAS_CXX_FPMATH_SSE) if (HAS_FPMATH_SSE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpmath=sse") endif() if (HAS_CXX_FPMATH_SSE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpmath=sse") endif() endif() check_c_compiler_flag(-msse2 HAS_SSE2) check_cxx_compiler_flag(-msse2 HAS_CXX_SSE2) if (HAS_SSE2 AND NOT IOS AND NOT WASM) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse2") endif() if (HAS_CXX_SSE2 AND NOT IOS AND NOT WASM) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse2") endif() check_c_compiler_flag(-fomit-frame-pointer HAS_OMIT_FRAME_POINTER) check_cxx_compiler_flag(-fomit-frame-pointer HAS_CXX_OMIT_FRAME_POINTER) if (HAS_OMIT_FRAME_POINTER) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fomit-frame-pointer") endif() if (HAS_CXX_OMIT_FRAME_POINTER) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fomit-frame-pointer") endif() csound-6.10.0/cmake/Modules/000077500000000000000000000000001321653344700155715ustar00rootroot00000000000000csound-6.10.0/cmake/Modules/FindGMM.cmake000066400000000000000000000011071321653344700200130ustar00rootroot00000000000000# Try to find the GMM library. # Once done this will define: # GMM_FOUND - System has the GMM library. # GMM_INCLUDE_DIRS - The GMM include directories. # GMM_HAS_VECTOR_OSTREAM - Wether GMM defines operator<< for std::vector find_path(GMM_INCLUDE_DIR gmm/gmm.h) set(GMM_INCLUDE_DIRS ${GMM_INCLUDE_DIR}) include(FindPackageHandleStandardArgs) # handle the QUIETLY and REQUIRED arguments and set GMM_FOUND to TRUE # if all listed variables are TRUE find_package_handle_standard_args(GMM DEFAULT_MSG GMM_INCLUDE_DIR) mark_as_advanced(GMM_INCLUDE_DIR GMM_HAS_VECTOR_OSTREAM) csound-6.10.0/cmake/Modules/FindLIBLO.cmake000066400000000000000000000014201321653344700202320ustar00rootroot00000000000000# Try to find the Liblo library. # Once done this will define: # LIBLO_FOUND - System has the OSC library. # LIBLO_INCLUDE_DIRS - The OSC include directories. # LIBLO_LIBRARIES - The libraries needed to use the OSC library. find_path(LIBLO_INCLUDE_DIR lo.h PATH_SUFFIXES lo) if(LINUX) find_library(LIBLO_LIBRARY NAMES lo) else() find_library(LIBLO_LIBRARY NAMES liblo.a lo) endif() set(LIBLO_INCLUDE_DIRS ${LIBLO_INCLUDE_DIR}) set(LIBLO_LIBRARIES ${LIBLO_LIBRARY} ) include(FindPackageHandleStandardArgs) # handle the QUIETLY and REQUIRED arguments and set LIBLO_FOUND to TRUE # if all listed variables are TRUE find_package_handle_standard_args(DEFAULT_MSG LIBLO_LIBRARY LIBLO_INCLUDE_DIR) mark_as_advanced(LIBLO_INCLUDE_DIR LIBLO_LIBRARY ) csound-6.10.0/cmake/Modules/FindLUAJIT.cmake000066400000000000000000000023001321653344700203570ustar00rootroot00000000000000# Try to find the LuaJIT library. # Once done this will define # LUAJIT_FOUND - System has LuaJIT # LUAJIT_INCLUDE_DIRS - The LuaJIT include directories # LUAJIT_LIBRARIES - The libraries needed to use LuaJIT # LUAJIT_DEFINITIONS - Compiler switches required for using LuaJIT find_package(PkgConfig) pkg_check_modules(PC_LUAJIT QUIET luajit) set(LUAJIT_DEFINITIONS ${PC_LUAJIT_CFLAGS_OTHER}) find_path(LUAJIT_INCLUDE_DIR luajit-2.0/luajit.h HINTS ${PC_LUAJIT_INCLUDEDIR} ${PC_LUAJIT_INCLUDE_DIRS} PATH_SUFFIXES luajit-2.0 ) if(WIN32) find_library(LUAJIT_LIBRARY lua51 HINTS ${PC_LUAJIT_LIBDIR} ${PC_LUAJIT_LIBRARY_DIRS} ) else() find_library(LUAJIT_LIBRARY NAMES luajit lua51 HINTS ${PC_LUAJIT_LIBDIR} ${PC_LUAJIT_LIBRARY_DIRS} ) endif() include(FindPackageHandleStandardArgs) # handle the QUIETLY and REQUIRED arguments and set LUAJIT_FOUND to TRUE # if all listed variables are TRUE find_package_handle_standard_args(LUAJIT DEFAULT_MSG LUAJIT_LIBRARY LUAJIT_INCLUDE_DIR) mark_as_advanced(LUAJIT_INCLUDE_DIR LUAJIT_LIBRARY ) set(LUAJIT_LIBRARIES ${LUAJIT_LIBRARY} ) set(LUAJIT_INCLUDE_DIRS ${LUAJIT_INCLUDE_DIR} ) csound-6.10.0/cmake/Modules/FindMUSICXML.cmake000066400000000000000000000014611321653344700206370ustar00rootroot00000000000000# Try to find the MusicXML library. # Once done this will define: # MUSICXML_FOUND - The system has the MusicXML library. # MUSICXML_INCLUDE_DIRS - The MusicXML include directories. # MUSICXML_LIBRARIES - The libraries needed to use MusicXML. find_path(MUSICXML_INCLUDE_DIR libmusicxml.h PATH_SUFFIXES libmusicxml) find_library(MUSICXML_LIBRARY NAMES libmusicxml2.dll musicxml2) set(MUSICXML_INCLUDE_DIRS ${MUSICXML_INCLUDE_DIR} ) set(MUSICXML_LIBRARIES ${MUSICXML_LIBRARY} ) include(FindPackageHandleStandardArgs) # handle the QUIETLY and REQUIRED arguments and set MUSICXML_FOUND to TRUE # if all listed variables are TRUE find_package_handle_standard_args(MUSICXML DEFAULT_MSG MUSICXML_LIBRARY MUSICXML_INCLUDE_DIR) mark_as_advanced(MUSICXML_INCLUDE_DIR MUSICXML_LIBRARY ) csound-6.10.0/cmake/Modules/FindPORTSMF.cmake000066400000000000000000000014041321653344700205250ustar00rootroot00000000000000# Try to find the PortSMF library. # Once done this will define: # PORTSMF_FOUND - The system has the PortSMF library. # PORTSMF_INCLUDE_DIRS - The PortSMF include directories. # PORTSMF_LIBRARIES - The libraries needed to use MusicXML. find_path(PORTSMF_INCLUDE_DIR allegro.h PATH_SUFFIXES portsmf) find_library(PORTSMF_LIBRARY NAMES portSMF) set(PORTSMF_INCLUDE_DIRS ${PORTSMF_INCLUDE_DIR} ) set(PORTSMF_LIBRARIES ${PORTSMF_LIBRARY} ) include(FindPackageHandleStandardArgs) # handle the QUIETLY and REQUIRED arguments and set PORTSMF_FOUND to TRUE # if all listed variables are TRUE find_package_handle_standard_args(PORTSMF DEFAULT_MSG PORTSMF_LIBRARY PORTSMF_INCLUDE_DIR) mark_as_advanced(PORTSMF_INCLUDE_DIR PORTSMF_LIBRARY ) csound-6.10.0/cmake/Modules/FindSTK.cmake000066400000000000000000000012511321653344700200340ustar00rootroot00000000000000# Try to find the STK library. # Once done this will define: # STK_FOUND - System has the STK library. # STK_INCLUDE_DIRS - The STK include directories. # STK_LIBRARIES - The libraries needed to use the STK. find_path(STK_INCLUDE_DIR Stk.h PATH_SUFFIXES stk) find_library(STK_LIBRARY NAMES stk) set(STK_INCLUDE_DIRS ${STK_INCLUDE_DIR}) set(STK_LIBRARIES ${STK_LIBRARY} ) include(FindPackageHandleStandardArgs) # handle the QUIETLY and REQUIRED arguments and set STK_FOUND to TRUE # if all listed variables are TRUE find_package_handle_standard_args(STK DEFAULT_MSG STK_LIBRARY STK_INCLUDE_DIR) mark_as_advanced(STK_INCLUDE_DIR STK_LIBRARY) csound-6.10.0/cmake/Modules/FindVSTSDK2X.cmake000066400000000000000000000013311321653344700206220ustar00rootroot00000000000000# Try to find the VSTSDK2X library. # Once done this will define: # VSTSDK2X_FOUND - The system has the VST SDK. # VSTSDK2X_DIR - The VST SDK root directory. # VSTSDK2X_INCLUDE_DIRS - The VST SDK include directories. find_path(VSTSDK2X_INCLUDE_DIR pluginterfaces/vst2.x/aeffect.h HINTS ${VST_SDK2_HOME} PATH_SUFFIXES vstsdk2.4) set(VSTSDK2X_DIR ${VSTSDK2X_INCLUDE_DIR}) set(VSTSDK2X_INCLUDE_DIRS ${VSTSDK2X_INCLUDE_DIR} ) include(FindPackageHandleStandardArgs) # handle the QUIETLY and REQUIRED arguments and set VSTSDK2X_FOUND to TRUE # if all listed variables are TRUE find_package_handle_standard_args(VSTSDK2X DEFAULT_MSG VSTSDK2X_INCLUDE_DIR) mark_as_advanced(VSTSDK2X_INCLUDE_DIR ) csound-6.10.0/cmake/cmake_uninstall.cmake.in000066400000000000000000000017631321653344700207500ustar00rootroot00000000000000if (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) string(REGEX REPLACE "\n" ";" files "${files}") list(REVERSE files) foreach (file ${files}) message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") if (EXISTS "$ENV{DESTDIR}${file}") execute_process( COMMAND @CMAKE_COMMAND@ -E remove "$ENV{DESTDIR}${file}" OUTPUT_VARIABLE rm_out RESULT_VARIABLE rm_retval ) if(NOT ${rm_retval} EQUAL 0) message(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") endif (NOT ${rm_retval} EQUAL 0) else (EXISTS "$ENV{DESTDIR}${file}") message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") endif (EXISTS "$ENV{DESTDIR}${file}") endforeach(file) csound-6.10.0/cmake/portaudio_test.c000066400000000000000000000002351321653344700173720ustar00rootroot00000000000000#include int main(int argc, char** argv) { /* Test for 1899 or greater as 1899 is used for v19-devel */ return Pa_GetVersion() >= 1899; } csound-6.10.0/config.doxygen000066400000000000000000000010121321653344700157370ustar00rootroot00000000000000PROJECT_NAME = "Csound" PROJECT_NUMBER = 6.09 OUTPUT_DIRECTORY = ./docs OUTPUT_LANGUAGE = English EXTRACT_ALL = YES EXTRACT_STATIC = YES EXTRACT_PRIVATE = NO HIDE_UNDOC_MEMBERS = YES CLASS_DIAGRAMS = YES VERBATIM_HEADERS = YES INPUT = @CMAKE_CURRENT_SOURCE_DIR@/include/csound.h EXAMPLE_PATH = @CMAKE_CURRENT_SOURCE_DIR@/examples GENERATE_HTML = YES HTML_OUTPUT = html GENERATE_LATEX = YES LATEX_OUTPUT = latex PAPER_TYPE = a4 GENERATE_MAN = YES MAN_OUTPUT = man FULL_PATH_NAMES = NO HAVE_DOT = YES DOT_NUM_THREADS = 6 csound-6.10.0/doc/000077500000000000000000000000001321653344700136465ustar00rootroot00000000000000csound-6.10.0/doc/.gitignore000066400000000000000000000000301321653344700156270ustar00rootroot00000000000000*.log *.out *.aux *.pdf csound-6.10.0/doc/Doxyfile000066400000000000000000003162071321653344700153650ustar00rootroot00000000000000# Doxyfile 1.8.11 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all text # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv # built into libc) for the transcoding. See http://www.gnu.org/software/libiconv # for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = "Csound API" # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = 6.09 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = doxygen/csound # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. # The default value is: NO. ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, # Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = NO # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = YES # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = YES # If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new # page for each member. If set to NO, the documentation of a member will be part # of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" # will allow you to use the command class in the itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, # C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: # FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: # Fortran. In the later case the parser tries to guess whether the code is fixed # or free formatted code, this is the default for Fortran type files), VHDL. For # instance to make doxygen treat .inc files as Fortran files (default is PHP), # and .f files as C (default is Fortran), use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. EXTENSION_MAPPING = YES # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or # globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # If one adds a struct or class to a group and this option is enabled, then also # any nested class or struct is added to the same group. By default this option # is disabled and one has to add nested compounds explicitly via \ingroup. # The default value is: NO. GROUP_NESTED_COMPOUNDS = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = YES # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES, all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # locally in source files will be included in the documentation. If set to NO, # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. If set to YES, local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO, only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO, these classes will be included in the various overviews. This option # has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # (class|struct|union) declarations. If set to NO, these declarations will be # included in the documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # names in lower-case letters. If set to YES, upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will # append additional text to a page's title, such as Class Reference. If set to # YES the compound reference will be hidden. # The default value is: NO. HIDE_COMPOUND_REFERENCE= NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = YES # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = YES # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo # list. This list is created by putting \todo commands in the documentation. # The default value is: YES. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test # list. This list is created by putting \test commands in the documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 24 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES, the # list will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = NO # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. See also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error (stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = YES # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO, doxygen will only warn about wrong or incomplete # parameter documentation, but not about the absence of documentation. # The default value is: NO. WARN_NO_PARAMDOC = NO # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when # a warning is encountered. # The default value is: NO. WARN_AS_ERROR = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. INPUT = include \ ../include # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: http://www.gnu.org/software/libiconv) for the list of # possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # read by doxygen. # # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, # *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, # *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl, # *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js. FILE_PATTERNS = csound.h \ csound.hpp \ csound_threaded.hpp \ csoundCore.h \ cscore.h \ csdl.h \ csdebug.h # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = AEff* \ aeff* \ AudioEff* \ audioeff* \ *wrap* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # function all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see http://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the config file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = NO #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = YES # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in # which the alphabetical index list will be split. # Minimum value: 1, maximum value: 20, default value: 5. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # cascading style sheets that are included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefore more robust against future updates. # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the # list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # http://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to YES can help to show when doxygen was last run and thus if the # documentation is up to date. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = NO # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = YES # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: http://developer.apple.com/tools/xcode/), introduced with # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler (hhc.exe). If non-empty, # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated # (YES) or that it should be included in the master .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated # (YES) or a normal table of contents (NO) in the .chm file. Furthermore it # enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- # folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location of Qt's # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = YES # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # http://www.mathjax.org) which uses client side Javascript for the rendering # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from http://www.mathjax.org before deployment. # The default value is: http://cdn.mathjax.org/mathjax/latest. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /
Opcodes
To Do
Bibliography