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 如何让企业微信机器人实现消息汇总整合
  • ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题
  • ¥15 如何用Python爬取各高校教师公开的教育和工作经历
  • ¥15 TLE9879QXA40 电机驱动
  • ¥20 对于工程问题的非线性数学模型进行线性化
  • ¥15 Mirare PLUS 进行密钥认证?(详解)
  • ¥15 物体双站RCS和其组成阵列后的双站RCS关系验证
  • ¥20 想用ollama做一个自己的AI数据库
  • ¥15 关于qualoth编辑及缝合服装领子的问题解决方案探寻
  • ¥15 请问怎么才能复现这样的图呀