Browse Source

lotsa changes

Keelan Lightfoot 7 years ago
parent
commit
63373ff45b
18 changed files with 399 additions and 215 deletions
  1. 39
    3
      README.md
  2. 1
    1
      code.go
  3. 1
    1
      common.go
  4. 1
    1
      decoder.go
  5. 1
    1
      demodulator.go
  6. 1
    1
      dsp.go
  7. 1
    1
      encoder.go
  8. 7
    7
      examples/audioin/main.go
  9. 3
    3
      examples/demtest.go
  10. 0
    175
      examples/foo/main.go
  11. 10
    10
      examples/main.go
  12. 63
    0
      examples/rawdemod/main.go
  13. 73
    0
      examples/rawinrawout/main.go
  14. 8
    8
      examples/rttymodem/main.go
  15. 2
    2
      gobaudot_test.go
  16. 1
    1
      modulator.go
  17. 95
    0
      rawdemodulator.go
  18. 92
    0
      rawmodulator.go

+ 39
- 3
README.md View File

@@ -1,5 +1,41 @@
1
-# Gobaudot
1
+# gortty
2 2
 
3
-Derived from the Open Baudot C library created David Rowe:
3
+gortty is a RTTY modulator/demodulator library for the Go language. The guts of it were derived from the openbaudot C library created David Rowe:
4 4
 
5
-// sourceforge link
5
+https://sourceforge.net/projects/openbaudot/
6
+
7
+# Architecture
8
+The library is based around 4 signal processing modules:
9
+
10
+## Encoder
11
+Converts UTF8 strings into 5 level code, supporting the following alphabets: 
12
+
13
+- TDD
14
+- US TTY
15
+- US ITA2
16
+- US Weather
17
+- US Fractions
18
+
19
+In addition to basic code translation, the coder inserts the necessary shift and unshift control codes as required. It also ensures that line length limits are respected. While all of the currently implemented alphabets are 5 unit codes, the library supports up to 8 unit codes.
20
+
21
+## Modulator
22
+From the coded output produced by the encoder, the modulator generates a 16 bit signed audio FSK waveform. Baud rate, fractional stop bits, marking and spacing frequencies are all configurable.
23
+
24
+## Demodulator
25
+Accepting a 16 bit signed audio FSK waveform as input, the demodulator generates a stream of coded characters. Supporting the same configuration flexibility as the modulator, the demodulator also supports an auto-baud mode to automatically recover the baud rate from a received samples.
26
+
27
+## Decoder
28
+The decoder operates in reverse of the encoder.
29
+
30
+# License
31
+
32
+This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
33
+
34
+# Author
35
+
36
+This library was created Keelan Lightfoot. The baudot translation and DSP sections are based closely on the work of David Rowe in his openbaudot C library.
37
+
38
+# Change Log
39
+
40
+## 1.0.0
41
+ - Initial release

+ 1
- 1
code.go View File

@@ -9,7 +9,7 @@
9 9
 // the Free Software Foundation; either version 2.1 of the License, or (at
10 10
 // your option) any later version.
11 11
 
12
-package gobaudot
12
+package gortty
13 13
 
14 14
 import "unicode"
15 15
 

+ 1
- 1
common.go View File

@@ -11,7 +11,7 @@
11 11
 
12 12
 // Package gobaudot provides a set of tools to encode, modulate, demodulate and
13 13
 // baudot/TTY/RTTY data streams
14
-package gobaudot
14
+package gortty
15 15
 
16 16
 import "math"
17 17
 

+ 1
- 1
decoder.go View File

@@ -9,7 +9,7 @@
9 9
 // the Free Software Foundation; either version 2.1 of the License, or (at
10 10
 // your option) any later version.
11 11
 
12
-package gobaudot
12
+package gortty
13 13
 
14 14
 // Decoder converts a stream of bytes representing baudot codes into a stream
15 15
 // of unicode runes.

+ 1
- 1
demodulator.go View File

@@ -9,7 +9,7 @@
9 9
 // the Free Software Foundation; either version 2.1 of the License, or (at
10 10
 // your option) any later version.
11 11
 
12
-package gobaudot
12
+package gortty
13 13
 
