Audiofiltering:

Add amplification filter which uses filter.Upper as factor for amplification
This commit is contained in:
David Sutton 2022-12-28 00:30:30 +10:30
parent d029038db9
commit b2d2a41fdc
2 changed files with 51 additions and 36 deletions

View File

@ -16,22 +16,21 @@ func main() {
start := time.Now()
// Read the audio data from the file.
input, _ := os.ReadFile("spike.pcm")
input, _ := os.ReadFile("sine.pcm")
// Create Buffer in struct format defined in pcm.go
format := pcm.BufferFormat{Rate: 44100, Channels: 1, SFormat: pcm.S16_LE}
buf := pcm.Buffer{Format: format, Data: input}
// Create a filter.
lp := pcm.Filter{BuffInfo: buf.Format, Type: pcm.LP, Upper: 10000, Taps: 50}
lp.Generate()
amp := pcm.Filter{BuffInfo: buf.Format, Type: pcm.AMPLIFIER, Upper: 3, Taps: 50}
// Apply the lowpass filter to the buffer.
output := lp.Apply(buf)
output := amp.Apply(buf)
// Save the transformed audio.
f, _ := os.Create("output.pcm")
f.Write(output[50 : len(output)-50])
f.Write(output)
// Display execution time.
fmt.Println("Finished execution. Total time:", time.Since(start))

View File

@ -13,10 +13,11 @@ type FilterType int
// Currently implemented filter types.
const (
LP FilterType = iota
HP
BP
BS
LOWPASS FilterType = iota
HIGHPASS
BANDPASS
BANDSTOP
AMPLIFIER
)
// Filter contains the specifications of the filter, as well as the coefficients to the filter function itself.
@ -48,7 +49,7 @@ func (filter *Filter) Generate() {
// Determine the type of filter to generate (based off filter.Type).
switch filter.Type {
case LP:
case LOWPASS:
// Create a lowpass filter with characteristics from struct.
size := filter.Taps + 1
@ -64,9 +65,9 @@ func (filter *Filter) Generate() {
}
filter.Coeffs[filter.Taps/2] = 2 * fd * winData[filter.Taps/2]
case HP:
case HIGHPASS:
// Create a Highpass filter with characteristics from struct.
// Create a HighIGHPASSass filter with characteristics from struct.
size := filter.Taps + 1
filter.Coeffs = make([]float64, size, size)
fd := (filter.Lower + 3000) / float64(filter.SampleRate)
@ -80,35 +81,35 @@ func (filter *Filter) Generate() {
}
filter.Coeffs[filter.Taps/2] = (1 - 2*fd) * winData[filter.Taps/2]
case BP:
case BANDPASS:
// Make Low and Highpass filters.
lp := Filter{Type: LP, SampleRate: filter.SampleRate, Upper: filter.Upper, Taps: filter.Taps}
hp := Filter{Type: HP, SampleRate: filter.SampleRate, Lower: filter.Lower, Taps: filter.Taps}
lp.Generate()
hp.Generate()
// Make Low and HighIGHPASSass filters.
lowpass := Filter{Type: LOWPASS, SampleRate: filter.SampleRate, Upper: filter.Upper, Taps: filter.Taps}
hIGHPASS := Filter{Type: HIGHPASS, SampleRate: filter.SampleRate, Lower: filter.Lower, Taps: filter.Taps}
lowpass.Generate()
hIGHPASS.Generate()
// Convolve lowpass filter with highpass filter to get bandpass filter.
// Convolve lowpass filter with highIGHPASSass filter to get bandpass filter.
var wg sync.WaitGroup
ch := make(chan []float64)
wg.Add(1)
go Convolve(lp.Coeffs, hp.Coeffs, &wg, ch)
go Convolve(lowpass.Coeffs, hIGHPASS.Coeffs, &wg, ch)
wg.Wait()
filter.Coeffs = <-ch
case BS:
case BANDSTOP:
// Make Low and Highpass filters.
lp := Filter{Type: LP, SampleRate: filter.SampleRate, Upper: filter.Lower, Taps: filter.Taps}
hp := Filter{Type: HP, SampleRate: filter.SampleRate, Lower: filter.Upper, Taps: filter.Taps}
lp.Generate()
hp.Generate()
// Make Low and HighIGHPASSass filters.
lowpass := Filter{Type: LOWPASS, SampleRate: filter.SampleRate, Upper: filter.Lower, Taps: filter.Taps}
hIGHPASS := Filter{Type: HIGHPASS, SampleRate: filter.SampleRate, Lower: filter.Upper, Taps: filter.Taps}
lowpass.Generate()
hIGHPASS.Generate()
// Add lowpass filter to highpass filter to get bandstop filter.
// Add lowpass filter to highIGHPASSass filter to get bandstop filter.
size := filter.Taps + 1
filter.Coeffs = make([]float64, size, size)
for i := range lp.Coeffs {
filter.Coeffs[i] = lp.Coeffs[i] + hp.Coeffs[i]
for i := range lowpass.Coeffs {
filter.Coeffs[i] = lowpass.Coeffs[i] + hIGHPASS.Coeffs[i]
}
}
@ -130,13 +131,28 @@ func (filter *Filter) Apply(b Buffer) []byte {
inputAsFloat[i] /= (32767)
}
// Convolve input with filter.
var wg sync.WaitGroup
ch := make(chan []float64, 1)
wg.Add(1)
go Convolve(inputAsFloat, filter.Coeffs, &wg, ch)
wg.Wait()
convolution := <-ch
var convolution []float64
// Check if filter type is frequency filter or amplifier.
if filter.Type == AMPLIFIER {
convolution = make([]float64, len(inputAsFloat))
for i := range inputAsFloat {
convolution[i] = inputAsFloat[i] * filter.Upper
// Stop audio artifacting by clipping outputs
if convolution[i] > 1 {
convolution[i] = 1
} else if convolution[i] < -1 {
convolution[i] = -1
}
}
} else {
// Convolve input with filter.
var wg sync.WaitGroup
ch := make(chan []float64, 1)
wg.Add(1)
go Convolve(inputAsFloat, filter.Coeffs, &wg, ch)
wg.Wait()
convolution = <-ch
}
// Convert convolution output back to bytes.
var output []byte