Skip to content

Commit

Permalink
Replace SortFloats()/RemapFloats() with stdlib's qsort and struct ref…
Browse files Browse the repository at this point in the history
…actoring.
  • Loading branch information
Cleon Chick committed Oct 8, 2016
1 parent fc2a404 commit 29d07b1
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 188 deletions.
4 changes: 2 additions & 2 deletions colorchord2/Makefile
Expand Up @@ -16,10 +16,10 @@ LDLIBS:=-lpthread -lasound -lm -lpulse-simple -lpulse
CFLAGS:=-g -O0 -flto -Wall -ffast-math -I../embeddedcommon -I. -DICACHE_FLASH_ATTR=
EXTRALIBS:=-lusb-1.0

colorchord : os_generic.o main.o dft.o decompose.o filter.o color.o sort.o notefinder.o util.o outdrivers.o $(RAWDRAW) $(SOUND) $(OUTS) parameters.o chash.o hook.o ../embeddedcommon/DFT32.o configs.o
colorchord : os_generic.o main.o dft.o decompose.o filter.o color.o notefinder.o util.o outdrivers.o $(RAWDRAW) $(SOUND) $(OUTS) parameters.o chash.o hook.o ../embeddedcommon/DFT32.o configs.o
gcc -o $@ $^ $(CFLAGS) $(LDLIBS) $(EXTRALIBS) $(RAWDRAWLIBS)

colorchord.exe : os_generic.c main.c dft.c decompose.c filter.c color.c sort.c notefinder.c util.c outdrivers.c DrawFunctions.c parameters.c chash.c WinDriver.c sound.c sound_null.c sound_win.c OutputVoronoi.c DisplayArray.c OutputLinear.c DisplayPie.c DisplayNetwork.c hook.c RecorderPlugin.c ../embeddedcommon/DFT32.c OutputCells.c configs.c
colorchord.exe : os_generic.c main.c dft.c decompose.c filter.c color.c notefinder.c util.c outdrivers.c DrawFunctions.c parameters.c chash.c WinDriver.c sound.c sound_null.c sound_win.c OutputVoronoi.c DisplayArray.c OutputLinear.c DisplayPie.c DisplayNetwork.c hook.c RecorderPlugin.c ../embeddedcommon/DFT32.c OutputCells.c configs.c
$(WINGCC) $(WINGCCFLAGS) -o $@ $^ $(WINLDFLAGS)


Expand Down
74 changes: 35 additions & 39 deletions colorchord2/decompose.c
@@ -1,6 +1,7 @@
//Copyright 2015 <>< Charles Lohr under the ColorChord License.

#include "decompose.h"
#include "notefinder.h"
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
Expand All @@ -10,7 +11,7 @@

#ifdef TURBO_DECOMPOSE

int DecomposeHistogram( float * histogram, int bins, float * out_means, float * out_amps, float * out_sigmas, int max_dists, double default_sigma, int iterations )
int DecomposeHistogram( float * histogram, int bins, struct NoteDists * out_dists, int max_dists, double default_sigma, int iterations )
{
//Step 1: Find the actual peaks.

Expand Down Expand Up @@ -41,35 +42,35 @@ int DecomposeHistogram( float * histogram, int bins, float * out_means, float *
offset = (0.5 - porpdiffN);
}

out_means[peak] = i + offset;
out_dists[peak].mean = i + offset;

//XXX XXX TODO Examine difference or relationship of "this" and "totaldiff"
out_amps[peak] = this * 4;
out_dists[peak].amp = this * 4;
//powf( totaldiff, .8) * 10;//powf( totaldiff, .5 )*4; //
out_sigmas[peak] = default_sigma;
out_dists[peak].sigma = default_sigma;
peak++;
}

for( i = peak; i < max_dists; i++ )
{
out_means[i] = -1;
out_amps[i] = 0;
out_sigmas[i] = default_sigma;
out_dists[i].mean = -1;
out_dists[i].amp = 0;
out_dists[i].sigma = default_sigma;
}

return peak;
}

