-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from pablodz/dev
resampler: linear and decimation
- Loading branch information
Showing
18 changed files
with
429 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package main | ||
|
||
import ( | ||
"os" | ||
|
||
"github.com/pablodz/sopro/pkg/audioconfig" | ||
"github.com/pablodz/sopro/pkg/cpuarch" | ||
"github.com/pablodz/sopro/pkg/encoding" | ||
"github.com/pablodz/sopro/pkg/fileformat" | ||
"github.com/pablodz/sopro/pkg/resampler" | ||
"github.com/pablodz/sopro/pkg/transcoder" | ||
) | ||
|
||
func main() { | ||
|
||
// Open the input file | ||
in, err := os.Open("./internal/samples/v1_16b_16000.wav") | ||
if err != nil { | ||
panic(err) | ||
} | ||
defer in.Close() | ||
|
||
// Create the output file | ||
out, err := os.Create("./internal/samples/v1_16b_8000.wav") | ||
if err != nil { | ||
panic(err) | ||
} | ||
defer out.Close() | ||
|
||
// create a transcoder | ||
t := &transcoder.Transcoder{ | ||
MethodR: resampler.LINEAR_INTERPOLATION, | ||
SourceConfigs: transcoder.TranscoderAudioConfig{ | ||
Endianness: cpuarch.LITTLE_ENDIAN, | ||
}, | ||
TargetConfigs: transcoder.TranscoderAudioConfig{ | ||
Endianness: cpuarch.LITTLE_ENDIAN, | ||
}, | ||
SizeBuffer: 1024, | ||
Verbose: true, | ||
} | ||
|
||
// Transcode the file | ||
err = t.Wav2Wav( | ||
&transcoder.AudioFileIn{ | ||
Data: in, | ||
AudioFileGeneral: transcoder.AudioFileGeneral{ | ||
Format: fileformat.AUDIO_WAV, | ||
Config: audioconfig.WavConfig{ | ||
BitDepth: 16, | ||
Channels: 1, | ||
Encoding: encoding.SPACE_LINEAR, // ulaw is logarithmic | ||
SampleRate: 16000, | ||
}, | ||
}, | ||
}, | ||
&transcoder.AudioFileOut{ | ||
Data: out, | ||
AudioFileGeneral: transcoder.AudioFileGeneral{ | ||
Format: fileformat.AUDIO_WAV, | ||
Config: audioconfig.WavConfig{ | ||
BitDepth: 16, | ||
Channels: 1, | ||
Encoding: encoding.SPACE_LINEAR, | ||
SampleRate: 8000, | ||
}, | ||
}, | ||
}, | ||
) | ||
|
||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package downsampler | ||
package resampler | ||
|
||
import "errors" | ||
|
||
|
2 changes: 1 addition & 1 deletion
2
pkg/downsampler/downsampler_test.go → pkg/resampler/downsampler_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package downsampler | ||
package resampler | ||
|
||
import ( | ||
"reflect" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package resampler | ||
|
||
func LinearInterpolation[T int16 | int32 | int64 | int | byte](data []T, ratio float64) ([]T, error) { | ||
|
||
// Calculate the length of the resampled data slice. | ||
resampledLength := int(float64(len(data)) / ratio) | ||
|
||
// Preallocate the resampled data slice with the correct size. | ||
resampledData := make([]T, resampledLength) | ||
|
||
// Iterate over the original data, interpolating new samples as necessary to | ||
// resample the data at the target sample rate. | ||
for i := 0; i < len(data)-1; i++ { | ||
// Calculate the interpolated value between the current and next samples. | ||
interpolatedValue := T((float64(data[i]) + float64(data[i+1])) / 2) | ||
resampledData[int(float64(i)/ratio)] = interpolatedValue | ||
|
||
// Skip the next sample if necessary. | ||
if ratio > 1.0 { | ||
i += int(ratio) - 1 | ||
} | ||
} | ||
|
||
return resampledData, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package resampler | ||
|
||
import "testing" | ||
|
||
func TestLinearInterpolation(t *testing.T) { | ||
data := []int16{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} | ||
expected := []int16{1, 3, 5, 7, 9} | ||
ratio := float64(16000) / float64(8000) | ||
resampledData, err := LinearInterpolation(data, ratio) | ||
if err != nil { | ||
t.Errorf("Expected no error, got %v", err) | ||
} | ||
if !testEq(resampledData, expected) { | ||
t.Errorf("Expected %v, got %v", expected, resampledData) | ||
} | ||
} | ||
|
||
func TestLinearInterpolation2(t *testing.T) { | ||
data := []int16{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} | ||
expected := []int16{1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, 0, 0} | ||
ratio := float64(8000) / float64(16000) | ||
resampledData, err := LinearInterpolation(data, ratio) | ||
if err != nil { | ||
t.Errorf("Expected no error, got %v", err) | ||
} | ||
if !testEq(resampledData, expected) { | ||
t.Errorf("Expected %v, got %v", expected, resampledData) | ||
} | ||
} | ||
|
||
// testEq is a helper function to compare two slices of int16 values. | ||
func testEq[T int16 | int32 | int64 | int](a, b []T) bool { | ||
if a == nil && b == nil { | ||
return true | ||
} | ||
if a == nil || b == nil { | ||
return false | ||
} | ||
if len(a) != len(b) { | ||
return false | ||
} | ||
for i := range a { | ||
if a[i] != b[i] { | ||
return false | ||
} | ||
} | ||
return true | ||
} |
2 changes: 1 addition & 1 deletion
2
pkg/upsampler/neuronal_networks.go → pkg/resampler/neuronal_networks.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
package upsampler | ||
package resampler | ||
|
||
// TODO: Add externals connection to infer from an endpoint |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package resampler | ||
|
||
const ( | ||
NOT_FILLED = (iota - 1) // Not filled | ||
LINEAR_INTERPOLATION // Linear interpolation | ||
POLYNOMIAL_INTERPOLATION // Polynomial interpolation | ||
) | ||
|
||
var RESAMPLER_METHODS = map[int]string{ | ||
NOT_FILLED: "NOT_FILLED", | ||
LINEAR_INTERPOLATION: "LINEAR_INTERPOLATION", | ||
POLYNOMIAL_INTERPOLATION: "POLYNOMIAL_INTERPOLATION", | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
package upsampler | ||
package resampler | ||
|
||
// TODO: Add different upsampling methods |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package transcoder | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
"sync" | ||
|
||
"github.com/pablodz/sopro/pkg/audioconfig" | ||
"github.com/pablodz/sopro/pkg/resampler" | ||
) | ||
|
||
var doOnceResampling sync.Once | ||
|
||
func ResampleBytes(in *AudioFileIn, out *AudioFileOut, transcoder *Transcoder) error { | ||
|
||
bitsProcessed, err := differentSampleRate(in, out, transcoder) | ||
if err != nil { | ||
return err | ||
} | ||
transcoder.Println("Transcoding done:", bitsProcessed, "bits processed") | ||
|
||
return nil | ||
} | ||
|
||
func differentSampleRate(in *AudioFileIn, out *AudioFileOut, transcoder *Transcoder) (int, error) { | ||
sizeBuff := 1024 // max size, more than that would be too much | ||
if transcoder.SizeBuffer > 0 { | ||
sizeBuff = transcoder.SizeBuffer | ||
} | ||
nTotal := 0 | ||
sampleRateIn := in.Config.(audioconfig.WavConfig).SampleRate | ||
sampleRateOut := out.Config.(audioconfig.WavConfig).SampleRate | ||
ratio := float64(sampleRateIn) / float64(sampleRateOut) | ||
|
||
bufIn := make([]byte, sizeBuff) // input buffer | ||
bufOut := make([]byte, sizeBuff*int(ratio)) // output buffer | ||
transcoder.Println("ratio", ratio, "ratioInt", int(ratio)) | ||
for { | ||
n, err := in.Reader.Read(bufIn) | ||
if err != nil && err != io.EOF { | ||
return nTotal, fmt.Errorf("error reading input file: %v", err) | ||
} | ||
if n == 0 { | ||
break | ||
} | ||
bufIn = bufIn[:n] | ||
// buf2 is different size than buf | ||
bufOut, _ = resampler.LinearInterpolation(bufIn, ratio) // IMPORTANT:buf cut to n bytes | ||
out.Length += len(bufOut) | ||
if _, err = out.Writer.Write(bufOut); err != nil { | ||
return nTotal, fmt.Errorf("error writing output file: %v", err) | ||
} | ||
nTotal += n | ||
|
||
doOnceResampling.Do(func() { | ||
transcoder.Println("[Transcoder] Transcoding data - sample of the first 4 bytes (hex)") | ||
onlyNFirst := 8 | ||
transcoder.Println( | ||
"[OLD]", fmt.Sprintf("% 2x", bufIn[:onlyNFirst]), | ||
"\n[NEW]", fmt.Sprintf("% 2x", bufOut[:onlyNFirst/2]), | ||
) | ||
transcoder.Println("[Transcoder] Transcoding data - sample of the first 4 bytes (decimal)") | ||
transcoder.Println( | ||
"[OLD]", fmt.Sprintf("%3d", bufIn[:onlyNFirst]), | ||
"\n[NEW]", fmt.Sprintf("%3d", bufOut[:onlyNFirst/2]), | ||
) | ||
}) | ||
} | ||
return nTotal, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.