Audiofiltering:

Increase the efficieny and stability of algorithms by making use of waitgroups and goroutines.
This commit is contained in:
ausocean-david 2022-12-15 00:42:44 +10:30
parent 80ab5e4768
commit 8231379a51
1 changed files with 70 additions and 115 deletions

View File

@ -6,9 +6,9 @@ import(
"os" "os"
"encoding/binary" "encoding/binary"
"github.com/mjibson/go-dsp/fft" "github.com/mjibson/go-dsp/fft"
// "github.com/mjibson/go-dsp/window"
"math/cmplx" "math/cmplx"
"time" "time"
"sync"
) )
// define constants used in the generation of the sound waves // define constants used in the generation of the sound waves
@ -21,18 +21,27 @@ const(
func main() { func main() {
var wg1, wg2 sync.WaitGroup
start := time.Now() start := time.Now()
// generate two sine waves with different frequencies to test frequency response // generate sine waves with different frequencies to test frequency response
n := 2 n := 100
wg1.Add(n)
audio := make([][]float64, n) audio := make([][]float64, n)
// for i:=0; i<n; i++ { for i:=0; i<n; i++ {
// audio[i] = generate(float64((i)*(22000/n))) go func(i int, audio [][]float64, wg *sync.WaitGroup) {
// } audio[i] = generate(float64((i)*(22000/n)))
audio[0] = generate(2000) wg.Done()
audio[1] = generate(10000) } (i, audio, &wg1)
}
// create filter
filterLen := 500
wg2.Add(1)
ch := make(chan []float64, 1)
go LowPass(filterLen, 5000, &wg2, ch)
wg1.Wait()
// combine audio // combine audio
combinedAudio := make([]float64, length) combinedAudio := make([]float64, length)
for i := range audio[0] { for i := range audio[0] {
@ -41,25 +50,19 @@ func main() {
combinedAudio[i] += audio[j][i] combinedAudio[i] += audio[j][i]
} }
} }
fmt.Println("audio generation:", time.Since(start))
start = time.Now()
filterLen := 500 wg2.Wait()
filter := LowPass(filterLen, 20000) filter := <- ch
fmt.Println("audio filter generation:", time.Since(start))
start = time.Now()
// convolve sinc with audio // convolve sinc with audio
filteredAudio := Convolve(combinedAudio, filter) wg1.Add(2)
fmt.Println("convolution:", time.Since(start)) go SaveAudioData(combinedAudio, "unfiltered", &wg1)
start = time.Now() wg2.Add(1)
SaveAudioData(filteredAudio, "lowpass") filteredAudio := Convolve(combinedAudio, filter, &wg2)
SaveAudioData(combinedAudio, "unfiltered") wg2.Wait()
fmt.Println("audio saving:", time.Since(start)) go SaveAudioData(filteredAudio, "lowpass", &wg1)
start = time.Now()
// SaveAudioData(filter, "test")
wg1.Wait()
fmt.Println(time.Since(start)) fmt.Println(time.Since(start))
} }
@ -77,104 +80,47 @@ func generate(Frequency float64) []float64 {
// generate samples and write to file // generate samples and write to file
for i := 0; i < int(nsamps); i++ { for i := 0; i < int(nsamps); i++ {
samp[i] = math.Sin(angle * Frequency * float64(i)) samp[i] = math.Sin(angle * Frequency * float64(4*i))
} }
return samp return samp
} }
func TopFive (a []float64) (topVal []float64, topI []int) { func LowPass (n int, fc float64, wg *sync.WaitGroup, ch chan []float64) {
length := 5
runMax := make([]float64, length, length)
indices := make([]int, length, length)
for i:=range a {
switch {
case a[i] > runMax[0]:
for i:=0; i<4; i++ {
runMax[4-i] = runMax[4-(1+i)]
indices[4-i] = indices[4-(1+i)]
}
runMax[0] = a[i]
indices[0] = i
case a[i] > runMax[1]:
for i:=0; i<3; i++ {
runMax[4-i] = runMax[4-(1+i)]
indices[4-i] = indices[4-(1+i)]
}
runMax[1] = a[i]
indices[1] = i
case a[i] > runMax[2]:
for i:=0; i<2; i++ {
runMax[4-i] = runMax[4-(1+i)]
indices[4-i] = indices[4-(1+i)]
}
runMax[2] = a[i]
indices[2] = i
case a[i] > runMax[3]:
for i:=0; i<1; i++ {
runMax[4-i] = runMax[4-(1+i)]
indices[4-i] = indices[4-(1+i)]
}
runMax[3] = a[i]
indices[3] = i
}
}
return runMax, indices
}
func Max (a []float64) float64 {
var runMax float64 = -1
for i:= range a {
if math.Abs(a[i]) > runMax {
runMax = math.Abs(a[i])
}
}
return runMax
}
func LowPass (n int, fc float64) (filter []float64) {
// n is number of points on either side of 0 // n is number of points on either side of 0
// determine digital frequency equivalent for fc // determine digital frequency equivalent for fc
fd := fc/(2*SampleRate) fd := (fc*4)/(2*SampleRate)
// create sinc function // create sinc function
return Sinc(n, fd) ch <- Sinc(n, fd)
wg.Done()
} }
func Convolve (x, h []float64) []float64 { func Convolve (x, h []float64, wg *sync.WaitGroup) []float64 {
convLen := len(x)+len(h) convLen := len(x)+len(h)
y := make([]float64, convLen) y := make([]float64, convLen)
for n:=0; n<convLen; n++ { for n:=0; n<convLen; n++ {
go SubConvolve(n, x, h, y) wg.Add(1)
go func (n int, x, h, y []float64, wg *sync.WaitGroup) {
var sum float64 = 0
for k:=0; k<len(x); k++ {
if n-k >= 0 && n-k < len(h) {
sum += x[k]*h[n-k]
}
}
y[n] = sum
wg.Done()
}(n, x, h, y, wg)
} }
wg.Done()
return y return y
} }
func SubConvolve (n int, x, h, y []float64) { func SaveAudioData (signal []float64, fileName string, wg1 *sync.WaitGroup) {
var sum float64 = 0
for k:=0; k<len(x); k++ {
if n-k >= 0 && n-k < len(h) {
sum += x[k]*h[n-k]
}
}
y[n] = sum
}
func SaveAudioData (signal []float64, fileName string) {
// compute fft of signal // compute fft of signal
FFTaudio := fft.FFTReal(signal) FFTaudio := fft.FFTReal(signal)
@ -188,23 +134,32 @@ func SaveAudioData (signal []float64, fileName string) {
for i := range spectrum { for i := range spectrum {
spectrum[i] = spectrum[i]/maximum spectrum[i] = spectrum[i]/maximum
} }
// spectrumAlt := spectrum[0:length/2 + 1]
// SAVE // SAVE
file := fileName + ".txt" wg1.Add(2)
f, _ := os.Create(file) go func (fileName string, length int, spectrum []float64, wg1 *sync.WaitGroup) {
for i:=0; i<20000; i++ { file := fileName + ".txt"
fmt.Fprintf(f, "%v\n", /*10*math.Log10*/(spectrum[i])) f, _ := os.Create(file)
} for i:=0; i<20000; i++ {
fmt.Printf("Saved spectrum values to: %s\n", fileName) fmt.Fprintf(f, "%v\n", /*10*math.Log10*/(spectrum[i]))
}
fmt.Printf("Saved spectrum values to: %s\n", fileName)
wg1.Done()
}(fileName, 44100, spectrum, wg1)
file = fileName + ".bin" go func (fileName string, signal []float64, wg1 *sync.WaitGroup) {
f, _ = os.Create(file) file := fileName + ".bin"
var buf [8]byte f, _ := os.Create(file)
for i:=0; i<length; i++ { var buf [8]byte
binary.LittleEndian.PutUint32(buf[:], math.Float32bits(float32(signal[i]))) for i:=0; i<length; i++ {
_, _ = f.Write(buf[:]) binary.LittleEndian.PutUint32(buf[:], math.Float32bits(float32(signal[i])))
} _, _ = f.Write(buf[:])
}
fmt.Printf("Saved binary values to: %s\n", fileName)
wg1.Done()
}(fileName, signal, wg1)
wg1.Done()
} }