├── test ├── llvm-gcov.sh ├── Delay │ └── CMakeLists.txt ├── Gain │ ├── CMakeLists.txt │ └── Gain.cpp ├── Sync │ ├── CMakeLists.txt │ └── SyncTargetOutput.m ├── Var │ ├── CMakeLists.txt │ └── Var.cpp ├── Allpass │ ├── CMakeLists.txt │ └── Allpass.cpp ├── Dataspace │ ├── CMakeLists.txt │ └── Dataspace.cpp ├── Dcblocker │ ├── CMakeLists.txt │ └── Dcblocker.cpp ├── Generator │ ├── CMakeLists.txt │ └── GeneratorTargetOutput.m ├── AudioObject │ ├── CMakeLists.txt │ └── AudioObject.cpp ├── Interpolator │ ├── CMakeLists.txt │ └── InterpolatorTargetOutput.m ├── SampleBundle │ └── CMakeLists.txt ├── UnitImpulse │ ├── CMakeLists.txt │ └── UnitImpulse.cpp ├── CircularStorage │ └── CMakeLists.txt ├── LowpassFourPole │ ├── CMakeLists.txt │ ├── LowpassFourPoleIR.m │ └── LowpassFourPole.cpp ├── LowpassOnePole │ └── CMakeLists.txt ├── coverage-report.sh └── UnitTest.cmake ├── doc ├── logo.png └── logo.graffle ├── include ├── third-party │ ├── mersenne │ │ ├── Random.jpg │ │ ├── Test │ │ │ ├── Cokus │ │ │ │ └── Cokus.cpp │ │ │ ├── Original │ │ │ │ ├── Original.cpp │ │ │ │ └── mt19937ar.c │ │ │ ├── Kuenning │ │ │ │ └── Kuenning.cpp │ │ │ ├── Blevins │ │ │ │ ├── Blevins.cpp │ │ │ │ └── mt.h │ │ │ ├── Yang │ │ │ │ ├── Yang.cpp │ │ │ │ └── mtrnd.h │ │ │ ├── Bedaux │ │ │ │ ├── Bedaux.cpp │ │ │ │ ├── mtrand.cpp │ │ │ │ └── mtrand.h │ │ │ ├── Ladd │ │ │ │ ├── Ladd.cpp │ │ │ │ └── mtprng.cpp │ │ │ ├── Standard │ │ │ │ └── Standard.cpp │ │ │ └── Results.sh │ │ ├── README │ │ ├── MersenneTwister.html │ │ └── example.cpp │ └── murmur │ │ ├── main.cpp │ │ └── Murmur3.h ├── core │ ├── JamomaQueue.h │ ├── JamomaEvent.h │ ├── JamomaMessage.h │ ├── JamomaNoneDataspace.h │ ├── JamomaNotification.h │ ├── JamomaFunction.h │ ├── JamomaDataspace.h │ ├── JamomaObject.h │ ├── JamomaGainDataspace.h │ ├── JamomaUnitTest.h │ ├── JamomaLimit.h │ ├── JamomaCircularStorage.h │ ├── JamomaAudioObject.h │ └── JamomaParameter.h ├── objects │ ├── JamomaGain.h │ ├── JamomaWhiteNoise.h │ ├── JamomaUnitImpulse.h │ ├── JamomaSync.h │ ├── JamomaLowpassOnePole.h │ ├── JamomaAllpass1.h │ └── JamomaDcblock.h └── Jamoma.h ├── .gitmodules ├── src └── filtered-noise-example │ ├── CMakeLists.txt │ └── filtered-noise-example.cpp ├── .travis.yml ├── LICENSE.md ├── CMakeLists.txt ├── .gitignore └── STYLE.md /test/llvm-gcov.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | exec llvm-cov gcov "$@" 3 | 4 | -------------------------------------------------------------------------------- /doc/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamoma/jamoma2/HEAD/doc/logo.png -------------------------------------------------------------------------------- /doc/logo.graffle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamoma/jamoma2/HEAD/doc/logo.graffle -------------------------------------------------------------------------------- /include/third-party/mersenne/Random.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamoma/jamoma2/HEAD/include/third-party/mersenne/Random.jpg -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "include/third-party/concurrentqueue"] 2 | path = include/third-party/concurrentqueue 3 | url = https://github.com/cameron314/concurrentqueue.git 4 | -------------------------------------------------------------------------------- /test/Delay/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | 4 | project(Delay) 5 | 6 | include(${PROJECT_SOURCE_DIR}/../UnitTest.cmake NO_POLICY_SCOPE) 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/Gain/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | 4 | project(Gain) 5 | 6 | include(${PROJECT_SOURCE_DIR}/../UnitTest.cmake NO_POLICY_SCOPE) 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/Sync/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | 4 | project(Sync) 5 | 6 | include(${PROJECT_SOURCE_DIR}/../UnitTest.cmake NO_POLICY_SCOPE) 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/Var/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | 4 | project(Var) 5 | 6 | 7 | include(${PROJECT_SOURCE_DIR}/../UnitTest.cmake NO_POLICY_SCOPE) 8 | 9 | -------------------------------------------------------------------------------- /test/Allpass/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | 4 | project(Allpass) 5 | 6 | include(${PROJECT_SOURCE_DIR}/../UnitTest.cmake NO_POLICY_SCOPE) 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/Dataspace/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | 4 | project(Dataspace) 5 | 6 | include(${PROJECT_SOURCE_DIR}/../UnitTest.cmake NO_POLICY_SCOPE) 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/Dcblocker/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | 4 | project(Dcblocker) 5 | 6 | include(${PROJECT_SOURCE_DIR}/../UnitTest.cmake NO_POLICY_SCOPE) 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/Generator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | 4 | project(Generator) 5 | 6 | include(${PROJECT_SOURCE_DIR}/../UnitTest.cmake NO_POLICY_SCOPE) 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/AudioObject/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | 4 | project(AudioObject) 5 | 6 | include(${PROJECT_SOURCE_DIR}/../UnitTest.cmake NO_POLICY_SCOPE) 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/Interpolator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | 4 | project(Interpolator) 5 | 6 | include(${PROJECT_SOURCE_DIR}/../UnitTest.cmake NO_POLICY_SCOPE) 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/SampleBundle/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | 4 | project(SampleBundle) 5 | 6 | include(${PROJECT_SOURCE_DIR}/../UnitTest.cmake NO_POLICY_SCOPE) 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/UnitImpulse/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | 4 | project(UnitImpulse) 5 | 6 | include(${PROJECT_SOURCE_DIR}/../UnitTest.cmake NO_POLICY_SCOPE) 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/CircularStorage/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | 4 | project(CircularStorage) 5 | 6 | include(${PROJECT_SOURCE_DIR}/../UnitTest.cmake NO_POLICY_SCOPE) 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/LowpassFourPole/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | 4 | project(LowpassFourPole) 5 | 6 | include(${PROJECT_SOURCE_DIR}/../UnitTest.cmake NO_POLICY_SCOPE) 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/LowpassOnePole/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | 4 | project(LowpassOnePole) 5 | 6 | include(${PROJECT_SOURCE_DIR}/../UnitTest.cmake NO_POLICY_SCOPE) 7 | 8 | 9 | -------------------------------------------------------------------------------- /include/third-party/murmur/main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Murmur3.h" 3 | 4 | 5 | 6 | int main() 7 | { 8 | 9 | const uint32_t hash = std::integral_constant::value; 10 | 11 | 12 | std::cerr << hash << std::endl; 13 | 14 | assert(hash == 4291478129); 15 | 16 | 17 | 18 | constexpr uint32_t i = Murmur3_32("foo"); 19 | std::cerr << i << std::endl; 20 | 21 | } 22 | 23 | -------------------------------------------------------------------------------- /test/coverage-report.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$1" ]; then 4 | echo Must provide test folder name as an argument to get report for it 5 | exit 6 | fi 7 | 8 | #NAME="SampleBundle" 9 | NAME="$1" 10 | 11 | cd $NAME 12 | lcov --directory . --base-directory . --gcov-tool ../llvm-gcov.sh --capture -o cov.info 13 | lcov --remove cov.info "/usr*" -o cov.info 14 | lcov --remove cov.info "/dependencies*" -o cov.info 15 | genhtml cov.info -o build 16 | cd .. 17 | 18 | open $NAME/build/index.html -------------------------------------------------------------------------------- /include/core/JamomaQueue.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | @ingroup jamoma2 4 | 5 | @brief Core infrastructure 6 | 7 | @author Timothy Place 8 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 9 | @license This project is released under the terms of the MIT License. 10 | 11 | */ 12 | 13 | #pragma once 14 | 15 | #include "JamomaEvent.h" 16 | 17 | 18 | namespace Jamoma { 19 | 20 | 21 | using Queue = ReaderWriterQueue; 22 | using QueuePool = std::unordered_map; 23 | 24 | // TODO: global QueuePool 25 | // TODO: what about temp per-object queues -- can we fabricate ids? 26 | 27 | 28 | } // namespace Jamoma 29 | -------------------------------------------------------------------------------- /include/core/JamomaEvent.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | @ingroup jamoma2 4 | 5 | @brief Core infrastructure 6 | 7 | @author Timothy Place 8 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 9 | @license This project is released under the terms of the MIT License. 10 | */ 11 | 12 | #pragma once 13 | 14 | #include "JamomaObject.h" 15 | 16 | namespace Jamoma { 17 | 18 | 19 | /** An Event in Jamoma may be one of three types: 20 | - Message 21 | - Parameter 22 | - Notification 23 | 24 | Events represent actions taken on an object that may or may not be queued to occur asynchronously. 25 | */ 26 | class Event { 27 | public: 28 | 29 | 30 | 31 | private: 32 | Function mFunction; 33 | Synopsis mSynopsis; 34 | 35 | }; 36 | 37 | 38 | } // namespace Jamoma 39 | -------------------------------------------------------------------------------- /test/Sync/SyncTargetOutput.m: -------------------------------------------------------------------------------- 1 | % @file 2 | % @ingroup jamoma2 3 | % 4 | % @brief Generates the Expected Target Output for Sync using Octave 5 | % 6 | % @author Nathan Wolek 7 | % @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 8 | % @license This project is released under the terms of the MIT License. 9 | 10 | clear 11 | 12 | % starting values 13 | frequency = 3000.0; 14 | initialPhase = 0.4; 15 | sampleRate = 22050.0; 16 | 17 | % algorithm variables 18 | stepSize = frequency / sampleRate; 19 | currentPhase = initialPhase - stepSize; 20 | 21 | output = double (1 : 64); 22 | 23 | for i = 1:64 24 | currentPhase = currentPhase + stepSize; 25 | if (currentPhase > 1.0) 26 | currentPhase = currentPhase - 1.0; 27 | elseif (currentPhase < 0.0) 28 | currentPhase = currentPhase + 1.0; 29 | endif 30 | output(i) = currentPhase; 31 | endfor 32 | 33 | save expectedOutput.mat output -------------------------------------------------------------------------------- /test/UnitTest.cmake: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | 4 | enable_testing() 5 | 6 | 7 | SET(CMAKE_C_COMPILER clang) 8 | SET(CMAKE_CXX_COMPILER clang++) 9 | 10 | 11 | include_directories( 12 | "${PROJECT_SOURCE_DIR}/../../include" 13 | "${PROJECT_SOURCE_DIR}/../../include/core" 14 | "${PROJECT_SOURCE_DIR}/../../include/objects" 15 | 16 | "${PROJECT_SOURCE_DIR}/../../include/third-party/gtest" 17 | "${PROJECT_SOURCE_DIR}/../../include/third-party/mersenne" 18 | "${PROJECT_SOURCE_DIR}/../../include/third-party/murmur" 19 | ) 20 | 21 | 22 | set(CMAKE_CXX_FLAGS "-std=c++1y -stdlib=libc++ -fprofile-arcs -ftest-coverage") 23 | set(CMAKE_C_FLAGS "-fprofile-arcs -ftest-coverage") 24 | #set(CMAKE_LD_FLAGS "-fprofile-arcs -ftest-coverage") 25 | SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") 26 | 27 | add_executable(${PROJECT_NAME}.test ${PROJECT_NAME}.cpp) 28 | 29 | add_test(NAME ${PROJECT_NAME} 30 | COMMAND ${PROJECT_NAME}.test) 31 | -------------------------------------------------------------------------------- /src/filtered-noise-example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | 4 | project(filtered-noise-example) 5 | 6 | 7 | find_path(PORTMIDI_INCLUDES "portmidi.h") 8 | find_path(PORTAUDIO_INCLUDES "portaudio.h") 9 | 10 | include_directories( 11 | "${PROJECT_SOURCE_DIR}/../../include" 12 | "${PROJECT_SOURCE_DIR}/../../include/core" 13 | "${PROJECT_SOURCE_DIR}/../../include/objects" 14 | 15 | "${PORTMIDI_INCLUDES}" 16 | "${PORTAUDIO_INCLUDES}" 17 | ) 18 | file(GLOB_RECURSE PROJECT_HEADERS ${PROJECT_SOURCE_DIR}/../../include/Jamoma*.h) 19 | 20 | 21 | SET(CMAKE_C_COMPILER clang) 22 | SET(CMAKE_CXX_COMPILER clang++) 23 | set(CMAKE_CXX_FLAGS "-std=c++1y -stdlib=libc++") 24 | 25 | 26 | add_executable( ${PROJECT_NAME} 27 | ${PROJECT_NAME}.cpp 28 | ${PROJECT_HEADERS} 29 | ) 30 | 31 | 32 | # Link Installed Dynamic Libraries 33 | find_library(PORTMIDI_LIB "portmidi") 34 | target_link_libraries(${PROJECT_NAME} ${PORTMIDI_LIB} ${SUPPORT_LIBS}) 35 | 36 | find_library(PORTAUDIO_LIB "portaudio") 37 | target_link_libraries(${PROJECT_NAME} ${PORTAUDIO_LIB} ${SUPPORT_LIBS}) 38 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # script to build Jamoma on Travis-ci.org 2 | # see : https://travis-ci.org/jamoma/jamoma2/ 3 | 4 | # calling it objective-c, which is a lie, to trick travis into building it on a mac 5 | language: 6 | - objective-c 7 | - c++ 8 | 9 | compiler: 10 | # - gcc 11 | - clang 12 | sudo: false 13 | 14 | os: osx 15 | 16 | osx_image: xcode6.4 17 | 18 | #addons: 19 | # apt: 20 | # sources: 21 | # - llvm-toolchain-precise-3.6 22 | # - ubuntu-toolchain-r-test 23 | # packages: 24 | # - clang-3.6 25 | # - gcc-4.9 26 | # - g++-4.9 27 | 28 | before_install: 29 | - mkdir -p /tmp/cmake 30 | - wget http://www.cmake.org/files/v3.3/cmake-3.3.1-Darwin-x86_64.tar.gz 31 | - tar -xf cmake-3.3.1-Darwin-x86_64.tar.gz -C /tmp/cmake --strip-components=1 32 | - ln -s /tmp/cmake/CMake.app/Contents/bin /tmp/cmake/bin 33 | - brew install portmidi 34 | - brew install portaudio 35 | 36 | # Prepare compiler 37 | # - if [ "$CXX" = "clang++" ]; then export CXX="clang++-3.6" CC="clang-3.6"; fi 38 | # - if [ "$CXX" = "g++" ]; then export CXX="g++-4.9" CC="clang-4.9"; fi 39 | 40 | 41 | script: 42 | - "cmake ." 43 | - "make" 44 | - "make test" 45 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | project(Jamoma) 4 | 5 | ####### PREREQUISITES 6 | 7 | message(STATUS "Updating Git Submodules") 8 | execute_process( 9 | COMMAND git submodule update --init --recursive 10 | WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" 11 | ) 12 | 13 | 14 | ####### EXAMPLES 15 | 16 | add_subdirectory(src/filtered-noise-example) 17 | 18 | 19 | ####### UNIT TESTS 20 | 21 | # Macro from http://stackoverflow.com/questions/7787823/cmake-how-to-get-the-name-of-all-subdirectories-of-a-directory 22 | MACRO(SUBDIRLIST result curdir) 23 | FILE(GLOB children RELATIVE ${curdir} ${curdir}/*) 24 | SET(dirlist "") 25 | FOREACH(child ${children}) 26 | IF(IS_DIRECTORY ${curdir}/${child}) 27 | LIST(APPEND dirlist ${child}) 28 | ENDIF() 29 | ENDFOREACH() 30 | SET(${result} ${dirlist}) 31 | ENDMACRO() 32 | 33 | 34 | enable_testing() 35 | 36 | SUBDIRLIST(TESTDIRS ${CMAKE_CURRENT_SOURCE_DIR}/test) 37 | foreach(testdir ${TESTDIRS}) 38 | MESSAGE("Generating Unit Test: ${testdir}") 39 | add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/test/${testdir}) 40 | add_test(NAME ${testdir} 41 | COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test/${testdir}/${testdir}.test) 42 | endforeach() 43 | -------------------------------------------------------------------------------- /include/core/JamomaMessage.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | @ingroup jamoma2 4 | 5 | @brief Define a message to a JamomaObject 6 | 7 | @author Timothy Place 8 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 9 | @license This project is released under the terms of the MIT License. 10 | */ 11 | 12 | #pragma once 13 | 14 | #include "JamomaObject.h" 15 | 16 | namespace Jamoma { 17 | 18 | 19 | /** Define a message that can be sent to a Jamoma::Object. 20 | Any such message may also be called directly as method of the Object in C++. 21 | */ 22 | class Message { 23 | public: 24 | 25 | /** Define a Message. 26 | @param name The name of the Message when called on your Object dynamically. 27 | @param synopsis A description of what the Message does. 28 | @param fn The actual function to perform. May be a function pointer, functor, or lamba. 29 | */ 30 | Message(String name, Synopsis synopsis, Function fn) 31 | : mFunction(fn) 32 | , mSynopsis(synopsis) 33 | {} 34 | 35 | 36 | /** Execute the Message directly as a method of the C++ class. */ 37 | Error operator ()() { 38 | mFunction(); 39 | return Error::none; // TODO: what's the point of returning an error code in this case? 40 | } 41 | 42 | const Synopsis& synopsis() { 43 | return mSynopsis; 44 | } 45 | 46 | private: 47 | Function mFunction; 48 | Synopsis mSynopsis; 49 | }; 50 | 51 | 52 | } // namespace Jamoma 53 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | 30 | Makefile 31 | *.xcodeproj 32 | .DS_Store 33 | build-xcode 34 | 35 | # Debug Symbols 36 | *.dSYM 37 | 38 | # Examples 39 | examples/simple/simple 40 | 41 | # Unit Test Binaries 42 | *.test 43 | 44 | # Coverage Tools 45 | *.gcda 46 | *.gcno 47 | cov.info 48 | build 49 | 50 | # CMake Temporaries 51 | CMakeFiles 52 | CMakeScripts 53 | *.build 54 | CMakeCache.txt 55 | cmake_install.cmake 56 | CTestTestfile.cmake 57 | Testing 58 | 59 | # Doxygen builds 60 | doc/html 61 | 62 | # Explicitly Ignored by ending in -- 63 | *-- 64 | *--.* 65 | 66 | # temp/backup files from unix text editors 67 | *.txt~ 68 | *.cmake~ 69 | *.h~ 70 | *.c~ 71 | .gitignore~ 72 | 73 | # detritus from portaudio build 74 | dependencies/portaudio/bin-stamp 75 | dependencies/portaudio/bin 76 | dependencies/portaudio/config.log 77 | dependencies/portaudio/config.status 78 | dependencies/portaudio/lib-stamp 79 | dependencies/portaudio/lib 80 | dependencies/portaudio/libtool 81 | dependencies/portaudio/portaudio-2.0.pc 82 | dependencies/portaudio/src/portaudio-stamp 83 | dependencies/portaudio/tmp 84 | 85 | # Octave output files 86 | *.mat 87 | -------------------------------------------------------------------------------- /test/LowpassFourPole/LowpassFourPoleIR.m: -------------------------------------------------------------------------------- 1 | % @file 2 | % @ingroup jamoma2 3 | % 4 | % @brief Generates the ExpectedIR for LowpassFourpoleTest using Octave 5 | % 6 | % @author Nathan Wolek 7 | % @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 8 | % @license This project is released under the terms of the MIT License. 9 | 10 | clear 11 | 12 | kPi = 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068; 13 | kTwoPi = kPi * 2.0; 14 | 15 | in1 = 0.0; 16 | in2 = 0.0; 17 | in3 = 0.0; 18 | in4 = 0.0; 19 | out1 = 0.0; 20 | out2 = 0.0; 21 | out3 = 0.0; 22 | out4 = 0.0; 23 | 24 | frequency = 1000.0; 25 | sampleRate = 44100.0; 26 | tenthResonance = 1.0; 27 | 28 | % linFreq 0-1 maps to 0-half the sampling rate 29 | % radians = (5000.0 * kTwoPi) / 44100.; 30 | fNormalizedToHalfNyquist = frequency * 4.0 / sampleRate; 31 | 32 | IR = double (1 : 64); 33 | 34 | for i = 1:64 35 | 36 | if (i==1) 37 | x = 1.0; 38 | else 39 | x = 0.0; 40 | endif 41 | 42 | %% source: http://musicdsp.org/archive.php?classid=3#26 43 | f = fNormalizedToHalfNyquist * 1.4716; 44 | fb = tenthResonance * (1.0 - 0.4 * f * f); 45 | in0 = x - (out4 * fb); 46 | in0 = in0 * (0.35013 * (f*f)*(f*f)); 47 | out1 = in0 + 0.3 * in1 + (1 - f) * out1; % Pole 1 48 | in1 = in0; 49 | out2 = out1 + 0.3 * in2 + (1 - f) * out2; % Pole 2 50 | in2 = out1; 51 | out3 = out2 + 0.3 * in3 + (1 - f) * out3; % Pole 3 52 | in3 = out2; 53 | out4 = out3 + 0.3 * in4 + (1 - f) * out4; % Pole 4 54 | in4 = out3; 55 | IR(i) = out4; 56 | 57 | endfor 58 | 59 | save expectedIR.mat IR -------------------------------------------------------------------------------- /include/objects/JamomaGain.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | @ingroup jamoma2 4 | 5 | @brief Apply gain to samples. 6 | 7 | @author Timothy Place, Nathan Wolek 8 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 9 | @license This project is released under the terms of the MIT License. 10 | */ 11 | 12 | #pragma once 13 | 14 | #include "../core/JamomaAudioObject.h" 15 | 16 | 17 | namespace Jamoma { 18 | 19 | 20 | /** This AudioObject scales the values within a Sample or SampleBundle according to the current value of its gain Parameter. 21 | Gain is currently represented internally as linear gain using a double. 22 | */ 23 | class Gain : public AudioObject { 24 | public: 25 | static constexpr Classname classname = { "gain" }; 26 | static constexpr auto tags = { "dspEffectsLib", "audio", "processor", "dynamics" }; 27 | 28 | 29 | Parameter, NativeUnit::LinearGain> gain = { this, "gain", 1.0 }; ///< Linear gain to be applied to the input signal. 30 | 31 | 32 | /** Process one sample. 33 | @param x Sample to be processed. 34 | @return Processed sample 35 | */ 36 | Sample operator()(const Sample x) 37 | { 38 | return x * gain; 39 | } 40 | 41 | 42 | /** Process a SharedSampleBundleGroup. 43 | @param x SharedSampleBundleGroup to be processed. 44 | @return Processed SharedSampleBundleGroup. 45 | */ 46 | SharedSampleBundleGroup operator()(const SampleBundle& x) 47 | { 48 | auto out = adapt(x); 49 | 50 | for (int channel=0; channel 8 | #include 9 | #include "mt19937ar-cok.c" 10 | 11 | int main ( int argc, char * const argv[] ) 12 | { 13 | printf( "Testing output and speed of Cokus's Mersenne Twister program\n" ); 14 | printf( "\nTest of random integer generation:\n" ); 15 | 16 | unsigned long oneSeed = 4357UL; 17 | unsigned long bigSeed[4] = { 0x123UL, 0x234UL, 0x345UL, 0x456UL }; 18 | 19 | printf( "\nTest of random integer generation:\n" ); 20 | init_by_array( bigSeed, 4 ); 21 | unsigned long i; 22 | for( i = 0; i < 1000UL; ++i ) 23 | { 24 | printf( "%10lu ", genrand_int32() ); 25 | if( i % 5 == 4 ) printf("\n"); 26 | } 27 | 28 | printf( "\nTest of random real number [0,1) generation:\n" ); 29 | for( i = 0; i < 1000UL; ++i ) 30 | { 31 | printf( "%10.8f ", genrand_real2() ); 32 | if( i % 5 == 4 ) printf("\n"); 33 | } 34 | 35 | printf( "\nTest of random real number [0,1] generation:\n" ); 36 | init_genrand( oneSeed ); 37 | for( i = 0; i < 2000UL; ++i ) 38 | { 39 | printf( "%10.8f ", genrand_real1() ); 40 | if( i % 5 == 4 ) printf("\n"); 41 | } 42 | 43 | printf( "\nTest of time to generate one billion random integers:\n" ); 44 | init_genrand( oneSeed ); 45 | unsigned long junk = 0; 46 | clock_t start = clock(); 47 | for( i = 0; i < 1000000000UL; ++i ) 48 | { 49 | junk ^= genrand_int32(); 50 | } 51 | clock_t stop = clock(); 52 | if( junk == 0 ) printf( "jinx\n" ); 53 | printf( "Time elapsed = " ); 54 | printf( "%8.3f", double( stop - start ) / CLOCKS_PER_SEC ); 55 | printf( " s\n" ); 56 | 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /include/third-party/mersenne/Test/Original/Original.cpp: -------------------------------------------------------------------------------- 1 | // Original.cpp 2 | // Test output and speed of inventors' Mersenne Twister program 3 | // Richard J. Wagner 29 Sep 2009 4 | 5 | // This is free, unrestricted software void of any warranty. 6 | 7 | #include 8 | #include 9 | #include "mt19937ar.c" 10 | 11 | int main ( int argc, char * const argv[] ) 12 | { 13 | printf( "Testing output and speed of inventors' Mersenne Twister program\n" ); 14 | printf( "\nTest of random integer generation:\n" ); 15 | 16 | unsigned long oneSeed = 4357UL; 17 | unsigned long bigSeed[4] = { 0x123UL, 0x234UL, 0x345UL, 0x456UL }; 18 | 19 | printf( "\nTest of random integer generation:\n" ); 20 | init_by_array( bigSeed, 4 ); 21 | unsigned long i; 22 | for( i = 0; i < 1000UL; ++i ) 23 | { 24 | printf( "%10lu ", genrand_int32() ); 25 | if( i % 5 == 4 ) printf("\n"); 26 | } 27 | 28 | printf( "\nTest of random real number [0,1) generation:\n" ); 29 | for( i = 0; i < 1000UL; ++i ) 30 | { 31 | printf( "%10.8f ", genrand_real2() ); 32 | if( i % 5 == 4 ) printf("\n"); 33 | } 34 | 35 | printf( "\nTest of random real number [0,1] generation:\n" ); 36 | init_genrand( oneSeed ); 37 | for( i = 0; i < 2000UL; ++i ) 38 | { 39 | printf( "%10.8f ", genrand_real1() ); 40 | if( i % 5 == 4 ) printf("\n"); 41 | } 42 | 43 | printf( "\nTest of time to generate one billion random integers:\n" ); 44 | init_genrand( oneSeed ); 45 | unsigned long junk = 0; 46 | clock_t start = clock(); 47 | for( i = 0; i < 1000000000UL; ++i ) 48 | { 49 | junk ^= genrand_int32(); 50 | } 51 | clock_t stop = clock(); 52 | if( junk == 0 ) printf( "jinx\n" ); 53 | printf( "Time elapsed = " ); 54 | printf( "%8.3f", double( stop - start ) / CLOCKS_PER_SEC ); 55 | printf( " s\n" ); 56 | 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /include/objects/JamomaWhiteNoise.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | @ingroup jamoma2 4 | 5 | @brief Generate random samples to produce noise. 6 | 7 | @author Timothy Place, Nathan Wolek 8 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 9 | @license This project is released under the terms of the MIT License. 10 | */ 11 | 12 | #pragma once 13 | 14 | #include "../core/JamomaAudioObject.h" 15 | #include "../third-party/mersenne/MersenneTwister.h" 16 | 17 | 18 | namespace Jamoma { 19 | 20 | /** This AudioObject generates white noise by filling a Sample or SampleBundle with random values. 21 | These values are generated using the Mersenne Twister algorithm. 22 | */ 23 | class WhiteNoise : public AudioObject { 24 | 25 | MTRand mTwister; ///< Class implementing Mersenne Twister algorithm 26 | 27 | public: 28 | static constexpr Classname classname = { "noise" }; 29 | static constexpr auto tags = { "dspGeneratorLib", "audio", "generator", "noise" }; 30 | 31 | /** Process one sample. 32 | @param x Sample to be processed. 33 | @return Processed sample 34 | */ 35 | Sample operator()(Sample x) 36 | { 37 | return mTwister.rand(2.0) - 1.0; 38 | } 39 | 40 | /** Process a SharedSampleBundleGroup. 41 | @param x SharedSampleBundleGroup to be processed. 42 | @return Processed SharedSampleBundleGroup. 43 | */ 44 | SharedSampleBundleGroup operator()(const SampleBundle& x = kSampleBundleNone) 45 | { 46 | auto out = mOutput; 47 | 48 | for (int channel=0; channel < out.channelCount(); ++channel) 49 | for (auto& sample : out[0][channel]) 50 | sample = (*this)(0.0); 51 | return out; 52 | } 53 | 54 | }; 55 | 56 | } // namespace Jamoma 57 | -------------------------------------------------------------------------------- /include/core/JamomaNoneDataspace.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | @ingroup jamoma2 4 | 5 | @brief None Dataspace 6 | 7 | @author Trond Lossius, Timothy Place, Nils Peters 8 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 9 | @license This project is released under the terms of the MIT License. 10 | */ 11 | 12 | #pragma once 13 | 14 | #include "JamomaDataspace.h" 15 | 16 | 17 | namespace Jamoma { 18 | namespace Dataspace { 19 | 20 | 21 | /** Names of all units for this dataspace. 22 | */ 23 | enum class NoneUnit : uint32_t { 24 | nothing = Hash("nothing"), ///< do nothing (the neutral unit for this dataspace) 25 | }; 26 | 27 | 28 | // the neutral unit is always a pass-through 29 | // compiler inlining should make it a noop 30 | template 31 | class Nothing : public UnitBase { 32 | public: 33 | T toNeutral(const T& input) const 34 | { 35 | return input; 36 | } 37 | 38 | T fromNeutral(const T& input) const 39 | { 40 | return input; 41 | } 42 | }; 43 | 44 | 45 | /** The "None" Dataspace -- no dataspace at all. 46 | 47 | NOTE: needs to be a template because we don't want to alter data by going through doubles if it isn't a double 48 | */ 49 | template 50 | class None /*: public Dataspace*/ { 51 | public: 52 | 53 | T operator()(const T& x) 54 | { 55 | return x; 56 | } 57 | 58 | /** Conversion function where the unit is passed as enum selection. */ 59 | T operator()(const T& x, NoneUnit& unit) 60 | { 61 | return x; 62 | } 63 | 64 | 65 | /** Conversion function where the unit is passed as a string. */ 66 | T operator()(const T& x, const char* str) 67 | { 68 | return x; 69 | } 70 | 71 | // TODO: should the above be T& references to make sure we don't copy anything? 72 | 73 | }; 74 | 75 | 76 | } // namespace Dataspace 77 | } // namespace Jamoma 78 | -------------------------------------------------------------------------------- /include/third-party/mersenne/Test/Kuenning/Kuenning.cpp: -------------------------------------------------------------------------------- 1 | // Kuenning.cpp 2 | // Test output and speed of Kuenning's Mersenne Twister class 3 | // Richard J. Wagner 28 Sep 2009 4 | 5 | // This is free, unrestricted software void of any warranty. 6 | 7 | #include 8 | #include 9 | #include "mtwist.h" 10 | 11 | int main ( int argc, char * const argv[] ) 12 | { 13 | printf( "Testing output and speed of Kuenning's Mersenne Twister class\n" ); 14 | printf( "\nTest of random integer generation:\n" ); 15 | 16 | unsigned long oneSeed = 4357UL; 17 | mt_u32bit_t bigSeed[MT_STATE_SIZE] = { 0x123, 0x234, 0x345, 0x456 }; 18 | 19 | // NOTE: Kuenning's class lacks the usual seeding and generation functions 20 | 21 | printf( "\nTest of random integer generation:\n" ); 22 | mt_prng mtrand1( bigSeed ); 23 | unsigned long i; 24 | for( i = 0; i < 1000UL; ++i ) 25 | { 26 | printf( "%10lu ", mtrand1.lrand() ); 27 | if( i % 5 == 4 ) printf("\n"); 28 | } 29 | 30 | printf( "\nTest of random real number [0,1) generation:\n" ); 31 | for( i = 0; i < 1000UL; ++i ) 32 | { 33 | printf( "%10.8f ", mtrand1.drand() ); 34 | if( i % 5 == 4 ) printf("\n"); 35 | } 36 | 37 | printf( "\nTest of random real number [0,1] generation:\n" ); 38 | mt_prng mtrand2( oneSeed ); 39 | for( i = 0; i < 2000UL; ++i ) 40 | { 41 | printf( "%10.8f ", mtrand2.drand() ); 42 | if( i % 5 == 4 ) printf("\n"); 43 | } 44 | 45 | printf( "\nTest of time to generate one billion random integers:\n" ); 46 | mt_prng mtrand3( oneSeed ); 47 | unsigned long junk = 0; 48 | clock_t start = clock(); 49 | for( i = 0; i < 1000000000UL; ++i ) 50 | { 51 | junk ^= mtrand3.lrand(); 52 | } 53 | clock_t stop = clock(); 54 | if( junk == 0 ) printf( "jinx\n" ); 55 | printf( "Time elapsed = " ); 56 | printf( "%8.3f", double( stop - start ) / CLOCKS_PER_SEC ); 57 | printf( " s\n" ); 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /include/third-party/mersenne/Test/Blevins/Blevins.cpp: -------------------------------------------------------------------------------- 1 | // Blevins.cpp 2 | // Test output and speed of Blevins's Mersenne Twister class 3 | // Richard J. Wagner 28 Sep 2009 4 | 5 | // This is free, unrestricted software void of any warranty. 6 | 7 | #include 8 | #include 9 | #include "mt.h" 10 | 11 | int main ( int argc, char * const argv[] ) 12 | { 13 | printf( "Testing output and speed of Blevins's Mersenne Twister class\n" ); 14 | printf( "\nTest of random integer generation:\n" ); 15 | 16 | unsigned long oneSeed = 4357UL; 17 | unsigned long bigSeed[4] = { 0x123UL, 0x234UL, 0x345UL, 0x456UL }; 18 | 19 | printf( "\nTest of random integer generation:\n" ); 20 | MersenneTwister mtrand1; 21 | mtrand1.init_by_array( bigSeed, 4 ); 22 | unsigned long i; 23 | for( i = 0; i < 1000UL; ++i ) 24 | { 25 | printf( "%10lu ", mtrand1.genrand_int32() ); 26 | if( i % 5 == 4 ) printf("\n"); 27 | } 28 | 29 | printf( "\nTest of random real number [0,1) generation:\n" ); 30 | for( i = 0; i < 1000UL; ++i ) 31 | { 32 | printf( "%10.8f ", mtrand1.genrand_real2() ); 33 | if( i % 5 == 4 ) printf("\n"); 34 | } 35 | 36 | printf( "\nTest of random real number [0,1] generation:\n" ); 37 | mtrand1.init_genrand( oneSeed ); 38 | for( i = 0; i < 2000UL; ++i ) 39 | { 40 | printf( "%10.8f ", mtrand1.genrand_real1() ); 41 | if( i % 5 == 4 ) printf("\n"); 42 | } 43 | 44 | printf( "\nTest of time to generate one billion random integers:\n" ); 45 | MersenneTwister mtrand2; 46 | mtrand2.init_genrand( oneSeed ); 47 | unsigned long junk = 0; 48 | clock_t start = clock(); 49 | for( i = 0; i < 1000000000UL; ++i ) 50 | { 51 | junk ^= mtrand2.genrand_int32(); 52 | } 53 | clock_t stop = clock(); 54 | if( junk == 0 ) printf( "jinx\n" ); 55 | printf( "Time elapsed = " ); 56 | printf( "%8.3f", double( stop - start ) / CLOCKS_PER_SEC ); 57 | printf( " s\n" ); 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /include/third-party/mersenne/Test/Yang/Yang.cpp: -------------------------------------------------------------------------------- 1 | // Yang.cpp 2 | // Test output and speed of Yang's Mersenne Twister class 3 | // Richard J. Wagner 28 Sep 2009 4 | 5 | // This is free, unrestricted software void of any warranty. 6 | 7 | #include 8 | #include 9 | #include "mtrnd.h" 10 | 11 | using namespace MT; 12 | 13 | int main ( int argc, char * const argv[] ) 14 | { 15 | printf( "Testing output and speed of Yang's Mersenne Twister class\n" ); 16 | printf( "\nTest of random integer generation:\n" ); 17 | 18 | unsigned long oneSeed = 4357UL; 19 | unsigned long bigSeed[4] = { 0x123UL, 0x234UL, 0x345UL, 0x456UL }; 20 | 21 | printf( "\nTest of random integer generation:\n" ); 22 | MersenneTwist mtrand1; 23 | mtrand1.init_by_array( bigSeed, 4 ); 24 | unsigned long i; 25 | for( i = 0; i < 1000UL; ++i ) 26 | { 27 | printf( "%10lu ", mtrand1.genrand_int32() ); 28 | if( i % 5 == 4 ) printf("\n"); 29 | } 30 | 31 | printf( "\nTest of random real number [0,1) generation:\n" ); 32 | for( i = 0; i < 1000UL; ++i ) 33 | { 34 | printf( "%10.8f ", mtrand1.genrand_real2() ); 35 | if( i % 5 == 4 ) printf("\n"); 36 | } 37 | 38 | printf( "\nTest of random real number [0,1] generation:\n" ); 39 | mtrand1.init_genrand( oneSeed ); 40 | for( i = 0; i < 2000UL; ++i ) 41 | { 42 | printf( "%10.8f ", mtrand1.genrand_real1() ); 43 | if( i % 5 == 4 ) printf("\n"); 44 | } 45 | 46 | printf( "\nTest of time to generate one billion random integers:\n" ); 47 | MersenneTwist mtrand2; 48 | mtrand2.init_genrand( oneSeed ); 49 | unsigned long junk = 0; 50 | clock_t start = clock(); 51 | for( i = 0; i < 1000000000UL; ++i ) 52 | { 53 | junk ^= mtrand2.genrand_int32(); 54 | } 55 | clock_t stop = clock(); 56 | if( junk == 0 ) printf( "jinx\n" ); 57 | printf( "Time elapsed = " ); 58 | printf( "%8.3f", double( stop - start ) / CLOCKS_PER_SEC ); 59 | printf( " s\n" ); 60 | 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /include/third-party/mersenne/Test/Bedaux/Bedaux.cpp: -------------------------------------------------------------------------------- 1 | // Bedaux.cpp 2 | // Test output and speed of Bedaux's Mersenne Twister class 3 | // Richard J. Wagner 28 Sep 2009 4 | 5 | // This is free, unrestricted software void of any warranty. 6 | 7 | #include 8 | #include 9 | #include "mtrand.h" 10 | 11 | int main ( int argc, char * const argv[] ) 12 | { 13 | printf( "Testing output and speed of Bedaux's Mersenne Twister class\n" ); 14 | printf( "\nTest of random integer generation:\n" ); 15 | 16 | unsigned long oneSeed = 4357UL; 17 | unsigned long bigSeed[4] = { 0x123UL, 0x234UL, 0x345UL, 0x456UL }; 18 | 19 | printf( "\nTest of random integer generation:\n" ); 20 | MTRand_int32 mtrand1( bigSeed, 4 ); 21 | unsigned long i; 22 | for( i = 0; i < 1000UL; ++i ) 23 | { 24 | printf( "%10lu ", mtrand1() ); 25 | if( i % 5 == 4 ) printf("\n"); 26 | } 27 | 28 | printf( "\nTest of random real number [0,1) generation:\n" ); 29 | MTRand mtrand2( bigSeed, 4 ); 30 | for( i = 0; i < 1000UL; ++i ) 31 | mtrand2(); // advance to the proper position in the series 32 | for( i = 0; i < 1000UL; ++i ) 33 | { 34 | printf( "%10.8f ", mtrand2() ); 35 | if( i % 5 == 4 ) printf("\n"); 36 | } 37 | 38 | printf( "\nTest of random real number [0,1] generation:\n" ); 39 | MTRand_closed mtrand3( oneSeed ); 40 | for( i = 0; i < 2000UL; ++i ) 41 | { 42 | printf( "%10.8f ", mtrand3() ); 43 | if( i % 5 == 4 ) printf("\n"); 44 | } 45 | 46 | printf( "\nTest of time to generate one billion random integers:\n" ); 47 | MTRand_int32 mtrand4( oneSeed ); 48 | unsigned long junk = 0; 49 | clock_t start = clock(); 50 | for( i = 0; i < 1000000000UL; ++i ) 51 | { 52 | junk ^= mtrand4(); 53 | } 54 | clock_t stop = clock(); 55 | if( junk == 0 ) printf( "jinx\n" ); 56 | printf( "Time elapsed = " ); 57 | printf( "%8.3f", double( stop - start ) / CLOCKS_PER_SEC ); 58 | printf( " s\n" ); 59 | 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /include/objects/JamomaUnitImpulse.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | @ingroup jamoma2 4 | 5 | @brief Generate one sample at maximum amplitude for testing. 6 | 7 | @author Nathan Wolek 8 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 9 | @license This project is released under the terms of the MIT License. 10 | */ 11 | 12 | #pragma once 13 | 14 | #include "../core/JamomaAudioObject.h" 15 | 16 | 17 | namespace Jamoma { 18 | 19 | /** This AudioObject generates a unit impulse function (sometimes called Dirac function by setting the initial Sample to one and filling the remainder of the SampleBundle with zeros. 20 | This function is typically used to test the impulse response of a time-invariant filter. 21 | */ 22 | class UnitImpulse : public AudioObject { 23 | 24 | 25 | public: 26 | static constexpr Classname classname = { "unitimpulse" }; 27 | static constexpr auto tags = { "dspGeneratorLib", "audio", "generator", "impulse" }; 28 | 29 | /** Process one sample. 30 | @param x Sample to be processed. 31 | @return Processed sample 32 | */ 33 | Sample operator()(Sample x) 34 | { 35 | return 1.0; 36 | } 37 | 38 | /** Process a SharedSampleBundleGroup. 39 | @param x SharedSampleBundleGroup to be processed. 40 | @return Processed SharedSampleBundleGroup. 41 | */ 42 | SharedSampleBundleGroup operator()(const SampleBundle& x = kSampleBundleNone) 43 | { 44 | auto out = mOutput; 45 | 46 | for (int channel=0; channel < channelCount; ++channel) { 47 | out[0][channel][0] = 1.0; 48 | for (int i=1; i < x.frameCount(); ++i) 49 | out[0][channel][i] = 0.0; 50 | } 51 | return out; 52 | } 53 | }; 54 | 55 | 56 | } // namespace Jamoma 57 | -------------------------------------------------------------------------------- /include/third-party/mersenne/Test/Ladd/Ladd.cpp: -------------------------------------------------------------------------------- 1 | // Ladd.cpp 2 | // Test output and speed of Ladd's Mersenne Twister class 3 | // Richard J. Wagner 28 Sep 2009 4 | 5 | // This is free, unrestricted software void of any warranty. 6 | 7 | #include 8 | #include 9 | #include 10 | #include "mtprng.h" 11 | 12 | using namespace libcoyote; 13 | using namespace std; 14 | 15 | int main ( int argc, char * const argv[] ) 16 | { 17 | printf( "Testing output and speed of Ladd's Mersenne Twister class\n" ); 18 | printf( "\nTest of random integer generation:\n" ); 19 | 20 | unsigned long oneSeed = 4357UL; 21 | vector bigSeed; 22 | bigSeed.push_back( 0x123UL ); 23 | bigSeed.push_back( 0x234UL ); 24 | bigSeed.push_back( 0x345UL ); 25 | bigSeed.push_back( 0x456UL ); 26 | 27 | printf( "\nTest of random integer generation:\n" ); 28 | mtprng mtrand1; 29 | mtrand1.init_by_array( bigSeed ); 30 | unsigned long i; 31 | for( i = 0; i < 1000UL; ++i ) 32 | { 33 | printf( "%10lu ", mtrand1.get_rand() ); 34 | if( i % 5 == 4 ) printf("\n"); 35 | } 36 | 37 | printf( "\nTest of random real number [0,1) generation:\n" ); 38 | for( i = 0; i < 1000UL; ++i ) 39 | { 40 | printf( "%10.8f ", mtrand1.get_rand_real2() ); 41 | if( i % 5 == 4 ) printf("\n"); 42 | } 43 | 44 | printf( "\nTest of random real number [0,1] generation:\n" ); 45 | mtprng mtrand2( oneSeed ); 46 | for( i = 0; i < 2000UL; ++i ) 47 | { 48 | printf( "%10.8f ", mtrand2.get_rand_real1() ); 49 | if( i % 5 == 4 ) printf("\n"); 50 | } 51 | 52 | printf( "\nTest of time to generate one billion random integers:\n" ); 53 | mtprng mtrand3( oneSeed ); 54 | unsigned long junk = 0; 55 | clock_t start = clock(); 56 | for( i = 0; i < 1000000000UL; ++i ) 57 | { 58 | junk ^= mtrand3.get_rand(); 59 | } 60 | clock_t stop = clock(); 61 | if( junk == 0 ) printf( "jinx\n" ); 62 | printf( "Time elapsed = " ); 63 | printf( "%8.3f", double( stop - start ) / CLOCKS_PER_SEC ); 64 | printf( " s\n" ); 65 | 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /include/third-party/mersenne/Test/Blevins/mt.h: -------------------------------------------------------------------------------- 1 | /** 2 | * mt.h: Mersenne Twister header file 3 | * 4 | * Jason R. Blevins 5 | * Durham, March 7, 2007 6 | */ 7 | 8 | #ifndef METRICS_MT_H 9 | #define METRICS_MT_H 10 | 11 | /** 12 | * Mersenne Twister. 13 | * 14 | * M. Matsumoto and T. Nishimura, "Mersenne Twister: A 15 | * 623-dimensionally equidistributed uniform pseudorandom number 16 | * generator", ACM Trans. on Modeling and Computer Simulation Vol. 8, 17 | * No. 1, January pp.3-30 (1998). 18 | * 19 | * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html. 20 | */ 21 | class MersenneTwister 22 | { 23 | public: 24 | MersenneTwister(void); 25 | ~MersenneTwister(void); 26 | 27 | double random(void) { return genrand_real1(); } 28 | void print(void); 29 | 30 | void init_genrand(unsigned long s); 31 | void init_by_array(unsigned long* init_key, int key_length); 32 | 33 | unsigned long genrand_int32(void); 34 | long genrand_int31(void); 35 | double genrand_real1(void); 36 | double genrand_real2(void); 37 | double genrand_real3(void); 38 | double genrand_res53(void); 39 | 40 | private: 41 | static const int N = 624; 42 | static const int M = 397; 43 | // constant vector a 44 | static const unsigned long MATRIX_A = 0x9908b0dfUL; 45 | // most significant w-r bits 46 | static const unsigned long UPPER_MASK = 0x80000000UL; 47 | // least significant r bits 48 | static const unsigned long LOWER_MASK = 0x7fffffffUL; 49 | 50 | unsigned long* mt_; // the state vector 51 | int mti_; // mti == N+1 means mt not initialized 52 | 53 | unsigned long* init_key_; // Storage for the seed vector 54 | int key_length_; // Seed vector length 55 | unsigned long s_; // Seed integer 56 | bool seeded_by_array_; // Seeded by an array 57 | bool seeded_by_int_; // Seeded by an integer 58 | }; 59 | 60 | #endif // METRICS_MT_H 61 | -------------------------------------------------------------------------------- /include/third-party/mersenne/Test/Standard/Standard.cpp: -------------------------------------------------------------------------------- 1 | // Standard.cpp 2 | // Test output and speed of standard random number generator 3 | // Richard J. Wagner 29 Sep 2009 4 | 5 | // This is free, unrestricted software void of any warranty. 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | int main ( int argc, char * const argv[] ) 12 | { 13 | printf( "Testing output and speed of standard random number generator\n" ); 14 | printf( "\nTest of random integer generation:\n" ); 15 | 16 | unsigned long oneSeed = 4357UL; 17 | unsigned long bigSeed[4] = { 0x123UL, 0x234UL, 0x345UL, 0x456UL }; 18 | 19 | // NOTE: The standard random number generator provided with a C++ compiler 20 | // is unlikely to be the Mersenne Twister. Therefore it probably lacks the 21 | // ability to accept a big seed and will probably not match any of the 22 | // expected output. 23 | 24 | printf( "\nTest of random integer generation:\n" ); 25 | srand( bigSeed[0] ); 26 | unsigned long i; 27 | for( i = 0; i < 1000UL; ++i ) 28 | { 29 | printf( "%10i ", rand() ); 30 | if( i % 5 == 4 ) printf("\n"); 31 | } 32 | 33 | printf( "\nTest of random real number [0,1) generation:\n" ); 34 | for( i = 0; i < 1000UL; ++i ) 35 | { 36 | printf( "%10.8f ", rand() / ( RAND_MAX + 1.0 ) ); 37 | if( i % 5 == 4 ) printf("\n"); 38 | } 39 | 40 | printf( "\nTest of random real number [0,1] generation:\n" ); 41 | srand( oneSeed ); 42 | for( i = 0; i < 2000UL; ++i ) 43 | { 44 | printf( "%10.8f ", rand() / ( RAND_MAX + 0.0 ) ); 45 | if( i % 5 == 4 ) printf("\n"); 46 | } 47 | 48 | printf( "\nTest of time to generate one billion random integers:\n" ); 49 | srand( oneSeed ); 50 | unsigned long junk = 0; 51 | clock_t start = clock(); 52 | for( i = 0; i < 1000000000UL; ++i ) 53 | { 54 | junk ^= rand(); 55 | } 56 | clock_t stop = clock(); 57 | if( junk == 0 ) printf( "jinx\n" ); 58 | printf( "Time elapsed = " ); 59 | printf( "%8.3f", double( stop - start ) / CLOCKS_PER_SEC ); 60 | printf( " s\n" ); 61 | 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /test/Dataspace/Dataspace.cpp: -------------------------------------------------------------------------------- 1 | /** @file 2 | @ingroup jamoma2 3 | 4 | @brief Unit test for the Dataspace class 5 | 6 | @author Timothy Place 7 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 8 | @license This project is released under the terms of the MIT License. 9 | 10 | */ 11 | 12 | #include "Jamoma.h" 13 | 14 | namespace Jamoma { 15 | 16 | class DataspaceTest { 17 | 18 | UnitTest* mTest; 19 | 20 | public: 21 | DataspaceTest(Jamoma::UnitTest* test) 22 | : mTest(test) 23 | { 24 | testGain(); 25 | } 26 | 27 | 28 | void testGain() 29 | { 30 | // Dataspace Test 31 | double y = 0; 32 | 33 | 34 | // Gain: conversions to linear 35 | Jamoma::Dataspace::Gain linearGainConverter; 36 | 37 | y = linearGainConverter(0.5); 38 | mTest->TEST_ASSERT("unspecified unit is assumed to be the native unit (linear)", mTest->compare(y, 0.5)); 39 | 40 | y = linearGainConverter(-6, Dataspace::GainUnit::db); 41 | mTest->TEST_ASSERT("db unit specified as enum", mTest->compare(y, 0.50118723362727224)); 42 | 43 | y = linearGainConverter(-12, "db"); 44 | // TODO: test 45 | mTest->TEST_ASSERT("db unit specified as string", mTest->compare(y, 0.25118864315095796)); 46 | 47 | 48 | // Gain: conversions to db 49 | Jamoma::Dataspace::Gain dbGainConverter; 50 | 51 | y = dbGainConverter(0.5); 52 | mTest->TEST_ASSERT("unspecified unit is assumed to be the native unit (db)", mTest->compare(y, 0.5)); 53 | 54 | y = dbGainConverter(2.0, Dataspace::GainUnit::linear); 55 | mTest->TEST_ASSERT("linear-to-db", mTest->compare(y, 6.0205999132796242)); 56 | 57 | y = dbGainConverter(100.0, Dataspace::GainUnit::midi); 58 | mTest->TEST_ASSERT("midi-to-db using enum unit", mTest->compare(y, 0.0)); 59 | 60 | y = dbGainConverter(50, "midi"); 61 | mTest->TEST_ASSERT("midi-to-db using string unit", mTest->compare(y, -28.999923402717513)); 62 | 63 | } 64 | 65 | 66 | }; 67 | 68 | } // namespace Jamoma 69 | 70 | 71 | int main(int argc, const char * argv[]) 72 | { 73 | Jamoma::UnitTest aUnitTestInstance; 74 | return aUnitTestInstance.failureCount(); 75 | } 76 | -------------------------------------------------------------------------------- /include/third-party/mersenne/Test/Bedaux/mtrand.cpp: -------------------------------------------------------------------------------- 1 | // mtrand.cpp, see include file mtrand.h for information 2 | 3 | #include "mtrand.h" 4 | // non-inline function definitions and static member definitions cannot 5 | // reside in header file because of the risk of multiple declarations 6 | 7 | // initialization of static private members 8 | unsigned long MTRand_int32::state[n] = {0x0UL}; 9 | int MTRand_int32::p = 0; 10 | bool MTRand_int32::init = false; 11 | 12 | void MTRand_int32::gen_state() { // generate new state vector 13 | for (int i = 0; i < (n - m); ++i) 14 | state[i] = state[i + m] ^ twiddle(state[i], state[i + 1]); 15 | for (int i = n - m; i < (n - 1); ++i) 16 | state[i] = state[i + m - n] ^ twiddle(state[i], state[i + 1]); 17 | state[n - 1] = state[m - 1] ^ twiddle(state[n - 1], state[0]); 18 | p = 0; // reset position 19 | } 20 | 21 | void MTRand_int32::seed(unsigned long s) { // init by 32 bit seed 22 | state[0] = s & 0xFFFFFFFFUL; // for > 32 bit machines 23 | for (int i = 1; i < n; ++i) { 24 | state[i] = 1812433253UL * (state[i - 1] ^ (state[i - 1] >> 30)) + i; 25 | // see Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier 26 | // in the previous versions, MSBs of the seed affect only MSBs of the array state 27 | // 2002/01/09 modified by Makoto Matsumoto 28 | state[i] &= 0xFFFFFFFFUL; // for > 32 bit machines 29 | } 30 | p = n; // force gen_state() to be called for next random number 31 | } 32 | 33 | void MTRand_int32::seed(const unsigned long* array, int size) { // init by array 34 | seed(19650218UL); 35 | int i = 1, j = 0; 36 | for (int k = ((n > size) ? n : size); k; --k) { 37 | state[i] = (state[i] ^ ((state[i - 1] ^ (state[i - 1] >> 30)) * 1664525UL)) 38 | + array[j] + j; // non linear 39 | state[i] &= 0xFFFFFFFFUL; // for > 32 bit machines 40 | ++j; j %= size; 41 | if ((++i) == n) { state[0] = state[n - 1]; i = 1; } 42 | } 43 | for (int k = n - 1; k; --k) { 44 | state[i] = (state[i] ^ ((state[i - 1] ^ (state[i - 1] >> 30)) * 1566083941UL)) - i; 45 | state[i] &= 0xFFFFFFFFUL; // for > 32 bit machines 46 | if ((++i) == n) { state[0] = state[n - 1]; i = 1; } 47 | } 48 | state[0] = 0x80000000UL; // MSB is 1; assuring non-zero initial array 49 | p = n; // force gen_state() to be called for next random number 50 | } 51 | -------------------------------------------------------------------------------- /include/third-party/mersenne/README: -------------------------------------------------------------------------------- 1 | README for MersenneTwister.h package 2 | Richard J. Wagner v1.1 29 September 2009 3 | 4 | Instructions 5 | ------------ 6 | 7 | The only necessary file for using this Mersenne Twister random number 8 | generator is "MersenneTwister.h". The class name is MTRand. 9 | 10 | Usage examples are in "example.cpp". Linux, Unix, and Max OS X users can type 11 | "make" to compile and then type "./example" to run the example program. 12 | 13 | To test the output and compare to other random number generators type 14 | "make test". 15 | 16 | When you are done with testing, type "make clean" to get rid of temporary files. 17 | 18 | For Windows users with a compiler such as Microsoft Visual C++, simply add 19 | "example.cpp" and "MersenneTwister.h" to an empty C++ console application. 20 | Compile and run to see the generator in action. The "make" command will not 21 | work, so the test program "Test/Wagner/Wagner.cpp" must be run manually if 22 | desired. The output should contain no error messages and the lists of random 23 | numbers should exactly match those in "Test/Reference.out". 24 | 25 | If you encounter any problems, please e-mail a copy of the output and a 26 | description of the test system to me at "wagnerr@umich.edu". Any other 27 | feedback is welcome too. 28 | 29 | 30 | Installation 31 | ------------ 32 | 33 | Just copy the file "MersenneTwister.h" to your working directory or some other 34 | place where your compiler can find it. Put the following line at the top of 35 | your program to access the MTRand class: 36 | 37 | #include "MersenneTwister.h" 38 | 39 | 40 | Contents 41 | -------- 42 | 43 | README - this file 44 | MersenneTwister.h - declaration and implementation of MTRand class 45 | example.cpp - examples of using MTRand 46 | Makefile - instructions used by "make" command 47 | 48 | MersenneTwister.html - Web page about MersenneTwister.h 49 | Random.jpg - background for MersenneTwister.html 50 | 51 | Test/Makefile - instructions used by "make" command for test programs 52 | Test/Results.sh - script to examine the output from test programs 53 | Test/Reference.out - expected output from MT random number generators 54 | Test/Wagner/ - test program for MersenneTwister.h 55 | Test/*/ - test programs for other MT implementations 56 | -------------------------------------------------------------------------------- /test/Generator/GeneratorTargetOutput.m: -------------------------------------------------------------------------------- 1 | % @file 2 | % @ingroup jamoma2 3 | % 4 | % @brief Generates the Expected Target Output for Generators using Octave 5 | % 6 | % @author Nathan Wolek 7 | % @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 8 | % @license This project is released under the terms of the MIT License. 9 | 10 | clear 11 | 12 | output_ramp = double (1 : 64); 13 | output_unipolarramp = double (1 : 64); 14 | output_sine = double (1 : 64); 15 | output_unipolarsine = double (1 : 64); 16 | output_cosine = double (1 : 64); 17 | output_unipolarcosine = double (1 : 64); 18 | output_triangle = double (1 : 64); 19 | output_unipolartriangle = double (1 : 64); 20 | 21 | % the following function is adapted from the code in JamomaGenerators 22 | function retval = generate_trangle(delta) 23 | retval = 0.0; 24 | if ( delta <= 0.25 ) 25 | retval = delta / 0.25; 26 | elseif ( delta >= 0.75 ) 27 | retval = -1.0 + (delta - 0.75) / 0.25; 28 | else 29 | retval = 1.0 - (delta - 0.25) / 0.25; 30 | endif 31 | endfunction 32 | 33 | function retval = generate_unipolartrangle(delta) 34 | retval = 0.0; 35 | if ( delta <= 0.25 ) 36 | retval = delta / 0.5; 37 | elseif ( delta >= 0.75 ) 38 | retval = 1.0 + (delta - 1.5) / 0.5; 39 | else 40 | retval = -2.0 - (delta - 1.5) / 0.5; 41 | endif 42 | retval = retval + 0.5; 43 | endfunction 44 | 45 | for i = 1:64 46 | current_delta = (i - 1) / 64; 47 | output_ramp(i) = ( current_delta * 2.0 ) - 1.0; 48 | output_unipolarramp(i) = current_delta; 49 | output_sine(i) = sin (current_delta * 2.0 * pi); 50 | output_unipolarsine(i) = 0.5 + 0.5 * sin (current_delta * 2.0 * pi); 51 | output_cosine(i) = cos (current_delta * 2.0 * pi); 52 | output_unipolarcosine(i) = 0.5 + 0.5 * cos (current_delta * 2.0 * pi); 53 | output_triangle(i) = generate_trangle(current_delta); 54 | output_unipolartriangle(i) = generate_unipolartrangle(current_delta); 55 | endfor 56 | 57 | save expectedOutput.mat output_ramp 58 | save -append expectedOutput.mat output_unipolarramp 59 | save -append expectedOutput.mat output_sine 60 | save -append expectedOutput.mat output_unipolarsine 61 | save -append expectedOutput.mat output_cosine 62 | save -append expectedOutput.mat output_unipolarcosine 63 | save -append expectedOutput.mat output_triangle 64 | save -append expectedOutput.mat output_unipolartriangle 65 | -------------------------------------------------------------------------------- /include/core/JamomaNotification.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | @ingroup jamoma2 4 | 5 | @brief Define a notification from a Jamoma::Object 6 | 7 | @author Timothy Place 8 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 9 | @license This project is released under the terms of the MIT License. 10 | */ 11 | 12 | #pragma once 13 | 14 | #include "JamomaObject.h" 15 | 16 | namespace Jamoma { 17 | 18 | 19 | /** Define a notification that can be delivered by a Jamoma::Object. 20 | */ 21 | class Notification { 22 | public: 23 | 24 | /** Define a Notification. 25 | @param name The name of the Message when called on your Object dynamically. 26 | @param synopsis A description of what the Message does. 27 | @param fn The actual function to perform. May be a function pointer, functor, or lamba. 28 | */ 29 | Notification(String name, Synopsis synopsis, Function fn) 30 | : mFunction(fn) 31 | , mSynopsis(synopsis) 32 | {} 33 | 34 | 35 | /** Execute the Message directly as a method of the C++ class. */ 36 | Error operator ()() { 37 | mFunction(); 38 | return Error::none; // TODO: what's the point of returning an error code in this case? 39 | } 40 | 41 | const Synopsis& synopsis() { 42 | return mSynopsis; 43 | } 44 | 45 | private: 46 | Function mFunction; 47 | Synopsis mSynopsis; 48 | }; 49 | 50 | 51 | 52 | 53 | 54 | class Observer { 55 | public: 56 | 57 | // TODO: Do we really need this variation of the constructor? YAGNI! 58 | // Notification(String name, Function fn) 59 | // : mFunction(fn) 60 | // {} 61 | 62 | 63 | /** Define a Notification. 64 | @param name The name of the Message when called on your Object dynamically. 65 | @param synopsis A description of what the Message does. 66 | @param fn The actual function to perform. May be a function pointer, functor, or lamba. 67 | */ 68 | Observer(Function fn) 69 | : mFunction(fn) 70 | {} 71 | 72 | 73 | /** Execute the Message directly as a method of the C++ class. */ 74 | Error operator ()() { 75 | mFunction(); 76 | return Error::none; // TODO: what's the point of returning an error code in this case? 77 | } 78 | 79 | private: 80 | Function mFunction; 81 | // Synopsis mSynopsis; 82 | }; 83 | 84 | 85 | 86 | 87 | 88 | } // namespace Jamoma 89 | -------------------------------------------------------------------------------- /test/AudioObject/AudioObject.cpp: -------------------------------------------------------------------------------- 1 | /** @file 2 | @ingroup jamoma2 3 | 4 | @brief Unit test for general features of AudioObject class 5 | 6 | @author Nathan Wolek 7 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 8 | @license This project is released under the terms of the MIT License. 9 | 10 | */ 11 | 12 | #include "Jamoma.h" 13 | 14 | 15 | class AudioObjectTest { 16 | 17 | Jamoma::UnitTest* mTest; 18 | 19 | public: 20 | AudioObjectTest(Jamoma::UnitTest* test) 21 | : mTest(test) 22 | { 23 | testSampleRateLimits(); 24 | } 25 | 26 | 27 | void testSampleRateLimits() 28 | { 29 | 30 | // testing the sampleRate limits with a common generator class 31 | Jamoma::Sync s; 32 | 33 | s.sampleRate = 1000; 34 | mTest->TEST_ASSERT("setting sampleRate param within range", s.sampleRate == 1000 ); 35 | 36 | s.sampleRate = 500000; 37 | mTest->TEST_ASSERT("setting sampleRate param way above range", s.sampleRate == 96000 ); 38 | 39 | s.sampleRate = -2000; 40 | mTest->TEST_ASSERT("setting sampleRate param below range", s.sampleRate == 1 ); 41 | 42 | s.sampleRate = 96010; 43 | mTest->TEST_ASSERT("setting sampleRate param slightly above range", s.sampleRate == 96000 ); 44 | 45 | s.sampleRate = 44100; 46 | mTest->TEST_ASSERT("setting sampleRate param within range", s.sampleRate == 44100 ); 47 | 48 | 49 | // testing the sampleRate limits again with a common processing class 50 | Jamoma::Dcblock dc; 51 | 52 | dc.sampleRate = 1000; 53 | mTest->TEST_ASSERT("setting sampleRate param within range", dc.sampleRate == 1000 ); 54 | 55 | dc.sampleRate = 500000; 56 | mTest->TEST_ASSERT("setting sampleRate param way above range", dc.sampleRate == 96000 ); 57 | 58 | dc.sampleRate = -2000; 59 | mTest->TEST_ASSERT("setting sampleRate param below range", dc.sampleRate == 1 ); 60 | 61 | dc.sampleRate = 96010; 62 | mTest->TEST_ASSERT("setting sampleRate param slightly above range", dc.sampleRate == 96000 ); 63 | 64 | dc.sampleRate = 44100; 65 | mTest->TEST_ASSERT("setting sampleRate param within range", dc.sampleRate == 44100 ); 66 | 67 | 68 | } 69 | 70 | }; 71 | 72 | 73 | int main(int argc, const char * argv[]) 74 | { 75 | Jamoma::UnitTest aUnitTestInstance; 76 | return aUnitTestInstance.failureCount(); 77 | } 78 | -------------------------------------------------------------------------------- /include/core/JamomaFunction.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | @ingroup jamoma2 4 | 5 | @brief Function class and related hooks. 6 | 7 | @author Timothy Place 8 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 9 | @license This project is released under the terms of the MIT License. 10 | */ 11 | 12 | #pragma once 13 | 14 | 15 | namespace Jamoma { 16 | 17 | 18 | /** A function. */ 19 | using Function = std::function; 20 | 21 | 22 | 23 | /** Value specialization for the Function type 24 | */ 25 | template <> 26 | class Var : public VarBase { 27 | public: 28 | 29 | auto data() const noexcept { 30 | return (Function**)&mData[0]; 31 | } 32 | 33 | /** Create an uninitialized Function Value. 34 | Initializing the value at construction is preferred. 35 | */ 36 | Var() 37 | : VarBase(typeid(Function)) 38 | { 39 | // Function* data = (Function*)&mData[0]; 40 | *data() = new Function; // can't use placement new because we don't have enough memory 41 | } 42 | 43 | 44 | /** Create a Value initialized with a Function. 45 | @param initial The Function with which to initialize. 46 | */ 47 | Var(Function initial) 48 | : VarBase(typeid(Function)) 49 | { 50 | // Var::Var(); 51 | // Function** data = (Function**)&mData[0]; 52 | *data() = new Function; // can't use placement new because we don't have enough memory 53 | *this = initial; 54 | } 55 | 56 | 57 | /** Copy constructor */ 58 | Var(const Var& other) 59 | : VarBase(typeid(Function)) 60 | { 61 | // Var::Var(); 62 | // Function* data = (Function*)&mData[0]; 63 | *data() = new Function; // can't use placement new because we don't have enough memory 64 | 65 | Function f = other; 66 | *this = f; 67 | } 68 | 69 | 70 | // TODO: Move ctor 71 | 72 | 73 | /** Destructor */ 74 | virtual ~Var() 75 | { 76 | // Function* data = (Function*)&mData[0]; 77 | delete *data(); 78 | } 79 | 80 | 81 | /** Assignment operator. 82 | @param value The Function to be assigned. 83 | */ 84 | Var& operator = (const Function& value) 85 | { 86 | // Function* data = (Function*)&mData[0]; 87 | **data() = value; 88 | return *this; 89 | } 90 | 91 | 92 | /** Casting operator to fetch the Function. 93 | @return The Function. 94 | */ 95 | operator Function() const noexcept 96 | { 97 | // Function* data = (Function*)&mData[0]; 98 | 99 | return **data(); 100 | } 101 | }; 102 | 103 | 104 | } // namespace Jamoma 105 | -------------------------------------------------------------------------------- /test/Gain/Gain.cpp: -------------------------------------------------------------------------------- 1 | /** @file 2 | @ingroup jamoma2 3 | 4 | @brief Unit test for the Gain class 5 | 6 | @author Timothy Place 7 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 8 | @license This project is released under the terms of the MIT License. 9 | 10 | */ 11 | 12 | #include "Jamoma.h" 13 | 14 | namespace Jamoma { 15 | 16 | class GainTest { 17 | 18 | UnitTest* mTest; 19 | 20 | public: 21 | GainTest(Jamoma::UnitTest* test) 22 | : mTest(test) 23 | { 24 | testBasic(); 25 | testParameterSetting(); 26 | } 27 | 28 | 29 | void testBasic() 30 | { 31 | // gain -- single sample 32 | 33 | Jamoma::Gain my_gain; 34 | Jamoma::Sample x = 1.0; 35 | Jamoma::Sample y = 0.0; 36 | 37 | my_gain.gain = 0.5; 38 | y = my_gain(x); 39 | 40 | mTest->TEST_ASSERT("single sample gain", mTest->compare(y, 0.5)); 41 | 42 | 43 | // gain -- vector 44 | 45 | Jamoma::SampleBundle in_samples(2, 8); 46 | 47 | in_samples.fill(1.0); 48 | auto out_samples = my_gain(in_samples); 49 | 50 | mTest->TEST_ASSERT("vector sample gain left 0", mTest->compare(out_samples[0][0][0], 0.5)); 51 | mTest->TEST_ASSERT("vector sample gain right 0", mTest->compare(out_samples[0][1][0], 0.5)); 52 | mTest->TEST_ASSERT("vector sample gain left 1", mTest->compare(out_samples[0][0][1], 0.5)); 53 | mTest->TEST_ASSERT("vector sample gain right 2", mTest->compare(out_samples[0][1][1], 0.5)); 54 | 55 | my_gain.gain = 0.25; 56 | in_samples = out_samples; 57 | out_samples = my_gain(in_samples); 58 | 59 | mTest->TEST_ASSERT("vector b sample gain left 0", mTest->compare(out_samples[0][0][0], 0.125)); 60 | mTest->TEST_ASSERT("vector b sample gain right 0", mTest->compare(out_samples[0][1][0], 0.125)); 61 | mTest->TEST_ASSERT("vector b sample gain left 1", mTest->compare(out_samples[0][0][1], 0.125)); 62 | mTest->TEST_ASSERT("vector b sample gain right 2", mTest->compare(out_samples[0][1][1], 0.125)); 63 | } 64 | 65 | 66 | void testParameterSetting() 67 | { 68 | Jamoma::Gain g; 69 | 70 | using namespace Dataspace; 71 | using namespace std; 72 | 73 | g.gain = make_pair(0.25, Unit::linearGain); 74 | mTest->TEST_ASSERT("setting gain param linearly", mTest->compare( g(1.0), 0.25) ); 75 | 76 | g.gain = make_pair(-6.0, Unit::db); 77 | mTest->TEST_ASSERT("setting gain param in db", mTest->compare( g(1.0), 0.50118723362727224) ); 78 | 79 | g.gain = make_pair(110.0, Unit::midiGain); 80 | mTest->TEST_ASSERT("setting gain param with midi", mTest->compare( g(1.0), 1.5826306885735968) ); 81 | 82 | 83 | } 84 | }; 85 | 86 | } // namespace Jamoma 87 | 88 | 89 | int main(int argc, const char * argv[]) 90 | { 91 | Jamoma::UnitTest aUnitTestInstance; 92 | return aUnitTestInstance.failureCount(); 93 | } 94 | -------------------------------------------------------------------------------- /test/Dcblocker/Dcblocker.cpp: -------------------------------------------------------------------------------- 1 | /** @file 2 | @ingroup jamoma2 3 | 4 | @brief Unit test for the Dcblocker class 5 | 6 | @author Timothy Place, Nathan Wolek 7 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 8 | @license This project is released under the terms of the MIT License. 9 | 10 | */ 11 | 12 | #include "Jamoma.h" 13 | 14 | 15 | class DcblockTest { 16 | 17 | Jamoma::UnitTest* mTest; 18 | 19 | public: 20 | DcblockTest(Jamoma::UnitTest* test) 21 | : mTest(test) 22 | { 23 | testImpulseResponse(); 24 | } 25 | 26 | 27 | void testImpulseResponse() 28 | { 29 | Jamoma::Dcblock my_dcblock; 30 | Jamoma::UnitImpulse impulse; 31 | 32 | impulse.channelCount = 1; 33 | impulse.frameCount = 64; 34 | 35 | auto out_samples = my_dcblock( impulse() ); 36 | 37 | Jamoma::SampleVector expectedIR = generateReferenceImpulseResponse(); 38 | 39 | int badSampleCount = 0; 40 | Jamoma::Sample temp = 0.0; 41 | Jamoma::Sample tempExpected = 0.0; 42 | 43 | for (int i=0; i < expectedIR.size(); i++) { 44 | temp = out_samples[0][0][i]; 45 | tempExpected = expectedIR[i]; 46 | if ( ! mTest->compare(temp, tempExpected ) ) { 47 | badSampleCount++; 48 | mTest->log("sample %i had a difference of %.10f", i, std::fabs(temp - tempExpected)); 49 | } 50 | } 51 | 52 | mTest->TEST_ASSERT("Bad Sample Count", badSampleCount == 0); 53 | if (badSampleCount) 54 | mTest->log("the impulse response of my_dcblock has %i bad sample(s)", badSampleCount); 55 | } 56 | 57 | 58 | // Generate an impulse response from a set of coefficients 59 | // TODO: factor this out into the core as it is generally useful 60 | std::vector generateReferenceImpulseResponse() 61 | { 62 | int N = 64; // size of the impulse response 63 | Jamoma::SampleVector a = {1.0, -1.0}; // feedforward coefficients (numerator) 64 | Jamoma::SampleVector b = {1.0, -0.9997}; // feedback coefficients (denominator) 65 | Jamoma::SampleVector x(N); // input -- feedforward history 66 | Jamoma::SampleVector y(N); // output -- feedback history 67 | 68 | std::fill_n(x.begin(), N, 0.0); 69 | std::fill_n(y.begin(), N, 0.0); 70 | x[0] = 1.0; 71 | 72 | for (int n=0; n aUnitTestInstance; 101 | return aUnitTestInstance.failureCount(); 102 | } 103 | -------------------------------------------------------------------------------- /include/objects/JamomaSync.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | @ingroup jamoma2 4 | 5 | @author Timothy Place, Nathan Wolek 6 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 7 | @license This project is released under the terms of the MIT License. 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "../core/JamomaAudioObject.h" 13 | 14 | 15 | namespace Jamoma { 16 | 17 | 18 | /** This AudioObject generates a non-bandlimited sawtooth wave oscillator. 19 | This function is typically used as a control signal for phase ramping. 20 | */ 21 | class Sync : public AudioObject { 22 | double mPhase = 0.0; 23 | double mStep = 0.0; 24 | 25 | void setStep() 26 | { 27 | mStep = frequency / sampleRate; 28 | ZeroDenormal(mStep); 29 | } 30 | 31 | 32 | public: 33 | static constexpr Classname classname = { "sync" }; 34 | static constexpr auto tags = { "dspGeneratorLib", "audio", "generator", "oscillator" }; 35 | 36 | 37 | Parameter, NativeUnit::None> phase = { this, 38 | "phase", 39 | 0.0, 40 | Range(0.0, 1.0), 41 | Setter([this]{ 42 | mPhase = phase; 43 | }) 44 | }; 45 | 46 | 47 | Parameter, NativeUnit::None> frequency = { this, 48 | "frequency", 49 | 1.0, 50 | Range(sampleRate * -0.5, sampleRate * 0.5), 51 | Setter( [this]{ 52 | setStep(); 53 | } ), 54 | Synopsis("Rate at which to cycle") 55 | }; 56 | 57 | 58 | Parameter, NativeUnit::LinearGain> gain = { this, "gain", 1.0 }; ///< scaling applied to the output 59 | 60 | 61 | Parameter offset = { this, "offset", 0.0 }; ///< shift applied to the output 62 | 63 | 64 | 65 | 66 | // TODO: add offset Parameter from Jamoma1 67 | // TODO: add gain Parameter from Jamoma1 68 | 69 | 70 | /** Process one sample. 71 | @param x Sample to be processed. 72 | @return Processed sample 73 | */ 74 | Sample operator()(const Sample x) 75 | { 76 | if (mPhase > 1.0) 77 | mPhase -= 1.0; 78 | else if (mPhase < 0.0) 79 | mPhase += 1.0; 80 | 81 | Sample y = mPhase * gain + offset; 82 | 83 | mPhase += mStep; 84 | return y; 85 | } 86 | 87 | 88 | /** Process a SharedSampleBundleGroup. 89 | @param x SharedSampleBundleGroup to be processed. 90 | @return Processed SharedSampleBundleGroup. 91 | */ 92 | SharedSampleBundleGroup operator()(const SampleBundle& x = kSampleBundleNone) 93 | { 94 | auto out = mOutput; 95 | 96 | for (int channel=0; channel 21 | class UnitBase { 22 | public: 23 | virtual T toNeutral(const T& input) const = 0; 24 | virtual T fromNeutral(const T& input) const = 0; 25 | }; 26 | 27 | 28 | } // namespace Dataspace 29 | } // namespace Jamoma 30 | 31 | 32 | #include "JamomaGainDataspace.h" 33 | #include "JamomaNoneDataspace.h" 34 | #include "JamomaTimeDataspace.h" 35 | 36 | 37 | namespace Jamoma { 38 | 39 | // Convenience types for Parameter definitions 40 | namespace NativeUnit { 41 | 42 | // None 43 | template 44 | using None = Dataspace::None ; 45 | 46 | // Gain 47 | using LinearGain = Dataspace::Gain ; 48 | using DbGain = Dataspace::Gain ; 49 | using MidiGain = Dataspace::Gain ; 50 | 51 | // Time 52 | using Seconds = Dataspace::Time ; 53 | using Bark = Dataspace::Time ; 54 | using Bpm = Dataspace::Time ; 55 | using Cents = Dataspace::Time ; 56 | using Mel = Dataspace::Time ; 57 | using MidiPitch = Dataspace::Time ; 58 | using Milliseconds = Dataspace::Time ; 59 | using Fps = Dataspace::Time ; 60 | using Hz = Dataspace::Time ; 61 | using Samples = Dataspace::Time ; 62 | using Speed = Dataspace::Time ; 63 | } 64 | 65 | 66 | // Units for setting/getting parameters 67 | // TODO: it is not dry to duplicate all these -- but we need a common enum in order to have a shared interface for all Parameters 68 | enum class Unit : uint32_t { 69 | none = (uint32_t)Dataspace::NoneUnit::nothing, 70 | 71 | linearGain = (uint32_t)Dataspace::GainUnit::linear, 72 | db = (uint32_t)Dataspace::GainUnit::db, 73 | midiGain = (uint32_t)Dataspace::GainUnit::midi, 74 | 75 | seconds = (uint32_t)Dataspace::TimeUnit::seconds, 76 | s = (uint32_t)Dataspace::TimeUnit::s, 77 | bark = (uint32_t)Dataspace::TimeUnit::bark, 78 | bpm = (uint32_t)Dataspace::TimeUnit::bpm, 79 | cents = (uint32_t)Dataspace::TimeUnit::cents, 80 | mel = (uint32_t)Dataspace::TimeUnit::mel, 81 | midiPitch = (uint32_t)Dataspace::TimeUnit::midi, 82 | milliseconds = (uint32_t)Dataspace::TimeUnit::milliseconds, 83 | ms = (uint32_t)Dataspace::TimeUnit::ms, 84 | fps = (uint32_t)Dataspace::TimeUnit::fps, 85 | hertz = (uint32_t)Dataspace::TimeUnit::hertz, 86 | hz = (uint32_t)Dataspace::TimeUnit::hz, 87 | samples = (uint32_t)Dataspace::TimeUnit::samples, 88 | speed = (uint32_t)Dataspace::TimeUnit::speed 89 | }; 90 | 91 | 92 | } // namespace Jamoma 93 | 94 | -------------------------------------------------------------------------------- /test/UnitImpulse/UnitImpulse.cpp: -------------------------------------------------------------------------------- 1 | /** @file 2 | @ingroup jamoma2 3 | 4 | @brief Unit test for the UnitImpulse class 5 | 6 | @author Timothy Place, Nathan Wolek 7 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 8 | @license This project is released under the terms of the MIT License. 9 | 10 | */ 11 | 12 | #include "Jamoma.h" 13 | 14 | 15 | class UnitImpulseTest { 16 | 17 | Jamoma::UnitTest* mTest; 18 | 19 | public: 20 | UnitImpulseTest(Jamoma::UnitTest* test) 21 | : mTest(test) 22 | { 23 | testImpulseResponse(); 24 | testImpulseResponseStereo(); 25 | } 26 | 27 | 28 | void testImpulseResponse() 29 | { 30 | Jamoma::UnitImpulse my_impulse; 31 | 32 | my_impulse.channelCount = 1; 33 | my_impulse.frameCount = 64; 34 | 35 | auto output = my_impulse(); 36 | 37 | Jamoma::SampleVector expectedImpulse = { 38 | 1.0, 39 | 0.0, 40 | 0.0, 41 | 0.0, 42 | 0.0, 43 | 0.0, 44 | 0.0, 45 | 0.0, 46 | 0.0, 47 | 0.0, 48 | 0.0, 49 | 0.0, 50 | 0.0, 51 | 0.0, 52 | 0.0, 53 | 0.0, 54 | 0.0, 55 | 0.0, 56 | 0.0, 57 | 0.0, 58 | 0.0, 59 | 0.0, 60 | 0.0, 61 | 0.0, 62 | 0.0, 63 | 0.0, 64 | 0.0, 65 | 0.0, 66 | 0.0, 67 | 0.0, 68 | 0.0, 69 | 0.0, 70 | 0.0, 71 | 0.0, 72 | 0.0, 73 | 0.0, 74 | 0.0, 75 | 0.0, 76 | 0.0, 77 | 0.0, 78 | 0.0, 79 | 0.0, 80 | 0.0, 81 | 0.0, 82 | 0.0, 83 | 0.0, 84 | 0.0, 85 | 0.0, 86 | 0.0, 87 | 0.0, 88 | 0.0, 89 | 0.0, 90 | 0.0, 91 | 0.0, 92 | 0.0, 93 | 0.0, 94 | 0.0, 95 | 0.0, 96 | 0.0, 97 | 0.0, 98 | 0.0, 99 | 0.0, 100 | 0.0, 101 | 0.0 102 | }; 103 | 104 | int badSampleCount = 0; 105 | 106 | for (int i = 0; i < expectedImpulse.size(); i++) { 107 | if (expectedImpulse[i] != output[0][0][i]) { 108 | badSampleCount++; 109 | std::cout << "sample " << i << " expected " << expectedImpulse[i] << " but instead was " << output[0][0][i] << std::endl; 110 | } 111 | } 112 | 113 | std::cout << "unit impulse has " << badSampleCount << " bad samples" << std::endl; 114 | mTest->TEST_ASSERT("Bad Sample Count", badSampleCount == 0); 115 | } 116 | 117 | 118 | 119 | void testImpulseResponseStereo() 120 | { 121 | Jamoma::UnitImpulse my_impulse; 122 | 123 | my_impulse.channelCount = 2; 124 | my_impulse.frameCount = 8; 125 | 126 | auto output = my_impulse(); 127 | 128 | Jamoma::SampleVector expectedImpulse = { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; 129 | 130 | int badSampleCount = 0; 131 | 132 | for (int i = 0; i < expectedImpulse.size(); i++) { 133 | if (expectedImpulse[i] != output[0][0][i]) { 134 | badSampleCount++; 135 | std::cout << "left sample " << i << " expected " << expectedImpulse[i] << " but instead was " << output[0][0][i] << std::endl; 136 | } 137 | if (expectedImpulse[i] != output[0][1][i]) { 138 | badSampleCount++; 139 | std::cout << "right sample " << i << " expected " << expectedImpulse[i] << " but instead was " << output[0][1][i] << std::endl; 140 | } 141 | } 142 | 143 | std::cout << "unit impulse has " << badSampleCount << " bad samples" << std::endl; 144 | mTest->TEST_ASSERT("Bad Sample Count", badSampleCount == 0); 145 | } 146 | 147 | }; 148 | 149 | 150 | int main(int argc, const char * argv[]) 151 | { 152 | Jamoma::UnitTest aUnitTestInstance; 153 | return aUnitTestInstance.failureCount(); 154 | } 155 | -------------------------------------------------------------------------------- /include/objects/JamomaLowpassOnePole.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | @ingroup jamoma2 4 | 5 | @brief Apply a first-order low-pass filter to samples. 6 | 7 | @author Timothy Place, Nathan Wolek 8 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 9 | @license This project is released under the terms of the MIT License. 10 | */ 11 | 12 | #pragma once 13 | 14 | #include "../core/JamomaAudioObject.h" 15 | 16 | namespace Jamoma { 17 | 18 | /** This AudioObject applies a basic low-pass filter to a Sample or SampleBundle. 19 | Handy for use in smoothing control signals or damping high frequency components. 20 | */ 21 | class LowpassOnePole : public AudioObject { 22 | 23 | AdaptingSampleBundle mY1 = {this}; ///< previous output sample (for each channel) 24 | double mA0; ///< gain coefficient 25 | double mB1; ///< feedback coefficient 26 | 27 | public: 28 | static constexpr Classname classname = { "lowpass.1" }; 29 | static constexpr auto tags = { "dspEffectsLib", "audio", "processor", "filter", "lowpass" }; 30 | 31 | 32 | /** Filter coefficient. */ 33 | Parameter, NativeUnit::None> coefficient = { this, 34 | "coefficient", 35 | 0.5, 36 | Range(0.0, 1.0), 37 | Setter([this]{ 38 | mA0 = coefficient; 39 | mB1 = 1 - coefficient; 40 | }) 41 | }; 42 | 43 | 44 | /** Set filter coefficient using a cutoff frequency. 45 | @see http://musicdsp.org/showArchiveComment.php?ArchiveID=237 46 | */ 47 | Parameter, NativeUnit::Hz> frequency = { this, "frequency", 1000.0, 48 | Setter([this]{coefficient = 1.0 - exp(-2.0 * 3.1415 * frequency / sampleRate);}) 49 | }; 50 | 51 | 52 | /** This algorithm is an IIR filter, meaning that it relies on feedback. If the filter should 53 | not be producing any signal (such as turning audio off and then back on in a host) or if the 54 | feedback has become corrupted (such as might happen if a NaN is fed in) then it may be 55 | neccesary to clear the filter by calling this method. 56 | */ 57 | Message clear = { "clear", 58 | Synopsis("Reset the Filter History"), 59 | [this]{ 60 | mY1.fill(0.0); 61 | } 62 | }; 63 | 64 | 65 | Sample operator()(Sample x) 66 | { 67 | return (*this)(x,0); 68 | } 69 | 70 | 71 | Sample operator()(Sample x, int channel) 72 | { 73 | Sample y = (x * mA0) + (mY1[channel][0] * mB1); // compute next output sample 74 | 75 | ZeroDenormal(y); 76 | mY1[channel][0] = y; // update history 77 | return y; 78 | } 79 | 80 | 81 | SharedSampleBundleGroup operator()(const SampleBundle& x) 82 | { 83 | auto out = adapt(x); 84 | 85 | for (int channel=0; channel < x.channelCount(); ++channel) { 86 | for (int i=0; i < x.frameCount(); ++i) 87 | out[0][channel][i] = (*this)(x[channel][i], channel); 88 | } 89 | 90 | return out; 91 | } 92 | 93 | }; 94 | 95 | 96 | } // namespace Jamoma 97 | -------------------------------------------------------------------------------- /include/core/JamomaObject.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | @ingroup jamoma2 4 | 5 | @brief Create Jamoma Object instances. 6 | 7 | @details Parent class for all Objects within the Jamoma library. 8 | Defines common features such as Parameters and Messages that are used by all Objects throughout the codebase. 9 | 10 | @author Timothy Place, Nathan Wolek 11 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 12 | @license This project is released under the terms of the MIT License. 13 | 14 | */ 15 | 16 | #pragma once 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "JamomaDataspace.h" 28 | 29 | 30 | namespace Jamoma { 31 | 32 | 33 | 34 | /** Defines the bounds of a Parameter. 35 | The low-bound comes first, then the high-bound. 36 | */ 37 | template 38 | using Range = std::pair; 39 | 40 | 41 | /** The behavior of a Parameter when the suggested Range is exceeded. */ 42 | // enum class RangeLimit : uint32_t { 43 | // none = Hash("none"), ///< Don't do anything. 44 | // clip = Hash("clip"), ///< Limit to the min and max values defined by the Range. 45 | // wrap = Hash("wrap"), ///< Wrap back around to the low/high value if the Range is exceeded. 46 | // fold = Hash("fold") ///< Mirror the value back down into the defined Range. 47 | // }; 48 | 49 | 50 | /** Custom code to be executed when parameters are set. */ 51 | using Setter = Function; 52 | 53 | 54 | class ParameterBase; // forward-declartion needed by Object 55 | 56 | 57 | /** The base class for all first-class objects in Jamoma. 58 | Such classes maybe used with traditional C++ compile-time linking or addressed dynamically my sending messages. 59 | */ 60 | class Object { 61 | template friend class Parameter; 62 | 63 | // we really just care that we have a pointer, not about the type of the attribute 64 | // attributes can be raw pointers because they are only accessed and owned by our class 65 | // TODO: perhaps these should still be done using STL "smart raw" pointers? 66 | // TODO: index should be the return type of the Hash function instead of a String? -- then we would lose all of the names... 67 | using ParameterMap = std::unordered_map; 68 | 69 | // Internal: a mapping of parameter names to the parameters themselves. 70 | ParameterMap parameters; 71 | 72 | public: 73 | /** Theoretically: constructor for users of an object that is created by dynamic lookup, e.g. 74 | @code 75 | Jamoma::Object filter("lowpass.4"); 76 | @endcode 77 | 78 | TODO: implement 79 | */ 80 | Object(String name) 81 | {} 82 | 83 | 84 | /** Inherited constructor for users of an object that is created statically/directly 85 | @code 86 | Jamoma::LowpassFourpole my_filter; 87 | @endcode 88 | */ 89 | Object() 90 | {} 91 | 92 | 93 | // TODO: do we also need a constexpr constructor so that objects can register and add their tags? how does that all work? 94 | 95 | 96 | /** Destructor. */ 97 | virtual ~Object() 98 | {} 99 | 100 | 101 | /** send a message to the object dynamically 102 | */ 103 | VarBase send(const String& name, const VarBase& input) 104 | { 105 | return 0; // TODO: stub 106 | } 107 | 108 | /** send a message to the object dynamically 109 | */ 110 | VarBase send(const String& name) 111 | { 112 | return 0; // TODO: stub 113 | } 114 | }; 115 | 116 | 117 | } // namespace Jamoma 118 | -------------------------------------------------------------------------------- /src/filtered-noise-example/filtered-noise-example.cpp: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | @ingroup jamoma2 4 | 5 | @brief Compiles an example program to test the jamoma2 library. 6 | 7 | @author Timothy Place, Nathan Wolek 8 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 9 | @license This project is released under the terms of the MIT License. 10 | 11 | */ 12 | 13 | #include "Jamoma.h" 14 | #include "portaudio.h" 15 | 16 | 17 | class MyGraph { 18 | public: 19 | Jamoma::WhiteNoise random; 20 | Jamoma::WhiteNoise noise; 21 | Jamoma::Dcblock dcblock; 22 | Jamoma::LowpassFourPole lowpass; 23 | Jamoma::SharedSampleBundleGroup output; 24 | 25 | 26 | MyGraph() 27 | { 28 | noise.channelCount = 2; // these should be set a queriable properties of the graph 29 | noise.frameCount = 2048; // ... so that multiple sources can simply ask the graph for this information 30 | 31 | lowpass.sampleRate = 44100; 32 | lowpass.frequency = 1000.0; 33 | lowpass.resonance = 38.0; 34 | } 35 | 36 | 37 | void process(float* out, unsigned long framesPerBuffer) 38 | { 39 | output = lowpass( dcblock( noise() ) ); // our "graph" 40 | 41 | for (int i=0; iprocess((float*)outputBuffer, framesPerBuffer); 57 | return 0; // we aren't done -- we want to run forever 58 | } 59 | 60 | 61 | void PortAudioExample() 62 | { 63 | MyGraph graph; 64 | PaStream* stream; 65 | PaError err; 66 | PaStreamParameters outputParameters; 67 | static const double SR = 44100.0; 68 | static const int FPB = 2048; // Frames per buffer 69 | 70 | err = Pa_Initialize(); 71 | if (err != paNoError) 72 | goto error; 73 | 74 | // Open a stereo PortAudio stream so we can hear the result. 75 | outputParameters.device = Pa_GetDefaultOutputDevice(); // Take the default output device. 76 | if (outputParameters.device == paNoDevice) { 77 | fprintf(stderr,"Error: No default output device.\n"); 78 | goto error; 79 | } 80 | outputParameters.channelCount = 2; 81 | outputParameters.hostApiSpecificStreamInfo = NULL; 82 | outputParameters.sampleFormat = paFloat32; 83 | outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency; 84 | 85 | err = Pa_OpenStream(&stream, 86 | NULL, // No input. 87 | &outputParameters, 88 | SR, // Sample rate. 89 | FPB, // Frames per buffer. 90 | paClipOff, // we won't output out of range samples so don't bother clipping them 91 | PortAudioExampleCallback, 92 | (void*)&graph); 93 | 94 | if (err != paNoError) 95 | goto error; 96 | 97 | err = Pa_StartStream( stream ); 98 | if (err != paNoError) 99 | goto error; 100 | 101 | // Loop until the callback returns non-zero 102 | while ( ( err = Pa_IsStreamActive( stream ) ) == 1 ) 103 | Pa_Sleep(100); 104 | 105 | if (!err) 106 | err = Pa_CloseStream(stream); 107 | error: 108 | Pa_Terminate(); 109 | } 110 | 111 | 112 | int main(int argc, const char * argv[]) 113 | { 114 | std::cout << "Hello, Noisy World!\n"; 115 | PortAudioExample(); 116 | return 0; 117 | } 118 | -------------------------------------------------------------------------------- /include/third-party/murmur/Murmur3.h: -------------------------------------------------------------------------------- 1 | /* 2 | This code comes from https://gist.github.com/mattyclarkson/5318077 3 | It is an implementation of the Murmur3 hashing algorithm: 4 | https://en.wikipedia.org/wiki/MurmurHash 5 | https://code.google.com/p/smhasher/ 6 | 7 | Distributed under the MIT License. 8 | */ 9 | 10 | #pragma once 11 | 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | constexpr size_t _StringLengthLoop(const char * const str, const size_t size) 20 | noexcept { 21 | return (str[size] == '\0') ? size : _StringLengthLoop(str, size + 1); 22 | } 23 | 24 | constexpr inline size_t _StringLength(const char * const str) noexcept { 25 | return _StringLengthLoop(str, 0); 26 | } 27 | 28 | constexpr uint32_t _Murmur3Rotate_32(const uint32_t target, 29 | const uint8_t rotation) noexcept { 30 | return (target << rotation) | (target >> (32 - rotation)); 31 | } 32 | 33 | constexpr uint32_t _Murmur3ShiftXor_32(const uint32_t hash, const size_t shift) 34 | noexcept { 35 | return hash ^ (hash >> shift); 36 | } 37 | 38 | constexpr uint32_t _Murmur3Last_32(const size_t len, const uint32_t hash) 39 | noexcept { 40 | return _Murmur3ShiftXor_32(0xc2b2ae35 * _Murmur3ShiftXor_32( 41 | 0x85ebca6b * _Murmur3ShiftXor_32( 42 | hash ^ (uint32_t)len, 16), 13), 16); 43 | } 44 | 45 | constexpr uint32_t _Murmur3Tail1_32(const char data, const size_t len, 46 | const uint32_t hash, const uint32_t constant) noexcept { 47 | return _Murmur3Last_32(len, hash ^ (0x1b873593 * _Murmur3Rotate_32( 48 | 0xcc9e2d51 * (constant ^ static_cast(data)), 15))); 49 | } 50 | 51 | constexpr uint32_t _Murmur3Tail2_32(const char data[2], const size_t len, 52 | const uint32_t hash, const uint32_t constant) noexcept { 53 | return _Murmur3Tail1_32(data[0], len, hash, 54 | constant ^ (static_cast(data[1]) << 8)); 55 | } 56 | 57 | constexpr uint32_t _Murmur3Tail3_32(const char data[3], const size_t len, 58 | const uint32_t hash) noexcept { 59 | return _Murmur3Tail2_32(data, len, hash, 60 | 0 ^ (static_cast(data[2]) << 16)); 61 | } 62 | 63 | constexpr uint32_t _Murmur3Rest_32(const char *const data, 64 | const size_t len, const uint32_t hash) noexcept { 65 | return ((len & 3) == 3) ? _Murmur3Tail3_32(&data[len - 3], len, hash) : 66 | ((len & 3) == 2) ? _Murmur3Tail2_32(&data[len - 2], len, hash, 0) : 67 | ((len & 3) == 1) ? _Murmur3Tail1_32(data[len - 1], len, hash, 0) : 68 | _Murmur3Last_32(len, hash); 69 | } 70 | 71 | constexpr inline uint32_t _Murmur3Load_32(const char *const data, 72 | const size_t i) noexcept { 73 | return static_cast(data[(i * sizeof(uint32_t)) + 3]) << 24 | 74 | static_cast(data[(i * sizeof(uint32_t)) + 2]) << 16 | 75 | static_cast(data[(i * sizeof(uint32_t)) + 1]) << 8 | 76 | static_cast(data[(i * sizeof(uint32_t)) + 0]) << 0; 77 | } 78 | 79 | constexpr inline uint32_t _Murmur3Update_32(const uint32_t hash, 80 | const uint32_t update) noexcept { 81 | return 0xe6546b64 + (5 * _Murmur3Rotate_32(hash ^ ( 82 | 0x1b873593 * _Murmur3Rotate_32(0xcc9e2d51 * update, 15)), 13)); 83 | } 84 | 85 | constexpr uint32_t _Murmur3Loop_32(const char *const data, 86 | const size_t len, const uint32_t hash, const size_t i = 0) noexcept { 87 | return (i < (len / 4)) ? 88 | _Murmur3Loop_32(data, len, 89 | _Murmur3Update_32(hash, _Murmur3Load_32(data, i)), i + 1) : 90 | _Murmur3Rest_32(data, len, hash); 91 | } 92 | 93 | constexpr inline uint32_t Murmur3_32(const char *const key, const size_t length, 94 | const uint32_t seed) noexcept { 95 | return _Murmur3Loop_32(key, length, seed); 96 | } 97 | 98 | constexpr inline uint32_t Murmur3_32(const char *const str, 99 | const uint32_t seed = 0xAED123FD) noexcept { 100 | return Murmur3_32(str, _StringLength(str), seed); 101 | } 102 | 103 | 104 | -------------------------------------------------------------------------------- /test/Allpass/Allpass.cpp: -------------------------------------------------------------------------------- 1 | /** @file 2 | @ingroup jamoma2 3 | 4 | @brief Unit test for the Allpass class 5 | 6 | @author Timothy Place 7 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 8 | @license This project is released under the terms of the MIT License. 9 | 10 | */ 11 | 12 | #include "Jamoma.h" 13 | 14 | 15 | class AllpassTest { 16 | 17 | Jamoma::UnitTest* mTest; 18 | 19 | public: 20 | AllpassTest(Jamoma::UnitTest* test) 21 | : mTest(test) 22 | { 23 | testImpulseResponse(); 24 | } 25 | 26 | 27 | void testImpulseResponse() 28 | { 29 | Jamoma::UnitImpulse impulse; 30 | impulse.channelCount = 1; 31 | impulse.frameCount = 64; 32 | 33 | Jamoma::Allpass1 allpass; 34 | allpass.sampleRate = 44100; 35 | allpass.delay = 1; 36 | allpass.gain = 0.5; 37 | 38 | auto out_samples = allpass( impulse() ); 39 | 40 | // coefficients calculated in Octave 41 | // a = [0.5, 1.0]; % numerator (fir) 42 | // b = [1.0, 0.5]; % denominator (iir) 43 | // i = impz(a, b, 64); 44 | Jamoma::SampleVector expectedIR = { 45 | 0.500000000000000 , 46 | 0.750000000000000 , 47 | -0.375000000000000 , 48 | 0.187500000000000 , 49 | -0.0937500000000000 , 50 | 0.0468750000000000 , 51 | -0.0234375000000000 , 52 | 0.0117187500000000 , 53 | -0.00585937500000000 , 54 | 0.00292968750000000 , 55 | -0.00146484375000000 , 56 | 0.000732421875000000 , 57 | -0.000366210937500000, 58 | 0.000183105468750000 , 59 | -9.15527343750000e-05, 60 | 4.57763671875000e-05 , 61 | -2.28881835937500e-05, 62 | 1.14440917968750e-05 , 63 | -5.72204589843750e-06, 64 | 2.86102294921875e-06 , 65 | -1.43051147460938e-06, 66 | 7.15255737304688e-07 , 67 | -3.57627868652344e-07, 68 | 1.78813934326172e-07 , 69 | -8.94069671630859e-08, 70 | 4.47034835815430e-08 , 71 | -2.23517417907715e-08, 72 | 1.11758708953857e-08 , 73 | -5.58793544769287e-09, 74 | 2.79396772384644e-09 , 75 | -1.39698386192322e-09, 76 | 6.98491930961609e-10 , 77 | -3.49245965480804e-10, 78 | 1.74622982740402e-10 , 79 | -8.73114913702011e-11, 80 | 4.36557456851006e-11 , 81 | -2.18278728425503e-11, 82 | 1.09139364212751e-11 , 83 | -5.45696821063757e-12, 84 | 2.72848410531878e-12 , 85 | -1.36424205265939e-12, 86 | 6.82121026329696e-13 , 87 | -3.41060513164848e-13, 88 | 1.70530256582424e-13 , 89 | -8.52651282912120e-14, 90 | 4.26325641456060e-14 , 91 | -2.13162820728030e-14, 92 | 1.06581410364015e-14 , 93 | -5.32907051820075e-15, 94 | 2.66453525910038e-15 , 95 | -1.33226762955019e-15, 96 | 6.66133814775094e-16 , 97 | -3.33066907387547e-16, 98 | 1.66533453693773e-16 , 99 | -8.32667268468867e-17, 100 | 4.16333634234434e-17 , 101 | -2.08166817117217e-17, 102 | 1.04083408558608e-17 , 103 | -5.20417042793042e-18, 104 | 2.60208521396521e-18 , 105 | -1.30104260698261e-18, 106 | 6.50521303491303e-19 , 107 | -3.25260651745651e-19, 108 | 1.62630325872826e-19 109 | 110 | }; 111 | 112 | Jamoma::Sample temp = 0.0; 113 | Jamoma::Sample tempExpected = 0.0; 114 | int badSampleCount = 0; 115 | 116 | for (int i=0; i < expectedIR.size(); i++) { 117 | temp = out_samples[0][0][i]; 118 | tempExpected = expectedIR[i]; 119 | 120 | // NOTE: setting comparison ULPs to 28 was done by trial and error -- roundoff accumulates signficantly due to recursive implementation 121 | if (! mTest->compare(temp, tempExpected, true, 28) ) { 122 | badSampleCount++; 123 | std::cout << "sample " << i << " had a difference of " << std::fabs(temp - tempExpected) << std::endl; 124 | } 125 | } 126 | 127 | std::cout << "the impulse response of my_comb has " << badSampleCount << " bad samples" << std::endl; 128 | mTest->TEST_ASSERT("Bad Sample Count", badSampleCount == 0); 129 | } 130 | 131 | }; 132 | 133 | 134 | int main(int argc, const char * argv[]) 135 | { 136 | Jamoma::UnitTest aUnitTestInstance; 137 | return aUnitTestInstance.failureCount(); 138 | } 139 | -------------------------------------------------------------------------------- /test/Interpolator/InterpolatorTargetOutput.m: -------------------------------------------------------------------------------- 1 | % @file 2 | % @ingroup jamoma2 3 | % 4 | % @brief Generates the Expected Target Output for Interpolators using Octave 5 | % 6 | % @author Nathan Wolek 7 | % @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 8 | % @license This project is released under the terms of the MIT License. 9 | 10 | clear 11 | 12 | % starting values 13 | x0 = -1.0; 14 | x1 = 2.0; 15 | x2 = 1.0; 16 | x3 = 4.0; 17 | x4 = 3.0; 18 | x = [x0,x1,x2,x3,x4]; 19 | 20 | output_linear = double (1 : 64); 21 | output_hermite = double (1 : 64); 22 | output_hermitegen = double (1 : 64); 23 | output_spline = double (1 : 64); 24 | output_splinegen = double (1 : 64); 25 | output_cubicgen = double (1 : 64); 26 | output_cosinegen = double (1 : 64); 27 | output_allpassgen = double (1 : 64); 28 | lastout_allpass = 0.0; 29 | 30 | % the following function is adapted from gen~.interpolation example from Max 7.1 31 | function retval = interp_hermitegen(v,delta) 32 | retval = 0.0; 33 | bias = 0.5; 34 | tension = 0.5; 35 | delta_int = fix(delta); 36 | a = delta - delta_int; 37 | w = v(delta_int-1); 38 | x = v(delta_int); 39 | y = v(delta_int+1); 40 | z = v(delta_int+2); 41 | aa = a*a; 42 | aaa = a*aa; 43 | bp = 1+bias; 44 | bm = 1-bias; 45 | mt = (1-tension)*0.5; 46 | m0 = ((x-w)*bp + (y-x)*bm) * mt; 47 | m1 = ((y-x)*bp + (z-y)*bm) * mt; 48 | a0 = 2*aaa - 3*aa + 1; 49 | a1 = aaa - 2*aa + a; 50 | a2 = aaa - aa; 51 | a3 = -2*aaa + 3*aa; 52 | retval = a0*x + a1*m0 + a2*m1 + a3*y; 53 | endfunction 54 | 55 | % the following function is adapted from gen~.interpolation example from Max 7.1 56 | function retval = interp_splinegen(v,delta) 57 | retval = 0.0; 58 | delta_int = fix(delta); 59 | a = delta - delta_int; 60 | w = v(delta_int-1); 61 | x = v(delta_int); 62 | y = v(delta_int+1); 63 | z = v(delta_int+2); 64 | a2 = a*a; 65 | f0 = -0.5*w + 1.5*x - 1.5*y + 0.5*z; 66 | f1 = w - 2.5*x + 2*y - 0.5*z; 67 | f2 = -0.5*w + 0.5*y; 68 | retval = f0*a*a2 + f1*a2 + f2*a + x; 69 | endfunction 70 | 71 | % the following function is adapted from gen~.interpolation example from Max 7.1 72 | function retval = interp_cubicgen(v,delta) 73 | retval = 0.0; 74 | delta_int = fix(delta); 75 | a = delta - delta_int; 76 | w = v(delta_int-1); 77 | x = v(delta_int); 78 | y = v(delta_int+1); 79 | z = v(delta_int+2); 80 | a2 = a*a; 81 | f0 = z - y - w + x; 82 | f1 = w - x - f0; 83 | f2 = y - w; 84 | retval = f0*a*a2 + f1*a2 + f2*a + x; 85 | endfunction 86 | 87 | % the following function is adapted from gen~.interpolation example from Max 7.1 88 | function retval = interp_cosinegen(v,delta) 89 | retval = 0.0; 90 | delta_int = fix(delta); 91 | a = delta - delta_int; 92 | x = v(delta_int); 93 | y = v(delta_int+1); 94 | a2 = 0.5*(1-cos(a*pi)); 95 | retval = x + a2*(y-x); 96 | endfunction 97 | 98 | % reference: https://ccrma.stanford.edu/~jos/pasp/First_Order_Allpass_Interpolation.html 99 | function retval = interp_allpassgen(v,delta,history) 100 | retval = 0.0; 101 | delta_int = fix(delta); 102 | a = delta - delta_int; 103 | % the following if statement corrects for a difference between deltas of 0.0 and 1.0 in this algorithm 104 | if (a == 0.0) 105 | delta_int = delta_int - 1; 106 | a = 1.0; 107 | endif 108 | x1 = v(delta_int); 109 | x2 = v(delta_int+1); 110 | out = x1 + a*(x2-history); 111 | retval = out; 112 | endfunction 113 | 114 | for i = 1:64 115 | current_delta = 2.0 + i / 64; 116 | output_linear(i) = interp1(x,current_delta); 117 | output_hermite(i) = interp1(x,current_delta,"pchip"); 118 | output_hermitegen(i) = interp_hermitegen(x,current_delta); 119 | output_spline(i) = interp1(x,current_delta,"spline"); 120 | output_splinegen(i) = interp_splinegen(x,current_delta); 121 | output_cubicgen(i) = interp_cubicgen(x,current_delta); 122 | output_cosinegen(i) = interp_cosinegen(x,current_delta); 123 | output_allpassgen(i) = interp_allpassgen(x,current_delta,lastout_allpass); 124 | lastout_allpass = output_allpassgen(i); 125 | endfor 126 | 127 | save expectedOutput.mat output_linear 128 | save -append expectedOutput.mat output_hermite 129 | save -append expectedOutput.mat output_hermitegen 130 | save -append expectedOutput.mat output_spline 131 | save -append expectedOutput.mat output_splinegen 132 | save -append expectedOutput.mat output_cubicgen 133 | save -append expectedOutput.mat output_cosinegen 134 | save -append expectedOutput.mat output_allpassgen 135 | -------------------------------------------------------------------------------- /include/core/JamomaGainDataspace.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | @ingroup jamoma2 4 | 5 | @brief Gain Dataspace 6 | 7 | @author Trond Lossius, Timothy Place, Nils Peters 8 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 9 | @license This project is released under the terms of the MIT License. 10 | */ 11 | 12 | #pragma once 13 | 14 | #include "JamomaDataspace.h" 15 | 16 | 17 | namespace Jamoma { 18 | namespace Dataspace { 19 | 20 | 21 | /** Names of all units for the gain dataspace. 22 | Implementation Note: This must be specified outside of the Gain dataspace class 23 | so that it can be used to specialize the templates for the Gain dataspace class. 24 | */ 25 | enum class GainUnit : uint32_t { 26 | linear = Hash("linear"), ///< linear gain (the neutral unit for this dataspace) 27 | midi = Hash("midi"), ///< midi gain where 100 is unity 28 | db = Hash("db") ///< decibels 29 | }; 30 | 31 | 32 | 33 | 34 | // Linear is the neutral unit, so it is a pass-through 35 | template 36 | class LinearGain : public UnitBase { 37 | public: 38 | T toNeutral(const T& input) const 39 | { 40 | return input; 41 | } 42 | 43 | T fromNeutral(const T& input) const 44 | { 45 | return input; 46 | } 47 | }; 48 | 49 | 50 | template 51 | class MidiGain : public UnitBase { 52 | public: 53 | T toNeutral(const T& input) const 54 | { 55 | return pow(input*0.01, kTTGainMidiPower); 56 | } 57 | 58 | T fromNeutral(const T& input) const 59 | { 60 | return 100.0 * pow(input, kTTGainMidiPowerInv); 61 | } 62 | }; 63 | 64 | 65 | template 66 | class DbGain : public UnitBase { 67 | public: 68 | T toNeutral(const T& input) const 69 | { 70 | return pow(10.0, input * 0.05); 71 | } 72 | 73 | T fromNeutral(const T& input) const 74 | { 75 | T temp = log10(input) * 20.0; 76 | 77 | // Output decibel range is limited to 24 bit range, avoids problems with singularities (-inf) when using dataspace in ramps 78 | if (temp < -144.49) 79 | temp = -144.49; 80 | return temp; 81 | } 82 | }; 83 | 84 | 85 | /** The Gain Dataspace. 86 | 87 | In Jamoma1 you would create a Gain Dataspace object and then it would do all possible conversions as you. 88 | In Jamoma2 we create an instance that is specialized for the "native" unit that you want to convert to/from. 89 | 90 | You then pass values to the instance along with a tag the specifies the unit. 91 | 92 | In Jamoma1 the unit was maintained as part of the state of the dataspace instance. 93 | In Jamoma2 the dataspace instance is stateless and you must specify the unit tag every time. 94 | 95 | Lots of problems stem from trying to be stateful -- remembering what the unit is when new 'naked' values come in 96 | is not always accurate when values might come pouring in from different sources simultaneously (rampers, mappers, etc). 97 | 98 | In all cases, even with specifying the unit every time, 99 | the performance of the new implementation should exceed that of the Jamoma1 implementation. 100 | TODO: perform actual benchmarks and publish the results. 101 | 102 | Cases where there are specific performance concerns we can further specialize the templates. 103 | */ 104 | template 105 | class Gain /*: public Dataspace*/ { 106 | 107 | /** Mapping from unit names to actual unit converter objects. 108 | TODO: make this a static so that we don't have to spend resources on it for all instances 109 | */ 110 | std::unordered_map*> sUnits = { 111 | {GainUnit::linear, new LinearGain()}, 112 | {GainUnit::midi, new MidiGain()}, 113 | {GainUnit::db, new DbGain()} 114 | }; 115 | 116 | 117 | /** The native unit to/from which we perform conversions. */ 118 | const UnitBase* mUnit = sUnits[U]; 119 | 120 | 121 | public: 122 | 123 | /** Conversion function where the unit is passed as enum selection. */ 124 | T operator()(const T& x, const GainUnit& unit = U) 125 | { 126 | return mUnit->fromNeutral( sUnits[unit]->toNeutral(x) ); 127 | } 128 | 129 | T operator()(const T& x, uint32_t unit) 130 | { 131 | return (*this)(x, (GainUnit)unit); 132 | } 133 | 134 | /** Conversion function where the unit is passed as a string. */ 135 | T operator()(const T x, const char* str) 136 | { 137 | return (*this)( x, (GainUnit)Hash(str) ); 138 | } 139 | 140 | }; 141 | 142 | } // namespace Dataspace 143 | } // namespace Jamoma 144 | -------------------------------------------------------------------------------- /STYLE.md: -------------------------------------------------------------------------------- 1 | # Jamoma2 Coding Guidelines 2 | 3 | The Jamoma codebase has a very strict and consistent coding style. 4 | This is important to maintain so that code contributed by many authors will be easily understood, debugged, and maintained as if it were written by a single author. 5 | 6 | These rules are largely taken from the [Juce Coding Standards](http://www.juce.com/learn/coding-standards) though there are some deviations. 7 | 8 | ## General Coding Principles 9 | 10 | * **Don't Repeat Yourself** -- Every piece of knowledge must have a single, unambiguous, authoritative representation within a system. 11 | * **Don't Use Pointers** -- Jamoma2 aims to eliminate ambiguous responsibility for resources (memory, files, etc), and error-prone idioms are discouraged. As such, using raw pointers is highly discouraged. Instead use a managed construct such as a class that contains an STL smart pointer. As a consequence, **never call `new` or `delete` or `malloc` or `free` etc...**. 12 | * **const** : Be intentional about const always. If it can be const, make it const. Even local variables. Prefer const ref arguments where practical. Don't return const temporaries. see [JUCE guidelines](http://www.juce.com/learn/coding-standards) 13 | * **use override and noexcept** : see [JUCE guidelines](http://www.juce.com/learn/coding-standards) 14 | * Give variables as localized a scope as possible 15 | * Prefer stack allocation to heap allocation 16 | * **Avoid raw loops** -- Here is a [video](https://channel9.msdn.com/Events/GoingNative/2013/Cpp-Seasoning) on the subject. 17 | 18 | ## Formatting and Whitespace 19 | 20 | * **Header Guards** -- All headers must be guarded to prevent multiple inclusion. Preferably using `#pragma once`. 21 | * **Prefer Tabs** -- Don't indent with spaces where a tab will work. 1 tab = 4 spaces. 22 | * **Braces** -- [Stroustrup Style](https://en.wikipedia.org/wiki/Indent_style#Variant:_Stroustrup) -- meaning closing braces on their own line but opening braces on the same line as the identifier for the block. There may be exceptions if it increases clarity (e.g. constructors with initializer lists) 23 | * **Hugging** -- pointer or ref designation hug the type not the var identifier, e.g. `MyType* foo = nullptr;` 24 | * **Variables** -- one per line only. Preferably initialized. (same as JUCE guidelines) 25 | * **Variables** -- blocks of variable definitions should use tabs to align the variable names. 26 | * **Commas** -- Never put a space before a comma. Always put a space after a comma. 27 | * Do not put a space before an open parenthesis 28 | * Do not write 'if' statements all-on-one-line. Except when you've got a sequence of lines containing similar if statements, and are aligning them all vertically to highlight their similarities. 29 | * Do not use braces on one-liner if-statements (unless it improves clarity, e.g. in multiple nested one-liners) 30 | * **Initialization Lists** : lists, including the leading colon, begin on a new line. Each succeeding member in the list go on a new line with a leading comma. 31 | * **Class Organization** : data members at the top (like you do for blocks in C) and then methods below. Try to minimize switching between `private`/`protected`/`public` a lot by grouping things together. Prefer to go from `private` to `public`, but this is not a hard-and-fast rule. 32 | * **Prefer preinc/predec** -- e.g. `++i` or `--i`. 33 | * Prefer a line of whitespace after variable declarations and before computation/logic. 34 | * Prefer a line of whitespace before and after one-or-more assert/static_assert statements. 35 | 36 | ## Naming Conventions 37 | 38 | * **camelCase** -- for variables and member methods. 39 | * **CamelCase** -- for types/classes as well as free-standing functions. 40 | * **Underscores** -- don't do it. Avoid underscores in your names, *especially* leading or trailing underscores. 41 | * * **Macros** -- generally avoid, but if you must, name it using ALL_CAPS_WITH_UNDERSCORES 42 | * Additional conventions: 43 | * **varName** -- local variables, or public members of a class (e.g. parameters) 44 | * **mVarName** -- members (non-public) 45 | * **kVarName** -- constants 46 | * **sVarName** -- statics (rare) 47 | * **gVarName** -- globals (exceptionally rare) 48 | * **Enums** -- use camel-case with the same capitalization that you use for a class and its member variables (enum is CamelCase, members are camelCase) 49 | 50 | 51 | ## Optional / Things to Consider 52 | 53 | JUCE suggests the following: 54 | 55 | * Constructors that take a single parameter should be default be marked 'explicit'. Obviously there are cases where you do want implicit conversion, but always think about it carefully before writing a non-explicit constructor. 56 | * Never put an "else" statement after a "return" -- The [LLVM coding standards](http://llvm.org/docs/CodingStandards.html#don-t-use-else-after-a-return) give a good explanation of this. 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /test/Var/Var.cpp: -------------------------------------------------------------------------------- 1 | /** @file 2 | @ingroup jamoma2 3 | 4 | @brief Unit test for the Var class 5 | 6 | @author Timothy Place, Nathan Wolek 7 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 8 | @license This project is released under the terms of the MIT License. 9 | 10 | */ 11 | 12 | #include "Jamoma.h" 13 | 14 | namespace Jamoma { 15 | 16 | class VarTest { 17 | 18 | UnitTest* mTest; 19 | 20 | public: 21 | VarTest(Jamoma::UnitTest* test) 22 | : mTest(test) 23 | { 24 | // Some informational posts before we get started... 25 | std::cout << "size of double: " << sizeof(double) << std::endl; 26 | std::cout << "size of TaggedValue: " << sizeof(TaggedValue) << std::endl; 27 | std::cout << "size of std::vector: " << sizeof(std::vector) << std::endl; 28 | 29 | std::vector vec16 = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; 30 | 31 | std::cout << "size of std::vector len=16: " << sizeof(vec16) << std::endl; 32 | std::cout << "size of std::string: " << sizeof(std::string) << std::endl; 33 | 34 | std::cout << "size of long long: " << sizeof(long long) << std::endl; 35 | std::cout << "size of long double: " << sizeof(long double) << std::endl; 36 | std::cout << "size of std::vector: " << sizeof(std::vector) << std::endl; 37 | 38 | std::cout << "size of Function: " << sizeof(Function) << std::endl; 39 | std::cout << "size of TimePoint: " << sizeof(TimePoint) << std::endl; 40 | 41 | // Now actually run the tests 42 | testBasic(); 43 | } 44 | 45 | 46 | void testBasic() 47 | { 48 | // Test setting and getting of a Function 49 | { 50 | // Simplest Case 51 | String s; 52 | Function f = [&s]{ s = "Hello World"; }; 53 | Var v = f; 54 | Function f1 = v; 55 | 56 | mTest->TEST_ASSERT("s is empty", s == ""); 57 | f1(); 58 | mTest->TEST_ASSERT("s is has been filled-in", s == "Hello World"); 59 | 60 | // Now test it using more generic version. 61 | VarBase& vbr = v; 62 | 63 | // this one asserts because we request an incorrect type 64 | // int i = vbr; 65 | 66 | Function f3 = vbr; 67 | 68 | s = "foo"; 69 | f3(); 70 | mTest->TEST_ASSERT("s is has been filled-in again", s == "Hello World"); 71 | } 72 | 73 | 74 | // Test Pairs (e.g. TaggedValue) 75 | { 76 | auto a = Tag(-6.0, Unit::db); 77 | Var> v = a; 78 | VarBase vb = a; 79 | TaggedValue out = v; 80 | 81 | mTest->TEST_ASSERT("TaggedValue, first item is returned correctly", mTest->compare(out.first, -6.0)); 82 | mTest->TEST_ASSERT("TaggedValue, second item is returned correctly", out.second == Unit::db); 83 | 84 | out = vb; 85 | 86 | mTest->TEST_ASSERT("TaggedValue (value assigned from value base by value), first item is returned correctly", 87 | mTest->compare(out.first, -6.0)); 88 | mTest->TEST_ASSERT("TaggedValue (value assigned from value base by value), second item is returned correctly", 89 | out.second == Unit::db); 90 | 91 | // normal copy assignment 92 | auto c = a; 93 | out = c; 94 | 95 | mTest->TEST_ASSERT("TaggedValue (value assigned from value), first item is returned correctly", 96 | mTest->compare(out.first, -6.0)); 97 | mTest->TEST_ASSERT("TaggedValue (value assigned from value), second item is returned correctly", 98 | out.second == Unit::db); 99 | 100 | // the follow asserts, as it should, because the type requested doesn't match the content 101 | // std::pair foo = vb; 102 | 103 | 104 | 105 | // TODO: passing to a parameter? 106 | 107 | 108 | } 109 | 110 | 111 | 112 | 113 | // Jamoma::Value val0; 114 | // Jamoma::Value val1 = 3.14; 115 | // Jamoma::Value val2(3.14); 116 | 117 | // val0 = 3.14; 118 | 119 | // bool equal = (val1 == val2); 120 | 121 | // mTest->TEST_ASSERT("comparison", equal); 122 | 123 | // double f1 = val1; 124 | // double f2 = val2; 125 | 126 | // if (f1 == f2) 127 | // ; 128 | 129 | 130 | /* 131 | Jamoma::Var v0; // empty -- how do we test it? 132 | 133 | 134 | Jamoma::Var v1 = {3.14}; 135 | 136 | 137 | Jamoma::Var v2(3.14); // should yield the same result as the above 138 | 139 | 140 | f1 = v1; 141 | f2 = v2; 142 | 143 | equal = (v1 == v2); 144 | 145 | 146 | mTest->TEST_ASSERT("comparison", equal); 147 | */ 148 | 149 | 150 | } 151 | }; 152 | 153 | } // namespace Jamoma 154 | 155 | 156 | int main(int argc, const char * argv[]) 157 | { 158 | Jamoma::UnitTest aUnitTestInstance; 159 | return aUnitTestInstance.failureCount(); 160 | } 161 | -------------------------------------------------------------------------------- /include/objects/JamomaAllpass1.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | @ingroup jamoma2 4 | 5 | @brief Generic IIR allpass filter 6 | 7 | @author Timothy Place, Trond Lossius 8 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 9 | @license This project is released under the terms of the MIT License. 10 | */ 11 | 12 | #pragma once 13 | 14 | #include "../core/JamomaAudioObject.h" 15 | #include "../objects/JamomaLowpassOnePole.h" 16 | 17 | namespace Jamoma { 18 | 19 | 20 | /** This AudioObject implements a generalized allpass filter. 21 | */ 22 | class Allpass1 : public AudioObject { 23 | 24 | const std::size_t mCapacity; 25 | CircularSampleBufferGroup mFeedforwardHistory; 26 | CircularSampleBufferGroup mFeedbackHistory; 27 | Observer mChannelCountObserver = { std::bind(&Allpass1::resizeHistory, this) }; 28 | 29 | void resizeHistory() { 30 | if ((mFeedbackHistory.size() && mFeedbackHistory[0].size() != size+frameCount) || mFeedbackHistory.size() != (size_t)channelCount) { 31 | mFeedforwardHistory.clear(); 32 | mFeedbackHistory.clear(); // ugly: doing this to force the reconstruction of the storage to the correct size 33 | mFeedforwardHistory.resize(channelCount, std::make_pair(mCapacity+frameCount, (size_t)size+frameCount)); 34 | mFeedbackHistory.resize(channelCount, std::make_pair(mCapacity+frameCount, (size_t)size+frameCount)); 35 | } 36 | } 37 | 38 | public: 39 | static constexpr Classname classname = { "allpass.1" }; 40 | static constexpr auto tags = { "dspFilterLib", "audio", "processor", "filter", "allpass" }; 41 | 42 | 43 | /** TODO: Make capacity dynamic? It already sort of is when the channel count changes... 44 | */ 45 | Allpass1(std::size_t capacity = 4410) 46 | : mCapacity(capacity) 47 | , mFeedforwardHistory(1, capacity) 48 | , mFeedbackHistory(1, capacity) 49 | { 50 | channelCount.addObserver(mChannelCountObserver); 51 | } 52 | 53 | 54 | /** size of the history buffers -- i.e. the delay time 55 | TODO: dataspace integration for units other than samples 56 | */ 57 | Parameter size = { this, "size", 1, 58 | Setter([this]{ 59 | for (auto& channel : mFeedforwardHistory) 60 | channel.resize((int)size); 61 | for (auto& channel : mFeedbackHistory) 62 | channel.resize((int)size); 63 | }) 64 | }; 65 | 66 | 67 | /** Delay time. 68 | An alias of the #size parameter. 69 | TODO: dataspace with Native Unit in samples 70 | */ 71 | Parameter delay = { this, "delay", 1, Setter([this] { size = (int)delay; }) }; 72 | 73 | 74 | /** Feedback coefficient. 75 | */ 76 | Parameter gain = { this, "gain", 0.0 }; 77 | 78 | 79 | /** This algorithm is an IIR filter, meaning that it relies on feedback. If the filter should 80 | not be producing any signal (such as turning audio off and then back on in a host) or if the 81 | feedback has become corrupted (such as might happen if a NaN is fed in) then it may be 82 | neccesary to clear the filter by calling this method. 83 | */ 84 | Message clear = { "clear", 85 | Synopsis("Reset the Filter History"), 86 | [this]{ 87 | for (auto& channel : mFeedforwardHistory) 88 | channel.clear(); 89 | for (auto& channel : mFeedbackHistory) 90 | channel.clear(); 91 | } 92 | }; 93 | 94 | 95 | Sample operator()(Sample x) 96 | { 97 | return (*this)(x, 0); 98 | } 99 | 100 | 101 | Sample operator()(Sample x, int channel) 102 | { 103 | Sample x1 = mFeedforwardHistory[channel].tail(-1); 104 | Sample y1 = mFeedbackHistory[channel].tail(-1); 105 | Sample alpha = gain; 106 | 107 | // Store the input in the feedforward buffer 108 | mFeedforwardHistory[channel].write(x); 109 | 110 | // Apply the filter 111 | // We start with the equation in standard form: 112 | // y = alpha * x + x1 - alpha * y1; 113 | // Then to a version that Fred Harris refers to as a "Re-Ordered All-Pass Filter Structure" in Multirate Signal Processing 114 | // y = x1 + alpha * x - alpha * y1; 115 | // Finally, here is a "Single Coefficient All-Pass Filter", dropping from 2 adds and 2 mults down to 2 adds and 1 mult 116 | Sample y = x1 + ((x - y1) * alpha); 117 | 118 | // The possibility of denormals is always lurking for IIR filters 119 | ZeroDenormal(y); 120 | 121 | // Store the output in the feedback buffer 122 | mFeedbackHistory[channel].write(y); 123 | 124 | return y; 125 | } 126 | 127 | 128 | SharedSampleBundleGroup operator()(const SampleBundle& x) 129 | { 130 | auto out = adapt(x); 131 | 132 | for (int channel=0; channel < x.channelCount(); ++channel) { 133 | for (int i=0; i < x.frameCount(); ++i) 134 | out[0][channel][i] = (*this)(x[channel][i], channel); 135 | } 136 | return out; 137 | } 138 | 139 | }; 140 | 141 | 142 | } // namespace Jamoma 143 | -------------------------------------------------------------------------------- /include/third-party/mersenne/Test/Results.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Results.sh 4 | # Examine the output from tests of Mersenne Twister random number generators 5 | # Explain the meaning in plain English 6 | 7 | rm -f Bug.txt 8 | 9 | echo 10 | 11 | echo "Examining performance of Wagner's MersenneTwister.h C++ class..." 12 | 13 | # Extract the various distribution series from each generator's output 14 | 15 | for NAME in *.out; do 16 | BASE=`basename $NAME .out` 17 | grep -A 200 "integer generation:" $NAME | tail -200 > $BASE.integer.tmp 18 | grep -A 200 -F "[0,1) generation:" $NAME | tail -200 > $BASE.exclusive.tmp 19 | grep -A 400 -F "[0,1] generation:" $NAME | tail -400 > $BASE.inclusive.tmp 20 | done 21 | 22 | # Compare the output to the inventors' reference output 23 | 24 | rm -f *.reference.tmp 25 | for NAME in *.out; do 26 | BASE=`basename $NAME .out` 27 | diff --brief $BASE.integer.tmp Reference.integer.tmp >> $BASE.reference.tmp 28 | diff --brief $BASE.exclusive.tmp Reference.exclusive.tmp >> $BASE.reference.tmp 29 | diff --brief $BASE.inclusive.tmp Reference.inclusive.tmp >> $BASE.reference.tmp 30 | done 31 | 32 | # Look for an available awk command 33 | 34 | if which awk &> /dev/null 35 | then 36 | AWK=awk 37 | elif which gawk &> /dev/null 38 | then 39 | AWK=gawk 40 | elif which nawk &> /dev/null 41 | then 42 | AWK=nawk 43 | fi 44 | 45 | # Report comparison test results 46 | 47 | if [ $AWK ]; then 48 | echo 49 | echo "Comparison of integer generation rate with other versions:" 50 | 51 | printf " This version " 52 | if [ -s Wagner.out ]; then 53 | $AWK '/Time elapsed/{ printf( "%6.1f million per second", 1000 / $4 ) }' Wagner.out 54 | if [ -s Wagner.reference.tmp ]; then 55 | printf " (non-conforming)\n" 56 | else 57 | printf "\n" 58 | fi 59 | else 60 | printf " Failed to run\n" 61 | fi 62 | 63 | printf " Inventors' version " 64 | if [ -s Original.out ]; then 65 | $AWK '/Time elapsed/{ printf( "%6.1f million per second", 1000 / $4 ) }' Original.out 66 | if [ -s Original.reference.tmp ]; then 67 | printf " (non-conforming)\n" 68 | else 69 | printf "\n" 70 | fi 71 | else 72 | printf " Failed to run\n" 73 | fi 74 | 75 | printf " Bedaux's version " 76 | if [ -s Bedaux.out ]; then 77 | $AWK '/Time elapsed/{ printf( "%6.1f million per second", 1000 / $4 ) }' Bedaux.out 78 | if [ -s Bedaux.reference.tmp ]; then 79 | printf " (non-conforming)\n" 80 | else 81 | printf "\n" 82 | fi 83 | else 84 | printf " Failed to run\n" 85 | fi 86 | 87 | printf " Blevins's version " 88 | if [ -s Blevins.out ]; then 89 | $AWK '/Time elapsed/{ printf( "%6.1f million per second", 1000 / $4 ) }' Blevins.out 90 | if [ -s Blevins.reference.tmp ]; then 91 | printf " (non-conforming)\n" 92 | else 93 | printf "\n" 94 | fi 95 | else 96 | printf " Failed to run\n" 97 | fi 98 | 99 | printf " Cokus's version " 100 | if [ -s Cokus.out ]; then 101 | $AWK '/Time elapsed/{ printf( "%6.1f million per second", 1000 / $4 ) }' Cokus.out 102 | if [ -s Cokus.reference.tmp ]; then 103 | printf " (non-conforming)\n" 104 | else 105 | printf "\n" 106 | fi 107 | else 108 | printf " Failed to run\n" 109 | fi 110 | 111 | printf " Kuenning's version " 112 | if [ -s Kuenning.out ]; then 113 | $AWK '/Time elapsed/{ printf( "%6.1f million per second", 1000 / $4 ) }' Kuenning.out 114 | if [ -s Kuenning.reference.tmp ]; then 115 | printf " (non-conforming)\n" 116 | else 117 | printf "\n" 118 | fi 119 | else 120 | printf " Failed to run\n" 121 | fi 122 | 123 | printf " Ladd's version " 124 | if [ -s Ladd.out ]; then 125 | $AWK '/Time elapsed/{ printf( "%6.1f million per second", 1000 / $4 ) }' Ladd.out 126 | if [ -s Ladd.reference.tmp ]; then 127 | printf " (non-conforming)\n" 128 | else 129 | printf "\n" 130 | fi 131 | else 132 | printf " Failed to run\n" 133 | fi 134 | 135 | printf " Yang's version " 136 | if [ -s Yang.out ]; then 137 | $AWK '/Time elapsed/{ printf( "%6.1f million per second", 1000 / $4 ) }' Yang.out 138 | if [ -s Yang.reference.tmp ]; then 139 | printf " (non-conforming)\n" 140 | else 141 | printf "\n" 142 | fi 143 | else 144 | printf " Failed to run\n" 145 | fi 146 | 147 | printf " Built-in rand() " 148 | if [ -s Standard.out ]; then 149 | $AWK '/Time elapsed/{ printf( "%6.1f million per second", 1000 / $4 ) }' Standard.out 150 | if [ -s Standard.reference.tmp ]; then 151 | printf " (non-conforming)\n" 152 | else 153 | printf "\n" 154 | fi 155 | else 156 | printf " Failed to run\n" 157 | fi 158 | fi 159 | 160 | # Report own performance test results 161 | 162 | echo 163 | 164 | grep -A 100 "Test of generation rates in various distributions:" Wagner.out 165 | 166 | # Summarize results 167 | 168 | echo 169 | 170 | grep "Error" Wagner.out >> Wagner.error.tmp 171 | 172 | if [ -s Wagner.reference.tmp ] && ![ -s Wagner.error.tmp ]; then 173 | cat Wagner.out Original.out Cokus.out > Bug.txt 174 | echo "Failed tests - MersenneTwister.h generated incorrect output" 175 | echo "Results have been written to a file called 'Bug.txt'" 176 | echo "Please send a copy of 'Bug.txt' and system info to wagnerr@umich.edu" 177 | else 178 | echo "MersenneTwister.h passed all tests" 179 | fi 180 | 181 | rm -f *.tmp 182 | 183 | exit 0 184 | -------------------------------------------------------------------------------- /include/Jamoma.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | @ingroup jamoma2 4 | 5 | @brief Jamoma.h is the starting point for the jamoma2 library. 6 | 7 | @details Jamoma.h can be used to include the entire jamoma2 library in a coding project. 8 | 9 | @author Timothy Place, Nathan Wolek 10 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 11 | @license This project is released under the terms of the MIT License. 12 | */ 13 | 14 | #pragma once 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | 25 | namespace Jamoma { 26 | 27 | using String = std::string; 28 | using Text = char[]; 29 | using Classname = Text; 30 | //using Tags = std::array; // probably make this a vector of symbols instead 31 | using TimePoint = std::chrono::high_resolution_clock::time_point; 32 | 33 | 34 | /** A brief string documenting a Function/Parameter/Message/Notification/Class/Etc. */ 35 | using Synopsis = String; 36 | 37 | 38 | enum class Error { 39 | none, 40 | generic 41 | }; 42 | 43 | 44 | /** Tag a value with some sort of marker such as a unit of measure, a label, etc. 45 | @param a The value 46 | @param tag The tag 47 | @return A pair containing both the value and the tag. 48 | */ 49 | template 50 | auto Tag(T a, U tag) { 51 | return std::make_pair(a, tag); 52 | } 53 | 54 | 55 | 56 | constexpr double kPi = 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068; 57 | constexpr double kTwoPi = kPi * 2.0; 58 | const double kTTGainMidiPower = log(pow(10.0, 10.0/20.0)) / log(127.0/100.0); 59 | const double kTTGainMidiPowerInv = 1.0/kTTGainMidiPower; 60 | 61 | 62 | 63 | 64 | 65 | /** Filter out denormaled values, which can make processing extremely slow when present. 66 | Calculation is performed in-place. 67 | Calculation is only performed if JAMOMA_SQUASH_DENORMALS is defined as a preprocessor symbol. 68 | 69 | We do this so that we can easily change the behavior of the routines for squashing denormals. 70 | * On the PPC we don't want to waste cycles unneccessarily; 71 | * On the Intel processors we can use SSE intrinsics as suggested by Nils Peters (see redmine ticket #799) 72 | * or we can use SSE intrinsics to disable denormals on a processor completely, in which case these functions should not waste cycles doing anything; 73 | * On ARM processors what happens? We might still need to squash denormals, or maybe there is an option as indicated @ http://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html 74 | 75 | Implementation Note: The __SSE3__ symbol is always defined in Xcode despite any changes you make to compiler settings 76 | On Linux, the __SSE3__ symbol is toggled based on passing the -msse3 flag to GCC 77 | On Windows, the __SSE3__ symbol is always UNdefined, despite any changes you make to compiler settings 78 | So this symbol is completely useless. 79 | 80 | When SSE3 is available, then we rely on the denormals being turned-off using a bit in the processor's control register 81 | http://software.intel.com/sites/products/documentation/studio/composer/en-us/2011/compiler_c/fpops/common/fpops_set_ftz_daz.htm 82 | 83 | For example, anything running the Max environment will be setting this bit on every thread and so we don't need to do anything at all. 84 | */ 85 | template 86 | static void ZeroDenormal(T& value) 87 | { 88 | #ifdef JAMOMA_SQUASH_DENORMALS 89 | if (!std::isnormal(value)) 90 | value = 0; 91 | #endif 92 | } 93 | 94 | 95 | 96 | } // namespace Jamoma 97 | 98 | 99 | 100 | // Dependencies 101 | 102 | //#include "readerwriterqueue.h" 103 | 104 | 105 | #include "third-party/murmur/Murmur3.h" // used for constexpr hash function 106 | 107 | /** A hash function using the Murmur3 algorithm ( https://en.wikipedia.org/wiki/MurmurHash ). 108 | This hash function is capable of being executed at compile time, 109 | meaning that the compiled binary will have a constant int value and no actually need to execute any code at runtime. 110 | @param str A c-string to be hashed into an int. 111 | @param seed An optional seed value. For most uses you should not override the default. 112 | @return An int (specifically a uint32_t) representing the hash of the string input. 113 | */ 114 | constexpr inline uint32_t Hash(const char *const str, const uint32_t seed = 0xAED123FD) noexcept 115 | { 116 | return Murmur3_32(str, _StringLength(str), seed); 117 | } 118 | 119 | 120 | // Core 121 | 122 | #include "core/JamomaGenerator.h" 123 | #include "core/JamomaLimit.h" 124 | #include "core/JamomaDataspace.h" 125 | #include "core/JamomaInterpolator.h" 126 | #include "core/JamomaVar.h" 127 | #include "core/JamomaFunction.h" 128 | 129 | #include "core/JamomaObject.h" 130 | #include "core/JamomaMessage.h" 131 | #include "core/JamomaNotification.h" 132 | #include "core/JamomaParameter.h" 133 | #include "core/JamomaAudioObject.h" 134 | #include "core/JamomaSample.h" 135 | 136 | 137 | #include "core/JamomaCircularStorage.h" 138 | #include "objects/JamomaDelay.h" 139 | #include "core/JamomaUnitTest.h" 140 | 141 | 142 | // Units 143 | 144 | #include "objects/JamomaAllpass1.h" 145 | #include "objects/JamomaDcblock.h" 146 | #include "objects/JamomaDelay.h" 147 | #include "objects/JamomaGain.h" 148 | #include "objects/JamomaLimiter.h" 149 | #include "objects/JamomaLowpassOnePole.h" 150 | #include "objects/JamomaLowpassFourPole.h" 151 | #include "objects/JamomaSync.h" 152 | #include "objects/JamomaWhiteNoise.h" 153 | #include "objects/JamomaUnitImpulse.h" 154 | -------------------------------------------------------------------------------- /include/objects/JamomaDcblock.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | @ingroup jamoma2 4 | 5 | @brief Block DC offset within samples. 6 | 7 | @author Timothy Place, Nathan Wolek 8 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 9 | @license This project is released under the terms of the MIT License. 10 | */ 11 | 12 | #pragma once 13 | 14 | #include "../core/JamomaAudioObject.h" 15 | 16 | 17 | namespace Jamoma { 18 | 19 | 20 | /** This AudioObject removes DC offset (sometimes called DC bias from a Sample or SampleBundle. 21 | The process is acheived by applying a first-order highpass filter to the input. 22 | 23 | This first-order highpass filter algorithm is used pretty much everywhere (STK, ChucK, RTCMix, SuperCollider, Max, Pd, etc), 24 | with the difference equation: 25 | 26 | y(n) = (1 * x(n)) + (-1 * x(n-1)) - (-0.9997 * y(n-1)) , n = 0, 1, 2, 3, ... 27 | 28 | which can be simplified to: 29 | 30 | y(n) = x(n) - x(n-1) + (0.9997 * y(n-1)) 31 | 32 | and thus characterized by the Z-transform: 33 | 34 | Y(z) = X(z) - X(z) * z^(-1) + Y(z) * 0.9997 * z^(-1) 35 | 36 | meaning the transfer function is: 37 | 38 | H(z) = [1 - z^(-1)] / [1 + 0.9997 * z^(-1)] 39 | 40 | and resulting in the frequency response: 41 | 42 | H( e^(i*omega*T) ) = [1 - e^(-i * omega * T)] / [1 + 0.9997 * e^(-i * omega * T)] 43 | 44 | where $i$ is the sqrt(-1), e is Euler's log base, T is the sampling interval, and omega is 2*pi*frequency. 45 | 46 | In Max, it usually shows up simply as [biquad~ 1.0 -1.0 0.0 -0.9997 0.0]. 47 | In other places it usually shows up with the feedback coefficient set to -0.995 48 | (e.g in SuperCollider and in [JOS, 2007, pp 273]). 49 | The higher coefficient is desirable so as to not attenuate lowish frequencies in the spectrum, 50 | but with the caveat that it also won't respond as quickly to varying amounts DC Offset. 51 | 52 | The power is attenuated by -3 dB at a normalized frequency of 0.1612 * pi @ 0.9997. 53 | At fs=44100 this translates to cf = 22050 * 0.1612 = 3554.46 Hz. 54 | 55 | The power is attenuated by -3 dB at a normalized frequency of 0.1604 * pi @ 0.995. 56 | At fs=44100 this translates to cf = 22050 * 0.1604 = 3536.82 Hz. 57 | 58 | For reference, in this last case, the power is attenuated by -6 db (magnitude attenuated by -12 dB) @ 0.0798 * pi, 59 | which at fs=44100 translates to 1759.59 Hz. 60 | 61 | ---- 62 | 63 | So what are benefits of this filter? In the case of biquad~ in Max, we are processing with 2 coefficients zeroed, 64 | meaning that we burn the cpu for a second-order filter when we are only getting the benefit of a first-order filter. 65 | Why would we want to do this instead of doing something like a using a Butterworth filter for DC Blocking? 66 | 67 | We could implement a nice third-order Butterworth with a cf=20 Hz @ fs=48000 that would not disturb the gain of the spectrum, 68 | but... the filter does not have linear phase. 69 | 70 | Since we are outside of Max, we can evaluate this filter for what it is: a first-order filter. 71 | The clear benefit then is its speed. 72 | - however, if we used a pure FIR filter then we could potentially use SSE instructions, so: 73 | how would a second-order FIR compare to this classical first-order FIR/IIR combination? 74 | */ 75 | class Dcblock : public AudioObject { 76 | 77 | AdaptingSampleBundle mX = { this }; ///< Input history -- AdaptingSampleBundle type will update channelCount automagically as needed 78 | AdaptingSampleBundle mY = { this }; ///< Output history -- AdaptingSampleBundle type will update channelCount automagically as needed 79 | 80 | public: 81 | static constexpr Classname classname = { "dcblock" }; 82 | static constexpr auto tags = { "dspFilterLib", "audio", "filter" }; 83 | 84 | 85 | /** Resets the DC-Blocking filter. 86 | This algorithm uses an IIR filter, meaning that it relies on feedback. 87 | If the filter should not be producing any signal (such as turning audio off and then back on in a host) 88 | or if the feedback has become corrupted (such as might happen if a NaN is fed in) 89 | then it may be neccesary to clear the filter by calling this method. 90 | */ 91 | Message clear = { "clear", 92 | "Reset the filter", 93 | [this]{ 94 | mX.fill(0.0); 95 | mY.fill(0.0); 96 | } 97 | }; 98 | 99 | 100 | /** Process one sample. 101 | @param x Sample to be processed. 102 | @return Processed sample. 103 | */ 104 | Sample operator()(Sample x) 105 | { 106 | return (*this)(x, 0); 107 | } 108 | 109 | 110 | /** Process one sample at a specified channel. 111 | @param x Sample to be processed. 112 | @param channel The channel. 113 | @return Processed sample. 114 | */ 115 | Sample operator()(Sample x, int channel) 116 | { 117 | Sample y = x - mX[channel][0] + (mY[channel][0] * 0.9997); 118 | 119 | ZeroDenormal(y); 120 | mY[channel][0] = y; 121 | mX[channel][0] = x; 122 | return y; 123 | } 124 | 125 | 126 | /** Process a SharedSampleBundleGroup. 127 | @param x SharedSampleBundleGroup to be processed. 128 | @return Processed SharedSampleBundleGroup. 129 | */ 130 | SharedSampleBundleGroup operator()(const SampleBundle& x) 131 | { 132 | auto out = adapt(x); 133 | 134 | for (int channel=0; channel < x.channelCount(); ++channel) { 135 | for (int i=0; i < x.frameCount(); ++i) 136 | out[0][channel][i] = (*this)(x[channel][i], channel); 137 | } 138 | return out; 139 | } 140 | 141 | }; 142 | 143 | } // namespace Jamoma 144 | -------------------------------------------------------------------------------- /test/LowpassFourPole/LowpassFourPole.cpp: -------------------------------------------------------------------------------- 1 | /** @file 2 | @ingroup jamoma2 3 | 4 | @brief Unit test for the LowpassFourPole class 5 | 6 | @author Timothy Place, Nathan Wolek 7 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 8 | @license This project is released under the terms of the MIT License. 9 | 10 | */ 11 | 12 | #include "Jamoma.h" 13 | 14 | 15 | class LowpassFourpoleTest { 16 | 17 | Jamoma::UnitTest* mTest; 18 | 19 | public: 20 | LowpassFourpoleTest(Jamoma::UnitTest* test) 21 | : mTest(test) 22 | { 23 | testImpulseResponse(); 24 | } 25 | 26 | 27 | void testImpulseResponse() 28 | { 29 | Jamoma::LowpassFourPole my_lowpass; 30 | 31 | my_lowpass.sampleRate = 44100; 32 | my_lowpass.frequency = 1000.; 33 | my_lowpass.resonance = 10.0; 34 | 35 | Jamoma::UnitImpulse impulse; 36 | 37 | impulse.channelCount = 1; 38 | impulse.frameCount = 64; 39 | 40 | auto out_samples = my_lowpass( impulse() ); 41 | 42 | 43 | 44 | 45 | // The following impulse was based on the code found here 46 | // http://musicdsp.org/archive.php?classid=3#26 47 | // implemented in Processing by NW, adopting tweaks made in jamoma2. 48 | // It should correspond to the following settings: 49 | // cutoff = 1000 50 | // q = 10.0 51 | 52 | Jamoma::SampleVector expectedIR = { 53 | 0.0001111409354565384, 54 | 0.0005185809173325713, 55 | 0.001356682889160042, 56 | 0.002667118485531729, 57 | 0.004419755956128823, 58 | 0.006540994270685398, 59 | 0.008934879326675504, 60 | 0.01149761817960361, 61 | 0.01412721081388471, 62 | 0.01672952232792294, 63 | 0.01922180273273093, 64 | 0.02153441289695431, 65 | 0.02361132125950997, 66 | 0.02540978624306706, 67 | 0.02689952494242021, 68 | 0.02806158223028391, 69 | 0.02888704984210379, 70 | 0.02937573734116469, 71 | 0.02953486217098515, 72 | 0.02937780113545063, 73 | 0.02892292814387115, 74 | 0.02819255100289367, 75 | 0.02721195195725074, 76 | 0.02600853145669125, 77 | 0.02461105141528048, 78 | 0.02304897240680268, 79 | 0.0213518783490958, 80 | 0.01954898194165014, 81 | 0.01766870420221603, 82 | 0.01573832173904799, 83 | 0.01378367578829957, 84 | 0.01182893747184068, 85 | 0.009896424147485519, 86 | 0.008006462108263472, 87 | 0.00617729122962732, 88 | 0.004425007461280003, 89 | 0.002763539316523515, 90 | 0.001204654732341931, 91 | -0.0002420051353221634, 92 | -0.001568868447412927, 93 | -0.002770354661245002, 94 | -0.00384277892198484, 95 | -0.00478424169516578, 96 | -0.005594506331008, 97 | -0.006274867111324928, 98 | -0.006828010186212292, 99 | -0.007257869659464013, 100 | -0.007569480928348766, 101 | -0.007768833225177001, 102 | -0.007862723145594849, 103 | -0.007858610782695312, 104 | -0.007764479918011999, 105 | -0.007588703551583271, 106 | -0.007339915884954236, 107 | -0.007026891704653052, 108 | -0.006658433950742859, 109 | -0.006243270096853714, 110 | -0.005789957815887236, 111 | -0.005306800260490047, 112 | -0.004801771150406263, 113 | -0.004282449730795825, 114 | -0.003755965547245381, 115 | -0.003228952875050936, 116 | -0.002707514542814925 117 | }; 118 | 119 | int badSampleCount = 0; 120 | Jamoma::Sample temp = 0.0; 121 | Jamoma::Sample tempExpected = 0.0; 122 | 123 | for (int i = 0; i < expectedIR.size(); i++) { 124 | temp = out_samples[0][0][i]; 125 | tempExpected = expectedIR[i]; 126 | if (! mTest->compare(temp, tempExpected) ) { 127 | badSampleCount++; 128 | std::cout << "sample " << i << " had a difference of " << std::fabs(temp - tempExpected) << std::endl; 129 | } 130 | } 131 | 132 | std::cout << "the impulse response of my_lowpass (4 pole) has " << badSampleCount << " bad samples" << std::endl; 133 | mTest->TEST_ASSERT("Bad Sample Count", badSampleCount == 0); 134 | 135 | 136 | // Test range limiting 137 | my_lowpass.frequency = 100.0; 138 | mTest->TEST_ASSERT("frequency setting is correct", my_lowpass.frequency == 100.0); 139 | 140 | my_lowpass.frequency = 5.0; 141 | mTest->TEST_ASSERT("low frequency is clipped", my_lowpass.frequency == 20.0); 142 | 143 | // TODO: boundaries for this object need to change when the sampleRate changes -- currently they don't! 144 | // So we do this test with the initial sampleRate instead of with `my_lowpass.sampleRate` 145 | my_lowpass.frequency = 100000; 146 | mTest->TEST_ASSERT("high frequency is clipped", my_lowpass.frequency < 96000 * 0.5); 147 | 148 | // resonance is not clipped at the moment, so we can do irrational bad things... we should change this 149 | my_lowpass.resonance = 100.0; 150 | mTest->TEST_ASSERT("insane resonance is not clipped", my_lowpass.resonance == 100.0); 151 | 152 | my_lowpass.resonance = -5.0; 153 | mTest->TEST_ASSERT("negative resonance is not clipped", my_lowpass.resonance == -5.0); 154 | } 155 | 156 | }; 157 | 158 | 159 | int main(int argc, const char * argv[]) 160 | { 161 | Jamoma::UnitTest aUnitTestInstance; 162 | return aUnitTestInstance.failureCount(); 163 | } 164 | -------------------------------------------------------------------------------- /include/core/JamomaUnitTest.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | @ingroup jamoma2 4 | 5 | @brief Define a parameter of a JamomaObject 6 | 7 | @author Timothy Place 8 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 9 | @license This project is released under the terms of the MIT License. 10 | 11 | */ 12 | 13 | #pragma once 14 | 15 | #include "JamomaObject.h" 16 | #include "../third-party/gtest/gtest-internal.h" 17 | 18 | namespace Jamoma { 19 | 20 | 21 | template 22 | class UnitTest { 23 | std::unique_ptr mUnitTest; 24 | int mAssertionCount; 25 | int mFailedAssertions; 26 | 27 | public: 28 | /** Create an instance of your unit test. 29 | Your unit test will be passed a pointer to this wrapper instance, which you then use to log results. 30 | */ 31 | UnitTest() 32 | { 33 | mAssertionCount = 0; 34 | mFailedAssertions = 0; 35 | mUnitTest = std::make_unique(this); 36 | } 37 | 38 | 39 | UnitTest(const UnitTest&) = delete; 40 | UnitTest(const UnitTest&&) = delete; 41 | 42 | 43 | /** Destructor cleans up and logs the results of the test. 44 | */ 45 | ~UnitTest() 46 | { 47 | log("\n"); 48 | log("Number of assertions: %ld", mAssertionCount); 49 | log("Number of failed assertions: %ld", mFailedAssertions); 50 | log("\n"); 51 | } 52 | 53 | 54 | /** Log the outcome of a proceedure that should result as true. 55 | Test assertions are not like normal C++ assertions -- test assertions are not designed to crash when they fail. 56 | You probably don't want to call this directly -- it is much more convenient to use the #TEST_ASSERT macro instead. 57 | 58 | @param aTestName A name you wish to give the assertion. Should be as descriptive as possible. 59 | @param aTestResult You should pass 'true' if the assertion passes, or 'false' if it failed. 60 | @param filename The filename where the assertion is located -- provided automatically if you use the #TEST_ASSERT macro instead. 61 | @param linenumber The line number in source code of the assertion -- provided automatically if you use the #TEST_ASSERT macro instead. 62 | @return Returns true if a == b, otherwise returns false. 63 | */ 64 | void assertion(String aTestName, bool aTestResult, const char* filename, int linenumber) 65 | { 66 | ++mAssertionCount; 67 | result(aTestName, aTestResult, filename, linenumber); 68 | if (!aTestResult) 69 | ++mFailedAssertions; 70 | } 71 | 72 | 73 | /** Declare a result to be expected. 74 | A failed expectation will be flagged as an error in the IDE (Xcode or VS). 75 | 76 | @param aTestName The name of the expectation for logging purposes. 77 | @param aTestName The result received. 78 | @return Returns a 1 if the expection failed, 0 if it passes. 79 | */ 80 | #define TEST_ASSERT(aTestName, aTestResult) \ 81 | assertion((aTestName),(aTestResult), __FILE__, __LINE__) 82 | 83 | 84 | /** Post a message to the console. 85 | Adequate indenting is provided for free, as are newlines at the end. 86 | At some point we may additionally log these messages in other ways (e.g. to a database). 87 | @param fmtstring The string to post 88 | @param ... Values to be substituted into the string 89 | TODO: Would be nice to have this as an output stream instead of this clunky old-sk00l C stuff 90 | */ 91 | void log(const char *fmtstring, ...) 92 | { 93 | char str[4096]; 94 | char fullstr[4096]; 95 | va_list ap; 96 | 97 | va_start(ap, fmtstring); 98 | vsnprintf(str, 4000, fmtstring, ap); 99 | va_end(ap); 100 | str[4095] = 0; 101 | 102 | strncpy(fullstr, " ", 4095); 103 | strncat(fullstr, str, 4095); 104 | std::cerr << fullstr << std::endl; 105 | } 106 | 107 | 108 | /** Determine if two floating-point numbers (32- or 64-bit) are equivalent in value, tolerant of floating-point precision. 109 | Internally using the FloatingPoint comparison developed by Google for GTest. 110 | @param a The first value to test 111 | @param b The second value to test 112 | @param equivalent The expected result when comparing the two floats a and b. Defaults to TRUE. 113 | @param maxUlps The maximum number of "units in last place" that can deviate and still evaluate as equivalent. 114 | See https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ 115 | @return Returns true if a is equivalent to b, otherwise returns false. 116 | */ 117 | template 118 | bool compare(U a, U b, bool equivalent = true, size_t maxUlps = 4) 119 | { 120 | testing::internal::FloatingPoint aa(a); 121 | testing::internal::FloatingPoint bb(b); 122 | 123 | bool result = aa.AlmostEquals(bb, maxUlps); 124 | 125 | if (result == equivalent) // Was this the expected result? 126 | return true; 127 | else 128 | return false; 129 | } 130 | 131 | 132 | auto failureCount() 133 | { 134 | return mFailedAssertions; 135 | } 136 | 137 | private: 138 | 139 | 140 | // Used internally for posting assertion info 141 | void result(String name, bool aResult, const char* filename = "", int linenumber = 0) 142 | { 143 | // Note: we don't post passing assertions because the log (at least in Xcode) starts suppressing the messages and failures won't be posted 144 | if (aResult == false) { 145 | #ifdef JAMOMA_PLATFORM_WIN 146 | std::cout << filename << "(" << linenumber << ") : error: " << "Test Assertion Failed -- " << name << std::endl; 147 | #else 148 | std::cout << filename << ":" << linenumber << ": error: " << "Test Assertion Failed -- " << name << std::endl; 149 | #endif 150 | } 151 | } 152 | 153 | 154 | }; 155 | 156 | 157 | 158 | 159 | } // namespace Jamoma 160 | -------------------------------------------------------------------------------- /include/core/JamomaLimit.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | @ingroup jamoma2 4 | 5 | @brief Various functions for limiting the range of a value. 6 | 7 | @author Timothy Place, Nils Peters, Tristan Matthews 8 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 9 | @license This project is released under the terms of the MIT License. 10 | */ 11 | 12 | #pragma once 13 | 14 | 15 | namespace Jamoma { 16 | 17 | 18 | /** Determine id a value is a power-of-two. Only works for ints. */ 19 | template 20 | bool IsPowerOfTwo(T value) 21 | { 22 | return (value > 0) && ((value & (value-1)) == 0); 23 | } 24 | 25 | 26 | /** Limit input to power-of-two values. 27 | Non-power-of-two values are increased to the next-highest power-of-two upon return. 28 | Only works for ints up to 32-bits. 29 | @seealso http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 30 | */ 31 | template 32 | void TTLimitPowerOfTwo(T value) { 33 | value--; 34 | value |= value >> 1; 35 | value |= value >> 2; 36 | value |= value >> 4; 37 | value |= value >> 8; 38 | value |= value >> 16; 39 | ++value; 40 | return value; 41 | } 42 | 43 | 44 | 45 | 46 | template 47 | T Clip(T input, T low, T high) 48 | { 49 | return std::min(std::max(input, low), high); 50 | } 51 | 52 | 53 | /** This routine wrapping around the range as much as necessary */ 54 | template 55 | T Wrap(T input, const T low_bound, const T high_bound) 56 | { 57 | if ((input >= low_bound) && (input < high_bound)) 58 | return input; //nothing to wrap 59 | else if (input - low_bound >= 0) 60 | return (fmod((double)input - low_bound, fabs((double)low_bound - high_bound)) + low_bound); 61 | else 62 | return (-1.0 * fmod(-1.0 * (input - low_bound), fabs((double)low_bound - high_bound)) + high_bound); 63 | } 64 | 65 | 66 | /** A fast routine for wrapping around the range once. This is faster than doing an expensive module, where you know the range of the input 67 | will not equal or exceed twice the range. */ 68 | template 69 | T WrapOnce(T input, const T low_bound, const T high_bound) 70 | { 71 | if ((input >= low_bound) && (input < high_bound)) 72 | return input; 73 | else if (input >= high_bound) 74 | return ((low_bound - 1) + (input - high_bound)); 75 | else 76 | return ((high_bound + 1) - (low_bound - input)); 77 | } 78 | 79 | 80 | /** This routine folds numbers into the data range */ 81 | template 82 | T Fold(T input, const T low_bound, const T high_bound) 83 | { 84 | double foldRange; 85 | 86 | if ((input >= low_bound) && (input <= high_bound)) 87 | return input; //nothing to fold 88 | else { 89 | foldRange = 2 * fabs((double)low_bound - high_bound); 90 | return fabs(remainder(input - low_bound, foldRange)) + low_bound; 91 | } 92 | } 93 | 94 | 95 | /** A utility for scaling one range of values onto another range of values. */ 96 | template 97 | static T Scale(T value, T inlow, T inhigh, T outlow, T outhigh) 98 | { 99 | double inscale, outdiff; 100 | 101 | inscale = 1 / (inhigh - inlow); 102 | outdiff = outhigh - outlow; 103 | 104 | value = (value - inlow) * inscale; 105 | value = (value * outdiff) + outlow; 106 | return(value); 107 | } 108 | 109 | 110 | /** Rounding utility. */ 111 | template 112 | auto Round(T value) 113 | { 114 | if (value > 0) 115 | return((long)(value + 0.5)); 116 | else 117 | return((long)(value - 0.5)); 118 | } 119 | 120 | /** Defines several functions for constraining values within specified boundaries and preventing unwanted values. A variety of behaviors are offered, including clipping, wrapping and folding.@n@n 121 | * Exercise caution when using the functions defined here with unsigned values. Negative, signed integers have the potential to become very large numbers when casting to unsigned integers. This can cause errors during a boundary check, such as values clipping to the high boundary instead of the low boundary or numerous iterations of loop to bring a wrapped value back into the acceptable range. 122 | */ 123 | namespace Limit { 124 | 125 | template 126 | class Base { 127 | public: 128 | Base() = delete; 129 | }; 130 | 131 | 132 | template 133 | class None : public Base { 134 | public: 135 | static T apply(T input, T low, T high) { 136 | return input; 137 | } 138 | 139 | T operator()(T input, T low, T high) { 140 | return apply(input, low, high); 141 | } 142 | }; 143 | 144 | 145 | template 146 | class Clip : public Base { 147 | public: 148 | static T apply(T input, T low, T high) { 149 | return Jamoma::Clip(input, low, high); 150 | } 151 | 152 | T operator()(T input, T low, T high) { 153 | return apply(input, low, high); 154 | } 155 | }; 156 | 157 | 158 | template 159 | class Wrap : public Base { 160 | public: 161 | static T apply(T input, T low, T high) { 162 | return Jamoma::Wrap(input, low, high); 163 | } 164 | 165 | T operator()(T input, T low, T high) { 166 | return apply(input, low, high); 167 | } 168 | }; 169 | 170 | template 171 | class WrapOnce : public Base { 172 | public: 173 | static T apply(T input, T low, T high) { 174 | return Jamoma::WrapOnce(input, low, high); 175 | } 176 | 177 | T operator()(T input, T low, T high) { 178 | return apply(input, low, high); 179 | } 180 | }; 181 | 182 | template 183 | class Fold : public Base { 184 | public: 185 | static T apply(T input, T low, T high) { 186 | return Jamoma::Fold(input, low, high); 187 | } 188 | 189 | T operator()(T input, T low, T high) { 190 | return apply(input, low, high); 191 | } 192 | }; 193 | 194 | 195 | } // namespace Limit 196 | 197 | 198 | 199 | 200 | } // namespace Jamoma 201 | -------------------------------------------------------------------------------- /include/core/JamomaCircularStorage.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | @ingroup jamoma2 4 | 5 | @brief Read and write items within a circular container. 6 | 7 | @author Timothy Place, Nathan Wolek 8 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 9 | @license This project is released under the terms of the MIT License. 10 | */ 11 | 12 | #pragma once 13 | 14 | #include 15 | #include 16 | 17 | namespace Jamoma { 18 | 19 | 20 | /** A generic circular buffer designed specifically for access from a single thread. 21 | 22 | Allows items of a single datatype to be written into a vector that wraps around to the beginning whenever the end is exceeded. 23 | Reading items from the vector can then return chunks of the N most recent items. 24 | The initial design of this class was for use as an audio sample delay buffer, 25 | however it's functionality has been generalized to allow for other datatypes and applications. 26 | */ 27 | template 28 | class CircularStorage { 29 | friend class CircularStorageTest; 30 | 31 | std::vector mItems; ///< storage for the circular buffer's data 32 | std::size_t mIndex = { 0 }; ///< location of the record head 33 | std::size_t mSize; ///< the size of the circular buffer (may be different from the amount of allocated storage) 34 | std::thread::id mThread = { std::this_thread::get_id() }; ///< used to ensure we don't access unsafely from multiple threads 35 | 36 | public: 37 | /** Constructor specifies a fixed amount of storage for the container. 38 | If you want a different amount of storage, create a new container and dispose of the one you don't want. 39 | */ 40 | CircularStorage(std::size_t itemCount) 41 | : mItems(itemCount) 42 | , mSize(itemCount) 43 | {} 44 | 45 | 46 | CircularStorage(std::pair capacityAndSize) 47 | : mItems(capacityAndSize.first) 48 | , mSize(capacityAndSize.second) 49 | {} 50 | 51 | 52 | virtual ~CircularStorage() 53 | {} 54 | 55 | 56 | /** Write a block of things into the container. 57 | @param newInput A block of things to add. May not be larger than the size of the buffer. 58 | */ 59 | void write(const std::vector& newInput) 60 | { 61 | assert(std::this_thread::get_id() == mThread); 62 | assert(newInput.size() <= size()); 63 | 64 | std::size_t count = newInput.size(); 65 | std::size_t roomRemaining = size() - mIndex; 66 | bool wrap = false; 67 | 68 | if (count > roomRemaining) { 69 | count = roomRemaining; 70 | wrap = true; 71 | } 72 | 73 | std::copy_n(newInput.begin(), count, mItems.begin()+mIndex); 74 | mIndex += count; 75 | 76 | if (wrap) { 77 | std::size_t offset = count; 78 | 79 | count = newInput.size() - offset; 80 | std::copy_n(newInput.begin()+offset, count, mItems.begin()); 81 | mIndex = count; 82 | } 83 | } 84 | 85 | 86 | void write(const T& newInput) { 87 | assert(std::this_thread::get_id() == mThread); 88 | 89 | mItems[mIndex] = newInput; 90 | ++mIndex; 91 | if (mIndex == size()) 92 | mIndex = 0; 93 | } 94 | 95 | 96 | /** Read a block of things out from the container. 97 | These will be the N most recent items added to the history. 98 | @param output A place to write the block of things from the buffer. 99 | The size of this buffer will determine the number of things to request. 100 | May not be larger than the size of the buffer. 101 | */ 102 | void read(std::vector& output) { 103 | head(output); 104 | } 105 | 106 | 107 | /** Read a block of things out from the container. 108 | These will be the N most recent items added to the history. 109 | @param output A place to write the block of things from the buffer. 110 | The size of this buffer will determine the number of things to request. 111 | May not be larger than the size of the buffer. 112 | @see tail() 113 | */ 114 | void head(std::vector& output) 115 | { 116 | assert(std::this_thread::get_id() == mThread); 117 | assert(size() >= output.size()); 118 | 119 | long count = output.size(); 120 | long start = mIndex - count; 121 | bool wrap = false; 122 | 123 | if (start<0) { 124 | count = -start; 125 | start = size() + start; 126 | wrap = true; 127 | } 128 | 129 | std::copy_n(mItems.begin()+start, count, output.begin()); 130 | 131 | if (wrap) { 132 | std::size_t offset = count; 133 | 134 | count = output.size() - offset; 135 | std::copy_n(mItems.begin(), count, output.begin()+offset); 136 | } 137 | } 138 | 139 | 140 | /** Read a block of things out from the container. 141 | These will be the N oldest items added in the history. 142 | @param output A place to write the block of things from the buffer. 143 | The size of this buffer will determine the number of things to request. 144 | May not be larger than the size of the buffer. 145 | @see head() 146 | */ 147 | void tail(std::vector& output) 148 | { 149 | assert(std::this_thread::get_id() == mThread); 150 | assert(size() >= output.size()); 151 | 152 | long count = output.size(); 153 | long start = mIndex % size(); 154 | bool wrap = false; 155 | 156 | if (start+count > size()) { 157 | count = size() - start; 158 | wrap = true; 159 | } 160 | 161 | std::copy_n(mItems.begin()+start, count, output.begin()); 162 | 163 | if (wrap) { 164 | std::size_t offset = count; 165 | 166 | count = output.size() - offset; 167 | std::copy_n(mItems.begin(), count, output.begin()+offset); 168 | } 169 | } 170 | 171 | 172 | T tail(int offset = 0) { 173 | // TODO: benchmark / evaluate use of modulo here 174 | return mItems[ (mIndex+offset) % size() ]; 175 | } 176 | 177 | 178 | /** Zero the contents. 179 | */ 180 | void clear() 181 | { 182 | assert(std::this_thread::get_id() == mThread); 183 | mItems.clear(); 184 | } 185 | 186 | 187 | /** The number of items in the buffer. 188 | */ 189 | std::size_t size() { 190 | return mSize; 191 | } 192 | 193 | 194 | /** Change the number of items in the buffer. 195 | */ 196 | void resize(std::size_t newSize) { 197 | assert(newSize <= mItems.size()); 198 | mSize = newSize; 199 | } 200 | 201 | }; 202 | 203 | 204 | using CircularSampleBuffer = CircularStorage; 205 | using CircularSampleBufferGroup = std::vector; 206 | 207 | 208 | } // namespace Jamoma 209 | -------------------------------------------------------------------------------- /include/third-party/mersenne/Test/Original/mt19937ar.c: -------------------------------------------------------------------------------- 1 | /* 2 | A C-program for MT19937, with initialization improved 2002/1/26. 3 | Coded by Takuji Nishimura and Makoto Matsumoto. 4 | 5 | Before using, initialize the state by using init_genrand(seed) 6 | or init_by_array(init_key, key_length). 7 | 8 | Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, 9 | All rights reserved. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions 13 | are met: 14 | 15 | 1. Redistributions of source code must retain the above copyright 16 | notice, this list of conditions and the following disclaimer. 17 | 18 | 2. Redistributions in binary form must reproduce the above copyright 19 | notice, this list of conditions and the following disclaimer in the 20 | documentation and/or other materials provided with the distribution. 21 | 22 | 3. The names of its contributors may not be used to endorse or promote 23 | products derived from this software without specific prior written 24 | permission. 25 | 26 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 30 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 31 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 32 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 33 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 34 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 35 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 36 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | 38 | 39 | Any feedback is very welcome. 40 | http://www.math.keio.ac.jp/matumoto/emt.html 41 | email: matumoto@math.keio.ac.jp 42 | */ 43 | 44 | #include 45 | 46 | /* Period parameters */ 47 | #define N 624 48 | #define M 397 49 | #define MATRIX_A 0x9908b0dfUL /* constant vector a */ 50 | #define UPPER_MASK 0x80000000UL /* most significant w-r bits */ 51 | #define LOWER_MASK 0x7fffffffUL /* least significant r bits */ 52 | 53 | static unsigned long mt[N]; /* the array for the state vector */ 54 | static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */ 55 | 56 | /* initializes mt[N] with a seed */ 57 | void init_genrand(unsigned long s) 58 | { 59 | mt[0]= s & 0xffffffffUL; 60 | for (mti=1; mti> 30)) + mti); 63 | /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ 64 | /* In the previous versions, MSBs of the seed affect */ 65 | /* only MSBs of the array mt[]. */ 66 | /* 2002/01/09 modified by Makoto Matsumoto */ 67 | mt[mti] &= 0xffffffffUL; 68 | /* for >32 bit machines */ 69 | } 70 | } 71 | 72 | /* initialize by an array with array-length */ 73 | /* init_key is the array for initializing keys */ 74 | /* key_length is its length */ 75 | void init_by_array(unsigned long init_key[], int key_length) 76 | { 77 | int i, j, k; 78 | init_genrand(19650218UL); 79 | i=1; j=0; 80 | k = (N>key_length ? N : key_length); 81 | for (; k; k--) { 82 | mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL)) 83 | + init_key[j] + j; /* non linear */ 84 | mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ 85 | i++; j++; 86 | if (i>=N) { mt[0] = mt[N-1]; i=1; } 87 | if (j>=key_length) j=0; 88 | } 89 | for (k=N-1; k; k--) { 90 | mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL)) 91 | - i; /* non linear */ 92 | mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ 93 | i++; 94 | if (i>=N) { mt[0] = mt[N-1]; i=1; } 95 | } 96 | 97 | mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ 98 | } 99 | 100 | /* generates a random number on [0,0xffffffff]-interval */ 101 | unsigned long genrand_int32(void) 102 | { 103 | unsigned long y; 104 | static unsigned long mag01[2]={0x0UL, MATRIX_A}; 105 | /* mag01[x] = x * MATRIX_A for x=0,1 */ 106 | 107 | if (mti >= N) { /* generate N words at one time */ 108 | int kk; 109 | 110 | if (mti == N+1) /* if init_genrand() has not been called, */ 111 | init_genrand(5489UL); /* a default initial seed is used */ 112 | 113 | for (kk=0;kk> 1) ^ mag01[y & 0x1UL]; 116 | } 117 | for (;kk> 1) ^ mag01[y & 0x1UL]; 120 | } 121 | y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); 122 | mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL]; 123 | 124 | mti = 0; 125 | } 126 | 127 | y = mt[mti++]; 128 | 129 | /* Tempering */ 130 | y ^= (y >> 11); 131 | y ^= (y << 7) & 0x9d2c5680UL; 132 | y ^= (y << 15) & 0xefc60000UL; 133 | y ^= (y >> 18); 134 | 135 | return y; 136 | } 137 | 138 | /* generates a random number on [0,0x7fffffff]-interval */ 139 | long genrand_int31(void) 140 | { 141 | return (long)(genrand_int32()>>1); 142 | } 143 | 144 | /* generates a random number on [0,1]-real-interval */ 145 | double genrand_real1(void) 146 | { 147 | return genrand_int32()*(1.0/4294967295.0); 148 | /* divided by 2^32-1 */ 149 | } 150 | 151 | /* generates a random number on [0,1)-real-interval */ 152 | double genrand_real2(void) 153 | { 154 | return genrand_int32()*(1.0/4294967296.0); 155 | /* divided by 2^32 */ 156 | } 157 | 158 | /* generates a random number on (0,1)-real-interval */ 159 | double genrand_real3(void) 160 | { 161 | return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0); 162 | /* divided by 2^32 */ 163 | } 164 | 165 | /* generates a random number on [0,1) with 53-bit resolution*/ 166 | double genrand_res53(void) 167 | { 168 | unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6; 169 | return(a*67108864.0+b)*(1.0/9007199254740992.0); 170 | } 171 | /* These real versions are due to Isaku Wada, 2002/01/09 added */ 172 | 173 | /* This main() outputs 2000 generated integers and reals. */ 174 | /* 175 | int main(void) 176 | { 177 | int i; 178 | unsigned long init[4]={0x123, 0x234, 0x345, 0x456}, length=4; 179 | init_by_array(init, length); 180 | printf("1000 outputs of genrand_int32()\n"); 181 | for (i=0; i<1000; i++) { 182 | printf("%10lu ", genrand_int32()); 183 | if (i%5==4) printf("\n"); 184 | } 185 | printf("\n1000 outputs of genrand_real2()\n"); 186 | for (i=0; i<1000; i++) { 187 | printf("%10.8f ", genrand_real2()); 188 | if (i%5==4) printf("\n"); 189 | } 190 | return 0; 191 | } 192 | */ 193 | -------------------------------------------------------------------------------- /include/third-party/mersenne/Test/Ladd/mtprng.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------- 2 | // Algorithmic Conjurings @ http://www.coyotegulch.com 3 | // 4 | // mtprng.cpp (libcoyote) 5 | // 6 | // Mersenne Twister -- A pseudorandom Number Generator 7 | // 8 | // ORIGINAL ALGORITHM COPYRIGHT 9 | // ============================ 10 | // Copyright (C) 1997, 2002 Makoto Matsumoto and Takuji Nishimura. 11 | // Any feedback is very welcome. For any question, comments, see 12 | // http://www.math.keio.ac.jp/matumoto/emt.html or email 13 | // matumoto@math.keio.ac.jp 14 | //--------------------------------------------------------------------- 15 | // 16 | // COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: 17 | // 18 | // This notice applies *only* to this specific expression of this 19 | // algorithm, and does not imply ownership or invention of the 20 | // implemented algorithm. 21 | // 22 | // If you modify this file, you may insert additional notices 23 | // immediately following this sentence. 24 | // 25 | // Copyright 2001, 2002, 2003 Scott Robert Ladd. 26 | // All rights reserved, except as noted herein. 27 | // 28 | // This computer program source file is supplied "AS IS". Scott Robert 29 | // Ladd (hereinafter referred to as "Author") disclaims all warranties, 30 | // expressed or implied, including, without limitation, the warranties 31 | // of merchantability and of fitness for any purpose. The Author 32 | // assumes no liability for direct, indirect, incidental, special, 33 | // exemplary, or consequential damages, which may result from the use 34 | // of this software, even if advised of the possibility of such damage. 35 | // 36 | // The Author hereby grants anyone permission to use, copy, modify, and 37 | // distribute this source code, or portions hereof, for any purpose, 38 | // without fee, subject to the following restrictions: 39 | // 40 | // 1. The origin of this source code must not be misrepresented. 41 | // 42 | // 2. Altered versions must be plainly marked as such and must not 43 | // be misrepresented as being the original source. 44 | // 45 | // 3. This Copyright notice may not be removed or altered from any 46 | // source or altered source distribution. 47 | // 48 | // The Author specifically permits (without fee) and encourages the use 49 | // of this source code for entertainment, education, or decoration. If 50 | // you use this source code in a product, acknowledgment is not required 51 | // but would be appreciated. 52 | // 53 | // Acknowledgement: 54 | // This license is based on the wonderful simple license that 55 | // accompanies libpng. 56 | // 57 | //----------------------------------------------------------------------- 58 | // 59 | // For more information on this software package, please visit 60 | // Scott's web site, Coyote Gulch Productions, at: 61 | // 62 | // http://www.coyotegulch.com 63 | // 64 | //----------------------------------------------------------------------- 65 | 66 | #include "mtprng.h" 67 | using namespace libcoyote; 68 | 69 | #if _MSC_VER < 1300 70 | const mtprng::int_type mtprng::MATRIX_A = 0x9908b0dfUL; 71 | const mtprng::int_type mtprng::UPPER_MASK = 0x80000000UL; 72 | const mtprng::int_type mtprng::LOWER_MASK = 0x7fffffffUL; 73 | #endif 74 | 75 | //-------------------------------------------------------------------------- 76 | // Constructor 77 | mtprng::mtprng(int_type seed) 78 | { 79 | init(seed); 80 | } 81 | 82 | //-------------------------------------------------------------------------- 83 | // Initializes the generator with "seed" 84 | void mtprng::init(int_type seed) 85 | { 86 | // Save seed for historical purpose 87 | m_seed = seed; 88 | m_mt[0] = seed & 0xffffffffUL; 89 | 90 | // Set the seed using values suggested by Matsumoto & Nishimura, using 91 | // a generator by Knuth. See original source for details. 92 | for (m_mti = 1; m_mti < N; ++m_mti) 93 | m_mt[m_mti] = 0xffffffffUL & (1812433253UL * (m_mt[m_mti - 1] ^ (m_mt[m_mti - 1] >> 30)) + m_mti); 94 | 95 | } 96 | 97 | //-------------------------------------------------------------------------- 98 | // Initialize the generator from an array of seeds 99 | void mtprng::init_by_array(const std::vector & init_key) 100 | { 101 | // Note: variable names match those in original example 102 | size_t i = 1; 103 | size_t j = 0; 104 | size_t k = static_cast((N > init_key.size()) ? N : init_key.size()); 105 | init(19650218UL); 106 | 107 | for (; k; --k) 108 | { 109 | m_mt[i] = (m_mt[i] ^ ((m_mt[i - 1] ^ (m_mt[i - 1] >> 30)) * 1664525UL)) + init_key[j] + j; 110 | m_mt[i] &= 0xffffffffUL; 111 | ++i; 112 | ++j; 113 | 114 | if (i >= N) 115 | { 116 | m_mt[0] = m_mt[N - 1]; 117 | i = 1; 118 | } 119 | 120 | if (j >= static_cast(init_key.size())) 121 | j = 0; 122 | } 123 | 124 | for (k = N - 1; k; --k) 125 | { 126 | m_mt[i] = (m_mt[i] ^ ((m_mt[i - 1] ^ (m_mt[i - 1] >> 30)) * 1566083941UL)) - i; 127 | m_mt[i] &= 0xffffffffUL; 128 | ++i; 129 | 130 | if (i >= N) 131 | { 132 | m_mt[0] = m_mt[N - 1]; 133 | i = 1; 134 | } 135 | } 136 | 137 | m_mt[0] = 0x80000000UL; 138 | } 139 | 140 | //-------------------------------------------------------------------------- 141 | // Obtain the next 32-bit integer in the psuedo-random sequence 142 | mtprng::int_type mtprng::get_rand() 143 | { 144 | // Note: variable names match those in original example 145 | const int_type mag01[2] = { 0, MATRIX_A }; 146 | int_type y; 147 | size_t kk; 148 | 149 | // Generate N words at a time 150 | if (m_mti >= N) 151 | { 152 | // Fill the m_mt array 153 | for (kk=0; kk < N-M; kk++) 154 | { 155 | y = (m_mt[kk] & UPPER_MASK) | (m_mt[kk+1] & LOWER_MASK); 156 | m_mt[kk] = m_mt[kk + M] ^ (y >> 1) ^ mag01[y & 0x1]; 157 | } 158 | 159 | for ( ; kk < N-1; kk++) 160 | { 161 | y = (m_mt[kk] & UPPER_MASK) | (m_mt[kk+1] & LOWER_MASK); 162 | m_mt[kk] = m_mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1]; 163 | } 164 | 165 | y = (m_mt[N-1] & UPPER_MASK) | (m_mt[0]&LOWER_MASK); 166 | m_mt[N-1] = m_mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1]; 167 | 168 | m_mti = 0; 169 | } 170 | 171 | // Here is where we actually calculate the number with a series of transformations 172 | y = m_mt[m_mti++]; 173 | 174 | y ^= (y >> 11); 175 | y ^= (y << 7) & 0x9d2c5680UL; 176 | y ^= (y << 15) & 0xefc60000UL; 177 | y ^= (y >> 18); 178 | 179 | return y; 180 | } 181 | 182 | //-------------------------------------------------------------------------- 183 | // Obtain a psuedorandom real number in the range [0,1), i.e., a number 184 | // greater than or equal to 0 and less than 1, with 53-bit precision. 185 | mtprng::real_type mtprng::get_rand_real53() 186 | { 187 | // privides a granularity of approx. 1.1E-16 188 | int_type a = get_rand() >> 5; 189 | int_type b = get_rand() >> 6; 190 | return real_type(a * 67108864.0 + b) * (1.0 / 9007199254740992.0); 191 | } 192 | 193 | -------------------------------------------------------------------------------- /include/third-party/mersenne/Test/Bedaux/mtrand.h: -------------------------------------------------------------------------------- 1 | // mtrand.h 2 | // C++ include file for MT19937, with initialization improved 2002/1/26. 3 | // Coded by Takuji Nishimura and Makoto Matsumoto. 4 | // Ported to C++ by Jasper Bedaux 2003/1/1 (see http://www.bedaux.net/mtrand/). 5 | // The generators returning floating point numbers are based on 6 | // a version by Isaku Wada, 2002/01/09 7 | // 8 | // Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, 9 | // All rights reserved. 10 | // 11 | // Redistribution and use in source and binary forms, with or without 12 | // modification, are permitted provided that the following conditions 13 | // are met: 14 | // 15 | // 1. Redistributions of source code must retain the above copyright 16 | // notice, this list of conditions and the following disclaimer. 17 | // 18 | // 2. Redistributions in binary form must reproduce the above copyright 19 | // notice, this list of conditions and the following disclaimer in the 20 | // documentation and/or other materials provided with the distribution. 21 | // 22 | // 3. The names of its contributors may not be used to endorse or promote 23 | // products derived from this software without specific prior written 24 | // permission. 25 | // 26 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 30 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 31 | // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 32 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 33 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 34 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 35 | // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 36 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | // 38 | // Any feedback is very welcome. 39 | // http://www.math.keio.ac.jp/matumoto/emt.html 40 | // email: matumoto@math.keio.ac.jp 41 | // 42 | // Feedback about the C++ port should be sent to Jasper Bedaux, 43 | // see http://www.bedaux.net/mtrand/ for e-mail address and info. 44 | 45 | #ifndef MTRAND_H 46 | #define MTRAND_H 47 | 48 | class MTRand_int32 { // Mersenne Twister random number generator 49 | public: 50 | // default constructor: uses default seed only if this is the first instance 51 | MTRand_int32() { if (!init) seed(5489UL); init = true; } 52 | // constructor with 32 bit int as seed 53 | MTRand_int32(unsigned long s) { seed(s); init = true; } 54 | // constructor with array of size 32 bit ints as seed 55 | MTRand_int32(const unsigned long* array, int size) { seed(array, size); init = true; } 56 | // the two seed functions 57 | void seed(unsigned long); // seed with 32 bit integer 58 | void seed(const unsigned long*, int size); // seed with array 59 | // overload operator() to make this a generator (functor) 60 | unsigned long operator()() { return rand_int32(); } 61 | // 2007-02-11: made the destructor virtual; thanks "double more" for pointing this out 62 | virtual ~MTRand_int32() {} // destructor 63 | protected: // used by derived classes, otherwise not accessible; use the ()-operator 64 | unsigned long rand_int32(); // generate 32 bit random integer 65 | private: 66 | static const int n = 624, m = 397; // compile time constants 67 | // the variables below are static (no duplicates can exist) 68 | static unsigned long state[n]; // state vector array 69 | static int p; // position in state array 70 | static bool init; // true if init function is called 71 | // private functions used to generate the pseudo random numbers 72 | unsigned long twiddle(unsigned long, unsigned long); // used by gen_state() 73 | void gen_state(); // generate new state 74 | // make copy constructor and assignment operator unavailable, they don't make sense 75 | MTRand_int32(const MTRand_int32&); // copy constructor not defined 76 | void operator=(const MTRand_int32&); // assignment operator not defined 77 | }; 78 | 79 | // inline for speed, must therefore reside in header file 80 | inline unsigned long MTRand_int32::twiddle(unsigned long u, unsigned long v) { 81 | return (((u & 0x80000000UL) | (v & 0x7FFFFFFFUL)) >> 1) 82 | ^ ((v & 1UL) ? 0x9908B0DFUL : 0x0UL); 83 | } 84 | 85 | inline unsigned long MTRand_int32::rand_int32() { // generate 32 bit random int 86 | if (p == n) gen_state(); // new state vector needed 87 | // gen_state() is split off to be non-inline, because it is only called once 88 | // in every 624 calls and otherwise irand() would become too big to get inlined 89 | unsigned long x = state[p++]; 90 | x ^= (x >> 11); 91 | x ^= (x << 7) & 0x9D2C5680UL; 92 | x ^= (x << 15) & 0xEFC60000UL; 93 | return x ^ (x >> 18); 94 | } 95 | 96 | // generates double floating point numbers in the half-open interval [0, 1) 97 | class MTRand : public MTRand_int32 { 98 | public: 99 | MTRand() : MTRand_int32() {} 100 | MTRand(unsigned long seed) : MTRand_int32(seed) {} 101 | MTRand(const unsigned long* seed, int size) : MTRand_int32(seed, size) {} 102 | ~MTRand() {} 103 | double operator()() { 104 | return static_cast(rand_int32()) * (1. / 4294967296.); } // divided by 2^32 105 | private: 106 | MTRand(const MTRand&); // copy constructor not defined 107 | void operator=(const MTRand&); // assignment operator not defined 108 | }; 109 | 110 | // generates double floating point numbers in the closed interval [0, 1] 111 | class MTRand_closed : public MTRand_int32 { 112 | public: 113 | MTRand_closed() : MTRand_int32() {} 114 | MTRand_closed(unsigned long seed) : MTRand_int32(seed) {} 115 | MTRand_closed(const unsigned long* seed, int size) : MTRand_int32(seed, size) {} 116 | ~MTRand_closed() {} 117 | double operator()() { 118 | return static_cast(rand_int32()) * (1. / 4294967295.); } // divided by 2^32 - 1 119 | private: 120 | MTRand_closed(const MTRand_closed&); // copy constructor not defined 121 | void operator=(const MTRand_closed&); // assignment operator not defined 122 | }; 123 | 124 | // generates double floating point numbers in the open interval (0, 1) 125 | class MTRand_open : public MTRand_int32 { 126 | public: 127 | MTRand_open() : MTRand_int32() {} 128 | MTRand_open(unsigned long seed) : MTRand_int32(seed) {} 129 | MTRand_open(const unsigned long* seed, int size) : MTRand_int32(seed, size) {} 130 | ~MTRand_open() {} 131 | double operator()() { 132 | return (static_cast(rand_int32()) + .5) * (1. / 4294967296.); } // divided by 2^32 133 | private: 134 | MTRand_open(const MTRand_open&); // copy constructor not defined 135 | void operator=(const MTRand_open&); // assignment operator not defined 136 | }; 137 | 138 | // generates 53 bit resolution doubles in the half-open interval [0, 1) 139 | class MTRand53 : public MTRand_int32 { 140 | public: 141 | MTRand53() : MTRand_int32() {} 142 | MTRand53(unsigned long seed) : MTRand_int32(seed) {} 143 | MTRand53(const unsigned long* seed, int size) : MTRand_int32(seed, size) {} 144 | ~MTRand53() {} 145 | double operator()() { 146 | return (static_cast(rand_int32() >> 5) * 67108864. + 147 | static_cast(rand_int32() >> 6)) * (1. / 9007199254740992.); } 148 | private: 149 | MTRand53(const MTRand53&); // copy constructor not defined 150 | void operator=(const MTRand53&); // assignment operator not defined 151 | }; 152 | 153 | #endif // MTRAND_H 154 | -------------------------------------------------------------------------------- /include/third-party/mersenne/MersenneTwister.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 30 | Mersenne Twister Random Number Generator 31 | 32 | 33 | 34 | 35 |

