new c++ code

This commit is contained in:
Dave Griffiths 2015-07-08 08:08:49 +01:00
parent fb642744a0
commit c6ef1b670f
14 changed files with 5411 additions and 0 deletions

56
samplebrain/Makefile.in Normal file
View File

@ -0,0 +1,56 @@
TARGET := samplebrain
TARGET_LIB := libsamplebrain.a
SRCS := src/fft.cpp \
src/brain.cpp \
src/brain_block.cpp \
src/libmfcc.cpp \
src/main.cpp
TARGET_SRCS := src/main.cpp
# for the minute, go out and up to link to the vision lib
CCFLAGS = @CFLAGS@ -ffast-math -Wno-unused -Isrc
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
CC = @CXX@
AR = ar
OBJS := ${SRCS:.cpp=.o}
MAIN_OBJS := ${MAIN_SRCS:.cpp=.o}
DEPS := ${SRCS:.cpp=.dep}
MAIN_DEPS := ${MAIN_SRCS:.cpp=.dep}
XDEPS := $(wildcard ${DEPS})
.PHONY: all clean distclean
all:: ${TARGET}
ifneq (${XDEPS},)
include ${XDEPS}
endif
${TARGET}: ${MAIN_OBJS} ${OBJS} ${COBJS}
${CC} ${LDFLAGS} -o $@ $^ ${LIBS}
${OBJS}: %.o: %.cpp %.dep
${CC} ${CCFLAGS} -o $@ -c $<
${DEPS}: %.dep: %.cpp Makefile
${CC} ${CCFLAGS} -MM $< > $@
${MAIN_OBJS}: %.o: %.cpp %.dep
${CC} ${CCFLAGS} -o $@ -c $<
${MAIN_DEPS}: %.dep: %.cpp Makefile
${CC} ${CCFLAGS} -MM $< > $@
library: ${OBJS} ${COBJS}
$(AR) $(ARFLAGS) ${TARGET_LIB} ${OBJS} ${COBJS}
clean:: cleandeps
-rm -f *~ src/*.o src/*/*.o ${TARGET}
cleandeps::
-rm -f src/*.dep src/*/*.dep
distclean:: clean
-rm -rf config.status autom4te.cache config.log Makefile

4951
samplebrain/configure vendored Executable file

File diff suppressed because it is too large Load Diff

14
samplebrain/configure.ac Normal file
View File

@ -0,0 +1,14 @@
AC_INIT(samplebrain, version-0.1)
AC_PROG_CC
AC_CHECK_LIB(m, cos)
AC_CHECK_LIB(fftw3, main)
AC_CHECK_LIB(portaudio, main)
AC_CHECK_LIB(jellyfish, main)
AC_PROG_CXX
AC_LANG(C++)
AC_CHECK_HEADERS(iostream)
AC_CONFIG_HEADER(src/config.h)
AC_OUTPUT(Makefile)

6
samplebrain/dist.sh Executable file
View File

@ -0,0 +1,6 @@
# clean up
make distclean
# build src/config.h from configure.ac
autoheader
# build configure
autoconf configure.ac > configure

20
samplebrain/replace.py Executable file
View File

@ -0,0 +1,20 @@
#!/usr/bin/env python
import re
import sys
fn = sys.argv[1]
test = open(fn, 'r').read()
pattern = re.compile('[A-Z](?=[a-z])')
def format_term(term):
return '_%s' % (term.lower())
test = pattern.sub(lambda m: format_term(m.group(0)), test)
test = re.sub(r'(?<=[^a-z])_(?=[a-z])','',test)
o = open(fn,'w')
o.write(test)
o.close()

View File

23
samplebrain/src/brain.h Normal file
View File

@ -0,0 +1,23 @@
#include <vector>
#include "sample.h"
#include "fft.h"
class brain {
public:
brain();
// rewrites whole brain
void init(u32 block_size, u32 overlap);
// take another brain and rebuild this brain from bits of that one
// (presumably this one is made from a single sample)
sample resynth(const sample_brain *other, ratio);
private:
vector<brain_block> m_blocks;
u32 m_block_size;
u32 m_overlap;
};

View File

@ -0,0 +1,20 @@
#include "brain_block.h"
FFT *brain_block::m_fftw;
brain_block::brain_block(const sample &pcm) :
m_pcm(pcm),
m_fft(pcm.get_length()),
m_mfcc(13)
{
init_fft(m_pcm.get_length());
}
void brain_block::init_fft(u32 block_size)
{
if (m_fftw == NULL || m_fftw->m_length!=block_size) {
if (m_fftw == NULL) delete m_fftw;
m_fftw = new FFT(block_size);
}
}

