From e4ffd90c8c168c056586a07a3b24d638ed56c522 Mon Sep 17 00:00:00 2001 From: Conor Landry Date: Mon, 27 Nov 2017 11:55:32 -0500 Subject: [PATCH 1/2] code is finished, bug exists where buffer isn't filling correctly still --- examples/localization.go | 13 +++++----- localization_filter.go | 55 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 59 insertions(+), 9 deletions(-) diff --git a/examples/localization.go b/examples/localization.go index fe077b3..8041d2d 100644 --- a/examples/localization.go +++ b/examples/localization.go @@ -30,9 +30,13 @@ func main() { agraph.SampleRate(int(reader.Fmt.Data.SampleRate)), agraph.BitsPerSample(int(reader.Fmt.Data.BitsPerSample))) - localizationNode, _ := agraph.NewNode(agraph.LocalizationFilter, + localizationNode, err := agraph.NewNode(agraph.LocalizationFilter, "localization", - agraph.Angle(0)) + agraph.Angle(-45)) + + if err != nil { + panic(err) + } localizationNode.SetSink(make(chan []uint16, 0)) @@ -51,18 +55,16 @@ func main() { modifiedData := <-localizationNode.Sink() //fmt.Printf("Localized: %v\n", modifiedData) - leftByte := make([]byte, 2) rightByte := make([]byte, 2) binary.LittleEndian.PutUint16(leftByte, modifiedData[0]) binary.LittleEndian.PutUint16(rightByte, modifiedData[1]) -/* fmt.Print("Packet Info: \n") fmt.Printf(" - Original [%v]uint16 = %v \n", len(data), data) // fmt.Printf(" - Modified [%v]uint16 = %v \n", len(data), data) fmt.Printf(" - L: [%v]byte = %v \n - R: [%v]byte = %v \n", len(leftByte), leftByte, len(rightByte), rightByte) -*/ + // pack all the bytes into the correct ordering fullByte := make([]byte, 4) @@ -76,7 +78,6 @@ func main() { // fmt.Println() - writer.Write(fullByte) } diff --git a/localization_filter.go b/localization_filter.go index 8add875..86a63c1 100644 --- a/localization_filter.go +++ b/localization_filter.go @@ -4,6 +4,9 @@ import ( "time" "math" "strconv" + "container/list" + "fmt" + "strings" ) /* @@ -27,12 +30,13 @@ import ( x x x x x x - 180°/-180° + -180°/180° */ const ( R = 9 // radius of the head in cm C = 345 // speed of sound in m/s + sampleRate = 8000 // won't work with audio that isn't 8000 (won't give the proper delay length) ) type Localization struct { @@ -41,6 +45,9 @@ type Localization struct { Name string Angle float64 itd time.Duration + sampleDelay int + delayChannel int + delayBuf *list.List } func newLocalization(name string, angle float64) (Node, error) { @@ -48,12 +55,27 @@ func newLocalization(name string, angle float64) (Node, error) { if err != nil { return nil, err } + + delayChannel := 0 + + if angle > 0 { + delayChannel = 1 + } + + fmt.Printf("sample delay info: \n - itd seconds: %v \n - sampleRate: %v \n", itd.Seconds(), sampleRate) + + // number of samples to buffer + sampleDelay := int(math.Floor(itd.Seconds() * sampleRate)) + return &Localization{ source: make(chan []uint16, SOURCE_SIZE), sink: nil, Name: name, Angle: angle, itd: itd, + sampleDelay: sampleDelay, + delayChannel: delayChannel, + delayBuf: list.New(), }, nil } @@ -85,19 +107,46 @@ func (n *Localization) Process() error { } func (n *Localization) do(data []uint16) ([]uint16, error) { + // add samples to the buffer if it isn't full + if n.delayBuf.Len() < n.sampleDelay { + n.delayBuf.PushFront(data[n.delayChannel]) + } + fmt.Println(n.sampleDelay) + fmt.Printf("LENGH OF DELAY BUF: %v\n", n.delayBuf.Len()) + + // if the buffer is full, replace the sample with the value + if n.delayBuf.Len() == n.sampleDelay { + samp := n.delayBuf.Front().Value.(uint16) + n.delayBuf.Remove(n.delayBuf.Front()) + data[n.delayChannel] = samp + } else { + // otherwise, set that sample in the data stream to 0 + data[n.delayChannel] = 0 + } + return data, nil } // interaural time difference (ITD) // ∆t = r/c(θ + sin(θ)) +// angle is in degrees coming in func itd(angle float64, radius float64, c float64) (time.Duration, error) { + + angRad := angle * 0.0174533 + // calculate the itd - itd := (radius / c) * (angle + math.Sin(angle)) + itd := math.Abs((radius / c) * (angRad + math.Sin(angle))) // prepare the itd to be parsed as a duration itdStrConv := strconv.FormatFloat(itd, 'f', -1, 64) + fmt.Println(itdStrConv) + unitIdent := "s" + itdStrArr := []string{itdStrConv, unitIdent} + + + itdStr := strings.Join(itdStrArr, "") // duration - return time.ParseDuration(itdStrConv) + return time.ParseDuration(itdStr) } From 4ddd75530b5ef6c9e555dbc834792a3e7ce25814 Mon Sep 17 00:00:00 2001 From: Conor Landry Date: Mon, 27 Nov 2017 20:30:55 -0500 Subject: [PATCH 2/2] working sound localization --- examples/localization.go | 25 ++++++++++++++++++++----- localization_filter.go | 18 +++++++++++------- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/examples/localization.go b/examples/localization.go index 8041d2d..e33de5a 100644 --- a/examples/localization.go +++ b/examples/localization.go @@ -9,7 +9,7 @@ import ( ) func main() { - file, err := os.OpenFile("M1F1-Alaw-AFsp.wav", os.O_RDWR, 066) + file, err := os.OpenFile("guns/gun_war-2-stereo.wav", os.O_RDWR, 066) if err != nil { fmt.Println(err) } @@ -19,7 +19,7 @@ func main() { fmt.Println(err) } - f, err := os.Create("M1F1-Alaw-AFsp_localized.wav") + f, err := os.Create("15_left_gun_war-2.wav") defer f.Close() if err != nil { fmt.Println(err) @@ -32,7 +32,7 @@ func main() { localizationNode, err := agraph.NewNode(agraph.LocalizationFilter, "localization", - agraph.Angle(-45)) + agraph.Angle(15)) if err != nil { panic(err) @@ -43,13 +43,25 @@ func main() { go localizationNode.Process() start := time.Now() + i := 0 + var originalFirstSample uint16 for { + //fmt.Printf("i: %v\n", i) + if i == 1885 { + fmt.Printf("Original First Sample: %v\n", originalFirstSample) + //panic("PAUSE") + } + data, err := reader.ReadSampleInt16() if err != nil { fmt.Println(err) break } + if i == 0 { + originalFirstSample = data[0] + } + localizationNode.Source() <- data modifiedData := <-localizationNode.Sink() @@ -60,11 +72,13 @@ func main() { binary.LittleEndian.PutUint16(leftByte, modifiedData[0]) binary.LittleEndian.PutUint16(rightByte, modifiedData[1]) + + /* fmt.Print("Packet Info: \n") fmt.Printf(" - Original [%v]uint16 = %v \n", len(data), data) - // fmt.Printf(" - Modified [%v]uint16 = %v \n", len(data), data) + fmt.Printf(" - Modified [%v]uint16 = %v \n", len(modifiedData), modifiedData) fmt.Printf(" - L: [%v]byte = %v \n - R: [%v]byte = %v \n", len(leftByte), leftByte, len(rightByte), rightByte) - + */ // pack all the bytes into the correct ordering fullByte := make([]byte, 4) @@ -79,6 +93,7 @@ func main() { // fmt.Println() writer.Write(fullByte) + i++ } writer.Close() diff --git a/localization_filter.go b/localization_filter.go index 86a63c1..0441c6c 100644 --- a/localization_filter.go +++ b/localization_filter.go @@ -36,7 +36,7 @@ import ( const ( R = 9 // radius of the head in cm C = 345 // speed of sound in m/s - sampleRate = 8000 // won't work with audio that isn't 8000 (won't give the proper delay length) + sampleRate = 22050 // won't work with audio that isn't 8000 (won't give the proper delay length) ) type Localization struct { @@ -62,11 +62,14 @@ func newLocalization(name string, angle float64) (Node, error) { delayChannel = 1 } - fmt.Printf("sample delay info: \n - itd seconds: %v \n - sampleRate: %v \n", itd.Seconds(), sampleRate) - // number of samples to buffer sampleDelay := int(math.Floor(itd.Seconds() * sampleRate)) + fmt.Printf("sample delay info: \n" + + " - itd seconds: %v \n" + + " - sampleRate: %v \n" + + " - sample delay %v \n", itd.Seconds(), sampleRate, sampleDelay) + return &Localization{ source: make(chan []uint16, SOURCE_SIZE), sink: nil, @@ -111,13 +114,14 @@ func (n *Localization) do(data []uint16) ([]uint16, error) { if n.delayBuf.Len() < n.sampleDelay { n.delayBuf.PushFront(data[n.delayChannel]) } - fmt.Println(n.sampleDelay) - fmt.Printf("LENGH OF DELAY BUF: %v\n", n.delayBuf.Len()) + //fmt.Println(n.sampleDelay) + //fmt.Printf("LENGH OF DELAY BUF: %v\n", n.delayBuf.Len()) // if the buffer is full, replace the sample with the value if n.delayBuf.Len() == n.sampleDelay { - samp := n.delayBuf.Front().Value.(uint16) - n.delayBuf.Remove(n.delayBuf.Front()) + samp := n.delayBuf.Back().Value.(uint16) + //fmt.Printf("Reading from buffer! \n - samp uint16: %v \n", samp) + n.delayBuf.Remove(n.delayBuf.Back()) data[n.delayChannel] = samp } else { // otherwise, set that sample in the data stream to 0