Mersenne Twister Random Number Generator

36 | 37 | The Mersenne Twister is an algorithm for generating random numbers. 38 | It was designed with consideration of the flaws in various other generators. 39 | It has an incredibly long period, 219937-1 (more than 106001), before its sequence of numbers will repeat. 40 | And it has 623 dimensions of equidistribution, meaning that all sequences up to 623 numbers long are equally probable. 41 | The generator is also fast; it avoids multiplication and division, and it benefits from caches and pipelines. 42 | See the 43 | inventors' page 44 | or 45 | Wikipedia article 46 | for more details. 47 | 48 |

I have implemented the Mersenne Twister in a C++ class that is fast, convenient, portable, and free. 49 | Take a look at the 50 | class 51 | and 52 | example 53 | program. 54 | Or download the complete package in 55 | zip 56 | or 57 | tarball 58 | format. 59 | 60 |

Features: 61 |

    62 |
  • Simple creation of generator with MTRand r;
  • 63 |
  • Convenient access with double a = r();
  • 64 |
  • Generation of integers or floating-point numbers
  • 65 |
  • Easy seeding options
  • 66 |
      67 |
    • Automatically from /dev/urandom or time() and clock()
    • 68 |
    • Single integer
    • 69 |
    • Arrays of any length (to access full 19937-bit range)
    • 70 |
    71 |
  • Ability to save and restore state
  • 72 |
  • Thorough example program
  • 73 |
  • Validation and performance tests
  • 74 |
  • Open source code under BSD license
  • 75 |