14 14
 import (
15 15
 	//"fmt"

+ 1
- 1
dsp.go View File

@@ -9,7 +9,7 @@
9 9
 // the Free Software Foundation; either version 2.1 of the License, or (at
10 10
 // your option) any later version.
11 11
 
12
-package gobaudot
12
+package gortty
13 13
 
14 14
 import "math"
15 15
 

+ 1
- 1
encoder.go View File

@@ -9,7 +9,7 @@
9 9
 // the Free Software Foundation; either version 2.1 of the License, or (at
10 10
 // your option) any later version.
11 11
 
12
-package gobaudot
12
+package gortty
13 13
 
14 14
 
15 15
 // Encoder is fun

+ 7
- 7
examples/audioin/main.go View File

@@ -4,12 +4,12 @@ import (
4 4
 	"fmt"
5 5
 
6 6
 	"github.com/gordonklaus/portaudio"
7
-	"github.com/naleek/openbaudot"
7
+	"github.com/naleek/gortty"
8 8
 )
9 9
 
10 10
 func main() {
11 11
 
12
-	s := &gobaudot.ModemSettings{
12
+	s := &gortty.ModemSettings{
13 13
 		Baud:       45,
14 14
 		StopBits:   2,
15 15
 		DataBits:   5,
@@ -27,7 +27,7 @@ func main() {
27 27
 		panic(err)
28 28
 	}
29 29
 	defer stream.Close()
30
-	charset := gobaudot.LoadCharset(&gobaudot.USTTY)
30
+	charset := gortty.LoadCharset(&gortty.USTTY)
31 31
 	//
32 32
 	// encoderIn := make(chan rune)
33 33
 	// modulatorIn := make(chan byte)
@@ -39,10 +39,10 @@ func main() {
39 39
 	//done := make(chan struct{})
40 40
 
41 41
 	//sig := make(chan [2]float64)
42
-	// encoder := gobaudot.NewEncoder(encoderIn, modulatorIn, charset)
43
-	// gobaudot.NewModulator(s, modulatorIn, demodulatorIn)
44
-	gobaudot.NewDemodulator(s, demodulatorIn, decoderIn)
45
-	gobaudot.NewDecoder(decoderIn, decoderOut, charset)
42
+	// encoder := gortty.NewEncoder(encoderIn, modulatorIn, charset)
43
+	// gortty.NewModulator(s, modulatorIn, demodulatorIn)
44
+	gortty.NewDemodulator(s, demodulatorIn, decoderIn)
45
+	gortty.NewDecoder(decoderIn, decoderOut, charset)
46 46
 
47 47
 	go func() {
48 48
 		for {

+ 3
- 3
examples/demtest.go View File

@@ -5,7 +5,7 @@ import (
5 5
 	"math"
6 6
 	"math/rand"
7 7
 
8
-	"github.com/naleek/openbaudot"
8
+	"github.com/naleek/gortty"
9 9
 )
10 10
 
11 11
 // 96000 = 14
@@ -34,7 +34,7 @@ func dostuff(freq int) float64 {
34 34
 
35 35
 	done := make(chan bool)
36 36
 
37
-	s := &openbaudot.ModemSettings{
37
+	s := &gortty.ModemSettings{
38 38
 		Baud:       45,
39 39
 		StopBits:   2,
40 40
 		DataBits:   5,
@@ -102,7 +102,7 @@ func dostuff(freq int) float64 {
102 102
 		done <- true
103 103
 	}()
104 104
 
105
-	openbaudot.NewDumbDemodulator(s, demodulatorIn, demodulatorOut)
105
+	gortty.NewDumbDemodulator(s, demodulatorIn, demodulatorOut)
106 106
 	c := 0
107 107
 	running := true
108 108
 	var r float64

+ 0
- 175
examples/foo/main.go View File

@@ -1,176 +0,0 @@
1
-package main
2
-
3
-import (
4
-	"fmt"
5
-
6
-	"github.com/gordonklaus/portaudio"
7
-	"github.com/naleek/openbaudot"
8
-)
9
-
10
-// CLoIP
11
-// Current Loop over IP
12
-// A Terrible Protocol
13
-// Based on TCP (because latency really doesn't matter)
14
-// Full duplex
15
-
16
-// client-server protocol
17
-// server handles pairing
18
-// client handles encoding/decoding
19
-
20
-/*
21
-
22
-SERVER
23
-
24
-<client connects>
25
-
26
->> greeting message
27
-<< IAM <client ID>
28
->> 200 ok
29
-
30
-<< RATE 1000
31
->> 200 ok
32
-
33
-<< WAIT
34
->> 200 ok <connection ID>
35
-
36
-
37
-
38
-<< JOIN <connection ID>
39
->> 200 ok
40
-
41
-
42
-
43
-
44
-*/
45
-
46
-type Frame struct {
47
-	Seq		uint32
48
-	Len		uint32
49
-	Samples []byte
50
-}
51
-
52
-func main() {
53
-
54
-	s := &gobaudot.ModemSettings{
55
-		Baud:       45,
56
-		StopBits:   2,
57
-		DataBits:   5,
58
-		SampleRate: 8000,
59
-		OneFreq:    2125,
60
-		ZeroFreq:   2295,
61
-	}
62
-
63
-	portaudio.Initialize()
64
-	defer portaudio.Terminate()
65
-
66
-	in := make([]int16, 64)
67
-	stream, err := portaudio.OpenDefaultStream(1, 0, float64(s.SampleRate), len(in), in)
68
-	if err != nil {
69
-		panic(err)
70
-	}
71
-	defer stream.Close()
72
-	
73
-	chopperIn := make(chan int16)
74
-	chopperOut := make(chan gobaudot.TimeSlice)
75
-	
76
-	gobaudot.NewChopper(s, chopperIn, chopperOut)
77
-
78
-
79
-	var buff byte
80
-	var bits int
81
-	x := 0
82
-	
83
-	sampleRate := 500
84
-	
85
-	rollover := s.SampleRate/sampleRate
86
-	
87
-	fmt.Println("Data Rate: ", sampleRate/8, "bytes per second")
88
-	fmt.Println(rollover)
89
-	
90
-	go func() {
91
-		for {
92
-			r := <-chopperOut
93
-			x++
94
-			
95
-			if r.Carrier && x%rollover==0 {
96
-				buff = buff << 1
97
-				bits++
98
-				if r.Marking {
99
-					buff = buff | 0x01
100
-				}
101
-				if bits == 8 {
102
-					fmt.Printf("%x",buff)
103
-					bits = 0
104
-					buff = 0
105
-				}
106
-				//fmt.Println(r.LpfVal, r.ThreshVal)
107
-			}
108
-		}
109
-	}()
110
-
111
-	stream.Start()
112
-	for {
113
-		stream.Read()
114
-		for i := range in {
115
-			chopperIn <- in[i]
116
-		}
117
-
118
-	}
119
-	//stream.Stop()
120
-
121
-	// go func() {
122
-	// 	encoder.EncodeString("hello world")
123
-	// 	time.Sleep(2000 * time.Millisecond)
124
-	// 	done <- struct{}{}
125
-	// }()
126
-
127
-}
128
-
129
-// // NewOBL is fun
130
-// func NewOBL(baud float64, callback Callback) *OBL {
131
-//
132
-// 	obl := new(OBL)
133
-//
134
-// 	obl.charset = USTTY.initialize()
135
-//
136
-// 	obl.callback = callback
137
-//
138
-// 	obl.mod.sinLutQ15 = make([]int16, 16384)
139
-// 	for i := 0; i < 16384; i++ {
140
-// 		obl.mod.sinLutQ15[i] = int16(32767 * math.Sin(2.0*math.Pi*float64(i)/float64(16384)))
141
-// 	}
142
-//
143
-// 	/* regular reset */
144
-// 	obl.autobaud.enabled = true
145
-// 	obl.Reset(baud)
146
-//
147
-// 	go func() {
148
-// 		portaudio.Initialize()
149
-// 		defer portaudio.Terminate()
150
-//
151
-// 		x := make(chan int16, 300)
152
-//
153
-// 		stream, _ := portaudio.OpenDefaultStream(0, 1, float64(sampleRate), 0, func(out []int16) {
154
-// 			for i := range out {
155
-// 				out[i] = <-x
156
-// 			}
157
-// 		})
158
-//
159
-// 		stream.Start()
160
-//
161
-// 		for {
162
-// 			s := <-obl.mod.output
163
-// 			//go func() {
164
-// 			obl.demod.input <- s
165
-// 			x <- s
166
-// 			//}()
167
-// 			//	binary.Write(f, binary.LittleEndian, s)
168
-// 		}
169
-// 	}()
170
-//
171
-// 	go obl.Modulate()
172
-// 	go obl.Demodulate()
173
-//
174
-// 	return obl
175
-// }

+ 10
- 10
examples/main.go View File

@@ -4,7 +4,7 @@ import (
4 4
 	"fmt"
5 5
 	"time"
6 6
 
7
-	"github.com/naleek/openbaudot"
7
+	"github.com/naleek/gortty"
8 8
 )
9 9
 
10 10
 type TTYFrame struct {
@@ -15,7 +15,7 @@ type TTYFrame struct {
15 15
 
16 16
 func main() {
17 17
 
18
-	s := &gobaudot.ModemSettings{
18
+	s := &gortty.ModemSettings{
19 19
 		Baud:       45,
20 20
 		StopBits:   2,
21 21
 		DataBits:   5,
@@ -24,7 +24,7 @@ func main() {
24 24
 		ZeroFreq:   2295,
25 25
 	}
26 26
 
27
-	charset := gobaudot.LoadCharset(&gobaudot.USTTY)
27
+	charset := gortty.LoadCharset(&gortty.USTTY)
28 28
 
29 29
 	encoderIn := make(chan rune)
30 30
 	modulatorIn := make(chan byte)
@@ -34,18 +34,18 @@ func main() {
34 34
 //	decoderOut := make(chan rune)
35 35
 
36 36
 	chopperIn := make(chan int16)
37
-	chopperOut := make(chan gobaudot.TimeSlice)
37
+	chopperOut := make(chan gortty.TimeSlice)
38 38
 	
39 39
 	done := make(chan struct{})
40 40
 
41 41
 	//sig := make(chan [2]float64)
42
-	encoder := gobaudot.NewEncoder(encoderIn, modulatorIn, charset)
43
-	gobaudot.NewModulator(s, modulatorIn, chopperIn)
44
-//	gobaudot.NewModulator(s, modulatorIn, demodulatorIn)
45
-	//gobaudot.NewDemodulator(s, demodulatorIn, decoderIn)
46
-//	gobaudot.NewDecoder(decoderIn, decoderOut, charset)
42
+	encoder := gortty.NewEncoder(encoderIn, modulatorIn, charset)
43
+	gortty.NewModulator(s, modulatorIn, chopperIn)
44
+//	gortty.NewModulator(s, modulatorIn, demodulatorIn)
45
+	//gortty.NewDemodulator(s, demodulatorIn, decoderIn)
46
+//	gortty.NewDecoder(decoderIn, decoderOut, charset)
47 47
 
48
-	gobaudot.NewChopper(s, chopperIn, chopperOut)
48
+	gortty.NewChopper(s, chopperIn, chopperOut)
49 49
 
50 50
 	go func() {
51 51
 		encoder.EncodeString("hello world")

+ 63
- 0
examples/rawdemod/main.go View File

@@ -0,0 +1,63 @@
1
+package main
2
+
3
+import (
4
+	"fmt"
5
+
6
+	"github.com/gordonklaus/portaudio"
7
+	"github.com/naleek/gortty"
8
+)
9
+
10
+
11
+type Frame struct {
12
+	Seq		uint32
13
+	Len		uint32
14
+	Samples []byte
15
+}
16
+
17
+func main() {
18
+
19
+	s := &gortty.ModemSettings{
20
+		Baud:       45,
21
+		StopBits:   2,
22
+		DataBits:   5,
23
+		SampleRate: 8000,
24
+		OneFreq:    2125,
25
+		ZeroFreq:   2295,
26
+	}
27
+
28
+
29
+	portaudio.Initialize()
30
+	defer portaudio.Terminate()
31
+
32
+	in := make([]int16, 64)
33
+	
34
+	stream, err := portaudio.OpenDefaultStream(1, 0, float64(s.SampleRate), len(in), in)
35
+	if err != nil {
36
+		panic(err)
37
+	}
38
+	defer stream.Close()
39
+	
40
+	RawDemodulatorIn := make(chan int16)
41
+	RawDemodulatorOut := make(chan gortty.DCSignal)
42
+	
43
+	gortty.NewRawDemodulator(s, RawDemodulatorIn, RawDemodulatorOut)
44
+	
45
+
46
+	stream.Start()
47
+	
48
+	go func() {
49
+		for v := range RawDemodulatorOut {
50
+			fmt.Println(v)
51
+		}
52
+	}()
53
+	
54
+	for {
55
+		stream.Read()
56
+		for i := range in {
57
+			RawDemodulatorIn <- in[i]
58
+		}
59
+	}
60
+	
61
+	
62
+
63
+}

+ 73
- 0
examples/rawinrawout/main.go View File

@@ -0,0 +1,73 @@
1
+package main
2
+
3
+import (
4
+	"github.com/gordonklaus/portaudio"
5
+	"github.com/naleek/gortty"
6
+	//"fmt"
7
+)
8
+
9
+
10
+
11
+func main() {
12
+
13
+	s := &gortty.ModemSettings{
14
+		Baud:       45,
15
+		StopBits:   2,
16
+		DataBits:   5,
17
+		SampleRate: 8000,
18
+		OneFreq:    1444,
19
+		ZeroFreq:   1626,
20
+	}
21
+	
22
+	s2 := &gortty.ModemSettings{
23
+		Baud:       45,
24
+		StopBits:   2,
25
+		DataBits:   5,
26
+		SampleRate: 8000,
27
+		OneFreq:    2125,
28
+		ZeroFreq:   2295,
29
+	}
30
+
31
+	portaudio.Initialize()
32
+	defer portaudio.Terminate()
33
+
34
+	in := make([]int16, 64)
35
+	out := make([]int16, 64)
36
+
37
+	stream, err := portaudio.OpenDefaultStream(1, 1, float64(s.SampleRate), len(in), in, out)
38
+	if err != nil {
39
+		panic(err)
40
+	}
41
+	defer stream.Close()
42
+	
43
+	RawDemodulatorIn := make(chan int16)
44
+	RawDemodulatorOut := make(chan gortty.DCSignal)
45
+	RawModulatorOut := make(chan int16)
46
+	
47
+	gortty.NewRawDemodulator(s, RawDemodulatorIn, RawDemodulatorOut)
48
+	gortty.NewRawModulator(s2, RawDemodulatorOut, RawModulatorOut)
49
+
50
+	stream.Start()
51
+	
52
+	go func() {
53
+		l := 0
54
+		for v := range RawModulatorOut {
55
+			out[l] = v
56
+			l++
57
+			if l == 64 {
58
+				l = 0
59
+				stream.Write()
60
+			}
61
+		}
62
+	}()
63
+	
64
+	for {
65
+		stream.Read()
66
+		for i := range in {
67
+			RawDemodulatorIn <- in[i]
68
+		}
69
+
70
+	}
71
+
72
+}
73
+

+ 8
- 8
examples/rttymodem/main.go View File

@@ -6,7 +6,7 @@ import (
6 6
 	"bufio"
7 7
 	"bytes"
8 8
 	"github.com/gordonklaus/portaudio"
9
-	"github.com/naleek/openbaudot"
9
+	"github.com/naleek/gortty"
10 10
 	"io"
11 11
 	"net"
12 12
 	"os"
@@ -24,7 +24,7 @@ func msain() {
24 24
 
25 25
 func main() {
26 26
 	fmt.Println("hi")
27
-	s := &gobaudot.ModemSettings{
27
+	s := &gortty.ModemSettings{
28 28
 		Baud:       45,
29 29
 		StopBits:   2,
30 30
 		DataBits:   5,
@@ -43,7 +43,7 @@ func main() {
43 43
 		panic(err)
44 44
 	}
45 45
 	defer stream.Close()
46
-	charset := gobaudot.LoadCharset(&gobaudot.USTTY)
46
+	charset := gortty.LoadCharset(&gortty.USTTY)
47 47
 
48 48
 	encoderIn := make(chan rune, 100)
49 49
 	modulatorIn := make(chan byte)
@@ -58,11 +58,11 @@ func main() {
58 58
 	modemWriter := NewModemWriter(encoderIn)
59 59
 
60 60
 	
61
-	gobaudot.NewEncoder(encoderIn, modulatorIn, charset)
62
-	modulator := gobaudot.NewModulator(s, modulatorIn, modulatorOut)
61
+	gortty.NewEncoder(encoderIn, modulatorIn, charset)
62
+	modulator := gortty.NewModulator(s, modulatorIn, modulatorOut)
63 63
 
64
-	gobaudot.NewDemodulator(s, demodulatorIn, decoderIn)
65
-	gobaudot.NewDecoder(decoderIn, decoderOut, charset)
64
+	gortty.NewDemodulator(s, demodulatorIn, decoderIn)
65
+	gortty.NewDecoder(decoderIn, decoderOut, charset)
66 66
 
67 67
 	//go CLI(modemReader, modemWriter)
68 68
 	modulator.SetAmplitude(0)
@@ -146,7 +146,7 @@ func (m *ModemWriter) Get() rune {
146 146
 	return <-m.output
147 147
 }
148 148
 
149
-func CLI(ttyReader io.Reader, ttyWriter io.Writer, modulator *gobaudot.Modulator) {
149
+func CLI(ttyReader io.Reader, ttyWriter io.Writer, modulator *gortty.Modulator) {
150 150
 
151 151
 	fmt.Fprintln(ttyWriter, "RTTY TCP Modem 1.0")
152 152
 

+ 2
- 2
gobaudot_test.go View File

@@ -1,9 +1,9 @@
1
-package gobaudot_test
1
+package gortty_test
2 2
 
3 3
 import (
4 4
 	"testing"
5 5
 
6
-	"github.com/naleek/openbaudot"
6
+	"github.com/naleek/gortty"
7 7
 )
8 8
 
9 9
 func TestEncoder(t *testing.T) {

+ 1
- 1
modulator.go View File

@@ -9,7 +9,7 @@
9 9
 // the Free Software Foundation; either version 2.1 of the License, or (at
10 10
 // your option) any later version.
11 11
 
12
-package gobaudot
12
+package gortty
13 13
 
14 14
 import "math"
15 15
 

+ 95
- 0
rawdemodulator.go View File

@@ -0,0 +1,95 @@
1
+// Copyright (C) 2017 Keelan Lightfoot
2
+// Copyright (C) 2007-2008 Board of Regents of the University of Wisconsin
3
+//             System (Univ. of Wisconsin-Madison, Trace R&D Center)
4
+// Copyright (C) 2007-2008 Omnitor AB
5
+// Copyright (C) 2007-2008 Voiceriver Inc
6
+//
7
+// This library is free software; you can redistribute it and/or modify it
8
+// under the terms of the GNU Lesser General Public License as published by
9
+// the Free Software Foundation; either version 2.1 of the License, or (at
10
+// your option) any later version.
11
+
12
+package gortty
13
+
14
+import (
15
+	"math"
16
+)
17
+
18
+
19
+
20
+// RawDemodulator is fun
21
+type RawDemodulator struct {
22
+	input         chan int16
23
+	output        chan DCSignal  
24
+	dsp           *dsp
25
+	settings      *ModemSettings
26
+	sigOut        bool
27
+	samplerate    int
28
+	div           int
29
+}
30
+
31
+// NewRawDemodulator is fun
32
+func NewRawDemodulator(s *ModemSettings, input chan int16, output chan DCSignal) *RawDemodulator {
33
+
34
+	d := new(RawDemodulator)
35
+	d.input = input
36
+	d.output = output
37
+	
38
+	d.settings = s
39
+
40
+	// the bandpass filter is picky about the sample rate, and the output is perfectly
41
+	// balanced when the sample rate is 3x the center frequency, so lets divide the sample
42
+	// rate down to as close to that as we can get.
43
+
44
+	centerFrequency := math.Abs(float64(d.settings.OneFreq)+float64(d.settings.ZeroFreq)) / 2 * 3
45
+
46
+	d.div = int(math.Floor(float64(d.settings.SampleRate) / float64(centerFrequency)))
47
+	if d.div == 0 {
48
+		d.div = 1
49
+	}
50
+
51
+	d.samplerate = d.settings.SampleRate / d.div
52
+	
53
+	d.dsp = newDsp(d.settings.OneFreq, d.settings.ZeroFreq, d.samplerate)
54
+
55
+	go d.run()
56
+	return d
57
+}
58
+
59
+func (d *RawDemodulator) run() {
60
+
61
+	count := 0
62
+	for sam := range d.input {
63
+	
64
+		// sample rate reduction
65
+		count++
66
+		if count%d.div > 0 {
67
+			continue
68
+		}
69
+
70
+		d.dsp.demod(float64(sam))
71
+
72
+		var signal int8
73
+		var quality int8
74
+		
75
+
76
+		if math.Abs(d.dsp.demLpf) > d.dsp.demTotal*d.dsp.minThresh && d.dsp.demTotal*d.dsp.minThresh != 0 {
77
+			quality = 1
78
+		} else {
79
+			quality = 0
80
+		}
81
+
82
+		if d.dsp.demLpf - d.dsp.minThresh*d.dsp.demTotal > 0 {
83
+			signal = 1*quality
84
+		} else {
85
+			signal = -1*quality
86
+		}	
87
+				
88
+		d.output <-  DCSignal {
89
+			Signal: signal,
90
+			Quality: quality,
91
+		}
92
+		
93
+	}
94
+
95
+}

+ 92
- 0
rawmodulator.go View File

@@ -0,0 +1,92 @@
1
+// Copyright (C) 2017 Keelan Lightfoot
2
+// Copyright (C) 2007-2008 Board of Regents of the University of Wisconsin
3
+//             System (Univ. of Wisconsin-Madison, Trace R&D Center)
4
+// Copyright (C) 2007-2008 Omnitor AB
5
+// Copyright (C) 2007-2008 Voiceriver Inc
6
+//
7
+// This library is free software; you can redistribute it and/or modify it
8
+// under the terms of the GNU Lesser General Public License as published by
9
+// the Free Software Foundation; either version 2.1 of the License, or (at
10
+// your option) any later version.
11
+
12
+package gortty
13
+
14
+import "math"
15
+//import "fmt"
16
+
17
+type DCSignal struct {
18
+	Signal int8
19
+	Quality int8
20
+}
21
+
22
+// RawModulator is fun
23
+type RawModulator struct {
24
+	input  chan DCSignal
25
+	output chan int16
26
+
27
+	settings *ModemSettings
28
+
29
+	phaseQ16        uint16  // phase acc 0..2math.Pi -> 0..65536
30
+	amplitude       int16   // peak RawModulator amplitude for one tone
31
+	wOneQ16         uint16  // scaled one freq 0..2math.Pi -> 0..65536
32
+	wZeroQ16        uint16  // scaled zero freq 0..2math.Pi -> 0..65536
33
+	sinLutQ15       []int16 // sine lookup table
34
+	callback        Callback
35
+}
36
+
37
+// NewRawModulator is fun
38
+func NewRawModulator(s *ModemSettings, input chan DCSignal, output chan int16) *RawModulator {
39
+
40
+	m := new(RawModulator)
41
+
42
+	m.input = input
43
+	m.output = output
44
+
45
+	m.settings = s
46
+
47
+	m.amplitude = 16384
48
+
49
+	wOne, wZero := calculateW(m.settings.OneFreq, m.settings.ZeroFreq, m.settings.SampleRate)
50
+
51
+	m.wOneQ16 = uint16((65536 / (2.0 * math.Pi)) * wOne)
52
+	m.wZeroQ16 = uint16((65536 / (2.0 * math.Pi)) * wZero)
53
+
54
+	m.sinLutQ15 = make([]int16, 16384)
55
+	for i := 0; i < 16384; i++ {
56
+		m.sinLutQ15[i] = int16(32767 * math.Sin(2.0*math.Pi*float64(i)/float64(16384)))
57
+	}
58
+	go m.run()
59
+	return m
60
+}
61
+
62
+// SetCallback is fun
63
+func (m *RawModulator) SetCallback(callback Callback) {
64
+	m.callback = callback
65
+}
66
+
67
+func (m *RawModulator) SetAmplitude(amplitude int16) {
68
+	m.amplitude = amplitude
69
+}
70
+
71
+func (m *RawModulator) run() {
72
+
73
+	var lut uint16
74
+	for {
75
+		select {
76
+		case s := <-m.input:
77
+			if s.Signal > 0 {
78
+				lut = m.wOneQ16
79
+			} else {
80
+				lut = m.wZeroQ16
81
+			}
82
+			m.phaseQ16 += lut
83
+			if s.Quality > 0 {
84
+				m.output <- multq15(m.amplitude, m.sinLutQ15[m.phaseQ16>>2])
85
+			} else {
86
+				m.output <- 0
87
+			}
88
+		}
89
+		
90
+	}			
91
+
92
+}