mirror of
https://gitlab.com/then-try-this/samplebrain.git
synced 2025-05-12 10:37:20 +00:00
isolated some core code
This commit is contained in:
parent
bb26e305c1
commit
b146f869c8
@ -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"
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <QtGui>
|
||||
#include "jellyfish/fluxa/OSC_server.h"
|
||||
#include "jellyfish/OSC_server.h"
|
||||
|
||||
#pragma once
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
147
samplebrain/src/jellyfish/OSC_server.cpp
Normal file
147
samplebrain/src/jellyfish/OSC_server.cpp
Normal 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;
|
||||
}
|
43
samplebrain/src/jellyfish/OSC_server.h
Normal file
43
samplebrain/src/jellyfish/OSC_server.h
Normal 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
|
64
samplebrain/src/jellyfish/allocator.cpp
Normal file
64
samplebrain/src/jellyfish/allocator.cpp
Normal 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!
|
||||
}
|
64
samplebrain/src/jellyfish/allocator.h
Normal file
64
samplebrain/src/jellyfish/allocator.h
Normal 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
|
102
samplebrain/src/jellyfish/audio.cpp
Normal file
102
samplebrain/src/jellyfish/audio.cpp
Normal 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
|
||||
}
|
56
samplebrain/src/jellyfish/audio.h
Normal file
56
samplebrain/src/jellyfish/audio.h
Normal 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;
|
||||
|
||||
};
|
||||
|
||||
}
|
91
samplebrain/src/jellyfish/command_ring_buffer.cpp
Normal file
91
samplebrain/src/jellyfish/command_ring_buffer.cpp
Normal 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));
|
||||
}
|
61
samplebrain/src/jellyfish/command_ring_buffer.h
Normal file
61
samplebrain/src/jellyfish/command_ring_buffer.h
Normal 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
|
191
samplebrain/src/jellyfish/fixed.h
Normal file
191
samplebrain/src/jellyfish/fixed.h
Normal 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
|
164
samplebrain/src/jellyfish/portaudio_client.cpp
Normal file
164
samplebrain/src/jellyfish/portaudio_client.cpp
Normal 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;
|
||||
}
|
75
samplebrain/src/jellyfish/portaudio_client.h
Normal file
75
samplebrain/src/jellyfish/portaudio_client.h
Normal 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
|
129
samplebrain/src/jellyfish/ring_buffer.cpp
Normal file
129
samplebrain/src/jellyfish/ring_buffer.cpp
Normal 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;
|
||||
}
|
46
samplebrain/src/jellyfish/ring_buffer.h
Normal file
46
samplebrain/src/jellyfish/ring_buffer.h
Normal 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
|
371
samplebrain/src/jellyfish/sample.cpp
Normal file
371
samplebrain/src/jellyfish/sample.cpp
Normal 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;
|
||||
}
|
||||
}
|
133
samplebrain/src/jellyfish/sample.h
Normal file
133
samplebrain/src/jellyfish/sample.h
Normal 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
|
150
samplebrain/src/jellyfish/stream.cpp
Normal file
150
samplebrain/src/jellyfish/stream.cpp
Normal 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;
|
||||
}
|
151
samplebrain/src/jellyfish/stream.h
Normal file
151
samplebrain/src/jellyfish/stream.h
Normal 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();
|
||||
|
||||
}
|
74
samplebrain/src/jellyfish/types.h
Normal file
74
samplebrain/src/jellyfish/types.h
Normal 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
|
@ -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>
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user