76 | 77 |

The included performance tests verify the speed and correctness of this generator compared to known sequences and alternative implementations. 78 | It has been tested in a variety of hardware and software environments including: 79 | Intel Core 2 Quad, AMD Opteron 848; 80 | Red Hat Linux, Mac OS X 10.5 Leopard, Windows XP; 81 | GNU Compiler Collection 4.2 (g++), Intel Compiler 10.1 (icpc), Portland Group International Compiler 9.0 (pgCC), Pathscale Compiler 3.1 (pathCC), and Microsoft Visual C++ 2008. 82 | 83 |

Version 1.0 incorporated several changes released by the Mersenne Twister inventors on 26 January 2002. 84 | The seeding algorithm was revised to correct a minor problem in which the highest bit of the seed was not well represented in the generator state. 85 | The ability to start with large seeds was extended to seed arrays of arbitrary length. 86 | Access was added for 53-bit real numbers in [0,1), matching the accuracy of IEEE doubles. 87 | Also, the software license was changed from the GNU Lesser General Public License to a BSD license, making commercial use of this software more convenient. 88 | 89 |

The v1.0 release included some other improvements as well. 90 | By popular demand, access was added for real numbers from normal (Gaussian) distributions. 91 | Safeguards were added to prevent out-of-range number generation on 64-bit machines. 92 | Finally, new optimizations yielded 25% faster generation overall and 100% faster generation for integers in [0,n]. 93 | 94 |

