Я написал небольшое приложение, которое записывает данные со звуковой карты и сохраняет данные в массиве для последующей обработки.Функция добавления перезаписывает существующие данные в срезе
Когда новые данные доступны, 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) над образцами для вычисления спектра. Я оставил эту часть, так как она не влияет на эту конкретную проблему.
Я был бы очень признателен за любую помощь. Может быть, кто-нибудь может указать мне, что я делаю неправильно.
Спасибо!
'append' никогда не переписывает существующие данные в том же массиве. «append» может потребоваться выделить новый массив, если срез не имеет достаточной емкости, что, конечно же, требует _copying_ данных для нового массива поддержки. Это то, о чем вы говорите? – JimB
Нет, данные будут явно перезаписаны. Также я понимаю, что append не перезаписывает данные, но я все еще сталкиваюсь с проблемой, что после вызова append в обратном вызове существующие данные в массиве перезаписываются :-( – DH1TW
Возможно, у вас может быть какая-то параллельная процедура которые делают этот беспорядок. –