From 494c61c793c5a1c0642128e77cf7bcb928583303 Mon Sep 17 00:00:00 2001 From: gogins Date: Tue, 21 Nov 2023 10:13:47 -0500 Subject: [PATCH 1/5] Local libCsnd (#13). --- CMakeLists.txt | 9 +- CsoundAC/CMakeLists.txt | 6 +- CsoundAC/CMaskNode.hpp | 219 ++++++ CsoundAC/CppSound.cpp | 221 ++++++ CsoundAC/CsoundFile.cpp | 1275 +++++++++++++++++++++++++++++++++ CsoundAC/CsoundFile.hpp | 222 ++++++ CsoundAC/Soundfile.cpp | 311 +++----- CsoundAC/Soundfile.hpp | 143 ++-- CsoundAC/cs_glue.cpp | 1345 +++++++++++++++++++++++++++++++++++ CsoundAC/cs_glue.hpp | 707 ++++++++++++++++++ CsoundAC/csound.asd | 19 + CsoundAC/csound.lisp | 394 ++++++++++ CsoundAC/filebuilding.cpp | 226 ++++++ CsoundAC/filebuilding.h | 211 ++++++ CsoundAC/filebuilding.lisp | 150 ++++ CsoundAC/pyMsgCb.cpp | 66 ++ CsoundAC/pyMsgCb_stub.cpp | 10 + CsoundAC/sb-csound.asd | 19 + CsoundAC/sb-csound.lisp | 178 +++++ playpen/playpen.ini | 2 +- tests/Parachronic-Piano.cpp | 266 +++++++ 21 files changed, 5671 insertions(+), 328 deletions(-) create mode 100644 CsoundAC/CMaskNode.hpp create mode 100644 CsoundAC/CppSound.cpp create mode 100644 CsoundAC/CsoundFile.cpp create mode 100644 CsoundAC/CsoundFile.hpp create mode 100644 CsoundAC/cs_glue.cpp create mode 100644 CsoundAC/cs_glue.hpp create mode 100644 CsoundAC/csound.asd create mode 100644 CsoundAC/csound.lisp create mode 100644 CsoundAC/filebuilding.cpp create mode 100644 CsoundAC/filebuilding.h create mode 100644 CsoundAC/filebuilding.lisp create mode 100644 CsoundAC/pyMsgCb.cpp create mode 100644 CsoundAC/pyMsgCb_stub.cpp create mode 100644 CsoundAC/sb-csound.asd create mode 100644 CsoundAC/sb-csound.lisp create mode 100644 tests/Parachronic-Piano.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0aed24be27..5858e6627b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.10) project(csound-ac) message("CMAKE BUILD SYSTEM FOR CSOUND-AC") @@ -25,7 +25,7 @@ set(CPACK_ARCHIVE_COMPONENT_INSTALL ON) set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME "csound-ac") add_definitions(-Dlinux) -set(APIVERSION "6.0") +set(APIVERSION "7.0") set(CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/local-linux") list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules") list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/dependencies/csound/cmake/Modules") @@ -73,11 +73,6 @@ message("CSOUND_INCLUDE_DIRS: ${CSOUND_INCLUDE_DIRS}") message("CSOUND_INCLUDE_PATH: ${CSOUND_INCLUDE_PATH}") include_directories("/Library/Frameworks/CsoundLib64.framework/Versions/6.0/Headers/") find_library(LIBSNDFILE_LIBRARY sndfile REQUIRED) -# For WebAssembly, csnd6 is not required, on other platforms, it is. -if("${CMAKE_SYSTEM_NAME}" STREQUAL "Emscripten") -else() -find_library(CSND6_LIBRARY csnd6) -endif() set(EIGEN3_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/dependencies/eigen") message("[DEBUG] EIGEN3_INCLUDE_DIRS: ${EIGEN3_INCLUDE_DIRS}") find_package(OpenCV) diff --git a/CsoundAC/CMakeLists.txt b/CsoundAC/CMakeLists.txt index 30f003c08c..1541244ae1 100644 --- a/CsoundAC/CMakeLists.txt +++ b/CsoundAC/CMakeLists.txt @@ -36,6 +36,8 @@ if(BUILD_CSOUND_AC) Counterpoint.cpp CounterpointMain.cpp CounterpointNode.cpp + CppSound.cpp + CsoundFile.cpp Event.cpp Lindenmayer.cpp MCRM.cpp @@ -95,7 +97,7 @@ endif() LIBRARY_OUTPUT_DIRECTORY "${BUILD_LIB_DIR}" ARCHIVE_OUTPUT_DIRECTORY "${BUILD_LIB_DIR}") - target_link_libraries(libCsoundAC PRIVATE ${MUSICXML2_LIBRARY} ${CSND6_LIBRARY} ${CSOUND_LIBRARIES} ${OpenCV_LIBRARIES} ${LIBSNDFILE_LIBRARY}) + target_link_libraries(libCsoundAC PRIVATE ${MUSICXML2_LIBRARY} ${CSOUND_LIBRARIES} ${OpenCV_LIBRARIES} ${LIBSNDFILE_LIBRARY}) if(WIN32) # for MSYS2/mingw64 # mingw64 needs this to create a valid .pyd. @@ -139,7 +141,7 @@ endif() swig_add_library(CsoundAC LANGUAGE python SOURCES CsoundAC.i) - swig_link_libraries(CsoundAC libCsoundAC ${MUSICXML2_LIBRARY} ${CSND6_LIBRARY} ${CSOUND_LIBRARIES} ${OpenCV_LIBRARIES} ${LIBSNDFILE_LIBRARY} ${Python3_LIBRARIES}) + swig_link_libraries(CsoundAC libCsoundAC ${MUSICXML2_LIBRARY} ${CSOUND_LIBRARIES} ${OpenCV_LIBRARIES} ${LIBSNDFILE_LIBRARY} ${Python3_LIBRARIES}) target_include_directories(${SWIG_MODULE_CsoundAC_REAL_NAME} PRIVATE ${EIGEN3_INCLUDE_DIRS} ${Boost_INCLUDE_DIR} ${CSOUND_SOURCE_HOME}/include) if(APPLE) target_include_directories(${SWIG_MODULE_CsoundAC_REAL_NAME} SYSTEM PRIVATE ${LIBSNDFILE_INCLUDE_DIR}) diff --git a/CsoundAC/CMaskNode.hpp b/CsoundAC/CMaskNode.hpp new file mode 100644 index 0000000000..2972f24288 --- /dev/null +++ b/CsoundAC/CMaskNode.hpp @@ -0,0 +1,219 @@ +#ifndef CMASKNODE_HPP_INCLUDED +#define CMASKNODE_HPP_INCLUDED +/* + * C S O U N D + * + * L I C E N S E + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "Platform.hpp" +#ifdef SWIG +%module CsoundAC +%{ +#include "Conversions.hpp" +#include "Event.hpp" +#include "Score.hpp" +#include "ScoreNode.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +%} +%include "std_string.i" +%include "std_vector.i" +%template(EventVector) std::vector; +#else +#include "Conversions.hpp" +#include "Event.hpp" +#include "Score.hpp" +#include "ScoreNode.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace cmask { +using namespace std; +// Andre Bartetzki's original code is bodily included into this file +// rather than adding his code to the CsoundAC build system. +#include "../dependencies/cmask/source/globals.h" +#if !defined(NL) + #define NL "\n" +#endif +#include "../dependencies/cmask/source/event.h" +#include "../dependencies/cmask/source/field.h" +#include "../dependencies/cmask/source/fileio.h" +#include "../dependencies/cmask/source/gen.h" +#include "../dependencies/cmask/source/items.h" +#include "../dependencies/cmask/source/mask.h" +#include "../dependencies/cmask/source/parser.h" +#include "../dependencies/cmask/source/quant.h" +#include "../dependencies/cmask/source/tables.h" +#include "../dependencies/cmask/source/utils.h" +#include "../dependencies/cmask/source/cmask.cpp" +#include "../dependencies/cmask/source/event.cpp" +#include "../dependencies/cmask/source/field.cpp" +#include "../dependencies/cmask/source/fileio.cpp" +#include "../dependencies/cmask/source/gen.cpp" +#include "../dependencies/cmask/source/items.cpp" +#include "../dependencies/cmask/source/mask.cpp" +#include "../dependencies/cmask/source/parser.cpp" +#include "../dependencies/cmask/source/quant.cpp" +#include "../dependencies/cmask/source/tables.cpp" +#include "../dependencies/cmask/source/utils.cpp" +}; +#endif + +namespace csound +{ +/** + * Uses the CMask library for tendency masks to generate events as a Csound + * score in the format determined by the CMask parameters text. The generated + * Csound score is also translated to a Silence score in the Silence music + * graph. This only works if at least the first 5 pfields in the Csound score + * (instrument number, time, duration, MIDI key, MIDI velocity) follow the + * Silence conventions declared in Event.hpp. + * + * Score literals in the CMask parameters are simply appended to the Csound + * score header in the Score object, and likewise are copied directly and + * without any processing to the translated Csound Score. + * + * For documentation and examples for CMask, see [Andre Bartetzki's original + * documentation](https://www.bartetzki.de/de/software.html). + */ + +SILENCE_PUBLIC class CMaskNode : public ScoreNode { + public: + virtual std::string getParametersText() const { + return parameters_text; + } + virtual void setParametersText(const std::string ¶meters_text_) { + parameters_text = parameters_text_; + } + virtual void generateLocally() { + cmask::frandinit(); + cmask::scanner scanner_; + //std::cout << "CMask parameters: " << std::endl << parameters_text << std::endl; + // Rather than monkey with the existing code, + // we just use temporary files. + char parameters_filename[0x100]; + std::tmpnam(parameters_filename); + std::string score_filename = parameters_filename; + score_filename.append(".sco"); + std::ofstream parameters_file(parameters_filename); + parameters_file << parameters_text->data << std::endl; + parameters_file.close(); + scanner_.scn(parameters_filename, const_cast(score_filename.c_str())); + scanner_.analyze(); + std::ifstream score_file(score_filename); + std::stringstream score_buffer; + score_buffer << score_file.rdbuf(); + score_file.close(); + score_text = score_buffer.str(); + //std::cout << "CMask generated: " << std::endl << score_text << std::endl; + std::remove(parameters_filename); + std::remove(score_filename.c_str()); + translate_to_silence(); + } + /** + * Maps Silence score fields to Csound "i" statement pfields. As noted + * above, the CMask fields _must_ be configured to match the Silence + * conventions for Csound scores. The first 5 fields are required. + * No more than 10 fields are used. + * + * i_instrument = p1 + * i_time = p2 + * i_duration = p3 + * i_midi_key = p4 + * i_midi_velocity = p5 + * k_space_front_to_back = p6 ; Ambisonic X + * k_space_left_to_right = p7 ; Ambisonic Y + * k_space_bottom_to_top = p8; Ambisonic Z + * i_phase = p9 + * i_pitches = p10 ; Mason number + */ + virtual void translate_to_silence() { + score.clear(); + std::stringstream score_stream; + score_stream << score_text; + for (std::string line; std::getline(input, line); ) { + std::stringstream line_stream(line); + // All lines that don't begin with "i" are treated as + // Csound score literals and appended to the score header. + if (line.begins_with("i") == false) { + score.appendToCsoundScoreHeader(line); + score.appendToCsoundScoreHeader("\n"); + } else { + csound::Event event; + int index = 0; + std::string token; + while (line_stream >> token) { + switch (index) { + case 0: + event.setStatus(144); + break; + case 1: + event.setInstrument(std::stof(token)); + break; + case 2: + event.setTime(std::stof(token)); + break; + case 3: + event.setDuration(std::stof(token)); + break; + case 4: + event.setKey(std::stof(token)); + break; + case 6: + event.setDepth(std::stof(token)); + break; + case 7: + event.setPan(std::stof(token)); + break; + case 8: + event.setHeight(std::stof(token)); + break; + case 9: + event.setPhase(std::stof(token)); + break; + case 10: + event.setPitches(std::stof(token)); + break; + } + } + score.append(event); + } + } + } + protected: + std::string parameters_text; + std::string score_text; + } +}; \ No newline at end of file diff --git a/CsoundAC/CppSound.cpp b/CsoundAC/CppSound.cpp new file mode 100644 index 0000000000..f90d0db8ac --- /dev/null +++ b/CsoundAC/CppSound.cpp @@ -0,0 +1,221 @@ +/* + * C S O U N D + * + * L I C E N S E + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "CppSound.hpp" + +#if !defined(__BUILDING_LIBCSOUND) +#define __BUILDING_LIBCSOUND +#endif +///#include + +#include +#include +#include + +extern "C" int argdecode(CSOUND *csound, int argc, const char **argv_); + +/*CppSound::CppSound() : Csound(), + go(false), + isCompiled(false), + isPerforming(false), + spoutSize(0) +{ + + //SetHostData((CSOUND *)0); + +} +*/ +CppSound::~CppSound() +{ +} + +int CppSound::compile(int argc, const char **argv_) +{ + Message("BEGAN CppSound::compile(%d, %p)...\n", argc, argv_); + int returnValue = 0; + go = false; +/* csound->orcname_mode = 1; + // Changed to use only internally stored Csound orchestra and score. + */ + returnValue = csoundCompileOrc(csound, getOrchestra().c_str()); + returnValue = csoundReadScore(csound, getScore().c_str()); + for (int i = 0; (size_t) i < argv.size(); ++i) { + Message("arg %3d: %s\n", i, argv[i]); + csoundSetOption(csound, argv[i]); + } + returnValue = csoundStart(csound); + spoutSize = GetKsmps() * GetNchnls() * sizeof(MYFLT); + if(returnValue) + { + isCompiled = false; + } + else + { + const char *outfilename = GetOutputName(); + if (outfilename) { + renderedSoundfile = outfilename; + } + isCompiled = true; + go = true; + } + Message("ENDED CppSound::compile.\n"); + return returnValue; +} + +int CppSound::compile() +{ + Message("BEGAN CppSound::compile()...\n"); + if(getCommand().length() <= 0) + { + Message("No Csound command.\n"); + return 0; + } + scatterArgs(getCommand(), const_cast< std::vector & >(args), const_cast< std::vector &>(argv)); + int returnValue = compile(argv.size(), (const char **) &argv.front()); + Message("ENDED CppSound::compile.\n"); + return returnValue; +} + +int CppSound::perform(int argc, const char **argv_) +{ + double beganAt = double(std::clock()) / double(CLOCKS_PER_SEC); + isCompiled = false; + go = false; + Message("BEGAN CppSound::perform(%d, %p)...\n", argc, argv_); + if(argc <= 0) + { + Message("ENDED CppSound::perform without compiling or performing.\n"); + return 0; + } + int result = compile(argc, argv_); + if(result == -1) + { + return result; + } + for(result = 0; (result == 0) && go; ) + { + result = PerformKsmps(); + } + cleanup(); + double endedAt = double(clock()) / double(CLOCKS_PER_SEC); + double elapsed = endedAt - beganAt; + Message("Elapsed time = %f seconds.\n", elapsed); + Message("ENDED CppSound::perform.\n"); + isCompiled = false; + isPerforming = false; + return 1; +} + +int CppSound::perform() +{ + int returnValue = 0; + std::string command = getCommand(); + std::string filename = getFilename(); + if(command.find("-") == 0) + { + const char *argv_[] = {"csound", filename.c_str(), 0}; + returnValue = perform(2, argv_); + } + else + { + scatterArgs(command, const_cast< std::vector & >(args), const_cast< std::vector &>(argv)); + returnValue = perform(args.size(), (const char **)&argv.front()); + } + return returnValue; +} + +void CppSound::stop() +{ + isCompiled = false; + isPerforming = false; + go = false; + Stop(); +} + +CSOUND *CppSound::getCsound() +{ + return csound; +} + +int CppSound::performKsmps() +{ + return PerformKsmps(); +} + +void CppSound::cleanup() +{ + Cleanup(); + Reset(); +} + +size_t CppSound::getSpoutSize() const +{ + return spoutSize; +} + +std::string CppSound::getOutputSoundfileName() const +{ + return renderedSoundfile; +} + +void CppSound::inputMessage(const char *istatement) +{ + InputMessage(istatement); +} + +void CppSound::write(const char *text) +{ + Message("%s", text); +} + +intptr_t CppSound::getThis() +{ + return (intptr_t) this; +} + +CsoundFile *CppSound::getCsoundFile() +{ + return dynamic_cast(this); +} + +bool CppSound::getIsCompiled() const +{ + return isCompiled; +} + +void CppSound::setIsPerforming(bool isPerforming) +{ + this->isPerforming = isPerforming; +} + +bool CppSound::getIsPerforming() const +{ + return isPerforming; +} + +bool CppSound::getIsGo() +{ + if(csound) { + if(GetSpin() && GetSpout()) { + return go; + } + } + return false; +} + diff --git a/CsoundAC/CsoundFile.cpp b/CsoundAC/CsoundFile.cpp new file mode 100644 index 0000000000..6fcbd1902b --- /dev/null +++ b/CsoundAC/CsoundFile.cpp @@ -0,0 +1,1275 @@ +/* + * C S O U N D + * + * L I C E N S E + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#if defined(MSVC) +#pragma warning(disable: 4786) +#endif +#include "CsoundFile.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(HAVE_MUSICXML2) +#include "elements.h" +#include "factory.h" +#include "xml.h" +#include "xmlfile.h" +#include "xml_tree_browser.h" +#include "xmlreader.h" +#include "midicontextvisitor.h" + +using namespace MusicXML2; +#endif + +void PUBLIC gatherArgs(int argc, const char **argv, std::string &commandLine) +{ + for(int i = 0; i < argc; i++) + { + if(i == 0) + { + commandLine = argv[i]; + } + else + { + commandLine += " "; + commandLine += argv[i]; + } + } +} + +void PUBLIC scatterArgs(const std::string line, + std::vector &args, std::vector &argv) +{ + args.clear(); + for (int i = 0; (size_t) i < argv.size(); ++i) { + char *arg = argv[i]; + if (arg) { + free(arg); + } + } + argv.clear(); + std::stringstream stream(line); + std::string token; + while (std::getline(stream, token, ' ')) { + if (!token.empty()) { + args.push_back(token); + argv.push_back(strdup(token.c_str())); + } + } +} + +std::string PUBLIC &trim(std::string &value) +{ + size_t i = value.find_first_not_of(" \n\r\t"); + if(i != value.npos) + { + value.erase(0, i); + } + else + { + value.erase(value.begin(), value.end()); + return value; + } + i = value.find_last_not_of(" \n\r\t"); + if(i != value.npos) + { + value.erase(i + 1, value.npos); + } + return value; +} + +std::string PUBLIC &trimQuotes(std::string &value) +{ + size_t i = value.find_first_not_of("\""); + if(i != value.npos) + { + value.erase(0, i); + } + i = value.find_last_not_of("\""); + if(i != value.npos) + { + value.erase(i + 1, value.npos); + } + return value; +} + +/** + * Returns true if definition is a valid Csound instrument definition block. + * Also returns the part before the instr number, the instr number, + * the name (all text after the first comment on the same line as + * the instr number), + * and the part after the instr number, all by reference. + */ +bool PUBLIC parseInstrument(const std::string &definition, std::string &preNumber, + std::string &id, std::string &name, + std::string &postNumber); + +char staticBuffer[0x1000]; + +/** + * Considerably more efficient than std::getline. + */ +bool getline(std::istream& stream, std::string &buffer) +{ + stream.getline(staticBuffer, sizeof(staticBuffer)); + buffer = staticBuffer; + return stream.good(); +} + +bool PUBLIC parseInstrument(const std::string &definition, std::string &preNumber, std::string &id, std::string &name, std::string &postName) +{ + preNumber.erase(); + name.erase(); + postName.erase(); + id.erase(); + int beginId = definition.find("instr"); + if(beginId == -1) + { + return false; + } + beginId += 5; + int newline = definition.find("\n", beginId); + int semicolon = definition.find(";", beginId); + if(semicolon > newline) + { + semicolon = -1; + } + size_t endId = 0; + size_t beginName = 0; + size_t endName = 0; + if(newline == -1) + { + return false; + } + if(semicolon == -1) + { + endId = newline; + id = definition.substr(beginId, endId - beginId); + trim(id); + if(id.length() == 0) + { + return false; + } + if(!strchr("0123456789", id[0])) + { + name = id; + } + } + else + { + endId = semicolon; + beginName = semicolon + 1; + endName = newline; + id = definition.substr(beginId, endId - beginId); + trim(id); + if(id.length() == 0) + { + return false; + } + name = definition.substr(beginName, endName - beginName); + trim(name); + } + postName = definition.substr(endName); + return true; +} + +CsoundFile::CsoundFile() +{ + removeAll(); +} + +int CsoundFile::load(std::string filename) +{ + removeAll(); + int returnValue = importFile(filename); + this->filename = filename.c_str(); + return returnValue; +} + +int CsoundFile::load(std::istream &stream) +{ + removeAll(); + return importFile(stream); +} + +int CsoundFile::save(std::string filename) const +{ + int returnValue = false; + std::ofstream stream(filename.c_str(), std::ios::binary); + if(!((filename.find(".orc") == filename.npos) && + (filename.find(".ORC") == filename.npos))) + { + returnValue += exportOrchestra(stream); + } + else if(!((filename.find(".sco") == filename.npos) && + (filename.find(".SCO") == filename.npos))) + { + returnValue += exportScore(stream); + } + else if(!((filename.find(".mid") == filename.npos) && + (filename.find(".MID") == filename.npos))) + { + returnValue += exportMidifile(stream); + } + else + { + returnValue += save(stream); + } + stream.close(); + return returnValue; +} + +int CsoundFile::save(std::ostream &stream) const +{ + int returnValue = 0; + stream << "" << std::endl; + stream << "" << std::endl; + returnValue += exportCommand(stream); + stream << "" << std::endl; + stream << "" << std::endl; + returnValue += exportOrchestra(stream); + stream << "" << std::endl; + stream << "" << std::endl; + returnValue += exportScore(stream); + stream << "" << std::endl; + if(arrangement.size() > 0) + { + stream << "" << std::endl; + returnValue += exportArrangement(stream); + stream << "" << std::endl; + } + if(midifile.size() > 0) + { + stream << "" << std::endl; + stream << "" << std::endl; + stream << midifile.size() << std::endl; + stream << "" << std::endl; + returnValue += exportMidifile(stream); + stream << "" << std::endl; + } + stream << "" << std::endl; + return returnValue; +} + +#if defined(HAVE_MUSICXML2) + + class CsoundFileMidiWriter : public midiwriter + { + public: + long tpq; + double tempo; + CsoundFileMidiWriter(CsoundFile *csoundFile_) : tpq(1000), tempo(1.0), + csoundFile(*csoundFile_) + { + csoundFile.removeScore(); + } + virtual void startPart (int instrCount) + { + } + virtual void newInstrument (std::string instrName, int chan=-1) + { + } + virtual void endPart (long date) + { + } + virtual void newNote (long start_, int insno_, float key_, + int velocity_, int duration_) + { + double insno = double(insno_ + 1.0); + double start = double(start_) / double(tpq) * tempo; + double duration = double(duration_) / double(tpq) * tempo; + double key = key_; + double velocity = velocity_; + csoundFile.addNote(insno, start, duration, key, velocity); + } + virtual void tempoChange (long date, int bpm) + { + tempo = 60.0 / double(bpm); + } + virtual void pedalChange (long date, pedalType t, int value) + { + } + virtual void volChange (long date, int chan, int vol) + { + } + virtual void bankChange (long date, int chan, int bank) + { + } + virtual void progChange (long date, int chan, int prog) + { + } + protected: + CsoundFile &csoundFile; + }; + +#endif + +int CsoundFile::importFile(std::string filename) +{ + struct stat statbuffer; + int returnValue = stat(filename.c_str(), &statbuffer); + if(returnValue) + { + return false; + } + std::ifstream stream(filename.c_str(), std::ios::binary); + if((filename.find(".orc") != filename.npos) || + (filename.find(".ORC") != filename.npos)) + { + returnValue += importOrchestra(stream); + } + else if((filename.find(".sco") != filename.npos) || + (filename.find(".SCO") != filename.npos)) + { + returnValue += importScore(stream); + } + else if((filename.find(".mid") != filename.npos) || + (filename.find(".MID") != filename.npos)) + { + returnValue += importMidifile(stream); + } +#if defined(HAVE_MUSICXML2) + else if((filename.find(".xml") != filename.npos) || + (filename.find(".XML") != filename.npos)) + { + score.erase(); + xmlreader xmlReader; + Sxmlelement sxmlElement; + // Try to read an SXMLFile out of the MusicXML file. + SXMLFile sxmlFile = xmlReader.read(filename.c_str()); + if (sxmlFile) { + // Get the document tree of XML elements from the SXMLFile. + sxmlElement = sxmlFile->elements(); + } + if (sxmlElement) { + // Create a CsoundFileMidiWriter that is attached to this Score. + CsoundFileMidiWriter csoundFileMidiWriter(this); + // Create a midicontextvisitor, which calls into an abstract + // midiwriter interface, which is attached to our + // CsoundFileMidiWriter, which implements that midiwriter + // interface. + midicontextvisitor midicontextvisitor_(csoundFileMidiWriter.tpq, + &csoundFileMidiWriter); + // Create an xml_tree_browser that is attached to our midicontextvisitor. + xml_tree_browser xmlTreeBrowser(&midicontextvisitor_); + // The xml_tree_browser will carry the midicontextvisitor to + // all the elements of the document tree, in the proper order, + // calling newNote as appropriate. + xmlTreeBrowser.browse(*sxmlElement); + } + } +#endif + else + { + returnValue += importFile(stream); + } + stream.close(); + return returnValue; +} + +int CsoundFile::importFile(std::istream &stream) +{ + std::string buffer; + while(getline(stream, buffer)) + { + if(buffer.find("") == 0) + { + while(getline(stream, buffer)) + { + if(buffer.find("") == 0) + { + return true; + } + else if(buffer.find("") == 0) + { + importCommand(stream); + } + else if(buffer.find("") == 0) + { + importOrchestra(stream); + } + else if(buffer.find("") == 0) + { + importArrangement(stream); + } + else if(buffer.find("") == 0) + { + importScore(stream); + } + else if(buffer.find("") == 0) + { + importMidifile(stream); + } + } + } + } + return false; +} + +int CsoundFile::importCommand(std::istream &stream) +{ + std::string buffer; + while(getline(stream, buffer)) + { + if(buffer.find("") == 0) + { + return true; + } + else + { + orchestra.append(buffer); + orchestra.append("\n"); + } + } + return false; +} + +int CsoundFile::exportOrchestra(std::ostream &stream) const +{ + stream << orchestra; + stream.flush(); + return stream.good(); +} + +int CsoundFile::importScore(std::istream &stream) +{ + score.erase(); + std::string buffer; + while(getline(stream, buffer)) + { + if(buffer.find("") == 0) + { + return true; + } + else + { + score.append(buffer); + score.append("\n"); + } + } + return false; +} + +int CsoundFile::exportScore(std::ostream &stream) const +{ + stream << score << std::endl; + return stream.good(); +} + +std::string CsoundFile::getFilename() const +{ + return filename.c_str(); +} + +void CsoundFile::setFilename(std::string name) +{ + filename = name; +} + +std::string CsoundFile::getCommand() const +{ + return command; +} + +void CsoundFile::setCommand(std::string value) +{ + command = value; +} + +void CsoundFile::removeCommand() +{ + command.erase(command.begin(), command.end()); +} + +std::string CsoundFile::getOrcFilename() const +{ + std::string buffer; + scatterArgs(command, const_cast< std::vector & >(args), + const_cast< std::vector &>(argv)); + if(args.size() >= 3) + { + buffer = args[args.size() - 2]; + } + return buffer.c_str(); +} + +std::string CsoundFile::getScoFilename() const +{ + std::string buffer; + scatterArgs(command, const_cast< std::vector & >(args), + const_cast< std::vector &>(argv)); + if(args.size() >= 3) + { + buffer = args[args.size() - 1]; + } + return buffer; +} + +std::string CsoundFile::getMidiFilename() const +{ + std::string buffer; + scatterArgs(command, const_cast< std::vector & >(args), + const_cast< std::vector &>(argv)); + for(int i = 1, n = args.size() - 2; i < n; i++) + { + std::string buffer = args[i]; + if(buffer.find("F") != buffer.npos) + { + if(buffer.find("F") == buffer.length() - 1) + { + buffer = args[i + 1]; + return buffer.c_str(); + } + else + { + buffer = buffer.substr(buffer.find("F") + 1); + return buffer.c_str(); + } + } + } + return buffer.c_str(); +} + +std::string CsoundFile::getOutputSoundfileName() const +{ + return "default"; +} + +std::string CsoundFile::getOrchestra() const +{ + return orchestra; +} + +void CsoundFile::setOrchestra(std::string value) +{ + orchestra = value; +} + +void CsoundFile::removeOrchestra() +{ + orchestra.erase(); +} + +void CsoundFile::removeScore() +{ + score.erase(); +} + +std::string CsoundFile::getScore() const +{ + return score; +} + +void CsoundFile::setScore(std::string score) +{ + this->score = score; +} + +void CsoundFile::addScoreLine(std::string scoreLine) +{ + score.append(scoreLine); + if(scoreLine.find("\n") == std::string::npos) + { + score.append("\n"); + } +} + +void CsoundFile::removeAll() +{ + filename.erase(); + command.erase(); + orchestra.erase(); + score.erase(); + arrangement.erase(arrangement.begin(), arrangement.end()); + removeMidifile(); +} + +int CsoundFile::importMidifile(std::istream &stream) +{ + // Importing from a standard MIDI file + // (Chunk ID == MThd or RIFF). + if(stream.peek() == 'M' || stream.peek() == 'R') + { + midifile.resize(0); + char buffer; + while(!(stream.get(buffer).eof())) + { + midifile.push_back(buffer); + } + return true; + } + // Importing from a "csd" file. + else + { + std::string buffer; + while(getline(stream, buffer)) + { + if(buffer.find("") == 0) + { + return true; + } + else if(buffer.find("") == 0) + { + getline(stream, buffer); + int size = atoi(buffer.c_str()); + getline(stream, buffer); + if(size > 0) + { + midifile.resize(0); + char charbuffer = 0; + for(int i = 0; i < size; i++) + { + stream.get(charbuffer); + midifile.push_back(charbuffer); + } + } + } + } + } + return false; +} + +int CsoundFile::exportMidifile(std::ostream &stream) const +{ + for(int i = 0, n = midifile.size(); i < n; i++) + { + stream.put(midifile[i]); + } + return stream.good(); +} + +void CsoundFile::removeMidifile() +{ + midifile.resize(0); +} + +void CsoundFile::addNote(double p1, double p2, double p3, double p4, + double p5, double p6, double p7, double p8, + double p9, double p10, double p11) +{ + char note[0x100]; + sprintf(note, "i %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g" + " %-.10g %-.10g %-.10g", p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); + addScoreLine(note); +} + +void CsoundFile::addNote(double p1, double p2, double p3, double p4, + double p5, double p6, double p7, double p8, + double p9, double p10) +{ + char note[0x100]; + sprintf(note, "i %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g" + " %-.10g %-.10g", p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); + addScoreLine(note); +} + +void CsoundFile::addNote(double p1, double p2, double p3, double p4, + double p5, double p6, double p7, double p8, + double p9) +{ + char note[0x100]; + sprintf(note, "i %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g", + p1, p2, p3, p4, p5, p6, p7, p8, p9); + addScoreLine(note); +} + +void CsoundFile::addNote(double p1, double p2, double p3, double p4, + double p5, double p6, double p7, double p8) +{ + char note[0x100]; + sprintf(note, "i %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g", + p1, p2, p3, p4, p5, p6, p7, p8); + addScoreLine(note); +} + +void CsoundFile::addNote(double p1, double p2, double p3, double p4, + double p5, double p6, double p7) +{ + char note[0x100]; + sprintf(note, "i %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g", + p1, p2, p3, p4, p5, p6, p7); + addScoreLine(note); +} + +void CsoundFile::addNote(double p1, double p2, double p3, double p4, + double p5, double p6) +{ + char note[0x100]; + sprintf(note, "i %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g", + p1, p2, p3, p4, p5, p6); + addScoreLine(note); +} + +void CsoundFile::addNote(double p1, double p2, double p3, double p4, double p5) +{ + char note[0x100]; + sprintf(note, "i %-.10g %-.10g %-.10g %-.10g %-.10g", p1, p2, p3, p4, p5); + addScoreLine(note); +} + +void CsoundFile::addNote(double p1, double p2, double p3, double p4) +{ + char note[0x100]; + sprintf(note, "i %-.10g %-.10g %-.10g %-.10g", p1, p2, p3, p4); + addScoreLine(note); +} + +void CsoundFile::addNote(double p1, double p2, double p3) +{ + char note[0x100]; + sprintf(note, "i %-.10g %-.10g %-.10g", p1, p2, p3); + addScoreLine(note); +} + +bool isToken(std::string text, int position, std::string token) +{ + size_t tokenend = position + token.size(); + if(text.size() > tokenend) + { + if(!std::isspace(text[tokenend])) + { + return false; + } + } + for(int i = position - 1; i >= 0; --i) + { + if(text[i] == ';') + { + return false; + } + else if(text[i] == '\n') + { + return true; + } + } + return true; +} + +int findToken(std::string text, std::string token, int position) +{ + int foundPosition = 0; + while((foundPosition = (int) text.find(token, position)) != -1) + { + if(isToken(text, foundPosition, token)) + { + return foundPosition; + } + position = foundPosition + 1; + } + return foundPosition; +} + +int CsoundFile::getInstrumentCount() const +{ + int beginDefinition = 0; + int endDefinition = 0; + int index; + for(index = 0; true; ) + { + beginDefinition = findToken(orchestra, "instr", beginDefinition); + if(beginDefinition == -1) + { + return index; + } + endDefinition = findToken(orchestra, "endin", beginDefinition); + if(endDefinition == -1) + { + return index; + } + endDefinition += 6; + std::string definition = orchestra.substr(beginDefinition, + endDefinition - beginDefinition); + std::string pre; + std::string id; + std::string name; + std::string post; + if(parseInstrument(definition, pre, id, name, post)) + { + index++; + beginDefinition++; + } + else + { + break; + } + } + return index; +} + +bool CsoundFile::getInstrument(int number, std::string &definition_) const +{ + int beginDefinition = 0; + int endDefinition = 0; + for(; true;) + { + beginDefinition = findToken(orchestra, "instr", beginDefinition); + if(beginDefinition == -1) + { + return false; + } + endDefinition = findToken(orchestra, "endin", beginDefinition); + if(endDefinition == -1) + { + return false; + } + endDefinition += 6; + std::string definition = orchestra.substr(beginDefinition, + endDefinition - beginDefinition); + std::string pre; + std::string id; + std::string name; + std::string post; + if(parseInstrument(definition, pre, id, name, post)) + { + if(number == atof(id.c_str())) + { + definition_ = definition; + return true; + } + } + beginDefinition++; + } + return false; +} + +std::string CsoundFile::getInstrument(std::string name) const +{ + std::string definition; + (void) getInstrument(name, definition); + return definition; +} + +std::string CsoundFile::getInstrument(int number) const +{ + std::string definition; + (void) getInstrument(number, definition); + return definition; +} + +std::string CsoundFile::getInstrumentBody(std::string name) const +{ + std::string definition; + getInstrument(name, definition); + std::string pre; + std::string id; + std::string name_; + std::string post; + (void) parseInstrument(definition, pre, id, name_, post); + return definition; +} + +std::string CsoundFile::getInstrumentBody(int number) const +{ + std::string definition; + getInstrument(number, definition); + std::string pre; + std::string id; + std::string name; + std::string post; + (void) parseInstrument(definition, pre, id, name, post); + return post; +} + +std::map CsoundFile::getInstrumentNames() const +{ + std::map instrumentNames; + int beginDefinition = 0; + int endDefinition = 0; + while(true) + { + beginDefinition = findToken(orchestra, "instr", beginDefinition); + if(beginDefinition == -1) + { + return instrumentNames; + } + endDefinition = findToken(orchestra, "endin", beginDefinition); + if(endDefinition == -1) + { + return instrumentNames; + } + endDefinition += 6; + std::string definition = orchestra.substr(beginDefinition, + endDefinition - beginDefinition); + std::string pre; + std::string id; + std::string name; + std::string post; + if(parseInstrument(definition, pre, id, name, post)) + { + instrumentNames[atof(id.c_str())] = name; + } + beginDefinition++; + } +} + +//bool CsoundFile::getInstrumentNumber(int number_, std::string &definition_) const +//{ +// int beginDefinition = 0; +// int endDefinition = 0; +// for(int index = 0; true; index++) +// { +// beginDefinition = findToken(orchestra, "instr", beginDefinition); +// if(beginDefinition == -1) +// { +// return false; +// } +// endDefinition = findToken(orchestra, "endin", beginDefinition); +// if(endDefinition == -1) +// { +// return false; +// } +// endDefinition += 6; +// std::string definition = orchestra.substr(beginDefinition, +// endDefinition - beginDefinition); +// std::string pre; +// std::string id; +// std::string name; +// std::string post; +// if(parseInstrument(definition, pre, number, name, post)) +// { +// if(number_ == number) +// { +// definition_ = definition; +// return true; +// } +// index++; +// } +// beginDefinition++; +// } +// return false; +//} + +bool CsoundFile::getInstrument(std::string name_, std::string &definition_) const +{ + trim(name_); + int beginDefinition = 0; + int endDefinition = 0; + for(;;) + { + beginDefinition = findToken(orchestra, "instr", beginDefinition); + if(beginDefinition == -1) + { + return false; + } + endDefinition = findToken(orchestra, "endin", beginDefinition); + if(endDefinition == -1) + { + return false; + } + endDefinition += 6; + std::string definition = orchestra.substr(beginDefinition, + endDefinition - beginDefinition); + std::string pre; + std::string id; + std::string name; + std::string post; + if(parseInstrument(definition, pre, id, name, post)) + { + if(name_.compare(name) == 0 || id.compare(name) == 0) + { + definition_ = definition; + return true; + } + } + beginDefinition++; + } + return false; +} + +double CsoundFile::getInstrumentNumber(std::string name_) const +{ + trim(name_); + int beginDefinition = 0; + int endDefinition = 0; + for(;;) + { + beginDefinition = findToken(orchestra, "instr", beginDefinition); + if(beginDefinition == -1) + { + return false; + } + endDefinition = findToken(orchestra, "endin", beginDefinition); + if(endDefinition == -1) + { + return false; + } + endDefinition += 6; + std::string definition = orchestra.substr(beginDefinition, + endDefinition - beginDefinition); + std::string pre; + std::string id; + std::string name; + std::string post; + if(parseInstrument(definition, pre, id, name, post)) + { + if(name_.compare(name) == 0 || id.compare(name) == 0) + { + return atof(id.c_str()); + } + } + beginDefinition++; + } + return -1.0; +} + +bool CsoundFile::exportForPerformance() const +{ + std::string orcFilename = getOrcFilename(); + if(orcFilename.length() > 0) + { + exportArrangementForPerformance(orcFilename); + } + std::string scoFilename = getScoFilename(); + if(scoFilename.length() > 0) + { + save(scoFilename); + } + std::string midiFilename = getMidiFilename(); + if(midiFilename.length() > 0 && midifile.size() > 0) + { + save(midiFilename); + } + return true; +} + +void CsoundFile::setCSD(const std::string xml) +{ + std::istringstream stringStream(xml); + load(stringStream); +} + +std::string CsoundFile::getCSD() const +{ + std::ostringstream stringStream; + save(stringStream); + return stringStream.str(); +} + +int CsoundFile::getArrangementCount() const +{ + return arrangement.size(); +} + +void CsoundFile::removeArrangement() +{ + arrangement.erase(arrangement.begin(), arrangement.end()); +} + +void CsoundFile::addArrangement(std::string instrumentName) +{ + arrangement.push_back(instrumentName); +} + +std::string CsoundFile::getArrangement(int index) const +{ + return arrangement[index]; +} + +int CsoundFile::importArrangement(std::istream &stream) +{ + removeArrangement(); + std::string buffer; + while(getline(stream, buffer)) + { + if(buffer.find("") == 0) + { + return true; + } + else + { + trim(buffer); + arrangement.push_back(buffer); + } + } + return false; +} + +int CsoundFile::exportArrangement(std::ostream &stream) const +{ + for(std::vector::const_iterator it = arrangement.begin(); + it != arrangement.end(); + ++it) + { + stream << (*it).c_str() << std::endl; + } + return stream.good(); +} + +std::string CsoundFile::getOrchestraHeader() const +{ + int instrIndex = findToken(orchestra, "instr", 0); + if(instrIndex == (int) orchestra.npos) + { + return ""; + } + return orchestra.substr(0, instrIndex); +} + +int CsoundFile::exportArrangementForPerformance(std::string filename) const +{ + std::ofstream stream(filename.c_str(), std::ios::binary); + exportArrangementForPerformance(stream); + stream.close(); + return stream.good(); +} + +int CsoundFile::exportArrangementForPerformance(std::ostream &stream) const +{ + int i,n; + if(arrangement.size() > 0) + { + stream << "; ARRANGEMENT " << getOrcFilename().c_str() << std::endl; + stream << getOrchestraHeader() << std::endl; +// for(i = 0, n = arrangement.size(); i < n; ++i) +// { +// stream << "massign " << (i + 1) << " , " << (i + 1) << std::endl; +// stream.flush(); +// } + for(i = 0, n = arrangement.size(); i < n; ++i) + { + std::string instrumentName = arrangement[i]; + std::string definition; + if(getInstrument(instrumentName, definition)) + { + std::string preNumber; + std::string id; + std::string postNumber; + if(parseInstrument(definition, preNumber, id, + instrumentName, postNumber)) + { + stream << std::endl << "instr " << (i + 1) << + " ; " << instrumentName << std::endl << postNumber << std::endl; + stream.flush(); + } + } + } + } + else + { + exportOrchestra(stream); + } + return stream.good(); +} + +//void CsoundFile::getInstrumentNames(std::vector &names) const +//{ +// names.erase(names.begin(), names.end()); +// std::string definition; +// for(int i = 0; getInstrument(i, definition); i++) +// { +// std::string preNumber; +// int number; +// std::string name; +// std::string postName; +// if(parseInstrument(definition, preNumber, number, name, postName)) +// { +// names.push_back(name); +// } +// } +// std::sort(names.begin(), names.end()); +//} + +void CsoundFile::insertArrangement(int index, std::string instrument) +{ + arrangement.insert(arrangement.begin() + index, instrument); +} + +void CsoundFile::removeArrangement(int index) +{ + arrangement.erase(arrangement.begin() + index); +} + +void CsoundFile::setArrangement(int index, std::string instrument) +{ + arrangement[index] = instrument; +} + +bool CsoundFile::loadOrcLibrary(const char *filename) +{ + if(!filename) + { + return false; + } + std::fstream stream; + if(strlen(filename) > 0) + { + stream.open(filename, std::fstream::in | std::ios::binary); + } + else + { + const char *filename_ = getenv("CSOUND_HOME"); + if (filename_ != 0) { + std::string orcLibraryFilename = filename_; + orcLibraryFilename.append("/"); + orcLibraryFilename.append("library.orc"); + stream.open(orcLibraryFilename.c_str(), std::fstream::in | std::ios::binary); + } else { + return false; + } + } + if(stream.good()) + { + removeOrchestra(); + importOrchestra(stream); + return true; + } + return false; +} + +std::string CsoundFile::generateFilename() +{ + time_t time_ = 0; + time(&time_); + struct tm* tm_ = gmtime(&time_); + char buffer[0x100]; + strftime(buffer, 0x100, "csound.%Y-%m-%d.%H-%M-%S.csd", tm_); + filename = buffer; + return filename; +} + diff --git a/CsoundAC/CsoundFile.hpp b/CsoundAC/CsoundFile.hpp new file mode 100644 index 0000000000..f77f924498 --- /dev/null +++ b/CsoundAC/CsoundFile.hpp @@ -0,0 +1,222 @@ +/* + * C S O U N D + * + * L I C E N S E + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef CSOUNDFILE_H +#define CSOUNDFILE_H + +#if 0 +#undef MYFLT +#ifdef USE_DOUBLE +#define MYFLT double +#else +#define MYFLT float +#endif +#endif + +#if defined(_MSC_VER) && !defined(__GNUC__) +#pragma warning(disable: 4786) +#endif +#ifdef SWIG +%module csnd6 +%include "std_string.i" +%include "std_vector.i" +#if !defined(SWIGLUA) +%include "std_map.i" +%template(IntToStringMap) std::map; +#endif +%{ +#include +#include +%} +#else +#include +#include +#include +#include +#include +#include +#include + +#ifndef PUBLIC +#if (defined(WIN32) || defined(_WIN32)) && !defined(SWIG) +# define PUBLIC __declspec(dllexport) +#elif defined(__GNUC__) && (__GNUC__ >= 4) /* && !defined(__MACH__) */ +# define PUBLIC __attribute__ ( (visibility("default")) ) +#else +# define PUBLIC +#endif +#endif + +#if defined(WIN32) +#include +#endif +#endif + +void PUBLIC gatherArgs(int argc, const char **argv, std::string &commandLine); + +void PUBLIC scatterArgs(const std::string commandLine, std::vector &args, std::vector &argv); + +std::string PUBLIC &trim(std::string &value); + +std::string PUBLIC &trimQuotes(std::string &value); + +/** + * Returns true if definition is a valid Csound instrument definition block. + * Also returns the part before the instr number, the instr number, + * the name (all text after the first comment on the same line as the instr number), + * and the part after the instr number, all by reference. + */ +bool PUBLIC parseInstrument(const std::string &definition, std::string &preNumber, std::string &id, std::string &name, std::string &postNumber); + +/** + * Manages a Csound Structured Data (CSD) file with facilities + * for creating an arrangement of selected instruments in the orchestra, + * and for programmatically building score files. + */ +class PUBLIC CsoundFile +{ +protected: + /** + * What are we storing, anyway? + */ + std::string filename; + /** + * CsOptions + */ + std::string command; + std::vector args; + std::vector argv; + /** + * CsInstruments + */ + std::string orchestra; + /** + * CsScore + */ + std::string score; + /** + * CsMidi + */ + std::vector midifile; +public: + /** + * Patch library and arrangement. + */ + std::string libraryFilename; + std::vector arrangement; + CsoundFile(); + virtual ~CsoundFile(){}; + virtual std::string generateFilename(); + virtual std::string getFilename() const; + virtual void setFilename(std::string name); + /** + * Clears all contents of this, + * then imports the indicated file, + * which can be a Csound unified file (.csd), + * Csound orchestra (.orc), Csound score (.sco), + * standard MIDI file (.mid), or MusicXML v2 (.xml) + * file. + * + * The MusicXML notes become instrument number + 1, + * time in seconds, duration in seconds, MIDI key + * number, and MIDI velocity number. + */ + virtual int load(std::string filename); + virtual int load(std::istream &stream); + virtual int save(std::string filename) const; + virtual int save(std::ostream &stream) const; + /** + * Imports the indicated file, + * which can be a Csound unified file (.csd), + * Csound orchestra (.orc), Csound score (.sco), + * standard MIDI file (.mid), or MusicXML v2 (.xml) + * file. The data that is read replaces existing + * data of that type, but leaves other types of data + * untouched. + * + * The MusicXML notes become instrument number + 1, + * time in seconds, duration in seconds, MIDI key + * number, and MIDI velocity number. + */ + virtual int importFile(std::string filename); + virtual int importFile(std::istream &stream); + virtual int importCommand(std::istream &stream); + virtual int exportCommand(std::ostream &stream) const; + virtual int importOrchestra(std::istream &stream); + virtual int exportOrchestra(std::ostream &stream) const; + virtual int importScore(std::istream &stream); + virtual int exportScore(std::ostream &stream) const; + virtual int importArrangement(std::istream &stream); + virtual int exportArrangement(std::ostream &stream) const; + virtual int exportArrangementForPerformance(std::string filename) const; + virtual int exportArrangementForPerformance(std::ostream &stream) const; + virtual int importMidifile(std::istream &stream); + virtual int exportMidifile(std::ostream &stream) const; + virtual std::string getCommand() const; + virtual void setCommand(std::string commandLine); + virtual std::string getOrcFilename() const; + virtual std::string getScoFilename() const; + virtual std::string getMidiFilename() const; + virtual std::string getOutputSoundfileName() const; + virtual std::string getOrchestra() const; + virtual void setOrchestra(std::string orchestra); + virtual int getInstrumentCount() const; + virtual std::string getOrchestraHeader() const; + virtual bool getInstrument(int number, std::string &definition) const; + //virtual bool getInstrumentNumber(int index, std::string &definition) const; + virtual bool getInstrument(std::string name, std::string &definition) const; + virtual std::string getInstrument(std::string name) const; + virtual std::string getInstrument(int number) const; + virtual std::string getInstrumentBody(std::string name) const; + virtual std::string getInstrumentBody(int number) const; + virtual std::map getInstrumentNames() const; + virtual double getInstrumentNumber(std::string name) const; + virtual std::string getScore() const; + virtual void setScore(std::string score); + virtual int getArrangementCount() const; + virtual std::string getArrangement(int index) const; + virtual void addArrangement(std::string instrument); + virtual void setArrangement(int index, std::string instrument); + virtual void insertArrangement(int index, std::string instrument); + virtual void removeArrangement(int index); + virtual void setCSD(std::string xml); + virtual std::string getCSD() const; + virtual void addScoreLine(const std::string line); + virtual void addNote(double p1, double p2, double p3, double p4, double p5, double p6, double p7, double p8, double p9, double p10, double p11); + virtual void addNote(double p1, double p2, double p3, double p4, double p5, double p6, double p7, double p8, double p9, double p10); + virtual void addNote(double p1, double p2, double p3, double p4, double p5, double p6, double p7, double p8, double p9); + virtual void addNote(double p1, double p2, double p3, double p4, double p5, double p6, double p7, double p8); + virtual void addNote(double p1, double p2, double p3, double p4, double p5, double p6, double p7); + virtual void addNote(double p1, double p2, double p3, double p4, double p5, double p6); + virtual void addNote(double p1, double p2, double p3, double p4, double p5); + virtual void addNote(double p1, double p2, double p3, double p4); + virtual void addNote(double p1, double p2, double p3); + virtual bool exportForPerformance() const; + virtual void removeAll(); + virtual void removeCommand(); + virtual void removeOrchestra(); + virtual void removeScore(); + virtual void removeArrangement(); + virtual void removeMidifile(); + //virtual void getInstrumentNames(std::vector &names) const; + virtual bool loadOrcLibrary(const char *filename = 0); +}; + +#endif // CSOUND_FILE_H + diff --git a/CsoundAC/Soundfile.cpp b/CsoundAC/Soundfile.cpp index bdb1d9fcf0..b59463bc6a 100644 --- a/CsoundAC/Soundfile.cpp +++ b/CsoundAC/Soundfile.cpp @@ -18,288 +18,157 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "Soundfile.hpp" -#include "Conversions.hpp" +#include +#include namespace csound { -Soundfile::Soundfile() : sampleCount(0), startTimeSeconds(0.0) -{ +#ifndef PI +#define PI (3.14159265358979323846) +#endif +#ifndef TWOPI +#define TWOPI (6.28318530717958647692) +#endif + + Soundfile::Soundfile() + { initialize(); -} -Soundfile::~Soundfile() -{ + } + Soundfile::~Soundfile() + { close(); -} -void Soundfile::initialize() -{ + } + void Soundfile::initialize() + { sndfile = 0; std::memset(&sf_info, 0, sizeof(sf_info)); -} -int Soundfile::getFramesPerSecond() const -{ + } + int Soundfile::getFramesPerSecond() const + { return sf_info.samplerate; -} -void Soundfile::setFramesPerSecond(int framesPerSecond) -{ + } + void Soundfile::setFramesPerSecond(int framesPerSecond) + { sf_info.samplerate = framesPerSecond; -} -int Soundfile::getChannelsPerFrame() const -{ + } + int Soundfile::getChannelsPerFrame() const + { return sf_info.channels; -} -void Soundfile::setChannelsPerFrame(int channelsPerFrame) -{ + } + void Soundfile::setChannelsPerFrame(int channelsPerFrame) + { sf_info.channels = channelsPerFrame; -} -int Soundfile::getFormat() const -{ + } + int Soundfile::getFormat() const + { return sf_info.format; -} -void Soundfile::setFormat(int format) -{ + } + void Soundfile::setFormat(int format) + { sf_info.format = format; -} -int Soundfile::getFrames() const -{ + } + int Soundfile::getFrames() const + { return (int) sf_info.frames; -} -int Soundfile::open(std::string filename) -{ + } + int Soundfile::open(std::string filename) + { close(); sndfile = sf_open(filename.c_str(), SFM_RDWR, &sf_info); if (!sndfile) { - error(); - return -1; + error(); + return -1; } return 0; -} -int Soundfile::create(std::string filename, int framesPerSecond, int channelsPerFrame, int format) -{ + } + int Soundfile::create(std::string filename, int framesPerSecond, int channelsPerFrame, int format) + { close(); sf_info.samplerate = framesPerSecond; sf_info.channels = channelsPerFrame; sf_info.format = format; sndfile = sf_open(filename.c_str(), SFM_RDWR, &sf_info); if (!sndfile) { - error(); - return -1; + error(); + return -1; } return 0; -} -int Soundfile::seek(int frames, int whence) -{ + } + int Soundfile::seek(int frames, int whence) + { int frame = sf_seek(sndfile, frames, whence); if (frame == -1) { - error(); + error(); } return frame; -} -double Soundfile::seekSeconds(double seconds, int whence) -{ + } + double Soundfile::seekSeconds(double seconds, int whence) + { int frame = int(seconds * double(sf_info.samplerate)); frame = sf_seek(sndfile, frame, whence); if (frame == -1) { - error(); + error(); } return frame; -} -int Soundfile::readFrame(double *outputFrame) -{ + } + int Soundfile::readFrame(double *outputFrame) + { return sf_readf_double(sndfile, outputFrame, 1); -} -int Soundfile::writeFrame(double *inputFrame) -{ + } + int Soundfile::writeFrame(double *inputFrame) + { return sf_writef_double(sndfile, inputFrame, 1); -} -int Soundfile::readFrames(double *outputFrames, int samples) -{ + } + int Soundfile::readFrames(double *outputFrames, int samples) + { return sf_read_double(sndfile, outputFrames, samples); -} -int Soundfile::writeFrames(double *inputFrames, int samples) -{ + } + int Soundfile::writeFrames(double *inputFrames, int samples) + { return sf_write_double(sndfile, inputFrames, samples); -} -int Soundfile::mixFrames(double *inputFrames, int samples, double *mixedFrames) -{ + } + int Soundfile::mixFrames(double *inputFrames, int samples, double *mixedFrames) + { size_t position = sf_seek(sndfile, 0, SEEK_CUR); sf_readf_double(sndfile, mixedFrames, samples); for (int i = 0; i < samples; i++) { - mixedFrames[i] += inputFrames[i]; + mixedFrames[i] += inputFrames[i]; } sf_seek(sndfile, position, SEEK_SET); return sf_writef_double(sndfile, mixedFrames, samples); -} -void Soundfile::updateHeader() -{ + } + void Soundfile::updateHeader() + { /* int status = */ sf_command(sndfile, SFC_UPDATE_HEADER_NOW, 0, 0); -} -int Soundfile::close() -{ + } + int Soundfile::close() + { int status = 0; if (sndfile) { - status = sf_close(sndfile); - if (status) { - std::cerr << sf_error_number(status) << std::endl; - } + status = sf_close(sndfile); + if (status) { + std::cerr << sf_error_number(status) << std::endl; + } } initialize(); return status; -} -void Soundfile::error() const -{ + } + void Soundfile::error() const + { std::cerr << sf_strerror(sndfile) << std::endl; -} + } -void Soundfile::blank(double duration) -{ + void Soundfile::blank(double duration) + { seekSeconds(0.0); std::vector frame; frame.resize(getChannelsPerFrame()); int framesToWrite = int(duration * getFramesPerSecond()); for (int i = 0; i < framesToWrite; i++) { - sf_writef_double(sndfile, &frame.front(), 1); + sf_writef_double(sndfile, &frame.front(), 1); } updateHeader(); seekSeconds(0.0); -} + } -void Soundfile::jonesParksGrain(double centerTimeSeconds, - double durationSeconds, - double beginningFrequencyHz, - double centerFrequencyHz, - double centerAmplitude, - double centerPhaseOffsetRadians, - double pan, - bool synchronousPhase, - bool buffer) -{ - if (synchronousPhase) { - double wavelengthSeconds = 1.0 / centerFrequencyHz; - double wavelengths = centerTimeSeconds / wavelengthSeconds; - double wholecycles = 0; - double fractionalCycle = std::modf(wavelengths, &wholecycles); - centerPhaseOffsetRadians = Conversions::get2PI() * fractionalCycle; - } - double leftGain = Conversions::leftPan(pan); - double rightGain = Conversions::rightPan(pan); - double centerTime = - (durationSeconds / 2.0); - int samplingRate = getFramesPerSecond(); - double samplingInterval = 1.0 / double(samplingRate); - size_t frameCount = size_t(2.0 * durationSeconds / samplingInterval); - double gaussianWidth = std::exp(1.0) / std::pow(durationSeconds / 4.0, 2.0); - double endingFrequencyHz = centerFrequencyHz + (centerFrequencyHz - beginningFrequencyHz); - double chirpRate = (endingFrequencyHz - beginningFrequencyHz) / durationSeconds; - double omega = Conversions::get2PI() * centerFrequencyHz; - std::complex c0(log(centerAmplitude) - (gaussianWidth * std::pow(centerTime, 2.0)), - (centerPhaseOffsetRadians - (chirpRate / 2.0) * centerTime) - (omega * centerTime)); - std::complex c1(-2.0 * gaussianWidth * samplingInterval * centerTime, - - (samplingInterval * (chirpRate * centerTime + omega))); - std::complex c2 = (-std::complex(gaussianWidth, chirpRate / 2.0)) * std::pow(samplingInterval, 2.0); - std::complex exp_2_c2 = std::exp(2.0 * c2); - std::complex h0 = std::exp(c1 + c2); - std::complex h1(0.0, 0.0); - std::complex f0 = std::exp(c0); - std::complex f1(0.0, 0.0); - size_t channelCount = getChannelsPerFrame(); - grainOutput.resize(frameCount, channelCount); - grainBuffer.resize(frameCount, channelCount); - for(size_t frameI = 0; frameI < frameCount; frameI++) { - double sample = f0.real(); - if (channelCount == 2) { - grainOutput(frameI, 0) += (leftGain * sample); - grainOutput(frameI, 1) += (rightGain * sample); - } else if (channelCount == 1) { - grainOutput(frameI, 0) += sample; - } else { - for(size_t channelI = 0; channelI < channelCount; channelI++) { - grainOutput(frameI, channelI) += sample; - } - } - h1 = h0 * exp_2_c2; - h0 = h1; - f1 = h1 * f0; - f0 = f1; - } - sampleCount = frameCount * channelCount; - startTimeSeconds = centerTimeSeconds - (durationSeconds / 2.0); - if (!buffer) { - mixGrain(); - } } - -void Soundfile::cosineGrain(double centerTimeSeconds, - double durationSeconds, - double frequencyHz, - double amplitude, - double phaseOffsetRadians, - double pan, - bool synchronousPhase, - bool buffer) -{ - if (synchronousPhase) { - double wavelengthSeconds = 1.0 / frequencyHz; - double wavelengths = centerTimeSeconds / wavelengthSeconds; - double wholecycles = 0; - double fractionalCycle = std::modf(wavelengths, &wholecycles); - phaseOffsetRadians = Conversions::get2PI() * fractionalCycle; - } - size_t frameN = size_t(Conversions::round(durationSeconds * getFramesPerSecond())); - size_t channelN = getChannelsPerFrame(); - grainOutput.resize(frameN, channelN); - grainBuffer.resize(frameN, channelN); - double leftGain = Conversions::leftPan(pan); - double rightGain = Conversions::rightPan(pan); - // The signal is a cosine sinusoid. - double framesPerSecond = double(getFramesPerSecond()); - double sinusoidRadiansPerFrame = Conversions::get2PI() * frequencyHz / framesPerSecond; - double sinusoidCoefficient = 2.0 * std::cos(sinusoidRadiansPerFrame); - // The initial frame. - double sinusoid1 = std::cos(phaseOffsetRadians); - // What would have been the previous frame. - double sinusoid2 = std::cos(-sinusoidRadiansPerFrame + phaseOffsetRadians); - // The envelope is exactly 1 cycle of a cosine sinusoid, offset by -1. - double envelopeFrequencyHz = 1.0 / durationSeconds; - double envelopeRadiansPerFrame = Conversions::get2PI() * envelopeFrequencyHz / framesPerSecond; - double envelopeCoefficient = 2.0 * std::cos(envelopeRadiansPerFrame); - // The initial frame. - double envelope1 = std::cos(0.0); - // What would have been the previous frame. - double envelope2 = std::cos(-envelopeRadiansPerFrame); - // Precompute grain into buffer. - double signal = 0.0; - double temporary = 0.0; - for(size_t frameI = 0; frameI < frameN; frameI++) - { - signal = (sinusoid1 * (envelope1 - 1.0)) * amplitude; - if (channelN == 2) { - grainOutput(frameI, 0) += (leftGain * signal); - grainOutput(frameI, 1) += (rightGain * signal); - } else if (channelN == 1) { - grainOutput(frameI, 0) += signal; - } else { - for(size_t channelI = 0; channelI < channelN; channelI++) { - grainOutput(frameI, channelI) += signal; - } - } - temporary = sinusoid1; - sinusoid1 = sinusoidCoefficient * sinusoid1 - sinusoid2; - sinusoid2 = temporary; - temporary = envelope1; - envelope1 = envelopeCoefficient * envelope1 - envelope2; - envelope2 = temporary; - } - sampleCount = frameN * channelN; - startTimeSeconds = centerTimeSeconds - (durationSeconds / 2.0); - if (!buffer) { - mixGrain(); - } -} - -void Soundfile::mixGrain() -{ - seekSeconds(startTimeSeconds); - mixFrames(&grainOutput(0, 0), sampleCount, &grainBuffer(0, 0)); - grainOutput *= 0.0; -} -} - diff --git a/CsoundAC/Soundfile.hpp b/CsoundAC/Soundfile.hpp index dc015681fa..7550d890ce 100644 --- a/CsoundAC/Soundfile.hpp +++ b/CsoundAC/Soundfile.hpp @@ -1,10 +1,5 @@ -#ifndef SOUNDFILE_HP_INCLUDED -#define SOUNDFILE_HP_INCLUDED /* - * C S O U N D A C - * - * A Python extension module for algorithmic composition - * with Csound. + * C S O U N D * * L I C E N S E * @@ -22,45 +17,46 @@ * License along with this software; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#ifndef CSOUND_SOUNDFILE_H +#define CSOUND_SOUNDFILE_H -#include "Platform.hpp" #ifdef SWIG -%module CsoundAC +%module csnd6 %{ #include #include #include #include #include -%} + %} %include "std_string.i" #ifdef SWIGPYTHON %typemap(in) double *outputFrame { - static double buffer[16]; - $1 = &buffer[0]; - for (int i = 0, n = PySequence_Size($input); i < n; i++) { - PyObject *o = PyFloat_FromDouble($1[i]); - PySequence_SetItem($input, i, o); - } + static double buffer[16]; + $1 = &buffer[0]; + for (int i = 0, n = PySequence_Size($input); i < n; i++) { + PyObject *o = PyFloat_FromDouble($1[i]); + PySequence_SetItem($input, i, o); + } } %typemap(in) double *inputFrame { - static double buffer[16]; - $1 = &buffer[0]; - for (int i = 0, n = PySequence_Size($input); i < n; i++) { - PyObject *o = PySequence_ITEM($input, i); - $1[i] = PyFloat_AS_DOUBLE(o); - } + static double buffer[16]; + $1 = &buffer[0]; + for (int i = 0, n = PySequence_Size($input); i < n; i++) { + PyObject *o = PySequence_ITEM($input, i); + $1[i] = PyFloat_AS_DOUBLE(o); + } } %typemap(in) (double *outputFrames, int samples) { - $1 = (double *) PyString_AsString($input); - $2 = PyString_Size($input) / sizeof(double); + $1 = (double *) PyString_AsString($input); + $2 = PyString_Size($input) / sizeof(double); } %typemap(in) (double *inputFrames, int samples) { - $1 = (double *) PyString_AsString($input); - $2 = PyString_Size($input) / sizeof(double); + $1 = (double *) PyString_AsString($input); + $2 = PyString_Size($input) / sizeof(double); } %typemap(in) double *mixedFrames { - $1 = (double *) PyString_AsString($input); + $1 = (double *) PyString_AsString($input); } #endif @@ -70,30 +66,36 @@ #include #include #include -#include -#include +#endif + +#if defined(WIN32) +#define SILENCE_PUBLIC __declspec(dllexport) +#elif defined(__GNUC__) +#define SILENCE_PUBLIC __attribute__ ( (visibility("default")) ) +#else +#define SILENCE_PUBLIC #endif namespace csound { -/** - * Simple, basic read/write access, in sample frames, to PCM soundfiles. - * Reads and writes any format, but write defaults to WAV float format. - * This class is designed for Python wrapping with SWIG. - * See http://www.mega-nerd.com/libsndfile for more information - * on the underlying libsndfile library. - */ -class SILENCE_PUBLIC Soundfile -{ + /** + * Simple, basic read/write access, in sample frames, to PCM soundfiles. + * Reads and writes any format, but write defaults to WAV float format. + * This class is designed for Python wrapping with SWIG. + * See http://www.mega-nerd.com/libsndfile for more information + * on the underlying libsndfile library. + */ +#ifdef SWIG + class Soundfile +#else + class SILENCE_PUBLIC Soundfile +#endif + { SNDFILE *sndfile; SF_INFO sf_info; - Eigen::MatrixXd grainOutput; - Eigen::MatrixXd grainBuffer; - size_t sampleCount; - double startTimeSeconds; -protected: + protected: virtual void initialize() ; -public: + public: Soundfile(); virtual ~Soundfile() ; virtual int getFramesPerSecond() const; @@ -183,59 +185,6 @@ class SILENCE_PUBLIC Soundfile * Make the soundfile be so many seconds of silence. */ virtual void blank(double duration); - /** - * Mix a Gaussian chirp into the soundfile. If the soundfile is stereo, - * the grain will be panned. If the synchronousPhase argument is true - * (the default value), then all grains of the same frequency - * will have synchronous phases, which can be useful in avoiding certain artifacts. - * - * If the buffer argument is true (the default is false), - * the grain is mixed into a buffer; this can be used - * to speed up writing grains that are arrangement in columns. - * To actually write the grain, call writeGrain(). - * - * The algorithm uses an efficient difference equation. - */ - virtual void jonesParksGrain(double centerTimeSeconds, - double durationSeconds, - double beginningFrequencyHz, - double centerFrequencyHz, - double centerAmplitude, - double centerPhaseOffsetRadians, - double pan, - bool synchronousPhase = true, - bool buffer = false); - /** - * Mix a cosine grain into the soundfile. If the soundfile is stereo, - * the grain will be panned. If the synchronousPhase argument is true - * (the default value), then all grains of the same frequency - * will have synchronous phases, which can be useful in avoiding certain artifacts. - * For example, if cosine grains of the same frequency have synchronous phases, - * they can be overlapped by 1/2 their duration without artifacts - * to produce a continuous cosine tone. - * - * If the buffer argument is true (the default is false), - * the grain is mixed into a buffer; this can be used - * to speed up writing grains that are arrangement in columns. - * To actually write the grain, call writeGrain(). - * - * The algorithm uses an efficient difference equation. - */ - virtual void cosineGrain(double centerTimeSeconds, - double durationSeconds, - double frequencyHz, - double amplitude, - double phaseOffsetRadians, - double pan, - bool synchronousPhase = true, - bool buffer = false); - /** - * Mix a grain that has already been computed into the soundfile. - */ - virtual void mixGrain(); -}; - + }; } - #endif - diff --git a/CsoundAC/cs_glue.cpp b/CsoundAC/cs_glue.cpp new file mode 100644 index 0000000000..5c9aa3291b --- /dev/null +++ b/CsoundAC/cs_glue.cpp @@ -0,0 +1,1345 @@ +/* + cs_glue.cpp: + + Copyright (C) 2005, 2006 Istvan Varga + + This file is part of Csound. + + The Csound Library is free software; you can redistribute it + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + Csound is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with Csound; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + 02110-1301 USA +*/ + +#include "csound.h" +//#include "cs_glue.h" +#include "csound.hpp" +#include "csdl.h" +#include "cs_glue.hpp" + +extern "C" { + + +// ---------------------------------------------------------------------------- + +/** + * CsoundOpcodeList(CSOUND *) + * CsoundOpcodeList(Csound *) + * + * Creates an alphabetically sorted opcode list for a Csound instance. + * Should be called after csoundCompile() or Csound::Compile(). + */ + +/** + * Returns the number of opcodes, or -1 if there is no list. + */ + +int CsoundOpcodeList::Count() +{ + return cnt; +} + +/** + * Returns the name of the opcode at index 'ndx' (counting from zero), + * or NULL if the index is out of range. + */ + +const char * CsoundOpcodeList::Name(int ndx) +{ + if (lst && (unsigned int) ndx < (unsigned int) cnt) + return lst[ndx].opname; + return (char*) 0; +} + +/** + * Returns the output types of the opcode at index 'ndx' (counting from + * zero), or NULL if the index is out of range. + */ + +const char * CsoundOpcodeList::OutTypes(int ndx) +{ + if (lst && (unsigned int) ndx < (unsigned int) cnt) + return lst[ndx].outypes; + return (char*) 0; +} + +/** + * Returns the input types of the opcode at index 'ndx' (counting from + * zero), or NULL if the index is out of range. + */ + +const char * CsoundOpcodeList::InTypes(int ndx) +{ + if (lst && (unsigned int) ndx < (unsigned int) cnt) + return lst[ndx].intypes; + return (char*) 0; +} + +/** + * Releases the memory used by the opcode list. Should be called + * before the Csound instance is destroyed or reset. + */ + +void CsoundOpcodeList::Clear() +{ + // FIXME: this depends on csoundDisposeOpcodeList() ignoring the + // instance pointer + if (lst) + csoundDisposeOpcodeList((CSOUND*) 0, lst); + lst = (opcodeListEntry*) 0; + cnt = -1; +} + +CsoundOpcodeList::CsoundOpcodeList(CSOUND *csound) +{ + lst = (opcodeListEntry*) 0; + cnt = csoundNewOpcodeList(csound, &lst); + if (cnt < 0 || !lst) { + lst = (opcodeListEntry*) 0; + cnt = -1; + } +} + +CsoundOpcodeList::CsoundOpcodeList(Csound *csound) +{ + lst = (opcodeListEntry*) 0; + cnt = csound->NewOpcodeList(lst); + if (cnt < 0 || !lst) { + lst = (opcodeListEntry*) 0; + cnt = -1; + } +} + +CsoundOpcodeList::~CsoundOpcodeList() +{ + this->Clear(); +} + +// ---------------------------------------------------------------------------- + +/** + * CsoundChannelList(CSOUND *) + * CsoundChannelList(Csound *) + * + * Creates an alphabetically sorted list of named channels of a Csound + * instance. Should be called after csoundCompile() or Csound::Compile(). + */ + +void CsoundChannelList::ResetVariables() +{ + lst = (controlChannelInfo_t*) 0; + cnt = -1; + csound = (CSOUND*) 0; +} + +int CsoundChannelList::GetChannelMetaData(int ndx, + controlChannelHints_t *hints) +{ + const char *name; + if (!lst || (unsigned int) ndx >= (unsigned int) cnt) + return -1; + name = lst[ndx].name; + int ret = csoundGetControlChannelHints(csound, name, hints); + return ret; +} + +/** + * Returns the number of channels (-1 if there is no list). + */ + +int CsoundChannelList::Count() +{ + return cnt; +} + +/** + * Returns the name of the channel at index 'ndx' (counting from zero), + * or NULL if the index is out of range. + */ + +const char * CsoundChannelList::Name(int ndx) +{ + if (lst && (unsigned int) ndx < (unsigned int) cnt) + return lst[ndx].name; + return (char*) 0; +} + +/** + * Returns the type of the channel at index 'ndx' (counting from zero), + * or -1 if the index is out of range. + */ + +int CsoundChannelList::Type(int ndx) +{ + if (lst && (unsigned int) ndx < (unsigned int) cnt) + return lst[ndx].type; + return -1; +} + +/** + * Returns 1 if the channel at index 'ndx' (counting from zero) exists + * and is a control channel, and 0 otherwise. + */ + +int CsoundChannelList::IsControlChannel(int ndx) +{ + if (lst && (unsigned int) ndx < (unsigned int) cnt) + return ((lst[ndx].type & CSOUND_CHANNEL_TYPE_MASK) + == CSOUND_CONTROL_CHANNEL ? 1 : 0); + return 0; +} + +/** + * Returns 1 if the channel at index 'ndx' (counting from zero) exists + * and is an audio channel, and 0 otherwise. + */ + +int CsoundChannelList::IsAudioChannel(int ndx) +{ + if (lst && (unsigned int) ndx < (unsigned int) cnt) + return ((lst[ndx].type & CSOUND_CHANNEL_TYPE_MASK) + == CSOUND_AUDIO_CHANNEL ? 1 : 0); + return 0; +} + +/** + * Returns 1 if the channel at index 'ndx' (counting from zero) exists + * and is a string channel, and 0 otherwise. + */ + +int CsoundChannelList::IsStringChannel(int ndx) +{ + if (lst && (unsigned int) ndx < (unsigned int) cnt) + return ((lst[ndx].type & CSOUND_CHANNEL_TYPE_MASK) + == CSOUND_STRING_CHANNEL ? 1 : 0); + return 0; +} + +/** + * Returns 1 if the channel at index 'ndx' (counting from zero) exists + * and the input bit is set, and 0 otherwise. + */ + +int CsoundChannelList::IsInputChannel(int ndx) +{ + if (lst && (unsigned int) ndx < (unsigned int) cnt) + return ((lst[ndx].type & CSOUND_INPUT_CHANNEL) ? 1 : 0); + return 0; +} + +/** + * Returns 1 if the channel at index 'ndx' (counting from zero) exists + * and the output bit is set, and 0 otherwise. + */ + +int CsoundChannelList::IsOutputChannel(int ndx) +{ + if (lst && (unsigned int) ndx < (unsigned int) cnt) + return ((lst[ndx].type & CSOUND_OUTPUT_CHANNEL) ? 1 : 0); + return 0; +} + +/** + * Returns the sub-type (0: normal, 1: integer, 2: linear, 3: exponential) + * of the control channel at index 'ndx' (counting from zero), or -1 if + * the channel does not exist or is not a control channel. + */ + +int CsoundChannelList::SubType(int ndx) +{ + int tmp; + controlChannelHints_t hints; + tmp = this->GetChannelMetaData(ndx, &hints); + if (tmp >= 0) { + tmp = hints.behav; + } + return tmp; +} + +/** + * Returns the default value set for the control channel at index 'ndx' + * (counting from zero), or 0.0 if the channel does not exist, is not a + * control channel, or has no default value. + */ + +double CsoundChannelList::DefaultValue(int ndx) +{ + controlChannelHints_t hints; + if (this->GetChannelMetaData(ndx, &hints) > 0) + return hints.dflt; + return 0.0; +} + +/** + * Returns the minimum value set for the control channel at index 'ndx' + * (counting from zero), or 0.0 if the channel does not exist, is not a + * control channel, or has no minimum value. + */ + +double CsoundChannelList::MinValue(int ndx) +{ + controlChannelHints_t hints; + if (this->GetChannelMetaData(ndx, &hints) > 0) + return hints.min; + return 0.0; +} + +/** + * Returns the maximum value set for the control channel at index 'ndx' + * (counting from zero), or 0.0 if the channel does not exist, is not a + * control channel, or has no maximum value. + */ + +double CsoundChannelList::MaxValue(int ndx) +{ + controlChannelHints_t hints; + if (this->GetChannelMetaData(ndx, &hints) > 0) + return hints.max; + return 0.0; +} + +/** + * Releases the memory used by the channel list. Should be called + * before the Csound instance is destroyed or reset. + */ + +void CsoundChannelList::Clear() +{ + // FIXME: this depends on csoundDeleteChannelList() ignoring the + // instance pointer + if (lst) + csoundDeleteChannelList((CSOUND*) 0, lst); + this->ResetVariables(); +} + +CsoundChannelList::CsoundChannelList(CSOUND *csound) +{ + lst = (controlChannelInfo_t*) 0; + cnt = csoundListChannels(csound, &lst); + this->csound = csound; + if (cnt < 0 || !lst) + this->ResetVariables(); +} + +CsoundChannelList::CsoundChannelList(Csound *csound) +{ + lst = (controlChannelInfo_t*) 0; + cnt = csound->ListChannels(lst); + this->csound = csound->GetCsound(); + if (cnt < 0 || !lst) + this->ResetVariables(); +} + +CsoundChannelList::~CsoundChannelList() +{ + this->Clear(); +} + +// ---------------------------------------------------------------------------- + +/** + * CsoundUtilityList(CSOUND *) + * CsoundUtilityList(Csound *) + * + * Creates an alphabetically sorted list of utilities registered + * for a Csound instance. Should be called after csoundPreCompile() + * or Csound::PreCompile(). + */ + +/** + * Returns the number of utilities, or -1 if there is no list. + */ + +int CsoundUtilityList::Count() +{ + return cnt; +} + +/** + * Returns the name of the utility at index 'ndx' (counting from zero), + * or NULL if the index is out of range. + */ + +const char * CsoundUtilityList::Name(int ndx) +{ + if (lst && (unsigned int) ndx < (unsigned int) cnt) + return lst[ndx]; + return (char*) 0; +} + +/** + * Releases the memory used by the utility list. Should be called + * before the Csound instance is destroyed or reset. + */ + +void CsoundUtilityList::Clear() +{ + // FIXME: this depends on csoundDeleteUtilityList() ignoring the + // instance pointer + if (lst) + csoundDeleteUtilityList((CSOUND*) 0, lst); + lst = (char**) 0; + cnt = -1; +} + +CsoundUtilityList::CsoundUtilityList(CSOUND *csound) +{ + int n = -1; + lst = csoundListUtilities(csound); + if (lst) { + while (lst[++n]) + ; + } + cnt = n; +} + +CsoundUtilityList::CsoundUtilityList(Csound *csound) +{ + int n = -1; + lst = csound->ListUtilities(); + if (lst) { + while (lst[++n]) + ; + } + cnt = n; +} + +CsoundUtilityList::~CsoundUtilityList() +{ + this->Clear(); +} + +// ---------------------------------------------------------------------------- + +/** + * CsoundMYFLTArray() + * + * Creates a pointer for use with csoundGetChannelPtr(), + * csoundGetOutputBuffer(), or other functions that return a + * pointer to an array of floating point values. + * + * CsoundMYFLTArray(int cnt) + * + * Allocates an array of 'cnt' floating point values, for use + * with Csound API functions that take a MYFLT* pointer. + */ + +/** + * Stores a string in the array (note: only do this with a pointer + * returned by csoundGetChannelPtr()), optionally limiting the length to + * maxLen - 1 characters. + */ +// FIXME - this is broken and does not work with STRINGDAT +void CsoundMYFLTArray::SetStringValue(const char *s, int maxLen) +{ + if (p) { + int i = 0; + if (s && --maxLen > 0) { + while (s[i]) { + ((char*) p)[i] = s[i]; + if (++i >= maxLen) + break; + } + } + ((char*) p)[i] = (char) '\0'; + } +} + +/** + * Returns a string from the array (note: only do this with a pointer + * returned by csoundGetChannelPtr()), or NULL if there is no array. + */ + +const char * CsoundMYFLTArray::GetStringValue() +{ + return ((STRINGDAT*) p)->data; +} + +/** + * Clears the array pointer, and releases any memory that was allocated + * by calling the constructor with a positive number of elements. + */ + +void CsoundMYFLTArray::Clear() +{ + if (pp) + free(pp); + p = (MYFLT*) 0; + pp = (void*) 0; +} + +CsoundMYFLTArray::CsoundMYFLTArray() +{ + p = (MYFLT*) 0; + pp = (void*) 0; +} + +CsoundMYFLTArray::CsoundMYFLTArray(int n) +{ + p = (MYFLT*) 0; + pp = (void*) 0; + if (n > 0) + pp = (void*) malloc((size_t) n * sizeof(MYFLT)); + if (pp) { + p = (MYFLT*) pp; + for (int i = 0; i < n; i++) + p[i] = (MYFLT) 0; + } +} + +CsoundMYFLTArray::~CsoundMYFLTArray() +{ + this->Clear(); +} + +// ---------------------------------------------------------------------------- + +/** + * A simple class for creating argv[] lists for use with + * functions like csoundCompile(). + */ + +void CsoundArgVList::destroy_argv() +{ + for (int i = 0; i < cnt; i++) + free((void*) ArgV_[i]); + if (ArgV_) + free((void*) ArgV_); + ArgV_ = (char**) 0; + cnt = -1; +} + +/** + * Returns the count of arguments in the list, zero if there are + * none, and -1 if the list could not be allocated. + */ + +int CsoundArgVList::argc() +{ + return cnt; +} + +/** + * Returns a char** pointer for use with csoundCompile() etc. + */ + +char ** CsoundArgVList::argv() +{ + return ArgV_; +} + +/** + * Returns the argument at the specified index (counting from zero), + * or NULL if the index is out of range. + */ + +const char * CsoundArgVList::argv(int ndx) +{ + if (ArgV_ && (unsigned int) ndx < (unsigned int) cnt) + return ArgV_[ndx]; + return (char*) 0; +} + +/** + * Inserts a new value to the argument list at the specified index + * (counting from zero). If there is not enough memory, the list is + * not changed. + */ + +void CsoundArgVList::Insert(int ndx, const char *s) +{ + char **new_argv; + int new_cnt, i; + + if (!s) + return; + if (ndx > cnt) + ndx = cnt; + if (ndx < 0) + ndx = 0; + new_cnt = (cnt >= 0 ? cnt + 1 : 1); + new_argv = (char**) malloc((size_t) (new_cnt + 1) * sizeof(char*)); + if (!new_argv) + return; + for (i = 0; i < ndx; i++) + new_argv[i] = ArgV_[i]; + new_argv[i] = (char*) malloc(strlen(s) + (size_t) 1); + if (!new_argv[i]) { + free((void*) new_argv); + return; + } + strcpy(new_argv[i], s); + while (++i < new_cnt) + new_argv[i] = ArgV_[i - 1]; + new_argv[i] = (char*) 0; + if (ArgV_) + free((void*) ArgV_); + ArgV_ = new_argv; + cnt = new_cnt; +} + +/** + * Appends a new value at the end of the argument list. + * If there is not enough memory, the list is not changed. + */ + +void CsoundArgVList::Append(const char *s) +{ + this->Insert(0x7FFFFFFF, s); +} + +/** + * Removes all elements of the list. + */ + +void CsoundArgVList::Clear() +{ + this->destroy_argv(); + ArgV_ = (char**) malloc(sizeof(char*)); + if (ArgV_) { + ArgV_[0] = (char*) 0; + cnt = 0; + } + else + cnt = -1; +} + +CsoundArgVList::CsoundArgVList() +{ + cnt = -1; + ArgV_ = (char**) malloc(sizeof(char*)); + if (ArgV_) { + ArgV_[0] = (char*) 0; + cnt = 0; + } +} + +CsoundArgVList::~CsoundArgVList() +{ + this->destroy_argv(); +} + +// ---------------------------------------------------------------------------- + +/** + * Experimental class for wrapping callbacks using SWIG directors. + */ + +extern "C" { + + static CS_NOINLINE void MessageCallback_wrapper(CSOUND *csound, + int attr, const char *fmt, va_list args) + { + CsoundCallbackWrapper *p; + p = (CsoundCallbackWrapper*) csoundGetHostData(csound); +#if defined(HAVE_C99) && !defined(WIN32) + { + char buf[2048]; + int n; + n = vsnprintf(&(buf[0]), (size_t) 2048, fmt, args); + if (n < 0) { // for compatibility only + fprintf(stderr, " *** buffer overflow in message callback\n"); + exit(-1); + } + else if (n >= 2048) { + char *bufp = (char*) malloc((size_t) n + (size_t) 1); + if (bufp) { + vsprintf(bufp, fmt, args); + p->MessageCallback(attr, bufp); + free((void*) bufp); + } + } + else + p->MessageCallback(attr, &(buf[0])); + } +#else + { + char buf[16384]; + if (vsprintf(&(buf[0]), fmt, args) >= 16384) { + fprintf(stderr, " *** buffer overflow in message callback\n"); + exit(-1); + } + p->MessageCallback(attr, &(buf[0])); + } +#endif + } + + /** + static CS_NOINLINE void InputValueCallback_wrapper(CSOUND *csound, + const char *chnName, MYFLT *value) + { + CsoundCallbackWrapper *p; + p = (CsoundCallbackWrapper*) csoundGetHostData(csound); + *value = (MYFLT) p->InputValueCallback(chnName); + } + */ + /** + static CS_NOINLINE void OutputValueCallback_wrapper(CSOUND *csound, + const char *chnName, MYFLT value) + { + CsoundCallbackWrapper *p; + p = (CsoundCallbackWrapper*) csoundGetHostData(csound); + p->OutputValueCallback(chnName, (double) value); + } + */ + static CS_NOINLINE int YieldCallback_wrapper(CSOUND *csound) + { + CsoundCallbackWrapper *p; + p = (CsoundCallbackWrapper*) csoundGetHostData(csound); + return p->YieldCallback(); + } + +} // extern "C" + +void CsoundCallbackWrapper::SetMessageCallback() +{ + csoundSetMessageCallback(csound_, MessageCallback_wrapper); +} + + /*void CsoundCallbackWrapper::SetInputValueCallback() +{ + csoundSetInputValueCallback(csound_, InputValueCallback_wrapper); +} + +void CsoundCallbackWrapper::SetOutputValueCallback() +{ + csoundSetOutputValueCallback(csound_, OutputValueCallback_wrapper); +} + */ +void CsoundCallbackWrapper::SetYieldCallback() +{ + csoundSetYieldCallback(csound_, YieldCallback_wrapper); +} + +void CsoundCallbackWrapper::SetMidiInputCallback(CsoundArgVList *argv) +{ + csoundSetExternalMidiInOpenCallback(csound_, midiInOpenCallback); + csoundSetExternalMidiReadCallback(csound_, midiInReadCallback); + csoundSetExternalMidiInCloseCallback(csound_, midiInCloseCallback); + if (argv != (CsoundArgVList*) 0) { + argv->Append("-+rtmidi=null"); + argv->Append("-M0"); + } + csoundMessage(csound_, + "rtmidi: CsoundCallbackWrapper::MidiInputCallback() " + "enabled\n"); +} + +void CsoundCallbackWrapper::SetMidiOutputCallback(CsoundArgVList *argv) +{ + csoundSetExternalMidiOutOpenCallback(csound_, midiOutOpenCallback); + csoundSetExternalMidiWriteCallback(csound_, midiOutWriteCallback); + csoundSetExternalMidiOutCloseCallback(csound_, midiOutCloseCallback); + if (argv != (CsoundArgVList*) 0) { + argv->Append("-+rtmidi=null"); + argv->Append("-Q0"); + } + csoundMessage(csound_, + "rtmidi: CsoundCallbackWrapper::MidiOutputCallback() " + "enabled\n"); +} + +CsoundCallbackWrapper::CsoundCallbackWrapper(Csound *cs) +{ + csound_ = cs->GetCsound(); + cs->SetHostData((void*) this); +} + +CsoundCallbackWrapper::CsoundCallbackWrapper(CSOUND *cs) +{ + csound_ = cs; + csoundSetHostData(cs, (void*) this); +} + +int CsoundCallbackWrapper::midiInOpenCallback(CSOUND *csound, void **userData, + const char *devName) +{ + (void) devName; + (*userData) = csoundGetHostData(csound); + return 0; +} + +int CsoundCallbackWrapper::midiInReadCallback(CSOUND *csound, void *userData, + unsigned char *buf, int nBytes) +{ + CsoundMidiInputBuffer buf_(buf, nBytes); + int bytesRead; + + (void) csound; + ((CsoundCallbackWrapper*) userData)->MidiInputCallback(&buf_); + bytesRead = buf_.bufBytes; + return bytesRead; +} + +int CsoundCallbackWrapper::midiInCloseCallback(CSOUND *csound, void *userData) +{ + (void) csound; + (void) userData; + return 0; +} + +int CsoundCallbackWrapper::midiOutOpenCallback(CSOUND *csound, void **userData, + const char *devName) +{ + (void) devName; + (*userData) = csoundGetHostData(csound); + return 0; +} + +int CsoundCallbackWrapper::midiOutWriteCallback(CSOUND *csound, void *userData, + const unsigned char *buf, + int nBytes) +{ + CsoundMidiOutputBuffer buf_((unsigned char*) buf, nBytes); + int bytesWritten; + + (void) csound; + buf_.bufBytes = nBytes; + ((CsoundCallbackWrapper*) userData)->MidiOutputCallback(&buf_); + bytesWritten = nBytes - buf_.bufBytes; + return bytesWritten; +} + +int CsoundCallbackWrapper::midiOutCloseCallback(CSOUND *csound, void *userData) +{ + (void) csound; + (void) userData; + return 0; +} + /* +void CsoundCallbackWrapper::SetChannelIOCallbacks() +{ + csoundSetChannelIOCallback(csound_, + (CsoundChannelIOCallback_t) + ChannelIOCallback_wrapper); +} + */ +// ---------------------------------------------------------------------------- + +static const unsigned char midiMessageByteCnt[32] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 0, 1 +}; + +CsoundMidiInputBuffer::CsoundMidiInputBuffer(unsigned char *buf, int bufSize) +{ + this->buf = buf; + mutex_ = csoundCreateMutex(0); + bufReadPos = 0; + bufWritePos = 0; + bufBytes = 0; + this->bufSize = bufSize; +} + +CsoundMidiInputBuffer::~CsoundMidiInputBuffer() +{ + buf = (unsigned char*) 0; + csoundDestroyMutex(mutex_); + mutex_ = (void*) 0; +} + +/** + * Sends a MIDI message, 'msg' is calculated as follows: + * STATUS + DATA1 * 256 + DATA2 * 65536 + */ + +void CsoundMidiInputBuffer::SendMidiMessage(int msg) +{ + int nBytes = (int) midiMessageByteCnt[(msg & (int) 0xF8) >> 3]; + + if (!nBytes) + return; + csoundLockMutex(mutex_); + if ((bufBytes + nBytes) <= bufSize) { + buf[bufWritePos] = (unsigned char) msg & (unsigned char) 0xFF; + bufWritePos = (bufWritePos < (bufSize - 1) ? bufWritePos + 1 : 0); + bufBytes++; + if (nBytes > 1) { + buf[bufWritePos] = (unsigned char) (msg >> 8) & (unsigned char) 0x7F; + bufWritePos = (bufWritePos < (bufSize - 1) ? bufWritePos + 1 : 0); + bufBytes++; + if (nBytes > 2) { + buf[bufWritePos] = (unsigned char) (msg >> 16) + & (unsigned char) 0x7F; + bufWritePos = (bufWritePos < (bufSize - 1) ? bufWritePos + 1 : 0); + bufBytes++; + } + } + } + csoundUnlockMutex(mutex_); +} + +/** + * Sends a MIDI message; 'channel' should be in the range 1 to 16, + * and data1 and data2 should be in the range 0 to 127. + */ + +void CsoundMidiInputBuffer::SendMidiMessage(int status, int channel, + int data1, int data2) +{ + int nBytes = (int) midiMessageByteCnt[(status & (int) 0xF8) >> 3]; + + if (!nBytes) + return; + csoundLockMutex(mutex_); + if ((bufBytes + nBytes) <= bufSize) { + unsigned char st = (unsigned char) status & (unsigned char) 0xFF; + if (nBytes > 1) { + st = (st & (unsigned char) 0xF0) + + ((unsigned char) (status + channel - 1) & (unsigned char) 0x0F); + } + buf[bufWritePos] = st; + bufWritePos = (bufWritePos < (bufSize - 1) ? bufWritePos + 1 : 0); + bufBytes++; + if (nBytes > 1) { + buf[bufWritePos] = (unsigned char) data1 & (unsigned char) 0x7F; + bufWritePos = (bufWritePos < (bufSize - 1) ? bufWritePos + 1 : 0); + bufBytes++; + if (nBytes > 2) { + buf[bufWritePos] = (unsigned char) data2 & (unsigned char) 0x7F; + bufWritePos = (bufWritePos < (bufSize - 1) ? bufWritePos + 1 : 0); + bufBytes++; + } + } + } + csoundUnlockMutex(mutex_); +} + +/** + * Sends a note-on message on 'channel' (1 to 16) for 'key' (0 to 127) + * with 'velocity' (0 to 127). + */ + +void CsoundMidiInputBuffer::SendNoteOn(int channel, int key, int velocity) +{ + SendMidiMessage((int) 0x90, channel, key, velocity); +} + +/** + * Sends a note-off message on 'channel' (1 to 16) for 'key' (0 to 127) + * with 'velocity' (0 to 127). + */ + +void CsoundMidiInputBuffer::SendNoteOff(int channel, int key, int velocity) +{ + SendMidiMessage((int) 0x80, channel, key, velocity); +} + +/** + * Sends a note-off message on 'channel' (1 to 16) for 'key', + * using a 0x90 status with zero velocity. + */ + +void CsoundMidiInputBuffer::SendNoteOff(int channel, int key) +{ + SendMidiMessage((int) 0x90, channel, key, 0); +} + +/** + * Sets polyphonic pressure on 'channel' (1 to 16) to 'value' (0 to 127) + * for 'key' (0 to 127). + */ + +void CsoundMidiInputBuffer::SendPolyphonicPressure(int channel, int key, + int value) +{ + SendMidiMessage((int) 0xA0, channel, key, value); +} + +/** + * Sets controller 'ctl' (0 to 127) to 'value' (0 to 127) + * on 'channel' (1 to 16). + */ + +void CsoundMidiInputBuffer::SendControlChange(int channel, int ctl, int value) +{ + SendMidiMessage((int) 0xB0, channel, ctl, value); +} + +/** + * Sends program change to 'pgm' (1 to 128) on 'channel' (1 to 16). + */ + +void CsoundMidiInputBuffer::SendProgramChange(int channel, int pgm) +{ + SendMidiMessage((int) 0xC0, channel, pgm - 1, 0); +} + +/** + * Sets channel pressure to 'value' (0 to 127) on 'channel' (1 to 16). + */ + +void CsoundMidiInputBuffer::SendChannelPressure(int channel, int value) +{ + SendMidiMessage((int) 0xD0, channel, value, 0); +} + +/** + * Sets pitch bend to 'value' (-8192 to 8191) on 'channel' (1 to 16). + */ + +void CsoundMidiInputBuffer::SendPitchBend(int channel, int value) +{ + SendMidiMessage((int) 0xE0, channel, + (value + 8192) & (int) 0x7F, + ((value + 8192) >> 7) & (int) 0x7F); +} + +/** + * Copies at most 'nBytes' bytes of MIDI data from the buffer to 'buf'. + * Returns the number of bytes copied. + */ + +int CsoundMidiInputBuffer::GetMidiData(unsigned char *buf, int nBytes) +{ + int i; + + if (!bufBytes) + return 0; + csoundLockMutex(mutex_); + for (i = 0; i < nBytes && bufBytes > 0; i++) { + buf[i] = this->buf[bufReadPos]; + bufReadPos = (bufReadPos < (bufSize - 1) ? bufReadPos + 1 : 0); + bufBytes--; + } + csoundUnlockMutex(mutex_); + return i; +} + +// ---------------------------------------------------------------------------- + +/** + * The following class allows sending MIDI input messages to a Csound + * instance. + */ + +CsoundMidiInputStream::CsoundMidiInputStream(CSOUND *csound) + : CsoundMidiInputBuffer(&(buf_[0]), 4096) +{ + this->csound = csound; +} + +CsoundMidiInputStream::CsoundMidiInputStream(Csound *csound) + : CsoundMidiInputBuffer(&(buf_[0]), 4096) +{ + this->csound = csound->GetCsound(); +} + +int CsoundMidiInputStream::midiInOpenCallback(CSOUND *csound, void **userData, + const char *devName) +{ + (void) devName; + (*userData) = *((void**) csoundQueryGlobalVariable(csound, + "__csnd_MidiInObject")); + return 0; +} + +int CsoundMidiInputStream::midiInReadCallback(CSOUND *csound, void *userData, + unsigned char *buf, int nBytes) +{ + (void) csound; + return ((CsoundMidiInputStream*) userData)->GetMidiData(buf, nBytes); +} + +int CsoundMidiInputStream::midiInCloseCallback(CSOUND *csound, void *userData) +{ + (void) csound; + (void) userData; + return 0; +} + +/** + * Enables MIDI input for the associated Csound instance. + * Should be called between csoundPreCompile() and csoundCompile(). + * If 'argv' is not NULL, the command line arguments required for + * MIDI input are appended. + */ + +void CsoundMidiInputStream::EnableMidiInput(CsoundArgVList *argv) +{ + csoundCreateGlobalVariable(csound, "__csnd_MidiInObject", + sizeof(void*)); + *((void**) csoundQueryGlobalVariable(csound, "__csnd_MidiInObject")) = + (void*) this; + csoundSetExternalMidiInOpenCallback(csound, midiInOpenCallback); + csoundSetExternalMidiReadCallback(csound, midiInReadCallback); + csoundSetExternalMidiInCloseCallback(csound, midiInCloseCallback); + if (argv != (CsoundArgVList*) 0) { + argv->Append("-+rtmidi=null"); + argv->Append("-M0"); + } + csoundMessage(csound, "rtmidi: CsoundMidiInputStream enabled\n"); +} + +// ---------------------------------------------------------------------------- + +CsoundMidiOutputBuffer::CsoundMidiOutputBuffer(unsigned char *buf, int bufSize) +{ + this->buf = buf; + mutex_ = csoundCreateMutex(0); + bufReadPos = 0; + bufWritePos = 0; + bufBytes = 0; + this->bufSize = bufSize; +} + +CsoundMidiOutputBuffer::~CsoundMidiOutputBuffer() +{ + buf = (unsigned char*) 0; + csoundDestroyMutex(mutex_); + mutex_ = (void*) 0; +} + +/** + * Pops and returns the first message from the buffer, in the following + * format: + * STATUS + DATA1 * 256 + DATA2 * 65536 + * where STATUS also includes the channel number (0 to 15), if any. + * The return value is zero if there are no messages. + */ + +int CsoundMidiOutputBuffer::PopMessage() +{ + int msg = 0; + + if (bufBytes) { + csoundLockMutex(mutex_); + if (bufBytes > 0) { + int nBytes; + unsigned char st; + + st = buf[bufReadPos] & (unsigned char) 0xFF; + nBytes = (int) midiMessageByteCnt[(st & (unsigned char) 0xF8) >> 3]; + if (nBytes > 0 && bufBytes >= nBytes) { + bufReadPos = (bufReadPos < (bufSize - 1) ? bufReadPos + 1 : 0); + bufBytes--; + msg = (int) st; + if (nBytes > 1) { + msg += ((int) (buf[bufReadPos] & (unsigned char) 0x7F) << 8); + bufReadPos = (bufReadPos < (bufSize - 1) ? bufReadPos + 1 : 0); + bufBytes--; + if (nBytes > 2) { + msg += ((int) (buf[bufReadPos] & (unsigned char) 0x7F) << 16); + bufReadPos = (bufReadPos < (bufSize - 1) ? bufReadPos + 1 : 0); + bufBytes--; + } + } + } + else { + // invalid MIDI data, discard the rest of the buffer + bufReadPos = bufWritePos; + bufBytes = 0; + } + } + csoundUnlockMutex(mutex_); + } + return msg; +} + +/** + * Returns the status byte for the first message in the buffer, not + * including the channel number in the case of channel messages. + * The return value is zero if there are no messages. + */ + +int CsoundMidiOutputBuffer::GetStatus() +{ + unsigned char st = (unsigned char) 0; + + if (bufBytes) { + csoundLockMutex(mutex_); + if (bufBytes > 0) { + int nBytes; + st = buf[bufReadPos] & (unsigned char) 0xFF; + nBytes = (int) midiMessageByteCnt[(st & (unsigned char) 0xF8) >> 3]; + if (nBytes <= 0 || bufBytes < nBytes) + st = (unsigned char) 0; // invalid MIDI data + if (nBytes > 1) + st &= (unsigned char) 0xF0; // channel msg: remove channel number + } + csoundUnlockMutex(mutex_); + } + return (int) st; +} + +/** + * Returns the channel number (1 to 16) for the first message in the + * buffer. The return value is zero if there are no messages, or the + * first message is not a channel message. + */ + +int CsoundMidiOutputBuffer::GetChannel() +{ + unsigned char st = (unsigned char) 0; + + if (bufBytes) { + csoundLockMutex(mutex_); + if (bufBytes > 0) { + int nBytes; + st = buf[bufReadPos] & (unsigned char) 0xFF; + nBytes = (int) midiMessageByteCnt[(st & (unsigned char) 0xF8) >> 3]; + if (nBytes < 2 || bufBytes < nBytes) + st = (unsigned char) 0; // invalid MIDI data, or system message + else + st = (st & (unsigned char) 0x0F) + (unsigned char) 1; + } + csoundUnlockMutex(mutex_); + } + return (int) st; +} + +/** + * Returns the first data byte (0 to 127) for the first message in the + * buffer. The return value is zero if there are no messages, or the + * first message does not have any data bytes. + */ + +int CsoundMidiOutputBuffer::GetData1() +{ + unsigned char st, d1 = (unsigned char) 0; + + if (bufBytes) { + csoundLockMutex(mutex_); + if (bufBytes > 0) { + int nBytes; + st = buf[bufReadPos] & (unsigned char) 0xFF; + nBytes = (int) midiMessageByteCnt[(st & (unsigned char) 0xF8) >> 3]; + if (nBytes >= 2 && bufBytes >= nBytes) { + int pos = bufReadPos; + pos = (pos < (bufSize - 1) ? pos + 1 : 0); + d1 = buf[pos] & (unsigned char) 0x7F; + } + } + csoundUnlockMutex(mutex_); + } + return (int) d1; +} + +/** + * Returns the second data byte (0 to 127) for the first message in the + * buffer. The return value is zero if there are no messages, or the + * first message has less than two data bytes. + */ + +int CsoundMidiOutputBuffer::GetData2() +{ + unsigned char st, d2 = (unsigned char) 0; + + if (bufBytes) { + csoundLockMutex(mutex_); + if (bufBytes > 0) { + int nBytes; + st = buf[bufReadPos] & (unsigned char) 0xFF; + nBytes = (int) midiMessageByteCnt[(st & (unsigned char) 0xF8) >> 3]; + if (nBytes >= 3 && bufBytes >= nBytes) { + int pos = bufReadPos; + pos = (pos < (bufSize - 1) ? pos + 1 : 0); + pos = (pos < (bufSize - 1) ? pos + 1 : 0); + d2 = buf[pos] & (unsigned char) 0x7F; + } + } + csoundUnlockMutex(mutex_); + } + return (int) d2; +} + +/** + * Copies at most 'nBytes' bytes of MIDI data to the buffer from 'buf'. + * Returns the number of bytes copied. + */ + +int CsoundMidiOutputBuffer::SendMidiData(const unsigned char *buf, int nBytes) +{ + int i; + + csoundLockMutex(mutex_); + for (i = 0; i < nBytes && bufBytes < bufSize; i++) { + this->buf[bufWritePos] = buf[i]; + bufWritePos = (bufWritePos < (bufSize - 1) ? bufWritePos + 1 : 0); + bufBytes++; + } + csoundUnlockMutex(mutex_); + return i; +} + +// ---------------------------------------------------------------------------- + +/** + * The following class allows receiving MIDI output messages + * from a Csound instance. + */ + +CsoundMidiOutputStream::CsoundMidiOutputStream(CSOUND *csound) + : CsoundMidiOutputBuffer(&(buf_[0]), 4096) +{ + this->csound = csound; +} + +CsoundMidiOutputStream::CsoundMidiOutputStream(Csound *csound) + : CsoundMidiOutputBuffer(&(buf_[0]), 4096) +{ + this->csound = csound->GetCsound(); +} + +int CsoundMidiOutputStream::midiOutOpenCallback(CSOUND *csound, + void **userData, + const char *devName) +{ + (void) devName; + (*userData) = *((void**) csoundQueryGlobalVariable(csound, + "__csnd_MidiOutObject")); + return 0; +} + +int CsoundMidiOutputStream::midiOutWriteCallback(CSOUND *csound, + void *userData, + const unsigned char *buf, + int nBytes) +{ + (void) csound; + return ((CsoundMidiOutputStream*) userData)->SendMidiData(buf, nBytes); +} + +int CsoundMidiOutputStream::midiOutCloseCallback(CSOUND *csound, + void *userData) +{ + (void) csound; + (void) userData; + return 0; +} + +/** + * Enables MIDI output for the associated Csound instance. + * Should be called between csoundPreCompile() and csoundCompile(). + * If 'argv' is not NULL, the command line arguments required for + * MIDI output are appended. + */ + +void CsoundMidiOutputStream::EnableMidiOutput(CsoundArgVList *argv) +{ + csoundCreateGlobalVariable(csound, "__csnd_MidiOutObject", + sizeof(void*)); + *((void**) csoundQueryGlobalVariable(csound, "__csnd_MidiOutObject")) = + (void*) this; + csoundSetExternalMidiOutOpenCallback(csound, midiOutOpenCallback); + csoundSetExternalMidiWriteCallback(csound, midiOutWriteCallback); + csoundSetExternalMidiOutCloseCallback(csound, midiOutCloseCallback); + if (argv != (CsoundArgVList*) 0) { + argv->Append("-+rtmidi=null"); + argv->Append("-Q0"); + } + csoundMessage(csound, "rtmidi: CsoundMidiOutputStream enabled\n"); +} + +}; + diff --git a/CsoundAC/cs_glue.hpp b/CsoundAC/cs_glue.hpp new file mode 100644 index 0000000000..fd021e0c42 --- /dev/null +++ b/CsoundAC/cs_glue.hpp @@ -0,0 +1,707 @@ +/* + cs_glue.hpp: + + Copyright (C) 2005, 2006 Istvan Varga + + This file is part of Csound. + + The Csound Library is free software; you can redistribute it + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + Csound is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with Csound; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + 02110-1301 USA +*/ + +#ifndef CSOUND_CS_GLUE_HPP +#define CSOUND_CS_GLUE_HPP + +/** + * CsoundOpcodeList(CSOUND *) + * CsoundOpcodeList(Csound *) + * + * Creates an alphabetically sorted opcode list for a Csound instance. + * Should be called after csoundCompile() or Csound::Compile(). + */ + +class PUBLIC CsoundOpcodeList { + private: + opcodeListEntry *lst; + int cnt; + public: + /** + * Returns the number of opcodes, or -1 if there is no list. + */ + int Count(); + /** + * Returns the name of the opcode at index 'ndx' (counting from zero), + * or NULL if the index is out of range. + */ + const char *Name(int ndx); + /** + * Returns the output types of the opcode at index 'ndx' (counting from + * zero), or NULL if the index is out of range. + */ + const char *OutTypes(int ndx); + /** + * Returns the input types of the opcode at index 'ndx' (counting from + * zero), or NULL if the index is out of range. + */ + const char *InTypes(int ndx); + /** + * Releases the memory used by the opcode list. Should be called + * before the Csound instance is destroyed or reset. + */ + void Clear(); + // -------- + CsoundOpcodeList(CSOUND *csound); + CsoundOpcodeList(Csound *csound); + ~CsoundOpcodeList(); +}; + +/** + * CsoundChannelList(CSOUND *) + * CsoundChannelList(Csound *) + * + * Creates an alphabetically sorted list of named channels of a Csound + * instance. Should be called after csoundCompile() or Csound::Compile(). + */ + +class PUBLIC CsoundChannelList { + private: + controlChannelInfo_t *lst; + int cnt; + CSOUND *csound; + void ResetVariables(); + int GetChannelMetaData(int ndx, controlChannelHints_t *hints); + public: + /** + * Returns the number of channels (-1 if there is no list). + */ + int Count(); + /** + * Returns the name of the channel at index 'ndx' (counting from zero), + * or NULL if the index is out of range. + */ + const char *Name(int ndx); + /** + * Returns the type of the channel at index 'ndx' (counting from zero), + * or -1 if the index is out of range. + */ + int Type(int ndx); + /** + * Returns 1 if the channel at index 'ndx' (counting from zero) exists + * and is a control channel, and 0 otherwise. + */ + int IsControlChannel(int ndx); + /** + * Returns 1 if the channel at index 'ndx' (counting from zero) exists + * and is an audio channel, and 0 otherwise. + */ + int IsAudioChannel(int ndx); + /** + * Returns 1 if the channel at index 'ndx' (counting from zero) exists + * and is a string channel, and 0 otherwise. + */ + int IsStringChannel(int ndx); + /** + * Returns 1 if the channel at index 'ndx' (counting from zero) exists + * and the input bit is set, and 0 otherwise. + */ + int IsInputChannel(int ndx); + /** + * Returns 1 if the channel at index 'ndx' (counting from zero) exists + * and the output bit is set, and 0 otherwise. + */ + int IsOutputChannel(int ndx); + /** + * Returns the sub-type (0: normal, 1: integer, 2: linear, 3: exponential) + * of the control channel at index 'ndx' (counting from zero), or -1 if + * the channel does not exist or is not a control channel. + */ + int SubType(int ndx); + /** + * Returns the default value set for the control channel at index 'ndx' + * (counting from zero), or 0.0 if the channel does not exist, is not a + * control channel, or has no default value. + */ + double DefaultValue(int ndx); + /** + * Returns the minimum value set for the control channel at index 'ndx' + * (counting from zero), or 0.0 if the channel does not exist, is not a + * control channel, or has no minimum value. + */ + double MinValue(int ndx); + /** + * Returns the maximum value set for the control channel at index 'ndx' + * (counting from zero), or 0.0 if the channel does not exist, is not a + * control channel, or has no maximum value. + */ + double MaxValue(int ndx); + /** + * Releases the memory used by the channel list. Should be called + * before the Csound instance is destroyed or reset. + */ + void Clear(); + // -------- + CsoundChannelList(CSOUND *csound); + CsoundChannelList(Csound *csound); + ~CsoundChannelList(); +}; + +/** + * CsoundUtilityList(CSOUND *) + * CsoundUtilityList(Csound *) + * + * Creates an alphabetically sorted list of utilities registered + * for a Csound instance. Should be called after csoundPreCompile() + * or Csound::PreCompile(). + */ + +class PUBLIC CsoundUtilityList { + private: + char **lst; + int cnt; + public: + /** + * Returns the number of utilities, or -1 if there is no list. + */ + int Count(); + /** + * Returns the name of the utility at index 'ndx' (counting from zero), + * or NULL if the index is out of range. + */ + const char *Name(int ndx); + /** + * Releases the memory used by the utility list. Should be called + * before the Csound instance is destroyed or reset. + */ + void Clear(); + // -------- + CsoundUtilityList(CSOUND *csound); + CsoundUtilityList(Csound *csound); + ~CsoundUtilityList(); +}; + +/** + * CsoundMYFLTArray() + * + * Creates a pointer for use with csoundGetChannelPtr(), + * csoundGetOutputBuffer(), or other functions that return a + * pointer to an array of floating point values. + * + * CsoundMYFLTArray(int cnt) + * + * Allocates an array of 'cnt' floating point values, for use + * with Csound API functions that take a MYFLT* pointer. + */ + +class PUBLIC CsoundMYFLTArray { + private: + MYFLT *p; + void *pp; + public: + /** + * Returns a MYFLT** pointer for use with csoundGetChannelPtr(). + */ + MYFLT **GetPtr() + { + return (&p); + } + /** + * Returns the address of the element at index 'ndx' (counting from + * zero) as a MYFLT* pointer, or NULL if there is no array. Does not + * check if 'ndx' is valid. + */ + MYFLT *GetPtr(int ndx) + { + if (p) + return &(p[ndx]); + return (MYFLT*) 0; + } + /** + * Sets the array pointer to a MYFLT* value returned by a Csound + * API function (e.g. csoundGetSpin() or csoundGetSpout()). + */ + void SetPtr(MYFLT *ptr) + { + p = ptr; + } + /** + * Stores a floating point value at index 'ndx' (counting from zero). + * No error checking is done, the array is assumed to exist and the + * index is assumed to be valid. + */ + void SetValue(int ndx, double value) + { + p[ndx] = (MYFLT) value; + } + /** + * Sets two floating point values starting at index 'ndx' (counting + * from zero). No error checking is done, the array is assumed to exist + * and the index is assumed to be valid. + */ + void SetValues(int ndx, double v0, double v1) + { + p[ndx] = (MYFLT) v0; p[ndx + 1] = (MYFLT) v1; + } + /** + * Sets three floating point values starting at index 'ndx' (counting + * from zero). No error checking is done, the array is assumed to exist + * and the index is assumed to be valid. + */ + void SetValues(int ndx, double v0, double v1, double v2) + { + p[ndx] = (MYFLT) v0; p[ndx + 1] = (MYFLT) v1; + p[ndx + 2] = (MYFLT) v2; + } + /** + * Sets four floating point values starting at index 'ndx' (counting + * from zero). No error checking is done, the array is assumed to exist + * and the index is assumed to be valid. + */ + void SetValues(int ndx, double v0, double v1, double v2, double v3) + { + p[ndx] = (MYFLT) v0; p[ndx + 1] = (MYFLT) v1; + p[ndx + 2] = (MYFLT) v2; p[ndx + 3] = (MYFLT) v3; + } + /** + * Sets five floating point values starting at index 'ndx' (counting + * from zero). No error checking is done, the array is assumed to exist + * and the index is assumed to be valid. + */ + void SetValues(int ndx, + double v0, double v1, double v2, double v3, double v4) + { + p[ndx] = (MYFLT) v0; p[ndx + 1] = (MYFLT) v1; + p[ndx + 2] = (MYFLT) v2; p[ndx + 3] = (MYFLT) v3; + p[ndx + 4] = (MYFLT) v4; + } + /** + * Sets six floating point values starting at index 'ndx' (counting + * from zero). No error checking is done, the array is assumed to exist + * and the index is assumed to be valid. + */ + void SetValues(int ndx, + double v0, double v1, double v2, double v3, double v4, + double v5) + { + p[ndx] = (MYFLT) v0; p[ndx + 1] = (MYFLT) v1; + p[ndx + 2] = (MYFLT) v2; p[ndx + 3] = (MYFLT) v3; + p[ndx + 4] = (MYFLT) v4; p[ndx + 5] = (MYFLT) v5; + } + /** + * Sets seven floating point values starting at index 'ndx' (counting + * from zero). No error checking is done, the array is assumed to exist + * and the index is assumed to be valid. + */ + void SetValues(int ndx, + double v0, double v1, double v2, double v3, double v4, + double v5, double v6) + { + p[ndx] = (MYFLT) v0; p[ndx + 1] = (MYFLT) v1; + p[ndx + 2] = (MYFLT) v2; p[ndx + 3] = (MYFLT) v3; + p[ndx + 4] = (MYFLT) v4; p[ndx + 5] = (MYFLT) v5; + p[ndx + 6] = (MYFLT) v6; + } + /** + * Sets eight floating point values starting at index 'ndx' (counting + * from zero). No error checking is done, the array is assumed to exist + * and the index is assumed to be valid. + */ + void SetValues(int ndx, + double v0, double v1, double v2, double v3, double v4, + double v5, double v6, double v7) + { + p[ndx] = (MYFLT) v0; p[ndx + 1] = (MYFLT) v1; + p[ndx + 2] = (MYFLT) v2; p[ndx + 3] = (MYFLT) v3; + p[ndx + 4] = (MYFLT) v4; p[ndx + 5] = (MYFLT) v5; + p[ndx + 6] = (MYFLT) v6; p[ndx + 7] = (MYFLT) v7; + } + /** + * Sets nine floating point values starting at index 'ndx' (counting + * from zero). No error checking is done, the array is assumed to exist + * and the index is assumed to be valid. + */ + void SetValues(int ndx, + double v0, double v1, double v2, double v3, double v4, + double v5, double v6, double v7, double v8) + { + p[ndx] = (MYFLT) v0; p[ndx + 1] = (MYFLT) v1; + p[ndx + 2] = (MYFLT) v2; p[ndx + 3] = (MYFLT) v3; + p[ndx + 4] = (MYFLT) v4; p[ndx + 5] = (MYFLT) v5; + p[ndx + 6] = (MYFLT) v6; p[ndx + 7] = (MYFLT) v7; + p[ndx + 8] = (MYFLT) v8; + } + /** + * Sets ten floating point values starting at index 'ndx' (counting + * from zero). No error checking is done, the array is assumed to exist + * and the index is assumed to be valid. + */ + void SetValues(int ndx, + double v0, double v1, double v2, double v3, double v4, + double v5, double v6, double v7, double v8, double v9) + { + p[ndx] = (MYFLT) v0; p[ndx + 1] = (MYFLT) v1; + p[ndx + 2] = (MYFLT) v2; p[ndx + 3] = (MYFLT) v3; + p[ndx + 4] = (MYFLT) v4; p[ndx + 5] = (MYFLT) v5; + p[ndx + 6] = (MYFLT) v6; p[ndx + 7] = (MYFLT) v7; + p[ndx + 8] = (MYFLT) v8; p[ndx + 9] = (MYFLT) v9; + } + /** + * Returns the floating point value at index 'ndx' (counting from zero). + * No error checking is done, the array is assumed to exist and the + * index is assumed to be valid. + */ + double GetValue(int ndx) + { + return (double) p[ndx]; + } + /** + * Copies 'n' values to the array from a source pointer, starting at + * index 'ndx' (counting from zero). No error checking is done. + */ + void SetValues(int ndx, int n, const MYFLT *src) + { + for (int i = 0; i < n; i++) + p[ndx + i] = src[i]; + } + /** + * Copies 'n' values from the array to 'dst', starting at index 'ndx' + * (counting from zero). No error checking is done. + */ + void GetValues(MYFLT *dst, int ndx, int n) + { + for (int i = 0; i < n; i++) + dst[i] = p[ndx + i]; + } + /** + * Stores a string in the array (note: only do this with a pointer + * returned by csoundGetChannelPtr()), optionally limiting the length to + * maxLen - 1 characters. + */ + void SetStringValue(const char *s, int maxLen); + /** + * Returns a string from the array (note: only do this with a pointer + * returned by csoundGetChannelPtr()), or NULL if there is no array. + */ + const char *GetStringValue(); + /** + * Clears the array pointer, and releases any memory that was allocated + * by calling the constructor with a positive number of elements. + */ + void Clear(); + // -------- + CsoundMYFLTArray(); + CsoundMYFLTArray(int n); + ~CsoundMYFLTArray(); +}; + +/** + * A simple class for creating argv[] lists for use with + * functions like csoundCompile(). + */ + +class PUBLIC CsoundArgVList { + private: + char **ArgV_; + int cnt; + void destroy_argv(); + public: + /** + * Returns the count of arguments in the list, zero if there are + * none, and -1 if the list could not be allocated. + */ + int argc(); + /** + * Returns a char** pointer for use with csoundCompile() etc. + */ + char **argv(); + /** + * Returns the argument at the specified index (counting from zero), + * or NULL if the index is out of range. + */ + const char *argv(int ndx); + /** + * Inserts a new value to the argument list at the specified index + * (counting from zero). If there is not enough memory, the list is + * not changed. + */ + void Insert(int ndx, const char *s); + /** + * Appends a new value at the end of the argument list. + * If there is not enough memory, the list is not changed. + */ + void Append(const char *s); + /** + * Removes all elements of the list. + */ + void Clear(); + // -------- + CsoundArgVList(); + ~CsoundArgVList(); +}; + +/** + * Experimental class for wrapping callbacks using SWIG directors. + */ + +class CsoundMidiInputBuffer; +class CsoundMidiOutputBuffer; + +class PUBLIC CsoundCallbackWrapper { + private: + CSOUND *csound_; + public: + virtual void MessageCallback(int attr, char *msg) + { + (void) attr; + (void) msg; + } + virtual double InputValueCallback(const char *chnName) + { + (void) chnName; + return 0.0; + } + virtual void OutputValueCallback(const char *chnName, double value) + { + (void) chnName; + (void) value; + } + virtual int YieldCallback() + { + return 1; + } + virtual void MidiInputCallback(CsoundMidiInputBuffer *p) + { + (void) p; + } + virtual void MidiOutputCallback(CsoundMidiOutputBuffer *p) + { + (void) p; + } + + void SetMessageCallback(); + // void SetInputValueCallback(); + // void SetOutputValueCallback(); + void SetYieldCallback(); + void SetMidiInputCallback(CsoundArgVList *argv); + void SetMidiOutputCallback(CsoundArgVList *argv); + // void SetChannelIOCallbacks(); + CSOUND *GetCsound() + { + return csound_; + } + // for converting SWIG char* type to a Python string + static const char *CharPtrToString(const char *s) + { + return s; + } + // -------- + CsoundCallbackWrapper(Csound *csound); + CsoundCallbackWrapper(CSOUND *csound); + virtual ~CsoundCallbackWrapper() + { + } + private: + static int midiInOpenCallback(CSOUND *, void **, const char *); + static int midiInReadCallback(CSOUND *, void *, unsigned char *, int); + static int midiInCloseCallback(CSOUND *, void *); + static int midiOutOpenCallback(CSOUND *, void **, const char *); + static int midiOutWriteCallback(CSOUND *, void *, + const unsigned char *, int); + static int midiOutCloseCallback(CSOUND *, void *); +}; + +// ---------------------------- MIDI INPUT ---------------------------- + +class PUBLIC CsoundMidiInputBuffer { + private: + unsigned char *buf; + void *mutex_; + int bufReadPos; + int bufWritePos; + int bufBytes; + int bufSize; + public: + CsoundMidiInputBuffer(unsigned char *buf, int bufSize); + ~CsoundMidiInputBuffer(); + /** + * Sends a MIDI message, 'msg' is calculated as follows: + * STATUS + DATA1 * 256 + DATA2 * 65536 + */ + void SendMidiMessage(int msg); + /** + * Sends a MIDI message; 'channel' should be in the range 1 to 16, + * and data1 and data2 should be in the range 0 to 127. + */ + void SendMidiMessage(int status, int channel, int data1, int data2); + /** + * Sends a note-on message on 'channel' (1 to 16) for 'key' (0 to 127) + * with 'velocity' (0 to 127). + */ + void SendNoteOn(int channel, int key, int velocity); + /** + * Sends a note-off message on 'channel' (1 to 16) for 'key' (0 to 127) + * with 'velocity' (0 to 127). + */ + void SendNoteOff(int channel, int key, int velocity); + /** + * Sends a note-off message on 'channel' (1 to 16) for 'key', + * using a 0x90 status with zero velocity. + */ + void SendNoteOff(int channel, int key); + /** + * Sets polyphonic pressure on 'channel' (1 to 16) to 'value' (0 to 127) + * for 'key' (0 to 127). + */ + void SendPolyphonicPressure(int channel, int key, int value); + /** + * Sets controller 'ctl' (0 to 127) to 'value' (0 to 127) + * on 'channel' (1 to 16). + */ + void SendControlChange(int channel, int ctl, int value); + /** + * Sends program change to 'pgm' (1 to 128) on 'channel' (1 to 16). + */ + void SendProgramChange(int channel, int pgm); + /** + * Sets channel pressure to 'value' (0 to 127) on 'channel' (1 to 16). + */ + void SendChannelPressure(int channel, int value); + /** + * Sets pitch bend to 'value' (-8192 to 8191) on 'channel' (1 to 16). + */ + void SendPitchBend(int channel, int value); + // ----------------------------------------------------------------- + friend class CsoundCallbackWrapper; + protected: + /** + * Copies at most 'nBytes' bytes of MIDI data from the buffer to 'buf'. + * Returns the number of bytes copied. + */ + int GetMidiData(unsigned char *buf, int nBytes); +}; + +/** + * The following class allows sending MIDI input messages to a Csound + * instance. + */ + +class PUBLIC CsoundMidiInputStream : public CsoundMidiInputBuffer { + private: + unsigned char buf_[4096]; + CSOUND *csound; + public: + CsoundMidiInputStream(CSOUND *csound); + CsoundMidiInputStream(Csound *csound); + //~CsoundMidiInputStream() + //{ + //} + /** + * Enables MIDI input for the associated Csound instance. + * Should be called between csoundPreCompile() and csoundCompile(). + * If 'argv' is not NULL, the command line arguments required for + * MIDI input are appended. + */ + void EnableMidiInput(CsoundArgVList *argv); + private: + static int midiInOpenCallback(CSOUND *, void **, const char *); + static int midiInReadCallback(CSOUND *, void *, unsigned char *, int); + static int midiInCloseCallback(CSOUND *, void *); +}; + +// ---------------------------- MIDI OUTPUT --------------------------- + +class PUBLIC CsoundMidiOutputBuffer { + private: + unsigned char *buf; + void *mutex_; + int bufReadPos; + int bufWritePos; + int bufBytes; + int bufSize; + public: + CsoundMidiOutputBuffer(unsigned char *buf, int bufSize); + ~CsoundMidiOutputBuffer(); + /** + * Pops and returns the first message from the buffer, in the following + * format: + * STATUS + DATA1 * 256 + DATA2 * 65536 + * where STATUS also includes the channel number (0 to 15), if any. + * The return value is zero if there are no messages. + */ + int PopMessage(); + /** + * Returns the status byte for the first message in the buffer, not + * including the channel number in the case of channel messages. + * The return value is zero if there are no messages. + */ + int GetStatus(); + /** + * Returns the channel number (1 to 16) for the first message in the + * buffer. The return value is zero if there are no messages, or the + * first message is not a channel message. + */ + int GetChannel(); + /** + * Returns the first data byte (0 to 127) for the first message in the + * buffer. The return value is zero if there are no messages, or the + * first message does not have any data bytes. + */ + int GetData1(); + /** + * Returns the second data byte (0 to 127) for the first message in the + * buffer. The return value is zero if there are no messages, or the + * first message has less than two data bytes. + */ + int GetData2(); + // ----------------------------------------------------------------- + friend class CsoundCallbackWrapper; + protected: + /** + * Copies at most 'nBytes' bytes of MIDI data to the buffer from 'buf'. + * Returns the number of bytes copied. + */ + int SendMidiData(const unsigned char *buf, int nBytes); +}; + +/** + * The following class allows receiving MIDI output messages + * from a Csound instance. + */ + +class PUBLIC CsoundMidiOutputStream : public CsoundMidiOutputBuffer { + private: + unsigned char buf_[4096]; + CSOUND *csound; + public: + CsoundMidiOutputStream(CSOUND *csound); + CsoundMidiOutputStream(Csound *csound); + //~CsoundMidiOutputStream() + //{ + //} + /** + * Enables MIDI output for the associated Csound instance. + * Should be called between csoundPreCompile() and csoundCompile(). + * If 'argv' is not NULL, the command line arguments required for + * MIDI output are appended. + */ + void EnableMidiOutput(CsoundArgVList *argv); + private: + static int midiOutOpenCallback(CSOUND *, void **, const char *); + static int midiOutWriteCallback(CSOUND *, void *, + const unsigned char *, int); + static int midiOutCloseCallback(CSOUND *, void *); +}; + +#endif // CSOUND_CS_GLUE_HPP + diff --git a/CsoundAC/csound.asd b/CsoundAC/csound.asd new file mode 100644 index 0000000000..9677109a1b --- /dev/null +++ b/CsoundAC/csound.asd @@ -0,0 +1,19 @@ +;;; +;;; ASDF 3.1 compliant system definition file for Csound. +;;; +;;; Michael Gogins +;;; 11 July 2016 +;;; +(require "asdf") +(asdf::defsystem "csound" + :name "csound" + :description "CFFI interface to the Csound C API." + :long-description "CFFI interface to the Csound C API." + :version "1.0" + :author "Michael Gogins " + :licence "LGPL" + :serial t ;; the dependencies are linear. + :depends-on (:cffi) + :components + ((:file "csound"))) + diff --git a/CsoundAC/csound.lisp b/CsoundAC/csound.lisp new file mode 100644 index 0000000000..182accfed3 --- /dev/null +++ b/CsoundAC/csound.lisp @@ -0,0 +1,394 @@ +; L I S P C F F I I N T E R F A C E F O R C S O U N D . H +; +; Copyright (C) 2016 Michael Gogins +; +; This file belongs to Csound. +; +; This software is free software; you can redistribute it and/or +; modify it under the terms of the GNU Lesser General Public +; License as published by the Free Software Foundation; either +; version 2.1 of the License, or (at your option) any later version. +; +; This software is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; Lesser General Public License for more details. +; +; You should have received a copy of the GNU Lesser General Public +; License along with this software; if not, write to the Free Software +; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +; +; This file is handwritten and should be maintained by keeping it up to date +; with regard to include/csound.h. This file is not intended to be complete +; and essentially defines a Lisp interface to a subset of the most useful +; functions in csound.h. At the present time, only pointers and +; other primitive types are used in this interface. +; +; Please note, in particular, that all strings passed to Csound are foreign +; strings, created for example with (setq foreign-string +; (cffi:foreign-string-alloc lisp-string)) + +(defpackage :csound + (:use :common-lisp :cffi) + (:export + :csoundSetControlChannel + :csoundInitialize + :csoundCreate + :csoundDestroy + :csoundGetVersion + :csoundGetAPIVersion + :csoundCompileOrc + :csoundEvalCode + :csoundCompileArgs + :csoundStart + :csoundCompile + :csoundCompileCsd + :csoundCompileCsdText + :csoundPerform + :csoundPerformKsmps + :csoundPerformBuffer + :csoundStop + :csoundCleanup + :csoundReset + :csoundGetSr + :csoundGetKr + :csoundGetKsmps + :csoundGetNchnls + :csoundGetNchnlsInput + :csoundGet0dBFS + :csoundGetCurrentTimeSamples + :csoundGetSizeOfMYFLT + :csoundGetHostData + :csoundSetHostData + :csoundSetOption + :csoundGetOutputName + :csoundSetOutput + :csoundSetInput + :csoundSetMIDIInput + :csoundSetMIDIFileInput + :csoundSetMIDIFileOutput + :csoundSetRTAudioModule + :csoundGetInputBufferSize + :csoundGetOutputBufferSize + :csoundGetInputBuffer + :csoundGetOutputBuffer + :csoundGetSpin + :csoundReadScore + )) +(cffi:define-foreign-library libcsound64 + (:darwin "libcsound64.dylib") + (:unix "libcsound64.so") + (:windows "csound64.dll") + (t (:default "libcsound64"))) +(cffi:use-foreign-library libcsound64) +(in-package :csound) + +; You can paste below here new definitions including those created +; e.g. by SWIG. Be sure to TEST any changes you make to this file! + +; (cffi:defcfun ("csoundTableLength" csoundTableLength) :int + ; (csound :pointer) + ; (table :int)) + +; (cffi:defcfun ("csoundTableGet" csoundTableGet) :double + ; (csound :pointer) + ; (table :int) + ; (index :int)) + +; (cffi:defcfun ("csoundTableSet" csoundTableSet) :void + ; (csound :pointer) + ; (table :int) + ; (index :int) + ; (valu :double)) + +; (cffi:defcfun ("csoundRunUtility" csoundRunUtility) :int + ; (csound :pointer) + ; (nayme :pointer) + ; (argc :int) + ; (argv :pointer)) + +; (cffi:defcfun ("csoundMessage" csoundMessage) :void + ; (csound :pointer) + ; (control :pointer) + ; &rest) + +; (defun csoundMessage (csound control &rest values) + ; (cffi:foreign-funcall "csoundMessage" csound :pointer control :pointer &rest values :void)) + +(cffi:defcfun ("csoundSetControlChannel" csoundSetControlChannel) :void + (csound :pointer) + (name :pointer) + (value :double)) + +(cffi:defcfun ("csoundInitialize" csoundInitialize) :int + (flags :int)) + +(cffi:defcfun ("csoundCreate" csoundCreate) :pointer + (host-data :pointer)) + +(cffi:defcfun ("csoundDestroy" csoundDestroy) :void + (csound :pointer)) + +(cffi:defcfun ("csoundGetVersion" csoundGetVersion) :int) + +(cffi:defcfun ("csoundGetAPIVersion" csoundGetAPIVersion) :int) + +(cffi:defcfun ("csoundCompileOrc" csoundCompileOrc) :int + (csound :pointer) + (orc :pointer)) + +(cffi:defcfun ("csoundEvalCode" csoundEvalCode) :double + (csound :pointer) + (orc :pointer)) + +(cffi:defcfun ("csoundCompileArgs" csoundCompileArgs) :int + (csound :pointer) + (argc :int) + (argv :pointer)) + +(cffi:defcfun ("csoundStart" csoundStart) :int + (csound :pointer)) + +(cffi:defcfun ("csoundCompile" csoundCompile) :int + (csound :pointer) + (argc :int) + (argv :pointer)) + +(cffi:defcfun ("csoundCompileCsd" csoundCompileCsd) :int + (csound :pointer) + (csd-pathname :pointer)) + +(cffi:defcfun ("csoundCompileCsdText" csoundCompileCsdText) :int + (csound :pointer) + (csd-text :pointer)) + +(cffi:defcfun ("csoundPerform" csoundPerform) :int + (csound :pointer)) + +(cffi:defcfun ("csoundPerformKsmps" csoundPerformKsmps) :int + (csound :pointer)) + +(cffi:defcfun ("csoundPerformBuffer" csoundPerformBuffer) :int + (csound :pointer)) + +(cffi:defcfun ("csoundStop" csoundStop) :void + (csound :pointer)) + +(cffi:defcfun ("csoundCleanup" csoundCleanup) :int + (csound :pointer)) + +(cffi:defcfun ("csoundReset" csoundReset) :void + (csound :pointer)) + +(cffi:defcfun ("csoundGetSr" csoundGetSr) :double + (csound :pointer)) + +(cffi:defcfun ("csoundGetKr" csoundGetKr) :double + (csound :pointer)) + +(cffi:defcfun ("csoundGetKsmps" csoundGetKsmps) :int32 + (csound :pointer)) + +(cffi:defcfun ("csoundGetNchnls" csoundGetNchnls) :int32 + (csound :pointer)) + +(cffi:defcfun ("csoundGetNchnlsInput" csoundGetNchnlsInput) :int32 + (csound :pointer)) + +(cffi:defcfun ("csoundGet0dBFS" csoundGet0dBFS) :double + (csound :pointer)) + +(cffi:defcfun ("csoundGetCurrentTimeSamples" csoundGetCurrentTimeSamples) :int64 + (csound :pointer)) + +(cffi:defcfun ("csoundGetSizeOfMYFLT" csoundGetSizeOfMYFLT) :int) + +(cffi:defcfun ("csoundGetHostData" csoundGetHostData) :pointer + (csound :pointer)) + +(cffi:defcfun ("csoundSetHostData" csoundSetHostData) :void + (csound :pointer) + (hostData :pointer)) + +(cffi:defcfun ("csoundSetOption" csoundSetOption) :int + (csound :pointer) + (option :pointer)) + +(cffi:defcfun ("csoundGetOutputName" csoundGetOutputName) :pointer + (csound :pointer)) + +(cffi:defcfun ("csoundSetOutput" csoundSetOutput) :void + (csound :pointer) + (nayme :pointer) + (tipe :pointer) + (format :pointer)) + +(cffi:defcfun ("csoundSetInput" csoundSetInput) :void + (csound :pointer) + (nayme :pointer)) + +(cffi:defcfun ("csoundSetMIDIInput" csoundSetMIDIInput) :void + (csound :pointer) + (nayme :pointer)) + +(cffi:defcfun ("csoundSetMIDIFileInput" csoundSetMIDIFileInput) :void + (csound :pointer) + (nayme :pointer)) + +(cffi:defcfun ("csoundSetMIDIOutput" csoundSetMIDIOutput) :void + (csound :pointer) + (nayme :pointer)) + +(cffi:defcfun ("csoundSetMIDIFileOutput" csoundSetMIDIFileOutput) :void + (csound :pointer) + (nayme :pointer)) + +(cffi:defcfun ("csoundSetRTAudioModule" csoundSetRTAudioModule) :void + (csound :pointer) + (moduule :pointer)) + +(cffi:defcfun ("csoundGetInputBufferSize" csoundGetInputBufferSize) :long + (csound :pointer)) + +(cffi:defcfun ("csoundGetOutputBufferSize" csoundGetOutputBufferSize) :long + (csound :pointer)) + + (cffi:defcfun ("csoundGetInputBuffer" csoundGetInputBuffer) :pointer + (csound :pointer)) + +(cffi:defcfun ("csoundGetOutputBuffer" csoundGetOutputBuffer) :pointer + (csound :pointer)) + +(cffi:defcfun ("csoundGetSpin" csoundGetSpin) :pointer + (csound :pointer)) + +; (cffi:defcfun ("csoundAddSpinSample" csoundAddSpinSample) :void + ; (csound :pointer) + ; (frayme :int) + ; (channel :int) + ; (sample :float)) + +; (cffi:defcfun ("csoundGetSpout" csoundGetSpout) :pointer + ; (csound :pointer)) + +; (cffi:defcfun ("csoundGetSpoutSample" csoundGetSpoutSample) :double + ; (csound :pointer) + ; (frame :int) + ; (channel :int)) + +(cffi:defcfun ("csoundReadScore" csoundReadScore) :int + (csound :pointer) + (score :pointer)) + +; (cffi:defcfun ("csoundGetScoreTime" csoundGetScoreTime) :double + ; (csound :pointer)) + +; (cffi:defcfun ("csoundIsScorePending" csoundIsScorePending) :int + ; (csound :pointer)) + +; (cffi:defcfun ("csoundSetScorePending" csoundSetScorePending) :void + ; (csound :pointer) + ; (pending :int)) + +; (cffi:defcfun ("csoundGetScoreOffsetSeconds" csoundGetScoreOffsetSeconds) :double + ; (csound :pointer)) + +; (cffi:defcfun ("csoundSetScoreOffsetSeconds" csoundSetScoreOffsetSeconds) :void + ; (csound :pointer) + ; (time :double)) + +; (cffi:defcfun ("csoundRewindScore" csoundRewindScore) :void + ; (csound :pointer)) + +; (cffi:defcfun ("csoundGetMessageLevel" csoundGetMessageLevel) :int + ; (csound :pointer)) + +; (cffi:defcfun ("csoundSetMessageLevel" csoundSetMessageLevel) :void + ; (csound :pointer) + ; (messageLevel :int)) + +; (cffi:defcfun ("csoundCreateMessageBuffer" csoundCreateMessageBuffer) :void + ; (csound :pointer) + ; (toStdOut :int)) + +; (cffi:defcfun ("csoundGetFirstMessage" csoundGetFirstMessage) :pointer + ; (csound :pointer)) + +; (cffi:defcfun ("csoundGetFirstMessageAttr" csoundGetFirstMessageAttr) :int + ; (csound :pointer)) + +; (cffi:defcfun ("csoundPopFirstMessage" csoundPopFirstMessage) :void + ; (csound :pointer)) + +; (cffi:defcfun ("csoundGetMessageCnt" csoundGetMessageCnt) :int + ; (csound :pointer)) + +; (cffi:defcfun ("csoundDestroyMessageBuffer" csoundDestroyMessageBuffer) :void + ; (csound :pointer)) + +; (cffi:defcfun ("csoundGetControlChannel" csoundGetControlChannel) :double + ; (csound :pointer) + ; (nayme :pointer) + ; (err :pointer)) + +; (cffi:defcfun ("csoundGetAudioChannel" csoundGetAudioChannel) :void + ; (csound :pointer) + ; (name :pointer) + ; (samples :pointer)) + +; (cffi:defcfun ("csoundSetAudioChannel" csoundSetAudioChannel) :void + ; (csound :pointer) + ; (name :pointer) + ; (samples :pointer)) + +; (cffi:defcfun ("csoundGetStringChannel" csoundGetStringChannel) :void + ; (csound :pointer) + ; (name :pointer) + ; (string :pointer)) + +; (cffi:defcfun ("csoundSetStringChannel" csoundSetStringChannel) :void + ; (csound :pointer) + ; (name :pointer) + ; (string :pointer)) + +; (cffi:defcfun ("csoundScoreEvent" csoundScoreEvent) :int + ; (csound :pointer) + ; (tipe :char) + ; (pFields :pointer) + ; (numFields :long)) + +; (cffi:defcfun ("csoundScoreEventAbsolute" csoundScoreEventAbsolute) :int + ; (csound :pointer) + ; (type :char) + ; (pfields :pointer) + ; (numFields :long) + ; (time_ofs :double)) + +; (cffi:defcfun ("csoundInputMessage" csoundInputMessage) :void + ; (csound :pointer) + ; (message :pointer)) + +; (cffi:defcfun ("csoundIsNamedGEN" csoundIsNamedGEN) :int + ; (csound :pointer) + ; (num :int)) + +; (cffi:defcfun ("csoundGetNamedGEN" csoundGetNamedGEN) :void + ; (csound :pointer) + ; (num :int) + ; (name :pointer) + ; (len :int)) + +; (cffi:defcfun ("csoundAppendOpcode" csoundAppendOpcode) :int + ; (csound :pointer) + ; (opname :pointer) + ; (dsblksiz :int) + ; (flags :int) + ; (thread :int) + ; (outypes :pointer) + ; (intypes :pointer) + ; (iopadr :pointer) + ; (kopadr :pointer) + ; (aopadr :pointer)) + + + diff --git a/CsoundAC/filebuilding.cpp b/CsoundAC/filebuilding.cpp new file mode 100644 index 0000000000..74daef593d --- /dev/null +++ b/CsoundAC/filebuilding.cpp @@ -0,0 +1,226 @@ + +#include "filebuilding.h" +#include +#include +#include +#include + +#ifdef MACOSX +#define gcvt(val,dig,buf) snprintf(buf,dig,"%f",val) +#endif + +struct CsoundFile_ +{ + std::string options; + std::string orchestra; + std::vector score; +}; + +static std::map files; + +#ifdef __cplusplus +extern "C" { +#endif + uintptr_t perfthread(void *data){ + CSOUND *cs = (CSOUND *)data; + int res = 0; + while(res == 0) res = csoundPerformKsmps(cs); + return 0; + } + + PUBLIC void csoundNewCSD(char *path) { + char *argv[2]; + CSOUND *instance; + argv[0] = (char *)malloc(7); + argv[1] = (char *)malloc(strlen(path)+1); + strcpy(argv[0], "csound"); + strcpy(argv[1], path); + + //argv[0] = "csound"; + //argv[1] = path; + + printf("%s \n", argv[1]); + instance = csoundCreate(NULL); + csoundCompile(instance,2,(const char**)argv); + perfthread((void *) instance); + csoundReset(instance); + // csoundDestroy(instance); + free(argv[0]); + free(argv[1]); + + } + + + PUBLIC int csoundPerformLoop(CSOUND *cs){ + csoundCreateThread(perfthread, (void *)cs); + return 1; + } + + PUBLIC void csoundCsdCreate(CSOUND *csound) + { + CsoundFile_ csoundFile; + files[csound] = csoundFile; + } + + PUBLIC void csoundCsdSetOptions(CSOUND *csound, char *options) + { + files[csound].options = options; + } + + PUBLIC const char* csoundCsdGetOptions(CSOUND *csound) + { + return files[csound].options.c_str(); + } + + PUBLIC void csoundCsdSetOrchestra(CSOUND *csound, char *orchestra) + { + files[csound].orchestra = orchestra; + } + + PUBLIC const char* csoundCsdGetOrchestra(CSOUND *csound) + { + return files[csound].orchestra.c_str(); + } + + PUBLIC void csoundCsdAddScoreLine(CSOUND *csound, char *line) + { + files[csound].score.push_back(line); + } + + PUBLIC void csoundCsdAddEvent11(CSOUND *csound, double p1, double p2, double p3, + double p4, double p5, double p6, double p7, + double p8, double p9, double p10, double p11) + { + char note[0x100]; + sprintf(note, "i %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g " + "%-.10g %-.10g %-.10g", p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); + files[csound].score.push_back(note); + } + + PUBLIC void csoundCsdAddEvent10(CSOUND *csound, double p1, double p2, double p3, + double p4, double p5, double p6, double p7, + double p8, double p9, double p10) + { + char note[0x100]; + sprintf(note, "i %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g " + "%-.10g %-.10g", p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); + files[csound].score.push_back(note); + } + + PUBLIC void csoundCsdAddEvent9(CSOUND *csound, double p1, double p2, double p3, + double p4, double p5, double p6, double p7, + double p8, double p9) + { + char note[0x100]; + sprintf(note, "i %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g " + "%-.10g", p1, p2, p3, p4, p5, p6, p7, p8, p9); + files[csound].score.push_back(note); + } + + PUBLIC void csoundCsdAddEvent8(CSOUND *csound, double p1, double p2, double p3, + double p4, double p5, double p6, double p7, + double p8) + { + char note[0x100]; + sprintf(note, "i %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g", + p1, p2, p3, p4, p5, p6, p7, p8); + files[csound].score.push_back(note); + } + PUBLIC void csoundCsdAddEvent7(CSOUND *csound, double p1, double p2, double p3, + double p4, double p5, double p6, double p7) + { + char note[0x100]; + sprintf(note, "i %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g", + p1, p2, p3, p4, p5, p6, p7); + files[csound].score.push_back(note); + } + + PUBLIC void csoundCsdAddEvent6(CSOUND *csound, double p1, double p2, double p3, + double p4, double p5, double p6) + { + char note[0x100]; + sprintf(note, "i %-.10g %-.10g %-.10g %-.10g %-.10g %-.10g", + p1, p2, p3, p4, p5, p6); + files[csound].score.push_back(note); + } + + PUBLIC void csoundCsdAddEvent5(CSOUND *csound, double p1, double p2, double p3, + double p4, double p5) + { + char note[0x100]; + sprintf(note, "i %-.10g %-.10g %-.10g %-.10g %-.10g", p1, p2, p3, p4, p5); + files[csound].score.push_back(note); + } + + PUBLIC void csoundCsdAddEvent4(CSOUND *csound, double p1, double p2, double p3, + double p4) + { + char note[0x100]; + sprintf(note, "i %-.10g %-.10g %-.10g %-.10g", p1, p2, p3, p4); + files[csound].score.push_back(note); + } + + PUBLIC void csoundCsdAddEvent3(CSOUND *csound, double p1, double p2, double p3) + { + char note[0x100]; + sprintf(note, "i %-.10g %-.10g %-.10g", p1, p2, p3); + files[csound].score.push_back(note); + } + + PUBLIC int csoundCsdSave(CSOUND *csound, char *filename) + { + CsoundFile_ &csoundFile = files[csound]; + FILE *file = fopen(filename, "w+"); + fprintf(file, ""); + fprintf(file, ""); + fprintf(file, "%s", csoundFile.options.c_str()); + fprintf(file, ""); + fprintf(file, ""); + fprintf(file, "%s", csoundFile.orchestra.c_str()); + fprintf(file, ""); + fprintf(file, ""); + for (std::vector::iterator it = csoundFile.score.begin(); + it != csoundFile.score.end(); ++it) { + fprintf(file, "%s", (it->c_str())); + } + fprintf(file, ""); + fprintf(file, ""); + return fclose(file); + } + + PUBLIC int csoundCsdCompile(CSOUND *csound, char *filename) + { + csoundCsdSave(csound, filename); + return csoundCompileCsd(csound, filename); + } + + PUBLIC int csoundCsdPerform(CSOUND *csound, char *filename) + { + csoundCsdSave(csound, filename); + return csoundPerformCsd(csound, filename); + } + + /* VL: a new version of this function has been added to the main + Csound library. + PUBLIC int csoundCompileCsd(CSOUND *csound, char *csdFilename) + { + char *argv[2]; + argv[0] = (char*)"csound"; + argv[1] = csdFilename; + return csoundCompile(csound, 2, argv); + } + */ + + PUBLIC int csoundPerformCsd(CSOUND *csound, char *csdFilename) + { + int retval = csoundCompileCsd(csound, csdFilename); + if (!retval) + retval = csoundPerform(csound); + csoundCleanup(csound); + return (retval >= 0 ? 0 : retval); + } + +#ifdef __cplusplus +} +#endif + diff --git a/CsoundAC/filebuilding.h b/CsoundAC/filebuilding.h new file mode 100644 index 0000000000..ef16dfea50 --- /dev/null +++ b/CsoundAC/filebuilding.h @@ -0,0 +1,211 @@ +/* + * C S O U N D + * + * An auto-extensible system for making music on computers + * by means of software alone. + * + * Copyright (C) 2001-2005 Michael Gogins, Matt Ingalls, John D. Ramsdell, + * John P. ffitch, Istvan Varga + * + * L I C E N S E + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef CSOUND_FILEBUILDING_H +#define CSOUND_FILEBUILDING_H + +#include "csound.h" +/** \file + * \brief Csound API functions to create, build up, and save CSD files. + * \author Michael Gogins + * + * \b Purpose + * + * The purpose of these functions is to make it easier for clients + * of the Csound API to programmatically build up CSD files, + * including set instrument definitions, set options, + * and especially append score statements. + * + * There are also convenience functions to compile and perform + * the saved CSD file. + */ +#ifndef PUBLIC +#if (defined(WIN32) || defined(_WIN32)) && !defined(SWIG) +# define PUBLIC __declspec(dllexport) +#elif defined(__GNUC__) && !defined(__MACH__) +# define PUBLIC __attribute__ ( (visibility("default")) ) +#else +# define PUBLIC +#endif +#endif + + /** + * Enables Python interface. + */ + +#ifdef SWIG +#define CS_PRINTF2 +#define CS_PRINTF3 +#include "float-version.h" +#ifndef __MYFLT_DEF +#define __MYFLT_DEF +#ifndef USE_DOUBLE +#define MYFLT float +#else +#define MYFLT double +#endif +#endif +%module filebuilding +%{ +# include "sysdep.h" +# include "text.h" +# include "csound.h" +# include +%} +#else +# include "sysdep.h" +# include "text.h" +# include "csound.h" +# include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + + +/** + * Initialize an internal CSD file. + */ + PUBLIC void csoundCsdCreate(CSOUND *csound); + +/** + * Set the CsOptions element of the internal CSD file. + */ +PUBLIC void csoundCsdSetOptions(CSOUND *csound, char *options); + +/** + * Return the CsOptions element of the internal CSD file. + */ +PUBLIC const char* csoundCsdGetOptions(CSOUND *csound); + +/** + * Set the CsInstruments element of the internal CSD file. + */ +PUBLIC void csoundCsdSetOrchestra(CSOUND *csound, char *orchestra); + +/** + * Return the CsInstruments element of the internal CSD file. + */ +PUBLIC const char* csoundCsdGetOrchestra(CSOUND *csound); + +/** + * Append a line of text to the CsScore element of the internal CSD file. + */ +PUBLIC void csoundCsdAddScoreLine(CSOUND *csound, char *line); + +/** + * Append an 'i' event to the CsScore element of the internal CSD file. + */ +PUBLIC void csoundCsdAddEvent11(CSOUND *csound, double p1, double p2, double p3, + double p4, double p5, double p6, double p7, + double p8, double p9, double p10, double p11); + +/** + * Append an 'i' event to the CsScore element of the internal CSD file. + */ +PUBLIC void csoundCsdAddEvent10(CSOUND *csound, double p1, double p2, double p3, + double p4, double p5, double p6, double p7, + double p8, double p9, double p10); + +/** + * Append an 'i' event to the CsScore element of the internal CSD file. + */ +PUBLIC void csoundCsdAddEvent9(CSOUND *csound, double p1, double p2, double p3, + double p4, double p5, double p6, double p7, + double p8, double p9); + +/** + * Append an 'i' event to the CsScore element of the internal CSD file. + */ +PUBLIC void csoundCsdAddEvent8(CSOUND *csound, double p1, double p2, double p3, + double p4, double p5, double p6, double p7, + double p8); + +/** + * Append an 'i' event to the CsScore element of the internal CSD file. + */ +PUBLIC void csoundCsdAddEvent7(CSOUND *csound, double p1, double p2, double p3, + double p4, double p5, double p6, double p7); + +/** + * Append an 'i' event to the CsScore element of the internal CSD file. + */ +PUBLIC void csoundCsdAddEvent6(CSOUND *csound, double p1, double p2, double p3, + double p4, double p5, double p6); + +/** + * Append an 'i' event to the CsScore element of the internal CSD file. + */ +PUBLIC void csoundCsdAddEvent5(CSOUND *csound, double p1, double p2, double p3, + double p4, double p5); + +/** + * Append an 'i' event to the CsScore element of the internal CSD file. + */ +PUBLIC void csoundCsdAddEvent4(CSOUND *csound, double p1, double p2, double p3, + double p4); + +/** + * Append an 'i' event to the CsScore element of the internal CSD file. + */ +PUBLIC void csoundCsdAddEvent3(CSOUND *csound, double p1, double p2, double p3); + +/** + * Save the internal CSD file to the indicated filename, which must end in '.csd'. + */ +PUBLIC int csoundCsdSave(CSOUND *csound, char *filename); + +/** + * Convenience function that saves the internal CSD file to the indicated filename, + * which must end in '.csd, then performs the file. + */ +PUBLIC int csoundCsdCompile(CSOUND *csound, char *filename); + +/** + * Convenience function that saves the internal CSD file to the indicated filename, + * which must end in '.csd, then compiles the file for later performance. + */ +PUBLIC int csoundCsdPerform(CSOUND *csound, char *filename); + + + /* VL: a new, more complete, version of this function has been added to the main + Csound library. + PUBLIC int csoundCompileCsd(CSOUND *, char *csdFilename); + */ + +/** + * Compiles and renders a Csound performance, + * as directed by the supplied CSD file, + * in one pass. Returns 0 for success. + */ +PUBLIC int csoundPerformCsd(CSOUND *, char *csdFilename); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/CsoundAC/filebuilding.lisp b/CsoundAC/filebuilding.lisp new file mode 100644 index 0000000000..9e9b7d5f69 --- /dev/null +++ b/CsoundAC/filebuilding.lisp @@ -0,0 +1,150 @@ +(defpackage :filebuilding + (:use :common-lisp :cffi)) + +(in-package :filebuilding) + +;;;SWIG wrapper code starts here + +(defmacro defanonenum (&body enums) + "Converts anonymous enums to defconstants." + `(progn ,@(loop for value in enums + for index = 0 then (1+ index) + when (listp value) do (setf index (second value) + value (first value)) + collect `(defconstant ,value ,index)))) + +;;;SWIG wrapper code ends here + + +(defcfun ("csoundCsdCreate" csoundCsdCreate) :void + (csound :pointer)) + +(defcfun ("csoundCsdSetOptions" csoundCsdSetOptions) :void + (csound :pointer) + (options :string)) + +(defcfun ("csoundCsdGetOptions" csoundCsdGetOptions) :string + (csound :pointer)) + +(defcfun ("csoundCsdSetOrchestra" csoundCsdSetOrchestra) :void + (csound :pointer) + (orchestra :string)) + +(defcfun ("csoundCsdGetOrchestra" csoundCsdGetOrchestra) :string + (csound :pointer)) + +(defcfun ("csoundCsdAddScoreLine" csoundCsdAddScoreLine) :void + (csound :pointer) + (line :string)) + +(defcfun ("csoundCsdAddEvent11" csoundCsdAddEvent11) :void + (csound :pointer) + (p1 :double) + (p2 :double) + (p3 :double) + (p4 :double) + (p5 :double) + (p6 :double) + (p7 :double) + (p8 :double) + (p9 :double) + (p10 :double) + (p11 :double)) + +(defcfun ("csoundCsdAddEvent10" csoundCsdAddEvent10) :void + (csound :pointer) + (p1 :double) + (p2 :double) + (p3 :double) + (p4 :double) + (p5 :double) + (p6 :double) + (p7 :double) + (p8 :double) + (p9 :double) + (p10 :double)) + +(defcfun ("csoundCsdAddEvent9" csoundCsdAddEvent9) :void + (csound :pointer) + (p1 :double) + (p2 :double) + (p3 :double) + (p4 :double) + (p5 :double) + (p6 :double) + (p7 :double) + (p8 :double) + (p9 :double)) + +(defcfun ("csoundCsdAddEvent8" csoundCsdAddEvent8) :void + (csound :pointer) + (p1 :double) + (p2 :double) + (p3 :double) + (p4 :double) + (p5 :double) + (p6 :double) + (p7 :double) + (p8 :double)) + +(defcfun ("csoundCsdAddEvent7" csoundCsdAddEvent7) :void + (csound :pointer) + (p1 :double) + (p2 :double) + (p3 :double) + (p4 :double) + (p5 :double) + (p6 :double) + (p7 :double)) + +(defcfun ("csoundCsdAddEvent6" csoundCsdAddEvent6) :void + (csound :pointer) + (p1 :double) + (p2 :double) + (p3 :double) + (p4 :double) + (p5 :double) + (p6 :double)) + +(defcfun ("csoundCsdAddEvent5" csoundCsdAddEvent5) :void + (csound :pointer) + (p1 :double) + (p2 :double) + (p3 :double) + (p4 :double) + (p5 :double)) + +(defcfun ("csoundCsdAddEvent4" csoundCsdAddEvent4) :void + (csound :pointer) + (p1 :double) + (p2 :double) + (p3 :double) + (p4 :double)) + +(defcfun ("csoundCsdAddEvent3" csoundCsdAddEvent3) :void + (csound :pointer) + (p1 :double) + (p2 :double) + (p3 :double)) + +(defcfun ("csoundCsdSave" csoundCsdSave) :int + (csound :pointer) + (filename :string)) + +(defcfun ("csoundCsdCompile" csoundCsdCompile) :int + (csound :pointer) + (filename :string)) + +(defcfun ("csoundCsdPerform" csoundCsdPerform) :int + (csound :pointer) + (filename :string)) + +(defcfun ("csoundCompileCsd" csoundCompileCsd) :int + (arg0 :pointer) + (csdFilename :string)) + +(defcfun ("csoundPerformCsd" csoundPerformCsd) :int + (arg0 :pointer) + (csdFilename :string)) + + diff --git a/CsoundAC/pyMsgCb.cpp b/CsoundAC/pyMsgCb.cpp new file mode 100644 index 0000000000..efb2c53ef0 --- /dev/null +++ b/CsoundAC/pyMsgCb.cpp @@ -0,0 +1,66 @@ +/* + * C S O U N D + * + * L I C E N S E + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "CppSound.hpp" + +extern "C" +{ + int PyRun_SimpleString(const char *string); +} + +static void pythonMessageCallback(CSOUND *csound, + int attr, const char *format, va_list valist) +{ + char buffer[8192]; + static std::string lineBuffer = "print '''"; // FIXME + unsigned int i, len; +#ifdef HAVE_C99 + len = (unsigned int) vsnprintf(&(buffer[0]), (size_t) 8192, format, valist); + if (len >= 8192U) + { + PyRun_SimpleString("print '''Error: message buffer overflow'''"); + return; + } +#else + len = (unsigned int) vsprintf(&(buffer[0]), format, valist); + if (len >= 8192U) + { + PyRun_SimpleString("print '''Error: message buffer overflow'''"); + exit(-1); + } +#endif + for (i = 0; i < len; i++) { + if (buffer[i] == '\n') { + lineBuffer += "'''"; + PyRun_SimpleString(lineBuffer.c_str()); + lineBuffer = "print '''"; + continue; + } + if (buffer[i] == '\'' || buffer[i] == '\\') + lineBuffer += '\\'; + lineBuffer += buffer[i]; + } +} + +void CppSound::setPythonMessageCallback() +{ + SetMessageCallback(pythonMessageCallback); +} + diff --git a/CsoundAC/pyMsgCb_stub.cpp b/CsoundAC/pyMsgCb_stub.cpp new file mode 100644 index 0000000000..6e144043ac --- /dev/null +++ b/CsoundAC/pyMsgCb_stub.cpp @@ -0,0 +1,10 @@ + +// stub to allow compiling a Java wrapper without +// a dependency on the Python library + +#include "CppSound.hpp" + +void CppSound::setPythonMessageCallback() +{ +} + diff --git a/CsoundAC/sb-csound.asd b/CsoundAC/sb-csound.asd new file mode 100644 index 0000000000..be802643ed --- /dev/null +++ b/CsoundAC/sb-csound.asd @@ -0,0 +1,19 @@ +;;; +;;; ASDF 3.1 compliant system definition file for Csound. +;;; +;;; Michael Gogins +;;; 11 July 2016 +;;; +(require :asdf) +(asdf::defsystem "sb-csound" + :description "SBCL FFI interface to the Csound C API." + :long-description "Steel Bank Common Lisp sb-alien interface to the Csound C API." + :version "1.0" + :author "Michael Gogins " + :licence "LLGPL" + :depends-on ("sb-posix" + "cm2") + :serial t ;; the dependencies are linear. + :components + ((:file "sb-csound"))) + diff --git a/CsoundAC/sb-csound.lisp b/CsoundAC/sb-csound.lisp new file mode 100644 index 0000000000..fd61864de1 --- /dev/null +++ b/CsoundAC/sb-csound.lisp @@ -0,0 +1,178 @@ +; S T E E L B A N K C O M M O N L I S P F F I I N T E R F A C E T O C S O U N D . H +; +; Copyright (C) 2016 Michael Gogins +; +; This file belongs to Csound. +; +; This software is free software; you can redistribute it and/or +; modify it under the terms of the GNU Lesser General Public +; License as published by the Free Software Foundation; either +; version 2.1 of the License, or (at your option) any later version. +; +; This software is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; Lesser General Public License for more details. +; +; You should have received a copy of the GNU Lesser General Public +; License along with this software; if not, write to the Free Software +; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +; +; This file is handwritten and should be maintained by keeping it up to date +; with regard to include/csound.h. This file is not intended to be complete +; and essentially defines a Steel Bank Common Lisp interface to a subset of +; the most useful functions in csound.h. At the present time, only pointers, +; strings, and other primitive types are used in this interface. + +(defpackage :sb-csound + (:use :common-lisp :sb-alien :sb-c-call :cm) + (:export + :csoundCompileCsd + :csoundCompileCsdText + :csoundCompileOrc + :csoundCreate + :csoundDestroy + :csoundPerformKsmps + :csoundReadScore + :csoundSetControlChanel + :csoundSetOption + :csoundStart + :csoundCleanup + :render-with-csound + ) +) + +(in-package :sb-csound) + +#+unix (sb-alien:load-shared-object "libcsound64.so") +#+win32 (sb-alien:load-shared-object "csound64.dll") + +(declaim (inline csoundCompileCsd)) +(define-alien-routine "csoundCompileCsd" integer (csound integer) (csd-pathname c-string)) + +(declaim (inline csoundCompileCsdText)) +(define-alien-routine "csoundCompileCsdText" integer (csound integer) (csd-text c-string)) + +(declaim (inline csoundCompileOrc)) +(define-alien-routine "csoundCompileOrc" integer (csound integer) (orc-text c-string)) + +(declaim (inline csoundCreate)) +(define-alien-routine "csoundCreate" integer (host-data integer)) + +(declaim (inline csoundDestroy)) +(define-alien-routine "csoundDestroy" sb-alien:void (csound integer)) + +(declaim (inline csoundPerformKsmps)) +(define-alien-routine "csoundPerformKsmps" integer (csound integer)) + +(declaim (inline csoundReadScore)) +(define-alien-routine "csoundReadScore" integer (csound integer) (sco-text c-string)) + +(declaim (inline csoundSetControlChannel)) +(define-alien-routine "csoundSetControlChannel" sb-alien:void (csound integer) (channel-name c-string) (channel-value double)) + +(declaim (inline csoundSetOption)) +(define-alien-routine "csoundSetOption" integer (csound integer) (one-option c-string)) + +(declaim (inline csoundStart)) +(define-alien-routine "csoundStart" integer (csound integer)) + +(declaim (inline csoundCleanup)) +(define-alien-routine "csoundCleanup" integer (csound integer)) + +(in-package :cm) +(use-package :sb-csound) + +(defun event-to-istatement (event channel-offset velocity-scale) +" +Translates a Common Music MIDI event to a Csound score event +(i-statement), which is terminated with a newline. An offset, which may +be any number, is added to the MIDI channel number. +" + (format nil "i ~,6f ~,6f ~,6f ~,6f ~,6f 0 0 0 0 0 0~%" (+ channel-offset (midi-channel event)) (object-time event)(midi-duration event)(keynum (midi-keynum event))(* velocity-scale (midi-amplitude event))) +) +(export 'event-to-istatement) + +(defun replace-all (string part replacement &key (test #'char=)) +" +Replaces all occurences of the string 'part' in 'string' with 'replacement', +using 'test' for character equality. +" + (with-output-to-string (out) + (loop with part-length = (length part) + for old-pos = 0 then (+ pos part-length) + for pos = (search part string + :start2 old-pos + :test test) + do (write-string string out + :start old-pos + :end (or pos (length string))) + when pos do (write-string replacement out) + while pos))) + +(defun render-csound (sequence csd-text &optional (channel-offset 1) (velocity-scale 127) (csound nil)) +" +Given a Common Music seq 'sequence', translates each of its events into a +Csound 'i' statement, optionally offsetting the channel number and/or +rescaling MIDI velocity, then renders the resulting score using 'csd-text'. +A CSD is used because it can contain any textual Csound input in one block of +raw text. The score generated from 'sequence' is appended to any +lines found in 'csd-text'. This is done so that Csound will quit performing +at the end of the score. It is possible to call csoundReadScore during the +performance. This function returns the Csound object that it uses. + +The optional 'csound' parameter is used to call Csound if passed. This enables +'render-with-csound' to be run in a separate thread of execution, and for +the caller to control Csound instrument parameters during real time +performance, e.g. + +(setq csound (sb-csound:csoundCreate 0)) +(setq my-thread (bt:make-thread (lambda () (render-with-csound cs csd 1 127 csound)))) +(sb-csound:csoundSetControlChannel csound 'mychannel' myvalue) +(bt:join-thread my-thread) + +" + + (let + ((score-list (list)) + (cs) + (sco-text) + (result) + (new-csd-text)) + (progn + (format t "Building Csound score...~%") + (defun curried-event-to-istatement (event) + (event-to-istatement event channel-offset velocity-scale)) + (setq score-list (mapcar 'curried-event-to-istatement (subobjects sequence))) + (setq sco-text (format nil "~{~A~^ ~}" score-list)) + (print sco-text) + (if csound + (setq cs csound) + (progn + (setq cs (sb-csound:csoundCreate 0)) + (format t "csoundCreate returned: ~S.~%" cs) + ) + ) + (setq new-csd-text (replace-all csd-text "" (concatenate 'string sco-text ""))) + (format t "new-csd-text: ~A~%" new-csd-text) + (setq result (sb-csound:csoundCompileCsdText cs new-csd-text)) + (format t "csoundCompileCsdText returned: ~D.~%" result) + (setq result (sb-csound:csoundStart cs)) + (format t "csoundStart returned: ~D.~%" result) + (loop + (setq result (sb-csound:csoundPerformKsmps cs)) + (when (not (equal result 0))(return)) + ) + (setf result(sb-csound:csoundCleanup cs)) + (format t "csoundCleanup returned: ~D.~%" result) + (sleep 5) + (if (not csound) + (sb-csound::csoundDestroy cs) + (format t "csoundDestroy was called.~%") + ) + (format t "The Csound performance has ended: ~D.~%" result) + ) + ) +) + + diff --git a/playpen/playpen.ini b/playpen/playpen.ini index 02528b7db3..efad008a9d 100644 --- a/playpen/playpen.ini +++ b/playpen/playpen.ini @@ -39,7 +39,7 @@ verbose=False [cplusplus] # Uncomment for your platform. # Darwin: -#compiler-command = c++ {} -v --std=gnu++17 -lstdc++ -O3 -g -Wno-write-strings -I. -I/Library/Frameworks/CsoundLib64.framework/Versions/6.0/Headers -I/usr/local/include -I/usr/local/include/csound -I/opt/homebrew/Cellar/eigen/3.4.0_1/include/eigen3 -I/opt/homebrew/Cellar/opencv/4.5.4_3/include/opencv4 -I/opt/homebrew/opt/boost/include -I/opt/local/include /Library/Frameworks/CsoundLib64.framework/Versions/6.0/CsoundLib64 -lCsoundAC -L/opt/homebrew/lib -lsndfile -lgc -lpthread -ldl -lm +# compiler-command = c++ {} -v --std=gnu++17 -lstdc++ -O3 -g -Wno-write-strings -I. -I/Library/Frameworks/CsoundLib64.framework/Versions/6.0/Headers -I/usr/local/include -I/usr/local/include/csound -I/opt/homebrew/include -I/opt/homebrew/include/eigen3 -I/opt/homebrew/Cellar/opencv/4.5.4_3/include/opencv4 -I/opt/homebrew/opt/boost/include -I/opt/local/include /Library/Frameworks/CsoundLib64.framework/Versions/6.0/CsoundLib64 -Wl,-rpath,/usr/local/lib -L/usr/local/lib -L/opt/homebrew/lib -lCsoundAC -lsndfile -lgc -lpthread -ldl -lm # Linux: compiler-command = c++ -v --std=gnu++17 -lstdc++ -O3 -g -Wno-write-strings -I. -I/usr/local/include -I/usr/local/include -I/usr/include/csound -I/usr/local/include/csound -I/home/mkg/csound/interfaces -I/usr/include/eigen3 -lcsound64 -lCsoundAC -lsndfile -lgc -lpthread -ldl -lm # Windows: diff --git a/tests/Parachronic-Piano.cpp b/tests/Parachronic-Piano.cpp new file mode 100644 index 0000000000..18d08ee708 --- /dev/null +++ b/tests/Parachronic-Piano.cpp @@ -0,0 +1,266 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PI (3.141592653589793238462643383279502884197) +#define TWO_PI (6.283185307179586476925286766559005768394) + +/** + * Generators are lambdas with the same signature as the following example. + * The pen is the current position of a "pen" in the score. The pen is + * "written" by appending it to the score. Additional events can be computed + * based on the parameters of the function, and also appended to the score. + * The function can, and usually does, move the pen to a new position before + * returning it. + */ +auto generator = [](const csound::Event &pen, int depth, csound::Score &score, csound::VoiceleadingNode &voiceleadingNode) +{ + csound::Event result = pen; + return result; +}; + +/** + * Computes a deterministic, finite recurrent iterated function system by + * recursively applying a set of generators (transformations) to a pen + * which represents the position of a "pen" on a "score." The entries in + * the transitions matrix represent open or closed paths of recurrence through + * the tree of calls. Because the pen is passed by value, it is in effect + * copied at each call of a generator and at each layer of recursion. The + * generators may or may not append a local copy of the pen to the score, + * thus "writing" a "note" or other event on the "score." + */ +void recurrent(std::vector< std::function > &generators, + Eigen::MatrixXd &transitions, + int depth, + int transformationIndex, + const csound::Event pen, + csound::Score &score, + csound::VoiceleadingNode &voiceleadingNode) +{ + depth = depth - 1; + if (depth == 0) { + return; + } + // std::printf("recurrent(depth: %3d index: %3d %s)\n", depth, transformationIndex, pen.toString().c_str()); + // Index is that of the current transformation. The column vector at that index determines which + // transformations may be applied. + for (int transitionIndex = 0, transitionN = transitions.rows(); transitionIndex < transitionN; ++transitionIndex) { + if (transitions(transformationIndex, transitionIndex)) { + auto newCursor = generators[transitionIndex](pen, depth, score, voiceleadingNode); + recurrent(generators, transitions, depth, transitionIndex, newCursor, score, voiceleadingNode); + } + } +} + +/** + * All composition and synthesis code is defined in the main function. + * There is no need for any of this code to be in a separate file. + */ +int main(int argc, const char **argv) +{ + csound::MusicModel model; + // These fields determine output filenames and ID 3 tags. + model.setAuthor("Michael Gogins"); + model.setTitle("Parachronic-Piano"); + model.setAlbum("Silence"); + model.setYear("2018"); + model.setPerformanceRightsOrganization("Irreducible Productions, ASCAP"); + + std::vector> generators; + + auto g1 = [](const csound::Event &pen_, int depth, csound::Score &score, csound::VoiceleadingNode &voiceleadingNode) { + csound::Event pen = pen_; + if (depth == 1) { + score.append(pen); + } + if (depth <= 1) { + return pen; + } + pen[csound::Event::TIME] = (pen[csound::Event::TIME] * 0.7600) + 0.2125; + pen[csound::Event::KEY] = (pen[csound::Event::KEY] * 1.0000) + 3.21050; + pen[csound::Event::INSTRUMENT] = 4.0 * 1.0 + double(depth % 4); + pen[csound::Event::VELOCITY] = 1.0; + pen[csound::Event::PAN] = .875; + if (depth == 4) { + //voiceleadingNode.C(pen[csound::Event::TIME], "Dm9"); + voiceleadingNode.Q(pen[csound::Event::TIME], -7); + } + if (depth == 3) { + voiceleadingNode.K(pen[csound::Event::TIME]); + } + return pen; + }; + generators.push_back(g1); + + auto g2 = [](const csound::Event &pen_, int depth, csound::Score &score, csound::VoiceleadingNode &voiceleadingNode) { + csound::Event pen = pen_; + if (depth == 1) { + score.append(pen); + } + if (depth <= 2) { + return pen; + } + pen[csound::Event::TIME] = (pen[csound::Event::TIME] * 0.8500) - 0.2700; + pen[csound::Event::KEY] = (pen[csound::Event::KEY] * 0.5000) + 3.0000; + pen[csound::Event::INSTRUMENT] = 4.0 * 2.0 + double(depth % 4); + pen[csound::Event::VELOCITY] = 2.0; + pen[csound::Event::PAN] = .675; + return pen; + }; + generators.push_back(g2); + + auto g3 = [](const csound::Event &pen_, int depth, csound::Score &score, csound::VoiceleadingNode &voiceleadingNode) { + csound::Event pen = pen_; + if (depth == 1) { + score.append(pen); + } + if (depth <= 1) { + return pen; + } + ///pen[csound::Event::TIME] = pen[csound::Event::TIME] * .65 - .27; + pen[csound::Event::TIME] = (pen[csound::Event::TIME] * 0.7500) - 0.2700; + pen[csound::Event::KEY] = (pen[csound::Event::KEY] * 0.5000) - 3.0700; + pen[csound::Event::INSTRUMENT] = 4.0 * 3.0 + double(depth % 4); + pen[csound::Event::VELOCITY] = 1.0; + pen[csound::Event::PAN] = -.675; + return pen; + }; + generators.push_back(g3); + + auto g4 = [](const csound::Event &pen_, int depth, csound::Score &score, csound::VoiceleadingNode &voiceleadingNode) { + csound::Event pen = pen_; + if (depth == 1) { + score.append(pen); + } + if (depth <= 0) { + return pen; + } + pen[csound::Event::TIME] = (pen[csound::Event::TIME] * 0.7900) + 0.2800; + pen[csound::Event::KEY] = (pen[csound::Event::KEY] * 0.5100) - 4.2500; + pen[csound::Event::INSTRUMENT] = 4.0 * 4.5 + double(depth % 4); + pen[csound::Event::VELOCITY] = 2.0; + pen[csound::Event::PAN] = -.875; + if (depth == 2) { + voiceleadingNode.Q(pen[csound::Event::TIME], -5); + } + if (depth == 3) { + voiceleadingNode.K(pen[csound::Event::TIME]); + } + return pen; + }; + generators.push_back(g4); + + auto g5 = [](const csound::Event &pen_, int depth, csound::Score &score, csound::VoiceleadingNode &voiceleadingNode) { + csound::Event pen = pen_; + if (depth == 1) { + score.append(pen); + } + if (depth <= 0) { + return pen; + } + pen[csound::Event::TIME] = (pen[csound::Event::TIME] * 0.7900) - 0.2900; + pen[csound::Event::KEY] = (pen[csound::Event::KEY] * 0.5000) + 4.0000; + pen[csound::Event::INSTRUMENT] = 4.0 * 3.0 + double(depth % 4); + pen[csound::Event::VELOCITY] = 2.0; + pen[csound::Event::PAN] = -.875; + return pen; + }; + generators.push_back(g5); + + // Generate the score. + csound::Event pen = {1,1,144,0,1,1,0,0,0,0,1}; + pen[csound::Event::DURATION] = 0.025; + Eigen::MatrixXd transitions(generators.size(), generators.size()); + transitions << 1, 1, 0, 1, 1, + 1, 1, 0, 1, 1, + 0, 1, 1, 0, 1, + 1, 0, 1, 1, 1, + 0, 1, 1, 0, 1; + csound::ScoreNode scoreNode; + csound::VoiceleadingNode voiceleadingNode; + voiceleadingNode.setModality({0., 2., 5., 7., 11.}); + voiceleadingNode.rescaleTimes = true; + voiceleadingNode.addChild(&scoreNode); + model.addChild(&voiceleadingNode); + csound::Score &score = scoreNode.getScore(); + recurrent(generators, transitions, 9, 0, pen, score, voiceleadingNode); + std::cout << "Generated duration: " << score.getDuration() << std::endl; + score.rescale(csound::Event::TIME, true, 0.0, false, 0.0); + score.rescale(csound::Event::TIME, true, 0.0, false, 0.0); + score.rescale(csound::Event::INSTRUMENT, true, 1.0, true, 0.0); + score.rescale(csound::Event::KEY, true, 36.0, true, 60.0); + score.rescale(csound::Event::VELOCITY, true, 40.0, true, 0.0); + score.rescale(csound::Event::DURATION, true, .30, true, 1.0); + score.rescale(csound::Event::PAN, true, 0.0, true, 0.0); + std::cout << "Move to origin duration:" << score.getDuration() << std::endl; + score.setDuration(240.0); + std::cout << "set duration: " << score.getDuration() << std::endl; + //score.rescale(csound::Event::DURATION, true, 0.25, true, 0.5); + score.temper(12.); + //score.tieOverlappingNotes(true); + score.findScale(); + score.setDuration(60. * 10.); + std::mt19937 mersenneTwister; + std::uniform_real_distribution<> randomvariable(-0.9, +0.9); + for (int i = 0, n = score.size(); i < n; ++i) { + score[i].setPan(randomvariable(mersenneTwister)); + } + for (int i = 0, n = score.size(); i < n; ++i) { + auto original = score[i]; + csound::Event clone(original); + clone.setTime(original.getTime() + std::sin(original.getTime() / 200.) * 2.); + score.append(clone); + } + score.tieOverlappingNotes(true); + score.sort(); + std::cout << "Final duration: " << score.getDuration() << std::endl; + + model.setCsoundOrchestra(R"( +sr = 48000 +ksmps = 128 +nchnls = 2 + alwayson "PianoOut" + + ; Load the Pianoteq into memory. +gipianoteq vstinit "/home/mkg/Pianoteq 7/x86-64bit/Pianoteq 7.so" + + ; Print information about the Pianoteq, such as parameter names and numbers. + vstinfo gipianoteq + + ; Open the Pianoteq's GUI. + ;vstedit gipianoteq + + ; Send notes from the score to the Pianoteq. + instr 1 + ; MIDI channels are numbered starting at 0. + ; p3 always contains the duration of the note. + ; p4 contains the MIDI key number (pitch), + ; p5 contains the MIDI velocity number (loudness), +imidichannel init 0 + vstnote gipianoteq, imidichannel, p4, p5, p3 + endin + + ; Send parameter changes to the Pianoteq. + instr 2 + ; p4 is the parameter number. + ; p5 is the parameter value. + vstparamset gipianoteq, p4, p5 + endin + + ; Send audio from the Pianoteq to the output. + instr PianoOut +ablankinput init 0 +aleft, aright vstaudio gipianoteq, ablankinput, ablankinput + outs aleft, aright + endin + + )"); + model.processArgv(argc, argv); +} + From 52dbea80edad0908fe066fde0a4145a870f94c2a Mon Sep 17 00:00:00 2001 From: Michael Gogins Date: Tue, 21 Nov 2023 10:17:59 -0500 Subject: [PATCH 2/5] Update cmake.yml --- .github/workflows/cmake.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 36662cec96..d81faaea7a 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -4,6 +4,7 @@ on: push: branches: - master + - internal_cppsound pull_request: branches: - master From e1c79a9d4bcd70cc7a46f5bb4dcae3f243c4e4fe Mon Sep 17 00:00:00 2001 From: gogins Date: Tue, 21 Nov 2023 12:32:08 -0500 Subject: [PATCH 3/5] Build Soundfile.cpp? (#13). --- CsoundAC/CMakeLists.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/CsoundAC/CMakeLists.txt b/CsoundAC/CMakeLists.txt index 1541244ae1..093d503ded 100644 --- a/CsoundAC/CMakeLists.txt +++ b/CsoundAC/CMakeLists.txt @@ -51,7 +51,6 @@ if(BUILD_CSOUND_AC) ScoreNode.cpp Sequence.cpp Shell.cpp - Soundfile.cpp StrangeAttractor.cpp System.cpp Voicelead.cpp @@ -66,9 +65,14 @@ if(BUILD_CSOUND_AC) ../dependencies/portsmf/mfmidi.cpp ../dependencies/portsmf/strparse.cpp trace.cpp) -if(OPENCV_FOUND) - list(APPEND libcsoundac_SRCS "ImageToScore.cpp") -endif() + if(APPLE) + else() + target_include_directories(libCsoundAC SYSTEM PRIVATE ${LIBSNDFILE_INCLUDE_DIR}) + list(APPEND libcsoundac_SRCS "Soundfile.cpp") + endif() + if(OPENCV_FOUND) + list(APPEND libcsoundac_SRCS "ImageToScore.cpp") + endif() message(STATUS "libcsoundac_SRCS: " ${libcsoundac_SRCS}) if (MSVC) @@ -77,10 +81,6 @@ endif() add_library(libCsoundAC SHARED ${libcsoundac_SRCS}) endif() - if(APPLE) - target_include_directories(libCsoundAC SYSTEM PRIVATE ${LIBSNDFILE_INCLUDE_DIR}) - endif() - target_include_directories(libCsoundAC SYSTEM PRIVATE ${Python3_INCLUDE_DIRS}) target_include_directories(libCsoundAC SYSTEM PRIVATE ${CSOUND_INCLUDE_DIRS}) target_include_directories(libCsoundAC PRIVATE ${EIGEN3_INCLUDE_DIRS}) From b180d9aa58bd095fc883b380d317ffa1465514f2 Mon Sep 17 00:00:00 2001 From: gogins Date: Tue, 21 Nov 2023 12:58:24 -0500 Subject: [PATCH 4/5] Removed unneeded files (#13). --- CsoundAC/CMakeLists.txt | 5 - CsoundAC/Silence.hpp | 1 - CsoundAC/cs_glue.cpp | 1345 ------------------------------------- CsoundAC/cs_glue.hpp | 707 ------------------- CsoundAC/pyMsgCb.cpp | 66 -- CsoundAC/pyMsgCb_stub.cpp | 10 - 6 files changed, 2134 deletions(-) delete mode 100644 CsoundAC/cs_glue.cpp delete mode 100644 CsoundAC/cs_glue.hpp delete mode 100644 CsoundAC/pyMsgCb.cpp delete mode 100644 CsoundAC/pyMsgCb_stub.cpp diff --git a/CsoundAC/CMakeLists.txt b/CsoundAC/CMakeLists.txt index 093d503ded..61d29e02df 100644 --- a/CsoundAC/CMakeLists.txt +++ b/CsoundAC/CMakeLists.txt @@ -65,11 +65,6 @@ if(BUILD_CSOUND_AC) ../dependencies/portsmf/mfmidi.cpp ../dependencies/portsmf/strparse.cpp trace.cpp) - if(APPLE) - else() - target_include_directories(libCsoundAC SYSTEM PRIVATE ${LIBSNDFILE_INCLUDE_DIR}) - list(APPEND libcsoundac_SRCS "Soundfile.cpp") - endif() if(OPENCV_FOUND) list(APPEND libcsoundac_SRCS "ImageToScore.cpp") endif() diff --git a/CsoundAC/Silence.hpp b/CsoundAC/Silence.hpp index 6578594208..c6a7663a9e 100644 --- a/CsoundAC/Silence.hpp +++ b/CsoundAC/Silence.hpp @@ -97,7 +97,6 @@ #include "StrangeAttractor.hpp" #include "Lindenmayer.hpp" #include "MCRM.hpp" -#include "Soundfile.hpp" #include "Voicelead.hpp" #include "VoiceleadingNode.hpp" #include "ChordLindenmayer.hpp" diff --git a/CsoundAC/cs_glue.cpp b/CsoundAC/cs_glue.cpp deleted file mode 100644 index 5c9aa3291b..0000000000 --- a/CsoundAC/cs_glue.cpp +++ /dev/null @@ -1,1345 +0,0 @@ -/* - cs_glue.cpp: - - Copyright (C) 2005, 2006 Istvan Varga - - This file is part of Csound. - - The Csound Library is free software; you can redistribute it - and/or modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - Csound is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with Csound; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - -#include "csound.h" -//#include "cs_glue.h" -#include "csound.hpp" -#include "csdl.h" -#include "cs_glue.hpp" - -extern "C" { - - -// ---------------------------------------------------------------------------- - -/** - * CsoundOpcodeList(CSOUND *) - * CsoundOpcodeList(Csound *) - * - * Creates an alphabetically sorted opcode list for a Csound instance. - * Should be called after csoundCompile() or Csound::Compile(). - */ - -/** - * Returns the number of opcodes, or -1 if there is no list. - */ - -int CsoundOpcodeList::Count() -{ - return cnt; -} - -/** - * Returns the name of the opcode at index 'ndx' (counting from zero), - * or NULL if the index is out of range. - */ - -const char * CsoundOpcodeList::Name(int ndx) -{ - if (lst && (unsigned int) ndx < (unsigned int) cnt) - return lst[ndx].opname; - return (char*) 0; -} - -/** - * Returns the output types of the opcode at index 'ndx' (counting from - * zero), or NULL if the index is out of range. - */ - -const char * CsoundOpcodeList::OutTypes(int ndx) -{ - if (lst && (unsigned int) ndx < (unsigned int) cnt) - return lst[ndx].outypes; - return (char*) 0; -} - -/** - * Returns the input types of the opcode at index 'ndx' (counting from - * zero), or NULL if the index is out of range. - */ - -const char * CsoundOpcodeList::InTypes(int ndx) -{ - if (lst && (unsigned int) ndx < (unsigned int) cnt) - return lst[ndx].intypes; - return (char*) 0; -} - -/** - * Releases the memory used by the opcode list. Should be called - * before the Csound instance is destroyed or reset. - */ - -void CsoundOpcodeList::Clear() -{ - // FIXME: this depends on csoundDisposeOpcodeList() ignoring the - // instance pointer - if (lst) - csoundDisposeOpcodeList((CSOUND*) 0, lst); - lst = (opcodeListEntry*) 0; - cnt = -1; -} - -CsoundOpcodeList::CsoundOpcodeList(CSOUND *csound) -{ - lst = (opcodeListEntry*) 0; - cnt = csoundNewOpcodeList(csound, &lst); - if (cnt < 0 || !lst) { - lst = (opcodeListEntry*) 0; - cnt = -1; - } -} - -CsoundOpcodeList::CsoundOpcodeList(Csound *csound) -{ - lst = (opcodeListEntry*) 0; - cnt = csound->NewOpcodeList(lst); - if (cnt < 0 || !lst) { - lst = (opcodeListEntry*) 0; - cnt = -1; - } -} - -CsoundOpcodeList::~CsoundOpcodeList() -{ - this->Clear(); -} - -// ---------------------------------------------------------------------------- - -/** - * CsoundChannelList(CSOUND *) - * CsoundChannelList(Csound *) - * - * Creates an alphabetically sorted list of named channels of a Csound - * instance. Should be called after csoundCompile() or Csound::Compile(). - */ - -void CsoundChannelList::ResetVariables() -{ - lst = (controlChannelInfo_t*) 0; - cnt = -1; - csound = (CSOUND*) 0; -} - -int CsoundChannelList::GetChannelMetaData(int ndx, - controlChannelHints_t *hints) -{ - const char *name; - if (!lst || (unsigned int) ndx >= (unsigned int) cnt) - return -1; - name = lst[ndx].name; - int ret = csoundGetControlChannelHints(csound, name, hints); - return ret; -} - -/** - * Returns the number of channels (-1 if there is no list). - */ - -int CsoundChannelList::Count() -{ - return cnt; -} - -/** - * Returns the name of the channel at index 'ndx' (counting from zero), - * or NULL if the index is out of range. - */ - -const char * CsoundChannelList::Name(int ndx) -{ - if (lst && (unsigned int) ndx < (unsigned int) cnt) - return lst[ndx].name; - return (char*) 0; -} - -/** - * Returns the type of the channel at index 'ndx' (counting from zero), - * or -1 if the index is out of range. - */ - -int CsoundChannelList::Type(int ndx) -{ - if (lst && (unsigned int) ndx < (unsigned int) cnt) - return lst[ndx].type; - return -1; -} - -/** - * Returns 1 if the channel at index 'ndx' (counting from zero) exists - * and is a control channel, and 0 otherwise. - */ - -int CsoundChannelList::IsControlChannel(int ndx) -{ - if (lst && (unsigned int) ndx < (unsigned int) cnt) - return ((lst[ndx].type & CSOUND_CHANNEL_TYPE_MASK) - == CSOUND_CONTROL_CHANNEL ? 1 : 0); - return 0; -} - -/** - * Returns 1 if the channel at index 'ndx' (counting from zero) exists - * and is an audio channel, and 0 otherwise. - */ - -int CsoundChannelList::IsAudioChannel(int ndx) -{ - if (lst && (unsigned int) ndx < (unsigned int) cnt) - return ((lst[ndx].type & CSOUND_CHANNEL_TYPE_MASK) - == CSOUND_AUDIO_CHANNEL ? 1 : 0); - return 0; -} - -/** - * Returns 1 if the channel at index 'ndx' (counting from zero) exists - * and is a string channel, and 0 otherwise. - */ - -int CsoundChannelList::IsStringChannel(int ndx) -{ - if (lst && (unsigned int) ndx < (unsigned int) cnt) - return ((lst[ndx].type & CSOUND_CHANNEL_TYPE_MASK) - == CSOUND_STRING_CHANNEL ? 1 : 0); - return 0; -} - -/** - * Returns 1 if the channel at index 'ndx' (counting from zero) exists - * and the input bit is set, and 0 otherwise. - */ - -int CsoundChannelList::IsInputChannel(int ndx) -{ - if (lst && (unsigned int) ndx < (unsigned int) cnt) - return ((lst[ndx].type & CSOUND_INPUT_CHANNEL) ? 1 : 0); - return 0; -} - -/** - * Returns 1 if the channel at index 'ndx' (counting from zero) exists - * and the output bit is set, and 0 otherwise. - */ - -int CsoundChannelList::IsOutputChannel(int ndx) -{ - if (lst && (unsigned int) ndx < (unsigned int) cnt) - return ((lst[ndx].type & CSOUND_OUTPUT_CHANNEL) ? 1 : 0); - return 0; -} - -/** - * Returns the sub-type (0: normal, 1: integer, 2: linear, 3: exponential) - * of the control channel at index 'ndx' (counting from zero), or -1 if - * the channel does not exist or is not a control channel. - */ - -int CsoundChannelList::SubType(int ndx) -{ - int tmp; - controlChannelHints_t hints; - tmp = this->GetChannelMetaData(ndx, &hints); - if (tmp >= 0) { - tmp = hints.behav; - } - return tmp; -} - -/** - * Returns the default value set for the control channel at index 'ndx' - * (counting from zero), or 0.0 if the channel does not exist, is not a - * control channel, or has no default value. - */ - -double CsoundChannelList::DefaultValue(int ndx) -{ - controlChannelHints_t hints; - if (this->GetChannelMetaData(ndx, &hints) > 0) - return hints.dflt; - return 0.0; -} - -/** - * Returns the minimum value set for the control channel at index 'ndx' - * (counting from zero), or 0.0 if the channel does not exist, is not a - * control channel, or has no minimum value. - */ - -double CsoundChannelList::MinValue(int ndx) -{ - controlChannelHints_t hints; - if (this->GetChannelMetaData(ndx, &hints) > 0) - return hints.min; - return 0.0; -} - -/** - * Returns the maximum value set for the control channel at index 'ndx' - * (counting from zero), or 0.0 if the channel does not exist, is not a - * control channel, or has no maximum value. - */ - -double CsoundChannelList::MaxValue(int ndx) -{ - controlChannelHints_t hints; - if (this->GetChannelMetaData(ndx, &hints) > 0) - return hints.max; - return 0.0; -} - -/** - * Releases the memory used by the channel list. Should be called - * before the Csound instance is destroyed or reset. - */ - -void CsoundChannelList::Clear() -{ - // FIXME: this depends on csoundDeleteChannelList() ignoring the - // instance pointer - if (lst) - csoundDeleteChannelList((CSOUND*) 0, lst); - this->ResetVariables(); -} - -CsoundChannelList::CsoundChannelList(CSOUND *csound) -{ - lst = (controlChannelInfo_t*) 0; - cnt = csoundListChannels(csound, &lst); - this->csound = csound; - if (cnt < 0 || !lst) - this->ResetVariables(); -} - -CsoundChannelList::CsoundChannelList(Csound *csound) -{ - lst = (controlChannelInfo_t*) 0; - cnt = csound->ListChannels(lst); - this->csound = csound->GetCsound(); - if (cnt < 0 || !lst) - this->ResetVariables(); -} - -CsoundChannelList::~CsoundChannelList() -{ - this->Clear(); -} - -// ---------------------------------------------------------------------------- - -/** - * CsoundUtilityList(CSOUND *) - * CsoundUtilityList(Csound *) - * - * Creates an alphabetically sorted list of utilities registered - * for a Csound instance. Should be called after csoundPreCompile() - * or Csound::PreCompile(). - */ - -/** - * Returns the number of utilities, or -1 if there is no list. - */ - -int CsoundUtilityList::Count() -{ - return cnt; -} - -/** - * Returns the name of the utility at index 'ndx' (counting from zero), - * or NULL if the index is out of range. - */ - -const char * CsoundUtilityList::Name(int ndx) -{ - if (lst && (unsigned int) ndx < (unsigned int) cnt) - return lst[ndx]; - return (char*) 0; -} - -/** - * Releases the memory used by the utility list. Should be called - * before the Csound instance is destroyed or reset. - */ - -void CsoundUtilityList::Clear() -{ - // FIXME: this depends on csoundDeleteUtilityList() ignoring the - // instance pointer - if (lst) - csoundDeleteUtilityList((CSOUND*) 0, lst); - lst = (char**) 0; - cnt = -1; -} - -CsoundUtilityList::CsoundUtilityList(CSOUND *csound) -{ - int n = -1; - lst = csoundListUtilities(csound); - if (lst) { - while (lst[++n]) - ; - } - cnt = n; -} - -CsoundUtilityList::CsoundUtilityList(Csound *csound) -{ - int n = -1; - lst = csound->ListUtilities(); - if (lst) { - while (lst[++n]) - ; - } - cnt = n; -} - -CsoundUtilityList::~CsoundUtilityList() -{ - this->Clear(); -} - -// ---------------------------------------------------------------------------- - -/** - * CsoundMYFLTArray() - * - * Creates a pointer for use with csoundGetChannelPtr(), - * csoundGetOutputBuffer(), or other functions that return a - * pointer to an array of floating point values. - * - * CsoundMYFLTArray(int cnt) - * - * Allocates an array of 'cnt' floating point values, for use - * with Csound API functions that take a MYFLT* pointer. - */ - -/** - * Stores a string in the array (note: only do this with a pointer - * returned by csoundGetChannelPtr()), optionally limiting the length to - * maxLen - 1 characters. - */ -// FIXME - this is broken and does not work with STRINGDAT -void CsoundMYFLTArray::SetStringValue(const char *s, int maxLen) -{ - if (p) { - int i = 0; - if (s && --maxLen > 0) { - while (s[i]) { - ((char*) p)[i] = s[i]; - if (++i >= maxLen) - break; - } - } - ((char*) p)[i] = (char) '\0'; - } -} - -/** - * Returns a string from the array (note: only do this with a pointer - * returned by csoundGetChannelPtr()), or NULL if there is no array. - */ - -const char * CsoundMYFLTArray::GetStringValue() -{ - return ((STRINGDAT*) p)->data; -} - -/** - * Clears the array pointer, and releases any memory that was allocated - * by calling the constructor with a positive number of elements. - */ - -void CsoundMYFLTArray::Clear() -{ - if (pp) - free(pp); - p = (MYFLT*) 0; - pp = (void*) 0; -} - -CsoundMYFLTArray::CsoundMYFLTArray() -{ - p = (MYFLT*) 0; - pp = (void*) 0; -} - -CsoundMYFLTArray::CsoundMYFLTArray(int n) -{ - p = (MYFLT*) 0; - pp = (void*) 0; - if (n > 0) - pp = (void*) malloc((size_t) n * sizeof(MYFLT)); - if (pp) { - p = (MYFLT*) pp; - for (int i = 0; i < n; i++) - p[i] = (MYFLT) 0; - } -} - -CsoundMYFLTArray::~CsoundMYFLTArray() -{ - this->Clear(); -} - -// ---------------------------------------------------------------------------- - -/** - * A simple class for creating argv[] lists for use with - * functions like csoundCompile(). - */ - -void CsoundArgVList::destroy_argv() -{ - for (int i = 0; i < cnt; i++) - free((void*) ArgV_[i]); - if (ArgV_) - free((void*) ArgV_); - ArgV_ = (char**) 0; - cnt = -1; -} - -/** - * Returns the count of arguments in the list, zero if there are - * none, and -1 if the list could not be allocated. - */ - -int CsoundArgVList::argc() -{ - return cnt; -} - -/** - * Returns a char** pointer for use with csoundCompile() etc. - */ - -char ** CsoundArgVList::argv() -{ - return ArgV_; -} - -/** - * Returns the argument at the specified index (counting from zero), - * or NULL if the index is out of range. - */ - -const char * CsoundArgVList::argv(int ndx) -{ - if (ArgV_ && (unsigned int) ndx < (unsigned int) cnt) - return ArgV_[ndx]; - return (char*) 0; -} - -/** - * Inserts a new value to the argument list at the specified index - * (counting from zero). If there is not enough memory, the list is - * not changed. - */ - -void CsoundArgVList::Insert(int ndx, const char *s) -{ - char **new_argv; - int new_cnt, i; - - if (!s) - return; - if (ndx > cnt) - ndx = cnt; - if (ndx < 0) - ndx = 0; - new_cnt = (cnt >= 0 ? cnt + 1 : 1); - new_argv = (char**) malloc((size_t) (new_cnt + 1) * sizeof(char*)); - if (!new_argv) - return; - for (i = 0; i < ndx; i++) - new_argv[i] = ArgV_[i]; - new_argv[i] = (char*) malloc(strlen(s) + (size_t) 1); - if (!new_argv[i]) { - free((void*) new_argv); - return; - } - strcpy(new_argv[i], s); - while (++i < new_cnt) - new_argv[i] = ArgV_[i - 1]; - new_argv[i] = (char*) 0; - if (ArgV_) - free((void*) ArgV_); - ArgV_ = new_argv; - cnt = new_cnt; -} - -/** - * Appends a new value at the end of the argument list. - * If there is not enough memory, the list is not changed. - */ - -void CsoundArgVList::Append(const char *s) -{ - this->Insert(0x7FFFFFFF, s); -} - -/** - * Removes all elements of the list. - */ - -void CsoundArgVList::Clear() -{ - this->destroy_argv(); - ArgV_ = (char**) malloc(sizeof(char*)); - if (ArgV_) { - ArgV_[0] = (char*) 0; - cnt = 0; - } - else - cnt = -1; -} - -CsoundArgVList::CsoundArgVList() -{ - cnt = -1; - ArgV_ = (char**) malloc(sizeof(char*)); - if (ArgV_) { - ArgV_[0] = (char*) 0; - cnt = 0; - } -} - -CsoundArgVList::~CsoundArgVList() -{ - this->destroy_argv(); -} - -// ---------------------------------------------------------------------------- - -/** - * Experimental class for wrapping callbacks using SWIG directors. - */ - -extern "C" { - - static CS_NOINLINE void MessageCallback_wrapper(CSOUND *csound, - int attr, const char *fmt, va_list args) - { - CsoundCallbackWrapper *p; - p = (CsoundCallbackWrapper*) csoundGetHostData(csound); -#if defined(HAVE_C99) && !defined(WIN32) - { - char buf[2048]; - int n; - n = vsnprintf(&(buf[0]), (size_t) 2048, fmt, args); - if (n < 0) { // for compatibility only - fprintf(stderr, " *** buffer overflow in message callback\n"); - exit(-1); - } - else if (n >= 2048) { - char *bufp = (char*) malloc((size_t) n + (size_t) 1); - if (bufp) { - vsprintf(bufp, fmt, args); - p->MessageCallback(attr, bufp); - free((void*) bufp); - } - } - else - p->MessageCallback(attr, &(buf[0])); - } -#else - { - char buf[16384]; - if (vsprintf(&(buf[0]), fmt, args) >= 16384) { - fprintf(stderr, " *** buffer overflow in message callback\n"); - exit(-1); - } - p->MessageCallback(attr, &(buf[0])); - } -#endif - } - - /** - static CS_NOINLINE void InputValueCallback_wrapper(CSOUND *csound, - const char *chnName, MYFLT *value) - { - CsoundCallbackWrapper *p; - p = (CsoundCallbackWrapper*) csoundGetHostData(csound); - *value = (MYFLT) p->InputValueCallback(chnName); - } - */ - /** - static CS_NOINLINE void OutputValueCallback_wrapper(CSOUND *csound, - const char *chnName, MYFLT value) - { - CsoundCallbackWrapper *p; - p = (CsoundCallbackWrapper*) csoundGetHostData(csound); - p->OutputValueCallback(chnName, (double) value); - } - */ - static CS_NOINLINE int YieldCallback_wrapper(CSOUND *csound) - { - CsoundCallbackWrapper *p; - p = (CsoundCallbackWrapper*) csoundGetHostData(csound); - return p->YieldCallback(); - } - -} // extern "C" - -void CsoundCallbackWrapper::SetMessageCallback() -{ - csoundSetMessageCallback(csound_, MessageCallback_wrapper); -} - - /*void CsoundCallbackWrapper::SetInputValueCallback() -{ - csoundSetInputValueCallback(csound_, InputValueCallback_wrapper); -} - -void CsoundCallbackWrapper::SetOutputValueCallback() -{ - csoundSetOutputValueCallback(csound_, OutputValueCallback_wrapper); -} - */ -void CsoundCallbackWrapper::SetYieldCallback() -{ - csoundSetYieldCallback(csound_, YieldCallback_wrapper); -} - -void CsoundCallbackWrapper::SetMidiInputCallback(CsoundArgVList *argv) -{ - csoundSetExternalMidiInOpenCallback(csound_, midiInOpenCallback); - csoundSetExternalMidiReadCallback(csound_, midiInReadCallback); - csoundSetExternalMidiInCloseCallback(csound_, midiInCloseCallback); - if (argv != (CsoundArgVList*) 0) { - argv->Append("-+rtmidi=null"); - argv->Append("-M0"); - } - csoundMessage(csound_, - "rtmidi: CsoundCallbackWrapper::MidiInputCallback() " - "enabled\n"); -} - -void CsoundCallbackWrapper::SetMidiOutputCallback(CsoundArgVList *argv) -{ - csoundSetExternalMidiOutOpenCallback(csound_, midiOutOpenCallback); - csoundSetExternalMidiWriteCallback(csound_, midiOutWriteCallback); - csoundSetExternalMidiOutCloseCallback(csound_, midiOutCloseCallback); - if (argv != (CsoundArgVList*) 0) { - argv->Append("-+rtmidi=null"); - argv->Append("-Q0"); - } - csoundMessage(csound_, - "rtmidi: CsoundCallbackWrapper::MidiOutputCallback() " - "enabled\n"); -} - -CsoundCallbackWrapper::CsoundCallbackWrapper(Csound *cs) -{ - csound_ = cs->GetCsound(); - cs->SetHostData((void*) this); -} - -CsoundCallbackWrapper::CsoundCallbackWrapper(CSOUND *cs) -{ - csound_ = cs; - csoundSetHostData(cs, (void*) this); -} - -int CsoundCallbackWrapper::midiInOpenCallback(CSOUND *csound, void **userData, - const char *devName) -{ - (void) devName; - (*userData) = csoundGetHostData(csound); - return 0; -} - -int CsoundCallbackWrapper::midiInReadCallback(CSOUND *csound, void *userData, - unsigned char *buf, int nBytes) -{ - CsoundMidiInputBuffer buf_(buf, nBytes); - int bytesRead; - - (void) csound; - ((CsoundCallbackWrapper*) userData)->MidiInputCallback(&buf_); - bytesRead = buf_.bufBytes; - return bytesRead; -} - -int CsoundCallbackWrapper::midiInCloseCallback(CSOUND *csound, void *userData) -{ - (void) csound; - (void) userData; - return 0; -} - -int CsoundCallbackWrapper::midiOutOpenCallback(CSOUND *csound, void **userData, - const char *devName) -{ - (void) devName; - (*userData) = csoundGetHostData(csound); - return 0; -} - -int CsoundCallbackWrapper::midiOutWriteCallback(CSOUND *csound, void *userData, - const unsigned char *buf, - int nBytes) -{ - CsoundMidiOutputBuffer buf_((unsigned char*) buf, nBytes); - int bytesWritten; - - (void) csound; - buf_.bufBytes = nBytes; - ((CsoundCallbackWrapper*) userData)->MidiOutputCallback(&buf_); - bytesWritten = nBytes - buf_.bufBytes; - return bytesWritten; -} - -int CsoundCallbackWrapper::midiOutCloseCallback(CSOUND *csound, void *userData) -{ - (void) csound; - (void) userData; - return 0; -} - /* -void CsoundCallbackWrapper::SetChannelIOCallbacks() -{ - csoundSetChannelIOCallback(csound_, - (CsoundChannelIOCallback_t) - ChannelIOCallback_wrapper); -} - */ -// ---------------------------------------------------------------------------- - -static const unsigned char midiMessageByteCnt[32] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 0, 1 -}; - -CsoundMidiInputBuffer::CsoundMidiInputBuffer(unsigned char *buf, int bufSize) -{ - this->buf = buf; - mutex_ = csoundCreateMutex(0); - bufReadPos = 0; - bufWritePos = 0; - bufBytes = 0; - this->bufSize = bufSize; -} - -CsoundMidiInputBuffer::~CsoundMidiInputBuffer() -{ - buf = (unsigned char*) 0; - csoundDestroyMutex(mutex_); - mutex_ = (void*) 0; -} - -/** - * Sends a MIDI message, 'msg' is calculated as follows: - * STATUS + DATA1 * 256 + DATA2 * 65536 - */ - -void CsoundMidiInputBuffer::SendMidiMessage(int msg) -{ - int nBytes = (int) midiMessageByteCnt[(msg & (int) 0xF8) >> 3]; - - if (!nBytes) - return; - csoundLockMutex(mutex_); - if ((bufBytes + nBytes) <= bufSize) { - buf[bufWritePos] = (unsigned char) msg & (unsigned char) 0xFF; - bufWritePos = (bufWritePos < (bufSize - 1) ? bufWritePos + 1 : 0); - bufBytes++; - if (nBytes > 1) { - buf[bufWritePos] = (unsigned char) (msg >> 8) & (unsigned char) 0x7F; - bufWritePos = (bufWritePos < (bufSize - 1) ? bufWritePos + 1 : 0); - bufBytes++; - if (nBytes > 2) { - buf[bufWritePos] = (unsigned char) (msg >> 16) - & (unsigned char) 0x7F; - bufWritePos = (bufWritePos < (bufSize - 1) ? bufWritePos + 1 : 0); - bufBytes++; - } - } - } - csoundUnlockMutex(mutex_); -} - -/** - * Sends a MIDI message; 'channel' should be in the range 1 to 16, - * and data1 and data2 should be in the range 0 to 127. - */ - -void CsoundMidiInputBuffer::SendMidiMessage(int status, int channel, - int data1, int data2) -{ - int nBytes = (int) midiMessageByteCnt[(status & (int) 0xF8) >> 3]; - - if (!nBytes) - return; - csoundLockMutex(mutex_); - if ((bufBytes + nBytes) <= bufSize) { - unsigned char st = (unsigned char) status & (unsigned char) 0xFF; - if (nBytes > 1) { - st = (st & (unsigned char) 0xF0) - + ((unsigned char) (status + channel - 1) & (unsigned char) 0x0F); - } - buf[bufWritePos] = st; - bufWritePos = (bufWritePos < (bufSize - 1) ? bufWritePos + 1 : 0); - bufBytes++; - if (nBytes > 1) { - buf[bufWritePos] = (unsigned char) data1 & (unsigned char) 0x7F; - bufWritePos = (bufWritePos < (bufSize - 1) ? bufWritePos + 1 : 0); - bufBytes++; - if (nBytes > 2) { - buf[bufWritePos] = (unsigned char) data2 & (unsigned char) 0x7F; - bufWritePos = (bufWritePos < (bufSize - 1) ? bufWritePos + 1 : 0); - bufBytes++; - } - } - } - csoundUnlockMutex(mutex_); -} - -/** - * Sends a note-on message on 'channel' (1 to 16) for 'key' (0 to 127) - * with 'velocity' (0 to 127). - */ - -void CsoundMidiInputBuffer::SendNoteOn(int channel, int key, int velocity) -{ - SendMidiMessage((int) 0x90, channel, key, velocity); -} - -/** - * Sends a note-off message on 'channel' (1 to 16) for 'key' (0 to 127) - * with 'velocity' (0 to 127). - */ - -void CsoundMidiInputBuffer::SendNoteOff(int channel, int key, int velocity) -{ - SendMidiMessage((int) 0x80, channel, key, velocity); -} - -/** - * Sends a note-off message on 'channel' (1 to 16) for 'key', - * using a 0x90 status with zero velocity. - */ - -void CsoundMidiInputBuffer::SendNoteOff(int channel, int key) -{ - SendMidiMessage((int) 0x90, channel, key, 0); -} - -/** - * Sets polyphonic pressure on 'channel' (1 to 16) to 'value' (0 to 127) - * for 'key' (0 to 127). - */ - -void CsoundMidiInputBuffer::SendPolyphonicPressure(int channel, int key, - int value) -{ - SendMidiMessage((int) 0xA0, channel, key, value); -} - -/** - * Sets controller 'ctl' (0 to 127) to 'value' (0 to 127) - * on 'channel' (1 to 16). - */ - -void CsoundMidiInputBuffer::SendControlChange(int channel, int ctl, int value) -{ - SendMidiMessage((int) 0xB0, channel, ctl, value); -} - -/** - * Sends program change to 'pgm' (1 to 128) on 'channel' (1 to 16). - */ - -void CsoundMidiInputBuffer::SendProgramChange(int channel, int pgm) -{ - SendMidiMessage((int) 0xC0, channel, pgm - 1, 0); -} - -/** - * Sets channel pressure to 'value' (0 to 127) on 'channel' (1 to 16). - */ - -void CsoundMidiInputBuffer::SendChannelPressure(int channel, int value) -{ - SendMidiMessage((int) 0xD0, channel, value, 0); -} - -/** - * Sets pitch bend to 'value' (-8192 to 8191) on 'channel' (1 to 16). - */ - -void CsoundMidiInputBuffer::SendPitchBend(int channel, int value) -{ - SendMidiMessage((int) 0xE0, channel, - (value + 8192) & (int) 0x7F, - ((value + 8192) >> 7) & (int) 0x7F); -} - -/** - * Copies at most 'nBytes' bytes of MIDI data from the buffer to 'buf'. - * Returns the number of bytes copied. - */ - -int CsoundMidiInputBuffer::GetMidiData(unsigned char *buf, int nBytes) -{ - int i; - - if (!bufBytes) - return 0; - csoundLockMutex(mutex_); - for (i = 0; i < nBytes && bufBytes > 0; i++) { - buf[i] = this->buf[bufReadPos]; - bufReadPos = (bufReadPos < (bufSize - 1) ? bufReadPos + 1 : 0); - bufBytes--; - } - csoundUnlockMutex(mutex_); - return i; -} - -// ---------------------------------------------------------------------------- - -/** - * The following class allows sending MIDI input messages to a Csound - * instance. - */ - -CsoundMidiInputStream::CsoundMidiInputStream(CSOUND *csound) - : CsoundMidiInputBuffer(&(buf_[0]), 4096) -{ - this->csound = csound; -} - -CsoundMidiInputStream::CsoundMidiInputStream(Csound *csound) - : CsoundMidiInputBuffer(&(buf_[0]), 4096) -{ - this->csound = csound->GetCsound(); -} - -int CsoundMidiInputStream::midiInOpenCallback(CSOUND *csound, void **userData, - const char *devName) -{ - (void) devName; - (*userData) = *((void**) csoundQueryGlobalVariable(csound, - "__csnd_MidiInObject")); - return 0; -} - -int CsoundMidiInputStream::midiInReadCallback(CSOUND *csound, void *userData, - unsigned char *buf, int nBytes) -{ - (void) csound; - return ((CsoundMidiInputStream*) userData)->GetMidiData(buf, nBytes); -} - -int CsoundMidiInputStream::midiInCloseCallback(CSOUND *csound, void *userData) -{ - (void) csound; - (void) userData; - return 0; -} - -/** - * Enables MIDI input for the associated Csound instance. - * Should be called between csoundPreCompile() and csoundCompile(). - * If 'argv' is not NULL, the command line arguments required for - * MIDI input are appended. - */ - -void CsoundMidiInputStream::EnableMidiInput(CsoundArgVList *argv) -{ - csoundCreateGlobalVariable(csound, "__csnd_MidiInObject", - sizeof(void*)); - *((void**) csoundQueryGlobalVariable(csound, "__csnd_MidiInObject")) = - (void*) this; - csoundSetExternalMidiInOpenCallback(csound, midiInOpenCallback); - csoundSetExternalMidiReadCallback(csound, midiInReadCallback); - csoundSetExternalMidiInCloseCallback(csound, midiInCloseCallback); - if (argv != (CsoundArgVList*) 0) { - argv->Append("-+rtmidi=null"); - argv->Append("-M0"); - } - csoundMessage(csound, "rtmidi: CsoundMidiInputStream enabled\n"); -} - -// ---------------------------------------------------------------------------- - -CsoundMidiOutputBuffer::CsoundMidiOutputBuffer(unsigned char *buf, int bufSize) -{ - this->buf = buf; - mutex_ = csoundCreateMutex(0); - bufReadPos = 0; - bufWritePos = 0; - bufBytes = 0; - this->bufSize = bufSize; -} - -CsoundMidiOutputBuffer::~CsoundMidiOutputBuffer() -{ - buf = (unsigned char*) 0; - csoundDestroyMutex(mutex_); - mutex_ = (void*) 0; -} - -/** - * Pops and returns the first message from the buffer, in the following - * format: - * STATUS + DATA1 * 256 + DATA2 * 65536 - * where STATUS also includes the channel number (0 to 15), if any. - * The return value is zero if there are no messages. - */ - -int CsoundMidiOutputBuffer::PopMessage() -{ - int msg = 0; - - if (bufBytes) { - csoundLockMutex(mutex_); - if (bufBytes > 0) { - int nBytes; - unsigned char st; - - st = buf[bufReadPos] & (unsigned char) 0xFF; - nBytes = (int) midiMessageByteCnt[(st & (unsigned char) 0xF8) >> 3]; - if (nBytes > 0 && bufBytes >= nBytes) { - bufReadPos = (bufReadPos < (bufSize - 1) ? bufReadPos + 1 : 0); - bufBytes--; - msg = (int) st; - if (nBytes > 1) { - msg += ((int) (buf[bufReadPos] & (unsigned char) 0x7F) << 8); - bufReadPos = (bufReadPos < (bufSize - 1) ? bufReadPos + 1 : 0); - bufBytes--; - if (nBytes > 2) { - msg += ((int) (buf[bufReadPos] & (unsigned char) 0x7F) << 16); - bufReadPos = (bufReadPos < (bufSize - 1) ? bufReadPos + 1 : 0); - bufBytes--; - } - } - } - else { - // invalid MIDI data, discard the rest of the buffer - bufReadPos = bufWritePos; - bufBytes = 0; - } - } - csoundUnlockMutex(mutex_); - } - return msg; -} - -/** - * Returns the status byte for the first message in the buffer, not - * including the channel number in the case of channel messages. - * The return value is zero if there are no messages. - */ - -int CsoundMidiOutputBuffer::GetStatus() -{ - unsigned char st = (unsigned char) 0; - - if (bufBytes) { - csoundLockMutex(mutex_); - if (bufBytes > 0) { - int nBytes; - st = buf[bufReadPos] & (unsigned char) 0xFF; - nBytes = (int) midiMessageByteCnt[(st & (unsigned char) 0xF8) >> 3]; - if (nBytes <= 0 || bufBytes < nBytes) - st = (unsigned char) 0; // invalid MIDI data - if (nBytes > 1) - st &= (unsigned char) 0xF0; // channel msg: remove channel number - } - csoundUnlockMutex(mutex_); - } - return (int) st; -} - -/** - * Returns the channel number (1 to 16) for the first message in the - * buffer. The return value is zero if there are no messages, or the - * first message is not a channel message. - */ - -int CsoundMidiOutputBuffer::GetChannel() -{ - unsigned char st = (unsigned char) 0; - - if (bufBytes) { - csoundLockMutex(mutex_); - if (bufBytes > 0) { - int nBytes; - st = buf[bufReadPos] & (unsigned char) 0xFF; - nBytes = (int) midiMessageByteCnt[(st & (unsigned char) 0xF8) >> 3]; - if (nBytes < 2 || bufBytes < nBytes) - st = (unsigned char) 0; // invalid MIDI data, or system message - else - st = (st & (unsigned char) 0x0F) + (unsigned char) 1; - } - csoundUnlockMutex(mutex_); - } - return (int) st; -} - -/** - * Returns the first data byte (0 to 127) for the first message in the - * buffer. The return value is zero if there are no messages, or the - * first message does not have any data bytes. - */ - -int CsoundMidiOutputBuffer::GetData1() -{ - unsigned char st, d1 = (unsigned char) 0; - - if (bufBytes) { - csoundLockMutex(mutex_); - if (bufBytes > 0) { - int nBytes; - st = buf[bufReadPos] & (unsigned char) 0xFF; - nBytes = (int) midiMessageByteCnt[(st & (unsigned char) 0xF8) >> 3]; - if (nBytes >= 2 && bufBytes >= nBytes) { - int pos = bufReadPos; - pos = (pos < (bufSize - 1) ? pos + 1 : 0); - d1 = buf[pos] & (unsigned char) 0x7F; - } - } - csoundUnlockMutex(mutex_); - } - return (int) d1; -} - -/** - * Returns the second data byte (0 to 127) for the first message in the - * buffer. The return value is zero if there are no messages, or the - * first message has less than two data bytes. - */ - -int CsoundMidiOutputBuffer::GetData2() -{ - unsigned char st, d2 = (unsigned char) 0; - - if (bufBytes) { - csoundLockMutex(mutex_); - if (bufBytes > 0) { - int nBytes; - st = buf[bufReadPos] & (unsigned char) 0xFF; - nBytes = (int) midiMessageByteCnt[(st & (unsigned char) 0xF8) >> 3]; - if (nBytes >= 3 && bufBytes >= nBytes) { - int pos = bufReadPos; - pos = (pos < (bufSize - 1) ? pos + 1 : 0); - pos = (pos < (bufSize - 1) ? pos + 1 : 0); - d2 = buf[pos] & (unsigned char) 0x7F; - } - } - csoundUnlockMutex(mutex_); - } - return (int) d2; -} - -/** - * Copies at most 'nBytes' bytes of MIDI data to the buffer from 'buf'. - * Returns the number of bytes copied. - */ - -int CsoundMidiOutputBuffer::SendMidiData(const unsigned char *buf, int nBytes) -{ - int i; - - csoundLockMutex(mutex_); - for (i = 0; i < nBytes && bufBytes < bufSize; i++) { - this->buf[bufWritePos] = buf[i]; - bufWritePos = (bufWritePos < (bufSize - 1) ? bufWritePos + 1 : 0); - bufBytes++; - } - csoundUnlockMutex(mutex_); - return i; -} - -// ---------------------------------------------------------------------------- - -/** - * The following class allows receiving MIDI output messages - * from a Csound instance. - */ - -CsoundMidiOutputStream::CsoundMidiOutputStream(CSOUND *csound) - : CsoundMidiOutputBuffer(&(buf_[0]), 4096) -{ - this->csound = csound; -} - -CsoundMidiOutputStream::CsoundMidiOutputStream(Csound *csound) - : CsoundMidiOutputBuffer(&(buf_[0]), 4096) -{ - this->csound = csound->GetCsound(); -} - -int CsoundMidiOutputStream::midiOutOpenCallback(CSOUND *csound, - void **userData, - const char *devName) -{ - (void) devName; - (*userData) = *((void**) csoundQueryGlobalVariable(csound, - "__csnd_MidiOutObject")); - return 0; -} - -int CsoundMidiOutputStream::midiOutWriteCallback(CSOUND *csound, - void *userData, - const unsigned char *buf, - int nBytes) -{ - (void) csound; - return ((CsoundMidiOutputStream*) userData)->SendMidiData(buf, nBytes); -} - -int CsoundMidiOutputStream::midiOutCloseCallback(CSOUND *csound, - void *userData) -{ - (void) csound; - (void) userData; - return 0; -} - -/** - * Enables MIDI output for the associated Csound instance. - * Should be called between csoundPreCompile() and csoundCompile(). - * If 'argv' is not NULL, the command line arguments required for - * MIDI output are appended. - */ - -void CsoundMidiOutputStream::EnableMidiOutput(CsoundArgVList *argv) -{ - csoundCreateGlobalVariable(csound, "__csnd_MidiOutObject", - sizeof(void*)); - *((void**) csoundQueryGlobalVariable(csound, "__csnd_MidiOutObject")) = - (void*) this; - csoundSetExternalMidiOutOpenCallback(csound, midiOutOpenCallback); - csoundSetExternalMidiWriteCallback(csound, midiOutWriteCallback); - csoundSetExternalMidiOutCloseCallback(csound, midiOutCloseCallback); - if (argv != (CsoundArgVList*) 0) { - argv->Append("-+rtmidi=null"); - argv->Append("-Q0"); - } - csoundMessage(csound, "rtmidi: CsoundMidiOutputStream enabled\n"); -} - -}; - diff --git a/CsoundAC/cs_glue.hpp b/CsoundAC/cs_glue.hpp deleted file mode 100644 index fd021e0c42..0000000000 --- a/CsoundAC/cs_glue.hpp +++ /dev/null @@ -1,707 +0,0 @@ -/* - cs_glue.hpp: - - Copyright (C) 2005, 2006 Istvan Varga - - This file is part of Csound. - - The Csound Library is free software; you can redistribute it - and/or modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - Csound is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with Csound; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - -#ifndef CSOUND_CS_GLUE_HPP -#define CSOUND_CS_GLUE_HPP - -/** - * CsoundOpcodeList(CSOUND *) - * CsoundOpcodeList(Csound *) - * - * Creates an alphabetically sorted opcode list for a Csound instance. - * Should be called after csoundCompile() or Csound::Compile(). - */ - -class PUBLIC CsoundOpcodeList { - private: - opcodeListEntry *lst; - int cnt; - public: - /** - * Returns the number of opcodes, or -1 if there is no list. - */ - int Count(); - /** - * Returns the name of the opcode at index 'ndx' (counting from zero), - * or NULL if the index is out of range. - */ - const char *Name(int ndx); - /** - * Returns the output types of the opcode at index 'ndx' (counting from - * zero), or NULL if the index is out of range. - */ - const char *OutTypes(int ndx); - /** - * Returns the input types of the opcode at index 'ndx' (counting from - * zero), or NULL if the index is out of range. - */ - const char *InTypes(int ndx); - /** - * Releases the memory used by the opcode list. Should be called - * before the Csound instance is destroyed or reset. - */ - void Clear(); - // -------- - CsoundOpcodeList(CSOUND *csound); - CsoundOpcodeList(Csound *csound); - ~CsoundOpcodeList(); -}; - -/** - * CsoundChannelList(CSOUND *) - * CsoundChannelList(Csound *) - * - * Creates an alphabetically sorted list of named channels of a Csound - * instance. Should be called after csoundCompile() or Csound::Compile(). - */ - -class PUBLIC CsoundChannelList { - private: - controlChannelInfo_t *lst; - int cnt; - CSOUND *csound; - void ResetVariables(); - int GetChannelMetaData(int ndx, controlChannelHints_t *hints); - public: - /** - * Returns the number of channels (-1 if there is no list). - */ - int Count(); - /** - * Returns the name of the channel at index 'ndx' (counting from zero), - * or NULL if the index is out of range. - */ - const char *Name(int ndx); - /** - * Returns the type of the channel at index 'ndx' (counting from zero), - * or -1 if the index is out of range. - */ - int Type(int ndx); - /** - * Returns 1 if the channel at index 'ndx' (counting from zero) exists - * and is a control channel, and 0 otherwise. - */ - int IsControlChannel(int ndx); - /** - * Returns 1 if the channel at index 'ndx' (counting from zero) exists - * and is an audio channel, and 0 otherwise. - */ - int IsAudioChannel(int ndx); - /** - * Returns 1 if the channel at index 'ndx' (counting from zero) exists - * and is a string channel, and 0 otherwise. - */ - int IsStringChannel(int ndx); - /** - * Returns 1 if the channel at index 'ndx' (counting from zero) exists - * and the input bit is set, and 0 otherwise. - */ - int IsInputChannel(int ndx); - /** - * Returns 1 if the channel at index 'ndx' (counting from zero) exists - * and the output bit is set, and 0 otherwise. - */ - int IsOutputChannel(int ndx); - /** - * Returns the sub-type (0: normal, 1: integer, 2: linear, 3: exponential) - * of the control channel at index 'ndx' (counting from zero), or -1 if - * the channel does not exist or is not a control channel. - */ - int SubType(int ndx); - /** - * Returns the default value set for the control channel at index 'ndx' - * (counting from zero), or 0.0 if the channel does not exist, is not a - * control channel, or has no default value. - */ - double DefaultValue(int ndx); - /** - * Returns the minimum value set for the control channel at index 'ndx' - * (counting from zero), or 0.0 if the channel does not exist, is not a - * control channel, or has no minimum value. - */ - double MinValue(int ndx); - /** - * Returns the maximum value set for the control channel at index 'ndx' - * (counting from zero), or 0.0 if the channel does not exist, is not a - * control channel, or has no maximum value. - */ - double MaxValue(int ndx); - /** - * Releases the memory used by the channel list. Should be called - * before the Csound instance is destroyed or reset. - */ - void Clear(); - // -------- - CsoundChannelList(CSOUND *csound); - CsoundChannelList(Csound *csound); - ~CsoundChannelList(); -}; - -/** - * CsoundUtilityList(CSOUND *) - * CsoundUtilityList(Csound *) - * - * Creates an alphabetically sorted list of utilities registered - * for a Csound instance. Should be called after csoundPreCompile() - * or Csound::PreCompile(). - */ - -class PUBLIC CsoundUtilityList { - private: - char **lst; - int cnt; - public: - /** - * Returns the number of utilities, or -1 if there is no list. - */ - int Count(); - /** - * Returns the name of the utility at index 'ndx' (counting from zero), - * or NULL if the index is out of range. - */ - const char *Name(int ndx); - /** - * Releases the memory used by the utility list. Should be called - * before the Csound instance is destroyed or reset. - */ - void Clear(); - // -------- - CsoundUtilityList(CSOUND *csound); - CsoundUtilityList(Csound *csound); - ~CsoundUtilityList(); -}; - -/** - * CsoundMYFLTArray() - * - * Creates a pointer for use with csoundGetChannelPtr(), - * csoundGetOutputBuffer(), or other functions that return a - * pointer to an array of floating point values. - * - * CsoundMYFLTArray(int cnt) - * - * Allocates an array of 'cnt' floating point values, for use - * with Csound API functions that take a MYFLT* pointer. - */ - -class PUBLIC CsoundMYFLTArray { - private: - MYFLT *p; - void *pp; - public: - /** - * Returns a MYFLT** pointer for use with csoundGetChannelPtr(). - */ - MYFLT **GetPtr() - { - return (&p); - } - /** - * Returns the address of the element at index 'ndx' (counting from - * zero) as a MYFLT* pointer, or NULL if there is no array. Does not - * check if 'ndx' is valid. - */ - MYFLT *GetPtr(int ndx) - { - if (p) - return &(p[ndx]); - return (MYFLT*) 0; - } - /** - * Sets the array pointer to a MYFLT* value returned by a Csound - * API function (e.g. csoundGetSpin() or csoundGetSpout()). - */ - void SetPtr(MYFLT *ptr) - { - p = ptr; - } - /** - * Stores a floating point value at index 'ndx' (counting from zero). - * No error checking is done, the array is assumed to exist and the - * index is assumed to be valid. - */ - void SetValue(int ndx, double value) - { - p[ndx] = (MYFLT) value; - } - /** - * Sets two floating point values starting at index 'ndx' (counting - * from zero). No error checking is done, the array is assumed to exist - * and the index is assumed to be valid. - */ - void SetValues(int ndx, double v0, double v1) - { - p[ndx] = (MYFLT) v0; p[ndx + 1] = (MYFLT) v1; - } - /** - * Sets three floating point values starting at index 'ndx' (counting - * from zero). No error checking is done, the array is assumed to exist - * and the index is assumed to be valid. - */ - void SetValues(int ndx, double v0, double v1, double v2) - { - p[ndx] = (MYFLT) v0; p[ndx + 1] = (MYFLT) v1; - p[ndx + 2] = (MYFLT) v2; - } - /** - * Sets four floating point values starting at index 'ndx' (counting - * from zero). No error checking is done, the array is assumed to exist - * and the index is assumed to be valid. - */ - void SetValues(int ndx, double v0, double v1, double v2, double v3) - { - p[ndx] = (MYFLT) v0; p[ndx + 1] = (MYFLT) v1; - p[ndx + 2] = (MYFLT) v2; p[ndx + 3] = (MYFLT) v3; - } - /** - * Sets five floating point values starting at index 'ndx' (counting - * from zero). No error checking is done, the array is assumed to exist - * and the index is assumed to be valid. - */ - void SetValues(int ndx, - double v0, double v1, double v2, double v3, double v4) - { - p[ndx] = (MYFLT) v0; p[ndx + 1] = (MYFLT) v1; - p[ndx + 2] = (MYFLT) v2; p[ndx + 3] = (MYFLT) v3; - p[ndx + 4] = (MYFLT) v4; - } - /** - * Sets six floating point values starting at index 'ndx' (counting - * from zero). No error checking is done, the array is assumed to exist - * and the index is assumed to be valid. - */ - void SetValues(int ndx, - double v0, double v1, double v2, double v3, double v4, - double v5) - { - p[ndx] = (MYFLT) v0; p[ndx + 1] = (MYFLT) v1; - p[ndx + 2] = (MYFLT) v2; p[ndx + 3] = (MYFLT) v3; - p[ndx + 4] = (MYFLT) v4; p[ndx + 5] = (MYFLT) v5; - } - /** - * Sets seven floating point values starting at index 'ndx' (counting - * from zero). No error checking is done, the array is assumed to exist - * and the index is assumed to be valid. - */ - void SetValues(int ndx, - double v0, double v1, double v2, double v3, double v4, - double v5, double v6) - { - p[ndx] = (MYFLT) v0; p[ndx + 1] = (MYFLT) v1; - p[ndx + 2] = (MYFLT) v2; p[ndx + 3] = (MYFLT) v3; - p[ndx + 4] = (MYFLT) v4; p[ndx + 5] = (MYFLT) v5; - p[ndx + 6] = (MYFLT) v6; - } - /** - * Sets eight floating point values starting at index 'ndx' (counting - * from zero). No error checking is done, the array is assumed to exist - * and the index is assumed to be valid. - */ - void SetValues(int ndx, - double v0, double v1, double v2, double v3, double v4, - double v5, double v6, double v7) - { - p[ndx] = (MYFLT) v0; p[ndx + 1] = (MYFLT) v1; - p[ndx + 2] = (MYFLT) v2; p[ndx + 3] = (MYFLT) v3; - p[ndx + 4] = (MYFLT) v4; p[ndx + 5] = (MYFLT) v5; - p[ndx + 6] = (MYFLT) v6; p[ndx + 7] = (MYFLT) v7; - } - /** - * Sets nine floating point values starting at index 'ndx' (counting - * from zero). No error checking is done, the array is assumed to exist - * and the index is assumed to be valid. - */ - void SetValues(int ndx, - double v0, double v1, double v2, double v3, double v4, - double v5, double v6, double v7, double v8) - { - p[ndx] = (MYFLT) v0; p[ndx + 1] = (MYFLT) v1; - p[ndx + 2] = (MYFLT) v2; p[ndx + 3] = (MYFLT) v3; - p[ndx + 4] = (MYFLT) v4; p[ndx + 5] = (MYFLT) v5; - p[ndx + 6] = (MYFLT) v6; p[ndx + 7] = (MYFLT) v7; - p[ndx + 8] = (MYFLT) v8; - } - /** - * Sets ten floating point values starting at index 'ndx' (counting - * from zero). No error checking is done, the array is assumed to exist - * and the index is assumed to be valid. - */ - void SetValues(int ndx, - double v0, double v1, double v2, double v3, double v4, - double v5, double v6, double v7, double v8, double v9) - { - p[ndx] = (MYFLT) v0; p[ndx + 1] = (MYFLT) v1; - p[ndx + 2] = (MYFLT) v2; p[ndx + 3] = (MYFLT) v3; - p[ndx + 4] = (MYFLT) v4; p[ndx + 5] = (MYFLT) v5; - p[ndx + 6] = (MYFLT) v6; p[ndx + 7] = (MYFLT) v7; - p[ndx + 8] = (MYFLT) v8; p[ndx + 9] = (MYFLT) v9; - } - /** - * Returns the floating point value at index 'ndx' (counting from zero). - * No error checking is done, the array is assumed to exist and the - * index is assumed to be valid. - */ - double GetValue(int ndx) - { - return (double) p[ndx]; - } - /** - * Copies 'n' values to the array from a source pointer, starting at - * index 'ndx' (counting from zero). No error checking is done. - */ - void SetValues(int ndx, int n, const MYFLT *src) - { - for (int i = 0; i < n; i++) - p[ndx + i] = src[i]; - } - /** - * Copies 'n' values from the array to 'dst', starting at index 'ndx' - * (counting from zero). No error checking is done. - */ - void GetValues(MYFLT *dst, int ndx, int n) - { - for (int i = 0; i < n; i++) - dst[i] = p[ndx + i]; - } - /** - * Stores a string in the array (note: only do this with a pointer - * returned by csoundGetChannelPtr()), optionally limiting the length to - * maxLen - 1 characters. - */ - void SetStringValue(const char *s, int maxLen); - /** - * Returns a string from the array (note: only do this with a pointer - * returned by csoundGetChannelPtr()), or NULL if there is no array. - */ - const char *GetStringValue(); - /** - * Clears the array pointer, and releases any memory that was allocated - * by calling the constructor with a positive number of elements. - */ - void Clear(); - // -------- - CsoundMYFLTArray(); - CsoundMYFLTArray(int n); - ~CsoundMYFLTArray(); -}; - -/** - * A simple class for creating argv[] lists for use with - * functions like csoundCompile(). - */ - -class PUBLIC CsoundArgVList { - private: - char **ArgV_; - int cnt; - void destroy_argv(); - public: - /** - * Returns the count of arguments in the list, zero if there are - * none, and -1 if the list could not be allocated. - */ - int argc(); - /** - * Returns a char** pointer for use with csoundCompile() etc. - */ - char **argv(); - /** - * Returns the argument at the specified index (counting from zero), - * or NULL if the index is out of range. - */ - const char *argv(int ndx); - /** - * Inserts a new value to the argument list at the specified index - * (counting from zero). If there is not enough memory, the list is - * not changed. - */ - void Insert(int ndx, const char *s); - /** - * Appends a new value at the end of the argument list. - * If there is not enough memory, the list is not changed. - */ - void Append(const char *s); - /** - * Removes all elements of the list. - */ - void Clear(); - // -------- - CsoundArgVList(); - ~CsoundArgVList(); -}; - -/** - * Experimental class for wrapping callbacks using SWIG directors. - */ - -class CsoundMidiInputBuffer; -class CsoundMidiOutputBuffer; - -class PUBLIC CsoundCallbackWrapper { - private: - CSOUND *csound_; - public: - virtual void MessageCallback(int attr, char *msg) - { - (void) attr; - (void) msg; - } - virtual double InputValueCallback(const char *chnName) - { - (void) chnName; - return 0.0; - } - virtual void OutputValueCallback(const char *chnName, double value) - { - (void) chnName; - (void) value; - } - virtual int YieldCallback() - { - return 1; - } - virtual void MidiInputCallback(CsoundMidiInputBuffer *p) - { - (void) p; - } - virtual void MidiOutputCallback(CsoundMidiOutputBuffer *p) - { - (void) p; - } - - void SetMessageCallback(); - // void SetInputValueCallback(); - // void SetOutputValueCallback(); - void SetYieldCallback(); - void SetMidiInputCallback(CsoundArgVList *argv); - void SetMidiOutputCallback(CsoundArgVList *argv); - // void SetChannelIOCallbacks(); - CSOUND *GetCsound() - { - return csound_; - } - // for converting SWIG char* type to a Python string - static const char *CharPtrToString(const char *s) - { - return s; - } - // -------- - CsoundCallbackWrapper(Csound *csound); - CsoundCallbackWrapper(CSOUND *csound); - virtual ~CsoundCallbackWrapper() - { - } - private: - static int midiInOpenCallback(CSOUND *, void **, const char *); - static int midiInReadCallback(CSOUND *, void *, unsigned char *, int); - static int midiInCloseCallback(CSOUND *, void *); - static int midiOutOpenCallback(CSOUND *, void **, const char *); - static int midiOutWriteCallback(CSOUND *, void *, - const unsigned char *, int); - static int midiOutCloseCallback(CSOUND *, void *); -}; - -// ---------------------------- MIDI INPUT ---------------------------- - -class PUBLIC CsoundMidiInputBuffer { - private: - unsigned char *buf; - void *mutex_; - int bufReadPos; - int bufWritePos; - int bufBytes; - int bufSize; - public: - CsoundMidiInputBuffer(unsigned char *buf, int bufSize); - ~CsoundMidiInputBuffer(); - /** - * Sends a MIDI message, 'msg' is calculated as follows: - * STATUS + DATA1 * 256 + DATA2 * 65536 - */ - void SendMidiMessage(int msg); - /** - * Sends a MIDI message; 'channel' should be in the range 1 to 16, - * and data1 and data2 should be in the range 0 to 127. - */ - void SendMidiMessage(int status, int channel, int data1, int data2); - /** - * Sends a note-on message on 'channel' (1 to 16) for 'key' (0 to 127) - * with 'velocity' (0 to 127). - */ - void SendNoteOn(int channel, int key, int velocity); - /** - * Sends a note-off message on 'channel' (1 to 16) for 'key' (0 to 127) - * with 'velocity' (0 to 127). - */ - void SendNoteOff(int channel, int key, int velocity); - /** - * Sends a note-off message on 'channel' (1 to 16) for 'key', - * using a 0x90 status with zero velocity. - */ - void SendNoteOff(int channel, int key); - /** - * Sets polyphonic pressure on 'channel' (1 to 16) to 'value' (0 to 127) - * for 'key' (0 to 127). - */ - void SendPolyphonicPressure(int channel, int key, int value); - /** - * Sets controller 'ctl' (0 to 127) to 'value' (0 to 127) - * on 'channel' (1 to 16). - */ - void SendControlChange(int channel, int ctl, int value); - /** - * Sends program change to 'pgm' (1 to 128) on 'channel' (1 to 16). - */ - void SendProgramChange(int channel, int pgm); - /** - * Sets channel pressure to 'value' (0 to 127) on 'channel' (1 to 16). - */ - void SendChannelPressure(int channel, int value); - /** - * Sets pitch bend to 'value' (-8192 to 8191) on 'channel' (1 to 16). - */ - void SendPitchBend(int channel, int value); - // ----------------------------------------------------------------- - friend class CsoundCallbackWrapper; - protected: - /** - * Copies at most 'nBytes' bytes of MIDI data from the buffer to 'buf'. - * Returns the number of bytes copied. - */ - int GetMidiData(unsigned char *buf, int nBytes); -}; - -/** - * The following class allows sending MIDI input messages to a Csound - * instance. - */ - -class PUBLIC CsoundMidiInputStream : public CsoundMidiInputBuffer { - private: - unsigned char buf_[4096]; - CSOUND *csound; - public: - CsoundMidiInputStream(CSOUND *csound); - CsoundMidiInputStream(Csound *csound); - //~CsoundMidiInputStream() - //{ - //} - /** - * Enables MIDI input for the associated Csound instance. - * Should be called between csoundPreCompile() and csoundCompile(). - * If 'argv' is not NULL, the command line arguments required for - * MIDI input are appended. - */ - void EnableMidiInput(CsoundArgVList *argv); - private: - static int midiInOpenCallback(CSOUND *, void **, const char *); - static int midiInReadCallback(CSOUND *, void *, unsigned char *, int); - static int midiInCloseCallback(CSOUND *, void *); -}; - -// ---------------------------- MIDI OUTPUT --------------------------- - -class PUBLIC CsoundMidiOutputBuffer { - private: - unsigned char *buf; - void *mutex_; - int bufReadPos; - int bufWritePos; - int bufBytes; - int bufSize; - public: - CsoundMidiOutputBuffer(unsigned char *buf, int bufSize); - ~CsoundMidiOutputBuffer(); - /** - * Pops and returns the first message from the buffer, in the following - * format: - * STATUS + DATA1 * 256 + DATA2 * 65536 - * where STATUS also includes the channel number (0 to 15), if any. - * The return value is zero if there are no messages. - */ - int PopMessage(); - /** - * Returns the status byte for the first message in the buffer, not - * including the channel number in the case of channel messages. - * The return value is zero if there are no messages. - */ - int GetStatus(); - /** - * Returns the channel number (1 to 16) for the first message in the - * buffer. The return value is zero if there are no messages, or the - * first message is not a channel message. - */ - int GetChannel(); - /** - * Returns the first data byte (0 to 127) for the first message in the - * buffer. The return value is zero if there are no messages, or the - * first message does not have any data bytes. - */ - int GetData1(); - /** - * Returns the second data byte (0 to 127) for the first message in the - * buffer. The return value is zero if there are no messages, or the - * first message has less than two data bytes. - */ - int GetData2(); - // ----------------------------------------------------------------- - friend class CsoundCallbackWrapper; - protected: - /** - * Copies at most 'nBytes' bytes of MIDI data to the buffer from 'buf'. - * Returns the number of bytes copied. - */ - int SendMidiData(const unsigned char *buf, int nBytes); -}; - -/** - * The following class allows receiving MIDI output messages - * from a Csound instance. - */ - -class PUBLIC CsoundMidiOutputStream : public CsoundMidiOutputBuffer { - private: - unsigned char buf_[4096]; - CSOUND *csound; - public: - CsoundMidiOutputStream(CSOUND *csound); - CsoundMidiOutputStream(Csound *csound); - //~CsoundMidiOutputStream() - //{ - //} - /** - * Enables MIDI output for the associated Csound instance. - * Should be called between csoundPreCompile() and csoundCompile(). - * If 'argv' is not NULL, the command line arguments required for - * MIDI output are appended. - */ - void EnableMidiOutput(CsoundArgVList *argv); - private: - static int midiOutOpenCallback(CSOUND *, void **, const char *); - static int midiOutWriteCallback(CSOUND *, void *, - const unsigned char *, int); - static int midiOutCloseCallback(CSOUND *, void *); -}; - -#endif // CSOUND_CS_GLUE_HPP - diff --git a/CsoundAC/pyMsgCb.cpp b/CsoundAC/pyMsgCb.cpp deleted file mode 100644 index efb2c53ef0..0000000000 --- a/CsoundAC/pyMsgCb.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * C S O U N D - * - * L I C E N S E - * - * This software is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "CppSound.hpp" - -extern "C" -{ - int PyRun_SimpleString(const char *string); -} - -static void pythonMessageCallback(CSOUND *csound, - int attr, const char *format, va_list valist) -{ - char buffer[8192]; - static std::string lineBuffer = "print '''"; // FIXME - unsigned int i, len; -#ifdef HAVE_C99 - len = (unsigned int) vsnprintf(&(buffer[0]), (size_t) 8192, format, valist); - if (len >= 8192U) - { - PyRun_SimpleString("print '''Error: message buffer overflow'''"); - return; - } -#else - len = (unsigned int) vsprintf(&(buffer[0]), format, valist); - if (len >= 8192U) - { - PyRun_SimpleString("print '''Error: message buffer overflow'''"); - exit(-1); - } -#endif - for (i = 0; i < len; i++) { - if (buffer[i] == '\n') { - lineBuffer += "'''"; - PyRun_SimpleString(lineBuffer.c_str()); - lineBuffer = "print '''"; - continue; - } - if (buffer[i] == '\'' || buffer[i] == '\\') - lineBuffer += '\\'; - lineBuffer += buffer[i]; - } -} - -void CppSound::setPythonMessageCallback() -{ - SetMessageCallback(pythonMessageCallback); -} - diff --git a/CsoundAC/pyMsgCb_stub.cpp b/CsoundAC/pyMsgCb_stub.cpp deleted file mode 100644 index 6e144043ac..0000000000 --- a/CsoundAC/pyMsgCb_stub.cpp +++ /dev/null @@ -1,10 +0,0 @@ - -// stub to allow compiling a Java wrapper without -// a dependency on the Python library - -#include "CppSound.hpp" - -void CppSound::setPythonMessageCallback() -{ -} - From a2daebc581b2e79da10cfbea92e06c2bdcad30d9 Mon Sep 17 00:00:00 2001 From: gogins Date: Fri, 24 Nov 2023 14:30:22 -0500 Subject: [PATCH 5/5] Bug fixes, reorganized examples (#13). --- CMakeLists.txt | 10 +- CsoundAC/CMakeLists.txt | 1 + CsoundAC/Event.cpp | 4 +- CsoundAC/Score.cpp | 11 +- README.md | 80 +- examples/README.md | 21 + {CsoundAC => examples}/abjad_csoundac.py | 0 {CsoundAC => examples}/athenacl_csoundac.py | 0 .../blue_leaves/Blue_Leaves_von_Ruesner-2.cpp | 0 .../cellular}/Cellular-v5-macos.py | 16 +- {tests => examples/cellular}/M1.mid | Bin {tests => examples/cellular}/M10.mid | Bin {tests => examples/cellular}/M100.mid | Bin {tests => examples/cellular}/M101.mid | Bin {tests => examples/cellular}/M102.mid | Bin {tests => examples/cellular}/M103.mid | Bin {tests => examples/cellular}/M104.mid | Bin {tests => examples/cellular}/M105.mid | Bin {tests => examples/cellular}/M106.mid | Bin {tests => examples/cellular}/M107.mid | Bin {tests => examples/cellular}/M108.mid | Bin {tests => examples/cellular}/M109.mid | Bin {tests => examples/cellular}/M11.mid | Bin {tests => examples/cellular}/M110.mid | Bin {tests => examples/cellular}/M111.mid | Bin {tests => examples/cellular}/M112.mid | Bin {tests => examples/cellular}/M113.mid | Bin {tests => examples/cellular}/M114.mid | Bin {tests => examples/cellular}/M115.mid | Bin {tests => examples/cellular}/M116.mid | Bin {tests => examples/cellular}/M117.mid | Bin {tests => examples/cellular}/M118.mid | Bin {tests => examples/cellular}/M119.mid | Bin {tests => examples/cellular}/M12.mid | Bin {tests => examples/cellular}/M120.mid | Bin {tests => examples/cellular}/M121.mid | Bin {tests => examples/cellular}/M122.mid | Bin {tests => examples/cellular}/M123.mid | Bin {tests => examples/cellular}/M124.mid | Bin {tests => examples/cellular}/M125.mid | Bin {tests => examples/cellular}/M126.mid | Bin {tests => examples/cellular}/M127.mid | Bin {tests => examples/cellular}/M128.mid | Bin {tests => examples/cellular}/M129.mid | Bin {tests => examples/cellular}/M13.mid | Bin {tests => examples/cellular}/M130.mid | Bin {tests => examples/cellular}/M131.mid | Bin {tests => examples/cellular}/M132.mid | Bin {tests => examples/cellular}/M133.mid | Bin {tests => examples/cellular}/M134.mid | Bin {tests => examples/cellular}/M135.mid | Bin {tests => examples/cellular}/M136.mid | Bin {tests => examples/cellular}/M137.mid | Bin {tests => examples/cellular}/M138.mid | Bin {tests => examples/cellular}/M139.mid | Bin {tests => examples/cellular}/M14.mid | Bin {tests => examples/cellular}/M140.mid | Bin {tests => examples/cellular}/M141.mid | Bin {tests => examples/cellular}/M142.mid | Bin {tests => examples/cellular}/M143.mid | Bin {tests => examples/cellular}/M144.mid | Bin {tests => examples/cellular}/M145.mid | Bin {tests => examples/cellular}/M146.mid | Bin {tests => examples/cellular}/M147.mid | Bin {tests => examples/cellular}/M148.mid | Bin {tests => examples/cellular}/M149.mid | Bin {tests => examples/cellular}/M15.mid | Bin {tests => examples/cellular}/M150.mid | Bin {tests => examples/cellular}/M151.mid | Bin {tests => examples/cellular}/M152.mid | Bin {tests => examples/cellular}/M153.mid | Bin {tests => examples/cellular}/M154.mid | Bin {tests => examples/cellular}/M155.mid | Bin {tests => examples/cellular}/M156.mid | Bin {tests => examples/cellular}/M157.mid | Bin {tests => examples/cellular}/M158.mid | Bin {tests => examples/cellular}/M159.mid | Bin {tests => examples/cellular}/M16.mid | Bin {tests => examples/cellular}/M160.mid | Bin {tests => examples/cellular}/M161.mid | Bin {tests => examples/cellular}/M162.mid | Bin {tests => examples/cellular}/M163.mid | Bin {tests => examples/cellular}/M164.mid | Bin {tests => examples/cellular}/M165.mid | Bin {tests => examples/cellular}/M166.mid | Bin {tests => examples/cellular}/M167.mid | Bin {tests => examples/cellular}/M168.mid | Bin {tests => examples/cellular}/M169.mid | Bin {tests => examples/cellular}/M17.mid | Bin {tests => examples/cellular}/M170.mid | Bin {tests => examples/cellular}/M171.mid | Bin {tests => examples/cellular}/M172.mid | Bin {tests => examples/cellular}/M173.mid | Bin {tests => examples/cellular}/M174.mid | Bin {tests => examples/cellular}/M175.mid | Bin {tests => examples/cellular}/M176.mid | Bin {tests => examples/cellular}/M18.mid | Bin {tests => examples/cellular}/M19.mid | Bin {tests => examples/cellular}/M2.mid | Bin {tests => examples/cellular}/M20.mid | Bin {tests => examples/cellular}/M21.mid | Bin {tests => examples/cellular}/M22.mid | Bin {tests => examples/cellular}/M23.mid | Bin {tests => examples/cellular}/M24.mid | Bin {tests => examples/cellular}/M25.mid | Bin {tests => examples/cellular}/M26.mid | Bin {tests => examples/cellular}/M27.mid | Bin {tests => examples/cellular}/M28.mid | Bin {tests => examples/cellular}/M29.mid | Bin {tests => examples/cellular}/M3.mid | Bin {tests => examples/cellular}/M30.mid | Bin {tests => examples/cellular}/M31.mid | Bin {tests => examples/cellular}/M32.mid | Bin {tests => examples/cellular}/M33.mid | Bin {tests => examples/cellular}/M34.mid | Bin {tests => examples/cellular}/M35.mid | Bin {tests => examples/cellular}/M36.mid | Bin {tests => examples/cellular}/M37.mid | Bin {tests => examples/cellular}/M38.mid | Bin {tests => examples/cellular}/M39.mid | Bin {tests => examples/cellular}/M4.mid | Bin {tests => examples/cellular}/M40.mid | Bin {tests => examples/cellular}/M41.mid | Bin {tests => examples/cellular}/M42.mid | Bin {tests => examples/cellular}/M43.mid | Bin {tests => examples/cellular}/M44.mid | Bin {tests => examples/cellular}/M45.mid | Bin {tests => examples/cellular}/M46.mid | Bin {tests => examples/cellular}/M47.mid | Bin {tests => examples/cellular}/M48.mid | Bin {tests => examples/cellular}/M49.mid | Bin {tests => examples/cellular}/M5.mid | Bin {tests => examples/cellular}/M50.mid | Bin {tests => examples/cellular}/M51.mid | Bin {tests => examples/cellular}/M52.mid | Bin {tests => examples/cellular}/M53.mid | Bin {tests => examples/cellular}/M54.mid | Bin {tests => examples/cellular}/M55.mid | Bin {tests => examples/cellular}/M56.mid | Bin {tests => examples/cellular}/M57.mid | Bin {tests => examples/cellular}/M58.mid | Bin {tests => examples/cellular}/M59.mid | Bin {tests => examples/cellular}/M6.mid | Bin {tests => examples/cellular}/M60.mid | Bin {tests => examples/cellular}/M61.mid | Bin {tests => examples/cellular}/M62.mid | Bin {tests => examples/cellular}/M63.mid | Bin {tests => examples/cellular}/M64.mid | Bin {tests => examples/cellular}/M65.mid | Bin {tests => examples/cellular}/M66.mid | Bin {tests => examples/cellular}/M67.mid | Bin {tests => examples/cellular}/M68.mid | Bin {tests => examples/cellular}/M69.mid | Bin {tests => examples/cellular}/M7.mid | Bin {tests => examples/cellular}/M70.mid | Bin {tests => examples/cellular}/M71.mid | Bin {tests => examples/cellular}/M72.mid | Bin {tests => examples/cellular}/M73.mid | Bin {tests => examples/cellular}/M74.mid | Bin {tests => examples/cellular}/M75.mid | Bin {tests => examples/cellular}/M76.mid | Bin {tests => examples/cellular}/M77.mid | Bin {tests => examples/cellular}/M78.mid | Bin {tests => examples/cellular}/M79.mid | Bin {tests => examples/cellular}/M8.mid | Bin {tests => examples/cellular}/M80.mid | Bin {tests => examples/cellular}/M81.mid | Bin {tests => examples/cellular}/M82.mid | Bin {tests => examples/cellular}/M83.mid | Bin {tests => examples/cellular}/M84.mid | Bin {tests => examples/cellular}/M85.mid | Bin {tests => examples/cellular}/M86.mid | Bin {tests => examples/cellular}/M87.mid | Bin {tests => examples/cellular}/M88.mid | Bin {tests => examples/cellular}/M89.mid | Bin {tests => examples/cellular}/M9.mid | Bin {tests => examples/cellular}/M90.mid | Bin {tests => examples/cellular}/M91.mid | Bin {tests => examples/cellular}/M92.mid | Bin {tests => examples/cellular}/M93.mid | Bin {tests => examples/cellular}/M94.mid | Bin {tests => examples/cellular}/M95.mid | Bin {tests => examples/cellular}/M96.mid | Bin {tests => examples/cellular}/M97.mid | Bin {tests => examples/cellular}/M98.mid | Bin {tests => examples/cellular}/M99.mid | Bin {tests => examples/cellular}/T1.mid | Bin {tests => examples/cellular}/T10.mid | Bin {tests => examples/cellular}/T11.mid | Bin {tests => examples/cellular}/T12.mid | Bin {tests => examples/cellular}/T13.mid | Bin {tests => examples/cellular}/T14.mid | Bin {tests => examples/cellular}/T15.mid | Bin {tests => examples/cellular}/T16.mid | Bin {tests => examples/cellular}/T17.mid | Bin {tests => examples/cellular}/T18.mid | Bin {tests => examples/cellular}/T19.mid | Bin {tests => examples/cellular}/T2.mid | Bin {tests => examples/cellular}/T20.mid | Bin {tests => examples/cellular}/T21.mid | Bin {tests => examples/cellular}/T22.mid | Bin {tests => examples/cellular}/T23.mid | Bin {tests => examples/cellular}/T24.mid | Bin {tests => examples/cellular}/T25.mid | Bin {tests => examples/cellular}/T26.mid | Bin {tests => examples/cellular}/T27.mid | Bin {tests => examples/cellular}/T28.mid | Bin {tests => examples/cellular}/T29.mid | Bin {tests => examples/cellular}/T3.mid | Bin {tests => examples/cellular}/T30.mid | Bin {tests => examples/cellular}/T31.mid | Bin {tests => examples/cellular}/T32.mid | Bin {tests => examples/cellular}/T33.mid | Bin {tests => examples/cellular}/T34.mid | Bin {tests => examples/cellular}/T35.mid | Bin {tests => examples/cellular}/T36.mid | Bin {tests => examples/cellular}/T37.mid | Bin {tests => examples/cellular}/T38.mid | Bin {tests => examples/cellular}/T39.mid | Bin {tests => examples/cellular}/T4.mid | Bin {tests => examples/cellular}/T40.mid | Bin {tests => examples/cellular}/T41.mid | Bin {tests => examples/cellular}/T42.mid | Bin {tests => examples/cellular}/T43.mid | Bin {tests => examples/cellular}/T44.mid | Bin {tests => examples/cellular}/T45.mid | Bin {tests => examples/cellular}/T46.mid | Bin {tests => examples/cellular}/T47.mid | Bin {tests => examples/cellular}/T48.mid | Bin {tests => examples/cellular}/T49.mid | Bin {tests => examples/cellular}/T5.mid | Bin {tests => examples/cellular}/T50.mid | Bin {tests => examples/cellular}/T51.mid | Bin {tests => examples/cellular}/T52.mid | Bin {tests => examples/cellular}/T53.mid | Bin {tests => examples/cellular}/T54.mid | Bin {tests => examples/cellular}/T55.mid | Bin {tests => examples/cellular}/T56.mid | Bin {tests => examples/cellular}/T57.mid | Bin {tests => examples/cellular}/T58.mid | Bin {tests => examples/cellular}/T59.mid | Bin {tests => examples/cellular}/T6.mid | Bin {tests => examples/cellular}/T60.mid | Bin {tests => examples/cellular}/T61.mid | Bin {tests => examples/cellular}/T62.mid | Bin {tests => examples/cellular}/T63.mid | Bin {tests => examples/cellular}/T64.mid | Bin {tests => examples/cellular}/T65.mid | Bin {tests => examples/cellular}/T66.mid | Bin {tests => examples/cellular}/T67.mid | Bin {tests => examples/cellular}/T68.mid | Bin {tests => examples/cellular}/T69.mid | Bin {tests => examples/cellular}/T7.mid | Bin {tests => examples/cellular}/T70.mid | Bin {tests => examples/cellular}/T71.mid | Bin {tests => examples/cellular}/T72.mid | Bin {tests => examples/cellular}/T73.mid | Bin {tests => examples/cellular}/T74.mid | Bin {tests => examples/cellular}/T75.mid | Bin {tests => examples/cellular}/T76.mid | Bin {tests => examples/cellular}/T77.mid | Bin {tests => examples/cellular}/T78.mid | Bin {tests => examples/cellular}/T79.mid | Bin {tests => examples/cellular}/T8.mid | Bin {tests => examples/cellular}/T80.mid | Bin {tests => examples/cellular}/T81.mid | Bin {tests => examples/cellular}/T82.mid | Bin {tests => examples/cellular}/T83.mid | Bin {tests => examples/cellular}/T84.mid | Bin {tests => examples/cellular}/T85.mid | Bin {tests => examples/cellular}/T86.mid | Bin {tests => examples/cellular}/T87.mid | Bin {tests => examples/cellular}/T88.mid | Bin {tests => examples/cellular}/T89.mid | Bin {tests => examples/cellular}/T9.mid | Bin {tests => examples/cellular}/T90.mid | Bin {tests => examples/cellular}/T91.mid | Bin {tests => examples/cellular}/T92.mid | Bin {tests => examples/cellular}/T93.mid | Bin {tests => examples/cellular}/T94.mid | Bin {tests => examples/cellular}/T95.mid | Bin {tests => examples/cellular}/T96.mid | Bin .../image_to_score/20180827_212842-1.png | Bin .../image_to_score/image_to_score.cpp | 0 .../message/csound_loader.js | 0 .../message/message.html | 0 {CsoundAC => examples}/music21_csoundac.py | 0 .../musx}/csoundac-gamelan.py | 0 .../musx}/musx-csound-demo.py | 0 .../musx}/musx-csound-gamelan.py | 0 {CsoundAC => examples/musx}/musx_csound.py | 0 {CsoundAC => examples/musx}/musx_csoundac.py | 0 examples/oblivion/oblivion.csd | 1609 +++++++++++++++++ .../oblivion/oblivion.mxl | Bin .../oblivion/oblivion.py | 4 +- .../sierpinski/sierpinski-csound-gtk.py | 0 .../sierpinski/sierpinski-csound-gtk.ui | 0 .../sierpinski/sierpinski-csound.py | 0 .../sierpinski/sierpinski-csound.ui | 0 .../sierpinski/sierpinski_csound_qt.py | 0 .../sierpinski/sierpinski_csound_qt.ui | 0 .../tests}/ChordLindenmayerTest.py | 15 +- .../tests}/CsoundAcUnitTests.py | 0 {tests => examples/tests}/KindsOfChords.py | 0 .../tests}/SoundfileUnitTests.py | 0 .../tests}/VoiceleadUnitTests.py | 0 .../tests}/VoiceleadingNodeUnitTests.py | 0 .../unperformed/unperformed-experiments.html | 0 .../examples => examples}/xanadu/xanadu.csd | 0 playpen/examples/oblivion/oblivion.csd | 921 ---------- playpen/playpen.ini | 10 +- playpen/playpen.py | 4 +- tests/Parachronic-Piano.cpp | 266 --- tests/README.md | 17 - vscode-playpen/extension.js | 11 +- 315 files changed, 1751 insertions(+), 1249 deletions(-) create mode 100644 examples/README.md rename {CsoundAC => examples}/abjad_csoundac.py (100%) rename {CsoundAC => examples}/athenacl_csoundac.py (100%) rename {playpen/examples => examples}/blue_leaves/Blue_Leaves_von_Ruesner-2.cpp (100%) rename {tests => examples/cellular}/Cellular-v5-macos.py (98%) rename {tests => examples/cellular}/M1.mid (100%) rename {tests => examples/cellular}/M10.mid (100%) rename {tests => examples/cellular}/M100.mid (100%) rename {tests => examples/cellular}/M101.mid (100%) rename {tests => examples/cellular}/M102.mid (100%) rename {tests => examples/cellular}/M103.mid (100%) rename {tests => examples/cellular}/M104.mid (100%) rename {tests => examples/cellular}/M105.mid (100%) rename {tests => examples/cellular}/M106.mid (100%) rename {tests => examples/cellular}/M107.mid (100%) rename {tests => examples/cellular}/M108.mid (100%) rename {tests => examples/cellular}/M109.mid (100%) rename {tests => examples/cellular}/M11.mid (100%) rename {tests => examples/cellular}/M110.mid (100%) rename {tests => examples/cellular}/M111.mid (100%) rename {tests => examples/cellular}/M112.mid (100%) rename {tests => examples/cellular}/M113.mid (100%) rename {tests => examples/cellular}/M114.mid (100%) rename {tests => examples/cellular}/M115.mid (100%) rename {tests => examples/cellular}/M116.mid (100%) rename {tests => examples/cellular}/M117.mid (100%) rename {tests => examples/cellular}/M118.mid (100%) rename {tests => examples/cellular}/M119.mid (100%) rename {tests => examples/cellular}/M12.mid (100%) rename {tests => examples/cellular}/M120.mid (100%) rename {tests => examples/cellular}/M121.mid (100%) rename {tests => examples/cellular}/M122.mid (100%) rename {tests => examples/cellular}/M123.mid (100%) rename {tests => examples/cellular}/M124.mid (100%) rename {tests => examples/cellular}/M125.mid (100%) rename {tests => examples/cellular}/M126.mid (100%) rename {tests => examples/cellular}/M127.mid (100%) rename {tests => examples/cellular}/M128.mid (100%) rename {tests => examples/cellular}/M129.mid (100%) rename {tests => examples/cellular}/M13.mid (100%) rename {tests => examples/cellular}/M130.mid (100%) rename {tests => examples/cellular}/M131.mid (100%) rename {tests => examples/cellular}/M132.mid (100%) rename {tests => examples/cellular}/M133.mid (100%) rename {tests => examples/cellular}/M134.mid (100%) rename {tests => examples/cellular}/M135.mid (100%) rename {tests => examples/cellular}/M136.mid (100%) rename {tests => examples/cellular}/M137.mid (100%) rename {tests => examples/cellular}/M138.mid (100%) rename {tests => examples/cellular}/M139.mid (100%) rename {tests => examples/cellular}/M14.mid (100%) rename {tests => examples/cellular}/M140.mid (100%) rename {tests => examples/cellular}/M141.mid (100%) rename {tests => examples/cellular}/M142.mid (100%) rename {tests => examples/cellular}/M143.mid (100%) rename {tests => examples/cellular}/M144.mid (100%) rename {tests => examples/cellular}/M145.mid (100%) rename {tests => examples/cellular}/M146.mid (100%) rename {tests => examples/cellular}/M147.mid (100%) rename {tests => examples/cellular}/M148.mid (100%) rename {tests => examples/cellular}/M149.mid (100%) rename {tests => examples/cellular}/M15.mid (100%) rename {tests => examples/cellular}/M150.mid (100%) rename {tests => examples/cellular}/M151.mid (100%) rename {tests => examples/cellular}/M152.mid (100%) rename {tests => examples/cellular}/M153.mid (100%) rename {tests => examples/cellular}/M154.mid (100%) rename {tests => examples/cellular}/M155.mid (100%) rename {tests => examples/cellular}/M156.mid (100%) rename {tests => examples/cellular}/M157.mid (100%) rename {tests => examples/cellular}/M158.mid (100%) rename {tests => examples/cellular}/M159.mid (100%) rename {tests => examples/cellular}/M16.mid (100%) rename {tests => examples/cellular}/M160.mid (100%) rename {tests => examples/cellular}/M161.mid (100%) rename {tests => examples/cellular}/M162.mid (100%) rename {tests => examples/cellular}/M163.mid (100%) rename {tests => examples/cellular}/M164.mid (100%) rename {tests => examples/cellular}/M165.mid (100%) rename {tests => examples/cellular}/M166.mid (100%) rename {tests => examples/cellular}/M167.mid (100%) rename {tests => examples/cellular}/M168.mid (100%) rename {tests => examples/cellular}/M169.mid (100%) rename {tests => examples/cellular}/M17.mid (100%) rename {tests => examples/cellular}/M170.mid (100%) rename {tests => examples/cellular}/M171.mid (100%) rename {tests => examples/cellular}/M172.mid (100%) rename {tests => examples/cellular}/M173.mid (100%) rename {tests => examples/cellular}/M174.mid (100%) rename {tests => examples/cellular}/M175.mid (100%) rename {tests => examples/cellular}/M176.mid (100%) rename {tests => examples/cellular}/M18.mid (100%) rename {tests => examples/cellular}/M19.mid (100%) rename {tests => examples/cellular}/M2.mid (100%) rename {tests => examples/cellular}/M20.mid (100%) rename {tests => examples/cellular}/M21.mid (100%) rename {tests => examples/cellular}/M22.mid (100%) rename {tests => examples/cellular}/M23.mid (100%) rename {tests => examples/cellular}/M24.mid (100%) rename {tests => examples/cellular}/M25.mid (100%) rename {tests => examples/cellular}/M26.mid (100%) rename {tests => examples/cellular}/M27.mid (100%) rename {tests => examples/cellular}/M28.mid (100%) rename {tests => examples/cellular}/M29.mid (100%) rename {tests => examples/cellular}/M3.mid (100%) rename {tests => examples/cellular}/M30.mid (100%) rename {tests => examples/cellular}/M31.mid (100%) rename {tests => examples/cellular}/M32.mid (100%) rename {tests => examples/cellular}/M33.mid (100%) rename {tests => examples/cellular}/M34.mid (100%) rename {tests => examples/cellular}/M35.mid (100%) rename {tests => examples/cellular}/M36.mid (100%) rename {tests => examples/cellular}/M37.mid (100%) rename {tests => examples/cellular}/M38.mid (100%) rename {tests => examples/cellular}/M39.mid (100%) rename {tests => examples/cellular}/M4.mid (100%) rename {tests => examples/cellular}/M40.mid (100%) rename {tests => examples/cellular}/M41.mid (100%) rename {tests => examples/cellular}/M42.mid (100%) rename {tests => examples/cellular}/M43.mid (100%) rename {tests => examples/cellular}/M44.mid (100%) rename {tests => examples/cellular}/M45.mid (100%) rename {tests => examples/cellular}/M46.mid (100%) rename {tests => examples/cellular}/M47.mid (100%) rename {tests => examples/cellular}/M48.mid (100%) rename {tests => examples/cellular}/M49.mid (100%) rename {tests => examples/cellular}/M5.mid (100%) rename {tests => examples/cellular}/M50.mid (100%) rename {tests => examples/cellular}/M51.mid (100%) rename {tests => examples/cellular}/M52.mid (100%) rename {tests => examples/cellular}/M53.mid (100%) rename {tests => examples/cellular}/M54.mid (100%) rename {tests => examples/cellular}/M55.mid (100%) rename {tests => examples/cellular}/M56.mid (100%) rename {tests => examples/cellular}/M57.mid (100%) rename {tests => examples/cellular}/M58.mid (100%) rename {tests => examples/cellular}/M59.mid (100%) rename {tests => examples/cellular}/M6.mid (100%) rename {tests => examples/cellular}/M60.mid (100%) rename {tests => examples/cellular}/M61.mid (100%) rename {tests => examples/cellular}/M62.mid (100%) rename {tests => examples/cellular}/M63.mid (100%) rename {tests => examples/cellular}/M64.mid (100%) rename {tests => examples/cellular}/M65.mid (100%) rename {tests => examples/cellular}/M66.mid (100%) rename {tests => examples/cellular}/M67.mid (100%) rename {tests => examples/cellular}/M68.mid (100%) rename {tests => examples/cellular}/M69.mid (100%) rename {tests => examples/cellular}/M7.mid (100%) rename {tests => examples/cellular}/M70.mid (100%) rename {tests => examples/cellular}/M71.mid (100%) rename {tests => examples/cellular}/M72.mid (100%) rename {tests => examples/cellular}/M73.mid (100%) rename {tests => examples/cellular}/M74.mid (100%) rename {tests => examples/cellular}/M75.mid (100%) rename {tests => examples/cellular}/M76.mid (100%) rename {tests => examples/cellular}/M77.mid (100%) rename {tests => examples/cellular}/M78.mid (100%) rename {tests => examples/cellular}/M79.mid (100%) rename {tests => examples/cellular}/M8.mid (100%) rename {tests => examples/cellular}/M80.mid (100%) rename {tests => examples/cellular}/M81.mid (100%) rename {tests => examples/cellular}/M82.mid (100%) rename {tests => examples/cellular}/M83.mid (100%) rename {tests => examples/cellular}/M84.mid (100%) rename {tests => examples/cellular}/M85.mid (100%) rename {tests => examples/cellular}/M86.mid (100%) rename {tests => examples/cellular}/M87.mid (100%) rename {tests => examples/cellular}/M88.mid (100%) rename {tests => examples/cellular}/M89.mid (100%) rename {tests => examples/cellular}/M9.mid (100%) rename {tests => examples/cellular}/M90.mid (100%) rename {tests => examples/cellular}/M91.mid (100%) rename {tests => examples/cellular}/M92.mid (100%) rename {tests => examples/cellular}/M93.mid (100%) rename {tests => examples/cellular}/M94.mid (100%) rename {tests => examples/cellular}/M95.mid (100%) rename {tests => examples/cellular}/M96.mid (100%) rename {tests => examples/cellular}/M97.mid (100%) rename {tests => examples/cellular}/M98.mid (100%) rename {tests => examples/cellular}/M99.mid (100%) rename {tests => examples/cellular}/T1.mid (100%) rename {tests => examples/cellular}/T10.mid (100%) rename {tests => examples/cellular}/T11.mid (100%) rename {tests => examples/cellular}/T12.mid (100%) rename {tests => examples/cellular}/T13.mid (100%) rename {tests => examples/cellular}/T14.mid (100%) rename {tests => examples/cellular}/T15.mid (100%) rename {tests => examples/cellular}/T16.mid (100%) rename {tests => examples/cellular}/T17.mid (100%) rename {tests => examples/cellular}/T18.mid (100%) rename {tests => examples/cellular}/T19.mid (100%) rename {tests => examples/cellular}/T2.mid (100%) rename {tests => examples/cellular}/T20.mid (100%) rename {tests => examples/cellular}/T21.mid (100%) rename {tests => examples/cellular}/T22.mid (100%) rename {tests => examples/cellular}/T23.mid (100%) rename {tests => examples/cellular}/T24.mid (100%) rename {tests => examples/cellular}/T25.mid (100%) rename {tests => examples/cellular}/T26.mid (100%) rename {tests => examples/cellular}/T27.mid (100%) rename {tests => examples/cellular}/T28.mid (100%) rename {tests => examples/cellular}/T29.mid (100%) rename {tests => examples/cellular}/T3.mid (100%) rename {tests => examples/cellular}/T30.mid (100%) rename {tests => examples/cellular}/T31.mid (100%) rename {tests => examples/cellular}/T32.mid (100%) rename {tests => examples/cellular}/T33.mid (100%) rename {tests => examples/cellular}/T34.mid (100%) rename {tests => examples/cellular}/T35.mid (100%) rename {tests => examples/cellular}/T36.mid (100%) rename {tests => examples/cellular}/T37.mid (100%) rename {tests => examples/cellular}/T38.mid (100%) rename {tests => examples/cellular}/T39.mid (100%) rename {tests => examples/cellular}/T4.mid (100%) rename {tests => examples/cellular}/T40.mid (100%) rename {tests => examples/cellular}/T41.mid (100%) rename {tests => examples/cellular}/T42.mid (100%) rename {tests => examples/cellular}/T43.mid (100%) rename {tests => examples/cellular}/T44.mid (100%) rename {tests => examples/cellular}/T45.mid (100%) rename {tests => examples/cellular}/T46.mid (100%) rename {tests => examples/cellular}/T47.mid (100%) rename {tests => examples/cellular}/T48.mid (100%) rename {tests => examples/cellular}/T49.mid (100%) rename {tests => examples/cellular}/T5.mid (100%) rename {tests => examples/cellular}/T50.mid (100%) rename {tests => examples/cellular}/T51.mid (100%) rename {tests => examples/cellular}/T52.mid (100%) rename {tests => examples/cellular}/T53.mid (100%) rename {tests => examples/cellular}/T54.mid (100%) rename {tests => examples/cellular}/T55.mid (100%) rename {tests => examples/cellular}/T56.mid (100%) rename {tests => examples/cellular}/T57.mid (100%) rename {tests => examples/cellular}/T58.mid (100%) rename {tests => examples/cellular}/T59.mid (100%) rename {tests => examples/cellular}/T6.mid (100%) rename {tests => examples/cellular}/T60.mid (100%) rename {tests => examples/cellular}/T61.mid (100%) rename {tests => examples/cellular}/T62.mid (100%) rename {tests => examples/cellular}/T63.mid (100%) rename {tests => examples/cellular}/T64.mid (100%) rename {tests => examples/cellular}/T65.mid (100%) rename {tests => examples/cellular}/T66.mid (100%) rename {tests => examples/cellular}/T67.mid (100%) rename {tests => examples/cellular}/T68.mid (100%) rename {tests => examples/cellular}/T69.mid (100%) rename {tests => examples/cellular}/T7.mid (100%) rename {tests => examples/cellular}/T70.mid (100%) rename {tests => examples/cellular}/T71.mid (100%) rename {tests => examples/cellular}/T72.mid (100%) rename {tests => examples/cellular}/T73.mid (100%) rename {tests => examples/cellular}/T74.mid (100%) rename {tests => examples/cellular}/T75.mid (100%) rename {tests => examples/cellular}/T76.mid (100%) rename {tests => examples/cellular}/T77.mid (100%) rename {tests => examples/cellular}/T78.mid (100%) rename {tests => examples/cellular}/T79.mid (100%) rename {tests => examples/cellular}/T8.mid (100%) rename {tests => examples/cellular}/T80.mid (100%) rename {tests => examples/cellular}/T81.mid (100%) rename {tests => examples/cellular}/T82.mid (100%) rename {tests => examples/cellular}/T83.mid (100%) rename {tests => examples/cellular}/T84.mid (100%) rename {tests => examples/cellular}/T85.mid (100%) rename {tests => examples/cellular}/T86.mid (100%) rename {tests => examples/cellular}/T87.mid (100%) rename {tests => examples/cellular}/T88.mid (100%) rename {tests => examples/cellular}/T89.mid (100%) rename {tests => examples/cellular}/T9.mid (100%) rename {tests => examples/cellular}/T90.mid (100%) rename {tests => examples/cellular}/T91.mid (100%) rename {tests => examples/cellular}/T92.mid (100%) rename {tests => examples/cellular}/T93.mid (100%) rename {tests => examples/cellular}/T94.mid (100%) rename {tests => examples/cellular}/T95.mid (100%) rename {tests => examples/cellular}/T96.mid (100%) rename {playpen/examples => examples}/image_to_score/20180827_212842-1.png (100%) rename {playpen/examples => examples}/image_to_score/image_to_score.cpp (100%) rename {playpen/examples => examples}/message/csound_loader.js (100%) rename {playpen/examples => examples}/message/message.html (100%) rename {CsoundAC => examples}/music21_csoundac.py (100%) rename {CsoundAC => examples/musx}/csoundac-gamelan.py (100%) rename {CsoundAC => examples/musx}/musx-csound-demo.py (100%) rename {CsoundAC => examples/musx}/musx-csound-gamelan.py (100%) rename {CsoundAC => examples/musx}/musx_csound.py (100%) rename {CsoundAC => examples/musx}/musx_csoundac.py (100%) create mode 100644 examples/oblivion/oblivion.csd rename {playpen/examples => examples}/oblivion/oblivion.mxl (100%) rename {playpen/examples => examples}/oblivion/oblivion.py (99%) rename {playpen/examples => examples}/sierpinski/sierpinski-csound-gtk.py (100%) rename {playpen/examples => examples}/sierpinski/sierpinski-csound-gtk.ui (100%) rename {playpen/examples => examples}/sierpinski/sierpinski-csound.py (100%) rename {playpen/examples => examples}/sierpinski/sierpinski-csound.ui (100%) rename {playpen/examples => examples}/sierpinski/sierpinski_csound_qt.py (100%) rename {playpen/examples => examples}/sierpinski/sierpinski_csound_qt.ui (100%) rename {tests => examples/tests}/ChordLindenmayerTest.py (98%) rename {tests => examples/tests}/CsoundAcUnitTests.py (100%) rename {tests => examples/tests}/KindsOfChords.py (100%) rename {tests => examples/tests}/SoundfileUnitTests.py (100%) rename {tests => examples/tests}/VoiceleadUnitTests.py (100%) rename {tests => examples/tests}/VoiceleadingNodeUnitTests.py (100%) rename {playpen/examples => examples}/unperformed/unperformed-experiments.html (100%) rename {playpen/examples => examples}/xanadu/xanadu.csd (100%) delete mode 100644 playpen/examples/oblivion/oblivion.csd delete mode 100644 tests/Parachronic-Piano.cpp delete mode 100644 tests/README.md diff --git a/CMakeLists.txt b/CMakeLists.txt index 5858e6627b..cc8a7c36e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,12 +17,20 @@ set(CMAKE_CXX_STANDARD 17) if("${CMAKE_CXX_COMPILER_ID}" MATCHES "MSVC") add_compile_options(/WX-) else() -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wall -Wno-sign-compare -Wno-unknown-pragmas -Wno-misleading-indentation -Wno-writable-strings") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wall -Wno-deprecated-declarations -Wno-sign-compare -Wno-unknown-pragmas -Wno-misleading-indentation -Wno-writable-strings") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") add_compile_options(-Wno-c++11-narrowing) endif() + + +# CMAKE_SYSTEM_NAME relevant here can be Darwin, Windows, Linux, or Android. set(CPACK_ARCHIVE_COMPONENT_INSTALL ON) set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME "csound-ac") +if(DARWIN) + set(CMAKE_MACOSX_RPATH ON) + set(CMAKE_INSTALL_RPATH "/usr/local/lib;~/.local/lib;") +else() +endif() add_definitions(-Dlinux) set(APIVERSION "7.0") diff --git a/CsoundAC/CMakeLists.txt b/CsoundAC/CMakeLists.txt index 61d29e02df..ed6a938b88 100644 --- a/CsoundAC/CMakeLists.txt +++ b/CsoundAC/CMakeLists.txt @@ -4,6 +4,7 @@ include(CheckIncludeFiles) set(CMAKE_VERBOSE_MAKEFILE ON) set(CMAKE_CXX_STANDARD 17) + add_definitions(-fPIC) set(CMAKE_INCLUDE_CURRENT_DIR "On") diff --git a/CsoundAC/Event.cpp b/CsoundAC/Event.cpp index 8564e9c606..5c9670444f 100644 --- a/CsoundAC/Event.cpp +++ b/CsoundAC/Event.cpp @@ -472,7 +472,7 @@ std::string Event::toCsoundIStatementRelease(int tag, double tempering) const std::string Event::toString() const { char buffer[0x100]; - sprintf(buffer, "t%8.3f d%8.3f s%3.0f i%6.2f k%6.2f v%6.2f y%5.2f pcs%8.2f %s", + sprintf(buffer, "Event: t%8.3f d%8.3f s%3.0f i%6.2f k%6.2f v%6.2f y%5.2f pcs%8.2f %s", getTime(), getDuration(), getStatus(), @@ -579,7 +579,7 @@ double Event::getHeight() const void Event::setHeight(double height) { - (*this)[DEPTH] = height; + (*this)[HEIGHT] = height; } double Event::getPitches() const diff --git a/CsoundAC/Score.cpp b/CsoundAC/Score.cpp index d0061100b8..1be2bed57c 100644 --- a/CsoundAC/Score.cpp +++ b/CsoundAC/Score.cpp @@ -141,7 +141,7 @@ void Score::load(std::string filename) stream.open(filename.c_str(), std::ifstream::binary); load(stream); stream.close(); - return; + return; } #if defined(MUSICXML_FOUND) if (filename.find(".musicxml") != std::string::npos || @@ -193,12 +193,13 @@ void Score::load(std::istream &stream) if (!event) { break; } + // void append(double time_, double duration, double status, double instrument, double key, double velocity, double phase=0, double pan=0, double depth=0, double height=0, double pitches=4095); append(event->get_start_time(), event->get_duration(), double(144), double(event->chan), - event->get_pitch(), - event->get_loud()); + double(event->get_pitch()), + double(event->get_loud())); } // MidiFile midiFile; // midiFile.read(stream); @@ -548,7 +549,7 @@ void Score::rescale_event(Event &event) void Score::dump(std::ostream &stream) { - stream << "silence::Score = " << int(size()) << " events:" << std::endl; + stream << "silence::Score " << int(size()) << " events:" << std::endl; for(Score::iterator i = begin(); i != end(); ++i) { (*i).dump(stream); } @@ -613,8 +614,6 @@ void Score::add(double time_, double duration, double status, double instrument, push_back(event); } - - void Score::append_note(double time_, double duration, double status, double instrument, double key, double velocity, double phase, double pan, double depth, double height, double pitches) { Event event; diff --git a/README.md b/README.md index d25862c13e..cc1c2d21d3 100644 --- a/README.md +++ b/README.md @@ -22,12 +22,16 @@ This repository contains: `playpen/README.md`. 3. My Visual Studio Code extension that implements the computer music - playpen. Consider working in this environment. + playpen. Consider working in this environment. For more information, see + `vscode-playpen/README.md` 4. silencio, a JavaScript library for algorithmic composition similar to - CsoundAC. + CsoundAC. However, using the WebAssembly build of CsoundAC in + [csound-wasm](https://github.com/gogins/csound-wasm) is now recommended in + place of silencio. -5. patches, a library of Csound instrument definitions. +5. patches, a library of Csound instrument definitions, developed over many + years and used in many of my pieces. Currently, CsoundAC is supported on macOS and Linux. @@ -41,9 +45,11 @@ log. ## Using -CsoundAC can be used both as a C++ library, and as a Python extension module. -Python is easier to use, but C++ offers considerably more power and speed. I -use both. +CsoundAC can be used both as a C++ library, as a Python extension module, +and as a WebAssembly kodue. Python is easier to use, but C++ offers +considerably more power and speed. The WebAssembly build of CsoundAC in +[csound-wasm](https://github.com/gogins/csound-wasm) has the same power +as the C++ library and somewhat less speed. Examples (some of which can also serve as tests) for the various aspects of csound-ac are maintained in my separate @@ -74,12 +80,30 @@ https://gogins.github.io/csound-examples. 2. There are prebuilt binary releases for this package available at https://github.com/gogins/csound-ac/releases. These can be downloaded, - unzipped in your home directory, and used from there. You will need to add - the directory containing the CsoundAC shared library to your binary search - path, the directory containing the CsoundAC include files to your - compiler's header search path, and the directory containing the _CsoundAC - shared library and CsoundAC.py to your Python path. - + unzipped to `/usr/local` (or even `~/usr/local`), and used from there. + The binary files are archives, not installers. They should be installed in + the same way on all platforms: + + 1. Download the archive from the releases page. + + 2. Use the 7z program to unzip the archive to the output directory, e.g. + `7z x -o/usr/local csound-ac-0.5.0-Darwin.zip`. 7z will ask you what + to do about any files that it might overwrite. + + 3. Run `sudo ldconfig` or take equivalent steps to ensure that the + libraries can be found by the operating system. You may need to add + appropriate directories to your compiler's header files path, and + to the operating system `PATH` environment variable. + + 4. To uninstall, you can list the contents of the archive to a file, + e.g. `unzip unzip csound-ac-0.5.0-Darwin.zip -l > listing.txt`. You + can use this to identify files to remove, and you could even write + a script to parse `listing.txt` and remove all files listed therein. + + Please note, on macOS the CsoundAC libraries are installed by default to + `/usr/local/lib`. They can be installed elsewhere, but if so, you will + probably need to set up install names and rpaths using `otool`. + ## Helpers There are files and directories in the Git repository and in the packages that @@ -112,17 +136,25 @@ these files to your home directory or other places. ## Building On Your Local Computer The following instructions are for macOS. Linux is similar. For -more information, look at `./github/cmake.yaml`. +more information, look at `./github/cmake.yaml`. However, on Linux it may be +better to build Csound for source code. 1. Clone this Git repository. 2. Install prerequisites as follows from the repository root directory: ``` brew update + brew upgrade brew install graphviz brew install doxygen brew install opencv brew install csound + brew install bwfmetaedit + brew install sox + brew install ffmpeg + brew install lame + brew install sndfile + brew install imagemagick git clone "https://gitlab.com/libeigen/eigen.git" ``` @@ -137,3 +169,25 @@ more information, look at `./github/cmake.yaml`. make -j6 VERBOSE=1 sudo make install ``` + +## Release Notes + +### [v7.0](https://github.com/gogins/csound-ac/releases/tag/v7.0-darwin) + +- There is a new version of the Computer Music Playpen, in the form of a + Visual Studio Code extension. This is now the recommnded environment for + using CsoundAC. + +- CsoundAC no longer implements the Soundfile class. + +- CsoundAC no longer maintains the Lua binding. + +- CsoundAC has internalized support for the CppSound class, because the brew + package for Csound on macOS includes the the `libcsnd6` dylib without the + corresponding header files. This may create a breaking change in the API for + some users, but makes it possible to keep maintaining the continuous + integration builds and releases of CsoundAC on GitHub. + + + + \ No newline at end of file diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000000..33711c29f9 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,21 @@ +# csound-ac +Michael Gogins
+https://github.com/gogins
+http://michaelgogins.tumblr.com + +## Examples + +This directory contains examples, mostly in Python, for CsoundAC. Many of +these pieces are old and no longer work, either because they were written for +Python 2, or because they use resources not found here. They can be fixed up +if necessary. + +However, there are some pieces that can be used not only as examples but also +as sanity checks to detect regressions after major commits: + +1. `cellular/Cellular-v5-macos.py`, that uses available resources (with the + exception of Modartt VST3 plugins, which can be substituted), the + MusicModel code in CsoundAC, and the Midifile code in CsoundAC, for both + reading and writing MIDI files. + +2. `Parachronic-Piano.cpp`. \ No newline at end of file diff --git a/CsoundAC/abjad_csoundac.py b/examples/abjad_csoundac.py similarity index 100% rename from CsoundAC/abjad_csoundac.py rename to examples/abjad_csoundac.py diff --git a/CsoundAC/athenacl_csoundac.py b/examples/athenacl_csoundac.py similarity index 100% rename from CsoundAC/athenacl_csoundac.py rename to examples/athenacl_csoundac.py diff --git a/playpen/examples/blue_leaves/Blue_Leaves_von_Ruesner-2.cpp b/examples/blue_leaves/Blue_Leaves_von_Ruesner-2.cpp similarity index 100% rename from playpen/examples/blue_leaves/Blue_Leaves_von_Ruesner-2.cpp rename to examples/blue_leaves/Blue_Leaves_von_Ruesner-2.cpp diff --git a/tests/Cellular-v5-macos.py b/examples/cellular/Cellular-v5-macos.py similarity index 98% rename from tests/Cellular-v5-macos.py rename to examples/cellular/Cellular-v5-macos.py index fa41a9dea1..989808b75b 100644 --- a/tests/Cellular-v5-macos.py +++ b/examples/cellular/Cellular-v5-macos.py @@ -30,10 +30,12 @@ print('Set "rendering" to: "soundfile" or "audio".') print -rendering = "audio" +rendering = "soundfile" model = CsoundAC.MusicModel() +model.thisown = 0 score = model.getScore() +score.thisown = 0 script_filename = sys.argv[0] print('Full Python script: %s' % script_filename) @@ -105,18 +107,21 @@ def read_measure(number): score_node.thisown = 0 filename = 'M' + str(number) + '.mid' score_for_measure = score_node.getScore() + score_for_measure.thisown = 0 score_for_measure.load(filename) # Remove false notes. for i, event in reverse_enumeration(score_for_measure): if event.getChannel() < 0: score_for_measure.remove(i) - #print("Loaded '%s':\n%s" % (filename, score_for_measure.toString())) + print("Loaded '%s':\n%s" % (filename, score_for_measure.toString())) return score_node tempo = 5./3. scale = CsoundAC.Scale("D major") +scale.thisown = 0 chord = scale.chord(1, 4) +chord.thisown = 0 initial_bass = 32 forte_measures = random.choices([1,0], [2/6, 4/6], k=measures_to_play) @@ -191,6 +196,7 @@ def build_voice(voiceleading_node, sequence, instrument, bass, time_offset, pan) duration = score_for_measure.getDuration() * tempo score_for_measure.setDuration(duration) rescale = CsoundAC.Rescale() + rescale.thisown = 0 rescale.setRescale(CsoundAC.Event.TIME, bool(1), bool(0), cumulative_time, 0) rescale.setRescale(CsoundAC.Event.INSTRUMENT, bool(1), bool(1), instrument, 0) bass = bass + bass_increment_per_bar @@ -210,10 +216,12 @@ def build_voice(voiceleading_node, sequence, instrument, bass, time_offset, pan) print() sequence = CsoundAC.Rescale() +sequence.thisown = 0 sequence.setRescale(CsoundAC.Event.VELOCITY, bool(1), bool(1), 60., 12.) # The actual harmony is applied after the notes for all voices have been ' # generated. voiceleading_node = CsoundAC.VoiceleadingNode() +voiceleading_node.thisown = 0 voiceleading_node.addChild(sequence); model.addChild(voiceleading_node) @@ -886,8 +894,9 @@ def build_voice(voiceleading_node, sequence, instrument, bass, time_offset, pan) model.generate() # Fix ending. Instruments would drop out, sustain till the end. Some notes # course will decay first. -score = model.getScore() +print("score:\n", score.getCsoundScore()) score_duration = score.getDuration() + 4. +print("score_duration: ", score_duration) sounding = set() for i, event in reverse_enumeration(score): event.setOffTime(score_duration) @@ -897,6 +906,7 @@ def build_voice(voiceleading_node, sequence, instrument, bass, time_offset, pan) if len(sounding) == total_instruments: break score.save(model.getMidifileFilepath()) +## print("score again:\n", score.toString()) model.performMaster() if rendering == 'soundfile': model.translateMaster() diff --git a/tests/M1.mid b/examples/cellular/M1.mid similarity index 100% rename from tests/M1.mid rename to examples/cellular/M1.mid diff --git a/tests/M10.mid b/examples/cellular/M10.mid similarity index 100% rename from tests/M10.mid rename to examples/cellular/M10.mid diff --git a/tests/M100.mid b/examples/cellular/M100.mid similarity index 100% rename from tests/M100.mid rename to examples/cellular/M100.mid diff --git a/tests/M101.mid b/examples/cellular/M101.mid similarity index 100% rename from tests/M101.mid rename to examples/cellular/M101.mid diff --git a/tests/M102.mid b/examples/cellular/M102.mid similarity index 100% rename from tests/M102.mid rename to examples/cellular/M102.mid diff --git a/tests/M103.mid b/examples/cellular/M103.mid similarity index 100% rename from tests/M103.mid rename to examples/cellular/M103.mid diff --git a/tests/M104.mid b/examples/cellular/M104.mid similarity index 100% rename from tests/M104.mid rename to examples/cellular/M104.mid diff --git a/tests/M105.mid b/examples/cellular/M105.mid similarity index 100% rename from tests/M105.mid rename to examples/cellular/M105.mid diff --git a/tests/M106.mid b/examples/cellular/M106.mid similarity index 100% rename from tests/M106.mid rename to examples/cellular/M106.mid diff --git a/tests/M107.mid b/examples/cellular/M107.mid similarity index 100% rename from tests/M107.mid rename to examples/cellular/M107.mid diff --git a/tests/M108.mid b/examples/cellular/M108.mid similarity index 100% rename from tests/M108.mid rename to examples/cellular/M108.mid diff --git a/tests/M109.mid b/examples/cellular/M109.mid similarity index 100% rename from tests/M109.mid rename to examples/cellular/M109.mid diff --git a/tests/M11.mid b/examples/cellular/M11.mid similarity index 100% rename from tests/M11.mid rename to examples/cellular/M11.mid diff --git a/tests/M110.mid b/examples/cellular/M110.mid similarity index 100% rename from tests/M110.mid rename to examples/cellular/M110.mid diff --git a/tests/M111.mid b/examples/cellular/M111.mid similarity index 100% rename from tests/M111.mid rename to examples/cellular/M111.mid diff --git a/tests/M112.mid b/examples/cellular/M112.mid similarity index 100% rename from tests/M112.mid rename to examples/cellular/M112.mid diff --git a/tests/M113.mid b/examples/cellular/M113.mid similarity index 100% rename from tests/M113.mid rename to examples/cellular/M113.mid diff --git a/tests/M114.mid b/examples/cellular/M114.mid similarity index 100% rename from tests/M114.mid rename to examples/cellular/M114.mid diff --git a/tests/M115.mid b/examples/cellular/M115.mid similarity index 100% rename from tests/M115.mid rename to examples/cellular/M115.mid diff --git a/tests/M116.mid b/examples/cellular/M116.mid similarity index 100% rename from tests/M116.mid rename to examples/cellular/M116.mid diff --git a/tests/M117.mid b/examples/cellular/M117.mid similarity index 100% rename from tests/M117.mid rename to examples/cellular/M117.mid diff --git a/tests/M118.mid b/examples/cellular/M118.mid similarity index 100% rename from tests/M118.mid rename to examples/cellular/M118.mid diff --git a/tests/M119.mid b/examples/cellular/M119.mid similarity index 100% rename from tests/M119.mid rename to examples/cellular/M119.mid diff --git a/tests/M12.mid b/examples/cellular/M12.mid similarity index 100% rename from tests/M12.mid rename to examples/cellular/M12.mid diff --git a/tests/M120.mid b/examples/cellular/M120.mid similarity index 100% rename from tests/M120.mid rename to examples/cellular/M120.mid diff --git a/tests/M121.mid b/examples/cellular/M121.mid similarity index 100% rename from tests/M121.mid rename to examples/cellular/M121.mid diff --git a/tests/M122.mid b/examples/cellular/M122.mid similarity index 100% rename from tests/M122.mid rename to examples/cellular/M122.mid diff --git a/tests/M123.mid b/examples/cellular/M123.mid similarity index 100% rename from tests/M123.mid rename to examples/cellular/M123.mid diff --git a/tests/M124.mid b/examples/cellular/M124.mid similarity index 100% rename from tests/M124.mid rename to examples/cellular/M124.mid diff --git a/tests/M125.mid b/examples/cellular/M125.mid similarity index 100% rename from tests/M125.mid rename to examples/cellular/M125.mid diff --git a/tests/M126.mid b/examples/cellular/M126.mid similarity index 100% rename from tests/M126.mid rename to examples/cellular/M126.mid diff --git a/tests/M127.mid b/examples/cellular/M127.mid similarity index 100% rename from tests/M127.mid rename to examples/cellular/M127.mid diff --git a/tests/M128.mid b/examples/cellular/M128.mid similarity index 100% rename from tests/M128.mid rename to examples/cellular/M128.mid diff --git a/tests/M129.mid b/examples/cellular/M129.mid similarity index 100% rename from tests/M129.mid rename to examples/cellular/M129.mid diff --git a/tests/M13.mid b/examples/cellular/M13.mid similarity index 100% rename from tests/M13.mid rename to examples/cellular/M13.mid diff --git a/tests/M130.mid b/examples/cellular/M130.mid similarity index 100% rename from tests/M130.mid rename to examples/cellular/M130.mid diff --git a/tests/M131.mid b/examples/cellular/M131.mid similarity index 100% rename from tests/M131.mid rename to examples/cellular/M131.mid diff --git a/tests/M132.mid b/examples/cellular/M132.mid similarity index 100% rename from tests/M132.mid rename to examples/cellular/M132.mid diff --git a/tests/M133.mid b/examples/cellular/M133.mid similarity index 100% rename from tests/M133.mid rename to examples/cellular/M133.mid diff --git a/tests/M134.mid b/examples/cellular/M134.mid similarity index 100% rename from tests/M134.mid rename to examples/cellular/M134.mid diff --git a/tests/M135.mid b/examples/cellular/M135.mid similarity index 100% rename from tests/M135.mid rename to examples/cellular/M135.mid diff --git a/tests/M136.mid b/examples/cellular/M136.mid similarity index 100% rename from tests/M136.mid rename to examples/cellular/M136.mid diff --git a/tests/M137.mid b/examples/cellular/M137.mid similarity index 100% rename from tests/M137.mid rename to examples/cellular/M137.mid diff --git a/tests/M138.mid b/examples/cellular/M138.mid similarity index 100% rename from tests/M138.mid rename to examples/cellular/M138.mid diff --git a/tests/M139.mid b/examples/cellular/M139.mid similarity index 100% rename from tests/M139.mid rename to examples/cellular/M139.mid diff --git a/tests/M14.mid b/examples/cellular/M14.mid similarity index 100% rename from tests/M14.mid rename to examples/cellular/M14.mid diff --git a/tests/M140.mid b/examples/cellular/M140.mid similarity index 100% rename from tests/M140.mid rename to examples/cellular/M140.mid diff --git a/tests/M141.mid b/examples/cellular/M141.mid similarity index 100% rename from tests/M141.mid rename to examples/cellular/M141.mid diff --git a/tests/M142.mid b/examples/cellular/M142.mid similarity index 100% rename from tests/M142.mid rename to examples/cellular/M142.mid diff --git a/tests/M143.mid b/examples/cellular/M143.mid similarity index 100% rename from tests/M143.mid rename to examples/cellular/M143.mid diff --git a/tests/M144.mid b/examples/cellular/M144.mid similarity index 100% rename from tests/M144.mid rename to examples/cellular/M144.mid diff --git a/tests/M145.mid b/examples/cellular/M145.mid similarity index 100% rename from tests/M145.mid rename to examples/cellular/M145.mid diff --git a/tests/M146.mid b/examples/cellular/M146.mid similarity index 100% rename from tests/M146.mid rename to examples/cellular/M146.mid diff --git a/tests/M147.mid b/examples/cellular/M147.mid similarity index 100% rename from tests/M147.mid rename to examples/cellular/M147.mid diff --git a/tests/M148.mid b/examples/cellular/M148.mid similarity index 100% rename from tests/M148.mid rename to examples/cellular/M148.mid diff --git a/tests/M149.mid b/examples/cellular/M149.mid similarity index 100% rename from tests/M149.mid rename to examples/cellular/M149.mid diff --git a/tests/M15.mid b/examples/cellular/M15.mid similarity index 100% rename from tests/M15.mid rename to examples/cellular/M15.mid diff --git a/tests/M150.mid b/examples/cellular/M150.mid similarity index 100% rename from tests/M150.mid rename to examples/cellular/M150.mid diff --git a/tests/M151.mid b/examples/cellular/M151.mid similarity index 100% rename from tests/M151.mid rename to examples/cellular/M151.mid diff --git a/tests/M152.mid b/examples/cellular/M152.mid similarity index 100% rename from tests/M152.mid rename to examples/cellular/M152.mid diff --git a/tests/M153.mid b/examples/cellular/M153.mid similarity index 100% rename from tests/M153.mid rename to examples/cellular/M153.mid diff --git a/tests/M154.mid b/examples/cellular/M154.mid similarity index 100% rename from tests/M154.mid rename to examples/cellular/M154.mid diff --git a/tests/M155.mid b/examples/cellular/M155.mid similarity index 100% rename from tests/M155.mid rename to examples/cellular/M155.mid diff --git a/tests/M156.mid b/examples/cellular/M156.mid similarity index 100% rename from tests/M156.mid rename to examples/cellular/M156.mid diff --git a/tests/M157.mid b/examples/cellular/M157.mid similarity index 100% rename from tests/M157.mid rename to examples/cellular/M157.mid diff --git a/tests/M158.mid b/examples/cellular/M158.mid similarity index 100% rename from tests/M158.mid rename to examples/cellular/M158.mid diff --git a/tests/M159.mid b/examples/cellular/M159.mid similarity index 100% rename from tests/M159.mid rename to examples/cellular/M159.mid diff --git a/tests/M16.mid b/examples/cellular/M16.mid similarity index 100% rename from tests/M16.mid rename to examples/cellular/M16.mid diff --git a/tests/M160.mid b/examples/cellular/M160.mid similarity index 100% rename from tests/M160.mid rename to examples/cellular/M160.mid diff --git a/tests/M161.mid b/examples/cellular/M161.mid similarity index 100% rename from tests/M161.mid rename to examples/cellular/M161.mid diff --git a/tests/M162.mid b/examples/cellular/M162.mid similarity index 100% rename from tests/M162.mid rename to examples/cellular/M162.mid diff --git a/tests/M163.mid b/examples/cellular/M163.mid similarity index 100% rename from tests/M163.mid rename to examples/cellular/M163.mid diff --git a/tests/M164.mid b/examples/cellular/M164.mid similarity index 100% rename from tests/M164.mid rename to examples/cellular/M164.mid diff --git a/tests/M165.mid b/examples/cellular/M165.mid similarity index 100% rename from tests/M165.mid rename to examples/cellular/M165.mid diff --git a/tests/M166.mid b/examples/cellular/M166.mid similarity index 100% rename from tests/M166.mid rename to examples/cellular/M166.mid diff --git a/tests/M167.mid b/examples/cellular/M167.mid similarity index 100% rename from tests/M167.mid rename to examples/cellular/M167.mid diff --git a/tests/M168.mid b/examples/cellular/M168.mid similarity index 100% rename from tests/M168.mid rename to examples/cellular/M168.mid diff --git a/tests/M169.mid b/examples/cellular/M169.mid similarity index 100% rename from tests/M169.mid rename to examples/cellular/M169.mid diff --git a/tests/M17.mid b/examples/cellular/M17.mid similarity index 100% rename from tests/M17.mid rename to examples/cellular/M17.mid diff --git a/tests/M170.mid b/examples/cellular/M170.mid similarity index 100% rename from tests/M170.mid rename to examples/cellular/M170.mid diff --git a/tests/M171.mid b/examples/cellular/M171.mid similarity index 100% rename from tests/M171.mid rename to examples/cellular/M171.mid diff --git a/tests/M172.mid b/examples/cellular/M172.mid similarity index 100% rename from tests/M172.mid rename to examples/cellular/M172.mid diff --git a/tests/M173.mid b/examples/cellular/M173.mid similarity index 100% rename from tests/M173.mid rename to examples/cellular/M173.mid diff --git a/tests/M174.mid b/examples/cellular/M174.mid similarity index 100% rename from tests/M174.mid rename to examples/cellular/M174.mid diff --git a/tests/M175.mid b/examples/cellular/M175.mid similarity index 100% rename from tests/M175.mid rename to examples/cellular/M175.mid diff --git a/tests/M176.mid b/examples/cellular/M176.mid similarity index 100% rename from tests/M176.mid rename to examples/cellular/M176.mid diff --git a/tests/M18.mid b/examples/cellular/M18.mid similarity index 100% rename from tests/M18.mid rename to examples/cellular/M18.mid diff --git a/tests/M19.mid b/examples/cellular/M19.mid similarity index 100% rename from tests/M19.mid rename to examples/cellular/M19.mid diff --git a/tests/M2.mid b/examples/cellular/M2.mid similarity index 100% rename from tests/M2.mid rename to examples/cellular/M2.mid diff --git a/tests/M20.mid b/examples/cellular/M20.mid similarity index 100% rename from tests/M20.mid rename to examples/cellular/M20.mid diff --git a/tests/M21.mid b/examples/cellular/M21.mid similarity index 100% rename from tests/M21.mid rename to examples/cellular/M21.mid diff --git a/tests/M22.mid b/examples/cellular/M22.mid similarity index 100% rename from tests/M22.mid rename to examples/cellular/M22.mid diff --git a/tests/M23.mid b/examples/cellular/M23.mid similarity index 100% rename from tests/M23.mid rename to examples/cellular/M23.mid diff --git a/tests/M24.mid b/examples/cellular/M24.mid similarity index 100% rename from tests/M24.mid rename to examples/cellular/M24.mid diff --git a/tests/M25.mid b/examples/cellular/M25.mid similarity index 100% rename from tests/M25.mid rename to examples/cellular/M25.mid diff --git a/tests/M26.mid b/examples/cellular/M26.mid similarity index 100% rename from tests/M26.mid rename to examples/cellular/M26.mid diff --git a/tests/M27.mid b/examples/cellular/M27.mid similarity index 100% rename from tests/M27.mid rename to examples/cellular/M27.mid diff --git a/tests/M28.mid b/examples/cellular/M28.mid similarity index 100% rename from tests/M28.mid rename to examples/cellular/M28.mid diff --git a/tests/M29.mid b/examples/cellular/M29.mid similarity index 100% rename from tests/M29.mid rename to examples/cellular/M29.mid diff --git a/tests/M3.mid b/examples/cellular/M3.mid similarity index 100% rename from tests/M3.mid rename to examples/cellular/M3.mid diff --git a/tests/M30.mid b/examples/cellular/M30.mid similarity index 100% rename from tests/M30.mid rename to examples/cellular/M30.mid diff --git a/tests/M31.mid b/examples/cellular/M31.mid similarity index 100% rename from tests/M31.mid rename to examples/cellular/M31.mid diff --git a/tests/M32.mid b/examples/cellular/M32.mid similarity index 100% rename from tests/M32.mid rename to examples/cellular/M32.mid diff --git a/tests/M33.mid b/examples/cellular/M33.mid similarity index 100% rename from tests/M33.mid rename to examples/cellular/M33.mid diff --git a/tests/M34.mid b/examples/cellular/M34.mid similarity index 100% rename from tests/M34.mid rename to examples/cellular/M34.mid diff --git a/tests/M35.mid b/examples/cellular/M35.mid similarity index 100% rename from tests/M35.mid rename to examples/cellular/M35.mid diff --git a/tests/M36.mid b/examples/cellular/M36.mid similarity index 100% rename from tests/M36.mid rename to examples/cellular/M36.mid diff --git a/tests/M37.mid b/examples/cellular/M37.mid similarity index 100% rename from tests/M37.mid rename to examples/cellular/M37.mid diff --git a/tests/M38.mid b/examples/cellular/M38.mid similarity index 100% rename from tests/M38.mid rename to examples/cellular/M38.mid diff --git a/tests/M39.mid b/examples/cellular/M39.mid similarity index 100% rename from tests/M39.mid rename to examples/cellular/M39.mid diff --git a/tests/M4.mid b/examples/cellular/M4.mid similarity index 100% rename from tests/M4.mid rename to examples/cellular/M4.mid diff --git a/tests/M40.mid b/examples/cellular/M40.mid similarity index 100% rename from tests/M40.mid rename to examples/cellular/M40.mid diff --git a/tests/M41.mid b/examples/cellular/M41.mid similarity index 100% rename from tests/M41.mid rename to examples/cellular/M41.mid diff --git a/tests/M42.mid b/examples/cellular/M42.mid similarity index 100% rename from tests/M42.mid rename to examples/cellular/M42.mid diff --git a/tests/M43.mid b/examples/cellular/M43.mid similarity index 100% rename from tests/M43.mid rename to examples/cellular/M43.mid diff --git a/tests/M44.mid b/examples/cellular/M44.mid similarity index 100% rename from tests/M44.mid rename to examples/cellular/M44.mid diff --git a/tests/M45.mid b/examples/cellular/M45.mid similarity index 100% rename from tests/M45.mid rename to examples/cellular/M45.mid diff --git a/tests/M46.mid b/examples/cellular/M46.mid similarity index 100% rename from tests/M46.mid rename to examples/cellular/M46.mid diff --git a/tests/M47.mid b/examples/cellular/M47.mid similarity index 100% rename from tests/M47.mid rename to examples/cellular/M47.mid diff --git a/tests/M48.mid b/examples/cellular/M48.mid similarity index 100% rename from tests/M48.mid rename to examples/cellular/M48.mid diff --git a/tests/M49.mid b/examples/cellular/M49.mid similarity index 100% rename from tests/M49.mid rename to examples/cellular/M49.mid diff --git a/tests/M5.mid b/examples/cellular/M5.mid similarity index 100% rename from tests/M5.mid rename to examples/cellular/M5.mid diff --git a/tests/M50.mid b/examples/cellular/M50.mid similarity index 100% rename from tests/M50.mid rename to examples/cellular/M50.mid diff --git a/tests/M51.mid b/examples/cellular/M51.mid similarity index 100% rename from tests/M51.mid rename to examples/cellular/M51.mid diff --git a/tests/M52.mid b/examples/cellular/M52.mid similarity index 100% rename from tests/M52.mid rename to examples/cellular/M52.mid diff --git a/tests/M53.mid b/examples/cellular/M53.mid similarity index 100% rename from tests/M53.mid rename to examples/cellular/M53.mid diff --git a/tests/M54.mid b/examples/cellular/M54.mid similarity index 100% rename from tests/M54.mid rename to examples/cellular/M54.mid diff --git a/tests/M55.mid b/examples/cellular/M55.mid similarity index 100% rename from tests/M55.mid rename to examples/cellular/M55.mid diff --git a/tests/M56.mid b/examples/cellular/M56.mid similarity index 100% rename from tests/M56.mid rename to examples/cellular/M56.mid diff --git a/tests/M57.mid b/examples/cellular/M57.mid similarity index 100% rename from tests/M57.mid rename to examples/cellular/M57.mid diff --git a/tests/M58.mid b/examples/cellular/M58.mid similarity index 100% rename from tests/M58.mid rename to examples/cellular/M58.mid diff --git a/tests/M59.mid b/examples/cellular/M59.mid similarity index 100% rename from tests/M59.mid rename to examples/cellular/M59.mid diff --git a/tests/M6.mid b/examples/cellular/M6.mid similarity index 100% rename from tests/M6.mid rename to examples/cellular/M6.mid diff --git a/tests/M60.mid b/examples/cellular/M60.mid similarity index 100% rename from tests/M60.mid rename to examples/cellular/M60.mid diff --git a/tests/M61.mid b/examples/cellular/M61.mid similarity index 100% rename from tests/M61.mid rename to examples/cellular/M61.mid diff --git a/tests/M62.mid b/examples/cellular/M62.mid similarity index 100% rename from tests/M62.mid rename to examples/cellular/M62.mid diff --git a/tests/M63.mid b/examples/cellular/M63.mid similarity index 100% rename from tests/M63.mid rename to examples/cellular/M63.mid diff --git a/tests/M64.mid b/examples/cellular/M64.mid similarity index 100% rename from tests/M64.mid rename to examples/cellular/M64.mid diff --git a/tests/M65.mid b/examples/cellular/M65.mid similarity index 100% rename from tests/M65.mid rename to examples/cellular/M65.mid diff --git a/tests/M66.mid b/examples/cellular/M66.mid similarity index 100% rename from tests/M66.mid rename to examples/cellular/M66.mid diff --git a/tests/M67.mid b/examples/cellular/M67.mid similarity index 100% rename from tests/M67.mid rename to examples/cellular/M67.mid diff --git a/tests/M68.mid b/examples/cellular/M68.mid similarity index 100% rename from tests/M68.mid rename to examples/cellular/M68.mid diff --git a/tests/M69.mid b/examples/cellular/M69.mid similarity index 100% rename from tests/M69.mid rename to examples/cellular/M69.mid diff --git a/tests/M7.mid b/examples/cellular/M7.mid similarity index 100% rename from tests/M7.mid rename to examples/cellular/M7.mid diff --git a/tests/M70.mid b/examples/cellular/M70.mid similarity index 100% rename from tests/M70.mid rename to examples/cellular/M70.mid diff --git a/tests/M71.mid b/examples/cellular/M71.mid similarity index 100% rename from tests/M71.mid rename to examples/cellular/M71.mid diff --git a/tests/M72.mid b/examples/cellular/M72.mid similarity index 100% rename from tests/M72.mid rename to examples/cellular/M72.mid diff --git a/tests/M73.mid b/examples/cellular/M73.mid similarity index 100% rename from tests/M73.mid rename to examples/cellular/M73.mid diff --git a/tests/M74.mid b/examples/cellular/M74.mid similarity index 100% rename from tests/M74.mid rename to examples/cellular/M74.mid diff --git a/tests/M75.mid b/examples/cellular/M75.mid similarity index 100% rename from tests/M75.mid rename to examples/cellular/M75.mid diff --git a/tests/M76.mid b/examples/cellular/M76.mid similarity index 100% rename from tests/M76.mid rename to examples/cellular/M76.mid diff --git a/tests/M77.mid b/examples/cellular/M77.mid similarity index 100% rename from tests/M77.mid rename to examples/cellular/M77.mid diff --git a/tests/M78.mid b/examples/cellular/M78.mid similarity index 100% rename from tests/M78.mid rename to examples/cellular/M78.mid diff --git a/tests/M79.mid b/examples/cellular/M79.mid similarity index 100% rename from tests/M79.mid rename to examples/cellular/M79.mid diff --git a/tests/M8.mid b/examples/cellular/M8.mid similarity index 100% rename from tests/M8.mid rename to examples/cellular/M8.mid diff --git a/tests/M80.mid b/examples/cellular/M80.mid similarity index 100% rename from tests/M80.mid rename to examples/cellular/M80.mid diff --git a/tests/M81.mid b/examples/cellular/M81.mid similarity index 100% rename from tests/M81.mid rename to examples/cellular/M81.mid diff --git a/tests/M82.mid b/examples/cellular/M82.mid similarity index 100% rename from tests/M82.mid rename to examples/cellular/M82.mid diff --git a/tests/M83.mid b/examples/cellular/M83.mid similarity index 100% rename from tests/M83.mid rename to examples/cellular/M83.mid diff --git a/tests/M84.mid b/examples/cellular/M84.mid similarity index 100% rename from tests/M84.mid rename to examples/cellular/M84.mid diff --git a/tests/M85.mid b/examples/cellular/M85.mid similarity index 100% rename from tests/M85.mid rename to examples/cellular/M85.mid diff --git a/tests/M86.mid b/examples/cellular/M86.mid similarity index 100% rename from tests/M86.mid rename to examples/cellular/M86.mid diff --git a/tests/M87.mid b/examples/cellular/M87.mid similarity index 100% rename from tests/M87.mid rename to examples/cellular/M87.mid diff --git a/tests/M88.mid b/examples/cellular/M88.mid similarity index 100% rename from tests/M88.mid rename to examples/cellular/M88.mid diff --git a/tests/M89.mid b/examples/cellular/M89.mid similarity index 100% rename from tests/M89.mid rename to examples/cellular/M89.mid diff --git a/tests/M9.mid b/examples/cellular/M9.mid similarity index 100% rename from tests/M9.mid rename to examples/cellular/M9.mid diff --git a/tests/M90.mid b/examples/cellular/M90.mid similarity index 100% rename from tests/M90.mid rename to examples/cellular/M90.mid diff --git a/tests/M91.mid b/examples/cellular/M91.mid similarity index 100% rename from tests/M91.mid rename to examples/cellular/M91.mid diff --git a/tests/M92.mid b/examples/cellular/M92.mid similarity index 100% rename from tests/M92.mid rename to examples/cellular/M92.mid diff --git a/tests/M93.mid b/examples/cellular/M93.mid similarity index 100% rename from tests/M93.mid rename to examples/cellular/M93.mid diff --git a/tests/M94.mid b/examples/cellular/M94.mid similarity index 100% rename from tests/M94.mid rename to examples/cellular/M94.mid diff --git a/tests/M95.mid b/examples/cellular/M95.mid similarity index 100% rename from tests/M95.mid rename to examples/cellular/M95.mid diff --git a/tests/M96.mid b/examples/cellular/M96.mid similarity index 100% rename from tests/M96.mid rename to examples/cellular/M96.mid diff --git a/tests/M97.mid b/examples/cellular/M97.mid similarity index 100% rename from tests/M97.mid rename to examples/cellular/M97.mid diff --git a/tests/M98.mid b/examples/cellular/M98.mid similarity index 100% rename from tests/M98.mid rename to examples/cellular/M98.mid diff --git a/tests/M99.mid b/examples/cellular/M99.mid similarity index 100% rename from tests/M99.mid rename to examples/cellular/M99.mid diff --git a/tests/T1.mid b/examples/cellular/T1.mid similarity index 100% rename from tests/T1.mid rename to examples/cellular/T1.mid diff --git a/tests/T10.mid b/examples/cellular/T10.mid similarity index 100% rename from tests/T10.mid rename to examples/cellular/T10.mid diff --git a/tests/T11.mid b/examples/cellular/T11.mid similarity index 100% rename from tests/T11.mid rename to examples/cellular/T11.mid diff --git a/tests/T12.mid b/examples/cellular/T12.mid similarity index 100% rename from tests/T12.mid rename to examples/cellular/T12.mid diff --git a/tests/T13.mid b/examples/cellular/T13.mid similarity index 100% rename from tests/T13.mid rename to examples/cellular/T13.mid diff --git a/tests/T14.mid b/examples/cellular/T14.mid similarity index 100% rename from tests/T14.mid rename to examples/cellular/T14.mid diff --git a/tests/T15.mid b/examples/cellular/T15.mid similarity index 100% rename from tests/T15.mid rename to examples/cellular/T15.mid diff --git a/tests/T16.mid b/examples/cellular/T16.mid similarity index 100% rename from tests/T16.mid rename to examples/cellular/T16.mid diff --git a/tests/T17.mid b/examples/cellular/T17.mid similarity index 100% rename from tests/T17.mid rename to examples/cellular/T17.mid diff --git a/tests/T18.mid b/examples/cellular/T18.mid similarity index 100% rename from tests/T18.mid rename to examples/cellular/T18.mid diff --git a/tests/T19.mid b/examples/cellular/T19.mid similarity index 100% rename from tests/T19.mid rename to examples/cellular/T19.mid diff --git a/tests/T2.mid b/examples/cellular/T2.mid similarity index 100% rename from tests/T2.mid rename to examples/cellular/T2.mid diff --git a/tests/T20.mid b/examples/cellular/T20.mid similarity index 100% rename from tests/T20.mid rename to examples/cellular/T20.mid diff --git a/tests/T21.mid b/examples/cellular/T21.mid similarity index 100% rename from tests/T21.mid rename to examples/cellular/T21.mid diff --git a/tests/T22.mid b/examples/cellular/T22.mid similarity index 100% rename from tests/T22.mid rename to examples/cellular/T22.mid diff --git a/tests/T23.mid b/examples/cellular/T23.mid similarity index 100% rename from tests/T23.mid rename to examples/cellular/T23.mid diff --git a/tests/T24.mid b/examples/cellular/T24.mid similarity index 100% rename from tests/T24.mid rename to examples/cellular/T24.mid diff --git a/tests/T25.mid b/examples/cellular/T25.mid similarity index 100% rename from tests/T25.mid rename to examples/cellular/T25.mid diff --git a/tests/T26.mid b/examples/cellular/T26.mid similarity index 100% rename from tests/T26.mid rename to examples/cellular/T26.mid diff --git a/tests/T27.mid b/examples/cellular/T27.mid similarity index 100% rename from tests/T27.mid rename to examples/cellular/T27.mid diff --git a/tests/T28.mid b/examples/cellular/T28.mid similarity index 100% rename from tests/T28.mid rename to examples/cellular/T28.mid diff --git a/tests/T29.mid b/examples/cellular/T29.mid similarity index 100% rename from tests/T29.mid rename to examples/cellular/T29.mid diff --git a/tests/T3.mid b/examples/cellular/T3.mid similarity index 100% rename from tests/T3.mid rename to examples/cellular/T3.mid diff --git a/tests/T30.mid b/examples/cellular/T30.mid similarity index 100% rename from tests/T30.mid rename to examples/cellular/T30.mid diff --git a/tests/T31.mid b/examples/cellular/T31.mid similarity index 100% rename from tests/T31.mid rename to examples/cellular/T31.mid diff --git a/tests/T32.mid b/examples/cellular/T32.mid similarity index 100% rename from tests/T32.mid rename to examples/cellular/T32.mid diff --git a/tests/T33.mid b/examples/cellular/T33.mid similarity index 100% rename from tests/T33.mid rename to examples/cellular/T33.mid diff --git a/tests/T34.mid b/examples/cellular/T34.mid similarity index 100% rename from tests/T34.mid rename to examples/cellular/T34.mid diff --git a/tests/T35.mid b/examples/cellular/T35.mid similarity index 100% rename from tests/T35.mid rename to examples/cellular/T35.mid diff --git a/tests/T36.mid b/examples/cellular/T36.mid similarity index 100% rename from tests/T36.mid rename to examples/cellular/T36.mid diff --git a/tests/T37.mid b/examples/cellular/T37.mid similarity index 100% rename from tests/T37.mid rename to examples/cellular/T37.mid diff --git a/tests/T38.mid b/examples/cellular/T38.mid similarity index 100% rename from tests/T38.mid rename to examples/cellular/T38.mid diff --git a/tests/T39.mid b/examples/cellular/T39.mid similarity index 100% rename from tests/T39.mid rename to examples/cellular/T39.mid diff --git a/tests/T4.mid b/examples/cellular/T4.mid similarity index 100% rename from tests/T4.mid rename to examples/cellular/T4.mid diff --git a/tests/T40.mid b/examples/cellular/T40.mid similarity index 100% rename from tests/T40.mid rename to examples/cellular/T40.mid diff --git a/tests/T41.mid b/examples/cellular/T41.mid similarity index 100% rename from tests/T41.mid rename to examples/cellular/T41.mid diff --git a/tests/T42.mid b/examples/cellular/T42.mid similarity index 100% rename from tests/T42.mid rename to examples/cellular/T42.mid diff --git a/tests/T43.mid b/examples/cellular/T43.mid similarity index 100% rename from tests/T43.mid rename to examples/cellular/T43.mid diff --git a/tests/T44.mid b/examples/cellular/T44.mid similarity index 100% rename from tests/T44.mid rename to examples/cellular/T44.mid diff --git a/tests/T45.mid b/examples/cellular/T45.mid similarity index 100% rename from tests/T45.mid rename to examples/cellular/T45.mid diff --git a/tests/T46.mid b/examples/cellular/T46.mid similarity index 100% rename from tests/T46.mid rename to examples/cellular/T46.mid diff --git a/tests/T47.mid b/examples/cellular/T47.mid similarity index 100% rename from tests/T47.mid rename to examples/cellular/T47.mid diff --git a/tests/T48.mid b/examples/cellular/T48.mid similarity index 100% rename from tests/T48.mid rename to examples/cellular/T48.mid diff --git a/tests/T49.mid b/examples/cellular/T49.mid similarity index 100% rename from tests/T49.mid rename to examples/cellular/T49.mid diff --git a/tests/T5.mid b/examples/cellular/T5.mid similarity index 100% rename from tests/T5.mid rename to examples/cellular/T5.mid diff --git a/tests/T50.mid b/examples/cellular/T50.mid similarity index 100% rename from tests/T50.mid rename to examples/cellular/T50.mid diff --git a/tests/T51.mid b/examples/cellular/T51.mid similarity index 100% rename from tests/T51.mid rename to examples/cellular/T51.mid diff --git a/tests/T52.mid b/examples/cellular/T52.mid similarity index 100% rename from tests/T52.mid rename to examples/cellular/T52.mid diff --git a/tests/T53.mid b/examples/cellular/T53.mid similarity index 100% rename from tests/T53.mid rename to examples/cellular/T53.mid diff --git a/tests/T54.mid b/examples/cellular/T54.mid similarity index 100% rename from tests/T54.mid rename to examples/cellular/T54.mid diff --git a/tests/T55.mid b/examples/cellular/T55.mid similarity index 100% rename from tests/T55.mid rename to examples/cellular/T55.mid diff --git a/tests/T56.mid b/examples/cellular/T56.mid similarity index 100% rename from tests/T56.mid rename to examples/cellular/T56.mid diff --git a/tests/T57.mid b/examples/cellular/T57.mid similarity index 100% rename from tests/T57.mid rename to examples/cellular/T57.mid diff --git a/tests/T58.mid b/examples/cellular/T58.mid similarity index 100% rename from tests/T58.mid rename to examples/cellular/T58.mid diff --git a/tests/T59.mid b/examples/cellular/T59.mid similarity index 100% rename from tests/T59.mid rename to examples/cellular/T59.mid diff --git a/tests/T6.mid b/examples/cellular/T6.mid similarity index 100% rename from tests/T6.mid rename to examples/cellular/T6.mid diff --git a/tests/T60.mid b/examples/cellular/T60.mid similarity index 100% rename from tests/T60.mid rename to examples/cellular/T60.mid diff --git a/tests/T61.mid b/examples/cellular/T61.mid similarity index 100% rename from tests/T61.mid rename to examples/cellular/T61.mid diff --git a/tests/T62.mid b/examples/cellular/T62.mid similarity index 100% rename from tests/T62.mid rename to examples/cellular/T62.mid diff --git a/tests/T63.mid b/examples/cellular/T63.mid similarity index 100% rename from tests/T63.mid rename to examples/cellular/T63.mid diff --git a/tests/T64.mid b/examples/cellular/T64.mid similarity index 100% rename from tests/T64.mid rename to examples/cellular/T64.mid diff --git a/tests/T65.mid b/examples/cellular/T65.mid similarity index 100% rename from tests/T65.mid rename to examples/cellular/T65.mid diff --git a/tests/T66.mid b/examples/cellular/T66.mid similarity index 100% rename from tests/T66.mid rename to examples/cellular/T66.mid diff --git a/tests/T67.mid b/examples/cellular/T67.mid similarity index 100% rename from tests/T67.mid rename to examples/cellular/T67.mid diff --git a/tests/T68.mid b/examples/cellular/T68.mid similarity index 100% rename from tests/T68.mid rename to examples/cellular/T68.mid diff --git a/tests/T69.mid b/examples/cellular/T69.mid similarity index 100% rename from tests/T69.mid rename to examples/cellular/T69.mid diff --git a/tests/T7.mid b/examples/cellular/T7.mid similarity index 100% rename from tests/T7.mid rename to examples/cellular/T7.mid diff --git a/tests/T70.mid b/examples/cellular/T70.mid similarity index 100% rename from tests/T70.mid rename to examples/cellular/T70.mid diff --git a/tests/T71.mid b/examples/cellular/T71.mid similarity index 100% rename from tests/T71.mid rename to examples/cellular/T71.mid diff --git a/tests/T72.mid b/examples/cellular/T72.mid similarity index 100% rename from tests/T72.mid rename to examples/cellular/T72.mid diff --git a/tests/T73.mid b/examples/cellular/T73.mid similarity index 100% rename from tests/T73.mid rename to examples/cellular/T73.mid diff --git a/tests/T74.mid b/examples/cellular/T74.mid similarity index 100% rename from tests/T74.mid rename to examples/cellular/T74.mid diff --git a/tests/T75.mid b/examples/cellular/T75.mid similarity index 100% rename from tests/T75.mid rename to examples/cellular/T75.mid diff --git a/tests/T76.mid b/examples/cellular/T76.mid similarity index 100% rename from tests/T76.mid rename to examples/cellular/T76.mid diff --git a/tests/T77.mid b/examples/cellular/T77.mid similarity index 100% rename from tests/T77.mid rename to examples/cellular/T77.mid diff --git a/tests/T78.mid b/examples/cellular/T78.mid similarity index 100% rename from tests/T78.mid rename to examples/cellular/T78.mid diff --git a/tests/T79.mid b/examples/cellular/T79.mid similarity index 100% rename from tests/T79.mid rename to examples/cellular/T79.mid diff --git a/tests/T8.mid b/examples/cellular/T8.mid similarity index 100% rename from tests/T8.mid rename to examples/cellular/T8.mid diff --git a/tests/T80.mid b/examples/cellular/T80.mid similarity index 100% rename from tests/T80.mid rename to examples/cellular/T80.mid diff --git a/tests/T81.mid b/examples/cellular/T81.mid similarity index 100% rename from tests/T81.mid rename to examples/cellular/T81.mid diff --git a/tests/T82.mid b/examples/cellular/T82.mid similarity index 100% rename from tests/T82.mid rename to examples/cellular/T82.mid diff --git a/tests/T83.mid b/examples/cellular/T83.mid similarity index 100% rename from tests/T83.mid rename to examples/cellular/T83.mid diff --git a/tests/T84.mid b/examples/cellular/T84.mid similarity index 100% rename from tests/T84.mid rename to examples/cellular/T84.mid diff --git a/tests/T85.mid b/examples/cellular/T85.mid similarity index 100% rename from tests/T85.mid rename to examples/cellular/T85.mid diff --git a/tests/T86.mid b/examples/cellular/T86.mid similarity index 100% rename from tests/T86.mid rename to examples/cellular/T86.mid diff --git a/tests/T87.mid b/examples/cellular/T87.mid similarity index 100% rename from tests/T87.mid rename to examples/cellular/T87.mid diff --git a/tests/T88.mid b/examples/cellular/T88.mid similarity index 100% rename from tests/T88.mid rename to examples/cellular/T88.mid diff --git a/tests/T89.mid b/examples/cellular/T89.mid similarity index 100% rename from tests/T89.mid rename to examples/cellular/T89.mid diff --git a/tests/T9.mid b/examples/cellular/T9.mid similarity index 100% rename from tests/T9.mid rename to examples/cellular/T9.mid diff --git a/tests/T90.mid b/examples/cellular/T90.mid similarity index 100% rename from tests/T90.mid rename to examples/cellular/T90.mid diff --git a/tests/T91.mid b/examples/cellular/T91.mid similarity index 100% rename from tests/T91.mid rename to examples/cellular/T91.mid diff --git a/tests/T92.mid b/examples/cellular/T92.mid similarity index 100% rename from tests/T92.mid rename to examples/cellular/T92.mid diff --git a/tests/T93.mid b/examples/cellular/T93.mid similarity index 100% rename from tests/T93.mid rename to examples/cellular/T93.mid diff --git a/tests/T94.mid b/examples/cellular/T94.mid similarity index 100% rename from tests/T94.mid rename to examples/cellular/T94.mid diff --git a/tests/T95.mid b/examples/cellular/T95.mid similarity index 100% rename from tests/T95.mid rename to examples/cellular/T95.mid diff --git a/tests/T96.mid b/examples/cellular/T96.mid similarity index 100% rename from tests/T96.mid rename to examples/cellular/T96.mid diff --git a/playpen/examples/image_to_score/20180827_212842-1.png b/examples/image_to_score/20180827_212842-1.png similarity index 100% rename from playpen/examples/image_to_score/20180827_212842-1.png rename to examples/image_to_score/20180827_212842-1.png diff --git a/playpen/examples/image_to_score/image_to_score.cpp b/examples/image_to_score/image_to_score.cpp similarity index 100% rename from playpen/examples/image_to_score/image_to_score.cpp rename to examples/image_to_score/image_to_score.cpp diff --git a/playpen/examples/message/csound_loader.js b/examples/message/csound_loader.js similarity index 100% rename from playpen/examples/message/csound_loader.js rename to examples/message/csound_loader.js diff --git a/playpen/examples/message/message.html b/examples/message/message.html similarity index 100% rename from playpen/examples/message/message.html rename to examples/message/message.html diff --git a/CsoundAC/music21_csoundac.py b/examples/music21_csoundac.py similarity index 100% rename from CsoundAC/music21_csoundac.py rename to examples/music21_csoundac.py diff --git a/CsoundAC/csoundac-gamelan.py b/examples/musx/csoundac-gamelan.py similarity index 100% rename from CsoundAC/csoundac-gamelan.py rename to examples/musx/csoundac-gamelan.py diff --git a/CsoundAC/musx-csound-demo.py b/examples/musx/musx-csound-demo.py similarity index 100% rename from CsoundAC/musx-csound-demo.py rename to examples/musx/musx-csound-demo.py diff --git a/CsoundAC/musx-csound-gamelan.py b/examples/musx/musx-csound-gamelan.py similarity index 100% rename from CsoundAC/musx-csound-gamelan.py rename to examples/musx/musx-csound-gamelan.py diff --git a/CsoundAC/musx_csound.py b/examples/musx/musx_csound.py similarity index 100% rename from CsoundAC/musx_csound.py rename to examples/musx/musx_csound.py diff --git a/CsoundAC/musx_csoundac.py b/examples/musx/musx_csoundac.py similarity index 100% rename from CsoundAC/musx_csoundac.py rename to examples/musx/musx_csoundac.py diff --git a/examples/oblivion/oblivion.csd b/examples/oblivion/oblivion.csd new file mode 100644 index 0000000000..8814f6bf68 --- /dev/null +++ b/examples/oblivion/oblivion.csd @@ -0,0 +1,1609 @@ + + +"Oblivion,"" by Astor Piazzola +Arranged for Csound by Michael Gogins + + +-+msg_color=0 -odac -m195 -d + + + +sr = 48000 +ksmps = 128 +nchnls = 2 +0dbfs = 1 + +gi_ampmidicurve_dynamic_range init .375 +gi_ampmidicurve_exponent init 5 + +prealloc "ZakianFlute", 4 +prealloc "Guitar", 4 +prealloc "Harpsichord", 4 +prealloc "YiString", 4 +prealloc "Bower", 4 + +connect "Guitar", "outleft", "ReverbSC", "inleft" +connect "Guitar", "outleft", "ReverbSC", "inleft" +connect "ZakianFlute", "outleft", "ReverbSC", "inleft" +connect "ZakianFlute", "outleft", "ReverbSC", "inleft" +connect "Harpsichord", "outleft", "ReverbSC", "inleft" +connect "Harpsichord", "outright", "ReverbSC", "inright" +connect "YiString", "outleft", "ReverbSC", "inleft" +connect "YiString", "outright", "ReverbSC", "inright" +connect "Bower", "outleft", "ReverbSC", "inleft" +connect "Bower", "outright", "ReverbSC", "inright" +connect "ReverbSC", "outleft", "MasterOutput", "inleft" +connect "ReverbSC", "outright", "MasterOutput", "inright" + +alwayson "ReverbSC" +alwayson "MasterOutput" + +gk_overlap init .0125 + +gk_ZakianFlute_level init -4 +gk_ZakianFlute_pan init (2 / 7 - .5) +gi_ZakianFLute_seed init .5 +gif2 ftgen 0, 0, 16, -2, 40, 40, 80, 160, 320, 640, 1280, 2560, 5120, 10240, 10240 +gif26 ftgen 0, 0, 65536, -10, 2000, 489, 74, 219, 125, 9, 33, 5, 5 +gif27 ftgen 0, 0, 65536, -10, 2729, 1926, 346, 662, 537, 110, 61, 29, 7 +gif28 ftgen 0, 0, 65536, -10, 2558, 2012, 390, 361, 534, 139, 53, 22, 10, 13, 10 +gif29 ftgen 0, 0, 65536, -10, 12318, 8844, 1841, 1636, 256, 150, 60, 46, 11 +gif30 ftgen 0, 0, 65536, -10, 1229, 16, 34, 57, 32 +gif31 ftgen 0, 0, 65536, -10, 163, 31, 1, 50, 31 +gif32 ftgen 0, 0, 65536, -10, 4128, 883, 354, 79, 59, 23 +gif33 ftgen 0, 0, 65536, -10, 1924, 930, 251, 50, 25, 14 +gif34 ftgen 0, 0, 65536, -10, 94, 6, 22, 8 +gif35 ftgen 0, 0, 65536, -10, 2661, 87, 33, 18 +gif36 ftgen 0, 0, 65536, -10, 174, 12 +gif37 ftgen 0, 0, 65536, -10, 314, 13 +giwtsin ftgen 0, 0, 65536, 10, 1 +instr ZakianFlute +; Author: Lee Zakian +; Adapted by: Michael Gogins +if p3 == -1 goto indefinite +goto non_indefinite +indefinite: + p3 = 1000000 +non_indefinite: +i_instrument = p1 +i_time = p2 +i_duration = p3 +i_midi_key = p4 +i_midi_velocity = p5 +k_space_front_to_back = p6 +k_space_left_to_right = p1/6 +k_space_bottom_to_top = p8 +i_phase = p9 +i_overall_amps = 65 +i_amplitude ampmidicurve i_midi_velocity, gi_ampmidicurve_dynamic_range, gi_ampmidicurve_exponent +k_gain = ampdb(gk_ZakianFlute_level) +iattack = .002 +isustain = p3 +irelease = .3 +xtratim iattack + isustain + irelease +iHz = cpsmidinn(i_midi_key) +kHz = k(iHz) +aenvelope transeg 1.0, 20.0, -10.0, 0.05 +ip3 = (p3 < 3.0 ? p3 : 3.0) +; parameters +; p4 overall amplitude scaling factor +ip4 init i_amplitude +; p5 pitch in Hertz (normal pitch range: C4-C7) +ip5 init iHz +; p6 percent vibrato depth, recommended values in range [-1., +1.] +ip6 init 0.5 +; 0.0 -> no vibrato +; +1. -> 1% vibrato depth, where vibrato rate increases slightly +; -1. -> 1% vibrato depth, where vibrato rate decreases slightly +; p7 attack time in seconds +; recommended value: .12 for slurred notes, .06 for tongued notes +; (.03 for short notes) +ip7 init .08 +; p8 decay time in seconds +; recommended value: .1 (.05 for short notes) +ip8 init .08 +; p9 overall brightness / filter cutoff factor +; 1 -> least bright / minimum filter cutoff frequency (40 Hz) +; 9 -> brightest / maximum filter cutoff frequency (10,240Hz) +ip9 init 5 +; initial variables +iampscale = ip4 ; overall amplitude scaling factor +ifreq = ip5 ; pitch in Hertz +ivibdepth = abs(ip6*ifreq/100.0) ; vibrato depth relative to fundamental frequency +iattack = ip7 * (1.1 - .2*gi_ZakianFLute_seed) ; attack time with up to +-10% random deviation +gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) ; reset gi_ZakianFLute_seed +idecay = ip8 * (1.1 - .2*gi_ZakianFLute_seed) ; decay time with up to +-10% random deviation +gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) +ifiltcut tablei ip9, gif2 ; lowpass filter cutoff frequency +iattack = (iattack < 6/kr ? 6/kr : iattack) ; minimal attack length +idecay = (idecay < 6/kr ? 6/kr : idecay) ; minimal decay length +isustain = p3 - iattack - idecay +p3 = (isustain < 5/kr ? iattack+idecay+5/kr : p3) ; minimal sustain length +isustain = (isustain < 5/kr ? 5/kr : isustain) +iatt = iattack/6 +isus = isustain/4 +idec = idecay/6 +iphase = gi_ZakianFLute_seed ; use same phase for all wavetables +gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) +; vibrato block +; kvibdepth linseg .1, .8*p3, 1, .2*p3, .7 +kvibdepth linseg .1, .8*ip3, 1, isustain, 1, .2*ip3, .7 +kvibdepth = kvibdepth* ivibdepth ; vibrato depth +kvibdepthr randi .1*kvibdepth, 5, gi_ZakianFLute_seed ; up to 10% vibrato depth variation +gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) +kvibdepth = kvibdepth + kvibdepthr +ivibr1 = gi_ZakianFLute_seed ; vibrato rate +gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) +ivibr2 = gi_ZakianFLute_seed +gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) +if ip6 < 0 goto vibrato1 +kvibrate linseg 2.5+ivibr1, p3, 4.5+ivibr2 ; if p6 positive vibrato gets faster + goto vibrato2 +vibrato1: +ivibr3 = gi_ZakianFLute_seed +gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) +kvibrate linseg 3.5+ivibr1, .1, 4.5+ivibr2, p3-.1, 2.5+ivibr3 ; if p6 negative vibrato gets slower +vibrato2: +kvibrater randi .1*kvibrate, 5, gi_ZakianFLute_seed ; up to 10% vibrato rate variation +gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) +kvibrate = kvibrate + kvibrater +kvib oscili kvibdepth, kvibrate, giwtsin +ifdev1 = -.03 * gi_ZakianFLute_seed ; frequency deviation +gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) +ifdev2 = .003 * gi_ZakianFLute_seed +gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) +ifdev3 = -.0015 * gi_ZakianFLute_seed +gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) +ifdev4 = .012 * gi_ZakianFLute_seed +gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) +kfreqr linseg ifdev1, iattack, ifdev2, isustain, ifdev3, idecay, ifdev4 +kfreq = kHz * (1 + kfreqr) + kvib +if ifreq < 427.28 goto range1 ; (cpspch(8.08) + cpspch(8.09))/2 +if ifreq < 608.22 goto range2 ; (cpspch(9.02) + cpspch(9.03))/2 +if ifreq < 1013.7 goto range3 ; (cpspch(9.11) + cpspch(10.00))/2 +goto range4 +; wavetable amplitude envelopes +range1: ; for low range tones +kamp1 linseg 0, iatt, 0.002, iatt, 0.045, iatt, 0.146, iatt, \ +0.272, iatt, 0.072, iatt, 0.043, isus, 0.230, isus, 0.000, isus, \ +0.118, isus, 0.923, idec, 1.191, idec, 0.794, idec, 0.418, idec, \ +0.172, idec, 0.053, idec, 0 +kamp2 linseg 0, iatt, 0.009, iatt, 0.022, iatt, -0.049, iatt, \ +-0.120, iatt, 0.297, iatt, 1.890, isus, 1.543, isus, 0.000, isus, \ +0.546, isus, 0.690, idec, -0.318, idec, -0.326, idec, -0.116, idec, \ +-0.035, idec, -0.020, idec, 0 +kamp3 linseg 0, iatt, 0.005, iatt, -0.026, iatt, 0.023, iatt, \ +0.133, iatt, 0.060, iatt, -1.245, isus, -0.760, isus, 1.000, isus, \ +0.360, isus, -0.526, idec, 0.165, idec, 0.184, idec, 0.060, idec, \ +0.010, idec, 0.013, idec, 0 +iwt1 = gif26 ; wavetable numbers +iwt2 = gif27 +iwt3 = gif28 +inorm = 3949 +goto end +range2: ; for low mid-range tones +kamp1 linseg 0, iatt, 0.000, iatt, -0.005, iatt, 0.000, iatt, \ +0.030, iatt, 0.198, iatt, 0.664, isus, 1.451, isus, 1.782, isus, \ +1.316, isus, 0.817, idec, 0.284, idec, 0.171, idec, 0.082, idec, \ +0.037, idec, 0.012, idec, 0 +kamp2 linseg 0, iatt, 0.000, iatt, 0.320, iatt, 0.882, iatt, \ +1.863, iatt, 4.175, iatt, 4.355, isus, -5.329, isus, -8.303, isus, \ +-1.480, isus, -0.472, idec, 1.819, idec, -0.135, idec, -0.082, idec, \ +-0.170, idec, -0.065, idec, 0 +kamp3 linseg 0, iatt, 1.000, iatt, 0.520, iatt, -0.303, iatt, \ +0.059, iatt, -4.103, iatt, -6.784, isus, 7.006, isus, 11, isus, \ +12.495, isus, -0.562, idec, -4.946, idec, -0.587, idec, 0.440, idec, \ +0.174, idec, -0.027, idec, 0 +iwt1 = gif29 +iwt2 = gif30 +iwt3 = gif31 +inorm = 27668.2 +goto end +range3: ; for high mid-range tones +kamp1 linseg 0, iatt, 0.005, iatt, 0.000, iatt, -0.082, iatt, \ +0.36, iatt, 0.581, iatt, 0.416, isus, 1.073, isus, 0.000, isus, \ +0.356, isus, .86, idec, 0.532, idec, 0.162, idec, 0.076, idec, 0.064, \ +idec, 0.031, idec, 0 +kamp2 linseg 0, iatt, -0.005, iatt, 0.000, iatt, 0.205, iatt, \ +-0.284, iatt, -0.208, iatt, 0.326, isus, -0.401, isus, 1.540, isus, \ +0.589, isus, -0.486, idec, -0.016, idec, 0.141, idec, 0.105, idec, \ +-0.003, idec, -0.023, idec, 0 +kamp3 linseg 0, iatt, 0.722, iatt, 1.500, iatt, 3.697, iatt, \ +0.080, iatt, -2.327, iatt, -0.684, isus, -2.638, isus, 0.000, isus, \ +1.347, isus, 0.485, idec, -0.419, idec, -.700, idec, -0.278, idec, \ +0.167, idec, -0.059, idec, 0 +iwt1 = gif32 +iwt2 = gif33 +iwt3 = gif34 +inorm = 3775 +goto end +range4: ; for high range tones +kamp1 linseg 0, iatt, 0.000, iatt, 0.000, iatt, 0.211, iatt, \ +0.526, iatt, 0.989, iatt, 1.216, isus, 1.727, isus, 1.881, isus, \ +1.462, isus, 1.28, idec, 0.75, idec, 0.34, idec, 0.154, idec, 0.122, \ +idec, 0.028, idec, 0 +kamp2 linseg 0, iatt, 0.500, iatt, 0.000, iatt, 0.181, iatt, \ +0.859, iatt, -0.205, iatt, -0.430, isus, -0.725, isus, -0.544, isus, \ +-0.436, isus, -0.109, idec, -0.03, idec, -0.022, idec, -0.046, idec, \ +-0.071, idec, -0.019, idec, 0 +kamp3 linseg 0, iatt, 0.000, iatt, 1.000, iatt, 0.426, iatt, \ +0.222, iatt, 0.175, iatt, -0.153, isus, 0.355, isus, 0.175, isus, \ +0.16, isus, -0.246, idec, -0.045, idec, -0.072, idec, 0.057, idec, \ +-0.024, idec, 0.002, idec, 0 +iwt1 = gif35 +iwt2 = gif36 +iwt3 = gif37 +inorm = 4909.05 +goto end +end: +kampr1 randi .02*kamp1, 10, gi_ZakianFLute_seed ; up to 2% wavetable amplitude variation +gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) +kamp1 = kamp1 + kampr1 +kampr2 randi .02*kamp2, 10, gi_ZakianFLute_seed ; up to 2% wavetable amplitude variation +gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) +kamp2 = kamp2 + kampr2 +kampr3 randi .02*kamp3, 10, gi_ZakianFLute_seed ; up to 2% wavetable amplitude variation +gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) +kamp3 = kamp3 + kampr3 +awt1 poscil kamp1, kfreq, iwt1, iphase ; wavetable lookup +awt2 poscil kamp2, kfreq, iwt2, iphase +awt3 poscil kamp3, kfreq, iwt3, iphase +asig = awt1 + awt2 + awt3 +asig = asig*(iampscale/inorm) +kcut linseg 0, iattack, ifiltcut, isustain, ifiltcut, idecay, 0 ; lowpass filter for brightness control +afilt tone asig, kcut +a_signal balance afilt, asig +i_attack = .002 +i_sustain = p3 +i_release = 0.01 +xtratim i_attack + i_sustain + i_release +a_declicking linsegr 0, i_attack, 1, i_sustain, 1, i_release, 0 +a_signal = a_signal * i_amplitude * a_declicking * k_gain +#ifdef USE_SPATIALIZATION +a_spatial_reverb_send init 0 +a_bsignal[] init 16 +a_bsignal, a_spatial_reverb_send Spatialize a_signal, k_space_front_to_back, k_space_left_to_right, k_space_bottom_to_top +outletv "outbformat", a_bsignal +outleta "out", a_spatial_reverb_send +#else +a_out_left, a_out_right pan2 a_signal, p1/6 +outleta "outleft", a_out_left +outleta "outright", a_out_right +#endif +prints "ZakianFlute i %9.4f t %9.4f d %9.4f k %9.4f v %9.4f p %9.4f #%3d\n", p1, p2, p3, p4, p5, p1/6, active(p1) +endin + +gk_Guitar_level init 8 +instr Guitar +; Michael Gogins +if p3 == -1 goto indefinite +goto non_indefinite +indefinite: + p3 = 1000000 +non_indefinite: +i_instrument = p1 +i_time = p2 +i_duration = p3 +i_midi_key = p4 +i_midi_velocity = p5 +k_space_front_to_back = p6 +k_space_left_to_right = p1/6 +k_space_bottom_to_top = p8 +i_phase = p9 +i_frequency = cpsmidinn(i_midi_key) +i_amplitude ampmidicurve i_midi_velocity, gi_ampmidicurve_dynamic_range, gi_ampmidicurve_exponent +k_gain = ampdb(gk_Guitar_level) +acomp pluck i_amplitude, 440.0, 440.0, 0, 1, .1 +i_frequency2 = i_frequency / 2.0 +kHz = k(i_frequency) +iattack = 0.004 +isustain = p3 +irelease = 0.05 +p3 = iattack + isustain + irelease +asigcomp pluck 1.0, 440, 440, 0, 1 +asig pluck 1.0, i_frequency, i_frequency, 0, 1 +af1 reson asig, 110, 80 +af2 reson asig, 220, 100 +af3 reson asig, 440, 80 +aout balance 0.6 * af1 + af2 + 0.6 * af3 + 0.4 * asig, asigcomp +aexp expseg 1.0, iattack, 2.0, isustain, 1.0, irelease, 1.0 +aenv = aexp - 1.0 +a_signal = aout * aenv +a_declicking linsegr 0, iattack, 1, isustain, 1, irelease, 0 +a_signal = a_signal * i_amplitude * a_declicking * k_gain +#ifdef USE_SPATIALIZATION +a_spatial_reverb_send init 0 +a_bsignal[] init 16 +a_bsignal, a_spatial_reverb_send Spatialize a_signal, k_space_front_to_back, k_space_left_to_right, k_space_bottom_to_top +outletv "outbformat", a_bsignal +outleta "out", a_spatial_reverb_send +#else +a_out_left, a_out_right pan2 a_signal, p1/6 +outleta "outleft", a_out_left +outleta "outright", a_out_right +#endif +prints "Guitar i %9.4f t %9.4f d %9.4f k %9.4f v %9.4f p %9.4f #%3d\n", p1, p2, p3, p4, p5, p1/6, active(p1) +endin + +gk_YiString_level init 6 +gk_YiString_reverb_send init .5 +gk_YiString_chorus_send init .5 +gi_YiString_overlap init .1 +instr YiString + ////////////////////////////////////////////// + // Original by Steven Yi. + // Adapted by Michael Gogins. + ////////////////////////////////////////////// +if p3 == -1 goto indefinite +goto non_indefinite +indefinite: + p3 = 1000000 +non_indefinite: +i_instrument = p1 +i_time = p2 +i_duration = p3 +i_midi_key = p4 +i_midi_velocity = p5 +k_space_front_to_back = p6 +k_space_left_to_right = p1/6 +k_space_bottom_to_top = p8 +i_phase = p9 +i_frequency = cpsmidinn(i_midi_key) +i_amplitude ampmidicurve i_midi_velocity, gi_ampmidicurve_dynamic_range, gi_ampmidicurve_exponent +k_gain = ampdb(gk_YiString_level) +iattack = gi_YiString_overlap +isustain = p3 +idecay = gi_YiString_overlap +p3 = iattack + isustain + idecay +aenvelope transeg 0.0, iattack / 2.0, 1.5, i_amplitude / 2.0, iattack / 2.0, -1.5, i_amplitude, isustain, 0.0, i_amplitude, idecay / 2.0, 1.5, i_amplitude / 2.0, idecay / 2.0, -1.5, 0 +;ampenv = madsr:a(1, 0.1, 0.95, 0.5) +asignal = vco2(1, i_frequency) +asignal = moogladder(asignal, 6000, 0.1) +a_signal = asignal * aenvelope +i_attack = .002 +i_release = 0.01 +i_sustain = p3 - (i_attack + i_release) +a_declicking linsegr 0, i_attack, 1, i_sustain, 1, i_release, 0 +a_signal = a_signal * i_amplitude * a_declicking * k_gain +#ifdef USE_SPATIALIZATION +a_spatial_reverb_send init 0 +a_bsignal[] init 16 +a_bsignal, a_spatial_reverb_send Spatialize a_signal, k_space_front_to_back, k_space_left_to_right, k_space_bottom_to_top +outletv "outbformat", a_bsignal +outleta "out", a_spatial_reverb_send +#else +a_out_left, a_out_right pan2 a_signal, p1/6 +outleta "outleft", a_out_left * gk_YiString_reverb_send +outleta "outright", a_out_right * gk_YiString_reverb_send +outleta "chorusleft", a_out_left * gk_YiString_chorus_send +outleta "chorusright", a_out_right * gk_YiString_chorus_send +;printks "YiString %9.4f %9.4f\n", 0.5, a_out_left, a_out_right +#endif +prints "YiString i %9.4f t %9.4f d %9.4f k %9.4f v %9.4f p %9.4f #%3d\n", p1, p2, p3, p4, p5, p1/6, active(p1) +endin + +gk_Bower_level init 20 +gk_Bower_pressure init 4.2 +gisine ftgen 0,0,65536,10,1 +instr Bower +if p3 == -1 goto indefinite +goto non_indefinite +indefinite: + p3 = 1000000 +non_indefinite: +insno = p1 +istart = p2 +iduration = p3 +ikey = p4 +ivelocity = p5 +iphase = p6 +ipan = (4 / 7 - .5) +iamp ampmidicurve ivelocity, gi_ampmidicurve_dynamic_range, gi_ampmidicurve_exponent +iattack = i(gk_overlap) +idecay = i(gk_overlap) +isustain = p3 - i(gk_overlap) +p3 = iattack + isustain + idecay +kenvelope transeg 0.0, iattack / 2.0, 1.5, iamp / 2.0, iattack / 2.0, -1.5, iamp, isustain, 0.0, iamp, idecay / 2.0, 1.5, iamp / 2.0, idecay / 2.0, -1.5, 0 +ihertz = cpsmidinn(ikey) +kamp = kenvelope +kfreq = ihertz +kpres = 0.25 +krat rspline 0.006,0.988,1,2 +kvibf = 4.5 +kvibamp = 0 +iminfreq = 30 +aSig wgbow kamp,kfreq,gk_Bower_pressure,krat,kvibf,kvibamp,gisine,iminfreq +aleft, aright pan2 aSig / 7, p1/6 +adamping linseg 0, 0.03, 1, p3 - 0.1, 1, 0.07, 0 +aleft = adamping * aleft +aright = adamping * aright +kgain = ampdb(gk_Bower_level) +outleta "outleft", aleft * kgain +outleta "outright", aright * kgain +prints "Bower i %9.4f t %9.4f d %9.4f k %9.4f v %9.4f p %9.4f #%3d\n", p1, p2, p3, p4, p5, p1/6, active(p1) +endin + +gk_Harpsichord_level init 0 +gk_Harpsichord_pick init .275 +gk_Harpsichord_reflection init .75 +gk_Harpsichord_pluck init .5 +giharptable ftgen 0, 0, 65536, 7, -1, 1024, 1, 1024, -1 +instr Harpsichord +if p3 == -1 goto indefinite +goto non_indefinite +indefinite: + p3 = 1000000 +non_indefinite: +i_instrument = p1 +i_time = p2 +i_duration = p3 +i_midi_key = p4 +i_midi_velocity = p5 +k_space_front_to_back = p6 +k_space_left_to_right = .2 +k_space_bottom_to_top = p8 +i_phase = p9 +i_amplitude ampmidicurve i_midi_velocity, gi_ampmidicurve_dynamic_range, gi_ampmidicurve_exponent +k_gain = ampdb(gk_Harpsichord_level) +iHz = cpsmidinn(i_midi_key) +kHz = k(iHz) +aenvelope transeg 1.0, 20.0, -10.0, 0.05 +k_amplitude = 1 +apluck pluck 1, kHz, iHz, 0, 1 +aharp poscil 1, kHz, giharptable +aharp2 balance apluck, aharp +a_signal = (apluck + aharp2) +i_attack = .002 +i_sustain = p3 +i_release = 0.01 +p3 = i_attack + i_sustain + i_release +a_declicking linsegr 0, i_attack, 1, i_sustain, 1, i_release, 0 +a_signal = a_signal * i_amplitude * a_declicking * k_gain +#ifdef USE_SPATIALIZATION +a_spatial_reverb_send init 0 +a_bsignal[] init 16 +a_bsignal, a_spatial_reverb_send Spatialize a_signal, k_space_front_to_back, k_space_left_to_right, k_space_bottom_to_top +outletv "outbformat", a_bsignal +outleta "out", a_spatial_reverb_send +#else +a_out_left, a_out_right pan2 a_signal, p1/6 +outleta "outleft", a_out_left +outleta "outright", a_out_right +#endif +; printks "Harpsichord %9.4f %9.4f\n", 0.5, a_out_left, a_out_right +prints "Harpsichord i %9.4f t %9.4f d %9.4f k %9.4f v %9.4f p %9.4f #%3d\n", p1, p2, p3, p4, p5, p1/6, active(p1) +kpbend pchbend 2 +printks2 "pchbend %9.4f\n", kpbend +kmodw midictrl 1 +printks2 "kmodw %9.4f\n", kmodw +kctl6 midictrl 6 +printks2 "kctl6 %9.4f\n", kctl6 +kctl4 midictrl 4 +printks2 "kctl4 %9.4f\n", kctl4 +kctl5 midictrl 5 +printks2 "kctl5 %9.4f\n", kctl5 +kafter aftouch 1 +printks2 "kafter %9.4f\n", kafter + +endin + +gk_Reverb_feedback init 0.85 +gi_Reverb_delay_modulation init 0.05 +gk_Reverb_frequency_cutoff init 15000 +instr ReverbSC +aleftout init 0 +arightout init 0 +aleft inleta "inleft" +aright inleta "inright" +; aoutL, aoutR reverbsc ainL, ainR, kfblvl, kfco[, israte[, ipitchm[, iskip]]] +aleftout, arightout reverbsc aleft, aright, gk_Reverb_feedback, gk_Reverb_frequency_cutoff, sr, gi_Reverb_delay_modulation +outleta "outleft", aleftout +outleta "outright", arightout +prints "ReverbSC i %9.4f t %9.4f d %9.4f k %9.4f v %9.4f p %9.4f #%3d\\n", p1, p2, p3, p4, p5, p1/6, active(p1) +endin + +gk_MasterOutput_level init -15 +gS_MasterOutput_filename init "" +instr MasterOutput +aleft inleta "inleft" +aright inleta "inright" +k_gain = ampdb(gk_MasterOutput_level) +printks2 "Master gain: %f\n", k_gain +iamp init 1 +iattack init .01 +idecay init 10 +isustain = 2400 - (iattack + idecay) +aenvelope transeg 0.0, iattack / 2.0, 1.5, iamp / 2.0, iattack / 2.0, -1.5, iamp, isustain, 0.0, iamp, idecay / 2.0, 1.5, iamp / 2.0, idecay / 2.0, -1.5, 0 +aleft butterlp aleft, 18000 +aright butterlp aright, 18000 +outs aleft * k_gain * aenvelope, aright * k_gain * aenvelope +; We want something that will play on my phone. +i_amplitude_adjustment = ampdbfs(-3) / 32767 +i_filename_length strlen gS_MasterOutput_filename +if i_filename_length > 0 goto has_filename +goto non_has_filename +has_filename: +prints sprintf("Output filename: %s\n", gS_MasterOutput_filename) +fout gS_MasterOutput_filename, 18, aleft * i_amplitude_adjustment, aright * i_amplitude_adjustment +non_has_filename: +prints "MasterOutput i %9.4f t %9.4f d %9.4f k %9.4f v %9.4f p %9.4f #%3d\n", p1, p2, p3, p4, p5, p1/6, active(p1) +kstatus, kchan, kdata1, kdata2 midiin +;printf " midi in s %4d c %4d %4d %4d\n", kdata2, kstatus, kchan, kdata1, kdata2 +endin + + + + +; track 1 + +t 0.0000 76.0 +i 1 1.5000 0.4979 60 49 +i 1 2.0000 0.4979 62 49 +i 1 2.5000 0.4979 63 49 +i 1 3.0000 0.9979 65 49 +i 1 5.5000 0.4979 60 49 +i 1 6.0000 0.4979 62 49 +i 1 6.5000 0.4979 63 49 +i 1 7.0000 0.9979 65 49 +i 1 9.5000 0.4979 60 49 +i 1 10.0000 0.4979 62 49 +i 1 10.5000 0.4979 63 49 +i 1 11.0000 0.9979 65 49 +i 1 13.5000 0.4979 60 49 +i 1 14.0000 0.4979 62 49 +i 1 14.5000 0.4979 63 49 +i 1 15.0000 0.9979 65 49 +i 1 17.5000 0.4979 60 49 +i 1 18.0000 0.4979 62 49 +i 1 18.5000 0.4979 63 49 +i 1 19.0000 0.9979 65 49 +i 1 21.5000 0.4979 60 49 +i 1 22.0000 0.4979 62 49 +i 1 22.5000 0.4979 63 49 +i 1 23.0000 0.9979 65 49 +i 1 25.5000 0.4979 60 49 +i 1 26.0000 0.4979 62 49 +i 1 26.5000 0.4979 63 49 +i 1 27.0000 0.9979 65 49 +i 1 29.5000 0.4979 60 49 +i 1 30.0000 0.4979 62 49 +i 1 30.5000 0.4979 63 49 +i 1 31.0000 0.9979 65 49 +i 1 32.0000 1.9979 68 49 +i 1 34.0000 1.9979 68 49 +i 1 36.0000 1.9979 67 49 +i 1 38.0000 1.9979 67 49 +i 1 40.0000 1.9979 65 49 +i 1 42.0000 1.9979 66 49 +i 1 44.0000 1.9979 67 49 +i 1 46.0000 0.4979 67 49 +i 1 46.5000 0.4979 67 49 +i 1 47.0000 0.2479 68 49 +i 1 47.2500 0.2479 67 49 +i 1 47.5000 0.2479 66 49 +i 1 47.7500 0.2479 67 49 +i 1 48.0000 4.6646 79 49 +i 1 52.6667 0.6646 77 49 +i 1 53.3333 0.6646 75 49 +i 1 54.0000 0.7479 74 49 +i 1 54.7500 0.2479 72 49 +i 1 55.0000 0.2479 74 49 +i 1 55.2500 0.2479 75 49 +i 1 55.5000 0.2479 74 49 +i 1 55.7500 0.2479 72 49 +i 1 56.0000 4.9979 75 49 +i 1 61.0000 0.4979 74 49 +i 1 61.5000 0.4979 72 49 +i 1 62.0000 1.4979 70 49 +i 1 63.5000 0.4979 68 49 +i 1 64.0000 2.9979 72 49 +i 1 67.0000 0.2479 70 49 +i 1 67.2500 0.2479 72 49 +i 1 67.5000 0.2479 70 49 +i 1 67.7500 0.2479 68 49 +i 1 68.0000 1.4979 70 49 +i 1 69.5000 0.4979 73 49 +i 1 70.0000 0.4979 73 49 +i 1 70.5000 0.9979 72 49 +i 1 71.5000 0.2479 70 49 +i 1 71.7500 0.2479 70 49 +i 1 72.0000 1.4979 70 49 +i 1 73.5000 0.2479 68 49 +i 1 73.7500 0.2479 70 49 +i 1 74.0000 1.9979 68 49 +i 1 76.0000 1.9979 68 49 +i 1 79.2500 0.2479 72 96 +i 1 79.5000 0.2479 77 96 +i 1 79.7500 0.2479 79 96 +i 1 80.0000 0.4979 79 96 +i 1 80.5000 0.9979 80 96 +i 1 81.5000 0.2479 79 96 +i 1 81.7500 0.2479 77 96 +i 1 82.0000 1.9979 80 96 +i 1 84.5000 0.4979 79 96 +i 1 85.0000 0.2479 82 96 +i 1 85.2500 0.2479 80 96 +i 1 85.5000 0.2479 79 96 +i 1 85.7500 0.2479 77 96 +i 1 86.0000 1.4979 77 96 +i 1 87.5000 0.2479 75 96 +i 1 87.7500 0.2479 77 96 +i 1 88.0000 0.2479 75 96 +i 1 88.2500 0.2479 72 96 +i 1 88.5000 0.4979 72 96 +i 1 89.0000 2.9979 72 96 +i 1 94.0000 0.7479 77 96 +i 1 94.7500 0.7479 75 96 +i 1 95.5000 0.2479 74 96 +i 1 95.7500 0.2479 72 96 +i 1 96.0000 2.9979 66 96 +i 1 99.0000 0.4979 66 96 +i 1 99.5000 0.4979 66 96 +i 1 100.0000 1.9979 67 96 +i 1 102.0000 0.4979 68 96 +i 1 102.5000 0.9979 67 96 +i 1 103.5000 0.2479 66 96 +i 1 103.7500 0.2479 67 96 +i 1 104.0000 5.9979 72 96 +i 1 110.0000 0.4979 72 96 +i 1 110.5000 0.4979 79 96 +i 1 111.0000 0.4979 84 96 +i 1 111.5000 0.4979 86 96 +i 1 112.0000 2.9979 87 96 +i 1 115.0000 0.4979 84 96 +i 1 115.5000 0.4979 86 96 +i 1 116.0000 0.6646 87 96 +i 1 116.6667 0.6646 86 96 +i 1 117.3333 0.6646 89 96 +i 1 118.0000 0.9979 82 96 +i 1 119.0000 0.9979 80 96 +i 1 120.0000 0.1375 79 96 +i 1 120.1396 0.1375 80 96 +i 1 120.2812 0.1375 81 96 +i 1 120.4250 0.1375 82 96 +i 1 120.5646 0.1375 83 96 +i 1 120.7062 0.1375 84 96 +i 1 120.8500 0.1479 85 96 +i 1 121.0000 2.9979 86 96 +i 1 124.0000 0.6646 86 96 +i 1 124.6667 0.6646 84 96 +i 1 125.3333 0.6646 87 96 +i 1 126.0000 0.9979 80 96 +i 1 127.0000 0.9979 79 96 +i 1 128.0000 0.1375 77 96 +i 1 128.1396 0.1375 78 96 +i 1 128.2812 0.1375 79 96 +i 1 128.4250 0.1375 80 96 +i 1 128.5646 0.1375 81 96 +i 1 128.7062 0.1375 82 96 +i 1 128.8500 0.1479 83 96 +i 1 129.0000 2.9979 84 96 +i 1 132.0000 0.6646 84 96 +i 1 132.6667 0.6646 83 96 +i 1 133.3333 0.6646 86 96 +i 1 134.0000 0.9979 79 96 +i 1 135.0000 0.9979 77 96 +i 1 136.0000 1.4979 75 96 +i 1 137.5000 1.4979 77 96 +i 1 139.0000 0.9979 79 96 +i 1 140.0000 3.9979 79 96 +i 1 160.0000 3.9979 60 33 +i 1 164.0000 3.9979 65 33 +i 1 168.0000 1.4979 67 33 +i 1 169.5000 1.4979 68 33 +i 1 171.0000 0.9979 67 33 +i 1 172.0000 1.4979 70 33 +i 1 173.5000 1.4979 68 33 +i 1 175.0000 0.9979 67 33 +i 1 177.5000 0.4979 60 33 +i 1 178.0000 0.4979 62 33 +i 1 178.5000 0.4979 63 33 +i 1 179.0000 0.9979 65 33 +i 1 181.5000 0.4979 60 33 +i 1 182.0000 0.4979 62 33 +i 1 182.5000 0.4979 63 33 +i 1 183.0000 0.9979 65 33 +i 1 185.5000 0.4979 60 33 +i 1 186.0000 0.4979 62 33 +i 1 186.5000 0.4979 63 33 +i 1 187.0000 0.9979 65 33 +i 1 189.5000 0.4979 60 33 +i 1 190.0000 0.4979 62 33 +i 1 190.5000 0.4979 63 33 +i 1 191.0000 0.9979 65 33 +i 1 192.0000 1.9979 68 33 +i 1 194.0000 1.9979 68 33 +i 1 196.0000 1.9979 67 33 +i 1 198.0000 1.9979 67 33 +i 1 200.0000 1.9979 65 33 +i 1 202.0000 1.9979 66 33 +i 1 204.0000 2.9979 67 33 +i 1 207.2500 0.2479 67 49 +i 1 207.5000 0.2479 67 49 +i 1 207.7500 0.2479 68 49 +i 1 208.0000 0.4979 79 49 +i 1 208.5000 0.4979 79 49 +i 1 209.0000 2.9979 79 49 +i 1 212.0000 0.6646 79 49 +i 1 212.6667 0.6646 77 49 +i 1 213.3333 0.6646 75 49 +i 1 214.0000 0.7479 74 49 +i 1 214.7500 0.2479 72 49 +i 1 215.0000 0.2479 74 49 +i 1 215.2500 0.2479 72 49 +i 1 215.5000 0.2479 71 49 +i 1 215.7500 0.2479 72 49 +i 1 216.0000 0.4979 75 49 +i 1 216.5000 0.4979 75 49 +i 1 217.0000 2.9979 75 49 +i 1 220.5000 0.4979 74 49 +i 1 221.0000 0.2479 77 49 +i 1 221.2500 0.2479 75 49 +i 1 221.5000 0.2479 74 49 +i 1 221.7500 0.2479 72 49 +i 1 222.0000 0.4979 70 49 +i 1 222.5000 0.9979 68 49 +i 1 223.5000 0.2479 67 49 +i 1 223.7500 0.2479 68 49 +i 1 224.0000 0.4979 72 49 +i 1 224.5000 1.4979 72 49 +i 1 226.0000 0.4979 72 49 +i 1 226.5000 0.4979 70 49 +i 1 227.0000 0.4979 70 49 +i 1 227.5000 0.4979 70 49 +i 1 228.0000 0.4979 68 49 +i 1 228.5000 0.4979 67 49 +i 1 229.0000 0.9979 67 49 +i 1 230.0000 0.4979 65 49 +i 1 230.5000 0.9979 65 49 +i 1 231.5000 0.4979 67 49 +i 1 232.0000 0.4979 70 49 +i 1 232.5000 0.2479 68 49 +i 1 232.7500 0.2479 67 49 +i 1 233.0000 2.9979 68 49 +i 1 236.0000 1.9979 68 49 +i 1 239.2500 0.2479 72 49 +i 1 239.5000 0.2479 77 49 +i 1 239.7500 0.2479 79 49 +i 1 240.0000 1.4979 82 96 +i 1 241.5000 0.2479 80 96 +i 1 241.7500 0.2479 79 96 +i 1 242.0000 1.9979 80 96 +i 1 244.5000 0.4979 79 96 +i 1 245.0000 0.2479 82 96 +i 1 245.2500 0.2479 80 96 +i 1 245.5000 0.2479 79 96 +i 1 245.7500 0.2479 77 96 +i 1 246.0000 0.2479 79 96 +i 1 246.2500 0.2479 77 96 +i 1 246.5000 0.2479 75 96 +i 1 246.7500 0.2479 74 96 +i 1 247.0000 0.2479 72 96 +i 1 247.2500 0.2479 74 96 +i 1 247.5000 0.2479 75 96 +i 1 247.7500 0.2479 77 96 +i 1 248.0000 0.4979 79 96 +i 1 248.5000 0.4979 72 96 +i 1 249.0000 2.9979 72 96 +i 1 252.0000 1.9979 72 96 +i 1 254.0000 0.4979 77 96 +i 1 254.5000 0.9979 75 93 +i 1 255.5000 0.2479 74 86 +i 1 255.7500 0.2479 72 84 +i 1 256.0000 2.9979 78 82 +i 1 259.0000 0.4979 78 61 +i 1 259.5000 0.4979 78 58 +i 1 260.0000 2.9979 79 54 +i 1 263.0000 0.9979 91 33 +i 1 264.0000 3.9979 96 33 +i 1 268.0000 3.9979 96 33 +i 1 272.0000 3.9979 96 33 +i 1 276.0000 3.9979 96 33 +i 1 280.0000 0.0542 96 33 +i 1 280.0562 0.0542 95 33 +i 1 280.1146 0.0542 94 33 +i 1 280.1729 0.0542 93 33 +i 1 280.2312 0.0542 92 33 +i 1 280.2896 0.0542 91 33 +i 1 280.3500 0.0542 90 33 +i 1 280.4062 0.0542 89 33 +i 1 280.4646 0.0542 88 33 +i 1 280.5229 0.0542 87 33 +i 1 280.5813 0.0542 86 33 +i 1 280.6396 0.0542 85 33 +i 1 280.7000 0.0542 84 33 +i 1 280.7563 0.0542 83 33 +i 1 280.8146 0.0542 82 33 +i 1 280.8729 0.0542 81 33 +i 1 280.9313 0.0542 80 33 +i 1 280.9896 0.0542 79 33 +i 1 281.0500 0.0542 78 33 +i 1 281.1063 0.0542 77 33 +i 1 281.1646 0.0542 76 33 +i 1 281.2229 0.0542 75 33 +i 1 281.2813 0.0542 74 33 +i 1 281.3396 0.0542 73 33 +i 1 281.4000 0.0542 72 33 +i 1 281.4563 0.0542 71 33 +i 1 281.5146 0.0542 70 33 +i 1 281.5729 0.0542 69 33 +i 1 281.6313 0.0542 68 33 +i 1 281.6896 0.0542 67 33 +i 1 281.7500 0.0542 66 33 +i 1 281.8063 0.0542 65 33 +i 1 281.8646 0.0542 64 33 +i 1 281.9229 0.0708 63 33 +i 1 282.0000 0.1208 62 33 +i 1 282.1229 0.1208 62 33 +i 1 282.2479 0.1208 62 33 +i 1 282.3708 0.1208 62 33 +i 1 282.4958 0.1208 62 33 +i 1 282.6188 0.1208 62 33 +i 1 282.7438 0.1208 62 33 +i 1 282.8667 0.1208 62 33 +i 1 282.9917 0.1208 62 33 +i 1 283.1146 0.1208 62 33 +i 1 283.2396 0.1208 62 33 +i 1 283.3625 0.1208 62 33 +i 1 283.4875 0.1208 62 33 +i 1 283.6104 0.1208 62 33 +i 1 283.7354 0.1208 62 33 +i 1 283.8583 0.1208 62 33 + +; track 2 + +i 2 0.5000 0.4979 55 49 +i 2 1.0000 2.9979 56 49 +i 2 4.5000 0.4979 55 49 +i 2 5.0000 2.9979 56 49 +i 2 8.5000 0.4979 55 49 +i 2 9.0000 2.9979 56 49 +i 2 12.5000 0.4979 55 49 +i 2 13.0000 2.9979 56 49 +i 2 16.5000 0.4979 55 49 +i 2 17.0000 2.9979 56 49 +i 2 20.5000 0.4979 55 49 +i 2 21.0000 2.9979 56 49 +i 2 24.5000 0.4979 55 49 +i 2 25.0000 2.9979 56 49 +i 2 28.5000 0.4979 55 49 +i 2 29.0000 2.9979 56 49 +i 2 32.5000 0.4979 63 49 +i 2 33.0000 0.4979 62 49 +i 2 33.5000 0.4979 63 49 +i 2 34.5000 0.4979 63 49 +i 2 35.0000 0.9979 62 49 +i 2 36.5000 0.4979 62 49 +i 2 37.0000 0.4979 60 49 +i 2 37.5000 0.4979 62 49 +i 2 38.5000 0.4979 62 49 +i 2 39.0000 0.4979 60 49 +i 2 39.5000 0.4979 62 49 +i 2 40.5000 0.4979 62 49 +i 2 41.0000 0.4979 60 48 +i 2 41.5000 0.4979 62 47 +i 2 42.5000 0.4979 62 45 +i 2 43.0000 0.4979 60 43 +i 2 43.5000 0.4979 62 42 +i 2 44.5000 0.4979 60 40 +i 2 45.0000 0.4979 62 38 +i 2 45.5000 0.4979 59 37 +i 2 46.0000 0.9979 63 36 +i 2 47.0000 0.9979 62 33 +i 2 49.5000 0.4979 60 33 +i 2 50.0000 0.4979 62 33 +i 2 50.5000 0.4979 63 33 +i 2 51.0000 0.9979 65 33 +i 2 53.5000 0.4979 60 33 +i 2 54.0000 0.4979 62 33 +i 2 54.5000 0.4979 63 33 +i 2 55.0000 0.9979 65 33 +i 2 57.5000 0.4979 60 33 +i 2 58.0000 0.4979 62 33 +i 2 58.5000 0.4979 63 33 +i 2 59.0000 0.9979 65 33 +i 2 61.5000 0.4979 60 33 +i 2 62.0000 0.4979 62 33 +i 2 62.5000 0.4979 63 33 +i 2 63.0000 0.9979 65 33 +i 2 64.0000 0.9979 65 33 +i 2 65.0000 0.9979 67 48 +i 2 66.0000 0.9979 64 64 +i 2 67.0000 0.9979 65 80 +i 2 68.0000 1.9979 68 80 +i 2 70.0000 1.9979 67 80 +i 2 72.0000 0.9979 60 80 +i 2 73.0000 0.9979 62 80 +i 2 74.0000 0.9979 63 80 +i 2 75.0000 0.9979 65 80 +i 2 76.0000 1.4979 67 80 +i 2 77.5000 0.2479 65 80 +i 2 77.7500 0.2479 63 80 +i 2 78.0000 0.9979 62 80 +i 2 79.0000 0.9979 60 80 +i 2 80.0000 0.9979 65 80 +i 2 81.0000 1.9979 67 80 +i 2 83.0000 0.9979 65 80 +i 2 84.0000 0.9979 68 80 +i 2 85.0000 1.9979 67 80 +i 2 87.0000 0.9979 65 80 +i 2 88.0000 0.9979 63 80 +i 2 89.0000 1.9979 65 80 +i 2 91.0000 0.9979 63 80 +i 2 92.0000 0.9979 67 80 +i 2 93.0000 1.9979 65 80 +i 2 95.0000 0.9979 63 80 +i 2 96.0000 0.9979 62 80 +i 2 97.0000 1.9979 63 80 +i 2 99.0000 0.9979 62 80 +i 2 100.0000 0.9979 62 80 +i 2 101.0000 1.9979 63 80 +i 2 103.0000 0.9979 62 80 +i 2 104.0000 1.4979 67 80 +i 2 105.5000 1.4979 68 80 +i 2 107.0000 0.9979 67 80 +i 2 108.0000 1.4979 70 80 +i 2 109.5000 1.4979 68 80 +i 2 111.0000 0.9979 67 80 +i 2 112.0000 2.9979 72 96 +i 2 115.0000 0.4979 68 96 +i 2 115.5000 0.4979 70 96 +i 2 116.0000 0.6646 72 96 +i 2 116.6667 0.6646 70 96 +i 2 117.3333 0.6646 74 96 +i 2 118.0000 0.9979 67 96 +i 2 119.0000 0.9979 65 96 +i 2 120.0000 0.1375 63 96 +i 2 120.1396 0.1375 64 96 +i 2 120.2813 0.1375 65 96 +i 2 120.4250 0.1375 66 96 +i 2 120.5646 0.1375 67 96 +i 2 120.7063 0.1375 68 96 +i 2 120.8500 0.1479 69 96 +i 2 121.0000 2.9979 70 96 +i 2 124.0000 0.6646 70 96 +i 2 124.6667 0.6646 68 96 +i 2 125.3333 0.6646 72 96 +i 2 126.0000 0.9979 65 96 +i 2 127.0000 0.9979 63 96 +i 2 128.0000 0.1625 62 96 +i 2 128.1646 0.1625 63 96 +i 2 128.3313 0.1625 64 96 +i 2 128.5000 0.1625 65 96 +i 2 128.6646 0.1625 66 96 +i 2 128.8312 0.1625 67 96 +i 2 129.0000 2.9979 68 96 +i 2 132.0000 0.6646 68 96 +i 2 132.6667 0.6646 67 96 +i 2 133.3333 0.6646 71 96 +i 2 134.0000 0.9979 63 96 +i 2 135.0000 0.9979 62 96 +i 2 136.0000 1.4979 60 96 +i 2 137.5000 1.4979 60 96 +i 2 139.0000 0.9979 60 96 +i 2 140.0000 2.9979 61 96 +i 2 143.0000 0.2479 68 96 +i 2 143.2500 0.2479 67 96 +i 2 143.5000 0.2479 66 96 +i 2 143.7500 0.2479 67 96 +i 2 144.0000 2.9979 75 49 +i 2 147.0000 0.4979 72 49 +i 2 147.5000 0.4979 74 49 +i 2 148.0000 0.6646 75 49 +i 2 148.6667 0.6646 74 49 +i 2 149.3333 0.6646 77 49 +i 2 150.0000 0.9979 70 49 +i 2 151.0000 0.9979 68 49 +i 2 152.0000 0.9979 67 49 +i 2 153.0000 2.9979 74 49 +i 2 156.0000 0.6646 74 49 +i 2 156.6667 0.6646 72 49 +i 2 157.3333 0.6646 75 49 +i 2 158.0000 0.9979 68 49 +i 2 159.0000 0.9979 67 49 +i 2 160.0000 3.9979 66 49 +i 2 164.0000 2.9979 67 49 +i 2 167.0000 0.4979 67 49 +i 2 167.5000 0.4979 67 49 +i 2 168.0000 5.9979 72 49 +i 2 176.5000 0.4979 55 33 +i 2 177.0000 2.9979 56 33 +i 2 180.5000 0.4979 55 33 +i 2 181.0000 2.9979 56 33 +i 2 184.5000 0.4979 55 33 +i 2 185.0000 2.9979 56 33 +i 2 188.5000 0.4979 55 33 +i 2 189.0000 2.9979 56 33 +i 2 192.5000 0.4979 63 33 +i 2 193.0000 0.4979 62 33 +i 2 193.5000 0.4979 63 33 +i 2 194.5000 0.4979 63 33 +i 2 195.0000 0.9979 62 33 +i 2 196.5000 0.4979 62 33 +i 2 197.0000 0.4979 60 33 +i 2 197.5000 0.4979 62 33 +i 2 198.5000 0.4979 62 33 +i 2 199.0000 0.4979 60 33 +i 2 199.5000 0.4979 62 33 +i 2 200.5000 0.4979 62 33 +i 2 201.0000 0.4979 60 33 +i 2 201.5000 0.4979 62 33 +i 2 202.5000 0.4979 62 33 +i 2 203.0000 0.4979 60 33 +i 2 203.5000 0.4979 62 33 +i 2 204.5000 0.4979 60 33 +i 2 205.0000 0.4979 62 33 +i 2 205.5000 0.4979 59 33 +i 2 206.0000 0.9979 63 33 +i 2 207.0000 0.9979 62 33 +i 2 209.5000 0.4979 60 33 +i 2 210.0000 0.4979 62 33 +i 2 210.5000 0.4979 63 33 +i 2 211.0000 0.9979 65 33 +i 2 213.5000 0.4979 60 33 +i 2 214.0000 0.4979 62 33 +i 2 214.5000 0.4979 63 33 +i 2 215.0000 0.9979 65 33 +i 2 217.5000 0.4979 60 33 +i 2 218.0000 0.4979 62 33 +i 2 218.5000 0.4979 63 33 +i 2 219.0000 0.9979 65 33 +i 2 221.5000 0.4979 60 33 +i 2 222.0000 0.4979 62 33 +i 2 222.5000 0.4979 63 33 +i 2 223.0000 0.9979 65 33 +i 2 224.0000 0.9979 65 33 +i 2 225.0000 0.9979 67 33 +i 2 226.0000 0.9979 64 33 +i 2 227.0000 0.9979 65 33 +i 2 228.0000 1.9979 68 33 +i 2 230.0000 1.9979 67 33 +i 2 232.0000 0.9979 60 33 +i 2 233.0000 0.9979 62 33 +i 2 234.0000 0.9979 63 33 +i 2 235.0000 0.9979 65 33 +i 2 236.0000 1.4979 67 33 +i 2 237.5000 0.2479 65 33 +i 2 237.7500 0.2479 63 33 +i 2 238.0000 0.9979 62 33 +i 2 239.0000 0.9979 60 33 +i 2 240.0000 0.9979 65 80 +i 2 241.0000 1.9979 67 80 +i 2 243.0000 0.9979 65 80 +i 2 244.0000 0.9979 68 80 +i 2 245.0000 1.9979 67 80 +i 2 247.0000 0.9979 65 80 +i 2 248.0000 0.9979 63 80 +i 2 249.0000 1.9979 65 80 +i 2 251.0000 0.9979 63 80 +i 2 252.0000 0.9979 67 80 +i 2 253.0000 1.9979 65 80 +i 2 255.0000 0.9979 63 74 +i 2 256.0000 0.9979 62 71 +i 2 257.0000 1.9979 63 68 +i 2 259.0000 0.9979 62 62 +i 2 260.0000 0.9979 62 59 +i 2 261.0000 1.9979 63 56 +i 2 263.0000 0.9979 62 49 +i 2 265.5000 0.4979 60 49 +i 2 266.0000 0.4979 62 49 +i 2 266.5000 0.4979 63 49 +i 2 267.0000 0.4979 65 49 +i 2 267.5000 0.4979 67 49 +i 2 269.5000 0.4979 60 49 +i 2 270.0000 0.4979 62 49 +i 2 270.5000 0.4979 63 49 +i 2 271.0000 0.4979 65 49 +i 2 271.5000 0.4979 67 49 +i 2 273.5000 0.4979 60 49 +i 2 274.0000 0.4979 62 49 +i 2 274.5000 0.4979 63 49 +i 2 275.0000 0.4979 65 49 +i 2 275.5000 0.4979 67 49 +i 2 277.5000 0.4979 60 49 +i 2 278.0000 0.4979 62 49 +i 2 278.5000 0.4979 63 49 +i 2 279.0000 0.4979 65 49 +i 2 279.5000 0.4979 67 49 +i 2 280.0000 3.9979 63 33 + +; track 3 + +i 3 16.0000 4.6646 67 64 +i 3 20.6667 0.6646 65 64 +i 3 21.3333 0.6646 63 64 +i 3 22.0000 1.4979 62 64 +i 3 23.5000 0.4979 60 64 +i 3 24.0000 5.4979 63 64 +i 3 29.5000 0.2479 62 64 +i 3 29.7500 0.2479 60 64 +i 3 30.0000 1.4979 58 64 +i 3 31.5000 0.4979 56 64 +i 3 32.0000 2.9979 60 64 +i 3 35.0000 0.2479 58 64 +i 3 35.2500 0.2479 60 64 +i 3 35.5000 0.2479 58 64 +i 3 35.7500 0.2479 56 64 +i 3 36.0000 1.4979 58 64 +i 3 37.5000 0.4979 60 64 +i 3 38.0000 0.4979 60 64 +i 3 38.5000 0.4979 58 64 +i 3 39.0000 0.4979 56 64 +i 3 39.5000 0.4979 55 64 +i 3 40.0000 1.4979 56 64 +i 3 41.5000 0.2479 55 53 +i 3 41.7500 0.2479 53 51 +i 3 42.0000 0.9979 51 49 +i 3 43.0000 0.9979 50 41 +i 3 44.0000 3.9979 55 33 +i 3 48.5000 0.4979 55 33 +i 3 49.0000 2.9979 56 33 +i 3 52.5000 0.4979 55 33 +i 3 53.0000 2.9979 56 33 +i 3 56.5000 0.4979 55 33 +i 3 57.0000 2.9979 56 33 +i 3 60.5000 0.4979 55 33 +i 3 61.0000 2.9979 56 33 +i 3 64.0000 1.4979 61 33 +i 3 65.5000 1.4979 61 33 +i 3 67.0000 0.9979 61 33 +i 3 68.0000 1.4979 61 33 +i 3 69.5000 1.4979 61 33 +i 3 71.0000 0.9979 61 33 +i 3 72.0000 1.4979 60 33 +i 3 73.5000 1.4979 60 33 +i 3 75.0000 0.9979 60 33 +i 3 76.0000 1.4979 60 33 +i 3 77.5000 1.4979 60 33 +i 3 79.0000 0.9979 60 33 +i 3 80.0000 1.4979 60 80 +i 3 81.5000 1.4979 60 80 +i 3 83.0000 0.9979 60 80 +i 3 84.0000 1.4979 62 80 +i 3 85.5000 1.4979 62 80 +i 3 87.0000 0.9979 58 80 +i 3 88.0000 1.4979 55 80 +i 3 89.5000 1.4979 55 80 +i 3 91.0000 0.9979 55 80 +i 3 92.0000 1.4979 60 80 +i 3 93.5000 1.4979 60 80 +i 3 95.0000 0.9979 60 80 +i 3 96.0000 1.4979 66 80 +i 3 97.5000 1.4979 66 80 +i 3 99.0000 0.9979 66 80 +i 3 100.0000 1.4979 65 80 +i 3 101.5000 1.4979 65 80 +i 3 103.0000 0.9979 65 80 +i 3 104.0000 1.4979 63 80 +i 3 105.5000 1.4979 63 80 +i 3 107.0000 0.9979 63 80 +i 3 108.0000 1.4979 63 80 +i 3 109.5000 1.4979 63 80 +i 3 111.0000 0.9979 63 80 +i 3 112.0000 2.9979 68 96 +i 3 115.0000 0.4979 65 96 +i 3 115.5000 0.4979 67 96 +i 3 116.0000 0.6646 68 96 +i 3 116.6667 0.6646 67 96 +i 3 117.3333 0.6646 70 96 +i 3 118.0000 0.9979 62 96 +i 3 119.0000 0.9979 60 96 +i 3 120.0000 0.1063 58 96 +i 3 120.1083 0.1063 59 96 +i 3 120.2188 0.1063 60 96 +i 3 120.3292 0.1063 61 96 +i 3 120.4396 0.1063 62 96 +i 3 120.5500 0.1063 63 96 +i 3 120.6604 0.1063 64 96 +i 3 120.7708 0.1063 65 96 +i 3 120.8813 0.1125 66 96 +i 3 121.0000 2.9979 67 96 +i 3 124.0000 0.6646 67 96 +i 3 124.6667 0.6646 65 96 +i 3 125.3333 0.6646 68 96 +i 3 126.0000 0.9979 60 96 +i 3 127.0000 0.9979 58 96 +i 3 128.0000 0.1062 56 96 +i 3 128.1083 0.1062 57 96 +i 3 128.2188 0.1062 58 96 +i 3 128.3292 0.1062 59 96 +i 3 128.4396 0.1062 60 96 +i 3 128.5500 0.1062 61 96 +i 3 128.6604 0.1062 62 96 +i 3 128.7708 0.1062 63 96 +i 3 128.8812 0.1125 64 96 +i 3 129.0000 2.9979 65 96 +i 3 132.0000 0.6646 65 96 +i 3 132.6667 0.6646 65 96 +i 3 133.3333 0.6646 67 96 +i 3 134.0000 0.9979 60 96 +i 3 135.0000 0.9979 59 96 +i 3 136.0000 1.4979 55 96 +i 3 137.5000 1.4979 56 96 +i 3 139.0000 0.9979 55 96 +i 3 140.0000 3.9979 58 96 +i 3 144.0000 0.4979 56 33 +i 3 144.5000 0.9979 63 33 +i 3 145.5000 0.4979 56 33 +i 3 146.0000 1.9979 63 33 +i 3 148.0000 0.4979 56 33 +i 3 148.5000 0.9979 65 33 +i 3 149.5000 0.4979 56 33 +i 3 150.0000 1.9979 62 33 +i 3 152.0000 0.4979 51 33 +i 3 152.5000 0.9979 58 33 +i 3 153.5000 0.4979 55 33 +i 3 154.0000 1.9979 62 33 +i 3 156.0000 0.4979 56 33 +i 3 156.5000 0.9979 63 33 +i 3 157.5000 0.4979 60 33 +i 3 158.0000 0.9979 65 33 +i 3 159.0000 0.9979 63 33 +i 3 160.0000 3.9979 56 33 +i 3 164.0000 3.9979 59 33 +i 3 168.0000 1.4979 63 33 +i 3 169.5000 1.4979 63 33 +i 3 171.0000 0.9979 63 33 +i 3 172.0000 1.4979 63 33 +i 3 173.5000 1.4979 63 33 +i 3 175.0000 0.9979 63 33 +i 3 176.0000 1.4979 48 33 +i 3 177.5000 0.4979 60 33 +i 3 178.0000 0.9979 60 33 +i 3 179.0000 0.9979 48 33 +i 3 180.0000 1.4979 48 33 +i 3 181.5000 0.4979 60 33 +i 3 182.0000 0.9979 60 33 +i 3 183.0000 0.9979 48 33 +i 3 184.0000 1.4979 48 33 +i 3 185.5000 0.4979 60 33 +i 3 186.0000 0.9979 60 33 +i 3 187.0000 0.9979 48 33 +i 3 188.0000 1.4979 48 33 +i 3 189.5000 0.4979 60 33 +i 3 190.0000 0.9979 60 33 +i 3 191.0000 0.9979 48 33 +i 3 192.0000 1.4979 53 33 +i 3 193.5000 0.4979 53 33 +i 3 194.0000 0.9979 58 33 +i 3 195.0000 0.9979 58 33 +i 3 196.0000 1.4979 51 33 +i 3 197.5000 0.4979 51 33 +i 3 198.0000 0.9979 56 33 +i 3 199.0000 0.9979 56 33 +i 3 200.0000 1.4979 50 33 +i 3 201.5000 0.4979 62 33 +i 3 202.0000 0.9979 62 33 +i 3 203.0000 0.9979 50 33 +i 3 204.0000 1.4979 55 33 +i 3 205.5000 0.4979 56 33 +i 3 206.0000 0.4979 55 33 +i 3 206.5000 0.4979 53 33 +i 3 207.0000 0.4979 51 33 +i 3 207.5000 0.4979 50 33 +i 3 208.0000 0.4979 48 33 +i 3 208.5000 0.4979 55 33 +i 3 209.0000 2.9979 56 33 +i 3 212.5000 0.4979 55 33 +i 3 213.0000 2.9979 56 33 +i 3 216.5000 0.4979 55 33 +i 3 217.0000 2.9979 56 33 +i 3 220.5000 0.4979 55 33 +i 3 221.0000 2.9979 56 33 +i 3 224.0000 1.4979 61 33 +i 3 225.5000 1.4979 61 33 +i 3 227.0000 0.9979 61 33 +i 3 228.0000 1.4979 61 33 +i 3 229.5000 1.4979 61 33 +i 3 231.0000 0.9979 61 33 +i 3 232.0000 1.4979 60 33 +i 3 233.5000 1.4979 60 33 +i 3 235.0000 0.9979 60 33 +i 3 236.0000 1.4979 60 33 +i 3 237.5000 1.4979 60 33 +i 3 239.0000 0.9979 60 33 +i 3 240.0000 1.4979 60 80 +i 3 241.5000 1.4979 60 80 +i 3 243.0000 0.9979 60 80 +i 3 244.0000 1.4979 62 80 +i 3 245.5000 1.4979 62 80 +i 3 247.0000 0.9979 58 80 +i 3 248.0000 1.4979 55 80 +i 3 249.5000 1.4979 55 80 +i 3 251.0000 0.9979 55 80 +i 3 252.0000 1.4979 60 80 +i 3 253.5000 1.4979 60 80 +i 3 255.0000 0.9979 60 76 +i 3 256.0000 1.4979 66 72 +i 3 257.5000 1.4979 66 67 +i 3 259.0000 0.9979 66 63 +i 3 260.0000 1.4979 65 59 +i 3 261.5000 1.4979 65 54 +i 3 263.0000 0.9979 65 49 +i 3 264.5000 0.4979 55 49 +i 3 265.0000 2.9979 56 49 +i 3 268.5000 0.4979 55 49 +i 3 269.0000 2.9979 56 49 +i 3 272.5000 0.4979 55 49 +i 3 273.0000 2.9979 56 49 +i 3 276.5000 0.4979 55 49 +i 3 277.0000 2.9979 56 49 +i 3 280.0000 3.9979 55 33 + +; track 4 + +i 4 0.0000 1.4979 36 49 +i 4 1.5000 0.4979 48 49 +i 4 2.0000 0.9979 48 49 +i 4 3.0000 0.9979 36 49 +i 4 4.0000 1.4979 36 49 +i 4 5.5000 0.4979 48 49 +i 4 6.0000 0.9979 48 49 +i 4 7.0000 0.9979 36 49 +i 4 8.0000 1.4979 36 49 +i 4 9.5000 0.4979 48 49 +i 4 10.0000 0.9979 48 49 +i 4 11.0000 0.9979 36 49 +i 4 12.0000 1.4979 36 49 +i 4 13.5000 0.4979 48 49 +i 4 14.0000 0.9979 48 49 +i 4 15.0000 0.9979 36 49 +i 4 16.0000 1.4979 36 49 +i 4 17.5000 0.4979 48 49 +i 4 18.0000 0.9979 48 49 +i 4 19.0000 0.9979 36 49 +i 4 20.0000 1.4979 36 49 +i 4 21.5000 0.4979 48 49 +i 4 22.0000 0.9979 48 49 +i 4 23.0000 0.9979 36 49 +i 4 24.0000 1.4979 36 49 +i 4 25.5000 0.4979 48 49 +i 4 26.0000 0.9979 48 49 +i 4 27.0000 0.9979 36 49 +i 4 28.0000 1.4979 36 49 +i 4 29.5000 0.4979 48 49 +i 4 30.0000 0.9979 48 49 +i 4 31.0000 0.9979 36 49 +i 4 32.0000 1.4979 41 49 +i 4 33.5000 0.4979 41 49 +i 4 34.0000 0.9979 46 49 +i 4 35.0000 0.9979 46 49 +i 4 36.0000 1.4979 39 49 +i 4 37.5000 0.4979 39 49 +i 4 38.0000 0.9979 44 49 +i 4 39.0000 0.9979 44 49 +i 4 40.0000 1.4979 38 49 +i 4 41.5000 0.4979 50 46 +i 4 42.0000 0.9979 50 45 +i 4 43.0000 0.9979 38 43 +i 4 44.0000 1.4979 43 41 +i 4 45.5000 0.4979 44 38 +i 4 46.0000 0.4979 43 37 +i 4 46.5000 0.4979 41 36 +i 4 47.0000 0.4979 39 35 +i 4 47.5000 0.4979 38 33 +i 4 48.0000 1.4979 36 33 +i 4 49.5000 0.4979 48 33 +i 4 50.0000 0.9979 48 33 +i 4 51.0000 0.9979 36 33 +i 4 52.0000 1.4979 36 33 +i 4 53.5000 0.4979 48 33 +i 4 54.0000 0.9979 48 33 +i 4 55.0000 0.9979 36 33 +i 4 56.0000 1.4979 36 33 +i 4 57.5000 0.4979 48 33 +i 4 58.0000 0.9979 48 33 +i 4 59.0000 0.9979 36 33 +i 4 60.0000 1.4979 36 33 +i 4 61.5000 0.4979 48 33 +i 4 62.0000 0.9979 48 33 +i 4 63.0000 0.9979 36 33 +i 4 64.0000 1.4979 43 33 +i 4 65.5000 0.4979 55 33 +i 4 66.0000 0.9979 55 33 +i 4 67.0000 0.9979 43 33 +i 4 68.0000 1.4979 36 33 +i 4 69.5000 0.4979 48 33 +i 4 70.0000 0.9979 48 33 +i 4 71.0000 0.9979 36 33 +i 4 72.0000 1.4979 41 33 +i 4 73.5000 0.4979 53 33 +i 4 74.0000 0.9979 53 33 +i 4 75.0000 0.9979 41 33 +i 4 76.0000 1.4979 39 33 +i 4 77.5000 0.4979 51 33 +i 4 78.0000 0.9979 51 33 +i 4 79.0000 0.9979 39 33 +i 4 80.0000 1.4979 38 80 +i 4 81.5000 0.4979 50 80 +i 4 82.0000 0.9979 50 80 +i 4 83.0000 0.9979 38 80 +i 4 84.0000 1.4979 43 80 +i 4 85.5000 0.4979 55 80 +i 4 86.0000 0.9979 55 80 +i 4 87.0000 0.9979 50 80 +i 4 88.0000 1.4979 48 80 +i 4 89.5000 0.4979 60 80 +i 4 90.0000 0.9979 60 80 +i 4 91.0000 0.9979 48 80 +i 4 92.0000 1.4979 46 80 +i 4 93.5000 0.4979 58 80 +i 4 94.0000 0.9979 58 80 +i 4 95.0000 0.9979 46 80 +i 4 96.0000 1.4979 45 80 +i 4 97.5000 0.4979 57 80 +i 4 98.0000 0.9979 57 80 +i 4 99.0000 0.9979 45 80 +i 4 100.0000 1.4979 43 80 +i 4 101.5000 0.4979 55 80 +i 4 102.0000 0.9979 55 80 +i 4 103.0000 0.9979 43 80 +i 4 104.0000 1.4979 36 80 +i 4 105.5000 0.4979 48 80 +i 4 106.0000 0.9979 48 80 +i 4 107.0000 0.9979 36 80 +i 4 108.0000 1.4979 36 80 +i 4 109.5000 0.4979 48 80 +i 4 110.0000 0.9979 48 80 +i 4 111.0000 0.9979 36 80 +i 4 112.0000 1.4979 41 96 +i 4 113.5000 0.4979 51 96 +i 4 114.0000 0.9979 51 96 +i 4 115.0000 0.9979 41 96 +i 4 116.0000 1.4979 46 96 +i 4 117.5000 0.4979 58 96 +i 4 118.0000 0.9979 58 96 +i 4 119.0000 0.9979 46 96 +i 4 120.0000 1.4979 39 96 +i 4 121.5000 0.4979 51 96 +i 4 122.0000 0.9979 51 96 +i 4 123.0000 0.9979 46 96 +i 4 124.0000 1.4979 44 96 +i 4 125.5000 0.4979 56 96 +i 4 126.0000 0.9979 56 96 +i 4 127.0000 0.9979 44 96 +i 4 128.0000 1.4979 38 96 +i 4 129.5000 0.4979 50 96 +i 4 130.0000 0.9979 50 96 +i 4 131.0000 0.9979 38 96 +i 4 132.0000 1.4979 43 96 +i 4 133.5000 0.4979 55 96 +i 4 134.0000 0.9979 55 96 +i 4 135.0000 0.9979 43 96 +i 4 136.0000 1.4979 36 96 +i 4 137.5000 0.4979 36 96 +i 4 138.0000 1.4979 38 96 +i 4 139.5000 0.4979 38 96 +i 4 140.0000 1.4979 39 96 +i 4 141.5000 0.4979 39 96 +i 4 142.0000 1.4979 40 96 +i 4 143.5000 0.4979 40 96 +i 4 144.0000 1.4979 41 33 +i 4 145.5000 0.4979 51 33 +i 4 146.0000 0.9979 51 33 +i 4 147.0000 0.9979 41 33 +i 4 148.0000 1.4979 46 33 +i 4 149.5000 0.4979 58 33 +i 4 150.0000 0.9979 58 33 +i 4 151.0000 0.9979 46 33 +i 4 152.0000 1.4979 39 33 +i 4 153.5000 0.4979 51 33 +i 4 154.0000 0.9979 51 33 +i 4 155.0000 0.9979 46 33 +i 4 156.0000 1.4979 44 33 +i 4 157.5000 0.4979 56 33 +i 4 158.0000 0.9979 56 33 +i 4 159.0000 0.9979 44 33 +i 4 160.0000 1.4979 38 33 +i 4 161.5000 0.4979 50 33 +i 4 162.0000 0.9979 50 33 +i 4 163.0000 0.9979 38 33 +i 4 164.0000 1.4979 43 33 +i 4 165.5000 0.4979 55 33 +i 4 166.0000 0.9979 55 33 +i 4 167.0000 0.9979 43 33 +i 4 168.0000 1.4979 36 33 +i 4 169.5000 0.4979 48 33 +i 4 170.0000 0.9979 48 33 +i 4 171.0000 0.9979 36 33 +i 4 172.0000 1.9979 36 33 +i 4 175.0000 0.9979 55 49 +i 4 176.0000 4.4979 67 49 +i 4 180.5000 0.4979 65 49 +i 4 181.0000 0.3313 67 49 +i 4 181.3333 0.3313 65 49 +i 4 181.6667 0.3313 63 49 +i 4 182.0000 1.4979 62 49 +i 4 183.5000 0.4979 60 49 +i 4 184.0000 4.4979 63 49 +i 4 188.5000 0.4979 62 49 +i 4 189.0000 0.4979 65 49 +i 4 189.5000 0.4979 63 49 +i 4 190.0000 0.4979 62 49 +i 4 190.5000 0.9979 60 49 +i 4 191.5000 0.2479 58 49 +i 4 191.7500 0.2479 56 49 +i 4 192.0000 2.9979 60 49 +i 4 195.0000 0.2479 58 49 +i 4 195.2500 0.2479 60 49 +i 4 195.5000 0.2479 58 49 +i 4 195.7500 0.2479 56 49 +i 4 196.0000 1.9979 58 49 +i 4 198.0000 0.4979 60 49 +i 4 198.5000 0.9979 58 49 +i 4 199.5000 0.2479 56 49 +i 4 199.7500 0.2479 55 49 +i 4 200.0000 1.4979 56 49 +i 4 201.5000 0.2479 55 49 +i 4 201.7500 0.2479 53 49 +i 4 202.0000 0.9979 51 49 +i 4 203.0000 0.9979 50 49 +i 4 204.0000 3.9979 55 49 +i 4 208.0000 1.4979 36 49 +i 4 209.5000 0.4979 48 49 +i 4 210.0000 0.9979 48 49 +i 4 211.0000 0.9979 36 49 +i 4 212.0000 1.4979 36 49 +i 4 213.5000 0.4979 48 49 +i 4 214.0000 0.9979 48 49 +i 4 215.0000 0.9979 36 49 +i 4 216.0000 1.4979 36 49 +i 4 217.5000 0.4979 48 49 +i 4 218.0000 0.9979 48 49 +i 4 219.0000 0.9979 36 49 +i 4 220.0000 1.4979 36 49 +i 4 221.5000 0.4979 48 49 +i 4 222.0000 0.9979 48 49 +i 4 223.0000 0.9979 36 49 +i 4 224.0000 1.4979 43 49 +i 4 225.5000 0.4979 55 49 +i 4 226.0000 0.9979 55 49 +i 4 227.0000 0.9979 43 49 +i 4 228.0000 1.4979 36 49 +i 4 229.5000 0.4979 48 49 +i 4 230.0000 0.9979 48 49 +i 4 231.0000 0.9979 36 49 +i 4 232.0000 1.4979 41 49 +i 4 233.5000 0.4979 53 49 +i 4 234.0000 0.9979 53 49 +i 4 235.0000 0.9979 41 49 +i 4 236.0000 1.4979 39 49 +i 4 237.5000 0.4979 51 49 +i 4 238.0000 0.9979 51 49 +i 4 239.0000 0.9979 39 49 +i 4 240.0000 1.4979 38 80 +i 4 241.5000 0.4979 50 80 +i 4 242.0000 0.9979 50 80 +i 4 243.0000 0.9979 38 80 +i 4 244.0000 1.4979 43 80 +i 4 245.5000 0.4979 55 80 +i 4 246.0000 0.9979 55 80 +i 4 247.0000 0.9979 50 80 +i 4 248.0000 1.4979 48 80 +i 4 249.5000 0.4979 60 80 +i 4 250.0000 0.9979 60 80 +i 4 251.0000 0.9979 48 80 +i 4 252.0000 1.4979 46 80 +i 4 253.5000 0.4979 58 76 +i 4 254.0000 0.9979 58 75 +i 4 255.0000 0.9979 46 72 +i 4 256.0000 1.4979 45 69 +i 4 257.5000 0.4979 57 65 +i 4 258.0000 0.9979 57 64 +i 4 259.0000 0.9979 45 61 +i 4 260.0000 1.4979 43 58 +i 4 261.5000 0.4979 55 54 +i 4 262.0000 0.9979 55 52 +i 4 263.0000 0.9979 43 49 +i 4 264.0000 2.9979 36 49 +i 4 267.0000 0.9979 48 49 +i 4 268.0000 2.9979 46 49 +i 4 271.0000 0.9979 46 49 +i 4 272.0000 2.9979 44 49 +i 4 275.0000 0.9979 44 49 +i 4 276.0000 2.9979 43 49 +i 4 279.0000 0.9979 43 49 +i 4 280.0000 3.9979 36 33 +e 5 + + diff --git a/playpen/examples/oblivion/oblivion.mxl b/examples/oblivion/oblivion.mxl similarity index 100% rename from playpen/examples/oblivion/oblivion.mxl rename to examples/oblivion/oblivion.mxl diff --git a/playpen/examples/oblivion/oblivion.py b/examples/oblivion/oblivion.py similarity index 99% rename from playpen/examples/oblivion/oblivion.py rename to examples/oblivion/oblivion.py index 9df463e78f..3b728534b2 100644 --- a/playpen/examples/oblivion/oblivion.py +++ b/examples/oblivion/oblivion.py @@ -2,7 +2,7 @@ score = CsoundAC.Score() score.load("oblivion.xml") sco = score.getCsoundScore() -print(sco) +print("sco:\n" + sco) csd = ''' @@ -11,7 +11,7 @@ Arranged for Csound by Michael Gogins --odac:plughw:0,0 -m195 -d +-odac -m195 -d diff --git a/playpen/examples/sierpinski/sierpinski-csound-gtk.py b/examples/sierpinski/sierpinski-csound-gtk.py similarity index 100% rename from playpen/examples/sierpinski/sierpinski-csound-gtk.py rename to examples/sierpinski/sierpinski-csound-gtk.py diff --git a/playpen/examples/sierpinski/sierpinski-csound-gtk.ui b/examples/sierpinski/sierpinski-csound-gtk.ui similarity index 100% rename from playpen/examples/sierpinski/sierpinski-csound-gtk.ui rename to examples/sierpinski/sierpinski-csound-gtk.ui diff --git a/playpen/examples/sierpinski/sierpinski-csound.py b/examples/sierpinski/sierpinski-csound.py similarity index 100% rename from playpen/examples/sierpinski/sierpinski-csound.py rename to examples/sierpinski/sierpinski-csound.py diff --git a/playpen/examples/sierpinski/sierpinski-csound.ui b/examples/sierpinski/sierpinski-csound.ui similarity index 100% rename from playpen/examples/sierpinski/sierpinski-csound.ui rename to examples/sierpinski/sierpinski-csound.ui diff --git a/playpen/examples/sierpinski/sierpinski_csound_qt.py b/examples/sierpinski/sierpinski_csound_qt.py similarity index 100% rename from playpen/examples/sierpinski/sierpinski_csound_qt.py rename to examples/sierpinski/sierpinski_csound_qt.py diff --git a/playpen/examples/sierpinski/sierpinski_csound_qt.ui b/examples/sierpinski/sierpinski_csound_qt.ui similarity index 100% rename from playpen/examples/sierpinski/sierpinski_csound_qt.ui rename to examples/sierpinski/sierpinski_csound_qt.ui diff --git a/tests/ChordLindenmayerTest.py b/examples/tests/ChordLindenmayerTest.py similarity index 98% rename from tests/ChordLindenmayerTest.py rename to examples/tests/ChordLindenmayerTest.py index f36f6ded07..ec018f1c71 100644 --- a/tests/ChordLindenmayerTest.py +++ b/examples/tests/ChordLindenmayerTest.py @@ -60,7 +60,6 @@ print(__doc__) print('IMPORTING REQUIRED MODULES...') print -import csnd6 import CsoundAC import datetime import math @@ -88,8 +87,8 @@ def createGlobalObjects(self): print('CREATING GLOBAL OBJECTS...') print() self.model = CsoundAC.MusicModel() - self.csound = self.model.getCppSound() - self.csound.setPythonMessageCallback() + ##self.csound = self.model.getCppSound() + ##self.csound.setPythonMessageCallback() self.score = self.model.getScore() def createFilenames(self): print('CREATING FILENAMES...') @@ -166,13 +165,13 @@ def renderCsound(self): self.createMusicModel() self.model.generate() self.createScore() - self.ended = time.clock() + self.ended = time.perf_counter() self.elapsed = self.ended - self.began print('Finished rendering at %s' % time.strftime('%Y-%b-%d %A %H:%M:%S')) print('Elapsed time: %-9.2f seconds.' % self.elapsed) self.csound.perform() print - self.ended = time.clock() + self.ended = time.perf_counter() self.elapsed = self.ended - self.began print('Finished rendering at %s' % time.strftime('%Y-%b-%d %A %H:%M:%S')) print('Elapsed time: %-9.2f seconds.' % self.elapsed) @@ -190,11 +189,11 @@ def renderMidiScore(self): self.createMusicModel() self.model.generate() self.createScore() - self.ended = time.clock() + self.ended = time.perf_counter() self.elapsed = self.ended - self.began print('Finished generating at %s' % time.strftime('%Y-%b-%d %A %H:%M:%S')) print('Elapsed time: %-9.2f seconds.' % self.elapsed) - self.ended = time.clock() + self.ended = time.perf_counter() self.elapsed = self.ended - self.began print('Finished rendering at %s' % time.strftime('%Y-%b-%d %A %H:%M:%S')) print('Elapsed time: %-9.2f seconds.' % self.elapsed) @@ -271,7 +270,7 @@ def render(self): print('Rendering mode: %s' % self.renderingMode) print('Playback: %s' % self.playback) print() - self.began = time.clock() + self.began = time.perf_counter() self.timestamp = datetime.datetime.now() print('Timestamp: %s' % self.timestamp) self.createGlobalObjects() diff --git a/tests/CsoundAcUnitTests.py b/examples/tests/CsoundAcUnitTests.py similarity index 100% rename from tests/CsoundAcUnitTests.py rename to examples/tests/CsoundAcUnitTests.py diff --git a/tests/KindsOfChords.py b/examples/tests/KindsOfChords.py similarity index 100% rename from tests/KindsOfChords.py rename to examples/tests/KindsOfChords.py diff --git a/tests/SoundfileUnitTests.py b/examples/tests/SoundfileUnitTests.py similarity index 100% rename from tests/SoundfileUnitTests.py rename to examples/tests/SoundfileUnitTests.py diff --git a/tests/VoiceleadUnitTests.py b/examples/tests/VoiceleadUnitTests.py similarity index 100% rename from tests/VoiceleadUnitTests.py rename to examples/tests/VoiceleadUnitTests.py diff --git a/tests/VoiceleadingNodeUnitTests.py b/examples/tests/VoiceleadingNodeUnitTests.py similarity index 100% rename from tests/VoiceleadingNodeUnitTests.py rename to examples/tests/VoiceleadingNodeUnitTests.py diff --git a/playpen/examples/unperformed/unperformed-experiments.html b/examples/unperformed/unperformed-experiments.html similarity index 100% rename from playpen/examples/unperformed/unperformed-experiments.html rename to examples/unperformed/unperformed-experiments.html diff --git a/playpen/examples/xanadu/xanadu.csd b/examples/xanadu/xanadu.csd similarity index 100% rename from playpen/examples/xanadu/xanadu.csd rename to examples/xanadu/xanadu.csd diff --git a/playpen/examples/oblivion/oblivion.csd b/playpen/examples/oblivion/oblivion.csd deleted file mode 100644 index 20442bf638..0000000000 --- a/playpen/examples/oblivion/oblivion.csd +++ /dev/null @@ -1,921 +0,0 @@ - - -"Oblivion," by Astor Piazzola -Arranged for Csound by Michael Gogins - - --odac:plughw:1,0 -m195 -d - - - -sr = 48000 -ksmps = 128 -nchnls = 2 -0dbfs = 1 - -gi_ampmidicurve_dynamic_range init .375 -gi_ampmidicurve_exponent init 5 - -prealloc "ZakianFlute", 4 -prealloc "Guitar", 4 -prealloc "Harpsichord", 4 -prealloc "YiString", 4 -prealloc "Bower", 4 - -connect "Guitar", "outleft", "ReverbSC", "inleft" -connect "Guitar", "outleft", "ReverbSC", "inleft" -connect "ZakianFlute", "outleft", "ReverbSC", "inleft" -connect "ZakianFlute", "outleft", "ReverbSC", "inleft" -connect "Harpsichord", "outleft", "ReverbSC", "inleft" -connect "Harpsichord", "outright", "ReverbSC", "inright" -connect "YiString", "outleft", "ReverbSC", "inleft" -connect "YiString", "outright", "ReverbSC", "inright" -connect "Bower", "outleft", "ReverbSC", "inleft" -connect "Bower", "outright", "ReverbSC", "inright" -connect "ReverbSC", "outleft", "MasterOutput", "inleft" -connect "ReverbSC", "outright", "MasterOutput", "inright" - -alwayson "ReverbSC" -alwayson "MasterOutput" - -gk_overlap init .0125 - -;gk_ZakianFlute_level init -2 -gk_ZakianFlute_level chnexport "gk_ZakianFlute_level",3 -gk_ZakianFlute_pan init (2 / 7 - .5) -gi_ZakianFLute_seed init .5 -gif2 ftgen 0, 0, 16, -2, 40, 40, 80, 160, 320, 640, 1280, 2560, 5120, 10240, 10240 -gif26 ftgen 0, 0, 65536, -10, 2000, 489, 74, 219, 125, 9, 33, 5, 5 -gif27 ftgen 0, 0, 65536, -10, 2729, 1926, 346, 662, 537, 110, 61, 29, 7 -gif28 ftgen 0, 0, 65536, -10, 2558, 2012, 390, 361, 534, 139, 53, 22, 10, 13, 10 -gif29 ftgen 0, 0, 65536, -10, 12318, 8844, 1841, 1636, 256, 150, 60, 46, 11 -gif30 ftgen 0, 0, 65536, -10, 1229, 16, 34, 57, 32 -gif31 ftgen 0, 0, 65536, -10, 163, 31, 1, 50, 31 -gif32 ftgen 0, 0, 65536, -10, 4128, 883, 354, 79, 59, 23 -gif33 ftgen 0, 0, 65536, -10, 1924, 930, 251, 50, 25, 14 -gif34 ftgen 0, 0, 65536, -10, 94, 6, 22, 8 -gif35 ftgen 0, 0, 65536, -10, 2661, 87, 33, 18 -gif36 ftgen 0, 0, 65536, -10, 174, 12 -gif37 ftgen 0, 0, 65536, -10, 314, 13 -giwtsin ftgen 0, 0, 65536, 10, 1 -instr ZakianFlute -; Author: Lee Zakian -; Adapted by: Michael Gogins -if p3 == -1 goto indefinite -goto non_indefinite -indefinite: - p3 = 1000000 -non_indefinite: -i_instrument = p1 -i_time = p2 -i_duration = p3 -i_midi_key = p4 -i_midi_velocity = p5 -k_space_front_to_back = p6 -k_space_left_to_right = p1/6 -k_space_bottom_to_top = p8 -i_phase = p9 -i_overall_amps = 65 -i_amplitude ampmidicurve i_midi_velocity, gi_ampmidicurve_dynamic_range, gi_ampmidicurve_exponent -k_gain = ampdb(gk_ZakianFlute_level) -iattack = .002 -isustain = p3 -irelease = .3 -xtratim iattack + isustain + irelease -iHz = cpsmidinn(i_midi_key) -kHz = k(iHz) -aenvelope transeg 1.0, 20.0, -10.0, 0.05 -ip3 = (p3 < 3.0 ? p3 : 3.0) -; parameters -; p4 overall amplitude scaling factor -ip4 init i_amplitude -; p5 pitch in Hertz (normal pitch range: C4-C7) -ip5 init iHz -; p6 percent vibrato depth, recommended values in range [-1., +1.] -ip6 init 0.5 -; 0.0 -> no vibrato -; +1. -> 1% vibrato depth, where vibrato rate increases slightly -; -1. -> 1% vibrato depth, where vibrato rate decreases slightly -; p7 attack time in seconds -; recommended value: .12 for slurred notes, .06 for tongued notes -; (.03 for short notes) -ip7 init .08 -; p8 decay time in seconds -; recommended value: .1 (.05 for short notes) -ip8 init .08 -; p9 overall brightness / filter cutoff factor -; 1 -> least bright / minimum filter cutoff frequency (40 Hz) -; 9 -> brightest / maximum filter cutoff frequency (10,240Hz) -ip9 init 5 -; initial variables -iampscale = ip4 ; overall amplitude scaling factor -ifreq = ip5 ; pitch in Hertz -ivibdepth = abs(ip6*ifreq/100.0) ; vibrato depth relative to fundamental frequency -iattack = ip7 * (1.1 - .2*gi_ZakianFLute_seed) ; attack time with up to +-10% random deviation -gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) ; reset gi_ZakianFLute_seed -idecay = ip8 * (1.1 - .2*gi_ZakianFLute_seed) ; decay time with up to +-10% random deviation -gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) -ifiltcut tablei ip9, gif2 ; lowpass filter cutoff frequency -iattack = (iattack < 6/kr ? 6/kr : iattack) ; minimal attack length -idecay = (idecay < 6/kr ? 6/kr : idecay) ; minimal decay length -isustain = p3 - iattack - idecay -p3 = (isustain < 5/kr ? iattack+idecay+5/kr : p3) ; minimal sustain length -isustain = (isustain < 5/kr ? 5/kr : isustain) -iatt = iattack/6 -isus = isustain/4 -idec = idecay/6 -iphase = gi_ZakianFLute_seed ; use same phase for all wavetables -gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) -; vibrato block -; kvibdepth linseg .1, .8*p3, 1, .2*p3, .7 -kvibdepth linseg .1, .8*ip3, 1, isustain, 1, .2*ip3, .7 -kvibdepth = kvibdepth* ivibdepth ; vibrato depth -kvibdepthr randi .1*kvibdepth, 5, gi_ZakianFLute_seed ; up to 10% vibrato depth variation -gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) -kvibdepth = kvibdepth + kvibdepthr -ivibr1 = gi_ZakianFLute_seed ; vibrato rate -gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) -ivibr2 = gi_ZakianFLute_seed -gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) -if ip6 < 0 goto vibrato1 -kvibrate linseg 2.5+ivibr1, p3, 4.5+ivibr2 ; if p6 positive vibrato gets faster - goto vibrato2 -vibrato1: -ivibr3 = gi_ZakianFLute_seed -gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) -kvibrate linseg 3.5+ivibr1, .1, 4.5+ivibr2, p3-.1, 2.5+ivibr3 ; if p6 negative vibrato gets slower -vibrato2: -kvibrater randi .1*kvibrate, 5, gi_ZakianFLute_seed ; up to 10% vibrato rate variation -gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) -kvibrate = kvibrate + kvibrater -kvib oscili kvibdepth, kvibrate, giwtsin -ifdev1 = -.03 * gi_ZakianFLute_seed ; frequency deviation -gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) -ifdev2 = .003 * gi_ZakianFLute_seed -gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) -ifdev3 = -.0015 * gi_ZakianFLute_seed -gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) -ifdev4 = .012 * gi_ZakianFLute_seed -gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) -kfreqr linseg ifdev1, iattack, ifdev2, isustain, ifdev3, idecay, ifdev4 -kfreq = kHz * (1 + kfreqr) + kvib -if ifreq < 427.28 goto range1 ; (cpspch(8.08) + cpspch(8.09))/2 -if ifreq < 608.22 goto range2 ; (cpspch(9.02) + cpspch(9.03))/2 -if ifreq < 1013.7 goto range3 ; (cpspch(9.11) + cpspch(10.00))/2 -goto range4 -; wavetable amplitude envelopes -range1: ; for low range tones -kamp1 linseg 0, iatt, 0.002, iatt, 0.045, iatt, 0.146, iatt, 0.272, iatt, 0.072, iatt, 0.043, isus, 0.230, isus, 0.000, isus, 0.118, isus, 0.923, idec, 1.191, idec, 0.794, idec, 0.418, idec, 0.172, idec, 0.053, idec, 0 -kamp2 linseg 0, iatt, 0.009, iatt, 0.022, iatt, -0.049, iatt, -0.120, iatt, 0.297, iatt, 1.890, isus, 1.543, isus, 0.000, isus, 0.546, isus, 0.690, idec, -0.318, idec, -0.326, idec, -0.116, idec, -0.035, idec, -0.020, idec, 0 -kamp3 linseg 0, iatt, 0.005, iatt, -0.026, iatt, 0.023, iatt, 0.133, iatt, 0.060, iatt, -1.245, isus, -0.760, isus, 1.000, isus, 0.360, isus, -0.526, idec, 0.165, idec, 0.184, idec, 0.060, idec, 0.010, idec, 0.013, idec, 0 -iwt1 = gif26 ; wavetable numbers -iwt2 = gif27 -iwt3 = gif28 -inorm = 3949 -goto end -range2: ; for low mid-range tones -kamp1 linseg 0, iatt, 0.000, iatt, -0.005, iatt, 0.000, iatt, 0.030, iatt, 0.198, iatt, 0.664, isus, 1.451, isus, 1.782, isus, 1.316, isus, 0.817, idec, 0.284, idec, 0.171, idec, 0.082, idec, 0.037, idec, 0.012, idec, 0 -kamp2 linseg 0, iatt, 0.000, iatt, 0.320, iatt, 0.882, iatt, 1.863, iatt, 4.175, iatt, 4.355, isus, -5.329, isus, -8.303, isus, -1.480, isus, -0.472, idec, 1.819, idec, -0.135, idec, -0.082, idec, -0.170, idec, -0.065, idec, 0 -kamp3 linseg 0, iatt, 1.000, iatt, 0.520, iatt, -0.303, iatt, 0.059, iatt, -4.103, iatt, -6.784, isus, 7.006, isus, 11, isus, 12.495, isus, -0.562, idec, -4.946, idec, -0.587, idec, 0.440, idec, 0.174, idec, -0.027, idec, 0 -iwt1 = gif29 -iwt2 = gif30 -iwt3 = gif31 -inorm = 27668.2 -goto end -range3: ; for high mid-range tones -kamp1 linseg 0, iatt, 0.005, iatt, 0.000, iatt, -0.082, iatt, 0.36, iatt, 0.581, iatt, 0.416, isus, 1.073, isus, 0.000, isus, 0.356, isus, .86, idec, 0.532, idec, 0.162, idec, 0.076, idec, 0.064, idec, 0.031, idec, 0 -kamp2 linseg 0, iatt, -0.005, iatt, 0.000, iatt, 0.205, iatt, -0.284, iatt, -0.208, iatt, 0.326, isus, -0.401, isus, 1.540, isus, 0.589, isus, -0.486, idec, -0.016, idec, 0.141, idec, 0.105, idec, -0.003, idec, -0.023, idec, 0 -kamp3 linseg 0, iatt, 0.722, iatt, 1.500, iatt, 3.697, iatt, 0.080, iatt, -2.327, iatt, -0.684, isus, -2.638, isus, 0.000, isus, 1.347, isus, 0.485, idec, -0.419, idec, -.700, idec, -0.278, idec, 0.167, idec, -0.059, idec, 0 -iwt1 = gif32 -iwt2 = gif33 -iwt3 = gif34 -inorm = 3775 -goto end -range4: ; for high range tones -kamp1 linseg 0, iatt, 0.000, iatt, 0.000, iatt, 0.211, iatt, 0.526, iatt, 0.989, iatt, 1.216, isus, 1.727, isus, 1.881, isus, 1.462, isus, 1.28, idec, 0.75, idec, 0.34, idec, 0.154, idec, 0.122, idec, 0.028, idec, 0 -kamp2 linseg 0, iatt, 0.500, iatt, 0.000, iatt, 0.181, iatt, 0.859, iatt, -0.205, iatt, -0.430, isus, -0.725, isus, -0.544, isus, -0.436, isus, -0.109, idec, -0.03, idec, -0.022, idec, -0.046, idec, -0.071, idec, -0.019, idec, 0 -kamp3 linseg 0, iatt, 0.000, iatt, 1.000, iatt, 0.426, iatt, 0.222, iatt, 0.175, iatt, -0.153, isus, 0.355, isus, 0.175, isus, 0.16, isus, -0.246, idec, -0.045, idec, -0.072, idec, 0.057, idec, -0.024, idec, 0.002, idec, 0 -iwt1 = gif35 -iwt2 = gif36 -iwt3 = gif37 -inorm = 4909.05 -goto end -end: -kampr1 randi .02*kamp1, 10, gi_ZakianFLute_seed ; up to 2% wavetable amplitude variation -gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) -kamp1 = kamp1 + kampr1 -kampr2 randi .02*kamp2, 10, gi_ZakianFLute_seed ; up to 2% wavetable amplitude variation -gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) -kamp2 = kamp2 + kampr2 -kampr3 randi .02*kamp3, 10, gi_ZakianFLute_seed ; up to 2% wavetable amplitude variation -gi_ZakianFLute_seed = frac(gi_ZakianFLute_seed*105.947) -kamp3 = kamp3 + kampr3 -awt1 poscil kamp1, kfreq, iwt1, iphase ; wavetable lookup -awt2 poscil kamp2, kfreq, iwt2, iphase -awt3 poscil kamp3, kfreq, iwt3, iphase -asig = awt1 + awt2 + awt3 -asig = asig*(iampscale/inorm) -kcut linseg 0, iattack, ifiltcut, isustain, ifiltcut, idecay, 0 ; lowpass filter for brightness control -afilt tone asig, kcut -a_signal balance afilt, asig -i_attack = .002 -i_sustain = p3 -i_release = 0.01 -xtratim i_attack + i_sustain + i_release -a_declicking linsegr 0, i_attack, 1, i_sustain, 1, i_release, 0 -a_signal = a_signal * i_amplitude * a_declicking * k_gain -#ifdef USE_SPATIALIZATION -a_spatial_reverb_send init 0 -a_bsignal[] init 16 -a_bsignal, a_spatial_reverb_send Spatialize a_signal, k_space_front_to_back, k_space_left_to_right, k_space_bottom_to_top -outletv "outbformat", a_bsignal -outleta "out", a_spatial_reverb_send -#else -a_out_left, a_out_right pan2 a_signal, p1/6 -outleta "outleft", a_out_left -outleta "outright", a_out_right -#endif -prints "ZakianFlute i %9.4f t %9.4f d %9.4f k %9.4f v %9.4f p %9.4f #%3d\n", p1, p2, p3, p4, p5, p1/6, active(p1) -endin - -gk_Guitar_level init 8 -instr Guitar -; Michael Gogins -if p3 == -1 goto indefinite -goto non_indefinite -indefinite: - p3 = 1000000 -non_indefinite: -i_instrument = p1 -i_time = p2 -i_duration = p3 -i_midi_key = p4 -i_midi_velocity = p5 -k_space_front_to_back = p6 -k_space_left_to_right = p1/6 -k_space_bottom_to_top = p8 -i_phase = p9 -i_frequency = cpsmidinn(i_midi_key) -i_amplitude ampmidicurve i_midi_velocity, gi_ampmidicurve_dynamic_range, gi_ampmidicurve_exponent -k_gain = ampdb(gk_Guitar_level) -acomp pluck i_amplitude, 440.0, 440.0, 0, 1, .1 -i_frequency2 = i_frequency / 2.0 -kHz = k(i_frequency) -iattack = 0.004 -isustain = p3 -irelease = 0.05 -p3 = iattack + isustain + irelease -asigcomp pluck 1.0, 440, 440, 0, 1 -asig pluck 1.0, i_frequency, i_frequency, 0, 1 -af1 reson asig, 110, 80 -af2 reson asig, 220, 100 -af3 reson asig, 440, 80 -aout balance 0.6 * af1 + af2 + 0.6 * af3 + 0.4 * asig, asigcomp -aexp expseg 1.0, iattack, 2.0, isustain, 1.0, irelease, 1.0 -aenv = aexp - 1.0 -a_signal = aout * aenv -a_declicking linsegr 0, iattack, 1, isustain, 1, irelease, 0 -a_signal = a_signal * i_amplitude * a_declicking * k_gain -#ifdef USE_SPATIALIZATION -a_spatial_reverb_send init 0 -a_bsignal[] init 16 -a_bsignal, a_spatial_reverb_send Spatialize a_signal, k_space_front_to_back, k_space_left_to_right, k_space_bottom_to_top -outletv "outbformat", a_bsignal -outleta "out", a_spatial_reverb_send -#else -a_out_left, a_out_right pan2 a_signal, p1/6 -outleta "outleft", a_out_left -outleta "outright", a_out_right -#endif -prints "Guitar i %9.4f t %9.4f d %9.4f k %9.4f v %9.4f p %9.4f #%3d\n", p1, p2, p3, p4, p5, p1/6, active(p1) -endin - -gk_YiString_level init 6 -gk_YiString_reverb_send init .5 -gk_YiString_chorus_send init .5 -gi_YiString_overlap init .1 -instr YiString - ////////////////////////////////////////////// - // Original by Steven Yi. - // Adapted by Michael Gogins. - ////////////////////////////////////////////// -if p3 == -1 goto indefinite -goto non_indefinite -indefinite: - p3 = 1000000 -non_indefinite: -i_instrument = p1 -i_time = p2 -i_duration = p3 -i_midi_key = p4 -i_midi_velocity = p5 -k_space_front_to_back = p6 -k_space_left_to_right = p1/6 -k_space_bottom_to_top = p8 -i_phase = p9 -i_frequency = cpsmidinn(i_midi_key) -i_amplitude ampmidicurve i_midi_velocity, gi_ampmidicurve_dynamic_range, gi_ampmidicurve_exponent -k_gain = ampdb(gk_YiString_level) -iattack = gi_YiString_overlap -isustain = p3 -idecay = gi_YiString_overlap -p3 = iattack + isustain + idecay -aenvelope transeg 0.0, iattack / 2.0, 1.5, i_amplitude / 2.0, iattack / 2.0, -1.5, i_amplitude, isustain, 0.0, i_amplitude, idecay / 2.0, 1.5, i_amplitude / 2.0, idecay / 2.0, -1.5, 0 -;ampenv = madsr:a(1, 0.1, 0.95, 0.5) -asignal = vco2(1, i_frequency) -asignal = moogladder(asignal, 6000, 0.1) -a_signal = asignal * aenvelope -i_attack = .002 -i_release = 0.01 -i_sustain = p3 - (i_attack + i_release) -a_declicking linsegr 0, i_attack, 1, i_sustain, 1, i_release, 0 -a_signal = a_signal * i_amplitude * a_declicking * k_gain -#ifdef USE_SPATIALIZATION -a_spatial_reverb_send init 0 -a_bsignal[] init 16 -a_bsignal, a_spatial_reverb_send Spatialize a_signal, k_space_front_to_back, k_space_left_to_right, k_space_bottom_to_top -outletv "outbformat", a_bsignal -outleta "out", a_spatial_reverb_send -#else -a_out_left, a_out_right pan2 a_signal, p1/6 -outleta "outleft", a_out_left * gk_YiString_reverb_send -outleta "outright", a_out_right * gk_YiString_reverb_send -outleta "chorusleft", a_out_left * gk_YiString_chorus_send -outleta "chorusright", a_out_right * gk_YiString_chorus_send -;printks "YiString %9.4f %9.4f\n", 0.5, a_out_left, a_out_right -#endif -prints "YiString i %9.4f t %9.4f d %9.4f k %9.4f v %9.4f p %9.4f #%3d\n", p1, p2, p3, p4, p5, p1/6, active(p1) -endin - -gk_Bower_level chnexport "gk_Bower_level", 3 -gk_Bower_pan chnexport "gk_Bower_pan", 3 -gi_Bower_minimum_hz chnexport "gi_Bower_minimum_hz", 3 -gk_Bower_bow_pressure chnexport "gk_Bower_bow_pressure", 3 -gk_Bower_bow_position chnexport "gk_Bower_bow_position", 3 -gk_Bower_vibrato_hz chnexport "gk_Bower_vibrato_hz", 3 -gk_Bower_vibrato_amplitude chnexport "gk_Bower_vibrato_amplitude", 3 -gi_Bower_sine ftgen 0,0,65537,10,1 -gk_Bower_level init -30 -gk_Bower_bow_pressure init 4.1 -gk_Bower_bow_position init .148 -gi_Bower_minimum_hz init 30 -instr Bower -i_instrument = p1 -i_time = p2 -i_duration = p3 -i_midi_key = p4 -i_midi_velocity = p5 -i_phase = p6 -i_pan = p7 -i_amplitude = ampdb(i_midi_velocity) * 500 -i_amplitude ampmidicurve i_midi_velocity, gi_ampmidicurve_dynamic_range, gi_ampmidicurve_exponent -i_amplitude *= 50000 - -i_attack = p3 * (1 / 4) * (4 / 3) -i_sustain = p3 * (1 / 2) * (4 / 3) -i_release = p3 * (1 / 4) * (4 / 3) -p3 = i_attack + i_sustain + i_release -k_envelope transeg 0.0, i_attack / 2.0, 1.5, i_amplitude / 2.0, i_attack / 2.0, -1.5, i_amplitude, i_sustain, 0.0, i_amplitude, i_release / 2.0, 1.5, i_amplitude / 2.0, i_release / 2.0, -1.5, 0 -i_frequency = cpsmidinn(i_midi_key) -kamp = k_envelope -kfreq = i_frequency -kpres = gk_Bower_bow_pressure -; krat rspline 0.006,0.988,0.1,0.4 -krat rspline 0.006,0.988,1,4 -krat = gk_Bower_bow_position -kvibf = gk_Bower_vibrato_hz -kvibamp = gk_Bower_vibrato_amplitude -iminfreq = gi_Bower_minimum_hz -aSig wgbow kamp,kfreq,kpres,krat,kvibf,kvibamp,gi_Bower_sine,iminfreq -k_gain = ampdb(gk_Bower_level) -aSig = aSig * k_gain -;aSig butlp aSig,2000 -;aSig pareq aSig,80,6,0.707 -a_left, a_right pan2 aSig / 7, i_pan -a_damping linseg 0, 0.03, 1, p3 - 0.1, 1, 0.07, 0 -a_left = a_damping * a_left -a_right = a_damping * a_right -outleta "outleft", a_left -outleta "outright", a_right -prints "%-24.24s i %9.4f t %9.4f d %9.4f k %9.4f v %9.4f p %9.4f #%3d\n", nstrstr(p1), p1, p2, p3, p4, p5, p7, active(p1) -endin - -gk_Harpsichord_level init 0 -gk_Harpsichord_pick init .275 -gk_Harpsichord_reflection init .75 -gk_Harpsichord_pluck init .5 -giharptable ftgen 0, 0, 65536, 7, -1, 1024, 1, 1024, -1 -instr Harpsichord -if p3 == -1 goto indefinite -goto non_indefinite -indefinite: - p3 = 1000000 -non_indefinite: -i_instrument = p1 -i_time = p2 -i_duration = p3 -i_midi_key = p4 -i_midi_velocity = p5 -k_space_front_to_back = p6 -k_space_left_to_right = .2 -k_space_bottom_to_top = p8 -i_phase = p9 -i_amplitude ampmidicurve i_midi_velocity, gi_ampmidicurve_dynamic_range, gi_ampmidicurve_exponent -k_gain = ampdb(gk_Harpsichord_level) -iHz = cpsmidinn(i_midi_key) -kHz = k(iHz) -aenvelope transeg 1.0, 20.0, -10.0, 0.05 -k_amplitude = 1 -apluck pluck 1, kHz, iHz, 0, 1 -aharp poscil 1, kHz, giharptable -aharp2 balance apluck, aharp -a_signal = (apluck + aharp2) -i_attack = .002 -i_sustain = p3 -i_release = 0.01 -p3 = i_attack + i_sustain + i_release -a_declicking linsegr 0, i_attack, 1, i_sustain, 1, i_release, 0 -a_signal = a_signal * i_amplitude * a_declicking * k_gain -#ifdef USE_SPATIALIZATION -a_spatial_reverb_send init 0 -a_bsignal[] init 16 -a_bsignal, a_spatial_reverb_send Spatialize a_signal, k_space_front_to_back, k_space_left_to_right, k_space_bottom_to_top -outletv "outbformat", a_bsignal -outleta "out", a_spatial_reverb_send -#else -a_out_left, a_out_right pan2 a_signal, p1/6 -outleta "outleft", a_out_left -outleta "outright", a_out_right -#endif -; printks "Harpsichord %9.4f %9.4f\n", 0.5, a_out_left, a_out_right -prints "Harpsichord i %9.4f t %9.4f d %9.4f k %9.4f v %9.4f p %9.4f #%3d\n", p1, p2, p3, p4, p5, p1/6, active(p1) -kpbend pchbend 2 -printks2 "pchbend %9.4f\n", kpbend -kmodw midictrl 1 -printks2 "kmodw %9.4f\n", kmodw -kctl6 midictrl 6 -printks2 "kctl6 %9.4f\n", kctl6 -kctl4 midictrl 4 -printks2 "kctl4 %9.4f\n", kctl4 -kctl5 midictrl 5 -printks2 "kctl5 %9.4f\n", kctl5 -kafter aftouch 1 -printks2 "kafter %9.4f\n", kafter - -endin - -gk_Reverb_feedback init 0.85 -gi_Reverb_delay_modulation init 0.05 -gk_Reverb_frequency_cutoff init 15000 -instr ReverbSC -aleftout init 0 -arightout init 0 -aleft inleta "inleft" -aright inleta "inright" -; aoutL, aoutR reverbsc ainL, ainR, kfblvl, kfco[, israte[, ipitchm[, iskip]]] -aleftout, arightout reverbsc aleft, aright, gk_Reverb_feedback, gk_Reverb_frequency_cutoff, sr, gi_Reverb_delay_modulation -outleta "outleft", aleftout -outleta "outright", arightout -prints "ReverbSC i %9.4f t %9.4f d %9.4f k %9.4f v %9.4f p %9.4f #%3d\ -", p1, p2, p3, p4, p5, p1/6, active(p1) -endin - -gk_MasterOutput_level init -15 -gS_MasterOutput_filename init "" -instr MasterOutput -aleft inleta "inleft" -aright inleta "inright" -k_gain = ampdb(gk_MasterOutput_level) -printks2 "Master gain: %f\n", k_gain -iamp init 1 -iattack init .01 -idecay init 10 -isustain = 2400 - (iattack + idecay) -aenvelope transeg 0.0, iattack / 2.0, 1.5, iamp / 2.0, iattack / 2.0, -1.5, iamp, isustain, 0.0, iamp, idecay / 2.0, 1.5, iamp / 2.0, idecay / 2.0, -1.5, 0 -aleft butterlp aleft, 18000 -aright butterlp aright, 18000 -outs aleft * k_gain * aenvelope, aright * k_gain * aenvelope -; We want something that will play on my phone. -i_amplitude_adjustment = ampdbfs(-3) / 32767 -i_filename_length strlen gS_MasterOutput_filename -if i_filename_length > 0 goto has_filename -goto non_has_filename -has_filename: -prints sprintf("Output filename: %s\n", gS_MasterOutput_filename) -fout gS_MasterOutput_filename, 18, aleft * i_amplitude_adjustment, aright * i_amplitude_adjustment -non_has_filename: -prints "MasterOutput i %9.4f t %9.4f d %9.4f k %9.4f v %9.4f p %9.4f #%3d\n", p1, p2, p3, p4, p5, p1/6, active(p1) -kstatus, kchan, kdata1, kdata2 midiin -;printf " midi in s %4d c %4d %4d %4d\n", kdata2, kstatus, kchan, kdata1, kdata2 -endin - - - -i 1 0 3.2 40 95 0 0 0 0 4095 1 -i 1 0 3.2 47 95 0 0 0 0 4095 1 -i 1 0 0.8 56 95 0 0 0 0 4095 1 -i 1 0.8 0.4 54 95 0 0 0 0 4095 1 -i 1 1.2 0.4 56 95 0 0 0 0 4095 1 -i 1 1.6 0.8 59 95 0 0 0 0 4095 1 -i 1 2.4 0.8 47 95 0 0 0 0 4095 1 -i 1 3.2 3.2 40 95 0 0 0 0 4095 1 -i 1 3.2 3.2 45 95 0 0 0 0 4095 1 -i 1 3.2 0.4 50 95 0 0 0 0 4095 1 -i 1 3.6 0.4 52 95 0 0 0 0 4095 1 -i 1 4 0.8 47 95 0 0 0 0 4095 1 -i 1 4.8 0.4 50 95 0 0 0 0 4095 1 -i 1 5.2 0.4 52 95 0 0 0 0 4095 1 -i 1 5.6 0.8 47 95 0 0 0 0 4095 1 -i 1 6.4 3.2 40 95 0 0 0 0 4095 1 -i 1 6.4 3.2 47 95 0 0 0 0 4095 1 -i 1 6.4 0.8 56 95 0 0 0 0 4095 1 -i 1 7.2 0.4 54 95 0 0 0 0 4095 1 -i 1 7.6 0.4 56 95 0 0 0 0 4095 1 -i 1 8 0.4 59 95 0 0 0 0 4095 1 -i 1 8.4 0.4 56 95 0 0 0 0 4095 1 -i 1 8.8 0.4 52 95 0 0 0 0 4095 1 -i 1 9.2 0.4 47 95 0 0 0 0 4095 1 -i 1 9.6 3.2 38 95 0 0 0 0 4095 1 -i 1 9.6 3.2 42 95 0 0 0 0 4095 1 -i 1 9.6 3.2 45 95 0 0 0 0 4095 1 -i 1 9.6 3.2 50 95 0 0 0 0 4095 1 -i 1 11.2 1.6 14 95 0 0 0 0 4095 1 -i 1 11.2 1.6 26 95 0 0 0 0 4095 1 -i 1 12.8 3.2 38 95 0 0 0 0 4095 1 -i 1 12.8 3.2 41 95 0 0 0 0 4095 1 -i 1 12.8 3.2 45 95 0 0 0 0 4095 1 -i 1 12.8 0.8 53 95 0 0 0 0 4095 1 -i 1 13.6 0.4 55 95 0 0 0 0 4095 1 -i 1 14 0.4 57 95 0 0 0 0 4095 1 -i 1 14.4 0.8 64 95 0 0 0 0 4095 1 -i 1 15.2 0.8 45 95 0 0 0 0 4095 1 -i 1 16 3.2 36 95 0 0 0 0 4095 1 -i 1 16 3.2 41 95 0 0 0 0 4095 1 -i 1 16 3.2 45 95 0 0 0 0 4095 1 -i 1 16 0.4 50 95 0 0 0 0 4095 1 -i 1 16.4 0.4 52 95 0 0 0 0 4095 1 -i 1 16.8 0.8 45 95 0 0 0 0 4095 1 -i 1 17.6 0.8 50 95 0 0 0 0 4095 1 -i 1 18.4 0.8 53 95 0 0 0 0 4095 1 -i 1 19.2 3.2 35 95 0 0 0 0 4095 1 -i 1 19.2 3.2 40 95 0 0 0 0 4095 1 -i 1 19.2 3.2 44 95 0 0 0 0 4095 1 -i 1 19.2 0.8 52 95 0 0 0 0 4095 1 -i 1 20 0.8 52 95 0 0 0 0 4095 1 -i 1 20.8 0.8 47 95 0 0 0 0 4095 1 -i 1 21.6 0.8 47 95 0 0 0 0 4095 1 -i 1 22.4 3.2 36 95 0 0 0 0 4095 1 -i 1 22.4 3.2 40 95 0 0 0 0 4095 1 -i 1 22.4 3.2 45 95 0 0 0 0 4095 1 -i 1 24 1.6 21 95 0 0 0 0 4095 1 -i 1 25.6 3.2 36 95 0 0 0 0 4095 1 -i 1 25.6 3.2 40 95 0 0 0 0 4095 1 -i 1 25.6 3.2 45 95 0 0 0 0 4095 1 -i 1 25.6 1.2 60 95 0 0 0 0 4095 1 -i 1 26.8 0.4 60 95 0 0 0 0 4095 1 -i 1 27.2 0.8 59 95 0 0 0 0 4095 1 -i 1 28 0.8 55 95 0 0 0 0 4095 1 -i 1 28.8 3.2 36 95 0 0 0 0 4095 1 -i 1 28.8 3.2 40 95 0 0 0 0 4095 1 -i 1 28.8 3.2 43 95 0 0 0 0 4095 1 -i 1 28.8 0.8 60 95 0 0 0 0 4095 1 -i 1 29.6 0.8 60 95 0 0 0 0 4095 1 -i 1 30.4 0.8 60 95 0 0 0 0 4095 1 -i 1 31.2 0.8 62 95 0 0 0 0 4095 1 -i 1 32 3.2 36 95 0 0 0 0 4095 1 -i 1 32 3.2 41 95 0 0 0 0 4095 1 -i 1 32 3.2 45 95 0 0 0 0 4095 1 -i 1 32 1.2 60 95 0 0 0 0 4095 1 -i 1 33.2 0.4 60 95 0 0 0 0 4095 1 -i 1 33.6 0.8 59 95 0 0 0 0 4095 1 -i 1 34.4 0.8 55 95 0 0 0 0 4095 1 -i 1 35.2 3.2 36 95 0 0 0 0 4095 1 -i 1 35.2 3.2 40 95 0 0 0 0 4095 1 -i 1 35.2 3.2 45 95 0 0 0 0 4095 1 -i 1 35.2 3.2 57 95 0 0 0 0 4095 1 -i 1 36.8 1.6 21 95 0 0 0 0 4095 1 -i 1 38.4 3.2 36 95 0 0 0 0 4095 1 -i 1 38.4 3.2 40 95 0 0 0 0 4095 1 -i 1 38.4 3.2 45 95 0 0 0 0 4095 1 -i 1 38.4 1.2 60 95 0 0 0 0 4095 1 -i 1 39.6 0.4 60 95 0 0 0 0 4095 1 -i 1 40 0.8 59 95 0 0 0 0 4095 1 -i 1 40.8 0.8 55 95 0 0 0 0 4095 1 -i 1 41.6 3.2 35 95 0 0 0 0 4095 1 -i 1 41.6 3.2 40 95 0 0 0 0 4095 1 -i 1 41.6 3.2 43 95 0 0 0 0 4095 1 -i 1 41.6 0.8 64 95 0 0 0 0 4095 1 -i 1 42.4 0.8 64 95 0 0 0 0 4095 1 -i 1 43.2 1.6 16 95 0 0 0 0 4095 1 -i 1 43.2 0.8 62 95 0 0 0 0 4095 1 -i 1 44 0.8 59 95 0 0 0 0 4095 1 -i 1 44.8 1.6 21 95 0 0 0 0 4095 1 -i 1 44.8 1.6 33 95 0 0 0 0 4095 1 -i 1 44.8 1.6 36 95 0 0 0 0 4095 1 -i 1 44.8 1.6 41 95 0 0 0 0 4095 1 -i 1 44.8 1.6 45 95 0 0 0 0 4095 1 -i 1 44.8 0.8 57 95 0 0 0 0 4095 1 -i 1 45.6 0.8 57 95 0 0 0 0 4095 1 -i 1 46.4 1.6 19 95 0 0 0 0 4095 1 -i 1 46.4 1.6 31 95 0 0 0 0 4095 1 -i 1 46.4 1.6 38 95 0 0 0 0 4095 1 -i 1 46.4 1.6 43 95 0 0 0 0 4095 1 -i 1 46.4 1.6 47 95 0 0 0 0 4095 1 -i 1 46.4 0.8 59 95 0 0 0 0 4095 1 -i 1 47.2 0.8 62 95 0 0 0 0 4095 1 -i 1 48 1.6 16 95 0 0 0 0 4095 1 -i 1 48 1.6 28 95 0 0 0 0 4095 1 -i 1 48 1.6 36 95 0 0 0 0 4095 1 -i 1 48 1.6 40 95 0 0 0 0 4095 1 -i 1 48 1.6 45 95 0 0 0 0 4095 1 -i 1 48 0.8 60 95 0 0 0 0 4095 1 -i 1 48.8 0.8 60 95 0 0 0 0 4095 1 -i 1 49.6 1.6 14 95 0 0 0 0 4095 1 -i 1 49.6 1.6 26 95 0 0 0 0 4095 1 -i 1 49.6 1.6 38 95 0 0 0 0 4095 1 -i 1 49.6 1.6 41 95 0 0 0 0 4095 1 -i 1 49.6 1.6 45 95 0 0 0 0 4095 1 -i 1 49.6 0.8 62 95 0 0 0 0 4095 1 -i 1 50.4 0.8 65 95 0 0 0 0 4095 1 -i 1 51.2 3.2 40 95 0 0 0 0 4095 1 -i 1 51.2 3.2 47 95 0 0 0 0 4095 1 -i 1 51.2 0.8 68 95 0 0 0 0 4095 1 -i 1 52 0.4 66 95 0 0 0 0 4095 1 -i 1 52.4 0.4 68 95 0 0 0 0 4095 1 -i 1 52.8 0.4 71 95 0 0 0 0 4095 1 -i 1 53.2 0.4 68 95 0 0 0 0 4095 1 -i 1 53.6 0.4 64 95 0 0 0 0 4095 1 -i 1 54 0.4 59 95 0 0 0 0 4095 1 -i 1 54.4 3.2 40 95 0 0 0 0 4095 1 -i 1 54.4 3.2 45 95 0 0 0 0 4095 1 -i 1 54.4 0.4 62 95 0 0 0 0 4095 1 -i 1 54.8 0.4 64 95 0 0 0 0 4095 1 -i 1 55.2 0.8 59 95 0 0 0 0 4095 1 -i 1 56 0.4 62 95 0 0 0 0 4095 1 -i 1 56.4 0.4 64 95 0 0 0 0 4095 1 -i 1 56.8 0.8 59 95 0 0 0 0 4095 1 -i 1 57.6 3.2 40 95 0 0 0 0 4095 1 -i 1 57.6 3.2 47 95 0 0 0 0 4095 1 -i 1 57.6 0.8 56 95 0 0 0 0 4095 1 -i 1 58.4 0.4 54 95 0 0 0 0 4095 1 -i 1 58.8 0.4 56 95 0 0 0 0 4095 1 -i 1 59.2 0.4 59 95 0 0 0 0 4095 1 -i 1 59.6 0.4 56 95 0 0 0 0 4095 1 -i 1 60 0.4 52 95 0 0 0 0 4095 1 -i 1 60.4 0.4 47 95 0 0 0 0 4095 1 -i 1 60.8 3.2 38 95 0 0 0 0 4095 1 -i 1 60.8 3.2 42 95 0 0 0 0 4095 1 -i 1 60.8 3.2 45 95 0 0 0 0 4095 1 -i 1 60.8 3.2 50 95 0 0 0 0 4095 1 -i 1 62.4 1.6 14 95 0 0 0 0 4095 1 -i 1 62.4 1.6 26 95 0 0 0 0 4095 1 -i 1 64 3.2 38 95 0 0 0 0 4095 1 -i 1 64 3.2 41 95 0 0 0 0 4095 1 -i 1 64 3.2 45 95 0 0 0 0 4095 1 -i 1 64 0.8 53 95 0 0 0 0 4095 1 -i 1 64.8 0.4 55 95 0 0 0 0 4095 1 -i 1 65.2 0.4 57 95 0 0 0 0 4095 1 -i 1 65.6 0.4 64 95 0 0 0 0 4095 1 -i 1 66 0.4 57 95 0 0 0 0 4095 1 -i 1 66.4 0.4 50 95 0 0 0 0 4095 1 -i 1 66.8 0.4 45 95 0 0 0 0 4095 1 -i 1 67.2 3.2 36 95 0 0 0 0 4095 1 -i 1 67.2 3.2 41 95 0 0 0 0 4095 1 -i 1 67.2 3.2 45 95 0 0 0 0 4095 1 -i 1 67.2 0.4 50 95 0 0 0 0 4095 1 -i 1 67.6 0.4 52 95 0 0 0 0 4095 1 -i 1 68 0.8 45 95 0 0 0 0 4095 1 -i 1 68.8 0.8 50 95 0 0 0 0 4095 1 -i 1 69.6 0.8 53 95 0 0 0 0 4095 1 -i 1 70.4 3.2 35 95 0 0 0 0 4095 1 -i 1 70.4 3.2 40 95 0 0 0 0 4095 1 -i 1 70.4 3.2 44 95 0 0 0 0 4095 1 -i 1 70.4 0.8 52 95 0 0 0 0 4095 1 -i 1 71.2 0.8 52 95 0 0 0 0 4095 1 -i 1 72 1.6 16 95 0 0 0 0 4095 1 -i 1 72 1.6 28 95 0 0 0 0 4095 1 -i 1 72 0.8 47 95 0 0 0 0 4095 1 -i 1 72.8 0.8 47 95 0 0 0 0 4095 1 -i 1 73.6 3.2 36 95 0 0 0 0 4095 1 -i 1 73.6 3.2 40 95 0 0 0 0 4095 1 -i 1 73.6 3.2 45 95 0 0 0 0 4095 1 -i 1 75.2 1.6 21 95 0 0 0 0 4095 1 -i 1 76.8 3.2 36 95 0 0 0 0 4095 1 -i 1 76.8 3.2 40 95 0 0 0 0 4095 1 -i 1 76.8 3.2 45 95 0 0 0 0 4095 1 -i 1 76.8 1.2 60 95 0 0 0 0 4095 1 -i 1 78 0.4 60 95 0 0 0 0 4095 1 -i 1 78.4 0.8 59 95 0 0 0 0 4095 1 -i 1 79.2 0.8 55 95 0 0 0 0 4095 1 -i 1 80 3.2 36 95 0 0 0 0 4095 1 -i 1 80 3.2 40 95 0 0 0 0 4095 1 -i 1 80 3.2 43 95 0 0 0 0 4095 1 -i 1 80 0.8 60 95 0 0 0 0 4095 1 -i 1 80.8 0.8 60 95 0 0 0 0 4095 1 -i 1 81.6 0.8 60 95 0 0 0 0 4095 1 -i 1 82.4 0.8 62 95 0 0 0 0 4095 1 -i 1 83.2 3.2 36 95 0 0 0 0 4095 1 -i 1 83.2 3.2 41 95 0 0 0 0 4095 1 -i 1 83.2 3.2 45 95 0 0 0 0 4095 1 -i 1 83.2 1.2 57 95 0 0 0 0 4095 1 -i 1 84.4 0.4 57 95 0 0 0 0 4095 1 -i 1 84.8 0.8 59 95 0 0 0 0 4095 1 -i 1 85.6 0.8 55 95 0 0 0 0 4095 1 -i 1 86.4 3.2 36 95 0 0 0 0 4095 1 -i 1 86.4 3.2 40 95 0 0 0 0 4095 1 -i 1 86.4 3.2 45 95 0 0 0 0 4095 1 -i 1 86.4 3.2 57 95 0 0 0 0 4095 1 -i 1 88 1.6 21 95 0 0 0 0 4095 1 -i 1 89.6 3.2 36 95 0 0 0 0 4095 1 -i 1 89.6 3.2 40 95 0 0 0 0 4095 1 -i 1 89.6 3.2 45 95 0 0 0 0 4095 1 -i 1 89.6 1.2 60 95 0 0 0 0 4095 1 -i 1 90.8 0.4 60 95 0 0 0 0 4095 1 -i 1 91.2 0.8 59 95 0 0 0 0 4095 1 -i 1 92 0.8 55 95 0 0 0 0 4095 1 -i 1 92.8 3.2 35 95 0 0 0 0 4095 1 -i 1 92.8 3.2 40 95 0 0 0 0 4095 1 -i 1 92.8 3.2 43 95 0 0 0 0 4095 1 -i 1 92.8 0.8 64 95 0 0 0 0 4095 1 -i 1 93.6 0.8 64 95 0 0 0 0 4095 1 -i 1 94.4 1.6 16 95 0 0 0 0 4095 1 -i 1 94.4 0.8 62 95 0 0 0 0 4095 1 -i 1 95.2 0.8 59 95 0 0 0 0 4095 1 -i 1 96 1.6 36 95 0 0 0 0 4095 1 -i 1 96 1.6 41 95 0 0 0 0 4095 1 -i 1 96 1.6 45 95 0 0 0 0 4095 1 -i 1 96 0.8 57 95 0 0 0 0 4095 1 -i 1 96.8 0.8 57 95 0 0 0 0 4095 1 -i 1 97.6 1.6 38 95 0 0 0 0 4095 1 -i 1 97.6 1.6 43 95 0 0 0 0 4095 1 -i 1 97.6 1.6 47 95 0 0 0 0 4095 1 -i 1 97.6 0.8 59 95 0 0 0 0 4095 1 -i 1 98.4 0.8 62 95 0 0 0 0 4095 1 -i 1 99.2 1.6 36 95 0 0 0 0 4095 1 -i 1 99.2 1.6 40 95 0 0 0 0 4095 1 -i 1 99.2 1.6 45 95 0 0 0 0 4095 1 -i 1 99.2 0.8 60 95 0 0 0 0 4095 1 -i 1 100 0.8 60 95 0 0 0 0 4095 1 -i 1 100.8 1.6 38 95 0 0 0 0 4095 1 -i 1 100.8 1.6 41 95 0 0 0 0 4095 1 -i 1 100.8 1.6 45 95 0 0 0 0 4095 1 -i 1 100.8 0.8 62 95 0 0 0 0 4095 1 -i 1 101.6 0.8 65 95 0 0 0 0 4095 1 -i 1 102.4 3.2 40 95 0 0 0 0 4095 1 -i 1 102.4 3.2 47 95 0 0 0 0 4095 1 -i 1 102.4 0.8 56 95 0 0 0 0 4095 1 -i 1 103.2 0.4 54 95 0 0 0 0 4095 1 -i 1 103.6 0.4 56 95 0 0 0 0 4095 1 -i 1 104 1.6 16 95 0 0 0 0 4095 1 -i 1 104 0.4 59 95 0 0 0 0 4095 1 -i 1 104.4 0.4 56 95 0 0 0 0 4095 1 -i 1 104.8 0.4 52 95 0 0 0 0 4095 1 -i 1 105.2 0.4 47 95 0 0 0 0 4095 1 -i 1 105.6 3.2 40 95 0 0 0 0 4095 1 -i 1 105.6 3.2 45 95 0 0 0 0 4095 1 -i 1 105.6 0.4 50 95 0 0 0 0 4095 1 -i 1 106 0.4 52 95 0 0 0 0 4095 1 -i 1 106.4 0.8 47 95 0 0 0 0 4095 1 -i 1 107.2 1.6 21 95 0 0 0 0 4095 1 -i 1 107.2 0.4 50 95 0 0 0 0 4095 1 -i 1 107.6 0.4 52 95 0 0 0 0 4095 1 -i 1 108 0.8 47 95 0 0 0 0 4095 1 -i 1 108.8 3.2 40 95 0 0 0 0 4095 1 -i 1 108.8 3.2 47 95 0 0 0 0 4095 1 -i 1 108.8 0.8 56 95 0 0 0 0 4095 1 -i 1 109.6 0.4 54 95 0 0 0 0 4095 1 -i 1 110 0.4 56 95 0 0 0 0 4095 1 -i 1 110.4 1.6 16 95 0 0 0 0 4095 1 -i 1 110.4 0.4 59 95 0 0 0 0 4095 1 -i 1 110.8 0.4 56 95 0 0 0 0 4095 1 -i 1 111.2 0.4 52 95 0 0 0 0 4095 1 -i 1 111.6 0.4 47 95 0 0 0 0 4095 1 -i 1 112 3.2 38 95 0 0 0 0 4095 1 -i 1 112 3.2 42 95 0 0 0 0 4095 1 -i 1 112 3.2 45 95 0 0 0 0 4095 1 -i 1 113.6 1.6 14 95 0 0 0 0 4095 1 -i 1 115.2 3.2 38 95 0 0 0 0 4095 1 -i 1 115.2 3.2 41 95 0 0 0 0 4095 1 -i 1 115.2 3.2 45 95 0 0 0 0 4095 1 -i 1 115.2 0.8 53 95 0 0 0 0 4095 1 -i 1 116 0.4 55 95 0 0 0 0 4095 1 -i 1 116.4 0.4 57 95 0 0 0 0 4095 1 -i 1 116.8 1.6 14 95 0 0 0 0 4095 1 -i 1 116.8 0.4 64 95 0 0 0 0 4095 1 -i 1 117.2 0.4 57 95 0 0 0 0 4095 1 -i 1 117.6 0.4 50 95 0 0 0 0 4095 1 -i 1 118 0.4 45 95 0 0 0 0 4095 1 -i 1 118.4 3.2 36 95 0 0 0 0 4095 1 -i 1 118.4 3.2 41 95 0 0 0 0 4095 1 -i 1 118.4 3.2 45 95 0 0 0 0 4095 1 -i 1 118.4 0.4 50 95 0 0 0 0 4095 1 -i 1 118.8 0.4 52 95 0 0 0 0 4095 1 -i 1 119.2 0.8 45 95 0 0 0 0 4095 1 -i 1 120 1.6 12 95 0 0 0 0 4095 1 -i 1 120 0.8 50 95 0 0 0 0 4095 1 -i 1 120.8 0.8 53 95 0 0 0 0 4095 1 -i 1 121.6 3.2 35 95 0 0 0 0 4095 1 -i 1 121.6 3.2 40 95 0 0 0 0 4095 1 -i 1 121.6 3.2 44 95 0 0 0 0 4095 1 -i 1 121.6 0.8 52 95 0 0 0 0 4095 1 -i 1 122.4 0.8 52 95 0 0 0 0 4095 1 -i 1 123.2 1.6 16 95 0 0 0 0 4095 1 -i 1 123.2 0.8 47 95 0 0 0 0 4095 1 -i 1 124 0.8 47 95 0 0 0 0 4095 1 -i 1 124.8 3.2 36 95 0 0 0 0 4095 1 -i 1 124.8 3.2 40 95 0 0 0 0 4095 1 -i 1 124.8 3.2 45 95 0 0 0 0 4095 1 -i 1 126.4 1.6 21 95 0 0 0 0 4095 1 -i 1 128 3.2 36 95 0 0 0 0 4095 1 -i 1 128 3.2 40 95 0 0 0 0 4095 1 -i 1 128 3.2 45 95 0 0 0 0 4095 1 -i 1 128 0.8 60 95 0 0 0 0 4095 1 -i 1 128.8 0.8 60 95 0 0 0 0 4095 1 -i 1 129.6 0.8 59 95 0 0 0 0 4095 1 -i 1 130.4 0.8 55 95 0 0 0 0 4095 1 -i 1 131.2 3.2 36 95 0 0 0 0 4095 1 -i 1 131.2 3.2 40 95 0 0 0 0 4095 1 -i 1 131.2 3.2 43 95 0 0 0 0 4095 1 -i 1 131.2 0.8 60 95 0 0 0 0 4095 1 -i 1 132 0.8 60 95 0 0 0 0 4095 1 -i 1 132.8 0.8 60 95 0 0 0 0 4095 1 -i 1 133.6 0.8 62 95 0 0 0 0 4095 1 -i 1 134.4 3.2 36 95 0 0 0 0 4095 1 -i 1 134.4 3.2 41 95 0 0 0 0 4095 1 -i 1 134.4 3.2 45 95 0 0 0 0 4095 1 -i 1 134.4 1.2 57 95 0 0 0 0 4095 1 -i 1 135.6 0.4 57 95 0 0 0 0 4095 1 -i 1 136 0.8 59 95 0 0 0 0 4095 1 -i 1 136.8 0.8 55 95 0 0 0 0 4095 1 -i 1 137.6 3.2 36 95 0 0 0 0 4095 1 -i 1 137.6 3.2 40 95 0 0 0 0 4095 1 -i 1 137.6 3.2 45 95 0 0 0 0 4095 1 -i 1 137.6 3.2 57 95 0 0 0 0 4095 1 -i 1 139.2 1.6 21 95 0 0 0 0 4095 1 -i 1 140.8 3.2 36 95 0 0 0 0 4095 1 -i 1 140.8 3.2 40 95 0 0 0 0 4095 1 -i 1 140.8 3.2 45 95 0 0 0 0 4095 1 -i 1 140.8 1.2 60 95 0 0 0 0 4095 1 -i 1 142 0.4 60 95 0 0 0 0 4095 1 -i 1 142.4 0.8 59 95 0 0 0 0 4095 1 -i 1 143.2 0.8 55 95 0 0 0 0 4095 1 -i 1 144 3.2 35 95 0 0 0 0 4095 1 -i 1 144 3.2 40 95 0 0 0 0 4095 1 -i 1 144 3.2 43 95 0 0 0 0 4095 1 -i 1 144 0.8 64 95 0 0 0 0 4095 1 -i 1 144.8 0.8 64 95 0 0 0 0 4095 1 -i 1 145.6 1.6 16 95 0 0 0 0 4095 1 -i 1 145.6 0.8 62 95 0 0 0 0 4095 1 -i 1 146.4 0.8 59 95 0 0 0 0 4095 1 -i 1 147.2 1.6 36 95 0 0 0 0 4095 1 -i 1 147.2 1.6 41 95 0 0 0 0 4095 1 -i 1 147.2 1.6 45 95 0 0 0 0 4095 1 -i 1 147.2 0.8 57 95 0 0 0 0 4095 1 -i 1 148 0.8 57 95 0 0 0 0 4095 1 -i 1 148.8 1.6 38 95 0 0 0 0 4095 1 -i 1 148.8 1.6 43 95 0 0 0 0 4095 1 -i 1 148.8 1.6 47 95 0 0 0 0 4095 1 -i 1 148.8 0.8 59 95 0 0 0 0 4095 1 -i 1 149.6 0.8 62 95 0 0 0 0 4095 1 -i 1 150.4 1.6 36 95 0 0 0 0 4095 1 -i 1 150.4 1.6 40 95 0 0 0 0 4095 1 -i 1 150.4 1.6 45 95 0 0 0 0 4095 1 -i 1 150.4 0.8 60 95 0 0 0 0 4095 1 -i 1 151.2 0.8 60 95 0 0 0 0 4095 1 -i 1 152 1.6 38 95 0 0 0 0 4095 1 -i 1 152 1.6 41 95 0 0 0 0 4095 1 -i 1 152 1.6 45 95 0 0 0 0 4095 1 -i 1 152 0.8 62 95 0 0 0 0 4095 1 -i 1 152.8 0.8 65 95 0 0 0 0 4095 1 -i 1 153.6 3.2 40 95 0 0 0 0 4095 1 -i 1 153.6 3.2 45 95 0 0 0 0 4095 1 -i 1 153.6 3.2 48 95 0 0 0 0 4095 1 -i 1 153.6 1.6 64 95 0 0 0 0 4095 1 -i 1 155.2 1.6 16 95 0 0 0 0 4095 1 -i 1 156 0.8 64 95 0 0 0 0 4095 1 -i 1 156.8 3.2 35 95 0 0 0 0 4095 1 -i 1 156.8 3.2 40 95 0 0 0 0 4095 1 -i 1 156.8 3.2 44 95 0 0 0 0 4095 1 -i 1 156.8 1.6 56 95 0 0 0 0 4095 1 -i 1 158.4 1.6 16 95 0 0 0 0 4095 1 -i 1 158.4 1.6 59 95 0 0 0 0 4095 1 -i 1 160 0.8 57 95 0 0 0 0 4095 1 -i 1 160.8 0.4 55 95 0 0 0 0 4095 1 -i 1 161.2 0.4 57 95 0 0 0 0 4095 1 -i 1 161.6 0.4 60 95 0 0 0 0 4095 1 -i 1 162 0.4 57 95 0 0 0 0 4095 1 -i 1 162.4 0.4 52 95 0 0 0 0 4095 1 -i 1 162.8 0.4 48 95 0 0 0 0 4095 1 -i 1 163.2 0.8 60 95 0 0 0 0 4095 1 -i 1 164 0.8 57 95 0 0 0 0 4095 1 -i 1 164.8 0.8 52 95 0 0 0 0 4095 1 -i 1 165.6 0.8 60 95 0 0 0 0 4095 1 -i 1 166.4 25.6 36 95 0 0 0 0 4095 1 -i 1 166.4 3.2 40 95 0 0 0 0 4095 1 -i 1 166.4 3.2 45 95 0 0 0 0 4095 1 -i 1 166.4 3.2 57 95 0 0 0 0 4095 1 -i 1 188.8 3.2 21 95 0 0 0 0 4095 1 - -e 5 - - diff --git a/playpen/playpen.ini b/playpen/playpen.ini index efad008a9d..2fb9bd4baa 100644 --- a/playpen/playpen.ini +++ b/playpen/playpen.ini @@ -1,4 +1,4 @@ -### Here are user-specific settings for the computer music 'playpen.py' program. +# Here are user-specific settings for the computer music 'playpen.py' program. # The first priority is 'playpen.ini' in the current working directory, then # the Free Desktop standard '$XDG_CONFIG_HOME/.config/playpen/playpen.ini', # then the Free Desktop fallback '$HOME/.config/playpen/playpen.ini'. @@ -20,7 +20,7 @@ license=ASCAP [csound] -audio-output=dac:plughw:2,0 +audio-output=dac # Other settings. @@ -38,10 +38,10 @@ verbose=False [cplusplus] # Uncomment for your platform. -# Darwin: -# compiler-command = c++ {} -v --std=gnu++17 -lstdc++ -O3 -g -Wno-write-strings -I. -I/Library/Frameworks/CsoundLib64.framework/Versions/6.0/Headers -I/usr/local/include -I/usr/local/include/csound -I/opt/homebrew/include -I/opt/homebrew/include/eigen3 -I/opt/homebrew/Cellar/opencv/4.5.4_3/include/opencv4 -I/opt/homebrew/opt/boost/include -I/opt/local/include /Library/Frameworks/CsoundLib64.framework/Versions/6.0/CsoundLib64 -Wl,-rpath,/usr/local/lib -L/usr/local/lib -L/opt/homebrew/lib -lCsoundAC -lsndfile -lgc -lpthread -ldl -lm +# Darwin needs apps to set rpath: +compiler-command = c++ {} -v --std=gnu++17 -lstdc++ -O3 -g -Wno-deprecated-declarations -Wno-write-strings -I. -I/Library/Frameworks/CsoundLib64.framework/Versions/6.0/Headers -I/usr/local/include -I/usr/local/include/csound -I/opt/homebrew/include -I/opt/homebrew/include/eigen3 -I/opt/homebrew/Cellar/opencv/4.5.4_3/include/opencv4 -I/opt/homebrew/opt/boost/include -I/opt/local/include /Library/Frameworks/CsoundLib64.framework/Versions/6.0/CsoundLib64 -Wl,-rpath,/usr/local/lib -L/usr/local/lib -L/opt/homebrew/lib -lCsoundAC -lsndfile -lgc -lpthread -ldl -lm # Linux: -compiler-command = c++ -v --std=gnu++17 -lstdc++ -O3 -g -Wno-write-strings -I. -I/usr/local/include -I/usr/local/include -I/usr/include/csound -I/usr/local/include/csound -I/home/mkg/csound/interfaces -I/usr/include/eigen3 -lcsound64 -lCsoundAC -lsndfile -lgc -lpthread -ldl -lm +#compiler-command = c++ -v --std=gnu++17 -lstdc++ -O3 -g -Wno-write-strings -I. -I/usr/local/include -I/usr/local/include -I/usr/include/csound -I/usr/local/include/csound -I/home/mkg/csound/interfaces -I/usr/include/eigen3 -lcsound64 -lCsoundAC -lsndfile -lgc -lpthread -ldl -lm # Windows: # compiler-command = "Not implemented." diff --git a/playpen/playpen.py b/playpen/playpen.py index 69459dcff4..5a6842457e 100755 --- a/playpen/playpen.py +++ b/playpen/playpen.py @@ -134,7 +134,7 @@ directory, basename = os.path.split(source_filepath) rootname, extension = os.path.splitext(basename) title = rootname.replace("-", " ").replace("_", " ") -label = '%s -- %s' % (metadata_author, title) +label = '%s -- %s' % (metadata_author, rootname) label = label.replace(" ", "_") output_filename = label + ".wav" master_filename = '%s.normalized.wav' % label @@ -225,7 +225,7 @@ def post_process(): str_artist = metadata_author str_date = metadata_year str_license = metadata_license - sox_normalize_command = '''sox -S "%s" "%s" gain -n -3''' % (output_filename, master_filename + 'untagged.wav') + sox_normalize_command = '''sox -S "%s" "%s" norm -6''' % (output_filename, master_filename + 'untagged.wav') print('sox_normalize command: ', sox_normalize_command) os.system(sox_normalize_command) tag_wav_command = '''sndfile-metadata-set "%s" --bext-description "%s" --bext-originator "%s" --bext-orig-ref "%s" --str-comment "%s" --str-title "%s" --str-copyright "%s" --str-artist "%s" --str-date "%s" --str-license "%s" "%s"''' % (master_filename + 'untagged.wav', bext_description, bext_originator, bext_orig_ref, str_comment, str_title, str_copyright, str_artist, str_date, str_license, master_filename) diff --git a/tests/Parachronic-Piano.cpp b/tests/Parachronic-Piano.cpp deleted file mode 100644 index 18d08ee708..0000000000 --- a/tests/Parachronic-Piano.cpp +++ /dev/null @@ -1,266 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define PI (3.141592653589793238462643383279502884197) -#define TWO_PI (6.283185307179586476925286766559005768394) - -/** - * Generators are lambdas with the same signature as the following example. - * The pen is the current position of a "pen" in the score. The pen is - * "written" by appending it to the score. Additional events can be computed - * based on the parameters of the function, and also appended to the score. - * The function can, and usually does, move the pen to a new position before - * returning it. - */ -auto generator = [](const csound::Event &pen, int depth, csound::Score &score, csound::VoiceleadingNode &voiceleadingNode) -{ - csound::Event result = pen; - return result; -}; - -/** - * Computes a deterministic, finite recurrent iterated function system by - * recursively applying a set of generators (transformations) to a pen - * which represents the position of a "pen" on a "score." The entries in - * the transitions matrix represent open or closed paths of recurrence through - * the tree of calls. Because the pen is passed by value, it is in effect - * copied at each call of a generator and at each layer of recursion. The - * generators may or may not append a local copy of the pen to the score, - * thus "writing" a "note" or other event on the "score." - */ -void recurrent(std::vector< std::function > &generators, - Eigen::MatrixXd &transitions, - int depth, - int transformationIndex, - const csound::Event pen, - csound::Score &score, - csound::VoiceleadingNode &voiceleadingNode) -{ - depth = depth - 1; - if (depth == 0) { - return; - } - // std::printf("recurrent(depth: %3d index: %3d %s)\n", depth, transformationIndex, pen.toString().c_str()); - // Index is that of the current transformation. The column vector at that index determines which - // transformations may be applied. - for (int transitionIndex = 0, transitionN = transitions.rows(); transitionIndex < transitionN; ++transitionIndex) { - if (transitions(transformationIndex, transitionIndex)) { - auto newCursor = generators[transitionIndex](pen, depth, score, voiceleadingNode); - recurrent(generators, transitions, depth, transitionIndex, newCursor, score, voiceleadingNode); - } - } -} - -/** - * All composition and synthesis code is defined in the main function. - * There is no need for any of this code to be in a separate file. - */ -int main(int argc, const char **argv) -{ - csound::MusicModel model; - // These fields determine output filenames and ID 3 tags. - model.setAuthor("Michael Gogins"); - model.setTitle("Parachronic-Piano"); - model.setAlbum("Silence"); - model.setYear("2018"); - model.setPerformanceRightsOrganization("Irreducible Productions, ASCAP"); - - std::vector> generators; - - auto g1 = [](const csound::Event &pen_, int depth, csound::Score &score, csound::VoiceleadingNode &voiceleadingNode) { - csound::Event pen = pen_; - if (depth == 1) { - score.append(pen); - } - if (depth <= 1) { - return pen; - } - pen[csound::Event::TIME] = (pen[csound::Event::TIME] * 0.7600) + 0.2125; - pen[csound::Event::KEY] = (pen[csound::Event::KEY] * 1.0000) + 3.21050; - pen[csound::Event::INSTRUMENT] = 4.0 * 1.0 + double(depth % 4); - pen[csound::Event::VELOCITY] = 1.0; - pen[csound::Event::PAN] = .875; - if (depth == 4) { - //voiceleadingNode.C(pen[csound::Event::TIME], "Dm9"); - voiceleadingNode.Q(pen[csound::Event::TIME], -7); - } - if (depth == 3) { - voiceleadingNode.K(pen[csound::Event::TIME]); - } - return pen; - }; - generators.push_back(g1); - - auto g2 = [](const csound::Event &pen_, int depth, csound::Score &score, csound::VoiceleadingNode &voiceleadingNode) { - csound::Event pen = pen_; - if (depth == 1) { - score.append(pen); - } - if (depth <= 2) { - return pen; - } - pen[csound::Event::TIME] = (pen[csound::Event::TIME] * 0.8500) - 0.2700; - pen[csound::Event::KEY] = (pen[csound::Event::KEY] * 0.5000) + 3.0000; - pen[csound::Event::INSTRUMENT] = 4.0 * 2.0 + double(depth % 4); - pen[csound::Event::VELOCITY] = 2.0; - pen[csound::Event::PAN] = .675; - return pen; - }; - generators.push_back(g2); - - auto g3 = [](const csound::Event &pen_, int depth, csound::Score &score, csound::VoiceleadingNode &voiceleadingNode) { - csound::Event pen = pen_; - if (depth == 1) { - score.append(pen); - } - if (depth <= 1) { - return pen; - } - ///pen[csound::Event::TIME] = pen[csound::Event::TIME] * .65 - .27; - pen[csound::Event::TIME] = (pen[csound::Event::TIME] * 0.7500) - 0.2700; - pen[csound::Event::KEY] = (pen[csound::Event::KEY] * 0.5000) - 3.0700; - pen[csound::Event::INSTRUMENT] = 4.0 * 3.0 + double(depth % 4); - pen[csound::Event::VELOCITY] = 1.0; - pen[csound::Event::PAN] = -.675; - return pen; - }; - generators.push_back(g3); - - auto g4 = [](const csound::Event &pen_, int depth, csound::Score &score, csound::VoiceleadingNode &voiceleadingNode) { - csound::Event pen = pen_; - if (depth == 1) { - score.append(pen); - } - if (depth <= 0) { - return pen; - } - pen[csound::Event::TIME] = (pen[csound::Event::TIME] * 0.7900) + 0.2800; - pen[csound::Event::KEY] = (pen[csound::Event::KEY] * 0.5100) - 4.2500; - pen[csound::Event::INSTRUMENT] = 4.0 * 4.5 + double(depth % 4); - pen[csound::Event::VELOCITY] = 2.0; - pen[csound::Event::PAN] = -.875; - if (depth == 2) { - voiceleadingNode.Q(pen[csound::Event::TIME], -5); - } - if (depth == 3) { - voiceleadingNode.K(pen[csound::Event::TIME]); - } - return pen; - }; - generators.push_back(g4); - - auto g5 = [](const csound::Event &pen_, int depth, csound::Score &score, csound::VoiceleadingNode &voiceleadingNode) { - csound::Event pen = pen_; - if (depth == 1) { - score.append(pen); - } - if (depth <= 0) { - return pen; - } - pen[csound::Event::TIME] = (pen[csound::Event::TIME] * 0.7900) - 0.2900; - pen[csound::Event::KEY] = (pen[csound::Event::KEY] * 0.5000) + 4.0000; - pen[csound::Event::INSTRUMENT] = 4.0 * 3.0 + double(depth % 4); - pen[csound::Event::VELOCITY] = 2.0; - pen[csound::Event::PAN] = -.875; - return pen; - }; - generators.push_back(g5); - - // Generate the score. - csound::Event pen = {1,1,144,0,1,1,0,0,0,0,1}; - pen[csound::Event::DURATION] = 0.025; - Eigen::MatrixXd transitions(generators.size(), generators.size()); - transitions << 1, 1, 0, 1, 1, - 1, 1, 0, 1, 1, - 0, 1, 1, 0, 1, - 1, 0, 1, 1, 1, - 0, 1, 1, 0, 1; - csound::ScoreNode scoreNode; - csound::VoiceleadingNode voiceleadingNode; - voiceleadingNode.setModality({0., 2., 5., 7., 11.}); - voiceleadingNode.rescaleTimes = true; - voiceleadingNode.addChild(&scoreNode); - model.addChild(&voiceleadingNode); - csound::Score &score = scoreNode.getScore(); - recurrent(generators, transitions, 9, 0, pen, score, voiceleadingNode); - std::cout << "Generated duration: " << score.getDuration() << std::endl; - score.rescale(csound::Event::TIME, true, 0.0, false, 0.0); - score.rescale(csound::Event::TIME, true, 0.0, false, 0.0); - score.rescale(csound::Event::INSTRUMENT, true, 1.0, true, 0.0); - score.rescale(csound::Event::KEY, true, 36.0, true, 60.0); - score.rescale(csound::Event::VELOCITY, true, 40.0, true, 0.0); - score.rescale(csound::Event::DURATION, true, .30, true, 1.0); - score.rescale(csound::Event::PAN, true, 0.0, true, 0.0); - std::cout << "Move to origin duration:" << score.getDuration() << std::endl; - score.setDuration(240.0); - std::cout << "set duration: " << score.getDuration() << std::endl; - //score.rescale(csound::Event::DURATION, true, 0.25, true, 0.5); - score.temper(12.); - //score.tieOverlappingNotes(true); - score.findScale(); - score.setDuration(60. * 10.); - std::mt19937 mersenneTwister; - std::uniform_real_distribution<> randomvariable(-0.9, +0.9); - for (int i = 0, n = score.size(); i < n; ++i) { - score[i].setPan(randomvariable(mersenneTwister)); - } - for (int i = 0, n = score.size(); i < n; ++i) { - auto original = score[i]; - csound::Event clone(original); - clone.setTime(original.getTime() + std::sin(original.getTime() / 200.) * 2.); - score.append(clone); - } - score.tieOverlappingNotes(true); - score.sort(); - std::cout << "Final duration: " << score.getDuration() << std::endl; - - model.setCsoundOrchestra(R"( -sr = 48000 -ksmps = 128 -nchnls = 2 - alwayson "PianoOut" - - ; Load the Pianoteq into memory. -gipianoteq vstinit "/home/mkg/Pianoteq 7/x86-64bit/Pianoteq 7.so" - - ; Print information about the Pianoteq, such as parameter names and numbers. - vstinfo gipianoteq - - ; Open the Pianoteq's GUI. - ;vstedit gipianoteq - - ; Send notes from the score to the Pianoteq. - instr 1 - ; MIDI channels are numbered starting at 0. - ; p3 always contains the duration of the note. - ; p4 contains the MIDI key number (pitch), - ; p5 contains the MIDI velocity number (loudness), -imidichannel init 0 - vstnote gipianoteq, imidichannel, p4, p5, p3 - endin - - ; Send parameter changes to the Pianoteq. - instr 2 - ; p4 is the parameter number. - ; p5 is the parameter value. - vstparamset gipianoteq, p4, p5 - endin - - ; Send audio from the Pianoteq to the output. - instr PianoOut -ablankinput init 0 -aleft, aright vstaudio gipianoteq, ablankinput, ablankinput - outs aleft, aright - endin - - )"); - model.processArgv(argc, argv); -} - diff --git a/tests/README.md b/tests/README.md deleted file mode 100644 index 22d5ebbd6e..0000000000 --- a/tests/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# csound-ac -Michael Gogins
-https://github.com/gogins
-http://michaelgogins.tumblr.com - -## Unit Tests - -This directory contains unit tests, mostly in Python, for CsoundAC. Many of -these tests are old and no longer work, either because they were written for -Python 2, or because they use resources not found here. They can be fixed up -if necessary. - -However, there is one piece, "Cellular-v5-macos.py", that uses available -resources (with the exception of Modartt VST3 plugins, which can be -substituted), the MusicModel code in CsoundAC, and the Midifile code in -CsoundAC, for both reading and writing MIDI files. This piece can be -considered a useful sanity check to detect regressions after major commits. \ No newline at end of file diff --git a/vscode-playpen/extension.js b/vscode-playpen/extension.js index eadbc892cf..f49318a97d 100644 --- a/vscode-playpen/extension.js +++ b/vscode-playpen/extension.js @@ -4,17 +4,22 @@ * have a symbolic link in the user's home directory to the real file. */ +const path = require('path'); const vscode = require('vscode'); /** * Execute the command text in the directory of the document. * A Terminal is used rather than a subprocess with an output channel, * because it is simpler, and only a Terminal can kill all subprocesses when - * the user kills the Terminal. + * the user kills the Terminal. The cwd is set to the directory containing + * the filepath. */ async function spawner(command, filepath) { - let terminal = vscode.window.createTerminal("Playpen"); + let terminal_options = {"name": "Playpen", + "cwd": path.dirname(filepath)}; + let terminal = vscode.window.createTerminal(terminal_options); terminal.show(false); + terminal.sendText("cd " + path.dirname(filepath), true); terminal.sendText(command, true); } @@ -69,7 +74,7 @@ function activate(context) { spawner(`python3 ~/playpen.py cpp-audio ${filepath}`, filepath); }); context.subscriptions.push(disposable); - disposable = vscode.commands.registerCommand('playpen.cpp_soundfile', function () { + disposable = vscode.commands.registerCommand('playpen.cpp_soundfile, function () { let filepath = vscode.window.activeTextEditor.document.uri.fsPath; console.log(`Rendering "${filepath}..."`) spawner(`python3 ~/playpen.py cpp-play ${filepath}`, filepath);