isolated some core code

This commit is contained in:
dave griffiths 2016-06-06 15:46:36 +01:00
parent bb26e305c1
commit b146f869c8
31 changed files with 2139 additions and 25 deletions

View File

@ -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"

View File

@ -16,7 +16,7 @@
#include <string>
#include <QtGui>
#include "jellyfish/fluxa/OSC_server.h"
#include "jellyfish/OSC_server.h"
#pragma once

View File

@ -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 <pthread.h>

View File

@ -32,6 +32,8 @@ int main( int argc , char *argv[] ){
MainWindow mainWin;
mainWin.show();
cerr<<"Qt version: "<<qVersion()<<endl;
//pitchshift::init(44100);
process_thread pt;

View File

@ -30,14 +30,14 @@ SOURCES += MainWindow.cpp \
../src/aquila/filter/MelFilterBank.cpp \
../src/aquila/filter/MelFilter.cpp \
../src/aquila/transform/Dct.cpp \
../../../jellyfish/src/fluxa/sample.cpp \
../../../jellyfish/src/fluxa/ring_buffer.cpp \
../../../jellyfish/src/fluxa/command_ring_buffer.cpp \
../../../jellyfish/src/audio/portaudio_client.cpp \
../../../jellyfish/src/audio.cpp \
../../../jellyfish/src/fluxa/OSC_server.cpp \
../../../jellyfish/src/fluxa/allocator.cpp \
../../../jellyfish/src/core/stream.cpp
../src/jellyfish/sample.cpp \
../src/jellyfish/ring_buffer.cpp \
../src/jellyfish/command_ring_buffer.cpp \
../src/jellyfish/portaudio_client.cpp \
../src/jellyfish/audio.cpp \
../src/jellyfish/OSC_server.cpp \
../src/jellyfish/allocator.cpp \
../src/jellyfish/stream.cpp
INCLUDEPATH += ../src
LIBS += -L.. -lportaudio -lfftw3 -lsndfile -llo -ldl -lpthread -lm

View File

@ -17,7 +17,7 @@
#include <QtGui>
#include <iostream>
#include <list>
#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);

View File

@ -16,13 +16,13 @@
#include <string>
#include <vector>
#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

View File

@ -17,8 +17,8 @@
#include <list>
#include <vector>
#include <string>
#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"

View File

@ -15,7 +15,7 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <fftw3.h>
#include <jellyfish/core/types.h>
#include <jellyfish/types.h>
#ifndef SPIRALCORE_FFT
#define SPIRALCORE_FFT

View File

@ -0,0 +1,147 @@
// copyright (C) 2004 david griffiths <dave@pawfal.org>
//
// 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 <cstring>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <iostream>
#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: ["<<port<<"]"<<endl;
m_server = lo_server_thread_new(port.c_str(), error_handler);
lo_server_thread_add_method(m_server, NULL, NULL, default_handler, this);
}
OSC_server::~OSC_server()
{
m_exit=true;
lo_server_thread_stop(m_server);
}
void OSC_server::run()
{
lo_server_thread_start(m_server);
// while (!m_exit) usleep(1000);
}
void OSC_server::error_handler(int num, const char *msg, const char *path)
{
//cerr<<"liblo server error "<<num<<" in path "<<path<<": "<<msg<<endl;
cerr<<"liblo server error "<<num<<endl;
}
int OSC_server::default_handler(const char *path, const char *types, lo_arg **argv,
int argc, void *data, void *user_data)
{
OSC_server *server = (OSC_server*)user_data;
unsigned int size = 0;
for (int i=0; i<argc; i++)
{
size+=lo_arg_size((lo_type)types[i],argv[i]);
// add one for the null terminator
if (types[i]=='s') size++;
}
char *newdata=new char[size];
unsigned int pos=0;
for (int i=0; i<argc; i++)
{
switch (types[i])
{
case LO_INT32:
{
if (pos+4>COMMAND_DATA_SIZE)
{
cerr<<"osc data too big for ringbuffer command"<<endl;
delete[] newdata;
return 1;
}
memcpy(newdata+pos,(char*)argv[i],4);
pos+=4;
}
break;
case LO_FLOAT:
{
if (pos+4>COMMAND_DATA_SIZE)
{
cerr<<"osc data too big for ringbuffer command"<<endl;
delete[] newdata;
return 1;
}
memcpy(newdata+pos,(char*)argv[i],4);
pos+=4;
}
break;
case LO_STRING:
{
int size=strlen(&argv[i]->s);
if (pos+size+1>COMMAND_DATA_SIZE)
{
cerr<<"osc data too big for ringbuffer command"<<endl;
delete[] newdata;
return 1;
}
memcpy(newdata+pos,&argv[i]->s,size);
newdata[pos+size]='\0';
pos+=size+1;
}
break;
default:
{
cerr<<"unsupported type: "<<types[i]<<endl;
delete[] newdata;
return 1;
}
break;
}
}
if (1)//pos==size) hmm
{
command_ring_buffer::command command(path,types,newdata,pos);
if (!server->m_command_ring_buffer.send(command))
{
//cerr<<"OSC_server - ringbuffer full!"<<endl;
}
}
else
{
cerr<<"OSC_server::default_handler: size mismatch ["<<pos<<":"<<size<<"], not sending message"<<endl;
}
delete[] newdata;
return 1;
}

