mirror of https://bitbucket.org/ausocean/av.git
Audiofiltering:
Increase the efficieny and stability of algorithms by making use of waitgroups and goroutines.
This commit is contained in:
parent
80ab5e4768
commit
8231379a51
|
@ -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()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue