Skip to content

Commit

Permalink
Merge pull request #2 from zaf/unstable
Browse files Browse the repository at this point in the history
Various Fixes

Fixed crashing benchmark code
Properly consume all input data
Properly handle fragmented input
Changed 32f testing sample
  • Loading branch information
zaf authored Feb 16, 2020
2 parents b8a6b3f + a22aecf commit 0796885
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 35 deletions.
47 changes: 18 additions & 29 deletions resample.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,15 +155,15 @@ func (r *Resampler) Write(p []byte) (i int, err error) {
if len(p) == 0 {
return
}
if fragment := len(p) % (r.frameSize * r.channels); fragment != 0 {
// Drop fragmented frames from the end of input data
p = p[:len(p)-fragment]
}
framesIn := len(p) / r.frameSize / r.channels
if framesIn == 0 {
err = errors.New("Incomplete input frame data")
return
}
if len(p)%(r.frameSize*r.channels) != 0 {
err = errors.New("Fragmented last frame in input data")
return
}
framesOut := int(float64(framesIn) * (r.outRate / r.inRate))
if framesOut == 0 {
err = errors.New("Not enough input to generate output")
Expand All @@ -172,33 +172,22 @@ func (r *Resampler) Write(p []byte) (i int, err error) {
dataIn := C.CBytes(p)
dataOut := C.malloc(C.size_t(framesOut*r.channels*r.frameSize + 4))
var soxErr C.soxr_error_t
var read1, read2, done1, done2 C.size_t = 0, 0, 0, 0
var w1, w2 int
soxErr = C.soxr_process(r.resampler, C.soxr_in_t(dataIn), C.size_t(framesIn), &read1, C.soxr_out_t(dataOut), C.size_t(framesOut), &done1)
if C.GoString(soxErr) != "" && C.GoString(soxErr) != "0" {
err = errors.New(C.GoString(soxErr))
goto cleanup
}
w1, err = r.destination.Write(C.GoBytes(dataOut, C.int(int(done1)*r.channels*r.frameSize)))
if err != nil {
goto cleanup
}
// Consume any data left in the resampling filter
soxErr = C.soxr_process(r.resampler, C.soxr_in_t(nil), C.size_t(0), &read2, C.soxr_out_t(dataOut), C.size_t(framesOut), &done2)
if C.GoString(soxErr) != "" && C.GoString(soxErr) != "0" {
err = errors.New(C.GoString(soxErr))
goto cleanup
}
w2, err = r.destination.Write(C.GoBytes(dataOut, C.int(int(done2)*r.channels*r.frameSize)))
if err == nil {
i = int(float64(w1+w2) * (r.inRate / r.outRate))
// If we have read all input and flushed all output, avoid to report short writes due
// to output frames missing because of downsampling or other odd reasons.
if framesIn == int(read1+read2) && framesOut == int(done1+done2) {
i = len(p)
var totalDone int
for totalDone < framesOut {
var read, done C.size_t = 0, 0
var w int
soxErr = C.soxr_process(r.resampler, C.soxr_in_t(dataIn), C.size_t(framesIn), &read, C.soxr_out_t(dataOut), C.size_t(framesOut), &done)
if C.GoString(soxErr) != "" && C.GoString(soxErr) != "0" {
err = errors.New(C.GoString(soxErr))
break
}
w, err = r.destination.Write(C.GoBytes(dataOut, C.int(int(done)*r.channels*r.frameSize)))
if err != nil {
break
}
totalDone += int(done)
i += int(float64(w) * (r.inRate / r.outRate))
}
cleanup:
C.free(dataIn)
C.free(dataOut)
C.free(unsafe.Pointer(soxErr))
Expand Down
26 changes: 20 additions & 6 deletions resample_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,23 +56,24 @@ func TestNew(t *testing.T) {
}
}

var WriterTest = []struct {
var WriterTest1 = []struct {
data []byte
expected int
err string
}{
{[]byte{}, 0, ""},
{[]byte{0x01}, 0, "Incomplete input frame data"},
{[]byte{0x01, 0x00}, 2, ""},
{[]byte{0x01, 0x00, 0x7c, 0x7f, 0xd1, 0xd0, 0xd3, 0xd2, 0xdd, 0xdc, 0xdf, 0xde, 0x01, 0x00, 0x7c, 0x7f, 0xd1, 0xd0, 0xd3, 0xd2, 0xdd, 0xdc, 0xdf, 0xde}, 24, ""},
{[]byte{0x01, 0x00, 0x7c, 0x7f, 0xd1, 0xd0, 0xd3, 0xd2, 0xdd, 0xdc, 0xdf, 0xde, 0x01, 0x00, 0x7c, 0x7f, 0xd1, 0xd0, 0xd3, 0xd2, 0xdd, 0xdc, 0xdf, 0xde, 0xd9}, 25, "Fragmented last frame in input data"},
{[]byte{0x01, 0x00, 0x7c, 0x7f, 0xd1, 0xd0, 0xd3, 0xd2, 0xdd, 0xdc, 0xdf, 0xde, 0x01, 0x00, 0x7c, 0x7f, 0xd1, 0xd0, 0xd3, 0xd2, 0xdd, 0xdc, 0xdf, 0xde, 0xd9}, 24, ""},
}

func TestWriter1(t *testing.T) {
res, err := New(ioutil.Discard, 8000.0, 8000.0, 1, I16, MediumQ)
if err != nil {
t.Fatal("Failed to create a 1-1 Resampler: ", err)
}
for _, tc := range WriterTest {
for _, tc := range WriterTest1 {
i, err := res.Write(tc.data)
if err != nil && err.Error() != tc.err {
t.Errorf("Resampler 1-1 writer error: %s , expecting: %s", err.Error(), tc.err)
Expand All @@ -87,12 +88,24 @@ func TestWriter1(t *testing.T) {
res.Close()
}

var WriterTest2 = []struct {
data []byte
expected int
err string
}{
{[]byte{}, 0, ""},
{[]byte{0x01}, 0, "Incomplete input frame data"},
{[]byte{0x01, 0x00, 0x7c, 0x7f}, 0, "Not enough input to generate output"},
{[]byte{0x01, 0x00, 0x7c, 0x7f, 0xd1, 0xd0, 0xd3, 0xd2, 0xdd, 0xdc, 0xdf, 0xde, 0x01, 0x00, 0x7c, 0x7f, 0xd1, 0xd0, 0xd3, 0xd2, 0xdd, 0xdc, 0xdf, 0xde}, 24, ""},
{[]byte{0x01, 0x00, 0x7c, 0x7f, 0xd1, 0xd0, 0xd3, 0xd2, 0xdd, 0xdc, 0xdf, 0xde, 0x01, 0x00, 0x7c, 0x7f, 0xd1, 0xd0, 0xd3, 0xd2, 0xdd, 0xdc, 0xdf, 0xde, 0xd9}, 24, ""},
}

func TestWriter2(t *testing.T) {
res, err := New(ioutil.Discard, 8000.0, 4000.0, 2, I16, MediumQ)
if err != nil {
t.Fatal("Failed to create a 1-2 Resampler: ", err)
}
for _, tc := range WriterTest {
for _, tc := range WriterTest2 {
i, err := res.Write(tc.data)
if err != nil && err.Error() != tc.err {
t.Errorf("Resampler 1-2 writer error: %s , expecting: %s", err.Error(), tc.err)
Expand All @@ -116,7 +129,7 @@ func TestClose(t *testing.T) {
if err != nil {
t.Fatal("Failed to Close the Resampler: ", err)
}
_, err = res.Write(WriterTest[2].data)
_, err = res.Write(WriterTest1[3].data)
if err == nil {
t.Fatal("Running Write on a closed Resampler didn't return an error.")
}
Expand Down Expand Up @@ -157,7 +170,7 @@ var BenchData = []struct {
}{
{"16bit 2 ch 44,1->16 Medium", "testing/piano-44.1k-16-2.wav", 44100.0, 16000.0, 2, I16, MediumQ},
{"16bit 2 ch 16->8 Medium", "testing/piano-16k-16-2.wav", 16000.0, 8000.0, 2, I16, MediumQ},
{"32fl 2 ch 44.1->8 Medium", "testing/organ44.1k-32f-2.wav", 44100.0, 8000.0, 2, F32, MediumQ},
{"32fl 2 ch 44.1->8 Medium", "testing/piano-44.1k-32f-2.wav", 44100.0, 8000.0, 2, F32, MediumQ},
{"16bit 2 ch 44.1->48 Medium", "testing/piano-44.1k-16-2.wav", 44100.0, 48000.0, 2, I16, MediumQ},
{"16bit 2 ch 48->44.1 Medium", "testing/piano-48k-16-2.wav", 48000.0, 44100.0, 2, I16, MediumQ},
{"16bit 1 ch 16->8 Quick", "testing/piano-16k-16-1.wav", 16000.0, 8000.0, 1, I16, Quick},
Expand Down Expand Up @@ -186,6 +199,7 @@ func BenchmarkResampling(b *testing.B) {
if err != nil {
b.Fatalf("Encoding failed: %s\n", err)
}
res.Reset(ioutil.Discard)
}
})
}
Expand Down
Binary file removed testing/organ44.1k-32f-2.wav
Binary file not shown.
Binary file added testing/piano-44.1k-32f-2.wav
Binary file not shown.

0 comments on commit 0796885

Please sign in to comment.