Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 追加函数覆盖切片中的现有数据_Arrays_Go_Slice_Portaudio - Fatal编程技术网

Arrays 追加函数覆盖切片中的现有数据

Arrays 追加函数覆盖切片中的现有数据,arrays,go,slice,portaudio,Arrays,Go,Slice,Portaudio,我编写了一个小应用程序,它记录来自声卡的数据,并将数据存储在一个数组中,以供以后处理 只要有新数据可用,portaudio就会执行回调记录。在回调中,我将数据附加到数组RecData.data golang内置函数append按预期将另一个元素添加到切片中,但出于任何原因,也会使用完全相同的数据覆盖数组中的所有现有元素 两天多来,我一直在试图孤立这个问题,但没有成功 下面是代码的精简版本,它可以工作并显示问题: package main import ( "fmt" "time

我编写了一个小应用程序,它记录来自声卡的数据,并将数据存储在一个数组中,以供以后处理

只要有新数据可用,portaudio就会执行回调
记录
。在回调中,我将数据附加到数组
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
在回调中提供从声卡录制的音频样本。正如你所看到的,它们总是不同的

如上所述,上面的代码是我的应用程序的精简版本。通常我会记录5秒钟,然后对样本进行快速傅立叶变换(FFT)来计算光谱。我把这部分放在一边,因为它对这个问题没有影响

我将非常感谢任何帮助。也许有人能指出我做错了什么


谢谢

传递到回调的缓冲区被portaudio包重用,因此您将相同的片结构附加到
数据
片中。每次portaudio分配的缓冲区覆盖数据时,都会在
数据
切片的每个元素中看到结果

您将需要分配新的切片并复制数据:

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)
例如:

append
永远不要在同一数组中重新写入现有数据<代码>追加当切片没有足够的容量时,可能需要分配一个新数组,这当然需要将数据复制到新的备份数组。这就是你指的吗?不,数据明显被覆盖了。据我所知,append不会重新写入数据,但我仍然面临在回调中调用append后,数组中现有数据被覆盖的问题:-(也许你可以有一些并发的go例程来处理这个问题。请给出一个例子,说明你希望看到什么,以及你正在看到什么。你将
中的
附加到切片上,然后如果
中的
在切片中,则写入错误消息,这似乎是预期的。@DH1TW:portaudio包正在重用提供的切片d到回调。你需要将数据复制到你自己的切片中。明白了!感谢代码片段@JimB!我确认,现在数据被正确地附加到
RecData.data
!再次感谢你的帮助!我不会每次都附加到
buf
,而是首先将
buf
的大小设置为适当的大小。这样,继续对于
buf
,只会发生一次分配。实际上,在本例中,我会将其更改为
make
,但并非完全出于这个原因(我通常只是建议人们不要担心它,使用
append
,因为它摊销效果好,代码更干净).给定示例数据,数字分配将是相同的,只是我们会过度分配内存,因为默认的
append
from 0分配了2的容量。