mirror of
https://gitlab.com/then-try-this/samplebrain.git
synced 2025-05-12 10:37:20 +00:00
new c++ code
This commit is contained in:
parent
fb642744a0
commit
c6ef1b670f
56
samplebrain/Makefile.in
Normal file
56
samplebrain/Makefile.in
Normal 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
4951
samplebrain/configure
vendored
Executable file
File diff suppressed because it is too large
Load Diff
14
samplebrain/configure.ac
Normal file
14
samplebrain/configure.ac
Normal 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
6
samplebrain/dist.sh
Executable 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
20
samplebrain/replace.py
Executable 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()
|
0
samplebrain/src/brain.cpp
Normal file
0
samplebrain/src/brain.cpp
Normal file
23
samplebrain/src/brain.h
Normal file
23
samplebrain/src/brain.h
Normal 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;
|
||||||
|
|
||||||
|
};
|
20
samplebrain/src/brain_block.cpp
Normal file
20
samplebrain/src/brain_block.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
25
samplebrain/src/brain_block.h
Normal file
25
samplebrain/src/brain_block.h
Normal 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
54
samplebrain/src/fft.cpp
Normal 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
23
samplebrain/src/fft.h
Normal 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
165
samplebrain/src/libmfcc.cpp
Normal 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
26
samplebrain/src/libmfcc.h
Normal 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
28
samplebrain/src/main.cpp
Normal 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);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user