View File

@ -0,0 +1,25 @@
#include <vector>
#include "jellyfish/fluxa/sample.h"
#include "jellyfish/core/types.h"
#include "fft.h"
using namespace spiralcore;
class brain_block {
public:
// runs analysis on pcm
brain_block(const sample &pcm);
// returns distance based on ratio of fft-mfcc values
float compare(const brain_block &other, float ratio);
static void init_fft(u32 block_size);
private:
sample m_pcm;
sample m_fft;
sample m_mfcc;
static FFT *m_fftw;
};

54
samplebrain/src/fft.cpp Normal file
View File

@ -0,0 +1,54 @@
#include <fft.h>
static const int MAX_FFT_LENGTH = 4096;
FFT::FFT(int length) :
m_length(length),
#ifndef __FFTWFLOAT__
m_in(new double[length]),
#else
m_in(new float[length]),
#endif
#ifndef __FFTWFLOAT__
m_spectrum(new fftw_complex[length])
{
m_plan = fftw_plan_dft_r2c_1d(m_length, m_in, m_spectrum, FFTW_ESTIMATE);
}
#else
m_spectrum(new fftwf_complex[length])
{
m_plan = fftwf_plan_dft_r2c_1d(m_length, m_in, m_spectrum, FFTW_ESTIMATE);
}
#endif
FFT::~FFT()
{
delete[] m_in;
#ifndef __FFTWFLOAT__
fftw_destroy_plan(m_plan);
#else
fftwf_destroy_plan(m_plan);
#endif
}
void FFT::impulse2freq(float *imp, float *out)
{
unsigned int i;
for (i=0; i<m_length; i++)
{
m_in[i] = imp[i];
}
#ifndef __FFTWFLOAT__
fftw_execute(m_plan);
#else
fftwf_execute(m_plan);
#endif
for (i=0; i<m_length; i++)
{
out[i] = m_spectrum[i][0];
}
}

23
samplebrain/src/fft.h Normal file
View File

@ -0,0 +1,23 @@
#include <fftw3.h>
//#define __FFTWFLOAT__
class FFT
{
public:
FFT(int length);
~FFT();
void impulse2freq(float *imp, float *out);
#ifndef __FFTWFLOAT__
fftw_plan m_plan;
unsigned int m_length;
double *m_in;
fftw_complex *m_spectrum;
#else
fftwf_plan m_plan;
unsigned int m_length;
float *m_in;
fftwf_complex *m_spectrum;
#endif
};

165
samplebrain/src/libmfcc.cpp Normal file
View File