View File

@ -0,0 +1,43 @@
// copyright (C) 2004 david griffiths <dave@pawfal.org>
//
// 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 <string>
#include <lo/lo.h>
#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

View File

@ -0,0 +1,64 @@
// Copyright (C) 2003 David Griffiths <dave@pawfal.org>
//
// 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 "<<size<<endl;
char *ret = m_buffer+m_position;
m_position+=size;
if (m_position>m_size)
{
// cerr<<"out of realtime buffer mem, here we go!!! :("<<endl;
m_position=0;
ret = m_buffer;
}
return ret;
}
void realtime_allocator::adelete(char *mem)
{
//cerr<<"delete"<<endl;
// we don't need no stinking delete!
}

View File

@ -0,0 +1,64 @@
// Copyright (C) 2004 David Griffiths <dave@pawfal.org>
//
// 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

View File

@ -0,0 +1,102 @@
// Copyright (C) 2015 David Griffiths <dave@pawfal.org>
//
// 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 <string>
#include "audio.h"
#include <sndfile.h>
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 "<<filename<<endl;
u32 written = sf_writef_float(f, s.get_buffer(), s.get_length());
if (written!=s.get_length()) cerr<<"error: wrote "<<written<<endl;
sf_close(f);
}
void audio_device::start_recording(std::string filename) {
m_record_filename=filename;
m_recording=true;
m_record_buffer_left.clear();
m_record_buffer_right.clear();
m_record_counter=0;
}
void audio_device::stop_recording() {
m_recording=false;
}
void audio_device::maybe_record() {
if (m_recording) {
m_record_buffer_left.add(left_out);
m_record_buffer_right.add(right_out);
m_record_counter++;
if (m_record_counter%10==0) {
save_sample(m_record_filename+"-left.wav", m_record_buffer_left);
save_sample(m_record_filename+"-right.wav", m_record_buffer_right);
}
}
}
#ifndef DONT_USE_FLUXA_GRAPH
void run_graph(void *c, unsigned int size) {
#ifndef DONT_USE_FLUXA_GRAPH
audio_device *a=(audio_device *)c;
a->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
}

View File

@ -0,0 +1,56 @@
// Copyright (C) 2015 David Griffiths <dave@pawfal.org>
//
// 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 <string>
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;
};
}

View File

