diff --git a/pkg/wave/float32.go b/pkg/wave/float32.go index 4d0ea95..54d06e2 100644 --- a/pkg/wave/float32.go +++ b/pkg/wave/float32.go @@ -34,6 +34,16 @@ func (a *Float32Interleaved) SetFloat32(i, ch int, s Float32Sample) { a.Data[i*a.Size.Channels+ch] = float32(s) } +// SubAudio returns part of the original audio sharing the buffer. +func (a *Float32Interleaved) SubAudio(offsetSamples, nSamples int) *Float32Interleaved { + ret := *a + offset := offsetSamples * a.Size.Channels + n := nSamples * a.Size.Channels + ret.Data = ret.Data[offset : offset+n] + ret.Size.Len = nSamples + return &ret +} + func NewFloat32Interleaved(size ChunkInfo) *Float32Interleaved { return &Float32Interleaved{ Data: make([]float32, size.Channels*size.Len), @@ -68,6 +78,16 @@ func (a *Float32NonInterleaved) SetFloat32(i, ch int, s Float32Sample) { a.Data[ch][i] = float32(s) } +// SubAudio returns part of the original audio sharing the buffer. +func (a *Float32NonInterleaved) SubAudio(offsetSamples, nSamples int) *Float32NonInterleaved { + ret := *a + for i := range a.Data { + ret.Data[i] = ret.Data[i][offsetSamples : offsetSamples+nSamples] + } + ret.Size.Len = nSamples + return &ret +} + func NewFloat32NonInterleaved(size ChunkInfo) *Float32NonInterleaved { d := make([][]float32, size.Channels) for i := 0; i < size.Channels; i++ { diff --git a/pkg/wave/float32_test.go b/pkg/wave/float32_test.go index 7f6775f..4c1ba31 100644 --- a/pkg/wave/float32_test.go +++ b/pkg/wave/float32_test.go @@ -51,3 +51,44 @@ func TestFloat32(t *testing.T) { }) } } + +func TestFloat32SubAudio(t *testing.T) { + t.Run("Interleaved", func(t *testing.T) { + in := &Float32Interleaved{ + Data: []float32{ + 0.1, -0.5, 0.2, -0.6, 0.3, -0.7, 0.4, -0.8, 0.5, -0.9, 0.6, -1.0, 0.7, -1.1, 0.8, -1.2, + }, + Size: ChunkInfo{8, 2, 48000}, + } + expected := &Float32Interleaved{ + Data: []float32{ + 0.3, -0.7, 0.4, -0.8, 0.5, -0.9, + }, + Size: ChunkInfo{3, 2, 48000}, + } + out := in.SubAudio(2, 3) + if !reflect.DeepEqual(expected, out) { + t.Errorf("SubAudio differs, expected: %v, got: %v", expected, out) + } + }) + t.Run("NonInterleaved", func(t *testing.T) { + in := &Float32NonInterleaved{ + Data: [][]float32{ + {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8}, + {-0.5, -0.6, -0.7, -0.8, -0.9, -1.0, -1.1, -1.2}, + }, + Size: ChunkInfo{8, 2, 48000}, + } + expected := &Float32NonInterleaved{ + Data: [][]float32{ + {0.3, 0.4, 0.5}, + {-0.7, -0.8, -0.9}, + }, + Size: ChunkInfo{3, 2, 48000}, + } + out := in.SubAudio(2, 3) + if !reflect.DeepEqual(expected, out) { + t.Errorf("SubAudio differs, expected: %v, got: %v", expected, out) + } + }) +} diff --git a/pkg/wave/int16.go b/pkg/wave/int16.go index 74604a2..3747d47 100644 --- a/pkg/wave/int16.go +++ b/pkg/wave/int16.go @@ -34,6 +34,16 @@ func (a *Int16Interleaved) SetInt16(i, ch int, s Int16Sample) { a.Data[i*a.Size.Channels+ch] = int16(s) } +// SubAudio returns part of the original audio sharing the buffer. +func (a *Int16Interleaved) SubAudio(offsetSamples, nSamples int) *Int16Interleaved { + ret := *a + offset := offsetSamples * a.Size.Channels + n := nSamples * a.Size.Channels + ret.Data = ret.Data[offset : offset+n] + ret.Size.Len = nSamples + return &ret +} + func NewInt16Interleaved(size ChunkInfo) *Int16Interleaved { return &Int16Interleaved{ Data: make([]int16, size.Channels*size.Len), @@ -68,6 +78,16 @@ func (a *Int16NonInterleaved) SetInt16(i, ch int, s Int16Sample) { a.Data[ch][i] = int16(s) } +// SubAudio returns part of the original audio sharing the buffer. +func (a *Int16NonInterleaved) SubAudio(offsetSamples, nSamples int) *Int16NonInterleaved { + ret := *a + for i := range a.Data { + ret.Data[i] = ret.Data[i][offsetSamples : offsetSamples+nSamples] + } + ret.Size.Len = nSamples + return &ret +} + func NewInt16NonInterleaved(size ChunkInfo) *Int16NonInterleaved { d := make([][]int16, size.Channels) for i := 0; i < size.Channels; i++ { diff --git a/pkg/wave/int16_test.go b/pkg/wave/int16_test.go index 6032670..a016fb0 100644 --- a/pkg/wave/int16_test.go +++ b/pkg/wave/int16_test.go @@ -51,3 +51,44 @@ func TestInt16(t *testing.T) { }) } } + +func TestInt32SubAudio(t *testing.T) { + t.Run("Interleaved", func(t *testing.T) { + in := &Int16Interleaved{ + Data: []int16{ + 1, -5, 2, -6, 3, -7, 4, -8, 5, -9, 6, -10, 7, -11, 8, -12, + }, + Size: ChunkInfo{8, 2, 48000}, + } + expected := &Int16Interleaved{ + Data: []int16{ + 3, -7, 4, -8, 5, -9, + }, + Size: ChunkInfo{3, 2, 48000}, + } + out := in.SubAudio(2, 3) + if !reflect.DeepEqual(expected, out) { + t.Errorf("SubAudio differs, expected: %v, got: %v", expected, out) + } + }) + t.Run("NonInterleaved", func(t *testing.T) { + in := &Int16NonInterleaved{ + Data: [][]int16{ + {1, 2, 3, 4, 5, 6, 7, 8}, + {-5, -6, -7, -8, -9, -10, -11, -12}, + }, + Size: ChunkInfo{8, 2, 48000}, + } + expected := &Int16NonInterleaved{ + Data: [][]int16{ + {3, 4, 5}, + {-7, -8, -9}, + }, + Size: ChunkInfo{3, 2, 48000}, + } + out := in.SubAudio(2, 3) + if !reflect.DeepEqual(expected, out) { + t.Errorf("SubAudio differs, expected: %v, got: %v", expected, out) + } + }) +}