Version 1.1 focuses on portability and reliability. 95 | Instances of deprecated C++ features were modernized. 96 | Operations were rewritten to work on ones'-complement machines and environments with unsigned enumerations. 97 | The test program was toughened and expanded. 98 | A slight correction was made in terminology; 99 | the parameter for setting the standard deviation of a Gaussian distribution is now properly labeled as "stddev" rather than "variance". 100 | A copy constructor and copy operator were also added. 101 | The seed correlations, generator functions, output sequences, and save formats are identical to Version 1.0. 102 | 103 |

Downloads: 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 |
Version 1.1Mersenne-1.1.zipMersenne-1.1.tar.gz
Version 1.0Mersenne-1.0.zipMersenne-1.0.tar.gz
Version 0.8Mersenne-0.8.zipMersenne-0.8.tar.gz
Version 0.7Mersenne-0.7.zipMersenne-0.7.tar.gz
Version 0.6Mersenne-0.6.zipMersenne-0.6.tar.gz
Version 0.5Mersenne-0.5.zipMersenne-0.5.tar.gz
Version 0.4Mersenne-0.4.zipMersenne-0.4.tar.gz
Version 0.3Mersenne-0.3.zipMersenne-0.3.tar.gz
Version 0.2Mersenne-0.2.zipMersenne-0.2.tar.gz
Version 0.1Mersenne-0.1.zipMersenne-0.1.tar.gz
116 | 117 |

