mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-12-24 13:08:06 +08:00
audio/internal/convert: bug fix: a returned stream's Length and actual read buffer length didn't match
Closes #3352
This commit is contained in:
@@ -556,7 +556,7 @@ func (h *hookerImpl) AppendHookOnBeforeUpdate(f func() error) {
|
||||
}
|
||||
|
||||
// ResampleReader converts the sample rate of the given singed 16bit integer, little-endian, 2 channels (stereo) stream.
|
||||
// size is the length of the source stream in bytes.
|
||||
// size is the length of the source stream in bytes. 0 indicates the length is unknown.
|
||||
// from is the original sample rate.
|
||||
// to is the target sample rate.
|
||||
//
|
||||
@@ -573,7 +573,7 @@ func ResampleReader(source io.Reader, size int64, from, to int) io.Reader {
|
||||
}
|
||||
|
||||
// ResampleReaderF32 converts the sample rate of the given 32bit float, little-endian, 2 channels (stereo) stream.
|
||||
// size is the length of the source stream in bytes.
|
||||
// size is the length of the source stream in bytes. 0 indicates the length is unknown.
|
||||
// from is the original sample rate.
|
||||
// to is the target sample rate.
|
||||
//
|
||||
@@ -590,7 +590,7 @@ func ResampleReaderF32(source io.Reader, size int64, from, to int) io.Reader {
|
||||
}
|
||||
|
||||
// Resample converts the sample rate of the given singed 16bit integer, little-endian, 2 channels (stereo) stream.
|
||||
// size is the length of the source stream in bytes.
|
||||
// size is the length of the source stream in bytes. 0 indicates the length is unknown.
|
||||
// from is the original sample rate.
|
||||
// to is the target sample rate.
|
||||
//
|
||||
@@ -605,7 +605,7 @@ func Resample(source io.ReadSeeker, size int64, from, to int) io.ReadSeeker {
|
||||
}
|
||||
|
||||
// ResampleF32 converts the sample rate of the given 32bit float, little-endian, 2 channels (stereo) stream.
|
||||
// size is the length of the source stream in bytes.
|
||||
// size is the length of the source stream in bytes. 0 indicates the length is unknown.
|
||||
// from is the original sample rate.
|
||||
// to is the target sample rate.
|
||||
//
|
||||
|
||||
@@ -80,8 +80,11 @@ func sinc01(x float64) float64 {
|
||||
}
|
||||
|
||||
type Resampling struct {
|
||||
source io.Reader
|
||||
size int64
|
||||
source io.Reader
|
||||
|
||||
// size is the length of the source stream in bytes. 0 indicates the length is unknown.
|
||||
size int64
|
||||
|
||||
from int
|
||||
to int
|
||||
bitDepthInBytes int
|
||||
@@ -199,10 +202,8 @@ func (r *Resampling) src(i int64) (float64, float64, error) {
|
||||
if r.eofBufIndex == r.srcBlock && ii >= int64(len(r.srcBufL[r.srcBlock])-1) {
|
||||
err = io.EOF
|
||||
}
|
||||
if _, ok := r.source.(io.Seeker); ok {
|
||||
if r.size/sizePerSample <= i {
|
||||
err = io.EOF
|
||||
}
|
||||
if r.size > 0 && r.size/sizePerSample <= i {
|
||||
err = io.EOF
|
||||
}
|
||||
return r.srcBufL[r.srcBlock][ii], r.srcBufR[r.srcBlock][ii], err
|
||||
}
|
||||
@@ -215,8 +216,7 @@ func (r *Resampling) at(t int64) (float64, float64, error) {
|
||||
startN = 0
|
||||
}
|
||||
endN := int64(tInSrc + windowSize)
|
||||
lv := 0.0
|
||||
rv := 0.0
|
||||
var lv, rv float64
|
||||
var eof bool
|
||||
for n := startN; n <= endN; n++ {
|
||||
srcL, srcR, err := r.src(n)
|
||||
@@ -259,11 +259,13 @@ func (r *Resampling) Read(b []byte) (int, error) {
|
||||
n := len(b) / size * size
|
||||
switch r.bitDepthInBytes {
|
||||
case 2:
|
||||
for i := 0; i < n/size; i++ {
|
||||
for i := range n / size {
|
||||
ldata, rdata, err := r.at(r.pos/int64(size) + int64(i))
|
||||
if err != nil && err != io.EOF {
|
||||
return 0, err
|
||||
}
|
||||
// EOF from the at method indicates that the source reaches the end, and doesn't indicate the resampled data ends.
|
||||
// Continue the loop even if EOF is returned.
|
||||
if err == io.EOF {
|
||||
r.eof = true
|
||||
}
|
||||
@@ -273,9 +275,14 @@ func (r *Resampling) Read(b []byte) (int, error) {
|
||||
b[4*i+1] = byte(l16 >> 8)
|
||||
b[4*i+2] = byte(r16)
|
||||
b[4*i+3] = byte(r16 >> 8)
|
||||
// If the source is an io.Seeker and the length is known, check whether the resampled data ends (#3352).
|
||||
if r.size > 0 && r.pos+int64(size*i) >= r.Length() {
|
||||
n = size * i
|
||||
break
|
||||
}
|
||||
}
|
||||
case 4:
|
||||
for i := 0; i < n/size; i++ {
|
||||
for i := range n / size {
|
||||
ldata, rdata, err := r.at(r.pos/int64(size) + int64(i))
|
||||
if err != nil && err != io.EOF {
|
||||
return 0, err
|
||||
@@ -295,6 +302,10 @@ func (r *Resampling) Read(b []byte) (int, error) {
|
||||
b[8*i+5] = byte(r32b >> 8)
|
||||
b[8*i+6] = byte(r32b >> 16)
|
||||
b[8*i+7] = byte(r32b >> 24)
|
||||
if r.size > 0 && r.pos+int64(size*i) >= r.Length() {
|
||||
n = size * i
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
panic("not reached")
|
||||
|
||||
@@ -164,3 +164,20 @@ func TestResampling(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Issue #3352
|
||||
func TestResamplingLen(t *testing.T) {
|
||||
buf := make([]byte, 8*48000)
|
||||
src := bytes.NewReader(buf)
|
||||
resampled := convert.NewResampling(src, int64(len(buf)), 48000, 96000, 4)
|
||||
if got, want := resampled.Length(), int64(len(buf)*2); got != want {
|
||||
t.Errorf("got: %d, want: %d", got, want)
|
||||
}
|
||||
decodedBuf, err := io.ReadAll(resampled)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got, want := len(decodedBuf), int(len(buf)*2); got != want {
|
||||
t.Errorf("got: %d, want: %d", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user