@ -0,0 +1,91 @@
// copyright (C) 2004 david griffiths <dave@pawfal.org>
//
// 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 <string.h>
#include <iostream>
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<m_num_args; i++)
{
m_offsets[i]=pos;
switch(types[i])
{
case 'i': pos+=4; break;
case 'f': pos+=4; break;
case 's': pos+=strlen(m_data+pos)+1; break;
case 'b': pos+=sizeof(char*); break;
default:
// invalidate the command
for(unsigned int n=0; n<strlen(types); n++) m_offsets[n]=-1;
cerr<<"command_ring_buffer::command::command: erk! unknown type: "<<types[i]<<endl;
return;
break;
}
}
}
int command_ring_buffer::command::get_int(unsigned int index)
{
if (m_offsets[index]!=-1 && m_types[index]=='i') return *((int*)(m_data+m_offsets[index]));
return 0;
}
float command_ring_buffer::command::get_float(unsigned int index)
{
if (m_offsets[index]!=-1 && m_types[index]=='f') return *((float*)(m_data+m_offsets[index]));
return 0;
}
char *command_ring_buffer::command::get_string(unsigned int index)
{
if (m_offsets[index]!=-1 && m_types[index]=='s') return ((char*)(m_data+m_offsets[index]));
return 0;
}
////////////////////////////////////////////////////////////////
command_ring_buffer::command_ring_buffer(unsigned int size):
ring_buffer(size)
{
}
command_ring_buffer::~command_ring_buffer()
{
}
bool command_ring_buffer::send(const command& command)
{
return write((char*)&command,sizeof(command));
}
bool command_ring_buffer::get(command& command)
{
return read((char*)&command, sizeof(command));
}

View File

@ -0,0 +1,61 @@
// copyright (C) 2004 david griffiths <dave@pawfal.org>
//
// 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

View File

@ -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); } // smallest step we can represent
// for private construction via guts
enum FixedRaw { RAW };
Fixed(FixedRaw, int guts) : g(guts) {}
//public:
Fixed() : g(0) {}
Fixed(const Fixed& a) : g( a.g ) {}
Fixed(float a) : g( int(a / (float)STEP()) ) {}
Fixed(double a) : g( int(a / (double)STEP()) ) {}
Fixed(int a) : g( a << BP ) {}
Fixed(long a) : g( a << BP ) {}
Fixed& operator =(const Fixed& a) { g= a.g; return *this; }
Fixed& operator =(float a) { g= Fixed(a).g; return *this; }
Fixed& operator =(double a) { g= Fixed(a).g; return *this; }
Fixed& operator =(int a) { g= Fixed(a).g; return *this; }
Fixed& operator =(long a) { g= Fixed(a).g; return *this; }
operator float() const { return g * (float)STEP(); }
operator double() const { return g * (double)STEP(); }
operator int() const { return g>>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

View File

@ -0,0 +1,164 @@
// copyright (C) 2003 david griffiths <dave@pawfal.org>
//
// 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 <stdio.h>
#include <limits.h>
#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"<<endl;
Pa_Terminate();
fprintf( stderr, "an error occured while using the portaudio stream\n" );
fprintf( stderr, "error number: %d\n", err );
fprintf( stderr, "error message: %s\n", Pa_GetErrorText( err ) );
}
PaStreamParameters output_parameters;
output_parameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
if (output_parameters.device == paNoDevice) {
cerr<<"error: no default output device."<<endl;
}
output_parameters.channelCount = 2; /* stereo output */
output_parameters.sampleFormat = paFloat32; /* 32 bit floating point output */
output_parameters.suggestedLatency = Pa_GetDeviceInfo( output_parameters.device )->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."<<endl;
}
input_parameters.channelCount = 2; /* stereo output */
input_parameters.sampleFormat = paFloat32; /* 32 bit floating point output */
input_parameters.suggestedLatency = Pa_GetDeviceInfo( input_parameters.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: "<<Pa_GetErrorText( err )<<endl;
Pa_Terminate();
return false;
}
err = Pa_StartStream(stream);
if( err != paNoError )
{
cerr<<"could not start stream: "<<Pa_GetErrorText( err )<<endl;
Pa_Terminate();
return false;
}
m_attached=true;
cerr<<"connected to portaudio..."<<endl;
return true;
}
/////////////////////////////////////////////////////////////////////////////////////////////
void portaudio_client::detach()
{
cerr<<"detaching from portaudio"<<endl;
Pa_Terminate();
m_attached=false;
}
/////////////////////////////////////////////////////////////////////////////////////////////
int portaudio_client::process(const void *input_buffer, void *output_buffer,
unsigned long frames_per_buffer,
const PaStreamCallbackTimeInfo* time_info,
PaStreamCallbackFlags status_flags,
void *user_data)
{
m_buffer_size=frames_per_buffer;
if(run_callback&&run_context)
{
// do the work
run_callback(run_context, frames_per_buffer);
}
if (m_right_data && m_left_data)
{
float *out = (float*)output_buffer;
for (unsigned int n=0; n<m_buffer_size; n++)
{
*out=m_left_data[n];
out++;
*out=m_right_data[n];
out++;
}
}
/* if (m_right_in_data && m_left_in_data)
{
float *in = (float*)input_buffer;
for (unsigned int n=0; n<m_buffer_size; n++)
{
m_left_in_data[n]=*in;
in++;
m_right_in_data[n]=*in;
in++;
}
}*/
return 0;
}

