mirror of https://bitbucket.org/ausocean/av.git
Audiofiltering:
Add amplification filter which uses filter.Upper as factor for amplification
This commit is contained in:
parent
d029038db9
commit
b2d2a41fdc
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue