追加函数覆盖切片中的现有数据
Append function overwrites existing data in slice
我写了一个小应用程序,它从声卡记录数据并将数据存储在数组中以供以后处理。
只要有新数据可用,portaudio 就会执行回调 record
。在回调中,我将数据附加到数组 RecData.data
.
golang 内置函数 append
按预期向切片添加另一个元素, 但出于某种原因也用完全相同的数据覆盖数组中的所有现有元素 .
两天多来我一直在尝试隔离问题,但没有成功。
这是代码的精简版本,它可以工作并显示问题:
package main
import (
"fmt"
"time"
// "reflect"
"github.com/gordonklaus/portaudio"
)
type RecData struct{
data [][][]float32
}
func main() {
var inputChs int = 1
var outputChs int = 0
var samplingRate float64 = 48000
var framesPerBuffer int = 3 //for test purpose that low. Would normally be 1024 or 2048
rec := RecData{make([][][]float32, 0, 1000)}
portaudio.Initialize()
stream, err := portaudio.OpenDefaultStream(inputChs, outputChs, samplingRate, framesPerBuffer, rec.record)
if err != nil {
fmt.Println(err)
}
defer stream.Close()
stream.Start()
for {
time.Sleep(time.Millisecond * 10)
}
}
// callback which gets called when new data is in the buffer
func (re *RecData)record(in [][]float32) {
fmt.Println("Received sound sample: ")
fmt.Println(in)
re.data = append(re.data, in)
fmt.Println("Content of RecData.data after adding received sound sample:")
fmt.Println(re.data, "\n")
time.Sleep(time.Millisecond * 500) //limit temporarily the amount of data read
// iterate over all recorded data and compare them
/*
for i, d := range re.data{
if reflect.DeepEqual(d, in){
fmt.Printf("Data at index %d is the same as the recorded one, but should not be!\n", i )
}
}*/
}
2。更新
这是应用程序输出:
Received sound sample:
[[0.71575254 1.0734825 0.7444282]]
Content of RecData.data after adding received sound sample:
[[[0.71575254 1.0734825 0.7444282]]]
Received sound sample:
[[0.7555193 0.768355 0.6575008]]
Content of RecData.data after adding received sound sample:
[[[0.7555193 0.768355 0.6575008]] [[0.7555193 0.768355 0.6575008]]]
Received sound sample:
[[0.7247052 0.68471473 0.6843796]]
Content of RecData.data after adding received sound sample:
[[[0.7247052 0.68471473 0.6843796]] [[0.7247052 0.68471473 0.6843796]] [[0.7247052 0.68471473 0.6843796]]]
Received sound sample:
[[0.6996536 0.66283375 0.67252487]]
Content of RecData.data after adding received sound sample:
[[[0.6996536 0.66283375 0.67252487]] [[0.6996536 0.66283375 0.67252487]] [[0.6996536 0.66283375 0.67252487]] [[0.6996536 0.66283375 0.67252487]]]
.... etc ....
正如我们所看到的,随着时间的推移,切片的大小正在增长,但数组中的数据不仅会附加数据,还会被覆盖。
这不应该发生。 portaudio
在回调中提供 [][]float32
以及从声卡录制的音频样本。如您所见,它们总是不同的。
如前所述,上面的代码是我的应用程序的精简版。通常我会记录 5 秒,然后对样本执行快速傅立叶变换 (FFT) 以计算频谱。我把这部分留了下来,因为它对这个特定问题没有影响。
如果有任何帮助,我将不胜感激。也许有人可以指出我做错了什么。
谢谢!
传递给回调的缓冲区被 portaudio 包重用,因此您将相同的切片结构附加到您的 data
切片。每次 portaudio 分配的缓冲区覆盖数据时,您都会在 data
切片的每个元素中看到结果。
您将需要分配新的切片并复制数据:
func (re *RecData) record(in [][]float32) {
buf := make([][]float32, len(in))
for i, v := range in {
buf[i] = append([]float32(nil), v...)
}
re.data = append(re.data, buf)
我写了一个小应用程序,它从声卡记录数据并将数据存储在数组中以供以后处理。
只要有新数据可用,portaudio 就会执行回调 record
。在回调中,我将数据附加到数组 RecData.data
.
golang 内置函数 append
按预期向切片添加另一个元素, 但出于某种原因也用完全相同的数据覆盖数组中的所有现有元素 .
两天多来我一直在尝试隔离问题,但没有成功。
这是代码的精简版本,它可以工作并显示问题:
package main
import (
"fmt"
"time"
// "reflect"
"github.com/gordonklaus/portaudio"
)
type RecData struct{
data [][][]float32
}
func main() {
var inputChs int = 1
var outputChs int = 0
var samplingRate float64 = 48000
var framesPerBuffer int = 3 //for test purpose that low. Would normally be 1024 or 2048
rec := RecData{make([][][]float32, 0, 1000)}
portaudio.Initialize()
stream, err := portaudio.OpenDefaultStream(inputChs, outputChs, samplingRate, framesPerBuffer, rec.record)
if err != nil {
fmt.Println(err)
}
defer stream.Close()
stream.Start()
for {
time.Sleep(time.Millisecond * 10)
}
}
// callback which gets called when new data is in the buffer
func (re *RecData)record(in [][]float32) {
fmt.Println("Received sound sample: ")
fmt.Println(in)
re.data = append(re.data, in)
fmt.Println("Content of RecData.data after adding received sound sample:")
fmt.Println(re.data, "\n")
time.Sleep(time.Millisecond * 500) //limit temporarily the amount of data read
// iterate over all recorded data and compare them
/*
for i, d := range re.data{
if reflect.DeepEqual(d, in){
fmt.Printf("Data at index %d is the same as the recorded one, but should not be!\n", i )
}
}*/
}
2。更新
这是应用程序输出:
Received sound sample:
[[0.71575254 1.0734825 0.7444282]]
Content of RecData.data after adding received sound sample:
[[[0.71575254 1.0734825 0.7444282]]]
Received sound sample:
[[0.7555193 0.768355 0.6575008]]
Content of RecData.data after adding received sound sample:
[[[0.7555193 0.768355 0.6575008]] [[0.7555193 0.768355 0.6575008]]]
Received sound sample:
[[0.7247052 0.68471473 0.6843796]]
Content of RecData.data after adding received sound sample:
[[[0.7247052 0.68471473 0.6843796]] [[0.7247052 0.68471473 0.6843796]] [[0.7247052 0.68471473 0.6843796]]]
Received sound sample:
[[0.6996536 0.66283375 0.67252487]]
Content of RecData.data after adding received sound sample:
[[[0.6996536 0.66283375 0.67252487]] [[0.6996536 0.66283375 0.67252487]] [[0.6996536 0.66283375 0.67252487]] [[0.6996536 0.66283375 0.67252487]]]
.... etc ....
正如我们所看到的,随着时间的推移,切片的大小正在增长,但数组中的数据不仅会附加数据,还会被覆盖。
这不应该发生。 portaudio
在回调中提供 [][]float32
以及从声卡录制的音频样本。如您所见,它们总是不同的。
如前所述,上面的代码是我的应用程序的精简版。通常我会记录 5 秒,然后对样本执行快速傅立叶变换 (FFT) 以计算频谱。我把这部分留了下来,因为它对这个特定问题没有影响。
如果有任何帮助,我将不胜感激。也许有人可以指出我做错了什么。
谢谢!
传递给回调的缓冲区被 portaudio 包重用,因此您将相同的切片结构附加到您的 data
切片。每次 portaudio 分配的缓冲区覆盖数据时,您都会在 data
切片的每个元素中看到结果。
您将需要分配新的切片并复制数据:
func (re *RecData) record(in [][]float32) {
buf := make([][]float32, len(in))
for i, v := range in {
buf[i] = append([]float32(nil), v...)
}
re.data = append(re.data, buf)