//Yick: Doesn't match.. I guess it's only for debugging, right?
float CalcHistAt( float pt, int bins, float * out_means, float * out_amps, float * out_sigmas, int cur_dists )
float CalcHistAt( float pt, int bins, struct NoteDists * out_dists, int cur_dists )
{
int i;
float mark = 0.0;
for( i = 0; i < cur_dists; i++ )
{
float amp = out_amps[i];
float mean = out_means[i];
float var = out_sigmas[i];
float amp = out_dists[i].amp;
float mean = out_dists[i].mean;
float var = out_dists[i].sigma;

float x = mean - pt;
if( x < - bins / 2 ) x += bins;
Expand All @@ -83,11 +84,11 @@ float CalcHistAt( float pt, int bins, float * out_means, float * out_amps, float

#else

float AttemptDecomposition( float * histogram, int bins, float * out_means, float * out_amps, float * out_sigmas, int cur_dists );
float CalcHistAt( float pt, int bins, float * out_means, float * out_amps, float * out_sigmas, int cur_dists );
float AttemptDecomposition( float * histogram, int bins, struct NoteDists * out_dists, int cur_dists );
float CalcHistAt( float pt, int bins, struct NoteDists * out_dists, int cur_dists );


int DecomposeHistogram( float * histogram, int bins, float * out_means, float * out_amps, float * out_sigmas, int max_dists, double default_sigma, int iterations )
int DecomposeHistogram( float * histogram, int bins, struct NoteDists * out_dists, int max_dists, double default_sigma, int iterations )
{
//NOTE: The sigma may change depending on all sorts of things, maybe?

Expand All @@ -108,9 +109,9 @@ int DecomposeHistogram( float * histogram, int bins, float * out_means, float *
else if( went_up)
{
went_up = 0;
out_amps[sigs] = thishist / (default_sigma + 1);
out_sigmas[sigs] = default_sigma;
out_means[sigs] = i-0.5;
out_dists[sigs].amp = thishist / (default_sigma + 1);
out_dists[sigs].sigma = default_sigma;
out_dists[sigs].mean = i-0.5;
sigs++;
}
vhist = thishist;
Expand All @@ -119,7 +120,7 @@ int DecomposeHistogram( float * histogram, int bins, float * out_means, float *
return 0;

int iteration;
float errbest = AttemptDecomposition( histogram, bins, out_means, out_amps, out_sigmas, sigs );
float errbest = AttemptDecomposition( histogram, bins, out_dists, sigs );
int dropped[bins];
for( i = 0; i < bins; i++ )
{
Expand All @@ -130,49 +131,44 @@ int DecomposeHistogram( float * histogram, int bins, float * out_means, float *
{
if( dropped[iteration%sigs] ) continue;
//Tweak with the values until they are closer to what we want.
float backup_mean = out_means[iteration%sigs];
float backup_amps = out_amps[iteration%sigs];
float backup_sigmas = out_sigmas[iteration%sigs];
struct NoteDists backup = out_dists[iteration%sigs];

float mute = 20. / (iteration+20.);
#define RANDFN ((rand()%2)-0.5)*mute
//#define RANDFN ((rand()%10000)-5000.0) / 5000.0 * mute
// out_sigmas[iteration%sigs] += RANDFN;
out_means[iteration%sigs] += RANDFN;
out_amps[iteration%sigs] += RANDFN;
float err = AttemptDecomposition( histogram, bins, out_means, out_amps, out_sigmas, sigs );
// out_dists[iteration%sigs].sigma += RANDFN;
out_dists[iteration%sigs].mean += RANDFN;
out_dists[iteration%sigs].amp += RANDFN;
float err = AttemptDecomposition( histogram, bins, out_dists, sigs );
if( err > errbest )
{
out_means[iteration%sigs] = backup_mean;
out_amps[iteration%sigs] = backup_amps;
out_sigmas[iteration%sigs] = backup_sigmas;
out_dists[iteration%sigs] = backup;
}
else
{
if( out_amps[iteration%sigs] < 0.01 )
if( out_dists[iteration%sigs].amp < 0.01 )
{
dropped[iteration%sigs] = 1;
out_amps[iteration%sigs] = 0.0;
out_dists[iteration%sigs].amp = 0.0;
}
errbest = err;
}

}

// printf( "%f / %f = %f\n", origerr, errbest, origerr/errbest );

return sigs;
}

float CalcHistAt( float pt, int bins, float * out_means, float * out_amps, float * out_sigmas, int cur_dists )
float CalcHistAt( float pt, int bins, struct NoteDists * out_dists, int cur_dists )
{
int i;
float mark = 0.0;
for( i = 0; i < cur_dists; i++ )
{
float amp = out_amps[i];
float mean = out_means[i];
float var = out_sigmas[i];
float amp = out_dists[i].amp;
float mean = out_dists[i].mean;
float var = out_dists[i].sigma;

float x = mean - pt;
if( x < - bins / 2 ) x += bins;
Expand All @@ -183,16 +179,16 @@ float CalcHistAt( float pt, int bins, float * out_means, float * out_amps, float
return mark;
}

float AttemptDecomposition( float * histogram, int bins, float * out_means, float * out_amps, float * out_sigmas, int cur_dists )
float AttemptDecomposition( float * histogram, int bins, struct NoteDists * out_dists, int cur_dists )
{
int i, j;
float hist[bins];
memcpy( hist, histogram, sizeof(hist) );
for( i = 0; i < cur_dists; i++ )
{
float amp = out_amps[i];
float mean = out_means[i];
float var = out_sigmas[i];
float amp = out_dists[i].amp;
float mean = out_dists[i].mean;
float var = out_dists[i].sigma;

for( j = 0; j < bins; j++ )
{
Expand Down
6 changes: 4 additions & 2 deletions colorchord2/decompose.h
Expand Up @@ -3,9 +3,11 @@
#ifndef _DECOMPOSE_H
#define _DECOMPOSE_H

#include "notefinder.h"

//Decompose a histogram into a series of normal distributions.
int DecomposeHistogram( float * histogram, int bins, float * out_means, float * out_amps, float * out_sigmas, int max_dists, double default_sigma, int iterations );
float CalcHistAt( float pt, int bins, float * out_means, float * out_amps, float * out_sigmas, int cur_dists );
int DecomposeHistogram( float * histogram, int bins, struct NoteDists * out_dists, int max_dists, double default_sigma, int iterations );
float CalcHistAt( float pt, int bins, struct NoteDists * out_dists, int cur_dists );


#define TURBO_DECOMPOSE
Expand Down
14 changes: 7 additions & 7 deletions colorchord2/main.c
Expand Up @@ -306,13 +306,13 @@ int main(int argc, char ** argv)
//char sttdebug[1024];
//char * sttend = sttdebug;

for( i = 0; i < nf->dists; i++ )
for( i = 0; i < nf->dists_count; i++ )
{
CNFGPenX = (nf->dist_means[i] + 0.5) / freqbins * screenx; //Move over 0.5 for visual purposes. The means is correct.
CNFGPenY = 400-nf->dist_amps[i] * 150.0 / nf->dist_sigmas[i];
//printf( "%f %f\n", dist_means[i], dist_amps[i] );
sprintf( stt, "%f\n%f\n", nf->dist_means[i], nf->dist_amps[i] );
// sttend += sprintf( sttend, "%f/%f ",nf->dist_means[i], nf->dist_amps[i] );
CNFGPenX = (nf->dists[i].mean + 0.5) / freqbins * screenx; //Move over 0.5 for visual purposes. The means is correct.
CNFGPenY = 400-nf->dists[i].amp * 150.0 / nf->dists[i].sigma;
//printf( "%f %f\n", dists[i].mean, dists[i].amp );
sprintf( stt, "%f\n%f\n", nf->dists[i].mean, nf->dists[i].amp );
// sttend += sprintf( sttend, "%f/%f ",nf->dists[i].mean, nf->dists[i].amp );
CNFGDrawText( stt, 2 );
}
CNFGColor( 0xffffff );
Expand Down Expand Up @@ -366,7 +366,7 @@ int main(int argc, char ** argv)

for( i = -1; i < screenx; i++ )
{
float thishistval = CalcHistAt( (float)i/(float)screenx*freqbins-0.5, nf->freqbins, nf->dist_means, nf->dist_amps, nf->dist_sigmas, nf->dists );
float thishistval = CalcHistAt( (float)i/(float)screenx*freqbins-0.5, nf->freqbins, nf->dists, nf->dists_count );
if( i >= 0 )
CNFGTackSegment( i, 400-lasthistval * 250.0, i+1, 400-thishistval * 250.0 );
lasthistval = thishistval;
Expand Down
78 changes: 35 additions & 43 deletions colorchord2/notefinder.c
Expand Up @@ -10,7 +10,6 @@
#include "dft.h"
#include "filter.h"
#include "decompose.h"
#include "sort.h"
#include "DFT32.h"

struct NoteFinder * CreateNoteFinder( int spsRec )
Expand Down Expand Up @@ -151,18 +150,8 @@ printf( "%d %d %f %f %f\n", ret->freqbins, ret->octaves, ret->base_hz, ret->dft_
if( ret->folded_bins ) free( ret->folded_bins );
ret->folded_bins = calloc( 1, sizeof( float ) * ret->freqbins );


if( ret->dist_amps ) free( ret->dist_amps );
ret->dist_amps = calloc( 1, sizeof( float ) * maxdists );

if( ret->dist_means ) free( ret->dist_means );
ret->dist_means = calloc( 1, sizeof( float ) * maxdists );

if( ret->dist_sigmas ) free( ret->dist_sigmas );
ret->dist_sigmas = calloc( 1, sizeof( float ) * maxdists );

if( ret->dist_takens ) free( ret->dist_takens );
ret->dist_takens = calloc( 1, sizeof( unsigned char ) * maxdists );
if( ret->dists ) free ( ret->dists );
ret->dists = calloc( 1, sizeof( struct NoteDists ) * maxdists );

ret->ofreqs = freqs;
}
Expand All @@ -174,6 +163,12 @@ printf( "%d %d %f %f %f\n", ret->freqbins, ret->octaves, ret->base_hz, ret->dft_

}

int NoteDistsComparer(const void * a, const void * b)
{
float v = ((struct NoteDists *)a)->amp - ((struct NoteDists *)b)->amp;
return (0.f < v) - (v < 0.f);
}

void RunNoteFinder( struct NoteFinder * nf, const float * audio_stream, int head, int buffersize )
{
int i, j;
Expand Down Expand Up @@ -242,37 +237,35 @@ void RunNoteFinder( struct NoteFinder * nf, const float * audio_stream, int head

nf->FilterTime = OGGetAbsoluteTime();

memset( nf->dist_takens, 0, sizeof( unsigned char ) * maxdists );
nf->dists = DecomposeHistogram( nf->folded_bins, freqbins, nf->dist_means, nf->dist_amps, nf->dist_sigmas, maxdists, nf->default_sigma, nf->decompose_iterations );
for (i = 0; i < maxdists; i++)
{
nf->dists[i].taken = 0;
}
nf->dists_count = DecomposeHistogram( nf->folded_bins, freqbins, nf->dists, maxdists, nf->default_sigma, nf->decompose_iterations );

//Compress/normalize dist_amps
float total_dist = 0;

for( i = 0; i < nf->dists; i++ )
for( i = 0; i < nf->dists_count; i++ )
{
total_dist += nf->dist_amps[i];
total_dist += nf->dists[i].amp;
}
float muxer = nf->compress_coefficient/powf( total_dist * nf->compress_coefficient, nf->compress_exponenet );
total_dist = muxer;
for( i = 0; i < nf->dists; i++ )
for( i = 0; i < nf->dists_count; i++ )
{
nf->dist_amps[i]*=total_dist;
nf->dists[i].amp*=total_dist;
}

{
int dist_sorts[nf->dists];
SortFloats( dist_sorts, nf->dist_amps, nf->dists );
RemapFloats( dist_sorts, nf->dist_amps, nf->dists );
RemapFloats( dist_sorts, nf->dist_means, nf->dists );
RemapFloats( dist_sorts, nf->dist_sigmas, nf->dists );
}
qsort(nf->dists, nf->dists_count, sizeof(struct NoteDists), NoteDistsComparer);

nf->DecomposeTime = OGGetAbsoluteTime();


//We now have the positions and amplitudes of the normal distributions that comprise our spectrum. IN SORTED ORDER!
//dists = # of distributions
//dist_amps[] = amplitudes of the normal distributions
//dist_means[] = positions of the normal distributions
//dists_count = # of distributions
//dists[].amp = amplitudes of the normal distributions
//dists[].mean = positions of the normal distributions

//We need to use this in a filtered manner to obtain the "note" peaks
//note_peaks = total number of peaks.
Expand All @@ -283,26 +276,26 @@ void RunNoteFinder( struct NoteFinder * nf, const float * audio_stream, int head
//First try to find any close peaks.
for( i = 0; i < note_peaks; i++ )
{
for( j = 0; j < nf->dists; j++ )
for( j = 0; j < nf->dists_count; j++ )
{
if( !nf->dist_takens[j] && !nf->note_founds[i] && fabsloop( nf->note_positions[i], nf->dist_means[j], freqbins ) < nf->note_jumpability && nf->dist_amps[j] > 0.00001 ) //0.00001 for stability.
if( !nf->dists[j].taken && !nf->note_founds[i] && fabsloop( nf->note_positions[i], nf->dists[j].mean, freqbins ) < nf->note_jumpability && nf->dists[j].amp > 0.00001 ) //0.00001 for stability.
{
//Attach ourselves to this bin.
nf->note_peaks_to_dists_mapping[i] = j;
nf->dist_takens[j] = 1;
nf->dists[j].taken = 1;
if( nf->enduring_note_id[i] == 0 )
nf->enduring_note_id[i] = nf->current_note_id++;
nf->note_founds[i] = 1;

nf->note_positions[i] = avgloop( nf->note_positions[i], (1.-nf->note_attach_freq_iir), nf->dist_means[j], nf->note_attach_freq_iir, nf->freqbins);
nf->note_positions[i] = avgloop( nf->note_positions[i], (1.-nf->note_attach_freq_iir), nf->dists[j].mean, nf->note_attach_freq_iir, nf->freqbins);

//I guess you can't IIR this like normal.
////note_positions[i] * (1.-note_attach_freq_iir) + dist_means[j] * note_attach_freq_iir;
////note_positions[i] * (1.-note_attach_freq_iir) + dists[j].mean * note_attach_freq_iir;

nf->note_amplitudes[i] = nf->note_amplitudes[i] * (1.-nf->note_attach_amp_iir) + nf->dist_amps[j] * nf->note_attach_amp_iir;
nf->note_amplitudes[i] = nf->note_amplitudes[i] * (1.-nf->note_attach_amp_iir) + nf->dists[j].amp * nf->note_attach_amp_iir;
//XXX TODO: Consider: Always boost power, never reduce?
// if( dist_amps[i] > note_amplitudes[i] )
// note_amplitudes[i] = dist_amps[i];
// if( dists[i].amp > note_amplitudes[i] )
// note_amplitudes[i] = dists[i].amp;
}
}
}
Expand Down Expand Up @@ -350,16 +343,15 @@ void RunNoteFinder( struct NoteFinder * nf, const float * audio_stream, int head
nf->enduring_note_id[i] = 0;

//Find a new peak for this note.
for( j = 0; j < nf->dists; j++ )
for( j = 0; j < nf->dists_count; j++ )
{
if( !nf->dist_takens[j] && nf->dist_amps[j] > nf->note_minimum_new_distribution_value )
if( !nf->dists[j].taken && nf->dists[j].amp > nf->note_minimum_new_distribution_value )
{
nf->enduring_note_id[i] = nf->current_note_id++;
nf->dist_takens[j] = 1;
nf->note_amplitudes[i] = nf->dist_amps[j];//min_note_amplitude + dist_amps[j] * note_attach_amp_iir; //TODO: Should this jump?
nf->note_positions[i] = nf->dist_means[j];
nf->dists[j].taken = 1;
nf->note_amplitudes[i] = nf->dists[j].amp;//min_note_amplitude + dists[j].amp * note_attach_amp_iir; //TODO: Should this jump?
nf->note_positions[i] = nf->dists[j].mean;
nf->note_founds[i] = 1;
nf->dist_takens[j] = 1;
}
}
}
Expand Down

0 comments on commit 29d07b1

Please sign in to comment.