shithub: libsamplerate

Download patch

ref: b64889efb02aab61b670ed228e5790c865b053e2
parent: b16609338307966dd259a871d3cc94a0294b51e0
author: Erik de Castro Lopo <erikd@miles>
date: Sun Oct 31 17:30:24 EST 2004

Sketch out skeleton of program fir_interp.

--- /dev/null
+++ b/FIR-POLY/Makefile
@@ -1,0 +1,40 @@
+TARGETS = fir_interp
+
+CXX = g++
+CXXFLAGS = -g -O3 -Wall -W -Werror -Wstrict-prototypes -Wmissing-prototypes
+
+GMATH_INC = $(shell pkg-config --cflags GMath)
+GMATH_LIB = $(shell pkg-config --libs GMath)
+
+FFTW_INC = $(shell pkg-config --cflags fftw3)
+FFTW_LIB = $(shell pkg-config --libs fftw3)
+
+
+
+all: $(TARGETS)
+
+clean:
+	rm -f $(TARGETS) *.o
+
+check: $(TARGETS)
+	./fir_interp
+
+fir_interp: fir_interp.o mag_spectrum.o demin.o
+	$(CXX) $(CXXFLAGS) $+ $(GMATH_LIB) $(FFTW_LIB) -o $@
+
+#---------------------------------------------------------------------
+
+fir_interp.o : fir_interp.cc mag_spectrum.hh
+	$(CXX) $(CXXFLAGS) $(GMATH_INC) -c fir_interp.cc -o $@
+
+mag_spectrum.o : mag_spectrum.cc mag_spectrum.hh
+	$(CXX) $(CXXFLAGS) $(FFTW_INC) -c mag_spectrum.cc -o $@
+
+demin.o : demin.cc
+	$(CXX) $(CXXFLAGS) $(GMATH_INC) -c $+ -o $@
+
+# Do not edit or modify anything in this comment block.
+# The arch-tag line is a file identity tag for the GNU Arch
+# revision control system.
+#
+# arch-tag: 34b6b183-dca1-4085-9089-c8b7d5b09099
--- /dev/null
+++ b/FIR-POLY/demin.cc
@@ -1,0 +1,268 @@
+/*
+** Copyright (C) 1998-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** The copyright above and this notice must be preserved in all
+** copies of this source code. The copyright above does not
+** evidence any actual or intended publication of this source code.
+**
+** This is unpublished proprietary trade secret of Erik de Castro
+** Lopo.  This source code may not be copied, disclosed,
+** distributed, demonstrated or licensed except as authorized by
+** Erik de Castro Lopo.
+**
+** No part of this program or publication may be reproduced,
+** transmitted, transcribed, stored in a retrieval system,
+** or translated into any language or computer language in any
+** form or by any means, electronic, mechanical, magnetic,
+** optical, chemical, manual, or otherwise, without the prior
+** written permission of Erik de Castro Lopo.
+*/
+
+#include	<stdio.h>
+#include	<unistd.h>
+
+#include	<Minimize.hh>
+#include	<PsuedoRand.hh>
+
+class	DEmin
+{	private :
+		u_int		PopSize, FuncCalcs, Generations ;
+
+		PsuedoRand	Rand ;
+
+		GMatrix		*MainVector, *Vector2 ;
+		double		*MainCost, *Cost2 ;
+		double		*ScaleFactor, *ScaleFactor2 ;
+		double		*Crossover, *Crossover2 ;
+
+		MinFunc		Function ;
+
+	public :
+				DEmin	(void) ;
+				~DEmin	(void) ;
+
+		void	Setup	(MinFunc func, const GMatrix& start, u_int popsize, double range, u_long seed) ;
+
+		GMatrix	Minimize (double tol, u_int maxgen) ;
+
+		void	PrintStats	(void) ;
+
+} ; // class DEmin
+
+//======================================================================================
+
+inline
+void	Swap	(GMatrix **a, GMatrix **b)
+{	GMatrix *temp ;
+	temp = *a ; *a = *b ; *b = temp ;
+} ; //
+
+inline void
+Swap	(double **a, double **b)
+{	double *temp ;
+	temp = *a ; *a = *b ; *b = temp ;
+} ; // Swap
+
+inline double
+Max	(double a, double b)
+{	return (a > b) ? a : b ;
+} ; // Max
+
+inline double
+Min	(double a, double b)
+{	return (a < b) ? a : b ;
+} ; // Max
+
+//======================================================================================
+
+double
+MinDiffEvol (MinFunc Function, GMatrix& start, double Ftol, double range, u_long seedval)
+{	DEmin		*pfmin ;
+	u_int		dimensions ;
+
+	dimensions = start.GetElements () ;
+
+	pfmin = new DEmin ;
+
+	pfmin -> Setup (Function, start, dimensions * 5, range, seedval) ;
+
+	Ftol = (Ftol < 1e-8) ? 1e-8 : Ftol ;
+
+	start = pfmin -> Minimize (Ftol, dimensions * 5000) ;
+
+	delete	pfmin ;
+
+	return Function (start) ;
+} ; // MinDiffEvol
+
+
+//======================================================================================
+
+DEmin::DEmin	(void)
+{	PopSize		= 0 ;
+	FuncCalcs	= 0 ;
+	Generations	= 0 ;
+	MainVector	= NULL ;
+	MainCost	= NULL ;
+	ScaleFactor	= NULL ;
+	Crossover	= NULL ;
+	Vector2		= NULL ;
+	Cost2		= NULL ;
+	ScaleFactor2 = NULL ;
+	Crossover2	= NULL ;
+} ; // DEmin constructor
+
+DEmin::~DEmin	(void)
+{	if (PopSize)
+	{	delete [] MainVector ;
+		delete MainCost ;
+		delete ScaleFactor ;
+		delete Crossover ;
+		delete [] Vector2 ;
+		delete Cost2 ;
+		delete ScaleFactor2 ;
+		delete Crossover2 ;
+		} ;
+	PopSize = 0 ;
+} ; // DEmin destructor
+
+void
+DEmin::Setup (MinFunc func, const GMatrix& start, u_int popsize, double range, u_long seed)
+{	u_int		k ;
+	u_short		rows, cols ;
+
+	Generations = 0 ;
+	Function = func ;
+
+	PopSize = (popsize < 2) ? popsize + 2 : popsize ;
+
+	MainVector	= new GMatrix [PopSize] ;
+	MainCost	= new double [PopSize] ;
+	ScaleFactor	= new double [PopSize] ;
+	Crossover	= new double [PopSize] ;
+	Vector2		= new GMatrix [PopSize] ;
+	Cost2		= new double [PopSize] ;
+	ScaleFactor2 = new double [PopSize] ;
+	Crossover2	= new double [PopSize] ;
+
+	Rand.Seed (seed + 1234567) ;
+
+	rows = start.GetRows () ;
+	cols = start.GetCols () ;
+
+	GMatrix::PsuedoRandSeed (123123) ;
+
+	if (IsComplex (start))
+		for (k = 0 ; k < PopSize ; k++)
+		{	MainVector [k].SetSizeComplex (rows, cols) ;
+			MainVector [k].PsuedoRandomize () ;
+			MainVector [k] = (2.0 * range) * (MainVector [k] - Complex (0.5, 0.5)) ;
+			}
+	else
+		for (k = 0 ; k < PopSize ; k++)
+		{	MainVector [k].SetSizeDouble (rows, cols) ;
+			MainVector [k].PsuedoRandomize () ;
+			MainVector [k] = (2.0 * range) * (MainVector [k] - 0.5) ;
+			} ;
+
+	MainVector [0] = start ;	// Must include given vector.
+
+	for (k = 0 ; k < PopSize ; k++)
+	{	MainCost [k] = Function (MainVector [k]) ;
+		FuncCalcs ++ ;
+		ScaleFactor [k] = 1.2 * Rand.UDDouble () ;
+		Crossover [k] = Rand.UDDouble () ;
+		} ;
+
+	return ;
+} ; // DEmin::Setup
+
+GMatrix
+DEmin::Minimize (double Ftol, u_int maxgen)
+{	u_int		k, a, b, c ;
+	GMatrix		temp ;
+	double		scalefactor, crossover, cost, improvement, best ;
+
+	improvement = 100 * Ftol ;
+	best = 10e10 ;
+
+	while (Generations < maxgen && best > Ftol)
+	{	Swap (&MainVector, &Vector2) ;
+		Swap (&MainCost, &Cost2) ;
+		Swap (&ScaleFactor, &ScaleFactor2) ;
+		Swap (&Crossover, &Crossover2) ;
+
+		improvement = 0.0 ;
+
+		for (k = 0 ; k < PopSize ; k++)
+		{	do
+				a = u_int (double (PopSize) * Rand.UDDouble ()) ;
+			while 	(a == k) ;
+			do
+				b = u_int (double (PopSize) * Rand.UDDouble ()) ;
+			while	(b == k || b == a) ;
+			do
+				c = u_int (double (PopSize) * Rand.UDDouble ()) ;
+			while	(c == k || c == a || c == b) ;
+
+if (a >= PopSize)	{	printf ("a - very bad.\n") ;	exit (0) ; } ;
+if (b >= PopSize)	{	printf ("b - very bad.\n") ;	exit (0) ; } ;
+if (c >= PopSize)	{	printf ("c - very bad.\n") ;	exit (0) ; } ;
+
+			scalefactor = 0.5 * (ScaleFactor2 [b] + ScaleFactor2 [c]) ;
+
+			temp = Vector2 [a] + scalefactor * (Vector2 [b] - Vector2 [c]) ;
+
+			crossover = 0.5 * (Crossover2 [k] + Crossover2 [a]) ;
+
+			temp.CrossOver (Vector2 [k], crossover) ;
+
+			cost = Function (temp) ;
+			FuncCalcs ++ ;
+
+			if (cost < Cost2 [k])
+			{	MainVector	[k] = temp ;
+				MainCost	[k] = cost ;
+				ScaleFactor [k] = scalefactor ;
+				Crossover	[k] = crossover ;
+				improvement = 0.5 * (improvement + Max (improvement, Cost2 [k] - cost)) ;
+				best = Min (best, cost) ;
+				}
+			else
+			{	MainVector	[k] = Vector2 [k] ;
+				MainCost	[k] = Cost2 [k] ;
+				ScaleFactor	[k] = ScaleFactor2 [k] ;
+				Crossover	[k] = Crossover2 [k] ;
+				} ;	// if
+			} ; // for k
+
+		Generations ++ ;
+		} ; // while
+
+	// Now find best vector.
+
+	for (a = 0, k = 1 ; k < PopSize ; k++)
+		if (MainCost [k] < MainCost [a])
+			a = k ;
+	temp = MainVector [a] ;
+
+	return temp ;
+} ; // DEmin::Minimize
+
+void
+DEmin::PrintStats (void)
+{	printf ("Generations          : %8d\n", Generations) ;
+	printf ("Function evaluations : %8d\n", FuncCalcs) ;
+	putchar ('\n') ;
+} ; // DEmin::PrintStats
+
+//======================================================================================
+
+
+
+// Do not edit or modify anything in this comment block.
+// The arch-tag line is a file identity tag for the GNU Arch
+// revision control system.
+//
+// arch-tag: e874ad11-7294-4757-9370-fd1e6e1261d0
+
--- /dev/null
+++ b/FIR-POLY/fir_interp.cc
@@ -1,0 +1,109 @@
+/*
+** Copyright (C) 2004 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** The copyright above and this notice must be preserved in all
+** copies of this source code. The copyright above does not
+** evidence any actual or intended publication of this source code.
+**
+** This is unpublished proprietary trade secret of Erik de Castro
+** Lopo.  This source code may not be copied, disclosed,
+** distributed, demonstrated or licensed except as authorized by
+** Erik de Castro Lopo.
+**
+** No part of this program or publication may be reproduced,
+** transmitted, transcribed, stored in a retrieval system,
+** or translated into any language or computer language in any
+** form or by any means, electronic, mechanical, magnetic,
+** optical, chemical, manual, or otherwise, without the prior
+** written permission of Erik de Castro Lopo.
+*/
+
+
+#include <cstdio>
+#include <cstdlib>
+#include <ctime>
+#include <cstring>
+#include <complex>
+
+#include <GMatrix.hh>
+#include <Minimize.hh>
+
+#include "mag_spectrum.hh"
+
+
+#define	ARRAY_LEN(x)	(sizeof (x) / sizeof ((x) [0]))
+
+/*
+** Number of half cycles of impulse response to the left and right
+** of the center.
+**		left_half_offset <= right_half_cycles
+*/
+
+// static int left_half_cycles = 5 ;
+// static int right_half_cycles = 15 ;
+
+
+typedef struct
+{
+	double sinc_time_fudge ;
+
+	/* Window coefficients (all in range [0, 1]). */
+	double left_ak [5], right_ak [5] ;
+
+} FIR_PARAMS ;
+
+static double fir_error (const GMatrix& gm) ;
+
+int
+main (void)
+{	static double data [32] ;
+	GMatrix gm_start ;
+	double error ;
+	int k, param_count ;
+	
+	param_count = sizeof (FIR_PARAMS) / sizeof (double) ;
+
+	srandom (time (NULL)) ;
+	for (k = 0 ; k < param_count ; k++)
+		data [k] = 3.0 * ((1.0 * random ()) / INT_MAX - 0.5) ;
+
+	gm_start = GMatrix (param_count, 1, data) ;
+
+	fir_error (gm_start) ;
+
+	do
+		error = MinDiffEvol (fir_error, gm_start, 1e-15, 2.0, random ()) ;
+	while (error > 10.0) ;
+
+	printf ("error : %f\n", error) ;
+
+	return 0 ;
+} /* main */
+
+/*==============================================================================
+*/
+
+static double
+fir_error (const GMatrix& gm)
+{	FIR_PARAMS params ;
+	double error = 0.0 ;
+	unsigned param_count ;
+	
+	
+	param_count = sizeof (params) / sizeof (double) ;
+
+	if (gm.GetData	(param_count, (double*) &params) != param_count)
+	{	printf ("\n\nError : GetData should return 2.\n") ;
+		exit (1) ;
+		} ;
+
+	return error ;
+} /* fir_error */
+
+/*
+** Do not edit or modify anything in this comment block.
+** The following line is a file identity tag for the GNU Arch
+** revision control system.
+**
+** arch-tag: 3ce7ca6f-394e-432c-aeaa-f228afc05afd
+*/
--- /dev/null
+++ b/FIR-POLY/mag_spectrum.cc
@@ -1,0 +1,62 @@
+/*
+** Copyright (C) 2004 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** The copyright above and this notice must be preserved in all
+** copies of this source code. The copyright above does not
+** evidence any actual or intended publication of this source code.
+**
+** This is unpublished proprietary trade secret of Erik de Castro
+** Lopo.  This source code may not be copied, disclosed,
+** distributed, demonstrated or licensed except as authorized by
+** Erik de Castro Lopo.
+**
+** No part of this program or publication may be reproduced,
+** transmitted, transcribed, stored in a retrieval system,
+** or translated into any language or computer language in any
+** form or by any means, electronic, mechanical, magnetic,
+** optical, chemical, manual, or otherwise, without the prior
+** written permission of Erik de Castro Lopo.
+*/
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cmath>
+
+#include <fftw3.h>
+
+void
+mag_spectrum (double *input, int len, double *magnitude, double scale)
+{	static fftw_plan plan = NULL ;
+
+	double	maxval ;
+	int		k ;
+
+	if (input == NULL || magnitude == NULL)
+		return ;
+
+	if (plan == NULL)
+	{	plan = fftw_plan_r2r_1d (len, input, magnitude, FFTW_R2HC, FFTW_ESTIMATE | FFTW_PRESERVE_INPUT) ;
+		if (plan == NULL)
+		{	printf ("%s : line %d : create plan failed.\n", __FILE__, __LINE__) ;
+			exit (1) ;
+			} ;
+		} ;
+
+	fftw_execute (plan) ;
+
+	/* (k < N/2 rounded up) */
+	maxval = 0.0 ;
+	for (k = 0 ; k < len / 2 ; k++)
+		magnitude [k] = scale * sqrt (magnitude [k] * magnitude [k] + magnitude [len - k - 1] * magnitude [len - k - 1]) ;
+
+	memset (magnitude + len / 2, 0, len / 2 * sizeof (magnitude [0])) ;
+
+	return ;
+} /* mag_spectrum */
+
+// Do not edit or modify anything in this comment block.
+// The following line is a file identity tag for the GNU Arch
+// revision control system.
+//
+// arch-tag: 58aa43ee-b8e1-4178-8861-7621399fa049
--- /dev/null
+++ b/FIR-POLY/mag_spectrum.hh
@@ -1,0 +1,27 @@
+/*
+** Copyright (C) 2004 Erik de Castro Lopo <erikd@mega-nerd.com>
+**
+** The copyright above and this notice must be preserved in all
+** copies of this source code. The copyright above does not
+** evidence any actual or intended publication of this source code.
+**
+** This is unpublished proprietary trade secret of Erik de Castro
+** Lopo.  This source code may not be copied, disclosed,
+** distributed, demonstrated or licensed except as authorized by
+** Erik de Castro Lopo.
+**
+** No part of this program or publication may be reproduced,
+** transmitted, transcribed, stored in a retrieval system,
+** or translated into any language or computer language in any
+** form or by any means, electronic, mechanical, magnetic,
+** optical, chemical, manual, or otherwise, without the prior
+** written permission of Erik de Castro Lopo.
+*/
+
+void mag_spectrum (double *input, int len, double *magnitude, double scale) ;
+
+// Do not edit or modify anything in this comment block.
+// The following line is a file identity tag for the GNU Arch
+// revision control system.
+//
+// arch-tag: cc5db1c8-4c67-49f7-9c2f-6c5021a69970