2016-10-31 3 views
2

사운드 카드의 데이터를 기록하고 나중에 처리 할 수 ​​있도록 배열에 데이터를 저장하는 작은 응용 프로그램을 작성했습니다.Append 함수가 슬라이스의 기존 데이터를 덮어 씁니다.

새 데이터를 사용할 수있을 때마다 portaudio는 콜백 record을 실행합니다. 콜백 내에서 배열 RecData.data 데이터를 추가합니다. 또한 똑같은 데이터으로 배열 내에 존재하는 모든 요소를 ​​덮어 어떤 이유 슬라이스, 뿐만위한 다른 요소를 예상

golang 내장 함수 append 덧붙인다.

저는이 문제를 2 일 넘게 성공시키지 않고 격리하려고했습니다.

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

여기

문제를 작동 보여줍니다 코드의 버전을 박탈한다 우리가 볼 수 있듯이 시간이 지남에 따라 슬라이스의 크기가 커지고 있지만 데이터를 추가하는 대신 배열의 데이터도 덮어 쓰게됩니다 en.

이렇게해서는 안됩니다. portaudio은 사운드 카드에서 녹음 한 오디오 샘플을 콜백에 [][]float32으로 제공합니다. 보시다시피 그들은 항상 다릅니다.

위에서 언급 한 것처럼 위 코드는 내 응용 프로그램을 삭제 한 버전입니다. 보통 나는 5 초를 말하고 스펙트럼을 계산하기 위해 샘플에 대해 고속 푸리에 변환 (FFT)을 수행합니다. 나는이 특별한 문제에 아무런 영향을 미치지 않기 때문에이 부분을 떠났다.

나는 어떤 도움을 주셔서 감사합니다. 어쩌면 누군가 내가 잘못하고있는 것을 지적 할 수 있습니다.

감사합니다.

+0

'append' 결코 기존의 다시없는이-데이터 쓰기. 'append'는 슬라이스에 충분한 용량이 없을 때 새로운 배열을 할당해야 할 수도 있습니다. 물론 새로운 배킹 배열에 데이터를 복사해야합니다. 네가 말하는거야? – JimB

+0

아니요, 데이터가 명확하게 덮어 씁니다. 또한 append가 데이터를 다시 쓰지 않는다는 것을 이해하고 있지만 콜백에 append를 호출하면 배열의 기존 데이터를 덮어 씁니다 .--( – DH1TW

+0

어쩌면 일부 루틴을 가질 수 있습니다. 이 엉망진창을하십시오. –

답변

4

콜백에 전달 된 버퍼는 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) 

예 : 같은 배열의 https://play.golang.org/p/cF57lQIZFU

+0

그것을 받으세요! 코드 스 니펫 @JimB에 감사드립니다! 이제 데이터가'RecData.data'에 올바르게 추가됩니다. 도와 주셔서 다시 한 번 감사드립니다! – DH1TW

+0

매번'buf'에 추가하는 대신, 처음에는'buf'를 적절한 크기로 만들 것입니다. 그렇게하면'buf '에 대해서만 하나의 할당이 일어납니다. –

+0

사실 저는이 예제에서'make '로 바꿀 것입니다.하지만 그 이유는 아닙니다. (저는 사람들이 잘 모으고 깨끗한 코드를 남기므로 보통 걱정하지 말고'append'를 사용하는 것이 좋습니다.) 예제 데이터가 주어지면 숫자 할당은 동일 할 것입니다. 단, 0을 기본으로하는 append가 2의 용량을 할당하기 때문에 메모리를 과도하게 할당한다는 점만 다릅니다. – JimB

관련 문제