dongtaoxue4674 2016-10-31 14:15
浏览 89
已采纳

追加功能覆盖切片中的现有数据

I wrote a small application which records data from a sound card and stores the data in an array for later processing.

Whenever new data is available, portaudio executes the callback record. Within the callback I append the data to the array RecData.data.

The golang builtin function append adds as expected another element to the slice, but for whatever reason also overwrites all existing elements within the array with exactly the same data.

I have been trying to isolate the problem for more than two days, without success.

Here is a stripped down version of the code, which works and shows the problem:

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, "
")
    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!
", i )
        }
    }*/
}

2. Update

This is the application output:

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 ....

As we one can see, over time, the size of the slice is growing, but instead of just appending the data, the data in the array gets also overwritten.

This should not happen. portaudio provides in the callback a [][]float32 with the audio sample recorded from the sound card. As you can see they are always different.

As mentioned, the code above is a stripped down version of my application. Usually I would record lets say 5 seconds, and then perform a Fast Fourier Transformation (FFT) over the samples to calculate the spectrum. I left this part away since it has no impact on this particular problem.

I would very much appreciate any help. Maybe somebody can point me out what I'm doing wrong.

Thanks!

  • 写回答

1条回答 默认 最新

  • dtwupu6414 2016-10-31 17:52
    关注

    The buffer passed into the callback is reused by the portaudio package, so you are appending the same slice structure to your data slice. Each time the buffer allocated by portaudio overwrites the data, you see the results in every element of your data slice.

    You will need to allocate new slices and make a copy of the 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)
    

    Example: https://play.golang.org/p/cF57lQIZFU

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 活动选择题。最多可以参加几个项目?
  • ¥15 飞机曲面部件如机翼,壁板等具体的孔位模型
  • ¥15 vs2019中数据导出问题
  • ¥20 云服务Linux系统TCP-MSS值修改?
  • ¥20 关于#单片机#的问题:项目:使用模拟iic与ov2640通讯环境:F407问题:读取的ID号总是0xff,自己调了调发现在读从机数据时,SDA线上并未有信号变化(语言-c语言)
  • ¥20 怎么在stm32门禁成品上增加查询记录功能
  • ¥15 Source insight编写代码后使用CCS5.2版本import之后,代码跳到注释行里面
  • ¥50 NT4.0系统 STOP:0X0000007B
  • ¥15 想问一下stata17中这段代码哪里有问题呀
  • ¥15 flink cdc无法实时同步mysql数据