commit e85dd19254df52b18d4d53554d4a60c8d61a16a4
parent 5fe48831dfd1faa966b571a08ec04ed4aa8b0628
Author: fundamental <mark.d.mccurry@gmail.com>
Date: Sat, 22 May 2010 07:21:17 -0400
Merge branch 'nio'
Diffstat:
97 files changed, 3909 insertions(+), 2605 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1,7 +1,5 @@
*.o
*~
-src/UI/*.h
-src/UI/*.cc
src/zynaddsubfx
src/Tests/runner
src/Tests/runner.cpp
diff --git a/AUTHORS.txt b/AUTHORS.txt
@@ -15,6 +15,7 @@ Contributors:
Alexis Ballier (const char* <-> string mismatch, NULLMidi prototype fix)
Tobias Doerffel (static-instance variables fix, missing include fix)
James Morris (Memory leaks in FLTK GUI)
+ Alan Calvert (Portions of New IO)
Stephen Parry (DSSI rebuild)
Ryan Billing (APhaser)
diff --git a/ChangeLog b/ChangeLog
@@ -963,6 +963,9 @@
28 Oct 2009 (Paul Nasca)
- Disable "bw" control on Reverb when Bandwidth mode is not enabled
+30 Oct 2009 (Mark McCurry)
+ - Commited first stage of Nio (New IO) WIP
+
18 Nov 2009 (Mark McCurry)
- Fixed segfault in VirKeyBoard
@@ -974,6 +977,11 @@
the Wextra flag
- Minor change to Filter_ and FormantFilter to reduce unwanted warnings
+13 Dec 2009 (Mark McCurry)
+ - Deprecating Output system for the Nio system
+ - General Code Cleanup
+ - Adding OpenGL linking for proper compiles
+
14 Jan 2010 (Mark McCurry)
- Fixed No UI Flag "-U" as it was previously partially initializing
the gui
diff --git a/cmake/Findfftw.cmake b/cmake/Findfftw.cmake
@@ -7,7 +7,7 @@
SET(fftw_FOUND 0)
-IF(UNIX)
+IF(UNIX OR CYGWIN)
FIND_PATH(fftw_INCLUDE_DIR
fftw3.h
/usr/include
@@ -18,7 +18,7 @@ IF(UNIX)
/usr/lib
)
-ENDIF(UNIX)
+ENDIF(UNIX OR CYGWIN)
# handle the QUIETLY and REQUIRED arguments and set fftw_FOUND to TRUE if
# all listed variables are TRUE
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
@@ -1,23 +1,38 @@
+#checking include/library paths
+message(STATUS "Checking Include Path" $ENV{CMAKE_INCLUDE_PATH} ${CMAKE_INCLUDE_PATH})
+message(STATUS "Checking Library Path" $ENV{CMAKE_LIBRARY_PATH} ${CMAKE_LIBRARY_PATH})
+
#Dependency check
find_package(zlib REQUIRED)
find_package(fftw REQUIRED)
find_package(MXML REQUIRED)
find_package(PkgConfig REQUIRED)
#find_package(pthread REQUIRED)
+#find_package(OSS)
find_package(Alsa)
find_package(JACK)
find_package(PortAudio)
+set(FLTK_SKIP_OPENGL true)
find_package(FLTK)
find_package(OpenGL) #for FLTK
######### Settings ###########
-# NOTE: These cache variables should normallly not be changed in this
+# NOTE: These cache variables should normally not be changed in this
# file, but either in in CMakeCache.txt before compile, or by passing
# parameters directly into cmake using the -D flag.
SET (FFTW_VERSION 3 CACHE STRING "Version number of FFTW")
-SET (OutputModule alsa CACHE STRING "Output module, either alsa, jack or portaudio")
+SET (DefaultOutput oss CACHE STRING
+ "Default Output module: [null, alsa, oss, jack, portaudio]")
SET (GuiModule fltk CACHE STRING "GUI module, either fltk, qt or off")
SET (CompileTests OFF CACHE BOOL "whether tests should be compiled in or not")
+SET (AlsaEnable ${ALSA_FOUND} CACHE BOOL
+ "Enable support for Advanced Linux Sound Architecture")
+SET (JackEnable ${JACK_FOUND} CACHE BOOL
+ "Enable support for JACK Audio Connection toolKit")
+SET (OssEnable ${ALSA_FOUND} CACHE BOOL #TODO perhaps check for /dev/dsp
+ "Enable support for Open Sound System")
+SET (PaEnable ${PORTAUDIO_FOUND} CACHE BOOL
+ "Enable support for Port Audio System")
# Now, handle the incoming settings and set define flags/variables based
@@ -35,16 +50,6 @@ else ()
message(STATUS "GUI module defaulting to off")
endif()
-if (OutputModule STREQUAL alsa AND ALSA_FOUND)
- set(AlsaMidiOutput TRUE)
-elseif(OutputModule STREQUAL jack AND JACK_FOUND)
- set(JackOutput TRUE)
-elseif(OutputModule STREQUAL portaudio AND PortAudio_FOUND)
- set(PortAudioOutput TRUE)
-else ()
- message(FATAL_ERROR "OutputModule must be either alsa, jack or portaudio")
-endif()
-
if(NOT PKG_CONFIG_FOUND)
message(FATAL_ERROR "pkg-config not found")
endif(NOT PKG_CONFIG_FOUND)
@@ -57,27 +62,32 @@ mark_as_advanced(LASH_LIBRARIES)
# From here on, the setting variables have been prepared so concentrate
# on the actual compiling.
-if(AlsaMidiOutput)
+if(AlsaEnable)
+ list(APPEND AUDIO_LIBRARIES ${ASOUND_LIBRARY})
+ add_definitions(-DALSA=1)
+endif(AlsaEnable)
+
+if(JackEnable)
+ list(APPEND AUDIO_LIBRARIES ${JACK_LIBRARIES})
+ add_definitions(-DJACK=1)
+endif(JackEnable)
+
+if(OssEnable)
add_definitions(-DOSSAUDIOOUT)
- set(AUDIO_LIBRARIES ${AUDIO_LIBRARIES} ${ASOUND_LIBRARY})
+ list(APPEND AUDIO_LIBRARIES ${ASOUND_LIBRARY})
+ add_definitions(-DOSS=1)
+endif(OssEnable)
+
+if(PaEnable)
+ include_directories(${PORTAUDIO_INCLUDE_DIR})
+ add_definitions(-DPORTAUDIO=1)
+ list(APPEND AUDIO_LIBRARIES ${PORTAUDIO_LIBRARIES})
endif()
if (CompileTests)
ENABLE_TESTING()
endif()
-if(JackOutput)
- include_directories(${JACK_INCLUDE_DIR})
- add_definitions(-DJACKAUDIOOUT)
- set(AUDIO_LIBRARIES ${AUDIO_LIBRARIES} ${JACK_LIBRARIES})
-endif()
-
-if(PortAudioOutput)
- include_directories(${PORTAUDIO_INCLUDE_DIR})
- add_definitions(-DPAAUDIOOUT)
- set(AUDIO_LIBRARIES ${AUDIO_LIBRARIES} ${PORTAUDIO_LIBRARIES})
-endif()
-
if(LASH_FOUND)
include_directories(${LASH_INCLUDE_DIRS})
add_definitions(-DUSE_LASH)
@@ -86,22 +96,28 @@ if(LASH_FOUND)
endif()
add_definitions(-DFFTW_VERSION_${FFTW_VERSION}
- -DOS_LINUX
- -DALSAMIDIIN
-DASM_F2I_YES
+ -g #TODO #todo put in a better location
+ -Wall
+ -Wextra
)
+#set os flag
+if(CYGWIN)
+ add_definitions(-DOS_CYGWIN=1)
+ set(OS_LIBRARIES "-Wl,--enable-auto-import")
+elseif(WINDOWS)
+ add_definitions(-DOS_WINDOWS=1)
+ set(OS_LIBRARIES "")
+elseif(UNIX)
+ add_definitions(-DOS_LINUX=1)
+ set(OS_LIBRARIES "")
+else()
+ message(STATUS "Error: building on unsupported OS")
+endif()
-if(FltkGui)
- #message(STATUS "FLTK_LIBRARIES: ${FLTK_LIBRARIES}")
- #message(STATUS "FLTK_MATH_LIBRARY: ${FLTK_MATH_LIBRARY}")
- #UGLY WORKAROUND
- find_program (MYFLTK_CONFIG fltk-config)
- if (MYFLTK_CONFIG)
- execute_process (COMMAND ${MYFLTK_CONFIG} --ldflags OUTPUT_VARIABLE MYFLTK_LDFLAGS)
- string(STRIP ${MYFLTK_LDFLAGS} MYFLTK_LIBRARIES)
- endif()
+if(FLTK_FOUND)
mark_as_advanced(FORCE FLTK_BASE_LIBRARY)
mark_as_advanced(FORCE FLTK_CONFIG_SCRIPT)
mark_as_advanced(FORCE FLTK_DIR)
@@ -111,9 +127,21 @@ if(FltkGui)
mark_as_advanced(FORCE FLTK_IMAGES_LIBRARY)
mark_as_advanced(FORCE FLTK_INCLUDE_DIR)
mark_as_advanced(FORCE FLTK_MATH_LIBRARY)
+endif(FLTK_FOUND)
+
+if(FltkGui)
+ #UGLY WORKAROUND
+ find_program (MYFLTK_CONFIG fltk-config)
+ if (MYFLTK_CONFIG)
+ execute_process (COMMAND ${MYFLTK_CONFIG} --ldflags OUTPUT_VARIABLE MYFLTK_LDFLAGS)
+ string(STRIP ${MYFLTK_LDFLAGS} MYFLTK_LIBRARIES)
+ endif()
+
+ message(STATUS ${MYFLTK_LDFLAGS})
set(GUI_LIBRARIES ${FLTK_LIBRARIES} ${MYFLTK_LIBRARIES} ${OPENGL_LIBRARIES} zynaddsubfx_gui)
+
add_definitions(-DFLTK_GUI)
message(STATUS "Will build fltk gui")
@@ -141,33 +169,32 @@ include_directories(
add_definitions(-DSOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
#macro for tests
macro(unit_test NAME CXX_FILE FILES)
- if (CompileTests)
- set(PATH_FILES "")
- foreach(part ${FILES})
- set(PATH_FILES "${CMAKE_CURRENT_SOURCE_DIR}/${part}" ${PATH_FILES})
- endforeach(part ${FILES})
- set(CXX_FILE_REAL "${CMAKE_CURRENT_SOURCE_DIR}/${CXX_FILE}")
- add_custom_command(
- OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${NAME}.cxx"
- COMMAND cxxtestgen.py --error-printer -o "${CMAKE_CURRENT_BINARY_DIR}/${NAME}.cxx" ${CXX_FILE_REAL}
- DEPENDS "${FILE}"
- )
- set(CXXTEST_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${NAME}.cxx")
- add_executable("${NAME}" "${CXXTEST_OUTPUT}" ${PATH_FILES})
- target_link_libraries("${NAME}" ${CXXTEST_LINK_LIBS}
- ${NONGUI_LIBRARIES}
- ${GUI_LIBRARIES}
- ${zlib_LIBRARIES}
- ${fftw_LIBRARIES}
- ${MXML_LIBRARIES}
- )
- add_test("${NAME}" "${EXECUTABLE_OUTPUT_PATH}/${NAME}")
- endif()
+ if (CompileTests)
+ set(PATH_FILES "")
+ foreach(part ${FILES})
+ set(PATH_FILES "${CMAKE_CURRENT_SOURCE_DIR}/${part}" ${PATH_FILES})
+ endforeach(part ${FILES})
+ set(CXX_FILE_REAL "${CMAKE_CURRENT_SOURCE_DIR}/${CXX_FILE}")
+ add_custom_command(
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${NAME}.cxx"
+ COMMAND cxxtestgen.py --error-printer -o "${CMAKE_CURRENT_BINARY_DIR}/${NAME}.cxx" ${CXX_FILE_REAL}
+ DEPENDS "${FILE}"
+ )
+ set(CXXTEST_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${NAME}.cxx")
+ add_executable("${NAME}" "${CXXTEST_OUTPUT}" ${PATH_FILES})
+ target_link_libraries("${NAME}" ${CXXTEST_LINK_LIBS}
+ ${NONGUI_LIBRARIES}
+ ${GUI_LIBRARIES}
+ ${zlib_LIBRARIES}
+ ${fftw_LIBRARIES}
+ ${MXML_LIBRARIES}
+ ${OS_LIBRARIES}
+ )
+ add_test("${NAME}" "${EXECUTABLE_OUTPUT_PATH}/${NAME}")
+ endif()
endmacro(unit_test)
set(NONGUI_LIBRARIES
- zynaddsubfx_input
- zynaddsubfx_output
zynaddsubfx_misc
zynaddsubfx_synth
zynaddsubfx_seq
@@ -175,27 +202,28 @@ set(NONGUI_LIBRARIES
zynaddsubfx_params
zynaddsubfx_dsp
zynaddsubfx_samples
+ zynaddsubfx_nio
)
set(CXXTEST_LINK_LIBS ${NONGUI_LIBRARIES})
-set(MIDIINPUT_LIBRARIES "")
add_subdirectory(Misc)
-add_subdirectory(Input)
add_subdirectory(Synth)
-add_subdirectory(Output)
add_subdirectory(Seq)
add_subdirectory(Effects)
add_subdirectory(Params)
add_subdirectory(DSP)
add_subdirectory(Samples)
-add_subdirectory(Tests)
+if(CompileTests)
+ add_subdirectory(Tests)
+endif(CompileTests)
+add_subdirectory(Nio)
set(zynaddsubfx_SRCS
main.cpp
)
-add_executable(zynaddsubfx
+add_executable(zynaddsubfx
${zynaddsubfx_SRCS}
)
@@ -205,8 +233,9 @@ target_link_libraries(zynaddsubfx
${zlib_LIBRARIES}
${fftw_LIBRARIES}
${MXML_LIBRARIES}
+ ${NIO_LIBRARIES}
${AUDIO_LIBRARIES}
- ${MIDIINPUT_LIBRARIES}
+ ${OS_LIBRARIES}
)
install(TARGETS zynaddsubfx
diff --git a/src/DSP/Makefile b/src/DSP/Makefile
@@ -1,14 +0,0 @@
-include ../Makefile.inc
-
-objects=FFTwrapper.o AnalogFilter.o FormantFilter.o SVFilter.o Filter.o Unison.o
-
-
-all: $(objects)
-
--include ../Make.deps
-
-.PHONY : clean
-clean:
- rm -f $(objects)
- rm -f makeinclude.deps
-
diff --git a/src/Effects/Effect.cpp b/src/Effects/Effect.cpp
@@ -21,6 +21,7 @@
*/
#include "Effect.h"
+#include "../Params/FilterParams.h"
Effect::Effect(bool insertion_, REALTYPE *const efxoutl_,
REALTYPE *const efxoutr_, FilterParams *filterpars_,
diff --git a/src/Effects/Effect.h b/src/Effects/Effect.h
@@ -28,6 +28,7 @@
#include "../Params/FilterParams.h"
#include "../Misc/Stereo.h"
+class FilterParams;
/**this class is inherited by the all effects(Reverb, Echo, ..)*/
class Effect
diff --git a/src/Effects/EffectMgr.cpp b/src/Effects/EffectMgr.cpp
@@ -21,6 +21,16 @@
*/
#include "EffectMgr.h"
+#include "Effect.h"
+#include "Reverb.h"
+#include "Echo.h"
+#include "Chorus.h"
+#include "Distorsion.h"
+#include "EQ.h"
+#include "DynamicFilter.h"
+#include "../Misc/XMLwrapper.h"
+#include "../Params/FilterParams.h"
+
#include <iostream>
using namespace std;
diff --git a/src/Effects/EffectMgr.h b/src/Effects/EffectMgr.h
@@ -24,12 +24,14 @@
#include <pthread.h>
-#include "Effect.h"
-#include "Reverb.h"
-#include "Echo.h"
-#include "Chorus.h"
-#include "Phaser.h"
#include "Alienwah.h"
+#include "Phaser.h"
+#include "../Params/Presets.h"
+
+class Effect;
+class FilterParams;
+class XMLwrapper;
+
#include "Distorsion.h"
#include "EQ.h"
#include "DynamicFilter.h"
diff --git a/src/Effects/Makefile b/src/Effects/Makefile
@@ -1,16 +0,0 @@
-include ../Makefile.inc
-
-objects=Alienwah.o Chorus.o Echo.o Effect.o \
- EffectLFO.o EffectMgr.o Phaser.o Reverb.o \
- Distorsion.o EQ.o DynamicFilter.o APhaser.o
-
-
-all: $(objects)
-
--include ../Make.deps
-
-.PHONY : clean
-clean:
- rm -f $(objects)
- rm -f makeinclude.deps
-
diff --git a/src/Input/ALSAMidiIn.cpp b/src/Input/ALSAMidiIn.cpp
@@ -1,118 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- ALSAMidiIn.cpp - Midi input for ALSA (this creates an ALSA virtual port)
- Copyright (C) 2002-2005 Nasca Octavian Paul
- Author: Nasca Octavian Paul
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License
- as published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License (version 2 or later) for more details.
-
- You should have received a copy of the GNU General Public License (version 2)
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-*/
-
-#include "ALSAMidiIn.h"
-
-ALSAMidiIn::ALSAMidiIn()
-{
- int alsaport;
- inputok = false;
-
- midi_handle = NULL;
-
- if(snd_seq_open(&midi_handle, "default", SND_SEQ_OPEN_INPUT, 0) != 0)
- return;
-
- snd_seq_set_client_name(midi_handle, "ZynAddSubFX"); //thanks to Frank Neumann
-
- alsaport = snd_seq_create_simple_port(
- midi_handle,
- "ZynAddSubFX",
- SND_SEQ_PORT_CAP_WRITE
- | SND_SEQ_PORT_CAP_SUBS_WRITE,
- SND_SEQ_PORT_TYPE_SYNTH);
- if(alsaport < 0)
- return;
-
- inputok = true;
-}
-
-ALSAMidiIn::~ALSAMidiIn()
-{
- if(midi_handle)
- snd_seq_close(midi_handle);
-}
-
-
-/*
- * Get the midi command,channel and parameters
- */
-void ALSAMidiIn::getmidicmd(MidiCmdType &cmdtype,
- unsigned char &cmdchan,
- int *cmdparams)
-{
- snd_seq_event_t *midievent = NULL;
- cmdtype = MidiNull;
-
- if(inputok == false) {
- /* The input is broken. We need to block for a while anyway so other
- non-RT threads get a chance to run. */
- sleep(1);
- return;
- }
-
- snd_seq_event_input(midi_handle, &midievent);
-
- if(midievent == NULL)
- return;
- switch(midievent->type) {
- case SND_SEQ_EVENT_NOTEON:
- cmdtype = MidiNoteON;
- cmdchan = midievent->data.note.channel;
- cmdparams[0] = midievent->data.note.note;
- cmdparams[1] = midievent->data.note.velocity;
- break;
- case SND_SEQ_EVENT_NOTEOFF:
- cmdtype = MidiNoteOFF;
- cmdchan = midievent->data.note.channel;
- cmdparams[0] = midievent->data.note.note;
- break;
- case SND_SEQ_EVENT_PITCHBEND:
- cmdtype = MidiController;
- cmdchan = midievent->data.control.channel;
- cmdparams[0] = C_pitchwheel; //Pitch Bend
- cmdparams[1] = midievent->data.control.value;
- break;
- case SND_SEQ_EVENT_CONTROLLER:
- cmdtype = MidiController;
- cmdchan = midievent->data.control.channel;
- cmdparams[0] = getcontroller(midievent->data.control.param);
- cmdparams[1] = midievent->data.control.value;
- //fprintf(stderr,"t=%d val=%d\n",midievent->data.control.param,midievent->data.control.value);
- break;
- }
-}
-
-
-int ALSAMidiIn::getalsaid()
-{
- if(midi_handle) {
- snd_seq_client_info_t *seq_info;
- snd_seq_client_info_malloc(&seq_info);
- snd_seq_get_client_info(midi_handle, seq_info);
- int id = snd_seq_client_info_get_client(seq_info);
- snd_seq_client_info_free(seq_info);
- return id;
- }
- return -1;
-}
-
diff --git a/src/Input/ALSAMidiIn.h b/src/Input/ALSAMidiIn.h
@@ -1,51 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- ALSAMidiIn.h - Midi input for ALSA (this creates an ALSA virtual port)
- Copyright (C) 2002-2005 Nasca Octavian Paul
- Author: Nasca Octavian Paul
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License
- as published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License (version 2 or later) for more details.
-
- You should have received a copy of the GNU General Public License (version 2)
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-*/
-
-#ifndef ALSA_MIDI_IN_H
-#define ALSA_MIDI_IN_H
-
-#include <alsa/asoundlib.h>
-#include "MidiIn.h"
-
-
-/**Midi input for ALSA (this creates an ALSA virtual port)*/
-class ALSAMidiIn:public MidiIn
-{
- public:
- /**Constructor*/
- ALSAMidiIn();
- /**Destructor*/
- ~ALSAMidiIn();
-
- void getmidicmd(MidiCmdType &cmdtype,
- unsigned char &cmdchan,
- int *cmdparams);
- /**Get the ALSA id
- * @return ALSA id*/
- int getalsaid();
-
- private:
- snd_seq_t *midi_handle;
-};
-
-#endif
-
diff --git a/src/Input/CMakeLists.txt b/src/Input/CMakeLists.txt
@@ -1,20 +0,0 @@
-set(AlsaMidiInput On CACHE BOOL "Include ALSA Midi input")
-set(zynaddsubfx_input_SRCS
- MidiIn.cpp
- NULLMidiIn.cpp
- #OSSMidiIn.cpp #[TODO] get OSS midi detection and
- #WINMidiIn.cpp # Win midi detection working
-)
-
-if(AlsaMidiInput)
- set(zynaddsubfx_input_SRCS
- ${zynaddsubfx_input_SRCS}
- ALSAMidiIn.cpp
- )
- message(STATUS "Alsa midi input enabled")
- set(MIDIINPUT_LIBRARIES ${ASOUND_LIBRARY} PARENT_SCOPE)
-endif(AlsaMidiInput)
-
-add_library(zynaddsubfx_input STATIC
- ${zynaddsubfx_input_SRCS}
- )
diff --git a/src/Input/Makefile b/src/Input/Makefile
@@ -1,26 +0,0 @@
-include ../Makefile.inc
-
-objects=NULLMidiIn.o MidiIn.o
-
-ifeq ($(MIDIIN),ALSA)
-objects+=ALSAMidiIn.o
-endif
-
-ifeq ($(MIDIIN),OSS)
-objects+=OSSMidiIn.o
-endif
-
-ifeq ($(MIDIIN),WIN)
-objects+=WINMidiIn.o
-endif
-
-
-all: $(objects)
-
--include ../Make.deps
-
-.PHONY : clean
-clean:
- rm -f $(objects)
- rm -f makeinclude.deps
-
diff --git a/src/Input/NULLMidiIn.cpp b/src/Input/NULLMidiIn.cpp
@@ -1,41 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- NULLMidiIn.cpp - a dummy Midi port
- Copyright (C) 2002-2005 Nasca Octavian Paul
- Author: Nasca Octavian Paul
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License
- as published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License (version 2 or later) for more details.
-
- You should have received a copy of the GNU General Public License (version 2)
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-*/
-
-#include "NULLMidiIn.h"
-
-NULLMidiIn::NULLMidiIn()
-{}
-
-NULLMidiIn::~NULLMidiIn()
-{}
-
-/*
- * Get the midi command,channel and parameters
- * It returns MidiNull because it is a dummy driver
- */
-void NULLMidiIn::getmidicmd(MidiCmdType &cmdtype,
- unsigned char &cmdchan,
- int *cmdparams)
-{
- cmdtype = MidiNull;
-}
-
diff --git a/src/Input/NULLMidiIn.h b/src/Input/NULLMidiIn.h
@@ -1,50 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- NULLMidiIn.h - a dummy Midi port
- Copyright (C) 2002-2005 Nasca Octavian Paul
- Author: Nasca Octavian Paul
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License
- as published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License (version 2 or later) for more details.
-
- You should have received a copy of the GNU General Public License (version 2)
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-*/
-
-#ifndef NULL_MIDI_IN_H
-#define NULL_MIDI_IN_H
-
-#include "MidiIn.h"
-
-
-/**a dummy Midi port*/
-class NULLMidiIn:public MidiIn
-{
- public:
- /**Dummy Constructor
- * \todo see if the default constructor would work here*/
- NULLMidiIn();
- /**Dummy Destructor
- * \todo see if the default destructor would work here*/
- ~NULLMidiIn();
- /**Get the midi command,channel and parameters
- * It returns MidiNull because it is a dummy driver
- */
- void getmidicmd(MidiCmdType &cmdtype,
- unsigned char &cmdchan,
- int *cmdparams);
-
- private:
-};
-
-#endif
-
diff --git a/src/Input/OSSMidiIn.cpp b/src/Input/OSSMidiIn.cpp
@@ -1,123 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- OSSMidiIn.cpp - Midi input for Open Sound System
- Copyright (C) 2002-2005 Nasca Octavian Paul
- Author: Nasca Octavian Paul
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License
- as published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License (version 2 or later) for more details.
-
- You should have received a copy of the GNU General Public License (version 2)
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-*/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/soundcard.h>
-
-#include "OSSMidiIn.h"
-#include "../Misc/Util.h"
-
-OSSMidiIn::OSSMidiIn()
-{
- inputok = false;
- midi_handle = open(config.cfg.LinuxOSSSeqInDev, O_RDONLY, 0);
- if(midi_handle != -1)
- inputok = true;
-
- lastmidicmd = 0;
- cmdtype = 0;
- cmdchan = 0;
-}
-
-OSSMidiIn::~OSSMidiIn()
-{
- close(midi_handle);
-}
-
-unsigned char OSSMidiIn::readbyte()
-{
- unsigned char tmp[4];
- read(midi_handle, &tmp[0], 1);
- while(tmp[0] != SEQ_MIDIPUTC) {
- read(midi_handle, &tmp[0], 4);
- }
- return tmp[1];
-}
-
-unsigned char OSSMidiIn::getmidibyte()
-{
- unsigned char b;
- do {
- b = readbyte();
- } while(b == 0xfe); //drops the Active Sense Messages
- return b;
-}
-
-/*
- * Get the midi command,channel and parameters
- */
-void OSSMidiIn::getmidicmd(MidiCmdType &cmdtype,
- unsigned char &cmdchan,
- int *cmdparams)
-{
- unsigned char tmp, i;
- if(inputok == false) {
- cmdtype = MidiNull;
- return;
- }
- i = 0;
- if(lastmidicmd == 0) { //asteapta prima data pana cand vine prima comanda midi
- while(tmp < 0x80)
- tmp = getmidibyte();
- lastmidicmd = tmp;
- }
-
- tmp = getmidibyte();
-
- if(tmp >= 0x80) {
- lastmidicmd = tmp;
- tmp = getmidibyte();
- }
-
- if((lastmidicmd >= 0x80) && (lastmidicmd <= 0x8f)) { //Note OFF
- cmdtype = MidiNoteOFF;
- cmdchan = lastmidicmd % 16;
- cmdparams[0] = tmp; //note number
- }
-
- if((lastmidicmd >= 0x90) && (lastmidicmd <= 0x9f)) { //Note ON
- cmdtype = MidiNoteON;
- cmdchan = lastmidicmd % 16;
- cmdparams[0] = tmp; //note number
- cmdparams[1] = getmidibyte(); //velocity
- if(cmdparams[1] == 0)
- cmdtype = MidiNoteOFF; //if velocity==0 then is note off
- }
- if((lastmidicmd >= 0xB0) && (lastmidicmd <= 0xBF)) { //Controllers
- cmdtype = MidiController;
- cmdchan = lastmidicmd % 16;
- cmdparams[0] = getcontroller(tmp);
- cmdparams[1] = getmidibyte();
- }
- if((lastmidicmd >= 0xE0) && (lastmidicmd <= 0xEF)) { //Pitch Wheel
- cmdtype = MidiController;
- cmdchan = lastmidicmd % 16;
- cmdparams[0] = C_pitchwheel;
- cmdparams[1] = (tmp + getmidibyte() * (int) 128) - 8192; //hope this is correct
- }
-}
-
diff --git a/src/Input/OSSMidiIn.h b/src/Input/OSSMidiIn.h
@@ -1,50 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- OSSMidiIn.h - Midi input for Open Sound System
- Copyright (C) 2002-2005 Nasca Octavian Paul
- Author: Nasca Octavian Paul
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License
- as published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License (version 2 or later) for more details.
-
- You should have received a copy of the GNU General Public License (version 2)
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-*/
-
-#ifndef OSS_MIDI_IN_H
-#define OSS_MIDI_IN_H
-
-#include "MidiIn.h"
-
-class OSSMidiIn:public MidiIn
-{
- public:
- OSSMidiIn();
- ~OSSMidiIn();
- unsigned char getmidibyte();
- unsigned char readbyte();
-
- //Midi parser
- void getmidicmd(MidiCmdType &cmdtype,
- unsigned char &cmdchan,
- int *cmdparams);
- unsigned char cmdtype; //the Message Type (noteon,noteof,sysex..)
- unsigned char cmdchan; //the channel number
-
- private:
- int midi_handle;
- unsigned char lastmidicmd; //last byte (>=80) received from the Midi
-};
-
-
-#endif
-
diff --git a/src/Makefile b/src/Makefile
@@ -1,134 +0,0 @@
-include Makefile.inc
-
-ifneq ($(MAKECMDGOALS),debug)
- CXXFLAGS= -O2 -Wall -g -fPIC
-else
- CXXFLAGS= -O2 -Wall -Wpointer-arith -fPIC
-endif
-
-CXXFLAGS += -DOS_$(OS_PORT) -D$(MIDIIN)MIDIIN -DFFTW_VERSION_$(FFTW_VERSION) -DASM_F2I_$(ASM_F2I) -ggdb
-
-ifeq ($(DISABLE_GUI),YES)
- CXXFLAGS += -DDISABLE_GUI
-else
- CXXFLAGS += -DFLTK_GUI `fltk-config --cflags`
-endif
-
-ifeq ($(AUDIOOUT),OSS_AND_JACK)
- CXXFLAGS += -DOSSAUDIOOUT -DJACKAUDIOOUT
-else
- CXXFLAGS += -D$(AUDIOOUT)AUDIOOUT
-endif
-
-export CXXFLAGS
-
-LIBS= -lm -lmxml -lz
-ifneq ($(DISABLE_GUI),YES)
- LIBS+=`fltk-config --ldflags`
-endif
-
-ifeq ($(FFTW_VERSION),2)
-LIBS += -lrfftw -lfftw
-else
-LIBS += -lfftw3
-endif
-
-ifeq ($(OS_PORT),LINUX)
-LIBS+= -lpthread
-else
-#dynamic linking
-#LIBS+= -lpthreadGC
-#static linking
-LIBS+= /usr/lib/libpthreadGC1.a
-endif
-
-ifeq ($(MIDIIN),ALSA)
-LIBS+= -lasound
-endif
-
-ifeq ($(AUDIOOUT),PA)
-LIBS+= -lportaudio
-endif
-
-ifeq ($(OS_PORT),WINDOWS)
-LIBS+= -lwinmm
-endif
-
-
-ifeq ($(AUDIOOUT),OSS_AND_JACK)
-CXXFLAGS += `pkg-config --cflags jack`
-LIBS+= `pkg-config --libs jack`
-endif
-
-ifeq ($(AUDIOOUT),JACK)
-CXXFLAGS += `pkg-config --cflags jack`
-LIBS+= `pkg-config --libs jack`
-endif
-
-ifeq ($(AUDIOOUT),JACK_RT)
-CXXFLAGS += `pkg-config --cflags jack`
-LIBS+= `pkg-config --libs jack`
-endif
-
-ifeq ($(LINUX_USE_LASH),YES)
-CXXFLAGS += `pkg-config --cflags lash-1.0` -DUSE_LASH
-LIBS+= `pkg-config --libs lash-1.0`
-endif
-
-
-objects=main.o
-SUBDIRS=DSP Effects Input Misc Output Params Samples Synth Seq
-
-.PHONY: subdirs $(SUBDIRS)
-
-all:
-# yes " " | head
-
- $(MAKE) -C UI $@
-# @sh -c "cd UI ; $(CXX) -MM -MG -w *.cc >> ../Make.deps ; cd .."
- @for name in $(SUBDIRS); do sh -c "cd $$name ; $(CXX) -MM -MG -w *.cpp >> ../Make.deps ; cd .."; done
- $(MAKE) subdirs
- $(MAKE) objs
- rm -f zynaddsubfx zynaddsubfx.exe
- rm -f Make.deps
-
-
-ifeq ($(AUDIOOUT),DSSI)
- $(CXX) -shared -o zynaddsubfx.so */*.o *.o $(LIBS)
-else
-ifeq ($(AUDIOOUT),VST)
- $(CXX) -shared -o zynaddsubfx_vst.dll */*.o *.o ../../vstsdk2/source/common/AudioEffect.cpp ../../vstsdk2/source/common/audioeffectx.cpp $(LIBS) zynaddsubfx_gcc.def
-else
-
-
-ifeq ($(OS_PORT),LINUX)
- $(CXX) -o zynaddsubfx */*.o *.o $(LIBS)
-else
- $(CXX) -o zynaddsubfx.exe */*.o *.o $(LIBS)
-endif
-endif
-endif
-
-subdirs: $(SUBDIRS)
-
-$(SUBDIRS):
- $(MAKE) -C $@
-
-
-objs:$(objects)
-
-debug: all
-
-main.o:Misc/Master.h Misc/Util.h Output/OSSaudiooutput.h\
- Input/OSSMidiIn.h Input/ALSAMidiIn.h
-
-
-.PHONY : clean
-clean:
- rm -f $(objects) zynaddsubfx zynaddsubfx_vst.dll zynaddsubfx.exe zynaddsubfx.so
- @for name in $(SUBDIRS); do sh -c "make -C $$name $@"; done
- rm -f Make.deps
- rm -f */*.o *.o
- rm -f ./*/*~ ./*~
- $(MAKE) -C UI $@
-
diff --git a/src/Makefile.inc b/src/Makefile.inc
@@ -1,84 +0,0 @@
-CXX=g++
-
-#You can set the on what OS is compiling (Linux/Windows)
-OS_PORT=LINUX
-#OS_PORT=WINDOWS
-
-#The version of the FFTW which is used (2 or 3)
-#FFTW_VERSION=2
-FFTW_VERSION=3
-
-#Assembler FLOAT to INT conversions
-ASM_F2I=YES
-#ASM_F2I=NO
-
-#Graphic user interface disable option (ZynAddSubFX will run only in text-mode)
-#DISABLE_GUI=YES
-DISABLE_GUI=NO
-
-# L I N U X C O N F I G U R A T I O N
-#Next line sets the midi input. It can be "ALSA", "OSS" or "NONE".
-LINUX_MIDIIN=ALSA
-#LINUX_MIDIIN=OSS
-#LINUX_MIDIIN=NONE
-
-#Next lines sets the audio output (OSS/JACK/PA)
-#You may use only one at the time
-#If you use "OSS_AND_JACK",,at runtime, zynaddsubfx will run by the default with jack support and
-#it will try OSS if JACK fails. At runtime you can set the OSS by default by command-line
-#parameters (run 'zynaddsubfx --help' for help)
-
-#LINUX_AUDIOOUT=OSS_AND_JACK
-LINUX_AUDIOOUT=OSS
-#LINUX_AUDIOOUT=NONE
-#LINUX_AUDIOOUT=JACK
-#LINUX_AUDIOOUT=JACK_RT JACK_RT support is broken
-#for PortAudio (PA)
-#LINUX_AUDIOOUT=PA
-
-
-#Next line sets if the synth is compiled for DSSI plugin (as .so file)
-#If this setting is "YES", MIDI in and AUDIOOUT are set automatically to DSSI
-LINUX_DSSI=NO
-#LINUX_DSSI=YES
-
-#Next line sets if the LASH session handler will be used
-#LINUX_USE_LASH=YES
-LINUX_USE_LASH=NO
-
-# W I N D O W S C O N F I G U R A T I O N
-
-#Next line sets the midi input
-#WINDOWS_MIDIIN=NONE
-WINDOWS_MIDIIN=WIN
-
-#Next line sets the audio output
-#WINDOWS_AUDIOOUT=NONE
-WINDOWS_AUDIOOUT=PA
-
-#Next line sets if the synth is compiled for VST (as .dll file)
-#If this setting is "YES", MIDI in and AUDIOOUT are set automatically to VST
-WINDOWS_VST=NO
-#WINDOWS_VST=YES
-
-#configuration end
-
-ifeq ($(OS_PORT),LINUX)
- MIDIIN=$(LINUX_MIDIIN)
- AUDIOOUT=$(LINUX_AUDIOOUT)
- WINDOWS_VST=NO
- ifeq ($(LINUX_DSSI),YES)
- DISABLE_GUI=YES
- MIDIIN=DSSI
- AUDIOOUT=DSSI
- endif
-else
- MIDIIN=$(WINDOWS_MIDIIN)
- AUDIOOUT=$(WINDOWS_AUDIOOUT)
- LINUX_DSSI=NO
- ifeq ($(WINDOWS_VST),YES)
- MIDIIN=VST
- AUDIOOUT=VST
- endif
-endif
-
diff --git a/src/Misc/Atomic.cpp b/src/Misc/Atomic.cpp
@@ -0,0 +1,70 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ Atomic.cpp - Simple Atomic operation wrapper
+ Copyright (C) 2009-2009 Mark McCurry
+ Author: Mark McCurry
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License (version 2 or later) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+template<class T>
+Atomic<T>::Atomic(const T &val)
+ :value(val)
+{
+ pthread_mutex_init(&mutex, NULL);
+}
+
+template<class T>
+Atomic<T>::~Atomic()
+{
+ pthread_mutex_destroy(&mutex);
+}
+
+template<class T>
+void Atomic<T>::operator=(const T &nval)
+{
+ pthread_mutex_lock(&mutex);
+ value = nval;
+ pthread_mutex_unlock(&mutex);
+}
+
+template<class T>
+T Atomic<T>::operator()() const
+{
+ T tmp;
+ pthread_mutex_lock(&mutex);
+ tmp = value;
+ pthread_mutex_unlock(&mutex);
+ return tmp;
+}
+
+template<class T>
+T Atomic<T>::operator++()
+{
+ T tmp;
+ pthread_mutex_lock(&mutex);
+ tmp = ++value;
+ pthread_mutex_unlock(&mutex);
+ return tmp;
+}
+
+template<class T>
+T Atomic<T>::operator--(){
+ T tmp;
+ pthread_mutex_lock(&mutex);
+ tmp = --value;
+ pthread_mutex_unlock(&mutex);
+ return tmp;
+}
diff --git a/src/Misc/Atomic.h b/src/Misc/Atomic.h
@@ -0,0 +1,46 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ Atomic.h - Simple Atomic operation wrapper
+ Copyright (C) 2009-2009 Mark McCurry
+ Author: Mark McCurry
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License (version 2 or later) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+#ifndef ATOM_H
+#define ATOM_H
+
+#include <pthread.h>
+
+/**Very simple threaded value container*/
+template<class T>
+class Atomic
+{
+ public:
+ /**Initializes Atom
+ * @param val the value of the atom*/
+ Atomic(const T &val);
+ ~Atomic();
+
+ void operator=(const T &val);
+ T operator()() const;
+ T operator++();
+ T operator--();
+ private:
+ mutable pthread_mutex_t mutex;
+ T value;
+};
+#include "Atomic.cpp"
+#endif
+
diff --git a/src/Misc/Bank.cpp b/src/Misc/Bank.cpp
@@ -340,10 +340,12 @@ int Bank::newbank(const char *newbankdirname)
strncat(bankdir, "/", MAX_STRING_SIZE);
;
strncat(bankdir, newbankdirname, MAX_STRING_SIZE);
-#ifdef OS_WINDOWS
+#if OS_WINDOWS
result = mkdir(bankdir);
-#else
+#elif OS_LINUX || OS_CYGWIN
result = mkdir(bankdir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+#else
+#warning Undefined OS
#endif
if(result < 0)
return -1;
diff --git a/src/Misc/Bank.h b/src/Misc/Bank.h
@@ -24,6 +24,7 @@
#define BANK_H
#include "../globals.h"
+#include "Util.h"
#include "XMLwrapper.h"
#include "Part.h"
diff --git a/src/Misc/CMakeLists.txt b/src/Misc/CMakeLists.txt
@@ -9,6 +9,8 @@ set(zynaddsubfx_misc_SRCS
Part.cpp
Util.cpp
XMLwrapper.cpp
+ Recorder.cpp
+ WavFile.cpp
)
if (LASH_FOUND)
@@ -19,4 +21,4 @@ add_library(zynaddsubfx_misc STATIC
${zynaddsubfx_misc_SRCS}
)
-target_link_libraries(zynaddsubfx_misc zynaddsubfx_output)
+target_link_libraries(zynaddsubfx_misc zynaddsubfx_nio)
diff --git a/src/Misc/Config.cpp b/src/Misc/Config.cpp
@@ -24,7 +24,7 @@
#include <stdlib.h>
#include <string.h>
-#ifdef OS_WINDOWS
+#if OS_WINDOWS
#include <windows.h>
#include <mmsystem.h>
#endif
@@ -32,6 +32,8 @@
#include "Config.h"
#include "XMLwrapper.h"
+using namespace std;
+
Config::Config()
{}
void Config::init()
@@ -105,7 +107,7 @@ void Config::init()
readConfig(filename);
if(cfg.bankRootDirList[0] == NULL) {
-#if defined(OS_LINUX)
+#if OS_LINUX
//banks
cfg.bankRootDirList[0] = new char[MAX_STRING_SIZE];
sprintf(cfg.bankRootDirList[0], "~/banks");
@@ -144,7 +146,7 @@ void Config::init()
}
if(cfg.presetsDirList[0] == NULL) {
-#if defined(OS_LINUX)
+#if OS_LINUX || OS_CYGWIN
//presets
cfg.presetsDirList[0] = new char[MAX_STRING_SIZE];
sprintf(cfg.presetsDirList[0], "./");
@@ -161,7 +163,7 @@ void Config::init()
cfg.presetsDirList[4] = new char[MAX_STRING_SIZE];
sprintf(cfg.presetsDirList[4], "/usr/local/share/zynaddsubfx/presets");
-#else
+#elif OS_WINDOWS
//presets
cfg.presetsDirList[0] = new char[MAX_STRING_SIZE];
sprintf(cfg.presetsDirList[0], "./");
@@ -172,12 +174,16 @@ void Config::init()
#else
cfg.presetsDirList[1] = new char[MAX_STRING_SIZE];
sprintf(cfg.presetsDirList[1], "../presets");
-#endif
+#endif //end vst
cfg.presetsDirList[2] = new char[MAX_STRING_SIZE];
sprintf(cfg.presetsDirList[2], "presets");
-#endif
+#else
+#error Undefined OS
+#endif //end OS
}
+ cfg.LinuxALSAaudioDev = "default";
+ cfg.nameTag = "";
}
Config::~Config()
@@ -394,8 +400,10 @@ void Config::getConfigFileName(char *name, int namesize)
name[0] = 0;
#ifdef OS_LINUX
snprintf(name, namesize, "%s%s", getenv("HOME"), "/.zynaddsubfxXML.cfg");
-#else
+#elif OS_WINDOWS || OS_CYGWIN
snprintf(name, namesize, "%s", "zynaddsubfxXML.cfg");
+#else
+#error Undefined OS
#endif
}
diff --git a/src/Misc/Config.h b/src/Misc/Config.h
@@ -23,6 +23,7 @@
#ifndef CONFIG_H
#define CONFIG_H
#include "../globals.h"
+#include <string>
#define MAX_STRING_SIZE 4000
#define MAX_BANK_ROOT_DIRS 100
@@ -48,6 +49,8 @@ class Config
int CheckPADsynth;
int UserInterfaceMode;
int VirKeybLayout;
+ std::string LinuxALSAaudioDev;
+ std::string nameTag;
} cfg;
int winwavemax, winmidimax; //number of wave/midi devices on Windows
int maxstringsize;
diff --git a/src/Misc/Makefile b/src/Misc/Makefile
@@ -1,18 +0,0 @@
-include ../Makefile.inc
-
-objects=Bank.o Master.o Microtonal.o Part.o Util.o Config.o Dump.o XMLwrapper.o
-
-ifeq ($(LINUX_USE_LASH),YES)
-objects += LASHClient.o
-endif
-
-
-all: $(objects)
-
--include ../Make.deps
-
-.PHONY : clean
-clean:
- rm -f $(objects)
- rm -f makeinclude.deps
-
diff --git a/src/Misc/Master.cpp b/src/Misc/Master.cpp
@@ -21,46 +21,42 @@
*/
+#warning TODO move Sequencer out of master
+
#include "Master.h"
+#include "../Params/LFOParams.h"
+#include "../Effects/EffectMgr.h"
+
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <iostream>
#include <unistd.h>
+using namespace std;
+
Master::Master()
{
swaplr = 0;
pthread_mutex_init(&mutex, NULL);
+ pthread_mutex_init(&vumutex, NULL);
fft = new FFTwrapper(OSCIL_SIZE);
tmpmixl = new REALTYPE[SOUND_BUFFER_SIZE];
tmpmixr = new REALTYPE[SOUND_BUFFER_SIZE];
- audiooutl = new REALTYPE[SOUND_BUFFER_SIZE];
- audiooutr = new REALTYPE[SOUND_BUFFER_SIZE];
- ksoundbuffersample = -1; //this is only time when this is -1; this means that the GetAudioOutSamples was never called
- ksoundbuffersamplelow = 0.0;
- oldsamplel = 0.0;
- oldsampler = 0.0;
shutup = 0;
for(int npart = 0; npart < NUM_MIDI_PARTS; npart++) {
vuoutpeakpart[npart] = 1e-9;
fakepeakpart[npart] = 0;
}
- for(int i = 0; i < SOUND_BUFFER_SIZE; i++) {
- audiooutl[i] = 0.0;
- audiooutr[i] = 0.0;
- }
-
for(int npart = 0; npart < NUM_MIDI_PARTS; npart++)
part[npart] = new Part(µtonal, fft, &mutex);
-
-
//Insertion Effects init
for(int nefx = 0; nefx < NUM_INS_EFX; nefx++)
insefx[nefx] = new EffectMgr(1, &mutex);
@@ -109,24 +105,25 @@ void Master::defaults()
ShutUp();
}
-/*
- * Note On Messages (velocity=0 for NoteOff)
- */
-void Master::NoteOn(unsigned char chan,
- unsigned char note,
- unsigned char velocity)
+bool Master::mutexLock(lockset request)
{
- dump.dumpnote(chan, note, velocity);
-
- noteon(chan, note, velocity);
+ switch (request)
+ {
+ case MUTEX_TRYLOCK:
+ return !pthread_mutex_trylock(&mutex);
+ case MUTEX_LOCK:
+ return !pthread_mutex_lock(&mutex);
+ case MUTEX_UNLOCK:
+ return !pthread_mutex_unlock(&mutex);
+ }
+ return false;
}
+
/*
- * Internal Note On (velocity=0 for NoteOff)
+ * Note On Messages (velocity=0 for NoteOff)
*/
-void Master::noteon(unsigned char chan,
- unsigned char note,
- unsigned char velocity)
+void Master::noteOn(char chan, char note, char velocity)
{
int npart;
if(velocity != 0) {
@@ -139,25 +136,14 @@ void Master::noteon(unsigned char chan,
}
}
else
- this->NoteOff(chan, note);
- ;
+ this->noteOff(chan, note);
HDDRecorder.triggernow();
}
/*
* Note Off Messages
*/
-void Master::NoteOff(unsigned char chan, unsigned char note)
-{
- dump.dumpnote(chan, note, 0);
-
- noteoff(chan, note);
-}
-
-/*
- * Internal Note Off
- */
-void Master::noteoff(unsigned char chan, unsigned char note)
+void Master::noteOff(char chan, char note)
{
int npart;
for(npart = 0; npart < NUM_MIDI_PARTS; npart++)
@@ -169,17 +155,7 @@ void Master::noteoff(unsigned char chan, unsigned char note)
/*
* Controllers
*/
-void Master::SetController(unsigned char chan, unsigned int type, int par)
-{
- dump.dumpcontroller(chan, type, par);
-
- setcontroller(chan, type, par);
-}
-
-/*
- * Internal Controllers
- */
-void Master::setcontroller(unsigned char chan, unsigned int type, int par)
+void Master::setController(char chan, int type, int par)
{
if((type == C_dataentryhi) || (type == C_dataentrylo)
|| (type == C_nrpnhi) || (type == C_nrpnlo)) { //Process RPN and NRPN by the Master (ignore the chan)
@@ -217,6 +193,52 @@ void Master::setcontroller(unsigned char chan, unsigned int type, int par)
}
}
+void Master::vuUpdate(const REALTYPE *outl, const REALTYPE *outr)
+{
+ //Peak computation (for vumeters)
+ vu.outpeakl = 1e-12;
+ vu.outpeakr = 1e-12;
+ for(int i = 0; i < SOUND_BUFFER_SIZE; i++) {
+ if(fabs(outl[i]) > vu.outpeakl)
+ vu.outpeakl = fabs(outl[i]);
+ if(fabs(outr[i]) > vu.outpeakr)
+ vu.outpeakr = fabs(outr[i]);
+ }
+ if((vu.outpeakl > 1.0) || (vu.outpeakr > 1.0))
+ vu.clipped = 1;
+ if(vu.maxoutpeakl < vu.outpeakl)
+ vu.maxoutpeakl = vu.outpeakl;
+ if(vu.maxoutpeakr < vu.outpeakr)
+ vu.maxoutpeakr = vu.outpeakr;
+
+ //RMS Peak computation (for vumeters)
+ vu.rmspeakl = 1e-12;
+ vu.rmspeakr = 1e-12;
+ for(int i = 0; i < SOUND_BUFFER_SIZE; i++) {
+ vu.rmspeakl += outl[i] * outl[i];
+ vu.rmspeakr += outr[i] * outr[i];
+ }
+ vu.rmspeakl = sqrt(vu.rmspeakl / SOUND_BUFFER_SIZE);
+ vu.rmspeakr = sqrt(vu.rmspeakr / SOUND_BUFFER_SIZE);
+
+ //Part Peak computation (for Part vumeters or fake part vumeters)
+ for(int npart = 0; npart < NUM_MIDI_PARTS; npart++) {
+ vuoutpeakpart[npart] = 1.0e-12;
+ if(part[npart]->Penabled != 0) {
+ REALTYPE *outl = part[npart]->partoutl,
+ *outr = part[npart]->partoutr;
+ for(int i = 0; i < SOUND_BUFFER_SIZE; i++) {
+ REALTYPE tmp = fabs(outl[i] + outr[i]);
+ if(tmp > vuoutpeakpart[npart])
+ vuoutpeakpart[npart] = tmp;
+ }
+ vuoutpeakpart[npart] *= volume;
+ }
+ else
+ if(fakepeakpart[npart] > 1)
+ fakepeakpart[npart]--;
+ }
+}
/*
* Enable/Disable a part
@@ -392,9 +414,11 @@ void Master::AudioOut(REALTYPE *outl, REALTYPE *outr)
//Mix all parts
for(npart = 0; npart < NUM_MIDI_PARTS; npart++) {
- for(i = 0; i < SOUND_BUFFER_SIZE; i++) { //the volume did not changed
- outl[i] += part[npart]->partoutl[i];
- outr[i] += part[npart]->partoutr[i];
+ if(part[npart]->Penabled) { //only mix active parts
+ for(i = 0; i < SOUND_BUFFER_SIZE; i++) { //the volume did not changed
+ outl[i] += part[npart]->partoutl[i];
+ outr[i] += part[npart]->partoutr[i];
+ }
}
}
@@ -410,49 +434,9 @@ void Master::AudioOut(REALTYPE *outl, REALTYPE *outr)
outr[i] *= volume;
}
- //Peak computation (for vumeters)
- vuoutpeakl = 1e-12;
- vuoutpeakr = 1e-12;
- for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
- if(fabs(outl[i]) > vuoutpeakl)
- vuoutpeakl = fabs(outl[i]);
- if(fabs(outr[i]) > vuoutpeakr)
- vuoutpeakr = fabs(outr[i]);
- }
- if((vuoutpeakl > 1.0) || (vuoutpeakr > 1.0))
- vuclipped = 1;
- if(vumaxoutpeakl < vuoutpeakl)
- vumaxoutpeakl = vuoutpeakl;
- if(vumaxoutpeakr < vuoutpeakr)
- vumaxoutpeakr = vuoutpeakr;
-
- //RMS Peak computation (for vumeters)
- vurmspeakl = 1e-12;
- vurmspeakr = 1e-12;
- for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
- vurmspeakl += outl[i] * outl[i];
- vurmspeakr += outr[i] * outr[i];
- }
- vurmspeakl = sqrt(vurmspeakl / SOUND_BUFFER_SIZE);
- vurmspeakr = sqrt(vurmspeakr / SOUND_BUFFER_SIZE);
-
- //Part Peak computation (for Part vumeters or fake part vumeters)
- for(npart = 0; npart < NUM_MIDI_PARTS; npart++) {
- vuoutpeakpart[npart] = 1.0e-12;
- if(part[npart]->Penabled != 0) {
- REALTYPE *outl = part[npart]->partoutl,
- *outr = part[npart]->partoutr;
- for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
- REALTYPE tmp = fabs(outl[i] + outr[i]);
- if(tmp > vuoutpeakpart[npart])
- vuoutpeakpart[npart] = tmp;
- }
- vuoutpeakpart[npart] *= volume;
- }
- else
- if(fakepeakpart[npart] > 1)
- fakepeakpart[npart]--;
- ;
+ if(!pthread_mutex_trylock(&vumutex)) {
+ vuUpdate(outl, outr);
+ pthread_mutex_unlock(&vumutex);
}
@@ -470,80 +454,9 @@ void Master::AudioOut(REALTYPE *outl, REALTYPE *outr)
//update the LFO's time
LFOParams::time++;
- if(HDDRecorder.recording())
- HDDRecorder.recordbuffer(outl, outr);
dump.inctick();
}
-void Master::GetAudioOutSamples(int nsamples,
- int samplerate,
- REALTYPE *outl,
- REALTYPE *outr)
-{
- if(ksoundbuffersample == -1) { //first time
- AudioOut(&audiooutl[0], &audiooutr[0]);
- ksoundbuffersample = 0;
- }
-
-
- if(samplerate == SAMPLE_RATE) { //no resample
- int ksample = 0;
- while(ksample < nsamples) {
- outl[ksample] = audiooutl[ksoundbuffersample];
- outr[ksample] = audiooutr[ksoundbuffersample];
-
- ksample++;
- ksoundbuffersample++;
- if(ksoundbuffersample >= SOUND_BUFFER_SIZE) {
- AudioOut(&audiooutl[0], &audiooutr[0]);
- ksoundbuffersample = 0;
- }
- }
- }
- else { //Resample
- int ksample = 0;
- REALTYPE srinc = SAMPLE_RATE / (REALTYPE)samplerate;
-
- while(ksample < nsamples) {
- if(ksoundbuffersample != 0) {
- outl[ksample] = audiooutl[ksoundbuffersample]
- * ksoundbuffersamplelow
- + audiooutl[ksoundbuffersample
- - 1] * (1.0 - ksoundbuffersamplelow);
- outr[ksample] = audiooutr[ksoundbuffersample]
- * ksoundbuffersamplelow
- + audiooutr[ksoundbuffersample
- - 1] * (1.0 - ksoundbuffersamplelow);
- }
- else {
- outl[ksample] = audiooutl[ksoundbuffersample]
- * ksoundbuffersamplelow
- + oldsamplel * (1.0 - ksoundbuffersamplelow);
- outr[ksample] = audiooutr[ksoundbuffersample]
- * ksoundbuffersamplelow
- + oldsampler * (1.0 - ksoundbuffersamplelow);
- }
-
- ksample++;
-
- ksoundbuffersamplelow += srinc;
- if(ksoundbuffersamplelow >= 1.0) {
- ksoundbuffersample += (int) floor(ksoundbuffersamplelow);
- ksoundbuffersamplelow = ksoundbuffersamplelow - floor(
- ksoundbuffersamplelow);
- }
-
- if(ksoundbuffersample >= SOUND_BUFFER_SIZE) {
- oldsamplel = audiooutl[SOUND_BUFFER_SIZE - 1];
- oldsampler = audiooutr[SOUND_BUFFER_SIZE - 1];
- AudioOut(&audiooutl[0], &audiooutr[0]);
- ksoundbuffersample = 0;
- }
- }
- }
-}
-
-
Master::~Master()
{
for(int npart = 0; npart < NUM_MIDI_PARTS; npart++)
@@ -553,13 +466,12 @@ Master::~Master()
for(int nefx = 0; nefx < NUM_SYS_EFX; nefx++)
delete sysefx[nefx];
- delete [] audiooutl;
- delete [] audiooutr;
delete [] tmpmixl;
delete [] tmpmixr;
delete (fft);
pthread_mutex_destroy(&mutex);
+ pthread_mutex_destroy(&vumutex);
}
@@ -615,14 +527,29 @@ void Master::ShutUp()
*/
void Master::vuresetpeaks()
{
- vuoutpeakl = 1e-9;
- vuoutpeakr = 1e-9;
- vumaxoutpeakl = 1e-9;
- vumaxoutpeakr = 1e-9;
- vuclipped = 0;
+ pthread_mutex_lock(&vumutex);
+ vu.outpeakl = 1e-9;
+ vu.outpeakr = 1e-9;
+ vu.maxoutpeakl = 1e-9;
+ vu.maxoutpeakr = 1e-9;
+ vu.clipped = 0;
+ pthread_mutex_unlock(&vumutex);
}
-
+vuData Master::getVuData()
+{
+ vuData tmp;
+ pthread_mutex_lock(&vumutex);
+ tmp.outpeakl=vu.outpeakl;
+ tmp.outpeakr=vu.outpeakr;
+ tmp.maxoutpeakl=vu.maxoutpeakl;
+ tmp.maxoutpeakr=vu.maxoutpeakr;
+ tmp.rmspeakl=vu.rmspeakl;
+ tmp.rmspeakr=vu.rmspeakr;
+ tmp.clipped=vu.clipped;
+ pthread_mutex_unlock(&vumutex);
+ return tmp;
+}
void Master::applyparameters()
{
diff --git a/src/Misc/Master.h b/src/Misc/Master.h
@@ -25,17 +25,26 @@
#define MASTER_H
#include "../globals.h"
-#include "../Effects/EffectMgr.h"
-#include "Part.h"
-#include "../Output/Recorder.h"
#include "Microtonal.h"
#include "Bank.h"
+#include "Recorder.h"
+#include "Part.h"
#include "Dump.h"
#include "../Seq/Sequencer.h"
#include "XMLwrapper.h"
+typedef enum { MUTEX_TRYLOCK, MUTEX_LOCK, MUTEX_UNLOCK } lockset;
+
extern Dump dump;
+
+typedef struct vuData_t {
+ REALTYPE outpeakl, outpeakr, maxoutpeakl, maxoutpeakr,
+ rmspeakl, rmspeakr;
+ int clipped;
+} vuData;
+
+
/** It sends Midi Messages to Parts, receives samples from parts,
* process them with system/insertion effects and mix them */
class Master
@@ -69,20 +78,24 @@ class Master
/**put all data from the *data array to zynaddsubfx parameters (used for VST)*/
void putalldata(char *data, int size);
-
+ //Mutex control
+ /**Control the Master's mutex state.
+ * @param lockset either trylock, lock, or unlock.
+ * @return true when successful false otherwise.*/
+ bool mutexLock(lockset request);
//Midi IN
- void NoteOn(unsigned char chan,
- unsigned char note,
- unsigned char velocity);
- void NoteOff(unsigned char chan, unsigned char note);
- void SetController(unsigned char chan, unsigned int type, int par);
+ void noteOn(char chan, char note, char velocity);
+ void noteOff(char chan, char note);
+ void setController(char chan, int type, int par);
//void NRPN...
void ShutUp();
int shutup;
+ void vuUpdate(const REALTYPE *outl, const REALTYPE *outr);
+
/**Audio Output*/
void AudioOut(REALTYPE *outl, REALTYPE *outr);
/**Audio Output (for callback mode). This allows the program to be controled by an external program*/
@@ -112,7 +125,7 @@ class Master
//effects
EffectMgr *sysefx[NUM_SYS_EFX]; //system
EffectMgr *insefx[NUM_INS_EFX]; //insertion
-// void swapcopyeffects(int what,int type,int neff1,int neff2);
+// void swapcopyeffects(int what,int type,int neff1,int neff2);
//HDD recorder
Recorder HDDRecorder;
@@ -120,13 +133,14 @@ class Master
//part that's apply the insertion effect; -1 to disable
short int Pinsparts[NUM_INS_EFX];
+
//peaks for VU-meter
void vuresetpeaks();
- REALTYPE vuoutpeakl, vuoutpeakr, vumaxoutpeakl, vumaxoutpeakr,
- vurmspeakl, vurmspeakr;
- int vuclipped;
+ //get VU-meter data
+ vuData getVuData();
//peaks for part VU-meters
+ /**\todo synchronize this with a mutex*/
REALTYPE vuoutpeakpart[NUM_MIDI_PARTS];
unsigned char fakepeakpart[NUM_MIDI_PARTS]; //this is used to compute the "peak" when the part is disabled
@@ -142,8 +156,12 @@ class Master
FFTwrapper *fft;
pthread_mutex_t mutex;
+ pthread_mutex_t vumutex;
+
private:
+ bool nullRun;
+ vuData vu;
REALTYPE volume;
REALTYPE sysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS];
REALTYPE sysefxsend[NUM_SYS_EFX][NUM_SYS_EFX];
@@ -152,24 +170,7 @@ class Master
REALTYPE *tmpmixl;
REALTYPE *tmpmixr;
-
int keyshift;
-
- //Audio Output samples (if it used GetAudioOutSamples - eg. for Jack output; elsewhere is unused)
- REALTYPE *audiooutl;
- REALTYPE *audiooutr;
-
- int ksoundbuffersample; //this is used to know if there is need to call AudioOut by GetAudioOutSamples method
- REALTYPE ksoundbuffersamplelow; //this is used for resampling (eg. if Jack samplerate!= SAMPLE_RATE)
- REALTYPE oldsamplel, oldsampler; //this is used for resampling
-
- //These are called by the NoteOn, NoteOff,SetController (which are from external sources like MIDI, Virtual Keyboard)
- //and are called by internal parts of the program (like sequencer)
- void noteon(unsigned char chan,
- unsigned char note,
- unsigned char velocity);
- void noteoff(unsigned char chan, unsigned char note);
- void setcontroller(unsigned char chan, unsigned int type, int par);
};
diff --git a/src/Misc/Part.cpp b/src/Misc/Part.cpp
@@ -22,6 +22,13 @@
#include "Part.h"
#include "Microtonal.h"
+#include "../Effects/EffectMgr.h"
+#include "../Params/ADnoteParameters.h"
+#include "../Params/SUBnoteParameters.h"
+#include "../Params/PADnoteParameters.h"
+#include "../Synth/ADnote.h"
+#include "../Synth/SUBnote.h"
+#include "../Synth/PADnote.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
diff --git a/src/Misc/Part.h b/src/Misc/Part.h
@@ -26,20 +26,21 @@
#define MAX_INFO_TEXT_SIZE 1000
#include "../globals.h"
-#include "../Params/ADnoteParameters.h"
-#include "../Params/SUBnoteParameters.h"
-#include "../Params/PADnoteParameters.h"
-#include "../Synth/ADnote.h"
-#include "../Synth/SUBnote.h"
-#include "../Synth/PADnote.h"
#include "../Params/Controller.h"
#include "../Misc/Microtonal.h"
#include "../DSP/FFTwrapper.h"
-#include "../Effects/EffectMgr.h"
#include "XMLwrapper.h"
#include <list> // For the monomemnotes list.
+class EffectMgr;
+class ADnoteParameters;
+class SUBnoteParameters;
+class PADnoteParameters;
+class ADnote;
+class SUBnote;
+class PADnote;
+
/** Part implementation*/
class Part
{
diff --git a/src/Misc/Recorder.cpp b/src/Misc/Recorder.cpp
@@ -0,0 +1,92 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ Recorder.cpp - Records sound to a file
+ Copyright (C) 2002-2005 Nasca Octavian Paul
+ Author: Nasca Octavian Paul
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License (version 2 or later) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#include <sys/stat.h>
+#include "Recorder.h"
+#include "WavFile.h"
+#include "../Nio/OutMgr.h"
+#include "../Nio/WavEngine.h"
+
+Recorder::Recorder()
+ :status(0), notetrigger(0)
+{}
+
+Recorder::~Recorder()
+{
+ if(recording() == 1)
+ stop();
+}
+
+int Recorder::preparefile(std::string filename_, int overwrite)
+{
+ if(!overwrite) {
+ struct stat fileinfo;
+ int statr;
+ statr = stat(filename_.c_str(), &fileinfo);
+ if(statr == 0) //file exists
+ return 1;
+ }
+
+ sysOut->wave->newFile(new WavFile(filename_, SAMPLE_RATE, 2));
+
+ status = 1; //ready
+
+ return 0;
+}
+
+void Recorder::start()
+{
+ notetrigger = 0;
+ status = 2; //recording
+}
+
+void Recorder::stop()
+{
+ sysOut->wave->Stop();
+ sysOut->wave->destroyFile();
+ status = 0;
+}
+
+void Recorder::pause()
+{
+ status = 0;
+ sysOut->wave->Stop();
+}
+
+int Recorder::recording()
+{
+ if((status == 2) && (notetrigger != 0))
+ return 1;
+ else
+ return 0;
+}
+
+void Recorder::triggernow()
+{
+ if(status == 2) {
+ if(notetrigger!=1) {
+ sysOut->wave->Start();
+ }
+ notetrigger = 1;
+ }
+}
+
diff --git a/src/Misc/Recorder.h b/src/Misc/Recorder.h
@@ -0,0 +1,55 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ Recorder.h - Records sound to a file
+ Copyright (C) 2002-2005 Nasca Octavian Paul
+ Author: Nasca Octavian Paul
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License (version 2 or later) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#ifndef RECORDER_H
+#define RECORDER_H
+#include <string>
+#include "../globals.h"
+
+/**Records sound to a file*/
+class Recorder
+{
+ public:
+
+ Recorder();
+ ~Recorder();
+ /**Prepare the given file.
+ * @returns 1 if the file exists */
+ int preparefile(std::string filename_, int overwrite);
+ void start();
+ void stop();
+ void pause();
+ int recording();
+ void triggernow();
+
+ /** Status:
+ * 0 - not ready(no file selected),
+ * 1 - ready
+ * 2 - recording */
+ int status;
+
+ private:
+ int notetrigger;
+};
+
+#endif
+
diff --git a/src/Misc/Stereo.h b/src/Misc/Stereo.h
@@ -30,6 +30,7 @@ class Stereo
/**Initializes Stereo with left and right set to val
* @param val the value for both channels*/
Stereo(const T &val);
+ Stereo() {};
~Stereo() {}
void operator=(const Stereo<T> &smp);
diff --git a/src/Misc/Util.cpp b/src/Misc/Util.cpp
@@ -30,6 +30,13 @@
#include <unistd.h>
#include <errno.h>
#include <string.h>
+#include <sched.h>
+#if OS_WINDOWS
+//used for the sleep func
+#include <winbase.h>
+#include <windows.h>
+#endif
+
int SAMPLE_RATE = 44100;
int SOUND_BUFFER_SIZE = 256;
@@ -113,3 +120,26 @@ bool fileexists(const char *filename)
return false;
}
+void set_realtime()
+{
+#if OS_LINUX || OS_CYGWIN
+ sched_param sc;
+ sc.sched_priority = 60;
+ //if you want get "sched_setscheduler undeclared" from compilation,
+ //you can safely remove the folowing line:
+ sched_setscheduler(0, SCHED_FIFO, &sc);
+ //if (err==0) printf("Real-time");
+#else
+#warning set_realtime() undefined for your opperating system
+#endif
+}
+
+void os_sleep(long length)
+{
+#if OS_LINUX || OS_CYGWIN
+ usleep(length);
+#elif OS_WINDOWS
+ Sleep((long)length/1000);
+#endif
+}
+
diff --git a/src/Misc/Util.h b/src/Misc/Util.h
@@ -38,6 +38,15 @@ extern REALTYPE getdetune(unsigned char type,
unsigned short int coarsedetune,
unsigned short int finedetune);
+/**Try to set current thread to realtime priority program priority
+ * \todo see if the right pid is being sent
+ * \todo see if this is having desired effect, if not then look at
+ * pthread_attr_t*/
+void set_realtime();
+
+/**Os independent sleep in microsecond*/
+void os_sleep(long length);
+
extern REALTYPE *denormalkillbuf; /**<the buffer to add noise in order to avoid denormalisation*/
extern Config config;
@@ -60,5 +69,11 @@ T stringTo(const char *x)
return ans;
}
+template <class T>
+T limit(T val, T min, T max)
+{
+ return (val < min ? min : (val > max ? max : val));
+}
+
#endif
diff --git a/src/Misc/WavFile.cpp b/src/Misc/WavFile.cpp
@@ -0,0 +1,94 @@
+/*
+ Copyright (C) 2006 Nasca Octavian Paul
+ Author: Nasca Octavian Paul
+ Mark McCurry
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License (version 2) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <cstdio>
+#include <cstring>
+#include <cstdlib>
+#include "WavFile.h"
+using namespace std;
+
+WavFile::WavFile(string filename, int samplerate, int channels)
+ :sampleswritten(0), samplerate(samplerate), channels(channels),
+ file(fopen(filename.c_str(), "w"))
+
+{
+ if(file) {
+ //making space for the header written at destruction
+ char tmp[44];
+ memset(tmp, 0, 44*sizeof(char));
+ fwrite(tmp, 1, 44, file);
+ }
+}
+
+WavFile::~WavFile()
+{
+ if(file) {
+ unsigned int chunksize;
+ rewind(file);
+
+ fwrite("RIFF", 4, 1, file);
+ chunksize = sampleswritten * 4 + 36;
+ fwrite(&chunksize, 4, 1, file);
+
+ fwrite("WAVEfmt ", 8, 1, file);
+ chunksize = 16;
+ fwrite(&chunksize, 4, 1, file);
+ unsigned short int formattag = 1; //uncompresed wave
+ fwrite(&formattag, 2, 1, file);
+ unsigned short int nchannels = channels; //stereo
+ fwrite(&nchannels, 2, 1, file);
+ unsigned int samplerate_ = samplerate; //samplerate
+ fwrite(&samplerate_, 4, 1, file);
+ unsigned int bytespersec = samplerate * 2 * channels; //bytes/sec
+ fwrite(&bytespersec, 4, 1, file);
+ unsigned short int blockalign = 2 * channels; //2 channels * 16 bits/8
+ fwrite(&blockalign, 2, 1, file);
+ unsigned short int bitspersample = 16;
+ fwrite(&bitspersample, 2, 1, file);
+
+ fwrite("data", 4, 1, file);
+ chunksize = sampleswritten * blockalign;
+ fwrite(&chunksize, 4, 1, file);
+
+ fclose(file);
+ file = NULL;
+ }
+}
+
+bool WavFile::good() const
+{
+ return NULL != file;
+}
+
+void WavFile::writeStereoSamples(int nsmps, short int *smps)
+{
+ if(file) {
+ fwrite(smps, nsmps, 4, file);
+ sampleswritten += nsmps;
+ }
+}
+
+void WavFile::writeMonoSamples(int nsmps, short int *smps)
+{
+ if(file) {
+ fwrite(smps, nsmps, 2, file);
+ sampleswritten += nsmps;
+ }
+}
+
diff --git a/src/Misc/WavFile.h b/src/Misc/WavFile.h
@@ -0,0 +1,45 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ WavFile.h - Records sound to a file
+ Copyright (C) 2008 Nasca Octavian Paul
+ Author: Nasca Octavian Paul
+ Mark McCurry
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License (version 2) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef WAVFILE_H
+#define WAVFILE_H
+#include <string>
+
+class WavFile
+{
+ public:
+ WavFile(std::string filename, int samplerate, int channels);
+ ~WavFile();
+
+ bool good() const;
+
+ void writeMonoSamples(int nsmps, short int *smps);
+ void writeStereoSamples(int nsmps, short int *smps);
+
+ private:
+ int sampleswritten;
+ int samplerate;
+ int channels;
+ FILE *file;
+};
+#endif
+
diff --git a/src/Nio/AlsaEngine.cpp b/src/Nio/AlsaEngine.cpp
@@ -0,0 +1,351 @@
+/*
+ AlsaEngine.cpp
+
+ Copyright 2009, Alan Calvert
+
+ This file is part of ZynAddSubFX, which is free software: you can
+ redistribute it and/or modify it under the terms of the GNU General
+ Public License as published by the Free Software Foundation, either
+ version 3 of the License, or (at your option) any later version.
+
+ ZynAddSubFX is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with ZynAddSubFX. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <iostream>
+#include <cmath>
+
+using namespace std;
+
+#include "../Misc/Util.h"
+#include "../Misc/Config.h"
+#include "../Misc/Master.h"
+#include "InMgr.h"
+#include "AlsaEngine.h"
+
+AlsaEngine::AlsaEngine(OutMgr *out)
+ :AudioOut(out)
+{
+ name = "ALSA";
+ audio.handle = NULL;
+
+ midi.handle = NULL;
+ midi.alsaId = -1;
+ midi.pThread = 0;
+
+}
+
+AlsaEngine::~AlsaEngine()
+{
+ Stop();
+}
+
+void *AlsaEngine::_AudioThread(void *arg)
+{
+ return (static_cast<AlsaEngine*>(arg))->AudioThread();
+}
+
+void *AlsaEngine::AudioThread()
+{
+ set_realtime();
+ processAudio();
+ return NULL;
+}
+
+bool AlsaEngine::Start()
+{
+ return openAudio() && openMidi();
+}
+
+void AlsaEngine::Stop()
+{
+ if(getMidiEn())
+ setMidiEn(false);
+ if(getAudioEn())
+ setAudioEn(false);
+}
+
+void AlsaEngine::setMidiEn(bool nval)
+{
+ if(nval)
+ openMidi();
+ else
+ stopMidi();
+}
+
+bool AlsaEngine::getMidiEn() const
+{
+ return midi.handle;
+}
+
+void AlsaEngine::setAudioEn(bool nval)
+{
+ if(nval)
+ openAudio();
+ else
+ stopAudio();
+}
+
+bool AlsaEngine::getAudioEn() const
+{
+ return audio.handle;
+}
+
+void *AlsaEngine::_MidiThread(void *arg)
+{
+ return static_cast<AlsaEngine*>(arg)->MidiThread();
+}
+
+
+void *AlsaEngine::MidiThread(void)
+{
+ snd_seq_event_t *event;
+ MidiEvent ev;
+ set_realtime();
+ while (snd_seq_event_input(midi.handle, &event) > 0)
+ {
+ //ensure ev is empty
+ ev.channel = 0;
+ ev.num = 0;
+ ev.value = 0;
+ ev.type = 0;
+
+ if (!event)
+ continue;
+ switch (event->type)
+ {
+ case SND_SEQ_EVENT_NOTEON:
+ if (event->data.note.note)
+ {
+ ev.type = M_NOTE;
+ ev.channel = event->data.note.channel;
+ ev.num = event->data.note.note;
+ ev.value = event->data.note.velocity;
+ sysIn->putEvent(ev);
+ }
+ break;
+
+ case SND_SEQ_EVENT_NOTEOFF:
+ ev.type = M_NOTE;
+ ev.channel = event->data.note.channel;
+ ev.num = event->data.note.note;
+ ev.value = 0;
+ sysIn->putEvent(ev);
+ break;
+
+ case SND_SEQ_EVENT_PITCHBEND:
+ ev.type = M_CONTROLLER;
+ ev.channel = event->data.control.channel;
+ ev.num = C_pitchwheel;
+ ev.value = event->data.control.value;
+ sysIn->putEvent(ev);
+ break;
+
+ case SND_SEQ_EVENT_CONTROLLER:
+ ev.type = M_CONTROLLER;
+ ev.channel = event->data.control.channel;
+ ev.num = event->data.control.param;
+ ev.value = event->data.control.value;
+ sysIn->putEvent(ev);
+ break;
+
+ case SND_SEQ_EVENT_RESET: // reset to power-on state
+ ev.type = M_CONTROLLER;
+ ev.channel = event->data.control.channel;
+ ev.num = C_resetallcontrollers;
+ ev.value = 0;
+ sysIn->putEvent(ev);
+ break;
+
+ case SND_SEQ_EVENT_PORT_SUBSCRIBED: // ports connected
+ if (true)
+ cout << "Info, alsa midi port connected" << endl;
+ break;
+
+ case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: // ports disconnected
+ if (true)
+ cout << "Info, alsa midi port disconnected" << endl;
+ break;
+
+ case SND_SEQ_EVENT_SYSEX: // system exclusive
+ case SND_SEQ_EVENT_SENSING: // midi device still there
+ break;
+
+ default:
+ if (true)
+ cout << "Info, other non-handled midi event, type: "
+ << (int)event->type << endl;
+ break;
+ }
+ snd_seq_free_event(event);
+ }
+ return NULL;
+}
+
+bool AlsaEngine::openMidi()
+{
+ if(getMidiEn())
+ return true;
+
+ int alsaport;
+ midi.handle = NULL;
+
+ if(snd_seq_open(&midi.handle, "default", SND_SEQ_OPEN_INPUT, 0) != 0)
+ return false;
+
+ snd_seq_set_client_name(midi.handle, "ZynAddSubFX");
+
+ alsaport = snd_seq_create_simple_port(
+ midi.handle,
+ "ZynAddSubFX",
+ SND_SEQ_PORT_CAP_WRITE
+ | SND_SEQ_PORT_CAP_SUBS_WRITE,
+ SND_SEQ_PORT_TYPE_SYNTH);
+ if(alsaport < 0)
+ return false;
+
+ pthread_attr_t attr;
+
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ pthread_create(&midi.pThread, &attr, _MidiThread, this);
+ return true;
+}
+
+void AlsaEngine::stopMidi()
+{
+ if(!getMidiEn())
+ return;
+
+ snd_seq_t *handle = midi.handle;
+ if (NULL != midi.handle && midi.pThread)
+ pthread_cancel(midi.pThread);
+ midi.handle = NULL;
+ if(handle)
+ snd_seq_close(handle);
+}
+
+const short *AlsaEngine::interleave(const Stereo<Sample> smps)const
+{
+ /**\todo TODO fix repeated allocation*/
+ short *shortInterleaved = new short[smps.l().size()*2];
+ memset(shortInterleaved,0,smps.l().size()*2*sizeof(short));
+ int idx = 0;//possible off by one error here
+ double scaled;
+ for (int frame = 0; frame < smps.l().size(); ++frame)
+ { // with a nod to libsamplerate ...
+ scaled = smps.l()[frame] * (8.0 * 0x10000000);
+ shortInterleaved[idx++] = (short int)(lrint(scaled) >> 16);
+ scaled = smps.r()[frame] * (8.0 * 0x10000000);
+ shortInterleaved[idx++] = (short int)(lrint(scaled) >> 16);
+ }
+ return shortInterleaved;
+}
+
+bool AlsaEngine::openAudio()
+{
+ if(getAudioEn())
+ return true;
+
+ int rc = 0;
+ /* Open PCM device for playback. */
+ audio.handle=NULL;
+ rc = snd_pcm_open(&audio.handle, "hw:0",
+ SND_PCM_STREAM_PLAYBACK, 0);
+ if (rc < 0) {
+ fprintf(stderr,
+ "unable to open pcm device: %s\n",
+ snd_strerror(rc));
+ return false;
+ }
+
+ /* Allocate a hardware parameters object. */
+ snd_pcm_hw_params_alloca(&audio.params);
+
+ /* Fill it in with default values. */
+ snd_pcm_hw_params_any(audio.handle, audio.params);
+
+ /* Set the desired hardware parameters. */
+
+ /* Interleaved mode */
+ snd_pcm_hw_params_set_access(audio.handle, audio.params,
+ SND_PCM_ACCESS_RW_INTERLEAVED);
+
+ /* Signed 16-bit little-endian format */
+ snd_pcm_hw_params_set_format(audio.handle, audio.params,
+ SND_PCM_FORMAT_S16_LE);
+
+ /* Two channels (stereo) */
+ snd_pcm_hw_params_set_channels(audio.handle, audio.params, 2);
+
+ audio.sampleRate = SAMPLE_RATE;
+ snd_pcm_hw_params_set_rate_near(audio.handle, audio.params,
+ &audio.sampleRate, NULL);
+
+ audio.frames = 512;
+ snd_pcm_hw_params_set_period_size_near(audio.handle,
+ audio.params, &audio.frames, NULL);
+
+ audio.periods = 4;
+ snd_pcm_hw_params_set_periods_near(audio.handle,
+ audio.params, &audio.periods, NULL);
+
+ /* Write the parameters to the driver */
+ rc = snd_pcm_hw_params(audio.handle, audio.params);
+ if (rc < 0) {
+ fprintf(stderr,
+ "unable to set hw parameters: %s\n",
+ snd_strerror(rc));
+ return false;
+ }
+
+ /* Set buffer size (in frames). The resulting latency is given by */
+ /* latency = periodsize * periods / (rate * bytes_per_frame) */
+ snd_pcm_hw_params_set_buffer_size(audio.handle, audio.params, SOUND_BUFFER_SIZE);
+
+ //snd_pcm_hw_params_get_period_size(audio.params, &audio.frames, NULL);
+ //snd_pcm_hw_params_get_period_time(audio.params, &val, NULL);
+
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+ pthread_create(&audio.pThread, &attr, _AudioThread, this);
+ return true;
+}
+
+void AlsaEngine::stopAudio()
+{
+ if(!getAudioEn())
+ return;
+
+ snd_pcm_t *handle = audio.handle;
+ audio.handle = NULL;
+ pthread_join(audio.pThread, NULL);
+ snd_pcm_drain(handle);
+ snd_pcm_close(handle);
+}
+
+void AlsaEngine::processAudio()
+{
+ int rc;
+ while (audio.handle) {
+ audio.buffer = interleave(getNext());
+ snd_pcm_t *handle = audio.handle;
+ if(handle)
+ rc = snd_pcm_writei(handle, audio.buffer, SOUND_BUFFER_SIZE);
+ delete[] audio.buffer;
+ if (rc == -EPIPE) {
+ /* EPIPE means underrun */
+ cerr << "underrun occurred" << endl;
+ snd_pcm_prepare(handle);
+ }
+ else if (rc < 0)
+ cerr << "error from writei: " << snd_strerror(rc) << endl;
+ }
+ pthread_exit(NULL);
+}
diff --git a/src/Nio/AlsaEngine.h b/src/Nio/AlsaEngine.h
@@ -0,0 +1,82 @@
+/*
+ AlsaEngine.h
+
+ Copyright 2009, Alan Calvert
+
+ This file is part of ZynAddSubFX, which is free software: you can
+ redistribute it and/or modify it under the terms of the GNU General
+ Public License as published by the Free Software Foundation, either
+ version 3 of the License, or (at your option) any later version.
+
+ ZynAddSubFX is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with ZynAddSubFX. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef ALSA_ENGINE_H
+#define ALSA_ENGINE_H
+
+#include <pthread.h>
+#include <string>
+#include <alsa/asoundlib.h>
+#include <queue>
+
+#include "AudioOut.h"
+#include "MidiIn.h"
+#include "OutMgr.h"
+#include "../Misc/Stereo.h"
+#include "../Samples/Sample.h"
+
+class AlsaEngine : public AudioOut, MidiIn
+{
+ public:
+ AlsaEngine(OutMgr *out);
+ ~AlsaEngine();
+
+ bool Start();
+ void Stop();
+
+ void setAudioEn(bool nval);
+ bool getAudioEn() const;
+ void setMidiEn(bool nval);
+ bool getMidiEn() const;
+
+ protected:
+ void *AudioThread();
+ static void *_AudioThread(void *arg);
+ void *MidiThread();
+ static void *_MidiThread(void *arg);
+
+ private:
+ bool openMidi();
+ void stopMidi();
+ bool openAudio();
+ void stopAudio();
+
+ const short *interleave(const Stereo<Sample> smps) const;
+
+ struct {
+ std::string device;
+ snd_seq_t *handle;
+ int alsaId;
+ pthread_t pThread;
+ } midi;
+
+ struct {
+ snd_pcm_t *handle;
+ snd_pcm_hw_params_t *params;
+ unsigned int sampleRate;
+ snd_pcm_uframes_t frames;
+ unsigned int periods;
+ const short *buffer;
+ pthread_t pThread;
+ } audio;
+
+ void processAudio();
+};
+
+#endif
diff --git a/src/Nio/AudioOut.cpp b/src/Nio/AudioOut.cpp
@@ -0,0 +1,92 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ AudioOut.h - Audio Output superclass
+ Copyright (C) 2009-2010 Mark McCurry
+ Author: Mark McCurry
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License (version 2 or later) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#include <iostream>
+#include <cstring>
+#include "SafeQueue.h"
+
+using namespace std;
+
+#include "OutMgr.h"
+#include "../Misc/Master.h"
+#include "AudioOut.h"
+
+struct AudioOut::Data
+{
+ Data(OutMgr *out);
+
+ int samplerate;
+ int bufferSize;
+
+ Stereo<Sample> current;/**<used for xrun defence*/
+
+ OutMgr *manager;
+};
+
+AudioOut::Data::Data(OutMgr *out)
+ :samplerate(SAMPLE_RATE),bufferSize(SOUND_BUFFER_SIZE),
+ current(Sample(SOUND_BUFFER_SIZE,0.0)),manager(out)
+{}
+
+AudioOut::AudioOut(OutMgr *out)
+ :dat(new Data(out))
+{}
+
+AudioOut::~AudioOut()
+{
+ delete dat;
+}
+
+void AudioOut::setSamplerate(int _samplerate)
+{
+ dat->samplerate = _samplerate;
+}
+
+int AudioOut::getSampleRate()
+{
+ return dat->samplerate;
+}
+
+void AudioOut::setBufferSize(int _bufferSize)
+{
+ dat->bufferSize = _bufferSize;
+}
+
+//delete me
+void AudioOut::bufferingSize(int nBuffering)
+{
+ //dat->buffering = nBuffering;
+}
+
+//delete me
+int AudioOut::bufferingSize()
+{
+ //return dat->buffering;
+}
+
+const Stereo<Sample> AudioOut::getNext(bool wait)
+{
+ Stereo<REALTYPE *> tmp = sysOut->tick(dat->bufferSize);
+
+ //stop the samples
+ return Stereo<Sample>(Sample(dat->bufferSize, tmp.l()), Sample(dat->bufferSize, tmp.r()));
+}
diff --git a/src/Nio/AudioOut.h b/src/Nio/AudioOut.h
@@ -0,0 +1,63 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ AudioOut.h - Audio Output superclass
+ Copyright (C) 2009-2010 Mark McCurry
+ Author: Mark McCurry
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License (version 2 or later) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#ifndef AUDIO_OUT_H
+#define AUDIO_OUT_H
+
+#include "../Misc/Stereo.h"
+#include "../Samples/Sample.h"
+#include "Engine.h"
+
+class AudioOut : public virtual Engine
+{
+ public:
+ AudioOut(class OutMgr *out);
+ virtual ~AudioOut();
+
+ /**Sets the Sample Rate of this Output
+ * (used for getNext()).*/
+ void setSamplerate(int _samplerate);
+
+ /**Sets the Samples required per Out of this driver
+ * not a realtime opperation */
+ int getSampleRate();
+ void setBufferSize(int _bufferSize);
+
+ /**Sets the Frame Size for output*/
+ void bufferingSize(int nBuffering);
+ int bufferingSize();
+
+ virtual void setAudioEn(bool nval)=0;
+ virtual bool getAudioEn() const=0;
+
+ protected:
+ /**Get the next sample for output.
+ * (has nsamples sampled at a rate of samplerate)*/
+ const Stereo<Sample> getNext(bool wait = false);
+
+ //using opaque pointer to reduce compile times
+ struct Data;
+ Data *dat;
+};
+
+#endif
+
diff --git a/src/Nio/CMakeLists.txt b/src/Nio/CMakeLists.txt
@@ -0,0 +1,55 @@
+#Defaults:
+# - Wave Output (enabled with the record function)
+# - Null Output
+# - Null Output Running by default
+# - Managed with OutMgr
+set(zynaddsubfx_nio_SRCS
+ WavEngine.cpp
+ NulEngine.cpp
+ AudioOut.cpp
+ MidiIn.cpp
+ OutMgr.cpp
+ InMgr.cpp
+ Engine.cpp
+ EngineMgr.cpp
+ )
+
+set(zynaddsubfx_nio_lib )
+
+if (DefaultOutput STREQUAL alsa)
+ add_definitions(-DALSA_DEFAULT=1)
+elseif(DefaultOutput STREQUAL oss)
+ add_definitions(-DOSS_DEFAULT=1)
+elseif(DefaultOutput STREQUAL jack)
+ add_definitions(-DJACK_DEFAULT=1)
+elseif(DefaultOutput STREQUAL portaudio)
+ add_definitions(-DPORTAUDIO_DEFAULT=1)
+endif()
+
+if(JackEnable)
+ include_directories(${JACK_INCLUDE_DIR})
+ list(APPEND zynaddsubfx_nio_SRCS JackEngine.cpp)
+ list(APPEND zynaddsubfx_nio_lib ${JACK_LIBRARIES})
+endif(JackEnable)
+
+if(PaEnable)
+ include_directories(${PORTAUDIO_INCLUDE_DIR})
+ list(APPEND zynaddsubfx_nio_SRCS PaEngine.cpp)
+ list(APPEND zynaddsubfx_nio_lib ${PORTAUDIO_LIBRARIES})
+endif(PaEnable)
+
+if(AlsaEnable)
+ list(APPEND zynaddsubfx_nio_SRCS AlsaEngine.cpp)
+ list(APPEND zynaddsubfx_nio_lib ${ASOUND_LIBRARY})
+endif(AlsaEnable)
+
+if(OssEnable)
+ list(APPEND zynaddsubfx_nio_SRCS OssEngine.cpp)
+endif(OssEnable)
+
+
+add_library(zynaddsubfx_nio STATIC
+ ${zynaddsubfx_nio_SRCS}
+ )
+
+target_link_libraries(zynaddsubfx_nio zynaddsubfx_misc) #for WavFile
diff --git a/src/Nio/Engine.cpp b/src/Nio/Engine.cpp
@@ -0,0 +1,29 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ Engine.cpp - Audio Driver base class
+ Copyright (C) 2009-2010 Mark McCurry
+ Author: Mark McCurry
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License (version 2 or later) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+#include "Engine.h"
+
+Engine::Engine()
+{};
+
+Engine::~Engine()
+{};
+
diff --git a/src/Nio/Engine.h b/src/Nio/Engine.h
@@ -0,0 +1,41 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ Engine.h - Audio Driver base class
+ Copyright (C) 2009-2010 Mark McCurry
+ Author: Mark McCurry
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License (version 2 or later) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#ifndef ENGINE_H
+#define ENGINE_H
+#include <string>
+/**Marker for input/output driver*/
+class Engine
+{
+ public:
+ Engine();
+ virtual ~Engine();
+
+ /**Start the Driver with all capabilities
+ * @return true on success*/
+ virtual bool Start()=0;
+ /**Completely stop the Driver*/
+ virtual void Stop()=0;
+
+ std::string name;
+};
+#endif
diff --git a/src/Nio/EngineMgr.cpp b/src/Nio/EngineMgr.cpp
@@ -0,0 +1,150 @@
+#include "EngineMgr.h"
+#include <algorithm>
+#include <iostream>
+#include "InMgr.h"
+#include "OutMgr.h"
+#include "AudioOut.h"
+#include "MidiIn.h"
+#include "NulEngine.h"
+#if OSS
+#include "OssEngine.h"
+#endif
+#if ALSA
+#include "AlsaEngine.h"
+#endif
+#if JACK
+#include "JackEngine.h"
+#endif
+#if PORTAUDIO
+#include "PaEngine.h"
+#endif
+
+using namespace std;
+
+EngineMgr *sysEngine;
+
+EngineMgr::EngineMgr()
+{
+ Engine *defaultEng = NULL;
+
+ //conditional compiling mess (but contained)
+ engines.push_back(defaultEng = new NulEngine(sysOut));
+#if OSS
+#if OSS_DEFAULT
+ engines.push_back(defaultEng = new OssEngine(sysOut));
+#else
+ engines.push_back(new OssEngine(sysOut));
+#endif
+#endif
+#if ALSA
+#if ALSA_DEFAULT
+ engines.push_back(defaultEng = new AlsaEngine(sysOut));
+#else
+ engines.push_back(new AlsaEngine(sysOut));
+#endif
+#endif
+#if JACK
+#if JACK_DEFAULT
+ engines.push_back(defaultEng = new JackEngine(sysOut));
+#else
+ engines.push_back(new JackEngine(sysOut));
+#endif
+#endif
+#if PORTAUDIO
+#if PORTAUDIO_DEFAULT
+ engines.push_back(defaultEng = new PaEngine(sysOut));
+#else
+ engines.push_back(new PaEngine(sysOut));
+#endif
+#endif
+
+ defaultOut = dynamic_cast<AudioOut *>(defaultEng);
+
+ defaultIn = dynamic_cast<MidiIn *>(defaultEng);
+};
+
+EngineMgr::~EngineMgr()
+{
+ for(list<Engine*>::iterator itr = engines.begin();
+ itr != engines.end(); ++itr) {
+ delete *itr;
+ }
+}
+
+Engine *EngineMgr::getEng(string name)
+{
+ transform(name.begin(), name.end(), name.begin(), ::toupper);
+ for(list<Engine*>::iterator itr = engines.begin();
+ itr != engines.end(); ++itr) {
+ if((*itr)->name == name) {
+ return *itr;
+ }
+ }
+ return NULL;
+}
+
+void EngineMgr::start()
+{
+ if(!(defaultOut&&defaultIn)) {
+ cerr << "ERROR: It looks like someone broke the Nio Output\n"
+ << " Attempting to recover by defaulting to the\n"
+ << " Null Engine." << endl;
+ defaultOut = dynamic_cast<AudioOut *>(getEng("NULL"));
+ defaultIn = dynamic_cast<MidiIn *>(getEng("NULL"));
+ }
+
+ sysOut->currentOut = defaultOut;
+ sysIn->current = defaultIn;
+
+ //open up the default output(s)
+ cout << "Starting Audio: " << defaultOut->name << endl;
+ defaultOut->setAudioEn(true);
+ if(defaultOut->getAudioEn()) {
+ cout << "Audio Started" << endl;
+ }
+ else {
+ cerr << "ERROR: The default audio output failed to open!" << endl;
+ sysOut->currentOut = dynamic_cast<AudioOut *>(sysEngine->getEng("NULL"));
+ sysOut->currentOut->setAudioEn(true);
+ }
+
+ cout << "Starting MIDI: " << defaultIn->name << endl;
+ defaultIn->setMidiEn(true);
+ if(defaultIn->getMidiEn()) {
+ cout << "MIDI Started" << endl;
+ }
+ else { //recover
+ cerr << "ERROR: The default MIDI input failed to open!" << endl;
+ sysIn->current = dynamic_cast<MidiIn *>(sysEngine->getEng("NULL"));
+ sysIn->current->setMidiEn(true);
+ }
+}
+
+void EngineMgr::stop()
+{
+ for(list<Engine*>::iterator itr = engines.begin();
+ itr != engines.end(); ++itr)
+ (*itr)->Stop();
+}
+
+bool EngineMgr::setInDefault(string name)
+{
+ MidiIn *chosen;
+ if((chosen = dynamic_cast<MidiIn *>(getEng(name)))){ //got the input
+ defaultIn = chosen;
+ return true;
+ }
+ return false;
+}
+
+bool EngineMgr::setOutDefault(string name)
+{
+ AudioOut *chosen;
+ if((chosen = dynamic_cast<AudioOut *>(getEng(name)))){ //got the output
+ defaultOut = chosen;
+ return true;
+ }
+ return false;
+}
+
+
diff --git a/src/Nio/EngineMgr.h b/src/Nio/EngineMgr.h
@@ -0,0 +1,43 @@
+#ifndef ENGINE_MGR_H
+#define ENGINE_MGR_H
+
+#include <list>
+#include <string>
+#include "Engine.h"
+
+
+class MidiIn;
+class AudioOut;
+class OutMgr;
+/**Container/Owner of the long lived Engines*/
+struct EngineMgr
+{
+ EngineMgr();
+ ~EngineMgr();
+
+ /**Gets requested engine
+ * @param name case unsensitive name of engine
+ * @return pointer to Engine or NULL
+ */
+ Engine *getEng(std::string name);
+
+ /**Start up defaults*/
+ void start();
+
+ /**Stop all engines*/
+ void stop();
+
+ std::list<Engine *> engines;
+
+ //return false on failure
+ bool setInDefault(std::string name);
+ bool setOutDefault(std::string name);
+
+ //default I/O
+ AudioOut *defaultOut;
+ MidiIn *defaultIn;
+};
+
+extern EngineMgr *sysEngine;
+#endif
+
diff --git a/src/Nio/InMgr.cpp b/src/Nio/InMgr.cpp
@@ -0,0 +1,101 @@
+#include "InMgr.h"
+#include "MidiIn.h"
+#include "EngineMgr.h"
+#include "../Misc/Master.h"
+#include <iostream>
+
+using namespace std;
+
+InMgr *sysIn;
+
+ostream &operator<<(ostream &out, const MidiEvent& ev)
+{
+ if(ev.type == M_NOTE)
+ out << "MidiNote: note(" << ev.num << ")\n"
+ << " channel(" << ev.channel << ")\n"
+ << " velocity(" << ev.value << ")";
+ else
+ out << "MidiCtl: controller(" << ev.num << ")\n"
+ << " channel(" << ev.channel << ")\n"
+ << " value(" << ev.value << ")";
+ return out;
+}
+
+MidiEvent::MidiEvent()
+ :channel(0),type(0),num(0),value(0)
+{}
+
+InMgr::InMgr(Master *_master)
+ :queue(100), master(_master)
+{
+ current = NULL;
+ sem_init(&work, PTHREAD_PROCESS_PRIVATE, 0);
+}
+
+InMgr::~InMgr()
+{
+ //lets stop the consumer thread
+ sem_destroy(&work);
+}
+
+void InMgr::putEvent(MidiEvent ev)
+{
+ if(queue.push(ev)) //check for error
+ cerr << "ERROR: Midi Ringbuffer is FULL" << endl;
+ else
+ sem_post(&work);
+}
+
+void InMgr::flush()
+{
+ MidiEvent ev;
+ while(!sem_trywait(&work)) {
+ queue.pop(ev);
+ cout << ev << endl;
+
+ if(M_NOTE == ev.type) {
+ dump.dumpnote(ev.channel, ev.num, ev.value);
+
+ if(ev.value)
+ master->noteOn(ev.channel, ev.num, ev.value);
+ else
+ master->noteOff(ev.channel, ev.num);
+ }
+ else {
+ dump.dumpcontroller(ev.channel, ev.num, ev.value);
+ master->setController(ev.channel, ev.num, ev.value);
+ }
+ }
+}
+
+bool InMgr::setSource(string name)
+{
+ MidiIn *src = NULL;
+ for(list<Engine*>::iterator itr = sysEngine->engines.begin();
+ itr != sysEngine->engines.end(); ++itr) {
+ MidiIn *in = dynamic_cast<MidiIn *>(*itr);
+ if(in && in->name == name) {
+ src = in;
+ break;
+ }
+ }
+
+ if(!src)
+ return false;
+
+ if(current)
+ current->setMidiEn(false);
+ current = src;
+ current->setMidiEn(true);
+
+ return current->getMidiEn();
+}
+
+string InMgr::getSource() const
+{
+ if(current)
+ return current->name;
+ else
+ return "ERROR";
+}
+
diff --git a/src/Nio/InMgr.h b/src/Nio/InMgr.h
@@ -0,0 +1,52 @@
+#ifndef INMGR_H
+#define INMGR_H
+
+#include <string>
+#include <semaphore.h>
+#include "SafeQueue.h"
+
+enum midi_type{
+ M_NOTE = 1,
+ M_CONTROLLER = 2
+}; //type=1 for note, type=2 for controller
+
+struct MidiEvent
+{
+ MidiEvent();
+ int channel; //the midi channel for the event
+ int type; //type=1 for note, type=2 for controller
+ int num; //note or contoller number
+ int value; //velocity or controller value
+};
+
+class Master;
+class MidiIn;
+//super simple class to manage the inputs
+class InMgr
+{
+ public:
+ InMgr(Master *nmaster);
+ ~InMgr();
+
+ void putEvent(MidiEvent ev);
+
+ /**Flush the Midi Queue*/
+ void flush();
+
+ bool setSource(std::string name);
+
+ std::string getSource() const;
+
+ friend class EngineMgr;
+ private:
+ SafeQueue<MidiEvent> queue;
+ sem_t work;
+ MidiIn *current;
+
+ /**the link to the rest of zyn*/
+ Master *master;
+};
+
+extern InMgr *sysIn;
+#endif
+
diff --git a/src/Nio/JackEngine.cpp b/src/Nio/JackEngine.cpp
@@ -0,0 +1,349 @@
+/*
+ JackEngine.cpp
+
+ Copyright 2009, Alan Calvert
+
+ This file is part of yoshimi, which is free software: you can
+ redistribute it and/or modify it under the terms of the GNU General
+ Public License as published by the Free Software Foundation, either
+ version 3 of the License, or (at your option) any later version.
+
+ yoshimi is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with yoshimi. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <iostream>
+
+#include <jack/midiport.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include "InMgr.h"
+
+#include "../Misc/Master.h"
+#include "JackEngine.h"
+
+using namespace std;
+
+JackEngine::JackEngine(OutMgr *out)
+ :AudioOut(out), jackClient(NULL)
+{
+ name = "JACK";
+ audio.jackSamplerate = 0;
+ audio.jackNframes = 0;
+ for (int i = 0; i < 2; ++i)
+ {
+ audio.ports[i] = NULL;
+ audio.portBuffs[i] = NULL;
+ }
+}
+
+bool JackEngine::connectServer(string server)
+{
+ bool autostart_jack = true;
+ if(jackClient)
+ return true;
+
+
+ string clientname = "zynaddsubfx";
+ jack_status_t jackstatus;
+ bool use_server_name = server.size() && server.compare("default") != 0;
+ jack_options_t jopts = (jack_options_t)
+ (((use_server_name) ? JackServerName : JackNullOption)
+ | ((autostart_jack) ? JackNullOption : JackNoStartServer));
+ if (use_server_name)
+ jackClient = jack_client_open(clientname.c_str(), jopts, &jackstatus,
+ server.c_str());
+ else
+ jackClient = jack_client_open(clientname.c_str(), jopts, &jackstatus);
+ if (NULL != jackClient)
+ return true;
+ else
+ cerr << "Error, failed to open jack client on server: " << server
+ << " status " << jackstatus << endl;
+ return false;
+
+ return true;
+}
+
+bool JackEngine::connectJack()
+{
+ connectServer("");
+ if (NULL != jackClient)
+ {
+ setBufferSize(jack_get_buffer_size(jackClient));
+ int chk;
+ jack_set_error_function(_errorCallback);
+ jack_set_info_function(_infoCallback);
+ if(jack_set_buffer_size_callback(jackClient, _bufferSizeCallback, this))
+ cerr << "Error setting the bufferSize callback" << endl;
+ if ((chk = jack_set_xrun_callback(jackClient, _xrunCallback, this)))
+ cerr << "Error setting jack xrun callback" << endl;
+ if (jack_set_process_callback(jackClient, _processCallback, this))
+ {
+ cerr << "Error, JackEngine failed to set process callback" << endl;
+ return false;
+ }
+ if (jack_activate(jackClient))
+ {
+ cerr << "Error, failed to activate jack client" << endl;;
+ return false;
+ }
+
+ return true;
+ }
+ else
+ cerr << "Error, NULL jackClient through Start()" << endl;
+ return false;
+}
+
+void JackEngine::disconnectJack()
+{
+ if(jackClient) {
+ jack_client_close(jackClient);
+ jackClient = NULL;
+ }
+}
+
+bool JackEngine::Start()
+{
+ return openMidi() && openAudio();
+}
+
+void JackEngine::Stop()
+{
+ stopMidi();
+ stopAudio();
+}
+
+void JackEngine::setMidiEn(bool nval)
+{
+ if(nval)
+ openMidi();
+ else
+ stopMidi();
+}
+
+bool JackEngine::getMidiEn() const
+{
+ return midi.inport;
+}
+
+void JackEngine::setAudioEn(bool nval)
+{
+ if(nval)
+ openAudio();
+ else
+ stopAudio();
+}
+
+bool JackEngine::getAudioEn() const
+{
+ return audio.ports[0];
+}
+
+bool JackEngine::openAudio()
+{
+ if(getAudioEn())
+ return true;
+
+ if(!getMidiEn())
+ if(!connectJack())
+ return false;
+
+
+ const char *portnames[] = { "out_1", "out_2" };
+ for (int port = 0; port < 2; ++port)
+ {
+ audio.ports[port] = jack_port_register(jackClient, portnames[port],
+ JACK_DEFAULT_AUDIO_TYPE,
+ JackPortIsOutput | JackPortIsTerminal, 0);
+ }
+ if (NULL != audio.ports[0] && NULL != audio.ports[1])
+ {
+ audio.jackSamplerate = jack_get_sample_rate(jackClient);
+ audio.jackNframes = jack_get_buffer_size(jackClient);
+ return true;
+ }
+ else
+ cerr << "Error, failed to register jack audio ports" << endl;
+ return false;
+}
+
+void JackEngine::stopAudio()
+{
+ for (int i = 0; i < 2; ++i)
+ {
+ jack_port_t *port = audio.ports[i];
+ audio.ports[i] = NULL;
+ if (NULL != port)
+ jack_port_unregister(jackClient, port);
+ }
+ if(!getMidiEn())
+ disconnectJack();
+}
+
+bool JackEngine::openMidi()
+{
+ if(getMidiEn())
+ return true;
+ if(!getAudioEn())
+ if(!connectJack())
+ return false;
+
+ midi.inport = jack_port_register(jackClient, "midi_input",
+ JACK_DEFAULT_MIDI_TYPE,
+ JackPortIsInput | JackPortIsTerminal, 0);
+ return midi.inport;
+}
+
+void JackEngine::stopMidi()
+{
+ jack_port_t *port = midi.inport;
+ midi.inport = NULL;
+ if(port)
+ jack_port_unregister(jackClient, port);
+
+ if(!getAudioEn())
+ disconnectJack();
+}
+
+int JackEngine::clientId()
+{
+ if (NULL != jackClient)
+ return jack_client_thread_id(jackClient);
+ else
+ return -1;
+}
+
+string JackEngine::clientName()
+{
+ if (NULL != jackClient)
+ return string(jack_get_client_name(jackClient));
+ else
+ cerr << "Error, clientName() with null jackClient" << endl;
+ return string("Oh, yoshimi :-(");
+}
+
+int JackEngine::_processCallback(jack_nframes_t nframes, void *arg)
+{
+ return static_cast<JackEngine*>(arg)->processCallback(nframes);
+}
+
+int JackEngine::processCallback(jack_nframes_t nframes)
+{
+ bool okaudio = true;
+
+ if (NULL != audio.ports[0] && NULL != audio.ports[1])
+ okaudio = processAudio(nframes);
+ return okaudio ? 0 : -1;
+}
+
+bool JackEngine::processAudio(jack_nframes_t nframes)
+{
+ for (int port = 0; port < 2; ++port)
+ {
+ audio.portBuffs[port] =
+ (jsample_t*)jack_port_get_buffer(audio.ports[port], nframes);
+ if (NULL == audio.portBuffs[port])
+ {
+ cerr << "Error, failed to get jack audio port buffer: "
+ << port << endl;
+ return false;
+ }
+ }
+
+ Stereo<Sample> smp = getNext();
+
+ //Assumes smp.l().size() == nframes
+ memcpy(audio.portBuffs[0], smp.l().c_buf(), smp.l().size()*sizeof(REALTYPE));
+ memcpy(audio.portBuffs[1], smp.r().c_buf(), smp.r().size()*sizeof(REALTYPE));
+ handleMidi(nframes);
+ return true;
+
+}
+
+int JackEngine::_xrunCallback(void * /*/arg*/)
+{
+ cerr << "Jack reports xrun" << endl;
+ return 0;
+}
+
+void JackEngine::_errorCallback(const char *msg)
+{
+ cerr << "Jack reports error: " << msg << endl;
+}
+
+void JackEngine::_infoCallback(const char *msg)
+{
+ cerr << "Jack info message: " << msg << endl;
+}
+
+int JackEngine::_bufferSizeCallback(jack_nframes_t nframes, void *arg)
+{
+ return static_cast<JackEngine*>(arg)->bufferSizeCallback(nframes);
+}
+
+int JackEngine::bufferSizeCallback(jack_nframes_t nframes)
+{
+ cerr << "Jack buffer resized" << endl;
+ setBufferSize(nframes);
+ return 0;
+}
+
+void JackEngine::handleMidi(unsigned long frames)
+{
+ if(!midi.inport)
+ return;
+ void *midi_buf = jack_port_get_buffer(midi.inport, frames);
+ jack_midi_event_t jack_midi_event;
+ jack_nframes_t event_index = 0;
+ unsigned char *midi_data;
+ unsigned char type;
+
+ while(jack_midi_event_get(&jack_midi_event, midi_buf,
+ event_index++) == 0) {
+ MidiEvent ev;
+ midi_data = jack_midi_event.buffer;
+ type = midi_data[0] & 0xF0;
+ ev.channel = midi_data[0] & 0x0F;
+
+ switch(type) {
+ case 0x80: /* note-off */
+ ev.type = M_NOTE;
+ ev.num = midi_data[1];
+ ev.value = 0;
+ sysIn->putEvent(ev);
+ break;
+
+ case 0x90: /* note-on */
+ ev.type = M_NOTE;
+ ev.num = midi_data[1];
+ ev.value = midi_data[2];
+ sysIn->putEvent(ev);
+ break;
+
+ case 0xB0: /* controller */
+ ev.type = M_CONTROLLER;
+ ev.num = midi_data[1];
+ ev.value = midi_data[2];
+ sysIn->putEvent(ev);
+ break;
+
+ case 0xE0: /* pitch bend */
+ ev.type = M_CONTROLLER;
+ ev.num = C_pitchwheel;
+ ev.value = ((midi_data[2] << 7) | midi_data[1]);
+ sysIn->putEvent(ev);
+ break;
+
+ /* XXX TODO: handle MSB/LSB controllers and RPNs and NRPNs */
+ }
+ }
+}
+
diff --git a/src/Nio/JackEngine.h b/src/Nio/JackEngine.h
@@ -0,0 +1,89 @@
+/*
+ JackEngine.h
+
+ Copyright 2009, Alan Calvert
+
+ This file is part of yoshimi, which is free software: you can
+ redistribute it and/or modify it under the terms of the GNU General
+ Public License as published by the Free Software Foundation, either
+ version 3 of the License, or (at your option) any later version.
+
+ yoshimi is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with yoshimi. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef JACK_ENGINE_H
+#define JACK_ENGINE_H
+
+#include <string>
+#include <pthread.h>
+#include <semaphore.h>
+#include <jack/jack.h>
+#include <pthread.h>
+
+#include "MidiIn.h"
+#include "AudioOut.h"
+
+typedef jack_default_audio_sample_t jsample_t;
+
+class JackEngine : public AudioOut, MidiIn
+{
+ public:
+ JackEngine(OutMgr *out);
+ ~JackEngine() { };
+
+ bool Start();
+ void Stop();
+
+ void setMidiEn(bool nval);
+ bool getMidiEn() const;
+
+ void setAudioEn(bool nval);
+ bool getAudioEn() const;
+
+ unsigned int getSamplerate() { return audio.jackSamplerate; };
+ unsigned int getBuffersize() { return audio.jackNframes; };
+
+ std::string clientName();
+ int clientId();
+
+ protected:
+
+ int processCallback(jack_nframes_t nframes);
+ static int _processCallback(jack_nframes_t nframes, void *arg);
+ int bufferSizeCallback(jack_nframes_t nframes);
+ static int _bufferSizeCallback(jack_nframes_t nframes, void *arg);
+ static void _errorCallback(const char *msg);
+ static void _infoCallback(const char *msg);
+ static int _xrunCallback(void *arg);
+
+ private:
+ bool connectServer(std::string server);
+ bool connectJack();
+ void disconnectJack();
+ bool openAudio();
+ void stopAudio();
+ bool processAudio(jack_nframes_t nframes);
+ bool openMidi();
+ void stopMidi();
+
+ jack_client_t *jackClient;
+ struct audio{
+ unsigned int jackSamplerate;
+ unsigned int jackNframes;
+ jack_port_t *ports[2];
+ jsample_t *portBuffs[2];
+ } audio;
+ struct midi{
+ jack_port_t *inport;
+ } midi;
+
+ void handleMidi(unsigned long frames);
+};
+
+#endif
diff --git a/src/Nio/MidiIn.cpp b/src/Nio/MidiIn.cpp
@@ -0,0 +1,62 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ MidiIn.C - This class is inherited by all the Midi input classes
+ Copyright (C) 2002-2005 Nasca Octavian Paul
+ Author: Nasca Octavian Paul
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License (version 2 or later) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#include "MidiIn.h"
+#include "../globals.h"
+#include "InMgr.h"
+
+void MidiIn::midiProcess(unsigned char head, unsigned char num, unsigned char value)
+{
+ MidiEvent ev;
+ unsigned char chan = head & 0x0f;
+ switch(head & 0xf0)
+ {
+ case 0x80: //Note Off
+ ev.type = M_NOTE;
+ ev.channel = chan;
+ ev.num = num;
+ ev.value = 0;
+ sysIn->putEvent(ev);
+ break;
+ case 0x90: //Note On
+ ev.type = M_NOTE;
+ ev.channel = chan;
+ ev.num = num;
+ ev.value = value;
+ sysIn->putEvent(ev);
+ break;
+ case 0xb0: //Controller
+ ev.type = M_CONTROLLER;
+ ev.channel = chan;
+ ev.num = num;
+ ev.value = value;
+ sysIn->putEvent(ev);
+ break;
+ case 0xe0: //Pitch Wheel
+ ev.type = M_CONTROLLER;
+ ev.channel = chan;
+ ev.num = C_pitchwheel;
+ ev.value = (num + value * (int) 128) - 8192;
+ sysIn->putEvent(ev);
+ break;
+ }
+}
diff --git a/src/Nio/MidiIn.h b/src/Nio/MidiIn.h
@@ -0,0 +1,41 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ MidiIn.h - This class is inherited by all the Midi input classes
+ Copyright (C) 2002-2005 Nasca Octavian Paul
+ Copyright (C) 2009-2010 Mark McCurry
+ Author: Nasca Octavian Paula
+ Mark McCurry
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License (version 2 or later) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#ifndef MIDI_IN_H
+#define MIDI_IN_H
+
+#include "Engine.h"
+
+/**This class is inherited by all the Midi input classes*/
+struct MidiIn : public virtual Engine
+{
+ /**Enables or disables driver based upon value*/
+ virtual void setMidiEn(bool nval)=0;
+ /**Returns if driver is initialized*/
+ virtual bool getMidiEn() const=0;
+ static void midiProcess(unsigned char head, unsigned char num, unsigned char value);
+};
+
+#endif
+
diff --git a/src/Nio/NulEngine.cpp b/src/Nio/NulEngine.cpp
@@ -0,0 +1,115 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ OSSaudiooutput.C - Audio output for Open Sound System
+ Copyright (C) 2002-2005 Nasca Octavian Paul
+ Author: Nasca Octavian Paul
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License (version 2 or later) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#include "NulEngine.h"
+#include "../globals.h"
+
+#include <iostream>
+
+using namespace std;
+
+NulEngine::NulEngine(OutMgr *out)
+ :AudioOut(out), pThread(NULL)
+{
+ name = "NULL";
+ playing_until.tv_sec = 0;
+ playing_until.tv_usec = 0;
+}
+
+void *NulEngine::_AudioThread(void *arg)
+{
+ return (static_cast<NulEngine*>(arg))->AudioThread();
+}
+
+void *NulEngine::AudioThread()
+{
+ while(pThread)
+ {
+ const Stereo<Sample> smps = getNext();
+
+ struct timeval now;
+ int remaining = 0;
+ gettimeofday(&now, NULL);
+ if((playing_until.tv_usec == 0) && (playing_until.tv_sec == 0)) {
+ playing_until.tv_usec = now.tv_usec;
+ playing_until.tv_sec = now.tv_sec;
+ }
+ else {
+ remaining = (playing_until.tv_usec - now.tv_usec)
+ + (playing_until.tv_sec - now.tv_sec) * 1000000;
+ if(remaining > 10000) //Don't sleep() less than 10ms.
+ //This will add latency...
+ usleep(remaining - 10000);
+ if(remaining < 0)
+ cerr << "WARNING - too late" << endl;
+ }
+ playing_until.tv_usec += SOUND_BUFFER_SIZE * 1000000 / SAMPLE_RATE;
+ if(remaining < 0)
+ playing_until.tv_usec -= remaining;
+ playing_until.tv_sec += playing_until.tv_usec / 1000000;
+ playing_until.tv_usec %= 1000000;
+ }
+ pthread_exit(NULL);
+}
+
+NulEngine::~NulEngine()
+{
+}
+
+bool NulEngine::Start()
+{
+ setAudioEn(true);
+ return getAudioEn();
+}
+
+void NulEngine::Stop()
+{
+ setAudioEn(false);
+}
+
+void NulEngine::setAudioEn(bool nval)
+{
+ if(nval) {
+ if(!getAudioEn()) {
+ pthread_t *thread = new pthread_t;
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+ pThread = thread;
+ pthread_create(pThread, &attr, _AudioThread, this);
+ }
+ }
+ else {
+ if(getAudioEn()) {
+ pthread_t *thread = pThread;
+ pThread = NULL;
+ pthread_join(*thread, NULL);
+ delete thread;
+ }
+ }
+}
+
+bool NulEngine::getAudioEn() const
+{
+ return pThread;
+}
+
diff --git a/src/Nio/NulEngine.h b/src/Nio/NulEngine.h
@@ -0,0 +1,57 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ NulEngine.h - Dummy In/Out driver
+ Copyright (C) 2002-2005 Nasca Octavian Paul
+ Author: Nasca Octavian Paul
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License (version 2 or later) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#ifndef NUL_ENGINE_H
+#define NUL_ENGINE_H
+
+#include <sys/time.h>
+#include <pthread.h>
+#include "../globals.h"
+#include "AudioOut.h"
+#include "MidiIn.h"
+
+class NulEngine: public AudioOut, MidiIn
+{
+ public:
+ NulEngine(OutMgr *out);
+ ~NulEngine();
+
+ bool Start();
+ void Stop();
+
+ void setAudioEn(bool nval);
+ bool getAudioEn() const;
+
+ void setMidiEn(bool){};
+ bool getMidiEn() const{return true;};
+
+ protected:
+ void *AudioThread();
+ static void *_AudioThread(void *arg);
+
+ private:
+ struct timeval playing_until;
+ pthread_t *pThread;
+};
+
+#endif
+
diff --git a/src/Nio/OssEngine.cpp b/src/Nio/OssEngine.cpp
@@ -0,0 +1,264 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ OSSaudiooutput.C - Audio output for Open Sound System
+ Copyright (C) 2002-2005 Nasca Octavian Paul
+ Author: Nasca Octavian Paul
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License (version 2 or later) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#include "OssEngine.h"
+#include "../Misc/Util.h"
+#include "../globals.h"
+
+#include <cstring>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/soundcard.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <iostream>
+
+#include "InMgr.h"
+
+using namespace std;
+
+OssEngine::OssEngine(OutMgr *out)
+ :AudioOut(out), engThread(NULL)
+{
+ name = "OSS";
+
+ midi.handle = -1;
+ audio.handle = -1;
+
+ audio.smps = new short[SOUND_BUFFER_SIZE * 2];
+ memset(audio.smps, 0, sizeof(short) * SOUND_BUFFER_SIZE * 2);
+}
+
+OssEngine::~OssEngine()
+{
+ Stop();
+ delete [] audio.smps;
+}
+
+bool OssEngine::openAudio()
+{
+ if(audio.handle != -1)
+ return true; //already open
+
+ int snd_bitsize = 16;
+ int snd_fragment = 0x00080009; //fragment size (?);
+ int snd_stereo = 1; //stereo;
+ int snd_format = AFMT_S16_LE;
+ int snd_samplerate = SAMPLE_RATE;;
+
+ audio.handle = open(config.cfg.LinuxOSSWaveOutDev, O_WRONLY, 0);
+ if(audio.handle == -1) {
+ cerr << "ERROR - I can't open the "
+ << config.cfg.LinuxOSSWaveOutDev << '.' << endl;
+ return false;
+ }
+ ioctl(audio.handle, SNDCTL_DSP_RESET, NULL);
+ ioctl(audio.handle, SNDCTL_DSP_SETFMT, &snd_format);
+ ioctl(audio.handle, SNDCTL_DSP_STEREO, &snd_stereo);
+ ioctl(audio.handle, SNDCTL_DSP_SPEED, &snd_samplerate);
+ ioctl(audio.handle, SNDCTL_DSP_SAMPLESIZE, &snd_bitsize);
+ ioctl(audio.handle, SNDCTL_DSP_SETFRAGMENT, &snd_fragment);
+
+ if(!getMidiEn()) {
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+ engThread = new pthread_t;
+ pthread_create(engThread, &attr, _thread, this);
+ }
+
+ return true;
+}
+
+void OssEngine::stopAudio()
+{
+ int handle = audio.handle;
+ if(handle == -1) //already closed
+ return;
+ audio.handle = -1;
+
+ if(!getMidiEn() && engThread)
+ pthread_join(*engThread, NULL);
+ delete engThread;
+ engThread = NULL;
+
+ close(handle);
+}
+
+bool OssEngine::Start()
+{
+ bool good = true;
+
+ if(!openAudio()) {
+ cerr << "Failed to open OSS audio" << endl;
+ good = false;
+ }
+
+ if(!openMidi()) {
+ cerr << "Failed to open OSS midi" << endl;
+ good = false;
+ }
+
+ return good;
+}
+
+void OssEngine::Stop()
+{
+ stopAudio();
+ stopMidi();
+}
+
+void OssEngine::setMidiEn(bool nval)
+{
+ if(nval)
+ openMidi();
+ else
+ stopMidi();
+}
+
+bool OssEngine::getMidiEn() const
+{
+ return midi.handle != -1;
+}
+
+void OssEngine::setAudioEn(bool nval)
+{
+ if(nval)
+ openAudio();
+ else
+ stopAudio();
+}
+
+bool OssEngine::getAudioEn() const
+{
+ return audio.handle != -1;
+}
+
+bool OssEngine::openMidi()
+{
+ int handle = midi.handle;
+ if(handle != -1)
+ return true;//already open
+
+ handle = open(config.cfg.LinuxOSSSeqInDev, O_RDONLY, 0);
+
+ if(-1 == handle) {
+ return false;
+ }
+ midi.handle = handle;
+
+ if(!getAudioEn()) {
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+ engThread = new pthread_t;
+ pthread_create(engThread, &attr, _thread, this);
+ }
+
+ return true;
+}
+
+void OssEngine::stopMidi()
+{
+ int handle = midi.handle;
+ if(handle == -1) //already closed
+ return;
+
+ midi.handle = -1;
+
+ if(!getAudioEn() && engThread) {
+ pthread_join(*engThread, NULL);
+ delete engThread;
+ engThread = NULL;
+ }
+
+ close(handle);
+}
+
+void *OssEngine::_thread(void *arg)
+{
+ return (static_cast<OssEngine*>(arg))->thread();
+}
+
+void *OssEngine::thread()
+{
+ unsigned char tmp[4] = {0, 0, 0, 0};
+ set_realtime();
+ while (getAudioEn() || getMidiEn())
+ {
+ if(getAudioEn())
+ {
+ const Stereo<Sample> smps = getNext();
+
+ REALTYPE l, r;
+ for(int i = 0; i < SOUND_BUFFER_SIZE; i++) {
+ l = smps.l()[i];
+ r = smps.r()[i];
+
+ if(l < -1.0)
+ l = -1.0;
+ else
+ if(l > 1.0)
+ l = 1.0;
+ if(r < -1.0)
+ r = -1.0;
+ else
+ if(r > 1.0)
+ r = 1.0;
+
+ audio.smps[i * 2] = (short int) (l * 32767.0);
+ audio.smps[i * 2 + 1] = (short int) (r * 32767.0);
+ }
+ int handle = audio.handle;
+ if(handle != -1)
+ write(handle, audio.smps, SOUND_BUFFER_SIZE * 4); // *2 because is 16 bit, again * 2 because is stereo
+ else
+ break;
+ }
+
+ //Collect up to 30 midi events
+ for (int k = 0; k < 30 && getMidiEn(); ++k) {
+ getMidi(tmp);
+ unsigned char type = tmp[0];
+ unsigned char header = tmp[1];
+ if(header!=0xfe&&type==SEQ_MIDIPUTC&&header>=0x80)
+ {
+ getMidi(tmp);
+ unsigned char num = tmp[1];
+ getMidi(tmp);
+ unsigned char value = tmp[1];
+
+ midiProcess(header, num, value);
+ }
+ }
+ }
+ pthread_exit(NULL);
+ return NULL;
+}
+
+void OssEngine::getMidi(unsigned char *midiPtr)
+{
+ read(midi.handle, midiPtr, 4);
+}
+
diff --git a/src/Nio/OssEngine.h b/src/Nio/OssEngine.h
@@ -0,0 +1,77 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ OSSaudiooutput.h - Audio output for Open Sound System
+ Copyright (C) 2002-2005 Nasca Octavian Paul
+ Author: Nasca Octavian Paul
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License (version 2 or later) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#ifndef OSS_ENGINE_H
+#define OSS_ENGINE_H
+
+#include <sys/time.h>
+#include "../globals.h"
+#include "AudioOut.h"
+#include "MidiIn.h"
+
+class OssEngine: public AudioOut, MidiIn
+{
+ public:
+ OssEngine(OutMgr *out);
+ ~OssEngine();
+
+ bool Start();
+ void Stop();
+
+ void setAudioEn(bool nval);
+ bool getAudioEn() const;
+
+ void setMidiEn(bool nval);
+ bool getMidiEn() const;
+
+
+ protected:
+ void *thread();
+ static void *_thread(void *arg);
+
+ private:
+ pthread_t *engThread;
+
+ //Audio
+ bool openAudio();
+ void stopAudio();
+
+ struct audio{
+ int handle;
+ short int *smps; //Samples to be sent to soundcard
+ bool en;
+ } audio;
+
+ //Midi
+ bool openMidi();
+ void stopMidi();
+ void getMidi(unsigned char *midiPtr);
+
+ struct midi{
+ int handle;
+ bool en;
+ bool run;
+ } midi;
+};
+
+#endif
+
diff --git a/src/Nio/OutMgr.cpp b/src/Nio/OutMgr.cpp
@@ -0,0 +1,135 @@
+#include "OutMgr.h"
+#include <algorithm>
+#include <iostream>
+#include "AudioOut.h"
+#include "Engine.h"
+#include "EngineMgr.h"
+#include "InMgr.h"
+#include "WavEngine.h"
+#include "../Misc/Master.h"
+#include "../Misc/Util.h"//for set_realtime()
+
+using namespace std;
+
+OutMgr *sysOut;
+
+OutMgr::OutMgr(Master *nmaster)
+ :wave(new WavEngine(this)),
+ priBuf(new REALTYPE[4096],new REALTYPE[4096]),priBuffCurrent(priBuf)
+{
+ currentOut = NULL;
+ stales = 0;
+ master = nmaster;
+
+ //init samples
+ outr = new REALTYPE[SOUND_BUFFER_SIZE];
+ outl = new REALTYPE[SOUND_BUFFER_SIZE];
+};
+
+OutMgr::~OutMgr()
+{
+ delete [] outr;
+ delete [] outl;
+}
+
+/* Sequence of a tick
+ * 1) lets see if we have any stuff to do via midi
+ * 2) Lets do that stuff
+ * 3) Lets see if the event queue has anything for us
+ * 4) Lets empty that out
+ * 5) Lets remove old/stale samples
+ * 6) Lets see if we need to generate samples
+ * 7) Lets generate some
+ * 8) Lets return those samples to the primary and secondary outputs
+ * 9) Lets wait for another tick
+ */
+const Stereo<REALTYPE *> OutMgr::tick(unsigned int frameSize)
+{
+ pthread_mutex_lock(&(master->mutex));
+ sysIn->flush();
+ pthread_mutex_unlock(&(master->mutex));
+ //SysEv->execute();
+ removeStaleSmps();
+ while(frameSize > storedSmps()) {
+ pthread_mutex_lock(&(master->mutex));
+ master->AudioOut(outl, outr);
+ pthread_mutex_unlock(&(master->mutex));
+ addSmps(outl,outr);
+ }
+ Stereo<REALTYPE *> ans = priBuffCurrent;
+ ans.l() -= frameSize;
+ ans.r() -= frameSize;
+ //cout << storedSmps() << '=' << frameSize << endl;
+ return priBuf;
+}
+
+AudioOut *OutMgr::getOut(string name)
+{
+ return dynamic_cast<AudioOut *>(sysEngine->getEng(name));
+}
+
+string OutMgr::getDriver() const
+{
+ return currentOut->name;
+}
+
+bool OutMgr::setSink(string name)
+{
+ AudioOut *sink = getOut(name);
+
+ if(!sink)
+ return false;
+
+ if(currentOut)
+ currentOut->setAudioEn(false);
+
+ currentOut = sink;
+ currentOut->setAudioEn(true);
+ return currentOut->getAudioEn();
+}
+
+string OutMgr::getSink() const
+{
+ if(currentOut)
+ return currentOut->name;
+ else {
+ cerr << "BUG: No current output in OutMgr " << __LINE__ << endl;
+ return "ERROR";
+ }
+ return "ERROR";
+}
+
+void OutMgr::addSmps(REALTYPE *l, REALTYPE *r)
+{
+ //allow wave file to syphon off stream
+ wave->push(Stereo<REALTYPE *>(l,r),SOUND_BUFFER_SIZE);
+
+ Stereo<Sample> smps(Sample(SOUND_BUFFER_SIZE, l), Sample(SOUND_BUFFER_SIZE, r));
+
+ if(currentOut->getSampleRate() != SAMPLE_RATE) { //we need to resample
+ //cout << "BAD RESAMPLING" << endl;
+ smps.l().resample(SAMPLE_RATE,currentOut->getSampleRate());
+ smps.r().resample(SAMPLE_RATE,currentOut->getSampleRate());
+ }
+
+ memcpy(priBuffCurrent.l(), smps.l().c_buf(), SOUND_BUFFER_SIZE*sizeof(REALTYPE));
+ memcpy(priBuffCurrent.r(), smps.r().c_buf(), SOUND_BUFFER_SIZE*sizeof(REALTYPE));
+ priBuffCurrent.l() += SOUND_BUFFER_SIZE;
+ priBuffCurrent.r() += SOUND_BUFFER_SIZE;
+ stales += SOUND_BUFFER_SIZE;
+}
+
+void OutMgr::removeStaleSmps()
+{
+ int toShift = storedSmps() - stales;
+ //cout << "toShift: " << toShift << endl << "stales: " << stales << endl << priBuf.l() << ' ' << priBuffCurrent.l() << endl;
+ if(!stales)
+ return;
+
+ memset(priBuf.l(), '0', 4096*sizeof(REALTYPE));
+ memset(priBuf.r(), '0', 4096*sizeof(REALTYPE));
+ priBuffCurrent = priBuf;
+ stales = 0;
+
+}
+
diff --git a/src/Nio/OutMgr.h b/src/Nio/OutMgr.h
@@ -0,0 +1,70 @@
+#ifndef OUTMGR_H
+#define OUTMGR_H
+
+#include "../globals.h"
+#include "../Misc/Stereo.h"
+#include "../Samples/Sample.h" //deprecated
+#include <list>
+#include <string>
+#include <semaphore.h>
+
+
+class AudioOut;
+class WavEngine;
+class Master;
+class OutMgr
+{
+ public:
+ OutMgr(Master *nmaster);
+ ~OutMgr();
+
+ /**Execute a tick*/
+ const Stereo<REALTYPE *> tick(unsigned int frameSize);
+
+ /**Request a new set of samples
+ * @param n number of requested samples (defaults to 1)
+ * @return -1 for locking issues 0 for valid request*/
+ void requestSamples(unsigned int n=1);
+
+ /**Gets requested driver
+ * @param name case unsensitive name of driver
+ * @return pointer to Audio Out or NULL
+ */
+ AudioOut *getOut(std::string name);
+
+ /**Gets the name of the first running driver
+ * Deprecated
+ * @return if no running output, "" is returned
+ */
+ std::string getDriver() const;
+
+ bool setSink(std::string name);
+
+ std::string getSink() const;
+
+ WavEngine *wave; /**<The Wave Recorder*/
+ friend class EngineMgr;
+ private:
+ void addSmps(REALTYPE *l, REALTYPE *r);
+ int storedSmps() const {return priBuffCurrent.l() - priBuf.l();};
+ void removeStaleSmps();
+
+ AudioOut *currentOut;/**<The current output driver*/
+
+ sem_t requested;
+
+ /**Buffer*/
+ Stereo<REALTYPE *> priBuf; //buffer for primary drivers
+ Stereo<REALTYPE *> priBuffCurrent; //current array accessor
+ Stereo<Sample> smps; /**Deprecated TODO Remove*/
+
+ REALTYPE *outl;
+ REALTYPE *outr;
+ Master *master;
+
+ int stales;
+};
+
+extern OutMgr *sysOut;
+#endif
+
diff --git a/src/Nio/PaEngine.cpp b/src/Nio/PaEngine.cpp
@@ -0,0 +1,111 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ PaEngine.cpp - Audio output for PortAudio
+ Copyright (C) 2002 Nasca Octavian Paul
+ Author: Nasca Octavian Paul
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License (version 2 or later) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#include "PaEngine.h"
+#include "../Samples/Sample.h"
+#include <iostream>
+
+using namespace std;
+
+PaEngine::PaEngine(OutMgr *out)
+ :AudioOut(out)
+{
+ name = "PA";
+}
+
+
+PaEngine::~PaEngine()
+{
+ Stop();
+}
+
+bool PaEngine::Start()
+{
+ if(enabled())
+ return true;
+ enabled = true;
+ Pa_Initialize();
+
+ PaStreamParameters outputParameters;
+ outputParameters.device = Pa_GetDefaultOutputDevice();
+ if (outputParameters.device == paNoDevice) {
+ cerr << "Error: No default output device." << endl;
+ Pa_Terminate();
+ return false;
+ }
+ outputParameters.channelCount = 2; /* stereo output */
+ outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
+ outputParameters.suggestedLatency =
+ Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency;
+ outputParameters.hostApiSpecificStreamInfo = NULL;
+
+
+ Pa_OpenStream(&stream,
+ NULL,
+ &outputParameters,
+ SAMPLE_RATE,
+ SOUND_BUFFER_SIZE,
+ NULL,
+ PAprocess,
+ (void *) this);
+ Pa_StartStream(stream);
+ return true;
+}
+
+int PaEngine::PAprocess(const void *inputBuffer, void *outputBuffer,
+ unsigned long framesPerBuffer,
+ const PaStreamCallbackTimeInfo *outTime, PaStreamCallbackFlags flags,
+ void *userData)
+{
+ return static_cast<PaEngine *>(userData)->process((float *) outputBuffer,
+ framesPerBuffer);
+}
+
+int PaEngine::process(float *out, unsigned long framesPerBuffer)
+{
+
+ const Stereo<Sample> smp = getNext();
+
+ if(framesPerBuffer != smp.l().size())
+ cerr << "Bug: PaEngine::process SOUND_BUFFER_SIZE!=framesPerBuffer"
+ << framesPerBuffer << ' ' << smp.l().size() << endl;
+
+ for(int i = 0; i < framesPerBuffer; i++) {
+ if(i >= smp.l().size())
+ break;//this should never happens, except only when framesPerBuffer!>SOUND_BUFFER_SIZE
+ *out++ = smp.l()[i];
+ *out++ = smp.r()[i];
+ }
+
+ return 0;
+}
+
+void PaEngine::Stop()
+{
+ if(!enabled())
+ return;
+ enabled = false;
+ Pa_StopStream(stream);
+ Pa_CloseStream(stream);
+ Pa_Terminate();
+}
+
diff --git a/src/Nio/PaEngine.h b/src/Nio/PaEngine.h
@@ -0,0 +1,54 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ PAaudiooutput.h - Audio output for PortAudio
+ Copyright (C) 2002 Nasca Octavian Paul
+ Author: Nasca Octavian Paul
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License (version 2 or later) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+#ifndef PA_ENGINE_H
+#define PA_ENGINE_H
+
+#include <portaudio.h>
+
+#include "../globals.h"
+#include "AudioOut.h"
+
+class PaEngine: public AudioOut
+{
+ public:
+ PaEngine(OutMgr *out);
+ ~PaEngine();
+
+ bool Start();
+ void Stop();
+
+ protected:
+ static int PAprocess(const void *inputBuffer, void *outputBuffer,
+ unsigned long framesPerBuffer,
+ const PaStreamCallbackTimeInfo *outTime, PaStreamCallbackFlags flags,
+ void *userData);
+ int process(float *out, unsigned long framesPerBuffer);
+ private:
+ PaStream *stream;
+};
+
+
+void PAaudiooutputinit(Master *master_);
+void PAfinish();
+
+#endif
+
diff --git a/src/Nio/SafeQueue.cpp b/src/Nio/SafeQueue.cpp
@@ -0,0 +1,83 @@
+
+template<class T>
+SafeQueue<T>::SafeQueue(size_t maxlen)
+ :writePtr(0),readPtr(0),bufSize(maxlen)
+{
+ buffer = new T[maxlen];
+}
+
+template<class T>
+SafeQueue<T>::~SafeQueue()
+{
+ delete[] buffer;
+}
+
+template<class T>
+unsigned int SafeQueue<T>::size() const
+{
+ return rSpace();
+}
+
+template<class T>
+unsigned int SafeQueue<T>::rSpace() const
+{
+ size_t w, r;
+
+ w = writePtr;
+ r = readPtr;
+
+ if (w > r) {
+ return w - r;
+ }
+ else {
+ return (w - r + bufSize) % bufSize;
+ }
+}
+
+template<class T>
+unsigned int SafeQueue<T>::wSpace() const
+{
+ size_t w, r;
+
+ w = writePtr;
+ r = readPtr - 1;
+
+ if (r > w) {
+ return r - w;
+ }
+ else {
+ return (r - w + bufSize) % bufSize;
+ }
+}
+
+template<class T>
+int SafeQueue<T>::push(const T &in)
+{
+ if(!wSpace())
+ return -1;
+
+ //ok, there is space to write
+ size_t w = (writePtr + 1) % bufSize;
+ buffer[w] = in;
+ writePtr = w;
+ return 0;
+}
+
+template<class T>
+int SafeQueue<T>::pop(T &out)
+{
+ if(!rSpace())
+ return -1;
+
+ //ok, there is space to read
+ size_t r = (readPtr + 1) % bufSize;
+ out = buffer[r];
+ readPtr = r;
+ return 0;
+}
+
+template<class T>
+void SafeQueue<T>::clear()
+{
+ readPtr = writePtr;
+}
diff --git a/src/Nio/SafeQueue.h b/src/Nio/SafeQueue.h
@@ -0,0 +1,40 @@
+
+#ifndef SAFEQUEUE_H
+#define SAFEQUEUE_H
+#include <cstdlib>
+
+/**
+ * C++ thread safe lockless queue
+ * Based off of jack's ringbuffer*/
+template <class T>
+class SafeQueue
+{
+ public:
+ SafeQueue(size_t maxlen);
+ ~SafeQueue();
+
+ /**Return read size*/
+ unsigned int size() const;
+
+ /**Returns 0 for normal
+ * Returns -1 on error*/
+ int push(const T &in);
+ int pop(T &out);
+
+ //clears reading space
+ void clear();
+
+ private:
+ unsigned int wSpace() const;
+ unsigned int rSpace() const;
+
+ //next writting spot
+ volatile size_t writePtr;
+ //next reading spot
+ volatile size_t readPtr;
+ const size_t bufSize;
+ T *buffer;
+};
+
+#include "SafeQueue.cpp"
+#endif
diff --git a/src/Nio/WavEngine.cpp b/src/Nio/WavEngine.cpp
@@ -0,0 +1,120 @@
+/*
+ Copyright (C) 2006 Nasca Octavian Paul
+ Author: Nasca Octavian Paul
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License (version 2) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "WavEngine.h"
+#include <cstdio>
+#include <iostream>
+#include <cstdlib>
+#include "../Misc/WavFile.h"
+#include "../Misc/Util.h"
+
+using namespace std;
+
+WavEngine::WavEngine(OutMgr *out)
+ :AudioOut(out), file(NULL), buffer(SAMPLE_RATE*2), pThread(NULL)
+{
+ sem_init(&work, PTHREAD_PROCESS_PRIVATE, 0);
+}
+
+WavEngine::~WavEngine()
+{
+ Stop();
+ sem_destroy(&work);
+ destroyFile();
+}
+
+bool WavEngine::openAudio()
+{
+ return file && file->good();
+}
+
+bool WavEngine::Start()
+{
+ if(pThread)
+ return true;
+ pThread = new pthread_t;
+
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+ pthread_create(pThread, &attr, _AudioThread, this);
+
+ return true;
+}
+
+void WavEngine::Stop()
+{
+ if(!pThread)
+ return;
+
+ pthread_t *tmp = pThread;
+ pThread = NULL;
+
+ sem_post(&work);
+ pthread_join(*tmp, NULL);
+ delete pThread;
+}
+
+void WavEngine::push(Stereo<REALTYPE *> smps, size_t len)
+{
+ if(!pThread)
+ return;
+
+
+ //copy the input [overflow when needed]
+ for(size_t i = 0; i < len; ++i) {
+ buffer.push(*smps.l()++);
+ buffer.push(*smps.r()++);
+ sem_post(&work);
+ }
+}
+
+void WavEngine::newFile(WavFile *_file)
+{
+ //ensure system is clean
+ destroyFile();
+ file = _file;
+}
+
+void WavEngine::destroyFile()
+{
+ if(file)
+ delete file;
+}
+
+void *WavEngine::_AudioThread(void *arg)
+{
+ return (static_cast<WavEngine*>(arg))->AudioThread();
+}
+
+void *WavEngine::AudioThread()
+{
+ short int recordbuf_16bit[2];
+
+ while(!sem_wait(&work) && pThread)
+ {
+ float left=0.0f, right=0.0f;
+ buffer.pop(left);
+ buffer.pop(right);
+ recordbuf_16bit[0] = limit((int)(left * 32767.0), -32768, 32767);
+ recordbuf_16bit[1] = limit((int)(right * 32767.0), -32768, 32767);
+ file->writeStereoSamples(1, recordbuf_16bit);
+ }
+ pthread_exit(NULL);
+}
+
diff --git a/src/Nio/WavEngine.h b/src/Nio/WavEngine.h
@@ -0,0 +1,62 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ WavEngine.h - Records sound to a file
+ Copyright (C) 2008 Nasca Octavian Paul
+ Author: Nasca Octavian Paul
+ Mark McCurry
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License (version 2) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef WAVENGINE_H
+#define WAVENGINE_H
+#include "AudioOut.h"
+#include <string>
+#include <pthread.h>
+#include <semaphore.h>
+#include "SafeQueue.h"
+
+class WavFile;
+class WavEngine: public AudioOut
+{
+ public:
+ WavEngine(OutMgr *out);
+ ~WavEngine();
+
+ bool openAudio();
+ bool Start();
+ void Stop();
+
+ void setAudioEn(bool /*nval*/){};
+ bool getAudioEn() const{return true;};
+
+ void push(Stereo<REALTYPE *> smps, size_t len);
+
+ void newFile(WavFile *_file);
+ void destroyFile();
+
+ protected:
+ void *AudioThread();
+ static void *_AudioThread(void *arg);
+
+ private:
+ WavFile *file;
+ sem_t work;
+ SafeQueue<float> buffer;
+
+ pthread_t *pThread;
+};
+#endif
+
diff --git a/src/Output/CMakeLists.txt b/src/Output/CMakeLists.txt
@@ -1,33 +0,0 @@
-set(zynaddsubfx_output_SRCS
- Recorder.cpp
- WAVaudiooutput.cpp
-)
-
-if(AlsaMidiOutput)
- set(zynaddsubfx_output_SRCS
- ${zynaddsubfx_output_SRCS}
- OSSaudiooutput.cpp)
- set(zynaddsubfx_output_lib ${ASOUND_LIBRARY})
-endif(AlsaMidiOutput)
-
-if(JackOutput)
- include_directories(${JACK_INCLUDE_DIR})
- set(zynaddsubfx_output_SRCS
- ${zynaddsubfx_output_SRCS}
- JACKaudiooutput.cpp)
- set(zynaddsubfx_output_lib ${JACK_LIBRARIES})
-endif(JackOutput)
-
-if(PortAudioOutput)
- include_directories(${PORTAUDIO_INCLUDE_DIR})
- set(zynaddsubfx_output_SRCS
- ${zynaddsubfx_output_SRCS}
- PAaudiooutput.cpp)
- set(zynaddsubfx_output_lib ${PORTAUDIO_LIBRARIES})
-endif(PortAudioOutput)
-
-add_library(zynaddsubfx_output STATIC
- ${zynaddsubfx_output_SRCS}
- )
-
-target_link_libraries(zynaddsubfx_output ${zynaddsubfx_output_lib})
diff --git a/src/Output/JACK_RTaudiooutput.cpp b/src/Output/JACK_RTaudiooutput.cpp
@@ -1,229 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- JACKaudiooutput.cpp - Audio output for JACK
- Copyright (C) 2002 Nasca Octavian Paul
- Author: Nasca Octavian Paul
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License
- as published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License (version 2 or later) for more details.
-
- You should have received a copy of the GNU General Public License (version 2)
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-*/
-
-#include <stdlib.h>
-#include <string.h>
-#include <pthread.h>
-#include <unistd.h>
-
-
-extern "C"
-{
-#include <jack/ringbuffer.h>
-};
-#include "JACKaudiooutput.h"
-
-Master *jackmaster;
-jack_client_t *jackclient;
-jack_port_t *outport_left, *outport_right;
-jack_ringbuffer_t *rb = NULL;
-
-REALTYPE *jackoutl, *jackoutr;
-int jackfinish = 0;
-
-void *thread_blocked(void *arg);
-int jackprocess(jack_nframes_t nframes, void *arg);
-int jacksrate(jack_nframes_t nframes, void *arg);
-void jackshutdown(void *arg);
-
-pthread_cond_t more_data = PTHREAD_COND_INITIALIZER;
-pthread_mutex_t zyn_thread_lock = PTHREAD_MUTEX_INITIALIZER;
-
-pthread_t bthr;
-
-
-bool JACKaudiooutputinit(Master *master_)
-{
- jackmaster = master_;
- jackclient = 0;
- char tmpstr[100];
-
- jackoutl = new REALTYPE [SOUND_BUFFER_SIZE];
- jackoutr = new REALTYPE [SOUND_BUFFER_SIZE];
-
- int rbbufsize = SOUND_BUFFER_SIZE * sizeof(REALTYPE) * 2 * 2;
- printf("%d\n", rbbufsize);
- rb = jack_ringbuffer_create(rbbufsize);
- for(int i = 0; i < rbbufsize; i++)
- rb->buf[i] = 0.0;
-
-
- for(int i = 0; i < 15; i++) {
- if(i != 0)
- snprintf(tmpstr, 100, "ZynAddSubFX_%d", i);
- else
- snprintf(tmpstr, 100, "ZynAddSubFX");
- jackclient = jack_client_new(tmpstr);
- if(jackclient != 0)
- break;
- }
-
- if(jackclient == 0) {
- fprintf(
- stderr,
- "\nERROR: Cannot make a jack client (possible reasons: JACK server is not running or jackd is launched by root and zynaddsubfx by another user.).\n\n\n");
- return false;
- }
-
- fprintf(stderr,
- "Internal SampleRate = %d\nJack Output SampleRate= %d\n",
- SAMPLE_RATE,
- jack_get_sample_rate(jackclient));
- if((unsigned int)jack_get_sample_rate(jackclient) !=
- (unsigned int) SAMPLE_RATE)
- fprintf(stderr,
- "It is recomanded that the both samplerates to be equal.\n");
-
- jack_set_process_callback(jackclient, jackprocess, 0);
- jack_set_sample_rate_callback(jackclient, jacksrate, 0);
- jack_on_shutdown(jackclient, jackshutdown, 0);
-
- outport_left = jack_port_register(jackclient,
- "out_1",
- JACK_DEFAULT_AUDIO_TYPE,
- JackPortIsOutput | JackPortIsTerminal,
- 0);
- outport_right = jack_port_register(jackclient,
- "out_2",
- JACK_DEFAULT_AUDIO_TYPE,
- JackPortIsOutput | JackPortIsTerminal,
- 0);
-
- if(jack_activate(jackclient)) {
- fprintf(stderr, "Cannot activate jack client\n");
- return false;
- }
-
- pthread_create(&bthr, NULL, thread_blocked, NULL);
-
- /*
- jack_connect(jackclient,jack_port_name(outport_left),"alsa_pcm:out_1");
- jack_connect(jackclient,jack_port_name(outport_right),"alsa_pcm:out_2");
- */
-
- return true;
-}
-
-void *thread_blocked(void *arg)
-{
- int datasize = SOUND_BUFFER_SIZE * sizeof(REALTYPE);
-
- //try to get realtime
- sched_param sc;
- sc.sched_priority = 50;
- int err = sched_setscheduler(0, SCHED_FIFO, &sc);
-
- pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
- pthread_mutex_lock(&zyn_thread_lock);
-
- while(jackfinish == 0) {
- while(jack_ringbuffer_write_space(rb) >= datasize) {
- pthread_mutex_lock(&jackmaster->mutex);
- jackmaster->GetAudioOutSamples(SOUND_BUFFER_SIZE,
- jack_get_sample_rate(jackclient),
- jackoutl,
- jackoutr);
- pthread_mutex_unlock(&jackmaster->mutex);
-
- jack_ringbuffer_write(rb, (char *) jackoutl, datasize);
- jack_ringbuffer_write(rb, (char *) jackoutr, datasize);
- }
- pthread_cond_wait(&more_data, &zyn_thread_lock);
- }
- pthread_mutex_unlock(&zyn_thread_lock);
-
- return 0;
-}
-
-
-int jackprocess(jack_nframes_t nframes, void *arg)
-{
- jack_default_audio_sample_t *outl =
- (jack_default_audio_sample_t *) jack_port_get_buffer(outport_left,
- nframes);
- jack_default_audio_sample_t *outr =
- (jack_default_audio_sample_t *) jack_port_get_buffer(outport_right,
- nframes);
-
- int datasize = nframes * sizeof(REALTYPE);
- int incoming_datasize = SOUND_BUFFER_SIZE * sizeof(REALTYPE);
- int data_read = 0;
-
-
- if(jack_ringbuffer_read_space(rb) >= (2 * incoming_datasize)) {
- if(datasize > incoming_datasize) {
- data_read = 0;
- while(data_read < datasize) {
- jack_ringbuffer_read(rb, (char *) outl + data_read, datasize);
- jack_ringbuffer_read(rb, (char *) outr + data_read, datasize);
- data_read += incoming_datasize;
- }
- }
- else
- if(datasize == incoming_datasize) {
- jack_ringbuffer_read(rb, (char *) outl, datasize);
- jack_ringbuffer_read(rb, (char *) outr, datasize);
- }
- else {}
- }
- else { //the ringbuffer is empty or there are too small amount of samples in it
- for(int i = 0; i < nframes; i++) {
- outl[i] = 0.0;
- outr[i] = 0.0;
- }
- }
- /* if (jack_ringbuffer_read_space(rb)>=datasize){
- jack_ringbuffer_read(rb, (char *) outl,datasize);
- jack_ringbuffer_read(rb, (char *) outr,datasize);
- } else {//the ringbuffer is empty or there are too small amount of samples in it
- for (int i=0;i<nframes;i++){
- outl[i]=0.0;outr[i]=0.0;
- };
- };
- */
- if(pthread_mutex_trylock(&zyn_thread_lock) == 0) {
- pthread_cond_signal(&more_data);
- pthread_mutex_unlock(&zyn_thread_lock);
- }
-
- return 0;
-}
-
-void JACKfinish()
-{
- jackfinish = 1;
- jack_ringbuffer_free(rb);
- jack_client_close(jackclient);
-
- usleep(100000);
- delete (jackoutl);
- delete (jackoutr);
-}
-
-int jacksrate(jack_nframes_t nframes, void *arg)
-{
- return 0;
-}
-
-void jackshutdown(void *arg)
-{}
-
diff --git a/src/Output/JACKaudiooutput.cpp b/src/Output/JACKaudiooutput.cpp
@@ -1,185 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- JACKaudiooutput.cpp - Audio output for JACK
- Copyright (C) 2002 Nasca Octavian Paul
- Author: Nasca Octavian Paul
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License
- as published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License (version 2 or later) for more details.
-
- You should have received a copy of the GNU General Public License (version 2)
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-*/
-
-#include <stdlib.h>
-#include <jack/midiport.h>
-#include "JACKaudiooutput.h"
-
-Master *jackmaster;
-jack_client_t *jackclient;
-char jackname[100];
-jack_port_t *outport_left, *outport_right, *midi_inport;
-
-int jackprocess(jack_nframes_t nframes, void *arg);
-int jacksrate(jack_nframes_t nframes, void *arg);
-void jackshutdown(void *arg);
-
-bool JACKaudiooutputinit(Master *master_)
-{
- jackmaster = master_;
- jackclient = 0;
-
- for(int i = 0; i < 15; i++) {
- if(i != 0)
- snprintf(jackname, 100, "ZynAddSubFX_%d", i);
- else
- snprintf(jackname, 100, "ZynAddSubFX");
- jackclient = jack_client_new(jackname);
- if(jackclient != 0)
- break;
- }
-
- if(jackclient == 0) {
- fprintf(
- stderr,
- "\nERROR: Cannot make a jack client (possible reasons: JACK server is not running or jackd is launched by root and zynaddsubfx by another user.).\n");
- return false;
- }
-
- fprintf(stderr,
- "Internal SampleRate = %d\nJack Output SampleRate= %d\n",
- SAMPLE_RATE,
- jack_get_sample_rate(jackclient));
- if((unsigned int)jack_get_sample_rate(jackclient) !=
- (unsigned int) SAMPLE_RATE)
- fprintf(stderr,
- "It is recomanded that the both samplerates to be equal.\n");
-
- jack_set_process_callback(jackclient, jackprocess, 0);
- jack_set_sample_rate_callback(jackclient, jacksrate, 0);
- jack_on_shutdown(jackclient, jackshutdown, 0);
-
- outport_left = jack_port_register(jackclient,
- "out_1",
- JACK_DEFAULT_AUDIO_TYPE,
- JackPortIsOutput | JackPortIsTerminal,
- 0);
- outport_right = jack_port_register(jackclient,
- "out_2",
- JACK_DEFAULT_AUDIO_TYPE,
- JackPortIsOutput | JackPortIsTerminal,
- 0);
- midi_inport = jack_port_register(jackclient,
- "midi_input",
- JACK_DEFAULT_MIDI_TYPE,
- JackPortIsInput | JackPortIsTerminal,
- 0);
-
- if(jack_activate(jackclient)) {
- fprintf(stderr, "Cannot activate jack client\n");
- return false;
- }
-
- /*
- jack_connect(jackclient,jack_port_name(outport_left),"alsa_pcm:out_1");
- jack_connect(jackclient,jack_port_name(outport_right),"alsa_pcm:out_2");
- */
- return true;
-}
-
-int jackprocess(jack_nframes_t nframes, void *arg)
-{
- jack_default_audio_sample_t *outl =
- (jack_default_audio_sample_t *) jack_port_get_buffer(outport_left,
- nframes);
- jack_default_audio_sample_t *outr =
- (jack_default_audio_sample_t *) jack_port_get_buffer(outport_right,
- nframes);
-
- if(!pthread_mutex_trylock(&jackmaster->mutex)) {
- JACKhandlemidi(nframes);
- jackmaster->GetAudioOutSamples(nframes, jack_get_sample_rate(
- jackclient), outl, outr);
- pthread_mutex_unlock(&jackmaster->mutex);
- }
- else {
- memset(outl, 0, sizeof(jack_default_audio_sample_t) * nframes);
- memset(outr, 0, sizeof(jack_default_audio_sample_t) * nframes);
- }
-
- return 0;
-}
-
-void JACKfinish()
-{
- jack_client_close(jackclient);
-}
-
-int jacksrate(jack_nframes_t nframes, void *arg)
-{
- return 0;
-}
-
-void jackshutdown(void *arg)
-{}
-
-
-void JACKhandlemidi(unsigned long frames)
-{
- // We must have the master mutex before we run this function
-
- // XXX This is really nasty, not only do we lose the sample accuracy of
- // JACK MIDI, but any accuracy at all below the buffer size
-
- void *midi_buf = jack_port_get_buffer(midi_inport, frames);
- jack_midi_event_t jack_midi_event;
- jack_nframes_t event_index = 0;
- unsigned char *midi_data;
- unsigned char type, chan;
-
- while(jack_midi_event_get(&jack_midi_event, midi_buf,
- event_index++) == 0) {
- midi_data = jack_midi_event.buffer;
- type = midi_data[0] & 0xF0;
- chan = midi_data[0] & 0x0F;
-
- switch(type) {
- case 0x80: /* note-off */
- jackmaster->NoteOff(chan, midi_data[1]);
- break;
-
- case 0x90: /* note-on */
- jackmaster->NoteOn(chan, midi_data[1], midi_data[2]);
- break;
-
- case 0xB0: /* controller */
- jackmaster->SetController(chan, midi_data[1], midi_data[2]);
- break;
-
- case 0xE0: /* pitch bend */
- jackmaster->SetController(chan, C_pitchwheel,
- ((midi_data[2] << 7) | midi_data[1]));
- break;
-
- /* XXX TODO: handle MSB/LSB controllers and RPNs and NRPNs */
- }
- }
-}
-
-
-const char *JACKgetname()
-{
- if(jackclient != NULL)
- return jackname;
- return NULL;
-}
-
diff --git a/src/Output/JACKaudiooutput.h b/src/Output/JACKaudiooutput.h
@@ -1,48 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- JACKaudiooutput.h - Audio output for JACK
- Copyright (C) 2002 Nasca Octavian Paul
- Author: Nasca Octavian Paul
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License
- as published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License (version 2 or later) for more details.
-
- You should have received a copy of the GNU General Public License (version 2)
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-*/
-#ifndef JACK_AUDIO_OUTPUT_H
-#define JACK_AUDIO_OUTPUT_H
-
-#include <jack/jack.h>
-
-#include "../globals.h"
-#include "../Misc/Master.h"
-
-
-#if (REALTYPE != jack_default_audio_sample_t)
-#error \
- "The internal sample datatype of ZynAddSubFX and the datatype of jack differs. \
- In order to compile ZynAddSubFX the 'REALTYPE' and 'jack_default_audio_sample_t' must be equal. \
- Set the 'REALTYPE' data type (which is defined in 'globals.h') to what is defined \
- in the file types.h from jack include directory as 'jack_default_audio_sample_t' (as float or double)."
-#endif
-
-
-
-
-bool JACKaudiooutputinit(Master *master_);
-void JACKfinish();
-void JACKhandlemidi(unsigned long frames);
-const char *JACKgetname();
-
-#endif
-
diff --git a/src/Output/Makefile b/src/Output/Makefile
@@ -1,42 +0,0 @@
-include ../Makefile.inc
-
-objects=Recorder.o WAVaudiooutput.o
-
-ifeq ($(AUDIOOUT),OSS_AND_JACK)
-objects+=OSSaudiooutput.o JACKaudiooutput.o
-endif
-
-ifeq ($(AUDIOOUT),JACK)
-objects+=JACKaudiooutput.o
-endif
-
-ifeq ($(AUDIOOUT),DSSI)
-objects+=DSSIaudiooutput.o
-endif
-
-ifeq ($(AUDIOOUT),JACK_RT)
-objects+=JACK_RTaudiooutput.o
-endif
-
-ifeq ($(AUDIOOUT),PA)
-objects+=PAaudiooutput.o
-endif
-
-ifeq ($(AUDIOOUT),OSS)
-objects+=OSSaudiooutput.o
-endif
-
-ifeq ($(AUDIOOUT),VST)
-objects+=VSTaudiooutput.o
-endif
-
-
-all: $(objects)
-
--include ../Make.deps
-
-.PHONY : clean
-clean:
- rm -f $(objects)
- rm -f makeinclude.deps
-
diff --git a/src/Output/OSSaudiooutput.cpp b/src/Output/OSSaudiooutput.cpp
@@ -1,128 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- OSSaudiooutput.cpp - Audio output for Open Sound System
- Copyright (C) 2002-2005 Nasca Octavian Paul
- Author: Nasca Octavian Paul
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License
- as published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License (version 2 or later) for more details.
-
- You should have received a copy of the GNU General Public License (version 2)
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-*/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <sys/soundcard.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-#include <iostream>
-
-#include "OSSaudiooutput.h"
-#include "../Misc/Util.h"
-#include "../globals.h"
-using namespace std;
-
-OSSaudiooutput::OSSaudiooutput()
-{
- int i;
- int snd_bitsize = 16;
- snd_fragment = 0x00080009; //fragment size (?)
- snd_stereo = 1; //stereo
- snd_format = AFMT_S16_LE;
- snd_samplerate = SAMPLE_RATE;
- playing_until.tv_sec = 0;
- playing_until.tv_usec = 0;
-
- smps = new short int[SOUND_BUFFER_SIZE * 2];
- for(i = 0; i < SOUND_BUFFER_SIZE * 2; i++)
- smps[i] = 0;
-
- snd_handle = open(config.cfg.LinuxOSSWaveOutDev, O_WRONLY, 0);
- if(snd_handle == -1) {
- cerr << "ERROR - I can't open the ";
- cerr << config.cfg.LinuxOSSWaveOutDev << '.' << endl;
- return;
- }
- ioctl(snd_handle, SNDCTL_DSP_RESET, NULL);
-
- ioctl(snd_handle, SNDCTL_DSP_SETFMT, &snd_format);
- ioctl(snd_handle, SNDCTL_DSP_STEREO, &snd_stereo);
- ioctl(snd_handle, SNDCTL_DSP_SPEED, &snd_samplerate);
- ioctl(snd_handle, SNDCTL_DSP_SAMPLESIZE, &snd_bitsize);
- ioctl(snd_handle, SNDCTL_DSP_SETFRAGMENT, &snd_fragment);
-}
-
-
-/*
- * Output the samples to the soundcard
- * The samples are bigger than -1.0 and smaller 1.0
- */
-void OSSaudiooutput::OSSout(REALTYPE *smp_left, REALTYPE *smp_right)
-{
- int i;
- REALTYPE l, r;
- if(snd_handle < 0) { //output could not be opened
- struct timeval now;
- int remaining;
- gettimeofday(&now, NULL);
- if((playing_until.tv_usec == 0) && (playing_until.tv_sec == 0)) {
- playing_until.tv_usec = now.tv_usec;
- playing_until.tv_sec = now.tv_sec;
- }
- else {
- remaining = (playing_until.tv_usec - now.tv_usec)
- + (playing_until.tv_sec - now.tv_sec) * 1000000;
- if(remaining > 10000) //Don't sleep() less than 10ms.
- //This will add latency...
- usleep(remaining - 10000);
- if(remaining < 0)
- cerr << "WARNING - too late" << endl;
- }
- playing_until.tv_usec += SOUND_BUFFER_SIZE * 1000000 / SAMPLE_RATE;
- if(remaining < 0)
- playing_until.tv_usec -= remaining;
- playing_until.tv_sec += playing_until.tv_usec / 1000000;
- playing_until.tv_usec %= 1000000;
- return;
- }
-
- for(i = 0; i < SOUND_BUFFER_SIZE; i++) {
- l = smp_left[i];
- r = smp_right[i];
-
- if(l < -1.0)
- l = -1.0;
- else
- if(l > 1.0)
- l = 1.0;
- if(r < -1.0)
- r = -1.0;
- else
- if(r > 1.0)
- r = 1.0;
-
- smps[i * 2] = (short int) (l * 32767.0);
- smps[i * 2 + 1] = (short int) (r * 32767.0);
- }
- write(snd_handle, smps, SOUND_BUFFER_SIZE * 4); // *2 because is 16 bit, again * 2 because is stereo
-}
-
-
-OSSaudiooutput::~OSSaudiooutput()
-{
- close(snd_handle);
- delete [] smps;
-}
-
diff --git a/src/Output/OSSaudiooutput.h b/src/Output/OSSaudiooutput.h
@@ -1,50 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- OSSaudiooutput.h - Audio output for Open Sound System
- Copyright (C) 2002-2005 Nasca Octavian Paul
- Author: Nasca Octavian Paul
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License
- as published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License (version 2 or later) for more details.
-
- You should have received a copy of the GNU General Public License (version 2)
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-*/
-
-#ifndef OSS_AUDIO_OUTPUT_H
-#define OSS_AUDIO_OUTPUT_H
-
-#include <sys/time.h>
-#include "../globals.h"
-
-class OSSaudiooutput
-{
- public:
- OSSaudiooutput();
- ~OSSaudiooutput();
-
- //the out is [-1.0 .. 1.0]
- /* smp_left[] and smp_right[] has the size of SOUND_BUFFER_SIZE */
- void OSSout(REALTYPE *smp_left, REALTYPE *smp_right);
- private:
- int snd_handle;
- int snd_fragment;
- int snd_stereo;
- int snd_format;
- int snd_samplerate;
- struct timeval playing_until;
-
- short int *smps; //Samples to be sent to soundcard
-};
-
-#endif
-
diff --git a/src/Output/Recorder.cpp b/src/Output/Recorder.cpp
@@ -1,113 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- Recorder.cpp - Records sound to a file
- Copyright (C) 2002-2005 Nasca Octavian Paul
- Author: Nasca Octavian Paul
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License
- as published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License (version 2 or later) for more details.
-
- You should have received a copy of the GNU General Public License (version 2)
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-*/
-
-#include <sys/stat.h>
-#include "Recorder.h"
-
-Recorder::Recorder()
-{
- recordbuf_16bit = new short int [SOUND_BUFFER_SIZE * 2];
- status = 0;
- notetrigger = 0;
- for(int i = 0; i < SOUND_BUFFER_SIZE * 2; i++)
- recordbuf_16bit[i] = 0;
-}
-
-Recorder::~Recorder()
-{
- if(recording() == 1)
- stop();
- delete [] recordbuf_16bit;
-}
-
-int Recorder::preparefile(std::string filename_, int overwrite)
-{
- if(!overwrite) {
- struct stat fileinfo;
- int statr;
- statr = stat(filename_.c_str(), &fileinfo);
- if(statr == 0) //file exists
- return 1;
- }
-
- if(!wav.newfile(filename_, SAMPLE_RATE, 2))
- return 2;
-
- status = 1; //ready
-
- return 0;
-}
-
-void Recorder::start()
-{
- notetrigger = 0;
- status = 2; //recording
-}
-
-void Recorder::stop()
-{
- wav.close();
- status = 0;
-}
-
-void Recorder::pause()
-{
- status = 0;
-}
-
-int Recorder::recording()
-{
- if((status == 2) && (notetrigger != 0))
- return 1;
- else
- return 0;
-}
-
-void Recorder::recordbuffer(REALTYPE *outl, REALTYPE *outr)
-{
- int tmp;
- if(status != 2)
- return;
- for(int i = 0; i < SOUND_BUFFER_SIZE; i++) {
- tmp = (int)(outl[i] * 32767.0);
- if(tmp < -32768)
- tmp = -32768;
- if(tmp > 32767)
- tmp = 32767;
- recordbuf_16bit[i * 2] = tmp;
-
- tmp = (int)(outr[i] * 32767.0);
- if(tmp < -32768)
- tmp = -32768;
- if(tmp > 32767)
- tmp = 32767;
- recordbuf_16bit[i * 2 + 1] = tmp;
- }
- wav.write_stereo_samples(SOUND_BUFFER_SIZE, recordbuf_16bit);
-}
-
-void Recorder::triggernow()
-{
- if(status == 2)
- notetrigger = 1;
-}
-
diff --git a/src/Output/Recorder.h b/src/Output/Recorder.h
@@ -1,57 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- Recorder.h - Records sound to a file
- Copyright (C) 2002-2005 Nasca Octavian Paul
- Author: Nasca Octavian Paul
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License
- as published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License (version 2 or later) for more details.
-
- You should have received a copy of the GNU General Public License (version 2)
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-*/
-
-#ifndef RECORDER_H
-#define RECORDER_H
-#include <string>
-#include "../globals.h"
-#include "WAVaudiooutput.h"
-
-/**Records sound to a file*/
-class Recorder
-{
- public:
-
- Recorder();
- ~Recorder();
- int preparefile(std::string filename_, int overwrite); //returns 1 if the file exists
- void start();
- void stop();
- void pause();
- int recording();
- void triggernow();
- void recordbuffer(REALTYPE *outl, REALTYPE *outr);
-
- /** Status:
- * 0 - not ready(no file selected),
- * 1 - ready
- * 2 - recording */
- int status;
-
- private:
- WAVaudiooutput wav;
- short int *recordbuf_16bit;
- int notetrigger;
-};
-
-#endif
-
diff --git a/src/Output/WAVaudiooutput.cpp b/src/Output/WAVaudiooutput.cpp
@@ -1,101 +0,0 @@
-/*
- Copyright (C) 2006 Nasca Octavian Paul
- Author: Nasca Octavian Paul
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License
- as published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License (version 2) for more details.
-
- You should have received a copy of the GNU General Public License (version 2)
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "WAVaudiooutput.h"
-using namespace std;
-
-WAVaudiooutput::WAVaudiooutput()
-{
- file = NULL;
- sampleswritten = 0;
- samplerate = 44100;
-}
-
-WAVaudiooutput::~WAVaudiooutput()
-{
- close();
-}
-
-bool WAVaudiooutput::newfile(string filename, int samplerate, int channels)
-{
- /**\todo Move this into the Constructor*/
- close(); //inchide un posibil fisier existent
- file = fopen(filename.c_str(), "w");
- if(!file)
- return false;
- this->samplerate = samplerate;
- this->channels = channels;
- sampleswritten = 0;
- char tmp[44];
- fwrite(tmp, 1, 44, file);
- return true;
-}
-
-void WAVaudiooutput::close()
-{
- if(file) {
- unsigned int chunksize;
- rewind(file);
-
- fwrite("RIFF", 4, 1, file);
- chunksize = sampleswritten * 4 + 36;
- fwrite(&chunksize, 4, 1, file);
-
- fwrite("WAVEfmt ", 8, 1, file);
- chunksize = 16;
- fwrite(&chunksize, 4, 1, file);
- unsigned short int formattag = 1; //uncompresed wave
- fwrite(&formattag, 2, 1, file);
- unsigned short int nchannels = channels; //stereo
- fwrite(&nchannels, 2, 1, file);
- unsigned int samplerate_ = samplerate; //samplerate
- fwrite(&samplerate_, 4, 1, file);
- unsigned int bytespersec = samplerate * 2 * channels; //bytes/sec
- fwrite(&bytespersec, 4, 1, file);
- unsigned short int blockalign = 2 * channels; //2 channels * 16 bits/8
- fwrite(&blockalign, 2, 1, file);
- unsigned short int bitspersample = 16;
- fwrite(&bitspersample, 2, 1, file);
-
- fwrite("data", 4, 1, file);
- chunksize = sampleswritten * blockalign;
- fwrite(&chunksize, 4, 1, file);
-
- fclose(file);
- file = NULL;
- }
-}
-
-void WAVaudiooutput::write_stereo_samples(int nsmps, short int *smps)
-{
- if(!file)
- return;
- fwrite(smps, nsmps, 4, file);
- sampleswritten += nsmps;
-}
-
-void WAVaudiooutput::write_mono_samples(int nsmps, short int *smps)
-{
- if(!file)
- return;
- fwrite(smps, nsmps, 2, file);
- sampleswritten += nsmps;
-}
-
diff --git a/src/Output/WAVaudiooutput.h b/src/Output/WAVaudiooutput.h
@@ -1,43 +0,0 @@
-/*
-
- Copyright (C) 2008 Nasca Octavian Paul
- Author: Nasca Octavian Paul
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License
- as published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License (version 2) for more details.
-
- You should have received a copy of the GNU General Public License (version 2)
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#ifndef WAVOUTPUT_H
-#define WAVOUTPUT_H
-#include <string>
-
-class WAVaudiooutput
-{
- public:
- WAVaudiooutput();
- ~WAVaudiooutput();
-
- bool newfile(std::string filename, int samplerate, int channels);
- void close();
-
- void write_mono_samples(int nsmps, short int *smps);
- void write_stereo_samples(int nsmps, short int *smps);
-
- private:
- int sampleswritten;
- int samplerate;
- int channels;
- FILE *file;
-};
-#endif
-
diff --git a/src/Params/ADnoteParameters.cpp b/src/Params/ADnoteParameters.cpp
@@ -25,6 +25,9 @@
#include <math.h>
#include "ADnoteParameters.h"
+#include "EnvelopeParams.h"
+#include "LFOParams.h"
+
int ADnote_unison_sizes[] =
{1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 25, 30, 40, 50, 0};
diff --git a/src/Params/ADnoteParameters.h b/src/Params/ADnoteParameters.h
@@ -25,8 +25,6 @@
#include "../globals.h"
-#include "EnvelopeParams.h"
-#include "LFOParams.h"
#include "FilterParams.h"
#include "../Synth/OscilGen.h"
#include "../Synth/Resonance.h"
@@ -35,6 +33,9 @@
#include "../DSP/FFTwrapper.h"
#include "PresetsArray.h"
+class EnvelopeParams;
+class LFOParams;
+
enum FMTYPE {
NONE, MORPH, RING_MOD, PHASE_MOD, FREQ_MOD, PITCH_MOD
};
diff --git a/src/Params/CMakeLists.txt b/src/Params/CMakeLists.txt
@@ -16,4 +16,4 @@ add_library(zynaddsubfx_params STATIC
${zynaddsubfx_params_SRCS}
)
-target_link_libraries(zynaddsubfx_params)# ${ASOUND_LIBRARY})
+target_link_libraries(zynaddsubfx_params zynaddsubfx_misc)
diff --git a/src/Params/Makefile b/src/Params/Makefile
@@ -1,15 +0,0 @@
-include ../Makefile.inc
-
-objects=ADnoteParameters.o EnvelopeParams.o FilterParams.o \
- LFOParams.o SUBnoteParameters.o PADnoteParameters.o Controller.o Presets.o PresetsArray.o PresetsStore.o
-
-
-all: $(objects)
-
--include ../Make.deps
-
-.PHONY : clean
-clean:
- rm -f $(objects)
- rm -f makeinclude.deps
-
diff --git a/src/Params/PADnoteParameters.cpp b/src/Params/PADnoteParameters.cpp
@@ -21,7 +21,7 @@
*/
#include <math.h>
#include "PADnoteParameters.h"
-#include "../Output/WAVaudiooutput.h"
+#include "../Misc/WavFile.h"
using namespace std;
PADnoteParameters::PADnoteParameters(FFTwrapper *fft_,
@@ -676,14 +676,13 @@ void PADnoteParameters::export2wav(string basefilename)
char tmpstr[20];
snprintf(tmpstr, 20, "_%02d", k + 1);
string filename = basefilename + string(tmpstr) + ".wav";
- WAVaudiooutput wav;
- if(wav.newfile(filename, SAMPLE_RATE, 1)) {
+ WavFile wav(filename, SAMPLE_RATE, 1);
+ if(wav.good()) {
int nsmps = sample[k].size;
short int *smps = new short int[nsmps];
for(int i = 0; i < nsmps; i++)
smps[i] = (short int)(sample[k].smp[i] * 32767.0);
- wav.write_mono_samples(nsmps, smps);
- wav.close();
+ wav.writeMonoSamples(nsmps, smps);
}
}
}
diff --git a/src/Samples/Makefile b/src/Samples/Makefile
@@ -1,14 +0,0 @@
-include ../Makefile.inc
-
-objects=Sample.o
-
-
-all: $(objects)
-
--include ../Make.deps
-
-.PHONY : clean
-clean:
- rm -f $(objects)
- rm -f makeinclude.deps
-
diff --git a/src/Samples/Sample.cpp b/src/Samples/Sample.cpp
@@ -20,6 +20,7 @@
*/
#include <cmath>
#include <cstring>//for memcpy/memset
+
#include <iostream>
#include "Sample.h"
@@ -28,12 +29,17 @@ using namespace std;
#warning TODO Think about renaming Sample to Frame
/**\TODO start using pointer math here as these will be Frequency called
* functions throughout the code*/
+Sample::Sample()
+ :bufferSize(1),buffer(new REALTYPE[1])
+{
+ buffer[0] = 0.0;
+}
+
Sample::Sample(const Sample &smp)
:bufferSize(smp.bufferSize)
{
buffer = new REALTYPE[bufferSize];
- for(int i = 0; i < bufferSize; ++i)
- *(i + buffer) = *(i + smp.buffer);
+ memcpy(buffer, smp.buffer, bufferSize * sizeof(float));
}
Sample::Sample(int length, REALTYPE fill)
@@ -42,8 +48,7 @@ Sample::Sample(int length, REALTYPE fill)
if(length < 1)
bufferSize = 1;
buffer = new REALTYPE[bufferSize];
- for(int i = 0; i < bufferSize; ++i)
- buffer[i] = fill;
+ memset(buffer, fill, bufferSize * sizeof(float));
}
Sample::Sample(int length, const REALTYPE *input)
@@ -51,8 +56,7 @@ Sample::Sample(int length, const REALTYPE *input)
{
if(length > 0) {
buffer = new REALTYPE[length];
- for(int i = 0; i < length; ++i)
- *(buffer + i) = *(input + i);
+ memcpy(buffer, input, bufferSize * sizeof(float));
}
else {
buffer = new REALTYPE[1];
@@ -74,17 +78,12 @@ void Sample::clear()
void Sample::operator=(const Sample &smp)
{
- /**\todo rewrite to be less repetitive*/
- if(bufferSize == smp.bufferSize)
- for(int i = 0; i < bufferSize; ++i)
- *(i + buffer) = *(i + smp.buffer);
- else {
+ if(bufferSize != smp.bufferSize) {
delete[] buffer;
buffer = new REALTYPE[smp.bufferSize];
bufferSize = smp.bufferSize;
- for(int i = 0; i < bufferSize; ++i)
- *(i + buffer) = *(i + smp.buffer);
}
+ memcpy(buffer, smp.buffer, bufferSize * sizeof(float));
}
bool Sample::operator==(const Sample &smp) const
@@ -106,63 +105,68 @@ bool Sample::operator==(const Sample &smp) const
* @param xb X of point b
* @return estimated Y of test point
*/
-inline float linearEstimate(float ya, float yb, float xt, int xa = 0, int xb = 1)
+float linearEstimate(float ya, float yb, float xt, float xa = 0.0, float xb =1.0)
{
- if(xa == xb)
- return ya;
+#warning TODO this could be done with a good bit less computation
+ //Lets make this simple by normalizing the x axis
+
+ //Normalize point a
+ xb -= xa;
+ xt -= xa;
+ xa -= xa;
- return (yb-ya) * (xt-xa)/(xb-xa) + ya;
+ //Normalize point b
+ xt /= xb;
+ xb /= xb;
+
+ //Now xa=0 xb=1 0<=xt<=1
+ //simpily use y=mx+b
+ return (yb-ya) * xt + ya;
}
-void Sample::resize(unsigned int nsize)
+
+void Sample::resample(const unsigned int rate, const unsigned int nrate)
{
- if(bufferSize == nsize)
- return;
+ if(rate == nrate)
+ return; //no resampling here
else {//resampling occurs here
- float ratio = (nsize * 1.0) / (bufferSize * 1.0);
+ float ratio = (nrate * 1.0) / (rate * 1.0);
- int nBufferSize = nsize;
+ int nBufferSize = (int)bufferSize * ratio;
float *nBuffer = new float[nBufferSize];
- //take care of edge cases
- *nBuffer = *buffer;
- *(nBuffer+nBufferSize-1) = *(buffer+bufferSize-1);
-
//addition is done to avoid 0 edge case
- for(int i = 1; i < nBufferSize - 1; ++i)
- {
- float left = floor(i/ratio);
- float right = ceil((i+1)/ratio);
- float test = i/ratio;
- if(left > bufferSize - 1)
- left = bufferSize - 1;
- if(right > bufferSize - 1)
- right = bufferSize - 1;
- if(left > test)
- test = left;
- nBuffer[i] = linearEstimate(buffer[(int)left],
- buffer[(int)right],
- test, (int)left, (int)right);
- }
+ for(int i = 0; i < nBufferSize; ++i)
+ nBuffer[i] = linearEstimate(buffer[(int)floor(i/ratio)],
+ buffer[(int)ceil((i+1)/ratio)],
+ i,
+ floor(i/ratio),
+ ceil((i+1)/ratio));
//put the new data in
- delete[] buffer;
+ delete[] buffer;
buffer = nBuffer;
bufferSize = nBufferSize;
}
}
-void Sample::append(const Sample &smp)
+Sample &Sample::append(const Sample &smp)
{
int nbufferSize = bufferSize + smp.bufferSize;
float *nbuffer = new float[nbufferSize];
memcpy(nbuffer, buffer, bufferSize * sizeof(float));
memcpy(nbuffer + bufferSize, smp.buffer, smp.bufferSize * sizeof(float));
- delete buffer;
+ delete[] buffer;
buffer = nbuffer;
bufferSize = nbufferSize;
+ return *this;
+}
+
+Sample Sample::subSample(int a, int b) const
+{
+ return Sample(b-a, buffer+a);
}
REALTYPE Sample::max() const
diff --git a/src/Samples/Sample.h b/src/Samples/Sample.h
@@ -22,11 +22,12 @@
#define SAMPLE_H
#include "../globals.h"
/**
- * Base Class for Samples
+ * Audio Samples Representation
*/
class Sample
{
public:
+ Sample();
Sample(const Sample &smp);
Sample(int length, REALTYPE fill = 0);
Sample(int length, const REALTYPE *fill);
@@ -57,11 +58,15 @@ class Sample
* sparingly*/
const REALTYPE *c_buf() const {return buffer;}
- /**Change the size of the sample*/
- void resize(unsigned int nsize);
+ /**Change the sampling rate of the Sample*/
+ void resample(const unsigned int rate, const unsigned int nrate);
- /**Appends another Sample to this Sample*/
- void append(const Sample &smp);
+ /**Appends another Sample to this Sample
+ * @return this*/
+ Sample &append(const Sample &smp);
+
+ /**Gets a subsample from a to b*/
+ Sample subSample(int a, int b) const;
REALTYPE max() const;
REALTYPE min() const;
diff --git a/src/Seq/Makefile b/src/Seq/Makefile
@@ -1,14 +0,0 @@
-include ../Makefile.inc
-
-objects=MIDIEvents.o MIDIFile.o Sequencer.o
-
-
-all: $(objects)
-
--include ../Make.deps
-
-.PHONY : clean
-clean:
- rm -f $(objects)
- rm -f makeinclude.deps
-
diff --git a/src/Synth/Makefile b/src/Synth/Makefile
@@ -1,14 +0,0 @@
-include ../Makefile.inc
-
-objects=ADnote.o Envelope.o LFO.o OscilGen.o SUBnote.o Resonance.o PADnote.o
-
-
-all: $(objects)
-
--include ../Make.deps
-
-.PHONY : clean
-clean:
- rm -f $(objects)
- rm -f makeinclude.deps
-
diff --git a/src/Tests/EchoTest.h b/src/Tests/EchoTest.h
@@ -21,6 +21,7 @@
*/
#include <cxxtest/TestSuite.h>
#include <cmath>
+#include <cstdlib>
#include <iostream>
#include "../Effects/Echo.h"
#include "../globals.h"
diff --git a/src/Tests/SampleTest.h b/src/Tests/SampleTest.h
@@ -80,5 +80,23 @@ class SampleTest:public CxxTest::TestSuite
for(int i = 0; i < 74; ++i)
TS_ASSERT_DELTA(smp1[i], (i < 54 ? 2 : 17), 0.001);
}
+
+ void testResample() {
+ Sample orig(32,2);
+ Sample cpy(orig);
+
+ //test for no resampleing
+ orig.resample(128,128);
+ TS_ASSERT_EQUALS(cpy,orig);
+
+ //test for no bad distortions
+ orig.resample(128,256);
+ orig.resample(256,128);
+ TS_ASSERT_EQUALS(cpy,orig);
+
+ //test for downsample
+ orig.resample(256,128);
+ TS_ASSERT_EQUALS(orig.size(),cpy.size()/2);
+ }
};
diff --git a/src/UI/CMakeLists.txt b/src/UI/CMakeLists.txt
@@ -27,6 +27,7 @@ fltk_wrap_ui(zynaddsubfx_gui ${UI_fl_files})
add_library(zynaddsubfx_gui STATIC
${UI_objs}
${zynaddsubfx_gui_FLTK_UI_SRCS}
+ NioUI.cpp
)
target_link_libraries(zynaddsubfx_gui ${FLTK_LIBRARIES} ${MYFLTK_LIBRARIES})
diff --git a/src/UI/Makefile b/src/UI/Makefile
@@ -1,41 +0,0 @@
-include ../Makefile.inc
-
-%.cc : %.fl
- fluid -c $<
-
-objects=WidgetPDial.o PresetsUI.o EnvelopeUI.o LFOUI.o FilterUI.o VirKeyboard.o ConfigUI.o\
- SUBnoteUI.o ResonanceUI.o OscilGenUI.o ADnoteUI.o PADnoteUI.o EffUI.o BankUI.o \
- PartUI.o MicrotonalUI.o SeqUI.o MasterUI.o
-ifeq ($(DISABLE_GUI),YES)
- objects=
-endif
-
-all: $(objects)
-
-WidgetPDial.o: WidgetPDial.fl WidgetPDial.cc WidgetPDial.h
-PresetsUI.o: PresetsUI.fl PresetsUI.cc PresetsUI.h
-EnvelopeUI.o: EnvelopeUI.fl EnvelopeUI.cc EnvelopeUI.h
-LFOUI.o: LFOUI.fl LFOUI.cc LFOUI.h
-FilterUI.o: FilterUI.fl FilterUI.cc FilterUI.h
-
-ResonanceUI.o:ResonanceUI.fl ResonanceUI.cc ResonanceUI.h
-OscilGenUI.o:OscilGenUI.fl OscilGenUI.cc OscilGenUI.h
-ADnoteUI.o:ADnoteUI.fl ADnoteUI.cc ADnoteUI.h
-SUBnoteUI.o:SUBnoteUI.fl SUBnoteUI.cc SUBnoteUI.h
-PADnoteUI.o:PADnoteUI.fl PADnoteUI.cc PADnoteUI.h
-
-EffUI.o: EffUI.fl EffUI.cc EffUI.h
-BankUI.o: BankUI.fl BankUI.cc BankUI.h
-PartUI.o: PartUI.fl PartUI.cc PartUI.h
-
-VirKeyboard.o: VirKeyboard.fl VirKeyboard.cc VirKeyboard.h
-ConfigUI.o: ConfigUI.fl ConfigUI.cc ConfigUI.h
-MicrotonalUI.o: MicrotonalUI.fl MicrotonalUI.cc MicrotonalUI.h
-SeqUI.o: SeqUI.fl SeqUI.cc SeqUI.h
-MasterUI.o: MasterUI.fl MasterUI.cc MasterUI.h
-
-.PHONY : clean
-clean:
- rm -f $(objects)
- rm -f makeinclude.deps
- rm -f *.h *.cc
diff --git a/src/UI/MasterUI.fl b/src/UI/MasterUI.fl
@@ -48,6 +48,9 @@ decl {\#include "SeqUI.h"} {public
decl {\#include "PresetsUI.h"} {public
}
+decl {\#include "NioUI.h"} {public global
+}
+
decl {\#include "../Misc/Master.h"} {public
}
@@ -60,7 +63,7 @@ decl {\#include "../Misc/Util.h"} {public
decl {\#include "../globals.h"} {public
}
-class VUMeter {: {public Fl_Box}
+class VUMeter {selected : {public Fl_Box}
} {
Function {VUMeter(int x,int y, int w, int h, const char *label=0):Fl_Box(x,y,w,h,label)} {} {
code {master=NULL;
@@ -81,15 +84,17 @@ oldrmsdbr=0.0;} {}
int ox=x(); int oy=y(); int lx=w(); int ly=h();
-pthread_mutex_lock(&master->mutex);
-REALTYPE dbl=rap2dB(master->vuoutpeakl);
-REALTYPE dbr=rap2dB(master->vuoutpeakr);
-REALTYPE rmsdbl=rap2dB(master->vurmspeakl);
-REALTYPE rmsdbr=rap2dB(master->vurmspeakr);
-REALTYPE maxdbl=rap2dB(master->vumaxoutpeakl);
-REALTYPE maxdbr=rap2dB(master->vumaxoutpeakr);
-int clipped=master->vuclipped;
-pthread_mutex_unlock(&master->mutex);
+vuData data = master->getVuData();
+
+//pthread_mutex_lock(&master->mutex);
+REALTYPE dbl=rap2dB(data.outpeakl);
+REALTYPE dbr=rap2dB(data.outpeakr);
+REALTYPE rmsdbl=rap2dB(data.rmspeakl);
+REALTYPE rmsdbr=rap2dB(data.rmspeakr);
+REALTYPE maxdbl=rap2dB(data.maxoutpeakl);
+REALTYPE maxdbr=rap2dB(data.maxoutpeakr);
+int clipped=data.clipped;
+//pthread_mutex_unlock(&master->mutex);
dbl=(MIN_DB-dbl)/MIN_DB;
if (dbl<0.0) dbl=0.0;
@@ -229,7 +234,7 @@ REALTYPE tmp=ly*1.0/MIN_DB;
Function {tick(void *v)} {return_type {static void}
} {
code {tickdraw((VUMeter *) v);
-Fl::add_timeout(1.0/25.0,tick,v);//25 fps} {}
+Fl::add_timeout(1.0/60.0,tick,v);//60 fps} {}
}
Function {handle(int event)} {return_type int
} {
@@ -298,7 +303,7 @@ class Panellistitem {: {public Fl_Group}
Function {make_window()} {private
} {
Fl_Window panellistitem {
- private xywh {315 213 70 260} type Double hide
+ private xywh {315 213 70 260} type Double labeltype NORMAL_LABEL align 80 hide
class Fl_Group
} {
Fl_Group panellistitemgroup {
@@ -425,7 +430,7 @@ if (fl_choice("Exit and leave the unsaved data?","No","Yes",NULL)) {
*exitprogram=1;
};
\#endif}
- xywh {31 206 390 465} type Double hide xclass zynaddsubfx
+ xywh {450 306 390 465} type Double align 80 hide xclass zynaddsubfx
} {
Fl_Menu_Bar mastermenu {
xywh {-5 0 690 25}
@@ -506,7 +511,13 @@ updatepanel();}
MenuItem {} {
label {&Settings...}
callback {configui->show();}
- xywh {25 25 100 20} divider
+ xywh {25 25 100 20}
+ }
+ MenuItem {} {
+ label {N&io Settings}
+ callback {nioui.refresh();
+nioui.show();}
+ xywh {0 0 36 21} divider
}
MenuItem {} {
label {&Copyright...}
@@ -1002,7 +1013,7 @@ panelwindow->show();}
}
Fl_Window aboutwindow {
label {Copyright...}
- xywh {411 344 365 280} type Double hide
+ xywh {411 344 365 280} type Double labeltype NORMAL_LABEL align 80 hide
} {
Fl_Box {} {
label {Copyright (c) 2002-2009 Nasca O. PAUL and others. Please read AUTHORS.txt}
@@ -1029,7 +1040,7 @@ GNU General Public License for details.}
}
Fl_Window syseffsendwindow {
label {System Effects Send}
- xywh {171 234 120 250} type Double hide resizable
+ xywh {171 234 120 250} type Double labeltype NORMAL_LABEL align 80 hide resizable
} {
Fl_Scroll {} {open
xywh {0 45 120 170} box FLAT_BOX resizable
@@ -1048,7 +1059,7 @@ GNU General Public License for details.}
}
Fl_Window panelwindow {
label {ZynAddSubFX Panel}
- xywh {89 59 630 635} type Double hide
+ xywh {89 59 630 635} type Double labeltype NORMAL_LABEL align 80 hide
} {
Fl_Scroll {} {
xywh {0 5 570 310} type HORIZONTAL box THIN_UP_BOX
@@ -1088,7 +1099,7 @@ if (fl_choice("Exit and leave the unsaved data?","No","Yes",NULL)) {
*exitprogram=1;
};
\#endif}
- xywh {400 405 600 335} type Double hide
+ xywh {400 405 600 335} type Double labeltype NORMAL_LABEL align 80 hide
} {
Fl_Menu_Bar {} {
xywh {0 0 690 25}
@@ -1578,7 +1589,7 @@ virkeys->take_focus();}
Fl_Window selectuiwindow {
label {User Interface mode}
callback {*exitprogram=1;}
- xywh {342 246 430 250} type Double hide non_modal
+ xywh {342 246 430 250} type Double labeltype NORMAL_LABEL align 80 hide non_modal
} {
Fl_Box {} {
label {Welcome to ZynAddSubFX}
@@ -1738,8 +1749,9 @@ pthread_mutex_lock(&master->mutex);
//load the data
int result=master->loadXML(filename);
-pthread_mutex_unlock(&master->mutex);
+
master->applyparameters();
+pthread_mutex_unlock(&master->mutex);
npartcounter->value(1);
refresh_master_ui();
@@ -1825,4 +1837,5 @@ bankui->hide();} {}
decl {int swapefftype;} {}
decl {char masterwindowlabel[100];} {}
decl {Panellistitem *panellistitem[NUM_MIDI_PARTS];} {}
+ decl {NioUI nioui;} {}
}
diff --git a/src/UI/NioUI.cpp b/src/UI/NioUI.cpp
@@ -0,0 +1,82 @@
+#include "NioUI.h"
+#include "../Nio/EngineMgr.h"
+#include "../Nio/OutMgr.h"
+#include "../Nio/InMgr.h"
+#include "../Nio/AudioOut.h"
+#include "../Nio/MidiIn.h"
+#include <cstdio>
+#include <FL/Fl_Tabs.H>
+#include <FL/Fl_Group.H>
+#include <FL/Fl_Text_Display.H>
+#include <iostream>
+#include <cstring>
+
+using namespace std;
+
+NioUI::NioUI()
+ :Fl_Window(200,100,400,400,"New IO Controls")
+{
+ //hm, I appear to be leaking memory
+ Fl_Tabs *wintabs = new Fl_Tabs(0,0,400,400-15);
+ {
+ Fl_Group *gen = new Fl_Group(0,20,400,400-35,"General");
+ {
+ Fl_Text_Buffer *buff = new Fl_Text_Buffer();
+ Fl_Text_Display *intro = new Fl_Text_Display(20,40,350,300);
+ intro->buffer(buff);
+ buff->text("Thanks For Testing Out the New"
+ " Input/Output system. "
+ "Beware of bugs that may exist and"
+ " enjoy the new system.");
+ intro->wrap_mode(4, 40);
+ }
+ gen->end();
+
+ Fl_Group *settings = new Fl_Group(0,20,400,400-35,"Settings");
+ {
+ audio = new Fl_Choice(60, 80, 100, 25, "Audio");
+ audio->callback(audioCallback);
+ midi = new Fl_Choice(60, 100, 100, 25, "Midi");
+ midi->callback(midiCallback);
+ }
+ settings->end();
+
+ int audioval = 0;
+ int midival = 0;
+ for(list<Engine *>::iterator itr = sysEngine->engines.begin();
+ itr != sysEngine->engines.end(); ++itr) {
+ Engine *eng = *itr;
+ if(dynamic_cast<MidiIn *>(eng))
+ midi->add(eng->name.c_str());
+ if(dynamic_cast<AudioOut *>(eng))
+ audio->add(eng->name.c_str());
+ if(eng->name == sysOut->getSink())
+ audioval = audio->size() - 2;
+ if(eng->name == sysIn->getSource())
+ midival = midi->size() - 2;
+ }
+ audio->value(audioval);
+ midi->value(midival);
+ }
+ wintabs->end();
+
+ resizable(this);
+ size_range(400,300);
+}
+
+void NioUI::refresh()
+{
+}
+
+void NioUI::midiCallback(Fl_Widget *c)
+{
+ bool good = sysIn->setSource(static_cast<Fl_Choice *>(c)->text());
+ static_cast<Fl_Choice *>(c)->textcolor(fl_rgb_color(255*!good,0,0));
+}
+
+void NioUI::audioCallback(Fl_Widget *c)
+{
+ bool good = sysOut->setSink(static_cast<Fl_Choice *>(c)->text());
+ static_cast<Fl_Choice *>(c)->textcolor(fl_rgb_color(255*!good,0,0));
+}
+
diff --git a/src/UI/NioUI.h b/src/UI/NioUI.h
@@ -0,0 +1,29 @@
+#ifndef NIOUI_H
+#define NIOUT_H
+
+#include <FL/Fl.H>
+#include <FL/Fl_Light_Button.H>
+#include <FL/Fl_Window.H>
+#include <FL/Fl_Pack.H>
+#include <FL/Fl_Spinner.H>
+#include <FL/Enumerations.H>
+#include <FL/Fl_Choice.H>
+#include <list>
+#include <string>
+
+class NioUI : public Fl_Window
+{
+ public:
+ NioUI();
+ void refresh();
+ private:
+ //std::list<NioTab *> tabs;
+
+ Fl_Choice *midi;
+ Fl_Choice *audio;
+ static void midiCallback(Fl_Widget *c);
+ static void audioCallback(Fl_Widget *c);
+};
+
+#endif
+
diff --git a/src/UI/VirKeyboard.fl b/src/UI/VirKeyboard.fl
@@ -1,5 +1,5 @@
# data file for the Fltk User Interface Designer (fluid)
-version 1.0107
+version 1.0300
header_name {.h}
code_name {.cc}
decl {//Copyright (c) 2002-2005 Nasca Octavian Paul} {}
@@ -205,7 +205,7 @@ if (rndvelocity!=0){
};
pthread_mutex_lock(&master->mutex);
- master->NoteOn(midich,nk+midioct*12,(int)vel);
+master->noteOn(midich,nk+midioct*12,(int)vel);
pthread_mutex_unlock(&master->mutex);} {}
}
Function {relasekey(int nk,int type)} {} {
@@ -219,7 +219,7 @@ pressed[nk]=0;
damage(1);
pthread_mutex_lock(&master->mutex);
- master->NoteOff(midich,nk+12*midioct);
+master->noteOff(midich,nk+12*midioct);
pthread_mutex_unlock(&master->mutex);} {}
}
Function {relaseallkeys(int type)} {} {
@@ -293,7 +293,7 @@ virkeyboardwindow->hide();}
callback {int ctl=midictl;
pthread_mutex_lock(&master->mutex);
- master->SetController(virkeys->midich,ctl,(int) o->value());
+master->setController(virkeys->midich,ctl,(int) o->value());
pthread_mutex_unlock(&master->mutex);
virkeys->take_focus();}
tooltip {Controller value} xywh {605 10 15 115} type {Vert Fill} box ENGRAVED_BOX selection_color 229 labelsize 8 align 5 minimum 127 maximum 0 step 1 value 64 textsize 7
@@ -375,7 +375,7 @@ virkeys->take_focus();}
Fl_Roller pitchwheelroller {
label Pwh
callback {pthread_mutex_lock(&master->mutex);
- master->SetController(virkeys->midich,C_pitchwheel,-(int) o->value());
+master->setController(virkeys->midich,C_pitchwheel,-(int) o->value());
pthread_mutex_unlock(&master->mutex);
virkeys->take_focus();}
tooltip {Pitch Wheel} xywh {625 10 20 95} box PLASTIC_UP_BOX labelsize 8 align 1 when 3 minimum -8192 maximum 8192 step 64
@@ -388,7 +388,7 @@ pitchwheelroller->do_callback();}
}
Fl_Dial {} {
label Vrnd
- callback {virkeys->rndvelocity=(int) o->value();}
+ callback {virkeys->rndvelocity=(int) o->value();} selected
tooltip {Velocity Randomness} xywh {205 105 20 20} box ROUND_UP_BOX labelsize 10 align 129 maximum 127 step 1
code0 {o->value(virkeys->rndvelocity);}
class WidgetPDial
@@ -410,8 +410,7 @@ midictl=75;
make_window();} {}
}
Function {~VirKeyboard()} {} {
- code {delete virkeyboardwindow;} {selected
- }
+ code {delete virkeyboardwindow;} {}
}
Function {show()} {} {
code {virkeyboardwindow->show();} {}
diff --git a/src/main.cpp b/src/main.cpp
@@ -1,7 +1,7 @@
/*
ZynAddSubFX - a software synthesizer
- main.c - Main file of the synthesizer
+ main.cpp - Main file of the synthesizer
Copyright (C) 2002-2005 Nasca Octavian Paul
Author: Nasca Octavian Paul
@@ -20,13 +20,15 @@
*/
-#include <stdio.h> //remove once iostream is used
#include <iostream>
+#include <cmath>
+#include <cctype>
+#include <algorithm>
#include <unistd.h>
#include <pthread.h>
-#ifdef OS_LINUX
+#if OS_LINUX || OS_CYGWIN
#include <getopt.h>
#elif OS_WINDOWS
#include <winbase.h>
@@ -38,21 +40,12 @@
#include "Misc/Dump.h"
extern Dump dump;
-#ifdef ALSAMIDIIN
-#include "Input/ALSAMidiIn.h"
-#endif
-
-#ifdef OSSMIDIIN
-#include "Input/OSSMidiIn.h"
-#endif
-
-#if (defined(NONEMIDIIN) || defined(VSTMIDIIN) || defined(DSSIMIDIIN))
-#include "Input/NULLMidiIn.h"
-#endif
-
-#ifdef WINMIDIIN
-#include "Input/WINMidiIn.h"
-#endif
+//Nio System
+#include "Nio/MidiIn.h"
+#include "Nio/AudioOut.h"
+#include "Nio/OutMgr.h"
+#include "Nio/InMgr.h"
+#include "Nio/EngineMgr.h"
#ifndef DISABLE_GUI
#ifdef QT_GUI
@@ -72,140 +65,27 @@ MasterUI *ui;
using namespace std;
-pthread_t thr1, thr2, thr3, thr4;
+pthread_t thr3, thr4;
Master *master;
int swaplr = 0; //1 for left-right swapping
-bool usejackit = false;
-
-#ifdef JACKAUDIOOUT
-#include "Output/JACKaudiooutput.h"
-#endif
-
-#ifdef JACK_RTAUDIOOUT
-#include "Output/JACKaudiooutput.h"
-#endif
-
-#ifdef PAAUDIOOUT
-#include "Output/PAaudiooutput.h"
-#endif
-
-#ifdef OSSAUDIOOUT
-#include "Output/OSSaudiooutput.h"
-OSSaudiooutput *audioout;
-#endif
#ifdef USE_LASH
#include "Misc/LASHClient.h"
LASHClient *lash;
#endif
-MidiIn *Midi;
int Pexitprogram = 0; //if the UI set this to 1, the program will exit
/*
- * Try to get the realtime priority
- */
-void set_realtime()
-{
-#ifdef OS_LINUX
- sched_param sc;
-
- sc.sched_priority = 50;
-
- //if you want get "sched_setscheduler undeclared" from compilation, you can safely remove the folowing line
- sched_setscheduler(0, SCHED_FIFO, &sc);
-// if (err==0) printf("Real-time");
-#endif
-}
-
-/*
- * Midi input thread
- */
-#if !(defined(WINMIDIIN) || defined(VSTMIDIIN))
-void *thread1(void *arg)
-{
- MidiCmdType cmdtype = MidiNoteOFF;
- unsigned char cmdchan = 0, note = 0, vel = 0;
- int cmdparams[MP_MAX_BYTES];
- for(int i = 0; i < MP_MAX_BYTES; ++i)
- cmdparams[i] = 0;
-
- set_realtime();
- while(Pexitprogram == 0) {
- Midi->getmidicmd(cmdtype, cmdchan, cmdparams);
- note = cmdparams[0];
- vel = cmdparams[1];
-
- pthread_mutex_lock(&master->mutex);
-
- if((cmdtype == MidiNoteON) && (note != 0))
- master->NoteOn(cmdchan, note, vel);
- if((cmdtype == MidiNoteOFF) && (note != 0))
- master->NoteOff(cmdchan, note);
- if(cmdtype == MidiController)
- master->SetController(cmdchan, cmdparams[0], cmdparams[1]);
-
- pthread_mutex_unlock(&master->mutex);
- }
-
- return 0;
-}
-#endif
-
-/*
- * Wave output thread (for OSS AUDIO out)
- */
-#if defined(OSSAUDIOOUT)
-//!(defined(JACKAUDIOOUT)||defined(JACK_RTAUDIOOUT)||defined(PAAUDIOOUT)||defined(VSTAUDIOOUT))
-
-void *thread2(void *arg)
-{
- REALTYPE outputl[SOUND_BUFFER_SIZE];
- REALTYPE outputr[SOUND_BUFFER_SIZE];
-
- set_realtime();
- while(Pexitprogram == 0) {
- pthread_mutex_lock(&master->mutex);
- master->AudioOut(outputl, outputr);
- pthread_mutex_unlock(&master->mutex);
-
-#ifndef NONEAUDIOOUT
- audioout->OSSout(outputl, outputr);
-#endif
-
- /** / int i,x,x2;
- REALTYPE xx,xx2;
-
- short int xsmps[SOUND_BUFFER_SIZE*2];
- for (i=0;i<SOUND_BUFFER_SIZE;i++){//output to stdout
- xx=-outputl[i]*32767;
- xx2=-outputr[i]*32767;
- if (xx<-32768) xx=-32768;
- if (xx>32767) xx=32767;
- if (xx2<-32768) xx2=-32768;
- if (xx2>32767) xx2=32767;
- x=(short int) xx;
- x2=(short int) xx2;
- xsmps[i*2]=x;xsmps[i*2+1]=x2;
- };
- write(1,&xsmps,SOUND_BUFFER_SIZE*2*2);
-
- / * */
- }
- return 0;
-}
-#endif
-
-/*
* User Interface thread
*/
-
-
-void *thread3(void *arg)
+void *thread3(void *)
{
#ifndef DISABLE_GUI
#ifdef FLTK_GUI
+
+ ui = new MasterUI(master, &Pexitprogram);
ui->showUI();
while(Pexitprogram == 0) {
@@ -240,6 +120,9 @@ void *thread3(void *arg)
return 0;
}
+//this code is disabled for Nio testing
+//it should get moved out of here into the nio system soon
+#if 0
/*
* Sequencer thread (test)
*/
@@ -277,36 +160,26 @@ void *thread4(void *arg)
}
//if (!realtime player) atunci fac asta
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-#ifdef OS_LINUX
- usleep(1000);
-#elif OS_WINDOWS
- Sleep(1);
-#endif
+ os_sleep(1000);
}
return 0;
}
+#endif
/*
* Program initialisation
*/
-
-
void initprogram()
{
cerr.precision(1);
cerr << std::fixed;
-#ifndef JACKAUDIOOUT
-#ifndef JACK_RTAUDIOOUT
cerr << "\nSample Rate = \t\t" << SAMPLE_RATE << endl;
-#endif
-#endif
cerr << "Sound Buffer Size = \t" << SOUND_BUFFER_SIZE << " samples" << endl;
cerr << "Internal latency = \t" << SOUND_BUFFER_SIZE * 1000.0
/ SAMPLE_RATE << " ms" << endl;
cerr << "ADsynth Oscil.Size = \t" << OSCIL_SIZE << " samples" << endl;
- //fflush(stderr);
srand(time(NULL));
denormalkillbuf = new REALTYPE [SOUND_BUFFER_SIZE];
for(int i = 0; i < SOUND_BUFFER_SIZE; i++)
@@ -315,42 +188,16 @@ void initprogram()
master = new Master();
master->swaplr = swaplr;
-#if defined(JACKAUDIOOUT)
- if(usejackit) {
- bool tmp = JACKaudiooutputinit(master);
-#if defined(OSSAUDIOOUT)
- if(!tmp)
- cout << "\nUsing OSS instead." << endl;
-#else
- if(!tmp)
- exit(1);
-#endif
- usejackit = tmp;
- }
-#endif
-#if defined(OSSAUDIOOUT)
- if(!usejackit)
- audioout = new OSSaudiooutput();
- else
- audioout = NULL;
-#endif
+ //Nio Initialization
-#ifdef JACK_RTAUDIOOUT
- JACKaudiooutputinit(master);
-#endif
-#ifdef PAAUDIOOUT
- PAaudiooutputinit(master);
-#endif
+ //Enable input wrapper
+ sysIn = new InMgr(master);
-#ifdef ALSAMIDIIN
- Midi = new ALSAMidiIn();
-#endif
-#ifdef OSSMIDIIN
- Midi = new OSSMidiIn();
-#endif
-#if (defined(NONEMIDIIN) || (defined(VSTMIDIIN)))
- Midi = new NULLMidiIn();
-#endif
+ //Initialize the Output Systems
+ sysOut = new OutMgr(master);
+
+ //Initialize The Engines
+ sysEngine = new EngineMgr();
}
/*
@@ -359,35 +206,25 @@ void initprogram()
void exitprogram()
{
pthread_mutex_lock(&master->mutex);
-#ifdef OSSAUDIOOUT
- delete (audioout);
-#endif
-#ifdef JACKAUDIOOUT
- if(usejackit)
- JACKfinish();
-#endif
-#ifdef JACK_RTAUDIOOUT
- JACKfinish();
-#endif
-#ifdef PAAUDIOOUT
- PAfinish();
-#endif
+ pthread_mutex_unlock(&master->mutex);
+ sysEngine->stop();
+ delete sysOut;
+ delete sysIn;
+ delete sysEngine;
#ifndef DISABLE_GUI
- delete (ui);
+ delete ui;
#endif
- delete (Midi);
- delete (master);
+ delete master;
#ifdef USE_LASH
- delete (lash);
+ delete lash;
#endif
-// pthread_mutex_unlock(&master->mutex);
delete [] denormalkillbuf;
}
-#ifdef OS_WINDOWS
+#if OS_WINDOWS
#define ARGSIZE 100
char winoptarguments[ARGSIZE];
char getopt(int argc, char *argv[], const char *shortopts, int *index)
@@ -403,9 +240,7 @@ char getopt(int argc, char *argv[], const char *shortopts, int *index)
result = argv[*index][1];
if(*index + 1 < argc)
snprintf(winoptarguments, ARGSIZE, "%s", argv[*index + 1]);
- ;
}
- ;
(*index)++;
return result;
}
@@ -424,91 +259,68 @@ int main(int argc, char *argv[])
config.init();
dump.startnow();
int noui = 0;
-#ifdef JACKAUDIOOUT
- usejackit = true; //use jack by default
-#endif
cerr
<< "\nZynAddSubFX - Copyright (c) 2002-2009 Nasca Octavian Paul and others"
<< endl;
cerr << "Compiled: " << __DATE__ << " " << __TIME__ << endl;
cerr << "This program is free software (GNU GPL v.2 or later) and \n";
cerr << "it comes with ABSOLUTELY NO WARRANTY.\n" << endl;
-#ifdef OS_LINUX
- if(argc == 1)
- cerr << "Try 'zynaddsubfx --help' for command-line options." << endl;
-#else
- if(argc == 1)
- cerr << "Try 'zynaddsubfx -h' for command-line options.\n" << endl;
+ if(argc == 1)
+#if OS_LINUX || OS_CYGWIN
+ cerr << "Try 'zynaddsubfx --help' for command-line options." << endl;
+#else //assuming windows
+ cerr << "Try 'zynaddsubfx -h' for command-line options.\n" << endl;
#endif
+
/* Get the settings from the Config*/
SAMPLE_RATE = config.cfg.SampleRate;
SOUND_BUFFER_SIZE = config.cfg.SoundBufferSize;
OSCIL_SIZE = config.cfg.OscilSize;
swaplr = config.cfg.SwapStereo;
+
/* Parse command-line options */
-#ifdef OS_LINUX
+#if OS_LINUX || OS_CYGWIN
struct option opts[] = {
- {
- "load", 2, NULL, 'l'
- },
- {
- "load-instrument", 2, NULL, 'L'
- },
- {
- "sample-rate", 2, NULL, 'r'
- },
- {
- "buffer-size", 2, NULL, 'b'
- },
- {
- "oscil-size", 2, NULL, 'o'
- },
- {
- "dump", 2, NULL, 'D'
- },
- {
- "swap", 2, NULL, 'S'
- },
- {
- "no-gui", 2, NULL, 'U'
- },
- {
- "not-use-jack", 2, NULL, 'A'
- },
- {
- "dummy", 2, NULL, 'Y'
- },
- {
- "help", 2, NULL, 'h'
- },
- {
- 0, 0, 0, 0
- }
+ {"load", 2, NULL, 'l'},
+ {"load-instrument", 2, NULL, 'L'},
+ {"sample-rate", 2, NULL, 'r'},
+ {"buffer-size", 2, NULL, 'b'},
+ {"oscil-size", 2, NULL, 'o'},
+ {"dump", 2, NULL, 'D'},
+ {"swap", 2, NULL, 'S'},
+ {"no-gui", 2, NULL, 'U'},
+ {"dummy", 2, NULL, 'Y'},
+ {"help", 2, NULL, 'h'},
+ {"output", 1, NULL, 'O'},
+ {"input", 1, NULL, 'I'},
+ {0, 0, 0, 0}
};
#endif
opterr = 0;
int option_index = 0, opt, exitwithhelp = 0;
- char loadfile[1001];
- ZERO(loadfile, 1001);
- char loadinstrument[1001];
- ZERO(loadinstrument, 1001);
+ string loadfile, loadinstrument, input, output;
while(1) {
/**\todo check this process for a small memory leak*/
-#ifdef OS_LINUX
- opt = getopt_long(argc, argv, "l:L:r:b:o:hSDUAY", opts, &option_index);
+#if OS_LINUX || OS_CYGWIN
+ opt = getopt_long(argc, argv, "l:L:r:b:o:I:O:hSDUY", opts, &option_index);
char *optarguments = optarg;
-#else
- opt = getopt(argc, argv, "l:L:r:b:o:hSDUAY", &option_index);
+#elif OS_WINDOWS
+ opt = getopt(argc, argv, "l:L:r:b:o:I:O:hSDUY", &option_index);
char *optarguments = &winoptarguments[0];
+#else
+#error Undefined OS
#endif
+#define GETOP(x) if(optarguments) x = optarguments
+#define GETOPNUM(x) if(optarguments) x = atoi(optarguments)
+
+
if(opt == -1)
break;
- int tmp;
switch(opt) {
case 'h':
exitwithhelp = 1;
@@ -523,60 +335,36 @@ int main(int argc, char *argv[])
case 'U':
noui = 1;
break;
- case 'A':
-#ifdef JACKAUDIOOUT
-#ifdef OSSAUDIOOUT
- usejackit = false;
-#endif
-#endif
- break;
case 'l':
- tmp = 0;
- if(optarguments != NULL)
- snprintf(loadfile, 1000, "%s", optarguments);
- ;
+ GETOP(loadfile);
break;
case 'L':
- tmp = 0;
- if(optarguments != NULL)
- snprintf(loadinstrument, 1000, "%s", optarguments);
- ;
+ GETOP(loadinstrument);
break;
case 'r':
- tmp = 0;
- if(optarguments != NULL)
- tmp = atoi(optarguments);
- if(tmp >= 4000)
- SAMPLE_RATE = tmp;
- else {
+ GETOPNUM(SAMPLE_RATE);
+ if(SAMPLE_RATE < 4000) {
cerr << "ERROR:Incorrect sample rate: " << optarguments << endl;
exit(1);
}
break;
case 'b':
- tmp = 0;
- if(optarguments != NULL)
- tmp = atoi(optarguments);
- if(tmp >= 2)
- SOUND_BUFFER_SIZE = tmp;
- else {
+ GETOPNUM(SOUND_BUFFER_SIZE);
+ if(SOUND_BUFFER_SIZE < 2) {
cerr << "ERROR:Incorrect buffer size: " << optarguments << endl;
exit(1);
}
break;
case 'o':
- tmp = 0;
- if(optarguments != NULL)
- tmp = atoi(optarguments);
- OSCIL_SIZE = tmp;
+ int tmp;
+ if(optarguments)
+ OSCIL_SIZE = tmp = atoi(optarguments);
if(OSCIL_SIZE < MAX_AD_HARMONICS * 2)
OSCIL_SIZE = MAX_AD_HARMONICS * 2;
OSCIL_SIZE = (int) pow(2, ceil(log(OSCIL_SIZE - 1.0) / log(2.0)));
if(tmp != OSCIL_SIZE) {
- cerr
- <<
- "\nOSCIL_SIZE is wrong (must be 2^n) or too small. Adjusting to ";
- cerr << OSCIL_SIZE << "." << endl;
+ cerr << "OSCIL_SIZE is wrong (must be 2^n) or too small. Adjusting to "
+ << OSCIL_SIZE << "." << endl;
}
break;
case 'S':
@@ -585,6 +373,12 @@ int main(int argc, char *argv[])
case 'D':
dump.startnow();
break;
+ case 'I':
+ GETOP(input);
+ break;
+ case 'O':
+ GETOP(output);
+ break;
case '?':
cerr << "ERROR:Bad option or parameter.\n" << endl;
exitwithhelp = 1;
@@ -593,44 +387,29 @@ int main(int argc, char *argv[])
}
if(exitwithhelp != 0) {
- cout << "Usage: zynaddsubfx [OPTION]\n" << endl;
- cout << " -h , --help \t\t\t\t display command-line help and exit"
- << endl;
- cout << " -l file, --load=FILE\t\t\t loads a .xmz file" << endl;
- cout << " -L file, --load-instrument=FILE\t\t loads a .xiz file"
- << endl;
- cout << " -r SR, --sample-rate=SR\t\t set the sample rate SR" << endl;
- cout
- << " -b BS, --buffer-size=SR\t\t set the buffer size (granularity)"
- << endl;
- cout << " -o OS, --oscil-size=OS\t\t set the ADsynth oscil. size"
- << endl;
- cout << " -S , --swap\t\t\t\t swap Left <--> Right" << endl;
- cout << " -D , --dump\t\t\t\t Dumps midi note ON/OFF commands" << endl;
- cout
- << " -U , --no-gui\t\t\t\t Run ZynAddSubFX without user interface"
- << endl;
-#ifdef JACKAUDIOOUT
-#ifdef OSSAUDIOOUT
- cout << " -A , --not-use-jack\t\t\t Use OSS/ALSA instead of JACK"
- << endl;
+ cout << "Usage: zynaddsubfx [OPTION]\n\n"
+ << " -h , --help \t\t\t\t Display command-line help and exit\n"
+ << " -l file, --load=FILE\t\t\t Loads a .xmz file\n"
+ << " -L file, --load-instrument=FILE\t Loads a .xiz file\n"
+ << " -r SR, --sample-rate=SR\t\t Set the sample rate SR\n"
+ << " -b BS, --buffer-size=SR\t\t Set the buffer size (granularity)\n"
+ << " -o OS, --oscil-size=OS\t\t Set the ADsynth oscil. size\n"
+ << " -S , --swap\t\t\t\t Swap Left <--> Right\n"
+ << " -D , --dump\t\t\t\t Dumps midi note ON/OFF commands\n"
+ << " -U , --no-gui\t\t\t\t Run ZynAddSubFX without user interface\n"
+ << " -O , --output\t\t\t\t Set Output Engine\n"
+ << " -I , --input\t\t\t\t Set Input Engine" << endl;
+
+#if OS_WINDOWS
+ cout << "nWARNING: On Windows systems, only short comandline parameters works.\n"
+ << " eg. instead '--buffer-size=512' use '-b 512'" << endl;
#endif
-#endif
-#ifdef OS_WINDOWS
- cout
- <<
- "\nWARNING: On Windows systems, only short comandline parameters works."
- << endl;
- cout << " eg. instead '--buffer-size=512' use '-b 512'" << endl;
-#endif
- cout << '\n' << endl;
return 0;
}
- //---------
-
initprogram();
+#if 0 //TODO update this code
#ifdef USE_LASH
#ifdef ALSAMIDIIN
ALSAMidiIn *alsamidi = dynamic_cast<ALSAMidiIn *>(Midi);
@@ -641,13 +420,14 @@ int main(int argc, char *argv[])
lash->setjackname(JACKgetname());
#endif
#endif
+#endif
- if(strlen(loadfile) > 1) {
- int tmp = master->loadXML(loadfile);
+
+ if(!loadfile.empty()) {
+ int tmp = master->loadXML(loadfile.c_str());
if(tmp < 0) {
- fprintf(stderr,
- "ERROR:Could not load master file %s .\n",
- loadfile);
+ cerr << "ERROR: Could not load master file " << loadfile
+ << "." << endl;
exit(1);
}
else {
@@ -656,11 +436,11 @@ int main(int argc, char *argv[])
}
}
- if(strlen(loadinstrument) > 1) {
+ if(!loadinstrument.empty()) {
int loadtopart = 0;
- int tmp = master->part[loadtopart]->loadXMLinstrument(loadinstrument);
+ int tmp = master->part[loadtopart]->loadXMLinstrument(loadinstrument.c_str());
if(tmp < 0) {
- cerr << "ERROR:Could not load instrument file "
+ cerr << "ERROR: Could not load instrument file "
<< loadinstrument << '.' << endl;
exit(1);
}
@@ -671,25 +451,27 @@ int main(int argc, char *argv[])
}
-#if !(defined(NONEMIDIIN) || defined(WINMIDIIN) || defined(VSTMIDIIN))
- pthread_create(&thr1, NULL, thread1, NULL);
-#endif
+ if(!input.empty()) {
+ if(!sysEngine->setInDefault(input)) {
+ cerr << "There is no input for " << input << endl;
+ exit(1);
+ }
+ cout << input << " selected." << endl;
+ }
+ if(!output.empty()) {
+ if(!sysEngine->setOutDefault(output)) {
+ cerr << "There is no output for " << output << endl;
+ exit(1);
+ }
+ cout << output << " selected." << endl;
+ }
-#ifdef OSSAUDIOOUT
-//!(defined(JACKAUDIOOUT)||defined(JACK_RTAUDIOOUT)||defined(PAAUDIOOUT)||defined(VSTAUDIOOUT))
- if(!usejackit)
- pthread_create(&thr2, NULL, thread2, NULL);
-#endif
+ //Run the Nio system
+ sysEngine->start(); //Drivers start your engines!
+
+#warning remove welcome message when system is out of beta
+ cout << "\nThanks for using the Nio system :)" << endl;
- /*It is not working and I don't know why
- //drop the suid-root permisions
- #if !(defined(JACKAUDIOOUT)||defined(PAAUDIOOUT)||defined(VSTAUDIOOUT)|| (defined (WINMIDIIN)) )
- setuid(getuid());
- seteuid(getuid());
- // setreuid(getuid(),getuid());
- // setregid(getuid(),getuid());
- #endif
- */
#ifndef DISABLE_GUI
if(noui == 0) {
ui = new MasterUI(master, &Pexitprogram);
@@ -697,11 +479,12 @@ int main(int argc, char *argv[])
}
#endif
- pthread_create(&thr4, NULL, thread4, NULL);
+// pthread_create(&thr4, NULL, thread4, NULL);
#ifdef WINMIDIIN
InitWinMidi(master);
#endif
+ //TODO look into a conditional variable here, it seems to match usage
while(Pexitprogram == 0) {
#ifdef OS_LINUX
usleep(100000);