View File

@ -0,0 +1,75 @@
// copyright (C) 2003 david griffiths <dave@pawfal.org>
//
// 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 <map>
#include <vector>
#include <string>
#include <iostream>
#include <portaudio.h>
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

View File

@ -0,0 +1,129 @@
// copyright (C) 2004 david griffiths <dave@pawfal.org>
//
// 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 <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#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_write_pos<<endl;
unsigned int space=write_space();
if (space<size)
{
cerr<<"ringbuffer ran out of space, needed: "<<size<<" have: "<<space<<endl;
return false;
}
if (size<m_size-m_write_pos)
{
//cerr<<"written to: "<<m_write_pos<<endl;
memcpy(&(m_buffer[m_write_pos]), src, size);
m_write_pos += size;
m_write_pos &= m_size_mask;
}
else // have to split data over boundary
{
unsigned int first = m_size-m_write_pos;
unsigned int second = (m_write_pos+size) & m_size_mask;
memcpy(&(m_buffer[m_write_pos]), src, first);
m_write_pos += first;
m_write_pos &= m_size_mask;
memcpy(&(m_buffer[m_write_pos]), &src[first], second);
m_write_pos += second;
m_write_pos &= m_size_mask;
}
return true;
}
bool ring_buffer::read(char *dest, unsigned int size)
{
//cerr<<"read pos: "<<m_read_pos<<endl;
unsigned int space=read_space();
if (space==0 || size>m_size) return false;
if (size<m_size-m_read_pos)
{
//cerr<<"reading from: "<<m_read_pos<<endl;
memcpy(dest, &(m_buffer[m_read_pos]), size);
m_read_pos += size;
m_read_pos &= m_size_mask;
}
else // have to split data over boundary
{
unsigned int first = m_size-m_read_pos;
unsigned int second = (m_read_pos+size) & m_size_mask;
memcpy(dest, &(m_buffer[m_read_pos]), first);
m_read_pos += first;
m_read_pos &= m_size_mask;
memcpy(&dest[first], &(m_buffer[m_read_pos]), second);
m_read_pos += second;
m_read_pos &= m_size_mask;
}
return true;
}
void ring_buffer::dump()
{
for (unsigned int i=0; i<m_size; i++) cerr<<m_buffer[i];
cerr<<endl;
}
unsigned int ring_buffer::write_space()
{
unsigned int read = m_read_pos;
unsigned int write = m_write_pos;
if (write > 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;
}

View File

@ -0,0 +1,46 @@
// copyright (C) 2004 david griffiths <dave@pawfal.org>
//
// 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

View File

@ -0,0 +1,371 @@
// _copyright (_c) 2003 _david _griffiths <dave@pawfal.org>
//
// _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 <string.h>
#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; n<m_length; n++)
{
m_data[n]=val;
}
}
void sample::insert(const sample &s, unsigned int pos)
{
// do some checking
assert(pos<=get_length());
unsigned int new_len = get_length()+s.get_length();
audio_type *new_buf = (audio_type*) m_allocator->anew(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_pos<s.get_length(); temp_buf_pos++)
{
new_buf[to_pos]=s[temp_buf_pos];
to_pos++;
}
}
else
{
// this test is needed so the loop can deal
// with samples being "inserted" on to the
// very end of the buffer
if (from_pos<get_length())
{
new_buf[to_pos]=m_data[from_pos];
}
}
from_pos++;
to_pos++;
}
clear();
m_data=new_buf;
m_length=new_len;
}
void sample::add(const sample &s)
{
insert(s,get_length());
}
void sample::mix(const sample &s, unsigned int pos)
{
// do some checking
assert(pos<get_length());
unsigned int to_pos=pos;
for (unsigned int from_pos=0; from_pos<s.get_length(); from_pos++)
{
m_data[to_pos]=m_data[to_pos]+s[from_pos];
if (to_pos>get_length()) to_pos=0;
to_pos++;
}
}
void sample::mul_mix(const sample &s, unsigned int pos, float m)
{
// do some checking
assert(pos<get_length());
unsigned int to_pos=pos;
for (unsigned int from_pos=0; from_pos<s.get_length(); from_pos++)
{
m_data[to_pos]=m_data[to_pos]+s[from_pos]*m;
if (to_pos>get_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_pos<s.get_length(); from_pos++)
{
float t=s[from_pos]*m;
if (t>m) 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(end<get_length() && start<get_length());
assert(start<=end);
// check the range
if (end>get_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_pos<get_length(); from_pos++)
{
// copy the areas outside of the cut range
if (from_pos<start || from_pos>end)
{
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(end<get_length() && start<get_length());
assert(start<=end);
// check the range
if (end>get_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_pos<end; to_pos++)
{
m_data[to_pos]=temp_buf[from_pos];
from_pos++;
}
}
void sample::move(unsigned int dist)
{
unsigned int length=get_length();
audio_type *temp_buf = (audio_type*) m_allocator->anew(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; to_pos++)
{
temp_buf[to_pos]=m_data[from_pos];
from_pos++;
if (from_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(end<get_length() && start<get_length());
assert(start<=end);
unsigned int length=end-start;
s.allocate(length);
unsigned int from_pos=start;
for (unsigned int to_pos=0; to_pos<length; to_pos++)
{
s.set(to_pos,m_data[from_pos]);
from_pos++;
}
}
void sample::crop_to(unsigned int new_length)
{
assert (new_length<get_length());
audio_type *temp = (audio_type*) m_allocator->anew(new_length*sizeof(audio_type));
for(unsigned int n=0; n<new_length; n++)
{
temp[n]=m_data[n];
}
clear();
m_data=temp;
m_length=new_length;
}
// adds length amount of blank space
void sample::expand(unsigned int length)
{
sample temp(length);
temp.zero();
add(temp);
}
// shrink the samle by length amount
void sample::shrink(unsigned int length)
{
unsigned int new_length=get_length()-length;
assert(new_length>0 && new_length<=get_length());
audio_type *temp = (audio_type*) m_allocator->anew(new_length*sizeof(audio_type));
for(unsigned int n=0; n<new_length; n++)
{
temp[n]=m_data[n];
}
clear();
m_data=temp;
m_length=new_length;
}
ios &spiralcore::operator||(ios &s, sample &sa) {
unsigned int version=1;
string id("sample");
s||id||version;
s||sa.m_sample_type;
ofstream *pos=dynamic_cast<ofstream*>(&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<ifstream*>(&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;
}
}

View File

@ -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 <memory.h>
#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#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<b+tol);
}
class sample
{
public:
enum sample_type {AUDIO=0, IMAGE, MIDI};
sample(unsigned int len=0);
sample(const sample &rhs);
sample(const audio_type *s, unsigned int len);
~sample();
static void set_allocator(base_allocator *s) { m_allocator=s; }
static base_allocator *get_allocator() { return m_allocator; }
bool allocate(unsigned int size);
void clear();
void zero();
void set(audio_type val);
void insert(const sample &s, unsigned int pos);
void add(const sample &s);
void mix(const sample &s, unsigned int pos=0);
void mul_mix(const sample &s, unsigned int pos, float m);
void mul_clip_mix(const sample &s, float m);
void remove(unsigned int start, unsigned int end);
void reverse(unsigned int start, unsigned int end);
void move(unsigned int dist);
void get_region(sample &s, unsigned int start, unsigned int end) const;
const audio_type *get_buffer() const {return m_data;}
audio_type *get_non_const_buffer() {return m_data;}
unsigned int get_length() const {return m_length;}
unsigned int get_length_in_bytes() const {return m_length*sizeof(audio_type);}
void expand(unsigned int length);
void shrink(unsigned int length);
void crop_to(unsigned int new_length);
audio_type &operator[](unsigned int i) const
{
#ifdef DEBUG
cerr<<"debug..."<<endl;
assert(i<m_length);
#endif
return m_data[i%m_length];
}
// _linear interpolated
inline audio_type operator[](float i) const
{
unsigned int ii=(unsigned int)i;
#ifdef DEBUG
assert(ii<m_length);
#endif
if (ii==m_length-1) return m_data[ii%m_length];
audio_type t=i-ii;
return ((m_data[ii%m_length]*(1-t))+
(m_data[(ii+1)%m_length])*t);
}
void set(unsigned int i, audio_type v)
{
#ifdef DEBUG
assert(i<m_length);
#endif
m_data[i%m_length]=v;
}
sample &operator=(const sample &rhs)
{
if (get_length()!=rhs.get_length()) allocate(rhs.get_length());
memcpy(m_data,rhs.get_buffer(),get_length_in_bytes());
return *this;
}
friend ios &operator||(ios &s, sample &sa);
private:
audio_type *m_data;
unsigned int m_length;
sample_type m_sample_type;
static base_allocator *m_allocator;
};
ios &operator||(ios &s, sample &sa);
}
#endif

View File

@ -0,0 +1,150 @@
// Copyright (C) 2015 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.
#include <fstream>
#include "stream.h"
#include <iostream>
#include "types.h"
using namespace spiralcore;
using namespace std;
template<>ios &spiralcore::operator||(ios &s, string &v) {
ofstream *pos=dynamic_cast<ofstream*>(&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<ifstream*>(&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<U> &v) {
ofstream *pos=dynamic_cast<ofstream*>(&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<ifstream*>(&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;
}
}*/
/*
template<class U>ios &operator||(ios &s, vector<U> &v) {
ofstream *pos=dynamic_cast<ofstream*>(&s);
if (pos!=NULL) {
ofstream &os = *pos;
size_t len = v.length();
for (size_t i=0; i<len; ++i) {
os||v[i];
}
return os;
}
else
{
ifstream *pis=dynamic_cast<ifstream*>(&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<len; ++i) {
is||v[i];
}
return is;
}
}
*/
void spiralcore::stream_unit_test() {
ofstream of("test_data/streamtest.bin",ios::binary);
int o_a(100);
float o_b(0.2);
string o_c("hello");
string o_d("there");
s32 size=10;
int *o_e = new int[size];
vector<int> o_f;
for(s32 i=0; i<size; i++) {
o_e[i]=i;
o_f.push_back(i);
}
of||o_a||o_b||o_c||o_d;
// o_e = stream_array(of,o_e,size);
stream_vector(of,o_f);
of.close();
delete[] o_e;
ifstream ifs("test_data/streamtest.bin",ios::binary);
int i_a;
float i_b;
string i_c,i_d;
ifs||i_a||i_b||i_c||i_d;
int *i_e;
vector<int> 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<size; i++) {
// assert(i_e[i]==i);
assert(i_f[i]==i);
}
//delete[] i_e;
}

View File

@ -0,0 +1,151 @@
// Copyright (C) 2015 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.
#include <fstream>
#include <string>
#include <vector>
#include <list>
#include <assert.h>
#include <iostream>
#pragma once
namespace spiralcore {
// hack to do both stream directions in one function
// saw this years ago at computer artworks, not seen it since...
template<typename T>std::ios &operator||(std::ios &s, T &v) {
std::ofstream *pos=dynamic_cast<std::ofstream*>(&s);
if (pos!=NULL) {
std::ofstream &os = *pos;
os.write((char*)(&v),sizeof(T));
return os;
}
else
{
std::ifstream *pis=dynamic_cast<std::ifstream*>(&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);
/*
template<typename T, typename U>T *stream_array(std::ios &s, T *v, U &len) {
std::ofstream *pos=dynamic_cast<std::ofstream*>(&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<std::ifstream*>(&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;
}
}
*/
template<typename T>std::ios &stream_vector(std::ios &s, std::vector<T> &v) {
std::ofstream *pos=dynamic_cast<std::ofstream*>(&s);
if (pos!=NULL) {
std::ofstream &os = *pos;
size_t len = v.size();
os||len;
for (size_t i=0; i<len; ++i) {
os||v[i];
}
return os;
}
else
{
std::ifstream *pis=dynamic_cast<std::ifstream*>(&s);
assert(pis);
std::ifstream &is = *pis;
size_t len=0;
is||len;
//v.reserve(len);
v.clear();
for (size_t i=0; i<len; ++i) {
T t;
is||t;
v.push_back(t);
}
return is;
}
}
// skip a vector when loading
template<typename T>std::ios &skip_vector(std::ifstream &is) {
size_t len=0;
is||len;
for (size_t i=0; i<len; ++i) {
T t;
is||t;
}
return is;
}
template<typename T>std::ios &stream_list(std::ios &s, std::list<T> &v) {
std::ofstream *pos=dynamic_cast<std::ofstream*>(&s);
if (pos!=NULL) {
std::ofstream &os = *pos;
size_t len = v.size();
os||len;
for (typename std::list<T>::iterator i=v.begin(); i!=v.end(); ++i) {
os||*i;
}
return os;
}
else
{
std::ifstream *pis=dynamic_cast<std::ifstream*>(&s);
assert(pis);
std::ifstream &is = *pis;
size_t len=0;
is||len;
for (size_t i=0; i<len; ++i) {
T t;
is||t;
v.push_back(t);
}
return is;
}
}
template<typename T>std::ios &skip_list(std::istream &is) {
size_t len=0;
is||len;
for (size_t i=0; i<len; ++i) {
T t;
is||t;
}
return is;
}
void stream_unit_test();
}

View File

@ -0,0 +1,74 @@
// Copyright (C) 2011 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.
#include "fixed.h"
//#include "ac_config.h"
#ifndef FLX_TYPES
#define FLX_TYPES
#include <math.h>
// 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

View File

@ -20,7 +20,7 @@
#include "aquila/global.h"
//#include "aquila/transform/FftFactory.h"
#include <jellyfish/fluxa/sample.h>
#include <jellyfish/sample.h>
#include <cstddef>
#include <vector>

View File

@ -15,7 +15,7 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <list>
#include <jellyfish/fluxa/sample.h>
#include <jellyfish/sample.h>
#include "brain.h"
#ifndef SB_RENDERER

View File

@ -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 <iostream>
#pragma once

View File

@ -16,8 +16,8 @@
#include <string>
#include <vector>
#include "jellyfish/fluxa/sample.h"
#include "jellyfish/core/types.h"
#include "jellyfish/sample.h"
#include "jellyfish/types.h"
#ifndef WINDOW
#define WINDOW