Compare commits

...

13 commits
master ... fhss

Author SHA1 Message Date
bemasher
654ad4c14a Pattern retracing complete. 2014-12-01 23:19:29 -07:00
bemasher
1ca6c9fdee Refactor argmax calculation. 2014-12-01 23:18:12 -07:00
bemasher
84711a3554 Add channels, hop flag and HopMessage. 2014-11-13 00:54:54 -07:00
bemasher
18fbe7b177 Add HopMessage and Logger interface. 2014-11-13 00:54:25 -07:00
bemasher
e6fc295967 Add hop flag. 2014-11-13 00:53:33 -07:00
bemasher
18f096ab21 Reset all buffers. Correct channel detection output. 2014-11-13 00:53:21 -07:00
Douglas Hall
8562b8ea6d Remove coverage profile. 2014-11-10 01:38:21 -07:00
bemasher
2d79fc24bd Add channel detection on valid messages. 2014-11-10 01:06:52 -07:00
bemasher
9f25bb68f5 Add channel to LogMessage. 2014-11-10 01:06:27 -07:00
bemasher
d375923436 Add condition on excess bandwidth for channel detection. 2014-11-10 01:05:51 -07:00
bemasher
447b64076f Change default symbollength to more channel detection friendly value. 2014-11-10 01:05:21 -07:00
bemasher
e04239caf9 Add periodogram for channel detection. 2014-11-10 01:04:46 -07:00
bemasher
0d9e5721e9 Add short-length dfts for periodogram. 2014-11-10 01:03:51 -07:00
19 changed files with 1819 additions and 42 deletions

View file