Comments, questions, and improvements are always welcome. 118 | 119 |

If you like this software, you might also want to try my 120 | ConfigFile 121 | (C++) configuration file reader and 122 | Anneal.py 123 | (Python) module for optimization by simulated annealing. 124 | 125 | 126 | 127 | 128 | 129 |

130 | Creations of Rick Wagner 131 | (wagnerr@umich.edu) 30 September 2009 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /include/third-party/mersenne/Test/Yang/mtrnd.h: -------------------------------------------------------------------------------- 1 | /* 2 | A C-program for MT19937, with initialization improved 2002/1/26. 3 | Coded by Takuji Nishimura and Makoto Matsumoto. 4 | 5 | Before using, initialize the state by using init_genrand(seed) 6 | or init_by_array(init_key, key_length). 7 | 8 | Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, 9 | All rights reserved. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions 13 | are met: 14 | 15 | 1. Redistributions of source code must retain the above copyright 16 | notice, this list of conditions and the following disclaimer. 17 | 18 | 2. Redistributions in binary form must reproduce the above copyright 19 | notice, this list of conditions and the following disclaimer in the 20 | documentation and/or other materials provided with the distribution. 21 | 22 | 3. The names of its contributors may not be used to endorse or promote 23 | products derived from this software without specific prior written 24 | permission. 25 | 26 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 30 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 31 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 32 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 33 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 34 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 35 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 36 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | 38 | 39 | Any feedback is very welcome. 40 | http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html 41 | email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) 42 | 43 | Reference: M. Matsumoto and T. Nishimura, "Mersenne Twister: 44 | A 623-Dimensionally Equidistributed Uniform Pseudo-Random Number Generator", 45 | ACM Transactions on Modeling and Computer Simulation, Vol. 8, No. 1, 46 | January 1998, pp 3--30. 47 | */ 48 | 49 | // C++ wrapped up by Changjiang Yang, more important: make it thread-safe. 50 | #ifndef _MT_RND_H_ 51 | #define _MT_RND_H_ 52 | 53 | namespace MT { 54 | /* Period parameters */ 55 | const int N = 624; 56 | const int M = 397; 57 | const unsigned long MATRIX_A = 0x9908b0dfUL; /* constant vector a */ 58 | const unsigned long UPPER_MASK = 0x80000000UL; /* most significant w-r bits */ 59 | const unsigned long LOWER_MASK = 0x7fffffffUL; /* least significant r bits */ 60 | 61 | class MersenneTwist { 62 | unsigned long mt[N]; /* the array for the state vector */ 63 | int mti; /* mti==N+1 means mt[N] is not initialized */ 64 | public: 65 | 66 | MersenneTwist() : mti(N+1) {} 67 | 68 | /* initializes mt[N] with a seed */ 69 | // Note: Initializing TWISTER to the scalar integer state 0 actually 70 | // corresponds to the C call init_genrand(5489). 71 | void init_genrand(unsigned long s) 72 | { 73 | mt[0]= s & 0xffffffffUL; 74 | for (mti=1; mti> 30)) + mti); 77 | /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ 78 | /* In the previous versions, MSBs of the seed affect */ 79 | /* only MSBs of the array mt[]. */ 80 | /* 2002/01/09 modified by Makoto Matsumoto */ 81 | mt[mti] &= 0xffffffffUL; 82 | /* for >32 bit machines */ 83 | } 84 | } 85 | 86 | /* initialize by an array with array-length */ 87 | /* init_key is the array for initializing keys */ 88 | /* key_length is its length */ 89 | /* slight change for C++, 2004/2/26 */ 90 | void init_by_array(unsigned long init_key[], int key_length) 91 | { 92 | int i, j, k; 93 | init_genrand(19650218UL); 94 | i=1; j=0; 95 | k = (N>key_length ? N : key_length); 96 | for (; k; k--) { 97 | mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL)) 98 | + init_key[j] + j; /* non linear */ 99 | mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ 100 | i++; j++; 101 | if (i>=N) { mt[0] = mt[N-1]; i=1; } 102 | if (j>=key_length) j=0; 103 | } 104 | for (k=N-1; k; k--) { 105 | mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL)) 106 | - i; /* non linear */ 107 | mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ 108 | i++; 109 | if (i>=N) { mt[0] = mt[N-1]; i=1; } 110 | } 111 | 112 | mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ 113 | } 114 | 115 | /* generates a random number on [0,0xffffffff]-interval */ 116 | unsigned long genrand_int32(void) 117 | { 118 | unsigned long y; 119 | static unsigned long mag01[2]={0x0UL, MATRIX_A}; 120 | /* mag01[x] = x * MATRIX_A for x=0,1 */ 121 | 122 | if (mti >= N) { /* generate N words at one time */ 123 | int kk; 124 | 125 | if (mti == N+1) /* if init_genrand() has not been called, */ 126 | init_genrand(5489UL); /* a default initial seed is used */ 127 | 128 | for (kk=0;kk> 1) ^ mag01[y & 0x1UL]; 131 | } 132 | for (;kk> 1) ^ mag01[y & 0x1UL]; 135 | } 136 | y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); 137 | mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL]; 138 | 139 | mti = 0; 140 | } 141 | 142 | y = mt[mti++]; 143 | 144 | /* Tempering */ 145 | y ^= (y >> 11); 146 | y ^= (y << 7) & 0x9d2c5680UL; 147 | y ^= (y << 15) & 0xefc60000UL; 148 | y ^= (y >> 18); 149 | 150 | return y; 151 | } 152 | 153 | /* generates a random number on [0,0x7fffffff]-interval */ 154 | long genrand_int31(void) 155 | { 156 | return (long)(genrand_int32()>>1); 157 | } 158 | 159 | /* generates a random number on [0,1]-real-interval */ 160 | double genrand_real1(void) 161 | { 162 | return genrand_int32()*(1.0/4294967295.0); 163 | /* divided by 2^32-1 */ 164 | } 165 | 166 | /* generates a random number on [0,1)-real-interval */ 167 | double genrand_real2(void) 168 | { 169 | return genrand_int32()*(1.0/4294967296.0); 170 | /* divided by 2^32 */ 171 | } 172 | 173 | /* generates a random number on (0,1)-real-interval */ 174 | double genrand_real3(void) 175 | { 176 | return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0); 177 | /* divided by 2^32 */ 178 | } 179 | 180 | /* generates a random number on [0,1) with 53-bit resolution*/ 181 | double genrand_res53(void) 182 | { 183 | unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6; 184 | return(a*67108864.0+b)*(1.0/9007199254740992.0); 185 | } 186 | }; 187 | } 188 | #endif 189 | -------------------------------------------------------------------------------- /include/third-party/mersenne/example.cpp: -------------------------------------------------------------------------------- 1 | // example.cpp 2 | // Examples of random number generation with MersenneTwister.h 3 | // Richard J. Wagner 27 September 2009 4 | 5 | #include 6 | #include 7 | #include "MersenneTwister.h" 8 | 9 | using namespace std; 10 | 11 | int main( int argc, char * const argv[] ) 12 | { 13 | // A Mersenne Twister random number generator 14 | // can be declared with a simple 15 | 16 | MTRand mtrand1; 17 | 18 | // and used with 19 | 20 | double a = mtrand1(); 21 | 22 | // or 23 | 24 | double b = mtrand1.rand(); 25 | 26 | cout << "Two real numbers in the range [0,1]: "; 27 | cout << a << ", " << b << endl; 28 | 29 | // Those calls produced the default of floating-point numbers 30 | // in the range 0 to 1, inclusive. We can also get integers 31 | // in the range 0 to 2^32 - 1 (4294967295) with 32 | 33 | unsigned long c = mtrand1.randInt(); 34 | 35 | cout << "An integer in the range [0," << 0xffffffffUL; 36 | cout << "]: " << c << endl; 37 | 38 | // Or get an integer in the range 0 to n (for n < 2^32) with 39 | 40 | int d = mtrand1.randInt( 42 ); 41 | 42 | cout << "An integer in the range [0,42]: " << d << endl; 43 | 44 | // We can get a real number in the range 0 to 1, excluding 45 | // 1, with 46 | 47 | double e = mtrand1.randExc(); 48 | 49 | cout << "A real number in the range [0,1): " << e << endl; 50 | 51 | // We can get a real number in the range 0 to 1, excluding 52 | // both 0 and 1, with 53 | 54 | double f = mtrand1.randDblExc(); 55 | 56 | cout << "A real number in the range (0,1): " << f << endl; 57 | 58 | // The functions rand(), randExc(), and randDblExc() can 59 | // also have ranges defined just like randInt() 60 | 61 | double g = mtrand1.rand( 2.5 ); 62 | double h = mtrand1.randExc( 10.0 ); 63 | double i = 12.0 + mtrand1.randDblExc( 8.0 ); 64 | 65 | cout << "A real number in the range [0,2.5]: " << g << endl; 66 | cout << "One in the range [0,10.0): " << h << endl; 67 | cout << "And one in the range (12.0,20.0): " << i << endl; 68 | 69 | // The distribution of numbers over each range is uniform, 70 | // but it can be transformed to other useful distributions. 71 | // One common transformation is included for drawing numbers 72 | // in a normal (Gaussian) distribution 73 | 74 | cout << "A few grades from a class with a 52 pt average "; 75 | cout << "and a 9 pt standard deviation:" << endl; 76 | for( int student = 0; student < 20; ++student ) 77 | { 78 | double j = mtrand1.randNorm( 52.0, 9.0 ); 79 | cout << ' ' << int(j); 80 | } 81 | cout << endl; 82 | 83 | // Random number generators need a seed value to start 84 | // producing a sequence of random numbers. We gave no seed 85 | // in our declaration of mtrand1, so one was automatically 86 | // generated from the system clock (or the operating system's 87 | // random number pool if available). Alternatively we could 88 | // provide our own seed. Each seed uniquely determines the 89 | // sequence of numbers that will be produced. We can 90 | // replicate a sequence by starting another generator with 91 | // the same seed. 92 | 93 | MTRand mtrand2a( 1973 ); // makes new MTRand with given seed 94 | 95 | double k1 = mtrand2a(); // gets the first number generated 96 | 97 | MTRand mtrand2b( 1973 ); // makes an identical MTRand 98 | 99 | double k2 = mtrand2b(); // and gets the same number 100 | 101 | cout << "These two numbers are the same: "; 102 | cout << k1 << ", " << k2 << endl; 103 | 104 | // We can also restart an existing MTRand with a new seed 105 | 106 | mtrand2a.seed( 1776 ); 107 | mtrand2b.seed( 1941 ); 108 | 109 | double l1 = mtrand2a(); 110 | double l2 = mtrand2b(); 111 | 112 | cout << "Re-seeding gives different numbers: "; 113 | cout << l1 << ", " << l2 << endl; 114 | 115 | // But there are only 2^32 possible seeds when we pass a 116 | // single 32-bit integer. Since the seed dictates the 117 | // sequence, only 2^32 different random number sequences will 118 | // result. For applications like Monte Carlo simulation we 119 | // might want many more. We can seed with an array of values 120 | // rather than a single integer to access the full 2^19937-1 121 | // possible sequences. 122 | 123 | MTRand::uint32 seed[ MTRand::N ]; 124 | for( int n = 0; n < MTRand::N; ++n ) 125 | seed[n] = 23 * n; // fill with anything 126 | MTRand mtrand3( seed ); 127 | 128 | double m1 = mtrand3(); 129 | double m2 = mtrand3(); 130 | double m3 = mtrand3(); 131 | 132 | cout << "We seeded this sequence with 19968 bits: "; 133 | cout << m1 << ", " << m2 << ", " << m3 << endl; 134 | 135 | // Again we will have the same sequence every time we run the 136 | // program. Make the array with something that will change 137 | // to get unique sequences. On a Linux system, the default 138 | // auto-initialization routine takes a unique sequence from 139 | // /dev/urandom. 140 | 141 | // For cryptography, also remember to hash the generated 142 | // random numbers. Otherwise the internal state of the 143 | // generator can be learned after reading 624 values. 144 | 145 | // We might want to save the state of the generator at an 146 | // arbitrary point after seeding so a sequence could be 147 | // replicated. An MTRand object can be saved into an array 148 | // or to a stream. 149 | 150 | MTRand mtrand4; 151 | 152 | // The array must be of type uint32 and length SAVE. 153 | 154 | MTRand::uint32 randState[ MTRand::SAVE ]; 155 | 156 | mtrand4.save( randState ); 157 | 158 | // A stream is convenient for saving to a file. 159 | 160 | ofstream stateOut( "state.dat" ); 161 | if( stateOut ) 162 | { 163 | stateOut << mtrand4; 164 | stateOut.close(); 165 | } 166 | 167 | unsigned long n1 = mtrand4.randInt(); 168 | unsigned long n2 = mtrand4.randInt(); 169 | unsigned long n3 = mtrand4.randInt(); 170 | 171 | cout << "A random sequence: " 172 | << n1 << ", " << n2 << ", " << n3 << endl; 173 | 174 | // And loading the saved state is as simple as 175 | 176 | mtrand4.load( randState ); 177 | 178 | unsigned long o4 = mtrand4.randInt(); 179 | unsigned long o5 = mtrand4.randInt(); 180 | unsigned long o6 = mtrand4.randInt(); 181 | 182 | cout << "Restored from an array: " 183 | << o4 << ", " << o5 << ", " << o6 << endl; 184 | 185 | ifstream stateIn( "state.dat" ); 186 | if( stateIn ) 187 | { 188 | stateIn >> mtrand4; 189 | stateIn.close(); 190 | } 191 | 192 | unsigned long p7 = mtrand4.randInt(); 193 | unsigned long p8 = mtrand4.randInt(); 194 | unsigned long p9 = mtrand4.randInt(); 195 | 196 | cout << "Restored from a stream: " 197 | << p7 << ", " << p8 << ", " << p9 << endl; 198 | 199 | // We can also duplicate a generator by copying 200 | 201 | MTRand mtrand5( mtrand3 ); // copy upon construction 202 | 203 | double q1 = mtrand3(); 204 | double q2 = mtrand5(); 205 | 206 | cout << "These two numbers are the same: "; 207 | cout << q1 << ", " << q2 << endl; 208 | 209 | mtrand5 = mtrand4; // copy by assignment 210 | 211 | double r1 = mtrand4(); 212 | double r2 = mtrand5(); 213 | 214 | cout << "These two numbers are the same: "; 215 | cout << r1 << ", " << r2 << endl; 216 | 217 | // In summary, the recommended common usage is 218 | 219 | MTRand mtrand6; // automatically generate seed 220 | double s = mtrand6(); // real number in [0,1] 221 | double t = mtrand6.randExc(0.5); // real number in [0,0.5) 222 | unsigned long u = mtrand6.randInt(10); // integer in [0,10] 223 | 224 | // with the << and >> operators used for saving to and 225 | // loading from streams if needed. 226 | 227 | cout << "Your lucky number for today is " 228 | << s + t * u << endl; 229 | 230 | return 0; 231 | } 232 | -------------------------------------------------------------------------------- /include/core/JamomaAudioObject.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | @ingroup jamoma2 4 | 5 | @brief Create Jamoma AudioObject instances. 6 | 7 | @details Parent class for all AudioObjects within the Jamoma library. 8 | Defines common features such as frameCount, sampleRate and operator(). 9 | 10 | @author Timothy Place, Nathan Wolek 11 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 12 | @license This project is released under the terms of the MIT License. 13 | */ 14 | 15 | #pragma once 16 | 17 | #include "JamomaObject.h" 18 | #include "JamomaSample.h" 19 | 20 | 21 | namespace Jamoma { 22 | 23 | 24 | class AudioObject; 25 | 26 | 27 | /** The AdaptingSampleBundle is a SampleBundle that automatically resizes its number of channels 28 | when the channelCount parameter of the owning AudioObject changes. */ 29 | class AdaptingSampleBundle : public SampleBundle { 30 | AudioObject* mOwner; 31 | 32 | public: 33 | 34 | /** Must pass a pointer to the owning object, i.e. "this", so that this object can register for notifications. 35 | @param AudioObject's "this" pointer 36 | */ 37 | AdaptingSampleBundle(AudioObject* owner); 38 | }; 39 | 40 | 41 | /** The base class for objects that serve as audio unit generators. 42 | Calculations are done by overriding the () operator for individual samples or bundles of samples. 43 | Each AudioObject provides SharedSampleBundleGroup to buffer it's own output. 44 | */ 45 | class AudioObject : public Object { 46 | protected: 47 | 48 | /** Each AudioObject provides SharedSampleBundleGroup to buffer it's own output. 49 | Before you use this you should make a local copy to ensure that the reference count doesn't go to zero while you are writing your output. 50 | A copy of a SharedSampleBundleGroup is a copy of a shared pointer, not a copy of the data in the bundle group. 51 | */ 52 | SharedSampleBundleGroup mOutput; 53 | 54 | 55 | private: 56 | friend class AdaptingSampleBundle; 57 | 58 | /** We maintain a list of AdaptingSampleBundles so that we can notify them when the channelCount parameter changes */ 59 | std::vector mAdaptingSampleBundles; 60 | 61 | /** Called internally by the AdaptingSampleBundle constructor to register the bundle for notifications. */ 62 | void registerAdaptingSampleBundle(AdaptingSampleBundle* asb) 63 | { 64 | mAdaptingSampleBundles.push_back(asb); 65 | } 66 | 67 | 68 | public: 69 | 70 | /** Default constructor. */ 71 | AudioObject() = default; 72 | 73 | virtual ~AudioObject() 74 | {} 75 | 76 | 77 | /** The channelCount parameter is universal to all AudioObjects. 78 | It is used by any AdaptingSampleBundles and also for generators that don't take an input signal. 79 | TODO: should get an intelligent default from the graph that owns this object (if there is a one) 80 | */ 81 | Parameter channelCount = { this, "channelCount", 1, 82 | Setter ([this]{ 83 | mOutput.resizeChannels(channelCount); 84 | 85 | // resize all AdaptingSampleVector instances for this class 86 | for (auto* asb : mAdaptingSampleBundles) 87 | asb->resizeChannels(channelCount); 88 | }) 89 | }; 90 | 91 | 92 | /** The frameCount parameter is used for initializing output to avoid resizing at perform time. 93 | It is also important for generator units that don't take an input AudioBundle. 94 | TODO: should get an intelligent default from the graph that owns this object (if there is a one) 95 | */ 96 | Parameter frameCount = { this, "frameCount", 1, 97 | Setter([this]{ mOutput.resizeFrames(frameCount); }) 98 | }; 99 | 100 | 101 | /** The sampleRate parameter may not be used in all cases, but provides a standard interface for when it is needed. 102 | TODO: need to deliver notifications, e.g. to recalculate filter coefficients in subclasses 103 | TODO: should get an intelligent default from the graph that owns this object (if there is a one) 104 | */ 105 | Parameter, NativeUnit::None> sampleRate = { this, 106 | "sampleRate", 107 | 96000, 108 | Range(1,96000), 109 | Setter([this]{ 110 | //mSampleRate = sampleRate; 111 | }) 112 | }; 113 | 114 | 115 | /** Convenience wrapper for adapting an AudioObject and it's output. 116 | @param x The SampleBundle whose dimensions will be used to set this AudioObject's dimensions. 117 | @return This AudioObject's output bundle. 118 | */ 119 | auto adapt(const SampleBundle& x) 120 | { 121 | mOutput.adapt(x); 122 | frameCount = (int)x.frameCount(); 123 | channelCount = (int)x.channelCount(); 124 | return mOutput; 125 | } 126 | 127 | 128 | /** Calculate a single sample. 129 | Subclasses must override this. 130 | This is typically where the meet of your algorithm will be defined. 131 | @param x An input sample 132 | @return An output sample 133 | */ 134 | virtual Sample operator()(const Sample x) = 0; 135 | 136 | 137 | /** Calculate a bundle of samples. 138 | Subclasses must override this. 139 | Typically the logistics of getting the required samples for the channels and vectors will happen in this function and then be handed-off 140 | to the above single-sample function (which can be inlined by the compiler). 141 | Output should be buffered (written) to mOutput, and then mOutput returned from this method. 142 | @param x An input bundle 143 | @return This classes' output bundle group 144 | */ 145 | virtual SharedSampleBundleGroup operator()(const SampleBundle& x) = 0; 146 | 147 | 148 | /** Calculate an entire SampleBundleGroup. 149 | Only classes that need to accept multiple SampleBundles for input (e.g. a crossfader or IFFT operator) will need to override this method. 150 | The default provided here will suffice for most subclasses. 151 | @param x An input bundle 152 | @return This classes' output bundle group 153 | */ 154 | virtual SharedSampleBundleGroup operator()(const SharedSampleBundleGroup x) 155 | { 156 | return (*this)(x[0]); 157 | } 158 | 159 | 160 | /** Convience method for doing Hertz-to-radians conversion based upon the current sampleRate 161 | @param hz The input in hertz. 162 | @return The output in radians. 163 | */ 164 | double hertzToRadians(const double hz) 165 | { 166 | assert(sampleRate != 0); 167 | return(hz * kTwoPi / (double)sampleRate); 168 | } 169 | }; 170 | 171 | 172 | #pragma mark - 173 | #pragma mark Implementation of AdaptingSampleBundle 174 | 175 | inline AdaptingSampleBundle::AdaptingSampleBundle(AudioObject* owner) 176 | : mOwner(owner) 177 | { 178 | mOwner->registerAdaptingSampleBundle(this); // register with owner so we can get notifications 179 | } 180 | 181 | 182 | #pragma mark - 183 | #pragma mark Utilities that likely belong elsewhere 184 | 185 | 186 | /** Convert linear amplitude into decibels. 187 | @param input The linear gain value to convert. 188 | @return Converted decibel value. 189 | */ 190 | inline double linearGainToDecibels(double input) 191 | { 192 | if (input < 0.0) 193 | return 0.0; 194 | else 195 | return(20.0 * (log10(input))); 196 | } 197 | 198 | 199 | /** Convert decibels into linear ampliude. 200 | @param input The decibel value to convert. 201 | @return The converted linear gain value. 202 | */ 203 | inline double decibelsToLinearGain(double input) 204 | { 205 | return(pow(10.0, (input / 20.0))); 206 | } 207 | 208 | 209 | 210 | } // namespace Jamoma 211 | -------------------------------------------------------------------------------- /include/core/JamomaParameter.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | @ingroup jamoma2 4 | 5 | @brief Define a parameter of a JamomaObject 6 | 7 | @author Timothy Place 8 | @copyright Copyright (c) 2005-2015 The Jamoma Group, http://jamoma.org. 9 | @license This project is released under the terms of the MIT License. 10 | */ 11 | 12 | #pragma once 13 | 14 | #include "JamomaObject.h" 15 | 16 | namespace Jamoma { 17 | 18 | 19 | /** ParameterBase allows us a unified means for referencing a Parameter of any template-specialization. 20 | All Parameters must be defined using a Parameter specialization and this base class is for internal use only. 21 | */ 22 | class ParameterBase { 23 | protected: 24 | Object* mOwner; ///< The owning Jamoma::Object to which this Parameter belongs. 25 | String mName; ///< The name of this Parameter as it would be addressed dynamically. 26 | Synopsis mSynopsis = ""; ///< A description of what this Parameter represents. 27 | Setter mSetter = nullptr; ///< A function to be executed after the parameter's value has been set. 28 | std::vector mObservers; ///< Objects receiving notifications when this parameter has been set. 29 | 30 | // TODO: the above raw pointer will lead to dangling references ?!?!?!?! 31 | 32 | ParameterBase(Object* owner, const String& name ) noexcept 33 | : mOwner(owner) 34 | , mName(name) 35 | {} 36 | 37 | 38 | virtual ~ParameterBase() 39 | {} 40 | 41 | public: 42 | String& name() { 43 | return mName; 44 | } 45 | 46 | 47 | friend bool operator == (const ParameterBase& lhs, const char* rhs) { 48 | return lhs.mName == rhs; 49 | } 50 | 51 | 52 | virtual ParameterBase& operator = (const VarBase& input) = 0; 53 | 54 | 55 | void addObserver(Observer& anObserver) { 56 | mObservers.push_back(&anObserver); 57 | } 58 | 59 | 60 | void removeObserver(Observer& anObserver) { 61 | // documentation of the below: https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom 62 | mObservers.erase(std::remove(mObservers.begin(), mObservers.end(), &anObserver), mObservers.end()); 63 | } 64 | 65 | }; 66 | 67 | 68 | /** Define a parameter of a Jamoma::Object. 69 | @tparam T The C++ data type of the Parameter (e.g. int, double, Jamoma::Sample, etc.) 70 | @tparam LimitType (optional) The name of a class defining behavior applied to received values that are out of Range (e.g. Jamoma::Limit::Clip). 71 | @tparam DataspaceType (optional) The name of a class defining a dataspace unit for the parameter so that values received in alternate units may be converted correctly. 72 | */ 73 | template < class T, 74 | class LimitType = Limit::None, 75 | class DataspaceType = Dataspace::None 76 | > 77 | class Parameter : public ParameterBase { 78 | public: 79 | 80 | Parameter() = delete; // constructor: can't create an unitialized Parameter 81 | 82 | 83 | private: 84 | /** constructor utility: handle an argument defining a parameter's synopsis 85 | */ 86 | template 87 | constexpr typename std::enable_if::value>::type assignFromArgument(const U& arg) noexcept { 88 | mSynopsis = arg; 89 | } 90 | 91 | /** constructor utility: handle an argument defining a parameter's range 92 | */ 93 | template 94 | constexpr typename std::enable_if>::value>::type assignFromArgument(const U& arg) noexcept { 95 | mRange = arg; 96 | } 97 | 98 | /** constructor utility: handle an argument defining a parameter's setter function 99 | */ 100 | template 101 | constexpr typename std::enable_if::value>::type assignFromArgument(const U& arg) noexcept { 102 | mSetter = arg; 103 | } 104 | 105 | /** constructor utility: empty argument handling (required for recursive variadic templates) 106 | */ 107 | constexpr void handleArguments() noexcept { 108 | ; 109 | } 110 | 111 | /** constructor utility: handle N arguments of any type by recursively working through them 112 | and matching them to the type-matched routine above. 113 | */ 114 | template 115 | constexpr void handleArguments(FIRST_ARG const& first, REMAINING_ARGS const& ...args) noexcept { 116 | assignFromArgument(first); 117 | if (sizeof...(args)) 118 | handleArguments(args...); // recurse 119 | } 120 | 121 | 122 | public: 123 | /** constructor 124 | @param owner A pointer to the object instance to whom the parameter belongs (pass `this` from your class) 125 | @param name A string specifying the name of the parmeter when dynamically addressed or inspected 126 | @param initial Initial value for the parameter 127 | @param ...args N arguments specifying optional properties of a parameter such as Setter, Range, Synopsis, etc. 128 | */ 129 | template 130 | constexpr Parameter(Object* owner, const String& name, T initial, ARGS...args) noexcept 131 | : ParameterBase(owner, name) 132 | , mValue(initial) 133 | { 134 | handleArguments(args...); 135 | } 136 | 137 | 138 | /** constructor for when default value is defined using a dataspace conversion 139 | @param owner A pointer to the object instance to whom the parameter belongs (pass `this` from your class) 140 | @param name A string specifying the name of the parmeter when dynamically addressed or inspected 141 | @param initial Initial value for the parameter 142 | @param ...args N arguments specifying optional properties of a parameter such as Setter, Range, Synopsis, etc. 143 | */ 144 | template 145 | constexpr Parameter(Object* owner, const String& name, const std::pair& initial, ARGS...args) noexcept 146 | : ParameterBase(owner, name) 147 | { 148 | handleArguments(args...); 149 | (*this) = initial; 150 | } 151 | 152 | 153 | /** Set the value of the parameter 154 | */ 155 | Parameter& operator = (T input) { 156 | set(input); 157 | return *this; 158 | } 159 | 160 | 161 | /** Set the value of the parameter using the specified unit, which will be converted automatically if needed. 162 | */ 163 | Parameter& operator = (const std::pair input) { 164 | set(input.first, input.second); 165 | return *this; 166 | } 167 | 168 | 169 | /** Set the value of the parameter from a generic Var 170 | */ 171 | // TODO: if a Var has 2 members then do we use the last one as a unit? perhaps it needs some metadata so that we know? 172 | Parameter& operator = (const VarBase& input) { 173 | set(input); 174 | return *this; 175 | } 176 | 177 | 178 | /** Set the *value* of the parameter from another Parameter 179 | */ 180 | Parameter& operator = (const Parameter& input) { 181 | set(input.mValue); 182 | return *this; 183 | } 184 | 185 | 186 | /** Get the value of the Parameter 187 | */ 188 | operator T() const noexcept { 189 | return this->mValue; 190 | } 191 | 192 | 193 | T& value() { 194 | return mValue; 195 | } 196 | 197 | 198 | private: 199 | 200 | /** worker fn for setters: naked values have no dataspace unit specified, so set them directly 201 | */ 202 | constexpr void set(T input) { 203 | this->mValue = LimitType::apply(input, this->mRange.first, this->mRange.second); 204 | if (this->mSetter) 205 | this->mSetter(); 206 | for (auto& observer : this->mObservers) 207 | (*observer)(); 208 | } 209 | 210 | 211 | /** worker fn for setters: set values using a dataspace conversion 212 | */ 213 | constexpr void set(T input, Unit unit) { 214 | set(mDataspace(input, (uint32_t)unit)); 215 | } 216 | 217 | 218 | T mValue; ///< the actual value storage 219 | Range mRange; ///< range of the parameter 220 | DataspaceType mDataspace; ///< dataspace of the parameter 221 | }; 222 | 223 | } // namespace Jamoma 224 | --------------------------------------------------------------------------------