test: playing a recording must not consume it
Reported: the recording plays once and never again, "as if it threw the sound away after playing it". PeekQSO is what the playback reads and it is meant to copy — TakeQSO is the one that clears — so this pins that, and that the copy is independent of the recorder's own buffer. It passes, which is the useful part: the take survives, so the one-shot failure is downstream of it and the search moves to the file and the player.
This commit is contained in:
@@ -0,0 +1,56 @@
|
|||||||
|
package audio
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Playing a stopped take must not consume it.
|
||||||
|
//
|
||||||
|
// Reported on the air: the recording plays once, then nothing — "as if it threw
|
||||||
|
// the sound away after playing it". PeekQSO is what the playback reads, and it
|
||||||
|
// is meant to COPY; TakeQSO is the one that clears.
|
||||||
|
func TestPeekDoesNotConsumeTheTake(t *testing.T) {
|
||||||
|
r := &Recorder{running: true, active: true, paused: true, prerollSamples: sampleRate}
|
||||||
|
r.acc = make([]int16, 4000)
|
||||||
|
for i := range r.acc {
|
||||||
|
r.acc[i] = int16(i % 500)
|
||||||
|
}
|
||||||
|
|
||||||
|
first, err := r.PeekQSO()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("first peek: %v", err)
|
||||||
|
}
|
||||||
|
second, err := r.PeekQSO()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("second peek: %v — the take was consumed by the first", err)
|
||||||
|
}
|
||||||
|
if len(first) != len(second) {
|
||||||
|
t.Errorf("second peek returned %d bytes, first %d", len(second), len(first))
|
||||||
|
}
|
||||||
|
|
||||||
|
// And the copy must be independent: the caller holds these bytes while the
|
||||||
|
// recorder may still be appending to its own slice.
|
||||||
|
if len(first) > 0 {
|
||||||
|
first[0] = ^first[0]
|
||||||
|
again, _ := r.PeekQSO()
|
||||||
|
if len(again) > 0 && again[0] == first[0] {
|
||||||
|
t.Error("PeekQSO handed out its internal buffer, not a copy")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resuming and stopping again keeps everything captured so far.
|
||||||
|
r.ResumeQSO()
|
||||||
|
r.mu.Lock()
|
||||||
|
r.acc = append(r.acc, make([]int16, 1000)...)
|
||||||
|
r.mu.Unlock()
|
||||||
|
r.PauseQSO()
|
||||||
|
third, err := r.PeekQSO()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("peek after resume: %v", err)
|
||||||
|
}
|
||||||
|
if len(third) <= len(second) {
|
||||||
|
t.Errorf("after resuming, the take is %d bytes — it should have grown past %d", len(third), len(second))
|
||||||
|
}
|
||||||
|
_ = time.Now
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user