@ -20,6 +20,12 @@ import (
"fmt" "fmt"
"log" "log"
"math" "math"
"github.com/bemasher/rtlamr/decode/dft"
)
const (
ChannelWidth = 196568
) )
// PacketConfig specifies packet-specific radio configuration. // PacketConfig specifies packet-specific radio configuration.
@ -44,6 +50,8 @@ func (cfg PacketConfig) Log() {
log.Println("PreambleLength:", cfg.PreambleLength) log.Println("PreambleLength:", cfg.PreambleLength)
log.Println("PacketSymbols:", cfg.PacketSymbols) log.Println("PacketSymbols:", cfg.PacketSymbols)
log.Println("PacketLength:", cfg.PacketLength) log.Println("PacketLength:", cfg.PacketLength)
log.Println("Channels:", cfg.SampleRate/ChannelWidth)
log.Println("ExcessBandwidth:", cfg.SampleRate%ChannelWidth)
log.Println("Preamble:", cfg.Preamble) log.Println("Preamble:", cfg.Preamble)
} }
@ -55,6 +63,10 @@ type Decoder struct {
Signal []float64 Signal []float64
Quantized []byte Quantized []byte
Periodogram Periodogram
Re, Im []float64
csum []float64 csum []float64
lut MagnitudeLUT lut MagnitudeLUT
@ -73,8 +85,13 @@ func NewDecoder(cfg PacketConfig, fastMag bool) (d Decoder) {
d.Signal = make([]float64, d.Cfg.BufferLength) d.Signal = make([]float64, d.Cfg.BufferLength)
d.Quantized = make([]byte, d.Cfg.BufferLength) d.Quantized = make([]byte, d.Cfg.BufferLength)
d.Re = make([]float64, d.Cfg.BufferLength)
d.Im = make([]float64, d.Cfg.BufferLength)
d.csum = make([]float64, d.Cfg.BlockSize+d.Cfg.SymbolLength2+1) d.csum = make([]float64, d.Cfg.BlockSize+d.Cfg.SymbolLength2+1)
d.Periodogram = NewPeriodogram(d.Cfg.SampleRate / ChannelWidth)
// Calculate magnitude lookup table specified by -fastmag flag. // Calculate magnitude lookup table specified by -fastmag flag.
if fastMag { if fastMag {
d.lut = NewAlphaMaxBetaMinLUT() d.lut = NewAlphaMaxBetaMinLUT()
@ -120,6 +137,13 @@ func (d Decoder) Decode(input []byte) (pkts [][]byte) {
iqBlock := d.IQ[d.Cfg.PacketLength<<1:] iqBlock := d.IQ[d.Cfg.PacketLength<<1:]
signalBlock := d.Signal[d.Cfg.PacketLength:] signalBlock := d.Signal[d.Cfg.PacketLength:]
re := d.Re[d.Cfg.PacketLength:]
im := d.Im[d.Cfg.PacketLength:]
for idx := range signalBlock {
re[idx] = 127.4 - float64(d.IQ[idx<<1])
im[idx] = 127.4 - float64(d.IQ[idx<<1+1])
}
// Compute the magnitude of the new block. // Compute the magnitude of the new block.
d.lut.Execute(iqBlock, signalBlock) d.lut.Execute(iqBlock, signalBlock)
@ -167,6 +191,90 @@ func (d Decoder) Decode(input []byte) (pkts [][]byte) {
return return
} }
func (d Decoder) Reset() {
for idx := range d.IQ {
d.IQ[idx] = 0
}
for idx := range d.Signal {
d.Signal[idx] = 0
d.Quantized[idx] = 0
d.Re[idx] = 0
d.Im[idx] = 0
}
}
type Periodogram struct {
length int
power []float64
re, im []float64
dft func(ri, ii, ro, io []float64)
}
func NewPeriodogram(n int) (p Periodogram) {
p.length = n
p.power = make([]float64, p.length)
p.re = make([]float64, p.length)
p.im = make([]float64, p.length)
switch p.length {
case 5:
p.dft = dft.DFT5
case 6:
p.dft = dft.DFT6
case 7:
p.dft = dft.DFT7
case 8:
p.dft = dft.DFT8
case 9:
p.dft = dft.DFT9
case 10:
p.dft = dft.DFT10
case 11:
p.dft = dft.DFT11
case 12:
p.dft = dft.DFT12
case 13:
p.dft = dft.DFT13
case 14:
p.dft = dft.DFT14
case 15:
p.dft = dft.DFT15
case 16:
p.dft = dft.DFT16
default:
panic(fmt.Errorf("invalid transform length: %d", p.length))
}
return
}
func (p Periodogram) Execute(re, im []float64) (argmax int) {
for idx := range p.power {
p.power[idx] = 0
}
for idx := 0; idx < len(re)-p.length; idx += p.length >> 1 {
p.dft(re[idx:], im[idx:], p.re, p.im)
for pIdx := range p.power {
p.power[pIdx] += math.Sqrt(p.re[pIdx]*p.re[pIdx] + p.im[pIdx]*p.im[pIdx])
}
}
max := 0.0
for idx, val := range p.power {
if max < val {
max = val
argmax = idx
}
}
if argmax > (p.length>>1 + p.length&1) {
argmax -= p.length
}
return argmax
}
// A MagnitudeLUT knows how to perform complex magnitude on a slice of IQ samples. // A MagnitudeLUT knows how to perform complex magnitude on a slice of IQ samples.
type MagnitudeLUT interface { type MagnitudeLUT interface {
Execute([]byte, []float64) Execute([]byte, []float64)

54
decode/dft/constants.go Normal file
View file

@ -0,0 +1,54 @@
package dft
const (
I = 1i
KP011599105 = +0.011599105605768290721655456654083252189827041
KP075902986 = +0.075902986037193865983102897245103540356428373
KP083333333 = +0.083333333333333333333333333333333333333333333
KP113854479 = +0.113854479055790798974654345867655310534642560
KP132983124 = +0.132983124607418643793760531921092974399165133
KP142314838 = +0.142314838273285140443792668616369668791051361
KP156891391 = +0.156891391051584611046832726756003269660212636
KP173648177 = +0.173648177666930348851716626769314796000375677
KP174138601 = +0.174138601152135905005660794929264742616964676
KP222520933 = +0.222520933956314404288902564496794759466355569
KP250000000 = +0.250000000000000000000000000000000000000000000
KP251768516 = +0.251768516431883313623436926934233488546674281
KP256247671 = +0.256247671582936600958684654061725059144125175
KP258260390 = +0.258260390311744861420450644284508567852516811
KP265966249 = +0.265966249214837287587521063842185948798330267
KP281732556 = +0.281732556841429697711417915346616899035777899
KP300238635 = +0.300238635966332641462884626667381504676006424
KP300462606 = +0.300462606288665774426601772289207995520941381
KP342020143 = +0.342020143325668733044099614682259580763083368
KP382683432 = +0.382683432365089771728459984030398866761344562
KP387390585 = +0.387390585467617292130675966426762851778775217
KP415415013 = +0.415415013001886425529274149229623203524004910
KP433883739 = +0.433883739117558120475768332848358754609990728
KP500000000 = +0.500000000000000000000000000000000000000000000
KP503537032 = +0.503537032863766627246873853868466977093348562
KP540640817 = +0.540640817455597582107635954318691695431770608
KP559016994 = +0.559016994374947424102293417182819058860154590
KP575140729 = +0.575140729474003121368385547455453388461001608
KP587785252 = +0.587785252292473129168705954639072768597652438
KP623489801 = +0.623489801858733530525004884004239810632274731
KP642787609 = +0.642787609686539326322643409907263432907559884
KP654860733 = +0.654860733945285064056925072466293553183791199
KP707106781 = +0.707106781186547524400844362104849039284835938
KP755749574 = +0.755749574354258283774035843972344420179717445
KP766044443 = +0.766044443118978035202392650555416673935832457
KP781831482 = +0.781831482468029808708444526674057750232334519
KP841253532 = +0.841253532831181168861811648919367717513292498
KP866025403 = +0.866025403784438646763723170752936183471402627
KP900968867 = +0.900968867902419126236102319507445051165919162
KP909631995 = +0.909631995354518371411715383079028460060241051
KP923879532 = +0.923879532511286756128183189396788286822416626
KP939692620 = +0.939692620785908384054109277324731469936208134
KP951056516 = +0.951056516295153572116439333379382143405698634
KP959492973 = +0.959492973614497389890368057066327699062454848
KP974927912 = +0.974927912181823607018131682993931217232785801
KP984807753 = +0.984807753012208059366743024589523013670643252
KP989821441 = +0.989821441880932732376092037776718787376519372
KP1_732050807 = +1.732050807568877293527446341505872366942805254
KP2_000000000 = +2.000000000000000000000000000000000000000000000
)

108
decode/dft/dft10.go Normal file
View file

@ -0,0 +1,108 @@
package dft
func DFT10(ri, ii, ro, io []float64) {
T1 := ri[0]
T2 := ri[5]
T3 := T1 - T2
T19 := T1 + T2
T50 := ii[0]
T51 := ii[5]
T52 := T50 - T51
T76 := T50 + T51
T4 := ri[2]
T5 := ri[7]
T6 := T4 - T5
T20 := T4 + T5
T14 := ri[6]
T15 := ri[1]
T16 := T14 - T15
T24 := T14 + T15
T7 := ri[8]
T8 := ri[3]
T9 := T7 - T8
T21 := T7 + T8
T11 := ri[4]
T12 := ri[9]
T13 := T11 - T12
T23 := T11 + T12
T56 := T6 - T9
T57 := T13 - T16
T74 := T20 - T21
T73 := T23 - T24
T22 := T20 + T21
T25 := T23 + T24
T26 := T22 + T25
T10 := T6 + T9
T17 := T13 + T16
T18 := T10 + T17
T30 := ii[2]
T31 := ii[7]
T32 := T30 - T31
T67 := T30 + T31
T40 := ii[6]
T41 := ii[1]
T42 := T40 - T41
T65 := T40 + T41
T33 := ii[8]
T34 := ii[3]
T35 := T33 - T34
T68 := T33 + T34
T37 := ii[4]
T38 := ii[9]
T39 := T37 - T38
T64 := T37 + T38
T36 := T32 - T35
T43 := T39 - T42
T69 := T67 - T68
T66 := T64 - T65
T77 := T67 + T68
T78 := T64 + T65
T79 := T77 + T78
T47 := T32 + T35
T48 := T39 + T42
T53 := T47 + T48
ro[5] = T3 + T18
io[5] = T52 + T53
ro[0] = T19 + T26
io[0] = T76 + T79
T44 := (KP951056516 * T36) + (KP587785252 * T43)
T46 := (KP951056516 * T43) - (KP587785252 * T36)
T27 := KP559016994 * (T10 - T17)
T28 := T3 - (KP250000000 * T18)
T29 := T27 + T28
T45 := T28 - T27
ro[9] = T29 - T44
ro[3] = T45 + T46
ro[1] = T29 + T44
ro[7] = T45 - T46
T58 := (KP951056516 * T56) + (KP587785252 * T57)
T60 := (KP951056516 * T57) - (KP587785252 * T56)
T49 := KP559016994 * (T47 - T48)
T54 := T52 - (KP250000000 * T53)
T55 := T49 + T54
T59 := T54 - T49
io[1] = T55 - T58
io[7] = T60 + T59
io[9] = T58 + T55
io[3] = T59 - T60
T70 := (KP951056516 * T66) - (KP587785252 * T69)
T72 := (KP951056516 * T69) + (KP587785252 * T66)
T61 := T19 - (KP250000000 * T26)
T62 := KP559016994 * (T22 - T25)
T63 := T61 - T62
T71 := T62 + T61
ro[2] = T63 - T70
ro[6] = T71 + T72
ro[8] = T63 + T70
ro[4] = T71 - T72
T75 := (KP951056516 * T73) - (KP587785252 * T74)
T83 := (KP951056516 * T74) + (KP587785252 * T73)
T80 := T76 - (KP250000000 * T79)
T81 := KP559016994 * (T77 - T78)
T82 := T80 - T81
T84 := T81 + T80
io[2] = T75 + T82
io[6] = T84 - T83
io[8] = T82 - T75
io[4] = T83 + T84
}

88
decode/dft/dft11.go Normal file
View file

@ -0,0 +1,88 @@
package dft
func DFT11(ri, ii, ro, io []float64) {
T1 := ri[0]
T48 := ii[0]
T2 := ri[1]
T3 := ri[10]
T4 := T2 + T3
T42 := T3 - T2
T18 := ii[1]
T19 := ii[10]
T20 := T18 - T19
T53 := T18 + T19
T30 := ii[2]
T31 := ii[9]
T32 := T30 - T31
T49 := T30 + T31
T5 := ri[2]
T6 := ri[9]
T7 := T5 + T6
T46 := T6 - T5
T8 := ri[3]
T9 := ri[8]
T10 := T8 + T9
T43 := T9 - T8
T21 := ii[3]
T22 := ii[8]
T23 := T21 - T22
T52 := T21 + T22
T11 := ri[4]
T12 := ri[7]
T13 := T11 + T12
T45 := T12 - T11
T24 := ii[4]
T25 := ii[7]
T26 := T24 - T25
T50 := T24 + T25
T27 := ii[5]
T28 := ii[6]
T29 := T27 - T28
T51 := T27 + T28
T14 := ri[5]
T15 := ri[6]
T16 := T14 + T15
T44 := T15 - T14
ro[0] = T1 + T4 + T7 + T10 + T13 + T16
io[0] = T48 + T53 + T49 + T52 + T50 + T51
T33 := (KP755749574 * T20) + (KP540640817 * T23) + (KP281732556 * T26) - (KP909631995 * T29) - (KP989821441 * T32)
T17 := T1 + (KP841253532 * T10) + (KP415415013 * T16) - (KP959492973 * T13) - (KP142314838 * T7) - (KP654860733 * T4)
ro[7] = T17 - T33
ro[4] = T17 + T33
T61 := (KP755749574 * T42) + (KP540640817 * T43) + (KP281732556 * T45) - (KP909631995 * T44) - (KP989821441 * T46)
T62 := T48 + (KP841253532 * T52) + (KP415415013 * T51) - (KP959492973 * T50) - (KP142314838 * T49) - (KP654860733 * T53)
io[4] = T61 + T62
io[7] = T62 - T61
T59 := (KP909631995 * T42) + (KP755749574 * T46) - (KP540640817 * T44) - (KP989821441 * T45) - (KP281732556 * T43)
T60 := T48 + (KP415415013 * T53) + (KP841253532 * T51) - (KP142314838 * T50) - (KP959492973 * T52) - (KP654860733 * T49)
io[2] = T59 + T60
io[9] = T60 - T59
T35 := (KP909631995 * T20) + (KP755749574 * T32) - (KP540640817 * T29) - (KP989821441 * T26) - (KP281732556 * T23)
T34 := T1 + (KP415415013 * T4) + (KP841253532 * T16) - (KP142314838 * T13) - (KP959492973 * T10) - (KP654860733 * T7)
ro[9] = T34 - T35
ro[2] = T34 + T35
T37 := (KP540640817 * T20) + (KP909631995 * T32) + (KP989821441 * T23) + (KP755749574 * T26) + (KP281732556 * T29)
T36 := T1 + (KP841253532 * T4) + (KP415415013 * T7) - (KP959492973 * T16) - (KP654860733 * T13) - (KP142314838 * T10)
ro[10] = T36 - T37
ro[1] = T36 + T37
T57 := (KP540640817 * T42) + (KP909631995 * T46) + (KP989821441 * T43) + (KP755749574 * T45) + (KP281732556 * T44)
T58 := T48 + (KP841253532 * T53) + (KP415415013 * T49) - (KP959492973 * T51) - (KP654860733 * T50) - (KP142314838 * T52)
io[1] = T57 + T58
io[10] = T58 - T57
T39 := (KP989821441 * T20) + (KP540640817 * T26) + (KP755749574 * T29) - (KP909631995 * T23) - (KP281732556 * T32)
T38 := T1 + (KP415415013 * T10) + (KP841253532 * T13) - (KP654860733 * T16) - (KP959492973 * T7) - (KP142314838 * T4)
ro[8] = T38 - T39
ro[3] = T38 + T39
T55 := (KP989821441 * T42) + (KP540640817 * T45) + (KP755749574 * T44) - (KP909631995 * T43) - (KP281732556 * T46)
T56 := T48 + (KP415415013 * T52) + (KP841253532 * T50) - (KP654860733 * T51) - (KP959492973 * T49) - (KP142314838 * T53)
io[3] = T55 + T56
io[8] = T56 - T55
T47 := (KP281732556 * T42) + (KP755749574 * T43) + (KP989821441 * T44) - (KP909631995 * T45) - (KP540640817 * T46)
T54 := T48 + (KP841253532 * T49) + (KP415415013 * T50) - (KP142314838 * T51) - (KP654860733 * T52) - (KP959492973 * T53)
io[5] = T47 + T54
io[6] = T54 - T47
T41 := (KP281732556 * T20) + (KP755749574 * T23) + (KP989821441 * T29) - (KP909631995 * T26) - (KP540640817 * T32)
T40 := T1 + (KP841253532 * T7) + (KP415415013 * T13) - (KP142314838 * T16) - (KP654860733 * T10) - (KP959492973 * T4)
ro[6] = T40 - T41
ro[5] = T40 + T41
}

124
decode/dft/dft12.go Normal file
View file

@ -0,0 +1,124 @@
package dft
func DFT12(ri, ii, ro, io []float64) {
T1 := ri[0]
T2 := ri[4]
T3 := ri[8]
T4 := T2 + T3
T5 := T1 + T4
T53 := T1 - (KP500000000 * T4)
T36 := KP866025403 * (T3 - T2)
T24 := ii[0]
T25 := ii[4]
T26 := ii[8]
T27 := T25 + T26
T28 := T24 + T27
T54 := KP866025403 * (T25 - T26)
T35 := T24 - (KP500000000 * T27)
T6 := ri[6]
T7 := ri[10]
T8 := ri[2]
T9 := T7 + T8
T10 := T6 + T9
T56 := T6 - (KP500000000 * T9)
T39 := KP866025403 * (T8 - T7)
T29 := ii[6]
T30 := ii[10]
T31 := ii[2]
T32 := T30 + T31
T33 := T29 + T32
T57 := KP866025403 * (T30 - T31)
T38 := T29 - (KP500000000 * T32)
T12 := ri[3]
T13 := ri[7]
T14 := ri[11]
T15 := T13 + T14
T16 := T12 + T15
T72 := KP866025403 * (T14 - T13)
T42 := T12 - (KP500000000 * T15)
T73 := ii[3]
T43 := ii[7]
T44 := ii[11]
T74 := T43 + T44
T45 := KP866025403 * (T43 - T44)
T92 := T73 + T74
T75 := T73 - (KP500000000 * T74)
T17 := ri[9]
T18 := ri[1]
T19 := ri[5]
T20 := T18 + T19
T21 := T17 + T20
T77 := KP866025403 * (T19 - T18)
T47 := T17 - (KP500000000 * T20)
T78 := ii[9]
T48 := ii[1]
T49 := ii[5]
T79 := T48 + T49
T50 := KP866025403 * (T48 - T49)
T93 := T78 + T79
T80 := T78 - (KP500000000 * T79)
T11 := T5 + T10
T22 := T16 + T21
ro[6] = T11 - T22
ro[0] = T11 + T22
T95 := T28 + T33
T96 := T92 + T93
io[6] = T95 - T96
io[0] = T95 + T96
T23 := T16 - T21
T34 := T28 - T33
io[3] = T23 + T34
io[9] = T34 - T23
T91 := T5 - T10
T94 := T92 - T93
ro[3] = T91 - T94
ro[9] = T91 + T94
T61 := T36 + T35
T62 := T39 + T38
T63 := T61 - T62
T83 := T61 + T62
T76 := T72 + T75
T81 := T77 + T80
T82 := T76 - T81
T84 := T76 + T81
T64 := T42 + T45
T65 := T47 + T50
T66 := T64 - T65
T70 := T64 + T65
T67 := T53 + T54
T68 := T56 + T57
T69 := T67 + T68
T71 := T67 - T68
io[1] = T63 - T66
ro[1] = T71 + T82
io[7] = T63 + T66
ro[7] = T71 - T82
ro[10] = T69 - T70
io[10] = T83 - T84
ro[4] = T69 + T70
io[4] = T83 + T84
T37 := T35 - T36
T40 := T38 - T39
T41 := T37 - T40
T89 := T37 + T40
T86 := T75 - T72
T87 := T80 - T77
T88 := T86 - T87
T90 := T86 + T87
T46 := T42 - T45
T51 := T47 - T50
T52 := T46 - T51
T60 := T46 + T51
T55 := T53 - T54
T58 := T56 - T57
T59 := T55 + T58
T85 := T55 - T58
io[5] = T41 - T52
ro[5] = T85 + T88
io[11] = T41 + T52
ro[11] = T85 - T88
ro[2] = T59 - T60
io[2] = T89 - T90
ro[8] = T59 + T60
io[8] = T89 + T90
}

206
decode/dft/dft13.go Normal file
View file

@ -0,0 +1,206 @@
package dft
func DFT13(ri, ii, ro, io []float64) {
T1 := ri[0]
T88 := ii[0]
T13 := ri[8]
T14 := ri[5]
T15 := T13 + T14
T25 := T13 - T14
T7 := ri[12]
T8 := ri[10]
T9 := ri[4]
T10 := T8 + T9
T11 := T7 + T10
T38 := T8 - T9
T33 := T7 - (KP500000000 * T10)
T2 := ri[1]
T3 := ri[3]
T4 := ri[9]
T5 := T3 + T4
T6 := T2 + T5
T37 := T3 - T4
T32 := T2 - (KP500000000 * T5)
T16 := ri[11]
T17 := ri[6]
T18 := T16 + T17
T26 := T16 - T17
T19 := ri[7]
T20 := ri[2]
T21 := T19 + T20
T27 := T19 - T20
T22 := T18 + T21
T28 := T26 + T27
T29 := T25 + T28
T30 := T6 - T11
T12 := T6 + T11
T23 := T15 + T22
T24 := T12 + T23
T126 := KP300462606 * (T12 - T23)
T122 := T37 + T38
T123 := T26 - T27
T124 := T122 - T123
T128 := T122 + T123
T39 := KP866025403 * (T37 - T38)
T40 := T25 - (KP500000000 * T28)
T41 := T39 - T40
T43 := T39 + T40
T34 := T32 - T33
T35 := KP866025403 * (T18 - T21)
T36 := T34 + T35
T44 := T34 - T35
T119 := T32 + T33
T120 := T15 - (KP500000000 * T22)
T121 := T119 - T120
T129 := T119 + T120
T59 := ii[8]
T60 := ii[5]
T61 := T59 + T60
T135 := T59 - T60
T53 := ii[12]
T54 := ii[10]
T55 := ii[4]
T56 := T54 + T55
T57 := T53 - (KP500000000 * T56)
T80 := T53 + T56
T72 := T54 - T55
T48 := ii[1]
T49 := ii[3]
T50 := ii[9]
T51 := T49 + T50
T52 := T48 - (KP500000000 * T51)
T79 := T48 + T51
T71 := T49 - T50
T62 := ii[11]
T63 := ii[6]
T64 := T62 + T63
T75 := T62 - T63
T65 := ii[7]
T66 := ii[2]
T67 := T65 + T66
T74 := T65 - T66
T68 := T64 + T67
T136 := T75 + T74
T134 := T79 - T80
T137 := T135 + T136
T58 := T52 + T57
T69 := T61 - (KP500000000 * T68)
T70 := T58 - T69
T85 := T58 + T69
T142 := T52 - T57
T143 := KP866025403 * (T67 - T64)
T144 := T142 + T143
T147 := T142 - T143
T81 := T79 + T80
T82 := T61 + T68
T83 := KP300462606 * (T81 - T82)
T89 := T81 + T82
T73 := T71 + T72
T76 := T74 - T75
T77 := T73 + T76
T86 := T76 - T73
T139 := T135 - (KP500000000 * T136)
T140 := KP866025403 * (T72 - T71)
T141 := T139 - T140
T146 := T140 + T139
ro[0] = T1 + T24
io[0] = T88 + T89
T99 := (KP387390585 * T77) + (KP265966249 * T70)
T100 := (KP113854479 * T86) + (KP503537032 * T85)
T101 := T99 + T100
T111 := T100 - T99
T96 := (KP575140729 * T30) + (KP174138601 * T29)
T93 := (KP256247671 * T44) - (KP156891391 * T43)
T94 := (KP011599105 * T41) + (KP300238635 * T36)
T95 := T93 - T94
T102 := T96 + T95
T112 := KP1_732050807 * (T93 + T94)
T31 := (KP575140729 * T29) - (KP174138601 * T30)
T42 := (KP011599105 * T36) - (KP300238635 * T41)
T45 := (KP256247671 * T43) + (KP156891391 * T44)
T46 := T42 - T45
T107 := KP1_732050807 * (T45 + T42)
T114 := T31 - T46
T78 := (KP258260390 * T70) - (KP132983124 * T77)
T105 := T83 - T78
T87 := (KP075902986 * T85) - (KP251768516 * T86)
T90 := T88 - (KP083333333 * T89)
T104 := T90 - T87
T84 := (KP2_000000000 * T78) + T83
T115 := T105 + T104
T91 := (KP2_000000000 * T87) + T90
T106 := T104 - T105
T47 := T31 + (KP2_000000000 * T46)
T92 := T84 + T91
io[1] = T47 + T92
io[12] = T92 - T47
T97 := (KP2_000000000 * T95) - T96
T98 := T91 - T84
io[5] = T97 + T98
io[8] = T98 - T97
T117 := T115 - T114
T118 := T112 + T111
io[4] = T117 - T118
io[10] = T118 + T117
T113 := T111 - T112
T116 := T114 + T115
io[3] = T113 + T116
io[9] = T116 - T113
T109 := T107 + T106
T110 := T102 + T101
io[6] = T109 - T110
io[11] = T110 + T109
T103 := T101 - T102
T108 := T106 - T107
io[2] = T103 + T108
io[7] = T108 - T103
T156 := (KP387390585 * T124) + (KP265966249 * T121)
T157 := (KP113854479 * T128) - (KP503537032 * T129)
T158 := T156 + T157
T168 := T156 - T157
T169 := (KP575140729 * T134) + (KP174138601 * T137)
T159 := (KP011599105 * T146) - (KP300238635 * T147)
T160 := (KP256247671 * T144) - (KP156891391 * T141)
T170 := T159 + T160
T161 := KP1_732050807 * (T159 - T160)
T171 := T169 + T170
T138 := (KP174138601 * T134) - (KP575140729 * T137)
T145 := (KP256247671 * T141) + (KP156891391 * T144)
T148 := (KP300238635 * T146) + (KP011599105 * T147)
T149 := T145 - T148
T154 := T138 - T149
T166 := KP1_732050807 * (T148 + T145)
T125 := (KP258260390 * T121) - (KP132983124 * T124)
T151 := T126 - T125
T130 := (KP251768516 * T128) + (KP075902986 * T129)
T131 := T1 - (KP083333333 * T24)
T152 := T131 - T130
T127 := (KP2_000000000 * T125) + T126
T165 := T152 - T151
T132 := (KP2_000000000 * T130) + T131
T153 := T151 + T152
T133 := T127 + T132
T150 := T138 + (KP2_000000000 * T149)
ro[12] = T133 - T150
ro[1] = T133 + T150
T155 := T153 - T154
T162 := T158 - T161
ro[10] = T155 - T162
ro[4] = T155 + T162
T175 := T132 - T127
T176 := (KP2_000000000 * T170) - T169
ro[5] = T175 - T176
ro[8] = T175 + T176
T173 := T165 - T166
T174 := T171 - T168
ro[11] = T173 - T174
ro[6] = T173 + T174
T167 := T165 + T166
T172 := T168 + T171
ro[7] = T167 - T172
ro[2] = T167 + T172
T163 := T153 + T154
T164 := T158 + T161
ro[3] = T163 - T164
ro[9] = T163 + T164
}

136
decode/dft/dft14.go Normal file
View file

@ -0,0 +1,136 @@
package dft
func DFT14(ri, ii, ro, io []float64) {
T1 := ri[0]
T2 := ri[7]
T3 := T1 - T2
T25 := T1 + T2
T66 := ii[0]
T67 := ii[7]
T68 := T66 - T67
T77 := T66 + T67
T4 := ri[2]
T5 := ri[9]
T6 := T4 - T5
T26 := T4 + T5
T7 := ri[12]
T8 := ri[5]
T9 := T7 - T8
T27 := T7 + T8
T10 := T6 + T9
T88 := T27 - T26
T28 := T26 + T27
T62 := T9 - T6
T36 := ii[2]
T37 := ii[9]
T38 := T36 - T37
T78 := T36 + T37
T39 := ii[12]
T40 := ii[5]
T41 := T39 - T40
T79 := T39 + T40
T42 := T38 - T41
T97 := T78 - T79
T71 := T38 + T41
T80 := T78 + T79
T11 := ri[4]
T12 := ri[11]
T13 := T11 - T12
T29 := T11 + T12
T14 := ri[10]
T15 := ri[3]
T16 := T14 - T15
T30 := T14 + T15
T17 := T13 + T16
T90 := T29 - T30
T31 := T29 + T30
T64 := T16 - T13
T50 := ii[4]
T51 := ii[11]
T52 := T50 - T51
T84 := T50 + T51
T53 := ii[10]
T54 := ii[3]
T55 := T53 - T54
T85 := T53 + T54
T56 := T52 - T55
T99 := T85 - T84
T69 := T52 + T55
T86 := T84 + T85
T18 := ri[6]
T19 := ri[13]
T20 := T18 - T19
T32 := T18 + T19
T21 := ri[8]
T22 := ri[1]
T23 := T21 - T22
T33 := T21 + T22
T24 := T20 + T23
T89 := T32 - T33
T34 := T32 + T33
T63 := T23 - T20
T43 := ii[6]
T44 := ii[13]
T45 := T43 - T44
T81 := T43 + T44
T46 := ii[8]
T47 := ii[1]
T48 := T46 - T47
T82 := T46 + T47
T49 := T45 - T48
T98 := T82 - T81
T70 := T45 + T48
T83 := T81 + T82
ro[7] = T3 + T10 + T17 + T24
io[7] = T68 + T71 + T69 + T70
ro[0] = T25 + T28 + T31 + T34
io[0] = T77 + T80 + T86 + T83
T57 := (KP974927912 * T42) - (KP781831482 * T49) - (KP433883739 * T56)
T35 := T3 + (KP623489801 * T24) - (KP900968867 * T17) - (KP222520933 * T10)
ro[5] = T35 - T57
ro[9] = T35 + T57
T76 := (KP974927912 * T62) - (KP781831482 * T63) - (KP433883739 * T64)
T75 := T68 + (KP623489801 * T70) - (KP900968867 * T69) - (KP222520933 * T71)
io[5] = T75 - T76
io[9] = T76 + T75
T59 := (KP781831482 * T42) + (KP974927912 * T56) + (KP433883739 * T49)
T58 := T3 + (KP623489801 * T10) - (KP900968867 * T24) - (KP222520933 * T17)
ro[13] = T58 - T59
ro[1] = T58 + T59
T73 := (KP781831482 * T62) + (KP974927912 * T64) + (KP433883739 * T63)
T74 := T68 + (KP623489801 * T71) - (KP900968867 * T70) - (KP222520933 * T69)
io[1] = T73 + T74
io[13] = T74 - T73
T61 := (KP433883739 * T42) + (KP974927912 * T49) - (KP781831482 * T56)
T60 := T3 + (KP623489801 * T17) - (KP222520933 * T24) - (KP900968867 * T10)
ro[11] = T60 - T61
ro[3] = T60 + T61
T65 := (KP433883739 * T62) + (KP974927912 * T63) - (KP781831482 * T64)
T72 := T68 + (KP623489801 * T69) - (KP222520933 * T70) - (KP900968867 * T71)
io[3] = T65 + T72
io[11] = T72 - T65
T91 := (KP781831482 * T88) - (KP433883739 * T89) - (KP974927912 * T90)
T87 := T77 + (KP623489801 * T80) - (KP900968867 * T83) - (KP222520933 * T86)
io[6] = T87 - T91
io[8] = T91 + T87
T100 := (KP781831482 * T97) - (KP433883739 * T98) - (KP974927912 * T99)
T96 := T25 + (KP623489801 * T28) - (KP900968867 * T34) - (KP222520933 * T31)
ro[6] = T96 - T100
ro[8] = T96 + T100
T93 := (KP433883739 * T88) + (KP781831482 * T90) - (KP974927912 * T89)
T92 := T77 + (KP623489801 * T86) - (KP222520933 * T83) - (KP900968867 * T80)
io[4] = T92 - T93
io[10] = T93 + T92
T102 := (KP433883739 * T97) + (KP781831482 * T99) - (KP974927912 * T98)
T101 := T25 + (KP623489801 * T31) - (KP222520933 * T34) - (KP900968867 * T28)
ro[4] = T101 - T102
ro[10] = T101 + T102
T94 := (KP974927912 * T88) + (KP433883739 * T90) + (KP781831482 * T89)
T95 := T77 + (KP623489801 * T83) - (KP900968867 * T86) - (KP222520933 * T80)
io[2] = T94 + T95
io[12] = T95 - T94
T104 := (KP974927912 * T97) + (KP433883739 * T99) + (KP781831482 * T98)
T103 := T25 + (KP623489801 * T34) - (KP900968867 * T31) - (KP222520933 * T28)
ro[12] = T103 - T104
ro[2] = T103 + T104
}

190
decode/dft/dft15.go Normal file
View file

@ -0,0 +1,190 @@
package dft
func DFT15(ri, ii, ro, io []float64) {
T1 := ri[0]
T97 := ii[0]
T2 := ri[5]
T3 := ri[10]
T4 := T2 + T3
T96 := KP866025403 * (T3 - T2)
T30 := ii[5]
T31 := ii[10]
T32 := KP866025403 * (T30 - T31)
T98 := T30 + T31
T5 := T1 + T4
T145 := T97 + T98
T29 := T1 - (KP500000000 * T4)
T33 := T29 - T32
T57 := T29 + T32
T99 := T97 - (KP500000000 * T98)
T100 := T96 + T99
T124 := T99 - T96
T17 := ri[6]
T18 := ri[11]
T19 := ri[1]
T20 := T18 + T19
T45 := T17 - (KP500000000 * T20)
T79 := KP866025403 * (T19 - T18)
T80 := ii[6]
T46 := ii[11]
T47 := ii[1]
T81 := T46 + T47
T48 := KP866025403 * (T46 - T47)
T82 := T80 - (KP500000000 * T81)
T22 := ri[9]
T23 := ri[14]
T24 := ri[4]
T25 := T23 + T24
T50 := T22 - (KP500000000 * T25)
T84 := KP866025403 * (T24 - T23)
T85 := ii[9]
T51 := ii[14]
T52 := ii[4]
T86 := T51 + T52
T53 := KP866025403 * (T51 - T52)
T87 := T85 - (KP500000000 * T86)
T21 := T17 + T20
T26 := T22 + T25
T27 := T21 + T26
T49 := T45 - T48
T54 := T50 - T53
T55 := T49 + T54
T136 := T80 + T81
T137 := T85 + T86
T147 := T136 + T137
T112 := T82 - T79
T113 := T87 - T84
T126 := T112 + T113
T83 := T79 + T82
T88 := T84 + T87
T94 := T83 + T88
T61 := T45 + T48
T62 := T50 + T53
T63 := T61 + T62
T6 := ri[3]
T7 := ri[8]
T8 := ri[13]
T9 := T7 + T8
T34 := T6 - (KP500000000 * T9)
T68 := KP866025403 * (T8 - T7)
T69 := ii[3]
T35 := ii[8]
T36 := ii[13]
T70 := T35 + T36
T37 := KP866025403 * (T35 - T36)
T71 := T69 - (KP500000000 * T70)
T11 := ri[12]
T12 := ri[2]
T13 := ri[7]
T14 := T12 + T13
T39 := T11 - (KP500000000 * T14)
T73 := KP866025403 * (T13 - T12)
T74 := ii[12]
T40 := ii[2]
T41 := ii[7]
T75 := T40 + T41
T42 := KP866025403 * (T40 - T41)
T76 := T74 - (KP500000000 * T75)
T10 := T6 + T9
T15 := T11 + T14
T16 := T10 + T15
T38 := T34 - T37
T43 := T39 - T42
T44 := T38 + T43
T139 := T69 + T70
T140 := T74 + T75
T146 := T139 + T140
T115 := T71 - T68
T116 := T76 - T73
T125 := T115 + T116
T72 := T68 + T71
T77 := T73 + T76
T93 := T72 + T77
T58 := T34 + T37
T59 := T39 + T42
T60 := T58 + T59
T134 := KP559016994 * (T16 - T27)
T28 := T16 + T27
T133 := T5 - (KP250000000 * T28)
T138 := T136 - T137
T141 := T139 - T140
T142 := (KP951056516 * T138) - (KP587785252 * T141)
T144 := (KP951056516 * T141) + (KP587785252 * T138)
ro[0] = T5 + T28
T143 := T134 + T133
ro[9] = T143 - T144
ro[6] = T143 + T144
T135 := T133 - T134
ro[12] = T135 - T142
ro[3] = T135 + T142
T150 := KP559016994 * (T146 - T147)
T148 := T146 + T147
T149 := T145 - (KP250000000 * T148)
T152 := T21 - T26
T153 := T10 - T15
T154 := (KP951056516 * T152) - (KP587785252 * T153)
T156 := (KP951056516 * T153) + (KP587785252 * T152)
io[0] = T145 + T148
T155 := T150 + T149
io[6] = T155 - T156
io[9] = T156 + T155
T151 := T149 - T150
io[3] = T151 - T154
io[12] = T154 + T151
T110 := KP559016994 * (T44 - T55)
T56 := T44 + T55
T109 := T33 - (KP250000000 * T56)
T114 := T112 - T113
T117 := T115 - T116
T118 := (KP951056516 * T114) - (KP587785252 * T117)
T120 := (KP951056516 * T117) + (KP587785252 * T114)
ro[5] = T33 + T56
T119 := T110 + T109
ro[14] = T119 - T120
ro[11] = T119 + T120
T111 := T109 - T110
ro[2] = T111 - T118
ro[8] = T111 + T118
T129 := KP559016994 * (T125 - T126)
T127 := T125 + T126
T128 := T124 - (KP250000000 * T127)
T121 := T49 - T54
T122 := T38 - T43
T123 := (KP951056516 * T121) - (KP587785252 * T122)
T132 := (KP951056516 * T122) + (KP587785252 * T121)
io[5] = T124 + T127
T131 := T129 + T128
io[11] = T131 - T132
io[14] = T132 + T131
T130 := T128 - T129
io[2] = T123 + T130
io[8] = T130 - T123
T95 := KP559016994 * (T93 - T94)
T101 := T93 + T94
T102 := T100 - (KP250000000 * T101)
T104 := T58 - T59
T105 := T61 - T62
T106 := (KP951056516 * T104) + (KP587785252 * T105)
T107 := (KP951056516 * T105) - (KP587785252 * T104)
io[10] = T100 + T101
T108 := T102 - T95
io[7] = T107 + T108
io[13] = T108 - T107
T103 := T95 + T102
io[1] = T103 - T106
io[4] = T106 + T103
T65 := KP559016994 * (T60 - T63)
T64 := T60 + T63
T66 := T57 - (KP250000000 * T64)
T78 := T72 - T77
T89 := T83 - T88
T90 := (KP951056516 * T78) + (KP587785252 * T89)
T92 := (KP951056516 * T89) - (KP587785252 * T78)
ro[10] = T57 + T64
T91 := T66 - T65
ro[7] = T91 - T92
ro[13] = T91 + T92
T67 := T65 + T66
ro[4] = T67 - T90
ro[1] = T67 + T90
}

180
decode/dft/dft16.go Normal file
View file

@ -0,0 +1,180 @@
package dft
func DFT16(ri, ii, ro, io []float64) {
T1 := ri[0]
T2 := ri[8]
T3 := T1 + T2
T47 := T1 - T2
T32 := ii[0]
T33 := ii[8]
T34 := T32 + T33
T82 := T32 - T33
T4 := ri[4]
T5 := ri[12]
T6 := T4 + T5
T81 := T4 - T5
T35 := ii[4]
T36 := ii[12]
T37 := T35 + T36
T48 := T35 - T36
T7 := T3 + T6
T115 := T3 - T6
T129 := T34 - T37
T38 := T34 + T37
T49 := T47 - T48
T95 := T47 + T48
T105 := T82 - T81
T83 := T81 + T82
T23 := ri[15]
T24 := ri[7]
T25 := T23 + T24
T69 := T23 - T24
T75 := ii[15]
T76 := ii[7]
T77 := T75 - T76
T124 := T75 + T76
T26 := ri[3]
T27 := ri[11]
T28 := T26 + T27
T74 := T26 - T27
T70 := ii[3]
T71 := ii[11]
T72 := T70 - T71
T125 := T70 + T71
T29 := T25 + T28
T126 := T124 - T125
T141 := T124 + T125
T73 := T69 - T72
T78 := T74 + T77
T102 := T77 - T74
T123 := T25 - T28
T101 := T69 + T72
T8 := ri[2]
T9 := ri[10]
T10 := T8 + T9
T51 := T8 - T9
T39 := ii[2]
T40 := ii[10]
T41 := T39 + T40
T50 := T39 - T40
T11 := ri[14]
T12 := ri[6]
T13 := T11 + T12
T53 := T11 - T12
T42 := ii[14]
T43 := ii[6]
T44 := T42 + T43
T54 := T42 - T43
T14 := T10 + T13
T116 := T41 - T44
T130 := T13 - T10
T45 := T41 + T44
T52 := T50 - T51
T84 := T53 - T54
T85 := T51 + T50
T55 := T53 + T54
T16 := ri[1]
T17 := ri[9]
T18 := T16 + T17
T63 := T16 - T17
T59 := ii[1]
T60 := ii[9]
T61 := T59 - T60
T119 := T59 + T60
T19 := ri[5]
T20 := ri[13]
T21 := T19 + T20
T58 := T19 - T20
T64 := ii[5]
T65 := ii[13]
T66 := T64 - T65
T120 := T64 + T65
T22 := T18 + T21
T121 := T119 - T120
T140 := T119 + T120
T62 := T58 + T61
T67 := T63 - T66
T99 := T63 + T66
T118 := T18 - T21
T98 := T61 - T58
T15 := T7 + T14
T30 := T22 + T29
ro[8] = T15 - T30
ro[0] = T15 + T30
T143 := T38 + T45
T144 := T140 + T141
io[8] = T143 - T144
io[0] = T143 + T144
T31 := T29 - T22
T46 := T38 - T45
io[4] = T31 + T46
io[12] = T46 - T31
T139 := T7 - T14
T142 := T140 - T141
ro[12] = T139 - T142
ro[4] = T139 + T142
T117 := T115 + T116
T131 := T129 - T130
T122 := T118 + T121
T127 := T123 - T126
T128 := KP707106781 * (T122 + T127)
T132 := KP707106781 * (T127 - T122)
ro[10] = T117 - T128
io[6] = T131 + T132
ro[2] = T117 + T128
io[14] = T131 - T132
T133 := T115 - T116
T137 := T130 + T129
T134 := T121 - T118
T135 := T123 + T126
T136 := KP707106781 * (T134 - T135)
T138 := KP707106781 * (T134 + T135)
ro[14] = T133 - T136
io[2] = T137 + T138
ro[6] = T133 + T136
io[10] = T137 - T138
T56 := KP707106781 * (T52 - T55)
T57 := T49 + T56
T89 := T49 - T56
T86 := KP707106781 * (T84 - T85)
T87 := T83 - T86
T93 := T83 + T86
T68 := (KP923879532 * T62) + (KP382683432 * T67)
T79 := (KP382683432 * T73) - (KP923879532 * T78)
T80 := T68 + T79
T88 := T79 - T68
T90 := (KP382683432 * T62) - (KP923879532 * T67)
T91 := (KP382683432 * T78) + (KP923879532 * T73)
T92 := T90 - T91
T94 := T90 + T91
ro[11] = T57 - T80
io[11] = T93 - T94
ro[3] = T57 + T80
io[3] = T93 + T94
io[15] = T87 - T88
ro[15] = T89 - T92
io[7] = T87 + T88
ro[7] = T89 + T92
T96 := KP707106781 * (T85 + T84)
T97 := T95 + T96
T109 := T95 - T96
T106 := KP707106781 * (T52 + T55)
T107 := T105 - T106
T113 := T105 + T106
T100 := (KP382683432 * T98) + (KP923879532 * T99)
T103 := (KP923879532 * T101) - (KP382683432 * T102)
T104 := T100 + T103
T108 := T103 - T100
T110 := (KP923879532 * T98) - (KP382683432 * T99)
T111 := (KP923879532 * T102) + (KP382683432 * T101)
T112 := T110 - T111
T114 := T110 + T111
ro[9] = T97 - T104
io[9] = T113 - T114
ro[1] = T97 + T104
io[1] = T113 + T114
io[13] = T107 - T108
ro[13] = T109 - T112
io[5] = T107 + T108
ro[5] = T109 + T112
}

46
decode/dft/dft5.go Normal file
View file

@ -0,0 +1,46 @@
package dft
func DFT5(ri, ii, ro, io []float64) {
T1 := ri[0]
T24 := ii[0]
T2 := ri[1]
T3 := ri[4]
T4 := T2 + T3
T5 := ri[2]
T6 := ri[3]
T7 := T5 + T6
T8 := T4 + T7
T29 := T5 - T6
T9 := KP559016994 * (T4 - T7)
T28 := T2 - T3
T12 := ii[1]
T13 := ii[4]
T21 := T12 + T13
T15 := ii[2]
T16 := ii[3]
T22 := T15 + T16
T14 := T12 - T13
T25 := T21 + T22
T17 := T15 - T16
T23 := KP559016994 * (T21 - T22)
ro[0] = T1 + T8
io[0] = T24 + T25
T18 := (KP951056516 * T14) + (KP587785252 * T17)
T20 := (KP951056516 * T17) - (KP587785252 * T14)
T10 := T1 - (KP250000000 * T8)
T11 := T9 + T10
T19 := T10 - T9
ro[4] = T11 - T18
ro[3] = T19 + T20
ro[1] = T11 + T18
ro[2] = T19 - T20
T30 := (KP951056516 * T28) + (KP587785252 * T29)
T31 := (KP951056516 * T29) - (KP587785252 * T28)
T26 := T24 - (KP250000000 * T25)
T27 := T23 + T26
T32 := T26 - T23
io[1] = T27 - T30
io[3] = T32 - T31
io[4] = T30 + T27
io[2] = T31 + T32
}

52
decode/dft/dft6.go Normal file
View file

@ -0,0 +1,52 @@
package dft
func DFT6(ri, ii, ro, io []float64) {
T1 := ri[0]
T2 := ri[3]
T3 := T1 - T2
T11 := T1 + T2
T24 := ii[0]
T25 := ii[3]
T26 := T24 - T25
T33 := T24 + T25
T4 := ri[2]
T5 := ri[5]
T6 := T4 - T5
T12 := T4 + T5
T7 := ri[4]
T8 := ri[1]
T9 := T7 - T8
T13 := T7 + T8
T10 := T6 + T9
T14 := T12 + T13
T16 := ii[2]
T17 := ii[5]
T18 := T16 - T17
T30 := T16 + T17
T19 := ii[4]
T20 := ii[1]
T21 := T19 - T20
T31 := T19 + T20
T27 := T18 + T21
T34 := T30 + T31
ro[3] = T3 + T10
io[3] = T26 + T27
ro[0] = T11 + T14
io[0] = T33 + T34
T15 := T3 - (KP500000000 * T10)
T22 := KP866025403 * (T18 - T21)
ro[5] = T15 - T22
ro[1] = T15 + T22
T23 := KP866025403 * (T9 - T6)
T28 := T26 - (KP500000000 * T27)
io[1] = T23 + T28
io[5] = T28 - T23
T29 := T11 - (KP500000000 * T14)
T32 := KP866025403 * (T30 - T31)
ro[2] = T29 - T32
ro[4] = T29 + T32
T35 := T33 - (KP500000000 * T34)
T36 := KP866025403 * (T13 - T12)
io[2] = T35 - T36
io[4] = T36 + T35
}

56
decode/dft/dft7.go Normal file
View file

@ -0,0 +1,56 @@
package dft
func DFT7(ri, ii, ro, io []float64) {
T1 := ri[0]
T30 := ii[0]
T2 := ri[1]
T3 := ri[6]
T4 := T2 + T3
T26 := T3 - T2
T12 := ii[1]
T13 := ii[6]
T14 := T12 - T13
T33 := T12 + T13
T5 := ri[2]
T6 := ri[5]
T7 := T5 + T6
T28 := T6 - T5
T18 := ii[2]
T19 := ii[5]
T20 := T18 - T19
T31 := T18 + T19
T8 := ri[3]
T9 := ri[4]
T10 := T8 + T9
T27 := T9 - T8
T15 := ii[3]
T16 := ii[4]
T17 := T15 - T16
T32 := T15 + T16
ro[0] = T1 + T4 + T7 + T10
io[0] = T30 + T33 + T31 + T32
T21 := (KP974927912 * T14) - (KP781831482 * T17) - (KP433883739 * T20)
T11 := T1 + (KP623489801 * T10) - (KP900968867 * T7) - (KP222520933 * T4)
ro[5] = T11 - T21
ro[2] = T11 + T21
T37 := (KP974927912 * T26) - (KP781831482 * T27) - (KP433883739 * T28)
T38 := T30 + (KP623489801 * T32) - (KP900968867 * T31) - (KP222520933 * T33)
io[2] = T37 + T38
io[5] = T38 - T37
T23 := (KP781831482 * T14) + (KP974927912 * T20) + (KP433883739 * T17)
T22 := T1 + (KP623489801 * T4) - (KP900968867 * T10) - (KP222520933 * T7)
ro[6] = T22 - T23
ro[1] = T22 + T23
T35 := (KP781831482 * T26) + (KP974927912 * T28) + (KP433883739 * T27)
T36 := T30 + (KP623489801 * T33) - (KP900968867 * T32) - (KP222520933 * T31)
io[1] = T35 + T36
io[6] = T36 - T35
T25 := (KP433883739 * T14) + (KP974927912 * T17) - (KP781831482 * T20)
T24 := T1 + (KP623489801 * T7) - (KP222520933 * T10) - (KP900968867 * T4)
ro[4] = T24 - T25
ro[3] = T24 + T25
T29 := (KP433883739 * T26) + (KP974927912 * T27) - (KP781831482 * T28)
T34 := T30 + (KP623489801 * T31) - (KP222520933 * T32) - (KP900968867 * T33)
io[3] = T29 + T34
io[4] = T34 - T29
}

72
decode/dft/dft8.go Normal file
View file

@ -0,0 +1,72 @@
package dft
func DFT8(ri, ii, ro, io []float64) {
T1 := ri[0]
T2 := ri[4]
T3 := T1 + T2
T23 := T1 - T2
T16 := ii[0]
T17 := ii[4]
T18 := T16 + T17
T38 := T16 - T17
T4 := ri[2]
T5 := ri[6]
T6 := T4 + T5
T37 := T4 - T5
T19 := ii[2]
T20 := ii[6]
T21 := T19 + T20
T24 := T19 - T20
T11 := ri[7]
T12 := ri[3]
T31 := T11 - T12
T32 := ii[7]
T33 := ii[3]
T34 := T32 - T33
T13 := T11 + T12
T49 := T32 + T33
T35 := T31 - T34
T43 := T31 + T34
T8 := ri[1]
T9 := ri[5]
T26 := T8 - T9
T27 := ii[1]
T28 := ii[5]
T29 := T27 - T28
T10 := T8 + T9
T48 := T27 + T28
T30 := T26 + T29
T42 := T29 - T26
T7 := T3 + T6
T14 := T10 + T13
ro[4] = T7 - T14
ro[0] = T7 + T14
T51 := T18 + T21
T52 := T48 + T49
io[4] = T51 - T52
io[0] = T51 + T52
T15 := T13 - T10
T22 := T18 - T21
io[2] = T15 + T22
io[6] = T22 - T15
T47 := T3 - T6
T50 := T48 - T49
ro[6] = T47 - T50
ro[2] = T47 + T50
T25 := T23 + T24
T36 := KP707106781 * (T30 + T35)
ro[5] = T25 - T36
ro[1] = T25 + T36
T45 := T38 - T37
T46 := KP707106781 * (T42 + T43)
io[5] = T45 - T46
io[1] = T45 + T46
T39 := T37 + T38
T40 := KP707106781 * (T35 - T30)
io[7] = T39 - T40
io[3] = T39 + T40
T41 := T23 - T24
T44 := KP707106781 * (T42 - T43)
ro[7] = T41 - T44
ro[3] = T41 + T44
}

102
decode/dft/dft9.go Normal file
View file

@ -0,0 +1,102 @@
package dft
func DFT9(ri, ii, ro, io []float64) {
T1 := ri[0]
T2 := ri[3]
T3 := ri[6]
T4 := T2 + T3
T5 := T1 + T4
T50 := KP866025403 * (T3 - T2)
T17 := T1 - (KP500000000 * T4)
T51 := ii[0]
T18 := ii[3]
T19 := ii[6]
T52 := T18 + T19
T20 := KP866025403 * (T18 - T19)
T78 := T51 + T52
T53 := T51 - (KP500000000 * T52)
T6 := ri[1]
T28 := ii[1]
T7 := ri[4]
T8 := ri[7]
T9 := T7 + T8
T27 := KP866025403 * (T8 - T7)
T23 := ii[4]
T24 := ii[7]
T25 := KP866025403 * (T23 - T24)
T29 := T23 + T24
T10 := T6 + T9
T74 := T28 + T29
T22 := T6 - (KP500000000 * T9)
T26 := T22 + T25
T58 := T22 - T25
T30 := T28 - (KP500000000 * T29)
T31 := T27 + T30
T59 := T30 - T27
T11 := ri[2]
T39 := ii[2]
T12 := ri[5]
T13 := ri[8]
T14 := T12 + T13
T38 := KP866025403 * (T13 - T12)
T34 := ii[5]
T35 := ii[8]
T36 := KP866025403 * (T34 - T35)
T40 := T34 + T35
T15 := T11 + T14
T75 := T39 + T40
T33 := T11 - (KP500000000 * T14)
T37 := T33 + T36
T62 := T33 - T36
T41 := T39 - (KP500000000 * T40)
T42 := T38 + T41
T61 := T41 - T38
T76 := KP866025403 * (T74 - T75)
T16 := T10 + T15
T73 := T5 - (KP500000000 * T16)
ro[0] = T5 + T16
ro[3] = T73 + T76
ro[6] = T73 - T76
T77 := KP866025403 * (T15 - T10)
T79 := T74 + T75
T80 := T78 - (KP500000000 * T79)
io[3] = T77 + T80
io[0] = T78 + T79
io[6] = T80 - T77
T21 := T17 + T20
T54 := T50 + T53
T32 := (KP766044443 * T26) + (KP642787609 * T31)
T43 := (KP173648177 * T37) + (KP984807753 * T42)
T44 := T32 + T43
T49 := KP866025403 * (T43 - T32)
T46 := (KP766044443 * T31) - (KP642787609 * T26)
T47 := (KP173648177 * T42) - (KP984807753 * T37)
T48 := KP866025403 * (T46 - T47)
T55 := T46 + T47
ro[1] = T21 + T44
io[1] = T54 + T55
T45 := T21 - (KP500000000 * T44)
ro[7] = T45 - T48
ro[4] = T45 + T48
T56 := T54 - (KP500000000 * T55)
io[4] = T49 + T56
io[7] = T56 - T49
T57 := T17 - T20
T66 := T53 - T50
T60 := (KP173648177 * T58) + (KP984807753 * T59)
T63 := (KP342020143 * T61) - (KP939692620 * T62)
T64 := T60 + T63
T65 := KP866025403 * (T63 - T60)
T67 := (KP173648177 * T59) - (KP984807753 * T58)
T68 := (KP342020143 * T62) + (KP939692620 * T61)
T69 := T67 - T68
T72 := KP866025403 * (T67 + T68)
ro[2] = T57 + T64
io[2] = T66 + T69
T70 := T66 - (KP500000000 * T69)
io[5] = T65 + T70
io[8] = T70 - T65
T71 := T57 - (KP500000000 * T64)
ro[8] = T71 - T72
ro[5] = T71 + T72
}

92
decode/dft/dft_test.go Normal file
View file

@ -0,0 +1,92 @@
package dft
import (
"math"
"math/cmplx"
"testing"
)
const (
Tolerance = 2.5e-15
)
type DFT struct {
name string
dft func(ri, ii, ro, io []float64)
length int
}
func StepFloat(n int) (out []float64) {
out = make([]float64, n)
for idx := 0; idx < n>>1; idx++ {
out[idx] = 1
}
return
}
func StepComplex(n int) (out []complex128) {
out = make([]complex128, n)
for idx := 0; idx < n>>1; idx++ {
out[idx] = 1
}
return
}
func Error(i, j []complex128) float64 {
var err float64
for idx := range i {
err += cmplx.Abs(i[idx] - j[idx])
}
return err / float64(len(i))
}
func DirectFourierTransform(f []complex128, sign float64) {
n := len(f)
h := make([]complex128, n)
phi := sign * 2.0 * math.Pi / float64(n)
for w := 0; w < n; w++ {
var t complex128
for k := 0; k < n; k++ {
t += f[k] * cmplx.Rect(1, phi*float64(k)*float64(w))
}
h[w] = t
}
copy(f, h)
}
func TestDFT(t *testing.T) {
dfts := []DFT{
{"DFT5", DFT5, 5},
{"DFT6", DFT6, 6},
{"DFT7", DFT7, 7},
{"DFT8", DFT8, 8},
{"DFT9", DFT9, 9},
{"DFT10", DFT10, 10},
{"DFT11", DFT11, 11},
{"DFT12", DFT12, 12},
{"DFT13", DFT13, 13},
{"DFT14", DFT14, 14},
{"DFT15", DFT15, 15},
{"DFT16", DFT16, 16},
}
for _, dft := range dfts {
re := StepFloat(dft.length)
im := make([]float64, dft.length)
dft.dft(re, im, re, im)
genOutput := make([]complex128, dft.length)
for idx := range genOutput {
genOutput[idx] = complex(re[idx], im[idx])
}
directOutput := StepComplex(dft.length)
DirectFourierTransform(directOutput, -1.0)
err := Error(genOutput, directOutput)
t.Logf("{Transform: %s Error: %0.6e}\n", dft.name, err)
if err > Tolerance {
t.Fail()
}
}
}

View file

@ -39,7 +39,7 @@ var sampleFile *os.File
var msgType = flag.String("msgtype", "scm", "message type to receive: scm or idm") var msgType = flag.String("msgtype", "scm", "message type to receive: scm or idm")
var fastMag = flag.Bool("fastmag", false, "use faster alpha max + beta min magnitude approximation") var fastMag = flag.Bool("fastmag", false, "use faster alpha max + beta min magnitude approximation")
var symbolLength = flag.Int("symbollength", 73, "symbol length in samples, see -help for valid lengths") var symbolLength = flag.Int("symbollength", 72, "symbol length in samples, see -help for valid lengths")
var timeLimit = flag.Duration("duration", 0, "time to run for, 0 for infinite, ex. 1h5m10s") var timeLimit = flag.Duration("duration", 0, "time to run for, 0 for infinite, ex. 1h5m10s")
var meterID UintMap var meterID UintMap
@ -52,6 +52,8 @@ var gobUnsafe = flag.Bool("gobunsafe", false, "allow gob output to stdout")
var quiet = flag.Bool("quiet", false, "suppress printing state information at startup") var quiet = flag.Bool("quiet", false, "suppress printing state information at startup")
var single = flag.Bool("single", false, "one shot execution") var single = flag.Bool("single", false, "one shot execution")
var hop = flag.Bool("hop", false, "hop to new channel after each message")
func RegisterFlags() { func RegisterFlags() {
meterID = make(UintMap) meterID = make(UintMap)
meterType = make(UintMap) meterType = make(UintMap)

View file

@ -27,7 +27,9 @@ func main() {
for symbolLength := 1; symbolLength < int(math.Ceil(UpperMax/DataRate)); symbolLength++ { for symbolLength := 1; symbolLength < int(math.Ceil(UpperMax/DataRate)); symbolLength++ {
sampleRate := symbolLength * DataRate sampleRate := symbolLength * DataRate
if (LowerMin < sampleRate && sampleRate <= LowerMax) || (UpperMin < sampleRate && sampleRate <= UpperMax) { if (LowerMin < sampleRate && sampleRate <= LowerMax) || (UpperMin < sampleRate && sampleRate <= UpperMax) {
fmt.Printf("SymbolLength:%d SampleRate:%d Channels:%d ExcessBandwidth:%d\n", symbolLength, sampleRate, sampleRate/ChannelWidth, sampleRate%ChannelWidth) if sampleRate%ChannelWidth <= 640 {
fmt.Printf("SymbolLength:%d SampleRate:%d Channels:%d ExcessBandwidth:%d\n", symbolLength, sampleRate, sampleRate/ChannelWidth, sampleRate%ChannelWidth)
}
} }
} }
} }

View file

@ -47,21 +47,57 @@ type Message interface {
csv.Recorder csv.Recorder
} }
type Logger interface {
fmt.Stringer
csv.Recorder
StringNoOffset() string
}
type HopMessage struct {
Time time.Time
ID uint32
Type uint8
CenterChannel int
OffsetChannel int
}
func (msg HopMessage) String() string {
return fmt.Sprintf("{Time:%s ID:%d Type:%d CenterChannel:%d OffsetChannel:%d}",
msg.Time.Format(TimeFormat), msg.ID, msg.Type, msg.CenterChannel, msg.OffsetChannel,
)
}
func (msg HopMessage) StringNoOffset() string {
return msg.String()
}
func (msg HopMessage) Record() (r []string) {
r = append(r, msg.Time.Format(time.RFC3339Nano))
r = append(r, strconv.FormatInt(int64(msg.ID), 10))
r = append(r, strconv.FormatInt(int64(msg.Type), 10))
r = append(r, strconv.FormatInt(int64(msg.CenterChannel), 10))
r = append(r, strconv.FormatInt(int64(msg.OffsetChannel), 10))
return r
}
type LogMessage struct { type LogMessage struct {
Time time.Time Time time.Time
Offset int64 Offset int64
Length int Length int
Channel int
Message Message
} }
func (msg LogMessage) String() string { func (msg LogMessage) String() string {
return fmt.Sprintf("{Time:%s Offset:%d Length:%d %s:%s}", return fmt.Sprintf("{Time:%s Offset:%d Length:%d Channel:%d %s:%s}",
msg.Time.Format(TimeFormat), msg.Offset, msg.Length, msg.MsgType(), msg.Message, msg.Time.Format(TimeFormat), msg.Offset, msg.Length, msg.Channel, msg.MsgType(), msg.Message,
) )
} }
func (msg LogMessage) StringNoOffset() string { func (msg LogMessage) StringNoOffset() string {
return fmt.Sprintf("{Time:%s %s:%s}", msg.Time.Format(TimeFormat), msg.MsgType(), msg.Message) return fmt.Sprintf("{Time:%s Channel:%d %s:%s}",
msg.Time.Format(TimeFormat), msg.Channel, msg.MsgType(), msg.Message,
)
} }
func (msg LogMessage) Record() (r []string) { func (msg LogMessage) Record() (r []string) {

191
recv.go
View file

@ -21,6 +21,7 @@ import (
"flag" "flag"
"fmt" "fmt"
"log" "log"
"math/rand"
"os" "os"
"os/signal" "os/signal"
"runtime/pprof" "runtime/pprof"
@ -35,7 +36,7 @@ import (
) )
const ( const (
CenterFreq = 920299072 CenterFreq = 920200788
) )
var rcvr Receiver var rcvr Receiver
@ -44,6 +45,17 @@ type Receiver struct {
rtltcp.SDR rtltcp.SDR
d decode.Decoder d decode.Decoder
p parse.Parser p parse.Parser
chIdx int
channels []uint32
last time.Time
pIdx int
pattern map[int]map[int]int
centers []int
centerOrder [50][]int
centerIdx [50]int
} }
func (rcvr *Receiver) NewReceiver() { func (rcvr *Receiver) NewReceiver() {
@ -58,6 +70,27 @@ func (rcvr *Receiver) NewReceiver() {
log.Fatalf("Invalid message type: %q\n", *msgType) log.Fatalf("Invalid message type: %q\n", *msgType)
} }
rcvr.channels = []uint32{
909586111, 909782679, 909979247, 910175815, 911224178, 911420746, // 0
911617314, 911813882, 912010451, 912207019, 912403587, 912600155, // 6
912796723, 912993291, 913189859, 913386427, 913582995, 913779563, // 12
913976132, 915024495, 915221063, 915417631, 915614199, 915810767, // 18
916007335, 916203903, 916400471, 916597040, 916793608, 916990176, // 24
917186744, 917383312, 917579880, 917776448, 918824811, 919021379, // 30
919217947, 919414516, 919611084, 919807652, 920004220, 920200788, // 36
920397356, 920593924, 920790492, 920987060, 921183628, 921380197, // 42
921576765, 921773333, // 44
}
rcvr.chIdx = 42
rcvr.pattern = make(map[int]map[int]int)
rcvr.centers = []int{0, 9, 13, 23, 28, 39, 44}
for idx := range rcvr.centerIdx {
rcvr.centerIdx[idx] = 0
rcvr.centerOrder[idx] = rand.Perm(len(rcvr.centers))
}
if !*quiet { if !*quiet {
rcvr.d.Cfg.Log() rcvr.d.Cfg.Log()
log.Println("CRC:", rcvr.p) log.Println("CRC:", rcvr.p)
@ -75,31 +108,11 @@ func (rcvr *Receiver) NewReceiver() {
log.Println("GainCount:", rcvr.SDR.Info.GainCount) log.Println("GainCount:", rcvr.SDR.Info.GainCount)
} }
centerfreqFlagSet := false rcvr.SetSampleRate(uint32(rcvr.d.Cfg.SampleRate))
sampleRateFlagSet := false rcvr.SetCenterFreq(rcvr.channels[rcvr.chIdx])
gainFlagSet := false rcvr.SetAGCMode(false)
flag.Visit(func(f *flag.Flag) { rcvr.SetGainMode(false)
switch f.Name { rcvr.SetGainByIndex(5)
case "centerfreq":
centerfreqFlagSet = true
case "samplerate":
sampleRateFlagSet = true
case "gainbyindex", "tunergainmode", "tunergain", "agcmode":
gainFlagSet = true
}
})
// Set some parameters for listening.
if !centerfreqFlagSet {
rcvr.SetCenterFreq(uint32(rcvr.Flags.CenterFreq))
}
if !sampleRateFlagSet {
rcvr.SetSampleRate(uint32(rcvr.d.Cfg.SampleRate))
}
if !gainFlagSet {
rcvr.SetGainMode(true)
}
return return
} }
@ -117,6 +130,9 @@ func (rcvr *Receiver) Run() {
block := make([]byte, rcvr.d.Cfg.BlockSize2) block := make([]byte, rcvr.d.Cfg.BlockSize2)
isOffset := false
var interval time.Duration
start := time.Now() start := time.Now()
for { for {
// Exit on interrupt or time limit, otherwise receive. // Exit on interrupt or time limit, otherwise receive.
@ -133,27 +149,55 @@ func (rcvr *Receiver) Run() {
log.Fatal("Error reading samples: ", err) log.Fatal("Error reading samples: ", err)
} }
if isOffset {
interval = 30 * time.Second
} else {
interval = 45 * time.Second
}
if !rcvr.last.IsZero() && time.Since(rcvr.last) > interval {
isOffset = true
// Missing on a retrace is a penalty to the channel retraced.
for ch := range rcvr.pattern[rcvr.pIdx] {
if ch == rcvr.chIdx {
rcvr.pattern[rcvr.pIdx][ch]--
} else {
rcvr.pattern[rcvr.pIdx][ch]++
}
}
log.Println("Missed: ", rcvr.pIdx, rcvr.chIdx)
rcvr.NextChannel()
}
pktFound := false pktFound := false
for _, pkt := range rcvr.d.Decode(block) { for _, pkt := range rcvr.d.Decode(block) {
scm, err := rcvr.p.Parse(parse.NewDataFromBytes(pkt)) rawMsg, err := rcvr.p.Parse(parse.NewDataFromBytes(pkt))
if err != nil { if err != nil {
// log.Println(err) // log.Println(err)
continue continue
} }
if len(meterID) > 0 && !meterID[uint(scm.MeterID())] { if len(meterID) > 0 && !meterID[uint(rawMsg.MeterID())] {
continue continue
} }
if len(meterType) > 0 && !meterType[uint(scm.MeterType())] { if len(meterType) > 0 && !meterType[uint(rawMsg.MeterType())] {
continue continue
} }
var msg parse.LogMessage channel := rcvr.d.Periodogram.Execute(rcvr.d.Re, rcvr.d.Im)
msg.Time = time.Now()
msg.Offset, _ = sampleFile.Seek(0, os.SEEK_CUR) var msg parse.Logger
msg.Length = rcvr.d.Cfg.BufferLength << 1 msg = parse.HopMessage{
msg.Message = scm time.Now(),
rawMsg.MeterID(),
rawMsg.MeterType(),
rcvr.chIdx,
channel,
}
if encoder == nil { if encoder == nil {
// A nil encoder is just plain-text output. // A nil encoder is just plain-text output.
@ -176,6 +220,30 @@ func (rcvr *Receiver) Run() {
} }
pktFound = true pktFound = true
if _, exists := rcvr.pattern[rcvr.pIdx]; !exists {
rcvr.pattern[rcvr.pIdx] = make(map[int]int)
}
// If this isn't a retrace, add it to the pattern.
if _, exists := rcvr.pattern[rcvr.pIdx][rcvr.chIdx+channel]; !exists {
rcvr.pattern[rcvr.pIdx][rcvr.chIdx+channel]++
} else {
// Reward retrace, penalize others.
for ch := range rcvr.pattern[rcvr.pIdx] {
if ch == rcvr.chIdx+channel {
rcvr.pattern[rcvr.pIdx][ch]++
} else {
rcvr.pattern[rcvr.pIdx][ch]--
}
}
}
log.Printf("%#v\n", rcvr.pattern)
isOffset = false
rcvr.NextChannel()
if *single { if *single {
break break
} }
@ -188,6 +256,7 @@ func (rcvr *Receiver) Run() {
log.Fatal("Error writing raw samples to file:", err) log.Fatal("Error writing raw samples to file:", err)
} }
} }
if *single { if *single {
return return
} }
@ -196,8 +265,62 @@ func (rcvr *Receiver) Run() {
} }
} }
func (rcvr *Receiver) NextChannel() {
defer rcvr.d.Reset()
rcvr.last = time.Now()
rcvr.centerIdx[rcvr.pIdx] = (rcvr.centerIdx[rcvr.pIdx] + 1) % len(rcvr.centers)
rcvr.pIdx = (rcvr.pIdx + 1) % 50
// Prune bad channels.
for idx := range rcvr.pattern {
for ch, count := range rcvr.pattern[idx] {
if count <= 0 || ch < 0 || ch >= 50 {
delete(rcvr.pattern[idx], ch)
}
}
}
pattern := make([]int, 50)
for idx := range pattern {
pattern[idx] = -1
}
for idx, channels := range rcvr.pattern {
max := ^int(^uint(0) >> 1)
for ch, count := range channels {
if max < count {
max = count
pattern[idx] = ch
}
}
}
encoder.Encode(struct {
Time time.Time
Pattern []int
}{time.Now(), pattern})
rcvr.chIdx = rcvr.centers[rcvr.centerOrder[rcvr.pIdx][rcvr.centerIdx[rcvr.pIdx]]]
max := ^int(^uint(0) >> 1)
for ch, count := range rcvr.pattern[rcvr.pIdx] {
if max < count {
max = count
rcvr.chIdx = ch
}
}
if max != ^int(^uint(0)>>1) {
log.Println("Retrace:", rcvr.pIdx, rcvr.chIdx)
} else {
log.Println("Guess: ", rcvr.pIdx, rcvr.chIdx)
}
rcvr.SetCenterFreq(rcvr.channels[rcvr.chIdx])
}
func init() { func init() {
log.SetFlags(log.Lshortfile | log.Lmicroseconds) log.SetFlags(log.Lshortfile | log.Lmicroseconds)
rand.Seed(time.Now().UnixNano())
} }
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to this file") var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to this file")