diff --git a/samplebrain/qt/audio_thread.h b/samplebrain/qt/audio_thread.h index 2eefab9..fca8b4b 100644 --- a/samplebrain/qt/audio_thread.h +++ b/samplebrain/qt/audio_thread.h @@ -14,7 +14,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -#include "jellyfish/fluxa/OSC_server.h" +#include "jellyfish/OSC_server.h" #include "process_thread.h" #include "renderer.h" #include "jellyfish/audio.h" diff --git a/samplebrain/qt/feedback.h b/samplebrain/qt/feedback.h index 1d9a347..45adea5 100644 --- a/samplebrain/qt/feedback.h +++ b/samplebrain/qt/feedback.h @@ -16,7 +16,7 @@ #include #include -#include "jellyfish/fluxa/OSC_server.h" +#include "jellyfish/OSC_server.h" #pragma once diff --git a/samplebrain/qt/process_thread.h b/samplebrain/qt/process_thread.h index 02b7af1..c614178 100644 --- a/samplebrain/qt/process_thread.h +++ b/samplebrain/qt/process_thread.h @@ -14,7 +14,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -#include "jellyfish/fluxa/OSC_server.h" +#include "jellyfish/OSC_server.h" #include "brain.h" #include "renderer.h" #include diff --git a/samplebrain/qt/qtmain.cpp b/samplebrain/qt/qtmain.cpp index 01cf308..4a204c3 100644 --- a/samplebrain/qt/qtmain.cpp +++ b/samplebrain/qt/qtmain.cpp @@ -32,6 +32,8 @@ int main( int argc , char *argv[] ){ MainWindow mainWin; mainWin.show(); + cerr<<"Qt version: "< #include #include -#include "jellyfish/core/types.h" +#include "jellyfish/types.h" #include "sound_items.h" @@ -39,7 +39,7 @@ sound_items::sound_item &sound_items::add(QVBoxLayout *container, const string & si.m_container->setSpacing(10); si.m_container->setMargin(0); si.m_container->setContentsMargins(0,0,0,0); - + si.m_enable = new QCheckBox(); si.m_enable->setChecked(enabled); si.m_enable->setStyleSheet(style); diff --git a/samplebrain/src/block.h b/samplebrain/src/block.h index 5bd16ab..88170e3 100644 --- a/samplebrain/src/block.h +++ b/samplebrain/src/block.h @@ -16,13 +16,13 @@ #include #include -#include "jellyfish/fluxa/sample.h" -#include "jellyfish/core/types.h" +#include "jellyfish/sample.h" +#include "jellyfish/types.h" #include "fft.h" #include "mfcc.h" #include "search_params.h" #include "window.h" -#include "jellyfish/core/stream.h" +#include "jellyfish/stream.h" #ifndef BLOCK #define BLOCK diff --git a/samplebrain/src/brain.h b/samplebrain/src/brain.h index 8f37a0a..74bb4bf 100644 --- a/samplebrain/src/brain.h +++ b/samplebrain/src/brain.h @@ -17,8 +17,8 @@ #include #include #include -#include "jellyfish/core/types.h" -#include "jellyfish/fluxa/sample.h" +#include "jellyfish/types.h" +#include "jellyfish/sample.h" #include "block.h" #include "search_params.h" #include "window.h" diff --git a/samplebrain/src/fft.h b/samplebrain/src/fft.h index 18265b7..a9e1f28 100644 --- a/samplebrain/src/fft.h +++ b/samplebrain/src/fft.h @@ -15,7 +15,7 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include -#include +#include #ifndef SPIRALCORE_FFT #define SPIRALCORE_FFT diff --git a/samplebrain/src/jellyfish/OSC_server.cpp b/samplebrain/src/jellyfish/OSC_server.cpp new file mode 100644 index 0000000..cfd1590 --- /dev/null +++ b/samplebrain/src/jellyfish/OSC_server.cpp @@ -0,0 +1,147 @@ +// copyright (C) 2004 david griffiths +// +// this program 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 2 of the license, or +// (at your option) any later version. +// +// 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 for more details. +// +// you should have received a copy of the GNU general public license +// along with this program; if not, write to the free software +// foundation, inc., 59 temple place - suite 330, boston, MA 02111-1307, USA. + +#include +#include +#include +#include +#include + +#include "OSC_server.h" + +using namespace std; + +#ifdef NO_LO_ARG_SIZE_DECL +extern "C" { + size_t lo_arg_size (lo_type type, void * data); +}; +#endif + +OSC_server::OSC_server(const string &port) : +m_port(port), +m_exit(false), +m_command_ring_buffer(262144) +{ + //cerr<<"using port: ["<COMMAND_DATA_SIZE) + { + cerr<<"osc data too big for ringbuffer command"<COMMAND_DATA_SIZE) + { + cerr<<"osc data too big for ringbuffer command"<s); + + if (pos+size+1>COMMAND_DATA_SIZE) + { + cerr<<"osc data too big for ringbuffer command"<s,size); + newdata[pos+size]='\0'; + pos+=size+1; + } + break; + default: + { + cerr<<"unsupported type: "<m_command_ring_buffer.send(command)) + { + //cerr<<"OSC_server - ringbuffer full!"< +// +// this program 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 2 of the license, or +// (at your option) any later version. +// +// 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 for more details. +// +// you should have received a copy of the GNU general public license +// along with this program; if not, write to the free software +// foundation, inc., 59 temple place - suite 330, boston, MA 02111-1307, USA. + +#ifndef OSC_SERVER +#define OSC_SERVER + +#include +#include +#include "command_ring_buffer.h" + +class OSC_server +{ +public: + OSC_server(const std::string &port); + ~OSC_server(); + + void run(); + bool get(command_ring_buffer::command& command) { return m_command_ring_buffer.get(command);} + +private: + static int default_handler(const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data); + static void error_handler(int num, const char *m, const char *path); + + lo_server_thread m_server; + std::string m_port; + bool m_exit; + command_ring_buffer m_command_ring_buffer; +}; + +#endif diff --git a/samplebrain/src/jellyfish/allocator.cpp b/samplebrain/src/jellyfish/allocator.cpp new file mode 100644 index 0000000..df78b31 --- /dev/null +++ b/samplebrain/src/jellyfish/allocator.cpp @@ -0,0 +1,64 @@ +// Copyright (C) 2003 David Griffiths +// +// This program 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 2 of the License, or +// (at your option) any later version. +// +// 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 for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "allocator.h" + +char *malloc_allocator::anew(unsigned int size) +{ + return new char[size]; +} + +void malloc_allocator::adelete(char *mem) +{ + delete[] mem; +} + +/////////////////////////////////////////////////////////// + +realtime_allocator::realtime_allocator(unsigned int size) : +m_position(0), +m_size(size) +{ + m_buffer = new char[m_size]; +} + +void realtime_allocator::reset() +{ + m_position=0; +} + +char *realtime_allocator::anew(unsigned int size) +{ + //cerr<<"new "<m_size) + { +// cerr<<"out of realtime buffer mem, here we go!!! :("< +// +// This program 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 2 of the License, or +// (at your option) any later version. +// +// 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 for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef ALLOCATOR +#define ALLOCATOR + +using namespace std; + +class base_allocator +{ +public: + virtual ~base_allocator() {} + virtual void reset() {} + virtual char *anew(unsigned int size)=0; + virtual void adelete(char *mem)=0; +}; + +/////////////////////////////////////////////////// + +class malloc_allocator : public base_allocator +{ +public: + malloc_allocator() {} + virtual ~malloc_allocator() {} + + virtual char *anew(unsigned int size); + virtual void adelete(char *mem); + +protected: +}; + +///////////////////////////////////////////////////// + +class realtime_allocator : public base_allocator +{ +public: + realtime_allocator(unsigned int size); + virtual ~realtime_allocator() {} + + virtual void reset(); + virtual char *anew(unsigned int size); + virtual void adelete(char *mem); + +protected: + + char *m_buffer; + unsigned int m_position; + unsigned int m_size; +}; + +#endif diff --git a/samplebrain/src/jellyfish/audio.cpp b/samplebrain/src/jellyfish/audio.cpp new file mode 100644 index 0000000..2cebad4 --- /dev/null +++ b/samplebrain/src/jellyfish/audio.cpp @@ -0,0 +1,102 @@ +// Copyright (C) 2015 David Griffiths +// +// This program 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 2 of the License, or +// (at your option) any later version. +// +// 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 for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include +#include "audio.h" +#include + +using namespace std; +using namespace spiralcore; + +audio_device::audio_device(const string &clientname, u32 samplerate, u32 buffer_size) : + left_out(buffer_size), + right_out(buffer_size), + left_in(buffer_size), + right_in(buffer_size), + m_recording(false), + m_record_filename("") +{ + portaudio_client::device_options opt; + opt.buffer_size = buffer_size; + opt.num_buffers = 2; + opt.samplerate = samplerate; + opt.in_channels = 2; + opt.out_channels = 2; + + m_client.attach(clientname,opt); + m_client.set_outputs(left_out.get_buffer(), right_out.get_buffer()); + m_client.set_inputs(left_in.get_non_const_buffer(), right_in.get_non_const_buffer()); + +} + +void audio_device::save_sample(const string &filename, const sample s) { + SF_INFO sfinfo; + sfinfo.format=SF_FORMAT_WAV | SF_FORMAT_FLOAT; + sfinfo.frames=s.get_length(); + sfinfo.samplerate=44100; + sfinfo.channels=1; + sfinfo.sections=1; + sfinfo.seekable=0; + SNDFILE* f=sf_open(filename.c_str(), SFM_WRITE, &sfinfo); + if (!f) cerr<<"couldn't open "<left_out.zero(); + a->right_out.zero(); + a->m_graph->process(size, a->left_out, a->right_out); + a->maybe_record(); +#endif +} +#endif + +void audio_device::start_graph(graph *graph) { +#ifndef DONT_USE_FLUXA_GRAPH + m_graph = graph; + m_client.set_callback(run_graph,this); +#endif +} diff --git a/samplebrain/src/jellyfish/audio.h b/samplebrain/src/jellyfish/audio.h new file mode 100644 index 0000000..9a73582 --- /dev/null +++ b/samplebrain/src/jellyfish/audio.h @@ -0,0 +1,56 @@ +// Copyright (C) 2015 David Griffiths +// +// This program 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 2 of the License, or +// (at your option) any later version. +// +// 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 for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "types.h" +#include "sample.h" +#include "portaudio_client.h" + +#include + +class graph; + +namespace spiralcore { + +class audio_device { +public: + audio_device(const string &clientname, u32 samplerate, u32 buffer_size); + + void start_graph(graph *graph); + + void start_recording(std::string filename); + void stop_recording(); + void maybe_record(); + + sample left_out; + sample right_out; + sample left_in; + sample right_in; + graph *m_graph; + + portaudio_client m_client; + + static void save_sample(const std::string &filename, const sample s); + +private: + bool m_recording; + std::string m_record_filename; + sample m_record_buffer_left; + sample m_record_buffer_right; + u32 m_record_counter; + +}; + +} diff --git a/samplebrain/src/jellyfish/command_ring_buffer.cpp b/samplebrain/src/jellyfish/command_ring_buffer.cpp new file mode 100644 index 0000000..1d4f547 --- /dev/null +++ b/samplebrain/src/jellyfish/command_ring_buffer.cpp @@ -0,0 +1,91 @@ +// copyright (C) 2004 david griffiths +// +// this program 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 2 of the license, or +// (at your option) any later version. +// +// 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 for more details. +// +// you should have received a copy of the GNU general public license +// along with this program; if not, write to the free software +// foundation, inc., 59 temple place - suite 330, boston, MA 02111-1307, USA. + +#include "command_ring_buffer.h" +#include +#include + +using namespace std; + +command_ring_buffer::command::command(const char *name, const char *types, const char *data, unsigned int datasize) +{ + strcpy(m_name,name); + strcpy(m_types,types); + // already checking datasize fits in OSCserver.cpp + memcpy(m_data,data,datasize); + + m_num_args=strlen(types); + + // figure out the offsets into the data to use later + int pos=0; + for(unsigned int i=0; i +// +// this program 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 2 of the license, or +// (at your option) any later version. +// +// 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 for more details. +// +// you should have received a copy of the GNU general public license +// along with this program; if not, write to the free software +// foundation, inc., 59 temple place - suite 330, boston, MA 02111-1307, USA. + +#include "ring_buffer.h" + +#ifndef COMMAND_RING_BUFFER +#define COMMAND_RING_BUFFER + +static const unsigned int COMMAND_DATA_SIZE = 128; + +class command_ring_buffer : public ring_buffer +{ +public: + command_ring_buffer(unsigned int size); + ~command_ring_buffer(); + + class command + { + public: + command() {} + command(const char *name, const char *types, const char *data, unsigned int datasize); + ~command() {} + + int get_int(unsigned int index); + float get_float(unsigned int index); + char *get_string(unsigned int index); + // unlike the string - ownership of the blob is yours + // you must delete it when you're done... + char *get_blob(unsigned int index); + unsigned int size() { return m_num_args; } + char m_name[256]; + char m_types[64]; + + private: + char m_data[COMMAND_DATA_SIZE]; + int m_offsets[64]; + unsigned int m_num_args; + + }; + + bool send(const command& command); + bool get(command& command); + +private: + command m_current; +}; + +#endif diff --git a/samplebrain/src/jellyfish/fixed.h b/samplebrain/src/jellyfish/fixed.h new file mode 100644 index 0000000..212e01a --- /dev/null +++ b/samplebrain/src/jellyfish/fixed.h @@ -0,0 +1,191 @@ +/* +Copyright (c) 2006 Henry Strickland & Ryan Seto + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + + (* http://www.opensource.org/licenses/mit-license.php *) +*/ + +#ifndef FLX_FIXED +#define FLX_FIXED + +namespace spiralcore { + +class Fixed { + +private: +public: +#ifdef _EE + short g; // the guts + const static int BP= 8; // how many low bits are right of Binary Point +#else + int g; // the guts + const static int BP= 16; // how many low bits are right of Binary Point +#endif + const static int BP2= BP*2; // how many low bits are right of Binary Point + const static int BPhalf= BP/2; // how many low bits are right of Binary Point + + static double STEP() { return 1.0 / (1<>BP; } + operator long() const { return g>>BP; } + + Fixed operator +() const { return Fixed(RAW,g); } + Fixed operator -() const { return Fixed(RAW,-g); } + + Fixed operator +(const Fixed& a) const { return Fixed(RAW, g + a.g); } + Fixed operator -(const Fixed& a) const { return Fixed(RAW, g - a.g); } +#if 1 + // more acurate, using long long + Fixed operator *(const Fixed& a) const { return Fixed(RAW, (int)( ((long long)g * (long long)a.g ) >> BP)); } +#else + // faster, but with only half as many bits right of binary point + Fixed operator *(const Fixed& a) const { return Fixed(RAW, (g>>BPhalf) * (a.g>>BPhalf) ); } +#endif + Fixed operator /(const Fixed& a) const { return Fixed(RAW, int( (((long long)g << BP2) / (long long)(a.g)) >> BP) ); } + + Fixed operator +(float a) const { return Fixed(RAW, g + Fixed(a).g); } + Fixed operator -(float a) const { return Fixed(RAW, g - Fixed(a).g); } + Fixed operator *(float a) const { return Fixed(RAW, (g>>BPhalf) * (Fixed(a).g>>BPhalf) ); } + Fixed operator /(float a) const { return Fixed(RAW, int( (((long long)g << BP2) / (long long)(Fixed(a).g)) >> BP) ); } + + Fixed operator +(double a) const { return Fixed(RAW, g + Fixed(a).g); } + Fixed operator -(double a) const { return Fixed(RAW, g - Fixed(a).g); } + Fixed operator *(double a) const { return Fixed(RAW, (g>>BPhalf) * (Fixed(a).g>>BPhalf) ); } + Fixed operator /(double a) const { return Fixed(RAW, int( (((long long)g << BP2) / (long long)(Fixed(a).g)) >> BP) ); } + + Fixed& operator +=(Fixed a) { return *this = *this + a; return *this; } + Fixed& operator -=(Fixed a) { return *this = *this - a; return *this; } + Fixed& operator *=(Fixed a) { return *this = *this * a; return *this; } + Fixed& operator /=(Fixed a) { return *this = *this / a; return *this; } + + Fixed& operator +=(int a) { return *this = *this + (Fixed)a; return *this; } + Fixed& operator -=(int a) { return *this = *this - (Fixed)a; return *this; } + Fixed& operator *=(int a) { return *this = *this * (Fixed)a; return *this; } + Fixed& operator /=(int a) { return *this = *this / (Fixed)a; return *this; } + + Fixed& operator +=(long a) { return *this = *this + (Fixed)a; return *this; } + Fixed& operator -=(long a) { return *this = *this - (Fixed)a; return *this; } + Fixed& operator *=(long a) { return *this = *this * (Fixed)a; return *this; } + Fixed& operator /=(long a) { return *this = *this / (Fixed)a; return *this; } + + Fixed& operator +=(float a) { return *this = *this + a; return *this; } + Fixed& operator -=(float a) { return *this = *this - a; return *this; } + Fixed& operator *=(float a) { return *this = *this * a; return *this; } + Fixed& operator /=(float a) { return *this = *this / a; return *this; } + + Fixed& operator +=(double a) { return *this = *this + a; return *this; } + Fixed& operator -=(double a) { return *this = *this - a; return *this; } + Fixed& operator *=(double a) { return *this = *this * a; return *this; } + Fixed& operator /=(double a) { return *this = *this / a; return *this; } + + bool operator ==(const Fixed& a) const { return g == a.g; } + bool operator !=(const Fixed& a) const { return g != a.g; } + bool operator <=(const Fixed& a) const { return g <= a.g; } + bool operator >=(const Fixed& a) const { return g >= a.g; } + bool operator <(const Fixed& a) const { return g < a.g; } + bool operator >(const Fixed& a) const { return g > a.g; } + + bool operator ==(float a) const { return g == Fixed(a).g; } + bool operator !=(float a) const { return g != Fixed(a).g; } + bool operator <=(float a) const { return g <= Fixed(a).g; } + bool operator >=(float a) const { return g >= Fixed(a).g; } + bool operator <(float a) const { return g < Fixed(a).g; } + bool operator >(float a) const { return g > Fixed(a).g; } + + bool operator ==(double a) const { return g == Fixed(a).g; } + bool operator !=(double a) const { return g != Fixed(a).g; } + bool operator <=(double a) const { return g <= Fixed(a).g; } + bool operator >=(double a) const { return g >= Fixed(a).g; } + bool operator <(double a) const { return g < Fixed(a).g; } + bool operator >(double a) const { return g > Fixed(a).g; } +}; + +inline Fixed operator +(float a, const Fixed& b) { return Fixed(a)+b; } +inline Fixed operator -(float a, const Fixed& b) { return Fixed(a)-b; } +inline Fixed operator *(float a, const Fixed& b) { return Fixed(a)*b; } +inline Fixed operator /(float a, const Fixed& b) { return Fixed(a)/b; } + +inline bool operator ==(float a, const Fixed& b) { return Fixed(a) == b; } +inline bool operator !=(float a, const Fixed& b) { return Fixed(a) != b; } +inline bool operator <=(float a, const Fixed& b) { return Fixed(a) <= b; } +inline bool operator >=(float a, const Fixed& b) { return Fixed(a) >= b; } +inline bool operator <(float a, const Fixed& b) { return Fixed(a) < b; } +inline bool operator >(float a, const Fixed& b) { return Fixed(a) > b; } + + + +inline Fixed operator +(double a, const Fixed& b) { return Fixed(a)+b; } +inline Fixed operator -(double a, const Fixed& b) { return Fixed(a)-b; } +inline Fixed operator *(double a, const Fixed& b) { return Fixed(a)*b; } +inline Fixed operator /(double a, const Fixed& b) { return Fixed(a)/b; } + +inline bool operator ==(double a, const Fixed& b) { return Fixed(a) == b; } +inline bool operator !=(double a, const Fixed& b) { return Fixed(a) != b; } +inline bool operator <=(double a, const Fixed& b) { return Fixed(a) <= b; } +inline bool operator >=(double a, const Fixed& b) { return Fixed(a) >= b; } +inline bool operator <(double a, const Fixed& b) { return Fixed(a) < b; } +inline bool operator >(double a, const Fixed& b) { return Fixed(a) > b; } + + +inline int& operator +=(int& a, const Fixed& b) { a = (Fixed)a + b; return a; } +inline int& operator -=(int& a, const Fixed& b) { a = (Fixed)a - b; return a; } +inline int& operator *=(int& a, const Fixed& b) { a = (Fixed)a * b; return a; } +inline int& operator /=(int& a, const Fixed& b) { a = (Fixed)a / b; return a; } + +inline long& operator +=(long& a, const Fixed& b) { a = (Fixed)a + b; return a; } +inline long& operator -=(long& a, const Fixed& b) { a = (Fixed)a - b; return a; } +inline long& operator *=(long& a, const Fixed& b) { a = (Fixed)a * b; return a; } +inline long& operator /=(long& a, const Fixed& b) { a = (Fixed)a / b; return a; } + +inline float& operator +=(float& a, const Fixed& b) { a = a + b; return a; } +inline float& operator -=(float& a, const Fixed& b) { a = a - b; return a; } +inline float& operator *=(float& a, const Fixed& b) { a = a * b; return a; } +inline float& operator /=(float& a, const Fixed& b) { a = a / b; return a; } + +inline double& operator +=(double& a, const Fixed& b) { a = a + b; return a; } +inline double& operator -=(double& a, const Fixed& b) { a = a - b; return a; } +inline double& operator *=(double& a, const Fixed& b) { a = a * b; return a; } +inline double& operator /=(double& a, const Fixed& b) { a = a / b; return a; } + +} + +#endif diff --git a/samplebrain/src/jellyfish/portaudio_client.cpp b/samplebrain/src/jellyfish/portaudio_client.cpp new file mode 100644 index 0000000..4f5f914 --- /dev/null +++ b/samplebrain/src/jellyfish/portaudio_client.cpp @@ -0,0 +1,164 @@ +// copyright (C) 2003 david griffiths +// +// this program 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 2 of the license, or +// (at your option) any later version. +// +// 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 for more details. +// +// you should have received a copy of the GNU general public license +// along with this program; if not, write to the free software +// foundation, inc., 59 temple place - suite 330, boston, MA 02111-1307, USA. + +#include +#include + +#include "portaudio_client.h" + +bool portaudio_client::m_attached = false; +long unsigned int portaudio_client::m_buffer_size = 0; +long unsigned int portaudio_client::m_sample_rate = 44100; +void (*portaudio_client::run_callback)(void*, unsigned int buf_size)=NULL; +void *portaudio_client::run_context = NULL; +const float *portaudio_client::m_right_data=NULL; +const float *portaudio_client::m_left_data=NULL; +float *portaudio_client::m_right_in_data=NULL; +float *portaudio_client::m_left_in_data=NULL; + +/////////////////////////////////////////////////////// + +portaudio_client::portaudio_client() +{ +} + +///////////////////////////////////////////////////////////////////////////////////////////// + +portaudio_client::~portaudio_client() +{ + detach(); +} + +///////////////////////////////////////////////////////////////////////////////////////////// + +bool portaudio_client::attach(const string &client_name, const device_options &dopt) +{ + if (m_attached) return true; + + PaError err; + err = Pa_Initialize(); + if( err != paNoError ) + { + cerr<<"could not init portaudio_client"<defaultLowOutputLatency; + output_parameters.hostApiSpecificStreamInfo = NULL; + + PaStreamParameters input_parameters; + input_parameters.device = Pa_GetDefaultInputDevice(); /* default output device */ + if (input_parameters.device == paNoDevice) { + cerr<<"error: no default input device."<defaultLowInputLatency; + input_parameters.hostApiSpecificStreamInfo = NULL; + + PaStream *stream; + + err = Pa_OpenStream( + &stream, + NULL, //&input_parameters, + &output_parameters, + dopt.samplerate, + dopt.buffer_size, + paClipOff, + process, + NULL); + + if( err != paNoError ) + { + cerr<<"could not attach portaudio_client: "< +// +// this program 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 2 of the license, or +// (at your option) any later version. +// +// 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 for more details. +// +// you should have received a copy of the GNU general public license +// along with this program; if not, write to the free software +// foundation, inc., 59 temple place - suite 330, boston, MA 02111-1307, USA. + +#include +#include +#include +#include +#include + +using namespace std; + +#ifndef PA_CLIENT +#define PA_CLIENT + +class portaudio_client +{ +public: + portaudio_client(); + ~portaudio_client(); + + class device_options + { + public: + enum type {READ,WRITE,READWRITE}; + unsigned int buffer_size; + unsigned int num_buffers; + unsigned int samplerate; + unsigned int in_channels; + unsigned int out_channels; + }; + + bool attach(const string &client_name, const device_options &dopt); + void detach(); + bool is_attached() { return m_attached; } + void set_callback(void(*run)(void*, unsigned int),void *context) { run_callback=run; run_context=context; } + void set_outputs(const float *l, const float *r) { m_left_data=l; m_right_data=r; } + void set_inputs(float *l, float *r) { m_left_in_data=l; m_right_in_data=r; } + +protected: + + static int process(const void *input_buffer, void *output_buffer, + unsigned long frames_per_buffer, + const PaStreamCallbackTimeInfo* time_info, + PaStreamCallbackFlags status_flags, + void *user_data); + +private: + + static long unsigned int m_buffer_size; + static long unsigned int m_sample_rate; + static bool m_attached; + + static const float *m_right_data; + static const float *m_left_data; + static float *m_right_in_data; + static float *m_left_in_data; + + static void(*run_callback)(void *, unsigned int); + static void *run_context; +}; + +#endif diff --git a/samplebrain/src/jellyfish/ring_buffer.cpp b/samplebrain/src/jellyfish/ring_buffer.cpp new file mode 100644 index 0000000..082d404 --- /dev/null +++ b/samplebrain/src/jellyfish/ring_buffer.cpp @@ -0,0 +1,129 @@ +// copyright (C) 2004 david griffiths +// +// this program 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 2 of the license, or +// (at your option) any later version. +// +// 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 for more details. +// +// you should have received a copy of the GNU general public license +// along with this program; if not, write to the free software +// foundation, inc., 59 temple place - suite 330, boston, MA 02111-1307, USA. + +#include +#include +#include +#include +#include "ring_buffer.h" + +using namespace std; + +ring_buffer::ring_buffer(unsigned int size): +m_read_pos(0), +m_write_pos(0), +m_size(size), +m_size_mask(size-1), +m_buffer(NULL) +{ + m_buffer = new char[m_size]; + memset(m_buffer,'Z',m_size); +} + +ring_buffer::~ring_buffer() +{ + delete[] m_buffer; +} + +bool ring_buffer::write(char *src, unsigned int size) +{ + //cerr<<"write pos: "<m_size) return false; + + if (size read) return (read - write + m_size) & (m_size_mask - 1); + if (write < read) return (read - write) - 1; + return m_size - 1; +} + +unsigned int ring_buffer::read_space() +{ + unsigned int read = m_read_pos; + unsigned int write = m_write_pos; + + if (write > read) return write - read; + else return (write - read + m_size) & m_size_mask; +} diff --git a/samplebrain/src/jellyfish/ring_buffer.h b/samplebrain/src/jellyfish/ring_buffer.h new file mode 100644 index 0000000..0dbcddb --- /dev/null +++ b/samplebrain/src/jellyfish/ring_buffer.h @@ -0,0 +1,46 @@ +// copyright (C) 2004 david griffiths +// +// this program 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 2 of the license, or +// (at your option) any later version. +// +// 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 for more details. +// +// you should have received a copy of the GNU general public license +// along with this program; if not, write to the free software +// foundation, inc., 59 temple place - suite 330, boston, MA 02111-1307, USA. + +// ringbuffer for processing commands between asycronous threads, either may be +// realtime and non blocking, so all code should be realtime capable + +#ifndef RING_BUFFER +#define RING_BUFFER + +class ring_buffer +{ +public: + ring_buffer(unsigned int size); + ~ring_buffer(); + + //bool lock(); + //bool unlock(); + bool write(char *src, unsigned int size); + bool read(char *dest, unsigned int size); + void dump(); + +private: + unsigned int write_space(); + unsigned int read_space(); + + unsigned int m_read_pos; + unsigned int m_write_pos; + unsigned int m_size; + unsigned int m_size_mask; + char *m_buffer; +}; + +#endif diff --git a/samplebrain/src/jellyfish/sample.cpp b/samplebrain/src/jellyfish/sample.cpp new file mode 100644 index 0000000..1c03326 --- /dev/null +++ b/samplebrain/src/jellyfish/sample.cpp @@ -0,0 +1,371 @@ +// _copyright (_c) 2003 _david _griffiths +// +// _this program is free software; you can redistribute it and/or modify +// it under the terms of the _g_n_u _general _public _license as published by +// the _free _software _foundation; either version 2 of the _license, or +// (at your option) any later version. +// +// _this program is distributed in the hope that it will be useful, +// but _w_i_t_h_o_u_t _a_n_y _w_a_r_r_a_n_t_y; without even the implied warranty of +// _m_e_r_c_h_a_n_t_a_b_i_l_i_t_y or _f_i_t_n_e_s_s _f_o_r _a _p_a_r_t_i_c_u_l_a_r _p_u_r_p_o_s_e. _see the +// _g_n_u _general _public _license for more details. +// +// _you should have received a copy of the _g_n_u _general _public _license +// along with this program; if not, write to the _free _software +// _foundation, _inc., 59 _temple _place - _suite 330, _boston, _m_a 02111-1307, _u_s_a. + +#include +#include "types.h" +#include "sample.h" + +using namespace spiralcore; + +base_allocator *sample::m_allocator = new malloc_allocator(); + +sample::sample(unsigned int len) : +m_data(NULL), +m_length(0) +{ + if (len) + { + allocate(len); + } +} + + +sample::sample(const sample &rhs): +m_data(NULL), +m_length(0) +{ + *this=rhs; +} + + +sample::sample(const audio_type *s, unsigned int len): +m_data(NULL), +m_length(0) +{ + assert(s); + allocate(len); + memcpy(m_data,s,get_length_in_bytes()); +} + + +sample::~sample() +{ + clear(); +} + + + +bool sample::allocate(unsigned int size) +{ + clear(); + + m_data = (audio_type*) m_allocator->anew(size*sizeof(audio_type)); + m_length=size; + + memset(m_data,0,get_length_in_bytes()); + + return (m_data); +} + +void sample::clear() +{ + if (m_data) + { + m_allocator->adelete((char*)m_data); + m_length=0; + m_data=NULL; + } +} + +void sample::zero() +{ + memset(m_data,0,get_length_in_bytes()); +} + +void sample::set(audio_type val) +{ + for (unsigned int n=0; nanew(new_len*sizeof(audio_type)); + unsigned int from_pos=0, to_pos=0, temp_buf_pos=0; + + while (from_pos<=get_length()) + { + if (from_pos==pos) + { + for (temp_buf_pos=0; temp_buf_posget_length()) to_pos=0; + to_pos++; + } +} + +void sample::mul_mix(const sample &s, unsigned int pos, float m) +{ + // do some checking + assert(posget_length()) to_pos=0; + to_pos++; + } +} + +void sample::mul_clip_mix(const sample &s, float m) +{ + unsigned int to_pos=0; + + for (unsigned int from_pos=0; from_posm) t=m; + else if (t<-m) t=-m; + + m_data[to_pos]=m_data[to_pos]+t; + + if (to_pos>get_length()) to_pos=0; + to_pos++; + } +} + +void sample::remove(unsigned int start, unsigned int end) +{ + // do some checking + assert(endget_length()) end=get_length(); + // unsigned, impossible + //if (start<0) start=0; + + // calc lengths and allocate memory + unsigned int cut_len = end - start; + // has to be granulated by the buffer size + + unsigned int new_len = get_length()-cut_len; + + audio_type *temp_buf = (audio_type*) m_allocator->anew(new_len*sizeof(audio_type)); + + unsigned int to_pos=0; + + for (unsigned int from_pos=0; from_posend) + { + temp_buf[to_pos]=m_data[from_pos]; + to_pos++; + // check the position is in range of the calculated length + assert(to_pos<=new_len); + } + } + + clear(); + m_data=temp_buf; + m_length=new_len; +} + +void sample::reverse(unsigned int start, unsigned int end) +{ + // do some checking + assert(endget_length()) end=get_length(); + + unsigned int new_len = end-start; + audio_type *temp_buf = (audio_type*) m_allocator->anew(new_len*sizeof(audio_type)); + unsigned int to_pos=0; + unsigned int from_pos=0; + + // get the reversed sample + for (from_pos=end; from_pos>start; from_pos--) + { + temp_buf[to_pos]=m_data[from_pos]; + to_pos++; + assert(to_pos<=new_len); + } + + from_pos=0; + + // overwrite back into place + for (to_pos=start; to_posanew(length*sizeof(audio_type)); + unsigned int to_pos=0; + unsigned int from_pos=dist; + + // unsigned - impossible + //if (from_pos<0) from_pos+=length; + if (from_pos>length) from_pos-=length; + + // get the offset sample + for (to_pos=0; to_pos=length) from_pos=0; + } + + clear(); + m_data=temp_buf; + m_length=length; +} + +void sample::get_region(sample &s, unsigned int start, unsigned int end) const +{ + // do some checking + assert(endanew(new_length*sizeof(audio_type)); + + for(unsigned int n=0; n0 && new_length<=get_length()); + + audio_type *temp = (audio_type*) m_allocator->anew(new_length*sizeof(audio_type)); + + for(unsigned int n=0; n(&s); + if (pos!=NULL) { + ofstream &os = *pos; + size_t len = sa.m_length; + os.write((char*)&len,sizeof(size_t)); + os.write((char*)sa.m_data,sa.m_length*sizeof(audio_type)); + return os; + } + else + { + ifstream *pis=dynamic_cast(&s); + assert(pis!=NULL); + ifstream &is = *pis; + size_t len=0; + is.read((char *)&len,sizeof(size_t)); + float *data = new float[len]; + is.read((char*)data,len*sizeof(audio_type)); + sa.m_data = data; + sa.m_length = len; + return is; + } +} diff --git a/samplebrain/src/jellyfish/sample.h b/samplebrain/src/jellyfish/sample.h new file mode 100644 index 0000000..5da6a79 --- /dev/null +++ b/samplebrain/src/jellyfish/sample.h @@ -0,0 +1,133 @@ +// Copyright (C) 2003 Dave Griffiths +// +// This program 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 2 of the License, or +// (at your option) any later version. +// +// 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 for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef SAMPLE +#define SAMPLE + +#include +#include +#include +#include +#include +#include + +#include "types.h" +#include "allocator.h" +#include "stream.h" + +namespace spiralcore +{ +//#define DEBUG + +inline float linear(float bot,float top,float pos,float val1,float val2) +{ + float t=(pos-bot)/(top-bot); + return val1*t + val2*(1.0f-t); +} + +inline bool feq(float a, float b, float tol=0.00001) +{ + return (a>b-tol && a +#include "stream.h" +#include +#include "types.h" + +using namespace spiralcore; +using namespace std; + +template<>ios &spiralcore::operator||(ios &s, string &v) { + ofstream *pos=dynamic_cast(&s); + if (pos!=NULL) { + ofstream &os = *pos; + size_t len = v.length(); + os.write((char *)&len,sizeof(size_t)); + os.write((char*)(v.c_str()),v.length()); + return os; + } + else + { + ifstream *pis=dynamic_cast(&s); + assert(pis!=NULL); + ifstream &is = *pis; + size_t len=0; + is.read((char *)&len,sizeof(size_t)); + if (len>0) { + char *str = new char[len+1]; + is.read(str,len); + str[len]='\0'; + v = string(str); + delete[] str; + } + else { + //v=string(""); + } + return is; + } +} + + +/*ios &operator||(ios &s, vector &v) { + ofstream *pos=dynamic_cast(&s); + if (pos!=NULL) { + ofstream &os = *pos; + size_t len = v.length(); + os.write((char *)&len,sizeof(size_t)); + return os.write((char*)(&v[0]),v.length()*sizeof(U)); + } + else + { + ifstream *pis=dynamic_cast(&s); + assert(pis); + ifstream &is = *pis; + size_t len=0; + is.read((char *)&len,sizeof(size_t)); + v.reserve(len); + is.read((char*)&v[0],len); + return is; + } + + + }*/ +/* +templateios &operator||(ios &s, vector &v) { + ofstream *pos=dynamic_cast(&s); + if (pos!=NULL) { + ofstream &os = *pos; + size_t len = v.length(); + for (size_t i=0; i(&s); + assert(pis); + ifstream &is = *pis; + size_t len=0; + is.read((char *)&len,sizeof(size_t)); + v.reserve(len); + for (size_t i=0; i o_f; + + for(s32 i=0; i i_f; +// i_e = stream_array(ifs,i_e,size); + stream_vector(ifs,i_f); + + ifs.close(); + assert(i_a==100); + assert(i_b>0.199f && i_b<0.20001); + assert(i_c=="hello"); + assert(i_d=="there"); + + for(s32 i=0; i +#include +#include +#include +#include +#include + +#pragma once + +namespace spiralcore { + +// hack to do both stream directions in one function +// saw this years ago at computer artworks, not seen it since... + +templatestd::ios &operator||(std::ios &s, T &v) { + std::ofstream *pos=dynamic_cast(&s); + if (pos!=NULL) { + std::ofstream &os = *pos; + os.write((char*)(&v),sizeof(T)); + return os; + } + else + { + std::ifstream *pis=dynamic_cast(&s); + assert(pis); + std::ifstream &is = *pis; + is.read((char *)(&v),sizeof(T)); + return is; + } +} + +template<>std::ios &operator||(std::ios &s, std::string &v); + +/* +templateT *stream_array(std::ios &s, T *v, U &len) { + std::ofstream *pos=dynamic_cast(&s); + if (pos!=NULL) { + std::ofstream &os = *pos; + os||len; + os.write((char*)v,sizeof(T)*len); + return v; + } else { + std::ifstream *pis=dynamic_cast(&s); + assert(pis); + std::ifstream &is = *pis; + is||len; + if (v!=NULL) delete[] v; + T* t = new T[len]; + is.read((char *)t,sizeof(T)*len); + return t; + } +} +*/ + +templatestd::ios &stream_vector(std::ios &s, std::vector &v) { + std::ofstream *pos=dynamic_cast(&s); + if (pos!=NULL) { + std::ofstream &os = *pos; + size_t len = v.size(); + os||len; + for (size_t i=0; i(&s); + assert(pis); + std::ifstream &is = *pis; + size_t len=0; + is||len; + //v.reserve(len); + v.clear(); + for (size_t i=0; istd::ios &skip_vector(std::ifstream &is) { + size_t len=0; + is||len; + for (size_t i=0; istd::ios &stream_list(std::ios &s, std::list &v) { + std::ofstream *pos=dynamic_cast(&s); + if (pos!=NULL) { + std::ofstream &os = *pos; + size_t len = v.size(); + os||len; + for (typename std::list::iterator i=v.begin(); i!=v.end(); ++i) { + os||*i; + } + return os; + } + else + { + std::ifstream *pis=dynamic_cast(&s); + assert(pis); + std::ifstream &is = *pis; + size_t len=0; + is||len; + for (size_t i=0; istd::ios &skip_list(std::istream &is) { + size_t len=0; + is||len; + for (size_t i=0; i + +// autoconf can tell us if we are on Pi +// only support Pi and linux for the moment +#ifdef HAVE_LIBBCM_HOST +#define FLX_RPI +#endif + +#ifndef FLX_RPI +#define FLX_LINUX +#endif + +#ifndef _EE +typedef unsigned char u8; +typedef char s8; +typedef unsigned short u16; +typedef short s16; +typedef unsigned int u32; +typedef int s32; +typedef unsigned long long int u64; +typedef long long int s64; +typedef float f32; +typedef spiralcore::Fixed x32; +#endif + +// get namespace bb everywhere, for differentiating from +// std::list where both are needed :/ +//#include "list.h" +//using namespace bb; + +typedef f32 audio_type; + +#ifdef FLX_LINUX +//-Linux/RPI--------------------------- +// use the fixed point version here +//#define flx_real x32 +#define flx_real float + +#else +#ifdef _EE +//-PS2---------------------------------- +#define flx_real float +#define sqrt sqrtf +#define isascii( c ) (!((c) & 0x80)) + +#else +//-Android------------------------------ +#define flx_real x32 +#endif +#endif + +#endif // FLX_TYPES diff --git a/samplebrain/src/mfcc.h b/samplebrain/src/mfcc.h index cc09dba..ab2a69b 100644 --- a/samplebrain/src/mfcc.h +++ b/samplebrain/src/mfcc.h @@ -20,7 +20,7 @@ #include "aquila/global.h" //#include "aquila/transform/FftFactory.h" -#include +#include #include #include diff --git a/samplebrain/src/renderer.h b/samplebrain/src/renderer.h index 767cfd1..de04c80 100644 --- a/samplebrain/src/renderer.h +++ b/samplebrain/src/renderer.h @@ -15,7 +15,7 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include -#include +#include #include "brain.h" #ifndef SB_RENDERER diff --git a/samplebrain/src/search_params.h b/samplebrain/src/search_params.h index a9e3fd2..05e4e7b 100644 --- a/samplebrain/src/search_params.h +++ b/samplebrain/src/search_params.h @@ -17,8 +17,8 @@ #ifndef SEARCH_PARAMS #define SEARCH_PARAMS -#include "jellyfish/core/types.h" -#include "jellyfish/core/stream.h" +#include "jellyfish/types.h" +#include "jellyfish/stream.h" #include #pragma once diff --git a/samplebrain/src/window.h b/samplebrain/src/window.h index a4e29ba..bf9b495 100644 --- a/samplebrain/src/window.h +++ b/samplebrain/src/window.h @@ -16,8 +16,8 @@ #include #include -#include "jellyfish/fluxa/sample.h" -#include "jellyfish/core/types.h" +#include "jellyfish/sample.h" +#include "jellyfish/types.h" #ifndef WINDOW #define WINDOW