@ -0,0 +1,165 @@
/*
* libmfcc.c - Code implementation for libMFCC
* Copyright (c) 2010 Jeremy Sawruk
*
* This code is released under the MIT License.
* For conditions of distribution and use, see the license in LICENSE
*/
#include <math.h>
#include "libmfcc.h"
/*
* Computes the specified (mth) MFCC
*
* spectralData - array of doubles containing the results of FFT computation. This data is already assumed to be purely real
* samplingRate - the rate that the original time-series data was sampled at (i.e 44100)
* NumFilters - the number of filters to use in the computation. Recommended value = 48
* binSize - the size of the spectralData array, usually a power of 2
* m - The mth MFCC coefficient to compute
*
*/
double GetCoefficient(double* spectralData, unsigned int samplingRate, unsigned int NumFilters, unsigned int binSize, unsigned int m)
{
double result = 0.0f;
double outerSum = 0.0f;
double innerSum = 0.0f;
unsigned int k, l;
// 0 <= m < L
if(m >= NumFilters)
{
// This represents an error condition - the specified coefficient is greater than or equal to the number of filters. The behavior in this case is undefined.
return 0.0f;
}
result = NormalizationFactor(NumFilters, m);
for(l = 1; l <= NumFilters; l++)
{
// Compute inner sum
innerSum = 0.0f;
for(k = 0; k < binSize - 1; k++)
{
innerSum += fabs(spectralData[k] * GetFilterParameter(samplingRate, binSize, k, l));
}
if(innerSum > 0.0f)
{
innerSum = log(innerSum); // The log of 0 is undefined, so don't use it
}
innerSum = innerSum * cos(((m * PI) / NumFilters) * (l - 0.5f));
outerSum += innerSum;
}
result *= outerSum;
return result;
}
/*
* Computes the Normalization Factor (Equation 6)
* Used for internal computation only - not to be called directly
*/
double NormalizationFactor(int NumFilters, int m)
{
double normalizationFactor = 0.0f;
if(m == 0)
{
normalizationFactor = sqrt(1.0f / NumFilters);
}
else
{
normalizationFactor = sqrt(2.0f / NumFilters);
}
return normalizationFactor;
}
/*
* Compute the filter parameter for the specified frequency and filter bands (Eq. 2)
* Used for internal computation only - not the be called directly
*/
double GetFilterParameter(unsigned int samplingRate, unsigned int binSize, unsigned int frequencyBand, unsigned int filterBand)
{
double filterParameter = 0.0f;
double boundary = (frequencyBand * samplingRate) / binSize; // k * Fs / N
double prevCenterFrequency = GetCenterFrequency(filterBand - 1); // fc(l - 1) etc.
double thisCenterFrequency = GetCenterFrequency(filterBand);
double nextCenterFrequency = GetCenterFrequency(filterBand + 1);
if(boundary >= 0 && boundary < prevCenterFrequency)
{
filterParameter = 0.0f;
}
else if(boundary >= prevCenterFrequency && boundary < thisCenterFrequency)
{
filterParameter = (boundary - prevCenterFrequency) / (thisCenterFrequency - prevCenterFrequency);
filterParameter *= GetMagnitudeFactor(filterBand);
}
else if(boundary >= thisCenterFrequency && boundary < nextCenterFrequency)
{
filterParameter = (boundary - nextCenterFrequency) / (thisCenterFrequency - nextCenterFrequency);
filterParameter *= GetMagnitudeFactor(filterBand);
}
else if(boundary >= nextCenterFrequency && boundary < samplingRate)
{
filterParameter = 0.0f;
}
return filterParameter;
}
/*
* Compute the band-dependent magnitude factor for the given filter band (Eq. 3)
* Used for internal computation only - not the be called directly
*/
double GetMagnitudeFactor(unsigned int filterBand)
{
double magnitudeFactor = 0.0f;
if(filterBand >= 1 && filterBand <= 14)
{
magnitudeFactor = 0.015;
}
else if(filterBand >= 15 && filterBand <= 48)
{
magnitudeFactor = 2.0f / (GetCenterFrequency(filterBand + 1) - GetCenterFrequency(filterBand -1));
}
return magnitudeFactor;
}
/*
* Compute the center frequency (fc) of the specified filter band (l) (Eq. 4)
* This where the mel-frequency scaling occurs. Filters are specified so that their
* center frequencies are equally spaced on the mel scale
* Used for internal computation only - not the be called directly
*/
double GetCenterFrequency(unsigned int filterBand)
{
double centerFrequency = 0.0f;
double exponent;
if(filterBand == 0)
{
centerFrequency = 0;
}
else if(filterBand >= 1 && filterBand <= 14)
{
centerFrequency = (200.0f * filterBand) / 3.0f;
}
else
{
exponent = filterBand - 14.0f;
centerFrequency = pow(1.0711703, exponent);
centerFrequency *= 1073.4;
}
return centerFrequency;
}

26
samplebrain/src/libmfcc.h Normal file
View File

@ -0,0 +1,26 @@
/*
* libmfcc.h - Header for libMFCC
* Copyright (c) 2010 Jeremy Sawruk
*
* This code is released under the MIT License.
* For conditions of distribution and use, see the license in LICENSE
*/
#pragma once
#define PI 3.14159265358979323846264338327
// Returns the specified (mth) MFCC
double GetCoefficient(double* spectralData, unsigned int samplingRate, unsigned int NumFilters, unsigned int binSize, unsigned int m);
// Compute the normalization factor (For internal computation only - not to be called directly)
double NormalizationFactor(int NumFilters, int m);
// Compute the filter parameter for the specified frequency and filter bands (For internal computation only - not the be called directly)
double GetFilterParameter(unsigned int samplingRate, unsigned int binSize, unsigned int frequencyBand, unsigned int filterBand);
// Compute the band-dependent magnitude factor for the given filter band (For internal computation only - not the be called directly)
double GetMagnitudeFactor(unsigned int filterBand);
// Compute the center frequency (fc) of the specified filter band (l) (For internal computation only - not the be called directly)
double GetCenterFrequency(unsigned int filterBand);

28
samplebrain/src/main.cpp Normal file
View File

@ -0,0 +1,28 @@
// 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 <stdio.h>
#include <stdlib.h>
#include <iostream>
#include "jellyfish/audio.h"
using namespace std;
int main(int argc, char *argv[])
{
audio_device *a = new audio_device("samplebrain",44100,2048);
}